@w6w/react 0.6.0 → 0.9.12

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.
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Single-flight store behind the read hooks: identical in-flight reads (same
3
+ * client, same key) share ONE request, and nothing outlives it.
4
+ *
5
+ * Scoping: one `Map` per `W6WClient` object, held in a `WeakMap` — never a
6
+ * bare module-level map and never keyed by `baseUrl`/token, so two providers
7
+ * with identical props (different tenants) cannot see each other's data.
8
+ *
9
+ * Lifetime: an entry exists only while its request is pending. It is deleted
10
+ * on resolve OR reject (only if it is still the mapped entry), so a consumer
11
+ * that mounts after the flight settled sends a fresh request — no staleness.
12
+ *
13
+ * Abort: refcounted. The shared `AbortController` aborts only when the last
14
+ * subscriber has detached AND stayed detached past a microtask grace. React
15
+ * StrictMode's synchronous cleanup -> remount re-attaches inside that grace,
16
+ * so it re-joins the flight instead of abort + refire.
17
+ *
18
+ * @module
19
+ */
20
+ /** One subscriber's hold on a shared flight. */
21
+ export interface Subscription<T> {
22
+ /** The shared request's result — the same promise for every subscriber. */
23
+ readonly promise: Promise<T>;
24
+ /** Release this subscriber's hold. Idempotent. */
25
+ detach(): void;
26
+ }
27
+ /**
28
+ * Join the pending flight for `(client, key)`, or start one with `start`.
29
+ * `fresh` always starts a new flight and takes over the key's slot; the entry
30
+ * it replaces keeps running for whoever still holds it.
31
+ */
32
+ export declare function subscribe<T>(client: object, key: string, start: (signal: AbortSignal) => Promise<T>, fresh?: boolean): Subscription<T>;
33
+ //# sourceMappingURL=single-flight.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"single-flight.d.ts","sourceRoot":"","sources":["../../src/single-flight.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAQH,gDAAgD;AAChD,MAAM,WAAW,YAAY,CAAC,CAAC;IAC7B,2EAA2E;IAC3E,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;IAC7B,kDAAkD;IAClD,MAAM,IAAI,IAAI,CAAC;CAChB;AAID;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,CAAC,EACzB,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,CAAC,MAAM,EAAE,WAAW,KAAK,OAAO,CAAC,CAAC,CAAC,EAC1C,KAAK,UAAQ,GACZ,YAAY,CAAC,CAAC,CAAC,CAyCjB"}
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Single-flight store behind the read hooks: identical in-flight reads (same
3
+ * client, same key) share ONE request, and nothing outlives it.
4
+ *
5
+ * Scoping: one `Map` per `W6WClient` object, held in a `WeakMap` — never a
6
+ * bare module-level map and never keyed by `baseUrl`/token, so two providers
7
+ * with identical props (different tenants) cannot see each other's data.
8
+ *
9
+ * Lifetime: an entry exists only while its request is pending. It is deleted
10
+ * on resolve OR reject (only if it is still the mapped entry), so a consumer
11
+ * that mounts after the flight settled sends a fresh request — no staleness.
12
+ *
13
+ * Abort: refcounted. The shared `AbortController` aborts only when the last
14
+ * subscriber has detached AND stayed detached past a microtask grace. React
15
+ * StrictMode's synchronous cleanup -> remount re-attaches inside that grace,
16
+ * so it re-joins the flight instead of abort + refire.
17
+ *
18
+ * @module
19
+ */
20
+ const stores = new WeakMap();
21
+ /**
22
+ * Join the pending flight for `(client, key)`, or start one with `start`.
23
+ * `fresh` always starts a new flight and takes over the key's slot; the entry
24
+ * it replaces keeps running for whoever still holds it.
25
+ */
26
+ export function subscribe(client, key, start, fresh = false) {
27
+ let map = stores.get(client);
28
+ if (!map) {
29
+ map = new Map();
30
+ stores.set(client, map);
31
+ }
32
+ const slots = map;
33
+ let entry = fresh ? undefined : slots.get(key);
34
+ if (!entry) {
35
+ const controller = new AbortController();
36
+ const created = {
37
+ promise: start(controller.signal),
38
+ controller,
39
+ refs: 0,
40
+ };
41
+ const settle = () => {
42
+ if (slots.get(key) === created)
43
+ slots.delete(key);
44
+ };
45
+ created.promise.then(settle, settle);
46
+ slots.set(key, created);
47
+ entry = created;
48
+ }
49
+ const held = entry;
50
+ held.refs++;
51
+ let detached = false;
52
+ return {
53
+ promise: held.promise,
54
+ detach() {
55
+ if (detached)
56
+ return;
57
+ detached = true;
58
+ held.refs--;
59
+ if (held.refs > 0)
60
+ return;
61
+ queueMicrotask(() => {
62
+ if (held.refs > 0)
63
+ return;
64
+ if (slots.get(key) === held)
65
+ slots.delete(key);
66
+ held.controller.abort();
67
+ });
68
+ },
69
+ };
70
+ }
71
+ //# sourceMappingURL=single-flight.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"single-flight.js","sourceRoot":"","sources":["../../src/single-flight.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAgBH,MAAM,MAAM,GAAG,IAAI,OAAO,EAAuC,CAAC;AAElE;;;;GAIG;AACH,MAAM,UAAU,SAAS,CACvB,MAAc,EACd,GAAW,EACX,KAA0C,EAC1C,KAAK,GAAG,KAAK;IAEb,IAAI,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAC7B,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,GAAG,GAAG,IAAI,GAAG,EAAE,CAAC;QAChB,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC1B,CAAC;IACD,MAAM,KAAK,GAAG,GAAG,CAAC;IAElB,IAAI,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAE,KAAK,CAAC,GAAG,CAAC,GAAG,CAA0B,CAAC;IACzE,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;QACzC,MAAM,OAAO,GAAa;YACxB,OAAO,EAAE,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC;YACjC,UAAU;YACV,IAAI,EAAE,CAAC;SACR,CAAC;QACF,MAAM,MAAM,GAAG,GAAG,EAAE;YAClB,IAAI,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,OAAO;gBAAE,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACpD,CAAC,CAAC;QACF,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACrC,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,OAAyB,CAAC,CAAC;QAC1C,KAAK,GAAG,OAAO,CAAC;IAClB,CAAC;IACD,MAAM,IAAI,GAAG,KAAK,CAAC;IACnB,IAAI,CAAC,IAAI,EAAE,CAAC;IAEZ,IAAI,QAAQ,GAAG,KAAK,CAAC;IACrB,OAAO;QACL,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,MAAM;YACJ,IAAI,QAAQ;gBAAE,OAAO;YACrB,QAAQ,GAAG,IAAI,CAAC;YAChB,IAAI,CAAC,IAAI,EAAE,CAAC;YACZ,IAAI,IAAI,CAAC,IAAI,GAAG,CAAC;gBAAE,OAAO;YAC1B,cAAc,CAAC,GAAG,EAAE;gBAClB,IAAI,IAAI,CAAC,IAAI,GAAG,CAAC;oBAAE,OAAO;gBAC1B,IAAI,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,IAAI;oBAAE,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;gBAC/C,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC;YAC1B,CAAC,CAAC,CAAC;QACL,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../../src/version.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,OAAO,EAAE,MAAgB,CAAC"}
1
+ {"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../../src/version.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,OAAO,EAAE,MAAiB,CAAC"}
@@ -15,5 +15,5 @@
15
15
  * every wrapper's version in lockstep, and that pattern depends on the literal
16
16
  * `: string` shape being present.
17
17
  */
18
- export const VERSION = "0.6.0";
18
+ export const VERSION = "0.9.12";
19
19
  //# sourceMappingURL=version.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"version.js","sourceRoot":"","sources":["../../src/version.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,MAAM,OAAO,GAAW,OAAO,CAAC"}
1
+ {"version":3,"file":"version.js","sourceRoot":"","sources":["../../src/version.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,MAAM,OAAO,GAAW,QAAQ,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@w6w/react",
3
- "version": "0.6.0",
3
+ "version": "0.9.12",
4
4
  "description": "React bindings for @w6w/sdk — a <W6WProvider>, a small hook set, and a structural adapter for @w6w/ui's W6WApi contract.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -10,7 +10,13 @@
10
10
  },
11
11
  "homepage": "https://github.com/w6w-io/w6w-wrappers/tree/main/react#readme",
12
12
  "bugs": "https://github.com/w6w-io/w6w-wrappers/issues",
13
- "keywords": ["w6w", "workflow", "react", "sdk", "hooks"],
13
+ "keywords": [
14
+ "w6w",
15
+ "workflow",
16
+ "react",
17
+ "sdk",
18
+ "hooks"
19
+ ],
14
20
  "type": "module",
15
21
  "types": "./dist/mod.d.ts",
16
22
  "main": "./dist/mod.js",
@@ -20,7 +26,9 @@
20
26
  "import": "./dist/mod.js"
21
27
  }
22
28
  },
23
- "files": ["dist"],
29
+ "files": [
30
+ "dist"
31
+ ],
24
32
  "sideEffects": false,
25
33
  "engines": {
26
34
  "node": ">=18"
@@ -36,11 +44,12 @@
36
44
  "react": ">=18"
37
45
  },
38
46
  "dependencies": {
39
- "@w6w/sdk": "^0.6.0"
47
+ "@w6w/sdk": "^0.9.12"
40
48
  },
41
49
  "devDependencies": {
42
50
  "@biomejs/biome": "^1.9.4",
43
51
  "@types/react": "^18.3.17",
52
+ "@w6w/ui": "0.1.0",
44
53
  "jsdom": "^30.0.1",
45
54
  "react": "^18.3.1",
46
55
  "react-dom": "^18.3.1",