@streetjs/storage 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +719 -0
- package/dist/access.d.ts +95 -0
- package/dist/access.d.ts.map +1 -0
- package/dist/access.js +114 -0
- package/dist/access.js.map +1 -0
- package/dist/cli/commands.d.ts +88 -0
- package/dist/cli/commands.d.ts.map +1 -0
- package/dist/cli/commands.js +369 -0
- package/dist/cli/commands.js.map +1 -0
- package/dist/cli/generators.d.ts +41 -0
- package/dist/cli/generators.d.ts.map +1 -0
- package/dist/cli/generators.js +119 -0
- package/dist/cli/generators.js.map +1 -0
- package/dist/directory.d.ts +88 -0
- package/dist/directory.d.ts.map +1 -0
- package/dist/directory.js +148 -0
- package/dist/directory.js.map +1 -0
- package/dist/driver.d.ts +83 -0
- package/dist/driver.d.ts.map +1 -0
- package/dist/driver.js +16 -0
- package/dist/driver.js.map +1 -0
- package/dist/drivers/azure.d.ts +239 -0
- package/dist/drivers/azure.d.ts.map +1 -0
- package/dist/drivers/azure.js +476 -0
- package/dist/drivers/azure.js.map +1 -0
- package/dist/drivers/backblaze.d.ts +105 -0
- package/dist/drivers/backblaze.d.ts.map +1 -0
- package/dist/drivers/backblaze.js +279 -0
- package/dist/drivers/backblaze.js.map +1 -0
- package/dist/drivers/gcs.d.ts +239 -0
- package/dist/drivers/gcs.d.ts.map +1 -0
- package/dist/drivers/gcs.js +454 -0
- package/dist/drivers/gcs.js.map +1 -0
- package/dist/drivers/local.d.ts +126 -0
- package/dist/drivers/local.d.ts.map +1 -0
- package/dist/drivers/local.js +321 -0
- package/dist/drivers/local.js.map +1 -0
- package/dist/drivers/memory.d.ts +104 -0
- package/dist/drivers/memory.d.ts.map +1 -0
- package/dist/drivers/memory.js +197 -0
- package/dist/drivers/memory.js.map +1 -0
- package/dist/drivers/minio.d.ts +90 -0
- package/dist/drivers/minio.d.ts.map +1 -0
- package/dist/drivers/minio.js +276 -0
- package/dist/drivers/minio.js.map +1 -0
- package/dist/drivers/r2.d.ts +100 -0
- package/dist/drivers/r2.d.ts.map +1 -0
- package/dist/drivers/r2.js +240 -0
- package/dist/drivers/r2.js.map +1 -0
- package/dist/drivers/s3-base.d.ts +270 -0
- package/dist/drivers/s3-base.d.ts.map +1 -0
- package/dist/drivers/s3-base.js +436 -0
- package/dist/drivers/s3-base.js.map +1 -0
- package/dist/drivers/s3.d.ts +111 -0
- package/dist/drivers/s3.d.ts.map +1 -0
- package/dist/drivers/s3.js +311 -0
- package/dist/drivers/s3.js.map +1 -0
- package/dist/drivers/supabase.d.ts +246 -0
- package/dist/drivers/supabase.d.ts.map +1 -0
- package/dist/drivers/supabase.js +502 -0
- package/dist/drivers/supabase.js.map +1 -0
- package/dist/errors.d.ts +115 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +131 -0
- package/dist/errors.js.map +1 -0
- package/dist/examples/storage-demo.d.ts +53 -0
- package/dist/examples/storage-demo.d.ts.map +1 -0
- package/dist/examples/storage-demo.js +242 -0
- package/dist/examples/storage-demo.js.map +1 -0
- package/dist/facade.d.ts +192 -0
- package/dist/facade.d.ts.map +1 -0
- package/dist/facade.js +898 -0
- package/dist/facade.js.map +1 -0
- package/dist/image.d.ts +94 -0
- package/dist/image.d.ts.map +1 -0
- package/dist/image.js +224 -0
- package/dist/image.js.map +1 -0
- package/dist/index.d.ts +47 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +53 -0
- package/dist/index.js.map +1 -0
- package/dist/integrations/events.d.ts +108 -0
- package/dist/integrations/events.d.ts.map +1 -0
- package/dist/integrations/events.js +111 -0
- package/dist/integrations/events.js.map +1 -0
- package/dist/integrations/queue.d.ts +89 -0
- package/dist/integrations/queue.d.ts.map +1 -0
- package/dist/integrations/queue.js +91 -0
- package/dist/integrations/queue.js.map +1 -0
- package/dist/integrations/realtime.d.ts +95 -0
- package/dist/integrations/realtime.d.ts.map +1 -0
- package/dist/integrations/realtime.js +90 -0
- package/dist/integrations/realtime.js.map +1 -0
- package/dist/lifecycle.d.ts +137 -0
- package/dist/lifecycle.d.ts.map +1 -0
- package/dist/lifecycle.js +240 -0
- package/dist/lifecycle.js.map +1 -0
- package/dist/metadata.d.ts +109 -0
- package/dist/metadata.d.ts.map +1 -0
- package/dist/metadata.js +139 -0
- package/dist/metadata.js.map +1 -0
- package/dist/multipart.d.ts +108 -0
- package/dist/multipart.d.ts.map +1 -0
- package/dist/multipart.js +200 -0
- package/dist/multipart.js.map +1 -0
- package/dist/observability.d.ts +82 -0
- package/dist/observability.d.ts.map +1 -0
- package/dist/observability.js +175 -0
- package/dist/observability.js.map +1 -0
- package/dist/plugin.d.ts +82 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/plugin.js +100 -0
- package/dist/plugin.js.map +1 -0
- package/dist/resumable.d.ts +118 -0
- package/dist/resumable.d.ts.map +1 -0
- package/dist/resumable.js +223 -0
- package/dist/resumable.js.map +1 -0
- package/dist/search.d.ts +57 -0
- package/dist/search.d.ts.map +1 -0
- package/dist/search.js +172 -0
- package/dist/search.js.map +1 -0
- package/dist/signed-url.d.ts +110 -0
- package/dist/signed-url.d.ts.map +1 -0
- package/dist/signed-url.js +237 -0
- package/dist/signed-url.js.map +1 -0
- package/dist/testing/index.d.ts +219 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +393 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/tests/access.test.d.ts +2 -0
- package/dist/tests/access.test.d.ts.map +1 -0
- package/dist/tests/access.test.js +270 -0
- package/dist/tests/access.test.js.map +1 -0
- package/dist/tests/azure-driver.test.d.ts +2 -0
- package/dist/tests/azure-driver.test.d.ts.map +1 -0
- package/dist/tests/azure-driver.test.js +183 -0
- package/dist/tests/azure-driver.test.js.map +1 -0
- package/dist/tests/backblaze-driver.test.d.ts +2 -0
- package/dist/tests/backblaze-driver.test.d.ts.map +1 -0
- package/dist/tests/backblaze-driver.test.js +185 -0
- package/dist/tests/backblaze-driver.test.js.map +1 -0
- package/dist/tests/bridge-degradation.test.d.ts +2 -0
- package/dist/tests/bridge-degradation.test.d.ts.map +1 -0
- package/dist/tests/bridge-degradation.test.js +138 -0
- package/dist/tests/bridge-degradation.test.js.map +1 -0
- package/dist/tests/cli.test.d.ts +2 -0
- package/dist/tests/cli.test.d.ts.map +1 -0
- package/dist/tests/cli.test.js +127 -0
- package/dist/tests/cli.test.js.map +1 -0
- package/dist/tests/contract.d.ts +131 -0
- package/dist/tests/contract.d.ts.map +1 -0
- package/dist/tests/contract.js +222 -0
- package/dist/tests/contract.js.map +1 -0
- package/dist/tests/contract.test.d.ts +2 -0
- package/dist/tests/contract.test.d.ts.map +1 -0
- package/dist/tests/contract.test.js +110 -0
- package/dist/tests/contract.test.js.map +1 -0
- package/dist/tests/directory.test.d.ts +2 -0
- package/dist/tests/directory.test.d.ts.map +1 -0
- package/dist/tests/directory.test.js +125 -0
- package/dist/tests/directory.test.js.map +1 -0
- package/dist/tests/errors.test.d.ts +2 -0
- package/dist/tests/errors.test.d.ts.map +1 -0
- package/dist/tests/errors.test.js +93 -0
- package/dist/tests/errors.test.js.map +1 -0
- package/dist/tests/events-bridge.test.d.ts +2 -0
- package/dist/tests/events-bridge.test.d.ts.map +1 -0
- package/dist/tests/events-bridge.test.js +228 -0
- package/dist/tests/events-bridge.test.js.map +1 -0
- package/dist/tests/example-smoke.test.d.ts +2 -0
- package/dist/tests/example-smoke.test.d.ts.map +1 -0
- package/dist/tests/example-smoke.test.js +34 -0
- package/dist/tests/example-smoke.test.js.map +1 -0
- package/dist/tests/gcs-driver.test.d.ts +2 -0
- package/dist/tests/gcs-driver.test.d.ts.map +1 -0
- package/dist/tests/gcs-driver.test.js +197 -0
- package/dist/tests/gcs-driver.test.js.map +1 -0
- package/dist/tests/image.test.d.ts +2 -0
- package/dist/tests/image.test.d.ts.map +1 -0
- package/dist/tests/image.test.js +102 -0
- package/dist/tests/image.test.js.map +1 -0
- package/dist/tests/lifecycle.test.d.ts +2 -0
- package/dist/tests/lifecycle.test.d.ts.map +1 -0
- package/dist/tests/lifecycle.test.js +171 -0
- package/dist/tests/lifecycle.test.js.map +1 -0
- package/dist/tests/local-driver.test.d.ts +2 -0
- package/dist/tests/local-driver.test.d.ts.map +1 -0
- package/dist/tests/local-driver.test.js +153 -0
- package/dist/tests/local-driver.test.js.map +1 -0
- package/dist/tests/local-streaming.test.d.ts +2 -0
- package/dist/tests/local-streaming.test.d.ts.map +1 -0
- package/dist/tests/local-streaming.test.js +121 -0
- package/dist/tests/local-streaming.test.js.map +1 -0
- package/dist/tests/memory-driver.test.d.ts +2 -0
- package/dist/tests/memory-driver.test.d.ts.map +1 -0
- package/dist/tests/memory-driver.test.js +180 -0
- package/dist/tests/memory-driver.test.js.map +1 -0
- package/dist/tests/memory-streaming.test.d.ts +2 -0
- package/dist/tests/memory-streaming.test.d.ts.map +1 -0
- package/dist/tests/memory-streaming.test.js +92 -0
- package/dist/tests/memory-streaming.test.js.map +1 -0
- package/dist/tests/minio-driver.test.d.ts +2 -0
- package/dist/tests/minio-driver.test.d.ts.map +1 -0
- package/dist/tests/minio-driver.test.js +146 -0
- package/dist/tests/minio-driver.test.js.map +1 -0
- package/dist/tests/non-s3-integration.test.d.ts +2 -0
- package/dist/tests/non-s3-integration.test.d.ts.map +1 -0
- package/dist/tests/non-s3-integration.test.js +201 -0
- package/dist/tests/non-s3-integration.test.js.map +1 -0
- package/dist/tests/observability.registration.test.d.ts +2 -0
- package/dist/tests/observability.registration.test.d.ts.map +1 -0
- package/dist/tests/observability.registration.test.js +103 -0
- package/dist/tests/observability.registration.test.js.map +1 -0
- package/dist/tests/observability.test.d.ts +2 -0
- package/dist/tests/observability.test.d.ts.map +1 -0
- package/dist/tests/observability.test.js +240 -0
- package/dist/tests/observability.test.js.map +1 -0
- package/dist/tests/plugin.test.d.ts +2 -0
- package/dist/tests/plugin.test.d.ts.map +1 -0
- package/dist/tests/plugin.test.js +112 -0
- package/dist/tests/plugin.test.js.map +1 -0
- package/dist/tests/prop-concurrent.test.d.ts +2 -0
- package/dist/tests/prop-concurrent.test.d.ts.map +1 -0
- package/dist/tests/prop-concurrent.test.js +59 -0
- package/dist/tests/prop-concurrent.test.js.map +1 -0
- package/dist/tests/prop-copy.test.d.ts +2 -0
- package/dist/tests/prop-copy.test.d.ts.map +1 -0
- package/dist/tests/prop-copy.test.js +63 -0
- package/dist/tests/prop-copy.test.js.map +1 -0
- package/dist/tests/prop-delete.test.d.ts +2 -0
- package/dist/tests/prop-delete.test.d.ts.map +1 -0
- package/dist/tests/prop-delete.test.js +35 -0
- package/dist/tests/prop-delete.test.js.map +1 -0
- package/dist/tests/prop-directory.test.d.ts +2 -0
- package/dist/tests/prop-directory.test.d.ts.map +1 -0
- package/dist/tests/prop-directory.test.js +118 -0
- package/dist/tests/prop-directory.test.js.map +1 -0
- package/dist/tests/prop-driver-conformance.test.d.ts +2 -0
- package/dist/tests/prop-driver-conformance.test.d.ts.map +1 -0
- package/dist/tests/prop-driver-conformance.test.js +110 -0
- package/dist/tests/prop-driver-conformance.test.js.map +1 -0
- package/dist/tests/prop-driver-equivalence.test.d.ts +2 -0
- package/dist/tests/prop-driver-equivalence.test.d.ts.map +1 -0
- package/dist/tests/prop-driver-equivalence.test.js +163 -0
- package/dist/tests/prop-driver-equivalence.test.js.map +1 -0
- package/dist/tests/prop-lifecycle.test.d.ts +2 -0
- package/dist/tests/prop-lifecycle.test.d.ts.map +1 -0
- package/dist/tests/prop-lifecycle.test.js +83 -0
- package/dist/tests/prop-lifecycle.test.js.map +1 -0
- package/dist/tests/prop-list.test.d.ts +2 -0
- package/dist/tests/prop-list.test.d.ts.map +1 -0
- package/dist/tests/prop-list.test.js +53 -0
- package/dist/tests/prop-list.test.js.map +1 -0
- package/dist/tests/prop-metadata.test.d.ts +2 -0
- package/dist/tests/prop-metadata.test.d.ts.map +1 -0
- package/dist/tests/prop-metadata.test.js +87 -0
- package/dist/tests/prop-metadata.test.js.map +1 -0
- package/dist/tests/prop-move.test.d.ts +2 -0
- package/dist/tests/prop-move.test.d.ts.map +1 -0
- package/dist/tests/prop-move.test.js +67 -0
- package/dist/tests/prop-move.test.js.map +1 -0
- package/dist/tests/prop-multipart-abort.test.d.ts +2 -0
- package/dist/tests/prop-multipart-abort.test.d.ts.map +1 -0
- package/dist/tests/prop-multipart-abort.test.js +48 -0
- package/dist/tests/prop-multipart-abort.test.js.map +1 -0
- package/dist/tests/prop-multipart.test.d.ts +2 -0
- package/dist/tests/prop-multipart.test.d.ts.map +1 -0
- package/dist/tests/prop-multipart.test.js +65 -0
- package/dist/tests/prop-multipart.test.js.map +1 -0
- package/dist/tests/prop-resumable.test.d.ts +2 -0
- package/dist/tests/prop-resumable.test.d.ts.map +1 -0
- package/dist/tests/prop-resumable.test.js +78 -0
- package/dist/tests/prop-resumable.test.js.map +1 -0
- package/dist/tests/prop-search.test.d.ts +2 -0
- package/dist/tests/prop-search.test.d.ts.map +1 -0
- package/dist/tests/prop-search.test.js +120 -0
- package/dist/tests/prop-search.test.js.map +1 -0
- package/dist/tests/prop-signed-url.test.d.ts +2 -0
- package/dist/tests/prop-signed-url.test.d.ts.map +1 -0
- package/dist/tests/prop-signed-url.test.js +74 -0
- package/dist/tests/prop-signed-url.test.js.map +1 -0
- package/dist/tests/prop-streaming.test.d.ts +2 -0
- package/dist/tests/prop-streaming.test.d.ts.map +1 -0
- package/dist/tests/prop-streaming.test.js +34 -0
- package/dist/tests/prop-streaming.test.js.map +1 -0
- package/dist/tests/prop-upload-download.test.d.ts +2 -0
- package/dist/tests/prop-upload-download.test.d.ts.map +1 -0
- package/dist/tests/prop-upload-download.test.js +30 -0
- package/dist/tests/prop-upload-download.test.js.map +1 -0
- package/dist/tests/prop-validation.test.d.ts +2 -0
- package/dist/tests/prop-validation.test.d.ts.map +1 -0
- package/dist/tests/prop-validation.test.js +50 -0
- package/dist/tests/prop-validation.test.js.map +1 -0
- package/dist/tests/prop-versioning.test.d.ts +2 -0
- package/dist/tests/prop-versioning.test.d.ts.map +1 -0
- package/dist/tests/prop-versioning.test.js +74 -0
- package/dist/tests/prop-versioning.test.js.map +1 -0
- package/dist/tests/queue-bridge.test.d.ts +2 -0
- package/dist/tests/queue-bridge.test.d.ts.map +1 -0
- package/dist/tests/queue-bridge.test.js +111 -0
- package/dist/tests/queue-bridge.test.js.map +1 -0
- package/dist/tests/r2-driver.test.d.ts +2 -0
- package/dist/tests/r2-driver.test.d.ts.map +1 -0
- package/dist/tests/r2-driver.test.js +143 -0
- package/dist/tests/r2-driver.test.js.map +1 -0
- package/dist/tests/realtime-bridge.test.d.ts +2 -0
- package/dist/tests/realtime-bridge.test.d.ts.map +1 -0
- package/dist/tests/realtime-bridge.test.js +106 -0
- package/dist/tests/realtime-bridge.test.js.map +1 -0
- package/dist/tests/resumable.test.d.ts +2 -0
- package/dist/tests/resumable.test.d.ts.map +1 -0
- package/dist/tests/resumable.test.js +104 -0
- package/dist/tests/resumable.test.js.map +1 -0
- package/dist/tests/s3-base.test.d.ts +2 -0
- package/dist/tests/s3-base.test.d.ts.map +1 -0
- package/dist/tests/s3-base.test.js +289 -0
- package/dist/tests/s3-base.test.js.map +1 -0
- package/dist/tests/s3-integration.test.d.ts +2 -0
- package/dist/tests/s3-integration.test.d.ts.map +1 -0
- package/dist/tests/s3-integration.test.js +270 -0
- package/dist/tests/s3-integration.test.js.map +1 -0
- package/dist/tests/s3.test.d.ts +2 -0
- package/dist/tests/s3.test.d.ts.map +1 -0
- package/dist/tests/s3.test.js +203 -0
- package/dist/tests/s3.test.js.map +1 -0
- package/dist/tests/scaffold.test.d.ts +2 -0
- package/dist/tests/scaffold.test.d.ts.map +1 -0
- package/dist/tests/scaffold.test.js +13 -0
- package/dist/tests/scaffold.test.js.map +1 -0
- package/dist/tests/search.test.d.ts +2 -0
- package/dist/tests/search.test.d.ts.map +1 -0
- package/dist/tests/search.test.js +106 -0
- package/dist/tests/search.test.js.map +1 -0
- package/dist/tests/supabase-driver.test.d.ts +2 -0
- package/dist/tests/supabase-driver.test.d.ts.map +1 -0
- package/dist/tests/supabase-driver.test.js +196 -0
- package/dist/tests/supabase-driver.test.js.map +1 -0
- package/dist/tests/testing-utilities.test.d.ts +2 -0
- package/dist/tests/testing-utilities.test.d.ts.map +1 -0
- package/dist/tests/testing-utilities.test.js +138 -0
- package/dist/tests/testing-utilities.test.js.map +1 -0
- package/dist/tests/validation.test.d.ts +2 -0
- package/dist/tests/validation.test.d.ts.map +1 -0
- package/dist/tests/validation.test.js +135 -0
- package/dist/tests/validation.test.js.map +1 -0
- package/dist/tests/versioning.test.d.ts +2 -0
- package/dist/tests/versioning.test.d.ts.map +1 -0
- package/dist/tests/versioning.test.js +128 -0
- package/dist/tests/versioning.test.js.map +1 -0
- package/dist/types.d.ts +232 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +23 -0
- package/dist/types.js.map +1 -0
- package/dist/validation.d.ts +105 -0
- package/dist/validation.d.ts.map +1 -0
- package/dist/validation.js +225 -0
- package/dist/validation.js.map +1 -0
- package/dist/versioning.d.ts +100 -0
- package/dist/versioning.d.ts.map +1 -0
- package/dist/versioning.js +179 -0
- package/dist/versioning.js.map +1 -0
- package/package.json +137 -0
|
@@ -0,0 +1,369 @@
|
|
|
1
|
+
// src/cli/commands.ts
|
|
2
|
+
// @streetjs/storage — CLI commands registered through the reused core CliKernel.
|
|
3
|
+
//
|
|
4
|
+
// Provides `make:storage`, `storage:list`, `storage:sync`, `storage:clean`,
|
|
5
|
+
// `storage:migrate`, and `storage:verify` as `@Command`-decorated methods.
|
|
6
|
+
//
|
|
7
|
+
// `make:storage` delegates to the pure functions in `generators.ts`: it
|
|
8
|
+
// validates the name before writing anything, refuses to overwrite an existing
|
|
9
|
+
// target, and otherwise emits a typed scaffold that compiles under `tsc`
|
|
10
|
+
// (Requirement 21.2). The operational commands build a configured
|
|
11
|
+
// `Storage`/`StorageDriver` from CLI flags and act through the public facade
|
|
12
|
+
// surface. `storage:verify` runs the shared contract-conformance suite against
|
|
13
|
+
// the configured driver and reports pass/fail per check (Requirement 21.4).
|
|
14
|
+
//
|
|
15
|
+
// No class-level decorator is used, so no constructor dependency metadata is
|
|
16
|
+
// emitted and the core `CliKernel` can `container.resolve` the class with no
|
|
17
|
+
// registered dependencies. This mirrors the `@streetjs/events` cli/commands.ts
|
|
18
|
+
// pattern.
|
|
19
|
+
//
|
|
20
|
+
// _Requirements: 21.1, 21.2, 21.3, 21.4_
|
|
21
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
22
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
23
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
24
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
25
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
26
|
+
};
|
|
27
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
28
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
29
|
+
};
|
|
30
|
+
import { Command } from "streetjs";
|
|
31
|
+
import { createStorage } from "../facade.js";
|
|
32
|
+
import { MemoryStorageDriver } from "../drivers/memory.js";
|
|
33
|
+
import { LocalStorageDriver } from "../drivers/local.js";
|
|
34
|
+
import { StorageConfigError } from "../errors.js";
|
|
35
|
+
import { runStorageDriverContract } from "../tests/contract.js";
|
|
36
|
+
import { generateStorage, isValidGeneratorName, isValidProvider, writeScaffold, DEFAULT_STORAGE_DIR, } from "./generators.js";
|
|
37
|
+
/**
|
|
38
|
+
* The set of `@Command`-decorated storage commands, registered through the core
|
|
39
|
+
* `CliKernel`. A plain class (no class-level decorator) so the kernel can
|
|
40
|
+
* `container.resolve` it without constructor dependency metadata.
|
|
41
|
+
*/
|
|
42
|
+
export class StorageCommands {
|
|
43
|
+
// ── make:storage ─────────────────────────────────────────────────────────
|
|
44
|
+
/**
|
|
45
|
+
* `street make:storage <Name> [--dir <dir>] [--provider memory|local]` —
|
|
46
|
+
* scaffold a typed storage module. Delegates to the pure generators: the name
|
|
47
|
+
* (and scaffold provider) are validated before any file is written, and an
|
|
48
|
+
* existing target is never overwritten (Requirement 21.2).
|
|
49
|
+
*/
|
|
50
|
+
makeStorage(args) {
|
|
51
|
+
const name = this.resolveName(args);
|
|
52
|
+
if (!isValidGeneratorName(name)) {
|
|
53
|
+
console.error(`[storage] Invalid storage name: "${name}". ` +
|
|
54
|
+
`Use a PascalCase identifier (a letter followed by letters or digits).`);
|
|
55
|
+
process.exitCode = 1;
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
const providerFlag = typeof args.flags["provider"] === "string" ? args.flags["provider"] : undefined;
|
|
59
|
+
let provider;
|
|
60
|
+
if (providerFlag !== undefined) {
|
|
61
|
+
if (!isValidProvider(providerFlag)) {
|
|
62
|
+
console.error(`[storage] Invalid scaffold provider: "${providerFlag}". ` +
|
|
63
|
+
`Use a built-in zero-dependency provider ("memory" or "local").`);
|
|
64
|
+
process.exitCode = 1;
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
provider = providerFlag;
|
|
68
|
+
}
|
|
69
|
+
const dir = typeof args.flags["dir"] === "string" ? args.flags["dir"] : DEFAULT_STORAGE_DIR;
|
|
70
|
+
let result;
|
|
71
|
+
try {
|
|
72
|
+
result = generateStorage(name, dir, provider);
|
|
73
|
+
writeScaffold(result);
|
|
74
|
+
}
|
|
75
|
+
catch (err) {
|
|
76
|
+
console.error(`[storage] ${err instanceof Error ? err.message : String(err)}`);
|
|
77
|
+
process.exitCode = 1;
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
console.log(`[storage] Generated storage module: ${result.path}`);
|
|
81
|
+
}
|
|
82
|
+
// ── storage:list ───────────────────────────────────────────────────────────
|
|
83
|
+
/**
|
|
84
|
+
* `street storage:list [<prefix>] [--provider memory|local] [--root <dir>]` —
|
|
85
|
+
* list the stored object keys for the configured driver. Builds a `Storage`
|
|
86
|
+
* from the CLI flags and prints every key under the prefix (Requirement 21.3).
|
|
87
|
+
*/
|
|
88
|
+
async storageList(args) {
|
|
89
|
+
const prefix = this.resolvePrefix(args);
|
|
90
|
+
const storage = this.buildStorage(this.configFromArgs(args));
|
|
91
|
+
try {
|
|
92
|
+
const items = await storage.list(prefix);
|
|
93
|
+
if (items.length === 0) {
|
|
94
|
+
console.log(`[storage] No objects found under "${prefix}".`);
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
for (const item of items) {
|
|
98
|
+
console.log(item.key);
|
|
99
|
+
}
|
|
100
|
+
console.log(`[storage] ${items.length} object(s).`);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
catch (err) {
|
|
104
|
+
console.error(`[storage] ${err instanceof Error ? err.message : String(err)}`);
|
|
105
|
+
process.exitCode = 1;
|
|
106
|
+
}
|
|
107
|
+
finally {
|
|
108
|
+
await this.closeQuietly(storage);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
// ── storage:clean ────────────────────────────────────────────────────────────
|
|
112
|
+
/**
|
|
113
|
+
* `street storage:clean <prefix> [--provider memory|local] [--root <dir>]` —
|
|
114
|
+
* remove every object under a prefix from the configured driver. A prefix is
|
|
115
|
+
* required so the command never silently wipes an entire store; deletion of
|
|
116
|
+
* each object is isolated so one failure does not abort the rest
|
|
117
|
+
* (Requirement 21.3).
|
|
118
|
+
*/
|
|
119
|
+
async storageClean(args) {
|
|
120
|
+
const prefix = this.resolvePrefix(args);
|
|
121
|
+
if (prefix === "") {
|
|
122
|
+
console.error(`[storage] storage:clean requires a non-empty prefix (refusing to remove every object). ` +
|
|
123
|
+
`Pass a prefix positionally or via --prefix.`);
|
|
124
|
+
process.exitCode = 1;
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
const storage = this.buildStorage(this.configFromArgs(args));
|
|
128
|
+
let removed = 0;
|
|
129
|
+
try {
|
|
130
|
+
const items = await storage.list(prefix);
|
|
131
|
+
for (const item of items) {
|
|
132
|
+
try {
|
|
133
|
+
await storage.delete(item.key);
|
|
134
|
+
removed += 1;
|
|
135
|
+
}
|
|
136
|
+
catch (err) {
|
|
137
|
+
console.error(`[storage] Failed to remove "${item.key}": ` +
|
|
138
|
+
`${err instanceof Error ? err.message : String(err)}`);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
console.log(`[storage] Removed ${removed} object(s) under "${prefix}".`);
|
|
142
|
+
}
|
|
143
|
+
catch (err) {
|
|
144
|
+
console.error(`[storage] ${err instanceof Error ? err.message : String(err)}`);
|
|
145
|
+
process.exitCode = 1;
|
|
146
|
+
}
|
|
147
|
+
finally {
|
|
148
|
+
await this.closeQuietly(storage);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
// ── storage:sync ─────────────────────────────────────────────────────────────
|
|
152
|
+
/**
|
|
153
|
+
* `street storage:sync [<prefix>] --from-provider <p> [--from-root <dir>]
|
|
154
|
+
* --to-provider <p> [--to-root <dir>]` — copy every object under a prefix from
|
|
155
|
+
* a source store to a destination store, leaving the source untouched
|
|
156
|
+
* (Requirement 21.3). Each object copy is isolated so a single failure does
|
|
157
|
+
* not abort the whole sync.
|
|
158
|
+
*/
|
|
159
|
+
async storageSync(args) {
|
|
160
|
+
await this.transfer(args, { verb: "Synced" });
|
|
161
|
+
}
|
|
162
|
+
// ── storage:migrate ──────────────────────────────────────────────────────────
|
|
163
|
+
/**
|
|
164
|
+
* `street storage:migrate [<prefix>] --from-provider <p> [--from-root <dir>]
|
|
165
|
+
* --to-provider <p> [--to-root <dir>]` — move every object under a prefix from
|
|
166
|
+
* a source store to a destination store (copy, then remove from the source),
|
|
167
|
+
* so the destination becomes the new home for the data (Requirement 21.3).
|
|
168
|
+
* Each object migration is isolated so a single failure does not abort the
|
|
169
|
+
* whole migration.
|
|
170
|
+
*/
|
|
171
|
+
async storageMigrate(args) {
|
|
172
|
+
await this.transfer(args, { removeSource: true, verb: "Migrated" });
|
|
173
|
+
}
|
|
174
|
+
// ── storage:verify ───────────────────────────────────────────────────────────
|
|
175
|
+
/**
|
|
176
|
+
* `street storage:verify [--provider memory|local] [--root <dir>]` — run the
|
|
177
|
+
* shared driver contract-conformance suite against the configured driver and
|
|
178
|
+
* report pass/fail per check, exiting non-zero when any check fails
|
|
179
|
+
* (Requirement 21.4).
|
|
180
|
+
*/
|
|
181
|
+
async storageVerify(args) {
|
|
182
|
+
const config = this.configFromArgs(args);
|
|
183
|
+
let factory;
|
|
184
|
+
try {
|
|
185
|
+
factory = this.driverFactory(config);
|
|
186
|
+
}
|
|
187
|
+
catch (err) {
|
|
188
|
+
console.error(`[storage] ${err instanceof Error ? err.message : String(err)}`);
|
|
189
|
+
process.exitCode = 1;
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
const report = await runStorageDriverContract(factory);
|
|
193
|
+
console.log(`[storage] Contract conformance for driver "${report.driver}":`);
|
|
194
|
+
for (const result of report.results) {
|
|
195
|
+
const status = result.passed ? "PASS" : "FAIL";
|
|
196
|
+
console.log(` [${status}] (${result.requirement}) ${result.name}`);
|
|
197
|
+
if (!result.passed && result.error !== undefined) {
|
|
198
|
+
console.log(` ${result.error}`);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
const passedCount = report.results.filter((r) => r.passed).length;
|
|
202
|
+
console.log(`[storage] ${passedCount}/${report.results.length} check(s) passed — ` +
|
|
203
|
+
`${report.passed ? "PASS" : "FAIL"}.`);
|
|
204
|
+
if (!report.passed) {
|
|
205
|
+
process.exitCode = 1;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
// ── Shared helpers ───────────────────────────────────────────────────────────
|
|
209
|
+
/**
|
|
210
|
+
* Copy (and optionally remove-from-source) every object under a prefix from a
|
|
211
|
+
* source store to a destination store. Shared by `storage:sync` (copy) and
|
|
212
|
+
* `storage:migrate` (move). Every per-object transfer is isolated so one
|
|
213
|
+
* failure does not abort the rest.
|
|
214
|
+
*/
|
|
215
|
+
async transfer(args, options) {
|
|
216
|
+
const prefix = this.resolvePrefix(args);
|
|
217
|
+
const source = this.buildStorage(this.transferConfig(args, "from"));
|
|
218
|
+
const destination = this.buildStorage(this.transferConfig(args, "to"));
|
|
219
|
+
let transferred = 0;
|
|
220
|
+
try {
|
|
221
|
+
const items = await source.list(prefix);
|
|
222
|
+
for (const item of items) {
|
|
223
|
+
try {
|
|
224
|
+
const got = await source.get(item.key);
|
|
225
|
+
if (!got.found || got.bytes === undefined) {
|
|
226
|
+
continue;
|
|
227
|
+
}
|
|
228
|
+
const metadata = got.metadata;
|
|
229
|
+
await destination.put(item.key, got.bytes, {
|
|
230
|
+
contentType: metadata?.contentType,
|
|
231
|
+
owner: metadata?.owner,
|
|
232
|
+
tenant: metadata?.tenant,
|
|
233
|
+
accessLevel: metadata?.accessLevel,
|
|
234
|
+
custom: metadata?.custom,
|
|
235
|
+
});
|
|
236
|
+
if (options.removeSource === true) {
|
|
237
|
+
await source.delete(item.key);
|
|
238
|
+
}
|
|
239
|
+
transferred += 1;
|
|
240
|
+
}
|
|
241
|
+
catch (err) {
|
|
242
|
+
console.error(`[storage] Failed to transfer "${item.key}": ` +
|
|
243
|
+
`${err instanceof Error ? err.message : String(err)}`);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
console.log(`[storage] ${options.verb} ${transferred} object(s) under "${prefix}".`);
|
|
247
|
+
}
|
|
248
|
+
catch (err) {
|
|
249
|
+
console.error(`[storage] ${err instanceof Error ? err.message : String(err)}`);
|
|
250
|
+
process.exitCode = 1;
|
|
251
|
+
}
|
|
252
|
+
finally {
|
|
253
|
+
await this.closeQuietly(source);
|
|
254
|
+
await this.closeQuietly(destination);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
/** Build a live {@link Storage} facade from a resolved {@link StorageConfig}. */
|
|
258
|
+
buildStorage(config) {
|
|
259
|
+
return createStorage(config);
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Resolve a {@link StorageConfig} from the CLI flags: `--provider` (defaults to
|
|
263
|
+
* `memory`) and `--root` (used by the `local` provider).
|
|
264
|
+
*/
|
|
265
|
+
configFromArgs(args) {
|
|
266
|
+
const provider = typeof args.flags["provider"] === "string" ? args.flags["provider"] : "memory";
|
|
267
|
+
const root = typeof args.flags["root"] === "string" ? args.flags["root"] : undefined;
|
|
268
|
+
return { provider, root };
|
|
269
|
+
}
|
|
270
|
+
/**
|
|
271
|
+
* Resolve a source (`from`) or destination (`to`) {@link StorageConfig} from a
|
|
272
|
+
* prefixed pair of flags, e.g. `--from-provider`/`--from-root` and
|
|
273
|
+
* `--to-provider`/`--to-root`. Defaults to the `memory` provider.
|
|
274
|
+
*/
|
|
275
|
+
transferConfig(args, side) {
|
|
276
|
+
const providerFlag = args.flags[`${side}-provider`];
|
|
277
|
+
const rootFlag = args.flags[`${side}-root`];
|
|
278
|
+
const provider = typeof providerFlag === "string" ? providerFlag : "memory";
|
|
279
|
+
const root = typeof rootFlag === "string" ? rootFlag : undefined;
|
|
280
|
+
return { provider, root };
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* Build a {@link StorageDriverFactory} for the configured driver, used by
|
|
284
|
+
* `storage:verify` to obtain a freshly constructed driver per contract check.
|
|
285
|
+
* A pre-constructed `config.driver` is returned as-is; the built-in `memory`
|
|
286
|
+
* and `local` providers are constructed fresh each call. An unknown provider
|
|
287
|
+
* with no supplied driver throws a descriptive {@link StorageConfigError}.
|
|
288
|
+
*/
|
|
289
|
+
driverFactory(config) {
|
|
290
|
+
if (config.driver !== undefined) {
|
|
291
|
+
const driver = config.driver;
|
|
292
|
+
return () => driver;
|
|
293
|
+
}
|
|
294
|
+
if (config.provider === "memory") {
|
|
295
|
+
return () => new MemoryStorageDriver({ clock: config.clock });
|
|
296
|
+
}
|
|
297
|
+
if (config.provider === "local") {
|
|
298
|
+
if (config.root === undefined || config.root === "") {
|
|
299
|
+
throw new StorageConfigError('The "local" storage provider requires a "root" directory (pass --root <dir>).', { provider: "local" });
|
|
300
|
+
}
|
|
301
|
+
const root = config.root;
|
|
302
|
+
return () => new LocalStorageDriver({ root, clock: config.clock });
|
|
303
|
+
}
|
|
304
|
+
throw new StorageConfigError(`Unknown storage provider "${config.provider}". Provide a built-in provider ` +
|
|
305
|
+
`("memory" or "local"), or supply a pre-constructed "driver" for cloud providers.`, { provider: config.provider });
|
|
306
|
+
}
|
|
307
|
+
/** Read the generator name from the first positional arg or `--name`. */
|
|
308
|
+
resolveName(args) {
|
|
309
|
+
const positional = args.positional[0];
|
|
310
|
+
if (typeof positional === "string") {
|
|
311
|
+
return positional;
|
|
312
|
+
}
|
|
313
|
+
return typeof args.flags["name"] === "string" ? args.flags["name"] : "";
|
|
314
|
+
}
|
|
315
|
+
/** Read the key prefix from the first positional arg or `--prefix` (default ""). */
|
|
316
|
+
resolvePrefix(args) {
|
|
317
|
+
const positional = args.positional[0];
|
|
318
|
+
if (typeof positional === "string") {
|
|
319
|
+
return positional;
|
|
320
|
+
}
|
|
321
|
+
return typeof args.flags["prefix"] === "string" ? args.flags["prefix"] : "";
|
|
322
|
+
}
|
|
323
|
+
/** Close a storage facade, swallowing any error so cleanup never masks results. */
|
|
324
|
+
async closeQuietly(storage) {
|
|
325
|
+
try {
|
|
326
|
+
await storage.close();
|
|
327
|
+
}
|
|
328
|
+
catch {
|
|
329
|
+
// Ignore close failures during CLI cleanup.
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
__decorate([
|
|
334
|
+
Command("make:storage", "Scaffold a new storage module (make:storage <Name> [--dir <dir>] [--provider memory|local])"),
|
|
335
|
+
__metadata("design:type", Function),
|
|
336
|
+
__metadata("design:paramtypes", [Object]),
|
|
337
|
+
__metadata("design:returntype", void 0)
|
|
338
|
+
], StorageCommands.prototype, "makeStorage", null);
|
|
339
|
+
__decorate([
|
|
340
|
+
Command("storage:list", "List stored object keys for the configured driver (storage:list [<prefix>] [--provider <p>] [--root <dir>])"),
|
|
341
|
+
__metadata("design:type", Function),
|
|
342
|
+
__metadata("design:paramtypes", [Object]),
|
|
343
|
+
__metadata("design:returntype", Promise)
|
|
344
|
+
], StorageCommands.prototype, "storageList", null);
|
|
345
|
+
__decorate([
|
|
346
|
+
Command("storage:clean", "Remove all objects under a prefix (storage:clean <prefix> [--provider <p>] [--root <dir>])"),
|
|
347
|
+
__metadata("design:type", Function),
|
|
348
|
+
__metadata("design:paramtypes", [Object]),
|
|
349
|
+
__metadata("design:returntype", Promise)
|
|
350
|
+
], StorageCommands.prototype, "storageClean", null);
|
|
351
|
+
__decorate([
|
|
352
|
+
Command("storage:sync", "Copy objects between two configured stores (storage:sync [<prefix>] --from-provider <p> --to-provider <p>)"),
|
|
353
|
+
__metadata("design:type", Function),
|
|
354
|
+
__metadata("design:paramtypes", [Object]),
|
|
355
|
+
__metadata("design:returntype", Promise)
|
|
356
|
+
], StorageCommands.prototype, "storageSync", null);
|
|
357
|
+
__decorate([
|
|
358
|
+
Command("storage:migrate", "Migrate objects from one store to another (storage:migrate [<prefix>] --from-provider <p> --to-provider <p>)"),
|
|
359
|
+
__metadata("design:type", Function),
|
|
360
|
+
__metadata("design:paramtypes", [Object]),
|
|
361
|
+
__metadata("design:returntype", Promise)
|
|
362
|
+
], StorageCommands.prototype, "storageMigrate", null);
|
|
363
|
+
__decorate([
|
|
364
|
+
Command("storage:verify", "Run the contract-conformance suite against the configured driver (storage:verify [--provider <p>] [--root <dir>])"),
|
|
365
|
+
__metadata("design:type", Function),
|
|
366
|
+
__metadata("design:paramtypes", [Object]),
|
|
367
|
+
__metadata("design:returntype", Promise)
|
|
368
|
+
], StorageCommands.prototype, "storageVerify", null);
|
|
369
|
+
//# sourceMappingURL=commands.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"commands.js","sourceRoot":"","sources":["../../src/cli/commands.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/** The outcome of a generator invocation. */
|
|
2
|
+
export interface GenerateResult {
|
|
3
|
+
/** Path of the file that was (or would be) written. */
|
|
4
|
+
path: string;
|
|
5
|
+
/** The generated source content. */
|
|
6
|
+
contents: string;
|
|
7
|
+
}
|
|
8
|
+
/** Default output directory for `make:storage` scaffolds. */
|
|
9
|
+
export declare const DEFAULT_STORAGE_DIR = "./storage";
|
|
10
|
+
/** The built-in, zero-dependency providers a scaffold may target directly. */
|
|
11
|
+
declare const BUILT_IN_PROVIDERS: readonly ["memory", "local"];
|
|
12
|
+
/** A zero-dependency provider name accepted by {@link generateStorage}. */
|
|
13
|
+
export type BuiltInProvider = (typeof BUILT_IN_PROVIDERS)[number];
|
|
14
|
+
/** Validate a `make:storage` name (identifier-safe). */
|
|
15
|
+
export declare function isValidGeneratorName(name: string): boolean;
|
|
16
|
+
/** Validate a scaffold provider against the built-in zero-dependency set. */
|
|
17
|
+
export declare function isValidProvider(provider: string): provider is BuiltInProvider;
|
|
18
|
+
/**
|
|
19
|
+
* Generate a storage module scaffold: a typed factory that builds a
|
|
20
|
+
* {@link Storage} instance through {@link createStorage}, importing only the
|
|
21
|
+
* public `@streetjs/storage` surface. Compiles cleanly under `tsc`
|
|
22
|
+
* (Requirement 21.2).
|
|
23
|
+
*
|
|
24
|
+
* @param name - PascalCase identifier for the storage module.
|
|
25
|
+
* @param dir - Output directory (defaults to {@link DEFAULT_STORAGE_DIR}).
|
|
26
|
+
* @param provider - A built-in zero-dependency provider (`memory` or `local`);
|
|
27
|
+
* defaults to `memory` so the scaffold runs without configuration.
|
|
28
|
+
* @throws Error when `name` is not a valid identifier or `provider` is not a
|
|
29
|
+
* built-in zero-dependency provider — validated before any output is produced.
|
|
30
|
+
*/
|
|
31
|
+
export declare function generateStorage(name: string, dir?: string, provider?: BuiltInProvider): GenerateResult;
|
|
32
|
+
/**
|
|
33
|
+
* Write a generated scaffold to disk, refusing to overwrite an existing target
|
|
34
|
+
* and creating a fresh file otherwise. The parent directory is created as
|
|
35
|
+
* needed; the `wx` flag makes the no-overwrite check atomic.
|
|
36
|
+
*
|
|
37
|
+
* @throws Error when the target file already exists.
|
|
38
|
+
*/
|
|
39
|
+
export declare function writeScaffold(result: GenerateResult): void;
|
|
40
|
+
export {};
|
|
41
|
+
//# sourceMappingURL=generators.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generators.d.ts","sourceRoot":"","sources":["../../src/cli/generators.ts"],"names":[],"mappings":"AAeA,6CAA6C;AAC7C,MAAM,WAAW,cAAc;IAC7B,uDAAuD;IACvD,IAAI,EAAE,MAAM,CAAC;IACb,oCAAoC;IACpC,QAAQ,EAAE,MAAM,CAAC;CAClB;AAKD,6DAA6D;AAC7D,eAAO,MAAM,mBAAmB,cAAc,CAAC;AAE/C,8EAA8E;AAC9E,QAAA,MAAM,kBAAkB,8BAA+B,CAAC;AAExD,2EAA2E;AAC3E,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,kBAAkB,CAAC,CAAC,MAAM,CAAC,CAAC;AAElE,wDAAwD;AACxD,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE1D;AAED,6EAA6E;AAC7E,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,QAAQ,IAAI,eAAe,CAE7E;AAsCD;;;;;;;;;;;;GAYG;AACH,wBAAgB,eAAe,CAC7B,IAAI,EAAE,MAAM,EACZ,GAAG,GAAE,MAA4B,EACjC,QAAQ,GAAE,eAA0B,GACnC,cAAc,CAoChB;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,cAAc,GAAG,IAAI,CAM1D"}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
// src/cli/generators.ts
|
|
2
|
+
// @streetjs/storage — code generators for `make:storage`.
|
|
3
|
+
//
|
|
4
|
+
// Validate a name, refuse to overwrite an existing target, and emit a typed
|
|
5
|
+
// scaffold that imports only public `@streetjs/storage` symbols and compiles
|
|
6
|
+
// under `tsc`. Name validation and template rendering are pure (no filesystem),
|
|
7
|
+
// so they are trivially unit-testable; `writeScaffold` performs the guarded
|
|
8
|
+
// write. This mirrors the `@streetjs/events` cli/generators.ts pattern.
|
|
9
|
+
//
|
|
10
|
+
// Requirement 21.2: `make:storage` produces TypeScript source that compiles
|
|
11
|
+
// with `tsc` without errors.
|
|
12
|
+
import { existsSync, mkdirSync, writeFileSync } from "node:fs";
|
|
13
|
+
import { dirname, join } from "node:path";
|
|
14
|
+
/** A generator name must be an identifier-safe PascalCase token. */
|
|
15
|
+
const IDENTIFIER_RE = /^[A-Za-z][A-Za-z0-9]*$/;
|
|
16
|
+
/** Default output directory for `make:storage` scaffolds. */
|
|
17
|
+
export const DEFAULT_STORAGE_DIR = "./storage";
|
|
18
|
+
/** The built-in, zero-dependency providers a scaffold may target directly. */
|
|
19
|
+
const BUILT_IN_PROVIDERS = ["memory", "local"];
|
|
20
|
+
/** Validate a `make:storage` name (identifier-safe). */
|
|
21
|
+
export function isValidGeneratorName(name) {
|
|
22
|
+
return typeof name === "string" && IDENTIFIER_RE.test(name);
|
|
23
|
+
}
|
|
24
|
+
/** Validate a scaffold provider against the built-in zero-dependency set. */
|
|
25
|
+
export function isValidProvider(provider) {
|
|
26
|
+
return BUILT_IN_PROVIDERS.includes(provider);
|
|
27
|
+
}
|
|
28
|
+
function toClassName(name) {
|
|
29
|
+
return name.charAt(0).toUpperCase() + name.slice(1);
|
|
30
|
+
}
|
|
31
|
+
function assertValidName(name) {
|
|
32
|
+
if (!isValidGeneratorName(name)) {
|
|
33
|
+
throw new Error(`Invalid generator name: "${name}". Use a PascalCase identifier ` +
|
|
34
|
+
`(a letter followed by letters or digits, e.g. "Uploads").`);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
function assertValidProvider(provider) {
|
|
38
|
+
if (!isValidProvider(provider)) {
|
|
39
|
+
throw new Error(`Invalid storage provider: "${provider}". Use a built-in zero-dependency ` +
|
|
40
|
+
`provider (${BUILT_IN_PROVIDERS.map((p) => `"${p}"`).join(" or ")}).`);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Render the provider-specific `StorageConfig` literal body. The `local`
|
|
45
|
+
* provider requires a `root` directory, so the scaffold supplies a sensible
|
|
46
|
+
* default that keeps the emitted module compiling and runnable out of the box.
|
|
47
|
+
*/
|
|
48
|
+
function renderConfigBody(provider, className) {
|
|
49
|
+
if (provider === "local") {
|
|
50
|
+
return ` provider: "local",
|
|
51
|
+
// The local filesystem driver persists objects beneath this directory.
|
|
52
|
+
root: "./var/${className.toLowerCase()}",`;
|
|
53
|
+
}
|
|
54
|
+
return ` provider: "memory",`;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Generate a storage module scaffold: a typed factory that builds a
|
|
58
|
+
* {@link Storage} instance through {@link createStorage}, importing only the
|
|
59
|
+
* public `@streetjs/storage` surface. Compiles cleanly under `tsc`
|
|
60
|
+
* (Requirement 21.2).
|
|
61
|
+
*
|
|
62
|
+
* @param name - PascalCase identifier for the storage module.
|
|
63
|
+
* @param dir - Output directory (defaults to {@link DEFAULT_STORAGE_DIR}).
|
|
64
|
+
* @param provider - A built-in zero-dependency provider (`memory` or `local`);
|
|
65
|
+
* defaults to `memory` so the scaffold runs without configuration.
|
|
66
|
+
* @throws Error when `name` is not a valid identifier or `provider` is not a
|
|
67
|
+
* built-in zero-dependency provider — validated before any output is produced.
|
|
68
|
+
*/
|
|
69
|
+
export function generateStorage(name, dir = DEFAULT_STORAGE_DIR, provider = "memory") {
|
|
70
|
+
// Validate every input BEFORE producing any output (pure, no filesystem).
|
|
71
|
+
assertValidName(name);
|
|
72
|
+
assertValidProvider(provider);
|
|
73
|
+
const className = toClassName(name);
|
|
74
|
+
const factoryName = `create${className}Storage`;
|
|
75
|
+
const configName = `${className.charAt(0).toLowerCase()}${className.slice(1)}StorageConfig`;
|
|
76
|
+
const path = join(dir, `${className}Storage.ts`);
|
|
77
|
+
const contents = `// ${className}Storage.ts — generated by \`street make:storage ${name}\`.
|
|
78
|
+
import { createStorage } from "@streetjs/storage";
|
|
79
|
+
import type { Storage, StorageConfig } from "@streetjs/storage";
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Configuration for the ${className} storage module. Backed by the built-in
|
|
83
|
+
* zero-dependency "${provider}" provider so it runs without external services.
|
|
84
|
+
* Switch \`provider\` (and supply a pre-constructed \`driver\` for cloud
|
|
85
|
+
* providers) to change the backend without touching call sites.
|
|
86
|
+
*/
|
|
87
|
+
export const ${configName}: StorageConfig = {
|
|
88
|
+
${renderConfigBody(provider, className)}
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Build the ${className} {@link Storage} instance. Application code should call
|
|
93
|
+
* this once during startup and share the returned facade.
|
|
94
|
+
*
|
|
95
|
+
* Use it:
|
|
96
|
+
* const storage = ${factoryName}();
|
|
97
|
+
* await storage.put("hello.txt", "world");
|
|
98
|
+
*/
|
|
99
|
+
export function ${factoryName}(): Storage {
|
|
100
|
+
return createStorage(${configName});
|
|
101
|
+
}
|
|
102
|
+
`;
|
|
103
|
+
return { path, contents };
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Write a generated scaffold to disk, refusing to overwrite an existing target
|
|
107
|
+
* and creating a fresh file otherwise. The parent directory is created as
|
|
108
|
+
* needed; the `wx` flag makes the no-overwrite check atomic.
|
|
109
|
+
*
|
|
110
|
+
* @throws Error when the target file already exists.
|
|
111
|
+
*/
|
|
112
|
+
export function writeScaffold(result) {
|
|
113
|
+
if (existsSync(result.path)) {
|
|
114
|
+
throw new Error(`Refusing to overwrite existing file: ${result.path}`);
|
|
115
|
+
}
|
|
116
|
+
mkdirSync(dirname(result.path), { recursive: true });
|
|
117
|
+
writeFileSync(result.path, result.contents, { encoding: "utf8", flag: "wx" });
|
|
118
|
+
}
|
|
119
|
+
//# sourceMappingURL=generators.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generators.js","sourceRoot":"","sources":["../../src/cli/generators.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @streetjs/storage — the Directory API over a flat key space (task 17.1).
|
|
3
|
+
*
|
|
4
|
+
* Object stores have a flat key space with no real directories. This module
|
|
5
|
+
* implements a directory-style API entirely over that flat key space using
|
|
6
|
+
* `/`-delimited prefixes, so the same code runs unchanged on every
|
|
7
|
+
* {@link StorageDriver} — including prefix-only cloud providers (Requirement
|
|
8
|
+
* 15.5). The facade exposes the constructed instance as `storage.directory`.
|
|
9
|
+
*
|
|
10
|
+
* The four operations map onto driver primitives (`list`/`put`/`delete`) as
|
|
11
|
+
* follows:
|
|
12
|
+
*
|
|
13
|
+
* - `mkdir(path)` records an empty marker key `path/`, making the path
|
|
14
|
+
* available as a directory prefix (Requirement 15.1). A root/empty path needs
|
|
15
|
+
* no marker and is a no-op.
|
|
16
|
+
* - `listDirectory(path)` calls `driver.list(path/)` and collapses the results
|
|
17
|
+
* to the **immediate** children by splitting each key on the next `/` after
|
|
18
|
+
* the prefix: keys with no further `/` are file entries, keys with a further
|
|
19
|
+
* `/` contribute a single synthesized sub-directory entry (Requirement 15.2).
|
|
20
|
+
* - `removeDirectory(path)` deletes every key under the prefix; when the prefix
|
|
21
|
+
* contains no objects it is a success no-op that removes nothing
|
|
22
|
+
* (Requirements 15.3, 15.6).
|
|
23
|
+
* - `walk(path)` returns every object key strictly beneath the prefix
|
|
24
|
+
* (Requirement 15.4).
|
|
25
|
+
*
|
|
26
|
+
* The public {@link DirectoryApi} type is owned by `facade.ts` (and re-exported
|
|
27
|
+
* from `index.ts`); it is imported here type-only so there is no runtime import
|
|
28
|
+
* cycle between the two modules.
|
|
29
|
+
*
|
|
30
|
+
* _Requirements: 15.1, 15.2, 15.3, 15.4, 15.5, 15.6_
|
|
31
|
+
*/
|
|
32
|
+
import type { StorageDriver } from "./driver.js";
|
|
33
|
+
import type { DirectoryApi } from "./facade.js";
|
|
34
|
+
import type { StorageListItem } from "./types.js";
|
|
35
|
+
/**
|
|
36
|
+
* A {@link DirectoryApi} implementation over any {@link StorageDriver}'s flat
|
|
37
|
+
* key space. It holds only the driver and derives every directory operation
|
|
38
|
+
* from `/`-delimited prefixes, so it behaves identically across providers.
|
|
39
|
+
*/
|
|
40
|
+
export declare class StorageDirectoryApi implements DirectoryApi {
|
|
41
|
+
private readonly driver;
|
|
42
|
+
constructor(driver: StorageDriver);
|
|
43
|
+
/**
|
|
44
|
+
* Normalize a directory `path` to a prefix ending in the delimiter. The root
|
|
45
|
+
* (`""` or `"/"`) normalizes to the empty prefix (which matches every key),
|
|
46
|
+
* and any leading delimiter is dropped so `"/photos"` and `"photos"` refer to
|
|
47
|
+
* the same directory. A path that already ends with the delimiter is left
|
|
48
|
+
* unchanged.
|
|
49
|
+
*/
|
|
50
|
+
private toPrefix;
|
|
51
|
+
/**
|
|
52
|
+
* List the keys stored under `prefix`, defensively re-filtering by the prefix
|
|
53
|
+
* so drivers that interpret `list` loosely never leak keys from outside the
|
|
54
|
+
* directory into a directory operation.
|
|
55
|
+
*/
|
|
56
|
+
private keysUnder;
|
|
57
|
+
/**
|
|
58
|
+
* Make `path` available as a directory prefix by recording an empty marker
|
|
59
|
+
* key `path/` (Requirement 15.1). The root/empty path requires no marker and
|
|
60
|
+
* is a no-op.
|
|
61
|
+
*/
|
|
62
|
+
mkdir(path: string): Promise<void>;
|
|
63
|
+
/**
|
|
64
|
+
* Return the immediate child entries under `path` (Requirement 15.2). Each
|
|
65
|
+
* key under the prefix is split on the next delimiter: a key with no further
|
|
66
|
+
* delimiter is returned as its file entry; keys sharing a further path
|
|
67
|
+
* segment collapse into a single synthesized sub-directory entry (key
|
|
68
|
+
* `path/child/`, `size` 0). The directory's own marker (a key equal to the
|
|
69
|
+
* prefix) is not reported as a child.
|
|
70
|
+
*/
|
|
71
|
+
listDirectory(path: string): Promise<StorageListItem[]>;
|
|
72
|
+
/**
|
|
73
|
+
* Remove every object stored under `path` (Requirement 15.3). When the prefix
|
|
74
|
+
* contains no objects — because the directory does not exist or is already
|
|
75
|
+
* empty — nothing is removed and a success result of `{ removed: false }` is
|
|
76
|
+
* returned without throwing (Requirement 15.6). When at least one object is
|
|
77
|
+
* removed the result is `{ removed: true }`.
|
|
78
|
+
*/
|
|
79
|
+
removeDirectory(path: string): Promise<{
|
|
80
|
+
readonly removed: boolean;
|
|
81
|
+
}>;
|
|
82
|
+
/**
|
|
83
|
+
* Return every object key strictly beneath `path` (Requirement 15.4),
|
|
84
|
+
* excluding the directory's own marker key (a key equal to the prefix).
|
|
85
|
+
*/
|
|
86
|
+
walk(path: string): Promise<string[]>;
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=directory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"directory.d.ts","sourceRoot":"","sources":["../src/directory.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAKlD;;;;GAIG;AACH,qBAAa,mBAAoB,YAAW,YAAY;IACtD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgB;gBAE3B,MAAM,EAAE,aAAa;IAIjC;;;;;;OAMG;IACH,OAAO,CAAC,QAAQ;IAWhB;;;;OAIG;YACW,SAAS;IAQvB;;;;OAIG;IACG,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQxC;;;;;;;OAOG;IACG,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC;IA+B7D;;;;;;OAMG;IACG,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;IAY3E;;;OAGG;IACG,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;CAK5C"}
|