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.
@@ -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/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
27
28
  });
28
- module.exports = __toCommonJS(createEnlaceHook_exports);
29
+ module.exports = __toCommonJS(hook_exports);
29
30
 
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
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 (Array.isArray(obj)) return obj.map(sortObjectKeys);
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(obj[key]);
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 ("ok" in entry) {
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 queryTags = requestOptions?.tags ?? (autoGenerateTags ? generateTags(trackedCall.path) : []);
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 needsFetch = includeNeedsFetch && (!hasCachedData || isStale(queryKey, staleTime));
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)(hookReducer, null, () => getCacheState(true));
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 unsubscribe = subscribeCache(queryKey, () => {
285
- if (mountedRef.current) {
286
- dispatch({ type: "SYNC_CACHE", state: getCacheState() });
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 trackedCall.path) {
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
- 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
- }
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 useSelectorMode(method, path, autoRevalidateTags) {
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: "FETCH_START" });
355
- const res = await methodRef.current(...args);
356
- if (res.ok) {
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 options = args[0];
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/types.ts
376
- var HTTP_METHODS = ["get", "post", "put", "patch", "delete"];
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/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;
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
- return createProxy();
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/createEnlaceHook.ts
408
- function createEnlaceHook(baseUrl, defaultOptions = {}, hookOptions = {}) {
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 = createEnlace(baseUrl, defaultOptions, {
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
- selectorPath ?? [],
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
- { autoGenerateTags, staleTime }
599
+ {
600
+ autoGenerateTags,
601
+ staleTime,
602
+ enabled: queryOptions?.enabled ?? true,
603
+ pollingInterval: queryOptions?.pollingInterval
604
+ }
440
605
  );
441
606
  }
442
607
  return useEnlaceHook;