@voidhash/mimic 0.0.1-alpha.1 → 0.0.1-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs ADDED
@@ -0,0 +1,2550 @@
1
+ import { t as __export } from "./chunk-C6wwvPpM.mjs";
2
+ import { Effect, Schema } from "effect";
3
+ import * as Schema$1 from "effect/Schema";
4
+
5
+ //#region \0@oxc-project+runtime@0.103.0/helpers/typeof.js
6
+ function _typeof(o) {
7
+ "@babel/helpers - typeof";
8
+ return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(o$1) {
9
+ return typeof o$1;
10
+ } : function(o$1) {
11
+ return o$1 && "function" == typeof Symbol && o$1.constructor === Symbol && o$1 !== Symbol.prototype ? "symbol" : typeof o$1;
12
+ }, _typeof(o);
13
+ }
14
+
15
+ //#endregion
16
+ //#region \0@oxc-project+runtime@0.103.0/helpers/toPrimitive.js
17
+ function toPrimitive(t, r) {
18
+ if ("object" != _typeof(t) || !t) return t;
19
+ var e = t[Symbol.toPrimitive];
20
+ if (void 0 !== e) {
21
+ var i = e.call(t, r || "default");
22
+ if ("object" != _typeof(i)) return i;
23
+ throw new TypeError("@@toPrimitive must return a primitive value.");
24
+ }
25
+ return ("string" === r ? String : Number)(t);
26
+ }
27
+
28
+ //#endregion
29
+ //#region \0@oxc-project+runtime@0.103.0/helpers/toPropertyKey.js
30
+ function toPropertyKey(t) {
31
+ var i = toPrimitive(t, "string");
32
+ return "symbol" == _typeof(i) ? i : i + "";
33
+ }
34
+
35
+ //#endregion
36
+ //#region \0@oxc-project+runtime@0.103.0/helpers/defineProperty.js
37
+ function _defineProperty(e, r, t) {
38
+ return (r = toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
39
+ value: t,
40
+ enumerable: !0,
41
+ configurable: !0,
42
+ writable: !0
43
+ }) : e[r] = t, e;
44
+ }
45
+
46
+ //#endregion
47
+ //#region src/primitives/shared.ts
48
+ var ValidationError = class extends Error {
49
+ constructor(message) {
50
+ super(message);
51
+ _defineProperty(this, "_tag", "ValidationError");
52
+ this.name = "ValidationError";
53
+ }
54
+ };
55
+ /**
56
+ * Runs all validators against a value, throwing ValidationError if any fail.
57
+ */
58
+ function runValidators(value, validators) {
59
+ for (const validator of validators) if (!validator.validate(value)) throw new ValidationError(validator.message);
60
+ }
61
+ /**
62
+ * Checks if an operation is compatible with the given operation definitions.
63
+ * @param operation - The operation to check.
64
+ * @param operationDefinitions - The operation definitions to check against.
65
+ * @returns True if the operation is compatible, false otherwise.
66
+ */
67
+ function isCompatibleOperation(operation, operationDefinitions) {
68
+ return Object.values(operationDefinitions).some((value) => value.kind === operation.kind);
69
+ }
70
+
71
+ //#endregion
72
+ //#region src/OperationDefinition.ts
73
+ const make$5 = (options) => {
74
+ return {
75
+ kind: options.kind,
76
+ payload: options.payload,
77
+ target: options.target,
78
+ apply: options.apply
79
+ };
80
+ };
81
+
82
+ //#endregion
83
+ //#region src/OperationPath.ts
84
+ var OperationPath_exports = /* @__PURE__ */ __export({
85
+ decode: () => decode$2,
86
+ encode: () => encode$2,
87
+ fromTokens: () => fromTokens,
88
+ getRelativePath: () => getRelativePath,
89
+ isPrefix: () => isPrefix,
90
+ make: () => make$4,
91
+ pathsEqual: () => pathsEqual,
92
+ pathsOverlap: () => pathsOverlap
93
+ });
94
+ const parseStringPath = (stringPath) => {
95
+ return stringPath.split("/");
96
+ };
97
+ const makeStringPathFromTokens = (tokens) => {
98
+ return tokens.join("/");
99
+ };
100
+ /**
101
+ * Creates a new operation path.
102
+ * @param stringPath - The string path to create the path from.
103
+ * @returns The new operation path.
104
+ */
105
+ function make$4(stringPath) {
106
+ const tokensInternal = stringPath ? parseStringPath(stringPath) : [];
107
+ /**
108
+ * Returns the tokens of the path.
109
+ * @returns The tokens of the path.
110
+ */
111
+ const toTokens = () => {
112
+ return tokensInternal;
113
+ };
114
+ /**
115
+ * Concatenates two paths.
116
+ * @param other - The other path to concatenate.
117
+ * @returns The new path.
118
+ */
119
+ const concat = (other) => {
120
+ return make$4(makeStringPathFromTokens(toTokens().concat(other.toTokens())));
121
+ };
122
+ /**
123
+ * Appends a token to the path.
124
+ * @param token - The token to append.
125
+ * @returns The new path.
126
+ */
127
+ const append = (token) => {
128
+ return make$4(makeStringPathFromTokens(toTokens().concat([token])));
129
+ };
130
+ /**
131
+ * Removes the last token from the path.
132
+ * @returns The new path.
133
+ */
134
+ const pop = () => {
135
+ return make$4(makeStringPathFromTokens(toTokens().slice(0, -1)));
136
+ };
137
+ /**
138
+ * Removes the first token from the path.
139
+ * @returns The new path.
140
+ */
141
+ const shift = () => {
142
+ return make$4(makeStringPathFromTokens(toTokens().slice(1)));
143
+ };
144
+ return {
145
+ _tag: "OperationPath",
146
+ toTokens,
147
+ concat,
148
+ append,
149
+ pop,
150
+ shift
151
+ };
152
+ }
153
+ /**
154
+ * Creates a new operation path from tokens.
155
+ * @param tokens - The tokens to create the path from.
156
+ * @returns The new operation path.
157
+ */
158
+ function fromTokens(tokens) {
159
+ return make$4(makeStringPathFromTokens(tokens));
160
+ }
161
+ /**
162
+ * Checks if two operation paths overlap (one is prefix of the other or equal).
163
+ */
164
+ const pathsOverlap = (pathA, pathB) => {
165
+ const tokensA = pathA.toTokens().filter((t) => t !== "");
166
+ const tokensB = pathB.toTokens().filter((t) => t !== "");
167
+ const minLength = Math.min(tokensA.length, tokensB.length);
168
+ for (let i = 0; i < minLength; i++) if (tokensA[i] !== tokensB[i]) return false;
169
+ return true;
170
+ };
171
+ /**
172
+ * Checks if pathA is a prefix of pathB (pathA is ancestor of pathB).
173
+ */
174
+ const isPrefix = (pathA, pathB) => {
175
+ const tokensA = pathA.toTokens().filter((t) => t !== "");
176
+ const tokensB = pathB.toTokens().filter((t) => t !== "");
177
+ if (tokensA.length > tokensB.length) return false;
178
+ for (let i = 0; i < tokensA.length; i++) if (tokensA[i] !== tokensB[i]) return false;
179
+ return true;
180
+ };
181
+ /**
182
+ * Checks if two paths are exactly equal.
183
+ */
184
+ const pathsEqual = (pathA, pathB) => {
185
+ const tokensA = pathA.toTokens().filter((t) => t !== "");
186
+ const tokensB = pathB.toTokens().filter((t) => t !== "");
187
+ if (tokensA.length !== tokensB.length) return false;
188
+ for (let i = 0; i < tokensA.length; i++) if (tokensA[i] !== tokensB[i]) return false;
189
+ return true;
190
+ };
191
+ /**
192
+ * Gets the relative path of pathB with respect to pathA.
193
+ * Assumes pathA is a prefix of pathB.
194
+ */
195
+ const getRelativePath = (basePath, fullPath) => {
196
+ const baseTokens = basePath.toTokens().filter((t) => t !== "");
197
+ return fullPath.toTokens().filter((t) => t !== "").slice(baseTokens.length);
198
+ };
199
+ /**
200
+ * Encodes an OperationPath to a string for network transport.
201
+ * @param path - The operation path to encode.
202
+ * @returns The encoded string representation.
203
+ */
204
+ const encode$2 = (path) => {
205
+ return makeStringPathFromTokens(path.toTokens());
206
+ };
207
+ /**
208
+ * Decodes an encoded string back to an OperationPath.
209
+ * @param encoded - The encoded string representation.
210
+ * @returns The decoded OperationPath.
211
+ */
212
+ const decode$2 = (encoded) => {
213
+ return make$4(encoded);
214
+ };
215
+
216
+ //#endregion
217
+ //#region src/Operation.ts
218
+ var Operation_exports = /* @__PURE__ */ __export({
219
+ decode: () => decode$1,
220
+ encode: () => encode$1,
221
+ fromDefinition: () => fromDefinition
222
+ });
223
+ const fromDefinition = (operationPath, definition, payload) => {
224
+ return {
225
+ kind: definition.kind,
226
+ path: operationPath,
227
+ payload
228
+ };
229
+ };
230
+ /**
231
+ * Encodes an Operation to a JSON-serializable format for network transport.
232
+ * @param operation - The operation to encode.
233
+ * @returns The encoded representation.
234
+ */
235
+ const encode$1 = (operation) => {
236
+ return {
237
+ kind: operation.kind,
238
+ path: encode$2(operation.path),
239
+ payload: operation.payload
240
+ };
241
+ };
242
+ /**
243
+ * Decodes an encoded operation back to an Operation.
244
+ * Note: This returns a partial operation without the definition methods.
245
+ * The caller must have the operation definitions to fully reconstruct if needed.
246
+ * @param encoded - The encoded representation.
247
+ * @returns The decoded Operation (without definition-specific methods).
248
+ */
249
+ const decode$1 = (encoded) => {
250
+ return {
251
+ kind: encoded.kind,
252
+ path: decode$2(encoded.path),
253
+ payload: encoded.payload
254
+ };
255
+ };
256
+
257
+ //#endregion
258
+ //#region \0@oxc-project+runtime@0.103.0/helpers/objectSpread2.js
259
+ function ownKeys(e, r) {
260
+ var t = Object.keys(e);
261
+ if (Object.getOwnPropertySymbols) {
262
+ var o = Object.getOwnPropertySymbols(e);
263
+ r && (o = o.filter(function(r$1) {
264
+ return Object.getOwnPropertyDescriptor(e, r$1).enumerable;
265
+ })), t.push.apply(t, o);
266
+ }
267
+ return t;
268
+ }
269
+ function _objectSpread2(e) {
270
+ for (var r = 1; r < arguments.length; r++) {
271
+ var t = null != arguments[r] ? arguments[r] : {};
272
+ r % 2 ? ownKeys(Object(t), !0).forEach(function(r$1) {
273
+ _defineProperty(e, r$1, t[r$1]);
274
+ }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function(r$1) {
275
+ Object.defineProperty(e, r$1, Object.getOwnPropertyDescriptor(t, r$1));
276
+ });
277
+ }
278
+ return e;
279
+ }
280
+
281
+ //#endregion
282
+ //#region src/primitives/String.ts
283
+ var StringPrimitive = class StringPrimitive {
284
+ constructor(schema) {
285
+ _defineProperty(this, "_tag", "StringPrimitive");
286
+ _defineProperty(this, "_State", void 0);
287
+ _defineProperty(this, "_Proxy", void 0);
288
+ _defineProperty(this, "_schema", void 0);
289
+ _defineProperty(this, "_opDefinitions", { set: make$5({
290
+ kind: "string.set",
291
+ payload: Schema.String,
292
+ target: Schema.String,
293
+ apply: (payload) => payload
294
+ }) });
295
+ _defineProperty(this, "_internal", {
296
+ createProxy: (env, operationPath) => {
297
+ const defaultValue = this._schema.defaultValue;
298
+ return {
299
+ get: () => {
300
+ const state = env.getState(operationPath);
301
+ return state !== null && state !== void 0 ? state : defaultValue;
302
+ },
303
+ set: (value) => {
304
+ env.addOperation(fromDefinition(operationPath, this._opDefinitions.set, value));
305
+ },
306
+ toSnapshot: () => {
307
+ const state = env.getState(operationPath);
308
+ return state !== null && state !== void 0 ? state : defaultValue;
309
+ }
310
+ };
311
+ },
312
+ applyOperation: (state, operation) => {
313
+ if (!isCompatibleOperation(operation, this._opDefinitions)) throw new ValidationError(`StringPrimitive cannot apply operation of kind: ${operation.kind}`);
314
+ const payload = operation.payload;
315
+ if (typeof payload !== "string") throw new ValidationError(`StringPrimitive.set requires a string payload, got: ${typeof payload}`);
316
+ runValidators(payload, this._schema.validators);
317
+ return payload;
318
+ },
319
+ getInitialState: () => {
320
+ return this._schema.defaultValue;
321
+ },
322
+ transformOperation: (clientOp, serverOp) => {
323
+ if (!pathsOverlap(clientOp.path, serverOp.path)) return {
324
+ type: "transformed",
325
+ operation: clientOp
326
+ };
327
+ return {
328
+ type: "transformed",
329
+ operation: clientOp
330
+ };
331
+ }
332
+ });
333
+ this._schema = schema;
334
+ }
335
+ /** Mark this string as required */
336
+ required() {
337
+ return new StringPrimitive(_objectSpread2(_objectSpread2({}, this._schema), {}, { required: true }));
338
+ }
339
+ /** Set a default value for this string */
340
+ default(defaultValue) {
341
+ return new StringPrimitive(_objectSpread2(_objectSpread2({}, this._schema), {}, { defaultValue }));
342
+ }
343
+ /** Add a custom validation rule */
344
+ refine(fn, message) {
345
+ return new StringPrimitive(_objectSpread2(_objectSpread2({}, this._schema), {}, { validators: [...this._schema.validators, {
346
+ validate: fn,
347
+ message
348
+ }] }));
349
+ }
350
+ /** Minimum string length */
351
+ min(length) {
352
+ return this.refine((v) => v.length >= length, `String must be at least ${length} characters`);
353
+ }
354
+ /** Maximum string length */
355
+ max(length) {
356
+ return this.refine((v) => v.length <= length, `String must be at most ${length} characters`);
357
+ }
358
+ /** Exact string length */
359
+ length(exact) {
360
+ return this.refine((v) => v.length === exact, `String must be exactly ${exact} characters`);
361
+ }
362
+ /** Match a regex pattern */
363
+ regex(pattern, message) {
364
+ return this.refine((v) => pattern.test(v), message !== null && message !== void 0 ? message : `String must match pattern ${pattern}`);
365
+ }
366
+ /** Validate as email format */
367
+ email() {
368
+ const emailPattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
369
+ return this.refine((v) => emailPattern.test(v), "Invalid email format");
370
+ }
371
+ /** Validate as URL format */
372
+ url() {
373
+ return this.refine((v) => {
374
+ try {
375
+ new URL(v);
376
+ return true;
377
+ } catch (_unused) {
378
+ return false;
379
+ }
380
+ }, "Invalid URL format");
381
+ }
382
+ };
383
+ /** Creates a new StringPrimitive */
384
+ const String$1 = () => new StringPrimitive({
385
+ required: false,
386
+ defaultValue: void 0,
387
+ validators: []
388
+ });
389
+
390
+ //#endregion
391
+ //#region src/primitives/Struct.ts
392
+ var StructPrimitive = class StructPrimitive {
393
+ constructor(schema) {
394
+ _defineProperty(this, "_tag", "StructPrimitive");
395
+ _defineProperty(this, "_State", void 0);
396
+ _defineProperty(this, "_Proxy", void 0);
397
+ _defineProperty(this, "_schema", void 0);
398
+ _defineProperty(this, "_opDefinitions", { set: make$5({
399
+ kind: "struct.set",
400
+ payload: Schema.Unknown,
401
+ target: Schema.Unknown,
402
+ apply: (payload) => payload
403
+ }) });
404
+ _defineProperty(this, "_internal", {
405
+ createProxy: (env, operationPath) => {
406
+ const fields = this._schema.fields;
407
+ const defaultValue = this._schema.defaultValue;
408
+ const buildSnapshot = () => {
409
+ const state = env.getState(operationPath);
410
+ const snapshot = {};
411
+ let hasAnyDefinedField = false;
412
+ for (const key in fields) {
413
+ const fieldPrimitive = fields[key];
414
+ const fieldPath = operationPath.append(key);
415
+ const fieldSnapshot = fieldPrimitive._internal.createProxy(env, fieldPath).toSnapshot();
416
+ snapshot[key] = fieldSnapshot;
417
+ if (fieldSnapshot !== void 0) hasAnyDefinedField = true;
418
+ }
419
+ if (state === void 0 && defaultValue === void 0 && !hasAnyDefinedField) return;
420
+ return snapshot;
421
+ };
422
+ return new globalThis.Proxy({
423
+ get: () => {
424
+ const state = env.getState(operationPath);
425
+ return state !== null && state !== void 0 ? state : defaultValue;
426
+ },
427
+ set: (value) => {
428
+ env.addOperation(fromDefinition(operationPath, this._opDefinitions.set, value));
429
+ },
430
+ toSnapshot: () => {
431
+ return buildSnapshot();
432
+ }
433
+ }, {
434
+ get: (target, prop, receiver) => {
435
+ if (prop === "get") return target.get;
436
+ if (prop === "set") return target.set;
437
+ if (prop === "toSnapshot") return target.toSnapshot;
438
+ if (typeof prop === "symbol") return;
439
+ if (prop in fields) {
440
+ const fieldPrimitive = fields[prop];
441
+ const fieldPath = operationPath.append(prop);
442
+ return fieldPrimitive._internal.createProxy(env, fieldPath);
443
+ }
444
+ },
445
+ has: (target, prop) => {
446
+ if (prop === "get" || prop === "set" || prop === "toSnapshot") return true;
447
+ if (typeof prop === "string" && prop in fields) return true;
448
+ return false;
449
+ }
450
+ });
451
+ },
452
+ applyOperation: (state, operation) => {
453
+ const path = operation.path;
454
+ const tokens = path.toTokens().filter((t) => t !== "");
455
+ let newState;
456
+ if (tokens.length === 0) {
457
+ if (operation.kind !== "struct.set") throw new ValidationError(`StructPrimitive root cannot apply operation of kind: ${operation.kind}`);
458
+ const payload = operation.payload;
459
+ if (typeof payload !== "object" || payload === null) throw new ValidationError(`StructPrimitive.set requires an object payload`);
460
+ newState = payload;
461
+ } else {
462
+ const fieldName = tokens[0];
463
+ if (!(fieldName in this._schema.fields)) throw new ValidationError(`Unknown field: ${globalThis.String(fieldName)}`);
464
+ const fieldPrimitive = this._schema.fields[fieldName];
465
+ const remainingPath = path.shift();
466
+ const fieldOperation = _objectSpread2(_objectSpread2({}, operation), {}, { path: remainingPath });
467
+ const currentState = state !== null && state !== void 0 ? state : {};
468
+ const currentFieldState = currentState[fieldName];
469
+ const newFieldState = fieldPrimitive._internal.applyOperation(currentFieldState, fieldOperation);
470
+ newState = _objectSpread2(_objectSpread2({}, currentState), {}, { [fieldName]: newFieldState });
471
+ }
472
+ runValidators(newState, this._schema.validators);
473
+ return newState;
474
+ },
475
+ getInitialState: () => {
476
+ if (this._schema.defaultValue !== void 0) return this._schema.defaultValue;
477
+ const fields = this._schema.fields;
478
+ const initialState = {};
479
+ let hasAnyDefault = false;
480
+ for (const key in fields) {
481
+ const fieldDefault = fields[key]._internal.getInitialState();
482
+ if (fieldDefault !== void 0) {
483
+ initialState[key] = fieldDefault;
484
+ hasAnyDefault = true;
485
+ }
486
+ }
487
+ return hasAnyDefault ? initialState : void 0;
488
+ },
489
+ transformOperation: (clientOp, serverOp) => {
490
+ const clientPath = clientOp.path;
491
+ const serverPath = serverOp.path;
492
+ if (!pathsOverlap(clientPath, serverPath)) return {
493
+ type: "transformed",
494
+ operation: clientOp
495
+ };
496
+ const clientTokens = clientPath.toTokens().filter((t) => t !== "");
497
+ const serverTokens = serverPath.toTokens().filter((t) => t !== "");
498
+ if (clientTokens.length === 0 && serverTokens.length === 0) return {
499
+ type: "transformed",
500
+ operation: clientOp
501
+ };
502
+ if (serverTokens.length === 0 && serverOp.kind === "struct.set") return {
503
+ type: "transformed",
504
+ operation: clientOp
505
+ };
506
+ if (clientTokens.length === 0 && clientOp.kind === "struct.set") return {
507
+ type: "transformed",
508
+ operation: clientOp
509
+ };
510
+ if (clientTokens.length > 0 && serverTokens.length > 0) {
511
+ const clientField = clientTokens[0];
512
+ if (clientField !== serverTokens[0]) return {
513
+ type: "transformed",
514
+ operation: clientOp
515
+ };
516
+ const fieldPrimitive = this._schema.fields[clientField];
517
+ if (!fieldPrimitive) return {
518
+ type: "transformed",
519
+ operation: clientOp
520
+ };
521
+ const clientOpForField = _objectSpread2(_objectSpread2({}, clientOp), {}, { path: clientOp.path.shift() });
522
+ const serverOpForField = _objectSpread2(_objectSpread2({}, serverOp), {}, { path: serverOp.path.shift() });
523
+ const result = fieldPrimitive._internal.transformOperation(clientOpForField, serverOpForField);
524
+ if (result.type === "transformed") return {
525
+ type: "transformed",
526
+ operation: _objectSpread2(_objectSpread2({}, result.operation), {}, { path: clientOp.path })
527
+ };
528
+ return result;
529
+ }
530
+ return {
531
+ type: "transformed",
532
+ operation: clientOp
533
+ };
534
+ }
535
+ });
536
+ this._schema = schema;
537
+ }
538
+ /** Mark this struct as required */
539
+ required() {
540
+ return new StructPrimitive(_objectSpread2(_objectSpread2({}, this._schema), {}, { required: true }));
541
+ }
542
+ /** Set a default value for this struct */
543
+ default(defaultValue) {
544
+ return new StructPrimitive(_objectSpread2(_objectSpread2({}, this._schema), {}, { defaultValue }));
545
+ }
546
+ /** Get the fields schema */
547
+ get fields() {
548
+ return this._schema.fields;
549
+ }
550
+ /** Add a custom validation rule (useful for cross-field validation) */
551
+ refine(fn, message) {
552
+ return new StructPrimitive(_objectSpread2(_objectSpread2({}, this._schema), {}, { validators: [...this._schema.validators, {
553
+ validate: fn,
554
+ message
555
+ }] }));
556
+ }
557
+ };
558
+ /** Creates a new StructPrimitive with the given fields */
559
+ const Struct = (fields) => new StructPrimitive({
560
+ required: false,
561
+ defaultValue: void 0,
562
+ fields,
563
+ validators: []
564
+ });
565
+
566
+ //#endregion
567
+ //#region src/primitives/Boolean.ts
568
+ var BooleanPrimitive = class BooleanPrimitive {
569
+ constructor(schema) {
570
+ _defineProperty(this, "_tag", "BooleanPrimitive");
571
+ _defineProperty(this, "_State", void 0);
572
+ _defineProperty(this, "_Proxy", void 0);
573
+ _defineProperty(this, "_schema", void 0);
574
+ _defineProperty(this, "_opDefinitions", { set: make$5({
575
+ kind: "boolean.set",
576
+ payload: Schema.Boolean,
577
+ target: Schema.Boolean,
578
+ apply: (payload) => payload
579
+ }) });
580
+ _defineProperty(this, "_internal", {
581
+ createProxy: (env, operationPath) => {
582
+ const defaultValue = this._schema.defaultValue;
583
+ return {
584
+ get: () => {
585
+ const state = env.getState(operationPath);
586
+ return state !== null && state !== void 0 ? state : defaultValue;
587
+ },
588
+ set: (value) => {
589
+ env.addOperation(fromDefinition(operationPath, this._opDefinitions.set, value));
590
+ },
591
+ toSnapshot: () => {
592
+ const state = env.getState(operationPath);
593
+ return state !== null && state !== void 0 ? state : defaultValue;
594
+ }
595
+ };
596
+ },
597
+ applyOperation: (state, operation) => {
598
+ if (operation.kind !== "boolean.set") throw new ValidationError(`BooleanPrimitive cannot apply operation of kind: ${operation.kind}`);
599
+ const payload = operation.payload;
600
+ if (typeof payload !== "boolean") throw new ValidationError(`BooleanPrimitive.set requires a boolean payload, got: ${typeof payload}`);
601
+ runValidators(payload, this._schema.validators);
602
+ return payload;
603
+ },
604
+ getInitialState: () => {
605
+ return this._schema.defaultValue;
606
+ },
607
+ transformOperation: (clientOp, serverOp) => {
608
+ if (!pathsOverlap(clientOp.path, serverOp.path)) return {
609
+ type: "transformed",
610
+ operation: clientOp
611
+ };
612
+ return {
613
+ type: "transformed",
614
+ operation: clientOp
615
+ };
616
+ }
617
+ });
618
+ this._schema = schema;
619
+ }
620
+ /** Mark this boolean as required */
621
+ required() {
622
+ return new BooleanPrimitive(_objectSpread2(_objectSpread2({}, this._schema), {}, { required: true }));
623
+ }
624
+ /** Set a default value for this boolean */
625
+ default(defaultValue) {
626
+ return new BooleanPrimitive(_objectSpread2(_objectSpread2({}, this._schema), {}, { defaultValue }));
627
+ }
628
+ /** Add a custom validation rule */
629
+ refine(fn, message) {
630
+ return new BooleanPrimitive(_objectSpread2(_objectSpread2({}, this._schema), {}, { validators: [...this._schema.validators, {
631
+ validate: fn,
632
+ message
633
+ }] }));
634
+ }
635
+ };
636
+ /** Creates a new BooleanPrimitive */
637
+ const Boolean = () => new BooleanPrimitive({
638
+ required: false,
639
+ defaultValue: void 0,
640
+ validators: []
641
+ });
642
+
643
+ //#endregion
644
+ //#region src/primitives/Number.ts
645
+ var NumberPrimitive = class NumberPrimitive {
646
+ constructor(schema) {
647
+ _defineProperty(this, "_tag", "NumberPrimitive");
648
+ _defineProperty(this, "_State", void 0);
649
+ _defineProperty(this, "_Proxy", void 0);
650
+ _defineProperty(this, "_schema", void 0);
651
+ _defineProperty(this, "_opDefinitions", { set: make$5({
652
+ kind: "number.set",
653
+ payload: Schema.Number,
654
+ target: Schema.Number,
655
+ apply: (payload) => payload
656
+ }) });
657
+ _defineProperty(this, "_internal", {
658
+ createProxy: (env, operationPath) => {
659
+ const defaultValue = this._schema.defaultValue;
660
+ return {
661
+ get: () => {
662
+ const state = env.getState(operationPath);
663
+ return state !== null && state !== void 0 ? state : defaultValue;
664
+ },
665
+ set: (value) => {
666
+ env.addOperation(fromDefinition(operationPath, this._opDefinitions.set, value));
667
+ },
668
+ toSnapshot: () => {
669
+ const state = env.getState(operationPath);
670
+ return state !== null && state !== void 0 ? state : defaultValue;
671
+ }
672
+ };
673
+ },
674
+ applyOperation: (state, operation) => {
675
+ if (operation.kind !== "number.set") throw new ValidationError(`NumberPrimitive cannot apply operation of kind: ${operation.kind}`);
676
+ const payload = operation.payload;
677
+ if (typeof payload !== "number") throw new ValidationError(`NumberPrimitive.set requires a number payload, got: ${typeof payload}`);
678
+ runValidators(payload, this._schema.validators);
679
+ return payload;
680
+ },
681
+ getInitialState: () => {
682
+ return this._schema.defaultValue;
683
+ },
684
+ transformOperation: (clientOp, serverOp) => {
685
+ if (!pathsOverlap(clientOp.path, serverOp.path)) return {
686
+ type: "transformed",
687
+ operation: clientOp
688
+ };
689
+ return {
690
+ type: "transformed",
691
+ operation: clientOp
692
+ };
693
+ }
694
+ });
695
+ this._schema = schema;
696
+ }
697
+ /** Mark this number as required */
698
+ required() {
699
+ return new NumberPrimitive(_objectSpread2(_objectSpread2({}, this._schema), {}, { required: true }));
700
+ }
701
+ /** Set a default value for this number */
702
+ default(defaultValue) {
703
+ return new NumberPrimitive(_objectSpread2(_objectSpread2({}, this._schema), {}, { defaultValue }));
704
+ }
705
+ /** Add a custom validation rule */
706
+ refine(fn, message) {
707
+ return new NumberPrimitive(_objectSpread2(_objectSpread2({}, this._schema), {}, { validators: [...this._schema.validators, {
708
+ validate: fn,
709
+ message
710
+ }] }));
711
+ }
712
+ /** Minimum value (inclusive) */
713
+ min(value) {
714
+ return this.refine((v) => v >= value, `Number must be at least ${value}`);
715
+ }
716
+ /** Maximum value (inclusive) */
717
+ max(value) {
718
+ return this.refine((v) => v <= value, `Number must be at most ${value}`);
719
+ }
720
+ /** Must be positive (> 0) */
721
+ positive() {
722
+ return this.refine((v) => v > 0, "Number must be positive");
723
+ }
724
+ /** Must be negative (< 0) */
725
+ negative() {
726
+ return this.refine((v) => v < 0, "Number must be negative");
727
+ }
728
+ /** Must be an integer */
729
+ int() {
730
+ return this.refine((v) => globalThis.Number.isInteger(v), "Number must be an integer");
731
+ }
732
+ };
733
+ /** Creates a new NumberPrimitive */
734
+ const Number$1 = () => new NumberPrimitive({
735
+ required: false,
736
+ defaultValue: void 0,
737
+ validators: []
738
+ });
739
+
740
+ //#endregion
741
+ //#region src/primitives/Literal.ts
742
+ var LiteralPrimitive = class LiteralPrimitive {
743
+ constructor(schema) {
744
+ _defineProperty(this, "_tag", "LiteralPrimitive");
745
+ _defineProperty(this, "_State", void 0);
746
+ _defineProperty(this, "_Proxy", void 0);
747
+ _defineProperty(this, "_schema", void 0);
748
+ _defineProperty(this, "_opDefinitions", { set: make$5({
749
+ kind: "literal.set",
750
+ payload: Schema.Unknown,
751
+ target: Schema.Unknown,
752
+ apply: (payload) => payload
753
+ }) });
754
+ _defineProperty(this, "_internal", {
755
+ createProxy: (env, operationPath) => {
756
+ const defaultValue = this._schema.defaultValue;
757
+ return {
758
+ get: () => {
759
+ const state = env.getState(operationPath);
760
+ return state !== null && state !== void 0 ? state : defaultValue;
761
+ },
762
+ set: (value) => {
763
+ env.addOperation(fromDefinition(operationPath, this._opDefinitions.set, value));
764
+ },
765
+ toSnapshot: () => {
766
+ const state = env.getState(operationPath);
767
+ return state !== null && state !== void 0 ? state : defaultValue;
768
+ }
769
+ };
770
+ },
771
+ applyOperation: (state, operation) => {
772
+ if (operation.kind !== "literal.set") throw new ValidationError(`LiteralPrimitive cannot apply operation of kind: ${operation.kind}`);
773
+ const payload = operation.payload;
774
+ if (payload !== this._schema.literal) throw new ValidationError(`LiteralPrimitive.set requires the exact literal value "${globalThis.String(this._schema.literal)}", got: "${globalThis.String(payload)}"`);
775
+ return payload;
776
+ },
777
+ getInitialState: () => {
778
+ return this._schema.defaultValue;
779
+ },
780
+ transformOperation: (clientOp, serverOp) => {
781
+ if (!pathsOverlap(clientOp.path, serverOp.path)) return {
782
+ type: "transformed",
783
+ operation: clientOp
784
+ };
785
+ return {
786
+ type: "transformed",
787
+ operation: clientOp
788
+ };
789
+ }
790
+ });
791
+ this._schema = schema;
792
+ }
793
+ /** Mark this literal as required */
794
+ required() {
795
+ return new LiteralPrimitive(_objectSpread2(_objectSpread2({}, this._schema), {}, { required: true }));
796
+ }
797
+ /** Set a default value for this literal */
798
+ default(defaultValue) {
799
+ return new LiteralPrimitive(_objectSpread2(_objectSpread2({}, this._schema), {}, { defaultValue }));
800
+ }
801
+ /** Get the literal value this primitive represents */
802
+ get literal() {
803
+ return this._schema.literal;
804
+ }
805
+ };
806
+ /** Creates a new LiteralPrimitive with the given literal value */
807
+ const Literal = (literal) => new LiteralPrimitive({
808
+ required: false,
809
+ defaultValue: void 0,
810
+ literal
811
+ });
812
+
813
+ //#endregion
814
+ //#region src/FractionalIndex.ts
815
+ function createCharSetDicts(charSet) {
816
+ const byCode = {};
817
+ const byChar = {};
818
+ const length = charSet.length;
819
+ for (let i = 0; i < length; i++) {
820
+ const char = charSet[i];
821
+ if (char === void 0) throw new Error("invalid charSet: missing character at index " + i);
822
+ byCode[i] = char;
823
+ byChar[char] = i;
824
+ }
825
+ return {
826
+ byCode,
827
+ byChar,
828
+ length
829
+ };
830
+ }
831
+ function integerLimits(dicts, firstPositive, mostPositive, mostNegative) {
832
+ return Effect.gen(function* () {
833
+ const firstPositiveIndex = firstPositive ? dicts.byChar[firstPositive] : Math.ceil(dicts.length / 2);
834
+ const mostPositiveIndex = mostPositive ? dicts.byChar[mostPositive] : dicts.length - 1;
835
+ const mostNegativeIndex = mostNegative ? dicts.byChar[mostNegative] : 0;
836
+ if (firstPositiveIndex === void 0 || mostPositiveIndex === void 0 || mostNegativeIndex === void 0) return yield* Effect.fail(/* @__PURE__ */ new Error("invalid charSet"));
837
+ if (mostPositiveIndex - firstPositiveIndex < 3) return yield* Effect.fail(/* @__PURE__ */ new Error("mostPositive must be at least 3 characters away from neutral"));
838
+ if (firstPositiveIndex - mostNegativeIndex < 3) return yield* Effect.fail(/* @__PURE__ */ new Error("mostNegative must be at least 3 characters away from neutral"));
839
+ const firstPositiveChar = dicts.byCode[firstPositiveIndex];
840
+ const mostPositiveChar = dicts.byCode[mostPositiveIndex];
841
+ const firstNegativeChar = dicts.byCode[firstPositiveIndex - 1];
842
+ const mostNegativeChar = dicts.byCode[mostNegativeIndex];
843
+ if (firstPositiveChar === void 0 || mostPositiveChar === void 0 || firstNegativeChar === void 0 || mostNegativeChar === void 0) return yield* Effect.fail(/* @__PURE__ */ new Error("invalid charSet"));
844
+ return {
845
+ firstPositive: firstPositiveChar,
846
+ mostPositive: mostPositiveChar,
847
+ firstNegative: firstNegativeChar,
848
+ mostNegative: mostNegativeChar
849
+ };
850
+ });
851
+ }
852
+ function paddingDict(jitterRange, charSetLength) {
853
+ const paddingDict$1 = {};
854
+ for (let i = 0; i < 100; i++) {
855
+ const value = Math.pow(charSetLength, i);
856
+ paddingDict$1[i] = value;
857
+ if (value > jitterRange) break;
858
+ }
859
+ return paddingDict$1;
860
+ }
861
+ function validateChars(characters) {
862
+ if (characters.length < 7) return Effect.fail(/* @__PURE__ */ new Error("charSet must be at least 7 characters long"));
863
+ if (!(characters.split("").sort().join("") === characters)) return Effect.fail(/* @__PURE__ */ new Error("charSet must be sorted"));
864
+ return Effect.void;
865
+ }
866
+ function indexCharacterSet(options) {
867
+ return Effect.gen(function* () {
868
+ var _options$jitterRange;
869
+ yield* validateChars(options.chars);
870
+ const dicts = createCharSetDicts(options.chars);
871
+ const limits = yield* integerLimits(dicts, options.firstPositive, options.mostPositive, options.mostNegative);
872
+ const jitterRange = (_options$jitterRange = options.jitterRange) !== null && _options$jitterRange !== void 0 ? _options$jitterRange : Math.floor(Math.pow(dicts.length, 3) / 5);
873
+ const paddingRange = paddingDict(jitterRange, dicts.length);
874
+ const first = dicts.byCode[0];
875
+ const last = dicts.byCode[dicts.length - 1];
876
+ if (first === void 0 || last === void 0) return yield* Effect.fail(/* @__PURE__ */ new Error("invalid charSet"));
877
+ return {
878
+ chars: options.chars,
879
+ byChar: dicts.byChar,
880
+ byCode: dicts.byCode,
881
+ length: dicts.length,
882
+ first,
883
+ last,
884
+ firstPositive: limits.firstPositive,
885
+ mostPositive: limits.mostPositive,
886
+ firstNegative: limits.firstNegative,
887
+ mostNegative: limits.mostNegative,
888
+ jitterRange,
889
+ paddingDict: paddingRange
890
+ };
891
+ });
892
+ }
893
+ let _base62CharSet = null;
894
+ function base62CharSet() {
895
+ if (_base62CharSet) return _base62CharSet;
896
+ _base62CharSet = Effect.runSync(indexCharacterSet({
897
+ chars: "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
898
+ firstPositive: "a",
899
+ mostPositive: "z",
900
+ mostNegative: "A"
901
+ }));
902
+ return _base62CharSet;
903
+ }
904
+ function makeSameLength(a, b, pad, fillChar, forceLength) {
905
+ const max = forceLength !== null && forceLength !== void 0 ? forceLength : Math.max(a.length, b.length);
906
+ if (pad === "start") return [a.padStart(max, fillChar), b.padStart(max, fillChar)];
907
+ return [a.padEnd(max, fillChar), b.padEnd(max, fillChar)];
908
+ }
909
+ function distanceBetween(a, b, charSet) {
910
+ const indexA = charSet.byChar[a];
911
+ const indexB = charSet.byChar[b];
912
+ if (indexA === void 0 || indexB === void 0) return Effect.fail(/* @__PURE__ */ new Error("invalid character in distance calculation"));
913
+ return Effect.succeed(Math.abs(indexA - indexB));
914
+ }
915
+ function integerLengthFromSecondLevel(key, direction, charSet) {
916
+ if (key.length === 0) return Effect.succeed(0);
917
+ const firstChar = key[0];
918
+ if (!firstChar || firstChar > charSet.mostPositive || firstChar < charSet.mostNegative) return Effect.fail(/* @__PURE__ */ new Error("invalid firstChar on key"));
919
+ if (firstChar === charSet.mostPositive && direction === "positive") return Effect.gen(function* () {
920
+ const totalPositiveRoom = yield* distanceBetween(firstChar, charSet.mostNegative, charSet);
921
+ const rest = yield* integerLengthFromSecondLevel(key.slice(1), direction, charSet);
922
+ return totalPositiveRoom + 1 + rest;
923
+ });
924
+ if (firstChar === charSet.mostNegative && direction === "negative") return Effect.gen(function* () {
925
+ const totalNegativeRoom = yield* distanceBetween(firstChar, charSet.mostPositive, charSet);
926
+ const rest = yield* integerLengthFromSecondLevel(key.slice(1), direction, charSet);
927
+ return totalNegativeRoom + 1 + rest;
928
+ });
929
+ if (direction === "positive") return Effect.gen(function* () {
930
+ return (yield* distanceBetween(firstChar, charSet.mostNegative, charSet)) + 2;
931
+ });
932
+ else return Effect.gen(function* () {
933
+ return (yield* distanceBetween(firstChar, charSet.mostPositive, charSet)) + 2;
934
+ });
935
+ }
936
+ function integerLength(head, charSet) {
937
+ if (head.length === 0) return Effect.fail(/* @__PURE__ */ new Error("head cannot be empty"));
938
+ const firstChar = head[0];
939
+ if (!firstChar || firstChar > charSet.mostPositive || firstChar < charSet.mostNegative) return Effect.fail(/* @__PURE__ */ new Error("invalid firstChar on key"));
940
+ if (firstChar === charSet.mostPositive) return Effect.gen(function* () {
941
+ const firstLevel = yield* distanceBetween(firstChar, charSet.firstPositive, charSet);
942
+ const rest = yield* integerLengthFromSecondLevel(head.slice(1), "positive", charSet);
943
+ return firstLevel + 1 + rest;
944
+ });
945
+ if (firstChar === charSet.mostNegative) return Effect.gen(function* () {
946
+ const firstLevel = yield* distanceBetween(firstChar, charSet.firstNegative, charSet);
947
+ const rest = yield* integerLengthFromSecondLevel(head.slice(1), "negative", charSet);
948
+ return firstLevel + 1 + rest;
949
+ });
950
+ if (firstChar >= charSet.firstPositive) return Effect.gen(function* () {
951
+ return (yield* distanceBetween(firstChar, charSet.firstPositive, charSet)) + 2;
952
+ });
953
+ else return Effect.gen(function* () {
954
+ return (yield* distanceBetween(firstChar, charSet.firstNegative, charSet)) + 2;
955
+ });
956
+ }
957
+ function encodeToCharSet(int, charSet) {
958
+ if (int === 0) {
959
+ const zero = charSet.byCode[0];
960
+ if (zero === void 0) return Effect.fail(/* @__PURE__ */ new Error("invalid charSet: missing code 0"));
961
+ return Effect.succeed(zero);
962
+ }
963
+ let res = "";
964
+ const max = charSet.length;
965
+ while (int > 0) {
966
+ const code = charSet.byCode[int % max];
967
+ if (code === void 0) return Effect.fail(/* @__PURE__ */ new Error("invalid character code in encodeToCharSet"));
968
+ res = code + res;
969
+ int = Math.floor(int / max);
970
+ }
971
+ return Effect.succeed(res);
972
+ }
973
+ function decodeCharSetToNumber(key, charSet) {
974
+ let res = 0;
975
+ const length = key.length;
976
+ const max = charSet.length;
977
+ for (let i = 0; i < length; i++) {
978
+ const char = key[i];
979
+ if (char === void 0) continue;
980
+ const charIndex = charSet.byChar[char];
981
+ if (charIndex === void 0) continue;
982
+ res += charIndex * Math.pow(max, length - i - 1);
983
+ }
984
+ return res;
985
+ }
986
+ function addCharSetKeys(a, b, charSet) {
987
+ const base = charSet.length;
988
+ const [paddedA, paddedB] = makeSameLength(a, b, "start", charSet.first);
989
+ const result = [];
990
+ let carry = 0;
991
+ for (let i = paddedA.length - 1; i >= 0; i--) {
992
+ const charA = paddedA[i];
993
+ const charB = paddedB[i];
994
+ if (!charA || !charB) return Effect.fail(/* @__PURE__ */ new Error("invalid character in addCharSetKeys"));
995
+ const digitA = charSet.byChar[charA];
996
+ const digitB = charSet.byChar[charB];
997
+ if (digitA === void 0 || digitB === void 0) return Effect.fail(/* @__PURE__ */ new Error("invalid character in addCharSetKeys"));
998
+ const sum = digitA + digitB + carry;
999
+ carry = Math.floor(sum / base);
1000
+ const remainder = sum % base;
1001
+ const codeChar = charSet.byCode[remainder];
1002
+ if (codeChar === void 0) return Effect.fail(/* @__PURE__ */ new Error("invalid character code in addCharSetKeys"));
1003
+ result.unshift(codeChar);
1004
+ }
1005
+ if (carry > 0) {
1006
+ const carryChar = charSet.byCode[carry];
1007
+ if (carryChar === void 0) return Effect.fail(/* @__PURE__ */ new Error("invalid carry character code"));
1008
+ result.unshift(carryChar);
1009
+ }
1010
+ return Effect.succeed(result.join(""));
1011
+ }
1012
+ function subtractCharSetKeys(a, b, charSet, stripLeadingZeros = true) {
1013
+ const base = charSet.length;
1014
+ const [paddedA, paddedB] = makeSameLength(a, b, "start", charSet.first);
1015
+ const result = [];
1016
+ let borrow = 0;
1017
+ for (let i = paddedA.length - 1; i >= 0; i--) {
1018
+ const charA = paddedA[i];
1019
+ const charB = paddedB[i];
1020
+ if (!charA || !charB) return Effect.fail(/* @__PURE__ */ new Error("invalid character in subtractCharSetKeys"));
1021
+ let digitA = charSet.byChar[charA];
1022
+ const digitBValue = charSet.byChar[charB];
1023
+ if (digitA === void 0 || digitBValue === void 0) return Effect.fail(/* @__PURE__ */ new Error("invalid character in subtractCharSetKeys"));
1024
+ const digitB = digitBValue + borrow;
1025
+ if (digitA < digitB) {
1026
+ borrow = 1;
1027
+ digitA += base;
1028
+ } else borrow = 0;
1029
+ const difference = digitA - digitB;
1030
+ const codeChar = charSet.byCode[difference];
1031
+ if (codeChar === void 0) return Effect.fail(/* @__PURE__ */ new Error("invalid character code in subtractCharSetKeys"));
1032
+ result.unshift(codeChar);
1033
+ }
1034
+ if (borrow > 0) return Effect.fail(/* @__PURE__ */ new Error("Subtraction result is negative. Ensure a is greater than or equal to b."));
1035
+ while (stripLeadingZeros && result.length > 1 && result[0] === charSet.first) result.shift();
1036
+ return Effect.succeed(result.join(""));
1037
+ }
1038
+ function incrementKey(key, charSet) {
1039
+ const one = charSet.byCode[1];
1040
+ if (one === void 0) return Effect.fail(/* @__PURE__ */ new Error("invalid charSet: missing code 1"));
1041
+ return addCharSetKeys(key, one, charSet);
1042
+ }
1043
+ function decrementKey(key, charSet) {
1044
+ const one = charSet.byCode[1];
1045
+ if (one === void 0) return Effect.fail(/* @__PURE__ */ new Error("invalid charSet: missing code 1"));
1046
+ return subtractCharSetKeys(key, one, charSet, false);
1047
+ }
1048
+ function lexicalDistance(a, b, charSet) {
1049
+ const [lower, upper] = makeSameLength(a, b, "end", charSet.first).sort();
1050
+ return Effect.gen(function* () {
1051
+ return decodeCharSetToNumber(yield* subtractCharSetKeys(upper, lower, charSet), charSet);
1052
+ });
1053
+ }
1054
+ function midPoint(lower, upper, charSet) {
1055
+ return Effect.gen(function* () {
1056
+ let [paddedLower, paddedUpper] = makeSameLength(lower, upper, "end", charSet.first);
1057
+ let distance = yield* lexicalDistance(paddedLower, paddedUpper, charSet);
1058
+ if (distance === 1) {
1059
+ paddedLower = paddedLower.padEnd(paddedLower.length + 1, charSet.first);
1060
+ distance = charSet.length;
1061
+ }
1062
+ const mid = yield* encodeToCharSet(Math.floor(distance / 2), charSet);
1063
+ return yield* addCharSetKeys(paddedLower, mid, charSet);
1064
+ });
1065
+ }
1066
+ function startKey(charSet) {
1067
+ return charSet.firstPositive + charSet.byCode[0];
1068
+ }
1069
+ function validInteger(integer, charSet) {
1070
+ return Effect.gen(function* () {
1071
+ return (yield* integerLength(integer, charSet)) === integer.length;
1072
+ });
1073
+ }
1074
+ function validateOrderKey(orderKey, charSet) {
1075
+ return Effect.gen(function* () {
1076
+ yield* getIntegerPart(orderKey, charSet);
1077
+ });
1078
+ }
1079
+ function getIntegerPart(orderKey, charSet) {
1080
+ return Effect.gen(function* () {
1081
+ const integerPartLength = yield* integerLength(integerHead(orderKey, charSet), charSet);
1082
+ if (integerPartLength > orderKey.length) return yield* Effect.fail(/* @__PURE__ */ new Error("invalid order key length: " + orderKey));
1083
+ return orderKey.slice(0, integerPartLength);
1084
+ });
1085
+ }
1086
+ function validateInteger(integer, charSet) {
1087
+ return Effect.gen(function* () {
1088
+ if (!(yield* validInteger(integer, charSet))) return yield* Effect.fail(/* @__PURE__ */ new Error("invalid integer length: " + integer));
1089
+ });
1090
+ }
1091
+ function integerHead(integer, charSet) {
1092
+ let i = 0;
1093
+ if (integer[0] === charSet.mostPositive) while (integer[i] === charSet.mostPositive) i = i + 1;
1094
+ if (integer[0] === charSet.mostNegative) while (integer[i] === charSet.mostNegative) i = i + 1;
1095
+ return integer.slice(0, i + 1);
1096
+ }
1097
+ function splitInteger(integer, charSet) {
1098
+ return Effect.gen(function* () {
1099
+ const head = integerHead(integer, {
1100
+ firstPositive: charSet.firstPositive,
1101
+ mostPositive: charSet.mostPositive,
1102
+ firstNegative: charSet.firstNegative,
1103
+ mostNegative: charSet.mostNegative
1104
+ });
1105
+ return [head, integer.slice(head.length)];
1106
+ });
1107
+ }
1108
+ function incrementIntegerHead(head, charSet) {
1109
+ return Effect.gen(function* () {
1110
+ const inPositiveRange = head >= charSet.firstPositive;
1111
+ const nextHead = yield* incrementKey(head, charSet);
1112
+ const headIsLimitMax = head[head.length - 1] === charSet.mostPositive;
1113
+ const nextHeadIsLimitMax = nextHead[nextHead.length - 1] === charSet.mostPositive;
1114
+ if (inPositiveRange && nextHeadIsLimitMax) return nextHead + charSet.mostNegative;
1115
+ if (!inPositiveRange && headIsLimitMax) return head.slice(0, head.length - 1);
1116
+ return nextHead;
1117
+ });
1118
+ }
1119
+ function decrementIntegerHead(head, charSet) {
1120
+ return Effect.gen(function* () {
1121
+ const inPositiveRange = head >= charSet.firstPositive;
1122
+ const headIsLimitMin = head[head.length - 1] === charSet.mostNegative;
1123
+ if (inPositiveRange && headIsLimitMin) return yield* decrementKey(head.slice(0, head.length - 1), charSet);
1124
+ if (!inPositiveRange && headIsLimitMin) return head + charSet.mostPositive;
1125
+ return yield* decrementKey(head, charSet);
1126
+ });
1127
+ }
1128
+ function startOnNewHead(head, limit, charSet) {
1129
+ return Effect.gen(function* () {
1130
+ const newLength = yield* integerLength(head, charSet);
1131
+ const fillCharCode = limit === "upper" ? charSet.length - 1 : 0;
1132
+ const fillChar = charSet.byCode[fillCharCode];
1133
+ if (fillChar === void 0) return yield* Effect.fail(/* @__PURE__ */ new Error("invalid fill character code"));
1134
+ return head + fillChar.repeat(newLength - head.length);
1135
+ });
1136
+ }
1137
+ function incrementInteger(integer, charSet) {
1138
+ return Effect.gen(function* () {
1139
+ yield* validateInteger(integer, charSet);
1140
+ const [head, digs] = yield* splitInteger(integer, charSet);
1141
+ const maxChar = charSet.byCode[charSet.length - 1];
1142
+ if (maxChar === void 0) return yield* Effect.fail(/* @__PURE__ */ new Error("invalid charSet: missing max character"));
1143
+ if (digs.split("").some((d) => d !== maxChar)) return head + (yield* incrementKey(digs, charSet));
1144
+ return yield* startOnNewHead(yield* incrementIntegerHead(head, charSet), "lower", charSet);
1145
+ });
1146
+ }
1147
+ function decrementInteger(integer, charSet) {
1148
+ return Effect.gen(function* () {
1149
+ yield* validateInteger(integer, charSet);
1150
+ const [head, digs] = yield* splitInteger(integer, charSet);
1151
+ const minChar = charSet.byCode[0];
1152
+ if (minChar === void 0) return yield* Effect.fail(/* @__PURE__ */ new Error("invalid charSet: missing min character"));
1153
+ if (digs.split("").some((d) => d !== minChar)) return head + (yield* decrementKey(digs, charSet));
1154
+ return yield* startOnNewHead(yield* decrementIntegerHead(head, charSet), "upper", charSet);
1155
+ });
1156
+ }
1157
+ /**
1158
+ * Generate a key between two other keys.
1159
+ * If either lower or upper is null, the key will be generated at the start or end of the list.
1160
+ */
1161
+ function generateKeyBetween(lower, upper, charSet = base62CharSet()) {
1162
+ return Effect.gen(function* () {
1163
+ if (lower !== null) yield* validateOrderKey(lower, charSet);
1164
+ if (upper !== null) yield* validateOrderKey(upper, charSet);
1165
+ if (lower === null && upper === null) return startKey(charSet);
1166
+ if (lower === null) return yield* decrementInteger(yield* getIntegerPart(upper, charSet), charSet);
1167
+ if (upper === null) return yield* incrementInteger(yield* getIntegerPart(lower, charSet), charSet);
1168
+ if (lower >= upper) return yield* Effect.fail(/* @__PURE__ */ new Error(lower + " >= " + upper));
1169
+ return yield* midPoint(lower, upper, charSet);
1170
+ });
1171
+ }
1172
+
1173
+ //#endregion
1174
+ //#region src/primitives/Array.ts
1175
+ /**
1176
+ * Sort array entries by their fractional position
1177
+ */
1178
+ const sortByPos = (entries) => [...entries].sort((a, b) => a.pos < b.pos ? -1 : a.pos > b.pos ? 1 : 0);
1179
+ /**
1180
+ * Generate a fractional position between two positions
1181
+ */
1182
+ const generatePosBetween = (left, right) => {
1183
+ const charSet = base62CharSet();
1184
+ return Effect.runSync(generateKeyBetween(left, right, charSet));
1185
+ };
1186
+ var ArrayPrimitive = class ArrayPrimitive {
1187
+ constructor(schema) {
1188
+ _defineProperty(this, "_tag", "ArrayPrimitive");
1189
+ _defineProperty(this, "_State", void 0);
1190
+ _defineProperty(this, "_Proxy", void 0);
1191
+ _defineProperty(this, "_schema", void 0);
1192
+ _defineProperty(this, "_opDefinitions", {
1193
+ set: make$5({
1194
+ kind: "array.set",
1195
+ payload: Schema.Unknown,
1196
+ target: Schema.Unknown,
1197
+ apply: (payload) => payload
1198
+ }),
1199
+ insert: make$5({
1200
+ kind: "array.insert",
1201
+ payload: Schema.Unknown,
1202
+ target: Schema.Unknown,
1203
+ apply: (payload) => payload
1204
+ }),
1205
+ remove: make$5({
1206
+ kind: "array.remove",
1207
+ payload: Schema.Unknown,
1208
+ target: Schema.Unknown,
1209
+ apply: (payload) => payload
1210
+ }),
1211
+ move: make$5({
1212
+ kind: "array.move",
1213
+ payload: Schema.Unknown,
1214
+ target: Schema.Unknown,
1215
+ apply: (payload) => payload
1216
+ })
1217
+ });
1218
+ _defineProperty(this, "_internal", {
1219
+ createProxy: (env, operationPath) => {
1220
+ const elementPrimitive = this._schema.element;
1221
+ const getCurrentState = () => {
1222
+ const state = env.getState(operationPath);
1223
+ if (!state || !globalThis.Array.isArray(state)) return [];
1224
+ return sortByPos(state);
1225
+ };
1226
+ return {
1227
+ get: () => {
1228
+ return getCurrentState();
1229
+ },
1230
+ set: (values) => {
1231
+ const entries = [];
1232
+ let prevPos = null;
1233
+ for (const value of values) {
1234
+ const id = env.generateId();
1235
+ const pos = generatePosBetween(prevPos, null);
1236
+ entries.push({
1237
+ id,
1238
+ pos,
1239
+ value
1240
+ });
1241
+ prevPos = pos;
1242
+ }
1243
+ env.addOperation(fromDefinition(operationPath, this._opDefinitions.set, entries));
1244
+ },
1245
+ push: (value) => {
1246
+ const sorted = getCurrentState();
1247
+ const lastPos = sorted.length > 0 ? sorted[sorted.length - 1].pos : null;
1248
+ const id = env.generateId();
1249
+ const pos = generatePosBetween(lastPos, null);
1250
+ env.addOperation(fromDefinition(operationPath, this._opDefinitions.insert, {
1251
+ id,
1252
+ pos,
1253
+ value
1254
+ }));
1255
+ },
1256
+ insertAt: (index, value) => {
1257
+ const sorted = getCurrentState();
1258
+ const leftPos = index > 0 && sorted[index - 1] ? sorted[index - 1].pos : null;
1259
+ const rightPos = index < sorted.length && sorted[index] ? sorted[index].pos : null;
1260
+ const id = env.generateId();
1261
+ const pos = generatePosBetween(leftPos, rightPos);
1262
+ env.addOperation(fromDefinition(operationPath, this._opDefinitions.insert, {
1263
+ id,
1264
+ pos,
1265
+ value
1266
+ }));
1267
+ },
1268
+ remove: (id) => {
1269
+ env.addOperation(fromDefinition(operationPath, this._opDefinitions.remove, { id }));
1270
+ },
1271
+ move: (id, toIndex) => {
1272
+ const without = getCurrentState().filter((e) => e.id !== id);
1273
+ const clampedIndex = Math.max(0, Math.min(toIndex, without.length));
1274
+ const pos = generatePosBetween(clampedIndex > 0 && without[clampedIndex - 1] ? without[clampedIndex - 1].pos : null, clampedIndex < without.length && without[clampedIndex] ? without[clampedIndex].pos : null);
1275
+ env.addOperation(fromDefinition(operationPath, this._opDefinitions.move, {
1276
+ id,
1277
+ pos
1278
+ }));
1279
+ },
1280
+ at: (id) => {
1281
+ const elementPath = operationPath.append(id);
1282
+ return elementPrimitive._internal.createProxy(env, elementPath);
1283
+ },
1284
+ find: (predicate) => {
1285
+ const found = getCurrentState().find((entry) => predicate(entry.value, entry.id));
1286
+ if (!found) return void 0;
1287
+ const elementPath = operationPath.append(found.id);
1288
+ return elementPrimitive._internal.createProxy(env, elementPath);
1289
+ },
1290
+ toSnapshot: () => {
1291
+ return getCurrentState().map((entry) => {
1292
+ const elementPath = operationPath.append(entry.id);
1293
+ const elementProxy = elementPrimitive._internal.createProxy(env, elementPath);
1294
+ return {
1295
+ id: entry.id,
1296
+ value: elementProxy.toSnapshot()
1297
+ };
1298
+ });
1299
+ }
1300
+ };
1301
+ },
1302
+ applyOperation: (state, operation) => {
1303
+ const path = operation.path;
1304
+ const tokens = path.toTokens().filter((t) => t !== "");
1305
+ const currentState = state !== null && state !== void 0 ? state : [];
1306
+ let newState;
1307
+ if (tokens.length === 0) switch (operation.kind) {
1308
+ case "array.set": {
1309
+ const payload = operation.payload;
1310
+ if (!globalThis.Array.isArray(payload)) throw new ValidationError(`ArrayPrimitive.set requires an array payload`);
1311
+ newState = payload;
1312
+ break;
1313
+ }
1314
+ case "array.insert": {
1315
+ const { id, pos, value } = operation.payload;
1316
+ newState = [...currentState, {
1317
+ id,
1318
+ pos,
1319
+ value
1320
+ }];
1321
+ break;
1322
+ }
1323
+ case "array.remove": {
1324
+ const { id } = operation.payload;
1325
+ newState = currentState.filter((entry) => entry.id !== id);
1326
+ break;
1327
+ }
1328
+ case "array.move": {
1329
+ const { id, pos } = operation.payload;
1330
+ newState = currentState.map((entry) => entry.id === id ? _objectSpread2(_objectSpread2({}, entry), {}, { pos }) : entry);
1331
+ break;
1332
+ }
1333
+ default: throw new ValidationError(`ArrayPrimitive cannot apply operation of kind: ${operation.kind}`);
1334
+ }
1335
+ else {
1336
+ const elementId = tokens[0];
1337
+ const entryIndex = currentState.findIndex((entry) => entry.id === elementId);
1338
+ if (entryIndex === -1) throw new ValidationError(`Array element not found with ID: ${elementId}`);
1339
+ const elementPrimitive = this._schema.element;
1340
+ const remainingPath = path.shift();
1341
+ const elementOperation = _objectSpread2(_objectSpread2({}, operation), {}, { path: remainingPath });
1342
+ const currentEntry = currentState[entryIndex];
1343
+ const newValue = elementPrimitive._internal.applyOperation(currentEntry.value, elementOperation);
1344
+ const mutableState = [...currentState];
1345
+ mutableState[entryIndex] = _objectSpread2(_objectSpread2({}, currentEntry), {}, { value: newValue });
1346
+ newState = mutableState;
1347
+ }
1348
+ runValidators(newState, this._schema.validators);
1349
+ return newState;
1350
+ },
1351
+ getInitialState: () => {
1352
+ return this._schema.defaultValue;
1353
+ },
1354
+ transformOperation: (clientOp, serverOp) => {
1355
+ const clientPath = clientOp.path;
1356
+ const serverPath = serverOp.path;
1357
+ if (!pathsOverlap(clientPath, serverPath)) return {
1358
+ type: "transformed",
1359
+ operation: clientOp
1360
+ };
1361
+ if (serverOp.kind === "array.remove") {
1362
+ const removedId = serverOp.payload.id;
1363
+ const clientTokens$1 = clientPath.toTokens().filter((t) => t !== "");
1364
+ const serverTokens$1 = serverPath.toTokens().filter((t) => t !== "");
1365
+ if (clientTokens$1.length > serverTokens$1.length) {
1366
+ if (clientTokens$1[serverTokens$1.length] === removedId) return { type: "noop" };
1367
+ }
1368
+ }
1369
+ if (serverOp.kind === "array.insert" && clientOp.kind === "array.insert") return {
1370
+ type: "transformed",
1371
+ operation: clientOp
1372
+ };
1373
+ if (serverOp.kind === "array.move" && clientOp.kind === "array.move") {
1374
+ if (serverOp.payload.id === clientOp.payload.id) return {
1375
+ type: "transformed",
1376
+ operation: clientOp
1377
+ };
1378
+ return {
1379
+ type: "transformed",
1380
+ operation: clientOp
1381
+ };
1382
+ }
1383
+ if (pathsEqual(clientPath, serverPath)) return {
1384
+ type: "transformed",
1385
+ operation: clientOp
1386
+ };
1387
+ if (serverOp.kind === "array.set" && isPrefix(serverPath, clientPath)) return {
1388
+ type: "transformed",
1389
+ operation: clientOp
1390
+ };
1391
+ const clientTokens = clientPath.toTokens().filter((t) => t !== "");
1392
+ const serverTokens = serverPath.toTokens().filter((t) => t !== "");
1393
+ if (clientTokens.length > 0 && serverTokens.length > 0) {
1394
+ if (clientTokens[0] !== serverTokens[0]) return {
1395
+ type: "transformed",
1396
+ operation: clientOp
1397
+ };
1398
+ const elementPrimitive = this._schema.element;
1399
+ const clientOpForElement = _objectSpread2(_objectSpread2({}, clientOp), {}, { path: clientOp.path.shift() });
1400
+ const serverOpForElement = _objectSpread2(_objectSpread2({}, serverOp), {}, { path: serverOp.path.shift() });
1401
+ const result = elementPrimitive._internal.transformOperation(clientOpForElement, serverOpForElement);
1402
+ if (result.type === "transformed") return {
1403
+ type: "transformed",
1404
+ operation: _objectSpread2(_objectSpread2({}, result.operation), {}, { path: clientOp.path })
1405
+ };
1406
+ return result;
1407
+ }
1408
+ return {
1409
+ type: "transformed",
1410
+ operation: clientOp
1411
+ };
1412
+ }
1413
+ });
1414
+ this._schema = schema;
1415
+ }
1416
+ /** Mark this array as required */
1417
+ required() {
1418
+ return new ArrayPrimitive(_objectSpread2(_objectSpread2({}, this._schema), {}, { required: true }));
1419
+ }
1420
+ /** Set a default value for this array */
1421
+ default(defaultValue) {
1422
+ return new ArrayPrimitive(_objectSpread2(_objectSpread2({}, this._schema), {}, { defaultValue }));
1423
+ }
1424
+ /** Get the element primitive */
1425
+ get element() {
1426
+ return this._schema.element;
1427
+ }
1428
+ /** Add a custom validation rule */
1429
+ refine(fn, message) {
1430
+ return new ArrayPrimitive(_objectSpread2(_objectSpread2({}, this._schema), {}, { validators: [...this._schema.validators, {
1431
+ validate: fn,
1432
+ message
1433
+ }] }));
1434
+ }
1435
+ /** Minimum array length */
1436
+ minLength(length) {
1437
+ return this.refine((v) => v.length >= length, `Array must have at least ${length} elements`);
1438
+ }
1439
+ /** Maximum array length */
1440
+ maxLength(length) {
1441
+ return this.refine((v) => v.length <= length, `Array must have at most ${length} elements`);
1442
+ }
1443
+ };
1444
+ /** Creates a new ArrayPrimitive with the given element type */
1445
+ const Array$1 = (element) => new ArrayPrimitive({
1446
+ required: false,
1447
+ defaultValue: void 0,
1448
+ element,
1449
+ validators: []
1450
+ });
1451
+
1452
+ //#endregion
1453
+ //#region src/primitives/Lazy.ts
1454
+ var LazyPrimitive = class {
1455
+ constructor(thunk) {
1456
+ _defineProperty(this, "_tag", "LazyPrimitive");
1457
+ _defineProperty(this, "_State", void 0);
1458
+ _defineProperty(this, "_Proxy", void 0);
1459
+ _defineProperty(this, "_thunk", void 0);
1460
+ _defineProperty(this, "_resolved", void 0);
1461
+ _defineProperty(this, "_internal", {
1462
+ createProxy: (env, operationPath) => {
1463
+ return this._resolve()._internal.createProxy(env, operationPath);
1464
+ },
1465
+ applyOperation: (state, operation) => {
1466
+ return this._resolve()._internal.applyOperation(state, operation);
1467
+ },
1468
+ getInitialState: () => {
1469
+ return this._resolve()._internal.getInitialState();
1470
+ },
1471
+ transformOperation: (clientOp, serverOp) => {
1472
+ return this._resolve()._internal.transformOperation(clientOp, serverOp);
1473
+ }
1474
+ });
1475
+ this._thunk = thunk;
1476
+ }
1477
+ /** Resolve and cache the lazy primitive */
1478
+ _resolve() {
1479
+ if (this._resolved === void 0) this._resolved = this._thunk();
1480
+ return this._resolved;
1481
+ }
1482
+ /** Mark this lazy primitive as required (delegates to resolved) */
1483
+ required() {
1484
+ return this;
1485
+ }
1486
+ };
1487
+ /** Creates a new LazyPrimitive with the given thunk */
1488
+ const Lazy = (thunk) => new LazyPrimitive(thunk);
1489
+
1490
+ //#endregion
1491
+ //#region src/primitives/Union.ts
1492
+ var UnionPrimitive = class UnionPrimitive {
1493
+ constructor(schema) {
1494
+ _defineProperty(this, "_tag", "UnionPrimitive");
1495
+ _defineProperty(this, "_State", void 0);
1496
+ _defineProperty(this, "_Proxy", void 0);
1497
+ _defineProperty(this, "_schema", void 0);
1498
+ _defineProperty(this, "_opDefinitions", { set: make$5({
1499
+ kind: "union.set",
1500
+ payload: Schema.Unknown,
1501
+ target: Schema.Unknown,
1502
+ apply: (payload) => payload
1503
+ }) });
1504
+ _defineProperty(this, "_internal", {
1505
+ createProxy: (env, operationPath) => {
1506
+ const variants = this._schema.variants;
1507
+ const defaultValue = this._schema.defaultValue;
1508
+ return {
1509
+ get: () => {
1510
+ const state = env.getState(operationPath);
1511
+ return state !== null && state !== void 0 ? state : defaultValue;
1512
+ },
1513
+ set: (value) => {
1514
+ env.addOperation(fromDefinition(operationPath, this._opDefinitions.set, value));
1515
+ },
1516
+ as: (variant) => {
1517
+ const variantPrimitive = variants[variant];
1518
+ if (!variantPrimitive) throw new ValidationError(`Unknown variant: ${globalThis.String(variant)}`);
1519
+ return variantPrimitive._internal.createProxy(env, operationPath);
1520
+ },
1521
+ match: (handlers) => {
1522
+ const state = env.getState(operationPath);
1523
+ if (!state) return void 0;
1524
+ const variantKey = this._findVariantKey(state);
1525
+ if (!variantKey) return void 0;
1526
+ const handler = handlers[variantKey];
1527
+ if (!handler) return void 0;
1528
+ return handler(variants[variantKey]._internal.createProxy(env, operationPath));
1529
+ },
1530
+ toSnapshot: () => {
1531
+ const state = env.getState(operationPath);
1532
+ const effectiveState = state !== null && state !== void 0 ? state : defaultValue;
1533
+ if (!effectiveState) return;
1534
+ const variantKey = this._findVariantKey(effectiveState);
1535
+ if (!variantKey) return;
1536
+ return variants[variantKey]._internal.createProxy(env, operationPath).toSnapshot();
1537
+ }
1538
+ };
1539
+ },
1540
+ applyOperation: (state, operation) => {
1541
+ if (operation.path.toTokens().filter((t) => t !== "").length === 0) {
1542
+ if (operation.kind !== "union.set") throw new ValidationError(`UnionPrimitive root cannot apply operation of kind: ${operation.kind}`);
1543
+ const payload = operation.payload;
1544
+ if (typeof payload !== "object" || payload === null) throw new ValidationError(`UnionPrimitive.set requires an object payload`);
1545
+ if (payload[this._schema.discriminator] === void 0) throw new ValidationError(`UnionPrimitive.set requires a "${this._schema.discriminator}" discriminator field`);
1546
+ return payload;
1547
+ }
1548
+ if (state === void 0) throw new ValidationError(`Cannot apply nested operation to undefined union state`);
1549
+ const variantKey = this._findVariantKey(state);
1550
+ if (variantKey === void 0) throw new ValidationError(`Cannot determine active variant from state`);
1551
+ return this._schema.variants[variantKey]._internal.applyOperation(state, operation);
1552
+ },
1553
+ getInitialState: () => {
1554
+ return this._schema.defaultValue;
1555
+ },
1556
+ transformOperation: (clientOp, serverOp) => {
1557
+ const clientPath = clientOp.path;
1558
+ const serverPath = serverOp.path;
1559
+ if (!pathsOverlap(clientPath, serverPath)) return {
1560
+ type: "transformed",
1561
+ operation: clientOp
1562
+ };
1563
+ const clientTokens = clientPath.toTokens().filter((t) => t !== "");
1564
+ const serverTokens = serverPath.toTokens().filter((t) => t !== "");
1565
+ if (clientTokens.length === 0 && serverTokens.length === 0) return {
1566
+ type: "transformed",
1567
+ operation: clientOp
1568
+ };
1569
+ if (serverTokens.length === 0 && serverOp.kind === "union.set") return {
1570
+ type: "transformed",
1571
+ operation: clientOp
1572
+ };
1573
+ if (clientTokens.length === 0 && clientOp.kind === "union.set") return {
1574
+ type: "transformed",
1575
+ operation: clientOp
1576
+ };
1577
+ if (clientTokens.length > 0 && serverTokens.length > 0) {
1578
+ if (clientTokens[0] !== serverTokens[0]) return {
1579
+ type: "transformed",
1580
+ operation: clientOp
1581
+ };
1582
+ const variantKeys = Object.keys(this._schema.variants);
1583
+ if (variantKeys.length === 0) return {
1584
+ type: "transformed",
1585
+ operation: clientOp
1586
+ };
1587
+ return this._schema.variants[variantKeys[0]]._internal.transformOperation(clientOp, serverOp);
1588
+ }
1589
+ return {
1590
+ type: "transformed",
1591
+ operation: clientOp
1592
+ };
1593
+ }
1594
+ });
1595
+ this._schema = schema;
1596
+ }
1597
+ /** Mark this union as required */
1598
+ required() {
1599
+ return new UnionPrimitive(_objectSpread2(_objectSpread2({}, this._schema), {}, { required: true }));
1600
+ }
1601
+ /** Set a default value for this union */
1602
+ default(defaultValue) {
1603
+ return new UnionPrimitive(_objectSpread2(_objectSpread2({}, this._schema), {}, { defaultValue }));
1604
+ }
1605
+ /** Get the discriminator field name */
1606
+ get discriminator() {
1607
+ return this._schema.discriminator;
1608
+ }
1609
+ /** Get the variants */
1610
+ get variants() {
1611
+ return this._schema.variants;
1612
+ }
1613
+ /** Find the variant key from a state value */
1614
+ _findVariantKey(state) {
1615
+ if (typeof state !== "object" || state === null) return;
1616
+ const discriminatorValue = state[this._schema.discriminator];
1617
+ for (const key in this._schema.variants) {
1618
+ const discriminatorField = this._schema.variants[key].fields[this._schema.discriminator];
1619
+ if (discriminatorField && discriminatorField._tag === "LiteralPrimitive") {
1620
+ if (discriminatorField.literal === discriminatorValue) return key;
1621
+ }
1622
+ }
1623
+ }
1624
+ };
1625
+ function Union(options) {
1626
+ var _options$discriminato;
1627
+ return new UnionPrimitive({
1628
+ required: false,
1629
+ defaultValue: void 0,
1630
+ discriminator: (_options$discriminato = options.discriminator) !== null && _options$discriminato !== void 0 ? _options$discriminato : "type",
1631
+ variants: options.variants
1632
+ });
1633
+ }
1634
+
1635
+ //#endregion
1636
+ //#region src/primitives/TreeNode.ts
1637
+ /**
1638
+ * TreeNodePrimitive - defines a node type with its data schema and allowed children
1639
+ */
1640
+ var TreeNodePrimitive = class {
1641
+ constructor(type, config) {
1642
+ _defineProperty(this, "_tag", "TreeNodePrimitive");
1643
+ _defineProperty(this, "_Type", void 0);
1644
+ _defineProperty(this, "_Data", void 0);
1645
+ _defineProperty(this, "_Children", void 0);
1646
+ _defineProperty(this, "_type", void 0);
1647
+ _defineProperty(this, "_data", void 0);
1648
+ _defineProperty(this, "_children", void 0);
1649
+ _defineProperty(this, "_resolvedChildren", void 0);
1650
+ this._type = type;
1651
+ this._data = config.data;
1652
+ this._children = config.children;
1653
+ }
1654
+ /** Get the node type identifier */
1655
+ get type() {
1656
+ return this._type;
1657
+ }
1658
+ /** Get the data primitive */
1659
+ get data() {
1660
+ return this._data;
1661
+ }
1662
+ /** Get resolved children (resolves lazy thunk if needed) */
1663
+ get children() {
1664
+ if (this._resolvedChildren === void 0) if (typeof this._children === "function") this._resolvedChildren = this._children();
1665
+ else this._resolvedChildren = this._children;
1666
+ return this._resolvedChildren;
1667
+ }
1668
+ /** Check if a child type is allowed */
1669
+ isChildAllowed(childType) {
1670
+ return this.children.some((child) => child.type === childType);
1671
+ }
1672
+ };
1673
+ /** Creates a new TreeNodePrimitive with the given type and config */
1674
+ const TreeNode = (type, config) => new TreeNodePrimitive(type, config);
1675
+
1676
+ //#endregion
1677
+ //#region src/primitives/Tree.ts
1678
+ /**
1679
+ * Helper to get children sorted by position
1680
+ */
1681
+ const getOrderedChildren = (nodes, parentId) => {
1682
+ return [...nodes].filter((n) => n.parentId === parentId).sort((a, b) => a.pos < b.pos ? -1 : a.pos > b.pos ? 1 : 0);
1683
+ };
1684
+ /**
1685
+ * Get all descendant IDs of a node (recursive)
1686
+ */
1687
+ const getDescendantIds = (nodes, nodeId) => {
1688
+ const children = nodes.filter((n) => n.parentId === nodeId);
1689
+ const descendantIds = [];
1690
+ for (const child of children) {
1691
+ descendantIds.push(child.id);
1692
+ descendantIds.push(...getDescendantIds(nodes, child.id));
1693
+ }
1694
+ return descendantIds;
1695
+ };
1696
+ /**
1697
+ * Check if moving a node to a new parent would create a cycle
1698
+ */
1699
+ const wouldCreateCycle = (nodes, nodeId, newParentId) => {
1700
+ if (newParentId === null) return false;
1701
+ if (newParentId === nodeId) return true;
1702
+ return getDescendantIds(nodes, nodeId).includes(newParentId);
1703
+ };
1704
+ /**
1705
+ * Generate a fractional position between two positions
1706
+ */
1707
+ const generateTreePosBetween = (left, right) => {
1708
+ const charSet = base62CharSet();
1709
+ return Effect.runSync(generateKeyBetween(left, right, charSet));
1710
+ };
1711
+ var TreePrimitive = class TreePrimitive {
1712
+ constructor(schema) {
1713
+ _defineProperty(this, "_tag", "TreePrimitive");
1714
+ _defineProperty(this, "_State", void 0);
1715
+ _defineProperty(this, "_Proxy", void 0);
1716
+ _defineProperty(this, "_schema", void 0);
1717
+ _defineProperty(this, "_nodeTypeRegistry", void 0);
1718
+ _defineProperty(this, "_opDefinitions", {
1719
+ set: make$5({
1720
+ kind: "tree.set",
1721
+ payload: Schema.Unknown,
1722
+ target: Schema.Unknown,
1723
+ apply: (payload) => payload
1724
+ }),
1725
+ insert: make$5({
1726
+ kind: "tree.insert",
1727
+ payload: Schema.Unknown,
1728
+ target: Schema.Unknown,
1729
+ apply: (payload) => payload
1730
+ }),
1731
+ remove: make$5({
1732
+ kind: "tree.remove",
1733
+ payload: Schema.Unknown,
1734
+ target: Schema.Unknown,
1735
+ apply: (payload) => payload
1736
+ }),
1737
+ move: make$5({
1738
+ kind: "tree.move",
1739
+ payload: Schema.Unknown,
1740
+ target: Schema.Unknown,
1741
+ apply: (payload) => payload
1742
+ })
1743
+ });
1744
+ _defineProperty(this, "_internal", {
1745
+ createProxy: (env, operationPath) => {
1746
+ const getCurrentState = () => {
1747
+ const state = env.getState(operationPath);
1748
+ return state !== null && state !== void 0 ? state : [];
1749
+ };
1750
+ const getParentType = (parentId) => {
1751
+ var _parent$type;
1752
+ if (parentId === null) return null;
1753
+ const parent = getCurrentState().find((n) => n.id === parentId);
1754
+ return (_parent$type = parent === null || parent === void 0 ? void 0 : parent.type) !== null && _parent$type !== void 0 ? _parent$type : null;
1755
+ };
1756
+ const createNodeProxy = (nodeState) => {
1757
+ return {
1758
+ id: nodeState.id,
1759
+ type: nodeState.type,
1760
+ is: (nodeType) => {
1761
+ return nodeState.type === nodeType.type;
1762
+ },
1763
+ as: (nodeType) => {
1764
+ if (nodeState.type !== nodeType.type) throw new ValidationError(`Node is of type "${nodeState.type}", not "${nodeType.type}"`);
1765
+ const nodePath = operationPath.append(nodeState.id);
1766
+ return {
1767
+ id: nodeState.id,
1768
+ type: nodeType.type,
1769
+ data: nodeType.data._internal.createProxy(env, nodePath),
1770
+ get: () => nodeState
1771
+ };
1772
+ },
1773
+ get: () => nodeState
1774
+ };
1775
+ };
1776
+ const buildSnapshot = (nodeId, nodes) => {
1777
+ const node = nodes.find((n) => n.id === nodeId);
1778
+ if (!node) return void 0;
1779
+ const childNodes = getOrderedChildren(nodes, nodeId);
1780
+ const children = [];
1781
+ for (const child of childNodes) {
1782
+ const childSnapshot = buildSnapshot(child.id, nodes);
1783
+ if (childSnapshot) children.push(childSnapshot);
1784
+ }
1785
+ return _objectSpread2(_objectSpread2({
1786
+ id: node.id,
1787
+ type: node.type
1788
+ }, node.data), {}, { children });
1789
+ };
1790
+ return {
1791
+ get: () => {
1792
+ return getCurrentState();
1793
+ },
1794
+ set: (nodes) => {
1795
+ env.addOperation(fromDefinition(operationPath, this._opDefinitions.set, nodes));
1796
+ },
1797
+ root: () => {
1798
+ return getCurrentState().find((n) => n.parentId === null);
1799
+ },
1800
+ children: (parentId) => {
1801
+ return getOrderedChildren(getCurrentState(), parentId);
1802
+ },
1803
+ node: (id) => {
1804
+ const nodeState = getCurrentState().find((n) => n.id === id);
1805
+ if (!nodeState) return void 0;
1806
+ return createNodeProxy(nodeState);
1807
+ },
1808
+ insertFirst: (parentId, nodeType, data) => {
1809
+ const state = getCurrentState();
1810
+ const siblings = getOrderedChildren(state, parentId);
1811
+ const pos = generateTreePosBetween(null, siblings.length > 0 ? siblings[0].pos : null);
1812
+ const id = env.generateId();
1813
+ if (parentId !== null && !state.find((n) => n.id === parentId)) throw new ValidationError(`Parent node not found: ${parentId}`);
1814
+ const parentType = getParentType(parentId);
1815
+ this._validateChildType(parentType, nodeType.type);
1816
+ if (parentId === null && state.some((n) => n.parentId === null)) throw new ValidationError("Tree already has a root node");
1817
+ env.addOperation(fromDefinition(operationPath, this._opDefinitions.insert, {
1818
+ id,
1819
+ type: nodeType.type,
1820
+ parentId,
1821
+ pos,
1822
+ data
1823
+ }));
1824
+ return id;
1825
+ },
1826
+ insertLast: (parentId, nodeType, data) => {
1827
+ const state = getCurrentState();
1828
+ const siblings = getOrderedChildren(state, parentId);
1829
+ const pos = generateTreePosBetween(siblings.length > 0 ? siblings[siblings.length - 1].pos : null, null);
1830
+ const id = env.generateId();
1831
+ if (parentId !== null && !state.find((n) => n.id === parentId)) throw new ValidationError(`Parent node not found: ${parentId}`);
1832
+ const parentType = getParentType(parentId);
1833
+ this._validateChildType(parentType, nodeType.type);
1834
+ if (parentId === null && state.some((n) => n.parentId === null)) throw new ValidationError("Tree already has a root node");
1835
+ env.addOperation(fromDefinition(operationPath, this._opDefinitions.insert, {
1836
+ id,
1837
+ type: nodeType.type,
1838
+ parentId,
1839
+ pos,
1840
+ data
1841
+ }));
1842
+ return id;
1843
+ },
1844
+ insertAt: (parentId, index, nodeType, data) => {
1845
+ const state = getCurrentState();
1846
+ const siblings = getOrderedChildren(state, parentId);
1847
+ const clampedIndex = Math.max(0, Math.min(index, siblings.length));
1848
+ const pos = generateTreePosBetween(clampedIndex > 0 && siblings[clampedIndex - 1] ? siblings[clampedIndex - 1].pos : null, clampedIndex < siblings.length && siblings[clampedIndex] ? siblings[clampedIndex].pos : null);
1849
+ const id = env.generateId();
1850
+ if (parentId !== null && !state.find((n) => n.id === parentId)) throw new ValidationError(`Parent node not found: ${parentId}`);
1851
+ const parentType = getParentType(parentId);
1852
+ this._validateChildType(parentType, nodeType.type);
1853
+ if (parentId === null && state.some((n) => n.parentId === null)) throw new ValidationError("Tree already has a root node");
1854
+ env.addOperation(fromDefinition(operationPath, this._opDefinitions.insert, {
1855
+ id,
1856
+ type: nodeType.type,
1857
+ parentId,
1858
+ pos,
1859
+ data
1860
+ }));
1861
+ return id;
1862
+ },
1863
+ insertAfter: (siblingId, nodeType, data) => {
1864
+ var _nextSibling$pos;
1865
+ const state = getCurrentState();
1866
+ const sibling = state.find((n) => n.id === siblingId);
1867
+ if (!sibling) throw new ValidationError(`Sibling node not found: ${siblingId}`);
1868
+ const parentId = sibling.parentId;
1869
+ const siblings = getOrderedChildren(state, parentId);
1870
+ const nextSibling = siblings[siblings.findIndex((n) => n.id === siblingId) + 1];
1871
+ const pos = generateTreePosBetween(sibling.pos, (_nextSibling$pos = nextSibling === null || nextSibling === void 0 ? void 0 : nextSibling.pos) !== null && _nextSibling$pos !== void 0 ? _nextSibling$pos : null);
1872
+ const id = env.generateId();
1873
+ const parentType = getParentType(parentId);
1874
+ this._validateChildType(parentType, nodeType.type);
1875
+ env.addOperation(fromDefinition(operationPath, this._opDefinitions.insert, {
1876
+ id,
1877
+ type: nodeType.type,
1878
+ parentId,
1879
+ pos,
1880
+ data
1881
+ }));
1882
+ return id;
1883
+ },
1884
+ insertBefore: (siblingId, nodeType, data) => {
1885
+ var _prevSibling$pos;
1886
+ const state = getCurrentState();
1887
+ const sibling = state.find((n) => n.id === siblingId);
1888
+ if (!sibling) throw new ValidationError(`Sibling node not found: ${siblingId}`);
1889
+ const parentId = sibling.parentId;
1890
+ const siblings = getOrderedChildren(state, parentId);
1891
+ const prevSibling = siblings[siblings.findIndex((n) => n.id === siblingId) - 1];
1892
+ const pos = generateTreePosBetween((_prevSibling$pos = prevSibling === null || prevSibling === void 0 ? void 0 : prevSibling.pos) !== null && _prevSibling$pos !== void 0 ? _prevSibling$pos : null, sibling.pos);
1893
+ const id = env.generateId();
1894
+ const parentType = getParentType(parentId);
1895
+ this._validateChildType(parentType, nodeType.type);
1896
+ env.addOperation(fromDefinition(operationPath, this._opDefinitions.insert, {
1897
+ id,
1898
+ type: nodeType.type,
1899
+ parentId,
1900
+ pos,
1901
+ data
1902
+ }));
1903
+ return id;
1904
+ },
1905
+ remove: (id) => {
1906
+ env.addOperation(fromDefinition(operationPath, this._opDefinitions.remove, { id }));
1907
+ },
1908
+ move: (nodeId, newParentId, toIndex) => {
1909
+ var _state$find$type, _state$find;
1910
+ const state = getCurrentState();
1911
+ const node = state.find((n) => n.id === nodeId);
1912
+ if (!node) throw new ValidationError(`Node not found: ${nodeId}`);
1913
+ if (newParentId !== null && !state.find((n) => n.id === newParentId)) throw new ValidationError(`Parent node not found: ${newParentId}`);
1914
+ if (wouldCreateCycle(state, nodeId, newParentId)) throw new ValidationError("Move would create a cycle in the tree");
1915
+ const newParentType = newParentId === null ? null : (_state$find$type = (_state$find = state.find((n) => n.id === newParentId)) === null || _state$find === void 0 ? void 0 : _state$find.type) !== null && _state$find$type !== void 0 ? _state$find$type : null;
1916
+ this._validateChildType(newParentType, node.type);
1917
+ if (node.parentId === null && newParentId !== null) throw new ValidationError("Cannot move root node to have a parent");
1918
+ const siblings = getOrderedChildren(state, newParentId).filter((n) => n.id !== nodeId);
1919
+ const clampedIndex = Math.max(0, Math.min(toIndex, siblings.length));
1920
+ const pos = generateTreePosBetween(clampedIndex > 0 && siblings[clampedIndex - 1] ? siblings[clampedIndex - 1].pos : null, clampedIndex < siblings.length && siblings[clampedIndex] ? siblings[clampedIndex].pos : null);
1921
+ env.addOperation(fromDefinition(operationPath, this._opDefinitions.move, {
1922
+ id: nodeId,
1923
+ parentId: newParentId,
1924
+ pos
1925
+ }));
1926
+ },
1927
+ moveAfter: (nodeId, siblingId) => {
1928
+ var _state$find$type2, _state$find2, _nextSibling$pos2;
1929
+ const state = getCurrentState();
1930
+ const node = state.find((n) => n.id === nodeId);
1931
+ const sibling = state.find((n) => n.id === siblingId);
1932
+ if (!node) throw new ValidationError(`Node not found: ${nodeId}`);
1933
+ if (!sibling) throw new ValidationError(`Sibling node not found: ${siblingId}`);
1934
+ const newParentId = sibling.parentId;
1935
+ if (wouldCreateCycle(state, nodeId, newParentId)) throw new ValidationError("Move would create a cycle in the tree");
1936
+ const newParentType = newParentId === null ? null : (_state$find$type2 = (_state$find2 = state.find((n) => n.id === newParentId)) === null || _state$find2 === void 0 ? void 0 : _state$find2.type) !== null && _state$find$type2 !== void 0 ? _state$find$type2 : null;
1937
+ this._validateChildType(newParentType, node.type);
1938
+ if (node.parentId === null && newParentId !== null) throw new ValidationError("Cannot move root node to have a parent");
1939
+ const siblings = getOrderedChildren(state, newParentId).filter((n) => n.id !== nodeId);
1940
+ const nextSibling = siblings[siblings.findIndex((n) => n.id === siblingId) + 1];
1941
+ const pos = generateTreePosBetween(sibling.pos, (_nextSibling$pos2 = nextSibling === null || nextSibling === void 0 ? void 0 : nextSibling.pos) !== null && _nextSibling$pos2 !== void 0 ? _nextSibling$pos2 : null);
1942
+ env.addOperation(fromDefinition(operationPath, this._opDefinitions.move, {
1943
+ id: nodeId,
1944
+ parentId: newParentId,
1945
+ pos
1946
+ }));
1947
+ },
1948
+ moveBefore: (nodeId, siblingId) => {
1949
+ var _state$find$type3, _state$find3, _prevSibling$pos2;
1950
+ const state = getCurrentState();
1951
+ const node = state.find((n) => n.id === nodeId);
1952
+ const sibling = state.find((n) => n.id === siblingId);
1953
+ if (!node) throw new ValidationError(`Node not found: ${nodeId}`);
1954
+ if (!sibling) throw new ValidationError(`Sibling node not found: ${siblingId}`);
1955
+ const newParentId = sibling.parentId;
1956
+ if (wouldCreateCycle(state, nodeId, newParentId)) throw new ValidationError("Move would create a cycle in the tree");
1957
+ const newParentType = newParentId === null ? null : (_state$find$type3 = (_state$find3 = state.find((n) => n.id === newParentId)) === null || _state$find3 === void 0 ? void 0 : _state$find3.type) !== null && _state$find$type3 !== void 0 ? _state$find$type3 : null;
1958
+ this._validateChildType(newParentType, node.type);
1959
+ if (node.parentId === null && newParentId !== null) throw new ValidationError("Cannot move root node to have a parent");
1960
+ const siblings = getOrderedChildren(state, newParentId).filter((n) => n.id !== nodeId);
1961
+ const prevSibling = siblings[siblings.findIndex((n) => n.id === siblingId) - 1];
1962
+ const pos = generateTreePosBetween((_prevSibling$pos2 = prevSibling === null || prevSibling === void 0 ? void 0 : prevSibling.pos) !== null && _prevSibling$pos2 !== void 0 ? _prevSibling$pos2 : null, sibling.pos);
1963
+ env.addOperation(fromDefinition(operationPath, this._opDefinitions.move, {
1964
+ id: nodeId,
1965
+ parentId: newParentId,
1966
+ pos
1967
+ }));
1968
+ },
1969
+ moveToFirst: (nodeId, newParentId) => {
1970
+ var _state$find$type4, _state$find4;
1971
+ const state = getCurrentState();
1972
+ const node = state.find((n) => n.id === nodeId);
1973
+ if (!node) throw new ValidationError(`Node not found: ${nodeId}`);
1974
+ if (newParentId !== null && !state.find((n) => n.id === newParentId)) throw new ValidationError(`Parent node not found: ${newParentId}`);
1975
+ if (wouldCreateCycle(state, nodeId, newParentId)) throw new ValidationError("Move would create a cycle in the tree");
1976
+ const newParentType = newParentId === null ? null : (_state$find$type4 = (_state$find4 = state.find((n) => n.id === newParentId)) === null || _state$find4 === void 0 ? void 0 : _state$find4.type) !== null && _state$find$type4 !== void 0 ? _state$find$type4 : null;
1977
+ this._validateChildType(newParentType, node.type);
1978
+ if (node.parentId === null && newParentId !== null) throw new ValidationError("Cannot move root node to have a parent");
1979
+ const siblings = getOrderedChildren(state, newParentId).filter((n) => n.id !== nodeId);
1980
+ const pos = generateTreePosBetween(null, siblings.length > 0 ? siblings[0].pos : null);
1981
+ env.addOperation(fromDefinition(operationPath, this._opDefinitions.move, {
1982
+ id: nodeId,
1983
+ parentId: newParentId,
1984
+ pos
1985
+ }));
1986
+ },
1987
+ moveToLast: (nodeId, newParentId) => {
1988
+ var _state$find$type5, _state$find5;
1989
+ const state = getCurrentState();
1990
+ const node = state.find((n) => n.id === nodeId);
1991
+ if (!node) throw new ValidationError(`Node not found: ${nodeId}`);
1992
+ if (newParentId !== null && !state.find((n) => n.id === newParentId)) throw new ValidationError(`Parent node not found: ${newParentId}`);
1993
+ if (wouldCreateCycle(state, nodeId, newParentId)) throw new ValidationError("Move would create a cycle in the tree");
1994
+ const newParentType = newParentId === null ? null : (_state$find$type5 = (_state$find5 = state.find((n) => n.id === newParentId)) === null || _state$find5 === void 0 ? void 0 : _state$find5.type) !== null && _state$find$type5 !== void 0 ? _state$find$type5 : null;
1995
+ this._validateChildType(newParentType, node.type);
1996
+ if (node.parentId === null && newParentId !== null) throw new ValidationError("Cannot move root node to have a parent");
1997
+ const siblings = getOrderedChildren(state, newParentId).filter((n) => n.id !== nodeId);
1998
+ const pos = generateTreePosBetween(siblings.length > 0 ? siblings[siblings.length - 1].pos : null, null);
1999
+ env.addOperation(fromDefinition(operationPath, this._opDefinitions.move, {
2000
+ id: nodeId,
2001
+ parentId: newParentId,
2002
+ pos
2003
+ }));
2004
+ },
2005
+ at: (id, nodeType) => {
2006
+ const node = getCurrentState().find((n) => n.id === id);
2007
+ if (!node) throw new ValidationError(`Node not found: ${id}`);
2008
+ if (node.type !== nodeType.type) throw new ValidationError(`Node is of type "${node.type}", not "${nodeType.type}"`);
2009
+ const nodePath = operationPath.append(id);
2010
+ return nodeType.data._internal.createProxy(env, nodePath);
2011
+ },
2012
+ toSnapshot: () => {
2013
+ const state = getCurrentState();
2014
+ const rootNode = state.find((n) => n.parentId === null);
2015
+ if (!rootNode) return void 0;
2016
+ return buildSnapshot(rootNode.id, state);
2017
+ }
2018
+ };
2019
+ },
2020
+ applyOperation: (state, operation) => {
2021
+ const path = operation.path;
2022
+ const tokens = path.toTokens().filter((t) => t !== "");
2023
+ const currentState = state !== null && state !== void 0 ? state : [];
2024
+ let newState;
2025
+ if (tokens.length === 0) switch (operation.kind) {
2026
+ case "tree.set": {
2027
+ const payload = operation.payload;
2028
+ if (!globalThis.Array.isArray(payload)) throw new ValidationError(`TreePrimitive.set requires an array payload`);
2029
+ newState = payload;
2030
+ break;
2031
+ }
2032
+ case "tree.insert": {
2033
+ const { id, type, parentId, pos, data } = operation.payload;
2034
+ newState = [...currentState, {
2035
+ id,
2036
+ type,
2037
+ parentId,
2038
+ pos,
2039
+ data
2040
+ }];
2041
+ break;
2042
+ }
2043
+ case "tree.remove": {
2044
+ const { id } = operation.payload;
2045
+ const descendantIds = getDescendantIds(currentState, id);
2046
+ const idsToRemove = new Set([id, ...descendantIds]);
2047
+ newState = currentState.filter((node) => !idsToRemove.has(node.id));
2048
+ break;
2049
+ }
2050
+ case "tree.move": {
2051
+ const { id, parentId, pos } = operation.payload;
2052
+ newState = currentState.map((node) => node.id === id ? _objectSpread2(_objectSpread2({}, node), {}, {
2053
+ parentId,
2054
+ pos
2055
+ }) : node);
2056
+ break;
2057
+ }
2058
+ default: throw new ValidationError(`TreePrimitive cannot apply operation of kind: ${operation.kind}`);
2059
+ }
2060
+ else {
2061
+ const nodeId = tokens[0];
2062
+ const nodeIndex = currentState.findIndex((node$1) => node$1.id === nodeId);
2063
+ if (nodeIndex === -1) throw new ValidationError(`Tree node not found with ID: ${nodeId}`);
2064
+ const node = currentState[nodeIndex];
2065
+ const nodeTypePrimitive = this._getNodeTypePrimitive(node.type);
2066
+ const remainingPath = path.shift();
2067
+ const nodeOperation = _objectSpread2(_objectSpread2({}, operation), {}, { path: remainingPath });
2068
+ const newData = nodeTypePrimitive.data._internal.applyOperation(node.data, nodeOperation);
2069
+ const mutableState = [...currentState];
2070
+ mutableState[nodeIndex] = _objectSpread2(_objectSpread2({}, node), {}, { data: newData });
2071
+ newState = mutableState;
2072
+ }
2073
+ runValidators(newState, this._schema.validators);
2074
+ return newState;
2075
+ },
2076
+ getInitialState: () => {
2077
+ var _rootNodeType$data$_i;
2078
+ if (this._schema.defaultValue !== void 0) return this._schema.defaultValue;
2079
+ const rootNodeType = this._schema.root;
2080
+ const rootData = (_rootNodeType$data$_i = rootNodeType.data._internal.getInitialState()) !== null && _rootNodeType$data$_i !== void 0 ? _rootNodeType$data$_i : {};
2081
+ const rootId = crypto.randomUUID();
2082
+ const rootPos = generateTreePosBetween(null, null);
2083
+ return [{
2084
+ id: rootId,
2085
+ type: rootNodeType.type,
2086
+ parentId: null,
2087
+ pos: rootPos,
2088
+ data: rootData
2089
+ }];
2090
+ },
2091
+ transformOperation: (clientOp, serverOp) => {
2092
+ const clientPath = clientOp.path;
2093
+ const serverPath = serverOp.path;
2094
+ if (!pathsOverlap(clientPath, serverPath)) return {
2095
+ type: "transformed",
2096
+ operation: clientOp
2097
+ };
2098
+ if (serverOp.kind === "tree.remove") {
2099
+ const removedId = serverOp.payload.id;
2100
+ const clientTokens$1 = clientPath.toTokens().filter((t) => t !== "");
2101
+ const serverTokens$1 = serverPath.toTokens().filter((t) => t !== "");
2102
+ if (clientOp.kind === "tree.move") {
2103
+ const movePayload = clientOp.payload;
2104
+ if (movePayload.id === removedId || movePayload.parentId === removedId) return { type: "noop" };
2105
+ }
2106
+ if (clientOp.kind === "tree.insert") {
2107
+ if (clientOp.payload.parentId === removedId) return { type: "noop" };
2108
+ }
2109
+ if (clientTokens$1.length > serverTokens$1.length) {
2110
+ if (clientTokens$1[serverTokens$1.length] === removedId) return { type: "noop" };
2111
+ }
2112
+ }
2113
+ if (serverOp.kind === "tree.insert" && clientOp.kind === "tree.insert") return {
2114
+ type: "transformed",
2115
+ operation: clientOp
2116
+ };
2117
+ if (serverOp.kind === "tree.move" && clientOp.kind === "tree.move") {
2118
+ if (serverOp.payload.id === clientOp.payload.id) return {
2119
+ type: "transformed",
2120
+ operation: clientOp
2121
+ };
2122
+ return {
2123
+ type: "transformed",
2124
+ operation: clientOp
2125
+ };
2126
+ }
2127
+ if (pathsEqual(clientPath, serverPath)) return {
2128
+ type: "transformed",
2129
+ operation: clientOp
2130
+ };
2131
+ if (serverOp.kind === "tree.set" && isPrefix(serverPath, clientPath)) return {
2132
+ type: "transformed",
2133
+ operation: clientOp
2134
+ };
2135
+ const clientTokens = clientPath.toTokens().filter((t) => t !== "");
2136
+ const serverTokens = serverPath.toTokens().filter((t) => t !== "");
2137
+ if (clientTokens.length > 0 && serverTokens.length > 0) {
2138
+ if (clientTokens[0] !== serverTokens[0]) return {
2139
+ type: "transformed",
2140
+ operation: clientOp
2141
+ };
2142
+ return {
2143
+ type: "transformed",
2144
+ operation: clientOp
2145
+ };
2146
+ }
2147
+ return {
2148
+ type: "transformed",
2149
+ operation: clientOp
2150
+ };
2151
+ }
2152
+ });
2153
+ this._schema = schema;
2154
+ }
2155
+ /** Mark this tree as required */
2156
+ required() {
2157
+ return new TreePrimitive(_objectSpread2(_objectSpread2({}, this._schema), {}, { required: true }));
2158
+ }
2159
+ /** Set a default value for this tree */
2160
+ default(defaultValue) {
2161
+ return new TreePrimitive(_objectSpread2(_objectSpread2({}, this._schema), {}, { defaultValue }));
2162
+ }
2163
+ /** Get the root node type */
2164
+ get root() {
2165
+ return this._schema.root;
2166
+ }
2167
+ /** Add a custom validation rule */
2168
+ refine(fn, message) {
2169
+ return new TreePrimitive(_objectSpread2(_objectSpread2({}, this._schema), {}, { validators: [...this._schema.validators, {
2170
+ validate: fn,
2171
+ message
2172
+ }] }));
2173
+ }
2174
+ /**
2175
+ * Build a registry of all node types reachable from root
2176
+ */
2177
+ _buildNodeTypeRegistry() {
2178
+ if (this._nodeTypeRegistry !== void 0) return this._nodeTypeRegistry;
2179
+ const registry = /* @__PURE__ */ new Map();
2180
+ const visited = /* @__PURE__ */ new Set();
2181
+ const visit = (node) => {
2182
+ if (visited.has(node.type)) return;
2183
+ visited.add(node.type);
2184
+ registry.set(node.type, node);
2185
+ for (const child of node.children) visit(child);
2186
+ };
2187
+ visit(this._schema.root);
2188
+ this._nodeTypeRegistry = registry;
2189
+ return registry;
2190
+ }
2191
+ /**
2192
+ * Get a node type primitive by its type string
2193
+ */
2194
+ _getNodeTypePrimitive(type) {
2195
+ const nodeType = this._buildNodeTypeRegistry().get(type);
2196
+ if (!nodeType) throw new ValidationError(`Unknown node type: ${type}`);
2197
+ return nodeType;
2198
+ }
2199
+ /**
2200
+ * Validate that a node type can be a child of a parent node type
2201
+ */
2202
+ _validateChildType(parentType, childType) {
2203
+ if (parentType === null) {
2204
+ if (childType !== this._schema.root.type) throw new ValidationError(`Root node must be of type "${this._schema.root.type}", got "${childType}"`);
2205
+ return;
2206
+ }
2207
+ const parentNodePrimitive = this._getNodeTypePrimitive(parentType);
2208
+ if (!parentNodePrimitive.isChildAllowed(childType)) throw new ValidationError(`Node type "${childType}" is not allowed as a child of "${parentType}". Allowed types: ${parentNodePrimitive.children.map((c) => c.type).join(", ") || "none"}`);
2209
+ }
2210
+ };
2211
+ /** Creates a new TreePrimitive with the given root node type */
2212
+ const Tree = (options) => new TreePrimitive({
2213
+ required: false,
2214
+ defaultValue: void 0,
2215
+ root: options.root,
2216
+ validators: []
2217
+ });
2218
+
2219
+ //#endregion
2220
+ //#region src/Primitive.ts
2221
+ var Primitive_exports = /* @__PURE__ */ __export({
2222
+ Array: () => Array$1,
2223
+ ArrayPrimitive: () => ArrayPrimitive,
2224
+ Boolean: () => Boolean,
2225
+ BooleanPrimitive: () => BooleanPrimitive,
2226
+ Lazy: () => Lazy,
2227
+ LazyPrimitive: () => LazyPrimitive,
2228
+ Literal: () => Literal,
2229
+ LiteralPrimitive: () => LiteralPrimitive,
2230
+ Number: () => Number$1,
2231
+ NumberPrimitive: () => NumberPrimitive,
2232
+ String: () => String$1,
2233
+ StringPrimitive: () => StringPrimitive,
2234
+ Struct: () => Struct,
2235
+ StructPrimitive: () => StructPrimitive,
2236
+ Tree: () => Tree,
2237
+ TreeNode: () => TreeNode,
2238
+ TreeNodePrimitive: () => TreeNodePrimitive,
2239
+ TreePrimitive: () => TreePrimitive,
2240
+ Union: () => Union,
2241
+ UnionPrimitive: () => UnionPrimitive,
2242
+ ValidationError: () => ValidationError,
2243
+ isCompatibleOperation: () => isCompatibleOperation,
2244
+ runValidators: () => runValidators
2245
+ });
2246
+
2247
+ //#endregion
2248
+ //#region src/ProxyEnvironment.ts
2249
+ var ProxyEnvironment_exports = /* @__PURE__ */ __export({ make: () => make$3 });
2250
+ /** Default UUID generator using crypto.randomUUID */
2251
+ const defaultGenerateId = () => {
2252
+ return crypto.randomUUID();
2253
+ };
2254
+ /** Default state getter that always returns undefined */
2255
+ const defaultGetState = (_path) => {};
2256
+ /**
2257
+ * Creates a ProxyEnvironment.
2258
+ * @param optionsOrCallback - Either an options object or a simple callback for operations
2259
+ */
2260
+ const make$3 = (optionsOrCallback) => {
2261
+ var _options$getState, _options$generateId;
2262
+ const options = typeof optionsOrCallback === "function" ? { onOperation: optionsOrCallback } : optionsOrCallback;
2263
+ return {
2264
+ addOperation: (operation) => {
2265
+ options.onOperation(operation);
2266
+ },
2267
+ getState: (_options$getState = options.getState) !== null && _options$getState !== void 0 ? _options$getState : defaultGetState,
2268
+ generateId: (_options$generateId = options.generateId) !== null && _options$generateId !== void 0 ? _options$generateId : defaultGenerateId
2269
+ };
2270
+ };
2271
+
2272
+ //#endregion
2273
+ //#region src/Transaction.ts
2274
+ var Transaction_exports = /* @__PURE__ */ __export({
2275
+ decode: () => decode,
2276
+ empty: () => empty,
2277
+ encode: () => encode,
2278
+ isEmpty: () => isEmpty,
2279
+ make: () => make$2,
2280
+ merge: () => merge
2281
+ });
2282
+ /**
2283
+ * Creates a new Transaction with the given operations.
2284
+ */
2285
+ const make$2 = (ops) => ({
2286
+ id: crypto.randomUUID(),
2287
+ ops,
2288
+ timestamp: Date.now()
2289
+ });
2290
+ /**
2291
+ * Creates an empty Transaction.
2292
+ */
2293
+ const empty = () => make$2([]);
2294
+ /**
2295
+ * Checks if a transaction is empty (has no operations).
2296
+ */
2297
+ const isEmpty = (tx) => tx.ops.length === 0;
2298
+ /**
2299
+ * Merges multiple transactions into one.
2300
+ */
2301
+ const merge = (txs) => {
2302
+ return make$2(txs.flatMap((tx) => tx.ops));
2303
+ };
2304
+ /**
2305
+ * Encodes a Transaction to a JSON-serializable format for network transport.
2306
+ * @param transaction - The transaction to encode.
2307
+ * @returns The encoded representation.
2308
+ */
2309
+ const encode = (transaction) => ({
2310
+ id: transaction.id,
2311
+ ops: transaction.ops.map(encode$1),
2312
+ timestamp: transaction.timestamp
2313
+ });
2314
+ /**
2315
+ * Decodes an encoded transaction back to a Transaction.
2316
+ * @param encoded - The encoded representation.
2317
+ * @returns The decoded Transaction.
2318
+ */
2319
+ const decode = (encoded) => ({
2320
+ id: encoded.id,
2321
+ ops: encoded.ops.map(decode$1),
2322
+ timestamp: encoded.timestamp
2323
+ });
2324
+
2325
+ //#endregion
2326
+ //#region src/Document.ts
2327
+ var Document_exports = /* @__PURE__ */ __export({
2328
+ NestedTransactionError: () => NestedTransactionError,
2329
+ OperationError: () => OperationError,
2330
+ make: () => make$1
2331
+ });
2332
+ /**
2333
+ * Error thrown when attempting to start a nested transaction.
2334
+ */
2335
+ var NestedTransactionError = class extends Error {
2336
+ constructor() {
2337
+ super("Nested transactions are not supported");
2338
+ _defineProperty(this, "_tag", "NestedTransactionError");
2339
+ this.name = "NestedTransactionError";
2340
+ }
2341
+ };
2342
+ /**
2343
+ * Error thrown when an operation fails to apply.
2344
+ */
2345
+ var OperationError = class extends Error {
2346
+ constructor(message) {
2347
+ super(message);
2348
+ _defineProperty(this, "_tag", "OperationError");
2349
+ this.name = "OperationError";
2350
+ }
2351
+ };
2352
+ /**
2353
+ * Creates a new Document for the given schema.
2354
+ */
2355
+ const make$1 = (schema, options) => {
2356
+ var _options$initial;
2357
+ let _state = (_options$initial = options === null || options === void 0 ? void 0 : options.initial) !== null && _options$initial !== void 0 ? _options$initial : schema._internal.getInitialState();
2358
+ let _pending = [];
2359
+ let _inTransaction = false;
2360
+ let _txOps = [];
2361
+ let _txBaseState = void 0;
2362
+ /**
2363
+ * Gets state at the given path.
2364
+ */
2365
+ const getStateAtPath = (path) => {
2366
+ const tokens = path.toTokens().filter((t) => t !== "");
2367
+ if (tokens.length === 0) return _state;
2368
+ let current = _state;
2369
+ for (const token of tokens) {
2370
+ if (current === null || current === void 0) return;
2371
+ if (typeof current === "object") {
2372
+ if (Array.isArray(current)) {
2373
+ const entry = current.find((e) => e.id === token);
2374
+ if (entry) {
2375
+ current = entry.value;
2376
+ continue;
2377
+ }
2378
+ }
2379
+ current = current[token];
2380
+ } else return;
2381
+ }
2382
+ return current;
2383
+ };
2384
+ /**
2385
+ * Applies a single operation to the current state.
2386
+ */
2387
+ const applyOperation = (op) => {
2388
+ try {
2389
+ _state = schema._internal.applyOperation(_state, op);
2390
+ } catch (error) {
2391
+ if (error instanceof Error) throw new OperationError(error.message);
2392
+ throw new OperationError(String(error));
2393
+ }
2394
+ };
2395
+ /**
2396
+ * Handles an operation from a proxy.
2397
+ * In transaction mode: collects operations, applies to state immediately for subsequent reads.
2398
+ * Outside transaction mode: auto-wraps in a single-operation transaction.
2399
+ */
2400
+ const handleOperation = (op) => {
2401
+ if (_inTransaction) {
2402
+ _txOps.push(op);
2403
+ applyOperation(op);
2404
+ } else {
2405
+ const baseState = _state;
2406
+ try {
2407
+ applyOperation(op);
2408
+ _pending.push(op);
2409
+ } catch (error) {
2410
+ _state = baseState;
2411
+ throw error;
2412
+ }
2413
+ }
2414
+ };
2415
+ /**
2416
+ * Creates a ProxyEnvironment for the document.
2417
+ */
2418
+ const createEnv = () => {
2419
+ return make$3({
2420
+ onOperation: handleOperation,
2421
+ getState: getStateAtPath
2422
+ });
2423
+ };
2424
+ const env = createEnv();
2425
+ const rootProxy = schema._internal.createProxy(env, make$4(""));
2426
+ return {
2427
+ schema,
2428
+ root: rootProxy,
2429
+ get: () => {
2430
+ return _state;
2431
+ },
2432
+ toSnapshot: () => {
2433
+ return rootProxy.toSnapshot();
2434
+ },
2435
+ transaction: (fn) => {
2436
+ if (_inTransaction) throw new NestedTransactionError();
2437
+ _inTransaction = true;
2438
+ _txOps = [];
2439
+ _txBaseState = _state;
2440
+ try {
2441
+ const result = fn(rootProxy);
2442
+ _pending.push(..._txOps);
2443
+ return result;
2444
+ } catch (error) {
2445
+ _state = _txBaseState;
2446
+ throw error;
2447
+ } finally {
2448
+ _inTransaction = false;
2449
+ _txOps = [];
2450
+ _txBaseState = void 0;
2451
+ }
2452
+ },
2453
+ apply: (ops) => {
2454
+ for (const op of ops) applyOperation(op);
2455
+ },
2456
+ flush: () => {
2457
+ const tx = make$2(_pending);
2458
+ _pending = [];
2459
+ return tx;
2460
+ }
2461
+ };
2462
+ };
2463
+
2464
+ //#endregion
2465
+ //#region src/Transform.ts
2466
+ var Transform_exports = {};
2467
+
2468
+ //#endregion
2469
+ //#region src/Presence.ts
2470
+ /**
2471
+ * @since 0.0.1
2472
+ * Presence module for ephemeral per-connection state.
2473
+ * Used by both client and server for schema validation.
2474
+ */
2475
+ var Presence_exports = /* @__PURE__ */ __export({
2476
+ isValid: () => isValid,
2477
+ make: () => make,
2478
+ validate: () => validate,
2479
+ validateSafe: () => validateSafe
2480
+ });
2481
+ /**
2482
+ * Creates a new Presence schema wrapper.
2483
+ *
2484
+ * @example
2485
+ * ```typescript
2486
+ * import { Presence } from "@voidhash/mimic";
2487
+ * import { Schema } from "effect";
2488
+ *
2489
+ * const CursorPresence = Presence.make({
2490
+ * schema: Schema.Struct({
2491
+ * name: Schema.String,
2492
+ * cursor: Schema.Struct({
2493
+ * x: Schema.Number,
2494
+ * y: Schema.Number,
2495
+ * }),
2496
+ * }),
2497
+ * });
2498
+ * ```
2499
+ */
2500
+ const make = (options) => ({
2501
+ _tag: "Presence",
2502
+ schema: options.schema,
2503
+ _Data: void 0
2504
+ });
2505
+ /**
2506
+ * Validates unknown data against a Presence schema.
2507
+ * Throws a ParseError if validation fails.
2508
+ *
2509
+ * @param presence - The Presence instance with the schema
2510
+ * @param data - Unknown data to validate
2511
+ * @returns The validated and typed data
2512
+ * @throws ParseError if validation fails
2513
+ */
2514
+ const validate = (presence, data) => {
2515
+ return Schema$1.decodeUnknownSync(presence.schema)(data);
2516
+ };
2517
+ /**
2518
+ * Safely validates unknown data against a Presence schema.
2519
+ * Returns undefined if validation fails instead of throwing.
2520
+ *
2521
+ * @param presence - The Presence instance with the schema
2522
+ * @param data - Unknown data to validate
2523
+ * @returns The validated data or undefined if invalid
2524
+ */
2525
+ const validateSafe = (presence, data) => {
2526
+ try {
2527
+ return Schema$1.decodeUnknownSync(presence.schema)(data);
2528
+ } catch (_unused) {
2529
+ return;
2530
+ }
2531
+ };
2532
+ /**
2533
+ * Checks if unknown data is valid according to a Presence schema.
2534
+ *
2535
+ * @param presence - The Presence instance with the schema
2536
+ * @param data - Unknown data to check
2537
+ * @returns true if valid, false otherwise
2538
+ */
2539
+ const isValid = (presence, data) => {
2540
+ try {
2541
+ Schema$1.decodeUnknownSync(presence.schema)(data);
2542
+ return true;
2543
+ } catch (_unused2) {
2544
+ return false;
2545
+ }
2546
+ };
2547
+
2548
+ //#endregion
2549
+ export { Document_exports as Document, Operation_exports as Operation, OperationPath_exports as OperationPath, Presence_exports as Presence, Primitive_exports as Primitive, ProxyEnvironment_exports as ProxyEnvironment, Transaction_exports as Transaction, Transform_exports as Transform };
2550
+ //# sourceMappingURL=index.mjs.map