@fragments-sdk/cli 0.9.0 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin.d.ts +1 -0
- package/dist/bin.js +502 -84
- package/dist/bin.js.map +1 -1
- package/dist/{chunk-CJEGT3WD.js → chunk-566BNPQZ.js} +21 -6
- package/dist/chunk-566BNPQZ.js.map +1 -0
- package/dist/{chunk-WI6SLMSO.js → chunk-CAMXG5HJ.js} +5 -5
- package/dist/chunk-D2CDBRNU.js +2 -0
- package/dist/{chunk-YMPGYEWK.js → chunk-D5PYOXEI.js} +2 -2
- package/dist/{chunk-NGIMCIK2.js → chunk-OQO55NKV.js} +405 -34
- package/dist/chunk-OQO55NKV.js.map +1 -0
- package/dist/{chunk-TOIE7VXF.js → chunk-PW7QTQA6.js} +2 -2
- package/dist/{chunk-AWYCDRPG.js → chunk-WXSR2II7.js} +2 -2
- package/dist/chunk-WXSR2II7.js.map +1 -0
- package/dist/{chunk-2JIKCJX3.js → chunk-ZDA3PLQ6.js} +17 -14
- package/dist/chunk-ZDA3PLQ6.js.map +1 -0
- package/dist/core/index.d.ts +1 -2092
- package/dist/core/index.js +26 -21
- package/dist/{discovery-Z4RDDFVR.js → discovery-NEOY4MPN.js} +3 -3
- package/dist/generate-BGKTKO6E.js +459 -0
- package/dist/generate-BGKTKO6E.js.map +1 -0
- package/dist/index.d.ts +3 -5
- package/dist/index.js +7 -8
- package/dist/index.js.map +1 -1
- package/dist/{init-KSAAS7X3.js → init-Q53R5Q2T.js} +66 -76
- package/dist/init-Q53R5Q2T.js.map +1 -0
- package/dist/mcp-bin.js +5 -7
- package/dist/mcp-bin.js.map +1 -1
- package/dist/scan-OQU7M4GH.js +14 -0
- package/dist/scan-generate-T5QNUG7N.js +691 -0
- package/dist/scan-generate-T5QNUG7N.js.map +1 -0
- package/dist/{service-A5GIGGGK.js → service-TQYWY65E.js} +4 -5
- package/dist/{static-viewer-NSODM5VX.js → static-viewer-NUBFPKWH.js} +4 -5
- package/dist/static-viewer-NUBFPKWH.js.map +1 -0
- package/dist/{test-RPWZAYSJ.js → test-2CSOSS3B.js} +4 -5
- package/dist/{test-RPWZAYSJ.js.map → test-2CSOSS3B.js.map} +1 -1
- package/dist/{tokens-NIXSZRX7.js → tokens-DXEGYTOJ.js} +6 -7
- package/dist/{tokens-NIXSZRX7.js.map → tokens-DXEGYTOJ.js.map} +1 -1
- package/dist/{viewer-SBTJDMP7.js → viewer-DBEPYM3G.js} +245 -23
- package/dist/viewer-DBEPYM3G.js.map +1 -0
- package/package.json +2 -1
- package/src/bin.ts +33 -1
- package/src/build.ts +13 -3
- package/src/commands/__tests__/scan-generate.test.ts +308 -0
- package/src/commands/build.ts +16 -2
- package/src/commands/generate.ts +383 -68
- package/src/commands/init.ts +81 -56
- package/src/commands/perf.ts +1 -1
- package/src/commands/scan-generate.ts +1013 -0
- package/src/commands/setup.ts +499 -0
- package/src/core/auto-props.ts +1 -1
- package/src/core/bundle-measurer.ts +2 -2
- package/src/core/config.ts +16 -4
- package/src/core/discovery.ts +2 -2
- package/src/core/generators/context.ts +1 -1
- package/src/core/generators/registry.ts +3 -3
- package/src/core/generators/typescript-extractor.ts +11 -1
- package/src/core/graph-extractor.ts +1 -1
- package/src/core/index.ts +3 -190
- package/src/core/loader.ts +2 -2
- package/src/core/parser.ts +1 -1
- package/src/core/previewLoader.ts +1 -1
- package/src/index.ts +2 -2
- package/src/migrate/converter.ts +9 -1
- package/src/migrate/parser.ts +2 -0
- package/src/migrate/types.ts +2 -0
- package/src/service/snippet-validation.test.ts +1 -1
- package/src/service/snippet-validation.ts +2 -2
- package/src/setup.ts +69 -24
- package/src/viewer/__tests__/viewer-integration.test.ts +4 -10
- package/src/viewer/components/AccessibilityPanel.tsx +305 -312
- package/src/viewer/components/ActionsPanel.tsx +31 -29
- package/src/viewer/components/AllVariantsPreview.tsx +78 -0
- package/src/viewer/components/App.tsx +187 -740
- package/src/viewer/components/BottomPanel.tsx +228 -132
- package/src/viewer/components/CodePanel.tsx +1 -1
- package/src/viewer/components/CommandPalette.tsx +7 -10
- package/src/viewer/components/ComponentDocView.tsx +164 -0
- package/src/viewer/components/ComponentGraph.tsx +111 -142
- package/src/viewer/components/ContractPanel.tsx +6 -6
- package/src/viewer/components/EmptyVariantMessage.tsx +54 -0
- package/src/viewer/components/FigmaEmbed.tsx +20 -18
- package/src/viewer/components/FragmentEditor.tsx +92 -115
- package/src/viewer/components/HeaderSearch.tsx +24 -0
- package/src/viewer/components/HealthDashboard.tsx +16 -2
- package/src/viewer/components/Icons.tsx +9 -0
- package/src/viewer/components/InteractionsPanel.tsx +101 -117
- package/src/viewer/components/IsolatedPreviewFrame.tsx +1 -0
- package/src/viewer/components/LandingPage.tsx +3 -3
- package/src/viewer/components/LeftSidebar.tsx +141 -63
- package/src/viewer/components/LoadErrorMessage.tsx +102 -0
- package/src/viewer/components/MultiViewportPreview.tsx +61 -142
- package/src/viewer/components/NoVariantsMessage.tsx +59 -0
- package/src/viewer/components/PanelShell.tsx +161 -0
- package/src/viewer/components/PerformancePanel.tsx +31 -28
- package/src/viewer/components/PreviewArea.tsx +1 -1
- package/src/viewer/components/PreviewAside.tsx +168 -0
- package/src/viewer/components/PreviewFrameHost.tsx +3 -3
- package/src/viewer/components/PropsEditor.tsx +70 -156
- package/src/viewer/components/ResizablePanel.tsx +103 -263
- package/src/viewer/components/RightSidebar.tsx +3 -9
- package/src/viewer/components/SkeletonLoader.tsx +13 -13
- package/src/viewer/components/TokenStylePanel.tsx +182 -209
- package/src/viewer/components/TopToolbar.tsx +159 -0
- package/src/viewer/components/VariantMatrix.tsx +42 -86
- package/src/viewer/components/VariantTabs.tsx +3 -3
- package/src/viewer/components/ViewerHeader.tsx +69 -0
- package/src/viewer/components/WebMCPDevTools.tsx +17 -23
- package/src/viewer/components/viewer-utils.ts +16 -0
- package/src/viewer/entry.tsx +5 -0
- package/src/viewer/hooks/useAppState.ts +27 -4
- package/src/viewer/hooks/usePreviewBridge.ts +2 -2
- package/src/viewer/preview-frame.html +6 -12
- package/src/viewer/server.ts +169 -2
- package/src/viewer/vendor/shared/src/ComponentDocContent.module.scss +10 -0
- package/src/viewer/vendor/shared/src/ComponentDocContent.module.scss.d.ts +2 -0
- package/src/viewer/vendor/shared/src/ComponentDocContent.tsx +274 -0
- package/src/viewer/vendor/shared/src/DocsHeaderBar.tsx +6 -18
- package/src/viewer/vendor/shared/src/DocsPageShell.tsx +5 -0
- package/src/viewer/vendor/shared/src/DocsSidebarNav.tsx +5 -16
- package/src/viewer/vendor/shared/src/PropsTable.module.scss +68 -0
- package/src/viewer/vendor/shared/src/PropsTable.module.scss.d.ts +2 -0
- package/src/viewer/vendor/shared/src/PropsTable.tsx +76 -0
- package/src/viewer/vendor/shared/src/VariantPreviewCard.module.scss +114 -0
- package/src/viewer/vendor/shared/src/VariantPreviewCard.module.scss.d.ts +2 -0
- package/src/viewer/vendor/shared/src/VariantPreviewCard.tsx +134 -0
- package/src/viewer/vendor/shared/src/index.ts +8 -0
- package/src/viewer/vendor/shared/src/types.ts +12 -0
- package/src/viewer/vite-plugin.ts +109 -4
- package/dist/chunk-2JIKCJX3.js.map +0 -1
- package/dist/chunk-AWYCDRPG.js.map +0 -1
- package/dist/chunk-CJEGT3WD.js.map +0 -1
- package/dist/chunk-EKLMXTWU.js +0 -80
- package/dist/chunk-EKLMXTWU.js.map +0 -1
- package/dist/chunk-GOVI6COW.js +0 -195
- package/dist/chunk-GOVI6COW.js.map +0 -1
- package/dist/chunk-NGIMCIK2.js.map +0 -1
- package/dist/defineFragment-D0UTve-I.d.ts +0 -665
- package/dist/generate-35OIMW4Y.js +0 -252
- package/dist/generate-35OIMW4Y.js.map +0 -1
- package/dist/init-KSAAS7X3.js.map +0 -1
- package/dist/scan-65RH3QMM.js +0 -15
- package/dist/viewer-SBTJDMP7.js.map +0 -1
- package/src/core/__tests__/preview-runtime.test.tsx +0 -111
- package/src/core/composition.test.ts +0 -262
- package/src/core/composition.ts +0 -318
- package/src/core/constants.ts +0 -114
- package/src/core/context.ts +0 -2
- package/src/core/defineFragment.ts +0 -141
- package/src/core/figma.ts +0 -263
- package/src/core/fragment-types.ts +0 -214
- package/src/core/performance-presets.ts +0 -142
- package/src/core/preview-runtime.tsx +0 -144
- package/src/core/schema.ts +0 -221
- package/src/core/storyAdapter.test.ts +0 -571
- package/src/core/storyAdapter.ts +0 -761
- package/src/core/storybook-csf.ts +0 -11
- package/src/core/token-parser.ts +0 -321
- package/src/core/token-types.ts +0 -287
- package/src/core/types.ts +0 -762
- /package/dist/{chunk-WI6SLMSO.js.map → chunk-CAMXG5HJ.js.map} +0 -0
- /package/dist/{discovery-Z4RDDFVR.js.map → chunk-D2CDBRNU.js.map} +0 -0
- /package/dist/{chunk-YMPGYEWK.js.map → chunk-D5PYOXEI.js.map} +0 -0
- /package/dist/{chunk-TOIE7VXF.js.map → chunk-PW7QTQA6.js.map} +0 -0
- /package/dist/{scan-65RH3QMM.js.map → discovery-NEOY4MPN.js.map} +0 -0
- /package/dist/{service-A5GIGGGK.js.map → scan-OQU7M4GH.js.map} +0 -0
- /package/dist/{static-viewer-NSODM5VX.js.map → service-TQYWY65E.js.map} +0 -0
package/dist/bin.js
CHANGED
|
@@ -12,17 +12,17 @@ import {
|
|
|
12
12
|
validateCoverage,
|
|
13
13
|
validateSchema,
|
|
14
14
|
validateSnippets
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-ZDA3PLQ6.js";
|
|
16
16
|
import {
|
|
17
17
|
scan
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-CAMXG5HJ.js";
|
|
19
19
|
import {
|
|
20
20
|
loadConfig,
|
|
21
21
|
loadFragmentFile
|
|
22
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-566BNPQZ.js";
|
|
23
23
|
import {
|
|
24
24
|
discoverFragmentFiles
|
|
25
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-WXSR2II7.js";
|
|
26
26
|
import {
|
|
27
27
|
FigmaClient,
|
|
28
28
|
StorageManager,
|
|
@@ -38,25 +38,23 @@ import {
|
|
|
38
38
|
renderAllComponentVariants,
|
|
39
39
|
scanCodebase,
|
|
40
40
|
shutdownSharedPool
|
|
41
|
-
} from "./chunk-
|
|
41
|
+
} from "./chunk-D5PYOXEI.js";
|
|
42
|
+
import "./chunk-D2CDBRNU.js";
|
|
42
43
|
import {
|
|
44
|
+
BRAND,
|
|
43
45
|
budgetBar,
|
|
44
46
|
formatBytes,
|
|
45
47
|
generateContext,
|
|
46
48
|
resolvePerformanceConfig
|
|
47
|
-
} from "./chunk-
|
|
48
|
-
import "./chunk-GOVI6COW.js";
|
|
49
|
-
import {
|
|
50
|
-
BRAND
|
|
51
|
-
} from "./chunk-EKLMXTWU.js";
|
|
49
|
+
} from "./chunk-OQO55NKV.js";
|
|
52
50
|
import "./chunk-Z7EY4VHE.js";
|
|
53
51
|
|
|
54
52
|
// src/bin.ts
|
|
55
53
|
import { Command } from "commander";
|
|
56
|
-
import
|
|
54
|
+
import pc24 from "picocolors";
|
|
57
55
|
import { readFileSync } from "fs";
|
|
58
56
|
import { fileURLToPath } from "url";
|
|
59
|
-
import { dirname as
|
|
57
|
+
import { dirname as dirname5, join as join12 } from "path";
|
|
60
58
|
|
|
61
59
|
// src/commands/validate.ts
|
|
62
60
|
import pc from "picocolors";
|
|
@@ -176,9 +174,20 @@ ${BRAND.name} Build
|
|
|
176
174
|
}
|
|
177
175
|
fragmentCount = result.fragmentCount;
|
|
178
176
|
outputPath = result.outputPath;
|
|
179
|
-
|
|
180
|
-
|
|
177
|
+
if (result.fragmentCount === 0 && result.errors.length === 0) {
|
|
178
|
+
console.log(pc2.dim("No compilable fragment files found. Falling back to source scan...\n"));
|
|
179
|
+
const scanResult = await scan({
|
|
180
|
+
config: options.config,
|
|
181
|
+
output: options.output,
|
|
182
|
+
verbose: options.verbose
|
|
183
|
+
});
|
|
184
|
+
fragmentCount = scanResult.componentCount;
|
|
185
|
+
outputPath = scanResult.outputPath;
|
|
186
|
+
} else {
|
|
187
|
+
console.log(pc2.green(`\u2713 Built ${result.fragmentCount} fragment(s)`));
|
|
188
|
+
console.log(pc2.dim(` Output: ${result.outputPath}
|
|
181
189
|
`));
|
|
190
|
+
}
|
|
182
191
|
}
|
|
183
192
|
if (options.registry || options.registryOnly) {
|
|
184
193
|
console.log(pc2.dim("Generating registry and context...\n"));
|
|
@@ -602,6 +611,7 @@ function parseMeta(content, filePath, warnings) {
|
|
|
602
611
|
);
|
|
603
612
|
if (importMatch) {
|
|
604
613
|
result.componentImport = importMatch[1];
|
|
614
|
+
result.isDefaultImport = false;
|
|
605
615
|
} else {
|
|
606
616
|
const defaultImportMatch = content.match(
|
|
607
617
|
new RegExp(
|
|
@@ -610,6 +620,7 @@ function parseMeta(content, filePath, warnings) {
|
|
|
610
620
|
);
|
|
611
621
|
if (defaultImportMatch) {
|
|
612
622
|
result.componentImport = defaultImportMatch[1];
|
|
623
|
+
result.isDefaultImport = true;
|
|
613
624
|
}
|
|
614
625
|
}
|
|
615
626
|
}
|
|
@@ -1199,6 +1210,7 @@ function convertToFragment(parsed) {
|
|
|
1199
1210
|
const code = generateFragmentCode({
|
|
1200
1211
|
componentName,
|
|
1201
1212
|
componentImport: parsed.meta.componentImport,
|
|
1213
|
+
isDefaultImport: parsed.meta.isDefaultImport,
|
|
1202
1214
|
description: parsed.meta.description,
|
|
1203
1215
|
category,
|
|
1204
1216
|
tags: parsed.meta.tags,
|
|
@@ -1434,6 +1446,7 @@ function generateFragmentCode(options) {
|
|
|
1434
1446
|
const {
|
|
1435
1447
|
componentName,
|
|
1436
1448
|
componentImport,
|
|
1449
|
+
isDefaultImport,
|
|
1437
1450
|
description,
|
|
1438
1451
|
category,
|
|
1439
1452
|
tags,
|
|
@@ -1461,8 +1474,9 @@ ${generated.skippedVariants.map((sv) => ` { name: "${escapeString(sv.name)}
|
|
|
1461
1474
|
},
|
|
1462
1475
|
`;
|
|
1463
1476
|
}
|
|
1477
|
+
const componentImportStatement = isDefaultImport ? `import ${componentName} from "${componentImport}";` : `import { ${componentName} } from "${componentImport}";`;
|
|
1464
1478
|
return `import { defineFragment } from "@fragments-sdk/cli/core";
|
|
1465
|
-
|
|
1479
|
+
${componentImportStatement}
|
|
1466
1480
|
|
|
1467
1481
|
export default defineFragment({
|
|
1468
1482
|
component: ${componentName},
|
|
@@ -1717,27 +1731,48 @@ async function runSetup(options = {}) {
|
|
|
1717
1731
|
const sbConfig = await detectStorybookConfig(configDir);
|
|
1718
1732
|
if (sbConfig) {
|
|
1719
1733
|
log(pc6.dim(` Found Storybook at ${sbConfig.configPath}`));
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1734
|
+
const hasStoryPatterns = config.include.some((p) => p.includes(".stories."));
|
|
1735
|
+
if (hasStoryPatterns) {
|
|
1736
|
+
log(pc6.dim(" Stories included in config \u2014 viewer will load them directly\n"));
|
|
1737
|
+
fragmentFiles = await discoverFragmentFiles(config, configDir);
|
|
1738
|
+
if (fragmentFiles.length > 0) {
|
|
1739
|
+
log(pc6.green(` Found ${fragmentFiles.length} story/fragment file(s)`));
|
|
1740
|
+
}
|
|
1741
|
+
} else {
|
|
1742
|
+
log(pc6.dim(" Converting stories to fragments...\n"));
|
|
1743
|
+
const storyFiles = await discoverStoryFiles(configDir, sbConfig.storyPatterns);
|
|
1744
|
+
if (storyFiles.length > 0) {
|
|
1745
|
+
let converted = 0;
|
|
1746
|
+
for (const storyFile of storyFiles) {
|
|
1747
|
+
try {
|
|
1748
|
+
const parsed = await parseStoryFile(storyFile);
|
|
1749
|
+
const fragmentResult = convertToFragment(parsed);
|
|
1750
|
+
await fs2.mkdir(path.dirname(fragmentResult.outputFile), { recursive: true });
|
|
1751
|
+
await fs2.writeFile(fragmentResult.outputFile, fragmentResult.code);
|
|
1752
|
+
converted++;
|
|
1753
|
+
} catch {
|
|
1754
|
+
}
|
|
1732
1755
|
}
|
|
1756
|
+
result.fragmentFilesCreated = converted;
|
|
1757
|
+
log(pc6.green(` Generated ${converted} fragment file(s)`));
|
|
1758
|
+
fragmentFiles = await discoverFragmentFiles(config, configDir);
|
|
1733
1759
|
}
|
|
1734
|
-
result.fragmentFilesCreated = converted;
|
|
1735
|
-
log(pc6.green(` Generated ${converted} fragment file(s)`));
|
|
1736
|
-
fragmentFiles = await discoverFragmentFiles(config, configDir);
|
|
1737
1760
|
}
|
|
1738
1761
|
} else {
|
|
1739
1762
|
log(pc6.dim(" No Storybook config found"));
|
|
1740
|
-
log(pc6.dim(
|
|
1763
|
+
log(pc6.dim(" Auto-scanning source code...\n"));
|
|
1764
|
+
try {
|
|
1765
|
+
const scanResult = await scan({
|
|
1766
|
+
config: options.configPath,
|
|
1767
|
+
verbose: false
|
|
1768
|
+
});
|
|
1769
|
+
if (scanResult.componentCount > 0) {
|
|
1770
|
+
result.fragmentsBuilt = scanResult.componentCount;
|
|
1771
|
+
log(pc6.green(` Scanned ${scanResult.componentCount} component(s) from source`));
|
|
1772
|
+
}
|
|
1773
|
+
} catch {
|
|
1774
|
+
log(pc6.dim(` Run ${pc6.cyan(`${BRAND.cliCommand} scan`)} to generate documentation from source`));
|
|
1775
|
+
}
|
|
1741
1776
|
}
|
|
1742
1777
|
} else if (fragmentFiles.length > 0) {
|
|
1743
1778
|
log(pc6.green(` Found ${fragmentFiles.length} fragment file(s)`));
|
|
@@ -1757,7 +1792,19 @@ ${reason} ${BRAND.outFile}...`));
|
|
|
1757
1792
|
result.errors.push(`${err.file}: ${err.error}`);
|
|
1758
1793
|
}
|
|
1759
1794
|
}
|
|
1760
|
-
|
|
1795
|
+
if (buildResult.fragmentCount > 0) {
|
|
1796
|
+
log(pc6.green(` Built ${buildResult.fragmentCount} fragment(s)`));
|
|
1797
|
+
} else {
|
|
1798
|
+
log(pc6.dim(" No compilable fragments found, falling back to source scan..."));
|
|
1799
|
+
try {
|
|
1800
|
+
const scanResult = await scan({ verbose: false });
|
|
1801
|
+
if (scanResult.componentCount > 0) {
|
|
1802
|
+
result.fragmentsBuilt = scanResult.componentCount;
|
|
1803
|
+
log(pc6.green(` Scanned ${scanResult.componentCount} component(s) from source`));
|
|
1804
|
+
}
|
|
1805
|
+
} catch {
|
|
1806
|
+
}
|
|
1807
|
+
}
|
|
1761
1808
|
} catch (error) {
|
|
1762
1809
|
result.errors.push(`Build failed: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
1763
1810
|
}
|
|
@@ -1811,7 +1858,7 @@ ${BRAND.name} Dev Server
|
|
|
1811
1858
|
}
|
|
1812
1859
|
}
|
|
1813
1860
|
}
|
|
1814
|
-
const { createDevServer } = await import("./viewer-
|
|
1861
|
+
const { createDevServer } = await import("./viewer-DBEPYM3G.js");
|
|
1815
1862
|
console.log(pc7.dim("\nStarting dev server..."));
|
|
1816
1863
|
const parsedPort = typeof port === "string" ? parseInt(port, 10) : port;
|
|
1817
1864
|
try {
|
|
@@ -5738,9 +5785,362 @@ ${BRAND.name} Doctor
|
|
|
5738
5785
|
return result;
|
|
5739
5786
|
}
|
|
5740
5787
|
|
|
5788
|
+
// src/commands/setup.ts
|
|
5789
|
+
import { readFile as readFile9, writeFile as writeFile9, access as access4, mkdir as mkdir7 } from "fs/promises";
|
|
5790
|
+
import { join as join11, resolve as resolve9, dirname as dirname4 } from "path";
|
|
5791
|
+
import pc23 from "picocolors";
|
|
5792
|
+
async function fileExists(path) {
|
|
5793
|
+
try {
|
|
5794
|
+
await access4(path);
|
|
5795
|
+
return true;
|
|
5796
|
+
} catch {
|
|
5797
|
+
return false;
|
|
5798
|
+
}
|
|
5799
|
+
}
|
|
5800
|
+
async function detectFramework(root) {
|
|
5801
|
+
if (await fileExists(join11(root, "app/layout.tsx")) || await fileExists(join11(root, "src/app/layout.tsx"))) {
|
|
5802
|
+
return "nextjs-app";
|
|
5803
|
+
}
|
|
5804
|
+
if (await fileExists(join11(root, "pages/_app.tsx")) || await fileExists(join11(root, "pages/_app.ts"))) {
|
|
5805
|
+
return "nextjs-pages";
|
|
5806
|
+
}
|
|
5807
|
+
if (await fileExists(join11(root, "next.config.ts")) || await fileExists(join11(root, "next.config.js")) || await fileExists(join11(root, "next.config.mjs"))) {
|
|
5808
|
+
return "nextjs-app";
|
|
5809
|
+
}
|
|
5810
|
+
if (await fileExists(join11(root, "vite.config.ts")) || await fileExists(join11(root, "vite.config.js"))) {
|
|
5811
|
+
return "vite";
|
|
5812
|
+
}
|
|
5813
|
+
return "unknown";
|
|
5814
|
+
}
|
|
5815
|
+
async function findEntryFile(root, framework) {
|
|
5816
|
+
const candidates = [];
|
|
5817
|
+
switch (framework) {
|
|
5818
|
+
case "nextjs-app":
|
|
5819
|
+
candidates.push(
|
|
5820
|
+
"src/app/layout.tsx",
|
|
5821
|
+
"app/layout.tsx",
|
|
5822
|
+
"src/app/layout.ts",
|
|
5823
|
+
"app/layout.ts"
|
|
5824
|
+
);
|
|
5825
|
+
break;
|
|
5826
|
+
case "nextjs-pages":
|
|
5827
|
+
candidates.push("pages/_app.tsx", "pages/_app.ts");
|
|
5828
|
+
break;
|
|
5829
|
+
case "vite":
|
|
5830
|
+
candidates.push(
|
|
5831
|
+
"src/main.tsx",
|
|
5832
|
+
"src/main.ts",
|
|
5833
|
+
"src/index.tsx",
|
|
5834
|
+
"src/index.ts"
|
|
5835
|
+
);
|
|
5836
|
+
break;
|
|
5837
|
+
default:
|
|
5838
|
+
candidates.push(
|
|
5839
|
+
"src/main.tsx",
|
|
5840
|
+
"src/main.ts",
|
|
5841
|
+
"src/index.tsx",
|
|
5842
|
+
"src/index.ts",
|
|
5843
|
+
"src/App.tsx",
|
|
5844
|
+
"src/App.ts"
|
|
5845
|
+
);
|
|
5846
|
+
}
|
|
5847
|
+
for (const candidate of candidates) {
|
|
5848
|
+
if (await fileExists(join11(root, candidate))) {
|
|
5849
|
+
return candidate;
|
|
5850
|
+
}
|
|
5851
|
+
}
|
|
5852
|
+
return null;
|
|
5853
|
+
}
|
|
5854
|
+
async function findNextConfig(root) {
|
|
5855
|
+
const candidates = ["next.config.ts", "next.config.mjs", "next.config.js"];
|
|
5856
|
+
for (const candidate of candidates) {
|
|
5857
|
+
if (await fileExists(join11(root, candidate))) {
|
|
5858
|
+
return candidate;
|
|
5859
|
+
}
|
|
5860
|
+
}
|
|
5861
|
+
return null;
|
|
5862
|
+
}
|
|
5863
|
+
async function addStylesImport(root, entryFile) {
|
|
5864
|
+
const fullPath = join11(root, entryFile);
|
|
5865
|
+
const content = await readFile9(fullPath, "utf-8");
|
|
5866
|
+
if (content.includes("@fragments-sdk/ui/styles")) {
|
|
5867
|
+
return { modified: false, message: `Styles already imported in ${entryFile}` };
|
|
5868
|
+
}
|
|
5869
|
+
const stylesImport = "import '@fragments-sdk/ui/styles';";
|
|
5870
|
+
let newContent;
|
|
5871
|
+
if (content.startsWith("'use client'") || content.startsWith('"use client"')) {
|
|
5872
|
+
const directiveEnd = content.indexOf("\n") + 1;
|
|
5873
|
+
newContent = content.slice(0, directiveEnd) + stylesImport + "\n" + content.slice(directiveEnd);
|
|
5874
|
+
} else {
|
|
5875
|
+
newContent = stylesImport + "\n" + content;
|
|
5876
|
+
}
|
|
5877
|
+
await writeFile9(fullPath, newContent, "utf-8");
|
|
5878
|
+
return { modified: true, message: `Added styles import to ${entryFile}` };
|
|
5879
|
+
}
|
|
5880
|
+
async function addThemeProvider(root, entryFile, framework) {
|
|
5881
|
+
const fullPath = join11(root, entryFile);
|
|
5882
|
+
const content = await readFile9(fullPath, "utf-8");
|
|
5883
|
+
if (content.includes("ThemeProvider")) {
|
|
5884
|
+
return { modified: false, message: `ThemeProvider already present in ${entryFile}` };
|
|
5885
|
+
}
|
|
5886
|
+
if (framework === "nextjs-app") {
|
|
5887
|
+
const providerImport = "import { ThemeProvider, TooltipProvider, ToastProvider } from '@fragments-sdk/ui';";
|
|
5888
|
+
let newContent = content;
|
|
5889
|
+
const importLines = content.split("\n");
|
|
5890
|
+
let lastImportIdx = -1;
|
|
5891
|
+
for (let i = 0; i < importLines.length; i++) {
|
|
5892
|
+
if (importLines[i].startsWith("import ") || importLines[i].startsWith("import '") || importLines[i].startsWith('import "')) {
|
|
5893
|
+
lastImportIdx = i;
|
|
5894
|
+
}
|
|
5895
|
+
}
|
|
5896
|
+
if (lastImportIdx >= 0) {
|
|
5897
|
+
importLines.splice(lastImportIdx + 1, 0, providerImport);
|
|
5898
|
+
newContent = importLines.join("\n");
|
|
5899
|
+
} else {
|
|
5900
|
+
newContent = providerImport + "\n" + content;
|
|
5901
|
+
}
|
|
5902
|
+
if (!content.includes("suppressHydrationWarning")) {
|
|
5903
|
+
await writeFile9(fullPath, newContent, "utf-8");
|
|
5904
|
+
return {
|
|
5905
|
+
modified: true,
|
|
5906
|
+
message: `Added provider imports to ${entryFile}. Wrap your {children} with:
|
|
5907
|
+
<ThemeProvider defaultMode="system"><TooltipProvider><ToastProvider>{children}</ToastProvider></TooltipProvider></ThemeProvider>
|
|
5908
|
+
Add suppressHydrationWarning to your <html> tag`
|
|
5909
|
+
};
|
|
5910
|
+
}
|
|
5911
|
+
await writeFile9(fullPath, newContent, "utf-8");
|
|
5912
|
+
return { modified: true, message: `Added provider imports to ${entryFile}. Wrap {children} with ThemeProvider.` };
|
|
5913
|
+
}
|
|
5914
|
+
return { modified: false, message: "Manual ThemeProvider setup needed \u2014 see https://usefragments.com/getting-started#provider-setup" };
|
|
5915
|
+
}
|
|
5916
|
+
async function addTranspilePackages(root) {
|
|
5917
|
+
const configFile = await findNextConfig(root);
|
|
5918
|
+
if (!configFile) {
|
|
5919
|
+
return { modified: false, message: "No next.config found" };
|
|
5920
|
+
}
|
|
5921
|
+
const fullPath = join11(root, configFile);
|
|
5922
|
+
const content = await readFile9(fullPath, "utf-8");
|
|
5923
|
+
if (content.includes("transpilePackages") && content.includes("@fragments-sdk/ui")) {
|
|
5924
|
+
return { modified: false, message: `transpilePackages already configured in ${configFile}` };
|
|
5925
|
+
}
|
|
5926
|
+
if (content.includes("transpilePackages")) {
|
|
5927
|
+
return {
|
|
5928
|
+
modified: false,
|
|
5929
|
+
message: `transpilePackages found in ${configFile} but missing '@fragments-sdk/ui'. Please add it manually.`
|
|
5930
|
+
};
|
|
5931
|
+
}
|
|
5932
|
+
const patterns = [
|
|
5933
|
+
// const nextConfig = { ... }
|
|
5934
|
+
{ search: /const\s+\w+\s*=\s*\{/, replacement: (match) => `${match}
|
|
5935
|
+
transpilePackages: ['@fragments-sdk/ui'],` },
|
|
5936
|
+
// module.exports = { ... }
|
|
5937
|
+
{ search: /module\.exports\s*=\s*\{/, replacement: (match) => `${match}
|
|
5938
|
+
transpilePackages: ['@fragments-sdk/ui'],` },
|
|
5939
|
+
// export default { ... }
|
|
5940
|
+
{ search: /export\s+default\s*\{/, replacement: (match) => `${match}
|
|
5941
|
+
transpilePackages: ['@fragments-sdk/ui'],` }
|
|
5942
|
+
];
|
|
5943
|
+
for (const pattern of patterns) {
|
|
5944
|
+
if (pattern.search.test(content)) {
|
|
5945
|
+
const newContent = content.replace(pattern.search, pattern.replacement);
|
|
5946
|
+
await writeFile9(fullPath, newContent, "utf-8");
|
|
5947
|
+
return { modified: true, message: `Added transpilePackages to ${configFile}` };
|
|
5948
|
+
}
|
|
5949
|
+
}
|
|
5950
|
+
return {
|
|
5951
|
+
modified: false,
|
|
5952
|
+
message: `Could not auto-modify ${configFile}. Add transpilePackages: ['@fragments-sdk/ui'] manually.`
|
|
5953
|
+
};
|
|
5954
|
+
}
|
|
5955
|
+
async function createScssSeeds(root, brand) {
|
|
5956
|
+
const scssLocations = [
|
|
5957
|
+
"src/app/globals.scss",
|
|
5958
|
+
"app/globals.scss",
|
|
5959
|
+
"src/styles/globals.scss",
|
|
5960
|
+
"src/globals.scss",
|
|
5961
|
+
"styles/globals.scss"
|
|
5962
|
+
];
|
|
5963
|
+
for (const loc of scssLocations) {
|
|
5964
|
+
const fullPath2 = join11(root, loc);
|
|
5965
|
+
if (await fileExists(fullPath2)) {
|
|
5966
|
+
const content = await readFile9(fullPath2, "utf-8");
|
|
5967
|
+
if (content.includes("@fragments-sdk/ui/styles")) {
|
|
5968
|
+
return { modified: false, message: `SCSS seeds already configured in ${loc}` };
|
|
5969
|
+
}
|
|
5970
|
+
const seedContent = generateScssSeedImport(brand);
|
|
5971
|
+
const newContent = seedContent + "\n" + content;
|
|
5972
|
+
await writeFile9(fullPath2, newContent, "utf-8");
|
|
5973
|
+
return { modified: true, message: `Added SCSS seed import to ${loc}` };
|
|
5974
|
+
}
|
|
5975
|
+
}
|
|
5976
|
+
const targetDir = await fileExists(join11(root, "src/app")) ? "src/app" : await fileExists(join11(root, "src")) ? "src/styles" : "styles";
|
|
5977
|
+
const targetPath = join11(targetDir, "globals.scss");
|
|
5978
|
+
const fullPath = join11(root, targetPath);
|
|
5979
|
+
await mkdir7(dirname4(fullPath), { recursive: true });
|
|
5980
|
+
await writeFile9(fullPath, generateScssSeedImport(brand), "utf-8");
|
|
5981
|
+
return { modified: true, message: `Created ${targetPath} with SCSS seed configuration` };
|
|
5982
|
+
}
|
|
5983
|
+
async function setupMcpConfig(root) {
|
|
5984
|
+
const mcpConfigPaths = [
|
|
5985
|
+
".cursor/mcp.json",
|
|
5986
|
+
".vscode/mcp.json"
|
|
5987
|
+
];
|
|
5988
|
+
for (const configPath of mcpConfigPaths) {
|
|
5989
|
+
const fullPath = join11(root, configPath);
|
|
5990
|
+
if (await fileExists(fullPath)) {
|
|
5991
|
+
try {
|
|
5992
|
+
const content = await readFile9(fullPath, "utf-8");
|
|
5993
|
+
const config = JSON.parse(content);
|
|
5994
|
+
const servers = config.mcpServers || {};
|
|
5995
|
+
const hasFragments = Object.values(servers).some((server) => {
|
|
5996
|
+
const s = server;
|
|
5997
|
+
return s.args?.some((arg) => arg.includes("@fragments-sdk/mcp"));
|
|
5998
|
+
});
|
|
5999
|
+
if (hasFragments) {
|
|
6000
|
+
return { modified: false, message: `MCP server already configured in ${configPath}` };
|
|
6001
|
+
}
|
|
6002
|
+
servers.fragments = {
|
|
6003
|
+
command: "npx",
|
|
6004
|
+
args: ["@fragments-sdk/mcp"]
|
|
6005
|
+
};
|
|
6006
|
+
config.mcpServers = servers;
|
|
6007
|
+
await writeFile9(fullPath, JSON.stringify(config, null, 2) + "\n", "utf-8");
|
|
6008
|
+
return { modified: true, message: `Added Fragments MCP server to ${configPath}` };
|
|
6009
|
+
} catch {
|
|
6010
|
+
return { modified: false, message: `Could not parse ${configPath}` };
|
|
6011
|
+
}
|
|
6012
|
+
}
|
|
6013
|
+
}
|
|
6014
|
+
const cursorDir = join11(root, ".cursor");
|
|
6015
|
+
const cursorMcpPath = join11(cursorDir, "mcp.json");
|
|
6016
|
+
await mkdir7(cursorDir, { recursive: true });
|
|
6017
|
+
const mcpConfig = {
|
|
6018
|
+
mcpServers: {
|
|
6019
|
+
fragments: {
|
|
6020
|
+
command: "npx",
|
|
6021
|
+
args: ["@fragments-sdk/mcp"]
|
|
6022
|
+
}
|
|
6023
|
+
}
|
|
6024
|
+
};
|
|
6025
|
+
await writeFile9(cursorMcpPath, JSON.stringify(mcpConfig, null, 2) + "\n", "utf-8");
|
|
6026
|
+
return { modified: true, message: "Created .cursor/mcp.json with Fragments MCP server" };
|
|
6027
|
+
}
|
|
6028
|
+
function generateScssSeedImport(brand) {
|
|
6029
|
+
const brandColor = brand || "#0066ff";
|
|
6030
|
+
return `@use '@fragments-sdk/ui/styles' with (
|
|
6031
|
+
$fui-brand: ${brandColor},
|
|
6032
|
+
$fui-neutral: "stone",
|
|
6033
|
+
$fui-density: "default",
|
|
6034
|
+
$fui-radius-style: "rounded"
|
|
6035
|
+
);
|
|
6036
|
+
`;
|
|
6037
|
+
}
|
|
6038
|
+
async function setup(options = {}) {
|
|
6039
|
+
const root = resolve9(options.root ?? process.cwd());
|
|
6040
|
+
const actions = [];
|
|
6041
|
+
const errors = [];
|
|
6042
|
+
console.log(pc23.cyan(`
|
|
6043
|
+
${BRAND.name} Setup
|
|
6044
|
+
`));
|
|
6045
|
+
const framework = await detectFramework(root);
|
|
6046
|
+
const frameworkLabel = framework === "nextjs-app" ? "Next.js (App Router)" : framework === "nextjs-pages" ? "Next.js (Pages Router)" : framework === "vite" ? "Vite" : "Unknown";
|
|
6047
|
+
console.log(` ${pc23.dim("Framework:")} ${frameworkLabel}`);
|
|
6048
|
+
const entryFile = await findEntryFile(root, framework);
|
|
6049
|
+
if (entryFile) {
|
|
6050
|
+
console.log(` ${pc23.dim("Entry:")} ${entryFile}`);
|
|
6051
|
+
} else {
|
|
6052
|
+
console.log(` ${pc23.yellow("!")} Could not detect entry file`);
|
|
6053
|
+
}
|
|
6054
|
+
console.log();
|
|
6055
|
+
if (entryFile) {
|
|
6056
|
+
try {
|
|
6057
|
+
const result = await addStylesImport(root, entryFile);
|
|
6058
|
+
const icon = result.modified ? pc23.green("+") : pc23.dim("\xB7");
|
|
6059
|
+
console.log(` ${icon} ${result.message}`);
|
|
6060
|
+
if (result.modified) actions.push(result.message);
|
|
6061
|
+
} catch (error) {
|
|
6062
|
+
const msg = `Failed to add styles import: ${error instanceof Error ? error.message : error}`;
|
|
6063
|
+
console.log(` ${pc23.red("\u2717")} ${msg}`);
|
|
6064
|
+
errors.push(msg);
|
|
6065
|
+
}
|
|
6066
|
+
}
|
|
6067
|
+
if (entryFile) {
|
|
6068
|
+
try {
|
|
6069
|
+
const result = await addThemeProvider(root, entryFile, framework);
|
|
6070
|
+
const icon = result.modified ? pc23.green("+") : pc23.dim("\xB7");
|
|
6071
|
+
console.log(` ${icon} ${result.message}`);
|
|
6072
|
+
if (result.modified) actions.push(result.message);
|
|
6073
|
+
} catch (error) {
|
|
6074
|
+
const msg = `Failed to add ThemeProvider: ${error instanceof Error ? error.message : error}`;
|
|
6075
|
+
console.log(` ${pc23.red("\u2717")} ${msg}`);
|
|
6076
|
+
errors.push(msg);
|
|
6077
|
+
}
|
|
6078
|
+
}
|
|
6079
|
+
if (framework === "nextjs-app" || framework === "nextjs-pages") {
|
|
6080
|
+
try {
|
|
6081
|
+
const result = await addTranspilePackages(root);
|
|
6082
|
+
const icon = result.modified ? pc23.green("+") : pc23.dim("\xB7");
|
|
6083
|
+
console.log(` ${icon} ${result.message}`);
|
|
6084
|
+
if (result.modified) actions.push(result.message);
|
|
6085
|
+
} catch (error) {
|
|
6086
|
+
const msg = `Failed to update next.config: ${error instanceof Error ? error.message : error}`;
|
|
6087
|
+
console.log(` ${pc23.red("\u2717")} ${msg}`);
|
|
6088
|
+
errors.push(msg);
|
|
6089
|
+
}
|
|
6090
|
+
}
|
|
6091
|
+
if (options.scss || options.brand) {
|
|
6092
|
+
try {
|
|
6093
|
+
const result = await createScssSeeds(root, options.brand);
|
|
6094
|
+
const icon = result.modified ? pc23.green("+") : pc23.dim("\xB7");
|
|
6095
|
+
console.log(` ${icon} ${result.message}`);
|
|
6096
|
+
if (result.modified) actions.push(result.message);
|
|
6097
|
+
} catch (error) {
|
|
6098
|
+
const msg = `Failed to create SCSS seeds: ${error instanceof Error ? error.message : error}`;
|
|
6099
|
+
console.log(` ${pc23.red("\u2717")} ${msg}`);
|
|
6100
|
+
errors.push(msg);
|
|
6101
|
+
}
|
|
6102
|
+
}
|
|
6103
|
+
if (options.mcp) {
|
|
6104
|
+
try {
|
|
6105
|
+
const result = await setupMcpConfig(root);
|
|
6106
|
+
const icon = result.modified ? pc23.green("+") : pc23.dim("\xB7");
|
|
6107
|
+
console.log(` ${icon} ${result.message}`);
|
|
6108
|
+
if (result.modified) actions.push(result.message);
|
|
6109
|
+
} catch (error) {
|
|
6110
|
+
const msg = `Failed to configure MCP: ${error instanceof Error ? error.message : error}`;
|
|
6111
|
+
console.log(` ${pc23.red("\u2717")} ${msg}`);
|
|
6112
|
+
errors.push(msg);
|
|
6113
|
+
}
|
|
6114
|
+
}
|
|
6115
|
+
console.log();
|
|
6116
|
+
if (errors.length > 0) {
|
|
6117
|
+
console.log(pc23.red(` ${errors.length} error(s) occurred during setup`));
|
|
6118
|
+
} else if (actions.length > 0) {
|
|
6119
|
+
console.log(pc23.green(` \u2713 Setup complete \u2014 ${actions.length} file(s) modified`));
|
|
6120
|
+
} else {
|
|
6121
|
+
console.log(pc23.green(" \u2713 Already configured \u2014 no changes needed"));
|
|
6122
|
+
}
|
|
6123
|
+
console.log();
|
|
6124
|
+
console.log(pc23.dim(" Next steps:"));
|
|
6125
|
+
if (!options.scss && !options.brand) {
|
|
6126
|
+
console.log(pc23.dim(" \u2022 Run with --scss to add build-time theme seeds"));
|
|
6127
|
+
}
|
|
6128
|
+
if (!options.mcp) {
|
|
6129
|
+
console.log(pc23.dim(" \u2022 Run with --mcp to configure AI tooling (MCP server)"));
|
|
6130
|
+
}
|
|
6131
|
+
console.log(pc23.dim(" \u2022 Run `fragments doctor` to verify your setup"));
|
|
6132
|
+
console.log(pc23.dim(" \u2022 Visit https://usefragments.com/getting-started"));
|
|
6133
|
+
console.log();
|
|
6134
|
+
return {
|
|
6135
|
+
success: errors.length === 0,
|
|
6136
|
+
actions,
|
|
6137
|
+
errors
|
|
6138
|
+
};
|
|
6139
|
+
}
|
|
6140
|
+
|
|
5741
6141
|
// src/bin.ts
|
|
5742
|
-
var __dirname =
|
|
5743
|
-
var pkg = JSON.parse(readFileSync(
|
|
6142
|
+
var __dirname = dirname5(fileURLToPath(import.meta.url));
|
|
6143
|
+
var pkg = JSON.parse(readFileSync(join12(__dirname, "../package.json"), "utf-8"));
|
|
5744
6144
|
var program = new Command();
|
|
5745
6145
|
program.name(BRAND.cliCommand).description(`${BRAND.name} - Design system documentation and compliance tool`).version(pkg.version);
|
|
5746
6146
|
program.command("validate").description("Validate fragment files").option("-c, --config <path>", "Path to config file").option("--schema", "Validate fragment schema only").option("--coverage", "Validate coverage only").option("--snippets", "Validate snippet/render policy only").option("--snippet-mode <mode>", "Override snippet policy mode (warn|error)").option("--component-start <name>", "Start component name for alphabetical snippet batch validation").option("--component-limit <n>", "Component count for alphabetical snippet batch validation", (value) => Number.parseInt(value, 10)).action(async (options) => {
|
|
@@ -5750,7 +6150,7 @@ program.command("validate").description("Validate fragment files").option("-c, -
|
|
|
5750
6150
|
process.exit(1);
|
|
5751
6151
|
}
|
|
5752
6152
|
} catch (error) {
|
|
5753
|
-
console.error(
|
|
6153
|
+
console.error(pc24.red("Error:"), error instanceof Error ? error.message : error);
|
|
5754
6154
|
process.exit(1);
|
|
5755
6155
|
}
|
|
5756
6156
|
});
|
|
@@ -5770,7 +6170,7 @@ program.command("build").description(`Build compiled ${BRAND.outFile} and ${BRAN
|
|
|
5770
6170
|
process.exit(1);
|
|
5771
6171
|
}
|
|
5772
6172
|
} catch (error) {
|
|
5773
|
-
console.error(
|
|
6173
|
+
console.error(pc24.red("Error:"), error instanceof Error ? error.message : error);
|
|
5774
6174
|
process.exit(1);
|
|
5775
6175
|
}
|
|
5776
6176
|
});
|
|
@@ -5789,7 +6189,7 @@ program.command("context").description("Generate AI-ready context for your desig
|
|
|
5789
6189
|
process.exit(1);
|
|
5790
6190
|
}
|
|
5791
6191
|
} catch (error) {
|
|
5792
|
-
console.error(
|
|
6192
|
+
console.error(pc24.red("Error:"), error instanceof Error ? error.message : error);
|
|
5793
6193
|
process.exit(1);
|
|
5794
6194
|
}
|
|
5795
6195
|
});
|
|
@@ -5816,7 +6216,7 @@ program.command("ai").description("Generate context optimized for AI assistants
|
|
|
5816
6216
|
}
|
|
5817
6217
|
}
|
|
5818
6218
|
} catch (error) {
|
|
5819
|
-
console.error(
|
|
6219
|
+
console.error(pc24.red("Error:"), error instanceof Error ? error.message : error);
|
|
5820
6220
|
process.exit(1);
|
|
5821
6221
|
}
|
|
5822
6222
|
});
|
|
@@ -5824,7 +6224,7 @@ program.command("list").description("List all discovered fragment files").option
|
|
|
5824
6224
|
try {
|
|
5825
6225
|
await list(options);
|
|
5826
6226
|
} catch (error) {
|
|
5827
|
-
console.error(
|
|
6227
|
+
console.error(pc24.red("Error:"), error instanceof Error ? error.message : error);
|
|
5828
6228
|
process.exit(1);
|
|
5829
6229
|
}
|
|
5830
6230
|
});
|
|
@@ -5832,7 +6232,7 @@ program.command("reset").description("Reset to initial state (delete all generat
|
|
|
5832
6232
|
try {
|
|
5833
6233
|
await reset(options);
|
|
5834
6234
|
} catch (error) {
|
|
5835
|
-
console.error(
|
|
6235
|
+
console.error(pc24.red("Error:"), error instanceof Error ? error.message : error);
|
|
5836
6236
|
process.exit(1);
|
|
5837
6237
|
}
|
|
5838
6238
|
});
|
|
@@ -5846,7 +6246,7 @@ linkCommand.command("figma").argument("[figma-url]", "Figma file URL to link com
|
|
|
5846
6246
|
variants: options.variants
|
|
5847
6247
|
});
|
|
5848
6248
|
} catch (error) {
|
|
5849
|
-
console.error(
|
|
6249
|
+
console.error(pc24.red("Error:"), error instanceof Error ? error.message : error);
|
|
5850
6250
|
process.exit(1);
|
|
5851
6251
|
}
|
|
5852
6252
|
});
|
|
@@ -5861,7 +6261,7 @@ linkCommand.command("storybook").description("Bootstrap fragments from existing
|
|
|
5861
6261
|
exclude: options.exclude
|
|
5862
6262
|
});
|
|
5863
6263
|
} catch (error) {
|
|
5864
|
-
console.error(
|
|
6264
|
+
console.error(pc24.red("Error:"), error instanceof Error ? error.message : error);
|
|
5865
6265
|
process.exit(1);
|
|
5866
6266
|
}
|
|
5867
6267
|
});
|
|
@@ -5876,9 +6276,9 @@ program.command("dev").description("Start the development server with live compo
|
|
|
5876
6276
|
skipBuild: options.skipBuild
|
|
5877
6277
|
});
|
|
5878
6278
|
} catch (error) {
|
|
5879
|
-
console.error(
|
|
6279
|
+
console.error(pc24.red("Error:"), error instanceof Error ? error.message : error);
|
|
5880
6280
|
if (error instanceof Error && error.stack) {
|
|
5881
|
-
console.error(
|
|
6281
|
+
console.error(pc24.dim(error.stack));
|
|
5882
6282
|
}
|
|
5883
6283
|
process.exit(1);
|
|
5884
6284
|
}
|
|
@@ -5899,7 +6299,7 @@ program.command("screenshot").description("Capture screenshots of component vari
|
|
|
5899
6299
|
process.exit(1);
|
|
5900
6300
|
}
|
|
5901
6301
|
} catch (error) {
|
|
5902
|
-
console.error(
|
|
6302
|
+
console.error(pc24.red("Error:"), error instanceof Error ? error.message : error);
|
|
5903
6303
|
process.exit(1);
|
|
5904
6304
|
}
|
|
5905
6305
|
});
|
|
@@ -5918,7 +6318,7 @@ program.command("diff").argument("[component]", "Component name to diff (optiona
|
|
|
5918
6318
|
process.exit(1);
|
|
5919
6319
|
}
|
|
5920
6320
|
} catch (error) {
|
|
5921
|
-
console.error(
|
|
6321
|
+
console.error(pc24.red("Error:"), error instanceof Error ? error.message : error);
|
|
5922
6322
|
process.exit(1);
|
|
5923
6323
|
}
|
|
5924
6324
|
});
|
|
@@ -5937,8 +6337,8 @@ program.command("compare").argument("[component]", "Component name to compare").
|
|
|
5937
6337
|
process.exit(1);
|
|
5938
6338
|
}
|
|
5939
6339
|
} catch (error) {
|
|
5940
|
-
console.error(
|
|
5941
|
-
console.log(
|
|
6340
|
+
console.error(pc24.red("Error:"), error instanceof Error ? error.message : error);
|
|
6341
|
+
console.log(pc24.dim(`
|
|
5942
6342
|
Make sure the dev server is running: ${BRAND.cliCommand} dev`));
|
|
5943
6343
|
process.exit(1);
|
|
5944
6344
|
}
|
|
@@ -5957,7 +6357,7 @@ program.command("analyze").description("Analyze design system and generate repor
|
|
|
5957
6357
|
process.exit(1);
|
|
5958
6358
|
}
|
|
5959
6359
|
} catch (error) {
|
|
5960
|
-
console.error(
|
|
6360
|
+
console.error(pc24.red("Error:"), error instanceof Error ? error.message : error);
|
|
5961
6361
|
process.exit(1);
|
|
5962
6362
|
}
|
|
5963
6363
|
});
|
|
@@ -5976,7 +6376,7 @@ program.command("verify").argument("[component]", "Component name to verify (opt
|
|
|
5976
6376
|
if (options.ci) {
|
|
5977
6377
|
console.log(JSON.stringify({ error: error instanceof Error ? error.message : "Verification failed" }));
|
|
5978
6378
|
} else {
|
|
5979
|
-
console.error(
|
|
6379
|
+
console.error(pc24.red("Error:"), error instanceof Error ? error.message : error);
|
|
5980
6380
|
}
|
|
5981
6381
|
process.exit(1);
|
|
5982
6382
|
}
|
|
@@ -5993,7 +6393,7 @@ program.command("audit").description("Scan all fragments and show compliance met
|
|
|
5993
6393
|
if (options.json) {
|
|
5994
6394
|
console.log(JSON.stringify({ error: error instanceof Error ? error.message : "Audit failed" }));
|
|
5995
6395
|
} else {
|
|
5996
|
-
console.error(
|
|
6396
|
+
console.error(pc24.red("Error:"), error instanceof Error ? error.message : error);
|
|
5997
6397
|
}
|
|
5998
6398
|
process.exit(1);
|
|
5999
6399
|
}
|
|
@@ -6015,7 +6415,7 @@ program.command("a11y").description("Run accessibility checks on all component v
|
|
|
6015
6415
|
if (options.json) {
|
|
6016
6416
|
console.log(JSON.stringify({ error: error instanceof Error ? error.message : "A11y check failed" }));
|
|
6017
6417
|
} else {
|
|
6018
|
-
console.error(
|
|
6418
|
+
console.error(pc24.red("Error:"), error instanceof Error ? error.message : error);
|
|
6019
6419
|
}
|
|
6020
6420
|
process.exit(1);
|
|
6021
6421
|
}
|
|
@@ -6038,7 +6438,7 @@ program.command("enhance").description("AI-powered documentation generation from
|
|
|
6038
6438
|
if (options.format === "json") {
|
|
6039
6439
|
console.log(JSON.stringify({ success: false, error: error instanceof Error ? error.message : "Enhance failed" }));
|
|
6040
6440
|
} else {
|
|
6041
|
-
console.error(
|
|
6441
|
+
console.error(pc24.red("Error:"), error instanceof Error ? error.message : error);
|
|
6042
6442
|
}
|
|
6043
6443
|
process.exit(1);
|
|
6044
6444
|
}
|
|
@@ -6059,7 +6459,7 @@ program.command("scan").description(`Zero-config ${BRAND.outFile} generation fro
|
|
|
6059
6459
|
process.exit(1);
|
|
6060
6460
|
}
|
|
6061
6461
|
} catch (error) {
|
|
6062
|
-
console.error(
|
|
6462
|
+
console.error(pc24.red("Error:"), error instanceof Error ? error.message : error);
|
|
6063
6463
|
process.exit(1);
|
|
6064
6464
|
}
|
|
6065
6465
|
});
|
|
@@ -6072,7 +6472,7 @@ program.command("storygen").description("Generate Storybook stories from fragmen
|
|
|
6072
6472
|
format: options.format
|
|
6073
6473
|
});
|
|
6074
6474
|
} catch (error) {
|
|
6075
|
-
console.error(
|
|
6475
|
+
console.error(pc24.red("Error:"), error instanceof Error ? error.message : error);
|
|
6076
6476
|
process.exit(1);
|
|
6077
6477
|
}
|
|
6078
6478
|
});
|
|
@@ -6084,7 +6484,7 @@ program.command("metrics").argument("[component]", "Component name (optional, sh
|
|
|
6084
6484
|
json: options.json
|
|
6085
6485
|
});
|
|
6086
6486
|
} catch (error) {
|
|
6087
|
-
console.error(
|
|
6487
|
+
console.error(pc24.red("Error:"), error instanceof Error ? error.message : error);
|
|
6088
6488
|
process.exit(1);
|
|
6089
6489
|
}
|
|
6090
6490
|
});
|
|
@@ -6098,9 +6498,9 @@ program.command("baseline").description("Manage visual regression baselines").ar
|
|
|
6098
6498
|
port: options.port
|
|
6099
6499
|
});
|
|
6100
6500
|
} catch (error) {
|
|
6101
|
-
console.error(
|
|
6501
|
+
console.error(pc24.red("Error:"), error instanceof Error ? error.message : error);
|
|
6102
6502
|
if (action === "update") {
|
|
6103
|
-
console.log(
|
|
6503
|
+
console.log(pc24.dim(`
|
|
6104
6504
|
Make sure the dev server is running: ${BRAND.cliCommand} dev`));
|
|
6105
6505
|
}
|
|
6106
6506
|
process.exit(1);
|
|
@@ -6108,27 +6508,27 @@ Make sure the dev server is running: ${BRAND.cliCommand} dev`));
|
|
|
6108
6508
|
});
|
|
6109
6509
|
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) => {
|
|
6110
6510
|
try {
|
|
6111
|
-
const { generateViewerFromJson } = await import("./static-viewer-
|
|
6511
|
+
const { generateViewerFromJson } = await import("./static-viewer-NUBFPKWH.js");
|
|
6112
6512
|
const fs2 = await import("fs/promises");
|
|
6113
6513
|
const path = await import("path");
|
|
6114
6514
|
const inputPath = path.resolve(process.cwd(), options.input);
|
|
6115
6515
|
const outputPath = path.resolve(process.cwd(), options.output);
|
|
6116
|
-
console.log(
|
|
6516
|
+
console.log(pc24.cyan(`
|
|
6117
6517
|
${BRAND.name} Viewer Generator
|
|
6118
6518
|
`));
|
|
6119
6519
|
try {
|
|
6120
6520
|
await fs2.access(inputPath);
|
|
6121
6521
|
} catch {
|
|
6122
|
-
console.log(
|
|
6123
|
-
console.log(
|
|
6124
|
-
Run ${
|
|
6522
|
+
console.log(pc24.red(`Error: ${options.input} not found.`));
|
|
6523
|
+
console.log(pc24.dim(`
|
|
6524
|
+
Run ${pc24.cyan(`${BRAND.cliCommand} build`)} first to generate ${BRAND.outFile}
|
|
6125
6525
|
`));
|
|
6126
6526
|
process.exit(1);
|
|
6127
6527
|
}
|
|
6128
|
-
console.log(
|
|
6528
|
+
console.log(pc24.dim(`Reading: ${options.input}`));
|
|
6129
6529
|
const html = await generateViewerFromJson(inputPath);
|
|
6130
6530
|
await fs2.writeFile(outputPath, html);
|
|
6131
|
-
console.log(
|
|
6531
|
+
console.log(pc24.green(`
|
|
6132
6532
|
\u2713 Generated: ${options.output}
|
|
6133
6533
|
`));
|
|
6134
6534
|
if (options.open) {
|
|
@@ -6137,7 +6537,7 @@ Run ${pc23.cyan(`${BRAND.cliCommand} build`)} first to generate ${BRAND.outFile}
|
|
|
6137
6537
|
exec(`${openCmd} "${outputPath}"`);
|
|
6138
6538
|
}
|
|
6139
6539
|
} catch (error) {
|
|
6140
|
-
console.error(
|
|
6540
|
+
console.error(pc24.red("Error:"), error instanceof Error ? error.message : error);
|
|
6141
6541
|
process.exit(1);
|
|
6142
6542
|
}
|
|
6143
6543
|
});
|
|
@@ -6150,33 +6550,51 @@ program.command("add").argument("[name]", 'Component name (e.g., "Button", "Text
|
|
|
6150
6550
|
component: options.component
|
|
6151
6551
|
});
|
|
6152
6552
|
} catch (error) {
|
|
6153
|
-
console.error(
|
|
6553
|
+
console.error(pc24.red("Error:"), error instanceof Error ? error.message : error);
|
|
6554
|
+
process.exit(1);
|
|
6555
|
+
}
|
|
6556
|
+
});
|
|
6557
|
+
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) => {
|
|
6558
|
+
try {
|
|
6559
|
+
const result = await setup({
|
|
6560
|
+
root: options.root,
|
|
6561
|
+
yes: options.yes,
|
|
6562
|
+
brand: options.brand,
|
|
6563
|
+
scss: options.scss,
|
|
6564
|
+
mcp: options.mcp
|
|
6565
|
+
});
|
|
6566
|
+
if (!result.success) {
|
|
6567
|
+
process.exit(1);
|
|
6568
|
+
}
|
|
6569
|
+
} catch (error) {
|
|
6570
|
+
console.error(pc24.red("Error:"), error instanceof Error ? error.message : error);
|
|
6154
6571
|
process.exit(1);
|
|
6155
6572
|
}
|
|
6156
6573
|
});
|
|
6157
|
-
program.command("init").description("Initialize fragments in a project (interactive by default)").option("--force", "Overwrite existing config").option("-y, --yes", "Non-interactive mode - auto-detect and use defaults").action(async (options) => {
|
|
6574
|
+
program.command("init").description("Initialize fragments in a project (interactive by default)").option("--force", "Overwrite existing config").option("-y, --yes", "Non-interactive mode - auto-detect and use defaults").option("--scan <path>", "Scan a TypeScript component directory and generate fragment files").action(async (options) => {
|
|
6158
6575
|
try {
|
|
6159
|
-
const { init } = await import("./init-
|
|
6576
|
+
const { init } = await import("./init-Q53R5Q2T.js");
|
|
6160
6577
|
const result = await init({
|
|
6161
6578
|
projectRoot: process.cwd(),
|
|
6162
6579
|
force: options.force,
|
|
6163
|
-
yes: options.yes
|
|
6580
|
+
yes: options.scan ? true : options.yes,
|
|
6581
|
+
scan: options.scan
|
|
6164
6582
|
});
|
|
6165
6583
|
if (!result.success) {
|
|
6166
|
-
console.error(
|
|
6584
|
+
console.error(pc24.red("\nInit failed with errors:"));
|
|
6167
6585
|
for (const error of result.errors) {
|
|
6168
|
-
console.error(
|
|
6586
|
+
console.error(pc24.red(` - ${error}`));
|
|
6169
6587
|
}
|
|
6170
6588
|
process.exit(1);
|
|
6171
6589
|
}
|
|
6172
6590
|
} catch (error) {
|
|
6173
|
-
console.error(
|
|
6591
|
+
console.error(pc24.red("Error:"), error instanceof Error ? error.message : error);
|
|
6174
6592
|
process.exit(1);
|
|
6175
6593
|
}
|
|
6176
6594
|
});
|
|
6177
6595
|
program.command("tokens").description("Discover and list design tokens from CSS/SCSS 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) => {
|
|
6178
6596
|
try {
|
|
6179
|
-
const { tokens } = await import("./tokens-
|
|
6597
|
+
const { tokens } = await import("./tokens-DXEGYTOJ.js");
|
|
6180
6598
|
const result = await tokens({
|
|
6181
6599
|
config: options.config,
|
|
6182
6600
|
json: options.json,
|
|
@@ -6189,13 +6607,13 @@ program.command("tokens").description("Discover and list design tokens from CSS/
|
|
|
6189
6607
|
process.exit(1);
|
|
6190
6608
|
}
|
|
6191
6609
|
} catch (error) {
|
|
6192
|
-
console.error(
|
|
6610
|
+
console.error(pc24.red("Error:"), error instanceof Error ? error.message : error);
|
|
6193
6611
|
process.exit(1);
|
|
6194
6612
|
}
|
|
6195
6613
|
});
|
|
6196
6614
|
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) => {
|
|
6197
6615
|
try {
|
|
6198
|
-
const { generate } = await import("./generate-
|
|
6616
|
+
const { generate } = await import("./generate-BGKTKO6E.js");
|
|
6199
6617
|
const result = await generate({
|
|
6200
6618
|
projectRoot: process.cwd(),
|
|
6201
6619
|
component,
|
|
@@ -6203,11 +6621,11 @@ program.command("generate").description("Generate fragment files from component
|
|
|
6203
6621
|
componentPattern: options.pattern
|
|
6204
6622
|
});
|
|
6205
6623
|
if (!result.success) {
|
|
6206
|
-
console.error(
|
|
6624
|
+
console.error(pc24.red("\nGenerate completed with errors"));
|
|
6207
6625
|
process.exit(1);
|
|
6208
6626
|
}
|
|
6209
6627
|
} catch (error) {
|
|
6210
|
-
console.error(
|
|
6628
|
+
console.error(pc24.red("Error:"), error instanceof Error ? error.message : error);
|
|
6211
6629
|
process.exit(1);
|
|
6212
6630
|
}
|
|
6213
6631
|
});
|
|
@@ -6215,7 +6633,7 @@ program.command("graph").description("Query the component relationship graph").a
|
|
|
6215
6633
|
try {
|
|
6216
6634
|
await graph(component, options);
|
|
6217
6635
|
} catch (error) {
|
|
6218
|
-
console.error(
|
|
6636
|
+
console.error(pc24.red("Error:"), error instanceof Error ? error.message : error);
|
|
6219
6637
|
process.exit(1);
|
|
6220
6638
|
}
|
|
6221
6639
|
});
|
|
@@ -6233,14 +6651,14 @@ program.command("perf").description("Profile component bundle sizes and performa
|
|
|
6233
6651
|
process.exit(1);
|
|
6234
6652
|
}
|
|
6235
6653
|
} catch (error) {
|
|
6236
|
-
console.error(
|
|
6654
|
+
console.error(pc24.red("Error:"), error instanceof Error ? error.message : error);
|
|
6237
6655
|
process.exit(1);
|
|
6238
6656
|
}
|
|
6239
6657
|
});
|
|
6240
6658
|
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) => {
|
|
6241
6659
|
try {
|
|
6242
6660
|
const { config, configDir } = await loadConfig(options.config);
|
|
6243
|
-
const { runTestCommand, listTests } = await import("./test-
|
|
6661
|
+
const { runTestCommand, listTests } = await import("./test-2CSOSS3B.js");
|
|
6244
6662
|
if (options.list) {
|
|
6245
6663
|
await listTests(config, configDir, {
|
|
6246
6664
|
component: options.component,
|
|
@@ -6273,7 +6691,7 @@ program.command("test").description("Run interaction tests for fragments with pl
|
|
|
6273
6691
|
});
|
|
6274
6692
|
process.exit(exitCode);
|
|
6275
6693
|
} catch (error) {
|
|
6276
|
-
console.error(
|
|
6694
|
+
console.error(pc24.red("Error:"), error instanceof Error ? error.message : error);
|
|
6277
6695
|
process.exit(1);
|
|
6278
6696
|
}
|
|
6279
6697
|
});
|
|
@@ -6288,7 +6706,7 @@ program.command("doctor").description("Diagnose design system configuration issu
|
|
|
6288
6706
|
process.exit(1);
|
|
6289
6707
|
}
|
|
6290
6708
|
} catch (error) {
|
|
6291
|
-
console.error(
|
|
6709
|
+
console.error(pc24.red("Error:"), error instanceof Error ? error.message : error);
|
|
6292
6710
|
process.exit(1);
|
|
6293
6711
|
}
|
|
6294
6712
|
});
|