@evolu/common 6.0.1-preview.19 → 6.0.1-preview.20

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.
Files changed (140) hide show
  1. package/dist/src/Assert.d.ts.map +1 -1
  2. package/dist/src/Assert.js +1 -1
  3. package/dist/src/Buffer.d.ts +1 -1
  4. package/dist/src/Buffer.d.ts.map +1 -1
  5. package/dist/src/Buffer.js +1 -1
  6. package/dist/src/CallbackRegistry.d.ts +53 -0
  7. package/dist/src/CallbackRegistry.d.ts.map +1 -0
  8. package/dist/src/CallbackRegistry.js +25 -0
  9. package/dist/src/Console.d.ts +31 -6
  10. package/dist/src/Console.d.ts.map +1 -1
  11. package/dist/src/Console.js +72 -9
  12. package/dist/src/Crypto.d.ts +48 -37
  13. package/dist/src/Crypto.d.ts.map +1 -1
  14. package/dist/src/Crypto.js +27 -50
  15. package/dist/src/Evolu/Db.d.ts +138 -66
  16. package/dist/src/Evolu/Db.d.ts.map +1 -1
  17. package/dist/src/Evolu/Db.js +248 -645
  18. package/dist/src/Evolu/Diff.d.ts +3 -3
  19. package/dist/src/Evolu/Diff.d.ts.map +1 -1
  20. package/dist/src/Evolu/Diff.js +7 -5
  21. package/dist/src/Evolu/Evolu.d.ts +79 -116
  22. package/dist/src/Evolu/Evolu.d.ts.map +1 -1
  23. package/dist/src/Evolu/Evolu.js +275 -132
  24. package/dist/src/Evolu/Internal.d.ts +0 -2
  25. package/dist/src/Evolu/Internal.d.ts.map +1 -1
  26. package/dist/src/Evolu/Internal.js +0 -2
  27. package/dist/src/Evolu/LocalAuth.d.ts +144 -0
  28. package/dist/src/Evolu/LocalAuth.d.ts.map +1 -0
  29. package/dist/src/Evolu/LocalAuth.js +171 -0
  30. package/dist/src/Evolu/Owner.d.ts +129 -83
  31. package/dist/src/Evolu/Owner.d.ts.map +1 -1
  32. package/dist/src/Evolu/Owner.js +80 -89
  33. package/dist/src/Evolu/Platform.d.ts +9 -7
  34. package/dist/src/Evolu/Platform.d.ts.map +1 -1
  35. package/dist/src/Evolu/Protocol.d.ts +114 -191
  36. package/dist/src/Evolu/Protocol.d.ts.map +1 -1
  37. package/dist/src/Evolu/Protocol.js +409 -416
  38. package/dist/src/Evolu/Public.d.ts +6 -8
  39. package/dist/src/Evolu/Public.d.ts.map +1 -1
  40. package/dist/src/Evolu/Public.js +2 -3
  41. package/dist/src/Evolu/PublicKysely.js +3 -3
  42. package/dist/src/Evolu/Relay.d.ts +1 -2
  43. package/dist/src/Evolu/Relay.d.ts.map +1 -1
  44. package/dist/src/Evolu/Relay.js +11 -9
  45. package/dist/src/Evolu/Schema.d.ts +88 -27
  46. package/dist/src/Evolu/Schema.d.ts.map +1 -1
  47. package/dist/src/Evolu/Schema.js +141 -24
  48. package/dist/src/Evolu/Storage.d.ts +158 -14
  49. package/dist/src/Evolu/Storage.d.ts.map +1 -1
  50. package/dist/src/Evolu/Storage.js +32 -32
  51. package/dist/src/Evolu/Sync.d.ts +77 -13
  52. package/dist/src/Evolu/Sync.d.ts.map +1 -1
  53. package/dist/src/Evolu/Sync.js +453 -20
  54. package/dist/src/Evolu/Timestamp.d.ts +29 -27
  55. package/dist/src/Evolu/Timestamp.d.ts.map +1 -1
  56. package/dist/src/Evolu/Timestamp.js +20 -18
  57. package/dist/src/ManyToManyMap.d.ts +74 -10
  58. package/dist/src/ManyToManyMap.d.ts.map +1 -1
  59. package/dist/src/ManyToManyMap.js +41 -6
  60. package/dist/src/Random.d.ts +3 -2
  61. package/dist/src/Random.d.ts.map +1 -1
  62. package/dist/src/RefCountedResourceManager.d.ts +119 -0
  63. package/dist/src/RefCountedResourceManager.d.ts.map +1 -0
  64. package/dist/src/RefCountedResourceManager.js +197 -0
  65. package/dist/src/Result.d.ts +144 -22
  66. package/dist/src/Result.d.ts.map +1 -1
  67. package/dist/src/Result.js +5 -2
  68. package/dist/src/Sqlite.d.ts +20 -4
  69. package/dist/src/Sqlite.d.ts.map +1 -1
  70. package/dist/src/Sqlite.js +50 -8
  71. package/dist/src/Task.d.ts +511 -0
  72. package/dist/src/Task.d.ts.map +1 -0
  73. package/dist/src/Task.js +410 -0
  74. package/dist/src/Time.d.ts +59 -0
  75. package/dist/src/Time.d.ts.map +1 -1
  76. package/dist/src/Time.js +87 -4
  77. package/dist/src/Type.d.ts +431 -341
  78. package/dist/src/Type.d.ts.map +1 -1
  79. package/dist/src/Type.js +458 -466
  80. package/dist/src/WebSocket.d.ts +5 -2
  81. package/dist/src/WebSocket.d.ts.map +1 -1
  82. package/dist/src/WebSocket.js +12 -13
  83. package/dist/src/Worker.d.ts +39 -11
  84. package/dist/src/Worker.d.ts.map +1 -1
  85. package/dist/src/Worker.js +22 -4
  86. package/dist/src/index.d.ts +2 -3
  87. package/dist/src/index.d.ts.map +1 -1
  88. package/dist/src/index.js +2 -3
  89. package/package.json +7 -7
  90. package/src/Assert.ts +2 -4
  91. package/src/Buffer.ts +1 -1
  92. package/src/CallbackRegistry.ts +84 -0
  93. package/src/Console.ts +91 -11
  94. package/src/Crypto.ts +78 -91
  95. package/src/Evolu/Db.ts +455 -947
  96. package/src/Evolu/Diff.ts +7 -5
  97. package/src/Evolu/Evolu.ts +545 -307
  98. package/src/Evolu/Internal.ts +0 -2
  99. package/src/Evolu/LocalAuth.ts +422 -0
  100. package/src/Evolu/Owner.ts +191 -131
  101. package/src/Evolu/Platform.ts +9 -9
  102. package/src/Evolu/Protocol.ts +536 -653
  103. package/src/Evolu/Public.ts +7 -9
  104. package/src/Evolu/PublicKysely.ts +3 -3
  105. package/src/Evolu/Relay.ts +17 -12
  106. package/src/Evolu/Schema.ts +271 -66
  107. package/src/Evolu/Storage.ts +263 -55
  108. package/src/Evolu/Sync.ts +758 -37
  109. package/src/Evolu/Timestamp.ts +30 -35
  110. package/src/ManyToManyMap.ts +127 -24
  111. package/src/Random.ts +3 -2
  112. package/src/RefCountedResourceManager.ts +368 -0
  113. package/src/Result.ts +149 -23
  114. package/src/Sqlite.ts +59 -24
  115. package/src/Task.ts +779 -0
  116. package/src/Time.ts +168 -4
  117. package/src/Type.ts +657 -695
  118. package/src/WebSocket.ts +23 -17
  119. package/src/Worker.ts +72 -23
  120. package/src/index.ts +2 -3
  121. package/dist/src/Callbacks.d.ts +0 -20
  122. package/dist/src/Callbacks.d.ts.map +0 -1
  123. package/dist/src/Callbacks.js +0 -18
  124. package/dist/src/Evolu/Config.d.ts +0 -82
  125. package/dist/src/Evolu/Config.d.ts.map +0 -1
  126. package/dist/src/Evolu/Config.js +0 -9
  127. package/dist/src/Evolu/Kysely.d.ts +0 -6
  128. package/dist/src/Evolu/Kysely.d.ts.map +0 -1
  129. package/dist/src/Evolu/Kysely.js +0 -21
  130. package/dist/src/NanoId.d.ts +0 -27
  131. package/dist/src/NanoId.d.ts.map +0 -1
  132. package/dist/src/NanoId.js +0 -6
  133. package/dist/src/Promise.d.ts +0 -180
  134. package/dist/src/Promise.d.ts.map +0 -1
  135. package/dist/src/Promise.js +0 -176
  136. package/src/Callbacks.ts +0 -43
  137. package/src/Evolu/Config.ts +0 -97
  138. package/src/Evolu/Kysely.ts +0 -38
  139. package/src/NanoId.ts +0 -39
  140. package/src/Promise.ts +0 -295
package/src/Crypto.ts CHANGED
@@ -3,53 +3,65 @@
3
3
  *
4
4
  * @module
5
5
  */
6
-
7
- import { xchacha20poly1305 } from "@noble/ciphers/chacha";
8
- import { hmac } from "@noble/hashes/hmac";
9
- import { sha512 } from "@noble/hashes/sha2";
10
- import { randomBytes } from "@noble/hashes/utils";
11
- import * as bip39 from "@scure/bip39";
12
- import { wordlist } from "@scure/bip39/wordlists/english";
13
- import { urlAlphabet } from "nanoid";
14
- import { getOrThrow, Result, trySync } from "./Result.js";
15
- import {
16
- brand,
17
- Id,
18
- length,
19
- Mnemonic,
20
- NonNegativeInt,
21
- Uint8Array,
22
- } from "./Type.js";
23
- import { Brand } from "./Brand.js";
24
- import { assert } from "./Assert.js";
25
- import { utf8ToBytes } from "./Buffer.js";
26
-
27
- /** `Uint8Array` created by {@link createRandomBytes}. */
28
- export type RandomBytes = Uint8Array & Brand<"RandomBytes">;
29
-
30
- export type CreateRandomBytes = (bytesLength?: number) => RandomBytes;
31
-
32
- export interface CreateRandomBytesDep {
33
- readonly createRandomBytes: CreateRandomBytes;
6
+ import { xchacha20poly1305 } from "@noble/ciphers/chacha.js";
7
+ import { hmac } from "@noble/hashes/hmac.js";
8
+ import { sha512 } from "@noble/hashes/sha2.js";
9
+ import { randomBytes, utf8ToBytes } from "@noble/hashes/utils.js";
10
+ import { Result, trySync } from "./Result.js";
11
+ import { brand, length, NonNegativeInt, Uint8Array } from "./Type.js";
12
+
13
+ export interface RandomBytes {
14
+ /**
15
+ * Creates cryptographically secure random bytes with type-safe length
16
+ * branding.
17
+ *
18
+ * Uses the operating system's cryptographically secure random number
19
+ * generator (crypto.getRandomValues) to generate high-quality entropy
20
+ * suitable for cryptographic operations.
21
+ *
22
+ * ### Type Safety
23
+ *
24
+ * Returns specific branded types for common sizes:
25
+ *
26
+ * - `Random16` for 16-byte values (128 bits)
27
+ * - `Random32` for 32-byte values (256 bits)
28
+ * - `Random64` for 64-byte values (512 bits)
29
+ * - `Random` for any other size
30
+ *
31
+ * ### Example
32
+ *
33
+ * ```ts
34
+ * const nonce = randomBytes.create(16); // Type: Random16
35
+ * const key = randomBytes.create(32); // Type: Random32
36
+ * const seed = randomBytes.create(64); // Type: Random64
37
+ * const custom = randomBytes.create(48); // Type: Random
38
+ * ```
39
+ */
40
+ create(bytesLength: 16): Entropy16;
41
+ create(bytesLength: 32): Entropy32;
42
+ create(bytesLength: 64): Entropy64;
43
+ create(bytesLength: number): Entropy;
34
44
  }
35
45
 
36
- /** Cryptographically secure PRNG. Uses internal OS-level crypto.getRandomValues. */
37
- export const createRandomBytes: CreateRandomBytes = (bytesLength = 32) =>
38
- randomBytes(bytesLength) as RandomBytes;
46
+ export interface RandomBytesDep {
47
+ readonly randomBytes: RandomBytes;
48
+ }
39
49
 
40
- export type CreateMnemonic = () => Mnemonic;
50
+ const Entropy = brand("Entropy", Uint8Array);
51
+ type Entropy = typeof Entropy.Type;
41
52
 
42
- export interface CreateMnemonicDep {
43
- readonly createMnemonic: CreateMnemonic;
44
- }
53
+ export const Entropy16 = length(16)(Entropy);
54
+ export type Entropy16 = typeof Entropy16.Type;
45
55
 
46
- export const createEnglishMnemonic: CreateMnemonic = () =>
47
- bip39.generateMnemonic(wordlist, 128) as Mnemonic;
56
+ export const Entropy32 = length(32)(Entropy);
57
+ export type Entropy32 = typeof Entropy32.Type;
48
58
 
49
- export type MnemonicSeed = Uint8Array & Brand<"MnemonicSeed">;
59
+ export const Entropy64 = length(64)(Entropy);
60
+ export type Entropy64 = typeof Entropy64.Type;
50
61
 
51
- export const mnemonicToMnemonicSeed = (mnemonic: Mnemonic): MnemonicSeed =>
52
- bip39.mnemonicToSeedSync(mnemonic) as MnemonicSeed;
62
+ export const createRandomBytes = (): RandomBytes => ({
63
+ create: randomBytes as RandomBytes["create"],
64
+ });
53
65
 
54
66
  /**
55
67
  * SLIP21.
@@ -57,19 +69,21 @@ export const mnemonicToMnemonicSeed = (mnemonic: Mnemonic): MnemonicSeed =>
57
69
  * https://github.com/satoshilabs/slips/blob/master/slip-0021.md
58
70
  */
59
71
  export const createSlip21 = (
60
- seed: Uint8Array,
61
- path: ReadonlyArray<string>,
62
- ): Uint8Array => {
63
- assert(
64
- seed.length >= 16 && seed.length <= 64,
65
- `Unusual SLIP-0021 seed length: ${seed.length} bytes`,
66
- );
67
-
68
- let m = hmac(sha512, utf8ToBytes("Symmetric key seed"), seed);
69
- for (const component of path) {
70
- m = deriveSlip21Node(component, m);
72
+ seed: Entropy16 | Entropy32 | Entropy64,
73
+ path: ReadonlyArray<string | number>,
74
+ ): Entropy32 => {
75
+ let currentNode = hmac(
76
+ sha512,
77
+ utf8ToBytes("Symmetric key seed"),
78
+ seed,
79
+ ) as Entropy64;
80
+
81
+ for (const element of path) {
82
+ const label = typeof element === "number" ? element.toString() : element;
83
+ currentNode = deriveSlip21Node(label, currentNode);
71
84
  }
72
- return m.slice(32, 64);
85
+
86
+ return currentNode.slice(32, 64) as Entropy32;
73
87
  };
74
88
 
75
89
  /**
@@ -78,45 +92,18 @@ export const createSlip21 = (
78
92
  * @see {@link createSlip21}
79
93
  */
80
94
  export const deriveSlip21Node = (
81
- component: string,
82
- m: Uint8Array,
83
- ): Uint8Array => {
84
- const p = utf8ToBytes(component);
85
- const e = new globalThis.Uint8Array(p.byteLength + 1);
86
- e[0] = 0;
87
- e.set(p, 1);
88
- return hmac(sha512, m.slice(0, 32), e);
89
- };
90
-
91
- /**
92
- * Creates a 21-character Base64URL ID (also known as nanoid) from a SLIP-21
93
- * derived key.
94
- *
95
- * Reduces the 256-bit SLIP-21 output to 126 bits (21 chars × 6 bits) for a
96
- * compact, human-readable, and shareable identifier suitable for UI display or
97
- * URL use. While this lowers entropy, 126 bits remains cryptographically secure
98
- * for uniqueness and unpredictability in most applications (comparable to
99
- * UUIDv4's 122 bits).
100
- *
101
- * See https://github.com/satoshilabs/slips/blob/master/slip-0021.md
102
- */
103
- export const createSlip21Id = (
104
- seed: MnemonicSeed,
105
- path: ReadonlyArray<string>,
106
- ): Id => {
107
- const slip21 = createSlip21(seed, path);
108
- let id = "" as Id;
109
-
110
- // Convert the key to the Id/NanoId/Base64Url format.
111
- for (let i = 0; i < 21; i++) {
112
- id = (id + urlAlphabet[slip21[i] & 63]) as Id;
113
- }
114
-
115
- return id;
95
+ label: string,
96
+ parentNode: Entropy64,
97
+ ): Entropy64 => {
98
+ const labelBytes = utf8ToBytes(label);
99
+ const message = new globalThis.Uint8Array(labelBytes.byteLength + 1);
100
+ message[0] = 0;
101
+ message.set(labelBytes, 1);
102
+ return hmac(sha512, parentNode.slice(0, 32), message) as Entropy64;
116
103
  };
117
104
 
118
105
  /** The encryption key for {@link SymmetricCrypto}. */
119
- export const EncryptionKey = brand("EncryptionKey", length(32)(Uint8Array));
106
+ export const EncryptionKey = brand("EncryptionKey", Entropy32);
120
107
  export type EncryptionKey = typeof EncryptionKey.Type;
121
108
 
122
109
  /** Symmetric cryptography. */
@@ -153,15 +140,15 @@ export interface SymmetricCryptoDecryptError {
153
140
  * https://github.com/paulmillr/noble-ciphers?tab=readme-ov-file#which-cipher-should-i-pick
154
141
  */
155
142
  export const createSymmetricCrypto = (
156
- deps: CreateRandomBytesDep,
143
+ deps: RandomBytesDep,
157
144
  ): SymmetricCrypto => {
158
- const nonceLength = getOrThrow(NonNegativeInt.from(24));
145
+ const nonceLength = NonNegativeInt.orThrow(24);
159
146
 
160
147
  const symmetricCrypto: SymmetricCrypto = {
161
148
  nonceLength,
162
149
 
163
150
  encrypt: (plaintext, encryptionKey) => {
164
- const nonce = deps.createRandomBytes(nonceLength);
151
+ const nonce = deps.randomBytes.create(nonceLength);
165
152
  const ciphertext = xchacha20poly1305(encryptionKey, nonce).encrypt(
166
153
  plaintext,
167
154
  );