@valkyrianlabs/payload-markdown-docs 0.5.1 → 0.5.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.
@@ -35,7 +35,7 @@ export const findDuplicateDesiredRouteCollisions = (routes)=>findRouteReservatio
35
35
  ownerType: 'doc',
36
36
  route
37
37
  }))).map(collisionToIssue);
38
- export const findExistingDocsRouteCollisions = async ({ collectionSlug, docsSetId, payload, routes, sourceId })=>{
38
+ export const findExistingDocsRouteCollisions = async ({ collectionSlug, docsSetId, includeDrafts = false, payload, routes, sourceId })=>{
39
39
  const normalizedRoutes = [
40
40
  ...new Set(routes.map(normalizeRoutePath))
41
41
  ];
@@ -45,6 +45,7 @@ export const findExistingDocsRouteCollisions = async ({ collectionSlug, docsSetI
45
45
  const result = await payload.find({
46
46
  collection: collectionSlug,
47
47
  depth: 0,
48
+ draft: includeDrafts,
48
49
  limit: 1000,
49
50
  overrideAccess: true,
50
51
  where: {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/payload/routeCollisions.ts"],"sourcesContent":["import type { DocsRouteCollision } from '../routing/index.js'\n\nimport {\n findPageRouteCollisions,\n findRouteReservationCollisions,\n normalizeRoutePath,\n} from '../routing/index.js'\n\nexport type RouteCollisionPayloadOperations = {\n find: (args: {\n collection: string\n depth?: number\n limit?: number\n overrideAccess?: boolean\n where?: unknown\n }) => Promise<{\n docs: unknown[]\n }>\n}\n\nexport type DocsRouteCollisionIssue = {\n reason: string\n route: string\n}\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === 'object' && value !== null && !Array.isArray(value)\n\nconst getRecordId = (doc: Record<string, unknown>): string | undefined => {\n if (typeof doc.id === 'string' || typeof doc.id === 'number') {\n return String(doc.id)\n }\n\n return undefined\n}\n\nconst getRelationshipId = (value: unknown): string | undefined => {\n if (typeof value === 'string' || typeof value === 'number') {\n return String(value)\n }\n\n if (isRecord(value)) {\n return getRecordId(value)\n }\n\n return undefined\n}\n\nconst getNestedString = (\n value: Record<string, unknown>,\n dottedPath: string,\n): string | undefined => {\n const segments = dottedPath.split('.')\n let current: unknown = value\n\n for (const segment of segments) {\n if (!isRecord(current)) {\n return undefined\n }\n\n current = current[segment]\n }\n\n return typeof current === 'string' ? current : undefined\n}\n\nconst collisionToIssue = (collision: DocsRouteCollision): DocsRouteCollisionIssue => ({\n reason: collision.reason,\n route: collision.first.route === collision.second.route\n ? collision.first.route\n : `${collision.first.route} <> ${collision.second.route}`,\n})\n\nexport const findDuplicateDesiredRouteCollisions = (\n routes: string[],\n): DocsRouteCollisionIssue[] =>\n findRouteReservationCollisions(\n routes.map((route, index) => ({\n ownerId: `desired-${index}`,\n ownerType: 'doc',\n route,\n })),\n ).map(collisionToIssue)\n\nexport const findExistingDocsRouteCollisions = async ({\n collectionSlug,\n docsSetId,\n payload,\n routes,\n sourceId,\n}: {\n collectionSlug: string\n docsSetId?: number | string\n payload: RouteCollisionPayloadOperations\n routes: string[]\n sourceId: string\n}): Promise<DocsRouteCollisionIssue[]> => {\n const normalizedRoutes = [...new Set(routes.map(normalizeRoutePath))]\n\n if (normalizedRoutes.length === 0) {\n return []\n }\n\n const result = await payload.find({\n collection: collectionSlug,\n depth: 0,\n limit: 1000,\n overrideAccess: true,\n where: {\n route: {\n in: normalizedRoutes,\n },\n },\n })\n\n return result.docs.flatMap((doc) => {\n if (!isRecord(doc) || typeof doc.route !== 'string') {\n return []\n }\n\n const existingDocsSetId = getRelationshipId(doc.docsSet)\n const existingSourceId = getNestedString(doc, 'sync.sourceId')\n const sameOwner = docsSetId\n ? existingDocsSetId === String(docsSetId) ||\n (!existingDocsSetId && existingSourceId === sourceId)\n : !existingDocsSetId && existingSourceId === sourceId\n\n if (sameOwner) {\n return []\n }\n\n return [\n {\n reason: 'existing_doc_route_collision',\n route: normalizeRoutePath(doc.route),\n },\n ]\n })\n}\n\nexport const findConfiguredPagesRouteCollisions = async ({\n allowBridgePages,\n bridgeField,\n collectionSlug,\n docsSetRouteBase,\n payload,\n routeField,\n}: {\n allowBridgePages: boolean\n bridgeField: string\n collectionSlug: string\n docsSetRouteBase: string\n payload: RouteCollisionPayloadOperations\n routeField: string\n}): Promise<DocsRouteCollisionIssue[]> => {\n const result = await payload.find({\n collection: collectionSlug,\n depth: 0,\n limit: 1000,\n overrideAccess: true,\n })\n\n const collisions = findPageRouteCollisions({\n allowBridgePages,\n docsSetRouteBase,\n pages: result.docs.flatMap((doc) => {\n if (!isRecord(doc)) {\n return []\n }\n\n const route = getNestedString(doc, routeField)\n\n if (!route) {\n return []\n }\n\n return [\n {\n id: getRecordId(doc),\n bridge: doc[bridgeField] === true,\n route,\n },\n ]\n }),\n })\n\n return collisions.map(collisionToIssue)\n}\n"],"names":["findPageRouteCollisions","findRouteReservationCollisions","normalizeRoutePath","isRecord","value","Array","isArray","getRecordId","doc","id","String","undefined","getRelationshipId","getNestedString","dottedPath","segments","split","current","segment","collisionToIssue","collision","reason","route","first","second","findDuplicateDesiredRouteCollisions","routes","map","index","ownerId","ownerType","findExistingDocsRouteCollisions","collectionSlug","docsSetId","payload","sourceId","normalizedRoutes","Set","length","result","find","collection","depth","limit","overrideAccess","where","in","docs","flatMap","existingDocsSetId","docsSet","existingSourceId","sameOwner","findConfiguredPagesRouteCollisions","allowBridgePages","bridgeField","docsSetRouteBase","routeField","collisions","pages","bridge"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/payload/routeCollisions.ts"],"sourcesContent":["import type { DocsRouteCollision } from '../routing/index.js'\n\nimport {\n findPageRouteCollisions,\n findRouteReservationCollisions,\n normalizeRoutePath,\n} from '../routing/index.js'\n\nexport type RouteCollisionPayloadOperations = {\n find: (args: {\n collection: string\n depth?: number\n draft?: boolean\n limit?: number\n overrideAccess?: boolean\n where?: unknown\n }) => Promise<{\n docs: unknown[]\n }>\n}\n\nexport type DocsRouteCollisionIssue = {\n reason: string\n route: string\n}\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === 'object' && value !== null && !Array.isArray(value)\n\nconst getRecordId = (doc: Record<string, unknown>): string | undefined => {\n if (typeof doc.id === 'string' || typeof doc.id === 'number') {\n return String(doc.id)\n }\n\n return undefined\n}\n\nconst getRelationshipId = (value: unknown): string | undefined => {\n if (typeof value === 'string' || typeof value === 'number') {\n return String(value)\n }\n\n if (isRecord(value)) {\n return getRecordId(value)\n }\n\n return undefined\n}\n\nconst getNestedString = (\n value: Record<string, unknown>,\n dottedPath: string,\n): string | undefined => {\n const segments = dottedPath.split('.')\n let current: unknown = value\n\n for (const segment of segments) {\n if (!isRecord(current)) {\n return undefined\n }\n\n current = current[segment]\n }\n\n return typeof current === 'string' ? current : undefined\n}\n\nconst collisionToIssue = (collision: DocsRouteCollision): DocsRouteCollisionIssue => ({\n reason: collision.reason,\n route:\n collision.first.route === collision.second.route\n ? collision.first.route\n : `${collision.first.route} <> ${collision.second.route}`,\n})\n\nexport const findDuplicateDesiredRouteCollisions = (routes: string[]): DocsRouteCollisionIssue[] =>\n findRouteReservationCollisions(\n routes.map((route, index) => ({\n ownerId: `desired-${index}`,\n ownerType: 'doc',\n route,\n })),\n ).map(collisionToIssue)\n\nexport const findExistingDocsRouteCollisions = async ({\n collectionSlug,\n docsSetId,\n includeDrafts = false,\n payload,\n routes,\n sourceId,\n}: {\n collectionSlug: string\n docsSetId?: number | string\n includeDrafts?: boolean\n payload: RouteCollisionPayloadOperations\n routes: string[]\n sourceId: string\n}): Promise<DocsRouteCollisionIssue[]> => {\n const normalizedRoutes = [...new Set(routes.map(normalizeRoutePath))]\n\n if (normalizedRoutes.length === 0) {\n return []\n }\n\n const result = await payload.find({\n collection: collectionSlug,\n depth: 0,\n draft: includeDrafts,\n limit: 1000,\n overrideAccess: true,\n where: {\n route: {\n in: normalizedRoutes,\n },\n },\n })\n\n return result.docs.flatMap((doc) => {\n if (!isRecord(doc) || typeof doc.route !== 'string') {\n return []\n }\n\n const existingDocsSetId = getRelationshipId(doc.docsSet)\n const existingSourceId = getNestedString(doc, 'sync.sourceId')\n const sameOwner = docsSetId\n ? existingDocsSetId === String(docsSetId) ||\n (!existingDocsSetId && existingSourceId === sourceId)\n : !existingDocsSetId && existingSourceId === sourceId\n\n if (sameOwner) {\n return []\n }\n\n return [\n {\n reason: 'existing_doc_route_collision',\n route: normalizeRoutePath(doc.route),\n },\n ]\n })\n}\n\nexport const findConfiguredPagesRouteCollisions = async ({\n allowBridgePages,\n bridgeField,\n collectionSlug,\n docsSetRouteBase,\n payload,\n routeField,\n}: {\n allowBridgePages: boolean\n bridgeField: string\n collectionSlug: string\n docsSetRouteBase: string\n payload: RouteCollisionPayloadOperations\n routeField: string\n}): Promise<DocsRouteCollisionIssue[]> => {\n const result = await payload.find({\n collection: collectionSlug,\n depth: 0,\n limit: 1000,\n overrideAccess: true,\n })\n\n const collisions = findPageRouteCollisions({\n allowBridgePages,\n docsSetRouteBase,\n pages: result.docs.flatMap((doc) => {\n if (!isRecord(doc)) {\n return []\n }\n\n const route = getNestedString(doc, routeField)\n\n if (!route) {\n return []\n }\n\n return [\n {\n id: getRecordId(doc),\n bridge: doc[bridgeField] === true,\n route,\n },\n ]\n }),\n })\n\n return collisions.map(collisionToIssue)\n}\n"],"names":["findPageRouteCollisions","findRouteReservationCollisions","normalizeRoutePath","isRecord","value","Array","isArray","getRecordId","doc","id","String","undefined","getRelationshipId","getNestedString","dottedPath","segments","split","current","segment","collisionToIssue","collision","reason","route","first","second","findDuplicateDesiredRouteCollisions","routes","map","index","ownerId","ownerType","findExistingDocsRouteCollisions","collectionSlug","docsSetId","includeDrafts","payload","sourceId","normalizedRoutes","Set","length","result","find","collection","depth","draft","limit","overrideAccess","where","in","docs","flatMap","existingDocsSetId","docsSet","existingSourceId","sameOwner","findConfiguredPagesRouteCollisions","allowBridgePages","bridgeField","docsSetRouteBase","routeField","collisions","pages","bridge"],"mappings":"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"}
@@ -5,6 +5,7 @@ export type ExistingDocsRecord = {
5
5
  route: string;
6
6
  sourceHash?: string;
7
7
  sourcePath: string;
8
+ status?: 'draft' | 'published';
8
9
  title?: string;
9
10
  };
10
11
  export type PlannedDocChange = {
package/dist/sync/plan.js CHANGED
@@ -33,7 +33,9 @@ export const planDocsSync = ({ deleteBehavior, desired, existing })=>{
33
33
  });
34
34
  continue;
35
35
  }
36
- if (current.sourceHash === desiredFile.sha256) {
36
+ const desiredStatus = desired.publish ? 'published' : 'draft';
37
+ const hasStatusMismatch = current.status !== undefined && current.status !== desiredStatus;
38
+ if (current.sourceHash === desiredFile.sha256 && !hasStatusMismatch) {
37
39
  plan.unchanged.push({
38
40
  current,
39
41
  desired: desiredFile,
@@ -45,7 +47,7 @@ export const planDocsSync = ({ deleteBehavior, desired, existing })=>{
45
47
  plan.update.push({
46
48
  current,
47
49
  desired: desiredFile,
48
- reason: 'Existing source hash differs from desired source hash.',
50
+ reason: hasStatusMismatch ? 'Existing draft status differs from desired publish state.' : 'Existing source hash differs from desired source hash.',
49
51
  sourcePath: desiredFile.path
50
52
  });
51
53
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/sync/plan.ts"],"sourcesContent":["import type {\n DocsDeleteBehavior,\n ValidatedDocsManifest,\n ValidatedDocsManifestFile,\n} from './manifest.js'\nimport type { DocsValidationIssue } from './validate.js'\n\nexport type ExistingDocsRecord = {\n archived?: boolean\n route: string\n sourceHash?: string\n sourcePath: string\n title?: string\n}\n\nexport type PlannedDocChange = {\n current?: ExistingDocsRecord\n desired?: ValidatedDocsManifestFile\n reason: string\n sourcePath: string\n}\n\nexport type DocsSyncPlan = {\n archive: PlannedDocChange[]\n create: PlannedDocChange[]\n delete: PlannedDocChange[]\n draft: PlannedDocChange[]\n unchanged: PlannedDocChange[]\n update: PlannedDocChange[]\n warnings: DocsValidationIssue[]\n}\n\nconst createEmptyPlan = (): DocsSyncPlan => ({\n archive: [],\n create: [],\n delete: [],\n draft: [],\n unchanged: [],\n update: [],\n warnings: [],\n})\n\nexport const planDocsSync = ({\n deleteBehavior,\n desired,\n existing,\n}: {\n deleteBehavior?: DocsDeleteBehavior\n desired: ValidatedDocsManifest\n existing: ExistingDocsRecord[]\n}): DocsSyncPlan => {\n const plan = createEmptyPlan()\n const effectiveDeleteBehavior = deleteBehavior ?? desired.deleteBehavior ?? 'archive'\n const existingBySourcePath = new Map<string, ExistingDocsRecord>()\n\n for (const existingRecord of existing) {\n if (existingBySourcePath.has(existingRecord.sourcePath)) {\n plan.warnings.push({\n code: 'duplicate_existing_path',\n message: `Existing docs contain duplicate sourcePath \"${existingRecord.sourcePath}\".`,\n path: existingRecord.sourcePath,\n })\n continue\n }\n\n existingBySourcePath.set(existingRecord.sourcePath, existingRecord)\n }\n\n const desiredSourcePaths = new Set(desired.files.map((file) => file.path))\n\n for (const desiredFile of desired.files) {\n const current = existingBySourcePath.get(desiredFile.path)\n\n if (!current) {\n plan.create.push({\n desired: desiredFile,\n reason: 'No existing doc has this sourcePath.',\n sourcePath: desiredFile.path,\n })\n continue\n }\n\n if (current.sourceHash === desiredFile.sha256) {\n plan.unchanged.push({\n current,\n desired: desiredFile,\n reason: 'Existing source hash matches desired source hash.',\n sourcePath: desiredFile.path,\n })\n continue\n }\n\n plan.update.push({\n current,\n desired: desiredFile,\n reason: 'Existing source hash differs from desired source hash.',\n sourcePath: desiredFile.path,\n })\n }\n\n for (const current of existingBySourcePath.values()) {\n if (desiredSourcePaths.has(current.sourcePath)) {\n continue\n }\n\n const change = {\n current,\n reason: 'Existing doc is missing from desired manifest.',\n sourcePath: current.sourcePath,\n }\n\n if (effectiveDeleteBehavior === 'archive') {\n plan.archive.push(change)\n } else if (effectiveDeleteBehavior === 'delete') {\n plan.delete.push(change)\n } else if (effectiveDeleteBehavior === 'draft') {\n plan.draft.push(change)\n }\n }\n\n return plan\n}\n"],"names":["createEmptyPlan","archive","create","delete","draft","unchanged","update","warnings","planDocsSync","deleteBehavior","desired","existing","plan","effectiveDeleteBehavior","existingBySourcePath","Map","existingRecord","has","sourcePath","push","code","message","path","set","desiredSourcePaths","Set","files","map","file","desiredFile","current","get","reason","sourceHash","sha256","values","change"],"mappings":"AAgCA,MAAMA,kBAAkB,IAAqB,CAAA;QAC3CC,SAAS,EAAE;QACXC,QAAQ,EAAE;QACVC,QAAQ,EAAE;QACVC,OAAO,EAAE;QACTC,WAAW,EAAE;QACbC,QAAQ,EAAE;QACVC,UAAU,EAAE;IACd,CAAA;AAEA,OAAO,MAAMC,eAAe,CAAC,EAC3BC,cAAc,EACdC,OAAO,EACPC,QAAQ,EAKT;IACC,MAAMC,OAAOZ;IACb,MAAMa,0BAA0BJ,kBAAkBC,QAAQD,cAAc,IAAI;IAC5E,MAAMK,uBAAuB,IAAIC;IAEjC,KAAK,MAAMC,kBAAkBL,SAAU;QACrC,IAAIG,qBAAqBG,GAAG,CAACD,eAAeE,UAAU,GAAG;YACvDN,KAAKL,QAAQ,CAACY,IAAI,CAAC;gBACjBC,MAAM;gBACNC,SAAS,CAAC,4CAA4C,EAAEL,eAAeE,UAAU,CAAC,EAAE,CAAC;gBACrFI,MAAMN,eAAeE,UAAU;YACjC;YACA;QACF;QAEAJ,qBAAqBS,GAAG,CAACP,eAAeE,UAAU,EAAEF;IACtD;IAEA,MAAMQ,qBAAqB,IAAIC,IAAIf,QAAQgB,KAAK,CAACC,GAAG,CAAC,CAACC,OAASA,KAAKN,IAAI;IAExE,KAAK,MAAMO,eAAenB,QAAQgB,KAAK,CAAE;QACvC,MAAMI,UAAUhB,qBAAqBiB,GAAG,CAACF,YAAYP,IAAI;QAEzD,IAAI,CAACQ,SAAS;YACZlB,KAAKV,MAAM,CAACiB,IAAI,CAAC;gBACfT,SAASmB;gBACTG,QAAQ;gBACRd,YAAYW,YAAYP,IAAI;YAC9B;YACA;QACF;QAEA,IAAIQ,QAAQG,UAAU,KAAKJ,YAAYK,MAAM,EAAE;YAC7CtB,KAAKP,SAAS,CAACc,IAAI,CAAC;gBAClBW;gBACApB,SAASmB;gBACTG,QAAQ;gBACRd,YAAYW,YAAYP,IAAI;YAC9B;YACA;QACF;QAEAV,KAAKN,MAAM,CAACa,IAAI,CAAC;YACfW;YACApB,SAASmB;YACTG,QAAQ;YACRd,YAAYW,YAAYP,IAAI;QAC9B;IACF;IAEA,KAAK,MAAMQ,WAAWhB,qBAAqBqB,MAAM,GAAI;QACnD,IAAIX,mBAAmBP,GAAG,CAACa,QAAQZ,UAAU,GAAG;YAC9C;QACF;QAEA,MAAMkB,SAAS;YACbN;YACAE,QAAQ;YACRd,YAAYY,QAAQZ,UAAU;QAChC;QAEA,IAAIL,4BAA4B,WAAW;YACzCD,KAAKX,OAAO,CAACkB,IAAI,CAACiB;QACpB,OAAO,IAAIvB,4BAA4B,UAAU;YAC/CD,KAAKT,MAAM,CAACgB,IAAI,CAACiB;QACnB,OAAO,IAAIvB,4BAA4B,SAAS;YAC9CD,KAAKR,KAAK,CAACe,IAAI,CAACiB;QAClB;IACF;IAEA,OAAOxB;AACT,EAAC"}
1
+ {"version":3,"sources":["../../src/sync/plan.ts"],"sourcesContent":["import type {\n DocsDeleteBehavior,\n ValidatedDocsManifest,\n ValidatedDocsManifestFile,\n} from './manifest.js'\nimport type { DocsValidationIssue } from './validate.js'\n\nexport type ExistingDocsRecord = {\n archived?: boolean\n route: string\n sourceHash?: string\n sourcePath: string\n status?: 'draft' | 'published'\n title?: string\n}\n\nexport type PlannedDocChange = {\n current?: ExistingDocsRecord\n desired?: ValidatedDocsManifestFile\n reason: string\n sourcePath: string\n}\n\nexport type DocsSyncPlan = {\n archive: PlannedDocChange[]\n create: PlannedDocChange[]\n delete: PlannedDocChange[]\n draft: PlannedDocChange[]\n unchanged: PlannedDocChange[]\n update: PlannedDocChange[]\n warnings: DocsValidationIssue[]\n}\n\nconst createEmptyPlan = (): DocsSyncPlan => ({\n archive: [],\n create: [],\n delete: [],\n draft: [],\n unchanged: [],\n update: [],\n warnings: [],\n})\n\nexport const planDocsSync = ({\n deleteBehavior,\n desired,\n existing,\n}: {\n deleteBehavior?: DocsDeleteBehavior\n desired: ValidatedDocsManifest\n existing: ExistingDocsRecord[]\n}): DocsSyncPlan => {\n const plan = createEmptyPlan()\n const effectiveDeleteBehavior = deleteBehavior ?? desired.deleteBehavior ?? 'archive'\n const existingBySourcePath = new Map<string, ExistingDocsRecord>()\n\n for (const existingRecord of existing) {\n if (existingBySourcePath.has(existingRecord.sourcePath)) {\n plan.warnings.push({\n code: 'duplicate_existing_path',\n message: `Existing docs contain duplicate sourcePath \"${existingRecord.sourcePath}\".`,\n path: existingRecord.sourcePath,\n })\n continue\n }\n\n existingBySourcePath.set(existingRecord.sourcePath, existingRecord)\n }\n\n const desiredSourcePaths = new Set(desired.files.map((file) => file.path))\n\n for (const desiredFile of desired.files) {\n const current = existingBySourcePath.get(desiredFile.path)\n\n if (!current) {\n plan.create.push({\n desired: desiredFile,\n reason: 'No existing doc has this sourcePath.',\n sourcePath: desiredFile.path,\n })\n continue\n }\n\n const desiredStatus = desired.publish ? 'published' : 'draft'\n const hasStatusMismatch = current.status !== undefined && current.status !== desiredStatus\n\n if (current.sourceHash === desiredFile.sha256 && !hasStatusMismatch) {\n plan.unchanged.push({\n current,\n desired: desiredFile,\n reason: 'Existing source hash matches desired source hash.',\n sourcePath: desiredFile.path,\n })\n continue\n }\n\n plan.update.push({\n current,\n desired: desiredFile,\n reason: hasStatusMismatch\n ? 'Existing draft status differs from desired publish state.'\n : 'Existing source hash differs from desired source hash.',\n sourcePath: desiredFile.path,\n })\n }\n\n for (const current of existingBySourcePath.values()) {\n if (desiredSourcePaths.has(current.sourcePath)) {\n continue\n }\n\n const change = {\n current,\n reason: 'Existing doc is missing from desired manifest.',\n sourcePath: current.sourcePath,\n }\n\n if (effectiveDeleteBehavior === 'archive') {\n plan.archive.push(change)\n } else if (effectiveDeleteBehavior === 'delete') {\n plan.delete.push(change)\n } else if (effectiveDeleteBehavior === 'draft') {\n plan.draft.push(change)\n }\n }\n\n return plan\n}\n"],"names":["createEmptyPlan","archive","create","delete","draft","unchanged","update","warnings","planDocsSync","deleteBehavior","desired","existing","plan","effectiveDeleteBehavior","existingBySourcePath","Map","existingRecord","has","sourcePath","push","code","message","path","set","desiredSourcePaths","Set","files","map","file","desiredFile","current","get","reason","desiredStatus","publish","hasStatusMismatch","status","undefined","sourceHash","sha256","values","change"],"mappings":"AAiCA,MAAMA,kBAAkB,IAAqB,CAAA;QAC3CC,SAAS,EAAE;QACXC,QAAQ,EAAE;QACVC,QAAQ,EAAE;QACVC,OAAO,EAAE;QACTC,WAAW,EAAE;QACbC,QAAQ,EAAE;QACVC,UAAU,EAAE;IACd,CAAA;AAEA,OAAO,MAAMC,eAAe,CAAC,EAC3BC,cAAc,EACdC,OAAO,EACPC,QAAQ,EAKT;IACC,MAAMC,OAAOZ;IACb,MAAMa,0BAA0BJ,kBAAkBC,QAAQD,cAAc,IAAI;IAC5E,MAAMK,uBAAuB,IAAIC;IAEjC,KAAK,MAAMC,kBAAkBL,SAAU;QACrC,IAAIG,qBAAqBG,GAAG,CAACD,eAAeE,UAAU,GAAG;YACvDN,KAAKL,QAAQ,CAACY,IAAI,CAAC;gBACjBC,MAAM;gBACNC,SAAS,CAAC,4CAA4C,EAAEL,eAAeE,UAAU,CAAC,EAAE,CAAC;gBACrFI,MAAMN,eAAeE,UAAU;YACjC;YACA;QACF;QAEAJ,qBAAqBS,GAAG,CAACP,eAAeE,UAAU,EAAEF;IACtD;IAEA,MAAMQ,qBAAqB,IAAIC,IAAIf,QAAQgB,KAAK,CAACC,GAAG,CAAC,CAACC,OAASA,KAAKN,IAAI;IAExE,KAAK,MAAMO,eAAenB,QAAQgB,KAAK,CAAE;QACvC,MAAMI,UAAUhB,qBAAqBiB,GAAG,CAACF,YAAYP,IAAI;QAEzD,IAAI,CAACQ,SAAS;YACZlB,KAAKV,MAAM,CAACiB,IAAI,CAAC;gBACfT,SAASmB;gBACTG,QAAQ;gBACRd,YAAYW,YAAYP,IAAI;YAC9B;YACA;QACF;QAEA,MAAMW,gBAAgBvB,QAAQwB,OAAO,GAAG,cAAc;QACtD,MAAMC,oBAAoBL,QAAQM,MAAM,KAAKC,aAAaP,QAAQM,MAAM,KAAKH;QAE7E,IAAIH,QAAQQ,UAAU,KAAKT,YAAYU,MAAM,IAAI,CAACJ,mBAAmB;YACnEvB,KAAKP,SAAS,CAACc,IAAI,CAAC;gBAClBW;gBACApB,SAASmB;gBACTG,QAAQ;gBACRd,YAAYW,YAAYP,IAAI;YAC9B;YACA;QACF;QAEAV,KAAKN,MAAM,CAACa,IAAI,CAAC;YACfW;YACApB,SAASmB;YACTG,QAAQG,oBACJ,8DACA;YACJjB,YAAYW,YAAYP,IAAI;QAC9B;IACF;IAEA,KAAK,MAAMQ,WAAWhB,qBAAqB0B,MAAM,GAAI;QACnD,IAAIhB,mBAAmBP,GAAG,CAACa,QAAQZ,UAAU,GAAG;YAC9C;QACF;QAEA,MAAMuB,SAAS;YACbX;YACAE,QAAQ;YACRd,YAAYY,QAAQZ,UAAU;QAChC;QAEA,IAAIL,4BAA4B,WAAW;YACzCD,KAAKX,OAAO,CAACkB,IAAI,CAACsB;QACpB,OAAO,IAAI5B,4BAA4B,UAAU;YAC/CD,KAAKT,MAAM,CAACgB,IAAI,CAACsB;QACnB,OAAO,IAAI5B,4BAA4B,SAAS;YAC9CD,KAAKR,KAAK,CAACe,IAAI,CAACsB;QAClB;IACF;IAEA,OAAO7B;AACT,EAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@valkyrianlabs/payload-markdown-docs",
3
- "version": "0.5.1",
3
+ "version": "0.5.2",
4
4
  "description": "Git-backed Markdown documentation sync for Payload CMS, powered by payload-markdown.",
5
5
  "bin": {
6
6
  "payload-markdown-docs": "./dist/cli/index.js"