@evolu/common 8.10.0 → 8.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/Bytes.d.ts +39 -2
- package/dist/src/Bytes.d.ts.map +1 -1
- package/dist/src/Bytes.js +50 -2
- package/dist/src/Config.d.ts +22 -22
- package/dist/src/Config.d.ts.map +1 -1
- package/dist/src/Console.d.ts +62 -7
- package/dist/src/Console.d.ts.map +1 -1
- package/dist/src/Console.js +20 -4
- package/dist/src/Crypto.d.ts +76 -4
- package/dist/src/Crypto.d.ts.map +1 -1
- package/dist/src/Crypto.js +55 -4
- package/dist/src/Error.d.ts +45 -0
- package/dist/src/Error.d.ts.map +1 -1
- package/dist/src/Error.js +69 -0
- package/dist/src/Fs.d.ts +92 -18
- package/dist/src/Fs.d.ts.map +1 -1
- package/dist/src/Fs.js +2 -0
- package/dist/src/Identicon.d.ts +2 -2
- package/dist/src/Identicon.js +2 -2
- package/dist/src/LeakDetector.d.ts +22 -3
- package/dist/src/LeakDetector.d.ts.map +1 -1
- package/dist/src/LeakDetector.js +12 -2
- package/dist/src/LockManager.d.ts +8 -0
- package/dist/src/LockManager.d.ts.map +1 -1
- package/dist/src/LockManager.js +6 -0
- package/dist/src/Object.d.ts.map +1 -1
- package/dist/src/Object.js +5 -0
- package/dist/src/Platform.d.ts +47 -7
- package/dist/src/Platform.d.ts.map +1 -1
- package/dist/src/Platform.js +24 -5
- package/dist/src/Random.d.ts +25 -2
- package/dist/src/Random.d.ts.map +1 -1
- package/dist/src/Random.js +14 -2
- package/dist/src/Resource.d.ts +156 -1
- package/dist/src/Resource.d.ts.map +1 -1
- package/dist/src/Resource.js +201 -72
- package/dist/src/Schedule.d.ts +11 -10
- package/dist/src/Schedule.d.ts.map +1 -1
- package/dist/src/Schedule.js +1 -1
- package/dist/src/Sqlite.d.ts +132 -16
- package/dist/src/Sqlite.d.ts.map +1 -1
- package/dist/src/Sqlite.js +63 -9
- package/dist/src/Task.d.ts +15 -4
- package/dist/src/Task.d.ts.map +1 -1
- package/dist/src/Task.js +41 -15
- package/dist/src/Test.d.ts +9 -0
- package/dist/src/Test.d.ts.map +1 -1
- package/dist/src/Test.js +4 -0
- package/dist/src/Time.d.ts +106 -9
- package/dist/src/Time.d.ts.map +1 -1
- package/dist/src/Time.js +55 -4
- package/dist/src/Type.d.ts +1455 -1310
- package/dist/src/Type.d.ts.map +1 -1
- package/dist/src/Type.js +1274 -517
- package/dist/src/WebSocket.d.ts +164 -13
- package/dist/src/WebSocket.d.ts.map +1 -1
- package/dist/src/WebSocket.js +133 -24
- package/dist/src/Worker.d.ts +90 -8
- package/dist/src/Worker.d.ts.map +1 -1
- package/dist/src/Worker.js +28 -2
- package/dist/src/index.d.ts +6 -7
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +2 -3
- package/dist/src/local-first/Db.d.ts +52 -3
- package/dist/src/local-first/Db.d.ts.map +1 -1
- package/dist/src/local-first/Db.js +412 -137
- package/dist/src/local-first/Evolu.d.ts +412 -213
- package/dist/src/local-first/Evolu.d.ts.map +1 -1
- package/dist/src/local-first/Evolu.js +181 -18
- package/dist/src/local-first/Owner.d.ts +13 -30
- package/dist/src/local-first/Owner.d.ts.map +1 -1
- package/dist/src/local-first/Owner.js +13 -30
- package/dist/src/local-first/Protocol.d.ts +106 -19
- package/dist/src/local-first/Protocol.d.ts.map +1 -1
- package/dist/src/local-first/Protocol.js +162 -60
- package/dist/src/local-first/Query.d.ts +8 -15
- package/dist/src/local-first/Query.d.ts.map +1 -1
- package/dist/src/local-first/Relay.d.ts.map +1 -1
- package/dist/src/local-first/Relay.js +4 -2
- package/dist/src/local-first/Schema.d.ts +346 -23
- package/dist/src/local-first/Schema.d.ts.map +1 -1
- package/dist/src/local-first/Schema.js +214 -17
- package/dist/src/local-first/Shared.d.ts +537 -22
- package/dist/src/local-first/Shared.d.ts.map +1 -1
- package/dist/src/local-first/Shared.js +1437 -234
- package/dist/src/local-first/Storage.d.ts +195 -17
- package/dist/src/local-first/Storage.d.ts.map +1 -1
- package/dist/src/local-first/Storage.js +85 -22
- package/dist/src/local-first/Timestamp.d.ts +392 -41
- package/dist/src/local-first/Timestamp.d.ts.map +1 -1
- package/dist/src/local-first/Timestamp.js +403 -81
- package/dist/src/local-first/index.d.ts +0 -1
- package/dist/src/local-first/index.d.ts.map +1 -1
- package/dist/src/local-first/index.js +0 -1
- package/package.json +1 -1
- package/src/Assert.test.ts +2 -5
- package/src/Bytes.test.ts +27 -0
- package/src/Bytes.ts +58 -2
- package/src/Config.test.ts +2 -6
- package/src/Config.ts +133 -133
- package/src/Console.ts +62 -7
- package/src/Crypto.ts +76 -4
- package/src/Eq.test.ts +2 -3
- package/src/Error.test.ts +76 -3
- package/src/Error.ts +71 -0
- package/src/Fs.ts +92 -18
- package/src/Identicon.ts +2 -2
- package/src/LeakDetector.ts +22 -3
- package/src/LockManager.ts +8 -0
- package/src/Object.test.ts +27 -12
- package/src/Object.ts +5 -0
- package/src/Platform.ts +50 -8
- package/src/Random.ts +25 -2
- package/src/Resource.test.ts +837 -0
- package/src/Resource.ts +235 -15
- package/src/Schedule.test.ts +50 -12
- package/src/Schedule.ts +24 -14
- package/src/Sqlite.ts +137 -17
- package/src/Task.test.ts +189 -8
- package/src/Task.ts +56 -17
- package/src/Test.ts +9 -0
- package/src/Time.ts +106 -9
- package/src/Type.test.ts +946 -1028
- package/src/Type.ts +4195 -3136
- package/src/Types.test.ts +4 -14
- package/src/WebSocket.ts +313 -40
- package/src/Worker.ts +90 -8
- package/src/index.ts +20 -6
- package/src/local-first/Db.ts +644 -339
- package/src/local-first/Evolu.test.ts +994 -22
- package/src/local-first/Evolu.ts +625 -232
- package/src/local-first/Owner.ts +13 -30
- package/src/local-first/Protocol.test.ts +634 -10
- package/src/local-first/Protocol.ts +255 -109
- package/src/local-first/Query.ts +8 -15
- package/src/local-first/Relay.ts +4 -2
- package/src/local-first/Schema.test.ts +143 -0
- package/src/local-first/Schema.ts +376 -26
- package/src/local-first/Shared.test.ts +7731 -559
- package/src/local-first/Shared.ts +2036 -267
- package/src/local-first/Storage.ts +224 -36
- package/src/local-first/Timestamp.test.ts +344 -70
- package/src/local-first/Timestamp.ts +434 -118
- package/src/local-first/index.ts +0 -1
- package/dist/src/local-first/Error.d.ts +0 -12
- package/dist/src/local-first/Error.d.ts.map +0 -1
- package/dist/src/local-first/Error.js +0 -6
- package/dist/src/local-first/LocalAuth.d.ts +0 -150
- package/dist/src/local-first/LocalAuth.d.ts.map +0 -1
- package/dist/src/local-first/LocalAuth.js +0 -179
- package/src/local-first/Error.ts +0 -17
- package/src/local-first/LocalAuth.ts +0 -457
package/src/LockManager.ts
CHANGED
|
@@ -47,6 +47,8 @@ import type { Callback } from "./Types.ts";
|
|
|
47
47
|
* );
|
|
48
48
|
* assertEqual(result, "example");
|
|
49
49
|
* ```
|
|
50
|
+
*
|
|
51
|
+
* @group Core
|
|
50
52
|
*/
|
|
51
53
|
|
|
52
54
|
export interface LockManagerDep {
|
|
@@ -65,6 +67,8 @@ export interface LockManagerDep {
|
|
|
65
67
|
* via internal namespacing, so tests can reuse the same lock names without
|
|
66
68
|
* contending through the global Web Locks. Query results are filtered to that
|
|
67
69
|
* private namespace and returned with the original visible names.
|
|
70
|
+
*
|
|
71
|
+
* @group Testing
|
|
68
72
|
*/
|
|
69
73
|
export const testCreateLockManager = (
|
|
70
74
|
nativeLockManager: LockManager = navigator.locks,
|
|
@@ -119,6 +123,8 @@ export const testCreateLockManager = (
|
|
|
119
123
|
* Leadership is held until the returned handle is disposed. Once released,
|
|
120
124
|
* another waiting caller may become the next leader. Waiting for leadership is
|
|
121
125
|
* abortable via the calling {@link Task}'s signal.
|
|
126
|
+
*
|
|
127
|
+
* @group Leader election
|
|
122
128
|
*/
|
|
123
129
|
export const acquireLeaderLock =
|
|
124
130
|
(name: string): Task<AsyncDisposable, never, LockManagerDep> =>
|
|
@@ -156,6 +162,8 @@ export const acquireLeaderLock =
|
|
|
156
162
|
* Leadership is held until the returned handle is disposed. Once released,
|
|
157
163
|
* another waiting caller may become the next leader. Waiting for leadership is
|
|
158
164
|
* abortable by disposing the returned handle.
|
|
165
|
+
*
|
|
166
|
+
* @group Leader election
|
|
159
167
|
*/
|
|
160
168
|
export const acquireLeaderLockCallback =
|
|
161
169
|
(deps: LockManagerDep) =>
|
package/src/Object.test.ts
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import nodeAssert from "node:assert/strict";
|
|
2
2
|
import { describe, it, test } from "node:test";
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
assertEqual,
|
|
5
|
+
assertFalse,
|
|
6
|
+
assertNonNullable,
|
|
7
|
+
assertSame,
|
|
8
|
+
assertTrue,
|
|
9
|
+
} from "./Assert.ts";
|
|
4
10
|
|
|
5
11
|
import type { Brand } from "./Brand.ts";
|
|
6
12
|
import type { ReadonlyRecord } from "./Object.ts";
|
|
@@ -105,6 +111,22 @@ test("isPlainObject", () => {
|
|
|
105
111
|
assertFalse(isPlainObject(Object.create(partialObjectPrototype)));
|
|
106
112
|
});
|
|
107
113
|
|
|
114
|
+
test("isPlainObject checks the root markers of Object.prototype", () => {
|
|
115
|
+
for (const key of ["hasOwnProperty", "isPrototypeOf"]) {
|
|
116
|
+
const descriptor = Object.getOwnPropertyDescriptor(Object.prototype, key);
|
|
117
|
+
assertNonNullable(descriptor);
|
|
118
|
+
Reflect.deleteProperty(Object.prototype, key);
|
|
119
|
+
try {
|
|
120
|
+
assertFalse(isPlainObject({}));
|
|
121
|
+
assertTrue(isPlainObject(Object.create(null)));
|
|
122
|
+
} finally {
|
|
123
|
+
// oxlint-disable-next-line eslint/no-extend-native -- Restores the built-in property this test deleted.
|
|
124
|
+
Object.defineProperty(Object.prototype, key, descriptor);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
assertTrue(isPlainObject({}));
|
|
128
|
+
});
|
|
129
|
+
|
|
108
130
|
test("isFunction", () => {
|
|
109
131
|
assertTrue(isFunction(() => {}));
|
|
110
132
|
assertTrue(isFunction(function () {}));
|
|
@@ -244,13 +266,12 @@ describe("filterObjectKeys", () => {
|
|
|
244
266
|
>();
|
|
245
267
|
assertEqual(selectedUsers, { u1: 1 });
|
|
246
268
|
|
|
247
|
-
|
|
269
|
+
void (() => {
|
|
248
270
|
// @ts-expect-error filterObjectKeys requires an object source.
|
|
249
271
|
filterObjectKeys("text", () => true);
|
|
250
272
|
// @ts-expect-error Selected properties are readonly.
|
|
251
273
|
selected.APP_PORT = "5000";
|
|
252
|
-
};
|
|
253
|
-
assertType<typeof reject, () => void>();
|
|
274
|
+
});
|
|
254
275
|
});
|
|
255
276
|
|
|
256
277
|
it("preserves descriptors without reading getters", () => {
|
|
@@ -360,16 +381,10 @@ test("createMutableRecord", () => {
|
|
|
360
381
|
assertEqual(source, { name: "Ada" });
|
|
361
382
|
assertSame(Object.getPrototypeOf(copy), null);
|
|
362
383
|
|
|
363
|
-
|
|
384
|
+
void (() => {
|
|
364
385
|
// @ts-expect-error createMutableRecord source must be an object.
|
|
365
386
|
createMutableRecord("Ada");
|
|
366
|
-
};
|
|
367
|
-
assertType<
|
|
368
|
-
typeof compileTimeAssertions extends (...args: Array<never>) => unknown
|
|
369
|
-
? true
|
|
370
|
-
: false,
|
|
371
|
-
true
|
|
372
|
-
>();
|
|
387
|
+
});
|
|
373
388
|
});
|
|
374
389
|
|
|
375
390
|
test("emptyRecord", () => {
|
package/src/Object.ts
CHANGED
|
@@ -87,6 +87,11 @@ export const isPlainObject = (
|
|
|
87
87
|
|
|
88
88
|
const prototype = Object.getPrototypeOf(value) as object | null;
|
|
89
89
|
if (prototype === null) return true;
|
|
90
|
+
// This realm's Object.prototype has an immutable null prototype, so `in`
|
|
91
|
+
// checks the same own properties as the structural test below, faster.
|
|
92
|
+
if (prototype === Object.prototype) {
|
|
93
|
+
return "hasOwnProperty" in prototype && "isPrototypeOf" in prototype;
|
|
94
|
+
}
|
|
90
95
|
return (
|
|
91
96
|
Object.getPrototypeOf(prototype) === null &&
|
|
92
97
|
Object.hasOwn(prototype, "hasOwnProperty") &&
|
package/src/Platform.ts
CHANGED
|
@@ -4,10 +4,18 @@
|
|
|
4
4
|
* @module
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
/**
|
|
7
|
+
/**
|
|
8
|
+
* Returns true if running in React Native with Hermes engine.
|
|
9
|
+
*
|
|
10
|
+
* @group Detection
|
|
11
|
+
*/
|
|
8
12
|
export const isHermes = "HermesInternal" in globalThis;
|
|
9
13
|
|
|
10
|
-
/**
|
|
14
|
+
/**
|
|
15
|
+
* Returns true if running in a server environment (no DOM).
|
|
16
|
+
*
|
|
17
|
+
* @group Detection
|
|
18
|
+
*/
|
|
11
19
|
export const isServer = typeof document === "undefined";
|
|
12
20
|
|
|
13
21
|
/**
|
|
@@ -20,6 +28,8 @@ export const isServer = typeof document === "undefined";
|
|
|
20
28
|
* where no bundler ran, such as un-bundled browser ESM, where it fails closed
|
|
21
29
|
* to production behavior. Node.js reads it natively; React Native polyfills it.
|
|
22
30
|
* A missing `NODE_ENV` counts as development, matching React semantics.
|
|
31
|
+
*
|
|
32
|
+
* @group Detection
|
|
23
33
|
*/
|
|
24
34
|
export const isDev =
|
|
25
35
|
typeof process === "undefined"
|
|
@@ -35,6 +45,7 @@ export const isDev =
|
|
|
35
45
|
* Returns false in React Native even if Buffer is polyfilled, as we prefer
|
|
36
46
|
* native methods in that environment.
|
|
37
47
|
*
|
|
48
|
+
* @group Detection
|
|
38
49
|
* @see https://github.com/craftzdog/react-native-quick-base64#installation
|
|
39
50
|
*/
|
|
40
51
|
export const hasNodeBuffer =
|
|
@@ -49,9 +60,16 @@ export const hasNodeBuffer =
|
|
|
49
60
|
* if an onComplete callback is used.
|
|
50
61
|
*
|
|
51
62
|
* https://react.dev/reference/react-dom/flushSync
|
|
63
|
+
*
|
|
64
|
+
* @group Integration
|
|
52
65
|
*/
|
|
53
66
|
export type FlushSync = (callback: () => void) => void;
|
|
54
67
|
|
|
68
|
+
/**
|
|
69
|
+
* Dependency wrapper for {@link FlushSync}.
|
|
70
|
+
*
|
|
71
|
+
* @group Integration
|
|
72
|
+
*/
|
|
55
73
|
export interface FlushSyncDep {
|
|
56
74
|
readonly flushSync: FlushSync;
|
|
57
75
|
}
|
|
@@ -59,18 +77,32 @@ export interface FlushSyncDep {
|
|
|
59
77
|
/**
|
|
60
78
|
* Reload the app in a platform-specific way.
|
|
61
79
|
*
|
|
62
|
-
*
|
|
63
|
-
* the
|
|
80
|
+
* On the web, Evolu reloads tabs of a build when another build of the app waits
|
|
81
|
+
* for the local databases, so they load the build the server now serves. It can
|
|
82
|
+
* also clear in-memory state after persistent storage was purged; it does not
|
|
83
|
+
* purge storage itself.
|
|
64
84
|
*
|
|
65
|
-
* - Web:
|
|
85
|
+
* - Web: Reloads the page, or loads the specified URL instead
|
|
66
86
|
* - React Native: Restarts the app (URL ignored)
|
|
87
|
+
*
|
|
88
|
+
* @group Integration
|
|
67
89
|
*/
|
|
68
90
|
export type ReloadApp = (url?: string) => void;
|
|
69
91
|
|
|
92
|
+
/**
|
|
93
|
+
* Dependency wrapper for {@link ReloadApp}.
|
|
94
|
+
*
|
|
95
|
+
* @group Integration
|
|
96
|
+
*/
|
|
70
97
|
export interface ReloadAppDep {
|
|
71
98
|
readonly reloadApp: ReloadApp;
|
|
72
99
|
}
|
|
73
100
|
|
|
101
|
+
/**
|
|
102
|
+
* Records platform global errors until disposed.
|
|
103
|
+
*
|
|
104
|
+
* @group Testing
|
|
105
|
+
*/
|
|
74
106
|
export interface TestGlobalErrors extends Disposable {
|
|
75
107
|
readonly errors: ReadonlyArray<unknown>;
|
|
76
108
|
readonly next: () => Promise<unknown>;
|
|
@@ -88,15 +120,25 @@ export interface TestGlobalErrors extends Disposable {
|
|
|
88
120
|
readonly settle: () => Promise<ReadonlyArray<unknown>>;
|
|
89
121
|
}
|
|
90
122
|
|
|
91
|
-
/**
|
|
123
|
+
/**
|
|
124
|
+
* Records platform global uncaught-error reporting until disposed.
|
|
125
|
+
*
|
|
126
|
+
* @group Testing
|
|
127
|
+
*/
|
|
92
128
|
export const testGlobalUncaughtErrors = (): TestGlobalErrors =>
|
|
93
129
|
createTestGlobalErrors("uncaughtErrors");
|
|
94
130
|
|
|
95
|
-
/**
|
|
131
|
+
/**
|
|
132
|
+
* Records platform global unhandled-rejection reporting until disposed.
|
|
133
|
+
*
|
|
134
|
+
* @group Testing
|
|
135
|
+
*/
|
|
96
136
|
export const testGlobalUnhandledRejections = (): TestGlobalErrors =>
|
|
97
137
|
createTestGlobalErrors("unhandledRejection");
|
|
98
138
|
|
|
99
|
-
const settleSentinel = new Error(
|
|
139
|
+
const settleSentinel = /*#__PURE__*/ new Error(
|
|
140
|
+
"TestGlobalErrors.settle sentinel",
|
|
141
|
+
);
|
|
100
142
|
|
|
101
143
|
const createTestGlobalErrors = (
|
|
102
144
|
kind: "uncaughtErrors" | "unhandledRejection",
|
package/src/Random.ts
CHANGED
|
@@ -11,6 +11,8 @@ import type { Brand } from "./Brand.ts";
|
|
|
11
11
|
* A random floating point number in [0, 1).
|
|
12
12
|
*
|
|
13
13
|
* Branded to distinguish random values from arbitrary numbers.
|
|
14
|
+
*
|
|
15
|
+
* @group Core
|
|
14
16
|
*/
|
|
15
17
|
export type RandomNumber = number & Brand<"RandomNumber">;
|
|
16
18
|
|
|
@@ -43,17 +45,28 @@ export type RandomNumber = number & Brand<"RandomNumber">;
|
|
|
43
45
|
* const secondTestRandom = testCreateRandom("test");
|
|
44
46
|
* assertEqual(firstTestRandom.next(), secondTestRandom.next());
|
|
45
47
|
* ```
|
|
48
|
+
*
|
|
49
|
+
* @group Core
|
|
46
50
|
*/
|
|
47
51
|
export interface Random {
|
|
48
52
|
/** Returns a floating point number in [0, 1). Just like Math.random(). */
|
|
49
53
|
readonly next: () => RandomNumber;
|
|
50
54
|
}
|
|
51
55
|
|
|
56
|
+
/**
|
|
57
|
+
* Dependency wrapper for {@link Random}.
|
|
58
|
+
*
|
|
59
|
+
* @group Core
|
|
60
|
+
*/
|
|
52
61
|
export interface RandomDep {
|
|
53
62
|
readonly random: Random;
|
|
54
63
|
}
|
|
55
64
|
|
|
56
|
-
/**
|
|
65
|
+
/**
|
|
66
|
+
* Creates a {@link Random} using Math.random().
|
|
67
|
+
*
|
|
68
|
+
* @group Core
|
|
69
|
+
*/
|
|
57
70
|
export const createRandom = (): Random => ({
|
|
58
71
|
next: () => Math.random() as RandomNumber,
|
|
59
72
|
});
|
|
@@ -62,6 +75,8 @@ export const createRandom = (): Random => ({
|
|
|
62
75
|
* Creates a seeded {@link Random} for deterministic tests.
|
|
63
76
|
*
|
|
64
77
|
* Default seed "evolu".
|
|
78
|
+
*
|
|
79
|
+
* @group Testing
|
|
65
80
|
*/
|
|
66
81
|
export const testCreateRandom = (seed = "evolu"): Random => {
|
|
67
82
|
const random = new RandomLib(seed);
|
|
@@ -75,12 +90,18 @@ export const testCreateRandom = (seed = "evolu"): Random => {
|
|
|
75
90
|
* provided by the NPM `random` package.
|
|
76
91
|
*
|
|
77
92
|
* https://github.com/transitive-bullshit/random
|
|
93
|
+
*
|
|
94
|
+
* @group Core
|
|
78
95
|
*/
|
|
79
96
|
export interface RandomLibDep {
|
|
80
97
|
readonly randomLib: RandomLib;
|
|
81
98
|
}
|
|
82
99
|
|
|
83
|
-
/**
|
|
100
|
+
/**
|
|
101
|
+
* Creates a random number generator from the NPM `random` package.
|
|
102
|
+
*
|
|
103
|
+
* @group Core
|
|
104
|
+
*/
|
|
84
105
|
export const createRandomLib = (): RandomLib => new RandomLib();
|
|
85
106
|
|
|
86
107
|
/**
|
|
@@ -88,6 +109,8 @@ export const createRandomLib = (): RandomLib => new RandomLib();
|
|
|
88
109
|
* deterministic tests.
|
|
89
110
|
*
|
|
90
111
|
* Default seed "evolu".
|
|
112
|
+
*
|
|
113
|
+
* @group Testing
|
|
91
114
|
*/
|
|
92
115
|
export const testCreateRandomLib = (seed = "evolu"): RandomLib =>
|
|
93
116
|
new RandomLib(seed);
|