@evolu/common 8.0.0-next.4 → 8.0.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.
Files changed (237) hide show
  1. package/dist/src/Array.d.ts +279 -173
  2. package/dist/src/Array.d.ts.map +1 -1
  3. package/dist/src/Array.js +105 -101
  4. package/dist/src/Assert.d.ts +44 -44
  5. package/dist/src/Assert.d.ts.map +1 -1
  6. package/dist/src/Assert.js +44 -32
  7. package/dist/src/BigInt.d.ts +6 -3
  8. package/dist/src/BigInt.d.ts.map +1 -1
  9. package/dist/src/BigInt.js +5 -2
  10. package/dist/src/Brand.d.ts +27 -40
  11. package/dist/src/Brand.d.ts.map +1 -1
  12. package/dist/src/Buffer.d.ts +27 -11
  13. package/dist/src/Buffer.d.ts.map +1 -1
  14. package/dist/src/Cache.d.ts +9 -4
  15. package/dist/src/Cache.d.ts.map +1 -1
  16. package/dist/src/Cache.js +8 -3
  17. package/dist/src/Callbacks.d.ts +30 -19
  18. package/dist/src/Callbacks.d.ts.map +1 -1
  19. package/dist/src/Console.d.ts +145 -66
  20. package/dist/src/Console.d.ts.map +1 -1
  21. package/dist/src/Console.js +91 -43
  22. package/dist/src/Crypto.d.ts +85 -42
  23. package/dist/src/Crypto.d.ts.map +1 -1
  24. package/dist/src/Crypto.js +44 -20
  25. package/dist/src/Eq.d.ts +87 -21
  26. package/dist/src/Eq.d.ts.map +1 -1
  27. package/dist/src/Eq.js +67 -19
  28. package/dist/src/Error.d.ts +5 -3
  29. package/dist/src/Error.d.ts.map +1 -1
  30. package/dist/src/Error.js +16 -0
  31. package/dist/src/Function.d.ts +119 -58
  32. package/dist/src/Function.d.ts.map +1 -1
  33. package/dist/src/Function.js +86 -43
  34. package/dist/src/Http.d.ts +394 -0
  35. package/dist/src/Http.d.ts.map +1 -0
  36. package/dist/src/Http.js +102 -0
  37. package/dist/src/Identicon.d.ts +16 -7
  38. package/dist/src/Identicon.d.ts.map +1 -1
  39. package/dist/src/Identicon.js +14 -5
  40. package/dist/src/LeakDetector.d.ts +88 -0
  41. package/dist/src/LeakDetector.d.ts.map +1 -0
  42. package/dist/src/LeakDetector.js +86 -0
  43. package/dist/src/LockManager.d.ts +18 -9
  44. package/dist/src/LockManager.d.ts.map +1 -1
  45. package/dist/src/LockManager.js +7 -8
  46. package/dist/src/Lookup.d.ts +43 -13
  47. package/dist/src/Lookup.d.ts.map +1 -1
  48. package/dist/src/Lookup.js +28 -8
  49. package/dist/src/Microtask.d.ts +1 -1
  50. package/dist/src/Microtask.d.ts.map +1 -1
  51. package/dist/src/Microtask.js +3 -7
  52. package/dist/src/Number.d.ts +49 -13
  53. package/dist/src/Number.d.ts.map +1 -1
  54. package/dist/src/Number.js +34 -5
  55. package/dist/src/Object.d.ts +160 -40
  56. package/dist/src/Object.d.ts.map +1 -1
  57. package/dist/src/Object.js +92 -46
  58. package/dist/src/Option.d.ts +10 -7
  59. package/dist/src/Option.d.ts.map +1 -1
  60. package/dist/src/Option.js +9 -6
  61. package/dist/src/Order.d.ts +21 -21
  62. package/dist/src/Order.d.ts.map +1 -1
  63. package/dist/src/Order.js +18 -21
  64. package/dist/src/Platform.d.ts +31 -0
  65. package/dist/src/Platform.d.ts.map +1 -1
  66. package/dist/src/Platform.js +98 -0
  67. package/dist/src/Random.d.ts +32 -17
  68. package/dist/src/Random.d.ts.map +1 -1
  69. package/dist/src/Random.js +12 -8
  70. package/dist/src/Redacted.d.ts +43 -29
  71. package/dist/src/Redacted.d.ts.map +1 -1
  72. package/dist/src/Redacted.js +14 -3
  73. package/dist/src/Ref.d.ts +11 -3
  74. package/dist/src/Ref.d.ts.map +1 -1
  75. package/dist/src/Ref.js +2 -2
  76. package/dist/src/RefCount.d.ts +2 -6
  77. package/dist/src/RefCount.d.ts.map +1 -1
  78. package/dist/src/RefCount.js +33 -90
  79. package/dist/src/Relation.d.ts +70 -5
  80. package/dist/src/Relation.d.ts.map +1 -1
  81. package/dist/src/Relation.js +77 -2
  82. package/dist/src/Resource.d.ts +590 -155
  83. package/dist/src/Resource.d.ts.map +1 -1
  84. package/dist/src/Resource.js +592 -343
  85. package/dist/src/Result.d.ts +838 -191
  86. package/dist/src/Result.d.ts.map +1 -1
  87. package/dist/src/Result.js +163 -102
  88. package/dist/src/Schedule.d.ts +684 -231
  89. package/dist/src/Schedule.d.ts.map +1 -1
  90. package/dist/src/Schedule.js +766 -295
  91. package/dist/src/Set.d.ts +89 -40
  92. package/dist/src/Set.d.ts.map +1 -1
  93. package/dist/src/Set.js +50 -29
  94. package/dist/src/Sqlite.d.ts +29 -72
  95. package/dist/src/Sqlite.d.ts.map +1 -1
  96. package/dist/src/Sqlite.js +41 -46
  97. package/dist/src/StackTrace.d.ts +40 -0
  98. package/dist/src/StackTrace.d.ts.map +1 -0
  99. package/dist/src/StackTrace.js +140 -0
  100. package/dist/src/Store.d.ts +5 -4
  101. package/dist/src/Store.d.ts.map +1 -1
  102. package/dist/src/Store.js +5 -4
  103. package/dist/src/String.d.ts +7 -1
  104. package/dist/src/String.d.ts.map +1 -1
  105. package/dist/src/String.js +20 -7
  106. package/dist/src/Task.d.ts +3572 -1770
  107. package/dist/src/Task.d.ts.map +1 -1
  108. package/dist/src/Task.js +1879 -1274
  109. package/dist/src/Test.d.ts +17 -125
  110. package/dist/src/Test.d.ts.map +1 -1
  111. package/dist/src/Test.js +17 -68
  112. package/dist/src/Time.d.ts +108 -49
  113. package/dist/src/Time.d.ts.map +1 -1
  114. package/dist/src/Time.js +172 -73
  115. package/dist/src/Type.d.ts +3542 -1926
  116. package/dist/src/Type.d.ts.map +1 -1
  117. package/dist/src/Type.js +3070 -1784
  118. package/dist/src/Types.d.ts +200 -108
  119. package/dist/src/Types.d.ts.map +1 -1
  120. package/dist/src/Types.js +39 -8
  121. package/dist/src/WebSocket.d.ts +48 -23
  122. package/dist/src/WebSocket.d.ts.map +1 -1
  123. package/dist/src/WebSocket.js +15 -6
  124. package/dist/src/Worker.d.ts +94 -36
  125. package/dist/src/Worker.d.ts.map +1 -1
  126. package/dist/src/Worker.js +58 -24
  127. package/dist/src/index.d.ts +55 -52
  128. package/dist/src/index.d.ts.map +1 -1
  129. package/dist/src/index.js +3 -1
  130. package/dist/src/intl/cs.d.ts +94 -0
  131. package/dist/src/intl/cs.d.ts.map +1 -0
  132. package/dist/src/intl/cs.js +220 -0
  133. package/dist/src/intl/index.d.ts +7 -0
  134. package/dist/src/intl/index.d.ts.map +1 -0
  135. package/dist/src/intl/index.js +6 -0
  136. package/dist/src/local-first/Db.d.ts +12 -8
  137. package/dist/src/local-first/Db.d.ts.map +1 -1
  138. package/dist/src/local-first/Db.js +109 -132
  139. package/dist/src/local-first/Error.d.ts +4 -4
  140. package/dist/src/local-first/Evolu.d.ts +338 -92
  141. package/dist/src/local-first/Evolu.d.ts.map +1 -1
  142. package/dist/src/local-first/Evolu.js +47 -55
  143. package/dist/src/local-first/LocalAuth.d.ts +4 -4
  144. package/dist/src/local-first/LocalAuth.d.ts.map +1 -1
  145. package/dist/src/local-first/Owner.d.ts +61 -24
  146. package/dist/src/local-first/Owner.d.ts.map +1 -1
  147. package/dist/src/local-first/Owner.js +45 -8
  148. package/dist/src/local-first/Protocol.d.ts +44 -31
  149. package/dist/src/local-first/Protocol.d.ts.map +1 -1
  150. package/dist/src/local-first/Protocol.js +36 -13
  151. package/dist/src/local-first/Query.d.ts +147 -62
  152. package/dist/src/local-first/Query.d.ts.map +1 -1
  153. package/dist/src/local-first/Query.js +112 -58
  154. package/dist/src/local-first/Relay.d.ts +44 -14
  155. package/dist/src/local-first/Relay.d.ts.map +1 -1
  156. package/dist/src/local-first/Schema.d.ts +92 -41
  157. package/dist/src/local-first/Schema.d.ts.map +1 -1
  158. package/dist/src/local-first/Schema.js +25 -8
  159. package/dist/src/local-first/Shared.d.ts +23 -21
  160. package/dist/src/local-first/Shared.d.ts.map +1 -1
  161. package/dist/src/local-first/Shared.js +100 -57
  162. package/dist/src/local-first/Storage.d.ts +53 -32
  163. package/dist/src/local-first/Storage.d.ts.map +1 -1
  164. package/dist/src/local-first/Storage.js +194 -234
  165. package/dist/src/local-first/Timestamp.d.ts +21 -21
  166. package/dist/src/local-first/Timestamp.d.ts.map +1 -1
  167. package/dist/src/local-first/Timestamp.js +2 -2
  168. package/dist/src/local-first/index.d.ts +11 -11
  169. package/package.json +14 -13
  170. package/src/Array.ts +306 -205
  171. package/src/Assert.ts +54 -69
  172. package/src/BigInt.ts +6 -3
  173. package/src/Brand.ts +27 -40
  174. package/src/Buffer.ts +28 -12
  175. package/src/Cache.ts +9 -4
  176. package/src/Callbacks.ts +30 -19
  177. package/src/Console.ts +156 -84
  178. package/src/Crypto.ts +83 -41
  179. package/src/Eq.ts +95 -22
  180. package/src/Error.ts +8 -4
  181. package/src/Function.ts +167 -59
  182. package/src/Http.ts +549 -0
  183. package/src/Identicon.ts +16 -7
  184. package/src/LeakDetector.ts +182 -0
  185. package/src/LockManager.ts +43 -39
  186. package/src/Lookup.ts +62 -28
  187. package/src/Microtask.ts +19 -23
  188. package/src/Number.ts +64 -12
  189. package/src/Object.ts +173 -49
  190. package/src/Option.ts +10 -7
  191. package/src/Order.ts +23 -21
  192. package/src/Platform.ts +136 -0
  193. package/src/Polyfills.ts +6 -12
  194. package/src/Random.ts +32 -19
  195. package/src/Redacted.ts +44 -30
  196. package/src/Ref.ts +14 -6
  197. package/src/RefCount.ts +38 -80
  198. package/src/Relation.ts +202 -10
  199. package/src/Resource.ts +1199 -591
  200. package/src/Result.ts +930 -271
  201. package/src/Schedule.ts +859 -343
  202. package/src/Set.ts +89 -40
  203. package/src/Sqlite.ts +144 -138
  204. package/src/StackTrace.ts +230 -0
  205. package/src/Store.ts +8 -7
  206. package/src/String.ts +22 -5
  207. package/src/Task.ts +5101 -2832
  208. package/src/Test.ts +20 -168
  209. package/src/Time.ts +293 -90
  210. package/src/Type.ts +10034 -4117
  211. package/src/Types.ts +227 -110
  212. package/src/WebSocket.ts +64 -36
  213. package/src/Worker.ts +180 -72
  214. package/src/index.ts +55 -52
  215. package/src/intl/cs.ts +388 -0
  216. package/src/intl/index.ts +7 -0
  217. package/src/local-first/Db.ts +152 -179
  218. package/src/local-first/Error.ts +4 -4
  219. package/src/local-first/Evolu.ts +495 -250
  220. package/src/local-first/LocalAuth.ts +6 -12
  221. package/src/local-first/Owner.ts +58 -21
  222. package/src/local-first/Protocol.ts +49 -31
  223. package/src/local-first/Query.ts +146 -61
  224. package/src/local-first/Relay.ts +51 -21
  225. package/src/local-first/Schema.ts +109 -51
  226. package/src/local-first/Shared.ts +266 -226
  227. package/src/local-first/Storage.ts +266 -264
  228. package/src/local-first/Timestamp.ts +25 -18
  229. package/src/local-first/index.ts +11 -11
  230. package/dist/src/Skiplist.d.ts +0 -28
  231. package/dist/src/Skiplist.d.ts.map +0 -1
  232. package/dist/src/Skiplist.js +0 -64
  233. package/dist/src/Tracer.d.ts +0 -48
  234. package/dist/src/Tracer.d.ts.map +0 -1
  235. package/dist/src/Tracer.js +0 -6
  236. package/src/Skiplist.ts +0 -108
  237. package/src/Tracer.ts +0 -54
@@ -20,15 +20,20 @@ export type ReadonlyRecord<K extends keyof any, V> = Readonly<Record<K, V>>;
20
20
  * Object.prototype` so it also works for plain objects coming from another
21
21
  * JavaScript realm.
22
22
  *
23
+ * TODO: deprecated Use `Object.is` from Type. Define a dedicated Type when
24
+ * another object domain is required.
25
+ *
23
26
  * ### Example
24
27
  *
25
28
  * ```ts
26
- * isPlainObject({}); // true
27
- * isPlainObject(Object.create(null)); // true
28
- * isPlainObject(new Date()); // false
29
- * isPlainObject(new (class Example {})()); // false
30
- * isPlainObject([]); // false
31
- * isPlainObject(null); // false
29
+ * import { isPlainObject } from "@evolu/common";
30
+ *
31
+ * expect(isPlainObject({})).toBe(true);
32
+ * expect(isPlainObject(Object.create(null))).toBe(true);
33
+ * expect(isPlainObject(new Date())).toBe(false);
34
+ * expect(isPlainObject(new (class Example {})())).toBe(false);
35
+ * expect(isPlainObject([])).toBe(false);
36
+ * expect(isPlainObject(null)).toBe(false);
32
37
  * ```
33
38
  */
34
39
  export declare const isPlainObject: (value: unknown) => value is Record<string, unknown>;
@@ -38,9 +43,11 @@ export declare const isPlainObject: (value: unknown) => value is Record<string,
38
43
  * ### Example
39
44
  *
40
45
  * ```ts
41
- * isFunction(() => {}); // true
42
- * isFunction(function () {}); // true
43
- * isFunction({}); // false
46
+ * import { isFunction } from "@evolu/common";
47
+ *
48
+ * expect(isFunction(() => {})).toBe(true);
49
+ * expect(isFunction(function () {})).toBe(true);
50
+ * expect(isFunction({})).toBe(false);
44
51
  * ```
45
52
  */
46
53
  export declare const isFunction: (value: unknown) => value is globalThis.Function;
@@ -50,9 +57,11 @@ export declare const isFunction: (value: unknown) => value is globalThis.Functio
50
57
  * ### Example
51
58
  *
52
59
  * ```ts
53
- * isIterable([1, 2, 3]); // true
54
- * isIterable("abc"); // true
55
- * isIterable({}); // false
60
+ * import { isIterable } from "@evolu/common";
61
+ *
62
+ * expect(isIterable([1, 2, 3])).toBe(true);
63
+ * expect(isIterable("abc")).toBe(true);
64
+ * expect(isIterable({})).toBe(false);
56
65
  * ```
57
66
  */
58
67
  export declare const isIterable: (value: unknown) => value is Iterable<unknown>;
@@ -62,9 +71,20 @@ export declare const isIterable: (value: unknown) => value is Iterable<unknown>;
62
71
  * ### Example
63
72
  *
64
73
  * ```ts
65
- * type UserId = string & { readonly __brand: "UserId" };
66
- * const users = createRecord<UserId, string>();
67
- * const entries = objectToEntries(users); // [UserId, string][]
74
+ * import {
75
+ * objectToEntries,
76
+ * type Brand,
77
+ * type ReadonlyRecord,
78
+ * } from "@evolu/common";
79
+ *
80
+ * type UserId = string & Brand<"UserId">;
81
+ *
82
+ * const userId = "u1" as UserId;
83
+ * const users: ReadonlyRecord<UserId, string> = { [userId]: "Alice" };
84
+ * const entries = objectToEntries(users);
85
+ *
86
+ * expectTypeOf(entries).toEqualTypeOf<ReadonlyArray<[UserId, string]>>();
87
+ * expect(entries).toEqual([[userId, "Alice"]]);
68
88
  * ```
69
89
  */
70
90
  export declare const objectToEntries: <T extends Record<string, any>>(record: T) => ReadonlyArray<[StringKeyOf<T>, T[StringKeyOf<T>]]>;
@@ -78,11 +98,20 @@ type StringKeyOf<T> = Extract<keyof T, string>;
78
98
  * ### Example
79
99
  *
80
100
  * ```ts
81
- * type UserId = string & { readonly __brand: "UserId" };
101
+ * import {
102
+ * objectFromEntries,
103
+ * type Brand,
104
+ * type ReadonlyRecord,
105
+ * } from "@evolu/common";
106
+ *
107
+ * type UserId = string & Brand<"UserId">;
82
108
  * const entries: ReadonlyArray<[UserId, string]> = [
83
109
  * ["u1" as UserId, "Alice"],
84
110
  * ];
85
- * const users = objectFromEntries(entries); // ReadonlyRecord<UserId, string>
111
+ * const users = objectFromEntries(entries);
112
+ *
113
+ * expectTypeOf(users).toEqualTypeOf<ReadonlyRecord<UserId, string>>();
114
+ * expect(users).toEqual({ u1: "Alice" });
86
115
  * ```
87
116
  */
88
117
  export declare const objectFromEntries: <K extends string, V>(entries: Iterable<readonly [K, V]>) => ReadonlyRecord<K, V>;
@@ -95,11 +124,20 @@ export declare const objectFromEntries: <K extends string, V>(entries: Iterable<
95
124
  * ### Example
96
125
  *
97
126
  * ```ts
98
- * objectFrom(["en", "fr", "de"], loadTranslations);
99
- * // { en: Translations, fr: Translations, de: Translations }
127
+ * import { objectFrom, type ReadonlyRecord } from "@evolu/common";
100
128
  *
101
- * objectFrom(["trace", "debug", "log"], (level) => createHandler(level));
102
- * // { trace: Handler, debug: Handler, log: Handler }
129
+ * const translations = objectFrom(
130
+ * ["en", "fr"] as const,
131
+ * (locale): string => `Hello in ${locale}`,
132
+ * );
133
+ *
134
+ * expectTypeOf(translations).toEqualTypeOf<
135
+ * ReadonlyRecord<"en" | "fr", string>
136
+ * >();
137
+ * expect(translations).toEqual({
138
+ * en: "Hello in en",
139
+ * fr: "Hello in fr",
140
+ * });
103
141
  * ```
104
142
  */
105
143
  export declare const objectFrom: <K extends string, V>(keys: ReadonlyArray<K>, getValue: (key: K) => V) => ReadonlyRecord<K, V>;
@@ -112,44 +150,123 @@ export declare const mapObject: <K extends string, V, U>(record: ReadonlyRecord<
112
150
  /** Conditionally excludes a property from an object. */
113
151
  export declare const excludeProp: <T extends object, K extends keyof T>(obj: T, prop: K, condition?: boolean) => typeof condition extends true ? T : Omit<T, K>;
114
152
  /**
115
- * Creates a prototype-less object typed as `Record<K, V>`.
153
+ * Creates a mutable Record.
154
+ *
155
+ * Use it to build a Record locally through mutation, avoiding repeated object
156
+ * spreads. Keep mutation scoped to the constructing function, and treat the
157
+ * completed Record as immutable after it leaves that scope. When a source is
158
+ * provided, its own enumerable properties are shallow-copied. Inherited and
159
+ * non-enumerable properties are not copied.
160
+ *
161
+ * The Record is created with `Object.create(null)`, so any string can be used
162
+ * as a key while it is being built. Missing keys such as `toString` and
163
+ * `constructor` do not resolve to inherited values, and assigning `__proto__`
164
+ * creates an own data property instead of changing the prototype.
165
+ *
166
+ * The null prototype makes dynamic construction safer, but it does not have to
167
+ * be preserved. Spreading the completed Record into an ordinary object is
168
+ * supported. Use {@link getOwnProp} when a lookup must read only own
169
+ * properties.
170
+ *
171
+ * For immutable empty application data, defaults, or placeholders, use
172
+ * {@link emptyRecord}.
173
+ *
174
+ * ### Example
175
+ *
176
+ * ```ts
177
+ * import { createMutableRecord } from "@evolu/common";
116
178
  *
117
- * Use this function when you need a plain record without a prototype chain
118
- * (e.g. when keys are controlled by external sources) to avoid prototype
119
- * pollution and accidental collisions with properties like `__proto__`.
179
+ * const createValuesByKey = (
180
+ * entries: ReadonlyArray<readonly [string, number]>,
181
+ * ): Readonly<Record<string, number>> => {
182
+ * const valuesByKey = createMutableRecord<string, number>();
120
183
  *
121
- * Example:
184
+ * for (const [key, value] of entries) {
185
+ * valuesByKey[key] = value;
186
+ * }
187
+ *
188
+ * return valuesByKey;
189
+ * };
190
+ *
191
+ * expect(
192
+ * createValuesByKey([
193
+ * ["a", 1],
194
+ * ["b", 2],
195
+ * ]),
196
+ * ).toEqual({ a: 1, b: 2 });
197
+ * ```
198
+ *
199
+ * Note that TypeScript does not model an object's runtime prototype. A plain
200
+ * TypeScript Record exposes `Object.prototype` members even when the runtime
201
+ * object has a `null` prototype:
202
+ *
203
+ * ```ts
204
+ * const values = Object.create(null) as Record<string, number>;
205
+ *
206
+ * // TypeScript accepts the call, but `toString` is undefined at runtime.
207
+ * expect(() => values.toString()).toThrow(TypeError);
208
+ * ```
209
+ *
210
+ * `createMutableRecord` uses the same TypeScript Record representation.
122
211
  *
123
212
  * ```ts
124
- * const values = createRecord<string, SqliteValue>();
125
- * values["__proto__"] = someValue; // safe, no prototype pollution
213
+ * import { createMutableRecord } from "@evolu/common";
214
+ *
215
+ * const values = createMutableRecord<string, number>();
216
+ *
217
+ * // TypeScript accepts the call, but `toString` is undefined at runtime.
218
+ * expect(() => values.toString()).toThrow(TypeError);
126
219
  * ```
220
+ *
221
+ * In other words, treat the returned object as string-keyed data rather than
222
+ * calling inherited object methods through it.
127
223
  */
128
- export declare const createRecord: <K extends string = string, V = unknown>() => Record<K, V>;
224
+ export declare function createMutableRecord<K extends string = string, V = unknown>(): Record<K, V>;
225
+ export declare function createMutableRecord<T extends object>(source: T): {
226
+ -readonly [K in keyof T]: T[K];
227
+ };
129
228
  /**
130
- * An empty readonly record.
229
+ * A shared frozen empty readonly Record.
131
230
  *
132
- * Use as a default or initial value to avoid allocating new empty records.
231
+ * Use it as an immutable empty value for defaults and placeholders instead of
232
+ * allocating a new empty object. Because the instance is shared, it is frozen
233
+ * to prevent accidental mutation.
234
+ *
235
+ * Use {@link createMutableRecord} to build a Record locally through mutation
236
+ * instead of repeated object spreads.
133
237
  *
134
238
  * @group Constants
135
239
  */
136
240
  export declare const emptyRecord: Readonly<Record<string, never>>;
137
241
  /**
138
- * Safely gets a property from a record, returning `undefined` if the key
139
- * doesn't exist.
242
+ * Gets an own property from a record, returning `undefined` if the key is
243
+ * missing or inherited.
140
244
  *
141
245
  * TypeScript's `Record<K, V>` type assumes all keys exist, but at runtime
142
- * accessing a non-existent key returns `undefined`. This helper provides proper
143
- * typing for that case without needing a type assertion.
246
+ * accessing a missing key returns `undefined`. This helper provides proper
247
+ * typing for that case without treating properties inherited from
248
+ * `Object.prototype` as record data.
144
249
  *
145
250
  * ### Example
146
251
  *
147
252
  * ```ts
148
- * const users: Record<string, User> = { alice: { name: "Alice" } };
149
- * const user = getProperty(users, "bob"); // User | undefined
253
+ * import { getOwnProp } from "@evolu/common";
254
+ *
255
+ * interface User {
256
+ * readonly name: string;
257
+ * }
258
+ *
259
+ * const users: Readonly<Record<string, User>> = {
260
+ * alice: { name: "Alice" },
261
+ * };
262
+ * const user = getOwnProp(users, "bob");
263
+ *
264
+ * expectTypeOf(user).toEqualTypeOf<User | undefined>();
265
+ * expect(user).toBeUndefined();
266
+ * expect(getOwnProp(users, "toString")).toBeUndefined();
150
267
  * ```
151
268
  */
152
- export declare const getProperty: <K extends string, V>(record: ReadonlyRecord<K, V>, key: K) => V | undefined;
269
+ export declare const getOwnProp: <K extends string, V>(record: ReadonlyRecord<K, V>, key: NoInfer<K>) => V | undefined;
153
270
  /**
154
271
  * A disposable wrapper around `URL.createObjectURL` that automatically revokes
155
272
  * the URL when disposed. Use with the `using` declaration for automatic
@@ -158,10 +275,13 @@ export declare const getProperty: <K extends string, V>(record: ReadonlyRecord<K
158
275
  * ### Example
159
276
  *
160
277
  * ```ts
278
+ * import { createObjectURL } from "@evolu/common";
279
+ *
161
280
  * const blob = new Blob(["hello"], { type: "text/plain" });
162
281
  * using objectUrl = createObjectURL(blob);
163
- * console.log(objectUrl.url); // blob:...
164
- * // URL.revokeObjectURL is automatically called when the scope ends
282
+ *
283
+ * expect(objectUrl.url).toMatch(/^blob:/);
284
+ * // URL.revokeObjectURL is automatically called when the scope ends.
165
285
  * ```
166
286
  *
167
287
  * This ensures the URL is always revoked when the scope ends, even if an error
@@ -1 +1 @@
1
- {"version":3,"file":"Object.d.ts","sourceRoot":"","sources":["../../src/Object.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Object.d.ts","sourceRoot":"","sources":["../../src/Object.ts"],"names":[],"mappings":"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"}
@@ -15,15 +15,20 @@
15
15
  * Object.prototype` so it also works for plain objects coming from another
16
16
  * JavaScript realm.
17
17
  *
18
+ * TODO: deprecated Use `Object.is` from Type. Define a dedicated Type when
19
+ * another object domain is required.
20
+ *
18
21
  * ### Example
19
22
  *
20
23
  * ```ts
21
- * isPlainObject({}); // true
22
- * isPlainObject(Object.create(null)); // true
23
- * isPlainObject(new Date()); // false
24
- * isPlainObject(new (class Example {})()); // false
25
- * isPlainObject([]); // false
26
- * isPlainObject(null); // false
24
+ * import { isPlainObject } from "@evolu/common";
25
+ *
26
+ * expect(isPlainObject({})).toBe(true);
27
+ * expect(isPlainObject(Object.create(null))).toBe(true);
28
+ * expect(isPlainObject(new Date())).toBe(false);
29
+ * expect(isPlainObject(new (class Example {})())).toBe(false);
30
+ * expect(isPlainObject([])).toBe(false);
31
+ * expect(isPlainObject(null)).toBe(false);
27
32
  * ```
28
33
  */
29
34
  export const isPlainObject = (value) => {
@@ -39,9 +44,11 @@ export const isPlainObject = (value) => {
39
44
  * ### Example
40
45
  *
41
46
  * ```ts
42
- * isFunction(() => {}); // true
43
- * isFunction(function () {}); // true
44
- * isFunction({}); // false
47
+ * import { isFunction } from "@evolu/common";
48
+ *
49
+ * expect(isFunction(() => {})).toBe(true);
50
+ * expect(isFunction(function () {})).toBe(true);
51
+ * expect(isFunction({})).toBe(false);
45
52
  * ```
46
53
  */
47
54
  export const isFunction = (value) => typeof value === "function";
@@ -51,9 +58,11 @@ export const isFunction = (value) => typeof value === "function";
51
58
  * ### Example
52
59
  *
53
60
  * ```ts
54
- * isIterable([1, 2, 3]); // true
55
- * isIterable("abc"); // true
56
- * isIterable({}); // false
61
+ * import { isIterable } from "@evolu/common";
62
+ *
63
+ * expect(isIterable([1, 2, 3])).toBe(true);
64
+ * expect(isIterable("abc")).toBe(true);
65
+ * expect(isIterable({})).toBe(false);
57
66
  * ```
58
67
  */
59
68
  export const isIterable = (value) => value != null &&
@@ -64,9 +73,20 @@ export const isIterable = (value) => value != null &&
64
73
  * ### Example
65
74
  *
66
75
  * ```ts
67
- * type UserId = string & { readonly __brand: "UserId" };
68
- * const users = createRecord<UserId, string>();
69
- * const entries = objectToEntries(users); // [UserId, string][]
76
+ * import {
77
+ * objectToEntries,
78
+ * type Brand,
79
+ * type ReadonlyRecord,
80
+ * } from "@evolu/common";
81
+ *
82
+ * type UserId = string & Brand<"UserId">;
83
+ *
84
+ * const userId = "u1" as UserId;
85
+ * const users: ReadonlyRecord<UserId, string> = { [userId]: "Alice" };
86
+ * const entries = objectToEntries(users);
87
+ *
88
+ * expectTypeOf(entries).toEqualTypeOf<ReadonlyArray<[UserId, string]>>();
89
+ * expect(entries).toEqual([[userId, "Alice"]]);
70
90
  * ```
71
91
  */
72
92
  export const objectToEntries = (record) => Object.entries(record);
@@ -79,11 +99,20 @@ export const objectToEntries = (record) => Object.entries(record);
79
99
  * ### Example
80
100
  *
81
101
  * ```ts
82
- * type UserId = string & { readonly __brand: "UserId" };
102
+ * import {
103
+ * objectFromEntries,
104
+ * type Brand,
105
+ * type ReadonlyRecord,
106
+ * } from "@evolu/common";
107
+ *
108
+ * type UserId = string & Brand<"UserId">;
83
109
  * const entries: ReadonlyArray<[UserId, string]> = [
84
110
  * ["u1" as UserId, "Alice"],
85
111
  * ];
86
- * const users = objectFromEntries(entries); // ReadonlyRecord<UserId, string>
112
+ * const users = objectFromEntries(entries);
113
+ *
114
+ * expectTypeOf(users).toEqualTypeOf<ReadonlyRecord<UserId, string>>();
115
+ * expect(users).toEqual({ u1: "Alice" });
87
116
  * ```
88
117
  */
89
118
  export const objectFromEntries = (entries) => Object.fromEntries(entries);
@@ -96,11 +125,20 @@ export const objectFromEntries = (entries) => Object.fromEntries(entries);
96
125
  * ### Example
97
126
  *
98
127
  * ```ts
99
- * objectFrom(["en", "fr", "de"], loadTranslations);
100
- * // { en: Translations, fr: Translations, de: Translations }
101
- *
102
- * objectFrom(["trace", "debug", "log"], (level) => createHandler(level));
103
- * // { trace: Handler, debug: Handler, log: Handler }
128
+ * import { objectFrom, type ReadonlyRecord } from "@evolu/common";
129
+ *
130
+ * const translations = objectFrom(
131
+ * ["en", "fr"] as const,
132
+ * (locale): string => `Hello in ${locale}`,
133
+ * );
134
+ *
135
+ * expectTypeOf(translations).toEqualTypeOf<
136
+ * ReadonlyRecord<"en" | "fr", string>
137
+ * >();
138
+ * expect(translations).toEqual({
139
+ * en: "Hello in en",
140
+ * fr: "Hello in fr",
141
+ * });
104
142
  * ```
105
143
  */
106
144
  export const objectFrom = (keys, getValue) => Object.fromEntries(keys.map((k) => [k, getValue(k)]));
@@ -124,46 +162,54 @@ export const excludeProp = (obj, prop, condition) => {
124
162
  const { [prop]: _, ...rest } = obj;
125
163
  return rest;
126
164
  };
165
+ export function createMutableRecord(source) {
166
+ const record = Object.create(null);
167
+ return source === undefined ? record : Object.assign(record, source);
168
+ }
127
169
  /**
128
- * Creates a prototype-less object typed as `Record<K, V>`.
170
+ * A shared frozen empty readonly Record.
129
171
  *
130
- * Use this function when you need a plain record without a prototype chain
131
- * (e.g. when keys are controlled by external sources) to avoid prototype
132
- * pollution and accidental collisions with properties like `__proto__`.
172
+ * Use it as an immutable empty value for defaults and placeholders instead of
173
+ * allocating a new empty object. Because the instance is shared, it is frozen
174
+ * to prevent accidental mutation.
133
175
  *
134
- * Example:
135
- *
136
- * ```ts
137
- * const values = createRecord<string, SqliteValue>();
138
- * values["__proto__"] = someValue; // safe, no prototype pollution
139
- * ```
140
- */
141
- export const createRecord = () => Object.create(null);
142
- /**
143
- * An empty readonly record.
144
- *
145
- * Use as a default or initial value to avoid allocating new empty records.
176
+ * Use {@link createMutableRecord} to build a Record locally through mutation
177
+ * instead of repeated object spreads.
146
178
  *
147
179
  * @group Constants
148
180
  */
149
181
  export const emptyRecord =
150
- /*#__PURE__*/ createRecord();
182
+ /*#__PURE__*/ Object.freeze(
183
+ /*#__PURE__*/ createMutableRecord());
151
184
  /**
152
- * Safely gets a property from a record, returning `undefined` if the key
153
- * doesn't exist.
185
+ * Gets an own property from a record, returning `undefined` if the key is
186
+ * missing or inherited.
154
187
  *
155
188
  * TypeScript's `Record<K, V>` type assumes all keys exist, but at runtime
156
- * accessing a non-existent key returns `undefined`. This helper provides proper
157
- * typing for that case without needing a type assertion.
189
+ * accessing a missing key returns `undefined`. This helper provides proper
190
+ * typing for that case without treating properties inherited from
191
+ * `Object.prototype` as record data.
158
192
  *
159
193
  * ### Example
160
194
  *
161
195
  * ```ts
162
- * const users: Record<string, User> = { alice: { name: "Alice" } };
163
- * const user = getProperty(users, "bob"); // User | undefined
196
+ * import { getOwnProp } from "@evolu/common";
197
+ *
198
+ * interface User {
199
+ * readonly name: string;
200
+ * }
201
+ *
202
+ * const users: Readonly<Record<string, User>> = {
203
+ * alice: { name: "Alice" },
204
+ * };
205
+ * const user = getOwnProp(users, "bob");
206
+ *
207
+ * expectTypeOf(user).toEqualTypeOf<User | undefined>();
208
+ * expect(user).toBeUndefined();
209
+ * expect(getOwnProp(users, "toString")).toBeUndefined();
164
210
  * ```
165
211
  */
166
- export const getProperty = (record, key) => (key in record ? record[key] : undefined);
212
+ export const getOwnProp = (record, key) => (Object.hasOwn(record, key) ? record[key] : undefined);
167
213
  /** Creates a disposable {@link ObjectURL} for the given blob. */
168
214
  export const createObjectURL = (blob) => {
169
215
  const url = URL.createObjectURL(blob);
@@ -9,23 +9,26 @@
9
9
  * ### Example
10
10
  *
11
11
  * ```ts
12
- * // A cache that can store any value, including null and undefined
12
+ * import { isNone, isSome, none, type Option, some } from "@evolu/common";
13
+ *
13
14
  * const cache = new Map<string, Option<unknown>>();
14
15
  *
15
16
  * const get = (key: string): Option<unknown> => cache.get(key) ?? none;
16
17
  *
17
- * cache.set("a", some(null)); // Stored null
18
- * cache.set("b", some(undefined)); // Stored undefined
18
+ * cache.set("a", some(null));
19
+ * cache.set("b", some(undefined));
19
20
  *
20
- * isSome(get("a")); // true — value is null
21
- * isSome(get("b")); // true — value is undefined
22
- * isNone(get("c")); // true — key doesn't exist
21
+ * const a = get("a");
22
+ * assert(isSome(a));
23
+ * expect(a.value).toBeNull();
24
+ * expect(isSome(get("b"))).toBe(true);
25
+ * expect(isNone(get("c"))).toBe(true);
23
26
  * ```
24
27
  *
25
28
  * @module
26
29
  */
27
30
  /** Optional value. */
28
- import type { Typed } from "./Type.js";
31
+ import type { Typed } from "./Type.ts";
29
32
  /** Optional value. */
30
33
  export type Option<T> = Some<T> | None;
31
34
  /** Present value in an {@link Option}. */
@@ -1 +1 @@
1
- {"version":3,"file":"Option.d.ts","sourceRoot":"","sources":["../../src/Option.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,sBAAsB;AACtB,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,WAAW,CAAC;AAEvC,sBAAsB;AACtB,MAAM,MAAM,MAAM,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;AAEvC,0CAA0C;AAC1C,MAAM,WAAW,IAAI,CAAC,GAAG,CAAC,CAAC,CAAE,SAAQ,KAAK,CAAC,MAAM,CAAC;IAChD,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC;CACnB;AAED,yCAAyC;AACzC,MAAM,WAAW,IAAK,SAAQ,KAAK,CAAC,MAAM,CAAC;CAAG;AAE9C;;;;GAIG;AACH,MAAM,MAAM,WAAW,CAAC,CAAC,SAAS,MAAM,CAAC,GAAG,CAAC,IAC3C,CAAC,SAAS,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;AAEtC,8BAA8B;AAC9B,eAAO,MAAM,IAAI,GAAI,CAAC,EAAE,OAAO,CAAC,KAAG,MAAM,CAAC,CAAC,CAGzC,CAAC;AAEH,oCAAoC;AACpC,eAAO,MAAM,IAAI,EAAE,IAAuB,CAAC;AAE3C,mCAAmC;AACnC,eAAO,MAAM,MAAM,GAAI,CAAC,EAAE,QAAQ,MAAM,CAAC,CAAC,CAAC,KAAG,MAAM,IAAI,IAAI,CAAC,CAAC,CACtC,CAAC;AAEzB,mCAAmC;AACnC,eAAO,MAAM,MAAM,GAAI,CAAC,EAAE,QAAQ,MAAM,CAAC,CAAC,CAAC,KAAG,MAAM,IAAI,IAChC,CAAC;AAEzB;;;;GAIG;AACH,eAAO,MAAM,YAAY,GAAI,CAAC,EAC5B,OAAO,CAAC,GAAG,IAAI,GAAG,SAAS,KAC1B,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,CAAyC,CAAC"}
1
+ {"version":3,"file":"Option.d.ts","sourceRoot":"","sources":["../../src/Option.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,sBAAsB;AACtB,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,WAAW,CAAC;AAEvC,sBAAsB;AACtB,MAAM,MAAM,MAAM,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;AAEvC,0CAA0C;AAC1C,MAAM,WAAW,IAAI,CAAC,GAAG,CAAC,CAAC,CAAE,SAAQ,KAAK,CAAC,MAAM,CAAC;IAChD,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC;CACnB;AAED,yCAAyC;AACzC,MAAM,WAAW,IAAK,SAAQ,KAAK,CAAC,MAAM,CAAC;CAAG;AAE9C;;;;GAIG;AACH,MAAM,MAAM,WAAW,CAAC,CAAC,SAAS,MAAM,CAAC,GAAG,CAAC,IAC3C,CAAC,SAAS,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;AAEtC,8BAA8B;AAC9B,eAAO,MAAM,IAAI,GAAI,CAAC,SAAS,CAAC,KAAG,MAAM,CAAC,CAAC,CAGzC,CAAC;AAEH,oCAAoC;AACpC,eAAO,MAAM,IAAI,EAAE,IAAuB,CAAC;AAE3C,mCAAmC;AACnC,eAAO,MAAM,MAAM,GAAI,CAAC,UAAU,MAAM,CAAC,CAAC,CAAC,KAAG,MAAM,IAAI,IAAI,CAAC,CAAC,CACtC,CAAC;AAEzB,mCAAmC;AACnC,eAAO,MAAM,MAAM,GAAI,CAAC,UAAU,MAAM,CAAC,CAAC,CAAC,KAAG,MAAM,IAAI,IAChC,CAAC;AAEzB;;;;GAIG;AACH,eAAO,MAAM,YAAY,GAAI,CAAC,SACrB,CAAC,GAAG,IAAI,GAAG,SAAS,KAC1B,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,CAAyC,CAAC"}
@@ -9,17 +9,20 @@
9
9
  * ### Example
10
10
  *
11
11
  * ```ts
12
- * // A cache that can store any value, including null and undefined
12
+ * import { isNone, isSome, none, type Option, some } from "@evolu/common";
13
+ *
13
14
  * const cache = new Map<string, Option<unknown>>();
14
15
  *
15
16
  * const get = (key: string): Option<unknown> => cache.get(key) ?? none;
16
17
  *
17
- * cache.set("a", some(null)); // Stored null
18
- * cache.set("b", some(undefined)); // Stored undefined
18
+ * cache.set("a", some(null));
19
+ * cache.set("b", some(undefined));
19
20
  *
20
- * isSome(get("a")); // true — value is null
21
- * isSome(get("b")); // true — value is undefined
22
- * isNone(get("c")); // true — key doesn't exist
21
+ * const a = get("a");
22
+ * assert(isSome(a));
23
+ * expect(a.value).toBeNull();
24
+ * expect(isSome(get("b"))).toBe(true);
25
+ * expect(isNone(get("c"))).toBe(true);
23
26
  * ```
24
27
  *
25
28
  * @module
@@ -11,6 +11,9 @@
11
11
  * - Returns `-1` if `x` is less than `y`.
12
12
  * - Returns `0` if `x` is equal to `y`.
13
13
  * - Returns `1` if `x` is greater than `y`.
14
+ *
15
+ * An `Order` also defines equality. Use {@link eqFromOrder} to derive an
16
+ * {@link Eq}.
14
17
  */
15
18
  export type Order<in A> = (x: A, y: A) => Ordering;
16
19
  /**
@@ -25,10 +28,12 @@ export type Ordering = -1 | 0 | 1;
25
28
  * ### Example
26
29
  *
27
30
  * ```ts
31
+ * import { createOrder } from "@evolu/common";
32
+ *
28
33
  * const orderNumber = createOrder<number>((x, y) => x < y);
29
- * expect(orderNumber(1, 2)).toEqual(-1);
30
- * expect(orderNumber(2, 1)).toEqual(1);
31
- * expect(orderNumber(1, 1)).toEqual(0);
34
+ * expect(orderNumber(1, 2)).toBe(-1);
35
+ * expect(orderNumber(2, 1)).toBe(1);
36
+ * expect(orderNumber(1, 1)).toBe(0);
32
37
  * ```
33
38
  */
34
39
  export declare const createOrder: <A>(isLessThan: (x: A, y: A) => boolean) => Order<A>;
@@ -38,9 +43,10 @@ export declare const createOrder: <A>(isLessThan: (x: A, y: A) => boolean) => Or
38
43
  * ### Example
39
44
  *
40
45
  * ```ts
41
- * reverseOrder(orderNumber)(1, 2); // 1
42
- * reverseOrder(orderNumber)(2, 1); // -1
43
- * reverseOrder(orderNumber)(1, 1); // 0
46
+ * import { orderNumber, reverseOrder } from "@evolu/common";
47
+ *
48
+ * const descendingOrderNumber = reverseOrder(orderNumber);
49
+ * expect([3, 1, 2].toSorted(descendingOrderNumber)).toEqual([3, 2, 1]);
44
50
  * ```
45
51
  */
46
52
  export declare const reverseOrder: <A>(order: Order<A>) => Order<A>;
@@ -50,10 +56,9 @@ export declare const reverseOrder: <A>(order: Order<A>) => Order<A>;
50
56
  * ### Example
51
57
  *
52
58
  * ```ts
53
- * orderString("a", "b"); // -1
54
- * orderString("b", "a"); // 1
55
- * orderString("a", "a"); // 0
56
- * ["c", "b", "a"].toSorted(orderString); // ["a", "b", "c"]
59
+ * import { orderString } from "@evolu/common";
60
+ *
61
+ * expect(["c", "b", "a"].toSorted(orderString)).toEqual(["a", "b", "c"]);
57
62
  * ```
58
63
  */
59
64
  export declare const orderString: Order<string>;
@@ -63,13 +68,9 @@ export declare const orderString: Order<string>;
63
68
  * ### Example
64
69
  *
65
70
  * ```ts
66
- * orderNumber(1, 2); // -1
67
- * orderNumber(2, 1); // 1
68
- * orderNumber(1, 1); // 0
69
- * [2, 1, 3].toSorted(orderNumber); // [1, 2, 3]
70
- * reverseOrder(orderNumber)(1, 2); // 1
71
- * reverseOrder(orderNumber)(2, 1); // -1
72
- * reverseOrder(orderNumber)(1, 1); // 0
71
+ * import { orderNumber } from "@evolu/common";
72
+ *
73
+ * expect([2, 1, 3].toSorted(orderNumber)).toEqual([1, 2, 3]);
73
74
  * ```
74
75
  */
75
76
  export declare const orderNumber: Order<number>;
@@ -79,10 +80,9 @@ export declare const orderNumber: Order<number>;
79
80
  * ### Example
80
81
  *
81
82
  * ```ts
82
- * orderBigInt(1n, 2n); // -1
83
- * orderBigInt(2n, 1n); // 1
84
- * orderBigInt(1n, 1n); // 0
85
- * [2n, 1n, 3n].toSorted(orderBigInt); // [1n, 2n, 3n]
83
+ * import { orderBigInt } from "@evolu/common";
84
+ *
85
+ * expect([2n, 1n, 3n].toSorted(orderBigInt)).toEqual([1n, 2n, 3n]);
86
86
  * ```
87
87
  */
88
88
  export declare const orderBigInt: Order<bigint>;