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