@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.
Files changed (41) hide show
  1. package/dist/directory/providers/destination/index.d.ts.map +1 -1
  2. package/dist/directory/providers/destination/index.js +11 -1
  3. package/dist/directory/providers/destination/index.js.map +1 -1
  4. package/dist/directory/providers/destination/index.mjs +11 -1
  5. package/dist/directory/providers/destination/index.mjs.map +1 -1
  6. package/dist/directory/providers/source/index.d.ts +2 -1
  7. package/dist/directory/providers/source/index.d.ts.map +1 -1
  8. package/dist/directory/providers/source/index.js +45 -12
  9. package/dist/directory/providers/source/index.js.map +1 -1
  10. package/dist/directory/providers/source/index.mjs +47 -14
  11. package/dist/directory/providers/source/index.mjs.map +1 -1
  12. package/dist/engine/index.d.ts +1 -0
  13. package/dist/engine/index.d.ts.map +1 -1
  14. package/dist/engine/index.js +62 -5
  15. package/dist/engine/index.js.map +1 -1
  16. package/dist/engine/index.mjs +62 -5
  17. package/dist/engine/index.mjs.map +1 -1
  18. package/dist/file/providers/destination/index.d.ts.map +1 -1
  19. package/dist/file/providers/destination/index.js +11 -1
  20. package/dist/file/providers/destination/index.js.map +1 -1
  21. package/dist/file/providers/destination/index.mjs +11 -1
  22. package/dist/file/providers/destination/index.mjs.map +1 -1
  23. package/dist/file/providers/source/index.d.ts +2 -1
  24. package/dist/file/providers/source/index.d.ts.map +1 -1
  25. package/dist/file/providers/source/index.js +97 -8
  26. package/dist/file/providers/source/index.js.map +1 -1
  27. package/dist/file/providers/source/index.mjs +100 -11
  28. package/dist/file/providers/source/index.mjs.map +1 -1
  29. package/dist/file/providers/source/utils.d.ts +2 -0
  30. package/dist/file/providers/source/utils.d.ts.map +1 -1
  31. package/dist/file/providers/source/utils.js +43 -0
  32. package/dist/file/providers/source/utils.js.map +1 -1
  33. package/dist/file/providers/source/utils.mjs +43 -1
  34. package/dist/file/providers/source/utils.mjs.map +1 -1
  35. package/dist/strapi/providers/local-source/assets.js +2 -2
  36. package/dist/strapi/providers/local-source/assets.js.map +1 -1
  37. package/dist/strapi/providers/local-source/assets.mjs +2 -2
  38. package/dist/strapi/providers/local-source/assets.mjs.map +1 -1
  39. package/dist/types/providers.d.ts +10 -0
  40. package/dist/types/providers.d.ts.map +1 -1
  41. package/package.json +6 -6
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","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.mjs","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,3 +1,5 @@
1
+ import type { IFile } from '../../../types';
2
+ export declare const validateAssetMetadata: (metadata: unknown, filename?: string) => IFile;
1
3
  /**
2
4
  * Note: in versions of the transfer engine <=4.9.0, exports were generated with windows paths
3
5
  * on Windows systems, and posix paths on posix systems.
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../../src/file/providers/source/utils.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;KAUK;AAEL;;;;;;;GAOG;AACH,eAAO,MAAM,mBAAmB,GAAI,cAAc,MAAM,EAAE,UAAU,MAAM,YAGzE,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,gBAAgB,GAAI,OAAO,MAAM,EAAE,OAAO,MAAM,YAM5D,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,kBAAkB,GAAI,UAAU,MAAM,WAOlD,CAAC"}
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../../src/file/providers/source/utils.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAE5C,eAAO,MAAM,qBAAqB,GAAI,UAAU,OAAO,EAAE,WAAW,MAAM,KAAG,KAuC5E,CAAC;AAEF;;;;;;;;;;KAUK;AAEL;;;;;;;GAOG;AACH,eAAO,MAAM,mBAAmB,GAAI,cAAc,MAAM,EAAE,UAAU,MAAM,YAGzE,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,gBAAgB,GAAI,OAAO,MAAM,EAAE,OAAO,MAAM,YAM5D,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,kBAAkB,GAAI,UAAU,MAAM,WAOlD,CAAC"}
@@ -6,6 +6,48 @@ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
6
6
 
7
7
  var path__default = /*#__PURE__*/_interopDefault(path);
8
8
 
9
+ const validateAssetMetadata = (metadata, filename)=>{
10
+ if (metadata === null || typeof metadata !== 'object' || Array.isArray(metadata)) {
11
+ throw new TypeError('Asset sidecar metadata must be a JSON object');
12
+ }
13
+ const file = metadata;
14
+ const invalidFields = [];
15
+ if (!Number.isInteger(file.id) || file.id <= 0) {
16
+ invalidFields.push('id');
17
+ }
18
+ if (!Number.isFinite(file.size) || file.size < 0) {
19
+ invalidFields.push('size');
20
+ }
21
+ for (const field of [
22
+ 'name',
23
+ 'hash',
24
+ 'mime',
25
+ 'url'
26
+ ]){
27
+ if (typeof file[field] !== 'string' || file[field].length === 0) {
28
+ invalidFields.push(field);
29
+ }
30
+ }
31
+ for (const field of [
32
+ 'ext',
33
+ 'type',
34
+ 'mainHash'
35
+ ]){
36
+ if (file[field] != null && typeof file[field] !== 'string') {
37
+ invalidFields.push(field);
38
+ }
39
+ }
40
+ if (invalidFields.length > 0) {
41
+ throw new TypeError(`Asset sidecar metadata has invalid required fields: ${invalidFields.join(', ')}`);
42
+ }
43
+ const typedFile = file;
44
+ const expectedFilename = `${typedFile.hash}${typedFile.ext ?? ''}`;
45
+ const legacyFilename = `${typedFile.hash}${typedFile.ext}`;
46
+ if (filename && filename !== expectedFilename && filename !== legacyFilename) {
47
+ throw new TypeError(`Asset sidecar metadata does not match upload filename "${filename}"`);
48
+ }
49
+ return typedFile;
50
+ };
9
51
  /**
10
52
  * Note: in versions of the transfer engine <=4.9.0, exports were generated with windows paths
11
53
  * on Windows systems, and posix paths on posix systems.
@@ -57,4 +99,5 @@ var path__default = /*#__PURE__*/_interopDefault(path);
57
99
  exports.isFilePathInDirname = isFilePathInDirname;
58
100
  exports.isPathEquivalent = isPathEquivalent;
59
101
  exports.unknownPathToPosix = unknownPathToPosix;
102
+ exports.validateAssetMetadata = validateAssetMetadata;
60
103
  //# sourceMappingURL=utils.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"utils.js","sources":["../../../../src/file/providers/source/utils.ts"],"sourcesContent":["import path from 'path';\n\n/**\n * Note: in versions of the transfer engine <=4.9.0, exports were generated with windows paths\n * on Windows systems, and posix paths on posix systems.\n *\n * We now store all paths as posix, but need to leave a separator conversion for legacy purposes, and to\n * support manually-created tar files coming from Windows systems (ie, if a user creates a\n * backup file with a windows tar tool rather than using the `export` command)\n *\n * Because of this, export/import files may never contain files with a forward slash in the name, even escaped\n *\n * */\n\n/**\n * Check if the directory of a given filePath (which can be either posix or win32) resolves to the same as the given posix-format path posixDirName\n * We must be able to assume the first argument is a path to a directory and the second is a path to a file, otherwise path.dirname will interpret a path without any slashes as the filename\n *\n * @param {string} posixDirName A posix path pointing to a directory\n * @param {string} filePath an unknown filesystem path pointing to a file\n * @returns {boolean} is the file located in the given directory\n */\nexport const isFilePathInDirname = (posixDirName: string, filePath: string) => {\n const normalizedDir = path.posix.dirname(unknownPathToPosix(filePath));\n return isPathEquivalent(posixDirName, normalizedDir);\n};\n\n/**\n * Check if two paths that can be either in posix or win32 format resolves to the same file\n *\n * @param {string} pathA a path that may be either win32 or posix\n * @param {string} pathB a path that may be either win32 or posix\n *\n * @returns {boolean} do paths point to the same place\n */\nexport const isPathEquivalent = (pathA: string, pathB: string) => {\n // Check if paths appear to be win32 or posix, and if win32 convert to posix\n const normalizedPathA = path.posix.normalize(unknownPathToPosix(pathA));\n const normalizedPathB = path.posix.normalize(unknownPathToPosix(pathB));\n\n return !path.posix.relative(normalizedPathB, normalizedPathA).length;\n};\n\n/**\n * Convert an unknown format path (win32 or posix) to a posix path\n *\n * @param {string} filePath a path that may be either win32 or posix\n *\n * @returns {string} a posix path\n */\nexport const unknownPathToPosix = (filePath: string) => {\n // if it includes a forward slash, it must be posix already -- we will not support win32 with mixed path separators\n if (filePath.includes(path.posix.sep)) {\n return filePath;\n }\n\n return path.normalize(filePath).split(path.win32.sep).join(path.posix.sep);\n};\n"],"names":["isFilePathInDirname","posixDirName","filePath","normalizedDir","path","posix","dirname","unknownPathToPosix","isPathEquivalent","pathA","pathB","normalizedPathA","normalize","normalizedPathB","relative","length","includes","sep","split","win32","join"],"mappings":";;;;;;;;AAEA;;;;;;;;;;;;;;;;;AAmBC,IACM,MAAMA,mBAAAA,GAAsB,CAACC,YAAAA,EAAsBC,QAAAA,GAAAA;AACxD,IAAA,MAAMC,gBAAgBC,qBAAAA,CAAKC,KAAK,CAACC,OAAO,CAACC,kBAAAA,CAAmBL,QAAAA,CAAAA,CAAAA;AAC5D,IAAA,OAAOM,iBAAiBP,YAAAA,EAAcE,aAAAA,CAAAA;AACxC;AAEA;;;;;;;AAOC,IACM,MAAMK,gBAAAA,GAAmB,CAACC,KAAAA,EAAeC,KAAAA,GAAAA;;AAE9C,IAAA,MAAMC,kBAAkBP,qBAAAA,CAAKC,KAAK,CAACO,SAAS,CAACL,kBAAAA,CAAmBE,KAAAA,CAAAA,CAAAA;AAChE,IAAA,MAAMI,kBAAkBT,qBAAAA,CAAKC,KAAK,CAACO,SAAS,CAACL,kBAAAA,CAAmBG,KAAAA,CAAAA,CAAAA;IAEhE,OAAO,CAACN,sBAAKC,KAAK,CAACS,QAAQ,CAACD,eAAAA,EAAiBF,iBAAiBI,MAAM;AACtE;AAEA;;;;;;IAOO,MAAMR,kBAAAA,GAAqB,CAACL,QAAAA,GAAAA;;AAEjC,IAAA,IAAIA,SAASc,QAAQ,CAACZ,sBAAKC,KAAK,CAACY,GAAG,CAAA,EAAG;QACrC,OAAOf,QAAAA;AACT,IAAA;AAEA,IAAA,OAAOE,sBAAKQ,SAAS,CAACV,QAAAA,CAAAA,CAAUgB,KAAK,CAACd,qBAAAA,CAAKe,KAAK,CAACF,GAAG,EAAEG,IAAI,CAAChB,qBAAAA,CAAKC,KAAK,CAACY,GAAG,CAAA;AAC3E;;;;;;"}
1
+ {"version":3,"file":"utils.js","sources":["../../../../src/file/providers/source/utils.ts"],"sourcesContent":["import path from 'path';\n\nimport type { IFile } from '../../../types';\n\nexport const validateAssetMetadata = (metadata: unknown, filename?: string): IFile => {\n if (metadata === null || typeof metadata !== 'object' || Array.isArray(metadata)) {\n throw new TypeError('Asset sidecar metadata must be a JSON object');\n }\n\n const file = metadata as Record<string, unknown>;\n const invalidFields: string[] = [];\n\n if (!Number.isInteger(file.id) || (file.id as number) <= 0) {\n invalidFields.push('id');\n }\n if (!Number.isFinite(file.size) || (file.size as number) < 0) {\n invalidFields.push('size');\n }\n for (const field of ['name', 'hash', 'mime', 'url'] as const) {\n if (typeof file[field] !== 'string' || file[field].length === 0) {\n invalidFields.push(field);\n }\n }\n for (const field of ['ext', 'type', 'mainHash'] as const) {\n if (file[field] != null && typeof file[field] !== 'string') {\n invalidFields.push(field);\n }\n }\n\n if (invalidFields.length > 0) {\n throw new TypeError(\n `Asset sidecar metadata has invalid required fields: ${invalidFields.join(', ')}`\n );\n }\n\n const typedFile = file as unknown as IFile;\n const expectedFilename = `${typedFile.hash}${typedFile.ext ?? ''}`;\n const legacyFilename = `${typedFile.hash}${typedFile.ext}`;\n if (filename && filename !== expectedFilename && filename !== legacyFilename) {\n throw new TypeError(`Asset sidecar metadata does not match upload filename \"${filename}\"`);\n }\n\n return typedFile;\n};\n\n/**\n * Note: in versions of the transfer engine <=4.9.0, exports were generated with windows paths\n * on Windows systems, and posix paths on posix systems.\n *\n * We now store all paths as posix, but need to leave a separator conversion for legacy purposes, and to\n * support manually-created tar files coming from Windows systems (ie, if a user creates a\n * backup file with a windows tar tool rather than using the `export` command)\n *\n * Because of this, export/import files may never contain files with a forward slash in the name, even escaped\n *\n * */\n\n/**\n * Check if the directory of a given filePath (which can be either posix or win32) resolves to the same as the given posix-format path posixDirName\n * We must be able to assume the first argument is a path to a directory and the second is a path to a file, otherwise path.dirname will interpret a path without any slashes as the filename\n *\n * @param {string} posixDirName A posix path pointing to a directory\n * @param {string} filePath an unknown filesystem path pointing to a file\n * @returns {boolean} is the file located in the given directory\n */\nexport const isFilePathInDirname = (posixDirName: string, filePath: string) => {\n const normalizedDir = path.posix.dirname(unknownPathToPosix(filePath));\n return isPathEquivalent(posixDirName, normalizedDir);\n};\n\n/**\n * Check if two paths that can be either in posix or win32 format resolves to the same file\n *\n * @param {string} pathA a path that may be either win32 or posix\n * @param {string} pathB a path that may be either win32 or posix\n *\n * @returns {boolean} do paths point to the same place\n */\nexport const isPathEquivalent = (pathA: string, pathB: string) => {\n // Check if paths appear to be win32 or posix, and if win32 convert to posix\n const normalizedPathA = path.posix.normalize(unknownPathToPosix(pathA));\n const normalizedPathB = path.posix.normalize(unknownPathToPosix(pathB));\n\n return !path.posix.relative(normalizedPathB, normalizedPathA).length;\n};\n\n/**\n * Convert an unknown format path (win32 or posix) to a posix path\n *\n * @param {string} filePath a path that may be either win32 or posix\n *\n * @returns {string} a posix path\n */\nexport const unknownPathToPosix = (filePath: string) => {\n // if it includes a forward slash, it must be posix already -- we will not support win32 with mixed path separators\n if (filePath.includes(path.posix.sep)) {\n return filePath;\n }\n\n return path.normalize(filePath).split(path.win32.sep).join(path.posix.sep);\n};\n"],"names":["validateAssetMetadata","metadata","filename","Array","isArray","TypeError","file","invalidFields","Number","isInteger","id","push","isFinite","size","field","length","join","typedFile","expectedFilename","hash","ext","legacyFilename","isFilePathInDirname","posixDirName","filePath","normalizedDir","path","posix","dirname","unknownPathToPosix","isPathEquivalent","pathA","pathB","normalizedPathA","normalize","normalizedPathB","relative","includes","sep","split","win32"],"mappings":"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"}
@@ -1,5 +1,47 @@
1
1
  import path from 'path';
2
2
 
3
+ const validateAssetMetadata = (metadata, filename)=>{
4
+ if (metadata === null || typeof metadata !== 'object' || Array.isArray(metadata)) {
5
+ throw new TypeError('Asset sidecar metadata must be a JSON object');
6
+ }
7
+ const file = metadata;
8
+ const invalidFields = [];
9
+ if (!Number.isInteger(file.id) || file.id <= 0) {
10
+ invalidFields.push('id');
11
+ }
12
+ if (!Number.isFinite(file.size) || file.size < 0) {
13
+ invalidFields.push('size');
14
+ }
15
+ for (const field of [
16
+ 'name',
17
+ 'hash',
18
+ 'mime',
19
+ 'url'
20
+ ]){
21
+ if (typeof file[field] !== 'string' || file[field].length === 0) {
22
+ invalidFields.push(field);
23
+ }
24
+ }
25
+ for (const field of [
26
+ 'ext',
27
+ 'type',
28
+ 'mainHash'
29
+ ]){
30
+ if (file[field] != null && typeof file[field] !== 'string') {
31
+ invalidFields.push(field);
32
+ }
33
+ }
34
+ if (invalidFields.length > 0) {
35
+ throw new TypeError(`Asset sidecar metadata has invalid required fields: ${invalidFields.join(', ')}`);
36
+ }
37
+ const typedFile = file;
38
+ const expectedFilename = `${typedFile.hash}${typedFile.ext ?? ''}`;
39
+ const legacyFilename = `${typedFile.hash}${typedFile.ext}`;
40
+ if (filename && filename !== expectedFilename && filename !== legacyFilename) {
41
+ throw new TypeError(`Asset sidecar metadata does not match upload filename "${filename}"`);
42
+ }
43
+ return typedFile;
44
+ };
3
45
  /**
4
46
  * Note: in versions of the transfer engine <=4.9.0, exports were generated with windows paths
5
47
  * on Windows systems, and posix paths on posix systems.
@@ -48,5 +90,5 @@ import path from 'path';
48
90
  return path.normalize(filePath).split(path.win32.sep).join(path.posix.sep);
49
91
  };
50
92
 
51
- export { isFilePathInDirname, isPathEquivalent, unknownPathToPosix };
93
+ export { isFilePathInDirname, isPathEquivalent, unknownPathToPosix, validateAssetMetadata };
52
94
  //# sourceMappingURL=utils.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"utils.mjs","sources":["../../../../src/file/providers/source/utils.ts"],"sourcesContent":["import path from 'path';\n\n/**\n * Note: in versions of the transfer engine <=4.9.0, exports were generated with windows paths\n * on Windows systems, and posix paths on posix systems.\n *\n * We now store all paths as posix, but need to leave a separator conversion for legacy purposes, and to\n * support manually-created tar files coming from Windows systems (ie, if a user creates a\n * backup file with a windows tar tool rather than using the `export` command)\n *\n * Because of this, export/import files may never contain files with a forward slash in the name, even escaped\n *\n * */\n\n/**\n * Check if the directory of a given filePath (which can be either posix or win32) resolves to the same as the given posix-format path posixDirName\n * We must be able to assume the first argument is a path to a directory and the second is a path to a file, otherwise path.dirname will interpret a path without any slashes as the filename\n *\n * @param {string} posixDirName A posix path pointing to a directory\n * @param {string} filePath an unknown filesystem path pointing to a file\n * @returns {boolean} is the file located in the given directory\n */\nexport const isFilePathInDirname = (posixDirName: string, filePath: string) => {\n const normalizedDir = path.posix.dirname(unknownPathToPosix(filePath));\n return isPathEquivalent(posixDirName, normalizedDir);\n};\n\n/**\n * Check if two paths that can be either in posix or win32 format resolves to the same file\n *\n * @param {string} pathA a path that may be either win32 or posix\n * @param {string} pathB a path that may be either win32 or posix\n *\n * @returns {boolean} do paths point to the same place\n */\nexport const isPathEquivalent = (pathA: string, pathB: string) => {\n // Check if paths appear to be win32 or posix, and if win32 convert to posix\n const normalizedPathA = path.posix.normalize(unknownPathToPosix(pathA));\n const normalizedPathB = path.posix.normalize(unknownPathToPosix(pathB));\n\n return !path.posix.relative(normalizedPathB, normalizedPathA).length;\n};\n\n/**\n * Convert an unknown format path (win32 or posix) to a posix path\n *\n * @param {string} filePath a path that may be either win32 or posix\n *\n * @returns {string} a posix path\n */\nexport const unknownPathToPosix = (filePath: string) => {\n // if it includes a forward slash, it must be posix already -- we will not support win32 with mixed path separators\n if (filePath.includes(path.posix.sep)) {\n return filePath;\n }\n\n return path.normalize(filePath).split(path.win32.sep).join(path.posix.sep);\n};\n"],"names":["isFilePathInDirname","posixDirName","filePath","normalizedDir","path","posix","dirname","unknownPathToPosix","isPathEquivalent","pathA","pathB","normalizedPathA","normalize","normalizedPathB","relative","length","includes","sep","split","win32","join"],"mappings":";;AAEA;;;;;;;;;;;;;;;;;AAmBC,IACM,MAAMA,mBAAAA,GAAsB,CAACC,YAAAA,EAAsBC,QAAAA,GAAAA;AACxD,IAAA,MAAMC,gBAAgBC,IAAAA,CAAKC,KAAK,CAACC,OAAO,CAACC,kBAAAA,CAAmBL,QAAAA,CAAAA,CAAAA;AAC5D,IAAA,OAAOM,iBAAiBP,YAAAA,EAAcE,aAAAA,CAAAA;AACxC;AAEA;;;;;;;AAOC,IACM,MAAMK,gBAAAA,GAAmB,CAACC,KAAAA,EAAeC,KAAAA,GAAAA;;AAE9C,IAAA,MAAMC,kBAAkBP,IAAAA,CAAKC,KAAK,CAACO,SAAS,CAACL,kBAAAA,CAAmBE,KAAAA,CAAAA,CAAAA;AAChE,IAAA,MAAMI,kBAAkBT,IAAAA,CAAKC,KAAK,CAACO,SAAS,CAACL,kBAAAA,CAAmBG,KAAAA,CAAAA,CAAAA;IAEhE,OAAO,CAACN,KAAKC,KAAK,CAACS,QAAQ,CAACD,eAAAA,EAAiBF,iBAAiBI,MAAM;AACtE;AAEA;;;;;;IAOO,MAAMR,kBAAAA,GAAqB,CAACL,QAAAA,GAAAA;;AAEjC,IAAA,IAAIA,SAASc,QAAQ,CAACZ,KAAKC,KAAK,CAACY,GAAG,CAAA,EAAG;QACrC,OAAOf,QAAAA;AACT,IAAA;AAEA,IAAA,OAAOE,KAAKQ,SAAS,CAACV,QAAAA,CAAAA,CAAUgB,KAAK,CAACd,IAAAA,CAAKe,KAAK,CAACF,GAAG,EAAEG,IAAI,CAAChB,IAAAA,CAAKC,KAAK,CAACY,GAAG,CAAA;AAC3E;;;;"}
1
+ {"version":3,"file":"utils.mjs","sources":["../../../../src/file/providers/source/utils.ts"],"sourcesContent":["import path from 'path';\n\nimport type { IFile } from '../../../types';\n\nexport const validateAssetMetadata = (metadata: unknown, filename?: string): IFile => {\n if (metadata === null || typeof metadata !== 'object' || Array.isArray(metadata)) {\n throw new TypeError('Asset sidecar metadata must be a JSON object');\n }\n\n const file = metadata as Record<string, unknown>;\n const invalidFields: string[] = [];\n\n if (!Number.isInteger(file.id) || (file.id as number) <= 0) {\n invalidFields.push('id');\n }\n if (!Number.isFinite(file.size) || (file.size as number) < 0) {\n invalidFields.push('size');\n }\n for (const field of ['name', 'hash', 'mime', 'url'] as const) {\n if (typeof file[field] !== 'string' || file[field].length === 0) {\n invalidFields.push(field);\n }\n }\n for (const field of ['ext', 'type', 'mainHash'] as const) {\n if (file[field] != null && typeof file[field] !== 'string') {\n invalidFields.push(field);\n }\n }\n\n if (invalidFields.length > 0) {\n throw new TypeError(\n `Asset sidecar metadata has invalid required fields: ${invalidFields.join(', ')}`\n );\n }\n\n const typedFile = file as unknown as IFile;\n const expectedFilename = `${typedFile.hash}${typedFile.ext ?? ''}`;\n const legacyFilename = `${typedFile.hash}${typedFile.ext}`;\n if (filename && filename !== expectedFilename && filename !== legacyFilename) {\n throw new TypeError(`Asset sidecar metadata does not match upload filename \"${filename}\"`);\n }\n\n return typedFile;\n};\n\n/**\n * Note: in versions of the transfer engine <=4.9.0, exports were generated with windows paths\n * on Windows systems, and posix paths on posix systems.\n *\n * We now store all paths as posix, but need to leave a separator conversion for legacy purposes, and to\n * support manually-created tar files coming from Windows systems (ie, if a user creates a\n * backup file with a windows tar tool rather than using the `export` command)\n *\n * Because of this, export/import files may never contain files with a forward slash in the name, even escaped\n *\n * */\n\n/**\n * Check if the directory of a given filePath (which can be either posix or win32) resolves to the same as the given posix-format path posixDirName\n * We must be able to assume the first argument is a path to a directory and the second is a path to a file, otherwise path.dirname will interpret a path without any slashes as the filename\n *\n * @param {string} posixDirName A posix path pointing to a directory\n * @param {string} filePath an unknown filesystem path pointing to a file\n * @returns {boolean} is the file located in the given directory\n */\nexport const isFilePathInDirname = (posixDirName: string, filePath: string) => {\n const normalizedDir = path.posix.dirname(unknownPathToPosix(filePath));\n return isPathEquivalent(posixDirName, normalizedDir);\n};\n\n/**\n * Check if two paths that can be either in posix or win32 format resolves to the same file\n *\n * @param {string} pathA a path that may be either win32 or posix\n * @param {string} pathB a path that may be either win32 or posix\n *\n * @returns {boolean} do paths point to the same place\n */\nexport const isPathEquivalent = (pathA: string, pathB: string) => {\n // Check if paths appear to be win32 or posix, and if win32 convert to posix\n const normalizedPathA = path.posix.normalize(unknownPathToPosix(pathA));\n const normalizedPathB = path.posix.normalize(unknownPathToPosix(pathB));\n\n return !path.posix.relative(normalizedPathB, normalizedPathA).length;\n};\n\n/**\n * Convert an unknown format path (win32 or posix) to a posix path\n *\n * @param {string} filePath a path that may be either win32 or posix\n *\n * @returns {string} a posix path\n */\nexport const unknownPathToPosix = (filePath: string) => {\n // if it includes a forward slash, it must be posix already -- we will not support win32 with mixed path separators\n if (filePath.includes(path.posix.sep)) {\n return filePath;\n }\n\n return path.normalize(filePath).split(path.win32.sep).join(path.posix.sep);\n};\n"],"names":["validateAssetMetadata","metadata","filename","Array","isArray","TypeError","file","invalidFields","Number","isInteger","id","push","isFinite","size","field","length","join","typedFile","expectedFilename","hash","ext","legacyFilename","isFilePathInDirname","posixDirName","filePath","normalizedDir","path","posix","dirname","unknownPathToPosix","isPathEquivalent","pathA","pathB","normalizedPathA","normalize","normalizedPathB","relative","includes","sep","split","win32"],"mappings":"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"}
@@ -101,7 +101,7 @@ const missingAssetWarningMessage = (file, filepath, format)=>{
101
101
  yield {
102
102
  metadata: file,
103
103
  filepath,
104
- filename: file.hash + file.ext,
104
+ filename: `${file.hash}${file.ext ?? ''}`,
105
105
  stream,
106
106
  stats: {
107
107
  size: stats.size
@@ -132,7 +132,7 @@ const missingAssetWarningMessage = (file, filepath, format)=>{
132
132
  yield {
133
133
  metadata,
134
134
  filepath: fileFormatFilepath,
135
- filename: fileFormat.hash + fileFormat.ext,
135
+ filename: `${fileFormat.hash}${fileFormat.ext ?? ''}`,
136
136
  stream: fileFormatStream,
137
137
  stats: {
138
138
  size: fileFormatStats.size
@@ -1 +1 @@
1
- {"version":3,"file":"assets.js","sources":["../../../../src/strapi/providers/local-source/assets.ts"],"sourcesContent":["import { join } from 'path';\nimport { Duplex, PassThrough, Readable } from 'stream';\nimport { stat, createReadStream, ReadStream } from 'fs-extra';\nimport * as webStream from 'stream/web';\nimport type { Core } from '@strapi/types';\n\nimport type { IAsset, IFile } from '../../../types';\n\nfunction getFileStream(\n filepath: string,\n strapi: Core.Strapi,\n isLocal = false\n): PassThrough | ReadStream {\n if (isLocal) {\n // Todo: handle errors\n return createReadStream(filepath);\n }\n\n const readableStream = new PassThrough();\n\n // fetch the image from remote url and stream it\n strapi\n .fetch(filepath)\n .then((res: Response) => {\n if (res.status !== 200) {\n readableStream.emit('error', new Error(`Request failed with status code ${res.status}`));\n return;\n }\n\n if (res.body) {\n // pipe the image data\n Readable.fromWeb(res.body as webStream.ReadableStream<Uint8Array>).pipe(readableStream);\n } else {\n readableStream.emit('error', new Error('Empty data found for file'));\n }\n })\n .catch((error: unknown) => {\n readableStream.emit('error', error);\n });\n\n return readableStream;\n}\n\nexport function getFileStatsForTransfer(\n filepath: string,\n strapi: Core.Strapi,\n isLocal = false\n): Promise<{ size: number }> {\n if (isLocal) {\n return stat(filepath);\n }\n return new Promise((resolve, reject) => {\n strapi\n .fetch(filepath)\n .then((res: Response) => {\n if (res.status !== 200) {\n reject(new Error(`Request failed with status code ${res.status}`));\n return;\n }\n\n const contentLength = res.headers.get('content-length');\n const stats = {\n size: contentLength ? parseInt(contentLength, 10) : 0,\n };\n\n resolve(stats);\n })\n .catch((error: unknown) => {\n reject(error);\n });\n });\n}\n\nexport async function signUploadFileForTransfer(strapi: Core.Strapi, file: IFile) {\n const { provider } = strapi.plugins.upload;\n const { provider: providerName } = strapi.config.get('plugin.upload') as { provider: string };\n const isPrivate = await provider.isPrivate();\n if (file?.provider === providerName && isPrivate) {\n const signUrl = async (f: IFile) => {\n const signedUrl = await provider.getSignedUrl(f);\n f.url = signedUrl.url;\n };\n\n await signUrl(file);\n if (file.formats) {\n for (const format of Object.keys(file.formats)) {\n await signUrl(file.formats[format]);\n }\n }\n }\n}\n\nconst missingAssetWarningMessage = (file: IFile, filepath: string, format?: string): string => {\n const formatPart = format ? ` (format: ${format})` : '';\n return `[Data transfer] Media item ${file.id} (hash: ${file.hash}) exists in database but no corresponding file was found to transfer${formatPart}. Path: ${filepath}`;\n};\n\n/**\n * Generate and consume assets streams in order to stream each file individually\n */\nexport const createAssetsStream = (\n strapi: Core.Strapi,\n options: { onWarning?: (message: string) => void } = {}\n): Duplex => {\n const warnMissingAsset = (message: string) => {\n strapi.log.warn(message);\n options.onWarning?.(message);\n };\n\n const generator: () => AsyncGenerator<IAsset, void> = async function* generateAssets() {\n const stream: Readable = strapi.db\n .queryBuilder('plugin::upload.file')\n // Create a query builder instance (default type is 'select')\n // Fetch all columns\n .select('*')\n // Get a readable stream\n .stream();\n\n for await (const file of stream) {\n const isLocalProvider = file.provider === 'local';\n if (!isLocalProvider) {\n await signUploadFileForTransfer(strapi, file);\n }\n const filepath = isLocalProvider ? join(strapi.dirs.static.public, file.url) : file.url;\n let stats: { size: number };\n try {\n stats = await getFileStatsForTransfer(filepath, strapi, isLocalProvider);\n } catch (err: unknown) {\n const code =\n err && typeof err === 'object' && 'code' in err\n ? (err as NodeJS.ErrnoException).code\n : undefined;\n if (code === 'ENOENT') {\n warnMissingAsset(missingAssetWarningMessage(file, filepath));\n continue;\n }\n throw err;\n }\n const stream = getFileStream(filepath, strapi, isLocalProvider);\n\n yield {\n metadata: file,\n filepath,\n filename: file.hash + file.ext,\n stream,\n stats: { size: stats.size },\n };\n\n if (file.formats) {\n for (const format of Object.keys(file.formats)) {\n const fileFormat = file.formats[format];\n const fileFormatFilepath = isLocalProvider\n ? join(strapi.dirs.static.public, fileFormat.url)\n : fileFormat.url;\n let fileFormatStats: { size: number };\n try {\n fileFormatStats = await getFileStatsForTransfer(\n fileFormatFilepath,\n strapi,\n isLocalProvider\n );\n } catch (err: unknown) {\n const code =\n err && typeof err === 'object' && 'code' in err\n ? (err as NodeJS.ErrnoException).code\n : undefined;\n if (code === 'ENOENT') {\n warnMissingAsset(missingAssetWarningMessage(file, fileFormatFilepath, format));\n continue;\n }\n throw err;\n }\n const fileFormatStream = getFileStream(fileFormatFilepath, strapi, isLocalProvider);\n const metadata = { ...fileFormat, type: format, id: file.id, mainHash: file.hash };\n yield {\n metadata,\n filepath: fileFormatFilepath,\n filename: fileFormat.hash + fileFormat.ext,\n stream: fileFormatStream,\n stats: { size: fileFormatStats.size },\n };\n }\n }\n }\n };\n\n return Duplex.from(generator());\n};\n"],"names":["getFileStream","filepath","strapi","isLocal","createReadStream","readableStream","PassThrough","fetch","then","res","status","emit","Error","body","Readable","fromWeb","pipe","catch","error","getFileStatsForTransfer","stat","Promise","resolve","reject","contentLength","headers","get","stats","size","parseInt","signUploadFileForTransfer","file","provider","plugins","upload","providerName","config","isPrivate","signUrl","f","signedUrl","getSignedUrl","url","formats","format","Object","keys","missingAssetWarningMessage","formatPart","id","hash","createAssetsStream","options","warnMissingAsset","message","log","warn","onWarning","generator","generateAssets","stream","db","queryBuilder","select","isLocalProvider","join","dirs","static","public","err","code","undefined","metadata","filename","ext","fileFormat","fileFormatFilepath","fileFormatStats","fileFormatStream","type","mainHash","Duplex","from"],"mappings":"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"}
1
+ {"version":3,"file":"assets.js","sources":["../../../../src/strapi/providers/local-source/assets.ts"],"sourcesContent":["import { join } from 'path';\nimport { Duplex, PassThrough, Readable } from 'stream';\nimport { stat, createReadStream, ReadStream } from 'fs-extra';\nimport * as webStream from 'stream/web';\nimport type { Core } from '@strapi/types';\n\nimport type { IAsset, IFile } from '../../../types';\n\nfunction getFileStream(\n filepath: string,\n strapi: Core.Strapi,\n isLocal = false\n): PassThrough | ReadStream {\n if (isLocal) {\n // Todo: handle errors\n return createReadStream(filepath);\n }\n\n const readableStream = new PassThrough();\n\n // fetch the image from remote url and stream it\n strapi\n .fetch(filepath)\n .then((res: Response) => {\n if (res.status !== 200) {\n readableStream.emit('error', new Error(`Request failed with status code ${res.status}`));\n return;\n }\n\n if (res.body) {\n // pipe the image data\n Readable.fromWeb(res.body as webStream.ReadableStream<Uint8Array>).pipe(readableStream);\n } else {\n readableStream.emit('error', new Error('Empty data found for file'));\n }\n })\n .catch((error: unknown) => {\n readableStream.emit('error', error);\n });\n\n return readableStream;\n}\n\nexport function getFileStatsForTransfer(\n filepath: string,\n strapi: Core.Strapi,\n isLocal = false\n): Promise<{ size: number }> {\n if (isLocal) {\n return stat(filepath);\n }\n return new Promise((resolve, reject) => {\n strapi\n .fetch(filepath)\n .then((res: Response) => {\n if (res.status !== 200) {\n reject(new Error(`Request failed with status code ${res.status}`));\n return;\n }\n\n const contentLength = res.headers.get('content-length');\n const stats = {\n size: contentLength ? parseInt(contentLength, 10) : 0,\n };\n\n resolve(stats);\n })\n .catch((error: unknown) => {\n reject(error);\n });\n });\n}\n\nexport async function signUploadFileForTransfer(strapi: Core.Strapi, file: IFile) {\n const { provider } = strapi.plugins.upload;\n const { provider: providerName } = strapi.config.get('plugin.upload') as { provider: string };\n const isPrivate = await provider.isPrivate();\n if (file?.provider === providerName && isPrivate) {\n const signUrl = async (f: IFile) => {\n const signedUrl = await provider.getSignedUrl(f);\n f.url = signedUrl.url;\n };\n\n await signUrl(file);\n if (file.formats) {\n for (const format of Object.keys(file.formats)) {\n await signUrl(file.formats[format]);\n }\n }\n }\n}\n\nconst missingAssetWarningMessage = (file: IFile, filepath: string, format?: string): string => {\n const formatPart = format ? ` (format: ${format})` : '';\n return `[Data transfer] Media item ${file.id} (hash: ${file.hash}) exists in database but no corresponding file was found to transfer${formatPart}. Path: ${filepath}`;\n};\n\n/**\n * Generate and consume assets streams in order to stream each file individually\n */\nexport const createAssetsStream = (\n strapi: Core.Strapi,\n options: { onWarning?: (message: string) => void } = {}\n): Duplex => {\n const warnMissingAsset = (message: string) => {\n strapi.log.warn(message);\n options.onWarning?.(message);\n };\n\n const generator: () => AsyncGenerator<IAsset, void> = async function* generateAssets() {\n const stream: Readable = strapi.db\n .queryBuilder('plugin::upload.file')\n // Create a query builder instance (default type is 'select')\n // Fetch all columns\n .select('*')\n // Get a readable stream\n .stream();\n\n for await (const file of stream) {\n const isLocalProvider = file.provider === 'local';\n if (!isLocalProvider) {\n await signUploadFileForTransfer(strapi, file);\n }\n const filepath = isLocalProvider ? join(strapi.dirs.static.public, file.url) : file.url;\n let stats: { size: number };\n try {\n stats = await getFileStatsForTransfer(filepath, strapi, isLocalProvider);\n } catch (err: unknown) {\n const code =\n err && typeof err === 'object' && 'code' in err\n ? (err as NodeJS.ErrnoException).code\n : undefined;\n if (code === 'ENOENT') {\n warnMissingAsset(missingAssetWarningMessage(file, filepath));\n continue;\n }\n throw err;\n }\n const stream = getFileStream(filepath, strapi, isLocalProvider);\n\n yield {\n metadata: file,\n filepath,\n filename: `${file.hash}${file.ext ?? ''}`,\n stream,\n stats: { size: stats.size },\n };\n\n if (file.formats) {\n for (const format of Object.keys(file.formats)) {\n const fileFormat = file.formats[format];\n const fileFormatFilepath = isLocalProvider\n ? join(strapi.dirs.static.public, fileFormat.url)\n : fileFormat.url;\n let fileFormatStats: { size: number };\n try {\n fileFormatStats = await getFileStatsForTransfer(\n fileFormatFilepath,\n strapi,\n isLocalProvider\n );\n } catch (err: unknown) {\n const code =\n err && typeof err === 'object' && 'code' in err\n ? (err as NodeJS.ErrnoException).code\n : undefined;\n if (code === 'ENOENT') {\n warnMissingAsset(missingAssetWarningMessage(file, fileFormatFilepath, format));\n continue;\n }\n throw err;\n }\n const fileFormatStream = getFileStream(fileFormatFilepath, strapi, isLocalProvider);\n const metadata = { ...fileFormat, type: format, id: file.id, mainHash: file.hash };\n yield {\n metadata,\n filepath: fileFormatFilepath,\n filename: `${fileFormat.hash}${fileFormat.ext ?? ''}`,\n stream: fileFormatStream,\n stats: { size: fileFormatStats.size },\n };\n }\n }\n }\n };\n\n return Duplex.from(generator());\n};\n"],"names":["getFileStream","filepath","strapi","isLocal","createReadStream","readableStream","PassThrough","fetch","then","res","status","emit","Error","body","Readable","fromWeb","pipe","catch","error","getFileStatsForTransfer","stat","Promise","resolve","reject","contentLength","headers","get","stats","size","parseInt","signUploadFileForTransfer","file","provider","plugins","upload","providerName","config","isPrivate","signUrl","f","signedUrl","getSignedUrl","url","formats","format","Object","keys","missingAssetWarningMessage","formatPart","id","hash","createAssetsStream","options","warnMissingAsset","message","log","warn","onWarning","generator","generateAssets","stream","db","queryBuilder","select","isLocalProvider","join","dirs","static","public","err","code","undefined","metadata","filename","ext","fileFormat","fileFormatFilepath","fileFormatStats","fileFormatStream","type","mainHash","Duplex","from"],"mappings":"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"}
@@ -99,7 +99,7 @@ const missingAssetWarningMessage = (file, filepath, format)=>{
99
99
  yield {
100
100
  metadata: file,
101
101
  filepath,
102
- filename: file.hash + file.ext,
102
+ filename: `${file.hash}${file.ext ?? ''}`,
103
103
  stream,
104
104
  stats: {
105
105
  size: stats.size
@@ -130,7 +130,7 @@ const missingAssetWarningMessage = (file, filepath, format)=>{
130
130
  yield {
131
131
  metadata,
132
132
  filepath: fileFormatFilepath,
133
- filename: fileFormat.hash + fileFormat.ext,
133
+ filename: `${fileFormat.hash}${fileFormat.ext ?? ''}`,
134
134
  stream: fileFormatStream,
135
135
  stats: {
136
136
  size: fileFormatStats.size
@@ -1 +1 @@
1
- {"version":3,"file":"assets.mjs","sources":["../../../../src/strapi/providers/local-source/assets.ts"],"sourcesContent":["import { join } from 'path';\nimport { Duplex, PassThrough, Readable } from 'stream';\nimport { stat, createReadStream, ReadStream } from 'fs-extra';\nimport * as webStream from 'stream/web';\nimport type { Core } from '@strapi/types';\n\nimport type { IAsset, IFile } from '../../../types';\n\nfunction getFileStream(\n filepath: string,\n strapi: Core.Strapi,\n isLocal = false\n): PassThrough | ReadStream {\n if (isLocal) {\n // Todo: handle errors\n return createReadStream(filepath);\n }\n\n const readableStream = new PassThrough();\n\n // fetch the image from remote url and stream it\n strapi\n .fetch(filepath)\n .then((res: Response) => {\n if (res.status !== 200) {\n readableStream.emit('error', new Error(`Request failed with status code ${res.status}`));\n return;\n }\n\n if (res.body) {\n // pipe the image data\n Readable.fromWeb(res.body as webStream.ReadableStream<Uint8Array>).pipe(readableStream);\n } else {\n readableStream.emit('error', new Error('Empty data found for file'));\n }\n })\n .catch((error: unknown) => {\n readableStream.emit('error', error);\n });\n\n return readableStream;\n}\n\nexport function getFileStatsForTransfer(\n filepath: string,\n strapi: Core.Strapi,\n isLocal = false\n): Promise<{ size: number }> {\n if (isLocal) {\n return stat(filepath);\n }\n return new Promise((resolve, reject) => {\n strapi\n .fetch(filepath)\n .then((res: Response) => {\n if (res.status !== 200) {\n reject(new Error(`Request failed with status code ${res.status}`));\n return;\n }\n\n const contentLength = res.headers.get('content-length');\n const stats = {\n size: contentLength ? parseInt(contentLength, 10) : 0,\n };\n\n resolve(stats);\n })\n .catch((error: unknown) => {\n reject(error);\n });\n });\n}\n\nexport async function signUploadFileForTransfer(strapi: Core.Strapi, file: IFile) {\n const { provider } = strapi.plugins.upload;\n const { provider: providerName } = strapi.config.get('plugin.upload') as { provider: string };\n const isPrivate = await provider.isPrivate();\n if (file?.provider === providerName && isPrivate) {\n const signUrl = async (f: IFile) => {\n const signedUrl = await provider.getSignedUrl(f);\n f.url = signedUrl.url;\n };\n\n await signUrl(file);\n if (file.formats) {\n for (const format of Object.keys(file.formats)) {\n await signUrl(file.formats[format]);\n }\n }\n }\n}\n\nconst missingAssetWarningMessage = (file: IFile, filepath: string, format?: string): string => {\n const formatPart = format ? ` (format: ${format})` : '';\n return `[Data transfer] Media item ${file.id} (hash: ${file.hash}) exists in database but no corresponding file was found to transfer${formatPart}. Path: ${filepath}`;\n};\n\n/**\n * Generate and consume assets streams in order to stream each file individually\n */\nexport const createAssetsStream = (\n strapi: Core.Strapi,\n options: { onWarning?: (message: string) => void } = {}\n): Duplex => {\n const warnMissingAsset = (message: string) => {\n strapi.log.warn(message);\n options.onWarning?.(message);\n };\n\n const generator: () => AsyncGenerator<IAsset, void> = async function* generateAssets() {\n const stream: Readable = strapi.db\n .queryBuilder('plugin::upload.file')\n // Create a query builder instance (default type is 'select')\n // Fetch all columns\n .select('*')\n // Get a readable stream\n .stream();\n\n for await (const file of stream) {\n const isLocalProvider = file.provider === 'local';\n if (!isLocalProvider) {\n await signUploadFileForTransfer(strapi, file);\n }\n const filepath = isLocalProvider ? join(strapi.dirs.static.public, file.url) : file.url;\n let stats: { size: number };\n try {\n stats = await getFileStatsForTransfer(filepath, strapi, isLocalProvider);\n } catch (err: unknown) {\n const code =\n err && typeof err === 'object' && 'code' in err\n ? (err as NodeJS.ErrnoException).code\n : undefined;\n if (code === 'ENOENT') {\n warnMissingAsset(missingAssetWarningMessage(file, filepath));\n continue;\n }\n throw err;\n }\n const stream = getFileStream(filepath, strapi, isLocalProvider);\n\n yield {\n metadata: file,\n filepath,\n filename: file.hash + file.ext,\n stream,\n stats: { size: stats.size },\n };\n\n if (file.formats) {\n for (const format of Object.keys(file.formats)) {\n const fileFormat = file.formats[format];\n const fileFormatFilepath = isLocalProvider\n ? join(strapi.dirs.static.public, fileFormat.url)\n : fileFormat.url;\n let fileFormatStats: { size: number };\n try {\n fileFormatStats = await getFileStatsForTransfer(\n fileFormatFilepath,\n strapi,\n isLocalProvider\n );\n } catch (err: unknown) {\n const code =\n err && typeof err === 'object' && 'code' in err\n ? (err as NodeJS.ErrnoException).code\n : undefined;\n if (code === 'ENOENT') {\n warnMissingAsset(missingAssetWarningMessage(file, fileFormatFilepath, format));\n continue;\n }\n throw err;\n }\n const fileFormatStream = getFileStream(fileFormatFilepath, strapi, isLocalProvider);\n const metadata = { ...fileFormat, type: format, id: file.id, mainHash: file.hash };\n yield {\n metadata,\n filepath: fileFormatFilepath,\n filename: fileFormat.hash + fileFormat.ext,\n stream: fileFormatStream,\n stats: { size: fileFormatStats.size },\n };\n }\n }\n }\n };\n\n return Duplex.from(generator());\n};\n"],"names":["getFileStream","filepath","strapi","isLocal","createReadStream","readableStream","PassThrough","fetch","then","res","status","emit","Error","body","Readable","fromWeb","pipe","catch","error","getFileStatsForTransfer","stat","Promise","resolve","reject","contentLength","headers","get","stats","size","parseInt","signUploadFileForTransfer","file","provider","plugins","upload","providerName","config","isPrivate","signUrl","f","signedUrl","getSignedUrl","url","formats","format","Object","keys","missingAssetWarningMessage","formatPart","id","hash","createAssetsStream","options","warnMissingAsset","message","log","warn","onWarning","generator","generateAssets","stream","db","queryBuilder","select","isLocalProvider","join","dirs","static","public","err","code","undefined","metadata","filename","ext","fileFormat","fileFormatFilepath","fileFormatStats","fileFormatStream","type","mainHash","Duplex","from"],"mappings":"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"}
1
+ {"version":3,"file":"assets.mjs","sources":["../../../../src/strapi/providers/local-source/assets.ts"],"sourcesContent":["import { join } from 'path';\nimport { Duplex, PassThrough, Readable } from 'stream';\nimport { stat, createReadStream, ReadStream } from 'fs-extra';\nimport * as webStream from 'stream/web';\nimport type { Core } from '@strapi/types';\n\nimport type { IAsset, IFile } from '../../../types';\n\nfunction getFileStream(\n filepath: string,\n strapi: Core.Strapi,\n isLocal = false\n): PassThrough | ReadStream {\n if (isLocal) {\n // Todo: handle errors\n return createReadStream(filepath);\n }\n\n const readableStream = new PassThrough();\n\n // fetch the image from remote url and stream it\n strapi\n .fetch(filepath)\n .then((res: Response) => {\n if (res.status !== 200) {\n readableStream.emit('error', new Error(`Request failed with status code ${res.status}`));\n return;\n }\n\n if (res.body) {\n // pipe the image data\n Readable.fromWeb(res.body as webStream.ReadableStream<Uint8Array>).pipe(readableStream);\n } else {\n readableStream.emit('error', new Error('Empty data found for file'));\n }\n })\n .catch((error: unknown) => {\n readableStream.emit('error', error);\n });\n\n return readableStream;\n}\n\nexport function getFileStatsForTransfer(\n filepath: string,\n strapi: Core.Strapi,\n isLocal = false\n): Promise<{ size: number }> {\n if (isLocal) {\n return stat(filepath);\n }\n return new Promise((resolve, reject) => {\n strapi\n .fetch(filepath)\n .then((res: Response) => {\n if (res.status !== 200) {\n reject(new Error(`Request failed with status code ${res.status}`));\n return;\n }\n\n const contentLength = res.headers.get('content-length');\n const stats = {\n size: contentLength ? parseInt(contentLength, 10) : 0,\n };\n\n resolve(stats);\n })\n .catch((error: unknown) => {\n reject(error);\n });\n });\n}\n\nexport async function signUploadFileForTransfer(strapi: Core.Strapi, file: IFile) {\n const { provider } = strapi.plugins.upload;\n const { provider: providerName } = strapi.config.get('plugin.upload') as { provider: string };\n const isPrivate = await provider.isPrivate();\n if (file?.provider === providerName && isPrivate) {\n const signUrl = async (f: IFile) => {\n const signedUrl = await provider.getSignedUrl(f);\n f.url = signedUrl.url;\n };\n\n await signUrl(file);\n if (file.formats) {\n for (const format of Object.keys(file.formats)) {\n await signUrl(file.formats[format]);\n }\n }\n }\n}\n\nconst missingAssetWarningMessage = (file: IFile, filepath: string, format?: string): string => {\n const formatPart = format ? ` (format: ${format})` : '';\n return `[Data transfer] Media item ${file.id} (hash: ${file.hash}) exists in database but no corresponding file was found to transfer${formatPart}. Path: ${filepath}`;\n};\n\n/**\n * Generate and consume assets streams in order to stream each file individually\n */\nexport const createAssetsStream = (\n strapi: Core.Strapi,\n options: { onWarning?: (message: string) => void } = {}\n): Duplex => {\n const warnMissingAsset = (message: string) => {\n strapi.log.warn(message);\n options.onWarning?.(message);\n };\n\n const generator: () => AsyncGenerator<IAsset, void> = async function* generateAssets() {\n const stream: Readable = strapi.db\n .queryBuilder('plugin::upload.file')\n // Create a query builder instance (default type is 'select')\n // Fetch all columns\n .select('*')\n // Get a readable stream\n .stream();\n\n for await (const file of stream) {\n const isLocalProvider = file.provider === 'local';\n if (!isLocalProvider) {\n await signUploadFileForTransfer(strapi, file);\n }\n const filepath = isLocalProvider ? join(strapi.dirs.static.public, file.url) : file.url;\n let stats: { size: number };\n try {\n stats = await getFileStatsForTransfer(filepath, strapi, isLocalProvider);\n } catch (err: unknown) {\n const code =\n err && typeof err === 'object' && 'code' in err\n ? (err as NodeJS.ErrnoException).code\n : undefined;\n if (code === 'ENOENT') {\n warnMissingAsset(missingAssetWarningMessage(file, filepath));\n continue;\n }\n throw err;\n }\n const stream = getFileStream(filepath, strapi, isLocalProvider);\n\n yield {\n metadata: file,\n filepath,\n filename: `${file.hash}${file.ext ?? ''}`,\n stream,\n stats: { size: stats.size },\n };\n\n if (file.formats) {\n for (const format of Object.keys(file.formats)) {\n const fileFormat = file.formats[format];\n const fileFormatFilepath = isLocalProvider\n ? join(strapi.dirs.static.public, fileFormat.url)\n : fileFormat.url;\n let fileFormatStats: { size: number };\n try {\n fileFormatStats = await getFileStatsForTransfer(\n fileFormatFilepath,\n strapi,\n isLocalProvider\n );\n } catch (err: unknown) {\n const code =\n err && typeof err === 'object' && 'code' in err\n ? (err as NodeJS.ErrnoException).code\n : undefined;\n if (code === 'ENOENT') {\n warnMissingAsset(missingAssetWarningMessage(file, fileFormatFilepath, format));\n continue;\n }\n throw err;\n }\n const fileFormatStream = getFileStream(fileFormatFilepath, strapi, isLocalProvider);\n const metadata = { ...fileFormat, type: format, id: file.id, mainHash: file.hash };\n yield {\n metadata,\n filepath: fileFormatFilepath,\n filename: `${fileFormat.hash}${fileFormat.ext ?? ''}`,\n stream: fileFormatStream,\n stats: { size: fileFormatStats.size },\n };\n }\n }\n }\n };\n\n return Duplex.from(generator());\n};\n"],"names":["getFileStream","filepath","strapi","isLocal","createReadStream","readableStream","PassThrough","fetch","then","res","status","emit","Error","body","Readable","fromWeb","pipe","catch","error","getFileStatsForTransfer","stat","Promise","resolve","reject","contentLength","headers","get","stats","size","parseInt","signUploadFileForTransfer","file","provider","plugins","upload","providerName","config","isPrivate","signUrl","f","signedUrl","getSignedUrl","url","formats","format","Object","keys","missingAssetWarningMessage","formatPart","id","hash","createAssetsStream","options","warnMissingAsset","message","log","warn","onWarning","generator","generateAssets","stream","db","queryBuilder","select","isLocalProvider","join","dirs","static","public","err","code","undefined","metadata","filename","ext","fileFormat","fileFormatFilepath","fileFormatStats","fileFormatStream","type","mainHash","Duplex","from"],"mappings":"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"}
@@ -13,6 +13,11 @@ export interface IProvider {
13
13
  * It is used for initialization operations such as making a database connection, opening a file, checking authorization, etc
14
14
  */
15
15
  bootstrap?(diagnostics?: IDiagnosticReporter): MaybePromise<void>;
16
+ /**
17
+ * Called after a successful transfer and on failure after rollback has been attempted.
18
+ * Implementations must be safe to close after partial bootstrap and, for destinations, after
19
+ * rollback. A destination that finalizes output in close() should make it a no-op after rollback.
20
+ */
16
21
  close?(): MaybePromise<void>;
17
22
  getMetadata(): MaybePromise<IMetadata | null>;
18
23
  getSchemas?(): MaybePromise<Record<string, Struct.Schema> | null>;
@@ -20,6 +25,11 @@ export interface IProvider {
20
25
  }
21
26
  export interface ISourceProvider extends IProvider {
22
27
  results?: ISourceProviderTransferResults;
28
+ /**
29
+ * Validate a stage before the destination provider prepares for transfer.
30
+ * Use this for checks that must happen before a restore can mutate destination data.
31
+ */
32
+ validateStage?(stage: TransferStage): MaybePromise<void>;
23
33
  /**
24
34
  * Optional totals for a stage. Called by the engine after the stage read stream is created and before `stage::start`.
25
35
  * Used for CLI progress (e.g. bytes/count remaining, ETA). Omit or return null when unknown (older remotes, file providers).
@@ -1 +1 @@
1
- {"version":3,"file":"providers.d.ts","sourceRoot":"","sources":["../../src/types/providers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AACjD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,KAAK,EACV,mCAAmC,EACnC,wBAAwB,EACxB,8BAA8B,EAC9B,YAAY,EACZ,mBAAmB,EACnB,aAAa,EACd,MAAM,SAAS,CAAC;AACjB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAE/D,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,aAAa,CAAC;AAEpD,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,YAAY,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,wBAAwB,CAAC;IAEnC;;;OAGG;IACH,SAAS,CAAC,CAAC,WAAW,CAAC,EAAE,mBAAmB,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IAClE,KAAK,CAAC,IAAI,YAAY,CAAC,IAAI,CAAC,CAAC;IAE7B,WAAW,IAAI,YAAY,CAAC,SAAS,GAAG,IAAI,CAAC,CAAC;IAC9C,UAAU,CAAC,IAAI,YAAY,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC;IAElE,cAAc,CAAC,IAAI,YAAY,CAAC,IAAI,CAAC,CAAC;CACvC;AAED,MAAM,WAAW,eAAgB,SAAQ,SAAS;IAChD,OAAO,CAAC,EAAE,8BAA8B,CAAC;IAEzC;;;OAGG;IACH,cAAc,CAAC,CAAC,KAAK,EAAE,aAAa,GAAG,YAAY,CAAC,mBAAmB,GAAG,IAAI,GAAG,SAAS,CAAC,CAAC;IAE5F,wBAAwB,CAAC,IAAI,YAAY,CAAC,QAAQ,CAAC,CAAC;IACpD,qBAAqB,CAAC,IAAI,YAAY,CAAC,QAAQ,CAAC,CAAC;IACjD,sBAAsB,CAAC,IAAI,YAAY,CAAC,QAAQ,CAAC,CAAC;IAClD,6BAA6B,CAAC,IAAI,YAAY,CAAC,QAAQ,CAAC,CAAC;IACzD,uBAAuB,CAAC,IAAI,YAAY,CAAC,QAAQ,CAAC,CAAC;CACpD;AAED,MAAM,WAAW,oBAAqB,SAAQ,SAAS;IACrD,OAAO,CAAC,EAAE,mCAAmC,CAAC;IAE9C;;;OAGG;IACH,QAAQ,CAAC,CAAC,CAAC,SAAS,KAAK,GAAG,KAAK,EAAE,CAAC,EAAE,CAAC,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IAE7D,WAAW,CAAC,CAAC,MAAM,EAAE,YAAY,EAAE,QAAQ,EAAE,SAAS,GAAG,oBAAoB,CAAC;IAC9E,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAEtC,yBAAyB,CAAC,IAAI,YAAY,CAAC,QAAQ,CAAC,CAAC;IACrD,sBAAsB,CAAC,IAAI,YAAY,CAAC,QAAQ,CAAC,CAAC;IAClD,uBAAuB,CAAC,IAAI,YAAY,CAAC,QAAQ,CAAC,CAAC;IACnD,8BAA8B,CAAC,IAAI,YAAY,CAAC,QAAQ,CAAC,CAAC;IAC1D,wBAAwB,CAAC,IAAI,YAAY,CAAC,QAAQ,CAAC,CAAC;CACrD"}
1
+ {"version":3,"file":"providers.d.ts","sourceRoot":"","sources":["../../src/types/providers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AACjD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,KAAK,EACV,mCAAmC,EACnC,wBAAwB,EACxB,8BAA8B,EAC9B,YAAY,EACZ,mBAAmB,EACnB,aAAa,EACd,MAAM,SAAS,CAAC;AACjB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAE/D,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,aAAa,CAAC;AAEpD,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,YAAY,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,wBAAwB,CAAC;IAEnC;;;OAGG;IACH,SAAS,CAAC,CAAC,WAAW,CAAC,EAAE,mBAAmB,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IAElE;;;;OAIG;IACH,KAAK,CAAC,IAAI,YAAY,CAAC,IAAI,CAAC,CAAC;IAE7B,WAAW,IAAI,YAAY,CAAC,SAAS,GAAG,IAAI,CAAC,CAAC;IAC9C,UAAU,CAAC,IAAI,YAAY,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC;IAElE,cAAc,CAAC,IAAI,YAAY,CAAC,IAAI,CAAC,CAAC;CACvC;AAED,MAAM,WAAW,eAAgB,SAAQ,SAAS;IAChD,OAAO,CAAC,EAAE,8BAA8B,CAAC;IAEzC;;;OAGG;IACH,aAAa,CAAC,CAAC,KAAK,EAAE,aAAa,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IAEzD;;;OAGG;IACH,cAAc,CAAC,CAAC,KAAK,EAAE,aAAa,GAAG,YAAY,CAAC,mBAAmB,GAAG,IAAI,GAAG,SAAS,CAAC,CAAC;IAE5F,wBAAwB,CAAC,IAAI,YAAY,CAAC,QAAQ,CAAC,CAAC;IACpD,qBAAqB,CAAC,IAAI,YAAY,CAAC,QAAQ,CAAC,CAAC;IACjD,sBAAsB,CAAC,IAAI,YAAY,CAAC,QAAQ,CAAC,CAAC;IAClD,6BAA6B,CAAC,IAAI,YAAY,CAAC,QAAQ,CAAC,CAAC;IACzD,uBAAuB,CAAC,IAAI,YAAY,CAAC,QAAQ,CAAC,CAAC;CACpD;AAED,MAAM,WAAW,oBAAqB,SAAQ,SAAS;IACrD,OAAO,CAAC,EAAE,mCAAmC,CAAC;IAE9C;;;OAGG;IACH,QAAQ,CAAC,CAAC,CAAC,SAAS,KAAK,GAAG,KAAK,EAAE,CAAC,EAAE,CAAC,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IAE7D,WAAW,CAAC,CAAC,MAAM,EAAE,YAAY,EAAE,QAAQ,EAAE,SAAS,GAAG,oBAAoB,CAAC;IAC9E,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAEtC,yBAAyB,CAAC,IAAI,YAAY,CAAC,QAAQ,CAAC,CAAC;IACrD,sBAAsB,CAAC,IAAI,YAAY,CAAC,QAAQ,CAAC,CAAC;IAClD,uBAAuB,CAAC,IAAI,YAAY,CAAC,QAAQ,CAAC,CAAC;IACnD,8BAA8B,CAAC,IAAI,YAAY,CAAC,QAAQ,CAAC,CAAC;IAC1D,wBAAwB,CAAC,IAAI,YAAY,CAAC,QAAQ,CAAC,CAAC;CACrD"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@strapi/data-transfer",
3
- "version": "5.53.0",
3
+ "version": "5.55.0",
4
4
  "description": "Data transfer capabilities for Strapi",
5
5
  "keywords": [
6
6
  "strapi",
@@ -54,9 +54,9 @@
54
54
  "watch": "run -T rollup -c -w"
55
55
  },
56
56
  "dependencies": {
57
- "@strapi/logger": "5.53.0",
58
- "@strapi/types": "5.53.0",
59
- "@strapi/utils": "5.53.0",
57
+ "@strapi/logger": "5.55.0",
58
+ "@strapi/types": "5.55.0",
59
+ "@strapi/utils": "5.55.0",
60
60
  "chalk": "4.1.2",
61
61
  "cli-table3": "0.6.5",
62
62
  "commander": "8.3.0",
@@ -74,7 +74,7 @@
74
74
  "ws": "8.21.2"
75
75
  },
76
76
  "devDependencies": {
77
- "@strapi/database": "5.53.0",
77
+ "@strapi/database": "5.55.0",
78
78
  "@types/fs-extra": "11.0.4",
79
79
  "@types/jest": "29.5.2",
80
80
  "@types/koa": "2.15.2",
@@ -92,7 +92,7 @@
92
92
  "rimraf": "6.1.3",
93
93
  "typescript": "5.9.3",
94
94
  "vitest": "catalog:",
95
- "vitest-config": "5.53.0"
95
+ "vitest-config": "5.55.0"
96
96
  },
97
97
  "engines": {
98
98
  "node": ">=20.0.0 <=26.x.x",