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