galaxy-design 0.2.73 → 0.2.74

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 (50) hide show
  1. package/README.md +113 -95
  2. package/dist/bin.js +17 -1
  3. package/dist/bin.js.map +1 -1
  4. package/dist/commands/add.js +59 -99
  5. package/dist/commands/add.js.map +1 -1
  6. package/dist/commands/init.js +120 -611
  7. package/dist/commands/init.js.map +1 -1
  8. package/dist/commands/migrate-tailwind.js +90 -0
  9. package/dist/commands/migrate-tailwind.js.map +1 -0
  10. package/dist/index.js +6 -1
  11. package/dist/index.js.map +1 -1
  12. package/dist/registries/registry-angular.json +145 -537
  13. package/dist/registry-angular.json +145 -537
  14. package/dist/schemas/components-schema.json +66 -11
  15. package/dist/schemas/registry-framework-schema.json +17 -7
  16. package/dist/utils/angular-provider-manager.js +1 -1
  17. package/dist/utils/angular-provider-manager.js.map +1 -1
  18. package/dist/utils/component-copier.js +102 -62
  19. package/dist/utils/component-copier.js.map +1 -1
  20. package/dist/utils/component-transformer.js +86 -16
  21. package/dist/utils/component-transformer.js.map +1 -1
  22. package/dist/utils/config-schema.js +160 -9
  23. package/dist/utils/config-schema.js.map +1 -1
  24. package/dist/utils/framework-registry-service.js +181 -0
  25. package/dist/utils/framework-registry-service.js.map +1 -0
  26. package/dist/utils/framework-registry.js +1 -138
  27. package/dist/utils/framework-registry.js.map +1 -1
  28. package/dist/utils/github-fetcher.js +55 -27
  29. package/dist/utils/github-fetcher.js.map +1 -1
  30. package/dist/utils/index.js +4 -3
  31. package/dist/utils/index.js.map +1 -1
  32. package/dist/utils/init-runtime.js +477 -0
  33. package/dist/utils/init-runtime.js.map +1 -0
  34. package/dist/utils/init-scaffold.js +115 -0
  35. package/dist/utils/init-scaffold.js.map +1 -0
  36. package/dist/utils/init-workflow.js +189 -0
  37. package/dist/utils/init-workflow.js.map +1 -0
  38. package/dist/utils/package-manager.js +77 -2
  39. package/dist/utils/package-manager.js.map +1 -1
  40. package/dist/utils/platform-detector.js +12 -8
  41. package/dist/utils/platform-detector.js.map +1 -1
  42. package/dist/utils/registry-loader.js +20 -41
  43. package/dist/utils/registry-loader.js.map +1 -1
  44. package/dist/utils/tailwind-detector.js +162 -0
  45. package/dist/utils/tailwind-detector.js.map +1 -0
  46. package/dist/utils/tailwind-migration.js +401 -0
  47. package/dist/utils/tailwind-migration.js.map +1 -0
  48. package/dist/utils/tailwind-scaffold.js +398 -0
  49. package/dist/utils/tailwind-scaffold.js.map +1 -0
  50. package/package.json +20 -2
@@ -0,0 +1,477 @@
1
+ import { existsSync, readFileSync, writeFileSync } from 'fs';
2
+ import { dirname, relative, resolve } from 'path';
3
+ import { writeFile } from './files.js';
4
+ import { scaffoldTailwindFiles } from './tailwind-scaffold.js';
5
+ export function scaffoldInitFrameworkRuntime(options) {
6
+ if (options.framework === 'flutter') {
7
+ return null;
8
+ }
9
+ if (options.framework === 'react-native') {
10
+ return configureReactNativeRuntime({
11
+ cwd: options.cwd,
12
+ cssPath: options.cssPath,
13
+ tailwindConfigPath: options.tailwindConfigPath || 'tailwind.config.js',
14
+ baseColor: options.baseColor,
15
+ usesSrcDir: options.usesSrcDir,
16
+ isExpo: options.isExpoProject
17
+ });
18
+ }
19
+ return scaffoldTailwindFiles({
20
+ cwd: options.cwd,
21
+ framework: options.framework,
22
+ mode: options.tailwindMode || 'v4',
23
+ configPath: options.tailwindConfigPath,
24
+ cssPath: options.cssPath,
25
+ baseColor: options.baseColor,
26
+ overwriteExisting: false
27
+ });
28
+ }
29
+ export function configureReactNativeRuntime(options) {
30
+ const result = {
31
+ written: [],
32
+ skipped: []
33
+ };
34
+ ensureReactNativeStylesheet(options.cwd, options.cssPath, options.baseColor, result);
35
+ writeRuntimeFileIfNeeded(options.cwd, options.tailwindConfigPath, getReactNativeTailwindConfigContent(options.usesSrcDir), result);
36
+ writeRuntimeFileIfNeeded(options.cwd, 'metro.config.js', getReactNativeMetroConfigContent(options.cssPath, options.isExpo), result);
37
+ ensureReactNativeBabelConfig(options.cwd, options.usesSrcDir, options.isExpo, result);
38
+ ensureEntryImportsStylesheet(options.cwd, options.cssPath, result);
39
+ return result;
40
+ }
41
+ function writeRuntimeFileIfNeeded(cwd, relativePath, content, result) {
42
+ const filePath = resolve(cwd, relativePath);
43
+ if (existsSync(filePath)) {
44
+ result.skipped.push(relativePath);
45
+ return;
46
+ }
47
+ writeFile(filePath, content);
48
+ result.written.push(relativePath);
49
+ }
50
+ function ensureReactNativeStylesheet(cwd, cssPath, baseColor, result) {
51
+ const filePath = resolve(cwd, cssPath);
52
+ const cssContent = getReactNativeCssContent(baseColor);
53
+ if (!existsSync(filePath)) {
54
+ writeFile(filePath, cssContent);
55
+ result.written.push(cssPath);
56
+ return;
57
+ }
58
+ const existingContent = readFileSync(filePath, 'utf-8');
59
+ if (/@tailwind\s+(base|components|utilities)/.test(existingContent)) {
60
+ result.skipped.push(cssPath);
61
+ return;
62
+ }
63
+ writeFileSync(filePath, `${cssContent}\n${existingContent}`.trimEnd() + '\n', 'utf-8');
64
+ result.written.push(cssPath);
65
+ }
66
+ function ensureReactNativeBabelConfig(cwd, usesSrcDir, isExpo, result) {
67
+ const relativePath = 'babel.config.js';
68
+ const filePath = resolve(cwd, relativePath);
69
+ const aliasTarget = usesSrcDir ? './src' : './';
70
+ if (!existsSync(filePath)) {
71
+ writeFile(filePath, getReactNativeBabelConfigContent(aliasTarget, isExpo));
72
+ result.written.push(relativePath);
73
+ return;
74
+ }
75
+ let content = readFileSync(filePath, 'utf-8');
76
+ const original = content;
77
+ if (!content.includes('nativewind/babel') && /plugins\s*:\s*\[/.test(content)) {
78
+ content = content.replace(/plugins\s*:\s*\[/, `plugins: [\n ["module-resolver", {\n alias: {\n "@": "${aliasTarget}"\n }\n }],\n "nativewind/babel",`);
79
+ } else if (!content.includes('module-resolver') && /plugins\s*:\s*\[/.test(content)) {
80
+ content = content.replace(/plugins\s*:\s*\[/, `plugins: [\n ["module-resolver", {\n alias: {\n "@": "${aliasTarget}"\n }\n }],`);
81
+ }
82
+ if (content !== original) {
83
+ writeFileSync(filePath, content, 'utf-8');
84
+ result.written.push(relativePath);
85
+ } else {
86
+ result.skipped.push(relativePath);
87
+ }
88
+ }
89
+ function ensureEntryImportsStylesheet(cwd, cssPath, result) {
90
+ const entryCandidates = [
91
+ 'app/_layout.tsx',
92
+ 'app/_layout.jsx',
93
+ 'app/_layout.ts',
94
+ 'app/_layout.js',
95
+ 'App.tsx',
96
+ 'App.jsx',
97
+ 'App.ts',
98
+ 'App.js',
99
+ 'index.ts',
100
+ 'index.js'
101
+ ];
102
+ const entryFile = entryCandidates.find((candidate)=>existsSync(resolve(cwd, candidate)));
103
+ if (!entryFile) {
104
+ result.skipped.push('entry:global.css import');
105
+ return;
106
+ }
107
+ const entryPath = resolve(cwd, entryFile);
108
+ const importPath = normalizeImportPath(relative(dirname(entryPath), resolve(cwd, cssPath)));
109
+ const importStatement = `import '${importPath}';`;
110
+ const content = readFileSync(entryPath, 'utf-8');
111
+ if (content.includes(importStatement)) {
112
+ result.skipped.push(entryFile);
113
+ return;
114
+ }
115
+ writeFileSync(entryPath, `${importStatement}\n${content}`, 'utf-8');
116
+ result.written.push(entryFile);
117
+ }
118
+ function normalizeImportPath(importPath) {
119
+ const normalized = importPath.replace(/\\/g, '/');
120
+ if (normalized.startsWith('.')) {
121
+ return normalized;
122
+ }
123
+ return `./${normalized}`;
124
+ }
125
+ function getReactNativeBabelConfigContent(aliasTarget, isExpo) {
126
+ const preset = isExpo ? 'babel-preset-expo' : 'module:@react-native/babel-preset';
127
+ return `module.exports = function (api) {
128
+ api.cache(true);
129
+ return {
130
+ presets: ["${preset}"],
131
+ plugins: [
132
+ ["module-resolver", {
133
+ alias: {
134
+ "@": "${aliasTarget}"
135
+ }
136
+ }],
137
+ "nativewind/babel"
138
+ ],
139
+ };
140
+ };
141
+ `;
142
+ }
143
+ function getReactNativeMetroConfigContent(cssPath, isExpo) {
144
+ if (isExpo) {
145
+ return `const { getDefaultConfig } = require("expo/metro-config");
146
+ const { withNativeWind } = require("nativewind/metro");
147
+
148
+ const config = getDefaultConfig(__dirname);
149
+
150
+ module.exports = withNativeWind(config, {
151
+ input: "./${cssPath}",
152
+ });
153
+ `;
154
+ }
155
+ return `const { getDefaultConfig, mergeConfig } = require("@react-native/metro-config");
156
+ const { withNativeWind } = require("nativewind/metro");
157
+
158
+ const config = mergeConfig(getDefaultConfig(__dirname), {});
159
+
160
+ module.exports = withNativeWind(config, {
161
+ input: "./${cssPath}",
162
+ });
163
+ `;
164
+ }
165
+ function getReactNativeTailwindConfigContent(usesSrcDir) {
166
+ const contentPath = usesSrcDir ? './src/**/*.{js,jsx,ts,tsx}' : './**/*.{js,jsx,ts,tsx}';
167
+ return `/** @type {import('tailwindcss').Config} */
168
+ module.exports = {
169
+ content: [
170
+ "./App.{js,jsx,ts,tsx}",
171
+ "./app/**/*.{js,jsx,ts,tsx}",
172
+ "${contentPath}",
173
+ ],
174
+ presets: [require("nativewind/preset")],
175
+ theme: {
176
+ extend: {
177
+ colors: {
178
+ border: "hsl(var(--border))",
179
+ input: "hsl(var(--input))",
180
+ ring: "hsl(var(--ring))",
181
+ background: "hsl(var(--background))",
182
+ foreground: "hsl(var(--foreground))",
183
+ primary: {
184
+ DEFAULT: "hsl(var(--primary))",
185
+ foreground: "hsl(var(--primary-foreground))",
186
+ },
187
+ secondary: {
188
+ DEFAULT: "hsl(var(--secondary))",
189
+ foreground: "hsl(var(--secondary-foreground))",
190
+ },
191
+ destructive: {
192
+ DEFAULT: "hsl(var(--destructive))",
193
+ foreground: "hsl(var(--destructive-foreground))",
194
+ },
195
+ muted: {
196
+ DEFAULT: "hsl(var(--muted))",
197
+ foreground: "hsl(var(--muted-foreground))",
198
+ },
199
+ accent: {
200
+ DEFAULT: "hsl(var(--accent))",
201
+ foreground: "hsl(var(--accent-foreground))",
202
+ },
203
+ popover: {
204
+ DEFAULT: "hsl(var(--popover))",
205
+ foreground: "hsl(var(--popover-foreground))",
206
+ },
207
+ card: {
208
+ DEFAULT: "hsl(var(--card))",
209
+ foreground: "hsl(var(--card-foreground))",
210
+ },
211
+ },
212
+ borderRadius: {
213
+ lg: "var(--radius)",
214
+ md: "calc(var(--radius) - 2px)",
215
+ sm: "calc(var(--radius) - 4px)",
216
+ },
217
+ },
218
+ },
219
+ plugins: [],
220
+ };
221
+ `;
222
+ }
223
+ function getReactNativeCssContent(baseColor) {
224
+ return getReactNativeColorVariableBlock(baseColor);
225
+ }
226
+ function getReactNativeColorVariableBlock(baseColor) {
227
+ const blocks = {
228
+ slate: `@tailwind base;
229
+ @tailwind components;
230
+ @tailwind utilities;
231
+
232
+ :root {
233
+ --background: 0 0% 100%;
234
+ --foreground: 222.2 84% 4.9%;
235
+ --card: 0 0% 100%;
236
+ --card-foreground: 222.2 84% 4.9%;
237
+ --popover: 0 0% 100%;
238
+ --popover-foreground: 222.2 84% 4.9%;
239
+ --primary: 222.2 47.4% 11.2%;
240
+ --primary-foreground: 210 40% 98%;
241
+ --secondary: 210 40% 96.1%;
242
+ --secondary-foreground: 222.2 47.4% 11.2%;
243
+ --muted: 210 40% 96.1%;
244
+ --muted-foreground: 215.4 16.3% 46.9%;
245
+ --accent: 210 40% 96.1%;
246
+ --accent-foreground: 222.2 47.4% 11.2%;
247
+ --destructive: 0 84.2% 60.2%;
248
+ --destructive-foreground: 210 40% 98%;
249
+ --border: 214.3 31.8% 91.4%;
250
+ --input: 214.3 31.8% 91.4%;
251
+ --ring: 222.2 84% 4.9%;
252
+ --radius: 0.5rem;
253
+ }
254
+
255
+ .dark {
256
+ --background: 222.2 84% 4.9%;
257
+ --foreground: 210 40% 98%;
258
+ --card: 222.2 84% 4.9%;
259
+ --card-foreground: 210 40% 98%;
260
+ --popover: 222.2 84% 4.9%;
261
+ --popover-foreground: 210 40% 98%;
262
+ --primary: 210 40% 98%;
263
+ --primary-foreground: 222.2 47.4% 11.2%;
264
+ --secondary: 217.2 32.6% 17.5%;
265
+ --secondary-foreground: 210 40% 98%;
266
+ --muted: 217.2 32.6% 17.5%;
267
+ --muted-foreground: 215 20.2% 65.1%;
268
+ --accent: 217.2 32.6% 17.5%;
269
+ --accent-foreground: 210 40% 98%;
270
+ --destructive: 0 62.8% 30.6%;
271
+ --destructive-foreground: 210 40% 98%;
272
+ --border: 217.2 32.6% 17.5%;
273
+ --input: 217.2 32.6% 17.5%;
274
+ --ring: 212.7 26.8% 83.9%;
275
+ }
276
+ `,
277
+ gray: `@tailwind base;
278
+ @tailwind components;
279
+ @tailwind utilities;
280
+
281
+ :root {
282
+ --background: 0 0% 100%;
283
+ --foreground: 224 71.4% 4.1%;
284
+ --card: 0 0% 100%;
285
+ --card-foreground: 224 71.4% 4.1%;
286
+ --popover: 0 0% 100%;
287
+ --popover-foreground: 224 71.4% 4.1%;
288
+ --primary: 220.9 39.3% 11%;
289
+ --primary-foreground: 210 20% 98%;
290
+ --secondary: 220 14.3% 95.9%;
291
+ --secondary-foreground: 220.9 39.3% 11%;
292
+ --muted: 220 14.3% 95.9%;
293
+ --muted-foreground: 220 8.9% 46.1%;
294
+ --accent: 220 14.3% 95.9%;
295
+ --accent-foreground: 220.9 39.3% 11%;
296
+ --destructive: 0 84.2% 60.2%;
297
+ --destructive-foreground: 210 20% 98%;
298
+ --border: 220 13% 91%;
299
+ --input: 220 13% 91%;
300
+ --ring: 224 71.4% 4.1%;
301
+ --radius: 0.5rem;
302
+ }
303
+
304
+ .dark {
305
+ --background: 224 71.4% 4.1%;
306
+ --foreground: 210 20% 98%;
307
+ --card: 224 71.4% 4.1%;
308
+ --card-foreground: 210 20% 98%;
309
+ --popover: 224 71.4% 4.1%;
310
+ --popover-foreground: 210 20% 98%;
311
+ --primary: 210 20% 98%;
312
+ --primary-foreground: 220.9 39.3% 11%;
313
+ --secondary: 215 27.9% 16.9%;
314
+ --secondary-foreground: 210 20% 98%;
315
+ --muted: 215 27.9% 16.9%;
316
+ --muted-foreground: 217.9 10.6% 64.9%;
317
+ --accent: 215 27.9% 16.9%;
318
+ --accent-foreground: 210 20% 98%;
319
+ --destructive: 0 62.8% 30.6%;
320
+ --destructive-foreground: 210 20% 98%;
321
+ --border: 215 27.9% 16.9%;
322
+ --input: 215 27.9% 16.9%;
323
+ --ring: 216 12.2% 83.9%;
324
+ }
325
+ `,
326
+ zinc: `@tailwind base;
327
+ @tailwind components;
328
+ @tailwind utilities;
329
+
330
+ :root {
331
+ --background: 0 0% 100%;
332
+ --foreground: 240 10% 3.9%;
333
+ --card: 0 0% 100%;
334
+ --card-foreground: 240 10% 3.9%;
335
+ --popover: 0 0% 100%;
336
+ --popover-foreground: 240 10% 3.9%;
337
+ --primary: 240 5.9% 10%;
338
+ --primary-foreground: 0 0% 98%;
339
+ --secondary: 240 4.8% 95.9%;
340
+ --secondary-foreground: 240 5.9% 10%;
341
+ --muted: 240 4.8% 95.9%;
342
+ --muted-foreground: 240 3.8% 46.1%;
343
+ --accent: 240 4.8% 95.9%;
344
+ --accent-foreground: 240 5.9% 10%;
345
+ --destructive: 0 84.2% 60.2%;
346
+ --destructive-foreground: 0 0% 98%;
347
+ --border: 240 5.9% 90%;
348
+ --input: 240 5.9% 90%;
349
+ --ring: 240 10% 3.9%;
350
+ --radius: 0.5rem;
351
+ }
352
+
353
+ .dark {
354
+ --background: 240 10% 3.9%;
355
+ --foreground: 0 0% 98%;
356
+ --card: 240 10% 3.9%;
357
+ --card-foreground: 0 0% 98%;
358
+ --popover: 240 10% 3.9%;
359
+ --popover-foreground: 0 0% 98%;
360
+ --primary: 0 0% 98%;
361
+ --primary-foreground: 240 5.9% 10%;
362
+ --secondary: 240 3.7% 15.9%;
363
+ --secondary-foreground: 0 0% 98%;
364
+ --muted: 240 3.7% 15.9%;
365
+ --muted-foreground: 240 5% 64.9%;
366
+ --accent: 240 3.7% 15.9%;
367
+ --accent-foreground: 0 0% 98%;
368
+ --destructive: 0 62.8% 30.6%;
369
+ --destructive-foreground: 0 0% 98%;
370
+ --border: 240 3.7% 15.9%;
371
+ --input: 240 3.7% 15.9%;
372
+ --ring: 240 4.9% 83.9%;
373
+ }
374
+ `,
375
+ neutral: `@tailwind base;
376
+ @tailwind components;
377
+ @tailwind utilities;
378
+
379
+ :root {
380
+ --background: 0 0% 100%;
381
+ --foreground: 0 0% 3.9%;
382
+ --card: 0 0% 100%;
383
+ --card-foreground: 0 0% 3.9%;
384
+ --popover: 0 0% 100%;
385
+ --popover-foreground: 0 0% 3.9%;
386
+ --primary: 0 0% 9%;
387
+ --primary-foreground: 0 0% 98%;
388
+ --secondary: 0 0% 96.1%;
389
+ --secondary-foreground: 0 0% 9%;
390
+ --muted: 0 0% 96.1%;
391
+ --muted-foreground: 0 0% 45.1%;
392
+ --accent: 0 0% 96.1%;
393
+ --accent-foreground: 0 0% 9%;
394
+ --destructive: 0 84.2% 60.2%;
395
+ --destructive-foreground: 0 0% 98%;
396
+ --border: 0 0% 89.8%;
397
+ --input: 0 0% 89.8%;
398
+ --ring: 0 0% 3.9%;
399
+ --radius: 0.5rem;
400
+ }
401
+
402
+ .dark {
403
+ --background: 0 0% 3.9%;
404
+ --foreground: 0 0% 98%;
405
+ --card: 0 0% 3.9%;
406
+ --card-foreground: 0 0% 98%;
407
+ --popover: 0 0% 3.9%;
408
+ --popover-foreground: 0 0% 98%;
409
+ --primary: 0 0% 98%;
410
+ --primary-foreground: 0 0% 9%;
411
+ --secondary: 0 0% 14.9%;
412
+ --secondary-foreground: 0 0% 98%;
413
+ --muted: 0 0% 14.9%;
414
+ --muted-foreground: 0 0% 63.9%;
415
+ --accent: 0 0% 14.9%;
416
+ --accent-foreground: 0 0% 98%;
417
+ --destructive: 0 62.8% 30.6%;
418
+ --destructive-foreground: 0 0% 98%;
419
+ --border: 0 0% 14.9%;
420
+ --input: 0 0% 14.9%;
421
+ --ring: 0 0% 83.1%;
422
+ }
423
+ `,
424
+ stone: `@tailwind base;
425
+ @tailwind components;
426
+ @tailwind utilities;
427
+
428
+ :root {
429
+ --background: 0 0% 100%;
430
+ --foreground: 20 14.3% 4.1%;
431
+ --card: 0 0% 100%;
432
+ --card-foreground: 20 14.3% 4.1%;
433
+ --popover: 0 0% 100%;
434
+ --popover-foreground: 20 14.3% 4.1%;
435
+ --primary: 24 9.8% 10%;
436
+ --primary-foreground: 60 9.1% 97.8%;
437
+ --secondary: 60 4.8% 95.9%;
438
+ --secondary-foreground: 24 9.8% 10%;
439
+ --muted: 60 4.8% 95.9%;
440
+ --muted-foreground: 25 5.3% 44.7%;
441
+ --accent: 60 4.8% 95.9%;
442
+ --accent-foreground: 24 9.8% 10%;
443
+ --destructive: 0 84.2% 60.2%;
444
+ --destructive-foreground: 60 9.1% 97.8%;
445
+ --border: 20 5.9% 90%;
446
+ --input: 20 5.9% 90%;
447
+ --ring: 20 14.3% 4.1%;
448
+ --radius: 0.5rem;
449
+ }
450
+
451
+ .dark {
452
+ --background: 20 14.3% 4.1%;
453
+ --foreground: 60 9.1% 97.8%;
454
+ --card: 20 14.3% 4.1%;
455
+ --card-foreground: 60 9.1% 97.8%;
456
+ --popover: 20 14.3% 4.1%;
457
+ --popover-foreground: 60 9.1% 97.8%;
458
+ --primary: 60 9.1% 97.8%;
459
+ --primary-foreground: 24 9.8% 10%;
460
+ --secondary: 12 6.5% 15.1%;
461
+ --secondary-foreground: 60 9.1% 97.8%;
462
+ --muted: 12 6.5% 15.1%;
463
+ --muted-foreground: 24 5.4% 63.9%;
464
+ --accent: 12 6.5% 15.1%;
465
+ --accent-foreground: 60 9.1% 97.8%;
466
+ --destructive: 0 62.8% 30.6%;
467
+ --destructive-foreground: 60 9.1% 97.8%;
468
+ --border: 12 6.5% 15.1%;
469
+ --input: 12 6.5% 15.1%;
470
+ --ring: 24 5.7% 82.9%;
471
+ }
472
+ `
473
+ };
474
+ return blocks[baseColor];
475
+ }
476
+
477
+ //# sourceMappingURL=init-runtime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/utils/init-runtime.ts"],"sourcesContent":["import { existsSync, readFileSync, writeFileSync } from 'fs';\nimport { dirname, relative, resolve } from 'path';\nimport { writeFile } from './files.js';\nimport {\n scaffoldTailwindFiles,\n type TailwindMode,\n type TailwindScaffoldResult,\n} from './tailwind-scaffold.js';\nimport type { BaseColor, Framework } from './config-schema.js';\n\nexport interface ReactNativeRuntimeOptions {\n cwd: string;\n cssPath: string;\n tailwindConfigPath: string;\n baseColor: BaseColor;\n usesSrcDir: boolean;\n isExpo: boolean;\n}\n\nexport interface RuntimeScaffoldResult {\n written: string[];\n skipped: string[];\n}\n\nexport function scaffoldInitFrameworkRuntime(options: {\n cwd: string;\n framework: Framework;\n tailwindMode: TailwindMode | null;\n cssPath: string;\n tailwindConfigPath: string;\n baseColor: BaseColor;\n usesSrcDir: boolean;\n isExpoProject: boolean;\n}): RuntimeScaffoldResult | TailwindScaffoldResult | null {\n if (options.framework === 'flutter') {\n return null;\n }\n\n if (options.framework === 'react-native') {\n return configureReactNativeRuntime({\n cwd: options.cwd,\n cssPath: options.cssPath,\n tailwindConfigPath: options.tailwindConfigPath || 'tailwind.config.js',\n baseColor: options.baseColor,\n usesSrcDir: options.usesSrcDir,\n isExpo: options.isExpoProject,\n });\n }\n\n return scaffoldTailwindFiles({\n cwd: options.cwd,\n framework: options.framework,\n mode: options.tailwindMode || 'v4',\n configPath: options.tailwindConfigPath,\n cssPath: options.cssPath,\n baseColor: options.baseColor,\n overwriteExisting: false,\n });\n}\n\nexport function configureReactNativeRuntime(\n options: ReactNativeRuntimeOptions,\n): RuntimeScaffoldResult {\n const result: RuntimeScaffoldResult = {\n written: [],\n skipped: [],\n };\n\n ensureReactNativeStylesheet(\n options.cwd,\n options.cssPath,\n options.baseColor,\n result,\n );\n writeRuntimeFileIfNeeded(\n options.cwd,\n options.tailwindConfigPath,\n getReactNativeTailwindConfigContent(options.usesSrcDir),\n result,\n );\n writeRuntimeFileIfNeeded(\n options.cwd,\n 'metro.config.js',\n getReactNativeMetroConfigContent(options.cssPath, options.isExpo),\n result,\n );\n ensureReactNativeBabelConfig(\n options.cwd,\n options.usesSrcDir,\n options.isExpo,\n result,\n );\n ensureEntryImportsStylesheet(options.cwd, options.cssPath, result);\n\n return result;\n}\n\nfunction writeRuntimeFileIfNeeded(\n cwd: string,\n relativePath: string,\n content: string,\n result: RuntimeScaffoldResult,\n): void {\n const filePath = resolve(cwd, relativePath);\n if (existsSync(filePath)) {\n result.skipped.push(relativePath);\n return;\n }\n\n writeFile(filePath, content);\n result.written.push(relativePath);\n}\n\nfunction ensureReactNativeStylesheet(\n cwd: string,\n cssPath: string,\n baseColor: BaseColor,\n result: RuntimeScaffoldResult,\n): void {\n const filePath = resolve(cwd, cssPath);\n const cssContent = getReactNativeCssContent(baseColor);\n\n if (!existsSync(filePath)) {\n writeFile(filePath, cssContent);\n result.written.push(cssPath);\n return;\n }\n\n const existingContent = readFileSync(filePath, 'utf-8');\n if (/@tailwind\\s+(base|components|utilities)/.test(existingContent)) {\n result.skipped.push(cssPath);\n return;\n }\n\n writeFileSync(\n filePath,\n `${cssContent}\\n${existingContent}`.trimEnd() + '\\n',\n 'utf-8',\n );\n result.written.push(cssPath);\n}\n\nfunction ensureReactNativeBabelConfig(\n cwd: string,\n usesSrcDir: boolean,\n isExpo: boolean,\n result: RuntimeScaffoldResult,\n): void {\n const relativePath = 'babel.config.js';\n const filePath = resolve(cwd, relativePath);\n const aliasTarget = usesSrcDir ? './src' : './';\n\n if (!existsSync(filePath)) {\n writeFile(filePath, getReactNativeBabelConfigContent(aliasTarget, isExpo));\n result.written.push(relativePath);\n return;\n }\n\n let content = readFileSync(filePath, 'utf-8');\n const original = content;\n\n if (\n !content.includes('nativewind/babel') &&\n /plugins\\s*:\\s*\\[/.test(content)\n ) {\n content = content.replace(\n /plugins\\s*:\\s*\\[/,\n `plugins: [\\n [\"module-resolver\", {\\n alias: {\\n \"@\": \"${aliasTarget}\"\\n }\\n }],\\n \"nativewind/babel\",`,\n );\n } else if (\n !content.includes('module-resolver') &&\n /plugins\\s*:\\s*\\[/.test(content)\n ) {\n content = content.replace(\n /plugins\\s*:\\s*\\[/,\n `plugins: [\\n [\"module-resolver\", {\\n alias: {\\n \"@\": \"${aliasTarget}\"\\n }\\n }],`,\n );\n }\n\n if (content !== original) {\n writeFileSync(filePath, content, 'utf-8');\n result.written.push(relativePath);\n } else {\n result.skipped.push(relativePath);\n }\n}\n\nfunction ensureEntryImportsStylesheet(\n cwd: string,\n cssPath: string,\n result: RuntimeScaffoldResult,\n): void {\n const entryCandidates = [\n 'app/_layout.tsx',\n 'app/_layout.jsx',\n 'app/_layout.ts',\n 'app/_layout.js',\n 'App.tsx',\n 'App.jsx',\n 'App.ts',\n 'App.js',\n 'index.ts',\n 'index.js',\n ];\n\n const entryFile = entryCandidates.find((candidate) =>\n existsSync(resolve(cwd, candidate)),\n );\n\n if (!entryFile) {\n result.skipped.push('entry:global.css import');\n return;\n }\n\n const entryPath = resolve(cwd, entryFile);\n const importPath = normalizeImportPath(\n relative(dirname(entryPath), resolve(cwd, cssPath)),\n );\n const importStatement = `import '${importPath}';`;\n const content = readFileSync(entryPath, 'utf-8');\n\n if (content.includes(importStatement)) {\n result.skipped.push(entryFile);\n return;\n }\n\n writeFileSync(entryPath, `${importStatement}\\n${content}`, 'utf-8');\n result.written.push(entryFile);\n}\n\nfunction normalizeImportPath(importPath: string): string {\n const normalized = importPath.replace(/\\\\/g, '/');\n if (normalized.startsWith('.')) {\n return normalized;\n }\n\n return `./${normalized}`;\n}\n\nfunction getReactNativeBabelConfigContent(\n aliasTarget: string,\n isExpo: boolean,\n): string {\n const preset = isExpo\n ? 'babel-preset-expo'\n : 'module:@react-native/babel-preset';\n\n return `module.exports = function (api) {\n api.cache(true);\n return {\n presets: [\"${preset}\"],\n plugins: [\n [\"module-resolver\", {\n alias: {\n \"@\": \"${aliasTarget}\"\n }\n }],\n \"nativewind/babel\"\n ],\n };\n};\n`;\n}\n\nfunction getReactNativeMetroConfigContent(\n cssPath: string,\n isExpo: boolean,\n): string {\n if (isExpo) {\n return `const { getDefaultConfig } = require(\"expo/metro-config\");\nconst { withNativeWind } = require(\"nativewind/metro\");\n\nconst config = getDefaultConfig(__dirname);\n\nmodule.exports = withNativeWind(config, {\n input: \"./${cssPath}\",\n});\n`;\n }\n\n return `const { getDefaultConfig, mergeConfig } = require(\"@react-native/metro-config\");\nconst { withNativeWind } = require(\"nativewind/metro\");\n\nconst config = mergeConfig(getDefaultConfig(__dirname), {});\n\nmodule.exports = withNativeWind(config, {\n input: \"./${cssPath}\",\n});\n`;\n}\n\nfunction getReactNativeTailwindConfigContent(usesSrcDir: boolean): string {\n const contentPath = usesSrcDir\n ? './src/**/*.{js,jsx,ts,tsx}'\n : './**/*.{js,jsx,ts,tsx}';\n\n return `/** @type {import('tailwindcss').Config} */\nmodule.exports = {\n content: [\n \"./App.{js,jsx,ts,tsx}\",\n \"./app/**/*.{js,jsx,ts,tsx}\",\n \"${contentPath}\",\n ],\n presets: [require(\"nativewind/preset\")],\n theme: {\n extend: {\n colors: {\n border: \"hsl(var(--border))\",\n input: \"hsl(var(--input))\",\n ring: \"hsl(var(--ring))\",\n background: \"hsl(var(--background))\",\n foreground: \"hsl(var(--foreground))\",\n primary: {\n DEFAULT: \"hsl(var(--primary))\",\n foreground: \"hsl(var(--primary-foreground))\",\n },\n secondary: {\n DEFAULT: \"hsl(var(--secondary))\",\n foreground: \"hsl(var(--secondary-foreground))\",\n },\n destructive: {\n DEFAULT: \"hsl(var(--destructive))\",\n foreground: \"hsl(var(--destructive-foreground))\",\n },\n muted: {\n DEFAULT: \"hsl(var(--muted))\",\n foreground: \"hsl(var(--muted-foreground))\",\n },\n accent: {\n DEFAULT: \"hsl(var(--accent))\",\n foreground: \"hsl(var(--accent-foreground))\",\n },\n popover: {\n DEFAULT: \"hsl(var(--popover))\",\n foreground: \"hsl(var(--popover-foreground))\",\n },\n card: {\n DEFAULT: \"hsl(var(--card))\",\n foreground: \"hsl(var(--card-foreground))\",\n },\n },\n borderRadius: {\n lg: \"var(--radius)\",\n md: \"calc(var(--radius) - 2px)\",\n sm: \"calc(var(--radius) - 4px)\",\n },\n },\n },\n plugins: [],\n};\n`;\n}\n\nfunction getReactNativeCssContent(baseColor: BaseColor): string {\n return getReactNativeColorVariableBlock(baseColor);\n}\n\nfunction getReactNativeColorVariableBlock(baseColor: BaseColor): string {\n const blocks: Record<BaseColor, string> = {\n slate: `@tailwind base;\n@tailwind components;\n@tailwind utilities;\n\n:root {\n --background: 0 0% 100%;\n --foreground: 222.2 84% 4.9%;\n --card: 0 0% 100%;\n --card-foreground: 222.2 84% 4.9%;\n --popover: 0 0% 100%;\n --popover-foreground: 222.2 84% 4.9%;\n --primary: 222.2 47.4% 11.2%;\n --primary-foreground: 210 40% 98%;\n --secondary: 210 40% 96.1%;\n --secondary-foreground: 222.2 47.4% 11.2%;\n --muted: 210 40% 96.1%;\n --muted-foreground: 215.4 16.3% 46.9%;\n --accent: 210 40% 96.1%;\n --accent-foreground: 222.2 47.4% 11.2%;\n --destructive: 0 84.2% 60.2%;\n --destructive-foreground: 210 40% 98%;\n --border: 214.3 31.8% 91.4%;\n --input: 214.3 31.8% 91.4%;\n --ring: 222.2 84% 4.9%;\n --radius: 0.5rem;\n}\n\n.dark {\n --background: 222.2 84% 4.9%;\n --foreground: 210 40% 98%;\n --card: 222.2 84% 4.9%;\n --card-foreground: 210 40% 98%;\n --popover: 222.2 84% 4.9%;\n --popover-foreground: 210 40% 98%;\n --primary: 210 40% 98%;\n --primary-foreground: 222.2 47.4% 11.2%;\n --secondary: 217.2 32.6% 17.5%;\n --secondary-foreground: 210 40% 98%;\n --muted: 217.2 32.6% 17.5%;\n --muted-foreground: 215 20.2% 65.1%;\n --accent: 217.2 32.6% 17.5%;\n --accent-foreground: 210 40% 98%;\n --destructive: 0 62.8% 30.6%;\n --destructive-foreground: 210 40% 98%;\n --border: 217.2 32.6% 17.5%;\n --input: 217.2 32.6% 17.5%;\n --ring: 212.7 26.8% 83.9%;\n}\n`,\n gray: `@tailwind base;\n@tailwind components;\n@tailwind utilities;\n\n:root {\n --background: 0 0% 100%;\n --foreground: 224 71.4% 4.1%;\n --card: 0 0% 100%;\n --card-foreground: 224 71.4% 4.1%;\n --popover: 0 0% 100%;\n --popover-foreground: 224 71.4% 4.1%;\n --primary: 220.9 39.3% 11%;\n --primary-foreground: 210 20% 98%;\n --secondary: 220 14.3% 95.9%;\n --secondary-foreground: 220.9 39.3% 11%;\n --muted: 220 14.3% 95.9%;\n --muted-foreground: 220 8.9% 46.1%;\n --accent: 220 14.3% 95.9%;\n --accent-foreground: 220.9 39.3% 11%;\n --destructive: 0 84.2% 60.2%;\n --destructive-foreground: 210 20% 98%;\n --border: 220 13% 91%;\n --input: 220 13% 91%;\n --ring: 224 71.4% 4.1%;\n --radius: 0.5rem;\n}\n\n.dark {\n --background: 224 71.4% 4.1%;\n --foreground: 210 20% 98%;\n --card: 224 71.4% 4.1%;\n --card-foreground: 210 20% 98%;\n --popover: 224 71.4% 4.1%;\n --popover-foreground: 210 20% 98%;\n --primary: 210 20% 98%;\n --primary-foreground: 220.9 39.3% 11%;\n --secondary: 215 27.9% 16.9%;\n --secondary-foreground: 210 20% 98%;\n --muted: 215 27.9% 16.9%;\n --muted-foreground: 217.9 10.6% 64.9%;\n --accent: 215 27.9% 16.9%;\n --accent-foreground: 210 20% 98%;\n --destructive: 0 62.8% 30.6%;\n --destructive-foreground: 210 20% 98%;\n --border: 215 27.9% 16.9%;\n --input: 215 27.9% 16.9%;\n --ring: 216 12.2% 83.9%;\n}\n`,\n zinc: `@tailwind base;\n@tailwind components;\n@tailwind utilities;\n\n:root {\n --background: 0 0% 100%;\n --foreground: 240 10% 3.9%;\n --card: 0 0% 100%;\n --card-foreground: 240 10% 3.9%;\n --popover: 0 0% 100%;\n --popover-foreground: 240 10% 3.9%;\n --primary: 240 5.9% 10%;\n --primary-foreground: 0 0% 98%;\n --secondary: 240 4.8% 95.9%;\n --secondary-foreground: 240 5.9% 10%;\n --muted: 240 4.8% 95.9%;\n --muted-foreground: 240 3.8% 46.1%;\n --accent: 240 4.8% 95.9%;\n --accent-foreground: 240 5.9% 10%;\n --destructive: 0 84.2% 60.2%;\n --destructive-foreground: 0 0% 98%;\n --border: 240 5.9% 90%;\n --input: 240 5.9% 90%;\n --ring: 240 10% 3.9%;\n --radius: 0.5rem;\n}\n\n.dark {\n --background: 240 10% 3.9%;\n --foreground: 0 0% 98%;\n --card: 240 10% 3.9%;\n --card-foreground: 0 0% 98%;\n --popover: 240 10% 3.9%;\n --popover-foreground: 0 0% 98%;\n --primary: 0 0% 98%;\n --primary-foreground: 240 5.9% 10%;\n --secondary: 240 3.7% 15.9%;\n --secondary-foreground: 0 0% 98%;\n --muted: 240 3.7% 15.9%;\n --muted-foreground: 240 5% 64.9%;\n --accent: 240 3.7% 15.9%;\n --accent-foreground: 0 0% 98%;\n --destructive: 0 62.8% 30.6%;\n --destructive-foreground: 0 0% 98%;\n --border: 240 3.7% 15.9%;\n --input: 240 3.7% 15.9%;\n --ring: 240 4.9% 83.9%;\n}\n`,\n neutral: `@tailwind base;\n@tailwind components;\n@tailwind utilities;\n\n:root {\n --background: 0 0% 100%;\n --foreground: 0 0% 3.9%;\n --card: 0 0% 100%;\n --card-foreground: 0 0% 3.9%;\n --popover: 0 0% 100%;\n --popover-foreground: 0 0% 3.9%;\n --primary: 0 0% 9%;\n --primary-foreground: 0 0% 98%;\n --secondary: 0 0% 96.1%;\n --secondary-foreground: 0 0% 9%;\n --muted: 0 0% 96.1%;\n --muted-foreground: 0 0% 45.1%;\n --accent: 0 0% 96.1%;\n --accent-foreground: 0 0% 9%;\n --destructive: 0 84.2% 60.2%;\n --destructive-foreground: 0 0% 98%;\n --border: 0 0% 89.8%;\n --input: 0 0% 89.8%;\n --ring: 0 0% 3.9%;\n --radius: 0.5rem;\n}\n\n.dark {\n --background: 0 0% 3.9%;\n --foreground: 0 0% 98%;\n --card: 0 0% 3.9%;\n --card-foreground: 0 0% 98%;\n --popover: 0 0% 3.9%;\n --popover-foreground: 0 0% 98%;\n --primary: 0 0% 98%;\n --primary-foreground: 0 0% 9%;\n --secondary: 0 0% 14.9%;\n --secondary-foreground: 0 0% 98%;\n --muted: 0 0% 14.9%;\n --muted-foreground: 0 0% 63.9%;\n --accent: 0 0% 14.9%;\n --accent-foreground: 0 0% 98%;\n --destructive: 0 62.8% 30.6%;\n --destructive-foreground: 0 0% 98%;\n --border: 0 0% 14.9%;\n --input: 0 0% 14.9%;\n --ring: 0 0% 83.1%;\n}\n`,\n stone: `@tailwind base;\n@tailwind components;\n@tailwind utilities;\n\n:root {\n --background: 0 0% 100%;\n --foreground: 20 14.3% 4.1%;\n --card: 0 0% 100%;\n --card-foreground: 20 14.3% 4.1%;\n --popover: 0 0% 100%;\n --popover-foreground: 20 14.3% 4.1%;\n --primary: 24 9.8% 10%;\n --primary-foreground: 60 9.1% 97.8%;\n --secondary: 60 4.8% 95.9%;\n --secondary-foreground: 24 9.8% 10%;\n --muted: 60 4.8% 95.9%;\n --muted-foreground: 25 5.3% 44.7%;\n --accent: 60 4.8% 95.9%;\n --accent-foreground: 24 9.8% 10%;\n --destructive: 0 84.2% 60.2%;\n --destructive-foreground: 60 9.1% 97.8%;\n --border: 20 5.9% 90%;\n --input: 20 5.9% 90%;\n --ring: 20 14.3% 4.1%;\n --radius: 0.5rem;\n}\n\n.dark {\n --background: 20 14.3% 4.1%;\n --foreground: 60 9.1% 97.8%;\n --card: 20 14.3% 4.1%;\n --card-foreground: 60 9.1% 97.8%;\n --popover: 20 14.3% 4.1%;\n --popover-foreground: 60 9.1% 97.8%;\n --primary: 60 9.1% 97.8%;\n --primary-foreground: 24 9.8% 10%;\n --secondary: 12 6.5% 15.1%;\n --secondary-foreground: 60 9.1% 97.8%;\n --muted: 12 6.5% 15.1%;\n --muted-foreground: 24 5.4% 63.9%;\n --accent: 12 6.5% 15.1%;\n --accent-foreground: 60 9.1% 97.8%;\n --destructive: 0 62.8% 30.6%;\n --destructive-foreground: 60 9.1% 97.8%;\n --border: 12 6.5% 15.1%;\n --input: 12 6.5% 15.1%;\n --ring: 24 5.7% 82.9%;\n}\n`,\n };\n\n return blocks[baseColor];\n}\n"],"names":["existsSync","readFileSync","writeFileSync","dirname","relative","resolve","writeFile","scaffoldTailwindFiles","scaffoldInitFrameworkRuntime","options","framework","configureReactNativeRuntime","cwd","cssPath","tailwindConfigPath","baseColor","usesSrcDir","isExpo","isExpoProject","mode","tailwindMode","configPath","overwriteExisting","result","written","skipped","ensureReactNativeStylesheet","writeRuntimeFileIfNeeded","getReactNativeTailwindConfigContent","getReactNativeMetroConfigContent","ensureReactNativeBabelConfig","ensureEntryImportsStylesheet","relativePath","content","filePath","push","cssContent","getReactNativeCssContent","existingContent","test","trimEnd","aliasTarget","getReactNativeBabelConfigContent","original","includes","replace","entryCandidates","entryFile","find","candidate","entryPath","importPath","normalizeImportPath","importStatement","normalized","startsWith","preset","contentPath","getReactNativeColorVariableBlock","blocks","slate","gray","zinc","neutral","stone"],"mappings":"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"}
@@ -0,0 +1,115 @@
1
+ import { existsSync, readFileSync, writeFileSync } from 'fs';
2
+ import { resolve } from 'path';
3
+ import chalk from 'chalk';
4
+ import { writeFile } from './files.js';
5
+ export function getUtilsTemplate(framework, typescript) {
6
+ if (framework === 'flutter') {
7
+ return null;
8
+ }
9
+ if (framework === 'react-native') {
10
+ return {
11
+ fileExtension: typescript ? '.ts' : '.js',
12
+ content: typescript ? `import { type ClassValue, clsx } from 'clsx';
13
+
14
+ export function cn(...inputs: ClassValue[]) {
15
+ return clsx(inputs);
16
+ }
17
+ ` : `import { clsx } from 'clsx';
18
+
19
+ export function cn(...inputs) {
20
+ return clsx(inputs);
21
+ }
22
+ `
23
+ };
24
+ }
25
+ return {
26
+ fileExtension: typescript ? '.ts' : '.js',
27
+ content: typescript ? `import { clsx, type ClassValue } from 'clsx';
28
+ import { twMerge } from 'tailwind-merge';
29
+
30
+ /**
31
+ * Merge Tailwind CSS classes
32
+ */
33
+ export function cn(...inputs: ClassValue[]) {
34
+ return twMerge(clsx(inputs));
35
+ }
36
+ ` : `import { clsx } from 'clsx';
37
+ import { twMerge } from 'tailwind-merge';
38
+
39
+ export function cn(...inputs) {
40
+ return twMerge(clsx(inputs));
41
+ }
42
+ `
43
+ };
44
+ }
45
+ export function writeInitUtilityFile(options) {
46
+ const utilsTemplate = getUtilsTemplate(options.framework, options.typescript);
47
+ if (!utilsTemplate) {
48
+ return false;
49
+ }
50
+ const baseDir = options.usesSrcDir ? 'src/' : '';
51
+ const utilsPath = resolve(options.cwd, baseDir + options.utilsAlias.replace('@/', '') + utilsTemplate.fileExtension);
52
+ writeFile(utilsPath, utilsTemplate.content);
53
+ return true;
54
+ }
55
+ export function configureProjectAliases(options) {
56
+ if (!options.typescript || options.framework === 'flutter') {
57
+ return;
58
+ }
59
+ if (options.framework === 'react' || options.framework === 'angular' || options.framework === 'vue') {
60
+ configureTypeScriptAliases(options.cwd, 'tsconfig.app.json', options.usesSrcDir);
61
+ } else if (options.framework === 'nextjs' || options.framework === 'react-native') {
62
+ configureTypeScriptAliases(options.cwd, 'tsconfig.json', options.usesSrcDir);
63
+ }
64
+ if (options.framework === 'react' || options.framework === 'vue') {
65
+ configureViteAliases(options.cwd, 'vite.config.ts');
66
+ }
67
+ }
68
+ function configureTypeScriptAliases(cwd, tsconfigFile, usesSrcDir) {
69
+ const tsconfigPath = resolve(cwd, tsconfigFile);
70
+ if (!existsSync(tsconfigPath)) {
71
+ return;
72
+ }
73
+ try {
74
+ let content = readFileSync(tsconfigPath, 'utf-8');
75
+ const pathMapping = usesSrcDir ? './src/*' : './*';
76
+ if (content.includes('"paths"')) {
77
+ return;
78
+ }
79
+ const compilerOptionsMatch = content.match(/"compilerOptions"\s*:\s*{/);
80
+ if (!compilerOptionsMatch) {
81
+ throw new Error('compilerOptions not found');
82
+ }
83
+ const insertPattern = /(\n)(\s*)(}\s*,?\s*\n\s*"(?:include|exclude|files|references))/;
84
+ const match = content.match(insertPattern);
85
+ if (match) {
86
+ const baseIndent = match[2] || ' ';
87
+ const propertyIndent = baseIndent + ' ';
88
+ const pathConfig = `,${match[1]}${propertyIndent}/* Path Aliases */${match[1]}${propertyIndent}"baseUrl": ".",${match[1]}${propertyIndent}"paths": {${match[1]}${propertyIndent} "@/*": ["${pathMapping}"]${match[1]}${propertyIndent}}`;
89
+ content = content.replace(insertPattern, `${pathConfig}${match[1]}${match[2]}${match[3]}`);
90
+ writeFileSync(tsconfigPath, content, 'utf-8');
91
+ }
92
+ } catch (e) {
93
+ // Non-critical best-effort alias config.
94
+ }
95
+ }
96
+ function configureViteAliases(cwd, viteConfigFile) {
97
+ const viteConfigPath = resolve(cwd, viteConfigFile);
98
+ if (!existsSync(viteConfigPath)) {
99
+ return;
100
+ }
101
+ try {
102
+ let content = readFileSync(viteConfigPath, 'utf-8');
103
+ if (!content.includes("import path from 'path'") && !content.includes('import path from "path"') && !content.includes("import path from 'node:path'") && !content.includes('import path from "node:path"')) {
104
+ content = content.replace(/(import .+ from .+\n)/, "$1import path from 'path'\n");
105
+ }
106
+ if (!content.includes('resolve:') && !content.includes('@:')) {
107
+ content = content.replace(RegExp("(plugins: \\[.+\\],?)", "s"), `$1\n resolve: {\n alias: {\n '@': path.resolve(__dirname, './src'),\n },\n },`);
108
+ }
109
+ writeFileSync(viteConfigPath, content, 'utf-8');
110
+ } catch (e) {
111
+ console.error(chalk.yellow(`Warning: Could not update ${viteConfigFile}`));
112
+ }
113
+ }
114
+
115
+ //# sourceMappingURL=init-scaffold.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/utils/init-scaffold.ts"],"sourcesContent":["import { existsSync, readFileSync, writeFileSync } from 'fs';\nimport { resolve } from 'path';\nimport chalk from 'chalk';\nimport { writeFile } from './files.js';\nimport type { Framework } from './config-schema.js';\n\nexport function getUtilsTemplate(\n framework: Framework,\n typescript: boolean,\n): { fileExtension: '.ts' | '.js'; content: string } | null {\n if (framework === 'flutter') {\n return null;\n }\n\n if (framework === 'react-native') {\n return {\n fileExtension: typescript ? '.ts' : '.js',\n content: typescript\n ? `import { type ClassValue, clsx } from 'clsx';\n\nexport function cn(...inputs: ClassValue[]) {\n return clsx(inputs);\n}\n`\n : `import { clsx } from 'clsx';\n\nexport function cn(...inputs) {\n return clsx(inputs);\n}\n`,\n };\n }\n\n return {\n fileExtension: typescript ? '.ts' : '.js',\n content: typescript\n ? `import { clsx, type ClassValue } from 'clsx';\nimport { twMerge } from 'tailwind-merge';\n\n/**\n * Merge Tailwind CSS classes\n */\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n`\n : `import { clsx } from 'clsx';\nimport { twMerge } from 'tailwind-merge';\n\nexport function cn(...inputs) {\n return twMerge(clsx(inputs));\n}\n`,\n };\n}\n\nexport function writeInitUtilityFile(options: {\n cwd: string;\n framework: Framework;\n typescript: boolean;\n usesSrcDir: boolean;\n utilsAlias: string;\n}): boolean {\n const utilsTemplate = getUtilsTemplate(options.framework, options.typescript);\n if (!utilsTemplate) {\n return false;\n }\n\n const baseDir = options.usesSrcDir ? 'src/' : '';\n const utilsPath = resolve(\n options.cwd,\n baseDir +\n options.utilsAlias.replace('@/', '') +\n utilsTemplate.fileExtension,\n );\n writeFile(utilsPath, utilsTemplate.content);\n return true;\n}\n\nexport function configureProjectAliases(options: {\n cwd: string;\n framework: Framework;\n typescript: boolean;\n usesSrcDir: boolean;\n}): void {\n if (!options.typescript || options.framework === 'flutter') {\n return;\n }\n\n if (\n options.framework === 'react' ||\n options.framework === 'angular' ||\n options.framework === 'vue'\n ) {\n configureTypeScriptAliases(\n options.cwd,\n 'tsconfig.app.json',\n options.usesSrcDir,\n );\n } else if (\n options.framework === 'nextjs' ||\n options.framework === 'react-native'\n ) {\n configureTypeScriptAliases(\n options.cwd,\n 'tsconfig.json',\n options.usesSrcDir,\n );\n }\n\n if (options.framework === 'react' || options.framework === 'vue') {\n configureViteAliases(options.cwd, 'vite.config.ts');\n }\n}\n\nfunction configureTypeScriptAliases(\n cwd: string,\n tsconfigFile: string,\n usesSrcDir: boolean,\n): void {\n const tsconfigPath = resolve(cwd, tsconfigFile);\n\n if (!existsSync(tsconfigPath)) {\n return;\n }\n\n try {\n let content = readFileSync(tsconfigPath, 'utf-8');\n const pathMapping = usesSrcDir ? './src/*' : './*';\n\n if (content.includes('\"paths\"')) {\n return;\n }\n\n const compilerOptionsMatch = content.match(/\"compilerOptions\"\\s*:\\s*{/);\n if (!compilerOptionsMatch) {\n throw new Error('compilerOptions not found');\n }\n\n const insertPattern =\n /(\\n)(\\s*)(}\\s*,?\\s*\\n\\s*\"(?:include|exclude|files|references))/;\n const match = content.match(insertPattern);\n\n if (match) {\n const baseIndent = match[2] || ' ';\n const propertyIndent = baseIndent + ' ';\n const pathConfig = `,${match[1]}${propertyIndent}/* Path Aliases */${match[1]}${propertyIndent}\"baseUrl\": \".\",${match[1]}${propertyIndent}\"paths\": {${match[1]}${propertyIndent} \"@/*\": [\"${pathMapping}\"]${match[1]}${propertyIndent}}`;\n\n content = content.replace(\n insertPattern,\n `${pathConfig}${match[1]}${match[2]}${match[3]}`,\n );\n writeFileSync(tsconfigPath, content, 'utf-8');\n }\n } catch {\n // Non-critical best-effort alias config.\n }\n}\n\nfunction configureViteAliases(cwd: string, viteConfigFile: string): void {\n const viteConfigPath = resolve(cwd, viteConfigFile);\n\n if (!existsSync(viteConfigPath)) {\n return;\n }\n\n try {\n let content = readFileSync(viteConfigPath, 'utf-8');\n\n if (\n !content.includes(\"import path from 'path'\") &&\n !content.includes('import path from \"path\"') &&\n !content.includes(\"import path from 'node:path'\") &&\n !content.includes('import path from \"node:path\"')\n ) {\n content = content.replace(\n /(import .+ from .+\\n)/,\n \"$1import path from 'path'\\n\",\n );\n }\n\n if (!content.includes('resolve:') && !content.includes('@:')) {\n content = content.replace(\n /(plugins: \\[.+\\],?)/s,\n `$1\\n resolve: {\\n alias: {\\n '@': path.resolve(__dirname, './src'),\\n },\\n },`,\n );\n }\n\n writeFileSync(viteConfigPath, content, 'utf-8');\n } catch {\n console.error(chalk.yellow(`Warning: Could not update ${viteConfigFile}`));\n }\n}\n"],"names":["existsSync","readFileSync","writeFileSync","resolve","chalk","writeFile","getUtilsTemplate","framework","typescript","fileExtension","content","writeInitUtilityFile","options","utilsTemplate","baseDir","usesSrcDir","utilsPath","cwd","utilsAlias","replace","configureProjectAliases","configureTypeScriptAliases","configureViteAliases","tsconfigFile","tsconfigPath","pathMapping","includes","compilerOptionsMatch","match","Error","insertPattern","baseIndent","propertyIndent","pathConfig","viteConfigFile","viteConfigPath","console","error","yellow"],"mappings":"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"}