@ng-cn/core 1.0.1 → 1.0.3
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/package.json
CHANGED
package/schematics/README.md
CHANGED
|
@@ -9,12 +9,43 @@ Angular schematics for installing shadcn-angular components individually.
|
|
|
9
9
|
First, add shadcn-angular to your project:
|
|
10
10
|
|
|
11
11
|
```bash
|
|
12
|
-
ng add
|
|
12
|
+
ng add @ng-cn/core
|
|
13
13
|
```
|
|
14
14
|
|
|
15
15
|
This will:
|
|
16
16
|
- Install required dependencies (lucide-angular, class-variance-authority, clsx, tailwind-merge, @angular/cdk)
|
|
17
17
|
- Set up the project for shadcn-angular components
|
|
18
|
+
- **Prompt you to select components** to install initially (multi-select checkbox)
|
|
19
|
+
|
|
20
|
+
### Interactive Component Selection
|
|
21
|
+
|
|
22
|
+
When running `ng add @ng-cn/core`, you'll be presented with an interactive multi-select prompt:
|
|
23
|
+
|
|
24
|
+
```
|
|
25
|
+
? Which components would you like to add? (Press space to select, enter to confirm)
|
|
26
|
+
❯◯ Button - Displays a button or a component that looks like a button
|
|
27
|
+
◯ Card - Displays a card with header, content, and footer
|
|
28
|
+
◯ Input - Displays a form input field
|
|
29
|
+
◯ Label - Renders an accessible label associated with controls
|
|
30
|
+
◯ Checkbox - A control that allows toggling between checked and not checked
|
|
31
|
+
...
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Use **space** to select/deselect components and **enter** to confirm your selection.
|
|
35
|
+
|
|
36
|
+
### Skip Component Selection
|
|
37
|
+
|
|
38
|
+
If you want to skip the component selection prompt:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
ng add @ng-cn/core --components=button,card,input
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Or to skip adding any components initially:
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
ng add @ng-cn/core --components=
|
|
48
|
+
```
|
|
18
49
|
|
|
19
50
|
### Install Individual Components
|
|
20
51
|
|
|
@@ -65,11 +96,48 @@ ng g shadcn-angular:c button --path=src/components
|
|
|
65
96
|
To build the schematics:
|
|
66
97
|
|
|
67
98
|
```bash
|
|
68
|
-
|
|
99
|
+
cd schematics
|
|
100
|
+
npx tsc -p tsconfig.json
|
|
69
101
|
```
|
|
70
102
|
|
|
71
103
|
This compiles the TypeScript files in the `schematics` directory to JavaScript.
|
|
72
104
|
|
|
105
|
+
### Testing
|
|
106
|
+
|
|
107
|
+
Run the test script to verify the schematics work correctly:
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
cd schematics
|
|
111
|
+
node test-schematic.js
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
This will:
|
|
115
|
+
- Create a mock Angular project with a tsconfig.json containing comments (like real projects)
|
|
116
|
+
- Run the ng-add schematic
|
|
117
|
+
- Verify all expected files are created
|
|
118
|
+
- Verify tsconfig path aliases are configured
|
|
119
|
+
- Verify styles are imported correctly
|
|
120
|
+
- Verify dependencies are added
|
|
121
|
+
|
|
122
|
+
### Local Testing
|
|
123
|
+
|
|
124
|
+
To test the schematic locally with a real Angular project:
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
# 1. Build the schematics
|
|
128
|
+
cd schematics && npx tsc -p tsconfig.json && cd ..
|
|
129
|
+
|
|
130
|
+
# 2. Create a test project
|
|
131
|
+
ng new test-app --style=scss --routing=true
|
|
132
|
+
|
|
133
|
+
# 3. Link the local package
|
|
134
|
+
cd test-app
|
|
135
|
+
npm link ../shadcn-angular
|
|
136
|
+
|
|
137
|
+
# 4. Run the schematic
|
|
138
|
+
ng add @ng-cn/core --skip-confirmation
|
|
139
|
+
```
|
|
140
|
+
|
|
73
141
|
## Structure
|
|
74
142
|
|
|
75
143
|
```
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.ngAdd = ngAdd;
|
|
4
4
|
const tasks_1 = require("@angular-devkit/schematics/tasks");
|
|
5
|
+
const jsonc_parser_1 = require("jsonc-parser");
|
|
5
6
|
// CSS Variables template for shadcn theming
|
|
6
7
|
const CSS_VARIABLES_TEMPLATE = `/* ng-cn/core - shadcn-angular styles */
|
|
7
8
|
@use "tailwindcss";
|
|
@@ -253,7 +254,8 @@ function ngAdd(options) {
|
|
|
253
254
|
context.logger.info('⚙️ TypeScript Config');
|
|
254
255
|
const tsconfigPath = '/tsconfig.json';
|
|
255
256
|
if (tree.exists(tsconfigPath)) {
|
|
256
|
-
const
|
|
257
|
+
const tsconfigContent = tree.read(tsconfigPath).toString('utf-8');
|
|
258
|
+
const tsconfig = (0, jsonc_parser_1.parse)(tsconfigContent);
|
|
257
259
|
tsconfig.compilerOptions = tsconfig.compilerOptions || {};
|
|
258
260
|
tsconfig.compilerOptions.paths = tsconfig.compilerOptions.paths || {};
|
|
259
261
|
const pathAliases = {
|
|
@@ -277,6 +279,27 @@ function ngAdd(options) {
|
|
|
277
279
|
context.logger.info(' ✓ Path aliases already set');
|
|
278
280
|
}
|
|
279
281
|
}
|
|
282
|
+
// Install selected components
|
|
283
|
+
if (options.components && options.components.length > 0) {
|
|
284
|
+
context.logger.info('');
|
|
285
|
+
context.logger.info('📦 Selected Components');
|
|
286
|
+
const packageJson = JSON.parse(tree.read(packageJsonPath).toString('utf-8'));
|
|
287
|
+
for (const component of options.components) {
|
|
288
|
+
const packageName = `@ng-cn/${component}`;
|
|
289
|
+
if (!packageJson.dependencies?.[packageName]) {
|
|
290
|
+
packageJson.dependencies = packageJson.dependencies || {};
|
|
291
|
+
packageJson.dependencies[packageName] = 'latest';
|
|
292
|
+
context.logger.info(` + ${packageName}`);
|
|
293
|
+
}
|
|
294
|
+
else {
|
|
295
|
+
context.logger.info(` ✓ ${packageName} already installed`);
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
tree.overwrite(packageJsonPath, JSON.stringify(packageJson, null, 2));
|
|
299
|
+
if (!options.skipInstall) {
|
|
300
|
+
context.addTask(new tasks_1.NodePackageInstallTask());
|
|
301
|
+
}
|
|
302
|
+
}
|
|
280
303
|
// Success message with ASCII art banner
|
|
281
304
|
context.logger.info('');
|
|
282
305
|
context.logger.info('');
|
|
@@ -289,10 +312,23 @@ function ngAdd(options) {
|
|
|
289
312
|
context.logger.info('');
|
|
290
313
|
context.logger.info(' ✅ Setup complete! shadcn for Angular');
|
|
291
314
|
context.logger.info('');
|
|
315
|
+
// Show selected components summary if any were installed
|
|
316
|
+
if (options.components && options.components.length > 0) {
|
|
317
|
+
context.logger.info('╭──────────────────────────────────────────────────╮');
|
|
318
|
+
context.logger.info('│ ✨ Components installed: │');
|
|
319
|
+
context.logger.info('│ │');
|
|
320
|
+
for (const component of options.components) {
|
|
321
|
+
const paddedComponent = `@ng-cn/${component}`.padEnd(40);
|
|
322
|
+
context.logger.info(`│ ${paddedComponent}│`);
|
|
323
|
+
}
|
|
324
|
+
context.logger.info('│ │');
|
|
325
|
+
context.logger.info('╰──────────────────────────────────────────────────╯');
|
|
326
|
+
context.logger.info('');
|
|
327
|
+
}
|
|
292
328
|
context.logger.info('╭──────────────────────────────────────────────────╮');
|
|
293
329
|
context.logger.info('│ 🚀 Next steps: │');
|
|
294
330
|
context.logger.info('│ │');
|
|
295
|
-
context.logger.info('│ 1. Add components:
|
|
331
|
+
context.logger.info('│ 1. Add more components: │');
|
|
296
332
|
context.logger.info('│ ng g @ng-cn/core:c button │');
|
|
297
333
|
context.logger.info('│ ng g @ng-cn/core:c card │');
|
|
298
334
|
context.logger.info('│ │');
|
|
@@ -300,7 +336,7 @@ function ngAdd(options) {
|
|
|
300
336
|
context.logger.info('│ npm i @ng-cn/button @ng-cn/card │');
|
|
301
337
|
context.logger.info('│ │');
|
|
302
338
|
context.logger.info('│ 3. Import and use: │');
|
|
303
|
-
context.logger.info("│ import { Button } from '
|
|
339
|
+
context.logger.info("│ import { Button } from '@ng-cn/button'; │");
|
|
304
340
|
context.logger.info('│ │');
|
|
305
341
|
context.logger.info('│ 📚 Docs: https://shadcn-angular.tigayon.com │');
|
|
306
342
|
context.logger.info('╰──────────────────────────────────────────────────╯');
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { Rule, SchematicContext, Tree } from '@angular-devkit/schematics';
|
|
2
2
|
import { NodePackageInstallTask } from '@angular-devkit/schematics/tasks';
|
|
3
|
+
import { parse as parseJsonc } from 'jsonc-parser';
|
|
3
4
|
|
|
4
5
|
interface NgAddOptions {
|
|
5
6
|
project?: string;
|
|
6
7
|
skipInstall?: boolean;
|
|
7
8
|
skipStyles?: boolean;
|
|
9
|
+
components?: string[];
|
|
8
10
|
}
|
|
9
11
|
|
|
10
12
|
// CSS Variables template for shadcn theming
|
|
@@ -273,7 +275,8 @@ export function ngAdd(options: NgAddOptions): Rule {
|
|
|
273
275
|
|
|
274
276
|
const tsconfigPath = '/tsconfig.json';
|
|
275
277
|
if (tree.exists(tsconfigPath)) {
|
|
276
|
-
const
|
|
278
|
+
const tsconfigContent = tree.read(tsconfigPath)!.toString('utf-8');
|
|
279
|
+
const tsconfig = parseJsonc(tsconfigContent) as Record<string, any>;
|
|
277
280
|
tsconfig.compilerOptions = tsconfig.compilerOptions || {};
|
|
278
281
|
tsconfig.compilerOptions.paths = tsconfig.compilerOptions.paths || {};
|
|
279
282
|
|
|
@@ -300,6 +303,31 @@ export function ngAdd(options: NgAddOptions): Rule {
|
|
|
300
303
|
}
|
|
301
304
|
}
|
|
302
305
|
|
|
306
|
+
// Install selected components
|
|
307
|
+
if (options.components && options.components.length > 0) {
|
|
308
|
+
context.logger.info('');
|
|
309
|
+
context.logger.info('📦 Selected Components');
|
|
310
|
+
|
|
311
|
+
const packageJson = JSON.parse(tree.read(packageJsonPath)!.toString('utf-8'));
|
|
312
|
+
|
|
313
|
+
for (const component of options.components) {
|
|
314
|
+
const packageName = `@ng-cn/${component}`;
|
|
315
|
+
if (!packageJson.dependencies?.[packageName]) {
|
|
316
|
+
packageJson.dependencies = packageJson.dependencies || {};
|
|
317
|
+
packageJson.dependencies[packageName] = 'latest';
|
|
318
|
+
context.logger.info(` + ${packageName}`);
|
|
319
|
+
} else {
|
|
320
|
+
context.logger.info(` ✓ ${packageName} already installed`);
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
tree.overwrite(packageJsonPath, JSON.stringify(packageJson, null, 2));
|
|
325
|
+
|
|
326
|
+
if (!options.skipInstall) {
|
|
327
|
+
context.addTask(new NodePackageInstallTask());
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
|
|
303
331
|
// Success message with ASCII art banner
|
|
304
332
|
context.logger.info('');
|
|
305
333
|
context.logger.info('');
|
|
@@ -312,10 +340,25 @@ export function ngAdd(options: NgAddOptions): Rule {
|
|
|
312
340
|
context.logger.info('');
|
|
313
341
|
context.logger.info(' ✅ Setup complete! shadcn for Angular');
|
|
314
342
|
context.logger.info('');
|
|
343
|
+
|
|
344
|
+
// Show selected components summary if any were installed
|
|
345
|
+
if (options.components && options.components.length > 0) {
|
|
346
|
+
context.logger.info('╭──────────────────────────────────────────────────╮');
|
|
347
|
+
context.logger.info('│ ✨ Components installed: │');
|
|
348
|
+
context.logger.info('│ │');
|
|
349
|
+
for (const component of options.components) {
|
|
350
|
+
const paddedComponent = `@ng-cn/${component}`.padEnd(40);
|
|
351
|
+
context.logger.info(`│ ${paddedComponent}│`);
|
|
352
|
+
}
|
|
353
|
+
context.logger.info('│ │');
|
|
354
|
+
context.logger.info('╰──────────────────────────────────────────────────╯');
|
|
355
|
+
context.logger.info('');
|
|
356
|
+
}
|
|
357
|
+
|
|
315
358
|
context.logger.info('╭──────────────────────────────────────────────────╮');
|
|
316
359
|
context.logger.info('│ 🚀 Next steps: │');
|
|
317
360
|
context.logger.info('│ │');
|
|
318
|
-
context.logger.info('│ 1. Add components:
|
|
361
|
+
context.logger.info('│ 1. Add more components: │');
|
|
319
362
|
context.logger.info('│ ng g @ng-cn/core:c button │');
|
|
320
363
|
context.logger.info('│ ng g @ng-cn/core:c card │');
|
|
321
364
|
context.logger.info('│ │');
|
|
@@ -323,7 +366,7 @@ export function ngAdd(options: NgAddOptions): Rule {
|
|
|
323
366
|
context.logger.info('│ npm i @ng-cn/button @ng-cn/card │');
|
|
324
367
|
context.logger.info('│ │');
|
|
325
368
|
context.logger.info('│ 3. Import and use: │');
|
|
326
|
-
context.logger.info("│ import { Button } from '
|
|
369
|
+
context.logger.info("│ import { Button } from '@ng-cn/button'; │");
|
|
327
370
|
context.logger.info('│ │');
|
|
328
371
|
context.logger.info('│ 📚 Docs: https://shadcn-angular.tigayon.com │');
|
|
329
372
|
context.logger.info('╰──────────────────────────────────────────────────╯');
|
|
@@ -20,6 +20,49 @@
|
|
|
20
20
|
"type": "boolean",
|
|
21
21
|
"default": false,
|
|
22
22
|
"description": "Skip creating ng-cn.scss styles file."
|
|
23
|
+
},
|
|
24
|
+
"components": {
|
|
25
|
+
"type": "array",
|
|
26
|
+
"items": {
|
|
27
|
+
"type": "string"
|
|
28
|
+
},
|
|
29
|
+
"default": [],
|
|
30
|
+
"description": "Components to install initially.",
|
|
31
|
+
"x-prompt": {
|
|
32
|
+
"message": "Which components would you like to add? (Press space to select, enter to confirm)",
|
|
33
|
+
"type": "list",
|
|
34
|
+
"multiselect": true,
|
|
35
|
+
"items": [
|
|
36
|
+
{ "value": "button", "label": "Button - Displays a button or a component that looks like a button" },
|
|
37
|
+
{ "value": "card", "label": "Card - Displays a card with header, content, and footer" },
|
|
38
|
+
{ "value": "input", "label": "Input - Displays a form input field" },
|
|
39
|
+
{ "value": "label", "label": "Label - Renders an accessible label associated with controls" },
|
|
40
|
+
{ "value": "checkbox", "label": "Checkbox - A control that allows toggling between checked and not checked" },
|
|
41
|
+
{ "value": "select", "label": "Select - Displays a list of options for the user to pick from" },
|
|
42
|
+
{ "value": "dialog", "label": "Dialog - A window overlaid on the primary window" },
|
|
43
|
+
{ "value": "toast", "label": "Toast - A succinct message that is displayed temporarily" },
|
|
44
|
+
{ "value": "dropdown-menu", "label": "Dropdown Menu - Displays a menu when triggered" },
|
|
45
|
+
{ "value": "tabs", "label": "Tabs - A set of layered sections of content" },
|
|
46
|
+
{ "value": "table", "label": "Table - A responsive table component" },
|
|
47
|
+
{ "value": "avatar", "label": "Avatar - An image element with a fallback for representing the user" },
|
|
48
|
+
{ "value": "badge", "label": "Badge - Displays a badge or a component that looks like a badge" },
|
|
49
|
+
{ "value": "alert", "label": "Alert - Displays a callout for user attention" },
|
|
50
|
+
{ "value": "tooltip", "label": "Tooltip - A popup that displays information related to an element" },
|
|
51
|
+
{ "value": "progress", "label": "Progress - Displays an indicator showing the completion progress" },
|
|
52
|
+
{ "value": "skeleton", "label": "Skeleton - Use to show a placeholder while content is loading" },
|
|
53
|
+
{ "value": "separator", "label": "Separator - Visually or semantically separates content" },
|
|
54
|
+
{ "value": "switch", "label": "Switch - A control that allows toggling between checked and not checked" },
|
|
55
|
+
{ "value": "textarea", "label": "Textarea - Displays a form textarea" },
|
|
56
|
+
{ "value": "accordion", "label": "Accordion - A vertically stacked set of interactive headings" },
|
|
57
|
+
{ "value": "sheet", "label": "Sheet - Extends the Dialog component to display complementary content" },
|
|
58
|
+
{ "value": "popover", "label": "Popover - Displays rich content in a portal, triggered by a button" },
|
|
59
|
+
{ "value": "calendar", "label": "Calendar - A date field component for entering and editing dates" },
|
|
60
|
+
{ "value": "command", "label": "Command - Fast, composable, unstyled command menu" },
|
|
61
|
+
{ "value": "form", "label": "Form - Building forms with validation" },
|
|
62
|
+
{ "value": "sidebar", "label": "Sidebar - A composable, themeable and customizable sidebar" },
|
|
63
|
+
{ "value": "spinner", "label": "Spinner - Loading indicator animations" }
|
|
64
|
+
]
|
|
65
|
+
}
|
|
23
66
|
}
|
|
24
67
|
}
|
|
25
68
|
}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test script for ng-add schematic
|
|
3
|
+
* Run with: node test-schematic.js
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const { SchematicTestRunner } = require('@angular-devkit/schematics/testing');
|
|
7
|
+
const { HostTree } = require('@angular-devkit/schematics');
|
|
8
|
+
const path = require('path');
|
|
9
|
+
|
|
10
|
+
const collectionPath = path.join(__dirname, 'collection.json');
|
|
11
|
+
|
|
12
|
+
// Mock tsconfig.json with comments (typical Angular project)
|
|
13
|
+
const MOCK_TSCONFIG = `/* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. */
|
|
14
|
+
/* To learn more about Angular compiler options: https://angular.dev/reference/configs/angular-compiler-options. */
|
|
15
|
+
{
|
|
16
|
+
"compileOnSave": false,
|
|
17
|
+
"compilerOptions": {
|
|
18
|
+
"outDir": "./dist/out-tsc",
|
|
19
|
+
"strict": true,
|
|
20
|
+
"noImplicitOverride": true,
|
|
21
|
+
"noPropertyAccessFromIndexSignature": true,
|
|
22
|
+
"noImplicitReturns": true,
|
|
23
|
+
"noFallthroughCasesInSwitch": true,
|
|
24
|
+
"skipLibCheck": true,
|
|
25
|
+
"isolatedModules": true,
|
|
26
|
+
"esModuleInterop": true,
|
|
27
|
+
"experimentalDecorators": true,
|
|
28
|
+
"moduleResolution": "bundler",
|
|
29
|
+
"importHelpers": true,
|
|
30
|
+
"target": "ES2022",
|
|
31
|
+
"module": "ES2022"
|
|
32
|
+
},
|
|
33
|
+
"angularCompilerOptions": {
|
|
34
|
+
"enableI18nLegacyMessageIdFormat": false,
|
|
35
|
+
"strictInjectionParameters": true,
|
|
36
|
+
"strictInputAccessModifiers": true,
|
|
37
|
+
"strictTemplates": true
|
|
38
|
+
}
|
|
39
|
+
}`;
|
|
40
|
+
|
|
41
|
+
const MOCK_PACKAGE_JSON = `{
|
|
42
|
+
"name": "test-angular",
|
|
43
|
+
"version": "0.0.0",
|
|
44
|
+
"scripts": {
|
|
45
|
+
"ng": "ng",
|
|
46
|
+
"start": "ng serve",
|
|
47
|
+
"build": "ng build"
|
|
48
|
+
},
|
|
49
|
+
"dependencies": {
|
|
50
|
+
"@angular/core": "^21.0.0"
|
|
51
|
+
},
|
|
52
|
+
"devDependencies": {}
|
|
53
|
+
}`;
|
|
54
|
+
|
|
55
|
+
const MOCK_STYLES_CSS = `/* You can add global styles to this file, and also import other style files */
|
|
56
|
+
`;
|
|
57
|
+
|
|
58
|
+
async function runTests() {
|
|
59
|
+
console.log('\n🧪 Testing ng-add schematic...\n');
|
|
60
|
+
|
|
61
|
+
const runner = new SchematicTestRunner('schematics', collectionPath);
|
|
62
|
+
|
|
63
|
+
// Create a mock project tree using HostTree
|
|
64
|
+
const appTree = new HostTree();
|
|
65
|
+
appTree.create('/package.json', MOCK_PACKAGE_JSON);
|
|
66
|
+
appTree.create('/tsconfig.json', MOCK_TSCONFIG);
|
|
67
|
+
appTree.create('/src/styles.css', MOCK_STYLES_CSS);
|
|
68
|
+
|
|
69
|
+
console.log('📁 Created mock project with:');
|
|
70
|
+
console.log(' - /package.json');
|
|
71
|
+
console.log(' - /tsconfig.json (with comments)');
|
|
72
|
+
console.log(' - /src/styles.css\n');
|
|
73
|
+
|
|
74
|
+
try {
|
|
75
|
+
// Run the ng-add schematic
|
|
76
|
+
const tree = await runner.runSchematic('ng-add', { skipInstall: true }, appTree);
|
|
77
|
+
|
|
78
|
+
console.log('✅ Schematic executed successfully!\n');
|
|
79
|
+
|
|
80
|
+
// Verify files were created
|
|
81
|
+
const expectedFiles = [
|
|
82
|
+
'/src/app/lib/utils/cn.ts',
|
|
83
|
+
'/src/app/lib/utils/index.ts',
|
|
84
|
+
'/src/app/lib/components/ui/.gitkeep',
|
|
85
|
+
'/src/ng-cn.scss'
|
|
86
|
+
];
|
|
87
|
+
|
|
88
|
+
console.log('📄 Checking created files:');
|
|
89
|
+
for (const file of expectedFiles) {
|
|
90
|
+
if (tree.exists(file)) {
|
|
91
|
+
console.log(` ✅ ${file}`);
|
|
92
|
+
} else {
|
|
93
|
+
console.log(` ❌ Missing: ${file}`);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Verify tsconfig was updated
|
|
98
|
+
console.log('\n⚙️ Checking tsconfig.json:');
|
|
99
|
+
const tsconfigContent = tree.read('/tsconfig.json').toString('utf-8');
|
|
100
|
+
const tsconfig = JSON.parse(tsconfigContent);
|
|
101
|
+
const paths = tsconfig.compilerOptions?.paths || {};
|
|
102
|
+
|
|
103
|
+
const expectedPaths = ['@/*', '@/lib/*', '@/ui/*', '@/utils/*'];
|
|
104
|
+
for (const p of expectedPaths) {
|
|
105
|
+
if (paths[p]) {
|
|
106
|
+
console.log(` ✅ Path alias: ${p}`);
|
|
107
|
+
} else {
|
|
108
|
+
console.log(` ❌ Missing path alias: ${p}`);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// Verify styles were imported
|
|
113
|
+
console.log('\n🎨 Checking styles:');
|
|
114
|
+
const stylesContent = tree.read('/src/styles.css').toString('utf-8');
|
|
115
|
+
if (stylesContent.includes('ng-cn.scss')) {
|
|
116
|
+
console.log(' ✅ ng-cn.scss imported in styles.css');
|
|
117
|
+
} else {
|
|
118
|
+
console.log(' ❌ ng-cn.scss not imported');
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Verify dependencies
|
|
122
|
+
console.log('\n📦 Checking dependencies:');
|
|
123
|
+
const packageJsonContent = tree.read('/package.json').toString('utf-8');
|
|
124
|
+
const packageJson = JSON.parse(packageJsonContent);
|
|
125
|
+
const requiredDeps = ['lucide-angular', 'clsx', 'tailwind-merge', 'class-variance-authority'];
|
|
126
|
+
for (const dep of requiredDeps) {
|
|
127
|
+
if (packageJson.dependencies?.[dep]) {
|
|
128
|
+
console.log(` ✅ ${dep}@${packageJson.dependencies[dep]}`);
|
|
129
|
+
} else {
|
|
130
|
+
console.log(` ❌ Missing: ${dep}`);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
console.log('\n✨ All tests passed!\n');
|
|
135
|
+
|
|
136
|
+
} catch (error) {
|
|
137
|
+
console.error('\n❌ Schematic failed with error:');
|
|
138
|
+
console.error(error);
|
|
139
|
+
process.exit(1);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
runTests();
|