@layoutdesign/context 0.4.0 → 0.5.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.
package/dist/bin/cli.js CHANGED
@@ -9,6 +9,7 @@ import { listCommand } from "../src/cli/list.js";
9
9
  import { installCommand } from "../src/cli/install.js";
10
10
  import { doctorCommand } from "../src/cli/doctor.js";
11
11
  import { serveLocalCommand } from "../src/cli/serve-local.js";
12
+ import { scanCommand } from "../src/cli/scan.js";
12
13
  const require = createRequire(import.meta.url);
13
14
  const pkg = require("../../package.json");
14
15
  const program = new Command();
@@ -75,5 +76,14 @@ program
75
76
  .action(async (options) => {
76
77
  await doctorCommand(options);
77
78
  });
79
+ program
80
+ .command("scan [path]")
81
+ .description("Scan the codebase for React components and Storybook stories")
82
+ .option("--sync", "Upload results to your Layout project")
83
+ .option("--project <id>", "Layout project ID (auto-detected from .layout/ if not specified)")
84
+ .option("--type <type>", "Scan type: storybook, codebase, or both (default: both)")
85
+ .action(async (targetPath, options) => {
86
+ await scanCommand(targetPath, options);
87
+ });
78
88
  program.parse();
79
89
  //# sourceMappingURL=cli.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../../bin/cli.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../../bin/cli.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEjD,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC/C,MAAM,GAAG,GAAG,OAAO,CAAC,oBAAoB,CAAwB,CAAC;AAEjE,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,gBAAgB,CAAC;KACtB,WAAW,CACV,+DAA+D,CAChE;KACA,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;AAExB,OAAO;KACJ,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CAAC,sDAAsD,CAAC;KACnE,MAAM,CAAC,cAAc,EAAE,kCAAkC,CAAC;KAC1D,MAAM,CAAC,KAAK,EAAE,OAAyB,EAAE,EAAE;IAC1C,MAAM,WAAW,CAAC,OAAO,CAAC,CAAC;AAC7B,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,OAAO,CAAC;KAChB,WAAW,CAAC,wCAAwC,CAAC;KACrD,MAAM,CAAC,KAAK,IAAI,EAAE;IACjB,MAAM,YAAY,EAAE,CAAC;AACvB,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,mBAAmB,CAAC;KAC5B,WAAW,CAAC,0CAA0C,CAAC;KACvD,MAAM,CAAC,KAAK,EAAE,OAAe,EAAE,EAAE;IAChC,MAAM,aAAa,CAAC,OAAO,CAAC,CAAC;AAC/B,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,gBAAgB,CAAC;KACzB,WAAW,CAAC,wCAAwC,CAAC;KACrD,MAAM,CAAC,KAAK,EAAE,OAAe,EAAE,EAAE;IAChC,MAAM,UAAU,CAAC,OAAO,CAAC,CAAC;AAC5B,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CAAC,gCAAgC,CAAC;KAC7C,MAAM,CAAC,KAAK,IAAI,EAAE;IACjB,MAAM,WAAW,EAAE,CAAC;AACtB,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,SAAS,CAAC;KAClB,WAAW,CAAC,uHAAuH,CAAC;KACpI,MAAM,CAAC,iBAAiB,EAAE,mEAAmE,CAAC;KAC9F,MAAM,CAAC,UAAU,EAAE,gEAAgE,CAAC;KACpF,MAAM,CAAC,cAAc,EAAE,qCAAqC,CAAC;KAC7D,MAAM,CAAC,KAAK,EAAE,OAAmE,EAAE,EAAE;IACpF,MAAM,cAAc,CAAC,OAAO,CAAC,CAAC;AAChC,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,oBAAoB,CAAC;KAC7B,WAAW,CAAC,+GAA+G,CAAC;KAC5H,MAAM,CAAC,YAAY,EAAE,8CAA8C,CAAC;KACpE,MAAM,CAAC,SAAS,EAAE,2CAA2C,CAAC;KAC9D,MAAM,CAAC,KAAK,EAAE,UAAkB,EAAE,OAA2C,EAAE,EAAE;IAChF,MAAM,iBAAiB,CAAC,UAAU,EAAE;QAClC,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS;QAC3D,KAAK,EAAE,OAAO,CAAC,KAAK;KACrB,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,QAAQ,CAAC;KACjB,WAAW,CAAC,2DAA2D,CAAC;KACxE,MAAM,CAAC,OAAO,EAAE,kCAAkC,CAAC;KACnD,MAAM,CAAC,WAAW,EAAE,+DAA+D,CAAC;KACpF,MAAM,CAAC,KAAK,EAAE,OAA6C,EAAE,EAAE;IAC9D,MAAM,aAAa,CAAC,OAAO,CAAC,CAAC;AAC/B,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,aAAa,CAAC;KACtB,WAAW,CAAC,8DAA8D,CAAC;KAC3E,MAAM,CAAC,QAAQ,EAAE,uCAAuC,CAAC;KACzD,MAAM,CAAC,gBAAgB,EAAE,kEAAkE,CAAC;KAC5F,MAAM,CAAC,eAAe,EAAE,yDAAyD,CAAC;KAClF,MAAM,CAAC,KAAK,EAAE,UAAmB,EAAE,OAA6D,EAAE,EAAE;IACnG,MAAM,WAAW,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;AACzC,CAAC,CAAC,CAAC;AAEL,OAAO,CAAC,KAAK,EAAE,CAAC"}
@@ -0,0 +1,8 @@
1
+ interface ScanOptions {
2
+ sync?: boolean;
3
+ project?: string;
4
+ type?: string;
5
+ }
6
+ export declare function scanCommand(targetPath?: string, options?: ScanOptions): Promise<void>;
7
+ export {};
8
+ //# sourceMappingURL=scan.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scan.d.ts","sourceRoot":"","sources":["../../../src/cli/scan.ts"],"names":[],"mappings":"AAOA,UAAU,WAAW;IACnB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AA4FD,wBAAsB,WAAW,CAC/B,UAAU,CAAC,EAAE,MAAM,EACnB,OAAO,CAAC,EAAE,WAAW,GACpB,OAAO,CAAC,IAAI,CAAC,CA0Cf"}
@@ -0,0 +1,143 @@
1
+ import { resolve } from "node:path";
2
+ import { readFileSync, existsSync } from "node:fs";
3
+ import chalk from "chalk";
4
+ import { scanCodebase, scanStorybook } from "../integrations/codebase-scan.js";
5
+ import { LAYOUT_DIR } from "../kit/types.js";
6
+ /**
7
+ * Read org and project IDs from the .layout/kit.json manifest.
8
+ * The layoutUrl field looks like: https://layout.design/<org>/<project>/studio
9
+ * or the manifest may have explicit orgId/projectId fields.
10
+ */
11
+ function readProjectContext(rootPath) {
12
+ const manifestPath = resolve(rootPath, LAYOUT_DIR, "kit.json");
13
+ if (!existsSync(manifestPath))
14
+ return {};
15
+ try {
16
+ const manifest = JSON.parse(readFileSync(manifestPath, "utf-8"));
17
+ // Check explicit fields first
18
+ if (manifest.orgId && manifest.projectId) {
19
+ return { orgId: manifest.orgId, projectId: manifest.projectId, apiBase: manifest.apiBase };
20
+ }
21
+ // Try to parse from layoutUrl
22
+ if (manifest.layoutUrl) {
23
+ const url = new URL(manifest.layoutUrl);
24
+ const parts = url.pathname.split("/").filter(Boolean);
25
+ // Expected: /<org>/<project>/studio or /<org>/<project>
26
+ if (parts.length >= 2) {
27
+ return { orgId: parts[0], projectId: parts[1] };
28
+ }
29
+ }
30
+ }
31
+ catch {
32
+ // Ignore parse errors
33
+ }
34
+ return {};
35
+ }
36
+ function formatScanResult(result) {
37
+ const withStories = result.components.filter((c) => c.storybook);
38
+ console.log();
39
+ console.log(chalk.bold(`Scan complete`), chalk.dim(`(${result.durationMs}ms)`));
40
+ console.log();
41
+ console.log(` ${chalk.green(String(result.components.length))} components found`, result.storybookStories.length > 0
42
+ ? chalk.dim(`(${withStories.length} with Storybook stories)`)
43
+ : "");
44
+ console.log(` ${chalk.green(String(result.storybookStories.length))} Storybook stories`);
45
+ console.log(` ${chalk.dim(String(result.filesScanned))} files scanned`);
46
+ if (result.unmatchedStories.length > 0) {
47
+ console.log(` ${chalk.yellow(String(result.unmatchedStories.length))} stories without matching components`);
48
+ }
49
+ // Show top components
50
+ if (result.components.length > 0) {
51
+ console.log();
52
+ console.log(chalk.bold("Components:"));
53
+ const display = result.components.slice(0, 20);
54
+ for (const comp of display) {
55
+ const propsCount = comp.props.length;
56
+ const storyIcon = comp.storybook ? chalk.blue(" [stories]") : "";
57
+ const refIcon = comp.usesForwardRef ? chalk.dim(" (forwardRef)") : "";
58
+ const propsLabel = propsCount > 0 ? chalk.dim(` ${propsCount} props`) : "";
59
+ console.log(` ${chalk.cyan(comp.name)}${propsLabel}${refIcon}${storyIcon}`, chalk.dim(`— ${comp.filePath}`));
60
+ }
61
+ if (result.components.length > 20) {
62
+ console.log(chalk.dim(` ... and ${result.components.length - 20} more`));
63
+ }
64
+ }
65
+ }
66
+ export async function scanCommand(targetPath, options) {
67
+ const rootPath = resolve(targetPath ?? process.cwd());
68
+ const scanType = options?.type ?? "both";
69
+ console.log();
70
+ console.log(chalk.bold("Layout Codebase Scanner"), chalk.dim(`— ${rootPath}`));
71
+ if (scanType === "storybook") {
72
+ console.log(chalk.dim(" Scanning for Storybook stories only..."));
73
+ const stories = await scanStorybook(rootPath);
74
+ console.log();
75
+ console.log(` ${chalk.green(String(stories.length))} Storybook stories found`);
76
+ for (const story of stories.slice(0, 20)) {
77
+ const storyNames = story.stories.map((s) => s.name).join(", ");
78
+ console.log(` ${chalk.cyan(story.componentName)}`, chalk.dim(`— ${storyNames}`), chalk.dim(`— ${story.filePath}`));
79
+ }
80
+ if (stories.length > 20) {
81
+ console.log(chalk.dim(` ... and ${stories.length - 20} more`));
82
+ }
83
+ return;
84
+ }
85
+ console.log(chalk.dim(" Scanning..."));
86
+ const result = await scanCodebase(rootPath);
87
+ formatScanResult(result);
88
+ // Sync to Layout web app
89
+ if (options?.sync) {
90
+ await syncResults(rootPath, result, options.project);
91
+ }
92
+ }
93
+ async function syncResults(rootPath, result, projectArg) {
94
+ console.log();
95
+ const context = readProjectContext(rootPath);
96
+ const orgId = context.orgId;
97
+ const projectId = projectArg ?? context.projectId;
98
+ const apiBase = (context.apiBase ?? "https://layout.design").replace(/\/$/, "");
99
+ if (!orgId || !projectId) {
100
+ console.log(chalk.red("Error:"), "Could not determine project to sync to.");
101
+ console.log(chalk.dim(" Add orgId and projectId to .layout/kit.json, or use --project <id>"));
102
+ return;
103
+ }
104
+ const url = `${apiBase}/api/organizations/${orgId}/projects/${projectId}/scan-results`;
105
+ console.log(chalk.dim(` Syncing to ${url}...`));
106
+ try {
107
+ const apiKey = process.env.LAYOUT_API_KEY;
108
+ const headers = { "Content-Type": "application/json" };
109
+ if (apiKey)
110
+ headers["Authorization"] = `Bearer ${apiKey}`;
111
+ const response = await fetch(url, {
112
+ method: "POST",
113
+ headers,
114
+ body: JSON.stringify({
115
+ components: result.components.map((c) => ({
116
+ name: c.name,
117
+ filePath: c.filePath,
118
+ exportType: c.exportType,
119
+ propsType: c.propsInterfaceName,
120
+ props: c.props.map((p) => p.name),
121
+ usesForwardRef: c.usesForwardRef,
122
+ importPath: c.filePath.replace(/\.(tsx?|jsx?)$/, "").replace(/\/index$/, ""),
123
+ source: c.storybook ? "storybook" : "codebase",
124
+ stories: c.storybook?.stories.map((s) => s.name),
125
+ args: c.storybook?.args,
126
+ })),
127
+ source: "cli",
128
+ }),
129
+ });
130
+ if (response.ok) {
131
+ console.log(chalk.green(" Synced successfully."));
132
+ }
133
+ else {
134
+ const text = await response.text();
135
+ console.log(chalk.red(" Sync failed:"), `${response.status} ${text}`);
136
+ }
137
+ }
138
+ catch (err) {
139
+ const msg = err instanceof Error ? err.message : String(err);
140
+ console.log(chalk.red(" Sync failed:"), msg);
141
+ }
142
+ }
143
+ //# sourceMappingURL=scan.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scan.js","sourceRoot":"","sources":["../../../src/cli/scan.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,46 @@
1
+ import { type StoryComponentMeta } from "./storybook.js";
2
+ export interface ScannedProp {
3
+ name: string;
4
+ type?: string;
5
+ optional?: boolean;
6
+ }
7
+ export interface ScannedComponent {
8
+ /** PascalCase component name */
9
+ name: string;
10
+ /** File path relative to the scan root */
11
+ filePath: string;
12
+ /** How the component is exported */
13
+ exportType: "named" | "default";
14
+ /** Props interface/type name if detected */
15
+ propsInterfaceName?: string;
16
+ /** Individual prop keys extracted from the interface */
17
+ props: ScannedProp[];
18
+ /** Whether the component uses forwardRef */
19
+ usesForwardRef: boolean;
20
+ /** Storybook metadata if a matching .stories file was found */
21
+ storybook?: StoryComponentMeta;
22
+ }
23
+ export interface ScanResult {
24
+ /** Root directory that was scanned */
25
+ rootPath: string;
26
+ /** All detected React components */
27
+ components: ScannedComponent[];
28
+ /** Storybook stories that matched a component */
29
+ storybookStories: StoryComponentMeta[];
30
+ /** Stories that did not match any scanned component */
31
+ unmatchedStories: StoryComponentMeta[];
32
+ /** Total files scanned */
33
+ filesScanned: number;
34
+ /** Scan duration in milliseconds */
35
+ durationMs: number;
36
+ }
37
+ /**
38
+ * Scan a directory for React components and Storybook stories.
39
+ * Returns structured results with component metadata and story associations.
40
+ */
41
+ export declare function scanCodebase(rootPath: string): Promise<ScanResult>;
42
+ /**
43
+ * Scan for Storybook stories only.
44
+ */
45
+ export declare function scanStorybook(rootPath: string): Promise<StoryComponentMeta[]>;
46
+ //# sourceMappingURL=codebase-scan.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codebase-scan.d.ts","sourceRoot":"","sources":["../../../src/integrations/codebase-scan.ts"],"names":[],"mappings":"AAEA,OAAO,EAEL,KAAK,kBAAkB,EACxB,MAAM,gBAAgB,CAAC;AAIxB,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,gBAAgB;IAC/B,gCAAgC;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,0CAA0C;IAC1C,QAAQ,EAAE,MAAM,CAAC;IACjB,oCAAoC;IACpC,UAAU,EAAE,OAAO,GAAG,SAAS,CAAC;IAChC,4CAA4C;IAC5C,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,wDAAwD;IACxD,KAAK,EAAE,WAAW,EAAE,CAAC;IACrB,4CAA4C;IAC5C,cAAc,EAAE,OAAO,CAAC;IACxB,+DAA+D;IAC/D,SAAS,CAAC,EAAE,kBAAkB,CAAC;CAChC;AAED,MAAM,WAAW,UAAU;IACzB,sCAAsC;IACtC,QAAQ,EAAE,MAAM,CAAC;IACjB,oCAAoC;IACpC,UAAU,EAAE,gBAAgB,EAAE,CAAC;IAC/B,iDAAiD;IACjD,gBAAgB,EAAE,kBAAkB,EAAE,CAAC;IACvC,uDAAuD;IACvD,gBAAgB,EAAE,kBAAkB,EAAE,CAAC;IACvC,0BAA0B;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB,oCAAoC;IACpC,UAAU,EAAE,MAAM,CAAC;CACpB;AAqLD;;;GAGG;AACH,wBAAsB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAuExE;AAED;;GAEG;AACH,wBAAsB,aAAa,CACjC,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,kBAAkB,EAAE,CAAC,CAkB/B"}
@@ -0,0 +1,231 @@
1
+ import { readFile, readdir } from "node:fs/promises";
2
+ import { join, relative, extname } from "node:path";
3
+ import { parseStoryFromPath, } from "./storybook.js";
4
+ // ── Constants ──────────────────────────────────────────────────────────────
5
+ const SKIP_DIRS = new Set([
6
+ "node_modules",
7
+ ".next",
8
+ ".nuxt",
9
+ "dist",
10
+ "build",
11
+ "out",
12
+ ".git",
13
+ ".layout",
14
+ ".superduper",
15
+ "coverage",
16
+ "__tests__",
17
+ "__mocks__",
18
+ ".turbo",
19
+ ".cache",
20
+ ".vercel",
21
+ ".output",
22
+ ]);
23
+ const COMPONENT_EXTENSIONS = new Set([".tsx", ".jsx"]);
24
+ const STORY_SUFFIXES = [".stories.ts", ".stories.tsx", ".stories.js", ".stories.jsx"];
25
+ // ── Regex patterns ─────────────────────────────────────────────────────────
26
+ // Named export: `export function Button(` or `export const Button =` or `export const Button: FC`
27
+ const NAMED_FUNCTION_RE = /export\s+function\s+([A-Z]\w+)\s*(?:<[^>]*>)?\s*\(/g;
28
+ const NAMED_CONST_RE = /export\s+const\s+([A-Z]\w+)\s*(?::\s*(?:React\.)?(?:FC|FunctionComponent|ComponentType)(?:<[^>]*>)?\s*)?=\s*/g;
29
+ // Default export: `export default function Button(`
30
+ const DEFAULT_FUNCTION_RE = /export\s+default\s+function\s+([A-Z]\w+)\s*(?:<[^>]*>)?\s*\(/g;
31
+ // forwardRef: `export const Button = forwardRef<` or `React.forwardRef<`
32
+ const FORWARD_REF_RE = /export\s+const\s+([A-Z]\w+)\s*=\s*(?:React\.)?forwardRef/g;
33
+ // Grouped export: `export { Button, Card, buttonVariants }` — capture PascalCase names only
34
+ const GROUPED_EXPORT_RE = /export\s*\{([^}]+)\}/g;
35
+ // Props interface: `interface ButtonProps {` or `type ButtonProps = {`
36
+ const PROPS_INTERFACE_RE = /(?:interface|type)\s+(\w+Props)\s*(?:=\s*)?\{([\s\S]*?)\n\}/g;
37
+ // Individual prop from interface body: ` label: string;` or ` disabled?: boolean;`
38
+ const PROP_LINE_RE = /^\s+(\w+)(\?)?\s*:\s*([^;]+)/gm;
39
+ // ── File discovery ─────────────────────────────────────────────────────────
40
+ function isStoryFile(filePath) {
41
+ return STORY_SUFFIXES.some((suffix) => filePath.endsWith(suffix));
42
+ }
43
+ /**
44
+ * Recursively walk a directory, yielding file paths.
45
+ * Skips directories in the SKIP_DIRS set.
46
+ */
47
+ async function* walkDir(dir) {
48
+ let entries;
49
+ try {
50
+ entries = await readdir(dir, { withFileTypes: true });
51
+ }
52
+ catch {
53
+ return;
54
+ }
55
+ for (const entry of entries) {
56
+ const fullPath = join(dir, entry.name);
57
+ if (entry.isDirectory()) {
58
+ if (!SKIP_DIRS.has(entry.name) && !entry.name.startsWith(".")) {
59
+ yield* walkDir(fullPath);
60
+ }
61
+ }
62
+ else if (entry.isFile()) {
63
+ yield fullPath;
64
+ }
65
+ }
66
+ }
67
+ // ── Component extraction ───────────────────────────────────────────────────
68
+ function extractComponents(content, filePath) {
69
+ const components = [];
70
+ const seen = new Set();
71
+ // Extract all props interfaces/types from the file
72
+ const propsMap = new Map();
73
+ let propsMatch;
74
+ PROPS_INTERFACE_RE.lastIndex = 0;
75
+ while ((propsMatch = PROPS_INTERFACE_RE.exec(content)) !== null) {
76
+ const interfaceName = propsMatch[1];
77
+ const body = propsMatch[2] ?? "";
78
+ const props = [];
79
+ let propLineMatch;
80
+ PROP_LINE_RE.lastIndex = 0;
81
+ while ((propLineMatch = PROP_LINE_RE.exec(body)) !== null) {
82
+ props.push({
83
+ name: propLineMatch[1],
84
+ optional: propLineMatch[2] === "?",
85
+ type: propLineMatch[3]?.trim(),
86
+ });
87
+ }
88
+ propsMap.set(interfaceName, props);
89
+ }
90
+ function addComponent(name, exportType, usesForwardRef) {
91
+ if (seen.has(name))
92
+ return;
93
+ seen.add(name);
94
+ // Try to find a matching props interface
95
+ const propsInterfaceName = `${name}Props`;
96
+ const props = propsMap.get(propsInterfaceName) ?? [];
97
+ components.push({
98
+ name,
99
+ filePath,
100
+ exportType,
101
+ propsInterfaceName: propsMap.has(propsInterfaceName)
102
+ ? propsInterfaceName
103
+ : undefined,
104
+ props,
105
+ usesForwardRef,
106
+ });
107
+ }
108
+ // Named function exports
109
+ let match;
110
+ NAMED_FUNCTION_RE.lastIndex = 0;
111
+ while ((match = NAMED_FUNCTION_RE.exec(content)) !== null) {
112
+ addComponent(match[1], "named", false);
113
+ }
114
+ // Named const exports (FC, arrow functions)
115
+ NAMED_CONST_RE.lastIndex = 0;
116
+ while ((match = NAMED_CONST_RE.exec(content)) !== null) {
117
+ addComponent(match[1], "named", false);
118
+ }
119
+ // Default function exports
120
+ DEFAULT_FUNCTION_RE.lastIndex = 0;
121
+ while ((match = DEFAULT_FUNCTION_RE.exec(content)) !== null) {
122
+ addComponent(match[1], "default", false);
123
+ }
124
+ // forwardRef exports
125
+ FORWARD_REF_RE.lastIndex = 0;
126
+ while ((match = FORWARD_REF_RE.exec(content)) !== null) {
127
+ addComponent(match[1], "named", true);
128
+ }
129
+ // Grouped exports: `export { Button, Card, buttonVariants }`
130
+ // Only pick PascalCase names (components), skip camelCase (utilities)
131
+ GROUPED_EXPORT_RE.lastIndex = 0;
132
+ while ((match = GROUPED_EXPORT_RE.exec(content)) !== null) {
133
+ const names = match[1].split(",").map((n) => n.trim().split(/\s+as\s+/).pop().trim());
134
+ for (const name of names) {
135
+ if (/^[A-Z][a-zA-Z0-9]+$/.test(name)) {
136
+ addComponent(name, "named", false);
137
+ }
138
+ }
139
+ }
140
+ return components;
141
+ }
142
+ // ── Main scanner ───────────────────────────────────────────────────────────
143
+ /**
144
+ * Scan a directory for React components and Storybook stories.
145
+ * Returns structured results with component metadata and story associations.
146
+ */
147
+ export async function scanCodebase(rootPath) {
148
+ const startTime = Date.now();
149
+ const componentFiles = [];
150
+ const storyFiles = [];
151
+ let filesScanned = 0;
152
+ // Collect all relevant files
153
+ for await (const filePath of walkDir(rootPath)) {
154
+ filesScanned++;
155
+ const ext = extname(filePath);
156
+ if (isStoryFile(filePath)) {
157
+ storyFiles.push(filePath);
158
+ }
159
+ else if (COMPONENT_EXTENSIONS.has(ext)) {
160
+ componentFiles.push(filePath);
161
+ }
162
+ }
163
+ // Parse all component files
164
+ const allComponents = [];
165
+ for (const filePath of componentFiles) {
166
+ try {
167
+ const content = await readFile(filePath, "utf-8");
168
+ const relPath = relative(rootPath, filePath);
169
+ const found = extractComponents(content, relPath);
170
+ allComponents.push(...found);
171
+ }
172
+ catch {
173
+ // Skip unreadable files
174
+ }
175
+ }
176
+ // Parse all story files
177
+ const allStories = [];
178
+ for (const filePath of storyFiles) {
179
+ try {
180
+ const relPath = relative(rootPath, filePath);
181
+ const story = await parseStoryFromPath(filePath);
182
+ if (story) {
183
+ // Use relative path in the result
184
+ allStories.push({ ...story, filePath: relPath });
185
+ }
186
+ }
187
+ catch {
188
+ // Skip unreadable files
189
+ }
190
+ }
191
+ // Match stories to components
192
+ const matchedStoryNames = new Set();
193
+ for (const component of allComponents) {
194
+ const matchingStory = allStories.find((s) => s.componentName === component.name);
195
+ if (matchingStory) {
196
+ component.storybook = matchingStory;
197
+ matchedStoryNames.add(matchingStory.componentName);
198
+ }
199
+ }
200
+ const unmatchedStories = allStories.filter((s) => !matchedStoryNames.has(s.componentName));
201
+ return {
202
+ rootPath,
203
+ components: allComponents,
204
+ storybookStories: allStories,
205
+ unmatchedStories,
206
+ filesScanned,
207
+ durationMs: Date.now() - startTime,
208
+ };
209
+ }
210
+ /**
211
+ * Scan for Storybook stories only.
212
+ */
213
+ export async function scanStorybook(rootPath) {
214
+ const stories = [];
215
+ for await (const filePath of walkDir(rootPath)) {
216
+ if (isStoryFile(filePath)) {
217
+ try {
218
+ const relPath = relative(rootPath, filePath);
219
+ const story = await parseStoryFromPath(filePath);
220
+ if (story) {
221
+ stories.push({ ...story, filePath: relPath });
222
+ }
223
+ }
224
+ catch {
225
+ // Skip unreadable files
226
+ }
227
+ }
228
+ }
229
+ return stories;
230
+ }
231
+ //# sourceMappingURL=codebase-scan.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codebase-scan.js","sourceRoot":"","sources":["../../../src/integrations/codebase-scan.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ export interface StoryArg {
2
+ name: string;
3
+ type?: string;
4
+ defaultValue?: string;
5
+ description?: string;
6
+ control?: string;
7
+ options?: string[];
8
+ }
9
+ export interface StoryEntry {
10
+ name: string;
11
+ tags?: string[];
12
+ }
13
+ export interface StoryComponentMeta {
14
+ /** Component name derived from the story title (e.g. "Button" from "Components/Button") */
15
+ componentName: string;
16
+ /** Full title as declared in the story meta */
17
+ title: string;
18
+ /** File path relative to the scan root */
19
+ filePath: string;
20
+ /** Args and argTypes extracted from the default export */
21
+ args: StoryArg[];
22
+ /** Individual stories (named exports) */
23
+ stories: StoryEntry[];
24
+ /** Tags declared on the meta object */
25
+ tags?: string[];
26
+ }
27
+ /**
28
+ * Parse a single Storybook story file and extract component metadata.
29
+ * Uses regex-based extraction (no AST required).
30
+ */
31
+ export declare function parseStoryFile(content: string, filePath: string): StoryComponentMeta | null;
32
+ /**
33
+ * Parse a story file from disk.
34
+ */
35
+ export declare function parseStoryFromPath(filePath: string): Promise<StoryComponentMeta | null>;
36
+ //# sourceMappingURL=storybook.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storybook.d.ts","sourceRoot":"","sources":["../../../src/integrations/storybook.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,MAAM,WAAW,kBAAkB;IACjC,2FAA2F;IAC3F,aAAa,EAAE,MAAM,CAAC;IACtB,+CAA+C;IAC/C,KAAK,EAAE,MAAM,CAAC;IACd,0CAA0C;IAC1C,QAAQ,EAAE,MAAM,CAAC;IACjB,0DAA0D;IAC1D,IAAI,EAAE,QAAQ,EAAE,CAAC;IACjB,yCAAyC;IACzC,OAAO,EAAE,UAAU,EAAE,CAAC;IACtB,uCAAuC;IACvC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;CACjB;AAmCD;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,GACf,kBAAkB,GAAG,IAAI,CAkG3B;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CACtC,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CAGpC"}
@@ -0,0 +1,124 @@
1
+ import { readFile } from "node:fs/promises";
2
+ // ── Regex patterns ─────────────────────────────────────────────────────────
3
+ // Match `title: "Components/Button"` or `title: 'Components/Button'`
4
+ const TITLE_RE = /title\s*:\s*["'`]([^"'`]+)["'`]/;
5
+ // Match `component: Button` or `component: "Button"`
6
+ const COMPONENT_RE = /component\s*:\s*["'`]?(\w+)["'`]?/;
7
+ // Match individual argTypes entries like: size: { control: "select", options: ["sm", "md", "lg"] }
8
+ const ARG_TYPE_RE = /(\w+)\s*:\s*\{([^}]*)\}/g;
9
+ // Match `control:` value inside an argType block
10
+ const CONTROL_RE = /control\s*:\s*["'`](\w+)["'`]/;
11
+ // Match `options:` array inside an argType block
12
+ const OPTIONS_RE = /options\s*:\s*\[([^\]]*)\]/;
13
+ // Match `type:` value inside an argType block
14
+ const TYPE_RE = /type\s*:\s*["'`](\w+)["'`]/;
15
+ // Match named exports like `export const Primary: Story = ...`
16
+ const STORY_EXPORT_RE = /export\s+const\s+(\w+)\s*(?::\s*\w+(?:<[^>]*>)?\s*)?=/g;
17
+ // Match `tags: ["autodocs", ...]` on the meta object
18
+ const TAGS_RE = /tags\s*:\s*\[([^\]]*)\]/;
19
+ // Match `args: { ... }` on the meta object (top-level default args)
20
+ const DEFAULT_ARGS_RE = /args\s*:\s*\{([^}]*)\}/;
21
+ // ── Parser ─────────────────────────────────────────────────────────────────
22
+ /**
23
+ * Parse a single Storybook story file and extract component metadata.
24
+ * Uses regex-based extraction (no AST required).
25
+ */
26
+ export function parseStoryFile(content, filePath) {
27
+ // Must have a default export (the meta object)
28
+ if (!content.includes("export default") &&
29
+ !content.includes("satisfies Meta")) {
30
+ return null;
31
+ }
32
+ // Extract title — required
33
+ const titleMatch = TITLE_RE.exec(content);
34
+ const componentMatch = COMPONENT_RE.exec(content);
35
+ // Derive component name from title or component field
36
+ let componentName;
37
+ if (titleMatch?.[1]) {
38
+ const parts = titleMatch[1].split("/");
39
+ componentName = parts[parts.length - 1];
40
+ }
41
+ else if (componentMatch?.[1]) {
42
+ componentName = componentMatch[1];
43
+ }
44
+ if (!componentName)
45
+ return null;
46
+ const title = titleMatch?.[1] ?? componentName;
47
+ // Extract args from argTypes
48
+ const args = [];
49
+ const argTypesSection = content.match(/argTypes\s*:\s*\{([\s\S]*?)\n\s*\}/);
50
+ if (argTypesSection?.[1]) {
51
+ let match;
52
+ ARG_TYPE_RE.lastIndex = 0;
53
+ while ((match = ARG_TYPE_RE.exec(argTypesSection[1])) !== null) {
54
+ const name = match[1];
55
+ const block = match[2] ?? "";
56
+ const controlMatch = CONTROL_RE.exec(block);
57
+ const optionsMatch = OPTIONS_RE.exec(block);
58
+ const typeMatch = TYPE_RE.exec(block);
59
+ const arg = { name };
60
+ if (typeMatch?.[1])
61
+ arg.type = typeMatch[1];
62
+ if (controlMatch?.[1])
63
+ arg.control = controlMatch[1];
64
+ if (optionsMatch?.[1]) {
65
+ arg.options = optionsMatch[1]
66
+ .split(",")
67
+ .map((s) => s.trim().replace(/["'`]/g, ""))
68
+ .filter(Boolean);
69
+ }
70
+ args.push(arg);
71
+ }
72
+ }
73
+ // Also extract from top-level `args: { ... }` if argTypes is empty
74
+ if (args.length === 0) {
75
+ const defaultArgsMatch = DEFAULT_ARGS_RE.exec(content);
76
+ if (defaultArgsMatch?.[1]) {
77
+ const entries = defaultArgsMatch[1].split(",");
78
+ for (const entry of entries) {
79
+ const [key, value] = entry.split(":").map((s) => s.trim());
80
+ if (key) {
81
+ args.push({
82
+ name: key,
83
+ defaultValue: value?.replace(/["'`]/g, ""),
84
+ });
85
+ }
86
+ }
87
+ }
88
+ }
89
+ // Extract story names from named exports
90
+ const stories = [];
91
+ let storyMatch;
92
+ STORY_EXPORT_RE.lastIndex = 0;
93
+ while ((storyMatch = STORY_EXPORT_RE.exec(content)) !== null) {
94
+ const name = storyMatch[1];
95
+ // Skip common non-story exports
96
+ if (name === "default" || name === "meta" || name === "Meta")
97
+ continue;
98
+ stories.push({ name });
99
+ }
100
+ // Extract tags
101
+ const tagsMatch = TAGS_RE.exec(content);
102
+ const tags = tagsMatch?.[1]
103
+ ? tagsMatch[1]
104
+ .split(",")
105
+ .map((s) => s.trim().replace(/["'`]/g, ""))
106
+ .filter(Boolean)
107
+ : undefined;
108
+ return {
109
+ componentName,
110
+ title,
111
+ filePath,
112
+ args,
113
+ stories,
114
+ tags,
115
+ };
116
+ }
117
+ /**
118
+ * Parse a story file from disk.
119
+ */
120
+ export async function parseStoryFromPath(filePath) {
121
+ const content = await readFile(filePath, "utf-8");
122
+ return parseStoryFile(content, filePath);
123
+ }
124
+ //# sourceMappingURL=storybook.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storybook.js","sourceRoot":"","sources":["../../../src/integrations/storybook.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../../src/mcp/server.ts"],"names":[],"mappings":"AA4BA;;;GAGG;AACH,wBAAsB,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CA+KjD"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../../src/mcp/server.ts"],"names":[],"mappings":"AA+BA;;;GAGG;AACH,wBAAsB,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CAoMjD"}
@@ -2,6 +2,7 @@ import { createRequire } from "node:module";
2
2
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
3
3
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
4
  import { loadKit } from "../kit/loader.js";
5
+ import { scanCodebase } from "../integrations/codebase-scan.js";
5
6
  import { startPreviewServer } from "../preview/server.js";
6
7
  import { setPreviewServer } from "../preview/ensure.js";
7
8
  import { checkMcpRegistration, addFigmaMcpServer, addPlaywrightMcpServer, fixGlobalClaudeJson } from "../cli/setup-utils.js";
@@ -22,12 +23,25 @@ import * as updateTokens from "./tools/update-tokens.js";
22
23
  import * as getScreenshots from "./tools/get-screenshots.js";
23
24
  import * as checkSetup from "./tools/check-setup.js";
24
25
  import * as pushTokensToFigma from "./tools/push-tokens-to-figma.js";
26
+ import * as scanProject from "./tools/scan-project.js";
25
27
  /**
26
28
  * Start the Layout Context MCP server.
27
29
  * Loads the kit from the current working directory and registers all tools.
28
30
  */
29
31
  export async function startServer() {
30
32
  const kit = loadKit();
33
+ // Auto-scan current directory for React components and Storybook stories
34
+ let scanResult = null;
35
+ try {
36
+ scanResult = await scanCodebase(process.cwd());
37
+ if (scanResult.components.length > 0) {
38
+ console.error(`[layout-context] Codebase: ${scanResult.components.length} components` +
39
+ (scanResult.storybookStories.length > 0 ? ` (${scanResult.storybookStories.length} stories)` : ""));
40
+ }
41
+ }
42
+ catch {
43
+ // Non-fatal — continue without codebase scan
44
+ }
31
45
  const kitName = kit?.manifest.displayName ?? "none";
32
46
  const componentCount = kit?.components.length ?? 0;
33
47
  // Log to stderr so it doesn't interfere with stdio transport
@@ -102,11 +116,11 @@ export async function startServer() {
102
116
  name: "layout-context",
103
117
  version: pkg.version,
104
118
  });
105
- // Register all 12 tools
119
+ // Register all 14 tools
106
120
  server.tool(getDesignSystem.name, getDesignSystem.description, getDesignSystem.inputSchema, getDesignSystem.handler(kit));
107
121
  server.tool(getTokens.name, getTokens.description, getTokens.inputSchema, getTokens.handler(kit));
108
122
  server.tool(getComponent.name, getComponent.description, getComponent.inputSchema, getComponent.handler(kit));
109
- server.tool(listComponents.name, listComponents.description, listComponents.inputSchema, listComponents.handler(kit));
123
+ server.tool(listComponents.name, listComponents.description, listComponents.inputSchema, listComponents.handler(kit, scanResult));
110
124
  server.tool(checkCompliance.name, checkCompliance.description, checkCompliance.inputSchema, checkCompliance.handler(kit));
111
125
  server.tool(preview.name, preview.description, preview.inputSchema, preview.handler(kit));
112
126
  server.tool(pushToFigma.name, pushToFigma.description, pushToFigma.inputSchema, pushToFigma.handler(kit));
@@ -116,6 +130,7 @@ export async function startServer() {
116
130
  server.tool(getScreenshots.name, getScreenshots.description, getScreenshots.inputSchema, getScreenshots.handler());
117
131
  server.tool(checkSetup.name, checkSetup.description, checkSetup.inputSchema, checkSetup.handler());
118
132
  server.tool(pushTokensToFigma.name, pushTokensToFigma.description, pushTokensToFigma.inputSchema, pushTokensToFigma.handler(kit));
133
+ server.tool(scanProject.name, scanProject.description, scanProject.inputSchema, scanProject.handler());
119
134
  // Connect via stdio
120
135
  const transport = new StdioServerTransport();
121
136
  await server.connect(transport);
@@ -1 +1 @@
1
- {"version":3,"file":"server.js","sourceRoot":"","sources":["../../../src/mcp/server.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../../../src/mcp/server.ts"],"names":[],"mappings":"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"}
@@ -1,8 +1,9 @@
1
1
  import type { Kit } from "../../kit/types.js";
2
+ import type { ScanResult } from "../../integrations/codebase-scan.js";
2
3
  export declare const name = "list-components";
3
4
  export declare const description: string;
4
5
  export declare const inputSchema: {};
5
- export declare function handler(kit: Kit | null): () => Promise<{
6
+ export declare function handler(kit: Kit | null, scanResult: ScanResult | null): () => Promise<{
6
7
  content: {
7
8
  type: "text";
8
9
  text: string;
@@ -1 +1 @@
1
- {"version":3,"file":"list-components.d.ts","sourceRoot":"","sources":["../../../../src/mcp/tools/list-components.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,oBAAoB,CAAC;AAE9C,eAAO,MAAM,IAAI,oBAAoB,CAAC;AAEtC,eAAO,MAAM,WAAW,QAE2E,CAAC;AAEpG,eAAO,MAAM,WAAW,IAAK,CAAC;AAE9B,wBAAgB,OAAO,CAAC,GAAG,EAAE,GAAG,GAAG,IAAI;;;;;GAqCtC"}
1
+ {"version":3,"file":"list-components.d.ts","sourceRoot":"","sources":["../../../../src/mcp/tools/list-components.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qCAAqC,CAAC;AAEtE,eAAO,MAAM,IAAI,oBAAoB,CAAC;AAEtC,eAAO,MAAM,WAAW,QAG4C,CAAC;AAErE,eAAO,MAAM,WAAW,IAAK,CAAC;AAE9B,wBAAgB,OAAO,CAAC,GAAG,EAAE,GAAG,GAAG,IAAI,EAAE,UAAU,EAAE,UAAU,GAAG,IAAI;;;;;GAmDrE"}
@@ -1,38 +1,64 @@
1
1
  export const name = "list-components";
2
- export const description = "Lists all available components in the active design system kit with their names and descriptions. " +
3
- "Use this to discover what components are available before requesting details on a specific one.";
2
+ export const description = "Lists all available components: design system components from layout.md, " +
3
+ "auto-detected React components from the codebase, and Storybook stories. " +
4
+ "Use this to discover existing components before building new UI.";
4
5
  export const inputSchema = {};
5
- export function handler(kit) {
6
+ export function handler(kit, scanResult) {
6
7
  return async () => {
7
- if (!kit) {
8
- return {
9
- content: [
10
- {
11
- type: "text",
12
- text: "No design system kit found. Run `npx @layoutdesign/context init` to set one up.",
13
- },
14
- ],
15
- };
8
+ const sections = [];
9
+ // 1. Design system components from layout.md
10
+ if (kit && kit.components.length > 0) {
11
+ const lines = kit.components.map((c) => `- **${c.name}** — ${c.description || "No description"}`);
12
+ sections.push(`## Design System (from layout.md)\n\n${lines.join("\n")}`);
16
13
  }
17
- if (kit.components.length === 0) {
14
+ // 2. Codebase components (auto-scanned)
15
+ if (scanResult && scanResult.components.length > 0) {
16
+ const lines = scanResult.components
17
+ .slice(0, 100) // cap for context budget
18
+ .map((c) => {
19
+ const propsStr = c.props.length > 0
20
+ ? ` props: ${c.props.map(p => p.name).join(", ")}`
21
+ : "";
22
+ const storyStr = c.storybook
23
+ ? ` [Storybook: ${c.storybook.stories.map(s => s.name).join(", ")}]`
24
+ : "";
25
+ const refStr = c.usesForwardRef ? " (forwardRef)" : "";
26
+ const importPath = buildImportPath(c.filePath);
27
+ const importStatement = c.exportType === "default"
28
+ ? `import ${c.name} from '${importPath}'`
29
+ : `import { ${c.name} } from '${importPath}'`;
30
+ return `- **${c.name}** (${c.filePath})${propsStr}${refStr}${storyStr}\n Import: \`${importStatement}\``;
31
+ });
32
+ sections.push(`## Your Codebase (auto-detected)\n\n${lines.join("\n")}`);
33
+ }
34
+ if (sections.length === 0) {
18
35
  return {
19
- content: [
20
- {
36
+ content: [{
21
37
  type: "text",
22
- text: "No components defined in this kit. Components are parsed from the ## Components section in layout.md.",
23
- },
24
- ],
38
+ text: "No components found. Set up a design system with `npx @layoutdesign/context init` or create React components in this project.",
39
+ }],
25
40
  };
26
41
  }
27
- const lines = kit.components.map((c) => `- **${c.name}** — ${c.description || "No description"}`);
42
+ const total = (kit?.components.length ?? 0) + (scanResult?.components.length ?? 0);
28
43
  return {
29
- content: [
30
- {
44
+ content: [{
31
45
  type: "text",
32
- text: `# Components (${kit.components.length})\n\n${lines.join("\n")}`,
33
- },
34
- ],
46
+ text: `# Components (${total})\n\n${sections.join("\n\n")}\n\n---\n**IMPORTANT:** When building UI, reuse existing components listed above. Import from the paths shown. Do NOT generate a new Button/Card/Input if one already exists.`,
47
+ }],
35
48
  };
36
49
  };
37
50
  }
51
+ function buildImportPath(filePath) {
52
+ // Convert file path to import path: src/components/ui/button.tsx -> @/components/ui/button
53
+ let importPath = filePath
54
+ .replace(/\.(tsx?|jsx?)$/, "")
55
+ .replace(/\/index$/, "");
56
+ if (importPath.startsWith("src/")) {
57
+ importPath = "@/" + importPath.slice(4);
58
+ }
59
+ else if (!importPath.startsWith(".") && !importPath.startsWith("@")) {
60
+ importPath = "./" + importPath;
61
+ }
62
+ return importPath;
63
+ }
38
64
  //# sourceMappingURL=list-components.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"list-components.js","sourceRoot":"","sources":["../../../../src/mcp/tools/list-components.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,IAAI,GAAG,iBAAiB,CAAC;AAEtC,MAAM,CAAC,MAAM,WAAW,GACtB,oGAAoG;IACpG,iGAAiG,CAAC;AAEpG,MAAM,CAAC,MAAM,WAAW,GAAG,EAAE,CAAC;AAE9B,MAAM,UAAU,OAAO,CAAC,GAAe;IACrC,OAAO,KAAK,IAAI,EAAE;QAChB,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE,iFAAiF;qBACxF;iBACF;aACF,CAAC;QACJ,CAAC;QAED,IAAI,GAAG,CAAC,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAChC,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE,uGAAuG;qBAC9G;iBACF;aACF,CAAC;QACJ,CAAC;QAED,MAAM,KAAK,GAAG,GAAG,CAAC,UAAU,CAAC,GAAG,CAC9B,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,IAAI,QAAQ,CAAC,CAAC,WAAW,IAAI,gBAAgB,EAAE,CAChE,CAAC;QAEF,OAAO;YACL,OAAO,EAAE;gBACP;oBACE,IAAI,EAAE,MAAe;oBACrB,IAAI,EAAE,iBAAiB,GAAG,CAAC,UAAU,CAAC,MAAM,QAAQ,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;iBACvE;aACF;SACF,CAAC;IACJ,CAAC,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"list-components.js","sourceRoot":"","sources":["../../../../src/mcp/tools/list-components.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ import { z } from "zod";
2
+ export declare const name = "scan-project";
3
+ export declare const description: string;
4
+ export declare const inputSchema: {
5
+ path: z.ZodOptional<z.ZodString>;
6
+ type: z.ZodOptional<z.ZodEnum<{
7
+ both: "both";
8
+ storybook: "storybook";
9
+ codebase: "codebase";
10
+ }>>;
11
+ };
12
+ type Input = {
13
+ path?: string;
14
+ type?: "both" | "storybook" | "codebase";
15
+ };
16
+ export declare function handler(): (input: Input) => Promise<{
17
+ content: {
18
+ type: "text";
19
+ text: string;
20
+ }[];
21
+ isError?: undefined;
22
+ } | {
23
+ content: {
24
+ type: "text";
25
+ text: string;
26
+ }[];
27
+ isError: boolean;
28
+ }>;
29
+ export {};
30
+ //# sourceMappingURL=scan-project.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scan-project.d.ts","sourceRoot":"","sources":["../../../../src/mcp/tools/scan-project.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,eAAO,MAAM,IAAI,iBAAiB,CAAC;AAEnC,eAAO,MAAM,WAAW,QAG8F,CAAC;AAEvH,eAAO,MAAM,WAAW;;;;;;;CAavB,CAAC;AAEF,KAAK,KAAK,GAAG;IACX,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,GAAG,WAAW,GAAG,UAAU,CAAC;CAC1C,CAAC;AAEF,wBAAgB,OAAO,KACP,OAAO,KAAK;;;;;;;;;;;;GA8F3B"}
@@ -0,0 +1,97 @@
1
+ import { z } from "zod";
2
+ import { resolve } from "node:path";
3
+ import { scanCodebase, scanStorybook } from "../../integrations/codebase-scan.js";
4
+ export const name = "scan-project";
5
+ export const description = "Scan the current project for React components and Storybook stories. " +
6
+ "Returns structured data about component names, props, export types, and story associations. " +
7
+ "Use this to understand the existing component inventory before generating new components or design system context.";
8
+ export const inputSchema = {
9
+ path: z
10
+ .string()
11
+ .optional()
12
+ .describe("Directory to scan. Defaults to the current working directory."),
13
+ type: z
14
+ .enum(["both", "storybook", "codebase"])
15
+ .optional()
16
+ .describe("What to scan: 'both' (default) scans components and stories, 'storybook' scans only stories, 'codebase' scans only components."),
17
+ };
18
+ export function handler() {
19
+ return async (input) => {
20
+ const rootPath = resolve(input.path ?? process.cwd());
21
+ const scanType = input.type ?? "both";
22
+ try {
23
+ if (scanType === "storybook") {
24
+ const stories = await scanStorybook(rootPath);
25
+ return {
26
+ content: [
27
+ {
28
+ type: "text",
29
+ text: JSON.stringify({
30
+ type: "storybook-scan",
31
+ rootPath,
32
+ storiesFound: stories.length,
33
+ stories,
34
+ }, null, 2),
35
+ },
36
+ ],
37
+ };
38
+ }
39
+ const result = await scanCodebase(rootPath);
40
+ // For "codebase" type, strip storybook data
41
+ if (scanType === "codebase") {
42
+ const components = result.components.map(({ storybook: _sb, ...rest }) => rest);
43
+ return {
44
+ content: [
45
+ {
46
+ type: "text",
47
+ text: JSON.stringify({
48
+ type: "codebase-scan",
49
+ rootPath,
50
+ componentsFound: components.length,
51
+ filesScanned: result.filesScanned,
52
+ durationMs: result.durationMs,
53
+ components,
54
+ }, null, 2),
55
+ },
56
+ ],
57
+ };
58
+ }
59
+ // Default: both
60
+ const withStories = result.components.filter((c) => c.storybook);
61
+ return {
62
+ content: [
63
+ {
64
+ type: "text",
65
+ text: JSON.stringify({
66
+ type: "full-scan",
67
+ rootPath,
68
+ summary: {
69
+ componentsFound: result.components.length,
70
+ storiesFound: result.storybookStories.length,
71
+ componentsWithStories: withStories.length,
72
+ unmatchedStories: result.unmatchedStories.length,
73
+ filesScanned: result.filesScanned,
74
+ durationMs: result.durationMs,
75
+ },
76
+ components: result.components,
77
+ unmatchedStories: result.unmatchedStories,
78
+ }, null, 2),
79
+ },
80
+ ],
81
+ };
82
+ }
83
+ catch (err) {
84
+ const msg = err instanceof Error ? err.message : String(err);
85
+ return {
86
+ content: [
87
+ {
88
+ type: "text",
89
+ text: `Error scanning project: ${msg}`,
90
+ },
91
+ ],
92
+ isError: true,
93
+ };
94
+ }
95
+ };
96
+ }
97
+ //# sourceMappingURL=scan-project.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scan-project.js","sourceRoot":"","sources":["../../../../src/mcp/tools/scan-project.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@layoutdesign/context",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "description": "Design system context for AI coding agents — MCP server + CLI + live preview",
5
5
  "license": "MIT",
6
6
  "type": "module",