diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2612c5c..0061b25 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,6 +31,11 @@ jobs: exit 1 } done + - name: Generate OpenCLI spec + run: node packages/cli/dist/index.js docgen --output packages/cli/opencli.json + - uses: bhouston/clidoc-action@v1 + with: + files: packages/cli/opencli.json - run: pnpm tsc - run: pnpm lint - run: pnpm test --coverage diff --git a/.gitignore b/.gitignore index 406f191..b4ec419 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,4 @@ profile-output packages/hdrify-vscode-extension/media publish release-artifacts +packages/cli/opencli.json diff --git a/packages/cli/package.json b/packages/cli/package.json index 4238da9..80df664 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -48,6 +48,8 @@ "start": "node dist/index.js" }, "dependencies": { + "@clidoc/core": "^1.0.0", + "@clidoc/yargs": "^0.1.0", "hdrify": "workspace:*", "sharp": "^0.34.5", "yargs": "^18.0.0", diff --git a/packages/cli/src/index.ts b/packages/cli/src/index.ts index 3885962..7674c04 100644 --- a/packages/cli/src/index.ts +++ b/packages/cli/src/index.ts @@ -1,13 +1,19 @@ #!/usr/bin/env node +import { readFileSync } from 'node:fs'; import * as path from 'node:path'; import { fileURLToPath } from 'node:url'; import yargs from 'yargs'; import { hideBin } from 'yargs/helpers'; import { fileCommands } from 'yargs-file-commands'; +import { createDocgenCommand, fromYargs } from '@clidoc/yargs'; +import { handleOpenCliRequest, infoFromPackageJson } from '@clidoc/core'; +import type { OpenCliDocument } from '@clidoc/core'; const __dirname = path.dirname(fileURLToPath(import.meta.url)); const commandsDir = path.join(__dirname, 'commands'); +const pkg = JSON.parse(readFileSync(path.join(__dirname, '../package.json'), 'utf8')); +const info = infoFromPackageJson(pkg); function isCommandError(msg: string): boolean { const lower = msg.toLowerCase(); @@ -24,10 +30,12 @@ function isCommandError(msg: string): boolean { * the caller handles exit codes. */ export async function runCli(argv: string[]): Promise { + let document: OpenCliDocument; const y = yargs(argv) .scriptName('hdrify') .usage('$0 [options]') .command(await fileCommands({ commandDirs: [commandsDir] })) + .command(createDocgenCommand(() => document)) .demandCommand(1, 'You must specify a command.') .help() .alias('h', 'help') @@ -44,6 +52,8 @@ export async function runCli(argv: string[]): Promise { if (err) throw err; throw new Error(msg); }); + // generate the document once every command, including docgen, is registered + document = fromYargs(y, info); if (argv.length === 0) { console.error('You must specify a command.\n'); @@ -51,6 +61,10 @@ export async function runCli(argv: string[]): Promise { return; } + if (await handleOpenCliRequest(argv, () => document)) { + return; + } + try { return await y.parse(); } catch (error) { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1d9cf60..c9043fc 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -96,6 +96,12 @@ importers: packages/cli: dependencies: + '@clidoc/core': + specifier: ^1.0.0 + version: 1.0.0 + '@clidoc/yargs': + specifier: ^0.1.0 + version: 0.1.0 hdrify: specifier: workspace:* version: link:../hdrify @@ -496,6 +502,18 @@ packages: resolution: {integrity: sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==} engines: {node: '>=18'} + '@clidoc/core@0.1.0': + resolution: {integrity: sha512-VTkkyimkP+JFCGrebS45ykvieAC4uXLOf7e5kTK/Smjx0S3bjklPaUYba4NJ0VV2AV1+z19+qUrzREnjNKEP0A==} + engines: {node: '>=22.12.0'} + + '@clidoc/core@1.0.0': + resolution: {integrity: sha512-oyUkkXQ7VNRO7fXXn388oYe77jE+rVZE8MVhXcZb3C9VlDwAlTx/EUTk1QjQMrnd7ecJxuryb/E3qsq8gLcqAQ==} + engines: {node: '>=22.12.0'} + + '@clidoc/yargs@0.1.0': + resolution: {integrity: sha512-/h1+yuT75unZLKcimbOxBwKCc7RxFij8jE4h5UDMqrzfr8oaEbjtO9vTugoUW6WBd4Kqx7lUNIYOqqhdtpyKWA==} + engines: {node: '>=22.12.0'} + '@cloudflare/kv-asset-handler@0.4.2': resolution: {integrity: sha512-SIOD2DxrRRwQ+jgzlXCqoEFiKOFqaPjhnNTGKXSRLvp1HiOvapLaFG2kEr9dYQTYe8rKrd9uvDUzmAITeNyaHQ==} engines: {node: '>=18.0.0'} @@ -3687,6 +3705,14 @@ packages: resolution: {integrity: sha512-gOsf2YwSlleG6IjRYG2A7k0HmBMEo6qVNk9Bp/EaLgAJT5ngH6PXbqa4ItvnEwCm/velL5jAnQgsHsWnjhGmvw==} engines: {node: '>=18'} + ajv-formats@3.0.1: + resolution: {integrity: sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==} + peerDependencies: + ajv: ^8.0.0 + peerDependenciesMeta: + ajv: + optional: true + ajv@8.18.0: resolution: {integrity: sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==} @@ -7964,6 +7990,22 @@ snapshots: '@bcoe/v8-coverage@1.0.2': {} + '@clidoc/core@0.1.0': + dependencies: + ajv: 8.18.0 + ajv-formats: 3.0.1(ajv@8.18.0) + yaml: 2.9.0 + + '@clidoc/core@1.0.0': + dependencies: + ajv: 8.18.0 + ajv-formats: 3.0.1(ajv@8.18.0) + yaml: 2.9.0 + + '@clidoc/yargs@0.1.0': + dependencies: + '@clidoc/core': 0.1.0 + '@cloudflare/kv-asset-handler@0.4.2': {} '@colors/colors@1.5.0': @@ -10861,6 +10903,10 @@ snapshots: clean-stack: 5.3.0 indent-string: 5.0.0 + ajv-formats@3.0.1(ajv@8.18.0): + optionalDependencies: + ajv: 8.18.0 + ajv@8.18.0: dependencies: fast-deep-equal: 3.1.3