@xylex-group/athena 1.4.1 → 1.6.0

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/react.cjs CHANGED
@@ -1,6 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  var react = require('react');
4
+ var shim = require('use-sync-external-store/shim');
4
5
 
5
6
  // src/gateway/use-athena-gateway.ts
6
7
 
@@ -536,8 +537,972 @@ function useAthenaGateway(config) {
536
537
  };
537
538
  }
538
539
 
540
+ // src/react/utils.ts
541
+ function isRecord2(value) {
542
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
543
+ }
544
+ function isPrimitive(value) {
545
+ return value == null || ["string", "number", "boolean"].includes(typeof value);
546
+ }
547
+ function encodePrimitive(value) {
548
+ if (value === null) return "null:0:";
549
+ if (value === void 0) return "undefined:0:";
550
+ if (typeof value === "string") return `str:${value.length}:${value}`;
551
+ if (typeof value === "number") {
552
+ const serialized2 = Number.isFinite(value) ? String(value) : "nan";
553
+ return `num:${serialized2.length}:${serialized2}`;
554
+ }
555
+ const serialized = value ? "1" : "0";
556
+ return `bool:${serialized.length}:${serialized}`;
557
+ }
558
+ function stableSerialize(value, seen) {
559
+ if (value === null) return "null";
560
+ if (value === void 0) return "undefined";
561
+ const valueType = typeof value;
562
+ if (valueType === "string") return `"${value}"`;
563
+ if (valueType === "number") return Number.isFinite(value) ? String(value) : "null";
564
+ if (valueType === "boolean") return value ? "true" : "false";
565
+ if (valueType === "bigint") return `${String(value)}n`;
566
+ if (valueType === "symbol") return `symbol:${String(value)}`;
567
+ if (valueType === "function") {
568
+ const namedFunction = value;
569
+ return `function:${namedFunction.name || "anonymous"}`;
570
+ }
571
+ if (value instanceof Date) return `date:${value.toISOString()}`;
572
+ if (Array.isArray(value)) {
573
+ return `[${value.map((item) => stableSerialize(item, seen)).join(",")}]`;
574
+ }
575
+ if (valueType === "object") {
576
+ const objectValue = value;
577
+ if (seen.has(objectValue)) return "[circular]";
578
+ seen.add(objectValue);
579
+ const keys = Object.keys(objectValue).sort();
580
+ const serialized = `{${keys.map((key) => `${key}:${stableSerialize(objectValue[key], seen)}`).join(",")}}`;
581
+ seen.delete(objectValue);
582
+ return serialized;
583
+ }
584
+ return String(value);
585
+ }
586
+ function safeSerializeQueryKey(queryKey) {
587
+ try {
588
+ if (typeof queryKey === "string") {
589
+ return `key:${queryKey}`;
590
+ }
591
+ if (Array.isArray(queryKey) && queryKey.every(isPrimitive)) {
592
+ return `arr:${queryKey.map((item) => encodePrimitive(item)).join("|")}`;
593
+ }
594
+ return `ser:${stableSerialize(queryKey, /* @__PURE__ */ new WeakSet())}`;
595
+ } catch {
596
+ try {
597
+ return `fallback:${String(queryKey)}`;
598
+ } catch {
599
+ return "fallback:[unserializable-query-key]";
600
+ }
601
+ }
602
+ }
603
+ function sleep(ms) {
604
+ if (ms <= 0) return Promise.resolve();
605
+ return new Promise((resolve) => {
606
+ setTimeout(resolve, ms);
607
+ });
608
+ }
609
+ function resolveRetryCount(retry) {
610
+ if (retry === false || retry == null) return 0;
611
+ if (!Number.isFinite(retry)) return 0;
612
+ return Math.max(0, Math.trunc(retry));
613
+ }
614
+ function resolveRetryDelay(retryDelay, attempt) {
615
+ if (typeof retryDelay === "function") {
616
+ const resolved = retryDelay(attempt);
617
+ if (!Number.isFinite(resolved)) return 0;
618
+ return Math.max(0, resolved);
619
+ }
620
+ if (typeof retryDelay === "number") {
621
+ if (!Number.isFinite(retryDelay)) return 0;
622
+ return Math.max(0, retryDelay);
623
+ }
624
+ return 0;
625
+ }
626
+ async function runWithRetry(execute, options) {
627
+ const retries = resolveRetryCount(options?.retry);
628
+ let attempt = 0;
629
+ for (; ; ) {
630
+ attempt += 1;
631
+ try {
632
+ return await execute(attempt);
633
+ } catch (error) {
634
+ if (attempt > retries) {
635
+ throw error;
636
+ }
637
+ const delay = resolveRetryDelay(options?.retryDelay, attempt);
638
+ await sleep(delay);
639
+ }
640
+ }
641
+ }
642
+ function errorMessageFromUnknown(error) {
643
+ if (typeof error === "string" && error.trim()) return error.trim();
644
+ if (error instanceof Error && error.message.trim()) return error.message.trim();
645
+ if (isRecord2(error)) {
646
+ const messageCandidate = error.message ?? error.error;
647
+ if (typeof messageCandidate === "string" && messageCandidate.trim()) {
648
+ return messageCandidate.trim();
649
+ }
650
+ }
651
+ return "Athena request failed";
652
+ }
653
+ function normalizeAthenaError(error, source) {
654
+ if (isRecord2(error) && typeof error.message === "string" && (error.status === void 0 || typeof error.status === "number") && (error.code === void 0 || typeof error.code === "string")) {
655
+ return {
656
+ message: error.message,
657
+ status: typeof error.status === "number" ? error.status : void 0,
658
+ code: typeof error.code === "string" ? error.code : void 0,
659
+ details: error.details,
660
+ raw: error.raw ?? source ?? error
661
+ };
662
+ }
663
+ if (isAthenaGatewayError(error)) {
664
+ const details = error.toDetails();
665
+ return {
666
+ message: details.message,
667
+ status: details.status,
668
+ code: details.code,
669
+ details,
670
+ raw: source ?? error
671
+ };
672
+ }
673
+ if (isRecord2(source) && source.errorDetails && isRecord2(source.errorDetails)) {
674
+ const details = source.errorDetails;
675
+ return {
676
+ message: errorMessageFromUnknown(error ?? source.error),
677
+ status: typeof source.status === "number" ? source.status : void 0,
678
+ code: typeof details.code === "string" ? details.code : void 0,
679
+ details,
680
+ raw: source
681
+ };
682
+ }
683
+ if (isRecord2(source) && typeof source.status === "number") {
684
+ return {
685
+ message: errorMessageFromUnknown(error),
686
+ status: source.status,
687
+ details: source,
688
+ raw: source
689
+ };
690
+ }
691
+ return {
692
+ message: errorMessageFromUnknown(error),
693
+ raw: source ?? error
694
+ };
695
+ }
696
+ function isAthenaResponseLike(value) {
697
+ if (!isRecord2(value)) return false;
698
+ if ("error" in value || "errorDetails" in value) return true;
699
+ if ("status" in value && typeof value.status === "number") {
700
+ return "data" in value || "raw" in value;
701
+ }
702
+ return "data" in value && ("raw" in value || "status" in value);
703
+ }
704
+ function normalizeAthenaResult(value, select) {
705
+ if (isAthenaResponseLike(value)) {
706
+ const status = typeof value.status === "number" ? value.status : value.error != null ? 500 : 200;
707
+ if (value.error != null) {
708
+ return {
709
+ data: void 0,
710
+ error: normalizeAthenaError(value.error, value),
711
+ status,
712
+ raw: value.raw ?? value
713
+ };
714
+ }
715
+ const hasData = "data" in value;
716
+ const sourceData2 = hasData ? value.data : void 0;
717
+ const selectedData2 = sourceData2 === void 0 ? void 0 : sourceData2 === null ? null : select ? select(sourceData2) : sourceData2;
718
+ return {
719
+ data: selectedData2,
720
+ error: null,
721
+ status,
722
+ raw: value.raw ?? value
723
+ };
724
+ }
725
+ const sourceData = value;
726
+ const selectedData = select ? select(sourceData) : sourceData;
727
+ return {
728
+ data: selectedData,
729
+ error: null,
730
+ status: 200,
731
+ raw: value
732
+ };
733
+ }
734
+
735
+ // src/react/query-client.ts
736
+ function createInitialQueryState(initialData) {
737
+ return {
738
+ status: initialData === void 0 ? "idle" : "success",
739
+ isFetching: false,
740
+ data: initialData,
741
+ error: null,
742
+ updatedAt: initialData === void 0 ? void 0 : Date.now()
743
+ };
744
+ }
745
+ function createInitialMutationState() {
746
+ return {
747
+ status: "idle",
748
+ data: void 0,
749
+ error: null,
750
+ isLoading: false,
751
+ lastVariables: void 0,
752
+ lastResponse: void 0,
753
+ updatedAt: void 0
754
+ };
755
+ }
756
+ function shouldUseMemoryCache(config) {
757
+ return config.cache?.mode === "memory";
758
+ }
759
+ var AthenaQueryClient = class {
760
+ queryEntries = /* @__PURE__ */ new Map();
761
+ mutationEntries = /* @__PURE__ */ new Map();
762
+ inflightQueries = /* @__PURE__ */ new Map();
763
+ eventSubscribers = /* @__PURE__ */ new Set();
764
+ adapters = /* @__PURE__ */ new Set();
765
+ requestCounter = 0;
766
+ config;
767
+ defaultQueryOptions;
768
+ defaultMutationOptions;
769
+ constructor(config = {}) {
770
+ this.config = {
771
+ cache: {
772
+ mode: config.cache?.mode ?? "none",
773
+ staleTime: config.cache?.staleTime,
774
+ gcTime: config.cache?.gcTime
775
+ },
776
+ defaultQueryOptions: config.defaultQueryOptions,
777
+ defaultMutationOptions: config.defaultMutationOptions
778
+ };
779
+ this.defaultQueryOptions = {
780
+ retry: config.defaultQueryOptions?.retry ?? 0,
781
+ retryDelay: config.defaultQueryOptions?.retryDelay,
782
+ refetchOnMount: config.defaultQueryOptions?.refetchOnMount ?? true,
783
+ refetchOnWindowFocus: config.defaultQueryOptions?.refetchOnWindowFocus ?? false,
784
+ refetchOnReconnect: config.defaultQueryOptions?.refetchOnReconnect ?? false
785
+ };
786
+ this.defaultMutationOptions = {
787
+ retry: config.defaultMutationOptions?.retry ?? 0,
788
+ retryDelay: config.defaultMutationOptions?.retryDelay
789
+ };
790
+ }
791
+ getQueryKeyToken(queryKey) {
792
+ return safeSerializeQueryKey(queryKey);
793
+ }
794
+ getMutationKeyToken(mutationKey) {
795
+ if (mutationKey == null) {
796
+ return "__mutation__default__";
797
+ }
798
+ return safeSerializeQueryKey(mutationKey);
799
+ }
800
+ getQueryState(key) {
801
+ const entry = this.ensureQueryEntry(key);
802
+ return entry.state;
803
+ }
804
+ getMutationState(key) {
805
+ const entry = this.ensureMutationEntry(key);
806
+ return entry.state;
807
+ }
808
+ subscribeQuery(key, listener) {
809
+ const entry = this.ensureQueryEntry(key);
810
+ if (entry.gcTimer) {
811
+ clearTimeout(entry.gcTimer);
812
+ entry.gcTimer = void 0;
813
+ }
814
+ entry.listeners.add(listener);
815
+ return () => {
816
+ const current = this.queryEntries.get(key);
817
+ if (!current) return;
818
+ current.listeners.delete(listener);
819
+ if (current.listeners.size === 0) {
820
+ this.scheduleQueryGc(current);
821
+ }
822
+ };
823
+ }
824
+ subscribeMutation(key, listener) {
825
+ const entry = this.ensureMutationEntry(key);
826
+ if (entry.gcTimer) {
827
+ clearTimeout(entry.gcTimer);
828
+ entry.gcTimer = void 0;
829
+ }
830
+ entry.listeners.add(listener);
831
+ return () => {
832
+ const current = this.mutationEntries.get(key);
833
+ if (!current) return;
834
+ current.listeners.delete(listener);
835
+ if (current.listeners.size === 0) {
836
+ this.scheduleMutationGc(current);
837
+ }
838
+ };
839
+ }
840
+ subscribeEvents(listener) {
841
+ this.eventSubscribers.add(listener);
842
+ return () => {
843
+ this.eventSubscribers.delete(listener);
844
+ };
845
+ }
846
+ attachAdapter(adapter) {
847
+ this.adapters.add(adapter);
848
+ return () => {
849
+ this.adapters.delete(adapter);
850
+ };
851
+ }
852
+ resetQuery(queryKey) {
853
+ const key = this.getQueryKeyToken(queryKey);
854
+ const entry = this.ensureQueryEntry(key);
855
+ entry.activeRequestId = ++this.requestCounter;
856
+ this.setQueryState(entry, createInitialQueryState(), "query_reset");
857
+ this.inflightQueries.delete(key);
858
+ }
859
+ resetMutation(mutationKey) {
860
+ const key = this.getMutationKeyToken(mutationKey);
861
+ const entry = this.ensureMutationEntry(key);
862
+ entry.activeRequestId = ++this.requestCounter;
863
+ this.setMutationState(entry, createInitialMutationState(), "mutation_reset");
864
+ }
865
+ async executeQuery(input) {
866
+ const entry = this.ensureQueryEntry(input.queryKeyToken);
867
+ if (input.dedupe !== false) {
868
+ const existing = this.inflightQueries.get(input.queryKeyToken);
869
+ if (existing) {
870
+ return existing;
871
+ }
872
+ }
873
+ if (!input.force && shouldUseMemoryCache(this.config)) {
874
+ const staleTime = this.config.cache?.staleTime ?? 0;
875
+ const hasFreshData = entry.state.status === "success" && entry.state.data !== void 0 && entry.state.updatedAt !== void 0 && Date.now() - entry.state.updatedAt <= staleTime;
876
+ if (hasFreshData) {
877
+ return {
878
+ data: entry.state.data,
879
+ error: null,
880
+ status: 200,
881
+ raw: entry.state.lastResponse ?? entry.state.data,
882
+ __applied: true
883
+ };
884
+ }
885
+ }
886
+ const requestId = ++this.requestCounter;
887
+ entry.activeRequestId = requestId;
888
+ const startRequestLog = {
889
+ requestId,
890
+ queryKey: input.queryKey,
891
+ queryKeyToken: input.queryKeyToken,
892
+ attempt: 1,
893
+ startedAt: Date.now()
894
+ };
895
+ const loadingStatus = entry.state.data === void 0 ? "loading" : entry.state.status;
896
+ this.setQueryState(
897
+ entry,
898
+ {
899
+ ...entry.state,
900
+ status: loadingStatus,
901
+ isFetching: true,
902
+ error: null,
903
+ lastRequest: startRequestLog
904
+ },
905
+ "query_updated"
906
+ );
907
+ const executionPromise = runWithRetry(
908
+ async (attempt) => {
909
+ const attemptRequestLog = {
910
+ ...startRequestLog,
911
+ attempt
912
+ };
913
+ if (entry.activeRequestId === requestId) {
914
+ this.setQueryState(
915
+ entry,
916
+ {
917
+ ...entry.state,
918
+ lastRequest: attemptRequestLog,
919
+ isFetching: true
920
+ },
921
+ "query_updated"
922
+ );
923
+ }
924
+ const rawResult = await input.queryFn();
925
+ const normalized = normalizeAthenaResult(rawResult, input.select);
926
+ if (normalized.error) {
927
+ throw {
928
+ __athenaNormalizedError: normalized.error,
929
+ __athenaStatus: normalized.status,
930
+ __athenaRaw: normalized.raw,
931
+ __athenaResponse: rawResult
932
+ };
933
+ }
934
+ return {
935
+ normalized,
936
+ response: rawResult,
937
+ attempt
938
+ };
939
+ },
940
+ {
941
+ retry: input.retry,
942
+ retryDelay: input.retryDelay
943
+ }
944
+ ).then((result) => {
945
+ const applied = entry.activeRequestId === requestId;
946
+ if (applied) {
947
+ const finishedAt = Date.now();
948
+ const doneRequestLog = {
949
+ ...startRequestLog,
950
+ attempt: result.attempt,
951
+ endedAt: finishedAt
952
+ };
953
+ this.setQueryState(
954
+ entry,
955
+ {
956
+ ...entry.state,
957
+ status: "success",
958
+ isFetching: false,
959
+ error: null,
960
+ data: result.normalized.data,
961
+ lastRequest: doneRequestLog,
962
+ lastResponse: result.response,
963
+ updatedAt: finishedAt
964
+ },
965
+ "query_updated"
966
+ );
967
+ }
968
+ return {
969
+ ...result.normalized,
970
+ __applied: applied
971
+ };
972
+ }).catch((error) => {
973
+ const wrapped = typeof error === "object" && error !== null ? error : void 0;
974
+ const normalizedError = wrapped?.__athenaNormalizedError ? wrapped.__athenaNormalizedError : normalizeAthenaError(error);
975
+ const status = typeof wrapped?.__athenaStatus === "number" ? wrapped.__athenaStatus : normalizedError.status ?? 500;
976
+ const raw = wrapped?.__athenaRaw ?? normalizedError.raw ?? null;
977
+ const response = wrapped?.__athenaResponse ?? raw;
978
+ const applied = entry.activeRequestId === requestId;
979
+ if (applied) {
980
+ const finishedAt = Date.now();
981
+ const doneRequestLog = {
982
+ ...startRequestLog,
983
+ endedAt: finishedAt,
984
+ attempt: entry.state.lastRequest?.requestId === requestId ? entry.state.lastRequest.attempt : startRequestLog.attempt
985
+ };
986
+ this.setQueryState(
987
+ entry,
988
+ {
989
+ ...entry.state,
990
+ status: "error",
991
+ isFetching: false,
992
+ error: normalizedError,
993
+ lastRequest: doneRequestLog,
994
+ lastResponse: response,
995
+ updatedAt: finishedAt
996
+ },
997
+ "query_updated"
998
+ );
999
+ }
1000
+ return {
1001
+ data: void 0,
1002
+ error: normalizedError,
1003
+ status,
1004
+ raw,
1005
+ __applied: applied
1006
+ };
1007
+ }).finally(() => {
1008
+ const inflight = this.inflightQueries.get(input.queryKeyToken);
1009
+ if (inflight === executionPromise) {
1010
+ this.inflightQueries.delete(input.queryKeyToken);
1011
+ }
1012
+ });
1013
+ this.inflightQueries.set(input.queryKeyToken, executionPromise);
1014
+ return executionPromise;
1015
+ }
1016
+ async executeMutation(input) {
1017
+ const entry = this.ensureMutationEntry(input.mutationKeyToken);
1018
+ const requestId = ++this.requestCounter;
1019
+ entry.activeRequestId = requestId;
1020
+ const startRequestLog = {
1021
+ requestId,
1022
+ mutationKey: input.mutationKey,
1023
+ mutationKeyToken: input.mutationKeyToken,
1024
+ attempt: 1,
1025
+ startedAt: Date.now(),
1026
+ variables: input.variables
1027
+ };
1028
+ this.setMutationState(
1029
+ entry,
1030
+ {
1031
+ ...entry.state,
1032
+ status: "loading",
1033
+ isLoading: true,
1034
+ error: null,
1035
+ lastVariables: input.variables,
1036
+ lastRequest: startRequestLog
1037
+ },
1038
+ "mutation_updated"
1039
+ );
1040
+ try {
1041
+ const result = await runWithRetry(
1042
+ async (attempt) => {
1043
+ const attemptRequestLog = {
1044
+ ...startRequestLog,
1045
+ attempt
1046
+ };
1047
+ if (entry.activeRequestId === requestId) {
1048
+ this.setMutationState(
1049
+ entry,
1050
+ {
1051
+ ...entry.state,
1052
+ lastRequest: attemptRequestLog,
1053
+ isLoading: true
1054
+ },
1055
+ "mutation_updated"
1056
+ );
1057
+ }
1058
+ const rawResult = await input.mutationFn(input.variables);
1059
+ const normalized = normalizeAthenaResult(rawResult, input.select);
1060
+ if (normalized.error) {
1061
+ throw {
1062
+ __athenaNormalizedError: normalized.error,
1063
+ __athenaStatus: normalized.status,
1064
+ __athenaRaw: normalized.raw,
1065
+ __athenaResponse: rawResult
1066
+ };
1067
+ }
1068
+ return {
1069
+ normalized,
1070
+ response: rawResult,
1071
+ attempt
1072
+ };
1073
+ },
1074
+ {
1075
+ retry: input.retry,
1076
+ retryDelay: input.retryDelay
1077
+ }
1078
+ );
1079
+ if (entry.activeRequestId === requestId) {
1080
+ const finishedAt = Date.now();
1081
+ const doneRequestLog = {
1082
+ ...startRequestLog,
1083
+ attempt: result.attempt,
1084
+ endedAt: finishedAt
1085
+ };
1086
+ this.setMutationState(
1087
+ entry,
1088
+ {
1089
+ ...entry.state,
1090
+ status: "success",
1091
+ isLoading: false,
1092
+ data: result.normalized.data,
1093
+ error: null,
1094
+ lastVariables: input.variables,
1095
+ lastRequest: doneRequestLog,
1096
+ lastResponse: result.response,
1097
+ updatedAt: finishedAt
1098
+ },
1099
+ "mutation_updated"
1100
+ );
1101
+ }
1102
+ return result.normalized;
1103
+ } catch (error) {
1104
+ const wrapped = typeof error === "object" && error !== null ? error : void 0;
1105
+ const normalizedError = wrapped?.__athenaNormalizedError ? wrapped.__athenaNormalizedError : normalizeAthenaError(error);
1106
+ const status = typeof wrapped?.__athenaStatus === "number" ? wrapped.__athenaStatus : normalizedError.status ?? 500;
1107
+ const raw = wrapped?.__athenaRaw ?? normalizedError.raw ?? null;
1108
+ const response = wrapped?.__athenaResponse ?? raw;
1109
+ if (entry.activeRequestId === requestId) {
1110
+ const finishedAt = Date.now();
1111
+ const doneRequestLog = {
1112
+ ...startRequestLog,
1113
+ endedAt: finishedAt,
1114
+ attempt: entry.state.lastRequest?.requestId === requestId ? entry.state.lastRequest.attempt : startRequestLog.attempt
1115
+ };
1116
+ this.setMutationState(
1117
+ entry,
1118
+ {
1119
+ ...entry.state,
1120
+ status: "error",
1121
+ isLoading: false,
1122
+ error: normalizedError,
1123
+ lastVariables: input.variables,
1124
+ lastRequest: doneRequestLog,
1125
+ lastResponse: response,
1126
+ updatedAt: finishedAt
1127
+ },
1128
+ "mutation_updated"
1129
+ );
1130
+ }
1131
+ return {
1132
+ data: void 0,
1133
+ error: normalizedError,
1134
+ status,
1135
+ raw
1136
+ };
1137
+ }
1138
+ }
1139
+ ensureQueryEntry(key) {
1140
+ let entry = this.queryEntries.get(key);
1141
+ if (entry) return entry;
1142
+ entry = {
1143
+ key,
1144
+ state: createInitialQueryState(),
1145
+ listeners: /* @__PURE__ */ new Set(),
1146
+ activeRequestId: 0
1147
+ };
1148
+ this.queryEntries.set(key, entry);
1149
+ return entry;
1150
+ }
1151
+ ensureMutationEntry(key) {
1152
+ let entry = this.mutationEntries.get(key);
1153
+ if (entry) return entry;
1154
+ entry = {
1155
+ key,
1156
+ state: createInitialMutationState(),
1157
+ listeners: /* @__PURE__ */ new Set(),
1158
+ activeRequestId: 0
1159
+ };
1160
+ this.mutationEntries.set(key, entry);
1161
+ return entry;
1162
+ }
1163
+ scheduleQueryGc(entry) {
1164
+ const gcTime = shouldUseMemoryCache(this.config) ? Math.max(0, this.config.cache?.gcTime ?? 3e5) : Math.max(0, this.config.cache?.gcTime ?? 0);
1165
+ entry.gcTimer = setTimeout(() => {
1166
+ const current = this.queryEntries.get(entry.key);
1167
+ if (!current || current.listeners.size > 0) return;
1168
+ this.queryEntries.delete(entry.key);
1169
+ this.inflightQueries.delete(entry.key);
1170
+ this.emitEvent({
1171
+ type: "query_gc",
1172
+ key: entry.key,
1173
+ state: current.state,
1174
+ timestamp: Date.now()
1175
+ });
1176
+ }, gcTime);
1177
+ }
1178
+ scheduleMutationGc(entry) {
1179
+ const gcTime = shouldUseMemoryCache(this.config) ? Math.max(0, this.config.cache?.gcTime ?? 3e5) : Math.max(0, this.config.cache?.gcTime ?? 0);
1180
+ entry.gcTimer = setTimeout(() => {
1181
+ const current = this.mutationEntries.get(entry.key);
1182
+ if (!current || current.listeners.size > 0) return;
1183
+ this.mutationEntries.delete(entry.key);
1184
+ }, gcTime);
1185
+ }
1186
+ setQueryState(entry, state, eventType) {
1187
+ entry.state = state;
1188
+ for (const listener of entry.listeners) {
1189
+ listener();
1190
+ }
1191
+ this.emitEvent({
1192
+ type: eventType,
1193
+ key: entry.key,
1194
+ state,
1195
+ timestamp: Date.now()
1196
+ });
1197
+ }
1198
+ setMutationState(entry, state, eventType) {
1199
+ entry.state = state;
1200
+ for (const listener of entry.listeners) {
1201
+ listener();
1202
+ }
1203
+ this.emitEvent({
1204
+ type: eventType,
1205
+ key: entry.key,
1206
+ state,
1207
+ timestamp: Date.now()
1208
+ });
1209
+ }
1210
+ emitEvent(event) {
1211
+ for (const listener of this.eventSubscribers) {
1212
+ listener(event);
1213
+ }
1214
+ for (const adapter of this.adapters) {
1215
+ adapter.onEvent?.(event);
1216
+ if (event.type === "query_updated" || event.type === "query_reset" || event.type === "query_gc") {
1217
+ adapter.onQueryUpdated?.(event);
1218
+ }
1219
+ if (event.type === "mutation_updated" || event.type === "mutation_reset") {
1220
+ adapter.onMutationUpdated?.(event);
1221
+ }
1222
+ }
1223
+ }
1224
+ };
1225
+ function createAthenaQueryClient(config) {
1226
+ return new AthenaQueryClient(config);
1227
+ }
1228
+ function attachStateAdapter(client, adapter) {
1229
+ return client.attachAdapter(adapter);
1230
+ }
1231
+ var AthenaQueryClientContext = react.createContext(null);
1232
+ function AthenaQueryClientProvider(props) {
1233
+ const memoizedClient = react.useMemo(() => {
1234
+ if (props.client) {
1235
+ return props.client;
1236
+ }
1237
+ return createAthenaQueryClient(props.config);
1238
+ }, [props.client, props.config]);
1239
+ return react.createElement(
1240
+ AthenaQueryClientContext.Provider,
1241
+ { value: memoizedClient },
1242
+ props.children
1243
+ );
1244
+ }
1245
+ function useAthenaQueryClient() {
1246
+ const client = react.useContext(AthenaQueryClientContext);
1247
+ if (!client) {
1248
+ throw new Error(
1249
+ "No AthenaQueryClient found. Wrap your component tree with AthenaQueryClientProvider."
1250
+ );
1251
+ }
1252
+ return client;
1253
+ }
1254
+ function getBrowserTarget() {
1255
+ const maybeGlobal = globalThis;
1256
+ const hasListeners = (value) => Boolean(value) && typeof value === "object" && typeof value.addEventListener === "function" && typeof value.removeEventListener === "function";
1257
+ if (hasListeners(maybeGlobal.window)) {
1258
+ return maybeGlobal.window;
1259
+ }
1260
+ if (hasListeners(maybeGlobal)) {
1261
+ return maybeGlobal;
1262
+ }
1263
+ return null;
1264
+ }
1265
+ function useQuery(options) {
1266
+ const client = useAthenaQueryClient();
1267
+ const queryKeyRef = react.useRef(options.queryKey);
1268
+ queryKeyRef.current = options.queryKey;
1269
+ const queryFnRef = react.useRef(options.queryFn);
1270
+ queryFnRef.current = options.queryFn;
1271
+ const selectRef = react.useRef(options.select);
1272
+ selectRef.current = options.select;
1273
+ const onSuccessRef = react.useRef(options.onSuccess);
1274
+ onSuccessRef.current = options.onSuccess;
1275
+ const onErrorRef = react.useRef(options.onError);
1276
+ onErrorRef.current = options.onError;
1277
+ const onSettledRef = react.useRef(options.onSettled);
1278
+ onSettledRef.current = options.onSettled;
1279
+ const enabledRef = react.useRef(options.enabled ?? true);
1280
+ enabledRef.current = options.enabled ?? true;
1281
+ const retryRef = react.useRef(options.retry);
1282
+ retryRef.current = options.retry;
1283
+ const retryDelayRef = react.useRef(options.retryDelay);
1284
+ retryDelayRef.current = options.retryDelay;
1285
+ const initialDataRef = react.useRef(options.initialData);
1286
+ initialDataRef.current = options.initialData;
1287
+ const refetchOnMountRef = react.useRef(options.refetchOnMount);
1288
+ refetchOnMountRef.current = options.refetchOnMount;
1289
+ const refetchOnWindowFocusRef = react.useRef(options.refetchOnWindowFocus);
1290
+ refetchOnWindowFocusRef.current = options.refetchOnWindowFocus;
1291
+ const refetchOnReconnectRef = react.useRef(options.refetchOnReconnect);
1292
+ refetchOnReconnectRef.current = options.refetchOnReconnect;
1293
+ const queryKeyToken = react.useMemo(
1294
+ () => client.getQueryKeyToken(options.queryKey),
1295
+ [client, options.queryKey]
1296
+ );
1297
+ const activeQueryKeyTokenRef = react.useRef(queryKeyToken);
1298
+ activeQueryKeyTokenRef.current = queryKeyToken;
1299
+ const subscribe = react.useCallback(
1300
+ (listener) => client.subscribeQuery(queryKeyToken, listener),
1301
+ [client, queryKeyToken]
1302
+ );
1303
+ const getSnapshot = react.useCallback(
1304
+ () => client.getQueryState(queryKeyToken),
1305
+ [client, queryKeyToken]
1306
+ );
1307
+ const snapshot = shim.useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
1308
+ const effectiveSnapshot = react.useMemo(() => {
1309
+ if (snapshot.status === "idle" && snapshot.data === void 0 && initialDataRef.current !== void 0) {
1310
+ return {
1311
+ ...snapshot,
1312
+ status: "success",
1313
+ data: initialDataRef.current,
1314
+ error: null
1315
+ };
1316
+ }
1317
+ return snapshot;
1318
+ }, [snapshot]);
1319
+ const runQuery = react.useCallback(
1320
+ async (force = false) => {
1321
+ const result = await client.executeQuery({
1322
+ queryKey: queryKeyRef.current,
1323
+ queryKeyToken,
1324
+ queryFn: () => queryFnRef.current(),
1325
+ select: selectRef.current,
1326
+ retry: retryRef.current ?? client.defaultQueryOptions.retry ?? 0,
1327
+ retryDelay: retryDelayRef.current ?? client.defaultQueryOptions.retryDelay,
1328
+ dedupe: true,
1329
+ force
1330
+ });
1331
+ const internalResult = result;
1332
+ if (activeQueryKeyTokenRef.current !== queryKeyToken || internalResult.__applied === false) {
1333
+ return result;
1334
+ }
1335
+ if (result.error) {
1336
+ onErrorRef.current?.(result.error);
1337
+ onSettledRef.current?.(result.data, result.error);
1338
+ return result;
1339
+ }
1340
+ onSuccessRef.current?.(result.data);
1341
+ onSettledRef.current?.(result.data, null);
1342
+ return result;
1343
+ },
1344
+ [client, queryKeyToken]
1345
+ );
1346
+ const lastAutoKeyRef = react.useRef(null);
1347
+ react.useEffect(() => {
1348
+ const refetchOnMount = refetchOnMountRef.current ?? client.defaultQueryOptions.refetchOnMount ?? true;
1349
+ const isFirstRenderForKey = lastAutoKeyRef.current !== queryKeyToken;
1350
+ lastAutoKeyRef.current = queryKeyToken;
1351
+ if (!enabledRef.current) {
1352
+ return;
1353
+ }
1354
+ const state = client.getQueryState(queryKeyToken);
1355
+ const shouldFetch = state.status === "idle" || isFirstRenderForKey && refetchOnMount;
1356
+ if (shouldFetch) {
1357
+ void runQuery(false);
1358
+ }
1359
+ }, [client, queryKeyToken, runQuery]);
1360
+ react.useEffect(() => {
1361
+ const browser = getBrowserTarget();
1362
+ if (!browser || !enabledRef.current) {
1363
+ return void 0;
1364
+ }
1365
+ const refetchOnWindowFocus = refetchOnWindowFocusRef.current ?? client.defaultQueryOptions.refetchOnWindowFocus ?? false;
1366
+ if (!refetchOnWindowFocus) {
1367
+ return void 0;
1368
+ }
1369
+ const onFocus = () => {
1370
+ if (!enabledRef.current) return;
1371
+ void runQuery(true);
1372
+ };
1373
+ browser.addEventListener("focus", onFocus);
1374
+ return () => {
1375
+ browser.removeEventListener("focus", onFocus);
1376
+ };
1377
+ }, [client, runQuery]);
1378
+ react.useEffect(() => {
1379
+ const browser = getBrowserTarget();
1380
+ if (!browser || !enabledRef.current) {
1381
+ return void 0;
1382
+ }
1383
+ const refetchOnReconnect = refetchOnReconnectRef.current ?? client.defaultQueryOptions.refetchOnReconnect ?? false;
1384
+ if (!refetchOnReconnect) {
1385
+ return void 0;
1386
+ }
1387
+ const onReconnect = () => {
1388
+ if (!enabledRef.current) return;
1389
+ void runQuery(true);
1390
+ };
1391
+ browser.addEventListener("online", onReconnect);
1392
+ return () => {
1393
+ browser.removeEventListener("online", onReconnect);
1394
+ };
1395
+ }, [client, runQuery]);
1396
+ const refetch = react.useCallback(() => runQuery(true), [runQuery]);
1397
+ const reset = react.useCallback(() => {
1398
+ client.resetQuery(queryKeyRef.current);
1399
+ }, [client]);
1400
+ return {
1401
+ data: effectiveSnapshot.data,
1402
+ error: effectiveSnapshot.error,
1403
+ isLoading: effectiveSnapshot.status === "loading" && effectiveSnapshot.data === void 0,
1404
+ isFetching: effectiveSnapshot.isFetching,
1405
+ isSuccess: effectiveSnapshot.status === "success",
1406
+ isError: effectiveSnapshot.status === "error",
1407
+ status: effectiveSnapshot.status,
1408
+ refetch,
1409
+ reset,
1410
+ lastResponse: effectiveSnapshot.lastResponse,
1411
+ lastRequest: effectiveSnapshot.lastRequest
1412
+ };
1413
+ }
1414
+ function useMutation(options) {
1415
+ const client = useAthenaQueryClient();
1416
+ const mutationKeyRef = react.useRef(options.mutationKey);
1417
+ mutationKeyRef.current = options.mutationKey;
1418
+ const mutationFnRef = react.useRef(options.mutationFn);
1419
+ mutationFnRef.current = options.mutationFn;
1420
+ const selectRef = react.useRef(options.select);
1421
+ selectRef.current = options.select;
1422
+ const retryRef = react.useRef(options.retry);
1423
+ retryRef.current = options.retry;
1424
+ const retryDelayRef = react.useRef(options.retryDelay);
1425
+ retryDelayRef.current = options.retryDelay;
1426
+ const onMutateRef = react.useRef(options.onMutate);
1427
+ onMutateRef.current = options.onMutate;
1428
+ const onSuccessRef = react.useRef(options.onSuccess);
1429
+ onSuccessRef.current = options.onSuccess;
1430
+ const onErrorRef = react.useRef(options.onError);
1431
+ onErrorRef.current = options.onError;
1432
+ const onSettledRef = react.useRef(options.onSettled);
1433
+ onSettledRef.current = options.onSettled;
1434
+ const mutationKeyToken = react.useMemo(
1435
+ () => client.getMutationKeyToken(options.mutationKey),
1436
+ [client, options.mutationKey]
1437
+ );
1438
+ const subscribe = react.useCallback(
1439
+ (listener) => client.subscribeMutation(mutationKeyToken, listener),
1440
+ [client, mutationKeyToken]
1441
+ );
1442
+ const getSnapshot = react.useCallback(
1443
+ () => client.getMutationState(mutationKeyToken),
1444
+ [client, mutationKeyToken]
1445
+ );
1446
+ const snapshot = shim.useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
1447
+ const mutateAsync = react.useCallback(
1448
+ async (variables) => {
1449
+ await onMutateRef.current?.(variables);
1450
+ const result = await client.executeMutation({
1451
+ mutationKey: mutationKeyRef.current,
1452
+ mutationKeyToken,
1453
+ variables,
1454
+ mutationFn: (currentVariables) => mutationFnRef.current(currentVariables),
1455
+ select: selectRef.current,
1456
+ retry: retryRef.current ?? client.defaultMutationOptions.retry ?? 0,
1457
+ retryDelay: retryDelayRef.current ?? client.defaultMutationOptions.retryDelay
1458
+ });
1459
+ if (result.error) {
1460
+ onErrorRef.current?.(result.error, variables);
1461
+ onSettledRef.current?.(result.data, result.error, variables);
1462
+ throw result.error;
1463
+ }
1464
+ const data = result.data;
1465
+ onSuccessRef.current?.(data, variables);
1466
+ onSettledRef.current?.(data, null, variables);
1467
+ return data;
1468
+ },
1469
+ [client, mutationKeyToken]
1470
+ );
1471
+ const mutate = react.useCallback(
1472
+ (variables) => {
1473
+ void mutateAsync(variables).catch(() => void 0);
1474
+ },
1475
+ [mutateAsync]
1476
+ );
1477
+ const reset = react.useCallback(() => {
1478
+ client.resetMutation(mutationKeyRef.current);
1479
+ }, [client]);
1480
+ return {
1481
+ mutate,
1482
+ mutateAsync,
1483
+ data: snapshot.data,
1484
+ error: snapshot.error,
1485
+ isIdle: snapshot.status === "idle",
1486
+ isLoading: snapshot.status === "loading",
1487
+ isSuccess: snapshot.status === "success",
1488
+ isError: snapshot.status === "error",
1489
+ status: snapshot.status,
1490
+ reset,
1491
+ lastResponse: snapshot.lastResponse,
1492
+ lastVariables: snapshot.lastVariables,
1493
+ lastRequest: snapshot.lastRequest
1494
+ };
1495
+ }
1496
+
539
1497
  exports.AthenaGatewayError = AthenaGatewayError;
1498
+ exports.AthenaQueryClient = AthenaQueryClient;
1499
+ exports.AthenaQueryClientProvider = AthenaQueryClientProvider;
1500
+ exports.attachStateAdapter = attachStateAdapter;
1501
+ exports.createAthenaQueryClient = createAthenaQueryClient;
540
1502
  exports.isAthenaGatewayError = isAthenaGatewayError;
541
1503
  exports.useAthenaGateway = useAthenaGateway;
1504
+ exports.useAthenaQueryClient = useAthenaQueryClient;
1505
+ exports.useMutation = useMutation;
1506
+ exports.useQuery = useQuery;
542
1507
  //# sourceMappingURL=react.cjs.map
543
1508
  //# sourceMappingURL=react.cjs.map