@nexushub/client 1.1.6 → 1.1.8

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
@@ -829,14 +829,14 @@ var ContentEngine = class {
829
829
  this.localCache = new LocalCacheProxy();
830
830
  this.memoryCache = new MemoryCache({
831
831
  maxSize: 500,
832
- ttl: 5 * 60 * 1e3
833
- // 5 minutes
832
+ ttl: 5 * 1e3
833
+ // 👈 5 seconds
834
834
  });
835
835
  if (!this.isServer) {
836
836
  this.browserCache = new BrowserCache(config.projectId);
837
837
  }
838
838
  this.rateLimiter = new RateLimiter({
839
- maxRequests: config.debug ? 100 : 50,
839
+ maxRequests: config.debug ? 200 : 100,
840
840
  timeWindow: 6e4
841
841
  });
842
842
  this.backoff = new ExponentialBackoff({
@@ -853,15 +853,11 @@ var ContentEngine = class {
853
853
  window.addEventListener("beforeunload", this.cleanup.bind(this));
854
854
  }
855
855
  }
856
- /** Update runtime configuration without exposing internal mutation. */
857
856
  updateConfig(config) {
858
857
  this.config = config;
859
858
  this.defaultRevalidate = _nullishCoalesce(config.revalidateTime, () => ( false));
860
859
  this.cacheStrategy = config.cacheStrategy || "memory";
861
860
  }
862
- /**
863
- * Fetch a Single Page with full strategy pipeline
864
- */
865
861
  async getPage(slug, options = {}) {
866
862
  const { result, duration } = _chunkOP3LNZPCcjs.measurePerformance.call(void 0,
867
863
  `getPage("${slug}")`,
@@ -883,66 +879,66 @@ var ContentEngine = class {
883
879
  includeMetadata = false
884
880
  } = options;
885
881
  const cacheKey = `page:${slug}`;
886
- const cached = await this.checkCaches(
887
- cacheKey,
888
- forceRefresh,
889
- includeMetadata
890
- );
891
- if (cached) {
892
- if (this.config.debug) console.log(`[NexusHub] \u26A1 Cache hit: ${slug}`);
893
- return includeMetadata ? cached : cached.data;
882
+ if (!this.isServer && !forceRefresh && this.cacheStrategy === "memory") {
883
+ const cached = this.memoryCache.get(cacheKey);
884
+ if (cached && this.isCacheValid(cached.metadata)) {
885
+ return includeMetadata ? cached : cached.data;
886
+ }
887
+ }
888
+ if (!forceRefresh && process.env.NODE_ENV === "development") {
889
+ try {
890
+ const local = await this.localCache.getPage(slug);
891
+ if (local) {
892
+ return includeMetadata ? {
893
+ data: local,
894
+ metadata: {
895
+ timestamp: Date.now(),
896
+ expiresAt: Infinity,
897
+ tags: []
898
+ }
899
+ } : local;
900
+ }
901
+ } catch (e6) {
902
+ }
894
903
  }
895
904
  if (this.circuitBreaker.isOpen()) {
896
- throw new Error(`[NexusHub] Circuit open. API is unavailable.`);
905
+ throw new Error("[NexusHub] Circuit open. API is unavailable.");
897
906
  }
898
907
  try {
899
908
  await this.rateLimiter.checkLimit();
900
- const data = await this.backoff.execute(
901
- async () => {
902
- return this.fetchPage(
903
- slug,
904
- cacheKey,
905
- tags,
906
- revalidate,
907
- forceRefresh
908
- );
909
- },
910
- (attempt, delay, error) => {
911
- if (this.config.debug) {
912
- console.log(
913
- `[NexusHub] \u{1F504} Retry ${attempt} for '${slug}' after ${delay}ms: ${error.message}`
914
- );
915
- }
916
- }
917
- );
909
+ const data = await this.backoff.execute(async () => {
910
+ return this.fetchPage(
911
+ slug,
912
+ cacheKey,
913
+ tags,
914
+ revalidate,
915
+ forceRefresh
916
+ );
917
+ });
918
918
  this.circuitBreaker.recordSuccess();
919
919
  return includeMetadata ? data : data.data;
920
920
  } catch (error) {
921
921
  this.circuitBreaker.recordFailure();
922
- const staleCache = this.memoryCache.get(cacheKey);
923
- if (staleCache && !forceRefresh) {
924
- console.warn(`[NexusHub] \u26A0\uFE0F Serving stale content for '${slug}'`);
925
- return includeMetadata ? staleCache : staleCache.data;
922
+ if (process.env.NODE_ENV === "development") {
923
+ try {
924
+ const local = await this.localCache.getPage(slug);
925
+ if (local) {
926
+ return includeMetadata ? {
927
+ data: local,
928
+ metadata: {
929
+ timestamp: Date.now(),
930
+ expiresAt: Infinity,
931
+ tags: []
932
+ }
933
+ } : local;
934
+ }
935
+ } catch (e7) {
936
+ }
926
937
  }
927
938
  throw this.normalizeError(error, `Failed to fetch page '${slug}'`);
928
939
  }
929
940
  }
930
- /**
931
- * Fetch a Collection (Optimized)
932
- */
933
941
  async getCollection(collectionId, query = {}, options = {}) {
934
- const { result, duration } = _chunkOP3LNZPCcjs.measurePerformance.call(void 0,
935
- `getCollection("${collectionId}")`,
936
- () => this._getCollection(collectionId, query, options)
937
- );
938
- if (this.config.debug && duration > 100) {
939
- console.warn(
940
- `[NexusHub] \u26A0\uFE0F getCollection("${collectionId}") took ${duration.toFixed(2)}ms`
941
- );
942
- }
943
- return result;
944
- }
945
- async _getCollection(collectionId, query = {}, options = {}) {
946
942
  const normalizedQuery = _chunkOP3LNZPCcjs.normalizeQuery.call(void 0, query);
947
943
  const {
948
944
  revalidate = this.defaultRevalidate,
@@ -952,20 +948,13 @@ var ContentEngine = class {
952
948
  } = options;
953
949
  const queryString = _chunkOP3LNZPCcjs.buildQueryString.call(void 0, normalizedQuery);
954
950
  const cacheKey = `collection:${collectionId}:${queryString}`;
955
- const cached = await this.checkCaches(
956
- cacheKey,
957
- forceRefresh,
958
- includeMetadata
959
- );
960
- if (cached) {
961
- if (this.config.debug) {
962
- console.log(
963
- `[NexusHub] \u26A1 Served collection '${collectionId}' from memory cache.`
964
- );
951
+ if (!this.isServer && !forceRefresh && this.cacheStrategy === "memory") {
952
+ const cached = this.memoryCache.get(cacheKey);
953
+ if (cached && this.isCacheValid(cached.metadata)) {
954
+ return includeMetadata ? cached : cached.data;
965
955
  }
966
- return includeMetadata ? cached : cached.data;
967
956
  }
968
- if (!forceRefresh) {
957
+ if (!forceRefresh && process.env.NODE_ENV === "development") {
969
958
  try {
970
959
  const localCollection = await this.localCache.getCollection(collectionId);
971
960
  if (localCollection) {
@@ -973,21 +962,14 @@ var ContentEngine = class {
973
962
  localCollection,
974
963
  normalizedQuery
975
964
  );
976
- if (this.config.debug) {
977
- console.log(
978
- `[NexusHub] \u{1F4C1} Compiled collection '${collectionId}' from local offline binaries.`
979
- );
980
- }
981
- this.memoryCache.set(cacheKey, result, {
982
- tags: [...tags, CacheTags.collection(collectionId)],
983
- revalidate: revalidate === false ? void 0 : revalidate
984
- });
985
965
  return result;
986
966
  }
987
- } catch (e6) {
967
+ } catch (e8) {
988
968
  }
989
969
  }
990
- if (this.circuitBreaker.isOpen()) throw new Error("Circuit open");
970
+ if (this.circuitBreaker.isOpen()) {
971
+ throw new Error("[NexusHub] Circuit open. API is unavailable.");
972
+ }
991
973
  try {
992
974
  await this.rateLimiter.checkLimit();
993
975
  const result = await this.backoff.execute(async () => {
@@ -996,19 +978,25 @@ var ContentEngine = class {
996
978
  normalizedQuery,
997
979
  cacheKey,
998
980
  tags,
999
- revalidate
981
+ revalidate,
982
+ forceRefresh
1000
983
  );
1001
984
  });
1002
985
  this.circuitBreaker.recordSuccess();
1003
986
  return includeMetadata ? result : result.data;
1004
987
  } catch (error) {
1005
988
  this.circuitBreaker.recordFailure();
1006
- const staleCache = this.memoryCache.get(cacheKey);
1007
- if (staleCache && !forceRefresh) {
1008
- console.warn(
1009
- `[NexusHub] \u26A0\uFE0F Using stale cache for collection '${collectionId}'`
1010
- );
1011
- return includeMetadata ? staleCache : staleCache.data;
989
+ if (process.env.NODE_ENV === "development") {
990
+ try {
991
+ const localCollection = await this.localCache.getCollection(collectionId);
992
+ if (localCollection) {
993
+ return this.applyLocalQuery(
994
+ localCollection,
995
+ normalizedQuery
996
+ );
997
+ }
998
+ } catch (e9) {
999
+ }
1012
1000
  }
1013
1001
  throw this.normalizeError(
1014
1002
  error,
@@ -1016,9 +1004,6 @@ var ContentEngine = class {
1016
1004
  );
1017
1005
  }
1018
1006
  }
1019
- /**
1020
- * Fetch Global Settings
1021
- */
1022
1007
  async getGlobals(options = {}) {
1023
1008
  const {
1024
1009
  include = [],
@@ -1026,31 +1011,19 @@ var ContentEngine = class {
1026
1011
  forceRefresh = false
1027
1012
  } = options;
1028
1013
  const cacheKey = `globals:${include.join(",")}`;
1029
- if (!forceRefresh && this.cacheStrategy === "memory") {
1014
+ if (!this.isServer && !forceRefresh && this.cacheStrategy === "memory") {
1030
1015
  const cached = this.memoryCache.get(cacheKey);
1031
1016
  if (cached && this.isCacheValid(cached.metadata)) {
1032
- if (this.config.debug)
1033
- console.log("[NexusHub] \u26A1 Served globals from memory cache.");
1034
1017
  return cached.data;
1035
1018
  }
1036
1019
  }
1037
- if (!forceRefresh && !this.isServer && this.cacheStrategy === "localStorage" && this.browserCache) {
1038
- const cached = this.browserCache.get(cacheKey);
1039
- if (cached) {
1040
- return cached;
1041
- }
1042
- }
1043
- if (!forceRefresh) {
1020
+ if (!forceRefresh && process.env.NODE_ENV === "development") {
1044
1021
  try {
1045
1022
  const localGlobals = await this.localCache.getGlobals();
1046
1023
  if (localGlobals) {
1047
- this.memoryCache.set(cacheKey, localGlobals, {
1048
- tags: [CacheTags.global],
1049
- revalidate: revalidate === false ? void 0 : revalidate
1050
- });
1051
1024
  return localGlobals;
1052
1025
  }
1053
- } catch (e7) {
1026
+ } catch (e10) {
1054
1027
  }
1055
1028
  }
1056
1029
  try {
@@ -1066,80 +1039,79 @@ var ContentEngine = class {
1066
1039
  method: "GET",
1067
1040
  headers: this.getHeaders(),
1068
1041
  tags: fetchTags,
1069
- revalidate
1042
+ revalidate,
1043
+ forceRefresh
1070
1044
  });
1071
1045
  if (!res.ok) {
1072
- if (res.status === 408) {
1073
- throw new Error("Request timeout");
1074
- }
1075
1046
  throw new Error(`API Error ${res.status}: ${res.statusText}`);
1076
1047
  }
1077
1048
  const json = await res.json();
1078
1049
  const data = json.data || json;
1079
- this.writeCache(cacheKey, data, {
1080
- revalidate,
1081
- tags: [CacheTags.project(this.config.projectId), CacheTags.global]
1082
- });
1050
+ if (!this.isServer) {
1051
+ this.writeCache(cacheKey, data, {
1052
+ revalidate,
1053
+ tags: fetchTags
1054
+ });
1055
+ }
1083
1056
  return data;
1084
1057
  } catch (error) {
1085
- const staleCache = this.memoryCache.get(cacheKey);
1086
- if (staleCache && !forceRefresh) {
1087
- console.warn("[NexusHub] \u26A0\uFE0F Using stale cache for globals");
1088
- return staleCache.data;
1058
+ if (process.env.NODE_ENV === "development") {
1059
+ try {
1060
+ const localGlobals = await this.localCache.getGlobals();
1061
+ if (localGlobals) {
1062
+ return localGlobals;
1063
+ }
1064
+ } catch (e11) {
1065
+ }
1089
1066
  }
1090
1067
  throw this.normalizeError(error, "Failed to fetch globals");
1091
1068
  }
1092
1069
  }
1093
- /**
1094
- * Get a single item from a collection (Uses Request Batching)
1095
- */
1096
1070
  async getItem(collectionId, itemId, options = {}) {
1071
+ const { forceRefresh = false } = options;
1097
1072
  const cacheKey = `item:${collectionId}:${itemId}`;
1098
- if (this.cacheStrategy === "memory") {
1073
+ if (!this.isServer && !forceRefresh && this.cacheStrategy === "memory") {
1099
1074
  const cached = this.memoryCache.get(cacheKey);
1100
1075
  if (cached && this.isCacheValid(cached.metadata)) {
1101
- if (this.config.debug) {
1102
- console.log(`[NexusHub] \u26A1 Served item '${itemId}' from cache.`);
1103
- }
1104
1076
  return cached.data;
1105
1077
  }
1106
1078
  }
1107
- return this.requestBatcher.schedule(cacheKey, async () => {
1108
- const params = new URLSearchParams();
1109
- if (_optionalChain([options, 'access', _17 => _17.include, 'optionalAccess', _18 => _18.length])) {
1110
- params.append("include", options.include.join(","));
1111
- }
1112
- const url = `${this.config.apiUrl}/content/${this.config.projectId}/collection/${collectionId}/${itemId}?${params}`;
1113
- const fetchTags = [
1114
- CacheTags.project(this.config.projectId),
1115
- CacheTags.collection(collectionId),
1116
- `item_${itemId}`,
1117
- ...options.tags || []
1118
- ];
1119
- const res = await this.fetchWithTimeout(url, {
1120
- method: "GET",
1121
- headers: this.getHeaders(),
1122
- tags: fetchTags,
1123
- revalidate: _nullishCoalesce(options.revalidate, () => ( this.defaultRevalidate))
1124
- });
1125
- if (!res.ok) {
1126
- if (res.status === 408) {
1127
- throw new Error("Request timeout");
1079
+ return this.requestBatcher.schedule(
1080
+ forceRefresh ? `${cacheKey}:refresh:${Date.now()}` : cacheKey,
1081
+ async () => {
1082
+ const params = new URLSearchParams();
1083
+ if (_optionalChain([options, 'access', _17 => _17.include, 'optionalAccess', _18 => _18.length])) {
1084
+ params.append("include", options.include.join(","));
1128
1085
  }
1129
- throw new Error(`API Error ${res.status}: ${res.statusText}`);
1086
+ const url = `${this.config.apiUrl}/content/${this.config.projectId}/collection/${collectionId}/${itemId}?${params}`;
1087
+ const fetchTags = [
1088
+ CacheTags.project(this.config.projectId),
1089
+ CacheTags.collection(collectionId),
1090
+ `item_${itemId}`,
1091
+ ...options.tags || []
1092
+ ];
1093
+ const res = await this.fetchWithTimeout(url, {
1094
+ method: "GET",
1095
+ headers: this.getHeaders(),
1096
+ tags: fetchTags,
1097
+ revalidate: _nullishCoalesce(options.revalidate, () => ( this.defaultRevalidate)),
1098
+ forceRefresh
1099
+ });
1100
+ if (!res.ok) {
1101
+ throw new Error(`API Error ${res.status}: ${res.statusText}`);
1102
+ }
1103
+ const json = await res.json();
1104
+ const data = json.data || json;
1105
+ if (!this.isServer) {
1106
+ this.writeCache(cacheKey, data, {
1107
+ revalidate: _nullishCoalesce(options.revalidate, () => ( this.defaultRevalidate)),
1108
+ tags: fetchTags
1109
+ });
1110
+ }
1111
+ return data;
1130
1112
  }
1131
- const json = await res.json();
1132
- const data = json.data || json;
1133
- this.writeCache(cacheKey, data, {
1134
- revalidate: _nullishCoalesce(options.revalidate, () => ( this.defaultRevalidate)),
1135
- tags: fetchTags
1136
- });
1137
- return data;
1138
- });
1113
+ );
1139
1114
  }
1140
- /**
1141
- * Search across collections
1142
- */
1143
1115
  async search(query, options = {}) {
1144
1116
  const params = new URLSearchParams({
1145
1117
  q: query,
@@ -1152,65 +1124,61 @@ var ContentEngine = class {
1152
1124
  params.append("fields", options.fields.join(","));
1153
1125
  }
1154
1126
  const url = `${this.config.apiUrl}/content/${this.config.projectId}/search?${params}`;
1127
+ const fetchTags = [
1128
+ CacheTags.project(this.config.projectId),
1129
+ ...(options.collections || []).map(
1130
+ (collection) => CacheTags.collection(collection)
1131
+ )
1132
+ ];
1155
1133
  const res = await this.fetchWithTimeout(url, {
1156
1134
  method: "GET",
1157
- headers: this.getHeaders()
1135
+ headers: this.getHeaders(),
1136
+ tags: fetchTags,
1137
+ revalidate: _nullishCoalesce(options.revalidate, () => ( this.defaultRevalidate)),
1138
+ forceRefresh: _nullishCoalesce(options.forceRefresh, () => ( false))
1158
1139
  });
1159
1140
  if (!res.ok) {
1160
- if (res.status === 408) {
1161
- throw new Error("Request timeout");
1162
- }
1163
1141
  throw new Error(`API Error ${res.status}: ${res.statusText}`);
1164
1142
  }
1165
1143
  return await res.json();
1166
1144
  }
1167
- /**
1168
- * Prefetch content
1169
- */
1170
1145
  async prefetch(urls) {
1171
1146
  if (typeof window !== "undefined" && "requestIdleCallback" in window) {
1172
1147
  requestIdleCallback(async () => {
1173
1148
  await Promise.allSettled(
1174
- urls.map((url) => fetch(url, { priority: "low" }))
1149
+ urls.map(
1150
+ (url) => fetch(url, {
1151
+ priority: "low"
1152
+ })
1153
+ )
1175
1154
  );
1176
1155
  });
1177
1156
  }
1178
1157
  }
1179
- /**
1180
- * Robust Real-time Subscriptions (SSE) with Auto-Reconnect
1181
- */
1182
1158
  subscribeToUpdates(callback) {
1183
1159
  if (this.isServer || typeof EventSource === "undefined") {
1184
- if (this.config.debug) {
1185
- console.warn(
1186
- "[NexusHub] subscribeToUpdates() called in a non-browser environment."
1187
- );
1188
- }
1189
1160
  return () => {
1190
1161
  };
1191
1162
  }
1192
1163
  if (!this.config.apiKey) {
1193
- console.warn("[NexusHub] subscribeToUpdates(): no apiKey configured.");
1164
+ return () => {
1165
+ };
1194
1166
  }
1195
1167
  let eventSource = null;
1196
1168
  let retryCount = 0;
1197
1169
  let isClosed = false;
1198
- const MAX_RETRY_DELAY_MS = 3e4;
1199
1170
  const connect = () => {
1200
1171
  if (isClosed) return;
1201
1172
  const url = `${this.config.apiUrl}/content/${this.config.projectId}/updates?key=${_nullishCoalesce(this.config.apiKey, () => ( ""))}`;
1202
1173
  eventSource = new EventSource(url);
1203
1174
  eventSource.onopen = () => {
1204
1175
  retryCount = 0;
1205
- if (this.config.debug)
1206
- console.log("[NexusHub] \u{1F7E2} Real-time stream connected");
1207
1176
  };
1208
1177
  eventSource.onmessage = (event) => {
1209
1178
  let data;
1210
1179
  try {
1211
1180
  data = JSON.parse(event.data);
1212
- } catch (e) {
1213
- console.error("[NexusHub] SSE Parse Error", e);
1181
+ } catch (e12) {
1214
1182
  return;
1215
1183
  }
1216
1184
  if (!data || typeof data.type !== "string") {
@@ -1222,6 +1190,9 @@ var ContentEngine = class {
1222
1190
  if (data.type === "collection.updated" && data.collectionId) {
1223
1191
  this.invalidateCache([CacheTags.collection(data.collectionId)]);
1224
1192
  }
1193
+ if (data.type === "globals.updated") {
1194
+ this.invalidateCache([CacheTags.global]);
1195
+ }
1225
1196
  if (data.type === "schema.updated") {
1226
1197
  this.clearCache();
1227
1198
  }
@@ -1230,16 +1201,8 @@ var ContentEngine = class {
1230
1201
  eventSource.onerror = () => {
1231
1202
  _optionalChain([eventSource, 'optionalAccess', _23 => _23.close, 'call', _24 => _24()]);
1232
1203
  if (isClosed) return;
1233
- const timeout = Math.min(
1234
- 1e3 * Math.pow(2, retryCount),
1235
- MAX_RETRY_DELAY_MS
1236
- );
1204
+ const timeout = Math.min(1e3 * Math.pow(2, retryCount), 3e4);
1237
1205
  retryCount++;
1238
- if (this.config.debug) {
1239
- console.warn(
1240
- `[NexusHub] \u{1F534} Stream disconnected. Reconnecting in ${timeout}ms...`
1241
- );
1242
- }
1243
1206
  setTimeout(connect, timeout);
1244
1207
  };
1245
1208
  };
@@ -1249,70 +1212,19 @@ var ContentEngine = class {
1249
1212
  _optionalChain([eventSource, 'optionalAccess', _25 => _25.close, 'call', _26 => _26()]);
1250
1213
  };
1251
1214
  }
1252
- // --- CACHE MANAGEMENT ---
1253
- async checkCaches(key, forceRefresh, includeMetadata) {
1254
- if (forceRefresh) return null;
1255
- if (this.cacheStrategy === "memory") {
1256
- const cached = this.memoryCache.get(key);
1257
- if (cached && this.isCacheValid(cached.metadata)) {
1258
- return cached;
1259
- }
1260
- }
1261
- if (!this.isServer && this.cacheStrategy === "localStorage" && this.browserCache) {
1262
- const cached = this.browserCache.get(key);
1263
- if (cached) {
1264
- return {
1265
- data: cached,
1266
- metadata: {
1267
- timestamp: 0,
1268
- expiresAt: Infinity,
1269
- tags: [],
1270
- etag: void 0
1271
- }
1272
- };
1273
- }
1274
- }
1275
- if (key.startsWith("page:")) {
1276
- const slug = key.split(":")[1];
1277
- try {
1278
- const local = await this.localCache.getPage(slug);
1279
- if (local && (process.env.NODE_ENV === "development" || !this.config.apiKey)) {
1280
- return {
1281
- data: local,
1282
- metadata: {
1283
- timestamp: Date.now(),
1284
- expiresAt: Infinity,
1285
- tags: [
1286
- CacheTags.content(slug),
1287
- CacheTags.project(this.config.projectId)
1288
- ],
1289
- etag: void 0
1290
- }
1291
- };
1292
- }
1293
- } catch (e8) {
1294
- }
1295
- }
1296
- return null;
1297
- }
1298
1215
  writeCache(key, data, options) {
1299
- const numericRevalidate = options.revalidate === false ? 31536e5 : options.revalidate;
1216
+ const ttlSeconds = options.revalidate === false ? 60 : Math.max(1, options.revalidate);
1300
1217
  if (this.cacheStrategy === "memory") {
1301
1218
  this.memoryCache.set(key, data, {
1302
1219
  tags: options.tags,
1303
- revalidate: numericRevalidate
1220
+ ttl: ttlSeconds * 1e3
1304
1221
  });
1305
1222
  }
1306
- if (!this.isServer && this.cacheStrategy === "localStorage" && this.browserCache) {
1307
- this.browserCache.set(key, data, numericRevalidate * 1e3);
1308
- }
1309
1223
  }
1310
1224
  invalidateCache(tags) {
1311
1225
  this.memoryCache.invalidateByTags(tags);
1312
- if (this.config.debug) {
1313
- console.log(
1314
- `[NexusHub] \u267B\uFE0F Invalidated cache for tags: ${tags.join(", ")}`
1315
- );
1226
+ if (this.browserCache) {
1227
+ this.browserCache.clear();
1316
1228
  }
1317
1229
  }
1318
1230
  clearCache() {
@@ -1320,24 +1232,17 @@ var ContentEngine = class {
1320
1232
  if (this.browserCache) {
1321
1233
  this.browserCache.clear();
1322
1234
  }
1323
- if (this.config.debug) {
1324
- console.log("[NexusHub] \u{1F9F9} Cleared all caches");
1325
- }
1326
1235
  }
1327
1236
  getCacheStats() {
1328
- const stats = {
1237
+ return {
1329
1238
  memory: this.memoryCache.getStats(),
1330
- local: { loaded: this.localCache.isLoaded() }
1239
+ local: {
1240
+ loaded: this.localCache.isLoaded()
1241
+ }
1331
1242
  };
1332
- if (this.browserCache) {
1333
- stats.browser = { size: 0 };
1334
- }
1335
- return stats;
1336
1243
  }
1337
- // --- REQUEST METHODS ---
1338
1244
  async fetchPage(slug, cacheKey, tags, revalidate, forceRefresh) {
1339
1245
  const url = `${this.config.apiUrl}/content/${this.config.projectId}/page/${slug}`;
1340
- const expiresAt = revalidate === false ? Infinity : Date.now() + revalidate * 1e3;
1341
1246
  const fetchTags = [
1342
1247
  CacheTags.project(this.config.projectId),
1343
1248
  CacheTags.content(slug),
@@ -1347,13 +1252,12 @@ var ContentEngine = class {
1347
1252
  method: "GET",
1348
1253
  headers: this.getHeaders(),
1349
1254
  tags: fetchTags,
1350
- revalidate
1255
+ revalidate,
1256
+ forceRefresh
1351
1257
  });
1352
1258
  if (!res.ok) {
1353
1259
  if (res.status === 404) {
1354
- throw new Error(
1355
- `Page '${slug}' not found. Check your Dashboard or Seed data.`
1356
- );
1260
+ throw new Error(`Page '${slug}' not found.`);
1357
1261
  }
1358
1262
  if (res.status === 408) {
1359
1263
  throw new Error("Request timeout");
@@ -1367,17 +1271,19 @@ var ContentEngine = class {
1367
1271
  metadata: {
1368
1272
  timestamp: Date.now(),
1369
1273
  etag: etag || void 0,
1370
- expiresAt,
1274
+ expiresAt: revalidate === false ? Infinity : Date.now() + revalidate * 1e3,
1371
1275
  tags: fetchTags
1372
1276
  }
1373
1277
  };
1374
- this.writeCache(cacheKey, cacheEntry.data, {
1375
- revalidate,
1376
- tags: fetchTags
1377
- });
1278
+ if (!this.isServer) {
1279
+ this.writeCache(cacheKey, cacheEntry.data, {
1280
+ revalidate,
1281
+ tags: fetchTags
1282
+ });
1283
+ }
1378
1284
  return cacheEntry;
1379
1285
  }
1380
- async fetchCollection(collectionId, query, cacheKey, tags, revalidate) {
1286
+ async fetchCollection(collectionId, query, cacheKey, tags, revalidate, forceRefresh) {
1381
1287
  const params = _chunkOP3LNZPCcjs.buildQueryString.call(void 0, query);
1382
1288
  const url = `${this.config.apiUrl}/content/${this.config.projectId}/collection/${collectionId}?${params}`;
1383
1289
  const fetchTags = [
@@ -1389,7 +1295,8 @@ var ContentEngine = class {
1389
1295
  method: "GET",
1390
1296
  headers: this.getHeaders(),
1391
1297
  tags: fetchTags,
1392
- revalidate
1298
+ revalidate,
1299
+ forceRefresh
1393
1300
  });
1394
1301
  if (!res.ok) {
1395
1302
  if (res.status === 408) {
@@ -1399,23 +1306,23 @@ var ContentEngine = class {
1399
1306
  }
1400
1307
  const json = await res.json();
1401
1308
  const etag = res.headers.get("etag");
1402
- const expiresAt = revalidate === false ? Infinity : Date.now() + revalidate * 1e3;
1403
1309
  const cacheEntry = {
1404
1310
  data: json,
1405
1311
  metadata: {
1406
1312
  timestamp: Date.now(),
1407
1313
  etag: etag || void 0,
1408
- expiresAt,
1314
+ expiresAt: revalidate === false ? Infinity : Date.now() + revalidate * 1e3,
1409
1315
  tags: fetchTags
1410
1316
  }
1411
1317
  };
1412
- this.writeCache(cacheKey, cacheEntry.data, {
1413
- revalidate,
1414
- tags: fetchTags
1415
- });
1318
+ if (!this.isServer) {
1319
+ this.writeCache(cacheKey, cacheEntry.data, {
1320
+ revalidate,
1321
+ tags: fetchTags
1322
+ });
1323
+ }
1416
1324
  return cacheEntry;
1417
1325
  }
1418
- // --- HELPER METHODS ---
1419
1326
  applyLocalQuery(items, query) {
1420
1327
  let filtered = [...items];
1421
1328
  if (query.search) {
@@ -1428,7 +1335,9 @@ var ContentEngine = class {
1428
1335
  filtered = filtered.filter((item) => {
1429
1336
  return Object.entries(query.filter).every(([key, value]) => {
1430
1337
  const itemValue = item[key];
1431
- if (itemValue === void 0) return false;
1338
+ if (itemValue === void 0) {
1339
+ return false;
1340
+ }
1432
1341
  if (Array.isArray(value)) {
1433
1342
  return value.includes(itemValue);
1434
1343
  }
@@ -1441,8 +1350,12 @@ var ContentEngine = class {
1441
1350
  const aVal = a[query.sort];
1442
1351
  const bVal = b[query.sort];
1443
1352
  const order = query.order === "asc" ? 1 : -1;
1444
- if (aVal < bVal) return -1 * order;
1445
- if (aVal > bVal) return 1 * order;
1353
+ if (aVal < bVal) {
1354
+ return -1 * order;
1355
+ }
1356
+ if (aVal > bVal) {
1357
+ return 1 * order;
1358
+ }
1446
1359
  return 0;
1447
1360
  });
1448
1361
  }
@@ -1466,15 +1379,18 @@ var ContentEngine = class {
1466
1379
  timeout = this.config.timeout || 1e4,
1467
1380
  tags = [],
1468
1381
  revalidate,
1382
+ forceRefresh = false,
1469
1383
  ...fetchOptions
1470
1384
  } = options;
1471
1385
  const controller = new AbortController();
1472
1386
  const id = setTimeout(() => controller.abort(), timeout);
1473
1387
  const nextConfig = this.isServer ? {
1474
- cache: revalidate === 0 ? "no-store" : "force-cache",
1475
- next: {
1476
- tags,
1477
- revalidate: revalidate === false ? false : revalidate
1388
+ cache: forceRefresh || revalidate === 0 ? "no-store" : "force-cache",
1389
+ ...forceRefresh ? {} : {
1390
+ next: {
1391
+ tags,
1392
+ revalidate: revalidate === false ? false : revalidate
1393
+ }
1478
1394
  }
1479
1395
  } : {};
1480
1396
  try {
@@ -1493,9 +1409,9 @@ var ContentEngine = class {
1493
1409
  getHeaders() {
1494
1410
  const headers = {
1495
1411
  "Content-Type": "application/json",
1496
- "X-Nexus-Client": `client-sdk/${_nullishCoalesce(this.config.sdkVersion, () => ( "1.1.0"))}`,
1497
- "X-Nexus-Request-ID": typeof crypto !== "undefined" && crypto.randomUUID ? crypto.randomUUID() : `nx_${Date.now()}_${Math.random().toString(36).slice(2)}`,
1498
- "X-Nexus-Project": this.config.projectId
1412
+ "X-GN-Apex-Client": `gnapex-sdk/${_nullishCoalesce(this.config.sdkVersion, () => ( "1.1.6"))}`,
1413
+ "X-GN-Apex-Request-ID": typeof crypto !== "undefined" && crypto.randomUUID ? crypto.randomUUID() : `nx_${Date.now()}_${Math.random().toString(36).slice(2)}`,
1414
+ "X-GN-Apex-Project": this.config.projectId
1499
1415
  };
1500
1416
  if (this.config.apiKey) {
1501
1417
  headers["Authorization"] = `Bearer ${this.config.apiKey}`;
@@ -1505,10 +1421,6 @@ var ContentEngine = class {
1505
1421
  isCacheValid(metadata) {
1506
1422
  return Date.now() < metadata.expiresAt;
1507
1423
  }
1508
- /**
1509
- * 🛡️ FIX: Normalizes timeout errors (AbortError, 408, or Timeout messages)
1510
- * into clean, standardized "Request timeout" errors.
1511
- */
1512
1424
  normalizeError(error, context) {
1513
1425
  if (error instanceof Error) {
1514
1426
  const msg = error.message.toLowerCase();
@@ -1523,14 +1435,7 @@ var ContentEngine = class {
1523
1435
  }
1524
1436
  return new Error(`${context}: ${String(error)}`);
1525
1437
  }
1526
- cancelRequests() {
1527
- if (this.abortController) {
1528
- this.abortController.abort();
1529
- this.abortController = new AbortController();
1530
- }
1531
- }
1532
1438
  cleanup() {
1533
- this.cancelRequests();
1534
1439
  if (!this.isServer) {
1535
1440
  window.removeEventListener("beforeunload", this.cleanup.bind(this));
1536
1441
  }
@@ -1581,7 +1486,7 @@ var generateCanvasHash = async () => {
1581
1486
  hash = hash & hash;
1582
1487
  }
1583
1488
  return hash.toString(16);
1584
- } catch (e9) {
1489
+ } catch (e13) {
1585
1490
  return "";
1586
1491
  }
1587
1492
  };
@@ -1812,20 +1717,20 @@ var eventStorage = new EventStorage();
1812
1717
  var safeGetItem = (key) => {
1813
1718
  try {
1814
1719
  return localStorage.getItem(key);
1815
- } catch (e10) {
1720
+ } catch (e14) {
1816
1721
  return null;
1817
1722
  }
1818
1723
  };
1819
1724
  var safeSetItem = (key, value) => {
1820
1725
  try {
1821
1726
  localStorage.setItem(key, value);
1822
- } catch (e11) {
1727
+ } catch (e15) {
1823
1728
  }
1824
1729
  };
1825
1730
  var safeRemoveItem = (key) => {
1826
1731
  try {
1827
1732
  localStorage.removeItem(key);
1828
- } catch (e12) {
1733
+ } catch (e16) {
1829
1734
  }
1830
1735
  };
1831
1736
  var generateUUID = () => {
@@ -1958,7 +1863,7 @@ var Tracker = class {
1958
1863
  keepalive: useBeacon
1959
1864
  }
1960
1865
  );
1961
- } catch (e13) {
1866
+ } catch (e17) {
1962
1867
  response = void 0;
1963
1868
  }
1964
1869
  if (!response || response.status === 404 || response.status === 405) {
@@ -2037,7 +1942,7 @@ function extractUtmParams(url) {
2037
1942
  if (val) result[key] = val;
2038
1943
  });
2039
1944
  return result;
2040
- } catch (e14) {
1945
+ } catch (e18) {
2041
1946
  return {};
2042
1947
  }
2043
1948
  }
@@ -2046,7 +1951,7 @@ function extractUtmParams(url) {
2046
1951
  var safeRemoveItem2 = (key) => {
2047
1952
  try {
2048
1953
  localStorage.removeItem(key);
2049
- } catch (e15) {
1954
+ } catch (e19) {
2050
1955
  }
2051
1956
  };
2052
1957
  var AnalyticsEngine = class {
@@ -2265,7 +2170,7 @@ var AnalyticsEngine = class {
2265
2170
  "outbound_click"
2266
2171
  );
2267
2172
  }
2268
- } catch (e16) {
2173
+ } catch (e20) {
2269
2174
  }
2270
2175
  };
2271
2176
  window.addEventListener("click", outboundHandler, { passive: true });
@@ -2522,7 +2427,7 @@ var NexusEventBus = class {
2522
2427
  _optionalChain([this, 'access', _49 => _49.listeners, 'access', _50 => _50.get, 'call', _51 => _51(event), 'optionalAccess', _52 => _52.forEach, 'call', _53 => _53((l) => {
2523
2428
  try {
2524
2429
  l(payload);
2525
- } catch (e17) {
2430
+ } catch (e21) {
2526
2431
  }
2527
2432
  })]);
2528
2433
  }
@@ -2622,7 +2527,7 @@ var NexusHttpClient = class {
2622
2527
  let details;
2623
2528
  try {
2624
2529
  details = await response.clone().json();
2625
- } catch (e18) {
2530
+ } catch (e22) {
2626
2531
  }
2627
2532
  const code = response.status === 404 ? "NOT_FOUND" : response.status === 429 ? "RATE_LIMITED" : "HTTP_ERROR";
2628
2533
  const err = new NexusError(
@@ -2979,7 +2884,7 @@ async function parseError(res) {
2979
2884
  code: json.code || "UNKNOWN_ERROR",
2980
2885
  message: json.message || "An error occurred during authentication"
2981
2886
  };
2982
- } catch (e19) {
2887
+ } catch (e23) {
2983
2888
  return {
2984
2889
  status: res.status,
2985
2890
  code: "NETWORK_ERROR",
@@ -3136,7 +3041,7 @@ var NexusProvider = ({
3136
3041
  try {
3137
3042
  const pushClient = new NexusPushClient(nexus.getConfig());
3138
3043
  await pushClient.requestSubscription("/sw.js");
3139
- } catch (e20) {
3044
+ } catch (e24) {
3140
3045
  }
3141
3046
  }
3142
3047
  }).catch((err) => {
@@ -3578,7 +3483,7 @@ function NexusCode({
3578
3483
  textArea.select();
3579
3484
  try {
3580
3485
  document.execCommand("copy");
3581
- } catch (e21) {
3486
+ } catch (e25) {
3582
3487
  }
3583
3488
  textArea.remove();
3584
3489
  }