@ng-shangjc/cli 1.0.0 → 1.0.2-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.
@@ -56,7 +56,7 @@ const AVAILABLE_COMPONENTS = [
56
56
  'alert'
57
57
  ];
58
58
  const COMPONENT_DEPENDENCIES = {
59
- button: ['utils'],
59
+ button: ['utils', 'class-variance-authority'],
60
60
  input: ['utils'],
61
61
  card: ['utils'],
62
62
  switch: ['utils'],
@@ -71,30 +71,24 @@ const COMPONENT_DEPENDENCIES = {
71
71
  };
72
72
  const COMPONENT_FILES = {
73
73
  button: [
74
- 'button.component.ts',
75
- 'button.metadata.ts'
74
+ 'button.component.ts'
76
75
  ],
77
76
  input: [
78
- 'input.component.ts',
79
- 'input.metadata.ts'
77
+ 'input.component.ts'
80
78
  ],
81
79
  card: [
82
- 'card.component.ts',
83
- 'card.metadata.ts'
80
+ 'card.component.ts'
84
81
  ],
85
82
  switch: [
86
- 'switch.component.ts',
87
- 'switch.metadata.ts'
83
+ 'switch.component.ts'
88
84
  ],
89
85
  dialog: [
90
86
  'dialog.component.ts',
91
- 'dialog.service.ts',
92
- 'dialog.metadata.ts'
87
+ 'dialog.service.ts'
93
88
  ],
94
89
  tooltip: [
95
90
  'tooltip.component.ts',
96
- 'tooltip.directive.ts',
97
- 'tooltip.metadata.ts'
91
+ 'tooltip.directive.ts'
98
92
  ],
99
93
  select: [
100
94
  'select.component.ts'
@@ -181,11 +175,18 @@ async function installComponent(componentName, options) {
181
175
  if (dependencies.includes('utils')) {
182
176
  await installUtils();
183
177
  }
178
+ // Install external dependencies (non-utils)
179
+ const externalDeps = dependencies.filter(dep => dep !== 'utils');
180
+ if (externalDeps.length > 0) {
181
+ await installExternalDependencies(externalDeps, componentName);
182
+ }
183
+ // Install the component package itself
184
+ await installComponentPackage(componentName);
184
185
  // Create destination directory
185
186
  const destDir = path.join(process.cwd(), componentsPath, componentName);
186
187
  await fs.ensureDir(destDir);
187
- // Get source directory
188
- const sourceDir = path.join(__dirname, '..', '..', '..', 'packages', componentName, 'src', 'lib');
188
+ // Get source directory from installed npm package
189
+ const sourceDir = path.join(process.cwd(), 'node_modules', '@ng-shangjc', componentName, 'src', 'lib');
189
190
  // Copy component files
190
191
  const files = COMPONENT_FILES[componentName];
191
192
  for (const file of files) {
@@ -203,22 +204,21 @@ async function installComponent(componentName, options) {
203
204
  const indexContent = generateIndexFile(componentName, files, config.componentType);
204
205
  await fs.writeFile(path.join(destDir, 'index.ts'), indexContent);
205
206
  console.log(`✅ Created index.ts`);
206
- // Copy README
207
- const readmePath = path.join(__dirname, '..', '..', '..', 'packages', componentName, 'README.md');
208
- if (await fs.pathExists(readmePath)) {
209
- await fs.copy(readmePath, path.join(destDir, 'README.md'));
210
- console.log(`✅ Copied README.md`);
211
- }
212
207
  // Update configuration
213
208
  if (!config.installedComponents.includes(componentName)) {
214
209
  config.installedComponents.push(componentName);
215
210
  await fs.writeJson(configPath, config, { spaces: 2 });
216
211
  console.log(`✅ Updated shangjc.config.json`);
217
212
  }
213
+ // Create/update barrel index.ts in the main ui/shangjc folder
214
+ await createOrUpdateBarrelIndex(config.componentsPath, config.installedComponents);
218
215
  console.log(`🎉 Successfully installed ${componentName} component!`);
219
216
  console.log(`\n📁 Files installed to: ${destDir}`);
220
217
  console.log(`\n📖 Usage:`);
218
+ console.log(`// Individual import:`);
221
219
  console.log(`import { ${getComponentClassName(componentName)} } from './${componentsPath}/${componentName}';`);
220
+ console.log(`// Or barrel import (if multiple components):`);
221
+ console.log(`import { ${getComponentClassName(componentName)} } from './${componentsPath}';`);
222
222
  }
223
223
  catch (error) {
224
224
  console.error('❌ Installation failed:', error);
@@ -232,7 +232,7 @@ async function installUtils() {
232
232
  const utilsPath = path.join(process.cwd(), 'node_modules', '@ng-shangjc', 'utils');
233
233
  if (!fs.existsSync(utilsPath)) {
234
234
  console.log('Installing @ng-shangjc/utils...');
235
- (0, child_process_1.execSync)('npm install @ng-shangjc/utils', { stdio: 'inherit' });
235
+ (0, child_process_1.execSync)('npm install --save-dev @ng-shangjc/utils', { stdio: 'inherit' });
236
236
  }
237
237
  else {
238
238
  console.log('✅ @ng-shangjc/utils already installed');
@@ -243,6 +243,115 @@ async function installUtils() {
243
243
  throw error;
244
244
  }
245
245
  }
246
+ async function installExternalDependencies(dependencies, componentName) {
247
+ // Read the component's package.json to get exact versions
248
+ const componentPackagePath = path.join(process.cwd(), 'node_modules', '@ng-shangjc', componentName, 'package.json');
249
+ let componentPackage;
250
+ try {
251
+ componentPackage = await fs.readJson(componentPackagePath);
252
+ }
253
+ catch (error) {
254
+ console.error(`❌ Failed to read component package.json:`, error);
255
+ throw error;
256
+ }
257
+ for (const dependency of dependencies) {
258
+ console.log(`📦 Installing ${dependency} dependency...`);
259
+ try {
260
+ // Get the exact version from component's peerDependencies or dependencies
261
+ const version = componentPackage.peerDependencies?.[dependency] || componentPackage.dependencies?.[dependency];
262
+ if (!version) {
263
+ console.warn(`⚠️ Could not find version for ${dependency} in component package.json, installing latest...`);
264
+ }
265
+ // Check if dependency is already installed in node_modules
266
+ const depPath = path.join(process.cwd(), 'node_modules', dependency);
267
+ if (!fs.existsSync(depPath)) {
268
+ const installSpec = version ? `${dependency}@${version}` : dependency;
269
+ console.log(`Installing ${installSpec}...`);
270
+ (0, child_process_1.execSync)(`npm install ${installSpec}`, { stdio: 'inherit' });
271
+ }
272
+ else {
273
+ console.log(`✅ ${dependency} already installed`);
274
+ }
275
+ }
276
+ catch (error) {
277
+ console.error(`❌ Failed to install ${dependency}:`, error);
278
+ throw error;
279
+ }
280
+ }
281
+ }
282
+ async function installComponentPackage(componentName) {
283
+ console.log(`📦 Installing ${componentName} package...`);
284
+ try {
285
+ // Check if component is already installed in node_modules
286
+ const componentPath = path.join(process.cwd(), 'node_modules', '@ng-shangjc', componentName);
287
+ if (!fs.existsSync(componentPath)) {
288
+ console.log(`Installing @ng-shangjc/${componentName}...`);
289
+ (0, child_process_1.execSync)(`npm install --save-dev @ng-shangjc/${componentName}`, { stdio: 'inherit' });
290
+ }
291
+ else {
292
+ console.log(`✅ @ng-shangjc/${componentName} already installed`);
293
+ }
294
+ }
295
+ catch (error) {
296
+ console.error(`❌ Failed to install ${componentName} package:`, error);
297
+ console.log(`🔄 Attempting to download files directly...`);
298
+ // Fallback: try to download files directly from npm registry
299
+ try {
300
+ await downloadComponentFiles(componentName);
301
+ console.log(`✅ Successfully downloaded ${componentName} files directly`);
302
+ }
303
+ catch (downloadError) {
304
+ console.error(`❌ Failed to download ${componentName} files:`, downloadError);
305
+ throw new Error(`Failed to install ${componentName}: Package installation and direct download both failed`);
306
+ }
307
+ }
308
+ }
309
+ async function downloadComponentFiles(componentName) {
310
+ const https = require('https');
311
+ const tar = require('tar');
312
+ return new Promise((resolve, reject) => {
313
+ const packageUrl = `https://registry.npmjs.org/@ng-shangjc/${componentName}/-/${componentName}-1.0.0.tgz`;
314
+ const tempDir = path.join(process.cwd(), '.ng-shangjc-temp');
315
+ // Ensure temp directory exists
316
+ fs.ensureDirSync(tempDir);
317
+ const file = fs.createWriteStream(path.join(tempDir, `${componentName}.tgz`));
318
+ https.get(packageUrl, (response) => {
319
+ if (response.statusCode !== 200) {
320
+ reject(new Error(`Failed to download package: ${response.statusCode}`));
321
+ return;
322
+ }
323
+ response.pipe(file);
324
+ file.on('finish', () => {
325
+ file.close();
326
+ // Extract the tarball
327
+ fs.createReadStream(path.join(tempDir, `${componentName}.tgz`))
328
+ .pipe(tar.extract({
329
+ cwd: tempDir,
330
+ strip: 1 // Remove the package folder
331
+ }))
332
+ .on('finish', () => {
333
+ // Copy the extracted files to node_modules structure
334
+ const sourceDir = path.join(tempDir, 'src', 'lib');
335
+ const targetDir = path.join(process.cwd(), 'node_modules', '@ng-shangjc', componentName, 'src', 'lib');
336
+ fs.ensureDirSync(path.dirname(targetDir));
337
+ if (fs.existsSync(sourceDir)) {
338
+ fs.copySync(sourceDir, targetDir);
339
+ }
340
+ // Copy package.json to node_modules structure
341
+ const packageSource = path.join(tempDir, 'package.json');
342
+ const packageTarget = path.join(process.cwd(), 'node_modules', '@ng-shangjc', componentName, 'package.json');
343
+ if (fs.existsSync(packageSource)) {
344
+ fs.copySync(packageSource, packageTarget);
345
+ }
346
+ // Clean up temp files
347
+ fs.removeSync(tempDir);
348
+ resolve();
349
+ })
350
+ .on('error', reject);
351
+ });
352
+ }).on('error', reject);
353
+ });
354
+ }
246
355
  function generateIndexFile(componentName, files, mode) {
247
356
  const exports = files
248
357
  .filter(file => file.endsWith('.ts'))
@@ -261,3 +370,24 @@ ${exports}
261
370
  function getComponentClassName(componentName) {
262
371
  return componentName.charAt(0).toUpperCase() + componentName.slice(1) + 'Component';
263
372
  }
373
+ async function createOrUpdateBarrelIndex(componentsPath, installedComponents) {
374
+ const barrelDir = path.join(process.cwd(), componentsPath);
375
+ const barrelPath = path.join(barrelDir, 'index.ts');
376
+ // Ensure the directory exists
377
+ await fs.ensureDir(barrelDir);
378
+ // Generate barrel content
379
+ const exports = installedComponents
380
+ .sort() // Sort for consistent ordering
381
+ .map(component => {
382
+ const className = getComponentClassName(component);
383
+ return `export { ${className} } from './${component}';`;
384
+ })
385
+ .join('\n');
386
+ const barrelContent = `// Generated by ng-shangjc CLI
387
+ // Barrel exports for all installed components
388
+
389
+ ${exports}
390
+ `;
391
+ await fs.writeFile(barrelPath, barrelContent);
392
+ console.log(`✅ Updated barrel index.ts at ${componentsPath}`);
393
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ng-shangjc/cli",
3
- "version": "1.0.0",
3
+ "version": "1.0.2-beta",
4
4
  "bin": {
5
5
  "ng-shangjc": "./dist/index.js"
6
6
  },
@@ -11,7 +11,8 @@
11
11
  "dependencies": {
12
12
  "commander": "^11.0.0",
13
13
  "fs-extra": "^11.0.0",
14
- "inquirer": "^9.0.0"
14
+ "inquirer": "^9.0.0",
15
+ "tar": "^6.0.0"
15
16
  },
16
17
  "devDependencies": {
17
18
  "@types/fs-extra": "^11.0.0",
@@ -33,7 +33,7 @@ const AVAILABLE_COMPONENTS = [
33
33
  ];
34
34
 
35
35
  const COMPONENT_DEPENDENCIES = {
36
- button: ['utils'],
36
+ button: ['utils', 'class-variance-authority'],
37
37
  input: ['utils'],
38
38
  card: ['utils'],
39
39
  switch: ['utils'],
@@ -49,30 +49,24 @@ const COMPONENT_DEPENDENCIES = {
49
49
 
50
50
  const COMPONENT_FILES = {
51
51
  button: [
52
- 'button.component.ts',
53
- 'button.metadata.ts'
52
+ 'button.component.ts'
54
53
  ],
55
54
  input: [
56
- 'input.component.ts',
57
- 'input.metadata.ts'
55
+ 'input.component.ts'
58
56
  ],
59
57
  card: [
60
- 'card.component.ts',
61
- 'card.metadata.ts'
58
+ 'card.component.ts'
62
59
  ],
63
60
  switch: [
64
- 'switch.component.ts',
65
- 'switch.metadata.ts'
61
+ 'switch.component.ts'
66
62
  ],
67
63
  dialog: [
68
64
  'dialog.component.ts',
69
- 'dialog.service.ts',
70
- 'dialog.metadata.ts'
65
+ 'dialog.service.ts'
71
66
  ],
72
67
  tooltip: [
73
68
  'tooltip.component.ts',
74
- 'tooltip.directive.ts',
75
- 'tooltip.metadata.ts'
69
+ 'tooltip.directive.ts'
76
70
  ],
77
71
  select: [
78
72
  'select.component.ts'
@@ -174,12 +168,21 @@ export async function installComponent(
174
168
  await installUtils();
175
169
  }
176
170
 
171
+ // Install external dependencies (non-utils)
172
+ const externalDeps = dependencies.filter(dep => dep !== 'utils');
173
+ if (externalDeps.length > 0) {
174
+ await installExternalDependencies(externalDeps, componentName);
175
+ }
176
+
177
+ // Install the component package itself
178
+ await installComponentPackage(componentName);
179
+
177
180
  // Create destination directory
178
181
  const destDir = path.join(process.cwd(), componentsPath, componentName);
179
182
  await fs.ensureDir(destDir);
180
183
 
181
- // Get source directory
182
- const sourceDir = path.join(__dirname, '..', '..', '..', 'packages', componentName, 'src', 'lib');
184
+ // Get source directory from installed npm package
185
+ const sourceDir = path.join(process.cwd(), 'node_modules', '@ng-shangjc', componentName, 'src', 'lib');
183
186
 
184
187
  // Copy component files
185
188
  const files = COMPONENT_FILES[componentName as keyof typeof COMPONENT_FILES];
@@ -201,13 +204,6 @@ export async function installComponent(
201
204
  await fs.writeFile(path.join(destDir, 'index.ts'), indexContent);
202
205
  console.log(`✅ Created index.ts`);
203
206
 
204
- // Copy README
205
- const readmePath = path.join(__dirname, '..', '..', '..', 'packages', componentName, 'README.md');
206
- if (await fs.pathExists(readmePath)) {
207
- await fs.copy(readmePath, path.join(destDir, 'README.md'));
208
- console.log(`✅ Copied README.md`);
209
- }
210
-
211
207
  // Update configuration
212
208
  if (!config.installedComponents.includes(componentName)) {
213
209
  config.installedComponents.push(componentName);
@@ -215,10 +211,16 @@ export async function installComponent(
215
211
  console.log(`✅ Updated shangjc.config.json`);
216
212
  }
217
213
 
214
+ // Create/update barrel index.ts in the main ui/shangjc folder
215
+ await createOrUpdateBarrelIndex(config.componentsPath, config.installedComponents);
216
+
218
217
  console.log(`🎉 Successfully installed ${componentName} component!`);
219
218
  console.log(`\n📁 Files installed to: ${destDir}`);
220
219
  console.log(`\n📖 Usage:`);
220
+ console.log(`// Individual import:`);
221
221
  console.log(`import { ${getComponentClassName(componentName)} } from './${componentsPath}/${componentName}';`);
222
+ console.log(`// Or barrel import (if multiple components):`);
223
+ console.log(`import { ${getComponentClassName(componentName)} } from './${componentsPath}';`);
222
224
 
223
225
  } catch (error) {
224
226
  console.error('❌ Installation failed:', error);
@@ -235,7 +237,7 @@ async function installUtils() {
235
237
 
236
238
  if (!fs.existsSync(utilsPath)) {
237
239
  console.log('Installing @ng-shangjc/utils...');
238
- execSync('npm install @ng-shangjc/utils', { stdio: 'inherit' });
240
+ execSync('npm install --save-dev @ng-shangjc/utils', { stdio: 'inherit' });
239
241
  } else {
240
242
  console.log('✅ @ng-shangjc/utils already installed');
241
243
  }
@@ -245,6 +247,133 @@ async function installUtils() {
245
247
  }
246
248
  }
247
249
 
250
+ async function installExternalDependencies(dependencies: string[], componentName: string) {
251
+ // Read the component's package.json to get exact versions
252
+ const componentPackagePath = path.join(process.cwd(), 'node_modules', '@ng-shangjc', componentName, 'package.json');
253
+ let componentPackage: any;
254
+
255
+ try {
256
+ componentPackage = await fs.readJson(componentPackagePath);
257
+ } catch (error) {
258
+ console.error(`❌ Failed to read component package.json:`, error);
259
+ throw error;
260
+ }
261
+
262
+ for (const dependency of dependencies) {
263
+ console.log(`📦 Installing ${dependency} dependency...`);
264
+
265
+ try {
266
+ // Get the exact version from component's peerDependencies or dependencies
267
+ const version = componentPackage.peerDependencies?.[dependency] || componentPackage.dependencies?.[dependency];
268
+ if (!version) {
269
+ console.warn(`⚠️ Could not find version for ${dependency} in component package.json, installing latest...`);
270
+ }
271
+
272
+ // Check if dependency is already installed in node_modules
273
+ const depPath = path.join(process.cwd(), 'node_modules', dependency);
274
+
275
+ if (!fs.existsSync(depPath)) {
276
+ const installSpec = version ? `${dependency}@${version}` : dependency;
277
+ console.log(`Installing ${installSpec}...`);
278
+ execSync(`npm install ${installSpec}`, { stdio: 'inherit' });
279
+ } else {
280
+ console.log(`✅ ${dependency} already installed`);
281
+ }
282
+ } catch (error) {
283
+ console.error(`❌ Failed to install ${dependency}:`, error);
284
+ throw error;
285
+ }
286
+ }
287
+ }
288
+
289
+ async function installComponentPackage(componentName: string) {
290
+ console.log(`📦 Installing ${componentName} package...`);
291
+
292
+ try {
293
+ // Check if component is already installed in node_modules
294
+ const componentPath = path.join(process.cwd(), 'node_modules', '@ng-shangjc', componentName);
295
+
296
+ if (!fs.existsSync(componentPath)) {
297
+ console.log(`Installing @ng-shangjc/${componentName}...`);
298
+ execSync(`npm install --save-dev @ng-shangjc/${componentName}`, { stdio: 'inherit' });
299
+ } else {
300
+ console.log(`✅ @ng-shangjc/${componentName} already installed`);
301
+ }
302
+ } catch (error) {
303
+ console.error(`❌ Failed to install ${componentName} package:`, error);
304
+ console.log(`🔄 Attempting to download files directly...`);
305
+
306
+ // Fallback: try to download files directly from npm registry
307
+ try {
308
+ await downloadComponentFiles(componentName);
309
+ console.log(`✅ Successfully downloaded ${componentName} files directly`);
310
+ } catch (downloadError) {
311
+ console.error(`❌ Failed to download ${componentName} files:`, downloadError);
312
+ throw new Error(`Failed to install ${componentName}: Package installation and direct download both failed`);
313
+ }
314
+ }
315
+ }
316
+
317
+ async function downloadComponentFiles(componentName: string) {
318
+ const https = require('https');
319
+ const tar = require('tar');
320
+
321
+ return new Promise<void>((resolve, reject) => {
322
+ const packageUrl = `https://registry.npmjs.org/@ng-shangjc/${componentName}/-/${componentName}-1.0.0.tgz`;
323
+ const tempDir = path.join(process.cwd(), '.ng-shangjc-temp');
324
+
325
+ // Ensure temp directory exists
326
+ fs.ensureDirSync(tempDir);
327
+
328
+ const file = fs.createWriteStream(path.join(tempDir, `${componentName}.tgz`));
329
+
330
+ https.get(packageUrl, (response: any) => {
331
+ if (response.statusCode !== 200) {
332
+ reject(new Error(`Failed to download package: ${response.statusCode}`));
333
+ return;
334
+ }
335
+
336
+ response.pipe(file);
337
+
338
+ file.on('finish', () => {
339
+ file.close();
340
+
341
+ // Extract the tarball
342
+ fs.createReadStream(path.join(tempDir, `${componentName}.tgz`))
343
+ .pipe(tar.extract({
344
+ cwd: tempDir,
345
+ strip: 1 // Remove the package folder
346
+ }))
347
+ .on('finish', () => {
348
+ // Copy the extracted files to node_modules structure
349
+ const sourceDir = path.join(tempDir, 'src', 'lib');
350
+ const targetDir = path.join(process.cwd(), 'node_modules', '@ng-shangjc', componentName, 'src', 'lib');
351
+
352
+ fs.ensureDirSync(path.dirname(targetDir));
353
+
354
+ if (fs.existsSync(sourceDir)) {
355
+ fs.copySync(sourceDir, targetDir);
356
+ }
357
+
358
+ // Copy package.json to node_modules structure
359
+ const packageSource = path.join(tempDir, 'package.json');
360
+ const packageTarget = path.join(process.cwd(), 'node_modules', '@ng-shangjc', componentName, 'package.json');
361
+
362
+ if (fs.existsSync(packageSource)) {
363
+ fs.copySync(packageSource, packageTarget);
364
+ }
365
+
366
+ // Clean up temp files
367
+ fs.removeSync(tempDir);
368
+
369
+ resolve();
370
+ })
371
+ .on('error', reject);
372
+ });
373
+ }).on('error', reject);
374
+ });
375
+ }
376
+
248
377
  function generateIndexFile(componentName: string, files: string[], mode: string): string {
249
378
  const exports = files
250
379
  .filter(file => file.endsWith('.ts'))
@@ -264,4 +393,30 @@ ${exports}
264
393
 
265
394
  function getComponentClassName(componentName: string): string {
266
395
  return componentName.charAt(0).toUpperCase() + componentName.slice(1) + 'Component';
396
+ }
397
+
398
+ async function createOrUpdateBarrelIndex(componentsPath: string, installedComponents: string[]) {
399
+ const barrelDir = path.join(process.cwd(), componentsPath);
400
+ const barrelPath = path.join(barrelDir, 'index.ts');
401
+
402
+ // Ensure the directory exists
403
+ await fs.ensureDir(barrelDir);
404
+
405
+ // Generate barrel content
406
+ const exports = installedComponents
407
+ .sort() // Sort for consistent ordering
408
+ .map(component => {
409
+ const className = getComponentClassName(component);
410
+ return `export { ${className} } from './${component}';`;
411
+ })
412
+ .join('\n');
413
+
414
+ const barrelContent = `// Generated by ng-shangjc CLI
415
+ // Barrel exports for all installed components
416
+
417
+ ${exports}
418
+ `;
419
+
420
+ await fs.writeFile(barrelPath, barrelContent);
421
+ console.log(`✅ Updated barrel index.ts at ${componentsPath}`);
267
422
  }