Skip to content

Commit d361a56

Browse files
committed
docs(README): update README with transform info
1 parent 6d0d0fc commit d361a56

2 files changed

Lines changed: 96 additions & 14 deletions

File tree

README.md

Lines changed: 92 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,9 @@ const sharedPos = bargs.positionals(
6767
);
6868
```
6969

70+
> [!TIP]
71+
> Helper functions are provided for convenience and composability, but you can also just use raw object literals. See the ["tasks" example](./examples/tasks.ts) to see how.
72+
7073
### Zero (0) Dependencies
7174

7275
Only Node.js v22+.
@@ -185,21 +188,99 @@ bargs({
185188
});
186189
```
187190

191+
## Transforms
192+
193+
Transforms let you modify parsed values and positionals before they reach your handler. This is useful for:
194+
195+
- Loading and merging configuration files
196+
- Adding computed/derived values
197+
- Validating or normalizing inputs
198+
- Async operations like file system checks
199+
200+
```typescript
201+
const result = await bargsAsync({
202+
name: 'my-cli',
203+
options: {
204+
config: bargsAsync.string({ aliases: ['c'] }),
205+
verbose: bargsAsync.boolean({ default: false }),
206+
},
207+
positionals: [bargsAsync.variadic('string', { name: 'files' })],
208+
transforms: {
209+
// Transform option values
210+
values: (values) => {
211+
// Load config file if specified
212+
const fileConfig = values.config
213+
? JSON.parse(readFileSync(values.config, 'utf8'))
214+
: {};
215+
216+
return {
217+
...fileConfig,
218+
...values,
219+
// Add computed values
220+
timestamp: new Date().toISOString(),
221+
};
222+
},
223+
// Transform positionals
224+
positionals: (positionals) => {
225+
const [files] = positionals;
226+
// Filter to only existing files
227+
return [files.filter((f) => existsSync(f))];
228+
},
229+
},
230+
handler: ({ values, positionals }) => {
231+
// values.timestamp is available here
232+
// positionals contains only valid files
233+
},
234+
});
235+
```
236+
237+
### Transform Properties
238+
239+
Transforms are akin to yargs' "middleware". They execute after parsing but before the handler (if present). Transforms should also be used in place of yargs' "coerce" option.
240+
241+
| Property | Type | Description |
242+
| ------------- | ----------------------------------------- | --------------------------------- |
243+
| `values` | `(values) => TransformedValues` | Transform parsed option values |
244+
| `positionals` | `(positionals) => TransformedPositionals` | Transform parsed positional tuple |
245+
246+
Both transforms can be sync or async. The return type of each transform becomes the type available in your handler.
247+
248+
### Type Inference
249+
250+
Transforms are fully type-safe. TypeScript infers the transformed types:
251+
252+
```typescript
253+
bargs({
254+
name: 'example',
255+
options: { count: bargs.number() },
256+
transforms: {
257+
values: (values) => ({
258+
...values,
259+
doubled: (values.count ?? 0) * 2, // Add computed property
260+
}),
261+
},
262+
handler: ({ values }) => {
263+
console.log(values.doubled); // number - fully typed!
264+
},
265+
});
266+
```
267+
188268
## Configuration
189269

190270
### Config Properties
191271

192-
| Property | Type | Description |
193-
| ------------- | --------------------- | ------------------------------------------------- |
194-
| `name` | `string` | CLI name (required) |
195-
| `description` | `string` | Description shown in help |
196-
| `version` | `string` | Enables `--version` flag |
197-
| `options` | `OptionsSchema` | Named options (`--flag`) |
198-
| `positionals` | `PositionalsSchema` | Positional arguments |
199-
| `commands` | `Record<string, ...>` | Subcommands |
200-
| `handler` | `Handler` | Handler function(s) for simple CLIs |
201-
| `epilog` | `string \| false` | Footer text in help (see [Epilog](#epilog)) |
202-
| `args` | `string[]` | Custom args (defaults to `process.argv.slice(2)`) |
272+
| Property | Type | Description |
273+
| ------------- | --------------------- | ------------------------------------------------------------ |
274+
| `name` | `string` | CLI name (required) |
275+
| `description` | `string` | Description shown in help |
276+
| `version` | `string` | Enables `--version` flag |
277+
| `options` | `OptionsSchema` | Named options (`--flag`) |
278+
| `positionals` | `PositionalsSchema` | Positional arguments |
279+
| `commands` | `Record<string, ...>` | Subcommands |
280+
| `transforms` | `TransformsConfig` | Transform values/positionals (see [Transforms](#transforms)) |
281+
| `handler` | `Handler` | Handler function for simple CLIs |
282+
| `epilog` | `string \| false` | Footer text in help (see [Epilog](#epilog)) |
283+
| `args` | `string[]` | Custom args (defaults to `process.argv.slice(2)`) |
203284

204285
```typescript
205286
bargs({

examples/tasks.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
* examples/tasks.ts list npx tsx examples/tasks.ts done 1 npx tsx
2020
* examples/tasks.ts --help npx tsx examples/tasks.ts add --help
2121
*/
22-
import { bargs, bargsAsync } from '../src/index.js';
22+
import { bargsAsync } from '../src/index.js';
2323

2424
// In-memory task storage (in a real app, this would be a file or database)
2525
interface Task {
@@ -71,11 +71,12 @@ await bargsAsync({
7171
},
7272
// Raw array works with const type parameter inference
7373
positionals: [
74-
bargs.stringPos({
74+
{
7575
description: 'Task description',
7676
name: 'text',
7777
required: true,
78-
}),
78+
type: 'string',
79+
},
7980
],
8081
handler: async ({ positionals, values }) => {
8182
const [text] = positionals;

0 commit comments

Comments
 (0)