@gilav21/shadcn-angular 0.0.25 ā 0.0.26
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/add.d.ts +2 -0
- package/dist/commands/add.js +169 -114
- package/dist/commands/add.spec.js +17 -23
- package/dist/commands/diff.d.ts +8 -0
- package/dist/commands/diff.js +99 -0
- package/dist/commands/help.js +15 -6
- package/dist/commands/init.d.ts +2 -0
- package/dist/commands/init.js +171 -185
- package/dist/commands/list.d.ts +1 -0
- package/dist/commands/list.js +50 -0
- package/dist/index.js +21 -1
- package/dist/registry/index.d.ts +122 -12
- package/dist/registry/index.js +56 -168
- package/dist/utils/config.d.ts +1 -1
- package/dist/utils/config.js +22 -2
- package/dist/utils/paths.d.ts +7 -0
- package/dist/utils/paths.js +43 -0
- package/dist/utils/shortcut-registry.js +1 -13
- package/package.json +1 -1
- package/scripts/sync-registry.ts +347 -0
- package/src/commands/add.spec.ts +22 -32
- package/src/commands/add.ts +211 -137
- package/src/commands/diff.ts +133 -0
- package/src/commands/help.ts +15 -6
- package/src/commands/init.ts +329 -314
- package/src/commands/list.ts +66 -0
- package/src/index.ts +24 -1
- package/src/registry/index.ts +71 -180
- package/src/utils/config.ts +22 -3
- package/src/utils/paths.ts +52 -0
- package/src/utils/shortcut-registry.ts +1 -15
- package/vitest.config.ts +7 -0
package/src/commands/init.ts
CHANGED
|
@@ -1,314 +1,329 @@
|
|
|
1
|
-
import fs from 'fs-extra';
|
|
2
|
-
import path from 'node:path';
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
import
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
const
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
},
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
1
|
+
import fs from 'fs-extra';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import prompts from 'prompts';
|
|
4
|
+
import chalk from 'chalk';
|
|
5
|
+
import ora from 'ora';
|
|
6
|
+
import { getDefaultConfig, type Config } from '../utils/config.js';
|
|
7
|
+
import { getStylesTemplate } from '../templates/styles.js';
|
|
8
|
+
import { getUtilsTemplate } from '../templates/utils.js';
|
|
9
|
+
import { installPackages } from '../utils/package-manager.js';
|
|
10
|
+
import { writeShortcutRegistryIndex } from '../utils/shortcut-registry.js';
|
|
11
|
+
import {
|
|
12
|
+
getLibRegistryBaseUrl,
|
|
13
|
+
getLocalLibDir,
|
|
14
|
+
resolveProjectPath,
|
|
15
|
+
aliasToProjectPath,
|
|
16
|
+
} from '../utils/paths.js';
|
|
17
|
+
|
|
18
|
+
const onCancel = () => {
|
|
19
|
+
console.log(chalk.dim('\nCancelled.'));
|
|
20
|
+
process.exit(0);
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
async function fetchLibFileContent(file: string, branch: string, remote?: boolean, registry?: string): Promise<string> {
|
|
24
|
+
const localLibDir = getLocalLibDir();
|
|
25
|
+
if (localLibDir && !remote) {
|
|
26
|
+
const localPath = path.join(localLibDir, file);
|
|
27
|
+
if (await fs.pathExists(localPath)) {
|
|
28
|
+
return fs.readFile(localPath, 'utf-8');
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const url = `${getLibRegistryBaseUrl(branch, registry)}/${file}`;
|
|
33
|
+
const response = await fetch(url);
|
|
34
|
+
if (!response.ok) {
|
|
35
|
+
throw new Error(`Failed to fetch library file from ${url}: ${response.statusText}`);
|
|
36
|
+
}
|
|
37
|
+
return response.text();
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
interface InitOptions {
|
|
41
|
+
yes?: boolean;
|
|
42
|
+
defaults?: boolean;
|
|
43
|
+
remote?: boolean;
|
|
44
|
+
branch: string;
|
|
45
|
+
registry?: string;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
interface InitConfig {
|
|
49
|
+
readonly config: Config;
|
|
50
|
+
readonly createShortcutRegistry: boolean;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function resolveAliasOrPath(cwd: string, aliasOrPath: string): string {
|
|
54
|
+
return resolveProjectPath(cwd, aliasToProjectPath(aliasOrPath));
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function toAlias(inputPath: string): string {
|
|
58
|
+
return inputPath.startsWith('src/')
|
|
59
|
+
? '@/' + inputPath.slice(4)
|
|
60
|
+
: inputPath;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
async function promptForConfig(): Promise<InitConfig> {
|
|
64
|
+
const THEME_COLORS: Record<string, string> = {
|
|
65
|
+
zinc: '#71717a', slate: '#64748b', stone: '#78716c',
|
|
66
|
+
gray: '#6b7280', neutral: '#737373', red: '#ef4444',
|
|
67
|
+
rose: '#f43f5e', orange: '#f97316', green: '#22c55e',
|
|
68
|
+
blue: '#3b82f6', yellow: '#eab308', violet: '#8b5cf6',
|
|
69
|
+
amber: '#d97706',
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
const colorSwatch = (value: string, label: string) =>
|
|
73
|
+
`${chalk.hex(THEME_COLORS[value])('āā')} ${label}`;
|
|
74
|
+
|
|
75
|
+
const themeChoices = [
|
|
76
|
+
'Zinc', 'Slate', 'Stone', 'Gray', 'Neutral',
|
|
77
|
+
'Red', 'Rose', 'Orange', 'Green', 'Blue',
|
|
78
|
+
'Yellow', 'Violet', 'Amber',
|
|
79
|
+
].map(label => {
|
|
80
|
+
const value = label.toLowerCase();
|
|
81
|
+
return { title: colorSwatch(value, label), value };
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
const baseColorChoices = ['Neutral', 'Slate', 'Stone', 'Gray', 'Zinc'].map(label => {
|
|
85
|
+
const value = label.toLowerCase();
|
|
86
|
+
return { title: colorSwatch(value, label), value };
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
const responses = await prompts([
|
|
90
|
+
{
|
|
91
|
+
type: 'select',
|
|
92
|
+
name: 'baseColor',
|
|
93
|
+
message: 'Which color would you like to use as base color?',
|
|
94
|
+
choices: baseColorChoices,
|
|
95
|
+
initial: 0,
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
type: 'select',
|
|
99
|
+
name: 'theme',
|
|
100
|
+
message: 'Which color would you like to use for the main theme?',
|
|
101
|
+
choices: themeChoices,
|
|
102
|
+
initial: (prev: string) => {
|
|
103
|
+
const index = themeChoices.findIndex(c => c.value === prev);
|
|
104
|
+
return index === -1 ? 0 : index;
|
|
105
|
+
},
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
type: 'text',
|
|
109
|
+
name: 'componentsPath',
|
|
110
|
+
message: 'Where would you like to install components?',
|
|
111
|
+
initial: 'src/components/ui',
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
type: 'text',
|
|
115
|
+
name: 'utilsPath',
|
|
116
|
+
message: 'Where would you like to install utils?',
|
|
117
|
+
initial: 'src/components/lib',
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
type: 'text',
|
|
121
|
+
name: 'globalCss',
|
|
122
|
+
message: 'Where is your global styles file?',
|
|
123
|
+
initial: 'src/styles.scss',
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
type: 'confirm',
|
|
127
|
+
name: 'createShortcutRegistry',
|
|
128
|
+
message: 'Would you like to create a shortcut registry scaffold?',
|
|
129
|
+
initial: true,
|
|
130
|
+
},
|
|
131
|
+
], { onCancel });
|
|
132
|
+
|
|
133
|
+
const componentsAlias = toAlias(responses.componentsPath);
|
|
134
|
+
const uiAlias = componentsAlias.endsWith('/ui')
|
|
135
|
+
? componentsAlias
|
|
136
|
+
: componentsAlias + '/ui';
|
|
137
|
+
|
|
138
|
+
return {
|
|
139
|
+
config: {
|
|
140
|
+
style: 'default',
|
|
141
|
+
tailwind: {
|
|
142
|
+
css: responses.globalCss,
|
|
143
|
+
baseColor: responses.baseColor,
|
|
144
|
+
theme: responses.theme,
|
|
145
|
+
cssVariables: true,
|
|
146
|
+
},
|
|
147
|
+
aliases: {
|
|
148
|
+
components: componentsAlias.replace(/\/ui$/, ''),
|
|
149
|
+
utils: toAlias(responses.utilsPath),
|
|
150
|
+
ui: uiAlias,
|
|
151
|
+
},
|
|
152
|
+
},
|
|
153
|
+
createShortcutRegistry: responses.createShortcutRegistry ?? true,
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
async function installMissingDeps(cwd: string): Promise<void> {
|
|
158
|
+
const allDependencies = [
|
|
159
|
+
'clsx', 'tailwind-merge', 'class-variance-authority',
|
|
160
|
+
'tailwindcss', 'postcss', '@tailwindcss/postcss',
|
|
161
|
+
];
|
|
162
|
+
|
|
163
|
+
const packageJsonPath = path.join(cwd, 'package.json');
|
|
164
|
+
let missingDeps = allDependencies;
|
|
165
|
+
if (await fs.pathExists(packageJsonPath)) {
|
|
166
|
+
const packageJson = await fs.readJson(packageJsonPath) as {
|
|
167
|
+
dependencies?: Record<string, string>;
|
|
168
|
+
devDependencies?: Record<string, string>;
|
|
169
|
+
};
|
|
170
|
+
const installed = { ...packageJson.dependencies, ...packageJson.devDependencies };
|
|
171
|
+
missingDeps = allDependencies.filter(dep => !installed[dep]);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
if (missingDeps.length > 0) {
|
|
175
|
+
await installPackages(missingDeps, { cwd });
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
async function setupPostcss(cwd: string): Promise<void> {
|
|
180
|
+
const postcssConfigFiles = [
|
|
181
|
+
'.postcssrc.json', '.postcssrc.js', '.postcssrc.yaml',
|
|
182
|
+
'postcss.config.js', 'postcss.config.cjs', 'postcss.config.mjs',
|
|
183
|
+
];
|
|
184
|
+
const existing = (await Promise.all(
|
|
185
|
+
postcssConfigFiles.map(async f => await fs.pathExists(path.join(cwd, f)) ? f : null)
|
|
186
|
+
)).filter(Boolean);
|
|
187
|
+
|
|
188
|
+
if (existing.length === 0) {
|
|
189
|
+
await fs.writeJson(path.join(cwd, '.postcssrc.json'), {
|
|
190
|
+
plugins: { '@tailwindcss/postcss': {} },
|
|
191
|
+
}, { spaces: 4 });
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
if (!existing.includes('.postcssrc.json')) {
|
|
196
|
+
console.log(chalk.yellow(` Existing PostCSS config found (${existing[0]}). Skipping .postcssrc.json creation.`));
|
|
197
|
+
console.log(chalk.dim(' Make sure @tailwindcss/postcss is configured in your PostCSS config.'));
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
async function autoConfigureTsconfig(cwd: string, spinner: ReturnType<typeof ora>): Promise<void> {
|
|
202
|
+
const tsconfigPath = path.join(cwd, 'tsconfig.json');
|
|
203
|
+
if (!await fs.pathExists(tsconfigPath)) return;
|
|
204
|
+
|
|
205
|
+
try {
|
|
206
|
+
const raw = await fs.readFile(tsconfigPath, 'utf-8');
|
|
207
|
+
const stripped = raw
|
|
208
|
+
.replaceAll(/\/\/.*$/gm, '')
|
|
209
|
+
.replaceAll(/\/\*[\s\S]*?\*\//g, '');
|
|
210
|
+
const tsconfig = JSON.parse(stripped) as {
|
|
211
|
+
compilerOptions?: { baseUrl?: string; paths?: Record<string, string[]> };
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
const compilerOptions = tsconfig.compilerOptions ??= {};
|
|
215
|
+
const paths = compilerOptions.paths ??= {};
|
|
216
|
+
|
|
217
|
+
if (paths['@/*']) return;
|
|
218
|
+
|
|
219
|
+
if (!compilerOptions.baseUrl) {
|
|
220
|
+
compilerOptions.baseUrl = '.';
|
|
221
|
+
}
|
|
222
|
+
paths['@/*'] = ['./src/*'];
|
|
223
|
+
|
|
224
|
+
await fs.writeJson(tsconfigPath, tsconfig, { spaces: 2 });
|
|
225
|
+
spinner.text = 'Configured tsconfig.json paths';
|
|
226
|
+
} catch {
|
|
227
|
+
console.log(chalk.dim(' Could not auto-configure tsconfig.json ā please add "@/*": ["./src/*"] to paths manually.'));
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
export async function init(options: InitOptions) {
|
|
232
|
+
console.log(chalk.bold('\nšØ Welcome to shadcn-angular!\n'));
|
|
233
|
+
|
|
234
|
+
const cwd = process.cwd();
|
|
235
|
+
|
|
236
|
+
const angularJsonPath = path.join(cwd, 'angular.json');
|
|
237
|
+
if (!await fs.pathExists(angularJsonPath)) {
|
|
238
|
+
console.log(chalk.red('Error: This does not appear to be an Angular project.'));
|
|
239
|
+
console.log(chalk.dim('Please run this command in the root of your Angular project.'));
|
|
240
|
+
process.exit(1);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
const componentsJsonPath = path.join(cwd, 'components.json');
|
|
244
|
+
|
|
245
|
+
if (await fs.pathExists(componentsJsonPath)) {
|
|
246
|
+
const overwrite = options.yes
|
|
247
|
+
? true
|
|
248
|
+
: (await prompts({
|
|
249
|
+
type: 'confirm',
|
|
250
|
+
name: 'overwrite',
|
|
251
|
+
message: 'components.json already exists. Overwrite?',
|
|
252
|
+
initial: false,
|
|
253
|
+
}, { onCancel })).overwrite;
|
|
254
|
+
if (!overwrite) {
|
|
255
|
+
console.log(chalk.dim('Initialization cancelled.'));
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
const { config, createShortcutRegistry } = options.defaults || options.yes
|
|
261
|
+
? { config: getDefaultConfig(), createShortcutRegistry: true }
|
|
262
|
+
: await promptForConfig();
|
|
263
|
+
|
|
264
|
+
if (options.registry) {
|
|
265
|
+
config.registry = options.registry;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
const spinner = ora('Initializing project...').start();
|
|
269
|
+
|
|
270
|
+
try {
|
|
271
|
+
await fs.writeJson(componentsJsonPath, config, { spaces: 2 });
|
|
272
|
+
spinner.text = 'Created components.json';
|
|
273
|
+
|
|
274
|
+
const libDir = resolveAliasOrPath(cwd, config.aliases.utils);
|
|
275
|
+
await fs.ensureDir(libDir);
|
|
276
|
+
await fs.writeFile(path.join(libDir, 'utils.ts'), getUtilsTemplate());
|
|
277
|
+
spinner.text = 'Created utils.ts';
|
|
278
|
+
|
|
279
|
+
if (createShortcutRegistry) {
|
|
280
|
+
const content = await fetchLibFileContent('shortcut-binding.service.ts', options.branch, options.remote, options.registry);
|
|
281
|
+
await fs.writeFile(path.join(libDir, 'shortcut-binding.service.ts'), content);
|
|
282
|
+
spinner.text = 'Created shortcut-binding.service.ts';
|
|
283
|
+
|
|
284
|
+
await writeShortcutRegistryIndex(cwd, config, []);
|
|
285
|
+
spinner.text = 'Created shortcut-registry.index.ts';
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
const userStylesPath = resolveProjectPath(cwd, config.tailwind.css);
|
|
289
|
+
const stylesDir = path.dirname(userStylesPath);
|
|
290
|
+
|
|
291
|
+
await fs.ensureDir(stylesDir);
|
|
292
|
+
await fs.writeFile(path.join(stylesDir, 'tailwind.css'), getStylesTemplate(config.tailwind.baseColor, config.tailwind.theme));
|
|
293
|
+
spinner.text = 'Created tailwind.css';
|
|
294
|
+
|
|
295
|
+
let userStyles = await fs.pathExists(userStylesPath)
|
|
296
|
+
? await fs.readFile(userStylesPath, 'utf-8')
|
|
297
|
+
: '';
|
|
298
|
+
|
|
299
|
+
if (!userStyles.includes('tailwind.css')) {
|
|
300
|
+
userStyles = '@import "./tailwind.css";\n\n' + userStyles;
|
|
301
|
+
await fs.writeFile(userStylesPath, userStyles);
|
|
302
|
+
spinner.text = 'Added tailwind.css import to styles';
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
const uiDir = resolveAliasOrPath(cwd, config.aliases.ui);
|
|
306
|
+
await fs.ensureDir(uiDir);
|
|
307
|
+
spinner.text = 'Created components directory';
|
|
308
|
+
|
|
309
|
+
spinner.text = 'Installing dependencies...';
|
|
310
|
+
await installMissingDeps(cwd);
|
|
311
|
+
|
|
312
|
+
spinner.text = 'Configuring PostCSS...';
|
|
313
|
+
await setupPostcss(cwd);
|
|
314
|
+
|
|
315
|
+
await autoConfigureTsconfig(cwd, spinner);
|
|
316
|
+
|
|
317
|
+
spinner.succeed(chalk.green('Project initialized successfully!'));
|
|
318
|
+
|
|
319
|
+
console.log('\n' + chalk.bold('Next steps:'));
|
|
320
|
+
console.log(chalk.dim(' 1. Add components: ') + chalk.cyan('npx @gilav21/shadcn-angular add button'));
|
|
321
|
+
console.log(chalk.dim(' 2. Import and use in your templates'));
|
|
322
|
+
console.log('');
|
|
323
|
+
|
|
324
|
+
} catch (error) {
|
|
325
|
+
spinner.fail('Failed to initialize project');
|
|
326
|
+
console.error(error);
|
|
327
|
+
process.exit(1);
|
|
328
|
+
}
|
|
329
|
+
}
|