@evolu/common 5.4.7 → 6.0.0-preview.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/README.md +30 -34
- package/dist/src/Array.d.ts +17 -0
- package/dist/src/Array.d.ts.map +1 -0
- package/dist/src/Array.js +12 -0
- package/dist/src/Assert.d.ts +68 -0
- package/dist/src/Assert.d.ts.map +1 -0
- package/dist/src/Assert.js +77 -0
- package/dist/src/BigInt.d.ts +20 -0
- package/dist/src/BigInt.d.ts.map +1 -0
- package/dist/src/BigInt.js +18 -0
- package/dist/src/Buffer.d.ts +92 -0
- package/dist/src/Buffer.d.ts.map +1 -0
- package/dist/src/Buffer.js +62 -0
- package/dist/src/Callbacks.d.ts +20 -0
- package/dist/src/Callbacks.d.ts.map +1 -0
- package/dist/src/Callbacks.js +18 -0
- package/dist/src/Console.d.ts +78 -0
- package/dist/src/Console.d.ts.map +1 -0
- package/dist/src/Console.js +103 -0
- package/dist/src/Crypto.d.ts +72 -39
- package/dist/src/Crypto.d.ts.map +1 -1
- package/dist/src/Crypto.js +89 -54
- package/dist/src/Eq.d.ts +97 -0
- package/dist/src/Eq.d.ts.map +1 -0
- package/dist/src/Eq.js +167 -0
- package/dist/src/Error.d.ts +14 -10
- package/dist/src/Error.d.ts.map +1 -1
- package/dist/src/Error.js +43 -11
- package/dist/src/Evolu/Config.d.ts +69 -0
- package/dist/src/Evolu/Config.d.ts.map +1 -0
- package/dist/src/Evolu/Config.js +9 -0
- package/dist/src/Evolu/Db.d.ts +126 -0
- package/dist/src/Evolu/Db.d.ts.map +1 -0
- package/dist/src/Evolu/Db.js +774 -0
- package/dist/src/Evolu/Diff.d.ts +43 -0
- package/dist/src/Evolu/Diff.d.ts.map +1 -0
- package/dist/src/Evolu/Diff.js +95 -0
- package/dist/src/Evolu/Evolu.d.ts +334 -0
- package/dist/src/Evolu/Evolu.d.ts.map +1 -0
- package/dist/src/Evolu/Evolu.js +434 -0
- package/dist/src/Evolu/Internal.d.ts +26 -0
- package/dist/src/Evolu/Internal.d.ts.map +1 -0
- package/dist/src/Evolu/Internal.js +25 -0
- package/dist/src/Evolu/Kysely.d.ts +6 -0
- package/dist/src/Evolu/Kysely.d.ts.map +1 -0
- package/dist/src/Evolu/Kysely.js +21 -0
- package/dist/src/Evolu/Owner.d.ts +155 -0
- package/dist/src/Evolu/Owner.d.ts.map +1 -0
- package/dist/src/Evolu/Owner.js +126 -0
- package/dist/src/Evolu/Platform.d.ts +23 -0
- package/dist/src/Evolu/Platform.d.ts.map +1 -0
- package/dist/src/Evolu/Platform.js +1 -0
- package/dist/src/Evolu/Protocol.d.ts +401 -0
- package/dist/src/Evolu/Protocol.d.ts.map +1 -0
- package/dist/src/Evolu/Protocol.js +1151 -0
- package/dist/src/Evolu/Public.d.ts +18 -0
- package/dist/src/Evolu/Public.d.ts.map +1 -0
- package/dist/src/Evolu/Public.js +11 -0
- package/dist/src/Evolu/PublicKysely.d.ts +148 -0
- package/dist/src/Evolu/PublicKysely.d.ts.map +1 -0
- package/dist/src/Evolu/PublicKysely.js +185 -0
- package/dist/src/Evolu/Query.d.ts +63 -0
- package/dist/src/Evolu/Query.d.ts.map +1 -0
- package/dist/src/Evolu/Query.js +61 -0
- package/dist/src/Evolu/Relay.d.ts +13 -0
- package/dist/src/Evolu/Relay.d.ts.map +1 -0
- package/dist/src/Evolu/Relay.js +109 -0
- package/dist/src/Evolu/Schema.d.ts +201 -0
- package/dist/src/Evolu/Schema.d.ts.map +1 -0
- package/dist/src/Evolu/Schema.js +150 -0
- package/dist/src/Evolu/Storage.d.ts +49 -0
- package/dist/src/Evolu/Storage.d.ts.map +1 -0
- package/dist/src/Evolu/Storage.js +1111 -0
- package/dist/src/Evolu/Sync.d.ts +59 -0
- package/dist/src/Evolu/Sync.d.ts.map +1 -0
- package/dist/src/Evolu/Sync.js +29 -0
- package/dist/src/Evolu/Timestamp.d.ts +106 -0
- package/dist/src/Evolu/Timestamp.d.ts.map +1 -0
- package/dist/src/Evolu/Timestamp.js +179 -0
- package/dist/src/Function.d.ts +54 -0
- package/dist/src/Function.d.ts.map +1 -0
- package/dist/src/Function.js +38 -0
- package/dist/src/ManyToManyMap.d.ts +26 -0
- package/dist/src/ManyToManyMap.d.ts.map +1 -0
- package/dist/src/ManyToManyMap.js +92 -0
- package/dist/src/NanoId.d.ts +27 -0
- package/dist/src/NanoId.d.ts.map +1 -0
- package/dist/src/NanoId.js +6 -0
- package/dist/src/Number.d.ts +42 -0
- package/dist/src/Number.d.ts.map +1 -0
- package/dist/src/Number.js +55 -0
- package/dist/src/Object.d.ts +35 -0
- package/dist/src/Object.d.ts.map +1 -0
- package/dist/src/Object.js +36 -0
- package/dist/src/Order.d.ts +90 -0
- package/dist/src/Order.d.ts.map +1 -0
- package/dist/src/Order.js +85 -0
- package/dist/src/Promise.d.ts +180 -0
- package/dist/src/Promise.d.ts.map +1 -0
- package/dist/src/Promise.js +176 -0
- package/dist/src/Random.d.ts +52 -0
- package/dist/src/Random.d.ts.map +1 -0
- package/dist/src/Random.js +29 -0
- package/dist/src/Ref.d.ts +40 -0
- package/dist/src/Ref.d.ts.map +1 -0
- package/dist/src/Ref.js +13 -0
- package/dist/src/Result.d.ts +421 -0
- package/dist/src/Result.d.ts.map +1 -0
- package/dist/src/Result.js +357 -0
- package/dist/src/Skiplist.d.ts +23 -0
- package/dist/src/Skiplist.d.ts.map +1 -0
- package/dist/src/Skiplist.js +58 -0
- package/dist/src/Sqlite.d.ts +116 -52
- package/dist/src/Sqlite.d.ts.map +1 -1
- package/dist/src/Sqlite.js +183 -67
- package/dist/src/Store.d.ts +45 -8
- package/dist/src/Store.d.ts.map +1 -1
- package/dist/src/Store.js +33 -17
- package/dist/src/String.d.ts +2 -0
- package/dist/src/String.d.ts.map +1 -0
- package/dist/src/String.js +14 -0
- package/dist/src/Time.d.ts +20 -0
- package/dist/src/Time.d.ts.map +1 -0
- package/dist/src/Time.js +25 -0
- package/dist/src/Type.d.ts +1937 -0
- package/dist/src/Type.d.ts.map +1 -0
- package/dist/src/Type.js +2002 -0
- package/dist/src/Types.d.ts +188 -0
- package/dist/src/Types.d.ts.map +1 -0
- package/dist/src/Types.js +6 -0
- package/dist/src/WebSocket.d.ts +112 -0
- package/dist/src/WebSocket.d.ts.map +1 -0
- package/dist/src/WebSocket.js +139 -0
- package/dist/src/Worker.d.ts +44 -0
- package/dist/src/Worker.d.ts.map +1 -0
- package/dist/src/Worker.js +66 -0
- package/dist/src/index.d.ts +24 -11
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +24 -11
- package/package.json +29 -38
- package/src/Array.ts +39 -0
- package/src/Assert.ts +116 -0
- package/src/BigInt.ts +29 -0
- package/src/Buffer.ts +175 -0
- package/src/Callbacks.ts +43 -0
- package/src/Console.ts +159 -0
- package/src/Crypto.ts +169 -115
- package/src/Eq.ts +204 -0
- package/src/Error.ts +57 -20
- package/src/Evolu/Config.ts +83 -0
- package/src/Evolu/Db.ts +1275 -0
- package/src/Evolu/Diff.ts +142 -0
- package/src/Evolu/Evolu.ts +947 -0
- package/src/Evolu/Internal.ts +26 -0
- package/src/Evolu/Kysely.ts +38 -0
- package/src/Evolu/Owner.ts +296 -0
- package/src/Evolu/Platform.ts +27 -0
- package/src/Evolu/Protocol.ts +1857 -0
- package/src/Evolu/Public.ts +43 -0
- package/src/Evolu/PublicKysely.ts +240 -0
- package/src/Evolu/Query.ts +167 -0
- package/src/Evolu/Relay.ts +142 -0
- package/src/Evolu/Schema.ts +417 -0
- package/src/Evolu/Storage.ts +1281 -0
- package/src/Evolu/Sync.ts +105 -0
- package/src/Evolu/Timestamp.ts +311 -0
- package/src/Function.ts +58 -0
- package/src/ManyToManyMap.ts +140 -0
- package/src/NanoId.ts +39 -0
- package/src/Number.ts +90 -0
- package/src/Object.ts +64 -0
- package/src/Order.ts +113 -0
- package/src/Promise.ts +295 -0
- package/src/Random.ts +68 -0
- package/src/Ref.ts +63 -0
- package/src/Result.ts +453 -0
- package/src/Skiplist.ts +102 -0
- package/src/Sqlite.ts +366 -153
- package/src/Store.ts +79 -36
- package/src/String.ts +10 -0
- package/src/Time.ts +36 -0
- package/src/Type.ts +3978 -0
- package/src/Types.ts +209 -0
- package/src/WebSocket.ts +273 -0
- package/src/Worker.ts +129 -0
- package/src/index.ts +24 -11
- package/dist/src/Config.d.ts +0 -56
- package/dist/src/Config.d.ts.map +0 -1
- package/dist/src/Config.js +0 -39
- package/dist/src/Crdt.d.ts +0 -89
- package/dist/src/Crdt.d.ts.map +0 -1
- package/dist/src/Crdt.js +0 -181
- package/dist/src/Db.d.ts +0 -107
- package/dist/src/Db.d.ts.map +0 -1
- package/dist/src/Db.js +0 -443
- package/dist/src/Diff.d.ts +0 -27
- package/dist/src/Diff.d.ts.map +0 -1
- package/dist/src/Diff.js +0 -84
- package/dist/src/Evolu.d.ts +0 -426
- package/dist/src/Evolu.d.ts.map +0 -1
- package/dist/src/Evolu.js +0 -333
- package/dist/src/Model.d.ts +0 -141
- package/dist/src/Model.d.ts.map +0 -1
- package/dist/src/Model.js +0 -125
- package/dist/src/Murmurhash.d.ts +0 -2
- package/dist/src/Murmurhash.d.ts.map +0 -1
- package/dist/src/Murmurhash.js +0 -60
- package/dist/src/Owner.d.ts +0 -33
- package/dist/src/Owner.d.ts.map +0 -1
- package/dist/src/Owner.js +0 -26
- package/dist/src/Platform.d.ts +0 -37
- package/dist/src/Platform.d.ts.map +0 -1
- package/dist/src/Platform.js +0 -11
- package/dist/src/Protobuf.d.ts +0 -81
- package/dist/src/Protobuf.d.ts.map +0 -1
- package/dist/src/Protobuf.js +0 -92
- package/dist/src/Public.d.ts +0 -13
- package/dist/src/Public.d.ts.map +0 -1
- package/dist/src/Public.js +0 -6
- package/dist/src/Socket.d.ts +0 -8
- package/dist/src/Socket.d.ts.map +0 -1
- package/dist/src/Socket.js +0 -51
- package/dist/src/Sql.d.ts +0 -12
- package/dist/src/Sql.d.ts.map +0 -1
- package/dist/src/Sql.js +0 -30
- package/dist/src/Sync.d.ts +0 -70
- package/dist/src/Sync.d.ts.map +0 -1
- package/dist/src/Sync.js +0 -127
- package/src/Config.ts +0 -119
- package/src/Crdt.ts +0 -361
- package/src/Db.ts +0 -955
- package/src/Diff.ts +0 -114
- package/src/Evolu.ts +0 -1016
- package/src/Model.ts +0 -233
- package/src/Murmurhash.ts +0 -70
- package/src/Owner.ts +0 -69
- package/src/Platform.ts +0 -47
- package/src/Protobuf.ts +0 -155
- package/src/Public.ts +0 -12
- package/src/Socket.ts +0 -83
- package/src/Sql.ts +0 -41
- package/src/Sync.ts +0 -315
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 📝 Cross-platform console
|
|
3
|
+
*
|
|
4
|
+
* Console abstraction for Chrome 123+, Firefox 125+, Safari 18.1+, Node.js
|
|
5
|
+
* 22.x+, and React Native 0.75+. Includes methods guaranteed to be available in
|
|
6
|
+
* these environments and expected to remain compatible in future versions.
|
|
7
|
+
* Output formatting may vary (e.g., interactive UI in browsers vs. text in
|
|
8
|
+
* Node.js/React Native), but functionality is consistent across platforms.
|
|
9
|
+
*
|
|
10
|
+
* **Convention**: Use a tag (e.g., `[db]`) as the first argument for log
|
|
11
|
+
* filtering.
|
|
12
|
+
*
|
|
13
|
+
* ### Example
|
|
14
|
+
*
|
|
15
|
+
* ```ts
|
|
16
|
+
* deps.console.log("[db]", "send data message", protocolMessage);
|
|
17
|
+
* ```
|
|
18
|
+
*
|
|
19
|
+
* **Tip**: In browser dev tools, you can filter logs by tag (e.g., `[db]`) to
|
|
20
|
+
* quickly find relevant messages.
|
|
21
|
+
*
|
|
22
|
+
* **Warning**: If you encounter platform-specific issues or missing methods,
|
|
23
|
+
* please contribute a PR with details about the environment and behavior.
|
|
24
|
+
*
|
|
25
|
+
* @module
|
|
26
|
+
*/
|
|
27
|
+
/** Creates a console instance using the global console. */
|
|
28
|
+
export const createConsole = (config = {}) => {
|
|
29
|
+
const instance = {
|
|
30
|
+
enabled: config.enableLogging ?? false,
|
|
31
|
+
log: (...args) => {
|
|
32
|
+
// eslint-disable-next-line no-console, @typescript-eslint/no-unsafe-argument
|
|
33
|
+
if (instance.enabled)
|
|
34
|
+
console.log(...args);
|
|
35
|
+
},
|
|
36
|
+
info: (...args) => {
|
|
37
|
+
// eslint-disable-next-line no-console, @typescript-eslint/no-unsafe-argument
|
|
38
|
+
if (instance.enabled)
|
|
39
|
+
console.info(...args);
|
|
40
|
+
},
|
|
41
|
+
warn: (...args) => {
|
|
42
|
+
// eslint-disable-next-line no-console, @typescript-eslint/no-unsafe-argument
|
|
43
|
+
if (instance.enabled)
|
|
44
|
+
console.warn(...args);
|
|
45
|
+
},
|
|
46
|
+
error: (...args) => {
|
|
47
|
+
// Always log errors, even if disabled
|
|
48
|
+
// eslint-disable-next-line no-console, @typescript-eslint/no-unsafe-argument
|
|
49
|
+
console.error(...args);
|
|
50
|
+
},
|
|
51
|
+
debug: (...args) => {
|
|
52
|
+
// eslint-disable-next-line no-console, @typescript-eslint/no-unsafe-argument
|
|
53
|
+
if (instance.enabled)
|
|
54
|
+
console.debug(...args);
|
|
55
|
+
},
|
|
56
|
+
time: (label) => {
|
|
57
|
+
// eslint-disable-next-line no-console
|
|
58
|
+
if (instance.enabled)
|
|
59
|
+
console.time(label);
|
|
60
|
+
},
|
|
61
|
+
timeEnd: (label) => {
|
|
62
|
+
// eslint-disable-next-line no-console
|
|
63
|
+
if (instance.enabled)
|
|
64
|
+
console.timeEnd(label);
|
|
65
|
+
},
|
|
66
|
+
dir: (object, options) => {
|
|
67
|
+
// eslint-disable-next-line no-console
|
|
68
|
+
if (instance.enabled)
|
|
69
|
+
console.dir(object, options);
|
|
70
|
+
},
|
|
71
|
+
table: (tabularData, properties) => {
|
|
72
|
+
// eslint-disable-next-line no-console
|
|
73
|
+
if (instance.enabled)
|
|
74
|
+
console.table(tabularData, properties);
|
|
75
|
+
},
|
|
76
|
+
count: (label) => {
|
|
77
|
+
// eslint-disable-next-line no-console
|
|
78
|
+
if (instance.enabled)
|
|
79
|
+
console.count(label);
|
|
80
|
+
},
|
|
81
|
+
countReset: (label) => {
|
|
82
|
+
// eslint-disable-next-line no-console
|
|
83
|
+
if (instance.enabled)
|
|
84
|
+
console.countReset(label);
|
|
85
|
+
},
|
|
86
|
+
assert: (value, message, ...optionalParams) => {
|
|
87
|
+
// eslint-disable-next-line no-console, @typescript-eslint/no-unsafe-argument
|
|
88
|
+
if (instance.enabled)
|
|
89
|
+
console.assert(value, message, ...optionalParams);
|
|
90
|
+
},
|
|
91
|
+
timeLog: (label, ...data) => {
|
|
92
|
+
// eslint-disable-next-line no-console, @typescript-eslint/no-unsafe-argument
|
|
93
|
+
if (instance.enabled)
|
|
94
|
+
console.timeLog(label, ...data);
|
|
95
|
+
},
|
|
96
|
+
trace: (message, ...optionalParams) => {
|
|
97
|
+
// eslint-disable-next-line no-console, @typescript-eslint/no-unsafe-argument
|
|
98
|
+
if (instance.enabled)
|
|
99
|
+
console.trace(message, ...optionalParams);
|
|
100
|
+
},
|
|
101
|
+
};
|
|
102
|
+
return instance;
|
|
103
|
+
};
|
package/dist/src/Crypto.d.ts
CHANGED
|
@@ -1,49 +1,82 @@
|
|
|
1
|
-
import * as S from "@effect/schema/Schema";
|
|
2
|
-
import * as Brand from "effect/Brand";
|
|
3
|
-
import * as Context from "effect/Context";
|
|
4
|
-
import * as Effect from "effect/Effect";
|
|
5
|
-
import * as Layer from "effect/Layer";
|
|
6
|
-
import { Id } from "./Model.js";
|
|
7
1
|
/**
|
|
8
|
-
*
|
|
2
|
+
* 🔒
|
|
9
3
|
*
|
|
10
|
-
*
|
|
11
|
-
* order chosen from a predefined list. The purpose of the BIP39 mnemonic is to
|
|
12
|
-
* provide a human-readable way of storing a private key.
|
|
4
|
+
* @module
|
|
13
5
|
*/
|
|
14
|
-
|
|
6
|
+
import { Result } from "./Result.js";
|
|
7
|
+
import { Id, Mnemonic, NonNegativeInt } from "./Type.js";
|
|
8
|
+
import { Brand } from "./Types.js";
|
|
9
|
+
/** `Uint8Array` created by {@link createRandomBytes}. */
|
|
10
|
+
export type RandomBytes = Uint8Array & Brand<"RandomBytes">;
|
|
11
|
+
export type CreateRandomBytes = (bytesLength?: number) => RandomBytes;
|
|
12
|
+
export interface CreateRandomBytesDep {
|
|
13
|
+
readonly createRandomBytes: CreateRandomBytes;
|
|
14
|
+
}
|
|
15
|
+
/** Cryptographically secure PRNG. Uses internal OS-level crypto.getRandomValues. */
|
|
16
|
+
export declare const createRandomBytes: CreateRandomBytes;
|
|
17
|
+
export type CreateMnemonic = () => Mnemonic;
|
|
18
|
+
export interface CreateMnemonicDep {
|
|
19
|
+
readonly createMnemonic: CreateMnemonic;
|
|
20
|
+
}
|
|
21
|
+
export declare const createEnglishMnemonic: CreateMnemonic;
|
|
22
|
+
export type MnemonicSeed = Uint8Array & Brand<"MnemonicSeed">;
|
|
23
|
+
export declare const mnemonicToMnemonicSeed: (mnemonic: Mnemonic) => MnemonicSeed;
|
|
15
24
|
/**
|
|
16
|
-
*
|
|
25
|
+
* SLIP21.
|
|
17
26
|
*
|
|
18
|
-
*
|
|
19
|
-
* order chosen from a predefined list. The purpose of the BIP39 mnemonic is to
|
|
20
|
-
* provide a human-readable way of storing a private key.
|
|
27
|
+
* https://github.com/satoshilabs/slips/blob/master/slip-0021.md
|
|
21
28
|
*/
|
|
22
|
-
export declare const
|
|
23
|
-
/**
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
29
|
+
export declare const createSlip21: (seed: MnemonicSeed, path: ReadonlyArray<string>) => Uint8Array;
|
|
30
|
+
/**
|
|
31
|
+
* Creates a 21-character Base64URL ID (also known as nanoid) from a SLIP-21
|
|
32
|
+
* derived key.
|
|
33
|
+
*
|
|
34
|
+
* Reduces the 256-bit SLIP-21 output to 126 bits (21 chars × 6 bits) for a
|
|
35
|
+
* compact, human-readable, and shareable identifier suitable for UI display or
|
|
36
|
+
* URL use. While this lowers entropy, 126 bits remains cryptographically secure
|
|
37
|
+
* for uniqueness and unpredictability in most applications (comparable to
|
|
38
|
+
* UUIDv4's 122 bits).
|
|
39
|
+
*
|
|
40
|
+
* See https://github.com/satoshilabs/slips/blob/master/slip-0021.md
|
|
41
|
+
*/
|
|
42
|
+
export declare const createSlip21Id: (seed: MnemonicSeed, path: ReadonlyArray<string>) => Id;
|
|
43
|
+
/** The encryption key for {@link SymmetricCrypto}. */
|
|
44
|
+
export declare const EncryptionKey: import("./Type.js").BrandType<import("./Type.js").BrandType<import("./Type.js").Type<"Uint8Array", Uint8Array<ArrayBufferLike>, Uint8Array<ArrayBufferLike>, import("./Type.js").Uint8ArrayError, Uint8Array<ArrayBufferLike>, import("./Type.js").Uint8ArrayError>, "Length32", import("./Type.js").LengthError<32>, import("./Type.js").Uint8ArrayError>, "EncryptionKey", import("./Type.js").BrandWithoutRefineError<"EncryptionKey", import("./Type.js").Uint8ArrayError | import("./Type.js").LengthError<32>>, never>;
|
|
45
|
+
export type EncryptionKey = typeof EncryptionKey.Type;
|
|
46
|
+
export declare const createEncryptionKey: (seed: MnemonicSeed) => EncryptionKey;
|
|
47
|
+
/** Symmetric cryptography. */
|
|
48
|
+
export interface SymmetricCrypto {
|
|
49
|
+
readonly nonceLength: NonNegativeInt;
|
|
50
|
+
readonly encrypt: (plaintext: Uint8Array, encryptionKey: EncryptionKey) => {
|
|
51
|
+
readonly nonce: Uint8Array;
|
|
52
|
+
readonly ciphertext: Uint8Array;
|
|
53
|
+
};
|
|
54
|
+
readonly decrypt: (ciphertext: Uint8Array, encryptionKey: EncryptionKey, nonce: Uint8Array) => Result<Uint8Array, SymmetricCryptoDecryptError>;
|
|
27
55
|
}
|
|
28
|
-
export
|
|
29
|
-
|
|
30
|
-
readonly nanoid: Effect.Effect<NanoId>;
|
|
31
|
-
readonly nodeId: Effect.Effect<NodeId>;
|
|
32
|
-
readonly rowId: Effect.Effect<Id>;
|
|
33
|
-
}>;
|
|
34
|
-
export declare class NanoIdGenerator extends NanoIdGenerator_base {
|
|
56
|
+
export interface SymmetricCryptoDep {
|
|
57
|
+
readonly symmetricCrypto: SymmetricCrypto;
|
|
35
58
|
}
|
|
36
|
-
export
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
export type NodeId = typeof NodeId.Type;
|
|
40
|
-
export declare const slip21Derive: (seed: Uint8Array, path: ReadonlyArray<string>) => Effect.Effect<Uint8Array>;
|
|
41
|
-
declare const SecretBox_base: Context.TagClass<SecretBox, "SecretBox", {
|
|
42
|
-
readonly seal: (key: Uint8Array, plaintext: Uint8Array) => Effect.Effect<Uint8Array>;
|
|
43
|
-
readonly open: (key: Uint8Array, ciphertext: Uint8Array) => Effect.Effect<Uint8Array>;
|
|
44
|
-
}>;
|
|
45
|
-
export declare class SecretBox extends SecretBox_base {
|
|
46
|
-
static Live: Layer.Layer<SecretBox, never, never>;
|
|
59
|
+
export interface SymmetricCryptoDecryptError {
|
|
60
|
+
readonly type: "SymmetricCryptoDecryptError";
|
|
61
|
+
readonly error: unknown;
|
|
47
62
|
}
|
|
48
|
-
|
|
63
|
+
/**
|
|
64
|
+
* XChaCha20-Poly1305 encryption
|
|
65
|
+
*
|
|
66
|
+
* https://github.com/paulmillr/noble-ciphers?tab=readme-ov-file#which-cipher-should-i-pick
|
|
67
|
+
*/
|
|
68
|
+
export declare const createSymmetricCrypto: (deps: CreateRandomBytesDep) => SymmetricCrypto;
|
|
69
|
+
/**
|
|
70
|
+
* Returns the PADMÉ padded length for a given input length.
|
|
71
|
+
*
|
|
72
|
+
* PADMÉ limits information leakage about the length of the plain-text for a
|
|
73
|
+
* wide range of encrypted data sizes. See the PURBs paper for details:
|
|
74
|
+
* https://bford.info/pub/sec/purb.pdf
|
|
75
|
+
*/
|
|
76
|
+
export declare const padmePaddedLength: (length: NonNegativeInt) => NonNegativeInt;
|
|
77
|
+
/**
|
|
78
|
+
* Returns the PADMÉ padding length for a given input length. Uses
|
|
79
|
+
* {@link padmePaddedLength}.
|
|
80
|
+
*/
|
|
81
|
+
export declare const padmePaddingLength: (length: NonNegativeInt) => NonNegativeInt;
|
|
49
82
|
//# sourceMappingURL=Crypto.d.ts.map
|
package/dist/src/Crypto.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Crypto.d.ts","sourceRoot":"","sources":["../../src/Crypto.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"Crypto.d.ts","sourceRoot":"","sources":["../../src/Crypto.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AASH,OAAO,EAAc,MAAM,EAAW,MAAM,aAAa,CAAC;AAC1D,OAAO,EAEL,EAAE,EAEF,QAAQ,EACR,cAAc,EAEf,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAEnC,yDAAyD;AACzD,MAAM,MAAM,WAAW,GAAG,UAAU,GAAG,KAAK,CAAC,aAAa,CAAC,CAAC;AAE5D,MAAM,MAAM,iBAAiB,GAAG,CAAC,WAAW,CAAC,EAAE,MAAM,KAAK,WAAW,CAAC;AAEtE,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,iBAAiB,EAAE,iBAAiB,CAAC;CAC/C;AAED,oFAAoF;AACpF,eAAO,MAAM,iBAAiB,EAAE,iBACS,CAAC;AAE1C,MAAM,MAAM,cAAc,GAAG,MAAM,QAAQ,CAAC;AAE5C,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,cAAc,EAAE,cAAc,CAAC;CACzC;AAED,eAAO,MAAM,qBAAqB,EAAE,cACe,CAAC;AAEpD,MAAM,MAAM,YAAY,GAAG,UAAU,GAAG,KAAK,CAAC,cAAc,CAAC,CAAC;AAE9D,eAAO,MAAM,sBAAsB,GAAI,UAAU,QAAQ,KAAG,YACR,CAAC;AAErD;;;;GAIG;AACH,eAAO,MAAM,YAAY,GACvB,MAAM,YAAY,EAClB,MAAM,aAAa,CAAC,MAAM,CAAC,KAC1B,UAUF,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,cAAc,GACzB,MAAM,YAAY,EAClB,MAAM,aAAa,CAAC,MAAM,CAAC,KAC1B,EAUF,CAAC;AAEF,sDAAsD;AACtD,eAAO,MAAM,aAAa,8fAAiD,CAAC;AAC5E,MAAM,MAAM,aAAa,GAAG,OAAO,aAAa,CAAC,IAAI,CAAC;AAEtD,eAAO,MAAM,mBAAmB,GAAI,MAAM,YAAY,KAAG,aACS,CAAC;AAEnE,8BAA8B;AAC9B,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,WAAW,EAAE,cAAc,CAAC;IAErC,QAAQ,CAAC,OAAO,EAAE,CAChB,SAAS,EAAE,UAAU,EACrB,aAAa,EAAE,aAAa,KACzB;QACH,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC;QAC3B,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAC;KACjC,CAAC;IAEF,QAAQ,CAAC,OAAO,EAAE,CAChB,UAAU,EAAE,UAAU,EACtB,aAAa,EAAE,aAAa,EAC5B,KAAK,EAAE,UAAU,KACd,MAAM,CAAC,UAAU,EAAE,2BAA2B,CAAC,CAAC;CACtD;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,eAAe,EAAE,eAAe,CAAC;CAC3C;AAED,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,CAAC,IAAI,EAAE,6BAA6B,CAAC;IAC7C,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;CACzB;AAED;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,GAChC,MAAM,oBAAoB,KACzB,eAyBF,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,iBAAiB,GAAI,QAAQ,cAAc,KAAG,cAO1D,CAAC;AAEF;;;GAGG;AAEH,eAAO,MAAM,kBAAkB,GAAI,QAAQ,cAAc,KAAG,cAE3D,CAAC"}
|
package/dist/src/Crypto.js
CHANGED
|
@@ -1,67 +1,102 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
/**
|
|
2
|
+
* 🔒
|
|
3
|
+
*
|
|
4
|
+
* @module
|
|
5
|
+
*/
|
|
6
|
+
import { xchacha20poly1305 } from "@noble/ciphers/chacha";
|
|
4
7
|
import { hmac } from "@noble/hashes/hmac";
|
|
5
|
-
import { sha512 } from "@noble/hashes/
|
|
8
|
+
import { sha512 } from "@noble/hashes/sha2";
|
|
6
9
|
import { randomBytes } from "@noble/hashes/utils";
|
|
7
10
|
import * as bip39 from "@scure/bip39";
|
|
8
11
|
import { wordlist } from "@scure/bip39/wordlists/english";
|
|
9
|
-
import
|
|
10
|
-
import
|
|
11
|
-
import
|
|
12
|
+
import { urlAlphabet } from "nanoid";
|
|
13
|
+
import { getOrThrow, trySync } from "./Result.js";
|
|
14
|
+
import { brand, length, NonNegativeInt, Uint8Array, } from "./Type.js";
|
|
15
|
+
/** Cryptographically secure PRNG. Uses internal OS-level crypto.getRandomValues. */
|
|
16
|
+
export const createRandomBytes = (bytesLength = 32) => randomBytes(bytesLength);
|
|
17
|
+
export const createEnglishMnemonic = () => bip39.generateMnemonic(wordlist, 128);
|
|
18
|
+
export const mnemonicToMnemonicSeed = (mnemonic) => bip39.mnemonicToSeedSync(mnemonic);
|
|
12
19
|
/**
|
|
13
|
-
*
|
|
20
|
+
* SLIP21.
|
|
14
21
|
*
|
|
15
|
-
*
|
|
16
|
-
* order chosen from a predefined list. The purpose of the BIP39 mnemonic is to
|
|
17
|
-
* provide a human-readable way of storing a private key.
|
|
22
|
+
* https://github.com/satoshilabs/slips/blob/master/slip-0021.md
|
|
18
23
|
*/
|
|
19
|
-
export const
|
|
20
|
-
/** Parse a string to {@link Mnemonic}. */
|
|
21
|
-
export const parseMnemonic = (mnemonic) => {
|
|
22
|
-
const mnemonicTrimmed = mnemonic.trim();
|
|
23
|
-
return bip39.validateMnemonic(mnemonicTrimmed, wordlist)
|
|
24
|
-
? Effect.succeed(mnemonicTrimmed)
|
|
25
|
-
: Effect.fail({
|
|
26
|
-
_tag: "InvalidMnemonicError",
|
|
27
|
-
});
|
|
28
|
-
};
|
|
29
|
-
export const mnemonicToSeed = (mnemonic) => bip39.mnemonicToSeedSync(mnemonic);
|
|
30
|
-
export class NanoIdGenerator extends Context.Tag("NanoIdGenerator")() {
|
|
31
|
-
}
|
|
32
|
-
export const createNanoIdGeneratorLive = (customAlphabet, nanoid) => {
|
|
33
|
-
const nanoidForNodeId = customAlphabet("0123456789abcdef", 16);
|
|
34
|
-
return Layer.succeed(NanoIdGenerator, NanoIdGenerator.of({
|
|
35
|
-
nanoid: Effect.sync(() => nanoid()),
|
|
36
|
-
nodeId: Effect.sync(() => nanoidForNodeId()),
|
|
37
|
-
rowId: Effect.sync(() => nanoid()),
|
|
38
|
-
}));
|
|
39
|
-
};
|
|
40
|
-
export const NodeId = S.String.pipe(S.pattern(/^[\w-]{16}$/), S.brand("NodeId"));
|
|
41
|
-
// SLIP-21 implementation
|
|
42
|
-
// https://github.com/satoshilabs/slips/blob/master/slip-0021.md
|
|
43
|
-
export const slip21Derive = (seed, path) => Effect.sync(() => {
|
|
24
|
+
export const createSlip21 = (seed, path) => {
|
|
44
25
|
let m = hmac(sha512, "Symmetric key seed", seed);
|
|
45
|
-
for (
|
|
46
|
-
const p = new TextEncoder().encode(
|
|
47
|
-
const e = new Uint8Array(p.byteLength + 1);
|
|
26
|
+
for (const component of path) {
|
|
27
|
+
const p = new TextEncoder().encode(component);
|
|
28
|
+
const e = new globalThis.Uint8Array(p.byteLength + 1);
|
|
48
29
|
e[0] = 0;
|
|
49
30
|
e.set(p, 1);
|
|
50
31
|
m = hmac(sha512, m.slice(0, 32), e);
|
|
51
32
|
}
|
|
52
33
|
return m.slice(32, 64);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* Creates a 21-character Base64URL ID (also known as nanoid) from a SLIP-21
|
|
37
|
+
* derived key.
|
|
38
|
+
*
|
|
39
|
+
* Reduces the 256-bit SLIP-21 output to 126 bits (21 chars × 6 bits) for a
|
|
40
|
+
* compact, human-readable, and shareable identifier suitable for UI display or
|
|
41
|
+
* URL use. While this lowers entropy, 126 bits remains cryptographically secure
|
|
42
|
+
* for uniqueness and unpredictability in most applications (comparable to
|
|
43
|
+
* UUIDv4's 122 bits).
|
|
44
|
+
*
|
|
45
|
+
* See https://github.com/satoshilabs/slips/blob/master/slip-0021.md
|
|
46
|
+
*/
|
|
47
|
+
export const createSlip21Id = (seed, path) => {
|
|
48
|
+
const slip21 = createSlip21(seed, path);
|
|
49
|
+
let id = "";
|
|
50
|
+
// Convert the key to the Id/NanoId/Base64Url format.
|
|
51
|
+
for (let i = 0; i < 21; i++) {
|
|
52
|
+
id = (id + urlAlphabet[slip21[i] & 63]);
|
|
53
|
+
}
|
|
54
|
+
return id;
|
|
55
|
+
};
|
|
56
|
+
/** The encryption key for {@link SymmetricCrypto}. */
|
|
57
|
+
export const EncryptionKey = brand("EncryptionKey", length(32)(Uint8Array));
|
|
58
|
+
export const createEncryptionKey = (seed) => createSlip21(seed, ["Evolu", "Encryption Key"]);
|
|
59
|
+
/**
|
|
60
|
+
* XChaCha20-Poly1305 encryption
|
|
61
|
+
*
|
|
62
|
+
* https://github.com/paulmillr/noble-ciphers?tab=readme-ov-file#which-cipher-should-i-pick
|
|
63
|
+
*/
|
|
64
|
+
export const createSymmetricCrypto = (deps) => {
|
|
65
|
+
const nonceLength = getOrThrow(NonNegativeInt.from(24));
|
|
66
|
+
const symmetricCrypto = {
|
|
67
|
+
nonceLength,
|
|
68
|
+
encrypt: (plaintext, encryptionKey) => {
|
|
69
|
+
const nonce = deps.createRandomBytes(nonceLength);
|
|
70
|
+
const ciphertext = xchacha20poly1305(encryptionKey, nonce).encrypt(plaintext);
|
|
71
|
+
return { nonce, ciphertext };
|
|
72
|
+
},
|
|
73
|
+
decrypt: (ciphertext, encryptionKey, nonce) => trySync(() => xchacha20poly1305(encryptionKey, nonce).decrypt(ciphertext), (error) => ({
|
|
74
|
+
type: "SymmetricCryptoDecryptError",
|
|
75
|
+
error,
|
|
76
|
+
})),
|
|
77
|
+
};
|
|
78
|
+
return symmetricCrypto;
|
|
79
|
+
};
|
|
80
|
+
/**
|
|
81
|
+
* Returns the PADMÉ padded length for a given input length.
|
|
82
|
+
*
|
|
83
|
+
* PADMÉ limits information leakage about the length of the plain-text for a
|
|
84
|
+
* wide range of encrypted data sizes. See the PURBs paper for details:
|
|
85
|
+
* https://bford.info/pub/sec/purb.pdf
|
|
86
|
+
*/
|
|
87
|
+
export const padmePaddedLength = (length) => {
|
|
88
|
+
if (length <= 0)
|
|
89
|
+
return 0;
|
|
90
|
+
const e = 31 - Math.clz32(length >>> 0);
|
|
91
|
+
const s = 32 - Math.clz32(e >>> 0);
|
|
92
|
+
const z = Math.max(0, e - s);
|
|
93
|
+
const mask = (1 << z) - 1;
|
|
94
|
+
return ((length + mask) & ~mask);
|
|
95
|
+
};
|
|
96
|
+
/**
|
|
97
|
+
* Returns the PADMÉ padding length for a given input length. Uses
|
|
98
|
+
* {@link padmePaddedLength}.
|
|
99
|
+
*/
|
|
100
|
+
export const padmePaddingLength = (length) => {
|
|
101
|
+
return (padmePaddedLength(length) - length);
|
|
102
|
+
};
|
package/dist/src/Eq.d.ts
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { JsonValue, JsonValueInput } from "./Type.js";
|
|
2
|
+
import { Order } from "./Order.js";
|
|
3
|
+
/**
|
|
4
|
+
* Compares two values of the same type `A` for equality.
|
|
5
|
+
*
|
|
6
|
+
* Equality functions start with an 'eq' prefix, e.g., `eqString`.
|
|
7
|
+
*
|
|
8
|
+
* TODO: Explain, examples (composition etc.)
|
|
9
|
+
*/
|
|
10
|
+
export type Eq<in A> = (x: A, y: A) => boolean;
|
|
11
|
+
export declare const eqStrict: <A>(x: A, y: A) => boolean;
|
|
12
|
+
export declare const eqString: Eq<string>;
|
|
13
|
+
export declare const eqNumber: Eq<number>;
|
|
14
|
+
export declare const eqBigInt: Eq<bigint>;
|
|
15
|
+
export declare const eqBoolean: Eq<boolean>;
|
|
16
|
+
export declare const eqUndefined: Eq<undefined>;
|
|
17
|
+
export declare const eqNull: Eq<null>;
|
|
18
|
+
/** Derives an {@link Eq} from an {@link Order}. */
|
|
19
|
+
export declare const eqFromOrder: <A>(order: Order<A>) => Eq<A>;
|
|
20
|
+
/**
|
|
21
|
+
* Creates an equivalence function for array-like structures based on an
|
|
22
|
+
* equivalence for their elements.
|
|
23
|
+
*
|
|
24
|
+
* ### Example
|
|
25
|
+
*
|
|
26
|
+
* ```ts
|
|
27
|
+
* const eqArrayNumber = createEqArrayLike(eqNumber);
|
|
28
|
+
* eqArrayNumber([1, 2, 3], [1, 2, 3]); // true (works with regular arrays)
|
|
29
|
+
* eqArrayNumber(new Uint8Array([1, 2, 3]), new Uint8Array([1, 2, 3])); // true (works with Uint8Array)
|
|
30
|
+
* eqArrayNumber([1, 2, 3], [1, 2, 4]); // false
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
export declare const createEqArrayLike: <A>(item: Eq<A>) => Eq<ArrayLike<A>>;
|
|
34
|
+
/**
|
|
35
|
+
* Compares two array-like structures of numbers for equality.
|
|
36
|
+
*
|
|
37
|
+
* ### Example
|
|
38
|
+
*
|
|
39
|
+
* ```ts
|
|
40
|
+
* eqArrayNumber([1, 2, 3], [1, 2, 3]); // true (works with regular arrays)
|
|
41
|
+
* eqArrayNumber(new Uint8Array([1, 2, 3]), new Uint8Array([1, 2, 3])); // true (works with Uint8Array)
|
|
42
|
+
* eqArrayNumber([1, 2, 3], [1, 2, 4]); // false
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
export declare const eqArrayNumber: Eq<ArrayLike<number>>;
|
|
46
|
+
/**
|
|
47
|
+
* Creates an equivalence function for objects based on an equivalence for their
|
|
48
|
+
* fields.
|
|
49
|
+
*
|
|
50
|
+
* ### Example
|
|
51
|
+
*
|
|
52
|
+
* ```ts
|
|
53
|
+
* const eqObjectNumber = createEqObject({ a: eqNumber });
|
|
54
|
+
* eqObjectNumber({ a: 1 }, { a: 1 }); // true
|
|
55
|
+
* eqObjectNumber({ a: 1 }, { a: 2 }); // false
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
58
|
+
export declare const createEqObject: <A>(eqs: { [K in keyof A]: Eq<A[K]>; }) => Eq<{ readonly [K in keyof A]: A[K]; }>;
|
|
59
|
+
/**
|
|
60
|
+
* Deeply compares two {@link JsonValue} values for equality.
|
|
61
|
+
*
|
|
62
|
+
* - Uses an iterative approach with a stack to handle large or deeply nested
|
|
63
|
+
* objects without risking stack overflow.
|
|
64
|
+
* - Handles circular references with a WeakMap to prevent infinite loops.
|
|
65
|
+
* - Unlike JSON.stringify, this function directly compares values, avoiding
|
|
66
|
+
* serialization overhead and leveraging short-circuit evaluation for faster
|
|
67
|
+
* failure on mismatched structures.
|
|
68
|
+
*
|
|
69
|
+
* ### Example
|
|
70
|
+
*
|
|
71
|
+
* ```ts
|
|
72
|
+
* const obj1: Json = { name: "Alice", hobbies: ["reading", "hiking"] };
|
|
73
|
+
* const obj2: Json = { name: "Alice", hobbies: ["reading", "hiking"] };
|
|
74
|
+
* console.log(eqJson(obj1, obj2)); // true
|
|
75
|
+
* ```
|
|
76
|
+
*/
|
|
77
|
+
export declare const eqJsonValue: (a: JsonValue, b: JsonValue) => boolean;
|
|
78
|
+
/**
|
|
79
|
+
* Deeply compares two {@link JsonValueInput} values for equality.
|
|
80
|
+
*
|
|
81
|
+
* - Uses an iterative approach with a stack to handle large or deeply nested
|
|
82
|
+
* objects without risking stack overflow.
|
|
83
|
+
* - Handles circular references with a WeakMap to prevent infinite loops.
|
|
84
|
+
* - Unlike JSON.stringify, this function directly compares values, avoiding
|
|
85
|
+
* serialization overhead and leveraging short-circuit evaluation for faster
|
|
86
|
+
* failure on mismatched structures.
|
|
87
|
+
*
|
|
88
|
+
* ### Example
|
|
89
|
+
*
|
|
90
|
+
* ```ts
|
|
91
|
+
* const obj1: Json = { name: "Alice", hobbies: ["reading", "hiking"] };
|
|
92
|
+
* const obj2: Json = { name: "Alice", hobbies: ["reading", "hiking"] };
|
|
93
|
+
* console.log(eqJson(obj1, obj2)); // true
|
|
94
|
+
* ```
|
|
95
|
+
*/
|
|
96
|
+
export declare const eqJsonValueInput: (a: JsonValueInput, b: JsonValueInput) => boolean;
|
|
97
|
+
//# sourceMappingURL=Eq.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Eq.d.ts","sourceRoot":"","sources":["../../src/Eq.ts"],"names":[],"mappings":"AAAA,OAAO,EAAyB,SAAS,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC7E,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAEnC;;;;;;GAMG;AACH,MAAM,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,OAAO,CAAC;AAE/C,eAAO,MAAM,QAAQ,GAAI,CAAC,EAAE,GAAG,CAAC,EAAE,GAAG,CAAC,KAAG,OAAkB,CAAC;AAE5D,eAAO,MAAM,QAAQ,EAAE,EAAE,CAAC,MAAM,CAAY,CAAC;AAC7C,eAAO,MAAM,QAAQ,EAAE,EAAE,CAAC,MAAM,CAAY,CAAC;AAC7C,eAAO,MAAM,QAAQ,EAAE,EAAE,CAAC,MAAM,CAAY,CAAC;AAC7C,eAAO,MAAM,SAAS,EAAE,EAAE,CAAC,OAAO,CAAY,CAAC;AAC/C,eAAO,MAAM,WAAW,EAAE,EAAE,CAAC,SAAS,CAAY,CAAC;AACnD,eAAO,MAAM,MAAM,EAAE,EAAE,CAAC,IAAI,CAAY,CAAC;AAEzC,mDAAmD;AACnD,eAAO,MAAM,WAAW,GACrB,CAAC,EAAE,OAAO,KAAK,CAAC,CAAC,CAAC,KAAG,EAAE,CAAC,CAAC,CAEP,CAAC;AAEtB;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,iBAAiB,GAC3B,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,KAAG,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,CAUhC,CAAC;AAEJ;;;;;;;;;;GAUG;AACH,eAAO,MAAM,aAAa,uBAA8B,CAAC;AAEzD;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,cAAc,GACxB,CAAC,EAAE,KAAK,GAAG,CAAC,IAAI,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAE,KAAG,EAAE,CAAC,EACzC,QAAQ,EAAE,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAC9B,CASA,CAAC;AAEJ;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,WAAW,GAAI,GAAG,SAAS,EAAE,GAAG,SAAS,KAAG,OAsExD,CAAC;AAEF;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,gBAAgB,GAC3B,GAAG,cAAc,EACjB,GAAG,cAAc,KAChB,OAAsD,CAAC"}
|
package/dist/src/Eq.js
ADDED
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
export const eqStrict = (x, y) => x === y;
|
|
2
|
+
export const eqString = eqStrict;
|
|
3
|
+
export const eqNumber = eqStrict;
|
|
4
|
+
export const eqBigInt = eqStrict;
|
|
5
|
+
export const eqBoolean = eqStrict;
|
|
6
|
+
export const eqUndefined = eqStrict;
|
|
7
|
+
export const eqNull = eqStrict;
|
|
8
|
+
/** Derives an {@link Eq} from an {@link Order}. */
|
|
9
|
+
export const eqFromOrder = (order) => (x, y) => order(x, y) === 0;
|
|
10
|
+
/**
|
|
11
|
+
* Creates an equivalence function for array-like structures based on an
|
|
12
|
+
* equivalence for their elements.
|
|
13
|
+
*
|
|
14
|
+
* ### Example
|
|
15
|
+
*
|
|
16
|
+
* ```ts
|
|
17
|
+
* const eqArrayNumber = createEqArrayLike(eqNumber);
|
|
18
|
+
* eqArrayNumber([1, 2, 3], [1, 2, 3]); // true (works with regular arrays)
|
|
19
|
+
* eqArrayNumber(new Uint8Array([1, 2, 3]), new Uint8Array([1, 2, 3])); // true (works with Uint8Array)
|
|
20
|
+
* eqArrayNumber([1, 2, 3], [1, 2, 4]); // false
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
export const createEqArrayLike = (item) => (x, y) => {
|
|
24
|
+
if (x === y)
|
|
25
|
+
return true;
|
|
26
|
+
if (x.length !== y.length)
|
|
27
|
+
return false;
|
|
28
|
+
for (let i = 0; i < x.length; i++) {
|
|
29
|
+
if (!item(x[i], y[i]))
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
return true;
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* Compares two array-like structures of numbers for equality.
|
|
36
|
+
*
|
|
37
|
+
* ### Example
|
|
38
|
+
*
|
|
39
|
+
* ```ts
|
|
40
|
+
* eqArrayNumber([1, 2, 3], [1, 2, 3]); // true (works with regular arrays)
|
|
41
|
+
* eqArrayNumber(new Uint8Array([1, 2, 3]), new Uint8Array([1, 2, 3])); // true (works with Uint8Array)
|
|
42
|
+
* eqArrayNumber([1, 2, 3], [1, 2, 4]); // false
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
export const eqArrayNumber = createEqArrayLike(eqNumber);
|
|
46
|
+
/**
|
|
47
|
+
* Creates an equivalence function for objects based on an equivalence for their
|
|
48
|
+
* fields.
|
|
49
|
+
*
|
|
50
|
+
* ### Example
|
|
51
|
+
*
|
|
52
|
+
* ```ts
|
|
53
|
+
* const eqObjectNumber = createEqObject({ a: eqNumber });
|
|
54
|
+
* eqObjectNumber({ a: 1 }, { a: 1 }); // true
|
|
55
|
+
* eqObjectNumber({ a: 1 }, { a: 2 }); // false
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
58
|
+
export const createEqObject = (eqs) => (x, y) => {
|
|
59
|
+
if (x === y)
|
|
60
|
+
return true;
|
|
61
|
+
for (const key in eqs) {
|
|
62
|
+
if (!eqs[key](x[key], y[key])) {
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return true;
|
|
67
|
+
};
|
|
68
|
+
/**
|
|
69
|
+
* Deeply compares two {@link JsonValue} values for equality.
|
|
70
|
+
*
|
|
71
|
+
* - Uses an iterative approach with a stack to handle large or deeply nested
|
|
72
|
+
* objects without risking stack overflow.
|
|
73
|
+
* - Handles circular references with a WeakMap to prevent infinite loops.
|
|
74
|
+
* - Unlike JSON.stringify, this function directly compares values, avoiding
|
|
75
|
+
* serialization overhead and leveraging short-circuit evaluation for faster
|
|
76
|
+
* failure on mismatched structures.
|
|
77
|
+
*
|
|
78
|
+
* ### Example
|
|
79
|
+
*
|
|
80
|
+
* ```ts
|
|
81
|
+
* const obj1: Json = { name: "Alice", hobbies: ["reading", "hiking"] };
|
|
82
|
+
* const obj2: Json = { name: "Alice", hobbies: ["reading", "hiking"] };
|
|
83
|
+
* console.log(eqJson(obj1, obj2)); // true
|
|
84
|
+
* ```
|
|
85
|
+
*/
|
|
86
|
+
export const eqJsonValue = (a, b) => {
|
|
87
|
+
const stack = [[a, b]];
|
|
88
|
+
const seen = new WeakMap();
|
|
89
|
+
while (stack.length > 0) {
|
|
90
|
+
const [x, y] = stack.pop();
|
|
91
|
+
if (x === y)
|
|
92
|
+
continue;
|
|
93
|
+
const typeX = typeof x;
|
|
94
|
+
const typeY = typeof y;
|
|
95
|
+
if (typeX !== typeY || x === null || y === null)
|
|
96
|
+
return false;
|
|
97
|
+
if (typeX === "number" && isNaN(x) && isNaN(y)) {
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
if (typeX === "object") {
|
|
101
|
+
const isArrayX = Array.isArray(x);
|
|
102
|
+
const isArrayY = Array.isArray(y);
|
|
103
|
+
if (isArrayX !== isArrayY)
|
|
104
|
+
return false;
|
|
105
|
+
const xObj = x;
|
|
106
|
+
const yObj = y;
|
|
107
|
+
if (seen.has(xObj)) {
|
|
108
|
+
const ySet = seen.get(xObj);
|
|
109
|
+
if (ySet.has(yObj)) {
|
|
110
|
+
continue;
|
|
111
|
+
}
|
|
112
|
+
ySet.add(yObj);
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
const ySet = new WeakSet();
|
|
116
|
+
ySet.add(yObj);
|
|
117
|
+
seen.set(xObj, ySet);
|
|
118
|
+
}
|
|
119
|
+
if (isArrayX && isArrayY) {
|
|
120
|
+
const xArr = x;
|
|
121
|
+
const yArr = y;
|
|
122
|
+
if (xArr.length !== yArr.length)
|
|
123
|
+
return false;
|
|
124
|
+
for (let i = 0; i < xArr.length; i++) {
|
|
125
|
+
stack.push([xArr[i], yArr[i]]);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
const xObjTyped = x;
|
|
130
|
+
const yObjTyped = y;
|
|
131
|
+
const xKeys = Object.keys(xObjTyped);
|
|
132
|
+
const yKeys = Object.keys(yObjTyped);
|
|
133
|
+
if (xKeys.length !== yKeys.length)
|
|
134
|
+
return false;
|
|
135
|
+
const yKeySet = new Set(yKeys);
|
|
136
|
+
for (const key of xKeys) {
|
|
137
|
+
if (!yKeySet.has(key))
|
|
138
|
+
return false;
|
|
139
|
+
stack.push([xObjTyped[key], yObjTyped[key]]);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
else {
|
|
144
|
+
return false;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
return true;
|
|
148
|
+
};
|
|
149
|
+
/**
|
|
150
|
+
* Deeply compares two {@link JsonValueInput} values for equality.
|
|
151
|
+
*
|
|
152
|
+
* - Uses an iterative approach with a stack to handle large or deeply nested
|
|
153
|
+
* objects without risking stack overflow.
|
|
154
|
+
* - Handles circular references with a WeakMap to prevent infinite loops.
|
|
155
|
+
* - Unlike JSON.stringify, this function directly compares values, avoiding
|
|
156
|
+
* serialization overhead and leveraging short-circuit evaluation for faster
|
|
157
|
+
* failure on mismatched structures.
|
|
158
|
+
*
|
|
159
|
+
* ### Example
|
|
160
|
+
*
|
|
161
|
+
* ```ts
|
|
162
|
+
* const obj1: Json = { name: "Alice", hobbies: ["reading", "hiking"] };
|
|
163
|
+
* const obj2: Json = { name: "Alice", hobbies: ["reading", "hiking"] };
|
|
164
|
+
* console.log(eqJson(obj1, obj2)); // true
|
|
165
|
+
* ```
|
|
166
|
+
*/
|
|
167
|
+
export const eqJsonValueInput = (a, b) => eqJsonValue(a, b);
|