@plumile/relay 0.1.181

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) Plumile and its affiliates.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,13 @@
1
+ import { getEnvironment as e, getRelayTransportSnapshot as t, subscribeRelayTransport as n } from "./environment.js";
2
+ import { useSyncExternalStore as r } from "react";
3
+ import * as i from "react-relay";
4
+ import { jsx as a } from "react/jsx-runtime";
5
+ //#region src/RelayProvider.tsx
6
+ var { RelayEnvironmentProvider: o } = i, s = ({ children: i }) => (r(n, () => t().generation, () => t().generation), /* @__PURE__ */ a(o, {
7
+ environment: e(),
8
+ children: i
9
+ }));
10
+ //#endregion
11
+ export { s as RelayProvider, s as default };
12
+
13
+ //# sourceMappingURL=RelayProvider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RelayProvider.js","names":[],"sources":["../../src/RelayProvider.tsx"],"sourcesContent":["import { useSyncExternalStore, type JSX, type ReactNode } from 'react';\nimport * as ReactRelay from 'react-relay';\n\nimport {\n getEnvironment,\n getRelayTransportSnapshot,\n subscribeRelayTransport,\n} from './environment.js';\n\nconst { RelayEnvironmentProvider } = ReactRelay;\n\ntype Props = {\n children: ReactNode;\n};\n\nexport const RelayProvider = ({ children }: Props): JSX.Element => {\n useSyncExternalStore(\n subscribeRelayTransport,\n () => {\n return getRelayTransportSnapshot().generation;\n },\n () => {\n return getRelayTransportSnapshot().generation;\n },\n );\n const environment = getEnvironment();\n\n return (\n <RelayEnvironmentProvider environment={environment}>\n {children}\n </RelayEnvironmentProvider>\n );\n};\n\nexport default RelayProvider;\n"],"mappings":";;;;;AASA,IAAM,EAAE,gCAA6B,GAMxB,KAAiB,EAAE,mBAC9B,EACE,SAES,EAA0B,EAAE,kBAG5B,EAA0B,EAAE,UAEvC,GAIE,kBAAC,GAAD;CAAuC,aAHrB,EAGqB;CACpC;AACuB,CAAA"}
@@ -0,0 +1,55 @@
1
+ //#region src/envHelpers.ts
2
+ var e = (() => {
3
+ try {
4
+ let e = import.meta;
5
+ return e.env == null ? {} : e.env;
6
+ } catch {
7
+ return {};
8
+ }
9
+ })(), t = (e, t) => {
10
+ let n = e[t];
11
+ if (typeof n != "string") return;
12
+ let r = n.trim();
13
+ if (r !== "") return r;
14
+ }, n = (e, t) => {
15
+ let n = e[t];
16
+ if (n === !0 || n === !1) return n;
17
+ if (typeof n == "string") {
18
+ if (n === "true") return !0;
19
+ if (n === "false") return !1;
20
+ }
21
+ }, r = (e) => !!n(e, "DEV");
22
+ function i(n) {
23
+ return t(e, n);
24
+ }
25
+ function a(t) {
26
+ return n(e, t);
27
+ }
28
+ function o() {
29
+ return r(e);
30
+ }
31
+ function s(e) {
32
+ let { envKeys: t, fallback: n, read: r = i } = e;
33
+ for (let e of t) {
34
+ let t = r(e);
35
+ if (t != null) return t;
36
+ }
37
+ return n;
38
+ }
39
+ function c(e) {
40
+ let { envKeys: t, fallback: n, httpEndpoint: r, read: a = i } = e;
41
+ for (let e of t) {
42
+ let t = a(e);
43
+ if (t != null) return t;
44
+ }
45
+ return r.startsWith("http") ? r.replace(/^http/, "ws") : r.startsWith("/") ? r.replace(/\/graphql$/, "/ws") : n;
46
+ }
47
+ var l = {
48
+ isDevEnvFromRecord: r,
49
+ readBooleanEnvFromRecord: n,
50
+ readEnvFromRecord: t
51
+ };
52
+ //#endregion
53
+ export { l as __test, o as isDevEnv, a as readBooleanEnv, i as readEnv, s as resolveHttpEndpoint, c as resolveWebsocketEndpoint };
54
+
55
+ //# sourceMappingURL=envHelpers.js.map
@@ -0,0 +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,OAAO;EAIpB,OAHI,EAAK,OAAO,OAGT,CAAC,IAFC,EAAK;CAGhB,QAAQ;EAEN,OAAO,CAAC;CACV;AACF,GAAG,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"}
@@ -0,0 +1,509 @@
1
+ import { isDevEnv as e } from "./envHelpers.js";
2
+ import { Environment as t, Network as n, Observable as r, RecordSource as i, Store as a } from "relay-runtime";
3
+ //#region src/environment.ts
4
+ var o = "/api/graphql", s = "/api/ws", c, l, u, d, f = "graphql-transport-ws", p = 5e3, m = 1e4, ee = 10, h = 500, g = {
5
+ generation: 0,
6
+ reason: null,
7
+ status: "idle"
8
+ }, _ = /* @__PURE__ */ new Set(), v = {
9
+ generation: 0,
10
+ pendingCount: 0,
11
+ pendingOperations: []
12
+ }, y = 0, b = /* @__PURE__ */ new Map(), x = /* @__PURE__ */ new Set(), S = !1;
13
+ function C() {}
14
+ var w = C;
15
+ e() && (w = (e) => {
16
+ console.log("relayFieldLogger: ", e);
17
+ });
18
+ var te = (e) => {
19
+ if (typeof e != "object" || !e) return null;
20
+ let { id: t } = e;
21
+ return typeof t != "string" || t.trim() === "" ? null : t;
22
+ }, T = (e, t) => d?.(e, t) ?? te(e, t);
23
+ function E(e, t) {
24
+ g = {
25
+ generation: g.generation + 1,
26
+ reason: t,
27
+ status: e
28
+ };
29
+ for (let e of _) e();
30
+ }
31
+ function D() {
32
+ v = {
33
+ generation: v.generation + 1,
34
+ pendingCount: b.size,
35
+ pendingOperations: [...b.values()]
36
+ }, !S && (S = !0, queueMicrotask(() => {
37
+ S = !1;
38
+ for (let e of x) e();
39
+ }));
40
+ }
41
+ function O() {
42
+ b.size !== 0 && (b.clear(), D());
43
+ }
44
+ function k(e) {
45
+ return e === "query" || e === "mutation" ? e : "unknown";
46
+ }
47
+ function A(e) {
48
+ let t = y;
49
+ y += 1, b.set(t, {
50
+ id: t,
51
+ kind: k(e.operationKind),
52
+ name: e.name ?? "AnonymousGraphQLOperation",
53
+ startedAt: Date.now()
54
+ }), D();
55
+ let n = !1;
56
+ return () => {
57
+ n || (n = !0, b.delete(t) && D());
58
+ };
59
+ }
60
+ function j() {
61
+ if (l != null) {
62
+ try {
63
+ l.dispose();
64
+ } catch {}
65
+ l = void 0;
66
+ }
67
+ }
68
+ function M() {
69
+ return g;
70
+ }
71
+ function N(e) {
72
+ return _.add(e), () => {
73
+ _.delete(e);
74
+ };
75
+ }
76
+ function ne() {
77
+ return v;
78
+ }
79
+ function re(e) {
80
+ return x.add(e), () => {
81
+ x.delete(e);
82
+ };
83
+ }
84
+ function P(e = {}) {
85
+ j(), E("reconnecting", e.reason ?? "manual_reconnect");
86
+ }
87
+ async function ie(e = {}) {
88
+ let t = l;
89
+ t?.hasActiveConnection() && (await t.refreshAuthentication() || P({ reason: e.reason ?? "auth_refresh_fallback" }));
90
+ }
91
+ function ae(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 && (w = r ? (e) => {
94
+ console.log("relayFieldLogger: ", e);
95
+ } : C), d = i, u = a, j(), c = void 0, O(), E("configured", "configure");
96
+ }
97
+ function oe() {
98
+ let e = s;
99
+ if (e.startsWith("ws")) return e;
100
+ if (e.startsWith("http")) return e.replace(/^http/, "ws");
101
+ if (e.startsWith("/")) {
102
+ if (typeof window > "u") return e;
103
+ let t = "ws:";
104
+ return window.location.protocol === "https:" && (t = "wss:"), `${t}//${window.location.host}${e}`;
105
+ }
106
+ return e;
107
+ }
108
+ function F(...t) {
109
+ e() && console.log("[RelayNetwork]", ...t);
110
+ }
111
+ async function I() {
112
+ return u == null ? {} : u();
113
+ }
114
+ var L = class {
115
+ url;
116
+ socket = null;
117
+ connectPromise = null;
118
+ disposed = !1;
119
+ acknowledged = !1;
120
+ retryCount = 0;
121
+ nextId = 1;
122
+ keepAliveTimer = null;
123
+ subscriptions = /* @__PURE__ */ new Map();
124
+ pendingAuthUpdate = null;
125
+ constructor(e) {
126
+ this.url = e;
127
+ }
128
+ hasActiveConnection() {
129
+ return this.socket?.readyState === WebSocket.OPEN && this.acknowledged;
130
+ }
131
+ dispose() {
132
+ this.disposed = !0, this.resolvePendingAuthUpdate(!1), this.stopKeepAlive();
133
+ let { socket: e } = this;
134
+ this.socket = null, this.connectPromise = null, this.acknowledged = !1, e != null && e.readyState !== WebSocket.CLOSED && e.close(1e3, "Normal Closure");
135
+ }
136
+ subscribe(e, t) {
137
+ let n = String(this.nextId);
138
+ return this.nextId += 1, this.subscriptions.set(n, {
139
+ payload: e,
140
+ sink: t
141
+ }), this.connectAndSubscribe(n).catch((e) => {
142
+ F("subscription websocket connect failed", e), this.scheduleReconnect();
143
+ }), () => {
144
+ this.unsubscribe(n);
145
+ };
146
+ }
147
+ async refreshAuthentication() {
148
+ if (!this.hasActiveConnection()) return !0;
149
+ let { socket: e } = this;
150
+ if (e == null) return !0;
151
+ if (this.pendingAuthUpdate != null) return !1;
152
+ let t;
153
+ try {
154
+ t = await I();
155
+ } catch {
156
+ return !1;
157
+ }
158
+ return Object.keys(t).length === 0 ? !1 : new Promise((e) => {
159
+ let n = setTimeout(() => {
160
+ this.pendingAuthUpdate = null, e(!1);
161
+ }, p);
162
+ this.pendingAuthUpdate = {
163
+ resolve: e,
164
+ timeout: n
165
+ }, this.send({
166
+ type: "connection_auth_update",
167
+ payload: t
168
+ });
169
+ });
170
+ }
171
+ async connectAndSubscribe(e) {
172
+ let t = this.hasActiveConnection();
173
+ if (await this.ensureConnected(), !t) return;
174
+ let n = this.subscriptions.get(e);
175
+ n != null && this.send({
176
+ id: e,
177
+ type: "subscribe",
178
+ payload: n.payload
179
+ });
180
+ }
181
+ async ensureConnected() {
182
+ if (!this.hasActiveConnection()) {
183
+ if (this.connectPromise != null) {
184
+ await this.connectPromise;
185
+ return;
186
+ }
187
+ this.connectPromise = this.openSocket();
188
+ try {
189
+ await this.connectPromise;
190
+ } finally {
191
+ this.connectPromise = null;
192
+ }
193
+ }
194
+ }
195
+ async openSocket() {
196
+ if (this.disposed) throw Error("WebSocket client is disposed");
197
+ await new Promise((e, t) => {
198
+ let n = !1, r = () => {
199
+ n || (n = !0, e());
200
+ }, i = (e) => {
201
+ n || (n = !0, t(e));
202
+ }, a = new WebSocket(this.url, f);
203
+ this.socket = a, this.acknowledged = !1, a.onopen = () => {
204
+ I().catch(() => ({})).then((e) => {
205
+ if (a.readyState === WebSocket.OPEN) {
206
+ if (Object.keys(e).length > 0) {
207
+ this.send({
208
+ type: "connection_init",
209
+ payload: e
210
+ });
211
+ return;
212
+ }
213
+ this.send({ type: "connection_init" });
214
+ }
215
+ }).catch((e) => {
216
+ i(e);
217
+ });
218
+ }, a.onerror = () => {
219
+ i(/* @__PURE__ */ Error("GraphQL subscription websocket error"));
220
+ }, a.onmessage = (e) => {
221
+ this.handleMessage(e.data, r, i);
222
+ }, a.onclose = () => {
223
+ i(/* @__PURE__ */ Error("GraphQL subscription websocket closed")), this.handleClose();
224
+ };
225
+ });
226
+ }
227
+ handleMessage(e, t, n) {
228
+ let r;
229
+ try {
230
+ r = JSON.parse(String(e));
231
+ } catch {
232
+ n(/* @__PURE__ */ Error("Invalid GraphQL websocket message")), this.socket?.close(4400, "Invalid websocket message");
233
+ return;
234
+ }
235
+ switch (r.type) {
236
+ case "connection_ack":
237
+ this.acknowledged = !0, this.retryCount = 0, this.startKeepAlive(), t(), this.resubscribeActiveOperations();
238
+ return;
239
+ case "connection_auth_update_ack":
240
+ this.resolvePendingAuthUpdate(!0);
241
+ return;
242
+ case "next":
243
+ this.subscriptions.get(r.id)?.sink.next(r.payload);
244
+ return;
245
+ case "error":
246
+ r.id == null ? this.resolvePendingAuthUpdate(!1) : this.failSubscription(r.id, r.payload);
247
+ return;
248
+ case "complete":
249
+ this.completeSubscription(r.id);
250
+ return;
251
+ case "ping":
252
+ this.send({
253
+ type: "pong",
254
+ payload: r.payload
255
+ });
256
+ return;
257
+ case "pong": return;
258
+ default: n(/* @__PURE__ */ Error("Unsupported GraphQL websocket message")), this.socket?.close(4400, "Unsupported websocket message");
259
+ }
260
+ }
261
+ handleClose() {
262
+ this.acknowledged = !1, this.socket = null, this.connectPromise = null, this.stopKeepAlive(), this.resolvePendingAuthUpdate(!1), !this.disposed && this.subscriptions.size > 0 && this.scheduleReconnect();
263
+ }
264
+ scheduleReconnect() {
265
+ if (this.retryCount >= ee) {
266
+ let e = /* @__PURE__ */ Error("GraphQL subscription websocket retry exhausted");
267
+ for (let t of [...this.subscriptions.keys()]) this.failSubscription(t, e);
268
+ return;
269
+ }
270
+ let e = Math.min(8e3, h * 2 ** this.retryCount) + Math.random() * 200;
271
+ this.retryCount += 1, setTimeout(() => {
272
+ this.disposed || this.subscriptions.size === 0 || this.ensureConnected().catch((e) => {
273
+ this.scheduleReconnect(), F("subscription websocket reconnect failed", e);
274
+ });
275
+ }, e);
276
+ }
277
+ resubscribeActiveOperations() {
278
+ for (let [e, t] of this.subscriptions) this.send({
279
+ id: e,
280
+ type: "subscribe",
281
+ payload: t.payload
282
+ });
283
+ }
284
+ unsubscribe(e) {
285
+ this.subscriptions.delete(e) && this.socket?.readyState === WebSocket.OPEN && this.send({
286
+ id: e,
287
+ type: "complete"
288
+ });
289
+ }
290
+ failSubscription(e, t) {
291
+ let n = this.subscriptions.get(e);
292
+ n != null && (this.subscriptions.delete(e), n.sink.error(t));
293
+ }
294
+ completeSubscription(e) {
295
+ let t = this.subscriptions.get(e);
296
+ t != null && (this.subscriptions.delete(e), t.sink.complete());
297
+ }
298
+ startKeepAlive() {
299
+ this.stopKeepAlive(), this.keepAliveTimer = setInterval(() => {
300
+ this.socket?.readyState === WebSocket.OPEN && this.send({ type: "ping" });
301
+ }, m);
302
+ }
303
+ stopKeepAlive() {
304
+ this.keepAliveTimer != null && (clearInterval(this.keepAliveTimer), this.keepAliveTimer = null);
305
+ }
306
+ resolvePendingAuthUpdate(e) {
307
+ let t = this.pendingAuthUpdate;
308
+ t != null && (clearTimeout(t.timeout), this.pendingAuthUpdate = null, t.resolve(e));
309
+ }
310
+ send(e) {
311
+ let { socket: t } = this;
312
+ t?.readyState === WebSocket.OPEN && t.send(JSON.stringify(e));
313
+ }
314
+ };
315
+ function R() {
316
+ if (l != null) return l;
317
+ if (typeof window > "u") throw Error("GraphQL subscriptions unavailable in non-browser environment");
318
+ return l = new L(oe()), l;
319
+ }
320
+ function z(e) {
321
+ return typeof File < "u" && e instanceof File || typeof Blob < "u" && e instanceof Blob;
322
+ }
323
+ function B(e, t, n) {
324
+ if (z(e)) return n.push({
325
+ path: t,
326
+ file: e
327
+ }), null;
328
+ if (Array.isArray(e)) return e.map((e, r) => B(e, `${t}.${r}`, n));
329
+ if (typeof e == "object" && e) {
330
+ let r = {};
331
+ for (let [i, a] of Object.entries(e)) r[i] = B(a, `${t}.${i}`, n);
332
+ return r;
333
+ }
334
+ return e;
335
+ }
336
+ function V(e, t) {
337
+ let n = [], r = B(t, "variables", n), i = new FormData(), a = {
338
+ query: e,
339
+ variables: r
340
+ };
341
+ i.append("operations", JSON.stringify(a));
342
+ let o = {};
343
+ return n.forEach((e, t) => {
344
+ o[t] = [e.path];
345
+ }), i.append("map", JSON.stringify(o)), n.forEach((e, t) => {
346
+ i.append(String(t), e.file);
347
+ }), i;
348
+ }
349
+ var H = {
350
+ maxAttempts: 3,
351
+ baseDelayMs: 300,
352
+ maxDelayMs: 4e3,
353
+ fetchTimeoutMs: 6e5
354
+ };
355
+ async function U(e) {
356
+ await new Promise((t) => {
357
+ setTimeout(() => {
358
+ t();
359
+ }, e);
360
+ });
361
+ }
362
+ function W(e, t) {
363
+ let n = Math.min(t.maxDelayMs, t.baseDelayMs * 2 ** e);
364
+ return n + Math.random() * .2 * n;
365
+ }
366
+ function G(e) {
367
+ return e === 408 || e === 429 || e >= 500 && e < 600;
368
+ }
369
+ function K(e) {
370
+ return e instanceof TypeError || e instanceof Error && e.name === "AbortError";
371
+ }
372
+ var q = class extends Error {
373
+ errors;
374
+ response;
375
+ constructor(e, t) {
376
+ super(e[0]?.message ?? "GraphQL response error"), this.errors = e, this.response = t, this.name = "GraphQLResponseError";
377
+ }
378
+ };
379
+ function J(e) {
380
+ return e == null ? !1 : typeof e == "object" ? Object.values(e).some((e) => e != null) : !0;
381
+ }
382
+ function se(e) {
383
+ let { data: t, errors: n } = e;
384
+ if (typeof t != "object" || !t || !Array.isArray(n) || n.length === 0) return !1;
385
+ let r = t;
386
+ return n.every((e) => {
387
+ let [t, ...n] = e.path ?? [];
388
+ return typeof t != "string" || n.length === 0 ? !1 : Object.prototype.hasOwnProperty.call(r, t) && r[t] == null;
389
+ });
390
+ }
391
+ function Y(e) {
392
+ return Array.isArray(e.errors) && e.errors.length > 0 && !J(e.data) && !se(e);
393
+ }
394
+ async function X(e, t, n, r) {
395
+ let i = e.text;
396
+ if (i == null) throw Error("Missing GraphQL query text");
397
+ let a = i, s = A(e);
398
+ async function c(e) {
399
+ let n = new AbortController(), r = setTimeout(() => {
400
+ n.abort();
401
+ }, H.fetchTimeoutMs);
402
+ try {
403
+ let r, i = {};
404
+ if (u != null) try {
405
+ Object.assign(i, await u());
406
+ } catch {}
407
+ (() => {
408
+ try {
409
+ let e = [t];
410
+ for (; e.length > 0;) {
411
+ let t = e.pop();
412
+ if (z(t)) return !0;
413
+ Array.isArray(t) ? e.push(...t) : typeof t == "object" && t && e.push(...Object.values(t));
414
+ }
415
+ } catch {}
416
+ return !1;
417
+ })() ? r = V(a, t) : (i["Content-Type"] = "application/json", r = JSON.stringify({
418
+ query: a,
419
+ variables: t
420
+ }));
421
+ let s = await fetch(o, {
422
+ method: "POST",
423
+ body: r,
424
+ headers: i,
425
+ credentials: "include",
426
+ signal: n.signal
427
+ });
428
+ if (!s.ok) {
429
+ if (e < H.maxAttempts - 1 && G(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}`);
432
+ }
433
+ let c = await s.json();
434
+ if (Array.isArray(c.errors) && c.errors.length > 0 && F("GraphQL errors", c.errors), Y(c)) throw new q(c.errors ?? [], c);
435
+ return c;
436
+ } finally {
437
+ clearTimeout(r);
438
+ }
439
+ }
440
+ try {
441
+ for (let e = 0; e < H.maxAttempts; e += 1) try {
442
+ return await c(e);
443
+ } catch (t) {
444
+ let n = e === H.maxAttempts - 1;
445
+ if (!(K(t) || t instanceof Error && t.message.includes("Retryable HTTP status")) || n) throw F("GraphQL fetch error", t), t;
446
+ await U(W(e, H));
447
+ }
448
+ throw Error("Exhausted retries without returning a result");
449
+ } finally {
450
+ s();
451
+ }
452
+ }
453
+ function ce(e, t) {
454
+ return F("subscription:start", e.name, t), r.create((n) => {
455
+ let r = e.text;
456
+ if (r == null || r === "") return n.error(/* @__PURE__ */ Error("Subscription operation text is empty")), () => {};
457
+ let i = R().subscribe({
458
+ query: r,
459
+ variables: t,
460
+ operationName: e.name
461
+ }, {
462
+ next: (e) => {
463
+ n.next(e);
464
+ },
465
+ error: (e) => {
466
+ let t;
467
+ t = e instanceof Error ? e : /* @__PURE__ */ Error("Subscription error"), n.error(t);
468
+ },
469
+ complete: () => {
470
+ n.complete();
471
+ }
472
+ });
473
+ return () => {
474
+ i();
475
+ };
476
+ });
477
+ }
478
+ function Z() {
479
+ return n.create(X, ce);
480
+ }
481
+ function Q() {
482
+ return c ??= new t({
483
+ getDataID: T,
484
+ relayFieldLogger: w,
485
+ network: Z(),
486
+ store: new a(new i())
487
+ }), c;
488
+ }
489
+ function le() {
490
+ let e = Q(), t = new i();
491
+ e.getStore().publish(t), e.getStore().notify();
492
+ }
493
+ var $ = {
494
+ RelayWebSocketClient: L,
495
+ buildFormData: V,
496
+ calcBackoff: W,
497
+ collectFiles: B,
498
+ fetchFn: X,
499
+ getDataId: T,
500
+ hasUsableTopLevelData: J,
501
+ isNetworkError: K,
502
+ isRetryableStatus: G,
503
+ isUploadable: z,
504
+ shouldThrowGraphQLResponseError: Y
505
+ };
506
+ //#endregion
507
+ export { q as GraphQLResponseError, $ as __test, ae as configureRelayEnvironment, Q as getEnvironment, Z as getNetwork, ne as getRelayOperationActivitySnapshot, M as getRelayTransportSnapshot, P as reconnectRelayWebSocket, ie as refreshRelayWebSocketAuthentication, le as resetRelayStore, re as subscribeRelayOperationActivity, N as subscribeRelayTransport };
508
+
509
+ //# sourceMappingURL=environment.js.map
@@ -0,0 +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>>)\n | undefined;\nlet customDataIdResolver:\n | ((fieldValue: unknown, typeName: string) => string | null)\n | undefined;\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>\n | 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 } 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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"}
@@ -0,0 +1,5 @@
1
+ import { configureRelayEnvironment as e, getEnvironment as t, getNetwork as n, getRelayOperationActivitySnapshot as r, getRelayTransportSnapshot as i, reconnectRelayWebSocket as a, refreshRelayWebSocketAuthentication as o, resetRelayStore as s, subscribeRelayOperationActivity as c, subscribeRelayTransport as l } from "./environment.js";
2
+ import { RelayProvider as u } from "./RelayProvider.js";
3
+ import { configureShortAccessTokenRelayEnvironment as d } from "./shortAccessTokenEnvironment.js";
4
+ import { useRelayOperationActivity as f } from "./useRelayOperationActivity.js";
5
+ export { u as RelayProvider, e as configureRelayEnvironment, d as configureShortAccessTokenRelayEnvironment, t as getEnvironment, n as getNetwork, r as getRelayOperationActivitySnapshot, i as getRelayTransportSnapshot, a as reconnectRelayWebSocket, o as refreshRelayWebSocketAuthentication, s as resetRelayStore, c as subscribeRelayOperationActivity, l as subscribeRelayTransport, f as useRelayOperationActivity };
@@ -0,0 +1,15 @@
1
+ import { configureRelayEnvironment as e, reconnectRelayWebSocket as t, refreshRelayWebSocketAuthentication as n } from "./environment.js";
2
+ import { configureShortAccessTokenRelayEnvironment as r } from "@plumile/auth/relay.js";
3
+ //#region src/shortAccessTokenEnvironment.ts
4
+ function i(i) {
5
+ return r({
6
+ ...i,
7
+ configureRelayEnvironment: e,
8
+ reconnectRelayWebSocket: t,
9
+ refreshRelayWebSocketAuthentication: n
10
+ });
11
+ }
12
+ //#endregion
13
+ export { i as configureShortAccessTokenRelayEnvironment };
14
+
15
+ //# sourceMappingURL=shortAccessTokenEnvironment.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shortAccessTokenEnvironment.js","names":[],"sources":["../../src/shortAccessTokenEnvironment.ts"],"sourcesContent":["import {\n configureShortAccessTokenRelayEnvironment as configureAuthShortAccessTokenRelayEnvironment,\n type ConfigureShortAccessTokenRelayEnvironmentInput,\n type ShortAccessTokenRelayEnvironment,\n} from '@plumile/auth/relay.js';\n\nimport {\n configureRelayEnvironment,\n reconnectRelayWebSocket,\n refreshRelayWebSocketAuthentication,\n} from './environment.js';\n\nexport type ConfigureShortAccessTokenRelayEnvironmentOptions = Omit<\n ConfigureShortAccessTokenRelayEnvironmentInput,\n | 'configureRelayEnvironment'\n | 'reconnectRelayWebSocket'\n | 'refreshRelayWebSocketAuthentication'\n>;\n\n/**\n * Configure the shared Relay environment with short access token auth support.\n */\nexport function configureShortAccessTokenRelayEnvironment(\n input: ConfigureShortAccessTokenRelayEnvironmentOptions,\n): ShortAccessTokenRelayEnvironment {\n return configureAuthShortAccessTokenRelayEnvironment({\n ...input,\n configureRelayEnvironment,\n reconnectRelayWebSocket,\n refreshRelayWebSocketAuthentication,\n });\n}\n"],"mappings":";;;AAsBA,SAAgB,EACd,GACkC;CAClC,OAAO,EAA8C;EACnD,GAAG;EACH;EACA;EACA;CACF,CAAC;AACH"}
@@ -0,0 +1,10 @@
1
+ import { getRelayOperationActivitySnapshot as e, subscribeRelayOperationActivity as t } from "./environment.js";
2
+ import { useSyncExternalStore as n } from "react";
3
+ //#region src/useRelayOperationActivity.ts
4
+ function r() {
5
+ return n(t, e, e);
6
+ }
7
+ //#endregion
8
+ export { r as useRelayOperationActivity };
9
+
10
+ //# sourceMappingURL=useRelayOperationActivity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useRelayOperationActivity.js","names":[],"sources":["../../src/useRelayOperationActivity.ts"],"sourcesContent":["import { useSyncExternalStore } from 'react';\n\nimport {\n getRelayOperationActivitySnapshot,\n subscribeRelayOperationActivity,\n type RelayOperationActivitySnapshot,\n} from './environment.js';\n\n/**\n * Subscribe to pending Relay HTTP operation activity for global route loaders.\n */\nexport function useRelayOperationActivity(): RelayOperationActivitySnapshot {\n return useSyncExternalStore(\n subscribeRelayOperationActivity,\n getRelayOperationActivitySnapshot,\n getRelayOperationActivitySnapshot,\n );\n}\n"],"mappings":";;;AAWA,SAAgB,IAA4D;CAC1E,OAAO,EACL,GACA,GACA,CACF;AACF"}
@@ -0,0 +1,7 @@
1
+ import { type JSX, type ReactNode } from 'react';
2
+ type Props = {
3
+ children: ReactNode;
4
+ };
5
+ export declare const RelayProvider: ({ children }: Props) => JSX.Element;
6
+ export default RelayProvider;
7
+ //# sourceMappingURL=RelayProvider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RelayProvider.d.ts","sourceRoot":"","sources":["../../src/RelayProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAwB,KAAK,GAAG,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAWvE,KAAK,KAAK,GAAG;IACX,QAAQ,EAAE,SAAS,CAAC;CACrB,CAAC;AAEF,eAAO,MAAM,aAAa,GAAI,cAAc,KAAK,KAAG,GAAG,CAAC,OAiBvD,CAAC;AAEF,eAAe,aAAa,CAAC"}
@@ -0,0 +1,22 @@
1
+ type EnvRecord = Record<string, string | boolean | undefined>;
2
+ export type ReadEnvFn = (key: string) => string | undefined;
3
+ export declare function readEnv(key: string): string | undefined;
4
+ export declare function readBooleanEnv(key: string): boolean | undefined;
5
+ export declare function isDevEnv(): boolean;
6
+ interface ResolveEndpointOptions {
7
+ envKeys: readonly string[];
8
+ fallback: string;
9
+ read?: ReadEnvFn;
10
+ }
11
+ export declare function resolveHttpEndpoint(options: ResolveEndpointOptions): string;
12
+ interface ResolveWebsocketEndpointOptions extends ResolveEndpointOptions {
13
+ httpEndpoint: string;
14
+ }
15
+ export declare function resolveWebsocketEndpoint(options: ResolveWebsocketEndpointOptions): string;
16
+ export declare const __test: {
17
+ isDevEnvFromRecord: (env: EnvRecord) => boolean;
18
+ readBooleanEnvFromRecord: (env: EnvRecord, key: string) => boolean | undefined;
19
+ readEnvFromRecord: (env: EnvRecord, key: string) => string | undefined;
20
+ };
21
+ export {};
22
+ //# sourceMappingURL=envHelpers.d.ts.map
@@ -0,0 +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;AA2C5D,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;8BA5Ec,SAAS,KAAG,OAAO;oCAlB7C,SAAS,OACT,MAAM,KACV,OAAO,GAAG,SAAS;6BAjBU,SAAS,OAAO,MAAM,KAAG,MAAM,GAAG,SAAS;CAiH1E,CAAC"}
@@ -0,0 +1,141 @@
1
+ import { Environment, Network } from 'relay-runtime';
2
+ export type RelayTransportStatus = 'idle' | 'configured' | 'reconnecting';
3
+ export interface RelayTransportSnapshot {
4
+ generation: number;
5
+ reason: string | null;
6
+ status: RelayTransportStatus;
7
+ }
8
+ export type RelayOperationKind = 'mutation' | 'query' | 'unknown';
9
+ export type RelayPendingOperation = {
10
+ id: number;
11
+ kind: RelayOperationKind;
12
+ name: string;
13
+ startedAt: number;
14
+ };
15
+ export interface RelayOperationActivitySnapshot {
16
+ generation: number;
17
+ pendingCount: number;
18
+ pendingOperations: readonly RelayPendingOperation[];
19
+ }
20
+ export interface RelayReconnectOptions {
21
+ reason?: string;
22
+ }
23
+ export interface RelayAuthRefreshOptions {
24
+ reason?: string;
25
+ }
26
+ type RelayTransportListener = () => void;
27
+ type RelayOperationActivityListener = () => void;
28
+ type SubscriptionSink = {
29
+ next: (value: unknown) => void;
30
+ error: (error: unknown) => void;
31
+ complete: () => void;
32
+ };
33
+ type ActiveSubscription = {
34
+ payload: {
35
+ query: string;
36
+ variables: Record<string, unknown>;
37
+ operationName: string;
38
+ };
39
+ sink: SubscriptionSink;
40
+ };
41
+ export declare function getRelayTransportSnapshot(): RelayTransportSnapshot;
42
+ export declare function subscribeRelayTransport(listener: RelayTransportListener): () => void;
43
+ export declare function getRelayOperationActivitySnapshot(): RelayOperationActivitySnapshot;
44
+ export declare function subscribeRelayOperationActivity(listener: RelayOperationActivityListener): () => void;
45
+ export declare function reconnectRelayWebSocket(options?: RelayReconnectOptions): void;
46
+ export declare function refreshRelayWebSocketAuthentication(options?: RelayAuthRefreshOptions): Promise<void>;
47
+ export interface RelayEnvironmentConfiguration {
48
+ httpUrl?: string;
49
+ wsUrl?: string;
50
+ logEvents?: boolean;
51
+ getDataId?: (fieldValue: unknown, typeName: string) => string | null;
52
+ getAuthHeaders?: () => Record<string, string> | Promise<Record<string, string>>;
53
+ }
54
+ export declare function configureRelayEnvironment(options?: RelayEnvironmentConfiguration): void;
55
+ declare class RelayWebSocketClient {
56
+ private readonly url;
57
+ private socket;
58
+ private connectPromise;
59
+ private disposed;
60
+ private acknowledged;
61
+ private retryCount;
62
+ private nextId;
63
+ private keepAliveTimer;
64
+ private readonly subscriptions;
65
+ private pendingAuthUpdate;
66
+ constructor(url: string);
67
+ hasActiveConnection(): boolean;
68
+ dispose(): void;
69
+ subscribe(payload: ActiveSubscription['payload'], sink: SubscriptionSink): () => void;
70
+ refreshAuthentication(): Promise<boolean>;
71
+ private connectAndSubscribe;
72
+ private ensureConnected;
73
+ private openSocket;
74
+ private handleMessage;
75
+ private handleClose;
76
+ private scheduleReconnect;
77
+ private resubscribeActiveOperations;
78
+ private unsubscribe;
79
+ private failSubscription;
80
+ private completeSubscription;
81
+ private startKeepAlive;
82
+ private stopKeepAlive;
83
+ private resolvePendingAuthUpdate;
84
+ private send;
85
+ }
86
+ declare function isUploadable(value: unknown): value is File | Blob;
87
+ interface FileRef {
88
+ path: string;
89
+ file: File | Blob;
90
+ }
91
+ declare function collectFiles(value: unknown, path: string, acc: FileRef[]): unknown;
92
+ declare function buildFormData(query: string, variables: Record<string, unknown>): FormData;
93
+ interface RetryOptions {
94
+ maxAttempts: number;
95
+ baseDelayMs: number;
96
+ maxDelayMs: number;
97
+ fetchTimeoutMs: number;
98
+ }
99
+ declare function calcBackoff(attempt: number, opts: RetryOptions): number;
100
+ declare function isRetryableStatus(status: number): boolean;
101
+ declare function isNetworkError(err: unknown): boolean;
102
+ interface GraphQLResponseErrorItem {
103
+ [key: string]: unknown;
104
+ message: string;
105
+ path?: readonly unknown[];
106
+ }
107
+ interface GraphQLResponseShape<T = unknown> {
108
+ data?: T;
109
+ errors?: GraphQLResponseErrorItem[];
110
+ extensions?: Record<string, unknown>;
111
+ }
112
+ export declare class GraphQLResponseError extends Error {
113
+ readonly errors: readonly GraphQLResponseErrorItem[];
114
+ readonly response: GraphQLResponseShape;
115
+ constructor(errors: readonly GraphQLResponseErrorItem[], response: GraphQLResponseShape);
116
+ }
117
+ declare function hasUsableTopLevelData(data: unknown): boolean;
118
+ declare function shouldThrowGraphQLResponseError(response: GraphQLResponseShape): boolean;
119
+ declare function fetchFn(request: {
120
+ name?: string | null;
121
+ operationKind?: unknown;
122
+ text: string | null | undefined;
123
+ }, variables: Record<string, unknown>, _cacheConfig: unknown, _uploadables: unknown): Promise<GraphQLResponseShape>;
124
+ export declare function getNetwork(): ReturnType<typeof Network.create>;
125
+ export declare function getEnvironment(): Environment;
126
+ export declare function resetRelayStore(): void;
127
+ export declare const __test: {
128
+ RelayWebSocketClient: typeof RelayWebSocketClient;
129
+ buildFormData: typeof buildFormData;
130
+ calcBackoff: typeof calcBackoff;
131
+ collectFiles: typeof collectFiles;
132
+ fetchFn: typeof fetchFn;
133
+ getDataId: (fieldValue: unknown, typeName: string) => string | null;
134
+ hasUsableTopLevelData: typeof hasUsableTopLevelData;
135
+ isNetworkError: typeof isNetworkError;
136
+ isRetryableStatus: typeof isRetryableStatus;
137
+ isUploadable: typeof isUploadable;
138
+ shouldThrowGraphQLResponseError: typeof shouldThrowGraphQLResponseError;
139
+ };
140
+ export {};
141
+ //# sourceMappingURL=environment.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"environment.d.ts","sourceRoot":"","sources":["../../src/environment.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ export { RelayProvider } from './RelayProvider.js';
2
+ export { configureRelayEnvironment, getEnvironment, getNetwork, getRelayOperationActivitySnapshot, getRelayTransportSnapshot, reconnectRelayWebSocket, refreshRelayWebSocketAuthentication, resetRelayStore, subscribeRelayOperationActivity, subscribeRelayTransport, type RelayAuthRefreshOptions, type RelayEnvironmentConfiguration, type RelayOperationActivitySnapshot, type RelayOperationKind, type RelayPendingOperation, type RelayReconnectOptions, type RelayTransportSnapshot, type RelayTransportStatus, } from './environment.js';
3
+ export { configureShortAccessTokenRelayEnvironment, type ConfigureShortAccessTokenRelayEnvironmentOptions, } from './shortAccessTokenEnvironment.js';
4
+ export { useRelayOperationActivity } from './useRelayOperationActivity.js';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EACL,yBAAyB,EACzB,cAAc,EACd,UAAU,EACV,iCAAiC,EACjC,yBAAyB,EACzB,uBAAuB,EACvB,mCAAmC,EACnC,eAAe,EACf,+BAA+B,EAC/B,uBAAuB,EACvB,KAAK,uBAAuB,EAC5B,KAAK,6BAA6B,EAClC,KAAK,8BAA8B,EACnC,KAAK,kBAAkB,EACvB,KAAK,qBAAqB,EAC1B,KAAK,qBAAqB,EAC1B,KAAK,sBAAsB,EAC3B,KAAK,oBAAoB,GAC1B,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,yCAAyC,EACzC,KAAK,gDAAgD,GACtD,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EAAE,yBAAyB,EAAE,MAAM,gCAAgC,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { type ConfigureShortAccessTokenRelayEnvironmentInput, type ShortAccessTokenRelayEnvironment } from '@plumile/auth/relay.js';
2
+ export type ConfigureShortAccessTokenRelayEnvironmentOptions = Omit<ConfigureShortAccessTokenRelayEnvironmentInput, 'configureRelayEnvironment' | 'reconnectRelayWebSocket' | 'refreshRelayWebSocketAuthentication'>;
3
+ export declare function configureShortAccessTokenRelayEnvironment(input: ConfigureShortAccessTokenRelayEnvironmentOptions): ShortAccessTokenRelayEnvironment;
4
+ //# sourceMappingURL=shortAccessTokenEnvironment.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shortAccessTokenEnvironment.d.ts","sourceRoot":"","sources":["../../src/shortAccessTokenEnvironment.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,8CAA8C,EACnD,KAAK,gCAAgC,EACtC,MAAM,wBAAwB,CAAC;AAQhC,MAAM,MAAM,gDAAgD,GAAG,IAAI,CACjE,8CAA8C,EAC5C,2BAA2B,GAC3B,yBAAyB,GACzB,qCAAqC,CACxC,CAAC;AAKF,wBAAgB,yCAAyC,CACvD,KAAK,EAAE,gDAAgD,GACtD,gCAAgC,CAOlC"}
@@ -0,0 +1,3 @@
1
+ import { type RelayOperationActivitySnapshot } from './environment.js';
2
+ export declare function useRelayOperationActivity(): RelayOperationActivitySnapshot;
3
+ //# sourceMappingURL=useRelayOperationActivity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useRelayOperationActivity.d.ts","sourceRoot":"","sources":["../../src/useRelayOperationActivity.ts"],"names":[],"mappings":"AAEA,OAAO,EAGL,KAAK,8BAA8B,EACpC,MAAM,kBAAkB,CAAC;AAK1B,wBAAgB,yBAAyB,IAAI,8BAA8B,CAM1E"}
package/package.json ADDED
@@ -0,0 +1,89 @@
1
+ {
2
+ "name": "@plumile/relay",
3
+ "version": "0.1.181",
4
+ "description": "Shared Relay runtime helpers for Plumile applications",
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "main": "lib/esm/index.js",
8
+ "module": "lib/esm/index.js",
9
+ "types": "lib/types/index.d.ts",
10
+ "typings": "lib/types/index.d.ts",
11
+ "exports": {
12
+ ".": {
13
+ "types": "./lib/types/index.d.ts",
14
+ "import": "./lib/esm/index.js",
15
+ "default": "./lib/esm/index.js"
16
+ },
17
+ "./*.js": {
18
+ "types": "./lib/types/*.d.ts",
19
+ "import": "./lib/esm/*.js",
20
+ "default": "./lib/esm/*.js"
21
+ },
22
+ "./*": {
23
+ "types": "./lib/types/*.d.ts",
24
+ "import": "./lib/esm/*.js",
25
+ "default": "./lib/esm/*.js"
26
+ },
27
+ "./package.json": "./package.json"
28
+ },
29
+ "sideEffects": false,
30
+ "author": "Olivier Hardy <olivier@plumile.com>",
31
+ "homepage": "https://gitlab.com/plumile/js/-/tree/main/packages/relay",
32
+ "repository": {
33
+ "type": "git",
34
+ "url": "https://gitlab.com/plumile/js",
35
+ "directory": "packages/relay"
36
+ },
37
+ "bugs": {
38
+ "url": "https://gitlab.com/plumile/js/-/issues"
39
+ },
40
+ "keywords": [
41
+ "relay",
42
+ "react",
43
+ "graphql"
44
+ ],
45
+ "engines": {
46
+ "node": ">=21.0.0",
47
+ "npm": ">=8.0.0"
48
+ },
49
+ "scripts": {
50
+ "build:package": "./tools/build-package.sh",
51
+ "prebuild:package:esm": "npm run --workspace @plumile/auth build:package",
52
+ "build:package:esm": "vite build",
53
+ "build:package:types": "tsc --build tsconfig.types.json",
54
+ "check:build-package": "tsc --noEmit",
55
+ "clean": "rimraf lib && rimraf *.tsbuildinfo",
56
+ "test:build-package": "./tools/test-build-package.sh"
57
+ },
58
+ "dependencies": {
59
+ "graphql-ws": "6.0.8",
60
+ "relay-runtime": "^21.0.1",
61
+ "tslib": "^2.8.1"
62
+ },
63
+ "devDependencies": {
64
+ "@plumile/auth": "^0.1.181",
65
+ "@types/react": "19.2.17",
66
+ "@types/react-dom": "19.2.3",
67
+ "@types/relay-runtime": "20.1.1",
68
+ "react": "19.2.7",
69
+ "react-dom": "19.2.7",
70
+ "react-relay": "21.0.1",
71
+ "relay-test-utils": "21.0.1",
72
+ "rimraf": "6.1.3",
73
+ "typescript": "6.0.3"
74
+ },
75
+ "peerDependencies": {
76
+ "@plumile/auth": "^0.1.179",
77
+ "react": "^19.2.7",
78
+ "react-dom": "^19.2.7",
79
+ "react-relay": "^21.0.1",
80
+ "relay-runtime": "^21.0.1"
81
+ },
82
+ "files": [
83
+ "lib",
84
+ "README.md"
85
+ ],
86
+ "publishConfig": {
87
+ "access": "public"
88
+ }
89
+ }