Skip to content

Commit 7440d1a

Browse files
committed
update docs
1 parent 2766f93 commit 7440d1a

3 files changed

Lines changed: 72 additions & 57 deletions

File tree

README.md

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ Subcommands are plain classes (no need to extend `Args`). Link them using
6666
`@subCommand`:
6767

6868
```typescript
69-
import { Args, cli, opt, subCommand } from "@sigma/parse";
69+
import { Args, cli, command, opt, subCommand } from "@sigma/parse";
7070

7171
@command
7272
class ServeCommand {
@@ -122,14 +122,14 @@ if (args.serve) {
122122

123123
**Explicitly Required** (must be provided on CLI):
124124

125-
```typescript
125+
```typescript ignore
126126
@opt({ type: "string", required: true })
127127
apiKey!: string;
128128
```
129129

130130
**Optional with Default** (inferred from value):
131131

132-
```typescript
132+
```typescript ignore
133133
port = 8080; // type inferred as number
134134
```
135135

@@ -138,7 +138,7 @@ port = 8080; // type inferred as number
138138
Use `short: true` to automatically use the first character of the property name
139139
as a short flag:
140140

141-
```typescript
141+
```typescript ignore
142142
verbose = false; // becomes -v, --verbose
143143
```
144144

@@ -147,20 +147,20 @@ verbose = false; // becomes -v, --verbose
147147
### Built-in Validators
148148

149149
```typescript
150-
import { Args, cli, opt, pattern, range } from "@sigma/parse";
150+
import { Args, cli, oneOf, opt, pattern, range, validate } from "@sigma/parse";
151151

152152
@cli({ name: "example" })
153153
class Example extends Args {
154154
@opt()
155-
@range(1, 100)
155+
@validate(range(1, 100))
156156
score = 50;
157157

158158
@opt()
159-
@oneOf(["dev", "prod"])
159+
@validate(oneOf(["dev", "prod"]))
160160
env = "dev";
161161

162162
@opt()
163-
@pattern(/^[a-z]+$/)
163+
@validate(pattern(/^[a-z]+$/))
164164
user = "admin";
165165
}
166166
```
@@ -169,7 +169,7 @@ class Example extends Args {
169169

170170
Use `raw: true` to build wrappers that forward arguments to other tools:
171171

172-
```typescript
172+
```typescript ignore
173173
@cli({ name: "proxy" })
174174
class Proxy extends Args {
175175
@arg({ description: "Command to run", required: true })

src/decorators.ts

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -69,25 +69,44 @@ export function addValidator(validator: Validator): (
6969
/**
7070
* Validate decorator for custom validation logic.
7171
*
72-
* This decorator creates a validator using a predicate function and custom error message.
72+
* This decorator can be used in two ways:
73+
* 1. With a built-in or custom validator function (e.g., `@validate(range(1, 10))`)
74+
* 2. With a predicate function and custom error message (e.g., `@validate(val => val > 0, "must be positive")`)
7375
*
74-
* @param predicate - Function that returns true if value is valid
75-
* @param message - Error message to show when validation fails
76+
* @param validatorOrPredicate - A validator function OR a predicate function
77+
* @param message - Error message (required only if using a predicate)
7678
* @returns A decorator function
7779
*/
80+
export function validate<T>(
81+
validator: Validator,
82+
): (
83+
_target: unknown,
84+
context: DecoratorContext,
85+
) => void;
7886
export function validate<T>(
7987
predicate: (value: T) => boolean,
8088
message: string,
8189
): (
8290
_target: unknown,
8391
context: DecoratorContext,
92+
) => void;
93+
export function validate<T>(
94+
validatorOrPredicate: Validator | ((value: T) => boolean),
95+
message?: string,
96+
): (
97+
_target: unknown,
98+
context: DecoratorContext,
8499
) => void {
85-
return addValidator((value: unknown) => {
86-
if (!predicate(value as T)) {
87-
return message;
100+
const validator = typeof message === "string"
101+
? (value: unknown) => {
102+
if (!(validatorOrPredicate as (value: T) => boolean)(value as T)) {
103+
return message;
104+
}
105+
return null;
88106
}
89-
return null;
90-
});
107+
: (validatorOrPredicate as Validator);
108+
109+
return addValidator(validator);
91110
}
92111

93112
/**
@@ -176,7 +195,7 @@ export function subCommand<T extends new () => unknown>(
176195
* @returns A decorator function
177196
*
178197
* @example
179-
* ```ts
198+
* ```ts ignore
180199
* class MyArgs extends Args {
181200
* @opt({ short: "p", description: "Port", required: true })
182201
* port!: number;
@@ -244,7 +263,7 @@ export function opt(
244263
* @returns A decorator function
245264
*
246265
* @example
247-
* ```ts
266+
* ```ts ignore
248267
* class MyArgs extends Args {
249268
* @arg({ description: "Input file", required: true })
250269
* input!: string;

src/validation.ts

Lines changed: 34 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -92,12 +92,12 @@ export function requiredValidator(): Validator {
9292
*
9393
* @example
9494
* ```ts
95-
* import { Args, cli, type, addValidator } from "@sigma/parse";
95+
* import { Args, cli, opt, validate, min } from "@sigma/parse";
9696
*
9797
* @cli({ name: "example" })
9898
* class Config extends Args {
99-
* @type("number")
100-
* @addValidator(min(0))
99+
* @opt({ type: "number" })
100+
* @validate(min(1024))
101101
* port = 3000;
102102
* }
103103
* ```
@@ -119,12 +119,12 @@ export function min(minValue: number): Validator {
119119
*
120120
* @example
121121
* ```ts
122-
* import { Args, cli, type, addValidator } from "@sigma/parse";
122+
* import { Args, cli, opt, validate, max } from "@sigma/parse";
123123
*
124124
* @cli({ name: "example" })
125125
* class Config extends Args {
126-
* @type("number")
127-
* @addValidator(max(65535))
126+
* @opt({ type: "number" })
127+
* @validate(max(65535))
128128
* port = 3000;
129129
* }
130130
* ```
@@ -147,14 +147,13 @@ export function max(maxValue: number): Validator {
147147
*
148148
* @example
149149
* ```ts
150-
* import { Args, cli, type, required, addValidator } from "@sigma/parse";
150+
* import { Args, cli, opt, validate, length } from "@sigma/parse";
151151
*
152152
* @cli({ name: "example" })
153153
* class Config extends Args {
154-
* @type("string")
155-
* @required()
156-
* @addValidator(length(3, 20))
157-
* username?: string;
154+
* @opt({ type: "string" })
155+
* @validate(length(3, 20))
156+
* username = "admin";
158157
* }
159158
* ```
160159
*/
@@ -181,14 +180,13 @@ export function length(minLength: number, maxLength?: number): Validator {
181180
*
182181
* @example
183182
* ```ts
184-
* import { Args, cli, type, required, addValidator } from "@sigma/parse";
183+
* import { Args, cli, opt, validate, pattern } from "@sigma/parse";
185184
*
186185
* @cli({ name: "example" })
187186
* class Config extends Args {
188-
* @type("string")
189-
* @required()
190-
* @addValidator(pattern(/^[a-zA-Z0-9]+$/, "must contain only letters and numbers"))
191-
* identifier?: string;
187+
* @opt({ type: "string" })
188+
* @validate(pattern(/^[a-z0-9]+$/))
189+
* slug = "my-post";
192190
* }
193191
* ```
194192
*/
@@ -209,11 +207,12 @@ export function pattern(pattern: RegExp, message?: string): Validator {
209207
*
210208
* @example
211209
* ```ts
212-
* import { Args, cli, addValidator } from "@sigma/parse";
210+
* import { Args, cli, opt, validate, oneOf } from "@sigma/parse";
213211
*
214212
* @cli({ name: "example" })
215213
* class Config extends Args {
216-
* @addValidator(oneOf(["development", "staging", "production"]))
214+
* @opt()
215+
* @validate(oneOf(["development", "staging", "production"]))
217216
* environment = "development";
218217
* }
219218
* ```
@@ -236,13 +235,13 @@ export function oneOf<T>(allowedValues: T[]): Validator {
236235
*
237236
* @example
238237
* ```ts
239-
* import { Args, cli, type, addValidator } from "@sigma/parse";
238+
* import { Args, cli, opt, validate, arrayLength } from "@sigma/parse";
240239
*
241240
* @cli({ name: "example" })
242241
* class Config extends Args {
243-
* @type("string[]")
244-
* @addValidator(arrayLength(1, 5))
245-
* tags: string[] = [];
242+
* @opt({ type: "string[]" })
243+
* @validate(arrayLength(1, 5))
244+
* tags: string[] = ["typescript"];
246245
* }
247246
* ```
248247
*/
@@ -269,14 +268,13 @@ export function arrayLength(minItems: number, maxItems?: number): Validator {
269268
*
270269
* @example
271270
* ```ts
272-
* import { Args, cli, type, required, addValidator } from "@sigma/parse";
271+
* import { Args, cli, opt, validate, range } from "@sigma/parse";
273272
*
274273
* @cli({ name: "example" })
275274
* class Config extends Args {
276-
* @type("number")
277-
* @required()
278-
* @addValidator(range(1, 100))
279-
* percentage?: number;
275+
* @opt({ type: "number" })
276+
* @validate(range(0, 100))
277+
* percentage = 50;
280278
* }
281279
* ```
282280
*/
@@ -298,14 +296,13 @@ export function range(minValue: number, maxValue: number): Validator {
298296
*
299297
* @example
300298
* ```ts
301-
* import { Args, cli, type, required, addValidator } from "@sigma/parse";
299+
* import { Args, cli, opt, validate, integer } from "@sigma/parse";
302300
*
303301
* @cli({ name: "example" })
304302
* class Config extends Args {
305-
* @type("number")
306-
* @required()
307-
* @addValidator(integer())
308-
* count?: number;
303+
* @opt({ type: "number" })
304+
* @validate(integer())
305+
* count = 1;
309306
* }
310307
* ```
311308
*/
@@ -326,15 +323,14 @@ export function integer(): Validator {
326323
* @returns A validator function
327324
*
328325
* @example
329-
* ```ts ignore
330-
* import { Args, cli, type, required, addValidator } from "@sigma/parse";
326+
* ```ts
327+
* import { Args, cli, opt, validate, custom } from "@sigma/parse";
331328
*
332329
* @cli({ name: "example" })
333330
* class Config extends Args {
334-
* @type("number")
335-
* @required()
336-
* @addValidator(custom((n: number) => n % 2 === 0, "must be even"))
337-
* evenNumber?: number;
331+
* @opt({ type: "number" })
332+
* @validate(custom((n: number) => n % 2 === 0, "must be even"))
333+
* evenNumber = 2;
338334
* }
339335
* ```
340336
*/

0 commit comments

Comments
 (0)