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