@modularizer/plat-client 0.4.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/dist/args/coerce.d.ts +54 -0
- package/dist/args/coerce.d.ts.map +1 -0
- package/dist/args/coerce.js +236 -0
- package/dist/args/coerce.js.map +1 -0
- package/dist/args/index.d.ts +2 -0
- package/dist/args/index.d.ts.map +1 -0
- package/dist/args/index.js +2 -0
- package/dist/args/index.js.map +1 -0
- package/dist/args/scalars.d.ts +87 -0
- package/dist/args/scalars.d.ts.map +1 -0
- package/dist/args/scalars.js +22 -0
- package/dist/args/scalars.js.map +1 -0
- package/dist/args/validate.d.ts +23 -0
- package/dist/args/validate.d.ts.map +1 -0
- package/dist/args/validate.js +185 -0
- package/dist/args/validate.js.map +1 -0
- package/dist/args/z2.d.ts +27 -0
- package/dist/args/z2.d.ts.map +1 -0
- package/dist/args/z2.js +24 -0
- package/dist/args/z2.js.map +1 -0
- package/dist/client/css-transport-plugin.d.ts +19 -0
- package/dist/client/css-transport-plugin.d.ts.map +1 -0
- package/dist/client/css-transport-plugin.js +78 -0
- package/dist/client/css-transport-plugin.js.map +1 -0
- package/dist/client/file-transport-plugin.d.ts +28 -0
- package/dist/client/file-transport-plugin.d.ts.map +1 -0
- package/dist/client/file-transport-plugin.js +80 -0
- package/dist/client/file-transport-plugin.js.map +1 -0
- package/dist/client/http-transport-plugin.d.ts +27 -0
- package/dist/client/http-transport-plugin.d.ts.map +1 -0
- package/dist/client/http-transport-plugin.js +48 -0
- package/dist/client/http-transport-plugin.js.map +1 -0
- package/dist/client/index.d.ts +7 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +7 -0
- package/dist/client/index.js.map +1 -0
- package/dist/client/openapi-client.d.ts +334 -0
- package/dist/client/openapi-client.d.ts.map +1 -0
- package/dist/client/openapi-client.js +910 -0
- package/dist/client/openapi-client.js.map +1 -0
- package/dist/client/proxy.d.ts +5 -0
- package/dist/client/proxy.d.ts.map +1 -0
- package/dist/client/proxy.js +353 -0
- package/dist/client/proxy.js.map +1 -0
- package/dist/client/request-builder.d.ts +5 -0
- package/dist/client/request-builder.d.ts.map +1 -0
- package/dist/client/request-builder.js +88 -0
- package/dist/client/request-builder.js.map +1 -0
- package/dist/client/rpc-transport-plugin.d.ts +17 -0
- package/dist/client/rpc-transport-plugin.d.ts.map +1 -0
- package/dist/client/rpc-transport-plugin.js +69 -0
- package/dist/client/rpc-transport-plugin.js.map +1 -0
- package/dist/client/tools.d.ts +69 -0
- package/dist/client/tools.d.ts.map +1 -0
- package/dist/client/tools.js +122 -0
- package/dist/client/tools.js.map +1 -0
- package/dist/client/transport-plugin.d.ts +62 -0
- package/dist/client/transport-plugin.d.ts.map +1 -0
- package/dist/client/transport-plugin.js +40 -0
- package/dist/client/transport-plugin.js.map +1 -0
- package/dist/client-entry.d.ts +25 -0
- package/dist/client-entry.d.ts.map +1 -0
- package/dist/client-entry.js +25 -0
- package/dist/client-entry.js.map +1 -0
- package/dist/client-server-entry.d.ts +13 -0
- package/dist/client-server-entry.d.ts.map +1 -0
- package/dist/client-server-entry.js +13 -0
- package/dist/client-server-entry.js.map +1 -0
- package/dist/client-side-python/runtime.d.ts +102 -0
- package/dist/client-side-python/runtime.d.ts.map +1 -0
- package/dist/client-side-python/runtime.js +595 -0
- package/dist/client-side-python/runtime.js.map +1 -0
- package/dist/client-side-server/bootstrap.d.ts +3 -0
- package/dist/client-side-server/bootstrap.d.ts.map +1 -0
- package/dist/client-side-server/bootstrap.js +20 -0
- package/dist/client-side-server/bootstrap.js.map +1 -0
- package/dist/client-side-server/channel.d.ts +17 -0
- package/dist/client-side-server/channel.d.ts.map +1 -0
- package/dist/client-side-server/channel.js +38 -0
- package/dist/client-side-server/channel.js.map +1 -0
- package/dist/client-side-server/identity.d.ts +116 -0
- package/dist/client-side-server/identity.d.ts.map +1 -0
- package/dist/client-side-server/identity.js +358 -0
- package/dist/client-side-server/identity.js.map +1 -0
- package/dist/client-side-server/mqtt-webrtc.d.ts +77 -0
- package/dist/client-side-server/mqtt-webrtc.d.ts.map +1 -0
- package/dist/client-side-server/mqtt-webrtc.js +575 -0
- package/dist/client-side-server/mqtt-webrtc.js.map +1 -0
- package/dist/client-side-server/protocol.d.ts +49 -0
- package/dist/client-side-server/protocol.d.ts.map +1 -0
- package/dist/client-side-server/protocol.js +13 -0
- package/dist/client-side-server/protocol.js.map +1 -0
- package/dist/client-side-server/runtime.d.ts +57 -0
- package/dist/client-side-server/runtime.d.ts.map +1 -0
- package/dist/client-side-server/runtime.js +188 -0
- package/dist/client-side-server/runtime.js.map +1 -0
- package/dist/client-side-server/server.d.ts +75 -0
- package/dist/client-side-server/server.d.ts.map +1 -0
- package/dist/client-side-server/server.js +380 -0
- package/dist/client-side-server/server.js.map +1 -0
- package/dist/client-side-server/signaling.d.ts +10 -0
- package/dist/client-side-server/signaling.d.ts.map +1 -0
- package/dist/client-side-server/signaling.js +19 -0
- package/dist/client-side-server/signaling.js.map +1 -0
- package/dist/client-side-server/source-analysis.d.ts +29 -0
- package/dist/client-side-server/source-analysis.d.ts.map +1 -0
- package/dist/client-side-server/source-analysis.js +395 -0
- package/dist/client-side-server/source-analysis.js.map +1 -0
- package/dist/generated/python-browser-sources.d.ts +2 -0
- package/dist/generated/python-browser-sources.d.ts.map +1 -0
- package/dist/generated/python-browser-sources.js +13 -0
- package/dist/generated/python-browser-sources.js.map +1 -0
- package/dist/logging.d.ts +9 -0
- package/dist/logging.d.ts.map +1 -0
- package/dist/logging.js +64 -0
- package/dist/logging.js.map +1 -0
- package/dist/python-browser-entry.d.ts +2 -0
- package/dist/python-browser-entry.d.ts.map +1 -0
- package/dist/python-browser-entry.js +2 -0
- package/dist/python-browser-entry.js.map +1 -0
- package/dist/rpc.d.ts +39 -0
- package/dist/rpc.d.ts.map +1 -0
- package/dist/rpc.js +2 -0
- package/dist/rpc.js.map +1 -0
- package/dist/server/authority-server.d.ts +27 -0
- package/dist/server/authority-server.d.ts.map +1 -0
- package/dist/server/authority-server.js +97 -0
- package/dist/server/authority-server.js.map +1 -0
- package/dist/server/cache/index.d.ts +2 -0
- package/dist/server/cache/index.d.ts.map +1 -0
- package/dist/server/cache/index.js +2 -0
- package/dist/server/cache/index.js.map +1 -0
- package/dist/server/cache/utils.d.ts +30 -0
- package/dist/server/cache/utils.d.ts.map +1 -0
- package/dist/server/cache/utils.js +116 -0
- package/dist/server/cache/utils.js.map +1 -0
- package/dist/server/core.d.ts +43 -0
- package/dist/server/core.d.ts.map +1 -0
- package/dist/server/core.js +215 -0
- package/dist/server/core.js.map +1 -0
- package/dist/server/operation-registry.d.ts +9 -0
- package/dist/server/operation-registry.d.ts.map +1 -0
- package/dist/server/operation-registry.js +16 -0
- package/dist/server/operation-registry.js.map +1 -0
- package/dist/server/param-aliases.d.ts +40 -0
- package/dist/server/param-aliases.d.ts.map +1 -0
- package/dist/server/param-aliases.js +112 -0
- package/dist/server/param-aliases.js.map +1 -0
- package/dist/server/rate-limit/index.d.ts +2 -0
- package/dist/server/rate-limit/index.d.ts.map +1 -0
- package/dist/server/rate-limit/index.js +2 -0
- package/dist/server/rate-limit/index.js.map +1 -0
- package/dist/server/rate-limit/utils.d.ts +27 -0
- package/dist/server/rate-limit/utils.d.ts.map +1 -0
- package/dist/server/rate-limit/utils.js +126 -0
- package/dist/server/rate-limit/utils.js.map +1 -0
- package/dist/server/routing.d.ts +39 -0
- package/dist/server/routing.d.ts.map +1 -0
- package/dist/server/routing.js +70 -0
- package/dist/server/routing.js.map +1 -0
- package/dist/server/token-limit/index.d.ts +2 -0
- package/dist/server/token-limit/index.d.ts.map +1 -0
- package/dist/server/token-limit/index.js +2 -0
- package/dist/server/token-limit/index.js.map +1 -0
- package/dist/server/token-limit/utils.d.ts +44 -0
- package/dist/server/token-limit/utils.d.ts.map +1 -0
- package/dist/server/token-limit/utils.js +260 -0
- package/dist/server/token-limit/utils.js.map +1 -0
- package/dist/server/tools.d.ts +33 -0
- package/dist/server/tools.d.ts.map +1 -0
- package/dist/server/tools.js +160 -0
- package/dist/server/tools.js.map +1 -0
- package/dist/server/transports.d.ts +25 -0
- package/dist/server/transports.d.ts.map +1 -0
- package/dist/server/transports.js +2 -0
- package/dist/server/transports.js.map +1 -0
- package/dist/shared/tools.d.ts +24 -0
- package/dist/shared/tools.d.ts.map +1 -0
- package/dist/shared/tools.js +86 -0
- package/dist/shared/tools.js.map +1 -0
- package/dist/spec/decorators.d.ts +41 -0
- package/dist/spec/decorators.d.ts.map +1 -0
- package/dist/spec/decorators.js +93 -0
- package/dist/spec/decorators.js.map +1 -0
- package/dist/spec/index.d.ts +3 -0
- package/dist/spec/index.d.ts.map +1 -0
- package/dist/spec/index.js +3 -0
- package/dist/spec/index.js.map +1 -0
- package/dist/spec/metadata.d.ts +5 -0
- package/dist/spec/metadata.d.ts.map +1 -0
- package/dist/spec/metadata.js +37 -0
- package/dist/spec/metadata.js.map +1 -0
- package/dist/types/client-route.d.ts +7 -0
- package/dist/types/client-route.d.ts.map +1 -0
- package/dist/types/client-route.js +2 -0
- package/dist/types/client-route.js.map +1 -0
- package/dist/types/client.d.ts +81 -0
- package/dist/types/client.d.ts.map +1 -0
- package/dist/types/client.js +14 -0
- package/dist/types/client.js.map +1 -0
- package/dist/types/endpoints.d.ts +76 -0
- package/dist/types/endpoints.d.ts.map +1 -0
- package/dist/types/endpoints.js +2 -0
- package/dist/types/endpoints.js.map +1 -0
- package/dist/types/errors.d.ts +86 -0
- package/dist/types/errors.d.ts.map +1 -0
- package/dist/types/errors.js +153 -0
- package/dist/types/errors.js.map +1 -0
- package/dist/types/http.d.ts +80 -0
- package/dist/types/http.d.ts.map +1 -0
- package/dist/types/http.js +61 -0
- package/dist/types/http.js.map +1 -0
- package/dist/types/index.d.ts +10 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +10 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/openapi.d.ts +220 -0
- package/dist/types/openapi.d.ts.map +1 -0
- package/dist/types/openapi.js +11 -0
- package/dist/types/openapi.js.map +1 -0
- package/dist/types/opts.d.ts +46 -0
- package/dist/types/opts.d.ts.map +1 -0
- package/dist/types/opts.js +2 -0
- package/dist/types/opts.js.map +1 -0
- package/dist/types/plugins.d.ts +93 -0
- package/dist/types/plugins.d.ts.map +1 -0
- package/dist/types/plugins.js +5 -0
- package/dist/types/plugins.js.map +1 -0
- package/dist/types/tools.d.ts +52 -0
- package/dist/types/tools.d.ts.map +1 -0
- package/dist/types/tools.js +2 -0
- package/dist/types/tools.js.map +1 -0
- package/package.json +51 -0
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type coercion for incoming data (query strings, form data, etc.)
|
|
3
|
+
*
|
|
4
|
+
* Handles: string→number, string→boolean, string→Date, trim strings.
|
|
5
|
+
* Called before validation so that "42" passes an integer schema.
|
|
6
|
+
*/
|
|
7
|
+
export declare function parseRelativeDate(input: string, now?: Date): Date | null;
|
|
8
|
+
export declare function parseDateish(value: unknown, now?: Date, dateOnly?: boolean): Date | null;
|
|
9
|
+
export interface JsonSchema {
|
|
10
|
+
type?: string;
|
|
11
|
+
format?: string;
|
|
12
|
+
coerce?: string | boolean;
|
|
13
|
+
properties?: Record<string, JsonSchema>;
|
|
14
|
+
items?: JsonSchema;
|
|
15
|
+
[key: string]: unknown;
|
|
16
|
+
}
|
|
17
|
+
export type CoerceFn = (value: unknown) => unknown;
|
|
18
|
+
/** Register a custom coercion function, usable via `// coerce: name` in types. */
|
|
19
|
+
export declare function registerCoerce(name: string, fn: CoerceFn): void;
|
|
20
|
+
/**
|
|
21
|
+
* Decorator that registers a function as a custom coercer.
|
|
22
|
+
* The function name becomes the coerce key.
|
|
23
|
+
*
|
|
24
|
+
* @Coerce
|
|
25
|
+
* function slug(v: unknown) {
|
|
26
|
+
* return String(v).trim().toLowerCase().replace(/\s+/g, '-')
|
|
27
|
+
* }
|
|
28
|
+
*
|
|
29
|
+
* Then use in types:
|
|
30
|
+
* type Post = { url: string } // coerce: slug
|
|
31
|
+
*/
|
|
32
|
+
export declare function Coerce(target: CoerceFn, context?: {
|
|
33
|
+
name?: string;
|
|
34
|
+
}): void;
|
|
35
|
+
export declare function Coerce(target: any, propertyKey?: string, descriptor?: PropertyDescriptor): void;
|
|
36
|
+
/**
|
|
37
|
+
* Coerce a value to match the expected schema type.
|
|
38
|
+
* Mutates objects in-place for performance.
|
|
39
|
+
*
|
|
40
|
+
* Coercion modes (set via comment or generic: coerce: <mode>):
|
|
41
|
+
* false — no coercion
|
|
42
|
+
* trim — trim whitespace (default for strings)
|
|
43
|
+
* lower — trim + lowercase
|
|
44
|
+
* upper — trim + uppercase
|
|
45
|
+
* number — string → number (default for number/integer types)
|
|
46
|
+
* int — string → integer (floors)
|
|
47
|
+
* bool — string/number → boolean (default for boolean type)
|
|
48
|
+
* date — string/number → ISO date string
|
|
49
|
+
* datetime — string/number → ISO datetime string
|
|
50
|
+
* json — JSON.parse string → object/array
|
|
51
|
+
* split — comma-separated string → array
|
|
52
|
+
*/
|
|
53
|
+
export declare function coerce(value: unknown, schema: JsonSchema): unknown;
|
|
54
|
+
//# sourceMappingURL=coerce.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"coerce.d.ts","sourceRoot":"","sources":["../../../typescript/src/args/coerce.ts"],"names":[],"mappings":"AACA;;;;;GAKG;AAkBH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAa,GAAG,IAAI,GAAG,IAAI,CA2B9E;AAED,wBAAgB,YAAY,CACxB,KAAK,EAAE,OAAO,EACd,GAAG,OAAa,EAChB,QAAQ,UAAQ,GACjB,IAAI,GAAG,IAAI,CAiBb;AAID,MAAM,WAAW,UAAU;IACvB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAA;IACvC,KAAK,CAAC,EAAE,UAAU,CAAA;IAClB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CACzB;AAID,MAAM,MAAM,QAAQ,GAAG,CAAC,KAAK,EAAE,OAAO,KAAK,OAAO,CAAA;AAIlD,kFAAkF;AAClF,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,QAAQ,QAExD;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,MAAM,CAAC,MAAM,EAAE,QAAQ,EAAE,OAAO,CAAC,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAAA;AAC3E,wBAAgB,MAAM,CAAC,MAAM,EAAE,GAAG,EAAE,WAAW,CAAC,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,kBAAkB,GAAG,IAAI,CAAA;AAahG;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,GAAG,OAAO,CAyBlE"}
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type coercion for incoming data (query strings, form data, etc.)
|
|
3
|
+
*
|
|
4
|
+
* Handles: string→number, string→boolean, string→Date, trim strings.
|
|
5
|
+
* Called before validation so that "42" passes an integer schema.
|
|
6
|
+
*/
|
|
7
|
+
// ── date helpers (kept from dateCoerce.ts) ──────────────────
|
|
8
|
+
const startOfDay = (d) => { const c = new Date(d); c.setHours(0, 0, 0, 0); return c; };
|
|
9
|
+
const isValidDate = (v) => v instanceof Date && !Number.isNaN(v.getTime());
|
|
10
|
+
const addMs = (d, ms) => new Date(d.getTime() + ms);
|
|
11
|
+
const addMonths = (d, months) => {
|
|
12
|
+
const c = new Date(d);
|
|
13
|
+
c.setMonth(c.getMonth() + months);
|
|
14
|
+
return c;
|
|
15
|
+
};
|
|
16
|
+
const addYears = (d, years) => {
|
|
17
|
+
const c = new Date(d);
|
|
18
|
+
c.setFullYear(c.getFullYear() + years);
|
|
19
|
+
return c;
|
|
20
|
+
};
|
|
21
|
+
const RELATIVE_RE = /^(\d+)\s*(ms|millisecond|milliseconds|s|sec|secs|second|seconds|m|min|mins|minute|minutes|h|hr|hrs|hour|hours|d|day|days|w|week|weeks|mo|month|months|y|yr|year|years)(?:\s+ago)?$/i;
|
|
22
|
+
export function parseRelativeDate(input, now = new Date()) {
|
|
23
|
+
const s = input.trim().toLowerCase();
|
|
24
|
+
if (s === 'now' || s === 'today')
|
|
25
|
+
return new Date(now);
|
|
26
|
+
if (s === 'yesterday')
|
|
27
|
+
return addMs(now, -86_400_000);
|
|
28
|
+
if (s === 'tomorrow')
|
|
29
|
+
return addMs(now, 86_400_000);
|
|
30
|
+
const match = s.match(RELATIVE_RE);
|
|
31
|
+
if (!match)
|
|
32
|
+
return null;
|
|
33
|
+
const amount = Number(match[1]);
|
|
34
|
+
const unit = match[2];
|
|
35
|
+
const sign = s.includes('ago') ? -1 : 1;
|
|
36
|
+
const MS = {
|
|
37
|
+
ms: 1, millisecond: 1, milliseconds: 1,
|
|
38
|
+
s: 1000, sec: 1000, secs: 1000, second: 1000, seconds: 1000,
|
|
39
|
+
m: 60_000, min: 60_000, mins: 60_000, minute: 60_000, minutes: 60_000,
|
|
40
|
+
h: 3_600_000, hr: 3_600_000, hrs: 3_600_000, hour: 3_600_000, hours: 3_600_000,
|
|
41
|
+
d: 86_400_000, day: 86_400_000, days: 86_400_000,
|
|
42
|
+
w: 604_800_000, week: 604_800_000, weeks: 604_800_000,
|
|
43
|
+
};
|
|
44
|
+
if (unit in MS)
|
|
45
|
+
return addMs(now, sign * amount * MS[unit]);
|
|
46
|
+
if (/^(mo|month|months)$/.test(unit))
|
|
47
|
+
return addMonths(now, sign * amount);
|
|
48
|
+
if (/^(y|yr|year|years)$/.test(unit))
|
|
49
|
+
return addYears(now, sign * amount);
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
export function parseDateish(value, now = new Date(), dateOnly = false) {
|
|
53
|
+
if (value instanceof Date) {
|
|
54
|
+
return isValidDate(value) ? (dateOnly ? startOfDay(value) : new Date(value)) : null;
|
|
55
|
+
}
|
|
56
|
+
if (typeof value === 'number') {
|
|
57
|
+
const d = new Date(value);
|
|
58
|
+
return isValidDate(d) ? (dateOnly ? startOfDay(d) : d) : null;
|
|
59
|
+
}
|
|
60
|
+
if (typeof value !== 'string')
|
|
61
|
+
return null;
|
|
62
|
+
const s = value.trim();
|
|
63
|
+
if (!s)
|
|
64
|
+
return null;
|
|
65
|
+
const rel = parseRelativeDate(s, now);
|
|
66
|
+
if (rel)
|
|
67
|
+
return dateOnly ? startOfDay(rel) : rel;
|
|
68
|
+
const abs = new Date(s);
|
|
69
|
+
return isValidDate(abs) ? (dateOnly ? startOfDay(abs) : abs) : null;
|
|
70
|
+
}
|
|
71
|
+
const customCoercers = new Map();
|
|
72
|
+
/** Register a custom coercion function, usable via `// coerce: name` in types. */
|
|
73
|
+
export function registerCoerce(name, fn) {
|
|
74
|
+
customCoercers.set(name, fn);
|
|
75
|
+
}
|
|
76
|
+
export function Coerce(target, contextOrKey, descriptor) {
|
|
77
|
+
if (typeof target === 'function' && (contextOrKey === undefined || typeof contextOrKey === 'object')) {
|
|
78
|
+
// TC39 / standalone function decorator: @Coerce function slug() {}
|
|
79
|
+
const name = contextOrKey?.name ?? target.name;
|
|
80
|
+
if (name)
|
|
81
|
+
customCoercers.set(name, target);
|
|
82
|
+
}
|
|
83
|
+
else if (descriptor && typeof descriptor.value === 'function') {
|
|
84
|
+
// legacy method decorator: class Foo { @Coerce slug(v) {} }
|
|
85
|
+
const name = String(contextOrKey);
|
|
86
|
+
customCoercers.set(name, descriptor.value);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Coerce a value to match the expected schema type.
|
|
91
|
+
* Mutates objects in-place for performance.
|
|
92
|
+
*
|
|
93
|
+
* Coercion modes (set via comment or generic: coerce: <mode>):
|
|
94
|
+
* false — no coercion
|
|
95
|
+
* trim — trim whitespace (default for strings)
|
|
96
|
+
* lower — trim + lowercase
|
|
97
|
+
* upper — trim + uppercase
|
|
98
|
+
* number — string → number (default for number/integer types)
|
|
99
|
+
* int — string → integer (floors)
|
|
100
|
+
* bool — string/number → boolean (default for boolean type)
|
|
101
|
+
* date — string/number → ISO date string
|
|
102
|
+
* datetime — string/number → ISO datetime string
|
|
103
|
+
* json — JSON.parse string → object/array
|
|
104
|
+
* split — comma-separated string → array
|
|
105
|
+
*/
|
|
106
|
+
export function coerce(value, schema) {
|
|
107
|
+
if (value === undefined || value === null)
|
|
108
|
+
return value;
|
|
109
|
+
// explicit coerce mode takes priority
|
|
110
|
+
if (schema.coerce !== undefined) {
|
|
111
|
+
if (schema.coerce === 'false' || schema.coerce === false)
|
|
112
|
+
return value;
|
|
113
|
+
return applyCoerce(value, String(schema.coerce));
|
|
114
|
+
}
|
|
115
|
+
// default coercion by type
|
|
116
|
+
switch (schema.type) {
|
|
117
|
+
case 'string':
|
|
118
|
+
return coerceTrim(value);
|
|
119
|
+
case 'number':
|
|
120
|
+
case 'integer':
|
|
121
|
+
return coerceNumber(value);
|
|
122
|
+
case 'boolean':
|
|
123
|
+
return coerceBoolean(value);
|
|
124
|
+
case 'object':
|
|
125
|
+
return coerceObject(value, schema);
|
|
126
|
+
case 'array':
|
|
127
|
+
return coerceArray(value, schema);
|
|
128
|
+
default:
|
|
129
|
+
return value;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
function applyCoerce(value, mode) {
|
|
133
|
+
switch (mode) {
|
|
134
|
+
case 'trim': return coerceTrim(value);
|
|
135
|
+
case 'lower': return coerceLower(value);
|
|
136
|
+
case 'upper': return coerceUpper(value);
|
|
137
|
+
case 'number': return coerceNumber(value);
|
|
138
|
+
case 'int': return coerceInt(value);
|
|
139
|
+
case 'bool': return coerceBoolean(value);
|
|
140
|
+
case 'date':
|
|
141
|
+
case 'datetime': {
|
|
142
|
+
const d = parseDateish(value, new Date(), mode === 'date');
|
|
143
|
+
return d ? d.toISOString() : value;
|
|
144
|
+
}
|
|
145
|
+
case 'json': return coerceJson(value);
|
|
146
|
+
case 'split': return coerceSplit(value);
|
|
147
|
+
default: {
|
|
148
|
+
const custom = customCoercers.get(mode);
|
|
149
|
+
return custom ? custom(value) : value;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
function coerceTrim(value) {
|
|
154
|
+
if (typeof value !== 'string')
|
|
155
|
+
return String(value);
|
|
156
|
+
return value.trim();
|
|
157
|
+
}
|
|
158
|
+
function coerceLower(value) {
|
|
159
|
+
if (typeof value !== 'string')
|
|
160
|
+
return String(value).toLowerCase();
|
|
161
|
+
return value.trim().toLowerCase();
|
|
162
|
+
}
|
|
163
|
+
function coerceUpper(value) {
|
|
164
|
+
if (typeof value !== 'string')
|
|
165
|
+
return String(value).toUpperCase();
|
|
166
|
+
return value.trim().toUpperCase();
|
|
167
|
+
}
|
|
168
|
+
function coerceNumber(value) {
|
|
169
|
+
if (typeof value === 'number')
|
|
170
|
+
return value;
|
|
171
|
+
if (typeof value === 'string') {
|
|
172
|
+
const n = Number(value);
|
|
173
|
+
if (!Number.isNaN(n) && value.trim() !== '')
|
|
174
|
+
return n;
|
|
175
|
+
}
|
|
176
|
+
return value;
|
|
177
|
+
}
|
|
178
|
+
function coerceInt(value) {
|
|
179
|
+
const n = coerceNumber(value);
|
|
180
|
+
return typeof n === 'number' ? Math.floor(n) : n;
|
|
181
|
+
}
|
|
182
|
+
const TRUTHY = new Set(['true', '1', 'yes', 'y', 'on']);
|
|
183
|
+
const FALSY = new Set(['false', '0', 'no', 'n', 'off', '']);
|
|
184
|
+
function coerceBoolean(value) {
|
|
185
|
+
if (typeof value === 'boolean')
|
|
186
|
+
return value;
|
|
187
|
+
if (typeof value === 'number')
|
|
188
|
+
return value !== 0;
|
|
189
|
+
if (typeof value === 'string') {
|
|
190
|
+
const s = value.trim().toLowerCase();
|
|
191
|
+
if (TRUTHY.has(s))
|
|
192
|
+
return true;
|
|
193
|
+
if (FALSY.has(s))
|
|
194
|
+
return false;
|
|
195
|
+
}
|
|
196
|
+
return value;
|
|
197
|
+
}
|
|
198
|
+
function coerceJson(value) {
|
|
199
|
+
if (typeof value !== 'string')
|
|
200
|
+
return value;
|
|
201
|
+
try {
|
|
202
|
+
return JSON.parse(value);
|
|
203
|
+
}
|
|
204
|
+
catch {
|
|
205
|
+
return value;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
function coerceSplit(value) {
|
|
209
|
+
if (Array.isArray(value))
|
|
210
|
+
return value;
|
|
211
|
+
if (typeof value !== 'string')
|
|
212
|
+
return value;
|
|
213
|
+
return value.split(',').map(s => s.trim()).filter(Boolean);
|
|
214
|
+
}
|
|
215
|
+
function coerceObject(value, schema) {
|
|
216
|
+
if (typeof value !== 'object' || value === null || Array.isArray(value))
|
|
217
|
+
return value;
|
|
218
|
+
if (!schema.properties)
|
|
219
|
+
return value;
|
|
220
|
+
const obj = value;
|
|
221
|
+
for (const [key, propSchema] of Object.entries(schema.properties)) {
|
|
222
|
+
if (key in obj) {
|
|
223
|
+
obj[key] = coerce(obj[key], propSchema);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
return obj;
|
|
227
|
+
}
|
|
228
|
+
function coerceArray(value, schema) {
|
|
229
|
+
if (!Array.isArray(value) || !schema.items)
|
|
230
|
+
return value;
|
|
231
|
+
for (let i = 0; i < value.length; i++) {
|
|
232
|
+
value[i] = coerce(value[i], schema.items);
|
|
233
|
+
}
|
|
234
|
+
return value;
|
|
235
|
+
}
|
|
236
|
+
//# sourceMappingURL=coerce.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"coerce.js","sourceRoot":"","sources":["../../../typescript/src/args/coerce.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../typescript/src/args/index.ts"],"names":[],"mappings":"AACA,cAAc,MAAM,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../typescript/src/args/index.ts"],"names":[],"mappings":"AACA,cAAc,MAAM,CAAA"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scalar type aliases.
|
|
3
|
+
*
|
|
4
|
+
* These are plain TypeScript types. The codegen reads the alias name
|
|
5
|
+
* and maps it to a richer JSON Schema. At runtime they're just
|
|
6
|
+
* string / number / boolean.
|
|
7
|
+
*
|
|
8
|
+
* Generic params override min/max from the comment constraints.
|
|
9
|
+
* int → { type: integer, minimum: 0 }
|
|
10
|
+
* int<5> → { type: integer, minimum: 5 }
|
|
11
|
+
* int<0, 100> → { type: integer, minimum: 0, maximum: 100 }
|
|
12
|
+
*
|
|
13
|
+
* Usage:
|
|
14
|
+
* type CreatePost = {
|
|
15
|
+
* author: email
|
|
16
|
+
* priority: pint
|
|
17
|
+
* title: str<1, 200>
|
|
18
|
+
* age: int<0, 150>
|
|
19
|
+
* }
|
|
20
|
+
*/
|
|
21
|
+
export type str<min = never, max = never> = string;
|
|
22
|
+
export type varchar<max = never> = string;
|
|
23
|
+
export type vc = varchar;
|
|
24
|
+
export type char = str<1, 1>;
|
|
25
|
+
export type text = str<0, 65535>;
|
|
26
|
+
export type word = pattern<'[a-zA-Z]+'>;
|
|
27
|
+
export type token = pattern<'[a-zA-Z0-9_]+'>;
|
|
28
|
+
export type line = pattern<'[^\\n]+'>;
|
|
29
|
+
export type email = string;
|
|
30
|
+
export type url = string;
|
|
31
|
+
export type uuid = string;
|
|
32
|
+
export type ip = string;
|
|
33
|
+
export type ipv6 = string;
|
|
34
|
+
export type hostname = string;
|
|
35
|
+
export type datestr = string;
|
|
36
|
+
export type datetime = string;
|
|
37
|
+
export type time = string;
|
|
38
|
+
export type json = string;
|
|
39
|
+
export type pattern<pattern = never> = string;
|
|
40
|
+
export type grep<grep = never> = string;
|
|
41
|
+
export type like<like = never> = string;
|
|
42
|
+
export type ilike<ilike = never> = string;
|
|
43
|
+
export type hex = pattern<'[0-9a-fA-F]+'>;
|
|
44
|
+
export type digits = pattern<'[0-9]+'>;
|
|
45
|
+
export type numeric = pattern<'-?[0-9]+(\\.[0-9]+)?'>;
|
|
46
|
+
export type upper = pattern<'[A-Z ]+'>;
|
|
47
|
+
export type lower = pattern<'[a-z ]+'>;
|
|
48
|
+
export type alpha = pattern<'[a-zA-Z]+'>;
|
|
49
|
+
export type alphanum = pattern<'[a-zA-Z0-9]+'>;
|
|
50
|
+
export type title = pattern<'[A-Z][a-zA-Z ]*'>;
|
|
51
|
+
export type slug = pattern<'[a-z0-9]+(-[a-z0-9]+)*'>;
|
|
52
|
+
export type semver = pattern<'[0-9]+\\.[0-9]+\\.[0-9]+'>;
|
|
53
|
+
export type base64 = pattern<'[A-Za-z0-9+/]+=*'>;
|
|
54
|
+
export type base58 = pattern<'[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]+'>;
|
|
55
|
+
export type phone = pattern<'\\+?[0-9\\- ()]+'>;
|
|
56
|
+
export type color = pattern<'#[0-9a-fA-F]{3,8}'>;
|
|
57
|
+
export type locale = pattern<'[a-z]{2}(-[A-Z]{2})?'>;
|
|
58
|
+
export type mimetype = pattern<'[a-z]+/[a-z0-9.+-]+'>;
|
|
59
|
+
export type filepath = pattern<'[^\\0]+'>;
|
|
60
|
+
export type cuid = pattern<'c[a-z0-9]{24}'>;
|
|
61
|
+
export type ulid = pattern<'[0-9A-HJKMNP-TV-Z]{26}'>;
|
|
62
|
+
export type nanoid = pattern<'[A-Za-z0-9_-]{21}'>;
|
|
63
|
+
export type jwt = pattern<'[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+'>;
|
|
64
|
+
export type countrycode = pattern<'[A-Z]{2}'>;
|
|
65
|
+
export type currency = pattern<'[A-Z]{3}'>;
|
|
66
|
+
export type lang = pattern<'[a-z]{2}'>;
|
|
67
|
+
export type cron = pattern<'[0-9*,/-]+ [0-9*,/-]+ [0-9*,/-]+ [0-9*,/-]+ [0-9*,/-]+'>;
|
|
68
|
+
export type num<min = never, max = never> = number;
|
|
69
|
+
export type float<min = never, max = never> = number;
|
|
70
|
+
export type double<min = never, max = never> = number;
|
|
71
|
+
export type int<min = never, max = never> = number;
|
|
72
|
+
export type pos = num<0>;
|
|
73
|
+
export type neg = number;
|
|
74
|
+
export type notneg = num<0>;
|
|
75
|
+
export type posint<max = never> = int<1, max>;
|
|
76
|
+
export type percent = num<0, 100>;
|
|
77
|
+
export type limit = int<1>;
|
|
78
|
+
export type offset = int<0>;
|
|
79
|
+
export type port = int<0, 65535>;
|
|
80
|
+
export type byte = int<0, 255>;
|
|
81
|
+
export type timestamp = int<0>;
|
|
82
|
+
export type age = int<0, 130>;
|
|
83
|
+
export type cents = int<0>;
|
|
84
|
+
export type lat = float<-90, 90>;
|
|
85
|
+
export type lng = float<-180, 180>;
|
|
86
|
+
export type flag = boolean;
|
|
87
|
+
//# sourceMappingURL=scalars.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scalars.d.ts","sourceRoot":"","sources":["../../../typescript/src/args/scalars.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scalar type aliases.
|
|
3
|
+
*
|
|
4
|
+
* These are plain TypeScript types. The codegen reads the alias name
|
|
5
|
+
* and maps it to a richer JSON Schema. At runtime they're just
|
|
6
|
+
* string / number / boolean.
|
|
7
|
+
*
|
|
8
|
+
* Generic params override min/max from the comment constraints.
|
|
9
|
+
* int → { type: integer, minimum: 0 }
|
|
10
|
+
* int<5> → { type: integer, minimum: 5 }
|
|
11
|
+
* int<0, 100> → { type: integer, minimum: 0, maximum: 100 }
|
|
12
|
+
*
|
|
13
|
+
* Usage:
|
|
14
|
+
* type CreatePost = {
|
|
15
|
+
* author: email
|
|
16
|
+
* priority: pint
|
|
17
|
+
* title: str<1, 200>
|
|
18
|
+
* age: int<0, 150>
|
|
19
|
+
* }
|
|
20
|
+
*/
|
|
21
|
+
export {};
|
|
22
|
+
//# sourceMappingURL=scalars.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scalars.js","sourceRoot":"","sources":["../../../typescript/src/args/scalars.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runtime validation against JSON Schema objects.
|
|
3
|
+
*
|
|
4
|
+
* Lean validator covering the JSON Schema subset that gen-schema.ts produces.
|
|
5
|
+
* Coerces before validating (string→number, string→date, trim, etc.)
|
|
6
|
+
*/
|
|
7
|
+
import { type JsonSchema } from './coerce';
|
|
8
|
+
export declare class ValidationError extends Error {
|
|
9
|
+
issues: string[];
|
|
10
|
+
constructor(issues: string[]);
|
|
11
|
+
}
|
|
12
|
+
export type ParseResult<T> = {
|
|
13
|
+
ok: true;
|
|
14
|
+
data: T;
|
|
15
|
+
} | {
|
|
16
|
+
ok: false;
|
|
17
|
+
error: ValidationError;
|
|
18
|
+
};
|
|
19
|
+
/** Coerce + validate. Throws on failure. */
|
|
20
|
+
export declare function parse<T = unknown>(schema: JsonSchema, value: unknown): T;
|
|
21
|
+
/** Coerce + validate. Returns result object. */
|
|
22
|
+
export declare function safeParse<T = unknown>(schema: JsonSchema, value: unknown): ParseResult<T>;
|
|
23
|
+
//# sourceMappingURL=validate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../../typescript/src/args/validate.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAU,KAAK,UAAU,EAAE,MAAM,UAAU,CAAA;AAElD,qBAAa,eAAgB,SAAQ,KAAK;IACnB,MAAM,EAAE,MAAM,EAAE;gBAAhB,MAAM,EAAE,MAAM,EAAE;CAItC;AAED,MAAM,MAAM,WAAW,CAAC,CAAC,IACnB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,CAAC,CAAA;CAAE,GACrB;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,eAAe,CAAA;CAAE,CAAA;AAE3C,4CAA4C;AAC5C,wBAAgB,KAAK,CAAC,CAAC,GAAG,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,OAAO,GAAG,CAAC,CAMxE;AAED,gDAAgD;AAChD,wBAAgB,SAAS,CAAC,CAAC,GAAG,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,OAAO,GAAG,WAAW,CAAC,CAAC,CAAC,CAOzF"}
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runtime validation against JSON Schema objects.
|
|
3
|
+
*
|
|
4
|
+
* Lean validator covering the JSON Schema subset that gen-schema.ts produces.
|
|
5
|
+
* Coerces before validating (string→number, string→date, trim, etc.)
|
|
6
|
+
*/
|
|
7
|
+
import { coerce } from './coerce.js';
|
|
8
|
+
export class ValidationError extends Error {
|
|
9
|
+
issues;
|
|
10
|
+
constructor(issues) {
|
|
11
|
+
super(issues.join('; '));
|
|
12
|
+
this.issues = issues;
|
|
13
|
+
this.name = 'ValidationError';
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
/** Coerce + validate. Throws on failure. */
|
|
17
|
+
export function parse(schema, value) {
|
|
18
|
+
const data = coerce(structuredClone(value), schema);
|
|
19
|
+
const issues = [];
|
|
20
|
+
validate(data, schema, '', issues);
|
|
21
|
+
if (issues.length > 0)
|
|
22
|
+
throw new ValidationError(issues);
|
|
23
|
+
return data;
|
|
24
|
+
}
|
|
25
|
+
/** Coerce + validate. Returns result object. */
|
|
26
|
+
export function safeParse(schema, value) {
|
|
27
|
+
try {
|
|
28
|
+
return { ok: true, data: parse(schema, value) };
|
|
29
|
+
}
|
|
30
|
+
catch (e) {
|
|
31
|
+
if (e instanceof ValidationError)
|
|
32
|
+
return { ok: false, error: e };
|
|
33
|
+
throw e;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
// ── validate recursively ────────────────────────────────────
|
|
37
|
+
function validate(value, schema, path, issues) {
|
|
38
|
+
// nullable
|
|
39
|
+
if (value === null || value === undefined) {
|
|
40
|
+
if (schema.nullable)
|
|
41
|
+
return;
|
|
42
|
+
issues.push(`${path || '.'}: required`);
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
// oneOf (used for nullable)
|
|
46
|
+
if (schema.oneOf) {
|
|
47
|
+
const sub = schema.oneOf;
|
|
48
|
+
for (const s of sub) {
|
|
49
|
+
const subIssues = [];
|
|
50
|
+
validate(value, s, path, subIssues);
|
|
51
|
+
if (subIssues.length === 0)
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
issues.push(`${path || '.'}: does not match any variant`);
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
switch (schema.type) {
|
|
58
|
+
case 'string': return validateString(value, schema, path, issues);
|
|
59
|
+
case 'number': return validateNumber(value, schema, path, issues);
|
|
60
|
+
case 'integer': return validateInteger(value, schema, path, issues);
|
|
61
|
+
case 'boolean': return validateBoolean(value, path, issues);
|
|
62
|
+
case 'object': return validateObject(value, schema, path, issues);
|
|
63
|
+
case 'array': return validateArray(value, schema, path, issues);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
function validateString(value, schema, path, issues) {
|
|
67
|
+
if (typeof value !== 'string') {
|
|
68
|
+
issues.push(`${path || '.'}: expected string, got ${typeof value}`);
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
const len = value.length;
|
|
72
|
+
if (schema.minLength !== undefined && len < schema.minLength)
|
|
73
|
+
issues.push(`${path || '.'}: string too short (min ${schema.minLength})`);
|
|
74
|
+
if (schema.maxLength !== undefined && len > schema.maxLength)
|
|
75
|
+
issues.push(`${path || '.'}: string too long (max ${schema.maxLength})`);
|
|
76
|
+
if (schema.pattern) {
|
|
77
|
+
const flags = schema.patternFlags || '';
|
|
78
|
+
if (!new RegExp(schema.pattern, flags).test(value))
|
|
79
|
+
issues.push(`${path || '.'}: does not match pattern ${schema.pattern}`);
|
|
80
|
+
}
|
|
81
|
+
if (schema.format)
|
|
82
|
+
validateFormat(value, schema.format, path, issues);
|
|
83
|
+
if (schema.enum && !schema.enum.includes(value))
|
|
84
|
+
issues.push(`${path || '.'}: must be one of ${schema.enum.join(', ')}`);
|
|
85
|
+
}
|
|
86
|
+
function validateFormat(value, format, path, issues) {
|
|
87
|
+
switch (format) {
|
|
88
|
+
case 'email':
|
|
89
|
+
if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value))
|
|
90
|
+
issues.push(`${path || '.'}: invalid email`);
|
|
91
|
+
break;
|
|
92
|
+
case 'uri':
|
|
93
|
+
try {
|
|
94
|
+
new URL(value);
|
|
95
|
+
}
|
|
96
|
+
catch {
|
|
97
|
+
issues.push(`${path || '.'}: invalid URL`);
|
|
98
|
+
}
|
|
99
|
+
break;
|
|
100
|
+
case 'uuid':
|
|
101
|
+
if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(value))
|
|
102
|
+
issues.push(`${path || '.'}: invalid UUID`);
|
|
103
|
+
break;
|
|
104
|
+
case 'date':
|
|
105
|
+
if (!/^\d{4}-\d{2}-\d{2}$/.test(value) || Number.isNaN(Date.parse(value)))
|
|
106
|
+
issues.push(`${path || '.'}: invalid date`);
|
|
107
|
+
break;
|
|
108
|
+
case 'date-time':
|
|
109
|
+
if (Number.isNaN(Date.parse(value)))
|
|
110
|
+
issues.push(`${path || '.'}: invalid datetime`);
|
|
111
|
+
break;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
function validateNumber(value, schema, path, issues) {
|
|
115
|
+
if (typeof value !== 'number' || Number.isNaN(value)) {
|
|
116
|
+
issues.push(`${path || '.'}: expected number, got ${typeof value}`);
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
checkNumericConstraints(value, schema, path, issues);
|
|
120
|
+
}
|
|
121
|
+
function validateInteger(value, schema, path, issues) {
|
|
122
|
+
if (typeof value !== 'number' || Number.isNaN(value)) {
|
|
123
|
+
issues.push(`${path || '.'}: expected integer, got ${typeof value}`);
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
if (!Number.isInteger(value))
|
|
127
|
+
issues.push(`${path || '.'}: expected integer, got float`);
|
|
128
|
+
checkNumericConstraints(value, schema, path, issues);
|
|
129
|
+
}
|
|
130
|
+
function checkNumericConstraints(value, schema, path, issues) {
|
|
131
|
+
if (schema.minimum !== undefined && value < schema.minimum)
|
|
132
|
+
issues.push(`${path || '.'}: must be >= ${schema.minimum}`);
|
|
133
|
+
if (schema.maximum !== undefined && value > schema.maximum)
|
|
134
|
+
issues.push(`${path || '.'}: must be <= ${schema.maximum}`);
|
|
135
|
+
if (schema.exclusiveMinimum !== undefined && value <= schema.exclusiveMinimum)
|
|
136
|
+
issues.push(`${path || '.'}: must be > ${schema.exclusiveMinimum}`);
|
|
137
|
+
if (schema.exclusiveMaximum !== undefined && value >= schema.exclusiveMaximum)
|
|
138
|
+
issues.push(`${path || '.'}: must be < ${schema.exclusiveMaximum}`);
|
|
139
|
+
if (schema.multipleOf !== undefined && value % schema.multipleOf !== 0)
|
|
140
|
+
issues.push(`${path || '.'}: must be multiple of ${schema.multipleOf}`);
|
|
141
|
+
if (schema.enum && !schema.enum.includes(value))
|
|
142
|
+
issues.push(`${path || '.'}: must be one of ${schema.enum.join(', ')}`);
|
|
143
|
+
}
|
|
144
|
+
function validateBoolean(value, path, issues) {
|
|
145
|
+
if (typeof value !== 'boolean')
|
|
146
|
+
issues.push(`${path || '.'}: expected boolean, got ${typeof value}`);
|
|
147
|
+
}
|
|
148
|
+
function validateObject(value, schema, path, issues) {
|
|
149
|
+
if (typeof value !== 'object' || value === null || Array.isArray(value)) {
|
|
150
|
+
issues.push(`${path || '.'}: expected object`);
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
const obj = value;
|
|
154
|
+
const required = schema.required ?? [];
|
|
155
|
+
// check required fields
|
|
156
|
+
for (const key of required) {
|
|
157
|
+
if (!(key in obj) || obj[key] === undefined) {
|
|
158
|
+
issues.push(`${path ? path + '.' : ''}${key}: required`);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
// validate each property
|
|
162
|
+
if (schema.properties) {
|
|
163
|
+
for (const [key, propSchema] of Object.entries(schema.properties)) {
|
|
164
|
+
if (key in obj && obj[key] !== undefined) {
|
|
165
|
+
validate(obj[key], propSchema, `${path ? path + '.' : ''}${key}`, issues);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
function validateArray(value, schema, path, issues) {
|
|
171
|
+
if (!Array.isArray(value)) {
|
|
172
|
+
issues.push(`${path || '.'}: expected array`);
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
if (schema.minItems !== undefined && value.length < schema.minItems)
|
|
176
|
+
issues.push(`${path || '.'}: too few items (min ${schema.minItems})`);
|
|
177
|
+
if (schema.maxItems !== undefined && value.length > schema.maxItems)
|
|
178
|
+
issues.push(`${path || '.'}: too many items (max ${schema.maxItems})`);
|
|
179
|
+
if (schema.items) {
|
|
180
|
+
for (let i = 0; i < value.length; i++) {
|
|
181
|
+
validate(value[i], schema.items, `${path}[${i}]`, issues);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
//# sourceMappingURL=validate.js.map
|