@oddington/sdk 0.1.45 → 0.1.46

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/browser.js CHANGED
@@ -1338,6 +1338,7 @@ var fieldProblems = ["unknown", "missing", "invalid", "source_schema"], reasons
1338
1338
  boolean: "a boolean",
1339
1339
  date: "a date in YYYY-MM-DD format",
1340
1340
  const: "the constant declared in the schema",
1341
+ datetime: "a UTC date and time in YYYY-MM-DDTHH:mm:ss.sssZ format, for example 2026-09-15T14:30:00.000Z",
1341
1342
  enum: "one of the choices declared in the schema",
1342
1343
  link: "a link to an existing record of an allowed type",
1343
1344
  object: "an object matching the schema",
@@ -1581,14 +1582,43 @@ function captureRecordsReadRefs(value) {
1581
1582
  }
1582
1583
  function captureRecordsReadOptions(value) {
1583
1584
  if (value === void 0) return {};
1584
- let row;
1585
1585
  try {
1586
- row = Object.fromEntries(Object.entries(historyProperties(value)).map(([key, descriptor]) => [key, descriptor.value]));
1586
+ historyProperties(value);
1587
1587
  } catch {
1588
1588
  throw new DataOperationError("invalid_query");
1589
1589
  }
1590
- if (!value || typeof value != "object" || Array.isArray(value) || ![Object.prototype, null].includes(Object.getPrototypeOf(value)) || Reflect.ownKeys(value).some((key) => key !== "body" || !Object.hasOwn(Object.getOwnPropertyDescriptor(value, key), "value")) || Object.hasOwn(row, "body") && typeof row.body != "boolean") throw new DataOperationError("invalid_query");
1591
- return Object.hasOwn(row, "body") ? { body: row.body } : {};
1590
+ if (!value || typeof value != "object" || Array.isArray(value) || ![Object.prototype, null].includes(Object.getPrototypeOf(value)) || Reflect.ownKeys(value).length)
1591
+ throw new DataOperationError("invalid_query");
1592
+ return {};
1593
+ }
1594
+
1595
+ function capture3(value, ancestors = /* @__PURE__ */ new Set(), depth = 0) {
1596
+ if (value === null || typeof value == "string" || typeof value == "boolean" || typeof value == "number" && Number.isFinite(value)) return value;
1597
+ if (!value || typeof value != "object" || ancestors.has(value) || depth > 32) throw new DataOperationError("invalid_query");
1598
+ ancestors.add(value);
1599
+ try {
1600
+ return Array.isArray(value) ? historyArray(value).map((item) => capture3(item, ancestors, depth + 1)) : Object.fromEntries(Object.entries(historyProperties(value)).map(([key, descriptor]) => [key, capture3(descriptor.value, ancestors, depth + 1)]));
1601
+ } finally {
1602
+ ancestors.delete(value);
1603
+ }
1604
+ }
1605
+ function captureRecordsAll(query, options) {
1606
+ let invalid9 = () => {
1607
+ throw new DataOperationError("invalid_query");
1608
+ };
1609
+ try {
1610
+ let properties = historyProperties(options), maxRecords = properties.maxRecords?.value;
1611
+ if (Object.keys(properties).join(",") !== "maxRecords" || !Number.isSafeInteger(maxRecords) || maxRecords < 1) return invalid9();
1612
+ let detached = capture3(query), selections = historyProperties(detached);
1613
+ if (Object.keys(selections).length < 1 || Object.keys(selections).length > 16) return invalid9();
1614
+ for (let selection2 of Object.values(selections)) {
1615
+ let fields5 = historyProperties(selection2.value);
1616
+ if (fields5.$ && Object.hasOwn(historyProperties(fields5.$.value), "after")) return invalid9();
1617
+ }
1618
+ return { query: detached, maxRecords };
1619
+ } catch {
1620
+ return invalid9();
1621
+ }
1592
1622
  }
1593
1623
 
1594
1624
  function validRecordBody(value) {
@@ -1775,19 +1805,19 @@ var invalid6 = () => {
1775
1805
  }, unavailable = () => {
1776
1806
  throw new DataOperationError("unavailable");
1777
1807
  }, text2 = (value) => typeof value == "string" && value.length > 0;
1778
- function capture3(value, ancestors = /* @__PURE__ */ new Set(), depth = 0) {
1808
+ function capture4(value, ancestors = /* @__PURE__ */ new Set(), depth = 0) {
1779
1809
  if (value === null || typeof value == "string" || typeof value == "boolean" || typeof value == "number" && Number.isFinite(value)) return value;
1780
1810
  if (!value || typeof value != "object" || ancestors.has(value) || depth > 32) return invalid6();
1781
1811
  ancestors.add(value);
1782
1812
  try {
1783
- return Array.isArray(value) ? historyArray(value).map((item) => capture3(item, ancestors, depth + 1)) : Object.fromEntries(Object.entries(historyProperties(value)).map(([key, descriptor]) => [key, capture3(descriptor.value, ancestors, depth + 1)]));
1813
+ return Array.isArray(value) ? historyArray(value).map((item) => capture4(item, ancestors, depth + 1)) : Object.fromEntries(Object.entries(historyProperties(value)).map(([key, descriptor]) => [key, capture4(descriptor.value, ancestors, depth + 1)]));
1784
1814
  } finally {
1785
1815
  ancestors.delete(value);
1786
1816
  }
1787
1817
  }
1788
1818
  function recordPagination(queryRecords) {
1789
1819
  function pages(query) {
1790
- let captured = capture3(query), names = Object.keys(historyProperties(captured));
1820
+ let captured = capture4(query), names = Object.keys(historyProperties(captured));
1791
1821
  for (let name2 of names) {
1792
1822
  let selection2 = historyProperties(captured[name2]);
1793
1823
  if (Object.hasOwn(selection2, "$")) {
@@ -1799,7 +1829,6 @@ function recordPagination(queryRecords) {
1799
1829
  async function* iterate() {
1800
1830
  let state = new Map(names.map((name2) => [name2, {
1801
1831
  seen: /* @__PURE__ */ new Set(),
1802
- total: 0,
1803
1832
  count: void 0,
1804
1833
  next: void 0
1805
1834
  }])), active2 = names, version;
@@ -1809,11 +1838,11 @@ function recordPagination(queryRecords) {
1809
1838
  return [name2, next === void 0 ? selection2 : { ...selection2, $: { ...selection2.$, after: next } }];
1810
1839
  })), response2 = await queryRecords(request2), page;
1811
1840
  try {
1812
- page = capture3(response2);
1841
+ page = capture4(response2);
1813
1842
  let keys4 = Object.keys(historyProperties(page));
1814
1843
  (keys4.length !== active2.length + 1 || keys4.some((key) => key !== "$meta" && !active2.includes(key))) && unavailable();
1815
1844
  let meta = page.$meta;
1816
- (Object.keys(historyProperties(meta)).sort().join(",") !== "collections,version" || !text2(meta.version) || version !== void 0 && version !== meta.version) && unavailable(), version = meta.version, Object.keys(historyProperties(meta.collections)).some((key) => !active2.includes(key)) && unavailable();
1845
+ (Object.keys(historyProperties(meta)).sort().join(",") !== "collections,version" || !text2(meta.version)) && unavailable(), version = meta.version, Object.keys(historyProperties(meta.collections)).some((key) => !active2.includes(key)) && unavailable();
1817
1846
  for (let name2 of active2) {
1818
1847
  let records = historyArray(page[name2]), metadata = Object.hasOwn(meta.collections, name2) ? meta.collections[name2] : {};
1819
1848
  (Object.keys(historyProperties(metadata)).some((key) => key !== "count" && key !== "next") || Object.hasOwn(metadata, "next") && !text2(metadata.next)) && unavailable();
@@ -1823,7 +1852,7 @@ function recordPagination(queryRecords) {
1823
1852
  (!validRecordRef(row.$ref) || !text2(row.$version)) && unavailable();
1824
1853
  }
1825
1854
  let current2 = state.get(name2);
1826
- captured[name2].$?.count === !0 ? ((!Number.isSafeInteger(metadata.count) || metadata.count < 0 || current2.count !== void 0 && current2.count !== metadata.count) && unavailable(), current2.count = metadata.count) : Object.hasOwn(metadata, "count") && unavailable(), current2.total += records.length, (!Number.isSafeInteger(current2.total) || current2.count !== void 0 && (current2.total > current2.count || metadata.next === void 0 && current2.total !== current2.count)) && unavailable(), metadata.next !== void 0 && (current2.seen.has(metadata.next) && unavailable(), current2.seen.add(metadata.next)), current2.next = metadata.next;
1855
+ captured[name2].$?.count === !0 ? ((!Number.isSafeInteger(metadata.count) || metadata.count < 0) && unavailable(), current2.count = metadata.count) : Object.hasOwn(metadata, "count") && unavailable(), metadata.next !== void 0 && (current2.seen.has(metadata.next) && unavailable(), current2.seen.add(metadata.next)), current2.next = metadata.next;
1827
1856
  }
1828
1857
  } catch {
1829
1858
  return unavailable();
@@ -1839,32 +1868,7 @@ function recordPagination(queryRecords) {
1839
1868
  } while (active2.length);
1840
1869
  }
1841
1870
  }
1842
- async function all(query, options) {
1843
- let properties = historyProperties(options), maxRecords = properties.maxRecords?.value;
1844
- (Object.keys(properties).join(",") !== "maxRecords" || !Number.isSafeInteger(maxRecords) || maxRecords < 1) && invalid6();
1845
- let captured = capture3(query), names = Object.keys(historyProperties(captured));
1846
- if (names.length === 1) {
1847
- let name2 = names[0], selection2 = historyProperties(captured[name2]), selectionNames = Object.keys(selection2), authored = selection2.$ ? historyProperties(selection2.$.value) : {};
1848
- selectionNames.every((key) => key === "$") && !Object.hasOwn(authored, "limit") && (captured[name2] = { ...captured[name2], $: { ...captured[name2].$, limit: Math.min(500, maxRecords) } });
1849
- }
1850
- let result2, total = 0;
1851
- for await (let page of pages(captured)) {
1852
- let names2 = Object.keys(page.$meta.collections), size = names2.reduce((sum, name2) => sum + page[name2].length, 0);
1853
- if (size > maxRecords - total) throw new DataOperationError("capacity", !1, void 0, void 0, {
1854
- code: "record_limit_exceeded",
1855
- maxRecords,
1856
- collections: names2
1857
- });
1858
- total += size, result2 ??= { ...Object.fromEntries(names2.map((name2) => [name2, []])), $meta: page.$meta };
1859
- for (let name2 of names2) {
1860
- let target = result2[name2];
1861
- for (let record4 of page[name2]) target.push(record4);
1862
- }
1863
- result2.$meta = page.$meta;
1864
- }
1865
- return result2;
1866
- }
1867
- return { pages, all };
1871
+ return { pages };
1868
1872
  }
1869
1873
 
1870
1874
  var genericData = {
@@ -1901,6 +1905,7 @@ var genericData = {
1901
1905
  read: read2,
1902
1906
  query: queryRecords,
1903
1907
  ...recordPagination(queryRecords),
1908
+ all: async (query, options) => send3({ operation: "records.all", ...captureRecordsAll(query, options) }),
1904
1909
  search: async (query, options) => send3({ operation: "records.search", ...captureRecordsSearchInput(query, options) })
1905
1910
  },
1906
1911
  history: {
@@ -3381,7 +3386,7 @@ function isAppOrigin(value) {
3381
3386
  return !1;
3382
3387
  }
3383
3388
  }
3384
- function appContext(origin, active2) {
3389
+ function appContext(origin, active2, changed) {
3385
3390
  let binding, credential, pair, serialized, denied = !1, controller = new AbortController(), access = new AbortController(), expiry, startup, renewalTimer, renewal, observation, resolution2, disposed = !1, stored = () => globalThis.localStorage.getItem(sessionKey), alive = () => {
3386
3391
  try {
3387
3392
  return !denied && !disposed && active2() && globalThis.location.origin === origin;
@@ -3391,12 +3396,20 @@ function appContext(origin, active2) {
3391
3396
  }, cancel = () => {
3392
3397
  controller.abort(), access.abort(), clearTimeout(expiry), clearTimeout(startup), clearTimeout(renewalTimer), clearInterval(monitor), globalThis.removeEventListener?.("storage", storageChanged);
3393
3398
  for (let event of ["pageshow", "focus", "visibilitychange"]) globalThis.removeEventListener?.(event, wake);
3394
- }, invalidate = () => {
3395
- denied = !0, cancel();
3399
+ }, notify = (state) => {
3396
3400
  try {
3397
- !disposed && active2() && globalThis.location.origin === origin && (!serialized || globalThis.localStorage.getItem(sessionKey) === serialized) && globalThis.localStorage.removeItem(sessionKey);
3401
+ changed?.(state);
3398
3402
  } catch {
3399
3403
  }
3404
+ }, invalidate = (state = "unavailable") => {
3405
+ if (!denied) {
3406
+ denied = !0, cancel();
3407
+ try {
3408
+ !disposed && active2() && globalThis.location.origin === origin && (!serialized || globalThis.localStorage.getItem(sessionKey) === serialized) && globalThis.localStorage.removeItem(sessionKey);
3409
+ } catch {
3410
+ }
3411
+ notify(state);
3412
+ }
3400
3413
  }, current2 = () => {
3401
3414
  try {
3402
3415
  return alive() && !!binding && binding.expiresAt > Date.now() && stored() === serialized;
@@ -3408,10 +3421,10 @@ function appContext(origin, active2) {
3408
3421
  if (!validPair(value) || value.context.expiresAt > Date.now() + 6e5 || !sameSession(value.context)) throw new Error();
3409
3422
  return value;
3410
3423
  }, expireAccess = () => {
3411
- binding && binding.expiresAt <= Date.now() && access.abort();
3424
+ binding && binding.expiresAt <= Date.now() && !access.signal.aborted && (access.abort(), notify("expired"));
3412
3425
  };
3413
3426
  async function send3(path, candidate, signal, init2 = {}) {
3414
- let url = `${origin}/_os/app/${path}`, response2;
3427
+ let url = path === "auth" ? `${origin}/api/auth` : `${origin}/_os/app/${path}`, response2;
3415
3428
  try {
3416
3429
  response2 = await fetch(url, {
3417
3430
  ...init2,
@@ -3449,7 +3462,7 @@ function appContext(origin, active2) {
3449
3462
  expiry = setTimeout(expireAccess, remaining), renewalTimer = setTimeout(() => {
3450
3463
  renew().catch(() => {
3451
3464
  });
3452
- }, remaining - Math.min(6e4, remaining / 5));
3465
+ }, remaining - Math.min(6e4, remaining / 5)), notify("connected");
3453
3466
  }
3454
3467
  async function synchronize(signal = controller.signal) {
3455
3468
  if (!alive()) throw new Error();
@@ -3570,28 +3583,28 @@ function appContext(origin, active2) {
3570
3583
  for (await synchronize(); alive() && stored() !== serialized; ) await synchronize();
3571
3584
  if (signal.aborted || !current2()) throw new Error();
3572
3585
  }
3573
- async function requestData(operation2, input) {
3586
+ async function requestData(operation2, input, parent) {
3574
3587
  try {
3575
3588
  if (operation2 !== "data/query" || !current2()) throw new Error();
3576
- let admitted = credential, signal = access.signal, response2 = await send3("data", credential, signal, { method: "POST", body: JSON.stringify(input) });
3589
+ let admitted = credential, signal = parent ? AbortSignal.any([access.signal, parent]) : access.signal, response2 = await send3("data", credential, signal, { method: "POST", body: JSON.stringify(input) });
3577
3590
  if (await settledAccess(signal), response2.status === 401 || response2.status === 403)
3578
3591
  throw admitted === credential && current2() && invalidate(), new DataOperationError("access_denied");
3579
3592
  let result2 = await appResponse(response2, Number.MAX_SAFE_INTEGER, signal);
3580
3593
  if (await settledAccess(signal), !response2.ok) throw dataTransportError(response2.status, result2);
3581
3594
  return result2;
3582
3595
  } catch (error) {
3583
- throw error instanceof DataOperationError ? error : !current2() || controller.signal.aborted ? new DataOperationError("context_unavailable") : new DataOperationError("unavailable", !0);
3596
+ throw error instanceof DataOperationError ? error : !current2() || controller.signal.aborted || parent?.aborted ? new DataOperationError("context_unavailable") : new DataOperationError("unavailable", !0);
3584
3597
  }
3585
3598
  }
3586
- async function requestInbox(operation2, input) {
3599
+ async function requestInbox(operation2, input, signal) {
3587
3600
  if (!["questions.list", "questions.answer", "questions.searchRecords"].includes(operation2)) throw new Error("Inbox operation unavailable");
3588
- return requestChecked("inbox", { method: "POST", body: JSON.stringify({ operation: operation2, input }) }, !0);
3601
+ return requestChecked("inbox", { method: "POST", body: JSON.stringify({ operation: operation2, input }), signal }, !0);
3589
3602
  }
3590
3603
  async function requestRoutine(key, suffix, init2 = {}) {
3591
3604
  return requestChecked(`routines/${encodeURIComponent(key)}/${suffix}`, init2);
3592
3605
  }
3593
- async function requestRetainedRoutine(key, suffix) {
3594
- return requestChecked(`routines/${encodeURIComponent(key)}/${suffix}`, {}, !1, !0);
3606
+ async function requestRetainedRoutine(key, suffix, signal) {
3607
+ return requestChecked(`routines/${encodeURIComponent(key)}/${suffix}`, { signal }, !1, !0);
3595
3608
  }
3596
3609
  async function requestFiles(suffix, init2, parent) {
3597
3610
  let unavailable5 = () => new FileOperationError("unsupported_context", 400);
@@ -3614,7 +3627,7 @@ function appContext(origin, active2) {
3614
3627
  }
3615
3628
  async function requestChecked(path, init2, inbox2 = !1, retained2 = !1) {
3616
3629
  if (!current2()) throw new Error("Local app context unavailable.");
3617
- let admitted = credential, signal = access.signal, response2 = await send3(path, credential, signal, init2), check = async () => {
3630
+ let admitted = credential, signal = init2.signal ? AbortSignal.any([access.signal, init2.signal]) : access.signal, response2 = await send3(path, credential, signal, init2), check = async () => {
3618
3631
  if (retained2) {
3619
3632
  if (signal.aborted || !current2()) throw new Error("Local app context unavailable.");
3620
3633
  } else await settledAccess(signal);
@@ -3703,17 +3716,41 @@ function appContext(origin, active2) {
3703
3716
  }, resolve = () => resolution2 || (resolution2 = resolveOnce().finally(() => {
3704
3717
  resolution2 = void 0;
3705
3718
  }), resolution2);
3706
- return { resolve, retained: async () => {
3707
- if (!expiry && alive() && (binding ? current2() && resolution2 : !stored() || readPair(stored()).context.expiresAt > Date.now()))
3708
- return resolve();
3709
- if (!expiry || !current2()) throw new Error("Local app context unavailable.");
3710
- return context();
3711
- }, start: () => {
3712
- startup = setTimeout(() => {
3713
- alive() && !resolution2 && !binding && resolve().catch(() => {
3714
- });
3715
- }, 0);
3716
- }, invalidate, dispose };
3719
+ return {
3720
+ resolve,
3721
+ retained: async () => {
3722
+ if (!expiry && alive() && (binding ? current2() && resolution2 : !stored() || readPair(stored()).context.expiresAt > Date.now()))
3723
+ return resolve();
3724
+ if (!expiry || !current2()) throw new Error("Local app context unavailable.");
3725
+ return context();
3726
+ },
3727
+ start: () => {
3728
+ startup = setTimeout(() => {
3729
+ alive() && !resolution2 && !binding && resolve().catch(() => {
3730
+ });
3731
+ }, 0);
3732
+ },
3733
+ invalidate,
3734
+ dispose,
3735
+ account: async () => {
3736
+ await resolve();
3737
+ let signal = access.signal, response2 = await requestChecked("auth", { method: "GET" }), value = await appResponse(response2, 4096, signal);
3738
+ if (!response2.ok || !current2() || !value || Object.keys(value).join(",") !== "account" || !value.account || Object.keys(value.account).sort().join(",") !== "displayName,email" || typeof value.account.email != "string" || value.account.email.length > 320 || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value.account.email) || typeof value.account.displayName != "string" || !value.account.displayName.trim() || value.account.displayName.length > 320)
3739
+ throw new Error("Local app account unavailable.");
3740
+ return Object.freeze({ email: value.account.email, displayName: value.account.displayName });
3741
+ },
3742
+ signOut: async () => {
3743
+ if (current2() || await resolve(), !current2()) throw new Error("Local app context unavailable.");
3744
+ let signal = AbortSignal.timeout(2e4), pending = send3("sign-out", credential, signal, { method: "POST" });
3745
+ invalidate("signed_out");
3746
+ let response2 = await pending, value = await appResponse(response2, 4096, signal);
3747
+ if (!response2.ok || !value || Object.keys(value).join(",") !== "signedOut" || value.signedOut !== !0)
3748
+ throw new Error("Local app sign-out unavailable.");
3749
+ },
3750
+ isCurrent() {
3751
+ return expireAccess(), current2();
3752
+ }
3753
+ };
3717
3754
  }
3718
3755
  function validProof(value) {
3719
3756
  return typeof value == "string" && /^[A-Za-z0-9_-]{43}$/.test(value);
@@ -3921,8 +3958,37 @@ function init({ auth: input }) {
3921
3958
  url.protocol === "https:" && !url.port && !url.username && !url.password && !url.search && !url.hash && url.pathname === "/" && /^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/.test(slug) && slug !== "auth" && (endpoint = url.origin, workspace = slug);
3922
3959
  } catch {
3923
3960
  }
3924
- let active2 = !0, revision = 0, person, token, binding = {}, local2 = localOrigin ? appContext(localOrigin, () => active2) : void 0, subscription, stopDisposal, resolve = async () => {
3925
- if (local2) return local2.resolve();
3961
+ let active2 = !0, revision = 0, person, token, binding = {}, installation = new AbortController(), sharedLocal = localOrigin && registered?.localContext?.origin === localOrigin ? registered.localContext.connection : void 0, local2 = sharedLocal ?? (localOrigin ? appContext(localOrigin, () => active2) : void 0), subscription, stopDisposal, owned = (context) => {
3962
+ let signal = AbortSignal.any([context.signal, installation.signal]);
3963
+ return {
3964
+ ...context,
3965
+ get expiresAt() {
3966
+ return context.expiresAt;
3967
+ },
3968
+ signal,
3969
+ isCurrent: () => active2 && !signal.aborted && context.isCurrent(),
3970
+ requestData: (operation2, input2) => context.requestData(operation2, input2, signal),
3971
+ requestInbox: (operation2, input2) => context.requestInbox(operation2, input2, signal),
3972
+ requestFiles: (suffix, init2, parent) => context.requestFiles(
3973
+ suffix,
3974
+ init2,
3975
+ parent ? AbortSignal.any([signal, parent]) : signal
3976
+ ),
3977
+ requestRoutine: (key, suffix, init2 = {}) => context.requestRoutine(
3978
+ key,
3979
+ suffix,
3980
+ { ...init2, signal: init2.signal ? AbortSignal.any([signal, init2.signal]) : signal }
3981
+ ),
3982
+ requestRetainedRoutine: (key, suffix) => context.requestRetainedRoutine(key, suffix, signal),
3983
+ requestAvailability: (key) => context.requestRoutine(key, "availability", { method: "GET", signal })
3984
+ };
3985
+ }, resolve = async () => {
3986
+ if (local2) {
3987
+ if (!active2) throw new Error("Local app context unavailable.");
3988
+ let context = await local2.resolve();
3989
+ if (!active2) throw new Error("Local app context unavailable.");
3990
+ return owned(context);
3991
+ }
3926
3992
  if (registered && await registered.ready(), !active2 || !endpoint || !workspace || globalThis.location.origin !== endpoint) throw new Error("Hosted Data context unavailable.");
3927
3993
  let started = revision, { data: { session }, error } = await auth2.getSession();
3928
3994
  if (!active2 || globalThis.location.origin !== endpoint || started !== revision || error || !session || person !== void 0 && person !== session.user.id)
@@ -3942,13 +4008,18 @@ function init({ auth: input }) {
3942
4008
  memberId: session.user.id,
3943
4009
  binding
3944
4010
  };
3945
- }, uninstall = installMemberContext(resolve, local2 ? local2.retained : resolve), dispose = () => {
3946
- active2 && (active2 = !1, local2?.dispose(), revision++, subscription?.unsubscribe(), stopDisposal?.(), uninstall(), installedDispose === dispose && (installedDispose = void 0));
4011
+ }, uninstall = installMemberContext(resolve, local2 ? async () => {
4012
+ if (!active2 || !local2) throw new Error("Local app context unavailable.");
4013
+ let context = await local2.retained();
4014
+ if (!active2) throw new Error("Local app context unavailable.");
4015
+ return owned(context);
4016
+ } : resolve), dispose = () => {
4017
+ active2 && (active2 = !1, installation.abort(), sharedLocal || local2?.dispose(), revision++, subscription?.unsubscribe(), stopDisposal?.(), uninstall(), installedDispose === dispose && (installedDispose = void 0));
3947
4018
  };
3948
- installedDispose = dispose, stopDisposal = registered?.onDispose(dispose), active2 && (subscription = auth2.onAuthStateChange((event, session) => {
4019
+ installedDispose = dispose, stopDisposal = registered?.onDispose(dispose), active2 && (sharedLocal || (subscription = auth2.onAuthStateChange((event, session) => {
3949
4020
  let next = session?.user.id ?? null;
3950
4021
  (event === "SIGNED_OUT" || person !== void 0 && next !== person || person !== void 0 && event === "SIGNED_IN" && token !== session?.access_token) && (revision++, local2?.invalidate()), person = next, token = session?.access_token;
3951
- }).data.subscription, local2?.start());
4022
+ }).data.subscription), sharedLocal || local2?.start());
3952
4023
  }
3953
4024
  var os = { init };
3954
4025
 
@@ -3988,9 +4059,127 @@ function authorizationFailure(error) {
3988
4059
  return Object.freeze({ status: status === 404 || status === 410 || status === 400 ? "expired" : status === 401 ? "signed_out" : status === 403 || status === 422 ? "invalid" : "unavailable" });
3989
4060
  }
3990
4061
 
4062
+ var coordinators = /* @__PURE__ */ new Map(), publish = (c, state) => {
4063
+ c.state = Object.freeze(state);
4064
+ for (let listener of c.listeners)
4065
+ try {
4066
+ listener(c.state);
4067
+ } catch {
4068
+ }
4069
+ };
4070
+ function refresh(c) {
4071
+ let revision = c.revision;
4072
+ if (c.loading?.revision === revision) return c.loading.promise;
4073
+ let promise = (async () => {
4074
+ try {
4075
+ let account = await c.context.account();
4076
+ c.active && !c.closed && c.revision === revision && publish(c, { status: "signed_in", account });
4077
+ } catch {
4078
+ c.active && !c.closed && c.revision === revision && publish(c, { status: "unavailable", error: "unavailable" });
4079
+ }
4080
+ })().finally(() => {
4081
+ c.loading?.promise === promise && (c.loading = void 0);
4082
+ });
4083
+ return c.loading = { revision, promise }, promise;
4084
+ }
4085
+ function createLocalBrowserAuth(origin, failure) {
4086
+ let c = coordinators.get(origin);
4087
+ if (!c) {
4088
+ let coordinator2 = {
4089
+ context: void 0,
4090
+ state: Object.freeze({ status: "initializing" }),
4091
+ active: !0,
4092
+ closed: !1,
4093
+ refs: 0,
4094
+ revision: 0,
4095
+ listeners: /* @__PURE__ */ new Set(),
4096
+ ready: Promise.resolve()
4097
+ };
4098
+ coordinator2.context = appContext(origin, () => coordinator2.active, (state) => {
4099
+ !coordinator2.active || coordinator2.closed || (state === "connected" ? coordinator2.state.status !== "initializing" && (coordinator2.revision++, refresh(coordinator2)) : (coordinator2.revision++, publish(coordinator2, { status: state === "expired" ? "expired" : state === "signed_out" ? "signed_out" : "unavailable" })));
4100
+ }), c = coordinator2, coordinators.set(origin, c), c.ready = Promise.resolve().then(() => refresh(coordinator2));
4101
+ }
4102
+ let coordinator = c;
4103
+ coordinator.refs++;
4104
+ let active2 = !0, lastState = coordinator.state, listeners = /* @__PURE__ */ new Set(), disposals = /* @__PURE__ */ new Set(), observe = (state) => {
4105
+ lastState = state;
4106
+ for (let listener of listeners)
4107
+ try {
4108
+ listener(state);
4109
+ } catch {
4110
+ }
4111
+ };
4112
+ coordinator.listeners.add(observe);
4113
+ let assertActive = () => {
4114
+ if (!active2) throw failure("disposed");
4115
+ }, unavailable5 = async () => Object.freeze({
4116
+ status: active2 ? coordinator.state.status === "signed_out" ? "signed_out" : "unavailable" : "disposed"
4117
+ }), handle2 = Object.freeze({
4118
+ authorization: Object.freeze({ get: unavailable5, approve: unavailable5, deny: unavailable5 }),
4119
+ getState() {
4120
+ return active2 && !coordinator.state.pending && coordinator.state.status === "signed_in" && !coordinator.context.isCurrent() && coordinator.state.status === "signed_in" && publish(coordinator, { status: "unavailable", error: "unavailable" }), lastState;
4121
+ },
4122
+ subscribe(listener) {
4123
+ return assertActive(), listeners.add(listener), () => {
4124
+ listeners.delete(listener);
4125
+ };
4126
+ },
4127
+ async sendCode() {
4128
+ throw assertActive(), failure("unavailable");
4129
+ },
4130
+ async verifyCode() {
4131
+ throw assertActive(), failure("unavailable");
4132
+ },
4133
+ async signOut() {
4134
+ if (assertActive(), coordinator.state.pending === "sign_out") throw failure("busy");
4135
+ if (coordinator.closed) throw failure("unavailable");
4136
+ coordinator.closed = !0, coordinator.revision++, publish(coordinator, { status: coordinator.state.status, pending: "sign_out" });
4137
+ try {
4138
+ await coordinator.context.signOut();
4139
+ } catch {
4140
+ throw coordinator.context.invalidate(), coordinator.active && publish(coordinator, { status: "unavailable", error: "unavailable" }), failure(active2 ? "unavailable" : "disposed");
4141
+ }
4142
+ coordinator.active && publish(coordinator, { status: "signed_out" }), assertActive();
4143
+ },
4144
+ dispose() {
4145
+ if (active2) {
4146
+ active2 = !1, coordinator.listeners.delete(observe), listeners.clear();
4147
+ for (let callback of disposals)
4148
+ try {
4149
+ callback();
4150
+ } catch {
4151
+ }
4152
+ disposals.clear(), --coordinator.refs === 0 && (coordinator.active = !1, coordinator.revision++, coordinator.context.dispose(), coordinator.listeners.clear(), coordinators.delete(origin));
4153
+ }
4154
+ }
4155
+ });
4156
+ return registerBrowserAuth(handle2, {
4157
+ localContext: { origin, connection: coordinator.context },
4158
+ async ready() {
4159
+ assertActive(), await coordinator.ready, assertActive();
4160
+ },
4161
+ async checkWorkspaceAccess() {
4162
+ assertActive(), await coordinator.context.resolve(), assertActive();
4163
+ },
4164
+ onDispose(callback) {
4165
+ return active2 ? (disposals.add(callback), () => {
4166
+ disposals.delete(callback);
4167
+ }) : (callback(), () => {
4168
+ });
4169
+ },
4170
+ async getSession() {
4171
+ return assertActive(), { data: { session: null }, error: null };
4172
+ },
4173
+ onAuthStateChange(callback) {
4174
+ return callback("INITIAL_SESSION", null), { data: { subscription: { unsubscribe() {
4175
+ } } } };
4176
+ }
4177
+ }), handle2;
4178
+ }
4179
+
3991
4180
  function createBrowserAuth(runtime) {
3992
- let coordinators = /* @__PURE__ */ new Map();
3993
- function publish(c, state) {
4181
+ let coordinators2 = /* @__PURE__ */ new Map();
4182
+ function publish2(c, state) {
3994
4183
  c.state = Object.freeze(state);
3995
4184
  for (let listener of c.listeners)
3996
4185
  try {
@@ -4006,7 +4195,7 @@ function createBrowserAuth(runtime) {
4006
4195
  }
4007
4196
  }
4008
4197
  function expire(c) {
4009
- !c.active || !c.session && c.state.status === "expired" || (c.revision++, c.timer && clearTimeout(c.timer), c.session = null, publish(c, { status: "expired" }), notify(c, "SIGNED_OUT"));
4198
+ !c.active || !c.session && c.state.status === "expired" || (c.revision++, c.timer && clearTimeout(c.timer), c.session = null, publish2(c, { status: "expired" }), notify(c, "SIGNED_OUT"));
4010
4199
  }
4011
4200
  function accept(c, event, session) {
4012
4201
  if (!c.active || event === "INITIAL_SESSION" && c.state.status !== "initializing" || event === "TOKEN_REFRESHED" && !c.session && c.state.status !== "initializing") return;
@@ -4014,7 +4203,7 @@ function createBrowserAuth(runtime) {
4014
4203
  replaced && c.revision++, c.timer && clearTimeout(c.timer);
4015
4204
  let pending = c.state.pending;
4016
4205
  if (!session) {
4017
- c.session = null, publish(c, { status: c.state.status === "expired" ? "expired" : "signed_out", ...pending ? { pending } : {} }), notify(c, "SIGNED_OUT");
4206
+ c.session = null, publish2(c, { status: c.state.status === "expired" ? "expired" : "signed_out", ...pending ? { pending } : {} }), notify(c, "SIGNED_OUT");
4018
4207
  return;
4019
4208
  }
4020
4209
  if (!validSession(session)) {
@@ -4023,7 +4212,7 @@ function createBrowserAuth(runtime) {
4023
4212
  }
4024
4213
  c.session = session;
4025
4214
  let email = typeof session.user.email == "string" ? session.user.email.trim() : "", metadata = session.user.user_metadata, name2 = ["name", "full_name", "first_name"].map((key) => metadata?.[key]).find((value) => typeof value == "string" && value.trim())?.trim() || email, account = !replaced && c.state.account?.email === email && c.state.account.displayName === name2 ? c.state.account : Object.freeze({ email, displayName: name2 });
4026
- notify(c, event), publish(c, { status: "signed_in", account, ...pending ? { pending } : {} });
4215
+ notify(c, event), publish2(c, { status: "signed_in", account, ...pending ? { pending } : {} });
4027
4216
  let checkExpiry = () => {
4028
4217
  if (!c.active || !c.session) return;
4029
4218
  let remaining = c.session.expires_at * 1e3 - Date.now();
@@ -4070,9 +4259,9 @@ function createBrowserAuth(runtime) {
4070
4259
  c.unsubscribe = () => subscription.unsubscribe();
4071
4260
  let started = c.revision, { data: data3, error } = await c.provider.getSession();
4072
4261
  if (!current2(c, origin, started)) return;
4073
- error ? terminalSessionFailure(error) ? expire(c) : (!c.session || !validSession(c.session)) && publish(c, { status: "unavailable", error: "unavailable" }) : c.state.pending !== "sign_out" && accept(c, "INITIAL_SESSION", data3.session);
4262
+ error ? terminalSessionFailure(error) ? expire(c) : (!c.session || !validSession(c.session)) && publish2(c, { status: "unavailable", error: "unavailable" }) : c.state.pending !== "sign_out" && accept(c, "INITIAL_SESSION", data3.session);
4074
4263
  } catch {
4075
- current2(c, origin, revision) && publish(c, { status: "unavailable", error: "unavailable" });
4264
+ current2(c, origin, revision) && publish2(c, { status: "unavailable", error: "unavailable" });
4076
4265
  }
4077
4266
  })(), c;
4078
4267
  }
@@ -4110,8 +4299,10 @@ function createBrowserAuth(runtime) {
4110
4299
  if (await c.workspaceAccess.result, !current2(c, origin, revision)) throw runtime.failure("stale");
4111
4300
  }
4112
4301
  return { create() {
4113
- let origin = globalThis.location?.origin ?? "", c = coordinators.get(origin);
4114
- c || (c = createCoordinator(origin), coordinators.set(origin, c));
4302
+ let origin = globalThis.location?.origin ?? "";
4303
+ if (isAppOrigin(origin) && origin !== "http://127.0.0.1:5176") return createLocalBrowserAuth(origin, runtime.failure);
4304
+ let c = coordinators2.get(origin);
4305
+ c || (c = createCoordinator(origin), coordinators2.set(origin, c));
4115
4306
  let coordinator = c;
4116
4307
  coordinator.refs++;
4117
4308
  let active2 = !0, ownedAction, authorizationId, authorizationGeneration = 0, inspected, observers = /* @__PURE__ */ new Set(), sessionObservers = /* @__PURE__ */ new Set(), disposalObservers = /* @__PURE__ */ new Set(), lastState = coordinator.state, observation = (state) => {
@@ -4132,15 +4323,15 @@ function createBrowserAuth(runtime) {
4132
4323
  let marker = {};
4133
4324
  coordinator.action = marker, ownedAction = marker;
4134
4325
  let revision = coordinator.revision;
4135
- publish(coordinator, { ...coordinator.state, error: void 0, pending: kind });
4326
+ publish2(coordinator, { ...coordinator.state, error: void 0, pending: kind });
4136
4327
  try {
4137
4328
  if (await coordinator.ready, assertActive(), !coordinator.provider || !coordinator.active || globalThis.location?.origin !== origin) throw runtime.failure("unavailable");
4138
4329
  if (!current2(coordinator, origin, revision) || coordinator.action !== marker || (await work(coordinator.provider), assertActive(), coordinator.action !== marker) || !current2(coordinator, origin, revision) && kind !== "verify_code" && kind !== "sign_out") throw runtime.failure("stale");
4139
4330
  } catch (error) {
4140
4331
  let reason = active2 ? current2(coordinator, origin, revision) ? safeReason(error) ?? "unavailable" : "stale" : "disposed";
4141
- throw active2 && current2(coordinator, origin, revision) && publish(coordinator, { ...coordinator.state, error: reason }), runtime.failure(reason);
4332
+ throw active2 && current2(coordinator, origin, revision) && publish2(coordinator, { ...coordinator.state, error: reason }), runtime.failure(reason);
4142
4333
  } finally {
4143
- coordinator.action === marker && (coordinator.action = void 0, coordinator.active && (publish(coordinator, { ...coordinator.state, pending: void 0 }), kind === "sign_out" && coordinator.session && notify(coordinator, "TOKEN_REFRESHED"))), ownedAction === marker && (ownedAction = void 0);
4334
+ coordinator.action === marker && (coordinator.action = void 0, coordinator.active && (publish2(coordinator, { ...coordinator.state, pending: void 0 }), kind === "sign_out" && coordinator.session && notify(coordinator, "TOKEN_REFRESHED"))), ownedAction === marker && (ownedAction = void 0);
4144
4335
  }
4145
4336
  }
4146
4337
  async function authorize(kind, id3) {
@@ -4237,7 +4428,7 @@ function createBrowserAuth(runtime) {
4237
4428
  }
4238
4429
  disposalObservers.clear();
4239
4430
  for (let listener of sessionObservers) coordinator.sessions.delete(listener);
4240
- sessionObservers.clear(), --coordinator.refs === 0 && (coordinator.active = !1, coordinator.revision++, coordinator.timer && clearTimeout(coordinator.timer), coordinator.unsubscribe?.(), coordinator.provider?.dispose(), coordinator.provider = void 0, coordinator.session = null, coordinator.listeners.clear(), coordinator.sessions.clear(), coordinators.delete(origin));
4431
+ sessionObservers.clear(), --coordinator.refs === 0 && (coordinator.active = !1, coordinator.revision++, coordinator.timer && clearTimeout(coordinator.timer), coordinator.unsubscribe?.(), coordinator.provider?.dispose(), coordinator.provider = void 0, coordinator.session = null, coordinator.listeners.clear(), coordinator.sessions.clear(), coordinators2.delete(origin));
4241
4432
  }
4242
4433
  }
4243
4434
  });