@n8n/blob-storage 1.0.0 → 1.2.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.
@@ -0,0 +1,9 @@
1
+ import type { ByteStore, StorageLocation } from './types';
2
+ export declare class ByteStoreRegistry {
3
+ private readonly byteStores;
4
+ constructor(byteStores: Partial<Record<StorageLocation, ByteStore>>);
5
+ register(loc: StorageLocation, store: ByteStore): void;
6
+ has(loc: StorageLocation): boolean;
7
+ find(loc: StorageLocation): ByteStore | undefined;
8
+ get(loc: StorageLocation): ByteStore;
9
+ }
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ByteStoreRegistry = void 0;
4
+ const n8n_workflow_1 = require("n8n-workflow");
5
+ class ByteStoreRegistry {
6
+ constructor(byteStores) {
7
+ this.byteStores = new Map();
8
+ for (const [loc, store] of Object.entries(byteStores)) {
9
+ if (store)
10
+ this.byteStores.set(loc, store);
11
+ }
12
+ }
13
+ register(loc, store) {
14
+ this.byteStores.set(loc, store);
15
+ }
16
+ has(loc) {
17
+ return this.byteStores.has(loc);
18
+ }
19
+ find(loc) {
20
+ return this.byteStores.get(loc);
21
+ }
22
+ get(loc) {
23
+ const store = this.byteStores.get(loc);
24
+ if (!store) {
25
+ throw new n8n_workflow_1.UnexpectedError(`Byte store for location "${loc}" is not configured.`);
26
+ }
27
+ return store;
28
+ }
29
+ }
30
+ exports.ByteStoreRegistry = ByteStoreRegistry;
31
+ //# sourceMappingURL=byte-store-registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"byte-store-registry.js","sourceRoot":"","sources":["../src/byte-store-registry.ts"],"names":[],"mappings":";;;AAAA,+CAA+C;AAS/C;IAGC,YAAY,UAAuD;QAFlD,eAAU,GAAG,IAAI,GAAG,EAA8B,CAAC;QAGnE,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC;YACvD,IAAI,KAAK;gBAAE,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,GAAsB,EAAE,KAAK,CAAC,CAAC;QAC/D,CAAC;IACF,CAAC;IAED,QAAQ,CAAC,GAAoB,EAAE,KAAgB;QAC9C,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IACjC,CAAC;IAED,GAAG,CAAC,GAAoB;QACvB,OAAO,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACjC,CAAC;IAGD,IAAI,CAAC,GAAoB;QACxB,OAAO,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACjC,CAAC;IAGD,GAAG,CAAC,GAAoB;QACvB,MAAM,KAAK,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAEvC,IAAI,CAAC,KAAK,EAAE,CAAC;YACZ,MAAM,IAAI,8BAAe,CAAC,4BAA4B,GAAG,sBAAsB,CAAC,CAAC;QAClF,CAAC;QAED,OAAO,KAAK,CAAC;IACd,CAAC;CACD"}
@@ -0,0 +1,23 @@
1
+ import type { Readable } from 'node:stream';
2
+ import type { ByteStore, ByteStoreKey } from './types';
3
+ export type FsByteStoreOptions = {
4
+ storagePath: string;
5
+ reportError: (error: unknown) => void;
6
+ };
7
+ export declare class FsByteStore implements ByteStore {
8
+ private readonly options;
9
+ constructor(options: FsByteStoreOptions);
10
+ init(): Promise<void>;
11
+ write(key: ByteStoreKey, body: Buffer | Readable): Promise<number>;
12
+ read(key: ByteStoreKey): Promise<NonSharedBuffer | null>;
13
+ readStream(key: ByteStoreKey, { chunkSize }?: {
14
+ chunkSize?: number;
15
+ }): Promise<import("fs").ReadStream | null>;
16
+ copy(sourceKey: ByteStoreKey, targetKey: ByteStoreKey): Promise<void>;
17
+ rename(oldKey: ByteStoreKey, newKey: ByteStoreKey): Promise<void>;
18
+ deletePrefix(prefix: string): Promise<void>;
19
+ delete(keys: ByteStoreKey[]): Promise<void>;
20
+ getAbsolutePath(key: ByteStoreKey): string;
21
+ private removeEmptyAncestors;
22
+ private isFileNotFound;
23
+ }
@@ -0,0 +1,120 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.FsByteStore = void 0;
7
+ const backend_common_1 = require("@n8n/backend-common");
8
+ const n8n_workflow_1 = require("n8n-workflow");
9
+ const node_crypto_1 = require("node:crypto");
10
+ const promises_1 = __importDefault(require("node:fs/promises"));
11
+ const node_path_1 = __importDefault(require("node:path"));
12
+ const stream_utils_1 = require("./stream-utils");
13
+ class FsByteStore {
14
+ constructor(options) {
15
+ this.options = options;
16
+ }
17
+ async init() {
18
+ await (0, backend_common_1.assertDir)(this.options.storagePath);
19
+ }
20
+ async write(key, body) {
21
+ const writePath = this.getAbsolutePath(key);
22
+ await (0, backend_common_1.assertDir)(node_path_1.default.dirname(writePath));
23
+ const tempPath = `${writePath}.tmp.${process.pid}.${(0, node_crypto_1.randomUUID)()}`;
24
+ let success = false;
25
+ try {
26
+ await promises_1.default.writeFile(tempPath, body);
27
+ const bytesWritten = Buffer.isBuffer(body) ? body.length : (await promises_1.default.stat(tempPath)).size;
28
+ await promises_1.default.rename(tempPath, writePath);
29
+ success = true;
30
+ return bytesWritten;
31
+ }
32
+ finally {
33
+ if (!success) {
34
+ await promises_1.default.rm(tempPath, { force: true }).catch((error) => this.options.reportError(error));
35
+ }
36
+ }
37
+ }
38
+ async read(key) {
39
+ const readPath = this.getAbsolutePath(key);
40
+ try {
41
+ return await promises_1.default.readFile(readPath);
42
+ }
43
+ catch (error) {
44
+ if (this.isFileNotFound(error))
45
+ return null;
46
+ throw error;
47
+ }
48
+ }
49
+ async readStream(key, { chunkSize } = {}) {
50
+ if (chunkSize !== undefined)
51
+ (0, stream_utils_1.assertChunkSize)(chunkSize);
52
+ const readPath = this.getAbsolutePath(key);
53
+ let fileHandle;
54
+ try {
55
+ fileHandle = await promises_1.default.open(readPath, 'r');
56
+ }
57
+ catch (error) {
58
+ if (this.isFileNotFound(error))
59
+ return null;
60
+ throw error;
61
+ }
62
+ try {
63
+ return fileHandle.createReadStream(chunkSize ? { highWaterMark: chunkSize } : {});
64
+ }
65
+ catch (error) {
66
+ await fileHandle.close().catch(() => { });
67
+ throw error;
68
+ }
69
+ }
70
+ async copy(sourceKey, targetKey) {
71
+ const targetPath = this.getAbsolutePath(targetKey);
72
+ await (0, backend_common_1.assertDir)(node_path_1.default.dirname(targetPath));
73
+ await promises_1.default.copyFile(this.getAbsolutePath(sourceKey), targetPath);
74
+ }
75
+ async rename(oldKey, newKey) {
76
+ if (oldKey === newKey)
77
+ return;
78
+ const newPath = this.getAbsolutePath(newKey);
79
+ await (0, backend_common_1.assertDir)(node_path_1.default.dirname(newPath));
80
+ await promises_1.default.rename(this.getAbsolutePath(oldKey), newPath);
81
+ }
82
+ async deletePrefix(prefix) {
83
+ const dir = this.getAbsolutePath(prefix);
84
+ await promises_1.default.rm(dir, { recursive: true, force: true });
85
+ await this.removeEmptyAncestors(node_path_1.default.dirname(dir));
86
+ }
87
+ async delete(keys) {
88
+ const deletePaths = keys.map((key) => this.getAbsolutePath(key));
89
+ await Promise.all(deletePaths.map(async (p) => await promises_1.default.rm(p, { force: true })));
90
+ const dirs = [...new Set(deletePaths.map((p) => node_path_1.default.dirname(p)))];
91
+ await Promise.all(dirs.map(async (dir) => await this.removeEmptyAncestors(dir)));
92
+ }
93
+ getAbsolutePath(key) {
94
+ const storagePath = node_path_1.default.resolve(this.options.storagePath);
95
+ const resolvedPath = node_path_1.default.resolve(storagePath, key);
96
+ const relativePath = node_path_1.default.relative(storagePath, resolvedPath);
97
+ if (relativePath === '' || relativePath.startsWith('..') || node_path_1.default.isAbsolute(relativePath)) {
98
+ throw new n8n_workflow_1.UnexpectedError('Byte store key must resolve to a location inside the storage path');
99
+ }
100
+ return resolvedPath;
101
+ }
102
+ async removeEmptyAncestors(dir) {
103
+ const storagePath = node_path_1.default.resolve(this.options.storagePath);
104
+ let current = dir;
105
+ while (current.startsWith(storagePath) && current !== storagePath) {
106
+ try {
107
+ await promises_1.default.rmdir(current);
108
+ }
109
+ catch {
110
+ return;
111
+ }
112
+ current = node_path_1.default.dirname(current);
113
+ }
114
+ }
115
+ isFileNotFound(error) {
116
+ return (error !== null && typeof error === 'object' && 'code' in error && error.code === 'ENOENT');
117
+ }
118
+ }
119
+ exports.FsByteStore = FsByteStore;
120
+ //# sourceMappingURL=fs-byte-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fs-byte-store.js","sourceRoot":"","sources":["../src/fs-byte-store.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,4 +1,10 @@
1
- export type { BlobMetadata, PreWriteBlobMetadata } from './types';
1
+ export type { BlobMetadata, PreWriteBlobMetadata, ByteStore, ByteStoreKey, StorageLocation, JsonEntry, Stored, JsonStoreOptions, } from './types';
2
+ export { ByteStoreRegistry } from './byte-store-registry';
3
+ export { FsByteStore, type FsByteStoreOptions } from './fs-byte-store';
4
+ export { S3ByteStore } from './s3-byte-store.ee';
5
+ export { AzureByteStore } from './azure-byte-store.ee';
6
+ export { JsonStore } from './json-store';
7
+ export { SkippedEntryDeletionError } from './skipped-entry-deletion.error';
2
8
  export { createFixedSizeChunker } from './stream-utils';
3
9
  export { ObjectStoreConfig } from './object-store/object-store.config';
4
10
  export type { MetadataResponseHeaders } from './object-store/types';
package/dist/index.js CHANGED
@@ -1,6 +1,18 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.AzureBlobConfig = exports.ObjectStoreConfig = exports.createFixedSizeChunker = void 0;
3
+ exports.AzureBlobConfig = exports.ObjectStoreConfig = exports.createFixedSizeChunker = exports.SkippedEntryDeletionError = exports.JsonStore = exports.AzureByteStore = exports.S3ByteStore = exports.FsByteStore = exports.ByteStoreRegistry = void 0;
4
+ var byte_store_registry_1 = require("./byte-store-registry");
5
+ Object.defineProperty(exports, "ByteStoreRegistry", { enumerable: true, get: function () { return byte_store_registry_1.ByteStoreRegistry; } });
6
+ var fs_byte_store_1 = require("./fs-byte-store");
7
+ Object.defineProperty(exports, "FsByteStore", { enumerable: true, get: function () { return fs_byte_store_1.FsByteStore; } });
8
+ var s3_byte_store_ee_1 = require("./s3-byte-store.ee");
9
+ Object.defineProperty(exports, "S3ByteStore", { enumerable: true, get: function () { return s3_byte_store_ee_1.S3ByteStore; } });
10
+ var azure_byte_store_ee_1 = require("./azure-byte-store.ee");
11
+ Object.defineProperty(exports, "AzureByteStore", { enumerable: true, get: function () { return azure_byte_store_ee_1.AzureByteStore; } });
12
+ var json_store_1 = require("./json-store");
13
+ Object.defineProperty(exports, "JsonStore", { enumerable: true, get: function () { return json_store_1.JsonStore; } });
14
+ var skipped_entry_deletion_error_1 = require("./skipped-entry-deletion.error");
15
+ Object.defineProperty(exports, "SkippedEntryDeletionError", { enumerable: true, get: function () { return skipped_entry_deletion_error_1.SkippedEntryDeletionError; } });
4
16
  var stream_utils_1 = require("./stream-utils");
5
17
  Object.defineProperty(exports, "createFixedSizeChunker", { enumerable: true, get: function () { return stream_utils_1.createFixedSizeChunker; } });
6
18
  var object_store_config_1 = require("./object-store/object-store.config");
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AACA,+CAAwD;AAA/C,sHAAA,sBAAsB,OAAA;AAC/B,0EAAuE;AAA9D,wHAAA,iBAAiB,OAAA;AAE1B,oEAAiE;AAAxD,oHAAA,eAAe,OAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAUA,6DAA0D;AAAjD,wHAAA,iBAAiB,OAAA;AAC1B,iDAAuE;AAA9D,4GAAA,WAAW,OAAA;AACpB,uDAAiD;AAAxC,+GAAA,WAAW,OAAA;AACpB,6DAAuD;AAA9C,qHAAA,cAAc,OAAA;AACvB,2CAAyC;AAAhC,uGAAA,SAAS,OAAA;AAClB,+EAA2E;AAAlE,yIAAA,yBAAyB,OAAA;AAClC,+CAAwD;AAA/C,sHAAA,sBAAsB,OAAA;AAC/B,0EAAuE;AAA9D,wHAAA,iBAAiB,OAAA;AAE1B,oEAAiE;AAAxD,oHAAA,eAAe,OAAA"}
@@ -0,0 +1,17 @@
1
+ import type { ByteStore, JsonEntry, JsonStoreOptions, StorageLocation, Stored } from './types';
2
+ export declare class JsonStore<Ref, Payload extends object> {
3
+ private readonly options;
4
+ private readonly byteStores;
5
+ constructor(options: JsonStoreOptions<Ref>);
6
+ registerByteStore(loc: StorageLocation, store: ByteStore): void;
7
+ hasLocation(loc: StorageLocation): boolean;
8
+ write(ref: Ref, payload: Payload, loc: StorageLocation): Promise<number>;
9
+ read(ref: Ref, loc: StorageLocation): Promise<JsonEntry<Payload> | null>;
10
+ readMany(refs: Array<Stored<Ref>>): Promise<Map<string, JsonEntry<Payload>>>;
11
+ delete(refs: Array<Stored<Ref>>): Promise<void>;
12
+ private groupByLocation;
13
+ private tryRead;
14
+ private parse;
15
+ private markCorrupt;
16
+ private isCorruptEntryError;
17
+ }
@@ -0,0 +1,118 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.JsonStore = void 0;
7
+ const chunk_1 = __importDefault(require("lodash/chunk"));
8
+ const n8n_workflow_1 = require("n8n-workflow");
9
+ const byte_store_registry_1 = require("./byte-store-registry");
10
+ const skipped_entry_deletion_error_1 = require("./skipped-entry-deletion.error");
11
+ const CORRUPT_ENTRY = Symbol('corruptEntry');
12
+ const MAX_READ_CONCURRENCY = 50;
13
+ class JsonStore {
14
+ constructor(options) {
15
+ this.options = options;
16
+ this.byteStores = new byte_store_registry_1.ByteStoreRegistry(options.byteStores);
17
+ }
18
+ registerByteStore(loc, store) {
19
+ this.byteStores.register(loc, store);
20
+ }
21
+ hasLocation(loc) {
22
+ return this.byteStores.has(loc);
23
+ }
24
+ async write(ref, payload, loc) {
25
+ const store = this.byteStores.get(loc);
26
+ if ('version' in payload) {
27
+ throw new n8n_workflow_1.UnexpectedError('Payload must not contain the reserved `version` key.');
28
+ }
29
+ try {
30
+ const body = Buffer.from((0, n8n_workflow_1.jsonStringify)({ ...payload, version: this.options.version }), 'utf-8');
31
+ return await store.write(this.options.key(ref), body, { mimeType: 'application/json' });
32
+ }
33
+ catch (error) {
34
+ throw this.options.createWriteError(ref, error);
35
+ }
36
+ }
37
+ async read(ref, loc) {
38
+ const store = this.byteStores.get(loc);
39
+ const key = this.options.key(ref);
40
+ const bytes = await store.read(key);
41
+ if (!bytes)
42
+ return null;
43
+ return this.parse(ref, bytes);
44
+ }
45
+ async readMany(refs) {
46
+ const entries = new Map();
47
+ if (refs.length === 0)
48
+ return entries;
49
+ await Promise.all([...this.groupByLocation(refs)].map(async ([loc, group]) => {
50
+ const store = this.byteStores.get(loc);
51
+ for (const batch of (0, chunk_1.default)(group, MAX_READ_CONCURRENCY)) {
52
+ const results = await Promise.all(batch.map(async (ref) => await this.tryRead(ref, store)));
53
+ results.forEach((entry, idx) => {
54
+ if (entry)
55
+ entries.set(this.options.getId(batch[idx]), entry);
56
+ });
57
+ }
58
+ }));
59
+ return entries;
60
+ }
61
+ async delete(refs) {
62
+ if (refs.length === 0)
63
+ return;
64
+ await Promise.all([...this.groupByLocation(refs)].map(async ([loc, group]) => {
65
+ const store = this.byteStores.find(loc);
66
+ if (!store) {
67
+ this.options.reportError(new skipped_entry_deletion_error_1.SkippedEntryDeletionError(loc, group.length));
68
+ return;
69
+ }
70
+ await store.delete(group.map((ref) => this.options.key(ref)));
71
+ }));
72
+ }
73
+ groupByLocation(refs) {
74
+ const groups = new Map();
75
+ for (const ref of refs) {
76
+ const group = groups.get(ref.storedAt) ?? [];
77
+ group.push(ref);
78
+ groups.set(ref.storedAt, group);
79
+ }
80
+ return groups;
81
+ }
82
+ async tryRead(ref, store) {
83
+ try {
84
+ const bytes = await store.read(this.options.key(ref));
85
+ if (!bytes)
86
+ return null;
87
+ return this.parse(ref, bytes);
88
+ }
89
+ catch (error) {
90
+ if (this.isCorruptEntryError(error)) {
91
+ this.options.reportError(error);
92
+ return null;
93
+ }
94
+ throw error;
95
+ }
96
+ }
97
+ parse(ref, bytes) {
98
+ try {
99
+ const entry = (0, n8n_workflow_1.jsonParse)(bytes.toString('utf-8'));
100
+ if (entry.version !== this.options.version) {
101
+ throw new Error(`Unsupported entry version: ${String(entry.version)}`);
102
+ }
103
+ return entry;
104
+ }
105
+ catch (error) {
106
+ throw this.markCorrupt(this.options.createCorruptedError(ref, error));
107
+ }
108
+ }
109
+ markCorrupt(error) {
110
+ Object.defineProperty(error, CORRUPT_ENTRY, { value: true });
111
+ return error;
112
+ }
113
+ isCorruptEntryError(error) {
114
+ return error instanceof Error && CORRUPT_ENTRY in error;
115
+ }
116
+ }
117
+ exports.JsonStore = JsonStore;
118
+ //# sourceMappingURL=json-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json-store.js","sourceRoot":"","sources":["../src/json-store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ import type { Readable } from 'node:stream';
2
+ import type { ObjectStoreService } from './object-store/object-store.service.ee';
3
+ import type { BlobMetadata, ByteStore, ByteStoreKey, PreWriteBlobMetadata } from './types';
4
+ export declare class S3ByteStore implements ByteStore {
5
+ private readonly objectStore;
6
+ constructor(objectStore: ObjectStoreService);
7
+ write(key: ByteStoreKey, body: Buffer | Readable, metadata?: PreWriteBlobMetadata): Promise<number>;
8
+ read(key: ByteStoreKey): Promise<Buffer<ArrayBufferLike> | null>;
9
+ readStream(key: ByteStoreKey, { chunkSize }?: {
10
+ chunkSize?: number;
11
+ }): Promise<Readable | null>;
12
+ copy(sourceKey: ByteStoreKey, targetKey: ByteStoreKey): Promise<void>;
13
+ rename(oldKey: ByteStoreKey, newKey: ByteStoreKey): Promise<void>;
14
+ delete(keys: ByteStoreKey[]): Promise<void>;
15
+ getMetadata(key: ByteStoreKey): Promise<BlobMetadata | null>;
16
+ private readNativeMetadata;
17
+ private isNoSuchKey;
18
+ private isHeadNotFound;
19
+ private errorName;
20
+ }
@@ -0,0 +1,95 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.S3ByteStore = void 0;
4
+ const backend_network_1 = require("@n8n/backend-network");
5
+ const ensure_error_1 = require("@n8n/utils/errors/ensure-error");
6
+ const stream_utils_1 = require("./stream-utils");
7
+ class S3ByteStore {
8
+ constructor(objectStore) {
9
+ this.objectStore = objectStore;
10
+ }
11
+ async write(key, body, metadata = {}) {
12
+ const buffer = Buffer.isBuffer(body) ? body : await (0, backend_network_1.binaryToBuffer)(body);
13
+ await this.objectStore.put(key, buffer, {
14
+ ...metadata,
15
+ mimeType: metadata.mimeType ?? 'application/octet-stream',
16
+ });
17
+ return buffer.length;
18
+ }
19
+ async read(key) {
20
+ try {
21
+ return await this.objectStore.get(key, { mode: 'buffer' });
22
+ }
23
+ catch (error) {
24
+ if (this.isNoSuchKey(error))
25
+ return null;
26
+ throw error;
27
+ }
28
+ }
29
+ async readStream(key, { chunkSize } = {}) {
30
+ if (chunkSize !== undefined)
31
+ (0, stream_utils_1.assertChunkSize)(chunkSize);
32
+ try {
33
+ return await this.objectStore.get(key, { mode: 'stream', chunkSize });
34
+ }
35
+ catch (error) {
36
+ if (this.isNoSuchKey(error))
37
+ return null;
38
+ throw error;
39
+ }
40
+ }
41
+ async copy(sourceKey, targetKey) {
42
+ const buffer = await this.objectStore.get(sourceKey, { mode: 'buffer' });
43
+ await this.objectStore.put(targetKey, buffer, await this.readNativeMetadata(sourceKey));
44
+ }
45
+ async rename(oldKey, newKey) {
46
+ if (oldKey === newKey)
47
+ return;
48
+ await this.copy(oldKey, newKey);
49
+ await this.objectStore.deleteOne(oldKey);
50
+ }
51
+ async delete(keys) {
52
+ if (keys.length === 0)
53
+ return;
54
+ await this.objectStore.deleteByKeys(keys);
55
+ }
56
+ async getMetadata(key) {
57
+ try {
58
+ const headers = await this.objectStore.getMetadata(key);
59
+ const metadata = { fileSize: Number(headers['content-length'] ?? 0) };
60
+ if (headers['content-type'])
61
+ metadata.mimeType = headers['content-type'];
62
+ if (headers['x-amz-meta-filename'])
63
+ metadata.fileName = headers['x-amz-meta-filename'];
64
+ return metadata;
65
+ }
66
+ catch (error) {
67
+ if (this.isHeadNotFound(error))
68
+ return null;
69
+ throw error;
70
+ }
71
+ }
72
+ async readNativeMetadata(key) {
73
+ const headers = await this.objectStore.getMetadata(key);
74
+ const metadata = {};
75
+ if (headers['content-type'])
76
+ metadata.mimeType = headers['content-type'];
77
+ if (headers['x-amz-meta-filename'])
78
+ metadata.fileName = headers['x-amz-meta-filename'];
79
+ return metadata;
80
+ }
81
+ isNoSuchKey(error) {
82
+ return this.errorName(error) === 'NoSuchKey';
83
+ }
84
+ isHeadNotFound(error) {
85
+ return this.errorName(error) === 'NotFound';
86
+ }
87
+ errorName(error) {
88
+ const original = (0, ensure_error_1.ensureError)(error).cause ?? error;
89
+ if (typeof original !== 'object' || original === null)
90
+ return undefined;
91
+ return 'name' in original ? original.name : undefined;
92
+ }
93
+ }
94
+ exports.S3ByteStore = S3ByteStore;
95
+ //# sourceMappingURL=s3-byte-store.ee.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"s3-byte-store.ee.js","sourceRoot":"","sources":["../src/s3-byte-store.ee.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import { OperationalError } from 'n8n-workflow';
2
+ import type { StorageLocation } from './types';
3
+ export declare class SkippedEntryDeletionError extends OperationalError {
4
+ constructor(loc: StorageLocation, count: number);
5
+ }
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SkippedEntryDeletionError = void 0;
4
+ const n8n_workflow_1 = require("n8n-workflow");
5
+ class SkippedEntryDeletionError extends n8n_workflow_1.OperationalError {
6
+ constructor(loc, count) {
7
+ super(`Skipped deleting entries - "${loc}" store is not configured`, {
8
+ extra: { count },
9
+ });
10
+ }
11
+ }
12
+ exports.SkippedEntryDeletionError = SkippedEntryDeletionError;
13
+ //# sourceMappingURL=skipped-entry-deletion.error.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skipped-entry-deletion.error.js","sourceRoot":"","sources":["../src/skipped-entry-deletion.error.ts"],"names":[],"mappings":";;;AAAA,+CAAgD;AAIhD,+BAAuC,SAAQ,+BAAgB;IAC9D,YAAY,GAAoB,EAAE,KAAa;QAC9C,KAAK,CAAC,+BAA+B,GAAG,2BAA2B,EAAE;YACpE,KAAK,EAAE,EAAE,KAAK,EAAE;SAChB,CAAC,CAAC;IACJ,CAAC;CACD"}
@@ -1,2 +1,3 @@
1
1
  import { Transform } from 'node:stream';
2
+ export declare function assertChunkSize(chunkSize: number): void;
2
3
  export declare function createFixedSizeChunker(chunkSize: number): Transform;
@@ -1,12 +1,16 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.assertChunkSize = assertChunkSize;
3
4
  exports.createFixedSizeChunker = createFixedSizeChunker;
4
5
  const n8n_workflow_1 = require("n8n-workflow");
5
6
  const node_stream_1 = require("node:stream");
6
- function createFixedSizeChunker(chunkSize) {
7
- if (chunkSize <= 0) {
8
- throw new n8n_workflow_1.UnexpectedError(`createFixedSizeChunker requires chunkSize > 0, got ${chunkSize}`);
7
+ function assertChunkSize(chunkSize) {
8
+ if (!Number.isInteger(chunkSize) || chunkSize <= 0) {
9
+ throw new n8n_workflow_1.UnexpectedError(`chunkSize must be a positive integer, got ${chunkSize}`);
9
10
  }
11
+ }
12
+ function createFixedSizeChunker(chunkSize) {
13
+ assertChunkSize(chunkSize);
10
14
  const queue = [];
11
15
  let queued = 0;
12
16
  const take = (size) => {
@@ -1 +1 @@
1
- {"version":3,"file":"stream-utils.js","sourceRoot":"","sources":["../src/stream-utils.ts"],"names":[],"mappings":";;;AAAA,+CAA+C;AAC/C,6CAAwC;AAcxC,gCAAuC,SAAiB;IACvD,IAAI,SAAS,IAAI,CAAC,EAAE,CAAC;QACpB,MAAM,IAAI,8BAAe,CAAC,sDAAsD,SAAS,EAAE,CAAC,CAAC;IAC9F,CAAC;IAED,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,IAAI,MAAM,GAAG,CAAC,CAAC;IAEf,MAAM,IAAI,GAAG,CAAC,IAAY,EAAU,EAAE;QACrC,MAAM,GAAG,GAAG,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;QACrC,IAAI,OAAO,GAAG,CAAC,CAAC;QAChB,OAAO,OAAO,GAAG,IAAI,EAAE,CAAC;YACvB,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;YACtB,MAAM,IAAI,GAAG,IAAI,GAAG,OAAO,CAAC;YAC5B,IAAI,IAAI,CAAC,MAAM,IAAI,IAAI,EAAE,CAAC;gBACzB,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;gBACxB,OAAO,IAAI,IAAI,CAAC,MAAM,CAAC;gBACvB,KAAK,CAAC,KAAK,EAAE,CAAC;YACf,CAAC;iBAAM,CAAC;gBACP,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC;gBACjC,KAAK,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;gBAC/B,OAAO,IAAI,IAAI,CAAC;YACjB,CAAC;QACF,CAAC;QACD,MAAM,IAAI,IAAI,CAAC;QACf,OAAO,GAAG,CAAC;IACZ,CAAC,CAAC;IAEF,OAAO,IAAI,uBAAS,CAAC;QACpB,SAAS,CAAC,KAAa,EAAE,SAAS,EAAE,IAAI;YACvC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAClB,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC;YACvB,OAAO,MAAM,IAAI,SAAS,EAAE,CAAC;gBAC5B,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC;YAC5B,CAAC;YACD,IAAI,EAAE,CAAC;QACR,CAAC;QACD,KAAK,CAAC,IAAI;YACT,IAAI,MAAM,GAAG,CAAC,EAAE,CAAC;gBAChB,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;YACzB,CAAC;YACD,IAAI,EAAE,CAAC;QACR,CAAC;QACD,OAAO,CAAC,KAAK,EAAE,IAAI;YAClB,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC;YACjB,MAAM,GAAG,CAAC,CAAC;YACX,IAAI,CAAC,KAAK,CAAC,CAAC;QACb,CAAC;KACD,CAAC,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"stream-utils.js","sourceRoot":"","sources":["../src/stream-utils.ts"],"names":[],"mappings":";;;;AAAA,+CAA+C;AAC/C,6CAAwC;AAGxC,yBAAgC,SAAiB;IAChD,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,SAAS,CAAC,IAAI,SAAS,IAAI,CAAC,EAAE,CAAC;QACpD,MAAM,IAAI,8BAAe,CAAC,6CAA6C,SAAS,EAAE,CAAC,CAAC;IACrF,CAAC;AACF,CAAC;AAcD,gCAAuC,SAAiB;IACvD,eAAe,CAAC,SAAS,CAAC,CAAC;IAE3B,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,IAAI,MAAM,GAAG,CAAC,CAAC;IAEf,MAAM,IAAI,GAAG,CAAC,IAAY,EAAU,EAAE;QACrC,MAAM,GAAG,GAAG,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;QACrC,IAAI,OAAO,GAAG,CAAC,CAAC;QAChB,OAAO,OAAO,GAAG,IAAI,EAAE,CAAC;YACvB,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;YACtB,MAAM,IAAI,GAAG,IAAI,GAAG,OAAO,CAAC;YAC5B,IAAI,IAAI,CAAC,MAAM,IAAI,IAAI,EAAE,CAAC;gBACzB,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;gBACxB,OAAO,IAAI,IAAI,CAAC,MAAM,CAAC;gBACvB,KAAK,CAAC,KAAK,EAAE,CAAC;YACf,CAAC;iBAAM,CAAC;gBACP,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC;gBACjC,KAAK,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;gBAC/B,OAAO,IAAI,IAAI,CAAC;YACjB,CAAC;QACF,CAAC;QACD,MAAM,IAAI,IAAI,CAAC;QACf,OAAO,GAAG,CAAC;IACZ,CAAC,CAAC;IAEF,OAAO,IAAI,uBAAS,CAAC;QACpB,SAAS,CAAC,KAAa,EAAE,SAAS,EAAE,IAAI;YACvC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAClB,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC;YACvB,OAAO,MAAM,IAAI,SAAS,EAAE,CAAC;gBAC5B,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC;YAC5B,CAAC;YACD,IAAI,EAAE,CAAC;QACR,CAAC;QACD,KAAK,CAAC,IAAI;YACT,IAAI,MAAM,GAAG,CAAC,EAAE,CAAC;gBAChB,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;YACzB,CAAC;YACD,IAAI,EAAE,CAAC;QACR,CAAC;QACD,OAAO,CAAC,KAAK,EAAE,IAAI;YAClB,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC;YACjB,MAAM,GAAG,CAAC,CAAC;YACX,IAAI,CAAC,KAAK,CAAC,CAAC;QACb,CAAC;KACD,CAAC,CAAC;AACJ,CAAC"}
package/dist/types.d.ts CHANGED
@@ -1,6 +1,38 @@
1
+ import type { Readable } from 'node:stream';
1
2
  export type BlobMetadata = {
2
3
  fileName?: string;
3
4
  mimeType?: string;
4
5
  fileSize: number;
5
6
  };
6
7
  export type PreWriteBlobMetadata = Omit<BlobMetadata, 'fileSize'>;
8
+ export type StorageLocation = 'fs' | 's3' | 'az';
9
+ export type ByteStoreKey = string;
10
+ export interface ByteStore {
11
+ init?(): Promise<void>;
12
+ write(key: ByteStoreKey, body: Buffer | Readable, metadata?: PreWriteBlobMetadata): Promise<number>;
13
+ read(key: ByteStoreKey): Promise<Buffer | null>;
14
+ readStream(key: ByteStoreKey, opts?: {
15
+ chunkSize?: number;
16
+ }): Promise<Readable | null>;
17
+ copy(sourceKey: ByteStoreKey, targetKey: ByteStoreKey): Promise<void>;
18
+ rename(oldKey: ByteStoreKey, newKey: ByteStoreKey): Promise<void>;
19
+ delete(keys: ByteStoreKey[]): Promise<void>;
20
+ getMetadata?(key: ByteStoreKey): Promise<BlobMetadata | null>;
21
+ getAbsolutePath?(key: ByteStoreKey): string;
22
+ deletePrefix?(prefix: string): Promise<void>;
23
+ }
24
+ export type JsonEntry<Payload extends object> = Payload & {
25
+ version: number;
26
+ };
27
+ export type Stored<Ref> = Ref & {
28
+ storedAt: StorageLocation;
29
+ };
30
+ export interface JsonStoreOptions<Ref> {
31
+ byteStores: Partial<Record<StorageLocation, ByteStore>>;
32
+ version: number;
33
+ key: (ref: Ref) => string;
34
+ getId: (ref: Ref) => string;
35
+ createWriteError: (ref: Ref, cause: unknown) => Error;
36
+ createCorruptedError: (ref: Ref, cause: unknown) => Error;
37
+ reportError: (error: unknown) => void;
38
+ }