@valkyrianlabs/payload-markdown-docs 0.5.0 → 0.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) 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 +13 -0
  8. package/dist/collections/docs.js.map +1 -1
  9. package/dist/collections/docsSets.d.ts +1 -4
  10. package/dist/collections/docsSets.js +17 -11
  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 +8 -15
  19. package/dist/endpoints/sync.js.map +1 -1
  20. package/dist/next/links.js +5 -2
  21. package/dist/next/links.js.map +1 -1
  22. package/dist/next/markdown.js +18 -6
  23. package/dist/next/markdown.js.map +1 -1
  24. package/dist/next/records.d.ts +4 -0
  25. package/dist/next/records.js +7 -0
  26. package/dist/next/records.js.map +1 -1
  27. package/dist/next/route.js +39 -13
  28. package/dist/next/route.js.map +1 -1
  29. package/dist/next/sidebar.js +1 -0
  30. package/dist/next/sidebar.js.map +1 -1
  31. package/dist/next/types.d.ts +2 -0
  32. package/dist/next/types.js.map +1 -1
  33. package/dist/payload/applyDocsSync.d.ts +4 -3
  34. package/dist/payload/applyDocsSync.js +18 -6
  35. package/dist/payload/applyDocsSync.js.map +1 -1
  36. package/dist/payload/docsData.d.ts +2 -5
  37. package/dist/payload/docsData.js +4 -8
  38. package/dist/payload/docsData.js.map +1 -1
  39. package/dist/payload/docsSets.d.ts +6 -2
  40. package/dist/payload/docsSets.js +5 -2
  41. package/dist/payload/docsSets.js.map +1 -1
  42. package/dist/payload/existingDocs.d.ts +5 -2
  43. package/dist/payload/existingDocs.js +5 -2
  44. package/dist/payload/existingDocs.js.map +1 -1
  45. package/dist/payload/index.d.ts +11 -11
  46. package/dist/payload/index.js.map +1 -1
  47. package/dist/payload/populatePublishedAt.d.ts +2 -0
  48. package/dist/payload/populatePublishedAt.js +14 -0
  49. package/dist/payload/populatePublishedAt.js.map +1 -0
  50. package/dist/payload/routeCollisions.d.ts +3 -1
  51. package/dist/payload/routeCollisions.js +2 -1
  52. package/dist/payload/routeCollisions.js.map +1 -1
  53. package/dist/payload/syncRuns.d.ts +1 -2
  54. package/dist/payload/syncRuns.js +1 -2
  55. package/dist/payload/syncRuns.js.map +1 -1
  56. package/dist/plugin.js +0 -4
  57. package/dist/plugin.js.map +1 -1
  58. package/dist/skills/codex/reference/admin.md +0 -1
  59. package/dist/sync/plan.d.ts +1 -0
  60. package/dist/sync/plan.js +4 -2
  61. package/dist/sync/plan.js.map +1 -1
  62. package/dist/types.d.ts +0 -1
  63. package/dist/types.js.map +1 -1
  64. package/package.json +1 -1
  65. package/dist/endpoints/publishGeneratedDocs.d.ts +0 -7
  66. package/dist/endpoints/publishGeneratedDocs.js +0 -77
  67. package/dist/endpoints/publishGeneratedDocs.js.map +0 -1
  68. package/dist/payload/publishGeneratedDocs.d.ts +0 -30
  69. package/dist/payload/publishGeneratedDocs.js +0 -92
  70. package/dist/payload/publishGeneratedDocs.js.map +0 -1
@@ -33,6 +33,7 @@ const resolveSyncSource = async ({ manifest, options, payload })=>{
33
33
  slug: sourceId,
34
34
  collectionSlug: options.docsSetsCollectionSlug,
35
35
  docsGroupsCollectionSlug: options.docsGroupsCollectionSlug,
36
+ includeDrafts: true,
36
37
  payload
37
38
  }) : undefined;
38
39
  if (docsSet) {
@@ -98,20 +99,13 @@ const getPlannedConflictChanges = ({ existing, plan })=>{
98
99
  ...archivedUnchanged
99
100
  ];
100
101
  };
101
- const getDefaultPublishMode = (options)=>options.defaultPublishMode ?? (options.docsEnableDrafts ? 'draft' : 'preserve');
102
- const getLifecyclePolicyError = ({ deleteBehavior, manifest, options, publishMode })=>{
102
+ const getLifecyclePolicyError = ({ deleteBehavior, manifest, options })=>{
103
103
  if (manifest.publish && options.allowPublish !== true) {
104
104
  return errorResponse('publish_disabled', 'Publishing is disabled by server configuration.', 403);
105
105
  }
106
- if ((manifest.publish || publishMode === 'published') && !options.docsEnableDrafts) {
106
+ if (manifest.publish && !options.docsEnableDrafts) {
107
107
  return errorResponse('publish_not_available', 'Publishing requires a draft-enabled dedicated docs collection.', 400);
108
108
  }
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
109
  if (deleteBehavior === 'draft' && !options.docsEnableDrafts) {
116
110
  return errorResponse('draft_behavior_not_available', 'Draft delete behavior requires a draft-enabled dedicated docs collection.', 400);
117
111
  }
@@ -126,6 +120,7 @@ const getRouteCollisionIssues = async ({ docsSet, manifest, options, payload, ro
126
120
  const existingDocsRouteCollisions = options.docsEnabled ? await findExistingDocsRouteCollisions({
127
121
  collectionSlug: options.docsCollectionSlug,
128
122
  docsSetId: docsSet?.id,
123
+ includeDrafts: options.docsEnableDrafts,
129
124
  payload,
130
125
  routes: desiredRoutes,
131
126
  sourceId: manifest.source.id
@@ -434,12 +429,10 @@ const createSyncEndpointHandler = (options)=>async (req)=>{
434
429
  }, 400);
435
430
  }
436
431
  const effectiveDeleteBehavior = options.deleteBehavior ?? 'archive';
437
- const effectivePublishMode = validation.data.publish ? 'published' : getDefaultPublishMode(options);
438
432
  const lifecyclePolicyError = getLifecyclePolicyError({
439
433
  deleteBehavior: effectiveDeleteBehavior,
440
434
  manifest: validation.data,
441
- options,
442
- publishMode: effectivePublishMode
435
+ options
443
436
  });
444
437
  if (lifecyclePolicyError) {
445
438
  return lifecyclePolicyError;
@@ -475,6 +468,7 @@ const createSyncEndpointHandler = (options)=>async (req)=>{
475
468
  const existingPayloadDocs = options.docsEnabled ? await findExistingPayloadDocsRecords({
476
469
  collectionSlug: options.docsCollectionSlug,
477
470
  docsSetId: sourceResolution.source.docsSet?.id,
471
+ draft: options.docsEnableDrafts,
478
472
  markdownFieldName: options.markdownFieldName,
479
473
  payload: req.payload,
480
474
  sourceId: validation.data.source.id
@@ -528,7 +522,6 @@ const createSyncEndpointHandler = (options)=>async (req)=>{
528
522
  commit: authentication.identity.commit ?? validation.data.source.commit,
529
523
  completedAt: isSyncMode ? startedAt : options.getNow?.() ?? new Date(),
530
524
  deleteBehavior: effectiveDeleteBehavior,
531
- effectivePublishMode,
532
525
  errors: [],
533
526
  fileCount: validation.data.files.length,
534
527
  keyId: authentication.identity.keyId,
@@ -561,7 +554,7 @@ const createSyncEndpointHandler = (options)=>async (req)=>{
561
554
  now: options.getNow?.() ?? new Date(),
562
555
  payload: req.payload,
563
556
  plan,
564
- publishMode: effectivePublishMode,
557
+ publish: validation.data.publish,
565
558
  syncRunId
566
559
  });
567
560
  if (!applyResult.ok) {
@@ -586,6 +579,7 @@ const createSyncEndpointHandler = (options)=>async (req)=>{
586
579
  docsSetId: sourceResolution.source.docsSet.id,
587
580
  now: options.getNow?.() ?? new Date(),
588
581
  payload: req.payload,
582
+ publish: validation.data.publish,
589
583
  syncRunId
590
584
  });
591
585
  }
@@ -612,7 +606,6 @@ const createSyncEndpointHandler = (options)=>async (req)=>{
612
606
  changes: serializeChanges(plan),
613
607
  deleteBehavior: effectiveDeleteBehavior,
614
608
  dryRun: !isSyncMode,
615
- effectivePublishMode,
616
609
  ok: true,
617
610
  publishRequested: validation.data.publish,
618
611
  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":"AA2BA,SACEA,sBAAsB,EACtBC,wBAAwB,EACxBC,yBAAyB,QACpB,kBAAiB;AACxB,SACEC,aAAa,EACbC,kCAAkC,EAClCC,kBAAkB,EAClBC,kCAAkC,EAClCC,eAAe,EACfC,iBAAiB,EACjBC,qBAAqB,EACrBC,mCAAmC,EACnCC,+BAA+B,EAC/BC,8BAA8B,EAC9BC,wBAAwB,EACxBC,WAAW,EACXC,oBAAoB,EACpBC,uBAAuB,EACvBC,oBAAoB,EACpBC,sBAAsB,EACtBC,kBAAkB,QACb,sBAAqB;AAC5B,SACEC,sBAAsB,EACtBC,2BAA2B,EAC3BC,yBAAyB,EACzBC,8BAA8B,EAC9BC,kBAAkB,EAClBC,qBAAqB,EACrBC,gBAAgB,EAChBC,sBAAsB,EACtBC,qBAAqB,QAChB,uBAAsB;AAC7B,SACEC,YAAY,EACZC,oBAAoB,QACf,mBAAkB;AA8IzB,MAAMC,eAAe,CACnBC,MACAC,SAAS,GAAG,GAEZC,SAASC,IAAI,CAACH,MAAM;QAClBC;IACF;AAEF,MAAMG,gBAAgB,CACpBC,MACAC,SACAL,SAAS,GAAG,EACZM,SAAkD,CAAC,CAAC,GAEpDR,aACE;QACE,GAAGQ,MAAM;QACTC,OAAO;YACLH;YACAC;QACF;QACAG,IAAI;IACN,GACAR;AAGJ,MAAMS,WAAW,CAACC,QAChB,OAAOA,UAAU,YAAYA,UAAU,QAAQ,CAACC,MAAMC,OAAO,CAACF;AAEhE,MAAMG,oBAAoB,CAACC;IACzB,IAAI;QACF,MAAMC,SAASC,KAAKC,KAAK,CAACH;QAE1B,OAAOL,SAASM,UAAWA,SAA0BG;IACvD,EAAE,OAAM;QACN,OAAOA;IACT;AACF;AAQA,MAAMC,oBAAoB,OAAO,EAC/BC,QAAQ,EACRC,OAAO,EACPC,OAAO,EAKR;IAUC,MAAMC,WAAWH,SAASI,MAAM,EAAEC;IAElC,IAAI,CAACF,UAAU;QACb,OAAO;YACLG,UAAUvB,cACR,sBACA,kEACA;QAEJ;IACF;IAEA,MAAMwB,UACJN,QAAQO,eAAe,GACnB,MAAMrD,kBAAkB;QACtBsD,MAAMN;QACNO,gBAAgBT,QAAQU,sBAAsB;QAC9CC,0BAA0BX,QAAQW,wBAAwB;QAC1DV;IACF,KACAJ;IAEN,IAAIS,SAAS;QACX,OAAO;YACLH,QAAQ;gBACNG;gBACAM,WAAWN,QAAQM,SAAS;gBAC5BV;YACF;QACF;IACF;IAEA,OAAO;QACLG,UAAUvB,cACR,sBACA,CAAC,+BAA+B,EAAEoB,SAAS,gCAAgC,EAAEA,SAAS,8CAA8C,CAAC,EACrI;IAEJ;AACF;AAEA,MAAMW,gBAAgB,CAACC,OAA2C,CAAA;QAChEC,SAASD,KAAKC,OAAO,CAACC,MAAM;QAC5BC,QAAQH,KAAKG,MAAM,CAACD,MAAM;QAC1BE,QAAQJ,KAAKI,MAAM,CAACF,MAAM;QAC1BG,OAAOL,KAAKK,KAAK,CAACH,MAAM;QACxBI,WAAWN,KAAKM,SAAS,CAACJ,MAAM;QAChCK,QAAQP,KAAKO,MAAM,CAACL,MAAM;QAC1BM,UAAUR,KAAKQ,QAAQ,CAACN,MAAM;IAChC,CAAA;AAEA,MAAMO,kBAAkB,CAACC,SAAgD,CAAA;QACvEC,SAASD,OAAOC,OAAO,GACnB;YACEC,UAAUF,OAAOC,OAAO,CAACC,QAAQ;YACjCC,OAAOH,OAAOC,OAAO,CAACE,KAAK;YAC3BC,YAAYJ,OAAOC,OAAO,CAACG,UAAU;YACrCC,OAAOL,OAAOC,OAAO,CAACI,KAAK;QAC7B,IACAhC;QACJiC,SAASN,OAAOM,OAAO,GACnB;YACEH,OAAOH,OAAOM,OAAO,CAACH,KAAK;YAC3BI,QAAQP,OAAOM,OAAO,CAACC,MAAM;YAC7BF,OAAOL,OAAOM,OAAO,CAACD,KAAK;QAC7B,IACAhC;QACJmC,QAAQR,OAAOQ,MAAM;QACrBC,YAAYT,OAAOS,UAAU;IAC/B,CAAA;AAEA,MAAMC,mBAAmB,CAACpB,OAA2C,CAAA;QACnEC,SAASD,KAAKC,OAAO,CAACoB,GAAG,CAACZ;QAC1BN,QAAQH,KAAKG,MAAM,CAACkB,GAAG,CAACZ;QACxBL,QAAQJ,KAAKI,MAAM,CAACiB,GAAG,CAACZ;QACxBJ,OAAOL,KAAKK,KAAK,CAACgB,GAAG,CAACZ;QACtBH,WAAWN,KAAKM,SAAS,CAACe,GAAG,CAACZ;QAC9BF,QAAQP,KAAKO,MAAM,CAACc,GAAG,CAACZ;IAC1B,CAAA;AAEA,MAAMa,wBAAwB,CAACrC,WAC7BA,SAASsC,KAAK,CAACC,MAAM,CACnB,CAACC,OAAOC,OAASD,QAAQE,OAAOC,UAAU,CAACF,KAAKG,OAAO,EAAE,SACzD;AAGJ,MAAMC,4BAA4B,CAAC,EACjCC,QAAQ,EACR/B,IAAI,EAIL;IACC,MAAMgC,uBAAuB,IAAIC,IAC/BF,SAASV,GAAG,CAAC,CAACa,SAAW;YAACA,OAAOf,UAAU;YAAEe;SAAO;IAEtD,MAAMC,oBAAoBnC,KAAKM,SAAS,CAAC8B,MAAM,CAAC,CAAC1B;QAC/C,MAAMC,UAAUqB,qBAAqBK,GAAG,CAAC3B,OAAOS,UAAU;QAE1D,OAAOR,SAASC,aAAa;IAC/B;IAEA,OAAO;WACFZ,KAAKO,MAAM;WACXP,KAAKC,OAAO;WACZD,KAAKK,KAAK;WACVL,KAAKI,MAAM;WACX+B;KACJ;AACH;AAEA,MAAMG,wBAAwB,CAC5BpD,UAEAA,QAAQqD,kBAAkB,IAAKrD,CAAAA,QAAQsD,gBAAgB,GAAG,UAAU,UAAS;AAE/E,MAAMC,0BAA0B,CAAC,EAC/BC,cAAc,EACdzD,QAAQ,EACRC,OAAO,EACPyD,WAAW,EAMZ;IACC,IAAI1D,SAAS2D,OAAO,IAAI1D,QAAQ2D,YAAY,KAAK,MAAM;QACrD,OAAO7E,cACL,oBACA,mDACA;IAEJ;IAEA,IACE,AAACiB,CAAAA,SAAS2D,OAAO,IAAID,gBAAgB,WAAU,KAC/C,CAACzD,QAAQsD,gBAAgB,EACzB;QACA,OAAOxE,cACL,yBACA,kEACA;IAEJ;IAEA,IAAI2E,gBAAgB,eAAezD,QAAQ2D,YAAY,KAAK,MAAM;QAChE,OAAO7E,cACL,oBACA,mDACA;IAEJ;IAEA,IAAI2E,gBAAgB,WAAW,CAACzD,QAAQsD,gBAAgB,EAAE;QACxD,OAAOxE,cACL,gCACA,kEACA;IAEJ;IAEA,IAAI0E,mBAAmB,WAAW,CAACxD,QAAQsD,gBAAgB,EAAE;QAC3D,OAAOxE,cACL,gCACA,6EACA;IAEJ;IAEA,IAAI0E,mBAAmB,YAAYxD,QAAQ4D,eAAe,KAAK,MAAM;QACnE,OAAO9E,cACL,wBACA,oDACA;IAEJ;IAEA,OAAOe;AACT;AAEA,MAAMgE,0BAA0B,OAAO,EACrCvD,OAAO,EACPP,QAAQ,EACRC,OAAO,EACPC,OAAO,EACPW,SAAS,EAOV;IACC,MAAMkD,gBAAgB/D,SAASsC,KAAK,CAACF,GAAG,CAAC,CAACK,OAASA,KAAKb,KAAK;IAC7D,MAAMoC,kCACJ3G,oCAAoC0G;IACtC,MAAME,8BAA8BhE,QAAQiE,WAAW,GACnD,MAAM5G,gCAAgC;QACpCoD,gBAAgBT,QAAQkE,kBAAkB;QAC1CC,WAAW7D,SAASF;QACpBH;QACAmE,QAAQN;QACR5D,UAAUH,SAASI,MAAM,CAACC,EAAE;IAC9B,KACA,EAAE;IACN,MAAMiE,sBACJrE,QAAQsE,OAAO,EAAEC,OAAOC,YAAY,OAChC,MAAMxH,mCAAmC;QACvCyH,kBAAkBzE,QAAQsE,OAAO,CAACC,KAAK,CAACE,gBAAgB;QACxDC,aAAa1E,QAAQsE,OAAO,CAACC,KAAK,CAACG,WAAW;QAC9CjE,gBAAgBT,QAAQsE,OAAO,CAACC,KAAK,CAACI,UAAU;QAChDC,kBAAkBhE;QAClBX;QACA4E,YAAY7E,QAAQsE,OAAO,CAACC,KAAK,CAACM,UAAU;IAC9C,KACA,EAAE;IAER,OAAO;WACFd;WACAC;WACAK;KACJ;AACH;AAaA,MAAMS,oBAAoB,CACxBC,SACAC;IAEA,MAAM3F,QAAQ0F,QAAQ5B,GAAG,CAAC6B;IAE1B,OAAO3F,SAASA,MAAM4F,IAAI,OAAO,KAAK5F,MAAM4F,IAAI,KAAKpF;AACvD;AAEA,MAAMqF,iBAAiB,CAACH;IACtB,MAAMI,gBAAgBL,kBAAkBC,SAAS;IAEjD,IAAI,CAACI,eAAe;QAClB,OAAOtF;IACT;IAEA,MAAM,CAACuF,QAAQC,MAAM,GAAGF,cAAcG,KAAK,CAAC,OAAO;IAEnD,IAAIF,QAAQG,kBAAkB,YAAY,CAACF,OAAO;QAChD,OAAO;IACT;IAEA,OAAOA;AACT;AAEA,MAAMG,wBAAwB,CAACT,UAC7BD,kBAAkBC,SAAS,2BAA2BlF,aACtDiF,kBAAkBC,SAAS,8BAA8BlF,aACzDiF,kBAAkBC,SAAS,8BAA8BlF,aACzDiF,kBAAkBC,SAAS,0BAA0BlF;AAEvD,MAAM4F,kCAAkC,CACtCzF,UAEAA,QAAQ0F,aAAa,GACjB7F,YACAf,cACE,iCACA,mDACA;AAGR,MAAM6G,6BAA6B,OAAO,EACxCC,GAAG,EACH5F,OAAO,EACPP,OAAO,EACPoG,GAAG,EAMJ;IAUC,MAAMC,gBAAgB9H,0BAA0B6H,IAAId,OAAO;IAE3D,IAAI,CAACe,cAAc3G,EAAE,EAAE;QACrB,OAAO;YACLkB,UAAUvB,cACR,kBACA,CAAC,8BAA8B,EAAEgH,cAAcC,MAAM,CAAC,CAAC,CAAC,EACxD;QAEJ;IACF;IAEA,IAAI,CAAC/F,QAAQgG,eAAe,EAAE;QAC5B,OAAO;YACL3F,UAAUvB,cACR,iBACA,iEACA;QAEJ;IACF;IAEA,MAAMmH,YAAY,MAAMhJ,gBAAgB;QACtCwD,gBAAgBT,QAAQkG,sBAAsB;QAC9CC,OAAOL,cAAcf,OAAO,CAACoB,KAAK;QAClClG,SAAS4F,IAAI5F,OAAO;IACtB;IAEA,IAAI,CAACgG,WAAW;QACd,OAAO;YACL5F,UAAUvB,cAAc,eAAe,gCAAgC;QACzE;IACF;IAEA,MAAMsH,WAAWhI,iBAAiB;QAChCM,MAAMe;QACN4G,cAAcP,cAAcf,OAAO,CAACuB,UAAU;IAChD;IAEA,IAAI,CAACF,SAASjH,EAAE,EAAE;QAChB,OAAO;YACLkB,UAAUvB,cACR,sBACA,4DACA;QAEJ;IACF;IAEA,MAAMyH,sBAAsBpI,sBAAsB;QAChDqI,gBACExG,QAAQwG,cAAc,IACtB7J;QACFiJ;QACAa,WAAWX,cAAcf,OAAO,CAAC0B,SAAS;IAC5C;IAEA,IAAI,CAACF,oBAAoBpH,EAAE,EAAE;QAC3B,OAAO;YACLkB,UAAUvB,cACR,qBACAyH,oBAAoBvH,OAAO,EAC3B;QAEJ;IACF;IAEA,MAAM0H,oBAAoBjB,gCAAgCzF;IAE1D,IAAI0G,mBAAmB;QACrB,OAAO;YACLrG,UAAUqG;QACZ;IACF;IAEA,MAAMC,iBAAiB,MAAM7I,uBAAuB;QAClD2C,gBAAgBT,QAAQ4G,oBAAoB;QAC5CT,OAAOL,cAAcf,OAAO,CAACoB,KAAK;QAClCU,OAAOf,cAAcf,OAAO,CAAC8B,KAAK;QAClCjB;QACA3F,SAAS4F,IAAI5F,OAAO;IACtB;IAEA,IAAI,CAAC0G,gBAAgB;QACnB,OAAO;YACLtG,UAAUvB,cACR,gBACA,6CACA;QAEJ;IACF;IAEA,MAAMgI,gBAAgB7I,+BAA+B;QACnD8I,cAAc/G,QAAQ+G,YAAY;QAClCC,KAAKnB,IAAImB,GAAG;IACd;IACA,MAAMC,kBAAkBlJ,4BAA4B;QAClDuI,YAAYF,SAASc,YAAY;QACjCC,QAAQ;QACRN,OAAOf,cAAcf,OAAO,CAAC8B,KAAK;QAClCO,MAAMN;QACNL,WAAWX,cAAcf,OAAO,CAAC0B,SAAS;IAC5C;IAEA,IACE,CAACpI,uBAAuB;QACtB4I;QACAI,WAAWpB,UAAUoB,SAAS;QAC9BC,WAAWxB,cAAcf,OAAO,CAACuC,SAAS;IAC5C,IACA;QACA,OAAO;YACLjH,UAAUvB,cACR,qBACA,mCACA;QAEJ;IACF;IAEA,MAAMyI,kBAAkBvH,QAAQuH,eAAe,IAAI3K;IAEnD,OAAO;QACL4K,UAAU;YACRpB,UAAUA,SAASc,YAAY;YAC/BO,WAAW,IAAIC,KAAK9B,IAAI+B,OAAO,KAAKJ,kBAAkB;YACtDpB,OAAOL,cAAcf,OAAO,CAACoB,KAAK;YAClCU,OAAOf,cAAcf,OAAO,CAAC8B,KAAK;QACpC;IACF;AACF;AAEA,MAAMe,gCAAgC,OAAO,EAC3CtH,OAAO,EACPsF,GAAG,EACH5F,OAAO,EACPP,OAAO,EACPoG,GAAG,EAOJ;IAUC,MAAMR,QAAQH,eAAeW,IAAId,OAAO;IAExC,IAAIM,UAAUxF,WAAW;QACvB,OAAO;YACLQ,UAAUvB,cACR,kBACA,gDACA;QAEJ;IACF;IAEA,IAAIuG,UAAU,IAAI;QAChB,OAAO;YACLhF,UAAUvB,cACR,sBACA,qDACA;QAEJ;IACF;IAEA,MAAMuH,eAAevB,kBACnBe,IAAId,OAAO,EACX;IAGF,IAAI,CAACsB,cAAc;QACjB,OAAO;YACLhG,UAAUvB,cACR,kBACA,2DACA;QAEJ;IACF;IAEA,MAAMsH,WAAWhI,iBAAiB;QAChCM,MAAMe;QACN4G;IACF;IAEA,IAAI,CAACD,SAASjH,EAAE,EAAE;QAChB,OAAO;YACLkB,UAAUvB,cACR,sBACA,0DACA;QAEJ;IACF;IAEA,IAAI,CAACkB,QAAQ6H,kBAAkB,EAAE;QAC/B,OAAO;YACLxH,UAAUvB,cACR,iBACA,yEACA;QAEJ;IACF;IAEA,MAAMgJ,iBAAiB,MAAMvK,yBAAyB;QACpDkD,gBAAgBT,QAAQ+H,yBAAyB;QACjD9H,SAAS4F,IAAI5F,OAAO;IACtB;IACA,MAAM+H,aAAa1H,QAAQ2H,MAAM,CAACC,UAAU,CAAC,WACzC5H,QAAQ2H,MAAM,GACd,CAAC,WAAW,EAAE3H,QAAQ2H,MAAM,EAAE;IAElC,MAAME,WAAW,MAAM7J,sBAAsB;QAC3C8J,QAAQ;YACNC,aAAa;gBAACL;aAAW;YACzBM,qBAAqBhI,QAAQiI,gBAAgB,EAAED;YAC/CE,mBAAmBlI,QAAQkI,iBAAiB;YAC5CC,UAAUnI,QAAQE,IAAI;YACtBkI,qBAAqBpI,QAAQiI,gBAAgB,EAAE/D,YAAY;YAC3DsD;QACF;QACAa,WAAW3I,QAAQ4I,aAAa;QAChChD;QACAP;IACF;IAEA,IAAI,CAAC8C,SAAShJ,EAAE,EAAE;QAChB,OAAO;YACLkB,UAAUvB,cACRqJ,SAASpJ,IAAI,EACboJ,SAASnJ,OAAO,EAChBmJ,SAASpJ,IAAI,KAAK,0BAA0B,MAAM;QAEtD;IACF;IAEA,MAAM2H,oBAAoBjB,gCAAgCzF;IAE1D,IAAI0G,mBAAmB;QACrB,OAAO;YACLrG,UAAUqG;QACZ;IACF;IAEA,MAAMC,iBAAiB,MAAM7I,uBAAuB;QAClD2C,gBAAgBT,QAAQ4G,oBAAoB;QAC5CT,OAAOgC,SAAS9C,KAAK,CAACc,KAAK;QAC3BU,OAAOsB,SAAS9C,KAAK,CAACwD,MAAM,CAACC,GAAG;QAChClD;QACA3F,SAAS4F,IAAI5F,OAAO;IACtB;IAEA,IAAI,CAAC0G,gBAAgB;QACnB,OAAO;YACLtG,UAAUvB,cACR,eACA,gDACA;QAEJ;IACF;IAEA,OAAO;QACL0I,UAAU;YACRuB,OAAOZ,SAAS9C,KAAK,CAACwD,MAAM,CAACE,KAAK;YAClC3C,UAAUA,SAASc,YAAY;YAC/Be,QAAQE,SAAS9C,KAAK,CAACwD,MAAM,CAACG,GAAG;YACjCC,QAAQd,SAAS9C,KAAK,CAACwD,MAAM,CAACK,GAAG;YACjCzB,WAAWU,SAAS9C,KAAK,CAACoC,SAAS;YACnCtB,OAAOgC,SAAS9C,KAAK,CAACc,KAAK;YAC3BU,OAAOsB,SAAS9C,KAAK,CAACwD,MAAM,CAACC,GAAG;YAChCK,YAAYhB,SAAS9C,KAAK,CAACwD,MAAM,CAACM,UAAU;QAC9C;IACF;AACF;AAEA,MAAMC,0BAA0B,OAAO,EACrC9I,OAAO,EACPsF,GAAG,EACH5F,OAAO,EACPP,OAAO,EACPoG,GAAG,EAOJ;IAUC,MAAMwD,iBAAiB5L,qBAAqBuC,QAAQsJ,IAAI;IACxD,MAAMC,oBAAoB7L,wBAAwBsC,QAAQsJ,IAAI;IAE9D,IAAI,CAACD,kBAAkB,CAACE,mBAAmB;QACzC,OAAO;YACLlJ,UAAUvB,cACR,iBACA,4DACA;QAEJ;IACF;IAEA,MAAM0K,cAActE,eAAeW,IAAId,OAAO;IAE9C,IAAIyE,gBAAgB3J,WAAW;QAC7B,IAAI,CAAC0J,mBAAmB;YACtB,OAAO;gBACLlJ,UAAUvB,cACR,iBACA,wEACA;YAEJ;QACF;QAEA,OAAO8I,8BAA8B;YACnCtH;YACAsF;YACA5F;YACAP;YACAoG;QACF;IACF;IAEA,IAAIL,sBAAsBK,IAAId,OAAO,KAAK,CAACwE,mBAAmB;QAC5D,IAAI,CAACF,gBAAgB;YACnB,OAAO;gBACLhJ,UAAUvB,cACR,iBACA,mEACA;YAEJ;QACF;QAEA,OAAO6G,2BAA2B;YAChCC;YACA5F;YACAP;YACAoG;QACF;IACF;IAEA,OAAO+B,8BAA8B;QACnCtH;QACAsF;QACA5F;QACAP;QACAoG;IACF;AACF;AAEA,MAAM4D,4BACJ,CAACzJ,UACD,OAAO6F;QACL,MAAM6D,YAAY1J,QAAQ2J,MAAM,QAAQ,IAAIjC;QAE5C,IAAI7B,IAAIsB,MAAM,IAAItB,IAAIsB,MAAM,CAACyC,WAAW,OAAO,QAAQ;YACrD,OAAO9K,cAAc,kBAAkB,oCAAoC;QAC7E;QAEA,IAAI,OAAO+G,IAAIgE,IAAI,KAAK,YAAY;YAClC,OAAO/K,cACL,gBACA,2DACA;QAEJ;QAEA,MAAMW,UAAU,MAAMoG,IAAIgE,IAAI;QAC9B,MAAMC,eAAe9J,QAAQ8J,YAAY,IAAIpN;QAE7C,IAAI+F,OAAOC,UAAU,CAACjD,SAAS,UAAUqK,cAAc;YACrD,OAAOhL,cAAc,gBAAgB,mCAAmC;QAC1E;QAEA,MAAMiB,WAAWP,kBAAkBC;QAEnC,IAAI,CAACM,UAAU;YACb,OAAOjB,cAAc,gBAAgB,8CAA8C;QACrF;QAEA,MAAMiL,mBAAmB,MAAMjK,kBAAkB;YAC/CC;YACAC;YACAC,SAAS4F,IAAI5F,OAAO;QACtB;QAEA,IAAI8J,iBAAiB1J,QAAQ,EAAE;YAC7B,OAAO0J,iBAAiB1J,QAAQ;QAClC;QAEA,MAAM2J,iBAAiB,MAAMZ,wBAAwB;YACnD9I,SAASyJ,iBAAiB5J,MAAM,CAACG,OAAO;YACxCsF,KAAK8D;YACL1J;YACAP;YACAoG;QACF;QAEA,IAAImE,eAAe3J,QAAQ,EAAE;YAC3B,OAAO2J,eAAe3J,QAAQ;QAChC;QAEA,MAAM4J,aAAazL,qBAAqBuB,UAAU;YAChDmK,kBAAkB;gBAACH,iBAAiB5J,MAAM,CAACD,QAAQ;aAAC;YACpDiK,eAAeL;YACflJ,WAAWmJ,iBAAiB5J,MAAM,CAACS,SAAS;QAC9C;QAEA,IAAI,CAACqJ,WAAW9K,EAAE,EAAE;YAClB,OAAOV,aACL;gBACES,OAAO;oBACLH,MAAM;oBACNC,SAAS;gBACX;gBACAG,IAAI;YACN,GACA;QAEJ;QAEA,MAAMiL,0BAA0BpK,QAAQwD,cAAc,IAAI;QAC1D,MAAM6G,uBAAwCJ,WAAWK,IAAI,CAAC5G,OAAO,GACjE,cACAN,sBAAsBpD;QAC1B,MAAMuK,uBAAuBhH,wBAAwB;YACnDC,gBAAgB4G;YAChBrK,UAAUkK,WAAWK,IAAI;YACzBtK;YACAyD,aAAa4G;QACf;QAEA,IAAIE,sBAAsB;YACxB,OAAOA;QACT;QAEA,MAAMC,kBAAkB,MAAM3G,wBAAwB;YACpDvD,SAASyJ,iBAAiB5J,MAAM,CAACG,OAAO;YACxCP,UAAUkK,WAAWK,IAAI;YACzBtK;YACAC,SAAS4F,IAAI5F,OAAO;YACpBW,WAAWmJ,iBAAiB5J,MAAM,CAACS,SAAS;QAC9C;QAEA,IAAI4J,gBAAgBxJ,MAAM,GAAG,GAAG;YAC9B,OAAOlC,cACL,mBACA,uEACA,KACA;gBACE0L;YACF;QAEJ;QAEA,MAAMC,aAAaR,WAAWK,IAAI,CAACI,IAAI,KAAK;QAE5C,IAAID,cAAczK,QAAQ2K,WAAW,KAAK,MAAM;YAC9C,OAAO7L,cACL,wBACA,qDACA;QAEJ;QAEA,IAAI2L,cAAczK,QAAQ4K,wBAAwB,KAAK,MAAM;YAC3D,OAAO9L,cACL,oCACA,+DACA;QAEJ;QAEA,IACE2L,cACA,CAAC3N,mCAAmCsN,yBAAyB;YAC3DxG,iBAAiB5D,QAAQ4D,eAAe;YACxCN,kBAAkBtD,QAAQsD,gBAAgB;QAC5C,IACA;YACA,OAAOxE,cACL,mCACA,iDACA;QAEJ;QAEA,IAAI2L,cAAc,CAACzK,QAAQ6K,eAAe,EAAE;YAC1C,OAAO/L,cACL,qBACA,wDACA;QAEJ;QAEA,MAAMgM,sBAAsB9K,QAAQiE,WAAW,GAC3C,MAAM3G,+BAA+B;YACnCmD,gBAAgBT,QAAQkE,kBAAkB;YAC1CC,WAAW4F,iBAAiB5J,MAAM,CAACG,OAAO,EAAEF;YAC5C2K,mBAAmB/K,QAAQ+K,iBAAiB;YAC5C9K,SAAS4F,IAAI5F,OAAO;YACpBC,UAAU+J,WAAWK,IAAI,CAACnK,MAAM,CAACC,EAAE;QACrC,KACA,EAAE;QACN,MAAM4K,eAAeF,oBAAoB3I,GAAG,CAACxE;QAC7C,MAAMmD,OAAOvC,aAAa;YACxBiF,gBAAgB4G;YAChBtI,SAASmI,WAAWK,IAAI;YACxBzH,UAAUmI;QACZ;QACA,MAAMC,UAAUpK,cAAcC;QAC9B,MAAMQ,WAAW;eAAI2I,WAAW3I,QAAQ;eAAKR,KAAKQ,QAAQ;SAAC;QAC3D,IAAImJ,YAAY;YACd,MAAM3H,uBAAuB,IAAIC,IAC/B+H,oBAAoB3I,GAAG,CAAC,CAACa,SAAW;oBAACA,OAAOf,UAAU;oBAAEe;iBAAO;YAEjE,MAAMkI,YAAY/N,sBAAsB;gBACtC2F;gBACAqI,gBAAgBvI,0BAA0B;oBACxCC,UAAUiI;oBACVhK;gBACF;YACF;YAEA,IAAIoK,UAAUlK,MAAM,GAAG,GAAG;gBACxB,OAAOlC,cACL,wBACA,kEACA,KACA;oBACEoM;gBACF;YAEJ;QACF;QAEA,MAAMhN,mBAAmB;YACvBkI,UAAU4D,eAAexC,QAAQ,CAACpB,QAAQ;YAC1C3F,gBAAgBT,QAAQ4G,oBAAoB;YAC5Ca,WAAWuC,eAAexC,QAAQ,CAACC,SAAS;YAC5CtB,OAAO6D,eAAexC,QAAQ,CAACrB,KAAK;YACpCU,OAAOmD,eAAexC,QAAQ,CAACX,KAAK;YACpC5G,SAAS4F,IAAI5F,OAAO;YACpBC,UAAU+J,WAAWK,IAAI,CAACnK,MAAM,CAACC,EAAE;YACnCgL,QAAQ1B;QACV;QAEA,IAAI2B;QAEJ,IAAIrL,QAAQ6K,eAAe,EAAE;YAC3B,MAAMS,UAAU,MAAMvO,mBAAmB;gBACvCgM,OAAOiB,eAAexC,QAAQ,CAACuB,KAAK;gBACpC3C,UAAU4D,eAAexC,QAAQ,CAACpB,QAAQ;gBAC1C6B,QAAQ+B,eAAexC,QAAQ,CAACS,MAAM,IAAIgC,WAAWK,IAAI,CAACnK,MAAM,CAAC8H,MAAM;gBACvExH,gBAAgBT,QAAQuL,sBAAsB;gBAC9CtC,QAAQe,eAAexC,QAAQ,CAACyB,MAAM,IAAIgB,WAAWK,IAAI,CAACnK,MAAM,CAAC8I,MAAM;gBACvEuC,aAAaf,aAAaf,YAAY1J,QAAQ2J,MAAM,QAAQ,IAAIjC;gBAChElE,gBAAgB4G;gBAChBC;gBACAoB,QAAQ,EAAE;gBACVC,WAAWzB,WAAWK,IAAI,CAACjI,KAAK,CAACrB,MAAM;gBACvCmF,OAAO6D,eAAexC,QAAQ,CAACrB,KAAK;gBACpCuE,MAAMD,aAAa,SAAS;gBAC5BxK,SAAS4F,IAAI5F,OAAO;gBACpB0L,kBAAkB1B,WAAWK,IAAI,CAAC5G,OAAO;gBACzCyF,YACEa,eAAexC,QAAQ,CAAC2B,UAAU,IAAIc,WAAWK,IAAI,CAACnK,MAAM,CAACgJ,UAAU;gBACzEjJ,UAAU+J,WAAWK,IAAI,CAACnK,MAAM,CAACC,EAAE;gBACnCsJ;gBACA/K,QAAQ8L,aAAa,YAAY;gBACjCQ;gBACAW,YAAYxJ,sBAAsB6H,WAAWK,IAAI;gBACjDhJ;YACF;YAEA+J,YAAY7N,YAAY8N;QAC1B;QAEA,IAAIb,YAAY;YACd,IAAI,CAACY,WAAW;gBACd,OAAOvM,cACL,qBACA,0DACA;YAEJ;YAEA,IAAI;gBACF,MAAM+M,cAAc,MAAMhP,cAAc;oBACtC4D,gBAAgBT,QAAQkE,kBAAkB;oBAC1CV,gBAAgB4G;oBAChB9G,kBAAkBtD,QAAQsD,gBAAgB;oBAC1Ca,WAAW4F,iBAAiB5J,MAAM,CAACG,OAAO,EAAEF;oBAC5CyC,UAAUiI;oBACV/K,UAAUkK,WAAWK,IAAI;oBACzBS,mBAAmB/K,QAAQ+K,iBAAiB;oBAC5CnF,KAAK5F,QAAQ2J,MAAM,QAAQ,IAAIjC;oBAC/BzH,SAAS4F,IAAI5F,OAAO;oBACpBa;oBACA2C,aAAa4G;oBACbgB;gBACF;gBAEA,IAAI,CAACQ,YAAY1M,EAAE,EAAE;oBACnB,OAAOL,cACL,wBACA,kEACA,KACA;wBACEoM,WAAWW,YAAYX,SAAS;oBAClC;gBAEJ;gBAEA,MAAMrN,mBAAmB;oBACvB4C,gBAAgBT,QAAQuL,sBAAsB;oBAC9CC,aAAaxL,QAAQ2J,MAAM,QAAQ,IAAIjC;oBACvCzH,SAAS4F,IAAI5F,OAAO;oBACpBtB,QAAQ;oBACRsM;oBACAI;oBACA/J;gBACF;gBAEA,IAAIyI,iBAAiB5J,MAAM,CAACG,OAAO,EAAE;oBACnC,MAAM1C,uBAAuB;wBAC3BkO,UAAU7B,WAAWK,IAAI,CAACwB,QAAQ;wBAClCrL,gBAAgBT,QAAQU,sBAAsB;wBAC9CqL,WAAW9B,WAAWK,IAAI,CAACjI,KAAK,CAACrB,MAAM;wBACvCmD,WAAW4F,iBAAiB5J,MAAM,CAACG,OAAO,CAACF,EAAE;wBAC7CwF,KAAK5F,QAAQ2J,MAAM,QAAQ,IAAIjC;wBAC/BzH,SAAS4F,IAAI5F,OAAO;wBACpBoL;oBACF;gBACF;YACF,EAAE,OAAOnM,OAAO;gBACd,MAAMrB,mBAAmB;oBACvB4C,gBAAgBT,QAAQuL,sBAAsB;oBAC9CC,aAAaxL,QAAQ2J,MAAM,QAAQ,IAAIjC;oBACvC+D,QAAQ;wBACN;4BACE1M,MAAM;4BACNC,SAASE,iBAAiB8M,QAAQ9M,MAAMF,OAAO,GAAG;wBACpD;qBACD;oBACDiB,SAAS4F,IAAI5F,OAAO;oBACpBtB,QAAQ;oBACRsM;oBACAI;oBACA/J;gBACF;gBAEA,OAAOxC,cAAc,qBAAqB,sBAAsB;YAClE;QACF;QAEA,OAAOL,aAAa;YAClBwN,SAAS/J,iBAAiBpB;YAC1B0C,gBAAgB4G;YAChB8B,QAAQ,CAACzB;YACTJ;YACAlL,IAAI;YACJwM,kBAAkB1B,WAAWK,IAAI,CAAC5G,OAAO;YACzCuH;YACAI,WAAWA,cAAcxL,YAAYA,YAAYsM,OAAOd;YACxD/J;QACF;IACF;AAEF,OAAO,MAAM8K,qBAAqB,CAACpM,UAAkD,CAAA;QACnFqM,SAAS5C,0BAA0BzJ;QACnCmH,QAAQ;QACRC,MAAMpH,QAAQ+G,YAAY;IAC5B,CAAA,EAAE"}
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 includeDrafts: true,\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 includeDrafts: options.docsEnableDrafts,\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 draft: options.docsEnableDrafts,\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 publish: validation.data.publish,\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","includeDrafts","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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"}
@@ -1,6 +1,6 @@
1
1
  import { DEFAULT_DOCS_GROUPS_COLLECTION_SLUG, DEFAULT_DOCS_SETS_COLLECTION_SLUG } from '../constants.js';
2
2
  import { deriveDocsSetRouteBase, joinRouteSegments } from '../routing/index.js';
3
- import { getRelationshipId, isRecord, toResolvedDocsSet } from './records.js';
3
+ import { getRelationshipId, isRecord, isVisibleDocsSet, toResolvedDocsSet } from './records.js';
4
4
  const getGroupRoutePath = ({ groupId, groupsById, seen = new Set() })=>{
5
5
  if (!groupId || seen.has(groupId)) {
6
6
  return undefined;
@@ -25,6 +25,7 @@ export const getPayloadMarkdownDocsLinks = async ({ collections, overrideAccess
25
25
  payload.find({
26
26
  collection: docsSetsCollectionSlug,
27
27
  depth: 0,
28
+ draft: false,
28
29
  limit: 1000,
29
30
  overrideAccess
30
31
  }),
@@ -49,7 +50,9 @@ export const getPayloadMarkdownDocsLinks = async ({ collections, overrideAccess
49
50
  }));
50
51
  return docsSetsResult.docs.flatMap((doc)=>{
51
52
  const docsSet = toResolvedDocsSet(doc);
52
- if (!docsSet?.slug || !isRecord(doc)) {
53
+ if (!docsSet?.slug || !isRecord(doc) || !isVisibleDocsSet({
54
+ docsSet
55
+ })) {
53
56
  return [];
54
57
  }
55
58
  return [
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/next/links.ts"],"sourcesContent":["import type {\n PayloadMarkdownDocsCollectionSlugs,\n PayloadMarkdownDocsReadPayload,\n} from './types.js'\n\nimport {\n DEFAULT_DOCS_GROUPS_COLLECTION_SLUG,\n DEFAULT_DOCS_SETS_COLLECTION_SLUG,\n} from '../constants.js'\nimport { deriveDocsSetRouteBase, joinRouteSegments } from '../routing/index.js'\nimport {\n getRelationshipId,\n isRecord,\n toResolvedDocsSet,\n} from './records.js'\n\nexport type PayloadMarkdownDocsLink = {\n label: string\n url: string\n}\n\nexport type GetPayloadMarkdownDocsLinksOptions = {\n collections?: Pick<PayloadMarkdownDocsCollectionSlugs, 'docsGroups' | 'docsSets'>\n overrideAccess?: boolean\n payload: PayloadMarkdownDocsReadPayload\n}\n\nconst getGroupRoutePath = ({\n groupId,\n groupsById,\n seen = new Set<string>(),\n}: {\n groupId?: string\n groupsById: Map<string, unknown>\n seen?: Set<string>\n}): string | undefined => {\n if (!groupId || seen.has(groupId)) {\n return undefined\n }\n\n const group = groupsById.get(groupId)\n\n if (!isRecord(group) || typeof group.slug !== 'string') {\n return undefined\n }\n\n return joinRouteSegments(\n getGroupRoutePath({\n groupId: getRelationshipId(group.parent),\n groupsById,\n seen: new Set([groupId, ...seen]),\n }),\n group.slug,\n )\n}\n\nexport const getPayloadMarkdownDocsLinks = async ({\n collections,\n overrideAccess = true,\n payload,\n}: GetPayloadMarkdownDocsLinksOptions): Promise<PayloadMarkdownDocsLink[]> => {\n const docsGroupsCollectionSlug =\n collections?.docsGroups ?? DEFAULT_DOCS_GROUPS_COLLECTION_SLUG\n const docsSetsCollectionSlug =\n collections?.docsSets ?? DEFAULT_DOCS_SETS_COLLECTION_SLUG\n const [docsSetsResult, docsGroupsResult] = await Promise.all([\n payload.find({\n collection: docsSetsCollectionSlug,\n depth: 0,\n limit: 1000,\n overrideAccess,\n }),\n payload.find({\n collection: docsGroupsCollectionSlug,\n depth: 0,\n limit: 1000,\n overrideAccess,\n }),\n ])\n const groupsById = new Map(\n docsGroupsResult.docs.flatMap((group) => {\n if (!isRecord(group)) {\n return []\n }\n\n const id = getRelationshipId(group)\n\n return id ? [[id, group]] : []\n }),\n )\n\n return docsSetsResult.docs\n .flatMap((doc) => {\n const docsSet = toResolvedDocsSet(doc)\n\n if (!docsSet?.slug || !isRecord(doc)) {\n return []\n }\n\n return [\n {\n label: docsSet.navTitle ?? docsSet.title,\n order: docsSet.order,\n url: deriveDocsSetRouteBase({\n docsSetSlug: docsSet.slug,\n groupRoutePath: getGroupRoutePath({\n groupId: getRelationshipId(doc.group),\n groupsById,\n }),\n }),\n },\n ]\n })\n .sort((first, second) => {\n if (first.order !== second.order) {\n return first.order - second.order\n }\n\n return first.label.localeCompare(second.label)\n })\n .map(({ label, url }) => ({\n label,\n url,\n }))\n}\n"],"names":["DEFAULT_DOCS_GROUPS_COLLECTION_SLUG","DEFAULT_DOCS_SETS_COLLECTION_SLUG","deriveDocsSetRouteBase","joinRouteSegments","getRelationshipId","isRecord","toResolvedDocsSet","getGroupRoutePath","groupId","groupsById","seen","Set","has","undefined","group","get","slug","parent","getPayloadMarkdownDocsLinks","collections","overrideAccess","payload","docsGroupsCollectionSlug","docsGroups","docsSetsCollectionSlug","docsSets","docsSetsResult","docsGroupsResult","Promise","all","find","collection","depth","limit","Map","docs","flatMap","id","doc","docsSet","label","navTitle","title","order","url","docsSetSlug","groupRoutePath","sort","first","second","localeCompare","map"],"mappings":"AAKA,SACEA,mCAAmC,EACnCC,iCAAiC,QAC5B,kBAAiB;AACxB,SAASC,sBAAsB,EAAEC,iBAAiB,QAAQ,sBAAqB;AAC/E,SACEC,iBAAiB,EACjBC,QAAQ,EACRC,iBAAiB,QACZ,eAAc;AAarB,MAAMC,oBAAoB,CAAC,EACzBC,OAAO,EACPC,UAAU,EACVC,OAAO,IAAIC,KAAa,EAKzB;IACC,IAAI,CAACH,WAAWE,KAAKE,GAAG,CAACJ,UAAU;QACjC,OAAOK;IACT;IAEA,MAAMC,QAAQL,WAAWM,GAAG,CAACP;IAE7B,IAAI,CAACH,SAASS,UAAU,OAAOA,MAAME,IAAI,KAAK,UAAU;QACtD,OAAOH;IACT;IAEA,OAAOV,kBACLI,kBAAkB;QAChBC,SAASJ,kBAAkBU,MAAMG,MAAM;QACvCR;QACAC,MAAM,IAAIC,IAAI;YAACH;eAAYE;SAAK;IAClC,IACAI,MAAME,IAAI;AAEd;AAEA,OAAO,MAAME,8BAA8B,OAAO,EAChDC,WAAW,EACXC,iBAAiB,IAAI,EACrBC,OAAO,EAC4B;IACnC,MAAMC,2BACJH,aAAaI,cAAcvB;IAC7B,MAAMwB,yBACJL,aAAaM,YAAYxB;IAC3B,MAAM,CAACyB,gBAAgBC,iBAAiB,GAAG,MAAMC,QAAQC,GAAG,CAAC;QAC3DR,QAAQS,IAAI,CAAC;YACXC,YAAYP;YACZQ,OAAO;YACPC,OAAO;YACPb;QACF;QACAC,QAAQS,IAAI,CAAC;YACXC,YAAYT;YACZU,OAAO;YACPC,OAAO;YACPb;QACF;KACD;IACD,MAAMX,aAAa,IAAIyB,IACrBP,iBAAiBQ,IAAI,CAACC,OAAO,CAAC,CAACtB;QAC7B,IAAI,CAACT,SAASS,QAAQ;YACpB,OAAO,EAAE;QACX;QAEA,MAAMuB,KAAKjC,kBAAkBU;QAE7B,OAAOuB,KAAK;YAAC;gBAACA;gBAAIvB;aAAM;SAAC,GAAG,EAAE;IAChC;IAGF,OAAOY,eAAeS,IAAI,CACvBC,OAAO,CAAC,CAACE;QACR,MAAMC,UAAUjC,kBAAkBgC;QAElC,IAAI,CAACC,SAASvB,QAAQ,CAACX,SAASiC,MAAM;YACpC,OAAO,EAAE;QACX;QAEA,OAAO;YACL;gBACEE,OAAOD,QAAQE,QAAQ,IAAIF,QAAQG,KAAK;gBACxCC,OAAOJ,QAAQI,KAAK;gBACpBC,KAAK1C,uBAAuB;oBAC1B2C,aAAaN,QAAQvB,IAAI;oBACzB8B,gBAAgBvC,kBAAkB;wBAChCC,SAASJ,kBAAkBkC,IAAIxB,KAAK;wBACpCL;oBACF;gBACF;YACF;SACD;IACH,GACCsC,IAAI,CAAC,CAACC,OAAOC;QACZ,IAAID,MAAML,KAAK,KAAKM,OAAON,KAAK,EAAE;YAChC,OAAOK,MAAML,KAAK,GAAGM,OAAON,KAAK;QACnC;QAEA,OAAOK,MAAMR,KAAK,CAACU,aAAa,CAACD,OAAOT,KAAK;IAC/C,GACCW,GAAG,CAAC,CAAC,EAAEX,KAAK,EAAEI,GAAG,EAAE,GAAM,CAAA;YACxBJ;YACAI;QACF,CAAA;AACJ,EAAC"}
1
+ {"version":3,"sources":["../../src/next/links.ts"],"sourcesContent":["import type { PayloadMarkdownDocsCollectionSlugs, PayloadMarkdownDocsReadPayload } from './types.js'\n\nimport {\n DEFAULT_DOCS_GROUPS_COLLECTION_SLUG,\n DEFAULT_DOCS_SETS_COLLECTION_SLUG,\n} from '../constants.js'\nimport { deriveDocsSetRouteBase, joinRouteSegments } from '../routing/index.js'\nimport { getRelationshipId, isRecord, isVisibleDocsSet, toResolvedDocsSet } from './records.js'\n\nexport type PayloadMarkdownDocsLink = {\n label: string\n url: string\n}\n\nexport type GetPayloadMarkdownDocsLinksOptions = {\n collections?: Pick<PayloadMarkdownDocsCollectionSlugs, 'docsGroups' | 'docsSets'>\n overrideAccess?: boolean\n payload: PayloadMarkdownDocsReadPayload\n}\n\nconst getGroupRoutePath = ({\n groupId,\n groupsById,\n seen = new Set<string>(),\n}: {\n groupId?: string\n groupsById: Map<string, unknown>\n seen?: Set<string>\n}): string | undefined => {\n if (!groupId || seen.has(groupId)) {\n return undefined\n }\n\n const group = groupsById.get(groupId)\n\n if (!isRecord(group) || typeof group.slug !== 'string') {\n return undefined\n }\n\n return joinRouteSegments(\n getGroupRoutePath({\n groupId: getRelationshipId(group.parent),\n groupsById,\n seen: new Set([groupId, ...seen]),\n }),\n group.slug,\n )\n}\n\nexport const getPayloadMarkdownDocsLinks = async ({\n collections,\n overrideAccess = true,\n payload,\n}: GetPayloadMarkdownDocsLinksOptions): Promise<PayloadMarkdownDocsLink[]> => {\n const docsGroupsCollectionSlug = collections?.docsGroups ?? DEFAULT_DOCS_GROUPS_COLLECTION_SLUG\n const docsSetsCollectionSlug = collections?.docsSets ?? DEFAULT_DOCS_SETS_COLLECTION_SLUG\n const [docsSetsResult, docsGroupsResult] = await Promise.all([\n payload.find({\n collection: docsSetsCollectionSlug,\n depth: 0,\n draft: false,\n limit: 1000,\n overrideAccess,\n }),\n payload.find({\n collection: docsGroupsCollectionSlug,\n depth: 0,\n limit: 1000,\n overrideAccess,\n }),\n ])\n const groupsById = new Map(\n docsGroupsResult.docs.flatMap((group) => {\n if (!isRecord(group)) {\n return []\n }\n\n const id = getRelationshipId(group)\n\n return id ? [[id, group]] : []\n }),\n )\n\n return docsSetsResult.docs\n .flatMap((doc) => {\n const docsSet = toResolvedDocsSet(doc)\n\n if (!docsSet?.slug || !isRecord(doc) || !isVisibleDocsSet({ docsSet })) {\n return []\n }\n\n return [\n {\n label: docsSet.navTitle ?? docsSet.title,\n order: docsSet.order,\n url: deriveDocsSetRouteBase({\n docsSetSlug: docsSet.slug,\n groupRoutePath: getGroupRoutePath({\n groupId: getRelationshipId(doc.group),\n groupsById,\n }),\n }),\n },\n ]\n })\n .sort((first, second) => {\n if (first.order !== second.order) {\n return first.order - second.order\n }\n\n return first.label.localeCompare(second.label)\n })\n .map(({ label, url }) => ({\n label,\n url,\n }))\n}\n"],"names":["DEFAULT_DOCS_GROUPS_COLLECTION_SLUG","DEFAULT_DOCS_SETS_COLLECTION_SLUG","deriveDocsSetRouteBase","joinRouteSegments","getRelationshipId","isRecord","isVisibleDocsSet","toResolvedDocsSet","getGroupRoutePath","groupId","groupsById","seen","Set","has","undefined","group","get","slug","parent","getPayloadMarkdownDocsLinks","collections","overrideAccess","payload","docsGroupsCollectionSlug","docsGroups","docsSetsCollectionSlug","docsSets","docsSetsResult","docsGroupsResult","Promise","all","find","collection","depth","draft","limit","Map","docs","flatMap","id","doc","docsSet","label","navTitle","title","order","url","docsSetSlug","groupRoutePath","sort","first","second","localeCompare","map"],"mappings":"AAEA,SACEA,mCAAmC,EACnCC,iCAAiC,QAC5B,kBAAiB;AACxB,SAASC,sBAAsB,EAAEC,iBAAiB,QAAQ,sBAAqB;AAC/E,SAASC,iBAAiB,EAAEC,QAAQ,EAAEC,gBAAgB,EAAEC,iBAAiB,QAAQ,eAAc;AAa/F,MAAMC,oBAAoB,CAAC,EACzBC,OAAO,EACPC,UAAU,EACVC,OAAO,IAAIC,KAAa,EAKzB;IACC,IAAI,CAACH,WAAWE,KAAKE,GAAG,CAACJ,UAAU;QACjC,OAAOK;IACT;IAEA,MAAMC,QAAQL,WAAWM,GAAG,CAACP;IAE7B,IAAI,CAACJ,SAASU,UAAU,OAAOA,MAAME,IAAI,KAAK,UAAU;QACtD,OAAOH;IACT;IAEA,OAAOX,kBACLK,kBAAkB;QAChBC,SAASL,kBAAkBW,MAAMG,MAAM;QACvCR;QACAC,MAAM,IAAIC,IAAI;YAACH;eAAYE;SAAK;IAClC,IACAI,MAAME,IAAI;AAEd;AAEA,OAAO,MAAME,8BAA8B,OAAO,EAChDC,WAAW,EACXC,iBAAiB,IAAI,EACrBC,OAAO,EAC4B;IACnC,MAAMC,2BAA2BH,aAAaI,cAAcxB;IAC5D,MAAMyB,yBAAyBL,aAAaM,YAAYzB;IACxD,MAAM,CAAC0B,gBAAgBC,iBAAiB,GAAG,MAAMC,QAAQC,GAAG,CAAC;QAC3DR,QAAQS,IAAI,CAAC;YACXC,YAAYP;YACZQ,OAAO;YACPC,OAAO;YACPC,OAAO;YACPd;QACF;QACAC,QAAQS,IAAI,CAAC;YACXC,YAAYT;YACZU,OAAO;YACPE,OAAO;YACPd;QACF;KACD;IACD,MAAMX,aAAa,IAAI0B,IACrBR,iBAAiBS,IAAI,CAACC,OAAO,CAAC,CAACvB;QAC7B,IAAI,CAACV,SAASU,QAAQ;YACpB,OAAO,EAAE;QACX;QAEA,MAAMwB,KAAKnC,kBAAkBW;QAE7B,OAAOwB,KAAK;YAAC;gBAACA;gBAAIxB;aAAM;SAAC,GAAG,EAAE;IAChC;IAGF,OAAOY,eAAeU,IAAI,CACvBC,OAAO,CAAC,CAACE;QACR,MAAMC,UAAUlC,kBAAkBiC;QAElC,IAAI,CAACC,SAASxB,QAAQ,CAACZ,SAASmC,QAAQ,CAAClC,iBAAiB;YAAEmC;QAAQ,IAAI;YACtE,OAAO,EAAE;QACX;QAEA,OAAO;YACL;gBACEC,OAAOD,QAAQE,QAAQ,IAAIF,QAAQG,KAAK;gBACxCC,OAAOJ,QAAQI,KAAK;gBACpBC,KAAK5C,uBAAuB;oBAC1B6C,aAAaN,QAAQxB,IAAI;oBACzB+B,gBAAgBxC,kBAAkB;wBAChCC,SAASL,kBAAkBoC,IAAIzB,KAAK;wBACpCL;oBACF;gBACF;YACF;SACD;IACH,GACCuC,IAAI,CAAC,CAACC,OAAOC;QACZ,IAAID,MAAML,KAAK,KAAKM,OAAON,KAAK,EAAE;YAChC,OAAOK,MAAML,KAAK,GAAGM,OAAON,KAAK;QACnC;QAEA,OAAOK,MAAMR,KAAK,CAACU,aAAa,CAACD,OAAOT,KAAK;IAC/C,GACCW,GAAG,CAAC,CAAC,EAAEX,KAAK,EAAEI,GAAG,EAAE,GAAM,CAAA;YACxBJ;YACAI;QACF,CAAA;AACJ,EAAC"}
@@ -1,7 +1,7 @@
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, joinRouteSegments, normalizeRoutePath } from '../routing/index.js';
3
3
  import { isExcludedFromAiExport } from '../sync/index.js';
4
- import { getRelationshipId, isRecord, isVisibleDocsRecord, toResolvedDocsGroup, toResolvedDocsRecord, toResolvedDocsSet } from './records.js';
4
+ import { getRelationshipId, isRecord, isVisibleDocsRecord, isVisibleDocsSet, toResolvedDocsGroup, toResolvedDocsRecord, toResolvedDocsSet } from './records.js';
5
5
  const resolveCollectionSlugs = (collections)=>({
6
6
  docs: collections?.docs ?? DEFAULT_DOCS_COLLECTION_SLUG,
7
7
  docsGroups: collections?.docsGroups ?? DEFAULT_DOCS_GROUPS_COLLECTION_SLUG,
@@ -75,11 +75,12 @@ const withComputedDocsSetRoute = ({ doc, docsSet, groupsById })=>{
75
75
  })
76
76
  };
77
77
  };
78
- const findDocsSetByRouteBase = async ({ collections, overrideAccess, payload, routeBase })=>{
78
+ const findDocsSetByRouteBase = async ({ collections, includeDrafts, overrideAccess, payload, routeBase })=>{
79
79
  const [result, groupsById] = await Promise.all([
80
80
  payload.find({
81
81
  collection: collections.docsSets,
82
82
  depth: 0,
83
+ draft: includeDrafts,
83
84
  limit: 1000,
84
85
  overrideAccess
85
86
  }),
@@ -93,13 +94,17 @@ const findDocsSetByRouteBase = async ({ collections, overrideAccess, payload, ro
93
94
  doc,
94
95
  docsSet: toResolvedDocsSet(doc),
95
96
  groupsById
96
- })).find((docsSet)=>docsSet?.routeBase === routeBase);
97
+ })).find((docsSet)=>docsSet?.routeBase === routeBase && isVisibleDocsSet({
98
+ docsSet,
99
+ includeDrafts
100
+ }));
97
101
  };
98
- const findDocsSetByAiExportOutput = async ({ collections, output, overrideAccess, payload })=>{
102
+ const findDocsSetByAiExportOutput = async ({ collections, includeDrafts, output, overrideAccess, payload })=>{
99
103
  const [result, groupsById] = await Promise.all([
100
104
  payload.find({
101
105
  collection: collections.docsSets,
102
106
  depth: 0,
107
+ draft: includeDrafts,
103
108
  limit: 1000,
104
109
  overrideAccess
105
110
  }),
@@ -113,21 +118,26 @@ const findDocsSetByAiExportOutput = async ({ collections, output, overrideAccess
113
118
  doc,
114
119
  docsSet: toResolvedDocsSet(doc),
115
120
  groupsById
116
- })).find((docsSet)=>docsSet?.aiExport?.output === output);
121
+ })).find((docsSet)=>docsSet?.aiExport?.output === output && isVisibleDocsSet({
122
+ docsSet,
123
+ includeDrafts
124
+ }));
117
125
  };
118
- const findDocsSetForMarkdownRoute = async ({ collections, overrideAccess, payload, route })=>{
126
+ const findDocsSetForMarkdownRoute = async ({ collections, includeDrafts, overrideAccess, payload, route })=>{
119
127
  const routeBase = stripMarkdownRouteSuffix(route);
120
128
  if (!routeBase) {
121
129
  return undefined;
122
130
  }
123
131
  const docsSet = await findDocsSetByRouteBase({
124
132
  collections,
133
+ includeDrafts,
125
134
  overrideAccess,
126
135
  payload,
127
136
  routeBase
128
137
  });
129
138
  return docsSet ?? findDocsSetByAiExportOutput({
130
139
  collections,
140
+ includeDrafts,
131
141
  output: route,
132
142
  overrideAccess,
133
143
  payload
@@ -137,6 +147,7 @@ const getDocsRecords = async ({ collections, docsSet, includeDrafts, markdownFie
137
147
  const result = await payload.find({
138
148
  collection: collections.docs,
139
149
  depth: 0,
150
+ draft: includeDrafts,
140
151
  limit: 1000,
141
152
  overrideAccess,
142
153
  where: {
@@ -251,6 +262,7 @@ overrideAccess = true, path, payload })=>{
251
262
  const collections = resolveCollectionSlugs(collectionOptions);
252
263
  const docsSet = await findDocsSetForMarkdownRoute({
253
264
  collections,
265
+ includeDrafts,
254
266
  overrideAccess,
255
267
  payload,
256
268
  route
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/next/markdown.ts"],"sourcesContent":["import type {\n DocsAiExportManifest,\n DocsValidationIssue,\n} from '../sync/index.js'\nimport type {\n PayloadMarkdownDocsCollectionSlugs,\n PayloadMarkdownDocsReadPayload,\n ResolvedPayloadMarkdownDocsRecord,\n ResolvedPayloadMarkdownDocsSet,\n ResolvePayloadMarkdownDocsRouteOptions,\n} from './types.js'\n\nimport {\n DEFAULT_DOCS_COLLECTION_SLUG,\n DEFAULT_DOCS_GROUPS_COLLECTION_SLUG,\n DEFAULT_DOCS_SETS_COLLECTION_SLUG,\n DEFAULT_MARKDOWN_FIELD_NAME,\n} from '../constants.js'\nimport {\n deriveDocsSetRouteBase,\n joinRouteSegments,\n normalizeRoutePath,\n} from '../routing/index.js'\nimport {\n isExcludedFromAiExport,\n} from '../sync/index.js'\nimport {\n getRelationshipId,\n isRecord,\n isVisibleDocsRecord,\n toResolvedDocsGroup,\n toResolvedDocsRecord,\n toResolvedDocsSet,\n} from './records.js'\n\nexport type ResolvedPayloadMarkdownDocsMarkdownRoute = {\n contentType: 'text/markdown; charset=utf-8'\n docsSet: ResolvedPayloadMarkdownDocsSet\n markdown: string\n output: string\n route: string\n type: 'markdown'\n warnings: DocsValidationIssue[]\n}\n\nexport type ResolvePayloadMarkdownDocsMarkdownRouteOptions =\n ResolvePayloadMarkdownDocsRouteOptions\n\ntype ResolvedCollectionSlugs = {\n docs: string\n docsGroups: string\n docsSets: string\n}\n\nconst resolveCollectionSlugs = (\n collections?: PayloadMarkdownDocsCollectionSlugs,\n): ResolvedCollectionSlugs => ({\n docs: collections?.docs ?? DEFAULT_DOCS_COLLECTION_SLUG,\n docsGroups: collections?.docsGroups ?? DEFAULT_DOCS_GROUPS_COLLECTION_SLUG,\n docsSets: collections?.docsSets ?? DEFAULT_DOCS_SETS_COLLECTION_SLUG,\n})\n\nconst getRoutePath = ({\n slug,\n path,\n}: Pick<ResolvePayloadMarkdownDocsRouteOptions, 'path' | 'slug'>): string => {\n if (path !== undefined) {\n return normalizeRoutePath(path)\n }\n\n if (Array.isArray(slug)) {\n return normalizeRoutePath(slug.length === 0 ? '/' : slug.join('/'))\n }\n\n if (typeof slug === 'string') {\n return normalizeRoutePath(slug)\n }\n\n return '/'\n}\n\nconst stripMarkdownRouteSuffix = (route: string): string | undefined =>\n route.toLowerCase().endsWith('.md') ? route.slice(0, -3) : undefined\n\nconst getGroupsById = async ({\n collections,\n overrideAccess,\n payload,\n}: {\n collections: ResolvedCollectionSlugs\n overrideAccess: boolean\n payload: PayloadMarkdownDocsReadPayload\n}): Promise<Map<string, unknown>> => {\n const result = await payload.find({\n collection: collections.docsGroups,\n depth: 0,\n limit: 1000,\n overrideAccess,\n })\n\n return new Map(\n result.docs.flatMap((doc) => {\n if (!isRecord(doc)) {\n return []\n }\n\n const id = getRelationshipId(doc)\n\n return id ? [[id, doc]] : []\n }),\n )\n}\n\nconst getGroupRoutePath = ({\n groupId,\n groupsById,\n seen = new Set<string>(),\n}: {\n groupId?: string\n groupsById: Map<string, unknown>\n seen?: Set<string>\n}): string | undefined => {\n if (!groupId || seen.has(groupId)) {\n return undefined\n }\n\n const group = groupsById.get(groupId)\n const resolvedGroup = toResolvedDocsGroup(group)\n\n if (!resolvedGroup?.slug) {\n return undefined\n }\n\n const parentRoutePath = isRecord(group)\n ? getGroupRoutePath({\n groupId: getRelationshipId(group.parent),\n groupsById,\n seen: new Set([groupId, ...seen]),\n })\n : undefined\n\n return joinRouteSegments(parentRoutePath, resolvedGroup.slug)\n}\n\nconst withComputedDocsSetRoute = ({\n doc,\n docsSet,\n groupsById,\n}: {\n doc: unknown\n docsSet?: ResolvedPayloadMarkdownDocsSet\n groupsById: Map<string, unknown>\n}): ResolvedPayloadMarkdownDocsSet | undefined => {\n if (!docsSet?.slug) {\n return docsSet\n }\n\n const groupRoutePath = isRecord(doc)\n ? getGroupRoutePath({\n groupId: getRelationshipId(doc.group),\n groupsById,\n })\n : undefined\n\n return {\n ...docsSet,\n routeBase: deriveDocsSetRouteBase({\n docsSetSlug: docsSet.slug,\n groupRoutePath,\n }),\n }\n}\n\nconst findDocsSetByRouteBase = async ({\n collections,\n overrideAccess,\n payload,\n routeBase,\n}: {\n collections: ResolvedCollectionSlugs\n overrideAccess: boolean\n payload: PayloadMarkdownDocsReadPayload\n routeBase: string\n}): Promise<ResolvedPayloadMarkdownDocsSet | undefined> => {\n const [result, groupsById] = await Promise.all([\n payload.find({\n collection: collections.docsSets,\n depth: 0,\n limit: 1000,\n overrideAccess,\n }),\n getGroupsById({\n collections,\n overrideAccess,\n payload,\n }),\n ])\n\n return result.docs\n .map((doc) =>\n withComputedDocsSetRoute({\n doc,\n docsSet: toResolvedDocsSet(doc),\n groupsById,\n }),\n )\n .find((docsSet) => docsSet?.routeBase === routeBase)\n}\n\nconst findDocsSetByAiExportOutput = async ({\n collections,\n output,\n overrideAccess,\n payload,\n}: {\n collections: ResolvedCollectionSlugs\n output: string\n overrideAccess: boolean\n payload: PayloadMarkdownDocsReadPayload\n}): Promise<ResolvedPayloadMarkdownDocsSet | undefined> => {\n const [result, groupsById] = await Promise.all([\n payload.find({\n collection: collections.docsSets,\n depth: 0,\n limit: 1000,\n overrideAccess,\n }),\n getGroupsById({\n collections,\n overrideAccess,\n payload,\n }),\n ])\n\n return result.docs\n .map((doc) =>\n withComputedDocsSetRoute({\n doc,\n docsSet: toResolvedDocsSet(doc),\n groupsById,\n }),\n )\n .find((docsSet) => docsSet?.aiExport?.output === output)\n}\n\nconst findDocsSetForMarkdownRoute = async ({\n collections,\n overrideAccess,\n payload,\n route,\n}: {\n collections: ResolvedCollectionSlugs\n overrideAccess: boolean\n payload: PayloadMarkdownDocsReadPayload\n route: string\n}): Promise<ResolvedPayloadMarkdownDocsSet | undefined> => {\n const routeBase = stripMarkdownRouteSuffix(route)\n\n if (!routeBase) {\n return undefined\n }\n\n const docsSet = await findDocsSetByRouteBase({\n collections,\n overrideAccess,\n payload,\n routeBase,\n })\n\n return (\n docsSet ??\n findDocsSetByAiExportOutput({\n collections,\n output: route,\n overrideAccess,\n payload,\n })\n )\n}\n\nconst getDocsRecords = async ({\n collections,\n docsSet,\n includeDrafts,\n markdownField,\n overrideAccess,\n payload,\n}: {\n collections: ResolvedCollectionSlugs\n docsSet: ResolvedPayloadMarkdownDocsSet\n includeDrafts: boolean\n markdownField: string\n overrideAccess: boolean\n payload: PayloadMarkdownDocsReadPayload\n}): Promise<ResolvedPayloadMarkdownDocsRecord[]> => {\n const result = await payload.find({\n collection: collections.docs,\n depth: 0,\n limit: 1000,\n overrideAccess,\n where: {\n docsSet: {\n equals: docsSet.id,\n },\n },\n })\n\n return result.docs\n .map((doc) =>\n toResolvedDocsRecord({\n doc,\n markdownField,\n }),\n )\n .filter(\n (record): record is ResolvedPayloadMarkdownDocsRecord =>\n record !== undefined &&\n isVisibleDocsRecord({\n includeDrafts,\n record,\n }),\n )\n}\n\nconst compareDocsRecords = (\n first: ResolvedPayloadMarkdownDocsRecord,\n second: ResolvedPayloadMarkdownDocsRecord,\n): number => {\n if (first.order !== second.order) {\n return first.order - second.order\n }\n\n const titleCompare = first.title.localeCompare(second.title)\n\n if (titleCompare !== 0) {\n return titleCompare\n }\n\n const pathCompare = first.sourcePath.localeCompare(second.sourcePath)\n\n return pathCompare !== 0 ? pathCompare : first.id.localeCompare(second.id)\n}\n\nconst getDefaultAiExportManifest = (\n docsSet: ResolvedPayloadMarkdownDocsSet,\n): DocsAiExportManifest => ({\n canonical: docsSet.routeBase,\n exclude: [],\n headingMode: 'normalize',\n order: [],\n orphans: 'append',\n output: `${docsSet.routeBase}.md`,\n sourcePath: 'fallback',\n title: docsSet.title,\n version: 1,\n})\n\nconst orderDocsRecords = ({\n manifest,\n records,\n}: {\n manifest: DocsAiExportManifest\n records: ResolvedPayloadMarkdownDocsRecord[]\n}): {\n ordered: ResolvedPayloadMarkdownDocsRecord[]\n warnings: DocsValidationIssue[]\n} => {\n const recordsBySourcePath = new Map(records.map((record) => [record.sourcePath, record]))\n const listedRecords: ResolvedPayloadMarkdownDocsRecord[] = []\n const listedSourcePaths = new Set<string>()\n const warnings: DocsValidationIssue[] = []\n\n for (const orderedPath of manifest.order) {\n listedSourcePaths.add(orderedPath)\n const record = recordsBySourcePath.get(orderedPath)\n\n if (!record) {\n warnings.push({\n code: 'missing_ai_export_order_path',\n message: `AI export manifest order path \"${orderedPath}\" does not exist in the generated docs records.`,\n path: manifest.sourcePath,\n })\n continue\n }\n\n listedRecords.push(record)\n }\n\n if (manifest.orphans === 'ignore') {\n return {\n ordered: listedRecords,\n warnings,\n }\n }\n\n const orphans = records\n .filter((record) => !listedSourcePaths.has(record.sourcePath))\n .sort(compareDocsRecords)\n\n return {\n ordered: [...listedRecords, ...orphans],\n warnings,\n }\n}\n\nconst shiftMarkdownHeadings = (markdown: string): string =>\n markdown.replace(/^(#{1,6})(\\s+)/gm, (match, hashes: string, whitespace: string) =>\n hashes.length >= 5 ? `${'#'.repeat(6)}${whitespace}` : `${hashes}##${whitespace}`,\n )\n\nconst sectionTitle = (record: ResolvedPayloadMarkdownDocsRecord): string =>\n record.title.trim() || record.sourcePath\n\nconst renderMarkdownExport = ({\n docsSet,\n manifest,\n records,\n}: {\n docsSet: ResolvedPayloadMarkdownDocsSet\n manifest: DocsAiExportManifest\n records: ResolvedPayloadMarkdownDocsRecord[]\n}): string => {\n const lines: string[] = []\n const title = manifest.title ?? docsSet.title\n const canonical = manifest.canonical ?? docsSet.routeBase\n const output = manifest.output ?? `${docsSet.routeBase}.md`\n\n lines.push(`# ${title}`)\n lines.push('')\n lines.push(`Canonical: ${canonical}`)\n lines.push(`Output: ${output}`)\n\n if (manifest.description) {\n lines.push('', manifest.description.trim())\n }\n\n if (manifest.preamble) {\n lines.push('', manifest.preamble.trim())\n }\n\n for (const record of records) {\n const content = record.content?.trim()\n\n if (!content) {\n continue\n }\n\n if (manifest.headingMode === 'preserve') {\n lines.push('', content)\n continue\n }\n\n lines.push('', `## ${sectionTitle(record)}`, '', shiftMarkdownHeadings(content))\n }\n\n return `${lines.join('\\n').replace(/\\n{4,}/g, '\\n\\n\\n').trimEnd()}\\n`\n}\n\nexport const resolvePayloadMarkdownDocsMarkdownRoute = async ({\n slug,\n collections: collectionOptions,\n includeDrafts = false,\n markdownField = DEFAULT_MARKDOWN_FIELD_NAME,\n // Route adapter reads plugin-owned generated docs collections server-side.\n // Access is overridden here, then public visibility and manifest exclusions are enforced.\n overrideAccess = true,\n path,\n payload,\n}: ResolvePayloadMarkdownDocsMarkdownRouteOptions): Promise<\n null | ResolvedPayloadMarkdownDocsMarkdownRoute\n> => {\n const route = getRoutePath({\n slug,\n path,\n })\n const collections = resolveCollectionSlugs(collectionOptions)\n const docsSet = await findDocsSetForMarkdownRoute({\n collections,\n overrideAccess,\n payload,\n route,\n })\n\n if (!docsSet) {\n return null\n }\n\n const manifest = docsSet.aiExport ?? getDefaultAiExportManifest(docsSet)\n const records = (\n await getDocsRecords({\n collections,\n docsSet,\n includeDrafts,\n markdownField,\n overrideAccess,\n payload,\n })\n ).filter(\n (record) =>\n !isExcludedFromAiExport({\n exclude: manifest.exclude,\n sourcePath: record.sourcePath,\n }),\n )\n const ordered = orderDocsRecords({\n manifest,\n records,\n })\n\n return {\n type: 'markdown',\n contentType: 'text/markdown; charset=utf-8',\n docsSet,\n markdown: renderMarkdownExport({\n docsSet,\n manifest,\n records: ordered.ordered,\n }),\n output: manifest.output ?? `${docsSet.routeBase}.md`,\n route,\n warnings: ordered.warnings,\n }\n}\n\nexport const createPayloadMarkdownDocsMarkdownResponse = async (\n options: ResolvePayloadMarkdownDocsMarkdownRouteOptions,\n): Promise<null | Response> => {\n const resolved = await resolvePayloadMarkdownDocsMarkdownRoute(options)\n\n if (!resolved) {\n return null\n }\n\n return new Response(resolved.markdown, {\n headers: {\n 'Content-Type': resolved.contentType,\n },\n status: 200,\n })\n}\n"],"names":["DEFAULT_DOCS_COLLECTION_SLUG","DEFAULT_DOCS_GROUPS_COLLECTION_SLUG","DEFAULT_DOCS_SETS_COLLECTION_SLUG","DEFAULT_MARKDOWN_FIELD_NAME","deriveDocsSetRouteBase","joinRouteSegments","normalizeRoutePath","isExcludedFromAiExport","getRelationshipId","isRecord","isVisibleDocsRecord","toResolvedDocsGroup","toResolvedDocsRecord","toResolvedDocsSet","resolveCollectionSlugs","collections","docs","docsGroups","docsSets","getRoutePath","slug","path","undefined","Array","isArray","length","join","stripMarkdownRouteSuffix","route","toLowerCase","endsWith","slice","getGroupsById","overrideAccess","payload","result","find","collection","depth","limit","Map","flatMap","doc","id","getGroupRoutePath","groupId","groupsById","seen","Set","has","group","get","resolvedGroup","parentRoutePath","parent","withComputedDocsSetRoute","docsSet","groupRoutePath","routeBase","docsSetSlug","findDocsSetByRouteBase","Promise","all","map","findDocsSetByAiExportOutput","output","aiExport","findDocsSetForMarkdownRoute","getDocsRecords","includeDrafts","markdownField","where","equals","filter","record","compareDocsRecords","first","second","order","titleCompare","title","localeCompare","pathCompare","sourcePath","getDefaultAiExportManifest","canonical","exclude","headingMode","orphans","version","orderDocsRecords","manifest","records","recordsBySourcePath","listedRecords","listedSourcePaths","warnings","orderedPath","add","push","code","message","ordered","sort","shiftMarkdownHeadings","markdown","replace","match","hashes","whitespace","repeat","sectionTitle","trim","renderMarkdownExport","lines","description","preamble","content","trimEnd","resolvePayloadMarkdownDocsMarkdownRoute","collectionOptions","type","contentType","createPayloadMarkdownDocsMarkdownResponse","options","resolved","Response","headers","status"],"mappings":"AAYA,SACEA,4BAA4B,EAC5BC,mCAAmC,EACnCC,iCAAiC,EACjCC,2BAA2B,QACtB,kBAAiB;AACxB,SACEC,sBAAsB,EACtBC,iBAAiB,EACjBC,kBAAkB,QACb,sBAAqB;AAC5B,SACEC,sBAAsB,QACjB,mBAAkB;AACzB,SACEC,iBAAiB,EACjBC,QAAQ,EACRC,mBAAmB,EACnBC,mBAAmB,EACnBC,oBAAoB,EACpBC,iBAAiB,QACZ,eAAc;AAqBrB,MAAMC,yBAAyB,CAC7BC,cAC6B,CAAA;QAC7BC,MAAMD,aAAaC,QAAQhB;QAC3BiB,YAAYF,aAAaE,cAAchB;QACvCiB,UAAUH,aAAaG,YAAYhB;IACrC,CAAA;AAEA,MAAMiB,eAAe,CAAC,EACpBC,IAAI,EACJC,IAAI,EAC0D;IAC9D,IAAIA,SAASC,WAAW;QACtB,OAAOhB,mBAAmBe;IAC5B;IAEA,IAAIE,MAAMC,OAAO,CAACJ,OAAO;QACvB,OAAOd,mBAAmBc,KAAKK,MAAM,KAAK,IAAI,MAAML,KAAKM,IAAI,CAAC;IAChE;IAEA,IAAI,OAAON,SAAS,UAAU;QAC5B,OAAOd,mBAAmBc;IAC5B;IAEA,OAAO;AACT;AAEA,MAAMO,2BAA2B,CAACC,QAChCA,MAAMC,WAAW,GAAGC,QAAQ,CAAC,SAASF,MAAMG,KAAK,CAAC,GAAG,CAAC,KAAKT;AAE7D,MAAMU,gBAAgB,OAAO,EAC3BjB,WAAW,EACXkB,cAAc,EACdC,OAAO,EAKR;IACC,MAAMC,SAAS,MAAMD,QAAQE,IAAI,CAAC;QAChCC,YAAYtB,YAAYE,UAAU;QAClCqB,OAAO;QACPC,OAAO;QACPN;IACF;IAEA,OAAO,IAAIO,IACTL,OAAOnB,IAAI,CAACyB,OAAO,CAAC,CAACC;QACnB,IAAI,CAACjC,SAASiC,MAAM;YAClB,OAAO,EAAE;QACX;QAEA,MAAMC,KAAKnC,kBAAkBkC;QAE7B,OAAOC,KAAK;YAAC;gBAACA;gBAAID;aAAI;SAAC,GAAG,EAAE;IAC9B;AAEJ;AAEA,MAAME,oBAAoB,CAAC,EACzBC,OAAO,EACPC,UAAU,EACVC,OAAO,IAAIC,KAAa,EAKzB;IACC,IAAI,CAACH,WAAWE,KAAKE,GAAG,CAACJ,UAAU;QACjC,OAAOvB;IACT;IAEA,MAAM4B,QAAQJ,WAAWK,GAAG,CAACN;IAC7B,MAAMO,gBAAgBzC,oBAAoBuC;IAE1C,IAAI,CAACE,eAAehC,MAAM;QACxB,OAAOE;IACT;IAEA,MAAM+B,kBAAkB5C,SAASyC,SAC7BN,kBAAkB;QAChBC,SAASrC,kBAAkB0C,MAAMI,MAAM;QACvCR;QACAC,MAAM,IAAIC,IAAI;YAACH;eAAYE;SAAK;IAClC,KACAzB;IAEJ,OAAOjB,kBAAkBgD,iBAAiBD,cAAchC,IAAI;AAC9D;AAEA,MAAMmC,2BAA2B,CAAC,EAChCb,GAAG,EACHc,OAAO,EACPV,UAAU,EAKX;IACC,IAAI,CAACU,SAASpC,MAAM;QAClB,OAAOoC;IACT;IAEA,MAAMC,iBAAiBhD,SAASiC,OAC5BE,kBAAkB;QAChBC,SAASrC,kBAAkBkC,IAAIQ,KAAK;QACpCJ;IACF,KACAxB;IAEJ,OAAO;QACL,GAAGkC,OAAO;QACVE,WAAWtD,uBAAuB;YAChCuD,aAAaH,QAAQpC,IAAI;YACzBqC;QACF;IACF;AACF;AAEA,MAAMG,yBAAyB,OAAO,EACpC7C,WAAW,EACXkB,cAAc,EACdC,OAAO,EACPwB,SAAS,EAMV;IACC,MAAM,CAACvB,QAAQW,WAAW,GAAG,MAAMe,QAAQC,GAAG,CAAC;QAC7C5B,QAAQE,IAAI,CAAC;YACXC,YAAYtB,YAAYG,QAAQ;YAChCoB,OAAO;YACPC,OAAO;YACPN;QACF;QACAD,cAAc;YACZjB;YACAkB;YACAC;QACF;KACD;IAED,OAAOC,OAAOnB,IAAI,CACf+C,GAAG,CAAC,CAACrB,MACJa,yBAAyB;YACvBb;YACAc,SAAS3C,kBAAkB6B;YAC3BI;QACF,IAEDV,IAAI,CAAC,CAACoB,UAAYA,SAASE,cAAcA;AAC9C;AAEA,MAAMM,8BAA8B,OAAO,EACzCjD,WAAW,EACXkD,MAAM,EACNhC,cAAc,EACdC,OAAO,EAMR;IACC,MAAM,CAACC,QAAQW,WAAW,GAAG,MAAMe,QAAQC,GAAG,CAAC;QAC7C5B,QAAQE,IAAI,CAAC;YACXC,YAAYtB,YAAYG,QAAQ;YAChCoB,OAAO;YACPC,OAAO;YACPN;QACF;QACAD,cAAc;YACZjB;YACAkB;YACAC;QACF;KACD;IAED,OAAOC,OAAOnB,IAAI,CACf+C,GAAG,CAAC,CAACrB,MACJa,yBAAyB;YACvBb;YACAc,SAAS3C,kBAAkB6B;YAC3BI;QACF,IAEDV,IAAI,CAAC,CAACoB,UAAYA,SAASU,UAAUD,WAAWA;AACrD;AAEA,MAAME,8BAA8B,OAAO,EACzCpD,WAAW,EACXkB,cAAc,EACdC,OAAO,EACPN,KAAK,EAMN;IACC,MAAM8B,YAAY/B,yBAAyBC;IAE3C,IAAI,CAAC8B,WAAW;QACd,OAAOpC;IACT;IAEA,MAAMkC,UAAU,MAAMI,uBAAuB;QAC3C7C;QACAkB;QACAC;QACAwB;IACF;IAEA,OACEF,WACAQ,4BAA4B;QAC1BjD;QACAkD,QAAQrC;QACRK;QACAC;IACF;AAEJ;AAEA,MAAMkC,iBAAiB,OAAO,EAC5BrD,WAAW,EACXyC,OAAO,EACPa,aAAa,EACbC,aAAa,EACbrC,cAAc,EACdC,OAAO,EAQR;IACC,MAAMC,SAAS,MAAMD,QAAQE,IAAI,CAAC;QAChCC,YAAYtB,YAAYC,IAAI;QAC5BsB,OAAO;QACPC,OAAO;QACPN;QACAsC,OAAO;YACLf,SAAS;gBACPgB,QAAQhB,QAAQb,EAAE;YACpB;QACF;IACF;IAEA,OAAOR,OAAOnB,IAAI,CACf+C,GAAG,CAAC,CAACrB,MACJ9B,qBAAqB;YACnB8B;YACA4B;QACF,IAEDG,MAAM,CACL,CAACC,SACCA,WAAWpD,aACXZ,oBAAoB;YAClB2D;YACAK;QACF;AAER;AAEA,MAAMC,qBAAqB,CACzBC,OACAC;IAEA,IAAID,MAAME,KAAK,KAAKD,OAAOC,KAAK,EAAE;QAChC,OAAOF,MAAME,KAAK,GAAGD,OAAOC,KAAK;IACnC;IAEA,MAAMC,eAAeH,MAAMI,KAAK,CAACC,aAAa,CAACJ,OAAOG,KAAK;IAE3D,IAAID,iBAAiB,GAAG;QACtB,OAAOA;IACT;IAEA,MAAMG,cAAcN,MAAMO,UAAU,CAACF,aAAa,CAACJ,OAAOM,UAAU;IAEpE,OAAOD,gBAAgB,IAAIA,cAAcN,MAAMjC,EAAE,CAACsC,aAAa,CAACJ,OAAOlC,EAAE;AAC3E;AAEA,MAAMyC,6BAA6B,CACjC5B,UAC0B,CAAA;QAC1B6B,WAAW7B,QAAQE,SAAS;QAC5B4B,SAAS,EAAE;QACXC,aAAa;QACbT,OAAO,EAAE;QACTU,SAAS;QACTvB,QAAQ,GAAGT,QAAQE,SAAS,CAAC,GAAG,CAAC;QACjCyB,YAAY;QACZH,OAAOxB,QAAQwB,KAAK;QACpBS,SAAS;IACX,CAAA;AAEA,MAAMC,mBAAmB,CAAC,EACxBC,QAAQ,EACRC,OAAO,EAIR;IAIC,MAAMC,sBAAsB,IAAIrD,IAAIoD,QAAQ7B,GAAG,CAAC,CAACW,SAAW;YAACA,OAAOS,UAAU;YAAET;SAAO;IACvF,MAAMoB,gBAAqD,EAAE;IAC7D,MAAMC,oBAAoB,IAAI/C;IAC9B,MAAMgD,WAAkC,EAAE;IAE1C,KAAK,MAAMC,eAAeN,SAASb,KAAK,CAAE;QACxCiB,kBAAkBG,GAAG,CAACD;QACtB,MAAMvB,SAASmB,oBAAoB1C,GAAG,CAAC8C;QAEvC,IAAI,CAACvB,QAAQ;YACXsB,SAASG,IAAI,CAAC;gBACZC,MAAM;gBACNC,SAAS,CAAC,+BAA+B,EAAEJ,YAAY,+CAA+C,CAAC;gBACvG5E,MAAMsE,SAASR,UAAU;YAC3B;YACA;QACF;QAEAW,cAAcK,IAAI,CAACzB;IACrB;IAEA,IAAIiB,SAASH,OAAO,KAAK,UAAU;QACjC,OAAO;YACLc,SAASR;YACTE;QACF;IACF;IAEA,MAAMR,UAAUI,QACbnB,MAAM,CAAC,CAACC,SAAW,CAACqB,kBAAkB9C,GAAG,CAACyB,OAAOS,UAAU,GAC3DoB,IAAI,CAAC5B;IAER,OAAO;QACL2B,SAAS;eAAIR;eAAkBN;SAAQ;QACvCQ;IACF;AACF;AAEA,MAAMQ,wBAAwB,CAACC,WAC7BA,SAASC,OAAO,CAAC,oBAAoB,CAACC,OAAOC,QAAgBC,aAC3DD,OAAOnF,MAAM,IAAI,IAAI,GAAG,IAAIqF,MAAM,CAAC,KAAKD,YAAY,GAAG,GAAGD,OAAO,EAAE,EAAEC,YAAY;AAGrF,MAAME,eAAe,CAACrC,SACpBA,OAAOM,KAAK,CAACgC,IAAI,MAAMtC,OAAOS,UAAU;AAE1C,MAAM8B,uBAAuB,CAAC,EAC5BzD,OAAO,EACPmC,QAAQ,EACRC,OAAO,EAKR;IACC,MAAMsB,QAAkB,EAAE;IAC1B,MAAMlC,QAAQW,SAASX,KAAK,IAAIxB,QAAQwB,KAAK;IAC7C,MAAMK,YAAYM,SAASN,SAAS,IAAI7B,QAAQE,SAAS;IACzD,MAAMO,SAAS0B,SAAS1B,MAAM,IAAI,GAAGT,QAAQE,SAAS,CAAC,GAAG,CAAC;IAE3DwD,MAAMf,IAAI,CAAC,CAAC,EAAE,EAAEnB,OAAO;IACvBkC,MAAMf,IAAI,CAAC;IACXe,MAAMf,IAAI,CAAC,CAAC,WAAW,EAAEd,WAAW;IACpC6B,MAAMf,IAAI,CAAC,CAAC,QAAQ,EAAElC,QAAQ;IAE9B,IAAI0B,SAASwB,WAAW,EAAE;QACxBD,MAAMf,IAAI,CAAC,IAAIR,SAASwB,WAAW,CAACH,IAAI;IAC1C;IAEA,IAAIrB,SAASyB,QAAQ,EAAE;QACrBF,MAAMf,IAAI,CAAC,IAAIR,SAASyB,QAAQ,CAACJ,IAAI;IACvC;IAEA,KAAK,MAAMtC,UAAUkB,QAAS;QAC5B,MAAMyB,UAAU3C,OAAO2C,OAAO,EAAEL;QAEhC,IAAI,CAACK,SAAS;YACZ;QACF;QAEA,IAAI1B,SAASJ,WAAW,KAAK,YAAY;YACvC2B,MAAMf,IAAI,CAAC,IAAIkB;YACf;QACF;QAEAH,MAAMf,IAAI,CAAC,IAAI,CAAC,GAAG,EAAEY,aAAarC,SAAS,EAAE,IAAI8B,sBAAsBa;IACzE;IAEA,OAAO,GAAGH,MAAMxF,IAAI,CAAC,MAAMgF,OAAO,CAAC,WAAW,UAAUY,OAAO,GAAG,EAAE,CAAC;AACvE;AAEA,OAAO,MAAMC,0CAA0C,OAAO,EAC5DnG,IAAI,EACJL,aAAayG,iBAAiB,EAC9BnD,gBAAgB,KAAK,EACrBC,gBAAgBnE,2BAA2B,EAC3C,2EAA2E;AAC3E,0FAA0F;AAC1F8B,iBAAiB,IAAI,EACrBZ,IAAI,EACJa,OAAO,EACwC;IAG/C,MAAMN,QAAQT,aAAa;QACzBC;QACAC;IACF;IACA,MAAMN,cAAcD,uBAAuB0G;IAC3C,MAAMhE,UAAU,MAAMW,4BAA4B;QAChDpD;QACAkB;QACAC;QACAN;IACF;IAEA,IAAI,CAAC4B,SAAS;QACZ,OAAO;IACT;IAEA,MAAMmC,WAAWnC,QAAQU,QAAQ,IAAIkB,2BAA2B5B;IAChE,MAAMoC,UAAU,AACd,CAAA,MAAMxB,eAAe;QACnBrD;QACAyC;QACAa;QACAC;QACArC;QACAC;IACF,EAAC,EACDuC,MAAM,CACN,CAACC,SACC,CAACnE,uBAAuB;YACtB+E,SAASK,SAASL,OAAO;YACzBH,YAAYT,OAAOS,UAAU;QAC/B;IAEJ,MAAMmB,UAAUZ,iBAAiB;QAC/BC;QACAC;IACF;IAEA,OAAO;QACL6B,MAAM;QACNC,aAAa;QACblE;QACAiD,UAAUQ,qBAAqB;YAC7BzD;YACAmC;YACAC,SAASU,QAAQA,OAAO;QAC1B;QACArC,QAAQ0B,SAAS1B,MAAM,IAAI,GAAGT,QAAQE,SAAS,CAAC,GAAG,CAAC;QACpD9B;QACAoE,UAAUM,QAAQN,QAAQ;IAC5B;AACF,EAAC;AAED,OAAO,MAAM2B,4CAA4C,OACvDC;IAEA,MAAMC,WAAW,MAAMN,wCAAwCK;IAE/D,IAAI,CAACC,UAAU;QACb,OAAO;IACT;IAEA,OAAO,IAAIC,SAASD,SAASpB,QAAQ,EAAE;QACrCsB,SAAS;YACP,gBAAgBF,SAASH,WAAW;QACtC;QACAM,QAAQ;IACV;AACF,EAAC"}
1
+ {"version":3,"sources":["../../src/next/markdown.ts"],"sourcesContent":["import type { DocsAiExportManifest, DocsValidationIssue } from '../sync/index.js'\nimport type {\n PayloadMarkdownDocsCollectionSlugs,\n PayloadMarkdownDocsReadPayload,\n ResolvedPayloadMarkdownDocsRecord,\n ResolvedPayloadMarkdownDocsSet,\n ResolvePayloadMarkdownDocsRouteOptions,\n} from './types.js'\n\nimport {\n DEFAULT_DOCS_COLLECTION_SLUG,\n DEFAULT_DOCS_GROUPS_COLLECTION_SLUG,\n DEFAULT_DOCS_SETS_COLLECTION_SLUG,\n DEFAULT_MARKDOWN_FIELD_NAME,\n} from '../constants.js'\nimport { deriveDocsSetRouteBase, joinRouteSegments, normalizeRoutePath } from '../routing/index.js'\nimport { isExcludedFromAiExport } from '../sync/index.js'\nimport {\n getRelationshipId,\n isRecord,\n isVisibleDocsRecord,\n isVisibleDocsSet,\n toResolvedDocsGroup,\n toResolvedDocsRecord,\n toResolvedDocsSet,\n} from './records.js'\n\nexport type ResolvedPayloadMarkdownDocsMarkdownRoute = {\n contentType: 'text/markdown; charset=utf-8'\n docsSet: ResolvedPayloadMarkdownDocsSet\n markdown: string\n output: string\n route: string\n type: 'markdown'\n warnings: DocsValidationIssue[]\n}\n\nexport type ResolvePayloadMarkdownDocsMarkdownRouteOptions = ResolvePayloadMarkdownDocsRouteOptions\n\ntype ResolvedCollectionSlugs = {\n docs: string\n docsGroups: string\n docsSets: string\n}\n\nconst resolveCollectionSlugs = (\n collections?: PayloadMarkdownDocsCollectionSlugs,\n): ResolvedCollectionSlugs => ({\n docs: collections?.docs ?? DEFAULT_DOCS_COLLECTION_SLUG,\n docsGroups: collections?.docsGroups ?? DEFAULT_DOCS_GROUPS_COLLECTION_SLUG,\n docsSets: collections?.docsSets ?? DEFAULT_DOCS_SETS_COLLECTION_SLUG,\n})\n\nconst getRoutePath = ({\n slug,\n path,\n}: Pick<ResolvePayloadMarkdownDocsRouteOptions, 'path' | 'slug'>): string => {\n if (path !== undefined) {\n return normalizeRoutePath(path)\n }\n\n if (Array.isArray(slug)) {\n return normalizeRoutePath(slug.length === 0 ? '/' : slug.join('/'))\n }\n\n if (typeof slug === 'string') {\n return normalizeRoutePath(slug)\n }\n\n return '/'\n}\n\nconst stripMarkdownRouteSuffix = (route: string): string | undefined =>\n route.toLowerCase().endsWith('.md') ? route.slice(0, -3) : undefined\n\nconst getGroupsById = async ({\n collections,\n overrideAccess,\n payload,\n}: {\n collections: ResolvedCollectionSlugs\n overrideAccess: boolean\n payload: PayloadMarkdownDocsReadPayload\n}): Promise<Map<string, unknown>> => {\n const result = await payload.find({\n collection: collections.docsGroups,\n depth: 0,\n limit: 1000,\n overrideAccess,\n })\n\n return new Map(\n result.docs.flatMap((doc) => {\n if (!isRecord(doc)) {\n return []\n }\n\n const id = getRelationshipId(doc)\n\n return id ? [[id, doc]] : []\n }),\n )\n}\n\nconst getGroupRoutePath = ({\n groupId,\n groupsById,\n seen = new Set<string>(),\n}: {\n groupId?: string\n groupsById: Map<string, unknown>\n seen?: Set<string>\n}): string | undefined => {\n if (!groupId || seen.has(groupId)) {\n return undefined\n }\n\n const group = groupsById.get(groupId)\n const resolvedGroup = toResolvedDocsGroup(group)\n\n if (!resolvedGroup?.slug) {\n return undefined\n }\n\n const parentRoutePath = isRecord(group)\n ? getGroupRoutePath({\n groupId: getRelationshipId(group.parent),\n groupsById,\n seen: new Set([groupId, ...seen]),\n })\n : undefined\n\n return joinRouteSegments(parentRoutePath, resolvedGroup.slug)\n}\n\nconst withComputedDocsSetRoute = ({\n doc,\n docsSet,\n groupsById,\n}: {\n doc: unknown\n docsSet?: ResolvedPayloadMarkdownDocsSet\n groupsById: Map<string, unknown>\n}): ResolvedPayloadMarkdownDocsSet | undefined => {\n if (!docsSet?.slug) {\n return docsSet\n }\n\n const groupRoutePath = isRecord(doc)\n ? getGroupRoutePath({\n groupId: getRelationshipId(doc.group),\n groupsById,\n })\n : undefined\n\n return {\n ...docsSet,\n routeBase: deriveDocsSetRouteBase({\n docsSetSlug: docsSet.slug,\n groupRoutePath,\n }),\n }\n}\n\nconst findDocsSetByRouteBase = async ({\n collections,\n includeDrafts,\n overrideAccess,\n payload,\n routeBase,\n}: {\n collections: ResolvedCollectionSlugs\n includeDrafts: boolean\n overrideAccess: boolean\n payload: PayloadMarkdownDocsReadPayload\n routeBase: string\n}): Promise<ResolvedPayloadMarkdownDocsSet | undefined> => {\n const [result, groupsById] = await Promise.all([\n payload.find({\n collection: collections.docsSets,\n depth: 0,\n draft: includeDrafts,\n limit: 1000,\n overrideAccess,\n }),\n getGroupsById({\n collections,\n overrideAccess,\n payload,\n }),\n ])\n\n return result.docs\n .map((doc) =>\n withComputedDocsSetRoute({\n doc,\n docsSet: toResolvedDocsSet(doc),\n groupsById,\n }),\n )\n .find(\n (docsSet) => docsSet?.routeBase === routeBase && isVisibleDocsSet({ docsSet, includeDrafts }),\n )\n}\n\nconst findDocsSetByAiExportOutput = async ({\n collections,\n includeDrafts,\n output,\n overrideAccess,\n payload,\n}: {\n collections: ResolvedCollectionSlugs\n includeDrafts: boolean\n output: string\n overrideAccess: boolean\n payload: PayloadMarkdownDocsReadPayload\n}): Promise<ResolvedPayloadMarkdownDocsSet | undefined> => {\n const [result, groupsById] = await Promise.all([\n payload.find({\n collection: collections.docsSets,\n depth: 0,\n draft: includeDrafts,\n limit: 1000,\n overrideAccess,\n }),\n getGroupsById({\n collections,\n overrideAccess,\n payload,\n }),\n ])\n\n return result.docs\n .map((doc) =>\n withComputedDocsSetRoute({\n doc,\n docsSet: toResolvedDocsSet(doc),\n groupsById,\n }),\n )\n .find(\n (docsSet) =>\n docsSet?.aiExport?.output === output && isVisibleDocsSet({ docsSet, includeDrafts }),\n )\n}\n\nconst findDocsSetForMarkdownRoute = async ({\n collections,\n includeDrafts,\n overrideAccess,\n payload,\n route,\n}: {\n collections: ResolvedCollectionSlugs\n includeDrafts: boolean\n overrideAccess: boolean\n payload: PayloadMarkdownDocsReadPayload\n route: string\n}): Promise<ResolvedPayloadMarkdownDocsSet | undefined> => {\n const routeBase = stripMarkdownRouteSuffix(route)\n\n if (!routeBase) {\n return undefined\n }\n\n const docsSet = await findDocsSetByRouteBase({\n collections,\n includeDrafts,\n overrideAccess,\n payload,\n routeBase,\n })\n\n return (\n docsSet ??\n findDocsSetByAiExportOutput({\n collections,\n includeDrafts,\n output: route,\n overrideAccess,\n payload,\n })\n )\n}\n\nconst getDocsRecords = async ({\n collections,\n docsSet,\n includeDrafts,\n markdownField,\n overrideAccess,\n payload,\n}: {\n collections: ResolvedCollectionSlugs\n docsSet: ResolvedPayloadMarkdownDocsSet\n includeDrafts: boolean\n markdownField: string\n overrideAccess: boolean\n payload: PayloadMarkdownDocsReadPayload\n}): Promise<ResolvedPayloadMarkdownDocsRecord[]> => {\n const result = await payload.find({\n collection: collections.docs,\n depth: 0,\n draft: includeDrafts,\n limit: 1000,\n overrideAccess,\n where: {\n docsSet: {\n equals: docsSet.id,\n },\n },\n })\n\n return result.docs\n .map((doc) =>\n toResolvedDocsRecord({\n doc,\n markdownField,\n }),\n )\n .filter(\n (record): record is ResolvedPayloadMarkdownDocsRecord =>\n record !== undefined &&\n isVisibleDocsRecord({\n includeDrafts,\n record,\n }),\n )\n}\n\nconst compareDocsRecords = (\n first: ResolvedPayloadMarkdownDocsRecord,\n second: ResolvedPayloadMarkdownDocsRecord,\n): number => {\n if (first.order !== second.order) {\n return first.order - second.order\n }\n\n const titleCompare = first.title.localeCompare(second.title)\n\n if (titleCompare !== 0) {\n return titleCompare\n }\n\n const pathCompare = first.sourcePath.localeCompare(second.sourcePath)\n\n return pathCompare !== 0 ? pathCompare : first.id.localeCompare(second.id)\n}\n\nconst getDefaultAiExportManifest = (\n docsSet: ResolvedPayloadMarkdownDocsSet,\n): DocsAiExportManifest => ({\n canonical: docsSet.routeBase,\n exclude: [],\n headingMode: 'normalize',\n order: [],\n orphans: 'append',\n output: `${docsSet.routeBase}.md`,\n sourcePath: 'fallback',\n title: docsSet.title,\n version: 1,\n})\n\nconst orderDocsRecords = ({\n manifest,\n records,\n}: {\n manifest: DocsAiExportManifest\n records: ResolvedPayloadMarkdownDocsRecord[]\n}): {\n ordered: ResolvedPayloadMarkdownDocsRecord[]\n warnings: DocsValidationIssue[]\n} => {\n const recordsBySourcePath = new Map(records.map((record) => [record.sourcePath, record]))\n const listedRecords: ResolvedPayloadMarkdownDocsRecord[] = []\n const listedSourcePaths = new Set<string>()\n const warnings: DocsValidationIssue[] = []\n\n for (const orderedPath of manifest.order) {\n listedSourcePaths.add(orderedPath)\n const record = recordsBySourcePath.get(orderedPath)\n\n if (!record) {\n warnings.push({\n code: 'missing_ai_export_order_path',\n message: `AI export manifest order path \"${orderedPath}\" does not exist in the generated docs records.`,\n path: manifest.sourcePath,\n })\n continue\n }\n\n listedRecords.push(record)\n }\n\n if (manifest.orphans === 'ignore') {\n return {\n ordered: listedRecords,\n warnings,\n }\n }\n\n const orphans = records\n .filter((record) => !listedSourcePaths.has(record.sourcePath))\n .sort(compareDocsRecords)\n\n return {\n ordered: [...listedRecords, ...orphans],\n warnings,\n }\n}\n\nconst shiftMarkdownHeadings = (markdown: string): string =>\n markdown.replace(/^(#{1,6})(\\s+)/gm, (match, hashes: string, whitespace: string) =>\n hashes.length >= 5 ? `${'#'.repeat(6)}${whitespace}` : `${hashes}##${whitespace}`,\n )\n\nconst sectionTitle = (record: ResolvedPayloadMarkdownDocsRecord): string =>\n record.title.trim() || record.sourcePath\n\nconst renderMarkdownExport = ({\n docsSet,\n manifest,\n records,\n}: {\n docsSet: ResolvedPayloadMarkdownDocsSet\n manifest: DocsAiExportManifest\n records: ResolvedPayloadMarkdownDocsRecord[]\n}): string => {\n const lines: string[] = []\n const title = manifest.title ?? docsSet.title\n const canonical = manifest.canonical ?? docsSet.routeBase\n const output = manifest.output ?? `${docsSet.routeBase}.md`\n\n lines.push(`# ${title}`)\n lines.push('')\n lines.push(`Canonical: ${canonical}`)\n lines.push(`Output: ${output}`)\n\n if (manifest.description) {\n lines.push('', manifest.description.trim())\n }\n\n if (manifest.preamble) {\n lines.push('', manifest.preamble.trim())\n }\n\n for (const record of records) {\n const content = record.content?.trim()\n\n if (!content) {\n continue\n }\n\n if (manifest.headingMode === 'preserve') {\n lines.push('', content)\n continue\n }\n\n lines.push('', `## ${sectionTitle(record)}`, '', shiftMarkdownHeadings(content))\n }\n\n return `${lines\n .join('\\n')\n .replace(/\\n{4,}/g, '\\n\\n\\n')\n .trimEnd()}\\n`\n}\n\nexport const resolvePayloadMarkdownDocsMarkdownRoute = async ({\n slug,\n collections: collectionOptions,\n includeDrafts = false,\n markdownField = DEFAULT_MARKDOWN_FIELD_NAME,\n // Route adapter reads plugin-owned generated docs collections server-side.\n // Access is overridden here, then public visibility and manifest exclusions are enforced.\n overrideAccess = true,\n path,\n payload,\n}: ResolvePayloadMarkdownDocsMarkdownRouteOptions): Promise<null | ResolvedPayloadMarkdownDocsMarkdownRoute> => {\n const route = getRoutePath({\n slug,\n path,\n })\n const collections = resolveCollectionSlugs(collectionOptions)\n const docsSet = await findDocsSetForMarkdownRoute({\n collections,\n includeDrafts,\n overrideAccess,\n payload,\n route,\n })\n\n if (!docsSet) {\n return null\n }\n\n const manifest = docsSet.aiExport ?? getDefaultAiExportManifest(docsSet)\n const records = (\n await getDocsRecords({\n collections,\n docsSet,\n includeDrafts,\n markdownField,\n overrideAccess,\n payload,\n })\n ).filter(\n (record) =>\n !isExcludedFromAiExport({\n exclude: manifest.exclude,\n sourcePath: record.sourcePath,\n }),\n )\n const ordered = orderDocsRecords({\n manifest,\n records,\n })\n\n return {\n type: 'markdown',\n contentType: 'text/markdown; charset=utf-8',\n docsSet,\n markdown: renderMarkdownExport({\n docsSet,\n manifest,\n records: ordered.ordered,\n }),\n output: manifest.output ?? `${docsSet.routeBase}.md`,\n route,\n warnings: ordered.warnings,\n }\n}\n\nexport const createPayloadMarkdownDocsMarkdownResponse = async (\n options: ResolvePayloadMarkdownDocsMarkdownRouteOptions,\n): Promise<null | Response> => {\n const resolved = await resolvePayloadMarkdownDocsMarkdownRoute(options)\n\n if (!resolved) {\n return null\n }\n\n return new Response(resolved.markdown, {\n headers: {\n 'Content-Type': resolved.contentType,\n },\n status: 200,\n })\n}\n"],"names":["DEFAULT_DOCS_COLLECTION_SLUG","DEFAULT_DOCS_GROUPS_COLLECTION_SLUG","DEFAULT_DOCS_SETS_COLLECTION_SLUG","DEFAULT_MARKDOWN_FIELD_NAME","deriveDocsSetRouteBase","joinRouteSegments","normalizeRoutePath","isExcludedFromAiExport","getRelationshipId","isRecord","isVisibleDocsRecord","isVisibleDocsSet","toResolvedDocsGroup","toResolvedDocsRecord","toResolvedDocsSet","resolveCollectionSlugs","collections","docs","docsGroups","docsSets","getRoutePath","slug","path","undefined","Array","isArray","length","join","stripMarkdownRouteSuffix","route","toLowerCase","endsWith","slice","getGroupsById","overrideAccess","payload","result","find","collection","depth","limit","Map","flatMap","doc","id","getGroupRoutePath","groupId","groupsById","seen","Set","has","group","get","resolvedGroup","parentRoutePath","parent","withComputedDocsSetRoute","docsSet","groupRoutePath","routeBase","docsSetSlug","findDocsSetByRouteBase","includeDrafts","Promise","all","draft","map","findDocsSetByAiExportOutput","output","aiExport","findDocsSetForMarkdownRoute","getDocsRecords","markdownField","where","equals","filter","record","compareDocsRecords","first","second","order","titleCompare","title","localeCompare","pathCompare","sourcePath","getDefaultAiExportManifest","canonical","exclude","headingMode","orphans","version","orderDocsRecords","manifest","records","recordsBySourcePath","listedRecords","listedSourcePaths","warnings","orderedPath","add","push","code","message","ordered","sort","shiftMarkdownHeadings","markdown","replace","match","hashes","whitespace","repeat","sectionTitle","trim","renderMarkdownExport","lines","description","preamble","content","trimEnd","resolvePayloadMarkdownDocsMarkdownRoute","collectionOptions","type","contentType","createPayloadMarkdownDocsMarkdownResponse","options","resolved","Response","headers","status"],"mappings":"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"}