@strapi/data-transfer 5.42.1 → 5.44.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 (126) hide show
  1. package/dist/directory/providers/source/index.d.ts.map +1 -1
  2. package/dist/directory/providers/source/index.js +3 -2
  3. package/dist/directory/providers/source/index.js.map +1 -1
  4. package/dist/directory/providers/source/index.mjs +3 -2
  5. package/dist/directory/providers/source/index.mjs.map +1 -1
  6. package/dist/engine/index.d.ts.map +1 -1
  7. package/dist/engine/index.js +130 -5
  8. package/dist/engine/index.js.map +1 -1
  9. package/dist/engine/index.mjs +130 -5
  10. package/dist/engine/index.mjs.map +1 -1
  11. package/dist/engine/validation/schemas/index.js +2 -0
  12. package/dist/engine/validation/schemas/index.js.map +1 -1
  13. package/dist/engine/validation/schemas/index.mjs +2 -0
  14. package/dist/engine/validation/schemas/index.mjs.map +1 -1
  15. package/dist/file/providers/source/index.d.ts.map +1 -1
  16. package/dist/file/providers/source/index.js +84 -45
  17. package/dist/file/providers/source/index.js.map +1 -1
  18. package/dist/file/providers/source/index.mjs +85 -46
  19. package/dist/file/providers/source/index.mjs.map +1 -1
  20. package/dist/strapi/providers/index.js +2 -0
  21. package/dist/strapi/providers/index.js.map +1 -1
  22. package/dist/strapi/providers/index.mjs +1 -0
  23. package/dist/strapi/providers/index.mjs.map +1 -1
  24. package/dist/strapi/providers/local-destination/assets-destination-writable.d.ts +22 -0
  25. package/dist/strapi/providers/local-destination/assets-destination-writable.d.ts.map +1 -0
  26. package/dist/strapi/providers/local-destination/assets-destination-writable.js +107 -0
  27. package/dist/strapi/providers/local-destination/assets-destination-writable.js.map +1 -0
  28. package/dist/strapi/providers/local-destination/assets-destination-writable.mjs +105 -0
  29. package/dist/strapi/providers/local-destination/assets-destination-writable.mjs.map +1 -0
  30. package/dist/strapi/providers/local-destination/index.d.ts +2 -0
  31. package/dist/strapi/providers/local-destination/index.d.ts.map +1 -1
  32. package/dist/strapi/providers/local-destination/index.js +18 -79
  33. package/dist/strapi/providers/local-destination/index.js.map +1 -1
  34. package/dist/strapi/providers/local-destination/index.mjs +18 -79
  35. package/dist/strapi/providers/local-destination/index.mjs.map +1 -1
  36. package/dist/strapi/providers/local-destination/strategies/restore/entities.js +2 -0
  37. package/dist/strapi/providers/local-destination/strategies/restore/entities.js.map +1 -1
  38. package/dist/strapi/providers/local-destination/strategies/restore/entities.mjs +2 -0
  39. package/dist/strapi/providers/local-destination/strategies/restore/entities.mjs.map +1 -1
  40. package/dist/strapi/providers/local-destination/strategies/restore/index.js +2 -0
  41. package/dist/strapi/providers/local-destination/strategies/restore/index.js.map +1 -1
  42. package/dist/strapi/providers/local-destination/strategies/restore/index.mjs +2 -0
  43. package/dist/strapi/providers/local-destination/strategies/restore/index.mjs.map +1 -1
  44. package/dist/strapi/providers/local-source/assets.d.ts +8 -1
  45. package/dist/strapi/providers/local-source/assets.d.ts.map +1 -1
  46. package/dist/strapi/providers/local-source/assets.js +47 -19
  47. package/dist/strapi/providers/local-source/assets.js.map +1 -1
  48. package/dist/strapi/providers/local-source/assets.mjs +46 -20
  49. package/dist/strapi/providers/local-source/assets.mjs.map +1 -1
  50. package/dist/strapi/providers/local-source/estimate-asset-totals.d.ts +11 -0
  51. package/dist/strapi/providers/local-source/estimate-asset-totals.d.ts.map +1 -0
  52. package/dist/strapi/providers/local-source/estimate-asset-totals.js +130 -0
  53. package/dist/strapi/providers/local-source/estimate-asset-totals.js.map +1 -0
  54. package/dist/strapi/providers/local-source/estimate-asset-totals.mjs +128 -0
  55. package/dist/strapi/providers/local-source/estimate-asset-totals.mjs.map +1 -0
  56. package/dist/strapi/providers/local-source/index.d.ts +3 -2
  57. package/dist/strapi/providers/local-source/index.d.ts.map +1 -1
  58. package/dist/strapi/providers/local-source/index.js +30 -3
  59. package/dist/strapi/providers/local-source/index.js.map +1 -1
  60. package/dist/strapi/providers/local-source/index.mjs +30 -4
  61. package/dist/strapi/providers/local-source/index.mjs.map +1 -1
  62. package/dist/strapi/providers/remote-destination/index.d.ts +3 -1
  63. package/dist/strapi/providers/remote-destination/index.d.ts.map +1 -1
  64. package/dist/strapi/providers/remote-destination/index.js +88 -19
  65. package/dist/strapi/providers/remote-destination/index.js.map +1 -1
  66. package/dist/strapi/providers/remote-destination/index.mjs +89 -20
  67. package/dist/strapi/providers/remote-destination/index.mjs.map +1 -1
  68. package/dist/strapi/providers/remote-source/index.d.ts +6 -3
  69. package/dist/strapi/providers/remote-source/index.d.ts.map +1 -1
  70. package/dist/strapi/providers/remote-source/index.js +180 -47
  71. package/dist/strapi/providers/remote-source/index.js.map +1 -1
  72. package/dist/strapi/providers/remote-source/index.mjs +181 -48
  73. package/dist/strapi/providers/remote-source/index.mjs.map +1 -1
  74. package/dist/strapi/providers/utils.d.ts +9 -6
  75. package/dist/strapi/providers/utils.d.ts.map +1 -1
  76. package/dist/strapi/providers/utils.js +9 -4
  77. package/dist/strapi/providers/utils.js.map +1 -1
  78. package/dist/strapi/providers/utils.mjs +9 -4
  79. package/dist/strapi/providers/utils.mjs.map +1 -1
  80. package/dist/strapi/remote/handlers/pull.d.ts +1 -0
  81. package/dist/strapi/remote/handlers/pull.d.ts.map +1 -1
  82. package/dist/strapi/remote/handlers/pull.js +36 -15
  83. package/dist/strapi/remote/handlers/pull.js.map +1 -1
  84. package/dist/strapi/remote/handlers/pull.mjs +37 -16
  85. package/dist/strapi/remote/handlers/pull.mjs.map +1 -1
  86. package/dist/strapi/remote/handlers/push.d.ts +13 -2
  87. package/dist/strapi/remote/handlers/push.d.ts.map +1 -1
  88. package/dist/strapi/remote/handlers/push.js +81 -34
  89. package/dist/strapi/remote/handlers/push.js.map +1 -1
  90. package/dist/strapi/remote/handlers/push.mjs +82 -35
  91. package/dist/strapi/remote/handlers/push.mjs.map +1 -1
  92. package/dist/strapi/remote/handlers/utils.d.ts.map +1 -1
  93. package/dist/strapi/remote/handlers/utils.js +5 -3
  94. package/dist/strapi/remote/handlers/utils.js.map +1 -1
  95. package/dist/strapi/remote/handlers/utils.mjs +5 -3
  96. package/dist/strapi/remote/handlers/utils.mjs.map +1 -1
  97. package/dist/utils/index.d.ts +2 -0
  98. package/dist/utils/index.d.ts.map +1 -1
  99. package/dist/utils/index.js +7 -0
  100. package/dist/utils/index.js.map +1 -1
  101. package/dist/utils/index.mjs +2 -0
  102. package/dist/utils/index.mjs.map +1 -1
  103. package/dist/utils/stream.d.ts.map +1 -1
  104. package/dist/utils/stream.js +40 -3
  105. package/dist/utils/stream.js.map +1 -1
  106. package/dist/utils/stream.mjs +40 -3
  107. package/dist/utils/stream.mjs.map +1 -1
  108. package/dist/utils/transfer-asset-chunk.d.ts +41 -0
  109. package/dist/utils/transfer-asset-chunk.d.ts.map +1 -0
  110. package/dist/utils/transfer-asset-chunk.js +93 -0
  111. package/dist/utils/transfer-asset-chunk.js.map +1 -0
  112. package/dist/utils/transfer-asset-chunk.mjs +88 -0
  113. package/dist/utils/transfer-asset-chunk.mjs.map +1 -0
  114. package/dist/utils/transfer-websocket-json.d.ts +24 -0
  115. package/dist/utils/transfer-websocket-json.d.ts.map +1 -0
  116. package/dist/utils/transfer-websocket-json.js +67 -0
  117. package/dist/utils/transfer-websocket-json.js.map +1 -0
  118. package/dist/utils/transfer-websocket-json.mjs +63 -0
  119. package/dist/utils/transfer-websocket-json.mjs.map +1 -0
  120. package/dist/utils/writable-async-write.d.ts +17 -0
  121. package/dist/utils/writable-async-write.d.ts.map +1 -0
  122. package/dist/utils/writable-async-write.js +61 -0
  123. package/dist/utils/writable-async-write.js.map +1 -0
  124. package/dist/utils/writable-async-write.mjs +59 -0
  125. package/dist/utils/writable-async-write.mjs.map +1 -0
  126. package/package.json +8 -8
@@ -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 { 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 * 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 (e) {\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 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 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 (error) {\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 outStream.write(asset);\n },\n }),\n ],\n () => outStream.end()\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 (e) {\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 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 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 outStream.write(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 async () => {\n // Manually send the 'end' event to the out stream\n // once every entry has finished streaming its content\n outStream.end();\n }\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","e","encryption","enabled","ProviderInitializationError","getMetadata","getSchemas","schemaCollection","utils","createSchemasReadStream","isEmpty","schemas","keyBy","createEntitiesReadStream","createLinksReadStream","createConfigurationReadStream","createAssetsReadStream","inStream","outStream","PassThrough","objectMode","loadAssetMetadata","bind","pipeline","Parser","filter","entry","type","isFilePathInDirname","onReadEntry","size","normalizedPath","unknownPathToPosix","basename","metadata","error","Error","asset","filename","filepath","stats","stream","write","end","name","key","undefined","message","report","details","createdAt","Date","origin","kind","backupStream","compression","streams","push","fs","createReadStream","zip","createGunzip","chain","directory","transforms","parser","checkErrors","line","value","pipe","chunk","destroy","ProviderTransferError","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 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 (e) {\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 (error) {\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 (e) {\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","e","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","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","ProviderTransferError","fileStream","Promise","resolve","reject","entryPath","isPathEquivalent","chunks","Buffer","isBuffer","from","parsedContent","JSON","parse","concat","toString"],"mappings":"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"}
@@ -8,11 +8,12 @@ import { chain } from 'stream-chain';
8
8
  import { parser } from 'stream-json/jsonl/Parser';
9
9
  import 'crypto';
10
10
  import { createDecryptionCipher } from '../../../utils/encryption/decrypt.mjs';
11
+ import { write } from '../../../utils/writable-async-write.mjs';
11
12
  import { collect } from '../../../utils/stream.mjs';
12
13
  import { schemasToValidJSON } from '../../../utils/schema.mjs';
13
14
  import 'events';
14
15
  import { ProviderInitializationError, ProviderTransferError } from '../../../errors/providers.mjs';
15
- import { unknownPathToPosix, isFilePathInDirname, isPathEquivalent } from './utils.mjs';
16
+ import { isFilePathInDirname, unknownPathToPosix, isPathEquivalent } from './utils.mjs';
16
17
 
17
18
  function _class_private_field_loose_base(receiver, privateKey) {
18
19
  if (!Object.prototype.hasOwnProperty.call(receiver, privateKey)) {
@@ -30,7 +31,10 @@ function _class_private_field_loose_key(name) {
30
31
  const createLocalFileSourceProvider = (options)=>{
31
32
  return new LocalFileSourceProvider(options);
32
33
  };
33
- 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"), _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
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
+ * tar `Parser` invokes the pipeline completion callback when the archive ends, but it does not
36
+ * reliably await async `onReadEntry` — defer `end` until outstanding async entry work is done.
37
+ */ _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
34
38
  _streamJsonlDirectory = /*#__PURE__*/ _class_private_field_loose_key("_streamJsonlDirectory"), _parseJSONFile = /*#__PURE__*/ _class_private_field_loose_key("_parseJSONFile");
35
39
  class LocalFileSourceProvider {
36
40
  /**
@@ -94,6 +98,15 @@ class LocalFileSourceProvider {
94
98
  });
95
99
  const loadAssetMetadata = _class_private_field_loose_base(this, _loadAssetMetadata)[_loadAssetMetadata].bind(this);
96
100
  _class_private_field_loose_base(this, _reportInfo)[_reportInfo]('creating assets read stream');
101
+ let activeAsyncEntries = 0;
102
+ const runReadEntry = async (fn)=>{
103
+ activeAsyncEntries += 1;
104
+ try {
105
+ await fn();
106
+ } finally{
107
+ activeAsyncEntries -= 1;
108
+ }
109
+ };
97
110
  pipeline([
98
111
  inStream,
99
112
  new Parser({
@@ -105,34 +118,39 @@ class LocalFileSourceProvider {
105
118
  return isFilePathInDirname('assets/uploads', filePath);
106
119
  },
107
120
  async onReadEntry (entry) {
108
- const { path: filePath, size = 0 } = entry;
109
- const normalizedPath = unknownPathToPosix(filePath);
110
- const file = path.basename(normalizedPath);
111
- let metadata;
112
- try {
113
- metadata = await loadAssetMetadata(`assets/metadata/${file}.json`);
114
- } catch (error) {
115
- throw new Error(`Failed to read metadata for ${file}`);
116
- }
117
- const asset = {
118
- metadata,
119
- filename: file,
120
- filepath: normalizedPath,
121
- stats: {
122
- size
123
- },
124
- stream: entry
125
- };
126
- outStream.write(asset);
121
+ await runReadEntry(async ()=>{
122
+ const { path: filePath, size = 0 } = entry;
123
+ const normalizedPath = unknownPathToPosix(filePath);
124
+ const file = path.basename(normalizedPath);
125
+ let metadata;
126
+ try {
127
+ metadata = await loadAssetMetadata(`assets/metadata/${file}.json`);
128
+ } catch (error) {
129
+ throw new Error(`Failed to read metadata for ${file}`);
130
+ }
131
+ const asset = {
132
+ metadata,
133
+ filename: file,
134
+ filepath: normalizedPath,
135
+ stats: {
136
+ size
137
+ },
138
+ stream: entry
139
+ };
140
+ await write(outStream, asset);
141
+ });
127
142
  }
128
143
  })
129
- ], ()=>outStream.end());
144
+ ], (err)=>_class_private_field_loose_base(this, _endPassThroughWhenTarIdle)[_endPassThroughWhenTarIdle](outStream, ()=>activeAsyncEntries, err));
130
145
  return outStream;
131
146
  }
132
147
  constructor(options){
133
148
  Object.defineProperty(this, _reportInfo, {
134
149
  value: reportInfo
135
150
  });
151
+ Object.defineProperty(this, _endPassThroughWhenTarIdle, {
152
+ value: endPassThroughWhenTarIdle
153
+ });
136
154
  Object.defineProperty(this, _loadMetadata, {
137
155
  value: loadMetadata
138
156
  });
@@ -176,6 +194,20 @@ function reportInfo(message) {
176
194
  kind: 'info'
177
195
  });
178
196
  }
197
+ function endPassThroughWhenTarIdle(outStream, activeAsyncEntries, err) {
198
+ if (err) {
199
+ outStream.destroy(err);
200
+ return;
201
+ }
202
+ const tick = ()=>{
203
+ if (activeAsyncEntries() === 0) {
204
+ outStream.end();
205
+ } else {
206
+ setImmediate(tick);
207
+ }
208
+ };
209
+ tick();
210
+ }
179
211
  async function loadMetadata() {
180
212
  const backupStream = _class_private_field_loose_base(this, _getBackupStream)[_getBackupStream]();
181
213
  _class_private_field_loose_base(this, _metadata)[_metadata] = await _class_private_field_loose_base(this, _parseJSONFile)[_parseJSONFile](backupStream, METADATA_FILE_PATH);
@@ -205,6 +237,15 @@ function streamJsonlDirectory(directory) {
205
237
  const outStream = new PassThrough({
206
238
  objectMode: true
207
239
  });
240
+ let activeAsyncEntries = 0;
241
+ const runReadEntry = async (fn)=>{
242
+ activeAsyncEntries += 1;
243
+ try {
244
+ await fn();
245
+ } finally{
246
+ activeAsyncEntries -= 1;
247
+ }
248
+ };
208
249
  pipeline([
209
250
  inStream,
210
251
  new Parser({
@@ -215,33 +256,31 @@ function streamJsonlDirectory(directory) {
215
256
  return isFilePathInDirname(directory, filePath);
216
257
  },
217
258
  async onReadEntry (entry) {
218
- const transforms = [
219
- // JSONL parser to read the data chunks one by one (line by line)
220
- parser({
221
- checkErrors: true
222
- }),
223
- // The JSONL parser returns each line as key/value
224
- (line)=>line.value
225
- ];
226
- const stream = entry.pipe(chain(transforms));
227
- try {
228
- for await (const chunk of stream){
229
- outStream.write(chunk);
230
- }
231
- } catch (e) {
232
- outStream.destroy(new ProviderTransferError(`Error parsing backup files from backup file ${entry.path}: ${e.message}`, {
233
- details: {
234
- error: e
259
+ await runReadEntry(async ()=>{
260
+ const transforms = [
261
+ // JSONL parser to read the data chunks one by one (line by line)
262
+ parser({
263
+ checkErrors: true
264
+ }),
265
+ // The JSONL parser returns each line as key/value
266
+ (line)=>line.value
267
+ ];
268
+ const stream = entry.pipe(chain(transforms));
269
+ try {
270
+ for await (const chunk of stream){
271
+ await write(outStream, chunk);
235
272
  }
236
- }));
237
- }
273
+ } catch (e) {
274
+ outStream.destroy(new ProviderTransferError(`Error parsing backup files from backup file ${entry.path}: ${e.message}`, {
275
+ details: {
276
+ error: e
277
+ }
278
+ }));
279
+ }
280
+ });
238
281
  }
239
282
  })
240
- ], async ()=>{
241
- // Manually send the 'end' event to the out stream
242
- // once every entry has finished streaming its content
243
- outStream.end();
244
- });
283
+ ], (err)=>_class_private_field_loose_base(this, _endPassThroughWhenTarIdle)[_endPassThroughWhenTarIdle](outStream, ()=>activeAsyncEntries, err));
245
284
  return outStream;
246
285
  }
247
286
  async function parseJSONFile(fileStream, filePath) {
@@ -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 { 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 * 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 (e) {\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 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 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 (error) {\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 outStream.write(asset);\n },\n }),\n ],\n () => outStream.end()\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 (e) {\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 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 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 outStream.write(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 async () => {\n // Manually send the 'end' event to the out stream\n // once every entry has finished streaming its content\n outStream.end();\n }\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","e","encryption","enabled","ProviderInitializationError","getMetadata","getSchemas","schemaCollection","utils","createSchemasReadStream","isEmpty","schemas","keyBy","createEntitiesReadStream","createLinksReadStream","createConfigurationReadStream","createAssetsReadStream","inStream","outStream","PassThrough","objectMode","loadAssetMetadata","bind","pipeline","Parser","filter","entry","type","isFilePathInDirname","onReadEntry","size","normalizedPath","unknownPathToPosix","basename","metadata","error","Error","asset","filename","filepath","stats","stream","write","end","name","key","undefined","message","report","details","createdAt","Date","origin","kind","backupStream","compression","streams","push","fs","createReadStream","zip","createGunzip","chain","directory","transforms","parser","checkErrors","line","value","pipe","chunk","destroy","ProviderTransferError","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 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 (e) {\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 (error) {\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 (e) {\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","e","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","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","ProviderTransferError","fileStream","Promise","resolve","reject","entryPath","isPathEquivalent","chunks","Buffer","isBuffer","from","parsedContent","JSON","parse","concat","toString"],"mappings":"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"}
@@ -4,6 +4,7 @@ var index = require('./local-destination/index.js');
4
4
  var index$1 = require('./local-source/index.js');
5
5
  var index$2 = require('./remote-destination/index.js');
6
6
  var index$3 = require('./remote-source/index.js');
7
+ var estimateAssetTotals = require('./local-source/estimate-asset-totals.js');
7
8
 
8
9
  // Local
9
10
 
@@ -13,4 +14,5 @@ exports.createLocalStrapiDestinationProvider = index.createLocalStrapiDestinatio
13
14
  exports.createLocalStrapiSourceProvider = index$1.createLocalStrapiSourceProvider;
14
15
  exports.createRemoteStrapiDestinationProvider = index$2.createRemoteStrapiDestinationProvider;
15
16
  exports.createRemoteStrapiSourceProvider = index$3.createRemoteStrapiSourceProvider;
17
+ exports.estimateAssetTotals = estimateAssetTotals.estimateAssetTotals;
16
18
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../../src/strapi/providers/index.ts"],"sourcesContent":["// Local\nexport * from './local-destination';\nexport * from './local-source';\n\n// Remote\nexport * from './remote-destination';\nexport * from './remote-source';\n"],"names":[],"mappings":";;;;;;;AAAA;;;;;;;;;"}
1
+ {"version":3,"file":"index.js","sources":["../../../src/strapi/providers/index.ts"],"sourcesContent":["// Local\nexport * from './local-destination';\nexport * from './local-source';\n\n// Remote\nexport * from './remote-destination';\nexport * from './remote-source';\n"],"names":[],"mappings":";;;;;;;;AAAA;;;;;;;;;;"}
@@ -2,6 +2,7 @@ export { DEFAULT_CONFLICT_STRATEGY, VALID_CONFLICT_STRATEGIES, createLocalStrapi
2
2
  export { createLocalStrapiSourceProvider } from './local-source/index.mjs';
3
3
  export { createRemoteStrapiDestinationProvider } from './remote-destination/index.mjs';
4
4
  export { createRemoteStrapiSourceProvider } from './remote-source/index.mjs';
5
+ export { estimateAssetTotals } from './local-source/estimate-asset-totals.mjs';
5
6
 
6
7
  // Local
7
8
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","sources":["../../../src/strapi/providers/index.ts"],"sourcesContent":["// Local\nexport * from './local-destination';\nexport * from './local-source';\n\n// Remote\nexport * from './remote-destination';\nexport * from './remote-source';\n"],"names":[],"mappings":";;;;;AAAA"}
1
+ {"version":3,"file":"index.mjs","sources":["../../../src/strapi/providers/index.ts"],"sourcesContent":["// Local\nexport * from './local-destination';\nexport * from './local-source';\n\n// Remote\nexport * from './remote-destination';\nexport * from './remote-source';\n"],"names":[],"mappings":";;;;;;AAAA"}
@@ -0,0 +1,22 @@
1
+ /// <reference types="node" />
2
+ import { Writable } from 'stream';
3
+ import type { Core } from '@strapi/types';
4
+ import type { Transaction } from '../../../../types/utils';
5
+ export interface CreateAssetsDestinationWritableOptions {
6
+ strapi: Core.Strapi;
7
+ transaction: Transaction;
8
+ resolveUploadFileId: (metadata: {
9
+ id: number;
10
+ }) => number | undefined;
11
+ restoreMediaEntitiesContent: boolean;
12
+ removeAssetsBackup: () => Promise<void>;
13
+ }
14
+ /**
15
+ * Writable for restoring upload assets during a local push destination transfer.
16
+ *
17
+ * The Writable `write()` callback must return as soon as the chunk is accepted — **before**
18
+ * `uploadStream` finishes — so the remote push handler can feed PassThrough data in the same
19
+ * WebSocket batch after an asset `start` row (see `streamAsset` in remote `push` handler).
20
+ */
21
+ export declare function createAssetsDestinationWritable(options: CreateAssetsDestinationWritableOptions): Writable;
22
+ //# sourceMappingURL=assets-destination-writable.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assets-destination-writable.d.ts","sourceRoot":"","sources":["../../../../src/strapi/providers/local-destination/assets-destination-writable.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,QAAQ,EAAY,MAAM,QAAQ,CAAC;AAC5C,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAG1C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAE3D,MAAM,WAAW,sCAAsC;IACrD,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC;IACpB,WAAW,EAAE,WAAW,CAAC;IACzB,mBAAmB,EAAE,CAAC,QAAQ,EAAE;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,KAAK,MAAM,GAAG,SAAS,CAAC;IACtE,2BAA2B,EAAE,OAAO,CAAC;IACrC,kBAAkB,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CACzC;AAED;;;;;;GAMG;AACH,wBAAgB,+BAA+B,CAC7C,OAAO,EAAE,sCAAsC,GAC9C,QAAQ,CAwGV"}
@@ -0,0 +1,107 @@
1
+ 'use strict';
2
+
3
+ var stream = require('stream');
4
+
5
+ /**
6
+ * Writable for restoring upload assets during a local push destination transfer.
7
+ *
8
+ * The Writable `write()` callback must return as soon as the chunk is accepted — **before**
9
+ * `uploadStream` finishes — so the remote push handler can feed PassThrough data in the same
10
+ * WebSocket batch after an asset `start` row (see `streamAsset` in remote `push` handler).
11
+ */ function createAssetsDestinationWritable(options) {
12
+ const { strapi, transaction, resolveUploadFileId, restoreMediaEntitiesContent, removeAssetsBackup } = options;
13
+ let pendingUploads = 0;
14
+ return new stream.Writable({
15
+ objectMode: true,
16
+ async final (next) {
17
+ while(pendingUploads > 0){
18
+ await new Promise((resolve)=>{
19
+ setImmediate(resolve);
20
+ });
21
+ }
22
+ await removeAssetsBackup();
23
+ next();
24
+ },
25
+ write (chunk, _encoding, callback) {
26
+ const uploadData = {
27
+ ...chunk.metadata,
28
+ stream: stream.Readable.from(chunk.stream),
29
+ buffer: chunk?.buffer
30
+ };
31
+ const provider = strapi.config.get('plugin::upload').provider;
32
+ const fileId = resolveUploadFileId(uploadData);
33
+ if (!fileId) {
34
+ callback(new Error(`File ID not found for ID: ${uploadData.id}`));
35
+ return;
36
+ }
37
+ if (!transaction) {
38
+ callback(new Error('Transaction not available for asset upload'));
39
+ return;
40
+ }
41
+ pendingUploads += 1;
42
+ transaction.attach(async ()=>{
43
+ try {
44
+ await strapi.plugin('upload').provider.uploadStream(uploadData);
45
+ if (!restoreMediaEntitiesContent) {
46
+ return;
47
+ }
48
+ if (uploadData?.type) {
49
+ const entry = await strapi.db.query('plugin::upload.file').findOne({
50
+ where: {
51
+ id: fileId
52
+ }
53
+ });
54
+ if (!entry) {
55
+ throw new Error('file not found');
56
+ }
57
+ const specificFormat = entry?.formats?.[uploadData.type];
58
+ if (specificFormat) {
59
+ specificFormat.url = uploadData.url;
60
+ }
61
+ await strapi.db.query('plugin::upload.file').update({
62
+ where: {
63
+ id: entry.id
64
+ },
65
+ data: {
66
+ formats: entry.formats,
67
+ provider
68
+ }
69
+ });
70
+ return;
71
+ }
72
+ const entry = await strapi.db.query('plugin::upload.file').findOne({
73
+ where: {
74
+ id: fileId
75
+ }
76
+ });
77
+ if (!entry) {
78
+ throw new Error('file not found');
79
+ }
80
+ entry.url = uploadData.url;
81
+ await strapi.db.query('plugin::upload.file').update({
82
+ where: {
83
+ id: entry.id
84
+ },
85
+ data: {
86
+ url: entry.url,
87
+ provider
88
+ }
89
+ });
90
+ } catch (error) {
91
+ throw new Error(`Error while uploading asset ${chunk.filename} ${error}`);
92
+ }
93
+ }).finally(()=>{
94
+ pendingUploads -= 1;
95
+ }).catch((error)=>{
96
+ const err = error instanceof Error ? error : new Error(String(error));
97
+ process.nextTick(()=>{
98
+ this.destroy(err);
99
+ });
100
+ });
101
+ callback();
102
+ }
103
+ });
104
+ }
105
+
106
+ exports.createAssetsDestinationWritable = createAssetsDestinationWritable;
107
+ //# sourceMappingURL=assets-destination-writable.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assets-destination-writable.js","sources":["../../../../src/strapi/providers/local-destination/assets-destination-writable.ts"],"sourcesContent":["import { Writable, Readable } from 'stream';\nimport type { Core } from '@strapi/types';\n\nimport type { IAsset, IFile } from '../../../../types';\nimport type { Transaction } from '../../../../types/utils';\n\nexport interface CreateAssetsDestinationWritableOptions {\n strapi: Core.Strapi;\n transaction: Transaction;\n resolveUploadFileId: (metadata: { id: number }) => number | undefined;\n restoreMediaEntitiesContent: boolean;\n removeAssetsBackup: () => Promise<void>;\n}\n\n/**\n * Writable for restoring upload assets during a local push destination transfer.\n *\n * The Writable `write()` callback must return as soon as the chunk is accepted — **before**\n * `uploadStream` finishes — so the remote push handler can feed PassThrough data in the same\n * WebSocket batch after an asset `start` row (see `streamAsset` in remote `push` handler).\n */\nexport function createAssetsDestinationWritable(\n options: CreateAssetsDestinationWritableOptions\n): Writable {\n const {\n strapi,\n transaction,\n resolveUploadFileId,\n restoreMediaEntitiesContent,\n removeAssetsBackup,\n } = options;\n\n let pendingUploads = 0;\n\n return new Writable({\n objectMode: true,\n async final(next) {\n while (pendingUploads > 0) {\n await new Promise<void>((resolve) => {\n setImmediate(resolve);\n });\n }\n await removeAssetsBackup();\n next();\n },\n write(chunk: IAsset, _encoding, callback) {\n const uploadData = {\n ...chunk.metadata,\n stream: Readable.from(chunk.stream),\n buffer: chunk?.buffer,\n };\n\n const provider = strapi.config.get<{ provider: string }>('plugin::upload').provider;\n\n const fileId = resolveUploadFileId(uploadData);\n if (!fileId) {\n callback(new Error(`File ID not found for ID: ${uploadData.id}`));\n return;\n }\n\n if (!transaction) {\n callback(new Error('Transaction not available for asset upload'));\n return;\n }\n\n pendingUploads += 1;\n transaction\n .attach(async () => {\n try {\n await strapi.plugin('upload').provider.uploadStream(uploadData);\n\n if (!restoreMediaEntitiesContent) {\n return;\n }\n\n if (uploadData?.type) {\n const entry: IFile = await strapi.db.query('plugin::upload.file').findOne({\n where: { id: fileId },\n });\n if (!entry) {\n throw new Error('file not found');\n }\n const specificFormat = entry?.formats?.[uploadData.type];\n if (specificFormat) {\n specificFormat.url = uploadData.url;\n }\n await strapi.db.query('plugin::upload.file').update({\n where: { id: entry.id },\n data: {\n formats: entry.formats,\n provider,\n },\n });\n return;\n }\n\n const entry: IFile = await strapi.db.query('plugin::upload.file').findOne({\n where: { id: fileId },\n });\n if (!entry) {\n throw new Error('file not found');\n }\n entry.url = uploadData.url;\n await strapi.db.query('plugin::upload.file').update({\n where: { id: entry.id },\n data: {\n url: entry.url,\n provider,\n },\n });\n } catch (error) {\n throw new Error(`Error while uploading asset ${chunk.filename} ${error}`);\n }\n })\n .finally(() => {\n pendingUploads -= 1;\n })\n .catch((error: unknown) => {\n const err = error instanceof Error ? error : new Error(String(error));\n process.nextTick(() => {\n this.destroy(err);\n });\n });\n\n callback();\n },\n });\n}\n"],"names":["createAssetsDestinationWritable","options","strapi","transaction","resolveUploadFileId","restoreMediaEntitiesContent","removeAssetsBackup","pendingUploads","Writable","objectMode","final","next","Promise","resolve","setImmediate","write","chunk","_encoding","callback","uploadData","metadata","stream","Readable","from","buffer","provider","config","get","fileId","Error","id","attach","plugin","uploadStream","type","entry","db","query","findOne","where","specificFormat","formats","url","update","data","error","filename","finally","catch","err","String","process","nextTick","destroy"],"mappings":";;;;AAcA;;;;;;IAOO,SAASA,+BAAAA,CACdC,OAA+C,EAAA;IAE/C,MAAM,EACJC,MAAM,EACNC,WAAW,EACXC,mBAAmB,EACnBC,2BAA2B,EAC3BC,kBAAkB,EACnB,GAAGL,OAAAA;AAEJ,IAAA,IAAIM,cAAAA,GAAiB,CAAA;AAErB,IAAA,OAAO,IAAIC,eAAAA,CAAS;QAClBC,UAAAA,EAAY,IAAA;AACZ,QAAA,MAAMC,OAAMC,IAAI,EAAA;AACd,YAAA,MAAOJ,iBAAiB,CAAA,CAAG;gBACzB,MAAM,IAAIK,QAAc,CAACC,OAAAA,GAAAA;oBACvBC,YAAAA,CAAaD,OAAAA,CAAAA;AACf,gBAAA,CAAA,CAAA;AACF,YAAA;YACA,MAAMP,kBAAAA,EAAAA;AACNK,YAAAA,IAAAA,EAAAA;AACF,QAAA,CAAA;AACAI,QAAAA,KAAAA,CAAAA,CAAMC,KAAa,EAAEC,SAAS,EAAEC,QAAQ,EAAA;AACtC,YAAA,MAAMC,UAAAA,GAAa;AACjB,gBAAA,GAAGH,MAAMI,QAAQ;AACjBC,gBAAAA,MAAAA,EAAQC,eAAAA,CAASC,IAAI,CAACP,KAAAA,CAAMK,MAAM,CAAA;AAClCG,gBAAAA,MAAAA,EAAQR,KAAAA,EAAOQ;AACjB,aAAA;AAEA,YAAA,MAAMC,WAAWvB,MAAAA,CAAOwB,MAAM,CAACC,GAAG,CAAuB,kBAAkBF,QAAQ;AAEnF,YAAA,MAAMG,SAASxB,mBAAAA,CAAoBe,UAAAA,CAAAA;AACnC,YAAA,IAAI,CAACS,MAAAA,EAAQ;AACXV,gBAAAA,QAAAA,CAAS,IAAIW,KAAAA,CAAM,CAAC,0BAA0B,EAAEV,UAAAA,CAAWW,EAAE,CAAA,CAAE,CAAA,CAAA;AAC/D,gBAAA;AACF,YAAA;AAEA,YAAA,IAAI,CAAC3B,WAAAA,EAAa;AAChBe,gBAAAA,QAAAA,CAAS,IAAIW,KAAAA,CAAM,4CAAA,CAAA,CAAA;AACnB,gBAAA;AACF,YAAA;YAEAtB,cAAAA,IAAkB,CAAA;AAClBJ,YAAAA,WAAAA,CACG4B,MAAM,CAAC,UAAA;gBACN,IAAI;AACF,oBAAA,MAAM7B,OAAO8B,MAAM,CAAC,UAAUP,QAAQ,CAACQ,YAAY,CAACd,UAAAA,CAAAA;AAEpD,oBAAA,IAAI,CAACd,2BAAAA,EAA6B;AAChC,wBAAA;AACF,oBAAA;AAEA,oBAAA,IAAIc,YAAYe,IAAAA,EAAM;wBACpB,MAAMC,KAAAA,GAAe,MAAMjC,MAAAA,CAAOkC,EAAE,CAACC,KAAK,CAAC,qBAAA,CAAA,CAAuBC,OAAO,CAAC;4BACxEC,KAAAA,EAAO;gCAAET,EAAAA,EAAIF;AAAO;AACtB,yBAAA,CAAA;AACA,wBAAA,IAAI,CAACO,KAAAA,EAAO;AACV,4BAAA,MAAM,IAAIN,KAAAA,CAAM,gBAAA,CAAA;AAClB,wBAAA;AACA,wBAAA,MAAMW,iBAAiBL,KAAAA,EAAOM,OAAAA,GAAUtB,UAAAA,CAAWe,IAAI,CAAC;AACxD,wBAAA,IAAIM,cAAAA,EAAgB;4BAClBA,cAAAA,CAAeE,GAAG,GAAGvB,UAAAA,CAAWuB,GAAG;AACrC,wBAAA;AACA,wBAAA,MAAMxC,OAAOkC,EAAE,CAACC,KAAK,CAAC,qBAAA,CAAA,CAAuBM,MAAM,CAAC;4BAClDJ,KAAAA,EAAO;AAAET,gCAAAA,EAAAA,EAAIK,MAAML;AAAG,6BAAA;4BACtBc,IAAAA,EAAM;AACJH,gCAAAA,OAAAA,EAASN,MAAMM,OAAO;AACtBhB,gCAAAA;AACF;AACF,yBAAA,CAAA;AACA,wBAAA;AACF,oBAAA;oBAEA,MAAMU,KAAAA,GAAe,MAAMjC,MAAAA,CAAOkC,EAAE,CAACC,KAAK,CAAC,qBAAA,CAAA,CAAuBC,OAAO,CAAC;wBACxEC,KAAAA,EAAO;4BAAET,EAAAA,EAAIF;AAAO;AACtB,qBAAA,CAAA;AACA,oBAAA,IAAI,CAACO,KAAAA,EAAO;AACV,wBAAA,MAAM,IAAIN,KAAAA,CAAM,gBAAA,CAAA;AAClB,oBAAA;oBACAM,KAAAA,CAAMO,GAAG,GAAGvB,UAAAA,CAAWuB,GAAG;AAC1B,oBAAA,MAAMxC,OAAOkC,EAAE,CAACC,KAAK,CAAC,qBAAA,CAAA,CAAuBM,MAAM,CAAC;wBAClDJ,KAAAA,EAAO;AAAET,4BAAAA,EAAAA,EAAIK,MAAML;AAAG,yBAAA;wBACtBc,IAAAA,EAAM;AACJF,4BAAAA,GAAAA,EAAKP,MAAMO,GAAG;AACdjB,4BAAAA;AACF;AACF,qBAAA,CAAA;AACF,gBAAA,CAAA,CAAE,OAAOoB,KAAAA,EAAO;oBACd,MAAM,IAAIhB,KAAAA,CAAM,CAAC,4BAA4B,EAAEb,MAAM8B,QAAQ,CAAC,CAAC,EAAED,KAAAA,CAAAA,CAAO,CAAA;AAC1E,gBAAA;AACF,YAAA,CAAA,CAAA,CACCE,OAAO,CAAC,IAAA;gBACPxC,cAAAA,IAAkB,CAAA;YACpB,CAAA,CAAA,CACCyC,KAAK,CAAC,CAACH,KAAAA,GAAAA;AACN,gBAAA,MAAMI,MAAMJ,KAAAA,YAAiBhB,KAAAA,GAAQgB,KAAAA,GAAQ,IAAIhB,MAAMqB,MAAAA,CAAOL,KAAAA,CAAAA,CAAAA;AAC9DM,gBAAAA,OAAAA,CAAQC,QAAQ,CAAC,IAAA;oBACf,IAAI,CAACC,OAAO,CAACJ,GAAAA,CAAAA;AACf,gBAAA,CAAA,CAAA;AACF,YAAA,CAAA,CAAA;AAEF/B,YAAAA,QAAAA,EAAAA;AACF,QAAA;AACF,KAAA,CAAA;AACF;;;;"}