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.
@@ -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/next/createEnlaceHook.ts
24
- var createEnlaceHook_exports = {};
25
- __export(createEnlaceHook_exports, {
26
- createEnlaceHook: () => createEnlaceHook
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(createEnlaceHook_exports);
30
+ module.exports = __toCommonJS(hook_exports);
29
31
 
30
- // src/next/index.ts
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 (Array.isArray(obj)) return obj.map(sortObjectKeys);
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(obj[key]);
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 ("ok" in entry) {
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 queryTags = requestOptions?.tags ?? (autoGenerateTags ? generateTags(trackedCall.path) : []);
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 needsFetch = includeNeedsFetch && (!hasCachedData || isStale(queryKey, staleTime));
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)(hookReducer, null, () => getCacheState(true));
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 unsubscribe = subscribeCache(queryKey, () => {
285
- if (mountedRef.current) {
286
- dispatch({ type: "SYNC_CACHE", state: getCacheState() });
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 trackedCall.path) {
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
- if (mountedRef.current) {
302
- setCache(queryKey, {
303
- data: res.ok ? res.data : void 0,
304
- error: res.ok ? void 0 : res.error,
305
- ok: res.ok,
306
- timestamp: Date.now(),
307
- tags: queryTags
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 useSelectorMode(method, path, autoRevalidateTags) {
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: "FETCH_START" });
355
- const res = await methodRef.current(...args);
356
- if (res.ok) {
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 options = args[0];
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/types.ts
376
- var HTTP_METHODS = ["get", "post", "put", "patch", "delete"];
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/react/trackingProxy.ts
379
- function createTrackingProxy(onTrack) {
380
- const createProxy = (path = []) => {
381
- return new Proxy(() => {
382
- }, {
383
- get(_, prop) {
384
- if (HTTP_METHODS.includes(prop)) {
385
- const methodFn = (options) => {
386
- onTrack({
387
- trackedCall: { path, method: prop, options },
388
- selectorPath: null,
389
- selectorMethod: null
390
- });
391
- return Promise.resolve({ ok: true, data: void 0 });
392
- };
393
- onTrack({
394
- trackedCall: null,
395
- selectorPath: path,
396
- selectorMethod: prop
397
- });
398
- return methodFn;
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
- return createProxy();
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/createEnlaceHook.ts
408
- function createEnlaceHook(baseUrl, defaultOptions = {}, hookOptions = {}) {
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 = createEnlace(baseUrl, defaultOptions, {
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
- selectorPath ?? [],
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
- { autoGenerateTags, staleTime }
600
+ {
601
+ autoGenerateTags,
602
+ staleTime,
603
+ enabled: queryOptions?.enabled ?? true,
604
+ pollingInterval: queryOptions?.pollingInterval
605
+ }
440
606
  );
441
607
  }
442
608
  return useEnlaceHook;