@fragments-sdk/cli 0.15.10 → 0.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. package/dist/bin.js +901 -789
  2. package/dist/bin.js.map +1 -1
  3. package/dist/{chunk-6SQPP47U.js → chunk-ANTWP3UG.js} +532 -31
  4. package/dist/chunk-ANTWP3UG.js.map +1 -0
  5. package/dist/{chunk-ONUP6Z4W.js → chunk-B4A4ZEGS.js} +9 -9
  6. package/dist/{chunk-32LIWN2P.js → chunk-FFCI6OVZ.js} +584 -261
  7. package/dist/chunk-FFCI6OVZ.js.map +1 -0
  8. package/dist/{chunk-HQ6A6DTV.js → chunk-HNHE64CR.js} +315 -1089
  9. package/dist/chunk-HNHE64CR.js.map +1 -0
  10. package/dist/{chunk-BJE3425I.js → chunk-MN3B2EE6.js} +2 -2
  11. package/dist/{chunk-QCN35LJU.js → chunk-SAQW37L5.js} +3 -2
  12. package/dist/chunk-SAQW37L5.js.map +1 -0
  13. package/dist/{chunk-2WXKALIG.js → chunk-SNZXGHL2.js} +2 -2
  14. package/dist/{chunk-5JF26E55.js → chunk-VT2J62ND.js} +11 -11
  15. package/dist/{codebase-scanner-MQHUZC2G.js → codebase-scanner-2T5QIDBA.js} +2 -2
  16. package/dist/core/index.js +53 -1
  17. package/dist/{create-EXURTBKK.js → create-D44QD7MV.js} +2 -2
  18. package/dist/{doctor-BDPMYYE6.js → doctor-7B5N4JYU.js} +2 -2
  19. package/dist/{generate-PVOLUAAC.js → generate-T47JZRVU.js} +4 -4
  20. package/dist/govern-scan-X6UEIOSV.js +632 -0
  21. package/dist/govern-scan-X6UEIOSV.js.map +1 -0
  22. package/dist/index.js +7 -8
  23. package/dist/index.js.map +1 -1
  24. package/dist/{init-SSGUSP7Z.js → init-2RGAY4W6.js} +5 -5
  25. package/dist/mcp-bin.js +2 -2
  26. package/dist/scan-A2WJM54L.js +14 -0
  27. package/dist/{scan-generate-VY27PIOX.js → scan-generate-LUSOHT36.js} +4 -4
  28. package/dist/{service-QJGWUIVL.js → service-ROCP7TKG.js} +13 -15
  29. package/dist/{snapshot-WIJMEIFT.js → snapshot-B3SAW74Y.js} +2 -2
  30. package/dist/{static-viewer-7QIBQZRC.js → static-viewer-7L6UEYTJ.js} +3 -3
  31. package/dist/{test-64Z5BKBA.js → test-PQDVDURE.js} +3 -3
  32. package/dist/{token-normalizer-TEPOVBPV.js → token-normalizer-7TFCVDZL.js} +2 -2
  33. package/dist/{tokens-NZWFQIAB.js → tokens-64FG5FDP.js} +8 -9
  34. package/dist/{tokens-NZWFQIAB.js.map → tokens-64FG5FDP.js.map} +1 -1
  35. package/dist/{tokens-generate-5JQSJ27E.js → tokens-generate-CL4LBBQA.js} +2 -2
  36. package/package.json +9 -8
  37. package/src/bin.ts +55 -88
  38. package/src/commands/__fixtures__/shadcn-label-wrapper/src/components/ui/label.contract.json +1 -1
  39. package/src/commands/__fixtures__/shadcn-label-wrapper/src/components/ui/primitive.contract.json +1 -1
  40. package/src/commands/__tests__/context-cloud.test.ts +291 -0
  41. package/src/commands/__tests__/govern-scan.test.ts +185 -0
  42. package/src/commands/__tests__/govern.test.ts +1 -0
  43. package/src/commands/context-cloud.ts +355 -0
  44. package/src/commands/govern-scan-report.ts +170 -0
  45. package/src/commands/govern-scan.ts +282 -135
  46. package/src/commands/govern.ts +0 -157
  47. package/src/mcp/__tests__/server.integration.test.ts +9 -20
  48. package/src/service/enhance/codebase-scanner.ts +3 -2
  49. package/src/service/enhance/types.ts +3 -0
  50. package/dist/chunk-32LIWN2P.js.map +0 -1
  51. package/dist/chunk-6SQPP47U.js.map +0 -1
  52. package/dist/chunk-HQ6A6DTV.js.map +0 -1
  53. package/dist/chunk-MHIBEEW4.js +0 -511
  54. package/dist/chunk-MHIBEEW4.js.map +0 -1
  55. package/dist/chunk-QCN35LJU.js.map +0 -1
  56. package/dist/govern-scan-DW4QUAYD.js +0 -414
  57. package/dist/govern-scan-DW4QUAYD.js.map +0 -1
  58. package/dist/init-cloud-3DNKPWFB.js +0 -304
  59. package/dist/init-cloud-3DNKPWFB.js.map +0 -1
  60. package/dist/node-37AUE74M.js +0 -65
  61. package/dist/push-contracts-WY32TFP6.js +0 -84
  62. package/dist/push-contracts-WY32TFP6.js.map +0 -1
  63. package/dist/scan-PKSYSTRR.js +0 -15
  64. package/dist/static-viewer-7QIBQZRC.js.map +0 -1
  65. package/dist/token-parser-32KOIOFN.js +0 -22
  66. package/dist/token-parser-32KOIOFN.js.map +0 -1
  67. package/dist/tokens-push-HY3KO36V.js +0 -148
  68. package/dist/tokens-push-HY3KO36V.js.map +0 -1
  69. package/src/commands/init-cloud.ts +0 -382
  70. package/src/commands/push-contracts.ts +0 -112
  71. package/src/commands/tokens-push.ts +0 -199
  72. /package/dist/{chunk-ONUP6Z4W.js.map → chunk-B4A4ZEGS.js.map} +0 -0
  73. /package/dist/{chunk-BJE3425I.js.map → chunk-MN3B2EE6.js.map} +0 -0
  74. /package/dist/{chunk-2WXKALIG.js.map → chunk-SNZXGHL2.js.map} +0 -0
  75. /package/dist/{chunk-5JF26E55.js.map → chunk-VT2J62ND.js.map} +0 -0
  76. /package/dist/{codebase-scanner-MQHUZC2G.js.map → codebase-scanner-2T5QIDBA.js.map} +0 -0
  77. /package/dist/{create-EXURTBKK.js.map → create-D44QD7MV.js.map} +0 -0
  78. /package/dist/{doctor-BDPMYYE6.js.map → doctor-7B5N4JYU.js.map} +0 -0
  79. /package/dist/{generate-PVOLUAAC.js.map → generate-T47JZRVU.js.map} +0 -0
  80. /package/dist/{init-SSGUSP7Z.js.map → init-2RGAY4W6.js.map} +0 -0
  81. /package/dist/{node-37AUE74M.js.map → scan-A2WJM54L.js.map} +0 -0
  82. /package/dist/{scan-generate-VY27PIOX.js.map → scan-generate-LUSOHT36.js.map} +0 -0
  83. /package/dist/{scan-PKSYSTRR.js.map → service-ROCP7TKG.js.map} +0 -0
  84. /package/dist/{snapshot-WIJMEIFT.js.map → snapshot-B3SAW74Y.js.map} +0 -0
  85. /package/dist/{service-QJGWUIVL.js.map → static-viewer-7L6UEYTJ.js.map} +0 -0
  86. /package/dist/{test-64Z5BKBA.js.map → test-PQDVDURE.js.map} +0 -0
  87. /package/dist/{token-normalizer-TEPOVBPV.js.map → token-normalizer-7TFCVDZL.js.map} +0 -0
  88. /package/dist/{tokens-generate-5JQSJ27E.js.map → tokens-generate-CL4LBBQA.js.map} +0 -0
@@ -1,199 +0,0 @@
1
- /**
2
- * fragments tokens push — Push code tokens to Fragments Cloud for drift comparison.
3
- *
4
- * Extracts CSS custom properties from Tailwind v4 @theme blocks (or config-based
5
- * token files) and POSTs them to the Fragments Cloud /api/ingest endpoint.
6
- * Supports --dry-run for local inspection without pushing.
7
- */
8
-
9
- import { resolve } from 'node:path';
10
- import pc from 'picocolors';
11
-
12
- // ---------------------------------------------------------------------------
13
- // Options
14
- // ---------------------------------------------------------------------------
15
-
16
- export interface TokensPushOptions {
17
- /** Path to fragments config file */
18
- config?: string;
19
- /** Path to Tailwind v4 CSS file with @theme block */
20
- tailwindV4?: string;
21
- /** Parse and display tokens without pushing */
22
- dryRun?: boolean;
23
- /** Show detailed output */
24
- verbose?: boolean;
25
- }
26
-
27
- // ---------------------------------------------------------------------------
28
- // tokensPush
29
- // ---------------------------------------------------------------------------
30
-
31
- export async function tokensPush(options: TokensPushOptions): Promise<void> {
32
- const startTime = Date.now();
33
-
34
- // 1. Resolve API credentials
35
- const apiKey = process.env.FRAGMENTS_API_KEY;
36
- const baseUrl = process.env.FRAGMENTS_URL || 'https://app.usefragments.com';
37
-
38
- if (!apiKey && !options.dryRun) {
39
- console.error(pc.red('Error: FRAGMENTS_API_KEY environment variable is required'));
40
- console.error(pc.dim('Get your API key from https://app.usefragments.com/api-keys'));
41
- process.exit(1);
42
- }
43
-
44
- // 2. Token extraction
45
- const flatMap: Record<string, string> = {};
46
-
47
- if (options.tailwindV4) {
48
- // Use @theme parser for Tailwind v4 CSS files
49
- const { parseTailwindV4File } = await import('../service/token-parser.js');
50
-
51
- const filePath = resolve(process.cwd(), options.tailwindV4);
52
- const result = parseTailwindV4File(filePath);
53
-
54
- if (result.errors.length > 0) {
55
- for (const err of result.errors) {
56
- console.error(pc.red(` Error: ${err.message}`));
57
- }
58
- }
59
-
60
- if (options.verbose && result.warnings.length > 0) {
61
- for (const warn of result.warnings) {
62
- console.warn(pc.yellow(` Warning: ${warn}`));
63
- }
64
- }
65
-
66
- for (const token of result.tokens) {
67
- flatMap[token.name] = token.resolvedValue;
68
- }
69
-
70
- if (options.verbose) {
71
- console.log(
72
- pc.dim(` Parsed ${result.tokens.length} tokens from ${options.tailwindV4} (${result.parseTimeMs.toFixed(1)}ms)`),
73
- );
74
- }
75
- } else if (options.config) {
76
- // Use config-based token extraction
77
- try {
78
- const { loadConfig } = await import('../core/node.js');
79
- const { parseTokenFiles } = await import('../service/index.js');
80
-
81
- const { config, configDir } = await loadConfig(options.config);
82
- if (config.tokens?.include?.length) {
83
- const result = await parseTokenFiles(config.tokens, configDir);
84
- for (const token of result.tokens) {
85
- flatMap[token.name] = token.resolvedValue;
86
- }
87
-
88
- if (options.verbose) {
89
- console.log(
90
- pc.dim(` Parsed ${result.tokens.length} tokens from config (${result.parseTimeMs.toFixed(1)}ms)`),
91
- );
92
- }
93
- } else {
94
- console.error(pc.red('Error: Config file has no tokens.include patterns'));
95
- process.exit(1);
96
- }
97
- } catch (error) {
98
- console.error(pc.red('Error loading config:'), error instanceof Error ? error.message : error);
99
- process.exit(1);
100
- }
101
- } else {
102
- // No source specified — try auto-detection
103
- try {
104
- const { loadConfig } = await import('../core/node.js');
105
- const { parseTokenFiles } = await import('../service/index.js');
106
-
107
- const { config, configDir } = await loadConfig();
108
- if (config.tokens?.include?.length) {
109
- const result = await parseTokenFiles(config.tokens, configDir);
110
- for (const token of result.tokens) {
111
- flatMap[token.name] = token.resolvedValue;
112
- }
113
-
114
- if (options.verbose) {
115
- console.log(
116
- pc.dim(` Parsed ${result.tokens.length} tokens from auto-detected config (${result.parseTimeMs.toFixed(1)}ms)`),
117
- );
118
- }
119
- }
120
- } catch {
121
- // No config found — fall through to error
122
- }
123
-
124
- if (Object.keys(flatMap).length === 0) {
125
- console.error(pc.red('Error: No token source specified'));
126
- console.error(pc.dim('Provide one of:'));
127
- console.error(pc.dim(' --tailwind-v4 <path> Path to Tailwind v4 CSS file with @theme block'));
128
- console.error(pc.dim(' --config <path> Path to fragments config with tokens.include'));
129
- console.error(pc.dim('\nExample: fragments tokens push --tailwind-v4 ./app.css'));
130
- process.exit(1);
131
- }
132
- }
133
-
134
- const tokenCount = Object.keys(flatMap).length;
135
-
136
- if (tokenCount === 0) {
137
- console.log(pc.yellow('No tokens found.'));
138
- return;
139
- }
140
-
141
- console.log(pc.cyan(`Found ${tokenCount} tokens`));
142
-
143
- // 3. Dry run — display tokens and exit
144
- if (options.dryRun) {
145
- console.log(pc.dim('\nDry run — tokens that would be pushed:\n'));
146
- const entries = Object.entries(flatMap);
147
- for (const [name, value] of entries.slice(0, 20)) {
148
- console.log(` ${pc.bold(name)}: ${value}`);
149
- }
150
- if (entries.length > 20) {
151
- console.log(pc.dim(` ... and ${entries.length - 20} more`));
152
- }
153
- return;
154
- }
155
-
156
- // 4. POST to Fragments Cloud
157
- try {
158
- const response = await fetch(`${baseUrl}/api/ingest`, {
159
- method: 'POST',
160
- headers: {
161
- 'Content-Type': 'application/json',
162
- 'Authorization': `Bearer ${apiKey}`,
163
- },
164
- body: JSON.stringify({
165
- codeTokens: JSON.stringify(flatMap),
166
- }),
167
- });
168
-
169
- if (!response.ok) {
170
- const errorText = await response.text();
171
- console.error(pc.red(`Error: API returned ${response.status}`));
172
- console.error(pc.dim(errorText));
173
- process.exit(1);
174
- }
175
-
176
- const result = await response.json() as Record<string, unknown>;
177
-
178
- console.log(pc.green(`\nPushed ${tokenCount} tokens to Fragments Cloud`));
179
-
180
- if (result.tokenDrift) {
181
- const drift = result.tokenDrift as Record<string, unknown>;
182
- const summary = drift.summary as Record<string, number> | undefined;
183
- if (summary) {
184
- console.log(pc.cyan('\nDrift Summary:'));
185
- if (summary.total !== undefined) console.log(pc.dim(` Total issues: ${summary.total}`));
186
- if (summary.missingInCode > 0) console.log(pc.yellow(` Missing in code: ${summary.missingInCode}`));
187
- if (summary.missingInFigma > 0) console.log(pc.yellow(` Missing in Figma: ${summary.missingInFigma}`));
188
- if (summary.valueMismatch > 0) console.log(pc.yellow(` Value mismatches: ${summary.valueMismatch}`));
189
- if (summary.score !== undefined) console.log(` Health score: ${summary.score}%`);
190
- }
191
- }
192
-
193
- console.log(pc.dim(`\nView dashboard: ${baseUrl}/tokens`));
194
- console.log(pc.dim(`Completed in ${Date.now() - startTime}ms`));
195
- } catch (error) {
196
- console.error(pc.red('Error pushing tokens:'), error instanceof Error ? error.message : error);
197
- process.exit(1);
198
- }
199
- }