@nestm/storage 0.1.0-alpha.6 → 0.1.0-alpha.8
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/CHANGELOG.md +128 -0
- package/README.md +398 -19
- package/SECURITY.md +69 -0
- package/dist/ai-sdk/ai-sdk-workspace-tools.d.ts +74 -0
- package/dist/ai-sdk/ai-sdk-workspace-tools.d.ts.map +1 -0
- package/dist/ai-sdk/ai-sdk-workspace-tools.js +414 -0
- package/dist/ai-sdk/ai-sdk-workspace-tools.js.map +1 -0
- package/dist/ai-sdk/index.d.ts +2 -0
- package/dist/ai-sdk/index.d.ts.map +1 -0
- package/dist/ai-sdk/index.js +2 -0
- package/dist/ai-sdk/index.js.map +1 -0
- package/dist/files-sdk/files-sdk.driver.d.ts +64 -6
- package/dist/files-sdk/files-sdk.driver.d.ts.map +1 -1
- package/dist/files-sdk/files-sdk.driver.js +918 -38
- package/dist/files-sdk/files-sdk.driver.js.map +1 -1
- package/dist/files-sdk/fs/index.d.ts +21 -2
- package/dist/files-sdk/fs/index.d.ts.map +1 -1
- package/dist/files-sdk/fs/index.js +833 -1
- package/dist/files-sdk/fs/index.js.map +1 -1
- package/dist/files-sdk/index.d.ts +1 -1
- package/dist/files-sdk/index.d.ts.map +1 -1
- package/dist/files-sdk/index.js.map +1 -1
- package/dist/files-sdk/provider/index.d.ts +9 -5
- package/dist/files-sdk/provider/index.d.ts.map +1 -1
- package/dist/files-sdk/provider/index.js +60 -15
- package/dist/files-sdk/provider/index.js.map +1 -1
- package/dist/files-sdk/s3/construction-metadata.d.ts +7 -0
- package/dist/files-sdk/s3/construction-metadata.d.ts.map +1 -0
- package/dist/files-sdk/s3/construction-metadata.js +13 -0
- package/dist/files-sdk/s3/construction-metadata.js.map +1 -0
- package/dist/files-sdk/s3/index.d.ts +43 -14
- package/dist/files-sdk/s3/index.d.ts.map +1 -1
- package/dist/files-sdk/s3/index.js +1046 -57
- package/dist/files-sdk/s3/index.js.map +1 -1
- package/dist/gateway/storage-gateway.controller.d.ts.map +1 -1
- package/dist/gateway/storage-gateway.controller.js +25 -5
- package/dist/gateway/storage-gateway.controller.js.map +1 -1
- package/dist/storage-etag.d.ts +13 -0
- package/dist/storage-etag.d.ts.map +1 -0
- package/dist/storage-etag.js +31 -0
- package/dist/storage-etag.js.map +1 -0
- package/dist/storage.client.d.ts +7 -1
- package/dist/storage.client.d.ts.map +1 -1
- package/dist/storage.client.js +124 -10
- package/dist/storage.client.js.map +1 -1
- package/dist/storage.driver.d.ts +23 -1
- package/dist/storage.driver.d.ts.map +1 -1
- package/dist/storage.driver.js.map +1 -1
- package/dist/storage.service.d.ts.map +1 -1
- package/dist/storage.service.js +28 -3
- package/dist/storage.service.js.map +1 -1
- package/dist/storage.types.d.ts +113 -6
- package/dist/storage.types.d.ts.map +1 -1
- package/dist/storage.types.js.map +1 -1
- package/dist/testing/index.d.ts +1 -0
- package/dist/testing/index.d.ts.map +1 -1
- package/dist/testing/index.js +1 -0
- package/dist/testing/index.js.map +1 -1
- package/dist/testing/provider-conformance.d.ts +65 -0
- package/dist/testing/provider-conformance.d.ts.map +1 -0
- package/dist/testing/provider-conformance.js +853 -0
- package/dist/testing/provider-conformance.js.map +1 -0
- package/dist/workspace/index.d.ts +5 -0
- package/dist/workspace/index.d.ts.map +1 -0
- package/dist/workspace/index.js +5 -0
- package/dist/workspace/index.js.map +1 -0
- package/dist/workspace/storage-workspace.cursor.d.ts +71 -0
- package/dist/workspace/storage-workspace.cursor.d.ts.map +1 -0
- package/dist/workspace/storage-workspace.cursor.js +408 -0
- package/dist/workspace/storage-workspace.cursor.js.map +1 -0
- package/dist/workspace/storage-workspace.d.ts +6 -0
- package/dist/workspace/storage-workspace.d.ts.map +1 -0
- package/dist/workspace/storage-workspace.error.d.ts +28 -0
- package/dist/workspace/storage-workspace.error.d.ts.map +1 -0
- package/dist/workspace/storage-workspace.error.js +67 -0
- package/dist/workspace/storage-workspace.error.js.map +1 -0
- package/dist/workspace/storage-workspace.js +755 -0
- package/dist/workspace/storage-workspace.js.map +1 -0
- package/dist/workspace/storage-workspace.path.d.ts +9 -0
- package/dist/workspace/storage-workspace.path.d.ts.map +1 -0
- package/dist/workspace/storage-workspace.path.js +68 -0
- package/dist/workspace/storage-workspace.path.js.map +1 -0
- package/dist/workspace/storage-workspace.types.d.ts +105 -0
- package/dist/workspace/storage-workspace.types.d.ts.map +1 -0
- package/dist/workspace/storage-workspace.types.js +21 -0
- package/dist/workspace/storage-workspace.types.js.map +1 -0
- package/package.json +24 -5
package/dist/storage.service.js
CHANGED
|
@@ -3,6 +3,30 @@ import { StorageClient } from './storage.client.js';
|
|
|
3
3
|
import { StorageError, StorageErrorCode } from './storage.error.js';
|
|
4
4
|
import { normalizeStorageName } from './storage.tokens.js';
|
|
5
5
|
const identity = (key) => key;
|
|
6
|
+
function joinStorageKey(prefix, key) {
|
|
7
|
+
if (prefix === undefined || prefix.length === 0) {
|
|
8
|
+
return key;
|
|
9
|
+
}
|
|
10
|
+
const normalizedPrefix = prefix.replace(/\/+$/u, '');
|
|
11
|
+
for (const [label, value] of [
|
|
12
|
+
['destinationPrefix', normalizedPrefix],
|
|
13
|
+
['transformed destination key', key],
|
|
14
|
+
]) {
|
|
15
|
+
if (value.length === 0 ||
|
|
16
|
+
value.startsWith('/') ||
|
|
17
|
+
value.includes('\\') ||
|
|
18
|
+
value.includes('\0') ||
|
|
19
|
+
value
|
|
20
|
+
.split('/')
|
|
21
|
+
.some((segment) => segment.length === 0 || segment === '.' || segment === '..')) {
|
|
22
|
+
throw new StorageError(`${label} must be a canonical relative POSIX storage key.`, {
|
|
23
|
+
code: StorageErrorCode.INVALID_ARGUMENT,
|
|
24
|
+
permanent: true,
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return `${normalizedPrefix}/${key}`;
|
|
29
|
+
}
|
|
6
30
|
function assertDifferentStores(from, to) {
|
|
7
31
|
if (from === to) {
|
|
8
32
|
throw new StorageError('Cross-store transfer and sync require different source and destination stores.', {
|
|
@@ -137,6 +161,7 @@ export class StorageService {
|
|
|
137
161
|
const source = this.use(fromName);
|
|
138
162
|
const destination = this.use(toName);
|
|
139
163
|
const transformKey = options.transformKey ?? identity;
|
|
164
|
+
const destinationKeyOf = (key) => joinStorageKey(options.destinationPrefix, transformKey(key));
|
|
140
165
|
const compare = options.compare ?? 'etag';
|
|
141
166
|
const sourceObjects = await walk(source, options);
|
|
142
167
|
const destinationObjects = await walk(destination, {
|
|
@@ -149,7 +174,7 @@ export class StorageService {
|
|
|
149
174
|
...(options.signal !== undefined && { signal: options.signal }),
|
|
150
175
|
});
|
|
151
176
|
const destinationIndex = new Map(destinationObjects.map((object) => [object.key, object]));
|
|
152
|
-
const desiredDestinationKeys = new Set(sourceObjects.map((object) =>
|
|
177
|
+
const desiredDestinationKeys = new Set(sourceObjects.map((object) => destinationKeyOf(object.key)));
|
|
153
178
|
const deleteKeys = (options.prune ?? false)
|
|
154
179
|
? destinationObjects
|
|
155
180
|
.map((object) => object.key)
|
|
@@ -158,7 +183,7 @@ export class StorageService {
|
|
|
158
183
|
const plannedUploads = [];
|
|
159
184
|
const plannedSkips = [];
|
|
160
185
|
for (const object of sourceObjects) {
|
|
161
|
-
const existing = destinationIndex.get(
|
|
186
|
+
const existing = destinationIndex.get(destinationKeyOf(object.key));
|
|
162
187
|
(existing && unchanged(object, existing, compare)
|
|
163
188
|
? plannedSkips
|
|
164
189
|
: plannedUploads).push(object.key);
|
|
@@ -178,7 +203,7 @@ export class StorageService {
|
|
|
178
203
|
};
|
|
179
204
|
const skipped = new Set();
|
|
180
205
|
const settled = await settleMany(sourceObjects, (object) => object.key, async (object) => {
|
|
181
|
-
const destinationKey =
|
|
206
|
+
const destinationKey = destinationKeyOf(object.key);
|
|
182
207
|
const existing = destinationIndex.get(destinationKey);
|
|
183
208
|
if (existing && unchanged(object, existing, compare)) {
|
|
184
209
|
skipped.add(object.key);
|
|
@@ -1 +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"]}
|
|
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 joinStorageKey(prefix: string | undefined, key: string): string {\n if (prefix === undefined || prefix.length === 0) {\n return key;\n }\n const normalizedPrefix = prefix.replace(/\\/+$/u, '');\n for (const [label, value] of [\n ['destinationPrefix', normalizedPrefix],\n ['transformed destination key', key],\n ] as const) {\n if (\n value.length === 0 ||\n value.startsWith('/') ||\n value.includes('\\\\') ||\n value.includes('\\0') ||\n value\n .split('/')\n .some(\n (segment) =>\n segment.length === 0 || segment === '.' || segment === '..',\n )\n ) {\n throw new StorageError(\n `${label} must be a canonical relative POSIX storage key.`,\n {\n code: StorageErrorCode.INVALID_ARGUMENT,\n permanent: true,\n },\n );\n }\n }\n return `${normalizedPrefix}/${key}`;\n}\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 destinationKeyOf = (key: string): string =>\n joinStorageKey(options.destinationPrefix, transformKey(key));\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) => destinationKeyOf(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(destinationKeyOf(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 = destinationKeyOf(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"]}
|
package/dist/storage.types.d.ts
CHANGED
|
@@ -24,6 +24,17 @@ export interface StoragePromotionOptions extends StorageOperationOptions {
|
|
|
24
24
|
sourceEtag?: string;
|
|
25
25
|
/** Copy this immutable provider version of the source object. */
|
|
26
26
|
sourceVersion?: string;
|
|
27
|
+
/**
|
|
28
|
+
* Protect the destination in the same provider copy request. When a source
|
|
29
|
+
* condition is also present, the provider profile must explicitly declare
|
|
30
|
+
* that both predicates are evaluated atomically.
|
|
31
|
+
*/
|
|
32
|
+
destination?: {
|
|
33
|
+
type: 'create';
|
|
34
|
+
} | {
|
|
35
|
+
type: 'replace';
|
|
36
|
+
etag: string;
|
|
37
|
+
};
|
|
27
38
|
}
|
|
28
39
|
export interface StorageMultipartOptions {
|
|
29
40
|
partSize?: number;
|
|
@@ -41,10 +52,29 @@ export interface StorageUploadOptions extends StorageOperationOptions {
|
|
|
41
52
|
multipart?: boolean | StorageMultipartOptions;
|
|
42
53
|
control?: StorageUploadControl;
|
|
43
54
|
}
|
|
55
|
+
export type StorageConditionalUploadOptions = StorageUploadOptions & ({
|
|
56
|
+
/** Atomically create the object only when its key does not exist. */
|
|
57
|
+
condition: {
|
|
58
|
+
type: 'create';
|
|
59
|
+
};
|
|
60
|
+
} | {
|
|
61
|
+
/** Atomically replace the object only when its current ETag matches. */
|
|
62
|
+
condition: {
|
|
63
|
+
type: 'replace';
|
|
64
|
+
etag: string;
|
|
65
|
+
};
|
|
66
|
+
});
|
|
67
|
+
export interface StorageConditionalDeleteOptions extends StorageOperationOptions {
|
|
68
|
+
/** Atomically delete the object only when its current ETag matches. */
|
|
69
|
+
condition: {
|
|
70
|
+
etag: string;
|
|
71
|
+
};
|
|
72
|
+
}
|
|
44
73
|
export interface StorageUploadResult {
|
|
45
74
|
key: string;
|
|
46
75
|
size: number;
|
|
47
76
|
contentType: string;
|
|
77
|
+
/** Canonical bare provider ETag; pass it back unchanged as a condition. */
|
|
48
78
|
etag?: string;
|
|
49
79
|
lastModified?: Date;
|
|
50
80
|
}
|
|
@@ -53,6 +83,7 @@ export interface StorageObjectMetadata {
|
|
|
53
83
|
name: string;
|
|
54
84
|
size: number;
|
|
55
85
|
contentType: string;
|
|
86
|
+
/** Canonical bare provider ETag; pass it back unchanged as a condition. */
|
|
56
87
|
etag?: string;
|
|
57
88
|
lastModified?: Date;
|
|
58
89
|
metadata?: Record<string, string>;
|
|
@@ -67,6 +98,21 @@ export interface StorageByteRange {
|
|
|
67
98
|
export interface StorageDownloadOptions extends StorageOperationOptions {
|
|
68
99
|
range?: StorageByteRange;
|
|
69
100
|
}
|
|
101
|
+
/**
|
|
102
|
+
* Reads one exact observed object identity. At least one provider identity is
|
|
103
|
+
* required; a driver must never emulate this with a separate head request.
|
|
104
|
+
*/
|
|
105
|
+
export type StorageConditionalReadOptions = StorageDownloadOptions & ({
|
|
106
|
+
condition: {
|
|
107
|
+
etag: string;
|
|
108
|
+
version?: string;
|
|
109
|
+
};
|
|
110
|
+
} | {
|
|
111
|
+
condition: {
|
|
112
|
+
etag?: string;
|
|
113
|
+
version: string;
|
|
114
|
+
};
|
|
115
|
+
});
|
|
70
116
|
export interface StorageBufferedDownloadOptions extends StorageDownloadOptions {
|
|
71
117
|
/**
|
|
72
118
|
* Maximum number of bytes buffered in memory. Defaults to 10 MiB.
|
|
@@ -76,6 +122,15 @@ export interface StorageBufferedDownloadOptions extends StorageDownloadOptions {
|
|
|
76
122
|
}
|
|
77
123
|
export interface StorageListOptions extends StorageOperationOptions {
|
|
78
124
|
prefix?: string;
|
|
125
|
+
/**
|
|
126
|
+
* Opaque, non-consuming continuation token returned by `list`.
|
|
127
|
+
*
|
|
128
|
+
* The token is bound to the original `prefix` and `delimiter`, but callers
|
|
129
|
+
* may change `limit` when resuming. While the provider token remains valid
|
|
130
|
+
* and available, replaying it against unchanged provider state must return
|
|
131
|
+
* the same logical position; token bytes returned for the following position
|
|
132
|
+
* need not be stable.
|
|
133
|
+
*/
|
|
79
134
|
cursor?: string;
|
|
80
135
|
limit?: number;
|
|
81
136
|
delimiter?: string;
|
|
@@ -83,6 +138,10 @@ export interface StorageListOptions extends StorageOperationOptions {
|
|
|
83
138
|
export interface StorageListResult {
|
|
84
139
|
items: StorageObjectMetadata[];
|
|
85
140
|
prefixes?: string[];
|
|
141
|
+
/**
|
|
142
|
+
* Opaque, replayable continuation token for the next logical position.
|
|
143
|
+
* See `StorageDriver.list` for the complete portability contract.
|
|
144
|
+
*/
|
|
86
145
|
cursor?: string;
|
|
87
146
|
}
|
|
88
147
|
export type StorageSearchMatch = 'glob' | 'regex' | 'substring' | 'exact';
|
|
@@ -116,11 +175,44 @@ export interface StorageSignedUrlCapability {
|
|
|
116
175
|
supported: boolean;
|
|
117
176
|
maxExpiresIn?: number;
|
|
118
177
|
}
|
|
119
|
-
export interface
|
|
120
|
-
|
|
178
|
+
export interface StorageConditionalWriteCapability {
|
|
179
|
+
/** A successful write returns the provider ETag identifying its result. */
|
|
180
|
+
resultEtag: boolean;
|
|
181
|
+
}
|
|
182
|
+
export interface StorageConditionalDeleteCapability {
|
|
183
|
+
/** Delete can compare the current object against an opaque provider ETag. */
|
|
184
|
+
etag: boolean;
|
|
185
|
+
}
|
|
186
|
+
export interface StorageConditionalReadCapability {
|
|
187
|
+
/** Read can require the current object to match an opaque provider ETag. */
|
|
188
|
+
etag: boolean;
|
|
189
|
+
/** Read can select an immutable provider version. */
|
|
190
|
+
version: boolean;
|
|
191
|
+
}
|
|
192
|
+
export interface StorageConditionalCopySourceCapability {
|
|
193
|
+
/** Copy can require the source to match an opaque provider ETag. */
|
|
121
194
|
etag: boolean;
|
|
195
|
+
/** Copy can select an immutable source version. */
|
|
122
196
|
version: boolean;
|
|
123
197
|
}
|
|
198
|
+
export interface StorageConditionalCopyDestinationCapability {
|
|
199
|
+
/** Copy can require that the destination does not exist. */
|
|
200
|
+
create: boolean;
|
|
201
|
+
/** Copy can require that the destination matches an opaque provider ETag. */
|
|
202
|
+
replace: boolean;
|
|
203
|
+
/** Source and destination predicates share one provider linearization point. */
|
|
204
|
+
atomicWithSource: boolean;
|
|
205
|
+
}
|
|
206
|
+
export interface StorageConditionalMultipartCompletionCapability {
|
|
207
|
+
/** Multipart completion can require that the destination does not exist. */
|
|
208
|
+
create: boolean;
|
|
209
|
+
/** Multipart completion can require that the destination ETag matches. */
|
|
210
|
+
replace: boolean;
|
|
211
|
+
}
|
|
212
|
+
export interface StoragePhysicalKeyCapability {
|
|
213
|
+
/** Maximum UTF-8 bytes in the complete provider key, including prefixes. */
|
|
214
|
+
maxBytes: number;
|
|
215
|
+
}
|
|
124
216
|
export interface StorageSignedUploadPolicyCapability {
|
|
125
217
|
/** The signed request fixes the exact declared content type. */
|
|
126
218
|
contentType: boolean;
|
|
@@ -141,11 +233,26 @@ export interface StorageCapabilities {
|
|
|
141
233
|
resumableUpload: boolean;
|
|
142
234
|
serverSideCopy: boolean;
|
|
143
235
|
/**
|
|
144
|
-
*
|
|
145
|
-
*
|
|
146
|
-
|
|
236
|
+
* Native create-if-absent support. Absent means unsupported; callers must
|
|
237
|
+
* not emulate it with an exists request followed by an unconditional write.
|
|
238
|
+
*/
|
|
239
|
+
conditionalCreate?: StorageConditionalWriteCapability;
|
|
240
|
+
/**
|
|
241
|
+
* Native replace-if-current-ETag-matches support. Absent means unsupported.
|
|
147
242
|
*/
|
|
148
|
-
|
|
243
|
+
conditionalReplace?: StorageConditionalWriteCapability;
|
|
244
|
+
/** Native delete-if-current-ETag-matches support. */
|
|
245
|
+
conditionalDelete?: StorageConditionalDeleteCapability;
|
|
246
|
+
/** Native conditional read of an exact observed identity. */
|
|
247
|
+
conditionalRead?: StorageConditionalReadCapability;
|
|
248
|
+
/** Source predicates supported by conditional server-side copy. */
|
|
249
|
+
conditionalCopySource?: StorageConditionalCopySourceCapability;
|
|
250
|
+
/** Destination predicates supported by conditional server-side copy. */
|
|
251
|
+
conditionalCopyDestination?: StorageConditionalCopyDestinationCapability;
|
|
252
|
+
/** Conditions enforced by multipart completion rather than part upload. */
|
|
253
|
+
conditionalMultipartCompletion?: StorageConditionalMultipartCompletionCapability;
|
|
254
|
+
/** Provider budget for the complete physical key. */
|
|
255
|
+
physicalKey?: StoragePhysicalKeyCapability;
|
|
149
256
|
signedDownload: StorageSignedUrlCapability;
|
|
150
257
|
/** Expiry guarantees enforced by the provider adapter. */
|
|
151
258
|
signedDownloadPolicy?: StorageSignedDownloadPolicyCapability;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"storage.types.d.ts","sourceRoot":"","sources":["../src/storage.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE5C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AAExE,MAAM,MAAM,WAAW,GACnB,IAAI,GACJ,IAAI,GACJ,cAAc,CAAC,UAAU,CAAC,GAC1B,QAAQ,GACR,WAAW,GACX,eAAe,GACf,UAAU,GACV,MAAM,CAAC;AAEX,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,YAAY,CAAC;CACrB;AAED,MAAM,MAAM,mBAAmB,GAC3B,MAAM,GACN;IACE,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,mBAAmB,KAAK,MAAM,CAAC;CACpD,CAAC;AAEN,MAAM,WAAW,uBAAuB;IACtC,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,mBAAmB,CAAC;CAC/B;AAED;;;GAGG;AACH,MAAM,WAAW,uBAAwB,SAAQ,uBAAuB;IACtE,uEAAuE;IACvE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iEAAiE;IACjE,aAAa,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"storage.types.d.ts","sourceRoot":"","sources":["../src/storage.types.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +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\n/**\n * Preconditions for promoting a staged object to its final key. At least one\n * source identity must be supplied; unsupported identities fail closed.\n */\nexport interface StoragePromotionOptions extends StorageOperationOptions {\n /** Copy only the source object whose provider ETag exactly matches. */\n sourceEtag?: string;\n /** Copy this immutable provider version of the source object. */\n sourceVersion?: string;\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 StorageConditionalCopyCapability {\n supported: boolean;\n etag: boolean;\n version: boolean;\n}\n\nexport interface StorageSignedUploadPolicyCapability {\n /** The signed request fixes the exact declared content type. */\n contentType: boolean;\n /** The signed request enforces the requested min/max byte range. */\n sizeRange: boolean;\n}\n\nexport interface StorageSignedDownloadPolicyCapability {\n /** Every generated URL honors the requested expiry. */\n expiresIn: boolean;\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 /**\n * Conditional server-side copy used to promote an already verified staged\n * object without a validation/copy race. Absent means unsupported for\n * compatibility with drivers built against earlier package versions.\n */\n conditionalCopy?: StorageConditionalCopyCapability;\n signedDownload: StorageSignedUrlCapability;\n /** Expiry guarantees enforced by the provider adapter. */\n signedDownloadPolicy?: StorageSignedDownloadPolicyCapability;\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 * Constraints cryptographically/provider-policy enforced by direct upload.\n * Absent means callers must not assume request options are enforced.\n */\n signedUploadPolicy?: StorageSignedUploadPolicyCapability;\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 | 'promote'\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"]}
|
|
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\n/**\n * Preconditions for promoting a staged object to its final key. At least one\n * source identity must be supplied; unsupported identities fail closed.\n */\nexport interface StoragePromotionOptions extends StorageOperationOptions {\n /** Copy only the source object whose provider ETag exactly matches. */\n sourceEtag?: string;\n /** Copy this immutable provider version of the source object. */\n sourceVersion?: string;\n /**\n * Protect the destination in the same provider copy request. When a source\n * condition is also present, the provider profile must explicitly declare\n * that both predicates are evaluated atomically.\n */\n destination?: { type: 'create' } | { type: 'replace'; etag: string };\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 type StorageConditionalUploadOptions = StorageUploadOptions &\n (\n | {\n /** Atomically create the object only when its key does not exist. */\n condition: { type: 'create' };\n }\n | {\n /** Atomically replace the object only when its current ETag matches. */\n condition: { type: 'replace'; etag: string };\n }\n );\n\nexport interface StorageConditionalDeleteOptions extends StorageOperationOptions {\n /** Atomically delete the object only when its current ETag matches. */\n condition: { etag: string };\n}\n\nexport interface StorageUploadResult {\n key: string;\n size: number;\n contentType: string;\n /** Canonical bare provider ETag; pass it back unchanged as a condition. */\n etag?: string;\n lastModified?: Date;\n}\n\nexport interface StorageObjectMetadata {\n key: string;\n name: string;\n size: number;\n contentType: string;\n /** Canonical bare provider ETag; pass it back unchanged as a condition. */\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\n/**\n * Reads one exact observed object identity. At least one provider identity is\n * required; a driver must never emulate this with a separate head request.\n */\nexport type StorageConditionalReadOptions = StorageDownloadOptions &\n (\n | {\n condition: { etag: string; version?: string };\n }\n | {\n condition: { etag?: string; version: string };\n }\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 /**\n * Opaque, non-consuming continuation token returned by `list`.\n *\n * The token is bound to the original `prefix` and `delimiter`, but callers\n * may change `limit` when resuming. While the provider token remains valid\n * and available, replaying it against unchanged provider state must return\n * the same logical position; token bytes returned for the following position\n * need not be stable.\n */\n cursor?: string;\n limit?: number;\n delimiter?: string;\n}\n\nexport interface StorageListResult {\n items: StorageObjectMetadata[];\n prefixes?: string[];\n /**\n * Opaque, replayable continuation token for the next logical position.\n * See `StorageDriver.list` for the complete portability contract.\n */\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 StorageConditionalWriteCapability {\n /** A successful write returns the provider ETag identifying its result. */\n resultEtag: boolean;\n}\n\nexport interface StorageConditionalDeleteCapability {\n /** Delete can compare the current object against an opaque provider ETag. */\n etag: boolean;\n}\n\nexport interface StorageConditionalReadCapability {\n /** Read can require the current object to match an opaque provider ETag. */\n etag: boolean;\n /** Read can select an immutable provider version. */\n version: boolean;\n}\n\nexport interface StorageConditionalCopySourceCapability {\n /** Copy can require the source to match an opaque provider ETag. */\n etag: boolean;\n /** Copy can select an immutable source version. */\n version: boolean;\n}\n\nexport interface StorageConditionalCopyDestinationCapability {\n /** Copy can require that the destination does not exist. */\n create: boolean;\n /** Copy can require that the destination matches an opaque provider ETag. */\n replace: boolean;\n /** Source and destination predicates share one provider linearization point. */\n atomicWithSource: boolean;\n}\n\nexport interface StorageConditionalMultipartCompletionCapability {\n /** Multipart completion can require that the destination does not exist. */\n create: boolean;\n /** Multipart completion can require that the destination ETag matches. */\n replace: boolean;\n}\n\nexport interface StoragePhysicalKeyCapability {\n /** Maximum UTF-8 bytes in the complete provider key, including prefixes. */\n maxBytes: number;\n}\n\nexport interface StorageSignedUploadPolicyCapability {\n /** The signed request fixes the exact declared content type. */\n contentType: boolean;\n /** The signed request enforces the requested min/max byte range. */\n sizeRange: boolean;\n}\n\nexport interface StorageSignedDownloadPolicyCapability {\n /** Every generated URL honors the requested expiry. */\n expiresIn: boolean;\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 /**\n * Native create-if-absent support. Absent means unsupported; callers must\n * not emulate it with an exists request followed by an unconditional write.\n */\n conditionalCreate?: StorageConditionalWriteCapability;\n /**\n * Native replace-if-current-ETag-matches support. Absent means unsupported.\n */\n conditionalReplace?: StorageConditionalWriteCapability;\n /** Native delete-if-current-ETag-matches support. */\n conditionalDelete?: StorageConditionalDeleteCapability;\n /** Native conditional read of an exact observed identity. */\n conditionalRead?: StorageConditionalReadCapability;\n /** Source predicates supported by conditional server-side copy. */\n conditionalCopySource?: StorageConditionalCopySourceCapability;\n /** Destination predicates supported by conditional server-side copy. */\n conditionalCopyDestination?: StorageConditionalCopyDestinationCapability;\n /** Conditions enforced by multipart completion rather than part upload. */\n conditionalMultipartCompletion?: StorageConditionalMultipartCompletionCapability;\n /** Provider budget for the complete physical key. */\n physicalKey?: StoragePhysicalKeyCapability;\n signedDownload: StorageSignedUrlCapability;\n /** Expiry guarantees enforced by the provider adapter. */\n signedDownloadPolicy?: StorageSignedDownloadPolicyCapability;\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 * Constraints cryptographically/provider-policy enforced by direct upload.\n * Absent means callers must not assume request options are enforced.\n */\n signedUploadPolicy?: StorageSignedUploadPolicyCapability;\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 | 'promote'\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"]}
|
package/dist/testing/index.d.ts
CHANGED
|
@@ -5,5 +5,6 @@ export interface MemoryStorageDriverOptions extends Omit<FilesSdkDriverOptions<M
|
|
|
5
5
|
adapter?: MemoryAdapterOptions;
|
|
6
6
|
}
|
|
7
7
|
export declare function createMemoryStorageDriver(options?: MemoryStorageDriverOptions): StorageDriver;
|
|
8
|
+
export { createStorageProviderConformanceCases, type StorageProviderConformanceCapabilities, type StorageProviderConformanceCase, type StorageProviderConformanceCaseResult, type StorageProviderConformanceFixture, type StorageProviderConformanceOptions, } from './provider-conformance.js';
|
|
8
9
|
export type { MemoryAdapterOptions, MemorySeed } from 'files-sdk/memory';
|
|
9
10
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +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"}
|
|
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,OAAO,EACL,qCAAqC,EACrC,KAAK,sCAAsC,EAC3C,KAAK,8BAA8B,EACnC,KAAK,oCAAoC,EACzC,KAAK,iCAAiC,EACtC,KAAK,iCAAiC,GACvC,MAAM,2BAA2B,CAAC;AAEnC,YAAY,EAAE,oBAAoB,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC"}
|
package/dist/testing/index.js
CHANGED
|
@@ -1 +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,OAAO,GAA+B,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"]}
|
|
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,OAAO,GAA+B,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;AAED,OAAO,EACL,qCAAqC,GAMtC,MAAM,2BAA2B,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 {\n createStorageProviderConformanceCases,\n type StorageProviderConformanceCapabilities,\n type StorageProviderConformanceCase,\n type StorageProviderConformanceCaseResult,\n type StorageProviderConformanceFixture,\n type StorageProviderConformanceOptions,\n} from './provider-conformance.js';\n\nexport type { MemoryAdapterOptions, MemorySeed } from 'files-sdk/memory';\n"]}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import type { StorageClient } from '../storage.client.js';
|
|
2
|
+
import type { StorageConditionalCopyDestinationCapability, StorageConditionalCopySourceCapability, StorageConditionalDeleteCapability, StorageConditionalMultipartCompletionCapability, StorageConditionalReadCapability, StorageConditionalWriteCapability, StoragePhysicalKeyCapability, StorageSignedUploadPolicyCapability } from '../storage.types.js';
|
|
3
|
+
declare const PASSED: Readonly<{
|
|
4
|
+
status: 'passed';
|
|
5
|
+
}>;
|
|
6
|
+
export interface StorageProviderConformanceCapabilities {
|
|
7
|
+
readonly conditionalCreate?: StorageConditionalWriteCapability;
|
|
8
|
+
readonly conditionalReplace?: StorageConditionalWriteCapability;
|
|
9
|
+
readonly conditionalDelete?: StorageConditionalDeleteCapability;
|
|
10
|
+
readonly conditionalRead?: StorageConditionalReadCapability;
|
|
11
|
+
readonly conditionalCopySource?: StorageConditionalCopySourceCapability;
|
|
12
|
+
readonly conditionalCopyDestination?: StorageConditionalCopyDestinationCapability;
|
|
13
|
+
readonly conditionalMultipartCompletion?: StorageConditionalMultipartCompletionCapability;
|
|
14
|
+
readonly physicalKey: StoragePhysicalKeyCapability;
|
|
15
|
+
readonly signedUploadPolicy?: StorageSignedUploadPolicyCapability;
|
|
16
|
+
}
|
|
17
|
+
export interface StorageProviderConformanceFixture {
|
|
18
|
+
readonly client: StorageClient;
|
|
19
|
+
/**
|
|
20
|
+
* Builds a new client and driver for the same logical store and backend
|
|
21
|
+
* configuration. The harness owns the returned client and shuts it down.
|
|
22
|
+
*/
|
|
23
|
+
readonly createReplica: () => StorageClient | Promise<StorageClient>;
|
|
24
|
+
/**
|
|
25
|
+
* Returns the number of operations dispatched to the provider driver. When
|
|
26
|
+
* supplied, the contract proves invalid inputs fail before provider I/O.
|
|
27
|
+
*/
|
|
28
|
+
readonly dispatchCount?: () => number;
|
|
29
|
+
/**
|
|
30
|
+
* Resolves the current immutable version for a logical key. Providers that
|
|
31
|
+
* advertise version predicates should supply this for a version-enabled
|
|
32
|
+
* test bucket. Returning undefined visibly skips only the version subcases.
|
|
33
|
+
*/
|
|
34
|
+
readonly resolveVersion?: (key: string) => Promise<string | undefined>;
|
|
35
|
+
/**
|
|
36
|
+
* Optional provider-aware cleanup. This is useful for versioned buckets,
|
|
37
|
+
* where a plain delete would leave historical object versions behind.
|
|
38
|
+
*/
|
|
39
|
+
readonly cleanup?: (keys: readonly string[]) => void | Promise<void>;
|
|
40
|
+
readonly close?: () => void | Promise<void>;
|
|
41
|
+
}
|
|
42
|
+
export interface StorageProviderConformanceOptions {
|
|
43
|
+
readonly createFixture: (() => StorageProviderConformanceFixture) | (() => Promise<StorageProviderConformanceFixture>);
|
|
44
|
+
readonly expected: StorageProviderConformanceCapabilities;
|
|
45
|
+
/** Values such as test credentials that must never occur in public errors. */
|
|
46
|
+
readonly forbiddenErrorValues?: readonly string[];
|
|
47
|
+
readonly multipartBytes?: number;
|
|
48
|
+
readonly provider: string;
|
|
49
|
+
}
|
|
50
|
+
export type StorageProviderConformanceCaseResult = typeof PASSED | {
|
|
51
|
+
readonly reason: string;
|
|
52
|
+
readonly status: 'skipped';
|
|
53
|
+
};
|
|
54
|
+
export interface StorageProviderConformanceCase {
|
|
55
|
+
readonly name: string;
|
|
56
|
+
run(): Promise<StorageProviderConformanceCaseResult>;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Builds runner-agnostic provider contract cases. A test runner can register
|
|
60
|
+
* each returned case independently and translate a `skipped` result into its
|
|
61
|
+
* native skip primitive. Every case receives a fresh client and namespace.
|
|
62
|
+
*/
|
|
63
|
+
export declare function createStorageProviderConformanceCases(options: StorageProviderConformanceOptions): readonly StorageProviderConformanceCase[];
|
|
64
|
+
export {};
|
|
65
|
+
//# sourceMappingURL=provider-conformance.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider-conformance.d.ts","sourceRoot":"","sources":["../../src/testing/provider-conformance.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAO1D,OAAO,KAAK,EAEV,2CAA2C,EAC3C,sCAAsC,EACtC,kCAAkC,EAClC,+CAA+C,EAC/C,gCAAgC,EAChC,iCAAiC,EAGjC,4BAA4B,EAC5B,mCAAmC,EAEpC,MAAM,qBAAqB,CAAC;AAY7B,QAAA,MAAM,MAAM;YAA2B,QAAQ;EAAY,CAAC;AAE5D,MAAM,WAAW,sCAAsC;IACrD,QAAQ,CAAC,iBAAiB,CAAC,EAAE,iCAAiC,CAAC;IAC/D,QAAQ,CAAC,kBAAkB,CAAC,EAAE,iCAAiC,CAAC;IAChE,QAAQ,CAAC,iBAAiB,CAAC,EAAE,kCAAkC,CAAC;IAChE,QAAQ,CAAC,eAAe,CAAC,EAAE,gCAAgC,CAAC;IAC5D,QAAQ,CAAC,qBAAqB,CAAC,EAAE,sCAAsC,CAAC;IACxE,QAAQ,CAAC,0BAA0B,CAAC,EAAE,2CAA2C,CAAC;IAClF,QAAQ,CAAC,8BAA8B,CAAC,EAAE,+CAA+C,CAAC;IAC1F,QAAQ,CAAC,WAAW,EAAE,4BAA4B,CAAC;IACnD,QAAQ,CAAC,kBAAkB,CAAC,EAAE,mCAAmC,CAAC;CACnE;AAED,MAAM,WAAW,iCAAiC;IAChD,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC;IAC/B;;;OAGG;IACH,QAAQ,CAAC,aAAa,EAAE,MAAM,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;IACrE;;;OAGG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,MAAM,CAAC;IACtC;;;;OAIG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IACvE;;;OAGG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACrE,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7C;AAED,MAAM,WAAW,iCAAiC;IAChD,QAAQ,CAAC,aAAa,EAClB,CAAC,MAAM,iCAAiC,CAAC,GACzC,CAAC,MAAM,OAAO,CAAC,iCAAiC,CAAC,CAAC,CAAC;IACvD,QAAQ,CAAC,QAAQ,EAAE,sCAAsC,CAAC;IAC1D,8EAA8E;IAC9E,QAAQ,CAAC,oBAAoB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAClD,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,MAAM,oCAAoC,GAC9C,OAAO,MAAM,GAAG;IAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAA;CAAE,CAAC;AAE1E,MAAM,WAAW,8BAA8B;IAC7C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,GAAG,IAAI,OAAO,CAAC,oCAAoC,CAAC,CAAC;CACtD;AAkBD;;;;GAIG;AACH,wBAAgB,qCAAqC,CACnD,OAAO,EAAE,iCAAiC,GACzC,SAAS,8BAA8B,EAAE,CA8E3C"}
|