@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,240 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @streetjs/storage — CloudflareR2Driver (submodule `@streetjs/storage/r2`).
|
|
3
|
+
*
|
|
4
|
+
* Cloudflare R2 speaks the S3 API, so this driver is a thin **endpoint/credential
|
|
5
|
+
* specialization** of the shared S3-style base ({@link createS3StyleDriver} in
|
|
6
|
+
* `s3-base.ts`). It differs from `s3.ts` only in how the underlying client is
|
|
7
|
+
* built — R2 uses an account-specific endpoint
|
|
8
|
+
* (`https://<accountId>.r2.cloudflarestorage.com`) with `region: "auto"` — never
|
|
9
|
+
* in how the {@link StorageDriver} contract is satisfied.
|
|
10
|
+
*
|
|
11
|
+
* ## Two ways to obtain a driver
|
|
12
|
+
*
|
|
13
|
+
* - {@link createCloudflareR2Driver} wraps an **already-constructed, injected**
|
|
14
|
+
* structural {@link S3ClientLike} and returns a driver synchronously. This is
|
|
15
|
+
* the SDK-free path: no provider SDK is touched, so it is fully testable with
|
|
16
|
+
* an in-memory fake and needs no `@aws-sdk/*` install.
|
|
17
|
+
* - {@link connectCloudflareR2Driver} **builds its own client** from R2
|
|
18
|
+
* connection config. It resolves the S3-compatible SDK through a **lazy
|
|
19
|
+
* dynamic `import()` performed inside the function** (never at module top
|
|
20
|
+
* level), so the optional peer dependency is only required when this path is
|
|
21
|
+
* actually used. If the SDK is not installed and no client was injected, it
|
|
22
|
+
* throws {@link StorageConfigError} (Requirement 1.5).
|
|
23
|
+
*
|
|
24
|
+
* ## SDK isolation (Requirements 2.1, 3.3)
|
|
25
|
+
*
|
|
26
|
+
* This module imports **no provider SDK at the top level** — only this package's
|
|
27
|
+
* own base/types/errors. The AWS S3 SDK (which R2 uses) is referenced solely via
|
|
28
|
+
* a dynamic `import()` with a non-literal specifier inside
|
|
29
|
+
* {@link connectCloudflareR2Driver}, so `tsc` never requires the SDK to be
|
|
30
|
+
* present and `streetjs` stays the only runtime dependency. This driver is a
|
|
31
|
+
* submodule-only export (`./r2` → `dist/drivers/r2.js`); it is intentionally not
|
|
32
|
+
* re-exported from the package's main `index.ts`.
|
|
33
|
+
*
|
|
34
|
+
* _Requirements: 2.1, 2.3, 3.3_
|
|
35
|
+
*/
|
|
36
|
+
import { StorageConfigError } from "../errors.js";
|
|
37
|
+
import { createS3StyleDriver, S3StyleDriver, } from "./s3-base.js";
|
|
38
|
+
/** The stable driver name surfaced as {@link StorageDriver.name} for R2. */
|
|
39
|
+
const R2_DRIVER_NAME = "r2";
|
|
40
|
+
/**
|
|
41
|
+
* The CloudflareR2 {@link StorageDriver}: the shared S3-style base pinned to the
|
|
42
|
+
* `"r2"` provider name. Construction is identical to the base — supply an
|
|
43
|
+
* {@link S3ClientLike} — the only difference is the fixed name.
|
|
44
|
+
*/
|
|
45
|
+
export class CloudflareR2Driver extends S3StyleDriver {
|
|
46
|
+
constructor(client, options = {}) {
|
|
47
|
+
super(client, { ...options, name: R2_DRIVER_NAME });
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Wrap an injected {@link S3ClientLike} as an R2 driver, delegating to
|
|
52
|
+
* {@link createS3StyleDriver} with the name `"r2"`. Synchronous and SDK-free:
|
|
53
|
+
* the caller supplies the client, so no provider SDK is resolved here.
|
|
54
|
+
*/
|
|
55
|
+
export function createCloudflareR2Driver(client, options = {}) {
|
|
56
|
+
return createS3StyleDriver(client, { ...options, name: R2_DRIVER_NAME });
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Build an R2 driver that owns its client, resolving the S3-compatible SDK
|
|
60
|
+
* lazily.
|
|
61
|
+
*
|
|
62
|
+
* The SDK is loaded through a dynamic `import()` with a non-literal specifier so
|
|
63
|
+
* it is never a static/top-level dependency: `tsc` does not require it to be
|
|
64
|
+
* installed, and it is only resolved when this function runs. When the SDK
|
|
65
|
+
* cannot be resolved, a {@link StorageConfigError} is thrown (Requirement 1.5) —
|
|
66
|
+
* callers that cannot install the SDK should use {@link createCloudflareR2Driver}
|
|
67
|
+
* with their own {@link S3ClientLike} instead.
|
|
68
|
+
*/
|
|
69
|
+
export async function connectCloudflareR2Driver(config) {
|
|
70
|
+
const { accountId, bucket, accessKeyId, secretAccessKey } = config;
|
|
71
|
+
if (!accountId || !bucket || !accessKeyId || !secretAccessKey) {
|
|
72
|
+
throw new StorageConfigError("CloudflareR2 requires accountId, bucket, accessKeyId, and secretAccessKey.", { provider: R2_DRIVER_NAME });
|
|
73
|
+
}
|
|
74
|
+
const endpoint = config.endpoint ?? `https://${accountId}.r2.cloudflarestorage.com`;
|
|
75
|
+
const region = config.region ?? "auto";
|
|
76
|
+
// Lazy, non-literal dynamic import so the S3 SDK stays an optional peer that
|
|
77
|
+
// `tsc` never resolves statically and Node only loads on this path.
|
|
78
|
+
const specifier = "@aws-sdk/client-s3";
|
|
79
|
+
let sdk;
|
|
80
|
+
try {
|
|
81
|
+
sdk = (await import(specifier));
|
|
82
|
+
}
|
|
83
|
+
catch (cause) {
|
|
84
|
+
throw new StorageConfigError('CloudflareR2 driver requires the optional peer dependency "@aws-sdk/client-s3". ' +
|
|
85
|
+
"Install it, or inject your own S3ClientLike via createCloudflareR2Driver().", { provider: R2_DRIVER_NAME, cause });
|
|
86
|
+
}
|
|
87
|
+
const s3 = new sdk.S3Client({
|
|
88
|
+
region,
|
|
89
|
+
endpoint,
|
|
90
|
+
credentials: { accessKeyId, secretAccessKey },
|
|
91
|
+
forcePathStyle: true,
|
|
92
|
+
});
|
|
93
|
+
const client = adaptAwsS3Client(s3, sdk, bucket);
|
|
94
|
+
return createCloudflareR2Driver(client, {
|
|
95
|
+
clock: config.clock,
|
|
96
|
+
capabilities: config.capabilities,
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
// ── AWS S3 SDK adapter ─────────────────────────────────────────────────────────
|
|
100
|
+
/**
|
|
101
|
+
* Adapt an AWS S3 v3 client into the structural {@link S3ClientLike} the base
|
|
102
|
+
* depends on, binding every call to `bucket`. Only the methods the base uses are
|
|
103
|
+
* mapped; the AWS response shapes are narrowed through the local structural
|
|
104
|
+
* types below so this module never imports concrete SDK types.
|
|
105
|
+
*/
|
|
106
|
+
function adaptAwsS3Client(s3, sdk, bucket) {
|
|
107
|
+
return {
|
|
108
|
+
async putObject(input) {
|
|
109
|
+
const res = await s3.send(new sdk.PutObjectCommand({
|
|
110
|
+
Bucket: bucket,
|
|
111
|
+
Key: input.key,
|
|
112
|
+
Body: input.body,
|
|
113
|
+
ContentType: input.contentType,
|
|
114
|
+
Metadata: input.metadata,
|
|
115
|
+
}));
|
|
116
|
+
return { etag: res.ETag ?? "" };
|
|
117
|
+
},
|
|
118
|
+
async getObject(input) {
|
|
119
|
+
let res;
|
|
120
|
+
try {
|
|
121
|
+
res = await s3.send(new sdk.GetObjectCommand({ Bucket: bucket, Key: input.key }));
|
|
122
|
+
}
|
|
123
|
+
catch (error) {
|
|
124
|
+
if (isNotFound(error)) {
|
|
125
|
+
return null;
|
|
126
|
+
}
|
|
127
|
+
throw error;
|
|
128
|
+
}
|
|
129
|
+
const body = res.Body ? await res.Body.transformToByteArray() : new Uint8Array(0);
|
|
130
|
+
return {
|
|
131
|
+
body,
|
|
132
|
+
contentType: res.ContentType,
|
|
133
|
+
etag: res.ETag,
|
|
134
|
+
size: res.ContentLength ?? body.byteLength,
|
|
135
|
+
lastModified: toEpochMs(res.LastModified),
|
|
136
|
+
metadata: res.Metadata,
|
|
137
|
+
};
|
|
138
|
+
},
|
|
139
|
+
async deleteObject(input) {
|
|
140
|
+
await s3.send(new sdk.DeleteObjectCommand({ Bucket: bucket, Key: input.key }));
|
|
141
|
+
},
|
|
142
|
+
async listObjects(input) {
|
|
143
|
+
const res = await s3.send(new sdk.ListObjectsV2Command({
|
|
144
|
+
Bucket: bucket,
|
|
145
|
+
Prefix: input.prefix,
|
|
146
|
+
MaxKeys: input.limit,
|
|
147
|
+
ContinuationToken: input.cursor,
|
|
148
|
+
Delimiter: input.delimiter === true ? "/" : undefined,
|
|
149
|
+
}));
|
|
150
|
+
const contents = res.Contents ?? [];
|
|
151
|
+
return contents.map((item) => ({
|
|
152
|
+
key: item.Key ?? "",
|
|
153
|
+
size: item.Size ?? 0,
|
|
154
|
+
updatedAt: toEpochMs(item.LastModified) ?? 0,
|
|
155
|
+
}));
|
|
156
|
+
},
|
|
157
|
+
async headObject(input) {
|
|
158
|
+
let res;
|
|
159
|
+
try {
|
|
160
|
+
res = await s3.send(new sdk.HeadObjectCommand({ Bucket: bucket, Key: input.key }));
|
|
161
|
+
}
|
|
162
|
+
catch (error) {
|
|
163
|
+
if (isNotFound(error)) {
|
|
164
|
+
return null;
|
|
165
|
+
}
|
|
166
|
+
throw error;
|
|
167
|
+
}
|
|
168
|
+
return {
|
|
169
|
+
contentType: res.ContentType,
|
|
170
|
+
etag: res.ETag,
|
|
171
|
+
size: res.ContentLength,
|
|
172
|
+
lastModified: toEpochMs(res.LastModified),
|
|
173
|
+
metadata: res.Metadata,
|
|
174
|
+
};
|
|
175
|
+
},
|
|
176
|
+
async createMultipartUpload(input) {
|
|
177
|
+
const res = await s3.send(new sdk.CreateMultipartUploadCommand({
|
|
178
|
+
Bucket: bucket,
|
|
179
|
+
Key: input.key,
|
|
180
|
+
ContentType: input.contentType,
|
|
181
|
+
Metadata: input.metadata,
|
|
182
|
+
}));
|
|
183
|
+
return { uploadId: res.UploadId ?? "" };
|
|
184
|
+
},
|
|
185
|
+
async uploadPart(input) {
|
|
186
|
+
const res = await s3.send(new sdk.UploadPartCommand({
|
|
187
|
+
Bucket: bucket,
|
|
188
|
+
Key: input.key,
|
|
189
|
+
UploadId: input.uploadId,
|
|
190
|
+
PartNumber: input.partNumber,
|
|
191
|
+
Body: input.body,
|
|
192
|
+
}));
|
|
193
|
+
return { etag: res.ETag ?? "" };
|
|
194
|
+
},
|
|
195
|
+
async completeMultipartUpload(input) {
|
|
196
|
+
const res = await s3.send(new sdk.CompleteMultipartUploadCommand({
|
|
197
|
+
Bucket: bucket,
|
|
198
|
+
Key: input.key,
|
|
199
|
+
UploadId: input.uploadId,
|
|
200
|
+
MultipartUpload: {
|
|
201
|
+
Parts: input.parts.map((part) => ({
|
|
202
|
+
PartNumber: part.partNumber,
|
|
203
|
+
ETag: part.etag,
|
|
204
|
+
})),
|
|
205
|
+
},
|
|
206
|
+
}));
|
|
207
|
+
return { etag: res.ETag ?? "" };
|
|
208
|
+
},
|
|
209
|
+
async abortMultipartUpload(input) {
|
|
210
|
+
await s3.send(new sdk.AbortMultipartUploadCommand({
|
|
211
|
+
Bucket: bucket,
|
|
212
|
+
Key: input.key,
|
|
213
|
+
UploadId: input.uploadId,
|
|
214
|
+
}));
|
|
215
|
+
},
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Recognize the "no such key / not found" conditions the S3 API reports so
|
|
220
|
+
* `getObject`/`headObject` can return `null` (Requirement 4.2/4.10) rather than
|
|
221
|
+
* throwing. Matches the SDK's error `name` and the HTTP 404 status.
|
|
222
|
+
*/
|
|
223
|
+
function isNotFound(error) {
|
|
224
|
+
if (typeof error !== "object" || error === null) {
|
|
225
|
+
return false;
|
|
226
|
+
}
|
|
227
|
+
const record = error;
|
|
228
|
+
if (record.name === "NoSuchKey" || record.name === "NotFound") {
|
|
229
|
+
return true;
|
|
230
|
+
}
|
|
231
|
+
if (record.Code === "NoSuchKey" || record.Code === "NotFound") {
|
|
232
|
+
return true;
|
|
233
|
+
}
|
|
234
|
+
return record.$metadata?.httpStatusCode === 404;
|
|
235
|
+
}
|
|
236
|
+
/** Convert an SDK `Date` (or undefined) to epoch milliseconds. */
|
|
237
|
+
function toEpochMs(value) {
|
|
238
|
+
return value instanceof Date ? value.getTime() : undefined;
|
|
239
|
+
}
|
|
240
|
+
//# sourceMappingURL=r2.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"r2.js","sourceRoot":"","sources":["../../src/drivers/r2.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @streetjs/storage — the shared S3-style driver base and {@link S3ClientLike}.
|
|
3
|
+
*
|
|
4
|
+
* S3-compatible providers (Amazon S3, Cloudflare R2, MinIO, and the Backblaze B2
|
|
5
|
+
* S3 API) share one wire shape: a small set of object operations
|
|
6
|
+
* (`putObject`/`getObject`/`deleteObject`/`listObjects`) plus optional
|
|
7
|
+
* multipart and presign calls. This module captures that shape as the structural
|
|
8
|
+
* {@link S3ClientLike} interface and maps the {@link StorageDriver} contract onto
|
|
9
|
+
* it, so `s3.ts`, `r2.ts`, `minio.ts`, and `backblaze.ts` (tasks 28.2–28.5) only
|
|
10
|
+
* differ in how they build/configure the client, never in how the contract is
|
|
11
|
+
* satisfied.
|
|
12
|
+
*
|
|
13
|
+
* ## SDK isolation (Requirements 3.1, 3.3)
|
|
14
|
+
*
|
|
15
|
+
* This module imports **no provider SDK** at the top level — only Node built-ins,
|
|
16
|
+
* `streetjs` (for the injected {@link Clock}), and this package's own type
|
|
17
|
+
* surface. The base accepts an **injected** {@link S3ClientLike}; it never
|
|
18
|
+
* resolves an SDK itself. The concrete submodules that *can* construct their own
|
|
19
|
+
* client do so with a **lazy dynamic `import()`** performed inside that submodule
|
|
20
|
+
* at construction time, so the optional peer SDK is resolved only when that
|
|
21
|
+
* submodule is actually imported. `streetjs` therefore stays the only runtime
|
|
22
|
+
* dependency.
|
|
23
|
+
*
|
|
24
|
+
* ## Capability delegation (Requirement 2.3)
|
|
25
|
+
*
|
|
26
|
+
* The base implements the **mandatory primitives** (`put`/`get`/`exists`/
|
|
27
|
+
* `delete`/`stat`/`list`/`putStream`/`getStream`) by mapping onto
|
|
28
|
+
* {@link S3ClientLike}, producing every {@link StorageObjectMetadata} through the
|
|
29
|
+
* shared metadata layer ({@link buildObjectMetadata}) so the field set is
|
|
30
|
+
* identical to Memory/Local, and reporting a missing key consistently
|
|
31
|
+
* ({@link MaybeObject} `{ found: false }` for `get`, `null` for `stat`,
|
|
32
|
+
* {@link NotFoundError} for `getStream`).
|
|
33
|
+
*
|
|
34
|
+
* Advanced capabilities are **delegated to the client when available, otherwise
|
|
35
|
+
* left `undefined` so the facade simulates them over the primitives**
|
|
36
|
+
* (Requirement 2, keeping behavior identical across providers):
|
|
37
|
+
*
|
|
38
|
+
* - **Multipart** is wired only when the client exposes the full SDK-shaped
|
|
39
|
+
* multipart method set; the base adapts those calls into a
|
|
40
|
+
* {@link MultipartCapability}, tracking the `uploadId → key` mapping the S3 API
|
|
41
|
+
* requires.
|
|
42
|
+
* - **Versioning / lifecycle / signed URLs** are delegated only when a native
|
|
43
|
+
* capability object is supplied through `options.capabilities`; otherwise they
|
|
44
|
+
* are left `undefined`. (A provider's presigned URLs are verified by the
|
|
45
|
+
* provider, not locally, so the base does not synthesize a
|
|
46
|
+
* {@link SignedUrlCapability} from a bare `presignUrl` — the facade's HMAC
|
|
47
|
+
* simulation is used instead unless a full native capability is injected.)
|
|
48
|
+
*
|
|
49
|
+
* _Requirements: 2.3, 3.1, 3.3_
|
|
50
|
+
*/
|
|
51
|
+
import { type Clock } from "streetjs";
|
|
52
|
+
import type { MaybeObject, MultipartCapability, NodeReadable, StorageDriver, VersioningCapability, SignedUrlCapability, LifecycleCapability } from "../driver.js";
|
|
53
|
+
import type { ListOptions, StorageListItem, StorageObjectMetadata, WriteMetadata } from "../types.js";
|
|
54
|
+
/** Input to {@link S3ClientLike.putObject}. */
|
|
55
|
+
export interface S3PutObjectInput {
|
|
56
|
+
readonly key: string;
|
|
57
|
+
readonly body: Uint8Array;
|
|
58
|
+
readonly contentType?: string;
|
|
59
|
+
/** Provider "user metadata" (string→string), used to carry typed metadata. */
|
|
60
|
+
readonly metadata?: Record<string, string>;
|
|
61
|
+
}
|
|
62
|
+
/** Result of {@link S3ClientLike.putObject}. */
|
|
63
|
+
export interface S3PutObjectOutput {
|
|
64
|
+
readonly etag: string;
|
|
65
|
+
}
|
|
66
|
+
/** Result of {@link S3ClientLike.getObject} (the object body plus attributes). */
|
|
67
|
+
export interface S3GetObjectOutput {
|
|
68
|
+
readonly body: Uint8Array;
|
|
69
|
+
readonly contentType?: string;
|
|
70
|
+
readonly etag?: string;
|
|
71
|
+
readonly size?: number;
|
|
72
|
+
/** Last-modified time as epoch ms. */
|
|
73
|
+
readonly lastModified?: number;
|
|
74
|
+
readonly metadata?: Record<string, string>;
|
|
75
|
+
}
|
|
76
|
+
/** Result of {@link S3ClientLike.headObject} (attributes only, no body). */
|
|
77
|
+
export interface S3HeadObjectOutput {
|
|
78
|
+
readonly contentType?: string;
|
|
79
|
+
readonly etag?: string;
|
|
80
|
+
readonly size?: number;
|
|
81
|
+
readonly lastModified?: number;
|
|
82
|
+
readonly metadata?: Record<string, string>;
|
|
83
|
+
}
|
|
84
|
+
/** A single entry returned by {@link S3ClientLike.listObjects}. */
|
|
85
|
+
export interface S3ListItem {
|
|
86
|
+
readonly key: string;
|
|
87
|
+
readonly size: number;
|
|
88
|
+
/** Last-modified time as epoch ms. */
|
|
89
|
+
readonly updatedAt: number;
|
|
90
|
+
}
|
|
91
|
+
/** Options passed to {@link S3ClientLike.listObjects}. */
|
|
92
|
+
export interface S3ListInput {
|
|
93
|
+
readonly prefix: string;
|
|
94
|
+
readonly limit?: number;
|
|
95
|
+
readonly cursor?: string;
|
|
96
|
+
readonly delimiter?: boolean;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* The **minimal, SDK-shaped structural interface** an S3-style driver depends on.
|
|
100
|
+
*
|
|
101
|
+
* It describes just the provider calls the driver needs — never any concrete
|
|
102
|
+
* SDK type — so the actual SDK stays an optional peer concern of the consumer
|
|
103
|
+
* (Requirement 3.1). The four object operations are mandatory; `headObject`,
|
|
104
|
+
* the multipart method set, and `presignUrl` are optional and unlock the
|
|
105
|
+
* corresponding native paths when present.
|
|
106
|
+
*/
|
|
107
|
+
export interface S3ClientLike {
|
|
108
|
+
/** Store `body` under `key` with optional content type and user metadata. */
|
|
109
|
+
putObject(input: S3PutObjectInput): Promise<S3PutObjectOutput>;
|
|
110
|
+
/** Fetch the object at `key`, or `null` when it does not exist. */
|
|
111
|
+
getObject(input: {
|
|
112
|
+
readonly key: string;
|
|
113
|
+
}): Promise<S3GetObjectOutput | null>;
|
|
114
|
+
/** Delete the object at `key` (a no-op when it is already absent). */
|
|
115
|
+
deleteObject(input: {
|
|
116
|
+
readonly key: string;
|
|
117
|
+
}): Promise<void>;
|
|
118
|
+
/** List objects whose key begins with `prefix`. */
|
|
119
|
+
listObjects(input: S3ListInput): Promise<readonly S3ListItem[]>;
|
|
120
|
+
/** Fetch object attributes without the body, or `null` when absent (optional). */
|
|
121
|
+
headObject?(input: {
|
|
122
|
+
readonly key: string;
|
|
123
|
+
}): Promise<S3HeadObjectOutput | null>;
|
|
124
|
+
createMultipartUpload?(input: {
|
|
125
|
+
readonly key: string;
|
|
126
|
+
readonly contentType?: string;
|
|
127
|
+
readonly metadata?: Record<string, string>;
|
|
128
|
+
}): Promise<{
|
|
129
|
+
readonly uploadId: string;
|
|
130
|
+
}>;
|
|
131
|
+
uploadPart?(input: {
|
|
132
|
+
readonly key: string;
|
|
133
|
+
readonly uploadId: string;
|
|
134
|
+
readonly partNumber: number;
|
|
135
|
+
readonly body: Uint8Array;
|
|
136
|
+
}): Promise<{
|
|
137
|
+
readonly etag: string;
|
|
138
|
+
}>;
|
|
139
|
+
completeMultipartUpload?(input: {
|
|
140
|
+
readonly key: string;
|
|
141
|
+
readonly uploadId: string;
|
|
142
|
+
readonly parts: readonly {
|
|
143
|
+
readonly partNumber: number;
|
|
144
|
+
readonly etag: string;
|
|
145
|
+
}[];
|
|
146
|
+
}): Promise<{
|
|
147
|
+
readonly etag: string;
|
|
148
|
+
}>;
|
|
149
|
+
abortMultipartUpload?(input: {
|
|
150
|
+
readonly key: string;
|
|
151
|
+
readonly uploadId: string;
|
|
152
|
+
}): Promise<void>;
|
|
153
|
+
/**
|
|
154
|
+
* Mint a provider presigned URL for `key` (optional). Consumed by concrete
|
|
155
|
+
* provider drivers that expose native presigned URLs; the base does not build
|
|
156
|
+
* a {@link SignedUrlCapability} from it because provider URLs are verified by
|
|
157
|
+
* the provider, not locally.
|
|
158
|
+
*/
|
|
159
|
+
presignUrl?(input: {
|
|
160
|
+
readonly key: string;
|
|
161
|
+
readonly op: "GET" | "PUT" | "DELETE";
|
|
162
|
+
readonly expiresInMs: number;
|
|
163
|
+
}): Promise<string>;
|
|
164
|
+
}
|
|
165
|
+
/** Native capability objects a provider driver may inject for delegation. */
|
|
166
|
+
export interface S3NativeCapabilities {
|
|
167
|
+
readonly versioning?: VersioningCapability;
|
|
168
|
+
readonly lifecycle?: LifecycleCapability;
|
|
169
|
+
readonly signedUrl?: SignedUrlCapability;
|
|
170
|
+
}
|
|
171
|
+
/** Options for {@link createS3StyleDriver} / {@link S3StyleDriver}. */
|
|
172
|
+
export interface S3StyleDriverOptions {
|
|
173
|
+
/** Stable driver name surfaced as {@link StorageDriver.name}. Default `"s3"`. */
|
|
174
|
+
readonly name?: string;
|
|
175
|
+
/** Injected clock for deterministic timestamps in tests. Default `systemClock`. */
|
|
176
|
+
readonly clock?: Clock;
|
|
177
|
+
/**
|
|
178
|
+
* Native capability objects to delegate to. Any capability omitted here (and
|
|
179
|
+
* not derivable from the client) is left `undefined` so the facade simulates
|
|
180
|
+
* it over the primitives.
|
|
181
|
+
*/
|
|
182
|
+
readonly capabilities?: S3NativeCapabilities;
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Maps the {@link StorageDriver} contract onto an injected {@link S3ClientLike}.
|
|
186
|
+
*
|
|
187
|
+
* This class is provider-agnostic: every S3-compatible driver (S3, R2, MinIO,
|
|
188
|
+
* Backblaze) is this base with a differently-constructed client. It imports no
|
|
189
|
+
* provider SDK; the client is supplied by the caller (typically a submodule that
|
|
190
|
+
* lazily `import()`s its SDK).
|
|
191
|
+
*/
|
|
192
|
+
export declare class S3StyleDriver implements StorageDriver {
|
|
193
|
+
readonly name: string;
|
|
194
|
+
private readonly client;
|
|
195
|
+
private readonly clock;
|
|
196
|
+
/** Tracks the `key` for each in-flight multipart `uploadId` (S3 needs both). */
|
|
197
|
+
private readonly multipartKeys;
|
|
198
|
+
multipart?: MultipartCapability;
|
|
199
|
+
versioning?: VersioningCapability;
|
|
200
|
+
signedUrl?: SignedUrlCapability;
|
|
201
|
+
lifecycle?: LifecycleCapability;
|
|
202
|
+
constructor(client: S3ClientLike, options?: S3StyleDriverOptions);
|
|
203
|
+
/**
|
|
204
|
+
* Store `bytes` under `key`, computing size and sha-256 checksum locally and
|
|
205
|
+
* taking timestamps from the injected clock. When overwriting, the original
|
|
206
|
+
* `createdAt` is preserved (a preceding attribute read). The typed metadata is
|
|
207
|
+
* encoded into the provider's user-metadata map so it round-trips on read
|
|
208
|
+
* (Requirements 4.1, 10.1, 10.2).
|
|
209
|
+
*/
|
|
210
|
+
put(key: string, bytes: Uint8Array, metadata: WriteMetadata): Promise<StorageObjectMetadata>;
|
|
211
|
+
/**
|
|
212
|
+
* Read the object at `key`, returning a discriminated {@link MaybeObject} so
|
|
213
|
+
* absence is reported rather than thrown (Requirements 4.2, 2.4). Metadata is
|
|
214
|
+
* rebuilt from the provider attributes and encoded user metadata via the
|
|
215
|
+
* shared metadata layer.
|
|
216
|
+
*/
|
|
217
|
+
get(key: string): Promise<MaybeObject>;
|
|
218
|
+
/** Report whether an object is stored under `key` (Requirement 4.3). */
|
|
219
|
+
exists(key: string): Promise<boolean>;
|
|
220
|
+
/** Delete the object at `key`; deleting a missing key is a no-op (Requirement 4.4). */
|
|
221
|
+
delete(key: string): Promise<void>;
|
|
222
|
+
/**
|
|
223
|
+
* Return the metadata for `key` without its content, or `null` when absent
|
|
224
|
+
* (Requirement 4.10). Uses `headObject` when available, else falls back to a
|
|
225
|
+
* body fetch.
|
|
226
|
+
*/
|
|
227
|
+
stat(key: string): Promise<StorageObjectMetadata | null>;
|
|
228
|
+
/** List objects whose key begins with `prefix` (Requirement 4.9). */
|
|
229
|
+
list(prefix: string, options?: ListOptions): Promise<StorageListItem[]>;
|
|
230
|
+
/**
|
|
231
|
+
* Consume a Node {@link Readable} and persist the assembled bytes under `key`
|
|
232
|
+
* with the same computed metadata as {@link put} (Requirement 5.1). Chunks are
|
|
233
|
+
* drained through a `pipeline` (correct backpressure and error propagation),
|
|
234
|
+
* then handed to {@link put}.
|
|
235
|
+
*/
|
|
236
|
+
putStream(key: string, stream: NodeReadable, metadata: WriteMetadata): Promise<StorageObjectMetadata>;
|
|
237
|
+
/**
|
|
238
|
+
* Return a Node {@link Readable} of the stored bytes at `key` (Requirement
|
|
239
|
+
* 5.2). Throws {@link NotFoundError} for a missing key (Requirement 5.5).
|
|
240
|
+
*/
|
|
241
|
+
getStream(key: string): Promise<NodeReadable>;
|
|
242
|
+
/**
|
|
243
|
+
* Best-effort read of an object's existing metadata (used to preserve
|
|
244
|
+
* `createdAt` on overwrite). Returns `null` when the object does not exist.
|
|
245
|
+
*/
|
|
246
|
+
private readMeta;
|
|
247
|
+
/**
|
|
248
|
+
* Rebuild the typed {@link StorageObjectMetadata} field set from provider
|
|
249
|
+
* attributes and the encoded user-metadata map, applying the shared layer's
|
|
250
|
+
* canonical defaults. Provider-supplied values are used as best-effort
|
|
251
|
+
* fallbacks when the encoded fields are absent (e.g. an object written outside
|
|
252
|
+
* this base): `etag`/`size`/`lastModified` back-fill the identity/timestamp
|
|
253
|
+
* fields, keeping the shape consistent across providers.
|
|
254
|
+
*/
|
|
255
|
+
private decodeMeta;
|
|
256
|
+
/**
|
|
257
|
+
* Adapt the client's SDK-shaped multipart calls into a
|
|
258
|
+
* {@link MultipartCapability}. The S3 API requires the object key on every
|
|
259
|
+
* part/complete/abort call, so the `uploadId → key` mapping is tracked here.
|
|
260
|
+
*/
|
|
261
|
+
private buildMultipartCapability;
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Construct an S3-style {@link StorageDriver} over an injected
|
|
265
|
+
* {@link S3ClientLike}. This is the entry point consumed by the concrete
|
|
266
|
+
* provider submodules (`s3.ts`/`r2.ts`/`minio.ts`/`backblaze.ts`), each of which
|
|
267
|
+
* supplies a differently-constructed client.
|
|
268
|
+
*/
|
|
269
|
+
export declare function createS3StyleDriver(client: S3ClientLike, options?: S3StyleDriverOptions): StorageDriver;
|
|
270
|
+
//# sourceMappingURL=s3-base.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"s3-base.d.ts","sourceRoot":"","sources":["../../src/drivers/s3-base.ts"],"names":[],"mappings":"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"}
|