@valkyrianlabs/payload-markdown-docs 0.3.1 → 0.4.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.
Files changed (98) hide show
  1. package/README.md +76 -176
  2. package/dist/admin/DocsSetManager.js +5 -3
  3. package/dist/admin/DocsSetManager.js.map +1 -1
  4. package/dist/admin/docsSetManagerData.d.ts +6 -5
  5. package/dist/admin/docsSetManagerData.js +60 -33
  6. package/dist/admin/docsSetManagerData.js.map +1 -1
  7. package/dist/admin/docsSetManagerTypes.d.ts +12 -9
  8. package/dist/admin/docsSetManagerTypes.js.map +1 -1
  9. package/dist/cli/commands/manifest.js +1 -2
  10. package/dist/cli/commands/manifest.js.map +1 -1
  11. package/dist/cli/commands/plan.js +1 -2
  12. package/dist/cli/commands/plan.js.map +1 -1
  13. package/dist/cli/commands/push.js +2 -5
  14. package/dist/cli/commands/push.js.map +1 -1
  15. package/dist/cli/commands/validate.js +11 -6
  16. package/dist/cli/commands/validate.js.map +1 -1
  17. package/dist/cli/index.js +5 -14
  18. package/dist/cli/index.js.map +1 -1
  19. package/dist/cli/parseArgs.js +0 -3
  20. package/dist/cli/parseArgs.js.map +1 -1
  21. package/dist/cli/types.d.ts +0 -3
  22. package/dist/cli/types.js.map +1 -1
  23. package/dist/collections/docs.js +0 -24
  24. package/dist/collections/docs.js.map +1 -1
  25. package/dist/collections/docsGroups.js +8 -9
  26. package/dist/collections/docsGroups.js.map +1 -1
  27. package/dist/collections/docsKeys.d.ts +5 -0
  28. package/dist/collections/docsKeys.js +44 -0
  29. package/dist/collections/docsKeys.js.map +1 -0
  30. package/dist/collections/docsSets.js +47 -202
  31. package/dist/collections/docsSets.js.map +1 -1
  32. package/dist/collections/docsTrusted.d.ts +5 -0
  33. package/dist/collections/docsTrusted.js +60 -0
  34. package/dist/collections/docsTrusted.js.map +1 -0
  35. package/dist/collections/index.d.ts +4 -0
  36. package/dist/collections/index.js +2 -0
  37. package/dist/collections/index.js.map +1 -1
  38. package/dist/constants.d.ts +3 -1
  39. package/dist/constants.js +3 -1
  40. package/dist/constants.js.map +1 -1
  41. package/dist/endpoints/sync.d.ts +6 -7
  42. package/dist/endpoints/sync.js +57 -124
  43. package/dist/endpoints/sync.js.map +1 -1
  44. package/dist/index.d.ts +2 -2
  45. package/dist/index.js +1 -1
  46. package/dist/index.js.map +1 -1
  47. package/dist/next/PayloadMarkdownDocsPage.js +2 -6
  48. package/dist/next/PayloadMarkdownDocsPage.js.map +1 -1
  49. package/dist/next/index.d.ts +2 -0
  50. package/dist/next/index.js +1 -0
  51. package/dist/next/index.js.map +1 -1
  52. package/dist/next/links.d.ts +11 -0
  53. package/dist/next/links.js +79 -0
  54. package/dist/next/links.js.map +1 -0
  55. package/dist/next/markdown.js +91 -19
  56. package/dist/next/markdown.js.map +1 -1
  57. package/dist/next/metadata.js +6 -6
  58. package/dist/next/metadata.js.map +1 -1
  59. package/dist/next/records.js +13 -23
  60. package/dist/next/records.js.map +1 -1
  61. package/dist/next/route.js +141 -49
  62. package/dist/next/route.js.map +1 -1
  63. package/dist/next/types.d.ts +0 -14
  64. package/dist/next/types.js.map +1 -1
  65. package/dist/payload/docsKeys.d.ts +20 -0
  66. package/dist/payload/docsKeys.js +29 -0
  67. package/dist/payload/docsKeys.js.map +1 -0
  68. package/dist/payload/docsSets.d.ts +32 -6
  69. package/dist/payload/docsSets.js +146 -83
  70. package/dist/payload/docsSets.js.map +1 -1
  71. package/dist/payload/docsTrusted.d.ts +16 -0
  72. package/dist/payload/docsTrusted.js +49 -0
  73. package/dist/payload/docsTrusted.js.map +1 -0
  74. package/dist/payload/index.d.ts +5 -1
  75. package/dist/payload/index.js +3 -1
  76. package/dist/payload/index.js.map +1 -1
  77. package/dist/plugin.js +36 -9
  78. package/dist/plugin.js.map +1 -1
  79. package/dist/security/githubOidc.d.ts +18 -5
  80. package/dist/security/githubOidc.js +44 -16
  81. package/dist/security/githubOidc.js.map +1 -1
  82. package/dist/security/index.d.ts +1 -1
  83. package/dist/security/index.js.map +1 -1
  84. package/dist/skills/codex/SKILL.md +3 -4
  85. package/dist/skills/codex/examples/github-actions.md +0 -2
  86. package/dist/skills/codex/reference/admin.md +0 -6
  87. package/dist/skills/codex/reference/routing.md +2 -1
  88. package/dist/skills/codex/reference/sync.md +7 -5
  89. package/dist/skills/codex/reference/troubleshooting.md +3 -4
  90. package/dist/skills/codex/reference/workflow.md +0 -1
  91. package/dist/sync/manifest.d.ts +1 -3
  92. package/dist/sync/manifest.js +2 -3
  93. package/dist/sync/manifest.js.map +1 -1
  94. package/dist/sync/validate.js +1 -2
  95. package/dist/sync/validate.js.map +1 -1
  96. package/dist/types.d.ts +7 -50
  97. package/dist/types.js.map +1 -1
  98. package/package.json +4 -4
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/admin/docsSetManagerData.ts"],"sourcesContent":["import type {\n DocsSetManagerData,\n DocsSetManagerDocItem,\n DocsSetManagerPayloadOperations,\n DocsSetManagerWarning,\n RawDocsRecord,\n RawDocsSetRecord,\n} from './docsSetManagerTypes.js'\n\nimport {\n DEFAULT_DOCS_COLLECTION_SLUG,\n DEFAULT_DOCS_SETS_COLLECTION_SLUG,\n} from '../constants.js'\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === 'object' && value !== null && !Array.isArray(value)\n\nconst getRecordId = (doc: unknown): string | undefined => {\n if (!isRecord(doc)) {\n return undefined\n }\n\n if (typeof doc.id === 'string' || typeof doc.id === 'number') {\n return String(doc.id)\n }\n\n return undefined\n}\n\nconst getRelationshipId = (value: unknown): string | undefined => {\n if (typeof value === 'string' || typeof value === 'number') {\n return String(value)\n }\n\n return getRecordId(value)\n}\n\nconst normalizeAdminRoute = (adminRoute = '/admin'): string => {\n const trimmed = adminRoute.trim()\n\n if (!trimmed || trimmed === '/') {\n return '/admin'\n }\n\n return `/${trimmed}`.replace(/\\/+/g, '/').replace(/\\/+$/g, '')\n}\n\nexport const getGeneratedDocAdminURL = ({\n id,\n adminRoute,\n docsCollectionSlug,\n}: {\n adminRoute?: string\n docsCollectionSlug: string\n id: string\n}): string =>\n `${normalizeAdminRoute(adminRoute)}/collections/${docsCollectionSlug}/${encodeURIComponent(id)}`\n\nconst hasText = (value: null | string | undefined): value is string =>\n typeof value === 'string' && value.trim().length > 0\n\nconst getOverrideSummary = (overrides: RawDocsRecord['overrides']): string[] => {\n if (!overrides || !isRecord(overrides)) {\n return []\n }\n\n const summary: string[] = []\n\n if (hasText(overrides.navTitle)) {\n summary.push('Nav title override')\n }\n\n if (overrides.hideFromNav === true) {\n summary.push('Hidden from nav')\n }\n\n if (hasText(overrides.theme)) {\n summary.push('Theme override')\n }\n\n if (\n hasText(overrides.heroEyebrow) ||\n hasText(overrides.heroTitle) ||\n hasText(overrides.heroDescription)\n ) {\n summary.push('Hero override')\n }\n\n if (hasText(overrides.seoTitle) || hasText(overrides.seoDescription)) {\n summary.push('SEO override')\n }\n\n return summary\n}\n\nconst getDocStatus = (\n doc: RawDocsRecord,\n): DocsSetManagerDocItem['status'] => {\n if (doc.sync?.archived === true) {\n return 'archived'\n }\n\n if (doc._status === 'draft') {\n return 'draft'\n }\n\n if (doc._status === 'published') {\n return 'published'\n }\n\n return 'synced'\n}\n\nconst getSourcePathSegments = (sourcePath: string): string[] => {\n const withoutExtension = sourcePath.replace(/\\.md$/i, '')\n const segments = withoutExtension.split('/').filter(Boolean)\n\n if (segments.at(-1) === 'index') {\n return segments.slice(0, -1)\n }\n\n return segments\n}\n\nconst titleCaseSegment = (segment: string): string =>\n segment\n .split(/[-_]+/)\n .filter(Boolean)\n .map((part) => `${part.charAt(0).toUpperCase()}${part.slice(1)}`)\n .join(' ')\n\nconst compareDocItems = (\n first: DocsSetManagerDocItem,\n second: DocsSetManagerDocItem,\n): number => {\n if (first.order !== second.order) {\n return first.order - second.order\n }\n\n if (first.sourcePath !== second.sourcePath) {\n return first.sourcePath.localeCompare(second.sourcePath)\n }\n\n return first.route.localeCompare(second.route)\n}\n\nconst getOrCreateFolder = ({\n items,\n order,\n segment,\n sourcePath,\n}: {\n items: DocsSetManagerDocItem[]\n order: number\n segment: string\n sourcePath: string\n}): DocsSetManagerDocItem => {\n const existing = items.find(\n (item) => item.kind === 'folder' && item.sourcePath === sourcePath,\n )\n\n if (existing) {\n existing.order = Math.min(existing.order, order)\n return existing\n }\n\n const folder: DocsSetManagerDocItem = {\n id: `folder:${sourcePath}`,\n children: [],\n kind: 'folder',\n order,\n overrideSummary: [],\n route: '',\n sourcePath,\n status: 'synced',\n title: titleCaseSegment(segment),\n }\n\n items.push(folder)\n\n return folder\n}\n\nconst insertIntoTree = ({\n item,\n tree,\n}: {\n item: DocsSetManagerDocItem\n tree: DocsSetManagerDocItem[]\n}) => {\n const segments = getSourcePathSegments(item.sourcePath)\n\n if (segments.length <= 1) {\n tree.push(item)\n return\n }\n\n let currentItems = tree\n\n for (const [index, segment] of segments.slice(0, -1).entries()) {\n const sourcePath = segments.slice(0, index + 1).join('/')\n const folder = getOrCreateFolder({\n items: currentItems,\n order: item.order,\n segment,\n sourcePath,\n })\n\n folder.children ??= []\n currentItems = folder.children\n }\n\n currentItems.push(item)\n}\n\nconst sortTree = (items: DocsSetManagerDocItem[]) => {\n items.sort(compareDocItems)\n\n for (const item of items) {\n if (item.children) {\n sortTree(item.children)\n }\n }\n}\n\nconst toDocItem = ({\n adminRoute,\n doc,\n docsCollectionSlug,\n index,\n warnings,\n}: {\n adminRoute?: string\n doc: RawDocsRecord\n docsCollectionSlug: string\n index: number\n warnings: DocsSetManagerWarning[]\n}): DocsSetManagerDocItem => {\n const id = getRecordId(doc) ?? `unknown-${index}`\n const route = hasText(doc.route) ? doc.route : ''\n const sourcePath = hasText(doc.sourcePath)\n ? doc.sourcePath\n : `missing-source-path-${id}`\n const title = hasText(doc.title) ? doc.title : sourcePath\n const status = getDocStatus(doc)\n const overrideSummary = getOverrideSummary(doc.overrides)\n\n if (!hasText(doc.route)) {\n warnings.push({\n docId: id,\n message: 'Generated doc is missing a route.',\n sourcePath,\n })\n }\n\n if (!hasText(doc.sourcePath)) {\n warnings.push({\n docId: id,\n message: 'Generated doc is missing a source path.',\n })\n }\n\n if (!hasText(doc.title)) {\n warnings.push({\n docId: id,\n message: 'Generated doc is missing a title.',\n sourcePath,\n })\n }\n\n return {\n id,\n ...(adminRoute\n ? {\n adminURL: getGeneratedDocAdminURL({\n id,\n adminRoute,\n docsCollectionSlug,\n }),\n }\n : {}),\n archived: status === 'archived',\n draft: status === 'draft',\n hiddenFromNav: doc.overrides?.hideFromNav === true,\n kind: 'doc',\n order: typeof doc.order === 'number' ? doc.order : 0,\n overrideSummary,\n published: status === 'published',\n route,\n sourcePath,\n status,\n title,\n }\n}\n\nexport const buildDocsSetManagerData = ({\n adminRoute,\n docs,\n docsCollectionSlug = DEFAULT_DOCS_COLLECTION_SLUG,\n docsSet,\n}: {\n adminRoute?: string\n docs: RawDocsRecord[]\n docsCollectionSlug?: string\n docsSet: RawDocsSetRecord\n}): DocsSetManagerData => {\n const warnings: DocsSetManagerWarning[] = []\n const docsSetId = getRecordId(docsSet) ?? 'unknown'\n const sortedDocs = docs\n .map((doc, index) =>\n toDocItem({\n adminRoute,\n doc,\n docsCollectionSlug,\n index,\n warnings,\n }),\n )\n .sort(compareDocItems)\n const tree: DocsSetManagerDocItem[] = []\n\n for (const item of sortedDocs) {\n insertIntoTree({\n item,\n tree,\n })\n }\n\n sortTree(tree)\n\n return {\n docs: sortedDocs,\n docsSet: {\n id: docsSetId,\n routeBase: docsSet.routeBase ?? '',\n sourceId: docsSet.sourceId ?? '',\n title: docsSet.title ?? docsSetId,\n },\n summary: {\n archived: sortedDocs.filter((doc) => doc.archived).length,\n drafts: sortedDocs.filter((doc) => doc.draft).length,\n hiddenFromNav: sortedDocs.filter((doc) => doc.hiddenFromNav).length,\n published: sortedDocs.filter((doc) => doc.published).length,\n total: sortedDocs.length,\n withOverrides: sortedDocs.filter((doc) => doc.overrideSummary.length > 0)\n .length,\n },\n sync: docsSet.sync\n ? {\n docsCount:\n typeof docsSet.sync.docsCount === 'number'\n ? docsSet.sync.docsCount\n : undefined,\n lastStatus: docsSet.sync.lastStatus ?? undefined,\n lastSyncedAt: docsSet.sync.lastSyncedAt ?? undefined,\n }\n : undefined,\n tree,\n warnings,\n }\n}\n\nexport const isDocsRecordForDocsSet = ({\n doc,\n docsSetId,\n sourceId,\n}: {\n doc: RawDocsRecord\n docsSetId: string\n sourceId: string\n}): boolean => {\n const docDocsSetId = getRelationshipId(doc.docsSet)\n\n if (docDocsSetId) {\n return docDocsSetId === docsSetId\n }\n\n return doc.sync?.sourceId === sourceId\n}\n\nexport const getDocsSetManagerData = async ({\n adminRoute,\n docsCollectionSlug = DEFAULT_DOCS_COLLECTION_SLUG,\n docsSetId,\n docsSetsCollectionSlug = DEFAULT_DOCS_SETS_COLLECTION_SLUG,\n overrideAccess = true,\n payload,\n}: {\n adminRoute?: string\n docsCollectionSlug?: string\n docsSetId: string\n docsSetsCollectionSlug?: string\n overrideAccess?: boolean\n payload: DocsSetManagerPayloadOperations\n}): Promise<DocsSetManagerData> => {\n const docsSet = (await payload.findByID({\n id: docsSetId,\n collection: docsSetsCollectionSlug,\n depth: 0,\n overrideAccess,\n })) as RawDocsSetRecord\n\n const docsResult = await payload.find({\n collection: docsCollectionSlug,\n depth: 0,\n limit: 1000,\n overrideAccess,\n where: {\n or: [\n {\n docsSet: {\n equals: docsSetId,\n },\n },\n {\n 'sync.sourceId': {\n equals: docsSet.sourceId,\n },\n },\n ],\n },\n })\n const docs = docsResult.docs\n .filter(isRecord)\n .map((doc) => doc as RawDocsRecord)\n .filter((doc) =>\n isDocsRecordForDocsSet({\n doc,\n docsSetId,\n sourceId: docsSet.sourceId ?? '',\n }),\n )\n\n return buildDocsSetManagerData({\n adminRoute,\n docs,\n docsCollectionSlug,\n docsSet,\n })\n}\n"],"names":["DEFAULT_DOCS_COLLECTION_SLUG","DEFAULT_DOCS_SETS_COLLECTION_SLUG","isRecord","value","Array","isArray","getRecordId","doc","undefined","id","String","getRelationshipId","normalizeAdminRoute","adminRoute","trimmed","trim","replace","getGeneratedDocAdminURL","docsCollectionSlug","encodeURIComponent","hasText","length","getOverrideSummary","overrides","summary","navTitle","push","hideFromNav","theme","heroEyebrow","heroTitle","heroDescription","seoTitle","seoDescription","getDocStatus","sync","archived","_status","getSourcePathSegments","sourcePath","withoutExtension","segments","split","filter","Boolean","at","slice","titleCaseSegment","segment","map","part","charAt","toUpperCase","join","compareDocItems","first","second","order","localeCompare","route","getOrCreateFolder","items","existing","find","item","kind","Math","min","folder","children","overrideSummary","status","title","insertIntoTree","tree","currentItems","index","entries","sortTree","sort","toDocItem","warnings","docId","message","adminURL","draft","hiddenFromNav","published","buildDocsSetManagerData","docs","docsSet","docsSetId","sortedDocs","routeBase","sourceId","drafts","total","withOverrides","docsCount","lastStatus","lastSyncedAt","isDocsRecordForDocsSet","docDocsSetId","getDocsSetManagerData","docsSetsCollectionSlug","overrideAccess","payload","findByID","collection","depth","docsResult","limit","where","or","equals"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/admin/docsSetManagerData.ts"],"sourcesContent":["import type {\n DocsSetManagerData,\n DocsSetManagerDocItem,\n DocsSetManagerPayloadOperations,\n DocsSetManagerWarning,\n RawDocsGroupRecord,\n RawDocsRecord,\n RawDocsSetRecord,\n} from './docsSetManagerTypes.js'\n\nimport {\n DEFAULT_DOCS_COLLECTION_SLUG,\n DEFAULT_DOCS_GROUPS_COLLECTION_SLUG,\n DEFAULT_DOCS_SETS_COLLECTION_SLUG,\n} from '../constants.js'\nimport {\n deriveDocsSetRouteBase,\n joinRouteSegments,\n} from '../routing/index.js'\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === 'object' && value !== null && !Array.isArray(value)\n\nconst getRecordId = (doc: unknown): string | undefined => {\n if (!isRecord(doc)) {\n return undefined\n }\n\n if (typeof doc.id === 'string' || typeof doc.id === 'number') {\n return String(doc.id)\n }\n\n return undefined\n}\n\nconst getRelationshipId = (value: unknown): string | undefined => {\n if (typeof value === 'string' || typeof value === 'number') {\n return String(value)\n }\n\n return getRecordId(value)\n}\n\nconst normalizeAdminRoute = (adminRoute = '/admin'): string => {\n const trimmed = adminRoute.trim()\n\n if (!trimmed || trimmed === '/') {\n return '/admin'\n }\n\n return `/${trimmed}`.replace(/\\/+/g, '/').replace(/\\/+$/g, '')\n}\n\nexport const getGeneratedDocAdminURL = ({\n id,\n adminRoute,\n docsCollectionSlug,\n}: {\n adminRoute?: string\n docsCollectionSlug: string\n id: string\n}): string =>\n `${normalizeAdminRoute(adminRoute)}/collections/${docsCollectionSlug}/${encodeURIComponent(id)}`\n\nconst hasText = (value: null | string | undefined): value is string =>\n typeof value === 'string' && value.trim().length > 0\n\nconst getOverrideSummary = (overrides: RawDocsRecord['overrides']): string[] => {\n if (!overrides || !isRecord(overrides)) {\n return []\n }\n\n const summary: string[] = []\n\n if (hasText(overrides.navTitle)) {\n summary.push('Nav title override')\n }\n\n if (overrides.hideFromNav === true) {\n summary.push('Hidden from nav')\n }\n\n return summary\n}\n\nconst getDocStatus = (\n doc: RawDocsRecord,\n): DocsSetManagerDocItem['status'] => {\n if (doc.sync?.archived === true) {\n return 'archived'\n }\n\n if (doc._status === 'draft') {\n return 'draft'\n }\n\n if (doc._status === 'published') {\n return 'published'\n }\n\n return 'synced'\n}\n\nconst getSourcePathSegments = (sourcePath: string): string[] => {\n const withoutExtension = sourcePath.replace(/\\.md$/i, '')\n const segments = withoutExtension.split('/').filter(Boolean)\n\n if (segments.at(-1) === 'index') {\n return segments.slice(0, -1)\n }\n\n return segments\n}\n\nconst getGroupRoutePath = ({\n groupId,\n groupsById,\n seen = new Set<string>(),\n}: {\n groupId?: string\n groupsById: Map<string, RawDocsGroupRecord>\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 (!group?.slug) {\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\nconst getDocsSetRouteBase = ({\n docsGroups,\n docsSet,\n}: {\n docsGroups: RawDocsGroupRecord[]\n docsSet: RawDocsSetRecord\n}): string => {\n if (!docsSet.slug) {\n return ''\n }\n\n const groupsById = new Map(\n docsGroups.flatMap((group) => {\n const id = getRecordId(group)\n\n return id ? [[id, group]] : []\n }),\n )\n\n return deriveDocsSetRouteBase({\n docsSetSlug: docsSet.slug,\n groupRoutePath: getGroupRoutePath({\n groupId: getRelationshipId(docsSet.group),\n groupsById,\n }),\n })\n}\n\nconst titleCaseSegment = (segment: string): string =>\n segment\n .split(/[-_]+/)\n .filter(Boolean)\n .map((part) => `${part.charAt(0).toUpperCase()}${part.slice(1)}`)\n .join(' ')\n\nconst compareDocItems = (\n first: DocsSetManagerDocItem,\n second: DocsSetManagerDocItem,\n): number => {\n if (first.order !== second.order) {\n return first.order - second.order\n }\n\n if (first.sourcePath !== second.sourcePath) {\n return first.sourcePath.localeCompare(second.sourcePath)\n }\n\n return first.route.localeCompare(second.route)\n}\n\nconst getOrCreateFolder = ({\n items,\n order,\n segment,\n sourcePath,\n}: {\n items: DocsSetManagerDocItem[]\n order: number\n segment: string\n sourcePath: string\n}): DocsSetManagerDocItem => {\n const existing = items.find(\n (item) => item.kind === 'folder' && item.sourcePath === sourcePath,\n )\n\n if (existing) {\n existing.order = Math.min(existing.order, order)\n return existing\n }\n\n const folder: DocsSetManagerDocItem = {\n id: `folder:${sourcePath}`,\n children: [],\n kind: 'folder',\n order,\n overrideSummary: [],\n route: '',\n sourcePath,\n status: 'synced',\n title: titleCaseSegment(segment),\n }\n\n items.push(folder)\n\n return folder\n}\n\nconst insertIntoTree = ({\n item,\n tree,\n}: {\n item: DocsSetManagerDocItem\n tree: DocsSetManagerDocItem[]\n}) => {\n const segments = getSourcePathSegments(item.sourcePath)\n\n if (segments.length <= 1) {\n tree.push(item)\n return\n }\n\n let currentItems = tree\n\n for (const [index, segment] of segments.slice(0, -1).entries()) {\n const sourcePath = segments.slice(0, index + 1).join('/')\n const folder = getOrCreateFolder({\n items: currentItems,\n order: item.order,\n segment,\n sourcePath,\n })\n\n folder.children ??= []\n currentItems = folder.children\n }\n\n currentItems.push(item)\n}\n\nconst sortTree = (items: DocsSetManagerDocItem[]) => {\n items.sort(compareDocItems)\n\n for (const item of items) {\n if (item.children) {\n sortTree(item.children)\n }\n }\n}\n\nconst toDocItem = ({\n adminRoute,\n doc,\n docsCollectionSlug,\n index,\n warnings,\n}: {\n adminRoute?: string\n doc: RawDocsRecord\n docsCollectionSlug: string\n index: number\n warnings: DocsSetManagerWarning[]\n}): DocsSetManagerDocItem => {\n const id = getRecordId(doc) ?? `unknown-${index}`\n const route = hasText(doc.route) ? doc.route : ''\n const sourcePath = hasText(doc.sourcePath)\n ? doc.sourcePath\n : `missing-source-path-${id}`\n const title = hasText(doc.title) ? doc.title : sourcePath\n const status = getDocStatus(doc)\n const overrideSummary = getOverrideSummary(doc.overrides)\n\n if (!hasText(doc.route)) {\n warnings.push({\n docId: id,\n message: 'Generated doc is missing a route.',\n sourcePath,\n })\n }\n\n if (!hasText(doc.sourcePath)) {\n warnings.push({\n docId: id,\n message: 'Generated doc is missing a source path.',\n })\n }\n\n if (!hasText(doc.title)) {\n warnings.push({\n docId: id,\n message: 'Generated doc is missing a title.',\n sourcePath,\n })\n }\n\n return {\n id,\n ...(adminRoute\n ? {\n adminURL: getGeneratedDocAdminURL({\n id,\n adminRoute,\n docsCollectionSlug,\n }),\n }\n : {}),\n archived: status === 'archived',\n draft: status === 'draft',\n hiddenFromNav: doc.overrides?.hideFromNav === true,\n kind: 'doc',\n order: typeof doc.order === 'number' ? doc.order : 0,\n overrideSummary,\n published: status === 'published',\n route,\n sourcePath,\n status,\n title,\n }\n}\n\nexport const buildDocsSetManagerData = ({\n adminRoute,\n docs,\n docsCollectionSlug = DEFAULT_DOCS_COLLECTION_SLUG,\n docsGroups = [],\n docsSet,\n}: {\n adminRoute?: string\n docs: RawDocsRecord[]\n docsCollectionSlug?: string\n docsGroups?: RawDocsGroupRecord[]\n docsSet: RawDocsSetRecord\n}): DocsSetManagerData => {\n const warnings: DocsSetManagerWarning[] = []\n const docsSetId = getRecordId(docsSet) ?? 'unknown'\n const sortedDocs = docs\n .map((doc, index) =>\n toDocItem({\n adminRoute,\n doc,\n docsCollectionSlug,\n index,\n warnings,\n }),\n )\n .sort(compareDocItems)\n const tree: DocsSetManagerDocItem[] = []\n\n for (const item of sortedDocs) {\n insertIntoTree({\n item,\n tree,\n })\n }\n\n sortTree(tree)\n\n return {\n docs: sortedDocs,\n docsSet: {\n id: docsSetId,\n slug: docsSet.slug ?? '',\n routeBase: getDocsSetRouteBase({\n docsGroups,\n docsSet,\n }),\n title: docsSet.title ?? docsSetId,\n },\n summary: {\n archived: sortedDocs.filter((doc) => doc.archived).length,\n drafts: sortedDocs.filter((doc) => doc.draft).length,\n hiddenFromNav: sortedDocs.filter((doc) => doc.hiddenFromNav).length,\n published: sortedDocs.filter((doc) => doc.published).length,\n total: sortedDocs.length,\n withOverrides: sortedDocs.filter((doc) => doc.overrideSummary.length > 0)\n .length,\n },\n sync: docsSet.sync\n ? {\n docsCount:\n typeof docsSet.sync.docsCount === 'number'\n ? docsSet.sync.docsCount\n : undefined,\n lastStatus: docsSet.sync.lastStatus ?? undefined,\n lastSyncedAt: docsSet.sync.lastSyncedAt ?? undefined,\n }\n : undefined,\n tree,\n warnings,\n }\n}\n\nexport const isDocsRecordForDocsSet = ({\n doc,\n docsSetId,\n}: {\n doc: RawDocsRecord\n docsSetId: string\n}): boolean => {\n const docDocsSetId = getRelationshipId(doc.docsSet)\n\n return docDocsSetId === docsSetId\n}\n\nexport const getDocsSetManagerData = async ({\n adminRoute,\n docsCollectionSlug = DEFAULT_DOCS_COLLECTION_SLUG,\n docsGroupsCollectionSlug = DEFAULT_DOCS_GROUPS_COLLECTION_SLUG,\n docsSetId,\n docsSetsCollectionSlug = DEFAULT_DOCS_SETS_COLLECTION_SLUG,\n overrideAccess = true,\n payload,\n}: {\n adminRoute?: string\n docsCollectionSlug?: string\n docsGroupsCollectionSlug?: string\n docsSetId: string\n docsSetsCollectionSlug?: string\n overrideAccess?: boolean\n payload: DocsSetManagerPayloadOperations\n}): Promise<DocsSetManagerData> => {\n const docsSet = (await payload.findByID({\n id: docsSetId,\n collection: docsSetsCollectionSlug,\n depth: 0,\n overrideAccess,\n })) as RawDocsSetRecord\n\n const docsResult = await payload.find({\n collection: docsCollectionSlug,\n depth: 0,\n limit: 1000,\n overrideAccess,\n where: {\n docsSet: {\n equals: docsSetId,\n },\n },\n })\n const docsGroupsResult = await payload.find({\n collection: docsGroupsCollectionSlug,\n depth: 0,\n limit: 1000,\n overrideAccess,\n })\n const docs = docsResult.docs\n .filter(isRecord)\n .map((doc) => doc as RawDocsRecord)\n .filter((doc) =>\n isDocsRecordForDocsSet({\n doc,\n docsSetId,\n }),\n )\n\n return buildDocsSetManagerData({\n adminRoute,\n docs,\n docsCollectionSlug,\n docsGroups: docsGroupsResult.docs\n .filter(isRecord)\n .map((group) => group as RawDocsGroupRecord),\n docsSet,\n })\n}\n"],"names":["DEFAULT_DOCS_COLLECTION_SLUG","DEFAULT_DOCS_GROUPS_COLLECTION_SLUG","DEFAULT_DOCS_SETS_COLLECTION_SLUG","deriveDocsSetRouteBase","joinRouteSegments","isRecord","value","Array","isArray","getRecordId","doc","undefined","id","String","getRelationshipId","normalizeAdminRoute","adminRoute","trimmed","trim","replace","getGeneratedDocAdminURL","docsCollectionSlug","encodeURIComponent","hasText","length","getOverrideSummary","overrides","summary","navTitle","push","hideFromNav","getDocStatus","sync","archived","_status","getSourcePathSegments","sourcePath","withoutExtension","segments","split","filter","Boolean","at","slice","getGroupRoutePath","groupId","groupsById","seen","Set","has","group","get","slug","parent","getDocsSetRouteBase","docsGroups","docsSet","Map","flatMap","docsSetSlug","groupRoutePath","titleCaseSegment","segment","map","part","charAt","toUpperCase","join","compareDocItems","first","second","order","localeCompare","route","getOrCreateFolder","items","existing","find","item","kind","Math","min","folder","children","overrideSummary","status","title","insertIntoTree","tree","currentItems","index","entries","sortTree","sort","toDocItem","warnings","docId","message","adminURL","draft","hiddenFromNav","published","buildDocsSetManagerData","docs","docsSetId","sortedDocs","routeBase","drafts","total","withOverrides","docsCount","lastStatus","lastSyncedAt","isDocsRecordForDocsSet","docDocsSetId","getDocsSetManagerData","docsGroupsCollectionSlug","docsSetsCollectionSlug","overrideAccess","payload","findByID","collection","depth","docsResult","limit","where","equals","docsGroupsResult"],"mappings":"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"}
@@ -1,7 +1,9 @@
1
1
  export type RawDocsSetRecord = {
2
+ group?: {
3
+ id?: number | string;
4
+ } | null | number | string;
2
5
  id?: number | string;
3
- routeBase?: string;
4
- sourceId?: string;
6
+ slug?: string;
5
7
  sync?: {
6
8
  docsCount?: null | number;
7
9
  lastStatus?: 'failed' | 'pending' | 'success' | null;
@@ -9,6 +11,13 @@ export type RawDocsSetRecord = {
9
11
  };
10
12
  title?: string;
11
13
  };
14
+ export type RawDocsGroupRecord = {
15
+ id?: number | string;
16
+ parent?: {
17
+ id?: number | string;
18
+ } | null | number | string;
19
+ slug?: string;
20
+ };
12
21
  export type RawDocsRecord = {
13
22
  _status?: 'draft' | 'published';
14
23
  description?: null | string;
@@ -19,14 +28,8 @@ export type RawDocsRecord = {
19
28
  navTitle?: null | string;
20
29
  order?: null | number;
21
30
  overrides?: {
22
- heroDescription?: null | string;
23
- heroEyebrow?: null | string;
24
- heroTitle?: null | string;
25
31
  hideFromNav?: boolean | null;
26
32
  navTitle?: null | string;
27
- seoDescription?: null | string;
28
- seoTitle?: null | string;
29
- theme?: null | string;
30
33
  };
31
34
  route?: null | string;
32
35
  sourcePath?: null | string;
@@ -65,7 +68,7 @@ export type DocsSetManagerData = {
65
68
  docsSet: {
66
69
  id: string;
67
70
  routeBase: string;
68
- sourceId: string;
71
+ slug: string;
69
72
  title: string;
70
73
  };
71
74
  summary: {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/admin/docsSetManagerTypes.ts"],"sourcesContent":["export type RawDocsSetRecord = {\n id?: number | string\n routeBase?: string\n sourceId?: string\n sync?: {\n docsCount?: null | number\n lastStatus?: 'failed' | 'pending' | 'success' | null\n lastSyncedAt?: null | string\n }\n title?: string\n}\n\nexport type RawDocsRecord = {\n _status?: 'draft' | 'published'\n description?: null | string\n docsSet?: { id?: number | string } | null | number | string\n id?: number | string\n navTitle?: null | string\n order?: null | number\n overrides?: {\n heroDescription?: null | string\n heroEyebrow?: null | string\n heroTitle?: null | string\n hideFromNav?: boolean | null\n navTitle?: null | string\n seoDescription?: null | string\n seoTitle?: null | string\n theme?: null | string\n }\n route?: null | string\n sourcePath?: null | string\n sync?: {\n archived?: boolean | null\n archivedAt?: null | string\n lastSyncedAt?: null | string\n sourceId?: null | string\n }\n title?: null | string\n}\n\nexport type DocsSetManagerWarning = {\n docId?: string\n message: string\n sourcePath?: string\n}\n\nexport type DocsSetManagerDocStatus =\n | 'archived'\n | 'draft'\n | 'published'\n | 'synced'\n\nexport type DocsSetManagerDocItem = {\n adminURL?: string\n archived?: boolean\n children?: DocsSetManagerDocItem[]\n draft?: boolean\n hiddenFromNav?: boolean\n id: string\n kind: 'doc' | 'folder'\n order: number\n overrideSummary: string[]\n published?: boolean\n route: string\n sourcePath: string\n status: DocsSetManagerDocStatus\n title: string\n}\n\nexport type DocsSetManagerData = {\n docs: DocsSetManagerDocItem[]\n docsSet: {\n id: string\n routeBase: string\n sourceId: string\n title: string\n }\n summary: {\n archived: number\n drafts: number\n hiddenFromNav: number\n published: number\n total: number\n withOverrides: number\n }\n sync?: {\n docsCount?: number\n lastStatus?: 'failed' | 'pending' | 'success'\n lastSyncedAt?: string\n }\n tree: DocsSetManagerDocItem[]\n warnings: DocsSetManagerWarning[]\n}\n\nexport type DocsSetManagerPayloadOperations = {\n find: (args: {\n collection: string\n depth?: number\n limit?: number\n overrideAccess?: boolean\n where?: unknown\n }) => Promise<{\n docs: unknown[]\n }>\n findByID: (args: {\n collection: string\n depth?: number\n id: number | string\n overrideAccess?: boolean\n }) => Promise<unknown>\n}\n"],"names":[],"mappings":"AA8FA,WAgBC"}
1
+ {"version":3,"sources":["../../src/admin/docsSetManagerTypes.ts"],"sourcesContent":["export type RawDocsSetRecord = {\n group?: { id?: number | string } | null | number | string\n id?: number | string\n slug?: string\n sync?: {\n docsCount?: null | number\n lastStatus?: 'failed' | 'pending' | 'success' | null\n lastSyncedAt?: null | string\n }\n title?: string\n}\n\nexport type RawDocsGroupRecord = {\n id?: number | string\n parent?: { id?: number | string } | null | number | string\n slug?: string\n}\n\nexport type RawDocsRecord = {\n _status?: 'draft' | 'published'\n description?: null | string\n docsSet?: { id?: number | string } | null | number | string\n id?: number | string\n navTitle?: null | string\n order?: null | number\n overrides?: {\n hideFromNav?: boolean | null\n navTitle?: null | string\n }\n route?: null | string\n sourcePath?: null | string\n sync?: {\n archived?: boolean | null\n archivedAt?: null | string\n lastSyncedAt?: null | string\n sourceId?: null | string\n }\n title?: null | string\n}\n\nexport type DocsSetManagerWarning = {\n docId?: string\n message: string\n sourcePath?: string\n}\n\nexport type DocsSetManagerDocStatus =\n | 'archived'\n | 'draft'\n | 'published'\n | 'synced'\n\nexport type DocsSetManagerDocItem = {\n adminURL?: string\n archived?: boolean\n children?: DocsSetManagerDocItem[]\n draft?: boolean\n hiddenFromNav?: boolean\n id: string\n kind: 'doc' | 'folder'\n order: number\n overrideSummary: string[]\n published?: boolean\n route: string\n sourcePath: string\n status: DocsSetManagerDocStatus\n title: string\n}\n\nexport type DocsSetManagerData = {\n docs: DocsSetManagerDocItem[]\n docsSet: {\n id: string\n routeBase: string\n slug: string\n title: string\n }\n summary: {\n archived: number\n drafts: number\n hiddenFromNav: number\n published: number\n total: number\n withOverrides: number\n }\n sync?: {\n docsCount?: number\n lastStatus?: 'failed' | 'pending' | 'success'\n lastSyncedAt?: string\n }\n tree: DocsSetManagerDocItem[]\n warnings: DocsSetManagerWarning[]\n}\n\nexport type DocsSetManagerPayloadOperations = {\n find: (args: {\n collection: string\n depth?: number\n limit?: number\n overrideAccess?: boolean\n where?: unknown\n }) => Promise<{\n docs: unknown[]\n }>\n findByID: (args: {\n collection: string\n depth?: number\n id: number | string\n overrideAccess?: boolean\n }) => Promise<unknown>\n}\n"],"names":[],"mappings":"AA8FA,WAgBC"}
@@ -26,14 +26,13 @@ export const runManifestCommand = async (args)=>{
26
26
  commit: options.commit,
27
27
  files,
28
28
  repository: options.repository,
29
- root: options.sourceRoot,
30
29
  sourceId: options.sourceId
31
30
  });
32
31
  const validation = validateDocsManifest(manifest, {
33
32
  maxFileBytes: options.maxFileBytes,
34
33
  maxFiles: options.maxFiles,
35
34
  maxTotalBytes: options.maxTotalBytes,
36
- routeBase: options.routeBase
35
+ routeBase: `/${options.sourceId}`
37
36
  });
38
37
  if (!validation.ok) {
39
38
  return {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/cli/commands/manifest.ts"],"sourcesContent":["import type { CliResult, ParsedCliArgs } from '../types.js'\n\nimport {\n buildDocsManifest,\n validateDocsManifest,\n} from '../../sync/index.js'\nimport {\n readDocsAiExportManifest,\n walkDocsFiles,\n} from '../filesystem.js'\nimport { formatIssues, printJson } from '../format.js'\nimport { getFlagBoolean } from '../parseArgs.js'\nimport { getDocsCommandOptions } from './validate.js'\n\nexport const runManifestCommand = async (\n args: ParsedCliArgs,\n): Promise<CliResult> => {\n const options = getDocsCommandOptions(args)\n\n if ('exitCode' in options) {\n return options\n }\n\n const files = await walkDocsFiles({\n root: options.docsRoot,\n })\n const aiExport = await readDocsAiExportManifest({\n root: options.docsRoot,\n })\n\n if (!aiExport.ok) {\n return {\n exitCode: 1,\n stderr: `AI export manifest is invalid.\\n\\nErrors:\\n${formatIssues(aiExport.issues)}\\n`,\n }\n }\n\n const manifest = buildDocsManifest({\n aiExport: aiExport.manifest,\n branch: options.branch,\n commit: options.commit,\n files,\n repository: options.repository,\n root: options.sourceRoot,\n sourceId: options.sourceId,\n })\n const validation = validateDocsManifest(manifest, {\n maxFileBytes: options.maxFileBytes,\n maxFiles: options.maxFiles,\n maxTotalBytes: options.maxTotalBytes,\n routeBase: options.routeBase,\n })\n\n if (!validation.ok) {\n return {\n exitCode: 1,\n stderr: `Manifest is invalid.\\n\\nErrors:\\n${formatIssues(validation.issues)}\\n`,\n }\n }\n\n return {\n exitCode: 0,\n stdout: printJson(manifest, getFlagBoolean(args, 'pretty')),\n }\n}\n"],"names":["buildDocsManifest","validateDocsManifest","readDocsAiExportManifest","walkDocsFiles","formatIssues","printJson","getFlagBoolean","getDocsCommandOptions","runManifestCommand","args","options","files","root","docsRoot","aiExport","ok","exitCode","stderr","issues","manifest","branch","commit","repository","sourceRoot","sourceId","validation","maxFileBytes","maxFiles","maxTotalBytes","routeBase","stdout"],"mappings":"AAEA,SACEA,iBAAiB,EACjBC,oBAAoB,QACf,sBAAqB;AAC5B,SACEC,wBAAwB,EACxBC,aAAa,QACR,mBAAkB;AACzB,SAASC,YAAY,EAAEC,SAAS,QAAQ,eAAc;AACtD,SAASC,cAAc,QAAQ,kBAAiB;AAChD,SAASC,qBAAqB,QAAQ,gBAAe;AAErD,OAAO,MAAMC,qBAAqB,OAChCC;IAEA,MAAMC,UAAUH,sBAAsBE;IAEtC,IAAI,cAAcC,SAAS;QACzB,OAAOA;IACT;IAEA,MAAMC,QAAQ,MAAMR,cAAc;QAChCS,MAAMF,QAAQG,QAAQ;IACxB;IACA,MAAMC,WAAW,MAAMZ,yBAAyB;QAC9CU,MAAMF,QAAQG,QAAQ;IACxB;IAEA,IAAI,CAACC,SAASC,EAAE,EAAE;QAChB,OAAO;YACLC,UAAU;YACVC,QAAQ,CAAC,2CAA2C,EAAEb,aAAaU,SAASI,MAAM,EAAE,EAAE,CAAC;QACzF;IACF;IAEA,MAAMC,WAAWnB,kBAAkB;QACjCc,UAAUA,SAASK,QAAQ;QAC3BC,QAAQV,QAAQU,MAAM;QACtBC,QAAQX,QAAQW,MAAM;QACtBV;QACAW,YAAYZ,QAAQY,UAAU;QAC9BV,MAAMF,QAAQa,UAAU;QACxBC,UAAUd,QAAQc,QAAQ;IAC5B;IACA,MAAMC,aAAaxB,qBAAqBkB,UAAU;QAChDO,cAAchB,QAAQgB,YAAY;QAClCC,UAAUjB,QAAQiB,QAAQ;QAC1BC,eAAelB,QAAQkB,aAAa;QACpCC,WAAWnB,QAAQmB,SAAS;IAC9B;IAEA,IAAI,CAACJ,WAAWV,EAAE,EAAE;QAClB,OAAO;YACLC,UAAU;YACVC,QAAQ,CAAC,iCAAiC,EAAEb,aAAaqB,WAAWP,MAAM,EAAE,EAAE,CAAC;QACjF;IACF;IAEA,OAAO;QACLF,UAAU;QACVc,QAAQzB,UAAUc,UAAUb,eAAeG,MAAM;IACnD;AACF,EAAC"}
1
+ {"version":3,"sources":["../../../src/cli/commands/manifest.ts"],"sourcesContent":["import type { CliResult, ParsedCliArgs } from '../types.js'\n\nimport {\n buildDocsManifest,\n validateDocsManifest,\n} from '../../sync/index.js'\nimport {\n readDocsAiExportManifest,\n walkDocsFiles,\n} from '../filesystem.js'\nimport { formatIssues, printJson } from '../format.js'\nimport { getFlagBoolean } from '../parseArgs.js'\nimport { getDocsCommandOptions } from './validate.js'\n\nexport const runManifestCommand = async (\n args: ParsedCliArgs,\n): Promise<CliResult> => {\n const options = getDocsCommandOptions(args)\n\n if ('exitCode' in options) {\n return options\n }\n\n const files = await walkDocsFiles({\n root: options.docsRoot,\n })\n const aiExport = await readDocsAiExportManifest({\n root: options.docsRoot,\n })\n\n if (!aiExport.ok) {\n return {\n exitCode: 1,\n stderr: `AI export manifest is invalid.\\n\\nErrors:\\n${formatIssues(aiExport.issues)}\\n`,\n }\n }\n\n const manifest = buildDocsManifest({\n aiExport: aiExport.manifest,\n branch: options.branch,\n commit: options.commit,\n files,\n repository: options.repository,\n sourceId: options.sourceId,\n })\n const validation = validateDocsManifest(manifest, {\n maxFileBytes: options.maxFileBytes,\n maxFiles: options.maxFiles,\n maxTotalBytes: options.maxTotalBytes,\n routeBase: `/${options.sourceId}`,\n })\n\n if (!validation.ok) {\n return {\n exitCode: 1,\n stderr: `Manifest is invalid.\\n\\nErrors:\\n${formatIssues(validation.issues)}\\n`,\n }\n }\n\n return {\n exitCode: 0,\n stdout: printJson(manifest, getFlagBoolean(args, 'pretty')),\n }\n}\n"],"names":["buildDocsManifest","validateDocsManifest","readDocsAiExportManifest","walkDocsFiles","formatIssues","printJson","getFlagBoolean","getDocsCommandOptions","runManifestCommand","args","options","files","root","docsRoot","aiExport","ok","exitCode","stderr","issues","manifest","branch","commit","repository","sourceId","validation","maxFileBytes","maxFiles","maxTotalBytes","routeBase","stdout"],"mappings":"AAEA,SACEA,iBAAiB,EACjBC,oBAAoB,QACf,sBAAqB;AAC5B,SACEC,wBAAwB,EACxBC,aAAa,QACR,mBAAkB;AACzB,SAASC,YAAY,EAAEC,SAAS,QAAQ,eAAc;AACtD,SAASC,cAAc,QAAQ,kBAAiB;AAChD,SAASC,qBAAqB,QAAQ,gBAAe;AAErD,OAAO,MAAMC,qBAAqB,OAChCC;IAEA,MAAMC,UAAUH,sBAAsBE;IAEtC,IAAI,cAAcC,SAAS;QACzB,OAAOA;IACT;IAEA,MAAMC,QAAQ,MAAMR,cAAc;QAChCS,MAAMF,QAAQG,QAAQ;IACxB;IACA,MAAMC,WAAW,MAAMZ,yBAAyB;QAC9CU,MAAMF,QAAQG,QAAQ;IACxB;IAEA,IAAI,CAACC,SAASC,EAAE,EAAE;QAChB,OAAO;YACLC,UAAU;YACVC,QAAQ,CAAC,2CAA2C,EAAEb,aAAaU,SAASI,MAAM,EAAE,EAAE,CAAC;QACzF;IACF;IAEA,MAAMC,WAAWnB,kBAAkB;QACjCc,UAAUA,SAASK,QAAQ;QAC3BC,QAAQV,QAAQU,MAAM;QACtBC,QAAQX,QAAQW,MAAM;QACtBV;QACAW,YAAYZ,QAAQY,UAAU;QAC9BC,UAAUb,QAAQa,QAAQ;IAC5B;IACA,MAAMC,aAAavB,qBAAqBkB,UAAU;QAChDM,cAAcf,QAAQe,YAAY;QAClCC,UAAUhB,QAAQgB,QAAQ;QAC1BC,eAAejB,QAAQiB,aAAa;QACpCC,WAAW,CAAC,CAAC,EAAElB,QAAQa,QAAQ,EAAE;IACnC;IAEA,IAAI,CAACC,WAAWT,EAAE,EAAE;QAClB,OAAO;YACLC,UAAU;YACVC,QAAQ,CAAC,iCAAiC,EAAEb,aAAaoB,WAAWN,MAAM,EAAE,EAAE,CAAC;QACjF;IACF;IAEA,OAAO;QACLF,UAAU;QACVa,QAAQxB,UAAUc,UAAUb,eAAeG,MAAM;IACnD;AACF,EAAC"}
@@ -75,14 +75,13 @@ export const runPlanCommand = async (args)=>{
75
75
  deleteBehavior,
76
76
  files,
77
77
  repository: options.repository,
78
- root: options.sourceRoot,
79
78
  sourceId: options.sourceId
80
79
  });
81
80
  const validation = validateDocsManifest(manifest, {
82
81
  maxFileBytes: options.maxFileBytes,
83
82
  maxFiles: options.maxFiles,
84
83
  maxTotalBytes: options.maxTotalBytes,
85
- routeBase: options.routeBase
84
+ routeBase: `/${options.sourceId}`
86
85
  });
87
86
  if (!validation.ok) {
88
87
  return {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/cli/commands/plan.ts"],"sourcesContent":["import { readFile } from 'node:fs/promises'\n\nimport type {\n DocsDeleteBehavior,\n ExistingDocsRecord,\n} from '../../sync/index.js'\nimport type { CliResult, ParsedCliArgs } from '../types.js'\n\nimport {\n buildDocsManifest,\n planDocsSync,\n validateDocsManifest,\n} from '../../sync/index.js'\nimport {\n readDocsAiExportManifest,\n walkDocsFiles,\n} from '../filesystem.js'\nimport { formatIssues, formatPlanSummary, printJson } from '../format.js'\nimport { getFlagBoolean, getFlagString } from '../parseArgs.js'\nimport { getDocsCommandOptions } from './validate.js'\n\nconst deleteBehaviors = new Set<DocsDeleteBehavior>([\n 'archive',\n 'delete',\n 'draft',\n 'ignore',\n])\n\nconst isExistingDocsRecord = (value: unknown): value is ExistingDocsRecord => {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) {\n return false\n }\n\n const record = value as Record<string, unknown>\n\n return (\n typeof record.route === 'string' &&\n typeof record.sourcePath === 'string' &&\n (record.sourceHash === undefined || typeof record.sourceHash === 'string') &&\n (record.title === undefined || typeof record.title === 'string') &&\n (record.archived === undefined || typeof record.archived === 'boolean')\n )\n}\n\nconst loadExistingDocs = async (\n existingPath: string | undefined,\n): Promise<CliResult | ExistingDocsRecord[]> => {\n if (!existingPath) {\n return []\n }\n\n let parsed: unknown\n\n try {\n const raw = await readFile(existingPath, 'utf8')\n parsed = JSON.parse(raw) as unknown\n } catch (error) {\n return {\n exitCode: 1,\n stderr:\n error instanceof Error\n ? `Could not read --existing file: ${error.message}\\n`\n : 'Could not read --existing file.\\n',\n }\n }\n\n if (!Array.isArray(parsed) || !parsed.every(isExistingDocsRecord)) {\n return {\n exitCode: 1,\n stderr: '--existing must point to a JSON array of existing docs records.\\n',\n }\n }\n\n return parsed\n}\n\nexport const runPlanCommand = async (args: ParsedCliArgs): Promise<CliResult> => {\n const options = getDocsCommandOptions(args)\n\n if ('exitCode' in options) {\n return options\n }\n\n const deleteBehaviorFlag = getFlagString(args, 'delete-behavior')\n\n if (\n deleteBehaviorFlag !== undefined &&\n !deleteBehaviors.has(deleteBehaviorFlag as DocsDeleteBehavior)\n ) {\n return {\n exitCode: 1,\n stderr: '--delete-behavior must be archive, delete, draft, or ignore.\\n',\n }\n }\n\n const existing = await loadExistingDocs(getFlagString(args, 'existing'))\n\n if ('exitCode' in existing) {\n return existing\n }\n\n const files = await walkDocsFiles({\n root: options.docsRoot,\n })\n const aiExport = await readDocsAiExportManifest({\n root: options.docsRoot,\n })\n\n if (!aiExport.ok) {\n return {\n exitCode: 1,\n stderr: `AI export manifest is invalid.\\n\\nErrors:\\n${formatIssues(aiExport.issues)}\\n`,\n }\n }\n\n const deleteBehavior = deleteBehaviorFlag as DocsDeleteBehavior | undefined\n const manifest = buildDocsManifest({\n aiExport: aiExport.manifest,\n branch: options.branch,\n commit: options.commit,\n deleteBehavior,\n files,\n repository: options.repository,\n root: options.sourceRoot,\n sourceId: options.sourceId,\n })\n const validation = validateDocsManifest(manifest, {\n maxFileBytes: options.maxFileBytes,\n maxFiles: options.maxFiles,\n maxTotalBytes: options.maxTotalBytes,\n routeBase: options.routeBase,\n })\n\n if (!validation.ok) {\n return {\n exitCode: 1,\n stderr: `Manifest is invalid.\\n\\nErrors:\\n${formatIssues(validation.issues)}\\n`,\n }\n }\n\n const plan = planDocsSync({\n deleteBehavior,\n desired: validation.data,\n existing,\n })\n\n if (getFlagBoolean(args, 'json')) {\n return {\n exitCode: 0,\n stdout: printJson(plan, getFlagBoolean(args, 'pretty')),\n }\n }\n\n return {\n exitCode: 0,\n stdout: formatPlanSummary(plan),\n }\n}\n"],"names":["readFile","buildDocsManifest","planDocsSync","validateDocsManifest","readDocsAiExportManifest","walkDocsFiles","formatIssues","formatPlanSummary","printJson","getFlagBoolean","getFlagString","getDocsCommandOptions","deleteBehaviors","Set","isExistingDocsRecord","value","Array","isArray","record","route","sourcePath","sourceHash","undefined","title","archived","loadExistingDocs","existingPath","parsed","raw","JSON","parse","error","exitCode","stderr","Error","message","every","runPlanCommand","args","options","deleteBehaviorFlag","has","existing","files","root","docsRoot","aiExport","ok","issues","deleteBehavior","manifest","branch","commit","repository","sourceRoot","sourceId","validation","maxFileBytes","maxFiles","maxTotalBytes","routeBase","plan","desired","data","stdout"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/cli/commands/plan.ts"],"sourcesContent":["import { readFile } from 'node:fs/promises'\n\nimport type {\n DocsDeleteBehavior,\n ExistingDocsRecord,\n} from '../../sync/index.js'\nimport type { CliResult, ParsedCliArgs } from '../types.js'\n\nimport {\n buildDocsManifest,\n planDocsSync,\n validateDocsManifest,\n} from '../../sync/index.js'\nimport {\n readDocsAiExportManifest,\n walkDocsFiles,\n} from '../filesystem.js'\nimport { formatIssues, formatPlanSummary, printJson } from '../format.js'\nimport { getFlagBoolean, getFlagString } from '../parseArgs.js'\nimport { getDocsCommandOptions } from './validate.js'\n\nconst deleteBehaviors = new Set<DocsDeleteBehavior>([\n 'archive',\n 'delete',\n 'draft',\n 'ignore',\n])\n\nconst isExistingDocsRecord = (value: unknown): value is ExistingDocsRecord => {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) {\n return false\n }\n\n const record = value as Record<string, unknown>\n\n return (\n typeof record.route === 'string' &&\n typeof record.sourcePath === 'string' &&\n (record.sourceHash === undefined || typeof record.sourceHash === 'string') &&\n (record.title === undefined || typeof record.title === 'string') &&\n (record.archived === undefined || typeof record.archived === 'boolean')\n )\n}\n\nconst loadExistingDocs = async (\n existingPath: string | undefined,\n): Promise<CliResult | ExistingDocsRecord[]> => {\n if (!existingPath) {\n return []\n }\n\n let parsed: unknown\n\n try {\n const raw = await readFile(existingPath, 'utf8')\n parsed = JSON.parse(raw) as unknown\n } catch (error) {\n return {\n exitCode: 1,\n stderr:\n error instanceof Error\n ? `Could not read --existing file: ${error.message}\\n`\n : 'Could not read --existing file.\\n',\n }\n }\n\n if (!Array.isArray(parsed) || !parsed.every(isExistingDocsRecord)) {\n return {\n exitCode: 1,\n stderr: '--existing must point to a JSON array of existing docs records.\\n',\n }\n }\n\n return parsed\n}\n\nexport const runPlanCommand = async (args: ParsedCliArgs): Promise<CliResult> => {\n const options = getDocsCommandOptions(args)\n\n if ('exitCode' in options) {\n return options\n }\n\n const deleteBehaviorFlag = getFlagString(args, 'delete-behavior')\n\n if (\n deleteBehaviorFlag !== undefined &&\n !deleteBehaviors.has(deleteBehaviorFlag as DocsDeleteBehavior)\n ) {\n return {\n exitCode: 1,\n stderr: '--delete-behavior must be archive, delete, draft, or ignore.\\n',\n }\n }\n\n const existing = await loadExistingDocs(getFlagString(args, 'existing'))\n\n if ('exitCode' in existing) {\n return existing\n }\n\n const files = await walkDocsFiles({\n root: options.docsRoot,\n })\n const aiExport = await readDocsAiExportManifest({\n root: options.docsRoot,\n })\n\n if (!aiExport.ok) {\n return {\n exitCode: 1,\n stderr: `AI export manifest is invalid.\\n\\nErrors:\\n${formatIssues(aiExport.issues)}\\n`,\n }\n }\n\n const deleteBehavior = deleteBehaviorFlag as DocsDeleteBehavior | undefined\n const manifest = buildDocsManifest({\n aiExport: aiExport.manifest,\n branch: options.branch,\n commit: options.commit,\n deleteBehavior,\n files,\n repository: options.repository,\n sourceId: options.sourceId,\n })\n const validation = validateDocsManifest(manifest, {\n maxFileBytes: options.maxFileBytes,\n maxFiles: options.maxFiles,\n maxTotalBytes: options.maxTotalBytes,\n routeBase: `/${options.sourceId}`,\n })\n\n if (!validation.ok) {\n return {\n exitCode: 1,\n stderr: `Manifest is invalid.\\n\\nErrors:\\n${formatIssues(validation.issues)}\\n`,\n }\n }\n\n const plan = planDocsSync({\n deleteBehavior,\n desired: validation.data,\n existing,\n })\n\n if (getFlagBoolean(args, 'json')) {\n return {\n exitCode: 0,\n stdout: printJson(plan, getFlagBoolean(args, 'pretty')),\n }\n }\n\n return {\n exitCode: 0,\n stdout: formatPlanSummary(plan),\n }\n}\n"],"names":["readFile","buildDocsManifest","planDocsSync","validateDocsManifest","readDocsAiExportManifest","walkDocsFiles","formatIssues","formatPlanSummary","printJson","getFlagBoolean","getFlagString","getDocsCommandOptions","deleteBehaviors","Set","isExistingDocsRecord","value","Array","isArray","record","route","sourcePath","sourceHash","undefined","title","archived","loadExistingDocs","existingPath","parsed","raw","JSON","parse","error","exitCode","stderr","Error","message","every","runPlanCommand","args","options","deleteBehaviorFlag","has","existing","files","root","docsRoot","aiExport","ok","issues","deleteBehavior","manifest","branch","commit","repository","sourceId","validation","maxFileBytes","maxFiles","maxTotalBytes","routeBase","plan","desired","data","stdout"],"mappings":"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"}
@@ -1,5 +1,4 @@
1
1
  import { readFile } from 'node:fs/promises';
2
- import { DEFAULT_GITHUB_OIDC_AUDIENCE } from '../../constants.js';
3
2
  import { signDocsSyncRequest } from '../../security/index.js';
4
3
  import { buildDocsManifest, sha256Hex, validateDocsManifest } from '../../sync/index.js';
5
4
  import { readDocsAiExportManifest, walkDocsFiles } from '../filesystem.js';
@@ -172,7 +171,6 @@ const getPushCommandOptions = async (args)=>{
172
171
  return {
173
172
  ...baseOptions,
174
173
  authMode: 'github-oidc',
175
- oidcAudience: getFlagString(args, 'oidc-audience') ?? DEFAULT_GITHUB_OIDC_AUDIENCE,
176
174
  oidcTokenEnv: getFlagString(args, 'oidc-token-env')
177
175
  };
178
176
  }
@@ -226,14 +224,13 @@ export const runPushCommand = async (args, httpPost = postJson, httpGet = getJso
226
224
  mode: options.mode,
227
225
  publish: options.publish,
228
226
  repository: options.repository,
229
- root: options.sourceRoot,
230
227
  sourceId: options.sourceId
231
228
  });
232
229
  const validation = validateDocsManifest(manifest, {
233
230
  maxFileBytes: options.maxFileBytes,
234
231
  maxFiles: options.maxFiles,
235
232
  maxTotalBytes: options.maxTotalBytes,
236
- routeBase: options.routeBase
233
+ routeBase: `/${options.sourceId}`
237
234
  });
238
235
  if (!validation.ok) {
239
236
  return {
@@ -246,7 +243,7 @@ export const runPushCommand = async (args, httpPost = postJson, httpGet = getJso
246
243
  if (options.authMode === 'github-oidc') {
247
244
  const oidcToken = await readGithubOidcToken({
248
245
  args,
249
- audience: options.oidcAudience,
246
+ audience: options.sourceId,
250
247
  httpGet
251
248
  });
252
249
  if (typeof oidcToken !== 'string') {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/cli/commands/push.ts"],"sourcesContent":["import { readFile } from 'node:fs/promises'\n\nimport type { DocsDeleteBehavior } from '../../sync/index.js'\nimport type {\n HttpGetJson,\n HttpPostJson,\n} from '../http.js'\nimport type {\n CliResult,\n ParsedCliArgs,\n PushCommandOptions,\n} from '../types.js'\n\nimport { DEFAULT_GITHUB_OIDC_AUDIENCE } from '../../constants.js'\nimport { signDocsSyncRequest } from '../../security/index.js'\nimport {\n buildDocsManifest,\n sha256Hex,\n validateDocsManifest,\n} from '../../sync/index.js'\nimport {\n readDocsAiExportManifest,\n walkDocsFiles,\n} from '../filesystem.js'\nimport { formatIssues, formatPushSummary, printJson } from '../format.js'\nimport {\n getJson,\n postJson,\n} from '../http.js'\nimport { getFlagBoolean, getFlagString } from '../parseArgs.js'\nimport { getDocsCommandOptions } from './validate.js'\n\nconst supportedPushDeleteBehaviors = new Set<DocsDeleteBehavior>([\n 'archive',\n 'delete',\n 'draft',\n 'ignore',\n])\n\ntype ServerPushResponse = {\n deleteBehavior?: string\n effectivePublishMode?: string\n error?: {\n code?: string\n message?: string\n }\n ok?: boolean\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}\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === 'object' && value !== null && !Array.isArray(value)\n\nconst isServerPushResponse = (value: unknown): value is ServerPushResponse =>\n isRecord(value)\n\nconst validateEndpointUrl = (endpoint: string): CliResult | string => {\n try {\n const parsed = new URL(endpoint)\n\n if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {\n return {\n exitCode: 1,\n stderr: '--endpoint must be a full http:// or https:// URL.\\n',\n }\n }\n\n return parsed.toString()\n } catch {\n return {\n exitCode: 1,\n stderr: '--endpoint must be a valid full http:// or https:// URL.\\n',\n }\n }\n}\n\nconst readPrivateKey = async (\n args: ParsedCliArgs,\n): Promise<CliResult | string> => {\n const privateKeyFile = getFlagString(args, 'private-key-file')\n const privateKeyEnv = getFlagString(args, 'private-key-env')\n\n if (privateKeyFile && privateKeyEnv) {\n return {\n exitCode: 1,\n stderr:\n 'Use either --private-key-file or --private-key-env, not both.\\n',\n }\n }\n\n if (!privateKeyFile && !privateKeyEnv) {\n return {\n exitCode: 1,\n stderr: 'Push requires --private-key-file or --private-key-env.\\n',\n }\n }\n\n if (privateKeyEnv) {\n const privateKey = process.env[privateKeyEnv]\n\n if (!privateKey) {\n return {\n exitCode: 1,\n stderr: `Environment variable \"${privateKeyEnv}\" is not set.\\n`,\n }\n }\n\n return privateKey\n }\n\n try {\n return await readFile(privateKeyFile ?? '', 'utf8')\n } catch (error) {\n return {\n exitCode: 1,\n stderr:\n error instanceof Error\n ? `Could not read private key file: ${error.message}\\n`\n : 'Could not read private key file.\\n',\n }\n }\n}\n\nconst getGithubOidcTokenRequestUrl = ({\n audience,\n requestUrl,\n}: {\n audience: string\n requestUrl: string\n}): CliResult | string => {\n try {\n const url = new URL(requestUrl)\n url.searchParams.set('audience', audience)\n\n return url.toString()\n } catch {\n return {\n exitCode: 1,\n stderr: 'ACTIONS_ID_TOKEN_REQUEST_URL is not a valid URL.\\n',\n }\n }\n}\n\nconst readGithubOidcToken = async ({\n args,\n audience,\n httpGet,\n}: {\n args: ParsedCliArgs\n audience: string\n httpGet: HttpGetJson\n}): Promise<CliResult | string> => {\n const tokenEnv = getFlagString(args, 'oidc-token-env')\n\n if (tokenEnv) {\n const token = process.env[tokenEnv]\n\n if (!token) {\n return {\n exitCode: 1,\n stderr: `Environment variable \"${tokenEnv}\" is not set.\\n`,\n }\n }\n\n return token\n }\n\n const requestUrl = process.env.ACTIONS_ID_TOKEN_REQUEST_URL\n const requestToken = process.env.ACTIONS_ID_TOKEN_REQUEST_TOKEN\n\n if (!requestUrl || !requestToken) {\n return {\n exitCode: 1,\n stderr:\n 'GitHub OIDC push requires ACTIONS_ID_TOKEN_REQUEST_URL and ACTIONS_ID_TOKEN_REQUEST_TOKEN, or --oidc-token-env.\\n',\n }\n }\n\n const url = getGithubOidcTokenRequestUrl({\n audience,\n requestUrl,\n })\n\n if (typeof url !== 'string') {\n return url\n }\n\n const response = await httpGet({\n headers: {\n Authorization: `bearer ${requestToken}`,\n },\n url,\n })\n\n if (!response.ok || !isRecord(response.body) || typeof response.body.value !== 'string') {\n return {\n exitCode: 1,\n stderr: `Could not retrieve GitHub OIDC token. HTTP status ${response.status}.\\n`,\n }\n }\n\n return response.body.value\n}\n\nconst getPushCommandOptions = async (\n args: ParsedCliArgs,\n): Promise<CliResult | PushCommandOptions> => {\n const docsOptions = getDocsCommandOptions(args)\n\n if ('exitCode' in docsOptions) {\n return docsOptions\n }\n\n const endpointFlag = getFlagString(args, 'endpoint')\n\n if (!endpointFlag) {\n return {\n exitCode: 1,\n stderr: 'Push requires --endpoint <url>.\\n',\n }\n }\n\n const endpoint = validateEndpointUrl(endpointFlag)\n\n if (typeof endpoint !== 'string') {\n return endpoint\n }\n\n if (getFlagBoolean(args, 'dry-run') && getFlagBoolean(args, 'sync')) {\n return {\n exitCode: 1,\n stderr: 'Use either --dry-run or --sync, not both.\\n',\n }\n }\n\n const deleteBehaviorFlag = getFlagString(args, 'delete-behavior')\n\n if (\n deleteBehaviorFlag !== undefined &&\n !supportedPushDeleteBehaviors.has(deleteBehaviorFlag as DocsDeleteBehavior)\n ) {\n return {\n exitCode: 1,\n stderr: '--delete-behavior for push must be archive, delete, draft, or ignore.\\n',\n }\n }\n\n const mode: PushCommandOptions['mode'] = getFlagBoolean(args, 'sync')\n ? 'sync'\n : 'dry-run'\n const baseOptions = {\n ...docsOptions,\n deleteBehavior: deleteBehaviorFlag as DocsDeleteBehavior | undefined,\n endpoint,\n mode,\n publish: getFlagBoolean(args, 'publish'),\n }\n\n if (getFlagBoolean(args, 'github-oidc')) {\n if (getFlagString(args, 'key-id')) {\n return {\n exitCode: 1,\n stderr: 'Do not use --key-id with --github-oidc.\\n',\n }\n }\n\n if (getFlagString(args, 'private-key-file') || getFlagString(args, 'private-key-env')) {\n return {\n exitCode: 1,\n stderr: 'Do not use Ed25519 private key flags with --github-oidc.\\n',\n }\n }\n\n return {\n ...baseOptions,\n authMode: 'github-oidc',\n oidcAudience:\n getFlagString(args, 'oidc-audience') ?? DEFAULT_GITHUB_OIDC_AUDIENCE,\n oidcTokenEnv: getFlagString(args, 'oidc-token-env'),\n }\n }\n\n const keyId = getFlagString(args, 'key-id')\n\n if (!keyId) {\n return {\n exitCode: 1,\n stderr: 'Push requires --key-id <id>.\\n',\n }\n }\n\n const privateKey = await readPrivateKey(args)\n\n if (typeof privateKey !== 'string') {\n return privateKey\n }\n\n return {\n ...baseOptions,\n authMode: 'ed25519',\n keyId,\n privateKey,\n }\n}\n\nconst formatServerFailure = ({\n body,\n status,\n}: {\n body: unknown\n status: number\n}): string => {\n if (isServerPushResponse(body) && body.error?.message) {\n return `${body.error.message}\\n`\n }\n\n return `Sync request failed with HTTP status ${status}.\\n`\n}\n\nexport const runPushCommand = async (\n args: ParsedCliArgs,\n httpPost: HttpPostJson = postJson,\n httpGet: HttpGetJson = getJson,\n): Promise<CliResult> => {\n const options = await getPushCommandOptions(args)\n\n if ('exitCode' in options) {\n return options\n }\n\n const files = await walkDocsFiles({\n root: options.docsRoot,\n })\n const aiExport = await readDocsAiExportManifest({\n root: options.docsRoot,\n })\n\n if (!aiExport.ok) {\n return {\n exitCode: 1,\n stderr: `AI export manifest is invalid.\\n\\nErrors:\\n${formatIssues(aiExport.issues)}\\n`,\n }\n }\n\n const manifest = buildDocsManifest({\n aiExport: aiExport.manifest,\n branch: options.branch,\n commit: options.commit,\n deleteBehavior: options.deleteBehavior ?? 'archive',\n files,\n mode: options.mode,\n publish: options.publish,\n repository: options.repository,\n root: options.sourceRoot,\n sourceId: options.sourceId,\n })\n const validation = validateDocsManifest(manifest, {\n maxFileBytes: options.maxFileBytes,\n maxFiles: options.maxFiles,\n maxTotalBytes: options.maxTotalBytes,\n routeBase: options.routeBase,\n })\n\n if (!validation.ok) {\n return {\n exitCode: 1,\n stderr: `Manifest is invalid.\\n\\nErrors:\\n${formatIssues(validation.issues)}\\n`,\n }\n }\n\n const body = JSON.stringify(manifest)\n let signedRequest:\n | {\n body: string\n headers: Record<string, string>\n }\n | ReturnType<typeof signDocsSyncRequest>\n\n if (options.authMode === 'github-oidc') {\n const oidcToken = await readGithubOidcToken({\n args,\n audience: options.oidcAudience,\n httpGet,\n })\n\n if (typeof oidcToken !== 'string') {\n return oidcToken\n }\n\n signedRequest = {\n body,\n headers: {\n Authorization: `Bearer ${oidcToken}`,\n 'Content-Type': 'application/json',\n 'X-VL-MD-DOCS-Body-SHA256': sha256Hex(body),\n },\n }\n } else {\n signedRequest = signDocsSyncRequest({\n body,\n endpoint: options.endpoint,\n keyId: options.keyId,\n privateKey: options.privateKey,\n })\n }\n\n const response = await httpPost({\n body: signedRequest.body,\n headers: signedRequest.headers,\n url: options.endpoint,\n })\n\n if (getFlagBoolean(args, 'json')) {\n return {\n exitCode:\n response.ok &&\n isServerPushResponse(response.body) &&\n response.body.ok === true\n ? 0\n : 1,\n stdout: printJson(\n {\n endpoint: options.endpoint,\n mode: options.mode,\n response: response.body,\n sourceId: options.sourceId,\n status: response.status,\n },\n getFlagBoolean(args, 'pretty'),\n ),\n }\n }\n\n if (\n !response.ok ||\n !isServerPushResponse(response.body) ||\n response.body.ok !== true\n ) {\n return {\n exitCode: 1,\n stderr: formatServerFailure({\n body: response.body,\n status: response.status,\n }),\n }\n }\n\n return {\n exitCode: 0,\n stdout: formatPushSummary({\n endpoint: options.endpoint,\n mode: options.mode,\n response: response.body,\n sourceId: options.sourceId,\n }),\n }\n}\n"],"names":["readFile","DEFAULT_GITHUB_OIDC_AUDIENCE","signDocsSyncRequest","buildDocsManifest","sha256Hex","validateDocsManifest","readDocsAiExportManifest","walkDocsFiles","formatIssues","formatPushSummary","printJson","getJson","postJson","getFlagBoolean","getFlagString","getDocsCommandOptions","supportedPushDeleteBehaviors","Set","isRecord","value","Array","isArray","isServerPushResponse","validateEndpointUrl","endpoint","parsed","URL","protocol","exitCode","stderr","toString","readPrivateKey","args","privateKeyFile","privateKeyEnv","privateKey","process","env","error","Error","message","getGithubOidcTokenRequestUrl","audience","requestUrl","url","searchParams","set","readGithubOidcToken","httpGet","tokenEnv","token","ACTIONS_ID_TOKEN_REQUEST_URL","requestToken","ACTIONS_ID_TOKEN_REQUEST_TOKEN","response","headers","Authorization","ok","body","status","getPushCommandOptions","docsOptions","endpointFlag","deleteBehaviorFlag","undefined","has","mode","baseOptions","deleteBehavior","publish","authMode","oidcAudience","oidcTokenEnv","keyId","formatServerFailure","runPushCommand","httpPost","options","files","root","docsRoot","aiExport","issues","manifest","branch","commit","repository","sourceRoot","sourceId","validation","maxFileBytes","maxFiles","maxTotalBytes","routeBase","JSON","stringify","signedRequest","oidcToken","stdout"],"mappings":"AAAA,SAASA,QAAQ,QAAQ,mBAAkB;AAa3C,SAASC,4BAA4B,QAAQ,qBAAoB;AACjE,SAASC,mBAAmB,QAAQ,0BAAyB;AAC7D,SACEC,iBAAiB,EACjBC,SAAS,EACTC,oBAAoB,QACf,sBAAqB;AAC5B,SACEC,wBAAwB,EACxBC,aAAa,QACR,mBAAkB;AACzB,SAASC,YAAY,EAAEC,iBAAiB,EAAEC,SAAS,QAAQ,eAAc;AACzE,SACEC,OAAO,EACPC,QAAQ,QACH,aAAY;AACnB,SAASC,cAAc,EAAEC,aAAa,QAAQ,kBAAiB;AAC/D,SAASC,qBAAqB,QAAQ,gBAAe;AAErD,MAAMC,+BAA+B,IAAIC,IAAwB;IAC/D;IACA;IACA;IACA;CACD;AAuBD,MAAMC,WAAW,CAACC,QAChB,OAAOA,UAAU,YAAYA,UAAU,QAAQ,CAACC,MAAMC,OAAO,CAACF;AAEhE,MAAMG,uBAAuB,CAACH,QAC5BD,SAASC;AAEX,MAAMI,sBAAsB,CAACC;IAC3B,IAAI;QACF,MAAMC,SAAS,IAAIC,IAAIF;QAEvB,IAAIC,OAAOE,QAAQ,KAAK,WAAWF,OAAOE,QAAQ,KAAK,UAAU;YAC/D,OAAO;gBACLC,UAAU;gBACVC,QAAQ;YACV;QACF;QAEA,OAAOJ,OAAOK,QAAQ;IACxB,EAAE,OAAM;QACN,OAAO;YACLF,UAAU;YACVC,QAAQ;QACV;IACF;AACF;AAEA,MAAME,iBAAiB,OACrBC;IAEA,MAAMC,iBAAiBnB,cAAckB,MAAM;IAC3C,MAAME,gBAAgBpB,cAAckB,MAAM;IAE1C,IAAIC,kBAAkBC,eAAe;QACnC,OAAO;YACLN,UAAU;YACVC,QACE;QACJ;IACF;IAEA,IAAI,CAACI,kBAAkB,CAACC,eAAe;QACrC,OAAO;YACLN,UAAU;YACVC,QAAQ;QACV;IACF;IAEA,IAAIK,eAAe;QACjB,MAAMC,aAAaC,QAAQC,GAAG,CAACH,cAAc;QAE7C,IAAI,CAACC,YAAY;YACf,OAAO;gBACLP,UAAU;gBACVC,QAAQ,CAAC,sBAAsB,EAAEK,cAAc,eAAe,CAAC;YACjE;QACF;QAEA,OAAOC;IACT;IAEA,IAAI;QACF,OAAO,MAAMnC,SAASiC,kBAAkB,IAAI;IAC9C,EAAE,OAAOK,OAAO;QACd,OAAO;YACLV,UAAU;YACVC,QACES,iBAAiBC,QACb,CAAC,iCAAiC,EAAED,MAAME,OAAO,CAAC,EAAE,CAAC,GACrD;QACR;IACF;AACF;AAEA,MAAMC,+BAA+B,CAAC,EACpCC,QAAQ,EACRC,UAAU,EAIX;IACC,IAAI;QACF,MAAMC,MAAM,IAAIlB,IAAIiB;QACpBC,IAAIC,YAAY,CAACC,GAAG,CAAC,YAAYJ;QAEjC,OAAOE,IAAId,QAAQ;IACrB,EAAE,OAAM;QACN,OAAO;YACLF,UAAU;YACVC,QAAQ;QACV;IACF;AACF;AAEA,MAAMkB,sBAAsB,OAAO,EACjCf,IAAI,EACJU,QAAQ,EACRM,OAAO,EAKR;IACC,MAAMC,WAAWnC,cAAckB,MAAM;IAErC,IAAIiB,UAAU;QACZ,MAAMC,QAAQd,QAAQC,GAAG,CAACY,SAAS;QAEnC,IAAI,CAACC,OAAO;YACV,OAAO;gBACLtB,UAAU;gBACVC,QAAQ,CAAC,sBAAsB,EAAEoB,SAAS,eAAe,CAAC;YAC5D;QACF;QAEA,OAAOC;IACT;IAEA,MAAMP,aAAaP,QAAQC,GAAG,CAACc,4BAA4B;IAC3D,MAAMC,eAAehB,QAAQC,GAAG,CAACgB,8BAA8B;IAE/D,IAAI,CAACV,cAAc,CAACS,cAAc;QAChC,OAAO;YACLxB,UAAU;YACVC,QACE;QACJ;IACF;IAEA,MAAMe,MAAMH,6BAA6B;QACvCC;QACAC;IACF;IAEA,IAAI,OAAOC,QAAQ,UAAU;QAC3B,OAAOA;IACT;IAEA,MAAMU,WAAW,MAAMN,QAAQ;QAC7BO,SAAS;YACPC,eAAe,CAAC,OAAO,EAAEJ,cAAc;QACzC;QACAR;IACF;IAEA,IAAI,CAACU,SAASG,EAAE,IAAI,CAACvC,SAASoC,SAASI,IAAI,KAAK,OAAOJ,SAASI,IAAI,CAACvC,KAAK,KAAK,UAAU;QACvF,OAAO;YACLS,UAAU;YACVC,QAAQ,CAAC,kDAAkD,EAAEyB,SAASK,MAAM,CAAC,GAAG,CAAC;QACnF;IACF;IAEA,OAAOL,SAASI,IAAI,CAACvC,KAAK;AAC5B;AAEA,MAAMyC,wBAAwB,OAC5B5B;IAEA,MAAM6B,cAAc9C,sBAAsBiB;IAE1C,IAAI,cAAc6B,aAAa;QAC7B,OAAOA;IACT;IAEA,MAAMC,eAAehD,cAAckB,MAAM;IAEzC,IAAI,CAAC8B,cAAc;QACjB,OAAO;YACLlC,UAAU;YACVC,QAAQ;QACV;IACF;IAEA,MAAML,WAAWD,oBAAoBuC;IAErC,IAAI,OAAOtC,aAAa,UAAU;QAChC,OAAOA;IACT;IAEA,IAAIX,eAAemB,MAAM,cAAcnB,eAAemB,MAAM,SAAS;QACnE,OAAO;YACLJ,UAAU;YACVC,QAAQ;QACV;IACF;IAEA,MAAMkC,qBAAqBjD,cAAckB,MAAM;IAE/C,IACE+B,uBAAuBC,aACvB,CAAChD,6BAA6BiD,GAAG,CAACF,qBAClC;QACA,OAAO;YACLnC,UAAU;YACVC,QAAQ;QACV;IACF;IAEA,MAAMqC,OAAmCrD,eAAemB,MAAM,UAC1D,SACA;IACJ,MAAMmC,cAAc;QAClB,GAAGN,WAAW;QACdO,gBAAgBL;QAChBvC;QACA0C;QACAG,SAASxD,eAAemB,MAAM;IAChC;IAEA,IAAInB,eAAemB,MAAM,gBAAgB;QACvC,IAAIlB,cAAckB,MAAM,WAAW;YACjC,OAAO;gBACLJ,UAAU;gBACVC,QAAQ;YACV;QACF;QAEA,IAAIf,cAAckB,MAAM,uBAAuBlB,cAAckB,MAAM,oBAAoB;YACrF,OAAO;gBACLJ,UAAU;gBACVC,QAAQ;YACV;QACF;QAEA,OAAO;YACL,GAAGsC,WAAW;YACdG,UAAU;YACVC,cACEzD,cAAckB,MAAM,oBAAoB/B;YAC1CuE,cAAc1D,cAAckB,MAAM;QACpC;IACF;IAEA,MAAMyC,QAAQ3D,cAAckB,MAAM;IAElC,IAAI,CAACyC,OAAO;QACV,OAAO;YACL7C,UAAU;YACVC,QAAQ;QACV;IACF;IAEA,MAAMM,aAAa,MAAMJ,eAAeC;IAExC,IAAI,OAAOG,eAAe,UAAU;QAClC,OAAOA;IACT;IAEA,OAAO;QACL,GAAGgC,WAAW;QACdG,UAAU;QACVG;QACAtC;IACF;AACF;AAEA,MAAMuC,sBAAsB,CAAC,EAC3BhB,IAAI,EACJC,MAAM,EAIP;IACC,IAAIrC,qBAAqBoC,SAASA,KAAKpB,KAAK,EAAEE,SAAS;QACrD,OAAO,GAAGkB,KAAKpB,KAAK,CAACE,OAAO,CAAC,EAAE,CAAC;IAClC;IAEA,OAAO,CAAC,qCAAqC,EAAEmB,OAAO,GAAG,CAAC;AAC5D;AAEA,OAAO,MAAMgB,iBAAiB,OAC5B3C,MACA4C,WAAyBhE,QAAQ,EACjCoC,UAAuBrC,OAAO;IAE9B,MAAMkE,UAAU,MAAMjB,sBAAsB5B;IAE5C,IAAI,cAAc6C,SAAS;QACzB,OAAOA;IACT;IAEA,MAAMC,QAAQ,MAAMvE,cAAc;QAChCwE,MAAMF,QAAQG,QAAQ;IACxB;IACA,MAAMC,WAAW,MAAM3E,yBAAyB;QAC9CyE,MAAMF,QAAQG,QAAQ;IACxB;IAEA,IAAI,CAACC,SAASxB,EAAE,EAAE;QAChB,OAAO;YACL7B,UAAU;YACVC,QAAQ,CAAC,2CAA2C,EAAErB,aAAayE,SAASC,MAAM,EAAE,EAAE,CAAC;QACzF;IACF;IAEA,MAAMC,WAAWhF,kBAAkB;QACjC8E,UAAUA,SAASE,QAAQ;QAC3BC,QAAQP,QAAQO,MAAM;QACtBC,QAAQR,QAAQQ,MAAM;QACtBjB,gBAAgBS,QAAQT,cAAc,IAAI;QAC1CU;QACAZ,MAAMW,QAAQX,IAAI;QAClBG,SAASQ,QAAQR,OAAO;QACxBiB,YAAYT,QAAQS,UAAU;QAC9BP,MAAMF,QAAQU,UAAU;QACxBC,UAAUX,QAAQW,QAAQ;IAC5B;IACA,MAAMC,aAAapF,qBAAqB8E,UAAU;QAChDO,cAAcb,QAAQa,YAAY;QAClCC,UAAUd,QAAQc,QAAQ;QAC1BC,eAAef,QAAQe,aAAa;QACpCC,WAAWhB,QAAQgB,SAAS;IAC9B;IAEA,IAAI,CAACJ,WAAWhC,EAAE,EAAE;QAClB,OAAO;YACL7B,UAAU;YACVC,QAAQ,CAAC,iCAAiC,EAAErB,aAAaiF,WAAWP,MAAM,EAAE,EAAE,CAAC;QACjF;IACF;IAEA,MAAMxB,OAAOoC,KAAKC,SAAS,CAACZ;IAC5B,IAAIa;IAOJ,IAAInB,QAAQP,QAAQ,KAAK,eAAe;QACtC,MAAM2B,YAAY,MAAMlD,oBAAoB;YAC1Cf;YACAU,UAAUmC,QAAQN,YAAY;YAC9BvB;QACF;QAEA,IAAI,OAAOiD,cAAc,UAAU;YACjC,OAAOA;QACT;QAEAD,gBAAgB;YACdtC;YACAH,SAAS;gBACPC,eAAe,CAAC,OAAO,EAAEyC,WAAW;gBACpC,gBAAgB;gBAChB,4BAA4B7F,UAAUsD;YACxC;QACF;IACF,OAAO;QACLsC,gBAAgB9F,oBAAoB;YAClCwD;YACAlC,UAAUqD,QAAQrD,QAAQ;YAC1BiD,OAAOI,QAAQJ,KAAK;YACpBtC,YAAY0C,QAAQ1C,UAAU;QAChC;IACF;IAEA,MAAMmB,WAAW,MAAMsB,SAAS;QAC9BlB,MAAMsC,cAActC,IAAI;QACxBH,SAASyC,cAAczC,OAAO;QAC9BX,KAAKiC,QAAQrD,QAAQ;IACvB;IAEA,IAAIX,eAAemB,MAAM,SAAS;QAChC,OAAO;YACLJ,UACE0B,SAASG,EAAE,IACXnC,qBAAqBgC,SAASI,IAAI,KAClCJ,SAASI,IAAI,CAACD,EAAE,KAAK,OACjB,IACA;YACNyC,QAAQxF,UACN;gBACEc,UAAUqD,QAAQrD,QAAQ;gBAC1B0C,MAAMW,QAAQX,IAAI;gBAClBZ,UAAUA,SAASI,IAAI;gBACvB8B,UAAUX,QAAQW,QAAQ;gBAC1B7B,QAAQL,SAASK,MAAM;YACzB,GACA9C,eAAemB,MAAM;QAEzB;IACF;IAEA,IACE,CAACsB,SAASG,EAAE,IACZ,CAACnC,qBAAqBgC,SAASI,IAAI,KACnCJ,SAASI,IAAI,CAACD,EAAE,KAAK,MACrB;QACA,OAAO;YACL7B,UAAU;YACVC,QAAQ6C,oBAAoB;gBAC1BhB,MAAMJ,SAASI,IAAI;gBACnBC,QAAQL,SAASK,MAAM;YACzB;QACF;IACF;IAEA,OAAO;QACL/B,UAAU;QACVsE,QAAQzF,kBAAkB;YACxBe,UAAUqD,QAAQrD,QAAQ;YAC1B0C,MAAMW,QAAQX,IAAI;YAClBZ,UAAUA,SAASI,IAAI;YACvB8B,UAAUX,QAAQW,QAAQ;QAC5B;IACF;AACF,EAAC"}
1
+ {"version":3,"sources":["../../../src/cli/commands/push.ts"],"sourcesContent":["import { readFile } from 'node:fs/promises'\n\nimport type { DocsDeleteBehavior } from '../../sync/index.js'\nimport type {\n HttpGetJson,\n HttpPostJson,\n} from '../http.js'\nimport type {\n CliResult,\n ParsedCliArgs,\n PushCommandOptions,\n} from '../types.js'\n\nimport { signDocsSyncRequest } from '../../security/index.js'\nimport {\n buildDocsManifest,\n sha256Hex,\n validateDocsManifest,\n} from '../../sync/index.js'\nimport {\n readDocsAiExportManifest,\n walkDocsFiles,\n} from '../filesystem.js'\nimport { formatIssues, formatPushSummary, printJson } from '../format.js'\nimport {\n getJson,\n postJson,\n} from '../http.js'\nimport { getFlagBoolean, getFlagString } from '../parseArgs.js'\nimport { getDocsCommandOptions } from './validate.js'\n\nconst supportedPushDeleteBehaviors = new Set<DocsDeleteBehavior>([\n 'archive',\n 'delete',\n 'draft',\n 'ignore',\n])\n\ntype ServerPushResponse = {\n deleteBehavior?: string\n effectivePublishMode?: string\n error?: {\n code?: string\n message?: string\n }\n ok?: boolean\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}\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === 'object' && value !== null && !Array.isArray(value)\n\nconst isServerPushResponse = (value: unknown): value is ServerPushResponse =>\n isRecord(value)\n\nconst validateEndpointUrl = (endpoint: string): CliResult | string => {\n try {\n const parsed = new URL(endpoint)\n\n if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {\n return {\n exitCode: 1,\n stderr: '--endpoint must be a full http:// or https:// URL.\\n',\n }\n }\n\n return parsed.toString()\n } catch {\n return {\n exitCode: 1,\n stderr: '--endpoint must be a valid full http:// or https:// URL.\\n',\n }\n }\n}\n\nconst readPrivateKey = async (\n args: ParsedCliArgs,\n): Promise<CliResult | string> => {\n const privateKeyFile = getFlagString(args, 'private-key-file')\n const privateKeyEnv = getFlagString(args, 'private-key-env')\n\n if (privateKeyFile && privateKeyEnv) {\n return {\n exitCode: 1,\n stderr:\n 'Use either --private-key-file or --private-key-env, not both.\\n',\n }\n }\n\n if (!privateKeyFile && !privateKeyEnv) {\n return {\n exitCode: 1,\n stderr: 'Push requires --private-key-file or --private-key-env.\\n',\n }\n }\n\n if (privateKeyEnv) {\n const privateKey = process.env[privateKeyEnv]\n\n if (!privateKey) {\n return {\n exitCode: 1,\n stderr: `Environment variable \"${privateKeyEnv}\" is not set.\\n`,\n }\n }\n\n return privateKey\n }\n\n try {\n return await readFile(privateKeyFile ?? '', 'utf8')\n } catch (error) {\n return {\n exitCode: 1,\n stderr:\n error instanceof Error\n ? `Could not read private key file: ${error.message}\\n`\n : 'Could not read private key file.\\n',\n }\n }\n}\n\nconst getGithubOidcTokenRequestUrl = ({\n audience,\n requestUrl,\n}: {\n audience: string\n requestUrl: string\n}): CliResult | string => {\n try {\n const url = new URL(requestUrl)\n url.searchParams.set('audience', audience)\n\n return url.toString()\n } catch {\n return {\n exitCode: 1,\n stderr: 'ACTIONS_ID_TOKEN_REQUEST_URL is not a valid URL.\\n',\n }\n }\n}\n\nconst readGithubOidcToken = async ({\n args,\n audience,\n httpGet,\n}: {\n args: ParsedCliArgs\n audience: string\n httpGet: HttpGetJson\n}): Promise<CliResult | string> => {\n const tokenEnv = getFlagString(args, 'oidc-token-env')\n\n if (tokenEnv) {\n const token = process.env[tokenEnv]\n\n if (!token) {\n return {\n exitCode: 1,\n stderr: `Environment variable \"${tokenEnv}\" is not set.\\n`,\n }\n }\n\n return token\n }\n\n const requestUrl = process.env.ACTIONS_ID_TOKEN_REQUEST_URL\n const requestToken = process.env.ACTIONS_ID_TOKEN_REQUEST_TOKEN\n\n if (!requestUrl || !requestToken) {\n return {\n exitCode: 1,\n stderr:\n 'GitHub OIDC push requires ACTIONS_ID_TOKEN_REQUEST_URL and ACTIONS_ID_TOKEN_REQUEST_TOKEN, or --oidc-token-env.\\n',\n }\n }\n\n const url = getGithubOidcTokenRequestUrl({\n audience,\n requestUrl,\n })\n\n if (typeof url !== 'string') {\n return url\n }\n\n const response = await httpGet({\n headers: {\n Authorization: `bearer ${requestToken}`,\n },\n url,\n })\n\n if (!response.ok || !isRecord(response.body) || typeof response.body.value !== 'string') {\n return {\n exitCode: 1,\n stderr: `Could not retrieve GitHub OIDC token. HTTP status ${response.status}.\\n`,\n }\n }\n\n return response.body.value\n}\n\nconst getPushCommandOptions = async (\n args: ParsedCliArgs,\n): Promise<CliResult | PushCommandOptions> => {\n const docsOptions = getDocsCommandOptions(args)\n\n if ('exitCode' in docsOptions) {\n return docsOptions\n }\n\n const endpointFlag = getFlagString(args, 'endpoint')\n\n if (!endpointFlag) {\n return {\n exitCode: 1,\n stderr: 'Push requires --endpoint <url>.\\n',\n }\n }\n\n const endpoint = validateEndpointUrl(endpointFlag)\n\n if (typeof endpoint !== 'string') {\n return endpoint\n }\n\n if (getFlagBoolean(args, 'dry-run') && getFlagBoolean(args, 'sync')) {\n return {\n exitCode: 1,\n stderr: 'Use either --dry-run or --sync, not both.\\n',\n }\n }\n\n const deleteBehaviorFlag = getFlagString(args, 'delete-behavior')\n\n if (\n deleteBehaviorFlag !== undefined &&\n !supportedPushDeleteBehaviors.has(deleteBehaviorFlag as DocsDeleteBehavior)\n ) {\n return {\n exitCode: 1,\n stderr: '--delete-behavior for push must be archive, delete, draft, or ignore.\\n',\n }\n }\n\n const mode: PushCommandOptions['mode'] = getFlagBoolean(args, 'sync')\n ? 'sync'\n : 'dry-run'\n const baseOptions = {\n ...docsOptions,\n deleteBehavior: deleteBehaviorFlag as DocsDeleteBehavior | undefined,\n endpoint,\n mode,\n publish: getFlagBoolean(args, 'publish'),\n }\n\n if (getFlagBoolean(args, 'github-oidc')) {\n if (getFlagString(args, 'key-id')) {\n return {\n exitCode: 1,\n stderr: 'Do not use --key-id with --github-oidc.\\n',\n }\n }\n\n if (getFlagString(args, 'private-key-file') || getFlagString(args, 'private-key-env')) {\n return {\n exitCode: 1,\n stderr: 'Do not use Ed25519 private key flags with --github-oidc.\\n',\n }\n }\n\n return {\n ...baseOptions,\n authMode: 'github-oidc',\n oidcTokenEnv: getFlagString(args, 'oidc-token-env'),\n }\n }\n\n const keyId = getFlagString(args, 'key-id')\n\n if (!keyId) {\n return {\n exitCode: 1,\n stderr: 'Push requires --key-id <id>.\\n',\n }\n }\n\n const privateKey = await readPrivateKey(args)\n\n if (typeof privateKey !== 'string') {\n return privateKey\n }\n\n return {\n ...baseOptions,\n authMode: 'ed25519',\n keyId,\n privateKey,\n }\n}\n\nconst formatServerFailure = ({\n body,\n status,\n}: {\n body: unknown\n status: number\n}): string => {\n if (isServerPushResponse(body) && body.error?.message) {\n return `${body.error.message}\\n`\n }\n\n return `Sync request failed with HTTP status ${status}.\\n`\n}\n\nexport const runPushCommand = async (\n args: ParsedCliArgs,\n httpPost: HttpPostJson = postJson,\n httpGet: HttpGetJson = getJson,\n): Promise<CliResult> => {\n const options = await getPushCommandOptions(args)\n\n if ('exitCode' in options) {\n return options\n }\n\n const files = await walkDocsFiles({\n root: options.docsRoot,\n })\n const aiExport = await readDocsAiExportManifest({\n root: options.docsRoot,\n })\n\n if (!aiExport.ok) {\n return {\n exitCode: 1,\n stderr: `AI export manifest is invalid.\\n\\nErrors:\\n${formatIssues(aiExport.issues)}\\n`,\n }\n }\n\n const manifest = buildDocsManifest({\n aiExport: aiExport.manifest,\n branch: options.branch,\n commit: options.commit,\n deleteBehavior: options.deleteBehavior ?? 'archive',\n files,\n mode: options.mode,\n publish: options.publish,\n repository: options.repository,\n sourceId: options.sourceId,\n })\n const validation = validateDocsManifest(manifest, {\n maxFileBytes: options.maxFileBytes,\n maxFiles: options.maxFiles,\n maxTotalBytes: options.maxTotalBytes,\n routeBase: `/${options.sourceId}`,\n })\n\n if (!validation.ok) {\n return {\n exitCode: 1,\n stderr: `Manifest is invalid.\\n\\nErrors:\\n${formatIssues(validation.issues)}\\n`,\n }\n }\n\n const body = JSON.stringify(manifest)\n let signedRequest:\n | {\n body: string\n headers: Record<string, string>\n }\n | ReturnType<typeof signDocsSyncRequest>\n\n if (options.authMode === 'github-oidc') {\n const oidcToken = await readGithubOidcToken({\n args,\n audience: options.sourceId,\n httpGet,\n })\n\n if (typeof oidcToken !== 'string') {\n return oidcToken\n }\n\n signedRequest = {\n body,\n headers: {\n Authorization: `Bearer ${oidcToken}`,\n 'Content-Type': 'application/json',\n 'X-VL-MD-DOCS-Body-SHA256': sha256Hex(body),\n },\n }\n } else {\n signedRequest = signDocsSyncRequest({\n body,\n endpoint: options.endpoint,\n keyId: options.keyId,\n privateKey: options.privateKey,\n })\n }\n\n const response = await httpPost({\n body: signedRequest.body,\n headers: signedRequest.headers,\n url: options.endpoint,\n })\n\n if (getFlagBoolean(args, 'json')) {\n return {\n exitCode:\n response.ok &&\n isServerPushResponse(response.body) &&\n response.body.ok === true\n ? 0\n : 1,\n stdout: printJson(\n {\n endpoint: options.endpoint,\n mode: options.mode,\n response: response.body,\n sourceId: options.sourceId,\n status: response.status,\n },\n getFlagBoolean(args, 'pretty'),\n ),\n }\n }\n\n if (\n !response.ok ||\n !isServerPushResponse(response.body) ||\n response.body.ok !== true\n ) {\n return {\n exitCode: 1,\n stderr: formatServerFailure({\n body: response.body,\n status: response.status,\n }),\n }\n }\n\n return {\n exitCode: 0,\n stdout: formatPushSummary({\n endpoint: options.endpoint,\n mode: options.mode,\n response: response.body,\n sourceId: options.sourceId,\n }),\n }\n}\n"],"names":["readFile","signDocsSyncRequest","buildDocsManifest","sha256Hex","validateDocsManifest","readDocsAiExportManifest","walkDocsFiles","formatIssues","formatPushSummary","printJson","getJson","postJson","getFlagBoolean","getFlagString","getDocsCommandOptions","supportedPushDeleteBehaviors","Set","isRecord","value","Array","isArray","isServerPushResponse","validateEndpointUrl","endpoint","parsed","URL","protocol","exitCode","stderr","toString","readPrivateKey","args","privateKeyFile","privateKeyEnv","privateKey","process","env","error","Error","message","getGithubOidcTokenRequestUrl","audience","requestUrl","url","searchParams","set","readGithubOidcToken","httpGet","tokenEnv","token","ACTIONS_ID_TOKEN_REQUEST_URL","requestToken","ACTIONS_ID_TOKEN_REQUEST_TOKEN","response","headers","Authorization","ok","body","status","getPushCommandOptions","docsOptions","endpointFlag","deleteBehaviorFlag","undefined","has","mode","baseOptions","deleteBehavior","publish","authMode","oidcTokenEnv","keyId","formatServerFailure","runPushCommand","httpPost","options","files","root","docsRoot","aiExport","issues","manifest","branch","commit","repository","sourceId","validation","maxFileBytes","maxFiles","maxTotalBytes","routeBase","JSON","stringify","signedRequest","oidcToken","stdout"],"mappings":"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"}
@@ -3,8 +3,16 @@ import { buildDocsManifest, validateDocsManifest } from '../../sync/index.js';
3
3
  import { readDocsAiExportManifest, walkDocsFiles } from '../filesystem.js';
4
4
  import { formatValidationSummary, printJson } from '../format.js';
5
5
  import { getFlagBoolean, getFlagString, parseIntegerFlag } from '../parseArgs.js';
6
+ const getRepositoryName = (repository)=>{
7
+ if (!repository) {
8
+ return undefined;
9
+ }
10
+ const [, name] = repository.split('/', 2);
11
+ return name ?? repository;
12
+ };
13
+ const getDefaultSourceId = (docsRoot)=>getRepositoryName(process.env.GITHUB_REPOSITORY) ?? (path.basename(path.resolve(docsRoot)) === 'docs' ? 'local-docs' : path.basename(path.resolve(docsRoot)));
6
14
  export const getDocsCommandOptions = (args)=>{
7
- const docsRoot = args.positionals[0] ?? getFlagString(args, 'root');
15
+ const docsRoot = args.positionals[0];
8
16
  if (!docsRoot) {
9
17
  return {
10
18
  exitCode: 1,
@@ -31,9 +39,7 @@ export const getDocsCommandOptions = (args)=>{
31
39
  maxFiles: typeof maxFiles === 'number' ? maxFiles : undefined,
32
40
  maxTotalBytes: typeof maxTotalBytes === 'number' ? maxTotalBytes : undefined,
33
41
  repository: getFlagString(args, 'repository'),
34
- routeBase: getFlagString(args, 'route-base'),
35
- sourceId: getFlagString(args, 'source') ?? 'local-docs',
36
- sourceRoot: getFlagString(args, 'root') ?? path.basename(path.resolve(docsRoot))
42
+ sourceId: getFlagString(args, 'source') ?? getDefaultSourceId(docsRoot)
37
43
  };
38
44
  };
39
45
  export const runValidateCommand = async (args)=>{
@@ -68,14 +74,13 @@ export const runValidateCommand = async (args)=>{
68
74
  commit: options.commit,
69
75
  files,
70
76
  repository: options.repository,
71
- root: options.sourceRoot,
72
77
  sourceId: options.sourceId
73
78
  });
74
79
  const validation = validateDocsManifest(manifest, {
75
80
  maxFileBytes: options.maxFileBytes,
76
81
  maxFiles: options.maxFiles,
77
82
  maxTotalBytes: options.maxTotalBytes,
78
- routeBase: options.routeBase
83
+ routeBase: `/${options.sourceId}`
79
84
  });
80
85
  const validationWithReadWarnings = {
81
86
  ...validation,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/cli/commands/validate.ts"],"sourcesContent":["import path from 'node:path'\n\nimport type {\n CliResult,\n DocsCommandOptions,\n ParsedCliArgs,\n} from '../types.js'\n\nimport {\n buildDocsManifest,\n validateDocsManifest,\n} from '../../sync/index.js'\nimport {\n readDocsAiExportManifest,\n walkDocsFiles,\n} from '../filesystem.js'\nimport { formatValidationSummary, printJson } from '../format.js'\nimport {\n getFlagBoolean,\n getFlagString,\n parseIntegerFlag,\n} from '../parseArgs.js'\n\nexport const getDocsCommandOptions = (\n args: ParsedCliArgs,\n): CliResult | DocsCommandOptions => {\n const docsRoot = args.positionals[0] ?? getFlagString(args, 'root')\n\n if (!docsRoot) {\n return {\n exitCode: 1,\n stderr: `Command \"${args.command}\" requires a docs root path.\\n`,\n }\n }\n\n const maxFiles = parseIntegerFlag(args, 'max-files')\n const maxFileBytes = parseIntegerFlag(args, 'max-file-bytes')\n const maxTotalBytes = parseIntegerFlag(args, 'max-total-bytes')\n\n for (const parsed of [maxFiles, maxFileBytes, maxTotalBytes]) {\n if (typeof parsed === 'object' && parsed !== null) {\n return parsed\n }\n }\n\n return {\n branch: getFlagString(args, 'branch'),\n commit: getFlagString(args, 'commit'),\n docsRoot,\n maxFileBytes: typeof maxFileBytes === 'number' ? maxFileBytes : undefined,\n maxFiles: typeof maxFiles === 'number' ? maxFiles : undefined,\n maxTotalBytes: typeof maxTotalBytes === 'number' ? maxTotalBytes : undefined,\n repository: getFlagString(args, 'repository'),\n routeBase: getFlagString(args, 'route-base'),\n sourceId: getFlagString(args, 'source') ?? 'local-docs',\n sourceRoot: getFlagString(args, 'root') ?? path.basename(path.resolve(docsRoot)),\n }\n}\n\nexport const runValidateCommand = async (\n args: ParsedCliArgs,\n): Promise<CliResult> => {\n const options = getDocsCommandOptions(args)\n\n if ('exitCode' in options) {\n return options\n }\n\n const files = await walkDocsFiles({\n root: options.docsRoot,\n })\n const aiExport = await readDocsAiExportManifest({\n root: options.docsRoot,\n })\n\n if (!aiExport.ok) {\n return {\n exitCode: 1,\n stdout: formatValidationSummary({\n fileCount: files.length,\n root: options.docsRoot,\n sourceId: options.sourceId,\n validation: {\n issues: aiExport.issues,\n ok: false,\n warnings: aiExport.warnings,\n },\n }),\n }\n }\n\n const manifest = buildDocsManifest({\n aiExport: aiExport.manifest,\n branch: options.branch,\n commit: options.commit,\n files,\n repository: options.repository,\n root: options.sourceRoot,\n sourceId: options.sourceId,\n })\n const validation = validateDocsManifest(manifest, {\n maxFileBytes: options.maxFileBytes,\n maxFiles: options.maxFiles,\n maxTotalBytes: options.maxTotalBytes,\n routeBase: options.routeBase,\n })\n const validationWithReadWarnings = {\n ...validation,\n warnings: [...aiExport.warnings, ...validation.warnings],\n } as typeof validation\n\n if (getFlagBoolean(args, 'json')) {\n return {\n exitCode: validation.ok ? 0 : 1,\n stdout: printJson({\n fileCount: files.length,\n root: options.docsRoot,\n sourceId: options.sourceId,\n validation: validationWithReadWarnings,\n }, getFlagBoolean(args, 'pretty')),\n }\n }\n\n return {\n exitCode: validation.ok ? 0 : 1,\n stdout: formatValidationSummary({\n fileCount: files.length,\n root: options.docsRoot,\n sourceId: options.sourceId,\n validation: validationWithReadWarnings,\n }),\n }\n}\n"],"names":["path","buildDocsManifest","validateDocsManifest","readDocsAiExportManifest","walkDocsFiles","formatValidationSummary","printJson","getFlagBoolean","getFlagString","parseIntegerFlag","getDocsCommandOptions","args","docsRoot","positionals","exitCode","stderr","command","maxFiles","maxFileBytes","maxTotalBytes","parsed","branch","commit","undefined","repository","routeBase","sourceId","sourceRoot","basename","resolve","runValidateCommand","options","files","root","aiExport","ok","stdout","fileCount","length","validation","issues","warnings","manifest","validationWithReadWarnings"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/cli/commands/validate.ts"],"sourcesContent":["import path from 'node:path'\n\nimport type {\n CliResult,\n DocsCommandOptions,\n ParsedCliArgs,\n} from '../types.js'\n\nimport {\n buildDocsManifest,\n validateDocsManifest,\n} from '../../sync/index.js'\nimport {\n readDocsAiExportManifest,\n walkDocsFiles,\n} from '../filesystem.js'\nimport { formatValidationSummary, printJson } from '../format.js'\nimport {\n getFlagBoolean,\n getFlagString,\n parseIntegerFlag,\n} from '../parseArgs.js'\n\nconst getRepositoryName = (repository: string | undefined): string | undefined => {\n if (!repository) {\n return undefined\n }\n\n const [, name] = repository.split('/', 2)\n\n return name ?? repository\n}\n\nconst getDefaultSourceId = (docsRoot: string): string =>\n getRepositoryName(process.env.GITHUB_REPOSITORY) ??\n (path.basename(path.resolve(docsRoot)) === 'docs'\n ? 'local-docs'\n : path.basename(path.resolve(docsRoot)))\n\nexport const getDocsCommandOptions = (\n args: ParsedCliArgs,\n): CliResult | DocsCommandOptions => {\n const docsRoot = args.positionals[0]\n\n if (!docsRoot) {\n return {\n exitCode: 1,\n stderr: `Command \"${args.command}\" requires a docs root path.\\n`,\n }\n }\n\n const maxFiles = parseIntegerFlag(args, 'max-files')\n const maxFileBytes = parseIntegerFlag(args, 'max-file-bytes')\n const maxTotalBytes = parseIntegerFlag(args, 'max-total-bytes')\n\n for (const parsed of [maxFiles, maxFileBytes, maxTotalBytes]) {\n if (typeof parsed === 'object' && parsed !== null) {\n return parsed\n }\n }\n\n return {\n branch: getFlagString(args, 'branch'),\n commit: getFlagString(args, 'commit'),\n docsRoot,\n maxFileBytes: typeof maxFileBytes === 'number' ? maxFileBytes : undefined,\n maxFiles: typeof maxFiles === 'number' ? maxFiles : undefined,\n maxTotalBytes: typeof maxTotalBytes === 'number' ? maxTotalBytes : undefined,\n repository: getFlagString(args, 'repository'),\n sourceId: getFlagString(args, 'source') ?? getDefaultSourceId(docsRoot),\n }\n}\n\nexport const runValidateCommand = async (\n args: ParsedCliArgs,\n): Promise<CliResult> => {\n const options = getDocsCommandOptions(args)\n\n if ('exitCode' in options) {\n return options\n }\n\n const files = await walkDocsFiles({\n root: options.docsRoot,\n })\n const aiExport = await readDocsAiExportManifest({\n root: options.docsRoot,\n })\n\n if (!aiExport.ok) {\n return {\n exitCode: 1,\n stdout: formatValidationSummary({\n fileCount: files.length,\n root: options.docsRoot,\n sourceId: options.sourceId,\n validation: {\n issues: aiExport.issues,\n ok: false,\n warnings: aiExport.warnings,\n },\n }),\n }\n }\n\n const manifest = buildDocsManifest({\n aiExport: aiExport.manifest,\n branch: options.branch,\n commit: options.commit,\n files,\n repository: options.repository,\n sourceId: options.sourceId,\n })\n const validation = validateDocsManifest(manifest, {\n maxFileBytes: options.maxFileBytes,\n maxFiles: options.maxFiles,\n maxTotalBytes: options.maxTotalBytes,\n routeBase: `/${options.sourceId}`,\n })\n const validationWithReadWarnings = {\n ...validation,\n warnings: [...aiExport.warnings, ...validation.warnings],\n } as typeof validation\n\n if (getFlagBoolean(args, 'json')) {\n return {\n exitCode: validation.ok ? 0 : 1,\n stdout: printJson({\n fileCount: files.length,\n root: options.docsRoot,\n sourceId: options.sourceId,\n validation: validationWithReadWarnings,\n }, getFlagBoolean(args, 'pretty')),\n }\n }\n\n return {\n exitCode: validation.ok ? 0 : 1,\n stdout: formatValidationSummary({\n fileCount: files.length,\n root: options.docsRoot,\n sourceId: options.sourceId,\n validation: validationWithReadWarnings,\n }),\n }\n}\n"],"names":["path","buildDocsManifest","validateDocsManifest","readDocsAiExportManifest","walkDocsFiles","formatValidationSummary","printJson","getFlagBoolean","getFlagString","parseIntegerFlag","getRepositoryName","repository","undefined","name","split","getDefaultSourceId","docsRoot","process","env","GITHUB_REPOSITORY","basename","resolve","getDocsCommandOptions","args","positionals","exitCode","stderr","command","maxFiles","maxFileBytes","maxTotalBytes","parsed","branch","commit","sourceId","runValidateCommand","options","files","root","aiExport","ok","stdout","fileCount","length","validation","issues","warnings","manifest","routeBase","validationWithReadWarnings"],"mappings":"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"}
package/dist/cli/index.js CHANGED
@@ -56,9 +56,7 @@ Options:
56
56
  manifest: `payload-markdown-docs manifest <docs-root>
57
57
 
58
58
  Options:
59
- --source <id> Manifest source id. Defaults to local-docs.
60
- --root <path> Manifest source root label.
61
- --route-base <route> Route base for validation. Defaults to /docs.
59
+ --source <id> Docs set slug. Defaults to the GitHub repository name in GitHub Actions, otherwise local-docs.
62
60
  --repository <repo> Source repository metadata.
63
61
  --branch <branch> Source branch metadata.
64
62
  --commit <sha> Source commit metadata.
@@ -75,9 +73,7 @@ Options:
75
73
  --delete-behavior <value> archive, delete, draft, or ignore.
76
74
  --json Print full plan JSON.
77
75
  --pretty Pretty-print JSON output.
78
- --source <id> Manifest source id. Defaults to local-docs.
79
- --root <path> Manifest source root label.
80
- --route-base <route> Route base for validation. Defaults to /docs.
76
+ --source <id> Docs set slug. Defaults to the GitHub repository name in GitHub Actions, otherwise local-docs.
81
77
  --repository <repo> Source repository metadata.
82
78
  --branch <branch> Source branch metadata.
83
79
  --commit <sha> Source commit metadata.
@@ -94,7 +90,6 @@ Options:
94
90
  --private-key-file <path> PEM private key file from keygen.
95
91
  --private-key-env <name> Environment variable containing the private key.
96
92
  --github-oidc Use GitHub Actions OIDC bearer auth instead of Ed25519.
97
- --oidc-audience <value> GitHub OIDC audience. Defaults to payload-markdown-docs.
98
93
  --oidc-token-env <name> Environment variable containing an already-fetched OIDC token.
99
94
  --dry-run Upload as dry-run mode. This is the default.
100
95
  --sync Upload as sync mode. Requires server sync.allowWrites.
@@ -102,9 +97,7 @@ Options:
102
97
  --delete-behavior <value> archive, delete, draft, or ignore. Defaults to archive.
103
98
  --json Print structured JSON output.
104
99
  --pretty Pretty-print JSON output with --json.
105
- --source <id> Manifest source id. Defaults to local-docs.
106
- --root <path> Manifest source root label.
107
- --route-base <route> Route base for local validation. Defaults to /docs.
100
+ --source <id> Docs set slug. Defaults to the GitHub repository name in GitHub Actions, otherwise local-docs.
108
101
  --repository <repo> Source repository metadata.
109
102
  --branch <branch> Source branch metadata.
110
103
  --commit <sha> Source commit metadata.
@@ -118,7 +111,7 @@ Examples:
118
111
  payload-markdown-docs push ./docs --endpoint "$DOCS_SYNC_ENDPOINT" --source main-docs --key-id github-actions-main --private-key-env DOCS_SYNC_PRIVATE_KEY --sync
119
112
 
120
113
  GitHub OIDC:
121
- payload-markdown-docs push ./docs --endpoint "$DOCS_SYNC_ENDPOINT" --source main-docs --github-oidc --oidc-audience payload-markdown-docs --sync
114
+ payload-markdown-docs push ./docs --endpoint "$DOCS_SYNC_ENDPOINT" --github-oidc --sync
122
115
 
123
116
  GitHub OIDC requires workflow permissions: id-token: write and contents: read.
124
117
  Hard delete requires explicit server sync.allowHardDelete. Existing collection and block targets are not supported yet.
@@ -128,9 +121,7 @@ Hard delete requires explicit server sync.allowHardDelete. Existing collection a
128
121
  Options:
129
122
  --json Print validation JSON.
130
123
  --pretty Pretty-print JSON output.
131
- --source <id> Manifest source id. Defaults to local-docs.
132
- --root <path> Manifest source root label.
133
- --route-base <route> Route base for validation. Defaults to /docs.
124
+ --source <id> Docs set slug. Defaults to the GitHub repository name in GitHub Actions, otherwise local-docs.
134
125
  --repository <repo> Source repository metadata.
135
126
  --branch <branch> Source branch metadata.
136
127
  --commit <sha> Source commit metadata.