@flare-ts/lib 0.1.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.
Files changed (80) hide show
  1. package/LICENSE +21 -0
  2. package/dist/index.d.ts +2 -0
  3. package/dist/index.d.ts.map +1 -0
  4. package/dist/index.js +1 -0
  5. package/dist/schema/index.d.ts +10 -0
  6. package/dist/schema/index.d.ts.map +1 -0
  7. package/dist/schema/index.js +21 -0
  8. package/dist/schema/internal/index.d.ts +4 -0
  9. package/dist/schema/internal/index.d.ts.map +1 -0
  10. package/dist/schema/internal/index.js +8 -0
  11. package/dist/schema/internal/parser/array.d.ts +7 -0
  12. package/dist/schema/internal/parser/array.d.ts.map +1 -0
  13. package/dist/schema/internal/parser/array.js +33 -0
  14. package/dist/schema/internal/parser/discriminated.d.ts +11 -0
  15. package/dist/schema/internal/parser/discriminated.d.ts.map +1 -0
  16. package/dist/schema/internal/parser/discriminated.js +40 -0
  17. package/dist/schema/internal/parser/input.d.ts +26 -0
  18. package/dist/schema/internal/parser/input.d.ts.map +1 -0
  19. package/dist/schema/internal/parser/input.js +56 -0
  20. package/dist/schema/internal/parser/object.d.ts +16 -0
  21. package/dist/schema/internal/parser/object.d.ts.map +1 -0
  22. package/dist/schema/internal/parser/object.js +81 -0
  23. package/dist/schema/internal/parser/path.d.ts +5 -0
  24. package/dist/schema/internal/parser/path.d.ts.map +1 -0
  25. package/dist/schema/internal/parser/path.js +11 -0
  26. package/dist/schema/internal/parser/record.d.ts +8 -0
  27. package/dist/schema/internal/parser/record.d.ts.map +1 -0
  28. package/dist/schema/internal/parser/record.js +44 -0
  29. package/dist/schema/internal/token/optionality.d.ts +6 -0
  30. package/dist/schema/internal/token/optionality.d.ts.map +1 -0
  31. package/dist/schema/internal/token/optionality.js +11 -0
  32. package/dist/schema/internal/token/symbols.d.ts +7 -0
  33. package/dist/schema/internal/token/symbols.d.ts.map +1 -0
  34. package/dist/schema/internal/token/symbols.js +8 -0
  35. package/dist/schema/internal/types/inference.d.ts +20 -0
  36. package/dist/schema/internal/types/inference.d.ts.map +1 -0
  37. package/dist/schema/internal/types/inference.js +0 -0
  38. package/dist/schema/json/serializer.d.ts +51 -0
  39. package/dist/schema/json/serializer.d.ts.map +1 -0
  40. package/dist/schema/json/serializer.js +265 -0
  41. package/dist/schema/model.d.ts +54 -0
  42. package/dist/schema/model.d.ts.map +1 -0
  43. package/dist/schema/model.js +41 -0
  44. package/dist/schema/primitives/array.d.ts +14 -0
  45. package/dist/schema/primitives/array.d.ts.map +1 -0
  46. package/dist/schema/primitives/array.js +21 -0
  47. package/dist/schema/primitives/bool.d.ts +7 -0
  48. package/dist/schema/primitives/bool.d.ts.map +1 -0
  49. package/dist/schema/primitives/bool.js +12 -0
  50. package/dist/schema/primitives/date.d.ts +23 -0
  51. package/dist/schema/primitives/date.d.ts.map +1 -0
  52. package/dist/schema/primitives/date.js +92 -0
  53. package/dist/schema/primitives/enum.d.ts +19 -0
  54. package/dist/schema/primitives/enum.d.ts.map +1 -0
  55. package/dist/schema/primitives/enum.js +19 -0
  56. package/dist/schema/primitives/float.d.ts +23 -0
  57. package/dist/schema/primitives/float.d.ts.map +1 -0
  58. package/dist/schema/primitives/float.js +33 -0
  59. package/dist/schema/primitives/index.d.ts +89 -0
  60. package/dist/schema/primitives/index.d.ts.map +1 -0
  61. package/dist/schema/primitives/index.js +44 -0
  62. package/dist/schema/primitives/int.d.ts +24 -0
  63. package/dist/schema/primitives/int.d.ts.map +1 -0
  64. package/dist/schema/primitives/int.js +43 -0
  65. package/dist/schema/primitives/str.d.ts +26 -0
  66. package/dist/schema/primitives/str.d.ts.map +1 -0
  67. package/dist/schema/primitives/str.js +30 -0
  68. package/dist/schema/primitives/text.d.ts +33 -0
  69. package/dist/schema/primitives/text.d.ts.map +1 -0
  70. package/dist/schema/primitives/text.js +30 -0
  71. package/dist/schema/primitives/uuid.d.ts +7 -0
  72. package/dist/schema/primitives/uuid.d.ts.map +1 -0
  73. package/dist/schema/primitives/uuid.js +13 -0
  74. package/dist/schema/schema.d.ts +167 -0
  75. package/dist/schema/schema.d.ts.map +1 -0
  76. package/dist/schema/schema.js +74 -0
  77. package/dist/schema/symbol.d.ts +15 -0
  78. package/dist/schema/symbol.d.ts.map +1 -0
  79. package/dist/schema/symbol.js +6 -0
  80. package/package.json +49 -0
@@ -0,0 +1,89 @@
1
+ export { array } from "./array.js";
2
+ export { bool } from "./bool.js";
3
+ export { date } from "./date.js";
4
+ export { enums } from "./enum.js";
5
+ export { float } from "./float.js";
6
+ export { int } from "./int.js";
7
+ export { str } from "./str.js";
8
+ export { text } from "./text.js";
9
+ export { uuid } from "./uuid.js";
10
+ /**
11
+ * JSON Schema fragment describing the constraints of a single primitive.
12
+ *
13
+ * Each primitive carries one of these on its `jsonSchema` property so the
14
+ * compiled serializer and {@link toJsonSchema} exporter can introspect it
15
+ * without re-deriving the shape.
16
+ */
17
+ export type PrimitiveJsonSchema = Record<string, never> | {
18
+ type: "string";
19
+ format?: string;
20
+ enum?: readonly string[];
21
+ minLength?: number;
22
+ maxLength?: number;
23
+ pattern?: string;
24
+ } | {
25
+ type: "integer";
26
+ minimum?: number;
27
+ maximum?: number;
28
+ } | {
29
+ type: "number";
30
+ minimum?: number;
31
+ maximum?: number;
32
+ } | {
33
+ type: "boolean";
34
+ } | {
35
+ type: "array";
36
+ items: PrimitiveJsonSchema;
37
+ };
38
+ /**
39
+ * Opaque reference to a primitive coercer.
40
+ *
41
+ * Carries the runtime metadata (`_type`, `_required`, `jsonSchema`) but no
42
+ * value-type information. Used wherever a collection of primitives is held
43
+ * without needing to invoke them or know their output type. To invoke a
44
+ * primitive and recover a typed value, use {@link TypedPrimitive}.
45
+ */
46
+ export type Primitive = {
47
+ readonly _type: string;
48
+ readonly _required: boolean;
49
+ readonly jsonSchema: PrimitiveJsonSchema;
50
+ };
51
+ /**
52
+ * Carries the output type alongside the primitive coercer.
53
+ *
54
+ * Callable as `(v: string) => T`. Used as a leaf value inside schema
55
+ * descriptors and wherever the output type is needed.
56
+ *
57
+ * @template T The output type produced after coercion and validation.
58
+ */
59
+ export type TypedPrimitive<T> = Primitive & {
60
+ (v: string): T;
61
+ };
62
+ /**
63
+ * Array-accepting primitive coercer that splits a comma-separated string or
64
+ * maps over an existing string array.
65
+ *
66
+ * @template T The element type produced after coercing each item.
67
+ */
68
+ export type ArrayTypedPrimitive<T> = Primitive & {
69
+ (v: string | string[]): T[];
70
+ };
71
+ /**
72
+ * Wraps a primitive to accept missing or empty-string inputs, mapping them to `undefined`.
73
+ *
74
+ * @example
75
+ * ```ts
76
+ * const maybeInt = optional(int); // TypedPrimitive<number | undefined>
77
+ * ```
78
+ */
79
+ export declare function optional<T>(primitive: TypedPrimitive<T>): TypedPrimitive<T | undefined>;
80
+ /**
81
+ * Wraps a primitive so that missing or empty-string inputs produce `fallback` instead.
82
+ *
83
+ * @example
84
+ * ```ts
85
+ * const countOrZero = defaultTo(0, int.min(0));
86
+ * ```
87
+ */
88
+ export declare function defaultTo<T>(fallback: T, primitive: TypedPrimitive<T>): TypedPrimitive<T>;
89
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/schema/primitives/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,KAAK,EAAE,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAC/B,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAC/B,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC;;;;;;GAMG;AACH,MAAM,MAAM,mBAAmB,GAC3B,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,GACrB;IACA,IAAI,EAAE,QAAQ,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,GACC;IACA,IAAI,EAAE,SAAS,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,GACC;IACA,IAAI,EAAE,QAAQ,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,GACC;IACA,IAAI,EAAE,SAAS,CAAC;CACjB,GACC;IACA,IAAI,EAAE,OAAO,CAAC;IACd,KAAK,EAAE,mBAAmB,CAAC;CAC5B,CAAC;AAEJ;;;;;;;GAOG;AACH,MAAM,MAAM,SAAS,GAAG;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,UAAU,EAAE,mBAAmB,CAAC;CAC1C,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,MAAM,cAAc,CAAC,CAAC,IAAI,SAAS,GAAG;IAC1C,CAAC,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC;CAChB,CAAC;AAEF;;;;;GAKG;AACH,MAAM,MAAM,mBAAmB,CAAC,CAAC,IAAI,SAAS,GAAG;IAC/C,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,CAAC,EAAE,CAAC;CAC7B,CAAC;AAEF;;;;;;;GAOG;AACH,wBAAgB,QAAQ,CAAC,CAAC,EAAE,SAAS,EAAE,cAAc,CAAC,CAAC,CAAC,GAAG,cAAc,CAAC,CAAC,GAAG,SAAS,CAAC,CAUvF;AAED;;;;;;;GAOG;AACH,wBAAgB,SAAS,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,SAAS,EAAE,cAAc,CAAC,CAAC,CAAC,GAAG,cAAc,CAAC,CAAC,CAAC,CAUzF"}
@@ -0,0 +1,44 @@
1
+ import { array } from "./array.js";
2
+ import { bool } from "./bool.js";
3
+ import { date } from "./date.js";
4
+ import { enums } from "./enum.js";
5
+ import { float } from "./float.js";
6
+ import { int } from "./int.js";
7
+ import { str } from "./str.js";
8
+ import { text } from "./text.js";
9
+ import { uuid } from "./uuid.js";
10
+ function optional(primitive) {
11
+ const optionalPrimitive = (v) => {
12
+ if (v === void 0) throw new TypeError("optional primitive received undefined");
13
+ if (v === "") return void 0;
14
+ return primitive(v);
15
+ };
16
+ optionalPrimitive._type = primitive._type;
17
+ optionalPrimitive._required = false;
18
+ optionalPrimitive.jsonSchema = primitive.jsonSchema;
19
+ return optionalPrimitive;
20
+ }
21
+ function defaultTo(fallback, primitive) {
22
+ const fn = (v) => {
23
+ if (v === void 0) throw new TypeError("defaultTo primitive received undefined");
24
+ if (v === "") return fallback;
25
+ return primitive(v);
26
+ };
27
+ fn._type = primitive._type;
28
+ fn._required = false;
29
+ fn.jsonSchema = primitive.jsonSchema;
30
+ return fn;
31
+ }
32
+ export {
33
+ array,
34
+ bool,
35
+ date,
36
+ defaultTo,
37
+ enums,
38
+ float,
39
+ int,
40
+ optional,
41
+ str,
42
+ text,
43
+ uuid
44
+ };
@@ -0,0 +1,24 @@
1
+ import type { TypedPrimitive } from "./index.js";
2
+ /**
3
+ * Integer primitive with optional chainable range constraints.
4
+ * Each builder method returns a new independent primitive so the original is never mutated.
5
+ */
6
+ type IntPrimitive = TypedPrimitive<number> & {
7
+ /** Returns a new primitive that rejects values below `n`. */
8
+ min(n: number): IntPrimitive;
9
+ /** Returns a new primitive that rejects values above `n`. */
10
+ max(n: number): IntPrimitive;
11
+ };
12
+ /**
13
+ * Integer primitive. Rejects non-integer input and optionally enforces a range.
14
+ *
15
+ * @example
16
+ * ```ts
17
+ * int // any integer
18
+ * int.min(0) // non-negative
19
+ * int.min(1).max(100) // bounded range
20
+ * ```
21
+ */
22
+ export declare const int: IntPrimitive;
23
+ export {};
24
+ //# sourceMappingURL=int.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"int.d.ts","sourceRoot":"","sources":["../../../src/schema/primitives/int.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD;;;GAGG;AACH,KAAK,YAAY,GAAG,cAAc,CAAC,MAAM,CAAC,GAAG;IAC3C,6DAA6D;IAC7D,GAAG,CAAC,CAAC,EAAE,MAAM,GAAG,YAAY,CAAC;IAC7B,6DAA6D;IAC7D,GAAG,CAAC,CAAC,EAAE,MAAM,GAAG,YAAY,CAAC;CAC9B,CAAC;AAkDF;;;;;;;;;GASG;AACH,eAAO,MAAM,GAAG,EAAE,YAAwB,CAAC"}
@@ -0,0 +1,43 @@
1
+ const MAX_SAFE_INTEGER_DIGITS = String(Number.MAX_SAFE_INTEGER).length;
2
+ function makeInt(config = {}) {
3
+ const { min, max } = config;
4
+ const fn = (v) => {
5
+ let i = 0;
6
+ let end = v.length;
7
+ while (i < end && v.charCodeAt(i) <= 32) i++;
8
+ while (end > i && v.charCodeAt(end - 1) <= 32) end--;
9
+ if (i >= end) throw new Error(`Expected integer, got "${v}"`);
10
+ let neg = false;
11
+ if (v.charCodeAt(i) === 45) {
12
+ neg = true;
13
+ i++;
14
+ }
15
+ if (i >= end) throw new Error(`Expected integer, got "${v}"`);
16
+ if (end - i > MAX_SAFE_INTEGER_DIGITS) throw new Error(`Value is not a safe integer: ${v}`);
17
+ let n = 0;
18
+ for (; i < end; i++) {
19
+ const d = v.charCodeAt(i) - 48;
20
+ if (d < 0 || d > 9) throw new Error(`Expected integer, got "${v}"`);
21
+ n = n * 10 + d;
22
+ }
23
+ const result = neg ? -n : n;
24
+ if (min !== void 0 && result < min) throw new Error(`Value too small: minimum is ${min}, got ${result}`);
25
+ if (max !== void 0 && result > max) throw new Error(`Value too large: maximum is ${max}, got ${result}`);
26
+ if (!Number.isSafeInteger(result)) throw new Error(`Value is not a safe integer: ${result}`);
27
+ return result;
28
+ };
29
+ fn._type = "int";
30
+ fn._required = true;
31
+ fn.jsonSchema = {
32
+ type: "integer",
33
+ ...config.min !== void 0 ? { minimum: config.min } : {},
34
+ ...config.max !== void 0 ? { maximum: config.max } : {}
35
+ };
36
+ fn.min = (n) => makeInt({ ...config, min: n });
37
+ fn.max = (n) => makeInt({ ...config, max: n });
38
+ return fn;
39
+ }
40
+ const int = makeInt();
41
+ export {
42
+ int
43
+ };
@@ -0,0 +1,26 @@
1
+ import type { TypedPrimitive } from "./index.js";
2
+ /**
3
+ * String primitive with optional chainable length and pattern constraints.
4
+ * Each builder method returns a new independent primitive so the original is never mutated.
5
+ */
6
+ type StringPrimitive = TypedPrimitive<string> & {
7
+ /** Returns a new primitive that rejects strings shorter than `n` characters. */
8
+ min(n: number): StringPrimitive;
9
+ /** Returns a new primitive that rejects strings longer than `n` characters. */
10
+ max(n: number): StringPrimitive;
11
+ /** Returns a new primitive that rejects strings not matching `regex`. */
12
+ pattern(regex: RegExp): StringPrimitive;
13
+ };
14
+ /**
15
+ * String primitive with optional chainable length and pattern constraints.
16
+ *
17
+ * @example
18
+ * ```ts
19
+ * string // any string
20
+ * string.min(3).max(50) // length range
21
+ * string.pattern(/^\S+@\S+\..+$/) // regex constraint
22
+ * ```
23
+ */
24
+ export declare const str: StringPrimitive;
25
+ export {};
26
+ //# sourceMappingURL=str.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"str.d.ts","sourceRoot":"","sources":["../../../src/schema/primitives/str.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD;;;GAGG;AACH,KAAK,eAAe,GAAG,cAAc,CAAC,MAAM,CAAC,GAAG;IAC9C,gFAAgF;IAChF,GAAG,CAAC,CAAC,EAAE,MAAM,GAAG,eAAe,CAAC;IAChC,+EAA+E;IAC/E,GAAG,CAAC,CAAC,EAAE,MAAM,GAAG,eAAe,CAAC;IAChC,yEAAyE;IACzE,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,eAAe,CAAC;CACzC,CAAC;AA+BF;;;;;;;;;GASG;AACH,eAAO,MAAM,GAAG,EAAE,eAA2B,CAAC"}
@@ -0,0 +1,30 @@
1
+ function makeStr(config = {}) {
2
+ const fn = (v) => {
3
+ if (config.min !== void 0 && v.length < config.min) {
4
+ throw new Error(`String too short: minimum length is ${config.min}, got ${v.length}`);
5
+ }
6
+ if (config.max !== void 0 && v.length > config.max) {
7
+ throw new Error(`String too long: maximum length is ${config.max}, got ${v.length}`);
8
+ }
9
+ if (config.pattern !== void 0 && !config.pattern.test(v)) {
10
+ throw new Error(`String does not match required pattern ${config.pattern}`);
11
+ }
12
+ return v;
13
+ };
14
+ fn._type = "string";
15
+ fn._required = true;
16
+ fn.jsonSchema = {
17
+ type: "string",
18
+ ...config.min !== void 0 ? { minLength: config.min } : {},
19
+ ...config.max !== void 0 ? { maxLength: config.max } : {},
20
+ ...config.pattern !== void 0 ? { pattern: config.pattern.source } : {}
21
+ };
22
+ fn.min = (n) => makeStr({ ...config, min: n });
23
+ fn.max = (n) => makeStr({ ...config, max: n });
24
+ fn.pattern = (regex) => makeStr({ ...config, pattern: regex });
25
+ return fn;
26
+ }
27
+ const str = makeStr();
28
+ export {
29
+ str
30
+ };
@@ -0,0 +1,33 @@
1
+ import type { TypedPrimitive } from "./index.js";
2
+ /**
3
+ * Text primitive with optional chainable length and pattern constraints.
4
+ * Each builder method returns a new independent primitive so the original is never mutated.
5
+ */
6
+ type TextPrimitive = TypedPrimitive<string> & {
7
+ /** Returns a new primitive that rejects strings shorter than `n` characters. */
8
+ min(n: number): TextPrimitive;
9
+ /** Returns a new primitive that rejects strings longer than `n` characters. */
10
+ max(n: number): TextPrimitive;
11
+ /** Returns a new primitive that rejects strings not matching `regex`. */
12
+ pattern(regex: RegExp): TextPrimitive;
13
+ };
14
+ /**
15
+ * Text primitive with optional chainable length and pattern constraints.
16
+ *
17
+ * Text is always escaped when serialized to JSON, so it is safe for untrusted input and
18
+ * can contain arbitrary Unicode characters including newlines. In contrast, the
19
+ * `string` primitive is intended for short single-line strings without special
20
+ * characters (e.g. names, titles) and is not escaped when serialized, so it will
21
+ * throw an error on the consumer side if the input contains special characters that
22
+ * would break JSON syntax.
23
+ *
24
+ * @example
25
+ * ```ts
26
+ * text // any text
27
+ * text.min(3).max(50) // length range
28
+ * text.pattern(/^\S+@\S+\..+$/) // regex constraint
29
+ * ```
30
+ */
31
+ export declare const text: TextPrimitive;
32
+ export {};
33
+ //# sourceMappingURL=text.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"text.d.ts","sourceRoot":"","sources":["../../../src/schema/primitives/text.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD;;;GAGG;AACH,KAAK,aAAa,GAAG,cAAc,CAAC,MAAM,CAAC,GAAG;IAC5C,gFAAgF;IAChF,GAAG,CAAC,CAAC,EAAE,MAAM,GAAG,aAAa,CAAC;IAC9B,+EAA+E;IAC/E,GAAG,CAAC,CAAC,EAAE,MAAM,GAAG,aAAa,CAAC;IAC9B,yEAAyE;IACzE,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,aAAa,CAAC;CACvC,CAAC;AA+BF;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,IAAI,EAAE,aAA0B,CAAC"}
@@ -0,0 +1,30 @@
1
+ function makeText(config = {}) {
2
+ const fn = (v) => {
3
+ if (config.min !== void 0 && v.length < config.min) {
4
+ throw new Error(`String too short: minimum length is ${config.min}, got ${v.length}`);
5
+ }
6
+ if (config.max !== void 0 && v.length > config.max) {
7
+ throw new Error(`String too long: maximum length is ${config.max}, got ${v.length}`);
8
+ }
9
+ if (config.pattern !== void 0 && !config.pattern.test(v)) {
10
+ throw new Error(`String does not match required pattern ${config.pattern}`);
11
+ }
12
+ return v;
13
+ };
14
+ fn._type = "text";
15
+ fn._required = true;
16
+ fn.jsonSchema = {
17
+ type: "string",
18
+ ...config.min !== void 0 ? { minLength: config.min } : {},
19
+ ...config.max !== void 0 ? { maxLength: config.max } : {},
20
+ ...config.pattern !== void 0 ? { pattern: config.pattern.source } : {}
21
+ };
22
+ fn.min = (n) => makeText({ ...config, min: n });
23
+ fn.max = (n) => makeText({ ...config, max: n });
24
+ fn.pattern = (regex) => makeText({ ...config, pattern: regex });
25
+ return fn;
26
+ }
27
+ const text = makeText();
28
+ export {
29
+ text
30
+ };
@@ -0,0 +1,7 @@
1
+ import type { TypedPrimitive } from "./index.js";
2
+ /**
3
+ * UUID v4 primitive. Validates the canonical 8-4-4-4-12 hyphenated format.
4
+ */
5
+ declare const uuid: TypedPrimitive<string>;
6
+ export { uuid };
7
+ //# sourceMappingURL=uuid.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"uuid.d.ts","sourceRoot":"","sources":["../../../src/schema/primitives/uuid.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAIjD;;GAEG;AACH,QAAA,MAAM,IAAI,EAAE,cAAc,CAAC,MAAM,CAQhC,CAAC;AAEF,OAAO,EAAE,IAAI,EAAE,CAAC"}
@@ -0,0 +1,13 @@
1
+ const UUID_V4_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
2
+ const uuid = Object.assign(
3
+ (v) => {
4
+ if (!UUID_V4_RE.test(v)) {
5
+ throw new Error(`Expected UUID v4, got "${v}"`);
6
+ }
7
+ return v;
8
+ },
9
+ { _type: "uuid", _required: true, jsonSchema: { type: "string", format: "uuid" } }
10
+ );
11
+ export {
12
+ uuid
13
+ };
@@ -0,0 +1,167 @@
1
+ import type { AnyDescriptorValue, InferSchemaShape } from "./internal/types/inference.js";
2
+ import type { TypedPrimitive } from "./primitives/index.js";
3
+ import { SCHEMA_BRAND } from "./internal/token/symbols.js";
4
+ /** @internal One-item tuple used to declare an array schema token. */
5
+ type TopLevelArraySchemaInput<T> = readonly [SchemaToken<T>];
6
+ /** @internal One-item tuple used to declare a record schema token. */
7
+ type TopLevelRecordSchemaInput<T> = readonly [{
8
+ $record: SchemaToken<T>;
9
+ }];
10
+ /**
11
+ * Single field-level parse error reported by {@link SchemaToken.safeParse}.
12
+ */
13
+ export type FieldError = {
14
+ path: string;
15
+ message: string;
16
+ received: string;
17
+ };
18
+ /**
19
+ * Collection of field-level errors produced by a failed schema parse.
20
+ */
21
+ export type ValidationError = {
22
+ fields: FieldError[];
23
+ };
24
+ /**
25
+ * Result of a schema parse operation.
26
+ *
27
+ * On success, `data` holds the parsed value typed as `T`. On failure, `error`
28
+ * holds a {@link ValidationError} describing which fields failed.
29
+ */
30
+ export type SafeParseResult<T> = {
31
+ success: true;
32
+ data: T;
33
+ } | {
34
+ success: false;
35
+ error: ValidationError;
36
+ };
37
+ /**
38
+ * Any value that can appear in a JSON payload.
39
+ */
40
+ export type JsonValue = string | number | boolean | null | JsonValue[] | {
41
+ [key: string]: JsonValue;
42
+ };
43
+ /**
44
+ * JSON object with string keys and {@link JsonValue} values.
45
+ */
46
+ export type JsonObject = {
47
+ [key: string]: JsonValue;
48
+ };
49
+ /**
50
+ * Runtime token representing a schema, with its value type erased.
51
+ *
52
+ * Used wherever a schema's identity is needed but not its output type, for
53
+ * example by the compiled serializer and JSON Schema exporter.
54
+ */
55
+ export type OpaqueSchemaToken = {
56
+ readonly [SCHEMA_BRAND]: true;
57
+ };
58
+ /**
59
+ * Represents a type `T` that can be parsed from JSON input.
60
+ *
61
+ * Intentionally not a constructor: schema tokens cannot be extended. Use
62
+ * {@link model} when an extendable DTO base class is required.
63
+ */
64
+ export type SchemaToken<T> = OpaqueSchemaToken & {
65
+ /** Parses raw input (JSON string, ArrayBuffer, or plain object) into `T`. */
66
+ safeParse(raw: ArrayBuffer | string | JsonValue): SafeParseResult<T>;
67
+ /** Marks this schema token as optional within a parent descriptor. */
68
+ optional(): SchemaToken<T>;
69
+ };
70
+ /**
71
+ * Extracts the union of all concrete discriminant values for key `K` across
72
+ * the members of the union type `T`.
73
+ *
74
+ * Useful when building generic utilities over discriminated schemas. Constrains
75
+ * the `branches` argument of the discriminated {@link schema} overload so every
76
+ * possible discriminant value must be handled.
77
+ */
78
+ export type DiscriminantValues<T, K extends keyof T> = T extends Record<K, infer V extends string | number | symbol> ? V : never;
79
+ /**
80
+ * For a union member of `T` whose discriminant key `K` equals `V`, produces
81
+ * the shape of that member with `K` omitted.
82
+ *
83
+ * Useful when building generic utilities over discriminated schemas.
84
+ */
85
+ export type BranchShape<T, K extends keyof T, V extends DiscriminantValues<T, K>> = T extends Record<K, V> ? Omit<T, K> : never;
86
+ /**
87
+ * Accepted value types for a single field within a schema descriptor.
88
+ *
89
+ * A field can be backed by either a {@link TypedPrimitive} coercer (e.g.
90
+ * `int`, `str`, `uuid`) or a nested {@link SchemaToken} produced by
91
+ * {@link schema}, enabling structural composition.
92
+ *
93
+ * @template T The TypeScript type the descriptor entry produces after parsing.
94
+ */
95
+ export type DescriptorValue<T> = TypedPrimitive<T> | SchemaToken<T>;
96
+ /**
97
+ * Creates a schema token that parses a JSON object field-by-field using the
98
+ * provided descriptor map.
99
+ *
100
+ * @example
101
+ * ```ts
102
+ * const UserSchema = schema({
103
+ * id: uuid,
104
+ * name: string,
105
+ * });
106
+ *
107
+ * // Manual parsing:
108
+ * const result = UserSchema.safeParse(requestBody);
109
+ *
110
+ * // Nested inside another schema:
111
+ * const EnvelopeSchema = schema({
112
+ * user: UserSchema,
113
+ * });
114
+ * ```
115
+ */
116
+ export declare function schema<D extends Record<string, AnyDescriptorValue>>(descriptor: D): SchemaToken<InferSchemaShape<D>>;
117
+ /**
118
+ * Creates a schema token for a JSON array whose items are parsed by the
119
+ * provided nested schema token.
120
+ *
121
+ * The returned token can be used as a top-level parser or nested within
122
+ * another object schema descriptor.
123
+ *
124
+ * @example
125
+ * ```ts
126
+ * const WorldSchema = schema({ id: int, randomNumber: int });
127
+ * const WorldListSchema = schema([WorldSchema]);
128
+ *
129
+ * const BatchSchema = schema({
130
+ * worlds: schema([WorldSchema]).optional(),
131
+ * });
132
+ * ```
133
+ */
134
+ export declare function schema<T>(items: TopLevelArraySchemaInput<T>): SchemaToken<T[]>;
135
+ /**
136
+ * Creates a schema token for a JSON object with dynamic string keys and uniform
137
+ * values, all validated by the provided nested schema token.
138
+ *
139
+ * Pass `[{ $record: ValueSchema }]` to use this overload.
140
+ *
141
+ * @example
142
+ * ```ts
143
+ * const TransportCfgSchema = schema({ level: enums(["debug", "info"]).optional() });
144
+ * const TransportsSchema = schema([{ $record: TransportCfgSchema }]);
145
+ * ```
146
+ */
147
+ export declare function schema<T>(items: TopLevelRecordSchemaInput<T>): SchemaToken<Record<string, T>>;
148
+ /**
149
+ * Creates a schema token that selects a branch descriptor based on the value
150
+ * of `discriminant` before parsing the remaining fields.
151
+ *
152
+ * @example
153
+ * ```ts
154
+ * const PetSchema = schema<Cat | Dog>('kind', {
155
+ * cat: { lives: int },
156
+ * dog: { breed: string },
157
+ * });
158
+ *
159
+ * ```
160
+ */
161
+ export declare function schema<T extends object, _ extends "union", K extends keyof T & string = keyof T & string>(discriminant: K, branches: {
162
+ [V in DiscriminantValues<T, K>]: {
163
+ [F in keyof BranchShape<T, K, V>]: DescriptorValue<BranchShape<T, K, V>[F]>;
164
+ };
165
+ }): SchemaToken<T>;
166
+ export {};
167
+ //# sourceMappingURL=schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/schema/schema.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,74 @@
1
+ import { arraySafeParse } from "./internal/parser/array.js";
2
+ import { discriminatedSafeParse } from "./internal/parser/discriminated.js";
3
+ import { flatSafeParse } from "./internal/parser/object.js";
4
+ import { recordSafeParse } from "./internal/parser/record.js";
5
+ import { makeOptionalSchemaToken } from "./internal/token/optionality.js";
6
+ import { SCHEMA_BRAND, SCHEMA_DESCRIPTOR, SCHEMA_REQUIRED } from "./internal/token/symbols.js";
7
+ function schema(descriptorOrDiscriminant, branches) {
8
+ if (Array.isArray(descriptorOrDiscriminant)) {
9
+ if (descriptorOrDiscriminant.length !== 1) {
10
+ throw new Error("Top-level array schemas must be declared with exactly one item schema.");
11
+ }
12
+ const first = descriptorOrDiscriminant[0];
13
+ if (first !== null && typeof first === "object" && "$record" in first) {
14
+ const valueSchema = first.$record;
15
+ const token3 = {
16
+ [SCHEMA_BRAND]: true,
17
+ [SCHEMA_REQUIRED]: true,
18
+ [SCHEMA_DESCRIPTOR]: descriptorOrDiscriminant,
19
+ optional() {
20
+ return makeOptionalSchemaToken(token3);
21
+ },
22
+ safeParse(raw) {
23
+ return recordSafeParse(raw, valueSchema);
24
+ }
25
+ };
26
+ return token3;
27
+ }
28
+ const items = descriptorOrDiscriminant;
29
+ const itemSchema = items[0];
30
+ const token2 = {
31
+ [SCHEMA_BRAND]: true,
32
+ [SCHEMA_REQUIRED]: true,
33
+ [SCHEMA_DESCRIPTOR]: items,
34
+ optional() {
35
+ return makeOptionalSchemaToken(token2);
36
+ },
37
+ safeParse(raw) {
38
+ return arraySafeParse(raw, itemSchema);
39
+ }
40
+ };
41
+ return token2;
42
+ }
43
+ if (typeof descriptorOrDiscriminant === "string" || typeof descriptorOrDiscriminant === "number" || typeof descriptorOrDiscriminant === "symbol") {
44
+ const discriminant = descriptorOrDiscriminant;
45
+ const token2 = {
46
+ [SCHEMA_BRAND]: true,
47
+ [SCHEMA_REQUIRED]: true,
48
+ [SCHEMA_DESCRIPTOR]: { discriminant, branches },
49
+ optional() {
50
+ return makeOptionalSchemaToken(token2);
51
+ },
52
+ safeParse(raw) {
53
+ return discriminatedSafeParse(raw, discriminant, branches);
54
+ }
55
+ };
56
+ return token2;
57
+ }
58
+ const descriptor = descriptorOrDiscriminant;
59
+ const token = {
60
+ [SCHEMA_BRAND]: true,
61
+ [SCHEMA_REQUIRED]: true,
62
+ [SCHEMA_DESCRIPTOR]: descriptor,
63
+ optional() {
64
+ return makeOptionalSchemaToken(token);
65
+ },
66
+ safeParse(raw) {
67
+ return flatSafeParse(raw, descriptor);
68
+ }
69
+ };
70
+ return token;
71
+ }
72
+ export {
73
+ schema
74
+ };
@@ -0,0 +1,15 @@
1
+ /**
2
+ * @internal
3
+ *
4
+ * Unique symbol stored as a static property on every class generated by
5
+ * {@link model}. Its value is the compiled JSON serializer produced eagerly
6
+ * at class-declaration time by {@link compileSerializer}.
7
+ *
8
+ * Consumers outside the lib package (e.g. the core transport layer) must
9
+ * access this symbol via {@link Symbol.for} with the same well-known key
10
+ * rather than importing this module directly.
11
+ *
12
+ * Well-known key: `"@flare-ts/schema/compiled-serializer"`
13
+ */
14
+ export declare const COMPILED_SERIALIZER: unique symbol;
15
+ //# sourceMappingURL=symbol.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"symbol.d.ts","sourceRoot":"","sources":["../../src/schema/symbol.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,mBAAmB,EAAE,OAAO,MAE/B,CAAC"}
@@ -0,0 +1,6 @@
1
+ const COMPILED_SERIALIZER = /* @__PURE__ */ Symbol.for(
2
+ "@flare-ts/schema/compiled-serializer"
3
+ );
4
+ export {
5
+ COMPILED_SERIALIZER
6
+ };