@hexclave/shared 1.0.28 → 1.0.29

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 (56) hide show
  1. package/dist/config/schema.d.ts +45 -45
  2. package/dist/esm/config/schema.d.ts +45 -45
  3. package/dist/esm/hooks/use-async-callback.js +1 -1
  4. package/dist/esm/hooks/use-async-external-store.js +1 -1
  5. package/dist/esm/hooks/use-strict-memo.js +1 -1
  6. package/dist/esm/interface/admin-interface.js +1 -1
  7. package/dist/esm/interface/admin-metrics.d.ts +13 -13
  8. package/dist/esm/interface/client-interface.js +1 -1
  9. package/dist/esm/interface/conversations.d.ts +28 -28
  10. package/dist/esm/interface/crud/current-user.d.ts +9 -9
  11. package/dist/esm/interface/crud/email-outbox.d.ts +248 -248
  12. package/dist/esm/interface/crud/invoices.d.ts +2 -2
  13. package/dist/esm/interface/crud/products.d.ts +9 -9
  14. package/dist/esm/interface/crud/products.d.ts.map +1 -1
  15. package/dist/esm/interface/crud/project-api-keys.d.ts +5 -5
  16. package/dist/esm/interface/crud/projects.d.ts +35 -35
  17. package/dist/esm/interface/crud/team-member-profiles.d.ts +14 -14
  18. package/dist/esm/interface/crud/transactions.d.ts +4 -4
  19. package/dist/esm/interface/crud/transactions.d.ts.map +1 -1
  20. package/dist/esm/interface/crud/users.d.ts +12 -12
  21. package/dist/esm/interface/plan-usage.d.ts +2 -2
  22. package/dist/esm/interface/server-interface.js +1 -1
  23. package/dist/esm/interface/webhooks.d.ts +2 -2
  24. package/dist/esm/sessions.d.ts +6 -6
  25. package/dist/esm/utils/promises.d.ts +12 -1
  26. package/dist/esm/utils/promises.d.ts.map +1 -1
  27. package/dist/esm/utils/promises.js +58 -2
  28. package/dist/esm/utils/promises.js.map +1 -1
  29. package/dist/hooks/use-async-callback.js +1 -1
  30. package/dist/hooks/use-async-external-store.js +1 -1
  31. package/dist/hooks/use-strict-memo.js +1 -1
  32. package/dist/interface/admin-interface.js +1 -1
  33. package/dist/interface/admin-metrics.d.ts +13 -13
  34. package/dist/interface/client-interface.js +1 -1
  35. package/dist/interface/conversations.d.ts +28 -28
  36. package/dist/interface/crud/current-user.d.ts +9 -9
  37. package/dist/interface/crud/email-outbox.d.ts +248 -248
  38. package/dist/interface/crud/invoices.d.ts +2 -2
  39. package/dist/interface/crud/products.d.ts +9 -9
  40. package/dist/interface/crud/products.d.ts.map +1 -1
  41. package/dist/interface/crud/project-api-keys.d.ts +5 -5
  42. package/dist/interface/crud/projects.d.ts +35 -35
  43. package/dist/interface/crud/team-member-profiles.d.ts +14 -14
  44. package/dist/interface/crud/transactions.d.ts +4 -4
  45. package/dist/interface/crud/transactions.d.ts.map +1 -1
  46. package/dist/interface/crud/users.d.ts +12 -12
  47. package/dist/interface/plan-usage.d.ts +2 -2
  48. package/dist/interface/server-interface.js +1 -1
  49. package/dist/interface/webhooks.d.ts +2 -2
  50. package/dist/sessions.d.ts +6 -6
  51. package/dist/utils/promises.d.ts +12 -1
  52. package/dist/utils/promises.d.ts.map +1 -1
  53. package/dist/utils/promises.js +58 -1
  54. package/dist/utils/promises.js.map +1 -1
  55. package/package.json +1 -1
  56. package/src/utils/promises.tsx +65 -0
@@ -51,6 +51,17 @@ declare class TimeoutError extends Error {
51
51
  }
52
52
  declare function timeout<T>(promiseOrFunc: Promise<T> | (() => Promise<T>), ms: number): Promise<Result<T, TimeoutError>>;
53
53
  declare function timeoutThrow<T>(promise: Promise<T>, ms: number): Promise<T>;
54
+ /**
55
+ * Maps over `items` with `fn`, running at most `concurrency` invocations at a time.
56
+ *
57
+ * Unlike `Promise.all(items.map(fn))`, this bounds the number of in-flight
58
+ * promises, which matters when `fn` hits a shared resource (e.g. a database) and
59
+ * an unbounded fan-out could exhaust connections or overload a replica. Results
60
+ * are returned in input order regardless of completion order, and the first
61
+ * rejection aborts further scheduling — already in-flight workers still settle
62
+ * but no new items are started.
63
+ */
64
+ declare function mapWithConcurrency<T, R>(items: readonly T[], concurrency: number, fn: (item: T, index: number) => Promise<R>): Promise<R[]>;
54
65
  type RateLimitOptions = {
55
66
  /**
56
67
  * The number of requests to process in parallel. Currently only 1 is supported.
@@ -76,5 +87,5 @@ type RateLimitOptions = {
76
87
  declare function rateLimited<T>(func: () => Promise<T>, options: RateLimitOptions): () => Promise<T>;
77
88
  declare function throttled<T, A extends any[]>(func: (...args: A) => Promise<T>, delayMs: number): (...args: A) => Promise<T>;
78
89
  //#endregion
79
- export { RateLimitOptions, ReactPromise, concatStacktracesIfRejected, createPromise, ignoreUnhandledRejection, neverResolve, pending, rateLimited, rejected, resolved, runAsynchronously, runAsynchronouslyWithAlert, throttled, timeout, timeoutThrow, wait, waitUntil };
90
+ export { RateLimitOptions, ReactPromise, concatStacktracesIfRejected, createPromise, ignoreUnhandledRejection, mapWithConcurrency, neverResolve, pending, rateLimited, rejected, resolved, runAsynchronously, runAsynchronouslyWithAlert, throttled, timeout, timeoutThrow, wait, waitUntil };
80
91
  //# sourceMappingURL=promises.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"promises.d.ts","names":[],"sources":["../../../src/utils/promises.tsx"],"mappings":";;;KAQY,YAAA,MAAkB,OAAA,CAAQ,CAAA;EAChC,MAAA;EAAoB,MAAA;AAAA;EACpB,MAAA;EAAqB,KAAA,EAAO,CAAA;AAAA;EAC5B,MAAA;AAAA;AAAA,KAGD,OAAA,OAAc,KAAA,EAAO,CAAA;AAAA,KACrB,MAAA,IAAU,MAAA;AAAA,iBACC,aAAA,GAAA,CAAiB,QAAA,GAAW,OAAA,EAAS,OAAA,CAAQ,CAAA,GAAI,MAAA,EAAQ,MAAA,YAAkB,YAAA,CAAa,CAAA;;;;;iBAwExF,QAAA,GAAA,CAAY,KAAA,EAAO,CAAA,GAAI,YAAA,CAAa,CAAA;;;;;iBA0CpC,QAAA,GAAA,CAAY,MAAA,YAAkB,YAAA,CAAa,CAAA;AAAA,iBA6C3C,YAAA,CAAA,GAAgB,YAAA;AAAA,iBAchB,OAAA,GAAA,CAAW,OAAA,EAAS,OAAA,CAAQ,CAAA,GAAI,OAAA;EAAW,oBAAA;AAAA,IAAwC,YAAA,CAAa,CAAA;;;;;AA/KrF;;iBAuNX,wBAAA,WAAmC,OAAA,MAAA,CAAc,OAAA,EAAS,CAAA;;;AArN1E;iBA0OgB,2BAAA,GAAA,CAA+B,OAAA,EAAS,OAAA,CAAQ,CAAA;AAAA,iBAW1C,IAAA,CAAK,EAAA,WAAU,OAAA;AAAA,iBAgCf,SAAA,CAAU,IAAA,EAAM,IAAA,GAAI,OAAA;AAAA,iBAsB1B,0BAAA,CAAA,GAA8B,IAAA,EAAM,UAAA,QAAkB,iBAAA;AAAA,iBAgCtD,iBAAA,CACd,aAAA,SAAsB,OAAA,0BAAiC,OAAA,wBACvD,OAAA;EACE,cAAA;EACA,OAAA,IAAW,KAAA,EAAO,KAAA;AAAA;AAAA,cAoChB,YAAA,SAAqB,KAAA;EAAA,SACG,EAAA;cAAA,EAAA;AAAA;AAAA,iBAMR,OAAA,GAAA,CAAW,aAAA,EAAe,OAAA,CAAQ,CAAA,WAAY,OAAA,CAAQ,CAAA,IAAK,EAAA,WAAa,OAAA,CAAQ,MAAA,CAAO,CAAA,EAAG,YAAA;AAAA,iBA0B1F,YAAA,GAAA,CAAgB,OAAA,EAAS,OAAA,CAAQ,CAAA,GAAI,EAAA,WAAa,OAAA,CAAQ,CAAA;AAAA,KAgBpE,gBAAA;EApaqB;;;EAwa/B,WAAA;EAxauG;AAwEzG;;EAqWE,UAAA;EArWiC;;;EA0WjC,UAAA;EA1WiD;;;EA+WjD,KAAA;EA/WqC;;;EAoXrC,UAAA;AAAA;AAAA,iBAGc,WAAA,GAAA,CACd,IAAA,QAAY,OAAA,CAAQ,CAAA,GACpB,OAAA,EAAS,gBAAA,SACF,OAAA,CAAQ,CAAA;AAAA,iBA0DD,SAAA,oBAAA,CAA8B,IAAA,MAAU,IAAA,EAAM,CAAA,KAAM,OAAA,CAAQ,CAAA,GAAI,OAAA,eAAsB,IAAA,EAAM,CAAA,KAAM,OAAA,CAAQ,CAAA"}
1
+ {"version":3,"file":"promises.d.ts","names":[],"sources":["../../../src/utils/promises.tsx"],"mappings":";;;KAQY,YAAA,MAAkB,OAAA,CAAQ,CAAA;EAChC,MAAA;EAAoB,MAAA;AAAA;EACpB,MAAA;EAAqB,KAAA,EAAO,CAAA;AAAA;EAC5B,MAAA;AAAA;AAAA,KAGD,OAAA,OAAc,KAAA,EAAO,CAAA;AAAA,KACrB,MAAA,IAAU,MAAA;AAAA,iBACC,aAAA,GAAA,CAAiB,QAAA,GAAW,OAAA,EAAS,OAAA,CAAQ,CAAA,GAAI,MAAA,EAAQ,MAAA,YAAkB,YAAA,CAAa,CAAA;;;;;iBAwExF,QAAA,GAAA,CAAY,KAAA,EAAO,CAAA,GAAI,YAAA,CAAa,CAAA;;;;;iBA0CpC,QAAA,GAAA,CAAY,MAAA,YAAkB,YAAA,CAAa,CAAA;AAAA,iBA6C3C,YAAA,CAAA,GAAgB,YAAA;AAAA,iBAchB,OAAA,GAAA,CAAW,OAAA,EAAS,OAAA,CAAQ,CAAA,GAAI,OAAA;EAAW,oBAAA;AAAA,IAAwC,YAAA,CAAa,CAAA;;;;;AA/KrF;;iBAuNX,wBAAA,WAAmC,OAAA,MAAA,CAAc,OAAA,EAAS,CAAA;;;AArN1E;iBA0OgB,2BAAA,GAAA,CAA+B,OAAA,EAAS,OAAA,CAAQ,CAAA;AAAA,iBAW1C,IAAA,CAAK,EAAA,WAAU,OAAA;AAAA,iBAgCf,SAAA,CAAU,IAAA,EAAM,IAAA,GAAI,OAAA;AAAA,iBAsB1B,0BAAA,CAAA,GAA8B,IAAA,EAAM,UAAA,QAAkB,iBAAA;AAAA,iBAgCtD,iBAAA,CACd,aAAA,SAAsB,OAAA,0BAAiC,OAAA,wBACvD,OAAA;EACE,cAAA;EACA,OAAA,IAAW,KAAA,EAAO,KAAA;AAAA;AAAA,cAoChB,YAAA,SAAqB,KAAA;EAAA,SACG,EAAA;cAAA,EAAA;AAAA;AAAA,iBAMR,OAAA,GAAA,CAAW,aAAA,EAAe,OAAA,CAAQ,CAAA,WAAY,OAAA,CAAQ,CAAA,IAAK,EAAA,WAAa,OAAA,CAAQ,MAAA,CAAO,CAAA,EAAG,YAAA;AAAA,iBA0B1F,YAAA,GAAA,CAAgB,OAAA,EAAS,OAAA,CAAQ,CAAA,GAAI,EAAA,WAAa,OAAA,CAAQ,CAAA;;;;;;;AA5UhF;;;;iBAsWsB,kBAAA,MAAA,CACpB,KAAA,WAAgB,CAAA,IAChB,WAAA,UACA,EAAA,GAAK,IAAA,EAAM,CAAA,EAAG,KAAA,aAAkB,OAAA,CAAQ,CAAA,IACvC,OAAA,CAAQ,CAAA;AAAA,KAmDC,gBAAA;EA7ZuC;;;EAiajD,WAAA;EAja0B;;;EAsa1B,UAAA;EAtamD;AA0CrD;;EAiYE,UAAA;EAjYwD;;;EAsYxD,KAAA;EAtYyD;;;EA2YzD,UAAA;AAAA;AAAA,iBAGc,WAAA,GAAA,CACd,IAAA,QAAY,OAAA,CAAQ,CAAA,GACpB,OAAA,EAAS,gBAAA,SACF,OAAA,CAAQ,CAAA;AAAA,iBA0DD,SAAA,oBAAA,CAA8B,IAAA,MAAU,IAAA,EAAM,CAAA,KAAM,OAAA,CAAQ,CAAA,GAAI,OAAA,eAAsB,IAAA,EAAM,CAAA,KAAM,OAAA,CAAQ,CAAA"}
@@ -1,9 +1,9 @@
1
+ import { KnownError } from "../index.js";
1
2
  import { HexclaveAssertionError, captureError, concatStacktraces, errorToNiceString } from "./errors.js";
2
3
  import { getProcessEnv } from "./env.js";
3
4
  import { DependenciesMap } from "./maps.js";
4
5
  import { Result } from "./results.js";
5
6
  import { traceSpan } from "./telemetry.js";
6
- import { KnownError } from "../index.js";
7
7
  import { generateUuid } from "./uuids.js";
8
8
 
9
9
  //#region src/utils/promises.tsx
@@ -282,6 +282,62 @@ async function timeoutThrow(promise, ms) {
282
282
  await expect(timeoutThrow(slowPromise, 10)).rejects.toThrow("Timeout after 10ms");
283
283
  await expect(timeoutThrow(slowPromise, 10)).rejects.toBeInstanceOf(TimeoutError);
284
284
  });
285
+ /**
286
+ * Maps over `items` with `fn`, running at most `concurrency` invocations at a time.
287
+ *
288
+ * Unlike `Promise.all(items.map(fn))`, this bounds the number of in-flight
289
+ * promises, which matters when `fn` hits a shared resource (e.g. a database) and
290
+ * an unbounded fan-out could exhaust connections or overload a replica. Results
291
+ * are returned in input order regardless of completion order, and the first
292
+ * rejection aborts further scheduling — already in-flight workers still settle
293
+ * but no new items are started.
294
+ */
295
+ async function mapWithConcurrency(items, concurrency, fn) {
296
+ if (!Number.isInteger(concurrency) || concurrency < 1) throw new HexclaveAssertionError(`mapWithConcurrency requires a positive integer concurrency, got ${concurrency}`);
297
+ const results = new Array(items.length);
298
+ let nextIndex = 0;
299
+ let aborted = false;
300
+ const worker = async () => {
301
+ while (!aborted) {
302
+ const index = nextIndex++;
303
+ if (index >= items.length) return;
304
+ try {
305
+ results[index] = await fn(items[index], index);
306
+ } catch (error) {
307
+ aborted = true;
308
+ throw error;
309
+ }
310
+ }
311
+ };
312
+ const workerCount = Math.min(concurrency, items.length);
313
+ await Promise.all(Array.from({ length: workerCount }, () => worker()));
314
+ return results;
315
+ }
316
+ (void 0)?.test("mapWithConcurrency", async ({ expect }) => {
317
+ expect(await mapWithConcurrency([
318
+ 30,
319
+ 10,
320
+ 20
321
+ ], 3, async (ms, index) => {
322
+ await wait(ms);
323
+ return `${index}:${ms}`;
324
+ })).toEqual([
325
+ "0:30",
326
+ "1:10",
327
+ "2:20"
328
+ ]);
329
+ let inFlight = 0;
330
+ let maxInFlight = 0;
331
+ await mapWithConcurrency(Array.from({ length: 10 }, (_, i) => i), 3, async () => {
332
+ inFlight++;
333
+ maxInFlight = Math.max(maxInFlight, inFlight);
334
+ await wait(5);
335
+ inFlight--;
336
+ });
337
+ expect(maxInFlight).toBe(3);
338
+ expect(await mapWithConcurrency([], 4, async () => 1)).toEqual([]);
339
+ await expect(mapWithConcurrency([1], 0, async (x) => x)).rejects.toThrow("positive integer concurrency");
340
+ });
285
341
  function rateLimited(func, options) {
286
342
  let waitUntil = performance.now();
287
343
  let queue = [];
@@ -329,5 +385,5 @@ function throttled(func, delayMs) {
329
385
  }
330
386
 
331
387
  //#endregion
332
- export { concatStacktracesIfRejected, createPromise, ignoreUnhandledRejection, neverResolve, pending, rateLimited, rejected, resolved, runAsynchronously, runAsynchronouslyWithAlert, throttled, timeout, timeoutThrow, wait, waitUntil };
388
+ export { concatStacktracesIfRejected, createPromise, ignoreUnhandledRejection, mapWithConcurrency, neverResolve, pending, rateLimited, rejected, resolved, runAsynchronously, runAsynchronouslyWithAlert, throttled, timeout, timeoutThrow, wait, waitUntil };
333
389
  //# sourceMappingURL=promises.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"promises.js","names":[],"sources":["../../../src/utils/promises.tsx"],"sourcesContent":["import { KnownError } from \"..\";\nimport { getProcessEnv } from \"./env\";\nimport { HexclaveAssertionError, captureError, concatStacktraces, errorToNiceString } from \"./errors\";\nimport { DependenciesMap } from \"./maps\";\nimport { Result } from \"./results\";\nimport { traceSpan } from \"./telemetry\";\nimport { generateUuid } from \"./uuids\";\n\nexport type ReactPromise<T> = Promise<T> & (\n | { status: \"rejected\", reason: unknown }\n | { status: \"fulfilled\", value: T }\n | { status: \"pending\" }\n);\n\ntype Resolve<T> = (value: T) => void;\ntype Reject = (reason: unknown) => void;\nexport function createPromise<T>(callback: (resolve: Resolve<T>, reject: Reject) => void): ReactPromise<T> {\n let status = \"pending\" as \"fulfilled\" | \"rejected\" | \"pending\";\n let valueOrReason: T | unknown | undefined = undefined;\n let resolve: Resolve<T> | null = null;\n let reject: Reject | null = null;\n const promise = new Promise<T>((res, rej) => {\n resolve = (value) => {\n if (status !== \"pending\") return;\n status = \"fulfilled\";\n valueOrReason = value;\n res(value);\n };\n reject = (reason) => {\n if (status !== \"pending\") return;\n status = \"rejected\";\n valueOrReason = reason;\n rej(reason);\n };\n });\n\n callback(resolve!, reject!);\n return Object.assign(promise, {\n status: status,\n ...status === \"fulfilled\" ? { value: valueOrReason as T } : {},\n ...status === \"rejected\" ? { reason: valueOrReason } : {},\n } as any);\n}\nimport.meta.vitest?.test(\"createPromise\", async ({ expect }) => {\n // Test resolved promise\n const resolvedPromise = createPromise<number>((resolve) => {\n resolve(42);\n });\n expect(resolvedPromise.status).toBe(\"fulfilled\");\n expect((resolvedPromise as any).value).toBe(42);\n expect(await resolvedPromise).toBe(42);\n\n // Test rejected promise\n const error = new Error(\"Test error\");\n const rejectedPromise = createPromise<number>((_, reject) => {\n reject(error);\n });\n expect(rejectedPromise.status).toBe(\"rejected\");\n expect((rejectedPromise as any).reason).toBe(error);\n await expect(rejectedPromise).rejects.toBe(error);\n\n // Test pending promise\n const pendingPromise = createPromise<number>(() => {\n // Do nothing, leave it pending\n });\n expect(pendingPromise.status).toBe(\"pending\");\n expect((pendingPromise as any).value).toBeUndefined();\n expect((pendingPromise as any).reason).toBeUndefined();\n\n // Test that resolving after already resolved does nothing\n let resolveCount = 0;\n const multiResolvePromise = createPromise<number>((resolve) => {\n resolve(1);\n resolveCount++;\n resolve(2);\n resolveCount++;\n });\n expect(resolveCount).toBe(2); // Both resolve calls executed\n expect(multiResolvePromise.status).toBe(\"fulfilled\");\n expect((multiResolvePromise as any).value).toBe(1); // Only first resolve took effect\n expect(await multiResolvePromise).toBe(1);\n});\n\nlet resolvedCache: DependenciesMap<[unknown], ReactPromise<unknown>> | null = null;\n/**\n * Like Promise.resolve(...), but also adds the status and value properties for use with React's `use` hook, and caches\n * the value so that invoking `resolved` twice returns the same promise.\n */\nexport function resolved<T>(value: T): ReactPromise<T> {\n resolvedCache ??= new DependenciesMap<[unknown], ReactPromise<unknown>>();\n if (resolvedCache.has([value])) {\n return resolvedCache.get([value]) as ReactPromise<T>;\n }\n\n const res = Object.assign(Promise.resolve(value), {\n status: \"fulfilled\",\n value,\n } as const);\n resolvedCache.set([value], res);\n return res;\n}\nimport.meta.vitest?.test(\"resolved\", async ({ expect }) => {\n // Test with primitive value\n const promise1 = resolved(42);\n expect(promise1.status).toBe(\"fulfilled\");\n // Need to use type assertion since value is only available when status is \"fulfilled\"\n expect((promise1 as { value: number }).value).toBe(42);\n expect(await promise1).toBe(42);\n\n // Test with object value\n const obj = { test: true };\n const promise2 = resolved(obj);\n expect(promise2.status).toBe(\"fulfilled\");\n expect((promise2 as { value: typeof obj }).value).toBe(obj);\n expect(await promise2).toBe(obj);\n\n // Test caching (same reference for same value)\n const promise3 = resolved(42);\n expect(promise3).toBe(promise1); // Same reference due to caching\n\n // Test with different value (different reference)\n const promise4 = resolved(43);\n expect(promise4).not.toBe(promise1);\n});\n\nlet rejectedCache: DependenciesMap<[unknown], ReactPromise<unknown>> | null = null;\n/**\n * Like Promise.reject(...), but also adds the status and value properties for use with React's `use` hook, and caches\n * the value so that invoking `rejected` twice returns the same promise.\n */\nexport function rejected<T>(reason: unknown): ReactPromise<T> {\n rejectedCache ??= new DependenciesMap<[unknown], ReactPromise<unknown>>();\n if (rejectedCache.has([reason])) {\n return rejectedCache.get([reason]) as ReactPromise<T>;\n }\n\n const promise = Promise.reject(reason);\n ignoreUnhandledRejection(promise);\n const res = Object.assign(promise, {\n status: \"rejected\",\n reason: reason,\n } as const);\n rejectedCache.set([reason], res);\n return res;\n}\nimport.meta.vitest?.test(\"rejected\", ({ expect }) => {\n // Test with error object\n const error = new Error(\"Test error\");\n const promise1 = rejected<number>(error);\n expect(promise1.status).toBe(\"rejected\");\n // Need to use type assertion since reason is only available when status is \"rejected\"\n expect((promise1 as { reason: Error }).reason).toBe(error);\n\n // Test with string reason\n const promise2 = rejected<string>(\"error message\");\n expect(promise2.status).toBe(\"rejected\");\n expect((promise2 as { reason: string }).reason).toBe(\"error message\");\n\n // Test caching (same reference for same reason)\n const promise3 = rejected<number>(error);\n expect(promise3).toBe(promise1); // Same reference due to caching\n\n // Test with different reason (different reference)\n const differentError = new Error(\"Different error\");\n const promise4 = rejected<number>(differentError);\n expect(promise4).not.toBe(promise1);\n\n // Note: We're not using await expect(promise).rejects to avoid unhandled rejections\n});\n\n// We'll skip the rejection test for pending() since it's causing unhandled rejections\n// The function is already well tested through other tests like rejected() and createPromise()\n\n\nconst neverResolvePromise = pending(new Promise<never>(() => {}));\nexport function neverResolve(): ReactPromise<never> {\n return neverResolvePromise;\n}\nimport.meta.vitest?.test(\"neverResolve\", ({ expect }) => {\n const promise = neverResolve();\n expect(promise.status).toBe(\"pending\");\n expect((promise as any).value).toBeUndefined();\n expect((promise as any).reason).toBeUndefined();\n\n // Test that multiple calls return the same promise\n const promise2 = neverResolve();\n expect(promise2).toBe(promise);\n});\n\nexport function pending<T>(promise: Promise<T>, options: { disableErrorWrapping?: boolean } = {}): ReactPromise<T> {\n const res = promise.then(\n value => {\n res.status = \"fulfilled\";\n (res as any).value = value;\n return value;\n },\n actualReason => {\n res.status = \"rejected\";\n (res as any).reason = actualReason;\n throw actualReason;\n },\n ) as ReactPromise<T>;\n res.status = \"pending\";\n return res;\n}\nimport.meta.vitest?.test(\"pending\", async ({ expect }) => {\n // Test with a promise that resolves\n const resolvePromise = Promise.resolve(42);\n const pendingPromise = pending(resolvePromise);\n\n // Initially it should be pending\n expect(pendingPromise.status).toBe(\"pending\");\n\n // After resolution, it should be fulfilled\n await resolvePromise;\n // Need to wait a tick for the then handler to execute\n await new Promise(resolve => setTimeout(resolve, 0));\n expect(pendingPromise.status).toBe(\"fulfilled\");\n expect((pendingPromise as { value: number }).value).toBe(42);\n\n // For the rejection test, we'll use a separate test to avoid unhandled rejections\n});\n\n/**\n * Should be used to wrap Promises that are not immediately awaited, so they don't throw an unhandled promise rejection\n * error.\n *\n * Vercel kills serverless functions on unhandled promise rejection errors, so this is important.\n */\nexport function ignoreUnhandledRejection<T extends Promise<any>>(promise: T): void {\n promise.catch(() => {});\n}\nimport.meta.vitest?.test(\"ignoreUnhandledRejection\", async ({ expect }) => {\n // Test with a promise that resolves\n const resolvePromise = Promise.resolve(42);\n ignoreUnhandledRejection(resolvePromise);\n expect(await resolvePromise).toBe(42); // Should still resolve to the same value\n\n // Test with a promise that rejects\n // The promise should still reject, but the rejection is caught internally\n // so it doesn't cause an unhandled rejection error\n const error = new Error(\"Test error\");\n const rejectPromise = Promise.reject(error);\n ignoreUnhandledRejection(rejectPromise);\n await expect(rejectPromise).rejects.toBe(error);\n});\n\n/**\n * See concatStacktraces for more information.\n */\nexport function concatStacktracesIfRejected<T>(promise: Promise<T>): void {\n const currentError = new Error();\n promise.catch(error => {\n if (error instanceof Error) {\n concatStacktraces(error, currentError);\n } else {\n // we can only concatenate errors, so we'll just ignore the non-error\n }\n });\n}\n\nexport async function wait(ms: number) {\n if (!Number.isFinite(ms) || ms < 0) {\n throw new HexclaveAssertionError(`wait() requires a non-negative integer number of milliseconds to wait. (found: ${ms}ms)`);\n }\n if (ms >= 2**31) {\n throw new HexclaveAssertionError(\"The maximum timeout for wait() is 2147483647ms (2**31 - 1). (found: ${ms}ms)\");\n }\n return await traceSpan({ description: 'wait(...)', attributes: { 'stack.wait.ms': ms } }, async (span) => {\n return await new Promise<void>(resolve => setTimeout(resolve, ms));\n });\n}\nimport.meta.vitest?.test(\"wait\", async ({ expect }) => {\n // Test with valid input\n const start = Date.now();\n await wait(10);\n const elapsed = Date.now() - start;\n expect(elapsed).toBeGreaterThanOrEqual(5); // Allow some flexibility in timing\n\n // Test with zero\n await expect(wait(0)).resolves.toBeUndefined();\n\n // Test with negative number\n await expect(wait(-10)).rejects.toThrow(\"wait() requires a non-negative integer\");\n\n // Test with non-finite number\n await expect(wait(NaN)).rejects.toThrow(\"wait() requires a non-negative integer\");\n await expect(wait(Infinity)).rejects.toThrow(\"wait() requires a non-negative integer\");\n\n // Test with too large number\n await expect(wait(2**31)).rejects.toThrow(\"The maximum timeout for wait()\");\n});\n\nexport async function waitUntil(date: Date) {\n return await wait(date.getTime() - Date.now());\n}\nimport.meta.vitest?.test(\"waitUntil\", async ({ expect }) => {\n // Test with future date\n const futureDate = new Date(Date.now() + 10);\n const start = Date.now();\n await waitUntil(futureDate);\n const elapsed = Date.now() - start;\n expect(elapsed).toBeGreaterThanOrEqual(5); // Allow some flexibility in timing\n\n // Test with past date - this will throw because wait() requires non-negative time\n // We need to verify it throws the correct error\n try {\n await waitUntil(new Date(Date.now() - 1000));\n expect.fail(\"Should have thrown an error\");\n } catch (error) {\n expect(error).toBeInstanceOf(HexclaveAssertionError);\n expect((error as Error).message).toContain(\"wait() requires a non-negative integer\");\n }\n});\n\nexport function runAsynchronouslyWithAlert(...args: Parameters<typeof runAsynchronously>) {\n return runAsynchronously(\n args[0],\n {\n ...args[1],\n onError: error => {\n const nodeEnv = getProcessEnv(\"NODE_ENV\");\n if (KnownError.isKnownError(error) && nodeEnv?.includes(\"production\")) {\n alert(error.message);\n } else {\n alert(`An unhandled error occurred. Please ${nodeEnv === \"development\" ? `check the browser console for the full error.` : \"report this to the developer.\"}\\n\\n${error}`);\n }\n args[1]?.onError?.(error);\n },\n },\n ...args.slice(2) as [],\n );\n}\nimport.meta.vitest?.test(\"runAsynchronouslyWithAlert\", ({ expect }) => {\n // Simple test to verify the function calls runAsynchronously\n // We can't easily test the alert functionality without mocking\n const testFn = () => Promise.resolve(\"test\");\n const testOptions = { noErrorLogging: true };\n\n // Just verify it doesn't throw\n expect(() => runAsynchronouslyWithAlert(testFn, testOptions)).not.toThrow();\n\n // We can't easily test the error handling without mocking, so we'll\n // just verify the function exists and can be called\n expect(typeof runAsynchronouslyWithAlert).toBe(\"function\");\n});\n\nexport function runAsynchronously(\n promiseOrFunc: void | Promise<unknown> | (() => void | Promise<unknown>) | undefined,\n options: {\n noErrorLogging?: boolean,\n onError?: (error: Error) => void,\n } = {},\n): void {\n if (typeof promiseOrFunc === \"function\") {\n promiseOrFunc = promiseOrFunc();\n }\n if (promiseOrFunc) {\n concatStacktracesIfRejected(promiseOrFunc);\n promiseOrFunc.catch(error => {\n options.onError?.(error);\n const newError = new HexclaveAssertionError(\n \"Uncaught error in asynchronous function: \" + errorToNiceString(error),\n { cause: error },\n );\n if (!options.noErrorLogging) {\n captureError(\"runAsynchronously\", newError);\n }\n });\n }\n}\nimport.meta.vitest?.test(\"runAsynchronously\", ({ expect }) => {\n // Simple test to verify the function exists and can be called\n const testFn = () => Promise.resolve(\"test\");\n\n // Just verify it doesn't throw\n expect(() => runAsynchronously(testFn)).not.toThrow();\n expect(() => runAsynchronously(Promise.resolve(\"test\"))).not.toThrow();\n expect(() => runAsynchronously(undefined)).not.toThrow();\n\n // We can't easily test the error handling without mocking, so we'll\n // just verify the function exists and can be called with options\n expect(() => runAsynchronously(testFn, { noErrorLogging: true })).not.toThrow();\n expect(() => runAsynchronously(testFn, { onError: () => {} })).not.toThrow();\n});\n\n\nclass TimeoutError extends Error {\n constructor(public readonly ms: number) {\n super(`Timeout after ${ms}ms`);\n this.name = \"TimeoutError\";\n }\n}\n\nexport async function timeout<T>(promiseOrFunc: Promise<T> | (() => Promise<T>), ms: number): Promise<Result<T, TimeoutError>> {\n const promise = typeof promiseOrFunc === \"function\" ? promiseOrFunc() : promiseOrFunc;\n return await Promise.race([\n promise.then(value => Result.ok(value)),\n wait(ms).then(() => Result.error(new TimeoutError(ms))),\n ]);\n}\nimport.meta.vitest?.test(\"timeout\", async ({ expect }) => {\n // Test with a promise that resolves quickly\n const fastPromise = Promise.resolve(42);\n const fastResult = await timeout(fastPromise, 100);\n expect(fastResult.status).toBe(\"ok\");\n if (fastResult.status === \"ok\") {\n expect(fastResult.data).toBe(42);\n }\n\n // Test with a promise that takes longer than the timeout\n const slowPromise = new Promise(resolve => setTimeout(() => resolve(\"too late\"), 50));\n const slowResult = await timeout(slowPromise, 10);\n expect(slowResult.status).toBe(\"error\");\n if (slowResult.status === \"error\") {\n expect(slowResult.error).toBeInstanceOf(TimeoutError);\n expect((slowResult.error as TimeoutError).ms).toBe(10);\n }\n});\n\nexport async function timeoutThrow<T>(promise: Promise<T>, ms: number): Promise<T> {\n return Result.orThrow(await timeout(promise, ms));\n}\nimport.meta.vitest?.test(\"timeoutThrow\", async ({ expect }) => {\n // Test with a promise that resolves quickly\n const fastPromise = Promise.resolve(42);\n const fastResult = await timeoutThrow(fastPromise, 100);\n expect(fastResult).toBe(42);\n\n // Test with a promise that takes longer than the timeout\n const slowPromise = new Promise(resolve => setTimeout(() => resolve(\"too late\"), 50));\n await expect(timeoutThrow(slowPromise, 10)).rejects.toThrow(\"Timeout after 10ms\");\n await expect(timeoutThrow(slowPromise, 10)).rejects.toBeInstanceOf(TimeoutError);\n});\n\n\nexport type RateLimitOptions = {\n /**\n * The number of requests to process in parallel. Currently only 1 is supported.\n */\n concurrency: 1,\n\n /**\n * If true, multiple requests waiting at the same time will be reduced to just one. Default is false.\n */\n batchCalls?: boolean,\n\n /**\n * Waits for throttleMs since the start of last request before starting the next request. Default is 0.\n */\n throttleMs?: number,\n\n /**\n * Waits for gapMs since the end of last request before starting the next request. Default is 0.\n */\n gapMs?: number,\n\n /**\n * Waits until there have been no new requests for debounceMs before starting a new request. Default is 0.\n */\n debounceMs?: number,\n};\n\nexport function rateLimited<T>(\n func: () => Promise<T>,\n options: RateLimitOptions,\n): () => Promise<T> {\n let waitUntil = performance.now();\n let queue: [(t: T) => void, (e: unknown) => void][] = [];\n let addedToQueueCallbacks = new Map<string, () => void>;\n\n const next = async () => {\n while (true) {\n if (waitUntil > performance.now()) {\n await wait(Math.max(1, waitUntil - performance.now() + 1));\n } else if (queue.length === 0) {\n const uuid = generateUuid();\n await new Promise<void>(resolve => {\n addedToQueueCallbacks.set(uuid, resolve);\n });\n addedToQueueCallbacks.delete(uuid);\n } else {\n break;\n }\n }\n const nextFuncs = options.batchCalls ? queue.splice(0, queue.length) : [queue.shift()!];\n\n const start = performance.now();\n const value = await Result.fromPromise(func());\n const end = performance.now();\n\n waitUntil = Math.max(\n waitUntil,\n start + (options.throttleMs ?? 0),\n end + (options.gapMs ?? 0),\n );\n\n for (const nextFunc of nextFuncs) {\n if (value.status === \"ok\") {\n nextFunc[0](value.data);\n } else {\n nextFunc[1](value.error);\n }\n }\n };\n\n runAsynchronously(async () => {\n while (true) {\n await next();\n }\n });\n\n return () => {\n return new Promise<T>((resolve, reject) => {\n waitUntil = Math.max(\n waitUntil,\n performance.now() + (options.debounceMs ?? 0),\n );\n queue.push([resolve, reject]);\n addedToQueueCallbacks.forEach(cb => cb());\n });\n };\n}\n\nexport function throttled<T, A extends any[]>(func: (...args: A) => Promise<T>, delayMs: number): (...args: A) => Promise<T> {\n let timeout: ReturnType<typeof setTimeout> | null = null;\n let nextAvailable: Promise<T> | null = null;\n return async (...args) => {\n while (nextAvailable !== null) {\n await nextAvailable;\n }\n nextAvailable = new Promise<T>(resolve => {\n timeout = setTimeout(() => {\n nextAvailable = null;\n resolve(func(...args));\n }, delayMs);\n });\n return await nextAvailable;\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"promises.js","names":[],"sources":["../../../src/utils/promises.tsx"],"sourcesContent":["import { KnownError } from \"..\";\nimport { getProcessEnv } from \"./env\";\nimport { HexclaveAssertionError, captureError, concatStacktraces, errorToNiceString } from \"./errors\";\nimport { DependenciesMap } from \"./maps\";\nimport { Result } from \"./results\";\nimport { traceSpan } from \"./telemetry\";\nimport { generateUuid } from \"./uuids\";\n\nexport type ReactPromise<T> = Promise<T> & (\n | { status: \"rejected\", reason: unknown }\n | { status: \"fulfilled\", value: T }\n | { status: \"pending\" }\n);\n\ntype Resolve<T> = (value: T) => void;\ntype Reject = (reason: unknown) => void;\nexport function createPromise<T>(callback: (resolve: Resolve<T>, reject: Reject) => void): ReactPromise<T> {\n let status = \"pending\" as \"fulfilled\" | \"rejected\" | \"pending\";\n let valueOrReason: T | unknown | undefined = undefined;\n let resolve: Resolve<T> | null = null;\n let reject: Reject | null = null;\n const promise = new Promise<T>((res, rej) => {\n resolve = (value) => {\n if (status !== \"pending\") return;\n status = \"fulfilled\";\n valueOrReason = value;\n res(value);\n };\n reject = (reason) => {\n if (status !== \"pending\") return;\n status = \"rejected\";\n valueOrReason = reason;\n rej(reason);\n };\n });\n\n callback(resolve!, reject!);\n return Object.assign(promise, {\n status: status,\n ...status === \"fulfilled\" ? { value: valueOrReason as T } : {},\n ...status === \"rejected\" ? { reason: valueOrReason } : {},\n } as any);\n}\nimport.meta.vitest?.test(\"createPromise\", async ({ expect }) => {\n // Test resolved promise\n const resolvedPromise = createPromise<number>((resolve) => {\n resolve(42);\n });\n expect(resolvedPromise.status).toBe(\"fulfilled\");\n expect((resolvedPromise as any).value).toBe(42);\n expect(await resolvedPromise).toBe(42);\n\n // Test rejected promise\n const error = new Error(\"Test error\");\n const rejectedPromise = createPromise<number>((_, reject) => {\n reject(error);\n });\n expect(rejectedPromise.status).toBe(\"rejected\");\n expect((rejectedPromise as any).reason).toBe(error);\n await expect(rejectedPromise).rejects.toBe(error);\n\n // Test pending promise\n const pendingPromise = createPromise<number>(() => {\n // Do nothing, leave it pending\n });\n expect(pendingPromise.status).toBe(\"pending\");\n expect((pendingPromise as any).value).toBeUndefined();\n expect((pendingPromise as any).reason).toBeUndefined();\n\n // Test that resolving after already resolved does nothing\n let resolveCount = 0;\n const multiResolvePromise = createPromise<number>((resolve) => {\n resolve(1);\n resolveCount++;\n resolve(2);\n resolveCount++;\n });\n expect(resolveCount).toBe(2); // Both resolve calls executed\n expect(multiResolvePromise.status).toBe(\"fulfilled\");\n expect((multiResolvePromise as any).value).toBe(1); // Only first resolve took effect\n expect(await multiResolvePromise).toBe(1);\n});\n\nlet resolvedCache: DependenciesMap<[unknown], ReactPromise<unknown>> | null = null;\n/**\n * Like Promise.resolve(...), but also adds the status and value properties for use with React's `use` hook, and caches\n * the value so that invoking `resolved` twice returns the same promise.\n */\nexport function resolved<T>(value: T): ReactPromise<T> {\n resolvedCache ??= new DependenciesMap<[unknown], ReactPromise<unknown>>();\n if (resolvedCache.has([value])) {\n return resolvedCache.get([value]) as ReactPromise<T>;\n }\n\n const res = Object.assign(Promise.resolve(value), {\n status: \"fulfilled\",\n value,\n } as const);\n resolvedCache.set([value], res);\n return res;\n}\nimport.meta.vitest?.test(\"resolved\", async ({ expect }) => {\n // Test with primitive value\n const promise1 = resolved(42);\n expect(promise1.status).toBe(\"fulfilled\");\n // Need to use type assertion since value is only available when status is \"fulfilled\"\n expect((promise1 as { value: number }).value).toBe(42);\n expect(await promise1).toBe(42);\n\n // Test with object value\n const obj = { test: true };\n const promise2 = resolved(obj);\n expect(promise2.status).toBe(\"fulfilled\");\n expect((promise2 as { value: typeof obj }).value).toBe(obj);\n expect(await promise2).toBe(obj);\n\n // Test caching (same reference for same value)\n const promise3 = resolved(42);\n expect(promise3).toBe(promise1); // Same reference due to caching\n\n // Test with different value (different reference)\n const promise4 = resolved(43);\n expect(promise4).not.toBe(promise1);\n});\n\nlet rejectedCache: DependenciesMap<[unknown], ReactPromise<unknown>> | null = null;\n/**\n * Like Promise.reject(...), but also adds the status and value properties for use with React's `use` hook, and caches\n * the value so that invoking `rejected` twice returns the same promise.\n */\nexport function rejected<T>(reason: unknown): ReactPromise<T> {\n rejectedCache ??= new DependenciesMap<[unknown], ReactPromise<unknown>>();\n if (rejectedCache.has([reason])) {\n return rejectedCache.get([reason]) as ReactPromise<T>;\n }\n\n const promise = Promise.reject(reason);\n ignoreUnhandledRejection(promise);\n const res = Object.assign(promise, {\n status: \"rejected\",\n reason: reason,\n } as const);\n rejectedCache.set([reason], res);\n return res;\n}\nimport.meta.vitest?.test(\"rejected\", ({ expect }) => {\n // Test with error object\n const error = new Error(\"Test error\");\n const promise1 = rejected<number>(error);\n expect(promise1.status).toBe(\"rejected\");\n // Need to use type assertion since reason is only available when status is \"rejected\"\n expect((promise1 as { reason: Error }).reason).toBe(error);\n\n // Test with string reason\n const promise2 = rejected<string>(\"error message\");\n expect(promise2.status).toBe(\"rejected\");\n expect((promise2 as { reason: string }).reason).toBe(\"error message\");\n\n // Test caching (same reference for same reason)\n const promise3 = rejected<number>(error);\n expect(promise3).toBe(promise1); // Same reference due to caching\n\n // Test with different reason (different reference)\n const differentError = new Error(\"Different error\");\n const promise4 = rejected<number>(differentError);\n expect(promise4).not.toBe(promise1);\n\n // Note: We're not using await expect(promise).rejects to avoid unhandled rejections\n});\n\n// We'll skip the rejection test for pending() since it's causing unhandled rejections\n// The function is already well tested through other tests like rejected() and createPromise()\n\n\nconst neverResolvePromise = pending(new Promise<never>(() => {}));\nexport function neverResolve(): ReactPromise<never> {\n return neverResolvePromise;\n}\nimport.meta.vitest?.test(\"neverResolve\", ({ expect }) => {\n const promise = neverResolve();\n expect(promise.status).toBe(\"pending\");\n expect((promise as any).value).toBeUndefined();\n expect((promise as any).reason).toBeUndefined();\n\n // Test that multiple calls return the same promise\n const promise2 = neverResolve();\n expect(promise2).toBe(promise);\n});\n\nexport function pending<T>(promise: Promise<T>, options: { disableErrorWrapping?: boolean } = {}): ReactPromise<T> {\n const res = promise.then(\n value => {\n res.status = \"fulfilled\";\n (res as any).value = value;\n return value;\n },\n actualReason => {\n res.status = \"rejected\";\n (res as any).reason = actualReason;\n throw actualReason;\n },\n ) as ReactPromise<T>;\n res.status = \"pending\";\n return res;\n}\nimport.meta.vitest?.test(\"pending\", async ({ expect }) => {\n // Test with a promise that resolves\n const resolvePromise = Promise.resolve(42);\n const pendingPromise = pending(resolvePromise);\n\n // Initially it should be pending\n expect(pendingPromise.status).toBe(\"pending\");\n\n // After resolution, it should be fulfilled\n await resolvePromise;\n // Need to wait a tick for the then handler to execute\n await new Promise(resolve => setTimeout(resolve, 0));\n expect(pendingPromise.status).toBe(\"fulfilled\");\n expect((pendingPromise as { value: number }).value).toBe(42);\n\n // For the rejection test, we'll use a separate test to avoid unhandled rejections\n});\n\n/**\n * Should be used to wrap Promises that are not immediately awaited, so they don't throw an unhandled promise rejection\n * error.\n *\n * Vercel kills serverless functions on unhandled promise rejection errors, so this is important.\n */\nexport function ignoreUnhandledRejection<T extends Promise<any>>(promise: T): void {\n promise.catch(() => {});\n}\nimport.meta.vitest?.test(\"ignoreUnhandledRejection\", async ({ expect }) => {\n // Test with a promise that resolves\n const resolvePromise = Promise.resolve(42);\n ignoreUnhandledRejection(resolvePromise);\n expect(await resolvePromise).toBe(42); // Should still resolve to the same value\n\n // Test with a promise that rejects\n // The promise should still reject, but the rejection is caught internally\n // so it doesn't cause an unhandled rejection error\n const error = new Error(\"Test error\");\n const rejectPromise = Promise.reject(error);\n ignoreUnhandledRejection(rejectPromise);\n await expect(rejectPromise).rejects.toBe(error);\n});\n\n/**\n * See concatStacktraces for more information.\n */\nexport function concatStacktracesIfRejected<T>(promise: Promise<T>): void {\n const currentError = new Error();\n promise.catch(error => {\n if (error instanceof Error) {\n concatStacktraces(error, currentError);\n } else {\n // we can only concatenate errors, so we'll just ignore the non-error\n }\n });\n}\n\nexport async function wait(ms: number) {\n if (!Number.isFinite(ms) || ms < 0) {\n throw new HexclaveAssertionError(`wait() requires a non-negative integer number of milliseconds to wait. (found: ${ms}ms)`);\n }\n if (ms >= 2**31) {\n throw new HexclaveAssertionError(\"The maximum timeout for wait() is 2147483647ms (2**31 - 1). (found: ${ms}ms)\");\n }\n return await traceSpan({ description: 'wait(...)', attributes: { 'stack.wait.ms': ms } }, async (span) => {\n return await new Promise<void>(resolve => setTimeout(resolve, ms));\n });\n}\nimport.meta.vitest?.test(\"wait\", async ({ expect }) => {\n // Test with valid input\n const start = Date.now();\n await wait(10);\n const elapsed = Date.now() - start;\n expect(elapsed).toBeGreaterThanOrEqual(5); // Allow some flexibility in timing\n\n // Test with zero\n await expect(wait(0)).resolves.toBeUndefined();\n\n // Test with negative number\n await expect(wait(-10)).rejects.toThrow(\"wait() requires a non-negative integer\");\n\n // Test with non-finite number\n await expect(wait(NaN)).rejects.toThrow(\"wait() requires a non-negative integer\");\n await expect(wait(Infinity)).rejects.toThrow(\"wait() requires a non-negative integer\");\n\n // Test with too large number\n await expect(wait(2**31)).rejects.toThrow(\"The maximum timeout for wait()\");\n});\n\nexport async function waitUntil(date: Date) {\n return await wait(date.getTime() - Date.now());\n}\nimport.meta.vitest?.test(\"waitUntil\", async ({ expect }) => {\n // Test with future date\n const futureDate = new Date(Date.now() + 10);\n const start = Date.now();\n await waitUntil(futureDate);\n const elapsed = Date.now() - start;\n expect(elapsed).toBeGreaterThanOrEqual(5); // Allow some flexibility in timing\n\n // Test with past date - this will throw because wait() requires non-negative time\n // We need to verify it throws the correct error\n try {\n await waitUntil(new Date(Date.now() - 1000));\n expect.fail(\"Should have thrown an error\");\n } catch (error) {\n expect(error).toBeInstanceOf(HexclaveAssertionError);\n expect((error as Error).message).toContain(\"wait() requires a non-negative integer\");\n }\n});\n\nexport function runAsynchronouslyWithAlert(...args: Parameters<typeof runAsynchronously>) {\n return runAsynchronously(\n args[0],\n {\n ...args[1],\n onError: error => {\n const nodeEnv = getProcessEnv(\"NODE_ENV\");\n if (KnownError.isKnownError(error) && nodeEnv?.includes(\"production\")) {\n alert(error.message);\n } else {\n alert(`An unhandled error occurred. Please ${nodeEnv === \"development\" ? `check the browser console for the full error.` : \"report this to the developer.\"}\\n\\n${error}`);\n }\n args[1]?.onError?.(error);\n },\n },\n ...args.slice(2) as [],\n );\n}\nimport.meta.vitest?.test(\"runAsynchronouslyWithAlert\", ({ expect }) => {\n // Simple test to verify the function calls runAsynchronously\n // We can't easily test the alert functionality without mocking\n const testFn = () => Promise.resolve(\"test\");\n const testOptions = { noErrorLogging: true };\n\n // Just verify it doesn't throw\n expect(() => runAsynchronouslyWithAlert(testFn, testOptions)).not.toThrow();\n\n // We can't easily test the error handling without mocking, so we'll\n // just verify the function exists and can be called\n expect(typeof runAsynchronouslyWithAlert).toBe(\"function\");\n});\n\nexport function runAsynchronously(\n promiseOrFunc: void | Promise<unknown> | (() => void | Promise<unknown>) | undefined,\n options: {\n noErrorLogging?: boolean,\n onError?: (error: Error) => void,\n } = {},\n): void {\n if (typeof promiseOrFunc === \"function\") {\n promiseOrFunc = promiseOrFunc();\n }\n if (promiseOrFunc) {\n concatStacktracesIfRejected(promiseOrFunc);\n promiseOrFunc.catch(error => {\n options.onError?.(error);\n const newError = new HexclaveAssertionError(\n \"Uncaught error in asynchronous function: \" + errorToNiceString(error),\n { cause: error },\n );\n if (!options.noErrorLogging) {\n captureError(\"runAsynchronously\", newError);\n }\n });\n }\n}\nimport.meta.vitest?.test(\"runAsynchronously\", ({ expect }) => {\n // Simple test to verify the function exists and can be called\n const testFn = () => Promise.resolve(\"test\");\n\n // Just verify it doesn't throw\n expect(() => runAsynchronously(testFn)).not.toThrow();\n expect(() => runAsynchronously(Promise.resolve(\"test\"))).not.toThrow();\n expect(() => runAsynchronously(undefined)).not.toThrow();\n\n // We can't easily test the error handling without mocking, so we'll\n // just verify the function exists and can be called with options\n expect(() => runAsynchronously(testFn, { noErrorLogging: true })).not.toThrow();\n expect(() => runAsynchronously(testFn, { onError: () => {} })).not.toThrow();\n});\n\n\nclass TimeoutError extends Error {\n constructor(public readonly ms: number) {\n super(`Timeout after ${ms}ms`);\n this.name = \"TimeoutError\";\n }\n}\n\nexport async function timeout<T>(promiseOrFunc: Promise<T> | (() => Promise<T>), ms: number): Promise<Result<T, TimeoutError>> {\n const promise = typeof promiseOrFunc === \"function\" ? promiseOrFunc() : promiseOrFunc;\n return await Promise.race([\n promise.then(value => Result.ok(value)),\n wait(ms).then(() => Result.error(new TimeoutError(ms))),\n ]);\n}\nimport.meta.vitest?.test(\"timeout\", async ({ expect }) => {\n // Test with a promise that resolves quickly\n const fastPromise = Promise.resolve(42);\n const fastResult = await timeout(fastPromise, 100);\n expect(fastResult.status).toBe(\"ok\");\n if (fastResult.status === \"ok\") {\n expect(fastResult.data).toBe(42);\n }\n\n // Test with a promise that takes longer than the timeout\n const slowPromise = new Promise(resolve => setTimeout(() => resolve(\"too late\"), 50));\n const slowResult = await timeout(slowPromise, 10);\n expect(slowResult.status).toBe(\"error\");\n if (slowResult.status === \"error\") {\n expect(slowResult.error).toBeInstanceOf(TimeoutError);\n expect((slowResult.error as TimeoutError).ms).toBe(10);\n }\n});\n\nexport async function timeoutThrow<T>(promise: Promise<T>, ms: number): Promise<T> {\n return Result.orThrow(await timeout(promise, ms));\n}\nimport.meta.vitest?.test(\"timeoutThrow\", async ({ expect }) => {\n // Test with a promise that resolves quickly\n const fastPromise = Promise.resolve(42);\n const fastResult = await timeoutThrow(fastPromise, 100);\n expect(fastResult).toBe(42);\n\n // Test with a promise that takes longer than the timeout\n const slowPromise = new Promise(resolve => setTimeout(() => resolve(\"too late\"), 50));\n await expect(timeoutThrow(slowPromise, 10)).rejects.toThrow(\"Timeout after 10ms\");\n await expect(timeoutThrow(slowPromise, 10)).rejects.toBeInstanceOf(TimeoutError);\n});\n\n\n/**\n * Maps over `items` with `fn`, running at most `concurrency` invocations at a time.\n *\n * Unlike `Promise.all(items.map(fn))`, this bounds the number of in-flight\n * promises, which matters when `fn` hits a shared resource (e.g. a database) and\n * an unbounded fan-out could exhaust connections or overload a replica. Results\n * are returned in input order regardless of completion order, and the first\n * rejection aborts further scheduling — already in-flight workers still settle\n * but no new items are started.\n */\nexport async function mapWithConcurrency<T, R>(\n items: readonly T[],\n concurrency: number,\n fn: (item: T, index: number) => Promise<R>,\n): Promise<R[]> {\n if (!Number.isInteger(concurrency) || concurrency < 1) {\n throw new HexclaveAssertionError(`mapWithConcurrency requires a positive integer concurrency, got ${concurrency}`);\n }\n const results = new Array<R>(items.length);\n let nextIndex = 0;\n let aborted = false;\n const worker = async () => {\n while (!aborted) {\n // Claim an index synchronously before awaiting so workers never process the same item.\n const index = nextIndex++;\n if (index >= items.length) return;\n try {\n // Bounds-checked above; `?? throwErr(…)` is unsuitable because T may legitimately be null/undefined\n results[index] = await fn(items[index] as T, index);\n } catch (error) {\n aborted = true;\n throw error;\n }\n }\n };\n const workerCount = Math.min(concurrency, items.length);\n await Promise.all(Array.from({ length: workerCount }, () => worker()));\n return results;\n}\nimport.meta.vitest?.test(\"mapWithConcurrency\", async ({ expect }) => {\n // Preserves input order regardless of completion order.\n const ordered = await mapWithConcurrency([30, 10, 20], 3, async (ms, index) => {\n await wait(ms);\n return `${index}:${ms}`;\n });\n expect(ordered).toEqual([\"0:30\", \"1:10\", \"2:20\"]);\n\n // Never exceeds the configured concurrency.\n let inFlight = 0;\n let maxInFlight = 0;\n await mapWithConcurrency(Array.from({ length: 10 }, (_, i) => i), 3, async () => {\n inFlight++;\n maxInFlight = Math.max(maxInFlight, inFlight);\n await wait(5);\n inFlight--;\n });\n expect(maxInFlight).toBe(3);\n\n // Empty input spawns no workers and returns an empty array.\n expect(await mapWithConcurrency([], 4, async () => 1)).toEqual([]);\n\n // Invalid concurrency fails loudly.\n await expect(mapWithConcurrency([1], 0, async (x) => x)).rejects.toThrow(\"positive integer concurrency\");\n});\n\nexport type RateLimitOptions = {\n /**\n * The number of requests to process in parallel. Currently only 1 is supported.\n */\n concurrency: 1,\n\n /**\n * If true, multiple requests waiting at the same time will be reduced to just one. Default is false.\n */\n batchCalls?: boolean,\n\n /**\n * Waits for throttleMs since the start of last request before starting the next request. Default is 0.\n */\n throttleMs?: number,\n\n /**\n * Waits for gapMs since the end of last request before starting the next request. Default is 0.\n */\n gapMs?: number,\n\n /**\n * Waits until there have been no new requests for debounceMs before starting a new request. Default is 0.\n */\n debounceMs?: number,\n};\n\nexport function rateLimited<T>(\n func: () => Promise<T>,\n options: RateLimitOptions,\n): () => Promise<T> {\n let waitUntil = performance.now();\n let queue: [(t: T) => void, (e: unknown) => void][] = [];\n let addedToQueueCallbacks = new Map<string, () => void>;\n\n const next = async () => {\n while (true) {\n if (waitUntil > performance.now()) {\n await wait(Math.max(1, waitUntil - performance.now() + 1));\n } else if (queue.length === 0) {\n const uuid = generateUuid();\n await new Promise<void>(resolve => {\n addedToQueueCallbacks.set(uuid, resolve);\n });\n addedToQueueCallbacks.delete(uuid);\n } else {\n break;\n }\n }\n const nextFuncs = options.batchCalls ? queue.splice(0, queue.length) : [queue.shift()!];\n\n const start = performance.now();\n const value = await Result.fromPromise(func());\n const end = performance.now();\n\n waitUntil = Math.max(\n waitUntil,\n start + (options.throttleMs ?? 0),\n end + (options.gapMs ?? 0),\n );\n\n for (const nextFunc of nextFuncs) {\n if (value.status === \"ok\") {\n nextFunc[0](value.data);\n } else {\n nextFunc[1](value.error);\n }\n }\n };\n\n runAsynchronously(async () => {\n while (true) {\n await next();\n }\n });\n\n return () => {\n return new Promise<T>((resolve, reject) => {\n waitUntil = Math.max(\n waitUntil,\n performance.now() + (options.debounceMs ?? 0),\n );\n queue.push([resolve, reject]);\n addedToQueueCallbacks.forEach(cb => cb());\n });\n };\n}\n\nexport function throttled<T, A extends any[]>(func: (...args: A) => Promise<T>, delayMs: number): (...args: A) => Promise<T> {\n let timeout: ReturnType<typeof setTimeout> | null = null;\n let nextAvailable: Promise<T> | null = null;\n return async (...args) => {\n while (nextAvailable !== null) {\n await nextAvailable;\n }\n nextAvailable = new Promise<T>(resolve => {\n timeout = setTimeout(() => {\n nextAvailable = null;\n resolve(func(...args));\n }, delayMs);\n });\n return await nextAvailable;\n };\n}\n"],"mappings":"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"}
@@ -1,8 +1,8 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
2
  const require_chunk = require('../chunk-BE-pF4vm.js');
3
- let ___utils_errors_js = require("../utils/errors.js");
4
3
  let react = require("react");
5
4
  react = require_chunk.__toESM(react);
5
+ let ___utils_errors_js = require("../utils/errors.js");
6
6
 
7
7
  //#region src/hooks/use-async-callback.tsx
8
8
  function useAsyncCallback(callback, deps) {
@@ -1,7 +1,7 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
2
  const require_chunk = require('../chunk-BE-pF4vm.js');
3
- let ___utils_results_js = require("../utils/results.js");
4
3
  let react = require("react");
4
+ let ___utils_results_js = require("../utils/results.js");
5
5
 
6
6
  //#region src/hooks/use-async-external-store.tsx
7
7
  function useAsyncExternalStore(subscribe) {
@@ -1,7 +1,7 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
2
  const require_chunk = require('../chunk-BE-pF4vm.js');
3
- let ___utils_results_js = require("../utils/results.js");
4
3
  let react = require("react");
4
+ let ___utils_results_js = require("../utils/results.js");
5
5
 
6
6
  //#region src/hooks/use-strict-memo.tsx
7
7
  const cached = /* @__PURE__ */ new Map();
@@ -1,8 +1,8 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
2
  const require_chunk = require('../chunk-BE-pF4vm.js');
3
3
  let ___utils_results_js = require("../utils/results.js");
4
- let ___known_errors_js = require("../known-errors.js");
5
4
  let ___utils_urls_js = require("../utils/urls.js");
5
+ let ___known_errors_js = require("../known-errors.js");
6
6
  let __server_interface_js = require("./server-interface.js");
7
7
 
8
8
  //#region src/interface/admin-interface.ts
@@ -150,23 +150,23 @@ declare const MetricsEmailOverviewSchema: yup.ObjectSchema<{
150
150
  activity: number;
151
151
  }[];
152
152
  daily_emails_by_status: {
153
- error: number;
154
- ok: number;
155
153
  date: string;
154
+ ok: number;
155
+ error: number;
156
156
  in_progress: number;
157
157
  }[];
158
158
  emails_sent: number;
159
159
  recent_emails: {
160
160
  status: string;
161
161
  id: string;
162
- subject: string;
163
162
  created_at_millis: number;
163
+ subject: string;
164
164
  }[];
165
165
  deliverability_status: {
166
166
  error: number;
167
- bounced: number;
168
167
  in_progress: number;
169
168
  delivered: number;
169
+ bounced: number;
170
170
  };
171
171
  deliverability_rate: number;
172
172
  bounce_rate: number;
@@ -403,8 +403,8 @@ declare const AnalyticsClickmapResponseBodySchema: yup.ObjectSchema<{
403
403
  replays: number;
404
404
  }[];
405
405
  users: {
406
- primary_email: string | null;
407
406
  display_name: string | null;
407
+ primary_email: string | null;
408
408
  id: string;
409
409
  profile_image_url: string | null;
410
410
  clicks: number;
@@ -443,8 +443,8 @@ declare const AnalyticsClickmapResponseBodySchema: yup.ObjectSchema<{
443
443
  elements: never[];
444
444
  }, "">;
445
445
  declare const MetricsActiveUsersByCountrySchema: yup.MixedSchema<Record<string, {
446
- primary_email: string | null;
447
446
  display_name: string | null;
447
+ primary_email: string | null;
448
448
  id: string;
449
449
  profile_image_url: string | null;
450
450
  signed_up_at_millis: number;
@@ -471,24 +471,24 @@ declare const MetricsResponseBodySchema: yup.ObjectSchema<{
471
471
  }[];
472
472
  users_by_country: Record<string, number>;
473
473
  active_users_by_country: Record<string, {
474
- primary_email: string | null;
475
474
  display_name: string | null;
475
+ primary_email: string | null;
476
476
  id: string;
477
477
  profile_image_url: string | null;
478
478
  signed_up_at_millis: number;
479
479
  last_active_at_millis: number | null;
480
480
  }[]>;
481
481
  recently_registered: {
482
- primary_email: string | null;
483
482
  display_name: string | null;
483
+ primary_email: string | null;
484
484
  id: string;
485
485
  profile_image_url: string | null;
486
486
  signed_up_at_millis: number;
487
487
  last_active_at_millis: number | null;
488
488
  }[];
489
489
  recently_active: {
490
- primary_email: string | null;
491
490
  display_name: string | null;
491
+ primary_email: string | null;
492
492
  id: string;
493
493
  profile_image_url: string | null;
494
494
  signed_up_at_millis: number;
@@ -563,23 +563,23 @@ declare const MetricsResponseBodySchema: yup.ObjectSchema<{
563
563
  emails_by_status: Record<string, number>;
564
564
  total_emails: number;
565
565
  daily_emails_by_status: {
566
- error: number;
567
- ok: number;
568
566
  date: string;
567
+ ok: number;
568
+ error: number;
569
569
  in_progress: number;
570
570
  }[];
571
571
  emails_sent: number;
572
572
  recent_emails: {
573
573
  status: string;
574
574
  id: string;
575
- subject: string;
576
575
  created_at_millis: number;
576
+ subject: string;
577
577
  }[];
578
578
  deliverability_status: {
579
579
  error: number;
580
- bounced: number;
581
580
  in_progress: number;
582
581
  delivered: number;
582
+ bounced: number;
583
583
  };
584
584
  deliverability_rate: number;
585
585
  bounce_rate: number;
@@ -5,8 +5,8 @@ let ___utils_objects_js = require("../utils/objects.js");
5
5
  let ___utils_strings_js = require("../utils/strings.js");
6
6
  let ___utils_oauth_js = require("../utils/oauth.js");
7
7
  let ___utils_results_js = require("../utils/results.js");
8
- let ___known_errors_js = require("../known-errors.js");
9
8
  let ___utils_urls_js = require("../utils/urls.js");
9
+ let ___known_errors_js = require("../known-errors.js");
10
10
  let ___sessions_js = require("../sessions.js");
11
11
  let ___utils_crypto_js = require("../utils/crypto.js");
12
12
  let ___utils_globals_js = require("../utils/globals.js");
@@ -139,8 +139,8 @@ declare const conversationMessageSchema: yup$1.ObjectSchema<{
139
139
  createdAt: string;
140
140
  sender: {
141
141
  type: "user" | "agent" | "system";
142
- displayName: string | null;
143
142
  id: string | null;
143
+ displayName: string | null;
144
144
  primaryEmail: string | null;
145
145
  };
146
146
  }, yup$1.AnyObject, {
@@ -174,17 +174,6 @@ declare const conversationListResponseSchema: yup$1.ObjectSchema<{
174
174
  closedAt?: string | null | undefined;
175
175
  recordMetadata?: {} | null | undefined;
176
176
  status: "pending" | "open" | "closed";
177
- source: "email" | "manual" | "chat" | "api";
178
- metadata: {
179
- tags: string[];
180
- assignedToUserId: string | null;
181
- assignedToDisplayName: string | null;
182
- firstResponseDueAt: string | null;
183
- firstResponseAt: string | null;
184
- nextResponseDueAt: string | null;
185
- lastCustomerReplyAt: string | null;
186
- lastAgentReplyAt: string | null;
187
- };
188
177
  priority: "low" | "normal" | "high" | "urgent";
189
178
  subject: string;
190
179
  conversationId: string;
@@ -193,9 +182,20 @@ declare const conversationListResponseSchema: yup$1.ObjectSchema<{
193
182
  userDisplayName: string | null;
194
183
  userPrimaryEmail: string | null;
195
184
  userProfileImageUrl: string | null;
185
+ source: "email" | "manual" | "chat" | "api";
196
186
  lastMessageType: "message" | "internal-note" | "status-change";
197
187
  preview: string | null;
198
188
  lastActivityAt: string;
189
+ metadata: {
190
+ tags: string[];
191
+ assignedToUserId: string | null;
192
+ assignedToDisplayName: string | null;
193
+ firstResponseDueAt: string | null;
194
+ firstResponseAt: string | null;
195
+ nextResponseDueAt: string | null;
196
+ lastCustomerReplyAt: string | null;
197
+ lastAgentReplyAt: string | null;
198
+ };
199
199
  }[];
200
200
  hasMore: boolean;
201
201
  }, yup$1.AnyObject, {
@@ -212,17 +212,6 @@ declare const conversationDetailResponseSchema: yup$1.ObjectSchema<{
212
212
  closedAt?: string | null | undefined;
213
213
  recordMetadata?: {} | null | undefined;
214
214
  status: "pending" | "open" | "closed";
215
- source: "email" | "manual" | "chat" | "api";
216
- metadata: {
217
- tags: string[];
218
- assignedToUserId: string | null;
219
- assignedToDisplayName: string | null;
220
- firstResponseDueAt: string | null;
221
- firstResponseAt: string | null;
222
- nextResponseDueAt: string | null;
223
- lastCustomerReplyAt: string | null;
224
- lastAgentReplyAt: string | null;
225
- };
226
215
  priority: "low" | "normal" | "high" | "urgent";
227
216
  subject: string;
228
217
  conversationId: string;
@@ -231,34 +220,45 @@ declare const conversationDetailResponseSchema: yup$1.ObjectSchema<{
231
220
  userDisplayName: string | null;
232
221
  userPrimaryEmail: string | null;
233
222
  userProfileImageUrl: string | null;
223
+ source: "email" | "manual" | "chat" | "api";
234
224
  lastMessageType: "message" | "internal-note" | "status-change";
235
225
  preview: string | null;
236
226
  lastActivityAt: string;
227
+ metadata: {
228
+ tags: string[];
229
+ assignedToUserId: string | null;
230
+ assignedToDisplayName: string | null;
231
+ firstResponseDueAt: string | null;
232
+ firstResponseAt: string | null;
233
+ nextResponseDueAt: string | null;
234
+ lastCustomerReplyAt: string | null;
235
+ lastAgentReplyAt: string | null;
236
+ };
237
237
  };
238
238
  messages: {
239
239
  status: "pending" | "open" | "closed";
240
- body: string | null;
241
- source: "email" | "manual" | "chat" | "api";
242
- metadata: {} | null;
243
240
  id: string;
244
241
  priority: "low" | "normal" | "high" | "urgent";
245
242
  subject: string;
246
243
  conversationId: string;
247
244
  userId: string | null;
248
245
  teamId: string | null;
246
+ source: "email" | "manual" | "chat" | "api";
247
+ metadata: {} | null;
249
248
  createdAt: string;
250
249
  messageType: "message" | "internal-note" | "status-change";
250
+ body: string | null;
251
251
  attachments: {}[];
252
252
  sender: {
253
253
  type: "user" | "agent" | "system";
254
- displayName: string | null;
255
254
  id: string | null;
255
+ displayName: string | null;
256
256
  primaryEmail: string | null;
257
257
  };
258
258
  }[];
259
259
  entryPoints: {
260
- metadata: {} | null;
261
260
  id: string;
261
+ metadata: {} | null;
262
262
  createdAt: string;
263
263
  updatedAt: string;
264
264
  channelType: string;
@@ -4,24 +4,23 @@ import * as yup$1 from "yup";
4
4
  //#region src/interface/crud/current-user.d.ts
5
5
  declare const currentUserCrud: CrudSchemaFromOptions<{
6
6
  clientReadSchema: yup$1.ObjectSchema<{
7
+ display_name: string | null;
7
8
  restricted_reason: {
8
9
  type: "anonymous" | "email_not_verified" | "restricted_by_administrator";
9
10
  } | null;
10
11
  primary_email: string | null;
11
- display_name: string | null;
12
12
  client_metadata: {} | null;
13
13
  client_read_only_metadata: {} | null;
14
14
  id: string;
15
- selected_team_id: string | null;
16
- is_anonymous: boolean;
17
- is_restricted: boolean;
18
- requires_totp_mfa: boolean;
19
- profile_image_url: string | null;
20
15
  primary_email_verified: boolean;
16
+ profile_image_url: string | null;
17
+ selected_team_id: string | null;
21
18
  signed_up_at_millis: number;
22
19
  has_password: boolean;
23
20
  otp_auth_enabled: boolean;
24
21
  passkey_auth_enabled: boolean;
22
+ is_anonymous: boolean;
23
+ is_restricted: boolean;
25
24
  restricted_by_admin: boolean;
26
25
  restricted_by_admin_reason: string | null;
27
26
  oauth_providers: {
@@ -30,6 +29,7 @@ declare const currentUserCrud: CrudSchemaFromOptions<{
30
29
  account_id: string;
31
30
  }[];
32
31
  auth_with_email: boolean;
32
+ requires_totp_mfa: boolean;
33
33
  } & {
34
34
  selected_team: {
35
35
  client_metadata?: {} | null | undefined;
@@ -92,8 +92,8 @@ declare const currentUserCrud: CrudSchemaFromOptions<{
92
92
  server_metadata?: {} | null | undefined;
93
93
  display_name: string;
94
94
  id: string;
95
- created_at_millis: number;
96
95
  profile_image_url: string | null;
96
+ created_at_millis: number;
97
97
  } | null;
98
98
  selected_team_id: string | null;
99
99
  profile_image_url: string | null;
@@ -172,11 +172,11 @@ declare const currentUserCrud: CrudSchemaFromOptions<{
172
172
  requires_totp_mfa: undefined;
173
173
  }, "">;
174
174
  clientUpdateSchema: yup$1.ObjectSchema<{
175
- primary_email: string | null | undefined;
176
175
  display_name: string | null | undefined;
176
+ primary_email: string | null | undefined;
177
177
  client_metadata: {} | null | undefined;
178
- selected_team_id: string | null | undefined;
179
178
  profile_image_url: string | null | undefined;
179
+ selected_team_id: string | null | undefined;
180
180
  otp_auth_enabled: boolean | undefined;
181
181
  passkey_auth_enabled: boolean | undefined;
182
182
  totp_secret_base64: string | null | undefined;