pema 0.4.0 → 0.6.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 (264) hide show
  1. package/lib/private/ArrayType.d.ts +2 -1
  2. package/lib/private/ArrayType.js +29 -41
  3. package/lib/private/BigIntType.d.ts +2 -2
  4. package/lib/private/BigUintType.d.ts +2 -2
  5. package/lib/private/BlobType.d.ts +2 -2
  6. package/lib/private/BlobType.js +2 -2
  7. package/lib/private/BooleanType.d.ts +2 -2
  8. package/lib/private/BooleanType.js +4 -4
  9. package/lib/private/BuiltinType.d.ts +1 -2
  10. package/lib/private/BuiltinType.js +3 -8
  11. package/lib/private/ConstructorType.d.ts +5 -2
  12. package/lib/private/ConstructorType.js +7 -5
  13. package/lib/private/DataType.d.ts +5 -1
  14. package/lib/private/DateType.d.ts +2 -2
  15. package/lib/private/DateType.js +2 -2
  16. package/lib/private/DefaultType.js +3 -6
  17. package/lib/private/EnumType.d.ts +21 -0
  18. package/lib/private/EnumType.js +30 -0
  19. package/lib/private/FileType.d.ts +2 -2
  20. package/lib/private/FileType.js +2 -2
  21. package/lib/private/FunctionType.d.ts +15 -0
  22. package/lib/private/FunctionType.js +20 -0
  23. package/lib/private/GenericType.d.ts +1 -1
  24. package/lib/private/InferInputSchema.d.ts +7 -17
  25. package/lib/private/InferStore.d.ts +1 -1
  26. package/lib/private/IntType.d.ts +2 -2
  27. package/lib/private/IsType.d.ts +19 -0
  28. package/lib/private/IsType.js +29 -0
  29. package/lib/private/Issue.d.ts +3 -1
  30. package/lib/private/IssueType.d.ts +3 -0
  31. package/lib/private/IssueType.js +2 -0
  32. package/lib/private/JSONType.d.ts +26 -0
  33. package/lib/private/JSONType.js +41 -0
  34. package/lib/private/LiteralType.d.ts +5 -2
  35. package/lib/private/LiteralType.js +11 -5
  36. package/lib/private/NormalizeSchema.d.ts +4 -6
  37. package/lib/private/NullType.js +3 -5
  38. package/lib/private/NumberType.d.ts +1 -1
  39. package/lib/private/NumberType.js +1 -1
  40. package/lib/private/NumericType.d.ts +2 -2
  41. package/lib/private/ObjectType.d.ts +13 -4
  42. package/lib/private/ObjectType.js +24 -11
  43. package/lib/private/OmitType.d.ts +1 -1
  44. package/lib/private/OmitType.js +7 -6
  45. package/lib/private/ParseError.d.ts +6 -2
  46. package/lib/private/ParseError.js +25 -15
  47. package/lib/private/ParseOptions.d.ts +1 -1
  48. package/lib/private/Parsed.d.ts +2 -1
  49. package/lib/private/Parsed.js +3 -0
  50. package/lib/private/PartialType.js +8 -10
  51. package/lib/private/Partialable.d.ts +1 -1
  52. package/lib/private/PrimitiveType.d.ts +0 -1
  53. package/lib/private/PrimitiveType.js +23 -22
  54. package/lib/private/PureType.d.ts +1 -1
  55. package/lib/private/RecordType.js +14 -39
  56. package/lib/private/Schema.d.ts +1 -1
  57. package/lib/private/Serialized.d.ts +18 -4
  58. package/lib/private/{Storeable.d.ts → Storable.d.ts} +3 -3
  59. package/lib/private/{Storeable.js → Storable.js} +2 -2
  60. package/lib/private/StoreSchema.d.ts +3 -6
  61. package/lib/private/StoreType.d.ts +5 -1
  62. package/lib/private/StoreType.js +22 -2
  63. package/lib/private/StringType.d.ts +2 -3
  64. package/lib/private/StringType.js +7 -13
  65. package/lib/private/TupleType.d.ts +2 -2
  66. package/lib/private/TupleType.js +19 -14
  67. package/lib/private/Type.d.ts +1 -1
  68. package/lib/private/URLType.d.ts +2 -2
  69. package/lib/private/URLType.js +2 -2
  70. package/lib/private/UUIDType.d.ts +17 -0
  71. package/lib/private/UUIDType.js +33 -0
  72. package/lib/private/UUIDV4Type.d.ts +13 -0
  73. package/lib/private/UUIDV4Type.js +23 -0
  74. package/lib/private/UUIDV7Type.d.ts +13 -0
  75. package/lib/private/UUIDV7Type.js +23 -0
  76. package/lib/private/UintType.d.ts +2 -2
  77. package/lib/private/UnionType.d.ts +3 -3
  78. package/lib/private/UnionType.js +11 -13
  79. package/lib/private/VirtualType.js +2 -3
  80. package/lib/private/coerce/bigint.d.ts +1 -1
  81. package/lib/private/coerce/bigint.js +4 -6
  82. package/lib/private/coerce/float.d.ts +2 -0
  83. package/lib/private/coerce/float.js +8 -0
  84. package/lib/private/coerce/int.d.ts +1 -1
  85. package/lib/private/coerce/int.js +7 -5
  86. package/lib/private/constructor.d.ts +1 -1
  87. package/lib/private/dict.d.ts +11 -0
  88. package/lib/private/dict.js +6 -0
  89. package/lib/private/enum.d.ts +3 -0
  90. package/lib/private/enum.js +5 -0
  91. package/lib/private/errors.d.ts +21 -0
  92. package/lib/private/errors.js +53 -0
  93. package/lib/private/function.d.ts +7 -0
  94. package/lib/private/function.js +6 -0
  95. package/lib/private/index.d.ts +79 -30
  96. package/lib/private/index.js +20 -2
  97. package/lib/private/is.d.ts +4 -0
  98. package/lib/private/is.js +3 -0
  99. package/lib/private/json/JSONIssue.d.ts +2 -0
  100. package/lib/private/json/JSONPayload.d.ts +1 -1
  101. package/lib/private/json.d.ts +5 -0
  102. package/lib/private/json.js +5 -0
  103. package/lib/private/normalize.js +2 -3
  104. package/lib/private/object.d.ts +3 -4
  105. package/lib/private/object.js +2 -2
  106. package/lib/private/omit.d.ts +1 -1
  107. package/lib/private/path/join.d.ts +1 -1
  108. package/lib/private/path/next.d.ts +1 -1
  109. package/lib/private/path/rebase.d.ts +1 -1
  110. package/lib/private/schema-errors.d.ts +16 -0
  111. package/lib/private/schema-errors.js +17 -0
  112. package/lib/private/spec/bigint.d.ts +1 -1
  113. package/lib/private/spec/bigint.js +30 -41
  114. package/lib/private/spec/biguint.d.ts +1 -1
  115. package/lib/private/spec/biguint.js +29 -45
  116. package/lib/private/spec/int.d.ts +1 -1
  117. package/lib/private/spec/int.js +27 -38
  118. package/lib/private/spec/uint.d.ts +1 -1
  119. package/lib/private/spec/uint.js +31 -43
  120. package/lib/private/test.d.ts +34 -0
  121. package/lib/private/test.js +107 -0
  122. package/lib/private/uuid.d.ts +4 -0
  123. package/lib/private/uuid.js +3 -0
  124. package/lib/private/validator/ends-with.d.ts +1 -2
  125. package/lib/private/validator/ends-with.js +8 -10
  126. package/lib/private/validator/f32.js +3 -8
  127. package/lib/private/validator/integer.d.ts +1 -2
  128. package/lib/private/validator/integer.js +7 -11
  129. package/lib/private/validator/isotime.js +8 -10
  130. package/lib/private/validator/length.js +12 -20
  131. package/lib/private/validator/max.js +15 -16
  132. package/lib/private/validator/min.js +15 -16
  133. package/lib/private/validator/port.d.ts +1 -2
  134. package/lib/private/validator/port.js +6 -9
  135. package/lib/private/validator/range.js +7 -13
  136. package/lib/private/validator/regex.d.ts +1 -1
  137. package/lib/private/validator/regex.js +5 -9
  138. package/lib/private/validator/starts-with.d.ts +1 -2
  139. package/lib/private/validator/starts-with.js +8 -10
  140. package/lib/private/validator/unique-by.d.ts +1 -1
  141. package/lib/private/validator/unique-by.js +8 -14
  142. package/lib/private/validator/unique-with.d.ts +1 -1
  143. package/lib/private/validator/unique-with.js +3 -7
  144. package/lib/private/validator/unique.js +2 -6
  145. package/lib/private/validator/values.d.ts +1 -1
  146. package/lib/private/validator/values.js +5 -8
  147. package/lib/public/StoreType.d.ts +1 -1
  148. package/lib/public/index.d.ts +1 -9
  149. package/lib/public/index.js +0 -9
  150. package/package.json +18 -15
  151. package/lib/private/DecrementDepth.d.ts +0 -3
  152. package/lib/private/DecrementDepth.js +0 -2
  153. package/lib/private/InferSchema.d.ts +0 -20
  154. package/lib/private/InferSchema.js +0 -2
  155. package/lib/private/PrimaryType.d.ts +0 -14
  156. package/lib/private/PrimaryType.js +0 -26
  157. package/lib/private/SchemaError.d.ts +0 -4
  158. package/lib/private/SchemaError.js +0 -8
  159. package/lib/private/error/fail.d.ts +0 -3
  160. package/lib/private/error/fail.js +0 -5
  161. package/lib/private/error/schemafail.d.ts +0 -3
  162. package/lib/private/error/schemafail.js +0 -5
  163. package/lib/private/error.d.ts +0 -4
  164. package/lib/private/error.js +0 -11
  165. package/lib/private/expect.d.ts +0 -22
  166. package/lib/private/expect.js +0 -32
  167. package/lib/private/expected.d.ts +0 -3
  168. package/lib/private/expected.js +0 -11
  169. package/lib/private/primary.d.ts +0 -4
  170. package/lib/private/primary.js +0 -3
  171. package/lib/private/test/messages-of.d.ts +0 -3
  172. package/lib/private/test/messages-of.js +0 -4
  173. package/lib/private/test/paths-of.d.ts +0 -3
  174. package/lib/private/test/paths-of.js +0 -4
  175. package/lib/private/test/throws-issues.d.ts +0 -4
  176. package/lib/private/test/throws-issues.js +0 -13
  177. package/lib/private/validator/uuid.d.ts +0 -3
  178. package/lib/private/validator/uuid.js +0 -4
  179. package/lib/public/DataType.d.ts +0 -2
  180. package/lib/public/DataType.js +0 -2
  181. package/lib/public/Id.d.ts +0 -2
  182. package/lib/public/Id.js +0 -2
  183. package/lib/public/InferStore.d.ts +0 -2
  184. package/lib/public/InferStore.js +0 -2
  185. package/lib/public/InferStoreOut.d.ts +0 -2
  186. package/lib/public/InferStoreOut.js +0 -2
  187. package/lib/public/Issue.d.ts +0 -2
  188. package/lib/public/Issue.js +0 -2
  189. package/lib/public/JSONPayload.d.ts +0 -2
  190. package/lib/public/JSONPayload.js +0 -2
  191. package/lib/public/OmitType.d.ts +0 -2
  192. package/lib/public/OmitType.js +0 -2
  193. package/lib/public/Schema.d.ts +0 -2
  194. package/lib/public/Schema.js +0 -2
  195. package/lib/public/Serialized.d.ts +0 -2
  196. package/lib/public/Serialized.js +0 -2
  197. package/lib/public/StoreId.d.ts +0 -2
  198. package/lib/public/StoreId.js +0 -2
  199. package/lib/public/StoreSchema.d.ts +0 -2
  200. package/lib/public/StoreSchema.js +0 -2
  201. package/lib/public/array.d.ts +0 -3
  202. package/lib/public/array.js +0 -3
  203. package/lib/public/bigint.d.ts +0 -2
  204. package/lib/public/bigint.js +0 -2
  205. package/lib/public/biguint.d.ts +0 -2
  206. package/lib/public/biguint.js +0 -2
  207. package/lib/public/blob.d.ts +0 -2
  208. package/lib/public/blob.js +0 -2
  209. package/lib/public/boolean.d.ts +0 -3
  210. package/lib/public/boolean.js +0 -3
  211. package/lib/public/constructor.d.ts +0 -3
  212. package/lib/public/constructor.js +0 -3
  213. package/lib/public/date.d.ts +0 -2
  214. package/lib/public/date.js +0 -2
  215. package/lib/public/f32.d.ts +0 -2
  216. package/lib/public/f32.js +0 -2
  217. package/lib/public/f64.d.ts +0 -2
  218. package/lib/public/f64.js +0 -2
  219. package/lib/public/file.d.ts +0 -2
  220. package/lib/public/file.js +0 -2
  221. package/lib/public/i128.d.ts +0 -2
  222. package/lib/public/i128.js +0 -2
  223. package/lib/public/i16.d.ts +0 -2
  224. package/lib/public/i16.js +0 -2
  225. package/lib/public/i32.d.ts +0 -2
  226. package/lib/public/i32.js +0 -2
  227. package/lib/public/i64.d.ts +0 -2
  228. package/lib/public/i64.js +0 -2
  229. package/lib/public/i8.d.ts +0 -2
  230. package/lib/public/i8.js +0 -2
  231. package/lib/public/int.d.ts +0 -2
  232. package/lib/public/int.js +0 -2
  233. package/lib/public/number.d.ts +0 -3
  234. package/lib/public/number.js +0 -3
  235. package/lib/public/object.d.ts +0 -2
  236. package/lib/public/object.js +0 -2
  237. package/lib/public/optional.d.ts +0 -2
  238. package/lib/public/optional.js +0 -2
  239. package/lib/public/primary.d.ts +0 -2
  240. package/lib/public/primary.js +0 -2
  241. package/lib/public/pure.d.ts +0 -2
  242. package/lib/public/pure.js +0 -2
  243. package/lib/public/record.d.ts +0 -3
  244. package/lib/public/record.js +0 -3
  245. package/lib/public/string.d.ts +0 -3
  246. package/lib/public/string.js +0 -3
  247. package/lib/public/symbol.d.ts +0 -2
  248. package/lib/public/symbol.js +0 -2
  249. package/lib/public/u128.d.ts +0 -2
  250. package/lib/public/u128.js +0 -2
  251. package/lib/public/u16.d.ts +0 -2
  252. package/lib/public/u16.js +0 -2
  253. package/lib/public/u32.d.ts +0 -2
  254. package/lib/public/u32.js +0 -2
  255. package/lib/public/u64.d.ts +0 -2
  256. package/lib/public/u64.js +0 -2
  257. package/lib/public/u8.d.ts +0 -2
  258. package/lib/public/u8.js +0 -2
  259. package/lib/public/uint.d.ts +0 -3
  260. package/lib/public/uint.js +0 -3
  261. package/lib/public/union.d.ts +0 -3
  262. package/lib/public/union.js +0 -3
  263. package/lib/public/unknown.d.ts +0 -3
  264. package/lib/public/unknown.js +0 -2
@@ -0,0 +1,26 @@
1
+ import DefaultType from "#DefaultType";
2
+ import type Infer from "#Infer";
3
+ import OptionalType from "#OptionalType";
4
+ import type Parsed from "#Parsed";
5
+ import type ParseOptions from "#ParseOptions";
6
+ import Storable from "#Storable";
7
+ import type { JSONValue } from "@rcompat/type";
8
+ export type ParsedJSON = Parsed<JSONValue>;
9
+ type JSONInput = ParsedJSON | undefined;
10
+ type JSONInfer<S extends JSONInput> = S extends ParsedJSON ? Infer<S> : JSONValue;
11
+ export default class JSONType<S extends JSONInput = undefined> extends Storable<"json", JSONInfer<S>> {
12
+ #private;
13
+ constructor(inner?: S);
14
+ get name(): "json";
15
+ get datatype(): "json";
16
+ optional(): OptionalType<this>;
17
+ default(value: (() => Infer<this>) | Infer<this>): DefaultType<this, Infer<this>>;
18
+ parse(x: unknown, options?: ParseOptions): Infer<this>;
19
+ toJSON(): {
20
+ of?: import("./Serialized.js").default | undefined;
21
+ type: "json";
22
+ datatype: "json";
23
+ };
24
+ }
25
+ export {};
26
+ //# sourceMappingURL=JSONType.d.ts.map
@@ -0,0 +1,41 @@
1
+ import DefaultType from "#DefaultType";
2
+ import E from "#errors";
3
+ import OptionalType from "#OptionalType";
4
+ import Storable from "#Storable";
5
+ import is from "@rcompat/is";
6
+ export default class JSONType extends Storable {
7
+ #inner;
8
+ constructor(inner) {
9
+ super();
10
+ this.#inner = inner;
11
+ }
12
+ get name() {
13
+ return "json";
14
+ }
15
+ get datatype() {
16
+ return "json";
17
+ }
18
+ optional() {
19
+ return new OptionalType(this);
20
+ }
21
+ default(value) {
22
+ return new DefaultType(this, value);
23
+ }
24
+ parse(x, options = {}) {
25
+ if (this.#inner !== undefined) {
26
+ // delegate to inner schema for typed validation
27
+ return this.#inner.parse(x, options);
28
+ }
29
+ if (!is.json(x))
30
+ throw E.invalid_type(x, "json", options);
31
+ return JSON.parse(JSON.stringify(x));
32
+ }
33
+ toJSON() {
34
+ return {
35
+ type: "json",
36
+ datatype: "json",
37
+ ...(this.#inner !== undefined && { of: this.#inner.toJSON() }),
38
+ };
39
+ }
40
+ }
41
+ //# sourceMappingURL=JSONType.js.map
@@ -1,14 +1,17 @@
1
+ import DefaultType from "#DefaultType";
1
2
  import GenericType from "#GenericType";
2
3
  import type Infer from "#Infer";
4
+ import OptionalType from "#OptionalType";
3
5
  import type ParseOptions from "#ParseOptions";
4
6
  type Literal = string | boolean | number;
5
- type InferLiteral<T extends Literal> = T;
6
- export default class LiteralType<T extends Literal> extends GenericType<T, InferLiteral<T>, "LiteralType"> {
7
+ export default class LiteralType<T extends Literal> extends GenericType<T, T, "LiteralType"> {
7
8
  #private;
8
9
  constructor(literal: T);
9
10
  static new<T extends Literal>(literal: T): LiteralType<T>;
10
11
  static get Literal(): Literal;
11
12
  get name(): string;
13
+ optional(): OptionalType<this>;
14
+ default(value: (() => T) | T): DefaultType<this, T>;
12
15
  parse(x: unknown, options?: ParseOptions): Infer<this>;
13
16
  toJSON(): {
14
17
  type: "literal";
@@ -1,6 +1,7 @@
1
- import error from "#error";
1
+ import DefaultType from "#DefaultType";
2
2
  import GenericType from "#GenericType";
3
- import ParseError from "#ParseError";
3
+ import OptionalType from "#OptionalType";
4
+ import E from "#errors";
4
5
  export default class LiteralType extends GenericType {
5
6
  #literal;
6
7
  constructor(literal) {
@@ -16,10 +17,15 @@ export default class LiteralType extends GenericType {
16
17
  get name() {
17
18
  return JSON.stringify(this.#literal);
18
19
  }
20
+ optional() {
21
+ return new OptionalType(this);
22
+ }
23
+ default(value) {
24
+ return new DefaultType(this, value);
25
+ }
19
26
  parse(x, options = {}) {
20
- if (x !== this.#literal) {
21
- throw new ParseError(error(this.name, x, options));
22
- }
27
+ if (x !== this.#literal)
28
+ throw E.invalid_type(x, this.name, options);
23
29
  return x;
24
30
  }
25
31
  toJSON() {
@@ -7,15 +7,13 @@ import type Parsed from "#Parsed";
7
7
  import type Schema from "#Schema";
8
8
  import type TupleType from "#TupleType";
9
9
  import type UndefinedType from "#UndefinedType";
10
- import type AbstractNewable from "@rcompat/type/AbstractNewable";
11
- import type EO from "@rcompat/type/EO";
12
- type IsEmptyObject<T> = keyof T extends never ? true : false;
10
+ import type { AbstractNewable } from "@rcompat/type";
13
11
  type NormalizeSchemaArray<T extends Schema[]> = {
14
12
  [K in keyof T]: NormalizeSchema<T[K]>;
15
13
  };
16
- type NormalizeSchemaObject<T extends Record<string, unknown>> = IsEmptyObject<T> extends true ? EO : {
17
- -readonly [K in keyof T]: T[K] extends Parsed<unknown> ? T[K] : NormalizeSchema<T[K]>;
14
+ export type NormalizeSchemaObject<T extends Record<string, unknown>> = {
15
+ -readonly [K in keyof T]: NormalizeSchema<T[K]>;
18
16
  };
19
- type NormalizeSchema<S> = S extends Parsed<unknown> ? S : S extends null ? NullType : S extends undefined ? UndefinedType : S extends string ? LiteralType<S> : S extends number ? LiteralType<S> : S extends boolean ? LiteralType<S> : S extends AbstractNewable ? ConstructorType<S> : S extends [infer O] ? O extends Schema ? ArrayType<NormalizeSchema<O>> : never : S extends Schema[] ? TupleType<NormalizeSchemaArray<S>> : S extends Record<string, unknown> ? ObjectType<NormalizeSchemaObject<S>> : never;
17
+ type NormalizeSchema<S> = S extends Parsed<unknown> ? S : S extends null ? NullType : S extends undefined ? UndefinedType : S extends string | number | boolean ? LiteralType<S> : S extends AbstractNewable ? ConstructorType<S> : S extends [Schema] ? ArrayType<NormalizeSchema<S[0]>> : S extends Schema[] ? TupleType<NormalizeSchemaArray<S>> : S extends Record<string, unknown> ? ObjectType<NormalizeSchemaObject<S>> : never;
20
18
  export type { NormalizeSchema as default };
21
19
  //# sourceMappingURL=NormalizeSchema.d.ts.map
@@ -1,14 +1,12 @@
1
- import error from "#error";
2
- import ParseError from "#ParseError";
3
1
  import PrimitiveType from "#PrimitiveType";
2
+ import E from "#errors";
4
3
  export default class NullType extends PrimitiveType {
5
4
  get name() {
6
5
  return "null";
7
6
  }
8
7
  parse(x, options = {}) {
9
- if (x !== null) {
10
- throw new ParseError(error(this.name, x, options));
11
- }
8
+ if (x !== null)
9
+ throw E.invalid_type(x, this.name, options);
12
10
  return x;
13
11
  }
14
12
  toJSON() {
@@ -1,7 +1,7 @@
1
1
  import CoerceKey from "#CoerceKey";
2
2
  import type FloatDataType from "#FloatDataType";
3
3
  import NumericType from "#NumericType";
4
- import coerce from "#coerce/int";
4
+ import coerce from "#coerce/float";
5
5
  export default class NumberType<T extends FloatDataType = "f64"> extends NumericType<T, number, "NumberType"> {
6
6
  [CoerceKey]: typeof coerce;
7
7
  get name(): "number";
@@ -1,6 +1,6 @@
1
1
  import CoerceKey from "#CoerceKey";
2
2
  import NumericType from "#NumericType";
3
- import coerce from "#coerce/int";
3
+ import coerce from "#coerce/float";
4
4
  export default class NumberType extends NumericType {
5
5
  [CoerceKey] = coerce;
6
6
  get name() {
@@ -1,13 +1,13 @@
1
1
  import type DataKey from "#DataKey";
2
2
  import type ParseOptions from "#ParseOptions";
3
3
  import PrimitiveType from "#PrimitiveType";
4
- import type Storeable from "#Storeable";
4
+ import type Storable from "#Storable";
5
5
  import type Validator from "#Validator";
6
6
  type Next<T> = {
7
7
  options?: ParseOptions;
8
8
  validators?: Validator<T>[];
9
9
  };
10
- export default abstract class NumericType<Key extends DataKey, T extends bigint | number, Name extends string> extends PrimitiveType<T, Name> implements Storeable<Key> {
10
+ export default abstract class NumericType<Key extends DataKey, T extends bigint | number, Name extends string> extends PrimitiveType<T, Name> implements Storable<Key> {
11
11
  #private;
12
12
  constructor(datatype: Key, validators?: Validator<T>[], options?: ParseOptions);
13
13
  derive(next: Next<T>): this;
@@ -1,23 +1,32 @@
1
1
  import GenericType from "#GenericType";
2
2
  import type Infer from "#Infer";
3
3
  import type InferInputSchema from "#InferInputSchema";
4
+ import OptionalType from "#OptionalType";
4
5
  import type Parsed from "#Parsed";
5
6
  import type ParseOptions from "#ParseOptions";
6
7
  import type Serialized from "#Serialized";
7
- import type Dict from "@rcompat/type/Dict";
8
- export default class ObjectType<P extends Dict<Parsed<unknown>>> extends GenericType<P, {
8
+ import type OptionalTrait from "#trait/Optional";
9
+ import type { Dict, Unpack } from "@rcompat/type";
10
+ type ObjectInfer<P extends Dict<Parsed<unknown>>> = {
9
11
  [K in keyof P]: P[K]["infer"];
10
- }, "ObjectType"> {
12
+ };
13
+ export default class ObjectType<P extends Dict<Parsed<unknown>>, I = ObjectInfer<P>> extends GenericType<P, I, "ObjectType"> implements OptionalTrait {
11
14
  #private;
15
+ readonly Complement: ObjectType<Record<Exclude<string, keyof P>, Parsed<unknown>>>;
12
16
  constructor(properties: P, options?: ParseOptions);
13
17
  get name(): string;
14
18
  get properties(): P;
15
19
  get input(): InferInputSchema<P>;
16
- get coerce(): this;
20
+ optional(): OptionalType<this>;
21
+ shape<T>(): ObjectType<P, T>;
22
+ extend<E extends {
23
+ [K in keyof E]: K extends keyof P ? never : Parsed<unknown>;
24
+ }>(extra: E | ObjectType<E>): ObjectType<Unpack<P & E>>;
17
25
  parse(x: unknown, options?: ParseOptions): Infer<this>;
18
26
  toJSON(): {
19
27
  type: "object";
20
28
  properties: Dict<Serialized>;
21
29
  };
22
30
  }
31
+ export {};
23
32
  //# sourceMappingURL=ObjectType.d.ts.map
@@ -1,5 +1,9 @@
1
+ import E from "#errors";
1
2
  import GenericType from "#GenericType";
3
+ import OptionalType from "#OptionalType";
2
4
  import next from "#path/next";
5
+ import SE from "#schema-errors";
6
+ import is from "@rcompat/is";
3
7
  export default class ObjectType extends GenericType {
4
8
  #properties;
5
9
  #options;
@@ -20,25 +24,34 @@ export default class ObjectType extends GenericType {
20
24
  get input() {
21
25
  return undefined;
22
26
  }
23
- #derive(next) {
27
+ #derive(options) {
24
28
  const Constructor = this.constructor;
25
- return new Constructor(this.#properties, { ...this.#options, ...next });
29
+ return new Constructor(this.#properties, { ...this.#options, ...options });
26
30
  }
27
- get coerce() {
28
- return this.#derive({ coerce: true });
31
+ optional() {
32
+ return new OptionalType(this);
33
+ }
34
+ shape() {
35
+ return new ObjectType(this.#properties, this.#options);
36
+ }
37
+ extend(extra) {
38
+ const properties = extra instanceof ObjectType ? extra.properties : extra;
39
+ for (const key of Object.keys(properties)) {
40
+ if (key in this.#properties)
41
+ throw SE.extend_key_collision(key);
42
+ }
43
+ return new ObjectType({ ...this.#properties, ...properties }, this.#options);
29
44
  }
30
45
  parse(x, options = {}) {
31
46
  const $options = { ...this.#options, ...options };
32
- let _x = x;
33
- if (typeof x !== "object" || x === null) {
34
- _x = {};
35
- }
47
+ if (is.defined(x) && !is.dict(x))
48
+ throw E.invalid_type(x, "object", $options);
49
+ const input = x ?? {};
36
50
  const out = {};
37
51
  for (const k in this.#properties) {
38
- const parsed = this.#properties[k].parse(_x[k], next(k, $options));
39
- if (parsed !== undefined) {
52
+ const parsed = this.#properties[k].parse(input[k], next(k, $options));
53
+ if (parsed !== undefined)
40
54
  out[k] = parsed;
41
- }
42
55
  }
43
56
  return out;
44
57
  }
@@ -4,7 +4,7 @@ import type ObjectType from "#ObjectType";
4
4
  import type Parsed from "#Parsed";
5
5
  import type ParseOptions from "#ParseOptions";
6
6
  import type Serialized from "#Serialized";
7
- import type Dict from "@rcompat/type/Dict";
7
+ import type { Dict } from "@rcompat/type";
8
8
  export default class OmitType<P extends Dict<Parsed<unknown>>, K extends keyof P> extends GenericType<Omit<P, K>, Omit<{
9
9
  [Key in keyof P]: Infer<P[Key]>;
10
10
  }, K>, "OmitType"> {
@@ -1,6 +1,8 @@
1
+ import E from "#errors";
1
2
  import GenericType from "#GenericType";
2
3
  import ParsedKey from "#ParsedKey";
3
4
  import join from "#path/join";
5
+ import is from "@rcompat/is";
4
6
  export default class OmitType extends GenericType {
5
7
  #properties;
6
8
  constructor(type, keys) {
@@ -15,10 +17,9 @@ export default class OmitType extends GenericType {
15
17
  return "omit";
16
18
  }
17
19
  parse(x, options = {}) {
18
- if (typeof x !== "object" || x === null) {
19
- throw new Error("Expected object");
20
- }
21
- const result = {};
20
+ if (!is.dict(x))
21
+ throw E.invalid_type(x, "object", options);
22
+ const out = {};
22
23
  const props = this.#properties;
23
24
  for (const k in props) {
24
25
  const field = props[k];
@@ -26,10 +27,10 @@ export default class OmitType extends GenericType {
26
27
  ...options, [ParsedKey]: join(options[ParsedKey] ?? "", String(k)),
27
28
  });
28
29
  if (r !== undefined) {
29
- result[k] = r;
30
+ out[k] = r;
30
31
  }
31
32
  }
32
- return result;
33
+ return out;
33
34
  }
34
35
  toJSON() {
35
36
  const properties = {};
@@ -1,10 +1,14 @@
1
1
  import type JSONPayload from "#json/JSONPayload";
2
2
  import type ParseIssue from "#ParseIssue";
3
- import type Serializable from "@rcompat/type/Serializable";
3
+ import type { Serializable } from "@rcompat/type";
4
+ declare const brand: unique symbol;
4
5
  export default class ParseError extends Error implements Serializable {
5
6
  #private;
7
+ [brand]: boolean;
8
+ static is(error: unknown): error is ParseError;
6
9
  constructor(issues: ParseIssue[]);
7
- get issues(): ParseIssue[] | undefined;
10
+ get issues(): ParseIssue[];
8
11
  toJSON(): JSONPayload;
9
12
  }
13
+ export {};
10
14
  //# sourceMappingURL=ParseError.d.ts.map
@@ -1,3 +1,4 @@
1
+ import assert from "@rcompat/assert";
1
2
  function humanize(path) {
2
3
  return path === ""
3
4
  ? ""
@@ -9,14 +10,19 @@ function humanize(path) {
9
10
  .join("");
10
11
  }
11
12
  function stringify(issue) {
12
- // For root (scalar) errors, keep just the message;
13
+ // for root (scalar) errors, keep just the message;
13
14
  // otherwise prefix with humanized path
14
15
  return issue.path === ""
15
16
  ? issue.message
16
17
  : `${humanize(issue.path)}: ${issue.message}`;
17
18
  }
19
+ const brand = Symbol.for("pema/error/parse/v0");
18
20
  export default class ParseError extends Error {
19
- #issues;
21
+ [brand] = true;
22
+ #issues = [];
23
+ static is(error) {
24
+ return typeof error === "object" && error !== null && brand in error;
25
+ }
20
26
  constructor(issues) {
21
27
  super(stringify(issues[0]));
22
28
  this.name = "ParseError";
@@ -26,24 +32,28 @@ export default class ParseError extends Error {
26
32
  return this.#issues;
27
33
  }
28
34
  toJSON() {
29
- const issues = this.#issues ?? [];
30
- if (issues.length === 0) {
31
- return { message: "Parsing failed", messages: ["Parsing failed"] };
32
- }
33
- const isForm = issues.some(i => i.path !== "");
34
- if (!isForm) {
35
+ const issues = this.#issues;
36
+ assert.uint(issues.length);
37
+ const is_form = issues.some(i => i.path !== "");
38
+ if (!is_form) {
35
39
  const messages = issues.map(i => i.message);
36
- return { message: messages[0], messages };
40
+ return {
41
+ type: issues[0].type,
42
+ message: messages[0],
43
+ messages,
44
+ };
37
45
  }
38
46
  const dict = {};
39
47
  for (const i of issues) {
40
48
  const key = i.path;
41
- if (!dict[key])
42
- dict[key] = { message: i.message, messages: [] };
43
- dict[key].messages.push(i.message);
44
- // Keep the first as the short message
45
- if (dict[key].messages.length === 1)
46
- dict[key].message = i.message;
49
+ if (!(key in dict))
50
+ dict[key] = {
51
+ type: i.type,
52
+ message: i.message,
53
+ messages: [],
54
+ };
55
+ const entry = dict[key];
56
+ entry.messages.push(i.message);
47
57
  }
48
58
  return dict;
49
59
  }
@@ -1,6 +1,6 @@
1
1
  import type ParsedKey from "#ParsedKey";
2
2
  import type Validator from "#Validator";
3
- import type JSONPointer from "@rcompat/type/JSONPointer";
3
+ import type { JSONPointer } from "@rcompat/type";
4
4
  export default interface ParseOptions<T = unknown> {
5
5
  coerce?: boolean;
6
6
  [ParsedKey]?: JSONPointer;
@@ -2,7 +2,7 @@ import CoerceKey from "#CoerceKey";
2
2
  import ParsedKey from "#ParsedKey";
3
3
  import type ParseOptions from "#ParseOptions";
4
4
  import type Serialized from "#Serialized";
5
- import type Serializable from "@rcompat/type/Serializable";
5
+ import type { Serializable } from "@rcompat/type";
6
6
  export default abstract class Parsed<StaticType> implements Serializable {
7
7
  get [ParsedKey](): "ParsedKey";
8
8
  get infer(): StaticType;
@@ -19,6 +19,7 @@ export default abstract class Parsed<StaticType> implements Serializable {
19
19
  * @returns The parsed value, if successfully parsed.
20
20
  */
21
21
  abstract parse(x: unknown, options?: ParseOptions): StaticType;
22
+ coerce(x: unknown, options?: ParseOptions): StaticType;
22
23
  abstract toJSON(): Serialized;
23
24
  }
24
25
  //# sourceMappingURL=Parsed.d.ts.map
@@ -13,5 +13,8 @@ export default class Parsed {
13
13
  [CoerceKey](x) {
14
14
  return x;
15
15
  }
16
+ coerce(x, options = {}) {
17
+ return this.parse(x, { ...options, coerce: true });
18
+ }
16
19
  }
17
20
  //# sourceMappingURL=Parsed.js.map
@@ -1,11 +1,11 @@
1
1
  import DefaultType from "#DefaultType";
2
- import error from "#error";
2
+ import E from "#errors";
3
3
  import ParsedKey from "#ParsedKey";
4
4
  import ParseError from "#ParseError";
5
5
  import join from "#path/join";
6
6
  import next from "#path/next";
7
7
  import VirtualType from "#VirtualType";
8
- import isDict from "@rcompat/is/dict";
8
+ import is from "@rcompat/is";
9
9
  export default class PartialType extends VirtualType {
10
10
  #spec;
11
11
  constructor(spec) {
@@ -22,9 +22,8 @@ export default class PartialType extends VirtualType {
22
22
  return new DefaultType(this, value);
23
23
  }
24
24
  parse(x, options = {}) {
25
- if (!isDict(x)) {
26
- throw new ParseError(error("object", x, options));
27
- }
25
+ if (!is.dict(x))
26
+ throw E.invalid_type(x, "object", options);
28
27
  const input = x;
29
28
  const out = {};
30
29
  const issues = [];
@@ -38,11 +37,10 @@ export default class PartialType extends VirtualType {
38
37
  out[key] = parsed;
39
38
  }
40
39
  catch (e) {
41
- if (e instanceof ParseError) {
40
+ if (ParseError.is(e)) {
42
41
  // child already rebased to /<key> via nextOptions -> just collect
43
- if (e.issues && e.issues.length) {
42
+ if (e.issues.length > 0)
44
43
  issues.push(...e.issues);
45
- }
46
44
  }
47
45
  else {
48
46
  // wrap non-ParseError into a properly-pathed issue at /<key>
@@ -51,15 +49,15 @@ export default class PartialType extends VirtualType {
51
49
  : String(e);
52
50
  issues.push({
53
51
  input: input[key],
52
+ type: "invalid_type",
54
53
  message: message,
55
54
  path: join(options[ParsedKey] ?? "", key),
56
55
  });
57
56
  }
58
57
  }
59
58
  }
60
- if (issues.length > 0) {
59
+ if (issues.length > 0)
61
60
  throw new ParseError(issues);
62
- }
63
61
  return out;
64
62
  }
65
63
  toJSON() {
@@ -1,5 +1,5 @@
1
1
  import type Parsed from "#Parsed";
2
- import type Dict from "@rcompat/type/Dict";
2
+ import type { Dict } from "@rcompat/type";
3
3
  type Partialable = Dict<Parsed<unknown>>;
4
4
  export type { Partialable as default };
5
5
  //# sourceMappingURL=Partialable.d.ts.map
@@ -12,7 +12,6 @@ export default abstract class PrimitiveType<StaticType, Name extends string> ext
12
12
  get options(): ParseOptions<unknown>;
13
13
  get validators(): Validator<StaticType>[];
14
14
  derive(next: Next<StaticType>): this;
15
- get coerce(): this;
16
15
  parse(x: unknown, options?: ParseOptions<StaticType>): Infer<this>;
17
16
  }
18
17
  export {};
@@ -1,5 +1,5 @@
1
1
  import CoerceKey from "#CoerceKey";
2
- import error from "#error";
2
+ import E from "#errors";
3
3
  import ParsedKey from "#ParsedKey";
4
4
  import ParseError from "#ParseError";
5
5
  import Type from "#Type";
@@ -21,41 +21,42 @@ export default class PrimitiveType extends Type {
21
21
  const Constructor = this.constructor;
22
22
  return new Constructor([...this.#validators, ...next.validators ?? []], { ...this.#options, ...next.options ?? {} });
23
23
  }
24
- get coerce() {
25
- return this.derive({ options: { coerce: true } });
26
- }
27
24
  parse(x, options = {}) {
28
- const $options = { ...this.#options, ...options };
29
- const validators = [...$options.validators ?? [], ...this.#validators];
25
+ // hotpath: avoid object spread when possible
26
+ const has_instance_options = this.#options.coerce !== undefined
27
+ || this.#options[ParsedKey] !== undefined;
28
+ const $options = has_instance_options
29
+ ? { ...this.#options, ...options }
30
+ : options;
31
+ // hotpath: avoid array spread when no option validators
32
+ const option_validators = $options.validators;
33
+ const validators = option_validators && option_validators.length > 0
34
+ ? option_validators.concat(this.#validators)
35
+ : this.#validators;
30
36
  const $x = $options.coerce === true ? this[CoerceKey](x) : x;
31
- if (typeof $x !== this.name) {
32
- throw new ParseError(error(this.name, $x, $options));
33
- }
37
+ if (typeof $x !== this.name)
38
+ throw E.invalid_type($x, this.name, $options);
34
39
  const base = $options[ParsedKey] ?? "";
35
- for (const v of validators) {
40
+ for (let i = 0; i < validators.length; i++) {
36
41
  try {
37
- v($x);
42
+ validators[i]($x);
38
43
  }
39
44
  catch (e) {
40
- if (e instanceof ParseError) {
45
+ if (ParseError.is(e)) {
41
46
  // rebase each issue path under `base`
42
- const rebased = (e.issues ?? []).map(i => ({
43
- ...i,
44
- path: i.path === ""
47
+ const rebased = e.issues.map(issue => ({
48
+ ...issue,
49
+ path: issue.path === ""
45
50
  ? base
46
- : (base === "" ? i.path : (base + i.path)),
51
+ : (base === "" ? issue.path : (base + issue.path)),
47
52
  }));
48
53
  throw new ParseError(rebased);
49
54
  }
50
- // non a ParseError - wrap with proper path
55
+ // not a ParseError - wrap with proper path
51
56
  const message = e && typeof e.message === "string"
52
57
  ? e.message
53
58
  : String(e);
54
- throw new ParseError([{
55
- input: x,
56
- message,
57
- path: base,
58
- }]);
59
+ throw E.invalid_type(x, message, base);
59
60
  }
60
61
  }
61
62
  return $x;
@@ -2,7 +2,7 @@ import type Infer from "#Infer";
2
2
  import OptionalType from "#OptionalType";
3
3
  import Parsed from "#Parsed";
4
4
  import type OptionalTrait from "#trait/Optional";
5
- import type Printable from "@rcompat/type/Printable";
5
+ import type { Printable } from "@rcompat/type";
6
6
  export default class PureType<Type, Name extends string = "PureType"> extends Parsed<Type> implements Printable, OptionalTrait {
7
7
  get name(): string;
8
8
  get Name(): Name;