@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
@@ -1,557 +0,0 @@
1
- import { describe, expect, it } from "@effect/vitest";
2
- import * as Document from "../src/Document";
3
- import * as Primitive from "../src/Primitive";
4
- import * as Transaction from "../src/Transaction";
5
- import * as OperationPath from "../src/OperationPath";
6
-
7
- describe("Document", () => {
8
- describe("make", () => {
9
- it("creates a document with a schema", () => {
10
- const schema = Primitive.Struct({
11
- name: Primitive.String(),
12
- age: Primitive.Number(),
13
- });
14
-
15
- const doc = Document.make(schema);
16
-
17
- expect(doc.schema).toBe(schema);
18
- expect(doc.root).toBeDefined();
19
- });
20
-
21
- it("initializes with default values from schema", () => {
22
- const schema = Primitive.Struct({
23
- name: Primitive.String().default("John"),
24
- age: Primitive.Number().default(25),
25
- });
26
-
27
- const doc = Document.make(schema);
28
-
29
- expect(doc.get()).toEqual({ name: "John", age: 25 });
30
- });
31
-
32
- it("initializes with provided initial state", () => {
33
- const schema = Primitive.Struct({
34
- name: Primitive.String(),
35
- age: Primitive.Number(),
36
- });
37
-
38
- const doc = Document.make(schema, {
39
- initial: { name: "Jane", age: 30 },
40
- });
41
-
42
- expect(doc.get()).toEqual({ name: "Jane", age: 30 });
43
- });
44
-
45
- it("returns undefined state when no defaults or initial value", () => {
46
- const schema = Primitive.Struct({
47
- name: Primitive.String(),
48
- age: Primitive.Number(),
49
- });
50
-
51
- const doc = Document.make(schema);
52
-
53
- expect(doc.get()).toBeUndefined();
54
- });
55
- });
56
-
57
- describe("root proxy", () => {
58
- it("get() returns current field value", () => {
59
- const schema = Primitive.Struct({
60
- name: Primitive.String(),
61
- });
62
-
63
- const doc = Document.make(schema, {
64
- initial: { name: "Alice" },
65
- });
66
-
67
- expect(doc.root.name.get()).toBe("Alice");
68
- });
69
-
70
- it("set() updates state and generates operation", () => {
71
- const schema = Primitive.Struct({
72
- name: Primitive.String(),
73
- });
74
-
75
- const doc = Document.make(schema, {
76
- initial: { name: "Alice" },
77
- });
78
-
79
- doc.root.name.set("Bob");
80
-
81
- expect(doc.root.name.get()).toBe("Bob");
82
- expect(doc.get()).toEqual({ name: "Bob" });
83
- });
84
-
85
- it("nested field access works correctly", () => {
86
- const schema = Primitive.Struct({
87
- user: Primitive.Struct({
88
- profile: Primitive.Struct({
89
- email: Primitive.String(),
90
- }),
91
- }),
92
- });
93
-
94
- const doc = Document.make(schema, {
95
- initial: {
96
- user: {
97
- profile: {
98
- email: "old@example.com",
99
- },
100
- },
101
- },
102
- });
103
-
104
- expect(doc.root.user.profile.email.get()).toBe("old@example.com");
105
-
106
- doc.root.user.profile.email.set("new@example.com");
107
-
108
- expect(doc.root.user.profile.email.get()).toBe("new@example.com");
109
- });
110
- });
111
-
112
- describe("transaction", () => {
113
- it("commits multiple operations atomically", () => {
114
- const schema = Primitive.Struct({
115
- name: Primitive.String(),
116
- age: Primitive.Number(),
117
- });
118
-
119
- const doc = Document.make(schema, {
120
- initial: { name: "Alice", age: 20 },
121
- });
122
-
123
- doc.transaction((root) => {
124
- root.name.set("Bob");
125
- root.age.set(30);
126
- });
127
-
128
- expect(doc.get()).toEqual({ name: "Bob", age: 30 });
129
- });
130
-
131
- it("returns the result of the transaction function", () => {
132
- const schema = Primitive.Struct({
133
- name: Primitive.String(),
134
- });
135
-
136
- const doc = Document.make(schema, {
137
- initial: { name: "Alice" },
138
- });
139
-
140
- const result = doc.transaction((root) => {
141
- root.name.set("Bob");
142
- return "success";
143
- });
144
-
145
- expect(result).toBe("success");
146
- });
147
-
148
- it("rolls back on error", () => {
149
- const schema = Primitive.Struct({
150
- name: Primitive.String(),
151
- age: Primitive.Number(),
152
- });
153
-
154
- const doc = Document.make(schema, {
155
- initial: { name: "Alice", age: 20 },
156
- });
157
-
158
- expect(() => {
159
- doc.transaction((root) => {
160
- root.name.set("Bob");
161
- throw new Error("Intentional error");
162
- });
163
- }).toThrow("Intentional error");
164
-
165
- // State should be rolled back
166
- expect(doc.get()).toEqual({ name: "Alice", age: 20 });
167
- });
168
-
169
- it("reads updated values within transaction", () => {
170
- const schema = Primitive.Struct({
171
- count: Primitive.Number(),
172
- });
173
-
174
- const doc = Document.make(schema, {
175
- initial: { count: 0 },
176
- });
177
-
178
- doc.transaction((root) => {
179
- root.count.set(1);
180
- expect(root.count.get()).toBe(1);
181
-
182
- root.count.set(2);
183
- expect(root.count.get()).toBe(2);
184
- });
185
-
186
- expect(doc.root.count.get()).toBe(2);
187
- });
188
-
189
- it("throws NestedTransactionError for nested transactions", () => {
190
- const schema = Primitive.Struct({
191
- name: Primitive.String(),
192
- });
193
-
194
- const doc = Document.make(schema);
195
-
196
- expect(() => {
197
- doc.transaction((root) => {
198
- doc.transaction((innerRoot) => {
199
- innerRoot.name.set("nested");
200
- });
201
- });
202
- }).toThrow(Document.NestedTransactionError);
203
- });
204
-
205
- it("operations outside transaction are auto-wrapped", () => {
206
- const schema = Primitive.Struct({
207
- name: Primitive.String(),
208
- });
209
-
210
- const doc = Document.make(schema, {
211
- initial: { name: "Alice" },
212
- });
213
-
214
- // Direct set outside transaction
215
- doc.root.name.set("Bob");
216
-
217
- expect(doc.get()).toEqual({ name: "Bob" });
218
-
219
- // Should have pending operations
220
- const tx = doc.flush();
221
- expect(tx.ops).toHaveLength(1);
222
- expect(tx.ops[0]!.kind).toBe("string.set");
223
- });
224
- });
225
-
226
- describe("flush", () => {
227
- it("returns pending operations as a transaction", () => {
228
- const schema = Primitive.Struct({
229
- name: Primitive.String(),
230
- age: Primitive.Number(),
231
- });
232
-
233
- const doc = Document.make(schema, {
234
- initial: { name: "Alice", age: 20 },
235
- });
236
-
237
- doc.transaction((root) => {
238
- root.name.set("Bob");
239
- root.age.set(30);
240
- });
241
-
242
- const tx = doc.flush();
243
-
244
- expect(tx.ops).toHaveLength(2);
245
- expect(tx.id).toBeDefined();
246
- expect(tx.timestamp).toBeDefined();
247
- });
248
-
249
- it("clears pending operations after flush", () => {
250
- const schema = Primitive.Struct({
251
- name: Primitive.String(),
252
- });
253
-
254
- const doc = Document.make(schema, {
255
- initial: { name: "Alice" },
256
- });
257
-
258
- doc.root.name.set("Bob");
259
-
260
- const tx1 = doc.flush();
261
- expect(tx1.ops).toHaveLength(1);
262
-
263
- const tx2 = doc.flush();
264
- expect(tx2.ops).toHaveLength(0);
265
- });
266
-
267
- it("returns empty transaction when no pending operations", () => {
268
- const schema = Primitive.Struct({
269
- name: Primitive.String(),
270
- });
271
-
272
- const doc = Document.make(schema);
273
-
274
- const tx = doc.flush();
275
-
276
- expect(tx.ops).toHaveLength(0);
277
- expect(Transaction.isEmpty(tx)).toBe(true);
278
- });
279
- });
280
-
281
- describe("apply", () => {
282
- it("applies external operations to state", () => {
283
- const schema = Primitive.Struct({
284
- name: Primitive.String(),
285
- });
286
-
287
- const doc = Document.make(schema, {
288
- initial: { name: "Alice" },
289
- });
290
-
291
- doc.apply([
292
- {
293
- kind: "string.set",
294
- path: OperationPath.make("name"),
295
- payload: "Bob",
296
- },
297
- ]);
298
-
299
- expect(doc.get()).toEqual({ name: "Bob" });
300
- });
301
-
302
- it("applied operations are not added to pending", () => {
303
- const schema = Primitive.Struct({
304
- name: Primitive.String(),
305
- });
306
-
307
- const doc = Document.make(schema, {
308
- initial: { name: "Alice" },
309
- });
310
-
311
- doc.apply([
312
- {
313
- kind: "string.set",
314
- path: OperationPath.make("name"),
315
- payload: "Bob",
316
- },
317
- ]);
318
-
319
- const tx = doc.flush();
320
- expect(tx.ops).toHaveLength(0);
321
- });
322
-
323
- it("applies multiple operations in sequence", () => {
324
- const schema = Primitive.Struct({
325
- name: Primitive.String(),
326
- age: Primitive.Number(),
327
- });
328
-
329
- const doc = Document.make(schema, {
330
- initial: { name: "Alice", age: 20 },
331
- });
332
-
333
- doc.apply([
334
- {
335
- kind: "string.set",
336
- path: OperationPath.make("name"),
337
- payload: "Bob",
338
- },
339
- {
340
- kind: "number.set",
341
- path: OperationPath.make("age"),
342
- payload: 30,
343
- },
344
- ]);
345
-
346
- expect(doc.get()).toEqual({ name: "Bob", age: 30 });
347
- });
348
-
349
- it("throws OperationError for invalid operations", () => {
350
- const schema = Primitive.Struct({
351
- name: Primitive.String(),
352
- });
353
-
354
- const doc = Document.make(schema, {
355
- initial: { name: "Alice" },
356
- });
357
-
358
- expect(() => {
359
- doc.apply([
360
- {
361
- kind: "string.set",
362
- path: OperationPath.make("name"),
363
- payload: 123, // Invalid: number instead of string
364
- },
365
- ]);
366
- }).toThrow(Document.OperationError);
367
- });
368
- });
369
-
370
- describe("arrays", () => {
371
- it("works with array primitives", () => {
372
- const schema = Primitive.Struct({
373
- items: Primitive.Array(Primitive.String()),
374
- });
375
-
376
- const doc = Document.make(schema, {
377
- initial: { items: [] },
378
- });
379
-
380
- doc.root.items.push("first");
381
-
382
- const items = doc.root.items.get();
383
- expect(items).toHaveLength(1);
384
- expect(items[0]!.value).toBe("first");
385
- });
386
-
387
- it("array operations generate correct pending ops", () => {
388
- const schema = Primitive.Struct({
389
- items: Primitive.Array(Primitive.String()),
390
- });
391
-
392
- const doc = Document.make(schema, {
393
- initial: { items: [] },
394
- });
395
-
396
- doc.transaction((root) => {
397
- root.items.push("first");
398
- root.items.push("second");
399
- });
400
-
401
- const tx = doc.flush();
402
- expect(tx.ops).toHaveLength(2);
403
- expect(tx.ops[0]!.kind).toBe("array.insert");
404
- expect(tx.ops[1]!.kind).toBe("array.insert");
405
- });
406
-
407
- it("modifying array elements works", () => {
408
- const schema = Primitive.Struct({
409
- users: Primitive.Array(
410
- Primitive.Struct({
411
- name: Primitive.String(),
412
- })
413
- ),
414
- });
415
-
416
- const entryId = "test-entry-id";
417
- const doc = Document.make(schema, {
418
- initial: {
419
- users: [{ id: entryId, pos: "a0", value: { name: "Alice" } }],
420
- },
421
- });
422
-
423
- doc.root.users.at(entryId).name.set("Bob");
424
-
425
- const users = doc.root.users.get();
426
- expect(users[0]!.value.name).toBe("Bob");
427
- });
428
- });
429
-
430
- describe("complex scenarios", () => {
431
- it("handles interleaved local and remote operations", () => {
432
- const schema = Primitive.Struct({
433
- counter: Primitive.Number(),
434
- });
435
-
436
- const doc = Document.make(schema, {
437
- initial: { counter: 0 },
438
- });
439
-
440
- // Local operation
441
- doc.root.counter.set(1);
442
-
443
- // Remote operation
444
- doc.apply([
445
- {
446
- kind: "number.set",
447
- path: OperationPath.make("counter"),
448
- payload: 10,
449
- },
450
- ]);
451
-
452
- // Another local operation
453
- doc.root.counter.set(11);
454
-
455
- expect(doc.get()).toEqual({ counter: 11 });
456
-
457
- // Only local ops should be pending (deduplicable ops on same path are collapsed)
458
- const tx = doc.flush();
459
- expect(tx.ops).toHaveLength(1);
460
- expect(tx.ops[0].payload).toBe(11);
461
- });
462
-
463
- it("handles struct with all primitive types", () => {
464
- const schema = Primitive.Struct({
465
- str: Primitive.String(),
466
- num: Primitive.Number(),
467
- bool: Primitive.Boolean(),
468
- literal: Primitive.Literal("status" as const),
469
- });
470
-
471
- const doc = Document.make(schema, {
472
- initial: {
473
- str: "hello",
474
- num: 42,
475
- bool: true,
476
- literal: "status",
477
- },
478
- });
479
-
480
- doc.transaction((root) => {
481
- root.str.set("world");
482
- root.num.set(100);
483
- root.bool.set(false);
484
- });
485
-
486
- expect(doc.get()).toEqual({
487
- str: "world",
488
- num: 100,
489
- bool: false,
490
- literal: "status",
491
- });
492
- });
493
- });
494
-
495
- describe("toSnapshot", () => {
496
- it("returns snapshot of document state", () => {
497
- const schema = Primitive.Struct({
498
- name: Primitive.String(),
499
- age: Primitive.Number(),
500
- });
501
-
502
- const doc = Document.make(schema, {
503
- initial: { name: "Alice", age: 30 },
504
- });
505
-
506
- const snapshot = doc.toSnapshot();
507
-
508
- expect(snapshot).toEqual({ name: "Alice", age: 30 });
509
- });
510
-
511
- it("respects field defaults in snapshot", () => {
512
- const schema = Primitive.Struct({
513
- name: Primitive.String().default("Unknown"),
514
- count: Primitive.Number().default(0),
515
- });
516
-
517
- const doc = Document.make(schema);
518
-
519
- const snapshot = doc.toSnapshot();
520
-
521
- expect(snapshot).toEqual({ name: "Unknown", count: 0 });
522
- });
523
-
524
- it("reflects state changes in snapshot", () => {
525
- const schema = Primitive.Struct({
526
- name: Primitive.String(),
527
- });
528
-
529
- const doc = Document.make(schema, {
530
- initial: { name: "Alice" },
531
- });
532
-
533
- expect(doc.toSnapshot()).toEqual({ name: "Alice" });
534
-
535
- doc.root.name.set("Bob");
536
-
537
- expect(doc.toSnapshot()).toEqual({ name: "Bob" });
538
- });
539
-
540
- it("handles arrays in snapshot", () => {
541
- const schema = Primitive.Struct({
542
- items: Primitive.Array(Primitive.String()),
543
- });
544
-
545
- const doc = Document.make(schema);
546
-
547
- doc.root.items.push("first");
548
- doc.root.items.push("second");
549
-
550
- const snapshot = doc.toSnapshot();
551
-
552
- expect(snapshot?.items).toHaveLength(2);
553
- expect(snapshot?.items[0]?.value).toBe("first");
554
- expect(snapshot?.items[1]?.value).toBe("second");
555
- });
556
- });
557
- });