@fragments-sdk/mcp 0.6.2 → 0.7.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/README.md +9 -9
- package/dist/bin.js +43 -21
- package/dist/bin.js.map +1 -1
- package/dist/chunk-3IHXJEMM.js +47 -0
- package/dist/chunk-3IHXJEMM.js.map +1 -0
- package/dist/{chunk-2W7DAUUS.js → chunk-7GGI7JJE.js} +11 -6
- package/dist/chunk-7GGI7JJE.js.map +1 -0
- package/dist/chunk-LZW5KUXV.js +4293 -0
- package/dist/chunk-LZW5KUXV.js.map +1 -0
- package/dist/index.js +80 -18
- package/dist/index.js.map +1 -1
- package/dist/rules-W47BYPZV.js +8 -0
- package/dist/server.js +2 -2
- package/package.json +4 -3
- package/dist/chunk-2W7DAUUS.js.map +0 -1
- package/dist/chunk-FGIBLPSU.js +0 -29
- package/dist/chunk-FGIBLPSU.js.map +0 -1
- package/dist/chunk-NVHGG7GW.js +0 -630
- package/dist/chunk-NVHGG7GW.js.map +0 -1
- package/dist/chunk-WBOVO43F.js +0 -2481
- package/dist/chunk-WBOVO43F.js.map +0 -1
- package/dist/config-TUFA5J2S.js +0 -7
- package/dist/rules-WGBCECAK.js +0 -7
- package/dist/rules-WGBCECAK.js.map +0 -1
- /package/dist/{config-TUFA5J2S.js.map → rules-W47BYPZV.js.map} +0 -0
package/README.md
CHANGED
|
@@ -71,15 +71,15 @@ Once the project root is known, the server walks up from it, scans `package.json
|
|
|
71
71
|
|
|
72
72
|
| Tool | Description |
|
|
73
73
|
|------|-------------|
|
|
74
|
-
| `
|
|
75
|
-
| `
|
|
76
|
-
| `
|
|
77
|
-
| `
|
|
78
|
-
| `
|
|
79
|
-
| `
|
|
80
|
-
| `
|
|
81
|
-
| `
|
|
82
|
-
| `
|
|
74
|
+
| `discover` | List, search, or get AI-powered component suggestions |
|
|
75
|
+
| `inspect` | Full component details — props, examples, guidelines |
|
|
76
|
+
| `blocks` | Composition patterns (e.g. "Login Form", "Settings Page") |
|
|
77
|
+
| `tokens` | CSS custom properties by category |
|
|
78
|
+
| `implement` | One-shot: components + blocks + tokens for a use case |
|
|
79
|
+
| `render` | Render a component screenshot (requires dev server) |
|
|
80
|
+
| `fix` | Generate token-compliance patches (requires dev server) |
|
|
81
|
+
| `graph` | Query the component relationship graph (dependencies, impact, composition, health) |
|
|
82
|
+
| `a11y` | Run an accessibility audit on a component (requires dev server) |
|
|
83
83
|
|
|
84
84
|
## How search works
|
|
85
85
|
|
package/dist/bin.js
CHANGED
|
@@ -1,18 +1,14 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
FragmentsJsonAdapter,
|
|
7
|
-
findFragmentsJson,
|
|
3
|
+
loadConfigFile,
|
|
4
|
+
resolveDataAdapter,
|
|
5
|
+
resolveSearchApiKey,
|
|
8
6
|
startMcpServer
|
|
9
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-LZW5KUXV.js";
|
|
10
8
|
import "./chunk-4SVS3AA3.js";
|
|
11
|
-
import "./chunk-
|
|
9
|
+
import "./chunk-3IHXJEMM.js";
|
|
12
10
|
|
|
13
11
|
// src/bin.ts
|
|
14
|
-
import { existsSync } from "fs";
|
|
15
|
-
import { join } from "path";
|
|
16
12
|
var args = process.argv.slice(2);
|
|
17
13
|
if (args[0] === "init") {
|
|
18
14
|
const { runInit } = await import("./init.js");
|
|
@@ -51,6 +47,8 @@ Examples:
|
|
|
51
47
|
var projectRoot = process.cwd();
|
|
52
48
|
var viewerUrl;
|
|
53
49
|
var apiKey;
|
|
50
|
+
var cloudApiKey;
|
|
51
|
+
var source = "auto";
|
|
54
52
|
var generateRules = false;
|
|
55
53
|
var rulesFormats;
|
|
56
54
|
var force = false;
|
|
@@ -62,6 +60,20 @@ for (let i = 0; i < args.length; i++) {
|
|
|
62
60
|
viewerUrl = args[++i];
|
|
63
61
|
} else if (arg === "--api-key" || arg === "-k") {
|
|
64
62
|
apiKey = args[++i];
|
|
63
|
+
} else if (arg === "--search-api-key") {
|
|
64
|
+
apiKey = args[++i];
|
|
65
|
+
} else if (arg === "--cloud-api-key") {
|
|
66
|
+
cloudApiKey = args[++i];
|
|
67
|
+
} else if (arg === "--source") {
|
|
68
|
+
const next = args[++i];
|
|
69
|
+
if (next === "auto" || next === "fragments-json" || next === "cloud" || next === "bundle" || next === "extract") {
|
|
70
|
+
source = next;
|
|
71
|
+
} else {
|
|
72
|
+
console.error(
|
|
73
|
+
`Invalid source: "${next}". Valid values: auto, fragments-json, cloud, bundle, extract`
|
|
74
|
+
);
|
|
75
|
+
process.exit(1);
|
|
76
|
+
}
|
|
65
77
|
} else if (arg === "--generate-rules") {
|
|
66
78
|
generateRules = true;
|
|
67
79
|
} else if (arg === "--formats") {
|
|
@@ -82,6 +94,9 @@ Options:
|
|
|
82
94
|
-p, --project-root <path> Project root directory (default: cwd)
|
|
83
95
|
-u, --viewer-url <url> Viewer URL for render/fix/a11y tools (optional)
|
|
84
96
|
-k, --api-key <key> Premium API key for semantic vector search (optional)
|
|
97
|
+
--search-api-key <key> Explicit premium vector search key (same as --api-key)
|
|
98
|
+
--cloud-api-key <key> Cloud API key for org-scoped catalog access
|
|
99
|
+
--source <mode> Source override: auto, fragments-json, cloud, bundle, extract
|
|
85
100
|
--generate-rules Generate IDE rules files and exit
|
|
86
101
|
--formats <list> Comma-separated formats: cursor,claude,copilot (default: all)
|
|
87
102
|
--force Overwrite existing rules files
|
|
@@ -93,19 +108,24 @@ Quick start:
|
|
|
93
108
|
process.exit(0);
|
|
94
109
|
}
|
|
95
110
|
}
|
|
96
|
-
var
|
|
97
|
-
var
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
111
|
+
var fileConfig = loadConfigFile(projectRoot) ?? void 0;
|
|
112
|
+
var serverConfig = {
|
|
113
|
+
projectRoot,
|
|
114
|
+
viewerUrl,
|
|
115
|
+
searchApiKey: resolveSearchApiKey({ projectRoot, apiKey }, fileConfig),
|
|
116
|
+
cloudApiKey,
|
|
117
|
+
source,
|
|
118
|
+
fileConfig
|
|
119
|
+
};
|
|
120
|
+
var { adapter, mode } = resolveDataAdapter(serverConfig, fileConfig);
|
|
121
|
+
if (mode === "extract") {
|
|
122
|
+
console.error(
|
|
123
|
+
"[fragments-mcp] No fragments.json found \u2014 auto-extracting from source."
|
|
124
|
+
);
|
|
105
125
|
}
|
|
106
126
|
if (generateRules) {
|
|
107
127
|
(async () => {
|
|
108
|
-
const { generateRulesFiles } = await import("./rules-
|
|
128
|
+
const { generateRulesFiles } = await import("./rules-W47BYPZV.js");
|
|
109
129
|
const defaultFormats = ["cursor", "claude", "copilot"];
|
|
110
130
|
const formats = rulesFormats ? rulesFormats.split(",").map((f) => f.trim()) : defaultFormats;
|
|
111
131
|
const validFormats = /* @__PURE__ */ new Set(["cursor", "claude", "copilot"]);
|
|
@@ -116,9 +136,7 @@ if (generateRules) {
|
|
|
116
136
|
}
|
|
117
137
|
}
|
|
118
138
|
const data = await adapter.load(projectRoot);
|
|
119
|
-
const { loadConfigFile } = await import("./config-TUFA5J2S.js");
|
|
120
139
|
const { BRAND } = await import("./constants-YXOTMY3I.js");
|
|
121
|
-
const fileConfig = loadConfigFile(projectRoot);
|
|
122
140
|
const brandName = fileConfig?.brand?.name ?? BRAND.name;
|
|
123
141
|
const files = generateRulesFiles({
|
|
124
142
|
data,
|
|
@@ -145,6 +163,10 @@ if (generateRules) {
|
|
|
145
163
|
projectRoot,
|
|
146
164
|
viewerUrl,
|
|
147
165
|
apiKey,
|
|
166
|
+
searchApiKey: resolveSearchApiKey({ projectRoot, apiKey }, fileConfig),
|
|
167
|
+
cloudApiKey,
|
|
168
|
+
source,
|
|
169
|
+
fileConfig,
|
|
148
170
|
adapter
|
|
149
171
|
}).catch((error) => {
|
|
150
172
|
console.error("Failed to start MCP server:", error);
|
package/dist/bin.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/bin.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { existsSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { startMcpServer } from './server.js';\nimport { FragmentsJsonAdapter } from './adapters/fragments-json.js';\nimport { AutoExtractionAdapter } from './adapters/auto-extract.js';\nimport { findFragmentsJson } from './discovery.js';\nimport type { DataAdapter } from './adapters/types.js';\n\n// Parse command line arguments\nconst args = process.argv.slice(2);\n\n// ---------------------------------------------------------------------------\n// Subcommand: init\n// ---------------------------------------------------------------------------\nif (args[0] === 'init') {\n const { runInit } = await import('./init.js');\n const initArgs = args.slice(1);\n\n let projectRoot = process.cwd();\n let clients: string[] | undefined;\n\n for (let i = 0; i < initArgs.length; i++) {\n const arg = initArgs[i];\n if (arg === '--project-root' || arg === '-p') {\n projectRoot = initArgs[++i] ?? projectRoot;\n } else if (arg === '--client' || arg === '-c') {\n clients = (initArgs[++i] ?? '').split(',').map((s) => s.trim());\n } else if (arg === '--help' || arg === '-h') {\n console.log(`\nUsage: fragments-mcp init [options]\n\nWrite MCP server config for your AI editor(s).\nAuto-detects Claude Code, Cursor, VS Code, and Windsurf.\n\nOptions:\n -p, --project-root <path> Project root directory (default: cwd)\n -c, --client <list> Comma-separated clients: claude,cursor,vscode,windsurf\n (default: auto-detect)\n -h, --help Show this help message\n\nExamples:\n npx @fragments-sdk/mcp init\n npx @fragments-sdk/mcp init --client cursor,claude\n`);\n process.exit(0);\n }\n }\n\n runInit({ projectRoot, clients: clients as import('./init.js').Client[] });\n process.exit(0);\n}\n\n// ---------------------------------------------------------------------------\n// Main: MCP server mode\n// ---------------------------------------------------------------------------\nlet projectRoot = process.cwd();\nlet viewerUrl: string | undefined;\nlet apiKey: string | undefined;\nlet generateRules = false;\nlet rulesFormats: string | undefined;\nlet force = false;\n\nfor (let i = 0; i < args.length; i++) {\n const arg = args[i];\n\n if (arg === '--project-root' || arg === '-p') {\n projectRoot = args[++i] ?? projectRoot;\n } else if (arg === '--viewer-url' || arg === '-u') {\n viewerUrl = args[++i];\n } else if (arg === '--api-key' || arg === '-k') {\n apiKey = args[++i];\n } else if (arg === '--generate-rules') {\n generateRules = true;\n } else if (arg === '--formats') {\n rulesFormats = args[++i];\n } else if (arg === '--force') {\n force = true;\n } else if (arg === '--help' || arg === '-h') {\n console.log(`\nUsage: fragments-mcp [command] [options]\n\nStandalone MCP server for design system intelligence.\nProvides component discovery, search, and governance — no CLI/Playwright needed.\n\nCommands:\n init Write MCP config for your AI editor(s)\n\nOptions:\n -p, --project-root <path> Project root directory (default: cwd)\n -u, --viewer-url <url> Viewer URL for render/fix/a11y tools (optional)\n -k, --api-key <key> Premium API key for semantic vector search (optional)\n --generate-rules Generate IDE rules files and exit\n --formats <list> Comma-separated formats: cursor,claude,copilot (default: all)\n --force Overwrite existing rules files\n -h, --help Show this help message\n\nQuick start:\n npx @fragments-sdk/mcp init\n`);\n process.exit(0);\n }\n}\n\n// Adapter selection: fragments.json > auto-extract > error\nlet adapter: DataAdapter;\nconst fragmentsJsonPaths = findFragmentsJson(projectRoot);\n\nif (fragmentsJsonPaths.length > 0) {\n adapter = new FragmentsJsonAdapter();\n} else if (\n existsSync(join(projectRoot, 'tsconfig.json')) ||\n existsSync(join(projectRoot, 'tsconfig.app.json'))\n) {\n adapter = new AutoExtractionAdapter();\n console.error('[fragments-mcp] No fragments.json found — auto-extracting from source.');\n} else {\n // Let FragmentsJsonAdapter throw a helpful error\n adapter = new FragmentsJsonAdapter();\n}\n\n// --generate-rules: generate IDE rules and exit\nif (generateRules) {\n (async () => {\n const { generateRulesFiles } = await import('./rules.js');\n type RulesFormat = 'cursor' | 'claude' | 'copilot';\n\n const defaultFormats: RulesFormat[] = ['cursor', 'claude', 'copilot'];\n const formats: RulesFormat[] = rulesFormats\n ? (rulesFormats.split(',').map(f => f.trim()) as RulesFormat[])\n : defaultFormats;\n\n // Validate formats\n const validFormats = new Set(['cursor', 'claude', 'copilot']);\n for (const fmt of formats) {\n if (!validFormats.has(fmt)) {\n console.error(`Invalid format: \"${fmt}\". Valid formats: cursor, claude, copilot`);\n process.exit(1);\n }\n }\n\n // Load data using the same adapter\n const data = await adapter.load(projectRoot);\n\n // Resolve brand name from config\n const { loadConfigFile } = await import('./config.js');\n const { BRAND } = await import('./constants.js');\n const fileConfig = loadConfigFile(projectRoot);\n const brandName = fileConfig?.brand?.name ?? BRAND.name;\n\n // Generate rules\n const files = generateRulesFiles({\n data,\n brandName,\n outputDir: projectRoot,\n formats,\n force,\n });\n\n if (files.length === 0) {\n console.log('No rules files generated.');\n } else {\n console.log(`Generated ${files.length} rules file(s):`);\n for (const file of files) {\n console.log(` ${file}`);\n }\n }\n\n process.exit(0);\n })().catch((error) => {\n console.error('Failed to generate rules:', error instanceof Error ? error.message : error);\n process.exit(1);\n });\n} else {\n // Default: start MCP server\n startMcpServer({\n projectRoot,\n viewerUrl,\n apiKey,\n adapter,\n }).catch((error) => {\n console.error('Failed to start MCP server:', error);\n process.exit(1);\n });\n}\n"],"mappings":"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","names":["projectRoot"]}
|
|
1
|
+
{"version":3,"sources":["../src/bin.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { startMcpServer } from './server.js';\nimport { loadConfigFile } from './config.js';\nimport { resolveDataAdapter, resolveSearchApiKey } from './source-selection.js';\n\n// Parse command line arguments\nconst args = process.argv.slice(2);\n\n// ---------------------------------------------------------------------------\n// Subcommand: init\n// ---------------------------------------------------------------------------\nif (args[0] === 'init') {\n const { runInit } = await import('./init.js');\n const initArgs = args.slice(1);\n\n let projectRoot = process.cwd();\n let clients: string[] | undefined;\n\n for (let i = 0; i < initArgs.length; i++) {\n const arg = initArgs[i];\n if (arg === '--project-root' || arg === '-p') {\n projectRoot = initArgs[++i] ?? projectRoot;\n } else if (arg === '--client' || arg === '-c') {\n clients = (initArgs[++i] ?? '').split(',').map((s) => s.trim());\n } else if (arg === '--help' || arg === '-h') {\n console.log(`\nUsage: fragments-mcp init [options]\n\nWrite MCP server config for your AI editor(s).\nAuto-detects Claude Code, Cursor, VS Code, and Windsurf.\n\nOptions:\n -p, --project-root <path> Project root directory (default: cwd)\n -c, --client <list> Comma-separated clients: claude,cursor,vscode,windsurf\n (default: auto-detect)\n -h, --help Show this help message\n\nExamples:\n npx @fragments-sdk/mcp init\n npx @fragments-sdk/mcp init --client cursor,claude\n`);\n process.exit(0);\n }\n }\n\n runInit({ projectRoot, clients: clients as import('./init.js').Client[] });\n process.exit(0);\n}\n\n// ---------------------------------------------------------------------------\n// Main: MCP server mode\n// ---------------------------------------------------------------------------\nlet projectRoot = process.cwd();\nlet viewerUrl: string | undefined;\nlet apiKey: string | undefined;\nlet cloudApiKey: string | undefined;\nlet source: 'auto' | 'fragments-json' | 'cloud' | 'bundle' | 'extract' =\n 'auto';\nlet generateRules = false;\nlet rulesFormats: string | undefined;\nlet force = false;\n\nfor (let i = 0; i < args.length; i++) {\n const arg = args[i];\n\n if (arg === '--project-root' || arg === '-p') {\n projectRoot = args[++i] ?? projectRoot;\n } else if (arg === '--viewer-url' || arg === '-u') {\n viewerUrl = args[++i];\n } else if (arg === '--api-key' || arg === '-k') {\n apiKey = args[++i];\n } else if (arg === '--search-api-key') {\n apiKey = args[++i];\n } else if (arg === '--cloud-api-key') {\n cloudApiKey = args[++i];\n } else if (arg === '--source') {\n const next = args[++i];\n if (\n next === 'auto' ||\n next === 'fragments-json' ||\n next === 'cloud' ||\n next === 'bundle' ||\n next === 'extract'\n ) {\n source = next;\n } else {\n console.error(\n `Invalid source: \"${next}\". Valid values: auto, fragments-json, cloud, bundle, extract`,\n );\n process.exit(1);\n }\n } else if (arg === '--generate-rules') {\n generateRules = true;\n } else if (arg === '--formats') {\n rulesFormats = args[++i];\n } else if (arg === '--force') {\n force = true;\n } else if (arg === '--help' || arg === '-h') {\n console.log(`\nUsage: fragments-mcp [command] [options]\n\nStandalone MCP server for design system intelligence.\nProvides component discovery, search, and governance — no CLI/Playwright needed.\n\nCommands:\n init Write MCP config for your AI editor(s)\n\nOptions:\n -p, --project-root <path> Project root directory (default: cwd)\n -u, --viewer-url <url> Viewer URL for render/fix/a11y tools (optional)\n -k, --api-key <key> Premium API key for semantic vector search (optional)\n --search-api-key <key> Explicit premium vector search key (same as --api-key)\n --cloud-api-key <key> Cloud API key for org-scoped catalog access\n --source <mode> Source override: auto, fragments-json, cloud, bundle, extract\n --generate-rules Generate IDE rules files and exit\n --formats <list> Comma-separated formats: cursor,claude,copilot (default: all)\n --force Overwrite existing rules files\n -h, --help Show this help message\n\nQuick start:\n npx @fragments-sdk/mcp init\n`);\n process.exit(0);\n }\n}\n\nconst fileConfig = loadConfigFile(projectRoot) ?? undefined;\nconst serverConfig = {\n projectRoot,\n viewerUrl,\n searchApiKey: resolveSearchApiKey({ projectRoot, apiKey }, fileConfig),\n cloudApiKey,\n source,\n fileConfig,\n};\nconst { adapter, mode } = resolveDataAdapter(serverConfig, fileConfig);\n\nif (mode === 'extract') {\n console.error(\n '[fragments-mcp] No fragments.json found — auto-extracting from source.',\n );\n}\n\n// --generate-rules: generate IDE rules and exit\nif (generateRules) {\n (async () => {\n const { generateRulesFiles } = await import('./rules.js');\n type RulesFormat = 'cursor' | 'claude' | 'copilot';\n\n const defaultFormats: RulesFormat[] = ['cursor', 'claude', 'copilot'];\n const formats: RulesFormat[] = rulesFormats\n ? (rulesFormats.split(',').map(f => f.trim()) as RulesFormat[])\n : defaultFormats;\n\n // Validate formats\n const validFormats = new Set(['cursor', 'claude', 'copilot']);\n for (const fmt of formats) {\n if (!validFormats.has(fmt)) {\n console.error(`Invalid format: \"${fmt}\". Valid formats: cursor, claude, copilot`);\n process.exit(1);\n }\n }\n\n // Load data using the same adapter\n const data = await adapter.load(projectRoot);\n\n // Resolve brand name from config\n const { BRAND } = await import('./constants.js');\n const brandName = fileConfig?.brand?.name ?? BRAND.name;\n\n // Generate rules\n const files = generateRulesFiles({\n data,\n brandName,\n outputDir: projectRoot,\n formats,\n force,\n });\n\n if (files.length === 0) {\n console.log('No rules files generated.');\n } else {\n console.log(`Generated ${files.length} rules file(s):`);\n for (const file of files) {\n console.log(` ${file}`);\n }\n }\n\n process.exit(0);\n })().catch((error) => {\n console.error('Failed to generate rules:', error instanceof Error ? error.message : error);\n process.exit(1);\n });\n} else {\n // Default: start MCP server\n startMcpServer({\n projectRoot,\n viewerUrl,\n apiKey,\n searchApiKey: resolveSearchApiKey({ projectRoot, apiKey }, fileConfig),\n cloudApiKey,\n source,\n fileConfig,\n adapter,\n }).catch((error) => {\n console.error('Failed to start MCP server:', error);\n process.exit(1);\n });\n}\n"],"mappings":"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","names":["projectRoot"]}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
// src/snapshot-helpers.ts
|
|
2
|
+
function listComponents(snapshot) {
|
|
3
|
+
return Object.values(snapshot.components);
|
|
4
|
+
}
|
|
5
|
+
function componentNames(snapshot) {
|
|
6
|
+
return listComponents(snapshot).map((component) => component.name);
|
|
7
|
+
}
|
|
8
|
+
function listBlocks(snapshot) {
|
|
9
|
+
return Object.values(snapshot.blocks ?? {});
|
|
10
|
+
}
|
|
11
|
+
function findComponentByName(snapshot, name) {
|
|
12
|
+
const query = name.toLowerCase();
|
|
13
|
+
return listComponents(snapshot).find(
|
|
14
|
+
(component) => component.name.toLowerCase() === query
|
|
15
|
+
);
|
|
16
|
+
}
|
|
17
|
+
function getGuidanceWhen(component) {
|
|
18
|
+
if (component.guidance.when.length > 0) {
|
|
19
|
+
return component.guidance.when;
|
|
20
|
+
}
|
|
21
|
+
if (component.guidance.usageGuidance) {
|
|
22
|
+
return [component.guidance.usageGuidance];
|
|
23
|
+
}
|
|
24
|
+
if (component.guidance.dos.length > 0) {
|
|
25
|
+
return component.guidance.dos;
|
|
26
|
+
}
|
|
27
|
+
return [];
|
|
28
|
+
}
|
|
29
|
+
function getGuidanceWhenNot(component) {
|
|
30
|
+
if (component.guidance.whenNot.length > 0) {
|
|
31
|
+
return component.guidance.whenNot;
|
|
32
|
+
}
|
|
33
|
+
if (component.guidance.donts.length > 0) {
|
|
34
|
+
return component.guidance.donts;
|
|
35
|
+
}
|
|
36
|
+
return [];
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export {
|
|
40
|
+
listComponents,
|
|
41
|
+
componentNames,
|
|
42
|
+
listBlocks,
|
|
43
|
+
findComponentByName,
|
|
44
|
+
getGuidanceWhen,
|
|
45
|
+
getGuidanceWhenNot
|
|
46
|
+
};
|
|
47
|
+
//# sourceMappingURL=chunk-3IHXJEMM.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/snapshot-helpers.ts"],"sourcesContent":["import type { McpBlock, McpComponent, McpSnapshot } from '@fragments-sdk/core';\n\nexport function listComponents(snapshot: Pick<McpSnapshot, 'components'>): McpComponent[] {\n return Object.values(snapshot.components);\n}\n\nexport function componentNames(snapshot: Pick<McpSnapshot, 'components'>): string[] {\n return listComponents(snapshot).map((component) => component.name);\n}\n\nexport function listBlocks(snapshot: Pick<McpSnapshot, 'blocks'>): McpBlock[] {\n return Object.values(snapshot.blocks ?? {});\n}\n\nexport function findComponentByName(\n snapshot: Pick<McpSnapshot, 'components'>,\n name: string,\n): McpComponent | undefined {\n const query = name.toLowerCase();\n return listComponents(snapshot).find(\n (component) => component.name.toLowerCase() === query,\n );\n}\n\nexport function getGuidanceWhen(component: McpComponent): string[] {\n if (component.guidance.when.length > 0) {\n return component.guidance.when;\n }\n if (component.guidance.usageGuidance) {\n return [component.guidance.usageGuidance];\n }\n if (component.guidance.dos.length > 0) {\n return component.guidance.dos;\n }\n return [];\n}\n\nexport function getGuidanceWhenNot(component: McpComponent): string[] {\n if (component.guidance.whenNot.length > 0) {\n return component.guidance.whenNot;\n }\n if (component.guidance.donts.length > 0) {\n return component.guidance.donts;\n }\n return [];\n}\n"],"mappings":";AAEO,SAAS,eAAe,UAA2D;AACxF,SAAO,OAAO,OAAO,SAAS,UAAU;AAC1C;AAEO,SAAS,eAAe,UAAqD;AAClF,SAAO,eAAe,QAAQ,EAAE,IAAI,CAAC,cAAc,UAAU,IAAI;AACnE;AAEO,SAAS,WAAW,UAAmD;AAC5E,SAAO,OAAO,OAAO,SAAS,UAAU,CAAC,CAAC;AAC5C;AAEO,SAAS,oBACd,UACA,MAC0B;AAC1B,QAAM,QAAQ,KAAK,YAAY;AAC/B,SAAO,eAAe,QAAQ,EAAE;AAAA,IAC9B,CAAC,cAAc,UAAU,KAAK,YAAY,MAAM;AAAA,EAClD;AACF;AAEO,SAAS,gBAAgB,WAAmC;AACjE,MAAI,UAAU,SAAS,KAAK,SAAS,GAAG;AACtC,WAAO,UAAU,SAAS;AAAA,EAC5B;AACA,MAAI,UAAU,SAAS,eAAe;AACpC,WAAO,CAAC,UAAU,SAAS,aAAa;AAAA,EAC1C;AACA,MAAI,UAAU,SAAS,IAAI,SAAS,GAAG;AACrC,WAAO,UAAU,SAAS;AAAA,EAC5B;AACA,SAAO,CAAC;AACV;AAEO,SAAS,mBAAmB,WAAmC;AACpE,MAAI,UAAU,SAAS,QAAQ,SAAS,GAAG;AACzC,WAAO,UAAU,SAAS;AAAA,EAC5B;AACA,MAAI,UAAU,SAAS,MAAM,SAAS,GAAG;AACvC,WAAO,UAAU,SAAS;AAAA,EAC5B;AACA,SAAO,CAAC;AACV;","names":[]}
|
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getGuidanceWhen,
|
|
3
|
+
getGuidanceWhenNot
|
|
4
|
+
} from "./chunk-3IHXJEMM.js";
|
|
5
|
+
|
|
1
6
|
// src/rules.ts
|
|
2
7
|
import { join } from "path";
|
|
3
8
|
import { writeFileSync, mkdirSync, existsSync } from "fs";
|
|
@@ -49,9 +54,9 @@ function buildRulesContent(data, brandName) {
|
|
|
49
54
|
sections.push("## Components\n");
|
|
50
55
|
const byCategory = /* @__PURE__ */ new Map();
|
|
51
56
|
for (const c of components) {
|
|
52
|
-
const cat = c.
|
|
57
|
+
const cat = c.category || "uncategorized";
|
|
53
58
|
if (!byCategory.has(cat)) byCategory.set(cat, []);
|
|
54
|
-
byCategory.get(cat).push(c.
|
|
59
|
+
byCategory.get(cat).push(c.name);
|
|
55
60
|
}
|
|
56
61
|
for (const [cat, names] of byCategory) {
|
|
57
62
|
sections.push(`### ${cat}
|
|
@@ -65,7 +70,7 @@ function buildRulesContent(data, brandName) {
|
|
|
65
70
|
sections.push(`Import components from \`${data.defaultPackageName}\`:
|
|
66
71
|
`);
|
|
67
72
|
sections.push("```typescript");
|
|
68
|
-
const exampleNames = components.slice(0, 3).map((c) => c.
|
|
73
|
+
const exampleNames = components.slice(0, 3).map((c) => c.name);
|
|
69
74
|
sections.push(`import { ${exampleNames.join(", ")} } from '${data.defaultPackageName}';`);
|
|
70
75
|
sections.push("```\n");
|
|
71
76
|
}
|
|
@@ -82,8 +87,8 @@ function buildRulesContent(data, brandName) {
|
|
|
82
87
|
const allDos = [];
|
|
83
88
|
const allDonts = [];
|
|
84
89
|
for (const c of components) {
|
|
85
|
-
|
|
86
|
-
|
|
90
|
+
allDos.push(...getGuidanceWhen(c).slice(0, 1).map((w) => `${c.name}: ${w}`));
|
|
91
|
+
allDonts.push(...getGuidanceWhenNot(c).slice(0, 1).map((w) => `${c.name}: ${w}`));
|
|
87
92
|
}
|
|
88
93
|
if (allDos.length > 0 || allDonts.length > 0) {
|
|
89
94
|
sections.push("## Usage Guidelines\n");
|
|
@@ -104,4 +109,4 @@ function buildRulesContent(data, brandName) {
|
|
|
104
109
|
export {
|
|
105
110
|
generateRulesFiles
|
|
106
111
|
};
|
|
107
|
-
//# sourceMappingURL=chunk-
|
|
112
|
+
//# sourceMappingURL=chunk-7GGI7JJE.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/rules.ts"],"sourcesContent":["import { join } from 'node:path';\nimport { writeFileSync, mkdirSync, existsSync } from 'node:fs';\nimport type { McpComponent } from '@fragments-sdk/core';\nimport type { DesignSystemData } from './types.js';\nimport { getGuidanceWhen, getGuidanceWhenNot } from './snapshot-helpers.js';\n\nexport type RulesFormat = 'cursor' | 'claude' | 'copilot';\n\nexport interface RulesGeneratorOptions {\n data: DesignSystemData;\n brandName: string;\n outputDir: string;\n formats: RulesFormat[];\n /** Overwrite existing files (default: false — skip and warn) */\n force?: boolean;\n}\n\n/**\n * Generate IDE rules files from design system data.\n * Returns list of files written. Skips existing files unless force is true.\n */\nexport function generateRulesFiles(options: RulesGeneratorOptions): string[] {\n const { data, brandName, outputDir, formats, force = false } = options;\n const content = buildRulesContent(data, brandName);\n const files: string[] = [];\n\n for (const format of formats) {\n let filePath: string;\n let fileContent: string;\n\n switch (format) {\n case 'cursor':\n filePath = join(outputDir, '.cursorrules');\n fileContent = content;\n break;\n case 'claude':\n filePath = join(outputDir, 'CLAUDE.md');\n fileContent = `# CLAUDE.md\\n\\nThis file provides guidance to Claude Code when working with code in this repository.\\n\\n${content}`;\n break;\n case 'copilot': {\n const dir = join(outputDir, '.github');\n if (!existsSync(dir)) mkdirSync(dir, { recursive: true });\n filePath = join(dir, 'copilot-instructions.md');\n fileContent = content;\n break;\n }\n }\n\n if (!force && existsSync(filePath)) {\n console.error(` Skipped ${filePath} (already exists, use --force to overwrite)`);\n continue;\n }\n\n writeFileSync(filePath, fileContent, 'utf-8');\n files.push(filePath);\n }\n\n return files;\n}\n\nfunction buildRulesContent(data: DesignSystemData, brandName: string): string {\n const sections: string[] = [];\n\n // Header\n sections.push(`# ${brandName} Design System Rules\\n`);\n sections.push(`Always use ${brandName} components and design tokens when building UI. Do not use raw HTML elements, Tailwind classes, or hardcoded CSS values when a design system component or token exists.\\n`);\n\n // Component inventory\n const components: McpComponent[] = Object.values(data.components);\n if (components.length > 0) {\n sections.push('## Components\\n');\n const byCategory = new Map<string, string[]>();\n for (const c of components) {\n const cat = c.category || 'uncategorized';\n if (!byCategory.has(cat)) byCategory.set(cat, []);\n byCategory.get(cat)!.push(c.name);\n }\n for (const [cat, names] of byCategory) {\n sections.push(`### ${cat}\\n`);\n sections.push(names.map(n => `- ${n}`).join('\\n'));\n sections.push('');\n }\n }\n\n // Import pattern\n if (data.defaultPackageName) {\n sections.push('## Imports\\n');\n sections.push(`Import components from \\`${data.defaultPackageName}\\`:\\n`);\n sections.push('```typescript');\n const exampleNames = components.slice(0, 3).map(c => c.name);\n sections.push(`import { ${exampleNames.join(', ')} } from '${data.defaultPackageName}';`);\n sections.push('```\\n');\n }\n\n // Tokens\n if (data.tokens && data.tokens.total > 0) {\n sections.push('## Design Tokens\\n');\n sections.push(`Prefix: \\`${data.tokens.prefix}\\`. Use \\`var(--token-name)\\` in CSS/styles.\\n`);\n sections.push('Available categories:');\n for (const [cat, tokens] of Object.entries(data.tokens.categories) as Array<\n [string, typeof data.tokens.categories[string]]\n >) {\n sections.push(`- **${cat}** (${tokens.length} tokens)`);\n }\n sections.push('');\n }\n\n // Usage guidelines (aggregated from all components)\n const allDos: string[] = [];\n const allDonts: string[] = [];\n for (const c of components) {\n allDos.push(...getGuidanceWhen(c).slice(0, 1).map(w => `${c.name}: ${w}`));\n allDonts.push(...getGuidanceWhenNot(c).slice(0, 1).map(w => `${c.name}: ${w}`));\n }\n if (allDos.length > 0 || allDonts.length > 0) {\n sections.push('## Usage Guidelines\\n');\n if (allDos.length > 0) {\n sections.push('**Do:**');\n sections.push(allDos.slice(0, 10).map(d => `- ${d}`).join('\\n'));\n sections.push('');\n }\n if (allDonts.length > 0) {\n sections.push('**Don\\'t:**');\n sections.push(allDonts.slice(0, 10).map(d => `- ${d}`).join('\\n'));\n sections.push('');\n }\n }\n\n return sections.join('\\n');\n}\n"],"mappings":"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","names":[]}
|