@anydocs/core 1.0.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 (124) hide show
  1. package/dist/config/index.d.ts +2 -0
  2. package/dist/config/index.d.ts.map +1 -0
  3. package/dist/config/index.js +1 -0
  4. package/dist/config/project-config.d.ts +10 -0
  5. package/dist/config/project-config.d.ts.map +1 -0
  6. package/dist/config/project-config.js +52 -0
  7. package/dist/errors/domain-error.d.ts +12 -0
  8. package/dist/errors/domain-error.d.ts.map +1 -0
  9. package/dist/errors/domain-error.js +8 -0
  10. package/dist/errors/index.d.ts +3 -0
  11. package/dist/errors/index.d.ts.map +1 -0
  12. package/dist/errors/index.js +2 -0
  13. package/dist/errors/validation-error.d.ts +5 -0
  14. package/dist/errors/validation-error.d.ts.map +1 -0
  15. package/dist/errors/validation-error.js +7 -0
  16. package/dist/fs/api-source-repository.d.ts +16 -0
  17. package/dist/fs/api-source-repository.d.ts.map +1 -0
  18. package/dist/fs/api-source-repository.js +89 -0
  19. package/dist/fs/content-repository.d.ts +13 -0
  20. package/dist/fs/content-repository.d.ts.map +1 -0
  21. package/dist/fs/content-repository.js +171 -0
  22. package/dist/fs/docs-repository.d.ts +26 -0
  23. package/dist/fs/docs-repository.d.ts.map +1 -0
  24. package/dist/fs/docs-repository.js +270 -0
  25. package/dist/fs/index.d.ts +5 -0
  26. package/dist/fs/index.d.ts.map +1 -0
  27. package/dist/fs/index.js +4 -0
  28. package/dist/fs/project-paths.d.ts +4 -0
  29. package/dist/fs/project-paths.d.ts.map +1 -0
  30. package/dist/fs/project-paths.js +55 -0
  31. package/dist/index.d.ts +9 -0
  32. package/dist/index.d.ts.map +1 -0
  33. package/dist/index.js +8 -0
  34. package/dist/publishing/build-artifacts.d.ts +4 -0
  35. package/dist/publishing/build-artifacts.d.ts.map +1 -0
  36. package/dist/publishing/build-artifacts.js +453 -0
  37. package/dist/publishing/build-openapi-artifacts.d.ts +3 -0
  38. package/dist/publishing/build-openapi-artifacts.d.ts.map +1 -0
  39. package/dist/publishing/build-openapi-artifacts.js +253 -0
  40. package/dist/publishing/index.d.ts +4 -0
  41. package/dist/publishing/index.d.ts.map +1 -0
  42. package/dist/publishing/index.js +3 -0
  43. package/dist/publishing/publication-filter.d.ts +22 -0
  44. package/dist/publishing/publication-filter.d.ts.map +1 -0
  45. package/dist/publishing/publication-filter.js +98 -0
  46. package/dist/schemas/api-source-schema.d.ts +3 -0
  47. package/dist/schemas/api-source-schema.d.ts.map +1 -0
  48. package/dist/schemas/api-source-schema.js +110 -0
  49. package/dist/schemas/docs-schema.d.ts +7 -0
  50. package/dist/schemas/docs-schema.d.ts.map +1 -0
  51. package/dist/schemas/docs-schema.js +212 -0
  52. package/dist/schemas/index.d.ts +4 -0
  53. package/dist/schemas/index.d.ts.map +1 -0
  54. package/dist/schemas/index.js +3 -0
  55. package/dist/schemas/project-schema.d.ts +3 -0
  56. package/dist/schemas/project-schema.d.ts.map +1 -0
  57. package/dist/schemas/project-schema.js +268 -0
  58. package/dist/services/authoring-service.d.ts +137 -0
  59. package/dist/services/authoring-service.d.ts.map +1 -0
  60. package/dist/services/authoring-service.js +583 -0
  61. package/dist/services/build-service.d.ts +35 -0
  62. package/dist/services/build-service.d.ts.map +1 -0
  63. package/dist/services/build-service.js +84 -0
  64. package/dist/services/index.d.ts +11 -0
  65. package/dist/services/index.d.ts.map +1 -0
  66. package/dist/services/index.js +10 -0
  67. package/dist/services/init-service.d.ts +15 -0
  68. package/dist/services/init-service.d.ts.map +1 -0
  69. package/dist/services/init-service.js +127 -0
  70. package/dist/services/legacy-conversion-service.d.ts +8 -0
  71. package/dist/services/legacy-conversion-service.d.ts.map +1 -0
  72. package/dist/services/legacy-conversion-service.js +601 -0
  73. package/dist/services/legacy-import-service.d.ts +10 -0
  74. package/dist/services/legacy-import-service.d.ts.map +1 -0
  75. package/dist/services/legacy-import-service.js +239 -0
  76. package/dist/services/page-template-service.d.ts +81 -0
  77. package/dist/services/page-template-service.d.ts.map +1 -0
  78. package/dist/services/page-template-service.js +342 -0
  79. package/dist/services/preview-service.d.ts +29 -0
  80. package/dist/services/preview-service.d.ts.map +1 -0
  81. package/dist/services/preview-service.js +45 -0
  82. package/dist/services/watch-service.d.ts +24 -0
  83. package/dist/services/watch-service.d.ts.map +1 -0
  84. package/dist/services/watch-service.js +216 -0
  85. package/dist/services/web-runtime-bridge.d.ts +33 -0
  86. package/dist/services/web-runtime-bridge.d.ts.map +1 -0
  87. package/dist/services/web-runtime-bridge.js +330 -0
  88. package/dist/services/workflow-compatibility-service.d.ts +3 -0
  89. package/dist/services/workflow-compatibility-service.d.ts.map +1 -0
  90. package/dist/services/workflow-compatibility-service.js +53 -0
  91. package/dist/services/workflow-standard-service.d.ts +9 -0
  92. package/dist/services/workflow-standard-service.d.ts.map +1 -0
  93. package/dist/services/workflow-standard-service.js +372 -0
  94. package/dist/types/api-source.d.ts +34 -0
  95. package/dist/types/api-source.d.ts.map +1 -0
  96. package/dist/types/api-source.js +8 -0
  97. package/dist/types/docs.d.ts +65 -0
  98. package/dist/types/docs.d.ts.map +1 -0
  99. package/dist/types/docs.js +8 -0
  100. package/dist/types/index.d.ts +6 -0
  101. package/dist/types/index.d.ts.map +1 -0
  102. package/dist/types/index.js +5 -0
  103. package/dist/types/legacy-import.d.ts +72 -0
  104. package/dist/types/legacy-import.d.ts.map +1 -0
  105. package/dist/types/legacy-import.js +1 -0
  106. package/dist/types/project.d.ts +85 -0
  107. package/dist/types/project.d.ts.map +1 -0
  108. package/dist/types/project.js +5 -0
  109. package/dist/types/workflow-standard.d.ts +51 -0
  110. package/dist/types/workflow-standard.d.ts.map +1 -0
  111. package/dist/types/workflow-standard.js +1 -0
  112. package/dist/utils/index.d.ts +4 -0
  113. package/dist/utils/index.d.ts.map +1 -0
  114. package/dist/utils/index.js +3 -0
  115. package/dist/utils/slug.d.ts +3 -0
  116. package/dist/utils/slug.d.ts.map +1 -0
  117. package/dist/utils/slug.js +21 -0
  118. package/dist/utils/yoopta-content.d.ts +13 -0
  119. package/dist/utils/yoopta-content.d.ts.map +1 -0
  120. package/dist/utils/yoopta-content.js +73 -0
  121. package/dist/utils/yoopta-render.d.ts +7 -0
  122. package/dist/utils/yoopta-render.d.ts.map +1 -0
  123. package/dist/utils/yoopta-render.js +155 -0
  124. package/package.json +30 -0
@@ -0,0 +1,453 @@
1
+ import { mkdir, readdir, unlink, writeFile } from 'node:fs/promises';
2
+ import path from 'node:path';
3
+ const CHUNK_MAX_CHARS = 2000;
4
+ const CHUNK_OVERLAP_CHARS = 200;
5
+ function stripMarkdown(markdown) {
6
+ return markdown
7
+ .replace(/```[\s\S]*?```/g, ' ')
8
+ .replace(/`[^`]*`/g, ' ')
9
+ .replace(/!\[[^\]]*\]\([^)]*\)/g, ' ')
10
+ .replace(/\[[^\]]*\]\([^)]*\)/g, ' ')
11
+ .replace(/[#>*_~]/g, ' ')
12
+ .replace(/\s+/g, ' ')
13
+ .trim();
14
+ }
15
+ function stripLeadingTitleHeading(markdown, title) {
16
+ const lines = markdown.split('\n');
17
+ let index = 0;
18
+ while (index < lines.length && lines[index]?.trim() === '') {
19
+ index += 1;
20
+ }
21
+ const firstLine = lines[index]?.trim();
22
+ if (!firstLine) {
23
+ return markdown;
24
+ }
25
+ const expectedHeading = `# ${title.trim()}`;
26
+ if (firstLine !== expectedHeading) {
27
+ return markdown;
28
+ }
29
+ index += 1;
30
+ while (index < lines.length && lines[index]?.trim() === '') {
31
+ index += 1;
32
+ }
33
+ return lines.slice(index).join('\n');
34
+ }
35
+ function stripLeadingTitleText(plainText, title) {
36
+ const normalizedText = plainText.trim();
37
+ const normalizedTitle = title.trim();
38
+ if (!normalizedText || !normalizedTitle) {
39
+ return normalizedText;
40
+ }
41
+ if (normalizedText === normalizedTitle) {
42
+ return '';
43
+ }
44
+ if (normalizedText.startsWith(`${normalizedTitle} `)) {
45
+ return normalizedText.slice(normalizedTitle.length).trimStart();
46
+ }
47
+ return normalizedText;
48
+ }
49
+ function walkNavItems(items, trail, callback) {
50
+ for (const item of items) {
51
+ callback(item, trail);
52
+ if (item.type === 'section' || item.type === 'folder') {
53
+ const nextTrail = item.title ? [...trail, item.title] : trail;
54
+ walkNavItems(item.children, nextTrail, callback);
55
+ }
56
+ }
57
+ }
58
+ function buildPageBreadcrumbs(items) {
59
+ const breadcrumbs = new Map();
60
+ walkNavItems(items, [], (item, trail) => {
61
+ if (item.type === 'page') {
62
+ breadcrumbs.set(item.pageId, trail);
63
+ }
64
+ });
65
+ return breadcrumbs;
66
+ }
67
+ function countNavigationItems(items) {
68
+ let count = 0;
69
+ for (const item of items) {
70
+ count += 1;
71
+ if (item.type === 'section' || item.type === 'folder') {
72
+ count += countNavigationItems(item.children);
73
+ }
74
+ }
75
+ return count;
76
+ }
77
+ function getPageText(page) {
78
+ const markdown = page.render?.markdown ?? '';
79
+ const plainText = page.render?.plainText ?? stripMarkdown(markdown);
80
+ return {
81
+ markdown,
82
+ plainText,
83
+ };
84
+ }
85
+ function toSearchDoc(page, breadcrumbs) {
86
+ const { plainText } = getPageText(page);
87
+ return {
88
+ id: page.id,
89
+ slug: page.slug,
90
+ title: page.title,
91
+ description: page.description ?? '',
92
+ tags: page.tags ?? [],
93
+ status: 'published',
94
+ updatedAt: page.updatedAt ?? null,
95
+ breadcrumbs,
96
+ text: plainText,
97
+ };
98
+ }
99
+ function buildLlmsTxt(siteArtifacts) {
100
+ const lines = [];
101
+ lines.push('# Docs (LLM-friendly index)');
102
+ lines.push('');
103
+ lines.push(`- Languages: ${siteArtifacts.map((entry) => entry.lang).join(', ')}`);
104
+ lines.push(`- Base routes: ${siteArtifacts.map((entry) => `/${entry.lang}`).join(', ')}`);
105
+ lines.push('');
106
+ for (const site of siteArtifacts) {
107
+ if (site.content.pages.length === 0) {
108
+ continue;
109
+ }
110
+ lines.push(`## ${site.lang}`);
111
+ lines.push('');
112
+ for (const page of site.content.pages) {
113
+ const title = page.title ?? page.slug;
114
+ const description = page.description ? ` — ${page.description}` : '';
115
+ lines.push(`- ${title} — /${site.lang}/${page.slug}${description}`);
116
+ }
117
+ lines.push('');
118
+ }
119
+ return lines.join('\n').trimEnd();
120
+ }
121
+ function buildLlmsFullTxt(contract, siteArtifacts, generatedAt) {
122
+ const lines = [];
123
+ lines.push('# Docs Full Export');
124
+ lines.push(`- Project: ${contract.config.projectId}`);
125
+ lines.push(`- Languages: ${siteArtifacts.map((entry) => entry.lang).join(', ')}`);
126
+ lines.push('- Publication Rule: published-only');
127
+ lines.push(`- Generated At: ${generatedAt}`);
128
+ lines.push('');
129
+ for (const site of siteArtifacts) {
130
+ lines.push(`## Language: ${site.lang}`);
131
+ lines.push('');
132
+ for (const page of site.content.pages) {
133
+ const { plainText } = getPageText(page);
134
+ const body = stripLeadingTitleText(plainText, page.title) || plainText.trim() || page.title.trim();
135
+ const breadcrumbs = buildPageBreadcrumbs(site.content.navigation.items).get(page.id) ?? [];
136
+ lines.push('### Page');
137
+ lines.push(`- Page ID: ${page.id}`);
138
+ lines.push(`- URL: /${site.lang}/${page.slug}`);
139
+ lines.push(`- Title: ${page.title}`);
140
+ lines.push(`- Breadcrumbs: ${breadcrumbs.length ? breadcrumbs.join(' > ') : '(none)'}`);
141
+ lines.push(`- Tags: ${page.tags?.length ? page.tags.join(', ') : '(none)'}`);
142
+ lines.push(`- Updated At: ${page.updatedAt ?? 'null'}`);
143
+ lines.push('');
144
+ lines.push(body);
145
+ lines.push('');
146
+ }
147
+ }
148
+ return lines.join('\n').trimEnd();
149
+ }
150
+ function extractMarkdownSections(markdown, title) {
151
+ const normalized = stripLeadingTitleHeading(markdown, title).replace(/\r\n/g, '\n').trim();
152
+ if (!normalized) {
153
+ return [];
154
+ }
155
+ const sections = [];
156
+ const headingStack = [];
157
+ const lines = normalized.split('\n');
158
+ let currentHeadingPath = [];
159
+ let currentLines = [];
160
+ const flushCurrent = () => {
161
+ const text = stripMarkdown(currentLines.join('\n'));
162
+ if (!text) {
163
+ return;
164
+ }
165
+ sections.push({
166
+ headingPath: [...currentHeadingPath],
167
+ text,
168
+ });
169
+ };
170
+ for (const line of lines) {
171
+ const headingMatch = /^(#{1,6})\s+(.+?)\s*$/.exec(line);
172
+ if (!headingMatch) {
173
+ currentLines.push(line);
174
+ continue;
175
+ }
176
+ flushCurrent();
177
+ currentLines = [];
178
+ const depth = headingMatch[1].length;
179
+ const headingTitle = headingMatch[2].replace(/`/g, '').trim();
180
+ while (headingStack.length > 0 && headingStack[headingStack.length - 1].depth >= depth) {
181
+ headingStack.pop();
182
+ }
183
+ headingStack.push({ depth, title: headingTitle });
184
+ currentHeadingPath = headingStack.map((entry) => entry.title);
185
+ }
186
+ flushCurrent();
187
+ return sections;
188
+ }
189
+ function splitChunkText(text, maxChars = CHUNK_MAX_CHARS, overlapChars = CHUNK_OVERLAP_CHARS) {
190
+ const normalized = text.replace(/\s+/g, ' ').trim();
191
+ if (!normalized) {
192
+ return [];
193
+ }
194
+ if (normalized.length <= maxChars) {
195
+ return [normalized];
196
+ }
197
+ const chunks = [];
198
+ let start = 0;
199
+ while (start < normalized.length) {
200
+ let end = Math.min(normalized.length, start + maxChars);
201
+ if (end < normalized.length) {
202
+ const lastSpace = normalized.lastIndexOf(' ', end);
203
+ if (lastSpace > start + Math.floor(maxChars * 0.6)) {
204
+ end = lastSpace;
205
+ }
206
+ }
207
+ const chunk = normalized.slice(start, end).trim();
208
+ if (chunk) {
209
+ chunks.push(chunk);
210
+ }
211
+ if (end >= normalized.length) {
212
+ break;
213
+ }
214
+ start = Math.max(start + 1, end - overlapChars);
215
+ }
216
+ return chunks;
217
+ }
218
+ function toChunkDocs(site, page, breadcrumbs) {
219
+ const { markdown, plainText } = getPageText(page);
220
+ const sectionCandidates = extractMarkdownSections(markdown, page.title);
221
+ const fallbackText = stripLeadingTitleText(plainText, page.title) || plainText.trim() || page.title.trim();
222
+ const sections = sectionCandidates.length > 0
223
+ ? sectionCandidates
224
+ : fallbackText
225
+ ? [{ headingPath: [], text: fallbackText }]
226
+ : [];
227
+ const chunks = [];
228
+ let order = 1;
229
+ for (const section of sections) {
230
+ for (const chunkText of splitChunkText(section.text)) {
231
+ chunks.push({
232
+ id: `${page.id}#${String(order).padStart(4, '0')}`,
233
+ pageId: page.id,
234
+ lang: site.lang,
235
+ slug: page.slug,
236
+ href: `/${site.lang}/${page.slug}`,
237
+ title: page.title,
238
+ description: page.description ?? '',
239
+ headingPath: section.headingPath,
240
+ breadcrumbs,
241
+ order,
242
+ tags: page.tags ?? [],
243
+ updatedAt: page.updatedAt ?? null,
244
+ text: chunkText,
245
+ tokenEstimate: Math.max(1, Math.ceil(chunkText.length / 4)),
246
+ });
247
+ order += 1;
248
+ }
249
+ }
250
+ if (chunks.length > 0) {
251
+ return chunks;
252
+ }
253
+ return [
254
+ {
255
+ id: `${page.id}#0001`,
256
+ pageId: page.id,
257
+ lang: site.lang,
258
+ slug: page.slug,
259
+ href: `/${site.lang}/${page.slug}`,
260
+ title: page.title,
261
+ description: page.description ?? '',
262
+ headingPath: [],
263
+ breadcrumbs,
264
+ order: 1,
265
+ tags: page.tags ?? [],
266
+ updatedAt: page.updatedAt ?? null,
267
+ text: page.title.trim(),
268
+ tokenEstimate: Math.max(1, Math.ceil(page.title.trim().length / 4)),
269
+ },
270
+ ];
271
+ }
272
+ async function writeJson(filePath, value) {
273
+ await mkdir(path.dirname(filePath), { recursive: true });
274
+ await writeFile(filePath, `${JSON.stringify(value, null, 2)}\n`, 'utf8');
275
+ }
276
+ async function writeText(filePath, value) {
277
+ await mkdir(path.dirname(filePath), { recursive: true });
278
+ await writeFile(filePath, `${value}\n`, 'utf8');
279
+ }
280
+ function serializeThemeMetadata(theme) {
281
+ return {
282
+ id: theme.id,
283
+ ...(theme.branding ? { branding: theme.branding } : {}),
284
+ ...(theme.chrome ? { chrome: theme.chrome } : {}),
285
+ ...(theme.colors ? { colors: theme.colors } : {}),
286
+ ...(theme.codeTheme ? { codeTheme: theme.codeTheme } : {}),
287
+ };
288
+ }
289
+ function serializeSiteNavigationMetadata(navigation) {
290
+ return {
291
+ ...(navigation?.topNav ? { topNav: navigation.topNav } : {}),
292
+ };
293
+ }
294
+ async function cleanupLegacyLanguageArtifacts(artifactRoot, machineReadableRoot, enabledLanguages) {
295
+ try {
296
+ const artifactFiles = await readdir(artifactRoot);
297
+ for (const fileName of artifactFiles) {
298
+ const searchMatch = /^search-index\.(.+)\.json$/.exec(fileName);
299
+ if (!searchMatch) {
300
+ continue;
301
+ }
302
+ const language = searchMatch[1];
303
+ if (enabledLanguages.has(language)) {
304
+ continue;
305
+ }
306
+ await unlink(path.join(artifactRoot, fileName));
307
+ }
308
+ }
309
+ catch {
310
+ // Ignore cleanup failures for non-existent directories. Build write step recreates canonical files.
311
+ }
312
+ try {
313
+ const machineReadableFiles = await readdir(machineReadableRoot);
314
+ for (const fileName of machineReadableFiles) {
315
+ const artifactMatch = /^(navigation|pages|chunks)\.(.+)\.json$/.exec(fileName);
316
+ if (!artifactMatch) {
317
+ continue;
318
+ }
319
+ const language = artifactMatch[2];
320
+ if (enabledLanguages.has(language)) {
321
+ continue;
322
+ }
323
+ await unlink(path.join(machineReadableRoot, fileName));
324
+ }
325
+ }
326
+ catch {
327
+ // Ignore cleanup failures for non-existent directories. Build write step recreates canonical files.
328
+ }
329
+ }
330
+ export async function writePublishedArtifacts(contract, siteArtifacts) {
331
+ const generatedAt = new Date().toISOString();
332
+ const enabledLanguages = new Set(siteArtifacts.map((entry) => entry.lang));
333
+ const outputRoot = contract.paths.artifactRoot;
334
+ await mkdir(contract.paths.artifactRoot, { recursive: true });
335
+ await mkdir(contract.paths.machineReadableRoot, { recursive: true });
336
+ await cleanupLegacyLanguageArtifacts(outputRoot, contract.paths.machineReadableRoot, enabledLanguages);
337
+ for (const site of siteArtifacts) {
338
+ const breadcrumbsById = buildPageBreadcrumbs(site.content.navigation.items);
339
+ const languagePaths = contract.paths.languageRoots[site.lang];
340
+ const searchIndex = {
341
+ lang: site.lang,
342
+ generatedAt,
343
+ docs: site.content.pages.map((page) => toSearchDoc(page, breadcrumbsById.get(page.id) ?? [])),
344
+ };
345
+ const navigationArtifact = {
346
+ lang: site.lang,
347
+ version: site.content.navigation.version,
348
+ items: site.content.navigation.items,
349
+ };
350
+ const chunkArtifact = {
351
+ lang: site.lang,
352
+ generatedAt,
353
+ chunking: {
354
+ strategy: 'heading-aware',
355
+ maxChars: CHUNK_MAX_CHARS,
356
+ overlapChars: CHUNK_OVERLAP_CHARS,
357
+ },
358
+ chunks: site.content.pages.flatMap((page) => toChunkDocs(site, page, breadcrumbsById.get(page.id) ?? [])),
359
+ };
360
+ const pagesArtifact = {
361
+ lang: site.lang,
362
+ generatedAt,
363
+ pages: site.content.pages.map((page) => ({
364
+ id: page.id,
365
+ slug: page.slug,
366
+ href: `/${site.lang}/${page.slug}`,
367
+ title: page.title,
368
+ description: page.description ?? '',
369
+ tags: page.tags ?? [],
370
+ updatedAt: page.updatedAt ?? null,
371
+ breadcrumbs: breadcrumbsById.get(page.id) ?? [],
372
+ })),
373
+ };
374
+ await writeJson(languagePaths.searchIndexFile, searchIndex);
375
+ await writeJson(path.join(contract.paths.machineReadableRoot, `navigation.${site.lang}.json`), navigationArtifact);
376
+ await writeJson(path.join(contract.paths.machineReadableRoot, `pages.${site.lang}.json`), pagesArtifact);
377
+ await writeJson(path.join(contract.paths.machineReadableRoot, `chunks.${site.lang}.json`), chunkArtifact);
378
+ }
379
+ const machineReadableIndex = {
380
+ version: 1,
381
+ generatedAt,
382
+ projectId: contract.config.projectId,
383
+ publicationRule: 'published-only',
384
+ site: {
385
+ theme: serializeThemeMetadata(contract.config.site.theme),
386
+ ...(contract.config.site.navigation ? { navigation: serializeSiteNavigationMetadata(contract.config.site.navigation) } : {}),
387
+ },
388
+ languages: siteArtifacts.map((site) => ({
389
+ lang: site.lang,
390
+ publishedPages: site.content.pages.length,
391
+ navigationItems: countNavigationItems(site.content.navigation.items),
392
+ files: {
393
+ searchIndex: `../search-index.${site.lang}.json`,
394
+ navigation: `navigation.${site.lang}.json`,
395
+ pages: `pages.${site.lang}.json`,
396
+ chunks: `chunks.${site.lang}.json`,
397
+ },
398
+ })),
399
+ };
400
+ await writeJson(path.join(contract.paths.machineReadableRoot, 'index.json'), machineReadableIndex);
401
+ const llms = buildLlmsTxt(siteArtifacts);
402
+ await writeText(contract.paths.llmsFile, llms);
403
+ const llmsFull = buildLlmsFullTxt(contract, siteArtifacts, generatedAt);
404
+ await writeText(path.join(outputRoot, 'llms-full.txt'), llmsFull);
405
+ // Generate build manifest
406
+ const publishedPagesByLang = {};
407
+ for (const site of siteArtifacts) {
408
+ publishedPagesByLang[site.lang] = site.content.pages.length;
409
+ }
410
+ const buildManifest = {
411
+ version: '1.0.0',
412
+ buildTime: generatedAt,
413
+ builder: {
414
+ tool: 'anydocs-cli',
415
+ version: '1.0.0',
416
+ },
417
+ source: {
418
+ projectRoot: contract.paths.projectRoot,
419
+ projectId: contract.config.projectId,
420
+ site: {
421
+ theme: serializeThemeMetadata(contract.config.site.theme),
422
+ ...(contract.config.site.navigation ? { navigation: serializeSiteNavigationMetadata(contract.config.site.navigation) } : {}),
423
+ },
424
+ },
425
+ output: {
426
+ directory: outputRoot,
427
+ structure: 'flat',
428
+ },
429
+ projects: [
430
+ {
431
+ projectId: contract.config.projectId,
432
+ languages: contract.config.languages,
433
+ site: {
434
+ theme: serializeThemeMetadata(contract.config.site.theme),
435
+ ...(contract.config.site.navigation ? { navigation: serializeSiteNavigationMetadata(contract.config.site.navigation) } : {}),
436
+ },
437
+ publishedPages: publishedPagesByLang,
438
+ artifacts: {
439
+ site: '.',
440
+ mcp: path.relative(outputRoot, contract.paths.machineReadableRoot),
441
+ llms: path.relative(outputRoot, contract.paths.llmsFile),
442
+ searchIndexes: contract.config.languages.map((lang) => path.relative(outputRoot, contract.paths.languageRoots[lang].searchIndexFile)),
443
+ },
444
+ },
445
+ ],
446
+ deployment: {
447
+ type: 'static',
448
+ serverRequired: false,
449
+ recommended: ['nginx', 'vercel', 'netlify', 'cloudflare-pages', 'github-pages'],
450
+ },
451
+ };
452
+ await writeJson(path.join(outputRoot, 'build-manifest.json'), buildManifest);
453
+ }
@@ -0,0 +1,3 @@
1
+ import type { ProjectContract } from '../types/project.ts';
2
+ export declare function writePublishedOpenApiArtifacts(contract: ProjectContract): Promise<void>;
3
+ //# sourceMappingURL=build-openapi-artifacts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build-openapi-artifacts.d.ts","sourceRoot":"","sources":["../../src/publishing/build-openapi-artifacts.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAoT3D,wBAAsB,8BAA8B,CAAC,QAAQ,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAmD7F"}