@entropy-softworks/ui 2026.8.18 → 2026.8.19

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.
@@ -1 +1 @@
1
- {"version":3,"file":"fetch.d.ts","sourceRoot":"","sources":["../../src/utils/fetch.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,WAAgB,EACzB,SAAS,SAAQ,GAChB,OAAO,CAAC,QAAQ,CAAC,CAanB"}
1
+ {"version":3,"file":"fetch.d.ts","sourceRoot":"","sources":["../../src/utils/fetch.ts"],"names":[],"mappings":"AAqCA;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,WAAgB,EACzB,SAAS,SAAQ,GAChB,OAAO,CAAC,QAAQ,CAAC,CAanB"}
@@ -1,3 +1,39 @@
1
+ /**
2
+ * Combines multiple AbortSignals into one that aborts when any input does.
3
+ * Prefers the native `AbortSignal.any` where present (modern browsers);
4
+ * falls back to manual event-listener wiring where it isn't.
5
+ *
6
+ * That fallback is load-bearing, not defensive padding: React Native
7
+ * doesn't provide a native AbortController at all — `setUpXHR.js` installs
8
+ * one from the third-party `abort-controller` npm package (pinned at
9
+ * v3.0.0 in this tree), which predates `AbortSignal.any` entering the
10
+ * WHATWG spec. Calling it unconditionally on native evaluates to invoking
11
+ * `undefined` as a function, which Hermes reports as the unhelpfully
12
+ * generic "undefined is not a function" — confirmed for real on
13
+ * 2026-08-17, the first time a native call site (a vault item detail
14
+ * screen, via its own cancellation AbortSignal) exercised the
15
+ * `signals.length > 1` branch this function has always had; every
16
+ * previous native caller only ever supplied the internal timeout signal,
17
+ * so `AbortSignal.any` had simply never been reached before.
18
+ */
19
+ function combineSignals(signals) {
20
+ if (signals.length === 1) {
21
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- length checked
22
+ return signals[0];
23
+ }
24
+ if (typeof AbortSignal.any === "function") {
25
+ return AbortSignal.any([...signals]);
26
+ }
27
+ const combined = new AbortController();
28
+ for (const s of signals) {
29
+ if (s.aborted) {
30
+ combined.abort();
31
+ break;
32
+ }
33
+ s.addEventListener("abort", () => combined.abort(), { once: true });
34
+ }
35
+ return combined.signal;
36
+ }
1
37
  /**
2
38
  * `fetch` with a timeout abort signal merged onto the caller's own signal.
3
39
  * The default timeout is 15s. Pass `Infinity` to disable the timeout
@@ -19,7 +55,7 @@ export function fetchWithTimeout(url, options = {}, timeoutMs = 15000) {
19
55
  ? setTimeout(() => controller.abort(), timeoutMs)
20
56
  : null;
21
57
  const signals = [controller.signal, options.signal].filter((s) => s != null);
22
- const combinedSignal = signals.length > 1 ? AbortSignal.any(signals) : controller.signal;
58
+ const combinedSignal = combineSignals(signals);
23
59
  return fetch(url, { ...options, signal: combinedSignal }).finally(() => {
24
60
  if (id !== null) {
25
61
  clearTimeout(id);
@@ -1 +1 @@
1
- {"version":3,"file":"fetch.js","sourceRoot":"","sources":["../../src/utils/fetch.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,gBAAgB,CAC9B,GAAW,EACX,UAAuB,EAAE,EACzB,SAAS,GAAG,KAAK;IAEjB,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;IACzC,MAAM,EAAE,GACN,SAAS,GAAG,CAAC,IAAI,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC;QACzC,CAAC,CAAC,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,SAAS,CAAC;QACjD,CAAC,CAAC,IAAI,CAAC;IACX,MAAM,OAAO,GAAG,CAAC,UAAU,CAAC,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAoB,EAAE,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC;IAC/F,MAAM,cAAc,GAAG,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC;IACzF,OAAO,KAAK,CAAC,GAAG,EAAE,EAAE,GAAG,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE;QACrE,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC;YAChB,YAAY,CAAC,EAAE,CAAC,CAAC;QACnB,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC"}
1
+ {"version":3,"file":"fetch.js","sourceRoot":"","sources":["../../src/utils/fetch.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,SAAS,cAAc,CAAC,OAA+B;IACrD,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,sFAAsF;QACtF,OAAO,OAAO,CAAC,CAAC,CAAE,CAAC;IACrB,CAAC;IACD,IAAI,OAAO,WAAW,CAAC,GAAG,KAAK,UAAU,EAAE,CAAC;QAC1C,OAAO,WAAW,CAAC,GAAG,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IACvC,CAAC;IACD,MAAM,QAAQ,GAAG,IAAI,eAAe,EAAE,CAAC;IACvC,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACxB,IAAI,CAAC,CAAC,OAAO,EAAE,CAAC;YACd,QAAQ,CAAC,KAAK,EAAE,CAAC;YACjB,MAAM;QACR,CAAC;QACD,CAAC,CAAC,gBAAgB,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,KAAK,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;IACtE,CAAC;IACD,OAAO,QAAQ,CAAC,MAAM,CAAC;AACzB,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,gBAAgB,CAC9B,GAAW,EACX,UAAuB,EAAE,EACzB,SAAS,GAAG,KAAK;IAEjB,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;IACzC,MAAM,EAAE,GACN,SAAS,GAAG,CAAC,IAAI,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC;QACzC,CAAC,CAAC,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,SAAS,CAAC;QACjD,CAAC,CAAC,IAAI,CAAC;IACX,MAAM,OAAO,GAAG,CAAC,UAAU,CAAC,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAoB,EAAE,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC;IAC/F,MAAM,cAAc,GAAG,cAAc,CAAC,OAAO,CAAC,CAAC;IAC/C,OAAO,KAAK,CAAC,GAAG,EAAE,EAAE,GAAG,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE;QACrE,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC;YAChB,YAAY,CAAC,EAAE,CAAC,CAAC;QACnB,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@entropy-softworks/ui",
3
- "version": "2026.8.18",
3
+ "version": "2026.8.19",
4
4
  "private": false,
5
5
  "description": "Shared React Native UI primitives, auth screens, hooks, and services for Entropy Softworks Expo apps",
6
6
  "license": "MIT",
@@ -1,3 +1,40 @@
1
+ /**
2
+ * Combines multiple AbortSignals into one that aborts when any input does.
3
+ * Prefers the native `AbortSignal.any` where present (modern browsers);
4
+ * falls back to manual event-listener wiring where it isn't.
5
+ *
6
+ * That fallback is load-bearing, not defensive padding: React Native
7
+ * doesn't provide a native AbortController at all — `setUpXHR.js` installs
8
+ * one from the third-party `abort-controller` npm package (pinned at
9
+ * v3.0.0 in this tree), which predates `AbortSignal.any` entering the
10
+ * WHATWG spec. Calling it unconditionally on native evaluates to invoking
11
+ * `undefined` as a function, which Hermes reports as the unhelpfully
12
+ * generic "undefined is not a function" — confirmed for real on
13
+ * 2026-08-17, the first time a native call site (a vault item detail
14
+ * screen, via its own cancellation AbortSignal) exercised the
15
+ * `signals.length > 1` branch this function has always had; every
16
+ * previous native caller only ever supplied the internal timeout signal,
17
+ * so `AbortSignal.any` had simply never been reached before.
18
+ */
19
+ function combineSignals(signals: readonly AbortSignal[]): AbortSignal {
20
+ if (signals.length === 1) {
21
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- length checked
22
+ return signals[0]!;
23
+ }
24
+ if (typeof AbortSignal.any === "function") {
25
+ return AbortSignal.any([...signals]);
26
+ }
27
+ const combined = new AbortController();
28
+ for (const s of signals) {
29
+ if (s.aborted) {
30
+ combined.abort();
31
+ break;
32
+ }
33
+ s.addEventListener("abort", () => combined.abort(), { once: true });
34
+ }
35
+ return combined.signal;
36
+ }
37
+
1
38
  /**
2
39
  * `fetch` with a timeout abort signal merged onto the caller's own signal.
3
40
  * The default timeout is 15s. Pass `Infinity` to disable the timeout
@@ -24,7 +61,7 @@ export function fetchWithTimeout(
24
61
  ? setTimeout(() => controller.abort(), timeoutMs)
25
62
  : null;
26
63
  const signals = [controller.signal, options.signal].filter((s): s is AbortSignal => s != null);
27
- const combinedSignal = signals.length > 1 ? AbortSignal.any(signals) : controller.signal;
64
+ const combinedSignal = combineSignals(signals);
28
65
  return fetch(url, { ...options, signal: combinedSignal }).finally(() => {
29
66
  if (id !== null) {
30
67
  clearTimeout(id);