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