@strapi/data-transfer 5.53.0 → 5.55.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/directory/providers/destination/index.d.ts.map +1 -1
- package/dist/directory/providers/destination/index.js +11 -1
- package/dist/directory/providers/destination/index.js.map +1 -1
- package/dist/directory/providers/destination/index.mjs +11 -1
- package/dist/directory/providers/destination/index.mjs.map +1 -1
- package/dist/directory/providers/source/index.d.ts +2 -1
- package/dist/directory/providers/source/index.d.ts.map +1 -1
- package/dist/directory/providers/source/index.js +45 -12
- package/dist/directory/providers/source/index.js.map +1 -1
- package/dist/directory/providers/source/index.mjs +47 -14
- package/dist/directory/providers/source/index.mjs.map +1 -1
- package/dist/engine/index.d.ts +1 -0
- package/dist/engine/index.d.ts.map +1 -1
- package/dist/engine/index.js +62 -5
- package/dist/engine/index.js.map +1 -1
- package/dist/engine/index.mjs +62 -5
- package/dist/engine/index.mjs.map +1 -1
- package/dist/file/providers/destination/index.d.ts.map +1 -1
- package/dist/file/providers/destination/index.js +11 -1
- package/dist/file/providers/destination/index.js.map +1 -1
- package/dist/file/providers/destination/index.mjs +11 -1
- package/dist/file/providers/destination/index.mjs.map +1 -1
- package/dist/file/providers/source/index.d.ts +2 -1
- package/dist/file/providers/source/index.d.ts.map +1 -1
- package/dist/file/providers/source/index.js +97 -8
- package/dist/file/providers/source/index.js.map +1 -1
- package/dist/file/providers/source/index.mjs +100 -11
- package/dist/file/providers/source/index.mjs.map +1 -1
- package/dist/file/providers/source/utils.d.ts +2 -0
- package/dist/file/providers/source/utils.d.ts.map +1 -1
- package/dist/file/providers/source/utils.js +43 -0
- package/dist/file/providers/source/utils.js.map +1 -1
- package/dist/file/providers/source/utils.mjs +43 -1
- package/dist/file/providers/source/utils.mjs.map +1 -1
- package/dist/strapi/providers/local-source/assets.js +2 -2
- package/dist/strapi/providers/local-source/assets.js.map +1 -1
- package/dist/strapi/providers/local-source/assets.mjs +2 -2
- package/dist/strapi/providers/local-source/assets.mjs.map +1 -1
- package/dist/types/providers.d.ts +10 -0
- package/dist/types/providers.d.ts.map +1 -1
- package/package.json +6 -6
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","sources":["../../../../src/file/providers/destination/index.ts"],"sourcesContent":["import path from 'path';\nimport zlib from 'zlib';\nimport { Readable, Writable } from 'stream';\nimport { rm, createWriteStream } from 'fs-extra';\nimport tar from 'tar-stream';\nimport { stringer } from 'stream-json/jsonl/Stringer';\nimport { chain } from 'stream-chain';\n\nimport { createEncryptionCipher } from '../../../utils/encryption';\nimport type {\n IAsset,\n IDestinationProvider,\n IDestinationProviderTransferResults,\n IMetadata,\n ProviderType,\n Stream,\n} from '../../../types';\nimport type { IDiagnosticReporter } from '../../../utils/diagnostic';\nimport { createFilePathFactory, createTarEntryStream } from './utils';\nimport { ProviderTransferError } from '../../../errors/providers';\n\nexport interface ILocalFileDestinationProviderOptions {\n encryption: {\n enabled: boolean; // if the file should be encrypted\n key?: string; // the key to use when encryption.enabled is true\n };\n\n compression: {\n enabled: boolean; // if the file should be compressed with gzip\n };\n\n file: {\n path: string; // the filename to create\n maxSize?: number; // the max size of a single backup file\n maxSizeJsonl?: number; // the max lines of each jsonl file before creating the next file\n };\n}\n\nexport interface ILocalFileDestinationProviderTransferResults\n extends IDestinationProviderTransferResults {\n file?: {\n path?: string;\n };\n}\n\nexport const createLocalFileDestinationProvider = (\n options: ILocalFileDestinationProviderOptions\n) => {\n return new LocalFileDestinationProvider(options);\n};\n\nclass LocalFileDestinationProvider implements IDestinationProvider {\n name = 'destination::local-file';\n\n type: ProviderType = 'destination';\n\n options: ILocalFileDestinationProviderOptions;\n\n results: ILocalFileDestinationProviderTransferResults = {};\n\n #providersMetadata: { source?: IMetadata; destination?: IMetadata } = {};\n\n #archive: { stream?: tar.Pack; pipeline?: Stream } = {};\n\n #diagnostics?: IDiagnosticReporter;\n\n constructor(options: ILocalFileDestinationProviderOptions) {\n this.options = options;\n }\n\n #reportInfo(message: string) {\n this.#diagnostics?.report({\n details: {\n createdAt: new Date(),\n message,\n origin: 'file-destination-provider',\n },\n kind: 'info',\n });\n }\n\n get #archivePath() {\n const { encryption, compression, file } = this.options;\n\n let filePath = `${file.path}.tar`;\n\n if (compression.enabled) {\n filePath += '.gz';\n }\n\n if (encryption.enabled) {\n filePath += '.enc';\n }\n\n return filePath;\n }\n\n setMetadata(target: ProviderType, metadata: IMetadata): IDestinationProvider {\n this.#providersMetadata[target] = metadata;\n\n return this;\n }\n\n createGzip(): zlib.Gzip {\n this.#reportInfo('creating gzip');\n return zlib.createGzip();\n }\n\n bootstrap(diagnostics: IDiagnosticReporter): void | Promise<void> {\n this.#diagnostics = diagnostics;\n const { compression, encryption } = this.options;\n\n if (encryption.enabled && !encryption.key) {\n throw new Error(\"Can't encrypt without a key\");\n }\n\n this.#archive.stream = tar.pack();\n\n const outStream = createWriteStream(this.#archivePath);\n\n outStream.on('error', (err: NodeJS.ErrnoException) => {\n if (err.code === 'ENOSPC') {\n throw new ProviderTransferError(\n \"Your server doesn't have space to proceed with the import.\"\n );\n }\n throw err;\n });\n\n const archiveTransforms: Stream[] = [];\n\n if (compression.enabled) {\n archiveTransforms.push(this.createGzip());\n }\n\n if (encryption.enabled && encryption.key) {\n archiveTransforms.push(createEncryptionCipher(encryption.key));\n }\n\n this.#archive.pipeline = chain([this.#archive.stream, ...archiveTransforms, outStream]);\n\n this.results.file = { path: this.#archivePath };\n }\n\n async close() {\n const { stream, pipeline } = this.#archive;\n\n if (!stream) {\n return;\n }\n\n await this.#writeMetadata();\n stream.finalize();\n\n if (pipeline && !pipeline.closed) {\n await new Promise<void>((resolve, reject) => {\n pipeline.on('close', resolve).on('error', reject);\n });\n }\n }\n\n async rollback(): Promise<void> {\n this.#reportInfo('rolling back');\n await this.close();\n await rm(this.#archivePath, { force: true });\n }\n\n getMetadata() {\n return null;\n }\n\n async #writeMetadata(): Promise<void> {\n this.#reportInfo('writing metadata');\n const metadata = this.#providersMetadata.source;\n\n if (metadata) {\n await new Promise((resolve) => {\n const outStream = this.#getMetadataStream();\n const data = JSON.stringify(metadata, null, 2);\n\n Readable.from(data).pipe(outStream).on('close', resolve);\n });\n }\n }\n\n #getMetadataStream() {\n const { stream } = this.#archive;\n\n if (!stream) {\n throw new Error('Archive stream is unavailable');\n }\n\n return createTarEntryStream(stream, () => 'metadata.json');\n }\n\n createSchemasWriteStream() {\n if (!this.#archive.stream) {\n throw new Error('Archive stream is unavailable');\n }\n this.#reportInfo('creating schemas write stream');\n const filePathFactory = createFilePathFactory('schemas');\n\n const entryStream = createTarEntryStream(\n this.#archive.stream,\n filePathFactory,\n this.options.file.maxSizeJsonl\n );\n\n return chain([stringer(), entryStream]);\n }\n\n createEntitiesWriteStream(): Writable {\n if (!this.#archive.stream) {\n throw new Error('Archive stream is unavailable');\n }\n this.#reportInfo('creating entities write stream');\n const filePathFactory = createFilePathFactory('entities');\n\n const entryStream = createTarEntryStream(\n this.#archive.stream,\n filePathFactory,\n this.options.file.maxSizeJsonl\n );\n\n return chain([stringer(), entryStream]);\n }\n\n createLinksWriteStream(): Writable {\n if (!this.#archive.stream) {\n throw new Error('Archive stream is unavailable');\n }\n this.#reportInfo('creating links write stream');\n const filePathFactory = createFilePathFactory('links');\n\n const entryStream = createTarEntryStream(\n this.#archive.stream,\n filePathFactory,\n this.options.file.maxSizeJsonl\n );\n\n return chain([stringer(), entryStream]);\n }\n\n createConfigurationWriteStream(): Writable {\n if (!this.#archive.stream) {\n throw new Error('Archive stream is unavailable');\n }\n this.#reportInfo('creating configuration write stream');\n const filePathFactory = createFilePathFactory('configuration');\n\n const entryStream = createTarEntryStream(\n this.#archive.stream,\n filePathFactory,\n this.options.file.maxSizeJsonl\n );\n\n return chain([stringer(), entryStream]);\n }\n\n createAssetsWriteStream(): Writable {\n const { stream: archiveStream } = this.#archive;\n\n if (!archiveStream) {\n throw new Error('Archive stream is unavailable');\n }\n\n this.#reportInfo('creating assets write stream');\n return new Writable({\n objectMode: true,\n write(data: IAsset, _encoding, callback) {\n // always write tar files with posix paths so we have a standard format for paths regardless of system\n const entryPath = path.posix.join('assets', 'uploads', data.filename);\n\n const entryMetadataPath = path.posix.join('assets', 'metadata', `${data.filename}.json`);\n const stringifiedMetadata = JSON.stringify(data.metadata);\n archiveStream.entry(\n {\n name: entryMetadataPath,\n size: stringifiedMetadata.length,\n },\n stringifiedMetadata\n );\n\n const entry = archiveStream.entry({\n name: entryPath,\n size: data.stats.size,\n });\n\n if (!entry) {\n callback(new Error(`Failed to created an asset tar entry for ${entryPath}`));\n return;\n }\n\n data.stream.pipe(entry);\n\n entry\n .on('finish', () => {\n callback(null);\n })\n .on('error', (error) => {\n callback(error);\n });\n },\n });\n }\n}\n"],"names":["createLocalFileDestinationProvider","options","LocalFileDestinationProvider","setMetadata","target","metadata","createGzip","zlib","bootstrap","diagnostics","compression","encryption","enabled","key","Error","stream","tar","pack","outStream","createWriteStream","on","err","code","ProviderTransferError","archiveTransforms","push","createEncryptionCipher","pipeline","chain","results","file","path","close","finalize","closed","Promise","resolve","reject","rollback","rm","force","getMetadata","createSchemasWriteStream","filePathFactory","createFilePathFactory","entryStream","createTarEntryStream","maxSizeJsonl","stringer","createEntitiesWriteStream","createLinksWriteStream","createConfigurationWriteStream","createAssetsWriteStream","archiveStream","Writable","objectMode","write","data","_encoding","callback","entryPath","posix","join","filename","entryMetadataPath","stringifiedMetadata","JSON","stringify","entry","name","size","length","stats","pipe","error","type","message","report","details","createdAt","Date","origin","kind","filePath","source","Readable","from"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","sources":["../../../../src/file/providers/destination/index.ts"],"sourcesContent":["import path from 'path';\nimport zlib from 'zlib';\nimport { Readable, Writable } from 'stream';\nimport { rm, createWriteStream } from 'fs-extra';\nimport tar from 'tar-stream';\nimport { stringer } from 'stream-json/jsonl/Stringer';\nimport { chain } from 'stream-chain';\n\nimport { createEncryptionCipher } from '../../../utils/encryption';\nimport type {\n IAsset,\n IDestinationProvider,\n IDestinationProviderTransferResults,\n IMetadata,\n ProviderType,\n Stream,\n} from '../../../types';\nimport type { IDiagnosticReporter } from '../../../utils/diagnostic';\nimport { createFilePathFactory, createTarEntryStream } from './utils';\nimport { ProviderTransferError } from '../../../errors/providers';\n\nexport interface ILocalFileDestinationProviderOptions {\n encryption: {\n enabled: boolean; // if the file should be encrypted\n key?: string; // the key to use when encryption.enabled is true\n };\n\n compression: {\n enabled: boolean; // if the file should be compressed with gzip\n };\n\n file: {\n path: string; // the filename to create\n maxSize?: number; // the max size of a single backup file\n maxSizeJsonl?: number; // the max lines of each jsonl file before creating the next file\n };\n}\n\nexport interface ILocalFileDestinationProviderTransferResults\n extends IDestinationProviderTransferResults {\n file?: {\n path?: string;\n };\n}\n\nexport const createLocalFileDestinationProvider = (\n options: ILocalFileDestinationProviderOptions\n) => {\n return new LocalFileDestinationProvider(options);\n};\n\nclass LocalFileDestinationProvider implements IDestinationProvider {\n name = 'destination::local-file';\n\n type: ProviderType = 'destination';\n\n options: ILocalFileDestinationProviderOptions;\n\n results: ILocalFileDestinationProviderTransferResults = {};\n\n #providersMetadata: { source?: IMetadata; destination?: IMetadata } = {};\n\n #archive: { stream?: tar.Pack; pipeline?: Stream } = {};\n\n #diagnostics?: IDiagnosticReporter;\n\n #closed = false;\n\n constructor(options: ILocalFileDestinationProviderOptions) {\n this.options = options;\n }\n\n #reportInfo(message: string) {\n this.#diagnostics?.report({\n details: {\n createdAt: new Date(),\n message,\n origin: 'file-destination-provider',\n },\n kind: 'info',\n });\n }\n\n get #archivePath() {\n const { encryption, compression, file } = this.options;\n\n let filePath = `${file.path}.tar`;\n\n if (compression.enabled) {\n filePath += '.gz';\n }\n\n if (encryption.enabled) {\n filePath += '.enc';\n }\n\n return filePath;\n }\n\n setMetadata(target: ProviderType, metadata: IMetadata): IDestinationProvider {\n this.#providersMetadata[target] = metadata;\n\n return this;\n }\n\n createGzip(): zlib.Gzip {\n this.#reportInfo('creating gzip');\n return zlib.createGzip();\n }\n\n bootstrap(diagnostics: IDiagnosticReporter): void | Promise<void> {\n this.#diagnostics = diagnostics;\n this.#closed = false;\n const { compression, encryption } = this.options;\n\n if (encryption.enabled && !encryption.key) {\n throw new Error(\"Can't encrypt without a key\");\n }\n\n this.#archive.stream = tar.pack();\n\n const outStream = createWriteStream(this.#archivePath);\n\n outStream.on('error', (err: NodeJS.ErrnoException) => {\n if (err.code === 'ENOSPC') {\n throw new ProviderTransferError(\n \"Your server doesn't have space to proceed with the import.\"\n );\n }\n throw err;\n });\n\n const archiveTransforms: Stream[] = [];\n\n if (compression.enabled) {\n archiveTransforms.push(this.createGzip());\n }\n\n if (encryption.enabled && encryption.key) {\n archiveTransforms.push(createEncryptionCipher(encryption.key));\n }\n\n this.#archive.pipeline = chain([this.#archive.stream, ...archiveTransforms, outStream]);\n\n this.results.file = { path: this.#archivePath };\n }\n\n async close() {\n if (this.#closed) {\n return;\n }\n\n this.#closed = true;\n const { stream, pipeline } = this.#archive;\n\n if (!stream) {\n return;\n }\n\n await this.#writeMetadata();\n stream.finalize();\n\n if (pipeline && !pipeline.closed) {\n await new Promise<void>((resolve, reject) => {\n pipeline.on('close', resolve).on('error', reject);\n });\n }\n }\n\n async rollback(): Promise<void> {\n this.#reportInfo('rolling back');\n await this.close();\n await rm(this.#archivePath, { force: true });\n }\n\n getMetadata() {\n return null;\n }\n\n async #writeMetadata(): Promise<void> {\n this.#reportInfo('writing metadata');\n const metadata = this.#providersMetadata.source;\n\n if (metadata) {\n await new Promise((resolve) => {\n const outStream = this.#getMetadataStream();\n const data = JSON.stringify(metadata, null, 2);\n\n Readable.from(data).pipe(outStream).on('close', resolve);\n });\n }\n }\n\n #getMetadataStream() {\n const { stream } = this.#archive;\n\n if (!stream) {\n throw new Error('Archive stream is unavailable');\n }\n\n return createTarEntryStream(stream, () => 'metadata.json');\n }\n\n createSchemasWriteStream() {\n if (!this.#archive.stream) {\n throw new Error('Archive stream is unavailable');\n }\n this.#reportInfo('creating schemas write stream');\n const filePathFactory = createFilePathFactory('schemas');\n\n const entryStream = createTarEntryStream(\n this.#archive.stream,\n filePathFactory,\n this.options.file.maxSizeJsonl\n );\n\n return chain([stringer(), entryStream]);\n }\n\n createEntitiesWriteStream(): Writable {\n if (!this.#archive.stream) {\n throw new Error('Archive stream is unavailable');\n }\n this.#reportInfo('creating entities write stream');\n const filePathFactory = createFilePathFactory('entities');\n\n const entryStream = createTarEntryStream(\n this.#archive.stream,\n filePathFactory,\n this.options.file.maxSizeJsonl\n );\n\n return chain([stringer(), entryStream]);\n }\n\n createLinksWriteStream(): Writable {\n if (!this.#archive.stream) {\n throw new Error('Archive stream is unavailable');\n }\n this.#reportInfo('creating links write stream');\n const filePathFactory = createFilePathFactory('links');\n\n const entryStream = createTarEntryStream(\n this.#archive.stream,\n filePathFactory,\n this.options.file.maxSizeJsonl\n );\n\n return chain([stringer(), entryStream]);\n }\n\n createConfigurationWriteStream(): Writable {\n if (!this.#archive.stream) {\n throw new Error('Archive stream is unavailable');\n }\n this.#reportInfo('creating configuration write stream');\n const filePathFactory = createFilePathFactory('configuration');\n\n const entryStream = createTarEntryStream(\n this.#archive.stream,\n filePathFactory,\n this.options.file.maxSizeJsonl\n );\n\n return chain([stringer(), entryStream]);\n }\n\n createAssetsWriteStream(): Writable {\n const { stream: archiveStream } = this.#archive;\n\n if (!archiveStream) {\n throw new Error('Archive stream is unavailable');\n }\n\n this.#reportInfo('creating assets write stream');\n return new Writable({\n objectMode: true,\n write(data: IAsset, _encoding, callback) {\n // always write tar files with posix paths so we have a standard format for paths regardless of system\n const entryPath = path.posix.join('assets', 'uploads', data.filename);\n\n const entryMetadataPath = path.posix.join('assets', 'metadata', `${data.filename}.json`);\n const stringifiedMetadata = JSON.stringify(data.metadata);\n archiveStream.entry(\n {\n name: entryMetadataPath,\n size: stringifiedMetadata.length,\n },\n stringifiedMetadata\n );\n\n const entry = archiveStream.entry({\n name: entryPath,\n size: data.stats.size,\n });\n\n if (!entry) {\n callback(new Error(`Failed to created an asset tar entry for ${entryPath}`));\n return;\n }\n\n data.stream.pipe(entry);\n\n entry\n .on('finish', () => {\n callback(null);\n })\n .on('error', (error) => {\n callback(error);\n });\n },\n });\n }\n}\n"],"names":["createLocalFileDestinationProvider","options","LocalFileDestinationProvider","setMetadata","target","metadata","createGzip","zlib","bootstrap","diagnostics","compression","encryption","enabled","key","Error","stream","tar","pack","outStream","createWriteStream","on","err","code","ProviderTransferError","archiveTransforms","push","createEncryptionCipher","pipeline","chain","results","file","path","close","finalize","closed","Promise","resolve","reject","rollback","rm","force","getMetadata","createSchemasWriteStream","filePathFactory","createFilePathFactory","entryStream","createTarEntryStream","maxSizeJsonl","stringer","createEntitiesWriteStream","createLinksWriteStream","createConfigurationWriteStream","createAssetsWriteStream","archiveStream","Writable","objectMode","write","data","_encoding","callback","entryPath","posix","join","filename","entryMetadataPath","stringifiedMetadata","JSON","stringify","entry","name","size","length","stats","pipe","error","type","message","report","details","createdAt","Date","origin","kind","filePath","source","Readable","from"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AA6CO,MAAMA,qCAAqC,CAChDC,OAAAA,GAAAA;AAEA,IAAA,OAAO,IAAIC,4BAAAA,CAA6BD,OAAAA,CAAAA;AAC1C;AAWE,IAAA,kBAAA,iBAAA,8BAAA,CAAA,oBAAA,CAAA,EAEA,QAAA,iBAAA,8BAAA,CAAA,UAAA,CAAA,EAEA,YAAA,iBAAA,8BAAA,CAAA,cAAA,CAAA,EAEA,OAAA,iBAAA,8BAAA,CAAA,SAAA,CAAA,EAMA,WAAA,iBAAA,8BAAA,CAAA,aAAA,CAAA,EAWI,6EAgGE,cAAA,iBAAA,8BAAA,CAAA,gBAAA,CAAA,EAcN,kBAAA,iBAAA,8BAAA,CAAA,oBAAA,CAAA;AA9IF,MAAMC,4BAAAA,CAAAA;IAgDJC,WAAAA,CAAYC,MAAoB,EAAEC,QAAmB,EAAwB;AAC3E,QAAA,+BAAA,CAAA,IAAI,EAAC,kBAAA,CAAA,CAAA,kBAAA,CAAkB,CAACD,OAAO,GAAGC,QAAAA;AAElC,QAAA,OAAO,IAAI;AACb,IAAA;IAEAC,UAAAA,GAAwB;QACtB,+BAAA,CAAA,IAAI,EAAC,WAAA,CAAA,CAAA,WAAA,CAAA,CAAY,eAAA,CAAA;AACjB,QAAA,OAAOC,IAAKD,UAAU,EAAA;AACxB,IAAA;AAEAE,IAAAA,SAAAA,CAAUC,WAAgC,EAAwB;QAChE,+BAAA,CAAA,IAAI,EAAC,YAAA,CAAA,CAAA,YAAA,CAAA,GAAeA,WAAAA;QACpB,+BAAA,CAAA,IAAI,EAAC,OAAA,CAAA,CAAA,OAAA,CAAA,GAAU,KAAA;QACf,MAAM,EAAEC,WAAW,EAAEC,UAAU,EAAE,GAAG,IAAI,CAACV,OAAO;AAEhD,QAAA,IAAIU,WAAWC,OAAO,IAAI,CAACD,UAAAA,CAAWE,GAAG,EAAE;AACzC,YAAA,MAAM,IAAIC,KAAAA,CAAM,6BAAA,CAAA;AAClB,QAAA;AAEA,QAAA,+BAAA,CAAA,IAAI,EAAC,QAAA,CAAA,CAAA,UAASC,MAAM,GAAGC,IAAIC,IAAI,EAAA;AAE/B,QAAA,MAAMC,SAAAA,GAAYC,iBAAAA,CAAkB,+BAAA,CAAA,IAAI,EAAC,YAAA,CAAA,CAAA,YAAA,CAAA,CAAA;QAEzCD,SAAAA,CAAUE,EAAE,CAAC,OAAA,EAAS,CAACC,GAAAA,GAAAA;YACrB,IAAIA,GAAAA,CAAIC,IAAI,KAAK,QAAA,EAAU;AACzB,gBAAA,MAAM,IAAIC,qBAAAA,CACR,4DAAA,CAAA;AAEJ,YAAA;YACA,MAAMF,GAAAA;AACR,QAAA,CAAA,CAAA;AAEA,QAAA,MAAMG,oBAA8B,EAAE;QAEtC,IAAId,WAAAA,CAAYE,OAAO,EAAE;AACvBY,YAAAA,iBAAAA,CAAkBC,IAAI,CAAC,IAAI,CAACnB,UAAU,EAAA,CAAA;AACxC,QAAA;AAEA,QAAA,IAAIK,UAAAA,CAAWC,OAAO,IAAID,UAAAA,CAAWE,GAAG,EAAE;AACxCW,YAAAA,iBAAAA,CAAkBC,IAAI,CAACC,sBAAAA,CAAuBf,UAAAA,CAAWE,GAAG,CAAA,CAAA;AAC9D,QAAA;AAEA,QAAA,+BAAA,CAAA,IAAI,EAAC,QAAA,CAAA,CAAA,QAAA,CAAA,CAASc,QAAQ,GAAGC,KAAAA,CAAM;AAAC,YAAA,+BAAA,CAAA,IAAI,EAAC,QAAA,CAAA,CAAA,QAAA,CAAA,CAASb,MAAM;AAAKS,YAAAA,GAAAA,iBAAAA;AAAmBN,YAAAA;AAAU,SAAA,CAAA;AAEtF,QAAA,IAAI,CAACW,OAAO,CAACC,IAAI,GAAG;AAAEC,YAAAA,IAAI,EAAE,+BAAA,CAAA,IAAI,EAAC,YAAA,CAAA,CAAA,YAAA;AAAa,SAAA;AAChD,IAAA;AAEA,IAAA,MAAMC,KAAAA,GAAQ;AACZ,QAAA,IAAI,+BAAA,CAAA,IAAI,EAAC,OAAA,CAAA,CAAA,OAAA,CAAA,EAAS;AAChB,YAAA;AACF,QAAA;QAEA,+BAAA,CAAA,IAAI,EAAC,OAAA,CAAA,CAAA,OAAA,CAAA,GAAU,IAAA;QACf,MAAM,EAAEjB,MAAM,EAAEY,QAAQ,EAAE,GAAG,+BAAA,CAAA,IAAI,EAAC,QAAA,CAAA,CAAA,QAAA,CAAA;AAElC,QAAA,IAAI,CAACZ,MAAAA,EAAQ;AACX,YAAA;AACF,QAAA;QAEA,MAAM,+BAAA,CAAA,IAAI,EAAC,cAAA,CAAA,CAAA,cAAA,CAAA,EAAA;AACXA,QAAAA,MAAAA,CAAOkB,QAAQ,EAAA;AAEf,QAAA,IAAIN,QAAAA,IAAY,CAACA,QAAAA,CAASO,MAAM,EAAE;YAChC,MAAM,IAAIC,OAAAA,CAAc,CAACC,OAAAA,EAASC,MAAAA,GAAAA;AAChCV,gBAAAA,QAAAA,CAASP,EAAE,CAAC,OAAA,EAASgB,OAAAA,CAAAA,CAAShB,EAAE,CAAC,OAAA,EAASiB,MAAAA,CAAAA;AAC5C,YAAA,CAAA,CAAA;AACF,QAAA;AACF,IAAA;AAEA,IAAA,MAAMC,QAAAA,GAA0B;QAC9B,+BAAA,CAAA,IAAI,EAAC,WAAA,CAAA,CAAA,WAAA,CAAA,CAAY,cAAA,CAAA;QACjB,MAAM,IAAI,CAACN,KAAK,EAAA;AAChB,QAAA,MAAMO,EAAAA,CAAG,+BAAA,CAAA,IAAI,EAAC,cAAA,YAAA,CAAA,EAAc;YAAEC,KAAAA,EAAO;AAAK,SAAA,CAAA;AAC5C,IAAA;IAEAC,WAAAA,GAAc;QACZ,OAAO,IAAA;AACT,IAAA;IA0BAC,wBAAAA,GAA2B;AACzB,QAAA,IAAI,CAAC,+BAAA,CAAA,IAAI,EAAC,QAAA,CAAA,CAAA,QAAA,CAAA,CAAS3B,MAAM,EAAE;AACzB,YAAA,MAAM,IAAID,KAAAA,CAAM,+BAAA,CAAA;AAClB,QAAA;QACA,+BAAA,CAAA,IAAI,EAAC,WAAA,CAAA,CAAA,WAAA,CAAA,CAAY,+BAAA,CAAA;AACjB,QAAA,MAAM6B,kBAAkBC,qBAAAA,CAAsB,SAAA,CAAA;AAE9C,QAAA,MAAMC,cAAcC,oBAAAA,CAClB,+BAAA,CAAA,IAAI,EAAC,UAAA,QAAA,CAAA,CAAS/B,MAAM,EACpB4B,eAAAA,EACA,IAAI,CAAC1C,OAAO,CAAC6B,IAAI,CAACiB,YAAY,CAAA;AAGhC,QAAA,OAAOnB,KAAAA,CAAM;AAACoB,YAAAA,QAAAA,EAAAA;AAAYH,YAAAA;AAAY,SAAA,CAAA;AACxC,IAAA;IAEAI,yBAAAA,GAAsC;AACpC,QAAA,IAAI,CAAC,+BAAA,CAAA,IAAI,EAAC,QAAA,CAAA,CAAA,QAAA,CAAA,CAASlC,MAAM,EAAE;AACzB,YAAA,MAAM,IAAID,KAAAA,CAAM,+BAAA,CAAA;AAClB,QAAA;QACA,+BAAA,CAAA,IAAI,EAAC,WAAA,CAAA,CAAA,WAAA,CAAA,CAAY,gCAAA,CAAA;AACjB,QAAA,MAAM6B,kBAAkBC,qBAAAA,CAAsB,UAAA,CAAA;AAE9C,QAAA,MAAMC,cAAcC,oBAAAA,CAClB,+BAAA,CAAA,IAAI,EAAC,UAAA,QAAA,CAAA,CAAS/B,MAAM,EACpB4B,eAAAA,EACA,IAAI,CAAC1C,OAAO,CAAC6B,IAAI,CAACiB,YAAY,CAAA;AAGhC,QAAA,OAAOnB,KAAAA,CAAM;AAACoB,YAAAA,QAAAA,EAAAA;AAAYH,YAAAA;AAAY,SAAA,CAAA;AACxC,IAAA;IAEAK,sBAAAA,GAAmC;AACjC,QAAA,IAAI,CAAC,+BAAA,CAAA,IAAI,EAAC,QAAA,CAAA,CAAA,QAAA,CAAA,CAASnC,MAAM,EAAE;AACzB,YAAA,MAAM,IAAID,KAAAA,CAAM,+BAAA,CAAA;AAClB,QAAA;QACA,+BAAA,CAAA,IAAI,EAAC,WAAA,CAAA,CAAA,WAAA,CAAA,CAAY,6BAAA,CAAA;AACjB,QAAA,MAAM6B,kBAAkBC,qBAAAA,CAAsB,OAAA,CAAA;AAE9C,QAAA,MAAMC,cAAcC,oBAAAA,CAClB,+BAAA,CAAA,IAAI,EAAC,UAAA,QAAA,CAAA,CAAS/B,MAAM,EACpB4B,eAAAA,EACA,IAAI,CAAC1C,OAAO,CAAC6B,IAAI,CAACiB,YAAY,CAAA;AAGhC,QAAA,OAAOnB,KAAAA,CAAM;AAACoB,YAAAA,QAAAA,EAAAA;AAAYH,YAAAA;AAAY,SAAA,CAAA;AACxC,IAAA;IAEAM,8BAAAA,GAA2C;AACzC,QAAA,IAAI,CAAC,+BAAA,CAAA,IAAI,EAAC,QAAA,CAAA,CAAA,QAAA,CAAA,CAASpC,MAAM,EAAE;AACzB,YAAA,MAAM,IAAID,KAAAA,CAAM,+BAAA,CAAA;AAClB,QAAA;QACA,+BAAA,CAAA,IAAI,EAAC,WAAA,CAAA,CAAA,WAAA,CAAA,CAAY,qCAAA,CAAA;AACjB,QAAA,MAAM6B,kBAAkBC,qBAAAA,CAAsB,eAAA,CAAA;AAE9C,QAAA,MAAMC,cAAcC,oBAAAA,CAClB,+BAAA,CAAA,IAAI,EAAC,UAAA,QAAA,CAAA,CAAS/B,MAAM,EACpB4B,eAAAA,EACA,IAAI,CAAC1C,OAAO,CAAC6B,IAAI,CAACiB,YAAY,CAAA;AAGhC,QAAA,OAAOnB,KAAAA,CAAM;AAACoB,YAAAA,QAAAA,EAAAA;AAAYH,YAAAA;AAAY,SAAA,CAAA;AACxC,IAAA;IAEAO,uBAAAA,GAAoC;QAClC,MAAM,EAAErC,QAAQsC,aAAa,EAAE,GAAG,+BAAA,CAAA,IAAI,EAAC,QAAA,CAAA,CAAA,QAAA,CAAA;AAEvC,QAAA,IAAI,CAACA,aAAAA,EAAe;AAClB,YAAA,MAAM,IAAIvC,KAAAA,CAAM,+BAAA,CAAA;AAClB,QAAA;QAEA,+BAAA,CAAA,IAAI,EAAC,WAAA,CAAA,CAAA,WAAA,CAAA,CAAY,8BAAA,CAAA;AACjB,QAAA,OAAO,IAAIwC,QAAAA,CAAS;YAClBC,UAAAA,EAAY,IAAA;AACZC,YAAAA,KAAAA,CAAAA,CAAMC,IAAY,EAAEC,SAAS,EAAEC,QAAQ,EAAA;;gBAErC,MAAMC,SAAAA,GAAY7B,KAAK8B,KAAK,CAACC,IAAI,CAAC,QAAA,EAAU,SAAA,EAAWL,IAAAA,CAAKM,QAAQ,CAAA;AAEpE,gBAAA,MAAMC,iBAAAA,GAAoBjC,IAAAA,CAAK8B,KAAK,CAACC,IAAI,CAAC,QAAA,EAAU,UAAA,EAAY,CAAA,EAAGL,IAAAA,CAAKM,QAAQ,CAAC,KAAK,CAAC,CAAA;AACvF,gBAAA,MAAME,mBAAAA,GAAsBC,IAAAA,CAAKC,SAAS,CAACV,KAAKpD,QAAQ,CAAA;AACxDgD,gBAAAA,aAAAA,CAAce,KAAK,CACjB;oBACEC,IAAAA,EAAML,iBAAAA;AACNM,oBAAAA,IAAAA,EAAML,oBAAoBM;iBAC5B,EACAN,mBAAAA,CAAAA;gBAGF,MAAMG,KAAAA,GAAQf,aAAAA,CAAce,KAAK,CAAC;oBAChCC,IAAAA,EAAMT,SAAAA;oBACNU,IAAAA,EAAMb,IAAAA,CAAKe,KAAK,CAACF;AACnB,iBAAA,CAAA;AAEA,gBAAA,IAAI,CAACF,KAAAA,EAAO;AACVT,oBAAAA,QAAAA,CAAS,IAAI7C,KAAAA,CAAM,CAAC,yCAAyC,EAAE8C,SAAAA,CAAAA,CAAW,CAAA,CAAA;AAC1E,oBAAA;AACF,gBAAA;gBAEAH,IAAAA,CAAK1C,MAAM,CAAC0D,IAAI,CAACL,KAAAA,CAAAA;gBAEjBA,KAAAA,CACGhD,EAAE,CAAC,QAAA,EAAU,IAAA;oBACZuC,QAAAA,CAAS,IAAA,CAAA;gBACX,CAAA,CAAA,CACCvC,EAAE,CAAC,OAAA,EAAS,CAACsD,KAAAA,GAAAA;oBACZf,QAAAA,CAASe,KAAAA,CAAAA;AACX,gBAAA,CAAA,CAAA;AACJ,YAAA;AACF,SAAA,CAAA;AACF,IAAA;AApPA,IAAA,WAAA,CAAYzE,OAA6C,CAAE;QAI3D,MAAA,CAAA,cAAA,CAAA,IAAA,EAAA,WAAA,EAAA;AAAA,YAAA,KAAA,EAAA;;QAWA,MAAA,CAAA,cAAA,CAAA,IAAA,EAAI,YAAA,EAAA;AAAJ,YAAA,GAAA,EAAA,eAAA;;;QAgGA,MAAA,CAAA,cAAA,CAAA,IAAA,EAAM,cAAA,EAAA;AAAN,YAAA,KAAA,EAAA;;QAcA,MAAA,CAAA,cAAA,CAAA,IAAA,EAAA,kBAAA,EAAA;AAAA,YAAA,KAAA,EAAA;;QArIA,MAAA,CAAA,cAAA,CAAA,IAAA,EAAA,kBAAA,EAAA;;mBAAA;;QAEA,MAAA,CAAA,cAAA,CAAA,IAAA,EAAA,QAAA,EAAA;;mBAAA;;QAEA,MAAA,CAAA,cAAA,CAAA,IAAA,EAAA,YAAA,EAAA;;mBAAA;;QAEA,MAAA,CAAA,cAAA,CAAA,IAAA,EAAA,OAAA,EAAA;;mBAAA;;aAdAoE,IAAAA,GAAO,yBAAA;aAEPM,IAAAA,GAAqB,aAAA;AAIrB9C,QAAAA,IAAAA,CAAAA,OAAAA,GAAwD,EAAC;AAEzD,QAAA,+BAAA,CAAA,IAAA,EAAA,kBAAA,CAAA,CAAA,sBAAsE,EAAC;AAEvE,QAAA,+BAAA,CAAA,IAAA,EAAA,QAAA,CAAA,CAAA,YAAqD,EAAC;AAItD,QAAA,+BAAA,CAAA,IAAA,EAAA,OAAA,CAAA,CAAA,OAAA,CAAA,GAAU,KAAA;QAGR,IAAI,CAAC5B,OAAO,GAAGA,OAAAA;AACjB,IAAA;AAmPF;AAjPE,SAAA,WAAY2E,OAAe,EAAA;AACzB,IAAA,+BAAA,CAAA,IAAI,EAAC,YAAA,CAAA,CAAA,YAAA,CAAA,EAAcC,MAAAA,CAAO;QACxBC,OAAAA,EAAS;AACPC,YAAAA,SAAAA,EAAW,IAAIC,IAAAA,EAAAA;AACfJ,YAAAA,OAAAA;YACAK,MAAAA,EAAQ;AACV,SAAA;QACAC,IAAAA,EAAM;AACR,KAAA,CAAA;AACF;AAEA,SAAA,eAAA,GAAA;IACE,MAAM,EAAEvE,UAAU,EAAED,WAAW,EAAEoB,IAAI,EAAE,GAAG,IAAI,CAAC7B,OAAO;AAEtD,IAAA,IAAIkF,WAAW,CAAA,EAAGrD,IAAAA,CAAKC,IAAI,CAAC,IAAI,CAAC;IAEjC,IAAIrB,WAAAA,CAAYE,OAAO,EAAE;QACvBuE,QAAAA,IAAY,KAAA;AACd,IAAA;IAEA,IAAIxE,UAAAA,CAAWC,OAAO,EAAE;QACtBuE,QAAAA,IAAY,MAAA;AACd,IAAA;IAEA,OAAOA,QAAAA;AACT;AAkFA,eAAA,aAAA,GAAA;IACE,+BAAA,CAAA,IAAI,EAAC,WAAA,CAAA,CAAA,WAAA,CAAA,CAAY,kBAAA,CAAA;AACjB,IAAA,MAAM9E,WAAW,+BAAA,CAAA,IAAI,EAAC,kBAAA,CAAA,CAAA,oBAAmB+E,MAAM;AAE/C,IAAA,IAAI/E,QAAAA,EAAU;QACZ,MAAM,IAAI8B,QAAQ,CAACC,OAAAA,GAAAA;AACjB,YAAA,MAAMlB,SAAAA,GAAY,+BAAA,CAAA,IAAI,EAAC,kBAAA,CAAA,CAAA,kBAAA,CAAA,EAAA;AACvB,YAAA,MAAMuC,IAAAA,GAAOS,IAAAA,CAAKC,SAAS,CAAC9D,UAAU,IAAA,EAAM,CAAA,CAAA;YAE5CgF,QAAAA,CAASC,IAAI,CAAC7B,IAAAA,CAAAA,CAAMgB,IAAI,CAACvD,SAAAA,CAAAA,CAAWE,EAAE,CAAC,OAAA,EAASgB,OAAAA,CAAAA;AAClD,QAAA,CAAA,CAAA;AACF,IAAA;AACF;AAEA,SAAA,iBAAA,GAAA;AACE,IAAA,MAAM,EAAErB,MAAM,EAAE,GAAG,+BAAA,CAAA,IAAI,EAAC,QAAA,CAAA,CAAA,QAAA,CAAA;AAExB,IAAA,IAAI,CAACA,MAAAA,EAAQ;AACX,QAAA,MAAM,IAAID,KAAAA,CAAM,+BAAA,CAAA;AAClB,IAAA;IAEA,OAAOgC,oBAAAA,CAAqB/B,QAAQ,IAAM,eAAA,CAAA;AAC5C;;;;"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Readable } from 'stream';
|
|
2
|
-
import type { IMetadata, ISourceProvider, ProviderType } from '../../../types';
|
|
2
|
+
import type { IMetadata, ISourceProvider, ProviderType, TransferStage } from '../../../types';
|
|
3
3
|
import type { IDiagnosticReporter } from '../../../utils/diagnostic';
|
|
4
4
|
/**
|
|
5
5
|
* Provider options
|
|
@@ -29,6 +29,7 @@ declare class LocalFileSourceProvider implements ISourceProvider {
|
|
|
29
29
|
bootstrap(diagnostics: IDiagnosticReporter): Promise<void>;
|
|
30
30
|
getMetadata(): Promise<IMetadata | null>;
|
|
31
31
|
getSchemas(): Promise<any>;
|
|
32
|
+
validateStage(stage: TransferStage): Promise<void>;
|
|
32
33
|
createEntitiesReadStream(): Readable;
|
|
33
34
|
createSchemasReadStream(): Readable;
|
|
34
35
|
createLinksReadStream(): Readable;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/file/providers/source/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/file/providers/source/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAavC,OAAO,KAAK,EAEV,SAAS,EACT,eAAe,EACf,YAAY,EAEZ,aAAa,EACd,MAAM,gBAAgB,CAAC;AACxB,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAuBrE;;GAEG;AACH,MAAM,WAAW,+BAA+B;IAC9C,IAAI,EAAE;QACJ,IAAI,EAAE,MAAM,CAAC;KACd,CAAC;IAEF,UAAU,EAAE;QACV,OAAO,EAAE,OAAO,CAAC;QACjB,GAAG,CAAC,EAAE,MAAM,CAAC;KACd,CAAC;IAEF,WAAW,EAAE;QACX,OAAO,EAAE,OAAO,CAAC;KAClB,CAAC;CACH;AAED,eAAO,MAAM,6BAA6B,GAAI,SAAS,+BAA+B,4BAErF,CAAC;AAEF,cAAM,uBAAwB,YAAW,eAAe;;IACtD,IAAI,EAAE,YAAY,CAAY;IAE9B,IAAI,SAAwB;IAE5B,OAAO,EAAE,+BAA+B,CAAC;gBAQ7B,OAAO,EAAE,+BAA+B;IA4CpD;;OAEG;IACG,SAAS,CAAC,WAAW,EAAE,mBAAmB;IAoC1C,WAAW;IASX,UAAU;IAiBV,aAAa,CAAC,KAAK,EAAE,aAAa;IA2GxC,wBAAwB,IAAI,QAAQ;IAKpC,uBAAuB,IAAI,QAAQ;IAKnC,qBAAqB,IAAI,QAAQ;IAKjC,6BAA6B,IAAI,QAAQ;IAMzC,sBAAsB,IAAI,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC;CAoMvD"}
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
var zip = require('zlib');
|
|
4
4
|
var path = require('path');
|
|
5
5
|
var stream$1 = require('stream');
|
|
6
|
+
var promises = require('stream/promises');
|
|
6
7
|
var fs = require('fs-extra');
|
|
7
8
|
var tar = require('tar');
|
|
8
9
|
var fp = require('lodash/fp');
|
|
@@ -39,7 +40,7 @@ function _class_private_field_loose_key(name) {
|
|
|
39
40
|
const createLocalFileSourceProvider = (options)=>{
|
|
40
41
|
return new LocalFileSourceProvider(options);
|
|
41
42
|
};
|
|
42
|
-
var _metadata = /*#__PURE__*/ _class_private_field_loose_key("_metadata"), _diagnostics = /*#__PURE__*/ _class_private_field_loose_key("_diagnostics"), _reportInfo = /*#__PURE__*/ _class_private_field_loose_key("_reportInfo"), /**
|
|
43
|
+
var _metadata = /*#__PURE__*/ _class_private_field_loose_key("_metadata"), _assetMetadata = /*#__PURE__*/ _class_private_field_loose_key("_assetMetadata"), _diagnostics = /*#__PURE__*/ _class_private_field_loose_key("_diagnostics"), _reportInfo = /*#__PURE__*/ _class_private_field_loose_key("_reportInfo"), /**
|
|
43
44
|
* tar `Parser` invokes the pipeline completion callback when the archive ends, but it does not
|
|
44
45
|
* reliably await async `onReadEntry` — defer `end` until outstanding async entry work is done.
|
|
45
46
|
*/ _endPassThroughWhenTarIdle = /*#__PURE__*/ _class_private_field_loose_key("_endPassThroughWhenTarIdle"), _loadMetadata = /*#__PURE__*/ _class_private_field_loose_key("_loadMetadata"), _loadAssetMetadata = /*#__PURE__*/ _class_private_field_loose_key("_loadAssetMetadata"), _getBackupStream = /*#__PURE__*/ _class_private_field_loose_key("_getBackupStream"), // `directory` must be posix formatted path
|
|
@@ -82,6 +83,91 @@ class LocalFileSourceProvider {
|
|
|
82
83
|
// Transform to valid JSON
|
|
83
84
|
return schema.schemasToValidJSON(schemas);
|
|
84
85
|
}
|
|
86
|
+
async validateStage(stage) {
|
|
87
|
+
if (stage !== 'assets') {
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
const uploads = new Set();
|
|
91
|
+
const sidecars = new Map();
|
|
92
|
+
const inStream = _class_private_field_loose_base(this, _getBackupStream)[_getBackupStream]();
|
|
93
|
+
await new Promise((resolve, reject)=>{
|
|
94
|
+
let activeEntries = 0;
|
|
95
|
+
let archiveFinished = false;
|
|
96
|
+
let validationError;
|
|
97
|
+
const finishWhenIdle = ()=>{
|
|
98
|
+
if (!archiveFinished || activeEntries > 0) {
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
if (validationError) {
|
|
102
|
+
reject(validationError);
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
resolve();
|
|
106
|
+
};
|
|
107
|
+
stream$1.pipeline([
|
|
108
|
+
inStream,
|
|
109
|
+
new tar.Parser({
|
|
110
|
+
filter (filePath, entry) {
|
|
111
|
+
if (!('type' in entry) || entry.type !== 'File') {
|
|
112
|
+
return false;
|
|
113
|
+
}
|
|
114
|
+
return utils.isFilePathInDirname('assets/uploads', filePath) || utils.isFilePathInDirname('assets/metadata', filePath);
|
|
115
|
+
},
|
|
116
|
+
async onReadEntry (entry) {
|
|
117
|
+
activeEntries += 1;
|
|
118
|
+
const normalizedPath = utils.unknownPathToPosix(entry.path);
|
|
119
|
+
const filename = path__default.default.basename(normalizedPath);
|
|
120
|
+
try {
|
|
121
|
+
if (utils.isFilePathInDirname('assets/uploads', normalizedPath)) {
|
|
122
|
+
uploads.add(filename);
|
|
123
|
+
entry.resume();
|
|
124
|
+
await promises.finished(entry);
|
|
125
|
+
} else {
|
|
126
|
+
const chunks = [];
|
|
127
|
+
for await (const chunk of entry){
|
|
128
|
+
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
129
|
+
}
|
|
130
|
+
if (filename.endsWith('.json')) {
|
|
131
|
+
const assetFilename = filename.slice(0, -'.json'.length);
|
|
132
|
+
sidecars.set(assetFilename, Buffer.concat(chunks));
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
} catch (error) {
|
|
136
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
137
|
+
validationError = new providers.ProviderValidationError(`Asset metadata preflight failed for "${filename}": ${reason}`, {
|
|
138
|
+
error
|
|
139
|
+
});
|
|
140
|
+
} finally{
|
|
141
|
+
activeEntries -= 1;
|
|
142
|
+
finishWhenIdle();
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
})
|
|
146
|
+
], (error)=>{
|
|
147
|
+
archiveFinished = true;
|
|
148
|
+
validationError || (validationError = error ?? undefined);
|
|
149
|
+
finishWhenIdle();
|
|
150
|
+
});
|
|
151
|
+
});
|
|
152
|
+
const missingSidecars = [
|
|
153
|
+
...uploads
|
|
154
|
+
].filter((filename)=>!sidecars.has(filename)).sort();
|
|
155
|
+
if (missingSidecars.length > 0) {
|
|
156
|
+
throw new providers.ProviderValidationError(`Asset metadata preflight failed: missing sidecar metadata for ${missingSidecars.map((filename)=>`"${filename}"`).join(', ')}. The destination was not modified; re-export and try again.`);
|
|
157
|
+
}
|
|
158
|
+
const metadata = new Map();
|
|
159
|
+
for (const filename of uploads){
|
|
160
|
+
try {
|
|
161
|
+
metadata.set(filename, utils.validateAssetMetadata(JSON.parse(sidecars.get(filename).toString()), filename));
|
|
162
|
+
} catch (error) {
|
|
163
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
164
|
+
throw new providers.ProviderValidationError(`Asset metadata preflight failed for "${filename}.json": ${reason}. The destination was not modified; re-export and try again.`, {
|
|
165
|
+
error
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
_class_private_field_loose_base(this, _assetMetadata)[_assetMetadata] = metadata;
|
|
170
|
+
}
|
|
85
171
|
createEntitiesReadStream() {
|
|
86
172
|
_class_private_field_loose_base(this, _reportInfo)[_reportInfo]('creating entities read stream');
|
|
87
173
|
return _class_private_field_loose_base(this, _streamJsonlDirectory)[_streamJsonlDirectory]('entities');
|
|
@@ -105,6 +191,7 @@ class LocalFileSourceProvider {
|
|
|
105
191
|
objectMode: true
|
|
106
192
|
});
|
|
107
193
|
const loadAssetMetadata = _class_private_field_loose_base(this, _loadAssetMetadata)[_loadAssetMetadata].bind(this);
|
|
194
|
+
const assetMetadata = _class_private_field_loose_base(this, _assetMetadata)[_assetMetadata];
|
|
108
195
|
_class_private_field_loose_base(this, _reportInfo)[_reportInfo]('creating assets read stream');
|
|
109
196
|
let activeAsyncEntries = 0;
|
|
110
197
|
const runReadEntry = async (fn)=>{
|
|
@@ -130,12 +217,9 @@ class LocalFileSourceProvider {
|
|
|
130
217
|
const { path: filePath, size = 0 } = entry;
|
|
131
218
|
const normalizedPath = utils.unknownPathToPosix(filePath);
|
|
132
219
|
const file = path__default.default.basename(normalizedPath);
|
|
133
|
-
|
|
134
|
-
try {
|
|
135
|
-
metadata = await loadAssetMetadata(`assets/metadata/${file}.json`);
|
|
136
|
-
} catch {
|
|
220
|
+
const metadata = assetMetadata?.get(file) ?? await loadAssetMetadata(`assets/metadata/${file}.json`).catch(()=>{
|
|
137
221
|
throw new Error(`Failed to read metadata for ${file}`);
|
|
138
|
-
}
|
|
222
|
+
});
|
|
139
223
|
const asset = {
|
|
140
224
|
metadata,
|
|
141
225
|
filename: file,
|
|
@@ -179,6 +263,10 @@ class LocalFileSourceProvider {
|
|
|
179
263
|
writable: true,
|
|
180
264
|
value: void 0
|
|
181
265
|
});
|
|
266
|
+
Object.defineProperty(this, _assetMetadata, {
|
|
267
|
+
writable: true,
|
|
268
|
+
value: void 0
|
|
269
|
+
});
|
|
182
270
|
Object.defineProperty(this, _diagnostics, {
|
|
183
271
|
writable: true,
|
|
184
272
|
value: void 0
|
|
@@ -220,9 +308,10 @@ async function loadMetadata() {
|
|
|
220
308
|
const backupStream = _class_private_field_loose_base(this, _getBackupStream)[_getBackupStream]();
|
|
221
309
|
_class_private_field_loose_base(this, _metadata)[_metadata] = await _class_private_field_loose_base(this, _parseJSONFile)[_parseJSONFile](backupStream, METADATA_FILE_PATH);
|
|
222
310
|
}
|
|
223
|
-
async function loadAssetMetadata(
|
|
311
|
+
async function loadAssetMetadata(sidecarPath) {
|
|
224
312
|
const backupStream = _class_private_field_loose_base(this, _getBackupStream)[_getBackupStream]();
|
|
225
|
-
|
|
313
|
+
const filename = path__default.default.posix.basename(sidecarPath).replace(/\.json$/, '');
|
|
314
|
+
return utils.validateAssetMetadata(await _class_private_field_loose_base(this, _parseJSONFile)[_parseJSONFile](backupStream, sidecarPath), filename);
|
|
226
315
|
}
|
|
227
316
|
function getBackupStream() {
|
|
228
317
|
const { file, encryption, compression } = this.options;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../../../src/file/providers/source/index.ts"],"sourcesContent":["import type { Stats } from 'node:fs';\nimport type { Readable } from 'stream';\n\nimport zip from 'zlib';\nimport path from 'path';\nimport { pipeline, PassThrough } from 'stream';\nimport fs from 'fs-extra';\nimport { Parser, type ReadEntry } from 'tar';\nimport { isEmpty, keyBy } from 'lodash/fp';\nimport { chain } from 'stream-chain';\nimport { parser } from 'stream-json/jsonl/Parser';\nimport type { Struct } from '@strapi/types';\n\nimport type { IAsset, IMetadata, ISourceProvider, ProviderType, IFile } from '../../../types';\nimport type { IDiagnosticReporter } from '../../../utils/diagnostic';\n\nimport * as utils from '../../../utils';\nimport { write } from '../../../utils/writable-async-write';\nimport { ProviderInitializationError, ProviderTransferError } from '../../../errors/providers';\nimport { isFilePathInDirname, isPathEquivalent, unknownPathToPosix } from './utils';\n\ntype StreamItemArray = Parameters<typeof chain>[0];\n\n/**\n * Constant for the metadata file path\n */\nconst METADATA_FILE_PATH = 'metadata.json';\n\n/**\n * Provider options\n */\nexport interface ILocalFileSourceProviderOptions {\n file: {\n path: string; // the file to load\n };\n\n encryption: {\n enabled: boolean; // if the file is encrypted (and should be decrypted)\n key?: string; // the key to decrypt the file\n };\n\n compression: {\n enabled: boolean; // if the file is compressed (and should be decompressed)\n };\n}\n\nexport const createLocalFileSourceProvider = (options: ILocalFileSourceProviderOptions) => {\n return new LocalFileSourceProvider(options);\n};\n\nclass LocalFileSourceProvider implements ISourceProvider {\n type: ProviderType = 'source';\n\n name = 'source::local-file';\n\n options: ILocalFileSourceProviderOptions;\n\n #metadata?: IMetadata;\n\n #diagnostics?: IDiagnosticReporter;\n\n constructor(options: ILocalFileSourceProviderOptions) {\n this.options = options;\n\n const { encryption } = this.options;\n\n if (encryption.enabled && encryption.key === undefined) {\n throw new Error('Missing encryption key');\n }\n }\n\n #reportInfo(message: string) {\n this.#diagnostics?.report({\n details: {\n createdAt: new Date(),\n message,\n origin: 'file-source-provider',\n },\n kind: 'info',\n });\n }\n\n /**\n * tar `Parser` invokes the pipeline completion callback when the archive ends, but it does not\n * reliably await async `onReadEntry` — defer `end` until outstanding async entry work is done.\n */\n #endPassThroughWhenTarIdle(\n outStream: PassThrough,\n activeAsyncEntries: () => number,\n err?: Error | null\n ) {\n if (err) {\n outStream.destroy(err);\n return;\n }\n const tick = () => {\n if (activeAsyncEntries() === 0) {\n outStream.end();\n } else {\n setImmediate(tick);\n }\n };\n tick();\n }\n\n /**\n * Pre flight checks regarding the provided options, making sure that the file can be opened (decrypted, decompressed), etc.\n */\n async bootstrap(diagnostics: IDiagnosticReporter) {\n this.#diagnostics = diagnostics;\n const { path: filePath } = this.options.file;\n\n try {\n // Read the metadata to ensure the file can be parsed\n await this.#loadMetadata();\n // TODO: we might also need to read the schema.jsonl files & implements a custom stream-check\n } catch {\n if (this.options?.encryption?.enabled) {\n throw new ProviderInitializationError(\n `Key is incorrect or the file '${filePath}' is not a valid Strapi data file.`\n );\n }\n throw new ProviderInitializationError(`File '${filePath}' is not a valid Strapi data file.`);\n }\n\n if (!this.#metadata) {\n throw new ProviderInitializationError('Could not load metadata from Strapi data file.');\n }\n }\n\n async #loadMetadata() {\n const backupStream = this.#getBackupStream();\n this.#metadata = await this.#parseJSONFile<IMetadata>(backupStream, METADATA_FILE_PATH);\n }\n\n async #loadAssetMetadata(path: string) {\n const backupStream = this.#getBackupStream();\n return this.#parseJSONFile<IFile>(backupStream, path);\n }\n\n async getMetadata() {\n this.#reportInfo('getting metadata');\n if (!this.#metadata) {\n await this.#loadMetadata();\n }\n\n return this.#metadata ?? null;\n }\n\n async getSchemas() {\n this.#reportInfo('getting schemas');\n const schemaCollection = await utils.stream.collect<Struct.Schema>(\n this.createSchemasReadStream()\n );\n\n if (isEmpty(schemaCollection)) {\n throw new ProviderInitializationError('Could not load schemas from Strapi data file.');\n }\n\n // Group schema by UID\n const schemas = keyBy('uid', schemaCollection);\n\n // Transform to valid JSON\n return utils.schema.schemasToValidJSON(schemas);\n }\n\n createEntitiesReadStream(): Readable {\n this.#reportInfo('creating entities read stream');\n return this.#streamJsonlDirectory('entities');\n }\n\n createSchemasReadStream(): Readable {\n this.#reportInfo('creating schemas read stream');\n return this.#streamJsonlDirectory('schemas');\n }\n\n createLinksReadStream(): Readable {\n this.#reportInfo('creating links read stream');\n return this.#streamJsonlDirectory('links');\n }\n\n createConfigurationReadStream(): Readable {\n this.#reportInfo('creating configuration read stream');\n // NOTE: TBD\n return this.#streamJsonlDirectory('configuration');\n }\n\n createAssetsReadStream(): Readable | Promise<Readable> {\n const inStream = this.#getBackupStream();\n const outStream = new PassThrough({ objectMode: true });\n const loadAssetMetadata = this.#loadAssetMetadata.bind(this);\n this.#reportInfo('creating assets read stream');\n\n let activeAsyncEntries = 0;\n const runReadEntry = async (fn: () => Promise<void>) => {\n activeAsyncEntries += 1;\n try {\n await fn();\n } finally {\n activeAsyncEntries -= 1;\n }\n };\n\n pipeline(\n [\n inStream,\n new Parser({\n // find only files in the assets/uploads folder\n filter(filePath: string, entry: Stats | ReadEntry) {\n if (!('type' in entry) || entry.type !== 'File') {\n return false;\n }\n return isFilePathInDirname('assets/uploads', filePath);\n },\n async onReadEntry(entry: ReadEntry) {\n await runReadEntry(async () => {\n const { path: filePath, size = 0 } = entry;\n const normalizedPath = unknownPathToPosix(filePath);\n const file = path.basename(normalizedPath);\n let metadata;\n try {\n metadata = await loadAssetMetadata(`assets/metadata/${file}.json`);\n } catch {\n throw new Error(`Failed to read metadata for ${file}`);\n }\n const asset: IAsset = {\n metadata,\n filename: file,\n filepath: normalizedPath,\n stats: { size },\n stream: entry as unknown as Readable,\n };\n await write(outStream, asset);\n });\n },\n }),\n ],\n (err) => this.#endPassThroughWhenTarIdle(outStream, () => activeAsyncEntries, err)\n );\n\n return outStream;\n }\n\n #getBackupStream() {\n const { file, encryption, compression } = this.options;\n\n const streams: StreamItemArray = [];\n\n try {\n streams.push(fs.createReadStream(file.path));\n } catch {\n throw new Error(`Could not read backup file path provided at \"${this.options.file.path}\"`);\n }\n\n if (encryption.enabled && encryption.key) {\n streams.push(utils.encryption.createDecryptionCipher(encryption.key));\n }\n\n if (compression.enabled) {\n streams.push(zip.createGunzip());\n }\n\n return chain(streams);\n }\n\n // `directory` must be posix formatted path\n #streamJsonlDirectory(directory: string) {\n const inStream = this.#getBackupStream();\n\n const outStream = new PassThrough({ objectMode: true });\n\n let activeAsyncEntries = 0;\n const runReadEntry = async (fn: () => Promise<void>) => {\n activeAsyncEntries += 1;\n try {\n await fn();\n } finally {\n activeAsyncEntries -= 1;\n }\n };\n\n pipeline(\n [\n inStream,\n new Parser({\n filter(filePath: string, entry: Stats | ReadEntry) {\n if (!('type' in entry) || entry.type !== 'File') {\n return false;\n }\n\n return isFilePathInDirname(directory, filePath);\n },\n\n async onReadEntry(entry: ReadEntry) {\n await runReadEntry(async () => {\n const transforms = [\n // JSONL parser to read the data chunks one by one (line by line)\n parser({\n checkErrors: true,\n }),\n // The JSONL parser returns each line as key/value\n (line: { key: string; value: object }) => line.value,\n ];\n\n const stream = entry.pipe(chain(transforms));\n\n try {\n for await (const chunk of stream) {\n await write(outStream, chunk);\n }\n } catch (e: unknown) {\n outStream.destroy(\n new ProviderTransferError(\n `Error parsing backup files from backup file ${entry.path}: ${\n (e as Error).message\n }`,\n {\n details: {\n error: e,\n },\n }\n )\n );\n }\n });\n },\n }),\n ],\n (err) => this.#endPassThroughWhenTarIdle(outStream, () => activeAsyncEntries, err)\n );\n\n return outStream;\n }\n\n // For collecting an entire JSON file then parsing it, not for streaming JSONL\n async #parseJSONFile<T extends object>(fileStream: Readable, filePath: string): Promise<T> {\n return new Promise<T>((resolve, reject) => {\n pipeline(\n [\n fileStream,\n // Custom backup archive parsing\n new Parser({\n /**\n * Filter the parsed entries to only keep the one that matches the given filepath\n */\n filter(entryPath: string, entry: Stats | ReadEntry) {\n if (!('type' in entry) || entry.type !== 'File') {\n return false;\n }\n\n return isPathEquivalent(entryPath, filePath);\n },\n\n async onReadEntry(entry: ReadEntry) {\n // Collect all the content of the entry stream (ReadEntry has no .collect() in tar v7)\n const chunks: Buffer[] = [];\n for await (const chunk of entry) {\n chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));\n }\n\n try {\n // Parse from buffer array to string to JSON\n const parsedContent = JSON.parse(Buffer.concat(chunks).toString());\n\n // Resolve the Promise with the parsed content\n resolve(parsedContent);\n } catch (e) {\n reject(e);\n } finally {\n // Cleanup (close the stream associated to the entry)\n entry.destroy();\n }\n },\n }),\n ],\n () => {\n // If the promise hasn't been resolved and we've parsed all\n // the archive entries, then the file doesn't exist\n reject(new Error(`File \"${filePath}\" not found`));\n }\n );\n });\n }\n}\n"],"names":["METADATA_FILE_PATH","createLocalFileSourceProvider","options","LocalFileSourceProvider","bootstrap","diagnostics","path","filePath","file","encryption","enabled","ProviderInitializationError","getMetadata","getSchemas","schemaCollection","utils","createSchemasReadStream","isEmpty","schemas","keyBy","createEntitiesReadStream","createLinksReadStream","createConfigurationReadStream","createAssetsReadStream","inStream","outStream","PassThrough","objectMode","loadAssetMetadata","bind","activeAsyncEntries","runReadEntry","fn","pipeline","Parser","filter","entry","type","isFilePathInDirname","onReadEntry","size","normalizedPath","unknownPathToPosix","basename","metadata","Error","asset","filename","filepath","stats","stream","write","err","name","key","undefined","message","report","details","createdAt","Date","origin","kind","destroy","tick","end","setImmediate","backupStream","compression","streams","push","fs","createReadStream","zip","createGunzip","chain","directory","transforms","parser","checkErrors","line","value","pipe","chunk","e","ProviderTransferError","error","fileStream","Promise","resolve","reject","entryPath","isPathEquivalent","chunks","Buffer","isBuffer","from","parsedContent","JSON","parse","concat","toString"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../../src/file/providers/source/index.ts"],"sourcesContent":["import type { Stats } from 'node:fs';\nimport type { Readable } from 'stream';\n\nimport zip from 'zlib';\nimport path from 'path';\nimport { pipeline, PassThrough } from 'stream';\nimport { finished } from 'stream/promises';\nimport fs from 'fs-extra';\nimport { Parser, type ReadEntry } from 'tar';\nimport { isEmpty, keyBy } from 'lodash/fp';\nimport { chain } from 'stream-chain';\nimport { parser } from 'stream-json/jsonl/Parser';\nimport type { Struct } from '@strapi/types';\n\nimport type {\n IAsset,\n IMetadata,\n ISourceProvider,\n ProviderType,\n IFile,\n TransferStage,\n} from '../../../types';\nimport type { IDiagnosticReporter } from '../../../utils/diagnostic';\n\nimport * as utils from '../../../utils';\nimport { write } from '../../../utils/writable-async-write';\nimport {\n ProviderInitializationError,\n ProviderTransferError,\n ProviderValidationError,\n} from '../../../errors/providers';\nimport {\n isFilePathInDirname,\n isPathEquivalent,\n unknownPathToPosix,\n validateAssetMetadata,\n} from './utils';\n\ntype StreamItemArray = Parameters<typeof chain>[0];\n\n/**\n * Constant for the metadata file path\n */\nconst METADATA_FILE_PATH = 'metadata.json';\n\n/**\n * Provider options\n */\nexport interface ILocalFileSourceProviderOptions {\n file: {\n path: string; // the file to load\n };\n\n encryption: {\n enabled: boolean; // if the file is encrypted (and should be decrypted)\n key?: string; // the key to decrypt the file\n };\n\n compression: {\n enabled: boolean; // if the file is compressed (and should be decompressed)\n };\n}\n\nexport const createLocalFileSourceProvider = (options: ILocalFileSourceProviderOptions) => {\n return new LocalFileSourceProvider(options);\n};\n\nclass LocalFileSourceProvider implements ISourceProvider {\n type: ProviderType = 'source';\n\n name = 'source::local-file';\n\n options: ILocalFileSourceProviderOptions;\n\n #metadata?: IMetadata;\n\n #assetMetadata?: Map<string, IFile>;\n\n #diagnostics?: IDiagnosticReporter;\n\n constructor(options: ILocalFileSourceProviderOptions) {\n this.options = options;\n\n const { encryption } = this.options;\n\n if (encryption.enabled && encryption.key === undefined) {\n throw new Error('Missing encryption key');\n }\n }\n\n #reportInfo(message: string) {\n this.#diagnostics?.report({\n details: {\n createdAt: new Date(),\n message,\n origin: 'file-source-provider',\n },\n kind: 'info',\n });\n }\n\n /**\n * tar `Parser` invokes the pipeline completion callback when the archive ends, but it does not\n * reliably await async `onReadEntry` — defer `end` until outstanding async entry work is done.\n */\n #endPassThroughWhenTarIdle(\n outStream: PassThrough,\n activeAsyncEntries: () => number,\n err?: Error | null\n ) {\n if (err) {\n outStream.destroy(err);\n return;\n }\n const tick = () => {\n if (activeAsyncEntries() === 0) {\n outStream.end();\n } else {\n setImmediate(tick);\n }\n };\n tick();\n }\n\n /**\n * Pre flight checks regarding the provided options, making sure that the file can be opened (decrypted, decompressed), etc.\n */\n async bootstrap(diagnostics: IDiagnosticReporter) {\n this.#diagnostics = diagnostics;\n const { path: filePath } = this.options.file;\n\n try {\n // Read the metadata to ensure the file can be parsed\n await this.#loadMetadata();\n // TODO: we might also need to read the schema.jsonl files & implements a custom stream-check\n } catch {\n if (this.options?.encryption?.enabled) {\n throw new ProviderInitializationError(\n `Key is incorrect or the file '${filePath}' is not a valid Strapi data file.`\n );\n }\n throw new ProviderInitializationError(`File '${filePath}' is not a valid Strapi data file.`);\n }\n\n if (!this.#metadata) {\n throw new ProviderInitializationError('Could not load metadata from Strapi data file.');\n }\n }\n\n async #loadMetadata() {\n const backupStream = this.#getBackupStream();\n this.#metadata = await this.#parseJSONFile<IMetadata>(backupStream, METADATA_FILE_PATH);\n }\n\n async #loadAssetMetadata(sidecarPath: string) {\n const backupStream = this.#getBackupStream();\n const filename = path.posix.basename(sidecarPath).replace(/\\.json$/, '');\n return validateAssetMetadata(\n await this.#parseJSONFile<IFile>(backupStream, sidecarPath),\n filename\n );\n }\n\n async getMetadata() {\n this.#reportInfo('getting metadata');\n if (!this.#metadata) {\n await this.#loadMetadata();\n }\n\n return this.#metadata ?? null;\n }\n\n async getSchemas() {\n this.#reportInfo('getting schemas');\n const schemaCollection = await utils.stream.collect<Struct.Schema>(\n this.createSchemasReadStream()\n );\n\n if (isEmpty(schemaCollection)) {\n throw new ProviderInitializationError('Could not load schemas from Strapi data file.');\n }\n\n // Group schema by UID\n const schemas = keyBy('uid', schemaCollection);\n\n // Transform to valid JSON\n return utils.schema.schemasToValidJSON(schemas);\n }\n\n async validateStage(stage: TransferStage) {\n if (stage !== 'assets') {\n return;\n }\n\n const uploads = new Set<string>();\n const sidecars = new Map<string, Buffer>();\n const inStream = this.#getBackupStream();\n\n await new Promise<void>((resolve, reject) => {\n let activeEntries = 0;\n let archiveFinished = false;\n let validationError: Error | undefined;\n\n const finishWhenIdle = () => {\n if (!archiveFinished || activeEntries > 0) {\n return;\n }\n if (validationError) {\n reject(validationError);\n return;\n }\n resolve();\n };\n\n pipeline(\n [\n inStream,\n new Parser({\n filter(filePath: string, entry: Stats | ReadEntry) {\n if (!('type' in entry) || entry.type !== 'File') {\n return false;\n }\n return (\n isFilePathInDirname('assets/uploads', filePath) ||\n isFilePathInDirname('assets/metadata', filePath)\n );\n },\n async onReadEntry(entry: ReadEntry) {\n activeEntries += 1;\n const normalizedPath = unknownPathToPosix(entry.path);\n const filename = path.basename(normalizedPath);\n\n try {\n if (isFilePathInDirname('assets/uploads', normalizedPath)) {\n uploads.add(filename);\n entry.resume();\n await finished(entry as unknown as Readable);\n } else {\n const chunks: Buffer[] = [];\n for await (const chunk of entry) {\n chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));\n }\n if (filename.endsWith('.json')) {\n const assetFilename = filename.slice(0, -'.json'.length);\n sidecars.set(assetFilename, Buffer.concat(chunks));\n }\n }\n } catch (error) {\n const reason = error instanceof Error ? error.message : String(error);\n validationError = new ProviderValidationError(\n `Asset metadata preflight failed for \"${filename}\": ${reason}`,\n { error }\n );\n } finally {\n activeEntries -= 1;\n finishWhenIdle();\n }\n },\n }),\n ],\n (error) => {\n archiveFinished = true;\n validationError ||= error ?? undefined;\n finishWhenIdle();\n }\n );\n });\n\n const missingSidecars = [...uploads].filter((filename) => !sidecars.has(filename)).sort();\n if (missingSidecars.length > 0) {\n throw new ProviderValidationError(\n `Asset metadata preflight failed: missing sidecar metadata for ${missingSidecars\n .map((filename) => `\"${filename}\"`)\n .join(', ')}. The destination was not modified; re-export and try again.`\n );\n }\n\n const metadata = new Map<string, IFile>();\n for (const filename of uploads) {\n try {\n metadata.set(\n filename,\n validateAssetMetadata(JSON.parse(sidecars.get(filename)!.toString()), filename)\n );\n } catch (error) {\n const reason = error instanceof Error ? error.message : String(error);\n throw new ProviderValidationError(\n `Asset metadata preflight failed for \"${filename}.json\": ${reason}. The destination was not modified; re-export and try again.`,\n { error }\n );\n }\n }\n\n this.#assetMetadata = metadata;\n }\n\n createEntitiesReadStream(): Readable {\n this.#reportInfo('creating entities read stream');\n return this.#streamJsonlDirectory('entities');\n }\n\n createSchemasReadStream(): Readable {\n this.#reportInfo('creating schemas read stream');\n return this.#streamJsonlDirectory('schemas');\n }\n\n createLinksReadStream(): Readable {\n this.#reportInfo('creating links read stream');\n return this.#streamJsonlDirectory('links');\n }\n\n createConfigurationReadStream(): Readable {\n this.#reportInfo('creating configuration read stream');\n // NOTE: TBD\n return this.#streamJsonlDirectory('configuration');\n }\n\n createAssetsReadStream(): Readable | Promise<Readable> {\n const inStream = this.#getBackupStream();\n const outStream = new PassThrough({ objectMode: true });\n const loadAssetMetadata = this.#loadAssetMetadata.bind(this);\n const assetMetadata = this.#assetMetadata;\n this.#reportInfo('creating assets read stream');\n\n let activeAsyncEntries = 0;\n const runReadEntry = async (fn: () => Promise<void>) => {\n activeAsyncEntries += 1;\n try {\n await fn();\n } finally {\n activeAsyncEntries -= 1;\n }\n };\n\n pipeline(\n [\n inStream,\n new Parser({\n // find only files in the assets/uploads folder\n filter(filePath: string, entry: Stats | ReadEntry) {\n if (!('type' in entry) || entry.type !== 'File') {\n return false;\n }\n return isFilePathInDirname('assets/uploads', filePath);\n },\n async onReadEntry(entry: ReadEntry) {\n await runReadEntry(async () => {\n const { path: filePath, size = 0 } = entry;\n const normalizedPath = unknownPathToPosix(filePath);\n const file = path.basename(normalizedPath);\n const metadata =\n assetMetadata?.get(file) ??\n (await loadAssetMetadata(`assets/metadata/${file}.json`).catch(() => {\n throw new Error(`Failed to read metadata for ${file}`);\n }));\n const asset: IAsset = {\n metadata,\n filename: file,\n filepath: normalizedPath,\n stats: { size },\n stream: entry as unknown as Readable,\n };\n await write(outStream, asset);\n });\n },\n }),\n ],\n (err) => this.#endPassThroughWhenTarIdle(outStream, () => activeAsyncEntries, err)\n );\n\n return outStream;\n }\n\n #getBackupStream() {\n const { file, encryption, compression } = this.options;\n\n const streams: StreamItemArray = [];\n\n try {\n streams.push(fs.createReadStream(file.path));\n } catch {\n throw new Error(`Could not read backup file path provided at \"${this.options.file.path}\"`);\n }\n\n if (encryption.enabled && encryption.key) {\n streams.push(utils.encryption.createDecryptionCipher(encryption.key));\n }\n\n if (compression.enabled) {\n streams.push(zip.createGunzip());\n }\n\n return chain(streams);\n }\n\n // `directory` must be posix formatted path\n #streamJsonlDirectory(directory: string) {\n const inStream = this.#getBackupStream();\n\n const outStream = new PassThrough({ objectMode: true });\n\n let activeAsyncEntries = 0;\n const runReadEntry = async (fn: () => Promise<void>) => {\n activeAsyncEntries += 1;\n try {\n await fn();\n } finally {\n activeAsyncEntries -= 1;\n }\n };\n\n pipeline(\n [\n inStream,\n new Parser({\n filter(filePath: string, entry: Stats | ReadEntry) {\n if (!('type' in entry) || entry.type !== 'File') {\n return false;\n }\n\n return isFilePathInDirname(directory, filePath);\n },\n\n async onReadEntry(entry: ReadEntry) {\n await runReadEntry(async () => {\n const transforms = [\n // JSONL parser to read the data chunks one by one (line by line)\n parser({\n checkErrors: true,\n }),\n // The JSONL parser returns each line as key/value\n (line: { key: string; value: object }) => line.value,\n ];\n\n const stream = entry.pipe(chain(transforms));\n\n try {\n for await (const chunk of stream) {\n await write(outStream, chunk);\n }\n } catch (e: unknown) {\n outStream.destroy(\n new ProviderTransferError(\n `Error parsing backup files from backup file ${entry.path}: ${\n (e as Error).message\n }`,\n {\n details: {\n error: e,\n },\n }\n )\n );\n }\n });\n },\n }),\n ],\n (err) => this.#endPassThroughWhenTarIdle(outStream, () => activeAsyncEntries, err)\n );\n\n return outStream;\n }\n\n // For collecting an entire JSON file then parsing it, not for streaming JSONL\n async #parseJSONFile<T extends object>(fileStream: Readable, filePath: string): Promise<T> {\n return new Promise<T>((resolve, reject) => {\n pipeline(\n [\n fileStream,\n // Custom backup archive parsing\n new Parser({\n /**\n * Filter the parsed entries to only keep the one that matches the given filepath\n */\n filter(entryPath: string, entry: Stats | ReadEntry) {\n if (!('type' in entry) || entry.type !== 'File') {\n return false;\n }\n\n return isPathEquivalent(entryPath, filePath);\n },\n\n async onReadEntry(entry: ReadEntry) {\n // Collect all the content of the entry stream (ReadEntry has no .collect() in tar v7)\n const chunks: Buffer[] = [];\n for await (const chunk of entry) {\n chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));\n }\n\n try {\n // Parse from buffer array to string to JSON\n const parsedContent = JSON.parse(Buffer.concat(chunks).toString());\n\n // Resolve the Promise with the parsed content\n resolve(parsedContent);\n } catch (e) {\n reject(e);\n } finally {\n // Cleanup (close the stream associated to the entry)\n entry.destroy();\n }\n },\n }),\n ],\n () => {\n // If the promise hasn't been resolved and we've parsed all\n // the archive entries, then the file doesn't exist\n reject(new Error(`File \"${filePath}\" not found`));\n }\n );\n });\n }\n}\n"],"names":["METADATA_FILE_PATH","createLocalFileSourceProvider","options","LocalFileSourceProvider","bootstrap","diagnostics","path","filePath","file","encryption","enabled","ProviderInitializationError","getMetadata","getSchemas","schemaCollection","utils","createSchemasReadStream","isEmpty","schemas","keyBy","validateStage","stage","uploads","Set","sidecars","Map","inStream","Promise","resolve","reject","activeEntries","archiveFinished","validationError","finishWhenIdle","pipeline","Parser","filter","entry","type","isFilePathInDirname","onReadEntry","normalizedPath","unknownPathToPosix","filename","basename","add","resume","finished","chunks","chunk","push","Buffer","isBuffer","from","endsWith","assetFilename","slice","length","set","concat","error","reason","Error","message","String","ProviderValidationError","undefined","missingSidecars","has","sort","map","join","metadata","validateAssetMetadata","JSON","parse","get","toString","createEntitiesReadStream","createLinksReadStream","createConfigurationReadStream","createAssetsReadStream","outStream","PassThrough","objectMode","loadAssetMetadata","bind","assetMetadata","activeAsyncEntries","runReadEntry","fn","size","catch","asset","filepath","stats","stream","write","err","name","key","report","details","createdAt","Date","origin","kind","destroy","tick","end","setImmediate","backupStream","sidecarPath","posix","replace","compression","streams","fs","createReadStream","zip","createGunzip","chain","directory","transforms","parser","checkErrors","line","value","pipe","e","ProviderTransferError","fileStream","entryPath","isPathEquivalent","parsedContent"],"mappings":"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"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import zip from 'zlib';
|
|
2
2
|
import path from 'path';
|
|
3
|
-
import {
|
|
3
|
+
import { pipeline, PassThrough } from 'stream';
|
|
4
|
+
import { finished } from 'stream/promises';
|
|
4
5
|
import fs__default from 'fs-extra';
|
|
5
6
|
import { Parser } from 'tar';
|
|
6
7
|
import { isEmpty, keyBy } from 'lodash/fp';
|
|
@@ -12,8 +13,8 @@ import { write } from '../../../utils/writable-async-write.mjs';
|
|
|
12
13
|
import { collect } from '../../../utils/stream.mjs';
|
|
13
14
|
import { schemasToValidJSON } from '../../../utils/schema.mjs';
|
|
14
15
|
import 'events';
|
|
15
|
-
import { ProviderInitializationError, ProviderTransferError } from '../../../errors/providers.mjs';
|
|
16
|
-
import { isFilePathInDirname,
|
|
16
|
+
import { ProviderInitializationError, ProviderValidationError, ProviderTransferError } from '../../../errors/providers.mjs';
|
|
17
|
+
import { unknownPathToPosix, isFilePathInDirname, validateAssetMetadata, isPathEquivalent } from './utils.mjs';
|
|
17
18
|
|
|
18
19
|
function _class_private_field_loose_base(receiver, privateKey) {
|
|
19
20
|
if (!Object.prototype.hasOwnProperty.call(receiver, privateKey)) {
|
|
@@ -31,7 +32,7 @@ function _class_private_field_loose_key(name) {
|
|
|
31
32
|
const createLocalFileSourceProvider = (options)=>{
|
|
32
33
|
return new LocalFileSourceProvider(options);
|
|
33
34
|
};
|
|
34
|
-
var _metadata = /*#__PURE__*/ _class_private_field_loose_key("_metadata"), _diagnostics = /*#__PURE__*/ _class_private_field_loose_key("_diagnostics"), _reportInfo = /*#__PURE__*/ _class_private_field_loose_key("_reportInfo"), /**
|
|
35
|
+
var _metadata = /*#__PURE__*/ _class_private_field_loose_key("_metadata"), _assetMetadata = /*#__PURE__*/ _class_private_field_loose_key("_assetMetadata"), _diagnostics = /*#__PURE__*/ _class_private_field_loose_key("_diagnostics"), _reportInfo = /*#__PURE__*/ _class_private_field_loose_key("_reportInfo"), /**
|
|
35
36
|
* tar `Parser` invokes the pipeline completion callback when the archive ends, but it does not
|
|
36
37
|
* reliably await async `onReadEntry` — defer `end` until outstanding async entry work is done.
|
|
37
38
|
*/ _endPassThroughWhenTarIdle = /*#__PURE__*/ _class_private_field_loose_key("_endPassThroughWhenTarIdle"), _loadMetadata = /*#__PURE__*/ _class_private_field_loose_key("_loadMetadata"), _loadAssetMetadata = /*#__PURE__*/ _class_private_field_loose_key("_loadAssetMetadata"), _getBackupStream = /*#__PURE__*/ _class_private_field_loose_key("_getBackupStream"), // `directory` must be posix formatted path
|
|
@@ -74,6 +75,91 @@ class LocalFileSourceProvider {
|
|
|
74
75
|
// Transform to valid JSON
|
|
75
76
|
return schemasToValidJSON(schemas);
|
|
76
77
|
}
|
|
78
|
+
async validateStage(stage) {
|
|
79
|
+
if (stage !== 'assets') {
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
const uploads = new Set();
|
|
83
|
+
const sidecars = new Map();
|
|
84
|
+
const inStream = _class_private_field_loose_base(this, _getBackupStream)[_getBackupStream]();
|
|
85
|
+
await new Promise((resolve, reject)=>{
|
|
86
|
+
let activeEntries = 0;
|
|
87
|
+
let archiveFinished = false;
|
|
88
|
+
let validationError;
|
|
89
|
+
const finishWhenIdle = ()=>{
|
|
90
|
+
if (!archiveFinished || activeEntries > 0) {
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
if (validationError) {
|
|
94
|
+
reject(validationError);
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
resolve();
|
|
98
|
+
};
|
|
99
|
+
pipeline([
|
|
100
|
+
inStream,
|
|
101
|
+
new Parser({
|
|
102
|
+
filter (filePath, entry) {
|
|
103
|
+
if (!('type' in entry) || entry.type !== 'File') {
|
|
104
|
+
return false;
|
|
105
|
+
}
|
|
106
|
+
return isFilePathInDirname('assets/uploads', filePath) || isFilePathInDirname('assets/metadata', filePath);
|
|
107
|
+
},
|
|
108
|
+
async onReadEntry (entry) {
|
|
109
|
+
activeEntries += 1;
|
|
110
|
+
const normalizedPath = unknownPathToPosix(entry.path);
|
|
111
|
+
const filename = path.basename(normalizedPath);
|
|
112
|
+
try {
|
|
113
|
+
if (isFilePathInDirname('assets/uploads', normalizedPath)) {
|
|
114
|
+
uploads.add(filename);
|
|
115
|
+
entry.resume();
|
|
116
|
+
await finished(entry);
|
|
117
|
+
} else {
|
|
118
|
+
const chunks = [];
|
|
119
|
+
for await (const chunk of entry){
|
|
120
|
+
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
121
|
+
}
|
|
122
|
+
if (filename.endsWith('.json')) {
|
|
123
|
+
const assetFilename = filename.slice(0, -'.json'.length);
|
|
124
|
+
sidecars.set(assetFilename, Buffer.concat(chunks));
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
} catch (error) {
|
|
128
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
129
|
+
validationError = new ProviderValidationError(`Asset metadata preflight failed for "${filename}": ${reason}`, {
|
|
130
|
+
error
|
|
131
|
+
});
|
|
132
|
+
} finally{
|
|
133
|
+
activeEntries -= 1;
|
|
134
|
+
finishWhenIdle();
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
})
|
|
138
|
+
], (error)=>{
|
|
139
|
+
archiveFinished = true;
|
|
140
|
+
validationError || (validationError = error ?? undefined);
|
|
141
|
+
finishWhenIdle();
|
|
142
|
+
});
|
|
143
|
+
});
|
|
144
|
+
const missingSidecars = [
|
|
145
|
+
...uploads
|
|
146
|
+
].filter((filename)=>!sidecars.has(filename)).sort();
|
|
147
|
+
if (missingSidecars.length > 0) {
|
|
148
|
+
throw new ProviderValidationError(`Asset metadata preflight failed: missing sidecar metadata for ${missingSidecars.map((filename)=>`"${filename}"`).join(', ')}. The destination was not modified; re-export and try again.`);
|
|
149
|
+
}
|
|
150
|
+
const metadata = new Map();
|
|
151
|
+
for (const filename of uploads){
|
|
152
|
+
try {
|
|
153
|
+
metadata.set(filename, validateAssetMetadata(JSON.parse(sidecars.get(filename).toString()), filename));
|
|
154
|
+
} catch (error) {
|
|
155
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
156
|
+
throw new ProviderValidationError(`Asset metadata preflight failed for "${filename}.json": ${reason}. The destination was not modified; re-export and try again.`, {
|
|
157
|
+
error
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
_class_private_field_loose_base(this, _assetMetadata)[_assetMetadata] = metadata;
|
|
162
|
+
}
|
|
77
163
|
createEntitiesReadStream() {
|
|
78
164
|
_class_private_field_loose_base(this, _reportInfo)[_reportInfo]('creating entities read stream');
|
|
79
165
|
return _class_private_field_loose_base(this, _streamJsonlDirectory)[_streamJsonlDirectory]('entities');
|
|
@@ -97,6 +183,7 @@ class LocalFileSourceProvider {
|
|
|
97
183
|
objectMode: true
|
|
98
184
|
});
|
|
99
185
|
const loadAssetMetadata = _class_private_field_loose_base(this, _loadAssetMetadata)[_loadAssetMetadata].bind(this);
|
|
186
|
+
const assetMetadata = _class_private_field_loose_base(this, _assetMetadata)[_assetMetadata];
|
|
100
187
|
_class_private_field_loose_base(this, _reportInfo)[_reportInfo]('creating assets read stream');
|
|
101
188
|
let activeAsyncEntries = 0;
|
|
102
189
|
const runReadEntry = async (fn)=>{
|
|
@@ -122,12 +209,9 @@ class LocalFileSourceProvider {
|
|
|
122
209
|
const { path: filePath, size = 0 } = entry;
|
|
123
210
|
const normalizedPath = unknownPathToPosix(filePath);
|
|
124
211
|
const file = path.basename(normalizedPath);
|
|
125
|
-
|
|
126
|
-
try {
|
|
127
|
-
metadata = await loadAssetMetadata(`assets/metadata/${file}.json`);
|
|
128
|
-
} catch {
|
|
212
|
+
const metadata = assetMetadata?.get(file) ?? await loadAssetMetadata(`assets/metadata/${file}.json`).catch(()=>{
|
|
129
213
|
throw new Error(`Failed to read metadata for ${file}`);
|
|
130
|
-
}
|
|
214
|
+
});
|
|
131
215
|
const asset = {
|
|
132
216
|
metadata,
|
|
133
217
|
filename: file,
|
|
@@ -171,6 +255,10 @@ class LocalFileSourceProvider {
|
|
|
171
255
|
writable: true,
|
|
172
256
|
value: void 0
|
|
173
257
|
});
|
|
258
|
+
Object.defineProperty(this, _assetMetadata, {
|
|
259
|
+
writable: true,
|
|
260
|
+
value: void 0
|
|
261
|
+
});
|
|
174
262
|
Object.defineProperty(this, _diagnostics, {
|
|
175
263
|
writable: true,
|
|
176
264
|
value: void 0
|
|
@@ -212,9 +300,10 @@ async function loadMetadata() {
|
|
|
212
300
|
const backupStream = _class_private_field_loose_base(this, _getBackupStream)[_getBackupStream]();
|
|
213
301
|
_class_private_field_loose_base(this, _metadata)[_metadata] = await _class_private_field_loose_base(this, _parseJSONFile)[_parseJSONFile](backupStream, METADATA_FILE_PATH);
|
|
214
302
|
}
|
|
215
|
-
async function loadAssetMetadata(
|
|
303
|
+
async function loadAssetMetadata(sidecarPath) {
|
|
216
304
|
const backupStream = _class_private_field_loose_base(this, _getBackupStream)[_getBackupStream]();
|
|
217
|
-
|
|
305
|
+
const filename = path.posix.basename(sidecarPath).replace(/\.json$/, '');
|
|
306
|
+
return validateAssetMetadata(await _class_private_field_loose_base(this, _parseJSONFile)[_parseJSONFile](backupStream, sidecarPath), filename);
|
|
218
307
|
}
|
|
219
308
|
function getBackupStream() {
|
|
220
309
|
const { file, encryption, compression } = this.options;
|