@ng-shangjc/cli 1.0.0-beta

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.
@@ -0,0 +1,332 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.installComponent = installComponent;
40
+ const fs = __importStar(require("fs-extra"));
41
+ const path = __importStar(require("path"));
42
+ const inquirer_1 = __importDefault(require("inquirer"));
43
+ const child_process_1 = require("child_process");
44
+ const AVAILABLE_COMPONENTS = [
45
+ 'button',
46
+ 'input',
47
+ 'card',
48
+ 'switch',
49
+ 'dialog',
50
+ 'tooltip',
51
+ 'select',
52
+ 'checkbox',
53
+ 'radio-group',
54
+ 'textarea',
55
+ 'badge',
56
+ 'alert'
57
+ ];
58
+ const COMPONENT_DEPENDENCIES = {
59
+ button: ['utils'],
60
+ input: ['utils'],
61
+ card: ['utils'],
62
+ switch: ['utils'],
63
+ dialog: ['utils'],
64
+ tooltip: ['utils'],
65
+ select: ['utils'],
66
+ checkbox: ['utils'],
67
+ 'radio-group': ['utils'],
68
+ textarea: ['utils'],
69
+ badge: ['utils'],
70
+ alert: ['utils']
71
+ };
72
+ const COMPONENT_FILES = {
73
+ button: [
74
+ 'button.component.ts'
75
+ ],
76
+ input: [
77
+ 'input.component.ts'
78
+ ],
79
+ card: [
80
+ 'card.component.ts'
81
+ ],
82
+ switch: [
83
+ 'switch.component.ts'
84
+ ],
85
+ dialog: [
86
+ 'dialog.component.ts',
87
+ 'dialog.service.ts'
88
+ ],
89
+ tooltip: [
90
+ 'tooltip.component.ts',
91
+ 'tooltip.directive.ts'
92
+ ],
93
+ select: [
94
+ 'select.component.ts'
95
+ ],
96
+ checkbox: [
97
+ 'checkbox.component.ts'
98
+ ],
99
+ 'radio-group': [
100
+ 'radio-group.component.ts'
101
+ ],
102
+ textarea: [
103
+ 'textarea.component.ts'
104
+ ],
105
+ badge: [
106
+ 'badge.component.ts'
107
+ ],
108
+ alert: [
109
+ 'alert.component.ts'
110
+ ]
111
+ };
112
+ async function installComponent(componentName, options) {
113
+ console.log(`🚀 Installing ${componentName} component...`);
114
+ // Validate component name
115
+ if (!AVAILABLE_COMPONENTS.includes(componentName)) {
116
+ console.error(`❌ Component "${componentName}" not found.`);
117
+ console.log(`Available components: ${AVAILABLE_COMPONENTS.join(', ')}`);
118
+ process.exit(1);
119
+ }
120
+ // Check if Angular project
121
+ if (!fs.existsSync('angular.json')) {
122
+ console.error('❌ This is not an Angular project. Please run this command in an Angular project root.');
123
+ process.exit(1);
124
+ }
125
+ // Check for shangjc.config.json
126
+ const configPath = 'shangjc.config.json';
127
+ if (!fs.existsSync(configPath)) {
128
+ console.log('⚠️ shangjc.config.json not found. Running init first...');
129
+ const { initProject } = await Promise.resolve().then(() => __importStar(require('./init')));
130
+ await initProject();
131
+ }
132
+ // Load configuration
133
+ const config = await fs.readJson(configPath);
134
+ const componentsPath = options.path || config.componentsPath;
135
+ // Check if component is already installed
136
+ if (config.installedComponents.includes(componentName)) {
137
+ console.log(`⚠️ ${componentName} is already installed.`);
138
+ const { reinstall } = await inquirer_1.default.prompt([
139
+ {
140
+ type: 'confirm',
141
+ name: 'reinstall',
142
+ message: 'Do you want to reinstall it?',
143
+ default: false
144
+ }
145
+ ]);
146
+ if (!reinstall) {
147
+ console.log('Installation cancelled.');
148
+ return;
149
+ }
150
+ }
151
+ // Show installation summary
152
+ const dependencies = COMPONENT_DEPENDENCIES[componentName] || [];
153
+ console.log(`\n📋 Installation Summary:`);
154
+ console.log(` Component: ${componentName}`);
155
+ console.log(` Path: ${componentsPath}/${componentName}`);
156
+ console.log(` Type: ${config.componentType}`);
157
+ if (dependencies.length > 0) {
158
+ console.log(` Dependencies: ${dependencies.join(', ')}`);
159
+ }
160
+ // Confirm installation
161
+ const { confirm } = await inquirer_1.default.prompt([
162
+ {
163
+ type: 'confirm',
164
+ name: 'confirm',
165
+ message: 'Proceed with installation?',
166
+ default: true
167
+ }
168
+ ]);
169
+ if (!confirm) {
170
+ console.log('Installation cancelled.');
171
+ return;
172
+ }
173
+ try {
174
+ // Install dependencies first
175
+ if (dependencies.includes('utils')) {
176
+ await installUtils();
177
+ }
178
+ // Install the component package itself
179
+ await installComponentPackage(componentName);
180
+ // Create destination directory
181
+ const destDir = path.join(process.cwd(), componentsPath, componentName);
182
+ await fs.ensureDir(destDir);
183
+ // Get source directory from installed npm package
184
+ const sourceDir = path.join(process.cwd(), 'node_modules', '@ng-shangjc', componentName, 'src', 'lib');
185
+ // Copy component files
186
+ const files = COMPONENT_FILES[componentName];
187
+ for (const file of files) {
188
+ const sourcePath = path.join(sourceDir, file);
189
+ const destPath = path.join(destDir, file);
190
+ if (await fs.pathExists(sourcePath)) {
191
+ await fs.copy(sourcePath, destPath);
192
+ console.log(`✅ Copied ${file}`);
193
+ }
194
+ else {
195
+ console.warn(`⚠️ Source file not found: ${sourcePath}`);
196
+ }
197
+ }
198
+ // Create index file
199
+ const indexContent = generateIndexFile(componentName, files, config.componentType);
200
+ await fs.writeFile(path.join(destDir, 'index.ts'), indexContent);
201
+ console.log(`✅ Created index.ts`);
202
+ // Copy README
203
+ const readmePath = path.join(process.cwd(), 'node_modules', '@ng-shangjc', componentName, 'README.md');
204
+ if (await fs.pathExists(readmePath)) {
205
+ await fs.copy(readmePath, path.join(destDir, 'README.md'));
206
+ console.log(`✅ Copied README.md`);
207
+ }
208
+ // Update configuration
209
+ if (!config.installedComponents.includes(componentName)) {
210
+ config.installedComponents.push(componentName);
211
+ await fs.writeJson(configPath, config, { spaces: 2 });
212
+ console.log(`✅ Updated shangjc.config.json`);
213
+ }
214
+ console.log(`🎉 Successfully installed ${componentName} component!`);
215
+ console.log(`\n📁 Files installed to: ${destDir}`);
216
+ console.log(`\n📖 Usage:`);
217
+ console.log(`import { ${getComponentClassName(componentName)} } from './${componentsPath}/${componentName}';`);
218
+ }
219
+ catch (error) {
220
+ console.error('❌ Installation failed:', error);
221
+ process.exit(1);
222
+ }
223
+ }
224
+ async function installUtils() {
225
+ console.log('📦 Installing utils dependency...');
226
+ try {
227
+ // Check if utils is already installed in node_modules
228
+ const utilsPath = path.join(process.cwd(), 'node_modules', '@ng-shangjc', 'utils');
229
+ if (!fs.existsSync(utilsPath)) {
230
+ console.log('Installing @ng-shangjc/utils...');
231
+ (0, child_process_1.execSync)('npm install --save-dev @ng-shangjc/utils', { stdio: 'inherit' });
232
+ }
233
+ else {
234
+ console.log('✅ @ng-shangjc/utils already installed');
235
+ }
236
+ }
237
+ catch (error) {
238
+ console.error('❌ Failed to install utils:', error);
239
+ throw error;
240
+ }
241
+ }
242
+ async function installComponentPackage(componentName) {
243
+ console.log(`📦 Installing ${componentName} package...`);
244
+ try {
245
+ // Check if component is already installed in node_modules
246
+ const componentPath = path.join(process.cwd(), 'node_modules', '@ng-shangjc', componentName);
247
+ if (!fs.existsSync(componentPath)) {
248
+ console.log(`Installing @ng-shangjc/${componentName}...`);
249
+ (0, child_process_1.execSync)(`npm install --save-dev @ng-shangjc/${componentName}`, { stdio: 'inherit' });
250
+ }
251
+ else {
252
+ console.log(`✅ @ng-shangjc/${componentName} already installed`);
253
+ }
254
+ }
255
+ catch (error) {
256
+ console.error(`❌ Failed to install ${componentName} package:`, error);
257
+ console.log(`🔄 Attempting to download files directly...`);
258
+ // Fallback: try to download files directly from npm registry
259
+ try {
260
+ await downloadComponentFiles(componentName);
261
+ console.log(`✅ Successfully downloaded ${componentName} files directly`);
262
+ }
263
+ catch (downloadError) {
264
+ console.error(`❌ Failed to download ${componentName} files:`, downloadError);
265
+ throw new Error(`Failed to install ${componentName}: Package installation and direct download both failed`);
266
+ }
267
+ }
268
+ }
269
+ async function downloadComponentFiles(componentName) {
270
+ const https = require('https');
271
+ const tar = require('tar');
272
+ return new Promise((resolve, reject) => {
273
+ const packageUrl = `https://registry.npmjs.org/@ng-shangjc/${componentName}/-/${componentName}-1.0.0.tgz`;
274
+ const tempDir = path.join(process.cwd(), '.ng-shangjc-temp');
275
+ // Ensure temp directory exists
276
+ fs.ensureDirSync(tempDir);
277
+ const file = fs.createWriteStream(path.join(tempDir, `${componentName}.tgz`));
278
+ https.get(packageUrl, (response) => {
279
+ if (response.statusCode !== 200) {
280
+ reject(new Error(`Failed to download package: ${response.statusCode}`));
281
+ return;
282
+ }
283
+ response.pipe(file);
284
+ file.on('finish', () => {
285
+ file.close();
286
+ // Extract the tarball
287
+ fs.createReadStream(path.join(tempDir, `${componentName}.tgz`))
288
+ .pipe(tar.extract({
289
+ cwd: tempDir,
290
+ strip: 1 // Remove the package folder
291
+ }))
292
+ .on('finish', () => {
293
+ // Copy the extracted files to node_modules structure
294
+ const sourceDir = path.join(tempDir, 'src', 'lib');
295
+ const targetDir = path.join(process.cwd(), 'node_modules', '@ng-shangjc', componentName, 'src', 'lib');
296
+ fs.ensureDirSync(path.dirname(targetDir));
297
+ if (fs.existsSync(sourceDir)) {
298
+ fs.copySync(sourceDir, targetDir);
299
+ }
300
+ // Copy README if exists
301
+ const readmeSource = path.join(tempDir, 'README.md');
302
+ const readmeTarget = path.join(process.cwd(), 'node_modules', '@ng-shangjc', componentName, 'README.md');
303
+ if (fs.existsSync(readmeSource)) {
304
+ fs.copySync(readmeSource, readmeTarget);
305
+ }
306
+ // Clean up temp files
307
+ fs.removeSync(tempDir);
308
+ resolve();
309
+ })
310
+ .on('error', reject);
311
+ });
312
+ }).on('error', reject);
313
+ });
314
+ }
315
+ function generateIndexFile(componentName, files, mode) {
316
+ const exports = files
317
+ .filter(file => file.endsWith('.ts'))
318
+ .map(file => {
319
+ const name = file.replace('.ts', '');
320
+ return `export * from './${name}';`;
321
+ })
322
+ .join('\n');
323
+ return `// Generated by ng-shangjc CLI
324
+ // Component: ${componentName}
325
+ // Mode: ${mode}
326
+
327
+ ${exports}
328
+ `;
329
+ }
330
+ function getComponentClassName(componentName) {
331
+ return componentName.charAt(0).toUpperCase() + componentName.slice(1) + 'Component';
332
+ }
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.showVariants = showVariants;
4
+ const variant_configs_1 = require("../utils/variant-configs");
5
+ async function showVariants(componentName) {
6
+ if (componentName) {
7
+ // Show variants for specific component
8
+ const config = (0, variant_configs_1.getComponentVariantConfig)(componentName);
9
+ if (!config) {
10
+ console.log(`❌ No variant configuration found for component "${componentName}"`);
11
+ console.log('\nAvailable components with variants:');
12
+ const allConfigs = (0, variant_configs_1.getAllVariantConfigs)();
13
+ allConfigs.forEach(config => {
14
+ console.log(` - ${config.component}`);
15
+ });
16
+ return;
17
+ }
18
+ console.log(`\n🎨 Variant configurations for ${config.component}:`);
19
+ console.log(` Default variant: ${config.defaultVariant}\n`);
20
+ config.variants.forEach(variant => {
21
+ console.log(` • ${variant.name}${variant.name === config.defaultVariant ? ' (default)' : ''}`);
22
+ if (variant.description) {
23
+ console.log(` ${variant.description}`);
24
+ }
25
+ console.log(` Classes: ${variant.classes}\n`);
26
+ });
27
+ }
28
+ else {
29
+ // Show all component variants
30
+ const allConfigs = (0, variant_configs_1.getAllVariantConfigs)();
31
+ if (allConfigs.length === 0) {
32
+ console.log('❌ No variant configurations found');
33
+ return;
34
+ }
35
+ console.log('\n🎨 All component variant configurations:\n');
36
+ allConfigs.forEach(config => {
37
+ console.log(`📦 ${config.component}:`);
38
+ console.log(` Variants: ${config.variants.map(v => v.name).join(', ')}`);
39
+ console.log(` Default: ${config.defaultVariant}\n`);
40
+ });
41
+ }
42
+ }
package/dist/index.js ADDED
@@ -0,0 +1,26 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ const commander_1 = require("commander");
5
+ const install_1 = require("./commands/install");
6
+ const init_1 = require("./commands/init");
7
+ const variants_1 = require("./commands/variants");
8
+ const program = new commander_1.Command();
9
+ program
10
+ .name('ng-shangjc')
11
+ .description('CLI for ng-shangjc UI component library')
12
+ .version('1.0.0');
13
+ program
14
+ .command('install <component>')
15
+ .description('Install a component into your project')
16
+ .option('-p, --path <path>', 'Override installation path from config')
17
+ .action(install_1.installComponent);
18
+ program
19
+ .command('init')
20
+ .description('Initialize shangjc in your project')
21
+ .action(init_1.initProject);
22
+ program
23
+ .command('variants [component]')
24
+ .description('Show variant configurations for components')
25
+ .action(variants_1.showVariants);
26
+ program.parse();
@@ -0,0 +1,122 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.COMPONENT_VARIANT_CONFIGS = void 0;
4
+ exports.getComponentVariantConfig = getComponentVariantConfig;
5
+ exports.getAllVariantConfigs = getAllVariantConfigs;
6
+ exports.COMPONENT_VARIANT_CONFIGS = {
7
+ alert: {
8
+ component: 'alert',
9
+ variants: [
10
+ {
11
+ name: 'default',
12
+ classes: 'bg-background text-foreground border-border',
13
+ description: 'Default alert style'
14
+ },
15
+ {
16
+ name: 'destructive',
17
+ classes: 'border-destructive/50 text-red-800 bg-red-50 dark:border-destructive dark:bg-red-950/30 dark:text-red-300 [&>svg]:text-red-600 dark:[&>svg]:text-red-300',
18
+ description: 'Red alert for errors'
19
+ },
20
+ {
21
+ name: 'warning',
22
+ classes: 'border-yellow-500/50 text-yellow-800 bg-yellow-50 dark:border-yellow-500 dark:text-yellow-300 dark:bg-yellow-950/30 [&>svg]:text-yellow-600 dark:[&>svg]:text-yellow-300',
23
+ description: 'Yellow alert for warnings'
24
+ },
25
+ {
26
+ name: 'success',
27
+ classes: 'border-green-500/50 text-green-800 bg-green-50 dark:border-green-500 dark:text-green-300 dark:bg-green-950/30 [&>svg]:text-green-600 dark:[&>svg]:text-green-300',
28
+ description: 'Green alert for success'
29
+ },
30
+ {
31
+ name: 'info',
32
+ classes: 'border-blue-500/50 text-blue-800 bg-blue-50 dark:border-blue-500 dark:text-blue-300 dark:bg-blue-950/30 [&>svg]:text-blue-600 dark:[&>svg]:text-blue-300',
33
+ description: 'Blue alert for information'
34
+ }
35
+ ],
36
+ defaultVariant: 'default'
37
+ },
38
+ button: {
39
+ component: 'button',
40
+ variants: [
41
+ {
42
+ name: 'default',
43
+ classes: 'bg-primary text-primary-foreground hover:bg-primary/90',
44
+ description: 'Primary button style'
45
+ },
46
+ {
47
+ name: 'destructive',
48
+ classes: 'bg-destructive text-destructive-foreground hover:bg-destructive/90',
49
+ description: 'Destructive button style'
50
+ },
51
+ {
52
+ name: 'outline',
53
+ classes: 'border border-input bg-background hover:bg-accent hover:text-accent-foreground',
54
+ description: 'Outline button style'
55
+ },
56
+ {
57
+ name: 'secondary',
58
+ classes: 'bg-secondary text-secondary-foreground hover:bg-secondary/80',
59
+ description: 'Secondary button style'
60
+ },
61
+ {
62
+ name: 'ghost',
63
+ classes: 'hover:bg-accent hover:text-accent-foreground',
64
+ description: 'Ghost button style'
65
+ },
66
+ {
67
+ name: 'link',
68
+ classes: 'text-primary underline-offset-4 hover:underline',
69
+ description: 'Link button style'
70
+ }
71
+ ],
72
+ defaultVariant: 'default'
73
+ },
74
+ input: {
75
+ component: 'input',
76
+ variants: [
77
+ {
78
+ name: 'default',
79
+ classes: 'flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50',
80
+ description: 'Default input style'
81
+ },
82
+ {
83
+ name: 'destructive',
84
+ classes: 'flex h-10 w-full rounded-md border border-destructive bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-destructive focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50',
85
+ description: 'Input with destructive border'
86
+ }
87
+ ],
88
+ defaultVariant: 'default'
89
+ },
90
+ badge: {
91
+ component: 'badge',
92
+ variants: [
93
+ {
94
+ name: 'default',
95
+ classes: 'border-transparent bg-primary text-primary-foreground hover:bg-primary/80',
96
+ description: 'Default badge style'
97
+ },
98
+ {
99
+ name: 'secondary',
100
+ classes: 'border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80',
101
+ description: 'Secondary badge style'
102
+ },
103
+ {
104
+ name: 'destructive',
105
+ classes: 'border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80',
106
+ description: 'Destructive badge style'
107
+ },
108
+ {
109
+ name: 'outline',
110
+ classes: 'text-foreground border',
111
+ description: 'Outline badge style'
112
+ }
113
+ ],
114
+ defaultVariant: 'default'
115
+ }
116
+ };
117
+ function getComponentVariantConfig(componentName) {
118
+ return exports.COMPONENT_VARIANT_CONFIGS[componentName] || null;
119
+ }
120
+ function getAllVariantConfigs() {
121
+ return Object.values(exports.COMPONENT_VARIANT_CONFIGS);
122
+ }
package/package.json ADDED
@@ -0,0 +1,23 @@
1
+ {
2
+ "name": "@ng-shangjc/cli",
3
+ "version": "1.0.0-beta",
4
+ "bin": {
5
+ "ng-shangjc": "./dist/index.js"
6
+ },
7
+ "scripts": {
8
+ "build": "tsc",
9
+ "dev": "tsc --watch"
10
+ },
11
+ "dependencies": {
12
+ "commander": "^11.0.0",
13
+ "fs-extra": "^11.0.0",
14
+ "inquirer": "^9.0.0",
15
+ "tar": "^6.0.0"
16
+ },
17
+ "devDependencies": {
18
+ "@types/fs-extra": "^11.0.0",
19
+ "@types/inquirer": "^9.0.0",
20
+ "@types/node": "^20.0.0",
21
+ "typescript": "~5.8.2"
22
+ }
23
+ }