@evolu/common 8.0.0-next.5 → 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 (236) 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 +39 -44
  5. package/dist/src/Assert.d.ts.map +1 -1
  6. package/dist/src/Assert.js +38 -31
  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 +3 -3
  29. package/dist/src/Error.d.ts.map +1 -1
  30. package/dist/src/Function.d.ts +119 -58
  31. package/dist/src/Function.d.ts.map +1 -1
  32. package/dist/src/Function.js +86 -43
  33. package/dist/src/Http.d.ts +394 -0
  34. package/dist/src/Http.d.ts.map +1 -0
  35. package/dist/src/Http.js +102 -0
  36. package/dist/src/Identicon.d.ts +16 -7
  37. package/dist/src/Identicon.d.ts.map +1 -1
  38. package/dist/src/Identicon.js +14 -5
  39. package/dist/src/LeakDetector.d.ts +88 -0
  40. package/dist/src/LeakDetector.d.ts.map +1 -0
  41. package/dist/src/LeakDetector.js +86 -0
  42. package/dist/src/LockManager.d.ts +18 -9
  43. package/dist/src/LockManager.d.ts.map +1 -1
  44. package/dist/src/LockManager.js +7 -8
  45. package/dist/src/Lookup.d.ts +43 -13
  46. package/dist/src/Lookup.d.ts.map +1 -1
  47. package/dist/src/Lookup.js +28 -8
  48. package/dist/src/Microtask.d.ts +1 -1
  49. package/dist/src/Microtask.d.ts.map +1 -1
  50. package/dist/src/Microtask.js +3 -7
  51. package/dist/src/Number.d.ts +49 -13
  52. package/dist/src/Number.d.ts.map +1 -1
  53. package/dist/src/Number.js +34 -5
  54. package/dist/src/Object.d.ts +160 -40
  55. package/dist/src/Object.d.ts.map +1 -1
  56. package/dist/src/Object.js +92 -46
  57. package/dist/src/Option.d.ts +10 -7
  58. package/dist/src/Option.d.ts.map +1 -1
  59. package/dist/src/Option.js +9 -6
  60. package/dist/src/Order.d.ts +21 -21
  61. package/dist/src/Order.d.ts.map +1 -1
  62. package/dist/src/Order.js +18 -21
  63. package/dist/src/Platform.d.ts +31 -0
  64. package/dist/src/Platform.d.ts.map +1 -1
  65. package/dist/src/Platform.js +98 -0
  66. package/dist/src/Random.d.ts +32 -17
  67. package/dist/src/Random.d.ts.map +1 -1
  68. package/dist/src/Random.js +12 -8
  69. package/dist/src/Redacted.d.ts +43 -29
  70. package/dist/src/Redacted.d.ts.map +1 -1
  71. package/dist/src/Redacted.js +14 -3
  72. package/dist/src/Ref.d.ts +11 -3
  73. package/dist/src/Ref.d.ts.map +1 -1
  74. package/dist/src/Ref.js +2 -2
  75. package/dist/src/RefCount.d.ts +2 -6
  76. package/dist/src/RefCount.d.ts.map +1 -1
  77. package/dist/src/RefCount.js +33 -90
  78. package/dist/src/Relation.d.ts +70 -5
  79. package/dist/src/Relation.d.ts.map +1 -1
  80. package/dist/src/Relation.js +77 -2
  81. package/dist/src/Resource.d.ts +590 -155
  82. package/dist/src/Resource.d.ts.map +1 -1
  83. package/dist/src/Resource.js +592 -343
  84. package/dist/src/Result.d.ts +838 -191
  85. package/dist/src/Result.d.ts.map +1 -1
  86. package/dist/src/Result.js +163 -102
  87. package/dist/src/Schedule.d.ts +684 -231
  88. package/dist/src/Schedule.d.ts.map +1 -1
  89. package/dist/src/Schedule.js +766 -295
  90. package/dist/src/Set.d.ts +89 -40
  91. package/dist/src/Set.d.ts.map +1 -1
  92. package/dist/src/Set.js +50 -29
  93. package/dist/src/Sqlite.d.ts +29 -72
  94. package/dist/src/Sqlite.d.ts.map +1 -1
  95. package/dist/src/Sqlite.js +39 -45
  96. package/dist/src/StackTrace.d.ts +40 -0
  97. package/dist/src/StackTrace.d.ts.map +1 -0
  98. package/dist/src/StackTrace.js +140 -0
  99. package/dist/src/Store.d.ts +5 -4
  100. package/dist/src/Store.d.ts.map +1 -1
  101. package/dist/src/Store.js +5 -4
  102. package/dist/src/String.d.ts +7 -1
  103. package/dist/src/String.d.ts.map +1 -1
  104. package/dist/src/String.js +20 -7
  105. package/dist/src/Task.d.ts +3428 -1629
  106. package/dist/src/Task.d.ts.map +1 -1
  107. package/dist/src/Task.js +1876 -1279
  108. package/dist/src/Test.d.ts +17 -124
  109. package/dist/src/Test.d.ts.map +1 -1
  110. package/dist/src/Test.js +17 -68
  111. package/dist/src/Time.d.ts +108 -49
  112. package/dist/src/Time.d.ts.map +1 -1
  113. package/dist/src/Time.js +172 -73
  114. package/dist/src/Type.d.ts +3542 -1926
  115. package/dist/src/Type.d.ts.map +1 -1
  116. package/dist/src/Type.js +3070 -1784
  117. package/dist/src/Types.d.ts +200 -100
  118. package/dist/src/Types.d.ts.map +1 -1
  119. package/dist/src/Types.js +39 -8
  120. package/dist/src/WebSocket.d.ts +48 -23
  121. package/dist/src/WebSocket.d.ts.map +1 -1
  122. package/dist/src/WebSocket.js +15 -6
  123. package/dist/src/Worker.d.ts +94 -36
  124. package/dist/src/Worker.d.ts.map +1 -1
  125. package/dist/src/Worker.js +58 -24
  126. package/dist/src/index.d.ts +55 -52
  127. package/dist/src/index.d.ts.map +1 -1
  128. package/dist/src/index.js +3 -1
  129. package/dist/src/intl/cs.d.ts +94 -0
  130. package/dist/src/intl/cs.d.ts.map +1 -0
  131. package/dist/src/intl/cs.js +220 -0
  132. package/dist/src/intl/index.d.ts +7 -0
  133. package/dist/src/intl/index.d.ts.map +1 -0
  134. package/dist/src/intl/index.js +6 -0
  135. package/dist/src/local-first/Db.d.ts +12 -8
  136. package/dist/src/local-first/Db.d.ts.map +1 -1
  137. package/dist/src/local-first/Db.js +107 -130
  138. package/dist/src/local-first/Error.d.ts +4 -4
  139. package/dist/src/local-first/Evolu.d.ts +338 -92
  140. package/dist/src/local-first/Evolu.d.ts.map +1 -1
  141. package/dist/src/local-first/Evolu.js +47 -55
  142. package/dist/src/local-first/LocalAuth.d.ts +4 -4
  143. package/dist/src/local-first/LocalAuth.d.ts.map +1 -1
  144. package/dist/src/local-first/Owner.d.ts +61 -24
  145. package/dist/src/local-first/Owner.d.ts.map +1 -1
  146. package/dist/src/local-first/Owner.js +45 -8
  147. package/dist/src/local-first/Protocol.d.ts +44 -31
  148. package/dist/src/local-first/Protocol.d.ts.map +1 -1
  149. package/dist/src/local-first/Protocol.js +36 -13
  150. package/dist/src/local-first/Query.d.ts +147 -62
  151. package/dist/src/local-first/Query.d.ts.map +1 -1
  152. package/dist/src/local-first/Query.js +112 -58
  153. package/dist/src/local-first/Relay.d.ts +44 -14
  154. package/dist/src/local-first/Relay.d.ts.map +1 -1
  155. package/dist/src/local-first/Schema.d.ts +92 -41
  156. package/dist/src/local-first/Schema.d.ts.map +1 -1
  157. package/dist/src/local-first/Schema.js +25 -8
  158. package/dist/src/local-first/Shared.d.ts +23 -21
  159. package/dist/src/local-first/Shared.d.ts.map +1 -1
  160. package/dist/src/local-first/Shared.js +85 -42
  161. package/dist/src/local-first/Storage.d.ts +53 -32
  162. package/dist/src/local-first/Storage.d.ts.map +1 -1
  163. package/dist/src/local-first/Storage.js +194 -234
  164. package/dist/src/local-first/Timestamp.d.ts +21 -21
  165. package/dist/src/local-first/Timestamp.d.ts.map +1 -1
  166. package/dist/src/local-first/Timestamp.js +2 -2
  167. package/dist/src/local-first/index.d.ts +11 -11
  168. package/package.json +14 -13
  169. package/src/Array.ts +306 -205
  170. package/src/Assert.ts +48 -68
  171. package/src/BigInt.ts +6 -3
  172. package/src/Brand.ts +27 -40
  173. package/src/Buffer.ts +28 -12
  174. package/src/Cache.ts +9 -4
  175. package/src/Callbacks.ts +30 -19
  176. package/src/Console.ts +156 -84
  177. package/src/Crypto.ts +83 -41
  178. package/src/Eq.ts +95 -22
  179. package/src/Error.ts +5 -2
  180. package/src/Function.ts +167 -59
  181. package/src/Http.ts +549 -0
  182. package/src/Identicon.ts +16 -7
  183. package/src/LeakDetector.ts +182 -0
  184. package/src/LockManager.ts +43 -39
  185. package/src/Lookup.ts +62 -28
  186. package/src/Microtask.ts +19 -23
  187. package/src/Number.ts +64 -12
  188. package/src/Object.ts +173 -49
  189. package/src/Option.ts +10 -7
  190. package/src/Order.ts +23 -21
  191. package/src/Platform.ts +136 -0
  192. package/src/Polyfills.ts +6 -12
  193. package/src/Random.ts +32 -19
  194. package/src/Redacted.ts +44 -30
  195. package/src/Ref.ts +14 -6
  196. package/src/RefCount.ts +38 -80
  197. package/src/Relation.ts +202 -10
  198. package/src/Resource.ts +1199 -591
  199. package/src/Result.ts +930 -271
  200. package/src/Schedule.ts +859 -343
  201. package/src/Set.ts +89 -40
  202. package/src/Sqlite.ts +142 -137
  203. package/src/StackTrace.ts +230 -0
  204. package/src/Store.ts +8 -7
  205. package/src/String.ts +22 -5
  206. package/src/Task.ts +5109 -2845
  207. package/src/Test.ts +20 -167
  208. package/src/Time.ts +293 -90
  209. package/src/Type.ts +10034 -4117
  210. package/src/Types.ts +227 -101
  211. package/src/WebSocket.ts +64 -36
  212. package/src/Worker.ts +180 -72
  213. package/src/index.ts +55 -52
  214. package/src/intl/cs.ts +388 -0
  215. package/src/intl/index.ts +7 -0
  216. package/src/local-first/Db.ts +161 -190
  217. package/src/local-first/Error.ts +4 -4
  218. package/src/local-first/Evolu.ts +495 -250
  219. package/src/local-first/LocalAuth.ts +6 -12
  220. package/src/local-first/Owner.ts +58 -21
  221. package/src/local-first/Protocol.ts +49 -31
  222. package/src/local-first/Query.ts +146 -61
  223. package/src/local-first/Relay.ts +51 -21
  224. package/src/local-first/Schema.ts +109 -51
  225. package/src/local-first/Shared.ts +253 -214
  226. package/src/local-first/Storage.ts +266 -264
  227. package/src/local-first/Timestamp.ts +25 -18
  228. package/src/local-first/index.ts +11 -11
  229. package/dist/src/Skiplist.d.ts +0 -28
  230. package/dist/src/Skiplist.d.ts.map +0 -1
  231. package/dist/src/Skiplist.js +0 -64
  232. package/dist/src/Tracer.d.ts +0 -48
  233. package/dist/src/Tracer.d.ts.map +0 -1
  234. package/dist/src/Tracer.js +0 -6
  235. package/src/Skiplist.ts +0 -108
  236. package/src/Tracer.ts +0 -54
@@ -55,12 +55,12 @@ var __disposeResources = (this && this.__disposeResources) || (function (Suppres
55
55
  var e = new Error(message);
56
56
  return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
57
57
  });
58
- import { assertNotDisposed } from "./Assert.js";
59
58
  import { bytesToHex, hexToBytes } from "./Buffer.js";
60
59
  import { createEqObject, eqArrayNumber, eqString } from "./Eq.js";
61
- import { createRecord, objectToEntries } from "./Object.js";
60
+ import { disposable } from "./Function.js";
61
+ import { createMutableRecord, objectToEntries } from "./Object.js";
62
62
  import { ok } from "./Result.js";
63
- import { testCreateRun } from "./Test.js";
63
+ import { testCreateRun } from "./Task.js";
64
64
  import { array, Null, Number, object, record, set, String, testName, Uint8Array, union, } from "./Type.js";
65
65
  /**
66
66
  * A value that can be stored in {@link Sqlite}.
@@ -106,15 +106,10 @@ export const createSqlite = (name, options) => async (run) => {
106
106
  const { createSqliteDriver } = run.deps;
107
107
  const console = run.deps.console.child("sql");
108
108
  const disposer = __addDisposableResource(env_1, new AsyncDisposableStack(), true);
109
- const driverResult = await run(createSqliteDriver(name, options));
110
- if (!driverResult.ok)
111
- return driverResult;
112
- const driver = disposer.use(driverResult.value);
109
+ const driver = disposer.use(await run.ok(createSqliteDriver(name, options)));
113
110
  console.debug("SQLite driver created");
114
- const disposables = disposer.move();
115
- const sqlite = {
111
+ return ok(disposable({
116
112
  exec: (query) => {
117
- assertNotDisposed(disposables);
118
113
  console.debug({ query });
119
114
  const label = query.options?.logQueryExecutionTime &&
120
115
  `SqliteQueryExecutionTime ${query.sql}`;
@@ -137,7 +132,6 @@ export const createSqlite = (name, options) => async (run) => {
137
132
  transaction: ((callback) => {
138
133
  const env_2 = { stack: [], error: void 0, hasError: false };
139
134
  try {
140
- assertNotDisposed(disposables);
141
135
  console.debug("begin");
142
136
  driver.exec(sql `begin;`);
143
137
  const rollback = __addDisposableResource(env_2, new DisposableStack(), false);
@@ -164,13 +158,8 @@ export const createSqlite = (name, options) => async (run) => {
164
158
  __disposeResources(env_2);
165
159
  }
166
160
  }),
167
- export: () => {
168
- assertNotDisposed(disposables);
169
- return driver.export();
170
- },
171
- [Symbol.asyncDispose]: () => disposables.disposeAsync(),
172
- };
173
- return ok(sqlite);
161
+ export: () => driver.export(),
162
+ }, disposer));
174
163
  }
175
164
  catch (e_1) {
176
165
  env_1.error = e_1;
@@ -188,7 +177,7 @@ export const testSetupSqlite = async (deps) => {
188
177
  try {
189
178
  const disposer = __addDisposableResource(env_3, new AsyncDisposableStack(), true);
190
179
  const run = disposer.use(testCreateRun(deps));
191
- const sqlite = disposer.use(await run.orThrow(createSqlite(testName, { mode: "memory" })));
180
+ const sqlite = disposer.use(await run.ok(createSqlite(testName, { mode: "memory" })));
192
181
  const runWithSqlite = disposer.use(run.create({ ...run.deps, sqlite }));
193
182
  const disposables = disposer.move();
194
183
  return {
@@ -250,10 +239,8 @@ export const createPreparedStatementsCache = (factory, disposeFn) => {
250
239
  __disposeResources(env_5);
251
240
  }
252
241
  });
253
- const disposables = disposer.move();
254
- return {
242
+ return disposable({
255
243
  get: (query, alwaysPrepare) => {
256
- assertNotDisposed(disposables);
257
244
  if (alwaysPrepare !== true && !query.options?.prepare)
258
245
  return null;
259
246
  let statement = statementsBySql.get(query.sql);
@@ -263,8 +250,7 @@ export const createPreparedStatementsCache = (factory, disposeFn) => {
263
250
  }
264
251
  return statement;
265
252
  },
266
- [Symbol.dispose]: () => disposables.dispose(),
267
- };
253
+ }, disposer);
268
254
  }
269
255
  catch (e_4) {
270
256
  env_4.error = e_4;
@@ -283,27 +269,32 @@ export const createPreparedStatementsCache = (factory, disposeFn) => {
283
269
  * ### Example
284
270
  *
285
271
  * ```ts
272
+ * import { sql } from "@evolu/common";
273
+ *
286
274
  * const id = 42;
287
275
  * const name = "Alice";
288
- *
289
- * const result = sqlite.exec(sql`
290
- * select *
291
- * from users
292
- * where id = ${id} and name = ${name};
293
- * `);
294
- *
295
- * // For identifiers
276
+ * const select = sql`
277
+ * select * from users where id = ${id} and name = ${name};
278
+ * `;
296
279
  * const tableName = "users";
297
- * sqlite.exec(sql`
280
+ * const createTable = sql`
298
281
  * create table ${sql.identifier(tableName)} (
299
282
  * "id" text primary key,
300
283
  * "name" text not null
301
284
  * );
302
- * `);
303
- *
304
- * // For raw SQL (use with caution)
285
+ * `;
286
+ * // Use sql.raw only with trusted SQL fragments.
305
287
  * const orderBy = "created_at desc";
306
- * sqlite.exec(sql`select * from users order by ${sql.raw(orderBy)};`);
288
+ * const ordered = sql`select * from users order by ${sql.raw(orderBy)};`;
289
+ *
290
+ * expect(select).toEqual({
291
+ * sql: "select * from users where id = ? and name = ?;",
292
+ * parameters: [42, "Alice"],
293
+ * });
294
+ * expect(createTable.sql).toContain('create table "users"');
295
+ * expect(ordered.sql).toBe(
296
+ * "select * from users order by created_at desc;",
297
+ * );
307
298
  * ```
308
299
  *
309
300
  * ## TIP
@@ -365,7 +356,7 @@ export const SqliteSchema = /*#__PURE__*/ object({
365
356
  });
366
357
  /** Get the current SQLite schema by reading SQLite metadata. */
367
358
  export const getSqliteSchema = (deps) => ({ excludeIndexNamePrefix, } = {}) => {
368
- const tables = createRecord();
359
+ const tables = createMutableRecord();
369
360
  const tableAndColumnInfoRows = deps.sqlite.exec(sql `
370
361
  select
371
362
  sqlite_master.name as tableName,
@@ -380,6 +371,7 @@ export const getSqliteSchema = (deps) => ({ excludeIndexNamePrefix, } = {}) => {
380
371
  const indexNamePrefixFilter = excludeIndexNamePrefix != null
381
372
  ? ` and name not like '${excludeIndexNamePrefix.replaceAll("'", "''")}%'`
382
373
  : "";
374
+ // prettier-ignore
383
375
  const indexesRows = deps.sqlite.exec(sql `
384
376
  select name, sql
385
377
  from sqlite_master
@@ -391,9 +383,9 @@ export const getSqliteSchema = (deps) => ({ excludeIndexNamePrefix, } = {}) => {
391
383
  const indexes = indexesRows.rows.map((row) => ({
392
384
  name: row.name,
393
385
  /**
394
- * SQLite returns "CREATE INDEX" for "create index" for some reason.
395
- * Other keywords remain unchanged. We have to normalize the casing for
396
- * schema comparison manually.
386
+ * SQLite returns "CREATE INDEX" for "create index" for some reason. Other
387
+ * keywords remain unchanged. We have to normalize the casing for schema
388
+ * comparison manually.
397
389
  */
398
390
  sql: row.sql
399
391
  .replace("CREATE INDEX", "create index")
@@ -453,8 +445,9 @@ export const sqliteFalse = 0;
453
445
  * ### Example
454
446
  *
455
447
  * ```ts
456
- * const isActive = true;
457
- * const sqlValue = booleanToSqliteBoolean(isActive); // Returns 1
448
+ * import { booleanToSqliteBoolean } from "@evolu/common";
449
+ *
450
+ * expect(booleanToSqliteBoolean(true)).toBe(1);
458
451
  * ```
459
452
  */
460
453
  export const booleanToSqliteBoolean = (value) => value ? sqliteTrue : sqliteFalse;
@@ -464,8 +457,9 @@ export const booleanToSqliteBoolean = (value) => value ? sqliteTrue : sqliteFals
464
457
  * ### Example
465
458
  *
466
459
  * ```ts
467
- * const sqlValue: SqliteBoolean = 1;
468
- * const bool = sqliteBooleanToBoolean(sqlValue); // Returns true
460
+ * import { sqliteBooleanToBoolean } from "@evolu/common";
461
+ *
462
+ * expect(sqliteBooleanToBoolean(1)).toBe(true);
469
463
  * ```
470
464
  */
471
465
  export const sqliteBooleanToBoolean = (value) => value === sqliteTrue;
@@ -0,0 +1,40 @@
1
+ /**
2
+ * JavaScript stack trace parsing utilities.
3
+ *
4
+ * @module
5
+ */
6
+ export interface StackTraceFrame {
7
+ /** Function or frame label reported by the engine, if available. */
8
+ readonly name: string | undefined;
9
+ /** Basename of the source location without query or hash suffixes. */
10
+ readonly sourceName: string;
11
+ readonly location: string;
12
+ readonly lineNumber: number;
13
+ readonly columnNumber: number;
14
+ }
15
+ export interface StackTrace {
16
+ readonly frames: ReadonlyArray<StackTraceFrame>;
17
+ readonly names: ReadonlyArray<string>;
18
+ readonly files: ReadonlyArray<string>;
19
+ readonly sites: ReadonlyArray<string>;
20
+ }
21
+ export interface StackTraceOptions {
22
+ readonly maxSourceLabelLineOffset?: number;
23
+ readonly sourceLabel?: string;
24
+ readonly sourceLabelsByLine?: Map<number, string>;
25
+ readonly sourceNameAllowlist?: ReadonlySet<string>;
26
+ readonly sourceName?: string;
27
+ }
28
+ /**
29
+ * Parses V8, SpiderMonkey, and JavaScriptCore stack frames for tests.
30
+ *
31
+ * Warning: This is AI-slop containment code for tests, not production stack
32
+ * trace parsing infrastructure.
33
+ *
34
+ * This is intentionally not a complete stack trace parser. It extracts only
35
+ * frame names and source positions needed by async stack trace tests and
36
+ * similar assertions that need stable, cross-engine stack evidence.
37
+ */
38
+ export declare function parseStackTrace(stack: string | undefined, options?: StackTraceOptions): StackTrace;
39
+ export declare function parseStackTrace(run: () => Promise<never>, options?: StackTraceOptions): Promise<StackTrace>;
40
+ //# sourceMappingURL=StackTrace.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StackTrace.d.ts","sourceRoot":"","sources":["../../src/StackTrace.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,WAAW,eAAe;IAC9B,oEAAoE;IACpE,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,sEAAsE;IACtE,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;CAC/B;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC,eAAe,CAAC,CAAC;IAChD,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IACtC,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IACtC,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;CACvC;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,wBAAwB,CAAC,EAAE,MAAM,CAAC;IAC3C,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,kBAAkB,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClD,QAAQ,CAAC,mBAAmB,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IACnD,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAC7B,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,OAAO,CAAC,EAAE,iBAAiB,GAC1B,UAAU,CAAC;AACd,wBAAgB,eAAe,CAC7B,GAAG,EAAE,MAAM,OAAO,CAAC,KAAK,CAAC,EACzB,OAAO,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC,UAAU,CAAC,CAAC"}
@@ -0,0 +1,140 @@
1
+ /**
2
+ * JavaScript stack trace parsing utilities.
3
+ *
4
+ * @module
5
+ */
6
+ export function parseStackTrace(input, options = {}) {
7
+ if (typeof input === "function")
8
+ return (async () => {
9
+ try {
10
+ if (options.sourceLabel != null)
11
+ parseStackTrace(new Error().stack, options);
12
+ await input();
13
+ }
14
+ catch (error) {
15
+ if (!(error instanceof Error))
16
+ throw error;
17
+ const { sourceLabel: _sourceLabel, ...readOptions } = options;
18
+ return parseStackTrace(error.stack, readOptions);
19
+ }
20
+ throw new Error("Stack trace capture must throw.");
21
+ })();
22
+ const frames = parseStackTraceFrames(input).filter(({ sourceName }) => options.sourceNameAllowlist == null ||
23
+ options.sourceNameAllowlist.has(sourceName));
24
+ recordSourceLabel(frames, options);
25
+ return {
26
+ files: frames.map(({ sourceName }) => sourceName),
27
+ frames,
28
+ names: frames
29
+ .map(({ name }) => name)
30
+ .filter((name) => name !== undefined),
31
+ sites: sourceLabels(frames, options),
32
+ };
33
+ }
34
+ const parseStackTraceFrames = (stack) => (stack ?? "")
35
+ .split("\n")
36
+ .map(parseStackTraceLine)
37
+ .filter((frame) => frame !== undefined);
38
+ const recordSourceLabel = (frames, { sourceLabel, sourceLabelsByLine, sourceName }) => {
39
+ if (sourceLabel == null || sourceLabelsByLine == null || sourceName == null)
40
+ return;
41
+ const frame = frames.find((frame) => frame.sourceName === sourceName);
42
+ if (frame == null)
43
+ return;
44
+ sourceLabelsByLine.set(frame.lineNumber, sourceLabel);
45
+ };
46
+ const sourceLabels = (frames, { maxSourceLabelLineOffset = 8, sourceLabelsByLine, sourceName, }) => {
47
+ if (sourceLabelsByLine == null || sourceName == null)
48
+ return [];
49
+ return frames.flatMap((frame) => {
50
+ if (frame.sourceName !== sourceName)
51
+ return [];
52
+ for (let offset = 0; offset <= maxSourceLabelLineOffset; offset += 1) {
53
+ const label = sourceLabelsByLine.get(frame.lineNumber - offset);
54
+ if (label != null)
55
+ return [label];
56
+ }
57
+ return [];
58
+ });
59
+ };
60
+ const parseStackTraceLine = (line) => {
61
+ const stackLine = parseStackLine(line);
62
+ if (stackLine == null)
63
+ return undefined;
64
+ const location = parseStackLocation(stackLine.location);
65
+ if (location == null)
66
+ return undefined;
67
+ return { ...location, name: stackLine.name };
68
+ };
69
+ const parseStackLine = (line) => {
70
+ let text = line.trim();
71
+ if (text === "")
72
+ return undefined;
73
+ if (text.startsWith("at ")) {
74
+ text = text.slice(3);
75
+ if (text.startsWith("async "))
76
+ text = text.slice(6);
77
+ const locationStart = text.lastIndexOf("(");
78
+ if (locationStart >= 0 && text.endsWith(")")) {
79
+ const name = stackFrameName(text.slice(0, locationStart).trim());
80
+ const location = text.slice(locationStart + 1, -1);
81
+ return { name, location };
82
+ }
83
+ return { location: text, name: undefined };
84
+ }
85
+ if (text.startsWith("async*"))
86
+ text = text.slice(6);
87
+ const locationStart = text.indexOf("@");
88
+ if (locationStart < 0)
89
+ return { location: text, name: undefined };
90
+ return {
91
+ location: text.slice(locationStart + 1),
92
+ name: stackFrameName(text.slice(0, locationStart)),
93
+ };
94
+ };
95
+ const parseStackLocation = (location) => {
96
+ const columnStart = location.lastIndexOf(":");
97
+ if (columnStart < 0)
98
+ return undefined;
99
+ const lineStart = location.lastIndexOf(":", columnStart - 1);
100
+ if (lineStart < 0)
101
+ return undefined;
102
+ const pathEnd = Math.max(location.lastIndexOf("/"), location.lastIndexOf("\\"));
103
+ if (lineStart <= pathEnd)
104
+ return undefined;
105
+ const lineNumber = parseLeadingInt(location.slice(lineStart + 1));
106
+ const columnNumber = parseLeadingInt(location.slice(columnStart + 1));
107
+ if (lineNumber == null || columnNumber == null)
108
+ return undefined;
109
+ return {
110
+ columnNumber,
111
+ lineNumber,
112
+ location,
113
+ sourceName: stackTraceSourceName(location.slice(0, lineStart)),
114
+ };
115
+ };
116
+ const stackTraceSourceName = (source) => {
117
+ const queryStart = source.indexOf("?");
118
+ const hashStart = source.indexOf("#");
119
+ const suffixStart = queryStart < 0
120
+ ? hashStart
121
+ : hashStart < 0
122
+ ? queryStart
123
+ : Math.min(queryStart, hashStart);
124
+ const path = suffixStart < 0 ? source : source.slice(0, suffixStart);
125
+ return path.slice(Math.max(path.lastIndexOf("/"), path.lastIndexOf("\\")) + 1);
126
+ };
127
+ const parseLeadingInt = (value) => {
128
+ let end = 0;
129
+ while (end < value.length && isAsciiDigit(value.charCodeAt(end)))
130
+ end += 1;
131
+ if (end === 0)
132
+ return undefined;
133
+ return Number(value.slice(0, end));
134
+ };
135
+ const isAsciiDigit = (charCode) => charCode >= 48 && charCode <= 57;
136
+ const stackFrameName = (value) => {
137
+ while (value.endsWith("/<"))
138
+ value = value.slice(0, -2);
139
+ return value === "" ? undefined : value;
140
+ };
@@ -3,8 +3,8 @@
3
3
  *
4
4
  * @module
5
5
  */
6
- import type { Eq } from "./Eq.js";
7
- import type { Ref } from "./Ref.js";
6
+ import type { Eq } from "./Eq.ts";
7
+ import type { Ref } from "./Ref.ts";
8
8
  /**
9
9
  * A store for managing state with change notifications. Like a {@link Ref} with
10
10
  * subscriptions.
@@ -43,8 +43,9 @@ export type Unsubscribe = () => void;
43
43
  * state, which can be read with `get` and updated with `set` or `update`. All
44
44
  * changes are broadcast to subscribers.
45
45
  *
46
- * By default, state changes are detected using strict equality (`===`). You can
47
- * provide a custom equality function as the second argument.
46
+ * By default, state changes are detected using {@link eqSameValueZero}, which
47
+ * considers `NaN` equal to itself and `0` equal to `-0`. You can provide a
48
+ * custom equality function as the second argument.
48
49
  */
49
50
  export declare const createStore: <T>(initialState: T, eq?: Eq<T>) => Store<T>;
50
51
  //# sourceMappingURL=Store.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Store.d.ts","sourceRoot":"","sources":["../../src/Store.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,SAAS,CAAC;AAElC,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAGpC;;;;;;;GAOG;AACH,MAAM,WAAW,KAAK,CAAC,CAAC,CAAE,SAAQ,aAAa,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;CAAG;AAE7D;;;;;;GAMG;AACH,MAAM,WAAW,aAAa,CAAC,CAAC,CAAE,SAAQ,UAAU;IAClD,8CAA8C;IAC9C,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IAEtB;;;OAGG;IACH,QAAQ,CAAC,SAAS,EAAE,CAAC,QAAQ,EAAE,QAAQ,KAAK,WAAW,CAAC;CACzD;AAED,2EAA2E;AAC3E,MAAM,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC;AAElC;;;GAGG;AACH,MAAM,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC;AAErC;;;;;;;GAOG;AACH,eAAO,MAAM,WAAW,GAAI,CAAC,EAAE,cAAc,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,KAAG,KAAK,CAAC,CAAC,CAqEnE,CAAC"}
1
+ {"version":3,"file":"Store.d.ts","sourceRoot":"","sources":["../../src/Store.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,SAAS,CAAC;AAElC,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAGpC;;;;;;;GAOG;AACH,MAAM,WAAW,KAAK,CAAC,CAAC,CAAE,SAAQ,aAAa,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;CAAG;AAE7D;;;;;;GAMG;AACH,MAAM,WAAW,aAAa,CAAC,CAAC,CAAE,SAAQ,UAAU;IAClD,8CAA8C;IAC9C,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IAEtB;;;OAGG;IACH,QAAQ,CAAC,SAAS,EAAE,CAAC,QAAQ,EAAE,QAAQ,KAAK,WAAW,CAAC;CACzD;AAED,2EAA2E;AAC3E,MAAM,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC;AAElC;;;GAGG;AACH,MAAM,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC;AAErC;;;;;;;;GAQG;AACH,eAAO,MAAM,WAAW,GAAI,CAAC,gBAAgB,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,KAAG,KAAK,CAAC,CAAC,CAqEnE,CAAC"}
package/dist/src/Store.js CHANGED
@@ -3,18 +3,19 @@
3
3
  *
4
4
  * @module
5
5
  */
6
- import { eqStrict } from "./Eq.js";
6
+ import { eqSameValueZero } from "./Eq.js";
7
7
  import { createRef } from "./Ref.js";
8
8
  /**
9
9
  * Creates a store with the given initial state. The store encapsulates its
10
10
  * state, which can be read with `get` and updated with `set` or `update`. All
11
11
  * changes are broadcast to subscribers.
12
12
  *
13
- * By default, state changes are detected using strict equality (`===`). You can
14
- * provide a custom equality function as the second argument.
13
+ * By default, state changes are detected using {@link eqSameValueZero}, which
14
+ * considers `NaN` equal to itself and `0` equal to `-0`. You can provide a
15
+ * custom equality function as the second argument.
15
16
  */
16
17
  export const createStore = (initialState, eq) => {
17
- const equality = eq ?? eqStrict;
18
+ const equality = eq ?? eqSameValueZero;
18
19
  const ref = createRef(initialState);
19
20
  const listeners = new Set();
20
21
  const notifyIfChanged = (previousState) => {
@@ -1,7 +1,13 @@
1
1
  /**
2
- * String utilities for safe value conversion.
2
+ * String utilities.
3
3
  *
4
4
  * @module
5
5
  */
6
+ /**
7
+ * Escapes regular-expression syntax so a string can be used as a literal
8
+ * pattern.
9
+ */
10
+ export declare const escapeRegExp: (value: string) => string;
11
+ /** Converts an unknown value to a compact, human-readable diagnostic string. */
6
12
  export declare const safelyStringifyUnknownValue: (value: unknown) => string;
7
13
  //# sourceMappingURL=String.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"String.d.ts","sourceRoot":"","sources":["../../src/String.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,eAAO,MAAM,2BAA2B,GAAI,OAAO,OAAO,KAAG,MAS5D,CAAC"}
1
+ {"version":3,"file":"String.d.ts","sourceRoot":"","sources":["../../src/String.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;GAGG;AACH,eAAO,MAAM,YAAY,UAAW,MAAM,KAAG,MACC,CAAC;AAE/C,gFAAgF;AAChF,eAAO,MAAM,2BAA2B,UAAW,OAAO,KAAG,MAkB5D,CAAC"}
@@ -1,19 +1,32 @@
1
1
  /**
2
- * String utilities for safe value conversion.
2
+ * String utilities.
3
3
  *
4
4
  * @module
5
5
  */
6
+ /**
7
+ * Escapes regular-expression syntax so a string can be used as a literal
8
+ * pattern.
9
+ */
10
+ export const escapeRegExp = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
11
+ /** Converts an unknown value to a compact, human-readable diagnostic string. */
6
12
  export const safelyStringifyUnknownValue = (value) => {
7
- if (value === null)
8
- return "null";
9
- if (value === undefined)
10
- return "undefined";
11
13
  if (typeof value === "string")
12
- return `"${value}"`;
13
- try {
14
14
  return JSON.stringify(value);
15
+ if (value === null || typeof value !== "object")
16
+ return globalThis.String(value);
17
+ try {
18
+ // `JSON.stringify` can return `undefined` when `toJSON` does.
19
+ const stringifiedValue = JSON.stringify(value);
20
+ if (typeof stringifiedValue === "string")
21
+ return stringifiedValue;
15
22
  }
16
23
  catch {
24
+ // Fall through to a simpler representation.
25
+ }
26
+ try {
17
27
  return globalThis.String(value);
18
28
  }
29
+ catch {
30
+ return "[Unserializable value]";
31
+ }
19
32
  };