@gilav21/shadcn-angular 0.0.24 → 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 +59 -158
- 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 +73 -169
- 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
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import fs from 'fs-extra';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import chalk from 'chalk';
|
|
4
|
+
import { getConfig } from '../utils/config.js';
|
|
5
|
+
import { registry, getComponentNames, type ComponentName } from '../registry/index.js';
|
|
6
|
+
import { resolveProjectPath, aliasToProjectPath } from '../utils/paths.js';
|
|
7
|
+
import { fetchAndTransform, normalizeContent } from './add.js';
|
|
8
|
+
|
|
9
|
+
interface DiffOptions {
|
|
10
|
+
branch: string;
|
|
11
|
+
remote?: boolean;
|
|
12
|
+
registry?: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function formatLineDiff(localLine: string | undefined, remoteLine: string | undefined): string[] {
|
|
16
|
+
if (localLine !== undefined && remoteLine !== undefined) {
|
|
17
|
+
return [chalk.red(`- ${localLine}`), chalk.green(`+ ${remoteLine}`)];
|
|
18
|
+
}
|
|
19
|
+
if (localLine === undefined) {
|
|
20
|
+
return [chalk.green(`+ ${remoteLine}`)];
|
|
21
|
+
}
|
|
22
|
+
return [chalk.red(`- ${localLine}`)];
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function formatUnifiedDiff(fileName: string, localContent: string, remoteContent: string): string {
|
|
26
|
+
const localLines = localContent.split('\n');
|
|
27
|
+
const remoteLines = remoteContent.split('\n');
|
|
28
|
+
const output: string[] = [
|
|
29
|
+
chalk.bold(`--- local/${fileName}`),
|
|
30
|
+
chalk.bold(`+++ remote/${fileName}`),
|
|
31
|
+
];
|
|
32
|
+
|
|
33
|
+
const maxLines = Math.max(localLines.length, remoteLines.length);
|
|
34
|
+
let diffFound = false;
|
|
35
|
+
|
|
36
|
+
for (let i = 0; i < maxLines; i++) {
|
|
37
|
+
const localLine = localLines[i];
|
|
38
|
+
const remoteLine = remoteLines[i];
|
|
39
|
+
|
|
40
|
+
if (localLine === remoteLine) continue;
|
|
41
|
+
|
|
42
|
+
diffFound = true;
|
|
43
|
+
output.push(chalk.cyan(`@@ line ${i + 1} @@`), ...formatLineDiff(localLine, remoteLine));
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return diffFound ? output.join('\n') : '';
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
async function diffFile(
|
|
50
|
+
file: string,
|
|
51
|
+
targetDir: string,
|
|
52
|
+
options: DiffOptions,
|
|
53
|
+
utilsAlias: string,
|
|
54
|
+
): Promise<string | null> {
|
|
55
|
+
const targetPath = path.join(targetDir, file);
|
|
56
|
+
if (!await fs.pathExists(targetPath)) return null;
|
|
57
|
+
|
|
58
|
+
try {
|
|
59
|
+
const localContent = normalizeContent(await fs.readFile(targetPath, 'utf-8'));
|
|
60
|
+
const remoteContent = normalizeContent(
|
|
61
|
+
await fetchAndTransform(file, { branch: options.branch, remote: options.remote, registry: options.registry }, utilsAlias),
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
if (localContent === remoteContent) return null;
|
|
65
|
+
|
|
66
|
+
const diffOutput = formatUnifiedDiff(file, localContent, remoteContent);
|
|
67
|
+
return diffOutput || null;
|
|
68
|
+
} catch {
|
|
69
|
+
return chalk.yellow(` Could not fetch remote version of ${file}`);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
async function diffComponent(
|
|
74
|
+
name: ComponentName,
|
|
75
|
+
targetDir: string,
|
|
76
|
+
options: DiffOptions,
|
|
77
|
+
utilsAlias: string,
|
|
78
|
+
): Promise<string[]> {
|
|
79
|
+
const component = registry[name];
|
|
80
|
+
const fileDiffs: string[] = [];
|
|
81
|
+
|
|
82
|
+
for (const file of component.files) {
|
|
83
|
+
const result = await diffFile(file, targetDir, options, utilsAlias);
|
|
84
|
+
if (result) fileDiffs.push(result);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
return fileDiffs;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export async function diff(components: string[], options: DiffOptions) {
|
|
91
|
+
const cwd = process.cwd();
|
|
92
|
+
|
|
93
|
+
const config = await getConfig(cwd);
|
|
94
|
+
if (!config) {
|
|
95
|
+
console.log(chalk.red('Error: components.json not found.'));
|
|
96
|
+
console.log(chalk.dim('Run `npx @gilav21/shadcn-angular init` first.'));
|
|
97
|
+
process.exit(1);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if (!options.registry && config.registry) {
|
|
101
|
+
options.registry = config.registry;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const uiBasePath = aliasToProjectPath(config.aliases.ui || 'src/components/ui');
|
|
105
|
+
const targetDir = resolveProjectPath(cwd, uiBasePath);
|
|
106
|
+
const utilsAlias = config.aliases.utils;
|
|
107
|
+
|
|
108
|
+
const names = components.length > 0
|
|
109
|
+
? components as ComponentName[]
|
|
110
|
+
: getComponentNames();
|
|
111
|
+
|
|
112
|
+
let totalDiffs = 0;
|
|
113
|
+
|
|
114
|
+
for (const name of names) {
|
|
115
|
+
if (!(name in registry)) {
|
|
116
|
+
console.log(chalk.red(`Unknown component: ${name}`));
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const fileDiffs = await diffComponent(name, targetDir, options, utilsAlias);
|
|
121
|
+
if (fileDiffs.length > 0) {
|
|
122
|
+
totalDiffs++;
|
|
123
|
+
console.log(chalk.bold.cyan(`\n${name}:`));
|
|
124
|
+
for (const d of fileDiffs) console.log(d);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
if (totalDiffs === 0) {
|
|
129
|
+
console.log(chalk.green('\nAll installed components are up to date.'));
|
|
130
|
+
} else {
|
|
131
|
+
console.log(chalk.dim(`\n${totalDiffs} component(s) have differences.`));
|
|
132
|
+
}
|
|
133
|
+
}
|
package/src/commands/help.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
|
-
import { registry } from '../registry/index.js';
|
|
2
|
+
import { registry, getComponentNames } from '../registry/index.js';
|
|
3
3
|
|
|
4
4
|
type Category = 'UI' | 'Charts' | 'Layout / Page Building' | 'Animation' | 'Kanban';
|
|
5
5
|
|
|
@@ -17,8 +17,8 @@ const KANBAN_COMPONENTS = new Set(['kanban']);
|
|
|
17
17
|
const LAYOUT_COMPONENTS = new Set(['bento-grid', 'page-builder']);
|
|
18
18
|
|
|
19
19
|
function categorize(name: string): Category {
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
if (!(name in registry)) return 'UI';
|
|
21
|
+
const def = registry[name as keyof typeof registry];
|
|
22
22
|
|
|
23
23
|
const hasChartFile = def.files.some(f => f.startsWith('charts/'));
|
|
24
24
|
if (hasChartFile) return 'Charts';
|
|
@@ -37,14 +37,14 @@ function buildComponentsByCategory(): Map<Category, readonly string[]> {
|
|
|
37
37
|
groups.set(cat, []);
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
for (const name of
|
|
40
|
+
for (const name of getComponentNames()) {
|
|
41
41
|
const cat = categorize(name);
|
|
42
42
|
const list = groups.get(cat);
|
|
43
43
|
if (list) list.push(name);
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
for (const list of groups.values()) {
|
|
47
|
-
list.sort();
|
|
47
|
+
list.sort((a, b) => a.localeCompare(b));
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
return groups;
|
|
@@ -71,17 +71,26 @@ function buildCommandsSection(): string[] {
|
|
|
71
71
|
' ' + chalk.cyan('init') + ' Initialize shadcn-angular in your project',
|
|
72
72
|
' ' + chalk.gray('-y, --yes') + ' Skip confirmation prompt',
|
|
73
73
|
' ' + chalk.gray('-d, --defaults') + ' Use default configuration',
|
|
74
|
+
' ' + chalk.gray('--remote') + ' Force remote fetch from GitHub registry',
|
|
74
75
|
' ' + chalk.gray('-b, --branch') + ' <branch> GitHub branch to fetch from ' + branchDefault,
|
|
75
76
|
'',
|
|
76
77
|
' ' + chalk.cyan('add') + ' Add component(s) to your project',
|
|
77
78
|
' ' + chalk.gray('[components...]') + ' One or more component names',
|
|
78
|
-
' ' + chalk.gray('-y, --yes') + ' Skip
|
|
79
|
+
' ' + chalk.gray('-y, --yes') + ' Skip prompts and overwrite conflicts',
|
|
79
80
|
' ' + chalk.gray('-o, --overwrite') + ' Overwrite existing files',
|
|
80
81
|
' ' + chalk.gray('-a, --all') + ' Add all available components',
|
|
81
82
|
' ' + chalk.gray('-p, --path') + ' <path> Custom install path',
|
|
82
83
|
' ' + chalk.gray('--remote') + ' Force remote fetch from GitHub registry',
|
|
84
|
+
' ' + chalk.gray('--dry-run') + ' Show what would be installed without changes',
|
|
85
|
+
' ' + chalk.gray('-b, --branch') + ' <branch> GitHub branch to fetch from ' + branchDefault,
|
|
86
|
+
'',
|
|
87
|
+
' ' + chalk.cyan('diff') + ' Show differences between local and remote versions',
|
|
88
|
+
' ' + chalk.gray('[components...]') + ' Components to diff (all installed if omitted)',
|
|
89
|
+
' ' + chalk.gray('--remote') + ' Force remote fetch from GitHub registry',
|
|
83
90
|
' ' + chalk.gray('-b, --branch') + ' <branch> GitHub branch to fetch from ' + branchDefault,
|
|
84
91
|
'',
|
|
92
|
+
' ' + chalk.cyan('list') + ' List all components and their install status',
|
|
93
|
+
'',
|
|
85
94
|
' ' + chalk.cyan('help') + ' Show this reference',
|
|
86
95
|
'',
|
|
87
96
|
];
|