first commit
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
# registry
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
|
||||
## Purpose
|
||||
|
||||
Module-augments `@suaveplan/storage/factory`'s `StorageProviderRegistry` and `StorageProviderConfig` to add the `"rackspace-cdn"` slot, and exposes `registerRackspaceCdnProvider()` to bind `RackspaceCdnAdapter` as the constructor for that slot. Consumers who prefer factory-style instantiation (`createStorage({ type: "rackspace-cdn", config })`) call `registerRackspaceCdnProvider()` once at boot and never reference the class directly.
|
||||
|
||||
Registration is idempotent — duplicate calls are no-ops, so wiring this into multiple bootstrappers (test fixtures + production startup) is safe.
|
||||
|
||||
## Features
|
||||
|
||||
- TypeScript module augmentation — `createStorage<"rackspace-cdn">` now type-checks with `RackspaceCdnAdapterOptions`.
|
||||
- Idempotent `registerRackspaceCdnProvider()` — safe to call from multiple bootstrap paths.
|
||||
- Zero runtime dependencies beyond `@suaveplan/storage/factory` and the local `RackspaceCdnAdapter` class.
|
||||
|
||||
## Usage: Basic
|
||||
|
||||
```ts
|
||||
import { registerRackspaceCdnProvider } from "@suaveplan/storage-cdn-rackspace";
|
||||
import { createStorage } from "@suaveplan/storage/factory";
|
||||
|
||||
registerRackspaceCdnProvider();
|
||||
const storage = createStorage({
|
||||
type: "rackspace-cdn",
|
||||
config: {
|
||||
originBaseUrl: "https://storage101.lon3.clouddrive.com/v1/AUTH_acc/",
|
||||
edgeBaseUrl: "https://abc.r88.cf6.rackcdn.com/",
|
||||
username: "u",
|
||||
apiKey: "k",
|
||||
container: "myc",
|
||||
region: "LON",
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
## Usage: Advanced
|
||||
|
||||
```ts
|
||||
import { registerRackspaceCdnProvider } from "@suaveplan/storage-cdn-rackspace";
|
||||
import { createStorage } from "@suaveplan/storage/factory";
|
||||
|
||||
// Bootstrap once per process.
|
||||
registerRackspaceCdnProvider();
|
||||
|
||||
function tenantStorage(tenant: { container: string; region: "LON" | "IAD" }) {
|
||||
return createStorage({
|
||||
type: "rackspace-cdn",
|
||||
config: { ...baseConfig, container: tenant.container, region: tenant.region },
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
### `registerRackspaceCdnProvider(): void`
|
||||
|
||||
Registers `RackspaceCdnAdapter` against `StorageFactory` under the `"rackspace-cdn"` slot when not already registered. Calling it twice is a no-op.
|
||||
|
||||
### Module augmentation
|
||||
|
||||
```ts
|
||||
declare module "@suaveplan/storage/factory" {
|
||||
interface StorageProviderRegistry { "rackspace-cdn": RackspaceCdnAdapter }
|
||||
interface StorageProviderConfig { "rackspace-cdn": RackspaceCdnAdapterOptions }
|
||||
}
|
||||
```
|
||||
|
||||
This means `createStorage<"rackspace-cdn">(...)` returns `RackspaceCdnAdapter` and the `config` parameter is typed as `RackspaceCdnAdapterOptions`.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
- The cast `RackspaceCdnAdapter as unknown as new (config?: unknown) => RackspaceCdnAdapter` is required because `StorageFactory`'s `ProviderCtor` is intentionally loose (`config?: unknown`) — adapter constructors take typed options that don't satisfy the registry's structural shape without the cast.
|
||||
- `hasStorageProvider("rackspace-cdn")` is the idempotency gate. After `unregisterStorageProvider("rackspace-cdn")` or `clearStorageProviders()`, a subsequent `registerRackspaceCdnProvider()` call cleanly re-registers.
|
||||
- The augmentation is pure type-level — there is no runtime cost beyond the one-time `Map.set` in the factory.
|
||||
- This module imports `RackspaceCdnAdapter` directly rather than via the package root barrel to avoid a circular import (the root barrel re-exports `registerRackspaceCdnProvider`).
|
||||
Reference in New Issue
Block a user