@0xobelisk/graphql-client 1.2.0-pre.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs ADDED
@@ -0,0 +1,1560 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
4
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
5
+ }) : x)(function(x) {
6
+ if (typeof require !== "undefined")
7
+ return require.apply(this, arguments);
8
+ throw Error('Dynamic require of "' + x + '" is not supported');
9
+ });
10
+ var __publicField = (obj, key, value) => {
11
+ __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
12
+ return value;
13
+ };
14
+
15
+ // src/client.ts
16
+ import {
17
+ ApolloClient,
18
+ InMemoryCache,
19
+ gql,
20
+ createHttpLink,
21
+ split,
22
+ Observable,
23
+ from
24
+ } from "@apollo/client";
25
+ import { RetryLink } from "@apollo/client/link/retry";
26
+ import { GraphQLWsLink } from "@apollo/client/link/subscriptions";
27
+ import { getMainDefinition } from "@apollo/client/utilities";
28
+
29
+ // ../../node_modules/.pnpm/graphql-ws@6.0.5_graphql@15.10.1_ws@8.18.2/node_modules/graphql-ws/dist/common-CGW11Fyb.js
30
+ function extendedTypeof(val) {
31
+ if (val === null) {
32
+ return "null";
33
+ }
34
+ if (Array.isArray(val)) {
35
+ return "array";
36
+ }
37
+ return typeof val;
38
+ }
39
+ function isObject(val) {
40
+ return extendedTypeof(val) === "object";
41
+ }
42
+ function areGraphQLFormattedErrors(obj) {
43
+ return Array.isArray(obj) && // must be at least one error
44
+ obj.length > 0 && // error has at least a message
45
+ obj.every((ob) => "message" in ob);
46
+ }
47
+ function limitCloseReason(reason, whenTooLong) {
48
+ return reason.length < 124 ? reason : whenTooLong;
49
+ }
50
+ var GRAPHQL_TRANSPORT_WS_PROTOCOL = "graphql-transport-ws";
51
+ var CloseCode = /* @__PURE__ */ ((CloseCode2) => {
52
+ CloseCode2[CloseCode2["InternalServerError"] = 4500] = "InternalServerError";
53
+ CloseCode2[CloseCode2["InternalClientError"] = 4005] = "InternalClientError";
54
+ CloseCode2[CloseCode2["BadRequest"] = 4400] = "BadRequest";
55
+ CloseCode2[CloseCode2["BadResponse"] = 4004] = "BadResponse";
56
+ CloseCode2[CloseCode2["Unauthorized"] = 4401] = "Unauthorized";
57
+ CloseCode2[CloseCode2["Forbidden"] = 4403] = "Forbidden";
58
+ CloseCode2[CloseCode2["SubprotocolNotAcceptable"] = 4406] = "SubprotocolNotAcceptable";
59
+ CloseCode2[CloseCode2["ConnectionInitialisationTimeout"] = 4408] = "ConnectionInitialisationTimeout";
60
+ CloseCode2[CloseCode2["ConnectionAcknowledgementTimeout"] = 4504] = "ConnectionAcknowledgementTimeout";
61
+ CloseCode2[CloseCode2["SubscriberAlreadyExists"] = 4409] = "SubscriberAlreadyExists";
62
+ CloseCode2[CloseCode2["TooManyInitialisationRequests"] = 4429] = "TooManyInitialisationRequests";
63
+ return CloseCode2;
64
+ })(CloseCode || {});
65
+ var MessageType = /* @__PURE__ */ ((MessageType2) => {
66
+ MessageType2["ConnectionInit"] = "connection_init";
67
+ MessageType2["ConnectionAck"] = "connection_ack";
68
+ MessageType2["Ping"] = "ping";
69
+ MessageType2["Pong"] = "pong";
70
+ MessageType2["Subscribe"] = "subscribe";
71
+ MessageType2["Next"] = "next";
72
+ MessageType2["Error"] = "error";
73
+ MessageType2["Complete"] = "complete";
74
+ return MessageType2;
75
+ })(MessageType || {});
76
+ function validateMessage(val) {
77
+ if (!isObject(val)) {
78
+ throw new Error(
79
+ `Message is expected to be an object, but got ${extendedTypeof(val)}`
80
+ );
81
+ }
82
+ if (!val.type) {
83
+ throw new Error(`Message is missing the 'type' property`);
84
+ }
85
+ if (typeof val.type !== "string") {
86
+ throw new Error(
87
+ `Message is expects the 'type' property to be a string, but got ${extendedTypeof(
88
+ val.type
89
+ )}`
90
+ );
91
+ }
92
+ switch (val.type) {
93
+ case "connection_init":
94
+ case "connection_ack":
95
+ case "ping":
96
+ case "pong": {
97
+ if (val.payload != null && !isObject(val.payload)) {
98
+ throw new Error(
99
+ `"${val.type}" message expects the 'payload' property to be an object or nullish or missing, but got "${val.payload}"`
100
+ );
101
+ }
102
+ break;
103
+ }
104
+ case "subscribe": {
105
+ if (typeof val.id !== "string") {
106
+ throw new Error(
107
+ `"${val.type}" message expects the 'id' property to be a string, but got ${extendedTypeof(
108
+ val.id
109
+ )}`
110
+ );
111
+ }
112
+ if (!val.id) {
113
+ throw new Error(
114
+ `"${val.type}" message requires a non-empty 'id' property`
115
+ );
116
+ }
117
+ if (!isObject(val.payload)) {
118
+ throw new Error(
119
+ `"${val.type}" message expects the 'payload' property to be an object, but got ${extendedTypeof(
120
+ val.payload
121
+ )}`
122
+ );
123
+ }
124
+ if (typeof val.payload.query !== "string") {
125
+ throw new Error(
126
+ `"${val.type}" message payload expects the 'query' property to be a string, but got ${extendedTypeof(
127
+ val.payload.query
128
+ )}`
129
+ );
130
+ }
131
+ if (val.payload.variables != null && !isObject(val.payload.variables)) {
132
+ throw new Error(
133
+ `"${val.type}" message payload expects the 'variables' property to be a an object or nullish or missing, but got ${extendedTypeof(
134
+ val.payload.variables
135
+ )}`
136
+ );
137
+ }
138
+ if (val.payload.operationName != null && extendedTypeof(val.payload.operationName) !== "string") {
139
+ throw new Error(
140
+ `"${val.type}" message payload expects the 'operationName' property to be a string or nullish or missing, but got ${extendedTypeof(
141
+ val.payload.operationName
142
+ )}`
143
+ );
144
+ }
145
+ if (val.payload.extensions != null && !isObject(val.payload.extensions)) {
146
+ throw new Error(
147
+ `"${val.type}" message payload expects the 'extensions' property to be a an object or nullish or missing, but got ${extendedTypeof(
148
+ val.payload.extensions
149
+ )}`
150
+ );
151
+ }
152
+ break;
153
+ }
154
+ case "next": {
155
+ if (typeof val.id !== "string") {
156
+ throw new Error(
157
+ `"${val.type}" message expects the 'id' property to be a string, but got ${extendedTypeof(
158
+ val.id
159
+ )}`
160
+ );
161
+ }
162
+ if (!val.id) {
163
+ throw new Error(
164
+ `"${val.type}" message requires a non-empty 'id' property`
165
+ );
166
+ }
167
+ if (!isObject(val.payload)) {
168
+ throw new Error(
169
+ `"${val.type}" message expects the 'payload' property to be an object, but got ${extendedTypeof(
170
+ val.payload
171
+ )}`
172
+ );
173
+ }
174
+ break;
175
+ }
176
+ case "error": {
177
+ if (typeof val.id !== "string") {
178
+ throw new Error(
179
+ `"${val.type}" message expects the 'id' property to be a string, but got ${extendedTypeof(
180
+ val.id
181
+ )}`
182
+ );
183
+ }
184
+ if (!val.id) {
185
+ throw new Error(
186
+ `"${val.type}" message requires a non-empty 'id' property`
187
+ );
188
+ }
189
+ if (!areGraphQLFormattedErrors(val.payload)) {
190
+ throw new Error(
191
+ `"${val.type}" message expects the 'payload' property to be an array of GraphQL errors, but got ${JSON.stringify(
192
+ val.payload
193
+ )}`
194
+ );
195
+ }
196
+ break;
197
+ }
198
+ case "complete": {
199
+ if (typeof val.id !== "string") {
200
+ throw new Error(
201
+ `"${val.type}" message expects the 'id' property to be a string, but got ${extendedTypeof(
202
+ val.id
203
+ )}`
204
+ );
205
+ }
206
+ if (!val.id) {
207
+ throw new Error(
208
+ `"${val.type}" message requires a non-empty 'id' property`
209
+ );
210
+ }
211
+ break;
212
+ }
213
+ default:
214
+ throw new Error(`Invalid message 'type' property "${val.type}"`);
215
+ }
216
+ return val;
217
+ }
218
+ function parseMessage(data, reviver) {
219
+ return validateMessage(
220
+ typeof data === "string" ? JSON.parse(data, reviver) : data
221
+ );
222
+ }
223
+ function stringifyMessage(msg, replacer) {
224
+ validateMessage(msg);
225
+ return JSON.stringify(msg, replacer);
226
+ }
227
+
228
+ // ../../node_modules/.pnpm/graphql-ws@6.0.5_graphql@15.10.1_ws@8.18.2/node_modules/graphql-ws/dist/client.js
229
+ function createClient(options) {
230
+ const {
231
+ url,
232
+ connectionParams,
233
+ lazy = true,
234
+ onNonLazyError = console.error,
235
+ lazyCloseTimeout: lazyCloseTimeoutMs = 0,
236
+ keepAlive = 0,
237
+ disablePong,
238
+ connectionAckWaitTimeout = 0,
239
+ retryAttempts = 5,
240
+ retryWait = async function randomisedExponentialBackoff(retries2) {
241
+ const retryDelaySeconds = Math.pow(2, retries2);
242
+ await new Promise(
243
+ (resolve) => setTimeout(
244
+ resolve,
245
+ retryDelaySeconds * 1e3 + // add random timeout from 300ms to 3s
246
+ Math.floor(Math.random() * (3e3 - 300) + 300)
247
+ )
248
+ );
249
+ },
250
+ shouldRetry = isLikeCloseEvent,
251
+ on,
252
+ webSocketImpl,
253
+ /**
254
+ * Generates a v4 UUID to be used as the ID using `Math`
255
+ * as the random number generator. Supply your own generator
256
+ * in case you need more uniqueness.
257
+ *
258
+ * Reference: https://gist.github.com/jed/982883
259
+ */
260
+ generateID = function generateUUID() {
261
+ return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
262
+ const r = Math.random() * 16 | 0, v = c == "x" ? r : r & 3 | 8;
263
+ return v.toString(16);
264
+ });
265
+ },
266
+ jsonMessageReplacer: replacer,
267
+ jsonMessageReviver: reviver
268
+ } = options;
269
+ let ws;
270
+ if (webSocketImpl) {
271
+ if (!isWebSocket(webSocketImpl)) {
272
+ throw new Error("Invalid WebSocket implementation provided");
273
+ }
274
+ ws = webSocketImpl;
275
+ } else if (typeof WebSocket !== "undefined") {
276
+ ws = WebSocket;
277
+ } else if (typeof global !== "undefined") {
278
+ ws = global.WebSocket || // @ts-expect-error: Support more browsers
279
+ global.MozWebSocket;
280
+ } else if (typeof window !== "undefined") {
281
+ ws = window.WebSocket || // @ts-expect-error: Support more browsers
282
+ window.MozWebSocket;
283
+ }
284
+ if (!ws)
285
+ throw new Error(
286
+ "WebSocket implementation missing; on Node you can `import WebSocket from 'ws';` and pass `webSocketImpl: WebSocket` to `createClient`"
287
+ );
288
+ const WebSocketImpl = ws;
289
+ const emitter = (() => {
290
+ const message = /* @__PURE__ */ (() => {
291
+ const listeners2 = {};
292
+ return {
293
+ on(id, listener) {
294
+ listeners2[id] = listener;
295
+ return () => {
296
+ delete listeners2[id];
297
+ };
298
+ },
299
+ emit(message2) {
300
+ if ("id" in message2)
301
+ listeners2[message2.id]?.(message2);
302
+ }
303
+ };
304
+ })();
305
+ const listeners = {
306
+ connecting: on?.connecting ? [on.connecting] : [],
307
+ opened: on?.opened ? [on.opened] : [],
308
+ connected: on?.connected ? [on.connected] : [],
309
+ ping: on?.ping ? [on.ping] : [],
310
+ pong: on?.pong ? [on.pong] : [],
311
+ message: on?.message ? [message.emit, on.message] : [message.emit],
312
+ closed: on?.closed ? [on.closed] : [],
313
+ error: on?.error ? [on.error] : []
314
+ };
315
+ return {
316
+ onMessage: message.on,
317
+ on(event, listener) {
318
+ const l = listeners[event];
319
+ l.push(listener);
320
+ return () => {
321
+ l.splice(l.indexOf(listener), 1);
322
+ };
323
+ },
324
+ emit(event, ...args) {
325
+ for (const listener of [...listeners[event]]) {
326
+ listener(...args);
327
+ }
328
+ }
329
+ };
330
+ })();
331
+ function errorOrClosed(cb) {
332
+ const listening = [
333
+ // errors are fatal and more critical than close events, throw them first
334
+ emitter.on("error", (err) => {
335
+ listening.forEach((unlisten) => unlisten());
336
+ cb(err);
337
+ }),
338
+ // closes can be graceful and not fatal, throw them second (if error didnt throw)
339
+ emitter.on("closed", (event) => {
340
+ listening.forEach((unlisten) => unlisten());
341
+ cb(event);
342
+ })
343
+ ];
344
+ }
345
+ let connecting, locks = 0, lazyCloseTimeout, retrying = false, retries = 0, disposed = false;
346
+ async function connect() {
347
+ clearTimeout(lazyCloseTimeout);
348
+ const [socket, throwOnClose] = await (connecting ?? (connecting = new Promise(
349
+ (connected, denied) => (async () => {
350
+ if (retrying) {
351
+ await retryWait(retries);
352
+ if (!locks) {
353
+ connecting = void 0;
354
+ return denied({ code: 1e3, reason: "All Subscriptions Gone" });
355
+ }
356
+ retries++;
357
+ }
358
+ emitter.emit("connecting", retrying);
359
+ const socket2 = new WebSocketImpl(
360
+ typeof url === "function" ? await url() : url,
361
+ GRAPHQL_TRANSPORT_WS_PROTOCOL
362
+ );
363
+ let connectionAckTimeout, queuedPing;
364
+ function enqueuePing() {
365
+ if (isFinite(keepAlive) && keepAlive > 0) {
366
+ clearTimeout(queuedPing);
367
+ queuedPing = setTimeout(() => {
368
+ if (socket2.readyState === WebSocketImpl.OPEN) {
369
+ socket2.send(stringifyMessage({ type: MessageType.Ping }));
370
+ emitter.emit("ping", false, void 0);
371
+ }
372
+ }, keepAlive);
373
+ }
374
+ }
375
+ errorOrClosed((errOrEvent) => {
376
+ connecting = void 0;
377
+ clearTimeout(connectionAckTimeout);
378
+ clearTimeout(queuedPing);
379
+ denied(errOrEvent);
380
+ if (errOrEvent instanceof TerminatedCloseEvent) {
381
+ socket2.close(4499, "Terminated");
382
+ socket2.onerror = null;
383
+ socket2.onclose = null;
384
+ }
385
+ });
386
+ socket2.onerror = (err) => emitter.emit("error", err);
387
+ socket2.onclose = (event) => emitter.emit("closed", event);
388
+ socket2.onopen = async () => {
389
+ try {
390
+ emitter.emit("opened", socket2);
391
+ const payload = typeof connectionParams === "function" ? await connectionParams() : connectionParams;
392
+ if (socket2.readyState !== WebSocketImpl.OPEN)
393
+ return;
394
+ socket2.send(
395
+ stringifyMessage(
396
+ payload ? {
397
+ type: MessageType.ConnectionInit,
398
+ payload
399
+ } : {
400
+ type: MessageType.ConnectionInit
401
+ // payload is completely absent if not provided
402
+ },
403
+ replacer
404
+ )
405
+ );
406
+ if (isFinite(connectionAckWaitTimeout) && connectionAckWaitTimeout > 0) {
407
+ connectionAckTimeout = setTimeout(() => {
408
+ socket2.close(
409
+ CloseCode.ConnectionAcknowledgementTimeout,
410
+ "Connection acknowledgement timeout"
411
+ );
412
+ }, connectionAckWaitTimeout);
413
+ }
414
+ enqueuePing();
415
+ } catch (err) {
416
+ emitter.emit("error", err);
417
+ socket2.close(
418
+ CloseCode.InternalClientError,
419
+ limitCloseReason(
420
+ err instanceof Error ? err.message : String(err),
421
+ "Internal client error"
422
+ )
423
+ );
424
+ }
425
+ };
426
+ let acknowledged = false;
427
+ socket2.onmessage = ({ data }) => {
428
+ try {
429
+ const message = parseMessage(data, reviver);
430
+ emitter.emit("message", message);
431
+ if (message.type === "ping" || message.type === "pong") {
432
+ emitter.emit(message.type, true, message.payload);
433
+ if (message.type === "pong") {
434
+ enqueuePing();
435
+ } else if (!disablePong) {
436
+ socket2.send(
437
+ stringifyMessage(
438
+ message.payload ? {
439
+ type: MessageType.Pong,
440
+ payload: message.payload
441
+ } : {
442
+ type: MessageType.Pong
443
+ // payload is completely absent if not provided
444
+ }
445
+ )
446
+ );
447
+ emitter.emit("pong", false, message.payload);
448
+ }
449
+ return;
450
+ }
451
+ if (acknowledged)
452
+ return;
453
+ if (message.type !== MessageType.ConnectionAck)
454
+ throw new Error(
455
+ `First message cannot be of type ${message.type}`
456
+ );
457
+ clearTimeout(connectionAckTimeout);
458
+ acknowledged = true;
459
+ emitter.emit("connected", socket2, message.payload, retrying);
460
+ retrying = false;
461
+ retries = 0;
462
+ connected([
463
+ socket2,
464
+ new Promise((_, reject) => errorOrClosed(reject))
465
+ ]);
466
+ } catch (err) {
467
+ socket2.onmessage = null;
468
+ emitter.emit("error", err);
469
+ socket2.close(
470
+ CloseCode.BadResponse,
471
+ limitCloseReason(
472
+ err instanceof Error ? err.message : String(err),
473
+ "Bad response"
474
+ )
475
+ );
476
+ }
477
+ };
478
+ })()
479
+ )));
480
+ if (socket.readyState === WebSocketImpl.CLOSING)
481
+ await throwOnClose;
482
+ let release = () => {
483
+ };
484
+ const released = new Promise((resolve) => release = resolve);
485
+ return [
486
+ socket,
487
+ release,
488
+ Promise.race([
489
+ // wait for
490
+ released.then(() => {
491
+ if (!locks) {
492
+ const complete = () => socket.close(1e3, "Normal Closure");
493
+ if (isFinite(lazyCloseTimeoutMs) && lazyCloseTimeoutMs > 0) {
494
+ lazyCloseTimeout = setTimeout(() => {
495
+ if (socket.readyState === WebSocketImpl.OPEN)
496
+ complete();
497
+ }, lazyCloseTimeoutMs);
498
+ } else {
499
+ complete();
500
+ }
501
+ }
502
+ }),
503
+ // or
504
+ throwOnClose
505
+ ])
506
+ ];
507
+ }
508
+ function shouldRetryConnectOrThrow(errOrCloseEvent) {
509
+ if (isLikeCloseEvent(errOrCloseEvent) && (isFatalInternalCloseCode(errOrCloseEvent.code) || [
510
+ CloseCode.InternalServerError,
511
+ CloseCode.InternalClientError,
512
+ CloseCode.BadRequest,
513
+ CloseCode.BadResponse,
514
+ CloseCode.Unauthorized,
515
+ // CloseCode.Forbidden, might grant access out after retry
516
+ CloseCode.SubprotocolNotAcceptable,
517
+ // CloseCode.ConnectionInitialisationTimeout, might not time out after retry
518
+ // CloseCode.ConnectionAcknowledgementTimeout, might not time out after retry
519
+ CloseCode.SubscriberAlreadyExists,
520
+ CloseCode.TooManyInitialisationRequests
521
+ // 4499, // Terminated, probably because the socket froze, we want to retry
522
+ ].includes(errOrCloseEvent.code)))
523
+ throw errOrCloseEvent;
524
+ if (disposed)
525
+ return false;
526
+ if (isLikeCloseEvent(errOrCloseEvent) && errOrCloseEvent.code === 1e3)
527
+ return locks > 0;
528
+ if (!retryAttempts || retries >= retryAttempts)
529
+ throw errOrCloseEvent;
530
+ if (!shouldRetry(errOrCloseEvent))
531
+ throw errOrCloseEvent;
532
+ return retrying = true;
533
+ }
534
+ if (!lazy) {
535
+ (async () => {
536
+ locks++;
537
+ for (; ; ) {
538
+ try {
539
+ const [, , throwOnClose] = await connect();
540
+ await throwOnClose;
541
+ } catch (errOrCloseEvent) {
542
+ try {
543
+ if (!shouldRetryConnectOrThrow(errOrCloseEvent))
544
+ return;
545
+ } catch (errOrCloseEvent2) {
546
+ return onNonLazyError?.(errOrCloseEvent2);
547
+ }
548
+ }
549
+ }
550
+ })();
551
+ }
552
+ function subscribe(payload, sink) {
553
+ const id = generateID(payload);
554
+ let done = false, errored = false, releaser = () => {
555
+ locks--;
556
+ done = true;
557
+ };
558
+ (async () => {
559
+ locks++;
560
+ for (; ; ) {
561
+ try {
562
+ const [socket, release, waitForReleaseOrThrowOnClose] = await connect();
563
+ if (done)
564
+ return release();
565
+ const unlisten = emitter.onMessage(id, (message) => {
566
+ switch (message.type) {
567
+ case MessageType.Next: {
568
+ sink.next(message.payload);
569
+ return;
570
+ }
571
+ case MessageType.Error: {
572
+ errored = true, done = true;
573
+ sink.error(message.payload);
574
+ releaser();
575
+ return;
576
+ }
577
+ case MessageType.Complete: {
578
+ done = true;
579
+ releaser();
580
+ return;
581
+ }
582
+ }
583
+ });
584
+ socket.send(
585
+ stringifyMessage(
586
+ {
587
+ id,
588
+ type: MessageType.Subscribe,
589
+ payload
590
+ },
591
+ replacer
592
+ )
593
+ );
594
+ releaser = () => {
595
+ if (!done && socket.readyState === WebSocketImpl.OPEN)
596
+ socket.send(
597
+ stringifyMessage(
598
+ {
599
+ id,
600
+ type: MessageType.Complete
601
+ },
602
+ replacer
603
+ )
604
+ );
605
+ locks--;
606
+ done = true;
607
+ release();
608
+ };
609
+ await waitForReleaseOrThrowOnClose.finally(unlisten);
610
+ return;
611
+ } catch (errOrCloseEvent) {
612
+ if (!shouldRetryConnectOrThrow(errOrCloseEvent))
613
+ return;
614
+ }
615
+ }
616
+ })().then(() => {
617
+ if (!errored)
618
+ sink.complete();
619
+ }).catch((err) => {
620
+ sink.error(err);
621
+ });
622
+ return () => {
623
+ if (!done)
624
+ releaser();
625
+ };
626
+ }
627
+ return {
628
+ on: emitter.on,
629
+ subscribe,
630
+ iterate(request) {
631
+ const pending = [];
632
+ const deferred = {
633
+ done: false,
634
+ error: null,
635
+ resolve: () => {
636
+ }
637
+ };
638
+ const dispose = subscribe(request, {
639
+ next(val) {
640
+ pending.push(val);
641
+ deferred.resolve();
642
+ },
643
+ error(err) {
644
+ deferred.done = true;
645
+ deferred.error = err;
646
+ deferred.resolve();
647
+ },
648
+ complete() {
649
+ deferred.done = true;
650
+ deferred.resolve();
651
+ }
652
+ });
653
+ const iterator = async function* iterator2() {
654
+ for (; ; ) {
655
+ if (!pending.length) {
656
+ await new Promise((resolve) => deferred.resolve = resolve);
657
+ }
658
+ while (pending.length) {
659
+ yield pending.shift();
660
+ }
661
+ if (deferred.error) {
662
+ throw deferred.error;
663
+ }
664
+ if (deferred.done) {
665
+ return;
666
+ }
667
+ }
668
+ }();
669
+ iterator.throw = async (err) => {
670
+ if (!deferred.done) {
671
+ deferred.done = true;
672
+ deferred.error = err;
673
+ deferred.resolve();
674
+ }
675
+ return { done: true, value: void 0 };
676
+ };
677
+ iterator.return = async () => {
678
+ dispose();
679
+ return { done: true, value: void 0 };
680
+ };
681
+ return iterator;
682
+ },
683
+ async dispose() {
684
+ disposed = true;
685
+ if (connecting) {
686
+ const [socket] = await connecting;
687
+ socket.close(1e3, "Normal Closure");
688
+ }
689
+ },
690
+ terminate() {
691
+ if (connecting) {
692
+ emitter.emit("closed", new TerminatedCloseEvent());
693
+ }
694
+ }
695
+ };
696
+ }
697
+ var TerminatedCloseEvent = class extends Error {
698
+ constructor() {
699
+ super(...arguments);
700
+ __publicField(this, "name", "TerminatedCloseEvent");
701
+ __publicField(this, "message", "4499: Terminated");
702
+ __publicField(this, "code", 4499);
703
+ __publicField(this, "reason", "Terminated");
704
+ __publicField(this, "wasClean", false);
705
+ }
706
+ };
707
+ function isLikeCloseEvent(val) {
708
+ return isObject(val) && "code" in val && "reason" in val;
709
+ }
710
+ function isFatalInternalCloseCode(code) {
711
+ if ([
712
+ 1e3,
713
+ // Normal Closure is not an erroneous close code
714
+ 1001,
715
+ // Going Away
716
+ 1006,
717
+ // Abnormal Closure
718
+ 1005,
719
+ // No Status Received
720
+ 1012,
721
+ // Service Restart
722
+ 1013,
723
+ // Try Again Later
724
+ 1014
725
+ // Bad Gateway
726
+ ].includes(code))
727
+ return false;
728
+ return code >= 1e3 && code <= 1999;
729
+ }
730
+ function isWebSocket(val) {
731
+ return typeof val === "function" && "constructor" in val && "CLOSED" in val && "CLOSING" in val && "CONNECTING" in val && "OPEN" in val;
732
+ }
733
+
734
+ // ../../node_modules/.pnpm/graphql-ws@6.0.5_graphql@15.10.1_ws@8.18.2/node_modules/graphql-ws/dist/index.js
735
+ import "graphql";
736
+
737
+ // src/client.ts
738
+ import pluralize from "pluralize";
739
+ function mapCachePolicyToFetchPolicy(cachePolicy) {
740
+ switch (cachePolicy) {
741
+ case "cache-first":
742
+ return "cache-first";
743
+ case "network-only":
744
+ return "network-only";
745
+ case "cache-only":
746
+ return "cache-only";
747
+ case "no-cache":
748
+ return "no-cache";
749
+ case "standby":
750
+ return "standby";
751
+ default:
752
+ return "cache-first";
753
+ }
754
+ }
755
+ var DubheGraphqlClient = class {
756
+ constructor(config) {
757
+ this.parsedTables = /* @__PURE__ */ new Map();
758
+ this.dubheMetadata = config.dubheMetadata;
759
+ if (this.dubheMetadata) {
760
+ this.parseTableInfoFromConfig();
761
+ }
762
+ const httpLink = createHttpLink({
763
+ uri: config.endpoint,
764
+ headers: config.headers,
765
+ fetch: (input, init) => fetch(input, { ...config.fetchOptions, ...init })
766
+ });
767
+ const retryLink = new RetryLink({
768
+ delay: {
769
+ // Initial retry delay time (milliseconds)
770
+ initial: config.retryOptions?.delay?.initial || 300,
771
+ // Maximum retry delay time (milliseconds)
772
+ max: config.retryOptions?.delay?.max || 5e3,
773
+ // Whether to add random jitter to avoid thundering herd, enabled by default
774
+ jitter: config.retryOptions?.delay?.jitter !== false
775
+ },
776
+ attempts: {
777
+ // Maximum number of attempts (including initial request)
778
+ max: config.retryOptions?.attempts?.max || 5,
779
+ // Custom retry condition function
780
+ retryIf: config.retryOptions?.attempts?.retryIf || ((error, _operation) => {
781
+ return Boolean(
782
+ error && (error.networkError || error.graphQLErrors && error.graphQLErrors.length === 0)
783
+ );
784
+ })
785
+ }
786
+ });
787
+ const httpWithRetryLink = from([retryLink, httpLink]);
788
+ let link = httpWithRetryLink;
789
+ if (config.subscriptionEndpoint) {
790
+ let webSocketImpl;
791
+ try {
792
+ if (typeof window === "undefined" && typeof global !== "undefined") {
793
+ const wsModule = __require("ws");
794
+ webSocketImpl = wsModule.default || wsModule;
795
+ if (typeof global.WebSocket === "undefined") {
796
+ global.WebSocket = webSocketImpl;
797
+ }
798
+ } else {
799
+ webSocketImpl = WebSocket;
800
+ }
801
+ } catch (error) {
802
+ }
803
+ const clientOptions = {
804
+ url: config.subscriptionEndpoint,
805
+ connectionParams: {
806
+ headers: config.headers
807
+ }
808
+ };
809
+ if (webSocketImpl && typeof window === "undefined") {
810
+ clientOptions.webSocketImpl = webSocketImpl;
811
+ }
812
+ this.subscriptionClient = createClient(clientOptions);
813
+ const wsLink = new GraphQLWsLink(this.subscriptionClient);
814
+ link = split(
815
+ ({ query }) => {
816
+ const definition = getMainDefinition(query);
817
+ return definition.kind === "OperationDefinition" && definition.operation === "subscription";
818
+ },
819
+ wsLink,
820
+ httpWithRetryLink
821
+ );
822
+ }
823
+ this.apolloClient = new ApolloClient({
824
+ link,
825
+ cache: config.cacheConfig?.paginatedTables && config.cacheConfig.paginatedTables.length > 0 ? new InMemoryCache({
826
+ typePolicies: {
827
+ // Configure cache strategy for Connection type
828
+ Query: {
829
+ fields: this.buildCacheFields(config.cacheConfig)
830
+ }
831
+ }
832
+ }) : new InMemoryCache(),
833
+ // Use simple cache by default
834
+ defaultOptions: {
835
+ watchQuery: {
836
+ errorPolicy: "all",
837
+ notifyOnNetworkStatusChange: true
838
+ },
839
+ query: {
840
+ errorPolicy: "all"
841
+ }
842
+ }
843
+ });
844
+ }
845
+ /**
846
+ * Execute GraphQL query
847
+ */
848
+ async query(query, variables, options) {
849
+ try {
850
+ const result = await this.apolloClient.query({
851
+ query,
852
+ variables,
853
+ fetchPolicy: options?.cachePolicy ? mapCachePolicyToFetchPolicy(options.cachePolicy) : "no-cache",
854
+ // : 'cache-first',
855
+ notifyOnNetworkStatusChange: options?.notifyOnNetworkStatusChange,
856
+ pollInterval: options?.pollInterval
857
+ });
858
+ return {
859
+ data: result.data,
860
+ loading: result.loading,
861
+ error: result.error,
862
+ networkStatus: result.networkStatus,
863
+ refetch: () => this.query(query, variables, options)
864
+ };
865
+ } catch (error) {
866
+ return {
867
+ data: void 0,
868
+ loading: false,
869
+ error,
870
+ networkStatus: 8,
871
+ // NetworkStatus.error
872
+ refetch: () => this.query(query, variables, options)
873
+ };
874
+ }
875
+ }
876
+ /**
877
+ * Execute GraphQL subscription
878
+ */
879
+ subscribe(subscription, variables, options) {
880
+ return new Observable((observer) => {
881
+ const sub = this.apolloClient.subscribe({
882
+ query: subscription,
883
+ variables
884
+ }).subscribe({
885
+ next: (result) => {
886
+ const subscriptionResult = {
887
+ data: result.data,
888
+ loading: false,
889
+ error: result.errors?.[0]
890
+ };
891
+ observer.next(subscriptionResult);
892
+ options?.onData?.(result.data);
893
+ },
894
+ error: (error) => {
895
+ const subscriptionResult = {
896
+ data: void 0,
897
+ loading: false,
898
+ error
899
+ };
900
+ observer.next(subscriptionResult);
901
+ options?.onError?.(error);
902
+ },
903
+ complete: () => {
904
+ observer.complete();
905
+ options?.onComplete?.();
906
+ }
907
+ });
908
+ return () => sub.unsubscribe();
909
+ });
910
+ }
911
+ /**
912
+ * Query all table data - Adapted to API without store prefix
913
+ *
914
+ * OrderBy field name support:
915
+ * - camelCase: { field: 'updatedAt', direction: 'DESC' } → UPDATED_AT_DESC
916
+ * - snake_case: { field: 'updated_at', direction: 'DESC' } → UPDATED_AT_DESC
917
+ *
918
+ * Usage examples:
919
+ * ```ts
920
+ * // Using camelCase field names
921
+ * const result = await client.getAllTables('account', {
922
+ * orderBy: [{ field: 'updatedAt', direction: 'DESC' }]
923
+ * });
924
+ *
925
+ * // Using snake_case field names
926
+ * const result = await client.getAllTables('account', {
927
+ * orderBy: [{ field: 'updated_at', direction: 'DESC' }]
928
+ * });
929
+ *
930
+ * // Mixed usage
931
+ * const result = await client.getAllTables('account', {
932
+ * orderBy: [
933
+ * { field: 'updatedAt', direction: 'DESC' },
934
+ * { field: 'created_at', direction: 'ASC' }
935
+ * ]
936
+ * });
937
+ * ```
938
+ */
939
+ async getAllTables(tableName, params) {
940
+ const pluralTableName = this.getPluralTableName(tableName);
941
+ const orderByEnums = convertOrderByToEnum(params?.orderBy);
942
+ const query = gql`
943
+ query GetAllTables(
944
+ $first: Int
945
+ $last: Int
946
+ $after: Cursor
947
+ $before: Cursor
948
+ $filter: ${this.getFilterTypeName(tableName)}
949
+ $orderBy: [${this.getOrderByTypeName(tableName)}!]
950
+ ) {
951
+ ${pluralTableName}(
952
+ first: $first
953
+ last: $last
954
+ after: $after
955
+ before: $before
956
+ filter: $filter
957
+ orderBy: $orderBy
958
+ ) {
959
+ totalCount
960
+ pageInfo {
961
+ hasNextPage
962
+ hasPreviousPage
963
+ startCursor
964
+ endCursor
965
+ }
966
+ edges {
967
+ cursor
968
+ node {
969
+ ${this.convertTableFields(tableName, params?.fields)}
970
+ }
971
+ }
972
+ }
973
+ }
974
+ `;
975
+ const queryParams = {
976
+ first: params?.first,
977
+ last: params?.last,
978
+ after: params?.after,
979
+ before: params?.before,
980
+ filter: params?.filter,
981
+ orderBy: orderByEnums
982
+ };
983
+ const result = await this.query(query, queryParams);
984
+ if (result.error) {
985
+ throw result.error;
986
+ }
987
+ return result.data?.[pluralTableName] || {
988
+ edges: [],
989
+ pageInfo: { hasNextPage: false, hasPreviousPage: false }
990
+ };
991
+ }
992
+ /**
993
+ * Get single table record by condition - Adapted to API without store prefix
994
+ */
995
+ async getTableByCondition(tableName, condition, fields) {
996
+ const conditionKeys = Object.keys(condition);
997
+ const singularTableName = this.getSingularTableName(tableName);
998
+ const query = gql`
999
+ query GetTableByCondition(${conditionKeys.map((key, index) => `$${key}: String!`).join(", ")}) {
1000
+ ${singularTableName}(${conditionKeys.map((key) => `${key}: $${key}`).join(", ")}) {
1001
+ ${this.convertTableFields(tableName, fields)}
1002
+ }
1003
+ }
1004
+ `;
1005
+ const result = await this.query(query, condition);
1006
+ if (result.error) {
1007
+ throw result.error;
1008
+ }
1009
+ return result.data?.[singularTableName] || null;
1010
+ }
1011
+ /**
1012
+ * Subscribe to table data changes - Using PostGraphile's listen subscription feature
1013
+ */
1014
+ subscribeToTableChanges(tableName, options) {
1015
+ const topic = options?.topicPrefix ? `${options.topicPrefix}${tableName}` : `store_${this.getSingularTableName(tableName)}`;
1016
+ const pluralTableName = this.getPluralTableName(tableName);
1017
+ const fields = this.convertTableFields(tableName, options?.fields);
1018
+ const subscription = gql`
1019
+ subscription ListenToTableChanges($topic: String!, $initialEvent: Boolean) {
1020
+ listen(topic: $topic, initialEvent: $initialEvent) {
1021
+ query {
1022
+ ${pluralTableName}(first: ${options?.first || 10}, orderBy: UPDATED_AT_DESC) {
1023
+ totalCount
1024
+ nodes {
1025
+ ${fields}
1026
+ }
1027
+ pageInfo {
1028
+ hasNextPage
1029
+ endCursor
1030
+ }
1031
+ }
1032
+ }
1033
+ }
1034
+ }
1035
+ `;
1036
+ return this.subscribe(
1037
+ subscription,
1038
+ {
1039
+ topic,
1040
+ initialEvent: options?.initialEvent || false
1041
+ },
1042
+ options
1043
+ );
1044
+ }
1045
+ /**
1046
+ * Advanced listen subscription - Support custom queries
1047
+ */
1048
+ subscribeWithListen(topic, query, options) {
1049
+ const subscription = gql`
1050
+ subscription CustomListenSubscription($topic: String!, $initialEvent: Boolean) {
1051
+ listen(topic: $topic, initialEvent: $initialEvent) {
1052
+ query {
1053
+ ${query}
1054
+ }
1055
+ }
1056
+ }
1057
+ `;
1058
+ return this.subscribe(
1059
+ subscription,
1060
+ {
1061
+ topic,
1062
+ initialEvent: options?.initialEvent || false,
1063
+ ...options?.variables
1064
+ },
1065
+ options
1066
+ );
1067
+ }
1068
+ /**
1069
+ * Subscribe to data changes with specific conditions
1070
+ */
1071
+ subscribeToFilteredTableChanges(tableName, filter, options) {
1072
+ const topic = options?.topicPrefix ? `${options.topicPrefix}${tableName}` : `store_${this.getSingularTableName(tableName)}`;
1073
+ const pluralTableName = this.getPluralTableName(tableName);
1074
+ const fields = this.convertTableFields(tableName, options?.fields);
1075
+ const orderByEnum = convertOrderByToEnum(options?.orderBy);
1076
+ const first = options?.first || 10;
1077
+ const subscription = gql`
1078
+ subscription FilteredListenSubscription(
1079
+ $topic: String!,
1080
+ $initialEvent: Boolean,
1081
+ $filter: ${this.getFilterTypeName(tableName)},
1082
+ $orderBy: [${this.getOrderByTypeName(tableName)}!],
1083
+ $first: Int
1084
+ ) {
1085
+ listen(topic: $topic, initialEvent: $initialEvent) {
1086
+ query {
1087
+ ${pluralTableName}(
1088
+ first: $first,
1089
+ filter: $filter,
1090
+ orderBy: $orderBy
1091
+ ) {
1092
+ totalCount
1093
+ nodes {
1094
+ ${fields}
1095
+ }
1096
+ pageInfo {
1097
+ hasNextPage
1098
+ endCursor
1099
+ }
1100
+ }
1101
+ }
1102
+ }
1103
+ }
1104
+ `;
1105
+ return this.subscribe(
1106
+ subscription,
1107
+ {
1108
+ topic,
1109
+ initialEvent: options?.initialEvent || false,
1110
+ filter,
1111
+ orderBy: orderByEnum,
1112
+ first
1113
+ },
1114
+ options
1115
+ );
1116
+ }
1117
+ /**
1118
+ * Subscribe to multiple table data changes - Support batch subscription of table name list
1119
+ */
1120
+ subscribeToMultipleTables(tableConfigs, globalOptions) {
1121
+ return new Observable((observer) => {
1122
+ const subscriptions = [];
1123
+ const latestData = {};
1124
+ tableConfigs.forEach(({ tableName, options }) => {
1125
+ const subscription = this.subscribeToFilteredTableChanges(
1126
+ tableName,
1127
+ options?.filter,
1128
+ {
1129
+ ...options,
1130
+ onData: (data) => {
1131
+ latestData[tableName] = data;
1132
+ if (options?.onData) {
1133
+ options.onData(data);
1134
+ }
1135
+ if (globalOptions?.onData) {
1136
+ globalOptions.onData(latestData);
1137
+ }
1138
+ observer.next({ ...latestData });
1139
+ },
1140
+ onError: (error) => {
1141
+ if (options?.onError) {
1142
+ options.onError(error);
1143
+ }
1144
+ if (globalOptions?.onError) {
1145
+ globalOptions.onError(error);
1146
+ }
1147
+ observer.error(error);
1148
+ }
1149
+ }
1150
+ );
1151
+ subscriptions.push({ tableName, subscription });
1152
+ });
1153
+ const activeSubscriptions = subscriptions.map(
1154
+ ({ subscription }) => subscription.subscribe()
1155
+ );
1156
+ return () => {
1157
+ activeSubscriptions.forEach((sub) => sub.unsubscribe());
1158
+ if (globalOptions?.onComplete) {
1159
+ globalOptions.onComplete();
1160
+ }
1161
+ };
1162
+ });
1163
+ }
1164
+ /**
1165
+ * Simplified multi-table subscription - Support table name array and unified configuration
1166
+ */
1167
+ subscribeToTableList(tableNames, options) {
1168
+ const tableConfigs = tableNames.map(
1169
+ (tableName) => ({
1170
+ tableName,
1171
+ options: {
1172
+ ...options,
1173
+ // Use same configuration for each table
1174
+ fields: options?.fields,
1175
+ filter: options?.filter,
1176
+ initialEvent: options?.initialEvent,
1177
+ first: options?.first,
1178
+ topicPrefix: options?.topicPrefix
1179
+ }
1180
+ })
1181
+ );
1182
+ return this.subscribeToMultipleTables(tableConfigs, options);
1183
+ }
1184
+ /**
1185
+ * Build dynamic query - Adapted to API without store prefix
1186
+ */
1187
+ buildQuery(tableName, fields, params) {
1188
+ const pluralTableName = this.getPluralTableName(tableName);
1189
+ const fieldSelection = fields.join("\n ");
1190
+ return gql`
1191
+ query DynamicQuery(
1192
+ $first: Int
1193
+ $after: Cursor
1194
+ $filter: ${this.getFilterTypeName(tableName)}
1195
+ $orderBy: [${this.getOrderByTypeName(tableName)}!]
1196
+ ) {
1197
+ ${pluralTableName}(
1198
+ first: $first
1199
+ after: $after
1200
+ filter: $filter
1201
+ orderBy: $orderBy
1202
+ ) {
1203
+ totalCount
1204
+ pageInfo {
1205
+ hasNextPage
1206
+ endCursor
1207
+ }
1208
+ edges {
1209
+ cursor
1210
+ node {
1211
+ ${fieldSelection}
1212
+ }
1213
+ }
1214
+ }
1215
+ }
1216
+ `;
1217
+ }
1218
+ /**
1219
+ * Batch query multiple tables - Adapted to API without store prefix
1220
+ */
1221
+ async batchQuery(queries) {
1222
+ const batchPromises = queries.map(async ({ key, tableName, params }) => {
1223
+ const result = await this.getAllTables(tableName, params);
1224
+ return { key, result };
1225
+ });
1226
+ const results = await Promise.all(batchPromises);
1227
+ return results.reduce(
1228
+ (acc, { key, result }) => {
1229
+ acc[key] = result;
1230
+ return acc;
1231
+ },
1232
+ {}
1233
+ );
1234
+ }
1235
+ /**
1236
+ * Real-time data stream listener - Adapted to API without store prefix
1237
+ */
1238
+ createRealTimeDataStream(tableName, initialQuery) {
1239
+ return new Observable((observer) => {
1240
+ this.getAllTables(tableName, initialQuery).then((initialData) => {
1241
+ observer.next(initialData);
1242
+ }).catch((error) => observer.error(error));
1243
+ const subscription = this.subscribeToTableChanges(tableName, {
1244
+ onData: () => {
1245
+ this.getAllTables(tableName, initialQuery).then((updatedData) => {
1246
+ observer.next(updatedData);
1247
+ }).catch((error) => observer.error(error));
1248
+ },
1249
+ onError: (error) => observer.error(error)
1250
+ });
1251
+ return () => subscription.subscribe().unsubscribe();
1252
+ });
1253
+ }
1254
+ // Improved table name handling methods
1255
+ getFilterTypeName(tableName) {
1256
+ const singularName = this.getSingularTableName(tableName);
1257
+ const pascalCaseName = this.toPascalCase(singularName);
1258
+ if (pascalCaseName.startsWith("Store")) {
1259
+ return `${pascalCaseName}Filter`;
1260
+ }
1261
+ return `Store${pascalCaseName}Filter`;
1262
+ }
1263
+ getOrderByTypeName(tableName) {
1264
+ const pluralName = this.getPluralTableName(tableName);
1265
+ const pascalCaseName = this.toPascalCase(pluralName);
1266
+ if (pascalCaseName.startsWith("Store")) {
1267
+ return `${pascalCaseName}OrderBy`;
1268
+ }
1269
+ return `Store${pascalCaseName}OrderBy`;
1270
+ }
1271
+ /**
1272
+ * Convert singular table name to plural form (using pluralize library for correctness)
1273
+ */
1274
+ getPluralTableName(tableName) {
1275
+ const camelCaseName = this.toCamelCase(tableName);
1276
+ return pluralize.plural(camelCaseName);
1277
+ }
1278
+ /**
1279
+ * Convert plural table name to singular form (using pluralize library for correctness)
1280
+ */
1281
+ getSingularTableName(tableName) {
1282
+ const camelCaseName = this.toCamelCase(tableName);
1283
+ return pluralize.singular(camelCaseName);
1284
+ }
1285
+ /**
1286
+ * Convert snake_case to camelCase
1287
+ */
1288
+ toCamelCase(str) {
1289
+ return str.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase());
1290
+ }
1291
+ /**
1292
+ * Convert snake_case to PascalCase
1293
+ */
1294
+ toPascalCase(str) {
1295
+ const camelCase = this.toCamelCase(str);
1296
+ return camelCase.charAt(0).toUpperCase() + camelCase.slice(1);
1297
+ }
1298
+ /**
1299
+ * Convert camelCase or snake_case to SNAKE_CASE (for GraphQL enum values)
1300
+ * Example: updatedAt -> UPDATED_AT, updated_at -> UPDATED_AT
1301
+ */
1302
+ toSnakeCase(str) {
1303
+ if (str.includes("_")) {
1304
+ return str.toUpperCase();
1305
+ }
1306
+ return str.replace(/([A-Z])/g, "_$1").toLowerCase().replace(/^_/, "").toUpperCase();
1307
+ }
1308
+ // private buildSingleQueryName(
1309
+ // tableName: string,
1310
+ // conditionKeys: string[]
1311
+ // ): string {
1312
+ // // Use camelCase conversion
1313
+ // const camelCaseTableName = this.toCamelCase(tableName);
1314
+ // const capitalizedKeys = conditionKeys.map(
1315
+ // (key) => key.charAt(0).toUpperCase() + key.slice(1)
1316
+ // );
1317
+ // return `${camelCaseTableName}By${capitalizedKeys.join('And')}`;
1318
+ // }
1319
+ /**
1320
+ * Clear Apollo Client cache
1321
+ */
1322
+ async clearCache() {
1323
+ await this.apolloClient.clearStore();
1324
+ }
1325
+ /**
1326
+ * Reset Apollo Client cache
1327
+ */
1328
+ async resetCache() {
1329
+ await this.apolloClient.resetStore();
1330
+ }
1331
+ /**
1332
+ * Get Apollo Client instance (for advanced usage)
1333
+ */
1334
+ getApolloClient() {
1335
+ return this.apolloClient;
1336
+ }
1337
+ /**
1338
+ * Close client connection
1339
+ */
1340
+ close() {
1341
+ if (this.subscriptionClient) {
1342
+ this.subscriptionClient.dispose();
1343
+ }
1344
+ }
1345
+ /**
1346
+ * Get Dubhe metadata
1347
+ */
1348
+ getDubheMetadata() {
1349
+ return this.dubheMetadata;
1350
+ }
1351
+ /**
1352
+ * Build dynamic cache field configuration
1353
+ */
1354
+ buildCacheFields(cacheConfig) {
1355
+ const fields = {};
1356
+ if (!cacheConfig) {
1357
+ return fields;
1358
+ }
1359
+ if (cacheConfig.paginatedTables) {
1360
+ cacheConfig.paginatedTables.forEach((tableName) => {
1361
+ const pluralTableName = this.getPluralTableName(tableName);
1362
+ const customStrategy = cacheConfig.customMergeStrategies?.[pluralTableName];
1363
+ fields[pluralTableName] = {
1364
+ keyArgs: customStrategy?.keyArgs || ["filter", "orderBy"],
1365
+ merge: customStrategy?.merge || this.defaultMergeStrategy
1366
+ };
1367
+ });
1368
+ }
1369
+ if (cacheConfig.customMergeStrategies) {
1370
+ Object.entries(cacheConfig.customMergeStrategies).forEach(
1371
+ ([tableName, strategy]) => {
1372
+ if (!fields[tableName]) {
1373
+ fields[tableName] = {
1374
+ keyArgs: strategy.keyArgs || ["filter", "orderBy"],
1375
+ merge: strategy.merge || this.defaultMergeStrategy
1376
+ };
1377
+ }
1378
+ }
1379
+ );
1380
+ }
1381
+ return fields;
1382
+ }
1383
+ /**
1384
+ * Default pagination merge strategy
1385
+ */
1386
+ defaultMergeStrategy(existing = { edges: [] }, incoming) {
1387
+ if (!incoming || !Array.isArray(incoming.edges)) {
1388
+ return existing;
1389
+ }
1390
+ return {
1391
+ ...incoming,
1392
+ edges: [...existing.edges || [], ...incoming.edges]
1393
+ };
1394
+ }
1395
+ /**
1396
+ * Parse table information from dubhe metadata
1397
+ */
1398
+ parseTableInfoFromConfig() {
1399
+ if (!this.dubheMetadata) {
1400
+ return;
1401
+ }
1402
+ const { components = [], resources = [], enums = [] } = this.dubheMetadata;
1403
+ components.forEach((componentObj) => {
1404
+ Object.entries(componentObj).forEach(
1405
+ ([componentName, componentData]) => {
1406
+ this.processTableData(componentName, componentData, enums);
1407
+ }
1408
+ );
1409
+ });
1410
+ resources.forEach((resourceObj) => {
1411
+ Object.entries(resourceObj).forEach(
1412
+ ([resourceName, resourceData]) => {
1413
+ this.processTableData(resourceName, resourceData, enums);
1414
+ }
1415
+ );
1416
+ });
1417
+ }
1418
+ /**
1419
+ * Process data for a single table
1420
+ */
1421
+ processTableData(tableName, tableData, enums) {
1422
+ const snakeTableName = this.toSnakeCase(tableName);
1423
+ const fields = [];
1424
+ const enumFields = {};
1425
+ if (tableData.fields && Array.isArray(tableData.fields)) {
1426
+ tableData.fields.forEach((fieldObj) => {
1427
+ Object.entries(fieldObj).forEach(
1428
+ ([fieldName, fieldType]) => {
1429
+ const fieldNameCamelCase = this.toCamelCase(fieldName);
1430
+ fields.push(fieldNameCamelCase);
1431
+ }
1432
+ );
1433
+ });
1434
+ }
1435
+ fields.push("createdAt", "updatedAt");
1436
+ const primaryKeys = tableData.keys.map(
1437
+ (key) => this.toCamelCase(key)
1438
+ );
1439
+ const tableInfo = {
1440
+ tableName: snakeTableName,
1441
+ fields: [...new Set(fields)],
1442
+ // Remove duplicates
1443
+ primaryKeys,
1444
+ enumFields
1445
+ };
1446
+ this.parsedTables.set(snakeTableName, tableInfo);
1447
+ this.parsedTables.set(this.toCamelCase(snakeTableName), tableInfo);
1448
+ }
1449
+ /**
1450
+ * Get table field information
1451
+ */
1452
+ getTableFields(tableName) {
1453
+ return this.getMinimalFields(tableName);
1454
+ }
1455
+ /**
1456
+ * Get table primary key information
1457
+ */
1458
+ getTablePrimaryKeys(tableName) {
1459
+ const tableInfo = this.parsedTables.get(tableName) || this.parsedTables.get(this.toSnakeCase(tableName));
1460
+ return tableInfo?.primaryKeys || [];
1461
+ }
1462
+ /**
1463
+ * Get table enum field information
1464
+ */
1465
+ getTableEnumFields(tableName) {
1466
+ const tableInfo = this.parsedTables.get(tableName) || this.parsedTables.get(this.toSnakeCase(tableName));
1467
+ return tableInfo?.enumFields || {};
1468
+ }
1469
+ /**
1470
+ * Get all parsed table information
1471
+ */
1472
+ getAllTableInfo() {
1473
+ return new Map(this.parsedTables);
1474
+ }
1475
+ /**
1476
+ * Get table's minimal field set (for fallback)
1477
+ */
1478
+ getMinimalFields(tableName) {
1479
+ const tableInfo = this.parsedTables.get(tableName) || this.parsedTables.get(this.toSnakeCase(tableName));
1480
+ if (tableInfo) {
1481
+ return tableInfo.fields;
1482
+ }
1483
+ return ["createdAt", "updatedAt"];
1484
+ }
1485
+ /**
1486
+ * Convert table fields to GraphQL query string
1487
+ */
1488
+ convertTableFields(tableName, customFields) {
1489
+ let fields;
1490
+ if (customFields && customFields.length > 0) {
1491
+ fields = customFields;
1492
+ } else {
1493
+ const autoFields = this.getTableFields(tableName);
1494
+ if (autoFields.length > 0) {
1495
+ fields = autoFields;
1496
+ } else {
1497
+ fields = ["createdAt", "updatedAt"];
1498
+ }
1499
+ }
1500
+ return fields.join("\n ");
1501
+ }
1502
+ };
1503
+ function createDubheGraphqlClient(config) {
1504
+ return new DubheGraphqlClient(config);
1505
+ }
1506
+ var QueryBuilders = {
1507
+ // Build basic query - Adapted to API without store prefix
1508
+ basic: (tableName, fields = ["createdAt", "updatedAt"]) => gql`
1509
+ query Basic${tableName.charAt(0).toUpperCase() + tableName.slice(1)}Query(
1510
+ $first: Int
1511
+ $after: String
1512
+ $filter: ${tableName.charAt(0).toUpperCase() + tableName.slice(1)}Filter
1513
+ ) {
1514
+ ${tableName}(first: $first, after: $after, filter: $filter) {
1515
+ totalCount
1516
+ pageInfo {
1517
+ hasNextPage
1518
+ endCursor
1519
+ }
1520
+ edges {
1521
+ cursor
1522
+ node {
1523
+ ${fields.join("\n ")}
1524
+ }
1525
+ }
1526
+ }
1527
+ }
1528
+ `,
1529
+ // Build subscription query - Adapted to API without store prefix
1530
+ subscription: (tableName) => gql`
1531
+ subscription ${tableName.charAt(0).toUpperCase() + tableName.slice(1)}Subscription {
1532
+ ${tableName.charAt(0).toLowerCase() + tableName.slice(1)}Changed {
1533
+ createdAt
1534
+ updatedAt
1535
+ }
1536
+ }
1537
+ `
1538
+ };
1539
+ function convertOrderByToEnum(orderBy) {
1540
+ if (!orderBy || orderBy.length === 0) {
1541
+ return ["NATURAL"];
1542
+ }
1543
+ return orderBy.map((order) => {
1544
+ const field = toSnakeCaseForEnum(order.field);
1545
+ const direction = order.direction === "DESC" ? "DESC" : "ASC";
1546
+ return `${field}_${direction}`;
1547
+ });
1548
+ }
1549
+ function toSnakeCaseForEnum(str) {
1550
+ if (str.includes("_")) {
1551
+ return str.toUpperCase();
1552
+ }
1553
+ return str.replace(/([A-Z])/g, "_$1").toLowerCase().replace(/^_/, "").toUpperCase();
1554
+ }
1555
+ export {
1556
+ DubheGraphqlClient,
1557
+ QueryBuilders,
1558
+ createDubheGraphqlClient
1559
+ };
1560
+ //# sourceMappingURL=index.mjs.map