amplifyquery 1.0.12 → 1.0.14

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/query.js CHANGED
@@ -134,7 +134,11 @@ function configure(options = {}) {
134
134
  maxAge: ((_a = config.storage) === null || _a === void 0 ? void 0 : _a.maxAge) || 1000 * 60 * 60 * 24 * 7, // Default 7 days
135
135
  dehydrateOptions: {
136
136
  shouldDehydrateQuery: (query) => {
137
- // Filter for queries not to cache (implement if needed)
137
+ var _a;
138
+ // Only persist successful queries to reduce hydration cancellation noise
139
+ if (((_a = query.state) === null || _a === void 0 ? void 0 : _a.status) !== "success")
140
+ return false;
141
+ // Avoid persisting mutation-like or transient keys if needed later
138
142
  return true;
139
143
  },
140
144
  },
@@ -169,7 +173,10 @@ function invalidateModel(modelName) {
169
173
  * @param id Item ID
170
174
  */
171
175
  function invalidateModelItem(modelName, id) {
172
- exports.queryClient.invalidateQueries({ queryKey: [modelName, id] });
176
+ // New item key
177
+ exports.queryClient.invalidateQueries({ queryKey: [modelName, "item", id] });
178
+ // Backward cleanup (in case legacy keys exist)
179
+ exports.queryClient.removeQueries({ queryKey: [modelName, id], exact: true });
173
180
  }
174
181
  /**
175
182
  * Invalidate model items with a specific field value
package/dist/service.js CHANGED
@@ -18,6 +18,15 @@ const react_query_1 = require("@tanstack/react-query");
18
18
  const auth_1 = require("aws-amplify/auth");
19
19
  const expo_crypto_1 = require("expo-crypto");
20
20
  const react_1 = require("react");
21
+ // -------------------------------
22
+ // Query key helpers
23
+ // -------------------------------
24
+ function itemKey(modelName, id) {
25
+ return [modelName, "item", id];
26
+ }
27
+ function isItemKeyForModel(modelName, key) {
28
+ return Array.isArray(key) && key[0] === modelName && key[1] === "item";
29
+ }
21
30
  /**
22
31
  * Utility function to get owner value based on authentication mode
23
32
  * Sets owner value only in userPool auth mode, returns empty string for other auth modes
@@ -58,9 +67,12 @@ function findRelatedQueryKeys(modelName, queryClient) {
58
67
  .getQueryCache()
59
68
  .findAll({
60
69
  predicate: ({ queryKey }) => {
61
- // Find all query keys starting with model name
62
- // Example: ["Mission"], ["Mission", "filter", ...], ["Daily", dailyId, "Mission"]
63
- return Array.isArray(queryKey) && queryKey[0] === modelName;
70
+ // Find all query keys for the model, but EXCLUDE single-item keys
71
+ // Examples kept: [model], [model, 'filter', ...], [model, 'query', ...], [model, Relation, id, ...]
72
+ // Excluded: [model, 'item', id]
73
+ return (Array.isArray(queryKey) &&
74
+ queryKey[0] === modelName &&
75
+ !isItemKeyForModel(modelName, queryKey));
64
76
  },
65
77
  })
66
78
  .map((query) => query.queryKey);
@@ -86,7 +98,7 @@ function performOptimisticUpdate(queryClient, modelName, relatedQueryKeys, itemI
86
98
  return previousDataMap; // 빈 맵 반환으로 rollback 시 영향 없음
87
99
  }
88
100
  // 1. Update individual item cache
89
- const singleItemQueryKey = [modelName, itemId];
101
+ const singleItemQueryKey = itemKey(modelName, itemId);
90
102
  const previousItemSingle = queryClient.getQueryData(singleItemQueryKey);
91
103
  previousDataMap.set(singleItemQueryKey, previousItemSingle);
92
104
  // Merge with existing data if available, otherwise use updateData as optimistic data
@@ -136,7 +148,7 @@ function handleCacheUpdateOnSuccess(queryClient, modelName, relatedQueryKeys, it
136
148
  if (actualItemId &&
137
149
  typeof actualItemId === "string" &&
138
150
  actualItemId === itemId) {
139
- queryClient.setQueryData([modelName, itemId], updatedItem);
151
+ queryClient.setQueryData(itemKey(modelName, itemId), updatedItem);
140
152
  }
141
153
  else {
142
154
  console.warn(`🍬 ${modelName} handleCacheUpdateOnSuccess: ID mismatch! Expected: ${itemId}, Actual: ${actualItemId}. Skipping cache update.`);
@@ -245,7 +257,7 @@ function createAmplifyService(modelName, defaultAuthMode) {
245
257
  // Backup previous data for optimistic update
246
258
  const previousDataMap = new Map();
247
259
  // Update individual item cache
248
- const singleItemQueryKey = [modelName, newItem.id];
260
+ const singleItemQueryKey = itemKey(modelName, newItem.id);
249
261
  const previousItemSingle = query_1.queryClient.getQueryData(singleItemQueryKey);
250
262
  previousDataMap.set(singleItemQueryKey, previousItemSingle);
251
263
  query_1.queryClient.setQueryData(singleItemQueryKey, newItem);
@@ -401,7 +413,7 @@ function createAmplifyService(modelName, defaultAuthMode) {
401
413
  });
402
414
  // Update individual item caches
403
415
  preparedItems.forEach((item) => {
404
- const singleItemQueryKey = [modelName, item.id];
416
+ const singleItemQueryKey = itemKey(modelName, item.id);
405
417
  const previousItemSingle = query_1.queryClient.getQueryData(singleItemQueryKey);
406
418
  previousDataMap.set(singleItemQueryKey, previousItemSingle);
407
419
  query_1.queryClient.setQueryData(singleItemQueryKey, item);
@@ -416,7 +428,7 @@ function createAmplifyService(modelName, defaultAuthMode) {
416
428
  const itemId = createdItem === null || createdItem === void 0 ? void 0 : createdItem.id;
417
429
  // 🔧 버그 수정: ID가 유효한 경우에만 개별 캐시에 저장
418
430
  if (itemId && typeof itemId === "string") {
419
- query_1.queryClient.setQueryData([modelName, itemId], createdItem);
431
+ query_1.queryClient.setQueryData(itemKey(modelName, itemId), createdItem);
420
432
  }
421
433
  else {
422
434
  console.warn(`🍬 ${modelName} createList: Invalid createdItem ID found, skipping cache update:`, itemId, createdItem);
@@ -465,7 +477,7 @@ function createAmplifyService(modelName, defaultAuthMode) {
465
477
  // Get item
466
478
  get: (id_1, ...args_1) => __awaiter(this, [id_1, ...args_1], void 0, function* (id, options = { forceRefresh: false }) {
467
479
  try {
468
- const singleItemQueryKey = [modelName, id];
480
+ const singleItemQueryKey = itemKey(modelName, id);
469
481
  // Check cache first (if forceRefresh is false)
470
482
  if (!options.forceRefresh) {
471
483
  const cachedItem = query_1.queryClient.getQueryData(singleItemQueryKey);
@@ -606,7 +618,7 @@ function createAmplifyService(modelName, defaultAuthMode) {
606
618
  const itemId = item === null || item === void 0 ? void 0 : item.id;
607
619
  // 🔧 버그 수정: ID가 유효한 경우에만 개별 캐시에 저장
608
620
  if (itemId && typeof itemId === "string") {
609
- query_1.queryClient.setQueryData([modelName, itemId], item);
621
+ query_1.queryClient.setQueryData(itemKey(modelName, itemId), item);
610
622
  }
611
623
  else {
612
624
  console.warn(`🍬 ${modelName} list: Invalid item ID found, skipping cache update:`, itemId, item);
@@ -661,7 +673,7 @@ function createAmplifyService(modelName, defaultAuthMode) {
661
673
  const itemId = item === null || item === void 0 ? void 0 : item.id;
662
674
  // 🔧 버그 수정: ID가 유효한 경우에만 개별 캐시에 저장
663
675
  if (itemId && typeof itemId === "string") {
664
- query_1.queryClient.setQueryData([modelName, itemId], item);
676
+ query_1.queryClient.setQueryData(itemKey(modelName, itemId), item);
665
677
  }
666
678
  else {
667
679
  console.warn(`🍬 ${modelName} list fallback: Invalid item ID found, skipping cache update:`, itemId, item);
@@ -727,7 +739,7 @@ function createAmplifyService(modelName, defaultAuthMode) {
727
739
  else {
728
740
  console.warn(`🍬 ${modelName} update API response missing. Maintaining optimistic update data.`);
729
741
  // If no API response, return the data saved during optimistic update
730
- const singleItemQueryKey = [modelName, itemId];
742
+ const singleItemQueryKey = itemKey(modelName, itemId);
731
743
  return (previousDataMap.get(singleItemQueryKey) || null);
732
744
  }
733
745
  }
@@ -759,7 +771,7 @@ function createAmplifyService(modelName, defaultAuthMode) {
759
771
  // Backup item data before deletion (for rollback)
760
772
  const previousDataMap = new Map();
761
773
  // Backup previous data and perform optimistic update for individual item (set to null)
762
- const singleItemQueryKey = [modelName, id];
774
+ const singleItemQueryKey = itemKey(modelName, id);
763
775
  const previousItemSingle = query_1.queryClient.getQueryData(singleItemQueryKey);
764
776
  previousDataMap.set(singleItemQueryKey, previousItemSingle);
765
777
  query_1.queryClient.setQueryData(singleItemQueryKey, null);
@@ -823,7 +835,7 @@ function createAmplifyService(modelName, defaultAuthMode) {
823
835
  // Optimistic update - remove items from all caches
824
836
  ids.forEach((id) => {
825
837
  // Backup previous data and perform optimistic update for individual item (null)
826
- const singleItemQueryKey = [modelName, id];
838
+ const singleItemQueryKey = itemKey(modelName, id);
827
839
  const previousItemSingle = query_1.queryClient.getQueryData(singleItemQueryKey);
828
840
  previousItemsCache.set(id, previousItemSingle || null);
829
841
  previousDataMap.set(singleItemQueryKey, previousItemSingle); // Backup to map
@@ -867,7 +879,7 @@ function createAmplifyService(modelName, defaultAuthMode) {
867
879
  const previousItem = previousItemsCache.get(failedId);
868
880
  if (previousItem !== undefined) {
869
881
  // Restore if not undefined (was in cache)
870
- const singleItemQueryKey = [modelName, failedId];
882
+ const singleItemQueryKey = itemKey(modelName, failedId);
871
883
  query_1.queryClient.setQueryData(singleItemQueryKey, previousItem);
872
884
  }
873
885
  // Restore failed item to list queries
@@ -892,7 +904,7 @@ function createAmplifyService(modelName, defaultAuthMode) {
892
904
  }
893
905
  // Invalidate all related queries to force refresh (safety mechanism)
894
906
  relatedQueryKeys.forEach((queryKey) => query_1.queryClient.invalidateQueries({ queryKey }));
895
- ids.forEach((id) => query_1.queryClient.invalidateQueries({ queryKey: [modelName, id] }));
907
+ ids.forEach((id) => query_1.queryClient.invalidateQueries({ queryKey: itemKey(modelName, id) }));
896
908
  console.log(`🍬 ${modelName} batch delete: ${results.success.length} items deleted, ${results.failed.length} items failed`);
897
909
  return results;
898
910
  }
@@ -949,7 +961,7 @@ function createAmplifyService(modelName, defaultAuthMode) {
949
961
  }
950
962
  else {
951
963
  console.warn(`🍬 ${modelName} upsert(update) no API response. Keeping optimistic update data.`);
952
- const singleItemQueryKey = [modelName, data.id];
964
+ const singleItemQueryKey = itemKey(modelName, data.id);
953
965
  return (previousDataMap.get(singleItemQueryKey) ||
954
966
  null);
955
967
  }
@@ -965,7 +977,7 @@ function createAmplifyService(modelName, defaultAuthMode) {
965
977
  }
966
978
  else {
967
979
  console.warn(`🍬 ${modelName} upsert(create) no API response. Keeping optimistic update data.`);
968
- const singleItemQueryKey = [modelName, data.id];
980
+ const singleItemQueryKey = itemKey(modelName, data.id);
969
981
  return (previousDataMap.get(singleItemQueryKey) ||
970
982
  null);
971
983
  }
@@ -1047,7 +1059,7 @@ function createAmplifyService(modelName, defaultAuthMode) {
1047
1059
  const itemId = item === null || item === void 0 ? void 0 : item.id;
1048
1060
  // 🔧 버그 수정: ID가 유효한 경우에만 개별 캐시에 저장
1049
1061
  if (itemId && typeof itemId === "string") {
1050
- query_1.queryClient.setQueryData([modelName, itemId], item);
1062
+ query_1.queryClient.setQueryData(itemKey(modelName, itemId), item);
1051
1063
  }
1052
1064
  else {
1053
1065
  console.warn(`🍬 ${modelName} customList: Invalid item ID found, skipping cache update:`, itemId, item);
@@ -1164,7 +1176,7 @@ function createAmplifyService(modelName, defaultAuthMode) {
1164
1176
  // Interface functions implementation
1165
1177
  const getItem = (0, react_1.useCallback)((id) => {
1166
1178
  // Use useQueryData to get latest single item from current cache
1167
- const cachedItem = hookQueryClient.getQueryData([modelName, id]);
1179
+ const cachedItem = hookQueryClient.getQueryData(itemKey(modelName, id));
1168
1180
  // 🔧 버그 수정: 캐시된 아이템의 ID가 요청한 ID와 일치하는지 검증
1169
1181
  if (cachedItem) {
1170
1182
  const itemId = cachedItem === null || cachedItem === void 0 ? void 0 : cachedItem.id;
@@ -1189,7 +1201,8 @@ function createAmplifyService(modelName, defaultAuthMode) {
1189
1201
  console.error(`🍬 ${modelName} useHook create error:`, _error);
1190
1202
  throw _error; // Re-throw error
1191
1203
  }
1192
- }), [service, refetch]);
1204
+ }), [service, refetch] // Add refetch dependency
1205
+ );
1193
1206
  const updateItem = (0, react_1.useCallback)((data) => __awaiter(this, void 0, void 0, function* () {
1194
1207
  try {
1195
1208
  const result = yield service.update(data);
@@ -1201,7 +1214,8 @@ function createAmplifyService(modelName, defaultAuthMode) {
1201
1214
  console.error(`🍬 ${modelName} useHook update error:`, _error);
1202
1215
  throw _error;
1203
1216
  }
1204
- }), [service, refetch]);
1217
+ }), [service, refetch] // Add refetch dependency
1218
+ );
1205
1219
  const deleteItem = (0, react_1.useCallback)((id) => __awaiter(this, void 0, void 0, function* () {
1206
1220
  try {
1207
1221
  const result = yield service.delete(id);
@@ -1213,7 +1227,8 @@ function createAmplifyService(modelName, defaultAuthMode) {
1213
1227
  console.error(`🍬 ${modelName} useHook delete error:`, error);
1214
1228
  throw error;
1215
1229
  }
1216
- }), [service, refetch]);
1230
+ }), [service, refetch] // refetch dependency added
1231
+ );
1217
1232
  const refresh = (0, react_1.useCallback)((refreshOptions) => __awaiter(this, void 0, void 0, function* () {
1218
1233
  console.log(`🍬 ${modelName} useHook refresh called`, queryKey);
1219
1234
  const { data } = yield refetch({ throwOnError: true }); // Throw on error
@@ -1244,7 +1259,7 @@ function createAmplifyService(modelName, defaultAuthMode) {
1244
1259
  // Hook for managing single item - Reimplemented based on TanStack Query
1245
1260
  useItemHook: (id) => {
1246
1261
  const hookQueryClient = (0, react_query_1.useQueryClient)();
1247
- const singleItemQueryKey = [modelName, id];
1262
+ const singleItemQueryKey = itemKey(modelName, id);
1248
1263
  // First check data from cache
1249
1264
  const rawCachedData = hookQueryClient.getQueryData(singleItemQueryKey);
1250
1265
  // 🔧 버그 수정: 배열이 캐시되어 있는 경우 처리
package/dist/singleton.js CHANGED
@@ -13,6 +13,7 @@ exports.getModelIds = void 0;
13
13
  exports.createSingletonService = createSingletonService;
14
14
  const client_1 = require("./client");
15
15
  const auth_1 = require("aws-amplify/auth");
16
+ const react_query_1 = require("@tanstack/react-query");
16
17
  /**
17
18
  * Function to create an extension service for singleton models
18
19
  * @param baseService Base service
@@ -32,7 +33,7 @@ function createSingletonService(baseService, getModelId) {
32
33
  return baseService.get(modelId, options);
33
34
  }
34
35
  catch (error) {
35
- console.error(`${modelName} singleton instance lookup error:`, error);
36
+ // console.error(`${modelName} singleton instance lookup error:`, error);
36
37
  // Safely call getStore
37
38
  try {
38
39
  (_c = (_b = (_a = baseService
@@ -122,7 +123,70 @@ function createSingletonService(baseService, getModelId) {
122
123
  console.error(`${modelName} singleton instance final Upsert error:`, error);
123
124
  return null;
124
125
  }
125
- }) });
126
+ }),
127
+ // React hook to manage the current singleton item
128
+ useCurrentHook: () => {
129
+ const { data: currentId, isLoading: isIdLoading, error: idError, refetch: refetchId, } = (0, react_query_1.useQuery)({
130
+ queryKey: [modelName, "currentId"],
131
+ queryFn: () => __awaiter(this, void 0, void 0, function* () {
132
+ var _a, _b, _c;
133
+ try {
134
+ const id = yield getModelId();
135
+ return id || null;
136
+ }
137
+ catch (error) {
138
+ try {
139
+ (_c = (_b = (_a = baseService
140
+ .getStore) === null || _a === void 0 ? void 0 : _a.call(baseService)) === null || _b === void 0 ? void 0 : _b.setError) === null || _c === void 0 ? void 0 : _c.call(_b, error instanceof Error ? error : new Error(String(error)));
141
+ }
142
+ catch (_storeError) { }
143
+ return null;
144
+ }
145
+ }),
146
+ staleTime: 1000 * 60,
147
+ refetchOnWindowFocus: false,
148
+ });
149
+ const idForItemHook = currentId !== null && currentId !== void 0 ? currentId : "";
150
+ const core = baseService.useItemHook(idForItemHook);
151
+ const item = (() => {
152
+ var _a;
153
+ if (!currentId)
154
+ return null;
155
+ const raw = core.item;
156
+ if (Array.isArray(raw)) {
157
+ const match = raw.find((i) => (i === null || i === void 0 ? void 0 : i.id) === currentId);
158
+ return match || null;
159
+ }
160
+ return (_a = raw) !== null && _a !== void 0 ? _a : null;
161
+ })();
162
+ const isLoading = isIdLoading || core.isLoading;
163
+ const error = idError || core.error || null;
164
+ const refresh = () => __awaiter(this, void 0, void 0, function* () {
165
+ if (!currentId) {
166
+ const { data } = yield refetchId({ throwOnError: false });
167
+ if (!data)
168
+ return null;
169
+ }
170
+ return core.refresh();
171
+ });
172
+ const update = (data) => __awaiter(this, void 0, void 0, function* () {
173
+ if (!currentId) {
174
+ const { data } = yield refetchId({ throwOnError: false });
175
+ if (!data)
176
+ return null;
177
+ }
178
+ return core.update(data);
179
+ });
180
+ const remove = () => __awaiter(this, void 0, void 0, function* () {
181
+ if (!currentId) {
182
+ const { data } = yield refetchId({ throwOnError: false });
183
+ if (!data)
184
+ return false;
185
+ }
186
+ return core.delete();
187
+ });
188
+ return { item, isLoading, error, refresh, update, delete: remove };
189
+ } });
126
190
  return singletonService;
127
191
  }
128
192
  /**
package/dist/types.d.ts CHANGED
@@ -106,6 +106,7 @@ export interface SingletonAmplifyService<T> extends AmplifyDataService<T> {
106
106
  }) => Promise<T | null>;
107
107
  updateCurrent: (data: Partial<T>) => Promise<T | null>;
108
108
  upsertCurrent: (data: Partial<T>) => Promise<T | null>;
109
+ useCurrentHook: () => ItemHook<T>;
109
110
  }
110
111
  export interface BaseModel {
111
112
  id: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "amplifyquery",
3
- "version": "1.0.12",
3
+ "version": "1.0.14",
4
4
  "description": "Amplify+Query",
5
5
  "keywords": [
6
6
  "Amplify",