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