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