package-installer-cli 1.3.0 → 1.3.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: de2baf8d0677e75c1471a523c2c8b581bde9c5187f0cecb4a5a4c79a6d03022a
4
- data.tar.gz: c3e5ee669f095c1537ba2bf505367da009999c907b6814fb907e5b569eebcc2a
3
+ metadata.gz: e6be7c9e887c130bca12178ca5b9c3814be6d872a43bd2f6889b0bc2b74611c3
4
+ data.tar.gz: 6c470b578f019a6753dd8a0a15050a2321f68d44ec18e4d911c9ec3648f177f1
5
5
  SHA512:
6
- metadata.gz: 3f593de7edcf4ec3b60397cf4de415d7e2703debb4a49c7f85d1911d2c2c64b9c644e637d259187dd965d43b23906985795cb5ed5fbc5eece7bf6af45b33c4fb
7
- data.tar.gz: c9f3538f2430caa503d7bbe21f52bd2592b689e80c1f08763b4afd2268a1cffd9ba4d1bd4dcf6a855aebacc0b2f59a1ca750ec296ad96aa57344b6cfdf40e043
6
+ metadata.gz: 3b56770128ea4abf8e2e67a5a9e45fcb460993e89477bf3c919c257436471be2a2df6dac5bc61cd89abfb77ca749af3cbe1adbd79d9d0a38d5cf0d17c11f004a
7
+ data.tar.gz: b05634c35e45ada304be549c392ea71dba86a44bafef8d1c6c5c3e3b71a4964138473f1a1517e3f9ec6c8f4cc45c19c5293422183462334d1c6971c62667c12a
data/dist/commands/add.js CHANGED
@@ -5,10 +5,11 @@ import boxen from 'boxen';
5
5
  import path from 'path';
6
6
  import fs from 'fs-extra';
7
7
  import { createStandardHelp } from '../utils/helpFormatter.js';
8
- import { addFeature, detectProjectStack, SUPPORTED_FEATURES } from '../utils/featureInstaller.js';
8
+ import { addFeature, detectProjectStack, SUPPORTED_FEATURES, ensureFeaturesLoaded } from '../utils/featureInstaller.js';
9
9
  import { historyManager } from '../utils/historyManager.js';
10
10
  import { cacheProjectData } from '../utils/cacheManager.js';
11
11
  import { getFeaturesJsonPath, getFeaturesPath } from '../utils/pathResolver.js';
12
+ import { displayCommandBanner } from '../utils/banner.js';
12
13
  /**
13
14
  * Helper function to capitalize strings
14
15
  */
@@ -18,7 +19,13 @@ function capitalize(str) {
18
19
  /**
19
20
  * Get features.json configuration with new jsonPath structure
20
21
  */
22
+ // Cache for features config to avoid repeated file reads
23
+ let featuresConfigCache = null;
21
24
  async function getFeaturesConfig() {
25
+ // Return cached config if available
26
+ if (featuresConfigCache) {
27
+ return featuresConfigCache;
28
+ }
22
29
  try {
23
30
  // Use the centralized path resolver
24
31
  const featuresPath = getFeaturesJsonPath();
@@ -42,12 +49,12 @@ async function getFeaturesConfig() {
42
49
  };
43
50
  }
44
51
  else {
45
- console.warn(chalk.yellow(`⚠️ Individual feature file not found: ${individualFeaturePath}`));
52
+ // Silently skip missing files to avoid console spam
46
53
  processedConfig[featureName] = featureConfig;
47
54
  }
48
55
  }
49
56
  catch (error) {
50
- console.warn(chalk.yellow(`⚠️ Could not load individual feature file for ${featureName}`));
57
+ // Silently handle errors to avoid console spam
51
58
  processedConfig[featureName] = featureConfig;
52
59
  }
53
60
  }
@@ -56,13 +63,16 @@ async function getFeaturesConfig() {
56
63
  processedConfig[featureName] = featureConfig;
57
64
  }
58
65
  }
59
- return { features: processedConfig };
66
+ // Cache the processed config
67
+ featuresConfigCache = { features: processedConfig };
68
+ return featuresConfigCache;
60
69
  }
61
- console.warn(chalk.yellow(`⚠️ features.json not found at: ${featuresPath}`));
62
- return { features: {} };
70
+ // Return empty config without warning to avoid console spam
71
+ featuresConfigCache = { features: {} };
72
+ return featuresConfigCache;
63
73
  }
64
74
  catch (error) {
65
- console.warn(chalk.yellow('⚠️ Error reading features.json, using fallback'));
75
+ // Return fallback config without warning
66
76
  return { features: {} };
67
77
  }
68
78
  }
@@ -88,6 +98,7 @@ async function getSubFeatures(category) {
88
98
  * List available features from features.json with descriptions
89
99
  */
90
100
  async function listAvailableFeatures() {
101
+ await ensureFeaturesLoaded();
91
102
  const featuresConfig = await getFeaturesConfig();
92
103
  if (!featuresConfig.features || Object.keys(featuresConfig.features).length === 0) {
93
104
  console.log(chalk.yellow('⚠️ No features found in configuration'));
@@ -269,6 +280,7 @@ function showEnhancedSetupInstructions(feature, provider) {
269
280
  * Show help for add command
270
281
  */
271
282
  export async function showAddHelp() {
283
+ await ensureFeaturesLoaded();
272
284
  const featuresConfig = await getFeaturesConfig();
273
285
  const availableFeatures = Object.keys(featuresConfig.features || {});
274
286
  const helpConfig = {
@@ -281,8 +293,7 @@ export async function showAddHelp() {
281
293
  ],
282
294
  options: [
283
295
  { flag: '-l, --list', description: 'List all available features' },
284
- { flag: '-v, --verbose', description: 'Show detailed output' },
285
- { flag: '-h, --help', description: 'Show this help message' }
296
+ { flag: '-v, --verbose', description: 'Show detailed output' }
286
297
  ],
287
298
  examples: [
288
299
  { command: 'add', description: 'Interactive feature selection' },
@@ -334,21 +345,19 @@ export async function showAddHelp() {
334
345
  */
335
346
  export async function addCommand(feature, provider, options = {}) {
336
347
  try {
337
- // Handle help flag
338
- if (options.help || feature === '--help' || feature === '-h') {
339
- await showAddHelp();
340
- return;
341
- }
348
+ // Ensure features are loaded first
349
+ await ensureFeaturesLoaded();
342
350
  // Handle list flag
343
351
  if (options.list || feature === '--list' || feature === '-l') {
344
352
  await listAvailableFeatures();
345
353
  return;
346
354
  }
355
+ // Display command banner
356
+ displayCommandBanner('Add', 'Add new features to your project with integrated templates and configurations');
347
357
  // Initialize history manager
348
358
  await historyManager.init();
349
359
  // Show disclaimer
350
360
  showFeatureDisclaimer();
351
- console.log(chalk.hex('#9c88ff')('\n🔮 Adding features to your project...'));
352
361
  // Use provided project path or current directory
353
362
  const projectPath = options.projectPath || process.cwd();
354
363
  let projectInfo;
@@ -8,7 +8,8 @@ import os from 'os';
8
8
  import gradientString from 'gradient-string';
9
9
  import boxen from 'boxen';
10
10
  import { createStandardHelp } from '../utils/helpFormatter.js';
11
- import { createBanner, displaySystemInfo, displaySuccessMessage } from '../utils/dashboard.js';
11
+ import { displayCommandBanner } from '../utils/banner.js';
12
+ import { displaySystemInfo, displaySuccessMessage } from '../utils/dashboard.js';
12
13
  import { HistoryManager } from '../utils/historyManager.js';
13
14
  /**
14
15
  * Display help for analyze command using standardized format
@@ -25,8 +26,7 @@ export function showAnalyzeHelp() {
25
26
  options: [
26
27
  { flag: '--export', description: 'Export analytics data to JSON file' },
27
28
  { flag: '--reset', description: 'Reset analytics history' },
28
- { flag: '--detailed', description: 'Show detailed analytics breakdown' },
29
- { flag: '-h, --help', description: 'Show this help message' }
29
+ { flag: '--detailed', description: 'Show detailed analytics breakdown' }
30
30
  ],
31
31
  examples: [
32
32
  { command: 'analyze', description: 'Show complete analytics dashboard' },
@@ -65,7 +65,7 @@ export async function analyzeCommand(options = {}) {
65
65
  showAnalyzeHelp();
66
66
  return;
67
67
  }
68
- createBanner('Package Installer CLI Analytics');
68
+ displayCommandBanner('Analytics', 'Comprehensive project analytics and usage insights');
69
69
  const historyManager = new HistoryManager();
70
70
  try {
71
71
  // Load analytics data from history.json
@@ -26,8 +26,7 @@ export function showCacheHelp() {
26
26
  { flag: '--clear [type]', description: 'Clear cache (optional type)' },
27
27
  { flag: '--info', description: 'Show cache information' },
28
28
  { flag: '--optimize', description: 'Optimize cache' },
29
- { flag: '--size', description: 'Show cache size only' },
30
- { flag: '-h, --help', description: 'Show this help message' }
29
+ { flag: '--size', description: 'Show cache size only' }
31
30
  ],
32
31
  examples: [
33
32
  { command: 'cache stats', description: 'Show cache statistics' },
@@ -8,6 +8,7 @@ import path from 'path';
8
8
  import semver from 'semver';
9
9
  import https from 'https';
10
10
  import { createStandardHelp } from '../utils/helpFormatter.js';
11
+ import { displayCommandBanner } from '../utils/banner.js';
11
12
  import { getSupportedLanguages, getLanguageConfig } from '../utils/languageConfig.js';
12
13
  const execAsync = promisify(exec);
13
14
  // Generate PROJECT_TYPES from shared language configuration with enhanced registry support
@@ -380,7 +381,6 @@ export function showCheckHelp() {
380
381
  'check [options]'
381
382
  ],
382
383
  options: [
383
- { flag: '-h, --help', description: 'Display help for this command' },
384
384
  { flag: '-v, --verbose', description: 'Show detailed information for all packages' }
385
385
  ],
386
386
  examples: [
@@ -427,6 +427,8 @@ export async function checkCommand(packageName, options) {
427
427
  packageName = undefined;
428
428
  }
429
429
  try {
430
+ // Display command banner
431
+ displayCommandBanner('Check', 'Check package versions and updates for your project dependencies');
430
432
  console.log('\n' + chalk.hex('#f39c12')('🔍 Starting package check...'));
431
433
  if (packageName && packageName !== '--verbose' && packageName !== '-v') {
432
434
  await checkSinglePackage(packageName, isVerbose);
@@ -6,6 +6,7 @@ import ora from 'ora';
6
6
  import fs from 'fs-extra';
7
7
  import path from 'path';
8
8
  import { createStandardHelp } from '../utils/helpFormatter.js';
9
+ import { displayCommandBanner } from '../utils/banner.js';
9
10
  /**
10
11
  * Display help for clean command
11
12
  */
@@ -25,8 +26,7 @@ export function showCleanHelp() {
25
26
  { flag: '--logs', description: 'Clean log files and debug outputs' },
26
27
  { flag: '--all', description: 'Clean everything (safe operation)' },
27
28
  { flag: '--deep', description: 'Deep clean (includes lock files)' },
28
- { flag: '--dry-run', description: 'Preview what would be cleaned' },
29
- { flag: '-h, --help', description: 'Show this help message' }
29
+ { flag: '--dry-run', description: 'Preview what would be cleaned' }
30
30
  ],
31
31
  examples: [
32
32
  { command: 'clean --build', description: 'Clean build directories only' },
@@ -65,7 +65,8 @@ export async function cleanCommand(options = {}) {
65
65
  showCleanHelp();
66
66
  return;
67
67
  }
68
- console.clear();
68
+ // Display command banner
69
+ displayCommandBanner('Clean', 'Clean development artifacts, caches, and temporary files from your project');
69
70
  console.log(chalk.hex('#ffa502')('🧹 Project Cleaner\n'));
70
71
  const projectPath = process.cwd();
71
72
  const isDryRun = options['dryRun'] || options['dry-run'];
@@ -16,7 +16,6 @@ export function showCloneHelp() {
16
16
  'clone [options]'
17
17
  ],
18
18
  options: [
19
- { flag: '-h, --help', description: 'Display help for this command' },
20
19
  { flag: '--offline', description: 'Use cached templates if available' },
21
20
  { flag: '--no-deps', description: 'Skip dependency installation' },
22
21
  { flag: '--no-git', description: 'Skip git initialization' },
@@ -4,6 +4,7 @@
4
4
  import chalk from 'chalk';
5
5
  import path from 'path';
6
6
  import { createStandardHelp } from '../utils/helpFormatter.js';
7
+ import { displayCommandBanner } from '../utils/banner.js';
7
8
  import { promptProjectName, promptFrameworkSelection, promptLanguageSelection, promptTemplateSelection, promptFrameworkOptions, promptTemplateConfirmation, promptFeatureSelection, hasFrameworkOptions, hasUIOptions, hasBundlerOptions, shouldShowTemplates } from '../utils/prompts.js';
8
9
  import { resolveTemplatePath, generateTemplateName, templateExists, getFrameworkConfig } from '../utils/templateResolver.js';
9
10
  import { createProjectFromTemplate, installDependenciesForCreate } from '../utils/templateCreator.js';
@@ -22,7 +23,6 @@ export function showCreateHelp() {
22
23
  'create [options]'
23
24
  ],
24
25
  options: [
25
- { flag: '-h, --help', description: 'Display help for this command' },
26
26
  { flag: '--show-cache', description: 'Show cached preferences' },
27
27
  { flag: '--clear-cache', description: 'Clear cached preferences' }
28
28
  ],
@@ -79,6 +79,8 @@ export async function createProject(providedName, options) {
79
79
  return;
80
80
  }
81
81
  try {
82
+ // Display command banner
83
+ displayCommandBanner('Create', 'Create stunning web applications with integrated templates and features');
82
84
  console.log('\n' + chalk.hex('#10ac84')('🚀 Welcome to Package Installer CLI!'));
83
85
  console.log(chalk.hex('#95afc0')('Let\'s create something amazing together...'));
84
86
  // Step 1: Get project name (prompt if not provided)
@@ -14,9 +14,7 @@ export function showDeployHelp() {
14
14
  emoji: '🚀',
15
15
  description: 'Deploy your projects to various cloud platforms seamlessly.\nThis feature is currently under development!',
16
16
  usage: ['pi deploy'],
17
- options: [
18
- { flag: '-h, --help', description: 'Display help for this command' }
19
- ],
17
+ options: [],
20
18
  examples: [
21
19
  { command: 'pi deploy', description: 'Deploy current project' },
22
20
  { command: 'pi deploy --help', description: 'Show this help message' }
@@ -192,8 +192,7 @@ export function showDoctorHelp() {
192
192
  { flag: '--node', description: 'Check Node.js and npm setup only' },
193
193
  { flag: '--deps', description: 'Check project dependencies only' },
194
194
  { flag: '--tools', description: 'Check development tools only' },
195
- { flag: '--verbose', description: 'Show detailed diagnostic information' },
196
- { flag: '-h, --help', description: 'Show this help message' }
195
+ { flag: '--verbose', description: 'Show detailed diagnostic information' }
197
196
  ],
198
197
  examples: [
199
198
  { command: 'pi doctor', description: 'Complete health check' },
data/dist/commands/env.js CHANGED
@@ -106,7 +106,7 @@ function checkEnvironmentVariables() {
106
106
  async function generateEnvTemplate(projectPath) {
107
107
  try {
108
108
  const projectInfo = await detectProjectStack(projectPath);
109
- const envPath = path.join(projectPath, '.env.example');
109
+ const envPath = path.join(projectPath, '.env');
110
110
  let envContent = `# Environment Configuration
111
111
  # Generated by Package Installer CLI
112
112
 
@@ -222,8 +222,7 @@ export function showEnvironmentHelp() {
222
222
  { flag: '--generate', description: 'Generate .env template for project' },
223
223
  { flag: '--validate', description: 'Validate existing .env file' },
224
224
  { flag: '--export', description: 'Export environment info to file' },
225
- { flag: '--system', description: 'Show system information only' },
226
- { flag: '-h, --help', description: 'Show this help message' }
225
+ { flag: '--system', description: 'Show system information only' }
227
226
  ],
228
227
  examples: [
229
228
  { command: 'env', description: 'Interactive environment analysis' },
@@ -731,7 +731,6 @@ export function showUpdateHelp() {
731
731
  'u [options] # alias'
732
732
  ],
733
733
  options: [
734
- { flag: '-h, --help', description: 'Show this help message' },
735
734
  { flag: '--latest', description: 'Update to latest versions (breaking changes possible)' }
736
735
  ],
737
736
  examples: [
@@ -19,9 +19,7 @@ export function showUpgradeHelp() {
19
19
  emoji: '🚀',
20
20
  description: 'Update Package Installer CLI to the latest version with intelligent upgrade management.\nIncludes breaking change detection and version compatibility checks!',
21
21
  usage: ['pi upgrade-cli'],
22
- options: [
23
- { flag: '-h, --help', description: 'Display help for this command' }
24
- ],
22
+ options: [],
25
23
  examples: [
26
24
  { command: 'pi upgrade-cli', description: 'Smart upgrade with breaking change detection' },
27
25
  { command: 'pi upgrade-cli --help', description: 'Show this help message' }
data/dist/index.js CHANGED
@@ -16,8 +16,10 @@ import { updateCommand, showUpdateHelp } from './commands/update.js';
16
16
  import { analyzeCommand, showAnalyzeHelp } from './commands/analyze.js';
17
17
  import { deployCommand, showDeployHelp } from './commands/deploy.js';
18
18
  import { cleanCommand, showCleanHelp } from './commands/clean.js';
19
+ import { cacheCommand, showCacheHelp } from './commands/cache.js';
19
20
  import { environmentCommand, showEnvironmentHelp } from './commands/env.js';
20
21
  import { doctorCommand, showDoctorHelp } from './commands/doctor.js';
22
+ // Import utilities
21
23
  import { initializeCache } from './utils/cacheManager.js';
22
24
  import { displayBanner, displayCommandBanner } from './utils/banner.js';
23
25
  import { getPackageJsonPath } from './utils/pathResolver.js';
@@ -155,11 +157,16 @@ program
155
157
  .argument('[provider]', chalk.hex('#95afc0')('Provider for the feature (optional)'))
156
158
  .option('-l, --list', chalk.hex('#95afc0')('List all available features'))
157
159
  .option('-v, --verbose', chalk.hex('#95afc0')('Show detailed output'))
160
+ .option('-h, --help', chalk.hex('#95afc0')('Display help for this command'))
158
161
  .on('--help', () => {
159
162
  showAddHelp();
160
163
  })
161
164
  .action(async (feature, provider, options) => {
162
165
  try {
166
+ if (options.help) {
167
+ showAddHelp();
168
+ return;
169
+ }
163
170
  await addCommand(feature, provider, options);
164
171
  }
165
172
  catch (error) {
@@ -169,6 +176,7 @@ program
169
176
  // UPGRADE-CLI COMMAND - Update CLI to latest version
170
177
  program
171
178
  .command('upgrade-cli')
179
+ .alias('upgrade')
172
180
  .description(chalk.hex('#ff6b6b')('🚀 ') + chalk.hex('#fd79a8')('Update Package Installer CLI to the latest version'))
173
181
  .on('--help', () => {
174
182
  showUpgradeHelp();
@@ -195,10 +203,6 @@ program
195
203
  })
196
204
  .action(async (options) => {
197
205
  try {
198
- if (options.help) {
199
- showAnalyzeHelp();
200
- return;
201
- }
202
206
  await analyzeCommand(options);
203
207
  }
204
208
  catch (error) {
@@ -310,12 +314,10 @@ program
310
314
  .option('--size', 'Show cache size information')
311
315
  .option('-h, --help', 'Show help for cache command')
312
316
  .on('--help', async () => {
313
- const { showCacheHelp } = await import('./commands/cache.js');
314
317
  showCacheHelp();
315
318
  })
316
319
  .action(async (subcommand, type, options) => {
317
320
  try {
318
- const { cacheCommand } = await import('./commands/cache.js');
319
321
  await cacheCommand(subcommand, type, options);
320
322
  }
321
323
  catch (error) {
data/dist/utils/banner.js CHANGED
@@ -10,8 +10,8 @@ import { getPackageVersion } from './utils.js';
10
10
  * Generate the main CLI banner with gradient colors
11
11
  */
12
12
  export function generateBanner() {
13
- const packageGradient = gradient(['#00c6ff', '#4facfe', '#6c5ce7']);
14
- const installerGradient = gradient(['#fd79a8', '#e84393', '#fd79a8']);
13
+ const packageGradient = gradient(['#0072ff', '#00c6ff', '#4facfe']);
14
+ const installerGradient = gradient(['#00c6ff', '#0072ff', '#667eea']);
15
15
  return boxen(packageGradient(' ██████╗ █████╗ ██████╗██╗ ██╗ █████╗ ██████╗ ███████╗') + '\n' +
16
16
  packageGradient(' ██╔══██╗██╔══██╗██╔════╝██║ ██╔╝██╔══██╗██╔════╝ ██╔════╝') + '\n' +
17
17
  packageGradient(' ██████╔╝███████║██║ █████╔╝ ███████║██║ ███╗█████╗ ') + '\n' +
@@ -29,7 +29,6 @@ async function loadFeatures() {
29
29
  const featuresConfig = featuresData.features || featuresData;
30
30
  // Get available features using the centralized function
31
31
  const availableFeatures = await getAvailableFeatures();
32
- console.log(chalk.gray(`📦 Loading ${availableFeatures.length} available features...`));
33
32
  // Process each feature and load its individual JSON file
34
33
  for (const [featureName, config] of Object.entries(featuresConfig)) {
35
34
  const featureConfig = config;
@@ -89,10 +88,17 @@ async function loadFeatures() {
89
88
  console.warn(chalk.yellow('⚠️ Could not load features.json, using fallback configuration'));
90
89
  }
91
90
  }
92
- // Initialize features on module load
93
- await loadFeatures();
91
+ // Lazy loading flag
92
+ let featuresLoaded = false;
93
+ // Lazy load features when needed
94
+ async function ensureFeaturesLoaded() {
95
+ if (!featuresLoaded) {
96
+ await loadFeatures();
97
+ featuresLoaded = true;
98
+ }
99
+ }
94
100
  // Export for use in other modules
95
- export { SUPPORTED_FEATURES };
101
+ export { SUPPORTED_FEATURES, ensureFeaturesLoaded };
96
102
  // Re-export path utilities for backward compatibility
97
103
  export { getCliRootPath } from './pathResolver.js';
98
104
  /**
@@ -348,7 +354,7 @@ export async function addFeature(featureName, provider, projectPath = process.cw
348
354
  const spinner = ora(chalk.hex('#9c88ff')(`Adding ${featureName} feature...`)).start();
349
355
  try {
350
356
  // Ensure features are loaded
351
- await loadFeatures();
357
+ await ensureFeaturesLoaded();
352
358
  // Validate project path exists
353
359
  if (!await fs.pathExists(projectPath)) {
354
360
  throw new Error(`Project path does not exist: ${projectPath}`);
@@ -25,13 +25,20 @@ export function createStandardHelp(config) {
25
25
  });
26
26
  helpContent += '\n';
27
27
  // Options
28
+ helpContent += chalk.cyan('Options:') + '\n';
29
+ // Check if help flag already exists
30
+ const hasHelpFlag = config.options && config.options.some(option => option.flag.includes('-h') || option.flag.includes('--help'));
31
+ // Add custom options first
28
32
  if (config.options && config.options.length > 0) {
29
- helpContent += chalk.cyan('Options:') + '\n';
30
33
  config.options.forEach(option => {
31
34
  helpContent += chalk.gray(` ${option.flag.padEnd(20)} ${option.description}`) + '\n';
32
35
  });
33
- helpContent += '\n';
34
36
  }
37
+ // Add the global help flag only if it doesn't already exist
38
+ if (!hasHelpFlag) {
39
+ helpContent += chalk.gray(` -h, --help`.padEnd(20) + ' Show this help message') + '\n';
40
+ }
41
+ helpContent += '\n';
35
42
  // Examples
36
43
  if (config.examples && config.examples.length > 0) {
37
44
  helpContent += chalk.cyan('Examples:') + '\n';
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: package-installer-cli
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.0
4
+ version: 1.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - sharique