@composius/payload-plugin-import-wordpress 1.0.1 → 1.0.2

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/dist/index.js CHANGED
@@ -1781,26 +1781,6 @@ var ComposiusPayloadPluginImportWordpress = (pluginOptions = {}) => async (confi
1781
1781
  ...config.jobs,
1782
1782
  tasks: [...config.jobs?.tasks ?? [], importWordpressTask(options)]
1783
1783
  };
1784
- if (pluginOptions.disabled) {
1785
- return config;
1786
- }
1787
- config.endpoints = [
1788
- ...config.endpoints ?? [],
1789
- startEndpoint(options.access),
1790
- statusEndpoint(options.access)
1791
- ];
1792
- if (pluginOptions.autoRun !== false) {
1793
- const schedule = typeof pluginOptions.autoRun === "object" ? pluginOptions.autoRun : {};
1794
- const entry = { cron: schedule.cron ?? "* * * * *", queue: schedule.queue ?? "default" };
1795
- const existing = config.jobs.autoRun;
1796
- if (existing === void 0) {
1797
- config.jobs.autoRun = [entry];
1798
- } else if (Array.isArray(existing)) {
1799
- config.jobs.autoRun = [...existing, entry];
1800
- } else {
1801
- warnings.push("`jobs.autoRun` is a function; skipping the plugin auto-run schedule.");
1802
- }
1803
- }
1804
1784
  if (options.redirects) {
1805
1785
  try {
1806
1786
  const { redirectsPlugin } = await import("@payloadcms/plugin-redirects");
@@ -1813,6 +1793,26 @@ var ComposiusPayloadPluginImportWordpress = (pluginOptions = {}) => async (confi
1813
1793
  );
1814
1794
  }
1815
1795
  }
1796
+ if (!pluginOptions.disabled) {
1797
+ config.endpoints = [
1798
+ ...config.endpoints ?? [],
1799
+ startEndpoint(options.access),
1800
+ statusEndpoint(options.access)
1801
+ ];
1802
+ if (pluginOptions.autoRun !== false) {
1803
+ const schedule = typeof pluginOptions.autoRun === "object" ? pluginOptions.autoRun : {};
1804
+ const entry = { cron: schedule.cron ?? "* * * * *", queue: schedule.queue ?? "default" };
1805
+ const jobs = config.jobs ??= { tasks: [] };
1806
+ const existing = jobs.autoRun;
1807
+ if (existing === void 0) {
1808
+ jobs.autoRun = [entry];
1809
+ } else if (Array.isArray(existing)) {
1810
+ jobs.autoRun = [...existing, entry];
1811
+ } else {
1812
+ warnings.push("`jobs.autoRun` is a function; skipping the plugin auto-run schedule.");
1813
+ }
1814
+ }
1815
+ }
1816
1816
  if (warnings.length > 0) {
1817
1817
  const incomingOnInit = config.onInit;
1818
1818
  config.onInit = async (payload) => {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/defaults.ts","../src/translations/en.ts","../src/translations/fr.ts","../src/translations/index.ts","../src/collections/ImportJobs.ts","../src/collections/ImportRecords.ts","../src/endpoints/index.ts","../src/lib/authors.ts","../src/lib/id.ts","../src/lib/url.ts","../src/lib/payloadOps.ts","../src/lib/records.ts","../src/lib/media.ts","../src/lib/categories.ts","../src/lib/content.ts","../src/lib/lexical.ts","../src/lib/editorConfig.ts","../src/lib/post.ts","../src/lib/redirects.ts","../src/lib/report.ts","../src/lib/wpClient.ts","../src/jobs/runImport.ts","../src/jobs/task.ts","../src/index.ts"],"sourcesContent":["import type { Access } from 'payload'\n\nimport type { ComposiusPayloadPluginImportWordpressConfig, ResolvedOptions } from './types.js'\n\nexport const anyone: Access = () => true\n\nexport const authenticated: Access = ({ req: { user } }) => Boolean(user)\n\nexport const defaultArticleUrl = (slug?: null | string): string =>\n `${process.env.NEXT_PUBLIC_SERVER_URL || 'http://localhost:3000'}/articles/${slug ?? ''}`\n\n/** Slug of the collection storing import jobs (the \"form\" + report surface). */\nexport const JOBS_SLUG = 'wp-import-jobs'\n/** Slug of the collection storing source→target mappings for idempotency. */\nexport const RECORDS_SLUG = 'wp-import-records'\n/** Job task slug registered on the Payload jobs queue. */\nexport const TASK_SLUG = 'importWordpress'\n\n/** Merges user options with defaults into a fully-resolved options object. */\nexport const resolveOptions = (\n pluginOptions: ComposiusPayloadPluginImportWordpressConfig,\n): ResolvedOptions => ({\n access: {\n create: pluginOptions.access?.create ?? authenticated,\n delete: pluginOptions.access?.delete ?? authenticated,\n read: pluginOptions.access?.read ?? authenticated,\n update: pluginOptions.access?.update ?? authenticated,\n },\n articleUrl: pluginOptions.articleUrl ?? defaultArticleUrl,\n authorMapping: {\n strategy: pluginOptions.authorMapping?.strategy ?? 'users',\n defaultUserId: pluginOptions.authorMapping?.defaultUserId,\n syntheticEmailDomain: pluginOptions.authorMapping?.syntheticEmailDomain ?? 'imported.invalid',\n },\n collections: {\n articles: pluginOptions.collections?.articles ?? 'articles',\n categories: pluginOptions.collections?.categories ?? 'categories',\n media: pluginOptions.collections?.media ?? 'media',\n authors: pluginOptions.collections?.authors ?? 'authors',\n users: pluginOptions.collections?.users ?? 'users',\n },\n dryRunPageLimit: pluginOptions.dryRunPageLimit ?? 1,\n excerptToSeoDescription: pluginOptions.excerptToSeoDescription ?? true,\n firstImageAsCover: pluginOptions.firstImageAsCover ?? true,\n fieldMap: {\n title: pluginOptions.fieldMap?.title ?? 'title',\n slug: pluginOptions.fieldMap?.slug ?? 'slug',\n content: pluginOptions.fieldMap?.content ?? 'content',\n coverImage: pluginOptions.fieldMap?.coverImage ?? 'coverImage',\n category: pluginOptions.fieldMap?.category ?? 'category',\n publishedAt: pluginOptions.fieldMap?.publishedAt ?? 'publishedAt',\n },\n redirects: pluginOptions.redirects ?? true,\n request: {\n concurrency: pluginOptions.request?.concurrency ?? 5,\n timeoutMs: pluginOptions.request?.timeoutMs ?? 30000,\n userAgent: pluginOptions.request?.userAgent,\n },\n})\n","export const en = {\n jobs: {\n singular: 'WordPress import',\n plural: 'WordPress imports',\n tabs: {\n configuration: 'Configuration',\n authors: 'Authors',\n categories: 'Categories',\n media: 'Media',\n posts: 'Posts',\n links: 'Links & redirects',\n report: 'Report',\n },\n fields: {\n sourceUrl: 'WordPress site URL',\n sourceUrlDescription:\n 'Base URL of the WordPress site, e.g. https://example.com — its REST API (/wp-json) is read.',\n credentials: 'Credentials (optional)',\n credentialsDescription:\n 'Optional WordPress user + application password. When set, requests are authenticated so non-public data (e.g. author emails) can be imported.',\n username: 'Username',\n applicationPassword: 'Application password',\n applicationPasswordDescription:\n 'Create one in WordPress under Users → Profile → Application Passwords. Stored on this document — delete the job (or clear this field) after the import.',\n dateFrom: 'From date',\n dateTo: 'To date',\n limit: 'Max posts',\n limitDescription: 'Optional cap on the number of posts imported in this run.',\n dryRun: 'Dry run',\n dryRunDescription:\n 'Preview only: report what would be imported without writing anything. Limited to the first page(s).',\n resume: 'Resume / retry',\n resumeDescription: 'Re-queue this job to continue where it stopped (already-imported items are skipped).',\n status: 'Status',\n progress: 'Progress',\n runs: 'Run history',\n authorsReport: 'Imported authors',\n categoriesReport: 'Imported categories',\n mediaReport: 'Imported media',\n postsReport: 'Imported posts',\n linksReport: 'Link mapping',\n errorsReport: 'Errors',\n startedAt: 'Started at',\n finishedAt: 'Finished at',\n },\n status: {\n queued: 'Queued',\n running: 'Running',\n paused: 'Paused',\n completed: 'Completed',\n failed: 'Failed',\n },\n },\n records: {\n singular: 'WordPress import record',\n plural: 'WordPress import records',\n fields: {\n job: 'Import job',\n site: 'Site',\n sourceType: 'Source type',\n sourceId: 'Source ID',\n sourceKey: 'Source key',\n targetCollection: 'Target collection',\n targetId: 'Target ID',\n status: 'Status',\n error: 'Error',\n },\n },\n}\n","import type { Translation } from './index.js'\n\nexport const fr: Translation = {\n jobs: {\n singular: 'Import WordPress',\n plural: 'Imports WordPress',\n tabs: {\n configuration: 'Configuration',\n authors: 'Auteurs',\n categories: 'Catégories',\n media: 'Médias',\n posts: 'Articles',\n links: 'Liens et redirections',\n report: 'Rapport',\n },\n fields: {\n sourceUrl: 'URL du site WordPress',\n sourceUrlDescription:\n 'URL de base du site WordPress, ex. https://example.com — son API REST (/wp-json) est lue.',\n credentials: 'Identifiants (optionnel)',\n credentialsDescription:\n 'Utilisateur WordPress + mot de passe d’application optionnels. Une fois définis, les requêtes sont authentifiées pour importer des données non publiques (ex. e-mails des auteurs).',\n username: 'Nom d’utilisateur',\n applicationPassword: 'Mot de passe d’application',\n applicationPasswordDescription:\n 'À créer dans WordPress sous Utilisateurs → Profil → Mots de passe d’application. Stocké sur ce document — supprimez le travail (ou videz ce champ) après l’import.',\n dateFrom: 'À partir du',\n dateTo: \"Jusqu'au\",\n limit: 'Nombre max. d’articles',\n limitDescription: 'Limite optionnelle du nombre d’articles importés lors de cette exécution.',\n dryRun: 'Simulation',\n dryRunDescription:\n 'Aperçu uniquement : indique ce qui serait importé sans rien écrire. Limité à la ou les premières pages.',\n resume: 'Reprendre / réessayer',\n resumeDescription:\n 'Remettre ce travail en file pour continuer là où il s’est arrêté (les éléments déjà importés sont ignorés).',\n status: 'Statut',\n progress: 'Progression',\n runs: 'Historique des exécutions',\n authorsReport: 'Auteurs importés',\n categoriesReport: 'Catégories importées',\n mediaReport: 'Médias importés',\n postsReport: 'Articles importés',\n linksReport: 'Correspondance des liens',\n errorsReport: 'Erreurs',\n startedAt: 'Démarré à',\n finishedAt: 'Terminé à',\n },\n status: {\n queued: 'En file',\n running: 'En cours',\n paused: 'En pause',\n completed: 'Terminé',\n failed: 'Échoué',\n },\n },\n records: {\n singular: 'Enregistrement d’import WordPress',\n plural: 'Enregistrements d’import WordPress',\n fields: {\n job: 'Travail d’import',\n site: 'Site',\n sourceType: 'Type de source',\n sourceId: 'ID source',\n sourceKey: 'Clé source',\n targetCollection: 'Collection cible',\n targetId: 'ID cible',\n status: 'Statut',\n error: 'Erreur',\n },\n },\n}\n","import { en } from './en.js'\nimport { fr } from './fr.js'\n\nexport type Translation = typeof en\n\n/** Builds a Payload label record ({ en, fr }) from a translation key selector. */\nexport const label = (pick: (t: Translation) => string): Record<string, string> => ({\n en: pick(en),\n fr: pick(fr),\n})\n","import type { CollectionConfig, PayloadRequest } from 'payload'\n\nimport type { ImportAccess } from '../types.js'\n\nimport { TASK_SLUG } from '../defaults.js'\nimport { label } from '../translations/index.js'\n\nexport type ImportJobsOptions = {\n access: Required<ImportAccess>\n}\n\n/** Queues the import task for a job document (task-slug not in generated types → loose cast). */\nconst queueImport = async (req: PayloadRequest, jobId: number | string): Promise<void> => {\n const queue = req.payload.jobs.queue as unknown as (args: {\n input: { jobId: number | string }\n req?: PayloadRequest\n task: string\n }) => Promise<unknown>\n await queue({ input: { jobId }, req, task: TASK_SLUG })\n}\n\n/**\n * The import \"form\" and report surface. Creating a document queues an import\n * run (via the jobs queue); the task writes `status`, `progress` and `report`\n * back onto the same document. Toggling `resume` re-queues a stopped run.\n */\nexport const ImportJobs = ({ access }: ImportJobsOptions): CollectionConfig => ({\n slug: 'wp-import-jobs',\n labels: {\n singular: label((t) => t.jobs.singular),\n plural: label((t) => t.jobs.plural),\n },\n admin: {\n useAsTitle: 'sourceUrl',\n defaultColumns: ['sourceUrl', 'status', 'dryRun', 'updatedAt'],\n group: 'WordPress import',\n },\n access: {\n read: access.read,\n create: access.create,\n update: access.update,\n delete: access.delete,\n },\n hooks: {\n afterChange: [\n async ({ context, doc, operation, req }) => {\n // Updates coming from the importer itself must not re-queue the job.\n if (context?.wpImport) {\n return doc\n }\n\n if (operation === 'create') {\n await queueImport(req, doc.id as number | string)\n return doc\n }\n\n // A user toggled \"resume\" on an existing job → re-queue and clear the flag.\n if (operation === 'update' && doc.resume) {\n await req.payload.update({\n collection: 'wp-import-jobs',\n id: doc.id as number | string,\n data: { resume: false, status: 'queued' },\n context: { wpImport: true },\n req,\n })\n await queueImport(req, doc.id as number | string)\n }\n\n return doc\n },\n ],\n },\n fields: [\n // Unnamed tabs keep their fields at the top level of the document data —\n // one tab per import step, so each step's outcome reads in its own tab.\n {\n type: 'tabs',\n tabs: [\n {\n label: label((t) => t.jobs.tabs.configuration),\n fields: [\n {\n name: 'sourceUrl',\n type: 'text',\n label: label((t) => t.jobs.fields.sourceUrl),\n required: true,\n admin: {\n description: label((t) => t.jobs.fields.sourceUrlDescription),\n },\n },\n {\n name: 'credentials',\n type: 'group',\n label: label((t) => t.jobs.fields.credentials),\n admin: {\n description: label((t) => t.jobs.fields.credentialsDescription),\n },\n fields: [\n {\n type: 'row',\n fields: [\n {\n name: 'username',\n type: 'text',\n label: label((t) => t.jobs.fields.username),\n admin: { width: '50%' },\n },\n {\n name: 'applicationPassword',\n type: 'text',\n label: label((t) => t.jobs.fields.applicationPassword),\n admin: {\n width: '50%',\n description: label((t) => t.jobs.fields.applicationPasswordDescription),\n components: {\n // Masked (•••) input instead of plain text.\n Field:\n '@composius/payload-plugin-import-wordpress/client#ApplicationPasswordFieldClient',\n },\n },\n },\n ],\n },\n ],\n },\n {\n type: 'row',\n fields: [\n {\n name: 'dateFrom',\n type: 'date',\n label: label((t) => t.jobs.fields.dateFrom),\n admin: { width: '50%', date: { pickerAppearance: 'dayOnly' } },\n },\n {\n name: 'dateTo',\n type: 'date',\n label: label((t) => t.jobs.fields.dateTo),\n admin: { width: '50%', date: { pickerAppearance: 'dayOnly' } },\n },\n ],\n },\n {\n name: 'limit',\n type: 'number',\n label: label((t) => t.jobs.fields.limit),\n min: 1,\n admin: {\n description: label((t) => t.jobs.fields.limitDescription),\n },\n },\n {\n name: 'dryRun',\n type: 'checkbox',\n label: label((t) => t.jobs.fields.dryRun),\n defaultValue: false,\n admin: {\n description: label((t) => t.jobs.fields.dryRunDescription),\n },\n },\n {\n name: 'resume',\n type: 'checkbox',\n label: label((t) => t.jobs.fields.resume),\n defaultValue: false,\n admin: {\n description: label((t) => t.jobs.fields.resumeDescription),\n },\n },\n ],\n },\n {\n label: label((t) => t.jobs.tabs.authors),\n fields: [\n {\n name: 'authorsReport',\n type: 'json',\n label: label((t) => t.jobs.fields.authorsReport),\n admin: { readOnly: true },\n },\n ],\n },\n {\n label: label((t) => t.jobs.tabs.categories),\n fields: [\n {\n name: 'categoriesReport',\n type: 'json',\n label: label((t) => t.jobs.fields.categoriesReport),\n admin: { readOnly: true },\n },\n ],\n },\n {\n label: label((t) => t.jobs.tabs.media),\n fields: [\n {\n name: 'mediaReport',\n type: 'json',\n label: label((t) => t.jobs.fields.mediaReport),\n admin: { readOnly: true },\n },\n ],\n },\n {\n label: label((t) => t.jobs.tabs.posts),\n fields: [\n {\n name: 'postsReport',\n type: 'json',\n label: label((t) => t.jobs.fields.postsReport),\n admin: { readOnly: true },\n },\n ],\n },\n {\n label: label((t) => t.jobs.tabs.links),\n fields: [\n {\n name: 'linksReport',\n type: 'json',\n label: label((t) => t.jobs.fields.linksReport),\n admin: { readOnly: true },\n },\n ],\n },\n {\n label: label((t) => t.jobs.tabs.report),\n fields: [\n {\n name: 'runs',\n type: 'json',\n label: label((t) => t.jobs.fields.runs),\n admin: { readOnly: true },\n },\n {\n name: 'progress',\n type: 'json',\n label: label((t) => t.jobs.fields.progress),\n admin: { readOnly: true },\n },\n {\n name: 'errorsReport',\n type: 'json',\n label: label((t) => t.jobs.fields.errorsReport),\n admin: { readOnly: true },\n },\n ],\n },\n ],\n },\n {\n name: 'status',\n type: 'select',\n label: label((t) => t.jobs.fields.status),\n defaultValue: 'queued',\n options: [\n { label: label((t) => t.jobs.status.queued), value: 'queued' },\n { label: label((t) => t.jobs.status.running), value: 'running' },\n { label: label((t) => t.jobs.status.paused), value: 'paused' },\n { label: label((t) => t.jobs.status.completed), value: 'completed' },\n { label: label((t) => t.jobs.status.failed), value: 'failed' },\n ],\n admin: {\n position: 'sidebar',\n readOnly: true,\n },\n },\n {\n name: 'startedAt',\n type: 'date',\n label: label((t) => t.jobs.fields.startedAt),\n admin: { position: 'sidebar', readOnly: true, date: { pickerAppearance: 'dayAndTime' } },\n },\n {\n name: 'finishedAt',\n type: 'date',\n label: label((t) => t.jobs.fields.finishedAt),\n admin: { position: 'sidebar', readOnly: true, date: { pickerAppearance: 'dayAndTime' } },\n },\n ],\n})\n","import type { CollectionConfig } from 'payload'\n\nimport type { ImportAccess } from '../types.js'\n\nimport { label } from '../translations/index.js'\n\nexport type ImportRecordsOptions = {\n access: Required<ImportAccess>\n}\n\n/**\n * Source→target mapping rows that make the import idempotent, resumable and\n * image-deduplicating. Before importing anything the task looks up a `done`\n * record for the same `site` + `sourceType` + `sourceId` (or `sourceKey` for\n * media, keyed by the image URL) and skips/reuses it.\n */\nexport const ImportRecords = ({ access }: ImportRecordsOptions): CollectionConfig => ({\n slug: 'wp-import-records',\n labels: {\n singular: label((t) => t.records.singular),\n plural: label((t) => t.records.plural),\n },\n admin: {\n useAsTitle: 'sourceKey',\n defaultColumns: ['site', 'sourceType', 'sourceId', 'targetCollection', 'targetId', 'status'],\n group: 'WordPress import',\n hidden: true,\n },\n access: {\n read: access.read,\n create: access.create,\n update: access.update,\n delete: access.delete,\n },\n indexes: [\n { fields: ['site', 'sourceType', 'sourceId'] },\n { fields: ['site', 'sourceType', 'sourceKey'] },\n ],\n fields: [\n {\n name: 'job',\n type: 'relationship',\n label: label((t) => t.records.fields.job),\n relationTo: 'wp-import-jobs',\n },\n {\n name: 'site',\n type: 'text',\n label: label((t) => t.records.fields.site),\n index: true,\n required: true,\n },\n {\n name: 'sourceType',\n type: 'select',\n label: label((t) => t.records.fields.sourceType),\n options: ['post', 'category', 'author', 'media'],\n index: true,\n required: true,\n },\n {\n name: 'sourceId',\n type: 'number',\n label: label((t) => t.records.fields.sourceId),\n index: true,\n },\n {\n name: 'sourceKey',\n type: 'text',\n label: label((t) => t.records.fields.sourceKey),\n index: true,\n },\n {\n name: 'targetCollection',\n type: 'text',\n label: label((t) => t.records.fields.targetCollection),\n },\n {\n name: 'targetId',\n type: 'text',\n label: label((t) => t.records.fields.targetId),\n },\n {\n name: 'status',\n type: 'select',\n label: label((t) => t.records.fields.status),\n defaultValue: 'done',\n options: ['done', 'failed'],\n },\n {\n name: 'error',\n type: 'text',\n label: label((t) => t.records.fields.error),\n },\n ],\n})\n","import type { Endpoint, PayloadRequest } from 'payload'\n\nimport { APIError } from 'payload'\n\nimport type { ImportAccess } from '../types.js'\n\nimport { JOBS_SLUG } from '../defaults.js'\n\ntype StartBody = {\n dateFrom?: string\n dateTo?: string\n dryRun?: boolean\n limit?: number\n sourceUrl?: string\n}\n\n/** Runs a per-operation access function and throws 403 when it denies. */\nconst assertAccess = async (\n access: Required<ImportAccess>,\n operation: 'create' | 'read',\n req: PayloadRequest,\n): Promise<void> => {\n const result = await access[operation]({ req } as Parameters<Required<ImportAccess>['read']>[0])\n if (!result) {\n throw new APIError('Forbidden', 403)\n }\n}\n\n/**\n * POST /api/wp-import/start — creates a `wp-import-jobs` document (which queues\n * the import via its afterChange hook) and returns the job id. Gated by the\n * plugin's `access.create` option, and again by the collection's create access\n * via `overrideAccess: false`.\n */\nexport const startEndpoint = (access: Required<ImportAccess>): Endpoint => ({\n path: '/wp-import/start',\n method: 'post',\n handler: async (req: PayloadRequest): Promise<Response> => {\n if (!req.user) {\n throw new APIError('Unauthorized', 401)\n }\n await assertAccess(access, 'create', req)\n\n const body = ((await req.json?.()) ?? {}) as StartBody\n if (!body.sourceUrl) {\n return Response.json({ error: 'sourceUrl is required' }, { status: 400 })\n }\n\n const job = await req.payload.create({\n collection: JOBS_SLUG,\n data: {\n dateFrom: body.dateFrom,\n dateTo: body.dateTo,\n dryRun: body.dryRun ?? false,\n limit: body.limit,\n sourceUrl: body.sourceUrl,\n },\n overrideAccess: false,\n req,\n user: req.user,\n })\n\n return Response.json({ jobId: job.id }, { status: 202 })\n },\n})\n\n/**\n * GET /api/wp-import/status/:id — returns the job's status, progress and report.\n * Gated by the plugin's `access.read` option and the collection's read access.\n */\nexport const statusEndpoint = (access: Required<ImportAccess>): Endpoint => ({\n path: '/wp-import/status/:id',\n method: 'get',\n handler: async (req: PayloadRequest): Promise<Response> => {\n if (!req.user) {\n throw new APIError('Unauthorized', 401)\n }\n await assertAccess(access, 'read', req)\n\n const id = req.routeParams?.id as number | string\n const job = (await req.payload.findByID({\n collection: JOBS_SLUG,\n id,\n overrideAccess: false,\n req,\n user: req.user,\n })) as unknown as Record<string, unknown>\n\n return Response.json({\n progress: job.progress,\n report: {\n authors: job.authorsReport,\n categories: job.categoriesReport,\n errors: job.errorsReport,\n links: job.linksReport,\n media: job.mediaReport,\n posts: job.postsReport,\n },\n runs: job.runs,\n status: job.status,\n })\n },\n})\n","import type { Payload } from 'payload'\n\nimport crypto from 'crypto'\n\nimport type { AuthorStrategy, ImportedItem } from '../types.js'\nimport type { ImageImportResult } from './media.js'\nimport type { WPUser } from './wpTypes.js'\n\nimport { coerceId } from './id.js'\nimport { decodeEntities } from './url.js'\nimport { importImage } from './media.js'\nimport { createDoc, findDocs } from './payloadOps.js'\nimport { findDoneRecord, saveRecord } from './records.js'\n\nexport type ResolvedAuthor = {\n /** Article relationship field to assign (`editor` for users, `author` for authors). */\n field: 'author' | 'editor'\n value: number | string\n}\n\nexport type ResolveAuthorArgs = {\n authorsSlug: string\n defaultUserId?: number | string\n dryRun: boolean\n fetchImpl?: typeof fetch\n imageCache: Map<string, ImageImportResult>\n jobId: number | string\n mediaSlug: string\n site: string\n strategy: AuthorStrategy\n /** Domain for synthesized emails, or `false` to skip users without a real email. */\n syntheticEmailDomain: false | string\n timeoutMs: number\n usersSlug: string\n wpUser?: WPUser\n}\n\n/** Highest-resolution avatar URL WordPress exposes, if any. */\nconst avatarUrl = (wpUser: WPUser): string | undefined => {\n const urls = wpUser.avatar_urls\n if (!urls) {\n return undefined\n }\n const sizes = Object.keys(urls)\n .map(Number)\n .filter((n) => !Number.isNaN(n))\n .sort((a, b) => b - a)\n return sizes.length ? urls[String(sizes[0])] : undefined\n}\n\nexport type ResolveAuthorResult = {\n author: null | ResolvedAuthor\n imported?: ImportedItem\n /** Set when a `users`-strategy author had no email and creation was skipped. */\n skippedNoEmail?: { name: string; sourceId: number }\n}\n\n/**\n * Resolves the article author relationship for a post per the configured\n * strategy, importing into `users` (default) or `authors`, or using a fixed\n * user. Idempotent via import records. Returns the imported item (if any new\n * doc was created) alongside the resolved relationship.\n */\nexport const resolveAuthor = async (\n payload: Payload,\n args: ResolveAuthorArgs,\n): Promise<ResolveAuthorResult> => {\n if (args.strategy === 'fixed') {\n return {\n author: args.defaultUserId != null ? { field: 'editor', value: args.defaultUserId } : null,\n }\n }\n\n const wpUser = args.wpUser\n if (!wpUser) {\n return { author: args.defaultUserId != null ? { field: 'editor', value: args.defaultUserId } : null }\n }\n\n const name = decodeEntities(wpUser.name ?? wpUser.slug ?? `author-${wpUser.id}`)\n\n const existing = await findDoneRecord(payload, {\n site: args.site,\n sourceId: wpUser.id,\n sourceType: 'author',\n })\n\n if (args.strategy === 'users') {\n const field = 'editor' as const\n if (existing) {\n return { author: { field, value: existing } }\n }\n // The public REST API rarely exposes emails; synthesize one from the\n // configured domain, or skip user creation when that is disabled.\n const email =\n wpUser.email ||\n (args.syntheticEmailDomain\n ? `${wpUser.slug || `author-${wpUser.id}`}@${args.syntheticEmailDomain}`\n : null)\n\n if (!email) {\n return {\n author: args.defaultUserId != null ? { field, value: args.defaultUserId } : null,\n skippedNoEmail: { name, sourceId: wpUser.id },\n }\n }\n\n if (args.dryRun) {\n return { author: null, imported: { sourceId: wpUser.id, targetId: 'dry-run', title: name } }\n }\n\n // Reuse an existing user with the same email if present.\n const { docs } = await findDocs(payload, {\n collection: args.usersSlug,\n where: { email: { equals: email } },\n limit: 1,\n depth: 0,\n })\n let userId = docs[0]?.id as number | string | undefined\n\n if (!userId) {\n const created = await createDoc(payload, {\n collection: args.usersSlug,\n data: {\n email,\n name,\n password: crypto.randomBytes(18).toString('hex'),\n },\n })\n userId = created.id\n }\n\n await saveRecord(payload, {\n jobId: args.jobId,\n site: args.site,\n sourceId: wpUser.id,\n sourceType: 'author',\n targetCollection: args.usersSlug,\n targetId: userId,\n })\n return {\n author: { field, value: userId },\n imported: { sourceId: wpUser.id, targetId: userId, title: name },\n }\n }\n\n // strategy === 'authors'\n const field = 'author' as const\n if (existing) {\n return { author: { field, value: existing } }\n }\n if (args.dryRun) {\n return { author: null, imported: { sourceId: wpUser.id, targetId: 'dry-run', title: name } }\n }\n\n const avatar = avatarUrl(wpUser)\n let pictureId: null | string = null\n if (avatar) {\n const result = await importImage(payload, {\n cache: args.imageCache,\n dryRun: args.dryRun,\n fetchImpl: args.fetchImpl,\n jobId: args.jobId,\n mediaSlug: args.mediaSlug,\n site: args.site,\n timeoutMs: args.timeoutMs,\n url: avatar,\n })\n pictureId = result.mediaId\n }\n\n const created = await createDoc(payload, {\n collection: args.authorsSlug,\n data: {\n name,\n ...(pictureId ? { picture: coerceId(pictureId) } : {}),\n ...(wpUser.description ? { biography: decodeEntities(wpUser.description) } : {}),\n },\n })\n const authorId = created.id\n\n await saveRecord(payload, {\n jobId: args.jobId,\n site: args.site,\n sourceId: wpUser.id,\n sourceType: 'author',\n targetCollection: args.authorsSlug,\n targetId: authorId,\n })\n return {\n author: { field, value: authorId },\n imported: { sourceId: wpUser.id, targetId: authorId, title: name },\n }\n}\n","/**\n * Normalizes an id for use as a relationship/upload value. Import records store\n * ids as text, but numeric-id database adapters (e.g. SQLite/Postgres) reject a\n * stringified number in relationship validation — so coerce all-digit strings\n * back to numbers.\n */\nexport const coerceId = (id: number | string): number | string =>\n typeof id === 'number' ? id : /^\\d+$/.test(id) ? Number(id) : id\n","/** Pure URL/string helpers used by the WordPress importer. All side-effect free (unit-tested). */\n\n/** Lower-cased host of a URL, or `null` when it can't be parsed. */\nexport const hostOf = (url: string): null | string => {\n try {\n return new URL(url).host.toLowerCase()\n } catch {\n return null\n }\n}\n\n/** The path (no host, no query/hash) of a URL, always starting with `/`. */\nexport const pathOf = (url: string): string => {\n try {\n return new URL(url).pathname || '/'\n } catch {\n // Already a path.\n const [pathAndQuery] = url.split('#')\n const [path] = pathAndQuery.split('?')\n return path.startsWith('/') ? path : `/${path}`\n }\n}\n\n/** Whether `url` points at the same host as the WordPress site. Relative URLs count as internal. */\nexport const isInternalUrl = (url: string, siteHost: string): boolean => {\n if (!url) {\n return false\n }\n if (url.startsWith('#') || url.startsWith('mailto:') || url.startsWith('tel:')) {\n return false\n }\n const host = hostOf(url)\n if (host === null) {\n // Relative link → internal to the site.\n return true\n }\n return host === siteHost.toLowerCase()\n}\n\n/**\n * Extracts the final path segment of a WordPress permalink as a candidate slug.\n * Handles trailing slashes and `/YYYY/MM/slug/` date-based permalinks.\n */\nexport const permalinkToSlug = (url: string): null | string => {\n const path = pathOf(url).replace(/\\/+$/, '')\n if (!path || path === '') {\n return null\n }\n const segments = path.split('/').filter(Boolean)\n const last = segments[segments.length - 1]\n return last ? decodeURIComponent(last) : null\n}\n\n/**\n * Derives the original (full-size) image URL from a WordPress-resized URL by\n * stripping the `-<width>x<height>` suffix WordPress appends before the\n * extension (e.g. `photo-1024x768.jpg` → `photo.jpg`). Returns the input\n * unchanged when no such suffix is present.\n */\nexport const deriveOriginalImageUrl = (url: string): string => {\n const [beforeHash] = url.split('#')\n const [path, query] = beforeHash.split('?')\n const original = path.replace(/-\\d+x\\d+(\\.[a-zA-Z0-9]+)$/, '$1')\n return query ? `${original}?${query}` : original\n}\n\n/** Basename of a URL path, used as the uploaded filename. */\nexport const filenameOf = (url: string): string => {\n const path = pathOf(url)\n const base = path.split('/').filter(Boolean).pop() ?? 'image'\n return decodeURIComponent(base) || 'image'\n}\n\n/** Named HTML entities WordPress commonly emits (beyond numeric references). */\nconst NAMED_ENTITIES: Record<string, string> = {\n agrave: 'à',\n amp: '&',\n apos: \"'\",\n bdquo: '„',\n bull: '•',\n ccedil: 'ç',\n copy: '©',\n deg: '°',\n eacute: 'é',\n ecirc: 'ê',\n egrave: 'è',\n gt: '>',\n hellip: '…',\n laquo: '«',\n ldquo: '“',\n lsaquo: '‹',\n lsquo: '‘',\n lt: '<',\n mdash: '—',\n middot: '·',\n nbsp: ' ',\n ndash: '–',\n quot: '\"',\n raquo: '»',\n rdquo: '”',\n reg: '®',\n rsaquo: '›',\n rsquo: '’',\n sbquo: '‚',\n trade: '™',\n}\n\n/**\n * Decodes the HTML entities WordPress emits in titles/excerpts: all numeric\n * references (`&#8217;`, `&#x2019;`) plus the common named ones (`&rsquo;`,\n * `&hellip;`, …). Unknown named entities are left as-is. Because `.replace`\n * never rescans replaced output, `&amp;rsquo;` correctly stays `&rsquo;`.\n */\nexport const decodeEntities = (value: string): string =>\n value\n .replace(/&#x([0-9a-f]+);/gi, (_, hex: string) => String.fromCodePoint(parseInt(hex, 16)))\n .replace(/&#(\\d+);/g, (_, dec: string) => String.fromCodePoint(Number(dec)))\n .replace(/&([a-zA-Z]+);/g, (match, name: string) => NAMED_ENTITIES[name.toLowerCase()] ?? match)\n .trim()\n\n/** Strips HTML tags (for excerpt → plain-text SEO description). */\nexport const stripHtml = (html: string): string =>\n decodeEntities(html.replace(/<[^>]*>/g, ' ').replace(/\\s+/g, ' ')).trim()\n","import type { Payload } from 'payload'\n\n/**\n * Loosely-typed wrappers around the Payload Local API. This plugin operates on\n * collection slugs the host configures at runtime, so the generated\n * `CollectionSlug` unions don't apply — these helpers centralize the casts\n * instead of scattering them across every call site.\n */\n\nexport type AnyDoc = { id: number | string; [key: string]: unknown }\n\ntype CreateArgs = {\n collection: string\n data: Record<string, unknown>\n file?: { data: Buffer; mimetype: string; name: string; size: number }\n overrideAccess?: boolean\n}\n\ntype FindArgs = {\n collection: string\n depth?: number\n limit?: number\n overrideAccess?: boolean\n select?: Record<string, unknown>\n where?: unknown\n}\n\nexport const createDoc = (payload: Payload, args: CreateArgs): Promise<AnyDoc> =>\n (payload.create as (a: unknown) => Promise<AnyDoc>)({ overrideAccess: true, ...args })\n\nexport const findDocs = (\n payload: Payload,\n args: FindArgs,\n): Promise<{ docs: AnyDoc[]; totalDocs: number }> =>\n (payload.find as (a: unknown) => Promise<{ docs: AnyDoc[]; totalDocs: number }>)({\n overrideAccess: true,\n ...args,\n })\n\nexport const countDocs = (\n payload: Payload,\n args: { collection: string; overrideAccess?: boolean; where?: unknown },\n): Promise<{ totalDocs: number }> =>\n (payload.count as (a: unknown) => Promise<{ totalDocs: number }>)({\n overrideAccess: true,\n ...args,\n })\n\nexport const findDoc = (\n payload: Payload,\n args: { collection: string; depth?: number; id: number | string; overrideAccess?: boolean },\n): Promise<AnyDoc> =>\n (payload.findByID as (a: unknown) => Promise<AnyDoc>)({ overrideAccess: true, ...args })\n\nexport const updateDoc = (\n payload: Payload,\n args: {\n collection: string\n context?: Record<string, unknown>\n data: Record<string, unknown>\n id: number | string\n overrideAccess?: boolean\n },\n): Promise<AnyDoc> =>\n (payload.update as (a: unknown) => Promise<AnyDoc>)({ overrideAccess: true, ...args })\n","import type { Payload } from 'payload'\n\nimport { RECORDS_SLUG } from '../defaults.js'\nimport { createDoc, findDocs } from './payloadOps.js'\n\nexport type SourceType = 'author' | 'category' | 'media' | 'post'\n\nexport type RecordLookup = {\n site: string\n sourceId?: null | number\n sourceKey?: null | string\n sourceType: SourceType\n}\n\nexport type SaveRecordArgs = RecordLookup & {\n error?: string\n jobId: number | string\n status?: 'done' | 'failed'\n targetCollection?: string\n targetId?: null | number | string\n}\n\n/**\n * Finds a completed import record for a source entity. Media are matched by\n * `sourceKey` (the original image URL) so an image reused across posts is only\n * uploaded once; everything else is matched by `sourceId`. Returns the mapped\n * target id (as a string) or `null`.\n *\n * Reads/writes deliberately omit `req` so each commits independently — a crash\n * mid-import leaves earlier work durable and the run resumes from these records.\n */\nexport const findDoneRecord = async (\n payload: Payload,\n lookup: RecordLookup,\n): Promise<null | string> => {\n const where =\n lookup.sourceType === 'media' && lookup.sourceKey\n ? {\n and: [\n { site: { equals: lookup.site } },\n { sourceType: { equals: 'media' } },\n { sourceKey: { equals: lookup.sourceKey } },\n { status: { equals: 'done' } },\n ],\n }\n : {\n and: [\n { site: { equals: lookup.site } },\n { sourceType: { equals: lookup.sourceType } },\n { sourceId: { equals: lookup.sourceId } },\n { status: { equals: 'done' } },\n ],\n }\n\n const { docs } = await findDocs(payload, {\n collection: RECORDS_SLUG,\n where,\n limit: 1,\n depth: 0,\n })\n\n const doc = docs[0] as undefined | { targetId?: null | string }\n return doc?.targetId != null ? String(doc.targetId) : null\n}\n\n/** Upserts an import record (used to mark an entity done or failed). */\nexport const saveRecord = async (payload: Payload, args: SaveRecordArgs): Promise<void> => {\n await createDoc(payload, {\n collection: RECORDS_SLUG,\n data: {\n job: args.jobId,\n site: args.site,\n sourceType: args.sourceType,\n sourceId: args.sourceId ?? undefined,\n sourceKey: args.sourceKey ?? undefined,\n targetCollection: args.targetCollection,\n targetId: args.targetId != null ? String(args.targetId) : undefined,\n status: args.status ?? 'done',\n error: args.error,\n },\n })\n}\n","import type { Payload } from 'payload'\n\nimport { createDoc } from './payloadOps.js'\nimport { deriveOriginalImageUrl, filenameOf } from './url.js'\nimport { findDoneRecord, saveRecord } from './records.js'\n\nexport type ImageImportResult = {\n error?: string\n mediaId: null | string\n reused: boolean\n uploaded: boolean\n}\n\nexport type ImportImageArgs = {\n alt?: string\n /** Preferred canonical key for dedupe (defaults to the derived original URL). */\n cache: Map<string, ImageImportResult>\n dryRun: boolean\n fetchImpl?: typeof fetch\n jobId: number | string\n mediaSlug: string\n site: string\n /** WordPress media id, when known. */\n sourceId?: number\n timeoutMs: number\n url: string\n}\n\nconst download = async (\n url: string,\n timeoutMs: number,\n fetchImpl: typeof fetch,\n): Promise<{ buffer: Buffer; mimeType: string }> => {\n const controller = new AbortController()\n const timer = setTimeout(() => controller.abort(), timeoutMs)\n try {\n const res = await fetchImpl(url, { signal: controller.signal })\n if (!res.ok) {\n throw new Error(`image download failed: ${res.status}`)\n }\n const arrayBuffer = await res.arrayBuffer()\n const mimeType = res.headers.get('content-type')?.split(';')[0] || 'image/jpeg'\n return { buffer: Buffer.from(arrayBuffer), mimeType }\n } finally {\n clearTimeout(timer)\n }\n}\n\n/**\n * Imports one image, uploading the original (full-size) version and reusing an\n * already-imported copy. Dedupe is by the derived original URL: within a run via\n * `cache`, across runs via `wp-import-records`. In dry-run mode it resolves\n * reuse but performs no download or write.\n */\nexport const importImage = async (\n payload: Payload,\n args: ImportImageArgs,\n): Promise<ImageImportResult> => {\n const fetchImpl = args.fetchImpl ?? fetch\n const canonical = deriveOriginalImageUrl(args.url)\n\n const cached = args.cache.get(canonical)\n if (cached) {\n return { ...cached, reused: true, uploaded: false }\n }\n\n // Already imported by a previous run?\n const existing = await findDoneRecord(payload, {\n site: args.site,\n sourceKey: canonical,\n sourceType: 'media',\n })\n if (existing) {\n const result: ImageImportResult = { mediaId: existing, reused: true, uploaded: false }\n args.cache.set(canonical, result)\n return result\n }\n\n if (args.dryRun) {\n // Report intent without writing; mark cached so the same image is planned once.\n const result: ImageImportResult = { mediaId: null, reused: false, uploaded: true }\n args.cache.set(canonical, result)\n return result\n }\n\n try {\n // Prefer the original; fall back to the (possibly resized) URL WordPress gave us.\n let downloaded\n try {\n downloaded = await download(canonical, args.timeoutMs, fetchImpl)\n } catch {\n downloaded = await download(args.url, args.timeoutMs, fetchImpl)\n }\n\n const created = await createDoc(payload, {\n collection: args.mediaSlug,\n data: { alt: args.alt || filenameOf(canonical) },\n file: {\n data: downloaded.buffer,\n mimetype: downloaded.mimeType,\n name: filenameOf(canonical),\n size: downloaded.buffer.length,\n },\n })\n\n const mediaId = String(created.id)\n await saveRecord(payload, {\n jobId: args.jobId,\n site: args.site,\n sourceId: args.sourceId ?? null,\n sourceKey: canonical,\n sourceType: 'media',\n targetCollection: args.mediaSlug,\n targetId: mediaId,\n })\n\n const result: ImageImportResult = { mediaId, reused: false, uploaded: true }\n args.cache.set(canonical, result)\n return result\n } catch (error) {\n return {\n error: error instanceof Error ? error.message : String(error),\n mediaId: null,\n reused: false,\n uploaded: false,\n }\n }\n}\n","import type { Payload } from 'payload'\n\nimport type { ImportError, ImportedItem } from '../types.js'\nimport type { WPCategory } from './wpTypes.js'\n\nimport { coerceId } from './id.js'\nimport { createDoc } from './payloadOps.js'\nimport { decodeEntities } from './url.js'\nimport { findDoneRecord, saveRecord } from './records.js'\n\n/**\n * Orders categories so every parent precedes its children (WordPress `parent`\n * is `0` for roots). Cycles/ophans are appended at the end. Pure — unit-tested.\n */\nexport const sortCategoriesParentsFirst = (categories: WPCategory[]): WPCategory[] => {\n const byId = new Map(categories.map((c) => [c.id, c]))\n const sorted: WPCategory[] = []\n const placed = new Set<number>()\n\n const place = (cat: WPCategory, stack: Set<number>): void => {\n if (placed.has(cat.id) || stack.has(cat.id)) {\n return\n }\n stack.add(cat.id)\n const parent = cat.parent && cat.parent !== 0 ? byId.get(cat.parent) : undefined\n if (parent) {\n place(parent, stack)\n }\n stack.delete(cat.id)\n if (!placed.has(cat.id)) {\n placed.add(cat.id)\n sorted.push(cat)\n }\n }\n\n for (const cat of categories) {\n place(cat, new Set())\n }\n return sorted\n}\n\nexport type ImportCategoriesArgs = {\n categories: WPCategory[]\n categoriesSlug: string\n dryRun: boolean\n jobId: number | string\n site: string\n}\n\nexport type ImportCategoriesResult = {\n errors: ImportError[]\n imported: ImportedItem[]\n /** WordPress category id → Payload category id. */\n idMap: Map<number, number | string>\n}\n\n/** Imports categories preserving hierarchy; idempotent via import records. */\nexport const importCategories = async (\n payload: Payload,\n args: ImportCategoriesArgs,\n): Promise<ImportCategoriesResult> => {\n const idMap = new Map<number, number | string>()\n const imported: ImportedItem[] = []\n const errors: ImportError[] = []\n const ordered = sortCategoriesParentsFirst(args.categories)\n\n for (const cat of ordered) {\n try {\n const existing = await findDoneRecord(payload, {\n site: args.site,\n sourceId: cat.id,\n sourceType: 'category',\n })\n if (existing) {\n idMap.set(cat.id, coerceId(existing))\n continue\n }\n\n const name = decodeEntities(cat.name ?? cat.slug ?? `category-${cat.id}`)\n\n if (args.dryRun) {\n imported.push({ sourceId: cat.id, targetId: 'dry-run', title: name })\n continue\n }\n\n const parentId = cat.parent && cat.parent !== 0 ? idMap.get(cat.parent) : undefined\n\n const created = await createDoc(payload, {\n collection: args.categoriesSlug,\n data: {\n name,\n ...(cat.slug ? { slug: cat.slug } : {}),\n ...(parentId != null ? { parent: coerceId(parentId) } : {}),\n ...(cat.description ? { description: decodeEntities(cat.description) } : {}),\n },\n })\n\n const rawId = created.id\n idMap.set(cat.id, rawId)\n imported.push({ sourceId: cat.id, targetId: rawId, title: name })\n await saveRecord(payload, {\n jobId: args.jobId,\n site: args.site,\n sourceId: cat.id,\n sourceType: 'category',\n targetCollection: args.categoriesSlug,\n targetId: rawId,\n })\n } catch (error) {\n errors.push({\n message: error instanceof Error ? error.message : String(error),\n scope: 'category',\n sourceId: cat.id,\n })\n }\n }\n\n return { errors, idMap, imported }\n}\n","import type { SanitizedServerEditorConfig } from '@payloadcms/richtext-lexical'\n\nimport { convertHTMLToLexical } from '@payloadcms/richtext-lexical'\nimport { JSDOM } from 'jsdom'\n\nimport type { LinkMapping } from '../types.js'\nimport type { ImageImportResult } from './media.js'\nimport type { LexNode } from './lexical.js'\n\nimport { imageToken, replaceImageTokens, rewriteLinkNodes } from './lexical.js'\n\nexport type BuildContentArgs = {\n articleUrl: (slug?: null | string) => string\n editorConfig: SanitizedServerEditorConfig\n html: string\n /** Uploads (or plans) a content image and returns the resulting media id. */\n importContentImage: (src: string) => Promise<ImageImportResult>\n mediaSlug: string\n /** Resolves an internal WordPress link to an imported article slug, or null. */\n resolveInternal: (url: string, slug: null | string) => null | string\n siteHost: string\n}\n\nexport type BuildContentResult = {\n content: { root: LexNode }\n images: Array<{ result: ImageImportResult; src: string }>\n links: LinkMapping[]\n}\n\n/**\n * Converts a WordPress post's rendered HTML into a Lexical editor state:\n * uploads in-content images (dedup-aware) and turns them into upload nodes,\n * and rewrites internal links that point at imported posts. Images are first\n * swapped for block-level text tokens so they survive HTML→Lexical conversion\n * at their original position, then replaced with upload nodes afterwards.\n */\nexport const buildContent = async (args: BuildContentArgs): Promise<BuildContentResult> => {\n const dom = new JSDOM(`<!DOCTYPE html><body>${args.html}</body>`)\n const { document } = dom.window\n const images: Array<{ result: ImageImportResult; src: string }> = []\n const tokenToMedia = new Map<number, null | string>()\n\n const imgs = Array.from(document.querySelectorAll('img'))\n let index = 0\n for (const img of imgs) {\n const src = img.getAttribute('src') || ''\n if (!src) {\n img.remove()\n continue\n }\n\n const result = await args.importContentImage(src)\n images.push({ result, src })\n\n const token = index\n tokenToMedia.set(token, result.mediaId)\n index += 1\n\n // Choose the block to replace: prefer an enclosing <figure>, else an\n // <a> that only wraps this image, else the image itself.\n let target: Element = img\n const anchor = img.parentElement\n if (anchor && anchor.tagName === 'A' && anchor.childNodes.length === 1) {\n target = anchor\n }\n const figure = target.closest('figure')\n if (figure) {\n target = figure\n }\n\n const placeholder = document.createElement('p')\n placeholder.textContent = imageToken(token)\n target.replaceWith(placeholder)\n }\n\n const modifiedHtml = document.body.innerHTML\n\n const state = convertHTMLToLexical({\n editorConfig: args.editorConfig,\n html: modifiedHtml,\n JSDOM: JSDOM as unknown as new (html: string) => { window: { document: Document } },\n }) as unknown as { root: LexNode }\n\n replaceImageTokens(state.root, (i) => tokenToMedia.get(i) ?? null, args.mediaSlug)\n\n const links = rewriteLinkNodes(state.root, {\n articleUrl: args.articleUrl,\n resolveInternal: args.resolveInternal,\n siteHost: args.siteHost,\n })\n\n return { content: state, images, links }\n}\n","import type { LinkMapping } from '../types.js'\n\nimport { coerceId } from './id.js'\nimport { isInternalUrl, permalinkToSlug } from './url.js'\n\n/** Loosely-typed serialized Lexical node (we only touch a few well-known shapes). */\nexport type LexNode = {\n children?: LexNode[]\n fields?: Record<string, unknown>\n tag?: string\n text?: string\n type: string\n [key: string]: unknown\n}\n\nexport type LexRoot = { root: LexNode }\n\n/**\n * Block-level placeholder inserted in place of each `<img>` before HTML→Lexical\n * conversion. It is unlikely to appear in real content and survives conversion\n * as a paragraph containing a single text node, which `replaceImageTokens`\n * then swaps for an upload node.\n */\nexport const imageToken = (index: number): string => `⁣WPIMG:${index}⁣`\n\nconst IMAGE_TOKEN_RE = /^⁣WPIMG:(\\d+)⁣$/\n\n/** Extracts `src` attributes of every `<img>` in an HTML string (order-preserving). */\nexport const extractImageSrcs = (html: string): string[] => {\n const srcs: string[] = []\n const re = /<img\\b[^>]*?\\bsrc\\s*=\\s*([\"'])(.*?)\\1/gi\n let match: null | RegExpExecArray\n while ((match = re.exec(html)) !== null) {\n srcs.push(match[2])\n }\n return srcs\n}\n\n/** Builds a serialized Lexical upload (decorator block) node for a media doc. */\nexport const buildUploadNode = (value: number | string, relationTo: string): LexNode => ({\n type: 'upload',\n fields: null as unknown as Record<string, unknown>,\n format: '',\n relationTo,\n value: coerceId(value),\n version: 3,\n})\n\n/** Depth-first walk over a serialized tree, invoking `visit` on every node. */\nexport const walk = (node: LexNode, visit: (node: LexNode) => void): void => {\n visit(node)\n if (Array.isArray(node.children)) {\n for (const child of node.children) {\n walk(child, visit)\n }\n }\n}\n\n/** Returns the sole text of a node if it is a paragraph wrapping one text node. */\nconst soleTextTokenIndex = (node: LexNode): null | number => {\n if (node.type !== 'paragraph' || !Array.isArray(node.children) || node.children.length !== 1) {\n return null\n }\n const child = node.children[0]\n if (child.type !== 'text' || typeof child.text !== 'string') {\n return null\n }\n const m = IMAGE_TOKEN_RE.exec(child.text.trim())\n return m ? Number(m[1]) : null\n}\n\n/**\n * Replaces token paragraphs (created by `imageToken`) with upload nodes.\n * `resolve(index)` returns the uploaded media id for that image, or `null` to\n * drop the placeholder. Mutates and returns the same root.\n */\nexport const replaceImageTokens = (\n root: LexNode,\n resolve: (index: number) => null | number | string,\n mediaSlug: string,\n): LexNode => {\n const replaceIn = (parent: LexNode): void => {\n if (!Array.isArray(parent.children)) {\n return\n }\n const next: LexNode[] = []\n for (const child of parent.children) {\n const index = soleTextTokenIndex(child)\n if (index !== null) {\n const mediaId = resolve(index)\n if (mediaId !== null && mediaId !== undefined) {\n next.push(buildUploadNode(mediaId, mediaSlug))\n }\n continue\n }\n replaceIn(child)\n next.push(child)\n }\n parent.children = next\n }\n replaceIn(root)\n return root\n}\n\n/**\n * Finds, removes and returns the value of the first upload node in document\n * order, or `null` when the tree has none. Used to promote a leading content\n * image to the cover field when the post has no featured image.\n */\nexport const takeFirstUploadNode = (root: LexNode): null | number | string => {\n const search = (parent: LexNode): null | number | string => {\n if (!Array.isArray(parent.children)) {\n return null\n }\n for (let i = 0; i < parent.children.length; i += 1) {\n const child = parent.children[i]\n if (child.type === 'upload') {\n parent.children.splice(i, 1)\n return (child as { value?: number | string }).value ?? null\n }\n const nested = search(child)\n if (nested !== null) {\n return nested\n }\n }\n return null\n }\n return search(root)\n}\n\nconst isEmptyParagraph = (node: LexNode): boolean =>\n node.type === 'paragraph' &&\n (!Array.isArray(node.children) ||\n node.children.every((child) => child.type === 'text' && !(child.text ?? '').trim()))\n\n/**\n * Drops a leading duplicate of the cover image: when the first non-empty block\n * is an upload of `value`, it is removed so the hero doesn't render twice\n * (once as the cover, once at the top of the content).\n */\nexport const removeLeadingUploadNode = (root: LexNode, value: number | string): boolean => {\n const children = root.children\n if (!Array.isArray(children)) {\n return false\n }\n for (let i = 0; i < children.length; i += 1) {\n const child = children[i]\n if (isEmptyParagraph(child)) {\n continue\n }\n if (\n child.type === 'upload' &&\n String((child as { value?: unknown }).value) === String(value)\n ) {\n children.splice(i, 1)\n return true\n }\n return false\n }\n return false\n}\n\nexport type LinkRewriteOptions = {\n articleUrl: (slug?: null | string) => string\n siteHost: string\n /** Resolves a WordPress permalink/slug to an imported article slug, or null. */\n resolveInternal: (url: string, slug: null | string) => null | string\n}\n\n/**\n * Rewrites internal `<a>` links whose target was imported and records every\n * internal link for the report. External links and unresolved internal links\n * are left untouched. Returns the collected link mappings.\n */\nexport const rewriteLinkNodes = (root: LexNode, options: LinkRewriteOptions): LinkMapping[] => {\n const { articleUrl, resolveInternal, siteHost } = options\n const links: LinkMapping[] = []\n\n walk(root, (node) => {\n if (node.type !== 'link' || !node.fields) {\n return\n }\n const url = typeof node.fields.url === 'string' ? node.fields.url : ''\n if (!url || !isInternalUrl(url, siteHost)) {\n return\n }\n const slug = permalinkToSlug(url)\n const targetSlug = resolveInternal(url, slug)\n if (targetSlug) {\n const to = articleUrl(targetSlug)\n node.fields.url = to\n node.fields.linkType = 'custom'\n links.push({ action: 'rewritten', from: url, to })\n } else {\n links.push({ action: 'unresolved', from: url })\n }\n })\n\n return links\n}\n","import type { SanitizedServerEditorConfig } from '@payloadcms/richtext-lexical'\nimport type { Field, Payload, RichTextField } from 'payload'\n\nimport { editorConfigFactory } from '@payloadcms/richtext-lexical'\n\n/** Recursively finds a named richText field within a field tree. */\nconst findRichTextField = (fields: Field[], name: string): RichTextField | undefined => {\n for (const field of fields) {\n if (field.type === 'richText' && 'name' in field && field.name === name) {\n return field as RichTextField\n }\n if ('fields' in field && Array.isArray(field.fields)) {\n const nested = findRichTextField(field.fields, name)\n if (nested) {\n return nested\n }\n }\n if (field.type === 'tabs' && Array.isArray(field.tabs)) {\n for (const tab of field.tabs) {\n const nested = findRichTextField(tab.fields, name)\n if (nested) {\n return nested\n }\n }\n }\n }\n return undefined\n}\n\n/**\n * Resolves the sanitized Lexical editor config for the target article content\n * field, so HTML→Lexical conversion uses exactly the features that field\n * accepts. Falls back to the config's default editor when the field can't be\n * located.\n */\nexport const resolveEditorConfig = async (\n payload: Payload,\n articlesSlug: string,\n contentFieldName: string,\n): Promise<SanitizedServerEditorConfig> => {\n const collections = payload.collections as unknown as Record<\n string,\n { config: { fields: Field[] } } | undefined\n >\n const collection = collections[articlesSlug]\n const field = collection\n ? findRichTextField(collection.config.fields, contentFieldName)\n : undefined\n\n if (field) {\n return editorConfigFactory.fromField({ field })\n }\n\n return editorConfigFactory.default({ config: payload.config })\n}\n","import type { WPPost } from './wpTypes.js'\n\n/** The primary category of a post — WordPress core has no \"primary\", so the first assigned. */\nexport const selectPrimaryCategoryId = (post: WPPost): null | number =>\n Array.isArray(post.categories) && post.categories.length > 0 ? post.categories[0] : null\n\n/** Best publish date for a post as an ISO string (prefers GMT). */\nexport const publishDate = (post: WPPost): string | undefined => {\n if (post.date_gmt) {\n // WordPress GMT dates omit the trailing Z.\n const value = post.date_gmt.endsWith('Z') ? post.date_gmt : `${post.date_gmt}Z`\n const date = new Date(value)\n return Number.isNaN(date.getTime()) ? undefined : date.toISOString()\n }\n if (post.date) {\n const date = new Date(post.date)\n return Number.isNaN(date.getTime()) ? undefined : date.toISOString()\n }\n return undefined\n}\n","import type { Payload } from 'payload'\n\nimport { countDocs, createDoc } from './payloadOps.js'\n\nexport type CreateRedirectArgs = {\n articleId: number | string\n articlesSlug: string\n from: string\n}\n\n/**\n * Creates a 301 redirect (via @payloadcms/plugin-redirects' `redirects`\n * collection) from an old WordPress path to an imported article, unless one\n * already exists or the collection isn't installed. Returns whether a redirect\n * was created.\n */\nexport const createRedirect = async (\n payload: Payload,\n args: CreateRedirectArgs,\n): Promise<boolean> => {\n if (!payload.collections.redirects) {\n return false\n }\n\n const { totalDocs } = await countDocs(payload, {\n collection: 'redirects',\n where: { from: { equals: args.from } },\n })\n if (totalDocs > 0) {\n return false\n }\n\n await createDoc(payload, {\n collection: 'redirects',\n data: {\n from: args.from,\n to: {\n type: 'reference',\n reference: { relationTo: args.articlesSlug, value: args.articleId },\n },\n },\n })\n return true\n}\n","import type {\n ImportedItem,\n ImportError,\n ImportProgress,\n ImportReport,\n LinkMapping,\n RunSummary,\n} from '../types.js'\n\nexport const emptyProgress = (): ImportProgress => ({\n currentPhase: 'queued',\n cursorPage: 0,\n importedAuthors: 0,\n importedCategories: 0,\n importedMedia: 0,\n importedPosts: 0,\n linksRewritten: 0,\n linksUnresolved: 0,\n redirectsCreated: 0,\n reusedMedia: 0,\n skippedPosts: 0,\n failedPosts: 0,\n totalPosts: 0,\n})\n\nexport const emptyReport = (dryRun: boolean): ImportReport => ({\n dryRun,\n errors: [],\n imported: { authors: [], categories: [], media: [], posts: [] },\n links: [],\n remaining: { posts: 0 },\n})\n\n/** Shape of the report fields persisted on a `wp-import-jobs` document. */\nexport type PersistedJobReports = {\n authorsReport?: null | { imported?: ImportedItem[] }\n categoriesReport?: null | { imported?: ImportedItem[] }\n errorsReport?: null | { errors?: ImportError[] }\n linksReport?: null | { links?: LinkMapping[] }\n mediaReport?: null | { imported?: ImportedItem[] }\n postsReport?: null | { imported?: ImportedItem[] }\n runs?: null | RunSummary[]\n}\n\n/**\n * Rebuilds the in-memory report from a job's persisted step reports, so a\n * resume/retry keeps the history of what earlier runs imported. Entries tagged\n * with a dry run are dropped (they were plans, not imports), and the next run\n * number is derived from the run history.\n */\nexport const rehydrateReport = (\n job: PersistedJobReports,\n dryRun: boolean,\n): { previousRuns: RunSummary[]; report: ImportReport; runNumber: number } => {\n const previousRuns = Array.isArray(job.runs) ? job.runs : []\n const dryRunNumbers = new Set(previousRuns.filter((r) => r.dryRun).map((r) => r.run))\n const keep = <T extends { run?: number }>(items?: null | T[]): T[] =>\n (items ?? []).filter((item) => item.run === undefined || !dryRunNumbers.has(item.run))\n\n const report = emptyReport(dryRun)\n report.imported.authors = keep(job.authorsReport?.imported)\n report.imported.categories = keep(job.categoriesReport?.imported)\n report.imported.media = keep(job.mediaReport?.imported)\n report.imported.posts = keep(job.postsReport?.imported)\n report.links = keep(job.linksReport?.links)\n report.errors = keep(job.errorsReport?.errors)\n\n const runNumber = previousRuns.reduce((max, r) => Math.max(max, r.run), 0) + 1\n return { previousRuns, report, runNumber }\n}\n","import type { RequestOptions } from '../types.js'\nimport type { WPCategory, WPMedia, WPPost, WPUser } from './wpTypes.js'\n\n/** Normalizes a site URL into its `/wp-json/wp/v2` REST base (no trailing slash). */\nexport const restBase = (siteUrl: string): string => {\n const trimmed = siteUrl.trim().replace(/\\/+$/, '')\n return `${trimmed}/wp-json/wp/v2`\n}\n\n/** WordPress user + application password (Users → Profile → Application Passwords). */\nexport type WPCredentials = {\n applicationPassword?: null | string\n username?: null | string\n}\n\nexport type WPClient = {\n /** Whether requests carry Basic auth (credentials were provided). */\n authenticated: boolean\n fetchCategories: () => Promise<WPCategory[]>\n fetchMedia: (id: number) => Promise<null | WPMedia>\n fetchPostsPage: (args: {\n after?: string\n before?: string\n page: number\n perPage: number\n }) => Promise<{ posts: WPPost[]; totalPages: number }>\n fetchUser: (id: number) => Promise<null | WPUser>\n}\n\nexport class WPRequestError extends Error {\n status: number\n constructor(message: string, status: number) {\n super(message)\n this.name = 'WPRequestError'\n this.status = status\n }\n}\n\nexport const createWPClient = (\n siteUrl: string,\n request: Pick<Required<RequestOptions>, 'timeoutMs'> &\n Pick<RequestOptions, 'userAgent'> & { credentials?: null | WPCredentials },\n fetchImpl: typeof fetch = fetch,\n): WPClient => {\n const base = restBase(siteUrl)\n\n const headers: Record<string, string> = { Accept: 'application/json' }\n if (request.userAgent) {\n headers['User-Agent'] = request.userAgent\n }\n\n // WordPress application passwords authenticate via HTTP Basic auth, which\n // unlocks non-public data (e.g. author emails via ?context=edit).\n const { applicationPassword, username } = request.credentials ?? {}\n const authenticated = Boolean(username && applicationPassword)\n if (authenticated) {\n headers.Authorization = `Basic ${Buffer.from(`${username}:${applicationPassword}`).toString('base64')}`\n }\n\n const get = async (path: string): Promise<{ body: unknown; totalPages: number }> => {\n const controller = new AbortController()\n const timer = setTimeout(() => controller.abort(), request.timeoutMs)\n try {\n const res = await fetchImpl(`${base}${path}`, { headers, signal: controller.signal })\n if (!res.ok) {\n throw new WPRequestError(`WordPress request failed: ${res.status} ${path}`, res.status)\n }\n const totalPages = Number(res.headers.get('X-WP-TotalPages') ?? '1') || 1\n const body = await res.json()\n return { body, totalPages }\n } finally {\n clearTimeout(timer)\n }\n }\n\n return {\n authenticated,\n fetchPostsPage: async ({ after, before, page, perPage }) => {\n const params = new URLSearchParams({\n _embed: '1',\n page: String(page),\n per_page: String(perPage),\n status: 'publish',\n })\n if (after) {\n params.set('after', after)\n }\n if (before) {\n params.set('before', before)\n }\n const { body, totalPages } = await get(`/posts?${params.toString()}`)\n return { posts: (body as WPPost[]) ?? [], totalPages }\n },\n fetchCategories: async () => {\n const all: WPCategory[] = []\n let page = 1\n let totalPages = 1\n do {\n const { body, totalPages: tp } = await get(`/categories?per_page=100&page=${page}`)\n all.push(...((body as WPCategory[]) ?? []))\n totalPages = tp\n page += 1\n } while (page <= totalPages)\n return all\n },\n fetchMedia: async (id) => {\n try {\n const { body } = await get(`/media/${id}`)\n return body as WPMedia\n } catch {\n return null\n }\n },\n fetchUser: async (id) => {\n // context=edit exposes non-public fields (email) but needs auth.\n if (authenticated) {\n try {\n const { body } = await get(`/users/${id}?context=edit`)\n return body as WPUser\n } catch {\n // Fall through to the public representation.\n }\n }\n try {\n const { body } = await get(`/users/${id}`)\n return body as WPUser\n } catch {\n return null\n }\n },\n }\n}\n","import type { Payload } from 'payload'\n\nimport type { ImportProgress, ImportReport, ResolvedOptions, RunSummary } from '../types.js'\nimport type { ImageImportResult } from '../lib/media.js'\nimport type { PersistedJobReports } from '../lib/report.js'\nimport type { WPPost, WPUser } from '../lib/wpTypes.js'\n\nimport { JOBS_SLUG } from '../defaults.js'\nimport { resolveAuthor } from '../lib/authors.js'\nimport { importCategories } from '../lib/categories.js'\nimport { buildContent } from '../lib/content.js'\nimport { coerceId } from '../lib/id.js'\nimport { resolveEditorConfig } from '../lib/editorConfig.js'\nimport { importImage } from '../lib/media.js'\nimport { removeLeadingUploadNode, takeFirstUploadNode } from '../lib/lexical.js'\nimport { createDoc, findDoc, findDocs, updateDoc } from '../lib/payloadOps.js'\nimport { publishDate, selectPrimaryCategoryId } from '../lib/post.js'\nimport { createRedirect } from '../lib/redirects.js'\nimport { emptyProgress, rehydrateReport } from '../lib/report.js'\nimport { findDoneRecord, saveRecord } from '../lib/records.js'\nimport { createWPClient } from '../lib/wpClient.js'\nimport { decodeEntities, hostOf, pathOf, permalinkToSlug, stripHtml } from '../lib/url.js'\n\nconst PER_PAGE = 100\n// Matches SEO_DESCRIPTION_MAX_LENGTH in the shared-components SEO defaults.\nconst SEO_DESCRIPTION_MAX = 150\n\nexport type RunImportArgs = {\n fetchImpl?: typeof fetch\n jobId: number | string\n options: ResolvedOptions\n}\n\ntype JobDoc = PersistedJobReports & {\n credentials?: null | { applicationPassword?: null | string; username?: null | string }\n dateFrom?: null | string\n dateTo?: null | string\n dryRun?: boolean | null\n limit?: null | number\n sourceUrl: string\n}\n\n/**\n * Executes one import run for a `wp-import-jobs` document. Idempotent and\n * resumable: every entity is checked against `wp-import-records` and skipped if\n * already imported, and writes intentionally omit `req` so each commits\n * independently. In dry-run mode it samples the first page(s) and writes\n * nothing, producing the same report describing what a real run would do.\n */\nexport const runImport = async (payload: Payload, args: RunImportArgs): Promise<ImportReport> => {\n const { options } = args\n const { collections: slugs } = options\n const progress: ImportProgress = emptyProgress()\n\n const job = (await findDoc(payload, {\n collection: JOBS_SLUG,\n id: args.jobId,\n depth: 0,\n })) as unknown as JobDoc\n\n const dryRun = Boolean(job.dryRun)\n // Resume/retry: start from what earlier runs reported (dry-run entries are\n // dropped), and tag everything new with this run's number.\n const { previousRuns, report, runNumber } = rehydrateReport(job, dryRun)\n const runSummary: RunSummary = {\n dryRun,\n run: runNumber,\n startedAt: new Date().toISOString(),\n status: 'running',\n }\n const runs: RunSummary[] = [...previousRuns, runSummary]\n const site = hostOf(job.sourceUrl) ?? job.sourceUrl\n const imageCache = new Map<string, ImageImportResult>()\n\n // Per-step report slices, persisted onto the job's step tabs.\n const stepReports = (): Record<string, unknown> => ({\n authorsReport: { imported: report.imported.authors },\n categoriesReport: { imported: report.imported.categories },\n errorsReport: { dryRun: report.dryRun, errors: report.errors },\n linksReport: { links: report.links },\n mediaReport: { imported: report.imported.media, reused: progress.reusedMedia },\n postsReport: {\n dryRun: report.dryRun,\n imported: report.imported.posts,\n remaining: report.remaining.posts,\n },\n runs,\n })\n\n const updateJob = async (data: Record<string, unknown>): Promise<void> => {\n await updateDoc(payload, {\n collection: JOBS_SLUG,\n id: args.jobId,\n data,\n context: { wpImport: true },\n })\n }\n\n const accountImage = (result: ImageImportResult, sourceId: number): void => {\n if (result.error) {\n report.errors.push({ message: result.error, run: runNumber, scope: 'media', sourceId })\n } else if (result.uploaded) {\n progress.importedMedia += 1\n report.imported.media.push({\n run: runNumber,\n sourceId,\n targetId: result.mediaId ?? 'dry-run',\n })\n } else if (result.reused) {\n progress.reusedMedia += 1\n }\n }\n\n try {\n progress.currentPhase = 'running'\n await updateJob({\n status: 'running',\n startedAt: new Date().toISOString(),\n progress,\n ...stepReports(),\n })\n\n const editorConfig = await resolveEditorConfig(payload, slugs.articles, options.fieldMap.content)\n const client = createWPClient(\n job.sourceUrl,\n {\n credentials: job.credentials,\n timeoutMs: options.request.timeoutMs,\n userAgent: options.request.userAgent,\n },\n args.fetchImpl,\n )\n\n // ---- Categories (full hierarchy) ----\n progress.currentPhase = 'categories'\n const wpCategories = await client.fetchCategories()\n const categoriesResult = await importCategories(payload, {\n categories: wpCategories,\n categoriesSlug: slugs.categories,\n dryRun,\n jobId: args.jobId,\n site,\n })\n const categoryIdMap = categoriesResult.idMap\n report.imported.categories.push(\n ...categoriesResult.imported.map((item) => ({ ...item, run: runNumber })),\n )\n report.errors.push(...categoriesResult.errors.map((error) => ({ ...error, run: runNumber })))\n progress.importedCategories = categoriesResult.imported.length\n await updateJob({ progress, ...stepReports() })\n\n // ---- Gather posts (two-pass: collect for full link resolution, then import) ----\n progress.currentPhase = 'posts'\n const after = job.dateFrom ? new Date(job.dateFrom).toISOString() : undefined\n const before = job.dateTo ? new Date(job.dateTo).toISOString() : undefined\n const maxPages = dryRun ? options.dryRunPageLimit : Number.POSITIVE_INFINITY\n const limit = job.limit ?? undefined\n\n const gathered: WPPost[] = []\n let page = 1\n let totalPages = 1\n do {\n const { posts, totalPages: tp } = await client.fetchPostsPage({ after, before, page, perPage: PER_PAGE })\n totalPages = tp\n gathered.push(...posts)\n progress.cursorPage = page\n page += 1\n } while (page <= totalPages && page <= maxPages && (!limit || gathered.length < limit))\n\n const postsToImport = limit ? gathered.slice(0, limit) : gathered\n progress.totalPosts = postsToImport.length\n\n // Known slugs (this run + already-imported) for internal-link resolution.\n const existingArticles = await findDocs(payload, {\n collection: slugs.articles,\n depth: 0,\n limit: 100000,\n select: { slug: true },\n })\n const knownSlugs = new Set<string>(\n existingArticles.docs.map((d) => (d as { slug?: string }).slug).filter(Boolean) as string[],\n )\n const slugByPath = new Map<string, string>()\n for (const p of postsToImport) {\n if (p.slug) {\n knownSlugs.add(p.slug)\n if (p.link) {\n slugByPath.set(pathOf(p.link), p.slug)\n }\n }\n }\n const resolveInternal = (url: string, slug: null | string): null | string => {\n const byPath = slugByPath.get(pathOf(url))\n if (byPath) {\n return byPath\n }\n const candidate = slug ?? permalinkToSlug(url)\n return candidate && knownSlugs.has(candidate) ? candidate : null\n }\n\n // With credentials, author details (incl. email) can be fetched via\n // ?context=edit — cached per WP user id across posts.\n const authorDetailCache = new Map<number, null | WPUser>()\n const enrichAuthor = async (embedded?: WPUser): Promise<undefined | WPUser> => {\n if (!embedded || embedded.email || !client.authenticated) {\n return embedded\n }\n if (!authorDetailCache.has(embedded.id)) {\n authorDetailCache.set(embedded.id, await client.fetchUser(embedded.id))\n }\n const detailed = authorDetailCache.get(embedded.id)\n return detailed?.email ? { ...embedded, email: detailed.email } : embedded\n }\n\n // ---- Import posts ----\n for (const post of postsToImport) {\n const permalinkPath = post.link ? pathOf(post.link) : `/?p=${post.id}`\n try {\n const already = await findDoneRecord(payload, { site, sourceId: post.id, sourceType: 'post' })\n if (already) {\n progress.skippedPosts += 1\n continue\n }\n\n // Featured image. Embeds can be stripped or error stubs (deleted or\n // private media), so fall back to the media endpoint.\n let coverId: null | string = null\n let featured = post._embedded?.['wp:featuredmedia']?.[0]\n if (!featured?.source_url && post.featured_media) {\n featured = (await client.fetchMedia(post.featured_media)) ?? undefined\n }\n if (featured?.source_url) {\n const result = await importImage(payload, {\n alt: featured.alt_text,\n cache: imageCache,\n dryRun,\n fetchImpl: args.fetchImpl,\n jobId: args.jobId,\n mediaSlug: slugs.media,\n site,\n sourceId: featured.id,\n timeoutMs: options.request.timeoutMs,\n url: featured.source_url,\n })\n coverId = result.mediaId\n accountImage(result, featured.id)\n }\n\n // Content: images + internal links.\n const built = await buildContent({\n articleUrl: options.articleUrl,\n editorConfig,\n html: post.content?.rendered ?? '',\n importContentImage: (src) =>\n importImage(payload, {\n cache: imageCache,\n dryRun,\n fetchImpl: args.fetchImpl,\n jobId: args.jobId,\n mediaSlug: slugs.media,\n site,\n timeoutMs: options.request.timeoutMs,\n url: src,\n }),\n mediaSlug: slugs.media,\n resolveInternal,\n siteHost: site,\n })\n for (const img of built.images) {\n accountImage(img.result, post.id)\n }\n report.links.push(...built.links.map((link) => ({ ...link, run: runNumber })))\n for (const link of built.links) {\n if (link.action === 'rewritten') {\n progress.linksRewritten += 1\n } else if (link.action === 'unresolved') {\n progress.linksUnresolved += 1\n }\n }\n\n // Cover handling: promote the first content image when there is no\n // featured image, and drop a leading duplicate of the cover so the\n // hero doesn't render twice.\n if (!coverId && options.firstImageAsCover) {\n const promoted = takeFirstUploadNode(built.content.root)\n if (promoted != null) {\n coverId = String(promoted)\n }\n } else if (coverId) {\n removeLeadingUploadNode(built.content.root, coverId)\n }\n\n // Author.\n const {\n author,\n imported: importedAuthor,\n skippedNoEmail,\n } = await resolveAuthor(payload, {\n authorsSlug: slugs.authors,\n defaultUserId: options.authorMapping.defaultUserId,\n dryRun,\n fetchImpl: args.fetchImpl,\n imageCache,\n jobId: args.jobId,\n mediaSlug: slugs.media,\n site,\n strategy: options.authorMapping.strategy,\n syntheticEmailDomain: options.authorMapping.syntheticEmailDomain,\n timeoutMs: options.request.timeoutMs,\n usersSlug: slugs.users,\n wpUser: await enrichAuthor(post._embedded?.author?.[0]),\n })\n if (importedAuthor) {\n progress.importedAuthors += 1\n report.imported.authors.push({ ...importedAuthor, run: runNumber })\n }\n if (\n skippedNoEmail &&\n !report.errors.some(\n (e) => e.scope === 'author' && e.sourceId === skippedNoEmail.sourceId,\n )\n ) {\n report.errors.push({\n message: `author \"${skippedNoEmail.name}\" has no email exposed by WordPress; user creation skipped (set authorMapping.syntheticEmailDomain or defaultUserId)`,\n run: runNumber,\n scope: 'author',\n sourceId: skippedNoEmail.sourceId,\n })\n }\n\n // Assemble article data.\n const title = decodeEntities(post.title?.rendered ?? post.slug ?? `post-${post.id}`)\n const primaryCategory = selectPrimaryCategoryId(post)\n const categoryId = primaryCategory != null ? categoryIdMap.get(primaryCategory) : undefined\n const data: Record<string, unknown> = {\n [options.fieldMap.title]: title,\n [options.fieldMap.content]: built.content,\n _status: 'published',\n }\n if (post.slug) {\n data[options.fieldMap.slug] = post.slug\n }\n if (coverId) {\n data[options.fieldMap.coverImage] = coerceId(coverId)\n }\n if (categoryId != null) {\n data[options.fieldMap.category] = coerceId(categoryId)\n }\n const date = publishDate(post)\n if (date) {\n data[options.fieldMap.publishedAt] = date\n }\n if (author) {\n data[author.field] = coerceId(author.value)\n }\n // SEO meta: title from the post title, image from the cover image,\n // description from the excerpt (when enabled). Silently ignored by\n // Payload when the target collection has no `meta` group.\n const meta: Record<string, unknown> = { title }\n if (coverId) {\n meta.image = coerceId(coverId)\n }\n if (options.excerptToSeoDescription && post.excerpt?.rendered) {\n meta.description = stripHtml(post.excerpt.rendered).slice(0, SEO_DESCRIPTION_MAX)\n }\n data.meta = meta\n\n if (dryRun) {\n report.imported.posts.push({\n run: runNumber,\n slug: post.slug,\n sourceId: post.id,\n targetId: 'dry-run',\n title,\n })\n progress.importedPosts += 1\n continue\n }\n\n const created = await createDoc(payload, {\n collection: slugs.articles,\n data,\n })\n const articleId = created.id\n await saveRecord(payload, {\n jobId: args.jobId,\n site,\n sourceId: post.id,\n sourceKey: permalinkPath,\n sourceType: 'post',\n targetCollection: slugs.articles,\n targetId: articleId,\n })\n report.imported.posts.push({\n run: runNumber,\n slug: post.slug,\n sourceId: post.id,\n targetId: articleId,\n title,\n })\n progress.importedPosts += 1\n\n // Redirect old permalink → new article.\n if (options.redirects) {\n const made = await createRedirect(payload, {\n articleId: coerceId(articleId),\n articlesSlug: slugs.articles,\n from: permalinkPath,\n })\n if (made) {\n progress.redirectsCreated += 1\n report.links.push({\n action: 'redirect',\n from: permalinkPath,\n run: runNumber,\n to: options.articleUrl(post.slug),\n })\n }\n }\n\n if (progress.importedPosts % 5 === 0) {\n await updateJob({ progress, ...stepReports() })\n }\n } catch (error) {\n progress.failedPosts += 1\n const message = error instanceof Error ? error.message : String(error)\n report.errors.push({ message, run: runNumber, scope: 'post', sourceId: post.id })\n if (!dryRun) {\n await saveRecord(payload, {\n error: message,\n jobId: args.jobId,\n site,\n sourceId: post.id,\n sourceType: 'post',\n status: 'failed',\n }).catch(() => undefined)\n }\n }\n }\n\n report.remaining.posts = Math.max(0, gathered.length - postsToImport.length)\n progress.currentPhase = 'done'\n runSummary.finishedAt = new Date().toISOString()\n runSummary.progress = { ...progress }\n runSummary.status = 'completed'\n await updateJob({\n finishedAt: runSummary.finishedAt,\n progress,\n status: 'completed',\n ...stepReports(),\n })\n return report\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n report.errors.push({ message, run: runNumber, scope: 'run' })\n progress.currentPhase = 'failed'\n runSummary.finishedAt = new Date().toISOString()\n runSummary.progress = { ...progress }\n runSummary.status = 'failed'\n await updateJob({\n finishedAt: runSummary.finishedAt,\n progress,\n status: 'failed',\n ...stepReports(),\n })\n return report\n }\n}\n","import type { TaskConfig } from 'payload'\n\nimport type { ResolvedOptions } from '../types.js'\n\nimport { TASK_SLUG } from '../defaults.js'\nimport { runImport } from './runImport.js'\n\n/**\n * Registers the `importWordpress` jobs-queue task. The handler is thin — it\n * loads the job document (by id) and delegates to `runImport`, which owns all\n * fetching, transformation, idempotency and reporting.\n */\nexport const importWordpressTask = (options: ResolvedOptions): TaskConfig<'inline'> =>\n ({\n slug: TASK_SLUG,\n handler: async ({ input, req }: { input: { jobId: number | string }; req: { payload: import('payload').Payload } }) => {\n await runImport(req.payload, { jobId: input.jobId, options })\n return { output: {} }\n },\n inputSchema: [{ name: 'jobId', type: 'text', required: true }],\n }) as unknown as TaskConfig<'inline'>\n","import type { Config } from 'payload'\n\nimport type { ComposiusPayloadPluginImportWordpressConfig } from './types.js'\n\nimport { ImportJobs } from './collections/ImportJobs.js'\nimport { ImportRecords } from './collections/ImportRecords.js'\nimport { resolveOptions } from './defaults.js'\nimport { startEndpoint, statusEndpoint } from './endpoints/index.js'\nimport { importWordpressTask } from './jobs/task.js'\n\nexport type { ComposiusPayloadPluginImportWordpressConfig } from './types.js'\nexport type { ImportProgress, ImportReport } from './types.js'\n\nconst LOG_PREFIX = '@composius/payload-plugin-import-wordpress'\n\n/**\n * Imports WordPress posts (via the REST API) into a target content collection —\n * by default the `@composius/payload-plugin-articles` `articles` collection —\n * along with their categories, authors, featured and in-content images. Images\n * are uploaded once and resized by the media collection; internal links are\n * rewritten and the rest get 301 redirects. Runs on the jobs queue and is\n * idempotent + resumable, writing a full report onto each job document.\n */\nexport const ComposiusPayloadPluginImportWordpress =\n (pluginOptions: ComposiusPayloadPluginImportWordpressConfig = {}) =>\n async (config: Config): Promise<Config> => {\n if (!config.collections) {\n config.collections = []\n }\n\n const options = resolveOptions(pluginOptions)\n // Warnings are deferred to onInit, where payload.logger is available.\n const warnings: string[] = []\n\n // Always register collections so the database schema stays consistent for\n // migrations, even when the plugin is disabled.\n config.collections.push(ImportJobs({ access: options.access }))\n config.collections.push(ImportRecords({ access: options.access }))\n\n // Register the import task so queued jobs can run (schema/queue consistency).\n config.jobs = {\n ...config.jobs,\n tasks: [...(config.jobs?.tasks ?? []), importWordpressTask(options)],\n }\n\n if (pluginOptions.disabled) {\n return config\n }\n\n // Endpoints for programmatic triggering / polling.\n config.endpoints = [\n ...(config.endpoints ?? []),\n startEndpoint(options.access),\n statusEndpoint(options.access),\n ]\n\n // Optional auto-run schedule so creating a job runs it without an external worker.\n if (pluginOptions.autoRun !== false) {\n const schedule = typeof pluginOptions.autoRun === 'object' ? pluginOptions.autoRun : {}\n const entry = { cron: schedule.cron ?? '* * * * *', queue: schedule.queue ?? 'default' }\n const existing = config.jobs.autoRun\n if (existing === undefined) {\n config.jobs.autoRun = [entry]\n } else if (Array.isArray(existing)) {\n config.jobs.autoRun = [...existing, entry]\n } else {\n warnings.push('`jobs.autoRun` is a function; skipping the plugin auto-run schedule.')\n }\n }\n\n // Apply @payloadcms/plugin-redirects (optional peer) for internal-link\n // redirects. Dynamically imported so hosts that disable redirects (or don't\n // install the plugin) aren't forced to depend on it.\n if (options.redirects) {\n try {\n const { redirectsPlugin } = await import('@payloadcms/plugin-redirects')\n // The target collection(s) become the `to.reference` relationTo.\n config = redirectsPlugin({\n collections: [options.collections.articles],\n })(config) as Config\n } catch {\n warnings.push(\n '`redirects` is enabled but `@payloadcms/plugin-redirects` is not installed; redirects will be skipped.',\n )\n }\n }\n\n if (warnings.length > 0) {\n const incomingOnInit = config.onInit\n config.onInit = async (payload) => {\n if (incomingOnInit) {\n await incomingOnInit(payload)\n }\n for (const warning of warnings) {\n payload.logger.warn(`[${LOG_PREFIX}] ${warning}`)\n }\n }\n }\n\n return config\n }\n"],"mappings":"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","names":["field","created","authenticated"]}
1
+ {"version":3,"sources":["../src/defaults.ts","../src/translations/en.ts","../src/translations/fr.ts","../src/translations/index.ts","../src/collections/ImportJobs.ts","../src/collections/ImportRecords.ts","../src/endpoints/index.ts","../src/lib/authors.ts","../src/lib/id.ts","../src/lib/url.ts","../src/lib/payloadOps.ts","../src/lib/records.ts","../src/lib/media.ts","../src/lib/categories.ts","../src/lib/content.ts","../src/lib/lexical.ts","../src/lib/editorConfig.ts","../src/lib/post.ts","../src/lib/redirects.ts","../src/lib/report.ts","../src/lib/wpClient.ts","../src/jobs/runImport.ts","../src/jobs/task.ts","../src/index.ts"],"sourcesContent":["import type { Access } from 'payload'\n\nimport type { ComposiusPayloadPluginImportWordpressConfig, ResolvedOptions } from './types.js'\n\nexport const anyone: Access = () => true\n\nexport const authenticated: Access = ({ req: { user } }) => Boolean(user)\n\nexport const defaultArticleUrl = (slug?: null | string): string =>\n `${process.env.NEXT_PUBLIC_SERVER_URL || 'http://localhost:3000'}/articles/${slug ?? ''}`\n\n/** Slug of the collection storing import jobs (the \"form\" + report surface). */\nexport const JOBS_SLUG = 'wp-import-jobs'\n/** Slug of the collection storing source→target mappings for idempotency. */\nexport const RECORDS_SLUG = 'wp-import-records'\n/** Job task slug registered on the Payload jobs queue. */\nexport const TASK_SLUG = 'importWordpress'\n\n/** Merges user options with defaults into a fully-resolved options object. */\nexport const resolveOptions = (\n pluginOptions: ComposiusPayloadPluginImportWordpressConfig,\n): ResolvedOptions => ({\n access: {\n create: pluginOptions.access?.create ?? authenticated,\n delete: pluginOptions.access?.delete ?? authenticated,\n read: pluginOptions.access?.read ?? authenticated,\n update: pluginOptions.access?.update ?? authenticated,\n },\n articleUrl: pluginOptions.articleUrl ?? defaultArticleUrl,\n authorMapping: {\n strategy: pluginOptions.authorMapping?.strategy ?? 'users',\n defaultUserId: pluginOptions.authorMapping?.defaultUserId,\n syntheticEmailDomain: pluginOptions.authorMapping?.syntheticEmailDomain ?? 'imported.invalid',\n },\n collections: {\n articles: pluginOptions.collections?.articles ?? 'articles',\n categories: pluginOptions.collections?.categories ?? 'categories',\n media: pluginOptions.collections?.media ?? 'media',\n authors: pluginOptions.collections?.authors ?? 'authors',\n users: pluginOptions.collections?.users ?? 'users',\n },\n dryRunPageLimit: pluginOptions.dryRunPageLimit ?? 1,\n excerptToSeoDescription: pluginOptions.excerptToSeoDescription ?? true,\n firstImageAsCover: pluginOptions.firstImageAsCover ?? true,\n fieldMap: {\n title: pluginOptions.fieldMap?.title ?? 'title',\n slug: pluginOptions.fieldMap?.slug ?? 'slug',\n content: pluginOptions.fieldMap?.content ?? 'content',\n coverImage: pluginOptions.fieldMap?.coverImage ?? 'coverImage',\n category: pluginOptions.fieldMap?.category ?? 'category',\n publishedAt: pluginOptions.fieldMap?.publishedAt ?? 'publishedAt',\n },\n redirects: pluginOptions.redirects ?? true,\n request: {\n concurrency: pluginOptions.request?.concurrency ?? 5,\n timeoutMs: pluginOptions.request?.timeoutMs ?? 30000,\n userAgent: pluginOptions.request?.userAgent,\n },\n})\n","export const en = {\n jobs: {\n singular: 'WordPress import',\n plural: 'WordPress imports',\n tabs: {\n configuration: 'Configuration',\n authors: 'Authors',\n categories: 'Categories',\n media: 'Media',\n posts: 'Posts',\n links: 'Links & redirects',\n report: 'Report',\n },\n fields: {\n sourceUrl: 'WordPress site URL',\n sourceUrlDescription:\n 'Base URL of the WordPress site, e.g. https://example.com — its REST API (/wp-json) is read.',\n credentials: 'Credentials (optional)',\n credentialsDescription:\n 'Optional WordPress user + application password. When set, requests are authenticated so non-public data (e.g. author emails) can be imported.',\n username: 'Username',\n applicationPassword: 'Application password',\n applicationPasswordDescription:\n 'Create one in WordPress under Users → Profile → Application Passwords. Stored on this document — delete the job (or clear this field) after the import.',\n dateFrom: 'From date',\n dateTo: 'To date',\n limit: 'Max posts',\n limitDescription: 'Optional cap on the number of posts imported in this run.',\n dryRun: 'Dry run',\n dryRunDescription:\n 'Preview only: report what would be imported without writing anything. Limited to the first page(s).',\n resume: 'Resume / retry',\n resumeDescription: 'Re-queue this job to continue where it stopped (already-imported items are skipped).',\n status: 'Status',\n progress: 'Progress',\n runs: 'Run history',\n authorsReport: 'Imported authors',\n categoriesReport: 'Imported categories',\n mediaReport: 'Imported media',\n postsReport: 'Imported posts',\n linksReport: 'Link mapping',\n errorsReport: 'Errors',\n startedAt: 'Started at',\n finishedAt: 'Finished at',\n },\n status: {\n queued: 'Queued',\n running: 'Running',\n paused: 'Paused',\n completed: 'Completed',\n failed: 'Failed',\n },\n },\n records: {\n singular: 'WordPress import record',\n plural: 'WordPress import records',\n fields: {\n job: 'Import job',\n site: 'Site',\n sourceType: 'Source type',\n sourceId: 'Source ID',\n sourceKey: 'Source key',\n targetCollection: 'Target collection',\n targetId: 'Target ID',\n status: 'Status',\n error: 'Error',\n },\n },\n}\n","import type { Translation } from './index.js'\n\nexport const fr: Translation = {\n jobs: {\n singular: 'Import WordPress',\n plural: 'Imports WordPress',\n tabs: {\n configuration: 'Configuration',\n authors: 'Auteurs',\n categories: 'Catégories',\n media: 'Médias',\n posts: 'Articles',\n links: 'Liens et redirections',\n report: 'Rapport',\n },\n fields: {\n sourceUrl: 'URL du site WordPress',\n sourceUrlDescription:\n 'URL de base du site WordPress, ex. https://example.com — son API REST (/wp-json) est lue.',\n credentials: 'Identifiants (optionnel)',\n credentialsDescription:\n 'Utilisateur WordPress + mot de passe d’application optionnels. Une fois définis, les requêtes sont authentifiées pour importer des données non publiques (ex. e-mails des auteurs).',\n username: 'Nom d’utilisateur',\n applicationPassword: 'Mot de passe d’application',\n applicationPasswordDescription:\n 'À créer dans WordPress sous Utilisateurs → Profil → Mots de passe d’application. Stocké sur ce document — supprimez le travail (ou videz ce champ) après l’import.',\n dateFrom: 'À partir du',\n dateTo: \"Jusqu'au\",\n limit: 'Nombre max. d’articles',\n limitDescription: 'Limite optionnelle du nombre d’articles importés lors de cette exécution.',\n dryRun: 'Simulation',\n dryRunDescription:\n 'Aperçu uniquement : indique ce qui serait importé sans rien écrire. Limité à la ou les premières pages.',\n resume: 'Reprendre / réessayer',\n resumeDescription:\n 'Remettre ce travail en file pour continuer là où il s’est arrêté (les éléments déjà importés sont ignorés).',\n status: 'Statut',\n progress: 'Progression',\n runs: 'Historique des exécutions',\n authorsReport: 'Auteurs importés',\n categoriesReport: 'Catégories importées',\n mediaReport: 'Médias importés',\n postsReport: 'Articles importés',\n linksReport: 'Correspondance des liens',\n errorsReport: 'Erreurs',\n startedAt: 'Démarré à',\n finishedAt: 'Terminé à',\n },\n status: {\n queued: 'En file',\n running: 'En cours',\n paused: 'En pause',\n completed: 'Terminé',\n failed: 'Échoué',\n },\n },\n records: {\n singular: 'Enregistrement d’import WordPress',\n plural: 'Enregistrements d’import WordPress',\n fields: {\n job: 'Travail d’import',\n site: 'Site',\n sourceType: 'Type de source',\n sourceId: 'ID source',\n sourceKey: 'Clé source',\n targetCollection: 'Collection cible',\n targetId: 'ID cible',\n status: 'Statut',\n error: 'Erreur',\n },\n },\n}\n","import { en } from './en.js'\nimport { fr } from './fr.js'\n\nexport type Translation = typeof en\n\n/** Builds a Payload label record ({ en, fr }) from a translation key selector. */\nexport const label = (pick: (t: Translation) => string): Record<string, string> => ({\n en: pick(en),\n fr: pick(fr),\n})\n","import type { CollectionConfig, PayloadRequest } from 'payload'\n\nimport type { ImportAccess } from '../types.js'\n\nimport { TASK_SLUG } from '../defaults.js'\nimport { label } from '../translations/index.js'\n\nexport type ImportJobsOptions = {\n access: Required<ImportAccess>\n}\n\n/** Queues the import task for a job document (task-slug not in generated types → loose cast). */\nconst queueImport = async (req: PayloadRequest, jobId: number | string): Promise<void> => {\n const queue = req.payload.jobs.queue as unknown as (args: {\n input: { jobId: number | string }\n req?: PayloadRequest\n task: string\n }) => Promise<unknown>\n await queue({ input: { jobId }, req, task: TASK_SLUG })\n}\n\n/**\n * The import \"form\" and report surface. Creating a document queues an import\n * run (via the jobs queue); the task writes `status`, `progress` and `report`\n * back onto the same document. Toggling `resume` re-queues a stopped run.\n */\nexport const ImportJobs = ({ access }: ImportJobsOptions): CollectionConfig => ({\n slug: 'wp-import-jobs',\n labels: {\n singular: label((t) => t.jobs.singular),\n plural: label((t) => t.jobs.plural),\n },\n admin: {\n useAsTitle: 'sourceUrl',\n defaultColumns: ['sourceUrl', 'status', 'dryRun', 'updatedAt'],\n group: 'WordPress import',\n },\n access: {\n read: access.read,\n create: access.create,\n update: access.update,\n delete: access.delete,\n },\n hooks: {\n afterChange: [\n async ({ context, doc, operation, req }) => {\n // Updates coming from the importer itself must not re-queue the job.\n if (context?.wpImport) {\n return doc\n }\n\n if (operation === 'create') {\n await queueImport(req, doc.id as number | string)\n return doc\n }\n\n // A user toggled \"resume\" on an existing job → re-queue and clear the flag.\n if (operation === 'update' && doc.resume) {\n await req.payload.update({\n collection: 'wp-import-jobs',\n id: doc.id as number | string,\n data: { resume: false, status: 'queued' },\n context: { wpImport: true },\n req,\n })\n await queueImport(req, doc.id as number | string)\n }\n\n return doc\n },\n ],\n },\n fields: [\n // Unnamed tabs keep their fields at the top level of the document data —\n // one tab per import step, so each step's outcome reads in its own tab.\n {\n type: 'tabs',\n tabs: [\n {\n label: label((t) => t.jobs.tabs.configuration),\n fields: [\n {\n name: 'sourceUrl',\n type: 'text',\n label: label((t) => t.jobs.fields.sourceUrl),\n required: true,\n admin: {\n description: label((t) => t.jobs.fields.sourceUrlDescription),\n },\n },\n {\n name: 'credentials',\n type: 'group',\n label: label((t) => t.jobs.fields.credentials),\n admin: {\n description: label((t) => t.jobs.fields.credentialsDescription),\n },\n fields: [\n {\n type: 'row',\n fields: [\n {\n name: 'username',\n type: 'text',\n label: label((t) => t.jobs.fields.username),\n admin: { width: '50%' },\n },\n {\n name: 'applicationPassword',\n type: 'text',\n label: label((t) => t.jobs.fields.applicationPassword),\n admin: {\n width: '50%',\n description: label((t) => t.jobs.fields.applicationPasswordDescription),\n components: {\n // Masked (•••) input instead of plain text.\n Field:\n '@composius/payload-plugin-import-wordpress/client#ApplicationPasswordFieldClient',\n },\n },\n },\n ],\n },\n ],\n },\n {\n type: 'row',\n fields: [\n {\n name: 'dateFrom',\n type: 'date',\n label: label((t) => t.jobs.fields.dateFrom),\n admin: { width: '50%', date: { pickerAppearance: 'dayOnly' } },\n },\n {\n name: 'dateTo',\n type: 'date',\n label: label((t) => t.jobs.fields.dateTo),\n admin: { width: '50%', date: { pickerAppearance: 'dayOnly' } },\n },\n ],\n },\n {\n name: 'limit',\n type: 'number',\n label: label((t) => t.jobs.fields.limit),\n min: 1,\n admin: {\n description: label((t) => t.jobs.fields.limitDescription),\n },\n },\n {\n name: 'dryRun',\n type: 'checkbox',\n label: label((t) => t.jobs.fields.dryRun),\n defaultValue: false,\n admin: {\n description: label((t) => t.jobs.fields.dryRunDescription),\n },\n },\n {\n name: 'resume',\n type: 'checkbox',\n label: label((t) => t.jobs.fields.resume),\n defaultValue: false,\n admin: {\n description: label((t) => t.jobs.fields.resumeDescription),\n },\n },\n ],\n },\n {\n label: label((t) => t.jobs.tabs.authors),\n fields: [\n {\n name: 'authorsReport',\n type: 'json',\n label: label((t) => t.jobs.fields.authorsReport),\n admin: { readOnly: true },\n },\n ],\n },\n {\n label: label((t) => t.jobs.tabs.categories),\n fields: [\n {\n name: 'categoriesReport',\n type: 'json',\n label: label((t) => t.jobs.fields.categoriesReport),\n admin: { readOnly: true },\n },\n ],\n },\n {\n label: label((t) => t.jobs.tabs.media),\n fields: [\n {\n name: 'mediaReport',\n type: 'json',\n label: label((t) => t.jobs.fields.mediaReport),\n admin: { readOnly: true },\n },\n ],\n },\n {\n label: label((t) => t.jobs.tabs.posts),\n fields: [\n {\n name: 'postsReport',\n type: 'json',\n label: label((t) => t.jobs.fields.postsReport),\n admin: { readOnly: true },\n },\n ],\n },\n {\n label: label((t) => t.jobs.tabs.links),\n fields: [\n {\n name: 'linksReport',\n type: 'json',\n label: label((t) => t.jobs.fields.linksReport),\n admin: { readOnly: true },\n },\n ],\n },\n {\n label: label((t) => t.jobs.tabs.report),\n fields: [\n {\n name: 'runs',\n type: 'json',\n label: label((t) => t.jobs.fields.runs),\n admin: { readOnly: true },\n },\n {\n name: 'progress',\n type: 'json',\n label: label((t) => t.jobs.fields.progress),\n admin: { readOnly: true },\n },\n {\n name: 'errorsReport',\n type: 'json',\n label: label((t) => t.jobs.fields.errorsReport),\n admin: { readOnly: true },\n },\n ],\n },\n ],\n },\n {\n name: 'status',\n type: 'select',\n label: label((t) => t.jobs.fields.status),\n defaultValue: 'queued',\n options: [\n { label: label((t) => t.jobs.status.queued), value: 'queued' },\n { label: label((t) => t.jobs.status.running), value: 'running' },\n { label: label((t) => t.jobs.status.paused), value: 'paused' },\n { label: label((t) => t.jobs.status.completed), value: 'completed' },\n { label: label((t) => t.jobs.status.failed), value: 'failed' },\n ],\n admin: {\n position: 'sidebar',\n readOnly: true,\n },\n },\n {\n name: 'startedAt',\n type: 'date',\n label: label((t) => t.jobs.fields.startedAt),\n admin: { position: 'sidebar', readOnly: true, date: { pickerAppearance: 'dayAndTime' } },\n },\n {\n name: 'finishedAt',\n type: 'date',\n label: label((t) => t.jobs.fields.finishedAt),\n admin: { position: 'sidebar', readOnly: true, date: { pickerAppearance: 'dayAndTime' } },\n },\n ],\n})\n","import type { CollectionConfig } from 'payload'\n\nimport type { ImportAccess } from '../types.js'\n\nimport { label } from '../translations/index.js'\n\nexport type ImportRecordsOptions = {\n access: Required<ImportAccess>\n}\n\n/**\n * Source→target mapping rows that make the import idempotent, resumable and\n * image-deduplicating. Before importing anything the task looks up a `done`\n * record for the same `site` + `sourceType` + `sourceId` (or `sourceKey` for\n * media, keyed by the image URL) and skips/reuses it.\n */\nexport const ImportRecords = ({ access }: ImportRecordsOptions): CollectionConfig => ({\n slug: 'wp-import-records',\n labels: {\n singular: label((t) => t.records.singular),\n plural: label((t) => t.records.plural),\n },\n admin: {\n useAsTitle: 'sourceKey',\n defaultColumns: ['site', 'sourceType', 'sourceId', 'targetCollection', 'targetId', 'status'],\n group: 'WordPress import',\n hidden: true,\n },\n access: {\n read: access.read,\n create: access.create,\n update: access.update,\n delete: access.delete,\n },\n indexes: [\n { fields: ['site', 'sourceType', 'sourceId'] },\n { fields: ['site', 'sourceType', 'sourceKey'] },\n ],\n fields: [\n {\n name: 'job',\n type: 'relationship',\n label: label((t) => t.records.fields.job),\n relationTo: 'wp-import-jobs',\n },\n {\n name: 'site',\n type: 'text',\n label: label((t) => t.records.fields.site),\n index: true,\n required: true,\n },\n {\n name: 'sourceType',\n type: 'select',\n label: label((t) => t.records.fields.sourceType),\n options: ['post', 'category', 'author', 'media'],\n index: true,\n required: true,\n },\n {\n name: 'sourceId',\n type: 'number',\n label: label((t) => t.records.fields.sourceId),\n index: true,\n },\n {\n name: 'sourceKey',\n type: 'text',\n label: label((t) => t.records.fields.sourceKey),\n index: true,\n },\n {\n name: 'targetCollection',\n type: 'text',\n label: label((t) => t.records.fields.targetCollection),\n },\n {\n name: 'targetId',\n type: 'text',\n label: label((t) => t.records.fields.targetId),\n },\n {\n name: 'status',\n type: 'select',\n label: label((t) => t.records.fields.status),\n defaultValue: 'done',\n options: ['done', 'failed'],\n },\n {\n name: 'error',\n type: 'text',\n label: label((t) => t.records.fields.error),\n },\n ],\n})\n","import type { Endpoint, PayloadRequest } from 'payload'\n\nimport { APIError } from 'payload'\n\nimport type { ImportAccess } from '../types.js'\n\nimport { JOBS_SLUG } from '../defaults.js'\n\ntype StartBody = {\n dateFrom?: string\n dateTo?: string\n dryRun?: boolean\n limit?: number\n sourceUrl?: string\n}\n\n/** Runs a per-operation access function and throws 403 when it denies. */\nconst assertAccess = async (\n access: Required<ImportAccess>,\n operation: 'create' | 'read',\n req: PayloadRequest,\n): Promise<void> => {\n const result = await access[operation]({ req } as Parameters<Required<ImportAccess>['read']>[0])\n if (!result) {\n throw new APIError('Forbidden', 403)\n }\n}\n\n/**\n * POST /api/wp-import/start — creates a `wp-import-jobs` document (which queues\n * the import via its afterChange hook) and returns the job id. Gated by the\n * plugin's `access.create` option, and again by the collection's create access\n * via `overrideAccess: false`.\n */\nexport const startEndpoint = (access: Required<ImportAccess>): Endpoint => ({\n path: '/wp-import/start',\n method: 'post',\n handler: async (req: PayloadRequest): Promise<Response> => {\n if (!req.user) {\n throw new APIError('Unauthorized', 401)\n }\n await assertAccess(access, 'create', req)\n\n const body = ((await req.json?.()) ?? {}) as StartBody\n if (!body.sourceUrl) {\n return Response.json({ error: 'sourceUrl is required' }, { status: 400 })\n }\n\n const job = await req.payload.create({\n collection: JOBS_SLUG,\n data: {\n dateFrom: body.dateFrom,\n dateTo: body.dateTo,\n dryRun: body.dryRun ?? false,\n limit: body.limit,\n sourceUrl: body.sourceUrl,\n },\n overrideAccess: false,\n req,\n user: req.user,\n })\n\n return Response.json({ jobId: job.id }, { status: 202 })\n },\n})\n\n/**\n * GET /api/wp-import/status/:id — returns the job's status, progress and report.\n * Gated by the plugin's `access.read` option and the collection's read access.\n */\nexport const statusEndpoint = (access: Required<ImportAccess>): Endpoint => ({\n path: '/wp-import/status/:id',\n method: 'get',\n handler: async (req: PayloadRequest): Promise<Response> => {\n if (!req.user) {\n throw new APIError('Unauthorized', 401)\n }\n await assertAccess(access, 'read', req)\n\n const id = req.routeParams?.id as number | string\n const job = (await req.payload.findByID({\n collection: JOBS_SLUG,\n id,\n overrideAccess: false,\n req,\n user: req.user,\n })) as unknown as Record<string, unknown>\n\n return Response.json({\n progress: job.progress,\n report: {\n authors: job.authorsReport,\n categories: job.categoriesReport,\n errors: job.errorsReport,\n links: job.linksReport,\n media: job.mediaReport,\n posts: job.postsReport,\n },\n runs: job.runs,\n status: job.status,\n })\n },\n})\n","import type { Payload } from 'payload'\n\nimport crypto from 'crypto'\n\nimport type { AuthorStrategy, ImportedItem } from '../types.js'\nimport type { ImageImportResult } from './media.js'\nimport type { WPUser } from './wpTypes.js'\n\nimport { coerceId } from './id.js'\nimport { decodeEntities } from './url.js'\nimport { importImage } from './media.js'\nimport { createDoc, findDocs } from './payloadOps.js'\nimport { findDoneRecord, saveRecord } from './records.js'\n\nexport type ResolvedAuthor = {\n /** Article relationship field to assign (`editor` for users, `author` for authors). */\n field: 'author' | 'editor'\n value: number | string\n}\n\nexport type ResolveAuthorArgs = {\n authorsSlug: string\n defaultUserId?: number | string\n dryRun: boolean\n fetchImpl?: typeof fetch\n imageCache: Map<string, ImageImportResult>\n jobId: number | string\n mediaSlug: string\n site: string\n strategy: AuthorStrategy\n /** Domain for synthesized emails, or `false` to skip users without a real email. */\n syntheticEmailDomain: false | string\n timeoutMs: number\n usersSlug: string\n wpUser?: WPUser\n}\n\n/** Highest-resolution avatar URL WordPress exposes, if any. */\nconst avatarUrl = (wpUser: WPUser): string | undefined => {\n const urls = wpUser.avatar_urls\n if (!urls) {\n return undefined\n }\n const sizes = Object.keys(urls)\n .map(Number)\n .filter((n) => !Number.isNaN(n))\n .sort((a, b) => b - a)\n return sizes.length ? urls[String(sizes[0])] : undefined\n}\n\nexport type ResolveAuthorResult = {\n author: null | ResolvedAuthor\n imported?: ImportedItem\n /** Set when a `users`-strategy author had no email and creation was skipped. */\n skippedNoEmail?: { name: string; sourceId: number }\n}\n\n/**\n * Resolves the article author relationship for a post per the configured\n * strategy, importing into `users` (default) or `authors`, or using a fixed\n * user. Idempotent via import records. Returns the imported item (if any new\n * doc was created) alongside the resolved relationship.\n */\nexport const resolveAuthor = async (\n payload: Payload,\n args: ResolveAuthorArgs,\n): Promise<ResolveAuthorResult> => {\n if (args.strategy === 'fixed') {\n return {\n author: args.defaultUserId != null ? { field: 'editor', value: args.defaultUserId } : null,\n }\n }\n\n const wpUser = args.wpUser\n if (!wpUser) {\n return { author: args.defaultUserId != null ? { field: 'editor', value: args.defaultUserId } : null }\n }\n\n const name = decodeEntities(wpUser.name ?? wpUser.slug ?? `author-${wpUser.id}`)\n\n const existing = await findDoneRecord(payload, {\n site: args.site,\n sourceId: wpUser.id,\n sourceType: 'author',\n })\n\n if (args.strategy === 'users') {\n const field = 'editor' as const\n if (existing) {\n return { author: { field, value: existing } }\n }\n // The public REST API rarely exposes emails; synthesize one from the\n // configured domain, or skip user creation when that is disabled.\n const email =\n wpUser.email ||\n (args.syntheticEmailDomain\n ? `${wpUser.slug || `author-${wpUser.id}`}@${args.syntheticEmailDomain}`\n : null)\n\n if (!email) {\n return {\n author: args.defaultUserId != null ? { field, value: args.defaultUserId } : null,\n skippedNoEmail: { name, sourceId: wpUser.id },\n }\n }\n\n if (args.dryRun) {\n return { author: null, imported: { sourceId: wpUser.id, targetId: 'dry-run', title: name } }\n }\n\n // Reuse an existing user with the same email if present.\n const { docs } = await findDocs(payload, {\n collection: args.usersSlug,\n where: { email: { equals: email } },\n limit: 1,\n depth: 0,\n })\n let userId = docs[0]?.id as number | string | undefined\n\n if (!userId) {\n const created = await createDoc(payload, {\n collection: args.usersSlug,\n data: {\n email,\n name,\n password: crypto.randomBytes(18).toString('hex'),\n },\n })\n userId = created.id\n }\n\n await saveRecord(payload, {\n jobId: args.jobId,\n site: args.site,\n sourceId: wpUser.id,\n sourceType: 'author',\n targetCollection: args.usersSlug,\n targetId: userId,\n })\n return {\n author: { field, value: userId },\n imported: { sourceId: wpUser.id, targetId: userId, title: name },\n }\n }\n\n // strategy === 'authors'\n const field = 'author' as const\n if (existing) {\n return { author: { field, value: existing } }\n }\n if (args.dryRun) {\n return { author: null, imported: { sourceId: wpUser.id, targetId: 'dry-run', title: name } }\n }\n\n const avatar = avatarUrl(wpUser)\n let pictureId: null | string = null\n if (avatar) {\n const result = await importImage(payload, {\n cache: args.imageCache,\n dryRun: args.dryRun,\n fetchImpl: args.fetchImpl,\n jobId: args.jobId,\n mediaSlug: args.mediaSlug,\n site: args.site,\n timeoutMs: args.timeoutMs,\n url: avatar,\n })\n pictureId = result.mediaId\n }\n\n const created = await createDoc(payload, {\n collection: args.authorsSlug,\n data: {\n name,\n ...(pictureId ? { picture: coerceId(pictureId) } : {}),\n ...(wpUser.description ? { biography: decodeEntities(wpUser.description) } : {}),\n },\n })\n const authorId = created.id\n\n await saveRecord(payload, {\n jobId: args.jobId,\n site: args.site,\n sourceId: wpUser.id,\n sourceType: 'author',\n targetCollection: args.authorsSlug,\n targetId: authorId,\n })\n return {\n author: { field, value: authorId },\n imported: { sourceId: wpUser.id, targetId: authorId, title: name },\n }\n}\n","/**\n * Normalizes an id for use as a relationship/upload value. Import records store\n * ids as text, but numeric-id database adapters (e.g. SQLite/Postgres) reject a\n * stringified number in relationship validation — so coerce all-digit strings\n * back to numbers.\n */\nexport const coerceId = (id: number | string): number | string =>\n typeof id === 'number' ? id : /^\\d+$/.test(id) ? Number(id) : id\n","/** Pure URL/string helpers used by the WordPress importer. All side-effect free (unit-tested). */\n\n/** Lower-cased host of a URL, or `null` when it can't be parsed. */\nexport const hostOf = (url: string): null | string => {\n try {\n return new URL(url).host.toLowerCase()\n } catch {\n return null\n }\n}\n\n/** The path (no host, no query/hash) of a URL, always starting with `/`. */\nexport const pathOf = (url: string): string => {\n try {\n return new URL(url).pathname || '/'\n } catch {\n // Already a path.\n const [pathAndQuery] = url.split('#')\n const [path] = pathAndQuery.split('?')\n return path.startsWith('/') ? path : `/${path}`\n }\n}\n\n/** Whether `url` points at the same host as the WordPress site. Relative URLs count as internal. */\nexport const isInternalUrl = (url: string, siteHost: string): boolean => {\n if (!url) {\n return false\n }\n if (url.startsWith('#') || url.startsWith('mailto:') || url.startsWith('tel:')) {\n return false\n }\n const host = hostOf(url)\n if (host === null) {\n // Relative link → internal to the site.\n return true\n }\n return host === siteHost.toLowerCase()\n}\n\n/**\n * Extracts the final path segment of a WordPress permalink as a candidate slug.\n * Handles trailing slashes and `/YYYY/MM/slug/` date-based permalinks.\n */\nexport const permalinkToSlug = (url: string): null | string => {\n const path = pathOf(url).replace(/\\/+$/, '')\n if (!path || path === '') {\n return null\n }\n const segments = path.split('/').filter(Boolean)\n const last = segments[segments.length - 1]\n return last ? decodeURIComponent(last) : null\n}\n\n/**\n * Derives the original (full-size) image URL from a WordPress-resized URL by\n * stripping the `-<width>x<height>` suffix WordPress appends before the\n * extension (e.g. `photo-1024x768.jpg` → `photo.jpg`). Returns the input\n * unchanged when no such suffix is present.\n */\nexport const deriveOriginalImageUrl = (url: string): string => {\n const [beforeHash] = url.split('#')\n const [path, query] = beforeHash.split('?')\n const original = path.replace(/-\\d+x\\d+(\\.[a-zA-Z0-9]+)$/, '$1')\n return query ? `${original}?${query}` : original\n}\n\n/** Basename of a URL path, used as the uploaded filename. */\nexport const filenameOf = (url: string): string => {\n const path = pathOf(url)\n const base = path.split('/').filter(Boolean).pop() ?? 'image'\n return decodeURIComponent(base) || 'image'\n}\n\n/** Named HTML entities WordPress commonly emits (beyond numeric references). */\nconst NAMED_ENTITIES: Record<string, string> = {\n agrave: 'à',\n amp: '&',\n apos: \"'\",\n bdquo: '„',\n bull: '•',\n ccedil: 'ç',\n copy: '©',\n deg: '°',\n eacute: 'é',\n ecirc: 'ê',\n egrave: 'è',\n gt: '>',\n hellip: '…',\n laquo: '«',\n ldquo: '“',\n lsaquo: '‹',\n lsquo: '‘',\n lt: '<',\n mdash: '—',\n middot: '·',\n nbsp: ' ',\n ndash: '–',\n quot: '\"',\n raquo: '»',\n rdquo: '”',\n reg: '®',\n rsaquo: '›',\n rsquo: '’',\n sbquo: '‚',\n trade: '™',\n}\n\n/**\n * Decodes the HTML entities WordPress emits in titles/excerpts: all numeric\n * references (`&#8217;`, `&#x2019;`) plus the common named ones (`&rsquo;`,\n * `&hellip;`, …). Unknown named entities are left as-is. Because `.replace`\n * never rescans replaced output, `&amp;rsquo;` correctly stays `&rsquo;`.\n */\nexport const decodeEntities = (value: string): string =>\n value\n .replace(/&#x([0-9a-f]+);/gi, (_, hex: string) => String.fromCodePoint(parseInt(hex, 16)))\n .replace(/&#(\\d+);/g, (_, dec: string) => String.fromCodePoint(Number(dec)))\n .replace(/&([a-zA-Z]+);/g, (match, name: string) => NAMED_ENTITIES[name.toLowerCase()] ?? match)\n .trim()\n\n/** Strips HTML tags (for excerpt → plain-text SEO description). */\nexport const stripHtml = (html: string): string =>\n decodeEntities(html.replace(/<[^>]*>/g, ' ').replace(/\\s+/g, ' ')).trim()\n","import type { Payload } from 'payload'\n\n/**\n * Loosely-typed wrappers around the Payload Local API. This plugin operates on\n * collection slugs the host configures at runtime, so the generated\n * `CollectionSlug` unions don't apply — these helpers centralize the casts\n * instead of scattering them across every call site.\n */\n\nexport type AnyDoc = { id: number | string; [key: string]: unknown }\n\ntype CreateArgs = {\n collection: string\n data: Record<string, unknown>\n file?: { data: Buffer; mimetype: string; name: string; size: number }\n overrideAccess?: boolean\n}\n\ntype FindArgs = {\n collection: string\n depth?: number\n limit?: number\n overrideAccess?: boolean\n select?: Record<string, unknown>\n where?: unknown\n}\n\nexport const createDoc = (payload: Payload, args: CreateArgs): Promise<AnyDoc> =>\n (payload.create as (a: unknown) => Promise<AnyDoc>)({ overrideAccess: true, ...args })\n\nexport const findDocs = (\n payload: Payload,\n args: FindArgs,\n): Promise<{ docs: AnyDoc[]; totalDocs: number }> =>\n (payload.find as (a: unknown) => Promise<{ docs: AnyDoc[]; totalDocs: number }>)({\n overrideAccess: true,\n ...args,\n })\n\nexport const countDocs = (\n payload: Payload,\n args: { collection: string; overrideAccess?: boolean; where?: unknown },\n): Promise<{ totalDocs: number }> =>\n (payload.count as (a: unknown) => Promise<{ totalDocs: number }>)({\n overrideAccess: true,\n ...args,\n })\n\nexport const findDoc = (\n payload: Payload,\n args: { collection: string; depth?: number; id: number | string; overrideAccess?: boolean },\n): Promise<AnyDoc> =>\n (payload.findByID as (a: unknown) => Promise<AnyDoc>)({ overrideAccess: true, ...args })\n\nexport const updateDoc = (\n payload: Payload,\n args: {\n collection: string\n context?: Record<string, unknown>\n data: Record<string, unknown>\n id: number | string\n overrideAccess?: boolean\n },\n): Promise<AnyDoc> =>\n (payload.update as (a: unknown) => Promise<AnyDoc>)({ overrideAccess: true, ...args })\n","import type { Payload } from 'payload'\n\nimport { RECORDS_SLUG } from '../defaults.js'\nimport { createDoc, findDocs } from './payloadOps.js'\n\nexport type SourceType = 'author' | 'category' | 'media' | 'post'\n\nexport type RecordLookup = {\n site: string\n sourceId?: null | number\n sourceKey?: null | string\n sourceType: SourceType\n}\n\nexport type SaveRecordArgs = RecordLookup & {\n error?: string\n jobId: number | string\n status?: 'done' | 'failed'\n targetCollection?: string\n targetId?: null | number | string\n}\n\n/**\n * Finds a completed import record for a source entity. Media are matched by\n * `sourceKey` (the original image URL) so an image reused across posts is only\n * uploaded once; everything else is matched by `sourceId`. Returns the mapped\n * target id (as a string) or `null`.\n *\n * Reads/writes deliberately omit `req` so each commits independently — a crash\n * mid-import leaves earlier work durable and the run resumes from these records.\n */\nexport const findDoneRecord = async (\n payload: Payload,\n lookup: RecordLookup,\n): Promise<null | string> => {\n const where =\n lookup.sourceType === 'media' && lookup.sourceKey\n ? {\n and: [\n { site: { equals: lookup.site } },\n { sourceType: { equals: 'media' } },\n { sourceKey: { equals: lookup.sourceKey } },\n { status: { equals: 'done' } },\n ],\n }\n : {\n and: [\n { site: { equals: lookup.site } },\n { sourceType: { equals: lookup.sourceType } },\n { sourceId: { equals: lookup.sourceId } },\n { status: { equals: 'done' } },\n ],\n }\n\n const { docs } = await findDocs(payload, {\n collection: RECORDS_SLUG,\n where,\n limit: 1,\n depth: 0,\n })\n\n const doc = docs[0] as undefined | { targetId?: null | string }\n return doc?.targetId != null ? String(doc.targetId) : null\n}\n\n/** Upserts an import record (used to mark an entity done or failed). */\nexport const saveRecord = async (payload: Payload, args: SaveRecordArgs): Promise<void> => {\n await createDoc(payload, {\n collection: RECORDS_SLUG,\n data: {\n job: args.jobId,\n site: args.site,\n sourceType: args.sourceType,\n sourceId: args.sourceId ?? undefined,\n sourceKey: args.sourceKey ?? undefined,\n targetCollection: args.targetCollection,\n targetId: args.targetId != null ? String(args.targetId) : undefined,\n status: args.status ?? 'done',\n error: args.error,\n },\n })\n}\n","import type { Payload } from 'payload'\n\nimport { createDoc } from './payloadOps.js'\nimport { deriveOriginalImageUrl, filenameOf } from './url.js'\nimport { findDoneRecord, saveRecord } from './records.js'\n\nexport type ImageImportResult = {\n error?: string\n mediaId: null | string\n reused: boolean\n uploaded: boolean\n}\n\nexport type ImportImageArgs = {\n alt?: string\n /** Preferred canonical key for dedupe (defaults to the derived original URL). */\n cache: Map<string, ImageImportResult>\n dryRun: boolean\n fetchImpl?: typeof fetch\n jobId: number | string\n mediaSlug: string\n site: string\n /** WordPress media id, when known. */\n sourceId?: number\n timeoutMs: number\n url: string\n}\n\nconst download = async (\n url: string,\n timeoutMs: number,\n fetchImpl: typeof fetch,\n): Promise<{ buffer: Buffer; mimeType: string }> => {\n const controller = new AbortController()\n const timer = setTimeout(() => controller.abort(), timeoutMs)\n try {\n const res = await fetchImpl(url, { signal: controller.signal })\n if (!res.ok) {\n throw new Error(`image download failed: ${res.status}`)\n }\n const arrayBuffer = await res.arrayBuffer()\n const mimeType = res.headers.get('content-type')?.split(';')[0] || 'image/jpeg'\n return { buffer: Buffer.from(arrayBuffer), mimeType }\n } finally {\n clearTimeout(timer)\n }\n}\n\n/**\n * Imports one image, uploading the original (full-size) version and reusing an\n * already-imported copy. Dedupe is by the derived original URL: within a run via\n * `cache`, across runs via `wp-import-records`. In dry-run mode it resolves\n * reuse but performs no download or write.\n */\nexport const importImage = async (\n payload: Payload,\n args: ImportImageArgs,\n): Promise<ImageImportResult> => {\n const fetchImpl = args.fetchImpl ?? fetch\n const canonical = deriveOriginalImageUrl(args.url)\n\n const cached = args.cache.get(canonical)\n if (cached) {\n return { ...cached, reused: true, uploaded: false }\n }\n\n // Already imported by a previous run?\n const existing = await findDoneRecord(payload, {\n site: args.site,\n sourceKey: canonical,\n sourceType: 'media',\n })\n if (existing) {\n const result: ImageImportResult = { mediaId: existing, reused: true, uploaded: false }\n args.cache.set(canonical, result)\n return result\n }\n\n if (args.dryRun) {\n // Report intent without writing; mark cached so the same image is planned once.\n const result: ImageImportResult = { mediaId: null, reused: false, uploaded: true }\n args.cache.set(canonical, result)\n return result\n }\n\n try {\n // Prefer the original; fall back to the (possibly resized) URL WordPress gave us.\n let downloaded\n try {\n downloaded = await download(canonical, args.timeoutMs, fetchImpl)\n } catch {\n downloaded = await download(args.url, args.timeoutMs, fetchImpl)\n }\n\n const created = await createDoc(payload, {\n collection: args.mediaSlug,\n data: { alt: args.alt || filenameOf(canonical) },\n file: {\n data: downloaded.buffer,\n mimetype: downloaded.mimeType,\n name: filenameOf(canonical),\n size: downloaded.buffer.length,\n },\n })\n\n const mediaId = String(created.id)\n await saveRecord(payload, {\n jobId: args.jobId,\n site: args.site,\n sourceId: args.sourceId ?? null,\n sourceKey: canonical,\n sourceType: 'media',\n targetCollection: args.mediaSlug,\n targetId: mediaId,\n })\n\n const result: ImageImportResult = { mediaId, reused: false, uploaded: true }\n args.cache.set(canonical, result)\n return result\n } catch (error) {\n return {\n error: error instanceof Error ? error.message : String(error),\n mediaId: null,\n reused: false,\n uploaded: false,\n }\n }\n}\n","import type { Payload } from 'payload'\n\nimport type { ImportError, ImportedItem } from '../types.js'\nimport type { WPCategory } from './wpTypes.js'\n\nimport { coerceId } from './id.js'\nimport { createDoc } from './payloadOps.js'\nimport { decodeEntities } from './url.js'\nimport { findDoneRecord, saveRecord } from './records.js'\n\n/**\n * Orders categories so every parent precedes its children (WordPress `parent`\n * is `0` for roots). Cycles/ophans are appended at the end. Pure — unit-tested.\n */\nexport const sortCategoriesParentsFirst = (categories: WPCategory[]): WPCategory[] => {\n const byId = new Map(categories.map((c) => [c.id, c]))\n const sorted: WPCategory[] = []\n const placed = new Set<number>()\n\n const place = (cat: WPCategory, stack: Set<number>): void => {\n if (placed.has(cat.id) || stack.has(cat.id)) {\n return\n }\n stack.add(cat.id)\n const parent = cat.parent && cat.parent !== 0 ? byId.get(cat.parent) : undefined\n if (parent) {\n place(parent, stack)\n }\n stack.delete(cat.id)\n if (!placed.has(cat.id)) {\n placed.add(cat.id)\n sorted.push(cat)\n }\n }\n\n for (const cat of categories) {\n place(cat, new Set())\n }\n return sorted\n}\n\nexport type ImportCategoriesArgs = {\n categories: WPCategory[]\n categoriesSlug: string\n dryRun: boolean\n jobId: number | string\n site: string\n}\n\nexport type ImportCategoriesResult = {\n errors: ImportError[]\n imported: ImportedItem[]\n /** WordPress category id → Payload category id. */\n idMap: Map<number, number | string>\n}\n\n/** Imports categories preserving hierarchy; idempotent via import records. */\nexport const importCategories = async (\n payload: Payload,\n args: ImportCategoriesArgs,\n): Promise<ImportCategoriesResult> => {\n const idMap = new Map<number, number | string>()\n const imported: ImportedItem[] = []\n const errors: ImportError[] = []\n const ordered = sortCategoriesParentsFirst(args.categories)\n\n for (const cat of ordered) {\n try {\n const existing = await findDoneRecord(payload, {\n site: args.site,\n sourceId: cat.id,\n sourceType: 'category',\n })\n if (existing) {\n idMap.set(cat.id, coerceId(existing))\n continue\n }\n\n const name = decodeEntities(cat.name ?? cat.slug ?? `category-${cat.id}`)\n\n if (args.dryRun) {\n imported.push({ sourceId: cat.id, targetId: 'dry-run', title: name })\n continue\n }\n\n const parentId = cat.parent && cat.parent !== 0 ? idMap.get(cat.parent) : undefined\n\n const created = await createDoc(payload, {\n collection: args.categoriesSlug,\n data: {\n name,\n ...(cat.slug ? { slug: cat.slug } : {}),\n ...(parentId != null ? { parent: coerceId(parentId) } : {}),\n ...(cat.description ? { description: decodeEntities(cat.description) } : {}),\n },\n })\n\n const rawId = created.id\n idMap.set(cat.id, rawId)\n imported.push({ sourceId: cat.id, targetId: rawId, title: name })\n await saveRecord(payload, {\n jobId: args.jobId,\n site: args.site,\n sourceId: cat.id,\n sourceType: 'category',\n targetCollection: args.categoriesSlug,\n targetId: rawId,\n })\n } catch (error) {\n errors.push({\n message: error instanceof Error ? error.message : String(error),\n scope: 'category',\n sourceId: cat.id,\n })\n }\n }\n\n return { errors, idMap, imported }\n}\n","import type { SanitizedServerEditorConfig } from '@payloadcms/richtext-lexical'\n\nimport { convertHTMLToLexical } from '@payloadcms/richtext-lexical'\nimport { JSDOM } from 'jsdom'\n\nimport type { LinkMapping } from '../types.js'\nimport type { ImageImportResult } from './media.js'\nimport type { LexNode } from './lexical.js'\n\nimport { imageToken, replaceImageTokens, rewriteLinkNodes } from './lexical.js'\n\nexport type BuildContentArgs = {\n articleUrl: (slug?: null | string) => string\n editorConfig: SanitizedServerEditorConfig\n html: string\n /** Uploads (or plans) a content image and returns the resulting media id. */\n importContentImage: (src: string) => Promise<ImageImportResult>\n mediaSlug: string\n /** Resolves an internal WordPress link to an imported article slug, or null. */\n resolveInternal: (url: string, slug: null | string) => null | string\n siteHost: string\n}\n\nexport type BuildContentResult = {\n content: { root: LexNode }\n images: Array<{ result: ImageImportResult; src: string }>\n links: LinkMapping[]\n}\n\n/**\n * Converts a WordPress post's rendered HTML into a Lexical editor state:\n * uploads in-content images (dedup-aware) and turns them into upload nodes,\n * and rewrites internal links that point at imported posts. Images are first\n * swapped for block-level text tokens so they survive HTML→Lexical conversion\n * at their original position, then replaced with upload nodes afterwards.\n */\nexport const buildContent = async (args: BuildContentArgs): Promise<BuildContentResult> => {\n const dom = new JSDOM(`<!DOCTYPE html><body>${args.html}</body>`)\n const { document } = dom.window\n const images: Array<{ result: ImageImportResult; src: string }> = []\n const tokenToMedia = new Map<number, null | string>()\n\n const imgs = Array.from(document.querySelectorAll('img'))\n let index = 0\n for (const img of imgs) {\n const src = img.getAttribute('src') || ''\n if (!src) {\n img.remove()\n continue\n }\n\n const result = await args.importContentImage(src)\n images.push({ result, src })\n\n const token = index\n tokenToMedia.set(token, result.mediaId)\n index += 1\n\n // Choose the block to replace: prefer an enclosing <figure>, else an\n // <a> that only wraps this image, else the image itself.\n let target: Element = img\n const anchor = img.parentElement\n if (anchor && anchor.tagName === 'A' && anchor.childNodes.length === 1) {\n target = anchor\n }\n const figure = target.closest('figure')\n if (figure) {\n target = figure\n }\n\n const placeholder = document.createElement('p')\n placeholder.textContent = imageToken(token)\n target.replaceWith(placeholder)\n }\n\n const modifiedHtml = document.body.innerHTML\n\n const state = convertHTMLToLexical({\n editorConfig: args.editorConfig,\n html: modifiedHtml,\n JSDOM: JSDOM as unknown as new (html: string) => { window: { document: Document } },\n }) as unknown as { root: LexNode }\n\n replaceImageTokens(state.root, (i) => tokenToMedia.get(i) ?? null, args.mediaSlug)\n\n const links = rewriteLinkNodes(state.root, {\n articleUrl: args.articleUrl,\n resolveInternal: args.resolveInternal,\n siteHost: args.siteHost,\n })\n\n return { content: state, images, links }\n}\n","import type { LinkMapping } from '../types.js'\n\nimport { coerceId } from './id.js'\nimport { isInternalUrl, permalinkToSlug } from './url.js'\n\n/** Loosely-typed serialized Lexical node (we only touch a few well-known shapes). */\nexport type LexNode = {\n children?: LexNode[]\n fields?: Record<string, unknown>\n tag?: string\n text?: string\n type: string\n [key: string]: unknown\n}\n\nexport type LexRoot = { root: LexNode }\n\n/**\n * Block-level placeholder inserted in place of each `<img>` before HTML→Lexical\n * conversion. It is unlikely to appear in real content and survives conversion\n * as a paragraph containing a single text node, which `replaceImageTokens`\n * then swaps for an upload node.\n */\nexport const imageToken = (index: number): string => `⁣WPIMG:${index}⁣`\n\nconst IMAGE_TOKEN_RE = /^⁣WPIMG:(\\d+)⁣$/\n\n/** Extracts `src` attributes of every `<img>` in an HTML string (order-preserving). */\nexport const extractImageSrcs = (html: string): string[] => {\n const srcs: string[] = []\n const re = /<img\\b[^>]*?\\bsrc\\s*=\\s*([\"'])(.*?)\\1/gi\n let match: null | RegExpExecArray\n while ((match = re.exec(html)) !== null) {\n srcs.push(match[2])\n }\n return srcs\n}\n\n/** Builds a serialized Lexical upload (decorator block) node for a media doc. */\nexport const buildUploadNode = (value: number | string, relationTo: string): LexNode => ({\n type: 'upload',\n fields: null as unknown as Record<string, unknown>,\n format: '',\n relationTo,\n value: coerceId(value),\n version: 3,\n})\n\n/** Depth-first walk over a serialized tree, invoking `visit` on every node. */\nexport const walk = (node: LexNode, visit: (node: LexNode) => void): void => {\n visit(node)\n if (Array.isArray(node.children)) {\n for (const child of node.children) {\n walk(child, visit)\n }\n }\n}\n\n/** Returns the sole text of a node if it is a paragraph wrapping one text node. */\nconst soleTextTokenIndex = (node: LexNode): null | number => {\n if (node.type !== 'paragraph' || !Array.isArray(node.children) || node.children.length !== 1) {\n return null\n }\n const child = node.children[0]\n if (child.type !== 'text' || typeof child.text !== 'string') {\n return null\n }\n const m = IMAGE_TOKEN_RE.exec(child.text.trim())\n return m ? Number(m[1]) : null\n}\n\n/**\n * Replaces token paragraphs (created by `imageToken`) with upload nodes.\n * `resolve(index)` returns the uploaded media id for that image, or `null` to\n * drop the placeholder. Mutates and returns the same root.\n */\nexport const replaceImageTokens = (\n root: LexNode,\n resolve: (index: number) => null | number | string,\n mediaSlug: string,\n): LexNode => {\n const replaceIn = (parent: LexNode): void => {\n if (!Array.isArray(parent.children)) {\n return\n }\n const next: LexNode[] = []\n for (const child of parent.children) {\n const index = soleTextTokenIndex(child)\n if (index !== null) {\n const mediaId = resolve(index)\n if (mediaId !== null && mediaId !== undefined) {\n next.push(buildUploadNode(mediaId, mediaSlug))\n }\n continue\n }\n replaceIn(child)\n next.push(child)\n }\n parent.children = next\n }\n replaceIn(root)\n return root\n}\n\n/**\n * Finds, removes and returns the value of the first upload node in document\n * order, or `null` when the tree has none. Used to promote a leading content\n * image to the cover field when the post has no featured image.\n */\nexport const takeFirstUploadNode = (root: LexNode): null | number | string => {\n const search = (parent: LexNode): null | number | string => {\n if (!Array.isArray(parent.children)) {\n return null\n }\n for (let i = 0; i < parent.children.length; i += 1) {\n const child = parent.children[i]\n if (child.type === 'upload') {\n parent.children.splice(i, 1)\n return (child as { value?: number | string }).value ?? null\n }\n const nested = search(child)\n if (nested !== null) {\n return nested\n }\n }\n return null\n }\n return search(root)\n}\n\nconst isEmptyParagraph = (node: LexNode): boolean =>\n node.type === 'paragraph' &&\n (!Array.isArray(node.children) ||\n node.children.every((child) => child.type === 'text' && !(child.text ?? '').trim()))\n\n/**\n * Drops a leading duplicate of the cover image: when the first non-empty block\n * is an upload of `value`, it is removed so the hero doesn't render twice\n * (once as the cover, once at the top of the content).\n */\nexport const removeLeadingUploadNode = (root: LexNode, value: number | string): boolean => {\n const children = root.children\n if (!Array.isArray(children)) {\n return false\n }\n for (let i = 0; i < children.length; i += 1) {\n const child = children[i]\n if (isEmptyParagraph(child)) {\n continue\n }\n if (\n child.type === 'upload' &&\n String((child as { value?: unknown }).value) === String(value)\n ) {\n children.splice(i, 1)\n return true\n }\n return false\n }\n return false\n}\n\nexport type LinkRewriteOptions = {\n articleUrl: (slug?: null | string) => string\n siteHost: string\n /** Resolves a WordPress permalink/slug to an imported article slug, or null. */\n resolveInternal: (url: string, slug: null | string) => null | string\n}\n\n/**\n * Rewrites internal `<a>` links whose target was imported and records every\n * internal link for the report. External links and unresolved internal links\n * are left untouched. Returns the collected link mappings.\n */\nexport const rewriteLinkNodes = (root: LexNode, options: LinkRewriteOptions): LinkMapping[] => {\n const { articleUrl, resolveInternal, siteHost } = options\n const links: LinkMapping[] = []\n\n walk(root, (node) => {\n if (node.type !== 'link' || !node.fields) {\n return\n }\n const url = typeof node.fields.url === 'string' ? node.fields.url : ''\n if (!url || !isInternalUrl(url, siteHost)) {\n return\n }\n const slug = permalinkToSlug(url)\n const targetSlug = resolveInternal(url, slug)\n if (targetSlug) {\n const to = articleUrl(targetSlug)\n node.fields.url = to\n node.fields.linkType = 'custom'\n links.push({ action: 'rewritten', from: url, to })\n } else {\n links.push({ action: 'unresolved', from: url })\n }\n })\n\n return links\n}\n","import type { SanitizedServerEditorConfig } from '@payloadcms/richtext-lexical'\nimport type { Field, Payload, RichTextField } from 'payload'\n\nimport { editorConfigFactory } from '@payloadcms/richtext-lexical'\n\n/** Recursively finds a named richText field within a field tree. */\nconst findRichTextField = (fields: Field[], name: string): RichTextField | undefined => {\n for (const field of fields) {\n if (field.type === 'richText' && 'name' in field && field.name === name) {\n return field as RichTextField\n }\n if ('fields' in field && Array.isArray(field.fields)) {\n const nested = findRichTextField(field.fields, name)\n if (nested) {\n return nested\n }\n }\n if (field.type === 'tabs' && Array.isArray(field.tabs)) {\n for (const tab of field.tabs) {\n const nested = findRichTextField(tab.fields, name)\n if (nested) {\n return nested\n }\n }\n }\n }\n return undefined\n}\n\n/**\n * Resolves the sanitized Lexical editor config for the target article content\n * field, so HTML→Lexical conversion uses exactly the features that field\n * accepts. Falls back to the config's default editor when the field can't be\n * located.\n */\nexport const resolveEditorConfig = async (\n payload: Payload,\n articlesSlug: string,\n contentFieldName: string,\n): Promise<SanitizedServerEditorConfig> => {\n const collections = payload.collections as unknown as Record<\n string,\n { config: { fields: Field[] } } | undefined\n >\n const collection = collections[articlesSlug]\n const field = collection\n ? findRichTextField(collection.config.fields, contentFieldName)\n : undefined\n\n if (field) {\n return editorConfigFactory.fromField({ field })\n }\n\n return editorConfigFactory.default({ config: payload.config })\n}\n","import type { WPPost } from './wpTypes.js'\n\n/** The primary category of a post — WordPress core has no \"primary\", so the first assigned. */\nexport const selectPrimaryCategoryId = (post: WPPost): null | number =>\n Array.isArray(post.categories) && post.categories.length > 0 ? post.categories[0] : null\n\n/** Best publish date for a post as an ISO string (prefers GMT). */\nexport const publishDate = (post: WPPost): string | undefined => {\n if (post.date_gmt) {\n // WordPress GMT dates omit the trailing Z.\n const value = post.date_gmt.endsWith('Z') ? post.date_gmt : `${post.date_gmt}Z`\n const date = new Date(value)\n return Number.isNaN(date.getTime()) ? undefined : date.toISOString()\n }\n if (post.date) {\n const date = new Date(post.date)\n return Number.isNaN(date.getTime()) ? undefined : date.toISOString()\n }\n return undefined\n}\n","import type { Payload } from 'payload'\n\nimport { countDocs, createDoc } from './payloadOps.js'\n\nexport type CreateRedirectArgs = {\n articleId: number | string\n articlesSlug: string\n from: string\n}\n\n/**\n * Creates a 301 redirect (via @payloadcms/plugin-redirects' `redirects`\n * collection) from an old WordPress path to an imported article, unless one\n * already exists or the collection isn't installed. Returns whether a redirect\n * was created.\n */\nexport const createRedirect = async (\n payload: Payload,\n args: CreateRedirectArgs,\n): Promise<boolean> => {\n if (!payload.collections.redirects) {\n return false\n }\n\n const { totalDocs } = await countDocs(payload, {\n collection: 'redirects',\n where: { from: { equals: args.from } },\n })\n if (totalDocs > 0) {\n return false\n }\n\n await createDoc(payload, {\n collection: 'redirects',\n data: {\n from: args.from,\n to: {\n type: 'reference',\n reference: { relationTo: args.articlesSlug, value: args.articleId },\n },\n },\n })\n return true\n}\n","import type {\n ImportedItem,\n ImportError,\n ImportProgress,\n ImportReport,\n LinkMapping,\n RunSummary,\n} from '../types.js'\n\nexport const emptyProgress = (): ImportProgress => ({\n currentPhase: 'queued',\n cursorPage: 0,\n importedAuthors: 0,\n importedCategories: 0,\n importedMedia: 0,\n importedPosts: 0,\n linksRewritten: 0,\n linksUnresolved: 0,\n redirectsCreated: 0,\n reusedMedia: 0,\n skippedPosts: 0,\n failedPosts: 0,\n totalPosts: 0,\n})\n\nexport const emptyReport = (dryRun: boolean): ImportReport => ({\n dryRun,\n errors: [],\n imported: { authors: [], categories: [], media: [], posts: [] },\n links: [],\n remaining: { posts: 0 },\n})\n\n/** Shape of the report fields persisted on a `wp-import-jobs` document. */\nexport type PersistedJobReports = {\n authorsReport?: null | { imported?: ImportedItem[] }\n categoriesReport?: null | { imported?: ImportedItem[] }\n errorsReport?: null | { errors?: ImportError[] }\n linksReport?: null | { links?: LinkMapping[] }\n mediaReport?: null | { imported?: ImportedItem[] }\n postsReport?: null | { imported?: ImportedItem[] }\n runs?: null | RunSummary[]\n}\n\n/**\n * Rebuilds the in-memory report from a job's persisted step reports, so a\n * resume/retry keeps the history of what earlier runs imported. Entries tagged\n * with a dry run are dropped (they were plans, not imports), and the next run\n * number is derived from the run history.\n */\nexport const rehydrateReport = (\n job: PersistedJobReports,\n dryRun: boolean,\n): { previousRuns: RunSummary[]; report: ImportReport; runNumber: number } => {\n const previousRuns = Array.isArray(job.runs) ? job.runs : []\n const dryRunNumbers = new Set(previousRuns.filter((r) => r.dryRun).map((r) => r.run))\n const keep = <T extends { run?: number }>(items?: null | T[]): T[] =>\n (items ?? []).filter((item) => item.run === undefined || !dryRunNumbers.has(item.run))\n\n const report = emptyReport(dryRun)\n report.imported.authors = keep(job.authorsReport?.imported)\n report.imported.categories = keep(job.categoriesReport?.imported)\n report.imported.media = keep(job.mediaReport?.imported)\n report.imported.posts = keep(job.postsReport?.imported)\n report.links = keep(job.linksReport?.links)\n report.errors = keep(job.errorsReport?.errors)\n\n const runNumber = previousRuns.reduce((max, r) => Math.max(max, r.run), 0) + 1\n return { previousRuns, report, runNumber }\n}\n","import type { RequestOptions } from '../types.js'\nimport type { WPCategory, WPMedia, WPPost, WPUser } from './wpTypes.js'\n\n/** Normalizes a site URL into its `/wp-json/wp/v2` REST base (no trailing slash). */\nexport const restBase = (siteUrl: string): string => {\n const trimmed = siteUrl.trim().replace(/\\/+$/, '')\n return `${trimmed}/wp-json/wp/v2`\n}\n\n/** WordPress user + application password (Users → Profile → Application Passwords). */\nexport type WPCredentials = {\n applicationPassword?: null | string\n username?: null | string\n}\n\nexport type WPClient = {\n /** Whether requests carry Basic auth (credentials were provided). */\n authenticated: boolean\n fetchCategories: () => Promise<WPCategory[]>\n fetchMedia: (id: number) => Promise<null | WPMedia>\n fetchPostsPage: (args: {\n after?: string\n before?: string\n page: number\n perPage: number\n }) => Promise<{ posts: WPPost[]; totalPages: number }>\n fetchUser: (id: number) => Promise<null | WPUser>\n}\n\nexport class WPRequestError extends Error {\n status: number\n constructor(message: string, status: number) {\n super(message)\n this.name = 'WPRequestError'\n this.status = status\n }\n}\n\nexport const createWPClient = (\n siteUrl: string,\n request: Pick<Required<RequestOptions>, 'timeoutMs'> &\n Pick<RequestOptions, 'userAgent'> & { credentials?: null | WPCredentials },\n fetchImpl: typeof fetch = fetch,\n): WPClient => {\n const base = restBase(siteUrl)\n\n const headers: Record<string, string> = { Accept: 'application/json' }\n if (request.userAgent) {\n headers['User-Agent'] = request.userAgent\n }\n\n // WordPress application passwords authenticate via HTTP Basic auth, which\n // unlocks non-public data (e.g. author emails via ?context=edit).\n const { applicationPassword, username } = request.credentials ?? {}\n const authenticated = Boolean(username && applicationPassword)\n if (authenticated) {\n headers.Authorization = `Basic ${Buffer.from(`${username}:${applicationPassword}`).toString('base64')}`\n }\n\n const get = async (path: string): Promise<{ body: unknown; totalPages: number }> => {\n const controller = new AbortController()\n const timer = setTimeout(() => controller.abort(), request.timeoutMs)\n try {\n const res = await fetchImpl(`${base}${path}`, { headers, signal: controller.signal })\n if (!res.ok) {\n throw new WPRequestError(`WordPress request failed: ${res.status} ${path}`, res.status)\n }\n const totalPages = Number(res.headers.get('X-WP-TotalPages') ?? '1') || 1\n const body = await res.json()\n return { body, totalPages }\n } finally {\n clearTimeout(timer)\n }\n }\n\n return {\n authenticated,\n fetchPostsPage: async ({ after, before, page, perPage }) => {\n const params = new URLSearchParams({\n _embed: '1',\n page: String(page),\n per_page: String(perPage),\n status: 'publish',\n })\n if (after) {\n params.set('after', after)\n }\n if (before) {\n params.set('before', before)\n }\n const { body, totalPages } = await get(`/posts?${params.toString()}`)\n return { posts: (body as WPPost[]) ?? [], totalPages }\n },\n fetchCategories: async () => {\n const all: WPCategory[] = []\n let page = 1\n let totalPages = 1\n do {\n const { body, totalPages: tp } = await get(`/categories?per_page=100&page=${page}`)\n all.push(...((body as WPCategory[]) ?? []))\n totalPages = tp\n page += 1\n } while (page <= totalPages)\n return all\n },\n fetchMedia: async (id) => {\n try {\n const { body } = await get(`/media/${id}`)\n return body as WPMedia\n } catch {\n return null\n }\n },\n fetchUser: async (id) => {\n // context=edit exposes non-public fields (email) but needs auth.\n if (authenticated) {\n try {\n const { body } = await get(`/users/${id}?context=edit`)\n return body as WPUser\n } catch {\n // Fall through to the public representation.\n }\n }\n try {\n const { body } = await get(`/users/${id}`)\n return body as WPUser\n } catch {\n return null\n }\n },\n }\n}\n","import type { Payload } from 'payload'\n\nimport type { ImportProgress, ImportReport, ResolvedOptions, RunSummary } from '../types.js'\nimport type { ImageImportResult } from '../lib/media.js'\nimport type { PersistedJobReports } from '../lib/report.js'\nimport type { WPPost, WPUser } from '../lib/wpTypes.js'\n\nimport { JOBS_SLUG } from '../defaults.js'\nimport { resolveAuthor } from '../lib/authors.js'\nimport { importCategories } from '../lib/categories.js'\nimport { buildContent } from '../lib/content.js'\nimport { coerceId } from '../lib/id.js'\nimport { resolveEditorConfig } from '../lib/editorConfig.js'\nimport { importImage } from '../lib/media.js'\nimport { removeLeadingUploadNode, takeFirstUploadNode } from '../lib/lexical.js'\nimport { createDoc, findDoc, findDocs, updateDoc } from '../lib/payloadOps.js'\nimport { publishDate, selectPrimaryCategoryId } from '../lib/post.js'\nimport { createRedirect } from '../lib/redirects.js'\nimport { emptyProgress, rehydrateReport } from '../lib/report.js'\nimport { findDoneRecord, saveRecord } from '../lib/records.js'\nimport { createWPClient } from '../lib/wpClient.js'\nimport { decodeEntities, hostOf, pathOf, permalinkToSlug, stripHtml } from '../lib/url.js'\n\nconst PER_PAGE = 100\n// Matches SEO_DESCRIPTION_MAX_LENGTH in the shared-components SEO defaults.\nconst SEO_DESCRIPTION_MAX = 150\n\nexport type RunImportArgs = {\n fetchImpl?: typeof fetch\n jobId: number | string\n options: ResolvedOptions\n}\n\ntype JobDoc = PersistedJobReports & {\n credentials?: null | { applicationPassword?: null | string; username?: null | string }\n dateFrom?: null | string\n dateTo?: null | string\n dryRun?: boolean | null\n limit?: null | number\n sourceUrl: string\n}\n\n/**\n * Executes one import run for a `wp-import-jobs` document. Idempotent and\n * resumable: every entity is checked against `wp-import-records` and skipped if\n * already imported, and writes intentionally omit `req` so each commits\n * independently. In dry-run mode it samples the first page(s) and writes\n * nothing, producing the same report describing what a real run would do.\n */\nexport const runImport = async (payload: Payload, args: RunImportArgs): Promise<ImportReport> => {\n const { options } = args\n const { collections: slugs } = options\n const progress: ImportProgress = emptyProgress()\n\n const job = (await findDoc(payload, {\n collection: JOBS_SLUG,\n id: args.jobId,\n depth: 0,\n })) as unknown as JobDoc\n\n const dryRun = Boolean(job.dryRun)\n // Resume/retry: start from what earlier runs reported (dry-run entries are\n // dropped), and tag everything new with this run's number.\n const { previousRuns, report, runNumber } = rehydrateReport(job, dryRun)\n const runSummary: RunSummary = {\n dryRun,\n run: runNumber,\n startedAt: new Date().toISOString(),\n status: 'running',\n }\n const runs: RunSummary[] = [...previousRuns, runSummary]\n const site = hostOf(job.sourceUrl) ?? job.sourceUrl\n const imageCache = new Map<string, ImageImportResult>()\n\n // Per-step report slices, persisted onto the job's step tabs.\n const stepReports = (): Record<string, unknown> => ({\n authorsReport: { imported: report.imported.authors },\n categoriesReport: { imported: report.imported.categories },\n errorsReport: { dryRun: report.dryRun, errors: report.errors },\n linksReport: { links: report.links },\n mediaReport: { imported: report.imported.media, reused: progress.reusedMedia },\n postsReport: {\n dryRun: report.dryRun,\n imported: report.imported.posts,\n remaining: report.remaining.posts,\n },\n runs,\n })\n\n const updateJob = async (data: Record<string, unknown>): Promise<void> => {\n await updateDoc(payload, {\n collection: JOBS_SLUG,\n id: args.jobId,\n data,\n context: { wpImport: true },\n })\n }\n\n const accountImage = (result: ImageImportResult, sourceId: number): void => {\n if (result.error) {\n report.errors.push({ message: result.error, run: runNumber, scope: 'media', sourceId })\n } else if (result.uploaded) {\n progress.importedMedia += 1\n report.imported.media.push({\n run: runNumber,\n sourceId,\n targetId: result.mediaId ?? 'dry-run',\n })\n } else if (result.reused) {\n progress.reusedMedia += 1\n }\n }\n\n try {\n progress.currentPhase = 'running'\n await updateJob({\n status: 'running',\n startedAt: new Date().toISOString(),\n progress,\n ...stepReports(),\n })\n\n const editorConfig = await resolveEditorConfig(payload, slugs.articles, options.fieldMap.content)\n const client = createWPClient(\n job.sourceUrl,\n {\n credentials: job.credentials,\n timeoutMs: options.request.timeoutMs,\n userAgent: options.request.userAgent,\n },\n args.fetchImpl,\n )\n\n // ---- Categories (full hierarchy) ----\n progress.currentPhase = 'categories'\n const wpCategories = await client.fetchCategories()\n const categoriesResult = await importCategories(payload, {\n categories: wpCategories,\n categoriesSlug: slugs.categories,\n dryRun,\n jobId: args.jobId,\n site,\n })\n const categoryIdMap = categoriesResult.idMap\n report.imported.categories.push(\n ...categoriesResult.imported.map((item) => ({ ...item, run: runNumber })),\n )\n report.errors.push(...categoriesResult.errors.map((error) => ({ ...error, run: runNumber })))\n progress.importedCategories = categoriesResult.imported.length\n await updateJob({ progress, ...stepReports() })\n\n // ---- Gather posts (two-pass: collect for full link resolution, then import) ----\n progress.currentPhase = 'posts'\n const after = job.dateFrom ? new Date(job.dateFrom).toISOString() : undefined\n const before = job.dateTo ? new Date(job.dateTo).toISOString() : undefined\n const maxPages = dryRun ? options.dryRunPageLimit : Number.POSITIVE_INFINITY\n const limit = job.limit ?? undefined\n\n const gathered: WPPost[] = []\n let page = 1\n let totalPages = 1\n do {\n const { posts, totalPages: tp } = await client.fetchPostsPage({ after, before, page, perPage: PER_PAGE })\n totalPages = tp\n gathered.push(...posts)\n progress.cursorPage = page\n page += 1\n } while (page <= totalPages && page <= maxPages && (!limit || gathered.length < limit))\n\n const postsToImport = limit ? gathered.slice(0, limit) : gathered\n progress.totalPosts = postsToImport.length\n\n // Known slugs (this run + already-imported) for internal-link resolution.\n const existingArticles = await findDocs(payload, {\n collection: slugs.articles,\n depth: 0,\n limit: 100000,\n select: { slug: true },\n })\n const knownSlugs = new Set<string>(\n existingArticles.docs.map((d) => (d as { slug?: string }).slug).filter(Boolean) as string[],\n )\n const slugByPath = new Map<string, string>()\n for (const p of postsToImport) {\n if (p.slug) {\n knownSlugs.add(p.slug)\n if (p.link) {\n slugByPath.set(pathOf(p.link), p.slug)\n }\n }\n }\n const resolveInternal = (url: string, slug: null | string): null | string => {\n const byPath = slugByPath.get(pathOf(url))\n if (byPath) {\n return byPath\n }\n const candidate = slug ?? permalinkToSlug(url)\n return candidate && knownSlugs.has(candidate) ? candidate : null\n }\n\n // With credentials, author details (incl. email) can be fetched via\n // ?context=edit — cached per WP user id across posts.\n const authorDetailCache = new Map<number, null | WPUser>()\n const enrichAuthor = async (embedded?: WPUser): Promise<undefined | WPUser> => {\n if (!embedded || embedded.email || !client.authenticated) {\n return embedded\n }\n if (!authorDetailCache.has(embedded.id)) {\n authorDetailCache.set(embedded.id, await client.fetchUser(embedded.id))\n }\n const detailed = authorDetailCache.get(embedded.id)\n return detailed?.email ? { ...embedded, email: detailed.email } : embedded\n }\n\n // ---- Import posts ----\n for (const post of postsToImport) {\n const permalinkPath = post.link ? pathOf(post.link) : `/?p=${post.id}`\n try {\n const already = await findDoneRecord(payload, { site, sourceId: post.id, sourceType: 'post' })\n if (already) {\n progress.skippedPosts += 1\n continue\n }\n\n // Featured image. Embeds can be stripped or error stubs (deleted or\n // private media), so fall back to the media endpoint.\n let coverId: null | string = null\n let featured = post._embedded?.['wp:featuredmedia']?.[0]\n if (!featured?.source_url && post.featured_media) {\n featured = (await client.fetchMedia(post.featured_media)) ?? undefined\n }\n if (featured?.source_url) {\n const result = await importImage(payload, {\n alt: featured.alt_text,\n cache: imageCache,\n dryRun,\n fetchImpl: args.fetchImpl,\n jobId: args.jobId,\n mediaSlug: slugs.media,\n site,\n sourceId: featured.id,\n timeoutMs: options.request.timeoutMs,\n url: featured.source_url,\n })\n coverId = result.mediaId\n accountImage(result, featured.id)\n }\n\n // Content: images + internal links.\n const built = await buildContent({\n articleUrl: options.articleUrl,\n editorConfig,\n html: post.content?.rendered ?? '',\n importContentImage: (src) =>\n importImage(payload, {\n cache: imageCache,\n dryRun,\n fetchImpl: args.fetchImpl,\n jobId: args.jobId,\n mediaSlug: slugs.media,\n site,\n timeoutMs: options.request.timeoutMs,\n url: src,\n }),\n mediaSlug: slugs.media,\n resolveInternal,\n siteHost: site,\n })\n for (const img of built.images) {\n accountImage(img.result, post.id)\n }\n report.links.push(...built.links.map((link) => ({ ...link, run: runNumber })))\n for (const link of built.links) {\n if (link.action === 'rewritten') {\n progress.linksRewritten += 1\n } else if (link.action === 'unresolved') {\n progress.linksUnresolved += 1\n }\n }\n\n // Cover handling: promote the first content image when there is no\n // featured image, and drop a leading duplicate of the cover so the\n // hero doesn't render twice.\n if (!coverId && options.firstImageAsCover) {\n const promoted = takeFirstUploadNode(built.content.root)\n if (promoted != null) {\n coverId = String(promoted)\n }\n } else if (coverId) {\n removeLeadingUploadNode(built.content.root, coverId)\n }\n\n // Author.\n const {\n author,\n imported: importedAuthor,\n skippedNoEmail,\n } = await resolveAuthor(payload, {\n authorsSlug: slugs.authors,\n defaultUserId: options.authorMapping.defaultUserId,\n dryRun,\n fetchImpl: args.fetchImpl,\n imageCache,\n jobId: args.jobId,\n mediaSlug: slugs.media,\n site,\n strategy: options.authorMapping.strategy,\n syntheticEmailDomain: options.authorMapping.syntheticEmailDomain,\n timeoutMs: options.request.timeoutMs,\n usersSlug: slugs.users,\n wpUser: await enrichAuthor(post._embedded?.author?.[0]),\n })\n if (importedAuthor) {\n progress.importedAuthors += 1\n report.imported.authors.push({ ...importedAuthor, run: runNumber })\n }\n if (\n skippedNoEmail &&\n !report.errors.some(\n (e) => e.scope === 'author' && e.sourceId === skippedNoEmail.sourceId,\n )\n ) {\n report.errors.push({\n message: `author \"${skippedNoEmail.name}\" has no email exposed by WordPress; user creation skipped (set authorMapping.syntheticEmailDomain or defaultUserId)`,\n run: runNumber,\n scope: 'author',\n sourceId: skippedNoEmail.sourceId,\n })\n }\n\n // Assemble article data.\n const title = decodeEntities(post.title?.rendered ?? post.slug ?? `post-${post.id}`)\n const primaryCategory = selectPrimaryCategoryId(post)\n const categoryId = primaryCategory != null ? categoryIdMap.get(primaryCategory) : undefined\n const data: Record<string, unknown> = {\n [options.fieldMap.title]: title,\n [options.fieldMap.content]: built.content,\n _status: 'published',\n }\n if (post.slug) {\n data[options.fieldMap.slug] = post.slug\n }\n if (coverId) {\n data[options.fieldMap.coverImage] = coerceId(coverId)\n }\n if (categoryId != null) {\n data[options.fieldMap.category] = coerceId(categoryId)\n }\n const date = publishDate(post)\n if (date) {\n data[options.fieldMap.publishedAt] = date\n }\n if (author) {\n data[author.field] = coerceId(author.value)\n }\n // SEO meta: title from the post title, image from the cover image,\n // description from the excerpt (when enabled). Silently ignored by\n // Payload when the target collection has no `meta` group.\n const meta: Record<string, unknown> = { title }\n if (coverId) {\n meta.image = coerceId(coverId)\n }\n if (options.excerptToSeoDescription && post.excerpt?.rendered) {\n meta.description = stripHtml(post.excerpt.rendered).slice(0, SEO_DESCRIPTION_MAX)\n }\n data.meta = meta\n\n if (dryRun) {\n report.imported.posts.push({\n run: runNumber,\n slug: post.slug,\n sourceId: post.id,\n targetId: 'dry-run',\n title,\n })\n progress.importedPosts += 1\n continue\n }\n\n const created = await createDoc(payload, {\n collection: slugs.articles,\n data,\n })\n const articleId = created.id\n await saveRecord(payload, {\n jobId: args.jobId,\n site,\n sourceId: post.id,\n sourceKey: permalinkPath,\n sourceType: 'post',\n targetCollection: slugs.articles,\n targetId: articleId,\n })\n report.imported.posts.push({\n run: runNumber,\n slug: post.slug,\n sourceId: post.id,\n targetId: articleId,\n title,\n })\n progress.importedPosts += 1\n\n // Redirect old permalink → new article.\n if (options.redirects) {\n const made = await createRedirect(payload, {\n articleId: coerceId(articleId),\n articlesSlug: slugs.articles,\n from: permalinkPath,\n })\n if (made) {\n progress.redirectsCreated += 1\n report.links.push({\n action: 'redirect',\n from: permalinkPath,\n run: runNumber,\n to: options.articleUrl(post.slug),\n })\n }\n }\n\n if (progress.importedPosts % 5 === 0) {\n await updateJob({ progress, ...stepReports() })\n }\n } catch (error) {\n progress.failedPosts += 1\n const message = error instanceof Error ? error.message : String(error)\n report.errors.push({ message, run: runNumber, scope: 'post', sourceId: post.id })\n if (!dryRun) {\n await saveRecord(payload, {\n error: message,\n jobId: args.jobId,\n site,\n sourceId: post.id,\n sourceType: 'post',\n status: 'failed',\n }).catch(() => undefined)\n }\n }\n }\n\n report.remaining.posts = Math.max(0, gathered.length - postsToImport.length)\n progress.currentPhase = 'done'\n runSummary.finishedAt = new Date().toISOString()\n runSummary.progress = { ...progress }\n runSummary.status = 'completed'\n await updateJob({\n finishedAt: runSummary.finishedAt,\n progress,\n status: 'completed',\n ...stepReports(),\n })\n return report\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n report.errors.push({ message, run: runNumber, scope: 'run' })\n progress.currentPhase = 'failed'\n runSummary.finishedAt = new Date().toISOString()\n runSummary.progress = { ...progress }\n runSummary.status = 'failed'\n await updateJob({\n finishedAt: runSummary.finishedAt,\n progress,\n status: 'failed',\n ...stepReports(),\n })\n return report\n }\n}\n","import type { TaskConfig } from 'payload'\n\nimport type { ResolvedOptions } from '../types.js'\n\nimport { TASK_SLUG } from '../defaults.js'\nimport { runImport } from './runImport.js'\n\n/**\n * Registers the `importWordpress` jobs-queue task. The handler is thin — it\n * loads the job document (by id) and delegates to `runImport`, which owns all\n * fetching, transformation, idempotency and reporting.\n */\nexport const importWordpressTask = (options: ResolvedOptions): TaskConfig<'inline'> =>\n ({\n slug: TASK_SLUG,\n handler: async ({ input, req }: { input: { jobId: number | string }; req: { payload: import('payload').Payload } }) => {\n await runImport(req.payload, { jobId: input.jobId, options })\n return { output: {} }\n },\n inputSchema: [{ name: 'jobId', type: 'text', required: true }],\n }) as unknown as TaskConfig<'inline'>\n","import type { Config } from 'payload'\n\nimport type { ComposiusPayloadPluginImportWordpressConfig } from './types.js'\n\nimport { ImportJobs } from './collections/ImportJobs.js'\nimport { ImportRecords } from './collections/ImportRecords.js'\nimport { resolveOptions } from './defaults.js'\nimport { startEndpoint, statusEndpoint } from './endpoints/index.js'\nimport { importWordpressTask } from './jobs/task.js'\n\nexport type { ComposiusPayloadPluginImportWordpressConfig } from './types.js'\nexport type { ImportProgress, ImportReport } from './types.js'\n\nconst LOG_PREFIX = '@composius/payload-plugin-import-wordpress'\n\n/**\n * Imports WordPress posts (via the REST API) into a target content collection —\n * by default the `@composius/payload-plugin-articles` `articles` collection —\n * along with their categories, authors, featured and in-content images. Images\n * are uploaded once and resized by the media collection; internal links are\n * rewritten and the rest get 301 redirects. Runs on the jobs queue and is\n * idempotent + resumable, writing a full report onto each job document.\n */\nexport const ComposiusPayloadPluginImportWordpress =\n (pluginOptions: ComposiusPayloadPluginImportWordpressConfig = {}) =>\n async (config: Config): Promise<Config> => {\n if (!config.collections) {\n config.collections = []\n }\n\n const options = resolveOptions(pluginOptions)\n // Warnings are deferred to onInit, where payload.logger is available.\n const warnings: string[] = []\n\n // Always register collections so the database schema stays consistent for\n // migrations, even when the plugin is disabled.\n config.collections.push(ImportJobs({ access: options.access }))\n config.collections.push(ImportRecords({ access: options.access }))\n\n // Register the import task so queued jobs can run (schema/queue consistency).\n config.jobs = {\n ...config.jobs,\n tasks: [...(config.jobs?.tasks ?? []), importWordpressTask(options)],\n }\n\n // Apply @payloadcms/plugin-redirects (optional peer) for internal-link\n // redirects. Dynamically imported so hosts that disable redirects (or don't\n // install the plugin) aren't forced to depend on it. Applied before the\n // `disabled` check so the `redirects` collection — and the\n // `payload_locked_documents_rels.redirects_id` column that comes with it —\n // stay in the schema once an import is done and the plugin is switched off.\n if (options.redirects) {\n try {\n const { redirectsPlugin } = await import('@payloadcms/plugin-redirects')\n // The target collection(s) become the `to.reference` relationTo.\n config = redirectsPlugin({\n collections: [options.collections.articles],\n })(config) as Config\n } catch {\n warnings.push(\n '`redirects` is enabled but `@payloadcms/plugin-redirects` is not installed; redirects will be skipped.',\n )\n }\n }\n\n // Everything below only affects runtime behavior, never the schema, so it\n // is skipped when the plugin is disabled.\n if (!pluginOptions.disabled) {\n // Endpoints for programmatic triggering / polling.\n config.endpoints = [\n ...(config.endpoints ?? []),\n startEndpoint(options.access),\n statusEndpoint(options.access),\n ]\n\n // Auto-run schedule so creating a job runs it without an external worker.\n if (pluginOptions.autoRun !== false) {\n const schedule = typeof pluginOptions.autoRun === 'object' ? pluginOptions.autoRun : {}\n const entry = { cron: schedule.cron ?? '* * * * *', queue: schedule.queue ?? 'default' }\n const jobs = (config.jobs ??= { tasks: [] })\n const existing = jobs.autoRun\n if (existing === undefined) {\n jobs.autoRun = [entry]\n } else if (Array.isArray(existing)) {\n jobs.autoRun = [...existing, entry]\n } else {\n warnings.push('`jobs.autoRun` is a function; skipping the plugin auto-run schedule.')\n }\n }\n }\n\n if (warnings.length > 0) {\n const incomingOnInit = config.onInit\n config.onInit = async (payload) => {\n if (incomingOnInit) {\n await incomingOnInit(payload)\n }\n for (const warning of warnings) {\n payload.logger.warn(`[${LOG_PREFIX}] ${warning}`)\n }\n }\n }\n\n return config\n }\n"],"mappings":"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","names":["field","created","authenticated"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@composius/payload-plugin-import-wordpress",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
4
4
  "description": "Import WordPress posts, categories, authors and images into Payload collections (idempotent, resumable, with a link/redirect report)",
5
5
  "license": "MIT",
6
6
  "author": {