@strapi/data-transfer
Version:
Data transfer capabilities for Strapi
1 lines • 19.4 kB
Source Map (JSON)
{"version":3,"file":"index.mjs","sources":["../../../../src/file/providers/source/index.ts"],"sourcesContent":["import type { Readable } from 'stream';\n\nimport zip from 'zlib';\nimport path from 'path';\nimport { pipeline, PassThrough } from 'stream';\nimport fs from 'fs-extra';\nimport tar 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 tar.Parse({\n // find only files in the assets/uploads folder\n filter(filePath, entry) {\n if (entry.type !== 'File') {\n return false;\n }\n return isFilePathInDirname('assets/uploads', filePath);\n },\n async onentry(entry) {\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 tar.Parse({\n filter(filePath, entry) {\n if (entry.type !== 'File') {\n return false;\n }\n\n return isFilePathInDirname(directory, filePath);\n },\n\n async onentry(entry) {\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 tar.Parse({\n /**\n * Filter the parsed entries to only keep the one that matches the given filepath\n */\n filter(entryPath, entry) {\n if (entry.type !== 'File') {\n return false;\n }\n\n return isPathEquivalent(entryPath, filePath);\n },\n\n async onentry(entry) {\n // Collect all the content of the entry file\n const content = await entry.collect();\n\n try {\n // Parse from buffer array to string to JSON\n const parsedContent = JSON.parse(Buffer.concat(content).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","tar","Parse","filter","entry","type","isFilePathInDirname","onentry","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","content","collect","parsedContent","JSON","parse","Buffer","concat","toString"],"mappings":"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"}