@gemini-designer/mcp-server 0.1.2 → 0.1.29

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 (129) hide show
  1. package/dist/components/catalog.d.ts.map +1 -1
  2. package/dist/components/catalog.js +10 -4
  3. package/dist/components/catalog.js.map +1 -1
  4. package/dist/config/index.d.ts.map +1 -1
  5. package/dist/config/index.js +11 -6
  6. package/dist/config/index.js.map +1 -1
  7. package/dist/context/builder.d.ts.map +1 -1
  8. package/dist/context/builder.js.map +1 -1
  9. package/dist/context/filter.d.ts.map +1 -1
  10. package/dist/context/filter.js +5 -1
  11. package/dist/context/filter.js.map +1 -1
  12. package/dist/context/grounding.d.ts.map +1 -1
  13. package/dist/context/grounding.js +7 -3
  14. package/dist/context/grounding.js.map +1 -1
  15. package/dist/context/guards.d.ts.map +1 -1
  16. package/dist/context/guards.js +53 -0
  17. package/dist/context/guards.js.map +1 -1
  18. package/dist/context/repo-hints.js.map +1 -1
  19. package/dist/context/styling-detector.d.ts +24 -0
  20. package/dist/context/styling-detector.d.ts.map +1 -0
  21. package/dist/context/styling-detector.js +337 -0
  22. package/dist/context/styling-detector.js.map +1 -0
  23. package/dist/design/principles.js.map +1 -1
  24. package/dist/generation/gemini-client.d.ts.map +1 -1
  25. package/dist/generation/gemini-client.js.map +1 -1
  26. package/dist/generation/litellm-client.d.ts.map +1 -1
  27. package/dist/generation/litellm-client.js +14 -7
  28. package/dist/generation/litellm-client.js.map +1 -1
  29. package/dist/generation/remote-client.d.ts +10 -5
  30. package/dist/generation/remote-client.d.ts.map +1 -1
  31. package/dist/generation/remote-client.js +13 -2
  32. package/dist/generation/remote-client.js.map +1 -1
  33. package/dist/index.js.map +1 -1
  34. package/dist/output/file-writer.d.ts.map +1 -1
  35. package/dist/output/file-writer.js +4 -4
  36. package/dist/output/file-writer.js.map +1 -1
  37. package/dist/output/formatter.d.ts.map +1 -1
  38. package/dist/output/formatter.js +5 -2
  39. package/dist/output/formatter.js.map +1 -1
  40. package/dist/server.d.ts.map +1 -1
  41. package/dist/server.js +2 -1
  42. package/dist/server.js.map +1 -1
  43. package/dist/stack/detect.d.ts.map +1 -1
  44. package/dist/stack/detect.js +42 -9
  45. package/dist/stack/detect.js.map +1 -1
  46. package/dist/tokens/sync.d.ts.map +1 -1
  47. package/dist/tokens/sync.js +22 -5
  48. package/dist/tokens/sync.js.map +1 -1
  49. package/dist/tools/analyze-screenshot-ui.d.ts.map +1 -1
  50. package/dist/tools/analyze-screenshot-ui.js +5 -5
  51. package/dist/tools/analyze-screenshot-ui.js.map +1 -1
  52. package/dist/tools/analyze-tokens.d.ts.map +1 -1
  53. package/dist/tools/analyze-tokens.js +3 -1
  54. package/dist/tools/analyze-tokens.js.map +1 -1
  55. package/dist/tools/catalog-components.d.ts.map +1 -1
  56. package/dist/tools/catalog-components.js +1 -4
  57. package/dist/tools/catalog-components.js.map +1 -1
  58. package/dist/tools/create-ui.d.ts +3 -0
  59. package/dist/tools/create-ui.d.ts.map +1 -1
  60. package/dist/tools/create-ui.js +203 -75
  61. package/dist/tools/create-ui.js.map +1 -1
  62. package/dist/tools/detect-ui-stack.js.map +1 -1
  63. package/dist/tools/generate-component-variants.d.ts.map +1 -1
  64. package/dist/tools/generate-component-variants.js +15 -4
  65. package/dist/tools/generate-component-variants.js.map +1 -1
  66. package/dist/tools/generate-vibes.d.ts.map +1 -1
  67. package/dist/tools/generate-vibes.js +7 -3
  68. package/dist/tools/generate-vibes.js.map +1 -1
  69. package/dist/tools/index.js.map +1 -1
  70. package/dist/tools/modify-ui.d.ts.map +1 -1
  71. package/dist/tools/modify-ui.js +7 -2
  72. package/dist/tools/modify-ui.js.map +1 -1
  73. package/dist/tools/scaffold-project.d.ts.map +1 -1
  74. package/dist/tools/scaffold-project.js +3 -1
  75. package/dist/tools/scaffold-project.js.map +1 -1
  76. package/dist/tools/snippet-ui.d.ts +3 -1
  77. package/dist/tools/snippet-ui.d.ts.map +1 -1
  78. package/dist/tools/snippet-ui.js +219 -88
  79. package/dist/tools/snippet-ui.js.map +1 -1
  80. package/dist/tools/sync-design-tokens.d.ts.map +1 -1
  81. package/dist/tools/sync-design-tokens.js +26 -11
  82. package/dist/tools/sync-design-tokens.js.map +1 -1
  83. package/dist/utils/walk.d.ts.map +1 -1
  84. package/dist/utils/walk.js.map +1 -1
  85. package/dist/version.d.ts +2 -0
  86. package/dist/version.d.ts.map +1 -0
  87. package/dist/version.js +5 -0
  88. package/dist/version.js.map +1 -0
  89. package/package.json +55 -55
  90. package/src/__tests__/builder.test.ts +19 -19
  91. package/src/__tests__/config.test.ts +63 -31
  92. package/src/__tests__/filter.test.ts +98 -92
  93. package/src/__tests__/remote-client.test.ts +179 -0
  94. package/src/components/catalog.ts +170 -166
  95. package/src/config/index.ts +185 -177
  96. package/src/context/builder.ts +157 -157
  97. package/src/context/filter.ts +110 -104
  98. package/src/context/grounding.ts +143 -129
  99. package/src/context/guards.ts +97 -38
  100. package/src/context/repo-hints.ts +24 -24
  101. package/src/context/styling-detector.ts +460 -0
  102. package/src/design/principles.ts +14 -14
  103. package/src/generation/gemini-client.ts +53 -56
  104. package/src/generation/litellm-client.ts +102 -86
  105. package/src/generation/remote-client.ts +100 -77
  106. package/src/index.ts +16 -16
  107. package/src/output/file-writer.ts +123 -123
  108. package/src/output/formatter.ts +139 -132
  109. package/src/server.ts +12 -11
  110. package/src/stack/detect.ts +226 -175
  111. package/src/tokens/sync.ts +189 -155
  112. package/src/tools/analyze-screenshot-ui.ts +89 -88
  113. package/src/tools/analyze-tokens.ts +80 -78
  114. package/src/tools/catalog-components.ts +68 -68
  115. package/src/tools/create-ui.ts +295 -142
  116. package/src/tools/detect-ui-stack.ts +36 -36
  117. package/src/tools/generate-component-variants.ts +155 -135
  118. package/src/tools/generate-vibes.ts +121 -117
  119. package/src/tools/index.ts +14 -14
  120. package/src/tools/modify-ui.ts +170 -165
  121. package/src/tools/scaffold-project.ts +68 -66
  122. package/src/tools/snippet-ui.ts +323 -172
  123. package/src/tools/sync-design-tokens.ts +217 -195
  124. package/src/utils/walk.ts +47 -45
  125. package/src/version.ts +6 -0
  126. package/tsconfig.json +23 -33
  127. package/vitest.config.ts +10 -10
  128. package/.prettierrc +0 -9
  129. package/eslint.config.js +0 -37
@@ -12,193 +12,244 @@ import * as fs from 'node:fs';
12
12
  import * as path from 'node:path';
13
13
 
14
14
  export interface StackDetectionResult {
15
- root: string;
16
- framework: {
17
- name: 'nextjs' | 'react' | 'vue' | 'svelte' | 'unknown';
18
- version?: string;
19
- router?: 'app' | 'pages' | 'unknown';
20
- };
21
- language: {
22
- typescript: boolean;
23
- };
24
- styling: {
25
- primary: 'tailwind' | 'css-modules' | 'emotion' | 'styled-components' | 'sass' | 'vanilla' | 'unknown';
26
- detected: string[];
27
- };
28
- uiLibraries: string[];
29
- iconLibraries: string[];
30
- tooling: {
31
- storybook: boolean;
32
- eslint: boolean;
33
- prettier: boolean;
34
- vitest: boolean;
35
- jest: boolean;
36
- };
37
- conventions: {
38
- srcDir: boolean;
39
- hasAppDir: boolean;
40
- hasPagesDir: boolean;
41
- tsconfigPaths?: Record<string, string[]>;
42
- };
43
- files: {
44
- packageJson?: string;
45
- tsconfig?: string;
46
- tailwindConfig?: string;
47
- componentsJson?: string;
48
- storybookDir?: string;
49
- };
50
- warnings: string[];
15
+ root: string;
16
+ framework: {
17
+ name: 'nextjs' | 'react' | 'vue' | 'svelte' | 'unknown';
18
+ version?: string;
19
+ router?: 'app' | 'pages' | 'unknown';
20
+ };
21
+ language: {
22
+ typescript: boolean;
23
+ };
24
+ styling: {
25
+ primary:
26
+ | 'tailwind'
27
+ | 'css-modules'
28
+ | 'emotion'
29
+ | 'styled-components'
30
+ | 'sass'
31
+ | 'vanilla'
32
+ | 'unknown';
33
+ detected: string[];
34
+ };
35
+ uiLibraries: string[];
36
+ iconLibraries: string[];
37
+ tooling: {
38
+ storybook: boolean;
39
+ eslint: boolean;
40
+ prettier: boolean;
41
+ vitest: boolean;
42
+ jest: boolean;
43
+ };
44
+ conventions: {
45
+ srcDir: boolean;
46
+ hasAppDir: boolean;
47
+ hasPagesDir: boolean;
48
+ tsconfigPaths?: Record<string, string[]>;
49
+ };
50
+ files: {
51
+ packageJson?: string;
52
+ tsconfig?: string;
53
+ tailwindConfig?: string;
54
+ componentsJson?: string;
55
+ storybookDir?: string;
56
+ };
57
+ warnings: string[];
51
58
  }
52
59
 
53
- function readJsonIfExists(filePath: string): any | null {
54
- if (!fs.existsSync(filePath)) return null;
55
- try {
56
- return JSON.parse(fs.readFileSync(filePath, 'utf-8'));
57
- } catch {
58
- return null;
59
- }
60
+ function readJsonIfExists(filePath: string): unknown | null {
61
+ if (!fs.existsSync(filePath)) return null;
62
+ try {
63
+ return JSON.parse(fs.readFileSync(filePath, 'utf-8'));
64
+ } catch {
65
+ return null;
66
+ }
60
67
  }
61
68
 
62
- function exists(root: string, ...parts: string[]): string | null {
63
- const p = path.join(root, ...parts);
64
- return fs.existsSync(p) ? p : null;
69
+ function isRecord(value: unknown): value is Record<string, unknown> {
70
+ return Boolean(value) && typeof value === 'object' && !Array.isArray(value);
65
71
  }
66
72
 
67
- function depVersion(pkg: any, name: string): string | undefined {
68
- const d = pkg?.dependencies?.[name] || pkg?.devDependencies?.[name] || pkg?.peerDependencies?.[name];
69
- return typeof d === 'string' ? d : undefined;
73
+ function exists(root: string, ...parts: string[]): string | null {
74
+ const p = path.join(root, ...parts);
75
+ return fs.existsSync(p) ? p : null;
70
76
  }
71
77
 
72
- export function detectUiStack(rootDir: string): StackDetectionResult {
73
- const warnings: string[] = [];
74
-
75
- const pkgPath = exists(rootDir, 'package.json');
76
- const pkg = pkgPath ? readJsonIfExists(pkgPath) : null;
77
- if (!pkg) warnings.push('package.json not found or invalid JSON');
78
-
79
- const hasTs = Boolean(
80
- exists(rootDir, 'tsconfig.json') ||
81
- exists(rootDir, 'tsconfig.base.json') ||
82
- exists(rootDir, 'tsconfig.app.json') ||
83
- depVersion(pkg, 'typescript')
84
- );
85
-
86
- // Framework detection
87
- let framework: StackDetectionResult['framework'] = { name: 'unknown', router: 'unknown' };
88
-
89
- if (depVersion(pkg, 'next')) {
90
- framework = { name: 'nextjs', version: depVersion(pkg, 'next'), router: 'unknown' };
91
- } else if (depVersion(pkg, 'react')) {
92
- framework = { name: 'react', version: depVersion(pkg, 'react'), router: 'unknown' };
93
- } else if (depVersion(pkg, 'vue')) {
94
- framework = { name: 'vue', version: depVersion(pkg, 'vue'), router: 'unknown' };
95
- } else if (depVersion(pkg, 'svelte')) {
96
- framework = { name: 'svelte', version: depVersion(pkg, 'svelte'), router: 'unknown' };
97
- }
78
+ function depVersion(pkg: unknown, name: string): string | undefined {
79
+ if (!isRecord(pkg)) return undefined;
98
80
 
99
- const srcDir = Boolean(exists(rootDir, 'src'));
100
- const hasAppDir = Boolean(exists(rootDir, 'app') || exists(rootDir, 'src', 'app'));
101
- const hasPagesDir = Boolean(exists(rootDir, 'pages') || exists(rootDir, 'src', 'pages'));
81
+ const dependencies = isRecord(pkg.dependencies) ? pkg.dependencies : undefined;
82
+ const devDependencies = isRecord(pkg.devDependencies) ? pkg.devDependencies : undefined;
83
+ const peerDependencies = isRecord(pkg.peerDependencies) ? pkg.peerDependencies : undefined;
102
84
 
103
- if (framework.name === 'nextjs') {
104
- framework.router = hasAppDir ? 'app' : hasPagesDir ? 'pages' : 'unknown';
105
- }
85
+ const dep =
86
+ (dependencies?.[name] as unknown) ??
87
+ (devDependencies?.[name] as unknown) ??
88
+ (peerDependencies?.[name] as unknown);
106
89
 
107
- // Styling detection
108
- const detectedStyling: string[] = [];
109
- if (depVersion(pkg, 'tailwindcss') || exists(rootDir, 'tailwind.config.js') || exists(rootDir, 'tailwind.config.ts')) {
110
- detectedStyling.push('tailwind');
111
- }
112
- if (depVersion(pkg, 'sass') || depVersion(pkg, 'node-sass')) detectedStyling.push('sass');
113
- if (depVersion(pkg, 'styled-components')) detectedStyling.push('styled-components');
114
- if (depVersion(pkg, '@emotion/react') || depVersion(pkg, '@emotion/styled')) detectedStyling.push('emotion');
115
-
116
- // CSS Modules: heuristic – Next and CRA often use .module.css. We can't scan whole tree here; mark as possible.
117
- if (framework.name === 'nextjs') detectedStyling.push('css-modules');
118
-
119
- let primary: StackDetectionResult['styling']['primary'] = 'unknown';
120
- if (detectedStyling.includes('tailwind')) primary = 'tailwind';
121
- else if (detectedStyling.includes('emotion')) primary = 'emotion';
122
- else if (detectedStyling.includes('styled-components')) primary = 'styled-components';
123
- else if (detectedStyling.includes('sass')) primary = 'sass';
124
- else if (framework.name !== 'unknown') primary = 'vanilla';
125
-
126
- // UI libraries (coarse)
127
- const uiCandidates = [
128
- '@mui/material',
129
- 'antd',
130
- '@chakra-ui/react',
131
- '@radix-ui/react-dialog',
132
- '@headlessui/react',
133
- 'shadcn-ui',
134
- 'lucide-react',
135
- '@mantine/core',
136
- '@nextui-org/react',
137
- ];
138
-
139
- const uiLibraries = uiCandidates.filter((n) => Boolean(depVersion(pkg, n)));
140
-
141
- // Icon libraries
142
- const iconCandidates = ['lucide-react', 'react-icons', '@heroicons/react', '@tabler/icons-react', '@phosphor-icons/react'];
143
- const iconLibraries = iconCandidates.filter((n) => Boolean(depVersion(pkg, n)));
144
-
145
- // Storybook / linting / formatting / tests
146
- const hasStorybook = Boolean(exists(rootDir, '.storybook')) || Boolean(depVersion(pkg, 'storybook')) || Boolean(depVersion(pkg, '@storybook/react'));
147
- const hasEslint = Boolean(depVersion(pkg, 'eslint')) || Boolean(exists(rootDir, '.eslintrc')) || Boolean(exists(rootDir, '.eslintrc.js'));
148
- const hasPrettier = Boolean(depVersion(pkg, 'prettier')) || Boolean(exists(rootDir, '.prettierrc'));
149
- const hasVitest = Boolean(depVersion(pkg, 'vitest'));
150
- const hasJest = Boolean(depVersion(pkg, 'jest'));
151
-
152
- // Shadcn detection
153
- const componentsJson = exists(rootDir, 'components.json');
154
- if (componentsJson) {
155
- if (!uiLibraries.includes('shadcn-ui')) uiLibraries.push('shadcn-ui');
156
- }
90
+ return typeof dep === 'string' ? dep : undefined;
91
+ }
157
92
 
158
- // tsconfig paths
159
- const tsconfigPath = exists(rootDir, 'tsconfig.json') || exists(rootDir, 'tsconfig.base.json');
160
- let tsconfigPaths: Record<string, string[]> | undefined;
161
- if (tsconfigPath) {
162
- const tsconfig = readJsonIfExists(tsconfigPath);
163
- const paths = tsconfig?.compilerOptions?.paths;
164
- if (paths && typeof paths === 'object') {
165
- tsconfigPaths = paths;
93
+ export function detectUiStack(rootDir: string): StackDetectionResult {
94
+ const warnings: string[] = [];
95
+
96
+ const pkgPath = exists(rootDir, 'package.json');
97
+ const pkg = pkgPath ? readJsonIfExists(pkgPath) : null;
98
+ if (!pkg) warnings.push('package.json not found or invalid JSON');
99
+
100
+ const hasTs = Boolean(
101
+ exists(rootDir, 'tsconfig.json') ||
102
+ exists(rootDir, 'tsconfig.base.json') ||
103
+ exists(rootDir, 'tsconfig.app.json') ||
104
+ depVersion(pkg, 'typescript')
105
+ );
106
+
107
+ // Framework detection
108
+ let framework: StackDetectionResult['framework'] = { name: 'unknown', router: 'unknown' };
109
+
110
+ if (depVersion(pkg, 'next')) {
111
+ framework = { name: 'nextjs', version: depVersion(pkg, 'next'), router: 'unknown' };
112
+ } else if (depVersion(pkg, 'react')) {
113
+ framework = { name: 'react', version: depVersion(pkg, 'react'), router: 'unknown' };
114
+ } else if (depVersion(pkg, 'vue')) {
115
+ framework = { name: 'vue', version: depVersion(pkg, 'vue'), router: 'unknown' };
116
+ } else if (depVersion(pkg, 'svelte')) {
117
+ framework = { name: 'svelte', version: depVersion(pkg, 'svelte'), router: 'unknown' };
118
+ }
119
+
120
+ const srcDir = Boolean(exists(rootDir, 'src'));
121
+ const hasAppDir = Boolean(exists(rootDir, 'app') || exists(rootDir, 'src', 'app'));
122
+ const hasPagesDir = Boolean(exists(rootDir, 'pages') || exists(rootDir, 'src', 'pages'));
123
+
124
+ if (framework.name === 'nextjs') {
125
+ framework.router = hasAppDir ? 'app' : hasPagesDir ? 'pages' : 'unknown';
126
+ }
127
+
128
+ // Styling detection
129
+ const detectedStyling: string[] = [];
130
+ if (
131
+ depVersion(pkg, 'tailwindcss') ||
132
+ exists(rootDir, 'tailwind.config.js') ||
133
+ exists(rootDir, 'tailwind.config.ts')
134
+ ) {
135
+ detectedStyling.push('tailwind');
136
+ }
137
+ if (depVersion(pkg, 'sass') || depVersion(pkg, 'node-sass')) detectedStyling.push('sass');
138
+ if (depVersion(pkg, 'styled-components')) detectedStyling.push('styled-components');
139
+ if (depVersion(pkg, '@emotion/react') || depVersion(pkg, '@emotion/styled'))
140
+ detectedStyling.push('emotion');
141
+
142
+ // CSS Modules: heuristic – Next and CRA often use .module.css. We can't scan whole tree here; mark as possible.
143
+ if (framework.name === 'nextjs') detectedStyling.push('css-modules');
144
+
145
+ let primary: StackDetectionResult['styling']['primary'] = 'unknown';
146
+ if (detectedStyling.includes('tailwind')) primary = 'tailwind';
147
+ else if (detectedStyling.includes('emotion')) primary = 'emotion';
148
+ else if (detectedStyling.includes('styled-components')) primary = 'styled-components';
149
+ else if (detectedStyling.includes('sass')) primary = 'sass';
150
+ else if (framework.name !== 'unknown') primary = 'vanilla';
151
+
152
+ // UI libraries (coarse)
153
+ const uiCandidates = [
154
+ '@mui/material',
155
+ 'antd',
156
+ '@chakra-ui/react',
157
+ '@radix-ui/react-dialog',
158
+ '@headlessui/react',
159
+ 'shadcn-ui',
160
+ 'lucide-react',
161
+ '@mantine/core',
162
+ '@nextui-org/react',
163
+ ];
164
+
165
+ const uiLibraries = uiCandidates.filter((n) => Boolean(depVersion(pkg, n)));
166
+
167
+ // Icon libraries
168
+ const iconCandidates = [
169
+ 'lucide-react',
170
+ 'react-icons',
171
+ '@heroicons/react',
172
+ '@tabler/icons-react',
173
+ '@phosphor-icons/react',
174
+ ];
175
+ const iconLibraries = iconCandidates.filter((n) => Boolean(depVersion(pkg, n)));
176
+
177
+ // Storybook / linting / formatting / tests
178
+ const hasStorybook =
179
+ Boolean(exists(rootDir, '.storybook')) ||
180
+ Boolean(depVersion(pkg, 'storybook')) ||
181
+ Boolean(depVersion(pkg, '@storybook/react'));
182
+ const hasEslint =
183
+ Boolean(depVersion(pkg, 'eslint')) ||
184
+ Boolean(exists(rootDir, '.eslintrc')) ||
185
+ Boolean(exists(rootDir, '.eslintrc.js'));
186
+ const hasPrettier =
187
+ Boolean(depVersion(pkg, 'prettier')) || Boolean(exists(rootDir, '.prettierrc'));
188
+ const hasVitest = Boolean(depVersion(pkg, 'vitest'));
189
+ const hasJest = Boolean(depVersion(pkg, 'jest'));
190
+
191
+ // Shadcn detection
192
+ const componentsJson = exists(rootDir, 'components.json');
193
+ if (componentsJson) {
194
+ if (!uiLibraries.includes('shadcn-ui')) uiLibraries.push('shadcn-ui');
195
+ }
196
+
197
+ // tsconfig paths
198
+ const tsconfigPath = exists(rootDir, 'tsconfig.json') || exists(rootDir, 'tsconfig.base.json');
199
+ let tsconfigPaths: Record<string, string[]> | undefined;
200
+ if (tsconfigPath) {
201
+ const tsconfig = readJsonIfExists(tsconfigPath);
202
+ if (isRecord(tsconfig)) {
203
+ const compilerOptions = isRecord(tsconfig.compilerOptions)
204
+ ? tsconfig.compilerOptions
205
+ : undefined;
206
+ const paths =
207
+ compilerOptions && isRecord(compilerOptions.paths) ? compilerOptions.paths : undefined;
208
+ if (paths) {
209
+ const out: Record<string, string[]> = {};
210
+ for (const [k, v] of Object.entries(paths)) {
211
+ if (Array.isArray(v) && v.every((x) => typeof x === 'string')) {
212
+ out[k] = v;
213
+ }
166
214
  }
215
+ tsconfigPaths = Object.keys(out).length > 0 ? out : undefined;
216
+ }
167
217
  }
168
-
169
- const tailwindConfig =
170
- exists(rootDir, 'tailwind.config.ts') ||
171
- exists(rootDir, 'tailwind.config.js') ||
172
- exists(rootDir, 'tailwind.config.cjs') ||
173
- exists(rootDir, 'tailwind.config.mjs');
174
-
175
- return {
176
- root: rootDir,
177
- framework,
178
- language: { typescript: hasTs },
179
- styling: { primary, detected: Array.from(new Set(detectedStyling)) },
180
- uiLibraries: Array.from(new Set(uiLibraries)),
181
- iconLibraries: Array.from(new Set(iconLibraries)),
182
- tooling: {
183
- storybook: hasStorybook,
184
- eslint: hasEslint,
185
- prettier: hasPrettier,
186
- vitest: hasVitest,
187
- jest: hasJest,
188
- },
189
- conventions: {
190
- srcDir,
191
- hasAppDir,
192
- hasPagesDir,
193
- tsconfigPaths,
194
- },
195
- files: {
196
- packageJson: pkgPath || undefined,
197
- tsconfig: tsconfigPath || undefined,
198
- tailwindConfig: tailwindConfig || undefined,
199
- componentsJson: componentsJson || undefined,
200
- storybookDir: exists(rootDir, '.storybook') || undefined,
201
- },
202
- warnings,
203
- };
218
+ }
219
+
220
+ const tailwindConfig =
221
+ exists(rootDir, 'tailwind.config.ts') ||
222
+ exists(rootDir, 'tailwind.config.js') ||
223
+ exists(rootDir, 'tailwind.config.cjs') ||
224
+ exists(rootDir, 'tailwind.config.mjs');
225
+
226
+ return {
227
+ root: rootDir,
228
+ framework,
229
+ language: { typescript: hasTs },
230
+ styling: { primary, detected: Array.from(new Set(detectedStyling)) },
231
+ uiLibraries: Array.from(new Set(uiLibraries)),
232
+ iconLibraries: Array.from(new Set(iconLibraries)),
233
+ tooling: {
234
+ storybook: hasStorybook,
235
+ eslint: hasEslint,
236
+ prettier: hasPrettier,
237
+ vitest: hasVitest,
238
+ jest: hasJest,
239
+ },
240
+ conventions: {
241
+ srcDir,
242
+ hasAppDir,
243
+ hasPagesDir,
244
+ tsconfigPaths,
245
+ },
246
+ files: {
247
+ packageJson: pkgPath || undefined,
248
+ tsconfig: tsconfigPath || undefined,
249
+ tailwindConfig: tailwindConfig || undefined,
250
+ componentsJson: componentsJson || undefined,
251
+ storybookDir: exists(rootDir, '.storybook') || undefined,
252
+ },
253
+ warnings,
254
+ };
204
255
  }