grg-kit-cli 0.6.2 → 0.6.4
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/README.md +35 -18
- package/bin/grg.js +2 -5
- package/commands/add.js +147 -36
- package/config/.catalog-cache.json +1 -0
- package/config/catalog-fetcher.js +2 -1
- package/package.json +3 -3
- package/scripts/generate-resources.js +25 -1
package/README.md
CHANGED
|
@@ -21,9 +21,15 @@ grg init
|
|
|
21
21
|
# Or with a specific theme
|
|
22
22
|
grg init --theme claude
|
|
23
23
|
|
|
24
|
-
# Add blocks
|
|
25
|
-
grg add block
|
|
26
|
-
grg add block
|
|
24
|
+
# Add blocks (all files)
|
|
25
|
+
grg add block auth
|
|
26
|
+
grg add block shell
|
|
27
|
+
|
|
28
|
+
# Add specific files from a block
|
|
29
|
+
grg add block auth login
|
|
30
|
+
grg add block shell sidebar
|
|
31
|
+
|
|
32
|
+
# Add all blocks
|
|
27
33
|
grg add block --all
|
|
28
34
|
|
|
29
35
|
# List available resources
|
|
@@ -73,24 +79,32 @@ Examples:
|
|
|
73
79
|
|
|
74
80
|
### `grg add block`
|
|
75
81
|
|
|
76
|
-
Add blocks to your project.
|
|
82
|
+
Add blocks or specific block files to your project.
|
|
77
83
|
|
|
78
84
|
```bash
|
|
79
|
-
grg add block [
|
|
85
|
+
grg add block <blockName> [fileIds...]
|
|
80
86
|
|
|
81
87
|
Options:
|
|
82
|
-
--all
|
|
83
|
-
--
|
|
84
|
-
--shell Add app shell block (sidebar, header, content area)
|
|
85
|
-
--settings Add settings block (settings page with sidebar navigation)
|
|
86
|
-
-o, --output <path> Custom output directory
|
|
88
|
+
--all Add all blocks
|
|
89
|
+
-o, --output <path> Custom output directory
|
|
87
90
|
|
|
88
91
|
Examples:
|
|
89
|
-
grg add block
|
|
90
|
-
grg add block
|
|
91
|
-
grg add block
|
|
92
|
+
grg add block auth # All auth files
|
|
93
|
+
grg add block auth login # Only login
|
|
94
|
+
grg add block auth login register # Login and register
|
|
95
|
+
grg add block shell sidebar # Only sidebar shell
|
|
96
|
+
grg add block shell topnav topnav-footer # Topnav variants
|
|
97
|
+
grg add block --all # All blocks
|
|
92
98
|
```
|
|
93
99
|
|
|
100
|
+
**Available blocks and files:**
|
|
101
|
+
|
|
102
|
+
| Block | Files |
|
|
103
|
+
|-------|-------|
|
|
104
|
+
| `auth` | `login`, `register`, `forgot-password` |
|
|
105
|
+
| `shell` | `sidebar`, `sidebar-footer`, `topnav`, `topnav-footer`, `collapsible`, `collapsible-footer` |
|
|
106
|
+
| `settings` | `profile`, `security`, `notification`, `danger-zone` |
|
|
107
|
+
|
|
94
108
|
### `grg list [category]`
|
|
95
109
|
|
|
96
110
|
List available blocks and themes.
|
|
@@ -181,11 +195,14 @@ cd my-app
|
|
|
181
195
|
grg init # Default theme
|
|
182
196
|
grg init --theme claude # Custom theme
|
|
183
197
|
|
|
184
|
-
# Add blocks
|
|
185
|
-
grg add block
|
|
186
|
-
grg add block
|
|
187
|
-
grg add block
|
|
188
|
-
|
|
198
|
+
# Add blocks (all files)
|
|
199
|
+
grg add block auth # All auth files
|
|
200
|
+
grg add block shell # All shell layouts
|
|
201
|
+
grg add block settings # All settings pages
|
|
202
|
+
|
|
203
|
+
# Add specific files
|
|
204
|
+
grg add block auth login # Just login
|
|
205
|
+
grg add block shell sidebar # Just sidebar shell
|
|
189
206
|
grg add block --all # All blocks
|
|
190
207
|
|
|
191
208
|
# List resources
|
package/bin/grg.js
CHANGED
|
@@ -24,12 +24,9 @@ program
|
|
|
24
24
|
const addCommand = program.command('add').description('Add resources to your project');
|
|
25
25
|
|
|
26
26
|
addCommand
|
|
27
|
-
.command('block')
|
|
28
|
-
.description('Add blocks to your project')
|
|
27
|
+
.command('block [blockName] [fileIds...]')
|
|
28
|
+
.description('Add blocks to your project (e.g., grg add block auth login)')
|
|
29
29
|
.option('--all', 'Add all blocks')
|
|
30
|
-
.option('--auth', 'Add authentication block (login, signup, forgot password)')
|
|
31
|
-
.option('--shell', 'Add app shell block (sidebar, header, content area)')
|
|
32
|
-
.option('--settings', 'Add settings block (settings page with sidebar navigation)')
|
|
33
30
|
.option('-o, --output <path>', 'Custom output directory')
|
|
34
31
|
.action(add);
|
|
35
32
|
|
package/commands/add.js
CHANGED
|
@@ -1,59 +1,81 @@
|
|
|
1
1
|
const degit = require('degit');
|
|
2
2
|
const chalk = require('chalk');
|
|
3
3
|
const ora = require('ora');
|
|
4
|
+
const fs = require('fs').promises;
|
|
5
|
+
const path = require('path');
|
|
6
|
+
const https = require('https');
|
|
4
7
|
const { fetchCatalog, REPO } = require('../config/catalog-fetcher');
|
|
5
8
|
|
|
6
9
|
/**
|
|
7
|
-
* Add command - downloads blocks
|
|
8
|
-
* Format: grg add block [
|
|
10
|
+
* Add command - downloads blocks or specific block files
|
|
11
|
+
* Format: grg add block <blockName> [fileIds...]
|
|
9
12
|
* Examples:
|
|
10
|
-
* grg add block
|
|
11
|
-
* grg add block
|
|
12
|
-
* grg add block
|
|
13
|
+
* grg add block auth # All auth files
|
|
14
|
+
* grg add block auth login register # Only login and register
|
|
15
|
+
* grg add block shell sidebar # Only sidebar shell
|
|
16
|
+
* grg add block --all # All blocks with all files
|
|
13
17
|
*/
|
|
14
|
-
async function add(options) {
|
|
18
|
+
async function add(blockName, fileIds, options) {
|
|
15
19
|
// Fetch catalog dynamically (with caching)
|
|
16
20
|
const spinner = ora('Fetching catalog...').start();
|
|
17
21
|
const RESOURCES = await fetchCatalog({ silent: true });
|
|
18
22
|
spinner.stop();
|
|
19
23
|
|
|
20
|
-
//
|
|
21
|
-
const blocksToAdd = [];
|
|
22
|
-
|
|
24
|
+
// Handle --all flag (download everything)
|
|
23
25
|
if (options.all) {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
if (block) blocksToAdd.push(block);
|
|
29
|
-
}
|
|
30
|
-
if (options.shell) {
|
|
31
|
-
const block = RESOURCES.blocks.find(b => b.name === 'shell');
|
|
32
|
-
if (block) blocksToAdd.push(block);
|
|
33
|
-
}
|
|
34
|
-
if (options.settings) {
|
|
35
|
-
const block = RESOURCES.blocks.find(b => b.name === 'settings');
|
|
36
|
-
if (block) blocksToAdd.push(block);
|
|
26
|
+
console.log(chalk.bold.cyan(`\n📦 Adding all blocks\n`));
|
|
27
|
+
|
|
28
|
+
for (const block of RESOURCES.blocks) {
|
|
29
|
+
await downloadBlock(block, null, options.output);
|
|
37
30
|
}
|
|
31
|
+
|
|
32
|
+
console.log(chalk.bold.green('✨ Done!'));
|
|
33
|
+
return;
|
|
38
34
|
}
|
|
39
35
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
console.log(chalk.cyan(' grg add block --auth'), chalk.gray(' Add authentication block'));
|
|
44
|
-
console.log(chalk.cyan(' grg add block --shell'), chalk.gray(' Add app shell block'));
|
|
45
|
-
console.log(chalk.cyan(' grg add block --settings'), chalk.gray(' Add settings block'));
|
|
46
|
-
console.log(chalk.gray('\nRun'), chalk.cyan('grg list blocks'), chalk.gray('for more details'));
|
|
36
|
+
// Validate block name
|
|
37
|
+
if (!blockName) {
|
|
38
|
+
showUsage(RESOURCES);
|
|
47
39
|
process.exit(1);
|
|
48
40
|
}
|
|
49
41
|
|
|
50
|
-
|
|
42
|
+
const block = RESOURCES.blocks.find(b => b.name === blockName);
|
|
43
|
+
if (!block) {
|
|
44
|
+
console.error(chalk.red(`\nError: Block "${blockName}" not found`));
|
|
45
|
+
console.log(chalk.yellow('\nAvailable blocks:'));
|
|
46
|
+
RESOURCES.blocks.forEach(b => {
|
|
47
|
+
console.log(chalk.cyan(` ${b.name}`), chalk.gray(`- ${b.description}`));
|
|
48
|
+
});
|
|
49
|
+
process.exit(1);
|
|
50
|
+
}
|
|
51
51
|
|
|
52
|
-
|
|
52
|
+
// Validate file IDs if provided
|
|
53
|
+
if (fileIds && fileIds.length > 0) {
|
|
54
|
+
const invalidFiles = fileIds.filter(id => !block.files?.find(f => f.id === id));
|
|
55
|
+
if (invalidFiles.length > 0) {
|
|
56
|
+
console.error(chalk.red(`\nError: Invalid file(s) for ${blockName}: ${invalidFiles.join(', ')}`));
|
|
57
|
+
console.log(chalk.yellow('\nAvailable files:'));
|
|
58
|
+
block.files?.forEach(f => {
|
|
59
|
+
console.log(chalk.cyan(` ${f.id}`), chalk.gray(`- ${f.title}`));
|
|
60
|
+
});
|
|
61
|
+
process.exit(1);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
await downloadBlock(block, fileIds, options.output);
|
|
66
|
+
console.log(chalk.bold.green('✨ Done!'));
|
|
67
|
+
}
|
|
53
68
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
69
|
+
/**
|
|
70
|
+
* Download a block (all files or specific files)
|
|
71
|
+
*/
|
|
72
|
+
async function downloadBlock(block, fileIds, customOutput) {
|
|
73
|
+
const downloadSpinner = ora();
|
|
74
|
+
|
|
75
|
+
// If no specific files requested, or block has no files array, download entire block
|
|
76
|
+
if (!fileIds || fileIds.length === 0 || !block.files || block.files.length === 0) {
|
|
77
|
+
const outputPath = customOutput
|
|
78
|
+
? `${customOutput}/${block.name}`
|
|
57
79
|
: block.defaultOutput;
|
|
58
80
|
|
|
59
81
|
downloadSpinner.start(`Downloading ${block.title}...`);
|
|
@@ -70,7 +92,6 @@ async function add(options) {
|
|
|
70
92
|
downloadSpinner.succeed(chalk.green(`✓ ${block.title} added`));
|
|
71
93
|
console.log(chalk.gray(` Location: ${outputPath}`));
|
|
72
94
|
|
|
73
|
-
// Show dependencies if any
|
|
74
95
|
if (block.dependencies && block.dependencies.length > 0) {
|
|
75
96
|
console.log(chalk.gray(` Dependencies: ${block.dependencies.join(', ')}`));
|
|
76
97
|
}
|
|
@@ -80,9 +101,99 @@ async function add(options) {
|
|
|
80
101
|
downloadSpinner.fail(chalk.red(`Failed to download ${block.title}`));
|
|
81
102
|
console.error(chalk.red(error.message));
|
|
82
103
|
}
|
|
104
|
+
return;
|
|
83
105
|
}
|
|
84
106
|
|
|
85
|
-
|
|
107
|
+
// Download specific files
|
|
108
|
+
const filesToDownload = block.files.filter(f => fileIds.includes(f.id));
|
|
109
|
+
const outputDir = customOutput || block.defaultOutput;
|
|
110
|
+
|
|
111
|
+
console.log(chalk.bold.cyan(`\n📦 Adding ${filesToDownload.length} file(s) from ${block.title}\n`));
|
|
112
|
+
|
|
113
|
+
// Ensure output directory exists
|
|
114
|
+
await fs.mkdir(outputDir, { recursive: true });
|
|
115
|
+
|
|
116
|
+
for (const file of filesToDownload) {
|
|
117
|
+
downloadSpinner.start(`Downloading ${file.title}...`);
|
|
118
|
+
|
|
119
|
+
try {
|
|
120
|
+
const fileUrl = `https://raw.githubusercontent.com/${REPO}/main/${block.path}/${file.file}`;
|
|
121
|
+
const outputPath = path.join(outputDir, file.file);
|
|
122
|
+
|
|
123
|
+
await downloadFile(fileUrl, outputPath);
|
|
124
|
+
|
|
125
|
+
downloadSpinner.succeed(chalk.green(`✓ ${file.title} added`));
|
|
126
|
+
console.log(chalk.gray(` Location: ${outputPath}`));
|
|
127
|
+
|
|
128
|
+
} catch (error) {
|
|
129
|
+
downloadSpinner.fail(chalk.red(`Failed to download ${file.title}`));
|
|
130
|
+
console.error(chalk.red(error.message));
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
if (block.dependencies && block.dependencies.length > 0) {
|
|
135
|
+
console.log(chalk.gray(`\nDependencies: ${block.dependencies.join(', ')}`));
|
|
136
|
+
}
|
|
137
|
+
console.log();
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Download a single file from URL
|
|
142
|
+
*/
|
|
143
|
+
function downloadFile(url, outputPath) {
|
|
144
|
+
return new Promise((resolve, reject) => {
|
|
145
|
+
https.get(url, (res) => {
|
|
146
|
+
if (res.statusCode === 301 || res.statusCode === 302) {
|
|
147
|
+
// Follow redirect
|
|
148
|
+
https.get(res.headers.location, (res2) => {
|
|
149
|
+
handleResponse(res2, outputPath, resolve, reject);
|
|
150
|
+
}).on('error', reject);
|
|
151
|
+
} else {
|
|
152
|
+
handleResponse(res, outputPath, resolve, reject);
|
|
153
|
+
}
|
|
154
|
+
}).on('error', reject);
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
function handleResponse(res, outputPath, resolve, reject) {
|
|
159
|
+
if (res.statusCode !== 200) {
|
|
160
|
+
reject(new Error(`HTTP ${res.statusCode}`));
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
let data = '';
|
|
165
|
+
res.on('data', chunk => data += chunk);
|
|
166
|
+
res.on('end', async () => {
|
|
167
|
+
try {
|
|
168
|
+
await fs.writeFile(outputPath, data, 'utf-8');
|
|
169
|
+
resolve();
|
|
170
|
+
} catch (e) {
|
|
171
|
+
reject(e);
|
|
172
|
+
}
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Show usage help
|
|
178
|
+
*/
|
|
179
|
+
function showUsage(RESOURCES) {
|
|
180
|
+
console.log(chalk.yellow('\nUsage: grg add block <blockName> [fileIds...]\n'));
|
|
181
|
+
console.log(chalk.bold('Examples:'));
|
|
182
|
+
console.log(chalk.cyan(' grg add block auth'), chalk.gray(' # All auth files'));
|
|
183
|
+
console.log(chalk.cyan(' grg add block auth login'), chalk.gray(' # Only login'));
|
|
184
|
+
console.log(chalk.cyan(' grg add block auth login register'), chalk.gray(' # Login and register'));
|
|
185
|
+
console.log(chalk.cyan(' grg add block shell sidebar'), chalk.gray(' # Only sidebar shell'));
|
|
186
|
+
console.log(chalk.cyan(' grg add block --all'), chalk.gray(' # All blocks'));
|
|
187
|
+
|
|
188
|
+
console.log(chalk.bold('\nAvailable blocks:'));
|
|
189
|
+
RESOURCES.blocks.forEach(b => {
|
|
190
|
+
console.log(chalk.cyan(` ${b.name}`), chalk.gray(`- ${b.description}`));
|
|
191
|
+
if (b.files && b.files.length > 0) {
|
|
192
|
+
console.log(chalk.gray(` Files: ${b.files.map(f => f.id).join(', ')}`));
|
|
193
|
+
}
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
console.log(chalk.gray('\nRun'), chalk.cyan('grg list blocks'), chalk.gray('for more details'));
|
|
86
197
|
}
|
|
87
198
|
|
|
88
199
|
module.exports = { add };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"timestamp":1765202627293,"data":{"themes":[{"name":"amber-minimal","title":"Amber Minimal","description":"Warm amber accents","file":"amber-minimal.css","tags":["minimal","warm","amber","orange"],"features":["dark-mode","tailwind-v4","spartan-ng","oklch"],"path":"templates/ui/themes/amber-minimal.css","defaultOutput":"src/themes/amber-minimal.css"},{"name":"claude","title":"Claude","description":"Claude-inspired warm tones","file":"claude.css","tags":["warm","orange","brown","claude"],"features":["dark-mode","tailwind-v4","spartan-ng","oklch"],"path":"templates/ui/themes/claude.css","defaultOutput":"src/themes/claude.css"},{"name":"clean-slate","title":"Clean Slate","description":"Minimal grayscale palette","file":"clean-slate.css","tags":["minimal","grayscale","neutral","clean"],"features":["dark-mode","tailwind-v4","spartan-ng","oklch"],"path":"templates/ui/themes/clean-slate.css","defaultOutput":"src/themes/clean-slate.css"},{"name":"grg-theme","title":"Grg Theme","description":"Default theme with purple/orange accents","file":"grg-theme.css","tags":["default","purple","orange","colorful"],"features":["dark-mode","tailwind-v4","spartan-ng","oklch"],"path":"templates/ui/themes/grg-theme.css","defaultOutput":"src/themes/grg-theme.css"},{"name":"mocks","title":"Mocks","description":"Theme for mockups and prototypes","file":"mocks.css","tags":["mockup","prototype","design"],"features":["dark-mode","tailwind-v4","spartan-ng","oklch"],"path":"templates/ui/themes/mocks.css","defaultOutput":"src/themes/mocks.css"},{"name":"modern-minimal","title":"Modern Minimal","description":"Contemporary minimal design","file":"modern-minimal.css","tags":["minimal","modern","contemporary","clean"],"features":["dark-mode","tailwind-v4","spartan-ng","oklch"],"path":"templates/ui/themes/modern-minimal.css","defaultOutput":"src/themes/modern-minimal.css"}],"components":[{"name":"file-upload","title":"File Upload","description":"Drag and drop file upload component","tags":["file","upload","form","drag-drop"],"dependencies":["@spartan-ng/helm/button"],"path":"templates/ui/components/file-upload","defaultOutput":"src/app/components/file-upload"},{"name":"stepper","title":"Stepper","description":"Multi-step form component with progress indicator","tags":["form","wizard","multi-step","progress"],"dependencies":["@spartan-ng/helm/button","@spartan-ng/helm/card"],"path":"templates/ui/components/stepper","defaultOutput":"src/app/components/stepper"}],"blocks":[{"name":"auth","title":"Auth","description":"Authentication pages (login, signup, forgot password)","tags":["auth","login","signup","authentication","form"],"dependencies":["@spartan-ng/helm/button","@spartan-ng/helm/card","@spartan-ng/helm/form-field"],"files":[{"id":"forgot-password","file":"forgot-password.component.ts","title":"Forgot Password","description":"Forgot Password"},{"id":"login","file":"login.component.ts","title":"Login","description":"Login"},{"id":"register","file":"register.component.ts","title":"Register","description":"Register"}],"path":"templates/ui/blocks/auth","defaultOutput":"src/app/blocks/auth"},{"name":"settings","title":"Settings","description":"Settings pages: profile, notifications, security, danger zone","tags":["settings","preferences","account","profile","security"],"dependencies":["@spartan-ng/helm/button","@spartan-ng/helm/card","@spartan-ng/helm/form-field","@spartan-ng/helm/switch"],"files":[{"id":"danger-zone","file":"danger-zone.component.ts","title":"Danger Zone","description":"Danger Zone"},{"id":"notification","file":"notification-settings.component.ts","title":"Notification Settings","description":"Notification Settings"},{"id":"profile","file":"profile-settings.component.ts","title":"Profile Settings","description":"Profile Settings"},{"id":"security","file":"security-settings.component.ts","title":"Security Settings","description":"Security Settings"}],"path":"templates/ui/blocks/settings","defaultOutput":"src/app/blocks/settings"},{"name":"shell","title":"Shell","description":"Application shell layouts: sidebar, topnav, collapsible - each with optional footer variant","tags":["shell","layout","sidebar","header","footer","navigation","topnav","collapsible"],"dependencies":["@spartan-ng/helm/button","@spartan-ng/helm/icon","@spartan-ng/helm/dropdown-menu"],"files":[{"id":"collapsible-footer","file":"collapsible-shell-footer.component.ts","title":"Collapsible Shell Footer","description":"Collapsible Shell Footer"},{"id":"collapsible","file":"collapsible-shell.component.ts","title":"Collapsible Shell","description":"Collapsible Shell"},{"id":"sidebar-footer","file":"sidebar-shell-footer.component.ts","title":"Sidebar Shell Footer","description":"Sidebar Shell Footer"},{"id":"sidebar","file":"sidebar-shell.component.ts","title":"Sidebar Shell","description":"Sidebar Shell"},{"id":"topnav-footer","file":"topnav-shell-footer.component.ts","title":"Topnav Shell Footer","description":"Topnav Shell Footer"},{"id":"topnav","file":"topnav-shell.component.ts","title":"Topnav Shell","description":"Topnav Shell"}],"path":"templates/ui/blocks/shell","defaultOutput":"src/app/blocks/shell"}]}}
|
|
@@ -124,7 +124,8 @@ async function fetchCatalog(options = {}) {
|
|
|
124
124
|
blocks: catalog.blocks.map(b => ({
|
|
125
125
|
...b,
|
|
126
126
|
path: `templates/ui/blocks/${b.name}`,
|
|
127
|
-
defaultOutput: `src/app/blocks/${b.name}
|
|
127
|
+
defaultOutput: `src/app/blocks/${b.name}`,
|
|
128
|
+
files: b.files || []
|
|
128
129
|
}))
|
|
129
130
|
};
|
|
130
131
|
|
package/package.json
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "grg-kit-cli",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.4",
|
|
4
4
|
"description": "CLI tool for pulling GRG Kit resources into your Angular project",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|
|
7
7
|
"grg": "./bin/grg.js"
|
|
8
8
|
},
|
|
9
9
|
"scripts": {
|
|
10
|
-
"
|
|
11
|
-
"prepublishOnly": "npm run
|
|
10
|
+
"catalog": "node scripts/generate-resources.js",
|
|
11
|
+
"prepublishOnly": "npm run catalog",
|
|
12
12
|
"test": "echo \"Error: no test specified\" && exit 1"
|
|
13
13
|
},
|
|
14
14
|
"keywords": [
|
|
@@ -298,9 +298,33 @@ module.exports = { RESOURCES, REPO };
|
|
|
298
298
|
|
|
299
299
|
const totalFiles = catalogBlocks.reduce((sum, b) => sum + (b.files?.length || 0), 0);
|
|
300
300
|
|
|
301
|
+
// Read CLI version from package.json
|
|
302
|
+
const cliPackage = JSON.parse(fs.readFileSync(path.join(__dirname, '../package.json'), 'utf-8'));
|
|
303
|
+
|
|
301
304
|
const catalog = {
|
|
302
|
-
|
|
305
|
+
_generated: 'AUTO-GENERATED FILE - DO NOT EDIT MANUALLY. Run: pnpm catalog',
|
|
306
|
+
version: '1.0.1',
|
|
303
307
|
lastUpdated: new Date().toISOString().split('T')[0],
|
|
308
|
+
cli: {
|
|
309
|
+
name: 'grg',
|
|
310
|
+
version: cliPackage.version,
|
|
311
|
+
commands: {
|
|
312
|
+
init: {
|
|
313
|
+
usage: 'grg init [--theme <name>]',
|
|
314
|
+
description: 'Initialize GRG Kit in current Angular project',
|
|
315
|
+
themeFlag: '--theme'
|
|
316
|
+
},
|
|
317
|
+
addBlock: {
|
|
318
|
+
usage: 'grg add block <blockName> [fileIds...]',
|
|
319
|
+
description: 'Add blocks to your project',
|
|
320
|
+
validBlocks: catalogBlocks.map(b => b.name)
|
|
321
|
+
},
|
|
322
|
+
list: {
|
|
323
|
+
usage: 'grg list [category]',
|
|
324
|
+
description: 'List available resources'
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
},
|
|
304
328
|
themes: catalogThemes,
|
|
305
329
|
components: catalogComponents,
|
|
306
330
|
blocks: catalogBlocks
|