@valkyrianlabs/payload-markdown-docs 0.1.0-canary.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (204) hide show
  1. package/README.md +195 -0
  2. package/dist/admin/DocsSetManager.d.ts +2 -0
  3. package/dist/admin/DocsSetManager.js +298 -0
  4. package/dist/admin/DocsSetManager.js.map +1 -0
  5. package/dist/admin/docsSetManagerData.d.ts +25 -0
  6. package/dist/admin/docsSetManagerData.js +266 -0
  7. package/dist/admin/docsSetManagerData.js.map +1 -0
  8. package/dist/admin/docsSetManagerTypes.d.ts +103 -0
  9. package/dist/admin/docsSetManagerTypes.js +3 -0
  10. package/dist/admin/docsSetManagerTypes.js.map +1 -0
  11. package/dist/admin/index.d.ts +3 -0
  12. package/dist/admin/index.js +4 -0
  13. package/dist/admin/index.js.map +1 -0
  14. package/dist/cli/commands/install.d.ts +2 -0
  15. package/dist/cli/commands/install.js +211 -0
  16. package/dist/cli/commands/install.js.map +1 -0
  17. package/dist/cli/commands/keygen.d.ts +2 -0
  18. package/dist/cli/commands/keygen.js +89 -0
  19. package/dist/cli/commands/keygen.js.map +1 -0
  20. package/dist/cli/commands/manifest.d.ts +2 -0
  21. package/dist/cli/commands/manifest.js +50 -0
  22. package/dist/cli/commands/manifest.js.map +1 -0
  23. package/dist/cli/commands/plan.d.ts +2 -0
  24. package/dist/cli/commands/plan.js +110 -0
  25. package/dist/cli/commands/plan.js.map +1 -0
  26. package/dist/cli/commands/push.d.ts +3 -0
  27. package/dist/cli/commands/push.js +308 -0
  28. package/dist/cli/commands/push.js.map +1 -0
  29. package/dist/cli/commands/validate.d.ts +3 -0
  30. package/dist/cli/commands/validate.js +109 -0
  31. package/dist/cli/commands/validate.js.map +1 -0
  32. package/dist/cli/filesystem.d.ts +20 -0
  33. package/dist/cli/filesystem.js +96 -0
  34. package/dist/cli/filesystem.js.map +1 -0
  35. package/dist/cli/format.d.ts +35 -0
  36. package/dist/cli/format.js +76 -0
  37. package/dist/cli/format.js.map +1 -0
  38. package/dist/cli/http.d.ts +19 -0
  39. package/dist/cli/http.js +39 -0
  40. package/dist/cli/http.js.map +1 -0
  41. package/dist/cli/index.d.ts +3 -0
  42. package/dist/cli/index.js +214 -0
  43. package/dist/cli/index.js.map +1 -0
  44. package/dist/cli/parseArgs.d.ts +5 -0
  45. package/dist/cli/parseArgs.js +219 -0
  46. package/dist/cli/parseArgs.js.map +1 -0
  47. package/dist/cli/types.d.ts +51 -0
  48. package/dist/cli/types.js +3 -0
  49. package/dist/cli/types.js.map +1 -0
  50. package/dist/collections/docs.d.ts +9 -0
  51. package/dist/collections/docs.js +168 -0
  52. package/dist/collections/docs.js.map +1 -0
  53. package/dist/collections/docsGroups.d.ts +5 -0
  54. package/dist/collections/docsGroups.js +57 -0
  55. package/dist/collections/docsGroups.js.map +1 -0
  56. package/dist/collections/docsSets.d.ts +8 -0
  57. package/dist/collections/docsSets.js +158 -0
  58. package/dist/collections/docsSets.js.map +1 -0
  59. package/dist/collections/index.d.ts +10 -0
  60. package/dist/collections/index.js +7 -0
  61. package/dist/collections/index.js.map +1 -0
  62. package/dist/collections/nonces.d.ts +6 -0
  63. package/dist/collections/nonces.js +57 -0
  64. package/dist/collections/nonces.js.map +1 -0
  65. package/dist/collections/syncRuns.d.ts +5 -0
  66. package/dist/collections/syncRuns.js +139 -0
  67. package/dist/collections/syncRuns.js.map +1 -0
  68. package/dist/constants.d.ts +21 -0
  69. package/dist/constants.js +23 -0
  70. package/dist/constants.js.map +1 -0
  71. package/dist/endpoints/index.d.ts +2 -0
  72. package/dist/endpoints/index.js +3 -0
  73. package/dist/endpoints/index.js.map +1 -0
  74. package/dist/endpoints/sync.d.ts +47 -0
  75. package/dist/endpoints/sync.js +616 -0
  76. package/dist/endpoints/sync.js.map +1 -0
  77. package/dist/index.d.ts +9 -0
  78. package/dist/index.js +7 -0
  79. package/dist/index.js.map +1 -0
  80. package/dist/next/PayloadMarkdownDocsPage.d.ts +7 -0
  81. package/dist/next/PayloadMarkdownDocsPage.js +142 -0
  82. package/dist/next/PayloadMarkdownDocsPage.js.map +1 -0
  83. package/dist/next/index.d.ts +9 -0
  84. package/dist/next/index.js +7 -0
  85. package/dist/next/index.js.map +1 -0
  86. package/dist/next/markdown.d.ts +14 -0
  87. package/dist/next/markdown.js +232 -0
  88. package/dist/next/markdown.js.map +1 -0
  89. package/dist/next/metadata.d.ts +3 -0
  90. package/dist/next/metadata.js +33 -0
  91. package/dist/next/metadata.js.map +1 -0
  92. package/dist/next/records.d.ts +14 -0
  93. package/dist/next/records.js +146 -0
  94. package/dist/next/records.js.map +1 -0
  95. package/dist/next/route.d.ts +6 -0
  96. package/dist/next/route.js +271 -0
  97. package/dist/next/route.js.map +1 -0
  98. package/dist/next/sidebar.d.ts +15 -0
  99. package/dist/next/sidebar.js +137 -0
  100. package/dist/next/sidebar.js.map +1 -0
  101. package/dist/next/types.d.ts +117 -0
  102. package/dist/next/types.js +3 -0
  103. package/dist/next/types.js.map +1 -0
  104. package/dist/payload/applyDocsSync.d.ts +54 -0
  105. package/dist/payload/applyDocsSync.js +176 -0
  106. package/dist/payload/applyDocsSync.js.map +1 -0
  107. package/dist/payload/docsConflicts.d.ts +12 -0
  108. package/dist/payload/docsConflicts.js +34 -0
  109. package/dist/payload/docsConflicts.js.map +1 -0
  110. package/dist/payload/docsData.d.ts +23 -0
  111. package/dist/payload/docsData.js +59 -0
  112. package/dist/payload/docsData.js.map +1 -0
  113. package/dist/payload/docsSets.d.ts +38 -0
  114. package/dist/payload/docsSets.js +57 -0
  115. package/dist/payload/docsSets.js.map +1 -0
  116. package/dist/payload/existingDocs.d.ts +43 -0
  117. package/dist/payload/existingDocs.js +97 -0
  118. package/dist/payload/existingDocs.js.map +1 -0
  119. package/dist/payload/index.d.ts +15 -0
  120. package/dist/payload/index.js +10 -0
  121. package/dist/payload/index.js.map +1 -0
  122. package/dist/payload/routeCollisions.d.ts +31 -0
  123. package/dist/payload/routeCollisions.js +104 -0
  124. package/dist/payload/routeCollisions.js.map +1 -0
  125. package/dist/payload/syncRuns.d.ts +60 -0
  126. package/dist/payload/syncRuns.js +53 -0
  127. package/dist/payload/syncRuns.js.map +1 -0
  128. package/dist/plugin.d.ts +3 -0
  129. package/dist/plugin.js +165 -0
  130. package/dist/plugin.js.map +1 -0
  131. package/dist/routing/index.d.ts +3 -0
  132. package/dist/routing/index.js +4 -0
  133. package/dist/routing/index.js.map +1 -0
  134. package/dist/routing/paths.d.ts +7 -0
  135. package/dist/routing/paths.js +23 -0
  136. package/dist/routing/paths.js.map +1 -0
  137. package/dist/routing/reservations.d.ts +37 -0
  138. package/dist/routing/reservations.js +79 -0
  139. package/dist/routing/reservations.js.map +1 -0
  140. package/dist/security/canonical.d.ts +12 -0
  141. package/dist/security/canonical.js +24 -0
  142. package/dist/security/canonical.js.map +1 -0
  143. package/dist/security/githubOidc.d.ts +45 -0
  144. package/dist/security/githubOidc.js +177 -0
  145. package/dist/security/githubOidc.js.map +1 -0
  146. package/dist/security/headers.d.ts +22 -0
  147. package/dist/security/headers.js +44 -0
  148. package/dist/security/headers.js.map +1 -0
  149. package/dist/security/index.d.ts +15 -0
  150. package/dist/security/index.js +9 -0
  151. package/dist/security/index.js.map +1 -0
  152. package/dist/security/jwks.d.ts +20 -0
  153. package/dist/security/jwks.js +40 -0
  154. package/dist/security/jwks.js.map +1 -0
  155. package/dist/security/jwt.d.ts +10 -0
  156. package/dist/security/jwt.js +42 -0
  157. package/dist/security/jwt.js.map +1 -0
  158. package/dist/security/nonce.d.ts +34 -0
  159. package/dist/security/nonce.js +43 -0
  160. package/dist/security/nonce.js.map +1 -0
  161. package/dist/security/sign.d.ts +13 -0
  162. package/dist/security/sign.js +39 -0
  163. package/dist/security/sign.js.map +1 -0
  164. package/dist/security/verify.d.ts +28 -0
  165. package/dist/security/verify.js +54 -0
  166. package/dist/security/verify.js.map +1 -0
  167. package/dist/skills/codex/SKILL.md +173 -0
  168. package/dist/skills/codex/examples/docs-page.md +42 -0
  169. package/dist/skills/codex/examples/github-actions.md +64 -0
  170. package/dist/skills/codex/reference/admin.md +28 -0
  171. package/dist/skills/codex/reference/frontmatter.md +39 -0
  172. package/dist/skills/codex/reference/payload-markdown-directives.md +77 -0
  173. package/dist/skills/codex/reference/routing.md +35 -0
  174. package/dist/skills/codex/reference/sync.md +35 -0
  175. package/dist/skills/codex/reference/troubleshooting.md +53 -0
  176. package/dist/skills/codex/reference/workflow.md +39 -0
  177. package/dist/sync/aiExportManifest.d.ts +58 -0
  178. package/dist/sync/aiExportManifest.js +430 -0
  179. package/dist/sync/aiExportManifest.js.map +1 -0
  180. package/dist/sync/frontmatter.d.ts +28 -0
  181. package/dist/sync/frontmatter.js +210 -0
  182. package/dist/sync/frontmatter.js.map +1 -0
  183. package/dist/sync/hash.d.ts +1 -0
  184. package/dist/sync/hash.js +8 -0
  185. package/dist/sync/hash.js.map +1 -0
  186. package/dist/sync/index.d.ts +12 -0
  187. package/dist/sync/index.js +9 -0
  188. package/dist/sync/index.js.map +1 -0
  189. package/dist/sync/manifest.d.ts +58 -0
  190. package/dist/sync/manifest.js +21 -0
  191. package/dist/sync/manifest.js.map +1 -0
  192. package/dist/sync/paths.d.ts +16 -0
  193. package/dist/sync/paths.js +116 -0
  194. package/dist/sync/paths.js.map +1 -0
  195. package/dist/sync/plan.d.ts +29 -0
  196. package/dist/sync/plan.js +72 -0
  197. package/dist/sync/plan.js.map +1 -0
  198. package/dist/sync/validate.d.ts +26 -0
  199. package/dist/sync/validate.js +308 -0
  200. package/dist/sync/validate.js.map +1 -0
  201. package/dist/types.d.ts +84 -0
  202. package/dist/types.js +3 -0
  203. package/dist/types.js.map +1 -0
  204. package/package.json +143 -0
@@ -0,0 +1,266 @@
1
+ import { DEFAULT_DOCS_COLLECTION_SLUG, DEFAULT_DOCS_SETS_COLLECTION_SLUG } from '../constants.js';
2
+ const isRecord = (value)=>typeof value === 'object' && value !== null && !Array.isArray(value);
3
+ const getRecordId = (doc)=>{
4
+ if (!isRecord(doc)) {
5
+ return undefined;
6
+ }
7
+ if (typeof doc.id === 'string' || typeof doc.id === 'number') {
8
+ return String(doc.id);
9
+ }
10
+ return undefined;
11
+ };
12
+ const getRelationshipId = (value)=>{
13
+ if (typeof value === 'string' || typeof value === 'number') {
14
+ return String(value);
15
+ }
16
+ return getRecordId(value);
17
+ };
18
+ const normalizeAdminRoute = (adminRoute = '/admin')=>{
19
+ const trimmed = adminRoute.trim();
20
+ if (!trimmed || trimmed === '/') {
21
+ return '/admin';
22
+ }
23
+ return `/${trimmed}`.replace(/\/+/g, '/').replace(/\/+$/g, '');
24
+ };
25
+ export const getGeneratedDocAdminURL = ({ id, adminRoute, docsCollectionSlug })=>`${normalizeAdminRoute(adminRoute)}/collections/${docsCollectionSlug}/${encodeURIComponent(id)}`;
26
+ const hasText = (value)=>typeof value === 'string' && value.trim().length > 0;
27
+ const getOverrideSummary = (overrides)=>{
28
+ if (!overrides || !isRecord(overrides)) {
29
+ return [];
30
+ }
31
+ const summary = [];
32
+ if (hasText(overrides.navTitle)) {
33
+ summary.push('Nav title override');
34
+ }
35
+ if (overrides.hideFromNav === true) {
36
+ summary.push('Hidden from nav');
37
+ }
38
+ if (hasText(overrides.theme)) {
39
+ summary.push('Theme override');
40
+ }
41
+ if (hasText(overrides.heroEyebrow) || hasText(overrides.heroTitle) || hasText(overrides.heroDescription)) {
42
+ summary.push('Hero override');
43
+ }
44
+ if (hasText(overrides.seoTitle) || hasText(overrides.seoDescription)) {
45
+ summary.push('SEO override');
46
+ }
47
+ return summary;
48
+ };
49
+ const getDocStatus = (doc)=>{
50
+ if (doc.sync?.archived === true) {
51
+ return 'archived';
52
+ }
53
+ if (doc._status === 'draft') {
54
+ return 'draft';
55
+ }
56
+ if (doc._status === 'published') {
57
+ return 'published';
58
+ }
59
+ return 'synced';
60
+ };
61
+ const getSourcePathSegments = (sourcePath)=>{
62
+ const withoutExtension = sourcePath.replace(/\.md$/i, '');
63
+ const segments = withoutExtension.split('/').filter(Boolean);
64
+ if (segments.at(-1) === 'index') {
65
+ return segments.slice(0, -1);
66
+ }
67
+ return segments;
68
+ };
69
+ const titleCaseSegment = (segment)=>segment.split(/[-_]+/).filter(Boolean).map((part)=>`${part.charAt(0).toUpperCase()}${part.slice(1)}`).join(' ');
70
+ const compareDocItems = (first, second)=>{
71
+ if (first.order !== second.order) {
72
+ return first.order - second.order;
73
+ }
74
+ if (first.sourcePath !== second.sourcePath) {
75
+ return first.sourcePath.localeCompare(second.sourcePath);
76
+ }
77
+ return first.route.localeCompare(second.route);
78
+ };
79
+ const getOrCreateFolder = ({ items, order, segment, sourcePath })=>{
80
+ const existing = items.find((item)=>item.kind === 'folder' && item.sourcePath === sourcePath);
81
+ if (existing) {
82
+ existing.order = Math.min(existing.order, order);
83
+ return existing;
84
+ }
85
+ const folder = {
86
+ id: `folder:${sourcePath}`,
87
+ children: [],
88
+ kind: 'folder',
89
+ order,
90
+ overrideSummary: [],
91
+ route: '',
92
+ sourcePath,
93
+ status: 'synced',
94
+ title: titleCaseSegment(segment)
95
+ };
96
+ items.push(folder);
97
+ return folder;
98
+ };
99
+ const insertIntoTree = ({ item, tree })=>{
100
+ const segments = getSourcePathSegments(item.sourcePath);
101
+ if (segments.length <= 1) {
102
+ tree.push(item);
103
+ return;
104
+ }
105
+ let currentItems = tree;
106
+ for (const [index, segment] of segments.slice(0, -1).entries()){
107
+ const sourcePath = segments.slice(0, index + 1).join('/');
108
+ const folder = getOrCreateFolder({
109
+ items: currentItems,
110
+ order: item.order,
111
+ segment,
112
+ sourcePath
113
+ });
114
+ folder.children ??= [];
115
+ currentItems = folder.children;
116
+ }
117
+ currentItems.push(item);
118
+ };
119
+ const sortTree = (items)=>{
120
+ items.sort(compareDocItems);
121
+ for (const item of items){
122
+ if (item.children) {
123
+ sortTree(item.children);
124
+ }
125
+ }
126
+ };
127
+ const toDocItem = ({ adminRoute, doc, docsCollectionSlug, index, warnings })=>{
128
+ const id = getRecordId(doc) ?? `unknown-${index}`;
129
+ const route = hasText(doc.route) ? doc.route : '';
130
+ const sourcePath = hasText(doc.sourcePath) ? doc.sourcePath : `missing-source-path-${id}`;
131
+ const title = hasText(doc.title) ? doc.title : sourcePath;
132
+ const status = getDocStatus(doc);
133
+ const overrideSummary = getOverrideSummary(doc.overrides);
134
+ if (!hasText(doc.route)) {
135
+ warnings.push({
136
+ docId: id,
137
+ message: 'Generated doc is missing a route.',
138
+ sourcePath
139
+ });
140
+ }
141
+ if (!hasText(doc.sourcePath)) {
142
+ warnings.push({
143
+ docId: id,
144
+ message: 'Generated doc is missing a source path.'
145
+ });
146
+ }
147
+ if (!hasText(doc.title)) {
148
+ warnings.push({
149
+ docId: id,
150
+ message: 'Generated doc is missing a title.',
151
+ sourcePath
152
+ });
153
+ }
154
+ return {
155
+ id,
156
+ ...adminRoute ? {
157
+ adminURL: getGeneratedDocAdminURL({
158
+ id,
159
+ adminRoute,
160
+ docsCollectionSlug
161
+ })
162
+ } : {},
163
+ archived: status === 'archived',
164
+ draft: status === 'draft',
165
+ hiddenFromNav: doc.overrides?.hideFromNav === true,
166
+ kind: 'doc',
167
+ order: typeof doc.order === 'number' ? doc.order : 0,
168
+ overrideSummary,
169
+ published: status === 'published',
170
+ route,
171
+ sourcePath,
172
+ status,
173
+ title
174
+ };
175
+ };
176
+ export const buildDocsSetManagerData = ({ adminRoute, docs, docsCollectionSlug = DEFAULT_DOCS_COLLECTION_SLUG, docsSet })=>{
177
+ const warnings = [];
178
+ const docsSetId = getRecordId(docsSet) ?? 'unknown';
179
+ const sortedDocs = docs.map((doc, index)=>toDocItem({
180
+ adminRoute,
181
+ doc,
182
+ docsCollectionSlug,
183
+ index,
184
+ warnings
185
+ })).sort(compareDocItems);
186
+ const tree = [];
187
+ for (const item of sortedDocs){
188
+ insertIntoTree({
189
+ item,
190
+ tree
191
+ });
192
+ }
193
+ sortTree(tree);
194
+ return {
195
+ docs: sortedDocs,
196
+ docsSet: {
197
+ id: docsSetId,
198
+ routeBase: docsSet.routeBase ?? '',
199
+ sourceId: docsSet.sourceId ?? '',
200
+ title: docsSet.title ?? docsSetId
201
+ },
202
+ summary: {
203
+ archived: sortedDocs.filter((doc)=>doc.archived).length,
204
+ drafts: sortedDocs.filter((doc)=>doc.draft).length,
205
+ hiddenFromNav: sortedDocs.filter((doc)=>doc.hiddenFromNav).length,
206
+ published: sortedDocs.filter((doc)=>doc.published).length,
207
+ total: sortedDocs.length,
208
+ withOverrides: sortedDocs.filter((doc)=>doc.overrideSummary.length > 0).length
209
+ },
210
+ sync: docsSet.sync ? {
211
+ docsCount: typeof docsSet.sync.docsCount === 'number' ? docsSet.sync.docsCount : undefined,
212
+ lastStatus: docsSet.sync.lastStatus ?? undefined,
213
+ lastSyncedAt: docsSet.sync.lastSyncedAt ?? undefined
214
+ } : undefined,
215
+ tree,
216
+ warnings
217
+ };
218
+ };
219
+ export const isDocsRecordForDocsSet = ({ doc, docsSetId, sourceId })=>{
220
+ const docDocsSetId = getRelationshipId(doc.docsSet);
221
+ if (docDocsSetId) {
222
+ return docDocsSetId === docsSetId;
223
+ }
224
+ return doc.sync?.sourceId === sourceId;
225
+ };
226
+ export const getDocsSetManagerData = async ({ adminRoute, docsCollectionSlug = DEFAULT_DOCS_COLLECTION_SLUG, docsSetId, docsSetsCollectionSlug = DEFAULT_DOCS_SETS_COLLECTION_SLUG, overrideAccess = true, payload })=>{
227
+ const docsSet = await payload.findByID({
228
+ id: docsSetId,
229
+ collection: docsSetsCollectionSlug,
230
+ depth: 0,
231
+ overrideAccess
232
+ });
233
+ const docsResult = await payload.find({
234
+ collection: docsCollectionSlug,
235
+ depth: 0,
236
+ limit: 1000,
237
+ overrideAccess,
238
+ where: {
239
+ or: [
240
+ {
241
+ docsSet: {
242
+ equals: docsSetId
243
+ }
244
+ },
245
+ {
246
+ 'sync.sourceId': {
247
+ equals: docsSet.sourceId
248
+ }
249
+ }
250
+ ]
251
+ }
252
+ });
253
+ const docs = docsResult.docs.filter(isRecord).map((doc)=>doc).filter((doc)=>isDocsRecordForDocsSet({
254
+ doc,
255
+ docsSetId,
256
+ sourceId: docsSet.sourceId ?? ''
257
+ }));
258
+ return buildDocsSetManagerData({
259
+ adminRoute,
260
+ docs,
261
+ docsCollectionSlug,
262
+ docsSet
263
+ });
264
+ };
265
+
266
+ //# sourceMappingURL=docsSetManagerData.js.map
@@ -0,0 +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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"}
@@ -0,0 +1,103 @@
1
+ export type RawDocsSetRecord = {
2
+ id?: number | string;
3
+ routeBase?: string;
4
+ sourceId?: string;
5
+ sync?: {
6
+ docsCount?: null | number;
7
+ lastStatus?: 'failed' | 'pending' | 'success' | null;
8
+ lastSyncedAt?: null | string;
9
+ };
10
+ title?: string;
11
+ };
12
+ export type RawDocsRecord = {
13
+ _status?: 'draft' | 'published';
14
+ description?: null | string;
15
+ docsSet?: {
16
+ id?: number | string;
17
+ } | null | number | string;
18
+ id?: number | string;
19
+ navTitle?: null | string;
20
+ order?: null | number;
21
+ overrides?: {
22
+ heroDescription?: null | string;
23
+ heroEyebrow?: null | string;
24
+ heroTitle?: null | string;
25
+ hideFromNav?: boolean | null;
26
+ navTitle?: null | string;
27
+ seoDescription?: null | string;
28
+ seoTitle?: null | string;
29
+ theme?: null | string;
30
+ };
31
+ route?: null | string;
32
+ sourcePath?: null | string;
33
+ sync?: {
34
+ archived?: boolean | null;
35
+ archivedAt?: null | string;
36
+ lastSyncedAt?: null | string;
37
+ sourceId?: null | string;
38
+ };
39
+ title?: null | string;
40
+ };
41
+ export type DocsSetManagerWarning = {
42
+ docId?: string;
43
+ message: string;
44
+ sourcePath?: string;
45
+ };
46
+ export type DocsSetManagerDocStatus = 'archived' | 'draft' | 'published' | 'synced';
47
+ export type DocsSetManagerDocItem = {
48
+ adminURL?: string;
49
+ archived?: boolean;
50
+ children?: DocsSetManagerDocItem[];
51
+ draft?: boolean;
52
+ hiddenFromNav?: boolean;
53
+ id: string;
54
+ kind: 'doc' | 'folder';
55
+ order: number;
56
+ overrideSummary: string[];
57
+ published?: boolean;
58
+ route: string;
59
+ sourcePath: string;
60
+ status: DocsSetManagerDocStatus;
61
+ title: string;
62
+ };
63
+ export type DocsSetManagerData = {
64
+ docs: DocsSetManagerDocItem[];
65
+ docsSet: {
66
+ id: string;
67
+ routeBase: string;
68
+ sourceId: string;
69
+ title: string;
70
+ };
71
+ summary: {
72
+ archived: number;
73
+ drafts: number;
74
+ hiddenFromNav: number;
75
+ published: number;
76
+ total: number;
77
+ withOverrides: number;
78
+ };
79
+ sync?: {
80
+ docsCount?: number;
81
+ lastStatus?: 'failed' | 'pending' | 'success';
82
+ lastSyncedAt?: string;
83
+ };
84
+ tree: DocsSetManagerDocItem[];
85
+ warnings: DocsSetManagerWarning[];
86
+ };
87
+ export type DocsSetManagerPayloadOperations = {
88
+ find: (args: {
89
+ collection: string;
90
+ depth?: number;
91
+ limit?: number;
92
+ overrideAccess?: boolean;
93
+ where?: unknown;
94
+ }) => Promise<{
95
+ docs: unknown[];
96
+ }>;
97
+ findByID: (args: {
98
+ collection: string;
99
+ depth?: number;
100
+ id: number | string;
101
+ overrideAccess?: boolean;
102
+ }) => Promise<unknown>;
103
+ };
@@ -0,0 +1,3 @@
1
+ export { };
2
+
3
+ //# sourceMappingURL=docsSetManagerTypes.js.map
@@ -0,0 +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"}
@@ -0,0 +1,3 @@
1
+ export { DocsSetManager } from './DocsSetManager.js';
2
+ export { buildDocsSetManagerData, getDocsSetManagerData, getGeneratedDocAdminURL, isDocsRecordForDocsSet, } from './docsSetManagerData.js';
3
+ export type { DocsSetManagerData, DocsSetManagerDocItem, DocsSetManagerDocStatus, DocsSetManagerPayloadOperations, DocsSetManagerWarning, RawDocsRecord, RawDocsSetRecord, } from './docsSetManagerTypes.js';
@@ -0,0 +1,4 @@
1
+ export { DocsSetManager } from './DocsSetManager.js';
2
+ export { buildDocsSetManagerData, getDocsSetManagerData, getGeneratedDocAdminURL, isDocsRecordForDocsSet } from './docsSetManagerData.js';
3
+
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/admin/index.ts"],"sourcesContent":["export { DocsSetManager } from './DocsSetManager.js'\nexport {\n buildDocsSetManagerData,\n getDocsSetManagerData,\n getGeneratedDocAdminURL,\n isDocsRecordForDocsSet,\n} from './docsSetManagerData.js'\nexport type {\n DocsSetManagerData,\n DocsSetManagerDocItem,\n DocsSetManagerDocStatus,\n DocsSetManagerPayloadOperations,\n DocsSetManagerWarning,\n RawDocsRecord,\n RawDocsSetRecord,\n} from './docsSetManagerTypes.js'\n"],"names":["DocsSetManager","buildDocsSetManagerData","getDocsSetManagerData","getGeneratedDocAdminURL","isDocsRecordForDocsSet"],"mappings":"AAAA,SAASA,cAAc,QAAQ,sBAAqB;AACpD,SACEC,uBAAuB,EACvBC,qBAAqB,EACrBC,uBAAuB,EACvBC,sBAAsB,QACjB,0BAAyB"}
@@ -0,0 +1,2 @@
1
+ import type { CliResult, ParsedCliArgs } from '../types.js';
2
+ export declare const runInstallCommand: (args: ParsedCliArgs) => Promise<CliResult>;
@@ -0,0 +1,211 @@
1
+ import { access, mkdir, readdir, readFile, writeFile } from 'node:fs/promises';
2
+ import path from 'node:path';
3
+ import { getFlagBoolean, getFlagString } from '../parseArgs.js';
4
+ const packageManagers = new Set([
5
+ 'bun',
6
+ 'npm',
7
+ 'pnpm',
8
+ 'yarn'
9
+ ]);
10
+ const supportedInstallTargets = new Set([
11
+ 'ai-skill',
12
+ 'skill'
13
+ ]);
14
+ const defaultSkillOutputPath = '.agents/skills/payload-markdown-docs';
15
+ const skillTemplateRoot = new URL('../../skills/codex/', import.meta.url);
16
+ const fileExists = async (filePath)=>{
17
+ try {
18
+ await access(filePath);
19
+ return true;
20
+ } catch {
21
+ return false;
22
+ }
23
+ };
24
+ const detectPackageManager = async (cwd = process.cwd())=>{
25
+ const lockfiles = [
26
+ [
27
+ 'pnpm-lock.yaml',
28
+ 'pnpm'
29
+ ],
30
+ [
31
+ 'package-lock.json',
32
+ 'npm'
33
+ ],
34
+ [
35
+ 'yarn.lock',
36
+ 'yarn'
37
+ ],
38
+ [
39
+ 'bun.lockb',
40
+ 'bun'
41
+ ]
42
+ ];
43
+ for (const [file, packageManager] of lockfiles){
44
+ if (await fileExists(path.join(cwd, file))) {
45
+ return packageManager;
46
+ }
47
+ }
48
+ return 'pnpm';
49
+ };
50
+ const readTemplateFiles = async (directoryUrl = skillTemplateRoot, basePath = '')=>{
51
+ const entries = await readdir(directoryUrl, {
52
+ withFileTypes: true
53
+ });
54
+ const files = [];
55
+ for (const entry of entries){
56
+ if (entry.isSymbolicLink()) {
57
+ continue;
58
+ }
59
+ const relativePath = path.posix.join(basePath, entry.name);
60
+ const entryUrl = new URL(`${entry.name}${entry.isDirectory() ? '/' : ''}`, directoryUrl);
61
+ if (entry.isDirectory()) {
62
+ files.push(...await readTemplateFiles(entryUrl, relativePath));
63
+ continue;
64
+ }
65
+ if (!entry.isFile()) {
66
+ continue;
67
+ }
68
+ files.push({
69
+ content: await readFile(entryUrl, 'utf8'),
70
+ relativePath
71
+ });
72
+ }
73
+ return files.sort((left, right)=>left.relativePath.localeCompare(right.relativePath));
74
+ };
75
+ const applyTemplateValues = ({ content, docsRoot, packageManager })=>content.replaceAll('{{docsRoot}}', docsRoot).replaceAll('{{packageManager}}', packageManager);
76
+ const assertSafeRelativePath = (relativePath)=>{
77
+ const normalized = path.posix.normalize(relativePath);
78
+ if (normalized.startsWith('../') || normalized === '..' || path.isAbsolute(relativePath) || relativePath.includes('\\')) {
79
+ return {
80
+ exitCode: 1,
81
+ stderr: `Unsafe bundled skill path "${relativePath}".\n`
82
+ };
83
+ }
84
+ return undefined;
85
+ };
86
+ const createPlannedFiles = async ({ docsRoot, outDir, packageManager })=>{
87
+ const absoluteOutDir = path.resolve(outDir);
88
+ const templates = await readTemplateFiles();
89
+ const plannedFiles = [];
90
+ for (const template of templates){
91
+ const unsafe = assertSafeRelativePath(template.relativePath);
92
+ if (unsafe) {
93
+ return unsafe;
94
+ }
95
+ const outputPath = path.resolve(absoluteOutDir, template.relativePath);
96
+ if (outputPath !== absoluteOutDir && !outputPath.startsWith(`${absoluteOutDir}${path.sep}`)) {
97
+ return {
98
+ exitCode: 1,
99
+ stderr: `Refusing to write outside target directory: ${template.relativePath}\n`
100
+ };
101
+ }
102
+ plannedFiles.push({
103
+ content: applyTemplateValues({
104
+ content: template.content,
105
+ docsRoot,
106
+ packageManager
107
+ }),
108
+ path: outputPath,
109
+ relativePath: template.relativePath
110
+ });
111
+ }
112
+ return plannedFiles;
113
+ };
114
+ const getInstallSkillOptions = async (args)=>{
115
+ const [target] = args.positionals;
116
+ if (!target || !supportedInstallTargets.has(target)) {
117
+ return {
118
+ exitCode: 1,
119
+ stderr: 'Install requires target "skill" or "ai-skill".\n'
120
+ };
121
+ }
122
+ const agentFlag = getFlagString(args, 'agent');
123
+ const codex = getFlagBoolean(args, 'codex');
124
+ if (agentFlag && agentFlag !== 'codex') {
125
+ return {
126
+ exitCode: 1,
127
+ stderr: '--agent currently supports only "codex".\n'
128
+ };
129
+ }
130
+ if (!codex && agentFlag !== 'codex') {
131
+ return {
132
+ exitCode: 1,
133
+ stderr: 'Install skill requires --codex or --agent codex.\n'
134
+ };
135
+ }
136
+ const packageManagerFlag = getFlagString(args, 'package-manager');
137
+ if (packageManagerFlag !== undefined && !packageManagers.has(packageManagerFlag)) {
138
+ return {
139
+ exitCode: 1,
140
+ stderr: '--package-manager must be pnpm, npm, yarn, or bun.\n'
141
+ };
142
+ }
143
+ return {
144
+ agent: 'codex',
145
+ docsRoot: getFlagString(args, 'docs-root') ?? './docs',
146
+ dryRun: getFlagBoolean(args, 'dry-run'),
147
+ force: getFlagBoolean(args, 'force'),
148
+ outDir: getFlagString(args, 'out') ?? defaultSkillOutputPath,
149
+ packageManager: packageManagerFlag ?? await detectPackageManager()
150
+ };
151
+ };
152
+ const formatPlannedFiles = ({ dryRun, files, outDir })=>{
153
+ const lines = [
154
+ dryRun ? 'payload-markdown-docs install skill dry-run' : 'payload-markdown-docs install skill',
155
+ '',
156
+ `Target: ${path.resolve(outDir)}`,
157
+ 'Files:',
158
+ ...files.map((file)=>`- ${file.relativePath}`)
159
+ ];
160
+ return `${lines.join('\n')}\n`;
161
+ };
162
+ export const runInstallCommand = async (args)=>{
163
+ const options = await getInstallSkillOptions(args);
164
+ if ('exitCode' in options) {
165
+ return options;
166
+ }
167
+ const plannedFiles = await createPlannedFiles(options);
168
+ if ('exitCode' in plannedFiles) {
169
+ return plannedFiles;
170
+ }
171
+ if (!options.force) {
172
+ const existingFiles = [];
173
+ for (const file of plannedFiles){
174
+ if (await fileExists(file.path)) {
175
+ existingFiles.push(file.relativePath);
176
+ }
177
+ }
178
+ if (existingFiles.length > 0) {
179
+ return {
180
+ exitCode: 1,
181
+ stderr: `Skill files already exist. Use --force to overwrite:\n${existingFiles.map((file)=>`- ${file}`).join('\n')}\n`
182
+ };
183
+ }
184
+ }
185
+ if (options.dryRun) {
186
+ return {
187
+ exitCode: 0,
188
+ stdout: formatPlannedFiles({
189
+ dryRun: true,
190
+ files: plannedFiles,
191
+ outDir: options.outDir
192
+ })
193
+ };
194
+ }
195
+ for (const file of plannedFiles){
196
+ await mkdir(path.dirname(file.path), {
197
+ recursive: true
198
+ });
199
+ await writeFile(file.path, file.content, 'utf8');
200
+ }
201
+ return {
202
+ exitCode: 0,
203
+ stdout: formatPlannedFiles({
204
+ dryRun: false,
205
+ files: plannedFiles,
206
+ outDir: options.outDir
207
+ })
208
+ };
209
+ };
210
+
211
+ //# sourceMappingURL=install.js.map