From b27d88e3e4d8f60481c2609ef479e798e41ceb87 Mon Sep 17 00:00:00 2001 From: shannonpereira Date: Mon, 3 Aug 2026 17:25:20 +0530 Subject: [PATCH 1/2] help simplified --- .structify/history.json | 20 +++ apps/cli/src/commands/index.ts | 5 +- apps/cli/src/commands/upgrade.ts | 33 +++- apps/cli/src/commands/validate.ts | 29 +++- apps/cli/src/context.ts | 22 ++- apps/cli/src/index.spec.ts | 2 +- apps/cli/src/index.ts | 271 +++++++++++++++++++++++++----- apps/cli/src/utils/version.ts | 50 ++++++ package.json | 4 +- 9 files changed, 374 insertions(+), 62 deletions(-) diff --git a/.structify/history.json b/.structify/history.json index 15d03bb..c7d92bd 100644 --- a/.structify/history.json +++ b/.structify/history.json @@ -8,5 +8,25 @@ "duration": 175.5287, "filesChanged": [], "summary": "Generated Graph" + }, + { + "id": "3f6df786-8828-4725-9aa7-0a279ca9d856", + "timestamp": "2026-08-03T11:42:54.024Z", + "version": "1.0.1", + "operation": "deps", + "status": "success", + "duration": 94.2069, + "filesChanged": [], + "summary": "Dependency Audit" + }, + { + "id": "0898d986-a491-4d87-a774-0ed0b2622f74", + "timestamp": "2026-08-03T11:43:04.650Z", + "version": "1.0.1", + "operation": "graph", + "status": "success", + "duration": 150.2621, + "filesChanged": [], + "summary": "Generated Graph" } ] \ No newline at end of file diff --git a/apps/cli/src/commands/index.ts b/apps/cli/src/commands/index.ts index 3b8eb4d..995cdd5 100644 --- a/apps/cli/src/commands/index.ts +++ b/apps/cli/src/commands/index.ts @@ -434,13 +434,14 @@ export function registerCommands(program: Command): void { program .command('upgrade') - .description('Preview or apply safe Structify project upgrades') + .description('Preview or apply safe Structify project upgrades or CLI updates') .option('-d, --dry-run', 'Preview upgrade plan without writing files') .option('-y, --yes', 'Apply safe metadata/package upgrades without confirmation') + .option('--cli', 'Check for updates to the structify-tool CLI package') .option('--path ', 'Project path to upgrade') .addHelpText( 'after', - '\nExamples:\n $ structify upgrade --dry-run\n $ structify upgrade --json', + '\nExamples:\n $ structify upgrade --dry-run\n $ structify upgrade --cli\n $ structify upgrade --json', ) .action(async (options, commandInstance) => { const globalOpts = program.opts(); diff --git a/apps/cli/src/commands/upgrade.ts b/apps/cli/src/commands/upgrade.ts index bbe4305..d0e71be 100644 --- a/apps/cli/src/commands/upgrade.ts +++ b/apps/cli/src/commands/upgrade.ts @@ -5,18 +5,49 @@ import { StructifyCLIError } from '../utils/error.js'; import { getElapsedMs } from '../utils/middleware.js'; import { createUpgradePlan, executePatchPlan, appendHistoryEntry } from '@structify/core'; +import { checkCliVersionUpdate } from '../utils/version.js'; + export interface UpgradeOptions { dryRun?: boolean; yes?: boolean; + cli?: boolean; path?: string; } export async function handleUpgrade(options: UpgradeOptions, context: CLIContext): Promise { const output = new CLIOutput(context); + const elapsed = getElapsedMs(context.startTime); + + if (options.cli) { + const updateCheck = await checkCliVersionUpdate(context.packageVersion); + if (context.json) { + output.json({ + success: true, + command: 'upgrade --cli', + timestamp: new Date().toISOString(), + durationMs: elapsed, + data: updateCheck, + }); + return; + } + + output.heading('Structify CLI Package Update Status'); + output.info(`Current Version: v${updateCheck.currentVersion}`); + output.info(`Latest Version on npm: v${updateCheck.latestVersion}`); + output.info(''); + if (updateCheck.updateAvailable) { + output.warn(`An update is available! (v${updateCheck.currentVersion} → v${updateCheck.latestVersion})`); + output.info(`To upgrade, run: ${updateCheck.updateCommand}`); + } else { + output.success('Structify CLI is up to date!'); + } + output.showFooter('upgrade'); + return; + } + output.heading('Structify Project Upgrade'); const projectPath = path.resolve(context.cwd, options.path ?? '.'); const upgrade = createUpgradePlan(projectPath); - const elapsed = getElapsedMs(context.startTime); if (context.json) { if (!options.dryRun && options.yes && !upgrade.reviewRequired) { diff --git a/apps/cli/src/commands/validate.ts b/apps/cli/src/commands/validate.ts index 72579a9..f9498fd 100644 --- a/apps/cli/src/commands/validate.ts +++ b/apps/cli/src/commands/validate.ts @@ -53,10 +53,31 @@ export async function handleValidate(options: ValidateOptions, context: CLIConte throw new StructifyCLIError('VALIDATION_ERROR', `Failed to parse config file JSON: ${msg}`); } } else { - throw new StructifyCLIError( - 'USAGE_ERROR', - 'Please specify a configuration path using "--config " or use "--example" to check the built-in demo configuration.', - ); + // Auto-discover structify.config.json or structify.json in cwd + const defaultConfigPath = path.join(context.cwd, 'structify.config.json'); + const altConfigPath = path.join(context.cwd, 'structify.json'); + let targetPath: string | null = null; + + if (fs.existsSync(defaultConfigPath)) { + targetPath = defaultConfigPath; + } else if (fs.existsSync(altConfigPath)) { + targetPath = altConfigPath; + } + + if (targetPath) { + output.info(`Auto-detected config file: ${path.basename(targetPath)}`); + try { + configToValidate = JSON.parse(fs.readFileSync(targetPath, 'utf8')); + } catch (err) { + const msg = err instanceof Error ? err.message : String(err); + throw new StructifyCLIError('VALIDATION_ERROR', `Failed to parse config file JSON: ${msg}`); + } + } else { + throw new StructifyCLIError( + 'USAGE_ERROR', + 'No structify.config.json or structify.json found in current directory. Specify a path using "--config " or use "--example" to check the demo config.', + ); + } } const result = validateStack(configToValidate as ProjectConfig); diff --git a/apps/cli/src/context.ts b/apps/cli/src/context.ts index 3bbf123..6134409 100644 --- a/apps/cli/src/context.ts +++ b/apps/cli/src/context.ts @@ -40,9 +40,9 @@ export function createCLIContext( ): CLIContext { const argList = args || []; const manualNoColor = argList.includes('--no-color'); - const manualVerbose = argList.includes('--verbose'); - const manualDebug = argList.includes('--debug'); - const manualJson = argList.includes('--json'); + const manualVerbose = argList.includes('--no-verbose') ? false : argList.includes('--verbose'); + const manualDebug = argList.includes('--no-debug') ? false : argList.includes('--debug'); + const manualJson = argList.includes('--no-json') ? false : argList.includes('--json'); let manualCwd: string | undefined; const cwdIdx = argList.indexOf('--cwd'); @@ -50,7 +50,11 @@ export function createCLIContext( manualCwd = argList[cwdIdx + 1]; } - const targetCwd = options.cwd ? path.resolve(options.cwd) : (manualCwd ? path.resolve(manualCwd) : process.cwd()); + const targetCwd = options.cwd + ? path.resolve(process.cwd(), options.cwd) + : manualCwd + ? path.resolve(process.cwd(), manualCwd) + : process.cwd(); let detectedPackageManager: 'npm' | 'none' = 'none'; try { @@ -61,6 +65,10 @@ export function createCLIContext( // Fail silently } + const debugVal = options.debug !== undefined ? options.debug : manualDebug; + const verboseVal = options.verbose !== undefined ? options.verbose : manualVerbose; + const jsonVal = options.json !== undefined ? options.json : manualJson; + return { packageName: 'structify-tool', packageVersion: getCliVersion(), @@ -71,9 +79,9 @@ export function createCLIContext( nodeVersion: process.version, platform: os.platform(), arch: os.arch(), - debug: !!options.debug || manualDebug, - verbose: !!options.verbose || manualVerbose, - json: !!options.json || manualJson, + debug: debugVal, + verbose: verboseVal, + json: jsonVal, noColor: !!options.noColor || manualNoColor || process.env.NO_COLOR === 'true', isCI: process.env.CI === 'true', isTTY: process.stdout.isTTY ?? false, diff --git a/apps/cli/src/index.spec.ts b/apps/cli/src/index.spec.ts index 0424a37..bd3314b 100644 --- a/apps/cli/src/index.spec.ts +++ b/apps/cli/src/index.spec.ts @@ -118,7 +118,7 @@ describe('CLI Shell Unit Tests', () => { it('should not hardcode the Commander version output', () => { const source = fs.readFileSync(path.resolve(__dirname, 'index.ts'), 'utf8'); - expect(source).toContain('.version(getCliVersion())'); + expect(source).toContain('.version(getCliVersion()'); expect(source).not.toContain(".version('1.0.0')"); expect(source).not.toContain('.version("1.0.0")'); }); diff --git a/apps/cli/src/index.ts b/apps/cli/src/index.ts index f907e7d..41b74dd 100644 --- a/apps/cli/src/index.ts +++ b/apps/cli/src/index.ts @@ -1,10 +1,12 @@ +import path from 'path'; +import fs from 'fs'; import { Command } from 'commander'; import { registerCommands } from './commands/index.js'; import { createCLIContext } from './context.js'; import { CLIOutput } from './utils/output.js'; import { StructifyCLIError } from './utils/error.js'; import { runCentralizedCleanup } from './utils/prompts.js'; -import { getCliVersion } from './utils/version.js'; +import { getCliVersion, checkCliVersionUpdate } from './utils/version.js'; async function main() { process.on('exit', () => { @@ -35,15 +37,20 @@ async function main() { .description( 'Professional platform for initializing, extending, and inspecting software architectures', ) - .version(getCliVersion()); + .version(getCliVersion(), '-v, --v, -version, -V, --version', 'Output the version number'); // Register global options program .option('--verbose', 'Print additional diagnostic logs') + .option('--no-verbose', 'Disable additional diagnostic logs') .option('--debug', 'Enable debug output and stack traces') + .option('--no-debug', 'Disable debug output and stack traces') .option('--json', 'Render machine-readable JSON payloads') + .option('--no-json', 'Disable machine-readable JSON payloads') .option('--no-color', 'Omit colored console outputs') - .option('--cwd ', 'Change context working directory'); + .option('--cwd ', 'Change context working directory') + .option('--update', 'Check or perform CLI / project updates') + .option('--upgrade', 'Check or perform CLI / project updates'); // Register commands registerCommands(program); @@ -64,6 +71,103 @@ async function main() { process.exit(0); } + // Check if process.argv consists solely of global option flags (no subcommand provided) + const rawArgs = process.argv.slice(2); + const nonFlagArgs = rawArgs.filter((arg, i) => { + if (arg.startsWith('-')) return false; + const prev = rawArgs[i - 1]; + if (prev && (prev === '--cwd' || prev === '-c' || prev === '-p' || prev === '--config' || prev === '--preset' || prev === '--output')) { + return false; + } + return true; + }); + + if (nonFlagArgs.length === 0) { + const globalOpts = { + json: rawArgs.includes('--no-json') ? false : rawArgs.includes('--json'), + debug: rawArgs.includes('--no-debug') ? false : rawArgs.includes('--debug'), + verbose: rawArgs.includes('--no-verbose') ? false : rawArgs.includes('--verbose'), + noColor: rawArgs.includes('--no-color'), + }; + const context = createCLIContext(process.argv, globalOpts); + const output = new CLIOutput(context); + + if (rawArgs.includes('--update') || rawArgs.includes('--upgrade')) { + const updateCheck = await checkCliVersionUpdate(getCliVersion()); + if (context.json) { + output.json({ + command: 'update', + ...updateCheck, + }); + } else { + output.heading('Structify Update Check'); + output.info(`Installed Version: v${updateCheck.currentVersion}`); + output.info(`Latest Version on npm: v${updateCheck.latestVersion}`); + output.info(''); + if (updateCheck.updateAvailable) { + output.warn(`Update available! (v${updateCheck.currentVersion} → v${updateCheck.latestVersion})`); + output.info(`Run: ${updateCheck.updateCommand}`); + } else { + output.success('Structify is up to date!'); + } + } + return; + } + + if (context.json) { + const pkgPath = path.join(context.cwd, 'package.json'); + let manifest: unknown = null; + if (fs.existsSync(pkgPath)) { + try { + manifest = JSON.parse(fs.readFileSync(pkgPath, 'utf8')); + } catch (_e) { + // ignore parse errors + } + } + + if (manifest) { + output.json(manifest); + } else { + output.json({ + name: program.name(), + version: getCliVersion(), + status: 'online', + overview: { + projectName: path.basename(context.cwd), + workingDirectory: context.cwd, + detectedPackageManager: context.detectedPackageManager, + nodeVersion: context.nodeVersion, + platform: `${context.platform} (${context.arch})`, + }, + diagnosticsState: { + debug: context.debug, + verbose: context.verbose, + json: context.json, + noColor: context.noColor, + }, + }); + } + process.exit(0); + } else if ( + rawArgs.includes('--debug') || + rawArgs.includes('--no-debug') || + rawArgs.includes('--verbose') || + rawArgs.includes('--no-verbose') + ) { + output.heading('Structify Debug & Diagnostics State'); + output.info(`Project Name: ${path.basename(context.cwd)}`); + output.info(`Version: ${getCliVersion()}`); + output.info(`Working Directory: ${context.cwd}`); + output.info(`Node Version: ${context.nodeVersion}`); + output.info(`Platform: ${context.platform} (${context.arch})`); + output.info(`Debug: ${context.debug}`); + output.info(`Verbose: ${context.verbose}`); + output.info(`JSON Output: ${context.json}`); + output.info(`No Color: ${context.noColor}`); + process.exit(0); + } + } + try { await program.parseAsync(process.argv); } catch (err) { @@ -104,15 +208,16 @@ function formatHelpScreen(program: Command, context: ReturnType context.noColor ? text : `\x1b[1m${text}\x1b[0m`; const gray = (text: string) => context.noColor ? text : `\x1b[90m${text}\x1b[0m`; + const showAll = process.argv.includes('--all'); const lines: string[] = []; // 1. Usage lines.push(`${cyan('◆')} ${bold('Usage:')} ${purple('structify')} ${gray('[options]')} ${cyan('[command]')}`); lines.push(''); - // 3. Global Options + // 2. Global Options lines.push(`${gray('┌─')} ${bold('GLOBAL OPTIONS')} ${gray('───────────────────────────────────────┐')}`); - lines.push(`${gray('│')} ${cyan('-V, --version')} ${gray('Output the version number')} ${gray('│')}`); + lines.push(`${gray('│')} ${cyan('-v, -V, --version')} ${gray('Output the version number')} ${gray('│')}`); lines.push(`${gray('│')} ${cyan('--verbose')} ${gray('Print additional diagnostic logs')} ${gray('│')}`); lines.push(`${gray('│')} ${cyan('--debug')} ${gray('Enable debug output and stack traces')} ${gray('│')}`); lines.push(`${gray('│')} ${cyan('--json')} ${gray('Render machine-readable JSON payloads')} ${gray('│')}`); @@ -121,7 +226,111 @@ function formatHelpScreen(program: Command, context: ReturnType', + purpose: 'Scaffold a brand new project interactively', + options: '--yes (skip questions), --preset (use template), --dry-run (preview output)', + example: 'structify init my-app --yes', + }, + { + cmd: 'structify add ', + purpose: 'Add a tool/module to existing project (e.g., docker, tailwind, prisma)', + options: '--force (overwrite files), --dry-run (preview files to be created)', + example: 'structify add docker', + }, + ], + }, + { + title: 'HEALTH & INTELLIGENCE', + cmds: [ + { + cmd: 'structify doctor', + purpose: 'Check Node version, installed tools, and project health', + options: '--fix (auto-fix issues), --json (export raw data)', + example: 'structify doctor --json', + }, + { + cmd: 'structify graph', + purpose: 'Show visual project folder & file architecture tree', + options: '--cwd (target subfolder), --json (output as JSON)', + example: 'structify graph --cwd packages/core', + }, + { + cmd: 'structify deps', + purpose: 'Check for missing, outdated, or unused npm packages', + options: '--path (check subfolder), --json (output report as JSON)', + example: 'structify deps --json', + }, + { + cmd: 'structify inspect', + purpose: 'View summary of detected stack components & status', + options: '--path (target subfolder), --json (output as JSON)', + example: 'structify inspect', + }, + ], + }, + { + title: 'MAINTENANCE & UPGRADES', + cmds: [ + { + cmd: 'structify repair', + purpose: 'Auto-fix broken config files or missing metadata', + options: '--yes (apply fixes immediately), --dry-run (preview fixes only)', + example: 'structify repair --dry-run', + }, + { + cmd: 'structify upgrade', + purpose: 'Update project dependencies or check for CLI updates', + options: '--cli (check structify CLI update), --yes (apply updates), --dry-run (preview)', + example: 'structify upgrade --cli', + }, + ], + }, + { + title: 'CONFIGURATION & PRESETS', + cmds: [ + { + cmd: 'structify preset ', + purpose: 'Manage saved stack templates (actions: list, save, apply, delete)', + options: 'list (show presets), save (save current), apply (use preset)', + example: 'structify preset list', + }, + { + cmd: 'structify validate', + purpose: 'Audit structify.config.json file for syntax & stack errors', + options: '--config (specify file), --example (check demo config)', + example: 'structify validate --example', + }, + ], + }, + ]; + + for (const cat of CATEGORIES) { + lines.push(`${gray('╭─')} ${bold(cat.title)} ${gray('──────────────────────────────────────────────╮')}`); + for (const item of cat.cmds) { + lines.push(`${gray('│')}`); + lines.push(`${gray('│')} ${cyan(item.cmd.padEnd(32))} ${gray('→')} ${bold(item.purpose)}`); + lines.push(`${gray('│')} ${gray('Options:')} ${purple(item.options)}`); + lines.push(`${gray('│')} ${gray('Example:')} ${cyan(item.example)}`); + } + lines.push(`${gray('│')}`); + lines.push(gray('╰──────────────────────────────────────────────────────────────────────────╯')); + lines.push(''); + } + + lines.push(`${gray('Run')} ${purple('structify help ')} ${gray('for custom command parameters')}`); + lines.push(`${gray('Run')} ${purple('structify --help --all')} ${gray('to view all extended enterprise commands')}`); + lines.push(''); + return lines.join('\n'); + } + + // Full extended view (--all flag) const setupGroup: string[] = []; const intelligenceGroup: string[] = []; const templatingGroup: string[] = []; @@ -137,7 +346,7 @@ function formatHelpScreen(program: Command, context: ReturnType 0) { lines.push(`${gray('╭─')} ${bold('SETUP & WORKSPACE')} ${gray('────────────────────────────────────╮')}`); - for (const line of setupGroup) { - lines.push(`${gray('│')} ${line}`); - } + for (const line of setupGroup) lines.push(`${gray('│')} ${line}`); lines.push(gray('╰────────────────────────────────────────────────────────╯')); lines.push(''); } - // Group 2: Intelligence & Auditing if (intelligenceGroup.length > 0) { lines.push(`${gray('╭─')} ${bold('INTELLIGENCE & AUDITING')} ${gray('──────────────────────────────╮')}`); - for (const line of intelligenceGroup) { - lines.push(`${gray('│')} ${line}`); - } + for (const line of intelligenceGroup) lines.push(`${gray('│')} ${line}`); lines.push(gray('╰────────────────────────────────────────────────────────╯')); lines.push(''); } - // Group 3: Core Templating & Generation if (templatingGroup.length > 0) { lines.push(`${gray('╭─')} ${bold('TEMPLATING & ARTIFACTS')} ${gray('───────────────────────────────╮')}`); - for (const line of templatingGroup) { - lines.push(`${gray('│')} ${line}`); - } + for (const line of templatingGroup) lines.push(`${gray('│')} ${line}`); lines.push(gray('╰────────────────────────────────────────────────────────╯')); lines.push(''); } - // Group 4: Registry & Packages if (registryGroup.length > 0) { lines.push(`${gray('╭─')} ${bold('REGISTRY & PACKAGES')} ${gray('──────────────────────────────────╮')}`); - for (const line of registryGroup) { - lines.push(`${gray('│')} ${line}`); - } + for (const line of registryGroup) lines.push(`${gray('│')} ${line}`); lines.push(gray('╰────────────────────────────────────────────────────────╯')); lines.push(''); } - // Group 5: Visualization & Graphs if (graphGroup.length > 0) { lines.push(`${gray('╭─')} ${bold('VISUALIZATION & GRAPHS')} ${gray('───────────────────────────────╮')}`); - for (const line of graphGroup) { - lines.push(`${gray('│')} ${line}`); - } + for (const line of graphGroup) lines.push(`${gray('│')} ${line}`); lines.push(gray('╰────────────────────────────────────────────────────────╯')); lines.push(''); } - // Group 6: Workspace State & Migrations if (migrationGroup.length > 0) { lines.push(`${gray('╭─')} ${bold('STATE & MIGRATIONS')} ${gray('───────────────────────────────────╮')}`); - for (const line of migrationGroup) { - lines.push(`${gray('│')} ${line}`); - } + for (const line of migrationGroup) lines.push(`${gray('│')} ${line}`); lines.push(gray('╰────────────────────────────────────────────────────────╯')); lines.push(''); } - // Group 7: Performance & Reports if (performanceGroup.length > 0) { lines.push(`${gray('╭─')} ${bold('PERFORMANCE & REPORTS')} ${gray('────────────────────────────────╮')}`); - for (const line of performanceGroup) { - lines.push(`${gray('│')} ${line}`); - } + for (const line of performanceGroup) lines.push(`${gray('│')} ${line}`); lines.push(gray('╰────────────────────────────────────────────────────────╯')); lines.push(''); } - // Group 8: Deep Explanations & Diagnostics if (diagnosticGroup.length > 0) { lines.push(`${gray('╭─')} ${bold('EXPLANATIONS & DIAGNOSTICS')} ${gray('───────────────────────────╮')}`); - for (const line of diagnosticGroup) { - lines.push(`${gray('│')} ${line}`); - } + for (const line of diagnosticGroup) lines.push(`${gray('│')} ${line}`); lines.push(gray('╰────────────────────────────────────────────────────────╯')); lines.push(''); } - // Group 9: Other Commands (Dynamic fallback) if (otherGroup.length > 0) { lines.push(`${gray('╭─')} ${bold('OTHER COMMANDS')} ${gray('───────────────────────────────────────╮')}`); - for (const line of otherGroup) { - lines.push(`${gray('│')} ${line}`); - } + for (const line of otherGroup) lines.push(`${gray('│')} ${line}`); lines.push(gray('╰────────────────────────────────────────────────────────╯')); lines.push(''); } diff --git a/apps/cli/src/utils/version.ts b/apps/cli/src/utils/version.ts index 74323be..9c331d2 100644 --- a/apps/cli/src/utils/version.ts +++ b/apps/cli/src/utils/version.ts @@ -73,3 +73,53 @@ function isStructifyPackage(packagePath: string): boolean { return false; } } + +export interface VersionCheckResult { + currentVersion: string; + latestVersion: string; + isLatest: boolean; + updateAvailable: boolean; + updateCommand: string; +} + +export async function checkCliVersionUpdate(currentVersion?: string): Promise { + const current = currentVersion || getCliVersion(); + let latest = current; + + try { + const res = await fetch('https://registry.npmjs.org/structify-tool/latest', { + headers: { Accept: 'application/json' }, + signal: AbortSignal.timeout(3000), + }); + if (res.ok) { + const data = (await res.json()) as { version?: string }; + if (data && typeof data.version === 'string') { + latest = data.version; + } + } + } catch { + // Fail silently if network/timeout occurs + } + + const updateAvailable = latest !== current && compareVersions(latest, current) > 0; + + return { + currentVersion: current, + latestVersion: latest, + isLatest: !updateAvailable, + updateAvailable, + updateCommand: 'npm install -g structify-tool@latest', + }; +} + +function compareVersions(v1: string, v2: string): number { + const p1 = v1.split('.').map(Number); + const p2 = v2.split('.').map(Number); + for (let i = 0; i < Math.max(p1.length, p2.length); i++) { + const num1 = p1[i] || 0; + const num2 = p2[i] || 0; + if (num1 > num2) return 1; + if (num1 < num2) return -1; + } + return 0; +} diff --git a/package.json b/package.json index 53728b1..0ca89c8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "structify-monorepo", - "version": "1.0.0", + "version": "1.3.2", "private": true, "workspaces": [ "apps/*", @@ -45,4 +45,4 @@ "vitest": "^1.6.0" }, "packageManager": "npm@11.12.1" -} +} \ No newline at end of file From 4fcf7bd55af1e3e049cfbd52ae22c1052a8ecbcc Mon Sep 17 00:00:00 2001 From: shannonpereira Date: Mon, 3 Aug 2026 17:31:08 +0530 Subject: [PATCH 2/2] fix prettier formatting for CI --- apps/cli/src/commands/upgrade.ts | 4 +- apps/cli/src/context.ts | 2 +- apps/cli/src/index.ts | 100 +++++++++++++++++++++++-------- package.json | 2 +- 4 files changed, 81 insertions(+), 27 deletions(-) diff --git a/apps/cli/src/commands/upgrade.ts b/apps/cli/src/commands/upgrade.ts index cab9598..5764602 100644 --- a/apps/cli/src/commands/upgrade.ts +++ b/apps/cli/src/commands/upgrade.ts @@ -36,7 +36,9 @@ export async function handleUpgrade(options: UpgradeOptions, context: CLIContext output.info(`Latest Version on npm: v${updateCheck.latestVersion}`); output.info(''); if (updateCheck.updateAvailable) { - output.warn(`An update is available! (v${updateCheck.currentVersion} → v${updateCheck.latestVersion})`); + output.warn( + `An update is available! (v${updateCheck.currentVersion} → v${updateCheck.latestVersion})`, + ); output.info(`To upgrade, run: ${updateCheck.updateCommand}`); } else { output.success('Structify CLI is up to date!'); diff --git a/apps/cli/src/context.ts b/apps/cli/src/context.ts index 6134409..c8dfd55 100644 --- a/apps/cli/src/context.ts +++ b/apps/cli/src/context.ts @@ -43,7 +43,7 @@ export function createCLIContext( const manualVerbose = argList.includes('--no-verbose') ? false : argList.includes('--verbose'); const manualDebug = argList.includes('--no-debug') ? false : argList.includes('--debug'); const manualJson = argList.includes('--no-json') ? false : argList.includes('--json'); - + let manualCwd: string | undefined; const cwdIdx = argList.indexOf('--cwd'); if (cwdIdx !== -1 && cwdIdx + 1 < argList.length) { diff --git a/apps/cli/src/index.ts b/apps/cli/src/index.ts index 11a596e..565f777 100644 --- a/apps/cli/src/index.ts +++ b/apps/cli/src/index.ts @@ -76,7 +76,15 @@ async function main() { const nonFlagArgs = rawArgs.filter((arg, i) => { if (arg.startsWith('-')) return false; const prev = rawArgs[i - 1]; - if (prev && (prev === '--cwd' || prev === '-c' || prev === '-p' || prev === '--config' || prev === '--preset' || prev === '--output')) { + if ( + prev && + (prev === '--cwd' || + prev === '-c' || + prev === '-p' || + prev === '--config' || + prev === '--preset' || + prev === '--output') + ) { return false; } return true; @@ -105,7 +113,9 @@ async function main() { output.info(`Latest Version on npm: v${updateCheck.latestVersion}`); output.info(''); if (updateCheck.updateAvailable) { - output.warn(`Update available! (v${updateCheck.currentVersion} → v${updateCheck.latestVersion})`); + output.warn( + `Update available! (v${updateCheck.currentVersion} → v${updateCheck.latestVersion})`, + ); output.info(`Run: ${updateCheck.updateCommand}`); } else { output.success('Structify is up to date!'); @@ -261,13 +271,27 @@ function formatHelpScreen(program: Command, context: ReturnType')} ${gray('Change context working directory')} ${gray('│')}`); + lines.push( + `${gray('┌─')} ${bold('GLOBAL OPTIONS')} ${gray('───────────────────────────────────────┐')}`, + ); + lines.push( + `${gray('│')} ${cyan('-v, -V, --version')} ${gray('Output the version number')} ${gray('│')}`, + ); + lines.push( + `${gray('│')} ${cyan('--verbose')} ${gray('Print additional diagnostic logs')} ${gray('│')}`, + ); + lines.push( + `${gray('│')} ${cyan('--debug')} ${gray('Enable debug output and stack traces')} ${gray('│')}`, + ); + lines.push( + `${gray('│')} ${cyan('--json')} ${gray('Render machine-readable JSON payloads')} ${gray('│')}`, + ); + lines.push( + `${gray('│')} ${cyan('--no-color')} ${gray('Omit colored console outputs')} ${gray('│')}`, + ); + lines.push( + `${gray('│')} ${cyan('--cwd ')} ${gray('Change context working directory')} ${gray('│')}`, + ); lines.push(gray('└────────────────────────────────────────────────────────┘')); lines.push(''); @@ -280,7 +304,8 @@ function formatHelpScreen(program: Command, context: ReturnType', purpose: 'Scaffold a brand new project interactively', - options: '--yes (skip questions), --preset (use template), --dry-run (preview output)', + options: + '--yes (skip questions), --preset (use template), --dry-run (preview output)', example: 'structify init my-app --yes', }, { @@ -332,7 +357,8 @@ function formatHelpScreen(program: Command, context: ReturnType')} ${gray('for custom command parameters')}`); - lines.push(`${gray('Run')} ${purple('structify --help --all')} ${gray('to view all extended enterprise commands')}`); + lines.push( + `${gray('Run')} ${purple('structify help ')} ${gray('for custom command parameters')}`, + ); + lines.push( + `${gray('Run')} ${purple('structify --help --all')} ${gray('to view all extended enterprise commands')}`, + ); lines.push(''); return lines.join('\n'); } @@ -419,63 +453,81 @@ function formatHelpScreen(program: Command, context: ReturnType 0) { - lines.push(`${gray('╭─')} ${bold('SETUP & WORKSPACE')} ${gray('────────────────────────────────────╮')}`); + lines.push( + `${gray('╭─')} ${bold('SETUP & WORKSPACE')} ${gray('────────────────────────────────────╮')}`, + ); for (const line of setupGroup) lines.push(`${gray('│')} ${line}`); lines.push(gray('╰────────────────────────────────────────────────────────╯')); lines.push(''); } if (intelligenceGroup.length > 0) { - lines.push(`${gray('╭─')} ${bold('INTELLIGENCE & AUDITING')} ${gray('──────────────────────────────╮')}`); + lines.push( + `${gray('╭─')} ${bold('INTELLIGENCE & AUDITING')} ${gray('──────────────────────────────╮')}`, + ); for (const line of intelligenceGroup) lines.push(`${gray('│')} ${line}`); lines.push(gray('╰────────────────────────────────────────────────────────╯')); lines.push(''); } if (templatingGroup.length > 0) { - lines.push(`${gray('╭─')} ${bold('TEMPLATING & ARTIFACTS')} ${gray('───────────────────────────────╮')}`); + lines.push( + `${gray('╭─')} ${bold('TEMPLATING & ARTIFACTS')} ${gray('───────────────────────────────╮')}`, + ); for (const line of templatingGroup) lines.push(`${gray('│')} ${line}`); lines.push(gray('╰────────────────────────────────────────────────────────╯')); lines.push(''); } if (registryGroup.length > 0) { - lines.push(`${gray('╭─')} ${bold('REGISTRY & PACKAGES')} ${gray('──────────────────────────────────╮')}`); + lines.push( + `${gray('╭─')} ${bold('REGISTRY & PACKAGES')} ${gray('──────────────────────────────────╮')}`, + ); for (const line of registryGroup) lines.push(`${gray('│')} ${line}`); lines.push(gray('╰────────────────────────────────────────────────────────╯')); lines.push(''); } if (graphGroup.length > 0) { - lines.push(`${gray('╭─')} ${bold('VISUALIZATION & GRAPHS')} ${gray('───────────────────────────────╮')}`); + lines.push( + `${gray('╭─')} ${bold('VISUALIZATION & GRAPHS')} ${gray('───────────────────────────────╮')}`, + ); for (const line of graphGroup) lines.push(`${gray('│')} ${line}`); lines.push(gray('╰────────────────────────────────────────────────────────╯')); lines.push(''); } if (migrationGroup.length > 0) { - lines.push(`${gray('╭─')} ${bold('STATE & MIGRATIONS')} ${gray('───────────────────────────────────╮')}`); + lines.push( + `${gray('╭─')} ${bold('STATE & MIGRATIONS')} ${gray('───────────────────────────────────╮')}`, + ); for (const line of migrationGroup) lines.push(`${gray('│')} ${line}`); lines.push(gray('╰────────────────────────────────────────────────────────╯')); lines.push(''); } if (performanceGroup.length > 0) { - lines.push(`${gray('╭─')} ${bold('PERFORMANCE & REPORTS')} ${gray('────────────────────────────────╮')}`); + lines.push( + `${gray('╭─')} ${bold('PERFORMANCE & REPORTS')} ${gray('────────────────────────────────╮')}`, + ); for (const line of performanceGroup) lines.push(`${gray('│')} ${line}`); lines.push(gray('╰────────────────────────────────────────────────────────╯')); lines.push(''); } if (diagnosticGroup.length > 0) { - lines.push(`${gray('╭─')} ${bold('EXPLANATIONS & DIAGNOSTICS')} ${gray('───────────────────────────╮')}`); + lines.push( + `${gray('╭─')} ${bold('EXPLANATIONS & DIAGNOSTICS')} ${gray('───────────────────────────╮')}`, + ); for (const line of diagnosticGroup) lines.push(`${gray('│')} ${line}`); lines.push(gray('╰────────────────────────────────────────────────────────╯')); lines.push(''); } if (otherGroup.length > 0) { - lines.push(`${gray('╭─')} ${bold('OTHER COMMANDS')} ${gray('───────────────────────────────────────╮')}`); + lines.push( + `${gray('╭─')} ${bold('OTHER COMMANDS')} ${gray('───────────────────────────────────────╮')}`, + ); for (const line of otherGroup) lines.push(`${gray('│')} ${line}`); lines.push(gray('╰────────────────────────────────────────────────────────╯')); lines.push(''); diff --git a/package.json b/package.json index 5c7263a..3160adc 100644 --- a/package.json +++ b/package.json @@ -48,4 +48,4 @@ "vitest": "^1.6.0" }, "packageManager": "npm@11.12.1" -} \ No newline at end of file +}