@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.
- package/dist/{ai-client-I6MDWNYA.js → ai-client-LSLQGOMM.js} +1 -2
- package/dist/bin.js +463 -71
- package/dist/bin.js.map +1 -1
- package/dist/chunk-5JF26E55.js +1255 -0
- package/dist/chunk-5JF26E55.js.map +1 -0
- package/dist/{chunk-XJQ5BIWI.js → chunk-6SQPP47U.js} +30 -314
- package/dist/chunk-6SQPP47U.js.map +1 -0
- package/dist/{chunk-65WSVDV5.js → chunk-HQ6A6DTV.js} +1386 -1097
- package/dist/chunk-HQ6A6DTV.js.map +1 -0
- package/dist/chunk-MHIBEEW4.js +511 -0
- package/dist/chunk-MHIBEEW4.js.map +1 -0
- package/dist/{chunk-CZD3AD4Q.js → chunk-ONUP6Z4W.js} +17 -6
- package/dist/chunk-ONUP6Z4W.js.map +1 -0
- package/dist/{codebase-scanner-VOTPXRYW.js → codebase-scanner-MQHUZC2G.js} +1 -2
- package/dist/{converter-JLINP7CJ.js → converter-7XM3Y6NJ.js} +1 -2
- package/dist/{converter-JLINP7CJ.js.map → converter-7XM3Y6NJ.js.map} +1 -1
- package/dist/core/index.js +0 -1
- package/dist/create-IH4R45GE.js +806 -0
- package/dist/create-IH4R45GE.js.map +1 -0
- package/dist/{generate-A4FP5426.js → generate-PVOLUAAC.js} +3 -4
- package/dist/{generate-A4FP5426.js.map → generate-PVOLUAAC.js.map} +1 -1
- package/dist/{govern-scan-UCBZR6D6.js → govern-scan-OYFZYOQW.js} +142 -9
- package/dist/govern-scan-OYFZYOQW.js.map +1 -0
- package/dist/index.d.ts +2 -22
- package/dist/index.js +8 -7
- package/dist/index.js.map +1 -1
- package/dist/{init-HGSM35XA.js → init-SSGUSP7Z.js} +3 -4
- package/dist/{init-HGSM35XA.js.map → init-SSGUSP7Z.js.map} +1 -1
- package/dist/{init-cloud-MQ6GRJAZ.js → init-cloud-3DNKPWFB.js} +29 -4
- package/dist/{init-cloud-MQ6GRJAZ.js.map → init-cloud-3DNKPWFB.js.map} +1 -1
- package/dist/mcp-bin.js +1 -2
- package/dist/mcp-bin.js.map +1 -1
- package/dist/node-37AUE74M.js +65 -0
- package/dist/push-contracts-WY32TFP6.js +84 -0
- package/dist/push-contracts-WY32TFP6.js.map +1 -0
- package/dist/{scan-VNNKACG2.js → scan-PKSYSTRR.js} +5 -5
- package/dist/{scan-generate-TWRHNU5M.js → scan-generate-VY27PIOX.js} +8 -9
- package/dist/scan-generate-VY27PIOX.js.map +1 -0
- package/dist/{scanner-7LAZYPWZ.js → scanner-4KZNOXAK.js} +1 -2
- package/dist/{service-FHQU7YS7.js → service-QJGWUIVL.js} +16 -9
- package/dist/{snapshot-KQEQ6XHL.js → snapshot-WIJMEIFT.js} +1 -2
- package/dist/{snapshot-KQEQ6XHL.js.map → snapshot-WIJMEIFT.js.map} +1 -1
- package/dist/{static-viewer-63PG6FWY.js → static-viewer-7QIBQZRC.js} +1 -2
- package/dist/{test-UQYUCZIS.js → test-64Z5BKBA.js} +2 -3
- package/dist/{test-UQYUCZIS.js.map → test-64Z5BKBA.js.map} +1 -1
- package/dist/token-normalizer-TEPOVBPV.js +312 -0
- package/dist/token-normalizer-TEPOVBPV.js.map +1 -0
- package/dist/token-parser-32KOIOFN.js +22 -0
- package/dist/token-parser-32KOIOFN.js.map +1 -0
- package/dist/{tokens-6GYKDV6U.js → tokens-NZWFQIAB.js} +7 -7
- package/dist/{tokens-generate-VTZV5EEW.js → tokens-generate-5JQSJ27E.js} +1 -2
- package/dist/{tokens-generate-VTZV5EEW.js.map → tokens-generate-5JQSJ27E.js.map} +1 -1
- package/dist/tokens-push-HY3KO36V.js +148 -0
- package/dist/tokens-push-HY3KO36V.js.map +1 -0
- package/package.json +5 -3
- package/src/bin.ts +90 -0
- package/src/commands/__fixtures__/shadcn-label-wrapper/src/components/ui/label.contract.json +1 -1
- package/src/commands/__fixtures__/shadcn-label-wrapper/src/components/ui/primitive.contract.json +1 -1
- package/src/commands/__tests__/build-freshness.test.ts +231 -0
- package/src/commands/__tests__/create.test.ts +71 -0
- package/src/commands/__tests__/drift-sync.test.ts +1 -1
- package/src/commands/__tests__/govern.test.ts +258 -0
- package/src/commands/__tests__/init.test.ts +1 -1
- package/src/commands/__tests__/scan-generate.test.ts +1 -1
- package/src/commands/build.ts +54 -1
- package/src/commands/context.ts +1 -1
- package/src/commands/create.ts +536 -0
- package/src/commands/doctor.ts +3 -2
- package/src/commands/govern-scan.ts +187 -8
- package/src/commands/govern.ts +65 -2
- package/src/commands/init-cloud.ts +32 -4
- package/src/commands/push-contracts.ts +112 -0
- package/src/commands/scan-generate.ts +1 -1
- package/src/commands/scan.ts +13 -0
- package/src/commands/sync.ts +2 -2
- package/src/commands/tokens-push.ts +199 -0
- package/src/core/__tests__/token-resolver.test.ts +1 -1
- package/src/core/component-extractor.test.ts +1 -1
- package/src/core/drift-verifier.ts +1 -1
- package/src/core/extractor-adapter.ts +1 -1
- package/src/index.ts +3 -3
- package/src/migrate/fragment-to-contract.ts +2 -2
- package/src/service/index.ts +8 -0
- package/src/service/tailwind-v4-parser.ts +314 -0
- package/src/service/token-parser.ts +56 -0
- package/src/setup.ts +10 -39
- package/src/theme/__tests__/component-contrast.test.ts +2 -2
- package/src/theme/__tests__/serializer.test.ts +1 -1
- package/src/theme/generator.ts +16 -1
- package/src/theme/schema.ts +8 -0
- package/src/theme/serializer.ts +13 -9
- package/src/theme/types.ts +8 -0
- package/src/validators.ts +1 -2
- package/dist/chunk-65WSVDV5.js.map +0 -1
- package/dist/chunk-7WHVW72L.js +0 -2664
- package/dist/chunk-7WHVW72L.js.map +0 -1
- package/dist/chunk-CZD3AD4Q.js.map +0 -1
- package/dist/chunk-MN3TJ3D5.js +0 -695
- package/dist/chunk-MN3TJ3D5.js.map +0 -1
- package/dist/chunk-XJQ5BIWI.js.map +0 -1
- package/dist/chunk-Z7EY4VHE.js +0 -50
- package/dist/govern-scan-UCBZR6D6.js.map +0 -1
- package/dist/sass.node-4XJK6YBF.js +0 -130708
- package/dist/sass.node-4XJK6YBF.js.map +0 -1
- package/dist/scan-generate-TWRHNU5M.js.map +0 -1
- package/src/build.ts +0 -736
- package/src/core/auto-props.ts +0 -464
- package/src/core/component-extractor.ts +0 -1121
- package/src/core/token-resolver.ts +0 -155
- package/src/viewer/preview-adapter.ts +0 -116
- /package/dist/{ai-client-I6MDWNYA.js.map → ai-client-LSLQGOMM.js.map} +0 -0
- /package/dist/{chunk-Z7EY4VHE.js.map → codebase-scanner-MQHUZC2G.js.map} +0 -0
- /package/dist/{codebase-scanner-VOTPXRYW.js.map → node-37AUE74M.js.map} +0 -0
- /package/dist/{scan-VNNKACG2.js.map → scan-PKSYSTRR.js.map} +0 -0
- /package/dist/{scanner-7LAZYPWZ.js.map → scanner-4KZNOXAK.js.map} +0 -0
- /package/dist/{service-FHQU7YS7.js.map → service-QJGWUIVL.js.map} +0 -0
- /package/dist/{static-viewer-63PG6FWY.js.map → static-viewer-7QIBQZRC.js.map} +0 -0
- /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-
|
|
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-
|
|
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-
|
|
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
|
|
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
|
|
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
|
|
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 =
|
|
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
|
|
5926
|
+
import { join as join11, resolve as resolve12 } from "path";
|
|
5642
5927
|
import pc22 from "picocolors";
|
|
5643
|
-
|
|
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 =
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 {
|
|
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
|
|
6257
|
-
const
|
|
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(
|
|
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:
|
|
6265
|
-
const { resolve:
|
|
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 =
|
|
6668
|
+
const envPath = resolve15(".env");
|
|
6334
6669
|
const envEntry = `FRAGMENTS_API_KEY=${apiKey.trim()}`;
|
|
6335
|
-
if (
|
|
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 =
|
|
6364
|
-
if (
|
|
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
|
|
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
|
|
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 =
|
|
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 =
|
|
6818
|
+
const extractor = createComponentExtractor2(options?.tsconfigPath);
|
|
6482
6819
|
try {
|
|
6483
6820
|
const componentExportName = parsed.componentName ?? parsed.meta.name;
|
|
6484
|
-
const componentSourcePath =
|
|
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 =
|
|
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 =
|
|
6509
|
-
sourcePath = relative8(configDir,
|
|
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 ?
|
|
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 =
|
|
6659
|
-
var pkg = JSON.parse(readFileSync(
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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
|