@fragments-sdk/cli 0.14.3 → 0.15.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (181) hide show
  1. package/README.md +0 -3
  2. package/dist/{ai-client-I6MDWNYA.js → ai-client-LSLQGOMM.js} +1 -2
  3. package/dist/bin.js +4745 -3817
  4. package/dist/bin.js.map +1 -1
  5. package/dist/{chunk-TXFCEDOC.js → chunk-2WXKALIG.js} +2 -2
  6. package/dist/{chunk-I34BC3CU.js → chunk-32LIWN2P.js} +1006 -3
  7. package/dist/chunk-32LIWN2P.js.map +1 -0
  8. package/dist/chunk-5JF26E55.js +1255 -0
  9. package/dist/chunk-5JF26E55.js.map +1 -0
  10. package/dist/{chunk-APTQIBS5.js → chunk-6SQPP47U.js} +153 -1342
  11. package/dist/chunk-6SQPP47U.js.map +1 -0
  12. package/dist/chunk-7DZC4YEV.js +294 -0
  13. package/dist/chunk-7DZC4YEV.js.map +1 -0
  14. package/dist/{chunk-PJT5IZ37.js → chunk-BJE3425I.js} +19 -52
  15. package/dist/{chunk-PJT5IZ37.js.map → chunk-BJE3425I.js.map} +1 -1
  16. package/dist/{chunk-55KERLWL.js → chunk-HQ6A6DTV.js} +1587 -1073
  17. package/dist/chunk-HQ6A6DTV.js.map +1 -0
  18. package/dist/chunk-MHIBEEW4.js +511 -0
  19. package/dist/chunk-MHIBEEW4.js.map +1 -0
  20. package/dist/{chunk-5A6X2Y73.js → chunk-ONUP6Z4W.js} +25 -13
  21. package/dist/chunk-ONUP6Z4W.js.map +1 -0
  22. package/dist/chunk-QCN35LJU.js +630 -0
  23. package/dist/chunk-QCN35LJU.js.map +1 -0
  24. package/dist/chunk-T47OLCSF.js +36 -0
  25. package/dist/chunk-T47OLCSF.js.map +1 -0
  26. package/dist/codebase-scanner-MQHUZC2G.js +21 -0
  27. package/dist/converter-7XM3Y6NJ.js +33 -0
  28. package/dist/converter-7XM3Y6NJ.js.map +1 -0
  29. package/dist/core/index.js +43 -2
  30. package/dist/create-IH4R45GE.js +806 -0
  31. package/dist/create-IH4R45GE.js.map +1 -0
  32. package/dist/{generate-RYWIPDN2.js → generate-PVOLUAAC.js} +4 -6
  33. package/dist/{generate-RYWIPDN2.js.map → generate-PVOLUAAC.js.map} +1 -1
  34. package/dist/govern-scan-OYFZYOQW.js +413 -0
  35. package/dist/govern-scan-OYFZYOQW.js.map +1 -0
  36. package/dist/index.d.ts +4 -23
  37. package/dist/index.js +15 -14
  38. package/dist/index.js.map +1 -1
  39. package/dist/{init-WRUSW7R5.js → init-SSGUSP7Z.js} +131 -129
  40. package/dist/init-SSGUSP7Z.js.map +1 -0
  41. package/dist/{init-cloud-REQ3XLHO.js → init-cloud-3DNKPWFB.js} +30 -5
  42. package/dist/{init-cloud-REQ3XLHO.js.map → init-cloud-3DNKPWFB.js.map} +1 -1
  43. package/dist/mcp-bin.js +5 -37
  44. package/dist/mcp-bin.js.map +1 -1
  45. package/dist/node-37AUE74M.js +65 -0
  46. package/dist/push-contracts-WY32TFP6.js +84 -0
  47. package/dist/push-contracts-WY32TFP6.js.map +1 -0
  48. package/dist/scan-PKSYSTRR.js +15 -0
  49. package/dist/{scan-generate-TFZVL3BT.js → scan-generate-VY27PIOX.js} +340 -52
  50. package/dist/scan-generate-VY27PIOX.js.map +1 -0
  51. package/dist/scanner-4KZNOXAK.js +12 -0
  52. package/dist/{service-HKJ6B7P7.js → service-QJGWUIVL.js} +41 -30
  53. package/dist/{snapshot-C5DYIGIV.js → snapshot-WIJMEIFT.js} +2 -3
  54. package/dist/{snapshot-C5DYIGIV.js.map → snapshot-WIJMEIFT.js.map} +1 -1
  55. package/dist/{static-viewer-DUVC4UIM.js → static-viewer-7QIBQZRC.js} +3 -4
  56. package/dist/static-viewer-7QIBQZRC.js.map +1 -0
  57. package/dist/{test-JW7JIDFG.js → test-64Z5BKBA.js} +4 -7
  58. package/dist/{test-JW7JIDFG.js.map → test-64Z5BKBA.js.map} +1 -1
  59. package/dist/token-normalizer-TEPOVBPV.js +312 -0
  60. package/dist/token-normalizer-TEPOVBPV.js.map +1 -0
  61. package/dist/token-parser-32KOIOFN.js +22 -0
  62. package/dist/token-parser-32KOIOFN.js.map +1 -0
  63. package/dist/{tokens-KE73G5JC.js → tokens-NZWFQIAB.js} +10 -9
  64. package/dist/{tokens-KE73G5JC.js.map → tokens-NZWFQIAB.js.map} +1 -1
  65. package/dist/tokens-generate-5JQSJ27E.js +85 -0
  66. package/dist/tokens-generate-5JQSJ27E.js.map +1 -0
  67. package/dist/tokens-push-HY3KO36V.js +148 -0
  68. package/dist/tokens-push-HY3KO36V.js.map +1 -0
  69. package/package.json +8 -6
  70. package/src/bin.ts +300 -48
  71. package/src/commands/__fixtures__/shadcn-label-wrapper/package.json +7 -0
  72. package/src/commands/__fixtures__/shadcn-label-wrapper/src/components/ui/label.contract.json +42 -0
  73. package/src/commands/__fixtures__/shadcn-label-wrapper/src/components/ui/label.tsx +11 -0
  74. package/src/commands/__fixtures__/shadcn-label-wrapper/src/components/ui/primitive.contract.json +20 -0
  75. package/src/commands/__fixtures__/shadcn-label-wrapper/src/components/ui/primitive.tsx +14 -0
  76. package/src/commands/__fixtures__/shadcn-label-wrapper/tsconfig.app.json +23 -0
  77. package/src/commands/__tests__/build-freshness.test.ts +231 -0
  78. package/src/commands/__tests__/create.test.ts +71 -0
  79. package/src/commands/__tests__/drift-sync.test.ts +1 -1
  80. package/src/commands/__tests__/govern.test.ts +258 -0
  81. package/src/commands/__tests__/init.test.ts +113 -0
  82. package/src/commands/__tests__/scan-generate.test.ts +189 -70
  83. package/src/commands/__tests__/verify.test.ts +91 -0
  84. package/src/commands/build.ts +54 -1
  85. package/src/commands/context.ts +1 -1
  86. package/src/commands/create.ts +536 -0
  87. package/src/commands/discover.ts +151 -0
  88. package/src/commands/doctor.ts +3 -2
  89. package/src/commands/enhance.ts +3 -1
  90. package/src/commands/govern-scan.ts +565 -0
  91. package/src/commands/govern.ts +67 -4
  92. package/src/commands/init-cloud.ts +32 -4
  93. package/src/commands/init.ts +152 -28
  94. package/src/commands/inspect.ts +290 -0
  95. package/src/commands/migrate-contract.ts +85 -0
  96. package/src/commands/push-contracts.ts +112 -0
  97. package/src/commands/scan-generate.ts +439 -51
  98. package/src/commands/scan.ts +14 -0
  99. package/src/commands/setup.ts +27 -50
  100. package/src/commands/sync.ts +2 -2
  101. package/src/commands/tokens-generate.ts +113 -0
  102. package/src/commands/tokens-push.ts +199 -0
  103. package/src/commands/verify.ts +195 -1
  104. package/src/core/__fixtures__/shadcn-input/input.tsx +7 -0
  105. package/src/core/__fixtures__/shadcn-input/tsconfig.json +14 -0
  106. package/src/core/__fixtures__/shadcn-label/label.tsx +11 -0
  107. package/src/core/__fixtures__/shadcn-label/primitive.tsx +14 -0
  108. package/src/core/__fixtures__/shadcn-label/tsconfig.json +14 -0
  109. package/src/core/__fixtures__/shadcn-radix-label/label.tsx +11 -0
  110. package/src/core/__fixtures__/shadcn-radix-label/node_modules/radix-ui/index.d.ts +12 -0
  111. package/src/core/__fixtures__/shadcn-radix-label/tsconfig.json +14 -0
  112. package/src/core/__tests__/contract-parity.test.ts +316 -0
  113. package/src/core/__tests__/token-resolver.test.ts +1 -1
  114. package/src/core/component-extractor.test.ts +40 -1
  115. package/src/core/config.ts +2 -1
  116. package/src/core/discovery.ts +13 -2
  117. package/src/core/drift-verifier.ts +123 -0
  118. package/src/core/extractor-adapter.ts +80 -0
  119. package/src/index.ts +3 -3
  120. package/src/mcp/__tests__/projectFields.test.ts +1 -1
  121. package/src/mcp/utils.ts +1 -50
  122. package/src/migrate/converter.ts +3 -3
  123. package/src/migrate/fragment-to-contract.ts +253 -0
  124. package/src/migrate/report.ts +1 -1
  125. package/src/scripts/token-benchmark.ts +121 -0
  126. package/src/service/__tests__/props-extractor.test.ts +94 -0
  127. package/src/service/__tests__/token-normalizer.test.ts +690 -0
  128. package/src/service/ast-utils.ts +4 -23
  129. package/src/service/babel-config.ts +23 -0
  130. package/src/service/enhance/converter.ts +61 -0
  131. package/src/service/enhance/props-extractor.ts +25 -8
  132. package/src/service/enhance/scanner.ts +5 -24
  133. package/src/service/index.ts +8 -0
  134. package/src/service/snippet-validation.ts +9 -3
  135. package/src/service/tailwind-v4-parser.ts +314 -0
  136. package/src/service/token-normalizer.ts +510 -0
  137. package/src/service/token-parser.ts +56 -0
  138. package/src/setup.ts +10 -39
  139. package/src/shared/index.ts +1 -0
  140. package/src/shared/project-fields.ts +46 -0
  141. package/src/theme/__tests__/component-contrast.test.ts +2 -2
  142. package/src/theme/__tests__/serializer.test.ts +1 -1
  143. package/src/theme/generator.ts +16 -1
  144. package/src/theme/schema.ts +8 -0
  145. package/src/theme/serializer.ts +13 -9
  146. package/src/theme/types.ts +8 -0
  147. package/src/validators.ts +1 -2
  148. package/src/viewer/__tests__/viewer-integration.test.ts +8 -8
  149. package/src/viewer/style-utils.ts +27 -412
  150. package/src/viewer/vite-plugin.ts +2 -2
  151. package/dist/chunk-55KERLWL.js.map +0 -1
  152. package/dist/chunk-5A6X2Y73.js.map +0 -1
  153. package/dist/chunk-APTQIBS5.js.map +0 -1
  154. package/dist/chunk-EYXVAMEX.js +0 -626
  155. package/dist/chunk-EYXVAMEX.js.map +0 -1
  156. package/dist/chunk-I34BC3CU.js.map +0 -1
  157. package/dist/chunk-LOYS64QS.js +0 -2453
  158. package/dist/chunk-LOYS64QS.js.map +0 -1
  159. package/dist/chunk-Z7EY4VHE.js +0 -50
  160. package/dist/chunk-ZKTFKHWN.js +0 -324
  161. package/dist/chunk-ZKTFKHWN.js.map +0 -1
  162. package/dist/discovery-VDANZAJ2.js +0 -28
  163. package/dist/init-WRUSW7R5.js.map +0 -1
  164. package/dist/sass.node-4XJK6YBF.js +0 -130708
  165. package/dist/sass.node-4XJK6YBF.js.map +0 -1
  166. package/dist/scan-YJHQIRKG.js +0 -14
  167. package/dist/scan-generate-TFZVL3BT.js.map +0 -1
  168. package/dist/viewer-2TZS3NDL.js +0 -2730
  169. package/dist/viewer-2TZS3NDL.js.map +0 -1
  170. package/src/build.ts +0 -612
  171. package/src/commands/dev.ts +0 -107
  172. package/src/core/auto-props.ts +0 -464
  173. package/src/core/component-extractor.ts +0 -1030
  174. package/src/core/token-resolver.ts +0 -155
  175. /package/dist/{ai-client-I6MDWNYA.js.map → ai-client-LSLQGOMM.js.map} +0 -0
  176. /package/dist/{chunk-TXFCEDOC.js.map → chunk-2WXKALIG.js.map} +0 -0
  177. /package/dist/{chunk-Z7EY4VHE.js.map → codebase-scanner-MQHUZC2G.js.map} +0 -0
  178. /package/dist/{discovery-VDANZAJ2.js.map → node-37AUE74M.js.map} +0 -0
  179. /package/dist/{scan-YJHQIRKG.js.map → scan-PKSYSTRR.js.map} +0 -0
  180. /package/dist/{service-HKJ6B7P7.js.map → scanner-4KZNOXAK.js.map} +0 -0
  181. /package/dist/{static-viewer-DUVC4UIM.js.map → service-QJGWUIVL.js.map} +0 -0
@@ -0,0 +1,294 @@
1
+ import { createRequire as __banner_createRequire } from 'module'; const require = __banner_createRequire(import.meta.url);
2
+
3
+ // src/service/enhance/scanner.ts
4
+ import { parse } from "@babel/parser";
5
+
6
+ // src/service/babel-config.ts
7
+ var BABEL_PARSER_OPTIONS = {
8
+ sourceType: "module",
9
+ plugins: [
10
+ "jsx",
11
+ "typescript",
12
+ ["decorators", { decoratorsBeforeExport: true }],
13
+ "classProperties",
14
+ "classPrivateProperties",
15
+ "classPrivateMethods",
16
+ "exportDefaultFrom",
17
+ "exportNamespaceFrom",
18
+ "dynamicImport",
19
+ "nullishCoalescingOperator",
20
+ "optionalChaining",
21
+ "objectRestSpread"
22
+ ]
23
+ };
24
+
25
+ // src/service/enhance/scanner.ts
26
+ import _traverse from "@babel/traverse";
27
+ import * as t from "@babel/types";
28
+ import { readFile } from "fs/promises";
29
+ var traverse = _traverse.default || _traverse;
30
+ async function scanFileForImports(filePath) {
31
+ const imports = [];
32
+ try {
33
+ const sourceCode = await readFile(filePath, "utf-8");
34
+ const ast = parse(sourceCode, BABEL_PARSER_OPTIONS);
35
+ traverse(ast, {
36
+ ImportDeclaration(path) {
37
+ const source = path.node.source.value;
38
+ const line = path.node.loc?.start.line ?? 0;
39
+ for (const specifier of path.node.specifiers) {
40
+ if (t.isImportSpecifier(specifier)) {
41
+ const importedName = t.isIdentifier(specifier.imported) ? specifier.imported.name : specifier.imported.value;
42
+ const localName = specifier.local.name;
43
+ if (isPascalCase(importedName)) {
44
+ imports.push({
45
+ componentName: importedName,
46
+ localName,
47
+ source,
48
+ isDefault: false,
49
+ filePath,
50
+ line
51
+ });
52
+ }
53
+ } else if (t.isImportDefaultSpecifier(specifier)) {
54
+ const localName = specifier.local.name;
55
+ if (isPascalCase(localName)) {
56
+ imports.push({
57
+ componentName: localName,
58
+ localName,
59
+ source,
60
+ isDefault: true,
61
+ filePath,
62
+ line
63
+ });
64
+ }
65
+ }
66
+ }
67
+ }
68
+ });
69
+ } catch (error) {
70
+ console.warn(`Failed to parse ${filePath}:`, error.message);
71
+ return [];
72
+ }
73
+ return imports;
74
+ }
75
+ async function scanFileForUsages(filePath, componentNames) {
76
+ const usages = [];
77
+ try {
78
+ const sourceCode = await readFile(filePath, "utf-8");
79
+ const lines = sourceCode.split("\n");
80
+ const ast = parse(sourceCode, BABEL_PARSER_OPTIONS);
81
+ traverse(ast, {
82
+ JSXOpeningElement(path) {
83
+ const elementName = getJSXElementName(path.node.name);
84
+ if (!elementName) return;
85
+ const componentName = componentNames.get(elementName);
86
+ if (!componentName) return;
87
+ const loc = path.node.loc;
88
+ if (!loc) return;
89
+ const props = extractProps(path.node.attributes);
90
+ const contextLines = getContextLines(lines, loc.start.line - 1, 3);
91
+ const isConditional = checkIfConditional(path);
92
+ const parentElement = getParentElementName(path);
93
+ usages.push({
94
+ componentName,
95
+ filePath,
96
+ line: loc.start.line,
97
+ column: loc.start.column,
98
+ props,
99
+ context: contextLines,
100
+ parentElement,
101
+ hasSpreadProps: props.spreads.length > 0,
102
+ isConditional
103
+ });
104
+ }
105
+ });
106
+ } catch (error) {
107
+ console.warn(`Failed to parse ${filePath}:`, error.message);
108
+ return [];
109
+ }
110
+ return usages;
111
+ }
112
+ async function scanFile(filePath, trackedComponents) {
113
+ const imports = [];
114
+ const usages = [];
115
+ try {
116
+ const sourceCode = await readFile(filePath, "utf-8");
117
+ const lines = sourceCode.split("\n");
118
+ const ast = parse(sourceCode, BABEL_PARSER_OPTIONS);
119
+ const localToComponent = /* @__PURE__ */ new Map();
120
+ traverse(ast, {
121
+ ImportDeclaration(path) {
122
+ const source = path.node.source.value;
123
+ const line = path.node.loc?.start.line ?? 0;
124
+ for (const specifier of path.node.specifiers) {
125
+ if (t.isImportSpecifier(specifier)) {
126
+ const importedName = t.isIdentifier(specifier.imported) ? specifier.imported.name : specifier.imported.value;
127
+ const localName = specifier.local.name;
128
+ if (isPascalCase(importedName)) {
129
+ if (!trackedComponents || trackedComponents.has(importedName)) {
130
+ imports.push({
131
+ componentName: importedName,
132
+ localName,
133
+ source,
134
+ isDefault: false,
135
+ filePath,
136
+ line
137
+ });
138
+ localToComponent.set(localName, importedName);
139
+ }
140
+ }
141
+ } else if (t.isImportDefaultSpecifier(specifier)) {
142
+ const localName = specifier.local.name;
143
+ if (isPascalCase(localName)) {
144
+ if (!trackedComponents || trackedComponents.has(localName)) {
145
+ imports.push({
146
+ componentName: localName,
147
+ localName,
148
+ source,
149
+ isDefault: true,
150
+ filePath,
151
+ line
152
+ });
153
+ localToComponent.set(localName, localName);
154
+ }
155
+ }
156
+ }
157
+ }
158
+ },
159
+ JSXOpeningElement(path) {
160
+ const elementName = getJSXElementName(path.node.name);
161
+ if (!elementName) return;
162
+ const componentName = localToComponent.get(elementName);
163
+ if (!componentName) return;
164
+ const loc = path.node.loc;
165
+ if (!loc) return;
166
+ const props = extractProps(path.node.attributes);
167
+ const contextLines = getContextLines(lines, loc.start.line - 1, 3);
168
+ const isConditional = checkIfConditional(path);
169
+ const parentElement = getParentElementName(path);
170
+ usages.push({
171
+ componentName,
172
+ filePath,
173
+ line: loc.start.line,
174
+ column: loc.start.column,
175
+ props,
176
+ context: contextLines,
177
+ parentElement,
178
+ hasSpreadProps: props.spreads.length > 0,
179
+ isConditional
180
+ });
181
+ }
182
+ });
183
+ } catch (error) {
184
+ console.warn(`Failed to parse ${filePath}:`, error.message);
185
+ return { imports: [], usages: [] };
186
+ }
187
+ return { imports, usages };
188
+ }
189
+ function isPascalCase(str) {
190
+ return /^[A-Z][a-zA-Z0-9]*$/.test(str);
191
+ }
192
+ function getJSXElementName(name) {
193
+ if (t.isJSXIdentifier(name)) {
194
+ return name.name;
195
+ }
196
+ if (t.isJSXMemberExpression(name)) {
197
+ const parts = [];
198
+ let current = name;
199
+ while (t.isJSXMemberExpression(current)) {
200
+ parts.unshift(current.property.name);
201
+ current = current.object;
202
+ }
203
+ if (t.isJSXIdentifier(current)) {
204
+ parts.unshift(current.name);
205
+ }
206
+ return parts.join(".");
207
+ }
208
+ return null;
209
+ }
210
+ function extractProps(attributes) {
211
+ const result = {
212
+ static: {},
213
+ dynamic: [],
214
+ spreads: []
215
+ };
216
+ for (const attr of attributes) {
217
+ if (t.isJSXSpreadAttribute(attr)) {
218
+ if (t.isIdentifier(attr.argument)) {
219
+ result.spreads.push(attr.argument.name);
220
+ } else {
221
+ result.spreads.push("(expression)");
222
+ }
223
+ } else if (t.isJSXAttribute(attr)) {
224
+ const propName = t.isJSXIdentifier(attr.name) ? attr.name.name : `${attr.name.namespace.name}:${attr.name.name.name}`;
225
+ const value = attr.value;
226
+ if (value === null) {
227
+ result.static[propName] = true;
228
+ } else if (t.isStringLiteral(value)) {
229
+ result.static[propName] = value.value;
230
+ } else if (t.isJSXExpressionContainer(value)) {
231
+ const expr = value.expression;
232
+ if (t.isStringLiteral(expr)) {
233
+ result.static[propName] = expr.value;
234
+ } else if (t.isNumericLiteral(expr)) {
235
+ result.static[propName] = expr.value;
236
+ } else if (t.isBooleanLiteral(expr)) {
237
+ result.static[propName] = expr.value;
238
+ } else if (t.isTemplateLiteral(expr) && expr.expressions.length === 0) {
239
+ result.static[propName] = expr.quasis.map((q) => q.value.raw).join("");
240
+ } else {
241
+ result.dynamic.push(propName);
242
+ }
243
+ }
244
+ }
245
+ }
246
+ return result;
247
+ }
248
+ function getContextLines(lines, centerLine, radius) {
249
+ const start = Math.max(0, centerLine - radius);
250
+ const end = Math.min(lines.length, centerLine + radius + 1);
251
+ return lines.slice(start, end).join("\n");
252
+ }
253
+ function checkIfConditional(path) {
254
+ let current = path.parentPath;
255
+ while (current) {
256
+ if (current.isLogicalExpression() && current.node.operator === "&&") {
257
+ return true;
258
+ }
259
+ if (current.isConditionalExpression()) {
260
+ return true;
261
+ }
262
+ if (current.isJSXExpressionContainer() && current.parentPath?.isJSXElement()) {
263
+ const expr = current.node.expression;
264
+ if (t.isLogicalExpression(expr) || t.isConditionalExpression(expr)) {
265
+ return true;
266
+ }
267
+ }
268
+ current = current.parentPath;
269
+ }
270
+ return false;
271
+ }
272
+ function getParentElementName(path) {
273
+ let current = path.parentPath;
274
+ const currentElementName = getJSXElementName(path.node.name);
275
+ while (current) {
276
+ if (current.isJSXElement()) {
277
+ const opening = current.node.openingElement;
278
+ const name = getJSXElementName(opening.name);
279
+ if (name && name !== currentElementName) {
280
+ return name;
281
+ }
282
+ }
283
+ current = current.parentPath;
284
+ }
285
+ return void 0;
286
+ }
287
+
288
+ export {
289
+ BABEL_PARSER_OPTIONS,
290
+ scanFileForImports,
291
+ scanFileForUsages,
292
+ scanFile
293
+ };
294
+ //# sourceMappingURL=chunk-7DZC4YEV.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/service/enhance/scanner.ts","../src/service/babel-config.ts"],"sourcesContent":["/**\n * AST Scanner for Component Usage Analysis\n *\n * Scans TypeScript/TSX files to find:\n * - Component imports (named, default, aliased)\n * - Component usages in JSX with props\n */\n\nimport { parse } from \"@babel/parser\";\nimport { BABEL_PARSER_OPTIONS } from \"../babel-config.js\";\nimport _traverse from \"@babel/traverse\";\nimport * as t from \"@babel/types\";\n\n// Handle CommonJS/ESM interop\nconst traverse = (_traverse as unknown as { default: typeof _traverse }).default || _traverse;\nimport { readFile } from \"node:fs/promises\";\nimport type {\n ComponentImport,\n ComponentUsage,\n UsageProps,\n} from \"./types.js\";\n\n\n/**\n * Scan a file for component imports\n *\n * Handles:\n * - Named imports: import { Button } from './Button'\n * - Default imports: import Button from './Button'\n * - Aliased imports: import { Button as Btn } from './Button'\n * - Namespace imports: import * as Components from './index'\n */\nexport async function scanFileForImports(\n filePath: string\n): Promise<ComponentImport[]> {\n const imports: ComponentImport[] = [];\n\n try {\n const sourceCode = await readFile(filePath, \"utf-8\");\n const ast = parse(sourceCode, BABEL_PARSER_OPTIONS);\n\n traverse(ast, {\n ImportDeclaration(path) {\n const source = path.node.source.value;\n const line = path.node.loc?.start.line ?? 0;\n\n for (const specifier of path.node.specifiers) {\n if (t.isImportSpecifier(specifier)) {\n // Named import: import { Button } from './Button'\n // or aliased: import { Button as Btn } from './Button'\n const importedName = t.isIdentifier(specifier.imported)\n ? specifier.imported.name\n : specifier.imported.value;\n const localName = specifier.local.name;\n\n // Only track PascalCase names (likely components)\n if (isPascalCase(importedName)) {\n imports.push({\n componentName: importedName,\n localName,\n source,\n isDefault: false,\n filePath,\n line,\n });\n }\n } else if (t.isImportDefaultSpecifier(specifier)) {\n // Default import: import Button from './Button'\n const localName = specifier.local.name;\n\n // Only track PascalCase names (likely components)\n if (isPascalCase(localName)) {\n imports.push({\n componentName: localName,\n localName,\n source,\n isDefault: true,\n filePath,\n line,\n });\n }\n }\n // Skip namespace imports for now (import * as X)\n }\n },\n });\n } catch (error) {\n // Return empty array for files with parse errors\n // Caller can check if empty means \"no imports\" or \"parse error\"\n console.warn(`Failed to parse ${filePath}:`, (error as Error).message);\n return [];\n }\n\n return imports;\n}\n\n/**\n * Scan a file for component usages in JSX\n *\n * @param filePath - File to scan\n * @param componentNames - Map of localName -> componentName for components to track\n */\nexport async function scanFileForUsages(\n filePath: string,\n componentNames: Map<string, string>\n): Promise<ComponentUsage[]> {\n const usages: ComponentUsage[] = [];\n\n try {\n const sourceCode = await readFile(filePath, \"utf-8\");\n const lines = sourceCode.split(\"\\n\");\n const ast = parse(sourceCode, BABEL_PARSER_OPTIONS);\n\n traverse(ast, {\n JSXOpeningElement(path) {\n const elementName = getJSXElementName(path.node.name);\n if (!elementName) return;\n\n // Check if this is a tracked component (by local name)\n const componentName = componentNames.get(elementName);\n if (!componentName) return;\n\n const loc = path.node.loc;\n if (!loc) return;\n\n // Extract props\n const props = extractProps(path.node.attributes);\n\n // Get surrounding context (3 lines before and after)\n const contextLines = getContextLines(lines, loc.start.line - 1, 3);\n\n // Check if conditionally rendered\n const isConditional = checkIfConditional(path);\n\n // Get parent element name\n const parentElement = getParentElementName(path);\n\n usages.push({\n componentName,\n filePath,\n line: loc.start.line,\n column: loc.start.column,\n props,\n context: contextLines,\n parentElement,\n hasSpreadProps: props.spreads.length > 0,\n isConditional,\n });\n },\n });\n } catch (error) {\n console.warn(`Failed to parse ${filePath}:`, (error as Error).message);\n return [];\n }\n\n return usages;\n}\n\n/**\n * Scan a file for both imports and usages in a single pass\n * More efficient for scanning many files\n */\nexport async function scanFile(\n filePath: string,\n trackedComponents?: Set<string>\n): Promise<{ imports: ComponentImport[]; usages: ComponentUsage[] }> {\n const imports: ComponentImport[] = [];\n const usages: ComponentUsage[] = [];\n\n try {\n const sourceCode = await readFile(filePath, \"utf-8\");\n const lines = sourceCode.split(\"\\n\");\n const ast = parse(sourceCode, BABEL_PARSER_OPTIONS);\n\n // Track local names to component names mapping within this file\n const localToComponent = new Map<string, string>();\n\n traverse(ast, {\n ImportDeclaration(path) {\n const source = path.node.source.value;\n const line = path.node.loc?.start.line ?? 0;\n\n for (const specifier of path.node.specifiers) {\n if (t.isImportSpecifier(specifier)) {\n const importedName = t.isIdentifier(specifier.imported)\n ? specifier.imported.name\n : specifier.imported.value;\n const localName = specifier.local.name;\n\n if (isPascalCase(importedName)) {\n // If we're tracking specific components, only add those\n if (!trackedComponents || trackedComponents.has(importedName)) {\n imports.push({\n componentName: importedName,\n localName,\n source,\n isDefault: false,\n filePath,\n line,\n });\n localToComponent.set(localName, importedName);\n }\n }\n } else if (t.isImportDefaultSpecifier(specifier)) {\n const localName = specifier.local.name;\n\n if (isPascalCase(localName)) {\n if (!trackedComponents || trackedComponents.has(localName)) {\n imports.push({\n componentName: localName,\n localName,\n source,\n isDefault: true,\n filePath,\n line,\n });\n localToComponent.set(localName, localName);\n }\n }\n }\n }\n },\n\n JSXOpeningElement(path) {\n const elementName = getJSXElementName(path.node.name);\n if (!elementName) return;\n\n // Check if this is a tracked component (by local name)\n const componentName = localToComponent.get(elementName);\n if (!componentName) return;\n\n const loc = path.node.loc;\n if (!loc) return;\n\n const props = extractProps(path.node.attributes);\n const contextLines = getContextLines(lines, loc.start.line - 1, 3);\n const isConditional = checkIfConditional(path);\n const parentElement = getParentElementName(path);\n\n usages.push({\n componentName,\n filePath,\n line: loc.start.line,\n column: loc.start.column,\n props,\n context: contextLines,\n parentElement,\n hasSpreadProps: props.spreads.length > 0,\n isConditional,\n });\n },\n });\n } catch (error) {\n console.warn(`Failed to parse ${filePath}:`, (error as Error).message);\n return { imports: [], usages: [] };\n }\n\n return { imports, usages };\n}\n\n/**\n * Check if a string is PascalCase (likely a component name)\n */\nfunction isPascalCase(str: string): boolean {\n return /^[A-Z][a-zA-Z0-9]*$/.test(str);\n}\n\n/**\n * Get the element name from a JSX element name node\n */\nfunction getJSXElementName(\n name: t.JSXIdentifier | t.JSXMemberExpression | t.JSXNamespacedName\n): string | null {\n if (t.isJSXIdentifier(name)) {\n return name.name;\n }\n if (t.isJSXMemberExpression(name)) {\n // Handle Component.SubComponent - return the full path\n const parts: string[] = [];\n let current: t.JSXMemberExpression | t.JSXIdentifier = name;\n while (t.isJSXMemberExpression(current)) {\n parts.unshift(current.property.name);\n current = current.object as t.JSXMemberExpression | t.JSXIdentifier;\n }\n if (t.isJSXIdentifier(current)) {\n parts.unshift(current.name);\n }\n return parts.join(\".\");\n }\n return null;\n}\n\n/**\n * Extract props from JSX attributes\n */\nfunction extractProps(\n attributes: (t.JSXAttribute | t.JSXSpreadAttribute)[]\n): UsageProps {\n const result: UsageProps = {\n static: {},\n dynamic: [],\n spreads: [],\n };\n\n for (const attr of attributes) {\n if (t.isJSXSpreadAttribute(attr)) {\n // {...props} or {...otherProps}\n if (t.isIdentifier(attr.argument)) {\n result.spreads.push(attr.argument.name);\n } else {\n result.spreads.push(\"(expression)\");\n }\n } else if (t.isJSXAttribute(attr)) {\n const propName = t.isJSXIdentifier(attr.name)\n ? attr.name.name\n : `${attr.name.namespace.name}:${attr.name.name.name}`;\n\n const value = attr.value;\n\n if (value === null) {\n // Boolean shorthand: <Button disabled />\n result.static[propName] = true;\n } else if (t.isStringLiteral(value)) {\n // String literal: <Button variant=\"primary\" />\n result.static[propName] = value.value;\n } else if (t.isJSXExpressionContainer(value)) {\n const expr = value.expression;\n\n if (t.isStringLiteral(expr)) {\n result.static[propName] = expr.value;\n } else if (t.isNumericLiteral(expr)) {\n result.static[propName] = expr.value;\n } else if (t.isBooleanLiteral(expr)) {\n result.static[propName] = expr.value;\n } else if (t.isTemplateLiteral(expr) && expr.expressions.length === 0) {\n // Static template literal: variant={`primary`}\n result.static[propName] = expr.quasis.map((q) => q.value.raw).join(\"\");\n } else {\n // Dynamic expression\n result.dynamic.push(propName);\n }\n }\n }\n }\n\n return result;\n}\n\n/**\n * Get surrounding context lines\n */\nfunction getContextLines(\n lines: string[],\n centerLine: number,\n radius: number\n): string {\n const start = Math.max(0, centerLine - radius);\n const end = Math.min(lines.length, centerLine + radius + 1);\n return lines.slice(start, end).join(\"\\n\");\n}\n\n/**\n * Check if JSX element is conditionally rendered\n */\nfunction checkIfConditional(path: babel.NodePath<t.JSXOpeningElement>): boolean {\n let current: babel.NodePath | null = path.parentPath;\n\n while (current) {\n // Check for {condition && <Component />}\n if (\n current.isLogicalExpression() &&\n current.node.operator === \"&&\"\n ) {\n return true;\n }\n\n // Check for {condition ? <Component /> : null}\n if (current.isConditionalExpression()) {\n return true;\n }\n\n // Check for ternary in JSX expression container\n if (\n current.isJSXExpressionContainer() &&\n current.parentPath?.isJSXElement()\n ) {\n const expr = current.node.expression;\n if (\n t.isLogicalExpression(expr) ||\n t.isConditionalExpression(expr)\n ) {\n return true;\n }\n }\n\n current = current.parentPath;\n }\n\n return false;\n}\n\n/**\n * Get the parent JSX element name\n */\nfunction getParentElementName(\n path: babel.NodePath<t.JSXOpeningElement>\n): string | undefined {\n let current: babel.NodePath | null = path.parentPath;\n const currentElementName = getJSXElementName(path.node.name);\n\n while (current) {\n if (current.isJSXElement()) {\n const opening = current.node.openingElement;\n const name = getJSXElementName(opening.name);\n if (name && name !== currentElementName) {\n return name;\n }\n }\n current = current.parentPath;\n }\n\n return undefined;\n}\n\n// Type import for babel NodePath\nimport type * as babel from \"@babel/traverse\";\n","/**\n * Shared Babel parser configuration for React/TypeScript files.\n */\n\nimport type { ParserOptions } from \"@babel/parser\";\n\nexport const BABEL_PARSER_OPTIONS: ParserOptions = {\n sourceType: \"module\",\n plugins: [\n \"jsx\",\n \"typescript\",\n [\"decorators\", { decoratorsBeforeExport: true }],\n \"classProperties\",\n \"classPrivateProperties\",\n \"classPrivateMethods\",\n \"exportDefaultFrom\",\n \"exportNamespaceFrom\",\n \"dynamicImport\",\n \"nullishCoalescingOperator\",\n \"optionalChaining\",\n \"objectRestSpread\",\n ],\n};\n"],"mappings":"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","names":[]}
@@ -1,7 +1,7 @@
1
1
  import { createRequire as __banner_createRequire } from 'module'; const require = __banner_createRequire(import.meta.url);
2
2
  import {
3
3
  BRAND
4
- } from "./chunk-I34BC3CU.js";
4
+ } from "./chunk-32LIWN2P.js";
5
5
 
6
6
  // src/commands/setup.ts
7
7
  import { readFile, writeFile, access, mkdir } from "fs/promises";
@@ -322,6 +322,18 @@ function generateScssSeedImport(brand) {
322
322
  );
323
323
  `;
324
324
  }
325
+ async function runSetupStep(fn, failureLabel, actions, errors) {
326
+ try {
327
+ const result = await fn();
328
+ const icon = result.modified ? pc.green("+") : pc.dim("\xB7");
329
+ console.log(` ${icon} ${result.message}`);
330
+ if (result.modified) actions.push(result.message);
331
+ } catch (error) {
332
+ const msg = `${failureLabel}: ${error instanceof Error ? error.message : error}`;
333
+ console.log(` ${pc.red("\u2717")} ${msg}`);
334
+ errors.push(msg);
335
+ }
336
+ }
325
337
  async function setup(options = {}) {
326
338
  const root = resolve(options.root ?? process.cwd());
327
339
  const actions = [];
@@ -347,64 +359,19 @@ ${BRAND.name} Setup
347
359
  }
348
360
  console.log();
349
361
  if (entryFile) {
350
- try {
351
- const result = await addStylesImport(root, entryFile);
352
- const icon = result.modified ? pc.green("+") : pc.dim("\xB7");
353
- console.log(` ${icon} ${result.message}`);
354
- if (result.modified) actions.push(result.message);
355
- } catch (error) {
356
- const msg = `Failed to add styles import: ${error instanceof Error ? error.message : error}`;
357
- console.log(` ${pc.red("\u2717")} ${msg}`);
358
- errors.push(msg);
359
- }
362
+ await runSetupStep(() => addStylesImport(root, entryFile), "Failed to add styles import", actions, errors);
360
363
  }
361
364
  if (entryFile) {
362
- try {
363
- const result = await addThemeProvider(root, entryFile, framework);
364
- const icon = result.modified ? pc.green("+") : pc.dim("\xB7");
365
- console.log(` ${icon} ${result.message}`);
366
- if (result.modified) actions.push(result.message);
367
- } catch (error) {
368
- const msg = `Failed to add ThemeProvider: ${error instanceof Error ? error.message : error}`;
369
- console.log(` ${pc.red("\u2717")} ${msg}`);
370
- errors.push(msg);
371
- }
365
+ await runSetupStep(() => addThemeProvider(root, entryFile, framework), "Failed to add ThemeProvider", actions, errors);
372
366
  }
373
367
  if (framework === "nextjs-app" || framework === "nextjs-pages") {
374
- try {
375
- const result = await addTranspilePackages(root);
376
- const icon = result.modified ? pc.green("+") : pc.dim("\xB7");
377
- console.log(` ${icon} ${result.message}`);
378
- if (result.modified) actions.push(result.message);
379
- } catch (error) {
380
- const msg = `Failed to update next.config: ${error instanceof Error ? error.message : error}`;
381
- console.log(` ${pc.red("\u2717")} ${msg}`);
382
- errors.push(msg);
383
- }
368
+ await runSetupStep(() => addTranspilePackages(root), "Failed to update next.config", actions, errors);
384
369
  }
385
370
  if (options.scss || options.brand) {
386
- try {
387
- const result = await createScssSeeds(root, options.brand);
388
- const icon = result.modified ? pc.green("+") : pc.dim("\xB7");
389
- console.log(` ${icon} ${result.message}`);
390
- if (result.modified) actions.push(result.message);
391
- } catch (error) {
392
- const msg = `Failed to create SCSS seeds: ${error instanceof Error ? error.message : error}`;
393
- console.log(` ${pc.red("\u2717")} ${msg}`);
394
- errors.push(msg);
395
- }
371
+ await runSetupStep(() => createScssSeeds(root, options.brand), "Failed to create SCSS seeds", actions, errors);
396
372
  }
397
373
  if (options.mcp) {
398
- try {
399
- const result = await setupMcpConfig(root);
400
- const icon = result.modified ? pc.green("+") : pc.dim("\xB7");
401
- console.log(` ${icon} ${result.message}`);
402
- if (result.modified) actions.push(result.message);
403
- } catch (error) {
404
- const msg = `Failed to configure MCP: ${error instanceof Error ? error.message : error}`;
405
- console.log(` ${pc.red("\u2717")} ${msg}`);
406
- errors.push(msg);
407
- }
374
+ await runSetupStep(() => setupMcpConfig(root), "Failed to configure MCP", actions, errors);
408
375
  }
409
376
  console.log();
410
377
  if (errors.length > 0) {
@@ -440,4 +407,4 @@ export {
440
407
  addTranspilePackages,
441
408
  setup
442
409
  };
443
- //# sourceMappingURL=chunk-PJT5IZ37.js.map
410
+ //# sourceMappingURL=chunk-BJE3425I.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/commands/setup.ts"],"sourcesContent":["/**\n * fragments setup - Configure @fragments-sdk/ui in a consumer project\n *\n * Auto-detects framework (Next.js, Vite, etc.) and scaffolds:\n * - Styles import in entry file\n * - ThemeProvider wrapper in layout/app\n * - transpilePackages for Next.js\n * - SCSS seeds file (optional)\n */\n\nimport { readFile, writeFile, access, mkdir } from 'node:fs/promises';\nimport { join, resolve, dirname } from 'node:path';\nimport pc from 'picocolors';\nimport { BRAND } from '../core/index.js';\n\n// ============================================\n// Types\n// ============================================\n\nexport interface SetupOptions {\n /** Project root directory (defaults to cwd) */\n root?: string;\n /** Skip interactive prompts */\n yes?: boolean;\n /** Brand color hex (e.g., #6366f1) */\n brand?: string;\n /** Include SCSS seed file */\n scss?: boolean;\n /** Configure MCP server for AI tooling */\n mcp?: boolean;\n}\n\nexport interface SetupResult {\n success: boolean;\n actions: string[];\n errors: string[];\n}\n\nexport type Framework = 'nextjs-app' | 'nextjs-pages' | 'vite' | 'remix' | 'astro' | 'unknown';\n\n// ============================================\n// Detection\n// ============================================\n\nexport async function fileExists(path: string): Promise<boolean> {\n try {\n await access(path);\n return true;\n } catch {\n return false;\n }\n}\n\nexport async function detectSetupFramework(root: string): Promise<Framework> {\n // Next.js App Router\n if (\n await fileExists(join(root, 'app/layout.tsx')) ||\n await fileExists(join(root, 'src/app/layout.tsx'))\n ) {\n return 'nextjs-app';\n }\n\n // Next.js Pages Router\n if (\n await fileExists(join(root, 'pages/_app.tsx')) ||\n await fileExists(join(root, 'pages/_app.ts'))\n ) {\n return 'nextjs-pages';\n }\n\n // Next.js (config exists but no router detected yet)\n if (\n await fileExists(join(root, 'next.config.ts')) ||\n await fileExists(join(root, 'next.config.js')) ||\n await fileExists(join(root, 'next.config.mjs'))\n ) {\n return 'nextjs-app';\n }\n\n // Remix\n if (\n await fileExists(join(root, 'app/root.tsx')) ||\n await fileExists(join(root, 'app/root.ts'))\n ) {\n return 'remix';\n }\n\n // Astro\n if (\n await fileExists(join(root, 'astro.config.mjs')) ||\n await fileExists(join(root, 'astro.config.ts'))\n ) {\n return 'astro';\n }\n\n // Vite (check after Remix/Astro since they also use Vite under the hood)\n if (\n await fileExists(join(root, 'vite.config.ts')) ||\n await fileExists(join(root, 'vite.config.js'))\n ) {\n return 'vite';\n }\n\n // Fallback: check package.json for framework deps\n try {\n const pkgPath = join(root, 'package.json');\n const pkgContent = await readFile(pkgPath, 'utf-8');\n const pkg = JSON.parse(pkgContent);\n const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };\n\n if (allDeps['next']) return 'nextjs-app';\n if (allDeps['@remix-run/react']) return 'remix';\n if (allDeps['astro']) return 'astro';\n if (allDeps['vite']) return 'vite';\n } catch {\n // No package.json or parse error\n }\n\n return 'unknown';\n}\n\nexport async function findEntryFile(root: string, framework: Framework): Promise<string | null> {\n const candidates: string[] = [];\n\n switch (framework) {\n case 'nextjs-app':\n candidates.push(\n 'src/app/layout.tsx', 'app/layout.tsx',\n 'src/app/layout.ts', 'app/layout.ts'\n );\n break;\n case 'nextjs-pages':\n candidates.push('pages/_app.tsx', 'pages/_app.ts');\n break;\n case 'remix':\n candidates.push('app/root.tsx', 'app/root.ts');\n break;\n case 'astro':\n candidates.push(\n 'src/layouts/Layout.astro',\n 'src/layouts/BaseLayout.astro',\n 'src/pages/index.astro'\n );\n break;\n case 'vite':\n candidates.push(\n 'src/main.tsx', 'src/main.ts',\n 'src/index.tsx', 'src/index.ts'\n );\n break;\n default:\n candidates.push(\n 'src/main.tsx', 'src/main.ts',\n 'src/index.tsx', 'src/index.ts',\n 'src/App.tsx', 'src/App.ts'\n );\n }\n\n for (const candidate of candidates) {\n if (await fileExists(join(root, candidate))) {\n return candidate;\n }\n }\n\n return null;\n}\n\nasync function findNextConfig(root: string): Promise<string | null> {\n const candidates = ['next.config.ts', 'next.config.mjs', 'next.config.js'];\n for (const candidate of candidates) {\n if (await fileExists(join(root, candidate))) {\n return candidate;\n }\n }\n return null;\n}\n\n// ============================================\n// Actions\n// ============================================\n\nexport async function addStylesImport(root: string, entryFile: string): Promise<{ modified: boolean; message: string }> {\n const fullPath = join(root, entryFile);\n const content = await readFile(fullPath, 'utf-8');\n\n if (content.includes('@fragments-sdk/ui/styles')) {\n return { modified: false, message: `Styles already imported in ${entryFile}` };\n }\n\n const stylesImport = \"import '@fragments-sdk/ui/styles';\";\n let newContent: string;\n\n // Astro files: insert inside frontmatter block (between --- fences)\n if (entryFile.endsWith('.astro')) {\n const fenceStart = content.indexOf('---');\n if (fenceStart !== -1) {\n const insertPos = fenceStart + 4; // after \"---\\n\"\n newContent = content.slice(0, insertPos) + stylesImport + '\\n' + content.slice(insertPos);\n } else {\n // No frontmatter — add one\n newContent = `---\\n${stylesImport}\\n---\\n${content}`;\n }\n } else {\n const useClientMatch = content.match(/^(?:\\uFEFF)?[ \\t]*['\"]use client['\"]\\s*;?[ \\t]*$/m);\n\n if (useClientMatch && useClientMatch.index != null) {\n const directiveLineEnd = content.indexOf('\\n', useClientMatch.index);\n const directiveEnd = directiveLineEnd === -1 ? content.length : directiveLineEnd + 1;\n const separator = directiveLineEnd === -1 ? '\\n' : '';\n newContent = content.slice(0, directiveEnd) + separator + stylesImport + '\\n' + content.slice(directiveEnd);\n } else {\n newContent = stylesImport + '\\n' + content;\n }\n }\n\n await writeFile(fullPath, newContent, 'utf-8');\n return { modified: true, message: `Added styles import to ${entryFile}` };\n}\n\nexport async function addThemeProvider(root: string, entryFile: string, framework: Framework): Promise<{ modified: boolean; message: string }> {\n const fullPath = join(root, entryFile);\n const content = await readFile(fullPath, 'utf-8');\n\n if (content.includes('ThemeProvider')) {\n return { modified: false, message: `ThemeProvider already present in ${entryFile}` };\n }\n\n // Astro uses .astro files — can't inject React imports\n if (framework === 'astro') {\n return { modified: false, message: 'Add ThemeProvider in your React island — see https://usefragments.com/getting-started#astro' };\n }\n\n // Add provider import after the last import line\n const providerImport = \"import { ThemeProvider, TooltipProvider, ToastProvider } from '@fragments-sdk/ui';\";\n\n let newContent = content;\n const lines = content.split('\\n');\n\n // Prefer placing right after the @fragments-sdk/ui/styles import if it exists\n let insertIdx = -1;\n for (let i = 0; i < lines.length; i++) {\n if (lines[i].includes('@fragments-sdk/ui/styles')) {\n insertIdx = i;\n break;\n }\n }\n\n // Otherwise, place after the last import line\n if (insertIdx === -1) {\n for (let i = 0; i < lines.length; i++) {\n if (lines[i].startsWith('import ') || lines[i].startsWith(\"import '\") || lines[i].startsWith('import \"')) {\n insertIdx = i;\n }\n }\n }\n\n if (insertIdx >= 0) {\n lines.splice(insertIdx + 1, 0, providerImport);\n newContent = lines.join('\\n');\n } else {\n newContent = providerImport + '\\n' + content;\n }\n\n await writeFile(fullPath, newContent, 'utf-8');\n\n // Framework-specific wrap instructions\n if (framework === 'nextjs-app') {\n const hint = !content.includes('suppressHydrationWarning')\n ? `\\n Add suppressHydrationWarning to your <html> tag`\n : '';\n return {\n modified: true,\n message: `Added provider imports to ${entryFile}. Wrap {children} with:\\n` +\n ` <ThemeProvider defaultMode=\"system\"><TooltipProvider><ToastProvider>{children}</ToastProvider></TooltipProvider></ThemeProvider>${hint}`,\n };\n }\n\n if (framework === 'nextjs-pages') {\n return {\n modified: true,\n message: `Added provider imports to ${entryFile}. Wrap <Component {...pageProps} /> with:\\n` +\n ` <ThemeProvider defaultMode=\"system\"><TooltipProvider><ToastProvider>...</ToastProvider></TooltipProvider></ThemeProvider>`,\n };\n }\n\n if (framework === 'remix') {\n return {\n modified: true,\n message: `Added provider imports to ${entryFile}. Wrap <Outlet /> with:\\n` +\n ` <ThemeProvider defaultMode=\"system\"><TooltipProvider><ToastProvider>...</ToastProvider></TooltipProvider></ThemeProvider>`,\n };\n }\n\n // Vite and unknown — generic instruction\n return {\n modified: true,\n message: `Added provider imports to ${entryFile}. Wrap your app root with:\\n` +\n ` <ThemeProvider defaultMode=\"system\"><TooltipProvider><ToastProvider>...</ToastProvider></TooltipProvider></ThemeProvider>`,\n };\n}\n\nexport async function addTranspilePackages(root: string): Promise<{ modified: boolean; message: string }> {\n const configFile = await findNextConfig(root);\n if (!configFile) {\n return { modified: false, message: 'No next.config found' };\n }\n\n const fullPath = join(root, configFile);\n const content = await readFile(fullPath, 'utf-8');\n\n if (content.includes('transpilePackages') && content.includes('@fragments-sdk/ui')) {\n return { modified: false, message: `transpilePackages already configured in ${configFile}` };\n }\n\n if (content.includes('transpilePackages')) {\n // transpilePackages exists but without @fragments-sdk/ui — need manual addition\n return {\n modified: false,\n message: `transpilePackages found in ${configFile} but missing '@fragments-sdk/ui'. Please add it manually.`,\n };\n }\n\n // Add transpilePackages to the config\n // Try to find the config object and add the property\n const patterns = [\n // const nextConfig: NextConfig = { ... } (with optional type annotation)\n { search: /const\\s+\\w+\\s*(?::\\s*\\w+)?\\s*=\\s*\\{/, replacement: (match: string) => `${match}\\n transpilePackages: ['@fragments-sdk/ui'],` },\n // module.exports = { ... }\n { search: /module\\.exports\\s*=\\s*\\{/, replacement: (match: string) => `${match}\\n transpilePackages: ['@fragments-sdk/ui'],` },\n // export default { ... }\n { search: /export\\s+default\\s*\\{/, replacement: (match: string) => `${match}\\n transpilePackages: ['@fragments-sdk/ui'],` },\n ];\n\n for (const pattern of patterns) {\n if (pattern.search.test(content)) {\n const newContent = content.replace(pattern.search, pattern.replacement);\n await writeFile(fullPath, newContent, 'utf-8');\n return { modified: true, message: `Added transpilePackages to ${configFile}` };\n }\n }\n\n return {\n modified: false,\n message: `Could not auto-modify ${configFile}. Add transpilePackages: ['@fragments-sdk/ui'] manually.`,\n };\n}\n\nasync function createScssSeeds(root: string, brand?: string): Promise<{ modified: boolean; message: string }> {\n // Try common SCSS locations\n const scssLocations = [\n 'src/app/globals.scss',\n 'app/globals.scss',\n 'src/styles/globals.scss',\n 'src/globals.scss',\n 'styles/globals.scss',\n ];\n\n // Check if any exists already\n for (const loc of scssLocations) {\n const fullPath = join(root, loc);\n if (await fileExists(fullPath)) {\n const content = await readFile(fullPath, 'utf-8');\n if (content.includes('@fragments-sdk/ui/styles')) {\n return { modified: false, message: `SCSS seeds already configured in ${loc}` };\n }\n\n // Prepend @use to existing file\n const seedContent = generateScssSeedImport(brand);\n const newContent = seedContent + '\\n' + content;\n await writeFile(fullPath, newContent, 'utf-8');\n return { modified: true, message: `Added SCSS seed import to ${loc}` };\n }\n }\n\n // Create new globals.scss in the most common location\n const targetDir = await fileExists(join(root, 'src/app'))\n ? 'src/app'\n : await fileExists(join(root, 'src'))\n ? 'src/styles'\n : 'styles';\n\n const targetPath = join(targetDir, 'globals.scss');\n const fullPath = join(root, targetPath);\n\n await mkdir(dirname(fullPath), { recursive: true });\n await writeFile(fullPath, generateScssSeedImport(brand), 'utf-8');\n return { modified: true, message: `Created ${targetPath} with SCSS seed configuration` };\n}\n\nasync function setupMcpConfig(root: string): Promise<{ modified: boolean; message: string }> {\n // Check common MCP config locations\n const mcpConfigPaths = [\n '.cursor/mcp.json',\n '.vscode/mcp.json',\n ];\n\n for (const configPath of mcpConfigPaths) {\n const fullPath = join(root, configPath);\n if (await fileExists(fullPath)) {\n try {\n const content = await readFile(fullPath, 'utf-8');\n const config = JSON.parse(content);\n const servers = config.mcpServers || {};\n\n // Check if fragments is already configured\n const hasFragments = Object.values(servers).some((server: unknown) => {\n const s = server as { command?: string; args?: string[] };\n return s.args?.some((arg: string) => arg.includes('@fragments-sdk/mcp'));\n });\n\n if (hasFragments) {\n return { modified: false, message: `MCP server already configured in ${configPath}` };\n }\n\n // Add fragments MCP server\n servers.fragments = {\n command: 'npx',\n args: ['@fragments-sdk/mcp'],\n };\n config.mcpServers = servers;\n\n await writeFile(fullPath, JSON.stringify(config, null, 2) + '\\n', 'utf-8');\n return { modified: true, message: `Added Fragments MCP server to ${configPath}` };\n } catch {\n return { modified: false, message: `Could not parse ${configPath}` };\n }\n }\n }\n\n // No existing MCP config — create one for Cursor (most common)\n const cursorDir = join(root, '.cursor');\n const cursorMcpPath = join(cursorDir, 'mcp.json');\n\n await mkdir(cursorDir, { recursive: true });\n const mcpConfig = {\n mcpServers: {\n fragments: {\n command: 'npx',\n args: ['@fragments-sdk/mcp'],\n },\n },\n };\n\n await writeFile(cursorMcpPath, JSON.stringify(mcpConfig, null, 2) + '\\n', 'utf-8');\n return { modified: true, message: 'Created .cursor/mcp.json with Fragments MCP server' };\n}\n\nfunction generateScssSeedImport(brand?: string): string {\n const brandColor = brand || '#0066ff';\n return `@use '@fragments-sdk/ui/styles' with (\n $fui-brand: ${brandColor},\n $fui-neutral: \"stone\",\n $fui-density: \"default\",\n $fui-radius-style: \"rounded\"\n);\n`;\n}\n\n// ============================================\n// Main Setup Function\n// ============================================\n\nexport async function setup(options: SetupOptions = {}): Promise<SetupResult> {\n const root = resolve(options.root ?? process.cwd());\n const actions: string[] = [];\n const errors: string[] = [];\n\n console.log(pc.cyan(`\\n${BRAND.name} Setup\\n`));\n\n // 1. Detect framework\n const framework = await detectSetupFramework(root);\n const frameworkLabels: Record<string, string> = {\n 'nextjs-app': 'Next.js (App Router)',\n 'nextjs-pages': 'Next.js (Pages Router)',\n 'vite': 'Vite',\n 'remix': 'Remix',\n 'astro': 'Astro',\n };\n const frameworkLabel = frameworkLabels[framework] || 'Unknown';\n\n console.log(` ${pc.dim('Framework:')} ${frameworkLabel}`);\n\n // 2. Find entry file\n const entryFile = await findEntryFile(root, framework);\n if (entryFile) {\n console.log(` ${pc.dim('Entry:')} ${entryFile}`);\n } else {\n console.log(` ${pc.yellow('!')} Could not detect entry file`);\n }\n console.log();\n\n // 3. Add styles import\n if (entryFile) {\n try {\n const result = await addStylesImport(root, entryFile);\n const icon = result.modified ? pc.green('+') : pc.dim('·');\n console.log(` ${icon} ${result.message}`);\n if (result.modified) actions.push(result.message);\n } catch (error) {\n const msg = `Failed to add styles import: ${error instanceof Error ? error.message : error}`;\n console.log(` ${pc.red('✗')} ${msg}`);\n errors.push(msg);\n }\n }\n\n // 4. Add ThemeProvider imports\n if (entryFile) {\n try {\n const result = await addThemeProvider(root, entryFile, framework);\n const icon = result.modified ? pc.green('+') : pc.dim('·');\n console.log(` ${icon} ${result.message}`);\n if (result.modified) actions.push(result.message);\n } catch (error) {\n const msg = `Failed to add ThemeProvider: ${error instanceof Error ? error.message : error}`;\n console.log(` ${pc.red('✗')} ${msg}`);\n errors.push(msg);\n }\n }\n\n // 5. Next.js: add transpilePackages\n if (framework === 'nextjs-app' || framework === 'nextjs-pages') {\n try {\n const result = await addTranspilePackages(root);\n const icon = result.modified ? pc.green('+') : pc.dim('·');\n console.log(` ${icon} ${result.message}`);\n if (result.modified) actions.push(result.message);\n } catch (error) {\n const msg = `Failed to update next.config: ${error instanceof Error ? error.message : error}`;\n console.log(` ${pc.red('✗')} ${msg}`);\n errors.push(msg);\n }\n }\n\n // 6. Create SCSS seeds file (if --scss flag or brand color specified)\n if (options.scss || options.brand) {\n try {\n const result = await createScssSeeds(root, options.brand);\n const icon = result.modified ? pc.green('+') : pc.dim('·');\n console.log(` ${icon} ${result.message}`);\n if (result.modified) actions.push(result.message);\n } catch (error) {\n const msg = `Failed to create SCSS seeds: ${error instanceof Error ? error.message : error}`;\n console.log(` ${pc.red('✗')} ${msg}`);\n errors.push(msg);\n }\n }\n\n // 7. Configure MCP server (if --mcp flag)\n if (options.mcp) {\n try {\n const result = await setupMcpConfig(root);\n const icon = result.modified ? pc.green('+') : pc.dim('·');\n console.log(` ${icon} ${result.message}`);\n if (result.modified) actions.push(result.message);\n } catch (error) {\n const msg = `Failed to configure MCP: ${error instanceof Error ? error.message : error}`;\n console.log(` ${pc.red('✗')} ${msg}`);\n errors.push(msg);\n }\n }\n\n // Summary\n console.log();\n if (errors.length > 0) {\n console.log(pc.red(` ${errors.length} error(s) occurred during setup`));\n } else if (actions.length > 0) {\n console.log(pc.green(` ✓ Setup complete — ${actions.length} file(s) modified`));\n } else {\n console.log(pc.green(' ✓ Already configured — no changes needed'));\n }\n\n // Next steps\n console.log();\n console.log(pc.dim(' Next steps:'));\n if (!options.scss && !options.brand) {\n console.log(pc.dim(' • Run with --scss to add build-time theme seeds'));\n }\n if (!options.mcp) {\n console.log(pc.dim(' • Run with --mcp to configure AI tooling (MCP server)'));\n }\n console.log(pc.dim(' • Run `fragments doctor` to verify your setup'));\n console.log(pc.dim(' • Visit https://usefragments.com/getting-started'));\n console.log();\n\n return {\n success: errors.length === 0,\n actions,\n errors,\n };\n}\n"],"mappings":"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","names":["fullPath"]}
1
+ {"version":3,"sources":["../src/commands/setup.ts"],"sourcesContent":["/**\n * fragments setup - Configure @fragments-sdk/ui in a consumer project\n *\n * Auto-detects framework (Next.js, Vite, etc.) and scaffolds:\n * - Styles import in entry file\n * - ThemeProvider wrapper in layout/app\n * - transpilePackages for Next.js\n * - SCSS seeds file (optional)\n */\n\nimport { readFile, writeFile, access, mkdir } from 'node:fs/promises';\nimport { join, resolve, dirname } from 'node:path';\nimport pc from 'picocolors';\nimport { BRAND } from '../core/index.js';\n\n// ============================================\n// Types\n// ============================================\n\nexport interface SetupOptions {\n /** Project root directory (defaults to cwd) */\n root?: string;\n /** Skip interactive prompts */\n yes?: boolean;\n /** Brand color hex (e.g., #6366f1) */\n brand?: string;\n /** Include SCSS seed file */\n scss?: boolean;\n /** Configure MCP server for AI tooling */\n mcp?: boolean;\n}\n\nexport interface SetupResult {\n success: boolean;\n actions: string[];\n errors: string[];\n}\n\nexport type Framework = 'nextjs-app' | 'nextjs-pages' | 'vite' | 'remix' | 'astro' | 'unknown';\n\n// ============================================\n// Detection\n// ============================================\n\nexport async function fileExists(path: string): Promise<boolean> {\n try {\n await access(path);\n return true;\n } catch {\n return false;\n }\n}\n\nexport async function detectSetupFramework(root: string): Promise<Framework> {\n // Next.js App Router\n if (\n await fileExists(join(root, 'app/layout.tsx')) ||\n await fileExists(join(root, 'src/app/layout.tsx'))\n ) {\n return 'nextjs-app';\n }\n\n // Next.js Pages Router\n if (\n await fileExists(join(root, 'pages/_app.tsx')) ||\n await fileExists(join(root, 'pages/_app.ts'))\n ) {\n return 'nextjs-pages';\n }\n\n // Next.js (config exists but no router detected yet)\n if (\n await fileExists(join(root, 'next.config.ts')) ||\n await fileExists(join(root, 'next.config.js')) ||\n await fileExists(join(root, 'next.config.mjs'))\n ) {\n return 'nextjs-app';\n }\n\n // Remix\n if (\n await fileExists(join(root, 'app/root.tsx')) ||\n await fileExists(join(root, 'app/root.ts'))\n ) {\n return 'remix';\n }\n\n // Astro\n if (\n await fileExists(join(root, 'astro.config.mjs')) ||\n await fileExists(join(root, 'astro.config.ts'))\n ) {\n return 'astro';\n }\n\n // Vite (check after Remix/Astro since they also use Vite under the hood)\n if (\n await fileExists(join(root, 'vite.config.ts')) ||\n await fileExists(join(root, 'vite.config.js'))\n ) {\n return 'vite';\n }\n\n // Fallback: check package.json for framework deps\n try {\n const pkgPath = join(root, 'package.json');\n const pkgContent = await readFile(pkgPath, 'utf-8');\n const pkg = JSON.parse(pkgContent);\n const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };\n\n if (allDeps['next']) return 'nextjs-app';\n if (allDeps['@remix-run/react']) return 'remix';\n if (allDeps['astro']) return 'astro';\n if (allDeps['vite']) return 'vite';\n } catch {\n // No package.json or parse error\n }\n\n return 'unknown';\n}\n\nexport async function findEntryFile(root: string, framework: Framework): Promise<string | null> {\n const candidates: string[] = [];\n\n switch (framework) {\n case 'nextjs-app':\n candidates.push(\n 'src/app/layout.tsx', 'app/layout.tsx',\n 'src/app/layout.ts', 'app/layout.ts'\n );\n break;\n case 'nextjs-pages':\n candidates.push('pages/_app.tsx', 'pages/_app.ts');\n break;\n case 'remix':\n candidates.push('app/root.tsx', 'app/root.ts');\n break;\n case 'astro':\n candidates.push(\n 'src/layouts/Layout.astro',\n 'src/layouts/BaseLayout.astro',\n 'src/pages/index.astro'\n );\n break;\n case 'vite':\n candidates.push(\n 'src/main.tsx', 'src/main.ts',\n 'src/index.tsx', 'src/index.ts'\n );\n break;\n default:\n candidates.push(\n 'src/main.tsx', 'src/main.ts',\n 'src/index.tsx', 'src/index.ts',\n 'src/App.tsx', 'src/App.ts'\n );\n }\n\n for (const candidate of candidates) {\n if (await fileExists(join(root, candidate))) {\n return candidate;\n }\n }\n\n return null;\n}\n\nasync function findNextConfig(root: string): Promise<string | null> {\n const candidates = ['next.config.ts', 'next.config.mjs', 'next.config.js'];\n for (const candidate of candidates) {\n if (await fileExists(join(root, candidate))) {\n return candidate;\n }\n }\n return null;\n}\n\n// ============================================\n// Actions\n// ============================================\n\nexport async function addStylesImport(root: string, entryFile: string): Promise<{ modified: boolean; message: string }> {\n const fullPath = join(root, entryFile);\n const content = await readFile(fullPath, 'utf-8');\n\n if (content.includes('@fragments-sdk/ui/styles')) {\n return { modified: false, message: `Styles already imported in ${entryFile}` };\n }\n\n const stylesImport = \"import '@fragments-sdk/ui/styles';\";\n let newContent: string;\n\n // Astro files: insert inside frontmatter block (between --- fences)\n if (entryFile.endsWith('.astro')) {\n const fenceStart = content.indexOf('---');\n if (fenceStart !== -1) {\n const insertPos = fenceStart + 4; // after \"---\\n\"\n newContent = content.slice(0, insertPos) + stylesImport + '\\n' + content.slice(insertPos);\n } else {\n // No frontmatter — add one\n newContent = `---\\n${stylesImport}\\n---\\n${content}`;\n }\n } else {\n const useClientMatch = content.match(/^(?:\\uFEFF)?[ \\t]*['\"]use client['\"]\\s*;?[ \\t]*$/m);\n\n if (useClientMatch && useClientMatch.index != null) {\n const directiveLineEnd = content.indexOf('\\n', useClientMatch.index);\n const directiveEnd = directiveLineEnd === -1 ? content.length : directiveLineEnd + 1;\n const separator = directiveLineEnd === -1 ? '\\n' : '';\n newContent = content.slice(0, directiveEnd) + separator + stylesImport + '\\n' + content.slice(directiveEnd);\n } else {\n newContent = stylesImport + '\\n' + content;\n }\n }\n\n await writeFile(fullPath, newContent, 'utf-8');\n return { modified: true, message: `Added styles import to ${entryFile}` };\n}\n\nexport async function addThemeProvider(root: string, entryFile: string, framework: Framework): Promise<{ modified: boolean; message: string }> {\n const fullPath = join(root, entryFile);\n const content = await readFile(fullPath, 'utf-8');\n\n if (content.includes('ThemeProvider')) {\n return { modified: false, message: `ThemeProvider already present in ${entryFile}` };\n }\n\n // Astro uses .astro files — can't inject React imports\n if (framework === 'astro') {\n return { modified: false, message: 'Add ThemeProvider in your React island — see https://usefragments.com/getting-started#astro' };\n }\n\n // Add provider import after the last import line\n const providerImport = \"import { ThemeProvider, TooltipProvider, ToastProvider } from '@fragments-sdk/ui';\";\n\n let newContent = content;\n const lines = content.split('\\n');\n\n // Prefer placing right after the @fragments-sdk/ui/styles import if it exists\n let insertIdx = -1;\n for (let i = 0; i < lines.length; i++) {\n if (lines[i].includes('@fragments-sdk/ui/styles')) {\n insertIdx = i;\n break;\n }\n }\n\n // Otherwise, place after the last import line\n if (insertIdx === -1) {\n for (let i = 0; i < lines.length; i++) {\n if (lines[i].startsWith('import ') || lines[i].startsWith(\"import '\") || lines[i].startsWith('import \"')) {\n insertIdx = i;\n }\n }\n }\n\n if (insertIdx >= 0) {\n lines.splice(insertIdx + 1, 0, providerImport);\n newContent = lines.join('\\n');\n } else {\n newContent = providerImport + '\\n' + content;\n }\n\n await writeFile(fullPath, newContent, 'utf-8');\n\n // Framework-specific wrap instructions\n if (framework === 'nextjs-app') {\n const hint = !content.includes('suppressHydrationWarning')\n ? `\\n Add suppressHydrationWarning to your <html> tag`\n : '';\n return {\n modified: true,\n message: `Added provider imports to ${entryFile}. Wrap {children} with:\\n` +\n ` <ThemeProvider defaultMode=\"system\"><TooltipProvider><ToastProvider>{children}</ToastProvider></TooltipProvider></ThemeProvider>${hint}`,\n };\n }\n\n if (framework === 'nextjs-pages') {\n return {\n modified: true,\n message: `Added provider imports to ${entryFile}. Wrap <Component {...pageProps} /> with:\\n` +\n ` <ThemeProvider defaultMode=\"system\"><TooltipProvider><ToastProvider>...</ToastProvider></TooltipProvider></ThemeProvider>`,\n };\n }\n\n if (framework === 'remix') {\n return {\n modified: true,\n message: `Added provider imports to ${entryFile}. Wrap <Outlet /> with:\\n` +\n ` <ThemeProvider defaultMode=\"system\"><TooltipProvider><ToastProvider>...</ToastProvider></TooltipProvider></ThemeProvider>`,\n };\n }\n\n // Vite and unknown — generic instruction\n return {\n modified: true,\n message: `Added provider imports to ${entryFile}. Wrap your app root with:\\n` +\n ` <ThemeProvider defaultMode=\"system\"><TooltipProvider><ToastProvider>...</ToastProvider></TooltipProvider></ThemeProvider>`,\n };\n}\n\nexport async function addTranspilePackages(root: string): Promise<{ modified: boolean; message: string }> {\n const configFile = await findNextConfig(root);\n if (!configFile) {\n return { modified: false, message: 'No next.config found' };\n }\n\n const fullPath = join(root, configFile);\n const content = await readFile(fullPath, 'utf-8');\n\n if (content.includes('transpilePackages') && content.includes('@fragments-sdk/ui')) {\n return { modified: false, message: `transpilePackages already configured in ${configFile}` };\n }\n\n if (content.includes('transpilePackages')) {\n // transpilePackages exists but without @fragments-sdk/ui — need manual addition\n return {\n modified: false,\n message: `transpilePackages found in ${configFile} but missing '@fragments-sdk/ui'. Please add it manually.`,\n };\n }\n\n // Add transpilePackages to the config\n // Try to find the config object and add the property\n const patterns = [\n // const nextConfig: NextConfig = { ... } (with optional type annotation)\n { search: /const\\s+\\w+\\s*(?::\\s*\\w+)?\\s*=\\s*\\{/, replacement: (match: string) => `${match}\\n transpilePackages: ['@fragments-sdk/ui'],` },\n // module.exports = { ... }\n { search: /module\\.exports\\s*=\\s*\\{/, replacement: (match: string) => `${match}\\n transpilePackages: ['@fragments-sdk/ui'],` },\n // export default { ... }\n { search: /export\\s+default\\s*\\{/, replacement: (match: string) => `${match}\\n transpilePackages: ['@fragments-sdk/ui'],` },\n ];\n\n for (const pattern of patterns) {\n if (pattern.search.test(content)) {\n const newContent = content.replace(pattern.search, pattern.replacement);\n await writeFile(fullPath, newContent, 'utf-8');\n return { modified: true, message: `Added transpilePackages to ${configFile}` };\n }\n }\n\n return {\n modified: false,\n message: `Could not auto-modify ${configFile}. Add transpilePackages: ['@fragments-sdk/ui'] manually.`,\n };\n}\n\nasync function createScssSeeds(root: string, brand?: string): Promise<{ modified: boolean; message: string }> {\n // Try common SCSS locations\n const scssLocations = [\n 'src/app/globals.scss',\n 'app/globals.scss',\n 'src/styles/globals.scss',\n 'src/globals.scss',\n 'styles/globals.scss',\n ];\n\n // Check if any exists already\n for (const loc of scssLocations) {\n const fullPath = join(root, loc);\n if (await fileExists(fullPath)) {\n const content = await readFile(fullPath, 'utf-8');\n if (content.includes('@fragments-sdk/ui/styles')) {\n return { modified: false, message: `SCSS seeds already configured in ${loc}` };\n }\n\n // Prepend @use to existing file\n const seedContent = generateScssSeedImport(brand);\n const newContent = seedContent + '\\n' + content;\n await writeFile(fullPath, newContent, 'utf-8');\n return { modified: true, message: `Added SCSS seed import to ${loc}` };\n }\n }\n\n // Create new globals.scss in the most common location\n const targetDir = await fileExists(join(root, 'src/app'))\n ? 'src/app'\n : await fileExists(join(root, 'src'))\n ? 'src/styles'\n : 'styles';\n\n const targetPath = join(targetDir, 'globals.scss');\n const fullPath = join(root, targetPath);\n\n await mkdir(dirname(fullPath), { recursive: true });\n await writeFile(fullPath, generateScssSeedImport(brand), 'utf-8');\n return { modified: true, message: `Created ${targetPath} with SCSS seed configuration` };\n}\n\nasync function setupMcpConfig(root: string): Promise<{ modified: boolean; message: string }> {\n // Check common MCP config locations\n const mcpConfigPaths = [\n '.cursor/mcp.json',\n '.vscode/mcp.json',\n ];\n\n for (const configPath of mcpConfigPaths) {\n const fullPath = join(root, configPath);\n if (await fileExists(fullPath)) {\n try {\n const content = await readFile(fullPath, 'utf-8');\n const config = JSON.parse(content);\n const servers = config.mcpServers || {};\n\n // Check if fragments is already configured\n const hasFragments = Object.values(servers).some((server: unknown) => {\n const s = server as { command?: string; args?: string[] };\n return s.args?.some((arg: string) => arg.includes('@fragments-sdk/mcp'));\n });\n\n if (hasFragments) {\n return { modified: false, message: `MCP server already configured in ${configPath}` };\n }\n\n // Add fragments MCP server\n servers.fragments = {\n command: 'npx',\n args: ['@fragments-sdk/mcp'],\n };\n config.mcpServers = servers;\n\n await writeFile(fullPath, JSON.stringify(config, null, 2) + '\\n', 'utf-8');\n return { modified: true, message: `Added Fragments MCP server to ${configPath}` };\n } catch {\n return { modified: false, message: `Could not parse ${configPath}` };\n }\n }\n }\n\n // No existing MCP config — create one for Cursor (most common)\n const cursorDir = join(root, '.cursor');\n const cursorMcpPath = join(cursorDir, 'mcp.json');\n\n await mkdir(cursorDir, { recursive: true });\n const mcpConfig = {\n mcpServers: {\n fragments: {\n command: 'npx',\n args: ['@fragments-sdk/mcp'],\n },\n },\n };\n\n await writeFile(cursorMcpPath, JSON.stringify(mcpConfig, null, 2) + '\\n', 'utf-8');\n return { modified: true, message: 'Created .cursor/mcp.json with Fragments MCP server' };\n}\n\nfunction generateScssSeedImport(brand?: string): string {\n const brandColor = brand || '#0066ff';\n return `@use '@fragments-sdk/ui/styles' with (\n $fui-brand: ${brandColor},\n $fui-neutral: \"stone\",\n $fui-density: \"default\",\n $fui-radius-style: \"rounded\"\n);\n`;\n}\n\n// ============================================\n// Step runner\n// ============================================\n\nasync function runSetupStep(\n fn: () => Promise<{ modified: boolean; message: string }>,\n failureLabel: string,\n actions: string[],\n errors: string[],\n): Promise<void> {\n try {\n const result = await fn();\n const icon = result.modified ? pc.green('+') : pc.dim('·');\n console.log(` ${icon} ${result.message}`);\n if (result.modified) actions.push(result.message);\n } catch (error) {\n const msg = `${failureLabel}: ${error instanceof Error ? error.message : error}`;\n console.log(` ${pc.red('✗')} ${msg}`);\n errors.push(msg);\n }\n}\n\n// ============================================\n// Main Setup Function\n// ============================================\n\nexport async function setup(options: SetupOptions = {}): Promise<SetupResult> {\n const root = resolve(options.root ?? process.cwd());\n const actions: string[] = [];\n const errors: string[] = [];\n\n console.log(pc.cyan(`\\n${BRAND.name} Setup\\n`));\n\n // 1. Detect framework\n const framework = await detectSetupFramework(root);\n const frameworkLabels: Record<string, string> = {\n 'nextjs-app': 'Next.js (App Router)',\n 'nextjs-pages': 'Next.js (Pages Router)',\n 'vite': 'Vite',\n 'remix': 'Remix',\n 'astro': 'Astro',\n };\n const frameworkLabel = frameworkLabels[framework] || 'Unknown';\n\n console.log(` ${pc.dim('Framework:')} ${frameworkLabel}`);\n\n // 2. Find entry file\n const entryFile = await findEntryFile(root, framework);\n if (entryFile) {\n console.log(` ${pc.dim('Entry:')} ${entryFile}`);\n } else {\n console.log(` ${pc.yellow('!')} Could not detect entry file`);\n }\n console.log();\n\n // 3. Add styles import\n if (entryFile) {\n await runSetupStep(() => addStylesImport(root, entryFile), 'Failed to add styles import', actions, errors);\n }\n\n // 4. Add ThemeProvider imports\n if (entryFile) {\n await runSetupStep(() => addThemeProvider(root, entryFile, framework), 'Failed to add ThemeProvider', actions, errors);\n }\n\n // 5. Next.js: add transpilePackages\n if (framework === 'nextjs-app' || framework === 'nextjs-pages') {\n await runSetupStep(() => addTranspilePackages(root), 'Failed to update next.config', actions, errors);\n }\n\n // 6. Create SCSS seeds file (if --scss flag or brand color specified)\n if (options.scss || options.brand) {\n await runSetupStep(() => createScssSeeds(root, options.brand), 'Failed to create SCSS seeds', actions, errors);\n }\n\n // 7. Configure MCP server (if --mcp flag)\n if (options.mcp) {\n await runSetupStep(() => setupMcpConfig(root), 'Failed to configure MCP', actions, errors);\n }\n\n // Summary\n console.log();\n if (errors.length > 0) {\n console.log(pc.red(` ${errors.length} error(s) occurred during setup`));\n } else if (actions.length > 0) {\n console.log(pc.green(` ✓ Setup complete — ${actions.length} file(s) modified`));\n } else {\n console.log(pc.green(' ✓ Already configured — no changes needed'));\n }\n\n // Next steps\n console.log();\n console.log(pc.dim(' Next steps:'));\n if (!options.scss && !options.brand) {\n console.log(pc.dim(' • Run with --scss to add build-time theme seeds'));\n }\n if (!options.mcp) {\n console.log(pc.dim(' • Run with --mcp to configure AI tooling (MCP server)'));\n }\n console.log(pc.dim(' • Run `fragments doctor` to verify your setup'));\n console.log(pc.dim(' • Visit https://usefragments.com/getting-started'));\n console.log();\n\n return {\n success: errors.length === 0,\n actions,\n errors,\n };\n}\n"],"mappings":";;;;;;AAUA,SAAS,UAAU,WAAW,QAAQ,aAAa;AACnD,SAAS,MAAM,SAAS,eAAe;AACvC,OAAO,QAAQ;AAgCf,eAAsB,WAAW,MAAgC;AAC/D,MAAI;AACF,UAAM,OAAO,IAAI;AACjB,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,eAAsB,qBAAqB,MAAkC;AAE3E,MACE,MAAM,WAAW,KAAK,MAAM,gBAAgB,CAAC,KAC7C,MAAM,WAAW,KAAK,MAAM,oBAAoB,CAAC,GACjD;AACA,WAAO;AAAA,EACT;AAGA,MACE,MAAM,WAAW,KAAK,MAAM,gBAAgB,CAAC,KAC7C,MAAM,WAAW,KAAK,MAAM,eAAe,CAAC,GAC5C;AACA,WAAO;AAAA,EACT;AAGA,MACE,MAAM,WAAW,KAAK,MAAM,gBAAgB,CAAC,KAC7C,MAAM,WAAW,KAAK,MAAM,gBAAgB,CAAC,KAC7C,MAAM,WAAW,KAAK,MAAM,iBAAiB,CAAC,GAC9C;AACA,WAAO;AAAA,EACT;AAGA,MACE,MAAM,WAAW,KAAK,MAAM,cAAc,CAAC,KAC3C,MAAM,WAAW,KAAK,MAAM,aAAa,CAAC,GAC1C;AACA,WAAO;AAAA,EACT;AAGA,MACE,MAAM,WAAW,KAAK,MAAM,kBAAkB,CAAC,KAC/C,MAAM,WAAW,KAAK,MAAM,iBAAiB,CAAC,GAC9C;AACA,WAAO;AAAA,EACT;AAGA,MACE,MAAM,WAAW,KAAK,MAAM,gBAAgB,CAAC,KAC7C,MAAM,WAAW,KAAK,MAAM,gBAAgB,CAAC,GAC7C;AACA,WAAO;AAAA,EACT;AAGA,MAAI;AACF,UAAM,UAAU,KAAK,MAAM,cAAc;AACzC,UAAM,aAAa,MAAM,SAAS,SAAS,OAAO;AAClD,UAAM,MAAM,KAAK,MAAM,UAAU;AACjC,UAAM,UAAU,EAAE,GAAG,IAAI,cAAc,GAAG,IAAI,gBAAgB;AAE9D,QAAI,QAAQ,MAAM,EAAG,QAAO;AAC5B,QAAI,QAAQ,kBAAkB,EAAG,QAAO;AACxC,QAAI,QAAQ,OAAO,EAAG,QAAO;AAC7B,QAAI,QAAQ,MAAM,EAAG,QAAO;AAAA,EAC9B,QAAQ;AAAA,EAER;AAEA,SAAO;AACT;AAEA,eAAsB,cAAc,MAAc,WAA8C;AAC9F,QAAM,aAAuB,CAAC;AAE9B,UAAQ,WAAW;AAAA,IACjB,KAAK;AACH,iBAAW;AAAA,QACT;AAAA,QAAsB;AAAA,QACtB;AAAA,QAAqB;AAAA,MACvB;AACA;AAAA,IACF,KAAK;AACH,iBAAW,KAAK,kBAAkB,eAAe;AACjD;AAAA,IACF,KAAK;AACH,iBAAW,KAAK,gBAAgB,aAAa;AAC7C;AAAA,IACF,KAAK;AACH,iBAAW;AAAA,QACT;AAAA,QACA;AAAA,QACA;AAAA,MACF;AACA;AAAA,IACF,KAAK;AACH,iBAAW;AAAA,QACT;AAAA,QAAgB;AAAA,QAChB;AAAA,QAAiB;AAAA,MACnB;AACA;AAAA,IACF;AACE,iBAAW;AAAA,QACT;AAAA,QAAgB;AAAA,QAChB;AAAA,QAAiB;AAAA,QACjB;AAAA,QAAe;AAAA,MACjB;AAAA,EACJ;AAEA,aAAW,aAAa,YAAY;AAClC,QAAI,MAAM,WAAW,KAAK,MAAM,SAAS,CAAC,GAAG;AAC3C,aAAO;AAAA,IACT;AAAA,EACF;AAEA,SAAO;AACT;AAEA,eAAe,eAAe,MAAsC;AAClE,QAAM,aAAa,CAAC,kBAAkB,mBAAmB,gBAAgB;AACzE,aAAW,aAAa,YAAY;AAClC,QAAI,MAAM,WAAW,KAAK,MAAM,SAAS,CAAC,GAAG;AAC3C,aAAO;AAAA,IACT;AAAA,EACF;AACA,SAAO;AACT;AAMA,eAAsB,gBAAgB,MAAc,WAAoE;AACtH,QAAM,WAAW,KAAK,MAAM,SAAS;AACrC,QAAM,UAAU,MAAM,SAAS,UAAU,OAAO;AAEhD,MAAI,QAAQ,SAAS,0BAA0B,GAAG;AAChD,WAAO,EAAE,UAAU,OAAO,SAAS,8BAA8B,SAAS,GAAG;AAAA,EAC/E;AAEA,QAAM,eAAe;AACrB,MAAI;AAGJ,MAAI,UAAU,SAAS,QAAQ,GAAG;AAChC,UAAM,aAAa,QAAQ,QAAQ,KAAK;AACxC,QAAI,eAAe,IAAI;AACrB,YAAM,YAAY,aAAa;AAC/B,mBAAa,QAAQ,MAAM,GAAG,SAAS,IAAI,eAAe,OAAO,QAAQ,MAAM,SAAS;AAAA,IAC1F,OAAO;AAEL,mBAAa;AAAA,EAAQ,YAAY;AAAA;AAAA,EAAU,OAAO;AAAA,IACpD;AAAA,EACF,OAAO;AACL,UAAM,iBAAiB,QAAQ,MAAM,mDAAmD;AAExF,QAAI,kBAAkB,eAAe,SAAS,MAAM;AAClD,YAAM,mBAAmB,QAAQ,QAAQ,MAAM,eAAe,KAAK;AACnE,YAAM,eAAe,qBAAqB,KAAK,QAAQ,SAAS,mBAAmB;AACnF,YAAM,YAAY,qBAAqB,KAAK,OAAO;AACnD,mBAAa,QAAQ,MAAM,GAAG,YAAY,IAAI,YAAY,eAAe,OAAO,QAAQ,MAAM,YAAY;AAAA,IAC5G,OAAO;AACL,mBAAa,eAAe,OAAO;AAAA,IACrC;AAAA,EACF;AAEA,QAAM,UAAU,UAAU,YAAY,OAAO;AAC7C,SAAO,EAAE,UAAU,MAAM,SAAS,0BAA0B,SAAS,GAAG;AAC1E;AAEA,eAAsB,iBAAiB,MAAc,WAAmB,WAAuE;AAC7I,QAAM,WAAW,KAAK,MAAM,SAAS;AACrC,QAAM,UAAU,MAAM,SAAS,UAAU,OAAO;AAEhD,MAAI,QAAQ,SAAS,eAAe,GAAG;AACrC,WAAO,EAAE,UAAU,OAAO,SAAS,oCAAoC,SAAS,GAAG;AAAA,EACrF;AAGA,MAAI,cAAc,SAAS;AACzB,WAAO,EAAE,UAAU,OAAO,SAAS,mGAA8F;AAAA,EACnI;AAGA,QAAM,iBAAiB;AAEvB,MAAI,aAAa;AACjB,QAAM,QAAQ,QAAQ,MAAM,IAAI;AAGhC,MAAI,YAAY;AAChB,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,QAAI,MAAM,CAAC,EAAE,SAAS,0BAA0B,GAAG;AACjD,kBAAY;AACZ;AAAA,IACF;AAAA,EACF;AAGA,MAAI,cAAc,IAAI;AACpB,aAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,UAAI,MAAM,CAAC,EAAE,WAAW,SAAS,KAAK,MAAM,CAAC,EAAE,WAAW,UAAU,KAAK,MAAM,CAAC,EAAE,WAAW,UAAU,GAAG;AACxG,oBAAY;AAAA,MACd;AAAA,IACF;AAAA,EACF;AAEA,MAAI,aAAa,GAAG;AAClB,UAAM,OAAO,YAAY,GAAG,GAAG,cAAc;AAC7C,iBAAa,MAAM,KAAK,IAAI;AAAA,EAC9B,OAAO;AACL,iBAAa,iBAAiB,OAAO;AAAA,EACvC;AAEA,QAAM,UAAU,UAAU,YAAY,OAAO;AAG7C,MAAI,cAAc,cAAc;AAC9B,UAAM,OAAO,CAAC,QAAQ,SAAS,0BAA0B,IACrD;AAAA,uDACA;AACJ,WAAO;AAAA,MACL,UAAU;AAAA,MACV,SAAS,6BAA6B,SAAS;AAAA,sIAC0F,IAAI;AAAA,IAC/I;AAAA,EACF;AAEA,MAAI,cAAc,gBAAgB;AAChC,WAAO;AAAA,MACL,UAAU;AAAA,MACV,SAAS,6BAA6B,SAAS;AAAA;AAAA,IAEjD;AAAA,EACF;AAEA,MAAI,cAAc,SAAS;AACzB,WAAO;AAAA,MACL,UAAU;AAAA,MACV,SAAS,6BAA6B,SAAS;AAAA;AAAA,IAEjD;AAAA,EACF;AAGA,SAAO;AAAA,IACL,UAAU;AAAA,IACV,SAAS,6BAA6B,SAAS;AAAA;AAAA,EAEjD;AACF;AAEA,eAAsB,qBAAqB,MAA+D;AACxG,QAAM,aAAa,MAAM,eAAe,IAAI;AAC5C,MAAI,CAAC,YAAY;AACf,WAAO,EAAE,UAAU,OAAO,SAAS,uBAAuB;AAAA,EAC5D;AAEA,QAAM,WAAW,KAAK,MAAM,UAAU;AACtC,QAAM,UAAU,MAAM,SAAS,UAAU,OAAO;AAEhD,MAAI,QAAQ,SAAS,mBAAmB,KAAK,QAAQ,SAAS,mBAAmB,GAAG;AAClF,WAAO,EAAE,UAAU,OAAO,SAAS,2CAA2C,UAAU,GAAG;AAAA,EAC7F;AAEA,MAAI,QAAQ,SAAS,mBAAmB,GAAG;AAEzC,WAAO;AAAA,MACL,UAAU;AAAA,MACV,SAAS,8BAA8B,UAAU;AAAA,IACnD;AAAA,EACF;AAIA,QAAM,WAAW;AAAA;AAAA,IAEf,EAAE,QAAQ,uCAAuC,aAAa,CAAC,UAAkB,GAAG,KAAK;AAAA,6CAAgD;AAAA;AAAA,IAEzI,EAAE,QAAQ,4BAA4B,aAAa,CAAC,UAAkB,GAAG,KAAK;AAAA,6CAAgD;AAAA;AAAA,IAE9H,EAAE,QAAQ,yBAAyB,aAAa,CAAC,UAAkB,GAAG,KAAK;AAAA,6CAAgD;AAAA,EAC7H;AAEA,aAAW,WAAW,UAAU;AAC9B,QAAI,QAAQ,OAAO,KAAK,OAAO,GAAG;AAChC,YAAM,aAAa,QAAQ,QAAQ,QAAQ,QAAQ,QAAQ,WAAW;AACtE,YAAM,UAAU,UAAU,YAAY,OAAO;AAC7C,aAAO,EAAE,UAAU,MAAM,SAAS,8BAA8B,UAAU,GAAG;AAAA,IAC/E;AAAA,EACF;AAEA,SAAO;AAAA,IACL,UAAU;AAAA,IACV,SAAS,yBAAyB,UAAU;AAAA,EAC9C;AACF;AAEA,eAAe,gBAAgB,MAAc,OAAiE;AAE5G,QAAM,gBAAgB;AAAA,IACpB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAGA,aAAW,OAAO,eAAe;AAC/B,UAAMA,YAAW,KAAK,MAAM,GAAG;AAC/B,QAAI,MAAM,WAAWA,SAAQ,GAAG;AAC9B,YAAM,UAAU,MAAM,SAASA,WAAU,OAAO;AAChD,UAAI,QAAQ,SAAS,0BAA0B,GAAG;AAChD,eAAO,EAAE,UAAU,OAAO,SAAS,oCAAoC,GAAG,GAAG;AAAA,MAC/E;AAGA,YAAM,cAAc,uBAAuB,KAAK;AAChD,YAAM,aAAa,cAAc,OAAO;AACxC,YAAM,UAAUA,WAAU,YAAY,OAAO;AAC7C,aAAO,EAAE,UAAU,MAAM,SAAS,6BAA6B,GAAG,GAAG;AAAA,IACvE;AAAA,EACF;AAGA,QAAM,YAAY,MAAM,WAAW,KAAK,MAAM,SAAS,CAAC,IACpD,YACA,MAAM,WAAW,KAAK,MAAM,KAAK,CAAC,IAChC,eACA;AAEN,QAAM,aAAa,KAAK,WAAW,cAAc;AACjD,QAAM,WAAW,KAAK,MAAM,UAAU;AAEtC,QAAM,MAAM,QAAQ,QAAQ,GAAG,EAAE,WAAW,KAAK,CAAC;AAClD,QAAM,UAAU,UAAU,uBAAuB,KAAK,GAAG,OAAO;AAChE,SAAO,EAAE,UAAU,MAAM,SAAS,WAAW,UAAU,gCAAgC;AACzF;AAEA,eAAe,eAAe,MAA+D;AAE3F,QAAM,iBAAiB;AAAA,IACrB;AAAA,IACA;AAAA,EACF;AAEA,aAAW,cAAc,gBAAgB;AACvC,UAAM,WAAW,KAAK,MAAM,UAAU;AACtC,QAAI,MAAM,WAAW,QAAQ,GAAG;AAC9B,UAAI;AACF,cAAM,UAAU,MAAM,SAAS,UAAU,OAAO;AAChD,cAAM,SAAS,KAAK,MAAM,OAAO;AACjC,cAAM,UAAU,OAAO,cAAc,CAAC;AAGtC,cAAM,eAAe,OAAO,OAAO,OAAO,EAAE,KAAK,CAAC,WAAoB;AACpE,gBAAM,IAAI;AACV,iBAAO,EAAE,MAAM,KAAK,CAAC,QAAgB,IAAI,SAAS,oBAAoB,CAAC;AAAA,QACzE,CAAC;AAED,YAAI,cAAc;AAChB,iBAAO,EAAE,UAAU,OAAO,SAAS,oCAAoC,UAAU,GAAG;AAAA,QACtF;AAGA,gBAAQ,YAAY;AAAA,UAClB,SAAS;AAAA,UACT,MAAM,CAAC,oBAAoB;AAAA,QAC7B;AACA,eAAO,aAAa;AAEpB,cAAM,UAAU,UAAU,KAAK,UAAU,QAAQ,MAAM,CAAC,IAAI,MAAM,OAAO;AACzE,eAAO,EAAE,UAAU,MAAM,SAAS,iCAAiC,UAAU,GAAG;AAAA,MAClF,QAAQ;AACN,eAAO,EAAE,UAAU,OAAO,SAAS,mBAAmB,UAAU,GAAG;AAAA,MACrE;AAAA,IACF;AAAA,EACF;AAGA,QAAM,YAAY,KAAK,MAAM,SAAS;AACtC,QAAM,gBAAgB,KAAK,WAAW,UAAU;AAEhD,QAAM,MAAM,WAAW,EAAE,WAAW,KAAK,CAAC;AAC1C,QAAM,YAAY;AAAA,IAChB,YAAY;AAAA,MACV,WAAW;AAAA,QACT,SAAS;AAAA,QACT,MAAM,CAAC,oBAAoB;AAAA,MAC7B;AAAA,IACF;AAAA,EACF;AAEA,QAAM,UAAU,eAAe,KAAK,UAAU,WAAW,MAAM,CAAC,IAAI,MAAM,OAAO;AACjF,SAAO,EAAE,UAAU,MAAM,SAAS,qDAAqD;AACzF;AAEA,SAAS,uBAAuB,OAAwB;AACtD,QAAM,aAAa,SAAS;AAC5B,SAAO;AAAA,gBACO,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAM1B;AAMA,eAAe,aACb,IACA,cACA,SACA,QACe;AACf,MAAI;AACF,UAAM,SAAS,MAAM,GAAG;AACxB,UAAM,OAAO,OAAO,WAAW,GAAG,MAAM,GAAG,IAAI,GAAG,IAAI,MAAG;AACzD,YAAQ,IAAI,KAAK,IAAI,IAAI,OAAO,OAAO,EAAE;AACzC,QAAI,OAAO,SAAU,SAAQ,KAAK,OAAO,OAAO;AAAA,EAClD,SAAS,OAAO;AACd,UAAM,MAAM,GAAG,YAAY,KAAK,iBAAiB,QAAQ,MAAM,UAAU,KAAK;AAC9E,YAAQ,IAAI,KAAK,GAAG,IAAI,QAAG,CAAC,IAAI,GAAG,EAAE;AACrC,WAAO,KAAK,GAAG;AAAA,EACjB;AACF;AAMA,eAAsB,MAAM,UAAwB,CAAC,GAAyB;AAC5E,QAAM,OAAO,QAAQ,QAAQ,QAAQ,QAAQ,IAAI,CAAC;AAClD,QAAM,UAAoB,CAAC;AAC3B,QAAM,SAAmB,CAAC;AAE1B,UAAQ,IAAI,GAAG,KAAK;AAAA,EAAK,MAAM,IAAI;AAAA,CAAU,CAAC;AAG9C,QAAM,YAAY,MAAM,qBAAqB,IAAI;AACjD,QAAM,kBAA0C;AAAA,IAC9C,cAAc;AAAA,IACd,gBAAgB;AAAA,IAChB,QAAQ;AAAA,IACR,SAAS;AAAA,IACT,SAAS;AAAA,EACX;AACA,QAAM,iBAAiB,gBAAgB,SAAS,KAAK;AAErD,UAAQ,IAAI,KAAK,GAAG,IAAI,YAAY,CAAC,IAAI,cAAc,EAAE;AAGzD,QAAM,YAAY,MAAM,cAAc,MAAM,SAAS;AACrD,MAAI,WAAW;AACb,YAAQ,IAAI,KAAK,GAAG,IAAI,QAAQ,CAAC,IAAI,SAAS,EAAE;AAAA,EAClD,OAAO;AACL,YAAQ,IAAI,KAAK,GAAG,OAAO,GAAG,CAAC,8BAA8B;AAAA,EAC/D;AACA,UAAQ,IAAI;AAGZ,MAAI,WAAW;AACb,UAAM,aAAa,MAAM,gBAAgB,MAAM,SAAS,GAAG,+BAA+B,SAAS,MAAM;AAAA,EAC3G;AAGA,MAAI,WAAW;AACb,UAAM,aAAa,MAAM,iBAAiB,MAAM,WAAW,SAAS,GAAG,+BAA+B,SAAS,MAAM;AAAA,EACvH;AAGA,MAAI,cAAc,gBAAgB,cAAc,gBAAgB;AAC9D,UAAM,aAAa,MAAM,qBAAqB,IAAI,GAAG,gCAAgC,SAAS,MAAM;AAAA,EACtG;AAGA,MAAI,QAAQ,QAAQ,QAAQ,OAAO;AACjC,UAAM,aAAa,MAAM,gBAAgB,MAAM,QAAQ,KAAK,GAAG,+BAA+B,SAAS,MAAM;AAAA,EAC/G;AAGA,MAAI,QAAQ,KAAK;AACf,UAAM,aAAa,MAAM,eAAe,IAAI,GAAG,2BAA2B,SAAS,MAAM;AAAA,EAC3F;AAGA,UAAQ,IAAI;AACZ,MAAI,OAAO,SAAS,GAAG;AACrB,YAAQ,IAAI,GAAG,IAAI,KAAK,OAAO,MAAM,iCAAiC,CAAC;AAAA,EACzE,WAAW,QAAQ,SAAS,GAAG;AAC7B,YAAQ,IAAI,GAAG,MAAM,kCAAwB,QAAQ,MAAM,mBAAmB,CAAC;AAAA,EACjF,OAAO;AACL,YAAQ,IAAI,GAAG,MAAM,sDAA4C,CAAC;AAAA,EACpE;AAGA,UAAQ,IAAI;AACZ,UAAQ,IAAI,GAAG,IAAI,eAAe,CAAC;AACnC,MAAI,CAAC,QAAQ,QAAQ,CAAC,QAAQ,OAAO;AACnC,YAAQ,IAAI,GAAG,IAAI,0DAAqD,CAAC;AAAA,EAC3E;AACA,MAAI,CAAC,QAAQ,KAAK;AAChB,YAAQ,IAAI,GAAG,IAAI,gEAA2D,CAAC;AAAA,EACjF;AACA,UAAQ,IAAI,GAAG,IAAI,wDAAmD,CAAC;AACvE,UAAQ,IAAI,GAAG,IAAI,2DAAsD,CAAC;AAC1E,UAAQ,IAAI;AAEZ,SAAO;AAAA,IACL,SAAS,OAAO,WAAW;AAAA,IAC3B;AAAA,IACA;AAAA,EACF;AACF;","names":["fullPath"]}