@valkyrianlabs/payload-markdown-docs 0.4.3 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/dist/admin/DocsSetManager.js +7 -40
  2. package/dist/admin/DocsSetManager.js.map +1 -1
  3. package/dist/cli/commands/push.js.map +1 -1
  4. package/dist/cli/format.d.ts +1 -3
  5. package/dist/cli/format.js +1 -2
  6. package/dist/cli/format.js.map +1 -1
  7. package/dist/collections/docs.js +18 -0
  8. package/dist/collections/docs.js.map +1 -1
  9. package/dist/collections/docsSets.d.ts +1 -3
  10. package/dist/collections/docsSets.js +17 -10
  11. package/dist/collections/docsSets.js.map +1 -1
  12. package/dist/collections/syncRuns.js +0 -9
  13. package/dist/collections/syncRuns.js.map +1 -1
  14. package/dist/endpoints/index.d.ts +0 -2
  15. package/dist/endpoints/index.js +0 -1
  16. package/dist/endpoints/index.js.map +1 -1
  17. package/dist/endpoints/sync.d.ts +0 -2
  18. package/dist/endpoints/sync.js +4 -15
  19. package/dist/endpoints/sync.js.map +1 -1
  20. package/dist/next/records.d.ts +4 -0
  21. package/dist/next/records.js +7 -0
  22. package/dist/next/records.js.map +1 -1
  23. package/dist/next/route.js +34 -13
  24. package/dist/next/route.js.map +1 -1
  25. package/dist/next/types.d.ts +1 -0
  26. package/dist/next/types.js.map +1 -1
  27. package/dist/payload/applyDocsSync.d.ts +2 -3
  28. package/dist/payload/applyDocsSync.js +4 -6
  29. package/dist/payload/applyDocsSync.js.map +1 -1
  30. package/dist/payload/docsConflicts.js +12 -1
  31. package/dist/payload/docsConflicts.js.map +1 -1
  32. package/dist/payload/docsData.d.ts +2 -5
  33. package/dist/payload/docsData.js +6 -8
  34. package/dist/payload/docsData.js.map +1 -1
  35. package/dist/payload/existingDocs.d.ts +1 -0
  36. package/dist/payload/existingDocs.js +1 -0
  37. package/dist/payload/existingDocs.js.map +1 -1
  38. package/dist/payload/index.d.ts +11 -11
  39. package/dist/payload/index.js.map +1 -1
  40. package/dist/payload/populatePublishedAt.d.ts +2 -0
  41. package/dist/payload/populatePublishedAt.js +14 -0
  42. package/dist/payload/populatePublishedAt.js.map +1 -0
  43. package/dist/payload/syncRuns.d.ts +1 -2
  44. package/dist/payload/syncRuns.js +1 -2
  45. package/dist/payload/syncRuns.js.map +1 -1
  46. package/dist/plugin.js +0 -3
  47. package/dist/plugin.js.map +1 -1
  48. package/dist/skills/codex/reference/admin.md +0 -1
  49. package/dist/types.d.ts +0 -1
  50. package/dist/types.js.map +1 -1
  51. package/package.json +1 -1
  52. package/dist/endpoints/publishGeneratedDocs.d.ts +0 -6
  53. package/dist/endpoints/publishGeneratedDocs.js +0 -76
  54. package/dist/endpoints/publishGeneratedDocs.js.map +0 -1
  55. package/dist/payload/publishGeneratedDocs.d.ts +0 -29
  56. package/dist/payload/publishGeneratedDocs.js +0 -78
  57. package/dist/payload/publishGeneratedDocs.js.map +0 -1
@@ -98,20 +98,13 @@ const getPlannedConflictChanges = ({ existing, plan })=>{
98
98
  ...archivedUnchanged
99
99
  ];
100
100
  };
101
- const getDefaultPublishMode = (options)=>options.defaultPublishMode ?? (options.docsEnableDrafts ? 'draft' : 'preserve');
102
- const getLifecyclePolicyError = ({ deleteBehavior, manifest, options, publishMode })=>{
101
+ const getLifecyclePolicyError = ({ deleteBehavior, manifest, options })=>{
103
102
  if (manifest.publish && options.allowPublish !== true) {
104
103
  return errorResponse('publish_disabled', 'Publishing is disabled by server configuration.', 403);
105
104
  }
106
- if ((manifest.publish || publishMode === 'published') && !options.docsEnableDrafts) {
105
+ if (manifest.publish && !options.docsEnableDrafts) {
107
106
  return errorResponse('publish_not_available', 'Publishing requires a draft-enabled dedicated docs collection.', 400);
108
107
  }
109
- if (publishMode === 'published' && options.allowPublish !== true) {
110
- return errorResponse('publish_disabled', 'Publishing is disabled by server configuration.', 403);
111
- }
112
- if (publishMode === 'draft' && !options.docsEnableDrafts) {
113
- return errorResponse('draft_behavior_not_available', 'Draft mode requires a draft-enabled dedicated docs collection.', 400);
114
- }
115
108
  if (deleteBehavior === 'draft' && !options.docsEnableDrafts) {
116
109
  return errorResponse('draft_behavior_not_available', 'Draft delete behavior requires a draft-enabled dedicated docs collection.', 400);
117
110
  }
@@ -434,12 +427,10 @@ const createSyncEndpointHandler = (options)=>async (req)=>{
434
427
  }, 400);
435
428
  }
436
429
  const effectiveDeleteBehavior = options.deleteBehavior ?? 'archive';
437
- const effectivePublishMode = validation.data.publish ? 'published' : getDefaultPublishMode(options);
438
430
  const lifecyclePolicyError = getLifecyclePolicyError({
439
431
  deleteBehavior: effectiveDeleteBehavior,
440
432
  manifest: validation.data,
441
- options,
442
- publishMode: effectivePublishMode
433
+ options
443
434
  });
444
435
  if (lifecyclePolicyError) {
445
436
  return lifecyclePolicyError;
@@ -528,7 +519,6 @@ const createSyncEndpointHandler = (options)=>async (req)=>{
528
519
  commit: authentication.identity.commit ?? validation.data.source.commit,
529
520
  completedAt: isSyncMode ? startedAt : options.getNow?.() ?? new Date(),
530
521
  deleteBehavior: effectiveDeleteBehavior,
531
- effectivePublishMode,
532
522
  errors: [],
533
523
  fileCount: validation.data.files.length,
534
524
  keyId: authentication.identity.keyId,
@@ -561,7 +551,7 @@ const createSyncEndpointHandler = (options)=>async (req)=>{
561
551
  now: options.getNow?.() ?? new Date(),
562
552
  payload: req.payload,
563
553
  plan,
564
- publishMode: effectivePublishMode,
554
+ publish: validation.data.publish,
565
555
  syncRunId
566
556
  });
567
557
  if (!applyResult.ok) {
@@ -612,7 +602,6 @@ const createSyncEndpointHandler = (options)=>async (req)=>{
612
602
  changes: serializeChanges(plan),
613
603
  deleteBehavior: effectiveDeleteBehavior,
614
604
  dryRun: !isSyncMode,
615
- effectivePublishMode,
616
605
  ok: true,
617
606
  publishRequested: validation.data.publish,
618
607
  summary,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/endpoints/sync.ts"],"sourcesContent":["import type { Endpoint, PayloadRequest } from 'payload'\n\nimport type {\n ApplyDocsSyncPayloadOperations,\n DocsKeyPayloadOperations,\n DocsPublishMode,\n DocsSetPayloadOperations,\n DocsTrustedPayloadOperations,\n ExistingDocsPayloadOperations,\n ExistingPayloadDocsRecord,\n ResolvedDocsSet,\n RouteCollisionPayloadOperations,\n SyncRunsPayloadOperations,\n} from '../payload/index.js'\nimport type {\n FetchJson,\n NoncePayloadOperations,\n} from '../security/index.js'\nimport type {\n DocsDeleteBehavior,\n DocsManifest,\n DocsValidationIssue,\n PlannedDocChange,\n ValidatedDocsManifest,\n} from '../sync/index.js'\nimport type { PayloadMarkdownDocsAuthConfig } from '../types.js'\n\nimport {\n DEFAULT_MAX_BODY_BYTES,\n DEFAULT_MAX_SKEW_SECONDS,\n DEFAULT_NONCE_TTL_SECONDS,\n} from '../constants.js'\nimport {\n applyDocsSync,\n assertApplyDeleteBehaviorSupported,\n createSyncRunAudit,\n findConfiguredPagesRouteCollisions,\n findDocsKeyById,\n findDocsSetBySlug,\n findDocsSyncConflicts,\n findDuplicateDesiredRouteCollisions,\n findExistingDocsRouteCollisions,\n findExistingPayloadDocsRecords,\n findTrustedGitHubSources,\n getRecordId,\n isEd25519AuthEnabled,\n isGitHubOidcAuthEnabled,\n toExistingDocsRecord,\n updateDocsSetAfterSync,\n updateSyncRunAudit,\n} from '../payload/index.js'\nimport {\n assertNonceNotReplayed,\n buildCanonicalSigningString,\n extractSyncRequestHeaders,\n getCanonicalPathFromRequestUrl,\n storeAcceptedNonce,\n validateTimestampSkew,\n verifyBodySha256,\n verifyEd25519Signature,\n verifyGitHubOidcToken,\n} from '../security/index.js'\nimport {\n planDocsSync,\n validateDocsManifest,\n} from '../sync/index.js'\n\nexport type DocsSyncEndpointErrorCode =\n | 'audit_unavailable'\n | 'auth_disabled'\n | 'body_hash_mismatch'\n | 'delete_behavior_not_implemented'\n | 'draft_behavior_not_available'\n | 'dry_run_required_not_implemented'\n | 'hard_delete_disabled'\n | 'invalid_body'\n | 'invalid_manifest'\n | 'invalid_method'\n | 'invalid_signature'\n | 'invalid_timestamp'\n | 'manual_edit_conflict'\n | 'missing_header'\n | 'nonce_replay'\n | 'oidc_expired'\n | 'oidc_invalid_audience'\n | 'oidc_invalid_issuer'\n | 'oidc_invalid_token'\n | 'oidc_jwks_unavailable'\n | 'oidc_missing_claim'\n | 'oidc_missing_jti'\n | 'oidc_not_yet_valid'\n | 'oidc_owner_not_allowed'\n | 'oidc_pull_request_not_allowed'\n | 'oidc_ref_not_allowed'\n | 'oidc_replay'\n | 'oidc_repository_not_allowed'\n | 'oidc_workflow_not_allowed'\n | 'publish_disabled'\n | 'publish_not_available'\n | 'replay_protection_unavailable'\n | 'route_collision'\n | 'source_not_allowed'\n | 'sync_apply_failed'\n | 'sync_mode_not_implemented'\n | 'sync_writes_disabled'\n | 'unknown_key'\n\nexport type CreateSyncEndpointOptions = {\n allowHardDelete?: boolean\n allowPublish?: boolean\n allowWrites?: boolean\n auth?: PayloadMarkdownDocsAuthConfig\n defaultPublishMode?: DocsPublishMode\n deleteBehavior?: DocsDeleteBehavior\n docsCollectionSlug: string\n docsEnabled: boolean\n docsEnableDrafts: boolean\n docsGroupsCollectionSlug: string\n docsKeysCollectionSlug: string\n docsKeysEnabled: boolean\n docsSetsCollectionSlug: string\n docsSetsEnabled: boolean\n docsTrustedCollectionSlug: string\n docsTrustedEnabled: boolean\n endpointPath: string\n getNow?: () => Date\n markdownFieldName: string\n maxBodyBytes?: number\n maxSkewSeconds?: number\n noncesCollectionSlug: string\n noncesEnabled: boolean\n nonceTtlSeconds?: number\n oidcFetchJson?: FetchJson\n requireDryRunBeforeApply?: boolean\n routing?: {\n pages?: {\n allowBridgePages: boolean\n bridgeField: string\n collection: string\n enabled: boolean\n routeField: string\n }\n }\n syncRunsCollectionSlug: string\n syncRunsEnabled: boolean\n}\n\ntype SyncErrorResponse = {\n conflicts?: {\n reason: string\n route?: string\n sourcePath: string\n }[]\n error: {\n code: DocsSyncEndpointErrorCode\n message: string\n }\n ok: false\n routeCollisions?: {\n reason: string\n route: string\n }[]\n}\n\ntype SerializedChange = {\n current?: {\n archived?: boolean\n route: string\n sourceHash?: string\n title?: string\n }\n desired?: {\n route: string\n sha256: string\n title: string\n }\n reason: string\n sourcePath: string\n}\n\ntype SyncSuccessResponse = {\n changes: {\n archive: SerializedChange[]\n create: SerializedChange[]\n delete: SerializedChange[]\n draft: SerializedChange[]\n unchanged: SerializedChange[]\n update: SerializedChange[]\n }\n deleteBehavior: DocsDeleteBehavior\n dryRun: boolean\n effectivePublishMode: DocsPublishMode\n ok: true\n publishRequested: boolean\n summary: {\n archive: number\n create: number\n delete: number\n draft: number\n unchanged: number\n update: number\n warnings: number\n }\n syncRunId?: string\n warnings: DocsValidationIssue[]\n}\n\nconst jsonResponse = (\n body: SyncErrorResponse | SyncSuccessResponse,\n status = 200,\n): Response =>\n Response.json(body, {\n status,\n })\n\nconst errorResponse = (\n code: DocsSyncEndpointErrorCode,\n message: string,\n status = 400,\n extras: Omit<SyncErrorResponse, 'error' | 'ok'> = {},\n): Response =>\n jsonResponse(\n {\n ...extras,\n error: {\n code,\n message,\n },\n ok: false,\n },\n status,\n )\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === 'object' && value !== null && !Array.isArray(value)\n\nconst parseManifestBody = (rawBody: string): DocsManifest | undefined => {\n try {\n const parsed = JSON.parse(rawBody) as unknown\n\n return isRecord(parsed) ? (parsed as DocsManifest) : undefined\n } catch {\n return undefined\n }\n}\n\ntype ResolvedSyncSource = {\n docsSet: ResolvedDocsSet\n routeBase: string\n sourceId: string\n}\n\nconst resolveSyncSource = async ({\n manifest,\n options,\n payload,\n}: {\n manifest: DocsManifest\n options: CreateSyncEndpointOptions\n payload: DocsSetPayloadOperations\n}): Promise<\n | {\n response: Response\n source?: never\n }\n | {\n response?: never\n source: ResolvedSyncSource\n }\n> => {\n const sourceId = manifest.source?.id\n\n if (!sourceId) {\n return {\n response: errorResponse(\n 'source_not_allowed',\n 'Manifest source.id is required and must match a docs set slug.',\n 400,\n ),\n }\n }\n\n const docsSet =\n options.docsSetsEnabled\n ? await findDocsSetBySlug({\n slug: sourceId,\n collectionSlug: options.docsSetsCollectionSlug,\n docsGroupsCollectionSlug: options.docsGroupsCollectionSlug,\n payload,\n })\n : undefined\n\n if (docsSet) {\n return {\n source: {\n docsSet,\n routeBase: docsSet.routeBase,\n sourceId,\n },\n }\n }\n\n return {\n response: errorResponse(\n 'source_not_allowed',\n `No docs set exists for source \"${sourceId}\". Create a docs set with slug \"${sourceId}\" in Payload Admin before syncing this source.`,\n 400,\n ),\n }\n}\n\nconst summarizePlan = (plan: ReturnType<typeof planDocsSync>) => ({\n archive: plan.archive.length,\n create: plan.create.length,\n delete: plan.delete.length,\n draft: plan.draft.length,\n unchanged: plan.unchanged.length,\n update: plan.update.length,\n warnings: plan.warnings.length,\n})\n\nconst serializeChange = (change: PlannedDocChange): SerializedChange => ({\n current: change.current\n ? {\n archived: change.current.archived,\n route: change.current.route,\n sourceHash: change.current.sourceHash,\n title: change.current.title,\n }\n : undefined,\n desired: change.desired\n ? {\n route: change.desired.route,\n sha256: change.desired.sha256,\n title: change.desired.title,\n }\n : undefined,\n reason: change.reason,\n sourcePath: change.sourcePath,\n})\n\nconst serializeChanges = (plan: ReturnType<typeof planDocsSync>) => ({\n archive: plan.archive.map(serializeChange),\n create: plan.create.map(serializeChange),\n delete: plan.delete.map(serializeChange),\n draft: plan.draft.map(serializeChange),\n unchanged: plan.unchanged.map(serializeChange),\n update: plan.update.map(serializeChange),\n})\n\nconst getTotalManifestBytes = (manifest: ValidatedDocsManifest): number =>\n manifest.files.reduce(\n (total, file) => total + Buffer.byteLength(file.content, 'utf8'),\n 0,\n )\n\nconst getPlannedConflictChanges = ({\n existing,\n plan,\n}: {\n existing: ExistingPayloadDocsRecord[]\n plan: ReturnType<typeof planDocsSync>\n}): PlannedDocChange[] => {\n const existingBySourcePath = new Map(\n existing.map((record) => [record.sourcePath, record]),\n )\n const archivedUnchanged = plan.unchanged.filter((change) => {\n const current = existingBySourcePath.get(change.sourcePath)\n\n return current?.archived === true\n })\n\n return [\n ...plan.update,\n ...plan.archive,\n ...plan.draft,\n ...plan.delete,\n ...archivedUnchanged,\n ]\n}\n\nconst getDefaultPublishMode = (\n options: CreateSyncEndpointOptions,\n): DocsPublishMode =>\n options.defaultPublishMode ?? (options.docsEnableDrafts ? 'draft' : 'preserve')\n\nconst getLifecyclePolicyError = ({\n deleteBehavior,\n manifest,\n options,\n publishMode,\n}: {\n deleteBehavior: DocsDeleteBehavior\n manifest: ValidatedDocsManifest\n options: CreateSyncEndpointOptions\n publishMode: DocsPublishMode\n}): Response | undefined => {\n if (manifest.publish && options.allowPublish !== true) {\n return errorResponse(\n 'publish_disabled',\n 'Publishing is disabled by server configuration.',\n 403,\n )\n }\n\n if (\n (manifest.publish || publishMode === 'published') &&\n !options.docsEnableDrafts\n ) {\n return errorResponse(\n 'publish_not_available',\n 'Publishing requires a draft-enabled dedicated docs collection.',\n 400,\n )\n }\n\n if (publishMode === 'published' && options.allowPublish !== true) {\n return errorResponse(\n 'publish_disabled',\n 'Publishing is disabled by server configuration.',\n 403,\n )\n }\n\n if (publishMode === 'draft' && !options.docsEnableDrafts) {\n return errorResponse(\n 'draft_behavior_not_available',\n 'Draft mode requires a draft-enabled dedicated docs collection.',\n 400,\n )\n }\n\n if (deleteBehavior === 'draft' && !options.docsEnableDrafts) {\n return errorResponse(\n 'draft_behavior_not_available',\n 'Draft delete behavior requires a draft-enabled dedicated docs collection.',\n 400,\n )\n }\n\n if (deleteBehavior === 'delete' && options.allowHardDelete !== true) {\n return errorResponse(\n 'hard_delete_disabled',\n 'Hard delete is disabled by server configuration.',\n 403,\n )\n }\n\n return undefined\n}\n\nconst getRouteCollisionIssues = async ({\n docsSet,\n manifest,\n options,\n payload,\n routeBase,\n}: {\n docsSet?: ResolvedDocsSet\n manifest: ValidatedDocsManifest\n options: CreateSyncEndpointOptions\n payload: RouteCollisionPayloadOperations\n routeBase: string\n}) => {\n const desiredRoutes = manifest.files.map((file) => file.route)\n const duplicateDesiredRouteCollisions =\n findDuplicateDesiredRouteCollisions(desiredRoutes)\n const existingDocsRouteCollisions = options.docsEnabled\n ? await findExistingDocsRouteCollisions({\n collectionSlug: options.docsCollectionSlug,\n docsSetId: docsSet?.id,\n payload,\n routes: desiredRoutes,\n sourceId: manifest.source.id,\n })\n : []\n const pageRouteCollisions =\n options.routing?.pages?.enabled === true\n ? await findConfiguredPagesRouteCollisions({\n allowBridgePages: options.routing.pages.allowBridgePages,\n bridgeField: options.routing.pages.bridgeField,\n collectionSlug: options.routing.pages.collection,\n docsSetRouteBase: routeBase,\n payload,\n routeField: options.routing.pages.routeField,\n })\n : []\n\n return [\n ...duplicateDesiredRouteCollisions,\n ...existingDocsRouteCollisions,\n ...pageRouteCollisions,\n ]\n}\n\ntype AuthenticatedSyncRequest = {\n actor?: string\n bodyHash: string\n branch?: string\n commit?: string\n expiresAt: Date\n keyId: string\n nonce: string\n repository?: string\n}\n\nconst getRequiredHeader = (\n headers: Headers,\n name: string,\n): string | undefined => {\n const value = headers.get(name)\n\n return value && value.trim() !== '' ? value.trim() : undefined\n}\n\nconst getBearerToken = (headers: Headers): string | undefined => {\n const authorization = getRequiredHeader(headers, 'authorization')\n\n if (!authorization) {\n return undefined\n }\n\n const [scheme, token] = authorization.split(/\\s+/, 2)\n\n if (scheme?.toLowerCase() !== 'bearer' || !token) {\n return ''\n }\n\n return token\n}\n\nconst hasEd25519AuthHeaders = (headers: Headers): boolean =>\n getRequiredHeader(headers, 'x-vl-md-docs-key-id') !== undefined ||\n getRequiredHeader(headers, 'x-vl-md-docs-signature') !== undefined ||\n getRequiredHeader(headers, 'x-vl-md-docs-timestamp') !== undefined ||\n getRequiredHeader(headers, 'x-vl-md-docs-nonce') !== undefined\n\nconst assertReplayProtectionAvailable = (\n options: CreateSyncEndpointOptions,\n): Response | undefined =>\n options.noncesEnabled\n ? undefined\n : errorResponse(\n 'replay_protection_unavailable',\n 'Sync endpoint requires nonce replay protection.',\n 500,\n )\n\nconst authenticateEd25519Request = async ({\n now,\n options,\n rawBody,\n req,\n}: {\n now: Date\n options: CreateSyncEndpointOptions\n rawBody: string\n req: PayloadRequest\n}): Promise<\n | {\n identity: AuthenticatedSyncRequest\n response?: never\n }\n | {\n identity?: never\n response: Response\n }\n> => {\n const headersResult = extractSyncRequestHeaders(req.headers)\n\n if (!headersResult.ok) {\n return {\n response: errorResponse(\n 'missing_header',\n `Missing required sync header: ${headersResult.header}.`,\n 401,\n ),\n }\n }\n\n if (!options.docsKeysEnabled) {\n return {\n response: errorResponse(\n 'auth_disabled',\n 'Signed sync authentication requires the docs Keys collection.',\n 401,\n ),\n }\n }\n\n const keyConfig = await findDocsKeyById({\n collectionSlug: options.docsKeysCollectionSlug,\n keyId: headersResult.headers.keyId,\n payload: req.payload as unknown as DocsKeyPayloadOperations,\n })\n\n if (!keyConfig) {\n return {\n response: errorResponse('unknown_key', 'Unknown sync request key id.', 401),\n }\n }\n\n const bodyHash = verifyBodySha256({\n body: rawBody,\n expectedHash: headersResult.headers.bodySha256,\n })\n\n if (!bodyHash.ok) {\n return {\n response: errorResponse(\n 'body_hash_mismatch',\n 'Sync request body hash does not match the signed header.',\n 401,\n ),\n }\n }\n\n const timestampValidation = validateTimestampSkew({\n maxSkewSeconds:\n options.maxSkewSeconds ??\n DEFAULT_MAX_SKEW_SECONDS,\n now,\n timestamp: headersResult.headers.timestamp,\n })\n\n if (!timestampValidation.ok) {\n return {\n response: errorResponse(\n 'invalid_timestamp',\n timestampValidation.message,\n 401,\n ),\n }\n }\n\n const replayUnavailable = assertReplayProtectionAvailable(options)\n\n if (replayUnavailable) {\n return {\n response: replayUnavailable,\n }\n }\n\n const nonceAvailable = await assertNonceNotReplayed({\n collectionSlug: options.noncesCollectionSlug,\n keyId: headersResult.headers.keyId,\n nonce: headersResult.headers.nonce,\n now,\n payload: req.payload as unknown as NoncePayloadOperations,\n })\n\n if (!nonceAvailable) {\n return {\n response: errorResponse(\n 'nonce_replay',\n 'Sync request nonce has already been used.',\n 409,\n ),\n }\n }\n\n const canonicalPath = getCanonicalPathFromRequestUrl({\n endpointPath: options.endpointPath,\n url: req.url,\n })\n const canonicalString = buildCanonicalSigningString({\n bodySha256: bodyHash.computedHash,\n method: 'POST',\n nonce: headersResult.headers.nonce,\n path: canonicalPath,\n timestamp: headersResult.headers.timestamp,\n })\n\n if (\n !verifyEd25519Signature({\n canonicalString,\n publicKey: keyConfig.publicKey,\n signature: headersResult.headers.signature,\n })\n ) {\n return {\n response: errorResponse(\n 'invalid_signature',\n 'Invalid sync request signature.',\n 401,\n ),\n }\n }\n\n const nonceTtlSeconds = options.nonceTtlSeconds ?? DEFAULT_NONCE_TTL_SECONDS\n\n return {\n identity: {\n bodyHash: bodyHash.computedHash,\n expiresAt: new Date(now.getTime() + nonceTtlSeconds * 1000),\n keyId: headersResult.headers.keyId,\n nonce: headersResult.headers.nonce,\n },\n }\n}\n\nconst authenticateGitHubOidcRequest = async ({\n docsSet,\n now,\n options,\n rawBody,\n req,\n}: {\n docsSet: ResolvedDocsSet\n now: Date\n options: CreateSyncEndpointOptions\n rawBody: string\n req: PayloadRequest\n}): Promise<\n | {\n identity: AuthenticatedSyncRequest\n response?: never\n }\n | {\n identity?: never\n response: Response\n }\n> => {\n const token = getBearerToken(req.headers)\n\n if (token === undefined) {\n return {\n response: errorResponse(\n 'missing_header',\n 'Missing required sync header: Authorization.',\n 401,\n ),\n }\n }\n\n if (token === '') {\n return {\n response: errorResponse(\n 'oidc_invalid_token',\n 'Authorization must be a Bearer GitHub OIDC token.',\n 401,\n ),\n }\n }\n\n const expectedHash = getRequiredHeader(\n req.headers,\n 'x-vl-md-docs-body-sha256',\n )\n\n if (!expectedHash) {\n return {\n response: errorResponse(\n 'missing_header',\n 'Missing required sync header: X-VL-MD-DOCS-Body-SHA256.',\n 401,\n ),\n }\n }\n\n const bodyHash = verifyBodySha256({\n body: rawBody,\n expectedHash,\n })\n\n if (!bodyHash.ok) {\n return {\n response: errorResponse(\n 'body_hash_mismatch',\n 'Sync request body hash does not match the OIDC header.',\n 401,\n ),\n }\n }\n\n if (!options.docsTrustedEnabled) {\n return {\n response: errorResponse(\n 'auth_disabled',\n 'GitHub OIDC sync authentication requires the docs Trusted collection.',\n 401,\n ),\n }\n }\n\n const trustedSources = await findTrustedGitHubSources({\n collectionSlug: options.docsTrustedCollectionSlug,\n payload: req.payload as unknown as DocsTrustedPayloadOperations,\n })\n const allowedRef = docsSet.branch.startsWith('refs/')\n ? docsSet.branch\n : `refs/heads/${docsSet.branch}`\n\n const verified = await verifyGitHubOidcToken({\n config: {\n allowedRefs: [allowedRef],\n allowedWorkflowRefs: docsSet.advancedSecurity?.allowedWorkflowRefs,\n allowPullRequests: docsSet.allowPullRequests,\n audience: docsSet.slug,\n enforceWorkflowRefs: docsSet.advancedSecurity?.enabled === true,\n trustedSources,\n },\n fetchJson: options.oidcFetchJson,\n now,\n token,\n })\n\n if (!verified.ok) {\n return {\n response: errorResponse(\n verified.code,\n verified.message,\n verified.code === 'oidc_jwks_unavailable' ? 503 : 401,\n ),\n }\n }\n\n const replayUnavailable = assertReplayProtectionAvailable(options)\n\n if (replayUnavailable) {\n return {\n response: replayUnavailable,\n }\n }\n\n const nonceAvailable = await assertNonceNotReplayed({\n collectionSlug: options.noncesCollectionSlug,\n keyId: verified.token.keyId,\n nonce: verified.token.claims.jti,\n now,\n payload: req.payload as unknown as NoncePayloadOperations,\n })\n\n if (!nonceAvailable) {\n return {\n response: errorResponse(\n 'oidc_replay',\n 'GitHub OIDC token jti has already been used.',\n 409,\n ),\n }\n }\n\n return {\n identity: {\n actor: verified.token.claims.actor,\n bodyHash: bodyHash.computedHash,\n branch: verified.token.claims.ref,\n commit: verified.token.claims.sha,\n expiresAt: verified.token.expiresAt,\n keyId: verified.token.keyId,\n nonce: verified.token.claims.jti,\n repository: verified.token.claims.repository,\n },\n }\n}\n\nconst authenticateSyncRequest = async ({\n docsSet,\n now,\n options,\n rawBody,\n req,\n}: {\n docsSet: ResolvedDocsSet\n now: Date\n options: CreateSyncEndpointOptions\n rawBody: string\n req: PayloadRequest\n}): Promise<\n | {\n identity: AuthenticatedSyncRequest\n response?: never\n }\n | {\n identity?: never\n response: Response\n }\n> => {\n const ed25519Enabled = isEd25519AuthEnabled(options.auth)\n const githubOidcEnabled = isGitHubOidcAuthEnabled(options.auth)\n\n if (!ed25519Enabled && !githubOidcEnabled) {\n return {\n response: errorResponse(\n 'auth_disabled',\n 'Sync authentication is not configured for this endpoint.',\n 401,\n ),\n }\n }\n\n const bearerToken = getBearerToken(req.headers)\n\n if (bearerToken !== undefined) {\n if (!githubOidcEnabled) {\n return {\n response: errorResponse(\n 'auth_disabled',\n 'GitHub OIDC sync authentication is not configured for this endpoint.',\n 401,\n ),\n }\n }\n\n return authenticateGitHubOidcRequest({\n docsSet,\n now,\n options,\n rawBody,\n req,\n })\n }\n\n if (hasEd25519AuthHeaders(req.headers) || !githubOidcEnabled) {\n if (!ed25519Enabled) {\n return {\n response: errorResponse(\n 'auth_disabled',\n 'Signed sync authentication is not configured for this endpoint.',\n 401,\n ),\n }\n }\n\n return authenticateEd25519Request({\n now,\n options,\n rawBody,\n req,\n })\n }\n\n return authenticateGitHubOidcRequest({\n docsSet,\n now,\n options,\n rawBody,\n req,\n })\n}\n\nconst createSyncEndpointHandler =\n (options: CreateSyncEndpointOptions) =>\n async (req: PayloadRequest): Promise<Response> => {\n const startedAt = options.getNow?.() ?? new Date()\n\n if (req.method && req.method.toUpperCase() !== 'POST') {\n return errorResponse('invalid_method', 'Sync endpoint only accepts POST.', 405)\n }\n\n if (typeof req.text !== 'function') {\n return errorResponse(\n 'invalid_body',\n 'Sync endpoint requires access to the request body text.',\n 400,\n )\n }\n\n const rawBody = await req.text()\n const maxBodyBytes = options.maxBodyBytes ?? DEFAULT_MAX_BODY_BYTES\n\n if (Buffer.byteLength(rawBody, 'utf8') > maxBodyBytes) {\n return errorResponse('invalid_body', 'Sync request body is too large.', 413)\n }\n\n const manifest = parseManifestBody(rawBody)\n\n if (!manifest) {\n return errorResponse('invalid_body', 'Sync request body must be a JSON manifest.', 400)\n }\n\n const sourceResolution = await resolveSyncSource({\n manifest,\n options,\n payload: req.payload as unknown as DocsSetPayloadOperations,\n })\n\n if (sourceResolution.response) {\n return sourceResolution.response\n }\n\n const authentication = await authenticateSyncRequest({\n docsSet: sourceResolution.source.docsSet,\n now: startedAt,\n options,\n rawBody,\n req,\n })\n\n if (authentication.response) {\n return authentication.response\n }\n\n const validation = validateDocsManifest(manifest, {\n allowedSourceIds: [sourceResolution.source.sourceId],\n maxTotalBytes: maxBodyBytes,\n routeBase: sourceResolution.source.routeBase,\n })\n\n if (!validation.ok) {\n return jsonResponse(\n {\n error: {\n code: 'invalid_manifest',\n message: 'Sync manifest is invalid.',\n },\n ok: false,\n },\n 400,\n )\n }\n\n const effectiveDeleteBehavior = options.deleteBehavior ?? 'archive'\n const effectivePublishMode: DocsPublishMode = validation.data.publish\n ? 'published'\n : getDefaultPublishMode(options)\n const lifecyclePolicyError = getLifecyclePolicyError({\n deleteBehavior: effectiveDeleteBehavior,\n manifest: validation.data,\n options,\n publishMode: effectivePublishMode,\n })\n\n if (lifecyclePolicyError) {\n return lifecyclePolicyError\n }\n\n const routeCollisions = await getRouteCollisionIssues({\n docsSet: sourceResolution.source.docsSet,\n manifest: validation.data,\n options,\n payload: req.payload as unknown as RouteCollisionPayloadOperations,\n routeBase: sourceResolution.source.routeBase,\n })\n\n if (routeCollisions.length > 0) {\n return errorResponse(\n 'route_collision',\n 'One or more docs routes collide with an existing route reservation.',\n 409,\n {\n routeCollisions,\n },\n )\n }\n\n const isSyncMode = validation.data.mode === 'sync'\n\n if (isSyncMode && options.allowWrites !== true) {\n return errorResponse(\n 'sync_writes_disabled',\n 'Sync writes are disabled by server configuration.',\n 403,\n )\n }\n\n if (isSyncMode && options.requireDryRunBeforeApply === true) {\n return errorResponse(\n 'dry_run_required_not_implemented',\n 'Required dry-run proof before apply is not implemented yet.',\n 400,\n )\n }\n\n if (\n isSyncMode &&\n !assertApplyDeleteBehaviorSupported(effectiveDeleteBehavior, {\n allowHardDelete: options.allowHardDelete,\n docsEnableDrafts: options.docsEnableDrafts,\n })\n ) {\n return errorResponse(\n 'delete_behavior_not_implemented',\n 'Configured delete behavior cannot be applied.',\n 400,\n )\n }\n\n if (isSyncMode && !options.syncRunsEnabled) {\n return errorResponse(\n 'audit_unavailable',\n 'Applied sync requires the sync-run audit collection.',\n 500,\n )\n }\n\n const existingPayloadDocs = options.docsEnabled\n ? await findExistingPayloadDocsRecords({\n collectionSlug: options.docsCollectionSlug,\n docsSetId: sourceResolution.source.docsSet?.id,\n markdownFieldName: options.markdownFieldName,\n payload: req.payload as unknown as ExistingDocsPayloadOperations,\n sourceId: validation.data.source.id,\n })\n : []\n const existingDocs = existingPayloadDocs.map(toExistingDocsRecord)\n const plan = planDocsSync({\n deleteBehavior: effectiveDeleteBehavior,\n desired: validation.data,\n existing: existingDocs,\n })\n const summary = summarizePlan(plan)\n const warnings = [...validation.warnings, ...plan.warnings]\n if (isSyncMode) {\n const existingBySourcePath = new Map(\n existingPayloadDocs.map((record) => [record.sourcePath, record]),\n )\n const conflicts = findDocsSyncConflicts({\n existingBySourcePath,\n plannedChanges: getPlannedConflictChanges({\n existing: existingPayloadDocs,\n plan,\n }),\n })\n\n if (conflicts.length > 0) {\n return errorResponse(\n 'manual_edit_conflict',\n 'One or more docs were modified outside the docs sync workflow.',\n 409,\n {\n conflicts,\n },\n )\n }\n }\n\n await storeAcceptedNonce({\n bodyHash: authentication.identity.bodyHash,\n collectionSlug: options.noncesCollectionSlug,\n expiresAt: authentication.identity.expiresAt,\n keyId: authentication.identity.keyId,\n nonce: authentication.identity.nonce,\n payload: req.payload as unknown as NoncePayloadOperations,\n sourceId: validation.data.source.id,\n usedAt: startedAt,\n })\n\n let syncRunId: number | string | undefined\n\n if (options.syncRunsEnabled) {\n const syncRun = await createSyncRunAudit({\n actor: authentication.identity.actor,\n bodyHash: authentication.identity.bodyHash,\n branch: authentication.identity.branch ?? validation.data.source.branch,\n collectionSlug: options.syncRunsCollectionSlug,\n commit: authentication.identity.commit ?? validation.data.source.commit,\n completedAt: isSyncMode ? startedAt : options.getNow?.() ?? new Date(),\n deleteBehavior: effectiveDeleteBehavior,\n effectivePublishMode,\n errors: [],\n fileCount: validation.data.files.length,\n keyId: authentication.identity.keyId,\n mode: isSyncMode ? 'sync' : 'dry-run',\n payload: req.payload as unknown as SyncRunsPayloadOperations,\n publishRequested: validation.data.publish,\n repository:\n authentication.identity.repository ?? validation.data.source.repository,\n sourceId: validation.data.source.id,\n startedAt,\n status: isSyncMode ? 'pending' : 'success',\n summary,\n totalBytes: getTotalManifestBytes(validation.data),\n warnings,\n })\n\n syncRunId = getRecordId(syncRun)\n }\n\n if (isSyncMode) {\n if (!syncRunId) {\n return errorResponse(\n 'audit_unavailable',\n 'Applied sync could not create a sync-run audit record.',\n 500,\n )\n }\n\n try {\n const applyResult = await applyDocsSync({\n collectionSlug: options.docsCollectionSlug,\n deleteBehavior: effectiveDeleteBehavior,\n docsEnableDrafts: options.docsEnableDrafts,\n docsSetId: sourceResolution.source.docsSet?.id,\n existing: existingPayloadDocs,\n manifest: validation.data,\n markdownFieldName: options.markdownFieldName,\n now: options.getNow?.() ?? new Date(),\n payload: req.payload as unknown as ApplyDocsSyncPayloadOperations,\n plan,\n publishMode: effectivePublishMode,\n syncRunId,\n })\n\n if (!applyResult.ok) {\n return errorResponse(\n 'manual_edit_conflict',\n 'One or more docs were modified outside the docs sync workflow.',\n 409,\n {\n conflicts: applyResult.conflicts,\n },\n )\n }\n\n await updateSyncRunAudit({\n collectionSlug: options.syncRunsCollectionSlug,\n completedAt: options.getNow?.() ?? new Date(),\n payload: req.payload as unknown as SyncRunsPayloadOperations,\n status: 'success',\n summary,\n syncRunId,\n warnings,\n })\n\n if (sourceResolution.source.docsSet) {\n await updateDocsSetAfterSync({\n aiExport: validation.data.aiExport,\n collectionSlug: options.docsSetsCollectionSlug,\n docsCount: validation.data.files.length,\n docsSetId: sourceResolution.source.docsSet.id,\n now: options.getNow?.() ?? new Date(),\n payload: req.payload as unknown as DocsSetPayloadOperations,\n syncRunId,\n })\n }\n } catch (error) {\n await updateSyncRunAudit({\n collectionSlug: options.syncRunsCollectionSlug,\n completedAt: options.getNow?.() ?? new Date(),\n errors: [\n {\n code: 'invalid_manifest',\n message: error instanceof Error ? error.message : 'Sync apply failed.',\n },\n ],\n payload: req.payload as unknown as SyncRunsPayloadOperations,\n status: 'failed',\n summary,\n syncRunId,\n warnings,\n })\n\n return errorResponse('sync_apply_failed', 'Sync apply failed.', 500)\n }\n }\n\n return jsonResponse({\n changes: serializeChanges(plan),\n deleteBehavior: effectiveDeleteBehavior,\n dryRun: !isSyncMode,\n effectivePublishMode,\n ok: true,\n publishRequested: validation.data.publish,\n summary,\n syncRunId: syncRunId === undefined ? undefined : String(syncRunId),\n warnings,\n })\n }\n\nexport const createSyncEndpoint = (options: CreateSyncEndpointOptions): Endpoint => ({\n handler: createSyncEndpointHandler(options),\n method: 'post',\n path: options.endpointPath,\n})\n"],"names":["DEFAULT_MAX_BODY_BYTES","DEFAULT_MAX_SKEW_SECONDS","DEFAULT_NONCE_TTL_SECONDS","applyDocsSync","assertApplyDeleteBehaviorSupported","createSyncRunAudit","findConfiguredPagesRouteCollisions","findDocsKeyById","findDocsSetBySlug","findDocsSyncConflicts","findDuplicateDesiredRouteCollisions","findExistingDocsRouteCollisions","findExistingPayloadDocsRecords","findTrustedGitHubSources","getRecordId","isEd25519AuthEnabled","isGitHubOidcAuthEnabled","toExistingDocsRecord","updateDocsSetAfterSync","updateSyncRunAudit","assertNonceNotReplayed","buildCanonicalSigningString","extractSyncRequestHeaders","getCanonicalPathFromRequestUrl","storeAcceptedNonce","validateTimestampSkew","verifyBodySha256","verifyEd25519Signature","verifyGitHubOidcToken","planDocsSync","validateDocsManifest","jsonResponse","body","status","Response","json","errorResponse","code","message","extras","error","ok","isRecord","value","Array","isArray","parseManifestBody","rawBody","parsed","JSON","parse","undefined","resolveSyncSource","manifest","options","payload","sourceId","source","id","response","docsSet","docsSetsEnabled","slug","collectionSlug","docsSetsCollectionSlug","docsGroupsCollectionSlug","routeBase","summarizePlan","plan","archive","length","create","delete","draft","unchanged","update","warnings","serializeChange","change","current","archived","route","sourceHash","title","desired","sha256","reason","sourcePath","serializeChanges","map","getTotalManifestBytes","files","reduce","total","file","Buffer","byteLength","content","getPlannedConflictChanges","existing","existingBySourcePath","Map","record","archivedUnchanged","filter","get","getDefaultPublishMode","defaultPublishMode","docsEnableDrafts","getLifecyclePolicyError","deleteBehavior","publishMode","publish","allowPublish","allowHardDelete","getRouteCollisionIssues","desiredRoutes","duplicateDesiredRouteCollisions","existingDocsRouteCollisions","docsEnabled","docsCollectionSlug","docsSetId","routes","pageRouteCollisions","routing","pages","enabled","allowBridgePages","bridgeField","collection","docsSetRouteBase","routeField","getRequiredHeader","headers","name","trim","getBearerToken","authorization","scheme","token","split","toLowerCase","hasEd25519AuthHeaders","assertReplayProtectionAvailable","noncesEnabled","authenticateEd25519Request","now","req","headersResult","header","docsKeysEnabled","keyConfig","docsKeysCollectionSlug","keyId","bodyHash","expectedHash","bodySha256","timestampValidation","maxSkewSeconds","timestamp","replayUnavailable","nonceAvailable","noncesCollectionSlug","nonce","canonicalPath","endpointPath","url","canonicalString","computedHash","method","path","publicKey","signature","nonceTtlSeconds","identity","expiresAt","Date","getTime","authenticateGitHubOidcRequest","docsTrustedEnabled","trustedSources","docsTrustedCollectionSlug","allowedRef","branch","startsWith","verified","config","allowedRefs","allowedWorkflowRefs","advancedSecurity","allowPullRequests","audience","enforceWorkflowRefs","fetchJson","oidcFetchJson","claims","jti","actor","ref","commit","sha","repository","authenticateSyncRequest","ed25519Enabled","auth","githubOidcEnabled","bearerToken","createSyncEndpointHandler","startedAt","getNow","toUpperCase","text","maxBodyBytes","sourceResolution","authentication","validation","allowedSourceIds","maxTotalBytes","effectiveDeleteBehavior","effectivePublishMode","data","lifecyclePolicyError","routeCollisions","isSyncMode","mode","allowWrites","requireDryRunBeforeApply","syncRunsEnabled","existingPayloadDocs","markdownFieldName","existingDocs","summary","conflicts","plannedChanges","usedAt","syncRunId","syncRun","syncRunsCollectionSlug","completedAt","errors","fileCount","publishRequested","totalBytes","applyResult","aiExport","docsCount","Error","changes","dryRun","String","createSyncEndpoint","handler"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/endpoints/sync.ts"],"sourcesContent":["import type { Endpoint, PayloadRequest } from 'payload'\n\nimport type {\n ApplyDocsSyncPayloadOperations,\n DocsKeyPayloadOperations,\n DocsSetPayloadOperations,\n DocsTrustedPayloadOperations,\n ExistingDocsPayloadOperations,\n ExistingPayloadDocsRecord,\n ResolvedDocsSet,\n RouteCollisionPayloadOperations,\n SyncRunsPayloadOperations,\n} from '../payload/index.js'\nimport type { FetchJson, NoncePayloadOperations } from '../security/index.js'\nimport type {\n DocsDeleteBehavior,\n DocsManifest,\n DocsValidationIssue,\n PlannedDocChange,\n ValidatedDocsManifest,\n} from '../sync/index.js'\nimport type { PayloadMarkdownDocsAuthConfig } from '../types.js'\n\nimport {\n DEFAULT_MAX_BODY_BYTES,\n DEFAULT_MAX_SKEW_SECONDS,\n DEFAULT_NONCE_TTL_SECONDS,\n} from '../constants.js'\nimport {\n applyDocsSync,\n assertApplyDeleteBehaviorSupported,\n createSyncRunAudit,\n findConfiguredPagesRouteCollisions,\n findDocsKeyById,\n findDocsSetBySlug,\n findDocsSyncConflicts,\n findDuplicateDesiredRouteCollisions,\n findExistingDocsRouteCollisions,\n findExistingPayloadDocsRecords,\n findTrustedGitHubSources,\n getRecordId,\n isEd25519AuthEnabled,\n isGitHubOidcAuthEnabled,\n toExistingDocsRecord,\n updateDocsSetAfterSync,\n updateSyncRunAudit,\n} from '../payload/index.js'\nimport {\n assertNonceNotReplayed,\n buildCanonicalSigningString,\n extractSyncRequestHeaders,\n getCanonicalPathFromRequestUrl,\n storeAcceptedNonce,\n validateTimestampSkew,\n verifyBodySha256,\n verifyEd25519Signature,\n verifyGitHubOidcToken,\n} from '../security/index.js'\nimport { planDocsSync, validateDocsManifest } from '../sync/index.js'\n\nexport type DocsSyncEndpointErrorCode =\n | 'audit_unavailable'\n | 'auth_disabled'\n | 'body_hash_mismatch'\n | 'delete_behavior_not_implemented'\n | 'draft_behavior_not_available'\n | 'dry_run_required_not_implemented'\n | 'hard_delete_disabled'\n | 'invalid_body'\n | 'invalid_manifest'\n | 'invalid_method'\n | 'invalid_signature'\n | 'invalid_timestamp'\n | 'manual_edit_conflict'\n | 'missing_header'\n | 'nonce_replay'\n | 'oidc_expired'\n | 'oidc_invalid_audience'\n | 'oidc_invalid_issuer'\n | 'oidc_invalid_token'\n | 'oidc_jwks_unavailable'\n | 'oidc_missing_claim'\n | 'oidc_missing_jti'\n | 'oidc_not_yet_valid'\n | 'oidc_owner_not_allowed'\n | 'oidc_pull_request_not_allowed'\n | 'oidc_ref_not_allowed'\n | 'oidc_replay'\n | 'oidc_repository_not_allowed'\n | 'oidc_workflow_not_allowed'\n | 'publish_disabled'\n | 'publish_not_available'\n | 'replay_protection_unavailable'\n | 'route_collision'\n | 'source_not_allowed'\n | 'sync_apply_failed'\n | 'sync_mode_not_implemented'\n | 'sync_writes_disabled'\n | 'unknown_key'\n\nexport type CreateSyncEndpointOptions = {\n allowHardDelete?: boolean\n allowPublish?: boolean\n allowWrites?: boolean\n auth?: PayloadMarkdownDocsAuthConfig\n deleteBehavior?: DocsDeleteBehavior\n docsCollectionSlug: string\n docsEnabled: boolean\n docsEnableDrafts: boolean\n docsGroupsCollectionSlug: string\n docsKeysCollectionSlug: string\n docsKeysEnabled: boolean\n docsSetsCollectionSlug: string\n docsSetsEnabled: boolean\n docsTrustedCollectionSlug: string\n docsTrustedEnabled: boolean\n endpointPath: string\n getNow?: () => Date\n markdownFieldName: string\n maxBodyBytes?: number\n maxSkewSeconds?: number\n noncesCollectionSlug: string\n noncesEnabled: boolean\n nonceTtlSeconds?: number\n oidcFetchJson?: FetchJson\n requireDryRunBeforeApply?: boolean\n routing?: {\n pages?: {\n allowBridgePages: boolean\n bridgeField: string\n collection: string\n enabled: boolean\n routeField: string\n }\n }\n syncRunsCollectionSlug: string\n syncRunsEnabled: boolean\n}\n\ntype SyncErrorResponse = {\n conflicts?: {\n reason: string\n route?: string\n sourcePath: string\n }[]\n error: {\n code: DocsSyncEndpointErrorCode\n message: string\n }\n ok: false\n routeCollisions?: {\n reason: string\n route: string\n }[]\n}\n\ntype SerializedChange = {\n current?: {\n archived?: boolean\n route: string\n sourceHash?: string\n title?: string\n }\n desired?: {\n route: string\n sha256: string\n title: string\n }\n reason: string\n sourcePath: string\n}\n\ntype SyncSuccessResponse = {\n changes: {\n archive: SerializedChange[]\n create: SerializedChange[]\n delete: SerializedChange[]\n draft: SerializedChange[]\n unchanged: SerializedChange[]\n update: SerializedChange[]\n }\n deleteBehavior: DocsDeleteBehavior\n dryRun: boolean\n ok: true\n publishRequested: boolean\n summary: {\n archive: number\n create: number\n delete: number\n draft: number\n unchanged: number\n update: number\n warnings: number\n }\n syncRunId?: string\n warnings: DocsValidationIssue[]\n}\n\nconst jsonResponse = (body: SyncErrorResponse | SyncSuccessResponse, status = 200): Response =>\n Response.json(body, {\n status,\n })\n\nconst errorResponse = (\n code: DocsSyncEndpointErrorCode,\n message: string,\n status = 400,\n extras: Omit<SyncErrorResponse, 'error' | 'ok'> = {},\n): Response =>\n jsonResponse(\n {\n ...extras,\n error: {\n code,\n message,\n },\n ok: false,\n },\n status,\n )\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === 'object' && value !== null && !Array.isArray(value)\n\nconst parseManifestBody = (rawBody: string): DocsManifest | undefined => {\n try {\n const parsed = JSON.parse(rawBody) as unknown\n\n return isRecord(parsed) ? (parsed as DocsManifest) : undefined\n } catch {\n return undefined\n }\n}\n\ntype ResolvedSyncSource = {\n docsSet: ResolvedDocsSet\n routeBase: string\n sourceId: string\n}\n\nconst resolveSyncSource = async ({\n manifest,\n options,\n payload,\n}: {\n manifest: DocsManifest\n options: CreateSyncEndpointOptions\n payload: DocsSetPayloadOperations\n}): Promise<\n | {\n response: Response\n source?: never\n }\n | {\n response?: never\n source: ResolvedSyncSource\n }\n> => {\n const sourceId = manifest.source?.id\n\n if (!sourceId) {\n return {\n response: errorResponse(\n 'source_not_allowed',\n 'Manifest source.id is required and must match a docs set slug.',\n 400,\n ),\n }\n }\n\n const docsSet = options.docsSetsEnabled\n ? await findDocsSetBySlug({\n slug: sourceId,\n collectionSlug: options.docsSetsCollectionSlug,\n docsGroupsCollectionSlug: options.docsGroupsCollectionSlug,\n payload,\n })\n : undefined\n\n if (docsSet) {\n return {\n source: {\n docsSet,\n routeBase: docsSet.routeBase,\n sourceId,\n },\n }\n }\n\n return {\n response: errorResponse(\n 'source_not_allowed',\n `No docs set exists for source \"${sourceId}\". Create a docs set with slug \"${sourceId}\" in Payload Admin before syncing this source.`,\n 400,\n ),\n }\n}\n\nconst summarizePlan = (plan: ReturnType<typeof planDocsSync>) => ({\n archive: plan.archive.length,\n create: plan.create.length,\n delete: plan.delete.length,\n draft: plan.draft.length,\n unchanged: plan.unchanged.length,\n update: plan.update.length,\n warnings: plan.warnings.length,\n})\n\nconst serializeChange = (change: PlannedDocChange): SerializedChange => ({\n current: change.current\n ? {\n archived: change.current.archived,\n route: change.current.route,\n sourceHash: change.current.sourceHash,\n title: change.current.title,\n }\n : undefined,\n desired: change.desired\n ? {\n route: change.desired.route,\n sha256: change.desired.sha256,\n title: change.desired.title,\n }\n : undefined,\n reason: change.reason,\n sourcePath: change.sourcePath,\n})\n\nconst serializeChanges = (plan: ReturnType<typeof planDocsSync>) => ({\n archive: plan.archive.map(serializeChange),\n create: plan.create.map(serializeChange),\n delete: plan.delete.map(serializeChange),\n draft: plan.draft.map(serializeChange),\n unchanged: plan.unchanged.map(serializeChange),\n update: plan.update.map(serializeChange),\n})\n\nconst getTotalManifestBytes = (manifest: ValidatedDocsManifest): number =>\n manifest.files.reduce((total, file) => total + Buffer.byteLength(file.content, 'utf8'), 0)\n\nconst getPlannedConflictChanges = ({\n existing,\n plan,\n}: {\n existing: ExistingPayloadDocsRecord[]\n plan: ReturnType<typeof planDocsSync>\n}): PlannedDocChange[] => {\n const existingBySourcePath = new Map(existing.map((record) => [record.sourcePath, record]))\n const archivedUnchanged = plan.unchanged.filter((change) => {\n const current = existingBySourcePath.get(change.sourcePath)\n\n return current?.archived === true\n })\n\n return [...plan.update, ...plan.archive, ...plan.draft, ...plan.delete, ...archivedUnchanged]\n}\n\nconst getLifecyclePolicyError = ({\n deleteBehavior,\n manifest,\n options,\n}: {\n deleteBehavior: DocsDeleteBehavior\n manifest: ValidatedDocsManifest\n options: CreateSyncEndpointOptions\n}): Response | undefined => {\n if (manifest.publish && options.allowPublish !== true) {\n return errorResponse('publish_disabled', 'Publishing is disabled by server configuration.', 403)\n }\n\n if (manifest.publish && !options.docsEnableDrafts) {\n return errorResponse(\n 'publish_not_available',\n 'Publishing requires a draft-enabled dedicated docs collection.',\n 400,\n )\n }\n\n if (deleteBehavior === 'draft' && !options.docsEnableDrafts) {\n return errorResponse(\n 'draft_behavior_not_available',\n 'Draft delete behavior requires a draft-enabled dedicated docs collection.',\n 400,\n )\n }\n\n if (deleteBehavior === 'delete' && options.allowHardDelete !== true) {\n return errorResponse(\n 'hard_delete_disabled',\n 'Hard delete is disabled by server configuration.',\n 403,\n )\n }\n\n return undefined\n}\n\nconst getRouteCollisionIssues = async ({\n docsSet,\n manifest,\n options,\n payload,\n routeBase,\n}: {\n docsSet?: ResolvedDocsSet\n manifest: ValidatedDocsManifest\n options: CreateSyncEndpointOptions\n payload: RouteCollisionPayloadOperations\n routeBase: string\n}) => {\n const desiredRoutes = manifest.files.map((file) => file.route)\n const duplicateDesiredRouteCollisions = findDuplicateDesiredRouteCollisions(desiredRoutes)\n const existingDocsRouteCollisions = options.docsEnabled\n ? await findExistingDocsRouteCollisions({\n collectionSlug: options.docsCollectionSlug,\n docsSetId: docsSet?.id,\n payload,\n routes: desiredRoutes,\n sourceId: manifest.source.id,\n })\n : []\n const pageRouteCollisions =\n options.routing?.pages?.enabled === true\n ? await findConfiguredPagesRouteCollisions({\n allowBridgePages: options.routing.pages.allowBridgePages,\n bridgeField: options.routing.pages.bridgeField,\n collectionSlug: options.routing.pages.collection,\n docsSetRouteBase: routeBase,\n payload,\n routeField: options.routing.pages.routeField,\n })\n : []\n\n return [\n ...duplicateDesiredRouteCollisions,\n ...existingDocsRouteCollisions,\n ...pageRouteCollisions,\n ]\n}\n\ntype AuthenticatedSyncRequest = {\n actor?: string\n bodyHash: string\n branch?: string\n commit?: string\n expiresAt: Date\n keyId: string\n nonce: string\n repository?: string\n}\n\nconst getRequiredHeader = (headers: Headers, name: string): string | undefined => {\n const value = headers.get(name)\n\n return value && value.trim() !== '' ? value.trim() : undefined\n}\n\nconst getBearerToken = (headers: Headers): string | undefined => {\n const authorization = getRequiredHeader(headers, 'authorization')\n\n if (!authorization) {\n return undefined\n }\n\n const [scheme, token] = authorization.split(/\\s+/, 2)\n\n if (scheme?.toLowerCase() !== 'bearer' || !token) {\n return ''\n }\n\n return token\n}\n\nconst hasEd25519AuthHeaders = (headers: Headers): boolean =>\n getRequiredHeader(headers, 'x-vl-md-docs-key-id') !== undefined ||\n getRequiredHeader(headers, 'x-vl-md-docs-signature') !== undefined ||\n getRequiredHeader(headers, 'x-vl-md-docs-timestamp') !== undefined ||\n getRequiredHeader(headers, 'x-vl-md-docs-nonce') !== undefined\n\nconst assertReplayProtectionAvailable = (\n options: CreateSyncEndpointOptions,\n): Response | undefined =>\n options.noncesEnabled\n ? undefined\n : errorResponse(\n 'replay_protection_unavailable',\n 'Sync endpoint requires nonce replay protection.',\n 500,\n )\n\nconst authenticateEd25519Request = async ({\n now,\n options,\n rawBody,\n req,\n}: {\n now: Date\n options: CreateSyncEndpointOptions\n rawBody: string\n req: PayloadRequest\n}): Promise<\n | {\n identity: AuthenticatedSyncRequest\n response?: never\n }\n | {\n identity?: never\n response: Response\n }\n> => {\n const headersResult = extractSyncRequestHeaders(req.headers)\n\n if (!headersResult.ok) {\n return {\n response: errorResponse(\n 'missing_header',\n `Missing required sync header: ${headersResult.header}.`,\n 401,\n ),\n }\n }\n\n if (!options.docsKeysEnabled) {\n return {\n response: errorResponse(\n 'auth_disabled',\n 'Signed sync authentication requires the docs Keys collection.',\n 401,\n ),\n }\n }\n\n const keyConfig = await findDocsKeyById({\n collectionSlug: options.docsKeysCollectionSlug,\n keyId: headersResult.headers.keyId,\n payload: req.payload as unknown as DocsKeyPayloadOperations,\n })\n\n if (!keyConfig) {\n return {\n response: errorResponse('unknown_key', 'Unknown sync request key id.', 401),\n }\n }\n\n const bodyHash = verifyBodySha256({\n body: rawBody,\n expectedHash: headersResult.headers.bodySha256,\n })\n\n if (!bodyHash.ok) {\n return {\n response: errorResponse(\n 'body_hash_mismatch',\n 'Sync request body hash does not match the signed header.',\n 401,\n ),\n }\n }\n\n const timestampValidation = validateTimestampSkew({\n maxSkewSeconds: options.maxSkewSeconds ?? DEFAULT_MAX_SKEW_SECONDS,\n now,\n timestamp: headersResult.headers.timestamp,\n })\n\n if (!timestampValidation.ok) {\n return {\n response: errorResponse('invalid_timestamp', timestampValidation.message, 401),\n }\n }\n\n const replayUnavailable = assertReplayProtectionAvailable(options)\n\n if (replayUnavailable) {\n return {\n response: replayUnavailable,\n }\n }\n\n const nonceAvailable = await assertNonceNotReplayed({\n collectionSlug: options.noncesCollectionSlug,\n keyId: headersResult.headers.keyId,\n nonce: headersResult.headers.nonce,\n now,\n payload: req.payload as unknown as NoncePayloadOperations,\n })\n\n if (!nonceAvailable) {\n return {\n response: errorResponse('nonce_replay', 'Sync request nonce has already been used.', 409),\n }\n }\n\n const canonicalPath = getCanonicalPathFromRequestUrl({\n endpointPath: options.endpointPath,\n url: req.url,\n })\n const canonicalString = buildCanonicalSigningString({\n bodySha256: bodyHash.computedHash,\n method: 'POST',\n nonce: headersResult.headers.nonce,\n path: canonicalPath,\n timestamp: headersResult.headers.timestamp,\n })\n\n if (\n !verifyEd25519Signature({\n canonicalString,\n publicKey: keyConfig.publicKey,\n signature: headersResult.headers.signature,\n })\n ) {\n return {\n response: errorResponse('invalid_signature', 'Invalid sync request signature.', 401),\n }\n }\n\n const nonceTtlSeconds = options.nonceTtlSeconds ?? DEFAULT_NONCE_TTL_SECONDS\n\n return {\n identity: {\n bodyHash: bodyHash.computedHash,\n expiresAt: new Date(now.getTime() + nonceTtlSeconds * 1000),\n keyId: headersResult.headers.keyId,\n nonce: headersResult.headers.nonce,\n },\n }\n}\n\nconst authenticateGitHubOidcRequest = async ({\n docsSet,\n now,\n options,\n rawBody,\n req,\n}: {\n docsSet: ResolvedDocsSet\n now: Date\n options: CreateSyncEndpointOptions\n rawBody: string\n req: PayloadRequest\n}): Promise<\n | {\n identity: AuthenticatedSyncRequest\n response?: never\n }\n | {\n identity?: never\n response: Response\n }\n> => {\n const token = getBearerToken(req.headers)\n\n if (token === undefined) {\n return {\n response: errorResponse(\n 'missing_header',\n 'Missing required sync header: Authorization.',\n 401,\n ),\n }\n }\n\n if (token === '') {\n return {\n response: errorResponse(\n 'oidc_invalid_token',\n 'Authorization must be a Bearer GitHub OIDC token.',\n 401,\n ),\n }\n }\n\n const expectedHash = getRequiredHeader(req.headers, 'x-vl-md-docs-body-sha256')\n\n if (!expectedHash) {\n return {\n response: errorResponse(\n 'missing_header',\n 'Missing required sync header: X-VL-MD-DOCS-Body-SHA256.',\n 401,\n ),\n }\n }\n\n const bodyHash = verifyBodySha256({\n body: rawBody,\n expectedHash,\n })\n\n if (!bodyHash.ok) {\n return {\n response: errorResponse(\n 'body_hash_mismatch',\n 'Sync request body hash does not match the OIDC header.',\n 401,\n ),\n }\n }\n\n if (!options.docsTrustedEnabled) {\n return {\n response: errorResponse(\n 'auth_disabled',\n 'GitHub OIDC sync authentication requires the docs Trusted collection.',\n 401,\n ),\n }\n }\n\n const trustedSources = await findTrustedGitHubSources({\n collectionSlug: options.docsTrustedCollectionSlug,\n payload: req.payload as unknown as DocsTrustedPayloadOperations,\n })\n const allowedRef = docsSet.branch.startsWith('refs/')\n ? docsSet.branch\n : `refs/heads/${docsSet.branch}`\n\n const verified = await verifyGitHubOidcToken({\n config: {\n allowedRefs: [allowedRef],\n allowedWorkflowRefs: docsSet.advancedSecurity?.allowedWorkflowRefs,\n allowPullRequests: docsSet.allowPullRequests,\n audience: docsSet.slug,\n enforceWorkflowRefs: docsSet.advancedSecurity?.enabled === true,\n trustedSources,\n },\n fetchJson: options.oidcFetchJson,\n now,\n token,\n })\n\n if (!verified.ok) {\n return {\n response: errorResponse(\n verified.code,\n verified.message,\n verified.code === 'oidc_jwks_unavailable' ? 503 : 401,\n ),\n }\n }\n\n const replayUnavailable = assertReplayProtectionAvailable(options)\n\n if (replayUnavailable) {\n return {\n response: replayUnavailable,\n }\n }\n\n const nonceAvailable = await assertNonceNotReplayed({\n collectionSlug: options.noncesCollectionSlug,\n keyId: verified.token.keyId,\n nonce: verified.token.claims.jti,\n now,\n payload: req.payload as unknown as NoncePayloadOperations,\n })\n\n if (!nonceAvailable) {\n return {\n response: errorResponse('oidc_replay', 'GitHub OIDC token jti has already been used.', 409),\n }\n }\n\n return {\n identity: {\n actor: verified.token.claims.actor,\n bodyHash: bodyHash.computedHash,\n branch: verified.token.claims.ref,\n commit: verified.token.claims.sha,\n expiresAt: verified.token.expiresAt,\n keyId: verified.token.keyId,\n nonce: verified.token.claims.jti,\n repository: verified.token.claims.repository,\n },\n }\n}\n\nconst authenticateSyncRequest = async ({\n docsSet,\n now,\n options,\n rawBody,\n req,\n}: {\n docsSet: ResolvedDocsSet\n now: Date\n options: CreateSyncEndpointOptions\n rawBody: string\n req: PayloadRequest\n}): Promise<\n | {\n identity: AuthenticatedSyncRequest\n response?: never\n }\n | {\n identity?: never\n response: Response\n }\n> => {\n const ed25519Enabled = isEd25519AuthEnabled(options.auth)\n const githubOidcEnabled = isGitHubOidcAuthEnabled(options.auth)\n\n if (!ed25519Enabled && !githubOidcEnabled) {\n return {\n response: errorResponse(\n 'auth_disabled',\n 'Sync authentication is not configured for this endpoint.',\n 401,\n ),\n }\n }\n\n const bearerToken = getBearerToken(req.headers)\n\n if (bearerToken !== undefined) {\n if (!githubOidcEnabled) {\n return {\n response: errorResponse(\n 'auth_disabled',\n 'GitHub OIDC sync authentication is not configured for this endpoint.',\n 401,\n ),\n }\n }\n\n return authenticateGitHubOidcRequest({\n docsSet,\n now,\n options,\n rawBody,\n req,\n })\n }\n\n if (hasEd25519AuthHeaders(req.headers) || !githubOidcEnabled) {\n if (!ed25519Enabled) {\n return {\n response: errorResponse(\n 'auth_disabled',\n 'Signed sync authentication is not configured for this endpoint.',\n 401,\n ),\n }\n }\n\n return authenticateEd25519Request({\n now,\n options,\n rawBody,\n req,\n })\n }\n\n return authenticateGitHubOidcRequest({\n docsSet,\n now,\n options,\n rawBody,\n req,\n })\n}\n\nconst createSyncEndpointHandler =\n (options: CreateSyncEndpointOptions) =>\n async (req: PayloadRequest): Promise<Response> => {\n const startedAt = options.getNow?.() ?? new Date()\n\n if (req.method && req.method.toUpperCase() !== 'POST') {\n return errorResponse('invalid_method', 'Sync endpoint only accepts POST.', 405)\n }\n\n if (typeof req.text !== 'function') {\n return errorResponse(\n 'invalid_body',\n 'Sync endpoint requires access to the request body text.',\n 400,\n )\n }\n\n const rawBody = await req.text()\n const maxBodyBytes = options.maxBodyBytes ?? DEFAULT_MAX_BODY_BYTES\n\n if (Buffer.byteLength(rawBody, 'utf8') > maxBodyBytes) {\n return errorResponse('invalid_body', 'Sync request body is too large.', 413)\n }\n\n const manifest = parseManifestBody(rawBody)\n\n if (!manifest) {\n return errorResponse('invalid_body', 'Sync request body must be a JSON manifest.', 400)\n }\n\n const sourceResolution = await resolveSyncSource({\n manifest,\n options,\n payload: req.payload as unknown as DocsSetPayloadOperations,\n })\n\n if (sourceResolution.response) {\n return sourceResolution.response\n }\n\n const authentication = await authenticateSyncRequest({\n docsSet: sourceResolution.source.docsSet,\n now: startedAt,\n options,\n rawBody,\n req,\n })\n\n if (authentication.response) {\n return authentication.response\n }\n\n const validation = validateDocsManifest(manifest, {\n allowedSourceIds: [sourceResolution.source.sourceId],\n maxTotalBytes: maxBodyBytes,\n routeBase: sourceResolution.source.routeBase,\n })\n\n if (!validation.ok) {\n return jsonResponse(\n {\n error: {\n code: 'invalid_manifest',\n message: 'Sync manifest is invalid.',\n },\n ok: false,\n },\n 400,\n )\n }\n\n const effectiveDeleteBehavior = options.deleteBehavior ?? 'archive'\n const lifecyclePolicyError = getLifecyclePolicyError({\n deleteBehavior: effectiveDeleteBehavior,\n manifest: validation.data,\n options,\n })\n\n if (lifecyclePolicyError) {\n return lifecyclePolicyError\n }\n\n const routeCollisions = await getRouteCollisionIssues({\n docsSet: sourceResolution.source.docsSet,\n manifest: validation.data,\n options,\n payload: req.payload as unknown as RouteCollisionPayloadOperations,\n routeBase: sourceResolution.source.routeBase,\n })\n\n if (routeCollisions.length > 0) {\n return errorResponse(\n 'route_collision',\n 'One or more docs routes collide with an existing route reservation.',\n 409,\n {\n routeCollisions,\n },\n )\n }\n\n const isSyncMode = validation.data.mode === 'sync'\n\n if (isSyncMode && options.allowWrites !== true) {\n return errorResponse(\n 'sync_writes_disabled',\n 'Sync writes are disabled by server configuration.',\n 403,\n )\n }\n\n if (isSyncMode && options.requireDryRunBeforeApply === true) {\n return errorResponse(\n 'dry_run_required_not_implemented',\n 'Required dry-run proof before apply is not implemented yet.',\n 400,\n )\n }\n\n if (\n isSyncMode &&\n !assertApplyDeleteBehaviorSupported(effectiveDeleteBehavior, {\n allowHardDelete: options.allowHardDelete,\n docsEnableDrafts: options.docsEnableDrafts,\n })\n ) {\n return errorResponse(\n 'delete_behavior_not_implemented',\n 'Configured delete behavior cannot be applied.',\n 400,\n )\n }\n\n if (isSyncMode && !options.syncRunsEnabled) {\n return errorResponse(\n 'audit_unavailable',\n 'Applied sync requires the sync-run audit collection.',\n 500,\n )\n }\n\n const existingPayloadDocs = options.docsEnabled\n ? await findExistingPayloadDocsRecords({\n collectionSlug: options.docsCollectionSlug,\n docsSetId: sourceResolution.source.docsSet?.id,\n markdownFieldName: options.markdownFieldName,\n payload: req.payload as unknown as ExistingDocsPayloadOperations,\n sourceId: validation.data.source.id,\n })\n : []\n const existingDocs = existingPayloadDocs.map(toExistingDocsRecord)\n const plan = planDocsSync({\n deleteBehavior: effectiveDeleteBehavior,\n desired: validation.data,\n existing: existingDocs,\n })\n const summary = summarizePlan(plan)\n const warnings = [...validation.warnings, ...plan.warnings]\n if (isSyncMode) {\n const existingBySourcePath = new Map(\n existingPayloadDocs.map((record) => [record.sourcePath, record]),\n )\n const conflicts = findDocsSyncConflicts({\n existingBySourcePath,\n plannedChanges: getPlannedConflictChanges({\n existing: existingPayloadDocs,\n plan,\n }),\n })\n\n if (conflicts.length > 0) {\n return errorResponse(\n 'manual_edit_conflict',\n 'One or more docs were modified outside the docs sync workflow.',\n 409,\n {\n conflicts,\n },\n )\n }\n }\n\n await storeAcceptedNonce({\n bodyHash: authentication.identity.bodyHash,\n collectionSlug: options.noncesCollectionSlug,\n expiresAt: authentication.identity.expiresAt,\n keyId: authentication.identity.keyId,\n nonce: authentication.identity.nonce,\n payload: req.payload as unknown as NoncePayloadOperations,\n sourceId: validation.data.source.id,\n usedAt: startedAt,\n })\n\n let syncRunId: number | string | undefined\n\n if (options.syncRunsEnabled) {\n const syncRun = await createSyncRunAudit({\n actor: authentication.identity.actor,\n bodyHash: authentication.identity.bodyHash,\n branch: authentication.identity.branch ?? validation.data.source.branch,\n collectionSlug: options.syncRunsCollectionSlug,\n commit: authentication.identity.commit ?? validation.data.source.commit,\n completedAt: isSyncMode ? startedAt : (options.getNow?.() ?? new Date()),\n deleteBehavior: effectiveDeleteBehavior,\n errors: [],\n fileCount: validation.data.files.length,\n keyId: authentication.identity.keyId,\n mode: isSyncMode ? 'sync' : 'dry-run',\n payload: req.payload as unknown as SyncRunsPayloadOperations,\n publishRequested: validation.data.publish,\n repository: authentication.identity.repository ?? validation.data.source.repository,\n sourceId: validation.data.source.id,\n startedAt,\n status: isSyncMode ? 'pending' : 'success',\n summary,\n totalBytes: getTotalManifestBytes(validation.data),\n warnings,\n })\n\n syncRunId = getRecordId(syncRun)\n }\n\n if (isSyncMode) {\n if (!syncRunId) {\n return errorResponse(\n 'audit_unavailable',\n 'Applied sync could not create a sync-run audit record.',\n 500,\n )\n }\n\n try {\n const applyResult = await applyDocsSync({\n collectionSlug: options.docsCollectionSlug,\n deleteBehavior: effectiveDeleteBehavior,\n docsEnableDrafts: options.docsEnableDrafts,\n docsSetId: sourceResolution.source.docsSet?.id,\n existing: existingPayloadDocs,\n manifest: validation.data,\n markdownFieldName: options.markdownFieldName,\n now: options.getNow?.() ?? new Date(),\n payload: req.payload as unknown as ApplyDocsSyncPayloadOperations,\n plan,\n publish: validation.data.publish,\n syncRunId,\n })\n\n if (!applyResult.ok) {\n return errorResponse(\n 'manual_edit_conflict',\n 'One or more docs were modified outside the docs sync workflow.',\n 409,\n {\n conflicts: applyResult.conflicts,\n },\n )\n }\n\n await updateSyncRunAudit({\n collectionSlug: options.syncRunsCollectionSlug,\n completedAt: options.getNow?.() ?? new Date(),\n payload: req.payload as unknown as SyncRunsPayloadOperations,\n status: 'success',\n summary,\n syncRunId,\n warnings,\n })\n\n if (sourceResolution.source.docsSet) {\n await updateDocsSetAfterSync({\n aiExport: validation.data.aiExport,\n collectionSlug: options.docsSetsCollectionSlug,\n docsCount: validation.data.files.length,\n docsSetId: sourceResolution.source.docsSet.id,\n now: options.getNow?.() ?? new Date(),\n payload: req.payload as unknown as DocsSetPayloadOperations,\n syncRunId,\n })\n }\n } catch (error) {\n await updateSyncRunAudit({\n collectionSlug: options.syncRunsCollectionSlug,\n completedAt: options.getNow?.() ?? new Date(),\n errors: [\n {\n code: 'invalid_manifest',\n message: error instanceof Error ? error.message : 'Sync apply failed.',\n },\n ],\n payload: req.payload as unknown as SyncRunsPayloadOperations,\n status: 'failed',\n summary,\n syncRunId,\n warnings,\n })\n\n return errorResponse('sync_apply_failed', 'Sync apply failed.', 500)\n }\n }\n\n return jsonResponse({\n changes: serializeChanges(plan),\n deleteBehavior: effectiveDeleteBehavior,\n dryRun: !isSyncMode,\n ok: true,\n publishRequested: validation.data.publish,\n summary,\n syncRunId: syncRunId === undefined ? undefined : String(syncRunId),\n warnings,\n })\n }\n\nexport const createSyncEndpoint = (options: CreateSyncEndpointOptions): Endpoint => ({\n handler: createSyncEndpointHandler(options),\n method: 'post',\n path: options.endpointPath,\n})\n"],"names":["DEFAULT_MAX_BODY_BYTES","DEFAULT_MAX_SKEW_SECONDS","DEFAULT_NONCE_TTL_SECONDS","applyDocsSync","assertApplyDeleteBehaviorSupported","createSyncRunAudit","findConfiguredPagesRouteCollisions","findDocsKeyById","findDocsSetBySlug","findDocsSyncConflicts","findDuplicateDesiredRouteCollisions","findExistingDocsRouteCollisions","findExistingPayloadDocsRecords","findTrustedGitHubSources","getRecordId","isEd25519AuthEnabled","isGitHubOidcAuthEnabled","toExistingDocsRecord","updateDocsSetAfterSync","updateSyncRunAudit","assertNonceNotReplayed","buildCanonicalSigningString","extractSyncRequestHeaders","getCanonicalPathFromRequestUrl","storeAcceptedNonce","validateTimestampSkew","verifyBodySha256","verifyEd25519Signature","verifyGitHubOidcToken","planDocsSync","validateDocsManifest","jsonResponse","body","status","Response","json","errorResponse","code","message","extras","error","ok","isRecord","value","Array","isArray","parseManifestBody","rawBody","parsed","JSON","parse","undefined","resolveSyncSource","manifest","options","payload","sourceId","source","id","response","docsSet","docsSetsEnabled","slug","collectionSlug","docsSetsCollectionSlug","docsGroupsCollectionSlug","routeBase","summarizePlan","plan","archive","length","create","delete","draft","unchanged","update","warnings","serializeChange","change","current","archived","route","sourceHash","title","desired","sha256","reason","sourcePath","serializeChanges","map","getTotalManifestBytes","files","reduce","total","file","Buffer","byteLength","content","getPlannedConflictChanges","existing","existingBySourcePath","Map","record","archivedUnchanged","filter","get","getLifecyclePolicyError","deleteBehavior","publish","allowPublish","docsEnableDrafts","allowHardDelete","getRouteCollisionIssues","desiredRoutes","duplicateDesiredRouteCollisions","existingDocsRouteCollisions","docsEnabled","docsCollectionSlug","docsSetId","routes","pageRouteCollisions","routing","pages","enabled","allowBridgePages","bridgeField","collection","docsSetRouteBase","routeField","getRequiredHeader","headers","name","trim","getBearerToken","authorization","scheme","token","split","toLowerCase","hasEd25519AuthHeaders","assertReplayProtectionAvailable","noncesEnabled","authenticateEd25519Request","now","req","headersResult","header","docsKeysEnabled","keyConfig","docsKeysCollectionSlug","keyId","bodyHash","expectedHash","bodySha256","timestampValidation","maxSkewSeconds","timestamp","replayUnavailable","nonceAvailable","noncesCollectionSlug","nonce","canonicalPath","endpointPath","url","canonicalString","computedHash","method","path","publicKey","signature","nonceTtlSeconds","identity","expiresAt","Date","getTime","authenticateGitHubOidcRequest","docsTrustedEnabled","trustedSources","docsTrustedCollectionSlug","allowedRef","branch","startsWith","verified","config","allowedRefs","allowedWorkflowRefs","advancedSecurity","allowPullRequests","audience","enforceWorkflowRefs","fetchJson","oidcFetchJson","claims","jti","actor","ref","commit","sha","repository","authenticateSyncRequest","ed25519Enabled","auth","githubOidcEnabled","bearerToken","createSyncEndpointHandler","startedAt","getNow","toUpperCase","text","maxBodyBytes","sourceResolution","authentication","validation","allowedSourceIds","maxTotalBytes","effectiveDeleteBehavior","lifecyclePolicyError","data","routeCollisions","isSyncMode","mode","allowWrites","requireDryRunBeforeApply","syncRunsEnabled","existingPayloadDocs","markdownFieldName","existingDocs","summary","conflicts","plannedChanges","usedAt","syncRunId","syncRun","syncRunsCollectionSlug","completedAt","errors","fileCount","publishRequested","totalBytes","applyResult","aiExport","docsCount","Error","changes","dryRun","String","createSyncEndpoint","handler"],"mappings":"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"}
@@ -3,6 +3,10 @@ export declare const isRecord: (value: unknown) => value is Record<string, unkno
3
3
  export declare const getRecordId: (doc: Record<string, unknown>) => string | undefined;
4
4
  export declare const getRelationshipId: (value: unknown) => string | undefined;
5
5
  export declare const toResolvedDocsSet: (doc: unknown) => ResolvedPayloadMarkdownDocsSet | undefined;
6
+ export declare const isVisibleDocsSet: ({ docsSet, includeDrafts, }: {
7
+ docsSet: ResolvedPayloadMarkdownDocsSet;
8
+ includeDrafts?: boolean;
9
+ }) => boolean;
6
10
  export declare const toResolvedDocsGroup: (doc: unknown) => ResolvedPayloadMarkdownDocsGroup | undefined;
7
11
  export declare const toResolvedDocsRecord: ({ doc, markdownField, }: {
8
12
  doc: unknown;
@@ -83,9 +83,16 @@ export const toResolvedDocsSet = (doc)=>{
83
83
  routeBase: normalizeRoutePath(routeBase ?? deriveDocsSetRouteBase({
84
84
  docsSetSlug: slug ?? id
85
85
  })),
86
+ status: doc._status === 'draft' || doc._status === 'published' ? doc._status : undefined,
86
87
  title
87
88
  };
88
89
  };
90
+ export const isVisibleDocsSet = ({ docsSet, includeDrafts = false })=>{
91
+ if (!includeDrafts && docsSet.status === 'draft') {
92
+ return false;
93
+ }
94
+ return true;
95
+ };
89
96
  export const toResolvedDocsGroup = (doc)=>{
90
97
  if (!isRecord(doc)) {
91
98
  return undefined;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/next/records.ts"],"sourcesContent":["import type {\n PayloadMarkdownDocsDefaults,\n PayloadMarkdownDocsHeroImage,\n PayloadMarkdownDocsOverrides,\n ResolvedPayloadMarkdownDocsGroup,\n ResolvedPayloadMarkdownDocsRecord,\n ResolvedPayloadMarkdownDocsSet,\n} from './types.js'\n\nimport { deriveDocsSetRouteBase, normalizeRoutePath } from '../routing/index.js'\nimport { isAiMarkdownExportManifestPath, validateDocsAiExportManifest } from '../sync/index.js'\n\nexport const isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === 'object' && value !== null && !Array.isArray(value)\n\nexport const 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\nexport const 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 getOptionalString = (doc: Record<string, unknown>, key: string): string | undefined =>\n typeof doc[key] === 'string' ? doc[key] : undefined\n\nconst getOptionalNumber = (doc: Record<string, unknown>, key: string): number | undefined =>\n typeof doc[key] === 'number' ? doc[key] : undefined\n\nconst getOptionalBoolean = (doc: Record<string, unknown>, key: string): boolean | undefined =>\n typeof doc[key] === 'boolean' ? doc[key] : undefined\n\nconst cleanObject = <T extends Record<string, unknown>>(input: T): Partial<T> =>\n Object.fromEntries(\n Object.entries(input).filter(([, value]) => value !== undefined && value !== null),\n ) as Partial<T>\n\nconst toDefaults = (value: unknown): PayloadMarkdownDocsDefaults | undefined => {\n if (!isRecord(value)) {\n return undefined\n }\n\n const sidebarMode: PayloadMarkdownDocsDefaults['sidebarMode'] =\n value.sidebarMode === 'auto' || value.sidebarMode === 'hidden' || value.sidebarMode === 'manual'\n ? value.sidebarMode\n : undefined\n const defaults = cleanObject({\n sidebarMode,\n } satisfies PayloadMarkdownDocsDefaults)\n\n return Object.keys(defaults).length > 0 ? (defaults as PayloadMarkdownDocsDefaults) : undefined\n}\n\nconst toOverrides = (value: unknown): PayloadMarkdownDocsOverrides | undefined => {\n if (!isRecord(value)) {\n return undefined\n }\n\n const overrides = cleanObject({\n hideFromNav: getOptionalBoolean(value, 'hideFromNav'),\n navTitle: getOptionalString(value, 'navTitle'),\n })\n\n return Object.keys(overrides).length > 0 ? overrides : undefined\n}\n\nconst toHeroImage = (value: unknown): PayloadMarkdownDocsHeroImage | undefined => {\n const media = isRecord(value) && isRecord(value.value) ? value.value : value\n\n if (!isRecord(media)) {\n return undefined\n }\n\n const url = getOptionalString(media, 'url')\n\n if (!url) {\n return undefined\n }\n\n return cleanObject({\n id: getRecordId(media),\n alt: getOptionalString(media, 'alt'),\n height: getOptionalNumber(media, 'height'),\n relationTo: isRecord(value) ? getOptionalString(value, 'relationTo') : undefined,\n url,\n width: getOptionalNumber(media, 'width'),\n }) as PayloadMarkdownDocsHeroImage\n}\n\nexport const toResolvedDocsSet = (doc: unknown): ResolvedPayloadMarkdownDocsSet | undefined => {\n if (!isRecord(doc)) {\n return undefined\n }\n\n const id = getRecordId(doc)\n const routeBase = getOptionalString(doc, 'routeBase')\n const title = getOptionalString(doc, 'title')\n const slug = getOptionalString(doc, 'slug')\n\n if (!id || !title || (!routeBase && !slug)) {\n return undefined\n }\n\n const aiExportValidation =\n doc.aiExport === undefined || doc.aiExport === null\n ? undefined\n : validateDocsAiExportManifest(doc.aiExport)\n\n return {\n ...(aiExportValidation?.ok ? { aiExport: aiExportValidation.manifest } : {}),\n id,\n slug,\n defaults: toDefaults(doc.defaults),\n description: getOptionalString(doc, 'description'),\n navTitle: getOptionalString(doc, 'navTitle'),\n order: getOptionalNumber(doc, 'order') ?? 0,\n routeBase: normalizeRoutePath(\n routeBase ??\n deriveDocsSetRouteBase({\n docsSetSlug: slug ?? id,\n }),\n ),\n title,\n }\n}\n\nexport const toResolvedDocsGroup = (doc: unknown): ResolvedPayloadMarkdownDocsGroup | undefined => {\n if (!isRecord(doc)) {\n return undefined\n }\n\n const id = getRecordId(doc)\n const routePath = getOptionalString(doc, 'routePath')\n const title = getOptionalString(doc, 'title')\n const slug = getOptionalString(doc, 'slug')\n\n if (!id || !title || (!routePath && !slug)) {\n return undefined\n }\n\n return {\n id,\n slug,\n description: getOptionalString(doc, 'description'),\n navTitle: getOptionalString(doc, 'navTitle'),\n order: getOptionalNumber(doc, 'order') ?? 0,\n routePath: normalizeRoutePath(routePath ?? `/${slug}`),\n serveIndex: getOptionalBoolean(doc, 'serveIndex') ?? false,\n title,\n }\n}\n\nexport const toResolvedDocsRecord = ({\n doc,\n markdownField,\n}: {\n doc: unknown\n markdownField: string\n}): ResolvedPayloadMarkdownDocsRecord | undefined => {\n if (!isRecord(doc)) {\n return undefined\n }\n\n const id = getRecordId(doc)\n const route = getOptionalString(doc, 'route')\n const sourcePath = getOptionalString(doc, 'sourcePath')\n const title = getOptionalString(doc, 'title')\n\n if (!id || !route || !sourcePath || !title) {\n return undefined\n }\n\n const sync = isRecord(doc.sync) ? doc.sync : undefined\n const status = doc._status === 'draft' || doc._status === 'published' ? doc._status : undefined\n\n return {\n id,\n archived: getOptionalBoolean(sync ?? {}, 'archived') ?? false,\n content: typeof doc[markdownField] === 'string' ? doc[markdownField] : undefined,\n depth: getOptionalNumber(doc, 'depth') ?? 0,\n description: getOptionalString(doc, 'description'),\n docsSetId: getRelationshipId(doc.docsSet),\n heroImage: toHeroImage(doc.heroImage),\n navTitle: getOptionalString(doc, 'navTitle'),\n order: getOptionalNumber(doc, 'order') ?? 0,\n overrides: toOverrides(doc.overrides),\n route: normalizeRoutePath(route),\n sourceHash: getOptionalString(doc, 'sourceHash'),\n sourcePath,\n status,\n title,\n }\n}\n\nexport const isVisibleDocsRecord = ({\n includeDrafts = false,\n record,\n}: {\n includeDrafts?: boolean\n record: ResolvedPayloadMarkdownDocsRecord\n}): boolean => {\n if (record.archived) {\n return false\n }\n\n if (isAiMarkdownExportManifestPath(record.sourcePath)) {\n return false\n }\n\n if (!includeDrafts && record.status === 'draft') {\n return false\n }\n\n return true\n}\n"],"names":["deriveDocsSetRouteBase","normalizeRoutePath","isAiMarkdownExportManifestPath","validateDocsAiExportManifest","isRecord","value","Array","isArray","getRecordId","doc","id","String","undefined","getRelationshipId","getOptionalString","key","getOptionalNumber","getOptionalBoolean","cleanObject","input","Object","fromEntries","entries","filter","toDefaults","sidebarMode","defaults","keys","length","toOverrides","overrides","hideFromNav","navTitle","toHeroImage","media","url","alt","height","relationTo","width","toResolvedDocsSet","routeBase","title","slug","aiExportValidation","aiExport","ok","manifest","description","order","docsSetSlug","toResolvedDocsGroup","routePath","serveIndex","toResolvedDocsRecord","markdownField","route","sourcePath","sync","status","_status","archived","content","depth","docsSetId","docsSet","heroImage","sourceHash","isVisibleDocsRecord","includeDrafts","record"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/next/records.ts"],"sourcesContent":["import type {\n PayloadMarkdownDocsDefaults,\n PayloadMarkdownDocsHeroImage,\n PayloadMarkdownDocsOverrides,\n ResolvedPayloadMarkdownDocsGroup,\n ResolvedPayloadMarkdownDocsRecord,\n ResolvedPayloadMarkdownDocsSet,\n} from './types.js'\n\nimport { deriveDocsSetRouteBase, normalizeRoutePath } from '../routing/index.js'\nimport { isAiMarkdownExportManifestPath, validateDocsAiExportManifest } from '../sync/index.js'\n\nexport const isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === 'object' && value !== null && !Array.isArray(value)\n\nexport const 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\nexport const 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 getOptionalString = (doc: Record<string, unknown>, key: string): string | undefined =>\n typeof doc[key] === 'string' ? doc[key] : undefined\n\nconst getOptionalNumber = (doc: Record<string, unknown>, key: string): number | undefined =>\n typeof doc[key] === 'number' ? doc[key] : undefined\n\nconst getOptionalBoolean = (doc: Record<string, unknown>, key: string): boolean | undefined =>\n typeof doc[key] === 'boolean' ? doc[key] : undefined\n\nconst cleanObject = <T extends Record<string, unknown>>(input: T): Partial<T> =>\n Object.fromEntries(\n Object.entries(input).filter(([, value]) => value !== undefined && value !== null),\n ) as Partial<T>\n\nconst toDefaults = (value: unknown): PayloadMarkdownDocsDefaults | undefined => {\n if (!isRecord(value)) {\n return undefined\n }\n\n const sidebarMode: PayloadMarkdownDocsDefaults['sidebarMode'] =\n value.sidebarMode === 'auto' || value.sidebarMode === 'hidden' || value.sidebarMode === 'manual'\n ? value.sidebarMode\n : undefined\n const defaults = cleanObject({\n sidebarMode,\n } satisfies PayloadMarkdownDocsDefaults)\n\n return Object.keys(defaults).length > 0 ? (defaults as PayloadMarkdownDocsDefaults) : undefined\n}\n\nconst toOverrides = (value: unknown): PayloadMarkdownDocsOverrides | undefined => {\n if (!isRecord(value)) {\n return undefined\n }\n\n const overrides = cleanObject({\n hideFromNav: getOptionalBoolean(value, 'hideFromNav'),\n navTitle: getOptionalString(value, 'navTitle'),\n })\n\n return Object.keys(overrides).length > 0 ? overrides : undefined\n}\n\nconst toHeroImage = (value: unknown): PayloadMarkdownDocsHeroImage | undefined => {\n const media = isRecord(value) && isRecord(value.value) ? value.value : value\n\n if (!isRecord(media)) {\n return undefined\n }\n\n const url = getOptionalString(media, 'url')\n\n if (!url) {\n return undefined\n }\n\n return cleanObject({\n id: getRecordId(media),\n alt: getOptionalString(media, 'alt'),\n height: getOptionalNumber(media, 'height'),\n relationTo: isRecord(value) ? getOptionalString(value, 'relationTo') : undefined,\n url,\n width: getOptionalNumber(media, 'width'),\n }) as PayloadMarkdownDocsHeroImage\n}\n\nexport const toResolvedDocsSet = (doc: unknown): ResolvedPayloadMarkdownDocsSet | undefined => {\n if (!isRecord(doc)) {\n return undefined\n }\n\n const id = getRecordId(doc)\n const routeBase = getOptionalString(doc, 'routeBase')\n const title = getOptionalString(doc, 'title')\n const slug = getOptionalString(doc, 'slug')\n\n if (!id || !title || (!routeBase && !slug)) {\n return undefined\n }\n\n const aiExportValidation =\n doc.aiExport === undefined || doc.aiExport === null\n ? undefined\n : validateDocsAiExportManifest(doc.aiExport)\n\n return {\n ...(aiExportValidation?.ok ? { aiExport: aiExportValidation.manifest } : {}),\n id,\n slug,\n defaults: toDefaults(doc.defaults),\n description: getOptionalString(doc, 'description'),\n navTitle: getOptionalString(doc, 'navTitle'),\n order: getOptionalNumber(doc, 'order') ?? 0,\n routeBase: normalizeRoutePath(\n routeBase ??\n deriveDocsSetRouteBase({\n docsSetSlug: slug ?? id,\n }),\n ),\n status: doc._status === 'draft' || doc._status === 'published' ? doc._status : undefined,\n title,\n }\n}\n\nexport const isVisibleDocsSet = ({\n docsSet,\n includeDrafts = false,\n}: {\n docsSet: ResolvedPayloadMarkdownDocsSet\n includeDrafts?: boolean\n}): boolean => {\n if (!includeDrafts && docsSet.status === 'draft') {\n return false\n }\n\n return true\n}\n\nexport const toResolvedDocsGroup = (doc: unknown): ResolvedPayloadMarkdownDocsGroup | undefined => {\n if (!isRecord(doc)) {\n return undefined\n }\n\n const id = getRecordId(doc)\n const routePath = getOptionalString(doc, 'routePath')\n const title = getOptionalString(doc, 'title')\n const slug = getOptionalString(doc, 'slug')\n\n if (!id || !title || (!routePath && !slug)) {\n return undefined\n }\n\n return {\n id,\n slug,\n description: getOptionalString(doc, 'description'),\n navTitle: getOptionalString(doc, 'navTitle'),\n order: getOptionalNumber(doc, 'order') ?? 0,\n routePath: normalizeRoutePath(routePath ?? `/${slug}`),\n serveIndex: getOptionalBoolean(doc, 'serveIndex') ?? false,\n title,\n }\n}\n\nexport const toResolvedDocsRecord = ({\n doc,\n markdownField,\n}: {\n doc: unknown\n markdownField: string\n}): ResolvedPayloadMarkdownDocsRecord | undefined => {\n if (!isRecord(doc)) {\n return undefined\n }\n\n const id = getRecordId(doc)\n const route = getOptionalString(doc, 'route')\n const sourcePath = getOptionalString(doc, 'sourcePath')\n const title = getOptionalString(doc, 'title')\n\n if (!id || !route || !sourcePath || !title) {\n return undefined\n }\n\n const sync = isRecord(doc.sync) ? doc.sync : undefined\n const status = doc._status === 'draft' || doc._status === 'published' ? doc._status : undefined\n\n return {\n id,\n archived: getOptionalBoolean(sync ?? {}, 'archived') ?? false,\n content: typeof doc[markdownField] === 'string' ? doc[markdownField] : undefined,\n depth: getOptionalNumber(doc, 'depth') ?? 0,\n description: getOptionalString(doc, 'description'),\n docsSetId: getRelationshipId(doc.docsSet),\n heroImage: toHeroImage(doc.heroImage),\n navTitle: getOptionalString(doc, 'navTitle'),\n order: getOptionalNumber(doc, 'order') ?? 0,\n overrides: toOverrides(doc.overrides),\n route: normalizeRoutePath(route),\n sourceHash: getOptionalString(doc, 'sourceHash'),\n sourcePath,\n status,\n title,\n }\n}\n\nexport const isVisibleDocsRecord = ({\n includeDrafts = false,\n record,\n}: {\n includeDrafts?: boolean\n record: ResolvedPayloadMarkdownDocsRecord\n}): boolean => {\n if (record.archived) {\n return false\n }\n\n if (isAiMarkdownExportManifestPath(record.sourcePath)) {\n return false\n }\n\n if (!includeDrafts && record.status === 'draft') {\n return false\n }\n\n return true\n}\n"],"names":["deriveDocsSetRouteBase","normalizeRoutePath","isAiMarkdownExportManifestPath","validateDocsAiExportManifest","isRecord","value","Array","isArray","getRecordId","doc","id","String","undefined","getRelationshipId","getOptionalString","key","getOptionalNumber","getOptionalBoolean","cleanObject","input","Object","fromEntries","entries","filter","toDefaults","sidebarMode","defaults","keys","length","toOverrides","overrides","hideFromNav","navTitle","toHeroImage","media","url","alt","height","relationTo","width","toResolvedDocsSet","routeBase","title","slug","aiExportValidation","aiExport","ok","manifest","description","order","docsSetSlug","status","_status","isVisibleDocsSet","docsSet","includeDrafts","toResolvedDocsGroup","routePath","serveIndex","toResolvedDocsRecord","markdownField","route","sourcePath","sync","archived","content","depth","docsSetId","heroImage","sourceHash","isVisibleDocsRecord","record"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import { DEFAULT_DOCS_COLLECTION_SLUG, DEFAULT_DOCS_GROUPS_COLLECTION_SLUG, DEFAULT_DOCS_SETS_COLLECTION_SLUG, DEFAULT_MARKDOWN_FIELD_NAME } from '../constants.js';
2
2
  import { deriveDocsSetRouteBase, isRouteDescendant, joinRouteSegments, normalizeRoutePath } from '../routing/index.js';
3
- import { getRelationshipId, isRecord, isVisibleDocsRecord, toResolvedDocsGroup, toResolvedDocsRecord, toResolvedDocsSet } from './records.js';
3
+ import { getRelationshipId, isRecord, isVisibleDocsRecord, isVisibleDocsSet, toResolvedDocsGroup, toResolvedDocsRecord, toResolvedDocsSet } from './records.js';
4
4
  import { getPayloadMarkdownDocsSidebar } from './sidebar.js';
5
5
  const resolveCollectionSlugs = (collections)=>({
6
6
  docs: collections?.docs ?? DEFAULT_DOCS_COLLECTION_SLUG,
@@ -78,7 +78,7 @@ const withComputedDocsSetRoute = ({ doc, docsSet, groupsById })=>{
78
78
  })
79
79
  };
80
80
  };
81
- const findDocsSetById = async ({ id, collections, overrideAccess, payload })=>{
81
+ const findDocsSetById = async ({ id, collections, includeDrafts, overrideAccess, payload })=>{
82
82
  const [result, groupsById] = await Promise.all([
83
83
  payload.find({
84
84
  collection: collections.docsSets,
@@ -97,13 +97,17 @@ const findDocsSetById = async ({ id, collections, overrideAccess, payload })=>{
97
97
  payload
98
98
  })
99
99
  ]);
100
- return withComputedDocsSetRoute({
100
+ const docsSet = withComputedDocsSetRoute({
101
101
  doc: result.docs[0],
102
102
  docsSet: toResolvedDocsSet(result.docs[0]),
103
103
  groupsById
104
104
  });
105
+ return docsSet && isVisibleDocsSet({
106
+ docsSet,
107
+ includeDrafts
108
+ }) ? docsSet : undefined;
105
109
  };
106
- const findDocsSetByRouteBase = async ({ collections, overrideAccess, payload, route })=>{
110
+ const findDocsSetByRouteBase = async ({ collections, includeDrafts, overrideAccess, payload, route })=>{
107
111
  const [result, groupsById] = await Promise.all([
108
112
  payload.find({
109
113
  collection: collections.docsSets,
@@ -121,9 +125,12 @@ const findDocsSetByRouteBase = async ({ collections, overrideAccess, payload, ro
121
125
  doc,
122
126
  docsSet: toResolvedDocsSet(doc),
123
127
  groupsById
128
+ })).filter((docsSet)=>docsSet !== undefined && isVisibleDocsSet({
129
+ docsSet,
130
+ includeDrafts
124
131
  })).find((docsSet)=>docsSet?.routeBase === route);
125
132
  };
126
- const findDocsSetByRoutePrefix = async ({ collections, overrideAccess, payload, route })=>{
133
+ const findDocsSetByRoutePrefix = async ({ collections, includeDrafts, overrideAccess, payload, route })=>{
127
134
  const [result, groupsById] = await Promise.all([
128
135
  payload.find({
129
136
  collection: collections.docsSets,
@@ -145,6 +152,12 @@ const findDocsSetByRoutePrefix = async ({ collections, overrideAccess, payload,
145
152
  if (!docsSet) {
146
153
  return false;
147
154
  }
155
+ if (!isVisibleDocsSet({
156
+ docsSet,
157
+ includeDrafts
158
+ })) {
159
+ return false;
160
+ }
148
161
  return docsSet.routeBase === route || isRouteDescendant(docsSet.routeBase, route);
149
162
  }).sort((first, second)=>second.routeBase.length - first.routeBase.length)[0];
150
163
  };
@@ -154,24 +167,26 @@ const getRelatedDocsSet = (doc)=>{
154
167
  }
155
168
  return toResolvedDocsSet(doc.docsSet);
156
169
  };
157
- const findDocsSetForRecord = async ({ collections, doc, overrideAccess, payload, record })=>{
170
+ const findDocsSetForRecord = async ({ collections, doc, includeDrafts, overrideAccess, payload, record })=>{
158
171
  if (record.docsSetId) {
159
- const docsSetById = await findDocsSetById({
172
+ return findDocsSetById({
160
173
  id: record.docsSetId,
161
174
  collections,
175
+ includeDrafts,
162
176
  overrideAccess,
163
177
  payload
164
178
  });
165
- if (docsSetById) {
166
- return docsSetById;
167
- }
168
179
  }
169
180
  const relatedDocsSet = getRelatedDocsSet(doc);
170
- if (relatedDocsSet) {
181
+ if (relatedDocsSet && isVisibleDocsSet({
182
+ docsSet: relatedDocsSet,
183
+ includeDrafts
184
+ })) {
171
185
  return relatedDocsSet;
172
186
  }
173
187
  return findDocsSetByRoutePrefix({
174
188
  collections,
189
+ includeDrafts,
175
190
  overrideAccess,
176
191
  payload,
177
192
  route: record.route
@@ -229,7 +244,7 @@ const findDocsSetIndexRecord = async ({ collections, docsSet, includeDrafts, mar
229
244
  }
230
245
  return result.record;
231
246
  };
232
- const findGroupIndexRoute = async ({ collections, overrideAccess, payload, route })=>{
247
+ const findGroupIndexRoute = async ({ collections, includeDrafts, overrideAccess, payload, route })=>{
233
248
  const groupsById = await getGroupsById({
234
249
  collections,
235
250
  overrideAccess,
@@ -261,7 +276,10 @@ const findGroupIndexRoute = async ({ collections, overrideAccess, payload, route
261
276
  doc,
262
277
  docsSet: toResolvedDocsSet(doc),
263
278
  groupsById
264
- })).filter((docsSet)=>docsSet !== undefined).sort((first, second)=>{
279
+ })).filter((docsSet)=>docsSet !== undefined).filter((docsSet)=>isVisibleDocsSet({
280
+ docsSet,
281
+ includeDrafts
282
+ })).sort((first, second)=>{
265
283
  if (first.order !== second.order) {
266
284
  return first.order - second.order;
267
285
  }
@@ -284,6 +302,7 @@ overrideAccess = true, path, payload })=>{
284
302
  const collections = resolveCollectionSlugs(collectionOptions);
285
303
  const docsSet = await findDocsSetByRouteBase({
286
304
  collections,
305
+ includeDrafts,
287
306
  overrideAccess,
288
307
  payload,
289
308
  route
@@ -329,6 +348,7 @@ overrideAccess = true, path, payload })=>{
329
348
  const resolvedDocsSet = await findDocsSetForRecord({
330
349
  collections,
331
350
  doc: docResult.doc,
351
+ includeDrafts,
332
352
  overrideAccess,
333
353
  payload,
334
354
  record: docResult.record
@@ -353,6 +373,7 @@ overrideAccess = true, path, payload })=>{
353
373
  }
354
374
  const groupRoute = await findGroupIndexRoute({
355
375
  collections,
376
+ includeDrafts,
356
377
  overrideAccess,
357
378
  payload,
358
379
  route