@valkyrianlabs/payload-markdown-docs 0.5.1 → 0.5.3
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/endpoints/sync.js +4 -0
- package/dist/endpoints/sync.js.map +1 -1
- package/dist/next/PayloadMarkdownDocsPage.js +11 -4
- package/dist/next/PayloadMarkdownDocsPage.js.map +1 -1
- package/dist/next/links.js +5 -2
- package/dist/next/links.js.map +1 -1
- package/dist/next/markdown.js +18 -6
- package/dist/next/markdown.js.map +1 -1
- package/dist/next/route.js +5 -0
- package/dist/next/route.js.map +1 -1
- package/dist/next/sidebar.js +20 -9
- package/dist/next/sidebar.js.map +1 -1
- package/dist/next/types.d.ts +2 -1
- package/dist/next/types.js.map +1 -1
- package/dist/payload/applyDocsSync.d.ts +2 -0
- package/dist/payload/applyDocsSync.js +14 -0
- package/dist/payload/applyDocsSync.js.map +1 -1
- package/dist/payload/docsSets.d.ts +6 -2
- package/dist/payload/docsSets.js +5 -2
- package/dist/payload/docsSets.js.map +1 -1
- package/dist/payload/existingDocs.d.ts +5 -2
- package/dist/payload/existingDocs.js +5 -2
- package/dist/payload/existingDocs.js.map +1 -1
- package/dist/payload/routeCollisions.d.ts +3 -1
- package/dist/payload/routeCollisions.js +2 -1
- package/dist/payload/routeCollisions.js.map +1 -1
- package/dist/sync/plan.d.ts +1 -0
- package/dist/sync/plan.js +4 -2
- package/dist/sync/plan.js.map +1 -1
- package/package.json +1 -1
package/dist/endpoints/sync.js
CHANGED
|
@@ -33,6 +33,7 @@ const resolveSyncSource = async ({ manifest, options, payload })=>{
|
|
|
33
33
|
slug: sourceId,
|
|
34
34
|
collectionSlug: options.docsSetsCollectionSlug,
|
|
35
35
|
docsGroupsCollectionSlug: options.docsGroupsCollectionSlug,
|
|
36
|
+
includeDrafts: true,
|
|
36
37
|
payload
|
|
37
38
|
}) : undefined;
|
|
38
39
|
if (docsSet) {
|
|
@@ -119,6 +120,7 @@ const getRouteCollisionIssues = async ({ docsSet, manifest, options, payload, ro
|
|
|
119
120
|
const existingDocsRouteCollisions = options.docsEnabled ? await findExistingDocsRouteCollisions({
|
|
120
121
|
collectionSlug: options.docsCollectionSlug,
|
|
121
122
|
docsSetId: docsSet?.id,
|
|
123
|
+
includeDrafts: options.docsEnableDrafts,
|
|
122
124
|
payload,
|
|
123
125
|
routes: desiredRoutes,
|
|
124
126
|
sourceId: manifest.source.id
|
|
@@ -466,6 +468,7 @@ const createSyncEndpointHandler = (options)=>async (req)=>{
|
|
|
466
468
|
const existingPayloadDocs = options.docsEnabled ? await findExistingPayloadDocsRecords({
|
|
467
469
|
collectionSlug: options.docsCollectionSlug,
|
|
468
470
|
docsSetId: sourceResolution.source.docsSet?.id,
|
|
471
|
+
draft: options.docsEnableDrafts,
|
|
469
472
|
markdownFieldName: options.markdownFieldName,
|
|
470
473
|
payload: req.payload,
|
|
471
474
|
sourceId: validation.data.source.id
|
|
@@ -576,6 +579,7 @@ const createSyncEndpointHandler = (options)=>async (req)=>{
|
|
|
576
579
|
docsSetId: sourceResolution.source.docsSet.id,
|
|
577
580
|
now: options.getNow?.() ?? new Date(),
|
|
578
581
|
payload: req.payload,
|
|
582
|
+
publish: validation.data.publish,
|
|
579
583
|
syncRunId
|
|
580
584
|
});
|
|
581
585
|
}
|
|
@@ -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 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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"}
|
|
1
|
+
{"version":3,"sources":["../../src/endpoints/sync.ts"],"sourcesContent":["import type { Endpoint, PayloadRequest } from 'payload'\n\nimport type {\n ApplyDocsSyncPayloadOperations,\n DocsKeyPayloadOperations,\n DocsSetPayloadOperations,\n DocsTrustedPayloadOperations,\n ExistingDocsPayloadOperations,\n ExistingPayloadDocsRecord,\n ResolvedDocsSet,\n RouteCollisionPayloadOperations,\n SyncRunsPayloadOperations,\n} from '../payload/index.js'\nimport type { FetchJson, NoncePayloadOperations } from '../security/index.js'\nimport type {\n DocsDeleteBehavior,\n DocsManifest,\n DocsValidationIssue,\n PlannedDocChange,\n ValidatedDocsManifest,\n} from '../sync/index.js'\nimport type { PayloadMarkdownDocsAuthConfig } from '../types.js'\n\nimport {\n DEFAULT_MAX_BODY_BYTES,\n DEFAULT_MAX_SKEW_SECONDS,\n DEFAULT_NONCE_TTL_SECONDS,\n} from '../constants.js'\nimport {\n applyDocsSync,\n assertApplyDeleteBehaviorSupported,\n createSyncRunAudit,\n findConfiguredPagesRouteCollisions,\n findDocsKeyById,\n findDocsSetBySlug,\n findDocsSyncConflicts,\n findDuplicateDesiredRouteCollisions,\n findExistingDocsRouteCollisions,\n findExistingPayloadDocsRecords,\n findTrustedGitHubSources,\n getRecordId,\n isEd25519AuthEnabled,\n isGitHubOidcAuthEnabled,\n toExistingDocsRecord,\n updateDocsSetAfterSync,\n updateSyncRunAudit,\n} from '../payload/index.js'\nimport {\n assertNonceNotReplayed,\n buildCanonicalSigningString,\n extractSyncRequestHeaders,\n getCanonicalPathFromRequestUrl,\n storeAcceptedNonce,\n validateTimestampSkew,\n verifyBodySha256,\n verifyEd25519Signature,\n verifyGitHubOidcToken,\n} from '../security/index.js'\nimport { planDocsSync, validateDocsManifest } from '../sync/index.js'\n\nexport type DocsSyncEndpointErrorCode =\n | 'audit_unavailable'\n | 'auth_disabled'\n | 'body_hash_mismatch'\n | 'delete_behavior_not_implemented'\n | 'draft_behavior_not_available'\n | 'dry_run_required_not_implemented'\n | 'hard_delete_disabled'\n | 'invalid_body'\n | 'invalid_manifest'\n | 'invalid_method'\n | 'invalid_signature'\n | 'invalid_timestamp'\n | 'manual_edit_conflict'\n | 'missing_header'\n | 'nonce_replay'\n | 'oidc_expired'\n | 'oidc_invalid_audience'\n | 'oidc_invalid_issuer'\n | 'oidc_invalid_token'\n | 'oidc_jwks_unavailable'\n | 'oidc_missing_claim'\n | 'oidc_missing_jti'\n | 'oidc_not_yet_valid'\n | 'oidc_owner_not_allowed'\n | 'oidc_pull_request_not_allowed'\n | 'oidc_ref_not_allowed'\n | 'oidc_replay'\n | 'oidc_repository_not_allowed'\n | 'oidc_workflow_not_allowed'\n | 'publish_disabled'\n | 'publish_not_available'\n | 'replay_protection_unavailable'\n | 'route_collision'\n | 'source_not_allowed'\n | 'sync_apply_failed'\n | 'sync_mode_not_implemented'\n | 'sync_writes_disabled'\n | 'unknown_key'\n\nexport type CreateSyncEndpointOptions = {\n allowHardDelete?: boolean\n allowPublish?: boolean\n allowWrites?: boolean\n auth?: PayloadMarkdownDocsAuthConfig\n deleteBehavior?: DocsDeleteBehavior\n docsCollectionSlug: string\n docsEnabled: boolean\n docsEnableDrafts: boolean\n docsGroupsCollectionSlug: string\n docsKeysCollectionSlug: string\n docsKeysEnabled: boolean\n docsSetsCollectionSlug: string\n docsSetsEnabled: boolean\n docsTrustedCollectionSlug: string\n docsTrustedEnabled: boolean\n endpointPath: string\n getNow?: () => Date\n markdownFieldName: string\n maxBodyBytes?: number\n maxSkewSeconds?: number\n noncesCollectionSlug: string\n noncesEnabled: boolean\n nonceTtlSeconds?: number\n oidcFetchJson?: FetchJson\n requireDryRunBeforeApply?: boolean\n routing?: {\n pages?: {\n allowBridgePages: boolean\n bridgeField: string\n collection: string\n enabled: boolean\n routeField: string\n }\n }\n syncRunsCollectionSlug: string\n syncRunsEnabled: boolean\n}\n\ntype SyncErrorResponse = {\n conflicts?: {\n reason: string\n route?: string\n sourcePath: string\n }[]\n error: {\n code: DocsSyncEndpointErrorCode\n message: string\n }\n ok: false\n routeCollisions?: {\n reason: string\n route: string\n }[]\n}\n\ntype SerializedChange = {\n current?: {\n archived?: boolean\n route: string\n sourceHash?: string\n title?: string\n }\n desired?: {\n route: string\n sha256: string\n title: string\n }\n reason: string\n sourcePath: string\n}\n\ntype SyncSuccessResponse = {\n changes: {\n archive: SerializedChange[]\n create: SerializedChange[]\n delete: SerializedChange[]\n draft: SerializedChange[]\n unchanged: SerializedChange[]\n update: SerializedChange[]\n }\n deleteBehavior: DocsDeleteBehavior\n dryRun: boolean\n ok: true\n publishRequested: boolean\n summary: {\n archive: number\n create: number\n delete: number\n draft: number\n unchanged: number\n update: number\n warnings: number\n }\n syncRunId?: string\n warnings: DocsValidationIssue[]\n}\n\nconst jsonResponse = (body: SyncErrorResponse | SyncSuccessResponse, status = 200): Response =>\n Response.json(body, {\n status,\n })\n\nconst errorResponse = (\n code: DocsSyncEndpointErrorCode,\n message: string,\n status = 400,\n extras: Omit<SyncErrorResponse, 'error' | 'ok'> = {},\n): Response =>\n jsonResponse(\n {\n ...extras,\n error: {\n code,\n message,\n },\n ok: false,\n },\n status,\n )\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === 'object' && value !== null && !Array.isArray(value)\n\nconst parseManifestBody = (rawBody: string): DocsManifest | undefined => {\n try {\n const parsed = JSON.parse(rawBody) as unknown\n\n return isRecord(parsed) ? (parsed as DocsManifest) : undefined\n } catch {\n return undefined\n }\n}\n\ntype ResolvedSyncSource = {\n docsSet: ResolvedDocsSet\n routeBase: string\n sourceId: string\n}\n\nconst resolveSyncSource = async ({\n manifest,\n options,\n payload,\n}: {\n manifest: DocsManifest\n options: CreateSyncEndpointOptions\n payload: DocsSetPayloadOperations\n}): Promise<\n | {\n response: Response\n source?: never\n }\n | {\n response?: never\n source: ResolvedSyncSource\n }\n> => {\n const sourceId = manifest.source?.id\n\n if (!sourceId) {\n return {\n response: errorResponse(\n 'source_not_allowed',\n 'Manifest source.id is required and must match a docs set slug.',\n 400,\n ),\n }\n }\n\n const docsSet = options.docsSetsEnabled\n ? await findDocsSetBySlug({\n slug: sourceId,\n collectionSlug: options.docsSetsCollectionSlug,\n docsGroupsCollectionSlug: options.docsGroupsCollectionSlug,\n includeDrafts: true,\n payload,\n })\n : undefined\n\n if (docsSet) {\n return {\n source: {\n docsSet,\n routeBase: docsSet.routeBase,\n sourceId,\n },\n }\n }\n\n return {\n response: errorResponse(\n 'source_not_allowed',\n `No docs set exists for source \"${sourceId}\". Create a docs set with slug \"${sourceId}\" in Payload Admin before syncing this source.`,\n 400,\n ),\n }\n}\n\nconst summarizePlan = (plan: ReturnType<typeof planDocsSync>) => ({\n archive: plan.archive.length,\n create: plan.create.length,\n delete: plan.delete.length,\n draft: plan.draft.length,\n unchanged: plan.unchanged.length,\n update: plan.update.length,\n warnings: plan.warnings.length,\n})\n\nconst serializeChange = (change: PlannedDocChange): SerializedChange => ({\n current: change.current\n ? {\n archived: change.current.archived,\n route: change.current.route,\n sourceHash: change.current.sourceHash,\n title: change.current.title,\n }\n : undefined,\n desired: change.desired\n ? {\n route: change.desired.route,\n sha256: change.desired.sha256,\n title: change.desired.title,\n }\n : undefined,\n reason: change.reason,\n sourcePath: change.sourcePath,\n})\n\nconst serializeChanges = (plan: ReturnType<typeof planDocsSync>) => ({\n archive: plan.archive.map(serializeChange),\n create: plan.create.map(serializeChange),\n delete: plan.delete.map(serializeChange),\n draft: plan.draft.map(serializeChange),\n unchanged: plan.unchanged.map(serializeChange),\n update: plan.update.map(serializeChange),\n})\n\nconst getTotalManifestBytes = (manifest: ValidatedDocsManifest): number =>\n manifest.files.reduce((total, file) => total + Buffer.byteLength(file.content, 'utf8'), 0)\n\nconst getPlannedConflictChanges = ({\n existing,\n plan,\n}: {\n existing: ExistingPayloadDocsRecord[]\n plan: ReturnType<typeof planDocsSync>\n}): PlannedDocChange[] => {\n const existingBySourcePath = new Map(existing.map((record) => [record.sourcePath, record]))\n const archivedUnchanged = plan.unchanged.filter((change) => {\n const current = existingBySourcePath.get(change.sourcePath)\n\n return current?.archived === true\n })\n\n return [...plan.update, ...plan.archive, ...plan.draft, ...plan.delete, ...archivedUnchanged]\n}\n\nconst getLifecyclePolicyError = ({\n deleteBehavior,\n manifest,\n options,\n}: {\n deleteBehavior: DocsDeleteBehavior\n manifest: ValidatedDocsManifest\n options: CreateSyncEndpointOptions\n}): Response | undefined => {\n if (manifest.publish && options.allowPublish !== true) {\n return errorResponse('publish_disabled', 'Publishing is disabled by server configuration.', 403)\n }\n\n if (manifest.publish && !options.docsEnableDrafts) {\n return errorResponse(\n 'publish_not_available',\n 'Publishing requires a draft-enabled dedicated docs collection.',\n 400,\n )\n }\n\n if (deleteBehavior === 'draft' && !options.docsEnableDrafts) {\n return errorResponse(\n 'draft_behavior_not_available',\n 'Draft delete behavior requires a draft-enabled dedicated docs collection.',\n 400,\n )\n }\n\n if (deleteBehavior === 'delete' && options.allowHardDelete !== true) {\n return errorResponse(\n 'hard_delete_disabled',\n 'Hard delete is disabled by server configuration.',\n 403,\n )\n }\n\n return undefined\n}\n\nconst getRouteCollisionIssues = async ({\n docsSet,\n manifest,\n options,\n payload,\n routeBase,\n}: {\n docsSet?: ResolvedDocsSet\n manifest: ValidatedDocsManifest\n options: CreateSyncEndpointOptions\n payload: RouteCollisionPayloadOperations\n routeBase: string\n}) => {\n const desiredRoutes = manifest.files.map((file) => file.route)\n const duplicateDesiredRouteCollisions = findDuplicateDesiredRouteCollisions(desiredRoutes)\n const existingDocsRouteCollisions = options.docsEnabled\n ? await findExistingDocsRouteCollisions({\n collectionSlug: options.docsCollectionSlug,\n docsSetId: docsSet?.id,\n includeDrafts: options.docsEnableDrafts,\n payload,\n routes: desiredRoutes,\n sourceId: manifest.source.id,\n })\n : []\n const pageRouteCollisions =\n options.routing?.pages?.enabled === true\n ? await findConfiguredPagesRouteCollisions({\n allowBridgePages: options.routing.pages.allowBridgePages,\n bridgeField: options.routing.pages.bridgeField,\n collectionSlug: options.routing.pages.collection,\n docsSetRouteBase: routeBase,\n payload,\n routeField: options.routing.pages.routeField,\n })\n : []\n\n return [\n ...duplicateDesiredRouteCollisions,\n ...existingDocsRouteCollisions,\n ...pageRouteCollisions,\n ]\n}\n\ntype AuthenticatedSyncRequest = {\n actor?: string\n bodyHash: string\n branch?: string\n commit?: string\n expiresAt: Date\n keyId: string\n nonce: string\n repository?: string\n}\n\nconst getRequiredHeader = (headers: Headers, name: string): string | undefined => {\n const value = headers.get(name)\n\n return value && value.trim() !== '' ? value.trim() : undefined\n}\n\nconst getBearerToken = (headers: Headers): string | undefined => {\n const authorization = getRequiredHeader(headers, 'authorization')\n\n if (!authorization) {\n return undefined\n }\n\n const [scheme, token] = authorization.split(/\\s+/, 2)\n\n if (scheme?.toLowerCase() !== 'bearer' || !token) {\n return ''\n }\n\n return token\n}\n\nconst hasEd25519AuthHeaders = (headers: Headers): boolean =>\n getRequiredHeader(headers, 'x-vl-md-docs-key-id') !== undefined ||\n getRequiredHeader(headers, 'x-vl-md-docs-signature') !== undefined ||\n getRequiredHeader(headers, 'x-vl-md-docs-timestamp') !== undefined ||\n getRequiredHeader(headers, 'x-vl-md-docs-nonce') !== undefined\n\nconst assertReplayProtectionAvailable = (\n options: CreateSyncEndpointOptions,\n): Response | undefined =>\n options.noncesEnabled\n ? undefined\n : errorResponse(\n 'replay_protection_unavailable',\n 'Sync endpoint requires nonce replay protection.',\n 500,\n )\n\nconst authenticateEd25519Request = async ({\n now,\n options,\n rawBody,\n req,\n}: {\n now: Date\n options: CreateSyncEndpointOptions\n rawBody: string\n req: PayloadRequest\n}): Promise<\n | {\n identity: AuthenticatedSyncRequest\n response?: never\n }\n | {\n identity?: never\n response: Response\n }\n> => {\n const headersResult = extractSyncRequestHeaders(req.headers)\n\n if (!headersResult.ok) {\n return {\n response: errorResponse(\n 'missing_header',\n `Missing required sync header: ${headersResult.header}.`,\n 401,\n ),\n }\n }\n\n if (!options.docsKeysEnabled) {\n return {\n response: errorResponse(\n 'auth_disabled',\n 'Signed sync authentication requires the docs Keys collection.',\n 401,\n ),\n }\n }\n\n const keyConfig = await findDocsKeyById({\n collectionSlug: options.docsKeysCollectionSlug,\n keyId: headersResult.headers.keyId,\n payload: req.payload as unknown as DocsKeyPayloadOperations,\n })\n\n if (!keyConfig) {\n return {\n response: errorResponse('unknown_key', 'Unknown sync request key id.', 401),\n }\n }\n\n const bodyHash = verifyBodySha256({\n body: rawBody,\n expectedHash: headersResult.headers.bodySha256,\n })\n\n if (!bodyHash.ok) {\n return {\n response: errorResponse(\n 'body_hash_mismatch',\n 'Sync request body hash does not match the signed header.',\n 401,\n ),\n }\n }\n\n const timestampValidation = validateTimestampSkew({\n maxSkewSeconds: options.maxSkewSeconds ?? DEFAULT_MAX_SKEW_SECONDS,\n now,\n timestamp: headersResult.headers.timestamp,\n })\n\n if (!timestampValidation.ok) {\n return {\n response: errorResponse('invalid_timestamp', timestampValidation.message, 401),\n }\n }\n\n const replayUnavailable = assertReplayProtectionAvailable(options)\n\n if (replayUnavailable) {\n return {\n response: replayUnavailable,\n }\n }\n\n const nonceAvailable = await assertNonceNotReplayed({\n collectionSlug: options.noncesCollectionSlug,\n keyId: headersResult.headers.keyId,\n nonce: headersResult.headers.nonce,\n now,\n payload: req.payload as unknown as NoncePayloadOperations,\n })\n\n if (!nonceAvailable) {\n return {\n response: errorResponse('nonce_replay', 'Sync request nonce has already been used.', 409),\n }\n }\n\n const canonicalPath = getCanonicalPathFromRequestUrl({\n endpointPath: options.endpointPath,\n url: req.url,\n })\n const canonicalString = buildCanonicalSigningString({\n bodySha256: bodyHash.computedHash,\n method: 'POST',\n nonce: headersResult.headers.nonce,\n path: canonicalPath,\n timestamp: headersResult.headers.timestamp,\n })\n\n if (\n !verifyEd25519Signature({\n canonicalString,\n publicKey: keyConfig.publicKey,\n signature: headersResult.headers.signature,\n })\n ) {\n return {\n response: errorResponse('invalid_signature', 'Invalid sync request signature.', 401),\n }\n }\n\n const nonceTtlSeconds = options.nonceTtlSeconds ?? DEFAULT_NONCE_TTL_SECONDS\n\n return {\n identity: {\n bodyHash: bodyHash.computedHash,\n expiresAt: new Date(now.getTime() + nonceTtlSeconds * 1000),\n keyId: headersResult.headers.keyId,\n nonce: headersResult.headers.nonce,\n },\n }\n}\n\nconst authenticateGitHubOidcRequest = async ({\n docsSet,\n now,\n options,\n rawBody,\n req,\n}: {\n docsSet: ResolvedDocsSet\n now: Date\n options: CreateSyncEndpointOptions\n rawBody: string\n req: PayloadRequest\n}): Promise<\n | {\n identity: AuthenticatedSyncRequest\n response?: never\n }\n | {\n identity?: never\n response: Response\n }\n> => {\n const token = getBearerToken(req.headers)\n\n if (token === undefined) {\n return {\n response: errorResponse(\n 'missing_header',\n 'Missing required sync header: Authorization.',\n 401,\n ),\n }\n }\n\n if (token === '') {\n return {\n response: errorResponse(\n 'oidc_invalid_token',\n 'Authorization must be a Bearer GitHub OIDC token.',\n 401,\n ),\n }\n }\n\n const expectedHash = getRequiredHeader(req.headers, 'x-vl-md-docs-body-sha256')\n\n if (!expectedHash) {\n return {\n response: errorResponse(\n 'missing_header',\n 'Missing required sync header: X-VL-MD-DOCS-Body-SHA256.',\n 401,\n ),\n }\n }\n\n const bodyHash = verifyBodySha256({\n body: rawBody,\n expectedHash,\n })\n\n if (!bodyHash.ok) {\n return {\n response: errorResponse(\n 'body_hash_mismatch',\n 'Sync request body hash does not match the OIDC header.',\n 401,\n ),\n }\n }\n\n if (!options.docsTrustedEnabled) {\n return {\n response: errorResponse(\n 'auth_disabled',\n 'GitHub OIDC sync authentication requires the docs Trusted collection.',\n 401,\n ),\n }\n }\n\n const trustedSources = await findTrustedGitHubSources({\n collectionSlug: options.docsTrustedCollectionSlug,\n payload: req.payload as unknown as DocsTrustedPayloadOperations,\n })\n const allowedRef = docsSet.branch.startsWith('refs/')\n ? docsSet.branch\n : `refs/heads/${docsSet.branch}`\n\n const verified = await verifyGitHubOidcToken({\n config: {\n allowedRefs: [allowedRef],\n allowedWorkflowRefs: docsSet.advancedSecurity?.allowedWorkflowRefs,\n allowPullRequests: docsSet.allowPullRequests,\n audience: docsSet.slug,\n enforceWorkflowRefs: docsSet.advancedSecurity?.enabled === true,\n trustedSources,\n },\n fetchJson: options.oidcFetchJson,\n now,\n token,\n })\n\n if (!verified.ok) {\n return {\n response: errorResponse(\n verified.code,\n verified.message,\n verified.code === 'oidc_jwks_unavailable' ? 503 : 401,\n ),\n }\n }\n\n const replayUnavailable = assertReplayProtectionAvailable(options)\n\n if (replayUnavailable) {\n return {\n response: replayUnavailable,\n }\n }\n\n const nonceAvailable = await assertNonceNotReplayed({\n collectionSlug: options.noncesCollectionSlug,\n keyId: verified.token.keyId,\n nonce: verified.token.claims.jti,\n now,\n payload: req.payload as unknown as NoncePayloadOperations,\n })\n\n if (!nonceAvailable) {\n return {\n response: errorResponse('oidc_replay', 'GitHub OIDC token jti has already been used.', 409),\n }\n }\n\n return {\n identity: {\n actor: verified.token.claims.actor,\n bodyHash: bodyHash.computedHash,\n branch: verified.token.claims.ref,\n commit: verified.token.claims.sha,\n expiresAt: verified.token.expiresAt,\n keyId: verified.token.keyId,\n nonce: verified.token.claims.jti,\n repository: verified.token.claims.repository,\n },\n }\n}\n\nconst authenticateSyncRequest = async ({\n docsSet,\n now,\n options,\n rawBody,\n req,\n}: {\n docsSet: ResolvedDocsSet\n now: Date\n options: CreateSyncEndpointOptions\n rawBody: string\n req: PayloadRequest\n}): Promise<\n | {\n identity: AuthenticatedSyncRequest\n response?: never\n }\n | {\n identity?: never\n response: Response\n }\n> => {\n const ed25519Enabled = isEd25519AuthEnabled(options.auth)\n const githubOidcEnabled = isGitHubOidcAuthEnabled(options.auth)\n\n if (!ed25519Enabled && !githubOidcEnabled) {\n return {\n response: errorResponse(\n 'auth_disabled',\n 'Sync authentication is not configured for this endpoint.',\n 401,\n ),\n }\n }\n\n const bearerToken = getBearerToken(req.headers)\n\n if (bearerToken !== undefined) {\n if (!githubOidcEnabled) {\n return {\n response: errorResponse(\n 'auth_disabled',\n 'GitHub OIDC sync authentication is not configured for this endpoint.',\n 401,\n ),\n }\n }\n\n return authenticateGitHubOidcRequest({\n docsSet,\n now,\n options,\n rawBody,\n req,\n })\n }\n\n if (hasEd25519AuthHeaders(req.headers) || !githubOidcEnabled) {\n if (!ed25519Enabled) {\n return {\n response: errorResponse(\n 'auth_disabled',\n 'Signed sync authentication is not configured for this endpoint.',\n 401,\n ),\n }\n }\n\n return authenticateEd25519Request({\n now,\n options,\n rawBody,\n req,\n })\n }\n\n return authenticateGitHubOidcRequest({\n docsSet,\n now,\n options,\n rawBody,\n req,\n })\n}\n\nconst createSyncEndpointHandler =\n (options: CreateSyncEndpointOptions) =>\n async (req: PayloadRequest): Promise<Response> => {\n const startedAt = options.getNow?.() ?? new Date()\n\n if (req.method && req.method.toUpperCase() !== 'POST') {\n return errorResponse('invalid_method', 'Sync endpoint only accepts POST.', 405)\n }\n\n if (typeof req.text !== 'function') {\n return errorResponse(\n 'invalid_body',\n 'Sync endpoint requires access to the request body text.',\n 400,\n )\n }\n\n const rawBody = await req.text()\n const maxBodyBytes = options.maxBodyBytes ?? DEFAULT_MAX_BODY_BYTES\n\n if (Buffer.byteLength(rawBody, 'utf8') > maxBodyBytes) {\n return errorResponse('invalid_body', 'Sync request body is too large.', 413)\n }\n\n const manifest = parseManifestBody(rawBody)\n\n if (!manifest) {\n return errorResponse('invalid_body', 'Sync request body must be a JSON manifest.', 400)\n }\n\n const sourceResolution = await resolveSyncSource({\n manifest,\n options,\n payload: req.payload as unknown as DocsSetPayloadOperations,\n })\n\n if (sourceResolution.response) {\n return sourceResolution.response\n }\n\n const authentication = await authenticateSyncRequest({\n docsSet: sourceResolution.source.docsSet,\n now: startedAt,\n options,\n rawBody,\n req,\n })\n\n if (authentication.response) {\n return authentication.response\n }\n\n const validation = validateDocsManifest(manifest, {\n allowedSourceIds: [sourceResolution.source.sourceId],\n maxTotalBytes: maxBodyBytes,\n routeBase: sourceResolution.source.routeBase,\n })\n\n if (!validation.ok) {\n return jsonResponse(\n {\n error: {\n code: 'invalid_manifest',\n message: 'Sync manifest is invalid.',\n },\n ok: false,\n },\n 400,\n )\n }\n\n const effectiveDeleteBehavior = options.deleteBehavior ?? 'archive'\n const lifecyclePolicyError = getLifecyclePolicyError({\n deleteBehavior: effectiveDeleteBehavior,\n manifest: validation.data,\n options,\n })\n\n if (lifecyclePolicyError) {\n return lifecyclePolicyError\n }\n\n const routeCollisions = await getRouteCollisionIssues({\n docsSet: sourceResolution.source.docsSet,\n manifest: validation.data,\n options,\n payload: req.payload as unknown as RouteCollisionPayloadOperations,\n routeBase: sourceResolution.source.routeBase,\n })\n\n if (routeCollisions.length > 0) {\n return errorResponse(\n 'route_collision',\n 'One or more docs routes collide with an existing route reservation.',\n 409,\n {\n routeCollisions,\n },\n )\n }\n\n const isSyncMode = validation.data.mode === 'sync'\n\n if (isSyncMode && options.allowWrites !== true) {\n return errorResponse(\n 'sync_writes_disabled',\n 'Sync writes are disabled by server configuration.',\n 403,\n )\n }\n\n if (isSyncMode && options.requireDryRunBeforeApply === true) {\n return errorResponse(\n 'dry_run_required_not_implemented',\n 'Required dry-run proof before apply is not implemented yet.',\n 400,\n )\n }\n\n if (\n isSyncMode &&\n !assertApplyDeleteBehaviorSupported(effectiveDeleteBehavior, {\n allowHardDelete: options.allowHardDelete,\n docsEnableDrafts: options.docsEnableDrafts,\n })\n ) {\n return errorResponse(\n 'delete_behavior_not_implemented',\n 'Configured delete behavior cannot be applied.',\n 400,\n )\n }\n\n if (isSyncMode && !options.syncRunsEnabled) {\n return errorResponse(\n 'audit_unavailable',\n 'Applied sync requires the sync-run audit collection.',\n 500,\n )\n }\n\n const existingPayloadDocs = options.docsEnabled\n ? await findExistingPayloadDocsRecords({\n collectionSlug: options.docsCollectionSlug,\n docsSetId: sourceResolution.source.docsSet?.id,\n draft: options.docsEnableDrafts,\n markdownFieldName: options.markdownFieldName,\n payload: req.payload as unknown as ExistingDocsPayloadOperations,\n sourceId: validation.data.source.id,\n })\n : []\n const existingDocs = existingPayloadDocs.map(toExistingDocsRecord)\n const plan = planDocsSync({\n deleteBehavior: effectiveDeleteBehavior,\n desired: validation.data,\n existing: existingDocs,\n })\n const summary = summarizePlan(plan)\n const warnings = [...validation.warnings, ...plan.warnings]\n if (isSyncMode) {\n const existingBySourcePath = new Map(\n existingPayloadDocs.map((record) => [record.sourcePath, record]),\n )\n const conflicts = findDocsSyncConflicts({\n existingBySourcePath,\n plannedChanges: getPlannedConflictChanges({\n existing: existingPayloadDocs,\n plan,\n }),\n })\n\n if (conflicts.length > 0) {\n return errorResponse(\n 'manual_edit_conflict',\n 'One or more docs were modified outside the docs sync workflow.',\n 409,\n {\n conflicts,\n },\n )\n }\n }\n\n await storeAcceptedNonce({\n bodyHash: authentication.identity.bodyHash,\n collectionSlug: options.noncesCollectionSlug,\n expiresAt: authentication.identity.expiresAt,\n keyId: authentication.identity.keyId,\n nonce: authentication.identity.nonce,\n payload: req.payload as unknown as NoncePayloadOperations,\n sourceId: validation.data.source.id,\n usedAt: startedAt,\n })\n\n let syncRunId: number | string | undefined\n\n if (options.syncRunsEnabled) {\n const syncRun = await createSyncRunAudit({\n actor: authentication.identity.actor,\n bodyHash: authentication.identity.bodyHash,\n branch: authentication.identity.branch ?? validation.data.source.branch,\n collectionSlug: options.syncRunsCollectionSlug,\n commit: authentication.identity.commit ?? validation.data.source.commit,\n completedAt: isSyncMode ? startedAt : (options.getNow?.() ?? new Date()),\n deleteBehavior: effectiveDeleteBehavior,\n errors: [],\n fileCount: validation.data.files.length,\n keyId: authentication.identity.keyId,\n mode: isSyncMode ? 'sync' : 'dry-run',\n payload: req.payload as unknown as SyncRunsPayloadOperations,\n publishRequested: validation.data.publish,\n repository: authentication.identity.repository ?? validation.data.source.repository,\n sourceId: validation.data.source.id,\n startedAt,\n status: isSyncMode ? 'pending' : 'success',\n summary,\n totalBytes: getTotalManifestBytes(validation.data),\n warnings,\n })\n\n syncRunId = getRecordId(syncRun)\n }\n\n if (isSyncMode) {\n if (!syncRunId) {\n return errorResponse(\n 'audit_unavailable',\n 'Applied sync could not create a sync-run audit record.',\n 500,\n )\n }\n\n try {\n const applyResult = await applyDocsSync({\n collectionSlug: options.docsCollectionSlug,\n deleteBehavior: effectiveDeleteBehavior,\n docsEnableDrafts: options.docsEnableDrafts,\n docsSetId: sourceResolution.source.docsSet?.id,\n existing: existingPayloadDocs,\n manifest: validation.data,\n markdownFieldName: options.markdownFieldName,\n now: options.getNow?.() ?? new Date(),\n payload: req.payload as unknown as ApplyDocsSyncPayloadOperations,\n plan,\n publish: validation.data.publish,\n syncRunId,\n })\n\n if (!applyResult.ok) {\n return errorResponse(\n 'manual_edit_conflict',\n 'One or more docs were modified outside the docs sync workflow.',\n 409,\n {\n conflicts: applyResult.conflicts,\n },\n )\n }\n\n await updateSyncRunAudit({\n collectionSlug: options.syncRunsCollectionSlug,\n completedAt: options.getNow?.() ?? new Date(),\n payload: req.payload as unknown as SyncRunsPayloadOperations,\n status: 'success',\n summary,\n syncRunId,\n warnings,\n })\n\n if (sourceResolution.source.docsSet) {\n await updateDocsSetAfterSync({\n aiExport: validation.data.aiExport,\n collectionSlug: options.docsSetsCollectionSlug,\n docsCount: validation.data.files.length,\n docsSetId: sourceResolution.source.docsSet.id,\n now: options.getNow?.() ?? new Date(),\n payload: req.payload as unknown as DocsSetPayloadOperations,\n publish: validation.data.publish,\n syncRunId,\n })\n }\n } catch (error) {\n await updateSyncRunAudit({\n collectionSlug: options.syncRunsCollectionSlug,\n completedAt: options.getNow?.() ?? new Date(),\n errors: [\n {\n code: 'invalid_manifest',\n message: error instanceof Error ? error.message : 'Sync apply failed.',\n },\n ],\n payload: req.payload as unknown as SyncRunsPayloadOperations,\n status: 'failed',\n summary,\n syncRunId,\n warnings,\n })\n\n return errorResponse('sync_apply_failed', 'Sync apply failed.', 500)\n }\n }\n\n return jsonResponse({\n changes: serializeChanges(plan),\n deleteBehavior: effectiveDeleteBehavior,\n dryRun: !isSyncMode,\n ok: true,\n publishRequested: validation.data.publish,\n summary,\n syncRunId: syncRunId === undefined ? undefined : String(syncRunId),\n warnings,\n })\n }\n\nexport const createSyncEndpoint = (options: CreateSyncEndpointOptions): Endpoint => ({\n handler: createSyncEndpointHandler(options),\n method: 'post',\n path: options.endpointPath,\n})\n"],"names":["DEFAULT_MAX_BODY_BYTES","DEFAULT_MAX_SKEW_SECONDS","DEFAULT_NONCE_TTL_SECONDS","applyDocsSync","assertApplyDeleteBehaviorSupported","createSyncRunAudit","findConfiguredPagesRouteCollisions","findDocsKeyById","findDocsSetBySlug","findDocsSyncConflicts","findDuplicateDesiredRouteCollisions","findExistingDocsRouteCollisions","findExistingPayloadDocsRecords","findTrustedGitHubSources","getRecordId","isEd25519AuthEnabled","isGitHubOidcAuthEnabled","toExistingDocsRecord","updateDocsSetAfterSync","updateSyncRunAudit","assertNonceNotReplayed","buildCanonicalSigningString","extractSyncRequestHeaders","getCanonicalPathFromRequestUrl","storeAcceptedNonce","validateTimestampSkew","verifyBodySha256","verifyEd25519Signature","verifyGitHubOidcToken","planDocsSync","validateDocsManifest","jsonResponse","body","status","Response","json","errorResponse","code","message","extras","error","ok","isRecord","value","Array","isArray","parseManifestBody","rawBody","parsed","JSON","parse","undefined","resolveSyncSource","manifest","options","payload","sourceId","source","id","response","docsSet","docsSetsEnabled","slug","collectionSlug","docsSetsCollectionSlug","docsGroupsCollectionSlug","includeDrafts","routeBase","summarizePlan","plan","archive","length","create","delete","draft","unchanged","update","warnings","serializeChange","change","current","archived","route","sourceHash","title","desired","sha256","reason","sourcePath","serializeChanges","map","getTotalManifestBytes","files","reduce","total","file","Buffer","byteLength","content","getPlannedConflictChanges","existing","existingBySourcePath","Map","record","archivedUnchanged","filter","get","getLifecyclePolicyError","deleteBehavior","publish","allowPublish","docsEnableDrafts","allowHardDelete","getRouteCollisionIssues","desiredRoutes","duplicateDesiredRouteCollisions","existingDocsRouteCollisions","docsEnabled","docsCollectionSlug","docsSetId","routes","pageRouteCollisions","routing","pages","enabled","allowBridgePages","bridgeField","collection","docsSetRouteBase","routeField","getRequiredHeader","headers","name","trim","getBearerToken","authorization","scheme","token","split","toLowerCase","hasEd25519AuthHeaders","assertReplayProtectionAvailable","noncesEnabled","authenticateEd25519Request","now","req","headersResult","header","docsKeysEnabled","keyConfig","docsKeysCollectionSlug","keyId","bodyHash","expectedHash","bodySha256","timestampValidation","maxSkewSeconds","timestamp","replayUnavailable","nonceAvailable","noncesCollectionSlug","nonce","canonicalPath","endpointPath","url","canonicalString","computedHash","method","path","publicKey","signature","nonceTtlSeconds","identity","expiresAt","Date","getTime","authenticateGitHubOidcRequest","docsTrustedEnabled","trustedSources","docsTrustedCollectionSlug","allowedRef","branch","startsWith","verified","config","allowedRefs","allowedWorkflowRefs","advancedSecurity","allowPullRequests","audience","enforceWorkflowRefs","fetchJson","oidcFetchJson","claims","jti","actor","ref","commit","sha","repository","authenticateSyncRequest","ed25519Enabled","auth","githubOidcEnabled","bearerToken","createSyncEndpointHandler","startedAt","getNow","toUpperCase","text","maxBodyBytes","sourceResolution","authentication","validation","allowedSourceIds","maxTotalBytes","effectiveDeleteBehavior","lifecyclePolicyError","data","routeCollisions","isSyncMode","mode","allowWrites","requireDryRunBeforeApply","syncRunsEnabled","existingPayloadDocs","markdownFieldName","existingDocs","summary","conflicts","plannedChanges","usedAt","syncRunId","syncRun","syncRunsCollectionSlug","completedAt","errors","fileCount","publishRequested","totalBytes","applyResult","aiExport","docsCount","Error","changes","dryRun","String","createSyncEndpoint","handler"],"mappings":"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"}
|
|
@@ -23,16 +23,23 @@ const renderSidebarItems = (items, activeRoute, depth = 0)=>{
|
|
|
23
23
|
}
|
|
24
24
|
return /*#__PURE__*/ _jsx("ul", {
|
|
25
25
|
className: cx(depth === 0 ? 'space-y-1' : 'ml-3 mt-1 space-y-1 border-l border-border pl-3'),
|
|
26
|
-
children: items.map((item)
|
|
26
|
+
children: items.map((item)=>{
|
|
27
|
+
const isActive = item.route === activeRoute;
|
|
28
|
+
const labelClassName = cx('block rounded-lg px-3 py-2 text-sm leading-5 transition-colors', item.route ? isActive ? 'bg-cyan-400/10 text-cyan-200' : 'text-foreground/70 hover:bg-white/[0.04] hover:text-foreground' : 'text-foreground/55');
|
|
29
|
+
return /*#__PURE__*/ _jsxs("li", {
|
|
27
30
|
children: [
|
|
28
|
-
/*#__PURE__*/ _jsx("a", {
|
|
29
|
-
className:
|
|
31
|
+
item.route ? /*#__PURE__*/ _jsx("a", {
|
|
32
|
+
className: labelClassName,
|
|
30
33
|
href: item.route,
|
|
31
34
|
children: item.label
|
|
35
|
+
}) : /*#__PURE__*/ _jsx("span", {
|
|
36
|
+
className: labelClassName,
|
|
37
|
+
children: item.label
|
|
32
38
|
}),
|
|
33
39
|
item.children ? renderSidebarItems(item.children, activeRoute, depth + 1) : null
|
|
34
40
|
]
|
|
35
|
-
}, item.route)
|
|
41
|
+
}, item.route ?? item.sourcePath);
|
|
42
|
+
})
|
|
36
43
|
});
|
|
37
44
|
};
|
|
38
45
|
const renderMarkdown = async ({ collectionSlug, markdown })=>{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/next/PayloadMarkdownDocsPage.tsx"],"sourcesContent":["import type { CSSProperties, ReactNode } from 'react'\n\nimport type {\n PayloadMarkdownDocsHeroImage,\n PayloadMarkdownDocsSidebarItem,\n ResolvedPayloadMarkdownDocsRecord,\n ResolvedPayloadMarkdownDocsRoute,\n ResolvedPayloadMarkdownDocsSet,\n} from './types.js'\n\nimport { DEFAULT_DOCS_COLLECTION_SLUG } from '../constants.js'\n\nexport type PayloadMarkdownDocsPageProps = {\n collectionSlug?: string\n renderSidebar?: boolean\n resolved: ResolvedPayloadMarkdownDocsRoute\n}\n\nconst cx = (...values: (false | null | string | undefined)[]): string =>\n values.filter(Boolean).join(' ')\n\nconst docsLayoutStyles = `\n[data-payload-markdown-docs-layout] {\n display: grid;\n gap: 2.5rem;\n grid-template-columns: minmax(0, 1fr);\n}\n\n@media (min-width: 1024px) {\n [data-payload-markdown-docs-layout=\"with-sidebar\"] {\n grid-template-columns: 16rem minmax(0, 1fr);\n }\n}\n`\n\nconst getDocsLayoutStyle = (hasHero: boolean): CSSProperties =>\n hasHero\n ? {}\n : {\n marginTop: '6rem',\n }\n\nconst renderSidebarItems = (\n items: PayloadMarkdownDocsSidebarItem[],\n activeRoute: string,\n depth = 0,\n): ReactNode => {\n if (items.length === 0) {\n return null\n }\n\n return (\n <ul\n className={cx(depth === 0 ? 'space-y-1' : 'ml-3 mt-1 space-y-1 border-l border-border pl-3')}\n >\n {items.map((item) => (\n <li key={item.route}>\n <a\n className={cx(\n 'block rounded-lg px-3 py-2 text-sm leading-5 transition-colors',\n item.route === activeRoute\n ? 'bg-cyan-400/10 text-cyan-200'\n : 'text-foreground/70 hover:bg-white/[0.04] hover:text-foreground',\n )}\n href={item.route}\n >\n {item.label}\n </a>\n {item.children ? renderSidebarItems(item.children, activeRoute, depth + 1) : null}\n </li>\n ))}\n </ul>\n )\n}\n\nconst renderMarkdown = async ({\n collectionSlug,\n markdown,\n}: {\n collectionSlug: string\n markdown?: string\n}): Promise<ReactNode> => {\n if (!markdown?.trim()) {\n return null\n }\n\n const { MarkdownRenderer } = await import('@valkyrianlabs/payload-markdown/server')\n\n return MarkdownRenderer({\n className: 'min-w-0',\n collectionSlug,\n markdown,\n scope: 'field',\n size: 'md',\n variant: 'docs',\n wrapperClassName: 'min-w-0',\n })\n}\n\nconst DocsHeader = ({\n doc,\n docsSet,\n}: {\n doc?: ResolvedPayloadMarkdownDocsRecord\n docsSet: ResolvedPayloadMarkdownDocsSet\n}) => {\n const description = doc?.description ?? docsSet.description\n const title = doc?.title ?? docsSet.title\n\n return (\n <header className=\"mb-10 border-b border-border pb-8\">\n <h1 className=\"text-4xl font-semibold tracking-tight text-foreground md:text-5xl\">{title}</h1>\n {description ? (\n <p className=\"mt-4 max-w-3xl text-lg leading-8 text-foreground/70\">{description}</p>\n ) : null}\n </header>\n )\n}\n\nconst DocsHero = ({\n heroImage,\n title,\n}: {\n heroImage?: PayloadMarkdownDocsHeroImage\n title: string\n}) => {\n if (!heroImage) {\n return null\n }\n\n return (\n <figure\n className=\"mb-10 overflow-hidden rounded-xl border border-border bg-white/[0.03]\"\n data-payload-markdown-docs-hero\n style={{\n borderRadius: '0.75rem',\n marginBottom: '2.5rem',\n overflow: 'hidden',\n }}\n >\n <img\n alt={heroImage.alt ?? title}\n className=\"block h-auto w-full\"\n height={heroImage.height}\n src={heroImage.url}\n style={{\n display: 'block',\n height: 'auto',\n width: '100%',\n }}\n width={heroImage.width}\n />\n </figure>\n )\n}\n\nexport const PayloadMarkdownDocsPage = async ({\n collectionSlug = DEFAULT_DOCS_COLLECTION_SLUG,\n renderSidebar = true,\n resolved,\n}: PayloadMarkdownDocsPageProps) => {\n if (resolved.type === 'docsGroupIndex') {\n return (\n <main\n className=\"min-h-screen bg-background text-foreground\"\n data-payload-markdown-docs-route={resolved.route}\n >\n <div className=\"mx-auto w-full max-w-6xl px-6 py-14 lg:px-8\">\n <header className=\"mb-10 border-b border-border pb-8\">\n <p className=\"mb-3 text-sm font-medium uppercase tracking-wide text-cyan-300\">Docs</p>\n <h1 className=\"text-4xl font-semibold tracking-tight md:text-5xl\">\n {resolved.group.navTitle ?? resolved.group.title}\n </h1>\n {resolved.group.description ? (\n <p className=\"mt-4 max-w-3xl text-lg leading-8 text-foreground/70\">\n {resolved.group.description}\n </p>\n ) : null}\n </header>\n {resolved.docsSets.length > 0 ? (\n <nav aria-label=\"Docs sets\">\n <ul className=\"grid gap-4 sm:grid-cols-2 lg:grid-cols-3\">\n {resolved.docsSets.map((docsSet) => (\n <li key={docsSet.id}>\n <a\n className=\"block rounded-xl border border-border bg-white/[0.03] p-5 transition-colors hover:bg-white/[0.06]\"\n href={docsSet.routeBase}\n >\n <span className=\"text-base font-semibold text-foreground\">\n {docsSet.navTitle ?? docsSet.title}\n </span>\n {docsSet.description ? (\n <span className=\"mt-2 block text-sm leading-6 text-foreground/65\">\n {docsSet.description}\n </span>\n ) : null}\n </a>\n </li>\n ))}\n </ul>\n </nav>\n ) : null}\n </div>\n </main>\n )\n }\n\n const markdown = await renderMarkdown({\n collectionSlug,\n markdown: resolved.doc?.content,\n })\n const hasHero = Boolean(resolved.doc?.heroImage)\n const hasSidebar = renderSidebar && resolved.sidebar.length > 0\n\n return (\n <main\n className=\"min-h-screen bg-background text-foreground\"\n data-payload-markdown-docs-route={resolved.route}\n >\n <style>{docsLayoutStyles}</style>\n <div\n className=\"mx-auto w-full max-w-7xl px-6 py-10 lg:px-8\"\n data-payload-markdown-docs-layout={hasSidebar ? 'with-sidebar' : 'default'}\n style={getDocsLayoutStyle(hasHero)}\n >\n {hasSidebar ? (\n <aside\n className=\"lg:sticky lg:top-8 lg:self-start\"\n style={{\n alignSelf: 'start',\n }}\n >\n <nav\n aria-label=\"Docs navigation\"\n className=\"rounded-xl border border-border bg-white/[0.03] p-3\"\n >\n {renderSidebarItems(resolved.sidebar, resolved.route)}\n </nav>\n </aside>\n ) : null}\n <article className=\"min-w-0 max-w-4xl\">\n <DocsHero\n heroImage={resolved.doc?.heroImage}\n title={resolved.doc?.title ?? resolved.docsSet.title}\n />\n <DocsHeader doc={resolved.doc} docsSet={resolved.docsSet} />\n {markdown}\n </article>\n </div>\n </main>\n )\n}\n"],"names":["DEFAULT_DOCS_COLLECTION_SLUG","cx","values","filter","Boolean","join","docsLayoutStyles","getDocsLayoutStyle","hasHero","marginTop","renderSidebarItems","items","activeRoute","depth","length","ul","className","map","item","li","a","route","href","label","children","renderMarkdown","collectionSlug","markdown","trim","MarkdownRenderer","scope","size","variant","wrapperClassName","DocsHeader","doc","docsSet","description","title","header","h1","p","DocsHero","heroImage","figure","data-payload-markdown-docs-hero","style","borderRadius","marginBottom","overflow","img","alt","height","src","url","display","width","PayloadMarkdownDocsPage","renderSidebar","resolved","type","main","data-payload-markdown-docs-route","div","group","navTitle","docsSets","nav","aria-label","routeBase","span","id","content","hasSidebar","sidebar","data-payload-markdown-docs-layout","aside","alignSelf","article"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../src/next/PayloadMarkdownDocsPage.tsx"],"sourcesContent":["import type { CSSProperties, ReactNode } from 'react'\n\nimport type {\n PayloadMarkdownDocsHeroImage,\n PayloadMarkdownDocsSidebarItem,\n ResolvedPayloadMarkdownDocsRecord,\n ResolvedPayloadMarkdownDocsRoute,\n ResolvedPayloadMarkdownDocsSet,\n} from './types.js'\n\nimport { DEFAULT_DOCS_COLLECTION_SLUG } from '../constants.js'\n\nexport type PayloadMarkdownDocsPageProps = {\n collectionSlug?: string\n renderSidebar?: boolean\n resolved: ResolvedPayloadMarkdownDocsRoute\n}\n\nconst cx = (...values: (false | null | string | undefined)[]): string =>\n values.filter(Boolean).join(' ')\n\nconst docsLayoutStyles = `\n[data-payload-markdown-docs-layout] {\n display: grid;\n gap: 2.5rem;\n grid-template-columns: minmax(0, 1fr);\n}\n\n@media (min-width: 1024px) {\n [data-payload-markdown-docs-layout=\"with-sidebar\"] {\n grid-template-columns: 16rem minmax(0, 1fr);\n }\n}\n`\n\nconst getDocsLayoutStyle = (hasHero: boolean): CSSProperties =>\n hasHero\n ? {}\n : {\n marginTop: '6rem',\n }\n\nconst renderSidebarItems = (\n items: PayloadMarkdownDocsSidebarItem[],\n activeRoute: string,\n depth = 0,\n): ReactNode => {\n if (items.length === 0) {\n return null\n }\n\n return (\n <ul\n className={cx(depth === 0 ? 'space-y-1' : 'ml-3 mt-1 space-y-1 border-l border-border pl-3')}\n >\n {items.map((item) => {\n const isActive = item.route === activeRoute\n const labelClassName = cx(\n 'block rounded-lg px-3 py-2 text-sm leading-5 transition-colors',\n item.route\n ? isActive\n ? 'bg-cyan-400/10 text-cyan-200'\n : 'text-foreground/70 hover:bg-white/[0.04] hover:text-foreground'\n : 'text-foreground/55',\n )\n\n return (\n <li key={item.route ?? item.sourcePath}>\n {item.route ? (\n <a className={labelClassName} href={item.route}>\n {item.label}\n </a>\n ) : (\n <span className={labelClassName}>{item.label}</span>\n )}\n {item.children ? renderSidebarItems(item.children, activeRoute, depth + 1) : null}\n </li>\n )\n })}\n </ul>\n )\n}\n\nconst renderMarkdown = async ({\n collectionSlug,\n markdown,\n}: {\n collectionSlug: string\n markdown?: string\n}): Promise<ReactNode> => {\n if (!markdown?.trim()) {\n return null\n }\n\n const { MarkdownRenderer } = await import('@valkyrianlabs/payload-markdown/server')\n\n return MarkdownRenderer({\n className: 'min-w-0',\n collectionSlug,\n markdown,\n scope: 'field',\n size: 'md',\n variant: 'docs',\n wrapperClassName: 'min-w-0',\n })\n}\n\nconst DocsHeader = ({\n doc,\n docsSet,\n}: {\n doc?: ResolvedPayloadMarkdownDocsRecord\n docsSet: ResolvedPayloadMarkdownDocsSet\n}) => {\n const description = doc?.description ?? docsSet.description\n const title = doc?.title ?? docsSet.title\n\n return (\n <header className=\"mb-10 border-b border-border pb-8\">\n <h1 className=\"text-4xl font-semibold tracking-tight text-foreground md:text-5xl\">{title}</h1>\n {description ? (\n <p className=\"mt-4 max-w-3xl text-lg leading-8 text-foreground/70\">{description}</p>\n ) : null}\n </header>\n )\n}\n\nconst DocsHero = ({\n heroImage,\n title,\n}: {\n heroImage?: PayloadMarkdownDocsHeroImage\n title: string\n}) => {\n if (!heroImage) {\n return null\n }\n\n return (\n <figure\n className=\"mb-10 overflow-hidden rounded-xl border border-border bg-white/[0.03]\"\n data-payload-markdown-docs-hero\n style={{\n borderRadius: '0.75rem',\n marginBottom: '2.5rem',\n overflow: 'hidden',\n }}\n >\n <img\n alt={heroImage.alt ?? title}\n className=\"block h-auto w-full\"\n height={heroImage.height}\n src={heroImage.url}\n style={{\n display: 'block',\n height: 'auto',\n width: '100%',\n }}\n width={heroImage.width}\n />\n </figure>\n )\n}\n\nexport const PayloadMarkdownDocsPage = async ({\n collectionSlug = DEFAULT_DOCS_COLLECTION_SLUG,\n renderSidebar = true,\n resolved,\n}: PayloadMarkdownDocsPageProps) => {\n if (resolved.type === 'docsGroupIndex') {\n return (\n <main\n className=\"min-h-screen bg-background text-foreground\"\n data-payload-markdown-docs-route={resolved.route}\n >\n <div className=\"mx-auto w-full max-w-6xl px-6 py-14 lg:px-8\">\n <header className=\"mb-10 border-b border-border pb-8\">\n <p className=\"mb-3 text-sm font-medium uppercase tracking-wide text-cyan-300\">Docs</p>\n <h1 className=\"text-4xl font-semibold tracking-tight md:text-5xl\">\n {resolved.group.navTitle ?? resolved.group.title}\n </h1>\n {resolved.group.description ? (\n <p className=\"mt-4 max-w-3xl text-lg leading-8 text-foreground/70\">\n {resolved.group.description}\n </p>\n ) : null}\n </header>\n {resolved.docsSets.length > 0 ? (\n <nav aria-label=\"Docs sets\">\n <ul className=\"grid gap-4 sm:grid-cols-2 lg:grid-cols-3\">\n {resolved.docsSets.map((docsSet) => (\n <li key={docsSet.id}>\n <a\n className=\"block rounded-xl border border-border bg-white/[0.03] p-5 transition-colors hover:bg-white/[0.06]\"\n href={docsSet.routeBase}\n >\n <span className=\"text-base font-semibold text-foreground\">\n {docsSet.navTitle ?? docsSet.title}\n </span>\n {docsSet.description ? (\n <span className=\"mt-2 block text-sm leading-6 text-foreground/65\">\n {docsSet.description}\n </span>\n ) : null}\n </a>\n </li>\n ))}\n </ul>\n </nav>\n ) : null}\n </div>\n </main>\n )\n }\n\n const markdown = await renderMarkdown({\n collectionSlug,\n markdown: resolved.doc?.content,\n })\n const hasHero = Boolean(resolved.doc?.heroImage)\n const hasSidebar = renderSidebar && resolved.sidebar.length > 0\n\n return (\n <main\n className=\"min-h-screen bg-background text-foreground\"\n data-payload-markdown-docs-route={resolved.route}\n >\n <style>{docsLayoutStyles}</style>\n <div\n className=\"mx-auto w-full max-w-7xl px-6 py-10 lg:px-8\"\n data-payload-markdown-docs-layout={hasSidebar ? 'with-sidebar' : 'default'}\n style={getDocsLayoutStyle(hasHero)}\n >\n {hasSidebar ? (\n <aside\n className=\"lg:sticky lg:top-8 lg:self-start\"\n style={{\n alignSelf: 'start',\n }}\n >\n <nav\n aria-label=\"Docs navigation\"\n className=\"rounded-xl border border-border bg-white/[0.03] p-3\"\n >\n {renderSidebarItems(resolved.sidebar, resolved.route)}\n </nav>\n </aside>\n ) : null}\n <article className=\"min-w-0 max-w-4xl\">\n <DocsHero\n heroImage={resolved.doc?.heroImage}\n title={resolved.doc?.title ?? resolved.docsSet.title}\n />\n <DocsHeader doc={resolved.doc} docsSet={resolved.docsSet} />\n {markdown}\n </article>\n </div>\n </main>\n )\n}\n"],"names":["DEFAULT_DOCS_COLLECTION_SLUG","cx","values","filter","Boolean","join","docsLayoutStyles","getDocsLayoutStyle","hasHero","marginTop","renderSidebarItems","items","activeRoute","depth","length","ul","className","map","item","isActive","route","labelClassName","li","a","href","label","span","children","sourcePath","renderMarkdown","collectionSlug","markdown","trim","MarkdownRenderer","scope","size","variant","wrapperClassName","DocsHeader","doc","docsSet","description","title","header","h1","p","DocsHero","heroImage","figure","data-payload-markdown-docs-hero","style","borderRadius","marginBottom","overflow","img","alt","height","src","url","display","width","PayloadMarkdownDocsPage","renderSidebar","resolved","type","main","data-payload-markdown-docs-route","div","group","navTitle","docsSets","nav","aria-label","routeBase","id","content","hasSidebar","sidebar","data-payload-markdown-docs-layout","aside","alignSelf","article"],"mappings":"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"}
|
package/dist/next/links.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { DEFAULT_DOCS_GROUPS_COLLECTION_SLUG, DEFAULT_DOCS_SETS_COLLECTION_SLUG } from '../constants.js';
|
|
2
2
|
import { deriveDocsSetRouteBase, joinRouteSegments } from '../routing/index.js';
|
|
3
|
-
import { getRelationshipId, isRecord, toResolvedDocsSet } from './records.js';
|
|
3
|
+
import { getRelationshipId, isRecord, isVisibleDocsSet, toResolvedDocsSet } from './records.js';
|
|
4
4
|
const getGroupRoutePath = ({ groupId, groupsById, seen = new Set() })=>{
|
|
5
5
|
if (!groupId || seen.has(groupId)) {
|
|
6
6
|
return undefined;
|
|
@@ -25,6 +25,7 @@ export const getPayloadMarkdownDocsLinks = async ({ collections, overrideAccess
|
|
|
25
25
|
payload.find({
|
|
26
26
|
collection: docsSetsCollectionSlug,
|
|
27
27
|
depth: 0,
|
|
28
|
+
draft: false,
|
|
28
29
|
limit: 1000,
|
|
29
30
|
overrideAccess
|
|
30
31
|
}),
|
|
@@ -49,7 +50,9 @@ export const getPayloadMarkdownDocsLinks = async ({ collections, overrideAccess
|
|
|
49
50
|
}));
|
|
50
51
|
return docsSetsResult.docs.flatMap((doc)=>{
|
|
51
52
|
const docsSet = toResolvedDocsSet(doc);
|
|
52
|
-
if (!docsSet?.slug || !isRecord(doc)
|
|
53
|
+
if (!docsSet?.slug || !isRecord(doc) || !isVisibleDocsSet({
|
|
54
|
+
docsSet
|
|
55
|
+
})) {
|
|
53
56
|
return [];
|
|
54
57
|
}
|
|
55
58
|
return [
|
package/dist/next/links.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/next/links.ts"],"sourcesContent":["import type {
|
|
1
|
+
{"version":3,"sources":["../../src/next/links.ts"],"sourcesContent":["import type { PayloadMarkdownDocsCollectionSlugs, PayloadMarkdownDocsReadPayload } from './types.js'\n\nimport {\n DEFAULT_DOCS_GROUPS_COLLECTION_SLUG,\n DEFAULT_DOCS_SETS_COLLECTION_SLUG,\n} from '../constants.js'\nimport { deriveDocsSetRouteBase, joinRouteSegments } from '../routing/index.js'\nimport { getRelationshipId, isRecord, isVisibleDocsSet, toResolvedDocsSet } from './records.js'\n\nexport type PayloadMarkdownDocsLink = {\n label: string\n url: string\n}\n\nexport type GetPayloadMarkdownDocsLinksOptions = {\n collections?: Pick<PayloadMarkdownDocsCollectionSlugs, 'docsGroups' | 'docsSets'>\n overrideAccess?: boolean\n payload: PayloadMarkdownDocsReadPayload\n}\n\nconst getGroupRoutePath = ({\n groupId,\n groupsById,\n seen = new Set<string>(),\n}: {\n groupId?: string\n groupsById: Map<string, unknown>\n seen?: Set<string>\n}): string | undefined => {\n if (!groupId || seen.has(groupId)) {\n return undefined\n }\n\n const group = groupsById.get(groupId)\n\n if (!isRecord(group) || typeof group.slug !== 'string') {\n return undefined\n }\n\n return joinRouteSegments(\n getGroupRoutePath({\n groupId: getRelationshipId(group.parent),\n groupsById,\n seen: new Set([groupId, ...seen]),\n }),\n group.slug,\n )\n}\n\nexport const getPayloadMarkdownDocsLinks = async ({\n collections,\n overrideAccess = true,\n payload,\n}: GetPayloadMarkdownDocsLinksOptions): Promise<PayloadMarkdownDocsLink[]> => {\n const docsGroupsCollectionSlug = collections?.docsGroups ?? DEFAULT_DOCS_GROUPS_COLLECTION_SLUG\n const docsSetsCollectionSlug = collections?.docsSets ?? DEFAULT_DOCS_SETS_COLLECTION_SLUG\n const [docsSetsResult, docsGroupsResult] = await Promise.all([\n payload.find({\n collection: docsSetsCollectionSlug,\n depth: 0,\n draft: false,\n limit: 1000,\n overrideAccess,\n }),\n payload.find({\n collection: docsGroupsCollectionSlug,\n depth: 0,\n limit: 1000,\n overrideAccess,\n }),\n ])\n const groupsById = new Map(\n docsGroupsResult.docs.flatMap((group) => {\n if (!isRecord(group)) {\n return []\n }\n\n const id = getRelationshipId(group)\n\n return id ? [[id, group]] : []\n }),\n )\n\n return docsSetsResult.docs\n .flatMap((doc) => {\n const docsSet = toResolvedDocsSet(doc)\n\n if (!docsSet?.slug || !isRecord(doc) || !isVisibleDocsSet({ docsSet })) {\n return []\n }\n\n return [\n {\n label: docsSet.navTitle ?? docsSet.title,\n order: docsSet.order,\n url: deriveDocsSetRouteBase({\n docsSetSlug: docsSet.slug,\n groupRoutePath: getGroupRoutePath({\n groupId: getRelationshipId(doc.group),\n groupsById,\n }),\n }),\n },\n ]\n })\n .sort((first, second) => {\n if (first.order !== second.order) {\n return first.order - second.order\n }\n\n return first.label.localeCompare(second.label)\n })\n .map(({ label, url }) => ({\n label,\n url,\n }))\n}\n"],"names":["DEFAULT_DOCS_GROUPS_COLLECTION_SLUG","DEFAULT_DOCS_SETS_COLLECTION_SLUG","deriveDocsSetRouteBase","joinRouteSegments","getRelationshipId","isRecord","isVisibleDocsSet","toResolvedDocsSet","getGroupRoutePath","groupId","groupsById","seen","Set","has","undefined","group","get","slug","parent","getPayloadMarkdownDocsLinks","collections","overrideAccess","payload","docsGroupsCollectionSlug","docsGroups","docsSetsCollectionSlug","docsSets","docsSetsResult","docsGroupsResult","Promise","all","find","collection","depth","draft","limit","Map","docs","flatMap","id","doc","docsSet","label","navTitle","title","order","url","docsSetSlug","groupRoutePath","sort","first","second","localeCompare","map"],"mappings":"AAEA,SACEA,mCAAmC,EACnCC,iCAAiC,QAC5B,kBAAiB;AACxB,SAASC,sBAAsB,EAAEC,iBAAiB,QAAQ,sBAAqB;AAC/E,SAASC,iBAAiB,EAAEC,QAAQ,EAAEC,gBAAgB,EAAEC,iBAAiB,QAAQ,eAAc;AAa/F,MAAMC,oBAAoB,CAAC,EACzBC,OAAO,EACPC,UAAU,EACVC,OAAO,IAAIC,KAAa,EAKzB;IACC,IAAI,CAACH,WAAWE,KAAKE,GAAG,CAACJ,UAAU;QACjC,OAAOK;IACT;IAEA,MAAMC,QAAQL,WAAWM,GAAG,CAACP;IAE7B,IAAI,CAACJ,SAASU,UAAU,OAAOA,MAAME,IAAI,KAAK,UAAU;QACtD,OAAOH;IACT;IAEA,OAAOX,kBACLK,kBAAkB;QAChBC,SAASL,kBAAkBW,MAAMG,MAAM;QACvCR;QACAC,MAAM,IAAIC,IAAI;YAACH;eAAYE;SAAK;IAClC,IACAI,MAAME,IAAI;AAEd;AAEA,OAAO,MAAME,8BAA8B,OAAO,EAChDC,WAAW,EACXC,iBAAiB,IAAI,EACrBC,OAAO,EAC4B;IACnC,MAAMC,2BAA2BH,aAAaI,cAAcxB;IAC5D,MAAMyB,yBAAyBL,aAAaM,YAAYzB;IACxD,MAAM,CAAC0B,gBAAgBC,iBAAiB,GAAG,MAAMC,QAAQC,GAAG,CAAC;QAC3DR,QAAQS,IAAI,CAAC;YACXC,YAAYP;YACZQ,OAAO;YACPC,OAAO;YACPC,OAAO;YACPd;QACF;QACAC,QAAQS,IAAI,CAAC;YACXC,YAAYT;YACZU,OAAO;YACPE,OAAO;YACPd;QACF;KACD;IACD,MAAMX,aAAa,IAAI0B,IACrBR,iBAAiBS,IAAI,CAACC,OAAO,CAAC,CAACvB;QAC7B,IAAI,CAACV,SAASU,QAAQ;YACpB,OAAO,EAAE;QACX;QAEA,MAAMwB,KAAKnC,kBAAkBW;QAE7B,OAAOwB,KAAK;YAAC;gBAACA;gBAAIxB;aAAM;SAAC,GAAG,EAAE;IAChC;IAGF,OAAOY,eAAeU,IAAI,CACvBC,OAAO,CAAC,CAACE;QACR,MAAMC,UAAUlC,kBAAkBiC;QAElC,IAAI,CAACC,SAASxB,QAAQ,CAACZ,SAASmC,QAAQ,CAAClC,iBAAiB;YAAEmC;QAAQ,IAAI;YACtE,OAAO,EAAE;QACX;QAEA,OAAO;YACL;gBACEC,OAAOD,QAAQE,QAAQ,IAAIF,QAAQG,KAAK;gBACxCC,OAAOJ,QAAQI,KAAK;gBACpBC,KAAK5C,uBAAuB;oBAC1B6C,aAAaN,QAAQxB,IAAI;oBACzB+B,gBAAgBxC,kBAAkB;wBAChCC,SAASL,kBAAkBoC,IAAIzB,KAAK;wBACpCL;oBACF;gBACF;YACF;SACD;IACH,GACCuC,IAAI,CAAC,CAACC,OAAOC;QACZ,IAAID,MAAML,KAAK,KAAKM,OAAON,KAAK,EAAE;YAChC,OAAOK,MAAML,KAAK,GAAGM,OAAON,KAAK;QACnC;QAEA,OAAOK,MAAMR,KAAK,CAACU,aAAa,CAACD,OAAOT,KAAK;IAC/C,GACCW,GAAG,CAAC,CAAC,EAAEX,KAAK,EAAEI,GAAG,EAAE,GAAM,CAAA;YACxBJ;YACAI;QACF,CAAA;AACJ,EAAC"}
|
package/dist/next/markdown.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { DEFAULT_DOCS_COLLECTION_SLUG, DEFAULT_DOCS_GROUPS_COLLECTION_SLUG, DEFAULT_DOCS_SETS_COLLECTION_SLUG, DEFAULT_MARKDOWN_FIELD_NAME } from '../constants.js';
|
|
2
2
|
import { deriveDocsSetRouteBase, joinRouteSegments, normalizeRoutePath } from '../routing/index.js';
|
|
3
3
|
import { isExcludedFromAiExport } from '../sync/index.js';
|
|
4
|
-
import { getRelationshipId, isRecord, isVisibleDocsRecord, toResolvedDocsGroup, toResolvedDocsRecord, toResolvedDocsSet } from './records.js';
|
|
4
|
+
import { getRelationshipId, isRecord, isVisibleDocsRecord, isVisibleDocsSet, toResolvedDocsGroup, toResolvedDocsRecord, toResolvedDocsSet } from './records.js';
|
|
5
5
|
const resolveCollectionSlugs = (collections)=>({
|
|
6
6
|
docs: collections?.docs ?? DEFAULT_DOCS_COLLECTION_SLUG,
|
|
7
7
|
docsGroups: collections?.docsGroups ?? DEFAULT_DOCS_GROUPS_COLLECTION_SLUG,
|
|
@@ -75,11 +75,12 @@ const withComputedDocsSetRoute = ({ doc, docsSet, groupsById })=>{
|
|
|
75
75
|
})
|
|
76
76
|
};
|
|
77
77
|
};
|
|
78
|
-
const findDocsSetByRouteBase = async ({ collections, overrideAccess, payload, routeBase })=>{
|
|
78
|
+
const findDocsSetByRouteBase = async ({ collections, includeDrafts, overrideAccess, payload, routeBase })=>{
|
|
79
79
|
const [result, groupsById] = await Promise.all([
|
|
80
80
|
payload.find({
|
|
81
81
|
collection: collections.docsSets,
|
|
82
82
|
depth: 0,
|
|
83
|
+
draft: includeDrafts,
|
|
83
84
|
limit: 1000,
|
|
84
85
|
overrideAccess
|
|
85
86
|
}),
|
|
@@ -93,13 +94,17 @@ const findDocsSetByRouteBase = async ({ collections, overrideAccess, payload, ro
|
|
|
93
94
|
doc,
|
|
94
95
|
docsSet: toResolvedDocsSet(doc),
|
|
95
96
|
groupsById
|
|
96
|
-
})).find((docsSet)=>docsSet?.routeBase === routeBase
|
|
97
|
+
})).find((docsSet)=>docsSet?.routeBase === routeBase && isVisibleDocsSet({
|
|
98
|
+
docsSet,
|
|
99
|
+
includeDrafts
|
|
100
|
+
}));
|
|
97
101
|
};
|
|
98
|
-
const findDocsSetByAiExportOutput = async ({ collections, output, overrideAccess, payload })=>{
|
|
102
|
+
const findDocsSetByAiExportOutput = async ({ collections, includeDrafts, output, overrideAccess, payload })=>{
|
|
99
103
|
const [result, groupsById] = await Promise.all([
|
|
100
104
|
payload.find({
|
|
101
105
|
collection: collections.docsSets,
|
|
102
106
|
depth: 0,
|
|
107
|
+
draft: includeDrafts,
|
|
103
108
|
limit: 1000,
|
|
104
109
|
overrideAccess
|
|
105
110
|
}),
|
|
@@ -113,21 +118,26 @@ const findDocsSetByAiExportOutput = async ({ collections, output, overrideAccess
|
|
|
113
118
|
doc,
|
|
114
119
|
docsSet: toResolvedDocsSet(doc),
|
|
115
120
|
groupsById
|
|
116
|
-
})).find((docsSet)=>docsSet?.aiExport?.output === output
|
|
121
|
+
})).find((docsSet)=>docsSet?.aiExport?.output === output && isVisibleDocsSet({
|
|
122
|
+
docsSet,
|
|
123
|
+
includeDrafts
|
|
124
|
+
}));
|
|
117
125
|
};
|
|
118
|
-
const findDocsSetForMarkdownRoute = async ({ collections, overrideAccess, payload, route })=>{
|
|
126
|
+
const findDocsSetForMarkdownRoute = async ({ collections, includeDrafts, overrideAccess, payload, route })=>{
|
|
119
127
|
const routeBase = stripMarkdownRouteSuffix(route);
|
|
120
128
|
if (!routeBase) {
|
|
121
129
|
return undefined;
|
|
122
130
|
}
|
|
123
131
|
const docsSet = await findDocsSetByRouteBase({
|
|
124
132
|
collections,
|
|
133
|
+
includeDrafts,
|
|
125
134
|
overrideAccess,
|
|
126
135
|
payload,
|
|
127
136
|
routeBase
|
|
128
137
|
});
|
|
129
138
|
return docsSet ?? findDocsSetByAiExportOutput({
|
|
130
139
|
collections,
|
|
140
|
+
includeDrafts,
|
|
131
141
|
output: route,
|
|
132
142
|
overrideAccess,
|
|
133
143
|
payload
|
|
@@ -137,6 +147,7 @@ const getDocsRecords = async ({ collections, docsSet, includeDrafts, markdownFie
|
|
|
137
147
|
const result = await payload.find({
|
|
138
148
|
collection: collections.docs,
|
|
139
149
|
depth: 0,
|
|
150
|
+
draft: includeDrafts,
|
|
140
151
|
limit: 1000,
|
|
141
152
|
overrideAccess,
|
|
142
153
|
where: {
|
|
@@ -251,6 +262,7 @@ overrideAccess = true, path, payload })=>{
|
|
|
251
262
|
const collections = resolveCollectionSlugs(collectionOptions);
|
|
252
263
|
const docsSet = await findDocsSetForMarkdownRoute({
|
|
253
264
|
collections,
|
|
265
|
+
includeDrafts,
|
|
254
266
|
overrideAccess,
|
|
255
267
|
payload,
|
|
256
268
|
route
|