Skip to content

Commit c087ac8

Browse files
committed
feat(inquirerer): add package helpers and update @inquirerer/utils
- Add getPackageJson, getPackageVersion, getPackageName to inquirerer - Remove findAndRequirePackageJson re-export (use getPackageJson instead) - Update README with CLI Utilities documentation - Update @inquirerer/utils to re-export from inquirerer for backwards compat - Remove duplicated code from @inquirerer/utils (argv.ts, cli-error.ts, package-json.ts) - Add legacy aliases (getSelfPackageJson, getSelfVersion, getSelfName) for backwards compat
1 parent f071c62 commit c087ac8

10 files changed

Lines changed: 2806 additions & 5339 deletions

File tree

packages/inquirerer-utils/package.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,7 @@
2929
},
3030
"dependencies": {
3131
"appstash": "workspace:*",
32-
"find-and-require-package-json": "workspace:*",
33-
"minimist": "^1.2.8"
32+
"inquirerer": "workspace:*"
3433
},
3534
"devDependencies": {
3635
"@types/minimist": "^1.2.5",

packages/inquirerer-utils/src/argv.ts

Lines changed: 0 additions & 16 deletions
This file was deleted.

packages/inquirerer-utils/src/cli-error.ts

Lines changed: 0 additions & 43 deletions
This file was deleted.

packages/inquirerer-utils/src/index.ts

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,19 @@
1-
// Argv utilities
2-
export { extractFirst } from './argv';
3-
export type { ParsedArgs } from './argv';
1+
// Re-export core CLI utilities from inquirerer for backwards compatibility
2+
export {
3+
extractFirst,
4+
cliExitWithError,
5+
getPackageJson,
6+
getPackageVersion,
7+
getPackageName
8+
} from 'inquirerer';
9+
export type { ParsedArgs, CliExitOptions, PackageJson } from 'inquirerer';
410

5-
// CLI error handling
6-
export { cliExitWithError } from './cli-error';
7-
export type { CliExitOptions } from './cli-error';
11+
// Legacy aliases for backwards compatibility
12+
export { getPackageJson as getSelfPackageJson } from 'inquirerer';
13+
export { getPackageVersion as getSelfVersion } from 'inquirerer';
14+
export { getPackageName as getSelfName } from 'inquirerer';
15+
export type { PackageJson as PackageJsonInfo } from 'inquirerer';
816

9-
// Update checking
17+
// Update checking (requires appstash, not available in inquirerer)
1018
export { checkForUpdates, shouldSkipUpdateCheck } from './update-check';
1119
export type { UpdateCheckOptions, UpdateCheckResult } from './update-check';
12-
13-
// Package.json utilities
14-
export { getSelfPackageJson, getSelfVersion, getSelfName } from './package-json';
15-
export type { PackageJsonInfo } from './package-json';

packages/inquirerer-utils/src/package-json.ts

Lines changed: 0 additions & 29 deletions
This file was deleted.

packages/inquirerer/README.md

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,10 @@ npm install inquirerer
6262
- [Custom Resolvers](#custom-resolvers)
6363
- [Resolver Examples](#resolver-examples)
6464
- [CLI Helper](#cli-helper)
65+
- [CLI Utilities](#cli-utilities)
66+
- [Package Information](#package-information)
67+
- [Argument Parsing](#argument-parsing)
68+
- [Error Handling](#error-handling)
6569
- [UI Components](#ui-components)
6670
- [Spinner](#spinner)
6771
- [Progress Bar](#progress-bar)
@@ -1248,6 +1252,131 @@ const cli = new CLI(handler, options);
12481252
await cli.run();
12491253
```
12501254

1255+
## CLI Utilities
1256+
1257+
inquirerer provides a complete set of utilities for building CLI applications, so you can import everything from a single package.
1258+
1259+
### Package Information
1260+
1261+
Get information about your CLI's package.json for version display and other metadata:
1262+
1263+
```typescript
1264+
import { getPackageJson, getPackageVersion, getPackageName } from 'inquirerer';
1265+
1266+
// Get the full package.json object
1267+
const pkg = getPackageJson(__dirname);
1268+
console.log(`${pkg.name}@${pkg.version}`);
1269+
1270+
// Or use the convenience helpers
1271+
if (argv.version) {
1272+
console.log(getPackageVersion(__dirname));
1273+
process.exit(0);
1274+
}
1275+
1276+
const toolName = getPackageName(__dirname);
1277+
console.log(`Welcome to ${toolName}!`);
1278+
```
1279+
1280+
### Argument Parsing
1281+
1282+
Extract the first positional argument for command routing:
1283+
1284+
```typescript
1285+
import { extractFirst, ParsedArgs } from 'inquirerer';
1286+
import minimist from 'minimist';
1287+
1288+
const argv = minimist(process.argv.slice(2));
1289+
const { first, newArgv } = extractFirst(argv);
1290+
1291+
// Running: mycli generate --output ./dist
1292+
// first = 'generate'
1293+
// newArgv = { output: './dist', _: [] }
1294+
1295+
switch (first) {
1296+
case 'generate':
1297+
await handleGenerate(newArgv);
1298+
break;
1299+
case 'init':
1300+
await handleInit(newArgv);
1301+
break;
1302+
default:
1303+
console.log('Unknown command');
1304+
}
1305+
```
1306+
1307+
### Error Handling
1308+
1309+
Exit gracefully with error messages and optional cleanup:
1310+
1311+
```typescript
1312+
import { cliExitWithError, CliExitOptions } from 'inquirerer';
1313+
1314+
try {
1315+
await riskyOperation();
1316+
} catch (error) {
1317+
await cliExitWithError(error, {
1318+
context: { operation: 'build', target: 'production' },
1319+
beforeExit: async () => {
1320+
await cleanup();
1321+
},
1322+
logger: customLogger // optional, defaults to console
1323+
});
1324+
}
1325+
```
1326+
1327+
### Complete CLI Example
1328+
1329+
Here's a complete example using all the CLI utilities:
1330+
1331+
```typescript
1332+
import {
1333+
CLI,
1334+
CLIOptions,
1335+
Inquirerer,
1336+
extractFirst,
1337+
cliExitWithError,
1338+
getPackageVersion,
1339+
ParsedArgs
1340+
} from 'inquirerer';
1341+
1342+
const options: Partial<CLIOptions> = {
1343+
minimistOpts: {
1344+
alias: { v: 'version', h: 'help' },
1345+
boolean: ['help', 'version']
1346+
}
1347+
};
1348+
1349+
const handler = async (argv: Partial<ParsedArgs>, prompter: Inquirerer) => {
1350+
if (argv.version) {
1351+
console.log(getPackageVersion(__dirname));
1352+
process.exit(0);
1353+
}
1354+
1355+
const { first, newArgv } = extractFirst(argv);
1356+
1357+
try {
1358+
switch (first) {
1359+
case 'init':
1360+
await handleInit(newArgv, prompter);
1361+
break;
1362+
case 'build':
1363+
await handleBuild(newArgv, prompter);
1364+
break;
1365+
default:
1366+
console.log('Usage: mycli <command> [options]');
1367+
console.log('Commands: init, build');
1368+
}
1369+
} catch (error) {
1370+
await cliExitWithError(error, {
1371+
context: { command: first }
1372+
});
1373+
}
1374+
};
1375+
1376+
const cli = new CLI(handler, options);
1377+
await cli.run();
1378+
```
1379+
12511380
## UI Components
12521381

12531382
inquirerer includes a set of UI components for building rich terminal interfaces beyond simple prompts. These are useful for showing progress, loading states, and streaming output.

packages/inquirerer/src/cli/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,6 @@ export type { ParsedArgs } from './argv';
33

44
export { cliExitWithError } from './error';
55
export type { CliExitOptions } from './error';
6+
7+
export { getPackageJson, getPackageVersion, getPackageName } from './package';
8+
export type { PackageJson } from './package';
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import { findAndRequirePackageJson } from 'find-and-require-package-json';
2+
3+
export interface PackageJson {
4+
name: string;
5+
version: string;
6+
[key: string]: any;
7+
}
8+
9+
/**
10+
* Gets the package.json for the current package by searching up from the given directory.
11+
* This is useful for CLIs to get their own package information.
12+
*
13+
* @example
14+
* ```typescript
15+
* const pkg = getPackageJson(__dirname);
16+
* console.log(`${pkg.name}@${pkg.version}`);
17+
* ```
18+
*/
19+
export const getPackageJson = (dirname: string): PackageJson => {
20+
return findAndRequirePackageJson(dirname);
21+
};
22+
23+
/**
24+
* Gets the version from the package.json for the current package.
25+
* Shorthand for `getPackageJson(dirname).version`.
26+
*
27+
* @example
28+
* ```typescript
29+
* if (argv.version) {
30+
* console.log(getPackageVersion(__dirname));
31+
* process.exit(0);
32+
* }
33+
* ```
34+
*/
35+
export const getPackageVersion = (dirname: string): string => {
36+
return getPackageJson(dirname).version;
37+
};
38+
39+
/**
40+
* Gets the name from the package.json for the current package.
41+
* Shorthand for `getPackageJson(dirname).name`.
42+
*
43+
* @example
44+
* ```typescript
45+
* const toolName = getPackageName(__dirname);
46+
* console.log(`Welcome to ${toolName}!`);
47+
* ```
48+
*/
49+
export const getPackageName = (dirname: string): string => {
50+
return getPackageJson(dirname).name;
51+
};

packages/inquirerer/src/index.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,3 @@ export * from './ui';
66

77
// CLI utilities for building command-line applications
88
export * from './cli';
9-
10-
// Re-export package.json finder for convenience
11-
export { findAndRequirePackageJson } from 'find-and-require-package-json';

0 commit comments

Comments
 (0)