@nestm/storage 0.1.0-alpha.2 → 0.1.0-alpha.4

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.
Files changed (66) hide show
  1. package/CHANGELOG.md +44 -0
  2. package/README.md +196 -15
  3. package/SECURITY.md +23 -0
  4. package/dist/files-sdk/files-sdk.driver.d.ts +31 -2
  5. package/dist/files-sdk/files-sdk.driver.d.ts.map +1 -1
  6. package/dist/files-sdk/files-sdk.driver.js +141 -20
  7. package/dist/files-sdk/files-sdk.driver.js.map +1 -1
  8. package/dist/files-sdk/fs/index.d.ts +21 -0
  9. package/dist/files-sdk/fs/index.d.ts.map +1 -0
  10. package/dist/files-sdk/fs/index.js +20 -0
  11. package/dist/files-sdk/fs/index.js.map +1 -0
  12. package/dist/files-sdk/index.d.ts +1 -1
  13. package/dist/files-sdk/index.d.ts.map +1 -1
  14. package/dist/files-sdk/index.js.map +1 -1
  15. package/dist/files-sdk/provider/index.d.ts +54 -0
  16. package/dist/files-sdk/provider/index.d.ts.map +1 -0
  17. package/dist/files-sdk/provider/index.js +80 -0
  18. package/dist/files-sdk/provider/index.js.map +1 -0
  19. package/dist/files-sdk/s3/index.d.ts +25 -0
  20. package/dist/files-sdk/s3/index.d.ts.map +1 -0
  21. package/dist/files-sdk/s3/index.js +119 -0
  22. package/dist/files-sdk/s3/index.js.map +1 -0
  23. package/dist/gateway/index.d.ts +1 -1
  24. package/dist/gateway/index.d.ts.map +1 -1
  25. package/dist/gateway/index.js.map +1 -1
  26. package/dist/gateway/storage-gateway-fastify-parser.d.ts.map +1 -1
  27. package/dist/gateway/storage-gateway-fastify-parser.js.map +1 -1
  28. package/dist/gateway/storage-gateway.controller.d.ts +12 -11
  29. package/dist/gateway/storage-gateway.controller.d.ts.map +1 -1
  30. package/dist/gateway/storage-gateway.controller.js +209 -65
  31. package/dist/gateway/storage-gateway.controller.js.map +1 -1
  32. package/dist/gateway/storage-gateway.guard.d.ts.map +1 -1
  33. package/dist/gateway/storage-gateway.guard.js.map +1 -1
  34. package/dist/gateway/storage-gateway.module.d.ts.map +1 -1
  35. package/dist/gateway/storage-gateway.module.js +60 -1
  36. package/dist/gateway/storage-gateway.module.js.map +1 -1
  37. package/dist/gateway/storage-gateway.tokens.d.ts +1 -0
  38. package/dist/gateway/storage-gateway.tokens.d.ts.map +1 -1
  39. package/dist/gateway/storage-gateway.tokens.js +1 -0
  40. package/dist/gateway/storage-gateway.tokens.js.map +1 -1
  41. package/dist/gateway/storage-gateway.types.d.ts +53 -10
  42. package/dist/gateway/storage-gateway.types.d.ts.map +1 -1
  43. package/dist/gateway/storage-gateway.types.js.map +1 -1
  44. package/dist/inject-storage.decorator.js.map +1 -1
  45. package/dist/storage-upload-control.d.ts.map +1 -1
  46. package/dist/storage.client.d.ts +8 -1
  47. package/dist/storage.client.d.ts.map +1 -1
  48. package/dist/storage.client.js +40 -0
  49. package/dist/storage.client.js.map +1 -1
  50. package/dist/storage.driver.d.ts +6 -1
  51. package/dist/storage.driver.d.ts.map +1 -1
  52. package/dist/storage.driver.js.map +1 -1
  53. package/dist/storage.error.d.ts +13 -10
  54. package/dist/storage.error.d.ts.map +1 -1
  55. package/dist/storage.error.js +33 -1
  56. package/dist/storage.error.js.map +1 -1
  57. package/dist/storage.module.d.ts.map +1 -1
  58. package/dist/storage.module.js.map +1 -1
  59. package/dist/storage.service.d.ts.map +1 -1
  60. package/dist/storage.service.js.map +1 -1
  61. package/dist/storage.tokens.js.map +1 -1
  62. package/dist/storage.types.d.ts +39 -1
  63. package/dist/storage.types.d.ts.map +1 -1
  64. package/dist/storage.types.js.map +1 -1
  65. package/dist/testing/index.js.map +1 -1
  66. package/package.json +38 -6
package/CHANGELOG.md CHANGED
@@ -1,5 +1,49 @@
1
1
  # @nestm/storage
2
2
 
3
+ ## 0.1.0-alpha.4
4
+
5
+ ### Minor Changes
6
+
7
+ - 79ad3af: Add runtime provider selection and a package-owned filesystem driver.
8
+
9
+ `@nestm/storage/files-sdk/provider` builds a driver from a provider slug carried
10
+ as data — `createProviderStorageDriver({ provider: 's3' | 'gcs' | 'azure' | 'r2'
11
+ | 'fs' | … })` — importing that provider's adapter, and only that one, on
12
+ demand. A deployment now selects its store with an environment variable and
13
+ installs a single native SDK instead of the application hard-coding a driver per
14
+ backend. The same entry point exposes the provider catalog (`listStorageProviders`,
15
+ `getStorageProvider`, `listStorageProviderEnvVars`,
16
+ `listStorageProviderSecretEnvVars`, `isStorageProvider`) as pure data, so config
17
+ validation and health checks can read a provider's env contract without loading
18
+ an adapter. An unknown slug fails closed with `INVALID_ARGUMENT` before anything
19
+ is imported.
20
+
21
+ `@nestm/storage/files-sdk/fs` adds `createFsStorageDriver` for local filesystem
22
+ storage, mirroring the S3 factory. Its adapter reaches only `node:fs`, so it adds
23
+ no native SDK to an install.
24
+
25
+ `@nestm/storage/files-sdk/s3` additionally exports `withS3Capabilities`, which
26
+ applies S3's conditional-copy promotion and signed-policy declarations to an
27
+ adapter built by `s3(...)`. The provider factory uses it so the `s3` slug keeps
28
+ those capabilities without re-deriving `S3AdapterOptions` from flat config.
29
+ `EnhancedS3Adapter` is now `S3StorageAdapter`; the type was not previously
30
+ exported.
31
+
32
+ ## 0.1.0-alpha.3
33
+
34
+ ### Minor Changes
35
+
36
+ - b947634: Harden storage integration boundaries with cross-copy-safe `StorageError`
37
+ detection, a package-owned S3 driver factory, conditional staged-object
38
+ promotion, and a mandatory parsed key policy plus signed-transfer limits for
39
+ the optional HTTP gateway.
40
+
41
+ ### Patch Changes
42
+
43
+ - b947634: Map structurally branded `files-sdk` errors, including errors wrapped across
44
+ duplicate package copies, so missing objects retain the `NOT_FOUND` storage
45
+ error code.
46
+
3
47
  ## 0.1.0-alpha.2
4
48
 
5
49
  ### Minor Changes
package/README.md CHANGED
@@ -25,7 +25,15 @@ consumers do not download NestJS.
25
25
  ## Install
26
26
 
27
27
  ```sh
28
- pnpm add @nestm/storage@alpha files-sdk@2.2.2
28
+ pnpm add @nestm/storage@alpha
29
+ ```
30
+
31
+ The package-owned S3 factory needs no direct `files-sdk` import. Install the
32
+ pinned engine explicitly only when the application imports another adapter
33
+ such as `files-sdk/gcs`:
34
+
35
+ ```sh
36
+ pnpm add files-sdk@2.2.3
29
37
  ```
30
38
 
31
39
  Install only the native SDKs required by the chosen provider. For example:
@@ -82,14 +90,15 @@ runtime or declaration imports. Provider adapters remain available through
82
90
 
83
91
  ## Configure named stores
84
92
 
85
- Create provider adapters with `files-sdk`, wrap them through the explicit
86
- bridge, and register the resulting drivers:
93
+ Use the package-owned S3 factory when applicable. For other providers, create a
94
+ `files-sdk` adapter, wrap it through the explicit bridge, and register the
95
+ resulting driver:
87
96
 
88
97
  ```ts
89
98
  import { Module } from '@nestjs/common';
90
- import { s3 } from 'files-sdk/s3';
91
99
  import { gcs } from 'files-sdk/gcs';
92
100
  import { createFilesSdkDriver } from '@nestm/storage/files-sdk';
101
+ import { createS3StorageDriver } from '@nestm/storage/files-sdk/s3';
93
102
  import { StorageModule } from '@nestm/storage';
94
103
 
95
104
  export const StorageKey = {
@@ -104,11 +113,11 @@ export const StorageKey = {
104
113
  stores: [
105
114
  {
106
115
  name: StorageKey.MEDIA,
107
- driver: createFilesSdkDriver({
108
- adapter: s3({
116
+ driver: createS3StorageDriver({
117
+ adapter: {
109
118
  bucket: 'media',
110
119
  region: 'us-east-1',
111
- }),
120
+ },
112
121
  }),
113
122
  },
114
123
  {
@@ -194,11 +203,11 @@ StorageModule.forRootAsync({
194
203
  name: 'media',
195
204
  inject: [ConfigService],
196
205
  useFactory: (config: ConfigService) =>
197
- createFilesSdkDriver({
198
- adapter: s3({
206
+ createS3StorageDriver({
207
+ adapter: {
199
208
  bucket: config.getOrThrow('MEDIA_BUCKET'),
200
209
  region: config.getOrThrow('AWS_REGION'),
201
- }),
210
+ },
202
211
  }),
203
212
  },
204
213
  ],
@@ -216,11 +225,77 @@ modules retain their own DI scope rather than mutating an application-wide
216
225
  registry. Names are case-sensitive and cannot contain leading or trailing
217
226
  whitespace.
218
227
 
228
+ ### Select the provider at runtime
229
+
230
+ An application that ships to more than one environment usually cannot name its
231
+ provider at build time. `createProviderStorageDriver` takes the slug as data and
232
+ imports that provider's adapter — and only that one — on demand, so a deployment
233
+ picks its store with an environment variable and installs one native SDK:
234
+
235
+ ```ts
236
+ import { createProviderStorageDriver } from '@nestm/storage/files-sdk/provider';
237
+
238
+ StorageModule.forRootAsync({
239
+ imports: [ConfigModule],
240
+ stores: [
241
+ {
242
+ name: 'media',
243
+ inject: [ConfigService],
244
+ useFactory: (config: ConfigService) =>
245
+ createProviderStorageDriver({
246
+ provider: config.getOrThrow('STORAGE_PROVIDER'),
247
+ prefix: config.get('STORAGE_PREFIX'),
248
+ config: {
249
+ bucket: config.get('STORAGE_BUCKET'),
250
+ region: config.get('STORAGE_REGION'),
251
+ root: config.get('STORAGE_ROOT'),
252
+ },
253
+ }),
254
+ },
255
+ ],
256
+ });
257
+ ```
258
+
259
+ `config` is one flat bag of provider settings — `bucket` and `region` for an
260
+ object store, `root` for the filesystem, `accountName` and `container` for
261
+ Azure. Each provider reads what it needs and ignores the rest, so the same shape
262
+ survives a provider change. Credentials may be omitted wherever the provider's
263
+ SDK resolves its own chain (an IAM role, Application Default Credentials, a
264
+ shared profile).
265
+
266
+ An unknown slug fails closed with `INVALID_ARGUMENT` before anything is
267
+ imported. Validate untrusted input up front with `isStorageProvider`, and drive
268
+ config validation from the catalog rather than a hand-kept list:
269
+
270
+ ```ts
271
+ import {
272
+ getStorageProvider,
273
+ isStorageProvider,
274
+ listStorageProviders,
275
+ listStorageProviderSecretEnvVars,
276
+ } from '@nestm/storage/files-sdk/provider';
277
+
278
+ listStorageProviders().map((provider) => provider.slug); // 'akamai', 'alibaba', …
279
+ getStorageProvider('gcs')?.peerDeps; // ['@google-cloud/storage', …]
280
+ listStorageProviderSecretEnvVars('s3').map((variable) => variable.key);
281
+ ```
282
+
283
+ The catalog is pure data and pulls in no adapter, so it is safe in config UIs,
284
+ health checks, and startup validation.
285
+
286
+ The `s3` slug additionally carries the conditional-promotion and signed-policy
287
+ capabilities described under
288
+ [Race-free staged-object promotion](#race-free-staged-object-promotion); every
289
+ other provider exposes exactly what its adapter declares. When the provider _is_
290
+ known at build time, import `@nestm/storage/files-sdk/s3` or
291
+ `@nestm/storage/files-sdk/fs` directly and skip the indirection.
292
+
219
293
  ## Storage API
220
294
 
221
295
  `StorageClient` exposes:
222
296
 
223
297
  - `upload`, `downloadStream`, `head`, `exists`, `delete`, `copy`, and `move`;
298
+ - conditional staged-object `promote` when the driver advertises it;
224
299
  - `list`, cursor-aware `listAll`, and lazy `search`;
225
300
  - `signDownload` and discriminated PUT/POST `signUpload`;
226
301
  - `uploadMany`, `downloadMany`, `headMany`, `existsMany`, and `deleteMany`;
@@ -250,6 +325,37 @@ Node `Readable` uploads are accepted and converted to Web streams without
250
325
  buffering. Provider capability gaps fail closed with `StorageError` rather than
251
326
  silently discarding a range, metadata, or cache-control request.
252
327
 
328
+ ### Race-free staged-object promotion
329
+
330
+ The S3 bridge advertises ETag- and version-conditional server-side copy. This
331
+ lets an application validate a staged object and copy that exact source to its
332
+ final key instead of re-reading whichever bytes occupy the staging key later:
333
+
334
+ ```ts
335
+ import { StorageError, StorageErrorCode } from '@nestm/storage';
336
+
337
+ const staged = await media.head(stagingKey);
338
+ if (staged.etag === undefined) {
339
+ throw new StorageError('Provider did not return a source ETag.', {
340
+ code: StorageErrorCode.NOT_SUPPORTED,
341
+ });
342
+ }
343
+
344
+ // Validate size, declared MIME, and magic bytes before this call.
345
+ await media.file(stagingKey).promoteTo(finalKey, {
346
+ sourceEtag: staged.etag,
347
+ });
348
+
349
+ // Commit ready metadata first. Promotion deliberately retains the staged
350
+ // object so a failed database commit remains recoverable.
351
+ await media.delete(stagingKey);
352
+ ```
353
+
354
+ `sourceVersion` can select an immutable S3 version and may be combined with
355
+ `sourceEtag`. A promotion without either identity is rejected. Drivers that do
356
+ not publish `capabilities.conditionalCopy` fail with `NOT_SUPPORTED` rather
357
+ than falling back to an unsafe ordinary copy.
358
+
253
359
  ### Resumable uploads
254
360
 
255
361
  ```ts
@@ -301,20 +407,42 @@ The gateway lives at `@nestm/storage/gateway` and is never mounted by
301
407
  `StorageModule`.
302
408
 
303
409
  ```ts
304
- import { Module } from '@nestjs/common';
410
+ import { Injectable, Module } from '@nestjs/common';
305
411
  import {
306
412
  StorageGatewayModule,
307
413
  StorageGatewayOperation,
414
+ type StorageGatewayKeyPolicy,
308
415
  } from '@nestm/storage/gateway';
309
416
 
417
+ @Injectable()
418
+ class TenantStorageKeyPolicy implements StorageGatewayKeyPolicy {
419
+ resolve({ input, request, target }) {
420
+ const tenantId = tenantIdFromAuthenticatedRequest(request);
421
+ const root = `tenants/${base64url(tenantId)}`;
422
+ if (target === 'pattern') {
423
+ // Search is already constrained by the separately resolved prefix.
424
+ return input?.value ?? '*';
425
+ }
426
+ return `${root}/${input?.value ?? ''}`;
427
+ }
428
+ }
429
+
430
+ @Module({
431
+ providers: [TenantStorageKeyPolicy],
432
+ exports: [TenantStorageKeyPolicy],
433
+ })
434
+ class StoragePolicyModule {}
435
+
310
436
  @Module({
311
437
  imports: [
312
438
  AppStorageModule,
313
439
  AuthModule,
440
+ StoragePolicyModule,
314
441
  StorageGatewayModule.register({
315
- imports: [AppStorageModule, AuthModule],
442
+ imports: [AppStorageModule, AuthModule, StoragePolicyModule],
316
443
  store: 'media',
317
444
  guards: [JwtAuthGuard],
445
+ keyPolicy: TenantStorageKeyPolicy,
318
446
  mode: 'hybrid',
319
447
  operations: [
320
448
  StorageGatewayOperation.DOWNLOAD,
@@ -325,6 +453,9 @@ import {
325
453
  StorageGatewayOperation.SIGN_UPLOAD,
326
454
  ],
327
455
  maxUploadBytes: 100 * 1024 * 1024,
456
+ maxSignedUploadBytes: 10 * 1024 * 1024,
457
+ signedUploadContentTypes: ['image/jpeg', 'image/png'],
458
+ maxSignedUrlExpiresIn: 900,
328
459
  maxListResults: 1000,
329
460
  maxSearchResults: 1000,
330
461
  proxyInlineContentTypes: ['image/jpeg', 'image/png'],
@@ -338,12 +469,39 @@ Registration fails without at least one existing Nest guard. The only bypass is
338
469
  the explicit `allowUnauthenticated: true` development escape hatch. Operations
339
470
  are deny-by-default and must be allowlisted individually.
340
471
 
472
+ Registration also fails without a `keyPolicy`. Guards answer whether a request
473
+ may reach the gateway; the key policy independently resolves every parsed
474
+ `key`, `prefix`, search `pattern`, `from`, and `to` value to the exact provider
475
+ path. It runs even when a list/search prefix was omitted, so the policy can
476
+ always impose a tenant root. Key-policy providers may be request scoped.
477
+ Returned paths are parsed again and reject absolute paths, backslashes, control
478
+ characters, empty segments, and dot/parent segments.
479
+
480
+ Existing single-tenant applications can temporarily set
481
+ `unsafeAllowUnscopedKeys: true` instead of `keyPolicy`. The name is intentional:
482
+ it preserves caller-controlled provider keys and must not be used on an exposed
483
+ or multi-tenant gateway. It cannot be combined with `keyPolicy`.
484
+
341
485
  Proxy downloads default to `Content-Disposition: attachment` and always send
342
486
  `X-Content-Type-Options: nosniff`. Add only trusted, non-active MIME types to
343
487
  `proxyInlineContentTypes` when browser rendering is required. Search responses
344
488
  are capped by `maxSearchResults`, and list pages by `maxListResults` (both
345
489
  1,000 by default).
346
490
 
491
+ Every signed URL is capped by `maxSignedUrlExpiresIn` (3,600 seconds by
492
+ default). Signed uploads always carry a provider-enforced maximum size, capped
493
+ by `maxSignedUploadBytes`, and require an exact lowercase MIME type from
494
+ `signedUploadContentTypes`. The default direct-upload allowlist contains only
495
+ `application/octet-stream`. Gateway callers may request only the literal
496
+ `attachment` or `inline` response disposition; arbitrary response-header text
497
+ and filenames are rejected. A driver must also advertise
498
+ `signedUploadPolicy.contentType` and `signedUploadPolicy.sizeRange`; otherwise
499
+ the gateway refuses to mint the URL. `createS3StorageDriver()` advertises both
500
+ and uses S3 POST policy conditions. Signed downloads similarly require
501
+ `signedDownloadPolicy.expiresIn`. The S3 factory advertises it only when no
502
+ permanent `publicBaseUrl` was configured, preventing a configured TTL from
503
+ silently returning a non-expiring public link.
504
+
347
505
  The fixed gateway prefix is `/storage`:
348
506
 
349
507
  | Method | Path | Operation |
@@ -394,9 +552,14 @@ try {
394
552
  }
395
553
  ```
396
554
 
555
+ `files-sdk` `NotFound` failures retain `StorageErrorCode.NOT_FOUND`, including
556
+ when a provider adapter and this driver resolve separate copies of `files-sdk`.
557
+ `isStorageError()` likewise recognizes branded and exact legacy structural
558
+ errors produced by a duplicated `@nestm/storage` package copy.
559
+
397
560
  Capability flags cover range reads, native byte-level upload progress,
398
561
  delimiter listing, metadata, cache control, resumable uploads, server-side
399
- copy, and signed transfers.
562
+ copy, conditional promotion, and signed transfers.
400
563
  Provider-specific native clients are intentionally not exposed from the root
401
564
  package.
402
565
 
@@ -412,8 +575,26 @@ StorageModule.forRoot({
412
575
  });
413
576
  ```
414
577
 
415
- For local filesystem storage, import `fs` from `files-sdk/fs` and pass it to
416
- `createFilesSdkDriver` exactly like a cloud adapter.
578
+ For local filesystem storage, use the package-owned factory. The adapter reaches
579
+ only `node:fs`, so it needs no native SDK:
580
+
581
+ ```ts
582
+ import { createFsStorageDriver } from '@nestm/storage/files-sdk/fs';
583
+
584
+ StorageModule.forRoot({
585
+ stores: [
586
+ {
587
+ name: 'artifacts',
588
+ driver: createFsStorageDriver({ adapter: { root: './var/artifacts' } }),
589
+ },
590
+ ],
591
+ });
592
+ ```
593
+
594
+ Bodies are written verbatim at `<root>/<key>`. A `<key>.meta.json` sidecar beside
595
+ each one carries the content type, ETag, and custom metadata a filesystem has
596
+ nowhere else to put; sidecars never surface as keys, and uploading a key ending
597
+ in `.meta.json` fails closed rather than colliding with one.
417
598
 
418
599
  ## License
419
600
 
package/SECURITY.md CHANGED
@@ -23,3 +23,26 @@ cross-store pruning, or dependency compromise are especially useful.
23
23
  For a vulnerability originating in NestJS, `files-sdk`, or a provider SDK,
24
24
  follow that project's security policy as well. You may still report it here
25
25
  privately when this integration needs a mitigation.
26
+
27
+ ## Gateway security boundary
28
+
29
+ Mounting the optional HTTP gateway requires both authentication guards and a
30
+ `StorageGatewayKeyPolicy`. The policy receives parsed paths and must derive the
31
+ provider key space from trusted request context. Do not treat a client prefix
32
+ or object key as a tenant identifier. `unsafeAllowUnscopedKeys` exists only to
33
+ migrate trusted single-tenant deployments and is unsafe on an exposed gateway.
34
+
35
+ Signed URL expiry, signed-upload byte size, and signed-upload MIME are bounded
36
+ by module configuration and cannot be increased by a request. Only `inline`
37
+ and `attachment` content dispositions are accepted. File type still must be
38
+ verified from magic bytes after upload; a signed MIME condition proves only
39
+ what header the uploader supplied. The gateway rejects signed-upload drivers
40
+ that do not advertise provider-enforced content-type and size-range policies.
41
+ It also rejects download adapters that cannot guarantee the requested expiry;
42
+ in particular, the S3 bridge does not treat `publicBaseUrl` links as expiring.
43
+
44
+ For staged uploads on S3, use `promote`/`promoteTo` with the ETag returned by
45
+ the validated `head` or with an immutable provider version. Ordinary `copy`
46
+ does not protect against a staging-key replay between validation and copy.
47
+ Conditional promotion keeps the staging source; delete it only after the
48
+ application's metadata transaction commits.
@@ -1,7 +1,23 @@
1
1
  import { type Adapter, type FilesOptions } from 'files-sdk';
2
+ import { StorageError } from '../storage.error.js';
2
3
  import type { StorageDriver } from '../storage.driver.js';
3
- import type { StorageBody, StorageDownloadOptions, StorageListOptions, StorageListResult, StorageObject, StorageObjectMetadata, StorageOperationOptions, StorageSearchOptions, StorageSignedDownloadOptions, StorageSignedUpload, StorageSignedUploadOptions, StorageUploadOptions, StorageUploadResult } from '../storage.types.js';
4
+ import type { StorageBody, StorageDownloadOptions, StorageListOptions, StorageListResult, StorageObject, StorageObjectMetadata, StorageOperationOptions, StorageConditionalCopyCapability, StoragePromotionOptions, StorageSearchOptions, StorageSignedUploadPolicyCapability, StorageSignedDownloadPolicyCapability, StorageSignedDownloadOptions, StorageSignedUpload, StorageSignedUploadOptions, StorageUploadOptions, StorageUploadResult } from '../storage.types.js';
4
5
  export type FilesSdkDriverOptions<AdapterType extends Adapter> = FilesOptions<AdapterType>;
6
+ /**
7
+ * Optional adapter extension for providers that can conditionally copy an
8
+ * immutable source identity. Plain files-sdk adapters remain fully supported.
9
+ */
10
+ export interface FilesSdkConditionalCopyAdapter {
11
+ readonly conditionalCopy: StorageConditionalCopyCapability;
12
+ promote(sourceKey: string, destinationKey: string, options: StoragePromotionOptions): Promise<void>;
13
+ }
14
+ export interface FilesSdkSignedUploadPolicyAdapter {
15
+ readonly signedUploadPolicy: StorageSignedUploadPolicyCapability;
16
+ }
17
+ export interface FilesSdkSignedDownloadPolicyAdapter {
18
+ readonly signedDownloadPolicy: StorageSignedDownloadPolicyCapability;
19
+ }
20
+ export declare function mapFilesSdkError(error: unknown): StorageError;
5
21
  export declare class FilesSdkStorageDriver<AdapterType extends Adapter = Adapter> implements StorageDriver {
6
22
  #private;
7
23
  constructor(options: FilesSdkDriverOptions<AdapterType>);
@@ -13,11 +29,23 @@ export declare class FilesSdkStorageDriver<AdapterType extends Adapter = Adapter
13
29
  rangeRead: boolean;
14
30
  resumableUpload: boolean;
15
31
  serverSideCopy: boolean;
32
+ conditionalCopy?: {
33
+ supported: boolean;
34
+ etag: boolean;
35
+ version: boolean;
36
+ };
16
37
  signedDownload: {
17
38
  supported: boolean;
18
39
  maxExpiresIn?: number;
19
40
  };
20
- signedUpload: "runtime";
41
+ signedDownloadPolicy?: {
42
+ expiresIn: boolean;
43
+ };
44
+ signedUpload: 'runtime';
45
+ signedUploadPolicy?: {
46
+ contentType: boolean;
47
+ sizeRange: boolean;
48
+ };
21
49
  nativeUploadProgress: boolean;
22
50
  };
23
51
  upload(key: string, body: StorageBody, options?: StorageUploadOptions): Promise<StorageUploadResult>;
@@ -27,6 +55,7 @@ export declare class FilesSdkStorageDriver<AdapterType extends Adapter = Adapter
27
55
  delete(key: string, options?: StorageOperationOptions): Promise<void>;
28
56
  copy(sourceKey: string, destinationKey: string, options?: StorageOperationOptions): Promise<void>;
29
57
  move(sourceKey: string, destinationKey: string, options?: StorageOperationOptions): Promise<void>;
58
+ promote(sourceKey: string, destinationKey: string, options: StoragePromotionOptions): Promise<void>;
30
59
  list(options?: StorageListOptions): Promise<StorageListResult>;
31
60
  search(pattern: string | RegExp, options?: StorageSearchOptions): AsyncIterable<StorageObjectMetadata>;
32
61
  signDownload(key: string, options?: StorageSignedDownloadOptions): Promise<string>;
@@ -1 +1 @@
1
- {"version":3,"file":"files-sdk.driver.d.ts","sourceRoot":"","sources":["../../src/files-sdk/files-sdk.driver.ts"],"names":[],"mappings":"AAEA,OAAO,EAGL,KAAK,OAAO,EAGZ,KAAK,YAAY,EAUlB,MAAM,WAAW,CAAC;AAGnB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,KAAK,EACV,WAAW,EACX,sBAAsB,EACtB,kBAAkB,EAClB,iBAAiB,EACjB,aAAa,EACb,qBAAqB,EACrB,uBAAuB,EAEvB,oBAAoB,EACpB,4BAA4B,EAC5B,mBAAmB,EACnB,0BAA0B,EAC1B,oBAAoB,EACpB,mBAAmB,EACpB,MAAM,qBAAqB,CAAC;AAG7B,MAAM,MAAM,qBAAqB,CAAC,WAAW,SAAS,OAAO,IAC3D,YAAY,CAAC,WAAW,CAAC,CAAC;AAyS5B,qBAAa,qBAAqB,CAChC,WAAW,SAAS,OAAO,GAAG,OAAO,CACrC,YAAW,aAAa;;gBAIZ,OAAO,EAAE,qBAAqB,CAAC,WAAW,CAAC;IAKvD,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,IAAI,YAAY;;;;;;;;;;;;;MAaf;IAEK,MAAM,CACV,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,WAAW,EACjB,OAAO,CAAC,EAAE,oBAAoB,GAC7B,OAAO,CAAC,mBAAmB,CAAC;IAQzB,QAAQ,CACZ,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE,sBAAsB,GAC/B,OAAO,CAAC,aAAa,CAAC;IAUnB,IAAI,CACR,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE,uBAAuB,GAChC,OAAO,CAAC,qBAAqB,CAAC;IAMjC,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,uBAAuB,GAAG,OAAO,CAAC,OAAO,CAAC;IAIxE,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,uBAAuB,GAAG,OAAO,CAAC,IAAI,CAAC;IAMrE,IAAI,CACF,SAAS,EAAE,MAAM,EACjB,cAAc,EAAE,MAAM,EACtB,OAAO,CAAC,EAAE,uBAAuB,GAChC,OAAO,CAAC,IAAI,CAAC;IAMhB,IAAI,CACF,SAAS,EAAE,MAAM,EACjB,cAAc,EAAE,MAAM,EACtB,OAAO,CAAC,EAAE,uBAAuB,GAChC,OAAO,CAAC,IAAI,CAAC;IAMV,IAAI,CAAC,OAAO,CAAC,EAAE,kBAAkB,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAapE,MAAM,CACJ,OAAO,EAAE,MAAM,GAAG,MAAM,EACxB,OAAO,CAAC,EAAE,oBAAoB,GAC7B,aAAa,CAAC,qBAAqB,CAAC;IAoBvC,YAAY,CACV,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE,4BAA4B,GACrC,OAAO,CAAC,MAAM,CAAC;IAMlB,UAAU,CACR,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,0BAA0B,GAClC,OAAO,CAAC,mBAAmB,CAAC;CAahC;AAED,wBAAgB,oBAAoB,CAAC,WAAW,SAAS,OAAO,EAC9D,OAAO,EAAE,qBAAqB,CAAC,WAAW,CAAC,GAC1C,qBAAqB,CAAC,WAAW,CAAC,CAEpC"}
1
+ {"version":3,"file":"files-sdk.driver.d.ts","sourceRoot":"","sources":["../../src/files-sdk/files-sdk.driver.ts"],"names":[],"mappings":"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"}