@gitpagedocs/cli 1.1.62 → 1.1.63

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 (59) hide show
  1. package/README.md +193 -193
  2. package/ai/application/ai-command.ts +24 -24
  3. package/ai/application/ai-provider-factory.ts +22 -22
  4. package/ai/application/docs-pattern.ts +68 -68
  5. package/ai/application/run-ai-cli-command.ts +167 -167
  6. package/ai/config.ts +50 -50
  7. package/ai/core/models/ai-cli-config.ts +33 -33
  8. package/ai/core/models/parse-ai-cli-config.ts +78 -78
  9. package/ai/core/ports/illm-provider.ts +32 -32
  10. package/ai/infrastructure/ai-config-file.ts +101 -101
  11. package/ai/infrastructure/file-system-adapter.ts +85 -85
  12. package/ai/infrastructure/llm/tools-llm-provider.ts +54 -54
  13. package/ai/infrastructure/version-docs-writer.ts +143 -143
  14. package/ai/presentation/ai-prompts.ts +239 -239
  15. package/application/ports/cli-runtime-ports.ts +91 -91
  16. package/application/report/config-only-reporter.mjs +64 -64
  17. package/application/use-cases/dispatch-mode.ts +18 -18
  18. package/builders/config-orchestrator.mjs +34 -34
  19. package/builders/project-links.mjs +50 -50
  20. package/builders/root-config-builder.mjs +61 -61
  21. package/builders/route-builders.mjs +136 -136
  22. package/builders/theme-template.mjs +76 -76
  23. package/builders/version-config-builder.mjs +186 -186
  24. package/content/docs-en.mjs +549 -549
  25. package/content/docs-es.mjs +462 -462
  26. package/content/docs-pt.mjs +462 -462
  27. package/contracts/doc-versions.mjs +3 -3
  28. package/data/default-site-config.mjs +321 -321
  29. package/data/i18n-langmenu.mjs +347 -347
  30. package/data/layouts.mjs +436 -436
  31. package/data/path-mappings.mjs +26 -26
  32. package/data/route-metas.mjs +93 -93
  33. package/data/theme-colors.mjs +443 -443
  34. package/data/urls.mjs +12 -12
  35. package/domain/models/cli-options.ts +33 -33
  36. package/home/constants.mjs +4 -4
  37. package/index.mjs +37 -37
  38. package/infrastructure/gitpagedocs-config-file.ts +47 -47
  39. package/infrastructure/home/runtime.mjs +37 -37
  40. package/package.json +3 -3
  41. package/presentation/commands/ai-info.ts +57 -57
  42. package/presentation/commands/config-clear.ts +23 -23
  43. package/presentation/commands/config-info.ts +24 -24
  44. package/presentation/commands/diagnostics.ts +164 -164
  45. package/presentation/commands/docs.ts +37 -37
  46. package/presentation/commands/mcp.ts +20 -20
  47. package/presentation/commands/pages.ts +101 -101
  48. package/presentation/commands/password.ts +62 -62
  49. package/presentation/commands/run-command.ts +70 -70
  50. package/presentation/index.ts +124 -124
  51. package/presentation/options/parser.ts +119 -119
  52. package/presentation/options/resolver.ts +46 -46
  53. package/presentation/ui/clack.ts +91 -91
  54. package/presentation/ui/prompts.ts +146 -146
  55. package/runtime/git-ops.mjs +110 -110
  56. package/runtime/output.mjs +159 -159
  57. package/runtime/workflow.mjs +129 -129
  58. package/start.mjs +12 -12
  59. package/ui/logger.mjs +9 -9
@@ -1,143 +1,143 @@
1
- import fs from "node:fs/promises";
2
- import path from "node:path";
3
- // @ts-expect-error .mjs runtime module is type-less in this package.
4
- import { buildMdRoute } from "../../builders/route-builders.mjs";
5
- import type { AiDocPage } from "../application/docs-pattern";
6
-
7
- const CANONICAL_LANGS = ["pt", "en", "es"] as const;
8
- type Lang = (typeof CANONICAL_LANGS)[number];
9
-
10
- /** AI routes/menus use a high, dedicated id range so they never clash with the
11
- * deterministic base routes (ids 1..N) and can be identified for idempotency. */
12
- const AI_ROUTE_ID_BASE = 1000;
13
-
14
- export interface VersionDocsWriteInput {
15
- cwd: string;
16
- versionId: string;
17
- /** Pages generated per language (only the languages the user selected). */
18
- pagesByLang: Partial<Record<Lang, AiDocPage[]>>;
19
- }
20
-
21
- export interface VersionDocsWriteResult {
22
- configPath: string;
23
- slugs: string[];
24
- files: string[];
25
- }
26
-
27
- interface LangContent {
28
- title: string;
29
- body: string;
30
- }
31
-
32
- function indexBySlug(pages: AiDocPage[] | undefined): Map<string, AiDocPage> {
33
- const map = new Map<string, AiDocPage>();
34
- for (const page of pages ?? []) {
35
- if (!map.has(page.slug)) map.set(page.slug, page);
36
- }
37
- return map;
38
- }
39
-
40
- /**
41
- * Write AI-generated pages into the gitpagedocs versioned structure and wire
42
- * them into the version config.json (routes-md + menus-header-md). Pages are
43
- * written for ALL three canonical languages (missing languages reuse an
44
- * available translation) so every route path stays valid. Idempotent: any prior
45
- * `aiGenerated` routes/menus are replaced, never duplicated. The base config and
46
- * its deterministic routes are preserved untouched.
47
- */
48
- export async function writeVersionDocs(input: VersionDocsWriteInput): Promise<VersionDocsWriteResult> {
49
- const { cwd, versionId, pagesByLang } = input;
50
- const base = `gitpagedocs/docs/versions/${versionId}`;
51
-
52
- const perLang: Record<Lang, Map<string, AiDocPage>> = {
53
- pt: indexBySlug(pagesByLang.pt),
54
- en: indexBySlug(pagesByLang.en),
55
- es: indexBySlug(pagesByLang.es),
56
- };
57
-
58
- // Ordered unique slug list (prefer en order, then pt, then es).
59
- const order: string[] = [];
60
- const seen = new Set<string>();
61
- for (const lang of ["en", "pt", "es"] as Lang[]) {
62
- for (const page of pagesByLang[lang] ?? []) {
63
- if (!seen.has(page.slug)) {
64
- seen.add(page.slug);
65
- order.push(page.slug);
66
- }
67
- }
68
- }
69
- if (order.length === 0) {
70
- throw new Error("No AI pages to write.");
71
- }
72
-
73
- const resolve = (slug: string): Record<Lang, LangContent> => {
74
- const fallback = CANONICAL_LANGS.map((lang) => perLang[lang].get(slug)).find(Boolean);
75
- const out = {} as Record<Lang, LangContent>;
76
- for (const lang of CANONICAL_LANGS) {
77
- const page = perLang[lang].get(slug) ?? fallback!;
78
- out[lang] = { title: page.title, body: page.body };
79
- }
80
- return out;
81
- };
82
-
83
- // 1) Write the markdown files (all 3 canonical languages).
84
- const writtenFiles: string[] = [];
85
- for (const slug of order) {
86
- const content = resolve(slug);
87
- for (const lang of CANONICAL_LANGS) {
88
- const rel = `${base}/${lang}/${slug}.md`;
89
- const abs = path.resolve(cwd, rel);
90
- await fs.mkdir(path.dirname(abs), { recursive: true });
91
- await fs.writeFile(abs, `${content[lang].body}\n`, "utf-8");
92
- writtenFiles.push(rel);
93
- }
94
- }
95
-
96
- // 2) Patch the version config.json (raw JSON round-trip, preserve all keys).
97
- const configRel = `${base}/config.json`;
98
- const configAbs = path.resolve(cwd, configRel);
99
- let raw: string;
100
- try {
101
- raw = await fs.readFile(configAbs, "utf-8");
102
- } catch {
103
- throw new Error(
104
- `Version config not found at ${configRel}. Run the base scaffold (\`gitpagedocs\`) first.`,
105
- );
106
- }
107
- const config = JSON.parse(raw) as Record<string, unknown>;
108
-
109
- const routesMd = Array.isArray(config["routes-md"]) ? (config["routes-md"] as Array<Record<string, unknown>>) : [];
110
- const menusMd = Array.isArray(config["menus-header-md"]) ? (config["menus-header-md"] as Array<Record<string, unknown>>) : [];
111
- const keptRoutes = routesMd.filter((route) => route?.aiGenerated !== true);
112
- const keptMenus = menusMd.filter((menu) => menu?.aiGenerated !== true);
113
-
114
- const newRoutes: Array<Record<string, unknown>> = [];
115
- const newMenus: Array<Record<string, unknown>> = [];
116
- order.forEach((slug, index) => {
117
- const content = resolve(slug);
118
- const id = AI_ROUTE_ID_BASE + index + 1;
119
- const pathByLang = {
120
- pt: `${base}/pt/${slug}.md`,
121
- en: `${base}/en/${slug}.md`,
122
- es: `${base}/es/${slug}.md`,
123
- };
124
- const titles = { pt: content.pt.title, en: content.en.title, es: content.es.title };
125
- const descriptions = { pt: "", en: "", es: "" };
126
- const route = buildMdRoute(versionId, id, pathByLang, titles, descriptions, {}) as Record<string, unknown>;
127
- route.aiGenerated = true;
128
- newRoutes.push(route);
129
- newMenus.push({
130
- id,
131
- aiGenerated: true,
132
- pt: { title: content.pt.title, "path-click": pathByLang.pt },
133
- en: { title: content.en.title, "path-click": pathByLang.en },
134
- es: { title: content.es.title, "path-click": pathByLang.es },
135
- });
136
- });
137
-
138
- config["routes-md"] = [...keptRoutes, ...newRoutes];
139
- config["menus-header-md"] = [...keptMenus, ...newMenus];
140
- await fs.writeFile(configAbs, `${JSON.stringify(config, null, 2)}\n`, "utf-8");
141
-
142
- return { configPath: configRel, slugs: order, files: writtenFiles };
143
- }
1
+ import fs from "node:fs/promises";
2
+ import path from "node:path";
3
+ // @ts-expect-error .mjs runtime module is type-less in this package.
4
+ import { buildMdRoute } from "../../builders/route-builders.mjs";
5
+ import type { AiDocPage } from "../application/docs-pattern";
6
+
7
+ const CANONICAL_LANGS = ["pt", "en", "es"] as const;
8
+ type Lang = (typeof CANONICAL_LANGS)[number];
9
+
10
+ /** AI routes/menus use a high, dedicated id range so they never clash with the
11
+ * deterministic base routes (ids 1..N) and can be identified for idempotency. */
12
+ const AI_ROUTE_ID_BASE = 1000;
13
+
14
+ export interface VersionDocsWriteInput {
15
+ cwd: string;
16
+ versionId: string;
17
+ /** Pages generated per language (only the languages the user selected). */
18
+ pagesByLang: Partial<Record<Lang, AiDocPage[]>>;
19
+ }
20
+
21
+ export interface VersionDocsWriteResult {
22
+ configPath: string;
23
+ slugs: string[];
24
+ files: string[];
25
+ }
26
+
27
+ interface LangContent {
28
+ title: string;
29
+ body: string;
30
+ }
31
+
32
+ function indexBySlug(pages: AiDocPage[] | undefined): Map<string, AiDocPage> {
33
+ const map = new Map<string, AiDocPage>();
34
+ for (const page of pages ?? []) {
35
+ if (!map.has(page.slug)) map.set(page.slug, page);
36
+ }
37
+ return map;
38
+ }
39
+
40
+ /**
41
+ * Write AI-generated pages into the gitpagedocs versioned structure and wire
42
+ * them into the version config.json (routes-md + menus-header-md). Pages are
43
+ * written for ALL three canonical languages (missing languages reuse an
44
+ * available translation) so every route path stays valid. Idempotent: any prior
45
+ * `aiGenerated` routes/menus are replaced, never duplicated. The base config and
46
+ * its deterministic routes are preserved untouched.
47
+ */
48
+ export async function writeVersionDocs(input: VersionDocsWriteInput): Promise<VersionDocsWriteResult> {
49
+ const { cwd, versionId, pagesByLang } = input;
50
+ const base = `gitpagedocs/docs/versions/${versionId}`;
51
+
52
+ const perLang: Record<Lang, Map<string, AiDocPage>> = {
53
+ pt: indexBySlug(pagesByLang.pt),
54
+ en: indexBySlug(pagesByLang.en),
55
+ es: indexBySlug(pagesByLang.es),
56
+ };
57
+
58
+ // Ordered unique slug list (prefer en order, then pt, then es).
59
+ const order: string[] = [];
60
+ const seen = new Set<string>();
61
+ for (const lang of ["en", "pt", "es"] as Lang[]) {
62
+ for (const page of pagesByLang[lang] ?? []) {
63
+ if (!seen.has(page.slug)) {
64
+ seen.add(page.slug);
65
+ order.push(page.slug);
66
+ }
67
+ }
68
+ }
69
+ if (order.length === 0) {
70
+ throw new Error("No AI pages to write.");
71
+ }
72
+
73
+ const resolve = (slug: string): Record<Lang, LangContent> => {
74
+ const fallback = CANONICAL_LANGS.map((lang) => perLang[lang].get(slug)).find(Boolean);
75
+ const out = {} as Record<Lang, LangContent>;
76
+ for (const lang of CANONICAL_LANGS) {
77
+ const page = perLang[lang].get(slug) ?? fallback!;
78
+ out[lang] = { title: page.title, body: page.body };
79
+ }
80
+ return out;
81
+ };
82
+
83
+ // 1) Write the markdown files (all 3 canonical languages).
84
+ const writtenFiles: string[] = [];
85
+ for (const slug of order) {
86
+ const content = resolve(slug);
87
+ for (const lang of CANONICAL_LANGS) {
88
+ const rel = `${base}/${lang}/${slug}.md`;
89
+ const abs = path.resolve(cwd, rel);
90
+ await fs.mkdir(path.dirname(abs), { recursive: true });
91
+ await fs.writeFile(abs, `${content[lang].body}\n`, "utf-8");
92
+ writtenFiles.push(rel);
93
+ }
94
+ }
95
+
96
+ // 2) Patch the version config.json (raw JSON round-trip, preserve all keys).
97
+ const configRel = `${base}/config.json`;
98
+ const configAbs = path.resolve(cwd, configRel);
99
+ let raw: string;
100
+ try {
101
+ raw = await fs.readFile(configAbs, "utf-8");
102
+ } catch {
103
+ throw new Error(
104
+ `Version config not found at ${configRel}. Run the base scaffold (\`gitpagedocs\`) first.`,
105
+ );
106
+ }
107
+ const config = JSON.parse(raw) as Record<string, unknown>;
108
+
109
+ const routesMd = Array.isArray(config["routes-md"]) ? (config["routes-md"] as Array<Record<string, unknown>>) : [];
110
+ const menusMd = Array.isArray(config["menus-header-md"]) ? (config["menus-header-md"] as Array<Record<string, unknown>>) : [];
111
+ const keptRoutes = routesMd.filter((route) => route?.aiGenerated !== true);
112
+ const keptMenus = menusMd.filter((menu) => menu?.aiGenerated !== true);
113
+
114
+ const newRoutes: Array<Record<string, unknown>> = [];
115
+ const newMenus: Array<Record<string, unknown>> = [];
116
+ order.forEach((slug, index) => {
117
+ const content = resolve(slug);
118
+ const id = AI_ROUTE_ID_BASE + index + 1;
119
+ const pathByLang = {
120
+ pt: `${base}/pt/${slug}.md`,
121
+ en: `${base}/en/${slug}.md`,
122
+ es: `${base}/es/${slug}.md`,
123
+ };
124
+ const titles = { pt: content.pt.title, en: content.en.title, es: content.es.title };
125
+ const descriptions = { pt: "", en: "", es: "" };
126
+ const route = buildMdRoute(versionId, id, pathByLang, titles, descriptions, {}) as Record<string, unknown>;
127
+ route.aiGenerated = true;
128
+ newRoutes.push(route);
129
+ newMenus.push({
130
+ id,
131
+ aiGenerated: true,
132
+ pt: { title: content.pt.title, "path-click": pathByLang.pt },
133
+ en: { title: content.en.title, "path-click": pathByLang.en },
134
+ es: { title: content.es.title, "path-click": pathByLang.es },
135
+ });
136
+ });
137
+
138
+ config["routes-md"] = [...keptRoutes, ...newRoutes];
139
+ config["menus-header-md"] = [...keptMenus, ...newMenus];
140
+ await fs.writeFile(configAbs, `${JSON.stringify(config, null, 2)}\n`, "utf-8");
141
+
142
+ return { configPath: configRel, slugs: order, files: writtenFiles };
143
+ }