regor 1.4.8 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -3
- package/dist/regor.d.ts +10 -2
- package/dist/regor.es2015.cjs.js +95 -10
- package/dist/regor.es2015.cjs.prod.js +3 -3
- package/dist/regor.es2015.esm.js +95 -10
- package/dist/regor.es2015.esm.prod.js +3 -3
- package/dist/regor.es2015.iife.js +95 -10
- package/dist/regor.es2015.iife.prod.js +3 -3
- package/dist/regor.es2019.cjs.js +95 -10
- package/dist/regor.es2019.cjs.prod.js +3 -3
- package/dist/regor.es2019.esm.js +95 -10
- package/dist/regor.es2019.esm.prod.js +3 -3
- package/dist/regor.es2019.iife.js +95 -10
- package/dist/regor.es2019.iife.prod.js +3 -3
- package/dist/regor.es2022.cjs.js +95 -10
- package/dist/regor.es2022.cjs.prod.js +3 -3
- package/dist/regor.es2022.esm.js +95 -10
- package/dist/regor.es2022.esm.prod.js +3 -3
- package/dist/regor.es2022.iife.js +95 -10
- package/dist/regor.es2022.iife.prod.js +3 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -152,11 +152,13 @@ pval.isBoolean
|
|
|
152
152
|
pval.isClass(MyClass)
|
|
153
153
|
pval.optional(pval.isString)
|
|
154
154
|
pval.nullable(pval.isNumber)
|
|
155
|
+
pval.or(pval.isString, pval.isNumber)
|
|
155
156
|
pval.oneOf(['create', 'edit'] as const)
|
|
156
157
|
pval.arrayOf(pval.isString)
|
|
157
158
|
pval.shape({ title: pval.isString, count: pval.isNumber })
|
|
158
159
|
pval.refOf(pval.isString)
|
|
159
|
-
pval.
|
|
160
|
+
pval.describe('value')
|
|
161
|
+
pval.fail('title', 'expected non-empty string, got string ("")')
|
|
160
162
|
```
|
|
161
163
|
|
|
162
164
|
### Dynamic bindings and refs
|
|
@@ -204,7 +206,7 @@ import { pval, type PropValidator } from 'regor'
|
|
|
204
206
|
|
|
205
207
|
const isNonEmptyString: PropValidator<string> = (value, name) => {
|
|
206
208
|
if (typeof value !== 'string' || value.trim() === '') {
|
|
207
|
-
pval.fail(name,
|
|
209
|
+
pval.fail(name, `expected non-empty string, ${pval.describe(value)}`)
|
|
208
210
|
}
|
|
209
211
|
}
|
|
210
212
|
|
|
@@ -219,7 +221,7 @@ Custom validators can also use the third `head` argument:
|
|
|
219
221
|
const startsWithPrefix: PropValidator<string> = (value, name, head) => {
|
|
220
222
|
const ctx = head.requireContext(AppServices)
|
|
221
223
|
if (typeof value !== 'string' || !value.startsWith(ctx.prefix)) {
|
|
222
|
-
pval.fail(name,
|
|
224
|
+
pval.fail(name, `expected prefixed value, ${pval.describe(value)}`)
|
|
223
225
|
}
|
|
224
226
|
}
|
|
225
227
|
```
|
package/dist/regor.d.ts
CHANGED
|
@@ -13,6 +13,12 @@
|
|
|
13
13
|
*/
|
|
14
14
|
export type PropValidator<TValue = unknown> = (value: unknown, name: string, head: ComponentHead<any>) => asserts value is TValue;
|
|
15
15
|
export type ValidationSchemaLike = Record<string, PropValidator<any>>;
|
|
16
|
+
export type ValidatorTuple = readonly [
|
|
17
|
+
PropValidator<any>,
|
|
18
|
+
PropValidator<any>,
|
|
19
|
+
...PropValidator<any>[]
|
|
20
|
+
];
|
|
21
|
+
export type InferValidatorValue<TValidator> = TValidator extends PropValidator<infer TValue> ? TValue : never;
|
|
16
22
|
/**
|
|
17
23
|
* Validation schema shape suggested by `ComponentHead<T>.props`.
|
|
18
24
|
*
|
|
@@ -34,8 +40,8 @@ export type InferPropValidationSchema<TSchema extends Record<string, unknown>> =
|
|
|
34
40
|
* Built-in prop-validator namespace used with `head.validateProps(...)`.
|
|
35
41
|
*
|
|
36
42
|
* This namespace includes both ready-made validators and composition helpers.
|
|
37
|
-
* Custom validators can also use `pval.fail(...)`
|
|
38
|
-
*
|
|
43
|
+
* Custom validators can also use `pval.fail(...)` and `pval.describe(...)`
|
|
44
|
+
* to produce messages in the same style as Regor's built-in validators.
|
|
39
45
|
*
|
|
40
46
|
* Example:
|
|
41
47
|
* ```ts
|
|
@@ -50,12 +56,14 @@ export type InferPropValidationSchema<TSchema extends Record<string, unknown>> =
|
|
|
50
56
|
*/
|
|
51
57
|
export declare const pval: {
|
|
52
58
|
readonly fail: (name: string, message: string) => never;
|
|
59
|
+
readonly describe: (value: unknown) => string;
|
|
53
60
|
readonly isString: PropValidator<string>;
|
|
54
61
|
readonly isNumber: PropValidator<number>;
|
|
55
62
|
readonly isBoolean: PropValidator<boolean>;
|
|
56
63
|
readonly isClass: <TValue extends object>(ctor: abstract new (...args: any[]) => TValue) => PropValidator<TValue>;
|
|
57
64
|
readonly optional: <TValue>(validator: PropValidator<TValue>) => PropValidator<TValue | undefined>;
|
|
58
65
|
readonly nullable: <TValue>(validator: PropValidator<TValue>) => PropValidator<TValue | null>;
|
|
66
|
+
readonly or: <TValidators extends ValidatorTuple>(...validators: TValidators) => PropValidator<InferValidatorValue<TValidators[number]>>;
|
|
59
67
|
readonly oneOf: <const TValue extends readonly unknown[]>(values: TValue) => PropValidator<TValue[number]>;
|
|
60
68
|
readonly arrayOf: <TValue>(validator: PropValidator<TValue>) => PropValidator<TValue[]>;
|
|
61
69
|
readonly shape: <TSchema extends ValidationSchemaLike>(schema: TSchema) => PropValidator<InferPropValidationSchema<TSchema>>;
|
package/dist/regor.es2015.cjs.js
CHANGED
|
@@ -301,6 +301,9 @@ var describeValue = (value) => {
|
|
|
301
301
|
var _a;
|
|
302
302
|
if (value === null) return "null";
|
|
303
303
|
if (value === void 0) return "undefined";
|
|
304
|
+
if (isRef(value)) {
|
|
305
|
+
return `ref<${describeValue(value())}>`;
|
|
306
|
+
}
|
|
304
307
|
if (typeof value === "string") return "string";
|
|
305
308
|
if (typeof value === "number") return "number";
|
|
306
309
|
if (typeof value === "boolean") return "boolean";
|
|
@@ -315,6 +318,64 @@ var describeValue = (value) => {
|
|
|
315
318
|
const ctorName = (_a = value == null ? void 0 : value.constructor) == null ? void 0 : _a.name;
|
|
316
319
|
return ctorName && ctorName !== "Object" ? ctorName : "object";
|
|
317
320
|
};
|
|
321
|
+
var trimPreview = (value) => {
|
|
322
|
+
return value.length > 60 ? `${value.slice(0, 57)}...` : value;
|
|
323
|
+
};
|
|
324
|
+
var formatPreview = (value, depth = 0) => {
|
|
325
|
+
const maxPreviewDepth = 1;
|
|
326
|
+
const maxArrayItems = 5;
|
|
327
|
+
const maxObjectEntries = 5;
|
|
328
|
+
if (depth > maxPreviewDepth) return "unknown";
|
|
329
|
+
if (isRef(value)) {
|
|
330
|
+
const refValue = value();
|
|
331
|
+
return `ref(${formatPreview(refValue, depth + 1)})`;
|
|
332
|
+
}
|
|
333
|
+
if (typeof value === "string") return trimPreview(JSON.stringify(value));
|
|
334
|
+
if (typeof value === "number" || typeof value === "boolean" || typeof value === "bigint") {
|
|
335
|
+
return String(value);
|
|
336
|
+
}
|
|
337
|
+
if (typeof value === "symbol") return String(value);
|
|
338
|
+
if (value === null) return "null";
|
|
339
|
+
if (value === void 0) return "undefined";
|
|
340
|
+
if (value instanceof Date) return value.toISOString();
|
|
341
|
+
if (value instanceof RegExp) return String(value);
|
|
342
|
+
if (isArray(value)) {
|
|
343
|
+
const items = value.slice(0, maxArrayItems).map((x) => formatPreview(x, depth + 1)).join(", ");
|
|
344
|
+
return value.length > maxArrayItems ? `[${items}, ...]` : `[${items}]`;
|
|
345
|
+
}
|
|
346
|
+
if (isObject(value)) {
|
|
347
|
+
const entries = Object.entries(value).slice(0, maxObjectEntries);
|
|
348
|
+
if (entries.length === 0) return "{}";
|
|
349
|
+
const text = entries.map(([key, entry]) => {
|
|
350
|
+
const preview = formatPreview(entry, depth + 1);
|
|
351
|
+
return `${key}: ${preview}`;
|
|
352
|
+
}).join(", ");
|
|
353
|
+
return Object.keys(value).length > maxObjectEntries ? `{ ${text}, ... }` : `{ ${text} }`;
|
|
354
|
+
}
|
|
355
|
+
return "unknown";
|
|
356
|
+
};
|
|
357
|
+
var describe = (value) => {
|
|
358
|
+
const type = describeValue(value);
|
|
359
|
+
const preview = formatPreview(value);
|
|
360
|
+
return `got ${type} (${preview})`;
|
|
361
|
+
};
|
|
362
|
+
var getErrorDetail = (error) => {
|
|
363
|
+
if (error instanceof PropValidationError) return error.detail;
|
|
364
|
+
if (error instanceof Error) return error.message;
|
|
365
|
+
return String(error);
|
|
366
|
+
};
|
|
367
|
+
var formatOrDetail = (errors2, value) => {
|
|
368
|
+
const received = `, ${describe(value)}.`;
|
|
369
|
+
const reasons = [];
|
|
370
|
+
for (const error of errors2) {
|
|
371
|
+
const detail = getErrorDetail(error);
|
|
372
|
+
const reason = detail.endsWith(received) ? detail.slice(0, -received.length) : detail;
|
|
373
|
+
if (!reasons.includes(reason)) reasons.push(reason);
|
|
374
|
+
}
|
|
375
|
+
if (reasons.length === 0) return describe(value);
|
|
376
|
+
if (reasons.length === 1) return `${reasons[0]}, ${describe(value)}`;
|
|
377
|
+
return `${reasons.join(" or ")}, ${describe(value)}`;
|
|
378
|
+
};
|
|
318
379
|
var formatLiteral = (value) => {
|
|
319
380
|
if (typeof value === "string") return `"${value}"`;
|
|
320
381
|
if (typeof value === "number" || typeof value === "boolean") {
|
|
@@ -325,18 +386,24 @@ var formatLiteral = (value) => {
|
|
|
325
386
|
return describeValue(value);
|
|
326
387
|
};
|
|
327
388
|
var isString2 = (value, name) => {
|
|
328
|
-
if (typeof value !== "string")
|
|
389
|
+
if (typeof value !== "string")
|
|
390
|
+
fail(name, `expected string, ${describe(value)}`);
|
|
329
391
|
};
|
|
330
392
|
var isNumber = (value, name) => {
|
|
331
|
-
if (typeof value !== "number")
|
|
393
|
+
if (typeof value !== "number")
|
|
394
|
+
fail(name, `expected number, ${describe(value)}`);
|
|
332
395
|
};
|
|
333
396
|
var isBoolean = (value, name) => {
|
|
334
|
-
if (typeof value !== "boolean")
|
|
397
|
+
if (typeof value !== "boolean")
|
|
398
|
+
fail(name, `expected boolean, ${describe(value)}`);
|
|
335
399
|
};
|
|
336
400
|
var isClass = (ctor) => {
|
|
337
401
|
return (value, name) => {
|
|
338
402
|
if (!(value instanceof ctor)) {
|
|
339
|
-
fail(
|
|
403
|
+
fail(
|
|
404
|
+
name,
|
|
405
|
+
`expected instance of ${ctor.name || "provided class"}, ${describe(value)}`
|
|
406
|
+
);
|
|
340
407
|
}
|
|
341
408
|
};
|
|
342
409
|
};
|
|
@@ -352,18 +419,32 @@ var nullable = (validator) => {
|
|
|
352
419
|
validator(value, name, head);
|
|
353
420
|
};
|
|
354
421
|
};
|
|
422
|
+
var or = (...validators) => {
|
|
423
|
+
return (value, name, head) => {
|
|
424
|
+
const errors2 = [];
|
|
425
|
+
for (const validator of validators) {
|
|
426
|
+
try {
|
|
427
|
+
validator(value, name, head);
|
|
428
|
+
return;
|
|
429
|
+
} catch (error) {
|
|
430
|
+
errors2.push(error);
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
fail(name, formatOrDetail(errors2, value));
|
|
434
|
+
};
|
|
435
|
+
};
|
|
355
436
|
var oneOf = (values) => {
|
|
356
437
|
return (value, name) => {
|
|
357
438
|
if (values.includes(value)) return;
|
|
358
439
|
fail(
|
|
359
440
|
name,
|
|
360
|
-
`expected one of ${values.map((x) => formatLiteral(x)).join(", ")}`
|
|
441
|
+
`expected one of ${values.map((x) => formatLiteral(x)).join(", ")}, ${describe(value)}`
|
|
361
442
|
);
|
|
362
443
|
};
|
|
363
444
|
};
|
|
364
445
|
var arrayOf = (validator) => {
|
|
365
446
|
return (value, name, head) => {
|
|
366
|
-
if (!isArray(value)) fail(name,
|
|
447
|
+
if (!isArray(value)) fail(name, `expected array, ${describe(value)}`);
|
|
367
448
|
const items = value;
|
|
368
449
|
for (let i = 0; i < items.length; ++i) {
|
|
369
450
|
validator(items[i], `${name}[${i}]`, head);
|
|
@@ -372,7 +453,7 @@ var arrayOf = (validator) => {
|
|
|
372
453
|
};
|
|
373
454
|
var shape = (schema) => {
|
|
374
455
|
return (value, name, head) => {
|
|
375
|
-
if (!isObject(value)) fail(name,
|
|
456
|
+
if (!isObject(value)) fail(name, `expected object, ${describe(value)}`);
|
|
376
457
|
const record = value;
|
|
377
458
|
for (const key in schema) {
|
|
378
459
|
const validator = schema[key];
|
|
@@ -382,19 +463,23 @@ var shape = (schema) => {
|
|
|
382
463
|
};
|
|
383
464
|
var refOf = (validator) => {
|
|
384
465
|
return (value, name, head) => {
|
|
385
|
-
if (
|
|
386
|
-
|
|
387
|
-
|
|
466
|
+
if (isRef(value)) {
|
|
467
|
+
validator(value(), `${name}.value`, head);
|
|
468
|
+
return;
|
|
469
|
+
}
|
|
470
|
+
fail(name, `expected ref, ${describe(value)}`);
|
|
388
471
|
};
|
|
389
472
|
};
|
|
390
473
|
var pval = {
|
|
391
474
|
fail,
|
|
475
|
+
describe,
|
|
392
476
|
isString: isString2,
|
|
393
477
|
isNumber,
|
|
394
478
|
isBoolean,
|
|
395
479
|
isClass,
|
|
396
480
|
optional,
|
|
397
481
|
nullable,
|
|
482
|
+
or,
|
|
398
483
|
oneOf,
|
|
399
484
|
arrayOf,
|
|
400
485
|
shape,
|