@nestm/storage 0.1.0-alpha.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.
Files changed (94) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/CONTRIBUTING.md +83 -0
  3. package/LICENSE +21 -0
  4. package/README.md +386 -0
  5. package/SECURITY.md +25 -0
  6. package/dist/files-sdk/files-sdk.driver.d.ts +36 -0
  7. package/dist/files-sdk/files-sdk.driver.d.ts.map +1 -0
  8. package/dist/files-sdk/files-sdk.driver.js +352 -0
  9. package/dist/files-sdk/files-sdk.driver.js.map +1 -0
  10. package/dist/files-sdk/index.d.ts +3 -0
  11. package/dist/files-sdk/index.d.ts.map +1 -0
  12. package/dist/files-sdk/index.js +2 -0
  13. package/dist/files-sdk/index.js.map +1 -0
  14. package/dist/gateway/index.d.ts +3 -0
  15. package/dist/gateway/index.d.ts.map +1 -0
  16. package/dist/gateway/index.js +3 -0
  17. package/dist/gateway/index.js.map +1 -0
  18. package/dist/gateway/storage-gateway-fastify-parser.d.ts +9 -0
  19. package/dist/gateway/storage-gateway-fastify-parser.d.ts.map +1 -0
  20. package/dist/gateway/storage-gateway-fastify-parser.js +50 -0
  21. package/dist/gateway/storage-gateway-fastify-parser.js.map +1 -0
  22. package/dist/gateway/storage-gateway.controller.d.ts +31 -0
  23. package/dist/gateway/storage-gateway.controller.d.ts.map +1 -0
  24. package/dist/gateway/storage-gateway.controller.js +601 -0
  25. package/dist/gateway/storage-gateway.controller.js.map +1 -0
  26. package/dist/gateway/storage-gateway.guard.d.ts +7 -0
  27. package/dist/gateway/storage-gateway.guard.d.ts.map +1 -0
  28. package/dist/gateway/storage-gateway.guard.js +40 -0
  29. package/dist/gateway/storage-gateway.guard.js.map +1 -0
  30. package/dist/gateway/storage-gateway.module.d.ts +6 -0
  31. package/dist/gateway/storage-gateway.module.d.ts.map +1 -0
  32. package/dist/gateway/storage-gateway.module.js +98 -0
  33. package/dist/gateway/storage-gateway.module.js.map +1 -0
  34. package/dist/gateway/storage-gateway.tokens.d.ts +3 -0
  35. package/dist/gateway/storage-gateway.tokens.d.ts.map +1 -0
  36. package/dist/gateway/storage-gateway.tokens.js +3 -0
  37. package/dist/gateway/storage-gateway.tokens.js.map +1 -0
  38. package/dist/gateway/storage-gateway.types.d.ts +65 -0
  39. package/dist/gateway/storage-gateway.types.d.ts.map +1 -0
  40. package/dist/gateway/storage-gateway.types.js +13 -0
  41. package/dist/gateway/storage-gateway.types.js.map +1 -0
  42. package/dist/index.d.ts +11 -0
  43. package/dist/index.d.ts.map +1 -0
  44. package/dist/index.js +8 -0
  45. package/dist/index.js.map +1 -0
  46. package/dist/inject-storage.decorator.d.ts +2 -0
  47. package/dist/inject-storage.decorator.d.ts.map +1 -0
  48. package/dist/inject-storage.decorator.js +6 -0
  49. package/dist/inject-storage.decorator.js.map +1 -0
  50. package/dist/internal/settle-many.d.ts +7 -0
  51. package/dist/internal/settle-many.d.ts.map +1 -0
  52. package/dist/internal/settle-many.js +62 -0
  53. package/dist/internal/settle-many.js.map +1 -0
  54. package/dist/storage-module.options.d.ts +62 -0
  55. package/dist/storage-module.options.d.ts.map +1 -0
  56. package/dist/storage-module.options.js +2 -0
  57. package/dist/storage-module.options.js.map +1 -0
  58. package/dist/storage-upload-control.d.ts +22 -0
  59. package/dist/storage-upload-control.d.ts.map +1 -0
  60. package/dist/storage-upload-control.js +139 -0
  61. package/dist/storage-upload-control.js.map +1 -0
  62. package/dist/storage.client.d.ts +51 -0
  63. package/dist/storage.client.d.ts.map +1 -0
  64. package/dist/storage.client.js +395 -0
  65. package/dist/storage.client.js.map +1 -0
  66. package/dist/storage.driver.d.ts +18 -0
  67. package/dist/storage.driver.d.ts.map +1 -0
  68. package/dist/storage.driver.js +2 -0
  69. package/dist/storage.driver.js.map +1 -0
  70. package/dist/storage.error.d.ts +39 -0
  71. package/dist/storage.error.d.ts.map +1 -0
  72. package/dist/storage.error.js +49 -0
  73. package/dist/storage.error.js.map +1 -0
  74. package/dist/storage.module.d.ts +11 -0
  75. package/dist/storage.module.d.ts.map +1 -0
  76. package/dist/storage.module.js +170 -0
  77. package/dist/storage.module.js.map +1 -0
  78. package/dist/storage.service.d.ts +12 -0
  79. package/dist/storage.service.d.ts.map +1 -0
  80. package/dist/storage.service.js +246 -0
  81. package/dist/storage.service.js.map +1 -0
  82. package/dist/storage.tokens.d.ts +6 -0
  83. package/dist/storage.tokens.d.ts.map +1 -0
  84. package/dist/storage.tokens.js +13 -0
  85. package/dist/storage.tokens.js.map +1 -0
  86. package/dist/storage.types.d.ts +244 -0
  87. package/dist/storage.types.d.ts.map +1 -0
  88. package/dist/storage.types.js +2 -0
  89. package/dist/storage.types.js.map +1 -0
  90. package/dist/testing/index.d.ts +9 -0
  91. package/dist/testing/index.d.ts.map +1 -0
  92. package/dist/testing/index.js +10 -0
  93. package/dist/testing/index.js.map +1 -0
  94. package/package.json +112 -0
@@ -0,0 +1,246 @@
1
+ import { settleMany } from './internal/settle-many.js';
2
+ import { StorageClient } from './storage.client.js';
3
+ import { StorageError, StorageErrorCode } from './storage.error.js';
4
+ import { normalizeStorageName } from './storage.tokens.js';
5
+ const identity = (key) => key;
6
+ function assertDifferentStores(from, to) {
7
+ if (from === to) {
8
+ throw new StorageError('Cross-store transfer and sync require different source and destination stores.', {
9
+ code: StorageErrorCode.INVALID_ARGUMENT,
10
+ permanent: true,
11
+ store: from,
12
+ });
13
+ }
14
+ }
15
+ function unchanged(source, destination, compare) {
16
+ if (typeof compare === 'function') {
17
+ return compare(source, destination);
18
+ }
19
+ if (compare === 'size') {
20
+ return source.size === destination.size;
21
+ }
22
+ return (source.size === destination.size &&
23
+ source.etag !== undefined &&
24
+ destination.etag !== undefined &&
25
+ source.etag === destination.etag);
26
+ }
27
+ async function walk(client, options) {
28
+ const objects = [];
29
+ for await (const object of client.listAll({
30
+ ...(options.limit !== undefined && { limit: options.limit }),
31
+ ...(options.prefix !== undefined && { prefix: options.prefix }),
32
+ ...(options.signal !== undefined && { signal: options.signal }),
33
+ })) {
34
+ objects.push(object);
35
+ }
36
+ return objects;
37
+ }
38
+ export class StorageService {
39
+ defaultName;
40
+ #clients;
41
+ constructor(clients, defaultName) {
42
+ this.defaultName = defaultName;
43
+ this.#clients = new Map(clients);
44
+ }
45
+ get names() {
46
+ return [...this.#clients.keys()].sort();
47
+ }
48
+ use(name) {
49
+ const resolved = name === undefined ? this.defaultName : normalizeStorageName(name);
50
+ if (resolved === null) {
51
+ throw new StorageError('No default storage store is configured; call storage.use(name).', {
52
+ code: StorageErrorCode.INVALID_ARGUMENT,
53
+ permanent: true,
54
+ });
55
+ }
56
+ const client = this.#clients.get(resolved);
57
+ if (client === undefined) {
58
+ const available = this.names;
59
+ throw new StorageError(available.length === 0
60
+ ? `Storage store "${resolved}" is not registered.`
61
+ : `Storage store "${resolved}" is not registered. Available stores: ${available.join(', ')}.`, {
62
+ code: StorageErrorCode.INVALID_ARGUMENT,
63
+ permanent: true,
64
+ store: resolved,
65
+ });
66
+ }
67
+ return client;
68
+ }
69
+ async transfer(options) {
70
+ const fromName = normalizeStorageName(options.from);
71
+ const toName = normalizeStorageName(options.to);
72
+ assertDifferentStores(fromName, toName);
73
+ const source = this.use(fromName);
74
+ const destination = this.use(toName);
75
+ const transformKey = options.transformKey ?? identity;
76
+ const overwrite = options.overwrite ?? true;
77
+ const objects = await walk(source, options);
78
+ const total = objects.length;
79
+ let done = 0;
80
+ const skipped = new Set();
81
+ const report = (key, status) => {
82
+ done += 1;
83
+ options.onProgress?.({ done, key, status, total });
84
+ };
85
+ const settled = await settleMany(objects, (object) => object.key, async (object) => {
86
+ const destinationKey = transformKey(object.key);
87
+ if (!overwrite &&
88
+ (await destination.exists(destinationKey, {
89
+ ...(options.signal !== undefined && {
90
+ signal: options.signal,
91
+ }),
92
+ }))) {
93
+ skipped.add(object.key);
94
+ report(object.key, 'skipped');
95
+ return object.key;
96
+ }
97
+ const downloaded = await source.downloadStream(object.key, {
98
+ ...(options.signal !== undefined && {
99
+ signal: options.signal,
100
+ }),
101
+ });
102
+ try {
103
+ await destination.upload(destinationKey, downloaded.body, {
104
+ contentType: downloaded.contentType,
105
+ ...(downloaded.metadata !== undefined && {
106
+ metadata: downloaded.metadata,
107
+ }),
108
+ ...(options.signal !== undefined && {
109
+ signal: options.signal,
110
+ }),
111
+ });
112
+ }
113
+ catch (error) {
114
+ if (!downloaded.body.locked) {
115
+ await downloaded.body.cancel().catch(() => undefined);
116
+ }
117
+ throw error;
118
+ }
119
+ report(object.key, 'transferred');
120
+ return object.key;
121
+ }, options);
122
+ const transferred = [];
123
+ const skippedKeys = [];
124
+ for (const key of settled.results) {
125
+ (skipped.has(key) ? skippedKeys : transferred).push(key);
126
+ }
127
+ return {
128
+ transferred,
129
+ ...(skippedKeys.length > 0 && { skipped: skippedKeys }),
130
+ ...(settled.errors.length > 0 && { errors: settled.errors }),
131
+ };
132
+ }
133
+ async sync(options) {
134
+ const fromName = normalizeStorageName(options.from);
135
+ const toName = normalizeStorageName(options.to);
136
+ assertDifferentStores(fromName, toName);
137
+ const source = this.use(fromName);
138
+ const destination = this.use(toName);
139
+ const transformKey = options.transformKey ?? identity;
140
+ const compare = options.compare ?? 'etag';
141
+ const sourceObjects = await walk(source, options);
142
+ const destinationObjects = await walk(destination, {
143
+ ...(options.destinationPrefix !== undefined
144
+ ? { prefix: options.destinationPrefix }
145
+ : options.prefix !== undefined
146
+ ? { prefix: options.prefix }
147
+ : {}),
148
+ ...(options.limit !== undefined && { limit: options.limit }),
149
+ ...(options.signal !== undefined && { signal: options.signal }),
150
+ });
151
+ const destinationIndex = new Map(destinationObjects.map((object) => [object.key, object]));
152
+ const desiredDestinationKeys = new Set(sourceObjects.map((object) => transformKey(object.key)));
153
+ const deleteKeys = (options.prune ?? false)
154
+ ? destinationObjects
155
+ .map((object) => object.key)
156
+ .filter((key) => !desiredDestinationKeys.has(key))
157
+ : [];
158
+ const plannedUploads = [];
159
+ const plannedSkips = [];
160
+ for (const object of sourceObjects) {
161
+ const existing = destinationIndex.get(transformKey(object.key));
162
+ (existing && unchanged(object, existing, compare)
163
+ ? plannedSkips
164
+ : plannedUploads).push(object.key);
165
+ }
166
+ if (options.dryRun) {
167
+ return {
168
+ uploaded: plannedUploads,
169
+ skipped: plannedSkips,
170
+ ...(options.prune && { deleted: deleteKeys }),
171
+ };
172
+ }
173
+ const total = sourceObjects.length + (options.prune ? deleteKeys.length : 0);
174
+ let done = 0;
175
+ const report = (key, status) => {
176
+ done += 1;
177
+ options.onProgress?.({ done, key, status, total });
178
+ };
179
+ const skipped = new Set();
180
+ const settled = await settleMany(sourceObjects, (object) => object.key, async (object) => {
181
+ const destinationKey = transformKey(object.key);
182
+ const existing = destinationIndex.get(destinationKey);
183
+ if (existing && unchanged(object, existing, compare)) {
184
+ skipped.add(object.key);
185
+ report(object.key, 'skipped');
186
+ return object.key;
187
+ }
188
+ const downloaded = await source.downloadStream(object.key, {
189
+ ...(options.signal !== undefined && {
190
+ signal: options.signal,
191
+ }),
192
+ });
193
+ try {
194
+ await destination.upload(destinationKey, downloaded.body, {
195
+ contentType: downloaded.contentType,
196
+ ...(downloaded.metadata !== undefined && {
197
+ metadata: downloaded.metadata,
198
+ }),
199
+ ...(options.signal !== undefined && {
200
+ signal: options.signal,
201
+ }),
202
+ });
203
+ }
204
+ catch (error) {
205
+ if (!downloaded.body.locked) {
206
+ await downloaded.body.cancel().catch(() => undefined);
207
+ }
208
+ throw error;
209
+ }
210
+ report(object.key, 'uploaded');
211
+ return object.key;
212
+ }, options);
213
+ const uploaded = [];
214
+ const skippedKeys = [];
215
+ for (const key of settled.results) {
216
+ (skipped.has(key) ? skippedKeys : uploaded).push(key);
217
+ }
218
+ let deleted;
219
+ let deleteErrors = [];
220
+ const canPrune = options.prune && !(options.stopOnError && settled.errors.length > 0);
221
+ if (canPrune) {
222
+ const deleteResult = await destination.deleteMany(deleteKeys, {
223
+ ...(options.concurrency !== undefined && {
224
+ concurrency: options.concurrency,
225
+ }),
226
+ ...(options.signal !== undefined && { signal: options.signal }),
227
+ ...(options.stopOnError !== undefined && {
228
+ stopOnError: options.stopOnError,
229
+ }),
230
+ });
231
+ deleted = deleteResult.deleted;
232
+ deleteErrors = deleteResult.errors ?? [];
233
+ for (const key of deleted) {
234
+ report(key, 'deleted');
235
+ }
236
+ }
237
+ const errors = [...settled.errors, ...deleteErrors];
238
+ return {
239
+ uploaded,
240
+ skipped: skippedKeys,
241
+ ...(options.prune && { deleted: deleted ?? [] }),
242
+ ...(errors.length > 0 && { errors }),
243
+ };
244
+ }
245
+ }
246
+ //# sourceMappingURL=storage.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage.service.js","sourceRoot":"","sources":["../src/storage.service.ts"],"names":[],"mappings":"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","sourcesContent":["import { settleMany } from './internal/settle-many.js';\nimport { StorageClient } from './storage.client.js';\nimport { StorageError, StorageErrorCode } from './storage.error.js';\nimport { normalizeStorageName } from './storage.tokens.js';\nimport type {\n StorageBulkError,\n StorageObjectMetadata,\n StorageSyncCompare,\n StorageSyncOptions,\n StorageSyncProgress,\n StorageSyncResult,\n StorageTransferOptions,\n StorageTransferProgress,\n StorageTransferResult,\n} from './storage.types.js';\n\nconst identity = (key: string): string => key;\n\nfunction assertDifferentStores(from: string, to: string): void {\n if (from === to) {\n throw new StorageError(\n 'Cross-store transfer and sync require different source and destination stores.',\n {\n code: StorageErrorCode.INVALID_ARGUMENT,\n permanent: true,\n store: from,\n },\n );\n }\n}\n\nfunction unchanged(\n source: StorageObjectMetadata,\n destination: StorageObjectMetadata,\n compare: StorageSyncCompare,\n): boolean {\n if (typeof compare === 'function') {\n return compare(source, destination);\n }\n if (compare === 'size') {\n return source.size === destination.size;\n }\n return (\n source.size === destination.size &&\n source.etag !== undefined &&\n destination.etag !== undefined &&\n source.etag === destination.etag\n );\n}\n\nasync function walk(\n client: StorageClient,\n options: {\n prefix?: string;\n limit?: number;\n signal?: AbortSignal;\n },\n): Promise<StorageObjectMetadata[]> {\n const objects: StorageObjectMetadata[] = [];\n for await (const object of client.listAll({\n ...(options.limit !== undefined && { limit: options.limit }),\n ...(options.prefix !== undefined && { prefix: options.prefix }),\n ...(options.signal !== undefined && { signal: options.signal }),\n })) {\n objects.push(object);\n }\n return objects;\n}\n\nexport class StorageService {\n readonly #clients: ReadonlyMap<string, StorageClient>;\n\n constructor(\n clients: ReadonlyMap<string, StorageClient>,\n private readonly defaultName: string | null,\n ) {\n this.#clients = new Map(clients);\n }\n\n get names(): readonly string[] {\n return [...this.#clients.keys()].sort();\n }\n\n use(name?: string): StorageClient {\n const resolved =\n name === undefined ? this.defaultName : normalizeStorageName(name);\n\n if (resolved === null) {\n throw new StorageError(\n 'No default storage store is configured; call storage.use(name).',\n {\n code: StorageErrorCode.INVALID_ARGUMENT,\n permanent: true,\n },\n );\n }\n\n const client = this.#clients.get(resolved);\n if (client === undefined) {\n const available = this.names;\n throw new StorageError(\n available.length === 0\n ? `Storage store \"${resolved}\" is not registered.`\n : `Storage store \"${resolved}\" is not registered. Available stores: ${available.join(', ')}.`,\n {\n code: StorageErrorCode.INVALID_ARGUMENT,\n permanent: true,\n store: resolved,\n },\n );\n }\n return client;\n }\n\n async transfer(\n options: StorageTransferOptions,\n ): Promise<StorageTransferResult> {\n const fromName = normalizeStorageName(options.from);\n const toName = normalizeStorageName(options.to);\n assertDifferentStores(fromName, toName);\n const source = this.use(fromName);\n const destination = this.use(toName);\n const transformKey = options.transformKey ?? identity;\n const overwrite = options.overwrite ?? true;\n const objects = await walk(source, options);\n const total = objects.length;\n let done = 0;\n const skipped = new Set<string>();\n\n const report = (\n key: string,\n status: StorageTransferProgress['status'],\n ): void => {\n done += 1;\n options.onProgress?.({ done, key, status, total });\n };\n\n const settled = await settleMany(\n objects,\n (object) => object.key,\n async (object) => {\n const destinationKey = transformKey(object.key);\n if (\n !overwrite &&\n (await destination.exists(destinationKey, {\n ...(options.signal !== undefined && {\n signal: options.signal,\n }),\n }))\n ) {\n skipped.add(object.key);\n report(object.key, 'skipped');\n return object.key;\n }\n\n const downloaded = await source.downloadStream(object.key, {\n ...(options.signal !== undefined && {\n signal: options.signal,\n }),\n });\n try {\n await destination.upload(destinationKey, downloaded.body, {\n contentType: downloaded.contentType,\n ...(downloaded.metadata !== undefined && {\n metadata: downloaded.metadata,\n }),\n ...(options.signal !== undefined && {\n signal: options.signal,\n }),\n });\n } catch (error) {\n if (!downloaded.body.locked) {\n await downloaded.body.cancel().catch(() => undefined);\n }\n throw error;\n }\n report(object.key, 'transferred');\n return object.key;\n },\n options,\n );\n\n const transferred: string[] = [];\n const skippedKeys: string[] = [];\n for (const key of settled.results) {\n (skipped.has(key) ? skippedKeys : transferred).push(key);\n }\n\n return {\n transferred,\n ...(skippedKeys.length > 0 && { skipped: skippedKeys }),\n ...(settled.errors.length > 0 && { errors: settled.errors }),\n };\n }\n\n async sync(options: StorageSyncOptions): Promise<StorageSyncResult> {\n const fromName = normalizeStorageName(options.from);\n const toName = normalizeStorageName(options.to);\n assertDifferentStores(fromName, toName);\n const source = this.use(fromName);\n const destination = this.use(toName);\n const transformKey = options.transformKey ?? identity;\n const compare = options.compare ?? 'etag';\n const sourceObjects = await walk(source, options);\n const destinationObjects = await walk(destination, {\n ...(options.destinationPrefix !== undefined\n ? { prefix: options.destinationPrefix }\n : options.prefix !== undefined\n ? { prefix: options.prefix }\n : {}),\n ...(options.limit !== undefined && { limit: options.limit }),\n ...(options.signal !== undefined && { signal: options.signal }),\n });\n const destinationIndex = new Map(\n destinationObjects.map((object) => [object.key, object]),\n );\n const desiredDestinationKeys = new Set(\n sourceObjects.map((object) => transformKey(object.key)),\n );\n const deleteKeys =\n (options.prune ?? false)\n ? destinationObjects\n .map((object) => object.key)\n .filter((key) => !desiredDestinationKeys.has(key))\n : [];\n\n const plannedUploads: string[] = [];\n const plannedSkips: string[] = [];\n for (const object of sourceObjects) {\n const existing = destinationIndex.get(transformKey(object.key));\n (existing && unchanged(object, existing, compare)\n ? plannedSkips\n : plannedUploads\n ).push(object.key);\n }\n\n if (options.dryRun) {\n return {\n uploaded: plannedUploads,\n skipped: plannedSkips,\n ...(options.prune && { deleted: deleteKeys }),\n };\n }\n\n const total =\n sourceObjects.length + (options.prune ? deleteKeys.length : 0);\n let done = 0;\n const report = (\n key: string,\n status: StorageSyncProgress['status'],\n ): void => {\n done += 1;\n options.onProgress?.({ done, key, status, total });\n };\n const skipped = new Set<string>();\n\n const settled = await settleMany(\n sourceObjects,\n (object) => object.key,\n async (object) => {\n const destinationKey = transformKey(object.key);\n const existing = destinationIndex.get(destinationKey);\n if (existing && unchanged(object, existing, compare)) {\n skipped.add(object.key);\n report(object.key, 'skipped');\n return object.key;\n }\n const downloaded = await source.downloadStream(object.key, {\n ...(options.signal !== undefined && {\n signal: options.signal,\n }),\n });\n try {\n await destination.upload(destinationKey, downloaded.body, {\n contentType: downloaded.contentType,\n ...(downloaded.metadata !== undefined && {\n metadata: downloaded.metadata,\n }),\n ...(options.signal !== undefined && {\n signal: options.signal,\n }),\n });\n } catch (error) {\n if (!downloaded.body.locked) {\n await downloaded.body.cancel().catch(() => undefined);\n }\n throw error;\n }\n report(object.key, 'uploaded');\n return object.key;\n },\n options,\n );\n\n const uploaded: string[] = [];\n const skippedKeys: string[] = [];\n for (const key of settled.results) {\n (skipped.has(key) ? skippedKeys : uploaded).push(key);\n }\n\n let deleted: string[] | undefined;\n let deleteErrors: StorageBulkError[] = [];\n const canPrune =\n options.prune && !(options.stopOnError && settled.errors.length > 0);\n if (canPrune) {\n const deleteResult = await destination.deleteMany(deleteKeys, {\n ...(options.concurrency !== undefined && {\n concurrency: options.concurrency,\n }),\n ...(options.signal !== undefined && { signal: options.signal }),\n ...(options.stopOnError !== undefined && {\n stopOnError: options.stopOnError,\n }),\n });\n deleted = deleteResult.deleted;\n deleteErrors = deleteResult.errors ?? [];\n for (const key of deleted) {\n report(key, 'deleted');\n }\n }\n\n const errors = [...settled.errors, ...deleteErrors];\n return {\n uploaded,\n skipped: skippedKeys,\n ...(options.prune && { deleted: deleted ?? [] }),\n ...(errors.length > 0 && { errors }),\n };\n }\n}\n"]}
@@ -0,0 +1,6 @@
1
+ export declare const DEFAULT_STORAGE_NAME = "default";
2
+ export declare const STORAGE_DEFAULT_NAME: unique symbol;
3
+ export declare function normalizeStorageName(name?: string): string;
4
+ export declare function getStorageToken(name?: string): symbol;
5
+ export declare const STORAGE: symbol;
6
+ //# sourceMappingURL=storage.tokens.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage.tokens.d.ts","sourceRoot":"","sources":["../src/storage.tokens.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,oBAAoB,YAAY,CAAC;AAE9C,eAAO,MAAM,oBAAoB,eAA4C,CAAC;AAE9E,wBAAgB,oBAAoB,CAClC,IAAI,GAAE,MAA6B,GAClC,MAAM,CAOR;AAED,wBAAgB,eAAe,CAAC,IAAI,GAAE,MAA6B,GAAG,MAAM,CAE3E;AAED,eAAO,MAAM,OAAO,QAAoB,CAAC"}
@@ -0,0 +1,13 @@
1
+ export const DEFAULT_STORAGE_NAME = 'default';
2
+ export const STORAGE_DEFAULT_NAME = Symbol.for('@nestm/storage/default-name');
3
+ export function normalizeStorageName(name = DEFAULT_STORAGE_NAME) {
4
+ if (typeof name !== 'string' || name.length === 0 || name.trim() !== name) {
5
+ throw new TypeError('Storage store names must be non-empty strings without leading or trailing whitespace.');
6
+ }
7
+ return name;
8
+ }
9
+ export function getStorageToken(name = DEFAULT_STORAGE_NAME) {
10
+ return Symbol.for(`@nestm/storage/store/${normalizeStorageName(name)}`);
11
+ }
12
+ export const STORAGE = getStorageToken();
13
+ //# sourceMappingURL=storage.tokens.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage.tokens.js","sourceRoot":"","sources":["../src/storage.tokens.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,oBAAoB,GAAG,SAAS,CAAC;AAE9C,MAAM,CAAC,MAAM,oBAAoB,GAAG,MAAM,CAAC,GAAG,CAAC,6BAA6B,CAAC,CAAC;AAE9E,MAAM,UAAU,oBAAoB,CAClC,OAAe,oBAAoB;IAEnC,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,IAAI,IAAI,CAAC,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC;QAC1E,MAAM,IAAI,SAAS,CACjB,uFAAuF,CACxF,CAAC;IACJ,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,OAAe,oBAAoB;IACjE,OAAO,MAAM,CAAC,GAAG,CAAC,wBAAwB,oBAAoB,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AAC1E,CAAC;AAED,MAAM,CAAC,MAAM,OAAO,GAAG,eAAe,EAAE,CAAC","sourcesContent":["export const DEFAULT_STORAGE_NAME = 'default';\n\nexport const STORAGE_DEFAULT_NAME = Symbol.for('@nestm/storage/default-name');\n\nexport function normalizeStorageName(\n name: string = DEFAULT_STORAGE_NAME,\n): string {\n if (typeof name !== 'string' || name.length === 0 || name.trim() !== name) {\n throw new TypeError(\n 'Storage store names must be non-empty strings without leading or trailing whitespace.',\n );\n }\n return name;\n}\n\nexport function getStorageToken(name: string = DEFAULT_STORAGE_NAME): symbol {\n return Symbol.for(`@nestm/storage/store/${normalizeStorageName(name)}`);\n}\n\nexport const STORAGE = getStorageToken();\n"]}
@@ -0,0 +1,244 @@
1
+ import type { Readable } from 'node:stream';
2
+ import type { StorageError } from './storage.error.js';
3
+ import type { StorageUploadControl } from './storage-upload-control.js';
4
+ export type StorageBody = Blob | File | ReadableStream<Uint8Array> | Readable | ArrayBuffer | ArrayBufferView | Uint8Array | string;
5
+ export interface StorageRetryContext {
6
+ attempt: number;
7
+ error: StorageError;
8
+ }
9
+ export type StorageRetryOptions = number | {
10
+ max: number;
11
+ backoff?: (context: StorageRetryContext) => number;
12
+ };
13
+ export interface StorageOperationOptions {
14
+ signal?: AbortSignal;
15
+ timeout?: number;
16
+ retries?: StorageRetryOptions;
17
+ }
18
+ export interface StorageMultipartOptions {
19
+ partSize?: number;
20
+ concurrency?: number;
21
+ }
22
+ export interface StorageUploadProgress {
23
+ loaded: number;
24
+ total?: number;
25
+ }
26
+ export interface StorageUploadOptions extends StorageOperationOptions {
27
+ contentType?: string;
28
+ cacheControl?: string;
29
+ metadata?: Record<string, string>;
30
+ onProgress?: (progress: StorageUploadProgress) => void;
31
+ multipart?: boolean | StorageMultipartOptions;
32
+ control?: StorageUploadControl;
33
+ }
34
+ export interface StorageUploadResult {
35
+ key: string;
36
+ size: number;
37
+ contentType: string;
38
+ etag?: string;
39
+ lastModified?: Date;
40
+ }
41
+ export interface StorageObjectMetadata {
42
+ key: string;
43
+ name: string;
44
+ size: number;
45
+ contentType: string;
46
+ etag?: string;
47
+ lastModified?: Date;
48
+ metadata?: Record<string, string>;
49
+ }
50
+ export interface StorageObject extends StorageObjectMetadata {
51
+ body: ReadableStream<Uint8Array>;
52
+ }
53
+ export interface StorageByteRange {
54
+ start: number;
55
+ end?: number;
56
+ }
57
+ export interface StorageDownloadOptions extends StorageOperationOptions {
58
+ range?: StorageByteRange;
59
+ }
60
+ export interface StorageBufferedDownloadOptions extends StorageDownloadOptions {
61
+ /**
62
+ * Maximum number of bytes buffered in memory. Defaults to 10 MiB.
63
+ * Pass `Infinity` only when the caller has independently bounded the object.
64
+ */
65
+ maxBytes?: number;
66
+ }
67
+ export interface StorageListOptions extends StorageOperationOptions {
68
+ prefix?: string;
69
+ cursor?: string;
70
+ limit?: number;
71
+ delimiter?: string;
72
+ }
73
+ export interface StorageListResult {
74
+ items: StorageObjectMetadata[];
75
+ prefixes?: string[];
76
+ cursor?: string;
77
+ }
78
+ export type StorageSearchMatch = 'glob' | 'regex' | 'substring' | 'exact';
79
+ export interface StorageSearchOptions extends StorageOperationOptions {
80
+ prefix?: string;
81
+ limit?: number;
82
+ maxResults?: number;
83
+ match?: StorageSearchMatch;
84
+ caseInsensitive?: boolean;
85
+ }
86
+ export interface StorageSignedDownloadOptions extends StorageOperationOptions {
87
+ expiresIn?: number;
88
+ responseContentDisposition?: string;
89
+ }
90
+ export interface StorageSignedUploadOptions extends StorageOperationOptions {
91
+ expiresIn: number;
92
+ contentType?: string;
93
+ maxSize?: number;
94
+ minSize?: number;
95
+ }
96
+ export type StorageSignedUpload = {
97
+ method: 'PUT';
98
+ url: string;
99
+ headers?: Record<string, string>;
100
+ } | {
101
+ method: 'POST';
102
+ url: string;
103
+ fields: Record<string, string>;
104
+ };
105
+ export interface StorageSignedUrlCapability {
106
+ supported: boolean;
107
+ maxExpiresIn?: number;
108
+ }
109
+ export interface StorageCapabilities {
110
+ rangeRead: boolean;
111
+ /** True when the provider reports native byte-level upload progress. */
112
+ nativeUploadProgress: boolean;
113
+ delimiter: boolean;
114
+ metadata: boolean;
115
+ cacheControl: boolean;
116
+ resumableUpload: boolean;
117
+ serverSideCopy: boolean;
118
+ signedDownload: StorageSignedUrlCapability;
119
+ /**
120
+ * Some providers decide support from credentials or requested constraints,
121
+ * so direct-upload support can only be known when the call is attempted.
122
+ */
123
+ signedUpload: boolean | 'runtime';
124
+ }
125
+ export interface StorageBulkOptions {
126
+ concurrency?: number;
127
+ stopOnError?: boolean;
128
+ }
129
+ export interface StorageBulkError {
130
+ key: string;
131
+ error: StorageError;
132
+ }
133
+ export interface StorageUploadManyItem {
134
+ key: string;
135
+ body: StorageBody;
136
+ contentType?: string;
137
+ cacheControl?: string;
138
+ metadata?: Record<string, string>;
139
+ multipart?: boolean | StorageMultipartOptions;
140
+ }
141
+ export interface StorageUploadManyOptions extends StorageBulkOptions, StorageOperationOptions {
142
+ onProgress?: (progress: StorageUploadProgress & {
143
+ key: string;
144
+ }) => void;
145
+ }
146
+ export interface StorageUploadManyResult {
147
+ uploaded: StorageUploadResult[];
148
+ errors?: StorageBulkError[];
149
+ }
150
+ export interface StorageDownloadManyResult {
151
+ downloaded: StorageObject[];
152
+ errors?: StorageBulkError[];
153
+ }
154
+ export interface StorageHeadManyResult {
155
+ objects: StorageObjectMetadata[];
156
+ errors?: StorageBulkError[];
157
+ }
158
+ export interface StorageExistsManyResult {
159
+ existing: string[];
160
+ missing: string[];
161
+ errors?: StorageBulkError[];
162
+ }
163
+ export interface StorageDeleteManyResult {
164
+ deleted: string[];
165
+ errors?: StorageBulkError[];
166
+ }
167
+ export type StorageOperationName = 'upload' | 'download' | 'head' | 'exists' | 'delete' | 'copy' | 'move' | 'list' | 'search' | 'signDownload' | 'signUpload';
168
+ export interface StorageOperationContext {
169
+ store: string;
170
+ operation: StorageOperationName;
171
+ key?: string;
172
+ from?: string;
173
+ to?: string;
174
+ }
175
+ export interface StoragePlugin {
176
+ name?: string;
177
+ /**
178
+ * Runs before the driver and may reject an operation, for example to enforce
179
+ * policy. Hooks run in registration order.
180
+ */
181
+ beforeOperation?: (context: StorageOperationContext) => void | Promise<void>;
182
+ /**
183
+ * Observes a successful operation. Throwing turns the call into a failure,
184
+ * which is useful for mandatory audit sinks.
185
+ *
186
+ * For streaming downloads, success means the provider returned a stream.
187
+ * Later consumption failures are normalized for the stream consumer but do
188
+ * not re-enter plugin hooks.
189
+ */
190
+ afterOperation?: (context: StorageOperationContext, result: unknown) => void | Promise<void>;
191
+ /**
192
+ * Best-effort error observation. Hook failures never replace the original
193
+ * storage error.
194
+ */
195
+ onError?: (context: StorageOperationContext, error: StorageError) => void | Promise<void>;
196
+ }
197
+ export interface StorageTransferProgress {
198
+ done: number;
199
+ total: number;
200
+ key: string;
201
+ status: 'transferred' | 'skipped';
202
+ }
203
+ export interface StorageTransferOptions extends StorageBulkOptions {
204
+ from: string;
205
+ to: string;
206
+ prefix?: string;
207
+ transformKey?: (key: string) => string;
208
+ overwrite?: boolean;
209
+ limit?: number;
210
+ signal?: AbortSignal;
211
+ onProgress?: (progress: StorageTransferProgress) => void;
212
+ }
213
+ export interface StorageTransferResult {
214
+ transferred: string[];
215
+ skipped?: string[];
216
+ errors?: StorageBulkError[];
217
+ }
218
+ export type StorageSyncCompare = 'etag' | 'size' | ((source: StorageObjectMetadata, destination: StorageObjectMetadata) => boolean);
219
+ export interface StorageSyncProgress {
220
+ done: number;
221
+ total: number;
222
+ key: string;
223
+ status: 'uploaded' | 'skipped' | 'deleted';
224
+ }
225
+ export interface StorageSyncOptions extends StorageBulkOptions {
226
+ from: string;
227
+ to: string;
228
+ prefix?: string;
229
+ destinationPrefix?: string;
230
+ transformKey?: (key: string) => string;
231
+ prune?: boolean;
232
+ compare?: StorageSyncCompare;
233
+ dryRun?: boolean;
234
+ limit?: number;
235
+ signal?: AbortSignal;
236
+ onProgress?: (progress: StorageSyncProgress) => void;
237
+ }
238
+ export interface StorageSyncResult {
239
+ uploaded: string[];
240
+ skipped: string[];
241
+ deleted?: string[];
242
+ errors?: StorageBulkError[];
243
+ }
244
+ //# sourceMappingURL=storage.types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage.types.d.ts","sourceRoot":"","sources":["../src/storage.types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=storage.types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage.types.js","sourceRoot":"","sources":["../src/storage.types.ts"],"names":[],"mappings":"","sourcesContent":["import type { Readable } from 'node:stream';\n\nimport type { StorageError } from './storage.error.js';\nimport type { StorageUploadControl } from './storage-upload-control.js';\n\nexport type StorageBody =\n | Blob\n | File\n | ReadableStream<Uint8Array>\n | Readable\n | ArrayBuffer\n | ArrayBufferView\n | Uint8Array\n | string;\n\nexport interface StorageRetryContext {\n attempt: number;\n error: StorageError;\n}\n\nexport type StorageRetryOptions =\n | number\n | {\n max: number;\n backoff?: (context: StorageRetryContext) => number;\n };\n\nexport interface StorageOperationOptions {\n signal?: AbortSignal;\n timeout?: number;\n retries?: StorageRetryOptions;\n}\n\nexport interface StorageMultipartOptions {\n partSize?: number;\n concurrency?: number;\n}\n\nexport interface StorageUploadProgress {\n loaded: number;\n total?: number;\n}\n\nexport interface StorageUploadOptions extends StorageOperationOptions {\n contentType?: string;\n cacheControl?: string;\n metadata?: Record<string, string>;\n onProgress?: (progress: StorageUploadProgress) => void;\n multipart?: boolean | StorageMultipartOptions;\n control?: StorageUploadControl;\n}\n\nexport interface StorageUploadResult {\n key: string;\n size: number;\n contentType: string;\n etag?: string;\n lastModified?: Date;\n}\n\nexport interface StorageObjectMetadata {\n key: string;\n name: string;\n size: number;\n contentType: string;\n etag?: string;\n lastModified?: Date;\n metadata?: Record<string, string>;\n}\n\nexport interface StorageObject extends StorageObjectMetadata {\n body: ReadableStream<Uint8Array>;\n}\n\nexport interface StorageByteRange {\n start: number;\n end?: number;\n}\n\nexport interface StorageDownloadOptions extends StorageOperationOptions {\n range?: StorageByteRange;\n}\n\nexport interface StorageBufferedDownloadOptions extends StorageDownloadOptions {\n /**\n * Maximum number of bytes buffered in memory. Defaults to 10 MiB.\n * Pass `Infinity` only when the caller has independently bounded the object.\n */\n maxBytes?: number;\n}\n\nexport interface StorageListOptions extends StorageOperationOptions {\n prefix?: string;\n cursor?: string;\n limit?: number;\n delimiter?: string;\n}\n\nexport interface StorageListResult {\n items: StorageObjectMetadata[];\n prefixes?: string[];\n cursor?: string;\n}\n\nexport type StorageSearchMatch = 'glob' | 'regex' | 'substring' | 'exact';\n\nexport interface StorageSearchOptions extends StorageOperationOptions {\n prefix?: string;\n limit?: number;\n maxResults?: number;\n match?: StorageSearchMatch;\n caseInsensitive?: boolean;\n}\n\nexport interface StorageSignedDownloadOptions extends StorageOperationOptions {\n expiresIn?: number;\n responseContentDisposition?: string;\n}\n\nexport interface StorageSignedUploadOptions extends StorageOperationOptions {\n expiresIn: number;\n contentType?: string;\n maxSize?: number;\n minSize?: number;\n}\n\nexport type StorageSignedUpload =\n | {\n method: 'PUT';\n url: string;\n headers?: Record<string, string>;\n }\n | {\n method: 'POST';\n url: string;\n fields: Record<string, string>;\n };\n\nexport interface StorageSignedUrlCapability {\n supported: boolean;\n maxExpiresIn?: number;\n}\n\nexport interface StorageCapabilities {\n rangeRead: boolean;\n /** True when the provider reports native byte-level upload progress. */\n nativeUploadProgress: boolean;\n delimiter: boolean;\n metadata: boolean;\n cacheControl: boolean;\n resumableUpload: boolean;\n serverSideCopy: boolean;\n signedDownload: StorageSignedUrlCapability;\n /**\n * Some providers decide support from credentials or requested constraints,\n * so direct-upload support can only be known when the call is attempted.\n */\n signedUpload: boolean | 'runtime';\n}\n\nexport interface StorageBulkOptions {\n concurrency?: number;\n stopOnError?: boolean;\n}\n\nexport interface StorageBulkError {\n key: string;\n error: StorageError;\n}\n\nexport interface StorageUploadManyItem {\n key: string;\n body: StorageBody;\n contentType?: string;\n cacheControl?: string;\n metadata?: Record<string, string>;\n multipart?: boolean | StorageMultipartOptions;\n}\n\nexport interface StorageUploadManyOptions\n extends StorageBulkOptions, StorageOperationOptions {\n onProgress?: (progress: StorageUploadProgress & { key: string }) => void;\n}\n\nexport interface StorageUploadManyResult {\n uploaded: StorageUploadResult[];\n errors?: StorageBulkError[];\n}\n\nexport interface StorageDownloadManyResult {\n downloaded: StorageObject[];\n errors?: StorageBulkError[];\n}\n\nexport interface StorageHeadManyResult {\n objects: StorageObjectMetadata[];\n errors?: StorageBulkError[];\n}\n\nexport interface StorageExistsManyResult {\n existing: string[];\n missing: string[];\n errors?: StorageBulkError[];\n}\n\nexport interface StorageDeleteManyResult {\n deleted: string[];\n errors?: StorageBulkError[];\n}\n\nexport type StorageOperationName =\n | 'upload'\n | 'download'\n | 'head'\n | 'exists'\n | 'delete'\n | 'copy'\n | 'move'\n | 'list'\n | 'search'\n | 'signDownload'\n | 'signUpload';\n\nexport interface StorageOperationContext {\n store: string;\n operation: StorageOperationName;\n key?: string;\n from?: string;\n to?: string;\n}\n\nexport interface StoragePlugin {\n name?: string;\n /**\n * Runs before the driver and may reject an operation, for example to enforce\n * policy. Hooks run in registration order.\n */\n beforeOperation?: (context: StorageOperationContext) => void | Promise<void>;\n /**\n * Observes a successful operation. Throwing turns the call into a failure,\n * which is useful for mandatory audit sinks.\n *\n * For streaming downloads, success means the provider returned a stream.\n * Later consumption failures are normalized for the stream consumer but do\n * not re-enter plugin hooks.\n */\n afterOperation?: (\n context: StorageOperationContext,\n result: unknown,\n ) => void | Promise<void>;\n /**\n * Best-effort error observation. Hook failures never replace the original\n * storage error.\n */\n onError?: (\n context: StorageOperationContext,\n error: StorageError,\n ) => void | Promise<void>;\n}\n\nexport interface StorageTransferProgress {\n done: number;\n total: number;\n key: string;\n status: 'transferred' | 'skipped';\n}\n\nexport interface StorageTransferOptions extends StorageBulkOptions {\n from: string;\n to: string;\n prefix?: string;\n transformKey?: (key: string) => string;\n overwrite?: boolean;\n limit?: number;\n signal?: AbortSignal;\n onProgress?: (progress: StorageTransferProgress) => void;\n}\n\nexport interface StorageTransferResult {\n transferred: string[];\n skipped?: string[];\n errors?: StorageBulkError[];\n}\n\nexport type StorageSyncCompare =\n | 'etag'\n | 'size'\n | ((\n source: StorageObjectMetadata,\n destination: StorageObjectMetadata,\n ) => boolean);\n\nexport interface StorageSyncProgress {\n done: number;\n total: number;\n key: string;\n status: 'uploaded' | 'skipped' | 'deleted';\n}\n\nexport interface StorageSyncOptions extends StorageBulkOptions {\n from: string;\n to: string;\n prefix?: string;\n destinationPrefix?: string;\n transformKey?: (key: string) => string;\n prune?: boolean;\n compare?: StorageSyncCompare;\n dryRun?: boolean;\n limit?: number;\n signal?: AbortSignal;\n onProgress?: (progress: StorageSyncProgress) => void;\n}\n\nexport interface StorageSyncResult {\n uploaded: string[];\n skipped: string[];\n deleted?: string[];\n errors?: StorageBulkError[];\n}\n"]}
@@ -0,0 +1,9 @@
1
+ import type { StorageDriver } from '../storage.driver.js';
2
+ import { type FilesSdkDriverOptions } from '../files-sdk/files-sdk.driver.js';
3
+ import { type MemoryAdapter, type MemoryAdapterOptions } from 'files-sdk/memory';
4
+ export interface MemoryStorageDriverOptions extends Omit<FilesSdkDriverOptions<MemoryAdapter>, 'adapter'> {
5
+ adapter?: MemoryAdapterOptions;
6
+ }
7
+ export declare function createMemoryStorageDriver(options?: MemoryStorageDriverOptions): StorageDriver;
8
+ export type { MemoryAdapterOptions, MemorySeed } from 'files-sdk/memory';
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/testing/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAEL,KAAK,qBAAqB,EAC3B,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EAEL,KAAK,aAAa,EAClB,KAAK,oBAAoB,EAC1B,MAAM,kBAAkB,CAAC;AAE1B,MAAM,WAAW,0BAA2B,SAAQ,IAAI,CACtD,qBAAqB,CAAC,aAAa,CAAC,EACpC,SAAS,CACV;IACC,OAAO,CAAC,EAAE,oBAAoB,CAAC;CAChC;AAED,wBAAgB,yBAAyB,CACvC,OAAO,GAAE,0BAA+B,GACvC,aAAa,CAMf;AAED,YAAY,EAAE,oBAAoB,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC"}
@@ -0,0 +1,10 @@
1
+ import { createFilesSdkDriver, } from '../files-sdk/files-sdk.driver.js';
2
+ import { memory, } from 'files-sdk/memory';
3
+ export function createMemoryStorageDriver(options = {}) {
4
+ const { adapter, ...filesOptions } = options;
5
+ return createFilesSdkDriver({
6
+ ...filesOptions,
7
+ adapter: memory(adapter),
8
+ });
9
+ }
10
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/testing/index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,oBAAoB,GAErB,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EACL,MAAM,GAGP,MAAM,kBAAkB,CAAC;AAS1B,MAAM,UAAU,yBAAyB,CACvC,UAAsC,EAAE;IAExC,MAAM,EAAE,OAAO,EAAE,GAAG,YAAY,EAAE,GAAG,OAAO,CAAC;IAC7C,OAAO,oBAAoB,CAAC;QAC1B,GAAG,YAAY;QACf,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC;KACzB,CAAC,CAAC;AACL,CAAC","sourcesContent":["import type { StorageDriver } from '../storage.driver.js';\nimport {\n createFilesSdkDriver,\n type FilesSdkDriverOptions,\n} from '../files-sdk/files-sdk.driver.js';\nimport {\n memory,\n type MemoryAdapter,\n type MemoryAdapterOptions,\n} from 'files-sdk/memory';\n\nexport interface MemoryStorageDriverOptions extends Omit<\n FilesSdkDriverOptions<MemoryAdapter>,\n 'adapter'\n> {\n adapter?: MemoryAdapterOptions;\n}\n\nexport function createMemoryStorageDriver(\n options: MemoryStorageDriverOptions = {},\n): StorageDriver {\n const { adapter, ...filesOptions } = options;\n return createFilesSdkDriver({\n ...filesOptions,\n adapter: memory(adapter),\n });\n}\n\nexport type { MemoryAdapterOptions, MemorySeed } from 'files-sdk/memory';\n"]}