docsui-cli 0.0.59

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 (49) hide show
  1. package/README.md +279 -0
  2. package/dist/commands/add.d.ts +5 -0
  3. package/dist/commands/add.js +254 -0
  4. package/dist/commands/doctor.d.ts +5 -0
  5. package/dist/commands/doctor.js +250 -0
  6. package/dist/commands/init.d.ts +5 -0
  7. package/dist/commands/init.js +548 -0
  8. package/dist/commands/list.d.ts +5 -0
  9. package/dist/commands/list.js +84 -0
  10. package/dist/commands/mcp.d.ts +3 -0
  11. package/dist/commands/mcp.js +1562 -0
  12. package/dist/commands/new.d.ts +5 -0
  13. package/dist/commands/new.js +113 -0
  14. package/dist/commands/remove.d.ts +5 -0
  15. package/dist/commands/remove.js +134 -0
  16. package/dist/commands/save.d.ts +5 -0
  17. package/dist/commands/save.js +60 -0
  18. package/dist/commands/update.d.ts +5 -0
  19. package/dist/commands/update.js +247 -0
  20. package/dist/index.d.ts +1 -0
  21. package/dist/index.js +88 -0
  22. package/dist/latex-to-primitives.d.ts +59 -0
  23. package/dist/latex-to-primitives.js +1019 -0
  24. package/dist/lib/component-registry.d.ts +33 -0
  25. package/dist/lib/component-registry.js +843 -0
  26. package/dist/lib/css-tokens.d.ts +8 -0
  27. package/dist/lib/css-tokens.js +294 -0
  28. package/dist/metadata.d.ts +1 -0
  29. package/dist/metadata.js +4 -0
  30. package/dist/symbol-map.d.ts +30 -0
  31. package/dist/symbol-map.js +1607 -0
  32. package/dist/utils/detect-structure.d.ts +16 -0
  33. package/dist/utils/detect-structure.js +58 -0
  34. package/dist/utils/fetch-component.d.ts +13 -0
  35. package/dist/utils/fetch-component.js +81 -0
  36. package/dist/utils/get-config.d.ts +14 -0
  37. package/dist/utils/get-config.js +19 -0
  38. package/dist/utils/install-deps.d.ts +3 -0
  39. package/dist/utils/install-deps.js +23 -0
  40. package/dist/utils/save-mdx-page.d.ts +35 -0
  41. package/dist/utils/save-mdx-page.js +44 -0
  42. package/dist/utils/scan-mdx.d.ts +20 -0
  43. package/dist/utils/scan-mdx.js +106 -0
  44. package/dist/utils/telemetry.d.ts +3 -0
  45. package/dist/utils/telemetry.js +42 -0
  46. package/dist/utils/write-component.d.ts +7 -0
  47. package/dist/utils/write-component.js +25 -0
  48. package/dist/webview-bundle.js +3478 -0
  49. package/package.json +94 -0
@@ -0,0 +1,5 @@
1
+ import { Command } from 'commander';
2
+
3
+ declare const newCommand: Command;
4
+
5
+ export { newCommand };
@@ -0,0 +1,113 @@
1
+ import { Command } from "commander";
2
+ import prompts from "prompts";
3
+ import chalk from "chalk";
4
+ import fs from "fs-extra";
5
+ import path from "path";
6
+ function slugify(title) {
7
+ return title.toLowerCase().trim().replace(/[^\w\s-]/g, "").replace(/[\s_]+/g, "-").replace(/^-+|-+$/g, "");
8
+ }
9
+ function todayIso() {
10
+ return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
11
+ }
12
+ function buildTemplate(title, description) {
13
+ return `---
14
+ title: "${title}"
15
+ description: "${description}"
16
+ date: ${todayIso()}
17
+ ---
18
+
19
+ # ${title}
20
+
21
+ <Callout>
22
+ Write your introduction here.
23
+ </Callout>
24
+
25
+ ## Overview
26
+
27
+ Your content goes here.
28
+
29
+ ## Key Concepts
30
+
31
+ <Definition term="Term">
32
+ Define your key terms here using the Definition component.
33
+ </Definition>
34
+
35
+ ## Summary
36
+
37
+ <Callout variant="success">
38
+ Summarize what the reader has learned.
39
+ </Callout>
40
+ `;
41
+ }
42
+ const newCommand = new Command().name("new").description("Scaffold a new blank .mdx page with starter components").argument("[title]", "page title (will be slugified for the filename)").option("-o, --out <dir>", "output directory").option(
43
+ "-p, --path <segments...>",
44
+ "optional sub-path segments placed between --out and the filename"
45
+ ).action(
46
+ async (titleArg, opts) => {
47
+ console.log();
48
+ let title = titleArg;
49
+ if (!title) {
50
+ const res = await prompts({
51
+ type: "text",
52
+ name: "title",
53
+ message: "Page title",
54
+ validate: (v) => v.trim() ? true : "Title cannot be empty"
55
+ });
56
+ if (!res.title) process.exit(0);
57
+ title = res.title;
58
+ }
59
+ let outDir = opts.out;
60
+ if (!outDir) {
61
+ const res = await prompts({
62
+ type: "text",
63
+ name: "out",
64
+ message: "Output directory",
65
+ initial: "content"
66
+ });
67
+ if (res.out === void 0) process.exit(0);
68
+ outDir = res.out || "content";
69
+ }
70
+ const { description } = await prompts({
71
+ type: "text",
72
+ name: "description",
73
+ message: "Short description (optional)",
74
+ initial: ""
75
+ });
76
+ const slug = slugify(title);
77
+ const fileName = `${slug}.mdx`;
78
+ const segments = opts.path ?? [];
79
+ const cwd = process.cwd();
80
+ const absoluteOut = path.isAbsolute(outDir) ? outDir : path.join(cwd, outDir);
81
+ const targetDir = path.join(absoluteOut, ...segments);
82
+ const filePath = path.join(targetDir, fileName);
83
+ const relativePath = path.relative(cwd, filePath);
84
+ if (await fs.pathExists(filePath)) {
85
+ const { overwrite } = await prompts({
86
+ type: "confirm",
87
+ name: "overwrite",
88
+ message: `${relativePath} already exists. Overwrite?`,
89
+ initial: false
90
+ });
91
+ if (!overwrite) {
92
+ console.log(chalk.yellow("Cancelled."));
93
+ process.exit(0);
94
+ }
95
+ }
96
+ await fs.ensureDir(targetDir);
97
+ await fs.writeFile(
98
+ filePath,
99
+ buildTemplate(title, description || title),
100
+ "utf-8"
101
+ );
102
+ console.log();
103
+ console.log(` ${chalk.green("\u2713")} ${chalk.bold(relativePath)}`);
104
+ console.log();
105
+ console.log(
106
+ chalk.dim(" Open the file and replace the placeholder content.")
107
+ );
108
+ console.log();
109
+ }
110
+ );
111
+ export {
112
+ newCommand
113
+ };
@@ -0,0 +1,5 @@
1
+ import { Command } from 'commander';
2
+
3
+ declare const remove: Command;
4
+
5
+ export { remove };
@@ -0,0 +1,134 @@
1
+ import { Command } from "commander";
2
+ import prompts from "prompts";
3
+ import chalk from "chalk";
4
+ import fs from "fs-extra";
5
+ import path from "path";
6
+ import { getConfig } from "../utils/get-config.js";
7
+ import {
8
+ COMPONENT_MDX_MAP,
9
+ COMPONENT_FILES
10
+ } from "../lib/component-registry.js";
11
+ async function unpatchMdxComponents(componentName, componentsDir, cwd) {
12
+ const mapping = COMPONENT_MDX_MAP[componentName];
13
+ if (!mapping) return;
14
+ const mdxPath = path.join(cwd, componentsDir, "mdx-components.tsx");
15
+ if (!await fs.pathExists(mdxPath)) return;
16
+ let content = await fs.readFile(mdxPath, "utf-8");
17
+ const lines = content.split("\n");
18
+ content = lines.filter((line) => !line.includes(`from "${mapping.importFile}"`)).join("\n");
19
+ for (const [element, component] of Object.entries(mapping.elementMappings)) {
20
+ content = content.replace(
21
+ new RegExp(`
22
+ [ ]+${element}:\\s*${component},`, "g"),
23
+ ""
24
+ );
25
+ }
26
+ for (const exportName of mapping.imports) {
27
+ const alreadyMapped = Object.values(mapping.elementMappings).includes(
28
+ exportName
29
+ );
30
+ if (!alreadyMapped) {
31
+ content = content.replace(new RegExp(`
32
+ [ ]+${exportName},`, "g"), "");
33
+ }
34
+ }
35
+ await fs.writeFile(mdxPath, content, "utf-8");
36
+ }
37
+ async function discoverInstalled(componentsDir, cwd) {
38
+ const dir = path.join(cwd, componentsDir);
39
+ if (!await fs.pathExists(dir)) return [];
40
+ const files = await fs.readdir(dir);
41
+ const installed = [];
42
+ for (const [name, componentFiles] of Object.entries(COMPONENT_FILES)) {
43
+ const ownFiles = componentFiles.filter((f) => !f.startsWith("lib/"));
44
+ if (ownFiles.length > 0 && ownFiles.every((f) => files.includes(f)))
45
+ installed.push(name);
46
+ }
47
+ if (files.includes("mdx-components.tsx")) installed.push("mdx-components");
48
+ const libDir = componentsDir.startsWith("src/") ? "src/lib" : "lib";
49
+ if (await fs.pathExists(path.join(cwd, libDir, "utils.ts")))
50
+ installed.push("utils");
51
+ return [...new Set(installed)];
52
+ }
53
+ const remove = new Command().name("remove").description("Remove installed components from your project").argument("[components...]", "components to remove").action(async (components) => {
54
+ console.log();
55
+ const config = await getConfig();
56
+ if (!config) {
57
+ console.log(chalk.red("\u2717 No docsui.json found."));
58
+ console.log(chalk.yellow(" Run: npx docsui-cli@latest init\n"));
59
+ process.exit(1);
60
+ }
61
+ const cwd = process.cwd();
62
+ if (components.length === 0) {
63
+ const installed = await discoverInstalled(config.componentsDir, cwd);
64
+ if (installed.length === 0) {
65
+ console.log(chalk.yellow("No installed components found.\n"));
66
+ process.exit(0);
67
+ }
68
+ const { selected } = await prompts({
69
+ type: "multiselect",
70
+ name: "selected",
71
+ message: "Which components would you like to remove?",
72
+ choices: installed.map((name) => ({ title: name, value: name }))
73
+ });
74
+ if (!selected || selected.length === 0) {
75
+ console.log(chalk.yellow("Nothing selected.\n"));
76
+ process.exit(0);
77
+ }
78
+ components = selected;
79
+ }
80
+ const { confirmed } = await prompts({
81
+ type: "confirm",
82
+ name: "confirmed",
83
+ message: `Remove ${components.length} component${components.length !== 1 ? "s" : ""}? (${components.join(", ")})`,
84
+ initial: false
85
+ });
86
+ if (!confirmed) {
87
+ console.log(chalk.yellow("\nCancelled.\n"));
88
+ process.exit(0);
89
+ }
90
+ console.log();
91
+ const removed = [];
92
+ const notFound = [];
93
+ for (const name of components) {
94
+ const files = name === "mdx-components" ? ["mdx-components.tsx"] : COMPONENT_FILES[name];
95
+ if (!files) {
96
+ notFound.push(name);
97
+ continue;
98
+ }
99
+ let deleted = false;
100
+ const libRoot = config.componentsDir.startsWith("src/") ? path.join(cwd, "src") : cwd;
101
+ for (const file of files) {
102
+ const filePath = file.startsWith("lib/") ? path.join(libRoot, file) : path.join(cwd, config.componentsDir, file);
103
+ if (await fs.pathExists(filePath)) {
104
+ await fs.remove(filePath);
105
+ deleted = true;
106
+ }
107
+ }
108
+ await unpatchMdxComponents(name, config.componentsDir, cwd);
109
+ if (deleted) {
110
+ removed.push(name);
111
+ console.log(chalk.green(` \u2713 removed ${name}`));
112
+ } else {
113
+ notFound.push(name);
114
+ console.log(chalk.dim(` \u2013 ${name} (not installed)`));
115
+ }
116
+ }
117
+ console.log();
118
+ if (removed.length > 0) {
119
+ console.log(
120
+ chalk.bold(
121
+ `Removed ${removed.length} component${removed.length !== 1 ? "s" : ""}.`
122
+ )
123
+ );
124
+ }
125
+ if (notFound.length > 0) {
126
+ console.log(
127
+ chalk.yellow(`${notFound.length} not found: ${notFound.join(", ")}`)
128
+ );
129
+ }
130
+ console.log();
131
+ });
132
+ export {
133
+ remove
134
+ };
@@ -0,0 +1,5 @@
1
+ import { Command } from 'commander';
2
+
3
+ declare const save: Command;
4
+
5
+ export { save };
@@ -0,0 +1,60 @@
1
+ import { Command } from "commander";
2
+ import chalk from "chalk";
3
+ import ora from "ora";
4
+ import fs from "fs-extra";
5
+ import { saveMdxPage } from "../utils/save-mdx-page.js";
6
+ const save = new Command().name("save").description("Save an MDX string to a structured file path").requiredOption("-o, --out <dir>", "root output folder (e.g. content, docs)").requiredOption(
7
+ "-p, --path <segments...>",
8
+ "ordered path segments \u2014 all but the last become folders, last becomes filename"
9
+ ).option("-f, --file <file>", "read MDX content from a file instead of stdin").action(async (opts) => {
10
+ console.log();
11
+ let content;
12
+ if (opts.file) {
13
+ if (!await fs.pathExists(opts.file)) {
14
+ console.log(chalk.red(`\u2717 File not found: ${opts.file}`));
15
+ process.exit(1);
16
+ }
17
+ content = await fs.readFile(opts.file, "utf-8");
18
+ } else if (!process.stdin.isTTY) {
19
+ const chunks = [];
20
+ for await (const chunk of process.stdin) chunks.push(chunk);
21
+ content = Buffer.concat(chunks).toString("utf-8");
22
+ } else {
23
+ console.log(
24
+ chalk.red("\u2717 Provide MDX via --file or pipe it through stdin")
25
+ );
26
+ console.log();
27
+ console.log(chalk.dim("Examples:"));
28
+ console.log(
29
+ chalk.dim(
30
+ " docsui save --out content --path 2025 ds bst intro --file page.mdx"
31
+ )
32
+ );
33
+ console.log(
34
+ chalk.dim(
35
+ " echo '<Callout>Hello</Callout>' | docsui save --out content --path 2025 ds bst intro"
36
+ )
37
+ );
38
+ process.exit(1);
39
+ }
40
+ const spinner = ora("Writing MDX file\u2026").start();
41
+ try {
42
+ const result = await saveMdxPage({
43
+ content,
44
+ outDir: opts.out,
45
+ path: opts.path
46
+ });
47
+ spinner.succeed("MDX file saved");
48
+ console.log();
49
+ console.log(` ${chalk.green("\u2713")} ${chalk.bold(result.relativePath)}`);
50
+ console.log();
51
+ } catch (error) {
52
+ spinner.fail("Failed to save MDX file");
53
+ const msg = error instanceof Error ? error.message : String(error);
54
+ console.error(chalk.red(msg));
55
+ process.exit(1);
56
+ }
57
+ });
58
+ export {
59
+ save
60
+ };
@@ -0,0 +1,5 @@
1
+ import { Command } from 'commander';
2
+
3
+ declare const update: Command;
4
+
5
+ export { update };
@@ -0,0 +1,247 @@
1
+ import { Command } from "commander";
2
+ import prompts from "prompts";
3
+ import chalk from "chalk";
4
+ import ora from "ora";
5
+ import fs from "fs-extra";
6
+ import path from "path";
7
+ import { getConfig } from "../utils/get-config.js";
8
+ import {
9
+ fetchComponent
10
+ } from "../utils/fetch-component.js";
11
+ import { installDependencies } from "../utils/install-deps.js";
12
+ import { writeComponent } from "../utils/write-component.js";
13
+ import {
14
+ FILE_TO_COMPONENT,
15
+ COMPONENT_MDX_MAP
16
+ } from "../lib/component-registry.js";
17
+ async function patchMdxComponents(componentName, componentsDir, cwd) {
18
+ const mapping = COMPONENT_MDX_MAP[componentName];
19
+ if (!mapping) return;
20
+ if (mapping.imports.length === 0 && Object.keys(mapping.elementMappings).length === 0)
21
+ return;
22
+ let mdxPath = path.join(cwd, componentsDir, "mdx-components.tsx");
23
+ if (!await fs.pathExists(mdxPath)) {
24
+ const jsxPath = path.join(cwd, componentsDir, "mdx-components.jsx");
25
+ if (await fs.pathExists(jsxPath)) mdxPath = jsxPath;
26
+ else return;
27
+ }
28
+ let content = await fs.readFile(mdxPath, "utf-8");
29
+ if (!content.includes(mapping.importFile)) {
30
+ const importLine = `import { ${mapping.imports.join(", ")} } from "${mapping.importFile}"
31
+ `;
32
+ const exportIdx = content.indexOf("export const mdxComponents");
33
+ content = exportIdx !== -1 ? content.slice(0, exportIdx) + importLine + content.slice(exportIdx) : importLine + content;
34
+ }
35
+ const ANCHOR = "export const mdxComponents";
36
+ const anchorIdx = content.indexOf(ANCHOR);
37
+ const openBrace = anchorIdx !== -1 ? content.indexOf("{", anchorIdx) : -1;
38
+ let closeIdx = -1;
39
+ if (openBrace !== -1) {
40
+ let depth = 0;
41
+ for (let i = openBrace; i < content.length; i++) {
42
+ if (content[i] === "{") depth++;
43
+ else if (content[i] === "}") {
44
+ depth--;
45
+ if (depth === 0) {
46
+ closeIdx = i;
47
+ break;
48
+ }
49
+ }
50
+ }
51
+ }
52
+ const objectBody = openBrace !== -1 && closeIdx !== -1 ? content.slice(openBrace + 1, closeIdx) : "";
53
+ const additions = [];
54
+ for (const [element, component] of Object.entries(mapping.elementMappings)) {
55
+ if (!objectBody.includes(`${element}:`) && !objectBody.includes(`${element} :`))
56
+ additions.push(` ${element}: ${component},`);
57
+ }
58
+ for (const exportName of mapping.imports) {
59
+ const alreadyMapped = Object.values(mapping.elementMappings).includes(
60
+ exportName
61
+ );
62
+ if (!alreadyMapped && !objectBody.includes(`${exportName},`) && !objectBody.includes(`${exportName}:`))
63
+ additions.push(` ${exportName},`);
64
+ }
65
+ if (additions.length > 0 && closeIdx !== -1) {
66
+ content = content.slice(0, closeIdx) + additions.join("\n") + "\n" + content.slice(closeIdx);
67
+ }
68
+ await fs.writeFile(mdxPath, content);
69
+ }
70
+ async function diffComponent(data, config, cwd) {
71
+ const changedFiles = [];
72
+ const framework = config.framework ?? "unknown";
73
+ for (const file of data.files) {
74
+ const libRoot = config.componentsDir.startsWith("src/") ? path.join(cwd, "src") : cwd;
75
+ const filePath = file.path.startsWith("lib/") ? path.join(libRoot, file.path) : path.join(cwd, config.componentsDir, file.path);
76
+ if (!await fs.pathExists(filePath)) {
77
+ changedFiles.push(file.path);
78
+ continue;
79
+ }
80
+ const existing = await fs.readFile(filePath, "utf-8");
81
+ let incoming = file.content;
82
+ if (framework === "react") {
83
+ incoming = incoming.replace(/^["']use client["']\n\n?/m, "");
84
+ }
85
+ if (existing.trim() !== incoming.trim()) {
86
+ changedFiles.push(file.path);
87
+ }
88
+ }
89
+ return {
90
+ name: data.name,
91
+ data,
92
+ changedFiles,
93
+ hasChanges: changedFiles.length > 0
94
+ };
95
+ }
96
+ async function discoverInstalled(componentsDir, cwd) {
97
+ const dir = path.join(cwd, componentsDir);
98
+ if (!await fs.pathExists(dir)) return [];
99
+ const files = await fs.readdir(dir);
100
+ const found = files.map((f) => FILE_TO_COMPONENT[f]).filter((n) => !!n);
101
+ const libDir = componentsDir.startsWith("src/") ? "src/lib" : "lib";
102
+ if (await fs.pathExists(path.join(cwd, libDir, "utils.ts"))) {
103
+ found.unshift("utils");
104
+ }
105
+ return [...new Set(found)];
106
+ }
107
+ const update = new Command().name("update").description("Update installed components to their latest versions").argument(
108
+ "[components...]",
109
+ "components to update (omit to update all installed)"
110
+ ).action(async (targets) => {
111
+ console.log();
112
+ const config = await getConfig();
113
+ if (!config) {
114
+ console.log(chalk.red("\u2717 No docsui.json found."));
115
+ console.log(chalk.yellow(" Run: npx docsui-cli@latest init\n"));
116
+ process.exit(1);
117
+ }
118
+ const cwd = process.cwd();
119
+ let toUpdate;
120
+ if (targets.length > 0) {
121
+ toUpdate = targets;
122
+ } else {
123
+ toUpdate = await discoverInstalled(config.componentsDir, cwd);
124
+ if (toUpdate.length === 0) {
125
+ console.log(chalk.yellow("No installed components found."));
126
+ console.log(
127
+ chalk.dim(" Run: npx docsui-cli@latest add <component>\n")
128
+ );
129
+ process.exit(0);
130
+ }
131
+ }
132
+ const spinner = ora("Checking for updates...").start();
133
+ try {
134
+ const componentsData = [];
135
+ const processed = /* @__PURE__ */ new Set();
136
+ async function fetchRecursive(name) {
137
+ if (processed.has(name)) return;
138
+ processed.add(name);
139
+ const data = await fetchComponent(name);
140
+ if (data.registryDependencies?.length) {
141
+ for (const dep of data.registryDependencies) {
142
+ await fetchRecursive(dep);
143
+ }
144
+ }
145
+ componentsData.push(data);
146
+ }
147
+ for (const name of toUpdate) {
148
+ await fetchRecursive(name);
149
+ }
150
+ const diffs = await Promise.all(
151
+ componentsData.map((data) => diffComponent(data, config, cwd))
152
+ );
153
+ spinner.stop();
154
+ console.log();
155
+ const maxLen = Math.max(...diffs.map((d) => d.name.length));
156
+ for (const diff of diffs) {
157
+ const name = diff.name.padEnd(maxLen);
158
+ if (diff.hasChanges) {
159
+ console.log(
160
+ ` ${chalk.yellow("~")} ${name} ${chalk.dim(diff.changedFiles.join(", "))}`
161
+ );
162
+ } else {
163
+ console.log(
164
+ ` ${chalk.green("\u2713")} ${name} ${chalk.dim("up to date")}`
165
+ );
166
+ }
167
+ }
168
+ console.log();
169
+ const changed = diffs.filter((d) => d.hasChanges);
170
+ if (changed.length === 0) {
171
+ console.log(chalk.green("All components are up to date."));
172
+ console.log();
173
+ process.exit(0);
174
+ }
175
+ console.log(
176
+ chalk.bold(
177
+ `${changed.length} component${changed.length !== 1 ? "s have" : " has"} updates.`
178
+ )
179
+ );
180
+ console.log();
181
+ const { strategy } = await prompts({
182
+ type: "select",
183
+ name: "strategy",
184
+ message: "How would you like to proceed?",
185
+ choices: [
186
+ {
187
+ title: `Overwrite all ${chalk.dim(`(${changed.length} component${changed.length !== 1 ? "s" : ""})`)}`,
188
+ value: "all"
189
+ },
190
+ { title: "Skip all", value: "skip" },
191
+ { title: "Choose which to update", value: "pick" }
192
+ ]
193
+ });
194
+ if (!strategy || strategy === "skip") {
195
+ console.log(chalk.yellow("\nSkipped. No files written.\n"));
196
+ process.exit(0);
197
+ }
198
+ let toWrite = [];
199
+ if (strategy === "all") {
200
+ toWrite = changed;
201
+ } else {
202
+ const { selected } = await prompts({
203
+ type: "multiselect",
204
+ name: "selected",
205
+ message: "Select components to update",
206
+ choices: changed.map((d) => ({
207
+ title: d.name,
208
+ value: d.name,
209
+ description: d.changedFiles.join(", "),
210
+ selected: true
211
+ }))
212
+ });
213
+ if (!selected || selected.length === 0) {
214
+ console.log(chalk.yellow("\nNothing selected. No files written.\n"));
215
+ process.exit(0);
216
+ }
217
+ toWrite = changed.filter((d) => selected.includes(d.name));
218
+ }
219
+ console.log();
220
+ const writeSpinner = ora("Installing dependencies...").start();
221
+ const allDeps = /* @__PURE__ */ new Set();
222
+ for (const diff of toWrite) {
223
+ diff.data.dependencies?.forEach((d) => allDeps.add(d));
224
+ }
225
+ if (allDeps.size > 0) await installDependencies(Array.from(allDeps));
226
+ writeSpinner.text = "Writing updated components...";
227
+ for (const diff of toWrite) {
228
+ await writeComponent(diff.data, config);
229
+ await patchMdxComponents(diff.name, config.componentsDir, cwd);
230
+ }
231
+ writeSpinner.succeed("Done!");
232
+ console.log();
233
+ for (const diff of toWrite) {
234
+ console.log(chalk.green(` \u2713 ${diff.name}`));
235
+ }
236
+ console.log();
237
+ } catch (error) {
238
+ spinner.fail("Update failed");
239
+ const msg = error instanceof Error ? error.message : String(error);
240
+ console.error(chalk.red(` ${msg}
241
+ `));
242
+ process.exit(1);
243
+ }
244
+ });
245
+ export {
246
+ update
247
+ };
@@ -0,0 +1 @@
1
+ #!/usr/bin/env node
package/dist/index.js ADDED
@@ -0,0 +1,88 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from "commander";
3
+ import { readFileSync } from "fs";
4
+ import { fileURLToPath } from "url";
5
+ import { dirname, join } from "path";
6
+ import prompts from "prompts";
7
+ import { add } from "./commands/add.js";
8
+ import { init } from "./commands/init.js";
9
+ import { list } from "./commands/list.js";
10
+ import { update } from "./commands/update.js";
11
+ import { remove } from "./commands/remove.js";
12
+ import { doctor } from "./commands/doctor.js";
13
+ import { save } from "./commands/save.js";
14
+ import { newCommand } from "./commands/new.js";
15
+ import { startMcpServer } from "./commands/mcp.js";
16
+ const __filename = fileURLToPath(import.meta.url);
17
+ const __dirname = dirname(__filename);
18
+ const packageJson = JSON.parse(
19
+ readFileSync(join(__dirname, "..", "package.json"), "utf-8")
20
+ );
21
+ process.on("SIGINT", () => process.exit(0));
22
+ process.on("SIGTERM", () => process.exit(0));
23
+ async function main() {
24
+ if (process.argv[2] === "mcp") {
25
+ await startMcpServer();
26
+ return;
27
+ }
28
+ const program = new Command().name("docsui").description("Add beautiful MDX components to your project").version(
29
+ packageJson.version || "0.0.1",
30
+ "-v, --version",
31
+ "display the version number"
32
+ );
33
+ program.addCommand(init).addCommand(add).addCommand(list).addCommand(update).addCommand(remove).addCommand(doctor).addCommand(save).addCommand(newCommand);
34
+ if (process.argv.length <= 2) {
35
+ console.log();
36
+ const { action } = await prompts({
37
+ type: "select",
38
+ name: "action",
39
+ message: "What would you like to do?",
40
+ choices: [
41
+ {
42
+ title: "Add components",
43
+ value: "add",
44
+ description: "Add MDX components to your project"
45
+ },
46
+ {
47
+ title: "Update components",
48
+ value: "update",
49
+ description: "Update installed components to latest"
50
+ },
51
+ {
52
+ title: "Initialize project",
53
+ value: "init",
54
+ description: "Set up docsui in your project"
55
+ },
56
+ {
57
+ title: "Remove components",
58
+ value: "remove",
59
+ description: "Remove installed components from your project"
60
+ },
61
+ {
62
+ title: "List components",
63
+ value: "list",
64
+ description: "Show all available components"
65
+ },
66
+ {
67
+ title: "Doctor",
68
+ value: "doctor",
69
+ description: "Check project health \u2014 missing deps, broken imports"
70
+ },
71
+ {
72
+ title: "Save MDX",
73
+ value: "save",
74
+ description: "Save an MDX string to a structured .ai.mdx file"
75
+ },
76
+ {
77
+ title: "New page",
78
+ value: "new",
79
+ description: "Scaffold a new blank .mdx page with starter components"
80
+ }
81
+ ]
82
+ });
83
+ if (!action) process.exit(0);
84
+ process.argv.push(action);
85
+ }
86
+ program.parse();
87
+ }
88
+ main();