@valkyrianlabs/payload-markdown-docs 0.1.0-canary.0
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/README.md +195 -0
- package/dist/admin/DocsSetManager.d.ts +2 -0
- package/dist/admin/DocsSetManager.js +298 -0
- package/dist/admin/DocsSetManager.js.map +1 -0
- package/dist/admin/docsSetManagerData.d.ts +25 -0
- package/dist/admin/docsSetManagerData.js +266 -0
- package/dist/admin/docsSetManagerData.js.map +1 -0
- package/dist/admin/docsSetManagerTypes.d.ts +103 -0
- package/dist/admin/docsSetManagerTypes.js +3 -0
- package/dist/admin/docsSetManagerTypes.js.map +1 -0
- package/dist/admin/index.d.ts +3 -0
- package/dist/admin/index.js +4 -0
- package/dist/admin/index.js.map +1 -0
- package/dist/cli/commands/install.d.ts +2 -0
- package/dist/cli/commands/install.js +211 -0
- package/dist/cli/commands/install.js.map +1 -0
- package/dist/cli/commands/keygen.d.ts +2 -0
- package/dist/cli/commands/keygen.js +89 -0
- package/dist/cli/commands/keygen.js.map +1 -0
- package/dist/cli/commands/manifest.d.ts +2 -0
- package/dist/cli/commands/manifest.js +50 -0
- package/dist/cli/commands/manifest.js.map +1 -0
- package/dist/cli/commands/plan.d.ts +2 -0
- package/dist/cli/commands/plan.js +110 -0
- package/dist/cli/commands/plan.js.map +1 -0
- package/dist/cli/commands/push.d.ts +3 -0
- package/dist/cli/commands/push.js +308 -0
- package/dist/cli/commands/push.js.map +1 -0
- package/dist/cli/commands/validate.d.ts +3 -0
- package/dist/cli/commands/validate.js +109 -0
- package/dist/cli/commands/validate.js.map +1 -0
- package/dist/cli/filesystem.d.ts +20 -0
- package/dist/cli/filesystem.js +96 -0
- package/dist/cli/filesystem.js.map +1 -0
- package/dist/cli/format.d.ts +35 -0
- package/dist/cli/format.js +76 -0
- package/dist/cli/format.js.map +1 -0
- package/dist/cli/http.d.ts +19 -0
- package/dist/cli/http.js +39 -0
- package/dist/cli/http.js.map +1 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.js +214 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/parseArgs.d.ts +5 -0
- package/dist/cli/parseArgs.js +219 -0
- package/dist/cli/parseArgs.js.map +1 -0
- package/dist/cli/types.d.ts +51 -0
- package/dist/cli/types.js +3 -0
- package/dist/cli/types.js.map +1 -0
- package/dist/collections/docs.d.ts +9 -0
- package/dist/collections/docs.js +168 -0
- package/dist/collections/docs.js.map +1 -0
- package/dist/collections/docsGroups.d.ts +5 -0
- package/dist/collections/docsGroups.js +57 -0
- package/dist/collections/docsGroups.js.map +1 -0
- package/dist/collections/docsSets.d.ts +8 -0
- package/dist/collections/docsSets.js +158 -0
- package/dist/collections/docsSets.js.map +1 -0
- package/dist/collections/index.d.ts +10 -0
- package/dist/collections/index.js +7 -0
- package/dist/collections/index.js.map +1 -0
- package/dist/collections/nonces.d.ts +6 -0
- package/dist/collections/nonces.js +57 -0
- package/dist/collections/nonces.js.map +1 -0
- package/dist/collections/syncRuns.d.ts +5 -0
- package/dist/collections/syncRuns.js +139 -0
- package/dist/collections/syncRuns.js.map +1 -0
- package/dist/constants.d.ts +21 -0
- package/dist/constants.js +23 -0
- package/dist/constants.js.map +1 -0
- package/dist/endpoints/index.d.ts +2 -0
- package/dist/endpoints/index.js +3 -0
- package/dist/endpoints/index.js.map +1 -0
- package/dist/endpoints/sync.d.ts +47 -0
- package/dist/endpoints/sync.js +616 -0
- package/dist/endpoints/sync.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -0
- package/dist/next/PayloadMarkdownDocsPage.d.ts +7 -0
- package/dist/next/PayloadMarkdownDocsPage.js +142 -0
- package/dist/next/PayloadMarkdownDocsPage.js.map +1 -0
- package/dist/next/index.d.ts +9 -0
- package/dist/next/index.js +7 -0
- package/dist/next/index.js.map +1 -0
- package/dist/next/markdown.d.ts +14 -0
- package/dist/next/markdown.js +232 -0
- package/dist/next/markdown.js.map +1 -0
- package/dist/next/metadata.d.ts +3 -0
- package/dist/next/metadata.js +33 -0
- package/dist/next/metadata.js.map +1 -0
- package/dist/next/records.d.ts +14 -0
- package/dist/next/records.js +146 -0
- package/dist/next/records.js.map +1 -0
- package/dist/next/route.d.ts +6 -0
- package/dist/next/route.js +271 -0
- package/dist/next/route.js.map +1 -0
- package/dist/next/sidebar.d.ts +15 -0
- package/dist/next/sidebar.js +137 -0
- package/dist/next/sidebar.js.map +1 -0
- package/dist/next/types.d.ts +117 -0
- package/dist/next/types.js +3 -0
- package/dist/next/types.js.map +1 -0
- package/dist/payload/applyDocsSync.d.ts +54 -0
- package/dist/payload/applyDocsSync.js +176 -0
- package/dist/payload/applyDocsSync.js.map +1 -0
- package/dist/payload/docsConflicts.d.ts +12 -0
- package/dist/payload/docsConflicts.js +34 -0
- package/dist/payload/docsConflicts.js.map +1 -0
- package/dist/payload/docsData.d.ts +23 -0
- package/dist/payload/docsData.js +59 -0
- package/dist/payload/docsData.js.map +1 -0
- package/dist/payload/docsSets.d.ts +38 -0
- package/dist/payload/docsSets.js +57 -0
- package/dist/payload/docsSets.js.map +1 -0
- package/dist/payload/existingDocs.d.ts +43 -0
- package/dist/payload/existingDocs.js +97 -0
- package/dist/payload/existingDocs.js.map +1 -0
- package/dist/payload/index.d.ts +15 -0
- package/dist/payload/index.js +10 -0
- package/dist/payload/index.js.map +1 -0
- package/dist/payload/routeCollisions.d.ts +31 -0
- package/dist/payload/routeCollisions.js +104 -0
- package/dist/payload/routeCollisions.js.map +1 -0
- package/dist/payload/syncRuns.d.ts +60 -0
- package/dist/payload/syncRuns.js +53 -0
- package/dist/payload/syncRuns.js.map +1 -0
- package/dist/plugin.d.ts +3 -0
- package/dist/plugin.js +165 -0
- package/dist/plugin.js.map +1 -0
- package/dist/routing/index.d.ts +3 -0
- package/dist/routing/index.js +4 -0
- package/dist/routing/index.js.map +1 -0
- package/dist/routing/paths.d.ts +7 -0
- package/dist/routing/paths.js +23 -0
- package/dist/routing/paths.js.map +1 -0
- package/dist/routing/reservations.d.ts +37 -0
- package/dist/routing/reservations.js +79 -0
- package/dist/routing/reservations.js.map +1 -0
- package/dist/security/canonical.d.ts +12 -0
- package/dist/security/canonical.js +24 -0
- package/dist/security/canonical.js.map +1 -0
- package/dist/security/githubOidc.d.ts +45 -0
- package/dist/security/githubOidc.js +177 -0
- package/dist/security/githubOidc.js.map +1 -0
- package/dist/security/headers.d.ts +22 -0
- package/dist/security/headers.js +44 -0
- package/dist/security/headers.js.map +1 -0
- package/dist/security/index.d.ts +15 -0
- package/dist/security/index.js +9 -0
- package/dist/security/index.js.map +1 -0
- package/dist/security/jwks.d.ts +20 -0
- package/dist/security/jwks.js +40 -0
- package/dist/security/jwks.js.map +1 -0
- package/dist/security/jwt.d.ts +10 -0
- package/dist/security/jwt.js +42 -0
- package/dist/security/jwt.js.map +1 -0
- package/dist/security/nonce.d.ts +34 -0
- package/dist/security/nonce.js +43 -0
- package/dist/security/nonce.js.map +1 -0
- package/dist/security/sign.d.ts +13 -0
- package/dist/security/sign.js +39 -0
- package/dist/security/sign.js.map +1 -0
- package/dist/security/verify.d.ts +28 -0
- package/dist/security/verify.js +54 -0
- package/dist/security/verify.js.map +1 -0
- package/dist/skills/codex/SKILL.md +173 -0
- package/dist/skills/codex/examples/docs-page.md +42 -0
- package/dist/skills/codex/examples/github-actions.md +64 -0
- package/dist/skills/codex/reference/admin.md +28 -0
- package/dist/skills/codex/reference/frontmatter.md +39 -0
- package/dist/skills/codex/reference/payload-markdown-directives.md +77 -0
- package/dist/skills/codex/reference/routing.md +35 -0
- package/dist/skills/codex/reference/sync.md +35 -0
- package/dist/skills/codex/reference/troubleshooting.md +53 -0
- package/dist/skills/codex/reference/workflow.md +39 -0
- package/dist/sync/aiExportManifest.d.ts +58 -0
- package/dist/sync/aiExportManifest.js +430 -0
- package/dist/sync/aiExportManifest.js.map +1 -0
- package/dist/sync/frontmatter.d.ts +28 -0
- package/dist/sync/frontmatter.js +210 -0
- package/dist/sync/frontmatter.js.map +1 -0
- package/dist/sync/hash.d.ts +1 -0
- package/dist/sync/hash.js +8 -0
- package/dist/sync/hash.js.map +1 -0
- package/dist/sync/index.d.ts +12 -0
- package/dist/sync/index.js +9 -0
- package/dist/sync/index.js.map +1 -0
- package/dist/sync/manifest.d.ts +58 -0
- package/dist/sync/manifest.js +21 -0
- package/dist/sync/manifest.js.map +1 -0
- package/dist/sync/paths.d.ts +16 -0
- package/dist/sync/paths.js +116 -0
- package/dist/sync/paths.js.map +1 -0
- package/dist/sync/plan.d.ts +29 -0
- package/dist/sync/plan.js +72 -0
- package/dist/sync/plan.js.map +1 -0
- package/dist/sync/validate.d.ts +26 -0
- package/dist/sync/validate.js +308 -0
- package/dist/sync/validate.js.map +1 -0
- package/dist/types.d.ts +84 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/package.json +143 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/endpoints/sync.ts"],"sourcesContent":["import type { Endpoint, PayloadRequest } from 'payload'\n\nimport type {\n ApplyDocsSyncPayloadOperations,\n DocsPublishMode,\n DocsSetPayloadOperations,\n ExistingDocsPayloadOperations,\n ExistingPayloadDocsRecord,\n ResolvedDocsSet,\n RouteCollisionPayloadOperations,\n SyncRunsPayloadOperations,\n} from '../payload/index.js'\nimport type {\n FetchJson,\n NoncePayloadOperations,\n} from '../security/index.js'\nimport type {\n DocsDeleteBehavior,\n DocsManifest,\n DocsValidationIssue,\n PlannedDocChange,\n ValidatedDocsManifest,\n} from '../sync/index.js'\nimport type { PayloadMarkdownDocsAuthConfig } from '../types.js'\n\nimport {\n DEFAULT_DOCS_ROUTE_BASE,\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 findDocsSetBySourceId,\n findDocsSyncConflicts,\n findDuplicateDesiredRouteCollisions,\n findExistingDocsRouteCollisions,\n findExistingPayloadDocsRecords,\n getRecordId,\n toExistingDocsRecord,\n updateDocsSetAfterSync,\n updateSyncRunAudit,\n} from '../payload/index.js'\nimport {\n assertNonceNotReplayed,\n buildCanonicalSigningString,\n extractSyncRequestHeaders,\n getCanonicalPathFromRequestUrl,\n storeAcceptedNonce,\n validateTimestampSkew,\n verifyBodySha256,\n verifyEd25519Signature,\n verifyGitHubOidcToken,\n} from '../security/index.js'\nimport {\n planDocsSync,\n validateDocsManifest,\n} from '../sync/index.js'\n\nexport type DocsSyncEndpointErrorCode =\n | 'audit_unavailable'\n | 'auth_disabled'\n | 'body_hash_mismatch'\n | 'delete_behavior_not_implemented'\n | 'draft_behavior_not_available'\n | 'dry_run_required_not_implemented'\n | 'hard_delete_disabled'\n | 'invalid_body'\n | 'invalid_manifest'\n | 'invalid_method'\n | 'invalid_signature'\n | 'invalid_timestamp'\n | 'manual_edit_conflict'\n | 'missing_header'\n | 'nonce_replay'\n | 'oidc_environment_not_allowed'\n | 'oidc_expired'\n | 'oidc_invalid_audience'\n | 'oidc_invalid_issuer'\n | 'oidc_invalid_token'\n | 'oidc_jwks_unavailable'\n | 'oidc_missing_claim'\n | 'oidc_missing_jti'\n | 'oidc_not_yet_valid'\n | 'oidc_owner_not_allowed'\n | 'oidc_pull_request_not_allowed'\n | 'oidc_ref_not_allowed'\n | 'oidc_replay'\n | 'oidc_repository_not_allowed'\n | 'oidc_workflow_not_allowed'\n | 'publish_disabled'\n | 'publish_not_available'\n | 'replay_protection_unavailable'\n | 'route_collision'\n | 'source_not_allowed'\n | 'sync_apply_failed'\n | 'sync_mode_not_implemented'\n | 'sync_writes_disabled'\n | 'unknown_key'\n\nexport type CreateSyncEndpointOptions = {\n allowHardDelete?: boolean\n allowPublish?: boolean\n allowWrites?: boolean\n auth?: PayloadMarkdownDocsAuthConfig\n defaultPublishMode?: DocsPublishMode\n deleteBehavior?: DocsDeleteBehavior\n docsCollectionSlug: string\n docsEnabled: boolean\n docsEnableDrafts: boolean\n docsSetsCollectionSlug: string\n docsSetsEnabled: 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 routeBase?: string\n routing?: {\n pages?: {\n allowBridgePages: boolean\n bridgeField: string\n collection: string\n enabled: boolean\n routeField: string\n }\n }\n sources?: {\n id: string\n root?: string\n routeBase: string\n }[]\n syncRunsCollectionSlug: string\n syncRunsEnabled: boolean\n}\n\ntype SyncErrorResponse = {\n conflicts?: {\n reason: string\n route?: string\n sourcePath: string\n }[]\n error: {\n code: DocsSyncEndpointErrorCode\n message: string\n }\n ok: false\n routeCollisions?: {\n reason: string\n route: string\n }[]\n}\n\ntype SerializedChange = {\n current?: {\n archived?: boolean\n route: string\n sourceHash?: string\n title?: string\n }\n desired?: {\n route: string\n sha256: string\n title: string\n }\n reason: string\n sourcePath: string\n}\n\ntype SyncSuccessResponse = {\n changes: {\n archive: SerializedChange[]\n create: SerializedChange[]\n delete: SerializedChange[]\n draft: SerializedChange[]\n unchanged: SerializedChange[]\n update: SerializedChange[]\n }\n deleteBehavior: DocsDeleteBehavior\n dryRun: boolean\n effectivePublishMode: DocsPublishMode\n ok: true\n publishRequested: boolean\n summary: {\n archive: number\n create: number\n delete: number\n draft: number\n unchanged: number\n update: number\n warnings: number\n }\n syncRunId?: string\n warnings: DocsValidationIssue[]\n}\n\nconst jsonResponse = (\n body: SyncErrorResponse | SyncSuccessResponse,\n status = 200,\n): Response =>\n Response.json(body, {\n status,\n })\n\nconst errorResponse = (\n code: DocsSyncEndpointErrorCode,\n message: string,\n status = 400,\n extras: Omit<SyncErrorResponse, 'error' | 'ok'> = {},\n): Response =>\n jsonResponse(\n {\n ...extras,\n error: {\n code,\n message,\n },\n ok: false,\n },\n status,\n )\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === 'object' && value !== null && !Array.isArray(value)\n\nconst parseManifestBody = (rawBody: string): DocsManifest | undefined => {\n try {\n const parsed = JSON.parse(rawBody) as unknown\n\n return isRecord(parsed) ? (parsed as DocsManifest) : undefined\n } catch {\n return undefined\n }\n}\n\nconst findSourceConfig = (\n sourceId: string,\n sources: CreateSyncEndpointOptions['sources'],\n) => sources?.find((source) => source.id === sourceId)\n\nconst getAllowedSourceIds = (\n sources: CreateSyncEndpointOptions['sources'],\n): string[] | undefined => {\n if (!sources || sources.length === 0) {\n return undefined\n }\n\n return sources.map((source) => source.id)\n}\n\ntype ResolvedSyncSource = {\n allowedSourceIds?: string[]\n docsSet?: ResolvedDocsSet\n routeBase: string\n sourceRoot?: 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 source: {\n allowedSourceIds: getAllowedSourceIds(options.sources),\n routeBase: options.routeBase ?? DEFAULT_DOCS_ROUTE_BASE,\n },\n }\n }\n\n const docsSet =\n options.docsSetsEnabled\n ? await findDocsSetBySourceId({\n collectionSlug: options.docsSetsCollectionSlug,\n payload,\n sourceId,\n })\n : undefined\n\n if (docsSet) {\n if (\n docsSet.sourceRoot &&\n manifest.source.root &&\n docsSet.sourceRoot !== manifest.source.root\n ) {\n return {\n response: errorResponse(\n 'source_not_allowed',\n `Manifest source.root \"${manifest.source.root}\" is not allowed for docs set source \"${sourceId}\".`,\n 400,\n ),\n }\n }\n\n return {\n source: {\n allowedSourceIds: [sourceId],\n docsSet,\n routeBase: docsSet.routeBase,\n sourceRoot: docsSet.sourceRoot,\n },\n }\n }\n\n const sourceConfig = findSourceConfig(sourceId, options.sources)\n\n if (options.sources && options.sources.length > 0 && !sourceConfig) {\n return {\n response: errorResponse(\n 'source_not_allowed',\n `Manifest source.id \"${sourceId}\" is not configured for this endpoint.`,\n 400,\n ),\n }\n }\n\n if (\n sourceConfig?.root &&\n manifest.source.root &&\n sourceConfig.root !== manifest.source.root\n ) {\n return {\n response: errorResponse(\n 'source_not_allowed',\n `Manifest source.root \"${manifest.source.root}\" is not allowed for source \"${sourceId}\".`,\n 400,\n ),\n }\n }\n\n return {\n source: {\n allowedSourceIds: getAllowedSourceIds(options.sources),\n routeBase: sourceConfig?.routeBase ?? options.routeBase ?? DEFAULT_DOCS_ROUTE_BASE,\n sourceRoot: sourceConfig?.root,\n },\n }\n}\n\nconst summarizePlan = (plan: ReturnType<typeof planDocsSync>) => ({\n archive: plan.archive.length,\n create: plan.create.length,\n delete: plan.delete.length,\n draft: plan.draft.length,\n unchanged: plan.unchanged.length,\n update: plan.update.length,\n warnings: plan.warnings.length,\n})\n\nconst serializeChange = (change: PlannedDocChange): SerializedChange => ({\n current: change.current\n ? {\n archived: change.current.archived,\n route: change.current.route,\n sourceHash: change.current.sourceHash,\n title: change.current.title,\n }\n : undefined,\n desired: change.desired\n ? {\n route: change.desired.route,\n sha256: change.desired.sha256,\n title: change.desired.title,\n }\n : undefined,\n reason: change.reason,\n sourcePath: change.sourcePath,\n})\n\nconst serializeChanges = (plan: ReturnType<typeof planDocsSync>) => ({\n archive: plan.archive.map(serializeChange),\n create: plan.create.map(serializeChange),\n delete: plan.delete.map(serializeChange),\n draft: plan.draft.map(serializeChange),\n unchanged: plan.unchanged.map(serializeChange),\n update: plan.update.map(serializeChange),\n})\n\nconst getTotalManifestBytes = (manifest: ValidatedDocsManifest): number =>\n manifest.files.reduce(\n (total, file) => total + Buffer.byteLength(file.content, 'utf8'),\n 0,\n )\n\nconst getPlannedConflictChanges = ({\n existing,\n plan,\n}: {\n existing: ExistingPayloadDocsRecord[]\n plan: ReturnType<typeof planDocsSync>\n}): PlannedDocChange[] => {\n const existingBySourcePath = new Map(\n existing.map((record) => [record.sourcePath, record]),\n )\n const archivedUnchanged = plan.unchanged.filter((change) => {\n const current = existingBySourcePath.get(change.sourcePath)\n\n return current?.archived === true\n })\n\n return [\n ...plan.update,\n ...plan.archive,\n ...plan.draft,\n ...plan.delete,\n ...archivedUnchanged,\n ]\n}\n\nconst getDefaultPublishMode = (\n options: CreateSyncEndpointOptions,\n): DocsPublishMode =>\n options.defaultPublishMode ?? (options.docsEnableDrafts ? 'draft' : 'preserve')\n\nconst getLifecyclePolicyError = ({\n deleteBehavior,\n manifest,\n options,\n publishMode,\n}: {\n deleteBehavior: DocsDeleteBehavior\n manifest: ValidatedDocsManifest\n options: CreateSyncEndpointOptions\n publishMode: DocsPublishMode\n}): Response | undefined => {\n if (manifest.publish && options.allowPublish !== true) {\n return errorResponse(\n 'publish_disabled',\n 'Publishing is disabled by server configuration.',\n 403,\n )\n }\n\n if (\n (manifest.publish || publishMode === 'published') &&\n !options.docsEnableDrafts\n ) {\n return errorResponse(\n 'publish_not_available',\n 'Publishing requires a draft-enabled dedicated docs collection.',\n 400,\n )\n }\n\n if (publishMode === 'published' && options.allowPublish !== true) {\n return errorResponse(\n 'publish_disabled',\n 'Publishing is disabled by server configuration.',\n 403,\n )\n }\n\n if (publishMode === 'draft' && !options.docsEnableDrafts) {\n return errorResponse(\n 'draft_behavior_not_available',\n 'Draft mode requires a draft-enabled dedicated docs collection.',\n 400,\n )\n }\n\n if (deleteBehavior === 'draft' && !options.docsEnableDrafts) {\n return errorResponse(\n 'draft_behavior_not_available',\n 'Draft delete behavior requires a draft-enabled dedicated docs collection.',\n 400,\n )\n }\n\n if (deleteBehavior === 'delete' && options.allowHardDelete !== true) {\n return errorResponse(\n 'hard_delete_disabled',\n 'Hard delete is disabled by server configuration.',\n 403,\n )\n }\n\n return undefined\n}\n\nconst getRouteCollisionIssues = async ({\n docsSet,\n manifest,\n options,\n payload,\n routeBase,\n}: {\n docsSet?: ResolvedDocsSet\n manifest: ValidatedDocsManifest\n options: CreateSyncEndpointOptions\n payload: RouteCollisionPayloadOperations\n routeBase: string\n}) => {\n const desiredRoutes = manifest.files.map((file) => file.route)\n const duplicateDesiredRouteCollisions =\n findDuplicateDesiredRouteCollisions(desiredRoutes)\n const existingDocsRouteCollisions = options.docsEnabled\n ? await findExistingDocsRouteCollisions({\n collectionSlug: options.docsCollectionSlug,\n docsSetId: docsSet?.id,\n payload,\n routes: desiredRoutes,\n sourceId: manifest.source.id,\n })\n : []\n const pageRouteCollisions =\n options.routing?.pages?.enabled === true\n ? await findConfiguredPagesRouteCollisions({\n allowBridgePages: options.routing.pages.allowBridgePages,\n bridgeField: options.routing.pages.bridgeField,\n collectionSlug: options.routing.pages.collection,\n docsSetRouteBase: routeBase,\n payload,\n routeField: options.routing.pages.routeField,\n })\n : []\n\n return [\n ...duplicateDesiredRouteCollisions,\n ...existingDocsRouteCollisions,\n ...pageRouteCollisions,\n ]\n}\n\ntype AuthenticatedSyncRequest = {\n actor?: string\n bodyHash: string\n branch?: string\n commit?: string\n expiresAt: Date\n keyId: string\n nonce: string\n repository?: string\n}\n\nconst getRequiredHeader = (\n headers: Headers,\n name: string,\n): string | undefined => {\n const value = headers.get(name)\n\n return value && value.trim() !== '' ? value.trim() : undefined\n}\n\nconst getBearerToken = (headers: Headers): string | undefined => {\n const authorization = getRequiredHeader(headers, 'authorization')\n\n if (!authorization) {\n return undefined\n }\n\n const [scheme, token] = authorization.split(/\\s+/, 2)\n\n if (scheme?.toLowerCase() !== 'bearer' || !token) {\n return ''\n }\n\n return token\n}\n\nconst 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 if (!options.auth || options.auth.mode !== 'ed25519') {\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 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 const keyConfig = options.auth.keys.find(\n (key) => key.id === headersResult.headers.keyId,\n )\n\n if (!keyConfig) {\n return {\n response: errorResponse('unknown_key', 'Unknown sync request key id.', 401),\n }\n }\n\n const bodyHash = verifyBodySha256({\n body: rawBody,\n expectedHash: headersResult.headers.bodySha256,\n })\n\n if (!bodyHash.ok) {\n return {\n response: errorResponse(\n 'body_hash_mismatch',\n 'Sync request body hash does not match the signed header.',\n 401,\n ),\n }\n }\n\n const timestampValidation = validateTimestampSkew({\n maxSkewSeconds:\n options.auth.maxSkewSeconds ??\n options.maxSkewSeconds ??\n DEFAULT_MAX_SKEW_SECONDS,\n now,\n timestamp: headersResult.headers.timestamp,\n })\n\n if (!timestampValidation.ok) {\n return {\n response: errorResponse(\n 'invalid_timestamp',\n timestampValidation.message,\n 401,\n ),\n }\n }\n\n const replayUnavailable = assertReplayProtectionAvailable(options)\n\n if (replayUnavailable) {\n return {\n response: replayUnavailable,\n }\n }\n\n const nonceAvailable = await assertNonceNotReplayed({\n collectionSlug: options.noncesCollectionSlug,\n keyId: headersResult.headers.keyId,\n nonce: headersResult.headers.nonce,\n now,\n payload: req.payload as unknown as NoncePayloadOperations,\n })\n\n if (!nonceAvailable) {\n return {\n response: errorResponse(\n 'nonce_replay',\n 'Sync request nonce has already been used.',\n 409,\n ),\n }\n }\n\n const canonicalPath = getCanonicalPathFromRequestUrl({\n endpointPath: options.endpointPath,\n url: req.url,\n })\n const canonicalString = buildCanonicalSigningString({\n bodySha256: bodyHash.computedHash,\n method: 'POST',\n nonce: headersResult.headers.nonce,\n path: canonicalPath,\n timestamp: headersResult.headers.timestamp,\n })\n\n if (\n !verifyEd25519Signature({\n canonicalString,\n publicKey: keyConfig.publicKey,\n signature: headersResult.headers.signature,\n })\n ) {\n return {\n response: errorResponse(\n 'invalid_signature',\n 'Invalid sync request signature.',\n 401,\n ),\n }\n }\n\n const nonceTtlSeconds =\n options.auth.nonceTtlSeconds ??\n options.nonceTtlSeconds ??\n 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 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 if (!options.auth || options.auth.mode !== 'github-oidc') {\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 const token = getBearerToken(req.headers)\n\n if (token === undefined) {\n return {\n response: errorResponse(\n 'missing_header',\n 'Missing required sync header: Authorization.',\n 401,\n ),\n }\n }\n\n if (token === '') {\n return {\n response: errorResponse(\n 'oidc_invalid_token',\n 'Authorization must be a Bearer GitHub OIDC token.',\n 401,\n ),\n }\n }\n\n const expectedHash = getRequiredHeader(\n req.headers,\n 'x-vl-md-docs-body-sha256',\n )\n\n if (!expectedHash) {\n return {\n response: errorResponse(\n 'missing_header',\n 'Missing required sync header: X-VL-MD-DOCS-Body-SHA256.',\n 401,\n ),\n }\n }\n\n const bodyHash = verifyBodySha256({\n body: rawBody,\n expectedHash,\n })\n\n if (!bodyHash.ok) {\n return {\n response: errorResponse(\n 'body_hash_mismatch',\n 'Sync request body hash does not match the OIDC header.',\n 401,\n ),\n }\n }\n\n const verified = await verifyGitHubOidcToken({\n config: options.auth,\n fetchJson: options.oidcFetchJson,\n now,\n token,\n })\n\n if (!verified.ok) {\n return {\n response: errorResponse(\n verified.code,\n verified.message,\n verified.code === 'oidc_jwks_unavailable' ? 503 : 401,\n ),\n }\n }\n\n const replayUnavailable = assertReplayProtectionAvailable(options)\n\n if (replayUnavailable) {\n return {\n response: replayUnavailable,\n }\n }\n\n const nonceAvailable = await assertNonceNotReplayed({\n collectionSlug: options.noncesCollectionSlug,\n keyId: verified.token.keyId,\n nonce: verified.token.claims.jti,\n now,\n payload: req.payload as unknown as NoncePayloadOperations,\n })\n\n if (!nonceAvailable) {\n return {\n response: errorResponse(\n 'oidc_replay',\n 'GitHub OIDC token jti has already been used.',\n 409,\n ),\n }\n }\n\n return {\n identity: {\n actor: verified.token.claims.actor,\n bodyHash: bodyHash.computedHash,\n branch: verified.token.claims.ref,\n commit: verified.token.claims.sha,\n expiresAt: verified.token.expiresAt,\n keyId: verified.token.keyId,\n nonce: verified.token.claims.jti,\n repository: verified.token.claims.repository,\n },\n }\n}\n\nconst authenticateSyncRequest = async ({\n 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 if (!options.auth || options.auth.mode === 'disabled') {\n return {\n response: errorResponse(\n 'auth_disabled',\n 'Sync authentication is not configured for this endpoint.',\n 401,\n ),\n }\n }\n\n if (options.auth.mode === 'github-oidc') {\n return authenticateGitHubOidcRequest({\n now,\n options,\n rawBody,\n req,\n })\n }\n\n return authenticateEd25519Request({\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 authentication = await authenticateSyncRequest({\n now: startedAt,\n options,\n rawBody,\n req,\n })\n\n if (authentication.response) {\n return authentication.response\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 validation = validateDocsManifest(manifest, {\n allowedSourceIds: sourceResolution.source.allowedSourceIds,\n maxTotalBytes: maxBodyBytes,\n routeBase: sourceResolution.source.routeBase,\n })\n\n if (!validation.ok) {\n return jsonResponse(\n {\n error: {\n code: 'invalid_manifest',\n message: 'Sync manifest is invalid.',\n },\n ok: false,\n },\n 400,\n )\n }\n\n const effectiveDeleteBehavior = options.deleteBehavior ?? 'archive'\n const effectivePublishMode: DocsPublishMode = validation.data.publish\n ? 'published'\n : getDefaultPublishMode(options)\n const lifecyclePolicyError = getLifecyclePolicyError({\n deleteBehavior: effectiveDeleteBehavior,\n manifest: validation.data,\n options,\n publishMode: effectivePublishMode,\n })\n\n if (lifecyclePolicyError) {\n return lifecyclePolicyError\n }\n\n const routeCollisions = await getRouteCollisionIssues({\n docsSet: sourceResolution.source.docsSet,\n manifest: validation.data,\n options,\n payload: req.payload as unknown as RouteCollisionPayloadOperations,\n routeBase: sourceResolution.source.routeBase,\n })\n\n if (routeCollisions.length > 0) {\n return errorResponse(\n 'route_collision',\n 'One or more docs routes collide with an existing route reservation.',\n 409,\n {\n routeCollisions,\n },\n )\n }\n\n const isSyncMode = validation.data.mode === 'sync'\n\n if (isSyncMode && options.allowWrites !== true) {\n return errorResponse(\n 'sync_writes_disabled',\n 'Sync writes are disabled by server configuration.',\n 403,\n )\n }\n\n if (isSyncMode && options.requireDryRunBeforeApply === true) {\n return errorResponse(\n 'dry_run_required_not_implemented',\n 'Required dry-run proof before apply is not implemented yet.',\n 400,\n )\n }\n\n if (\n isSyncMode &&\n !assertApplyDeleteBehaviorSupported(effectiveDeleteBehavior, {\n allowHardDelete: options.allowHardDelete,\n docsEnableDrafts: options.docsEnableDrafts,\n })\n ) {\n return errorResponse(\n 'delete_behavior_not_implemented',\n 'Configured delete behavior cannot be applied.',\n 400,\n )\n }\n\n if (isSyncMode && !options.syncRunsEnabled) {\n return errorResponse(\n 'audit_unavailable',\n 'Applied sync requires the sync-run audit collection.',\n 500,\n )\n }\n\n const existingPayloadDocs = options.docsEnabled\n ? await findExistingPayloadDocsRecords({\n collectionSlug: options.docsCollectionSlug,\n docsSetId: sourceResolution.source.docsSet?.id,\n markdownFieldName: options.markdownFieldName,\n payload: req.payload as unknown as ExistingDocsPayloadOperations,\n sourceId: validation.data.source.id,\n })\n : []\n const existingDocs = existingPayloadDocs.map(toExistingDocsRecord)\n const plan = planDocsSync({\n deleteBehavior: effectiveDeleteBehavior,\n desired: validation.data,\n existing: existingDocs,\n })\n const summary = summarizePlan(plan)\n const warnings = [...validation.warnings, ...plan.warnings]\n if (isSyncMode) {\n const existingBySourcePath = new Map(\n existingPayloadDocs.map((record) => [record.sourcePath, record]),\n )\n const conflicts = findDocsSyncConflicts({\n existingBySourcePath,\n plannedChanges: getPlannedConflictChanges({\n existing: existingPayloadDocs,\n plan,\n }),\n })\n\n if (conflicts.length > 0) {\n return errorResponse(\n 'manual_edit_conflict',\n 'One or more docs were modified outside the docs sync workflow.',\n 409,\n {\n conflicts,\n },\n )\n }\n }\n\n await storeAcceptedNonce({\n bodyHash: authentication.identity.bodyHash,\n collectionSlug: options.noncesCollectionSlug,\n expiresAt: authentication.identity.expiresAt,\n keyId: authentication.identity.keyId,\n nonce: authentication.identity.nonce,\n payload: req.payload as unknown as NoncePayloadOperations,\n sourceId: validation.data.source.id,\n usedAt: startedAt,\n })\n\n let syncRunId: number | string | undefined\n\n if (options.syncRunsEnabled) {\n const syncRun = await createSyncRunAudit({\n actor: authentication.identity.actor,\n bodyHash: authentication.identity.bodyHash,\n branch: authentication.identity.branch ?? validation.data.source.branch,\n collectionSlug: options.syncRunsCollectionSlug,\n commit: authentication.identity.commit ?? validation.data.source.commit,\n completedAt: isSyncMode ? startedAt : options.getNow?.() ?? new Date(),\n deleteBehavior: effectiveDeleteBehavior,\n effectivePublishMode,\n errors: [],\n fileCount: validation.data.files.length,\n keyId: authentication.identity.keyId,\n mode: isSyncMode ? 'sync' : 'dry-run',\n payload: req.payload as unknown as SyncRunsPayloadOperations,\n publishRequested: validation.data.publish,\n repository:\n authentication.identity.repository ?? validation.data.source.repository,\n sourceId: validation.data.source.id,\n startedAt,\n status: isSyncMode ? 'pending' : 'success',\n summary,\n totalBytes: getTotalManifestBytes(validation.data),\n warnings,\n })\n\n syncRunId = getRecordId(syncRun)\n }\n\n if (isSyncMode) {\n if (!syncRunId) {\n return errorResponse(\n 'audit_unavailable',\n 'Applied sync could not create a sync-run audit record.',\n 500,\n )\n }\n\n try {\n const applyResult = await applyDocsSync({\n collectionSlug: options.docsCollectionSlug,\n deleteBehavior: effectiveDeleteBehavior,\n docsEnableDrafts: options.docsEnableDrafts,\n docsSetId: sourceResolution.source.docsSet?.id,\n existing: existingPayloadDocs,\n manifest: validation.data,\n markdownFieldName: options.markdownFieldName,\n now: options.getNow?.() ?? new Date(),\n payload: req.payload as unknown as ApplyDocsSyncPayloadOperations,\n plan,\n publishMode: effectivePublishMode,\n syncRunId,\n })\n\n if (!applyResult.ok) {\n return errorResponse(\n 'manual_edit_conflict',\n 'One or more docs were modified outside the docs sync workflow.',\n 409,\n {\n conflicts: applyResult.conflicts,\n },\n )\n }\n\n await updateSyncRunAudit({\n collectionSlug: options.syncRunsCollectionSlug,\n completedAt: options.getNow?.() ?? new Date(),\n payload: req.payload as unknown as SyncRunsPayloadOperations,\n status: 'success',\n summary,\n syncRunId,\n warnings,\n })\n\n if (sourceResolution.source.docsSet) {\n await updateDocsSetAfterSync({\n aiExport: validation.data.aiExport,\n collectionSlug: options.docsSetsCollectionSlug,\n docsCount: validation.data.files.length,\n docsSetId: sourceResolution.source.docsSet.id,\n now: options.getNow?.() ?? new Date(),\n payload: req.payload as unknown as DocsSetPayloadOperations,\n syncRunId,\n })\n }\n } catch (error) {\n await updateSyncRunAudit({\n collectionSlug: options.syncRunsCollectionSlug,\n completedAt: options.getNow?.() ?? new Date(),\n errors: [\n {\n code: 'invalid_manifest',\n message: error instanceof Error ? error.message : 'Sync apply failed.',\n },\n ],\n payload: req.payload as unknown as SyncRunsPayloadOperations,\n status: 'failed',\n summary,\n syncRunId,\n warnings,\n })\n\n return errorResponse('sync_apply_failed', 'Sync apply failed.', 500)\n }\n }\n\n return jsonResponse({\n changes: serializeChanges(plan),\n deleteBehavior: effectiveDeleteBehavior,\n dryRun: !isSyncMode,\n effectivePublishMode,\n ok: true,\n publishRequested: validation.data.publish,\n summary,\n syncRunId: syncRunId === undefined ? undefined : String(syncRunId),\n warnings,\n })\n }\n\nexport const createSyncEndpoint = (options: CreateSyncEndpointOptions): Endpoint => ({\n handler: createSyncEndpointHandler(options),\n method: 'post',\n path: options.endpointPath,\n})\n"],"names":["DEFAULT_DOCS_ROUTE_BASE","DEFAULT_MAX_BODY_BYTES","DEFAULT_MAX_SKEW_SECONDS","DEFAULT_NONCE_TTL_SECONDS","applyDocsSync","assertApplyDeleteBehaviorSupported","createSyncRunAudit","findConfiguredPagesRouteCollisions","findDocsSetBySourceId","findDocsSyncConflicts","findDuplicateDesiredRouteCollisions","findExistingDocsRouteCollisions","findExistingPayloadDocsRecords","getRecordId","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","findSourceConfig","sourceId","sources","find","source","id","getAllowedSourceIds","length","map","resolveSyncSource","manifest","options","payload","allowedSourceIds","routeBase","docsSet","docsSetsEnabled","collectionSlug","docsSetsCollectionSlug","sourceRoot","root","response","sourceConfig","summarizePlan","plan","archive","create","delete","draft","unchanged","update","warnings","serializeChange","change","current","archived","route","sourceHash","title","desired","sha256","reason","sourcePath","serializeChanges","getTotalManifestBytes","files","reduce","total","file","Buffer","byteLength","content","getPlannedConflictChanges","existing","existingBySourcePath","Map","record","archivedUnchanged","filter","get","getDefaultPublishMode","defaultPublishMode","docsEnableDrafts","getLifecyclePolicyError","deleteBehavior","publishMode","publish","allowPublish","allowHardDelete","getRouteCollisionIssues","desiredRoutes","duplicateDesiredRouteCollisions","existingDocsRouteCollisions","docsEnabled","docsCollectionSlug","docsSetId","routes","pageRouteCollisions","routing","pages","enabled","allowBridgePages","bridgeField","collection","docsSetRouteBase","routeField","getRequiredHeader","headers","name","trim","getBearerToken","authorization","scheme","token","split","toLowerCase","assertReplayProtectionAvailable","noncesEnabled","authenticateEd25519Request","now","req","auth","mode","headersResult","header","keyConfig","keys","key","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","verified","config","fetchJson","oidcFetchJson","claims","jti","actor","branch","ref","commit","sha","repository","authenticateSyncRequest","createSyncEndpointHandler","startedAt","getNow","toUpperCase","text","maxBodyBytes","authentication","sourceResolution","validation","maxTotalBytes","effectiveDeleteBehavior","effectivePublishMode","data","lifecyclePolicyError","routeCollisions","isSyncMode","allowWrites","requireDryRunBeforeApply","syncRunsEnabled","existingPayloadDocs","markdownFieldName","existingDocs","summary","conflicts","plannedChanges","usedAt","syncRunId","syncRun","syncRunsCollectionSlug","completedAt","errors","fileCount","publishRequested","totalBytes","applyResult","aiExport","docsCount","Error","changes","dryRun","String","createSyncEndpoint","handler"],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export { DEFAULT_DOCS_COLLECTION_SLUG, DEFAULT_DOCS_GROUPS_COLLECTION_SLUG, DEFAULT_DOCS_ROUTE_BASE, DEFAULT_DOCS_SETS_COLLECTION_SLUG, DEFAULT_DOCS_SYNC_ENDPOINT_PATH, DEFAULT_DOCS_SYNC_NONCES_COLLECTION_SLUG, DEFAULT_DOCS_SYNC_RUNS_COLLECTION_SLUG, DEFAULT_MARKDOWN_FIELD_NAME, DEFAULT_MAX_BODY_BYTES, DEFAULT_MAX_DOCS_FILE_BYTES, DEFAULT_MAX_DOCS_FILES, DEFAULT_MAX_DOCS_TOTAL_BYTES, DEFAULT_MAX_SKEW_SECONDS, DEFAULT_NONCE_TTL_SECONDS, DEFAULT_PAGES_BRIDGE_FIELD, DEFAULT_PAGES_COLLECTION_SLUG, DEFAULT_PAGES_ROUTE_FIELD, DOCS_SET_MANAGER_COMPONENT, } from './constants.js';
|
|
2
|
+
export { payloadMarkdownDocs } from './plugin.js';
|
|
3
|
+
export { deriveDocsSetRouteBase, findPageRouteCollisions, findRouteReservationCollisions, isRouteDescendant, joinRouteSegments, normalizeRoutePath, } from './routing/index.js';
|
|
4
|
+
export type { DocsRouteCollision, DocsRouteCollisionReason, DocsRouteReservation, DocsRouteReservationOwnerType, } from './routing/index.js';
|
|
5
|
+
export { signDocsSyncRequest } from './security/index.js';
|
|
6
|
+
export type { SignDocsSyncRequestOptions, SignedDocsSyncRequest, } from './security/index.js';
|
|
7
|
+
export { buildDocsManifest, deriveRouteFromSourcePath, inferTitleFromMarkdown, normalizeDocsPath, parseDocsFrontmatter, planDocsSync, resolveDocsTitle, sha256Hex, titleFromSourcePath, validateDocsManifest, } from './sync/index.js';
|
|
8
|
+
export type { DocsDeleteBehavior, DocsFrontmatter, DocsManifest, DocsManifestFile, DocsManifestInputFile, DocsManifestSource, DocsSyncMode, DocsSyncPlan, DocsValidationErrorCode, DocsValidationIssue, DocsValidationOptions, DocsValidationResult, ExistingDocsRecord, ParseDocsFrontmatterResult, PlannedDocChange, ValidatedDocsManifest, ValidatedDocsManifestFile, } from './sync/index.js';
|
|
9
|
+
export type { PayloadMarkdownDocsAuthConfig, PayloadMarkdownDocsCollectionConfig, PayloadMarkdownDocsCollectionsConfig, PayloadMarkdownDocsConfig, PayloadMarkdownDocsEd25519Key, PayloadMarkdownDocsEndpointConfig, PayloadMarkdownDocsPagesRoutingConfig, PayloadMarkdownDocsRoutingConfig, PayloadMarkdownDocsSourceConfig, PayloadMarkdownDocsSyncConfig, PayloadMarkdownDocsTargetConfig, } from './types.js';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { DEFAULT_DOCS_COLLECTION_SLUG, DEFAULT_DOCS_GROUPS_COLLECTION_SLUG, DEFAULT_DOCS_ROUTE_BASE, DEFAULT_DOCS_SETS_COLLECTION_SLUG, DEFAULT_DOCS_SYNC_ENDPOINT_PATH, DEFAULT_DOCS_SYNC_NONCES_COLLECTION_SLUG, DEFAULT_DOCS_SYNC_RUNS_COLLECTION_SLUG, DEFAULT_MARKDOWN_FIELD_NAME, DEFAULT_MAX_BODY_BYTES, DEFAULT_MAX_DOCS_FILE_BYTES, DEFAULT_MAX_DOCS_FILES, DEFAULT_MAX_DOCS_TOTAL_BYTES, DEFAULT_MAX_SKEW_SECONDS, DEFAULT_NONCE_TTL_SECONDS, DEFAULT_PAGES_BRIDGE_FIELD, DEFAULT_PAGES_COLLECTION_SLUG, DEFAULT_PAGES_ROUTE_FIELD, DOCS_SET_MANAGER_COMPONENT } from './constants.js';
|
|
2
|
+
export { payloadMarkdownDocs } from './plugin.js';
|
|
3
|
+
export { deriveDocsSetRouteBase, findPageRouteCollisions, findRouteReservationCollisions, isRouteDescendant, joinRouteSegments, normalizeRoutePath } from './routing/index.js';
|
|
4
|
+
export { signDocsSyncRequest } from './security/index.js';
|
|
5
|
+
export { buildDocsManifest, deriveRouteFromSourcePath, inferTitleFromMarkdown, normalizeDocsPath, parseDocsFrontmatter, planDocsSync, resolveDocsTitle, sha256Hex, titleFromSourcePath, validateDocsManifest } from './sync/index.js';
|
|
6
|
+
|
|
7
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["export {\n DEFAULT_DOCS_COLLECTION_SLUG,\n DEFAULT_DOCS_GROUPS_COLLECTION_SLUG,\n DEFAULT_DOCS_ROUTE_BASE,\n DEFAULT_DOCS_SETS_COLLECTION_SLUG,\n DEFAULT_DOCS_SYNC_ENDPOINT_PATH,\n DEFAULT_DOCS_SYNC_NONCES_COLLECTION_SLUG,\n DEFAULT_DOCS_SYNC_RUNS_COLLECTION_SLUG,\n DEFAULT_MARKDOWN_FIELD_NAME,\n DEFAULT_MAX_BODY_BYTES,\n DEFAULT_MAX_DOCS_FILE_BYTES,\n DEFAULT_MAX_DOCS_FILES,\n DEFAULT_MAX_DOCS_TOTAL_BYTES,\n DEFAULT_MAX_SKEW_SECONDS,\n DEFAULT_NONCE_TTL_SECONDS,\n DEFAULT_PAGES_BRIDGE_FIELD,\n DEFAULT_PAGES_COLLECTION_SLUG,\n DEFAULT_PAGES_ROUTE_FIELD,\n DOCS_SET_MANAGER_COMPONENT,\n} from './constants.js'\nexport { payloadMarkdownDocs } from './plugin.js'\nexport {\n deriveDocsSetRouteBase,\n findPageRouteCollisions,\n findRouteReservationCollisions,\n isRouteDescendant,\n joinRouteSegments,\n normalizeRoutePath,\n} from './routing/index.js'\nexport type {\n DocsRouteCollision,\n DocsRouteCollisionReason,\n DocsRouteReservation,\n DocsRouteReservationOwnerType,\n} from './routing/index.js'\nexport { signDocsSyncRequest } from './security/index.js'\nexport type {\n SignDocsSyncRequestOptions,\n SignedDocsSyncRequest,\n} from './security/index.js'\nexport {\n buildDocsManifest,\n deriveRouteFromSourcePath,\n inferTitleFromMarkdown,\n normalizeDocsPath,\n parseDocsFrontmatter,\n planDocsSync,\n resolveDocsTitle,\n sha256Hex,\n titleFromSourcePath,\n validateDocsManifest,\n} from './sync/index.js'\nexport type {\n DocsDeleteBehavior,\n DocsFrontmatter,\n DocsManifest,\n DocsManifestFile,\n DocsManifestInputFile,\n DocsManifestSource,\n DocsSyncMode,\n DocsSyncPlan,\n DocsValidationErrorCode,\n DocsValidationIssue,\n DocsValidationOptions,\n DocsValidationResult,\n ExistingDocsRecord,\n ParseDocsFrontmatterResult,\n PlannedDocChange,\n ValidatedDocsManifest,\n ValidatedDocsManifestFile,\n} from './sync/index.js'\nexport type {\n PayloadMarkdownDocsAuthConfig,\n PayloadMarkdownDocsCollectionConfig,\n PayloadMarkdownDocsCollectionsConfig,\n PayloadMarkdownDocsConfig,\n PayloadMarkdownDocsEd25519Key,\n PayloadMarkdownDocsEndpointConfig,\n PayloadMarkdownDocsPagesRoutingConfig,\n PayloadMarkdownDocsRoutingConfig,\n PayloadMarkdownDocsSourceConfig,\n PayloadMarkdownDocsSyncConfig,\n PayloadMarkdownDocsTargetConfig,\n} from './types.js'\n"],"names":["DEFAULT_DOCS_COLLECTION_SLUG","DEFAULT_DOCS_GROUPS_COLLECTION_SLUG","DEFAULT_DOCS_ROUTE_BASE","DEFAULT_DOCS_SETS_COLLECTION_SLUG","DEFAULT_DOCS_SYNC_ENDPOINT_PATH","DEFAULT_DOCS_SYNC_NONCES_COLLECTION_SLUG","DEFAULT_DOCS_SYNC_RUNS_COLLECTION_SLUG","DEFAULT_MARKDOWN_FIELD_NAME","DEFAULT_MAX_BODY_BYTES","DEFAULT_MAX_DOCS_FILE_BYTES","DEFAULT_MAX_DOCS_FILES","DEFAULT_MAX_DOCS_TOTAL_BYTES","DEFAULT_MAX_SKEW_SECONDS","DEFAULT_NONCE_TTL_SECONDS","DEFAULT_PAGES_BRIDGE_FIELD","DEFAULT_PAGES_COLLECTION_SLUG","DEFAULT_PAGES_ROUTE_FIELD","DOCS_SET_MANAGER_COMPONENT","payloadMarkdownDocs","deriveDocsSetRouteBase","findPageRouteCollisions","findRouteReservationCollisions","isRouteDescendant","joinRouteSegments","normalizeRoutePath","signDocsSyncRequest","buildDocsManifest","deriveRouteFromSourcePath","inferTitleFromMarkdown","normalizeDocsPath","parseDocsFrontmatter","planDocsSync","resolveDocsTitle","sha256Hex","titleFromSourcePath","validateDocsManifest"],"mappings":"AAAA,SACEA,4BAA4B,EAC5BC,mCAAmC,EACnCC,uBAAuB,EACvBC,iCAAiC,EACjCC,+BAA+B,EAC/BC,wCAAwC,EACxCC,sCAAsC,EACtCC,2BAA2B,EAC3BC,sBAAsB,EACtBC,2BAA2B,EAC3BC,sBAAsB,EACtBC,4BAA4B,EAC5BC,wBAAwB,EACxBC,yBAAyB,EACzBC,0BAA0B,EAC1BC,6BAA6B,EAC7BC,yBAAyB,EACzBC,0BAA0B,QACrB,iBAAgB;AACvB,SAASC,mBAAmB,QAAQ,cAAa;AACjD,SACEC,sBAAsB,EACtBC,uBAAuB,EACvBC,8BAA8B,EAC9BC,iBAAiB,EACjBC,iBAAiB,EACjBC,kBAAkB,QACb,qBAAoB;AAO3B,SAASC,mBAAmB,QAAQ,sBAAqB;AAKzD,SACEC,iBAAiB,EACjBC,yBAAyB,EACzBC,sBAAsB,EACtBC,iBAAiB,EACjBC,oBAAoB,EACpBC,YAAY,EACZC,gBAAgB,EAChBC,SAAS,EACTC,mBAAmB,EACnBC,oBAAoB,QACf,kBAAiB"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { ResolvedPayloadMarkdownDocsRoute } from './types.js';
|
|
2
|
+
export type PayloadMarkdownDocsPageProps = {
|
|
3
|
+
collectionSlug?: string;
|
|
4
|
+
renderSidebar?: boolean;
|
|
5
|
+
resolved: ResolvedPayloadMarkdownDocsRoute;
|
|
6
|
+
};
|
|
7
|
+
export declare const PayloadMarkdownDocsPage: ({ collectionSlug, renderSidebar, resolved, }: PayloadMarkdownDocsPageProps) => Promise<import("react/jsx-runtime").JSX.Element>;
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { DEFAULT_DOCS_COLLECTION_SLUG } from '../constants.js';
|
|
3
|
+
const cx = (...values)=>values.filter(Boolean).join(' ');
|
|
4
|
+
const renderSidebarItems = (items, activeRoute, depth = 0)=>{
|
|
5
|
+
if (items.length === 0) {
|
|
6
|
+
return null;
|
|
7
|
+
}
|
|
8
|
+
return /*#__PURE__*/ _jsx("ul", {
|
|
9
|
+
className: cx(depth === 0 ? 'space-y-1' : 'ml-3 mt-1 space-y-1 border-l border-border pl-3'),
|
|
10
|
+
children: items.map((item)=>/*#__PURE__*/ _jsxs("li", {
|
|
11
|
+
children: [
|
|
12
|
+
/*#__PURE__*/ _jsx("a", {
|
|
13
|
+
className: cx('block rounded-lg px-3 py-2 text-sm leading-5 transition-colors', item.route === activeRoute ? 'bg-cyan-400/10 text-cyan-200' : 'text-foreground/70 hover:bg-white/[0.04] hover:text-foreground'),
|
|
14
|
+
href: item.route,
|
|
15
|
+
children: item.label
|
|
16
|
+
}),
|
|
17
|
+
item.children ? renderSidebarItems(item.children, activeRoute, depth + 1) : null
|
|
18
|
+
]
|
|
19
|
+
}, item.route))
|
|
20
|
+
});
|
|
21
|
+
};
|
|
22
|
+
const renderMarkdown = async ({ collectionSlug, markdown })=>{
|
|
23
|
+
if (!markdown?.trim()) {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
const { MarkdownRenderer } = await import('@valkyrianlabs/payload-markdown/server');
|
|
27
|
+
return MarkdownRenderer({
|
|
28
|
+
className: 'min-w-0',
|
|
29
|
+
collectionSlug,
|
|
30
|
+
markdown,
|
|
31
|
+
scope: 'field',
|
|
32
|
+
size: 'md',
|
|
33
|
+
variant: 'docs',
|
|
34
|
+
wrapperClassName: 'min-w-0'
|
|
35
|
+
});
|
|
36
|
+
};
|
|
37
|
+
const DocsHeader = ({ doc, docsSet })=>{
|
|
38
|
+
const description = doc?.overrides?.heroDescription ?? doc?.description ?? docsSet.defaults?.heroDescription ?? docsSet.description;
|
|
39
|
+
const title = doc?.overrides?.heroTitle ?? doc?.title ?? docsSet.defaults?.heroTitle ?? docsSet.title;
|
|
40
|
+
return /*#__PURE__*/ _jsxs("header", {
|
|
41
|
+
className: "mb-10 border-b border-border pb-8",
|
|
42
|
+
children: [
|
|
43
|
+
docsSet.defaults?.heroEyebrow ? /*#__PURE__*/ _jsx("p", {
|
|
44
|
+
className: "mb-3 text-sm font-medium uppercase tracking-wide text-cyan-300",
|
|
45
|
+
children: docsSet.defaults.heroEyebrow
|
|
46
|
+
}) : null,
|
|
47
|
+
/*#__PURE__*/ _jsx("h1", {
|
|
48
|
+
className: "text-4xl font-semibold tracking-tight text-foreground md:text-5xl",
|
|
49
|
+
children: title
|
|
50
|
+
}),
|
|
51
|
+
description ? /*#__PURE__*/ _jsx("p", {
|
|
52
|
+
className: "mt-4 max-w-3xl text-lg leading-8 text-foreground/70",
|
|
53
|
+
children: description
|
|
54
|
+
}) : null
|
|
55
|
+
]
|
|
56
|
+
});
|
|
57
|
+
};
|
|
58
|
+
export const PayloadMarkdownDocsPage = async ({ collectionSlug = DEFAULT_DOCS_COLLECTION_SLUG, renderSidebar = true, resolved })=>{
|
|
59
|
+
if (resolved.type === 'docsGroupIndex') {
|
|
60
|
+
return /*#__PURE__*/ _jsx("main", {
|
|
61
|
+
className: "min-h-screen bg-background text-foreground",
|
|
62
|
+
"data-payload-markdown-docs-route": resolved.route,
|
|
63
|
+
children: /*#__PURE__*/ _jsxs("div", {
|
|
64
|
+
className: "mx-auto w-full max-w-6xl px-6 py-14 lg:px-8",
|
|
65
|
+
children: [
|
|
66
|
+
/*#__PURE__*/ _jsxs("header", {
|
|
67
|
+
className: "mb-10 border-b border-border pb-8",
|
|
68
|
+
children: [
|
|
69
|
+
/*#__PURE__*/ _jsx("p", {
|
|
70
|
+
className: "mb-3 text-sm font-medium uppercase tracking-wide text-cyan-300",
|
|
71
|
+
children: "Docs"
|
|
72
|
+
}),
|
|
73
|
+
/*#__PURE__*/ _jsx("h1", {
|
|
74
|
+
className: "text-4xl font-semibold tracking-tight md:text-5xl",
|
|
75
|
+
children: resolved.group.navTitle ?? resolved.group.title
|
|
76
|
+
}),
|
|
77
|
+
resolved.group.description ? /*#__PURE__*/ _jsx("p", {
|
|
78
|
+
className: "mt-4 max-w-3xl text-lg leading-8 text-foreground/70",
|
|
79
|
+
children: resolved.group.description
|
|
80
|
+
}) : null
|
|
81
|
+
]
|
|
82
|
+
}),
|
|
83
|
+
resolved.docsSets.length > 0 ? /*#__PURE__*/ _jsx("nav", {
|
|
84
|
+
"aria-label": "Docs sets",
|
|
85
|
+
children: /*#__PURE__*/ _jsx("ul", {
|
|
86
|
+
className: "grid gap-4 sm:grid-cols-2 lg:grid-cols-3",
|
|
87
|
+
children: resolved.docsSets.map((docsSet)=>/*#__PURE__*/ _jsx("li", {
|
|
88
|
+
children: /*#__PURE__*/ _jsxs("a", {
|
|
89
|
+
className: "block rounded-xl border border-border bg-white/[0.03] p-5 transition-colors hover:bg-white/[0.06]",
|
|
90
|
+
href: docsSet.routeBase,
|
|
91
|
+
children: [
|
|
92
|
+
/*#__PURE__*/ _jsx("span", {
|
|
93
|
+
className: "text-base font-semibold text-foreground",
|
|
94
|
+
children: docsSet.navTitle ?? docsSet.title
|
|
95
|
+
}),
|
|
96
|
+
docsSet.description ? /*#__PURE__*/ _jsx("span", {
|
|
97
|
+
className: "mt-2 block text-sm leading-6 text-foreground/65",
|
|
98
|
+
children: docsSet.description
|
|
99
|
+
}) : null
|
|
100
|
+
]
|
|
101
|
+
})
|
|
102
|
+
}, docsSet.id))
|
|
103
|
+
})
|
|
104
|
+
}) : null
|
|
105
|
+
]
|
|
106
|
+
})
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
const markdown = await renderMarkdown({
|
|
110
|
+
collectionSlug,
|
|
111
|
+
markdown: resolved.doc?.content
|
|
112
|
+
});
|
|
113
|
+
return /*#__PURE__*/ _jsx("main", {
|
|
114
|
+
className: "min-h-screen bg-background text-foreground",
|
|
115
|
+
"data-payload-markdown-docs-route": resolved.route,
|
|
116
|
+
children: /*#__PURE__*/ _jsxs("div", {
|
|
117
|
+
className: cx('mx-auto grid w-full max-w-7xl gap-10 px-6 py-10 lg:px-8', renderSidebar && resolved.sidebar.length > 0 ? 'lg:grid-cols-[16rem_minmax(0,1fr)]' : 'lg:grid-cols-[minmax(0,1fr)]'),
|
|
118
|
+
children: [
|
|
119
|
+
renderSidebar && resolved.sidebar.length > 0 ? /*#__PURE__*/ _jsx("aside", {
|
|
120
|
+
className: "lg:sticky lg:top-8 lg:self-start",
|
|
121
|
+
children: /*#__PURE__*/ _jsx("nav", {
|
|
122
|
+
"aria-label": "Docs navigation",
|
|
123
|
+
className: "rounded-xl border border-border bg-white/[0.03] p-3",
|
|
124
|
+
children: renderSidebarItems(resolved.sidebar, resolved.route)
|
|
125
|
+
})
|
|
126
|
+
}) : null,
|
|
127
|
+
/*#__PURE__*/ _jsxs("article", {
|
|
128
|
+
className: "min-w-0 max-w-4xl",
|
|
129
|
+
children: [
|
|
130
|
+
/*#__PURE__*/ _jsx(DocsHeader, {
|
|
131
|
+
doc: resolved.doc,
|
|
132
|
+
docsSet: resolved.docsSet
|
|
133
|
+
}),
|
|
134
|
+
markdown
|
|
135
|
+
]
|
|
136
|
+
})
|
|
137
|
+
]
|
|
138
|
+
})
|
|
139
|
+
});
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
//# sourceMappingURL=PayloadMarkdownDocsPage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/next/PayloadMarkdownDocsPage.tsx"],"sourcesContent":["import type { ReactNode } from 'react'\n\nimport type {\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 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(\n depth === 0\n ? 'space-y-1'\n : 'ml-3 mt-1 space-y-1 border-l border-border pl-3',\n )}\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\n ? renderSidebarItems(item.children, activeRoute, depth + 1)\n : 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 =\n doc?.overrides?.heroDescription ??\n doc?.description ??\n docsSet.defaults?.heroDescription ??\n docsSet.description\n const title =\n doc?.overrides?.heroTitle ??\n doc?.title ??\n docsSet.defaults?.heroTitle ??\n docsSet.title\n\n return (\n <header className=\"mb-10 border-b border-border pb-8\">\n {docsSet.defaults?.heroEyebrow ? (\n <p className=\"mb-3 text-sm font-medium uppercase tracking-wide text-cyan-300\">\n {docsSet.defaults.heroEyebrow}\n </p>\n ) : null}\n <h1 className=\"text-4xl font-semibold tracking-tight text-foreground md:text-5xl\">\n {title}\n </h1>\n {description ? (\n <p className=\"mt-4 max-w-3xl text-lg leading-8 text-foreground/70\">\n {description}\n </p>\n ) : null}\n </header>\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\">\n Docs\n </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\n return (\n <main\n className=\"min-h-screen bg-background text-foreground\"\n data-payload-markdown-docs-route={resolved.route}\n >\n <div\n className={cx(\n 'mx-auto grid w-full max-w-7xl gap-10 px-6 py-10 lg:px-8',\n renderSidebar && resolved.sidebar.length > 0\n ? 'lg:grid-cols-[16rem_minmax(0,1fr)]'\n : 'lg:grid-cols-[minmax(0,1fr)]',\n )}\n >\n {renderSidebar && resolved.sidebar.length > 0 ? (\n <aside className=\"lg:sticky lg:top-8 lg:self-start\">\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 <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","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","overrides","heroDescription","defaults","title","heroTitle","header","heroEyebrow","p","h1","PayloadMarkdownDocsPage","renderSidebar","resolved","type","main","data-payload-markdown-docs-route","div","group","navTitle","docsSets","nav","aria-label","routeBase","span","id","content","sidebar","aside","article"],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export { createPayloadMarkdownDocsMarkdownResponse, resolvePayloadMarkdownDocsMarkdownRoute, } from './markdown.js';
|
|
2
|
+
export type { ResolvedPayloadMarkdownDocsMarkdownRoute, ResolvePayloadMarkdownDocsMarkdownRouteOptions, } from './markdown.js';
|
|
3
|
+
export { generatePayloadMarkdownDocsMetadata, getPayloadMarkdownDocsMetadata, } from './metadata.js';
|
|
4
|
+
export { PayloadMarkdownDocsPage } from './PayloadMarkdownDocsPage.js';
|
|
5
|
+
export type { PayloadMarkdownDocsPageProps } from './PayloadMarkdownDocsPage.js';
|
|
6
|
+
export { getPayloadMarkdownDocsRoutePath, resolvePayloadMarkdownDocsRoute, } from './route.js';
|
|
7
|
+
export { buildPayloadMarkdownDocsSidebar, getPayloadMarkdownDocsSidebar, } from './sidebar.js';
|
|
8
|
+
export type { BuildPayloadMarkdownDocsSidebarOptions, GetPayloadMarkdownDocsSidebarOptions, } from './sidebar.js';
|
|
9
|
+
export type { PayloadMarkdownDocsCollectionSlugs, PayloadMarkdownDocsDefaults, PayloadMarkdownDocsFindArgs, PayloadMarkdownDocsMetadata, PayloadMarkdownDocsOverrides, PayloadMarkdownDocsReadPayload, PayloadMarkdownDocsSidebarItem, ResolvedPayloadMarkdownDocsGroup, ResolvedPayloadMarkdownDocsRecord, ResolvedPayloadMarkdownDocsRoute, ResolvedPayloadMarkdownDocsSet, ResolvePayloadMarkdownDocsRouteOptions, } from './types.js';
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { createPayloadMarkdownDocsMarkdownResponse, resolvePayloadMarkdownDocsMarkdownRoute } from './markdown.js';
|
|
2
|
+
export { generatePayloadMarkdownDocsMetadata, getPayloadMarkdownDocsMetadata } from './metadata.js';
|
|
3
|
+
export { PayloadMarkdownDocsPage } from './PayloadMarkdownDocsPage.js';
|
|
4
|
+
export { getPayloadMarkdownDocsRoutePath, resolvePayloadMarkdownDocsRoute } from './route.js';
|
|
5
|
+
export { buildPayloadMarkdownDocsSidebar, getPayloadMarkdownDocsSidebar } from './sidebar.js';
|
|
6
|
+
|
|
7
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/next/index.ts"],"sourcesContent":["export {\n createPayloadMarkdownDocsMarkdownResponse,\n resolvePayloadMarkdownDocsMarkdownRoute,\n} from './markdown.js'\nexport type {\n ResolvedPayloadMarkdownDocsMarkdownRoute,\n ResolvePayloadMarkdownDocsMarkdownRouteOptions,\n} from './markdown.js'\nexport {\n generatePayloadMarkdownDocsMetadata,\n getPayloadMarkdownDocsMetadata,\n} from './metadata.js'\nexport { PayloadMarkdownDocsPage } from './PayloadMarkdownDocsPage.js'\nexport type { PayloadMarkdownDocsPageProps } from './PayloadMarkdownDocsPage.js'\nexport {\n getPayloadMarkdownDocsRoutePath,\n resolvePayloadMarkdownDocsRoute,\n} from './route.js'\nexport {\n buildPayloadMarkdownDocsSidebar,\n getPayloadMarkdownDocsSidebar,\n} from './sidebar.js'\nexport type {\n BuildPayloadMarkdownDocsSidebarOptions,\n GetPayloadMarkdownDocsSidebarOptions,\n} from './sidebar.js'\nexport type {\n PayloadMarkdownDocsCollectionSlugs,\n PayloadMarkdownDocsDefaults,\n PayloadMarkdownDocsFindArgs,\n PayloadMarkdownDocsMetadata,\n PayloadMarkdownDocsOverrides,\n PayloadMarkdownDocsReadPayload,\n PayloadMarkdownDocsSidebarItem,\n ResolvedPayloadMarkdownDocsGroup,\n ResolvedPayloadMarkdownDocsRecord,\n ResolvedPayloadMarkdownDocsRoute,\n ResolvedPayloadMarkdownDocsSet,\n ResolvePayloadMarkdownDocsRouteOptions,\n} from './types.js'\n"],"names":["createPayloadMarkdownDocsMarkdownResponse","resolvePayloadMarkdownDocsMarkdownRoute","generatePayloadMarkdownDocsMetadata","getPayloadMarkdownDocsMetadata","PayloadMarkdownDocsPage","getPayloadMarkdownDocsRoutePath","resolvePayloadMarkdownDocsRoute","buildPayloadMarkdownDocsSidebar","getPayloadMarkdownDocsSidebar"],"mappings":"AAAA,SACEA,yCAAyC,EACzCC,uCAAuC,QAClC,gBAAe;AAKtB,SACEC,mCAAmC,EACnCC,8BAA8B,QACzB,gBAAe;AACtB,SAASC,uBAAuB,QAAQ,+BAA8B;AAEtE,SACEC,+BAA+B,EAC/BC,+BAA+B,QAC1B,aAAY;AACnB,SACEC,+BAA+B,EAC/BC,6BAA6B,QACxB,eAAc"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { DocsValidationIssue } from '../sync/index.js';
|
|
2
|
+
import type { ResolvedPayloadMarkdownDocsSet, ResolvePayloadMarkdownDocsRouteOptions } from './types.js';
|
|
3
|
+
export type ResolvedPayloadMarkdownDocsMarkdownRoute = {
|
|
4
|
+
contentType: 'text/markdown; charset=utf-8';
|
|
5
|
+
docsSet: ResolvedPayloadMarkdownDocsSet;
|
|
6
|
+
markdown: string;
|
|
7
|
+
output: string;
|
|
8
|
+
route: string;
|
|
9
|
+
type: 'markdown';
|
|
10
|
+
warnings: DocsValidationIssue[];
|
|
11
|
+
};
|
|
12
|
+
export type ResolvePayloadMarkdownDocsMarkdownRouteOptions = ResolvePayloadMarkdownDocsRouteOptions;
|
|
13
|
+
export declare const resolvePayloadMarkdownDocsMarkdownRoute: ({ slug, collections: collectionOptions, includeDrafts, markdownField, overrideAccess, path, payload, }: ResolvePayloadMarkdownDocsMarkdownRouteOptions) => Promise<null | ResolvedPayloadMarkdownDocsMarkdownRoute>;
|
|
14
|
+
export declare const createPayloadMarkdownDocsMarkdownResponse: (options: ResolvePayloadMarkdownDocsMarkdownRouteOptions) => Promise<null | Response>;
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
import { DEFAULT_DOCS_COLLECTION_SLUG, DEFAULT_DOCS_GROUPS_COLLECTION_SLUG, DEFAULT_DOCS_SETS_COLLECTION_SLUG, DEFAULT_MARKDOWN_FIELD_NAME } from '../constants.js';
|
|
2
|
+
import { normalizeRoutePath } from '../routing/index.js';
|
|
3
|
+
import { isExcludedFromAiExport } from '../sync/index.js';
|
|
4
|
+
import { isVisibleDocsRecord, toResolvedDocsRecord, toResolvedDocsSet } from './records.js';
|
|
5
|
+
const resolveCollectionSlugs = (collections)=>({
|
|
6
|
+
docs: collections?.docs ?? DEFAULT_DOCS_COLLECTION_SLUG,
|
|
7
|
+
docsGroups: collections?.docsGroups ?? DEFAULT_DOCS_GROUPS_COLLECTION_SLUG,
|
|
8
|
+
docsSets: collections?.docsSets ?? DEFAULT_DOCS_SETS_COLLECTION_SLUG
|
|
9
|
+
});
|
|
10
|
+
const getRoutePath = ({ slug, path })=>{
|
|
11
|
+
if (path !== undefined) {
|
|
12
|
+
return normalizeRoutePath(path);
|
|
13
|
+
}
|
|
14
|
+
if (Array.isArray(slug)) {
|
|
15
|
+
return normalizeRoutePath(slug.length === 0 ? '/' : slug.join('/'));
|
|
16
|
+
}
|
|
17
|
+
if (typeof slug === 'string') {
|
|
18
|
+
return normalizeRoutePath(slug);
|
|
19
|
+
}
|
|
20
|
+
return '/';
|
|
21
|
+
};
|
|
22
|
+
const stripMarkdownRouteSuffix = (route)=>route.toLowerCase().endsWith('.md') ? route.slice(0, -3) : undefined;
|
|
23
|
+
const findDocsSetByRouteBase = async ({ collections, overrideAccess, payload, routeBase })=>{
|
|
24
|
+
const result = await payload.find({
|
|
25
|
+
collection: collections.docsSets,
|
|
26
|
+
depth: 0,
|
|
27
|
+
limit: 1,
|
|
28
|
+
overrideAccess,
|
|
29
|
+
where: {
|
|
30
|
+
routeBase: {
|
|
31
|
+
equals: routeBase
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
return result.docs.map(toResolvedDocsSet).find((docsSet)=>docsSet?.routeBase === routeBase);
|
|
36
|
+
};
|
|
37
|
+
const findDocsSetByAiExportOutput = async ({ collections, output, overrideAccess, payload })=>{
|
|
38
|
+
const result = await payload.find({
|
|
39
|
+
collection: collections.docsSets,
|
|
40
|
+
depth: 0,
|
|
41
|
+
limit: 1000,
|
|
42
|
+
overrideAccess
|
|
43
|
+
});
|
|
44
|
+
return result.docs.map(toResolvedDocsSet).find((docsSet)=>docsSet?.aiExport?.output === output);
|
|
45
|
+
};
|
|
46
|
+
const findDocsSetForMarkdownRoute = async ({ collections, overrideAccess, payload, route })=>{
|
|
47
|
+
const routeBase = stripMarkdownRouteSuffix(route);
|
|
48
|
+
if (!routeBase) {
|
|
49
|
+
return undefined;
|
|
50
|
+
}
|
|
51
|
+
const docsSet = await findDocsSetByRouteBase({
|
|
52
|
+
collections,
|
|
53
|
+
overrideAccess,
|
|
54
|
+
payload,
|
|
55
|
+
routeBase
|
|
56
|
+
});
|
|
57
|
+
return docsSet ?? findDocsSetByAiExportOutput({
|
|
58
|
+
collections,
|
|
59
|
+
output: route,
|
|
60
|
+
overrideAccess,
|
|
61
|
+
payload
|
|
62
|
+
});
|
|
63
|
+
};
|
|
64
|
+
const getDocsRecords = async ({ collections, docsSet, includeDrafts, markdownField, overrideAccess, payload })=>{
|
|
65
|
+
const result = await payload.find({
|
|
66
|
+
collection: collections.docs,
|
|
67
|
+
depth: 0,
|
|
68
|
+
limit: 1000,
|
|
69
|
+
overrideAccess,
|
|
70
|
+
where: {
|
|
71
|
+
docsSet: {
|
|
72
|
+
equals: docsSet.id
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
return result.docs.map((doc)=>toResolvedDocsRecord({
|
|
77
|
+
doc,
|
|
78
|
+
markdownField
|
|
79
|
+
})).filter((record)=>record !== undefined && isVisibleDocsRecord({
|
|
80
|
+
includeDrafts,
|
|
81
|
+
record
|
|
82
|
+
}));
|
|
83
|
+
};
|
|
84
|
+
const compareDocsRecords = (first, second)=>{
|
|
85
|
+
if (first.order !== second.order) {
|
|
86
|
+
return first.order - second.order;
|
|
87
|
+
}
|
|
88
|
+
const titleCompare = first.title.localeCompare(second.title);
|
|
89
|
+
if (titleCompare !== 0) {
|
|
90
|
+
return titleCompare;
|
|
91
|
+
}
|
|
92
|
+
const pathCompare = first.sourcePath.localeCompare(second.sourcePath);
|
|
93
|
+
return pathCompare !== 0 ? pathCompare : first.id.localeCompare(second.id);
|
|
94
|
+
};
|
|
95
|
+
const getDefaultAiExportManifest = (docsSet)=>({
|
|
96
|
+
canonical: docsSet.routeBase,
|
|
97
|
+
exclude: [],
|
|
98
|
+
headingMode: 'normalize',
|
|
99
|
+
order: [],
|
|
100
|
+
orphans: 'append',
|
|
101
|
+
output: `${docsSet.routeBase}.md`,
|
|
102
|
+
sourcePath: 'fallback',
|
|
103
|
+
title: docsSet.title,
|
|
104
|
+
version: 1
|
|
105
|
+
});
|
|
106
|
+
const orderDocsRecords = ({ manifest, records })=>{
|
|
107
|
+
const recordsBySourcePath = new Map(records.map((record)=>[
|
|
108
|
+
record.sourcePath,
|
|
109
|
+
record
|
|
110
|
+
]));
|
|
111
|
+
const listedRecords = [];
|
|
112
|
+
const listedSourcePaths = new Set();
|
|
113
|
+
const warnings = [];
|
|
114
|
+
for (const orderedPath of manifest.order){
|
|
115
|
+
listedSourcePaths.add(orderedPath);
|
|
116
|
+
const record = recordsBySourcePath.get(orderedPath);
|
|
117
|
+
if (!record) {
|
|
118
|
+
warnings.push({
|
|
119
|
+
code: 'missing_ai_export_order_path',
|
|
120
|
+
message: `AI export manifest order path "${orderedPath}" does not exist in the generated docs records.`,
|
|
121
|
+
path: manifest.sourcePath
|
|
122
|
+
});
|
|
123
|
+
continue;
|
|
124
|
+
}
|
|
125
|
+
listedRecords.push(record);
|
|
126
|
+
}
|
|
127
|
+
if (manifest.orphans === 'ignore') {
|
|
128
|
+
return {
|
|
129
|
+
ordered: listedRecords,
|
|
130
|
+
warnings
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
const orphans = records.filter((record)=>!listedSourcePaths.has(record.sourcePath)).sort(compareDocsRecords);
|
|
134
|
+
return {
|
|
135
|
+
ordered: [
|
|
136
|
+
...listedRecords,
|
|
137
|
+
...orphans
|
|
138
|
+
],
|
|
139
|
+
warnings
|
|
140
|
+
};
|
|
141
|
+
};
|
|
142
|
+
const shiftMarkdownHeadings = (markdown)=>markdown.replace(/^(#{1,6})(\s+)/gm, (match, hashes, whitespace)=>hashes.length >= 5 ? `${'#'.repeat(6)}${whitespace}` : `${hashes}##${whitespace}`);
|
|
143
|
+
const sectionTitle = (record)=>record.title.trim() || record.sourcePath;
|
|
144
|
+
const renderMarkdownExport = ({ docsSet, manifest, records })=>{
|
|
145
|
+
const lines = [];
|
|
146
|
+
const title = manifest.title ?? docsSet.title;
|
|
147
|
+
const canonical = manifest.canonical ?? docsSet.routeBase;
|
|
148
|
+
const output = manifest.output ?? `${docsSet.routeBase}.md`;
|
|
149
|
+
lines.push(`# ${title}`);
|
|
150
|
+
lines.push('');
|
|
151
|
+
lines.push(`Canonical: ${canonical}`);
|
|
152
|
+
lines.push(`Output: ${output}`);
|
|
153
|
+
if (manifest.description) {
|
|
154
|
+
lines.push('', manifest.description.trim());
|
|
155
|
+
}
|
|
156
|
+
if (manifest.preamble) {
|
|
157
|
+
lines.push('', manifest.preamble.trim());
|
|
158
|
+
}
|
|
159
|
+
for (const record of records){
|
|
160
|
+
const content = record.content?.trim();
|
|
161
|
+
if (!content) {
|
|
162
|
+
continue;
|
|
163
|
+
}
|
|
164
|
+
if (manifest.headingMode === 'preserve') {
|
|
165
|
+
lines.push('', content);
|
|
166
|
+
continue;
|
|
167
|
+
}
|
|
168
|
+
lines.push('', `## ${sectionTitle(record)}`, '', shiftMarkdownHeadings(content));
|
|
169
|
+
}
|
|
170
|
+
return `${lines.join('\n').replace(/\n{4,}/g, '\n\n\n').trimEnd()}\n`;
|
|
171
|
+
};
|
|
172
|
+
export const resolvePayloadMarkdownDocsMarkdownRoute = async ({ slug, collections: collectionOptions, includeDrafts = false, markdownField = DEFAULT_MARKDOWN_FIELD_NAME, // Route adapter reads plugin-owned generated docs collections server-side.
|
|
173
|
+
// Access is overridden here, then public visibility and manifest exclusions are enforced.
|
|
174
|
+
overrideAccess = true, path, payload })=>{
|
|
175
|
+
const route = getRoutePath({
|
|
176
|
+
slug,
|
|
177
|
+
path
|
|
178
|
+
});
|
|
179
|
+
const collections = resolveCollectionSlugs(collectionOptions);
|
|
180
|
+
const docsSet = await findDocsSetForMarkdownRoute({
|
|
181
|
+
collections,
|
|
182
|
+
overrideAccess,
|
|
183
|
+
payload,
|
|
184
|
+
route
|
|
185
|
+
});
|
|
186
|
+
if (!docsSet) {
|
|
187
|
+
return null;
|
|
188
|
+
}
|
|
189
|
+
const manifest = docsSet.aiExport ?? getDefaultAiExportManifest(docsSet);
|
|
190
|
+
const records = (await getDocsRecords({
|
|
191
|
+
collections,
|
|
192
|
+
docsSet,
|
|
193
|
+
includeDrafts,
|
|
194
|
+
markdownField,
|
|
195
|
+
overrideAccess,
|
|
196
|
+
payload
|
|
197
|
+
})).filter((record)=>!isExcludedFromAiExport({
|
|
198
|
+
exclude: manifest.exclude,
|
|
199
|
+
sourcePath: record.sourcePath
|
|
200
|
+
}));
|
|
201
|
+
const ordered = orderDocsRecords({
|
|
202
|
+
manifest,
|
|
203
|
+
records
|
|
204
|
+
});
|
|
205
|
+
return {
|
|
206
|
+
type: 'markdown',
|
|
207
|
+
contentType: 'text/markdown; charset=utf-8',
|
|
208
|
+
docsSet,
|
|
209
|
+
markdown: renderMarkdownExport({
|
|
210
|
+
docsSet,
|
|
211
|
+
manifest,
|
|
212
|
+
records: ordered.ordered
|
|
213
|
+
}),
|
|
214
|
+
output: manifest.output ?? `${docsSet.routeBase}.md`,
|
|
215
|
+
route,
|
|
216
|
+
warnings: ordered.warnings
|
|
217
|
+
};
|
|
218
|
+
};
|
|
219
|
+
export const createPayloadMarkdownDocsMarkdownResponse = async (options)=>{
|
|
220
|
+
const resolved = await resolvePayloadMarkdownDocsMarkdownRoute(options);
|
|
221
|
+
if (!resolved) {
|
|
222
|
+
return null;
|
|
223
|
+
}
|
|
224
|
+
return new Response(resolved.markdown, {
|
|
225
|
+
headers: {
|
|
226
|
+
'Content-Type': resolved.contentType
|
|
227
|
+
},
|
|
228
|
+
status: 200
|
|
229
|
+
});
|
|
230
|
+
};
|
|
231
|
+
|
|
232
|
+
//# sourceMappingURL=markdown.js.map
|