@fragments-sdk/cli 0.14.3 → 0.15.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 (181) hide show
  1. package/README.md +0 -3
  2. package/dist/{ai-client-I6MDWNYA.js → ai-client-LSLQGOMM.js} +1 -2
  3. package/dist/bin.js +4745 -3817
  4. package/dist/bin.js.map +1 -1
  5. package/dist/{chunk-TXFCEDOC.js → chunk-2WXKALIG.js} +2 -2
  6. package/dist/{chunk-I34BC3CU.js → chunk-32LIWN2P.js} +1006 -3
  7. package/dist/chunk-32LIWN2P.js.map +1 -0
  8. package/dist/chunk-5JF26E55.js +1255 -0
  9. package/dist/chunk-5JF26E55.js.map +1 -0
  10. package/dist/{chunk-APTQIBS5.js → chunk-6SQPP47U.js} +153 -1342
  11. package/dist/chunk-6SQPP47U.js.map +1 -0
  12. package/dist/chunk-7DZC4YEV.js +294 -0
  13. package/dist/chunk-7DZC4YEV.js.map +1 -0
  14. package/dist/{chunk-PJT5IZ37.js → chunk-BJE3425I.js} +19 -52
  15. package/dist/{chunk-PJT5IZ37.js.map → chunk-BJE3425I.js.map} +1 -1
  16. package/dist/{chunk-55KERLWL.js → chunk-HQ6A6DTV.js} +1587 -1073
  17. package/dist/chunk-HQ6A6DTV.js.map +1 -0
  18. package/dist/chunk-MHIBEEW4.js +511 -0
  19. package/dist/chunk-MHIBEEW4.js.map +1 -0
  20. package/dist/{chunk-5A6X2Y73.js → chunk-ONUP6Z4W.js} +25 -13
  21. package/dist/chunk-ONUP6Z4W.js.map +1 -0
  22. package/dist/chunk-QCN35LJU.js +630 -0
  23. package/dist/chunk-QCN35LJU.js.map +1 -0
  24. package/dist/chunk-T47OLCSF.js +36 -0
  25. package/dist/chunk-T47OLCSF.js.map +1 -0
  26. package/dist/codebase-scanner-MQHUZC2G.js +21 -0
  27. package/dist/converter-7XM3Y6NJ.js +33 -0
  28. package/dist/converter-7XM3Y6NJ.js.map +1 -0
  29. package/dist/core/index.js +43 -2
  30. package/dist/create-IH4R45GE.js +806 -0
  31. package/dist/create-IH4R45GE.js.map +1 -0
  32. package/dist/{generate-RYWIPDN2.js → generate-PVOLUAAC.js} +4 -6
  33. package/dist/{generate-RYWIPDN2.js.map → generate-PVOLUAAC.js.map} +1 -1
  34. package/dist/govern-scan-OYFZYOQW.js +413 -0
  35. package/dist/govern-scan-OYFZYOQW.js.map +1 -0
  36. package/dist/index.d.ts +4 -23
  37. package/dist/index.js +15 -14
  38. package/dist/index.js.map +1 -1
  39. package/dist/{init-WRUSW7R5.js → init-SSGUSP7Z.js} +131 -129
  40. package/dist/init-SSGUSP7Z.js.map +1 -0
  41. package/dist/{init-cloud-REQ3XLHO.js → init-cloud-3DNKPWFB.js} +30 -5
  42. package/dist/{init-cloud-REQ3XLHO.js.map → init-cloud-3DNKPWFB.js.map} +1 -1
  43. package/dist/mcp-bin.js +5 -37
  44. package/dist/mcp-bin.js.map +1 -1
  45. package/dist/node-37AUE74M.js +65 -0
  46. package/dist/push-contracts-WY32TFP6.js +84 -0
  47. package/dist/push-contracts-WY32TFP6.js.map +1 -0
  48. package/dist/scan-PKSYSTRR.js +15 -0
  49. package/dist/{scan-generate-TFZVL3BT.js → scan-generate-VY27PIOX.js} +340 -52
  50. package/dist/scan-generate-VY27PIOX.js.map +1 -0
  51. package/dist/scanner-4KZNOXAK.js +12 -0
  52. package/dist/{service-HKJ6B7P7.js → service-QJGWUIVL.js} +41 -30
  53. package/dist/{snapshot-C5DYIGIV.js → snapshot-WIJMEIFT.js} +2 -3
  54. package/dist/{snapshot-C5DYIGIV.js.map → snapshot-WIJMEIFT.js.map} +1 -1
  55. package/dist/{static-viewer-DUVC4UIM.js → static-viewer-7QIBQZRC.js} +3 -4
  56. package/dist/static-viewer-7QIBQZRC.js.map +1 -0
  57. package/dist/{test-JW7JIDFG.js → test-64Z5BKBA.js} +4 -7
  58. package/dist/{test-JW7JIDFG.js.map → test-64Z5BKBA.js.map} +1 -1
  59. package/dist/token-normalizer-TEPOVBPV.js +312 -0
  60. package/dist/token-normalizer-TEPOVBPV.js.map +1 -0
  61. package/dist/token-parser-32KOIOFN.js +22 -0
  62. package/dist/token-parser-32KOIOFN.js.map +1 -0
  63. package/dist/{tokens-KE73G5JC.js → tokens-NZWFQIAB.js} +10 -9
  64. package/dist/{tokens-KE73G5JC.js.map → tokens-NZWFQIAB.js.map} +1 -1
  65. package/dist/tokens-generate-5JQSJ27E.js +85 -0
  66. package/dist/tokens-generate-5JQSJ27E.js.map +1 -0
  67. package/dist/tokens-push-HY3KO36V.js +148 -0
  68. package/dist/tokens-push-HY3KO36V.js.map +1 -0
  69. package/package.json +8 -6
  70. package/src/bin.ts +300 -48
  71. package/src/commands/__fixtures__/shadcn-label-wrapper/package.json +7 -0
  72. package/src/commands/__fixtures__/shadcn-label-wrapper/src/components/ui/label.contract.json +42 -0
  73. package/src/commands/__fixtures__/shadcn-label-wrapper/src/components/ui/label.tsx +11 -0
  74. package/src/commands/__fixtures__/shadcn-label-wrapper/src/components/ui/primitive.contract.json +20 -0
  75. package/src/commands/__fixtures__/shadcn-label-wrapper/src/components/ui/primitive.tsx +14 -0
  76. package/src/commands/__fixtures__/shadcn-label-wrapper/tsconfig.app.json +23 -0
  77. package/src/commands/__tests__/build-freshness.test.ts +231 -0
  78. package/src/commands/__tests__/create.test.ts +71 -0
  79. package/src/commands/__tests__/drift-sync.test.ts +1 -1
  80. package/src/commands/__tests__/govern.test.ts +258 -0
  81. package/src/commands/__tests__/init.test.ts +113 -0
  82. package/src/commands/__tests__/scan-generate.test.ts +189 -70
  83. package/src/commands/__tests__/verify.test.ts +91 -0
  84. package/src/commands/build.ts +54 -1
  85. package/src/commands/context.ts +1 -1
  86. package/src/commands/create.ts +536 -0
  87. package/src/commands/discover.ts +151 -0
  88. package/src/commands/doctor.ts +3 -2
  89. package/src/commands/enhance.ts +3 -1
  90. package/src/commands/govern-scan.ts +565 -0
  91. package/src/commands/govern.ts +67 -4
  92. package/src/commands/init-cloud.ts +32 -4
  93. package/src/commands/init.ts +152 -28
  94. package/src/commands/inspect.ts +290 -0
  95. package/src/commands/migrate-contract.ts +85 -0
  96. package/src/commands/push-contracts.ts +112 -0
  97. package/src/commands/scan-generate.ts +439 -51
  98. package/src/commands/scan.ts +14 -0
  99. package/src/commands/setup.ts +27 -50
  100. package/src/commands/sync.ts +2 -2
  101. package/src/commands/tokens-generate.ts +113 -0
  102. package/src/commands/tokens-push.ts +199 -0
  103. package/src/commands/verify.ts +195 -1
  104. package/src/core/__fixtures__/shadcn-input/input.tsx +7 -0
  105. package/src/core/__fixtures__/shadcn-input/tsconfig.json +14 -0
  106. package/src/core/__fixtures__/shadcn-label/label.tsx +11 -0
  107. package/src/core/__fixtures__/shadcn-label/primitive.tsx +14 -0
  108. package/src/core/__fixtures__/shadcn-label/tsconfig.json +14 -0
  109. package/src/core/__fixtures__/shadcn-radix-label/label.tsx +11 -0
  110. package/src/core/__fixtures__/shadcn-radix-label/node_modules/radix-ui/index.d.ts +12 -0
  111. package/src/core/__fixtures__/shadcn-radix-label/tsconfig.json +14 -0
  112. package/src/core/__tests__/contract-parity.test.ts +316 -0
  113. package/src/core/__tests__/token-resolver.test.ts +1 -1
  114. package/src/core/component-extractor.test.ts +40 -1
  115. package/src/core/config.ts +2 -1
  116. package/src/core/discovery.ts +13 -2
  117. package/src/core/drift-verifier.ts +123 -0
  118. package/src/core/extractor-adapter.ts +80 -0
  119. package/src/index.ts +3 -3
  120. package/src/mcp/__tests__/projectFields.test.ts +1 -1
  121. package/src/mcp/utils.ts +1 -50
  122. package/src/migrate/converter.ts +3 -3
  123. package/src/migrate/fragment-to-contract.ts +253 -0
  124. package/src/migrate/report.ts +1 -1
  125. package/src/scripts/token-benchmark.ts +121 -0
  126. package/src/service/__tests__/props-extractor.test.ts +94 -0
  127. package/src/service/__tests__/token-normalizer.test.ts +690 -0
  128. package/src/service/ast-utils.ts +4 -23
  129. package/src/service/babel-config.ts +23 -0
  130. package/src/service/enhance/converter.ts +61 -0
  131. package/src/service/enhance/props-extractor.ts +25 -8
  132. package/src/service/enhance/scanner.ts +5 -24
  133. package/src/service/index.ts +8 -0
  134. package/src/service/snippet-validation.ts +9 -3
  135. package/src/service/tailwind-v4-parser.ts +314 -0
  136. package/src/service/token-normalizer.ts +510 -0
  137. package/src/service/token-parser.ts +56 -0
  138. package/src/setup.ts +10 -39
  139. package/src/shared/index.ts +1 -0
  140. package/src/shared/project-fields.ts +46 -0
  141. package/src/theme/__tests__/component-contrast.test.ts +2 -2
  142. package/src/theme/__tests__/serializer.test.ts +1 -1
  143. package/src/theme/generator.ts +16 -1
  144. package/src/theme/schema.ts +8 -0
  145. package/src/theme/serializer.ts +13 -9
  146. package/src/theme/types.ts +8 -0
  147. package/src/validators.ts +1 -2
  148. package/src/viewer/__tests__/viewer-integration.test.ts +8 -8
  149. package/src/viewer/style-utils.ts +27 -412
  150. package/src/viewer/vite-plugin.ts +2 -2
  151. package/dist/chunk-55KERLWL.js.map +0 -1
  152. package/dist/chunk-5A6X2Y73.js.map +0 -1
  153. package/dist/chunk-APTQIBS5.js.map +0 -1
  154. package/dist/chunk-EYXVAMEX.js +0 -626
  155. package/dist/chunk-EYXVAMEX.js.map +0 -1
  156. package/dist/chunk-I34BC3CU.js.map +0 -1
  157. package/dist/chunk-LOYS64QS.js +0 -2453
  158. package/dist/chunk-LOYS64QS.js.map +0 -1
  159. package/dist/chunk-Z7EY4VHE.js +0 -50
  160. package/dist/chunk-ZKTFKHWN.js +0 -324
  161. package/dist/chunk-ZKTFKHWN.js.map +0 -1
  162. package/dist/discovery-VDANZAJ2.js +0 -28
  163. package/dist/init-WRUSW7R5.js.map +0 -1
  164. package/dist/sass.node-4XJK6YBF.js +0 -130708
  165. package/dist/sass.node-4XJK6YBF.js.map +0 -1
  166. package/dist/scan-YJHQIRKG.js +0 -14
  167. package/dist/scan-generate-TFZVL3BT.js.map +0 -1
  168. package/dist/viewer-2TZS3NDL.js +0 -2730
  169. package/dist/viewer-2TZS3NDL.js.map +0 -1
  170. package/src/build.ts +0 -612
  171. package/src/commands/dev.ts +0 -107
  172. package/src/core/auto-props.ts +0 -464
  173. package/src/core/component-extractor.ts +0 -1030
  174. package/src/core/token-resolver.ts +0 -155
  175. /package/dist/{ai-client-I6MDWNYA.js.map → ai-client-LSLQGOMM.js.map} +0 -0
  176. /package/dist/{chunk-TXFCEDOC.js.map → chunk-2WXKALIG.js.map} +0 -0
  177. /package/dist/{chunk-Z7EY4VHE.js.map → codebase-scanner-MQHUZC2G.js.map} +0 -0
  178. /package/dist/{discovery-VDANZAJ2.js.map → node-37AUE74M.js.map} +0 -0
  179. /package/dist/{scan-YJHQIRKG.js.map → scan-PKSYSTRR.js.map} +0 -0
  180. /package/dist/{service-HKJ6B7P7.js.map → scanner-4KZNOXAK.js.map} +0 -0
  181. /package/dist/{static-viewer-DUVC4UIM.js.map → service-QJGWUIVL.js.map} +0 -0
@@ -0,0 +1,413 @@
1
+ import { createRequire as __banner_createRequire } from 'module'; const require = __banner_createRequire(import.meta.url);
2
+ import "./chunk-D2CDBRNU.js";
3
+ import {
4
+ BRAND
5
+ } from "./chunk-32LIWN2P.js";
6
+
7
+ // src/commands/govern-scan.ts
8
+ import pc from "picocolors";
9
+ import { resolve, relative } from "path";
10
+ import { existsSync } from "fs";
11
+ var SCAN_DEFAULT_RULES = {
12
+ "safety/no-dangerous-html": true,
13
+ "safety/sanitize-hrefs": true,
14
+ "safety/no-inline-scripts": true,
15
+ "safety/no-exposed-secrets": true,
16
+ "tokens/require-design-tokens": true
17
+ };
18
+ function detectRootDir(cwd) {
19
+ const candidates = ["src", "app", "pages", "components"];
20
+ for (const dir of candidates) {
21
+ if (existsSync(resolve(cwd, dir))) {
22
+ return cwd;
23
+ }
24
+ }
25
+ return cwd;
26
+ }
27
+ function groupByFile(usages) {
28
+ const grouped = /* @__PURE__ */ new Map();
29
+ for (const usage of usages) {
30
+ const existing = grouped.get(usage.filePath);
31
+ if (existing) {
32
+ existing.push(usage);
33
+ } else {
34
+ grouped.set(usage.filePath, [usage]);
35
+ }
36
+ }
37
+ return grouped;
38
+ }
39
+ async function governScan(options = {}) {
40
+ const {
41
+ loadPolicy,
42
+ createEngine,
43
+ buildAdaptersFromConfig,
44
+ createCloudAdapter,
45
+ formatVerdict,
46
+ computeComponentHealth
47
+ } = await import("@fragments-sdk/govern");
48
+ const { scanCodebase } = await import("./codebase-scanner-MQHUZC2G.js");
49
+ const { usagesToSpec } = await import("./converter-7XM3Y6NJ.js");
50
+ const format = options.format ?? "summary";
51
+ const quiet = options.quiet ?? false;
52
+ if (!quiet) {
53
+ console.log(pc.cyan(`
54
+ ${BRAND.name} Governance Scan
55
+ `));
56
+ }
57
+ const rootDir = resolve(options.dir ?? detectRootDir(process.cwd()));
58
+ if (!quiet) {
59
+ console.log(pc.dim(` Root: ${rootDir}
60
+ `));
61
+ }
62
+ let policy = await loadPolicy(options.config);
63
+ const hasRules = Object.keys(policy.rules).length > 0;
64
+ if (!hasRules) {
65
+ policy = { ...policy, rules: SCAN_DEFAULT_RULES };
66
+ if (!quiet) {
67
+ console.log(pc.dim(" No config found \u2014 using scan defaults (safety + tokens)\n"));
68
+ }
69
+ }
70
+ let codeTokens;
71
+ if (process.env.FRAGMENTS_API_KEY) {
72
+ codeTokens = await extractCodeTokens(rootDir, options.config, quiet);
73
+ }
74
+ let contractRegistry;
75
+ let registryMap;
76
+ {
77
+ const { readFileSync, existsSync: existsSync2 } = await import("fs");
78
+ const fragmentsJsonPath = resolve(rootDir, "fragments.json");
79
+ if (existsSync2(fragmentsJsonPath)) {
80
+ try {
81
+ const raw = readFileSync(fragmentsJsonPath, "utf-8");
82
+ const parsed = JSON.parse(raw);
83
+ if (parsed.fragments && Array.isArray(parsed.fragments)) {
84
+ const map = {};
85
+ for (const f of parsed.fragments) {
86
+ if (f.meta?.name) {
87
+ map[f.meta.name] = f;
88
+ }
89
+ }
90
+ registryMap = map;
91
+ if (process.env.FRAGMENTS_API_KEY) {
92
+ contractRegistry = JSON.stringify({ fragments: parsed.fragments });
93
+ }
94
+ if (!quiet) {
95
+ console.log(pc.dim(` Contract registry loaded (${parsed.fragments.length} components)
96
+ `));
97
+ }
98
+ }
99
+ } catch {
100
+ }
101
+ }
102
+ }
103
+ const adapters = buildAdaptersFromConfig(policy.audit);
104
+ const hasCloudAdapter = adapters.length > 0 && policy.audit?.cloud;
105
+ if (!hasCloudAdapter && process.env.FRAGMENTS_API_KEY) {
106
+ adapters.push(createCloudAdapter({ codeTokens, contractRegistry }));
107
+ if (!quiet) {
108
+ console.log(pc.dim(" Cloud audit enabled (FRAGMENTS_API_KEY detected)\n"));
109
+ }
110
+ }
111
+ const engine = createEngine(
112
+ policy,
113
+ adapters,
114
+ registryMap ? { registry: { fragments: registryMap } } : void 0
115
+ );
116
+ if (!quiet) {
117
+ console.log(pc.dim(" Scanning files...\n"));
118
+ }
119
+ const analysis = await scanCodebase({
120
+ rootDir,
121
+ useCache: true,
122
+ onProgress: quiet ? void 0 : (progress) => {
123
+ if (progress.phase === "scanning") {
124
+ process.stdout.write(
125
+ `\r ${pc.dim(`[${progress.current}/${progress.total}]`)} ${pc.dim(relative(rootDir, progress.currentFile))}`
126
+ );
127
+ }
128
+ }
129
+ });
130
+ if (!quiet) {
131
+ process.stdout.write("\r" + " ".repeat(80) + "\r");
132
+ console.log(
133
+ pc.dim(` Scanned ${analysis.totalFiles} files, found ${analysis.totalComponents} component types
134
+ `)
135
+ );
136
+ }
137
+ const allUsages = [];
138
+ for (const comp of Object.values(analysis.components)) {
139
+ allUsages.push(...comp.usages);
140
+ }
141
+ if (allUsages.length === 0) {
142
+ if (!quiet) {
143
+ console.log(pc.yellow(" No component usages found.\n"));
144
+ }
145
+ return { exitCode: 0 };
146
+ }
147
+ const grouped = groupByFile(allUsages);
148
+ let totalFiles = 0;
149
+ let passedFiles = 0;
150
+ let totalViolations = 0;
151
+ const violationCounts = /* @__PURE__ */ new Map();
152
+ const allVerdicts = [];
153
+ const usageSnapshot = [];
154
+ for (const [filePath, usages] of grouped) {
155
+ const spec = usagesToSpec(usages, filePath, rootDir);
156
+ const relPath = relative(rootDir, filePath);
157
+ const verdict = await engine.check(spec, {
158
+ runner: "cli",
159
+ input: relPath
160
+ });
161
+ allVerdicts.push(verdict);
162
+ usageSnapshot.push({
163
+ file: relPath,
164
+ components: usages.map((u) => ({
165
+ name: u.componentName,
166
+ line: u.line,
167
+ props: {
168
+ static: u.props.static,
169
+ dynamic: u.props.dynamic
170
+ }
171
+ }))
172
+ });
173
+ totalFiles++;
174
+ if (verdict.passed) {
175
+ passedFiles++;
176
+ } else {
177
+ if (!quiet) {
178
+ console.log(pc.red(` \u2717 ${relPath}`));
179
+ if (format === "summary") {
180
+ for (const result of verdict.results) {
181
+ for (const v of result.violations) {
182
+ const count = violationCounts.get(v.rule) ?? 0;
183
+ violationCounts.set(v.rule, count + 1);
184
+ totalViolations++;
185
+ console.log(
186
+ pc.dim(` ${v.severity} `) + pc.yellow(v.rule) + pc.dim(` \u2014 ${v.message}`)
187
+ );
188
+ if (v.nodeId) {
189
+ console.log(pc.dim(` at ${v.nodeId}`));
190
+ }
191
+ }
192
+ }
193
+ }
194
+ }
195
+ }
196
+ if (verdict.passed && !quiet && format === "summary") {
197
+ console.log(pc.green(` \u2713 ${relPath}`) + pc.dim(` (${usages.length} components, score: ${verdict.score}/100)`));
198
+ }
199
+ if (format === "json" || format === "sarif") {
200
+ const output = formatVerdict(verdict, format);
201
+ console.log(output);
202
+ }
203
+ }
204
+ const health = computeComponentHealth(allVerdicts, registryMap ?? {});
205
+ if (!quiet && format === "summary") {
206
+ console.log(pc.dim("\n \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n"));
207
+ console.log(` Files checked: ${totalFiles}`);
208
+ console.log(` Passed: ${passedFiles}/${totalFiles}`);
209
+ console.log(` Violations: ${totalViolations}`);
210
+ if (violationCounts.size > 0) {
211
+ console.log(pc.dim("\n Top violations:"));
212
+ const sorted = [...violationCounts.entries()].sort((a, b) => b[1] - a[1]);
213
+ for (const [rule, count] of sorted.slice(0, 5)) {
214
+ console.log(pc.dim(` ${count}\xD7 `) + pc.yellow(rule));
215
+ }
216
+ }
217
+ console.log(pc.dim("\n Component Health:"));
218
+ console.log(` Contract coverage: ${health.contractCoverage}% (${health.contractedComponents}/${health.totalComponents})`);
219
+ console.log(` Compliance rate: ${health.overallCompliance}%`);
220
+ if (health.uncontracted.length > 0) {
221
+ console.log(pc.dim(` Uncontracted: ${health.uncontracted.slice(0, 5).join(", ")}${health.uncontracted.length > 5 ? ` (+${health.uncontracted.length - 5} more)` : ""}`));
222
+ }
223
+ console.log();
224
+ if (passedFiles === totalFiles) {
225
+ console.log(pc.green(` \u2713 All files passed governance checks
226
+ `));
227
+ } else {
228
+ console.log(
229
+ pc.red(` \u2717 ${totalFiles - passedFiles} file(s) failed governance checks
230
+ `)
231
+ );
232
+ }
233
+ }
234
+ if (process.env.FRAGMENTS_API_KEY && usageSnapshot.length > 0) {
235
+ try {
236
+ const apiKey = process.env.FRAGMENTS_API_KEY;
237
+ const url = process.env.FRAGMENTS_URL ?? "https://app.usefragments.com";
238
+ await fetch(`${url}/api/ingest`, {
239
+ method: "POST",
240
+ headers: {
241
+ "Content-Type": "application/json",
242
+ Authorization: `Bearer ${apiKey}`
243
+ },
244
+ body: JSON.stringify({
245
+ componentUsage: JSON.stringify(usageSnapshot),
246
+ componentHealth: JSON.stringify(health)
247
+ })
248
+ });
249
+ } catch {
250
+ }
251
+ }
252
+ return { exitCode: passedFiles === totalFiles ? 0 : 1 };
253
+ }
254
+ async function extractCodeTokens(rootDir, configPath, quiet) {
255
+ try {
256
+ try {
257
+ const { loadConfig } = await import("./node-37AUE74M.js");
258
+ const { parseTokenFiles } = await import("./service-QJGWUIVL.js");
259
+ const { config, configDir } = await loadConfig(configPath);
260
+ if (config.tokens?.include?.length) {
261
+ const result = await parseTokenFiles(config.tokens, configDir);
262
+ if (result.tokens.length > 0) {
263
+ const flat = {};
264
+ for (const token of result.tokens) {
265
+ flat[token.name] = token.resolvedValue;
266
+ }
267
+ if (!quiet) {
268
+ console.log(
269
+ pc.dim(` Extracted ${result.tokens.length} code tokens from config
270
+ `)
271
+ );
272
+ }
273
+ return JSON.stringify(flat);
274
+ }
275
+ }
276
+ } catch {
277
+ }
278
+ const {
279
+ findTailwindConfig,
280
+ loadTailwindConfig
281
+ } = await import("./token-normalizer-TEPOVBPV.js");
282
+ const tailwindPath = findTailwindConfig(rootDir);
283
+ if (tailwindPath) {
284
+ const tokens = await loadTailwindConfig(tailwindPath);
285
+ if (tokens.length > 0) {
286
+ const flat = {};
287
+ for (const token of tokens) {
288
+ flat[token.name] = token.value;
289
+ }
290
+ if (!quiet) {
291
+ console.log(
292
+ pc.dim(` Extracted ${tokens.length} tokens from Tailwind config
293
+ `)
294
+ );
295
+ }
296
+ return JSON.stringify(flat);
297
+ }
298
+ }
299
+ } catch (error) {
300
+ if (!quiet) {
301
+ console.log(
302
+ pc.dim(
303
+ ` Token extraction skipped: ${error instanceof Error ? error.message : "unknown error"}
304
+ `
305
+ )
306
+ );
307
+ }
308
+ }
309
+ return void 0;
310
+ }
311
+ async function governWatch(options = {}) {
312
+ const {
313
+ loadPolicy,
314
+ createEngine,
315
+ buildAdaptersFromConfig,
316
+ createCloudAdapter,
317
+ formatVerdict
318
+ } = await import("@fragments-sdk/govern");
319
+ const { scanFile } = await import("./scanner-4KZNOXAK.js");
320
+ const { usagesToSpec } = await import("./converter-7XM3Y6NJ.js");
321
+ const quiet = options.quiet ?? false;
322
+ const debounceMs = options.debounce ?? 300;
323
+ const format = options.format ?? "summary";
324
+ console.log(pc.cyan(`
325
+ ${BRAND.name} Governance Watch
326
+ `));
327
+ const { exitCode } = await governScan(options);
328
+ if (!quiet) {
329
+ console.log(
330
+ pc.dim(` Initial scan ${exitCode === 0 ? "passed" : "completed with violations"}
331
+ `)
332
+ );
333
+ }
334
+ const rootDir = resolve(options.dir ?? detectRootDir(process.cwd()));
335
+ let policy = await loadPolicy(options.config);
336
+ if (Object.keys(policy.rules).length === 0) {
337
+ policy = { ...policy, rules: SCAN_DEFAULT_RULES };
338
+ }
339
+ const adapters = buildAdaptersFromConfig(policy.audit);
340
+ if (!adapters.some(() => policy.audit?.cloud) && process.env.FRAGMENTS_API_KEY) {
341
+ adapters.push(createCloudAdapter());
342
+ }
343
+ const engine = createEngine(policy, adapters);
344
+ console.log(pc.dim(" Watching for changes... (Ctrl+C to stop)\n"));
345
+ const chokidar = await import("chokidar");
346
+ const watcher = chokidar.watch(
347
+ ["**/*.tsx", "**/*.ts", "**/*.jsx", "**/*.js"],
348
+ {
349
+ cwd: rootDir,
350
+ ignoreInitial: true,
351
+ ignored: [
352
+ "**/node_modules/**",
353
+ "**/dist/**",
354
+ "**/build/**",
355
+ "**/.next/**",
356
+ "**/*.test.*",
357
+ "**/*.spec.*",
358
+ "**/*.stories.*"
359
+ ],
360
+ awaitWriteFinish: { stabilityThreshold: debounceMs }
361
+ }
362
+ );
363
+ const handleChange = async (changedRelPath) => {
364
+ const absolutePath = resolve(rootDir, changedRelPath);
365
+ try {
366
+ const { usages } = await scanFile(absolutePath);
367
+ if (usages.length === 0) {
368
+ if (!quiet) {
369
+ console.log(pc.dim(` \u25CB ${changedRelPath} \u2014 no component usages`));
370
+ }
371
+ return;
372
+ }
373
+ const spec = usagesToSpec(usages, absolutePath, rootDir);
374
+ const verdict = await engine.check(spec, {
375
+ runner: "cli",
376
+ input: changedRelPath
377
+ });
378
+ if (verdict.passed) {
379
+ console.log(
380
+ pc.green(` \u2713 ${changedRelPath}`) + pc.dim(` (${usages.length} components, score: ${verdict.score}/100)`)
381
+ );
382
+ } else {
383
+ console.log(pc.red(` \u2717 ${changedRelPath}`));
384
+ if (format === "summary") {
385
+ for (const result of verdict.results) {
386
+ for (const v of result.violations) {
387
+ console.log(
388
+ pc.dim(` ${v.severity} `) + pc.yellow(v.rule) + pc.dim(` \u2014 ${v.message}`)
389
+ );
390
+ }
391
+ }
392
+ } else {
393
+ console.log(formatVerdict(verdict, format));
394
+ }
395
+ }
396
+ } catch (error) {
397
+ if (!quiet) {
398
+ console.log(
399
+ pc.dim(` \u26A0 ${changedRelPath} \u2014 `) + pc.yellow(error instanceof Error ? error.message : "parse error")
400
+ );
401
+ }
402
+ }
403
+ };
404
+ watcher.on("change", handleChange);
405
+ watcher.on("add", handleChange);
406
+ await new Promise(() => {
407
+ });
408
+ }
409
+ export {
410
+ governScan,
411
+ governWatch
412
+ };
413
+ //# sourceMappingURL=govern-scan-OYFZYOQW.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/govern-scan.ts"],"sourcesContent":["/**\n * govern scan / govern watch — Zero-config governance scanning\n *\n * Parses real JSX/TSX files via the existing codebase scanner, converts\n * component usages to UISpec, and runs governance checks per file.\n * Optionally submits results to Fragments Cloud.\n */\n\nimport pc from 'picocolors';\nimport { resolve, relative } from 'node:path';\nimport { existsSync } from 'node:fs';\nimport { BRAND } from '../core/index.js';\nimport type { ComponentUsage } from '../service/enhance/types.js';\n\n// ---------------------------------------------------------------------------\n// Options\n// ---------------------------------------------------------------------------\n\nexport interface GovernScanOptions {\n /** Root directory to scan (default: auto-detect) */\n dir?: string;\n /** Path to govern.config.ts */\n config?: string;\n /** Output format */\n format?: 'summary' | 'json' | 'sarif';\n /** Suppress non-error output */\n quiet?: boolean;\n}\n\nexport interface GovernWatchOptions extends GovernScanOptions {\n /** Debounce interval in ms (default: 300) */\n debounce?: number;\n}\n\n// ---------------------------------------------------------------------------\n// Scan defaults — applied when no config file exists\n// ---------------------------------------------------------------------------\n\nconst SCAN_DEFAULT_RULES: Record<string, boolean | object> = {\n 'safety/no-dangerous-html': true,\n 'safety/sanitize-hrefs': true,\n 'safety/no-inline-scripts': true,\n 'safety/no-exposed-secrets': true,\n 'tokens/require-design-tokens': true,\n};\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Auto-detect root directory by looking for common React project dirs\n */\nfunction detectRootDir(cwd: string): string {\n const candidates = ['src', 'app', 'pages', 'components'];\n for (const dir of candidates) {\n if (existsSync(resolve(cwd, dir))) {\n return cwd;\n }\n }\n return cwd;\n}\n\n/**\n * Group component usages by their source file\n */\nfunction groupByFile(usages: ComponentUsage[]): Map<string, ComponentUsage[]> {\n const grouped = new Map<string, ComponentUsage[]>();\n for (const usage of usages) {\n const existing = grouped.get(usage.filePath);\n if (existing) {\n existing.push(usage);\n } else {\n grouped.set(usage.filePath, [usage]);\n }\n }\n return grouped;\n}\n\n// ---------------------------------------------------------------------------\n// governScan\n// ---------------------------------------------------------------------------\n\nexport async function governScan(\n options: GovernScanOptions = {},\n): Promise<{ exitCode: number }> {\n const {\n loadPolicy,\n createEngine,\n buildAdaptersFromConfig,\n createCloudAdapter,\n formatVerdict,\n computeComponentHealth,\n } = await import('@fragments-sdk/govern');\n\n const { scanCodebase } = await import(\n '../service/enhance/codebase-scanner.js'\n );\n const { usagesToSpec } = await import(\n '../service/enhance/converter.js'\n );\n\n const format = options.format ?? 'summary';\n const quiet = options.quiet ?? false;\n\n if (!quiet) {\n console.log(pc.cyan(`\\n${BRAND.name} Governance Scan\\n`));\n }\n\n // 1. Resolve root directory\n const rootDir = resolve(options.dir ?? detectRootDir(process.cwd()));\n if (!quiet) {\n console.log(pc.dim(` Root: ${rootDir}\\n`));\n }\n\n // 2. Load policy — use scan defaults if no config exists\n let policy = await loadPolicy(options.config);\n const hasRules = Object.keys(policy.rules).length > 0;\n\n if (!hasRules) {\n policy = { ...policy, rules: SCAN_DEFAULT_RULES };\n if (!quiet) {\n console.log(pc.dim(' No config found — using scan defaults (safety + tokens)\\n'));\n }\n }\n\n // 3. Extract code tokens for cloud ingest\n let codeTokens: string | undefined;\n if (process.env.FRAGMENTS_API_KEY) {\n codeTokens = await extractCodeTokens(rootDir, options.config, quiet);\n }\n\n // 3b. Load contract registry for governance + cloud ingest (if fragments.json exists)\n let contractRegistry: string | undefined;\n let registryMap: Record<string, unknown> | undefined;\n {\n const { readFileSync, existsSync } = await import('node:fs');\n const fragmentsJsonPath = resolve(rootDir, 'fragments.json');\n if (existsSync(fragmentsJsonPath)) {\n try {\n const raw = readFileSync(fragmentsJsonPath, 'utf-8');\n const parsed = JSON.parse(raw);\n if (parsed.fragments && Array.isArray(parsed.fragments)) {\n // Build name-keyed map for engine registry injection\n const map: Record<string, unknown> = {};\n for (const f of parsed.fragments) {\n if (f.meta?.name) {\n map[f.meta.name] = f;\n }\n }\n registryMap = map;\n\n if (process.env.FRAGMENTS_API_KEY) {\n contractRegistry = JSON.stringify({ fragments: parsed.fragments });\n }\n if (!quiet) {\n console.log(pc.dim(` Contract registry loaded (${parsed.fragments.length} components)\\n`));\n }\n }\n } catch {\n // Invalid fragments.json — skip\n }\n }\n }\n\n // 4. Build adapters. Auto-add cloud if FRAGMENTS_API_KEY is set\n const adapters = buildAdaptersFromConfig(policy.audit);\n const hasCloudAdapter = adapters.length > 0 && policy.audit?.cloud;\n if (!hasCloudAdapter && process.env.FRAGMENTS_API_KEY) {\n adapters.push(createCloudAdapter({ codeTokens, contractRegistry }));\n if (!quiet) {\n console.log(pc.dim(' Cloud audit enabled (FRAGMENTS_API_KEY detected)\\n'));\n }\n }\n\n // 5. Create engine (with registry for contract-aware validators)\n const engine = createEngine(\n policy,\n adapters,\n registryMap\n ? { registry: { fragments: registryMap as Record<string, Record<string, unknown>> } }\n : undefined,\n );\n\n // 6. Scan codebase\n if (!quiet) {\n console.log(pc.dim(' Scanning files...\\n'));\n }\n\n const analysis = await scanCodebase({\n rootDir,\n useCache: true,\n onProgress: quiet\n ? undefined\n : (progress) => {\n if (progress.phase === 'scanning') {\n process.stdout.write(\n `\\r ${pc.dim(`[${progress.current}/${progress.total}]`)} ${pc.dim(relative(rootDir, progress.currentFile))}`,\n );\n }\n },\n });\n\n if (!quiet) {\n // Clear progress line\n process.stdout.write('\\r' + ' '.repeat(80) + '\\r');\n console.log(\n pc.dim(` Scanned ${analysis.totalFiles} files, found ${analysis.totalComponents} component types\\n`),\n );\n }\n\n // 7. Collect all usages across components\n const allUsages: ComponentUsage[] = [];\n for (const comp of Object.values(analysis.components)) {\n allUsages.push(...comp.usages);\n }\n\n if (allUsages.length === 0) {\n if (!quiet) {\n console.log(pc.yellow(' No component usages found.\\n'));\n }\n return { exitCode: 0 };\n }\n\n // 8. Group by file and run checks\n const grouped = groupByFile(allUsages);\n let totalFiles = 0;\n let passedFiles = 0;\n let totalViolations = 0;\n const violationCounts = new Map<string, number>();\n const allVerdicts: Awaited<ReturnType<typeof engine.check>>[] = [];\n\n // Build per-file usage snapshot for cloud\n const usageSnapshot: Array<{\n file: string;\n components: Array<{\n name: string;\n line: number;\n props: { static: Record<string, unknown>; dynamic: string[] };\n }>;\n }> = [];\n\n for (const [filePath, usages] of grouped) {\n const spec = usagesToSpec(usages, filePath, rootDir);\n const relPath = relative(rootDir, filePath);\n\n const verdict = await engine.check(spec, {\n runner: 'cli',\n input: relPath,\n });\n allVerdicts.push(verdict);\n\n // Collect per-file usage snapshot\n usageSnapshot.push({\n file: relPath,\n components: usages.map((u) => ({\n name: u.componentName,\n line: u.line,\n props: {\n static: u.props.static,\n dynamic: u.props.dynamic,\n },\n })),\n });\n\n totalFiles++;\n\n if (verdict.passed) {\n passedFiles++;\n } else {\n if (!quiet) {\n console.log(pc.red(` ✗ ${relPath}`));\n if (format === 'summary') {\n for (const result of verdict.results) {\n for (const v of result.violations) {\n const count = violationCounts.get(v.rule) ?? 0;\n violationCounts.set(v.rule, count + 1);\n totalViolations++;\n console.log(\n pc.dim(` ${v.severity} `) +\n pc.yellow(v.rule) +\n pc.dim(` — ${v.message}`),\n );\n if (v.nodeId) {\n console.log(pc.dim(` at ${v.nodeId}`));\n }\n }\n }\n }\n }\n }\n\n if (verdict.passed && !quiet && format === 'summary') {\n console.log(pc.green(` ✓ ${relPath}`) + pc.dim(` (${usages.length} components, score: ${verdict.score}/100)`));\n }\n\n // JSON/SARIF: print per-file\n if (format === 'json' || format === 'sarif') {\n const output = formatVerdict(verdict, format);\n console.log(output);\n }\n }\n\n // 8b. Compute component health\n const health = computeComponentHealth(allVerdicts, registryMap ?? {});\n\n // 9. Summary\n if (!quiet && format === 'summary') {\n console.log(pc.dim('\\n ─────────────────────────────────────\\n'));\n console.log(` Files checked: ${totalFiles}`);\n console.log(` Passed: ${passedFiles}/${totalFiles}`);\n console.log(` Violations: ${totalViolations}`);\n\n if (violationCounts.size > 0) {\n console.log(pc.dim('\\n Top violations:'));\n const sorted = [...violationCounts.entries()].sort((a, b) => b[1] - a[1]);\n for (const [rule, count] of sorted.slice(0, 5)) {\n console.log(pc.dim(` ${count}× `) + pc.yellow(rule));\n }\n }\n\n // Component health\n console.log(pc.dim('\\n Component Health:'));\n console.log(` Contract coverage: ${health.contractCoverage}% (${health.contractedComponents}/${health.totalComponents})`);\n console.log(` Compliance rate: ${health.overallCompliance}%`);\n\n if (health.uncontracted.length > 0) {\n console.log(pc.dim(` Uncontracted: ${health.uncontracted.slice(0, 5).join(', ')}${health.uncontracted.length > 5 ? ` (+${health.uncontracted.length - 5} more)` : ''}`));\n }\n\n console.log();\n\n if (passedFiles === totalFiles) {\n console.log(pc.green(` ✓ All files passed governance checks\\n`));\n } else {\n console.log(\n pc.red(` ✗ ${totalFiles - passedFiles} file(s) failed governance checks\\n`),\n );\n }\n }\n\n // 10. Push component usage snapshot + health to Cloud (if API key set)\n if (process.env.FRAGMENTS_API_KEY && usageSnapshot.length > 0) {\n try {\n const apiKey = process.env.FRAGMENTS_API_KEY;\n const url = process.env.FRAGMENTS_URL ?? 'https://app.usefragments.com';\n await fetch(`${url}/api/ingest`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${apiKey}`,\n },\n body: JSON.stringify({\n componentUsage: JSON.stringify(usageSnapshot),\n componentHealth: JSON.stringify(health),\n }),\n });\n } catch {\n // Non-critical — don't fail the scan\n }\n }\n\n return { exitCode: passedFiles === totalFiles ? 0 : 1 };\n}\n\n// ---------------------------------------------------------------------------\n// Token extraction for cloud ingest\n// ---------------------------------------------------------------------------\n\n/**\n * Auto-detect and extract code tokens to send alongside governance verdicts.\n * Tries: 1) tokens config from fragments.config.ts, 2) Tailwind config.\n * Returns a flat JSON string of token name → value, or undefined if nothing found.\n */\nasync function extractCodeTokens(\n rootDir: string,\n configPath?: string,\n quiet?: boolean,\n): Promise<string | undefined> {\n try {\n // 1. Try fragments.config.ts tokens config\n try {\n const { loadConfig } = await import('../core/node.js');\n const { parseTokenFiles } = await import('../service/index.js');\n\n const { config, configDir } = await loadConfig(configPath);\n if (config.tokens?.include?.length) {\n const result = await parseTokenFiles(config.tokens, configDir);\n if (result.tokens.length > 0) {\n const flat: Record<string, string> = {};\n for (const token of result.tokens) {\n flat[token.name] = token.resolvedValue;\n }\n if (!quiet) {\n console.log(\n pc.dim(` Extracted ${result.tokens.length} code tokens from config\\n`),\n );\n }\n return JSON.stringify(flat);\n }\n }\n } catch {\n // No config or no tokens section — fall through\n }\n\n // 2. Try Tailwind config\n const {\n findTailwindConfig,\n loadTailwindConfig,\n } = await import('../service/token-normalizer.js');\n\n const tailwindPath = findTailwindConfig(rootDir);\n if (tailwindPath) {\n const tokens = await loadTailwindConfig(tailwindPath);\n if (tokens.length > 0) {\n const flat: Record<string, string> = {};\n for (const token of tokens) {\n flat[token.name] = token.value;\n }\n if (!quiet) {\n console.log(\n pc.dim(` Extracted ${tokens.length} tokens from Tailwind config\\n`),\n );\n }\n return JSON.stringify(flat);\n }\n }\n } catch (error) {\n if (!quiet) {\n console.log(\n pc.dim(\n ` Token extraction skipped: ${error instanceof Error ? error.message : 'unknown error'}\\n`,\n ),\n );\n }\n }\n\n return undefined;\n}\n\n// ---------------------------------------------------------------------------\n// governWatch\n// ---------------------------------------------------------------------------\n\nexport async function governWatch(\n options: GovernWatchOptions = {},\n): Promise<void> {\n const {\n loadPolicy,\n createEngine,\n buildAdaptersFromConfig,\n createCloudAdapter,\n formatVerdict,\n } = await import('@fragments-sdk/govern');\n\n const { scanFile } = await import('../service/enhance/scanner.js');\n const { usagesToSpec } = await import(\n '../service/enhance/converter.js'\n );\n\n const quiet = options.quiet ?? false;\n const debounceMs = options.debounce ?? 300;\n const format = options.format ?? 'summary';\n\n // 1. Run initial scan\n console.log(pc.cyan(`\\n${BRAND.name} Governance Watch\\n`));\n\n const { exitCode } = await governScan(options);\n if (!quiet) {\n console.log(\n pc.dim(` Initial scan ${exitCode === 0 ? 'passed' : 'completed with violations'}\\n`),\n );\n }\n\n // 2. Set up engine for incremental checks\n const rootDir = resolve(options.dir ?? detectRootDir(process.cwd()));\n let policy = await loadPolicy(options.config);\n if (Object.keys(policy.rules).length === 0) {\n policy = { ...policy, rules: SCAN_DEFAULT_RULES };\n }\n const adapters = buildAdaptersFromConfig(policy.audit);\n if (!adapters.some(() => policy.audit?.cloud) && process.env.FRAGMENTS_API_KEY) {\n adapters.push(createCloudAdapter());\n }\n const engine = createEngine(policy, adapters);\n\n // 3. Watch for changes\n console.log(pc.dim(' Watching for changes... (Ctrl+C to stop)\\n'));\n\n const chokidar = await import('chokidar');\n\n const watcher = chokidar.watch(\n ['**/*.tsx', '**/*.ts', '**/*.jsx', '**/*.js'],\n {\n cwd: rootDir,\n ignoreInitial: true,\n ignored: [\n '**/node_modules/**',\n '**/dist/**',\n '**/build/**',\n '**/.next/**',\n '**/*.test.*',\n '**/*.spec.*',\n '**/*.stories.*',\n ],\n awaitWriteFinish: { stabilityThreshold: debounceMs },\n },\n );\n\n const handleChange = async (changedRelPath: string) => {\n const absolutePath = resolve(rootDir, changedRelPath);\n\n try {\n const { usages } = await scanFile(absolutePath);\n\n if (usages.length === 0) {\n if (!quiet) {\n console.log(pc.dim(` ○ ${changedRelPath} — no component usages`));\n }\n return;\n }\n\n const spec = usagesToSpec(usages, absolutePath, rootDir);\n const verdict = await engine.check(spec, {\n runner: 'cli',\n input: changedRelPath,\n });\n\n if (verdict.passed) {\n console.log(\n pc.green(` ✓ ${changedRelPath}`) +\n pc.dim(` (${usages.length} components, score: ${verdict.score}/100)`),\n );\n } else {\n console.log(pc.red(` ✗ ${changedRelPath}`));\n if (format === 'summary') {\n for (const result of verdict.results) {\n for (const v of result.violations) {\n console.log(\n pc.dim(` ${v.severity} `) +\n pc.yellow(v.rule) +\n pc.dim(` — ${v.message}`),\n );\n }\n }\n } else {\n console.log(formatVerdict(verdict, format));\n }\n }\n } catch (error) {\n if (!quiet) {\n console.log(\n pc.dim(` ⚠ ${changedRelPath} — `) +\n pc.yellow(error instanceof Error ? error.message : 'parse error'),\n );\n }\n }\n };\n\n watcher.on('change', handleChange);\n watcher.on('add', handleChange);\n\n // Keep process alive\n await new Promise(() => {});\n}\n"],"mappings":"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","names":["existsSync"]}
package/dist/index.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import { FragmentsConfig, Theme, DiffResult, CompiledFragmentsFile } from '@fragments-sdk/core';
2
2
  export { FragmentsConfig, defineBlock, defineFragment } from '@fragments-sdk/core';
3
+ export { BuildResult, buildFragments } from '@fragments-sdk/compiler';
3
4
  export { CLI_COMMANDS, CLI_COMMAND_CATEGORIES, CliCategoryInfo, CliCommandCategory, CliCommandDef, CliOptionDef } from '@fragments-sdk/context/cli-commands';
4
5
 
5
6
  /**
@@ -22,7 +23,8 @@ interface DiscoveredFile {
22
23
  relativePath: string;
23
24
  }
24
25
  /**
25
- * Discover fragment files matching the config patterns
26
+ * Discover fragment files matching the config patterns.
27
+ * Also discovers .contract.json files for framework-agnostic component contracts.
26
28
  */
27
29
  declare function discoverFragmentFiles(config: FragmentsConfig, configDir: string): Promise<DiscoveredFile[]>;
28
30
  /**
@@ -71,27 +73,6 @@ declare function validateAll(config: FragmentsConfig, configDir: string, options
71
73
  */
72
74
  declare function validateSnippets(config: FragmentsConfig, configDir: string, options?: ValidationRunOptions): Promise<ValidationResult>;
73
75
 
74
- interface BuildResult {
75
- success: boolean;
76
- outputPath: string;
77
- fragmentCount: number;
78
- errors: Array<{
79
- file: string;
80
- error: string;
81
- }>;
82
- warnings: Array<{
83
- file: string;
84
- warning: string;
85
- }>;
86
- }
87
- /**
88
- * Build compiled fragments.json file for AI consumption.
89
- *
90
- * Uses AST parsing to extract metadata WITHOUT executing fragment files.
91
- * This means the build works without any project dependencies installed.
92
- */
93
- declare function buildFragments(config: FragmentsConfig, configDir: string): Promise<BuildResult>;
94
-
95
76
  /**
96
77
  * Options for the screenshot command
97
78
  */
@@ -399,4 +380,4 @@ declare function generateStaticViewer(data: CompiledFragmentsFile): string;
399
380
  */
400
381
  declare function generateViewerFromJson(jsonPath: string): Promise<string>;
401
382
 
402
- export { type AnalyzeOptions, type AnalyzeResult, type BuildResult, type DiffCommandOptions, type DiffCommandResult, type DiscoveredFile, type ScreenshotCommandOptions, type ScreenshotResult, type ValidationError, type ValidationResult, type ValidationRunOptions, type ValidationWarning, type VariantDiffResult, buildFragments, discoverComponentFiles, discoverFragmentFiles, extractComponentName, findConfigFile, generateStaticViewer, generateViewerFromJson, loadConfig, runAnalyzeCommand, runDiffCommand, runScreenshotCommand, validateAll, validateCoverage, validateSchema, validateSnippets };
383
+ export { type AnalyzeOptions, type AnalyzeResult, type DiffCommandOptions, type DiffCommandResult, type DiscoveredFile, type ScreenshotCommandOptions, type ScreenshotResult, type ValidationError, type ValidationResult, type ValidationRunOptions, type ValidationWarning, type VariantDiffResult, discoverComponentFiles, discoverFragmentFiles, extractComponentName, findConfigFile, generateStaticViewer, generateViewerFromJson, loadConfig, runAnalyzeCommand, runDiffCommand, runScreenshotCommand, validateAll, validateCoverage, validateSchema, validateSnippets };
package/dist/index.js CHANGED
@@ -2,9 +2,8 @@ import { createRequire as __banner_createRequire } from 'module'; const require
2
2
  import {
3
3
  generateStaticViewer,
4
4
  generateViewerFromJson
5
- } from "./chunk-TXFCEDOC.js";
5
+ } from "./chunk-2WXKALIG.js";
6
6
  import {
7
- buildFragments,
8
7
  runAnalyzeCommand,
9
8
  runDiffCommand,
10
9
  runScreenshotCommand,
@@ -12,24 +11,26 @@ import {
12
11
  validateCoverage,
13
12
  validateSchema,
14
13
  validateSnippets
15
- } from "./chunk-LOYS64QS.js";
16
- import "./chunk-EYXVAMEX.js";
17
- import {
18
- findConfigFile,
19
- loadConfig
20
- } from "./chunk-55KERLWL.js";
14
+ } from "./chunk-5JF26E55.js";
15
+ import "./chunk-6SQPP47U.js";
16
+ import "./chunk-D2CDBRNU.js";
21
17
  import {
22
18
  discoverComponentFiles,
23
19
  discoverFragmentFiles,
24
- extractComponentName
25
- } from "./chunk-ZKTFKHWN.js";
26
- import "./chunk-APTQIBS5.js";
27
- import "./chunk-D2CDBRNU.js";
20
+ extractComponentName,
21
+ findConfigFile,
22
+ loadConfig
23
+ } from "./chunk-HQ6A6DTV.js";
28
24
  import {
29
25
  defineBlock,
30
26
  defineFragment
31
- } from "./chunk-I34BC3CU.js";
32
- import "./chunk-Z7EY4VHE.js";
27
+ } from "./chunk-32LIWN2P.js";
28
+ import "./chunk-MHIBEEW4.js";
29
+ import "./chunk-QCN35LJU.js";
30
+ import "./chunk-7DZC4YEV.js";
31
+
32
+ // src/index.ts
33
+ import { buildFragments } from "@fragments-sdk/compiler";
33
34
 
34
35
  // src/cli-commands.ts
35
36
  import {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli-commands.ts"],"sourcesContent":["/**\n * CLI command metadata — re-exported from @fragments-sdk/context for convenience.\n *\n * The source of truth lives in @fragments-sdk/context/cli-commands so that\n * browser-safe consumers (like the docs site) can import without pulling in\n * Node.js dependencies from the CLI package.\n */\nexport {\n CLI_COMMANDS,\n CLI_COMMAND_CATEGORIES,\n} from '@fragments-sdk/context/cli-commands';\n\nexport type {\n CliCommandDef,\n CliOptionDef,\n CliCommandCategory,\n CliCategoryInfo,\n} from '@fragments-sdk/context/cli-commands';\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAOA;AAAA,EACE;AAAA,EACA;AAAA,OACK;","names":[]}
1
+ {"version":3,"sources":["../src/index.ts","../src/cli-commands.ts"],"sourcesContent":["// Re-export from core/node (Node.js-only APIs)\nexport {\n loadConfig,\n findConfigFile,\n discoverFragmentFiles,\n discoverComponentFiles,\n extractComponentName,\n} from \"./core/node.js\";\nexport type { DiscoveredFile } from \"./core/node.js\";\n\n// Validators\nexport { validateSchema, validateCoverage, validateAll, validateSnippets } from \"./validators.js\";\nexport type {\n ValidationResult,\n ValidationError,\n ValidationWarning,\n ValidationRunOptions,\n} from \"./validators.js\";\n\n// Build (delegated to @fragments-sdk/compiler)\nexport { buildFragments } from '@fragments-sdk/compiler';\nexport type { BuildResult } from '@fragments-sdk/compiler';\n\n// Screenshot\nexport { runScreenshotCommand } from \"./screenshot.js\";\nexport type {\n ScreenshotCommandOptions,\n ScreenshotResult,\n} from \"./screenshot.js\";\n\n// Diff\nexport { runDiffCommand } from \"./diff.js\";\nexport type {\n DiffCommandOptions,\n DiffCommandResult,\n VariantDiffResult,\n} from \"./diff.js\";\n\n// Analyze\nexport { runAnalyzeCommand } from \"./analyze.js\";\nexport type { AnalyzeOptions, AnalyzeResult } from \"./analyze.js\";\n\n// Static Viewer\nexport { generateStaticViewer, generateViewerFromJson } from \"./static-viewer.js\";\n\n// Config type (used by generated fragments.config.ts)\nexport type { FragmentsConfig } from \"./core/index.js\";\n\n// Fragment definition API (used by generated .fragment.tsx files)\nexport { defineFragment, defineBlock } from \"./core/index.js\";\n\n// CLI Command metadata (for docs)\nexport { CLI_COMMANDS, CLI_COMMAND_CATEGORIES } from \"./cli-commands.js\";\nexport type { CliCommandDef, CliOptionDef, CliCommandCategory, CliCategoryInfo } from \"./cli-commands.js\";\n","/**\n * CLI command metadata — re-exported from @fragments-sdk/context for convenience.\n *\n * The source of truth lives in @fragments-sdk/context/cli-commands so that\n * browser-safe consumers (like the docs site) can import without pulling in\n * Node.js dependencies from the CLI package.\n */\nexport {\n CLI_COMMANDS,\n CLI_COMMAND_CATEGORIES,\n} from '@fragments-sdk/context/cli-commands';\n\nexport type {\n CliCommandDef,\n CliOptionDef,\n CliCommandCategory,\n CliCategoryInfo,\n} from '@fragments-sdk/context/cli-commands';\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoBA,SAAS,sBAAsB;;;ACb/B;AAAA,EACE;AAAA,EACA;AAAA,OACK;","names":[]}