inai-react-components 0.1.6 → 1.2.1

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 (62) hide show
  1. package/README.md +80 -0
  2. package/dist/commands/add.d.ts +39 -5
  3. package/dist/commands/add.d.ts.map +1 -1
  4. package/dist/commands/add.js +415 -81
  5. package/dist/commands/diff.d.ts +6 -0
  6. package/dist/commands/diff.d.ts.map +1 -1
  7. package/dist/commands/diff.js +92 -20
  8. package/dist/commands/init.d.ts +6 -3
  9. package/dist/commands/init.d.ts.map +1 -1
  10. package/dist/commands/init.js +33 -26
  11. package/dist/commands/mcp.d.ts +123 -0
  12. package/dist/commands/mcp.d.ts.map +1 -0
  13. package/dist/commands/mcp.js +289 -0
  14. package/dist/commands/migrate.d.ts +41 -0
  15. package/dist/commands/migrate.d.ts.map +1 -0
  16. package/dist/commands/migrate.js +139 -0
  17. package/dist/commands/registries.d.ts +46 -0
  18. package/dist/commands/registries.d.ts.map +1 -0
  19. package/dist/commands/registries.js +152 -0
  20. package/dist/commands/remove.d.ts +11 -0
  21. package/dist/commands/remove.d.ts.map +1 -0
  22. package/dist/commands/remove.js +170 -0
  23. package/dist/commands/schema.d.ts +16 -0
  24. package/dist/commands/schema.d.ts.map +1 -0
  25. package/dist/commands/schema.js +32 -0
  26. package/dist/commands/status.d.ts +32 -3
  27. package/dist/commands/status.d.ts.map +1 -1
  28. package/dist/commands/status.js +148 -25
  29. package/dist/commands/theme.d.ts.map +1 -1
  30. package/dist/commands/theme.js +3 -17
  31. package/dist/commands/update.d.ts +18 -1
  32. package/dist/commands/update.d.ts.map +1 -1
  33. package/dist/commands/update.js +195 -5
  34. package/dist/index.js +76 -5
  35. package/dist/schemas/registry-config.schema.json +62 -0
  36. package/dist/schemas/registry-item.schema.json +63 -0
  37. package/dist/schemas/registry.schema.json +15 -0
  38. package/dist/types/registry.d.ts +50 -0
  39. package/dist/types/registry.d.ts.map +1 -0
  40. package/dist/types/registry.js +10 -0
  41. package/dist/utils/auto-install.d.ts +11 -0
  42. package/dist/utils/auto-install.d.ts.map +1 -0
  43. package/dist/utils/auto-install.js +29 -0
  44. package/dist/utils/framework-detect.d.ts +15 -0
  45. package/dist/utils/framework-detect.d.ts.map +1 -0
  46. package/dist/utils/framework-detect.js +90 -0
  47. package/dist/utils/fuzzy-search.d.ts +16 -0
  48. package/dist/utils/fuzzy-search.d.ts.map +1 -0
  49. package/dist/utils/fuzzy-search.js +67 -0
  50. package/dist/utils/registry-config.d.ts +27 -0
  51. package/dist/utils/registry-config.d.ts.map +1 -0
  52. package/dist/utils/registry-config.js +94 -0
  53. package/dist/utils/registry-resolver.d.ts +26 -0
  54. package/dist/utils/registry-resolver.d.ts.map +1 -1
  55. package/dist/utils/registry-resolver.js +134 -10
  56. package/dist/utils/snapshot.d.ts +20 -0
  57. package/dist/utils/snapshot.d.ts.map +1 -0
  58. package/dist/utils/snapshot.js +32 -0
  59. package/dist/utils/themes.d.ts +17 -0
  60. package/dist/utils/themes.d.ts.map +1 -0
  61. package/dist/utils/themes.js +49 -0
  62. package/package.json +12 -3
@@ -2,33 +2,80 @@ import fs from "node:fs";
2
2
  import path from "node:path";
3
3
  import chalk from "chalk";
4
4
  import ora from "ora";
5
+ import { diffLines } from "diff";
5
6
  import { readComponentsJson, readRegistryJson, } from "./status.js";
6
7
  import { resolveRegistryDir } from "../utils/registry-resolver.js";
8
+ const CONTEXT_LINES = 2;
9
+ /**
10
+ * Render a unified-style colored diff between two strings using a real
11
+ * LCS-based algorithm (`diffLines` from the `diff` package). Lines that
12
+ * changed are shown in red/green; unchanged lines are only shown as dim
13
+ * context within `CONTEXT_LINES` of a change.
14
+ */
7
15
  export function computeDiff(localContent, registryContent) {
8
- const localLines = localContent.split("\n");
9
- const registryLines = registryContent.split("\n");
16
+ // `diffLines` reports hunks: each has `value` (the text), and flags
17
+ // `added` (present only in the second arg) or `removed` (present only in
18
+ // the first arg). Neither flag means unchanged.
19
+ // We pass (registryContent, localContent) so that "added" means the
20
+ // local file added a line vs the registry (green +), and "removed" means
21
+ // the line was removed from the registry in the local file (red -).
22
+ const hunks = diffLines(registryContent, localContent);
23
+ const hasChanges = hunks.some((h) => h.added || h.removed);
24
+ if (!hasChanges) {
25
+ return chalk.green("No differences found. Component is up to date.");
26
+ }
10
27
  const output = [];
11
- const maxLen = Math.max(localLines.length, registryLines.length);
12
- let hasChanges = false;
13
- for (let i = 0; i < maxLen; i++) {
14
- const localLine = localLines[i];
15
- const registryLine = registryLines[i];
16
- if (localLine === registryLine) {
17
- output.push(chalk.dim(` ${localLine ?? ""}`));
28
+ for (let i = 0; i < hunks.length; i++) {
29
+ const hunk = hunks[i];
30
+ const lines = hunk.value.replace(/\n$/, "").split("\n");
31
+ if (hunk.added) {
32
+ for (const line of lines) {
33
+ output.push(chalk.green(`+ ${line}`));
34
+ }
35
+ }
36
+ else if (hunk.removed) {
37
+ for (const line of lines) {
38
+ output.push(chalk.red(`- ${line}`));
39
+ }
18
40
  }
19
41
  else {
20
- hasChanges = true;
21
- if (registryLine !== undefined) {
22
- output.push(chalk.red(`- ${registryLine}`));
42
+ // Unchanged hunk — keep only CONTEXT_LINES around neighboring changes.
43
+ const prevChanged = i > 0 && (hunks[i - 1].added || hunks[i - 1].removed);
44
+ const nextChanged = i < hunks.length - 1 && (hunks[i + 1].added || hunks[i + 1].removed);
45
+ if (!prevChanged && !nextChanged) {
46
+ continue;
47
+ }
48
+ if (prevChanged && nextChanged && lines.length > CONTEXT_LINES * 2) {
49
+ // Show trailing context from previous change, a separator, then
50
+ // leading context for next change.
51
+ for (let j = 0; j < CONTEXT_LINES; j++) {
52
+ output.push(chalk.dim(` ${lines[j]}`));
53
+ }
54
+ output.push(chalk.dim(" ..."));
55
+ for (let j = lines.length - CONTEXT_LINES; j < lines.length; j++) {
56
+ output.push(chalk.dim(` ${lines[j]}`));
57
+ }
23
58
  }
24
- if (localLine !== undefined) {
25
- output.push(chalk.green(`+ ${localLine}`));
59
+ else if (prevChanged) {
60
+ const end = Math.min(lines.length, CONTEXT_LINES);
61
+ for (let j = 0; j < end; j++) {
62
+ output.push(chalk.dim(` ${lines[j]}`));
63
+ }
64
+ if (lines.length > CONTEXT_LINES) {
65
+ output.push(chalk.dim(" ..."));
66
+ }
67
+ }
68
+ else if (nextChanged) {
69
+ const start = Math.max(0, lines.length - CONTEXT_LINES);
70
+ if (start > 0) {
71
+ output.push(chalk.dim(" ..."));
72
+ }
73
+ for (let j = start; j < lines.length; j++) {
74
+ output.push(chalk.dim(` ${lines[j]}`));
75
+ }
26
76
  }
27
77
  }
28
78
  }
29
- if (!hasChanges) {
30
- return chalk.green("No differences found. Component is up to date.");
31
- }
32
79
  return output.join("\n");
33
80
  }
34
81
  export function findComponentInRegistry(registryPath, componentName) {
@@ -42,6 +89,29 @@ export function findComponentInRegistry(registryPath, componentName) {
42
89
  ];
43
90
  return allItems.find((c) => c.name === componentName) ?? null;
44
91
  }
92
+ /**
93
+ * Map a registry component to the alias slot that should hold its local copy.
94
+ * Fixes the earlier bug where `diff` always assumed `aliases.components`.
95
+ */
96
+ function getLocalAliasDir(component, componentsJson) {
97
+ const type = component.type.toLowerCase();
98
+ if (type === "block") {
99
+ return componentsJson.aliases.blocks.replace(/^@\//, "src/");
100
+ }
101
+ if (type === "template") {
102
+ // ComponentsJsonFile doesn't officially type `aliases.templates`, but
103
+ // it may be present in user config — fall back to blocks/templates.
104
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
105
+ const templatesAlias = componentsJson.aliases.templates;
106
+ if (templatesAlias) {
107
+ return templatesAlias.replace(/^@\//, "src/");
108
+ }
109
+ const blocksDir = componentsJson.aliases.blocks.replace(/^@\//, "src/");
110
+ const parent = path.dirname(blocksDir);
111
+ return path.join(parent, "templates");
112
+ }
113
+ return componentsJson.aliases.components.replace(/^@\//, "src/");
114
+ }
45
115
  export async function runDiff(componentName, rootDir) {
46
116
  const componentsJson = readComponentsJson(rootDir);
47
117
  if (!componentsJson) {
@@ -57,11 +127,14 @@ export async function runDiff(componentName, rootDir) {
57
127
  return chalk.yellow(`Component "${componentName}" has no files in the registry.`);
58
128
  }
59
129
  const results = [];
130
+ const localComponentDir = getLocalAliasDir(registryComponent, componentsJson);
131
+ const isMultiFile = registryComponent.type === "block" || registryComponent.type === "template";
60
132
  for (const filePath of registryComponent.files) {
61
133
  const registryFilePath = path.join(registryDir, filePath);
62
- const localComponentDir = componentsJson.aliases.components.replace(/^@\//, "src/");
63
134
  const fileName = path.basename(filePath);
64
- const localFilePath = path.join(rootDir, localComponentDir, fileName);
135
+ const localFilePath = isMultiFile
136
+ ? path.join(rootDir, localComponentDir, componentName, fileName)
137
+ : path.join(rootDir, localComponentDir, fileName);
65
138
  results.push(chalk.bold(`\nDiff for ${fileName}:`));
66
139
  results.push(chalk.dim("─".repeat(60)));
67
140
  if (!fs.existsSync(registryFilePath)) {
@@ -71,7 +144,6 @@ export async function runDiff(componentName, rootDir) {
71
144
  const registryContent = fs.readFileSync(registryFilePath, "utf-8");
72
145
  if (!fs.existsSync(localFilePath)) {
73
146
  results.push(chalk.yellow(`Local file not found at ${localComponentDir}/${fileName}. Component may not be installed.`));
74
- // Show what registry has as all additions
75
147
  const lines = registryContent.split("\n");
76
148
  for (const line of lines) {
77
149
  results.push(chalk.green(`+ ${line}`));
@@ -1,5 +1,5 @@
1
- declare const AVAILABLE_THEMES: readonly ["monday", "linear", "notion", "vercel", "inai", "anthropic", "shadcn-default", "shadcn-blue", "shadcn-green", "shadcn-orange", "shadcn-red", "shadcn-rose", "shadcn-violet", "shadcn-yellow"];
2
- type Theme = (typeof AVAILABLE_THEMES)[number];
1
+ import { type Framework } from "../utils/framework-detect.js";
2
+ type Theme = string;
3
3
  declare const FONT_PRESETS: readonly [{
4
4
  readonly name: "outfit";
5
5
  readonly label: "Outfit";
@@ -227,11 +227,14 @@ export interface InitConfig {
227
227
  tanstackQuery: boolean;
228
228
  tanstackForm: boolean;
229
229
  tanstackTable: boolean;
230
+ framework?: Framework;
231
+ cssEntryPoint?: string;
230
232
  }
231
233
  export interface ComponentsJson {
232
234
  $schema: string;
233
235
  registrySource?: string;
234
236
  style: string;
237
+ framework?: Framework;
235
238
  tailwind: {
236
239
  config: string;
237
240
  css: string;
@@ -254,7 +257,7 @@ export interface ComponentsJson {
254
257
  table: boolean;
255
258
  };
256
259
  }
257
- export declare function promptInitConfig(registryDir?: string): Promise<InitConfig | null>;
260
+ export declare function promptInitConfig(registryDir?: string, framework?: Framework): Promise<InitConfig | null>;
258
261
  export declare function buildComponentsJson(config: InitConfig, repoUrl?: string): ComponentsJson;
259
262
  export declare function getCnTemplate(): string;
260
263
  export declare function getLocalTailwindCssTemplate(theme: Theme, fontBody: FontPreset, fontHeading: FontPreset, radius: number): string;
@@ -1 +1 @@
1
- {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAOA,OAAO,EAIL,KAAK,SAAS,EACf,MAAM,8BAA8B,CAAC;AAGtC,KAAK,KAAK,GAAG,MAAM,CAAC;AAEpB,QAAA,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA4DR,CAAC;AACX,KAAK,UAAU,GAAG,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC;AAUxD,MAAM,WAAW,UAAU;IACzB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,KAAK,CAAC;IACb,QAAQ,EAAE,UAAU,CAAC;IACrB,WAAW,EAAE,UAAU,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,OAAO,CAAC;IACxB,aAAa,EAAE,OAAO,CAAC;IACvB,YAAY,EAAE,OAAO,CAAC;IACtB,aAAa,EAAE,OAAO,CAAC;IACvB,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,QAAQ,EAAE;QACR,MAAM,EAAE,MAAM,CAAC;QACf,GAAG,EAAE,MAAM,CAAC;KACb,CAAC;IACF,OAAO,EAAE;QACP,UAAU,EAAE,MAAM,CAAC;QACnB,MAAM,EAAE,MAAM,CAAC;QACf,KAAK,EAAE,MAAM,CAAC;KACf,CAAC;IACF,KAAK,EAAE,KAAK,CAAC;IACb,IAAI,EAAE;QACJ,IAAI,EAAE,UAAU,CAAC;QACjB,OAAO,EAAE,UAAU,CAAC;KACrB,CAAC;IACF,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE;QACR,MAAM,EAAE,OAAO,CAAC;QAChB,KAAK,EAAE,OAAO,CAAC;QACf,IAAI,EAAE,OAAO,CAAC;QACd,KAAK,EAAE,OAAO,CAAC;KAChB,CAAC;CACH;AAgBD,wBAAsB,gBAAgB,CACpC,WAAW,CAAC,EAAE,MAAM,EACpB,SAAS,CAAC,EAAE,SAAS,GACpB,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAoG5B;AAED,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,UAAU,EAClB,OAAO,CAAC,EAAE,MAAM,GACf,cAAc,CAmChB;AAED,wBAAgB,aAAa,IAAI,MAAM,CAQtC;AAOD,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAc/H;AAED,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAahI;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAoBpE;AAwFD,wBAAsB,OAAO,CAC3B,MAAM,EAAE,UAAU,EAClB,SAAS,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,YAAY,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,CA4CvD;AAED,wBAAsB,WAAW,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA+DjE"}
@@ -4,22 +4,9 @@ import chalk from "chalk";
4
4
  import ora from "ora";
5
5
  import prompts from "prompts";
6
6
  import { cloneRegistry, getCacheDir } from "../utils/registry-resolver.js";
7
- const AVAILABLE_THEMES = [
8
- "monday",
9
- "linear",
10
- "notion",
11
- "vercel",
12
- "inai",
13
- "anthropic",
14
- "shadcn-default",
15
- "shadcn-blue",
16
- "shadcn-green",
17
- "shadcn-orange",
18
- "shadcn-red",
19
- "shadcn-rose",
20
- "shadcn-violet",
21
- "shadcn-yellow",
22
- ];
7
+ import { THEME_NAMES } from "../utils/themes.js";
8
+ import { detectFramework, frameworkLabel, getCssEntryPoint, } from "../utils/framework-detect.js";
9
+ const AVAILABLE_THEMES = THEME_NAMES;
23
10
  const FONT_PRESETS = [
24
11
  // Sans-serif — geometric & modern
25
12
  { name: "outfit", label: "Outfit", family: "'Outfit', system-ui, sans-serif" },
@@ -101,8 +88,11 @@ function discoverThemes(registryDir) {
101
88
  }
102
89
  return [...AVAILABLE_THEMES];
103
90
  }
104
- export async function promptInitConfig(registryDir) {
91
+ export async function promptInitConfig(registryDir, framework) {
105
92
  const themes = discoverThemes(registryDir);
93
+ const defaultCssEntry = framework
94
+ ? getCssEntryPoint(framework)
95
+ : "src/index.css";
106
96
  const response = await prompts([
107
97
  {
108
98
  type: "text",
@@ -188,15 +178,19 @@ export async function promptInitConfig(registryDir) {
188
178
  if (!response.componentPath) {
189
179
  return null;
190
180
  }
191
- return response;
181
+ const config = response;
182
+ config.framework = framework;
183
+ config.cssEntryPoint = defaultCssEntry;
184
+ return config;
192
185
  }
193
186
  export function buildComponentsJson(config, repoUrl) {
194
187
  const json = {
195
188
  $schema: "https://inai-ui.dev/schema.json",
196
189
  style: "default",
190
+ framework: config.framework,
197
191
  tailwind: {
198
192
  config: "tailwind.config.ts",
199
- css: "src/index.css",
193
+ css: config.cssEntryPoint ?? "src/index.css",
200
194
  },
201
195
  aliases: {
202
196
  components: config.importAlias,
@@ -238,7 +232,8 @@ function getFontFamily(font) {
238
232
  }
239
233
  export function getLocalTailwindCssTemplate(theme, fontBody, fontHeading, radius) {
240
234
  return `@import "tailwindcss";
241
- @import "./styles/tokens/index.css";
235
+ @import "./styles/tokens/primitives/colors.css";
236
+ @import "./styles/tokens/base.css";
242
237
  @import "./styles/tokens/themes/${theme}.css";
243
238
  @import "./styles/tokens/presets/typography.css";
244
239
  @import "./styles/tokens/presets/animations.css";
@@ -308,13 +303,23 @@ function copyTokensToProject(registryDir, targetDir, theme) {
308
303
  return copied;
309
304
  fs.mkdirSync(tokensDest, { recursive: true });
310
305
  // Copy base files
311
- for (const file of ["base.css", "index.css"]) {
306
+ for (const file of ["base.css"]) {
312
307
  const src = path.join(tokensSrc, file);
313
308
  if (fs.existsSync(src)) {
314
309
  fs.copyFileSync(src, path.join(tokensDest, file));
315
310
  copied.push(`src/styles/tokens/${file}`);
316
311
  }
317
312
  }
313
+ // Copy primitives (color scales referenced by all themes)
314
+ const primitivesSrc = path.join(tokensSrc, "primitives");
315
+ const primitivesDest = path.join(tokensDest, "primitives");
316
+ if (fs.existsSync(primitivesSrc)) {
317
+ const primitiveCopied = copyDirRecursive(primitivesSrc, primitivesDest);
318
+ for (const file of primitiveCopied) {
319
+ const rel = path.relative(targetDir, file);
320
+ copied.push(rel);
321
+ }
322
+ }
318
323
  // Copy selected theme (normalized so it applies without data-theme attribute)
319
324
  const themesSrc = path.join(tokensSrc, "themes");
320
325
  const themesDest = path.join(tokensDest, "themes");
@@ -363,9 +368,9 @@ export async function runInit(config, targetDir, repoUrl) {
363
368
  fs.writeFileSync(cnPath, getCnTemplate());
364
369
  filesCreated.push("src/lib/cn.ts");
365
370
  // 4. Copy tokens and create CSS
366
- const cssDir = path.join(targetDir, "src");
367
- fs.mkdirSync(cssDir, { recursive: true });
368
- const cssPath = path.join(cssDir, "index.css");
371
+ const cssRelPath = config.cssEntryPoint ?? "src/index.css";
372
+ const cssPath = path.join(targetDir, cssRelPath);
373
+ fs.mkdirSync(path.dirname(cssPath), { recursive: true });
369
374
  if (repoUrl) {
370
375
  // Remote mode: copy tokens from cached registry
371
376
  const registryDir = getCacheDir();
@@ -377,11 +382,13 @@ export async function runInit(config, targetDir, repoUrl) {
377
382
  // Local mode: reference @company/tokens package
378
383
  fs.writeFileSync(cssPath, getLegacyTailwindCssTemplate(config.theme, config.fontBody, config.fontHeading, config.radius));
379
384
  }
380
- filesCreated.push("src/index.css");
385
+ filesCreated.push(cssRelPath);
381
386
  return { success: true, filesCreated };
382
387
  }
383
388
  export async function initCommand(repoUrl) {
384
389
  console.log(chalk.bold("\nInAI UI - Project Initialization\n"));
390
+ const detectedFramework = detectFramework(process.cwd());
391
+ console.log(chalk.dim(`Detected framework: ${frameworkLabel(detectedFramework)}`));
385
392
  if (repoUrl) {
386
393
  const spinner = ora("Cloning component registry...").start();
387
394
  try {
@@ -397,7 +404,7 @@ export async function initCommand(repoUrl) {
397
404
  }
398
405
  }
399
406
  const registryDir = repoUrl ? getCacheDir() : undefined;
400
- const config = await promptInitConfig(registryDir);
407
+ const config = await promptInitConfig(registryDir, detectedFramework);
401
408
  if (!config) {
402
409
  console.log(chalk.yellow("\nInitialization cancelled."));
403
410
  process.exit(0);
@@ -0,0 +1,123 @@
1
+ /**
2
+ * Print the JSON config fragment that users must drop into their Claude
3
+ * Desktop or Cursor `mcpServers` block. Invoked from `inai-ui mcp init`.
4
+ */
5
+ export declare function printMcpConfig(): void;
6
+ export interface ToolTextResult {
7
+ content: Array<{
8
+ type: "text";
9
+ text: string;
10
+ }>;
11
+ isError?: boolean;
12
+ }
13
+ export declare function handleListComponents(args: {
14
+ category?: string;
15
+ } | undefined, cwd: string): Promise<ToolTextResult>;
16
+ export declare function handleViewComponent(args: {
17
+ name?: string;
18
+ } | undefined, cwd: string): Promise<ToolTextResult>;
19
+ export declare function handleAddComponent(args: {
20
+ name?: string;
21
+ force?: boolean;
22
+ } | undefined, cwd: string): Promise<ToolTextResult>;
23
+ export declare function handleDiffComponent(args: {
24
+ name?: string;
25
+ } | undefined, cwd: string): Promise<ToolTextResult>;
26
+ export declare function handleUpdateComponent(args: {
27
+ name?: string;
28
+ } | undefined, cwd: string): Promise<ToolTextResult>;
29
+ export declare function handleListThemes(): Promise<ToolTextResult>;
30
+ export declare function handleStatus(args: {
31
+ json?: boolean;
32
+ } | undefined, cwd: string): Promise<ToolTextResult>;
33
+ export declare const MCP_TOOLS: readonly [{
34
+ readonly name: "list_components";
35
+ readonly description: "List all available components, blocks and templates in the InAI UI registry.";
36
+ readonly inputSchema: {
37
+ readonly type: "object";
38
+ readonly properties: {
39
+ readonly category: {
40
+ readonly type: "string";
41
+ readonly description: "Optional type filter (e.g. 'component', 'form', 'block').";
42
+ };
43
+ };
44
+ };
45
+ }, {
46
+ readonly name: "view_component";
47
+ readonly description: "View the source code of a component from the registry.";
48
+ readonly inputSchema: {
49
+ readonly type: "object";
50
+ readonly properties: {
51
+ readonly name: {
52
+ readonly type: "string";
53
+ readonly description: "Component name";
54
+ };
55
+ };
56
+ readonly required: readonly ["name"];
57
+ };
58
+ }, {
59
+ readonly name: "add_component";
60
+ readonly description: "Install a component (and its transitive registry dependencies) into the current project.";
61
+ readonly inputSchema: {
62
+ readonly type: "object";
63
+ readonly properties: {
64
+ readonly name: {
65
+ readonly type: "string";
66
+ readonly description: "Component name";
67
+ };
68
+ readonly force: {
69
+ readonly type: "boolean";
70
+ readonly description: "Overwrite existing files without prompting.";
71
+ };
72
+ };
73
+ readonly required: readonly ["name"];
74
+ };
75
+ }, {
76
+ readonly name: "diff_component";
77
+ readonly description: "Show a unified diff between the locally-installed component and the registry version.";
78
+ readonly inputSchema: {
79
+ readonly type: "object";
80
+ readonly properties: {
81
+ readonly name: {
82
+ readonly type: "string";
83
+ readonly description: "Component name";
84
+ };
85
+ };
86
+ readonly required: readonly ["name"];
87
+ };
88
+ }, {
89
+ readonly name: "update_component";
90
+ readonly description: "Update an installed component to the latest registry version using a 3-way merge against the snapshot captured at install time. Emits conflict markers when local and registry edits overlap.";
91
+ readonly inputSchema: {
92
+ readonly type: "object";
93
+ readonly properties: {
94
+ readonly name: {
95
+ readonly type: "string";
96
+ readonly description: "Component name";
97
+ };
98
+ };
99
+ readonly required: readonly ["name"];
100
+ };
101
+ }, {
102
+ readonly name: "list_themes";
103
+ readonly description: "List the available InAI UI themes with their categories and descriptions.";
104
+ readonly inputSchema: {
105
+ readonly type: "object";
106
+ readonly properties: {};
107
+ };
108
+ }, {
109
+ readonly name: "project_status";
110
+ readonly description: "Return the InAI UI project status (HEALTHY / DRIFT / OUTDATED / MISSING per component).";
111
+ readonly inputSchema: {
112
+ readonly type: "object";
113
+ readonly properties: {
114
+ readonly json: {
115
+ readonly type: "boolean";
116
+ readonly description: "Return JSON payload (default true).";
117
+ };
118
+ };
119
+ };
120
+ }];
121
+ export declare function runMcp(cwd?: string): Promise<void>;
122
+ export declare function mcpCommand(subcommand?: "init"): Promise<void>;
123
+ //# sourceMappingURL=mcp.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp.d.ts","sourceRoot":"","sources":["../../src/commands/mcp.ts"],"names":[],"mappings":"AAgCA;;;GAGG;AACH,wBAAgB,cAAc,IAAI,IAAI,CAErC;AAID,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC/C,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AASD,wBAAsB,oBAAoB,CACxC,IAAI,EAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,EACvC,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,cAAc,CAAC,CAKzB;AAED,wBAAsB,mBAAmB,CACvC,IAAI,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,EACnC,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,cAAc,CAAC,CA8BzB;AAED,wBAAsB,kBAAkB,CACtC,IAAI,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,SAAS,EACpD,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,cAAc,CAAC,CAkBzB;AAED,wBAAsB,mBAAmB,CACvC,IAAI,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,EACnC,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,cAAc,CAAC,CAmCzB;AAED,wBAAsB,qBAAqB,CACzC,IAAI,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,EACnC,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,cAAc,CAAC,CAgBzB;AAED,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,cAAc,CAAC,CAEhE;AAED,wBAAsB,YAAY,CAChC,IAAI,EAAE;IAAE,IAAI,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,SAAS,EACpC,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,cAAc,CAAC,CAGzB;AAID,eAAO,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAoFZ,CAAC;AAEX,wBAAsB,MAAM,CAAC,GAAG,GAAE,MAAsB,GAAG,OAAO,CAAC,IAAI,CAAC,CAiEvE;AAED,wBAAsB,UAAU,CAC9B,UAAU,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,IAAI,CAAC,CAMf"}