amplifyquery 1.0.19 → 1.0.20
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/config.d.ts +12 -0
- package/dist/config.js +24 -0
- package/dist/index.js +4 -0
- package/dist/service.js +33 -7
- package/dist/singleton.js +28 -2
- package/dist/types.d.ts +10 -1
- package/package.json +1 -1
package/dist/config.d.ts
CHANGED
|
@@ -35,3 +35,15 @@ export declare function getDefaultAuthMode(): "apiKey" | "iam" | "identityPool"
|
|
|
35
35
|
* Reset global configuration (mainly for testing)
|
|
36
36
|
*/
|
|
37
37
|
export declare function resetConfig(): void;
|
|
38
|
+
/**
|
|
39
|
+
* Enable/disable singleton auto-create behavior for useCurrentHook().
|
|
40
|
+
*/
|
|
41
|
+
export declare function setSingletonAutoCreate(config: {
|
|
42
|
+
enabled?: boolean;
|
|
43
|
+
models?: string[];
|
|
44
|
+
}): void;
|
|
45
|
+
export declare function getSingletonAutoCreate(): {
|
|
46
|
+
enabled?: boolean;
|
|
47
|
+
models?: string[];
|
|
48
|
+
} | undefined;
|
|
49
|
+
export declare function isSingletonAutoCreateEnabledForModel(modelName: string): boolean;
|
package/dist/config.js
CHANGED
|
@@ -9,6 +9,9 @@ exports.getOwnerQueryName = getOwnerQueryName;
|
|
|
9
9
|
exports.setDefaultAuthMode = setDefaultAuthMode;
|
|
10
10
|
exports.getDefaultAuthMode = getDefaultAuthMode;
|
|
11
11
|
exports.resetConfig = resetConfig;
|
|
12
|
+
exports.setSingletonAutoCreate = setSingletonAutoCreate;
|
|
13
|
+
exports.getSingletonAutoCreate = getSingletonAutoCreate;
|
|
14
|
+
exports.isSingletonAutoCreateEnabledForModel = isSingletonAutoCreateEnabledForModel;
|
|
12
15
|
// Global configuration state
|
|
13
16
|
let globalConfig = {};
|
|
14
17
|
/**
|
|
@@ -61,3 +64,24 @@ function resetConfig() {
|
|
|
61
64
|
globalConfig = {};
|
|
62
65
|
console.log("🔧 AmplifyQuery: Global configuration reset");
|
|
63
66
|
}
|
|
67
|
+
/**
|
|
68
|
+
* Enable/disable singleton auto-create behavior for useCurrentHook().
|
|
69
|
+
*/
|
|
70
|
+
function setSingletonAutoCreate(config) {
|
|
71
|
+
globalConfig.singletonAutoCreate = {
|
|
72
|
+
enabled: config.enabled === true,
|
|
73
|
+
models: Array.isArray(config.models) ? config.models : undefined,
|
|
74
|
+
};
|
|
75
|
+
console.log("🔧 AmplifyQuery: Singleton auto-create configured", globalConfig.singletonAutoCreate);
|
|
76
|
+
}
|
|
77
|
+
function getSingletonAutoCreate() {
|
|
78
|
+
return globalConfig.singletonAutoCreate;
|
|
79
|
+
}
|
|
80
|
+
function isSingletonAutoCreateEnabledForModel(modelName) {
|
|
81
|
+
const cfg = getSingletonAutoCreate();
|
|
82
|
+
if (!(cfg === null || cfg === void 0 ? void 0 : cfg.enabled))
|
|
83
|
+
return false;
|
|
84
|
+
if (!cfg.models || cfg.models.length === 0)
|
|
85
|
+
return true;
|
|
86
|
+
return cfg.models.includes(modelName);
|
|
87
|
+
}
|
package/dist/index.js
CHANGED
|
@@ -69,6 +69,10 @@ function configure(config) {
|
|
|
69
69
|
if (config.defaultAuthMode) {
|
|
70
70
|
(0, config_1.setDefaultAuthMode)(config.defaultAuthMode);
|
|
71
71
|
}
|
|
72
|
+
// Set singleton auto-create
|
|
73
|
+
if (config.singletonAutoCreate) {
|
|
74
|
+
(0, config_1.setSingletonAutoCreate)(config.singletonAutoCreate);
|
|
75
|
+
}
|
|
72
76
|
// Apply React Query settings
|
|
73
77
|
(0, query_1.configure)({
|
|
74
78
|
isCachingEnabled: config.isCachingEnabled,
|
package/dist/service.js
CHANGED
|
@@ -1122,7 +1122,7 @@ function createAmplifyService(modelName, defaultAuthMode) {
|
|
|
1122
1122
|
},
|
|
1123
1123
|
// React Hook returning method - Reimplemented based on TanStack Query
|
|
1124
1124
|
useHook: (options) => {
|
|
1125
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
|
|
1125
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;
|
|
1126
1126
|
const hookQueryClient = (0, react_query_1.useQueryClient)();
|
|
1127
1127
|
// Determine query key
|
|
1128
1128
|
const queryKey = (0, react_1.useMemo)(() => {
|
|
@@ -1372,10 +1372,32 @@ function createAmplifyService(modelName, defaultAuthMode) {
|
|
|
1372
1372
|
}), [service, refetch] // refetch dependency added
|
|
1373
1373
|
);
|
|
1374
1374
|
const refresh = (0, react_1.useCallback)((refreshOptions) => __awaiter(this, void 0, void 0, function* () {
|
|
1375
|
+
var _a, _b;
|
|
1375
1376
|
console.log(`🍬 ${modelName} useHook refresh called`, queryKey);
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1377
|
+
// IMPORTANT:
|
|
1378
|
+
// TanStack Query's refetch() re-runs queryFn, but our service.list/customList can short-circuit
|
|
1379
|
+
// and return cached data unless forceRefresh is true.
|
|
1380
|
+
// refresh() must guarantee a network fetch to reflect server-side updates.
|
|
1381
|
+
try {
|
|
1382
|
+
if (options === null || options === void 0 ? void 0 : options.customList) {
|
|
1383
|
+
return yield service.customList(options.customList.queryName, options.customList.args, { forceRefresh: true });
|
|
1384
|
+
}
|
|
1385
|
+
const mergedFilter = (_a = refreshOptions === null || refreshOptions === void 0 ? void 0 : refreshOptions.filter) !== null && _a !== void 0 ? _a : (_b = options === null || options === void 0 ? void 0 : options.initialFetchOptions) === null || _b === void 0 ? void 0 : _b.filter;
|
|
1386
|
+
if (mergedFilter) {
|
|
1387
|
+
return yield service.list({
|
|
1388
|
+
filter: mergedFilter,
|
|
1389
|
+
forceRefresh: true,
|
|
1390
|
+
});
|
|
1391
|
+
}
|
|
1392
|
+
return yield service.list({ forceRefresh: true });
|
|
1393
|
+
}
|
|
1394
|
+
catch (e) {
|
|
1395
|
+
// Keep previous behavior of surfacing errors via refetch when desired
|
|
1396
|
+
// while still logging consistently.
|
|
1397
|
+
console.error(`🍬 ${modelName} useHook refresh error:`, e);
|
|
1398
|
+
throw e;
|
|
1399
|
+
}
|
|
1400
|
+
}), [modelName, options === null || options === void 0 ? void 0 : options.customList, (_p = options === null || options === void 0 ? void 0 : options.initialFetchOptions) === null || _p === void 0 ? void 0 : _p.filter, queryKey, service]);
|
|
1379
1401
|
const customListFn = (0, react_1.useCallback)((queryName, args, options) => __awaiter(this, void 0, void 0, function* () {
|
|
1380
1402
|
try {
|
|
1381
1403
|
const result = yield service.customList(queryName, args, options);
|
|
@@ -1527,9 +1549,13 @@ function createAmplifyService(modelName, defaultAuthMode) {
|
|
|
1527
1549
|
// Interface function implementations
|
|
1528
1550
|
const refreshItem = (0, react_1.useCallback)(() => __awaiter(this, void 0, void 0, function* () {
|
|
1529
1551
|
console.log(`🍬 ${modelName} useItemHook refresh called`, singleItemQueryKey);
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1552
|
+
// IMPORTANT:
|
|
1553
|
+
// refetch() re-runs queryFn which calls service.get(id) (default forceRefresh=false).
|
|
1554
|
+
// If cache exists, service.get will return cached data and never hit the network.
|
|
1555
|
+
// refresh() must guarantee a network fetch to reflect server-side updates.
|
|
1556
|
+
const latest = yield service.get(id, { forceRefresh: true });
|
|
1557
|
+
return latest || null;
|
|
1558
|
+
}), [id, modelName, service, singleItemQueryKey]); // Added id/modelName for correctness
|
|
1533
1559
|
const updateItem = (0, react_1.useCallback)((data) => __awaiter(this, void 0, void 0, function* () {
|
|
1534
1560
|
// No additional work needed here as cache is already updated in service.update
|
|
1535
1561
|
try {
|
package/dist/singleton.js
CHANGED
|
@@ -14,6 +14,8 @@ exports.createSingletonService = createSingletonService;
|
|
|
14
14
|
const client_1 = require("./client");
|
|
15
15
|
const auth_1 = require("aws-amplify/auth");
|
|
16
16
|
const react_query_1 = require("@tanstack/react-query");
|
|
17
|
+
const config_1 = require("./config");
|
|
18
|
+
const react_1 = require("react");
|
|
17
19
|
/**
|
|
18
20
|
* Function to create an extension service for singleton models
|
|
19
21
|
* @param baseService Base service
|
|
@@ -125,7 +127,7 @@ function createSingletonService(baseService, getModelId) {
|
|
|
125
127
|
}
|
|
126
128
|
}),
|
|
127
129
|
// React hook to manage the current singleton item
|
|
128
|
-
useCurrentHook: () => {
|
|
130
|
+
useCurrentHook: (options) => {
|
|
129
131
|
const { data: currentId, isLoading: isIdLoading, error: idError, refetch: refetchId, } = (0, react_query_1.useQuery)({
|
|
130
132
|
queryKey: [modelName, "currentId"],
|
|
131
133
|
queryFn: () => __awaiter(this, void 0, void 0, function* () {
|
|
@@ -147,7 +149,8 @@ function createSingletonService(baseService, getModelId) {
|
|
|
147
149
|
refetchOnWindowFocus: false,
|
|
148
150
|
});
|
|
149
151
|
const idForItemHook = currentId !== null && currentId !== void 0 ? currentId : "";
|
|
150
|
-
const core = baseService.useItemHook(idForItemHook);
|
|
152
|
+
const core = baseService.useItemHook(idForItemHook, options);
|
|
153
|
+
const didAutoCreateRef = (0, react_1.useRef)(false);
|
|
151
154
|
const item = (() => {
|
|
152
155
|
var _a;
|
|
153
156
|
if (!currentId)
|
|
@@ -161,6 +164,29 @@ function createSingletonService(baseService, getModelId) {
|
|
|
161
164
|
})();
|
|
162
165
|
const isLoading = isIdLoading || core.isLoading;
|
|
163
166
|
const error = idError || core.error || null;
|
|
167
|
+
(0, react_1.useEffect)(() => {
|
|
168
|
+
if (!currentId)
|
|
169
|
+
return;
|
|
170
|
+
if (isLoading)
|
|
171
|
+
return;
|
|
172
|
+
if (!(0, config_1.isSingletonAutoCreateEnabledForModel)(modelName))
|
|
173
|
+
return;
|
|
174
|
+
if (didAutoCreateRef.current)
|
|
175
|
+
return;
|
|
176
|
+
if (item)
|
|
177
|
+
return;
|
|
178
|
+
didAutoCreateRef.current = true;
|
|
179
|
+
// Best-effort: create { id } if missing.
|
|
180
|
+
void (() => __awaiter(this, void 0, void 0, function* () {
|
|
181
|
+
try {
|
|
182
|
+
yield singletonService.upsertCurrent({});
|
|
183
|
+
yield core.refresh();
|
|
184
|
+
}
|
|
185
|
+
catch (e) {
|
|
186
|
+
console.warn(`🍬 ${modelName} useCurrentHook auto-create failed:`, e);
|
|
187
|
+
}
|
|
188
|
+
}))();
|
|
189
|
+
}, [currentId, isLoading, item, modelName]);
|
|
164
190
|
const refresh = () => __awaiter(this, void 0, void 0, function* () {
|
|
165
191
|
if (!currentId) {
|
|
166
192
|
const { data } = yield refetchId({ throwOnError: false });
|
package/dist/types.d.ts
CHANGED
|
@@ -118,7 +118,12 @@ export interface SingletonAmplifyService<T> extends AmplifyDataService<T> {
|
|
|
118
118
|
}) => Promise<T | null>;
|
|
119
119
|
updateCurrent: (data: Partial<T>) => Promise<T | null>;
|
|
120
120
|
upsertCurrent: (data: Partial<T>) => Promise<T | null>;
|
|
121
|
-
useCurrentHook: (
|
|
121
|
+
useCurrentHook: (options?: {
|
|
122
|
+
realtime?: {
|
|
123
|
+
enabled?: boolean;
|
|
124
|
+
observeOptions?: Record<string, any>;
|
|
125
|
+
};
|
|
126
|
+
}) => ItemHook<T>;
|
|
122
127
|
}
|
|
123
128
|
export interface BaseModel {
|
|
124
129
|
id: string;
|
|
@@ -142,6 +147,10 @@ export interface AmplifyQueryConfig {
|
|
|
142
147
|
client: GraphQLClient;
|
|
143
148
|
defaultAuthMode?: AuthMode;
|
|
144
149
|
modelOwnerQueryMap?: Record<string, string>;
|
|
150
|
+
singletonAutoCreate?: {
|
|
151
|
+
enabled?: boolean;
|
|
152
|
+
models?: string[];
|
|
153
|
+
};
|
|
145
154
|
isCachingEnabled?: boolean;
|
|
146
155
|
queryClientConfig?: QueryClientConfig;
|
|
147
156
|
storage?: {
|