@baby-ui/cli 0.0.0-stage → 0.1.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 (44) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +36 -2
  3. package/bin.mjs +20 -0
  4. package/dist/add-Dw_xdBjM.js +8472 -0
  5. package/dist/add-Dw_xdBjM.js.map +1 -0
  6. package/dist/auth-Cqd8NPiR.js +52 -0
  7. package/dist/auth-Cqd8NPiR.js.map +1 -0
  8. package/dist/auth-DLL_PGWB.js +41 -0
  9. package/dist/auth-DLL_PGWB.js.map +1 -0
  10. package/dist/banner-b_aKYU5F.js +23 -0
  11. package/dist/banner-b_aKYU5F.js.map +1 -0
  12. package/dist/core-Cd391zXy.js +142 -0
  13. package/dist/core-Cd391zXy.js.map +1 -0
  14. package/dist/dist-Bs-3vZ2T.js +2712 -0
  15. package/dist/dist-Bs-3vZ2T.js.map +1 -0
  16. package/dist/dist-CxDndWiZ.js +6661 -0
  17. package/dist/dist-CxDndWiZ.js.map +1 -0
  18. package/dist/errors-zXXytRXF.js +16 -0
  19. package/dist/errors-zXXytRXF.js.map +1 -0
  20. package/dist/history-l3B-mc6n.js +55 -0
  21. package/dist/history-l3B-mc6n.js.map +1 -0
  22. package/dist/index.js +3097 -0
  23. package/dist/index.js.map +1 -0
  24. package/dist/info-mS7KbPJ_.js +43 -0
  25. package/dist/info-mS7KbPJ_.js.map +1 -0
  26. package/dist/init-DO1txT-A.js +168 -0
  27. package/dist/init-DO1txT-A.js.map +1 -0
  28. package/dist/list-DnQNQUNr.js +48 -0
  29. package/dist/list-DnQNQUNr.js.map +1 -0
  30. package/dist/maintain-DeyqYm5K.js +183 -0
  31. package/dist/maintain-DeyqYm5K.js.map +1 -0
  32. package/dist/schemas-DwMX1h2B.js +5160 -0
  33. package/dist/schemas-DwMX1h2B.js.map +1 -0
  34. package/dist/shared-BJaaV-dl.js +96 -0
  35. package/dist/shared-BJaaV-dl.js.map +1 -0
  36. package/dist/state-CsT6LJsH.js +430 -0
  37. package/dist/state-CsT6LJsH.js.map +1 -0
  38. package/dist/targets-Bpv2h7C4.js +316 -0
  39. package/dist/targets-Bpv2h7C4.js.map +1 -0
  40. package/dist/tx-DBnjY8eR.js +226 -0
  41. package/dist/tx-DBnjY8eR.js.map +1 -0
  42. package/dist/ui-Cthxlfe6.js +206 -0
  43. package/dist/ui-Cthxlfe6.js.map +1 -0
  44. package/package.json +50 -3
@@ -0,0 +1,168 @@
1
+ import { a as parseComponentsConfig, i as targetAt, n as findWorkspace, t as discoverTargets } from "./targets-Bpv2h7C4.js";
2
+ import { t as CliError } from "./errors-zXXytRXF.js";
3
+ import { u as c } from "./core-Cd391zXy.js";
4
+ import { _ as installConfig, u as BABY_UI_ORIGIN, v as resolveAlias } from "./state-CsT6LJsH.js";
5
+ import { l as text, n as intro, o as outro, r as message } from "./ui-Cthxlfe6.js";
6
+ import { n as selectTargets } from "./shared-BJaaV-dl.js";
7
+ import { installInto } from "./add-Dw_xdBjM.js";
8
+ import { existsSync } from "node:fs";
9
+ import { join } from "node:path";
10
+ //#region src/commands/init.ts
11
+ const CSS_CANDIDATES = {
12
+ react: [
13
+ "src/app/globals.css",
14
+ "app/globals.css",
15
+ "src/index.css",
16
+ "src/styles/globals.css",
17
+ "styles/globals.css",
18
+ "app/app.css"
19
+ ],
20
+ svelte: [
21
+ "src/app.css",
22
+ "src/routes/layout.css",
23
+ "src/styles/app.css",
24
+ "src/index.css"
25
+ ]
26
+ };
27
+ const REACT_UTILS = `import { type ClassValue, clsx } from "clsx";
28
+ import { twMerge } from "tailwind-merge";
29
+
30
+ export function cn(...inputs: ClassValue[]) {
31
+ return twMerge(clsx(inputs));
32
+ }
33
+ `;
34
+ const JS_UTILS = `import { clsx } from "clsx";
35
+ import { twMerge } from "tailwind-merge";
36
+
37
+ export function cn(...inputs) {
38
+ return twMerge(clsx(inputs));
39
+ }
40
+ `;
41
+ const SVELTE_UTILS = `${REACT_UTILS}
42
+ export type WithoutChild<T> = T extends { child?: unknown } ? Omit<T, "child"> : T;
43
+ export type WithoutChildren<T> = T extends { children?: unknown } ? Omit<T, "children"> : T;
44
+ export type WithoutChildrenOrChild<T> = WithoutChildren<WithoutChild<T>>;
45
+ export type WithElementRef<T, U extends HTMLElement = HTMLElement> = T & { ref?: U | null };
46
+ `;
47
+ async function pickTarget(options) {
48
+ const workspace = await findWorkspace(options.cwd);
49
+ const all = await discoverTargets(workspace);
50
+ const here = targetAt(all, options.cwd);
51
+ if (here && !options.target?.length) return here;
52
+ const pool = options.target?.length ? all : all.filter((t) => !t.config);
53
+ const [picked] = await selectTargets(pool.length ? pool : all, options.cwd, options);
54
+ if (!picked) throw new CliError("No project selected.");
55
+ return picked;
56
+ }
57
+ function reactConfig(target, css) {
58
+ const alias = target.aliases.find((a) => a.prefix === "@/") ?? target.aliases.find((a) => !a.withExtension);
59
+ if (!alias) throw new CliError("No import alias found for React components.", { hint: "Add `\"paths\": { \"@/*\": [\"./src/*\"] }` to tsconfig.json compilerOptions." });
60
+ const p = alias.prefix.replace(/\/$/, "");
61
+ const app = ["app", join("src", "app")].some((d) => existsSync(join(target.root, d)));
62
+ return {
63
+ $schema: "https://ui.shadcn.com/schema.json",
64
+ style: "new-york",
65
+ rsc: target.meta === "next" && app,
66
+ tsx: existsSync(join(target.root, "tsconfig.json")),
67
+ tailwind: {
68
+ config: "",
69
+ css,
70
+ baseColor: "neutral",
71
+ cssVariables: true,
72
+ prefix: ""
73
+ },
74
+ iconLibrary: "lucide",
75
+ aliases: {
76
+ components: `${p}/components`,
77
+ utils: `${p}/lib/utils`,
78
+ ui: `${p}/components/ui`,
79
+ lib: `${p}/lib`,
80
+ hooks: `${p}/hooks`
81
+ },
82
+ registries: {
83
+ "@baby-ui": `${BABY_UI_ORIGIN}/r/{name}.json`,
84
+ "@baby-ui-pro": {
85
+ url: `${BABY_UI_ORIGIN}/pro/r/{name}.json`,
86
+ headers: { Authorization: "Bearer ${BABY_UI_TOKEN}" }
87
+ }
88
+ }
89
+ };
90
+ }
91
+ function svelteConfig(target, css) {
92
+ const lib = target.aliases.some((a) => a.prefix === "#lib/") ? "#lib" : "$lib";
93
+ return {
94
+ $schema: "https://shadcn-svelte.com/schema.json",
95
+ tailwind: {
96
+ css,
97
+ baseColor: "neutral"
98
+ },
99
+ aliases: {
100
+ components: `${lib}/components`,
101
+ utils: `${lib}/utils`,
102
+ ui: `${lib}/components/ui`,
103
+ hooks: `${lib}/hooks`,
104
+ lib
105
+ },
106
+ typescript: existsSync(join(target.root, "tsconfig.json")),
107
+ registry: "https://shadcn-svelte.com/registry"
108
+ };
109
+ }
110
+ async function init(options, version) {
111
+ const { printBanner } = await import("./banner-b_aKYU5F.js");
112
+ printBanner(version);
113
+ const target = await pickTarget(options);
114
+ const framework = target.framework;
115
+ if (!framework) throw new CliError(`${target.path} is not a React or Svelte project.`);
116
+ intro(`baby-ui init ${c.dim(`${target.path} (${framework}, ${target.meta ?? "unknown"})`)}`);
117
+ if (target.config && !options.force) {
118
+ message(`components.json already exists; installing the theme only. ${c.dim("--force rewrites it")}`);
119
+ if (options.base !== false) await installInto(target, {
120
+ ...options,
121
+ items: ["theme"],
122
+ command: "init (theme)"
123
+ });
124
+ outro("Done");
125
+ return;
126
+ }
127
+ const found = CSS_CANDIDATES[framework].find((p) => existsSync(join(target.root, p)));
128
+ const css = options.css ?? await text({
129
+ message: "Where is your global CSS file?",
130
+ defaultValue: found ?? CSS_CANDIDATES[framework][0],
131
+ placeholder: found ?? CSS_CANDIDATES[framework][0]
132
+ });
133
+ const raw = framework === "react" ? reactConfig(target, css) : svelteConfig(target, css);
134
+ const project = {
135
+ ...target,
136
+ config: parseComponentsConfig(raw)
137
+ };
138
+ const cfg = installConfig(project);
139
+ const base = options.base !== false;
140
+ if (!target.dependencies.has("tailwindcss")) message(c.yellow("Tailwind CSS v4 is not installed; components need it."));
141
+ const ext = cfg.typescript ? ".ts" : ".js";
142
+ const utils = `${resolveAlias(cfg.aliases.utils, project) ?? cfg.paths.utils}${ext}`;
143
+ const preOps = [{
144
+ path: join(target.root, "components.json"),
145
+ content: `${JSON.stringify(raw, null, 2)}\n`
146
+ }];
147
+ if (!existsSync(utils)) {
148
+ const content = !cfg.typescript ? JS_UTILS : framework === "svelte" ? SVELTE_UTILS : REACT_UTILS;
149
+ preOps.push({
150
+ path: utils,
151
+ content
152
+ });
153
+ }
154
+ await installInto(project, {
155
+ ...options,
156
+ items: base ? ["theme"] : [],
157
+ command: "init"
158
+ }, {
159
+ preOps,
160
+ dependencies: ["clsx", "tailwind-merge"],
161
+ cssSource: "@import \"tailwindcss\";\n"
162
+ });
163
+ outro(`Ready. Add components with ${c.brand("baby-ui add button")}`);
164
+ }
165
+ //#endregion
166
+ export { init };
167
+
168
+ //# sourceMappingURL=init-DO1txT-A.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init-DO1txT-A.js","names":[],"sources":["../src/commands/init.ts"],"sourcesContent":["import { existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { CliError } from \"../errors.ts\";\nimport { c } from \"../logger.ts\";\nimport { parseComponentsConfig } from \"../project/config.ts\";\nimport type { Json } from \"../project/fs.ts\";\nimport { installConfig, resolveAlias } from \"../project/paths.ts\";\nimport { selectTargets } from \"../project/select.ts\";\nimport {\n\tdiscoverTargets,\n\tfindWorkspace,\n\ttype Target,\n\ttargetAt,\n} from \"../project/targets.ts\";\nimport { BABY_UI_ORIGIN } from \"../registry/resolve.ts\";\nimport { intro, message, outro, text } from \"../ui/index.ts\";\nimport type { FileOp } from \"../write/tx.ts\";\nimport { installInto } from \"./add.ts\";\nimport type { CommonOptions } from \"./shared.ts\";\n\nexport interface InitOptions extends CommonOptions {\n\treadonly css?: string;\n\treadonly base?: boolean;\n\treadonly install?: boolean;\n\treadonly dryRun?: boolean;\n\treadonly force?: boolean;\n}\n\nconst CSS_CANDIDATES = {\n\treact: [\n\t\t\"src/app/globals.css\",\n\t\t\"app/globals.css\",\n\t\t\"src/index.css\",\n\t\t\"src/styles/globals.css\",\n\t\t\"styles/globals.css\",\n\t\t\"app/app.css\",\n\t],\n\tsvelte: [\"src/app.css\", \"src/routes/layout.css\", \"src/styles/app.css\", \"src/index.css\"],\n} as const;\n\nconst REACT_UTILS = `import { type ClassValue, clsx } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n\treturn twMerge(clsx(inputs));\n}\n`;\n\nconst JS_UTILS = `import { clsx } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs) {\n\treturn twMerge(clsx(inputs));\n}\n`;\n\n// shadcn-svelte components import these helper types from utils as well as cn.\nconst SVELTE_UTILS = `${REACT_UTILS}\nexport type WithoutChild<T> = T extends { child?: unknown } ? Omit<T, \"child\"> : T;\nexport type WithoutChildren<T> = T extends { children?: unknown } ? Omit<T, \"children\"> : T;\nexport type WithoutChildrenOrChild<T> = WithoutChildren<WithoutChild<T>>;\nexport type WithElementRef<T, U extends HTMLElement = HTMLElement> = T & { ref?: U | null };\n`;\n\nasync function pickTarget(options: InitOptions): Promise<Target> {\n\tconst workspace = await findWorkspace(options.cwd);\n\tconst all = await discoverTargets(workspace);\n\tconst here = targetAt(all, options.cwd);\n\tif (here && !options.target?.length) return here;\n\tconst pool = options.target?.length ? all : all.filter((t) => !t.config);\n\tconst [picked] = await selectTargets(pool.length ? pool : all, options.cwd, options);\n\tif (!picked) throw new CliError(\"No project selected.\");\n\treturn picked;\n}\n\nfunction reactConfig(target: Target, css: string): Json {\n\tconst alias =\n\t\ttarget.aliases.find((a) => a.prefix === \"@/\") ??\n\t\ttarget.aliases.find((a) => !a.withExtension);\n\tif (!alias) {\n\t\tthrow new CliError(\"No import alias found for React components.\", {\n\t\t\thint: 'Add `\"paths\": { \"@/*\": [\"./src/*\"] }` to tsconfig.json compilerOptions.',\n\t\t});\n\t}\n\tconst p = alias.prefix.replace(/\\/$/, \"\");\n\tconst app = [\"app\", join(\"src\", \"app\")].some((d) => existsSync(join(target.root, d)));\n\treturn {\n\t\t$schema: \"https://ui.shadcn.com/schema.json\",\n\t\tstyle: \"new-york\",\n\t\trsc: target.meta === \"next\" && app,\n\t\ttsx: existsSync(join(target.root, \"tsconfig.json\")),\n\t\ttailwind: { config: \"\", css, baseColor: \"neutral\", cssVariables: true, prefix: \"\" },\n\t\ticonLibrary: \"lucide\",\n\t\taliases: {\n\t\t\tcomponents: `${p}/components`,\n\t\t\tutils: `${p}/lib/utils`,\n\t\t\tui: `${p}/components/ui`,\n\t\t\tlib: `${p}/lib`,\n\t\t\thooks: `${p}/hooks`,\n\t\t},\n\t\t// Lets the stock shadcn CLI install Baby UI (and, with a token, Pro) items too.\n\t\tregistries: {\n\t\t\t\"@baby-ui\": `${BABY_UI_ORIGIN}/r/{name}.json`,\n\t\t\t\"@baby-ui-pro\": {\n\t\t\t\turl: `${BABY_UI_ORIGIN}/pro/r/{name}.json`,\n\t\t\t\t// biome-ignore lint/suspicious/noTemplateCurlyInString: shadcn expands ${VAR} itself\n\t\t\t\theaders: { Authorization: \"Bearer ${BABY_UI_TOKEN}\" },\n\t\t\t},\n\t\t},\n\t};\n}\n\nfunction svelteConfig(target: Target, css: string): Json {\n\tconst hashLib = target.aliases.some((a) => a.prefix === \"#lib/\");\n\tconst lib = hashLib ? \"#lib\" : \"$lib\";\n\treturn {\n\t\t$schema: \"https://shadcn-svelte.com/schema.json\",\n\t\ttailwind: { css, baseColor: \"neutral\" },\n\t\taliases: {\n\t\t\tcomponents: `${lib}/components`,\n\t\t\tutils: `${lib}/utils`,\n\t\t\tui: `${lib}/components/ui`,\n\t\t\thooks: `${lib}/hooks`,\n\t\t\tlib,\n\t\t},\n\t\ttypescript: existsSync(join(target.root, \"tsconfig.json\")),\n\t\tregistry: \"https://shadcn-svelte.com/registry\",\n\t};\n}\n\nexport async function init(options: InitOptions, version: string): Promise<void> {\n\tconst { printBanner } = await import(\"../ui/banner.ts\");\n\tprintBanner(version);\n\tconst target = await pickTarget(options);\n\tconst framework = target.framework;\n\tif (!framework) throw new CliError(`${target.path} is not a React or Svelte project.`);\n\tintro(\n\t\t`baby-ui init ${c.dim(`${target.path} (${framework}, ${target.meta ?? \"unknown\"})`)}`,\n\t);\n\n\tif (target.config && !options.force) {\n\t\tmessage(\n\t\t\t`components.json already exists; installing the theme only. ${c.dim(\"--force rewrites it\")}`,\n\t\t);\n\t\tif (options.base !== false) {\n\t\t\tawait installInto(target, {\n\t\t\t\t...options,\n\t\t\t\titems: [\"theme\"],\n\t\t\t\tcommand: \"init (theme)\",\n\t\t\t});\n\t\t}\n\t\toutro(\"Done\");\n\t\treturn;\n\t}\n\n\tconst found = CSS_CANDIDATES[framework].find((p) => existsSync(join(target.root, p)));\n\tconst css =\n\t\toptions.css ??\n\t\t(await text({\n\t\t\tmessage: \"Where is your global CSS file?\",\n\t\t\tdefaultValue: found ?? CSS_CANDIDATES[framework][0],\n\t\t\tplaceholder: found ?? CSS_CANDIDATES[framework][0],\n\t\t}));\n\tconst raw =\n\t\tframework === \"react\" ? reactConfig(target, css) : svelteConfig(target, css);\n\tconst project: Target = { ...target, config: parseComponentsConfig(raw) };\n\tconst cfg = installConfig(project);\n\n\tconst base = options.base !== false;\n\tif (!target.dependencies.has(\"tailwindcss\")) {\n\t\tmessage(c.yellow(\"Tailwind CSS v4 is not installed; components need it.\"));\n\t}\n\n\tconst ext = cfg.typescript ? \".ts\" : \".js\";\n\tconst utils = `${resolveAlias(cfg.aliases.utils, project) ?? cfg.paths.utils}${ext}`;\n\tconst preOps: FileOp[] = [\n\t\t{\n\t\t\tpath: join(target.root, \"components.json\"),\n\t\t\tcontent: `${JSON.stringify(raw, null, 2)}\\n`,\n\t\t},\n\t];\n\tif (!existsSync(utils)) {\n\t\tconst content = !cfg.typescript\n\t\t\t? JS_UTILS\n\t\t\t: framework === \"svelte\"\n\t\t\t\t? SVELTE_UTILS\n\t\t\t\t: REACT_UTILS;\n\t\tpreOps.push({ path: utils, content });\n\t}\n\n\tawait installInto(\n\t\tproject,\n\t\t{ ...options, items: base ? [\"theme\"] : [], command: \"init\" },\n\t\t{\n\t\t\tpreOps,\n\t\t\tdependencies: [\"clsx\", \"tailwind-merge\"],\n\t\t\tcssSource: '@import \"tailwindcss\";\\n',\n\t\t},\n\t);\n\toutro(`Ready. Add components with ${c.brand(\"baby-ui add button\")}`);\n}\n"],"mappings":"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"}
@@ -0,0 +1,48 @@
1
+ import { u as c } from "./core-Cd391zXy.js";
2
+ import { _ as installConfig, d as babyUiUrl, l as fetchJson, s as RegistryIndexSchema, t as inspect } from "./state-CsT6LJsH.js";
3
+ import { a as note, n as intro, o as outro } from "./ui-Cthxlfe6.js";
4
+ import { a as readLock, t as configuredTargets } from "./shared-BJaaV-dl.js";
5
+ //#region src/commands/list.ts
6
+ /** The Baby UI index for each target's framework, with install state from its lock. */
7
+ async function list(options) {
8
+ const targets = await configuredTargets(options);
9
+ const query = options.query?.toLowerCase();
10
+ const rows = [];
11
+ if (!options.json) intro(query ? `baby-ui search ${query}` : "baby-ui list");
12
+ for (const target of targets) {
13
+ const cfg = installConfig(target);
14
+ const ctx = {
15
+ framework: cfg.framework,
16
+ typescript: cfg.typescript,
17
+ config: {},
18
+ cwd: target.root
19
+ };
20
+ const index = RegistryIndexSchema.parse(await fetchJson({
21
+ url: babyUiUrl("index", ctx),
22
+ headers: {}
23
+ }));
24
+ const states = await inspect(cfg, await readLock(target.root));
25
+ const state = new Map(states.map((s) => [s.item.name, s.files.some((f) => f.health !== "clean") ? "edited" : "installed"]));
26
+ const matches = index.filter((i) => (!options.type || i.type === `registry:${options.type}`) && (!query || i.name.includes(query) || i.title?.toLowerCase().includes(query) || i.description?.toLowerCase().includes(query)));
27
+ for (const i of matches) rows.push({
28
+ target: target.path,
29
+ name: i.name,
30
+ type: i.type,
31
+ installed: state.get(i.name) ?? ""
32
+ });
33
+ if (options.json) continue;
34
+ const width = Math.max(0, ...matches.map((i) => i.name.length));
35
+ const lines = matches.map((i) => {
36
+ const mark = state.get(i.name);
37
+ const tag = mark === "edited" ? c.yellow(" edited") : mark ? c.green(" installed") : "";
38
+ return `${i.name.padEnd(width)} ${c.dim(i.description ?? "")}${tag}`;
39
+ });
40
+ note(lines.join("\n") || c.dim("no matches"), `${target.path} ${c.dim(`(${cfg.framework})`)}`);
41
+ }
42
+ if (options.json) console.log(JSON.stringify(rows, null, 2));
43
+ else outro(`${rows.length} item(s). Add one with ${c.brand("baby-ui add <name>")}`);
44
+ }
45
+ //#endregion
46
+ export { list };
47
+
48
+ //# sourceMappingURL=list-DnQNQUNr.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list-DnQNQUNr.js","names":[],"sources":["../src/commands/list.ts"],"sourcesContent":["import { c } from \"../logger.ts\";\nimport { installConfig } from \"../project/paths.ts\";\nimport { fetchJson } from \"../registry/fetch.ts\";\nimport { babyUiUrl } from \"../registry/resolve.ts\";\nimport { RegistryIndexSchema } from \"../registry/schema.ts\";\nimport { intro, note, outro } from \"../ui/index.ts\";\nimport { readLock } from \"../write/lock.ts\";\nimport { inspect } from \"../write/state.ts\";\nimport { type CommonOptions, configuredTargets } from \"./shared.ts\";\n\nexport interface ListOptions extends CommonOptions {\n\treadonly query?: string;\n\treadonly json?: boolean;\n\treadonly type?: string;\n}\n\n/** The Baby UI index for each target's framework, with install state from its lock. */\nexport async function list(options: ListOptions): Promise<void> {\n\tconst targets = await configuredTargets(options);\n\tconst query = options.query?.toLowerCase();\n\tconst rows: Array<Record<string, string | boolean>> = [];\n\tif (!options.json) intro(query ? `baby-ui search ${query}` : \"baby-ui list\");\n\tfor (const target of targets) {\n\t\tconst cfg = installConfig(target);\n\t\tconst ctx = {\n\t\t\tframework: cfg.framework,\n\t\t\ttypescript: cfg.typescript,\n\t\t\tconfig: {},\n\t\t\tcwd: target.root,\n\t\t};\n\t\tconst index = RegistryIndexSchema.parse(\n\t\t\tawait fetchJson({ url: babyUiUrl(\"index\", ctx), headers: {} }),\n\t\t);\n\t\tconst states = await inspect(cfg, await readLock(target.root));\n\t\tconst state = new Map(\n\t\t\tstates.map((s) => [\n\t\t\t\ts.item.name,\n\t\t\t\ts.files.some((f) => f.health !== \"clean\") ? \"edited\" : \"installed\",\n\t\t\t]),\n\t\t);\n\t\tconst matches = index.filter(\n\t\t\t(i) =>\n\t\t\t\t(!options.type || i.type === `registry:${options.type}`) &&\n\t\t\t\t(!query ||\n\t\t\t\t\ti.name.includes(query) ||\n\t\t\t\t\ti.title?.toLowerCase().includes(query) ||\n\t\t\t\t\ti.description?.toLowerCase().includes(query)),\n\t\t);\n\t\tfor (const i of matches) {\n\t\t\trows.push({\n\t\t\t\ttarget: target.path,\n\t\t\t\tname: i.name,\n\t\t\t\ttype: i.type,\n\t\t\t\tinstalled: state.get(i.name) ?? \"\",\n\t\t\t});\n\t\t}\n\t\tif (options.json) continue;\n\t\tconst width = Math.max(0, ...matches.map((i) => i.name.length));\n\t\tconst lines = matches.map((i) => {\n\t\t\tconst mark = state.get(i.name);\n\t\t\tconst tag =\n\t\t\t\tmark === \"edited\" ? c.yellow(\" edited\") : mark ? c.green(\" installed\") : \"\";\n\t\t\treturn `${i.name.padEnd(width)} ${c.dim(i.description ?? \"\")}${tag}`;\n\t\t});\n\t\tnote(\n\t\t\tlines.join(\"\\n\") || c.dim(\"no matches\"),\n\t\t\t`${target.path} ${c.dim(`(${cfg.framework})`)}`,\n\t\t);\n\t}\n\tif (options.json) console.log(JSON.stringify(rows, null, 2));\n\telse outro(`${rows.length} item(s). Add one with ${c.brand(\"baby-ui add <name>\")}`);\n}\n"],"mappings":";;;;;;AAiBA,eAAsB,KAAK,SAAqC;CAC/D,MAAM,UAAU,MAAM,kBAAkB,OAAO;CAC/C,MAAM,QAAQ,QAAQ,OAAO,YAAY;CACzC,MAAM,OAAgD,CAAC;CACvD,IAAI,CAAC,QAAQ,MAAM,MAAM,QAAQ,kBAAkB,UAAU,cAAc;CAC3E,KAAK,MAAM,UAAU,SAAS;EAC7B,MAAM,MAAM,cAAc,MAAM;EAChC,MAAM,MAAM;GACX,WAAW,IAAI;GACf,YAAY,IAAI;GAChB,QAAQ,CAAC;GACT,KAAK,OAAO;EACb;EACA,MAAM,QAAQ,oBAAoB,MACjC,MAAM,UAAU;GAAE,KAAK,UAAU,SAAS,GAAG;GAAG,SAAS,CAAC;EAAE,CAAC,CAC9D;EACA,MAAM,SAAS,MAAM,QAAQ,KAAK,MAAM,SAAS,OAAO,IAAI,CAAC;EAC7D,MAAM,QAAQ,IAAI,IACjB,OAAO,KAAK,MAAM,CACjB,EAAE,KAAK,MACP,EAAE,MAAM,MAAM,MAAM,EAAE,WAAW,OAAO,IAAI,WAAW,WACxD,CAAC,CACF;EACA,MAAM,UAAU,MAAM,QACpB,OACC,CAAC,QAAQ,QAAQ,EAAE,SAAS,YAAY,QAAQ,YAChD,CAAC,SACD,EAAE,KAAK,SAAS,KAAK,KACrB,EAAE,OAAO,YAAY,CAAC,CAAC,SAAS,KAAK,KACrC,EAAE,aAAa,YAAY,CAAC,CAAC,SAAS,KAAK,EAC9C;EACA,KAAK,MAAM,KAAK,SACf,KAAK,KAAK;GACT,QAAQ,OAAO;GACf,MAAM,EAAE;GACR,MAAM,EAAE;GACR,WAAW,MAAM,IAAI,EAAE,IAAI,KAAK;EACjC,CAAC;EAEF,IAAI,QAAQ,MAAM;EAClB,MAAM,QAAQ,KAAK,IAAI,GAAG,GAAG,QAAQ,KAAK,MAAM,EAAE,KAAK,MAAM,CAAC;EAC9D,MAAM,QAAQ,QAAQ,KAAK,MAAM;GAChC,MAAM,OAAO,MAAM,IAAI,EAAE,IAAI;GAC7B,MAAM,MACL,SAAS,WAAW,EAAE,OAAO,SAAS,IAAI,OAAO,EAAE,MAAM,YAAY,IAAI;GAC1E,OAAO,GAAG,EAAE,KAAK,OAAO,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,eAAe,EAAE,IAAI;EACjE,CAAC;EACD,KACC,MAAM,KAAK,IAAI,KAAK,EAAE,IAAI,YAAY,GACtC,GAAG,OAAO,KAAK,GAAG,EAAE,IAAI,IAAI,IAAI,UAAU,EAAE,GAC7C;CACD;CACA,IAAI,QAAQ,MAAM,QAAQ,IAAI,KAAK,UAAU,MAAM,MAAM,CAAC,CAAC;MACtD,MAAM,GAAG,KAAK,OAAO,yBAAyB,EAAE,MAAM,oBAAoB,GAAG;AACnF"}
@@ -0,0 +1,183 @@
1
+ import { t as CliError } from "./errors-zXXytRXF.js";
2
+ import { f as symbols, u as c } from "./core-Cd391zXy.js";
3
+ import { _ as installConfig, d as babyUiUrl, f as canonicalUrl, l as fetchJson, m as requestFor, n as matchItems, s as RegistryIndexSchema, t as inspect } from "./state-CsT6LJsH.js";
4
+ import { a as note, n as intro, o as outro, r as message } from "./ui-Cthxlfe6.js";
5
+ import { a as readLock, c as sha256, o as relativeTo, t as configuredTargets } from "./shared-BJaaV-dl.js";
6
+ import { installInto, n as load, r as formatDiff, t as planInstall } from "./add-Dw_xdBjM.js";
7
+ import { existsSync, readFileSync, readdirSync } from "node:fs";
8
+ import { join } from "node:path";
9
+ //#region src/commands/maintain.ts
10
+ const context = (cfg) => ({
11
+ framework: cfg.framework,
12
+ typescript: cfg.typescript,
13
+ config: cfg.project.config?.raw ?? {},
14
+ cwd: cfg.project.root
15
+ });
16
+ async function lockedUrls(target, names) {
17
+ const lock = await readLock(target.root);
18
+ const matched = matchItems(lock, names);
19
+ const missing = names.filter((n) => !matched.some(([url, i]) => i.name === n || url === n));
20
+ if (missing.length) throw new CliError(`Not installed in ${target.path}: ${missing.join(", ")}.`, { hint: "Add it first, or adopt files from the stock CLI with `baby-ui repair --adopt <item>`." });
21
+ return matched.map(([url]) => url);
22
+ }
23
+ const DRIFT = {
24
+ upstream: c.brand("update available"),
25
+ local: c.yellow("local edits"),
26
+ both: c.red("both changed"),
27
+ missing: c.red("missing"),
28
+ new: c.green("new upstream file")
29
+ };
30
+ async function diff(options) {
31
+ const targets = await configuredTargets(options);
32
+ intro("baby-ui diff");
33
+ let drifted = 0;
34
+ for (const target of targets) {
35
+ const cfg = installConfig(target);
36
+ const lock = await readLock(target.root);
37
+ const urls = await lockedUrls(target, options.items);
38
+ const items = await Promise.all(urls.map(async (url) => ({
39
+ url,
40
+ item: await load(requestFor(url, context(cfg))),
41
+ requested: true
42
+ })));
43
+ const plan = planInstall(cfg, items);
44
+ for (const { url, item } of items) {
45
+ const locked = lock.items[canonicalUrl(url)];
46
+ const lines = [];
47
+ if (locked && locked.itemHash !== sha256(JSON.stringify(item))) lines.push(c.dim("registry item changed since install"));
48
+ for (const file of plan.files.filter((f) => f.itemUrl === url && f.root === target.root)) {
49
+ const rel = relativeTo(target.root, file.path);
50
+ const hash = locked?.files[rel];
51
+ const local = existsSync(file.path) ? readFileSync(file.path, "utf8") : void 0;
52
+ if (local === file.content) continue;
53
+ const drift = local === void 0 ? hash ? "missing" : "new" : sha256(local) === hash ? "upstream" : sha256(file.content) === hash ? "local" : "both";
54
+ lines.push(`${DRIFT[drift]} ${rel}`);
55
+ if (!options.stat && local !== void 0) lines.push(formatDiff(local, file.content));
56
+ }
57
+ if (lines.length) {
58
+ drifted++;
59
+ note(lines.join("\n"), `${item.name} ${c.dim(target.path)}`);
60
+ }
61
+ }
62
+ }
63
+ outro(drifted ? `${drifted} item(s) differ. ${c.dim("Apply with `baby-ui update`.")}` : "Up to date");
64
+ if (drifted && options.exitCode) process.exitCode = 1;
65
+ }
66
+ async function update(options) {
67
+ const targets = await configuredTargets(options);
68
+ intro(`baby-ui update ${options.items.join(" ")}`);
69
+ for (const target of targets) {
70
+ const urls = await lockedUrls(target, options.items);
71
+ if (!urls.length) {
72
+ message(c.dim(`${target.path}: nothing installed`));
73
+ continue;
74
+ }
75
+ await installInto(target, {
76
+ ...options,
77
+ items: urls,
78
+ command: `update ${options.items.join(" ") || "(all)"}`
79
+ });
80
+ }
81
+ outro("Done");
82
+ }
83
+ async function guessInstalled(cfg) {
84
+ const ctx = context(cfg);
85
+ const index = RegistryIndexSchema.safeParse(await fetchJson({
86
+ url: babyUiUrl("index", ctx),
87
+ headers: {}
88
+ }));
89
+ if (!index.success || !existsSync(cfg.paths.ui)) return [];
90
+ const present = new Set(readdirSync(cfg.paths.ui).map((n) => n.replace(/\.(tsx?|jsx?|svelte)$/, "")));
91
+ return index.data.map((i) => i.name).filter((name) => present.has(name));
92
+ }
93
+ async function repair(options) {
94
+ const targets = await configuredTargets(options);
95
+ intro(options.adopt ? "baby-ui repair --adopt" : "baby-ui repair");
96
+ for (const target of targets) {
97
+ const cfg = installConfig(target);
98
+ if (options.adopt) {
99
+ const names = options.items.length ? options.items : await guessInstalled(cfg);
100
+ if (!names.length) {
101
+ message(c.dim(`${target.path}: no Baby UI components found to adopt`));
102
+ continue;
103
+ }
104
+ await installInto(target, {
105
+ ...options,
106
+ items: names,
107
+ mode: "adopt",
108
+ command: `repair --adopt ${names.join(" ")}`
109
+ });
110
+ continue;
111
+ }
112
+ const urls = await lockedUrls(target, options.items);
113
+ if (!urls.length) {
114
+ message(c.dim(`${target.path}: nothing installed`));
115
+ continue;
116
+ }
117
+ const before = await inspect(cfg);
118
+ await installInto(target, {
119
+ ...options,
120
+ items: urls,
121
+ mode: options.force ? "add" : "repair",
122
+ overwrite: options.force,
123
+ command: `repair${options.force ? " --force" : ""} ${options.items.join(" ")}`.trim()
124
+ });
125
+ if (options.force) continue;
126
+ const edited = before.flatMap((s) => s.files.filter((f) => f.health === "modified" || f.health === "broken").map((f) => f.path));
127
+ if (edited.length) note(edited.join("\n"), `${c.yellow("Left alone")} ${c.dim("(edited locally; --force restores them, undo reverts)")}`);
128
+ }
129
+ outro("Done");
130
+ }
131
+ const MARK = {
132
+ ok: c.green(symbols.tick),
133
+ warn: c.yellow("!"),
134
+ fail: c.red(symbols.cross)
135
+ };
136
+ async function checkTarget(target) {
137
+ const out = [];
138
+ let cfg;
139
+ try {
140
+ cfg = installConfig(target);
141
+ out.push(["ok", `components.json (${cfg.framework}), aliases resolve`]);
142
+ } catch (error) {
143
+ out.push(["fail", error instanceof Error ? error.message : String(error)]);
144
+ return out;
145
+ }
146
+ const css = cfg.paths.css;
147
+ if (!css || !existsSync(css)) out.push(["fail", `stylesheet ${css ?? "(unset)"} not found`]);
148
+ else if (!/@import\s+["']tailwindcss["']/.test(readFileSync(css, "utf8"))) out.push(["warn", `${relativeTo(target.root, css)} does not import tailwindcss`]);
149
+ else out.push(["ok", `stylesheet ${relativeTo(target.root, css)}`]);
150
+ out.push(target.dependencies.has("tailwindcss") ? ["ok", "tailwindcss installed"] : ["warn", "tailwindcss is not a dependency"]);
151
+ const states = await inspect(cfg);
152
+ const files = states.flatMap((s) => s.files);
153
+ const count = (h) => files.filter((f) => f.health === h).length;
154
+ if (!states.length) out.push(["ok", "no Baby UI items installed yet"]);
155
+ else out.push(["ok", `${states.length} item(s), ${count("clean")}/${files.length} files untouched`]);
156
+ if (count("modified")) out.push(["ok", `${count("modified")} file(s) edited locally`]);
157
+ for (const s of states) {
158
+ for (const f of s.files) {
159
+ if (f.health === "missing") out.push(["fail", `${s.item.name}: ${f.path} is missing`]);
160
+ if (f.health === "broken") out.push(["fail", `${s.item.name}: ${f.path} does not parse`]);
161
+ for (const spec of f.unresolved) out.push(["fail", `${s.item.name}: ${f.path} imports ${spec}, which does not resolve`]);
162
+ }
163
+ if (s.missingDeps.length) out.push(["fail", `${s.item.name}: missing packages ${s.missingDeps.join(", ")}`]);
164
+ }
165
+ if (existsSync(join(target.root, ".baby-ui", "history")) && !existsSync(join(target.root, ".baby-ui", ".gitignore"))) out.push(["warn", ".baby-ui/.gitignore is missing; undo snapshots could get committed"]);
166
+ return out;
167
+ }
168
+ async function doctor(options) {
169
+ const targets = await configuredTargets(options);
170
+ intro("baby-ui doctor");
171
+ let failed = false;
172
+ for (const target of targets) {
173
+ const results = await checkTarget(target);
174
+ failed ||= results.some(([level]) => level === "fail");
175
+ note(results.map(([level, text]) => `${MARK[level]} ${text}`).join("\n"), target.path);
176
+ }
177
+ outro(failed ? c.red("Problems found. `baby-ui repair` fixes most of them.") : "All good");
178
+ if (failed) process.exitCode = 1;
179
+ }
180
+ //#endregion
181
+ export { diff, doctor, repair, update };
182
+
183
+ //# sourceMappingURL=maintain-DeyqYm5K.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"maintain-DeyqYm5K.js","names":[],"sources":["../src/commands/maintain.ts"],"sourcesContent":["import { existsSync, readdirSync, readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { formatDiff } from \"../diff.ts\";\nimport { CliError } from \"../errors.ts\";\nimport { c, symbols } from \"../logger.ts\";\nimport { type InstallConfig, installConfig } from \"../project/paths.ts\";\nimport type { Target } from \"../project/targets.ts\";\nimport { fetchJson } from \"../registry/fetch.ts\";\nimport { load, type ResolvedItem } from \"../registry/graph.ts\";\nimport {\n\tbabyUiUrl,\n\tcanonicalUrl,\n\ttype RegistryContext,\n\trequestFor,\n} from \"../registry/resolve.ts\";\nimport { RegistryIndexSchema } from \"../registry/schema.ts\";\nimport { intro, message, note, outro } from \"../ui/index.ts\";\nimport { readLock, relativeTo, sha256 } from \"../write/lock.ts\";\nimport { planInstall } from \"../write/plan.ts\";\nimport { inspect, matchItems } from \"../write/state.ts\";\nimport { type AddOptions, installInto } from \"./add.ts\";\nimport { type CommonOptions, configuredTargets } from \"./shared.ts\";\n\nexport interface ItemsOptions extends CommonOptions {\n\treadonly items: readonly string[];\n}\n\nconst context = (cfg: InstallConfig): RegistryContext => ({\n\tframework: cfg.framework,\n\ttypescript: cfg.typescript,\n\tconfig: cfg.project.config?.raw ?? {},\n\tcwd: cfg.project.root,\n});\n\nasync function lockedUrls(target: Target, names: readonly string[]): Promise<string[]> {\n\tconst lock = await readLock(target.root);\n\tconst matched = matchItems(lock, names);\n\tconst missing = names.filter(\n\t\t(n) => !matched.some(([url, i]) => i.name === n || url === n),\n\t);\n\tif (missing.length) {\n\t\tthrow new CliError(`Not installed in ${target.path}: ${missing.join(\", \")}.`, {\n\t\t\thint: \"Add it first, or adopt files from the stock CLI with `baby-ui repair --adopt <item>`.\",\n\t\t});\n\t}\n\treturn matched.map(([url]) => url);\n}\n\n// --- diff ---\n\nexport interface DiffOptions extends ItemsOptions {\n\treadonly stat?: boolean;\n\t/** Exit 1 when anything differs, for CI. */\n\treadonly exitCode?: boolean;\n}\n\ntype Drift = \"upstream\" | \"local\" | \"both\" | \"missing\" | \"new\";\n\nconst DRIFT: Record<Drift, string> = {\n\tupstream: c.brand(\"update available\"),\n\tlocal: c.yellow(\"local edits\"),\n\tboth: c.red(\"both changed\"),\n\tmissing: c.red(\"missing\"),\n\tnew: c.green(\"new upstream file\"),\n};\n\nexport async function diff(options: DiffOptions): Promise<void> {\n\tconst targets = await configuredTargets(options);\n\tintro(\"baby-ui diff\");\n\tlet drifted = 0;\n\tfor (const target of targets) {\n\t\tconst cfg = installConfig(target);\n\t\tconst lock = await readLock(target.root);\n\t\tconst urls = await lockedUrls(target, options.items);\n\t\tconst items: ResolvedItem[] = await Promise.all(\n\t\t\turls.map(async (url) => ({\n\t\t\t\turl,\n\t\t\t\titem: await load(requestFor(url, context(cfg))),\n\t\t\t\trequested: true,\n\t\t\t})),\n\t\t);\n\t\tconst plan = planInstall(cfg, items);\n\t\tfor (const { url, item } of items) {\n\t\t\tconst locked = lock.items[canonicalUrl(url)];\n\t\t\tconst lines: string[] = [];\n\t\t\tif (locked && locked.itemHash !== sha256(JSON.stringify(item))) {\n\t\t\t\tlines.push(c.dim(\"registry item changed since install\"));\n\t\t\t}\n\t\t\tfor (const file of plan.files.filter(\n\t\t\t\t(f) => f.itemUrl === url && f.root === target.root,\n\t\t\t)) {\n\t\t\t\tconst rel = relativeTo(target.root, file.path);\n\t\t\t\tconst hash = locked?.files[rel];\n\t\t\t\tconst local = existsSync(file.path) ? readFileSync(file.path, \"utf8\") : undefined;\n\t\t\t\tif (local === file.content) continue;\n\t\t\t\tconst drift: Drift =\n\t\t\t\t\tlocal === undefined\n\t\t\t\t\t\t? hash\n\t\t\t\t\t\t\t? \"missing\"\n\t\t\t\t\t\t\t: \"new\"\n\t\t\t\t\t\t: sha256(local) === hash\n\t\t\t\t\t\t\t? \"upstream\"\n\t\t\t\t\t\t\t: sha256(file.content) === hash\n\t\t\t\t\t\t\t\t? \"local\"\n\t\t\t\t\t\t\t\t: \"both\";\n\t\t\t\tlines.push(`${DRIFT[drift]} ${rel}`);\n\t\t\t\tif (!options.stat && local !== undefined)\n\t\t\t\t\tlines.push(formatDiff(local, file.content));\n\t\t\t}\n\t\t\tif (lines.length) {\n\t\t\t\tdrifted++;\n\t\t\t\tnote(lines.join(\"\\n\"), `${item.name} ${c.dim(target.path)}`);\n\t\t\t}\n\t\t}\n\t}\n\toutro(\n\t\tdrifted\n\t\t\t? `${drifted} item(s) differ. ${c.dim(\"Apply with `baby-ui update`.\")}`\n\t\t\t: \"Up to date\",\n\t);\n\tif (drifted && options.exitCode) process.exitCode = 1;\n}\n\n// --- update ---\n\nexport async function update(\n\toptions: ItemsOptions & Omit<AddOptions, \"items\">,\n): Promise<void> {\n\tconst targets = await configuredTargets(options);\n\tintro(`baby-ui update ${options.items.join(\" \")}`);\n\tfor (const target of targets) {\n\t\tconst urls = await lockedUrls(target, options.items);\n\t\tif (!urls.length) {\n\t\t\tmessage(c.dim(`${target.path}: nothing installed`));\n\t\t\tcontinue;\n\t\t}\n\t\tawait installInto(target, {\n\t\t\t...options,\n\t\t\titems: urls,\n\t\t\tcommand: `update ${options.items.join(\" \") || \"(all)\"}`,\n\t\t});\n\t}\n\toutro(\"Done\");\n}\n\n// --- repair ---\n\nexport interface RepairOptions extends ItemsOptions {\n\treadonly adopt?: boolean;\n\treadonly force?: boolean;\n\treadonly install?: boolean;\n\treadonly dryRun?: boolean;\n}\n\n// Stock-CLI installs: match registry names against folders and files in the ui dir.\nasync function guessInstalled(cfg: InstallConfig): Promise<string[]> {\n\tconst ctx = context(cfg);\n\tconst index = RegistryIndexSchema.safeParse(\n\t\tawait fetchJson({ url: babyUiUrl(\"index\", ctx), headers: {} }),\n\t);\n\tif (!index.success || !existsSync(cfg.paths.ui)) return [];\n\tconst present = new Set(\n\t\treaddirSync(cfg.paths.ui).map((n) => n.replace(/\\.(tsx?|jsx?|svelte)$/, \"\")),\n\t);\n\treturn index.data.map((i) => i.name).filter((name) => present.has(name));\n}\n\nexport async function repair(options: RepairOptions): Promise<void> {\n\tconst targets = await configuredTargets(options);\n\tintro(options.adopt ? \"baby-ui repair --adopt\" : \"baby-ui repair\");\n\tfor (const target of targets) {\n\t\tconst cfg = installConfig(target);\n\t\tif (options.adopt) {\n\t\t\tconst names = options.items.length ? options.items : await guessInstalled(cfg);\n\t\t\tif (!names.length) {\n\t\t\t\tmessage(c.dim(`${target.path}: no Baby UI components found to adopt`));\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tawait installInto(target, {\n\t\t\t\t...options,\n\t\t\t\titems: names,\n\t\t\t\tmode: \"adopt\",\n\t\t\t\tcommand: `repair --adopt ${names.join(\" \")}`,\n\t\t\t});\n\t\t\tcontinue;\n\t\t}\n\t\tconst urls = await lockedUrls(target, options.items);\n\t\tif (!urls.length) {\n\t\t\tmessage(c.dim(`${target.path}: nothing installed`));\n\t\t\tcontinue;\n\t\t}\n\t\tconst before = await inspect(cfg);\n\t\tawait installInto(target, {\n\t\t\t...options,\n\t\t\titems: urls,\n\t\t\tmode: options.force ? \"add\" : \"repair\",\n\t\t\toverwrite: options.force,\n\t\t\tcommand:\n\t\t\t\t`repair${options.force ? \" --force\" : \"\"} ${options.items.join(\" \")}`.trim(),\n\t\t});\n\t\tif (options.force) continue;\n\t\tconst edited = before.flatMap((s) =>\n\t\t\ts.files\n\t\t\t\t.filter((f) => f.health === \"modified\" || f.health === \"broken\")\n\t\t\t\t.map((f) => f.path),\n\t\t);\n\t\tif (edited.length) {\n\t\t\tnote(\n\t\t\t\tedited.join(\"\\n\"),\n\t\t\t\t`${c.yellow(\"Left alone\")} ${c.dim(\"(edited locally; --force restores them, undo reverts)\")}`,\n\t\t\t);\n\t\t}\n\t}\n\toutro(\"Done\");\n}\n\n// --- doctor ---\n\ntype Level = \"ok\" | \"warn\" | \"fail\";\nconst MARK: Record<Level, string> = {\n\tok: c.green(symbols.tick),\n\twarn: c.yellow(\"!\"),\n\tfail: c.red(symbols.cross),\n};\n\nasync function checkTarget(target: Target): Promise<Array<[Level, string]>> {\n\tconst out: Array<[Level, string]> = [];\n\tlet cfg: InstallConfig;\n\ttry {\n\t\tcfg = installConfig(target);\n\t\tout.push([\"ok\", `components.json (${cfg.framework}), aliases resolve`]);\n\t} catch (error) {\n\t\tout.push([\"fail\", error instanceof Error ? error.message : String(error)]);\n\t\treturn out;\n\t}\n\tconst css = cfg.paths.css;\n\tif (!css || !existsSync(css))\n\t\tout.push([\"fail\", `stylesheet ${css ?? \"(unset)\"} not found`]);\n\telse if (!/@import\\s+[\"']tailwindcss[\"']/.test(readFileSync(css, \"utf8\"))) {\n\t\tout.push([\"warn\", `${relativeTo(target.root, css)} does not import tailwindcss`]);\n\t} else out.push([\"ok\", `stylesheet ${relativeTo(target.root, css)}`]);\n\tout.push(\n\t\ttarget.dependencies.has(\"tailwindcss\")\n\t\t\t? [\"ok\", \"tailwindcss installed\"]\n\t\t\t: [\"warn\", \"tailwindcss is not a dependency\"],\n\t);\n\n\tconst states = await inspect(cfg);\n\tconst files = states.flatMap((s) => s.files);\n\tconst count = (h: string) => files.filter((f) => f.health === h).length;\n\tif (!states.length) out.push([\"ok\", \"no Baby UI items installed yet\"]);\n\telse\n\t\tout.push([\n\t\t\t\"ok\",\n\t\t\t`${states.length} item(s), ${count(\"clean\")}/${files.length} files untouched`,\n\t\t]);\n\tif (count(\"modified\")) out.push([\"ok\", `${count(\"modified\")} file(s) edited locally`]);\n\tfor (const s of states) {\n\t\tfor (const f of s.files) {\n\t\t\tif (f.health === \"missing\")\n\t\t\t\tout.push([\"fail\", `${s.item.name}: ${f.path} is missing`]);\n\t\t\tif (f.health === \"broken\")\n\t\t\t\tout.push([\"fail\", `${s.item.name}: ${f.path} does not parse`]);\n\t\t\tfor (const spec of f.unresolved) {\n\t\t\t\tout.push([\n\t\t\t\t\t\"fail\",\n\t\t\t\t\t`${s.item.name}: ${f.path} imports ${spec}, which does not resolve`,\n\t\t\t\t]);\n\t\t\t}\n\t\t}\n\t\tif (s.missingDeps.length) {\n\t\t\tout.push([\"fail\", `${s.item.name}: missing packages ${s.missingDeps.join(\", \")}`]);\n\t\t}\n\t}\n\tif (\n\t\texistsSync(join(target.root, \".baby-ui\", \"history\")) &&\n\t\t!existsSync(join(target.root, \".baby-ui\", \".gitignore\"))\n\t) {\n\t\tout.push([\n\t\t\t\"warn\",\n\t\t\t\".baby-ui/.gitignore is missing; undo snapshots could get committed\",\n\t\t]);\n\t}\n\treturn out;\n}\n\nexport async function doctor(options: CommonOptions): Promise<void> {\n\tconst targets = await configuredTargets(options);\n\tintro(\"baby-ui doctor\");\n\tlet failed = false;\n\tfor (const target of targets) {\n\t\tconst results = await checkTarget(target);\n\t\tfailed ||= results.some(([level]) => level === \"fail\");\n\t\tnote(\n\t\t\tresults.map(([level, text]) => `${MARK[level]} ${text}`).join(\"\\n\"),\n\t\t\ttarget.path,\n\t\t);\n\t}\n\toutro(\n\t\tfailed ? c.red(\"Problems found. `baby-ui repair` fixes most of them.\") : \"All good\",\n\t);\n\tif (failed) process.exitCode = 1;\n}\n"],"mappings":";;;;;;;;;AA2BA,MAAM,WAAW,SAAyC;CACzD,WAAW,IAAI;CACf,YAAY,IAAI;CAChB,QAAQ,IAAI,QAAQ,QAAQ,OAAO,CAAC;CACpC,KAAK,IAAI,QAAQ;AAClB;AAEA,eAAe,WAAW,QAAgB,OAA6C;CACtF,MAAM,OAAO,MAAM,SAAS,OAAO,IAAI;CACvC,MAAM,UAAU,WAAW,MAAM,KAAK;CACtC,MAAM,UAAU,MAAM,QACpB,MAAM,CAAC,QAAQ,MAAM,CAAC,KAAK,OAAO,EAAE,SAAS,KAAK,QAAQ,CAAC,CAC7D;CACA,IAAI,QAAQ,QACX,MAAM,IAAI,SAAS,oBAAoB,OAAO,KAAK,IAAI,QAAQ,KAAK,IAAI,EAAE,IAAI,EAC7E,MAAM,wFACP,CAAC;CAEF,OAAO,QAAQ,KAAK,CAAC,SAAS,GAAG;AAClC;AAYA,MAAM,QAA+B;CACpC,UAAU,EAAE,MAAM,kBAAkB;CACpC,OAAO,EAAE,OAAO,aAAa;CAC7B,MAAM,EAAE,IAAI,cAAc;CAC1B,SAAS,EAAE,IAAI,SAAS;CACxB,KAAK,EAAE,MAAM,mBAAmB;AACjC;AAEA,eAAsB,KAAK,SAAqC;CAC/D,MAAM,UAAU,MAAM,kBAAkB,OAAO;CAC/C,MAAM,cAAc;CACpB,IAAI,UAAU;CACd,KAAK,MAAM,UAAU,SAAS;EAC7B,MAAM,MAAM,cAAc,MAAM;EAChC,MAAM,OAAO,MAAM,SAAS,OAAO,IAAI;EACvC,MAAM,OAAO,MAAM,WAAW,QAAQ,QAAQ,KAAK;EACnD,MAAM,QAAwB,MAAM,QAAQ,IAC3C,KAAK,IAAI,OAAO,SAAS;GACxB;GACA,MAAM,MAAM,KAAK,WAAW,KAAK,QAAQ,GAAG,CAAC,CAAC;GAC9C,WAAW;EACZ,EAAE,CACH;EACA,MAAM,OAAO,YAAY,KAAK,KAAK;EACnC,KAAK,MAAM,EAAE,KAAK,UAAU,OAAO;GAClC,MAAM,SAAS,KAAK,MAAM,aAAa,GAAG;GAC1C,MAAM,QAAkB,CAAC;GACzB,IAAI,UAAU,OAAO,aAAa,OAAO,KAAK,UAAU,IAAI,CAAC,GAC5D,MAAM,KAAK,EAAE,IAAI,qCAAqC,CAAC;GAExD,KAAK,MAAM,QAAQ,KAAK,MAAM,QAC5B,MAAM,EAAE,YAAY,OAAO,EAAE,SAAS,OAAO,IAC/C,GAAG;IACF,MAAM,MAAM,WAAW,OAAO,MAAM,KAAK,IAAI;IAC7C,MAAM,OAAO,QAAQ,MAAM;IAC3B,MAAM,QAAQ,WAAW,KAAK,IAAI,IAAI,aAAa,KAAK,MAAM,MAAM,IAAI,KAAA;IACxE,IAAI,UAAU,KAAK,SAAS;IAC5B,MAAM,QACL,UAAU,KAAA,IACP,OACC,YACA,QACD,OAAO,KAAK,MAAM,OACjB,aACA,OAAO,KAAK,OAAO,MAAM,OACxB,UACA;IACN,MAAM,KAAK,GAAG,MAAM,OAAO,IAAI,KAAK;IACpC,IAAI,CAAC,QAAQ,QAAQ,UAAU,KAAA,GAC9B,MAAM,KAAK,WAAW,OAAO,KAAK,OAAO,CAAC;GAC5C;GACA,IAAI,MAAM,QAAQ;IACjB;IACA,KAAK,MAAM,KAAK,IAAI,GAAG,GAAG,KAAK,KAAK,GAAG,EAAE,IAAI,OAAO,IAAI,GAAG;GAC5D;EACD;CACD;CACA,MACC,UACG,GAAG,QAAQ,mBAAmB,EAAE,IAAI,8BAA8B,MAClE,YACJ;CACA,IAAI,WAAW,QAAQ,UAAU,QAAQ,WAAW;AACrD;AAIA,eAAsB,OACrB,SACgB;CAChB,MAAM,UAAU,MAAM,kBAAkB,OAAO;CAC/C,MAAM,kBAAkB,QAAQ,MAAM,KAAK,GAAG,GAAG;CACjD,KAAK,MAAM,UAAU,SAAS;EAC7B,MAAM,OAAO,MAAM,WAAW,QAAQ,QAAQ,KAAK;EACnD,IAAI,CAAC,KAAK,QAAQ;GACjB,QAAQ,EAAE,IAAI,GAAG,OAAO,KAAK,oBAAoB,CAAC;GAClD;EACD;EACA,MAAM,YAAY,QAAQ;GACzB,GAAG;GACH,OAAO;GACP,SAAS,UAAU,QAAQ,MAAM,KAAK,GAAG,KAAK;EAC/C,CAAC;CACF;CACA,MAAM,MAAM;AACb;AAYA,eAAe,eAAe,KAAuC;CACpE,MAAM,MAAM,QAAQ,GAAG;CACvB,MAAM,QAAQ,oBAAoB,UACjC,MAAM,UAAU;EAAE,KAAK,UAAU,SAAS,GAAG;EAAG,SAAS,CAAC;CAAE,CAAC,CAC9D;CACA,IAAI,CAAC,MAAM,WAAW,CAAC,WAAW,IAAI,MAAM,EAAE,GAAG,OAAO,CAAC;CACzD,MAAM,UAAU,IAAI,IACnB,YAAY,IAAI,MAAM,EAAE,CAAC,CAAC,KAAK,MAAM,EAAE,QAAQ,yBAAyB,EAAE,CAAC,CAC5E;CACA,OAAO,MAAM,KAAK,KAAK,MAAM,EAAE,IAAI,CAAC,CAAC,QAAQ,SAAS,QAAQ,IAAI,IAAI,CAAC;AACxE;AAEA,eAAsB,OAAO,SAAuC;CACnE,MAAM,UAAU,MAAM,kBAAkB,OAAO;CAC/C,MAAM,QAAQ,QAAQ,2BAA2B,gBAAgB;CACjE,KAAK,MAAM,UAAU,SAAS;EAC7B,MAAM,MAAM,cAAc,MAAM;EAChC,IAAI,QAAQ,OAAO;GAClB,MAAM,QAAQ,QAAQ,MAAM,SAAS,QAAQ,QAAQ,MAAM,eAAe,GAAG;GAC7E,IAAI,CAAC,MAAM,QAAQ;IAClB,QAAQ,EAAE,IAAI,GAAG,OAAO,KAAK,uCAAuC,CAAC;IACrE;GACD;GACA,MAAM,YAAY,QAAQ;IACzB,GAAG;IACH,OAAO;IACP,MAAM;IACN,SAAS,kBAAkB,MAAM,KAAK,GAAG;GAC1C,CAAC;GACD;EACD;EACA,MAAM,OAAO,MAAM,WAAW,QAAQ,QAAQ,KAAK;EACnD,IAAI,CAAC,KAAK,QAAQ;GACjB,QAAQ,EAAE,IAAI,GAAG,OAAO,KAAK,oBAAoB,CAAC;GAClD;EACD;EACA,MAAM,SAAS,MAAM,QAAQ,GAAG;EAChC,MAAM,YAAY,QAAQ;GACzB,GAAG;GACH,OAAO;GACP,MAAM,QAAQ,QAAQ,QAAQ;GAC9B,WAAW,QAAQ;GACnB,SACC,SAAS,QAAQ,QAAQ,aAAa,GAAG,GAAG,QAAQ,MAAM,KAAK,GAAG,IAAI,KAAK;EAC7E,CAAC;EACD,IAAI,QAAQ,OAAO;EACnB,MAAM,SAAS,OAAO,SAAS,MAC9B,EAAE,MACA,QAAQ,MAAM,EAAE,WAAW,cAAc,EAAE,WAAW,QAAQ,CAAC,CAC/D,KAAK,MAAM,EAAE,IAAI,CACpB;EACA,IAAI,OAAO,QACV,KACC,OAAO,KAAK,IAAI,GAChB,GAAG,EAAE,OAAO,YAAY,EAAE,GAAG,EAAE,IAAI,uDAAuD,GAC3F;CAEF;CACA,MAAM,MAAM;AACb;AAKA,MAAM,OAA8B;CACnC,IAAI,EAAE,MAAM,QAAQ,IAAI;CACxB,MAAM,EAAE,OAAO,GAAG;CAClB,MAAM,EAAE,IAAI,QAAQ,KAAK;AAC1B;AAEA,eAAe,YAAY,QAAiD;CAC3E,MAAM,MAA8B,CAAC;CACrC,IAAI;CACJ,IAAI;EACH,MAAM,cAAc,MAAM;EAC1B,IAAI,KAAK,CAAC,MAAM,oBAAoB,IAAI,UAAU,mBAAmB,CAAC;CACvE,SAAS,OAAO;EACf,IAAI,KAAK,CAAC,QAAQ,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC,CAAC;EACzE,OAAO;CACR;CACA,MAAM,MAAM,IAAI,MAAM;CACtB,IAAI,CAAC,OAAO,CAAC,WAAW,GAAG,GAC1B,IAAI,KAAK,CAAC,QAAQ,cAAc,OAAO,UAAU,WAAW,CAAC;MACzD,IAAI,CAAC,gCAAgC,KAAK,aAAa,KAAK,MAAM,CAAC,GACvE,IAAI,KAAK,CAAC,QAAQ,GAAG,WAAW,OAAO,MAAM,GAAG,EAAE,6BAA6B,CAAC;MAC1E,IAAI,KAAK,CAAC,MAAM,cAAc,WAAW,OAAO,MAAM,GAAG,GAAG,CAAC;CACpE,IAAI,KACH,OAAO,aAAa,IAAI,aAAa,IAClC,CAAC,MAAM,uBAAuB,IAC9B,CAAC,QAAQ,iCAAiC,CAC9C;CAEA,MAAM,SAAS,MAAM,QAAQ,GAAG;CAChC,MAAM,QAAQ,OAAO,SAAS,MAAM,EAAE,KAAK;CAC3C,MAAM,SAAS,MAAc,MAAM,QAAQ,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC;CACjE,IAAI,CAAC,OAAO,QAAQ,IAAI,KAAK,CAAC,MAAM,gCAAgC,CAAC;MAEpE,IAAI,KAAK,CACR,MACA,GAAG,OAAO,OAAO,YAAY,MAAM,OAAO,EAAE,GAAG,MAAM,OAAO,iBAC7D,CAAC;CACF,IAAI,MAAM,UAAU,GAAG,IAAI,KAAK,CAAC,MAAM,GAAG,MAAM,UAAU,EAAE,wBAAwB,CAAC;CACrF,KAAK,MAAM,KAAK,QAAQ;EACvB,KAAK,MAAM,KAAK,EAAE,OAAO;GACxB,IAAI,EAAE,WAAW,WAChB,IAAI,KAAK,CAAC,QAAQ,GAAG,EAAE,KAAK,KAAK,IAAI,EAAE,KAAK,YAAY,CAAC;GAC1D,IAAI,EAAE,WAAW,UAChB,IAAI,KAAK,CAAC,QAAQ,GAAG,EAAE,KAAK,KAAK,IAAI,EAAE,KAAK,gBAAgB,CAAC;GAC9D,KAAK,MAAM,QAAQ,EAAE,YACpB,IAAI,KAAK,CACR,QACA,GAAG,EAAE,KAAK,KAAK,IAAI,EAAE,KAAK,WAAW,KAAK,yBAC3C,CAAC;EAEH;EACA,IAAI,EAAE,YAAY,QACjB,IAAI,KAAK,CAAC,QAAQ,GAAG,EAAE,KAAK,KAAK,qBAAqB,EAAE,YAAY,KAAK,IAAI,GAAG,CAAC;CAEnF;CACA,IACC,WAAW,KAAK,OAAO,MAAM,YAAY,SAAS,CAAC,KACnD,CAAC,WAAW,KAAK,OAAO,MAAM,YAAY,YAAY,CAAC,GAEvD,IAAI,KAAK,CACR,QACA,oEACD,CAAC;CAEF,OAAO;AACR;AAEA,eAAsB,OAAO,SAAuC;CACnE,MAAM,UAAU,MAAM,kBAAkB,OAAO;CAC/C,MAAM,gBAAgB;CACtB,IAAI,SAAS;CACb,KAAK,MAAM,UAAU,SAAS;EAC7B,MAAM,UAAU,MAAM,YAAY,MAAM;EACxC,WAAW,QAAQ,MAAM,CAAC,WAAW,UAAU,MAAM;EACrD,KACC,QAAQ,KAAK,CAAC,OAAO,UAAU,GAAG,KAAK,OAAO,GAAG,MAAM,CAAC,CAAC,KAAK,IAAI,GAClE,OAAO,IACR;CACD;CACA,MACC,SAAS,EAAE,IAAI,sDAAsD,IAAI,UAC1E;CACA,IAAI,QAAQ,QAAQ,WAAW;AAChC"}