@plumile/relay 0.1.200 → 0.1.205

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/README.md ADDED
@@ -0,0 +1,42 @@
1
+ # @plumile/relay
2
+
3
+ Shared Relay environment, transport, provider, and operation-activity helpers
4
+ for Plumile applications.
5
+
6
+ ## HTTP authentication ownership
7
+
8
+ `configureShortAccessTokenRelayEnvironment()` injects an auth-aware GraphQL
9
+ fetch into this package. The injected fetch owns the single refresh and retry
10
+ after `401`; this transport owns multipart encoding, timeouts, and retries for
11
+ network, `408`, `429`, and `5xx` failures. It does not patch
12
+ `globalThis.fetch`.
13
+
14
+ ## WebSocket transport contract
15
+
16
+ Subscriptions use the `graphql-transport-ws` subprotocol through the package's
17
+ owned client. The client deliberately remains local because the deployed server
18
+ contract includes authentication rotation beyond the standard protocol:
19
+
20
+ - the client sends `connection_init` with the current authentication headers and
21
+ waits for `connection_ack` before subscribing;
22
+ - subscriptions use `subscribe`, `next`, `error`, and `complete`, while
23
+ keep-alive messages use `ping` and `pong`;
24
+ - credential rotation sends `connection_auth_update` and requires
25
+ `connection_auth_update_ack` within five seconds;
26
+ - an unexpected disconnect retries with bounded exponential backoff (at most ten
27
+ attempts) and re-subscribes every still-active operation after the next ack;
28
+ - invalid or unsupported server messages close the socket with code `4400`;
29
+ normal environment disposal closes it with code `1000`.
30
+
31
+ Do not replace this client with a generic GraphQL WebSocket dependency unless
32
+ that implementation proves the same authentication-update and reconnection
33
+ contract without an adapter of comparable complexity.
34
+
35
+ ## Validation
36
+
37
+ From the repository root, run the Relay tests and build:
38
+
39
+ ```bash
40
+ npx vitest run packages/relay
41
+ npm run --workspace @plumile/relay build:package
42
+ ```
@@ -1,55 +1,63 @@
1
1
  //#region src/envHelpers.ts
2
- var e = (() => {
2
+ function e(e) {
3
+ return typeof e == "object" && !!e;
4
+ }
5
+ var t = (() => {
3
6
  try {
4
- let e = import.meta;
5
- return e.env == null ? {} : e.env;
7
+ let t = import.meta, n;
8
+ if ("env" in t && (n = t.env), e(n)) {
9
+ let e = {};
10
+ for (let [t, r] of Object.entries(n)) (typeof r == "string" || typeof r == "boolean" || r === void 0) && (e[t] = r);
11
+ return e;
12
+ }
13
+ return {};
6
14
  } catch {
7
15
  return {};
8
16
  }
9
- })(), t = (e, t) => {
17
+ })(), n = (e, t) => {
10
18
  let n = e[t];
11
19
  if (typeof n != "string") return;
12
20
  let r = n.trim();
13
21
  if (r !== "") return r;
14
- }, n = (e, t) => {
22
+ }, r = (e, t) => {
15
23
  let n = e[t];
16
24
  if (n === !0 || n === !1) return n;
17
25
  if (typeof n == "string") {
18
26
  if (n === "true") return !0;
19
27
  if (n === "false") return !1;
20
28
  }
21
- }, r = (e) => !!n(e, "DEV");
22
- function i(n) {
23
- return t(e, n);
29
+ }, i = (e) => !!r(e, "DEV");
30
+ function a(e) {
31
+ return n(t, e);
24
32
  }
25
- function a(t) {
26
- return n(e, t);
33
+ function o(e) {
34
+ return r(t, e);
27
35
  }
28
- function o() {
29
- return r(e);
36
+ function s() {
37
+ return i(t);
30
38
  }
31
- function s(e) {
32
- let { envKeys: t, fallback: n, read: r = i } = e;
39
+ function c(e) {
40
+ let { envKeys: t, fallback: n, read: r = a } = e;
33
41
  for (let e of t) {
34
42
  let t = r(e);
35
43
  if (t != null) return t;
36
44
  }
37
45
  return n;
38
46
  }
39
- function c(e) {
40
- let { envKeys: t, fallback: n, httpEndpoint: r, read: a = i } = e;
47
+ function l(e) {
48
+ let { envKeys: t, fallback: n, httpEndpoint: r, read: i = a } = e;
41
49
  for (let e of t) {
42
- let t = a(e);
50
+ let t = i(e);
43
51
  if (t != null) return t;
44
52
  }
45
53
  return r.startsWith("http") ? r.replace(/^http/, "ws") : r.startsWith("/") ? r.replace(/\/graphql$/, "/ws") : n;
46
54
  }
47
- var l = {
48
- isDevEnvFromRecord: r,
49
- readBooleanEnvFromRecord: n,
50
- readEnvFromRecord: t
55
+ var u = {
56
+ isDevEnvFromRecord: i,
57
+ readBooleanEnvFromRecord: r,
58
+ readEnvFromRecord: n
51
59
  };
52
60
  //#endregion
53
- export { l as __test, o as isDevEnv, a as readBooleanEnv, i as readEnv, s as resolveHttpEndpoint, c as resolveWebsocketEndpoint };
61
+ export { u as __test, s as isDevEnv, o as readBooleanEnv, a as readEnv, c as resolveHttpEndpoint, l as resolveWebsocketEndpoint };
54
62
 
55
63
  //# sourceMappingURL=envHelpers.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"envHelpers.js","names":[],"sources":["../../src/envHelpers.ts"],"sourcesContent":["type EnvRecord = Record<string, string | boolean | undefined>;\n\nconst viteEnv: EnvRecord = (() => {\n try {\n const meta = import.meta as unknown as { env?: EnvRecord };\n if (meta.env != null) {\n return meta.env;\n }\n return {};\n } catch {\n // `import.meta` is not defined outside of ESM environments; fall back to an empty record.\n return {};\n }\n})();\n\nexport type ReadEnvFn = (key: string) => string | undefined;\n\nconst readEnvFromRecord = (env: EnvRecord, key: string): string | undefined => {\n const value = env[key];\n if (typeof value !== 'string') {\n return undefined;\n }\n\n const trimmed = value.trim();\n if (trimmed === '') {\n return undefined;\n }\n\n return trimmed;\n};\n\nconst readBooleanEnvFromRecord = (\n env: EnvRecord,\n key: string,\n): boolean | undefined => {\n const value = env[key];\n if (value === true || value === false) {\n return value;\n }\n if (typeof value === 'string') {\n if (value === 'true') {\n return true;\n }\n if (value === 'false') {\n return false;\n }\n }\n return undefined;\n};\n\nconst isDevEnvFromRecord = (env: EnvRecord): boolean => {\n return Boolean(readBooleanEnvFromRecord(env, 'DEV'));\n};\n\n/**\n * Read a string environment variable from Vite's `import.meta.env` (if available).\n * Returns `undefined` when the value is missing or empty.\n */\nexport function readEnv(key: string): string | undefined {\n return readEnvFromRecord(viteEnv, key);\n}\n\n/**\n * Reads an environment variable and coerces common string values to booleans.\n */\nexport function readBooleanEnv(key: string): boolean | undefined {\n return readBooleanEnvFromRecord(viteEnv, key);\n}\n\n/**\n * Indicates whether the current build is running in development mode.\n */\nexport function isDevEnv(): boolean {\n return isDevEnvFromRecord(viteEnv);\n}\n\ninterface ResolveEndpointOptions {\n envKeys: readonly string[];\n fallback: string;\n read?: ReadEnvFn;\n}\n\n/**\n * Resolve HTTP endpoint from environment variables.\n */\nexport function resolveHttpEndpoint(options: ResolveEndpointOptions): string {\n const { envKeys, fallback, read = readEnv } = options;\n for (const key of envKeys) {\n const value = read(key);\n if (value != null) {\n return value;\n }\n }\n return fallback;\n}\n\ninterface ResolveWebsocketEndpointOptions extends ResolveEndpointOptions {\n httpEndpoint: string;\n}\n\n/**\n * Resolve websocket endpoint from environment variables or derive it from the HTTP endpoint.\n */\nexport function resolveWebsocketEndpoint(\n options: ResolveWebsocketEndpointOptions,\n): string {\n const { envKeys, fallback, httpEndpoint, read = readEnv } = options;\n\n for (const key of envKeys) {\n const value = read(key);\n if (value != null) {\n return value;\n }\n }\n\n if (httpEndpoint.startsWith('http')) {\n return httpEndpoint.replace(/^http/, 'ws');\n }\n\n if (httpEndpoint.startsWith('/')) {\n return httpEndpoint.replace(/\\/graphql$/, '/ws');\n }\n\n return fallback;\n}\n\nexport const __test = {\n isDevEnvFromRecord,\n readBooleanEnvFromRecord,\n readEnvFromRecord,\n};\n"],"mappings":";AAEA,IAAM,WAA4B;CAChC,IAAI;EACF,IAAM,IAAO;EAIb,OAHI,EAAK,OAAO,OAGT,CAAC,IAFC,EAAK;CAGhB,QAAQ;EAEN,OAAO,CAAC;CACV;AACF,EAAA,CAAG,GAIG,KAAqB,GAAgB,MAAoC;CAC7E,IAAM,IAAQ,EAAI;CAClB,IAAI,OAAO,KAAU,UACnB;CAGF,IAAM,IAAU,EAAM,KAAK;CACvB,UAAY,IAIhB,OAAO;AACT,GAEM,KACJ,GACA,MACwB;CACxB,IAAM,IAAQ,EAAI;CAClB,IAAI,MAAU,MAAQ,MAAU,IAC9B,OAAO;CAET,IAAI,OAAO,KAAU,UAAU;EAC7B,IAAI,MAAU,QACZ,OAAO;EAET,IAAI,MAAU,SACZ,OAAO;CAEX;AAEF,GAEM,KAAsB,MACnB,EAAQ,EAAyB,GAAK,KAAK;AAOpD,SAAgB,EAAQ,GAAiC;CACvD,OAAO,EAAkB,GAAS,CAAG;AACvC;AAKA,SAAgB,EAAe,GAAkC;CAC/D,OAAO,EAAyB,GAAS,CAAG;AAC9C;AAKA,SAAgB,IAAoB;CAClC,OAAO,EAAmB,CAAO;AACnC;AAWA,SAAgB,EAAoB,GAAyC;CAC3E,IAAM,EAAE,YAAS,aAAU,UAAO,MAAY;CAC9C,KAAK,IAAM,KAAO,GAAS;EACzB,IAAM,IAAQ,EAAK,CAAG;EACtB,IAAI,KAAS,MACX,OAAO;CAEX;CACA,OAAO;AACT;AASA,SAAgB,EACd,GACQ;CACR,IAAM,EAAE,YAAS,aAAU,iBAAc,UAAO,MAAY;CAE5D,KAAK,IAAM,KAAO,GAAS;EACzB,IAAM,IAAQ,EAAK,CAAG;EACtB,IAAI,KAAS,MACX,OAAO;CAEX;CAUA,OARI,EAAa,WAAW,MAAM,IACzB,EAAa,QAAQ,SAAS,IAAI,IAGvC,EAAa,WAAW,GAAG,IACtB,EAAa,QAAQ,cAAc,KAAK,IAG1C;AACT;AAEA,IAAa,IAAS;CACpB;CACA;CACA;AACF"}
1
+ {"version":3,"file":"envHelpers.js","names":[],"sources":["../../src/envHelpers.ts"],"sourcesContent":["type EnvRecord = Record<string, string | boolean | undefined>;\n\n/** Narrows external environment objects before enumerating their values. */\nfunction isUnknownRecord(value: unknown): value is Record<string, unknown> {\n return value != null && typeof value === 'object';\n}\n\nconst viteEnv: EnvRecord = (() => {\n try {\n const meta: object = import.meta;\n let env: unknown;\n if ('env' in meta) {\n env = meta.env;\n }\n if (isUnknownRecord(env)) {\n const result: EnvRecord = {};\n for (const [key, value] of Object.entries(env)) {\n if (\n typeof value === 'string' ||\n typeof value === 'boolean' ||\n value === undefined\n ) {\n result[key] = value;\n }\n }\n return result;\n }\n return {};\n } catch {\n // `import.meta` is not defined outside of ESM environments; fall back to an empty record.\n return {};\n }\n})();\n\nexport type ReadEnvFn = (key: string) => string | undefined;\n\nconst readEnvFromRecord = (env: EnvRecord, key: string): string | undefined => {\n const value = env[key];\n if (typeof value !== 'string') {\n return undefined;\n }\n\n const trimmed = value.trim();\n if (trimmed === '') {\n return undefined;\n }\n\n return trimmed;\n};\n\nconst readBooleanEnvFromRecord = (\n env: EnvRecord,\n key: string,\n): boolean | undefined => {\n const value = env[key];\n if (value === true || value === false) {\n return value;\n }\n if (typeof value === 'string') {\n if (value === 'true') {\n return true;\n }\n if (value === 'false') {\n return false;\n }\n }\n return undefined;\n};\n\nconst isDevEnvFromRecord = (env: EnvRecord): boolean => {\n return Boolean(readBooleanEnvFromRecord(env, 'DEV'));\n};\n\n/**\n * Read a string environment variable from Vite's `import.meta.env` (if available).\n * Returns `undefined` when the value is missing or empty.\n */\nexport function readEnv(key: string): string | undefined {\n return readEnvFromRecord(viteEnv, key);\n}\n\n/**\n * Reads an environment variable and coerces common string values to booleans.\n */\nexport function readBooleanEnv(key: string): boolean | undefined {\n return readBooleanEnvFromRecord(viteEnv, key);\n}\n\n/**\n * Indicates whether the current build is running in development mode.\n */\nexport function isDevEnv(): boolean {\n return isDevEnvFromRecord(viteEnv);\n}\n\ninterface ResolveEndpointOptions {\n envKeys: readonly string[];\n fallback: string;\n read?: ReadEnvFn;\n}\n\n/**\n * Resolve HTTP endpoint from environment variables.\n */\nexport function resolveHttpEndpoint(options: ResolveEndpointOptions): string {\n const { envKeys, fallback, read = readEnv } = options;\n for (const key of envKeys) {\n const value = read(key);\n if (value != null) {\n return value;\n }\n }\n return fallback;\n}\n\ninterface ResolveWebsocketEndpointOptions extends ResolveEndpointOptions {\n httpEndpoint: string;\n}\n\n/**\n * Resolve websocket endpoint from environment variables or derive it from the HTTP endpoint.\n */\nexport function resolveWebsocketEndpoint(\n options: ResolveWebsocketEndpointOptions,\n): string {\n const { envKeys, fallback, httpEndpoint, read = readEnv } = options;\n\n for (const key of envKeys) {\n const value = read(key);\n if (value != null) {\n return value;\n }\n }\n\n if (httpEndpoint.startsWith('http')) {\n return httpEndpoint.replace(/^http/, 'ws');\n }\n\n if (httpEndpoint.startsWith('/')) {\n return httpEndpoint.replace(/\\/graphql$/, '/ws');\n }\n\n return fallback;\n}\n\nexport const __test = {\n isDevEnvFromRecord,\n readBooleanEnvFromRecord,\n readEnvFromRecord,\n};\n"],"mappings":";AAGA,SAAS,EAAgB,GAAkD;CACzE,OAAwB,OAAO,KAAU,cAAlC;AACT;AAEA,IAAM,WAA4B;CAChC,IAAI;EACF,IAAM,IAAe,aACjB;EAIJ,IAHI,SAAS,MACX,IAAM,EAAK,MAET,EAAgB,CAAG,GAAG;GACxB,IAAM,IAAoB,CAAC;GAC3B,KAAK,IAAM,CAAC,GAAK,MAAU,OAAO,QAAQ,CAAG,GAC3C,CACE,OAAO,KAAU,YACjB,OAAO,KAAU,aACjB,MAAU,KAAA,OAEV,EAAO,KAAO;GAGlB,OAAO;EACT;EACA,OAAO,CAAC;CACV,QAAQ;EAEN,OAAO,CAAC;CACV;AACF,EAAA,CAAG,GAIG,KAAqB,GAAgB,MAAoC;CAC7E,IAAM,IAAQ,EAAI;CAClB,IAAI,OAAO,KAAU,UACnB;CAGF,IAAM,IAAU,EAAM,KAAK;CACvB,UAAY,IAIhB,OAAO;AACT,GAEM,KACJ,GACA,MACwB;CACxB,IAAM,IAAQ,EAAI;CAClB,IAAI,MAAU,MAAQ,MAAU,IAC9B,OAAO;CAET,IAAI,OAAO,KAAU,UAAU;EAC7B,IAAI,MAAU,QACZ,OAAO;EAET,IAAI,MAAU,SACZ,OAAO;CAEX;AAEF,GAEM,KAAsB,MACnB,EAAQ,EAAyB,GAAK,KAAK;AAOpD,SAAgB,EAAQ,GAAiC;CACvD,OAAO,EAAkB,GAAS,CAAG;AACvC;AAKA,SAAgB,EAAe,GAAkC;CAC/D,OAAO,EAAyB,GAAS,CAAG;AAC9C;AAKA,SAAgB,IAAoB;CAClC,OAAO,EAAmB,CAAO;AACnC;AAWA,SAAgB,EAAoB,GAAyC;CAC3E,IAAM,EAAE,YAAS,aAAU,UAAO,MAAY;CAC9C,KAAK,IAAM,KAAO,GAAS;EACzB,IAAM,IAAQ,EAAK,CAAG;EACtB,IAAI,KAAS,MACX,OAAO;CAEX;CACA,OAAO;AACT;AASA,SAAgB,EACd,GACQ;CACR,IAAM,EAAE,YAAS,aAAU,iBAAc,UAAO,MAAY;CAE5D,KAAK,IAAM,KAAO,GAAS;EACzB,IAAM,IAAQ,EAAK,CAAG;EACtB,IAAI,KAAS,MACX,OAAO;CAEX;CAUA,OARI,EAAa,WAAW,MAAM,IACzB,EAAa,QAAQ,SAAS,IAAI,IAGvC,EAAa,WAAW,GAAG,IACtB,EAAa,QAAQ,cAAc,KAAK,IAG1C;AACT;AAEA,IAAa,IAAS;CACpB;CACA;CACA;AACF"}
@@ -1,63 +1,123 @@
1
1
  import { isDevEnv as e } from "./envHelpers.js";
2
2
  import { Environment as t, Network as n, Observable as r, RecordSource as i, Store as a } from "relay-runtime";
3
3
  //#region src/environment.ts
4
- var o = "/api/graphql", s = "/api/ws", c, l, u, d, f = "require-preflight", p = "true", ee = "graphql-transport-ws", m = 5e3, h = 1e4, g = 10, _ = 500, v = {
4
+ var o = "/api/graphql", s = "/api/ws", c, l, u = 0, d = /* @__PURE__ */ new Set(), f, p = async (e, t) => globalThis.fetch(e, t), m = p, h, g = "require-preflight", ee = "true", te = (e) => typeof e == "object" && !!e && !Array.isArray(e), _ = (e) => {
5
+ if (!te(e) || typeof e.type != "string") return {
6
+ ok: !1,
7
+ reason: "invalid"
8
+ };
9
+ let { payload: t } = e;
10
+ switch (e.type) {
11
+ case "connection_ack":
12
+ case "connection_auth_update_ack":
13
+ case "ping":
14
+ case "pong": return {
15
+ ok: !0,
16
+ value: {
17
+ type: e.type,
18
+ payload: t
19
+ }
20
+ };
21
+ case "next": return typeof e.id == "string" ? {
22
+ ok: !0,
23
+ value: {
24
+ id: e.id,
25
+ type: e.type,
26
+ payload: t
27
+ }
28
+ } : {
29
+ ok: !1,
30
+ reason: "invalid"
31
+ };
32
+ case "error": return e.id != null && typeof e.id != "string" ? {
33
+ ok: !1,
34
+ reason: "invalid"
35
+ } : e.id == null ? {
36
+ ok: !0,
37
+ value: {
38
+ type: e.type,
39
+ payload: t
40
+ }
41
+ } : {
42
+ ok: !0,
43
+ value: {
44
+ id: e.id,
45
+ type: e.type,
46
+ payload: t
47
+ }
48
+ };
49
+ case "complete": return typeof e.id == "string" ? {
50
+ ok: !0,
51
+ value: {
52
+ id: e.id,
53
+ type: e.type
54
+ }
55
+ } : {
56
+ ok: !1,
57
+ reason: "invalid"
58
+ };
59
+ default: return {
60
+ ok: !1,
61
+ reason: "unsupported"
62
+ };
63
+ }
64
+ }, ne = "graphql-transport-ws", re = 5e3, ie = 1e4, ae = 10, oe = 500, v = "Relay operation cancelled after environment rotation", y = {
5
65
  generation: 0,
6
66
  reason: null,
7
67
  status: "idle"
8
- }, y = /* @__PURE__ */ new Set(), b = {
68
+ }, b = /* @__PURE__ */ new Set(), x = {
9
69
  generation: 0,
10
70
  pendingCount: 0,
11
71
  pendingOperations: []
12
- }, x = 0, S = /* @__PURE__ */ new Map(), C = /* @__PURE__ */ new Set(), w = !1;
13
- function T() {}
14
- var E = T;
15
- e() && (E = (e) => {
72
+ }, S = 0, C = /* @__PURE__ */ new Map(), w = /* @__PURE__ */ new Set(), T = !1;
73
+ function E() {}
74
+ var D = E;
75
+ e() && (D = (e) => {
16
76
  console.log("relayFieldLogger: ", e);
17
77
  });
18
- var te = (e) => {
78
+ var O = (e) => {
19
79
  if (typeof e != "object" || !e) return null;
20
80
  let { id: t } = e;
21
81
  return typeof t != "string" || t.trim() === "" ? null : t;
22
- }, D = (e, t) => d?.(e, t) ?? te(e, t);
23
- function O(e, t) {
24
- v = {
25
- generation: v.generation + 1,
82
+ }, k = (e, t) => h?.(e, t) ?? O(e, t);
83
+ function A(e, t) {
84
+ y = {
85
+ generation: y.generation + 1,
26
86
  reason: t,
27
87
  status: e
28
88
  };
29
- for (let e of y) e();
30
- }
31
- function k() {
32
- b = {
33
- generation: b.generation + 1,
34
- pendingCount: S.size,
35
- pendingOperations: [...S.values()]
36
- }, !w && (w = !0, queueMicrotask(() => {
37
- w = !1;
38
- for (let e of C) e();
89
+ for (let e of b) e();
90
+ }
91
+ function j() {
92
+ x = {
93
+ generation: x.generation + 1,
94
+ pendingCount: C.size,
95
+ pendingOperations: [...C.values()]
96
+ }, !T && (T = !0, queueMicrotask(() => {
97
+ T = !1;
98
+ for (let e of w) e();
39
99
  }));
40
100
  }
41
- function A() {
42
- S.size !== 0 && (S.clear(), k());
101
+ function se() {
102
+ C.size !== 0 && (C.clear(), j());
43
103
  }
44
- function j(e) {
104
+ function ce(e) {
45
105
  return e === "query" || e === "mutation" ? e : "unknown";
46
106
  }
47
- function M(e) {
48
- let t = x;
49
- x += 1, S.set(t, {
107
+ function le(e) {
108
+ let t = S;
109
+ S += 1, C.set(t, {
50
110
  id: t,
51
- kind: j(e.operationKind),
111
+ kind: ce(e.operationKind),
52
112
  name: e.name ?? "AnonymousGraphQLOperation",
53
113
  startedAt: Date.now()
54
- }), k();
114
+ }), j();
55
115
  let n = !1;
56
116
  return () => {
57
- n || (n = !0, S.delete(t) && k());
117
+ n || (n = !0, C.delete(t) && j());
58
118
  };
59
119
  }
60
- function N() {
120
+ function ue() {
61
121
  if (l != null) {
62
122
  try {
63
123
  l.dispose();
@@ -65,36 +125,66 @@ function N() {
65
125
  l = void 0;
66
126
  }
67
127
  }
68
- function ne() {
69
- return v;
128
+ function de() {
129
+ if (l != null) {
130
+ try {
131
+ l.terminate();
132
+ } catch {}
133
+ l = void 0;
134
+ }
135
+ }
136
+ function fe() {
137
+ for (let e of d) e.abort();
138
+ d.clear();
139
+ }
140
+ function pe(e) {
141
+ let t = e.getStore(), n = t.getSource(), r = new i();
142
+ for (let e of n.getRecordIDs()) r.delete(e);
143
+ try {
144
+ r.size() > 0 && (t.publish(r), t.notify());
145
+ } finally {
146
+ n instanceof i && n.clear();
147
+ }
148
+ }
149
+ function M(e, t) {
150
+ let n = c;
151
+ c = void 0, u += 1, fe(), de();
152
+ try {
153
+ n != null && pe(n);
154
+ } finally {
155
+ se(), A(e, t);
156
+ }
157
+ }
158
+ function me() {
159
+ return y;
70
160
  }
71
- function re(e) {
72
- return y.add(e), () => {
73
- y.delete(e);
161
+ function he(e) {
162
+ return b.add(e), () => {
163
+ b.delete(e);
74
164
  };
75
165
  }
76
- function ie() {
77
- return b;
166
+ function N() {
167
+ return x;
78
168
  }
79
- function ae(e) {
80
- return C.add(e), () => {
81
- C.delete(e);
169
+ function P(e) {
170
+ return w.add(e), () => {
171
+ w.delete(e);
82
172
  };
83
173
  }
84
- function P(e = {}) {
85
- N(), O("reconnecting", e.reason ?? "manual_reconnect");
174
+ function F(e = {}) {
175
+ ue(), A("reconnecting", e.reason ?? "manual_reconnect");
86
176
  }
87
- async function oe(e = {}) {
177
+ async function I(e = {}) {
88
178
  let t = l;
89
- t?.hasActiveConnection() && (await t.refreshAuthentication() || P({ reason: e.reason ?? "auth_refresh_fallback" }));
179
+ t?.hasActiveConnection() && (await t.refreshAuthentication() || F({ reason: e.reason ?? "auth_refresh_fallback" }));
90
180
  }
91
- function se(e = {}) {
92
- let { httpUrl: t, wsUrl: n, logEvents: r, getDataId: i, getAuthHeaders: a } = e;
93
- typeof t == "string" && t !== "" && (o = t), typeof n == "string" && n !== "" && (s = n), r != null && (E = r ? (e) => {
181
+ function L(e = {}) {
182
+ let { httpUrl: t, wsUrl: n, logEvents: r, getDataId: i, getAuthHeaders: a, fetchImpl: c } = e;
183
+ typeof t == "string" && t !== "" && (o = t), typeof n == "string" && n !== "" && (s = n), r != null && (D = r ? (e) => {
94
184
  console.log("relayFieldLogger: ", e);
95
- } : T), d = i, u = a, N(), c = void 0, A(), O("configured", "configure");
185
+ } : E), h = i, f = a, m = c ?? p, M("configured", "configure");
96
186
  }
97
- function F() {
187
+ function ge() {
98
188
  let e = s;
99
189
  if (e.startsWith("ws")) return e;
100
190
  if (e.startsWith("http")) return e.replace(/^http/, "ws");
@@ -105,13 +195,13 @@ function F() {
105
195
  }
106
196
  return e;
107
197
  }
108
- function I(...t) {
198
+ function R(...t) {
109
199
  e() && console.log("[RelayNetwork]", ...t);
110
200
  }
111
- async function L() {
112
- return u == null ? {} : u();
201
+ async function z() {
202
+ return f == null ? {} : f();
113
203
  }
114
- var R = class {
204
+ var B = class {
115
205
  url;
116
206
  socket = null;
117
207
  connectPromise = null;
@@ -133,13 +223,19 @@ var R = class {
133
223
  let { socket: e } = this;
134
224
  this.socket = null, this.connectPromise = null, this.acknowledged = !1, e != null && e.readyState !== WebSocket.CLOSED && e.close(1e3, "Normal Closure");
135
225
  }
226
+ terminate() {
227
+ for (let e of this.subscriptions.values()) try {
228
+ e.sink.complete();
229
+ } catch {}
230
+ this.subscriptions.clear(), this.dispose();
231
+ }
136
232
  subscribe(e, t) {
137
233
  let n = String(this.nextId);
138
234
  return this.nextId += 1, this.subscriptions.set(n, {
139
235
  payload: e,
140
236
  sink: t
141
237
  }), this.connectAndSubscribe(n).catch((e) => {
142
- I("subscription websocket connect failed", e), this.scheduleReconnect();
238
+ R("subscription websocket connect failed", e), this.scheduleReconnect();
143
239
  }), () => {
144
240
  this.unsubscribe(n);
145
241
  };
@@ -151,14 +247,14 @@ var R = class {
151
247
  if (this.pendingAuthUpdate != null) return !1;
152
248
  let t;
153
249
  try {
154
- t = await L();
250
+ t = await z();
155
251
  } catch {
156
252
  return !1;
157
253
  }
158
254
  return Object.keys(t).length !== 0 && new Promise((e) => {
159
255
  let n = setTimeout(() => {
160
256
  this.pendingAuthUpdate = null, e(!1);
161
- }, m);
257
+ }, re);
162
258
  this.pendingAuthUpdate = {
163
259
  resolve: e,
164
260
  timeout: n
@@ -199,9 +295,9 @@ var R = class {
199
295
  n || (n = !0, e());
200
296
  }, i = (e) => {
201
297
  n || (n = !0, t(e));
202
- }, a = new WebSocket(this.url, ee);
298
+ }, a = new WebSocket(this.url, ne);
203
299
  this.socket = a, this.acknowledged = !1, a.onopen = () => {
204
- L().catch(() => ({})).then((e) => {
300
+ z().catch(() => ({})).then((e) => {
205
301
  if (a.readyState === WebSocket.OPEN) {
206
302
  if (Object.keys(e).length > 0) {
207
303
  this.send({
@@ -232,7 +328,14 @@ var R = class {
232
328
  n(/* @__PURE__ */ Error("Invalid GraphQL websocket message")), this.socket?.close(4400, "Invalid websocket message");
233
329
  return;
234
330
  }
235
- switch (r.type) {
331
+ let i = _(r);
332
+ if (!i.ok) {
333
+ let e = i.reason === "unsupported", t = "Invalid GraphQL websocket message", r = "Invalid websocket message";
334
+ e && (t = "Unsupported GraphQL websocket message", r = "Unsupported websocket message"), n(Error(t)), this.socket?.close(4400, r);
335
+ return;
336
+ }
337
+ let a = i.value;
338
+ switch (a.type) {
236
339
  case "connection_ack":
237
340
  this.acknowledged = !0, this.retryCount = 0, this.startKeepAlive(), t(), this.resubscribeActiveOperations();
238
341
  return;
@@ -240,37 +343,33 @@ var R = class {
240
343
  this.resolvePendingAuthUpdate(!0);
241
344
  return;
242
345
  case "next":
243
- this.subscriptions.get(r.id)?.sink.next(r.payload);
346
+ this.subscriptions.get(a.id)?.sink.next(a.payload);
244
347
  return;
245
348
  case "error":
246
- r.id == null ? this.resolvePendingAuthUpdate(!1) : this.failSubscription(r.id, r.payload);
349
+ a.id == null ? this.resolvePendingAuthUpdate(!1) : this.failSubscription(a.id, a.payload);
247
350
  return;
248
351
  case "complete":
249
- this.completeSubscription(r.id);
250
- return;
251
- case "ping":
252
- this.send({
253
- type: "pong",
254
- payload: r.payload
255
- });
352
+ this.completeSubscription(a.id);
256
353
  return;
257
- case "pong": return;
258
- default: n(/* @__PURE__ */ Error("Unsupported GraphQL websocket message")), this.socket?.close(4400, "Unsupported websocket message");
354
+ case "ping": this.send({
355
+ type: "pong",
356
+ payload: a.payload
357
+ });
259
358
  }
260
359
  }
261
360
  handleClose() {
262
361
  this.acknowledged = !1, this.socket = null, this.connectPromise = null, this.stopKeepAlive(), this.resolvePendingAuthUpdate(!1), !this.disposed && this.subscriptions.size > 0 && this.scheduleReconnect();
263
362
  }
264
363
  scheduleReconnect() {
265
- if (this.retryCount >= g) {
364
+ if (this.retryCount >= ae) {
266
365
  let e = /* @__PURE__ */ Error("GraphQL subscription websocket retry exhausted");
267
366
  for (let t of [...this.subscriptions.keys()]) this.failSubscription(t, e);
268
367
  return;
269
368
  }
270
- let e = Math.min(8e3, _ * 2 ** this.retryCount) + Math.random() * 200;
369
+ let e = Math.min(8e3, oe * 2 ** this.retryCount) + Math.random() * 200;
271
370
  this.retryCount += 1, setTimeout(() => {
272
371
  this.disposed || this.subscriptions.size === 0 || this.ensureConnected().catch((e) => {
273
- this.scheduleReconnect(), I("subscription websocket reconnect failed", e);
372
+ this.scheduleReconnect(), R("subscription websocket reconnect failed", e);
274
373
  });
275
374
  }, e);
276
375
  }
@@ -298,7 +397,7 @@ var R = class {
298
397
  startKeepAlive() {
299
398
  this.stopKeepAlive(), this.keepAliveTimer = setInterval(() => {
300
399
  this.socket?.readyState === WebSocket.OPEN && this.send({ type: "ping" });
301
- }, h);
400
+ }, ie);
302
401
  }
303
402
  stopKeepAlive() {
304
403
  this.keepAliveTimer != null && (clearInterval(this.keepAliveTimer), this.keepAliveTimer = null);
@@ -312,29 +411,29 @@ var R = class {
312
411
  t?.readyState === WebSocket.OPEN && t.send(JSON.stringify(e));
313
412
  }
314
413
  };
315
- function z() {
414
+ function _e() {
316
415
  if (l != null) return l;
317
416
  if (typeof window > "u") throw Error("GraphQL subscriptions unavailable in non-browser environment");
318
- return l = new R(F()), l;
417
+ return l = new B(ge()), l;
319
418
  }
320
- function B(e) {
419
+ function V(e) {
321
420
  return typeof File < "u" && e instanceof File || typeof Blob < "u" && e instanceof Blob;
322
421
  }
323
- function V(e, t, n) {
324
- if (B(e)) return n.push({
422
+ function H(e, t, n) {
423
+ if (V(e)) return n.push({
325
424
  path: t,
326
425
  file: e
327
426
  }), null;
328
- if (Array.isArray(e)) return e.map((e, r) => V(e, `${t}.${r}`, n));
427
+ if (Array.isArray(e)) return e.map((e, r) => H(e, `${t}.${r}`, n));
329
428
  if (typeof e == "object" && e) {
330
429
  let r = {};
331
- for (let [i, a] of Object.entries(e)) r[i] = V(a, `${t}.${i}`, n);
430
+ for (let [i, a] of Object.entries(e)) r[i] = H(a, `${t}.${i}`, n);
332
431
  return r;
333
432
  }
334
433
  return e;
335
434
  }
336
- function H(e, t) {
337
- let n = [], r = V(t, "variables", n), i = new FormData(), a = {
435
+ function U(e, t) {
436
+ let n = [], r = H(t, "variables", n), i = new FormData(), a = {
338
437
  query: e,
339
438
  variables: r
340
439
  };
@@ -346,13 +445,13 @@ function H(e, t) {
346
445
  i.append(String(t), e.file);
347
446
  }), i;
348
447
  }
349
- var U = {
448
+ var W = {
350
449
  maxAttempts: 3,
351
450
  baseDelayMs: 300,
352
451
  maxDelayMs: 4e3,
353
452
  fetchTimeoutMs: 6e5
354
453
  };
355
- async function W(e) {
454
+ async function ve(e) {
356
455
  await new Promise((t) => {
357
456
  setTimeout(() => {
358
457
  t();
@@ -379,7 +478,7 @@ var J = class extends Error {
379
478
  function Y(e) {
380
479
  return e == null ? !1 : typeof e != "object" || Object.values(e).some((e) => e != null);
381
480
  }
382
- function ce(e) {
481
+ function ye(e) {
383
482
  let { data: t, errors: n } = e;
384
483
  if (typeof t != "object" || !t || !Array.isArray(n) || n.length === 0) return !1;
385
484
  let r = t;
@@ -389,72 +488,78 @@ function ce(e) {
389
488
  });
390
489
  }
391
490
  function X(e) {
392
- return Array.isArray(e.errors) && e.errors.length > 0 && !Y(e.data) && !ce(e);
491
+ return Array.isArray(e.errors) && e.errors.length > 0 && !Y(e.data) && !ye(e);
393
492
  }
394
493
  async function Z(e, t, n, r) {
395
- let i = e.text;
396
- if (i == null) throw Error("Missing GraphQL query text");
397
- let a = i, s = M(e);
398
- async function c(e) {
399
- let n = new AbortController(), r = setTimeout(() => {
494
+ let i = u, a = e.text;
495
+ if (a == null) throw Error("Missing GraphQL query text");
496
+ let s = a, c = le(e);
497
+ async function l(e) {
498
+ if (i !== u) throw Error(v);
499
+ let n = new AbortController();
500
+ d.add(n);
501
+ let r = setTimeout(() => {
400
502
  n.abort();
401
- }, U.fetchTimeoutMs);
503
+ }, W.fetchTimeoutMs);
402
504
  try {
403
- let r, i = {};
404
- if (u != null) try {
405
- Object.assign(i, await u());
505
+ let r, a = {};
506
+ if (f != null) try {
507
+ Object.assign(a, await f());
406
508
  } catch {}
509
+ if (i !== u) throw Error(v);
407
510
  (() => {
408
511
  try {
409
512
  let e = [t];
410
513
  for (; e.length > 0;) {
411
514
  let t = e.pop();
412
- if (B(t)) return !0;
515
+ if (V(t)) return !0;
413
516
  Array.isArray(t) ? e.push(...t) : typeof t == "object" && t && e.push(...Object.values(t));
414
517
  }
415
518
  } catch {}
416
519
  return !1;
417
- })() ? (r = H(a, t), i[f] = p) : (i["Content-Type"] = "application/json", r = JSON.stringify({
418
- query: a,
520
+ })() ? (r = U(s, t), a[g] = ee) : (a["Content-Type"] = "application/json", r = JSON.stringify({
521
+ query: s,
419
522
  variables: t
420
523
  }));
421
- let s = await fetch(o, {
524
+ let c = await m(o, {
422
525
  method: "POST",
423
526
  body: r,
424
- headers: i,
527
+ headers: a,
425
528
  credentials: "include",
426
529
  signal: n.signal
427
530
  });
428
- if (!s.ok) {
429
- if (e < U.maxAttempts - 1 && K(s.status)) throw Error(`Retryable HTTP status ${s.status}`);
430
- let t = await s.text().catch(() => "");
431
- throw Error(`GraphQL HTTP error ${s.status}: ${t}`);
531
+ if (i !== u) throw Error(v);
532
+ if (!c.ok) {
533
+ if (e < W.maxAttempts - 1 && K(c.status)) throw Error(`Retryable HTTP status ${c.status}`);
534
+ let t = await c.text().catch(() => "");
535
+ throw Error(`GraphQL HTTP error ${c.status}: ${t}`);
432
536
  }
433
- let c = await s.json();
434
- if (Array.isArray(c.errors) && c.errors.length > 0 && I("GraphQL errors", c.errors), X(c)) throw new J(c.errors ?? [], c);
435
- return c;
537
+ let l = await c.json();
538
+ if (Array.isArray(l.errors) && l.errors.length > 0 && R("GraphQL errors", l.errors), X(l)) throw new J(l.errors ?? [], l);
539
+ return l;
436
540
  } finally {
437
- clearTimeout(r);
541
+ clearTimeout(r), d.delete(n);
438
542
  }
439
543
  }
440
544
  try {
441
- for (let e = 0; e < U.maxAttempts; e += 1) try {
442
- return await c(e);
545
+ for (let e = 0; e < W.maxAttempts; e += 1) try {
546
+ return await l(e);
443
547
  } catch (t) {
444
- let n = e === U.maxAttempts - 1;
445
- if (!(q(t) || t instanceof Error && t.message.includes("Retryable HTTP status")) || n) throw I("GraphQL fetch error", t), t;
446
- await W(G(e, U));
548
+ if (i !== u) throw Error(v, { cause: t });
549
+ let n = e === W.maxAttempts - 1;
550
+ if (!(q(t) || t instanceof Error && t.message.includes("Retryable HTTP status")) || n) throw R("GraphQL fetch error", t), t;
551
+ await ve(G(e, W));
447
552
  }
448
553
  throw Error("Exhausted retries without returning a result");
449
554
  } finally {
450
- s();
555
+ c();
451
556
  }
452
557
  }
453
- function le(e, t) {
454
- return I("subscription:start", e.name, t), r.create((n) => {
558
+ function Q(e, t) {
559
+ return R("subscription:start", e.name, t), r.create((n) => {
455
560
  let r = e.text;
456
561
  if (r == null || r === "") return n.error(/* @__PURE__ */ Error("Subscription operation text is empty")), () => {};
457
- let i = z().subscribe({
562
+ let i = _e().subscribe({
458
563
  query: r,
459
564
  variables: t,
460
565
  operationName: e.name
@@ -475,35 +580,36 @@ function le(e, t) {
475
580
  };
476
581
  });
477
582
  }
478
- function Q() {
479
- return n.create(Z, le);
480
- }
481
583
  function $() {
584
+ return n.create(Z, Q);
585
+ }
586
+ function be() {
482
587
  return c ??= new t({
483
- getDataID: D,
484
- relayFieldLogger: E,
485
- network: Q(),
588
+ getDataID: k,
589
+ relayFieldLogger: D,
590
+ network: $(),
486
591
  store: new a(new i())
487
592
  }), c;
488
593
  }
489
- function ue() {
490
- let e = $(), t = new i();
491
- e.getStore().publish(t), e.getStore().notify();
594
+ function xe() {
595
+ M("configured", "session_reset");
492
596
  }
493
- var de = {
494
- RelayWebSocketClient: R,
495
- buildFormData: H,
597
+ var Se = {
598
+ RelayWebSocketClient: B,
599
+ buildFormData: U,
496
600
  calcBackoff: G,
497
- collectFiles: V,
601
+ collectFiles: H,
602
+ decodeGraphqlWsMessage: _,
498
603
  fetchFn: Z,
499
- getDataId: D,
604
+ getDataId: k,
500
605
  hasUsableTopLevelData: Y,
501
606
  isNetworkError: q,
502
607
  isRetryableStatus: K,
503
- isUploadable: B,
504
- shouldThrowGraphQLResponseError: X
608
+ isUploadable: V,
609
+ shouldThrowGraphQLResponseError: X,
610
+ subscribeFn: Q
505
611
  };
506
612
  //#endregion
507
- export { J as GraphQLResponseError, de as __test, se as configureRelayEnvironment, $ as getEnvironment, Q as getNetwork, ie as getRelayOperationActivitySnapshot, ne as getRelayTransportSnapshot, P as reconnectRelayWebSocket, oe as refreshRelayWebSocketAuthentication, ue as resetRelayStore, ae as subscribeRelayOperationActivity, re as subscribeRelayTransport };
613
+ export { J as GraphQLResponseError, Se as __test, L as configureRelayEnvironment, be as getEnvironment, $ as getNetwork, N as getRelayOperationActivitySnapshot, me as getRelayTransportSnapshot, F as reconnectRelayWebSocket, I as refreshRelayWebSocketAuthentication, xe as resetRelayStore, P as subscribeRelayOperationActivity, he as subscribeRelayTransport };
508
614
 
509
615
  //# sourceMappingURL=environment.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"environment.js","names":[],"sources":["../../src/environment.ts"],"sourcesContent":["import {\n Environment,\n Network,\n Observable,\n RecordSource,\n Store,\n type FetchFunction,\n type SubscribeFunction,\n type RelayFieldLogger,\n} from 'relay-runtime';\nimport { isDevEnv } from './envHelpers.js';\n\nlet graphqlHttpEndpoint = '/api/graphql';\nlet graphqlWsEndpoint = '/api/ws';\n\n// (anonymousEnvironment reserved if needed later for public access / logout scenarios)\n// Removed until actually required to avoid lint errors.\n// let anonymousEnvironment: Environment | undefined;\nlet environment: Environment | undefined;\nlet wsClient: RelayWebSocketClient | undefined;\nlet getAuthHeaders:\n (() => Record<string, string> | Promise<Record<string, string>>) | undefined;\nlet customDataIdResolver:\n ((fieldValue: unknown, typeName: string) => string | null) | undefined;\n\nconst GRAPHQL_CSRF_PREFLIGHT_HEADER = 'require-preflight';\nconst GRAPHQL_CSRF_PREFLIGHT_HEADER_VALUE = 'true';\n\nexport type RelayTransportStatus = 'idle' | 'configured' | 'reconnecting';\n\nexport interface RelayTransportSnapshot {\n generation: number;\n reason: string | null;\n status: RelayTransportStatus;\n}\n\nexport type RelayOperationKind = 'mutation' | 'query' | 'unknown';\n\nexport type RelayPendingOperation = {\n id: number;\n kind: RelayOperationKind;\n name: string;\n startedAt: number;\n};\n\nexport interface RelayOperationActivitySnapshot {\n generation: number;\n pendingCount: number;\n pendingOperations: readonly RelayPendingOperation[];\n}\n\nexport interface RelayReconnectOptions {\n reason?: string;\n}\n\nexport interface RelayAuthRefreshOptions {\n reason?: string;\n}\n\ntype RelayTransportListener = () => void;\ntype RelayOperationActivityListener = () => void;\n\ntype GraphqlWsPayload = Record<string, unknown>;\n\ntype GraphqlWsMessage =\n | { type: 'connection_ack'; payload?: unknown }\n | { type: 'connection_auth_update_ack'; payload?: unknown }\n | { id: string; type: 'next'; payload: unknown }\n | { id?: string; type: 'error'; payload: unknown }\n | { id: string; type: 'complete' }\n | { type: 'ping'; payload?: unknown }\n | { type: 'pong'; payload?: unknown };\n\ntype SubscriptionSink = {\n next: (value: unknown) => void;\n error: (error: unknown) => void;\n complete: () => void;\n};\n\ntype ActiveSubscription = {\n payload: {\n query: string;\n variables: Record<string, unknown>;\n operationName: string;\n };\n sink: SubscriptionSink;\n};\n\nconst GRAPHQL_TRANSPORT_WS_PROTOCOL = 'graphql-transport-ws';\nconst AUTH_UPDATE_TIMEOUT_MS = 5_000;\nconst WS_KEEP_ALIVE_MS = 10_000;\nconst WS_MAX_RETRY_ATTEMPTS = 10;\nconst WS_BASE_RETRY_DELAY_MS = 500;\n\nlet relayTransportSnapshot: RelayTransportSnapshot = {\n generation: 0,\n reason: null,\n status: 'idle',\n};\nconst relayTransportListeners = new Set<RelayTransportListener>();\n\nlet relayOperationActivitySnapshot: RelayOperationActivitySnapshot = {\n generation: 0,\n pendingCount: 0,\n pendingOperations: [],\n};\nlet relayOperationActivityId = 0;\nconst relayPendingOperations = new Map<number, RelayPendingOperation>();\nconst relayOperationActivityListeners =\n new Set<RelayOperationActivityListener>();\nlet relayOperationActivityNotifyScheduled = false;\n\n/**\n * No-op Relay field logger used to satisfy @required(action: LOG).\n */\nfunction noopRelayFieldLogger(): void {}\n\nlet relayFieldLogger: RelayFieldLogger = noopRelayFieldLogger;\n\nif (isDevEnv()) {\n relayFieldLogger = (event) => {\n // eslint-disable-next-line no-console\n console.log('relayFieldLogger: ', event);\n };\n}\n\nconst defaultGetDataId: (\n fieldValue: unknown,\n typeName: string,\n) => string | null = (fieldValue) => {\n if (fieldValue == null || typeof fieldValue !== 'object') {\n return null;\n }\n const { id } = fieldValue as { id?: unknown };\n if (typeof id !== 'string' || id.trim() === '') {\n return null;\n }\n return id;\n};\n\nconst getDataId = (fieldValue: unknown, typeName: string): string | null => {\n const customId = customDataIdResolver?.(fieldValue, typeName);\n if (customId != null) {\n return customId;\n }\n return defaultGetDataId(fieldValue, typeName);\n};\n\n/**\n * Notify subscribers that the Relay transport state changed.\n */\nfunction emitRelayTransportChange(\n status: RelayTransportStatus,\n reason: string | null,\n): void {\n relayTransportSnapshot = {\n generation: relayTransportSnapshot.generation + 1,\n reason,\n status,\n };\n for (const listener of relayTransportListeners) {\n listener();\n }\n}\n\n/**\n * Publish the latest Relay HTTP operation activity snapshot.\n */\nfunction emitRelayOperationActivityChange(): void {\n relayOperationActivitySnapshot = {\n generation: relayOperationActivitySnapshot.generation + 1,\n pendingCount: relayPendingOperations.size,\n pendingOperations: [...relayPendingOperations.values()],\n };\n if (relayOperationActivityNotifyScheduled) {\n return;\n }\n relayOperationActivityNotifyScheduled = true;\n queueMicrotask(() => {\n relayOperationActivityNotifyScheduled = false;\n for (const listener of relayOperationActivityListeners) {\n listener();\n }\n });\n}\n\n/**\n * Clear pending Relay HTTP operations after environment reconfiguration.\n */\nfunction resetRelayOperationActivity(): void {\n if (relayPendingOperations.size === 0) {\n return;\n }\n relayPendingOperations.clear();\n emitRelayOperationActivityChange();\n}\n\n/**\n * Normalize Relay operation kind values from runtime requests.\n */\nfunction resolveRelayOperationKind(operationKind: unknown): RelayOperationKind {\n if (operationKind === 'query' || operationKind === 'mutation') {\n return operationKind;\n }\n return 'unknown';\n}\n\n/**\n * Track a Relay HTTP operation until its returned disposer is called.\n */\nfunction startRelayOperationActivity(request: {\n name?: string | null;\n operationKind?: unknown;\n}): () => void {\n const id = relayOperationActivityId;\n relayOperationActivityId += 1;\n relayPendingOperations.set(id, {\n id,\n kind: resolveRelayOperationKind(request.operationKind),\n name: request.name ?? 'AnonymousGraphQLOperation',\n startedAt: Date.now(),\n });\n emitRelayOperationActivityChange();\n\n let isSettled = false;\n return () => {\n if (isSettled) {\n return;\n }\n isSettled = true;\n if (!relayPendingOperations.delete(id)) {\n return;\n }\n emitRelayOperationActivityChange();\n };\n}\n\n/**\n * Dispose the active websocket client and ignore shutdown failures.\n */\nfunction disposeWsClient(): void {\n if (wsClient == null) {\n return;\n }\n try {\n wsClient.dispose();\n } catch {\n // ignore errors during dispose\n }\n wsClient = undefined;\n}\n\n/**\n * Return the current Relay transport state used by subscription hooks.\n */\nexport function getRelayTransportSnapshot(): RelayTransportSnapshot {\n return relayTransportSnapshot;\n}\n\n/**\n * Subscribe to Relay transport changes.\n */\nexport function subscribeRelayTransport(\n listener: RelayTransportListener,\n): () => void {\n relayTransportListeners.add(listener);\n return () => {\n relayTransportListeners.delete(listener);\n };\n}\n\n/**\n * Return the current Relay HTTP operation activity snapshot.\n */\nexport function getRelayOperationActivitySnapshot(): RelayOperationActivitySnapshot {\n return relayOperationActivitySnapshot;\n}\n\n/**\n * Subscribe to Relay HTTP operation activity changes.\n */\nexport function subscribeRelayOperationActivity(\n listener: RelayOperationActivityListener,\n): () => void {\n relayOperationActivityListeners.add(listener);\n return () => {\n relayOperationActivityListeners.delete(listener);\n };\n}\n\n/**\n * Force the websocket transport to reconnect and notify mounted subscriptions.\n */\nexport function reconnectRelayWebSocket(\n options: RelayReconnectOptions = {},\n): void {\n disposeWsClient();\n emitRelayTransportChange(\n 'reconnecting',\n options.reason ?? 'manual_reconnect',\n );\n}\n\n/**\n * Refresh the active websocket authentication without recreating subscriptions.\n */\nexport async function refreshRelayWebSocketAuthentication(\n options: RelayAuthRefreshOptions = {},\n): Promise<void> {\n const client = wsClient;\n if (!client?.hasActiveConnection()) {\n return;\n }\n\n const refreshed = await client.refreshAuthentication();\n if (!refreshed) {\n reconnectRelayWebSocket({\n reason: options.reason ?? 'auth_refresh_fallback',\n });\n }\n}\n\nexport interface RelayEnvironmentConfiguration {\n httpUrl?: string;\n wsUrl?: string;\n logEvents?: boolean;\n getDataId?: (fieldValue: unknown, typeName: string) => string | null;\n getAuthHeaders?: () =>\n Record<string, string> | Promise<Record<string, string>>;\n}\n\n/**\n * Configure the endpoints and logging behavior used by the shared Relay environment.\n */\nexport function configureRelayEnvironment(\n options: RelayEnvironmentConfiguration = {},\n): void {\n const {\n httpUrl,\n wsUrl,\n logEvents,\n getDataId: nextGetDataId,\n getAuthHeaders: nextGetAuthHeaders,\n } = options;\n\n if (typeof httpUrl === 'string' && httpUrl !== '') {\n graphqlHttpEndpoint = httpUrl;\n }\n\n if (typeof wsUrl === 'string' && wsUrl !== '') {\n graphqlWsEndpoint = wsUrl;\n }\n\n if (logEvents != null) {\n if (logEvents) {\n relayFieldLogger = (event) => {\n // eslint-disable-next-line no-console\n console.log('relayFieldLogger: ', event);\n };\n } else {\n relayFieldLogger = noopRelayFieldLogger;\n }\n }\n\n customDataIdResolver = nextGetDataId;\n getAuthHeaders = nextGetAuthHeaders;\n\n disposeWsClient();\n environment = undefined;\n resetRelayOperationActivity();\n emitRelayTransportChange('configured', 'configure');\n}\n\n/**\n * Resolve the websocket endpoint into an absolute URL suitable for graphql-ws.\n */\nfunction resolveWebsocketUrl(): string {\n const endpoint = graphqlWsEndpoint;\n\n if (endpoint.startsWith('ws')) {\n return endpoint;\n }\n\n if (endpoint.startsWith('http')) {\n return endpoint.replace(/^http/, 'ws');\n }\n\n if (endpoint.startsWith('/')) {\n if (typeof window === 'undefined') {\n return endpoint;\n }\n let protocol = 'ws:';\n if (window.location.protocol === 'https:') {\n protocol = 'wss:';\n }\n return `${protocol}//${window.location.host}${endpoint}`;\n }\n\n return endpoint;\n}\n\n/** Debug log helper (no-op en production) */\nfunction debugLog(...args: unknown[]): void {\n if (isDevEnv()) {\n // eslint-disable-next-line no-console\n console.log('[RelayNetwork]', ...args);\n }\n}\n\n/** Resolve authentication headers for Relay HTTP and websocket transports. */\nasync function resolveAuthHeaders(): Promise<Record<string, string>> {\n if (getAuthHeaders == null) {\n return {};\n }\n return getAuthHeaders();\n}\n\nclass RelayWebSocketClient {\n private socket: WebSocket | null = null;\n\n private connectPromise: Promise<void> | null = null;\n\n private disposed = false;\n\n private acknowledged = false;\n\n private retryCount = 0;\n\n private nextId = 1;\n\n private keepAliveTimer: ReturnType<typeof setInterval> | null = null;\n\n private readonly subscriptions = new Map<string, ActiveSubscription>();\n\n private pendingAuthUpdate: {\n resolve: (value: boolean) => void;\n timeout: ReturnType<typeof setTimeout>;\n } | null = null;\n\n public constructor(private readonly url: string) {}\n\n public hasActiveConnection(): boolean {\n return this.socket?.readyState === WebSocket.OPEN && this.acknowledged;\n }\n\n public dispose(): void {\n this.disposed = true;\n this.resolvePendingAuthUpdate(false);\n this.stopKeepAlive();\n const { socket } = this;\n this.socket = null;\n this.connectPromise = null;\n this.acknowledged = false;\n if (socket != null && socket.readyState !== WebSocket.CLOSED) {\n socket.close(1000, 'Normal Closure');\n }\n }\n\n public subscribe(\n payload: ActiveSubscription['payload'],\n sink: SubscriptionSink,\n ): () => void {\n const id = String(this.nextId);\n this.nextId += 1;\n this.subscriptions.set(id, { payload, sink });\n this.connectAndSubscribe(id).catch((error: unknown) => {\n debugLog('subscription websocket connect failed', error);\n this.scheduleReconnect();\n });\n\n return () => {\n this.unsubscribe(id);\n };\n }\n\n public async refreshAuthentication(): Promise<boolean> {\n if (!this.hasActiveConnection()) {\n return true;\n }\n const { socket } = this;\n if (socket == null) {\n return true;\n }\n if (this.pendingAuthUpdate != null) {\n return false;\n }\n\n let payload: Record<string, string>;\n try {\n payload = await resolveAuthHeaders();\n } catch {\n return false;\n }\n if (Object.keys(payload).length === 0) {\n return false;\n }\n\n return new Promise<boolean>((resolve) => {\n const timeout = setTimeout(() => {\n this.pendingAuthUpdate = null;\n resolve(false);\n }, AUTH_UPDATE_TIMEOUT_MS);\n this.pendingAuthUpdate = { resolve, timeout };\n this.send({\n type: 'connection_auth_update',\n payload,\n });\n });\n }\n\n private async connectAndSubscribe(id: string): Promise<void> {\n const wasConnected = this.hasActiveConnection();\n await this.ensureConnected();\n if (!wasConnected) {\n return;\n }\n const subscription = this.subscriptions.get(id);\n if (subscription == null) {\n return;\n }\n this.send({\n id,\n type: 'subscribe',\n payload: subscription.payload,\n });\n }\n\n private async ensureConnected(): Promise<void> {\n if (this.hasActiveConnection()) {\n return;\n }\n if (this.connectPromise != null) {\n await this.connectPromise;\n return;\n }\n\n this.connectPromise = this.openSocket();\n try {\n await this.connectPromise;\n } finally {\n this.connectPromise = null;\n }\n }\n\n private async openSocket(): Promise<void> {\n if (this.disposed) {\n throw new Error('WebSocket client is disposed');\n }\n\n await new Promise<void>((resolve, reject) => {\n let settled = false;\n const resolveConnected = (): void => {\n if (settled) {\n return;\n }\n settled = true;\n resolve();\n };\n const rejectConnection = (error: unknown): void => {\n if (settled) {\n return;\n }\n settled = true;\n reject(error);\n };\n const socket = new WebSocket(this.url, GRAPHQL_TRANSPORT_WS_PROTOCOL);\n this.socket = socket;\n this.acknowledged = false;\n\n socket.onopen = () => {\n resolveAuthHeaders()\n .catch(() => {\n return {};\n })\n .then((payload) => {\n if (socket.readyState !== WebSocket.OPEN) {\n return;\n }\n if (Object.keys(payload).length > 0) {\n this.send({ type: 'connection_init', payload });\n return;\n }\n this.send({ type: 'connection_init' });\n })\n .catch((error: unknown) => {\n rejectConnection(error);\n });\n };\n\n socket.onerror = () => {\n rejectConnection(new Error('GraphQL subscription websocket error'));\n };\n\n socket.onmessage = (event) => {\n this.handleMessage(event.data, resolveConnected, rejectConnection);\n };\n\n socket.onclose = () => {\n rejectConnection(new Error('GraphQL subscription websocket closed'));\n this.handleClose();\n };\n });\n }\n\n private handleMessage(\n data: unknown,\n connected: () => void,\n rejected: (error: unknown) => void,\n ): void {\n let message: GraphqlWsMessage;\n try {\n message = JSON.parse(String(data)) as GraphqlWsMessage;\n } catch {\n rejected(new Error('Invalid GraphQL websocket message'));\n this.socket?.close(4400, 'Invalid websocket message');\n return;\n }\n\n switch (message.type) {\n case 'connection_ack':\n this.acknowledged = true;\n this.retryCount = 0;\n this.startKeepAlive();\n connected();\n this.resubscribeActiveOperations();\n return;\n case 'connection_auth_update_ack':\n this.resolvePendingAuthUpdate(true);\n return;\n case 'next':\n this.subscriptions.get(message.id)?.sink.next(message.payload);\n return;\n case 'error':\n if (message.id != null) {\n this.failSubscription(message.id, message.payload);\n } else {\n this.resolvePendingAuthUpdate(false);\n }\n return;\n case 'complete':\n this.completeSubscription(message.id);\n return;\n case 'ping':\n this.send({ type: 'pong', payload: message.payload });\n return;\n case 'pong':\n return;\n default:\n rejected(new Error('Unsupported GraphQL websocket message'));\n this.socket?.close(4400, 'Unsupported websocket message');\n }\n }\n\n private handleClose(): void {\n this.acknowledged = false;\n this.socket = null;\n this.connectPromise = null;\n this.stopKeepAlive();\n this.resolvePendingAuthUpdate(false);\n if (!this.disposed && this.subscriptions.size > 0) {\n this.scheduleReconnect();\n }\n }\n\n private scheduleReconnect(): void {\n if (this.retryCount >= WS_MAX_RETRY_ATTEMPTS) {\n const error = new Error('GraphQL subscription websocket retry exhausted');\n for (const id of [...this.subscriptions.keys()]) {\n this.failSubscription(id, error);\n }\n return;\n }\n const delay =\n Math.min(8_000, WS_BASE_RETRY_DELAY_MS * 2 ** this.retryCount) +\n Math.random() * 200;\n this.retryCount += 1;\n setTimeout(() => {\n if (this.disposed || this.subscriptions.size === 0) {\n return;\n }\n this.ensureConnected().catch((error: unknown) => {\n this.scheduleReconnect();\n debugLog('subscription websocket reconnect failed', error);\n });\n }, delay);\n }\n\n private resubscribeActiveOperations(): void {\n for (const [id, subscription] of this.subscriptions) {\n this.send({\n id,\n type: 'subscribe',\n payload: subscription.payload,\n });\n }\n }\n\n private unsubscribe(id: string): void {\n const hadSubscription = this.subscriptions.delete(id);\n if (hadSubscription && this.socket?.readyState === WebSocket.OPEN) {\n this.send({ id, type: 'complete' });\n }\n }\n\n private failSubscription(id: string, error: unknown): void {\n const subscription = this.subscriptions.get(id);\n if (subscription == null) {\n return;\n }\n this.subscriptions.delete(id);\n subscription.sink.error(error);\n }\n\n private completeSubscription(id: string): void {\n const subscription = this.subscriptions.get(id);\n if (subscription == null) {\n return;\n }\n this.subscriptions.delete(id);\n subscription.sink.complete();\n }\n\n private startKeepAlive(): void {\n this.stopKeepAlive();\n this.keepAliveTimer = setInterval(() => {\n if (this.socket?.readyState === WebSocket.OPEN) {\n this.send({ type: 'ping' });\n }\n }, WS_KEEP_ALIVE_MS);\n }\n\n private stopKeepAlive(): void {\n if (this.keepAliveTimer != null) {\n clearInterval(this.keepAliveTimer);\n this.keepAliveTimer = null;\n }\n }\n\n private resolvePendingAuthUpdate(value: boolean): void {\n const pending = this.pendingAuthUpdate;\n if (pending == null) {\n return;\n }\n clearTimeout(pending.timeout);\n this.pendingAuthUpdate = null;\n pending.resolve(value);\n }\n\n private send(message: GraphqlWsPayload): void {\n const { socket } = this;\n if (socket?.readyState !== WebSocket.OPEN) {\n return;\n }\n socket.send(JSON.stringify(message));\n }\n}\n\n/**\n * Build or get a singleton graphql-transport-ws client with auth refresh support.\n */\nfunction getWsClient(): RelayWebSocketClient {\n if (wsClient != null) {\n return wsClient;\n }\n if (typeof window === 'undefined') {\n throw new Error(\n 'GraphQL subscriptions unavailable in non-browser environment',\n );\n }\n\n const url = resolveWebsocketUrl();\n wsClient = new RelayWebSocketClient(url);\n\n return wsClient;\n}\n\n/**\n * Get organization slug from current window location\n */\n// export function getOrganizationSlug(): string | null {\n// const { pathname } = window.location;\n// const slug = pathname.split('/')[1];\n// if (slug == null) {\n// return null;\n// }\n\n// return slug;\n// }\n\n// -------------------------\n// Upload detection helpers\n// -------------------------\n/** Test if a value is an uploadable (File/Blob) */\nfunction isUploadable(value: unknown): value is File | Blob {\n return (\n (typeof File !== 'undefined' && value instanceof File) ||\n (typeof Blob !== 'undefined' && value instanceof Blob)\n );\n}\n\ninterface FileRef {\n path: string; // JSON pointer-like (e.g. variables.input.file)\n file: File | Blob;\n}\n\n/** Recursively clone a structure replacing files with null and collecting them */\nfunction collectFiles(value: unknown, path: string, acc: FileRef[]): unknown {\n if (isUploadable(value)) {\n acc.push({ path, file: value });\n return null; // placeholder per multipart spec\n }\n if (Array.isArray(value)) {\n return value.map((v, i) => {\n return collectFiles(v, `${path}.${i}`, acc);\n });\n }\n if (value != null && typeof value === 'object') {\n const out: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(value as Record<string, unknown>)) {\n out[k] = collectFiles(v, `${path}.${k}`, acc);\n }\n return out;\n }\n return value; // primitives unchanged\n}\n\n/** Build GraphQL multipart form-data payload */\nfunction buildFormData(\n query: string,\n variables: Record<string, unknown>,\n): FormData {\n const files: FileRef[] = [];\n // Deep clone variables while replacing files with null\n const clonedVars = collectFiles(variables, 'variables', files) as Record<\n string,\n unknown\n >;\n\n const form = new FormData();\n const operations = { query, variables: clonedVars };\n form.append('operations', JSON.stringify(operations));\n\n const map: Record<string, string[]> = {};\n files.forEach((ref, idx) => {\n map[idx] = [ref.path];\n });\n form.append('map', JSON.stringify(map));\n files.forEach((ref, idx) => {\n form.append(String(idx), ref.file);\n });\n return form;\n}\n\n// -------------------------\n// Retry / timeout helpers\n// -------------------------\ninterface RetryOptions {\n maxAttempts: number; // total attempts including initial\n baseDelayMs: number;\n maxDelayMs: number;\n fetchTimeoutMs: number;\n}\n\nconst RETRY_OPTIONS: RetryOptions = {\n maxAttempts: 3,\n baseDelayMs: 300,\n maxDelayMs: 4000,\n fetchTimeoutMs: 600_000, // 10 minutes (parité avec ancien middleware)\n};\n\n/** Sleep helper with Promise */\nasync function sleep(ms: number): Promise<void> {\n await new Promise<void>((res) => {\n setTimeout(() => {\n res();\n }, ms);\n });\n}\n\n/** Exponential backoff with jitter */\nfunction calcBackoff(attempt: number, opts: RetryOptions): number {\n const exp = Math.min(opts.maxDelayMs, opts.baseDelayMs * 2 ** attempt);\n return exp + Math.random() * 0.2 * exp; // jitter 0-20%\n}\n\n/** Determine if an HTTP status is retryable */\nfunction isRetryableStatus(status: number): boolean {\n return status === 408 || status === 429 || (status >= 500 && status < 600);\n}\n\n/** Determine if an error should be treated as transient network issue */\nfunction isNetworkError(err: unknown): boolean {\n return (\n err instanceof TypeError ||\n (err instanceof Error && err.name === 'AbortError')\n );\n}\n\n// -------------------------\n// fetchFn implementation\n// -------------------------\ninterface GraphQLResponseErrorItem {\n [key: string]: unknown;\n message: string;\n path?: readonly unknown[];\n}\n\ninterface GraphQLResponseShape<T = unknown> {\n data?: T;\n errors?: GraphQLResponseErrorItem[];\n extensions?: Record<string, unknown>;\n}\n\nexport class GraphQLResponseError extends Error {\n public constructor(\n public readonly errors: readonly GraphQLResponseErrorItem[],\n public readonly response: GraphQLResponseShape,\n ) {\n super(errors[0]?.message ?? 'GraphQL response error');\n this.name = 'GraphQLResponseError';\n }\n}\n\n/** Determine whether a GraphQL payload includes non-null top-level data. */\nfunction hasUsableTopLevelData(data: unknown): boolean {\n if (data == null) {\n return false;\n }\n if (typeof data !== 'object') {\n return true;\n }\n return Object.values(data as Record<string, unknown>).some((value) => {\n return value != null;\n });\n}\n\n/** Determine whether all errors are child-field errors under top-level null data. */\nfunction hasOnlyErrorsBelowNullTopLevelFields(\n response: GraphQLResponseShape,\n): boolean {\n const { data, errors } = response;\n if (\n data == null ||\n typeof data !== 'object' ||\n !Array.isArray(errors) ||\n errors.length === 0\n ) {\n return false;\n }\n\n const dataRecord = data as Record<string, unknown>;\n return errors.every((error) => {\n const [topLevelField, ...childPath] = error.path ?? [];\n if (typeof topLevelField !== 'string' || childPath.length === 0) {\n return false;\n }\n return (\n Object.prototype.hasOwnProperty.call(dataRecord, topLevelField) &&\n dataRecord[topLevelField] == null\n );\n });\n}\n\n/** Determine whether GraphQL errors should be surfaced as a thrown response error. */\nfunction shouldThrowGraphQLResponseError(\n response: GraphQLResponseShape,\n): boolean {\n return (\n Array.isArray(response.errors) &&\n response.errors.length > 0 &&\n !hasUsableTopLevelData(response.data) &&\n !hasOnlyErrorsBelowNullTopLevelFields(response)\n );\n}\n\n/** Fetch GraphQL (with retry + upload) */\nasync function fetchFn(\n request: {\n name?: string | null;\n operationKind?: unknown;\n text: string | null | undefined;\n },\n variables: Record<string, unknown>,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n _cacheConfig: unknown,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n _uploadables: unknown,\n): Promise<GraphQLResponseShape> {\n const queryText: string | null | undefined = request.text; // no persisted queries here (yet)\n if (queryText == null) {\n throw new Error('Missing GraphQL query text');\n }\n const safeQueryText: string = queryText; // narrowed non-null\n const stopRelayOperationActivity = startRelayOperationActivity(request);\n\n /** Execute one network attempt */\n async function execOnce(attempt: number): Promise<GraphQLResponseShape> {\n const controller = new AbortController();\n const timeout = setTimeout(() => {\n controller.abort();\n }, RETRY_OPTIONS.fetchTimeoutMs);\n try {\n let body: BodyInit;\n const headers: Record<string, string> = {};\n if (getAuthHeaders != null) {\n try {\n Object.assign(headers, await getAuthHeaders());\n } catch {\n // ignore auth header failures\n }\n }\n const hasFiles = ((): boolean => {\n try {\n const stack: unknown[] = [variables];\n while (stack.length > 0) {\n const v = stack.pop();\n if (isUploadable(v)) {\n return true;\n }\n if (Array.isArray(v)) {\n stack.push(...v);\n } else if (v != null && typeof v === 'object') {\n stack.push(...Object.values(v as Record<string, unknown>));\n }\n }\n } catch {\n // ignore traversal errors\n }\n return false;\n })();\n\n if (hasFiles) {\n body = buildFormData(safeQueryText, variables);\n headers[GRAPHQL_CSRF_PREFLIGHT_HEADER] =\n GRAPHQL_CSRF_PREFLIGHT_HEADER_VALUE;\n } else {\n headers['Content-Type'] = 'application/json';\n body = JSON.stringify({ query: safeQueryText, variables });\n }\n\n const response = await fetch(graphqlHttpEndpoint, {\n method: 'POST',\n body,\n headers,\n credentials: 'include',\n signal: controller.signal,\n });\n\n if (!response.ok) {\n if (\n attempt < RETRY_OPTIONS.maxAttempts - 1 &&\n isRetryableStatus(response.status)\n ) {\n throw new Error(`Retryable HTTP status ${response.status}`);\n }\n const text = await response.text().catch(() => {\n return '';\n });\n throw new Error(`GraphQL HTTP error ${response.status}: ${text}`);\n }\n\n const json: GraphQLResponseShape = await response.json();\n if (Array.isArray(json.errors) && json.errors.length > 0) {\n debugLog('GraphQL errors', json.errors);\n }\n if (shouldThrowGraphQLResponseError(json)) {\n throw new GraphQLResponseError(json.errors ?? [], json);\n }\n return json;\n } finally {\n clearTimeout(timeout);\n }\n }\n\n try {\n for (let attempt = 0; attempt < RETRY_OPTIONS.maxAttempts; attempt += 1) {\n try {\n return await execOnce(attempt);\n } catch (err) {\n const last = attempt === RETRY_OPTIONS.maxAttempts - 1;\n const retryable =\n isNetworkError(err) ||\n (err instanceof Error &&\n err.message.includes('Retryable HTTP status'));\n if (!retryable || last) {\n debugLog('GraphQL fetch error', err);\n throw err;\n }\n const delay = calcBackoff(attempt, RETRY_OPTIONS);\n await sleep(delay);\n }\n }\n throw new Error('Exhausted retries without returning a result');\n } finally {\n stopRelayOperationActivity();\n }\n}\n\n// -------------------------\n// subscribeFn implementation (wrap existing logic in Relay Observable)\n// -------------------------\n/** Subscription function bridging graphql-ws client to Relay */\nfunction subscribeFn(\n operation: { text: string | null | undefined; name: string },\n variables: Record<string, unknown>,\n): Observable<unknown> {\n debugLog('subscription:start', operation.name, variables);\n return Observable.create<unknown>((sink) => {\n const query = operation.text;\n if (query == null || query === '') {\n sink.error(new Error('Subscription operation text is empty'));\n return () => {\n // noop\n };\n }\n const client = getWsClient();\n const dispose = client.subscribe(\n { query, variables, operationName: operation.name },\n {\n next: (data) => {\n sink.next(data);\n },\n error: (err) => {\n let errorObj: Error;\n if (err instanceof Error) {\n errorObj = err;\n } else {\n errorObj = new Error('Subscription error');\n }\n sink.error(errorObj);\n },\n complete: () => {\n sink.complete();\n },\n },\n );\n return () => {\n dispose();\n };\n });\n}\n\n/**\n * Create native Relay network layer (fetch + subscribe)\n */\nexport function getNetwork(): ReturnType<typeof Network.create> {\n return Network.create(\n fetchFn as FetchFunction,\n subscribeFn as SubscribeFunction,\n );\n}\n\n/**\n * Get anonymous relay environment\n */\nexport function getEnvironment(): Environment {\n environment ??= new Environment({\n getDataID: getDataId,\n relayFieldLogger,\n network: getNetwork(),\n store: new Store(new RecordSource()),\n });\n\n return environment;\n}\n\n/**\n * Reset the Relay store by creating a new empty source\n */\nexport function resetRelayStore(): void {\n const environment = getEnvironment();\n\n // Create a new store with an empty source\n const source = new RecordSource();\n\n // Replace the data in the store with our empty source\n environment.getStore().publish(source);\n\n // Notify subscribers that the data has changed\n environment.getStore().notify();\n}\n\nexport const __test = {\n RelayWebSocketClient,\n buildFormData,\n calcBackoff,\n collectFiles,\n fetchFn,\n getDataId,\n hasUsableTopLevelData,\n isNetworkError,\n isRetryableStatus,\n isUploadable,\n shouldThrowGraphQLResponseError,\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"environment.js","names":[],"sources":["../../src/environment.ts"],"sourcesContent":["import {\n Environment,\n Network,\n Observable,\n RecordSource,\n Store,\n type FetchFunction,\n type SubscribeFunction,\n type RelayFieldLogger,\n} from 'relay-runtime';\nimport { isDevEnv } from './envHelpers.js';\n\nlet graphqlHttpEndpoint = '/api/graphql';\nlet graphqlWsEndpoint = '/api/ws';\n\n// (anonymousEnvironment reserved if needed later for public access / logout scenarios)\n// Removed until actually required to avoid lint errors.\n// let anonymousEnvironment: Environment | undefined;\nlet environment: Environment | undefined;\nlet wsClient: RelayWebSocketClient | undefined;\nlet environmentGeneration = 0;\nconst activeHttpControllers = new Set<AbortController>();\nlet getAuthHeaders:\n (() => Record<string, string> | Promise<Record<string, string>>) | undefined;\nconst defaultGraphqlFetch: typeof fetch = async (input, init) => {\n return globalThis.fetch(input, init);\n};\nlet graphqlFetch: typeof fetch = defaultGraphqlFetch;\nlet customDataIdResolver:\n ((fieldValue: unknown, typeName: string) => string | null) | undefined;\n\nconst GRAPHQL_CSRF_PREFLIGHT_HEADER = 'require-preflight';\nconst GRAPHQL_CSRF_PREFLIGHT_HEADER_VALUE = 'true';\n\nexport type RelayTransportStatus = 'idle' | 'configured' | 'reconnecting';\n\nexport interface RelayTransportSnapshot {\n generation: number;\n reason: string | null;\n status: RelayTransportStatus;\n}\n\nexport type RelayOperationKind = 'mutation' | 'query' | 'unknown';\n\nexport type RelayPendingOperation = {\n id: number;\n kind: RelayOperationKind;\n name: string;\n startedAt: number;\n};\n\nexport interface RelayOperationActivitySnapshot {\n generation: number;\n pendingCount: number;\n pendingOperations: readonly RelayPendingOperation[];\n}\n\nexport interface RelayReconnectOptions {\n reason?: string;\n}\n\nexport interface RelayAuthRefreshOptions {\n reason?: string;\n}\n\ntype RelayTransportListener = () => void;\ntype RelayOperationActivityListener = () => void;\n\ntype GraphqlWsPayload = Record<string, unknown>;\n\ntype GraphqlWsMessage =\n | { type: 'connection_ack'; payload?: unknown }\n | { type: 'connection_auth_update_ack'; payload?: unknown }\n | { id: string; type: 'next'; payload: unknown }\n | { id?: string; type: 'error'; payload: unknown }\n | { id: string; type: 'complete' }\n | { type: 'ping'; payload?: unknown }\n | { type: 'pong'; payload?: unknown };\n\ntype GraphqlWsMessageDecodeResult =\n | { readonly ok: true; readonly value: GraphqlWsMessage }\n | {\n readonly ok: false;\n readonly reason: 'invalid' | 'unsupported';\n };\n\nconst isUnknownRecord = (\n value: unknown,\n): value is Readonly<Record<string, unknown>> => {\n return value != null && typeof value === 'object' && !Array.isArray(value);\n};\n\nconst decodeGraphqlWsMessage = (\n value: unknown,\n): GraphqlWsMessageDecodeResult => {\n if (!isUnknownRecord(value) || typeof value.type !== 'string') {\n return { ok: false, reason: 'invalid' };\n }\n const { payload } = value;\n switch (value.type) {\n case 'connection_ack':\n case 'connection_auth_update_ack':\n case 'ping':\n case 'pong':\n return { ok: true, value: { type: value.type, payload } };\n case 'next':\n if (typeof value.id !== 'string') {\n return { ok: false, reason: 'invalid' };\n }\n return { ok: true, value: { id: value.id, type: value.type, payload } };\n case 'error':\n if (value.id != null && typeof value.id !== 'string') {\n return { ok: false, reason: 'invalid' };\n }\n if (value.id == null) {\n return { ok: true, value: { type: value.type, payload } };\n }\n return {\n ok: true,\n value: { id: value.id, type: value.type, payload },\n };\n case 'complete':\n if (typeof value.id !== 'string') {\n return { ok: false, reason: 'invalid' };\n }\n return { ok: true, value: { id: value.id, type: value.type } };\n default:\n return { ok: false, reason: 'unsupported' };\n }\n};\n\ntype SubscriptionSink = {\n next: (value: unknown) => void;\n error: (error: unknown) => void;\n complete: () => void;\n};\n\ntype ActiveSubscription = {\n payload: {\n query: string;\n variables: Record<string, unknown>;\n operationName: string;\n };\n sink: SubscriptionSink;\n};\n\nconst GRAPHQL_TRANSPORT_WS_PROTOCOL = 'graphql-transport-ws';\nconst AUTH_UPDATE_TIMEOUT_MS = 5_000;\nconst WS_KEEP_ALIVE_MS = 10_000;\nconst WS_MAX_RETRY_ATTEMPTS = 10;\nconst WS_BASE_RETRY_DELAY_MS = 500;\nconst ENVIRONMENT_ROTATED_ERROR =\n 'Relay operation cancelled after environment rotation';\n\nlet relayTransportSnapshot: RelayTransportSnapshot = {\n generation: 0,\n reason: null,\n status: 'idle',\n};\nconst relayTransportListeners = new Set<RelayTransportListener>();\n\nlet relayOperationActivitySnapshot: RelayOperationActivitySnapshot = {\n generation: 0,\n pendingCount: 0,\n pendingOperations: [],\n};\nlet relayOperationActivityId = 0;\nconst relayPendingOperations = new Map<number, RelayPendingOperation>();\nconst relayOperationActivityListeners =\n new Set<RelayOperationActivityListener>();\nlet relayOperationActivityNotifyScheduled = false;\n\n/**\n * No-op Relay field logger used to satisfy @required(action: LOG).\n */\nfunction noopRelayFieldLogger(): void {}\n\nlet relayFieldLogger: RelayFieldLogger = noopRelayFieldLogger;\n\nif (isDevEnv()) {\n relayFieldLogger = (event) => {\n // eslint-disable-next-line no-console\n console.log('relayFieldLogger: ', event);\n };\n}\n\nconst defaultGetDataId: (\n fieldValue: unknown,\n typeName: string,\n) => string | null = (fieldValue) => {\n if (fieldValue == null || typeof fieldValue !== 'object') {\n return null;\n }\n const { id } = fieldValue as { id?: unknown };\n if (typeof id !== 'string' || id.trim() === '') {\n return null;\n }\n return id;\n};\n\nconst getDataId = (fieldValue: unknown, typeName: string): string | null => {\n const customId = customDataIdResolver?.(fieldValue, typeName);\n if (customId != null) {\n return customId;\n }\n return defaultGetDataId(fieldValue, typeName);\n};\n\n/**\n * Notify subscribers that the Relay transport state changed.\n */\nfunction emitRelayTransportChange(\n status: RelayTransportStatus,\n reason: string | null,\n): void {\n relayTransportSnapshot = {\n generation: relayTransportSnapshot.generation + 1,\n reason,\n status,\n };\n for (const listener of relayTransportListeners) {\n listener();\n }\n}\n\n/**\n * Publish the latest Relay HTTP operation activity snapshot.\n */\nfunction emitRelayOperationActivityChange(): void {\n relayOperationActivitySnapshot = {\n generation: relayOperationActivitySnapshot.generation + 1,\n pendingCount: relayPendingOperations.size,\n pendingOperations: [...relayPendingOperations.values()],\n };\n if (relayOperationActivityNotifyScheduled) {\n return;\n }\n relayOperationActivityNotifyScheduled = true;\n queueMicrotask(() => {\n relayOperationActivityNotifyScheduled = false;\n for (const listener of relayOperationActivityListeners) {\n listener();\n }\n });\n}\n\n/**\n * Clear pending Relay HTTP operations after environment reconfiguration.\n */\nfunction resetRelayOperationActivity(): void {\n if (relayPendingOperations.size === 0) {\n return;\n }\n relayPendingOperations.clear();\n emitRelayOperationActivityChange();\n}\n\n/**\n * Normalize Relay operation kind values from runtime requests.\n */\nfunction resolveRelayOperationKind(operationKind: unknown): RelayOperationKind {\n if (operationKind === 'query' || operationKind === 'mutation') {\n return operationKind;\n }\n return 'unknown';\n}\n\n/**\n * Track a Relay HTTP operation until its returned disposer is called.\n */\nfunction startRelayOperationActivity(request: {\n name?: string | null;\n operationKind?: unknown;\n}): () => void {\n const id = relayOperationActivityId;\n relayOperationActivityId += 1;\n relayPendingOperations.set(id, {\n id,\n kind: resolveRelayOperationKind(request.operationKind),\n name: request.name ?? 'AnonymousGraphQLOperation',\n startedAt: Date.now(),\n });\n emitRelayOperationActivityChange();\n\n let isSettled = false;\n return () => {\n if (isSettled) {\n return;\n }\n isSettled = true;\n if (!relayPendingOperations.delete(id)) {\n return;\n }\n emitRelayOperationActivityChange();\n };\n}\n\n/**\n * Dispose the active websocket client and ignore shutdown failures.\n */\nfunction disposeWsClient(): void {\n if (wsClient == null) {\n return;\n }\n try {\n wsClient.dispose();\n } catch {\n // ignore errors during dispose\n }\n wsClient = undefined;\n}\n\n/** End every subscription owned by an environment that is being replaced. */\nfunction terminateWsClient(): void {\n if (wsClient == null) {\n return;\n }\n try {\n wsClient.terminate();\n } catch {\n // ignore errors during termination\n }\n wsClient = undefined;\n}\n\n/** Abort every HTTP operation owned by the current Relay environment. */\nfunction abortActiveHttpOperations(): void {\n for (const controller of activeHttpControllers) {\n controller.abort();\n }\n activeHttpControllers.clear();\n}\n\n/** Remove all records from an environment while notifying its active selectors. */\nfunction clearEnvironmentStore(currentEnvironment: Environment): void {\n const store = currentEnvironment.getStore();\n const source = store.getSource();\n const deletedRecords = new RecordSource();\n\n for (const dataId of source.getRecordIDs()) {\n deletedRecords.delete(dataId);\n }\n try {\n if (deletedRecords.size() > 0) {\n store.publish(deletedRecords);\n store.notify();\n }\n } finally {\n if (source instanceof RecordSource) {\n source.clear();\n }\n }\n}\n\n/** Replace the shared environment and terminate work owned by its generation. */\nfunction rotateRelayEnvironment(\n status: RelayTransportStatus,\n reason: string,\n): void {\n const previousEnvironment = environment;\n environment = undefined;\n environmentGeneration += 1;\n abortActiveHttpOperations();\n terminateWsClient();\n try {\n if (previousEnvironment != null) {\n clearEnvironmentStore(previousEnvironment);\n }\n } finally {\n resetRelayOperationActivity();\n emitRelayTransportChange(status, reason);\n }\n}\n\n/**\n * Return the current Relay transport state used by subscription hooks.\n */\nexport function getRelayTransportSnapshot(): RelayTransportSnapshot {\n return relayTransportSnapshot;\n}\n\n/**\n * Subscribe to Relay transport changes.\n */\nexport function subscribeRelayTransport(\n listener: RelayTransportListener,\n): () => void {\n relayTransportListeners.add(listener);\n return () => {\n relayTransportListeners.delete(listener);\n };\n}\n\n/**\n * Return the current Relay HTTP operation activity snapshot.\n */\nexport function getRelayOperationActivitySnapshot(): RelayOperationActivitySnapshot {\n return relayOperationActivitySnapshot;\n}\n\n/**\n * Subscribe to Relay HTTP operation activity changes.\n */\nexport function subscribeRelayOperationActivity(\n listener: RelayOperationActivityListener,\n): () => void {\n relayOperationActivityListeners.add(listener);\n return () => {\n relayOperationActivityListeners.delete(listener);\n };\n}\n\n/**\n * Force the websocket transport to reconnect and notify mounted subscriptions.\n */\nexport function reconnectRelayWebSocket(\n options: RelayReconnectOptions = {},\n): void {\n disposeWsClient();\n emitRelayTransportChange(\n 'reconnecting',\n options.reason ?? 'manual_reconnect',\n );\n}\n\n/**\n * Refresh the active websocket authentication without recreating subscriptions.\n */\nexport async function refreshRelayWebSocketAuthentication(\n options: RelayAuthRefreshOptions = {},\n): Promise<void> {\n const client = wsClient;\n if (!client?.hasActiveConnection()) {\n return;\n }\n\n const refreshed = await client.refreshAuthentication();\n if (!refreshed) {\n reconnectRelayWebSocket({\n reason: options.reason ?? 'auth_refresh_fallback',\n });\n }\n}\n\nexport interface RelayEnvironmentConfiguration {\n httpUrl?: string;\n wsUrl?: string;\n logEvents?: boolean;\n getDataId?: (fieldValue: unknown, typeName: string) => string | null;\n getAuthHeaders?: () =>\n Record<string, string> | Promise<Record<string, string>>;\n fetchImpl?: typeof fetch;\n}\n\n/**\n * Configure the endpoints and logging behavior used by the shared Relay environment.\n */\nexport function configureRelayEnvironment(\n options: RelayEnvironmentConfiguration = {},\n): void {\n const {\n httpUrl,\n wsUrl,\n logEvents,\n getDataId: nextGetDataId,\n getAuthHeaders: nextGetAuthHeaders,\n fetchImpl: nextFetchImpl,\n } = options;\n\n if (typeof httpUrl === 'string' && httpUrl !== '') {\n graphqlHttpEndpoint = httpUrl;\n }\n\n if (typeof wsUrl === 'string' && wsUrl !== '') {\n graphqlWsEndpoint = wsUrl;\n }\n\n if (logEvents != null) {\n if (logEvents) {\n relayFieldLogger = (event) => {\n // eslint-disable-next-line no-console\n console.log('relayFieldLogger: ', event);\n };\n } else {\n relayFieldLogger = noopRelayFieldLogger;\n }\n }\n\n customDataIdResolver = nextGetDataId;\n getAuthHeaders = nextGetAuthHeaders;\n graphqlFetch = nextFetchImpl ?? defaultGraphqlFetch;\n\n rotateRelayEnvironment('configured', 'configure');\n}\n\n/**\n * Resolve the websocket endpoint into an absolute GraphQL WebSocket URL.\n */\nfunction resolveWebsocketUrl(): string {\n const endpoint = graphqlWsEndpoint;\n\n if (endpoint.startsWith('ws')) {\n return endpoint;\n }\n\n if (endpoint.startsWith('http')) {\n return endpoint.replace(/^http/, 'ws');\n }\n\n if (endpoint.startsWith('/')) {\n if (typeof window === 'undefined') {\n return endpoint;\n }\n let protocol = 'ws:';\n if (window.location.protocol === 'https:') {\n protocol = 'wss:';\n }\n return `${protocol}//${window.location.host}${endpoint}`;\n }\n\n return endpoint;\n}\n\n/** Debug log helper (no-op en production) */\nfunction debugLog(...args: unknown[]): void {\n if (isDevEnv()) {\n // eslint-disable-next-line no-console\n console.log('[RelayNetwork]', ...args);\n }\n}\n\n/** Resolve authentication headers for Relay HTTP and websocket transports. */\nasync function resolveAuthHeaders(): Promise<Record<string, string>> {\n if (getAuthHeaders == null) {\n return {};\n }\n return getAuthHeaders();\n}\n\nclass RelayWebSocketClient {\n private socket: WebSocket | null = null;\n\n private connectPromise: Promise<void> | null = null;\n\n private disposed = false;\n\n private acknowledged = false;\n\n private retryCount = 0;\n\n private nextId = 1;\n\n private keepAliveTimer: ReturnType<typeof setInterval> | null = null;\n\n private readonly subscriptions = new Map<string, ActiveSubscription>();\n\n private pendingAuthUpdate: {\n resolve: (value: boolean) => void;\n timeout: ReturnType<typeof setTimeout>;\n } | null = null;\n\n public constructor(private readonly url: string) {}\n\n public hasActiveConnection(): boolean {\n return this.socket?.readyState === WebSocket.OPEN && this.acknowledged;\n }\n\n public dispose(): void {\n this.disposed = true;\n this.resolvePendingAuthUpdate(false);\n this.stopKeepAlive();\n const { socket } = this;\n this.socket = null;\n this.connectPromise = null;\n this.acknowledged = false;\n if (socket != null && socket.readyState !== WebSocket.CLOSED) {\n socket.close(1000, 'Normal Closure');\n }\n }\n\n public terminate(): void {\n for (const subscription of this.subscriptions.values()) {\n try {\n subscription.sink.complete();\n } catch {\n // ignore subscriber failures while ending an environment\n }\n }\n this.subscriptions.clear();\n this.dispose();\n }\n\n public subscribe(\n payload: ActiveSubscription['payload'],\n sink: SubscriptionSink,\n ): () => void {\n const id = String(this.nextId);\n this.nextId += 1;\n this.subscriptions.set(id, { payload, sink });\n this.connectAndSubscribe(id).catch((error: unknown) => {\n debugLog('subscription websocket connect failed', error);\n this.scheduleReconnect();\n });\n\n return () => {\n this.unsubscribe(id);\n };\n }\n\n public async refreshAuthentication(): Promise<boolean> {\n if (!this.hasActiveConnection()) {\n return true;\n }\n const { socket } = this;\n if (socket == null) {\n return true;\n }\n if (this.pendingAuthUpdate != null) {\n return false;\n }\n\n let payload: Record<string, string>;\n try {\n payload = await resolveAuthHeaders();\n } catch {\n return false;\n }\n if (Object.keys(payload).length === 0) {\n return false;\n }\n\n return new Promise<boolean>((resolve) => {\n const timeout = setTimeout(() => {\n this.pendingAuthUpdate = null;\n resolve(false);\n }, AUTH_UPDATE_TIMEOUT_MS);\n this.pendingAuthUpdate = { resolve, timeout };\n this.send({\n type: 'connection_auth_update',\n payload,\n });\n });\n }\n\n private async connectAndSubscribe(id: string): Promise<void> {\n const wasConnected = this.hasActiveConnection();\n await this.ensureConnected();\n if (!wasConnected) {\n return;\n }\n const subscription = this.subscriptions.get(id);\n if (subscription == null) {\n return;\n }\n this.send({\n id,\n type: 'subscribe',\n payload: subscription.payload,\n });\n }\n\n private async ensureConnected(): Promise<void> {\n if (this.hasActiveConnection()) {\n return;\n }\n if (this.connectPromise != null) {\n await this.connectPromise;\n return;\n }\n\n this.connectPromise = this.openSocket();\n try {\n await this.connectPromise;\n } finally {\n this.connectPromise = null;\n }\n }\n\n private async openSocket(): Promise<void> {\n if (this.disposed) {\n throw new Error('WebSocket client is disposed');\n }\n\n await new Promise<void>((resolve, reject) => {\n let settled = false;\n const resolveConnected = (): void => {\n if (settled) {\n return;\n }\n settled = true;\n resolve();\n };\n const rejectConnection = (error: unknown): void => {\n if (settled) {\n return;\n }\n settled = true;\n reject(error);\n };\n const socket = new WebSocket(this.url, GRAPHQL_TRANSPORT_WS_PROTOCOL);\n this.socket = socket;\n this.acknowledged = false;\n\n socket.onopen = () => {\n resolveAuthHeaders()\n .catch(() => {\n return {};\n })\n .then((payload) => {\n if (socket.readyState !== WebSocket.OPEN) {\n return;\n }\n if (Object.keys(payload).length > 0) {\n this.send({ type: 'connection_init', payload });\n return;\n }\n this.send({ type: 'connection_init' });\n })\n .catch((error: unknown) => {\n rejectConnection(error);\n });\n };\n\n socket.onerror = () => {\n rejectConnection(new Error('GraphQL subscription websocket error'));\n };\n\n socket.onmessage = (event) => {\n this.handleMessage(event.data, resolveConnected, rejectConnection);\n };\n\n socket.onclose = () => {\n rejectConnection(new Error('GraphQL subscription websocket closed'));\n this.handleClose();\n };\n });\n }\n\n private handleMessage(\n data: unknown,\n connected: () => void,\n rejected: (error: unknown) => void,\n ): void {\n let parsed: unknown;\n try {\n parsed = JSON.parse(String(data));\n } catch {\n rejected(new Error('Invalid GraphQL websocket message'));\n this.socket?.close(4400, 'Invalid websocket message');\n return;\n }\n\n const decoded = decodeGraphqlWsMessage(parsed);\n if (!decoded.ok) {\n const unsupported = decoded.reason === 'unsupported';\n let errorMessage = 'Invalid GraphQL websocket message';\n let closeMessage = 'Invalid websocket message';\n if (unsupported) {\n errorMessage = 'Unsupported GraphQL websocket message';\n closeMessage = 'Unsupported websocket message';\n }\n rejected(new Error(errorMessage));\n this.socket?.close(4400, closeMessage);\n return;\n }\n const message = decoded.value;\n\n switch (message.type) {\n case 'connection_ack':\n this.acknowledged = true;\n this.retryCount = 0;\n this.startKeepAlive();\n connected();\n this.resubscribeActiveOperations();\n return;\n case 'connection_auth_update_ack':\n this.resolvePendingAuthUpdate(true);\n return;\n case 'next':\n this.subscriptions.get(message.id)?.sink.next(message.payload);\n return;\n case 'error':\n if (message.id != null) {\n this.failSubscription(message.id, message.payload);\n } else {\n this.resolvePendingAuthUpdate(false);\n }\n return;\n case 'complete':\n this.completeSubscription(message.id);\n return;\n case 'ping':\n this.send({ type: 'pong', payload: message.payload });\n break;\n case 'pong':\n break;\n default:\n break;\n }\n }\n\n private handleClose(): void {\n this.acknowledged = false;\n this.socket = null;\n this.connectPromise = null;\n this.stopKeepAlive();\n this.resolvePendingAuthUpdate(false);\n if (!this.disposed && this.subscriptions.size > 0) {\n this.scheduleReconnect();\n }\n }\n\n private scheduleReconnect(): void {\n if (this.retryCount >= WS_MAX_RETRY_ATTEMPTS) {\n const error = new Error('GraphQL subscription websocket retry exhausted');\n for (const id of [...this.subscriptions.keys()]) {\n this.failSubscription(id, error);\n }\n return;\n }\n const delay =\n Math.min(8_000, WS_BASE_RETRY_DELAY_MS * 2 ** this.retryCount) +\n Math.random() * 200;\n this.retryCount += 1;\n setTimeout(() => {\n if (this.disposed || this.subscriptions.size === 0) {\n return;\n }\n this.ensureConnected().catch((error: unknown) => {\n this.scheduleReconnect();\n debugLog('subscription websocket reconnect failed', error);\n });\n }, delay);\n }\n\n private resubscribeActiveOperations(): void {\n for (const [id, subscription] of this.subscriptions) {\n this.send({\n id,\n type: 'subscribe',\n payload: subscription.payload,\n });\n }\n }\n\n private unsubscribe(id: string): void {\n const hadSubscription = this.subscriptions.delete(id);\n if (hadSubscription && this.socket?.readyState === WebSocket.OPEN) {\n this.send({ id, type: 'complete' });\n }\n }\n\n private failSubscription(id: string, error: unknown): void {\n const subscription = this.subscriptions.get(id);\n if (subscription == null) {\n return;\n }\n this.subscriptions.delete(id);\n subscription.sink.error(error);\n }\n\n private completeSubscription(id: string): void {\n const subscription = this.subscriptions.get(id);\n if (subscription == null) {\n return;\n }\n this.subscriptions.delete(id);\n subscription.sink.complete();\n }\n\n private startKeepAlive(): void {\n this.stopKeepAlive();\n this.keepAliveTimer = setInterval(() => {\n if (this.socket?.readyState === WebSocket.OPEN) {\n this.send({ type: 'ping' });\n }\n }, WS_KEEP_ALIVE_MS);\n }\n\n private stopKeepAlive(): void {\n if (this.keepAliveTimer != null) {\n clearInterval(this.keepAliveTimer);\n this.keepAliveTimer = null;\n }\n }\n\n private resolvePendingAuthUpdate(value: boolean): void {\n const pending = this.pendingAuthUpdate;\n if (pending == null) {\n return;\n }\n clearTimeout(pending.timeout);\n this.pendingAuthUpdate = null;\n pending.resolve(value);\n }\n\n private send(message: GraphqlWsPayload): void {\n const { socket } = this;\n if (socket?.readyState !== WebSocket.OPEN) {\n return;\n }\n socket.send(JSON.stringify(message));\n }\n}\n\n/**\n * Build or get a singleton graphql-transport-ws client with auth refresh support.\n */\nfunction getWsClient(): RelayWebSocketClient {\n if (wsClient != null) {\n return wsClient;\n }\n if (typeof window === 'undefined') {\n throw new Error(\n 'GraphQL subscriptions unavailable in non-browser environment',\n );\n }\n\n const url = resolveWebsocketUrl();\n wsClient = new RelayWebSocketClient(url);\n\n return wsClient;\n}\n\n/**\n * Get organization slug from current window location\n */\n// export function getOrganizationSlug(): string | null {\n// const { pathname } = window.location;\n// const slug = pathname.split('/')[1];\n// if (slug == null) {\n// return null;\n// }\n\n// return slug;\n// }\n\n// -------------------------\n// Upload detection helpers\n// -------------------------\n/** Test if a value is an uploadable (File/Blob) */\nfunction isUploadable(value: unknown): value is File | Blob {\n return (\n (typeof File !== 'undefined' && value instanceof File) ||\n (typeof Blob !== 'undefined' && value instanceof Blob)\n );\n}\n\ninterface FileRef {\n path: string; // JSON pointer-like (e.g. variables.input.file)\n file: File | Blob;\n}\n\n/** Recursively clone a structure replacing files with null and collecting them */\nfunction collectFiles(value: unknown, path: string, acc: FileRef[]): unknown {\n if (isUploadable(value)) {\n acc.push({ path, file: value });\n return null; // placeholder per multipart spec\n }\n if (Array.isArray(value)) {\n return value.map((v, i) => {\n return collectFiles(v, `${path}.${i}`, acc);\n });\n }\n if (value != null && typeof value === 'object') {\n const out: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(value as Record<string, unknown>)) {\n out[k] = collectFiles(v, `${path}.${k}`, acc);\n }\n return out;\n }\n return value; // primitives unchanged\n}\n\n/** Build GraphQL multipart form-data payload */\nfunction buildFormData(\n query: string,\n variables: Record<string, unknown>,\n): FormData {\n const files: FileRef[] = [];\n // Deep clone variables while replacing files with null\n const clonedVars = collectFiles(variables, 'variables', files) as Record<\n string,\n unknown\n >;\n\n const form = new FormData();\n const operations = { query, variables: clonedVars };\n form.append('operations', JSON.stringify(operations));\n\n const map: Record<string, string[]> = {};\n files.forEach((ref, idx) => {\n map[idx] = [ref.path];\n });\n form.append('map', JSON.stringify(map));\n files.forEach((ref, idx) => {\n form.append(String(idx), ref.file);\n });\n return form;\n}\n\n// -------------------------\n// Retry / timeout helpers\n// -------------------------\ninterface RetryOptions {\n maxAttempts: number; // total attempts including initial\n baseDelayMs: number;\n maxDelayMs: number;\n fetchTimeoutMs: number;\n}\n\nconst RETRY_OPTIONS: RetryOptions = {\n maxAttempts: 3,\n baseDelayMs: 300,\n maxDelayMs: 4000,\n fetchTimeoutMs: 600_000, // 10 minutes (parité avec ancien middleware)\n};\n\n/** Sleep helper with Promise */\nasync function sleep(ms: number): Promise<void> {\n await new Promise<void>((res) => {\n setTimeout(() => {\n res();\n }, ms);\n });\n}\n\n/** Exponential backoff with jitter */\nfunction calcBackoff(attempt: number, opts: RetryOptions): number {\n const exp = Math.min(opts.maxDelayMs, opts.baseDelayMs * 2 ** attempt);\n return exp + Math.random() * 0.2 * exp; // jitter 0-20%\n}\n\n/** Determine if an HTTP status is retryable */\nfunction isRetryableStatus(status: number): boolean {\n return status === 408 || status === 429 || (status >= 500 && status < 600);\n}\n\n/** Determine if an error should be treated as transient network issue */\nfunction isNetworkError(err: unknown): boolean {\n return (\n err instanceof TypeError ||\n (err instanceof Error && err.name === 'AbortError')\n );\n}\n\n// -------------------------\n// fetchFn implementation\n// -------------------------\ninterface GraphQLResponseErrorItem {\n [key: string]: unknown;\n message: string;\n path?: readonly unknown[];\n}\n\ninterface GraphQLResponseShape<T = unknown> {\n data?: T;\n errors?: GraphQLResponseErrorItem[];\n extensions?: Record<string, unknown>;\n}\n\nexport class GraphQLResponseError extends Error {\n public constructor(\n public readonly errors: readonly GraphQLResponseErrorItem[],\n public readonly response: GraphQLResponseShape,\n ) {\n super(errors[0]?.message ?? 'GraphQL response error');\n this.name = 'GraphQLResponseError';\n }\n}\n\n/** Determine whether a GraphQL payload includes non-null top-level data. */\nfunction hasUsableTopLevelData(data: unknown): boolean {\n if (data == null) {\n return false;\n }\n if (typeof data !== 'object') {\n return true;\n }\n return Object.values(data as Record<string, unknown>).some((value) => {\n return value != null;\n });\n}\n\n/** Determine whether all errors are child-field errors under top-level null data. */\nfunction hasOnlyErrorsBelowNullTopLevelFields(\n response: GraphQLResponseShape,\n): boolean {\n const { data, errors } = response;\n if (\n data == null ||\n typeof data !== 'object' ||\n !Array.isArray(errors) ||\n errors.length === 0\n ) {\n return false;\n }\n\n const dataRecord = data as Record<string, unknown>;\n return errors.every((error) => {\n const [topLevelField, ...childPath] = error.path ?? [];\n if (typeof topLevelField !== 'string' || childPath.length === 0) {\n return false;\n }\n return (\n Object.prototype.hasOwnProperty.call(dataRecord, topLevelField) &&\n dataRecord[topLevelField] == null\n );\n });\n}\n\n/** Determine whether GraphQL errors should be surfaced as a thrown response error. */\nfunction shouldThrowGraphQLResponseError(\n response: GraphQLResponseShape,\n): boolean {\n return (\n Array.isArray(response.errors) &&\n response.errors.length > 0 &&\n !hasUsableTopLevelData(response.data) &&\n !hasOnlyErrorsBelowNullTopLevelFields(response)\n );\n}\n\n/** Fetch GraphQL (with retry + upload) */\nasync function fetchFn(\n request: {\n name?: string | null;\n operationKind?: unknown;\n text: string | null | undefined;\n },\n variables: Record<string, unknown>,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n _cacheConfig: unknown,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n _uploadables: unknown,\n): Promise<GraphQLResponseShape> {\n const operationEnvironmentGeneration = environmentGeneration;\n const queryText: string | null | undefined = request.text; // no persisted queries here (yet)\n if (queryText == null) {\n throw new Error('Missing GraphQL query text');\n }\n const safeQueryText: string = queryText; // narrowed non-null\n const stopRelayOperationActivity = startRelayOperationActivity(request);\n\n /** Execute one network attempt */\n async function execOnce(attempt: number): Promise<GraphQLResponseShape> {\n if (operationEnvironmentGeneration !== environmentGeneration) {\n throw new Error(ENVIRONMENT_ROTATED_ERROR);\n }\n const controller = new AbortController();\n activeHttpControllers.add(controller);\n const timeout = setTimeout(() => {\n controller.abort();\n }, RETRY_OPTIONS.fetchTimeoutMs);\n try {\n let body: BodyInit;\n const headers: Record<string, string> = {};\n if (getAuthHeaders != null) {\n try {\n Object.assign(headers, await getAuthHeaders());\n } catch {\n // ignore auth header failures\n }\n }\n if (operationEnvironmentGeneration !== environmentGeneration) {\n throw new Error(ENVIRONMENT_ROTATED_ERROR);\n }\n const hasFiles = ((): boolean => {\n try {\n const stack: unknown[] = [variables];\n while (stack.length > 0) {\n const v = stack.pop();\n if (isUploadable(v)) {\n return true;\n }\n if (Array.isArray(v)) {\n stack.push(...v);\n } else if (v != null && typeof v === 'object') {\n stack.push(...Object.values(v as Record<string, unknown>));\n }\n }\n } catch {\n // ignore traversal errors\n }\n return false;\n })();\n\n if (hasFiles) {\n body = buildFormData(safeQueryText, variables);\n headers[GRAPHQL_CSRF_PREFLIGHT_HEADER] =\n GRAPHQL_CSRF_PREFLIGHT_HEADER_VALUE;\n } else {\n headers['Content-Type'] = 'application/json';\n body = JSON.stringify({ query: safeQueryText, variables });\n }\n\n const response = await graphqlFetch(graphqlHttpEndpoint, {\n method: 'POST',\n body,\n headers,\n credentials: 'include',\n signal: controller.signal,\n });\n\n if (operationEnvironmentGeneration !== environmentGeneration) {\n throw new Error(ENVIRONMENT_ROTATED_ERROR);\n }\n\n if (!response.ok) {\n if (\n attempt < RETRY_OPTIONS.maxAttempts - 1 &&\n isRetryableStatus(response.status)\n ) {\n throw new Error(`Retryable HTTP status ${response.status}`);\n }\n const text = await response.text().catch(() => {\n return '';\n });\n throw new Error(`GraphQL HTTP error ${response.status}: ${text}`);\n }\n\n const json: GraphQLResponseShape = await response.json();\n if (Array.isArray(json.errors) && json.errors.length > 0) {\n debugLog('GraphQL errors', json.errors);\n }\n if (shouldThrowGraphQLResponseError(json)) {\n throw new GraphQLResponseError(json.errors ?? [], json);\n }\n return json;\n } finally {\n clearTimeout(timeout);\n activeHttpControllers.delete(controller);\n }\n }\n\n try {\n for (let attempt = 0; attempt < RETRY_OPTIONS.maxAttempts; attempt += 1) {\n try {\n return await execOnce(attempt);\n } catch (err) {\n if (operationEnvironmentGeneration !== environmentGeneration) {\n throw new Error(ENVIRONMENT_ROTATED_ERROR, { cause: err });\n }\n const last = attempt === RETRY_OPTIONS.maxAttempts - 1;\n const retryable =\n isNetworkError(err) ||\n (err instanceof Error &&\n err.message.includes('Retryable HTTP status'));\n if (!retryable || last) {\n debugLog('GraphQL fetch error', err);\n throw err;\n }\n const delay = calcBackoff(attempt, RETRY_OPTIONS);\n await sleep(delay);\n }\n }\n throw new Error('Exhausted retries without returning a result');\n } finally {\n stopRelayOperationActivity();\n }\n}\n\n// -------------------------\n// subscribeFn implementation (wrap existing logic in Relay Observable)\n// -------------------------\n/** Subscription function bridging the owned GraphQL WebSocket client to Relay. */\nfunction subscribeFn(\n operation: { text: string | null | undefined; name: string },\n variables: Record<string, unknown>,\n): Observable<unknown> {\n debugLog('subscription:start', operation.name, variables);\n return Observable.create<unknown>((sink) => {\n const query = operation.text;\n if (query == null || query === '') {\n sink.error(new Error('Subscription operation text is empty'));\n return () => {\n // noop\n };\n }\n const client = getWsClient();\n const dispose = client.subscribe(\n { query, variables, operationName: operation.name },\n {\n next: (data) => {\n sink.next(data);\n },\n error: (err) => {\n let errorObj: Error;\n if (err instanceof Error) {\n errorObj = err;\n } else {\n errorObj = new Error('Subscription error');\n }\n sink.error(errorObj);\n },\n complete: () => {\n sink.complete();\n },\n },\n );\n return () => {\n dispose();\n };\n });\n}\n\n/**\n * Create native Relay network layer (fetch + subscribe)\n */\nexport function getNetwork(): ReturnType<typeof Network.create> {\n return Network.create(\n fetchFn as FetchFunction,\n subscribeFn as SubscribeFunction,\n );\n}\n\n/**\n * Get anonymous relay environment\n */\nexport function getEnvironment(): Environment {\n environment ??= new Environment({\n getDataID: getDataId,\n relayFieldLogger,\n network: getNetwork(),\n store: new Store(new RecordSource()),\n });\n\n return environment;\n}\n\n/**\n * End the current Relay session and expose a new empty environment.\n */\nexport function resetRelayStore(): void {\n rotateRelayEnvironment('configured', 'session_reset');\n}\n\nexport const __test = {\n RelayWebSocketClient,\n buildFormData,\n calcBackoff,\n collectFiles,\n decodeGraphqlWsMessage,\n fetchFn,\n getDataId,\n hasUsableTopLevelData,\n isNetworkError,\n isRetryableStatus,\n isUploadable,\n shouldThrowGraphQLResponseError,\n subscribeFn,\n};\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"envHelpers.d.ts","sourceRoot":"","sources":["../../src/envHelpers.ts"],"names":[],"mappings":"AAAA,KAAK,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC,CAAC;AAe9D,MAAM,MAAM,SAAS,GAAG,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;AAE5D,QAAA,MAAM,iBAAiB,QAAS,SAAS,OAAO,MAAM,KAAG,MAAM,GAAG,SAYjE,CAAC;AAEF,QAAA,MAAM,wBAAwB,QACvB,SAAS,OACT,MAAM,KACV,OAAO,GAAG,SAcZ,CAAC;AAEF,QAAA,MAAM,kBAAkB,QAAS,SAAS,KAAG,OAE5C,CAAC;AAMF,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAEvD;AAKD,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CAE/D;AAKD,wBAAgB,QAAQ,IAAI,OAAO,CAElC;AAED,UAAU,sBAAsB;IAC9B,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,SAAS,CAAC;CAClB;AAKD,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,sBAAsB,GAAG,MAAM,CAS3E;AAED,UAAU,+BAAgC,SAAQ,sBAAsB;IACtE,YAAY,EAAE,MAAM,CAAC;CACtB;AAKD,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,+BAA+B,GACvC,MAAM,CAmBR;AAED,eAAO,MAAM,MAAM;;;;CAIlB,CAAC"}
1
+ {"version":3,"file":"envHelpers.d.ts","sourceRoot":"","sources":["../../src/envHelpers.ts"],"names":[],"mappings":"AAAA,KAAK,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC,CAAC;AAkC9D,MAAM,MAAM,SAAS,GAAG,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;AAE5D,QAAA,MAAM,iBAAiB,QAAS,SAAS,OAAO,MAAM,KAAG,MAAM,GAAG,SAYjE,CAAC;AAEF,QAAA,MAAM,wBAAwB,QACvB,SAAS,OACT,MAAM,KACV,OAAO,GAAG,SAcZ,CAAC;AAEF,QAAA,MAAM,kBAAkB,QAAS,SAAS,KAAG,OAE5C,CAAC;AAMF,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAEvD;AAKD,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CAE/D;AAKD,wBAAgB,QAAQ,IAAI,OAAO,CAElC;AAED,UAAU,sBAAsB;IAC9B,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,SAAS,CAAC;CAClB;AAKD,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,sBAAsB,GAAG,MAAM,CAS3E;AAED,UAAU,+BAAgC,SAAQ,sBAAsB;IACtE,YAAY,EAAE,MAAM,CAAC;CACtB;AAKD,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,+BAA+B,GACvC,MAAM,CAmBR;AAED,eAAO,MAAM,MAAM;;;;CAIlB,CAAC"}
@@ -1,4 +1,4 @@
1
- import { Environment, Network } from 'relay-runtime';
1
+ import { Environment, Network, Observable } from 'relay-runtime';
2
2
  export type RelayTransportStatus = 'idle' | 'configured' | 'reconnecting';
3
3
  export interface RelayTransportSnapshot {
4
4
  generation: number;
@@ -25,6 +25,38 @@ export interface RelayAuthRefreshOptions {
25
25
  }
26
26
  type RelayTransportListener = () => void;
27
27
  type RelayOperationActivityListener = () => void;
28
+ type GraphqlWsMessage = {
29
+ type: 'connection_ack';
30
+ payload?: unknown;
31
+ } | {
32
+ type: 'connection_auth_update_ack';
33
+ payload?: unknown;
34
+ } | {
35
+ id: string;
36
+ type: 'next';
37
+ payload: unknown;
38
+ } | {
39
+ id?: string;
40
+ type: 'error';
41
+ payload: unknown;
42
+ } | {
43
+ id: string;
44
+ type: 'complete';
45
+ } | {
46
+ type: 'ping';
47
+ payload?: unknown;
48
+ } | {
49
+ type: 'pong';
50
+ payload?: unknown;
51
+ };
52
+ type GraphqlWsMessageDecodeResult = {
53
+ readonly ok: true;
54
+ readonly value: GraphqlWsMessage;
55
+ } | {
56
+ readonly ok: false;
57
+ readonly reason: 'invalid' | 'unsupported';
58
+ };
59
+ declare const decodeGraphqlWsMessage: (value: unknown) => GraphqlWsMessageDecodeResult;
28
60
  type SubscriptionSink = {
29
61
  next: (value: unknown) => void;
30
62
  error: (error: unknown) => void;
@@ -51,6 +83,7 @@ export interface RelayEnvironmentConfiguration {
51
83
  logEvents?: boolean;
52
84
  getDataId?: (fieldValue: unknown, typeName: string) => string | null;
53
85
  getAuthHeaders?: () => Record<string, string> | Promise<Record<string, string>>;
86
+ fetchImpl?: typeof fetch;
54
87
  }
55
88
  export declare function configureRelayEnvironment(options?: RelayEnvironmentConfiguration): void;
56
89
  declare class RelayWebSocketClient {
@@ -67,6 +100,7 @@ declare class RelayWebSocketClient {
67
100
  constructor(url: string);
68
101
  hasActiveConnection(): boolean;
69
102
  dispose(): void;
103
+ terminate(): void;
70
104
  subscribe(payload: ActiveSubscription['payload'], sink: SubscriptionSink): () => void;
71
105
  refreshAuthentication(): Promise<boolean>;
72
106
  private connectAndSubscribe;
@@ -122,6 +156,10 @@ declare function fetchFn(request: {
122
156
  operationKind?: unknown;
123
157
  text: string | null | undefined;
124
158
  }, variables: Record<string, unknown>, _cacheConfig: unknown, _uploadables: unknown): Promise<GraphQLResponseShape>;
159
+ declare function subscribeFn(operation: {
160
+ text: string | null | undefined;
161
+ name: string;
162
+ }, variables: Record<string, unknown>): Observable<unknown>;
125
163
  export declare function getNetwork(): ReturnType<typeof Network.create>;
126
164
  export declare function getEnvironment(): Environment;
127
165
  export declare function resetRelayStore(): void;
@@ -130,6 +168,7 @@ export declare const __test: {
130
168
  buildFormData: typeof buildFormData;
131
169
  calcBackoff: typeof calcBackoff;
132
170
  collectFiles: typeof collectFiles;
171
+ decodeGraphqlWsMessage: typeof decodeGraphqlWsMessage;
133
172
  fetchFn: typeof fetchFn;
134
173
  getDataId: typeof getDataId;
135
174
  hasUsableTopLevelData: typeof hasUsableTopLevelData;
@@ -137,6 +176,7 @@ export declare const __test: {
137
176
  isRetryableStatus: typeof isRetryableStatus;
138
177
  isUploadable: typeof isUploadable;
139
178
  shouldThrowGraphQLResponseError: typeof shouldThrowGraphQLResponseError;
179
+ subscribeFn: typeof subscribeFn;
140
180
  };
141
181
  export {};
142
182
  //# sourceMappingURL=environment.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"environment.d.ts","sourceRoot":"","sources":["../../src/environment.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,WAAW,EACX,OAAO,EAOR,MAAM,eAAe,CAAC;AAmBvB,MAAM,MAAM,oBAAoB,GAAG,MAAM,GAAG,YAAY,GAAG,cAAc,CAAC;AAE1E,MAAM,WAAW,sBAAsB;IACrC,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,MAAM,EAAE,oBAAoB,CAAC;CAC9B;AAED,MAAM,MAAM,kBAAkB,GAAG,UAAU,GAAG,OAAO,GAAG,SAAS,CAAC;AAElE,MAAM,MAAM,qBAAqB,GAAG;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,kBAAkB,CAAC;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,WAAW,8BAA8B;IAC7C,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,iBAAiB,EAAE,SAAS,qBAAqB,EAAE,CAAC;CACrD;AAED,MAAM,WAAW,qBAAqB;IACpC,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,uBAAuB;IACtC,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,KAAK,sBAAsB,GAAG,MAAM,IAAI,CAAC;AACzC,KAAK,8BAA8B,GAAG,MAAM,IAAI,CAAC;AAajD,KAAK,gBAAgB,GAAG;IACtB,IAAI,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IAC/B,KAAK,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IAChC,QAAQ,EAAE,MAAM,IAAI,CAAC;CACtB,CAAC;AAEF,KAAK,kBAAkB,GAAG;IACxB,OAAO,EAAE;QACP,KAAK,EAAE,MAAM,CAAC;QACd,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACnC,aAAa,EAAE,MAAM,CAAC;KACvB,CAAC;IACF,IAAI,EAAE,gBAAgB,CAAC;CACxB,CAAC;AAsDF,QAAA,MAAM,SAAS,eAAgB,OAAO,YAAY,MAAM,KAAG,MAAM,GAAG,IAMnE,CAAC;AA6GF,wBAAgB,yBAAyB,IAAI,sBAAsB,CAElE;AAKD,wBAAgB,uBAAuB,CACrC,QAAQ,EAAE,sBAAsB,GAC/B,MAAM,IAAI,CAKZ;AAKD,wBAAgB,iCAAiC,IAAI,8BAA8B,CAElF;AAKD,wBAAgB,+BAA+B,CAC7C,QAAQ,EAAE,8BAA8B,GACvC,MAAM,IAAI,CAKZ;AAKD,wBAAgB,uBAAuB,CACrC,OAAO,GAAE,qBAA0B,GAClC,IAAI,CAMN;AAKD,wBAAsB,mCAAmC,CACvD,OAAO,GAAE,uBAA4B,GACpC,OAAO,CAAC,IAAI,CAAC,CAYf;AAED,MAAM,WAAW,6BAA6B;IAC5C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,SAAS,CAAC,EAAE,CAAC,UAAU,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;IACrE,cAAc,CAAC,EAAE,MACf,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CAC5D;AAKD,wBAAgB,yBAAyB,CACvC,OAAO,GAAE,6BAAkC,GAC1C,IAAI,CAmCN;AA8CD,cAAM,oBAAoB;IAsBL,OAAO,CAAC,QAAQ,CAAC,GAAG;IArBvC,OAAO,CAAC,MAAM,CAA0B;IAExC,OAAO,CAAC,cAAc,CAA8B;IAEpD,OAAO,CAAC,QAAQ,CAAS;IAEzB,OAAO,CAAC,YAAY,CAAS;IAE7B,OAAO,CAAC,UAAU,CAAK;IAEvB,OAAO,CAAC,MAAM,CAAK;IAEnB,OAAO,CAAC,cAAc,CAA+C;IAErE,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAyC;IAEvE,OAAO,CAAC,iBAAiB,CAGT;IAEhB,YAAoC,GAAG,EAAE,MAAM,EAAI;IAE5C,mBAAmB,IAAI,OAAO,CAEpC;IAEM,OAAO,IAAI,IAAI,CAWrB;IAEM,SAAS,CACd,OAAO,EAAE,kBAAkB,CAAC,SAAS,CAAC,EACtC,IAAI,EAAE,gBAAgB,GACrB,MAAM,IAAI,CAYZ;IAEY,qBAAqB,IAAI,OAAO,CAAC,OAAO,CAAC,CAiCrD;YAEa,mBAAmB;YAiBnB,eAAe;YAiBf,UAAU;IA4DxB,OAAO,CAAC,aAAa;IAiDrB,OAAO,CAAC,WAAW;IAWnB,OAAO,CAAC,iBAAiB;IAuBzB,OAAO,CAAC,2BAA2B;IAUnC,OAAO,CAAC,WAAW;IAOnB,OAAO,CAAC,gBAAgB;IASxB,OAAO,CAAC,oBAAoB;IAS5B,OAAO,CAAC,cAAc;IAStB,OAAO,CAAC,aAAa;IAOrB,OAAO,CAAC,wBAAwB;IAUhC,OAAO,CAAC,IAAI;CAOb;AAsCD,iBAAS,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,IAAI,GAAG,IAAI,CAK1D;AAED,UAAU,OAAO;IACf,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC;CACnB;AAGD,iBAAS,YAAY,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,OAAO,CAkB3E;AAGD,iBAAS,aAAa,CACpB,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACjC,QAAQ,CAqBV;AAKD,UAAU,YAAY;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;CACxB;AAmBD,iBAAS,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,GAAG,MAAM,CAGhE;AAGD,iBAAS,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAElD;AAGD,iBAAS,cAAc,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAK7C;AAKD,UAAU,wBAAwB;IAChC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,SAAS,OAAO,EAAE,CAAC;CAC3B;AAED,UAAU,oBAAoB,CAAC,CAAC,GAAG,OAAO;IACxC,IAAI,CAAC,EAAE,CAAC,CAAC;IACT,MAAM,CAAC,EAAE,wBAAwB,EAAE,CAAC;IACpC,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACtC;AAED,qBAAa,oBAAqB,SAAQ,KAAK;aAE3B,MAAM,EAAE,SAAS,wBAAwB,EAAE;aAC3C,QAAQ,EAAE,oBAAoB;IAFhD,YACkB,MAAM,EAAE,SAAS,wBAAwB,EAAE,EAC3C,QAAQ,EAAE,oBAAoB,EAI/C;CACF;AAGD,iBAAS,qBAAqB,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAUrD;AA8BD,iBAAS,+BAA+B,CACtC,QAAQ,EAAE,oBAAoB,GAC7B,OAAO,CAOT;AAGD,iBAAe,OAAO,CACpB,OAAO,EAAE;IACP,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;CACjC,EACD,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAElC,YAAY,EAAE,OAAO,EAErB,YAAY,EAAE,OAAO,GACpB,OAAO,CAAC,oBAAoB,CAAC,CA6G/B;AAiDD,wBAAgB,UAAU,IAAI,UAAU,CAAC,OAAO,OAAO,CAAC,MAAM,CAAC,CAK9D;AAKD,wBAAgB,cAAc,IAAI,WAAW,CAS5C;AAKD,wBAAgB,eAAe,IAAI,IAAI,CAWtC;AAED,eAAO,MAAM,MAAM;;;;;;;;;;;;CAYlB,CAAC"}
1
+ {"version":3,"file":"environment.d.ts","sourceRoot":"","sources":["../../src/environment.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@plumile/relay",
3
- "version": "0.1.200",
3
+ "version": "0.1.205",
4
4
  "description": "Shared Relay runtime helpers for Plumile applications",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -56,12 +56,11 @@
56
56
  "test:build-package": "./tools/test-build-package.sh"
57
57
  },
58
58
  "dependencies": {
59
- "graphql-ws": "6.2.1",
60
59
  "relay-runtime": "^21.0.1",
61
60
  "tslib": "^2.8.1"
62
61
  },
63
62
  "devDependencies": {
64
- "@plumile/auth": "^0.1.200",
63
+ "@plumile/auth": "^0.1.205",
65
64
  "@types/react": "19.2.18",
66
65
  "@types/react-dom": "19.2.4",
67
66
  "@types/relay-runtime": "20.1.1",
@@ -73,9 +72,8 @@
73
72
  "rimraf": "6.1.3"
74
73
  },
75
74
  "peerDependencies": {
76
- "@plumile/auth": "^0.1.199",
75
+ "@plumile/auth": "^0.1.201",
77
76
  "react": "^19.2.8",
78
- "react-dom": "^19.2.8",
79
77
  "react-relay": "^21.0.1",
80
78
  "relay-runtime": "^21.0.1"
81
79
  },