@humaan/payload-storage-imagekit 2.4.0 → 2.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -110,8 +110,9 @@ Behavior:
110
110
  - Creates destination folders automatically if they do not exist
111
111
  - Optional database update via Payload local API
112
112
  - Dry-run is enabled by default (`dryRun: true`)
113
- - Copies from the configured source folder path first, with stored `imagekit.url` as a fallback only when the source file cannot be found
114
- - Handles [private files](#private-files): mark a collection `{ private: true }` and migrated documents are stored with `imagekit.isPrivate: true` and a signed-URL admin thumbnail. The fast server-side copy preserves the source file's ImageKit privacy; when the copy falls back to re-uploading from the source URL, the source URL is signed (so a private source can be read) and the file is re-uploaded with `isPrivateFile: true`. Because ImageKit privacy is fixed at upload, migrating assumes the destination collection's privacy matches the source — copying a public file into a `{ private: true }` collection keeps the file public on ImageKit.
113
+ - Resolves each source asset by the stored `imagekit.fileId`, then copies the ImageKit-returned file path into the destination folder. This avoids mismatches between Payload's `filename` field and ImageKit's normalized file names.
114
+ - Reruns are idempotent, including dry-runs: if a document's stored `imagekit.fileId` already resolves to a file in the destination collection folder, that document is skipped.
115
+ - Handles [private files](#private-files): mark a collection `{ private: true }` and migrated documents are stored with `imagekit.isPrivate: true`. The fast server-side copy preserves the source file's ImageKit privacy; when the copy falls back to re-uploading from the source URL, the source URL is signed (so a private source can be read) and the file is re-uploaded with `isPrivateFile: true`. Because ImageKit privacy is fixed at upload, migrating assumes the destination collection's privacy matches the source — copying a public file into a `{ private: true }` collection keeps the file public on ImageKit.
115
116
 
116
117
  Example:
117
118
 
package/dist/migrate.d.ts CHANGED
@@ -21,8 +21,8 @@ export type MigrateFolderOptions = {
21
21
  */
22
22
  from: string;
23
23
  /**
24
- * Optional Payload instance. When provided, the stored `imagekit.*` and `url` fields
25
- * in the database will be updated to reflect the new file locations after copying.
24
+ * Optional Payload instance. When provided, the stored `imagekit.*` fields in the
25
+ * database will be updated to reflect the new ImageKit asset after copying.
26
26
  */
27
27
  payload?: Payload;
28
28
  /**
@@ -40,8 +40,8 @@ export type MigrateFolderOptions = {
40
40
  */
41
41
  to: string;
42
42
  /**
43
- * ImageKit URL endpoint (e.g. `https://ik.imagekit.io/your_id`). Required to
44
- * reconstruct canonical `url` values when updating the database.
43
+ * ImageKit URL endpoint (e.g. `https://ik.imagekit.io/your_id`). Required to sign
44
+ * private source URLs when the migrator falls back to re-uploading from the source URL.
45
45
  */
46
46
  urlEndpoint: string;
47
47
  };
package/dist/migrate.js CHANGED
@@ -1,6 +1,5 @@
1
1
  import ImageKit from '@imagekit/nodejs';
2
2
  import path from 'node:path';
3
- import { getAdminThumbnailURL, getPrivateAdminThumbnailURL } from './getAdminThumbnailURL.js';
4
3
  const DEFAULT_SIGNED_URL_EXPIRES_IN = 900;
5
4
  const isPrivateCollectionConfig = (value)=>value !== true && typeof value === 'object' && value?.private === true;
6
5
  const normalizeFolder = (folder)=>{
@@ -11,7 +10,7 @@ const normalizeFolder = (folder)=>{
11
10
  return `/${normalized}`;
12
11
  };
13
12
  const getCollectionFolder = (rootFolder, collectionSlug)=>path.posix.join(rootFolder, collectionSlug);
14
- const getFilePath = (rootFolder, collectionSlug, filename)=>path.posix.join(getCollectionFolder(rootFolder, collectionSlug), filename);
13
+ const isFileInFolder = (filePath, folderPath)=>filePath === folderPath || filePath.startsWith(`${folderPath}/`);
15
14
  const ensureFolderExists = async (client, folderPath)=>{
16
15
  const normalized = normalizeFolder(folderPath);
17
16
  const segments = normalized.split('/').filter(Boolean);
@@ -84,6 +83,18 @@ const uploadFileFromURL = async ({ client, fileName, folder, isPrivate, sourceUr
84
83
  url: uploaded.url
85
84
  };
86
85
  };
86
+ const getSourceImagekitFields = async ({ client, fileId })=>{
87
+ const file = await client.files.get(fileId);
88
+ if (!file.fileId || !file.filePath || !file.url) {
89
+ throw new Error(`migrateFolder: missing ImageKit source file details for "${fileId}".`);
90
+ }
91
+ return {
92
+ fileId: file.fileId,
93
+ fileName: file.name || path.posix.basename(file.filePath),
94
+ filePath: file.filePath,
95
+ url: file.url
96
+ };
97
+ };
87
98
  const getUploadedImagekitFields = async ({ client, fileId })=>{
88
99
  const file = await client.files.get(fileId);
89
100
  if (!file.fileId || !file.url) {
@@ -122,7 +133,6 @@ export const migrateFolder = async (options)=>{
122
133
  }
123
134
  const privateSlugs = new Set(Object.entries(collections).filter(([, value])=>isPrivateCollectionConfig(value)).map(([slug])=>slug));
124
135
  const signedUrlExpiresIn = typeof signedUrlExpiresInOption === 'number' && signedUrlExpiresInOption > 0 ? signedUrlExpiresInOption : DEFAULT_SIGNED_URL_EXPIRES_IN;
125
- const apiRoute = payload?.config.routes?.api ?? '/api';
126
136
  const fromFolder = normalizeFolder(from);
127
137
  const toFolder = normalizeFolder(to);
128
138
  if (fromFolder === toFolder) {
@@ -170,26 +180,35 @@ export const migrateFolder = async (options)=>{
170
180
  const doc = found.docs[i];
171
181
  const filename = doc.filename;
172
182
  const existingImagekit = doc.imagekit;
183
+ const displayName = filename || existingImagekit?.fileId || doc.id;
173
184
  console.log(`[migrateFolder] [${i + 1}/${found.docs.length}] Processing document ${doc.id}`);
174
- // Skip items that don't have ImageKit data or filename
175
- if (!filename || !existingImagekit?.fileId || !existingImagekit?.url) {
185
+ // Skip items that don't have an ImageKit file ID to migrate from.
186
+ if (!existingImagekit?.fileId) {
176
187
  skippedCount += 1;
177
- console.log(`[migrateFolder] Skipping document ${doc.id} - missing filename or ImageKit data`);
188
+ console.log(`[migrateFolder] Skipping document ${doc.id} - missing ImageKit file ID`);
178
189
  continue;
179
190
  }
180
- if (dryRun) {
181
- console.log(`[migrateFolder] [dry-run] Would upload: ${toFolder}/${slug}/${filename}`);
182
- console.log(`[migrateFolder] [dry-run] Would update Payload document: ${doc.id}`);
183
- } else {
184
- try {
185
- const sourceFilePath = getFilePath(fromFolder, slug, filename);
186
- const destinationFolder = getCollectionFolder(toFolder, slug);
187
- const destinationFilePath = getFilePath(toFolder, slug, filename);
191
+ try {
192
+ const destinationFolder = getCollectionFolder(toFolder, slug);
193
+ const source = await getSourceImagekitFields({
194
+ client,
195
+ fileId: existingImagekit.fileId
196
+ });
197
+ if (isFileInFolder(source.filePath, destinationFolder)) {
198
+ skippedCount += 1;
199
+ console.log(`[migrateFolder] Skipping document ${doc.id} - ImageKit file ID ${source.fileId} is already in ${destinationFolder}`);
200
+ continue;
201
+ }
202
+ if (dryRun) {
203
+ console.log(`[migrateFolder] [dry-run] Would copy ImageKit file ID ${source.fileId} from ${source.filePath} to ${destinationFolder}`);
204
+ console.log(`[migrateFolder] [dry-run] Would update Payload document: ${doc.id}`);
205
+ } else {
206
+ const destinationFilePath = path.posix.join(destinationFolder, source.fileName);
188
207
  let uploaded;
189
208
  try {
190
209
  const copyResponse = await client.files.copy({
191
210
  destinationPath: destinationFolder,
192
- sourceFilePath
211
+ sourceFilePath: source.filePath
193
212
  }).asResponse();
194
213
  let copiedFileId = await readFileIdFromCopyResponse(copyResponse);
195
214
  if (!copiedFileId) {
@@ -199,7 +218,7 @@ export const migrateFolder = async (options)=>{
199
218
  });
200
219
  }
201
220
  if (!copiedFileId) {
202
- throw new Error(`migrateFolder: copy request completed for "${sourceFilePath}", but the destination asset at "${destinationFilePath}" was not discoverable via ImageKit after retrying.`);
221
+ throw new Error(`migrateFolder: copy request completed for ImageKit file ID "${source.fileId}" from "${source.filePath}", but the destination asset at "${destinationFilePath}" was not discoverable via ImageKit after retrying.`);
203
222
  }
204
223
  uploaded = await getUploadedImagekitFields({
205
224
  client,
@@ -209,37 +228,23 @@ export const migrateFolder = async (options)=>{
209
228
  if (!isImageKitFileNotFoundError(error)) {
210
229
  throw error;
211
230
  }
212
- console.warn(`[migrateFolder] Source file not found at ${sourceFilePath}. Falling back to stored ImageKit URL for "${filename}".`);
231
+ console.warn(`[migrateFolder] Source file not found for ImageKit file ID ${source.fileId}. Falling back to resolved ImageKit URL for "${source.fileName}".`);
213
232
  // A private source file 401s on its plain URL, so sign it before ImageKit
214
233
  // fetches it, and re-upload as private so the copy keeps its privacy.
215
234
  const sourceUrl = isCollectionPrivate ? client.helper.buildSrc({
216
235
  expiresIn: signedUrlExpiresIn,
217
236
  signed: true,
218
- src: existingImagekit.url,
237
+ src: source.url,
219
238
  urlEndpoint
220
- }) : existingImagekit.url;
239
+ }) : source.url;
221
240
  uploaded = await uploadFileFromURL({
222
241
  client,
223
- fileName: filename,
242
+ fileName: source.fileName,
224
243
  folder: destinationFolder,
225
244
  isPrivate: isCollectionPrivate,
226
245
  sourceUrl
227
246
  });
228
247
  }
229
- const canonicalUrl = client.helper.buildSrc({
230
- src: destinationFilePath,
231
- urlEndpoint
232
- });
233
- const mimeType = doc.mimeType;
234
- const adminThumbnailURL = isCollectionPrivate ? getPrivateAdminThumbnailURL({
235
- filename,
236
- mimeType
237
- }, slug, apiRoute) : getAdminThumbnailURL({
238
- imagekit: {
239
- url: uploaded.url
240
- },
241
- mimeType
242
- });
243
248
  // Update the document with new ImageKit data
244
249
  await payload.update({
245
250
  id: doc.id,
@@ -250,17 +255,15 @@ export const migrateFolder = async (options)=>{
250
255
  isPrivate: isCollectionPrivate,
251
256
  thumbnailUrl: uploaded.thumbnailUrl,
252
257
  url: uploaded.url
253
- },
254
- thumbnailURL: adminThumbnailURL || canonicalUrl,
255
- url: canonicalUrl
258
+ }
256
259
  }
257
260
  });
258
261
  updatedCount += 1;
259
- console.log(`[migrateFolder] Content migrated! ${filename} (${doc.id})`);
260
- } catch (error) {
261
- errorCount += 1;
262
- console.error(`[migrateFolder] Failed to migrate document "${doc.id}" for file "${filename}":`, error);
262
+ console.log(`[migrateFolder] Content migrated! ${displayName} (${doc.id})`);
263
263
  }
264
+ } catch (error) {
265
+ errorCount += 1;
266
+ console.error(`[migrateFolder] Failed to migrate document "${doc.id}" for file "${displayName}":`, error);
264
267
  }
265
268
  }
266
269
  results.push({
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/migrate.ts"],"sourcesContent":["import type { Payload, UploadCollectionSlug } from 'payload'\n\nimport ImageKit from '@imagekit/nodejs'\nimport path from 'node:path'\n\nimport { getAdminThumbnailURL, getPrivateAdminThumbnailURL } from './getAdminThumbnailURL.js'\n\ntype ImageKitCollectionConfig = { private?: boolean } | true\ntype ImageKitCollectionMap = Partial<Record<UploadCollectionSlug, ImageKitCollectionConfig>>\n\nconst DEFAULT_SIGNED_URL_EXPIRES_IN = 900\n\nconst isPrivateCollectionConfig = (value: ImageKitCollectionConfig | undefined): boolean =>\n value !== true && typeof value === 'object' && value?.private === true\n\nexport type MigrateFolderOptions = {\n /**\n * The Payload upload collections to migrate. Keys are collection slugs; the value is\n * `true`, or `{ private: true }` to mark migrated files as ImageKit private files.\n */\n collections: ImageKitCollectionMap\n /**\n * Dry-run mode. When `true`, migration logs what would happen without writing\n * to ImageKit or Payload. Defaults to `true`.\n * @default true\n */\n dryRun?: boolean\n /**\n * The source ImageKit root folder (e.g. `/staging`). Each collection subfolder\n * (`/staging/media`) will be copied into `to`.\n */\n from: string\n /**\n * Optional Payload instance. When provided, the stored `imagekit.*` and `url` fields\n * in the database will be updated to reflect the new file locations after copying.\n */\n payload?: Payload\n /**\n * ImageKit private API key.\n */\n privateKey: string\n /**\n * Expiry (in seconds) for the signed URL used to read a private source file when the\n * fast server-side copy is not possible and the migrator falls back to re-uploading\n * from the source URL. Defaults to 900 (15 minutes).\n */\n signedUrlExpiresIn?: number\n /**\n * The destination ImageKit root folder (e.g. `/production`).\n */\n to: string\n /**\n * ImageKit URL endpoint (e.g. `https://ik.imagekit.io/your_id`). Required to\n * reconstruct canonical `url` values when updating the database.\n */\n urlEndpoint: string\n}\n\nexport type MigrationJobResult = {\n collectionSlug: string\n jobId: string\n status: 'Completed' | 'Pending'\n}\n\nconst normalizeFolder = (folder: string): string => {\n const normalized = folder.trim().replace(/^\\/+|\\/+$/g, '')\n\n if (!normalized) {\n throw new Error('migrateFolder: folder path cannot be empty.')\n }\n\n return `/${normalized}`\n}\n\nconst getCollectionFolder = (rootFolder: string, collectionSlug: string): string =>\n path.posix.join(rootFolder, collectionSlug)\n\nconst getFilePath = (rootFolder: string, collectionSlug: string, filename: string): string =>\n path.posix.join(getCollectionFolder(rootFolder, collectionSlug), filename)\n\nconst ensureFolderExists = async (client: ImageKit, folderPath: string): Promise<void> => {\n const normalized = normalizeFolder(folderPath)\n const segments = normalized.split('/').filter(Boolean)\n\n let parentFolderPath = '/'\n\n for (const folderName of segments) {\n try {\n await client.folders.create({\n folderName,\n parentFolderPath,\n })\n } catch (error) {\n const message =\n error && typeof error === 'object' && 'message' in error ? String(error.message) : ''\n\n if (!/already exists/i.test(message)) {\n throw error\n }\n }\n\n parentFolderPath = path.posix.join(parentFolderPath, folderName)\n }\n}\n\nconst findImageKitFileId = async (\n imagekit: ImageKit,\n filePath: string,\n options?: {\n retries?: number\n retryDelayMs?: number\n },\n): Promise<string | undefined> => {\n const parentPath = path.posix.dirname(filePath)\n const name = path.posix.basename(filePath)\n\n const retries = options?.retries ?? 0\n const retryDelayMs = options?.retryDelayMs ?? 250\n const limit = 100\n\n for (let attempt = 0; attempt <= retries; attempt++) {\n for (let skip = 0; ; skip += limit) {\n const assets = await imagekit.assets.list({\n type: 'file',\n limit,\n path: parentPath === '/' ? '/' : `${parentPath}/`,\n skip,\n })\n\n const found = assets.find(\n (asset) => 'fileId' in asset && asset.filePath === filePath && asset.name === name,\n )\n\n if (found && 'fileId' in found) {\n return found.fileId\n }\n\n if (assets.length < limit) {\n break\n }\n }\n\n if (attempt < retries) {\n await new Promise((resolve) => {\n setTimeout(resolve, retryDelayMs)\n })\n }\n }\n\n return undefined\n}\n\nconst isImageKitFileNotFoundError = (error: unknown): boolean => {\n const message =\n error && typeof error === 'object' && 'message' in error ? String(error.message) : ''\n\n return /does not exist|not found|no such file/i.test(message)\n}\n\nconst uploadFileFromURL = async ({\n client,\n fileName,\n folder,\n isPrivate,\n sourceUrl,\n}: {\n client: ImageKit\n fileName: string\n folder: string\n isPrivate?: boolean\n sourceUrl: string\n}) => {\n const uploaded = await client.files.upload({\n file: sourceUrl,\n fileName,\n folder,\n useUniqueFileName: false,\n ...(isPrivate ? { isPrivateFile: true } : {}),\n })\n\n if (!uploaded.fileId || !uploaded.url) {\n throw new Error(`migrateFolder: upload from URL did not return file details for \"${fileName}\".`)\n }\n\n return {\n fileId: uploaded.fileId,\n thumbnailUrl: uploaded.thumbnailUrl,\n url: uploaded.url,\n }\n}\n\nconst getUploadedImagekitFields = async ({\n client,\n fileId,\n}: {\n client: ImageKit\n fileId: string\n}): Promise<{ fileId: string; thumbnailUrl?: string; url: string }> => {\n const file = await client.files.get(fileId)\n\n if (!file.fileId || !file.url) {\n throw new Error(`migrateFolder: missing ImageKit file details for \"${fileId}\".`)\n }\n\n return {\n fileId: file.fileId,\n thumbnailUrl: file.thumbnail,\n url: file.url,\n }\n}\n\nconst readFileIdFromCopyResponse = async (response: Response): Promise<string | undefined> => {\n try {\n const result = (await response.json()) as { file_id?: unknown; fileId?: unknown }\n\n if (typeof result.fileId === 'string' && result.fileId.length > 0) {\n return result.fileId\n }\n\n if (typeof result.file_id === 'string' && result.file_id.length > 0) {\n return result.file_id\n }\n } catch {\n // Ignore empty or non-JSON responses and fall back to asset discovery.\n }\n\n return undefined\n}\n\nexport const migrateFolder = async (\n options: MigrateFolderOptions,\n): Promise<MigrationJobResult[]> => {\n const {\n collections,\n dryRun = true,\n from,\n payload,\n privateKey,\n signedUrlExpiresIn: signedUrlExpiresInOption,\n to,\n urlEndpoint,\n } = options\n\n if (!privateKey?.trim()) {\n throw new Error('migrateFolder: `privateKey` is required.')\n }\n\n if (!urlEndpoint?.trim()) {\n throw new Error('migrateFolder: `urlEndpoint` is required.')\n }\n\n if (!collections || Object.keys(collections).length === 0) {\n throw new Error('migrateFolder: `collections` must include at least one upload collection.')\n }\n\n const privateSlugs = new Set(\n Object.entries(collections)\n .filter(([, value]) => isPrivateCollectionConfig(value))\n .map(([slug]) => slug),\n )\n const signedUrlExpiresIn =\n typeof signedUrlExpiresInOption === 'number' && signedUrlExpiresInOption > 0\n ? signedUrlExpiresInOption\n : DEFAULT_SIGNED_URL_EXPIRES_IN\n const apiRoute = payload?.config.routes?.api ?? '/api'\n\n const fromFolder = normalizeFolder(from)\n const toFolder = normalizeFolder(to)\n\n if (fromFolder === toFolder) {\n throw new Error('migrateFolder: `from` and `to` cannot be the same folder.')\n }\n\n const client = new ImageKit({ privateKey })\n\n console.log(\n `[migrateFolder] Starting ${dryRun ? 'DRY-RUN' : 'LIVE'} migration from ${fromFolder} to ${toFolder} for ${Object.keys(collections).length} collection(s).`,\n )\n\n if (dryRun) {\n console.log(\n `[migrateFolder] [dry-run] Would ensure destination root folder exists: ${toFolder}`,\n )\n } else {\n console.log(`[migrateFolder] Ensuring destination root folder exists: ${toFolder}`)\n await ensureFolderExists(client, toFolder)\n }\n\n // Always copy file-by-file per collection\n const collectionSlugs = Object.keys(collections)\n const results: MigrationJobResult[] = []\n\n // Ensure destination folder structure exists\n if (!dryRun) {\n for (const slug of collectionSlugs) {\n const destinationFolderPath = path.posix.join(toFolder, slug)\n console.log(`[migrateFolder] Ensuring destination folder: ${destinationFolderPath}`)\n await ensureFolderExists(client, destinationFolderPath)\n }\n }\n\n // Process documents directly like the old migration script\n if (payload) {\n console.log('[migrateFolder] Starting document-by-document migration.')\n\n for (const slug of collectionSlugs) {\n const isCollectionPrivate = privateSlugs.has(slug)\n\n console.log(\n `[migrateFolder] Migrating collection \"${slug}\"${isCollectionPrivate ? ' (private)' : ''}...`,\n )\n\n const found = await payload.find({\n collection: slug,\n depth: 0,\n limit: 0,\n pagination: false,\n })\n\n console.log(\n `[migrateFolder] Processing ${found.docs.length} document(s) in collection \"${slug}\".`,\n )\n\n let updatedCount = 0\n let skippedCount = 0\n let errorCount = 0\n\n // Process each document one by one, like the old migration script\n for (let i = 0; i < found.docs.length; i++) {\n const doc = found.docs[i]\n const filename = (doc as { filename?: string }).filename\n const existingImagekit = (doc as any).imagekit\n\n console.log(`[migrateFolder] [${i + 1}/${found.docs.length}] Processing document ${doc.id}`)\n\n // Skip items that don't have ImageKit data or filename\n if (!filename || !existingImagekit?.fileId || !existingImagekit?.url) {\n skippedCount += 1\n console.log(\n `[migrateFolder] Skipping document ${doc.id} - missing filename or ImageKit data`,\n )\n continue\n }\n\n if (dryRun) {\n console.log(`[migrateFolder] [dry-run] Would upload: ${toFolder}/${slug}/${filename}`)\n console.log(`[migrateFolder] [dry-run] Would update Payload document: ${doc.id}`)\n } else {\n try {\n const sourceFilePath = getFilePath(fromFolder, slug, filename)\n const destinationFolder = getCollectionFolder(toFolder, slug)\n const destinationFilePath = getFilePath(toFolder, slug, filename)\n\n let uploaded: { fileId: string; thumbnailUrl?: string; url: string }\n\n try {\n const copyResponse = await client.files\n .copy({\n destinationPath: destinationFolder,\n sourceFilePath,\n })\n .asResponse()\n\n let copiedFileId = await readFileIdFromCopyResponse(copyResponse)\n\n if (!copiedFileId) {\n copiedFileId = await findImageKitFileId(client, destinationFilePath, {\n retries: 20,\n retryDelayMs: 1000,\n })\n }\n\n if (!copiedFileId) {\n throw new Error(\n `migrateFolder: copy request completed for \"${sourceFilePath}\", but the destination asset at \"${destinationFilePath}\" was not discoverable via ImageKit after retrying.`,\n )\n }\n\n uploaded = await getUploadedImagekitFields({\n client,\n fileId: copiedFileId,\n })\n } catch (error) {\n if (!isImageKitFileNotFoundError(error)) {\n throw error\n }\n\n console.warn(\n `[migrateFolder] Source file not found at ${sourceFilePath}. Falling back to stored ImageKit URL for \"${filename}\".`,\n )\n\n // A private source file 401s on its plain URL, so sign it before ImageKit\n // fetches it, and re-upload as private so the copy keeps its privacy.\n const sourceUrl = isCollectionPrivate\n ? client.helper.buildSrc({\n expiresIn: signedUrlExpiresIn,\n signed: true,\n src: existingImagekit.url,\n urlEndpoint,\n })\n : existingImagekit.url\n\n uploaded = await uploadFileFromURL({\n client,\n fileName: filename,\n folder: destinationFolder,\n isPrivate: isCollectionPrivate,\n sourceUrl,\n })\n }\n\n const canonicalUrl = client.helper.buildSrc({\n src: destinationFilePath,\n urlEndpoint,\n })\n\n const mimeType = (doc as { mimeType?: string }).mimeType\n const adminThumbnailURL = isCollectionPrivate\n ? getPrivateAdminThumbnailURL({ filename, mimeType }, slug, apiRoute)\n : getAdminThumbnailURL({ imagekit: { url: uploaded.url }, mimeType })\n\n // Update the document with new ImageKit data\n await payload.update({\n id: doc.id,\n collection: slug,\n data: {\n imagekit: {\n fileId: uploaded.fileId,\n isPrivate: isCollectionPrivate,\n thumbnailUrl: uploaded.thumbnailUrl,\n url: uploaded.url,\n },\n thumbnailURL: adminThumbnailURL || canonicalUrl,\n url: canonicalUrl,\n },\n })\n\n updatedCount += 1\n console.log(`[migrateFolder] Content migrated! ${filename} (${doc.id})`)\n } catch (error) {\n errorCount += 1\n console.error(\n `[migrateFolder] Failed to migrate document \"${doc.id}\" for file \"${filename}\":`,\n error,\n )\n }\n }\n }\n\n results.push({\n collectionSlug: slug,\n jobId: `migrate:${slug}`,\n status: dryRun ? 'Pending' : 'Completed',\n })\n\n console.log(\n `[migrateFolder] Collection \"${slug}\" complete: updated=${updatedCount}, skipped=${skippedCount}, errors=${errorCount}.`,\n )\n }\n\n console.log('[migrateFolder] Document-by-document migration complete.')\n } else {\n console.log('[migrateFolder] No Payload instance provided - skipping migration.')\n }\n\n console.log(`[migrateFolder] ${dryRun ? 'DRY-RUN simulation' : 'Migration'} complete.`)\n\n return results\n}\n"],"names":["ImageKit","path","getAdminThumbnailURL","getPrivateAdminThumbnailURL","DEFAULT_SIGNED_URL_EXPIRES_IN","isPrivateCollectionConfig","value","private","normalizeFolder","folder","normalized","trim","replace","Error","getCollectionFolder","rootFolder","collectionSlug","posix","join","getFilePath","filename","ensureFolderExists","client","folderPath","segments","split","filter","Boolean","parentFolderPath","folderName","folders","create","error","message","String","test","findImageKitFileId","imagekit","filePath","options","parentPath","dirname","name","basename","retries","retryDelayMs","limit","attempt","skip","assets","list","type","found","find","asset","fileId","length","Promise","resolve","setTimeout","undefined","isImageKitFileNotFoundError","uploadFileFromURL","fileName","isPrivate","sourceUrl","uploaded","files","upload","file","useUniqueFileName","isPrivateFile","url","thumbnailUrl","getUploadedImagekitFields","get","thumbnail","readFileIdFromCopyResponse","response","result","json","file_id","migrateFolder","collections","dryRun","from","payload","privateKey","signedUrlExpiresIn","signedUrlExpiresInOption","to","urlEndpoint","Object","keys","privateSlugs","Set","entries","map","slug","apiRoute","config","routes","api","fromFolder","toFolder","console","log","collectionSlugs","results","destinationFolderPath","isCollectionPrivate","has","collection","depth","pagination","docs","updatedCount","skippedCount","errorCount","i","doc","existingImagekit","id","sourceFilePath","destinationFolder","destinationFilePath","copyResponse","copy","destinationPath","asResponse","copiedFileId","warn","helper","buildSrc","expiresIn","signed","src","canonicalUrl","mimeType","adminThumbnailURL","update","data","thumbnailURL","push","jobId","status"],"mappings":"AAEA,OAAOA,cAAc,mBAAkB;AACvC,OAAOC,UAAU,YAAW;AAE5B,SAASC,oBAAoB,EAAEC,2BAA2B,QAAQ,4BAA2B;AAK7F,MAAMC,gCAAgC;AAEtC,MAAMC,4BAA4B,CAACC,QACjCA,UAAU,QAAQ,OAAOA,UAAU,YAAYA,OAAOC,YAAY;AAmDpE,MAAMC,kBAAkB,CAACC;IACvB,MAAMC,aAAaD,OAAOE,IAAI,GAAGC,OAAO,CAAC,cAAc;IAEvD,IAAI,CAACF,YAAY;QACf,MAAM,IAAIG,MAAM;IAClB;IAEA,OAAO,CAAC,CAAC,EAAEH,YAAY;AACzB;AAEA,MAAMI,sBAAsB,CAACC,YAAoBC,iBAC/Cf,KAAKgB,KAAK,CAACC,IAAI,CAACH,YAAYC;AAE9B,MAAMG,cAAc,CAACJ,YAAoBC,gBAAwBI,WAC/DnB,KAAKgB,KAAK,CAACC,IAAI,CAACJ,oBAAoBC,YAAYC,iBAAiBI;AAEnE,MAAMC,qBAAqB,OAAOC,QAAkBC;IAClD,MAAMb,aAAaF,gBAAgBe;IACnC,MAAMC,WAAWd,WAAWe,KAAK,CAAC,KAAKC,MAAM,CAACC;IAE9C,IAAIC,mBAAmB;IAEvB,KAAK,MAAMC,cAAcL,SAAU;QACjC,IAAI;YACF,MAAMF,OAAOQ,OAAO,CAACC,MAAM,CAAC;gBAC1BF;gBACAD;YACF;QACF,EAAE,OAAOI,OAAO;YACd,MAAMC,UACJD,SAAS,OAAOA,UAAU,YAAY,aAAaA,QAAQE,OAAOF,MAAMC,OAAO,IAAI;YAErF,IAAI,CAAC,kBAAkBE,IAAI,CAACF,UAAU;gBACpC,MAAMD;YACR;QACF;QAEAJ,mBAAmB3B,KAAKgB,KAAK,CAACC,IAAI,CAACU,kBAAkBC;IACvD;AACF;AAEA,MAAMO,qBAAqB,OACzBC,UACAC,UACAC;IAKA,MAAMC,aAAavC,KAAKgB,KAAK,CAACwB,OAAO,CAACH;IACtC,MAAMI,OAAOzC,KAAKgB,KAAK,CAAC0B,QAAQ,CAACL;IAEjC,MAAMM,UAAUL,SAASK,WAAW;IACpC,MAAMC,eAAeN,SAASM,gBAAgB;IAC9C,MAAMC,QAAQ;IAEd,IAAK,IAAIC,UAAU,GAAGA,WAAWH,SAASG,UAAW;QACnD,IAAK,IAAIC,OAAO,IAAKA,QAAQF,MAAO;YAClC,MAAMG,SAAS,MAAMZ,SAASY,MAAM,CAACC,IAAI,CAAC;gBACxCC,MAAM;gBACNL;gBACA7C,MAAMuC,eAAe,MAAM,MAAM,GAAGA,WAAW,CAAC,CAAC;gBACjDQ;YACF;YAEA,MAAMI,QAAQH,OAAOI,IAAI,CACvB,CAACC,QAAU,YAAYA,SAASA,MAAMhB,QAAQ,KAAKA,YAAYgB,MAAMZ,IAAI,KAAKA;YAGhF,IAAIU,SAAS,YAAYA,OAAO;gBAC9B,OAAOA,MAAMG,MAAM;YACrB;YAEA,IAAIN,OAAOO,MAAM,GAAGV,OAAO;gBACzB;YACF;QACF;QAEA,IAAIC,UAAUH,SAAS;YACrB,MAAM,IAAIa,QAAQ,CAACC;gBACjBC,WAAWD,SAASb;YACtB;QACF;IACF;IAEA,OAAOe;AACT;AAEA,MAAMC,8BAA8B,CAAC7B;IACnC,MAAMC,UACJD,SAAS,OAAOA,UAAU,YAAY,aAAaA,QAAQE,OAAOF,MAAMC,OAAO,IAAI;IAErF,OAAO,yCAAyCE,IAAI,CAACF;AACvD;AAEA,MAAM6B,oBAAoB,OAAO,EAC/BxC,MAAM,EACNyC,QAAQ,EACRtD,MAAM,EACNuD,SAAS,EACTC,SAAS,EAOV;IACC,MAAMC,WAAW,MAAM5C,OAAO6C,KAAK,CAACC,MAAM,CAAC;QACzCC,MAAMJ;QACNF;QACAtD;QACA6D,mBAAmB;QACnB,GAAIN,YAAY;YAAEO,eAAe;QAAK,IAAI,CAAC,CAAC;IAC9C;IAEA,IAAI,CAACL,SAASX,MAAM,IAAI,CAACW,SAASM,GAAG,EAAE;QACrC,MAAM,IAAI3D,MAAM,CAAC,gEAAgE,EAAEkD,SAAS,EAAE,CAAC;IACjG;IAEA,OAAO;QACLR,QAAQW,SAASX,MAAM;QACvBkB,cAAcP,SAASO,YAAY;QACnCD,KAAKN,SAASM,GAAG;IACnB;AACF;AAEA,MAAME,4BAA4B,OAAO,EACvCpD,MAAM,EACNiC,MAAM,EAIP;IACC,MAAMc,OAAO,MAAM/C,OAAO6C,KAAK,CAACQ,GAAG,CAACpB;IAEpC,IAAI,CAACc,KAAKd,MAAM,IAAI,CAACc,KAAKG,GAAG,EAAE;QAC7B,MAAM,IAAI3D,MAAM,CAAC,kDAAkD,EAAE0C,OAAO,EAAE,CAAC;IACjF;IAEA,OAAO;QACLA,QAAQc,KAAKd,MAAM;QACnBkB,cAAcJ,KAAKO,SAAS;QAC5BJ,KAAKH,KAAKG,GAAG;IACf;AACF;AAEA,MAAMK,6BAA6B,OAAOC;IACxC,IAAI;QACF,MAAMC,SAAU,MAAMD,SAASE,IAAI;QAEnC,IAAI,OAAOD,OAAOxB,MAAM,KAAK,YAAYwB,OAAOxB,MAAM,CAACC,MAAM,GAAG,GAAG;YACjE,OAAOuB,OAAOxB,MAAM;QACtB;QAEA,IAAI,OAAOwB,OAAOE,OAAO,KAAK,YAAYF,OAAOE,OAAO,CAACzB,MAAM,GAAG,GAAG;YACnE,OAAOuB,OAAOE,OAAO;QACvB;IACF,EAAE,OAAM;IACN,uEAAuE;IACzE;IAEA,OAAOrB;AACT;AAEA,OAAO,MAAMsB,gBAAgB,OAC3B3C;IAEA,MAAM,EACJ4C,WAAW,EACXC,SAAS,IAAI,EACbC,IAAI,EACJC,OAAO,EACPC,UAAU,EACVC,oBAAoBC,wBAAwB,EAC5CC,EAAE,EACFC,WAAW,EACZ,GAAGpD;IAEJ,IAAI,CAACgD,YAAY5E,QAAQ;QACvB,MAAM,IAAIE,MAAM;IAClB;IAEA,IAAI,CAAC8E,aAAahF,QAAQ;QACxB,MAAM,IAAIE,MAAM;IAClB;IAEA,IAAI,CAACsE,eAAeS,OAAOC,IAAI,CAACV,aAAa3B,MAAM,KAAK,GAAG;QACzD,MAAM,IAAI3C,MAAM;IAClB;IAEA,MAAMiF,eAAe,IAAIC,IACvBH,OAAOI,OAAO,CAACb,aACZzD,MAAM,CAAC,CAAC,GAAGpB,MAAM,GAAKD,0BAA0BC,QAChD2F,GAAG,CAAC,CAAC,CAACC,KAAK,GAAKA;IAErB,MAAMV,qBACJ,OAAOC,6BAA6B,YAAYA,2BAA2B,IACvEA,2BACArF;IACN,MAAM+F,WAAWb,SAASc,OAAOC,QAAQC,OAAO;IAEhD,MAAMC,aAAa/F,gBAAgB6E;IACnC,MAAMmB,WAAWhG,gBAAgBkF;IAEjC,IAAIa,eAAeC,UAAU;QAC3B,MAAM,IAAI3F,MAAM;IAClB;IAEA,MAAMS,SAAS,IAAItB,SAAS;QAAEuF;IAAW;IAEzCkB,QAAQC,GAAG,CACT,CAAC,yBAAyB,EAAEtB,SAAS,YAAY,OAAO,gBAAgB,EAAEmB,WAAW,IAAI,EAAEC,SAAS,KAAK,EAAEZ,OAAOC,IAAI,CAACV,aAAa3B,MAAM,CAAC,eAAe,CAAC;IAG7J,IAAI4B,QAAQ;QACVqB,QAAQC,GAAG,CACT,CAAC,uEAAuE,EAAEF,UAAU;IAExF,OAAO;QACLC,QAAQC,GAAG,CAAC,CAAC,yDAAyD,EAAEF,UAAU;QAClF,MAAMnF,mBAAmBC,QAAQkF;IACnC;IAEA,0CAA0C;IAC1C,MAAMG,kBAAkBf,OAAOC,IAAI,CAACV;IACpC,MAAMyB,UAAgC,EAAE;IAExC,6CAA6C;IAC7C,IAAI,CAACxB,QAAQ;QACX,KAAK,MAAMc,QAAQS,gBAAiB;YAClC,MAAME,wBAAwB5G,KAAKgB,KAAK,CAACC,IAAI,CAACsF,UAAUN;YACxDO,QAAQC,GAAG,CAAC,CAAC,6CAA6C,EAAEG,uBAAuB;YACnF,MAAMxF,mBAAmBC,QAAQuF;QACnC;IACF;IAEA,2DAA2D;IAC3D,IAAIvB,SAAS;QACXmB,QAAQC,GAAG,CAAC;QAEZ,KAAK,MAAMR,QAAQS,gBAAiB;YAClC,MAAMG,sBAAsBhB,aAAaiB,GAAG,CAACb;YAE7CO,QAAQC,GAAG,CACT,CAAC,sCAAsC,EAAER,KAAK,CAAC,EAAEY,sBAAsB,eAAe,GAAG,GAAG,CAAC;YAG/F,MAAM1D,QAAQ,MAAMkC,QAAQjC,IAAI,CAAC;gBAC/B2D,YAAYd;gBACZe,OAAO;gBACPnE,OAAO;gBACPoE,YAAY;YACd;YAEAT,QAAQC,GAAG,CACT,CAAC,2BAA2B,EAAEtD,MAAM+D,IAAI,CAAC3D,MAAM,CAAC,4BAA4B,EAAE0C,KAAK,EAAE,CAAC;YAGxF,IAAIkB,eAAe;YACnB,IAAIC,eAAe;YACnB,IAAIC,aAAa;YAEjB,kEAAkE;YAClE,IAAK,IAAIC,IAAI,GAAGA,IAAInE,MAAM+D,IAAI,CAAC3D,MAAM,EAAE+D,IAAK;gBAC1C,MAAMC,MAAMpE,MAAM+D,IAAI,CAACI,EAAE;gBACzB,MAAMnG,WAAW,AAACoG,IAA8BpG,QAAQ;gBACxD,MAAMqG,mBAAmB,AAACD,IAAYnF,QAAQ;gBAE9CoE,QAAQC,GAAG,CAAC,CAAC,iBAAiB,EAAEa,IAAI,EAAE,CAAC,EAAEnE,MAAM+D,IAAI,CAAC3D,MAAM,CAAC,sBAAsB,EAAEgE,IAAIE,EAAE,EAAE;gBAE3F,uDAAuD;gBACvD,IAAI,CAACtG,YAAY,CAACqG,kBAAkBlE,UAAU,CAACkE,kBAAkBjD,KAAK;oBACpE6C,gBAAgB;oBAChBZ,QAAQC,GAAG,CACT,CAAC,kCAAkC,EAAEc,IAAIE,EAAE,CAAC,oCAAoC,CAAC;oBAEnF;gBACF;gBAEA,IAAItC,QAAQ;oBACVqB,QAAQC,GAAG,CAAC,CAAC,wCAAwC,EAAEF,SAAS,CAAC,EAAEN,KAAK,CAAC,EAAE9E,UAAU;oBACrFqF,QAAQC,GAAG,CAAC,CAAC,yDAAyD,EAAEc,IAAIE,EAAE,EAAE;gBAClF,OAAO;oBACL,IAAI;wBACF,MAAMC,iBAAiBxG,YAAYoF,YAAYL,MAAM9E;wBACrD,MAAMwG,oBAAoB9G,oBAAoB0F,UAAUN;wBACxD,MAAM2B,sBAAsB1G,YAAYqF,UAAUN,MAAM9E;wBAExD,IAAI8C;wBAEJ,IAAI;4BACF,MAAM4D,eAAe,MAAMxG,OAAO6C,KAAK,CACpC4D,IAAI,CAAC;gCACJC,iBAAiBJ;gCACjBD;4BACF,GACCM,UAAU;4BAEb,IAAIC,eAAe,MAAMrD,2BAA2BiD;4BAEpD,IAAI,CAACI,cAAc;gCACjBA,eAAe,MAAM9F,mBAAmBd,QAAQuG,qBAAqB;oCACnEjF,SAAS;oCACTC,cAAc;gCAChB;4BACF;4BAEA,IAAI,CAACqF,cAAc;gCACjB,MAAM,IAAIrH,MACR,CAAC,2CAA2C,EAAE8G,eAAe,iCAAiC,EAAEE,oBAAoB,mDAAmD,CAAC;4BAE5K;4BAEA3D,WAAW,MAAMQ,0BAA0B;gCACzCpD;gCACAiC,QAAQ2E;4BACV;wBACF,EAAE,OAAOlG,OAAO;4BACd,IAAI,CAAC6B,4BAA4B7B,QAAQ;gCACvC,MAAMA;4BACR;4BAEAyE,QAAQ0B,IAAI,CACV,CAAC,yCAAyC,EAAER,eAAe,2CAA2C,EAAEvG,SAAS,EAAE,CAAC;4BAGtH,0EAA0E;4BAC1E,sEAAsE;4BACtE,MAAM6C,YAAY6C,sBACdxF,OAAO8G,MAAM,CAACC,QAAQ,CAAC;gCACrBC,WAAW9C;gCACX+C,QAAQ;gCACRC,KAAKf,iBAAiBjD,GAAG;gCACzBmB;4BACF,KACA8B,iBAAiBjD,GAAG;4BAExBN,WAAW,MAAMJ,kBAAkB;gCACjCxC;gCACAyC,UAAU3C;gCACVX,QAAQmH;gCACR5D,WAAW8C;gCACX7C;4BACF;wBACF;wBAEA,MAAMwE,eAAenH,OAAO8G,MAAM,CAACC,QAAQ,CAAC;4BAC1CG,KAAKX;4BACLlC;wBACF;wBAEA,MAAM+C,WAAW,AAAClB,IAA8BkB,QAAQ;wBACxD,MAAMC,oBAAoB7B,sBACtB3G,4BAA4B;4BAAEiB;4BAAUsH;wBAAS,GAAGxC,MAAMC,YAC1DjG,qBAAqB;4BAAEmC,UAAU;gCAAEmC,KAAKN,SAASM,GAAG;4BAAC;4BAAGkE;wBAAS;wBAErE,6CAA6C;wBAC7C,MAAMpD,QAAQsD,MAAM,CAAC;4BACnBlB,IAAIF,IAAIE,EAAE;4BACVV,YAAYd;4BACZ2C,MAAM;gCACJxG,UAAU;oCACRkB,QAAQW,SAASX,MAAM;oCACvBS,WAAW8C;oCACXrC,cAAcP,SAASO,YAAY;oCACnCD,KAAKN,SAASM,GAAG;gCACnB;gCACAsE,cAAcH,qBAAqBF;gCACnCjE,KAAKiE;4BACP;wBACF;wBAEArB,gBAAgB;wBAChBX,QAAQC,GAAG,CAAC,CAAC,kCAAkC,EAAEtF,SAAS,EAAE,EAAEoG,IAAIE,EAAE,CAAC,CAAC,CAAC;oBACzE,EAAE,OAAO1F,OAAO;wBACdsF,cAAc;wBACdb,QAAQzE,KAAK,CACX,CAAC,4CAA4C,EAAEwF,IAAIE,EAAE,CAAC,YAAY,EAAEtG,SAAS,EAAE,CAAC,EAChFY;oBAEJ;gBACF;YACF;YAEA4E,QAAQmC,IAAI,CAAC;gBACX/H,gBAAgBkF;gBAChB8C,OAAO,CAAC,QAAQ,EAAE9C,MAAM;gBACxB+C,QAAQ7D,SAAS,YAAY;YAC/B;YAEAqB,QAAQC,GAAG,CACT,CAAC,4BAA4B,EAAER,KAAK,oBAAoB,EAAEkB,aAAa,UAAU,EAAEC,aAAa,SAAS,EAAEC,WAAW,CAAC,CAAC;QAE5H;QAEAb,QAAQC,GAAG,CAAC;IACd,OAAO;QACLD,QAAQC,GAAG,CAAC;IACd;IAEAD,QAAQC,GAAG,CAAC,CAAC,gBAAgB,EAAEtB,SAAS,uBAAuB,YAAY,UAAU,CAAC;IAEtF,OAAOwB;AACT,EAAC"}
1
+ {"version":3,"sources":["../src/migrate.ts"],"sourcesContent":["import type { Payload, UploadCollectionSlug } from 'payload'\n\nimport ImageKit from '@imagekit/nodejs'\nimport path from 'node:path'\n\ntype ImageKitCollectionConfig = { private?: boolean } | true\ntype ImageKitCollectionMap = Partial<Record<UploadCollectionSlug, ImageKitCollectionConfig>>\n\nconst DEFAULT_SIGNED_URL_EXPIRES_IN = 900\n\nconst isPrivateCollectionConfig = (value: ImageKitCollectionConfig | undefined): boolean =>\n value !== true && typeof value === 'object' && value?.private === true\n\nexport type MigrateFolderOptions = {\n /**\n * The Payload upload collections to migrate. Keys are collection slugs; the value is\n * `true`, or `{ private: true }` to mark migrated files as ImageKit private files.\n */\n collections: ImageKitCollectionMap\n /**\n * Dry-run mode. When `true`, migration logs what would happen without writing\n * to ImageKit or Payload. Defaults to `true`.\n * @default true\n */\n dryRun?: boolean\n /**\n * The source ImageKit root folder (e.g. `/staging`). Each collection subfolder\n * (`/staging/media`) will be copied into `to`.\n */\n from: string\n /**\n * Optional Payload instance. When provided, the stored `imagekit.*` fields in the\n * database will be updated to reflect the new ImageKit asset after copying.\n */\n payload?: Payload\n /**\n * ImageKit private API key.\n */\n privateKey: string\n /**\n * Expiry (in seconds) for the signed URL used to read a private source file when the\n * fast server-side copy is not possible and the migrator falls back to re-uploading\n * from the source URL. Defaults to 900 (15 minutes).\n */\n signedUrlExpiresIn?: number\n /**\n * The destination ImageKit root folder (e.g. `/production`).\n */\n to: string\n /**\n * ImageKit URL endpoint (e.g. `https://ik.imagekit.io/your_id`). Required to sign\n * private source URLs when the migrator falls back to re-uploading from the source URL.\n */\n urlEndpoint: string\n}\n\nexport type MigrationJobResult = {\n collectionSlug: string\n jobId: string\n status: 'Completed' | 'Pending'\n}\n\nconst normalizeFolder = (folder: string): string => {\n const normalized = folder.trim().replace(/^\\/+|\\/+$/g, '')\n\n if (!normalized) {\n throw new Error('migrateFolder: folder path cannot be empty.')\n }\n\n return `/${normalized}`\n}\n\nconst getCollectionFolder = (rootFolder: string, collectionSlug: string): string =>\n path.posix.join(rootFolder, collectionSlug)\n\nconst isFileInFolder = (filePath: string, folderPath: string): boolean =>\n filePath === folderPath || filePath.startsWith(`${folderPath}/`)\n\nconst ensureFolderExists = async (client: ImageKit, folderPath: string): Promise<void> => {\n const normalized = normalizeFolder(folderPath)\n const segments = normalized.split('/').filter(Boolean)\n\n let parentFolderPath = '/'\n\n for (const folderName of segments) {\n try {\n await client.folders.create({\n folderName,\n parentFolderPath,\n })\n } catch (error) {\n const message =\n error && typeof error === 'object' && 'message' in error ? String(error.message) : ''\n\n if (!/already exists/i.test(message)) {\n throw error\n }\n }\n\n parentFolderPath = path.posix.join(parentFolderPath, folderName)\n }\n}\n\nconst findImageKitFileId = async (\n imagekit: ImageKit,\n filePath: string,\n options?: {\n retries?: number\n retryDelayMs?: number\n },\n): Promise<string | undefined> => {\n const parentPath = path.posix.dirname(filePath)\n const name = path.posix.basename(filePath)\n\n const retries = options?.retries ?? 0\n const retryDelayMs = options?.retryDelayMs ?? 250\n const limit = 100\n\n for (let attempt = 0; attempt <= retries; attempt++) {\n for (let skip = 0; ; skip += limit) {\n const assets = await imagekit.assets.list({\n type: 'file',\n limit,\n path: parentPath === '/' ? '/' : `${parentPath}/`,\n skip,\n })\n\n const found = assets.find(\n (asset) => 'fileId' in asset && asset.filePath === filePath && asset.name === name,\n )\n\n if (found && 'fileId' in found) {\n return found.fileId\n }\n\n if (assets.length < limit) {\n break\n }\n }\n\n if (attempt < retries) {\n await new Promise((resolve) => {\n setTimeout(resolve, retryDelayMs)\n })\n }\n }\n\n return undefined\n}\n\nconst isImageKitFileNotFoundError = (error: unknown): boolean => {\n const message =\n error && typeof error === 'object' && 'message' in error ? String(error.message) : ''\n\n return /does not exist|not found|no such file/i.test(message)\n}\n\nconst uploadFileFromURL = async ({\n client,\n fileName,\n folder,\n isPrivate,\n sourceUrl,\n}: {\n client: ImageKit\n fileName: string\n folder: string\n isPrivate?: boolean\n sourceUrl: string\n}) => {\n const uploaded = await client.files.upload({\n file: sourceUrl,\n fileName,\n folder,\n useUniqueFileName: false,\n ...(isPrivate ? { isPrivateFile: true } : {}),\n })\n\n if (!uploaded.fileId || !uploaded.url) {\n throw new Error(`migrateFolder: upload from URL did not return file details for \"${fileName}\".`)\n }\n\n return {\n fileId: uploaded.fileId,\n thumbnailUrl: uploaded.thumbnailUrl,\n url: uploaded.url,\n }\n}\n\nconst getSourceImagekitFields = async ({\n client,\n fileId,\n}: {\n client: ImageKit\n fileId: string\n}): Promise<{\n fileId: string\n fileName: string\n filePath: string\n url: string\n}> => {\n const file = await client.files.get(fileId)\n\n if (!file.fileId || !file.filePath || !file.url) {\n throw new Error(`migrateFolder: missing ImageKit source file details for \"${fileId}\".`)\n }\n\n return {\n fileId: file.fileId,\n fileName: file.name || path.posix.basename(file.filePath),\n filePath: file.filePath,\n url: file.url,\n }\n}\n\nconst getUploadedImagekitFields = async ({\n client,\n fileId,\n}: {\n client: ImageKit\n fileId: string\n}): Promise<{ fileId: string; thumbnailUrl?: string; url: string }> => {\n const file = await client.files.get(fileId)\n\n if (!file.fileId || !file.url) {\n throw new Error(`migrateFolder: missing ImageKit file details for \"${fileId}\".`)\n }\n\n return {\n fileId: file.fileId,\n thumbnailUrl: file.thumbnail,\n url: file.url,\n }\n}\n\nconst readFileIdFromCopyResponse = async (response: Response): Promise<string | undefined> => {\n try {\n const result = (await response.json()) as { file_id?: unknown; fileId?: unknown }\n\n if (typeof result.fileId === 'string' && result.fileId.length > 0) {\n return result.fileId\n }\n\n if (typeof result.file_id === 'string' && result.file_id.length > 0) {\n return result.file_id\n }\n } catch {\n // Ignore empty or non-JSON responses and fall back to asset discovery.\n }\n\n return undefined\n}\n\nexport const migrateFolder = async (\n options: MigrateFolderOptions,\n): Promise<MigrationJobResult[]> => {\n const {\n collections,\n dryRun = true,\n from,\n payload,\n privateKey,\n signedUrlExpiresIn: signedUrlExpiresInOption,\n to,\n urlEndpoint,\n } = options\n\n if (!privateKey?.trim()) {\n throw new Error('migrateFolder: `privateKey` is required.')\n }\n\n if (!urlEndpoint?.trim()) {\n throw new Error('migrateFolder: `urlEndpoint` is required.')\n }\n\n if (!collections || Object.keys(collections).length === 0) {\n throw new Error('migrateFolder: `collections` must include at least one upload collection.')\n }\n\n const privateSlugs = new Set(\n Object.entries(collections)\n .filter(([, value]) => isPrivateCollectionConfig(value))\n .map(([slug]) => slug),\n )\n const signedUrlExpiresIn =\n typeof signedUrlExpiresInOption === 'number' && signedUrlExpiresInOption > 0\n ? signedUrlExpiresInOption\n : DEFAULT_SIGNED_URL_EXPIRES_IN\n const fromFolder = normalizeFolder(from)\n const toFolder = normalizeFolder(to)\n\n if (fromFolder === toFolder) {\n throw new Error('migrateFolder: `from` and `to` cannot be the same folder.')\n }\n\n const client = new ImageKit({ privateKey })\n\n console.log(\n `[migrateFolder] Starting ${dryRun ? 'DRY-RUN' : 'LIVE'} migration from ${fromFolder} to ${toFolder} for ${Object.keys(collections).length} collection(s).`,\n )\n\n if (dryRun) {\n console.log(\n `[migrateFolder] [dry-run] Would ensure destination root folder exists: ${toFolder}`,\n )\n } else {\n console.log(`[migrateFolder] Ensuring destination root folder exists: ${toFolder}`)\n await ensureFolderExists(client, toFolder)\n }\n\n // Always copy file-by-file per collection\n const collectionSlugs = Object.keys(collections)\n const results: MigrationJobResult[] = []\n\n // Ensure destination folder structure exists\n if (!dryRun) {\n for (const slug of collectionSlugs) {\n const destinationFolderPath = path.posix.join(toFolder, slug)\n console.log(`[migrateFolder] Ensuring destination folder: ${destinationFolderPath}`)\n await ensureFolderExists(client, destinationFolderPath)\n }\n }\n\n // Process documents directly like the old migration script\n if (payload) {\n console.log('[migrateFolder] Starting document-by-document migration.')\n\n for (const slug of collectionSlugs) {\n const isCollectionPrivate = privateSlugs.has(slug)\n\n console.log(\n `[migrateFolder] Migrating collection \"${slug}\"${isCollectionPrivate ? ' (private)' : ''}...`,\n )\n\n const found = await payload.find({\n collection: slug,\n depth: 0,\n limit: 0,\n pagination: false,\n })\n\n console.log(\n `[migrateFolder] Processing ${found.docs.length} document(s) in collection \"${slug}\".`,\n )\n\n let updatedCount = 0\n let skippedCount = 0\n let errorCount = 0\n\n // Process each document one by one, like the old migration script\n for (let i = 0; i < found.docs.length; i++) {\n const doc = found.docs[i]\n const filename = (doc as { filename?: string }).filename\n const existingImagekit = (doc as any).imagekit\n const displayName = filename || existingImagekit?.fileId || doc.id\n\n console.log(`[migrateFolder] [${i + 1}/${found.docs.length}] Processing document ${doc.id}`)\n\n // Skip items that don't have an ImageKit file ID to migrate from.\n if (!existingImagekit?.fileId) {\n skippedCount += 1\n console.log(`[migrateFolder] Skipping document ${doc.id} - missing ImageKit file ID`)\n continue\n }\n\n try {\n const destinationFolder = getCollectionFolder(toFolder, slug)\n const source = await getSourceImagekitFields({\n client,\n fileId: existingImagekit.fileId,\n })\n\n if (isFileInFolder(source.filePath, destinationFolder)) {\n skippedCount += 1\n console.log(\n `[migrateFolder] Skipping document ${doc.id} - ImageKit file ID ${source.fileId} is already in ${destinationFolder}`,\n )\n continue\n }\n\n if (dryRun) {\n console.log(\n `[migrateFolder] [dry-run] Would copy ImageKit file ID ${source.fileId} from ${source.filePath} to ${destinationFolder}`,\n )\n console.log(`[migrateFolder] [dry-run] Would update Payload document: ${doc.id}`)\n } else {\n const destinationFilePath = path.posix.join(destinationFolder, source.fileName)\n\n let uploaded: { fileId: string; thumbnailUrl?: string; url: string }\n\n try {\n const copyResponse = await client.files\n .copy({\n destinationPath: destinationFolder,\n sourceFilePath: source.filePath,\n })\n .asResponse()\n\n let copiedFileId = await readFileIdFromCopyResponse(copyResponse)\n\n if (!copiedFileId) {\n copiedFileId = await findImageKitFileId(client, destinationFilePath, {\n retries: 20,\n retryDelayMs: 1000,\n })\n }\n\n if (!copiedFileId) {\n throw new Error(\n `migrateFolder: copy request completed for ImageKit file ID \"${source.fileId}\" from \"${source.filePath}\", but the destination asset at \"${destinationFilePath}\" was not discoverable via ImageKit after retrying.`,\n )\n }\n\n uploaded = await getUploadedImagekitFields({\n client,\n fileId: copiedFileId,\n })\n } catch (error) {\n if (!isImageKitFileNotFoundError(error)) {\n throw error\n }\n\n console.warn(\n `[migrateFolder] Source file not found for ImageKit file ID ${source.fileId}. Falling back to resolved ImageKit URL for \"${source.fileName}\".`,\n )\n\n // A private source file 401s on its plain URL, so sign it before ImageKit\n // fetches it, and re-upload as private so the copy keeps its privacy.\n const sourceUrl = isCollectionPrivate\n ? client.helper.buildSrc({\n expiresIn: signedUrlExpiresIn,\n signed: true,\n src: source.url,\n urlEndpoint,\n })\n : source.url\n\n uploaded = await uploadFileFromURL({\n client,\n fileName: source.fileName,\n folder: destinationFolder,\n isPrivate: isCollectionPrivate,\n sourceUrl,\n })\n }\n\n // Update the document with new ImageKit data\n await payload.update({\n id: doc.id,\n collection: slug,\n data: {\n imagekit: {\n fileId: uploaded.fileId,\n isPrivate: isCollectionPrivate,\n thumbnailUrl: uploaded.thumbnailUrl,\n url: uploaded.url,\n },\n },\n })\n\n updatedCount += 1\n console.log(`[migrateFolder] Content migrated! ${displayName} (${doc.id})`)\n }\n } catch (error) {\n errorCount += 1\n console.error(\n `[migrateFolder] Failed to migrate document \"${doc.id}\" for file \"${displayName}\":`,\n error,\n )\n }\n }\n\n results.push({\n collectionSlug: slug,\n jobId: `migrate:${slug}`,\n status: dryRun ? 'Pending' : 'Completed',\n })\n\n console.log(\n `[migrateFolder] Collection \"${slug}\" complete: updated=${updatedCount}, skipped=${skippedCount}, errors=${errorCount}.`,\n )\n }\n\n console.log('[migrateFolder] Document-by-document migration complete.')\n } else {\n console.log('[migrateFolder] No Payload instance provided - skipping migration.')\n }\n\n console.log(`[migrateFolder] ${dryRun ? 'DRY-RUN simulation' : 'Migration'} complete.`)\n\n return results\n}\n"],"names":["ImageKit","path","DEFAULT_SIGNED_URL_EXPIRES_IN","isPrivateCollectionConfig","value","private","normalizeFolder","folder","normalized","trim","replace","Error","getCollectionFolder","rootFolder","collectionSlug","posix","join","isFileInFolder","filePath","folderPath","startsWith","ensureFolderExists","client","segments","split","filter","Boolean","parentFolderPath","folderName","folders","create","error","message","String","test","findImageKitFileId","imagekit","options","parentPath","dirname","name","basename","retries","retryDelayMs","limit","attempt","skip","assets","list","type","found","find","asset","fileId","length","Promise","resolve","setTimeout","undefined","isImageKitFileNotFoundError","uploadFileFromURL","fileName","isPrivate","sourceUrl","uploaded","files","upload","file","useUniqueFileName","isPrivateFile","url","thumbnailUrl","getSourceImagekitFields","get","getUploadedImagekitFields","thumbnail","readFileIdFromCopyResponse","response","result","json","file_id","migrateFolder","collections","dryRun","from","payload","privateKey","signedUrlExpiresIn","signedUrlExpiresInOption","to","urlEndpoint","Object","keys","privateSlugs","Set","entries","map","slug","fromFolder","toFolder","console","log","collectionSlugs","results","destinationFolderPath","isCollectionPrivate","has","collection","depth","pagination","docs","updatedCount","skippedCount","errorCount","i","doc","filename","existingImagekit","displayName","id","destinationFolder","source","destinationFilePath","copyResponse","copy","destinationPath","sourceFilePath","asResponse","copiedFileId","warn","helper","buildSrc","expiresIn","signed","src","update","data","push","jobId","status"],"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.4.0",
3
+ "version": "2.5.0",
4
4
  "description": "ImageKit storage adapter plugin for Payload CMS uploads",
5
5
  "license": "MIT",
6
6
  "type": "module",