@voidhash/mimic 0.0.1-alpha.1 → 0.0.1-alpha.10
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 +51 -0
- package/LICENSE.md +663 -0
- package/dist/Document-ChuFrTk1.cjs +571 -0
- package/dist/Document-CwiAFTIq.mjs +438 -0
- package/dist/Document-CwiAFTIq.mjs.map +1 -0
- package/dist/Presence-DKKP4v5X.d.cts +91 -0
- package/dist/Presence-DKKP4v5X.d.cts.map +1 -0
- package/dist/Presence-DdMVKcOv.mjs +110 -0
- package/dist/Presence-DdMVKcOv.mjs.map +1 -0
- package/dist/Presence-N8u7Eppr.d.mts +91 -0
- package/dist/Presence-N8u7Eppr.d.mts.map +1 -0
- package/dist/Presence-gWrmGBeu.cjs +126 -0
- package/dist/Primitive-CvFVxR8_.d.cts +1175 -0
- package/dist/Primitive-CvFVxR8_.d.cts.map +1 -0
- package/dist/Primitive-lEhQyGVL.d.mts +1175 -0
- package/dist/Primitive-lEhQyGVL.d.mts.map +1 -0
- package/dist/chunk-CLMFDpHK.mjs +18 -0
- package/dist/client/index.cjs +1456 -0
- package/dist/client/index.d.cts +692 -0
- package/dist/client/index.d.cts.map +1 -0
- package/dist/client/index.d.mts +692 -0
- package/dist/client/index.d.mts.map +1 -0
- package/dist/client/index.mjs +1413 -0
- package/dist/client/index.mjs.map +1 -0
- package/dist/index.cjs +2577 -0
- package/dist/index.d.cts +143 -0
- package/dist/index.d.cts.map +1 -0
- package/dist/index.d.mts +143 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +2526 -0
- package/dist/index.mjs.map +1 -0
- package/dist/server/index.cjs +191 -0
- package/dist/server/index.d.cts +148 -0
- package/dist/server/index.d.cts.map +1 -0
- package/dist/server/index.d.mts +148 -0
- package/dist/server/index.d.mts.map +1 -0
- package/dist/server/index.mjs +182 -0
- package/dist/server/index.mjs.map +1 -0
- package/package.json +25 -13
- package/src/EffectSchema.ts +374 -0
- package/src/Primitive.ts +3 -0
- package/src/client/ClientDocument.ts +1 -1
- package/src/client/errors.ts +10 -10
- package/src/index.ts +1 -0
- package/src/primitives/Array.ts +57 -22
- package/src/primitives/Boolean.ts +33 -19
- package/src/primitives/Either.ts +379 -0
- package/src/primitives/Lazy.ts +16 -2
- package/src/primitives/Literal.ts +33 -20
- package/src/primitives/Number.ts +39 -26
- package/src/primitives/String.ts +40 -25
- package/src/primitives/Struct.ts +126 -29
- package/src/primitives/Tree.ts +119 -32
- package/src/primitives/TreeNode.ts +77 -30
- package/src/primitives/Union.ts +56 -29
- package/src/primitives/shared.ts +111 -9
- package/src/server/errors.ts +6 -6
- package/tests/EffectSchema.test.ts +546 -0
- package/tests/primitives/Array.test.ts +108 -0
- package/tests/primitives/Either.test.ts +707 -0
- package/tests/primitives/Struct.test.ts +250 -0
- package/tests/primitives/Tree.test.ts +250 -0
- package/tsdown.config.ts +1 -1
|
@@ -0,0 +1,438 @@
|
|
|
1
|
+
import { t as __export } from "./chunk-CLMFDpHK.mjs";
|
|
2
|
+
|
|
3
|
+
//#region \0@oxc-project+runtime@0.103.0/helpers/typeof.js
|
|
4
|
+
function _typeof(o) {
|
|
5
|
+
"@babel/helpers - typeof";
|
|
6
|
+
return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(o$1) {
|
|
7
|
+
return typeof o$1;
|
|
8
|
+
} : function(o$1) {
|
|
9
|
+
return o$1 && "function" == typeof Symbol && o$1.constructor === Symbol && o$1 !== Symbol.prototype ? "symbol" : typeof o$1;
|
|
10
|
+
}, _typeof(o);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
//#endregion
|
|
14
|
+
//#region \0@oxc-project+runtime@0.103.0/helpers/toPrimitive.js
|
|
15
|
+
function toPrimitive(t, r) {
|
|
16
|
+
if ("object" != _typeof(t) || !t) return t;
|
|
17
|
+
var e = t[Symbol.toPrimitive];
|
|
18
|
+
if (void 0 !== e) {
|
|
19
|
+
var i = e.call(t, r || "default");
|
|
20
|
+
if ("object" != _typeof(i)) return i;
|
|
21
|
+
throw new TypeError("@@toPrimitive must return a primitive value.");
|
|
22
|
+
}
|
|
23
|
+
return ("string" === r ? String : Number)(t);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
//#endregion
|
|
27
|
+
//#region \0@oxc-project+runtime@0.103.0/helpers/toPropertyKey.js
|
|
28
|
+
function toPropertyKey(t) {
|
|
29
|
+
var i = toPrimitive(t, "string");
|
|
30
|
+
return "symbol" == _typeof(i) ? i : i + "";
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
//#endregion
|
|
34
|
+
//#region \0@oxc-project+runtime@0.103.0/helpers/defineProperty.js
|
|
35
|
+
function _defineProperty(e, r, t) {
|
|
36
|
+
return (r = toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
|
|
37
|
+
value: t,
|
|
38
|
+
enumerable: !0,
|
|
39
|
+
configurable: !0,
|
|
40
|
+
writable: !0
|
|
41
|
+
}) : e[r] = t, e;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
//#endregion
|
|
45
|
+
//#region src/OperationPath.ts
|
|
46
|
+
var OperationPath_exports = /* @__PURE__ */ __export({
|
|
47
|
+
decode: () => decode$2,
|
|
48
|
+
encode: () => encode$2,
|
|
49
|
+
fromTokens: () => fromTokens,
|
|
50
|
+
getRelativePath: () => getRelativePath,
|
|
51
|
+
isPrefix: () => isPrefix,
|
|
52
|
+
make: () => make$3,
|
|
53
|
+
pathsEqual: () => pathsEqual,
|
|
54
|
+
pathsOverlap: () => pathsOverlap
|
|
55
|
+
});
|
|
56
|
+
const parseStringPath = (stringPath) => {
|
|
57
|
+
return stringPath.split("/");
|
|
58
|
+
};
|
|
59
|
+
const makeStringPathFromTokens = (tokens) => {
|
|
60
|
+
return tokens.join("/");
|
|
61
|
+
};
|
|
62
|
+
/**
|
|
63
|
+
* Creates a new operation path.
|
|
64
|
+
* @param stringPath - The string path to create the path from.
|
|
65
|
+
* @returns The new operation path.
|
|
66
|
+
*/
|
|
67
|
+
function make$3(stringPath) {
|
|
68
|
+
const tokensInternal = stringPath ? parseStringPath(stringPath) : [];
|
|
69
|
+
/**
|
|
70
|
+
* Returns the tokens of the path.
|
|
71
|
+
* @returns The tokens of the path.
|
|
72
|
+
*/
|
|
73
|
+
const toTokens = () => {
|
|
74
|
+
return tokensInternal;
|
|
75
|
+
};
|
|
76
|
+
/**
|
|
77
|
+
* Concatenates two paths.
|
|
78
|
+
* @param other - The other path to concatenate.
|
|
79
|
+
* @returns The new path.
|
|
80
|
+
*/
|
|
81
|
+
const concat = (other) => {
|
|
82
|
+
return make$3(makeStringPathFromTokens(toTokens().concat(other.toTokens())));
|
|
83
|
+
};
|
|
84
|
+
/**
|
|
85
|
+
* Appends a token to the path.
|
|
86
|
+
* @param token - The token to append.
|
|
87
|
+
* @returns The new path.
|
|
88
|
+
*/
|
|
89
|
+
const append = (token) => {
|
|
90
|
+
return make$3(makeStringPathFromTokens(toTokens().concat([token])));
|
|
91
|
+
};
|
|
92
|
+
/**
|
|
93
|
+
* Removes the last token from the path.
|
|
94
|
+
* @returns The new path.
|
|
95
|
+
*/
|
|
96
|
+
const pop = () => {
|
|
97
|
+
return make$3(makeStringPathFromTokens(toTokens().slice(0, -1)));
|
|
98
|
+
};
|
|
99
|
+
/**
|
|
100
|
+
* Removes the first token from the path.
|
|
101
|
+
* @returns The new path.
|
|
102
|
+
*/
|
|
103
|
+
const shift = () => {
|
|
104
|
+
return make$3(makeStringPathFromTokens(toTokens().slice(1)));
|
|
105
|
+
};
|
|
106
|
+
return {
|
|
107
|
+
_tag: "OperationPath",
|
|
108
|
+
toTokens,
|
|
109
|
+
concat,
|
|
110
|
+
append,
|
|
111
|
+
pop,
|
|
112
|
+
shift
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Creates a new operation path from tokens.
|
|
117
|
+
* @param tokens - The tokens to create the path from.
|
|
118
|
+
* @returns The new operation path.
|
|
119
|
+
*/
|
|
120
|
+
function fromTokens(tokens) {
|
|
121
|
+
return make$3(makeStringPathFromTokens(tokens));
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Checks if two operation paths overlap (one is prefix of the other or equal).
|
|
125
|
+
*/
|
|
126
|
+
const pathsOverlap = (pathA, pathB) => {
|
|
127
|
+
const tokensA = pathA.toTokens().filter((t) => t !== "");
|
|
128
|
+
const tokensB = pathB.toTokens().filter((t) => t !== "");
|
|
129
|
+
const minLength = Math.min(tokensA.length, tokensB.length);
|
|
130
|
+
for (let i = 0; i < minLength; i++) if (tokensA[i] !== tokensB[i]) return false;
|
|
131
|
+
return true;
|
|
132
|
+
};
|
|
133
|
+
/**
|
|
134
|
+
* Checks if pathA is a prefix of pathB (pathA is ancestor of pathB).
|
|
135
|
+
*/
|
|
136
|
+
const isPrefix = (pathA, pathB) => {
|
|
137
|
+
const tokensA = pathA.toTokens().filter((t) => t !== "");
|
|
138
|
+
const tokensB = pathB.toTokens().filter((t) => t !== "");
|
|
139
|
+
if (tokensA.length > tokensB.length) return false;
|
|
140
|
+
for (let i = 0; i < tokensA.length; i++) if (tokensA[i] !== tokensB[i]) return false;
|
|
141
|
+
return true;
|
|
142
|
+
};
|
|
143
|
+
/**
|
|
144
|
+
* Checks if two paths are exactly equal.
|
|
145
|
+
*/
|
|
146
|
+
const pathsEqual = (pathA, pathB) => {
|
|
147
|
+
const tokensA = pathA.toTokens().filter((t) => t !== "");
|
|
148
|
+
const tokensB = pathB.toTokens().filter((t) => t !== "");
|
|
149
|
+
if (tokensA.length !== tokensB.length) return false;
|
|
150
|
+
for (let i = 0; i < tokensA.length; i++) if (tokensA[i] !== tokensB[i]) return false;
|
|
151
|
+
return true;
|
|
152
|
+
};
|
|
153
|
+
/**
|
|
154
|
+
* Gets the relative path of pathB with respect to pathA.
|
|
155
|
+
* Assumes pathA is a prefix of pathB.
|
|
156
|
+
*/
|
|
157
|
+
const getRelativePath = (basePath, fullPath) => {
|
|
158
|
+
const baseTokens = basePath.toTokens().filter((t) => t !== "");
|
|
159
|
+
return fullPath.toTokens().filter((t) => t !== "").slice(baseTokens.length);
|
|
160
|
+
};
|
|
161
|
+
/**
|
|
162
|
+
* Encodes an OperationPath to a string for network transport.
|
|
163
|
+
* @param path - The operation path to encode.
|
|
164
|
+
* @returns The encoded string representation.
|
|
165
|
+
*/
|
|
166
|
+
const encode$2 = (path) => {
|
|
167
|
+
return makeStringPathFromTokens(path.toTokens());
|
|
168
|
+
};
|
|
169
|
+
/**
|
|
170
|
+
* Decodes an encoded string back to an OperationPath.
|
|
171
|
+
* @param encoded - The encoded string representation.
|
|
172
|
+
* @returns The decoded OperationPath.
|
|
173
|
+
*/
|
|
174
|
+
const decode$2 = (encoded) => {
|
|
175
|
+
return make$3(encoded);
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
//#endregion
|
|
179
|
+
//#region src/Operation.ts
|
|
180
|
+
var Operation_exports = /* @__PURE__ */ __export({
|
|
181
|
+
decode: () => decode$1,
|
|
182
|
+
encode: () => encode$1,
|
|
183
|
+
fromDefinition: () => fromDefinition
|
|
184
|
+
});
|
|
185
|
+
const fromDefinition = (operationPath, definition, payload) => {
|
|
186
|
+
return {
|
|
187
|
+
kind: definition.kind,
|
|
188
|
+
path: operationPath,
|
|
189
|
+
payload
|
|
190
|
+
};
|
|
191
|
+
};
|
|
192
|
+
/**
|
|
193
|
+
* Encodes an Operation to a JSON-serializable format for network transport.
|
|
194
|
+
* @param operation - The operation to encode.
|
|
195
|
+
* @returns The encoded representation.
|
|
196
|
+
*/
|
|
197
|
+
const encode$1 = (operation) => {
|
|
198
|
+
return {
|
|
199
|
+
kind: operation.kind,
|
|
200
|
+
path: encode$2(operation.path),
|
|
201
|
+
payload: operation.payload
|
|
202
|
+
};
|
|
203
|
+
};
|
|
204
|
+
/**
|
|
205
|
+
* Decodes an encoded operation back to an Operation.
|
|
206
|
+
* Note: This returns a partial operation without the definition methods.
|
|
207
|
+
* The caller must have the operation definitions to fully reconstruct if needed.
|
|
208
|
+
* @param encoded - The encoded representation.
|
|
209
|
+
* @returns The decoded Operation (without definition-specific methods).
|
|
210
|
+
*/
|
|
211
|
+
const decode$1 = (encoded) => {
|
|
212
|
+
return {
|
|
213
|
+
kind: encoded.kind,
|
|
214
|
+
path: decode$2(encoded.path),
|
|
215
|
+
payload: encoded.payload
|
|
216
|
+
};
|
|
217
|
+
};
|
|
218
|
+
|
|
219
|
+
//#endregion
|
|
220
|
+
//#region src/ProxyEnvironment.ts
|
|
221
|
+
var ProxyEnvironment_exports = /* @__PURE__ */ __export({ make: () => make$2 });
|
|
222
|
+
/** Default UUID generator using crypto.randomUUID */
|
|
223
|
+
const defaultGenerateId = () => {
|
|
224
|
+
return crypto.randomUUID();
|
|
225
|
+
};
|
|
226
|
+
/** Default state getter that always returns undefined */
|
|
227
|
+
const defaultGetState = (_path) => {};
|
|
228
|
+
/**
|
|
229
|
+
* Creates a ProxyEnvironment.
|
|
230
|
+
* @param optionsOrCallback - Either an options object or a simple callback for operations
|
|
231
|
+
*/
|
|
232
|
+
const make$2 = (optionsOrCallback) => {
|
|
233
|
+
var _options$getState, _options$generateId;
|
|
234
|
+
const options = typeof optionsOrCallback === "function" ? { onOperation: optionsOrCallback } : optionsOrCallback;
|
|
235
|
+
return {
|
|
236
|
+
addOperation: (operation) => {
|
|
237
|
+
options.onOperation(operation);
|
|
238
|
+
},
|
|
239
|
+
getState: (_options$getState = options.getState) !== null && _options$getState !== void 0 ? _options$getState : defaultGetState,
|
|
240
|
+
generateId: (_options$generateId = options.generateId) !== null && _options$generateId !== void 0 ? _options$generateId : defaultGenerateId
|
|
241
|
+
};
|
|
242
|
+
};
|
|
243
|
+
|
|
244
|
+
//#endregion
|
|
245
|
+
//#region src/Transaction.ts
|
|
246
|
+
var Transaction_exports = /* @__PURE__ */ __export({
|
|
247
|
+
decode: () => decode,
|
|
248
|
+
empty: () => empty,
|
|
249
|
+
encode: () => encode,
|
|
250
|
+
isEmpty: () => isEmpty,
|
|
251
|
+
make: () => make$1,
|
|
252
|
+
merge: () => merge
|
|
253
|
+
});
|
|
254
|
+
/**
|
|
255
|
+
* Creates a new Transaction with the given operations.
|
|
256
|
+
*/
|
|
257
|
+
const make$1 = (ops) => ({
|
|
258
|
+
id: crypto.randomUUID(),
|
|
259
|
+
ops,
|
|
260
|
+
timestamp: Date.now()
|
|
261
|
+
});
|
|
262
|
+
/**
|
|
263
|
+
* Creates an empty Transaction.
|
|
264
|
+
*/
|
|
265
|
+
const empty = () => make$1([]);
|
|
266
|
+
/**
|
|
267
|
+
* Checks if a transaction is empty (has no operations).
|
|
268
|
+
*/
|
|
269
|
+
const isEmpty = (tx) => tx.ops.length === 0;
|
|
270
|
+
/**
|
|
271
|
+
* Merges multiple transactions into one.
|
|
272
|
+
*/
|
|
273
|
+
const merge = (txs) => {
|
|
274
|
+
return make$1(txs.flatMap((tx) => tx.ops));
|
|
275
|
+
};
|
|
276
|
+
/**
|
|
277
|
+
* Encodes a Transaction to a JSON-serializable format for network transport.
|
|
278
|
+
* @param transaction - The transaction to encode.
|
|
279
|
+
* @returns The encoded representation.
|
|
280
|
+
*/
|
|
281
|
+
const encode = (transaction) => ({
|
|
282
|
+
id: transaction.id,
|
|
283
|
+
ops: transaction.ops.map(encode$1),
|
|
284
|
+
timestamp: transaction.timestamp
|
|
285
|
+
});
|
|
286
|
+
/**
|
|
287
|
+
* Decodes an encoded transaction back to a Transaction.
|
|
288
|
+
* @param encoded - The encoded representation.
|
|
289
|
+
* @returns The decoded Transaction.
|
|
290
|
+
*/
|
|
291
|
+
const decode = (encoded) => ({
|
|
292
|
+
id: encoded.id,
|
|
293
|
+
ops: encoded.ops.map(decode$1),
|
|
294
|
+
timestamp: encoded.timestamp
|
|
295
|
+
});
|
|
296
|
+
|
|
297
|
+
//#endregion
|
|
298
|
+
//#region src/Document.ts
|
|
299
|
+
var Document_exports = /* @__PURE__ */ __export({
|
|
300
|
+
NestedTransactionError: () => NestedTransactionError,
|
|
301
|
+
OperationError: () => OperationError,
|
|
302
|
+
make: () => make
|
|
303
|
+
});
|
|
304
|
+
/**
|
|
305
|
+
* Error thrown when attempting to start a nested transaction.
|
|
306
|
+
*/
|
|
307
|
+
var NestedTransactionError = class extends Error {
|
|
308
|
+
constructor() {
|
|
309
|
+
super("Nested transactions are not supported");
|
|
310
|
+
_defineProperty(this, "_tag", "NestedTransactionError");
|
|
311
|
+
this.name = "NestedTransactionError";
|
|
312
|
+
}
|
|
313
|
+
};
|
|
314
|
+
/**
|
|
315
|
+
* Error thrown when an operation fails to apply.
|
|
316
|
+
*/
|
|
317
|
+
var OperationError = class extends Error {
|
|
318
|
+
constructor(message) {
|
|
319
|
+
super(message);
|
|
320
|
+
_defineProperty(this, "_tag", "OperationError");
|
|
321
|
+
this.name = "OperationError";
|
|
322
|
+
}
|
|
323
|
+
};
|
|
324
|
+
/**
|
|
325
|
+
* Creates a new Document for the given schema.
|
|
326
|
+
*/
|
|
327
|
+
const make = (schema, options) => {
|
|
328
|
+
var _options$initial;
|
|
329
|
+
let _state = (_options$initial = options === null || options === void 0 ? void 0 : options.initial) !== null && _options$initial !== void 0 ? _options$initial : schema._internal.getInitialState();
|
|
330
|
+
let _pending = [];
|
|
331
|
+
let _inTransaction = false;
|
|
332
|
+
let _txOps = [];
|
|
333
|
+
let _txBaseState = void 0;
|
|
334
|
+
/**
|
|
335
|
+
* Gets state at the given path.
|
|
336
|
+
*/
|
|
337
|
+
const getStateAtPath = (path) => {
|
|
338
|
+
const tokens = path.toTokens().filter((t) => t !== "");
|
|
339
|
+
if (tokens.length === 0) return _state;
|
|
340
|
+
let current = _state;
|
|
341
|
+
for (const token of tokens) {
|
|
342
|
+
if (current === null || current === void 0) return;
|
|
343
|
+
if (typeof current === "object") {
|
|
344
|
+
if (Array.isArray(current)) {
|
|
345
|
+
const entry = current.find((e) => e.id === token);
|
|
346
|
+
if (entry) {
|
|
347
|
+
current = entry.value;
|
|
348
|
+
continue;
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
current = current[token];
|
|
352
|
+
} else return;
|
|
353
|
+
}
|
|
354
|
+
return current;
|
|
355
|
+
};
|
|
356
|
+
/**
|
|
357
|
+
* Applies a single operation to the current state.
|
|
358
|
+
*/
|
|
359
|
+
const applyOperation = (op) => {
|
|
360
|
+
try {
|
|
361
|
+
_state = schema._internal.applyOperation(_state, op);
|
|
362
|
+
} catch (error) {
|
|
363
|
+
if (error instanceof Error) throw new OperationError(error.message);
|
|
364
|
+
throw new OperationError(String(error));
|
|
365
|
+
}
|
|
366
|
+
};
|
|
367
|
+
/**
|
|
368
|
+
* Handles an operation from a proxy.
|
|
369
|
+
* In transaction mode: collects operations, applies to state immediately for subsequent reads.
|
|
370
|
+
* Outside transaction mode: auto-wraps in a single-operation transaction.
|
|
371
|
+
*/
|
|
372
|
+
const handleOperation = (op) => {
|
|
373
|
+
if (_inTransaction) {
|
|
374
|
+
_txOps.push(op);
|
|
375
|
+
applyOperation(op);
|
|
376
|
+
} else {
|
|
377
|
+
const baseState = _state;
|
|
378
|
+
try {
|
|
379
|
+
applyOperation(op);
|
|
380
|
+
_pending.push(op);
|
|
381
|
+
} catch (error) {
|
|
382
|
+
_state = baseState;
|
|
383
|
+
throw error;
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
};
|
|
387
|
+
/**
|
|
388
|
+
* Creates a ProxyEnvironment for the document.
|
|
389
|
+
*/
|
|
390
|
+
const createEnv = () => {
|
|
391
|
+
return make$2({
|
|
392
|
+
onOperation: handleOperation,
|
|
393
|
+
getState: getStateAtPath
|
|
394
|
+
});
|
|
395
|
+
};
|
|
396
|
+
const env = createEnv();
|
|
397
|
+
const rootProxy = schema._internal.createProxy(env, make$3(""));
|
|
398
|
+
return {
|
|
399
|
+
schema,
|
|
400
|
+
root: rootProxy,
|
|
401
|
+
get: () => {
|
|
402
|
+
return _state;
|
|
403
|
+
},
|
|
404
|
+
toSnapshot: () => {
|
|
405
|
+
return rootProxy.toSnapshot();
|
|
406
|
+
},
|
|
407
|
+
transaction: (fn) => {
|
|
408
|
+
if (_inTransaction) throw new NestedTransactionError();
|
|
409
|
+
_inTransaction = true;
|
|
410
|
+
_txOps = [];
|
|
411
|
+
_txBaseState = _state;
|
|
412
|
+
try {
|
|
413
|
+
const result = fn(rootProxy);
|
|
414
|
+
_pending.push(..._txOps);
|
|
415
|
+
return result;
|
|
416
|
+
} catch (error) {
|
|
417
|
+
_state = _txBaseState;
|
|
418
|
+
throw error;
|
|
419
|
+
} finally {
|
|
420
|
+
_inTransaction = false;
|
|
421
|
+
_txOps = [];
|
|
422
|
+
_txBaseState = void 0;
|
|
423
|
+
}
|
|
424
|
+
},
|
|
425
|
+
apply: (ops) => {
|
|
426
|
+
for (const op of ops) applyOperation(op);
|
|
427
|
+
},
|
|
428
|
+
flush: () => {
|
|
429
|
+
const tx = make$1(_pending);
|
|
430
|
+
_pending = [];
|
|
431
|
+
return tx;
|
|
432
|
+
}
|
|
433
|
+
};
|
|
434
|
+
};
|
|
435
|
+
|
|
436
|
+
//#endregion
|
|
437
|
+
export { encode as a, Operation_exports as c, isPrefix as d, pathsEqual as f, decode as i, fromDefinition as l, _defineProperty as m, make as n, isEmpty as o, pathsOverlap as p, Transaction_exports as r, ProxyEnvironment_exports as s, Document_exports as t, OperationPath_exports as u };
|
|
438
|
+
//# sourceMappingURL=Document-CwiAFTIq.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Document-CwiAFTIq.mjs","names":["make","tokensInternal: ReadonlyArray<OperationPathToken>","encode","decode","encode","OperationPath.encode","decode","OperationPath.decode","make","options: ProxyEnvironmentOptions","make","Operation.encode","Operation.decode","_state: Primitive.InferState<TSchema> | undefined","_pending: Operation.Operation<any, any, any>[]","_txOps: Operation.Operation<any, any, any>[]","_txBaseState: Primitive.InferState<TSchema> | undefined","current: unknown","ProxyEnvironment.make","OperationPath.make","Transaction.make"],"sources":["../src/OperationPath.ts","../src/Operation.ts","../src/ProxyEnvironment.ts","../src/Transaction.ts","../src/Document.ts"],"sourcesContent":["// export type OperationPath = string\nexport type OperationPathToken = string\n\nexport interface OperationPath {\n readonly _tag: \"OperationPath\"\n readonly toTokens: () => ReadonlyArray<OperationPathToken>\n readonly concat: (other: OperationPath) => OperationPath\n readonly append: (token: OperationPathToken) => OperationPath\n readonly pop: () => OperationPath\n readonly shift: () => OperationPath\n}\n\nconst parseStringPath = (stringPath: string): ReadonlyArray<OperationPathToken> => {\n return stringPath.split(\"/\")\n}\n\nconst makeStringPathFromTokens = (tokens: ReadonlyArray<OperationPathToken>): string => {\n return tokens.join(\"/\")\n}\n\n/**\n * Creates a new operation path.\n * @param stringPath - The string path to create the path from.\n * @returns The new operation path.\n */\nexport function make(stringPath?: string): OperationPath {\n\n const tokensInternal: ReadonlyArray<OperationPathToken> = stringPath ? parseStringPath(stringPath) : []\n\n /**\n * Returns the tokens of the path.\n * @returns The tokens of the path.\n */\n const toTokens = () => {\n return tokensInternal\n }\n\n /**\n * Concatenates two paths.\n * @param other - The other path to concatenate.\n * @returns The new path.\n */\n const concat = (other: OperationPath): OperationPath => {\n return make(makeStringPathFromTokens(toTokens().concat(other.toTokens())))\n }\n\n /**\n * Appends a token to the path.\n * @param token - The token to append.\n * @returns The new path.\n */\n const append = (token: OperationPathToken): OperationPath => {\n return make(makeStringPathFromTokens(toTokens().concat([token])))\n }\n\n /**\n * Removes the last token from the path.\n * @returns The new path.\n */\n const pop = (): OperationPath => {\n return make(makeStringPathFromTokens(toTokens().slice(0, -1)))\n }\n\n /**\n * Removes the first token from the path.\n * @returns The new path.\n */\n const shift = (): OperationPath => {\n return make(makeStringPathFromTokens(toTokens().slice(1)))\n }\n\n return {\n _tag: \"OperationPath\",\n toTokens,\n concat,\n append,\n pop,\n shift\n } as const\n}\n\n/**\n * Creates a new operation path from tokens.\n * @param tokens - The tokens to create the path from.\n * @returns The new operation path.\n */\nexport function fromTokens(tokens: ReadonlyArray<OperationPathToken>): OperationPath {\n return make(makeStringPathFromTokens(tokens))\n}\n\n// =============================================================================\n// Path Utility Functions\n// =============================================================================\n\n/**\n * Checks if two operation paths overlap (one is prefix of the other or equal).\n */\nexport const pathsOverlap = (\n pathA: OperationPath,\n pathB: OperationPath\n): boolean => {\n const tokensA = pathA.toTokens().filter((t) => t !== \"\");\n const tokensB = pathB.toTokens().filter((t) => t !== \"\");\n\n const minLength = Math.min(tokensA.length, tokensB.length);\n\n for (let i = 0; i < minLength; i++) {\n if (tokensA[i] !== tokensB[i]) {\n return false;\n }\n }\n\n return true;\n};\n\n/**\n * Checks if pathA is a prefix of pathB (pathA is ancestor of pathB).\n */\nexport const isPrefix = (\n pathA: OperationPath,\n pathB: OperationPath\n): boolean => {\n const tokensA = pathA.toTokens().filter((t) => t !== \"\");\n const tokensB = pathB.toTokens().filter((t) => t !== \"\");\n\n if (tokensA.length > tokensB.length) {\n return false;\n }\n\n for (let i = 0; i < tokensA.length; i++) {\n if (tokensA[i] !== tokensB[i]) {\n return false;\n }\n }\n\n return true;\n};\n\n/**\n * Checks if two paths are exactly equal.\n */\nexport const pathsEqual = (\n pathA: OperationPath,\n pathB: OperationPath\n): boolean => {\n const tokensA = pathA.toTokens().filter((t) => t !== \"\");\n const tokensB = pathB.toTokens().filter((t) => t !== \"\");\n\n if (tokensA.length !== tokensB.length) {\n return false;\n }\n\n for (let i = 0; i < tokensA.length; i++) {\n if (tokensA[i] !== tokensB[i]) {\n return false;\n }\n }\n\n return true;\n};\n\n/**\n * Gets the relative path of pathB with respect to pathA.\n * Assumes pathA is a prefix of pathB.\n */\nexport const getRelativePath = (\n basePath: OperationPath,\n fullPath: OperationPath\n): string[] => {\n const baseTokens = basePath.toTokens().filter((t) => t !== \"\");\n const fullTokens = fullPath.toTokens().filter((t) => t !== \"\");\n\n return fullTokens.slice(baseTokens.length);\n};\n\n/**\n * Encoded representation of an OperationPath for network transport.\n */\nexport type EncodedOperationPath = string;\n\n/**\n * Encodes an OperationPath to a string for network transport.\n * @param path - The operation path to encode.\n * @returns The encoded string representation.\n */\nexport const encode = (path: OperationPath): EncodedOperationPath => {\n return makeStringPathFromTokens(path.toTokens());\n};\n\n/**\n * Decodes an encoded string back to an OperationPath.\n * @param encoded - The encoded string representation.\n * @returns The decoded OperationPath.\n */\nexport const decode = (encoded: EncodedOperationPath): OperationPath => {\n return make(encoded);\n};","\nimport * as OperationPath from \"./OperationPath\"\nimport * as OperationDefinition from \"./OperationDefinition\"\nimport { Schema } from \"effect\";\n\n\nexport type Operation<TKind, TPayload extends Schema.Schema.Any, TDef extends OperationDefinition.OperationDefinition<TKind, TPayload, any>> = {\n readonly kind: TKind\n readonly path: OperationPath.OperationPath\n readonly payload: Schema.Schema.Type<TPayload>,\n\n} & TDef\n\nexport const fromDefinition = <TKind, TPayload extends Schema.Schema.Any, TDef extends OperationDefinition.OperationDefinition<TKind, TPayload, any>>(operationPath: OperationPath.OperationPath, definition: TDef, payload: Schema.Schema.Type<TPayload>): Operation<TKind, TPayload, TDef> => {\n return {\n kind: definition.kind,\n path: operationPath,\n payload: payload,\n } as Operation<TKind, TPayload, TDef>\n}\n\n/**\n * Encoded representation of an Operation for network transport.\n */\nexport interface EncodedOperation {\n readonly kind: unknown\n readonly path: OperationPath.EncodedOperationPath\n readonly payload: unknown\n}\n\n/**\n * Encodes an Operation to a JSON-serializable format for network transport.\n * @param operation - The operation to encode.\n * @returns The encoded representation.\n */\nexport const encode = <TKind, TPayload extends Schema.Schema.Any, TDef extends OperationDefinition.OperationDefinition<TKind, TPayload, any>>(\n operation: Operation<TKind, TPayload, TDef>\n): EncodedOperation => {\n return {\n kind: operation.kind,\n path: OperationPath.encode(operation.path),\n payload: operation.payload,\n }\n}\n\n/**\n * Decodes an encoded operation back to an Operation.\n * Note: This returns a partial operation without the definition methods.\n * The caller must have the operation definitions to fully reconstruct if needed.\n * @param encoded - The encoded representation.\n * @returns The decoded Operation (without definition-specific methods).\n */\nexport const decode = (encoded: EncodedOperation): Operation<unknown, Schema.Schema.Any, any> => {\n return {\n kind: encoded.kind,\n path: OperationPath.decode(encoded.path),\n payload: encoded.payload,\n } as Operation<unknown, Schema.Schema.Any, any>\n}","import * as Operation from \"./Operation\";\nimport * as OperationPath from \"./OperationPath\";\n\nexport type ProxyEnvironment = {\n /** Adds an operation to be collected/applied */\n readonly addOperation: (operation: Operation.Operation<any, any, any>) => void;\n /** Gets the current state at the given path */\n readonly getState: (path: OperationPath.OperationPath) => unknown;\n /** Generates a unique ID (UUID) for array elements */\n readonly generateId: () => string;\n};\n\nexport interface ProxyEnvironmentOptions {\n /** Callback when an operation is added */\n readonly onOperation: (operation: Operation.Operation<any, any, any>) => void;\n /** Function to retrieve current state at a path (defaults to returning undefined) */\n readonly getState?: (path: OperationPath.OperationPath) => unknown;\n /** Optional: Custom ID generator (defaults to crypto.randomUUID) */\n readonly generateId?: () => string;\n}\n\n/** Default UUID generator using crypto.randomUUID */\nconst defaultGenerateId = (): string => {\n return crypto.randomUUID();\n};\n\n/** Default state getter that always returns undefined */\nconst defaultGetState = (_path: OperationPath.OperationPath): unknown => {\n return undefined;\n};\n\n/**\n * Creates a ProxyEnvironment.\n * @param optionsOrCallback - Either an options object or a simple callback for operations\n */\nexport const make = (\n optionsOrCallback: ProxyEnvironmentOptions | ((operation: Operation.Operation<any, any, any>) => void)\n): ProxyEnvironment => {\n // Support both old callback style and new options object\n const options: ProxyEnvironmentOptions =\n typeof optionsOrCallback === \"function\"\n ? { onOperation: optionsOrCallback }\n : optionsOrCallback;\n\n return {\n addOperation: (operation: Operation.Operation<any, any, any>) => {\n options.onOperation(operation);\n },\n getState: options.getState ?? defaultGetState,\n generateId: options.generateId ?? defaultGenerateId,\n };\n};\n","import * as Operation from \"./Operation\";\n\n/**\n * A Transaction represents a group of operations that were applied atomically.\n */\nexport interface Transaction {\n /** Unique identifier for this transaction */\n readonly id: string;\n /** Operations contained in this transaction */\n readonly ops: ReadonlyArray<Operation.Operation<any, any, any>>;\n /** Timestamp when the transaction was created */\n readonly timestamp: number;\n}\n\n/**\n * Creates a new Transaction with the given operations.\n */\nexport const make = (ops: ReadonlyArray<Operation.Operation<any, any, any>>): Transaction => ({\n id: crypto.randomUUID(),\n ops,\n timestamp: Date.now(),\n});\n\n/**\n * Creates an empty Transaction.\n */\nexport const empty = (): Transaction => make([]);\n\n/**\n * Checks if a transaction is empty (has no operations).\n */\nexport const isEmpty = (tx: Transaction): boolean => tx.ops.length === 0;\n\n/**\n * Merges multiple transactions into one.\n */\nexport const merge = (txs: ReadonlyArray<Transaction>): Transaction => {\n const allOps = txs.flatMap(tx => tx.ops);\n return make(allOps);\n};\n\n\n/**\n * Encoded representation of a Transaction for network transport.\n */\nexport interface EncodedTransaction {\n readonly id: string;\n readonly ops: ReadonlyArray<Operation.EncodedOperation>;\n readonly timestamp: number;\n}\n\n/**\n * Encodes a Transaction to a JSON-serializable format for network transport.\n * @param transaction - The transaction to encode.\n * @returns The encoded representation.\n */\nexport const encode = (transaction: Transaction): EncodedTransaction => ({\n id: transaction.id,\n ops: transaction.ops.map(Operation.encode),\n timestamp: transaction.timestamp,\n});\n\n/**\n * Decodes an encoded transaction back to a Transaction.\n * @param encoded - The encoded representation.\n * @returns The decoded Transaction.\n */\nexport const decode = (encoded: EncodedTransaction): Transaction => ({\n id: encoded.id,\n ops: encoded.ops.map(Operation.decode),\n timestamp: encoded.timestamp,\n});\n","import * as Operation from \"./Operation\";\nimport * as OperationPath from \"./OperationPath\";\nimport * as ProxyEnvironment from \"./ProxyEnvironment\";\nimport * as Transaction from \"./Transaction\";\nimport type * as Primitive from \"./Primitive\";\n\n// =============================================================================\n// Document Errors\n// =============================================================================\n\n/**\n * Error thrown when attempting to start a nested transaction.\n */\nexport class NestedTransactionError extends Error {\n readonly _tag = \"NestedTransactionError\";\n constructor() {\n super(\"Nested transactions are not supported\");\n this.name = \"NestedTransactionError\";\n }\n}\n\n/**\n * Error thrown when an operation fails to apply.\n */\nexport class OperationError extends Error {\n readonly _tag = \"OperationError\";\n constructor(message: string) {\n super(message);\n this.name = \"OperationError\";\n }\n}\n\n// =============================================================================\n// Document Interface\n// =============================================================================\n\n/**\n * A Document manages state for a primitive-based schema with transaction support.\n */\nexport interface Document<TSchema extends Primitive.AnyPrimitive> {\n /** The schema defining this document's structure */\n readonly schema: TSchema;\n \n /** Root proxy for accessing and modifying document data */\n readonly root: Primitive.InferProxy<TSchema>;\n \n /** Returns the current document state */\n get(): Primitive.InferState<TSchema> | undefined;\n \n /**\n * Returns a readonly snapshot of the entire document state for rendering.\n * The snapshot is a type-safe, readonly structure where:\n * - Required fields and fields with defaults are guaranteed to be defined\n * - Optional fields may be undefined\n */\n toSnapshot(): Primitive.InferSnapshot<TSchema>;\n \n /**\n * Runs a function within a transaction.\n * All operations are collected and applied atomically.\n * If the function throws, all changes are rolled back.\n * @returns The return value of the function\n */\n transaction<R>(fn: (root: Primitive.InferProxy<TSchema>) => R): R;\n \n /**\n * Applies external operations (e.g., from server/peers) to the document.\n * These operations are NOT added to pending operations.\n */\n apply(ops: ReadonlyArray<Operation.Operation<any, any, any>>): void;\n \n /**\n * Returns pending local operations as a Transaction and clears the buffer.\n */\n flush(): Transaction.Transaction;\n}\n\n// =============================================================================\n// Document Options\n// =============================================================================\n\nexport interface DocumentOptions<TSchema extends Primitive.AnyPrimitive> {\n /** Initial state for the document */\n readonly initial?: Primitive.InferState<TSchema>;\n}\n\n// =============================================================================\n// Document Implementation\n// =============================================================================\n\n/**\n * Creates a new Document for the given schema.\n */\nexport const make = <TSchema extends Primitive.AnyPrimitive>(\n schema: TSchema,\n options?: DocumentOptions<TSchema>\n): Document<TSchema> => {\n // Internal state\n let _state: Primitive.InferState<TSchema> | undefined = \n options?.initial ?? schema._internal.getInitialState();\n \n // Pending operations buffer (local changes not yet flushed)\n let _pending: Operation.Operation<any, any, any>[] = [];\n \n // Transaction state\n let _inTransaction = false;\n let _txOps: Operation.Operation<any, any, any>[] = [];\n let _txBaseState: Primitive.InferState<TSchema> | undefined = undefined;\n\n /**\n * Gets state at the given path.\n */\n const getStateAtPath = (path: OperationPath.OperationPath): unknown => {\n const tokens = path.toTokens().filter(t => t !== \"\");\n \n if (tokens.length === 0) {\n return _state;\n }\n \n let current: unknown = _state;\n for (const token of tokens) {\n if (current === null || current === undefined) {\n return undefined;\n }\n \n if (typeof current === \"object\") {\n // Handle array entries (which have { id, pos, value } structure)\n if (Array.isArray(current)) {\n // Try to find by ID in array entries\n const entry = current.find((e: any) => e.id === token);\n if (entry) {\n current = entry.value;\n continue;\n }\n }\n \n // Handle regular object property access\n current = (current as Record<string, unknown>)[token];\n } else {\n return undefined;\n }\n }\n \n return current;\n };\n\n /**\n * Applies a single operation to the current state.\n */\n const applyOperation = (op: Operation.Operation<any, any, any>): void => {\n try {\n _state = schema._internal.applyOperation(_state, op);\n } catch (error) {\n if (error instanceof Error) {\n throw new OperationError(error.message);\n }\n throw new OperationError(String(error));\n }\n };\n\n /**\n * Handles an operation from a proxy.\n * In transaction mode: collects operations, applies to state immediately for subsequent reads.\n * Outside transaction mode: auto-wraps in a single-operation transaction.\n */\n const handleOperation = (op: Operation.Operation<any, any, any>): void => {\n if (_inTransaction) {\n // In transaction: collect op and apply immediately for subsequent reads\n _txOps.push(op);\n applyOperation(op);\n } else {\n // Not in transaction: auto-wrap in single-operation transaction\n const baseState = _state;\n try {\n applyOperation(op);\n _pending.push(op);\n } catch (error) {\n // Rollback on error\n _state = baseState;\n throw error;\n }\n }\n };\n\n /**\n * Creates a ProxyEnvironment for the document.\n */\n const createEnv = (): ProxyEnvironment.ProxyEnvironment => {\n return ProxyEnvironment.make({\n onOperation: handleOperation,\n getState: getStateAtPath,\n });\n };\n\n // Create the root proxy\n const env = createEnv();\n const rootProxy = schema._internal.createProxy(env, OperationPath.make(\"\")) as Primitive.InferProxy<TSchema>;\n\n // Document implementation\n const document: Document<TSchema> = {\n schema,\n root: rootProxy,\n \n get: (): Primitive.InferState<TSchema> | undefined => {\n return _state;\n },\n \n toSnapshot: (): Primitive.InferSnapshot<TSchema> => {\n return (rootProxy as { toSnapshot(): Primitive.InferSnapshot<TSchema> }).toSnapshot();\n },\n \n transaction: <R,>(fn: (root: Primitive.InferProxy<TSchema>) => R): R => {\n if (_inTransaction) {\n throw new NestedTransactionError();\n }\n \n // Start transaction\n _inTransaction = true;\n _txOps = [];\n _txBaseState = _state;\n \n try {\n // Execute the transaction function\n const result = fn(rootProxy);\n \n // Commit: add transaction ops to pending\n _pending.push(..._txOps);\n \n return result;\n } catch (error) {\n // Rollback: restore base state\n _state = _txBaseState;\n throw error;\n } finally {\n // Clean up transaction state\n _inTransaction = false;\n _txOps = [];\n _txBaseState = undefined;\n }\n },\n \n apply: (ops: ReadonlyArray<Operation.Operation<any, any, any>>): void => {\n for (const op of ops) {\n applyOperation(op);\n }\n },\n \n flush: (): Transaction.Transaction => {\n const tx = Transaction.make(_pending);\n _pending = [];\n return tx;\n },\n };\n\n return document;\n};\n"],"mappings":"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"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import * as Schema from "effect/Schema";
|
|
2
|
+
|
|
3
|
+
//#region src/Presence.d.ts
|
|
4
|
+
declare namespace Presence_d_exports {
|
|
5
|
+
export { AnyPresence, Infer, Presence, PresenceEntry, PresenceOptions, isValid, make, validate, validateSafe };
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* A Presence schema wrapper that holds an Effect Schema for validation.
|
|
9
|
+
* This is used by both client and server to validate presence data.
|
|
10
|
+
*/
|
|
11
|
+
interface Presence<TData> {
|
|
12
|
+
readonly _tag: "Presence";
|
|
13
|
+
/** The Effect Schema used for validation */
|
|
14
|
+
readonly schema: Schema.Schema<TData>;
|
|
15
|
+
/** Branded type marker for inference */
|
|
16
|
+
readonly _Data: TData;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Options for creating a Presence instance.
|
|
20
|
+
*/
|
|
21
|
+
interface PresenceOptions<TData> {
|
|
22
|
+
/** The Effect Schema defining the presence data structure */
|
|
23
|
+
readonly schema: Schema.Schema<TData>;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Infer the data type from a Presence instance.
|
|
27
|
+
*/
|
|
28
|
+
type Infer<P extends Presence<any>> = P["_Data"];
|
|
29
|
+
/**
|
|
30
|
+
* Any Presence type (for generic constraints).
|
|
31
|
+
*/
|
|
32
|
+
type AnyPresence = Presence<any>;
|
|
33
|
+
/**
|
|
34
|
+
* A presence entry as stored/transmitted.
|
|
35
|
+
*/
|
|
36
|
+
interface PresenceEntry<TData = unknown> {
|
|
37
|
+
/** The presence data */
|
|
38
|
+
readonly data: TData;
|
|
39
|
+
/** Optional user ID from authentication */
|
|
40
|
+
readonly userId?: string;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Creates a new Presence schema wrapper.
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* ```typescript
|
|
47
|
+
* import { Presence } from "@voidhash/mimic";
|
|
48
|
+
* import { Schema } from "effect";
|
|
49
|
+
*
|
|
50
|
+
* const CursorPresence = Presence.make({
|
|
51
|
+
* schema: Schema.Struct({
|
|
52
|
+
* name: Schema.String,
|
|
53
|
+
* cursor: Schema.Struct({
|
|
54
|
+
* x: Schema.Number,
|
|
55
|
+
* y: Schema.Number,
|
|
56
|
+
* }),
|
|
57
|
+
* }),
|
|
58
|
+
* });
|
|
59
|
+
* ```
|
|
60
|
+
*/
|
|
61
|
+
declare const make: <TData>(options: PresenceOptions<TData>) => Presence<TData>;
|
|
62
|
+
/**
|
|
63
|
+
* Validates unknown data against a Presence schema.
|
|
64
|
+
* Throws a ParseError if validation fails.
|
|
65
|
+
*
|
|
66
|
+
* @param presence - The Presence instance with the schema
|
|
67
|
+
* @param data - Unknown data to validate
|
|
68
|
+
* @returns The validated and typed data
|
|
69
|
+
* @throws ParseError if validation fails
|
|
70
|
+
*/
|
|
71
|
+
declare const validate: <TData>(presence: Presence<TData>, data: unknown) => TData;
|
|
72
|
+
/**
|
|
73
|
+
* Safely validates unknown data against a Presence schema.
|
|
74
|
+
* Returns undefined if validation fails instead of throwing.
|
|
75
|
+
*
|
|
76
|
+
* @param presence - The Presence instance with the schema
|
|
77
|
+
* @param data - Unknown data to validate
|
|
78
|
+
* @returns The validated data or undefined if invalid
|
|
79
|
+
*/
|
|
80
|
+
declare const validateSafe: <TData>(presence: Presence<TData>, data: unknown) => TData | undefined;
|
|
81
|
+
/**
|
|
82
|
+
* Checks if unknown data is valid according to a Presence schema.
|
|
83
|
+
*
|
|
84
|
+
* @param presence - The Presence instance with the schema
|
|
85
|
+
* @param data - Unknown data to check
|
|
86
|
+
* @returns true if valid, false otherwise
|
|
87
|
+
*/
|
|
88
|
+
declare const isValid: <TData>(presence: Presence<TData>, data: unknown) => data is TData;
|
|
89
|
+
//#endregion
|
|
90
|
+
export { Presence_d_exports as i, Infer as n, PresenceEntry as r, AnyPresence as t };
|
|
91
|
+
//# sourceMappingURL=Presence-DKKP4v5X.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Presence-DKKP4v5X.d.cts","names":[],"sources":["../src/Presence.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;UAeiB;;;mBAGE,MAAA,CAAO,OAAO;;EAHhB,SAAA,KAAQ,EAKP,KALO;;;;;AAWR,UAAA,eAAe,CAAA,KAAA,CAEC,CAAA;EAMrB;EAKA,SAAA,MAAW,EAXJ,MAAA,CAAO,MAWA,CAXO,KAWC,CAAA;AASlC;AA8BA;;;AAAwE,KA5C5D,KA4C4D,CAAA,UA5C5C,QA4C4C,CAAA,GAAA,CAAA,CAAA,GA5C3B,CA4C2B,CAAA,OAAA,CAAA;;;AAmBxE;AACqB,KA3DT,WAAA,GAAc,QA2DL,CAAA,GAAA,CAAA;;;;AAcR,UAhEI,aAyEhB,CAAA,QAAA,OAAA,CAAA,CAAA;EARoB;EAAT,SAAA,IAAA,EA/DK,KA+DL;EAET;EAAK,SAAA,MAAA,CAAA,EAAA,MAAA;AAeR;;;;;;;;;;;;;;;;;;;;cApDa,uBAAyB,gBAAgB,WAAS,SAAS;;;;;;;;;;cAmB3D,4BACD,SAAS,0BAElB;;;;;;;;;cAYU,gCACD,SAAS,0BAElB;;;;;;;;cAeU,2BACD,SAAS,kCAEV"}
|