@fragments-sdk/cli 0.15.0 → 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 (118) hide show
  1. package/dist/{ai-client-I6MDWNYA.js → ai-client-LSLQGOMM.js} +1 -2
  2. package/dist/bin.js +463 -71
  3. package/dist/bin.js.map +1 -1
  4. package/dist/chunk-5JF26E55.js +1255 -0
  5. package/dist/chunk-5JF26E55.js.map +1 -0
  6. package/dist/{chunk-XJQ5BIWI.js → chunk-6SQPP47U.js} +30 -314
  7. package/dist/chunk-6SQPP47U.js.map +1 -0
  8. package/dist/{chunk-65WSVDV5.js → chunk-HQ6A6DTV.js} +1386 -1097
  9. package/dist/chunk-HQ6A6DTV.js.map +1 -0
  10. package/dist/chunk-MHIBEEW4.js +511 -0
  11. package/dist/chunk-MHIBEEW4.js.map +1 -0
  12. package/dist/{chunk-CZD3AD4Q.js → chunk-ONUP6Z4W.js} +17 -6
  13. package/dist/chunk-ONUP6Z4W.js.map +1 -0
  14. package/dist/{codebase-scanner-VOTPXRYW.js → codebase-scanner-MQHUZC2G.js} +1 -2
  15. package/dist/{converter-JLINP7CJ.js → converter-7XM3Y6NJ.js} +1 -2
  16. package/dist/{converter-JLINP7CJ.js.map → converter-7XM3Y6NJ.js.map} +1 -1
  17. package/dist/core/index.js +0 -1
  18. package/dist/create-IH4R45GE.js +806 -0
  19. package/dist/create-IH4R45GE.js.map +1 -0
  20. package/dist/{generate-A4FP5426.js → generate-PVOLUAAC.js} +3 -4
  21. package/dist/{generate-A4FP5426.js.map → generate-PVOLUAAC.js.map} +1 -1
  22. package/dist/{govern-scan-UCBZR6D6.js → govern-scan-OYFZYOQW.js} +142 -9
  23. package/dist/govern-scan-OYFZYOQW.js.map +1 -0
  24. package/dist/index.d.ts +2 -22
  25. package/dist/index.js +8 -7
  26. package/dist/index.js.map +1 -1
  27. package/dist/{init-HGSM35XA.js → init-SSGUSP7Z.js} +3 -4
  28. package/dist/{init-HGSM35XA.js.map → init-SSGUSP7Z.js.map} +1 -1
  29. package/dist/{init-cloud-MQ6GRJAZ.js → init-cloud-3DNKPWFB.js} +29 -4
  30. package/dist/{init-cloud-MQ6GRJAZ.js.map → init-cloud-3DNKPWFB.js.map} +1 -1
  31. package/dist/mcp-bin.js +1 -2
  32. package/dist/mcp-bin.js.map +1 -1
  33. package/dist/node-37AUE74M.js +65 -0
  34. package/dist/push-contracts-WY32TFP6.js +84 -0
  35. package/dist/push-contracts-WY32TFP6.js.map +1 -0
  36. package/dist/{scan-VNNKACG2.js → scan-PKSYSTRR.js} +5 -5
  37. package/dist/{scan-generate-TWRHNU5M.js → scan-generate-VY27PIOX.js} +8 -9
  38. package/dist/scan-generate-VY27PIOX.js.map +1 -0
  39. package/dist/{scanner-7LAZYPWZ.js → scanner-4KZNOXAK.js} +1 -2
  40. package/dist/{service-FHQU7YS7.js → service-QJGWUIVL.js} +16 -9
  41. package/dist/{snapshot-KQEQ6XHL.js → snapshot-WIJMEIFT.js} +1 -2
  42. package/dist/{snapshot-KQEQ6XHL.js.map → snapshot-WIJMEIFT.js.map} +1 -1
  43. package/dist/{static-viewer-63PG6FWY.js → static-viewer-7QIBQZRC.js} +1 -2
  44. package/dist/{test-UQYUCZIS.js → test-64Z5BKBA.js} +2 -3
  45. package/dist/{test-UQYUCZIS.js.map → test-64Z5BKBA.js.map} +1 -1
  46. package/dist/token-normalizer-TEPOVBPV.js +312 -0
  47. package/dist/token-normalizer-TEPOVBPV.js.map +1 -0
  48. package/dist/token-parser-32KOIOFN.js +22 -0
  49. package/dist/token-parser-32KOIOFN.js.map +1 -0
  50. package/dist/{tokens-6GYKDV6U.js → tokens-NZWFQIAB.js} +7 -7
  51. package/dist/{tokens-generate-VTZV5EEW.js → tokens-generate-5JQSJ27E.js} +1 -2
  52. package/dist/{tokens-generate-VTZV5EEW.js.map → tokens-generate-5JQSJ27E.js.map} +1 -1
  53. package/dist/tokens-push-HY3KO36V.js +148 -0
  54. package/dist/tokens-push-HY3KO36V.js.map +1 -0
  55. package/package.json +5 -3
  56. package/src/bin.ts +90 -0
  57. package/src/commands/__fixtures__/shadcn-label-wrapper/src/components/ui/label.contract.json +1 -1
  58. package/src/commands/__fixtures__/shadcn-label-wrapper/src/components/ui/primitive.contract.json +1 -1
  59. package/src/commands/__tests__/build-freshness.test.ts +231 -0
  60. package/src/commands/__tests__/create.test.ts +71 -0
  61. package/src/commands/__tests__/drift-sync.test.ts +1 -1
  62. package/src/commands/__tests__/govern.test.ts +258 -0
  63. package/src/commands/__tests__/init.test.ts +1 -1
  64. package/src/commands/__tests__/scan-generate.test.ts +1 -1
  65. package/src/commands/build.ts +54 -1
  66. package/src/commands/context.ts +1 -1
  67. package/src/commands/create.ts +536 -0
  68. package/src/commands/doctor.ts +3 -2
  69. package/src/commands/govern-scan.ts +187 -8
  70. package/src/commands/govern.ts +65 -2
  71. package/src/commands/init-cloud.ts +32 -4
  72. package/src/commands/push-contracts.ts +112 -0
  73. package/src/commands/scan-generate.ts +1 -1
  74. package/src/commands/scan.ts +13 -0
  75. package/src/commands/sync.ts +2 -2
  76. package/src/commands/tokens-push.ts +199 -0
  77. package/src/core/__tests__/token-resolver.test.ts +1 -1
  78. package/src/core/component-extractor.test.ts +1 -1
  79. package/src/core/drift-verifier.ts +1 -1
  80. package/src/core/extractor-adapter.ts +1 -1
  81. package/src/index.ts +3 -3
  82. package/src/migrate/fragment-to-contract.ts +2 -2
  83. package/src/service/index.ts +8 -0
  84. package/src/service/tailwind-v4-parser.ts +314 -0
  85. package/src/service/token-parser.ts +56 -0
  86. package/src/setup.ts +10 -39
  87. package/src/theme/__tests__/component-contrast.test.ts +2 -2
  88. package/src/theme/__tests__/serializer.test.ts +1 -1
  89. package/src/theme/generator.ts +16 -1
  90. package/src/theme/schema.ts +8 -0
  91. package/src/theme/serializer.ts +13 -9
  92. package/src/theme/types.ts +8 -0
  93. package/src/validators.ts +1 -2
  94. package/dist/chunk-65WSVDV5.js.map +0 -1
  95. package/dist/chunk-7WHVW72L.js +0 -2664
  96. package/dist/chunk-7WHVW72L.js.map +0 -1
  97. package/dist/chunk-CZD3AD4Q.js.map +0 -1
  98. package/dist/chunk-MN3TJ3D5.js +0 -695
  99. package/dist/chunk-MN3TJ3D5.js.map +0 -1
  100. package/dist/chunk-XJQ5BIWI.js.map +0 -1
  101. package/dist/chunk-Z7EY4VHE.js +0 -50
  102. package/dist/govern-scan-UCBZR6D6.js.map +0 -1
  103. package/dist/sass.node-4XJK6YBF.js +0 -130708
  104. package/dist/sass.node-4XJK6YBF.js.map +0 -1
  105. package/dist/scan-generate-TWRHNU5M.js.map +0 -1
  106. package/src/build.ts +0 -736
  107. package/src/core/auto-props.ts +0 -464
  108. package/src/core/component-extractor.ts +0 -1121
  109. package/src/core/token-resolver.ts +0 -155
  110. package/src/viewer/preview-adapter.ts +0 -116
  111. /package/dist/{ai-client-I6MDWNYA.js.map → ai-client-LSLQGOMM.js.map} +0 -0
  112. /package/dist/{chunk-Z7EY4VHE.js.map → codebase-scanner-MQHUZC2G.js.map} +0 -0
  113. /package/dist/{codebase-scanner-VOTPXRYW.js.map → node-37AUE74M.js.map} +0 -0
  114. /package/dist/{scan-VNNKACG2.js.map → scan-PKSYSTRR.js.map} +0 -0
  115. /package/dist/{scanner-7LAZYPWZ.js.map → scanner-4KZNOXAK.js.map} +0 -0
  116. /package/dist/{service-FHQU7YS7.js.map → service-QJGWUIVL.js.map} +0 -0
  117. /package/dist/{static-viewer-63PG6FWY.js.map → static-viewer-7QIBQZRC.js.map} +0 -0
  118. /package/dist/{tokens-6GYKDV6U.js.map → tokens-NZWFQIAB.js.map} +0 -0
package/dist/bin.js CHANGED
@@ -1,43 +1,26 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire as __banner_createRequire } from 'module'; const require = __banner_createRequire(import.meta.url);
3
+ import {
4
+ setup
5
+ } from "./chunk-BJE3425I.js";
3
6
  import {
4
7
  scan
5
- } from "./chunk-CZD3AD4Q.js";
8
+ } from "./chunk-ONUP6Z4W.js";
6
9
  import {
7
10
  createAIClient,
8
11
  detectProvider,
9
12
  getApiKey
10
13
  } from "./chunk-SXTKFDCR.js";
11
14
  import {
12
- setup
13
- } from "./chunk-BJE3425I.js";
14
- import {
15
- buildFragments,
16
- buildFragmentsDir,
17
- measureBundleSizes,
18
- resolveComponentSourcePath,
19
15
  runAnalyzeCommand,
20
16
  runDiffCommand,
21
17
  runScreenshotCommand,
22
- toPerformanceData,
23
18
  validateAll,
24
19
  validateCoverage,
25
20
  validateDrift,
26
21
  validateSchema,
27
22
  validateSnippets
28
- } from "./chunk-7WHVW72L.js";
29
- import {
30
- createComponentExtractor
31
- } from "./chunk-MN3TJ3D5.js";
32
- import {
33
- discoverFragmentFiles,
34
- loadConfig,
35
- loadFragmentFile,
36
- parseFragmentFile
37
- } from "./chunk-65WSVDV5.js";
38
- import {
39
- projectFields
40
- } from "./chunk-T47OLCSF.js";
23
+ } from "./chunk-5JF26E55.js";
41
24
  import {
42
25
  FigmaClient,
43
26
  StorageManager,
@@ -51,28 +34,38 @@ import {
51
34
  parseAllStories,
52
35
  renderAllComponentVariants,
53
36
  shutdownSharedPool
54
- } from "./chunk-XJQ5BIWI.js";
37
+ } from "./chunk-6SQPP47U.js";
38
+ import {
39
+ projectFields
40
+ } from "./chunk-T47OLCSF.js";
55
41
  import "./chunk-D2CDBRNU.js";
42
+ import {
43
+ discoverFragmentFiles,
44
+ loadConfig,
45
+ loadFragmentFile,
46
+ parseFragmentFile
47
+ } from "./chunk-HQ6A6DTV.js";
56
48
  import {
57
49
  BRAND,
58
50
  budgetBar,
51
+ classifyComplexity,
59
52
  formatBytes,
60
53
  generateContext,
61
54
  resolvePerformanceConfig
62
55
  } from "./chunk-32LIWN2P.js";
56
+ import "./chunk-MHIBEEW4.js";
63
57
  import {
64
58
  getScanStats,
65
59
  scanCodebase
66
60
  } from "./chunk-QCN35LJU.js";
67
61
  import "./chunk-7DZC4YEV.js";
68
- import "./chunk-Z7EY4VHE.js";
69
62
 
70
63
  // src/bin.ts
71
64
  import { Command } from "commander";
72
65
  import pc26 from "picocolors";
73
66
  import { readFileSync } from "fs";
74
67
  import { fileURLToPath } from "url";
75
- import { dirname as dirname5, join as join11 } from "path";
68
+ import { dirname as dirname6, join as join12 } from "path";
76
69
 
77
70
  // src/commands/validate.ts
78
71
  import pc from "picocolors";
@@ -168,6 +161,7 @@ function printDriftReport(result) {
168
161
 
169
162
  // src/commands/build.ts
170
163
  import pc2 from "picocolors";
164
+ import { buildFragments, buildFragmentsDir, getFragmentsJsonStatus } from "@fragments-sdk/compiler";
171
165
  async function build(options = {}) {
172
166
  if (options.fromSource) {
173
167
  console.log(pc2.cyan(`
@@ -202,6 +196,50 @@ ${BRAND.name} Build
202
196
  let registryPath;
203
197
  let contextPath;
204
198
  if (!options.registryOnly) {
199
+ const status = await getFragmentsJsonStatus(config, configDir, {
200
+ output: config.outFile,
201
+ configPath: options.config
202
+ });
203
+ if (options.check) {
204
+ if (status.missing || status.stale) {
205
+ const message = status.missing ? `${BRAND.outFile} is missing` : `${BRAND.outFile} is stale${status.reason ? ` (${status.reason})` : ""}`;
206
+ console.log(pc2.red(`\u2717 ${message}
207
+ `));
208
+ errors.push({
209
+ file: status.outputPath,
210
+ error: message
211
+ });
212
+ return {
213
+ success: false,
214
+ outputPath: status.outputPath,
215
+ errors
216
+ };
217
+ }
218
+ console.log(pc2.green(`\u2713 ${BRAND.outFile} is up to date`));
219
+ console.log(pc2.dim(` Output: ${status.outputPath}
220
+ `));
221
+ if (!options.registry) {
222
+ return {
223
+ success: true,
224
+ fragmentCount: Object.keys(status.data?.fragments ?? {}).length,
225
+ outputPath: status.outputPath,
226
+ errors
227
+ };
228
+ }
229
+ }
230
+ if (options.ifNeeded && !status.missing && !status.stale) {
231
+ console.log(pc2.green(`\u2713 ${BRAND.outFile} is up to date`));
232
+ console.log(pc2.dim(` Output: ${status.outputPath}
233
+ `));
234
+ if (!options.registry) {
235
+ return {
236
+ success: true,
237
+ fragmentCount: Object.keys(status.data?.fragments ?? {}).length,
238
+ outputPath: status.outputPath,
239
+ errors
240
+ };
241
+ }
242
+ }
205
243
  console.log(pc2.dim("Compiling fragments...\n"));
206
244
  const result = await buildFragments(config, configDir);
207
245
  if (result.errors.length > 0) {
@@ -277,6 +315,7 @@ ${BRAND.name} Build
277
315
  import { readFile } from "fs/promises";
278
316
  import { resolve } from "path";
279
317
  import pc3 from "picocolors";
318
+ import { buildFragments as buildFragments2 } from "@fragments-sdk/compiler";
280
319
  async function context(options = {}) {
281
320
  const {
282
321
  format = "markdown",
@@ -293,7 +332,7 @@ async function context(options = {}) {
293
332
  fragments = Object.values(data.fragments);
294
333
  } else {
295
334
  const { config, configDir } = await loadConfig(options.config);
296
- const result = await buildFragments(config, configDir);
335
+ const result = await buildFragments2(config, configDir);
297
336
  if (result.errors.length > 0 && result.fragmentCount === 0) {
298
337
  console.error(pc3.red("Error: No fragments found. Run `fragments build` first or fix errors."));
299
338
  return { success: false, tokenEstimate: 0 };
@@ -5488,13 +5527,259 @@ ${BRAND.name} Components (${fragments.length})
5488
5527
  // src/commands/perf.ts
5489
5528
  import pc21 from "picocolors";
5490
5529
  import { readFile as readFile10, writeFile as writeFile8 } from "fs/promises";
5491
- import { resolve as resolve10 } from "path";
5530
+ import { resolve as resolve11 } from "path";
5531
+
5532
+ // src/core/bundle-measurer.ts
5533
+ import { build as build2 } from "esbuild";
5534
+ import { gzipSync } from "zlib";
5535
+ import { resolve as resolve10, dirname as dirname4, join as join10, basename } from "path";
5536
+ import { existsSync as existsSync3 } from "fs";
5537
+ function resolveEntryPoint(fragmentFilePath, configDir) {
5538
+ const absPath = resolve10(configDir, fragmentFilePath);
5539
+ const dir = dirname4(absPath);
5540
+ const candidates = ["index.tsx", "index.ts", "index.jsx", "index.js"];
5541
+ for (const candidate of candidates) {
5542
+ const path = join10(dir, candidate);
5543
+ if (existsSync3(path)) return path;
5544
+ }
5545
+ return null;
5546
+ }
5547
+ function labelForPath(filePath) {
5548
+ const lastNmIdx = filePath.lastIndexOf("node_modules/");
5549
+ if (lastNmIdx >= 0) {
5550
+ const afterNm = filePath.slice(lastNmIdx + "node_modules/".length);
5551
+ if (afterNm.startsWith("@")) {
5552
+ const parts = afterNm.split("/");
5553
+ return parts.slice(0, 2).join("/");
5554
+ }
5555
+ return afterNm.split("/")[0];
5556
+ }
5557
+ const componentsIdx = filePath.indexOf("components/");
5558
+ if (componentsIdx >= 0) {
5559
+ const afterComponents = filePath.slice(componentsIdx + "components/".length);
5560
+ const componentName = afterComponents.split("/")[0];
5561
+ return componentName;
5562
+ }
5563
+ const srcIdx = filePath.indexOf("src/");
5564
+ if (srcIdx >= 0) return filePath.slice(srcIdx);
5565
+ return filePath;
5566
+ }
5567
+ function groupImportsByDirectDep(metafile, entryPoint) {
5568
+ const inputs = metafile.inputs;
5569
+ const outputKey = Object.keys(metafile.outputs)[0];
5570
+ const outputMeta = outputKey ? metafile.outputs[outputKey] : void 0;
5571
+ if (!outputMeta?.inputs) return [];
5572
+ const bytesMap = /* @__PURE__ */ new Map();
5573
+ for (const [path, info] of Object.entries(outputMeta.inputs)) {
5574
+ if (info.bytesInOutput > 0) {
5575
+ bytesMap.set(path, info.bytesInOutput);
5576
+ }
5577
+ }
5578
+ let entryKey;
5579
+ for (const key of Object.keys(inputs)) {
5580
+ if (key === entryPoint || entryPoint.endsWith(key) || key.endsWith(basename(entryPoint))) {
5581
+ const entryDir = dirname4(entryPoint);
5582
+ if (key.includes(basename(entryDir))) {
5583
+ entryKey = key;
5584
+ break;
5585
+ }
5586
+ }
5587
+ }
5588
+ if (!entryKey) {
5589
+ const entryBasename = basename(dirname4(entryPoint));
5590
+ for (const key of Object.keys(inputs)) {
5591
+ if (key.includes(`/${entryBasename}/index.`)) {
5592
+ entryKey = key;
5593
+ break;
5594
+ }
5595
+ }
5596
+ }
5597
+ if (!entryKey || !inputs[entryKey]) {
5598
+ return groupByPackage(bytesMap);
5599
+ }
5600
+ const directImports = inputs[entryKey].imports.map((imp) => imp.path).filter((p) => inputs[p]);
5601
+ const claimed = /* @__PURE__ */ new Set();
5602
+ claimed.add(entryKey);
5603
+ const groupMap = /* @__PURE__ */ new Map();
5604
+ for (const directPath of directImports) {
5605
+ if (claimed.has(directPath)) continue;
5606
+ const queue = [directPath];
5607
+ const reachable = /* @__PURE__ */ new Set();
5608
+ while (queue.length > 0) {
5609
+ const current = queue.pop();
5610
+ if (reachable.has(current) || claimed.has(current)) continue;
5611
+ reachable.add(current);
5612
+ claimed.add(current);
5613
+ const entry = inputs[current];
5614
+ if (entry?.imports) {
5615
+ for (const imp of entry.imports) {
5616
+ if (inputs[imp.path] && !claimed.has(imp.path)) {
5617
+ queue.push(imp.path);
5618
+ }
5619
+ }
5620
+ }
5621
+ }
5622
+ let totalBytes = 0;
5623
+ for (const path of reachable) {
5624
+ totalBytes += bytesMap.get(path) ?? 0;
5625
+ }
5626
+ if (totalBytes > 0) {
5627
+ const label = labelForPath(directPath);
5628
+ const existing = groupMap.get(label);
5629
+ if (existing) {
5630
+ existing.bytes += totalBytes;
5631
+ } else {
5632
+ const entry = { path: label, bytes: totalBytes };
5633
+ groupMap.set(label, entry);
5634
+ }
5635
+ }
5636
+ }
5637
+ const entryLabel = labelForPath(entryKey);
5638
+ const selfLabel = entryLabel + " (self)";
5639
+ let selfBytes = bytesMap.get(entryKey) ?? 0;
5640
+ const siblingGroup = groupMap.get(entryLabel);
5641
+ if (siblingGroup) {
5642
+ selfBytes += siblingGroup.bytes;
5643
+ groupMap.delete(entryLabel);
5644
+ }
5645
+ if (selfBytes > 0) {
5646
+ groupMap.set(selfLabel, { path: selfLabel, bytes: selfBytes });
5647
+ }
5648
+ let unclaimedBytes = 0;
5649
+ for (const [path, bytes] of bytesMap) {
5650
+ if (!claimed.has(path)) unclaimedBytes += bytes;
5651
+ }
5652
+ if (unclaimedBytes > 0) {
5653
+ groupMap.set("(other)", { path: "(other)", bytes: unclaimedBytes });
5654
+ }
5655
+ return [...groupMap.values()].sort((a, b) => b.bytes - a.bytes);
5656
+ }
5657
+ function groupByPackage(bytesMap) {
5658
+ const groups = /* @__PURE__ */ new Map();
5659
+ for (const [path, bytes] of bytesMap) {
5660
+ const label = labelForPath(path);
5661
+ const key = label.includes("/") && !label.startsWith("components/") ? label.split("/").slice(0, label.startsWith("@") ? 2 : 1).join("/") : label;
5662
+ groups.set(key, (groups.get(key) ?? 0) + bytes);
5663
+ }
5664
+ return [...groups.entries()].map(([path, bytes]) => ({ path, bytes })).sort((a, b) => b.bytes - a.bytes);
5665
+ }
5666
+ async function measureSingleComponent(entryPoint, name) {
5667
+ const result = await build2({
5668
+ entryPoints: [entryPoint],
5669
+ bundle: true,
5670
+ write: false,
5671
+ minify: true,
5672
+ metafile: true,
5673
+ format: "esm",
5674
+ target: "es2020",
5675
+ platform: "browser",
5676
+ treeShaking: true,
5677
+ external: [
5678
+ "react",
5679
+ "react-dom",
5680
+ "react/jsx-runtime",
5681
+ "react/jsx-dev-runtime",
5682
+ // Optional peer deps — excluded from measurement
5683
+ "recharts",
5684
+ "shiki",
5685
+ "react-day-picker",
5686
+ "@tanstack/react-table",
5687
+ "date-fns",
5688
+ "@base-ui-components/*",
5689
+ "@base-ui/react/*"
5690
+ ],
5691
+ loader: {
5692
+ ".scss": "empty",
5693
+ ".css": "empty",
5694
+ ".svg": "empty",
5695
+ ".png": "empty",
5696
+ ".jpg": "empty",
5697
+ ".gif": "empty",
5698
+ ".woff": "empty",
5699
+ ".woff2": "empty",
5700
+ ".ttf": "empty",
5701
+ ".eot": "empty"
5702
+ },
5703
+ logLevel: "silent"
5704
+ });
5705
+ const output = result.outputFiles[0];
5706
+ const rawBytes = output.contents.byteLength;
5707
+ const gzipBytes = gzipSync(output.contents).byteLength;
5708
+ const imports = result.metafile ? groupImportsByDirectDep(result.metafile, entryPoint) : void 0;
5709
+ return { name, rawBytes, gzipBytes, imports };
5710
+ }
5711
+ async function measureBundleSizes(fragments, configDir, options = {}) {
5712
+ const concurrency = options.concurrency ?? 4;
5713
+ const measurements = /* @__PURE__ */ new Map();
5714
+ const errors = [];
5715
+ const start = Date.now();
5716
+ const entries = [];
5717
+ for (const [name, fragment] of Object.entries(fragments)) {
5718
+ const entryPoint = resolveEntryPoint(fragment.filePath, configDir);
5719
+ if (entryPoint) {
5720
+ entries.push({ name, entryPoint });
5721
+ } else {
5722
+ errors.push({
5723
+ name,
5724
+ error: `Could not resolve entry point from ${fragment.filePath}`
5725
+ });
5726
+ }
5727
+ }
5728
+ let completed = 0;
5729
+ for (let i = 0; i < entries.length; i += concurrency) {
5730
+ const batch = entries.slice(i, i + concurrency);
5731
+ const results = await Promise.allSettled(
5732
+ batch.map(
5733
+ ({ name, entryPoint }) => measureSingleComponent(entryPoint, name)
5734
+ )
5735
+ );
5736
+ for (let j = 0; j < results.length; j++) {
5737
+ const result = results[j];
5738
+ const { name } = batch[j];
5739
+ completed++;
5740
+ if (result.status === "fulfilled") {
5741
+ measurements.set(name, result.value);
5742
+ } else {
5743
+ errors.push({
5744
+ name,
5745
+ error: result.reason instanceof Error ? result.reason.message : String(result.reason)
5746
+ });
5747
+ }
5748
+ options.onProgress?.(completed, entries.length, name);
5749
+ }
5750
+ }
5751
+ return {
5752
+ measurements,
5753
+ errors,
5754
+ elapsed: Date.now() - start
5755
+ };
5756
+ }
5757
+ function toPerformanceData(measurement, config, contractBudget) {
5758
+ const budget = contractBudget ?? config.budgets.bundleSize;
5759
+ const budgetPercent = Math.round(measurement.gzipBytes / budget * 100);
5760
+ const imports = measurement.imports?.slice(0, 10).map((imp) => ({
5761
+ path: imp.path,
5762
+ bytes: imp.bytes,
5763
+ percent: Math.round(imp.bytes / measurement.rawBytes * 100)
5764
+ }));
5765
+ return {
5766
+ bundleSize: measurement.gzipBytes,
5767
+ rawSize: measurement.rawBytes,
5768
+ complexity: classifyComplexity(measurement.gzipBytes),
5769
+ budgetPercent,
5770
+ overBudget: budgetPercent > 100,
5771
+ measuredAt: (/* @__PURE__ */ new Date()).toISOString(),
5772
+ ...imports && imports.length > 0 ? { imports } : {}
5773
+ };
5774
+ }
5775
+
5776
+ // src/commands/perf.ts
5492
5777
  async function perf(options) {
5493
5778
  const { config: configPath, json, component, concurrency, detail } = options;
5494
5779
  const shouldWrite = options.write !== false;
5495
5780
  const { config, configDir } = await loadConfig(configPath);
5496
5781
  const perfConfig = resolvePerformanceConfig(config.performance ?? "standard");
5497
- const outFile = resolve10(configDir, config.outFile ?? BRAND.outFile);
5782
+ const outFile = resolve11(configDir, config.outFile ?? BRAND.outFile);
5498
5783
  let data;
5499
5784
  try {
5500
5785
  data = JSON.parse(await readFile10(outFile, "utf-8"));
@@ -5638,14 +5923,15 @@ ${pc21.bold("Summary")}`);
5638
5923
 
5639
5924
  // src/commands/doctor.ts
5640
5925
  import { readFile as readFile11, access as access3 } from "fs/promises";
5641
- import { join as join10, resolve as resolve11 } from "path";
5926
+ import { join as join11, resolve as resolve12 } from "path";
5642
5927
  import pc22 from "picocolors";
5643
- var VALID_NEUTRALS = ["stone", "ice", "earth", "sand", "fire"];
5928
+ import { NEUTRAL_PALETTES } from "@fragments-sdk/viewer/docs-data";
5929
+ var VALID_NEUTRALS = NEUTRAL_PALETTES.map((p) => p.name);
5644
5930
  var VALID_DENSITIES = ["compact", "default", "relaxed"];
5645
5931
  var VALID_RADII = ["sharp", "subtle", "default", "rounded", "pill"];
5646
5932
  async function checkPackageInstalled(root) {
5647
5933
  try {
5648
- const pkgPath = join10(root, "package.json");
5934
+ const pkgPath = join11(root, "package.json");
5649
5935
  const content = await readFile11(pkgPath, "utf-8");
5650
5936
  const pkg2 = JSON.parse(content);
5651
5937
  const allDeps = { ...pkg2.dependencies, ...pkg2.devDependencies };
@@ -5688,7 +5974,7 @@ async function checkStylesImport(root) {
5688
5974
  ];
5689
5975
  for (const pattern of entryPatterns) {
5690
5976
  try {
5691
- const content = await readFile11(join10(root, pattern), "utf-8");
5977
+ const content = await readFile11(join11(root, pattern), "utf-8");
5692
5978
  if (content.includes("@fragments-sdk/ui/styles")) {
5693
5979
  return {
5694
5980
  name: "Styles import",
@@ -5717,7 +6003,7 @@ async function checkStylesImport(root) {
5717
6003
  ];
5718
6004
  for (const pattern of scssPatterns) {
5719
6005
  try {
5720
- const content = await readFile11(join10(root, pattern), "utf-8");
6006
+ const content = await readFile11(join11(root, pattern), "utf-8");
5721
6007
  if (content.includes("@fragments-sdk/ui/styles")) {
5722
6008
  return {
5723
6009
  name: "Styles import",
@@ -5749,7 +6035,7 @@ async function checkThemeProvider(root) {
5749
6035
  ];
5750
6036
  for (const pattern of providerPatterns) {
5751
6037
  try {
5752
- const content = await readFile11(join10(root, pattern), "utf-8");
6038
+ const content = await readFile11(join11(root, pattern), "utf-8");
5753
6039
  if (content.includes("ThemeProvider")) {
5754
6040
  if (content.includes("defaultTheme=") || content.includes("defaultTheme =")) {
5755
6041
  return {
@@ -5787,7 +6073,7 @@ async function checkScssSeeds(root) {
5787
6073
  ];
5788
6074
  for (const pattern of scssPatterns) {
5789
6075
  try {
5790
- const content = await readFile11(join10(root, pattern), "utf-8");
6076
+ const content = await readFile11(join11(root, pattern), "utf-8");
5791
6077
  if (!content.includes("@fragments-sdk/ui/styles")) continue;
5792
6078
  const standalonePattern = /^\$fui-\w+:\s*.+;$/m;
5793
6079
  if (standalonePattern.test(content) && !content.includes("@use")) {
@@ -5858,7 +6144,7 @@ async function checkScssSeeds(root) {
5858
6144
  async function checkPeerDeps(root) {
5859
6145
  const checks = [];
5860
6146
  try {
5861
- const pkgPath = join10(root, "package.json");
6147
+ const pkgPath = join11(root, "package.json");
5862
6148
  const content = await readFile11(pkgPath, "utf-8");
5863
6149
  const pkg2 = JSON.parse(content);
5864
6150
  const allDeps = { ...pkg2.dependencies, ...pkg2.devDependencies };
@@ -5916,7 +6202,7 @@ async function checkMcpConfig(root) {
5916
6202
  ];
5917
6203
  for (const configPath of mcpConfigPaths) {
5918
6204
  try {
5919
- const fullPath = join10(root, configPath);
6205
+ const fullPath = join11(root, configPath);
5920
6206
  const content = await readFile11(fullPath, "utf-8");
5921
6207
  const config = JSON.parse(content);
5922
6208
  const servers = config.mcpServers || config.servers || {};
@@ -5943,7 +6229,7 @@ async function checkMcpConfig(root) {
5943
6229
  }
5944
6230
  async function checkTypeScript(root) {
5945
6231
  try {
5946
- const tsconfigPath = join10(root, "tsconfig.json");
6232
+ const tsconfigPath = join11(root, "tsconfig.json");
5947
6233
  await access3(tsconfigPath);
5948
6234
  return {
5949
6235
  name: "TypeScript",
@@ -5959,7 +6245,7 @@ async function checkTypeScript(root) {
5959
6245
  }
5960
6246
  }
5961
6247
  async function doctor(options = {}) {
5962
- const root = resolve11(options.root ?? process.cwd());
6248
+ const root = resolve12(options.root ?? process.cwd());
5963
6249
  const checks = [];
5964
6250
  if (!options.json) {
5965
6251
  console.log(pc22.cyan(`
@@ -6014,6 +6300,8 @@ ${BRAND.name} Doctor
6014
6300
  // src/commands/sync.ts
6015
6301
  import pc23 from "picocolors";
6016
6302
  import { readFile as readFile12, writeFile as writeFile9 } from "fs/promises";
6303
+ import { resolveComponentSourcePath } from "@fragments-sdk/extract";
6304
+ import { createComponentExtractor } from "@fragments-sdk/extract";
6017
6305
  async function sync(options = {}) {
6018
6306
  const { config, configDir } = await loadConfig(options.config);
6019
6307
  console.log(pc23.cyan(`
@@ -6251,18 +6539,65 @@ ${BRAND.name} Governance Check
6251
6539
  }
6252
6540
  async function governInit(options = {}) {
6253
6541
  const { writeFile: writeFile11 } = await import("fs/promises");
6254
- const { resolve: resolve14 } = await import("path");
6542
+ const { existsSync: existsSync4 } = await import("fs");
6543
+ const { resolve: resolve15 } = await import("path");
6255
6544
  const { generateConfigTemplate } = await import("@fragments-sdk/govern");
6256
- const outputPath = resolve14(options.output ?? "fragments.config.ts");
6257
- const template = generateConfigTemplate();
6545
+ const { findTailwindConfig } = await import("./token-normalizer-TEPOVBPV.js");
6546
+ const cwd = process.cwd();
6547
+ const detected = {
6548
+ tokenIncludes: [],
6549
+ projectType: "unknown"
6550
+ };
6551
+ const tailwindPath = findTailwindConfig(cwd);
6552
+ if (tailwindPath) {
6553
+ const { relative: relative9 } = await import("path");
6554
+ detected.tokenIncludes.push(relative9(cwd, tailwindPath));
6555
+ detected.projectType = "tailwind";
6556
+ console.log(pc24.dim(` Detected Tailwind config: ${detected.tokenIncludes[0]}`));
6557
+ }
6558
+ if (detected.tokenIncludes.length === 0) {
6559
+ const candidates = [
6560
+ "src/styles/tokens.scss",
6561
+ "src/styles/variables.scss",
6562
+ "src/styles/theme.scss",
6563
+ "src/tokens.css",
6564
+ "src/styles/tokens.css",
6565
+ "src/styles/variables.css",
6566
+ "styles/tokens.scss",
6567
+ "styles/variables.scss",
6568
+ "tokens.json",
6569
+ "src/tokens.json"
6570
+ ];
6571
+ for (const candidate of candidates) {
6572
+ if (existsSync4(resolve15(cwd, candidate))) {
6573
+ detected.tokenIncludes.push(candidate);
6574
+ detected.projectType = candidate.endsWith(".scss") ? "scss" : candidate.endsWith(".json") ? "dtcg" : "css";
6575
+ console.log(pc24.dim(` Detected token source: ${candidate}`));
6576
+ }
6577
+ }
6578
+ }
6579
+ if (detected.tokenIncludes.length === 0) {
6580
+ console.log(pc24.dim(" No token sources auto-detected. You can add them manually."));
6581
+ }
6582
+ const outputPath = resolve15(options.output ?? "fragments.config.ts");
6583
+ const template = generateConfigTemplate({ tokenIncludes: detected.tokenIncludes });
6258
6584
  await writeFile11(outputPath, template, "utf-8");
6259
- console.log(pc24.green(`\u2713 Created ${outputPath}
6585
+ console.log(pc24.green(`
6586
+ \u2713 Created ${outputPath}
6260
6587
  `));
6588
+ if (detected.tokenIncludes.length > 0) {
6589
+ console.log(
6590
+ pc24.dim(` Token sources configured: ${detected.tokenIncludes.join(", ")}`)
6591
+ );
6592
+ }
6593
+ console.log(
6594
+ pc24.dim(" Run ") + pc24.cyan("fragments govern scan") + pc24.dim(" to check your project.\n")
6595
+ );
6261
6596
  }
6262
6597
  async function governConnect() {
6263
6598
  const { readFile: readFile14, writeFile: writeFile11, appendFile } = await import("fs/promises");
6264
- const { existsSync: existsSync3 } = await import("fs");
6265
- const { resolve: resolve14 } = await import("path");
6599
+ const { existsSync: existsSync4 } = await import("fs");
6600
+ const { resolve: resolve15 } = await import("path");
6266
6601
  const { platform } = await import("os");
6267
6602
  const { exec } = await import("child_process");
6268
6603
  const { password, confirm } = await import("@inquirer/prompts");
@@ -6330,9 +6665,9 @@ async function governConnect() {
6330
6665
  default: true
6331
6666
  });
6332
6667
  if (saveToEnv) {
6333
- const envPath = resolve14(".env");
6668
+ const envPath = resolve15(".env");
6334
6669
  const envEntry = `FRAGMENTS_API_KEY=${apiKey.trim()}`;
6335
- if (existsSync3(envPath)) {
6670
+ if (existsSync4(envPath)) {
6336
6671
  const envContent = await readFile14(envPath, "utf-8");
6337
6672
  if (envContent.includes("FRAGMENTS_API_KEY=")) {
6338
6673
  const updated = envContent.replace(
@@ -6360,8 +6695,8 @@ ${envEntry}
6360
6695
  console.log(pc24.green(` \u2713 Added FRAGMENTS_URL to .env`));
6361
6696
  }
6362
6697
  }
6363
- const gitignorePath = resolve14(".gitignore");
6364
- if (existsSync3(gitignorePath)) {
6698
+ const gitignorePath = resolve15(".gitignore");
6699
+ if (existsSync4(gitignorePath)) {
6365
6700
  const gitignore = await readFile14(gitignorePath, "utf-8");
6366
6701
  if (!gitignore.split("\n").some((line) => line.trim() === ".env")) {
6367
6702
  await appendFile(gitignorePath, "\n.env\n", "utf-8");
@@ -6429,11 +6764,13 @@ ${BRAND.name} Governance Report
6429
6764
  // src/commands/migrate-contract.ts
6430
6765
  import pc25 from "picocolors";
6431
6766
  import fg4 from "fast-glob";
6432
- import { resolve as resolve13 } from "path";
6767
+ import { resolve as resolve14 } from "path";
6433
6768
 
6434
6769
  // src/migrate/fragment-to-contract.ts
6435
6770
  import { readFile as readFile13, writeFile as writeFile10 } from "fs/promises";
6436
- import { resolve as resolve12, dirname as dirname4, relative as relative8 } from "path";
6771
+ import { resolve as resolve13, dirname as dirname5, relative as relative8 } from "path";
6772
+ import { createComponentExtractor as createComponentExtractor2 } from "@fragments-sdk/extract";
6773
+ import { resolveComponentSourcePath as resolveComponentSourcePath2 } from "@fragments-sdk/extract";
6437
6774
  function compilePropsSummaryFromExtracted(props) {
6438
6775
  return Object.entries(props).filter(([, p]) => p.source === "local").map(([name, prop]) => {
6439
6776
  let summary = name + ": ";
@@ -6470,7 +6807,7 @@ function compilePropsSummaryFromDocs(props) {
6470
6807
  }
6471
6808
  async function migrateFragmentToContract(fragmentPath, configDir, options) {
6472
6809
  const warnings = [];
6473
- const absFragmentPath = resolve12(fragmentPath);
6810
+ const absFragmentPath = resolve13(fragmentPath);
6474
6811
  const content = await readFile13(absFragmentPath, "utf-8");
6475
6812
  const parsed = parseFragmentFile(content, fragmentPath);
6476
6813
  warnings.push(...parsed.warnings);
@@ -6478,10 +6815,10 @@ async function migrateFragmentToContract(fragmentPath, configDir, options) {
6478
6815
  throw new Error(`Fragment file ${fragmentPath} has no meta.name`);
6479
6816
  }
6480
6817
  let extractedMeta = null;
6481
- const extractor = createComponentExtractor(options?.tsconfigPath);
6818
+ const extractor = createComponentExtractor2(options?.tsconfigPath);
6482
6819
  try {
6483
6820
  const componentExportName = parsed.componentName ?? parsed.meta.name;
6484
- const componentSourcePath = resolveComponentSourcePath(
6821
+ const componentSourcePath = resolveComponentSourcePath2(
6485
6822
  absFragmentPath,
6486
6823
  parsed.componentImport
6487
6824
  );
@@ -6497,7 +6834,7 @@ async function migrateFragmentToContract(fragmentPath, configDir, options) {
6497
6834
  }
6498
6835
  let sourcePath;
6499
6836
  if (parsed.componentImport) {
6500
- const absSource = resolveComponentSourcePath(absFragmentPath, parsed.componentImport);
6837
+ const absSource = resolveComponentSourcePath2(absFragmentPath, parsed.componentImport);
6501
6838
  if (absSource) {
6502
6839
  sourcePath = relative8(configDir, absSource);
6503
6840
  } else {
@@ -6505,8 +6842,8 @@ async function migrateFragmentToContract(fragmentPath, configDir, options) {
6505
6842
  warnings.push(`Could not resolve component source path: ${parsed.componentImport}`);
6506
6843
  }
6507
6844
  } else {
6508
- const fragDir = dirname4(absFragmentPath);
6509
- sourcePath = relative8(configDir, resolve12(fragDir, "index.tsx"));
6845
+ const fragDir = dirname5(absFragmentPath);
6846
+ sourcePath = relative8(configDir, resolve13(fragDir, "index.tsx"));
6510
6847
  warnings.push("No component import found; assuming ./index.tsx");
6511
6848
  }
6512
6849
  const exportName = parsed.componentName ?? parsed.meta.name;
@@ -6622,7 +6959,7 @@ async function migrateContract(options) {
6622
6959
  let migrated = 0;
6623
6960
  let failed = 0;
6624
6961
  let totalWarnings = 0;
6625
- const tsconfigPath = options.tsconfig ? resolve13(options.tsconfig) : void 0;
6962
+ const tsconfigPath = options.tsconfig ? resolve14(options.tsconfig) : void 0;
6626
6963
  for (const file of files) {
6627
6964
  try {
6628
6965
  const result = await migrateFragmentToContract(file, configDir, {
@@ -6655,8 +6992,8 @@ async function migrateContract(options) {
6655
6992
  }
6656
6993
 
6657
6994
  // src/bin.ts
6658
- var __dirname = dirname5(fileURLToPath(import.meta.url));
6659
- var pkg = JSON.parse(readFileSync(join11(__dirname, "../package.json"), "utf-8"));
6995
+ var __dirname = dirname6(fileURLToPath(import.meta.url));
6996
+ var pkg = JSON.parse(readFileSync(join12(__dirname, "../package.json"), "utf-8"));
6660
6997
  var EXPERIMENTAL = process.env.FRAGMENTS_EXPERIMENTAL === "1";
6661
6998
  var program = new Command();
6662
6999
  program.name(BRAND.cliCommand).description(`${BRAND.name} - Design system documentation and compliance tool`).version(pkg.version);
@@ -6687,7 +7024,7 @@ program.command("sync").description("Auto-update fragment files from component s
6687
7024
  process.exit(1);
6688
7025
  }
6689
7026
  });
6690
- program.command("build").description(`Build compiled ${BRAND.outFile} and ${BRAND.dataDir}/ directory`).option("-c, --config <path>", "Path to config file").option("-o, --output <path>", "Output file path").option("--registry", `Also generate ${BRAND.dataDir}/${BRAND.registryFile} and ${BRAND.contextFile}`).option("--registry-only", `Only generate ${BRAND.dataDir}/ directory (skip ${BRAND.outFile})`).option("--from-source", "Build from source code (zero-config, no fragment files needed)").option("--skip-usage", "Skip usage analysis when building from source").option("--skip-storybook", "Skip Storybook parsing when building from source").option("-v, --verbose", "Verbose output").action(async (options) => {
7027
+ program.command("build").description(`Build compiled ${BRAND.outFile} and ${BRAND.dataDir}/ directory`).option("-c, --config <path>", "Path to config file").option("-o, --output <path>", "Output file path").option("--registry", `Also generate ${BRAND.dataDir}/${BRAND.registryFile} and ${BRAND.contextFile}`).option("--registry-only", `Only generate ${BRAND.dataDir}/ directory (skip ${BRAND.outFile})`).option("--from-source", "Build from source code (zero-config, no fragment files needed)").option("--if-needed", `Skip rebuilding when ${BRAND.outFile} is already fresh`).option("--check", `Check whether ${BRAND.outFile} is fresh and exit non-zero if it is stale`).option("--skip-usage", "Skip usage analysis when building from source").option("--skip-storybook", "Skip Storybook parsing when building from source").option("-v, --verbose", "Verbose output").action(async (options) => {
6691
7028
  try {
6692
7029
  const result = await build({
6693
7030
  config: options.config,
@@ -6695,6 +7032,8 @@ program.command("build").description(`Build compiled ${BRAND.outFile} and ${BRAN
6695
7032
  registry: options.registry,
6696
7033
  registryOnly: options.registryOnly,
6697
7034
  fromSource: options.fromSource,
7035
+ ifNeeded: options.ifNeeded,
7036
+ check: options.check,
6698
7037
  skipUsage: options.skipUsage,
6699
7038
  skipStorybook: options.skipStorybook,
6700
7039
  verbose: options.verbose
@@ -7039,7 +7378,7 @@ Make sure a dev server is running on the expected port.`));
7039
7378
  });
7040
7379
  program.command("view").description(`Generate a static HTML viewer for ${BRAND.outFile}`).option("-i, --input <path>", `Path to ${BRAND.outFile}`, BRAND.outFile).option("-o, --output <path>", "Output HTML file path", BRAND.viewerHtmlFile).option("--open", "Open in browser after generation").action(async (options) => {
7041
7380
  try {
7042
- const { generateViewerFromJson } = await import("./static-viewer-63PG6FWY.js");
7381
+ const { generateViewerFromJson } = await import("./static-viewer-7QIBQZRC.js");
7043
7382
  const fs2 = await import("fs/promises");
7044
7383
  const path = await import("path");
7045
7384
  const inputPath = path.resolve(process.cwd(), options.input);
@@ -7085,6 +7424,30 @@ program.command("add").argument("[name]", 'Component name (e.g., "Button", "Text
7085
7424
  process.exit(1);
7086
7425
  }
7087
7426
  });
7427
+ program.command("create").argument("[name]", "Project name").description("Create a new project with Fragments UI and your custom theme").option("-t, --template <template>", "Framework template (nextjs, vite)", "nextjs").option("--pm <manager>", "Package manager (npm, pnpm, yarn, bun)").option("--theme <encoded>", "Encoded theme string").option("--preset <id>", "Theme preset ID from usefragments.com/create").option("--brand <color>", "Brand color hex (e.g., #6366f1)").option("--scss", "Use SCSS output (installs sass)").option("--mcp", "Configure MCP server for AI tooling").option("-y, --yes", "Skip interactive prompts").option("--no-git", "Skip git initialization").action(async (name, options) => {
7428
+ try {
7429
+ const { create } = await import("./create-IH4R45GE.js");
7430
+ const result = await create({
7431
+ name,
7432
+ template: options.template,
7433
+ packageManager: options.pm,
7434
+ theme: options.theme,
7435
+ preset: options.preset,
7436
+ brand: options.brand,
7437
+ scss: options.scss,
7438
+ mcp: options.mcp,
7439
+ yes: options.yes,
7440
+ noGit: !options.git
7441
+ });
7442
+ if (!result.success) {
7443
+ if (result.error) console.error(pc26.red(`Error: ${result.error}`));
7444
+ process.exit(1);
7445
+ }
7446
+ } catch (error) {
7447
+ console.error(pc26.red("Error:"), error instanceof Error ? error.message : error);
7448
+ process.exit(1);
7449
+ }
7450
+ });
7088
7451
  program.command("setup").description("Configure @fragments-sdk/ui in a consumer project (styles, providers, Next.js config)").option("--root <dir>", "Project root directory", process.cwd()).option("-y, --yes", "Skip interactive prompts").option("--brand <color>", "Brand color hex (e.g., #6366f1)").option("--scss", "Create SCSS seed file for build-time theming").option("--mcp", "Configure MCP server for AI tooling").action(async (options) => {
7089
7452
  try {
7090
7453
  const result = await setup({
@@ -7116,7 +7479,7 @@ initCmd.action(async (options) => {
7116
7479
  `));
7117
7480
  process.exit(1);
7118
7481
  }
7119
- const { initCloud } = await import("./init-cloud-MQ6GRJAZ.js");
7482
+ const { initCloud } = await import("./init-cloud-3DNKPWFB.js");
7120
7483
  await initCloud({
7121
7484
  url: options.cloudUrl,
7122
7485
  port: options.port ? Number(options.port) : void 0,
@@ -7125,7 +7488,7 @@ initCmd.action(async (options) => {
7125
7488
  });
7126
7489
  return;
7127
7490
  }
7128
- const { init } = await import("./init-HGSM35XA.js");
7491
+ const { init } = await import("./init-SSGUSP7Z.js");
7129
7492
  const result = await init({
7130
7493
  projectRoot: process.cwd(),
7131
7494
  force: options.force,
@@ -7154,7 +7517,7 @@ initCmd.action(async (options) => {
7154
7517
  });
7155
7518
  program.command("snapshot").description("Run visual snapshot tests per component variant").option("-p, --port <port>", "Port of running dev server (skips starting one)").option("--update", "Update existing snapshots instead of comparing").option("--component <name>", "Filter to a specific component").option("--spec <path>", "Path to snapshot spec file").option("--ci", "CI mode - exit 1 on mismatch").action(async (options) => {
7156
7519
  try {
7157
- const { snapshot } = await import("./snapshot-KQEQ6XHL.js");
7520
+ const { snapshot } = await import("./snapshot-WIJMEIFT.js");
7158
7521
  const result = await snapshot({
7159
7522
  port: options.port,
7160
7523
  update: options.update,
@@ -7173,7 +7536,7 @@ program.command("snapshot").description("Run visual snapshot tests per component
7173
7536
  var tokensCmd = program.command("tokens").description("Design token discovery, listing, and generation");
7174
7537
  tokensCmd.command("list", { isDefault: true }).description("Discover and list design tokens from CSS/SCSS/DTCG files").option("-c, --config <path>", "Path to config file").option("--json", "Output as JSON").option("--categories", "Group tokens by category").option("--theme <theme>", "Filter by theme name").option("--category <category>", "Filter by category (color, spacing, typography, etc.)").option("--verbose", "Show all tokens (no truncation)").action(async (options) => {
7175
7538
  try {
7176
- const { tokens } = await import("./tokens-6GYKDV6U.js");
7539
+ const { tokens } = await import("./tokens-NZWFQIAB.js");
7177
7540
  const result = await tokens({
7178
7541
  config: options.config,
7179
7542
  json: options.json,
@@ -7192,7 +7555,7 @@ tokensCmd.command("list", { isDefault: true }).description("Discover and list de
7192
7555
  });
7193
7556
  tokensCmd.command("generate").description("Generate CSS, SCSS, Tailwind, or Figma output from a DTCG .tokens.json file").requiredOption("--from <path>", "Path to DTCG .tokens.json source file").requiredOption("--format <formats>", "Output formats (comma-separated: css, scss, tailwind, figma)").option("--out <dir>", "Output directory (default: same directory as source)").option("--prefix <prefix>", "Token name prefix").option("--selector <selector>", "CSS selector for custom properties (default: :root)").option("--verbose", "Verbose output").action(async (options) => {
7194
7557
  try {
7195
- const { tokensGenerate } = await import("./tokens-generate-VTZV5EEW.js");
7558
+ const { tokensGenerate } = await import("./tokens-generate-5JQSJ27E.js");
7196
7559
  await tokensGenerate({
7197
7560
  from: options.from,
7198
7561
  format: options.format,
@@ -7206,9 +7569,23 @@ tokensCmd.command("generate").description("Generate CSS, SCSS, Tailwind, or Figm
7206
7569
  process.exit(1);
7207
7570
  }
7208
7571
  });
7572
+ tokensCmd.command("push").description("Push code tokens to Fragments Cloud for drift comparison").option("-c, --config <path>", "Path to fragments config file").option("--tailwind-v4 <path>", "Path to Tailwind v4 CSS file with @theme block").option("--dry-run", "Parse and display tokens without pushing").option("--verbose", "Show detailed output").action(async (options) => {
7573
+ try {
7574
+ const { tokensPush } = await import("./tokens-push-HY3KO36V.js");
7575
+ await tokensPush({
7576
+ config: options.config,
7577
+ tailwindV4: options.tailwindV4,
7578
+ dryRun: options.dryRun,
7579
+ verbose: options.verbose
7580
+ });
7581
+ } catch (error) {
7582
+ console.error(pc26.red("Error:"), error instanceof Error ? error.message : error);
7583
+ process.exit(1);
7584
+ }
7585
+ });
7209
7586
  program.command("generate").description("Generate fragment files from component source code").argument("[component]", "Specific component name to generate (optional)").option("--force", "Overwrite existing fragment files").option("--pattern <glob>", "Pattern for component files", "src/components/**/*.tsx").action(async (component, options) => {
7210
7587
  try {
7211
- const { generate } = await import("./generate-A4FP5426.js");
7588
+ const { generate } = await import("./generate-PVOLUAAC.js");
7212
7589
  const result = await generate({
7213
7590
  projectRoot: process.cwd(),
7214
7591
  component,
@@ -7291,7 +7668,7 @@ program.command("perf").description("Profile component bundle sizes and performa
7291
7668
  program.command("test").description("Run interaction tests for fragments with play functions").option("-c, --config <path>", "Path to config file").option("--component <name>", "Filter by component name").option("--tags <tags>", "Filter by tags (comma-separated)").option("--grep <pattern>", "Filter by variant name pattern").option("--exclude <pattern>", "Exclude tests matching pattern").option("--parallel <count>", "Number of parallel browser contexts", parseInt, 4).option("--timeout <ms>", "Timeout per test in milliseconds", parseInt, 3e4).option("--retries <count>", "Number of retries for failed tests", parseInt, 0).option("--bail", "Stop on first failure").option("--browser <name>", "Browser to use (chromium, firefox, webkit)", "chromium").option("--headed", "Run in headed mode (show browser)").option("--a11y", "Run accessibility checks with axe-core").option("--visual", "Capture screenshots for visual regression").option("--update-snapshots", "Update visual snapshots").option("--watch", "Watch mode - re-run on file changes").option("--reporters <names>", "Reporters to use (console, junit, json)", "console").option("-o, --output <dir>", "Output directory for results", "./test-results").option("--server-url <url>", "URL of running dev server (skips starting server)").option("-p, --port <port>", "Port for dev server", parseInt, 6006).option("--ci", "CI mode - non-interactive, exit with code 1 on failure").option("--list", "List available tests without running them").action(async (options) => {
7292
7669
  try {
7293
7670
  const { config, configDir } = await loadConfig(options.config);
7294
- const { runTestCommand, listTests } = await import("./test-UQYUCZIS.js");
7671
+ const { runTestCommand, listTests } = await import("./test-64Z5BKBA.js");
7295
7672
  if (options.list) {
7296
7673
  await listTests(config, configDir, {
7297
7674
  component: options.component,
@@ -7392,7 +7769,7 @@ governCmd.command("connect").description("Connect your project to the Fragments
7392
7769
  });
7393
7770
  governCmd.command("scan").description("Scan JSX/TSX codebase for governance violations").option("-d, --dir <path>", "Root directory (default: auto-detect)").option("-c, --config <path>", "Path to govern.config.ts").option("-f, --format <format>", "Output format: summary, json, sarif", "summary").option("-q, --quiet", "Suppress non-error output").action(async (options) => {
7394
7771
  try {
7395
- const { governScan } = await import("./govern-scan-UCBZR6D6.js");
7772
+ const { governScan } = await import("./govern-scan-OYFZYOQW.js");
7396
7773
  const { exitCode } = await governScan({
7397
7774
  dir: options.dir,
7398
7775
  config: options.config,
@@ -7407,7 +7784,7 @@ governCmd.command("scan").description("Scan JSX/TSX codebase for governance viol
7407
7784
  });
7408
7785
  governCmd.command("watch").description("Watch JSX/TSX files and re-check on changes").option("-d, --dir <path>", "Root directory (default: auto-detect)").option("-c, --config <path>", "Path to govern.config.ts").option("-q, --quiet", "Suppress non-error output").option("--debounce <ms>", "Debounce interval in ms", "300").action(async (options) => {
7409
7786
  try {
7410
- const { governWatch } = await import("./govern-scan-UCBZR6D6.js");
7787
+ const { governWatch } = await import("./govern-scan-OYFZYOQW.js");
7411
7788
  await governWatch({
7412
7789
  dir: options.dir,
7413
7790
  config: options.config,
@@ -7419,5 +7796,20 @@ governCmd.command("watch").description("Watch JSX/TSX files and re-check on chan
7419
7796
  process.exit(1);
7420
7797
  }
7421
7798
  });
7799
+ governCmd.command("push-contracts").description("Push component contracts to Fragments Cloud").option("-i, --input <path>", "Path to fragments.json (default: ./fragments.json)").option("--url <url>", "Fragments Cloud URL").option("--api-key <key>", "API key (default: FRAGMENTS_API_KEY env var)").option("-q, --quiet", "Suppress non-error output").action(async (options) => {
7800
+ try {
7801
+ const { pushContracts } = await import("./push-contracts-WY32TFP6.js");
7802
+ const { exitCode } = await pushContracts({
7803
+ input: options.input,
7804
+ url: options.url,
7805
+ apiKey: options.apiKey,
7806
+ quiet: options.quiet
7807
+ });
7808
+ process.exit(exitCode);
7809
+ } catch (error) {
7810
+ console.error(pc26.red("Error:"), error instanceof Error ? error.message : error);
7811
+ process.exit(1);
7812
+ }
7813
+ });
7422
7814
  program.parse();
7423
7815
  //# sourceMappingURL=bin.js.map