enlace 0.0.1-beta.2 → 0.0.1-beta.21
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/README.md +668 -85
- package/dist/hook/index.d.mts +238 -0
- package/dist/hook/index.d.ts +238 -0
- package/dist/{next/hook → hook}/index.js +335 -169
- package/dist/hook/index.mjs +591 -0
- package/dist/index.d.mts +73 -70
- package/dist/index.d.ts +73 -70
- package/dist/index.js +57 -327
- package/dist/index.mjs +59 -327
- package/package.json +17 -12
- package/dist/next/hook/index.d.mts +0 -124
- package/dist/next/hook/index.d.ts +0 -124
- package/dist/next/hook/index.mjs +0 -444
- package/dist/next/index.d.mts +0 -74
- package/dist/next/index.d.ts +0 -74
- package/dist/next/index.js +0 -111
- package/dist/next/index.mjs +0 -95
|
@@ -17,107 +17,21 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
17
17
|
}
|
|
18
18
|
return to;
|
|
19
19
|
};
|
|
20
|
-
var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
|
|
21
20
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
22
21
|
|
|
23
|
-
// src/
|
|
24
|
-
var
|
|
25
|
-
__export(
|
|
26
|
-
|
|
22
|
+
// src/hook/index.ts
|
|
23
|
+
var hook_exports = {};
|
|
24
|
+
__export(hook_exports, {
|
|
25
|
+
HTTP_METHODS: () => HTTP_METHODS,
|
|
26
|
+
enlaceHookNext: () => enlaceHookNext,
|
|
27
|
+
enlaceHookReact: () => enlaceHookReact,
|
|
28
|
+
invalidateTags: () => invalidateTags
|
|
27
29
|
});
|
|
28
|
-
module.exports = __toCommonJS(
|
|
30
|
+
module.exports = __toCommonJS(hook_exports);
|
|
29
31
|
|
|
30
|
-
// src/
|
|
31
|
-
var next_exports = {};
|
|
32
|
-
__export(next_exports, {
|
|
33
|
-
createEnlace: () => createEnlace
|
|
34
|
-
});
|
|
35
|
-
var import_enlace_core2 = require("enlace-core");
|
|
36
|
-
|
|
37
|
-
// src/next/fetch.ts
|
|
32
|
+
// src/react/enlaceHookReact.ts
|
|
38
33
|
var import_enlace_core = require("enlace-core");
|
|
39
34
|
|
|
40
|
-
// src/utils/generateTags.ts
|
|
41
|
-
function generateTags(path) {
|
|
42
|
-
return path.map((_, i) => path.slice(0, i + 1).join("/"));
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
// src/next/fetch.ts
|
|
46
|
-
async function executeNextFetch(baseUrl, path, method, combinedOptions, requestOptions) {
|
|
47
|
-
const {
|
|
48
|
-
autoGenerateTags = true,
|
|
49
|
-
autoRevalidateTags = true,
|
|
50
|
-
revalidator,
|
|
51
|
-
headers: defaultHeaders,
|
|
52
|
-
...restOptions
|
|
53
|
-
} = combinedOptions;
|
|
54
|
-
const url = (0, import_enlace_core.buildUrl)(baseUrl, path, requestOptions?.query);
|
|
55
|
-
let headers = (0, import_enlace_core.mergeHeaders)(defaultHeaders, requestOptions?.headers);
|
|
56
|
-
const isGet = method === "GET";
|
|
57
|
-
const autoTags = generateTags(path);
|
|
58
|
-
const fetchOptions = {
|
|
59
|
-
...restOptions,
|
|
60
|
-
method
|
|
61
|
-
};
|
|
62
|
-
if (requestOptions?.cache) {
|
|
63
|
-
fetchOptions.cache = requestOptions.cache;
|
|
64
|
-
}
|
|
65
|
-
if (isGet) {
|
|
66
|
-
const tags = requestOptions?.tags ?? (autoGenerateTags ? autoTags : void 0);
|
|
67
|
-
const nextFetchOptions = {};
|
|
68
|
-
if (tags) {
|
|
69
|
-
nextFetchOptions.tags = tags;
|
|
70
|
-
}
|
|
71
|
-
if (requestOptions?.revalidate !== void 0) {
|
|
72
|
-
nextFetchOptions.revalidate = requestOptions.revalidate;
|
|
73
|
-
}
|
|
74
|
-
fetchOptions.next = nextFetchOptions;
|
|
75
|
-
}
|
|
76
|
-
if (headers) {
|
|
77
|
-
fetchOptions.headers = headers;
|
|
78
|
-
}
|
|
79
|
-
if (requestOptions?.body !== void 0) {
|
|
80
|
-
if ((0, import_enlace_core.isJsonBody)(requestOptions.body)) {
|
|
81
|
-
fetchOptions.body = JSON.stringify(requestOptions.body);
|
|
82
|
-
headers = (0, import_enlace_core.mergeHeaders)(headers, { "Content-Type": "application/json" });
|
|
83
|
-
if (headers) {
|
|
84
|
-
fetchOptions.headers = headers;
|
|
85
|
-
}
|
|
86
|
-
} else {
|
|
87
|
-
fetchOptions.body = requestOptions.body;
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
const response = await fetch(url, fetchOptions);
|
|
91
|
-
const contentType = response.headers.get("content-type");
|
|
92
|
-
const isJson = contentType?.includes("application/json");
|
|
93
|
-
if (response.ok) {
|
|
94
|
-
if (!isGet && !requestOptions?.skipRevalidator) {
|
|
95
|
-
const revalidateTags = requestOptions?.revalidateTags ?? (autoRevalidateTags ? autoTags : []);
|
|
96
|
-
const revalidatePaths = requestOptions?.revalidatePaths ?? [];
|
|
97
|
-
if (revalidateTags.length || revalidatePaths.length) {
|
|
98
|
-
revalidator?.(revalidateTags, revalidatePaths);
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
return {
|
|
102
|
-
ok: true,
|
|
103
|
-
status: response.status,
|
|
104
|
-
data: isJson ? await response.json() : response
|
|
105
|
-
};
|
|
106
|
-
}
|
|
107
|
-
return {
|
|
108
|
-
ok: false,
|
|
109
|
-
status: response.status,
|
|
110
|
-
error: isJson ? await response.json() : response
|
|
111
|
-
};
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
// src/next/index.ts
|
|
115
|
-
__reExport(next_exports, require("enlace-core"));
|
|
116
|
-
function createEnlace(baseUrl, defaultOptions = {}, nextOptions = {}) {
|
|
117
|
-
const combinedOptions = { ...defaultOptions, ...nextOptions };
|
|
118
|
-
return (0, import_enlace_core2.createProxyHandler)(baseUrl, combinedOptions, [], executeNextFetch);
|
|
119
|
-
}
|
|
120
|
-
|
|
121
35
|
// src/react/useQueryMode.ts
|
|
122
36
|
var import_react = require("react");
|
|
123
37
|
|
|
@@ -125,25 +39,31 @@ var import_react = require("react");
|
|
|
125
39
|
var initialState = {
|
|
126
40
|
loading: false,
|
|
127
41
|
fetching: false,
|
|
128
|
-
ok: void 0,
|
|
129
42
|
data: void 0,
|
|
130
43
|
error: void 0
|
|
131
44
|
};
|
|
132
45
|
function hookReducer(state, action) {
|
|
133
46
|
switch (action.type) {
|
|
134
47
|
case "RESET":
|
|
135
|
-
return action.state;
|
|
48
|
+
return action.state ?? initialState;
|
|
136
49
|
case "FETCH_START":
|
|
137
50
|
return {
|
|
138
51
|
...state,
|
|
139
52
|
loading: state.data === void 0,
|
|
140
|
-
fetching: true
|
|
53
|
+
fetching: true,
|
|
54
|
+
error: void 0
|
|
55
|
+
};
|
|
56
|
+
case "MUTATION_START":
|
|
57
|
+
return {
|
|
58
|
+
...state,
|
|
59
|
+
loading: true,
|
|
60
|
+
fetching: true,
|
|
61
|
+
error: void 0
|
|
141
62
|
};
|
|
142
63
|
case "FETCH_SUCCESS":
|
|
143
64
|
return {
|
|
144
65
|
loading: false,
|
|
145
66
|
fetching: false,
|
|
146
|
-
ok: true,
|
|
147
67
|
data: action.data,
|
|
148
68
|
error: void 0
|
|
149
69
|
};
|
|
@@ -151,7 +71,6 @@ function hookReducer(state, action) {
|
|
|
151
71
|
return {
|
|
152
72
|
loading: false,
|
|
153
73
|
fetching: false,
|
|
154
|
-
ok: false,
|
|
155
74
|
data: void 0,
|
|
156
75
|
error: action.error
|
|
157
76
|
};
|
|
@@ -162,13 +81,27 @@ function hookReducer(state, action) {
|
|
|
162
81
|
}
|
|
163
82
|
}
|
|
164
83
|
|
|
84
|
+
// src/utils/generateTags.ts
|
|
85
|
+
function generateTags(path) {
|
|
86
|
+
return path.map((_, i) => path.slice(0, i + 1).join("/"));
|
|
87
|
+
}
|
|
88
|
+
|
|
165
89
|
// src/utils/sortObjectKeys.ts
|
|
166
|
-
function sortObjectKeys(obj) {
|
|
90
|
+
function sortObjectKeys(obj, seen = /* @__PURE__ */ new WeakSet()) {
|
|
167
91
|
if (obj === null || typeof obj !== "object") return obj;
|
|
168
|
-
if (
|
|
92
|
+
if (seen.has(obj)) {
|
|
93
|
+
return "[Circular]";
|
|
94
|
+
}
|
|
95
|
+
seen.add(obj);
|
|
96
|
+
if (Array.isArray(obj)) {
|
|
97
|
+
return obj.map((item) => sortObjectKeys(item, seen));
|
|
98
|
+
}
|
|
169
99
|
return Object.keys(obj).sort().reduce(
|
|
170
100
|
(sorted, key) => {
|
|
171
|
-
sorted[key] = sortObjectKeys(
|
|
101
|
+
sorted[key] = sortObjectKeys(
|
|
102
|
+
obj[key],
|
|
103
|
+
seen
|
|
104
|
+
);
|
|
172
105
|
return sorted;
|
|
173
106
|
},
|
|
174
107
|
{}
|
|
@@ -192,7 +125,7 @@ function getCache(key) {
|
|
|
192
125
|
function setCache(key, entry) {
|
|
193
126
|
const existing = cache.get(key);
|
|
194
127
|
if (existing) {
|
|
195
|
-
if ("
|
|
128
|
+
if ("data" in entry || "error" in entry) {
|
|
196
129
|
delete existing.promise;
|
|
197
130
|
}
|
|
198
131
|
Object.assign(existing, entry);
|
|
@@ -201,7 +134,6 @@ function setCache(key, entry) {
|
|
|
201
134
|
cache.set(key, {
|
|
202
135
|
data: void 0,
|
|
203
136
|
error: void 0,
|
|
204
|
-
ok: void 0,
|
|
205
137
|
timestamp: 0,
|
|
206
138
|
tags: [],
|
|
207
139
|
subscribers: /* @__PURE__ */ new Set(),
|
|
@@ -215,7 +147,6 @@ function subscribeCache(key, callback) {
|
|
|
215
147
|
cache.set(key, {
|
|
216
148
|
data: void 0,
|
|
217
149
|
error: void 0,
|
|
218
|
-
ok: void 0,
|
|
219
150
|
timestamp: 0,
|
|
220
151
|
tags: [],
|
|
221
152
|
subscribers: /* @__PURE__ */ new Set()
|
|
@@ -236,11 +167,9 @@ function clearCacheByTags(tags) {
|
|
|
236
167
|
cache.forEach((entry) => {
|
|
237
168
|
const hasMatch = entry.tags.some((tag) => tags.includes(tag));
|
|
238
169
|
if (hasMatch) {
|
|
239
|
-
entry.data = void 0;
|
|
240
|
-
entry.error = void 0;
|
|
241
|
-
entry.ok = void 0;
|
|
242
170
|
entry.timestamp = 0;
|
|
243
171
|
delete entry.promise;
|
|
172
|
+
entry.subscribers.forEach((cb) => cb());
|
|
244
173
|
}
|
|
245
174
|
});
|
|
246
175
|
}
|
|
@@ -257,35 +186,82 @@ function onRevalidate(callback) {
|
|
|
257
186
|
}
|
|
258
187
|
|
|
259
188
|
// src/react/useQueryMode.ts
|
|
189
|
+
function resolvePath(path, params) {
|
|
190
|
+
if (!params) return path;
|
|
191
|
+
return path.map((segment) => {
|
|
192
|
+
if (segment.startsWith(":")) {
|
|
193
|
+
const paramName = segment.slice(1);
|
|
194
|
+
const value = params[paramName];
|
|
195
|
+
if (value === void 0) {
|
|
196
|
+
throw new Error(`Missing path parameter: ${paramName}`);
|
|
197
|
+
}
|
|
198
|
+
return String(value);
|
|
199
|
+
}
|
|
200
|
+
return segment;
|
|
201
|
+
});
|
|
202
|
+
}
|
|
260
203
|
function useQueryMode(api, trackedCall, options) {
|
|
261
|
-
const { autoGenerateTags, staleTime } = options;
|
|
204
|
+
const { autoGenerateTags, staleTime, enabled, pollingInterval } = options;
|
|
262
205
|
const queryKey = createQueryKey(trackedCall);
|
|
263
206
|
const requestOptions = trackedCall.options;
|
|
264
|
-
const
|
|
207
|
+
const resolvedPath = resolvePath(trackedCall.path, requestOptions?.params);
|
|
208
|
+
const baseTags = requestOptions?.tags ?? (autoGenerateTags ? generateTags(resolvedPath) : []);
|
|
209
|
+
const queryTags = [...baseTags, ...requestOptions?.additionalTags ?? []];
|
|
265
210
|
const getCacheState = (includeNeedsFetch = false) => {
|
|
266
211
|
const cached = getCache(queryKey);
|
|
267
212
|
const hasCachedData = cached?.data !== void 0;
|
|
268
213
|
const isFetching = !!cached?.promise;
|
|
269
|
-
const
|
|
214
|
+
const stale = isStale(queryKey, staleTime);
|
|
215
|
+
const needsFetch = includeNeedsFetch && (!hasCachedData || stale);
|
|
270
216
|
return {
|
|
271
217
|
loading: !hasCachedData && (isFetching || needsFetch),
|
|
272
218
|
fetching: isFetching || needsFetch,
|
|
273
|
-
ok: cached?.ok,
|
|
274
219
|
data: cached?.data,
|
|
275
220
|
error: cached?.error
|
|
276
221
|
};
|
|
277
222
|
};
|
|
278
|
-
const [state, dispatch] = (0, import_react.useReducer)(
|
|
223
|
+
const [state, dispatch] = (0, import_react.useReducer)(
|
|
224
|
+
hookReducer,
|
|
225
|
+
null,
|
|
226
|
+
() => getCacheState(true)
|
|
227
|
+
);
|
|
279
228
|
const mountedRef = (0, import_react.useRef)(true);
|
|
280
229
|
const fetchRef = (0, import_react.useRef)(null);
|
|
230
|
+
const pollingTimeoutRef = (0, import_react.useRef)(null);
|
|
231
|
+
const pollingIntervalRef = (0, import_react.useRef)(pollingInterval);
|
|
232
|
+
pollingIntervalRef.current = pollingInterval;
|
|
281
233
|
(0, import_react.useEffect)(() => {
|
|
282
234
|
mountedRef.current = true;
|
|
235
|
+
if (!enabled) {
|
|
236
|
+
dispatch({ type: "RESET" });
|
|
237
|
+
if (pollingTimeoutRef.current) {
|
|
238
|
+
clearTimeout(pollingTimeoutRef.current);
|
|
239
|
+
pollingTimeoutRef.current = null;
|
|
240
|
+
}
|
|
241
|
+
return () => {
|
|
242
|
+
mountedRef.current = false;
|
|
243
|
+
};
|
|
244
|
+
}
|
|
283
245
|
dispatch({ type: "RESET", state: getCacheState(true) });
|
|
284
|
-
const
|
|
285
|
-
|
|
286
|
-
|
|
246
|
+
const scheduleNextPoll = () => {
|
|
247
|
+
const currentPollingInterval = pollingIntervalRef.current;
|
|
248
|
+
if (!mountedRef.current || !enabled || currentPollingInterval === void 0) {
|
|
249
|
+
return;
|
|
287
250
|
}
|
|
288
|
-
|
|
251
|
+
const cached2 = getCache(queryKey);
|
|
252
|
+
const interval = typeof currentPollingInterval === "function" ? currentPollingInterval(cached2?.data, cached2?.error) : currentPollingInterval;
|
|
253
|
+
if (interval === false || interval <= 0) {
|
|
254
|
+
return;
|
|
255
|
+
}
|
|
256
|
+
if (pollingTimeoutRef.current) {
|
|
257
|
+
clearTimeout(pollingTimeoutRef.current);
|
|
258
|
+
}
|
|
259
|
+
pollingTimeoutRef.current = setTimeout(() => {
|
|
260
|
+
if (mountedRef.current && enabled && fetchRef.current) {
|
|
261
|
+
fetchRef.current();
|
|
262
|
+
}
|
|
263
|
+
}, interval);
|
|
264
|
+
};
|
|
289
265
|
const doFetch = () => {
|
|
290
266
|
const cached2 = getCache(queryKey);
|
|
291
267
|
if (cached2?.promise) {
|
|
@@ -293,20 +269,26 @@ function useQueryMode(api, trackedCall, options) {
|
|
|
293
269
|
}
|
|
294
270
|
dispatch({ type: "FETCH_START" });
|
|
295
271
|
let current = api;
|
|
296
|
-
for (const segment of
|
|
272
|
+
for (const segment of resolvedPath) {
|
|
297
273
|
current = current[segment];
|
|
298
274
|
}
|
|
299
275
|
const method = current[trackedCall.method];
|
|
300
276
|
const fetchPromise = method(trackedCall.options).then((res) => {
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
277
|
+
setCache(queryKey, {
|
|
278
|
+
data: res.error ? void 0 : res.data,
|
|
279
|
+
error: res.error,
|
|
280
|
+
timestamp: Date.now(),
|
|
281
|
+
tags: queryTags
|
|
282
|
+
});
|
|
283
|
+
}).catch((err) => {
|
|
284
|
+
setCache(queryKey, {
|
|
285
|
+
data: void 0,
|
|
286
|
+
error: err,
|
|
287
|
+
timestamp: Date.now(),
|
|
288
|
+
tags: queryTags
|
|
289
|
+
});
|
|
290
|
+
}).finally(() => {
|
|
291
|
+
scheduleNextPoll();
|
|
310
292
|
});
|
|
311
293
|
setCache(queryKey, {
|
|
312
294
|
promise: fetchPromise,
|
|
@@ -317,15 +299,25 @@ function useQueryMode(api, trackedCall, options) {
|
|
|
317
299
|
const cached = getCache(queryKey);
|
|
318
300
|
if (cached?.data !== void 0 && !isStale(queryKey, staleTime)) {
|
|
319
301
|
dispatch({ type: "SYNC_CACHE", state: getCacheState() });
|
|
302
|
+
scheduleNextPoll();
|
|
320
303
|
} else {
|
|
321
304
|
doFetch();
|
|
322
305
|
}
|
|
306
|
+
const unsubscribe = subscribeCache(queryKey, () => {
|
|
307
|
+
if (mountedRef.current) {
|
|
308
|
+
dispatch({ type: "SYNC_CACHE", state: getCacheState() });
|
|
309
|
+
}
|
|
310
|
+
});
|
|
323
311
|
return () => {
|
|
324
312
|
mountedRef.current = false;
|
|
325
313
|
fetchRef.current = null;
|
|
314
|
+
if (pollingTimeoutRef.current) {
|
|
315
|
+
clearTimeout(pollingTimeoutRef.current);
|
|
316
|
+
pollingTimeoutRef.current = null;
|
|
317
|
+
}
|
|
326
318
|
unsubscribe();
|
|
327
319
|
};
|
|
328
|
-
}, [queryKey]);
|
|
320
|
+
}, [queryKey, enabled]);
|
|
329
321
|
(0, import_react.useEffect)(() => {
|
|
330
322
|
if (queryTags.length === 0) return;
|
|
331
323
|
return onRevalidate((invalidatedTags) => {
|
|
@@ -338,25 +330,100 @@ function useQueryMode(api, trackedCall, options) {
|
|
|
338
330
|
return state;
|
|
339
331
|
}
|
|
340
332
|
|
|
333
|
+
// src/react/types.ts
|
|
334
|
+
var HTTP_METHODS = [
|
|
335
|
+
"$get",
|
|
336
|
+
"$post",
|
|
337
|
+
"$put",
|
|
338
|
+
"$patch",
|
|
339
|
+
"$delete"
|
|
340
|
+
];
|
|
341
|
+
|
|
342
|
+
// src/react/trackingProxy.ts
|
|
343
|
+
function createTrackingProxy(onTrack) {
|
|
344
|
+
const createProxy = (path = []) => {
|
|
345
|
+
return new Proxy(() => {
|
|
346
|
+
}, {
|
|
347
|
+
get(_, prop) {
|
|
348
|
+
if (HTTP_METHODS.includes(prop)) {
|
|
349
|
+
const methodFn = (options) => {
|
|
350
|
+
onTrack({
|
|
351
|
+
trackedCall: { path, method: prop, options },
|
|
352
|
+
selectorPath: null,
|
|
353
|
+
selectorMethod: null
|
|
354
|
+
});
|
|
355
|
+
return Promise.resolve({
|
|
356
|
+
status: 200,
|
|
357
|
+
data: void 0,
|
|
358
|
+
error: void 0
|
|
359
|
+
});
|
|
360
|
+
};
|
|
361
|
+
onTrack({
|
|
362
|
+
trackedCall: null,
|
|
363
|
+
selectorPath: path,
|
|
364
|
+
selectorMethod: prop
|
|
365
|
+
});
|
|
366
|
+
return methodFn;
|
|
367
|
+
}
|
|
368
|
+
return createProxy([...path, prop]);
|
|
369
|
+
}
|
|
370
|
+
});
|
|
371
|
+
};
|
|
372
|
+
return createProxy();
|
|
373
|
+
}
|
|
374
|
+
|
|
341
375
|
// src/react/useSelectorMode.ts
|
|
342
376
|
var import_react2 = require("react");
|
|
343
|
-
function
|
|
377
|
+
function resolvePath2(path, params) {
|
|
378
|
+
if (!params) return path;
|
|
379
|
+
return path.map((segment) => {
|
|
380
|
+
if (segment.startsWith(":")) {
|
|
381
|
+
const paramName = segment.slice(1);
|
|
382
|
+
const value = params[paramName];
|
|
383
|
+
if (value === void 0) {
|
|
384
|
+
throw new Error(`Missing path parameter: ${paramName}`);
|
|
385
|
+
}
|
|
386
|
+
return String(value);
|
|
387
|
+
}
|
|
388
|
+
return segment;
|
|
389
|
+
});
|
|
390
|
+
}
|
|
391
|
+
function hasPathParams(path) {
|
|
392
|
+
return path.some((segment) => segment.startsWith(":"));
|
|
393
|
+
}
|
|
394
|
+
function useSelectorMode(config) {
|
|
395
|
+
const { method, api, path, methodName, autoRevalidateTags } = config;
|
|
344
396
|
const [state, dispatch] = (0, import_react2.useReducer)(hookReducer, initialState);
|
|
345
397
|
const methodRef = (0, import_react2.useRef)(method);
|
|
398
|
+
const apiRef = (0, import_react2.useRef)(api);
|
|
346
399
|
const triggerRef = (0, import_react2.useRef)(null);
|
|
347
400
|
const pathRef = (0, import_react2.useRef)(path);
|
|
401
|
+
const methodNameRef = (0, import_react2.useRef)(methodName);
|
|
348
402
|
const autoRevalidateRef = (0, import_react2.useRef)(autoRevalidateTags);
|
|
349
403
|
methodRef.current = method;
|
|
404
|
+
apiRef.current = api;
|
|
350
405
|
pathRef.current = path;
|
|
406
|
+
methodNameRef.current = methodName;
|
|
351
407
|
autoRevalidateRef.current = autoRevalidateTags;
|
|
352
408
|
if (!triggerRef.current) {
|
|
353
409
|
triggerRef.current = (async (...args) => {
|
|
354
|
-
dispatch({ type: "
|
|
355
|
-
const
|
|
356
|
-
|
|
410
|
+
dispatch({ type: "MUTATION_START" });
|
|
411
|
+
const options = args[0];
|
|
412
|
+
const resolvedPath = resolvePath2(pathRef.current, options?.params);
|
|
413
|
+
let res;
|
|
414
|
+
if (hasPathParams(pathRef.current)) {
|
|
415
|
+
let current = apiRef.current;
|
|
416
|
+
for (const segment of resolvedPath) {
|
|
417
|
+
current = current[segment];
|
|
418
|
+
}
|
|
419
|
+
const resolvedMethod = current[methodNameRef.current];
|
|
420
|
+
res = await resolvedMethod(...args);
|
|
421
|
+
} else {
|
|
422
|
+
res = await methodRef.current(...args);
|
|
423
|
+
}
|
|
424
|
+
if (!res.error) {
|
|
357
425
|
dispatch({ type: "FETCH_SUCCESS", data: res.data });
|
|
358
|
-
const
|
|
359
|
-
const tagsToInvalidate = options?.revalidateTags ?? (autoRevalidateRef.current ? generateTags(pathRef.current) : []);
|
|
426
|
+
const tagsToInvalidate = options?.revalidateTags ?? (autoRevalidateRef.current ? generateTags(resolvedPath) : []);
|
|
360
427
|
if (tagsToInvalidate.length > 0) {
|
|
361
428
|
invalidateTags(tagsToInvalidate);
|
|
362
429
|
}
|
|
@@ -372,71 +439,170 @@ function useSelectorMode(method, path, autoRevalidateTags) {
|
|
|
372
439
|
};
|
|
373
440
|
}
|
|
374
441
|
|
|
375
|
-
// src/react/
|
|
376
|
-
|
|
442
|
+
// src/react/enlaceHookReact.ts
|
|
443
|
+
function enlaceHookReact(baseUrl, defaultOptions = {}, hookOptions = {}) {
|
|
444
|
+
const {
|
|
445
|
+
autoGenerateTags = true,
|
|
446
|
+
autoRevalidateTags = true,
|
|
447
|
+
staleTime = 0,
|
|
448
|
+
onSuccess,
|
|
449
|
+
onError
|
|
450
|
+
} = hookOptions;
|
|
451
|
+
const api = (0, import_enlace_core.enlace)(baseUrl, defaultOptions, {
|
|
452
|
+
onSuccess,
|
|
453
|
+
onError
|
|
454
|
+
});
|
|
455
|
+
function useEnlaceHook(selectorOrQuery, queryOptions) {
|
|
456
|
+
let trackingResult = {
|
|
457
|
+
trackedCall: null,
|
|
458
|
+
selectorPath: null,
|
|
459
|
+
selectorMethod: null
|
|
460
|
+
};
|
|
461
|
+
const trackingProxy = createTrackingProxy((result2) => {
|
|
462
|
+
trackingResult = result2;
|
|
463
|
+
});
|
|
464
|
+
const result = selectorOrQuery(trackingProxy);
|
|
465
|
+
if (typeof result === "function") {
|
|
466
|
+
const actualResult = selectorOrQuery(api);
|
|
467
|
+
return useSelectorMode({
|
|
468
|
+
method: actualResult,
|
|
469
|
+
api,
|
|
470
|
+
path: trackingResult.selectorPath ?? [],
|
|
471
|
+
methodName: trackingResult.selectorMethod ?? "",
|
|
472
|
+
autoRevalidateTags
|
|
473
|
+
});
|
|
474
|
+
}
|
|
475
|
+
if (!trackingResult.trackedCall) {
|
|
476
|
+
throw new Error(
|
|
477
|
+
"useAPI query mode requires calling an HTTP method ($get, $post, etc.). Did you mean to use selector mode? Example: useAPI((api) => api.posts.$get())"
|
|
478
|
+
);
|
|
479
|
+
}
|
|
480
|
+
return useQueryMode(
|
|
481
|
+
api,
|
|
482
|
+
trackingResult.trackedCall,
|
|
483
|
+
{
|
|
484
|
+
autoGenerateTags,
|
|
485
|
+
staleTime,
|
|
486
|
+
enabled: queryOptions?.enabled ?? true,
|
|
487
|
+
pollingInterval: queryOptions?.pollingInterval
|
|
488
|
+
}
|
|
489
|
+
);
|
|
490
|
+
}
|
|
491
|
+
return useEnlaceHook;
|
|
492
|
+
}
|
|
377
493
|
|
|
378
|
-
// src/
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
494
|
+
// src/next/index.ts
|
|
495
|
+
var import_enlace_core3 = require("enlace-core");
|
|
496
|
+
|
|
497
|
+
// src/next/fetch.ts
|
|
498
|
+
var import_enlace_core2 = require("enlace-core");
|
|
499
|
+
async function executeNextFetch(baseUrl, path, method, combinedOptions, requestOptions) {
|
|
500
|
+
const {
|
|
501
|
+
autoGenerateTags = true,
|
|
502
|
+
autoRevalidateTags = true,
|
|
503
|
+
skipServerRevalidation = false,
|
|
504
|
+
serverRevalidator,
|
|
505
|
+
onSuccess,
|
|
506
|
+
...coreOptions
|
|
507
|
+
} = combinedOptions;
|
|
508
|
+
const isGet = method === "GET";
|
|
509
|
+
const autoTags = generateTags(path);
|
|
510
|
+
const nextOnSuccess = (payload) => {
|
|
511
|
+
if (!isGet) {
|
|
512
|
+
const shouldRevalidateServer = requestOptions?.serverRevalidate ?? !skipServerRevalidation;
|
|
513
|
+
if (shouldRevalidateServer) {
|
|
514
|
+
const baseRevalidateTags = requestOptions?.revalidateTags ?? (autoRevalidateTags ? autoTags : []);
|
|
515
|
+
const revalidateTags = [
|
|
516
|
+
...baseRevalidateTags,
|
|
517
|
+
...requestOptions?.additionalRevalidateTags ?? []
|
|
518
|
+
];
|
|
519
|
+
const revalidatePaths = requestOptions?.revalidatePaths ?? [];
|
|
520
|
+
if (revalidateTags.length || revalidatePaths.length) {
|
|
521
|
+
serverRevalidator?.(revalidateTags, revalidatePaths);
|
|
399
522
|
}
|
|
400
|
-
return createProxy([...path, prop]);
|
|
401
523
|
}
|
|
402
|
-
}
|
|
524
|
+
}
|
|
525
|
+
onSuccess?.(payload);
|
|
403
526
|
};
|
|
404
|
-
|
|
527
|
+
const nextRequestOptions = { ...requestOptions };
|
|
528
|
+
if (isGet) {
|
|
529
|
+
const tags = requestOptions?.tags ?? (autoGenerateTags ? autoTags : void 0);
|
|
530
|
+
const nextFetchOptions = {};
|
|
531
|
+
if (tags) {
|
|
532
|
+
nextFetchOptions.tags = tags;
|
|
533
|
+
}
|
|
534
|
+
if (requestOptions?.revalidate !== void 0) {
|
|
535
|
+
nextFetchOptions.revalidate = requestOptions.revalidate;
|
|
536
|
+
}
|
|
537
|
+
nextRequestOptions.next = nextFetchOptions;
|
|
538
|
+
}
|
|
539
|
+
return (0, import_enlace_core2.executeFetch)(
|
|
540
|
+
baseUrl,
|
|
541
|
+
path,
|
|
542
|
+
method,
|
|
543
|
+
{ ...coreOptions, onSuccess: nextOnSuccess },
|
|
544
|
+
nextRequestOptions
|
|
545
|
+
);
|
|
405
546
|
}
|
|
406
547
|
|
|
407
|
-
// src/next/
|
|
408
|
-
function
|
|
548
|
+
// src/next/index.ts
|
|
549
|
+
function enlaceNext(baseUrl, defaultOptions = {}, nextOptions = {}) {
|
|
550
|
+
const combinedOptions = { ...defaultOptions, ...nextOptions };
|
|
551
|
+
return (0, import_enlace_core3.createProxyHandler)(
|
|
552
|
+
baseUrl,
|
|
553
|
+
combinedOptions,
|
|
554
|
+
[],
|
|
555
|
+
executeNextFetch
|
|
556
|
+
);
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
// src/next/enlaceHookNext.ts
|
|
560
|
+
function enlaceHookNext(baseUrl, defaultOptions = {}, hookOptions = {}) {
|
|
409
561
|
const {
|
|
410
562
|
autoGenerateTags = true,
|
|
411
563
|
autoRevalidateTags = true,
|
|
412
564
|
staleTime = 0,
|
|
413
565
|
...nextOptions
|
|
414
566
|
} = hookOptions;
|
|
415
|
-
const api =
|
|
567
|
+
const api = enlaceNext(baseUrl, defaultOptions, {
|
|
416
568
|
autoGenerateTags,
|
|
417
569
|
autoRevalidateTags,
|
|
418
570
|
...nextOptions
|
|
419
571
|
});
|
|
420
|
-
function useEnlaceHook(selectorOrQuery) {
|
|
572
|
+
function useEnlaceHook(selectorOrQuery, queryOptions) {
|
|
421
573
|
let trackedCall = null;
|
|
422
574
|
let selectorPath = null;
|
|
575
|
+
let selectorMethod = null;
|
|
423
576
|
const trackingProxy = createTrackingProxy((result2) => {
|
|
424
577
|
trackedCall = result2.trackedCall;
|
|
425
578
|
selectorPath = result2.selectorPath;
|
|
579
|
+
selectorMethod = result2.selectorMethod;
|
|
426
580
|
});
|
|
427
581
|
const result = selectorOrQuery(trackingProxy);
|
|
428
582
|
if (typeof result === "function") {
|
|
429
583
|
const actualResult = selectorOrQuery(api);
|
|
430
|
-
return useSelectorMode(
|
|
431
|
-
actualResult,
|
|
432
|
-
|
|
584
|
+
return useSelectorMode({
|
|
585
|
+
method: actualResult,
|
|
586
|
+
api,
|
|
587
|
+
path: selectorPath ?? [],
|
|
588
|
+
methodName: selectorMethod ?? "",
|
|
433
589
|
autoRevalidateTags
|
|
590
|
+
});
|
|
591
|
+
}
|
|
592
|
+
if (!trackedCall) {
|
|
593
|
+
throw new Error(
|
|
594
|
+
"useAPI query mode requires calling an HTTP method ($get, $post, etc.). Did you mean to use selector mode? Example: useAPI((api) => api.posts.$get())"
|
|
434
595
|
);
|
|
435
596
|
}
|
|
436
597
|
return useQueryMode(
|
|
437
598
|
api,
|
|
438
599
|
trackedCall,
|
|
439
|
-
{
|
|
600
|
+
{
|
|
601
|
+
autoGenerateTags,
|
|
602
|
+
staleTime,
|
|
603
|
+
enabled: queryOptions?.enabled ?? true,
|
|
604
|
+
pollingInterval: queryOptions?.pollingInterval
|
|
605
|
+
}
|
|
440
606
|
);
|
|
441
607
|
}
|
|
442
608
|
return useEnlaceHook;
|