@humaan/payload-storage-imagekit 2.9.0 → 2.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -318,6 +318,12 @@ paths are flattened into the destination collection folder; collisions are repor
318
318
  history and account-specific custom metadata schemas are not transferred. Run one migration per
319
319
  destination at a time; concurrent runs may report a conflict recoverable on a subsequent run.
320
320
 
321
+ On MongoDB, migration updates use the database adapter directly so the old `_objectKey` can be
322
+ removed in the same write as the new storage reference. Writing `null` would collide with the
323
+ legacy sparse unique index. These metadata updates bypass Payload validation and change hooks,
324
+ including cache revalidation; refresh application caches after the migration. Already uploaded
325
+ files from an interrupted 2.9.0 migration can be recovered by rerunning with this fix.
326
+
321
327
  Run a migration script:
322
328
 
323
329
  ```bash
package/dist/migrate.js CHANGED
@@ -227,20 +227,40 @@ const transferTag = (source, filePath, documentID, isPrivate)=>{
227
227
  filename: destination.name,
228
228
  imagekit
229
229
  };
230
- await payload.update({
231
- id: doc.id,
232
- collection: slug,
233
- context: {
234
- skipCloudStorage: true
235
- },
236
- data: {
237
- _objectKey: null,
238
- filename: destination.name,
239
- imagekit,
240
- prefix: destinationFolder.replace(/^\//, ''),
241
- thumbnailURL: isPrivate ? getPrivateAdminThumbnailURL(updated, slug, payload.config.routes.api) : getAdminThumbnailURL(updated)
242
- }
243
- });
230
+ const data = {
231
+ filename: destination.name,
232
+ imagekit,
233
+ prefix: destinationFolder.replace(/^\//, ''),
234
+ thumbnailURL: isPrivate ? getPrivateAdminThumbnailURL(updated, slug, payload.config.routes.api) : getAdminThumbnailURL(updated)
235
+ };
236
+ if (payload.db.name === 'mongoose') {
237
+ // A sparse unique MongoDB index permits missing keys, but only one null.
238
+ // Use the adapter directly: Local API merges the old key back into the
239
+ // update, which conflicts with $unset. Remove it and save the reference
240
+ // in one database write, so failed updates leave the source intact.
241
+ await payload.db.updateOne({
242
+ id: doc.id,
243
+ collection: slug,
244
+ data: {
245
+ ...data,
246
+ $unset: {
247
+ _objectKey: 1
248
+ }
249
+ }
250
+ });
251
+ } else {
252
+ await payload.update({
253
+ id: doc.id,
254
+ collection: slug,
255
+ context: {
256
+ skipCloudStorage: true
257
+ },
258
+ data: {
259
+ ...data,
260
+ _objectKey: null
261
+ }
262
+ });
263
+ }
244
264
  result.migrated += 1;
245
265
  console.log(`[migrateFolder] Migrated ${slug}/${doc.id} to ${destinationPath}.`);
246
266
  } catch (error) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/migrate.ts"],"sourcesContent":["/* eslint-disable no-console -- Migration progress is intentionally reported to the invoking process. */\n\nimport type { Payload, UploadCollectionSlug } from 'payload'\n\nimport ImageKit from '@imagekit/nodejs'\nimport { createHash } from 'node:crypto'\nimport path from 'node:path'\n\nimport { getAdminThumbnailURL, getPrivateAdminThumbnailURL } from './getAdminThumbnailURL.js'\n\nexport type MigrationLocation = {\n /** Root folder, with collection subfolders beneath it. */\n folder: string\n privateKey: string\n urlEndpoint: string\n}\n\nexport type MigrateFolderOptions = {\n /** `true` preserves source privacy; an explicit `private` value sets destination privacy. */\n collections: Partial<Record<UploadCollectionSlug, { private?: boolean } | true>>\n /** Reads and reports the same plan without uploading or updating documents. Defaults to true. */\n dryRun?: boolean\n from: MigrationLocation\n /** The database containing the records to update, including any already at the destination. */\n payload: Payload\n signedUrlExpiresIn?: number\n to: MigrationLocation\n}\n\nexport type MigrationJobResult = {\n collectionSlug: string\n errors: { documentID: number | string; message: string }[]\n failed: number\n migrated: number\n planned: number\n /** Existing tagged transfers recovered after an interrupted run. Included in migrated when live. */\n reused: number\n skipped: number\n}\n\ntype Asset = {\n fileId: string\n filePath: string\n isPrivateFile?: boolean\n name: string\n tags?: null | string[]\n thumbnail?: string\n updatedAt?: string\n url: string\n versionInfo?: { id?: string }\n}\n\nconst normalizeLocation = (location: MigrationLocation, label: string): MigrationLocation => {\n if (!location?.privateKey?.trim()) {\n throw new Error(`migrateFolder: \\`${label}.privateKey\\` is required.`)\n }\n if (!location.urlEndpoint?.trim()) {\n throw new Error(`migrateFolder: \\`${label}.urlEndpoint\\` is required.`)\n }\n const endpoint = new URL(location.urlEndpoint)\n if (!['http:', 'https:'].includes(endpoint.protocol) || endpoint.search || endpoint.hash) {\n throw new Error(\n `migrateFolder: \\`${label}.urlEndpoint\\` must be an HTTP(S) URL without a query or fragment.`,\n )\n }\n const folder = location.folder?.trim().replace(/^\\/+|\\/+$/g, '')\n if (\n !folder ||\n folder.split('/').some((segment) => !segment || segment === '.' || segment === '..')\n ) {\n throw new Error(\n `migrateFolder: \\`${label}.folder\\` must be a non-empty folder without dot segments.`,\n )\n }\n return { ...location, folder: `/${folder}`, urlEndpoint: endpoint.href.replace(/\\/$/, '') }\n}\n\nconst isInFolder = (filePath: string, folder: string): boolean => filePath.startsWith(`${folder}/`)\n\nconst getAsset = async (client: ImageKit, fileId: string): Promise<Asset | undefined> => {\n try {\n const file = await client.files.get(fileId)\n if (!file.fileId || !file.filePath || !file.url) {\n throw new Error(`ImageKit returned incomplete file details for \"${fileId}\".`)\n }\n return {\n ...file,\n name: file.name || path.posix.basename(file.filePath),\n fileId: file.fileId,\n filePath: file.filePath,\n url: file.url,\n }\n } catch (error) {\n // Authentication errors, rate limits and outages are not evidence of a missing file.\n if (error instanceof ImageKit.NotFoundError) {\n return undefined\n }\n throw error\n }\n}\n\nconst findDestination = async (client: ImageKit, filePath: string): Promise<Asset | undefined> => {\n const limit = 100\n for (let skip = 0; ; skip += limit) {\n const assets = await client.assets.list({\n type: 'file',\n limit,\n path: `${path.posix.dirname(filePath)}/`,\n skip,\n })\n const match = assets.find((asset) => 'fileId' in asset && asset.filePath === filePath)\n if (match && 'fileId' in match && match.fileId) {\n return getAsset(client, match.fileId)\n }\n if (assets.length < limit) {\n return undefined\n }\n }\n}\n\nconst transferTag = (\n source: Asset,\n filePath: string,\n documentID: number | string,\n isPrivate: boolean,\n): string => {\n const identity = JSON.stringify([\n source.fileId,\n source.versionInfo?.id || source.updatedAt,\n source.url,\n filePath,\n documentID,\n isPrivate,\n ])\n return `payload-migration-${createHash('sha256').update(identity).digest('hex')}`\n}\n\n/**\n * Copy referenced originals between ImageKit folders/accounts and update Payload in place.\n * Transfers are tagged at upload time and never overwrite an existing destination file.\n * Reruns recover the upload/database-update gap without relying on filename equality.\n */\nexport const migrateFolder = async (\n options: MigrateFolderOptions,\n): Promise<MigrationJobResult[]> => {\n const { collections, dryRun = true, payload, signedUrlExpiresIn = 900 } = options\n const from = normalizeLocation(options.from, 'from')\n const to = normalizeLocation(options.to, 'to')\n if (!payload) {\n throw new Error('migrateFolder: `payload` is required.')\n }\n const slugs = Object.keys(collections || {})\n if (!slugs.length) {\n throw new Error('migrateFolder: `collections` must include at least one upload collection.')\n }\n for (const slug of slugs) {\n if (!payload.collections[slug]?.config.upload) {\n throw new Error(`migrateFolder: \"${slug}\" is not an upload collection.`)\n }\n }\n if (!Number.isFinite(signedUrlExpiresIn) || signedUrlExpiresIn <= 0) {\n throw new Error('migrateFolder: `signedUrlExpiresIn` must be positive.')\n }\n\n // A single transfer path for both cases gives uploads atomic provenance tags, including\n // when an upload succeeds remotely but its response is lost. Native copy cannot add a tag.\n const sourceClient = new ImageKit({ maxRetries: 0, privateKey: from.privateKey })\n const destinationClient = new ImageKit({ maxRetries: 0, privateKey: to.privateKey })\n const results: MigrationJobResult[] = []\n\n for (const slug of slugs) {\n const result: MigrationJobResult = {\n collectionSlug: slug,\n errors: [],\n failed: 0,\n migrated: 0,\n planned: 0,\n reused: 0,\n skipped: 0,\n }\n const sourceFolder = path.posix.join(from.folder, slug)\n const destinationFolder = path.posix.join(to.folder, slug)\n const collectionOptions = collections[slug]\n const plannedPaths = new Map<string, string>()\n let page = 1\n let hasNextPage: boolean\n\n do {\n const found = await payload.find({ collection: slug, depth: 0, limit: 100, page, sort: 'id' })\n hasNextPage = found.hasNextPage\n page += 1\n for (const doc of found.docs) {\n const reference = (doc as { imagekit?: { fileId?: string } }).imagekit\n if (!reference?.fileId) {\n result.skipped += 1\n console.log(`[migrateFolder] Skipping ${slug}/${doc.id}: no ImageKit file ID.`)\n continue\n }\n try {\n const atDestination = await getAsset(destinationClient, reference.fileId)\n if (atDestination && isInFolder(atDestination.filePath, destinationFolder)) {\n result.skipped += 1\n console.log(`[migrateFolder] Skipping ${slug}/${doc.id}: already at destination.`)\n continue\n }\n const source = await getAsset(sourceClient, reference.fileId)\n if (!source) {\n throw new Error(`File \"${reference.fileId}\" was not found in the source account.`)\n }\n if (!isInFolder(source.filePath, sourceFolder)) {\n result.skipped += 1\n console.log(`[migrateFolder] Skipping ${slug}/${doc.id}: outside ${sourceFolder}.`)\n continue\n }\n\n const isPrivate =\n collectionOptions !== true && typeof collectionOptions?.private === 'boolean'\n ? collectionOptions.private\n : source.isPrivateFile === true\n const destinationPath = path.posix.join(destinationFolder, source.name)\n const tag = transferTag(source, destinationPath, doc.id, isPrivate)\n const previousTransfer = plannedPaths.get(destinationPath)\n if (previousTransfer && previousTransfer !== tag) {\n throw new Error(\n `Destination conflict at \"${destinationPath}\": multiple source records target this path.`,\n )\n }\n plannedPaths.set(destinationPath, tag)\n let destination = await findDestination(destinationClient, destinationPath)\n if (\n destination &&\n (!destination.tags?.includes(tag) || (destination.isPrivateFile === true) !== isPrivate)\n ) {\n throw new Error(\n `Destination conflict at \"${destinationPath}\": existing asset is not this transfer.`,\n )\n }\n if (destination) {\n result.reused += 1\n }\n if (dryRun) {\n result.planned += 1\n console.log(\n `[migrateFolder] [dry-run] Would ${destination ? 'reuse' : 'upload'} ${slug}/${doc.id}: ${source.filePath} -> ${destinationPath}`,\n )\n continue\n }\n\n if (!destination) {\n const sourceURL = sourceClient.helper.buildSrc({\n ...(source.isPrivateFile ? { expiresIn: signedUrlExpiresIn, signed: true } : {}),\n src: source.filePath,\n transformation: [{ raw: 'orig-true' }],\n urlEndpoint: from.urlEndpoint,\n })\n const uploaded = await destinationClient.files.upload({\n file: sourceURL,\n fileName: source.name,\n folder: destinationFolder,\n isPrivateFile: isPrivate,\n overwriteFile: false,\n tags: [tag],\n useUniqueFileName: false,\n })\n if (!uploaded.fileId) {\n throw new Error(`Upload of \"${source.fileId}\" did not return a file ID.`)\n }\n destination = await getAsset(destinationClient, uploaded.fileId)\n if (\n !destination ||\n destination.filePath !== destinationPath ||\n !destination.tags?.includes(tag) ||\n (destination.isPrivateFile === true) !== isPrivate\n ) {\n throw new Error(\n `Upload of \"${source.fileId}\" returned unexpected destination details.`,\n )\n }\n }\n\n const imagekit = {\n fileId: destination.fileId,\n isPrivate,\n thumbnailUrl: destination.thumbnail || null,\n url: destinationClient.helper.buildSrc({\n src: destination.filePath,\n urlEndpoint: to.urlEndpoint,\n }),\n }\n const updated = { ...doc, filename: destination.name, imagekit }\n await payload.update({\n id: doc.id,\n collection: slug,\n context: { skipCloudStorage: true },\n data: {\n _objectKey: null,\n filename: destination.name,\n imagekit,\n prefix: destinationFolder.replace(/^\\//, ''),\n thumbnailURL: isPrivate\n ? getPrivateAdminThumbnailURL(updated, slug, payload.config.routes.api)\n : getAdminThumbnailURL(updated),\n },\n })\n result.migrated += 1\n console.log(`[migrateFolder] Migrated ${slug}/${doc.id} to ${destinationPath}.`)\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Unknown migration error'\n result.failed += 1\n result.errors.push({ documentID: doc.id, message })\n console.error(`[migrateFolder] Failed ${slug}/${doc.id}: ${message}`)\n }\n }\n } while (hasNextPage)\n\n results.push(result)\n console.log(\n `[migrateFolder] ${slug}: planned=${result.planned}, migrated=${result.migrated}, reused=${result.reused}, skipped=${result.skipped}, failed=${result.failed}.`,\n )\n }\n return results\n}\n"],"names":["ImageKit","createHash","path","getAdminThumbnailURL","getPrivateAdminThumbnailURL","normalizeLocation","location","label","privateKey","trim","Error","urlEndpoint","endpoint","URL","includes","protocol","search","hash","folder","replace","split","some","segment","href","isInFolder","filePath","startsWith","getAsset","client","fileId","file","files","get","url","name","posix","basename","error","NotFoundError","undefined","findDestination","limit","skip","assets","list","type","dirname","match","find","asset","length","transferTag","source","documentID","isPrivate","identity","JSON","stringify","versionInfo","id","updatedAt","update","digest","migrateFolder","options","collections","dryRun","payload","signedUrlExpiresIn","from","to","slugs","Object","keys","slug","config","upload","Number","isFinite","sourceClient","maxRetries","destinationClient","results","result","collectionSlug","errors","failed","migrated","planned","reused","skipped","sourceFolder","join","destinationFolder","collectionOptions","plannedPaths","Map","page","hasNextPage","found","collection","depth","sort","doc","docs","reference","imagekit","console","log","atDestination","private","isPrivateFile","destinationPath","tag","previousTransfer","set","destination","tags","sourceURL","helper","buildSrc","expiresIn","signed","src","transformation","raw","uploaded","fileName","overwriteFile","useUniqueFileName","thumbnailUrl","thumbnail","updated","filename","context","skipCloudStorage","data","_objectKey","prefix","thumbnailURL","routes","api","message","push"],"mappings":"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"}
1
+ {"version":3,"sources":["../src/migrate.ts"],"sourcesContent":["/* eslint-disable no-console -- Migration progress is intentionally reported to the invoking process. */\n\nimport type { Payload, UploadCollectionSlug } from 'payload'\n\nimport ImageKit from '@imagekit/nodejs'\nimport { createHash } from 'node:crypto'\nimport path from 'node:path'\n\nimport { getAdminThumbnailURL, getPrivateAdminThumbnailURL } from './getAdminThumbnailURL.js'\n\nexport type MigrationLocation = {\n /** Root folder, with collection subfolders beneath it. */\n folder: string\n privateKey: string\n urlEndpoint: string\n}\n\nexport type MigrateFolderOptions = {\n /** `true` preserves source privacy; an explicit `private` value sets destination privacy. */\n collections: Partial<Record<UploadCollectionSlug, { private?: boolean } | true>>\n /** Reads and reports the same plan without uploading or updating documents. Defaults to true. */\n dryRun?: boolean\n from: MigrationLocation\n /** The database containing the records to update, including any already at the destination. */\n payload: Payload\n signedUrlExpiresIn?: number\n to: MigrationLocation\n}\n\nexport type MigrationJobResult = {\n collectionSlug: string\n errors: { documentID: number | string; message: string }[]\n failed: number\n migrated: number\n planned: number\n /** Existing tagged transfers recovered after an interrupted run. Included in migrated when live. */\n reused: number\n skipped: number\n}\n\ntype Asset = {\n fileId: string\n filePath: string\n isPrivateFile?: boolean\n name: string\n tags?: null | string[]\n thumbnail?: string\n updatedAt?: string\n url: string\n versionInfo?: { id?: string }\n}\n\nconst normalizeLocation = (location: MigrationLocation, label: string): MigrationLocation => {\n if (!location?.privateKey?.trim()) {\n throw new Error(`migrateFolder: \\`${label}.privateKey\\` is required.`)\n }\n if (!location.urlEndpoint?.trim()) {\n throw new Error(`migrateFolder: \\`${label}.urlEndpoint\\` is required.`)\n }\n const endpoint = new URL(location.urlEndpoint)\n if (!['http:', 'https:'].includes(endpoint.protocol) || endpoint.search || endpoint.hash) {\n throw new Error(\n `migrateFolder: \\`${label}.urlEndpoint\\` must be an HTTP(S) URL without a query or fragment.`,\n )\n }\n const folder = location.folder?.trim().replace(/^\\/+|\\/+$/g, '')\n if (\n !folder ||\n folder.split('/').some((segment) => !segment || segment === '.' || segment === '..')\n ) {\n throw new Error(\n `migrateFolder: \\`${label}.folder\\` must be a non-empty folder without dot segments.`,\n )\n }\n return { ...location, folder: `/${folder}`, urlEndpoint: endpoint.href.replace(/\\/$/, '') }\n}\n\nconst isInFolder = (filePath: string, folder: string): boolean => filePath.startsWith(`${folder}/`)\n\nconst getAsset = async (client: ImageKit, fileId: string): Promise<Asset | undefined> => {\n try {\n const file = await client.files.get(fileId)\n if (!file.fileId || !file.filePath || !file.url) {\n throw new Error(`ImageKit returned incomplete file details for \"${fileId}\".`)\n }\n return {\n ...file,\n name: file.name || path.posix.basename(file.filePath),\n fileId: file.fileId,\n filePath: file.filePath,\n url: file.url,\n }\n } catch (error) {\n // Authentication errors, rate limits and outages are not evidence of a missing file.\n if (error instanceof ImageKit.NotFoundError) {\n return undefined\n }\n throw error\n }\n}\n\nconst findDestination = async (client: ImageKit, filePath: string): Promise<Asset | undefined> => {\n const limit = 100\n for (let skip = 0; ; skip += limit) {\n const assets = await client.assets.list({\n type: 'file',\n limit,\n path: `${path.posix.dirname(filePath)}/`,\n skip,\n })\n const match = assets.find((asset) => 'fileId' in asset && asset.filePath === filePath)\n if (match && 'fileId' in match && match.fileId) {\n return getAsset(client, match.fileId)\n }\n if (assets.length < limit) {\n return undefined\n }\n }\n}\n\nconst transferTag = (\n source: Asset,\n filePath: string,\n documentID: number | string,\n isPrivate: boolean,\n): string => {\n const identity = JSON.stringify([\n source.fileId,\n source.versionInfo?.id || source.updatedAt,\n source.url,\n filePath,\n documentID,\n isPrivate,\n ])\n return `payload-migration-${createHash('sha256').update(identity).digest('hex')}`\n}\n\n/**\n * Copy referenced originals between ImageKit folders/accounts and update Payload in place.\n * Transfers are tagged at upload time and never overwrite an existing destination file.\n * Reruns recover the upload/database-update gap without relying on filename equality.\n */\nexport const migrateFolder = async (\n options: MigrateFolderOptions,\n): Promise<MigrationJobResult[]> => {\n const { collections, dryRun = true, payload, signedUrlExpiresIn = 900 } = options\n const from = normalizeLocation(options.from, 'from')\n const to = normalizeLocation(options.to, 'to')\n if (!payload) {\n throw new Error('migrateFolder: `payload` is required.')\n }\n const slugs = Object.keys(collections || {})\n if (!slugs.length) {\n throw new Error('migrateFolder: `collections` must include at least one upload collection.')\n }\n for (const slug of slugs) {\n if (!payload.collections[slug]?.config.upload) {\n throw new Error(`migrateFolder: \"${slug}\" is not an upload collection.`)\n }\n }\n if (!Number.isFinite(signedUrlExpiresIn) || signedUrlExpiresIn <= 0) {\n throw new Error('migrateFolder: `signedUrlExpiresIn` must be positive.')\n }\n\n // A single transfer path for both cases gives uploads atomic provenance tags, including\n // when an upload succeeds remotely but its response is lost. Native copy cannot add a tag.\n const sourceClient = new ImageKit({ maxRetries: 0, privateKey: from.privateKey })\n const destinationClient = new ImageKit({ maxRetries: 0, privateKey: to.privateKey })\n const results: MigrationJobResult[] = []\n\n for (const slug of slugs) {\n const result: MigrationJobResult = {\n collectionSlug: slug,\n errors: [],\n failed: 0,\n migrated: 0,\n planned: 0,\n reused: 0,\n skipped: 0,\n }\n const sourceFolder = path.posix.join(from.folder, slug)\n const destinationFolder = path.posix.join(to.folder, slug)\n const collectionOptions = collections[slug]\n const plannedPaths = new Map<string, string>()\n let page = 1\n let hasNextPage: boolean\n\n do {\n const found = await payload.find({ collection: slug, depth: 0, limit: 100, page, sort: 'id' })\n hasNextPage = found.hasNextPage\n page += 1\n for (const doc of found.docs) {\n const reference = (doc as { imagekit?: { fileId?: string } }).imagekit\n if (!reference?.fileId) {\n result.skipped += 1\n console.log(`[migrateFolder] Skipping ${slug}/${doc.id}: no ImageKit file ID.`)\n continue\n }\n try {\n const atDestination = await getAsset(destinationClient, reference.fileId)\n if (atDestination && isInFolder(atDestination.filePath, destinationFolder)) {\n result.skipped += 1\n console.log(`[migrateFolder] Skipping ${slug}/${doc.id}: already at destination.`)\n continue\n }\n const source = await getAsset(sourceClient, reference.fileId)\n if (!source) {\n throw new Error(`File \"${reference.fileId}\" was not found in the source account.`)\n }\n if (!isInFolder(source.filePath, sourceFolder)) {\n result.skipped += 1\n console.log(`[migrateFolder] Skipping ${slug}/${doc.id}: outside ${sourceFolder}.`)\n continue\n }\n\n const isPrivate =\n collectionOptions !== true && typeof collectionOptions?.private === 'boolean'\n ? collectionOptions.private\n : source.isPrivateFile === true\n const destinationPath = path.posix.join(destinationFolder, source.name)\n const tag = transferTag(source, destinationPath, doc.id, isPrivate)\n const previousTransfer = plannedPaths.get(destinationPath)\n if (previousTransfer && previousTransfer !== tag) {\n throw new Error(\n `Destination conflict at \"${destinationPath}\": multiple source records target this path.`,\n )\n }\n plannedPaths.set(destinationPath, tag)\n let destination = await findDestination(destinationClient, destinationPath)\n if (\n destination &&\n (!destination.tags?.includes(tag) || (destination.isPrivateFile === true) !== isPrivate)\n ) {\n throw new Error(\n `Destination conflict at \"${destinationPath}\": existing asset is not this transfer.`,\n )\n }\n if (destination) {\n result.reused += 1\n }\n if (dryRun) {\n result.planned += 1\n console.log(\n `[migrateFolder] [dry-run] Would ${destination ? 'reuse' : 'upload'} ${slug}/${doc.id}: ${source.filePath} -> ${destinationPath}`,\n )\n continue\n }\n\n if (!destination) {\n const sourceURL = sourceClient.helper.buildSrc({\n ...(source.isPrivateFile ? { expiresIn: signedUrlExpiresIn, signed: true } : {}),\n src: source.filePath,\n transformation: [{ raw: 'orig-true' }],\n urlEndpoint: from.urlEndpoint,\n })\n const uploaded = await destinationClient.files.upload({\n file: sourceURL,\n fileName: source.name,\n folder: destinationFolder,\n isPrivateFile: isPrivate,\n overwriteFile: false,\n tags: [tag],\n useUniqueFileName: false,\n })\n if (!uploaded.fileId) {\n throw new Error(`Upload of \"${source.fileId}\" did not return a file ID.`)\n }\n destination = await getAsset(destinationClient, uploaded.fileId)\n if (\n !destination ||\n destination.filePath !== destinationPath ||\n !destination.tags?.includes(tag) ||\n (destination.isPrivateFile === true) !== isPrivate\n ) {\n throw new Error(\n `Upload of \"${source.fileId}\" returned unexpected destination details.`,\n )\n }\n }\n\n const imagekit = {\n fileId: destination.fileId,\n isPrivate,\n thumbnailUrl: destination.thumbnail || null,\n url: destinationClient.helper.buildSrc({\n src: destination.filePath,\n urlEndpoint: to.urlEndpoint,\n }),\n }\n const updated = { ...doc, filename: destination.name, imagekit }\n const data = {\n filename: destination.name,\n imagekit,\n prefix: destinationFolder.replace(/^\\//, ''),\n thumbnailURL: isPrivate\n ? getPrivateAdminThumbnailURL(updated, slug, payload.config.routes.api)\n : getAdminThumbnailURL(updated),\n }\n if (payload.db.name === 'mongoose') {\n // A sparse unique MongoDB index permits missing keys, but only one null.\n // Use the adapter directly: Local API merges the old key back into the\n // update, which conflicts with $unset. Remove it and save the reference\n // in one database write, so failed updates leave the source intact.\n await payload.db.updateOne({\n id: doc.id,\n collection: slug,\n data: { ...data, $unset: { _objectKey: 1 } },\n })\n } else {\n await payload.update({\n id: doc.id,\n collection: slug,\n context: { skipCloudStorage: true },\n data: { ...data, _objectKey: null },\n })\n }\n result.migrated += 1\n console.log(`[migrateFolder] Migrated ${slug}/${doc.id} to ${destinationPath}.`)\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Unknown migration error'\n result.failed += 1\n result.errors.push({ documentID: doc.id, message })\n console.error(`[migrateFolder] Failed ${slug}/${doc.id}: ${message}`)\n }\n }\n } while (hasNextPage)\n\n results.push(result)\n console.log(\n `[migrateFolder] ${slug}: planned=${result.planned}, migrated=${result.migrated}, reused=${result.reused}, skipped=${result.skipped}, failed=${result.failed}.`,\n )\n }\n return results\n}\n"],"names":["ImageKit","createHash","path","getAdminThumbnailURL","getPrivateAdminThumbnailURL","normalizeLocation","location","label","privateKey","trim","Error","urlEndpoint","endpoint","URL","includes","protocol","search","hash","folder","replace","split","some","segment","href","isInFolder","filePath","startsWith","getAsset","client","fileId","file","files","get","url","name","posix","basename","error","NotFoundError","undefined","findDestination","limit","skip","assets","list","type","dirname","match","find","asset","length","transferTag","source","documentID","isPrivate","identity","JSON","stringify","versionInfo","id","updatedAt","update","digest","migrateFolder","options","collections","dryRun","payload","signedUrlExpiresIn","from","to","slugs","Object","keys","slug","config","upload","Number","isFinite","sourceClient","maxRetries","destinationClient","results","result","collectionSlug","errors","failed","migrated","planned","reused","skipped","sourceFolder","join","destinationFolder","collectionOptions","plannedPaths","Map","page","hasNextPage","found","collection","depth","sort","doc","docs","reference","imagekit","console","log","atDestination","private","isPrivateFile","destinationPath","tag","previousTransfer","set","destination","tags","sourceURL","helper","buildSrc","expiresIn","signed","src","transformation","raw","uploaded","fileName","overwriteFile","useUniqueFileName","thumbnailUrl","thumbnail","updated","filename","data","prefix","thumbnailURL","routes","api","db","updateOne","$unset","_objectKey","context","skipCloudStorage","message","push"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@humaan/payload-storage-imagekit",
3
- "version": "2.9.0",
3
+ "version": "2.9.1",
4
4
  "description": "ImageKit storage adapter plugin for Payload CMS uploads",
5
5
  "license": "MIT",
6
6
  "type": "module",