@voidhash/mimic 1.0.0-beta.16 → 1.0.0-beta.17

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 (95) hide show
  1. package/dist/EffectSchema.cjs +3 -3
  2. package/dist/EffectSchema.d.cts +5 -5
  3. package/dist/EffectSchema.d.cts.map +1 -1
  4. package/dist/EffectSchema.d.mts +5 -5
  5. package/dist/EffectSchema.d.mts.map +1 -1
  6. package/dist/EffectSchema.mjs +3 -3
  7. package/dist/EffectSchema.mjs.map +1 -1
  8. package/dist/FractionalIndex.mjs.map +1 -1
  9. package/dist/Operation.d.cts +4 -4
  10. package/dist/Operation.d.cts.map +1 -1
  11. package/dist/Operation.d.mts +4 -4
  12. package/dist/Operation.d.mts.map +1 -1
  13. package/dist/Operation.mjs.map +1 -1
  14. package/dist/OperationDefinition.d.cts +2 -2
  15. package/dist/OperationDefinition.d.cts.map +1 -1
  16. package/dist/OperationDefinition.d.mts +2 -2
  17. package/dist/OperationDefinition.d.mts.map +1 -1
  18. package/dist/OperationDefinition.mjs.map +1 -1
  19. package/dist/Presence.mjs.map +1 -1
  20. package/dist/SchemaJSON.cjs +305 -0
  21. package/dist/SchemaJSON.d.cts +11 -0
  22. package/dist/SchemaJSON.d.cts.map +1 -0
  23. package/dist/SchemaJSON.d.mts +11 -0
  24. package/dist/SchemaJSON.d.mts.map +1 -0
  25. package/dist/SchemaJSON.mjs +301 -0
  26. package/dist/SchemaJSON.mjs.map +1 -0
  27. package/dist/index.cjs +7 -0
  28. package/dist/index.d.cts +2 -1
  29. package/dist/index.d.mts +2 -1
  30. package/dist/index.mjs +2 -1
  31. package/dist/primitives/Array.cjs +12 -2
  32. package/dist/primitives/Array.d.cts.map +1 -1
  33. package/dist/primitives/Array.d.mts.map +1 -1
  34. package/dist/primitives/Array.mjs +12 -2
  35. package/dist/primitives/Array.mjs.map +1 -1
  36. package/dist/primitives/Boolean.mjs.map +1 -1
  37. package/dist/primitives/Either.mjs.map +1 -1
  38. package/dist/primitives/Literal.mjs.map +1 -1
  39. package/dist/primitives/Number.cjs +27 -5
  40. package/dist/primitives/Number.d.cts.map +1 -1
  41. package/dist/primitives/Number.d.mts.map +1 -1
  42. package/dist/primitives/Number.mjs +27 -5
  43. package/dist/primitives/Number.mjs.map +1 -1
  44. package/dist/primitives/String.cjs +44 -13
  45. package/dist/primitives/String.d.cts.map +1 -1
  46. package/dist/primitives/String.d.mts.map +1 -1
  47. package/dist/primitives/String.mjs +44 -13
  48. package/dist/primitives/String.mjs.map +1 -1
  49. package/dist/primitives/Union.mjs.map +1 -1
  50. package/dist/primitives/shared.d.cts +2 -0
  51. package/dist/primitives/shared.d.cts.map +1 -1
  52. package/dist/primitives/shared.d.mts +2 -0
  53. package/dist/primitives/shared.d.mts.map +1 -1
  54. package/dist/primitives/shared.mjs.map +1 -1
  55. package/package.json +15 -8
  56. package/src/EffectSchema.ts +3 -3
  57. package/src/FractionalIndex.ts +18 -18
  58. package/src/Operation.ts +5 -5
  59. package/src/OperationDefinition.ts +2 -2
  60. package/src/Presence.ts +3 -3
  61. package/src/SchemaJSON.ts +396 -0
  62. package/src/index.ts +1 -0
  63. package/src/primitives/Array.ts +18 -8
  64. package/src/primitives/Boolean.ts +2 -2
  65. package/src/primitives/Either.ts +2 -2
  66. package/src/primitives/Literal.ts +2 -2
  67. package/src/primitives/Number.ts +44 -22
  68. package/src/primitives/String.ts +61 -34
  69. package/src/primitives/Union.ts +1 -1
  70. package/src/primitives/shared.ts +2 -0
  71. package/.turbo/turbo-build.log +0 -270
  72. package/tests/Document.test.ts +0 -557
  73. package/tests/EffectSchema.test.ts +0 -546
  74. package/tests/FractionalIndex.test.ts +0 -377
  75. package/tests/OperationPath.test.ts +0 -151
  76. package/tests/Presence.test.ts +0 -321
  77. package/tests/Primitive.test.ts +0 -381
  78. package/tests/client/ClientDocument.test.ts +0 -1981
  79. package/tests/client/WebSocketTransport.test.ts +0 -1217
  80. package/tests/primitives/Array.test.ts +0 -526
  81. package/tests/primitives/Boolean.test.ts +0 -126
  82. package/tests/primitives/Either.test.ts +0 -707
  83. package/tests/primitives/Lazy.test.ts +0 -143
  84. package/tests/primitives/Literal.test.ts +0 -122
  85. package/tests/primitives/Number.test.ts +0 -133
  86. package/tests/primitives/String.test.ts +0 -128
  87. package/tests/primitives/Struct.test.ts +0 -1154
  88. package/tests/primitives/Tree.test.ts +0 -1139
  89. package/tests/primitives/TreeNode.test.ts +0 -50
  90. package/tests/primitives/Union.test.ts +0 -554
  91. package/tests/server/ServerDocument.test.ts +0 -903
  92. package/tsconfig.build.json +0 -24
  93. package/tsconfig.json +0 -8
  94. package/tsdown.config.ts +0 -18
  95. package/vitest.mts +0 -11
@@ -0,0 +1,396 @@
1
+ import type { AnyPrimitive, Validator } from "./primitives/shared";
2
+ import { StringPrimitive } from "./primitives/String";
3
+ import { NumberPrimitive } from "./primitives/Number";
4
+ import { BooleanPrimitive } from "./primitives/Boolean";
5
+ import { LiteralPrimitive } from "./primitives/Literal";
6
+ import { StructPrimitive } from "./primitives/Struct";
7
+ import { ArrayPrimitive } from "./primitives/Array";
8
+ import { LazyPrimitive } from "./primitives/Lazy";
9
+ import { UnionPrimitive } from "./primitives/Union";
10
+ import { EitherPrimitive } from "./primitives/Either";
11
+ import { TreePrimitive } from "./primitives/Tree";
12
+ import { TreeNodePrimitive, type AnyTreeNodePrimitive } from "./primitives/TreeNode";
13
+ import * as Primitive from "./Primitive";
14
+
15
+ // =============================================================================
16
+ // JSON Types
17
+ // =============================================================================
18
+
19
+ interface ValidatorJSON {
20
+ readonly kind: string;
21
+ readonly params?: unknown;
22
+ }
23
+
24
+ interface ScalarJSON {
25
+ readonly type: "string" | "number" | "boolean";
26
+ readonly required: boolean;
27
+ readonly default?: unknown;
28
+ readonly validators?: readonly ValidatorJSON[];
29
+ }
30
+
31
+ interface LiteralJSON {
32
+ readonly type: "literal";
33
+ readonly value: string | number | boolean | null;
34
+ readonly required: boolean;
35
+ readonly default?: unknown;
36
+ }
37
+
38
+ interface StructJSON {
39
+ readonly type: "struct";
40
+ readonly required: boolean;
41
+ readonly default?: unknown;
42
+ readonly fields: Record<string, unknown>;
43
+ }
44
+
45
+ interface ArrayJSON {
46
+ readonly type: "array";
47
+ readonly required: boolean;
48
+ readonly default?: unknown;
49
+ readonly element: unknown;
50
+ readonly validators?: readonly ValidatorJSON[];
51
+ }
52
+
53
+ interface UnionJSON {
54
+ readonly type: "union";
55
+ readonly required: boolean;
56
+ readonly default?: unknown;
57
+ readonly discriminator: string;
58
+ readonly variants: Record<string, unknown>;
59
+ }
60
+
61
+ interface EitherJSON {
62
+ readonly type: "either";
63
+ readonly required: boolean;
64
+ readonly default?: unknown;
65
+ readonly variants: readonly unknown[];
66
+ }
67
+
68
+ interface TreeNodeJSON {
69
+ readonly type: "treeNode";
70
+ readonly nodeType: string;
71
+ readonly data: unknown;
72
+ readonly children: readonly string[];
73
+ }
74
+
75
+ interface TreeJSON {
76
+ readonly type: "tree";
77
+ readonly required: boolean;
78
+ readonly default?: unknown;
79
+ readonly root: string;
80
+ readonly nodes: Record<string, TreeNodeJSON>;
81
+ }
82
+
83
+ // =============================================================================
84
+ // Helper: access private _schema
85
+ // =============================================================================
86
+
87
+ function getSchema(primitive: AnyPrimitive): any {
88
+ return (primitive as any)._schema;
89
+ }
90
+
91
+ // =============================================================================
92
+ // Serialize validators
93
+ // =============================================================================
94
+
95
+ function serializeValidators(validators: readonly Validator<any>[]): ValidatorJSON[] | undefined {
96
+ const serializable = validators.filter((v) => v.kind != null);
97
+ if (serializable.length === 0) return undefined;
98
+ return serializable.map((v) => {
99
+ const json: ValidatorJSON = { kind: v.kind! };
100
+ if (v.params !== undefined) {
101
+ return { ...json, params: v.params };
102
+ }
103
+ return json;
104
+ });
105
+ }
106
+
107
+ // =============================================================================
108
+ // toJSON
109
+ // =============================================================================
110
+
111
+ function collectTreeNodes(
112
+ node: AnyTreeNodePrimitive,
113
+ visited: Map<string, AnyTreeNodePrimitive>
114
+ ): void {
115
+ if (visited.has(node.type)) return;
116
+ visited.set(node.type, node);
117
+ for (const child of node.children) {
118
+ collectTreeNodes(child, visited);
119
+ }
120
+ }
121
+
122
+ export function toJSON(primitive: AnyPrimitive): unknown {
123
+ // Resolve Lazy first
124
+ if (primitive instanceof LazyPrimitive) {
125
+ const resolved = (primitive as any)._resolve();
126
+ return toJSON(resolved);
127
+ }
128
+
129
+ const schema = getSchema(primitive);
130
+
131
+ if (primitive instanceof StringPrimitive) {
132
+ const json: any = { type: "string", required: schema.required };
133
+ if (schema.defaultValue !== undefined) json.default = schema.defaultValue;
134
+ const validators = serializeValidators(schema.validators);
135
+ if (validators) json.validators = validators;
136
+ return json;
137
+ }
138
+
139
+ if (primitive instanceof NumberPrimitive) {
140
+ const json: any = { type: "number", required: schema.required };
141
+ if (schema.defaultValue !== undefined) json.default = schema.defaultValue;
142
+ const validators = serializeValidators(schema.validators);
143
+ if (validators) json.validators = validators;
144
+ return json;
145
+ }
146
+
147
+ if (primitive instanceof BooleanPrimitive) {
148
+ const json: any = { type: "boolean", required: schema.required };
149
+ if (schema.defaultValue !== undefined) json.default = schema.defaultValue;
150
+ return json;
151
+ }
152
+
153
+ if (primitive instanceof LiteralPrimitive) {
154
+ const json: any = {
155
+ type: "literal",
156
+ value: (primitive as LiteralPrimitive<any>).literal,
157
+ required: schema.required,
158
+ };
159
+ if (schema.defaultValue !== undefined) json.default = schema.defaultValue;
160
+ return json;
161
+ }
162
+
163
+ if (primitive instanceof StructPrimitive) {
164
+ const fields: Record<string, unknown> = {};
165
+ const structFields = (primitive as StructPrimitive<any>).fields;
166
+ for (const key in structFields) {
167
+ fields[key] = toJSON(structFields[key]!);
168
+ }
169
+ const json: any = { type: "struct", required: schema.required, fields };
170
+ if (schema.defaultValue !== undefined) json.default = schema.defaultValue;
171
+ return json;
172
+ }
173
+
174
+ if (primitive instanceof ArrayPrimitive) {
175
+ const json: any = {
176
+ type: "array",
177
+ required: schema.required,
178
+ element: toJSON((primitive as ArrayPrimitive<any>).element),
179
+ };
180
+ if (schema.defaultValue !== undefined) json.default = schema.defaultValue;
181
+ const validators = serializeValidators(schema.validators);
182
+ if (validators) json.validators = validators;
183
+ return json;
184
+ }
185
+
186
+ if (primitive instanceof UnionPrimitive) {
187
+ const variants: Record<string, unknown> = {};
188
+ const unionVariants = (primitive as UnionPrimitive<any, any>).variants;
189
+ for (const key in unionVariants) {
190
+ variants[key] = toJSON(unionVariants[key]!);
191
+ }
192
+ const json: any = {
193
+ type: "union",
194
+ required: schema.required,
195
+ discriminator: (primitive as UnionPrimitive<any, any>).discriminator,
196
+ variants,
197
+ };
198
+ if (schema.defaultValue !== undefined) json.default = schema.defaultValue;
199
+ return json;
200
+ }
201
+
202
+ if (primitive instanceof EitherPrimitive) {
203
+ const variants = (primitive as EitherPrimitive<any>).variants;
204
+ const json: any = {
205
+ type: "either",
206
+ required: schema.required,
207
+ variants: variants.map((v: AnyPrimitive) => toJSON(v)),
208
+ };
209
+ if (schema.defaultValue !== undefined) json.default = schema.defaultValue;
210
+ return json;
211
+ }
212
+
213
+ if (primitive instanceof TreePrimitive) {
214
+ const root = (primitive as TreePrimitive<any>).root;
215
+ const nodeMap = new Map<string, AnyTreeNodePrimitive>();
216
+ collectTreeNodes(root, nodeMap);
217
+
218
+ const nodes: Record<string, TreeNodeJSON> = {};
219
+ for (const [nodeType, node] of nodeMap) {
220
+ nodes[nodeType] = {
221
+ type: "treeNode",
222
+ nodeType,
223
+ data: toJSON(node.data),
224
+ children: node.children.map((c) => c.type),
225
+ };
226
+ }
227
+
228
+ const json: any = {
229
+ type: "tree",
230
+ required: schema.required,
231
+ root: root.type,
232
+ nodes,
233
+ };
234
+ if (schema.defaultInput !== undefined) json.default = schema.defaultInput;
235
+ return json;
236
+ }
237
+
238
+ throw new Error(`Unknown primitive type: ${primitive._tag}`);
239
+ }
240
+
241
+ // =============================================================================
242
+ // fromJSON
243
+ // =============================================================================
244
+
245
+ function applyStringValidators(p: StringPrimitive<any, any>, validators: readonly ValidatorJSON[]): StringPrimitive<any, any> {
246
+ let result = p;
247
+ for (const v of validators) {
248
+ const params = v.params as any;
249
+ switch (v.kind) {
250
+ case "min": result = result.min(params.value); break;
251
+ case "max": result = result.max(params.value); break;
252
+ case "length": result = result.length(params.value); break;
253
+ case "regex": result = result.regex(new RegExp(params.pattern, params.flags)); break;
254
+ case "email": result = result.email(); break;
255
+ case "url": result = result.url(); break;
256
+ }
257
+ }
258
+ return result;
259
+ }
260
+
261
+ function applyNumberValidators(p: NumberPrimitive<any, any>, validators: readonly ValidatorJSON[]): NumberPrimitive<any, any> {
262
+ let result = p;
263
+ for (const v of validators) {
264
+ const params = v.params as any;
265
+ switch (v.kind) {
266
+ case "min": result = result.min(params.value); break;
267
+ case "max": result = result.max(params.value); break;
268
+ case "positive": result = result.positive(); break;
269
+ case "negative": result = result.negative(); break;
270
+ case "int": result = result.int(); break;
271
+ }
272
+ }
273
+ return result;
274
+ }
275
+
276
+ function applyArrayValidators(p: ArrayPrimitive<any, any, any>, validators: readonly ValidatorJSON[]): ArrayPrimitive<any, any, any> {
277
+ let result = p;
278
+ for (const v of validators) {
279
+ const params = v.params as any;
280
+ switch (v.kind) {
281
+ case "minLength": result = result.minLength(params.value); break;
282
+ case "maxLength": result = result.maxLength(params.value); break;
283
+ }
284
+ }
285
+ return result;
286
+ }
287
+
288
+ export function fromJSON(json: unknown): AnyPrimitive {
289
+ const obj = json as any;
290
+
291
+ switch (obj.type) {
292
+ case "string": {
293
+ let p: StringPrimitive<any, any> = Primitive.String();
294
+ if (obj.validators) p = applyStringValidators(p, obj.validators);
295
+ if (obj.required) p = p.required();
296
+ if (obj.default !== undefined) p = p.default(obj.default);
297
+ return p;
298
+ }
299
+
300
+ case "number": {
301
+ let p: NumberPrimitive<any, any> = Primitive.Number();
302
+ if (obj.validators) p = applyNumberValidators(p, obj.validators);
303
+ if (obj.required) p = p.required();
304
+ if (obj.default !== undefined) p = p.default(obj.default);
305
+ return p;
306
+ }
307
+
308
+ case "boolean": {
309
+ let p: BooleanPrimitive<any, any> = Primitive.Boolean();
310
+ if (obj.required) p = p.required();
311
+ if (obj.default !== undefined) p = p.default(obj.default);
312
+ return p;
313
+ }
314
+
315
+ case "literal": {
316
+ let p: LiteralPrimitive<any, any, any> = Primitive.Literal(obj.value);
317
+ if (obj.required) p = p.required();
318
+ if (obj.default !== undefined) p = p.default(obj.default);
319
+ return p;
320
+ }
321
+
322
+ case "struct": {
323
+ const fields: Record<string, AnyPrimitive> = {};
324
+ for (const key in obj.fields) {
325
+ fields[key] = fromJSON(obj.fields[key]);
326
+ }
327
+ let p: StructPrimitive<any, any, any> = Primitive.Struct(fields);
328
+ if (obj.required) p = p.required();
329
+ if (obj.default !== undefined) p = p.default(obj.default);
330
+ return p;
331
+ }
332
+
333
+ case "array": {
334
+ const element = fromJSON(obj.element);
335
+ let p: ArrayPrimitive<any, any, any> = Primitive.Array(element);
336
+ if (obj.validators) p = applyArrayValidators(p, obj.validators);
337
+ if (obj.required) p = p.required();
338
+ if (obj.default !== undefined) p = p.default(obj.default);
339
+ return p;
340
+ }
341
+
342
+ case "union": {
343
+ const variants: Record<string, any> = {};
344
+ for (const key in obj.variants) {
345
+ variants[key] = fromJSON(obj.variants[key]);
346
+ }
347
+ let p: UnionPrimitive<any, any, any, any> = Primitive.Union({
348
+ discriminator: obj.discriminator,
349
+ variants,
350
+ });
351
+ if (obj.required) p = p.required();
352
+ if (obj.default !== undefined) p = p.default(obj.default);
353
+ return p;
354
+ }
355
+
356
+ case "either": {
357
+ const variants = obj.variants.map((v: unknown) => fromJSON(v));
358
+ let p: EitherPrimitive<any, any, any> = Primitive.Either(...variants);
359
+ if (obj.required) p = p.required();
360
+ if (obj.default !== undefined) p = p.default(obj.default);
361
+ return p;
362
+ }
363
+
364
+ case "tree": {
365
+ const treeJSON = obj as TreeJSON;
366
+ // First pass: create all TreeNode primitives with placeholder children
367
+ const nodeMap = new Map<string, AnyTreeNodePrimitive>();
368
+ const nodeJSONMap = new Map<string, TreeNodeJSON>();
369
+
370
+ for (const nodeType in treeJSON.nodes) {
371
+ nodeJSONMap.set(nodeType, treeJSON.nodes[nodeType]!);
372
+ }
373
+
374
+ // Create nodes with lazy children to handle circular references
375
+ for (const [nodeType, nodeJSON] of nodeJSONMap) {
376
+ const data = fromJSON(nodeJSON.data) as StructPrimitive<any>;
377
+ const childTypes = nodeJSON.children;
378
+
379
+ const node = Primitive.TreeNode(nodeType, {
380
+ data,
381
+ children: () => childTypes.map((ct) => nodeMap.get(ct)!),
382
+ });
383
+ nodeMap.set(nodeType, node);
384
+ }
385
+
386
+ const root = nodeMap.get(treeJSON.root)!;
387
+ let p: TreePrimitive<any, any, any> = Primitive.Tree({ root });
388
+ if (obj.required) p = p.required();
389
+ if (obj.default !== undefined) p = p.default(obj.default);
390
+ return p;
391
+ }
392
+
393
+ default:
394
+ throw new Error(`Unknown JSON schema type: ${obj.type}`);
395
+ }
396
+ }
package/src/index.ts CHANGED
@@ -14,3 +14,4 @@ export * as Presence from "./Presence";
14
14
  export * as EffectSchema from "./EffectSchema";
15
15
  export * as Types from "./types/index";
16
16
  export * as TreeHelpers from "./utils/tree-helpers";
17
+ export * as SchemaJSON from "./SchemaJSON";
@@ -173,18 +173,28 @@ export class ArrayPrimitive<TElement extends AnyPrimitive, TRequired extends boo
173
173
 
174
174
  /** Minimum array length */
175
175
  minLength(length: number): ArrayPrimitive<TElement, TRequired, THasDefault> {
176
- return this.refine(
177
- (v) => v.length >= length,
178
- `Array must have at least ${length} elements`
179
- );
176
+ return new ArrayPrimitive({
177
+ ...this._schema,
178
+ validators: [...this._schema.validators, {
179
+ validate: (v) => v.length >= length,
180
+ message: `Array must have at least ${length} elements`,
181
+ kind: "minLength",
182
+ params: { value: length },
183
+ }],
184
+ });
180
185
  }
181
186
 
182
187
  /** Maximum array length */
183
188
  maxLength(length: number): ArrayPrimitive<TElement, TRequired, THasDefault> {
184
- return this.refine(
185
- (v) => v.length <= length,
186
- `Array must have at most ${length} elements`
187
- );
189
+ return new ArrayPrimitive({
190
+ ...this._schema,
191
+ validators: [...this._schema.validators, {
192
+ validate: (v) => v.length <= length,
193
+ message: `Array must have at most ${length} elements`,
194
+ kind: "maxLength",
195
+ params: { value: length },
196
+ }],
197
+ });
188
198
  }
189
199
 
190
200
  readonly _internal: PrimitiveInternal<ArrayState<TElement>, ArrayProxy<TElement>> = {
@@ -87,12 +87,12 @@ export class BooleanPrimitive<TRequired extends boolean = false, THasDefault ext
87
87
  },
88
88
  set: (value: InferSetInput<TRequired, THasDefault>) => {
89
89
  env.addOperation(
90
- Operation.fromDefinition(operationPath, this._opDefinitions.set, value)
90
+ Operation.fromDefinition(operationPath, this._opDefinitions.set as any, value)
91
91
  );
92
92
  },
93
93
  update: (value: InferUpdateInput<TRequired, THasDefault>) => {
94
94
  env.addOperation(
95
- Operation.fromDefinition(operationPath, this._opDefinitions.set, value)
95
+ Operation.fromDefinition(operationPath, this._opDefinitions.set as any, value)
96
96
  );
97
97
  },
98
98
  toSnapshot: (): MaybeUndefined<boolean, TRequired, THasDefault> => {
@@ -271,12 +271,12 @@ export class EitherPrimitive<TVariants extends readonly ScalarPrimitive[], TRequ
271
271
  },
272
272
  set: (value: InferSetInput<TVariants, TRequired, THasDefault>) => {
273
273
  env.addOperation(
274
- Operation.fromDefinition(operationPath, this._opDefinitions.set, value)
274
+ Operation.fromDefinition(operationPath, this._opDefinitions.set as any, value)
275
275
  );
276
276
  },
277
277
  update: (value: InferUpdateInput<TVariants, TRequired, THasDefault>) => {
278
278
  env.addOperation(
279
- Operation.fromDefinition(operationPath, this._opDefinitions.set, value)
279
+ Operation.fromDefinition(operationPath, this._opDefinitions.set as any, value)
280
280
  );
281
281
  },
282
282
  match: <R,>(handlers: EitherMatchHandlers<R>): R | undefined => {
@@ -87,12 +87,12 @@ export class LiteralPrimitive<T extends LiteralValue, TRequired extends boolean
87
87
  },
88
88
  set: (value: InferSetInput<T, TRequired, THasDefault>) => {
89
89
  env.addOperation(
90
- Operation.fromDefinition(operationPath, this._opDefinitions.set, value)
90
+ Operation.fromDefinition(operationPath, this._opDefinitions.set as any, value)
91
91
  );
92
92
  },
93
93
  update: (value: InferUpdateInput<T, TRequired, THasDefault>) => {
94
94
  env.addOperation(
95
- Operation.fromDefinition(operationPath, this._opDefinitions.set, value)
95
+ Operation.fromDefinition(operationPath, this._opDefinitions.set as any, value)
96
96
  );
97
97
  },
98
98
  toSnapshot: (): MaybeUndefined<T, TRequired, THasDefault> => {
@@ -79,42 +79,64 @@ export class NumberPrimitive<TRequired extends boolean = false, THasDefault exte
79
79
 
80
80
  /** Minimum value (inclusive) */
81
81
  min(value: number): NumberPrimitive<TRequired, THasDefault> {
82
- return this.refine(
83
- (v) => v >= value,
84
- `Number must be at least ${value}`
85
- );
82
+ return new NumberPrimitive({
83
+ ...this._schema,
84
+ validators: [...this._schema.validators, {
85
+ validate: (v) => v >= value,
86
+ message: `Number must be at least ${value}`,
87
+ kind: "min",
88
+ params: { value },
89
+ }],
90
+ });
86
91
  }
87
92
 
88
93
  /** Maximum value (inclusive) */
89
94
  max(value: number): NumberPrimitive<TRequired, THasDefault> {
90
- return this.refine(
91
- (v) => v <= value,
92
- `Number must be at most ${value}`
93
- );
95
+ return new NumberPrimitive({
96
+ ...this._schema,
97
+ validators: [...this._schema.validators, {
98
+ validate: (v) => v <= value,
99
+ message: `Number must be at most ${value}`,
100
+ kind: "max",
101
+ params: { value },
102
+ }],
103
+ });
94
104
  }
95
105
 
96
106
  /** Must be positive (> 0) */
97
107
  positive(): NumberPrimitive<TRequired, THasDefault> {
98
- return this.refine(
99
- (v) => v > 0,
100
- "Number must be positive"
101
- );
108
+ return new NumberPrimitive({
109
+ ...this._schema,
110
+ validators: [...this._schema.validators, {
111
+ validate: (v) => v > 0,
112
+ message: "Number must be positive",
113
+ kind: "positive",
114
+ }],
115
+ });
102
116
  }
103
117
 
104
118
  /** Must be negative (< 0) */
105
119
  negative(): NumberPrimitive<TRequired, THasDefault> {
106
- return this.refine(
107
- (v) => v < 0,
108
- "Number must be negative"
109
- );
120
+ return new NumberPrimitive({
121
+ ...this._schema,
122
+ validators: [...this._schema.validators, {
123
+ validate: (v) => v < 0,
124
+ message: "Number must be negative",
125
+ kind: "negative",
126
+ }],
127
+ });
110
128
  }
111
129
 
112
130
  /** Must be an integer */
113
131
  int(): NumberPrimitive<TRequired, THasDefault> {
114
- return this.refine(
115
- (v) => globalThis.Number.isInteger(v),
116
- "Number must be an integer"
117
- );
132
+ return new NumberPrimitive({
133
+ ...this._schema,
134
+ validators: [...this._schema.validators, {
135
+ validate: (v) => globalThis.Number.isInteger(v),
136
+ message: "Number must be an integer",
137
+ kind: "int",
138
+ }],
139
+ });
118
140
  }
119
141
 
120
142
  readonly _internal: PrimitiveInternal<number, NumberProxy<TRequired, THasDefault>> = {
@@ -127,12 +149,12 @@ export class NumberPrimitive<TRequired extends boolean = false, THasDefault exte
127
149
  },
128
150
  set: (value: InferSetInput<TRequired, THasDefault>) => {
129
151
  env.addOperation(
130
- Operation.fromDefinition(operationPath, this._opDefinitions.set, value)
152
+ Operation.fromDefinition(operationPath, this._opDefinitions.set as any, value)
131
153
  );
132
154
  },
133
155
  update: (value: InferUpdateInput<TRequired, THasDefault>) => {
134
156
  env.addOperation(
135
- Operation.fromDefinition(operationPath, this._opDefinitions.set, value)
157
+ Operation.fromDefinition(operationPath, this._opDefinitions.set as any, value)
136
158
  );
137
159
  },
138
160
  toSnapshot: (): MaybeUndefined<number, TRequired, THasDefault> => {