@spoosh/angular 0.1.3 → 0.1.4

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/dist/index.js CHANGED
@@ -47,9 +47,10 @@ function createInjectRead(options) {
47
47
  let currentController = null;
48
48
  let currentQueryKey = null;
49
49
  let currentSubscription = null;
50
+ let currentResolvedTags = [];
50
51
  let prevContext = null;
51
- let initialized = false;
52
52
  let isMounted = false;
53
+ const hookId = `angular-${Math.random().toString(36).slice(2)}`;
53
54
  const captureSelector = () => {
54
55
  const selectorResult = {
55
56
  call: null,
@@ -64,6 +65,43 @@ function createInjectRead(options) {
64
65
  readFn(selectorProxy);
65
66
  return selectorResult;
66
67
  };
68
+ const createController = (capturedCall, resolvedPath, resolvedTags, queryKey) => {
69
+ if (currentSubscription) {
70
+ currentSubscription();
71
+ }
72
+ const controller = (0, import_core2.createOperationController)({
73
+ operationType: "read",
74
+ path: capturedCall.path,
75
+ method: capturedCall.method,
76
+ tags: resolvedTags,
77
+ requestOptions: capturedCall.options,
78
+ stateManager,
79
+ eventEmitter,
80
+ pluginExecutor,
81
+ hookId,
82
+ fetchFn: async (fetchOpts) => {
83
+ let current = api;
84
+ for (const segment of resolvedPath) {
85
+ current = current[segment];
86
+ }
87
+ const method = current[capturedCall.method];
88
+ return method(fetchOpts);
89
+ }
90
+ });
91
+ controller.setPluginOptions(pluginOpts);
92
+ currentSubscription = controller.subscribe(() => {
93
+ const state = controller.getState();
94
+ dataSignal.set(state.data);
95
+ errorSignal.set(state.error);
96
+ const entry = stateManager.getCache(queryKey);
97
+ const newMeta = entry?.pluginResult ? Object.fromEntries(entry.pluginResult) : {};
98
+ metaSignal.set(newMeta);
99
+ });
100
+ currentController = controller;
101
+ currentQueryKey = queryKey;
102
+ currentResolvedTags = resolvedTags;
103
+ return controller;
104
+ };
67
105
  const executeWithTracking = async (controller, force = false) => {
68
106
  const hasData = dataSignal() !== void 0;
69
107
  loadingSignal.set(!hasData);
@@ -87,6 +125,34 @@ function createInjectRead(options) {
87
125
  fetchingSignal.set(false);
88
126
  }
89
127
  };
128
+ const initialSelectorResult = captureSelector();
129
+ const initialCapturedCall = initialSelectorResult.call;
130
+ if (!initialCapturedCall) {
131
+ throw new Error(
132
+ "injectRead requires calling an HTTP method ($get). Example: injectRead((api) => api.posts.$get())"
133
+ );
134
+ }
135
+ const initialRequestOptions = initialCapturedCall.options;
136
+ const initialResolvedPath = (0, import_core2.resolvePath)(
137
+ initialCapturedCall.path,
138
+ initialRequestOptions?.params
139
+ );
140
+ const initialResolvedTags = (0, import_core2.resolveTags)(
141
+ { tags, additionalTags },
142
+ initialResolvedPath
143
+ );
144
+ const initialQueryKey = stateManager.createQueryKey({
145
+ path: initialCapturedCall.path,
146
+ method: initialCapturedCall.method,
147
+ options: initialCapturedCall.options
148
+ });
149
+ createController(
150
+ initialCapturedCall,
151
+ initialResolvedPath,
152
+ initialResolvedTags,
153
+ initialQueryKey
154
+ );
155
+ loadingSignal.set(false);
90
156
  let wasEnabled = false;
91
157
  (0, import_core.effect)(
92
158
  () => {
@@ -131,45 +197,20 @@ function createInjectRead(options) {
131
197
  const enabledChanged = isEnabled !== wasEnabled;
132
198
  wasEnabled = isEnabled;
133
199
  if (queryKeyChanged) {
134
- if (currentController && initialized) {
200
+ if (currentController) {
135
201
  prevContext = currentController.getContext();
136
- }
137
- if (currentSubscription) {
138
- currentSubscription();
139
- }
140
- const controller = (0, import_core2.createOperationController)({
141
- operationType: "read",
142
- path: capturedCall.path,
143
- method: capturedCall.method,
144
- tags: resolvedTags,
145
- requestOptions: capturedCall.options,
146
- stateManager,
147
- eventEmitter,
148
- pluginExecutor,
149
- hookId: `angular-${Math.random().toString(36).slice(2)}`,
150
- fetchFn: async (fetchOpts) => {
151
- let current = api;
152
- for (const segment of resolvedPath) {
153
- current = current[segment];
154
- }
155
- const method = current[capturedCall.method];
156
- return method(fetchOpts);
202
+ if (isMounted) {
203
+ currentController.unmount();
204
+ isMounted = false;
157
205
  }
158
- });
159
- controller.setPluginOptions(pluginOpts);
160
- currentSubscription = controller.subscribe(() => {
161
- const state = controller.getState();
162
- dataSignal.set(state.data);
163
- errorSignal.set(state.error);
164
- const entry = stateManager.getCache(queryKey);
165
- const newMeta = entry?.pluginResult ? Object.fromEntries(entry.pluginResult) : {};
166
- metaSignal.set(newMeta);
167
- });
168
- currentController = controller;
169
- currentQueryKey = queryKey;
170
- if (!initialized) {
171
- initialized = true;
172
- } else if (prevContext) {
206
+ }
207
+ const controller = createController(
208
+ capturedCall,
209
+ resolvedPath,
210
+ resolvedTags,
211
+ queryKey
212
+ );
213
+ if (prevContext) {
173
214
  controller.update(prevContext);
174
215
  prevContext = null;
175
216
  }
@@ -212,7 +253,7 @@ function createInjectRead(options) {
212
253
  "invalidate",
213
254
  (invalidatedTags) => {
214
255
  const hasMatch = invalidatedTags.some(
215
- (tag) => resolvedTags.includes(tag)
256
+ (tag) => currentResolvedTags.includes(tag)
216
257
  );
217
258
  if (hasMatch && currentController) {
218
259
  (0, import_core.untracked)(() => {
@@ -241,6 +282,10 @@ function createInjectRead(options) {
241
282
  };
242
283
  const refetch = () => {
243
284
  if (currentController) {
285
+ if (!isMounted) {
286
+ currentController.mount();
287
+ isMounted = true;
288
+ }
244
289
  return executeWithTracking(currentController, true);
245
290
  }
246
291
  return Promise.resolve({ data: void 0, error: void 0 });
@@ -268,81 +313,104 @@ function createInjectWrite(options) {
268
313
  const { api, stateManager, pluginExecutor, eventEmitter } = options;
269
314
  return function injectWrite(writeFn) {
270
315
  const destroyRef = (0, import_core3.inject)(import_core3.DestroyRef);
271
- const selectorResult = {
272
- call: null,
273
- selector: null
274
- };
275
- const selectorProxy = (0, import_core4.createSelectorProxy)(
276
- (result2) => {
277
- selectorResult.call = result2.call;
278
- selectorResult.selector = result2.selector;
279
- }
280
- );
281
- writeFn(selectorProxy);
282
- const selectedEndpoint = selectorResult.selector;
283
- if (!selectedEndpoint) {
284
- throw new Error(
285
- "injectWrite requires selecting an HTTP method ($post, $put, $patch, $delete). Example: injectWrite((api) => api.posts.$post)"
286
- );
287
- }
288
- const queryKey = stateManager.createQueryKey({
289
- path: selectedEndpoint.path,
290
- method: selectedEndpoint.method,
291
- options: void 0
292
- });
293
- const controller = (0, import_core4.createOperationController)({
294
- operationType: "write",
295
- path: selectedEndpoint.path,
296
- method: selectedEndpoint.method,
297
- tags: [],
298
- stateManager,
299
- eventEmitter,
300
- pluginExecutor,
301
- hookId: `angular-${Math.random().toString(36).slice(2)}`,
302
- fetchFn: async (fetchOpts) => {
303
- const params = fetchOpts?.params;
304
- const resolvedPath = (0, import_core4.resolvePath)(selectedEndpoint.path, params);
305
- let current = api;
306
- for (const segment of resolvedPath) {
307
- current = current[segment];
316
+ const captureSelector = () => {
317
+ const selectorResult = {
318
+ call: null,
319
+ selector: null
320
+ };
321
+ const selectorProxy = (0, import_core4.createSelectorProxy)(
322
+ (result2) => {
323
+ selectorResult.call = result2.call;
324
+ selectorResult.selector = result2.selector;
308
325
  }
309
- const method = current[selectedEndpoint.method];
310
- return method(fetchOpts);
326
+ );
327
+ writeFn(selectorProxy);
328
+ if (!selectorResult.selector) {
329
+ throw new Error(
330
+ "injectWrite requires selecting an HTTP method ($post, $put, $patch, $delete). Example: injectWrite((api) => api.posts.$post)"
331
+ );
311
332
  }
312
- });
333
+ return selectorResult.selector;
334
+ };
335
+ const hookId = `angular-${Math.random().toString(36).slice(2)}`;
336
+ let currentQueryKey = null;
337
+ let currentController = null;
338
+ let currentSubscription = null;
313
339
  const dataSignal = (0, import_core3.signal)(void 0);
314
340
  const errorSignal = (0, import_core3.signal)(void 0);
315
341
  const loadingSignal = (0, import_core3.signal)(false);
316
342
  const lastTriggerOptionsSignal = (0, import_core3.signal)(void 0);
317
343
  const metaSignal = (0, import_core3.signal)({});
318
- const subscription = controller.subscribe(() => {
319
- const state = controller.getState();
320
- dataSignal.set(state.data);
321
- errorSignal.set(state.error);
322
- const entry = stateManager.getCache(queryKey);
323
- const newMeta = entry?.pluginResult ? Object.fromEntries(entry.pluginResult) : {};
324
- metaSignal.set(newMeta);
325
- });
326
344
  destroyRef.onDestroy(() => {
327
- subscription();
345
+ if (currentSubscription) {
346
+ currentSubscription();
347
+ }
328
348
  });
329
349
  const reset = () => {
330
- stateManager.deleteCache(queryKey);
350
+ if (currentQueryKey) {
351
+ stateManager.deleteCache(currentQueryKey);
352
+ }
353
+ dataSignal.set(void 0);
331
354
  errorSignal.set(void 0);
332
355
  loadingSignal.set(false);
333
356
  };
334
357
  const abort = () => {
335
- controller.abort();
358
+ currentController?.abort();
336
359
  };
337
360
  const trigger = async (triggerOptions) => {
338
- lastTriggerOptionsSignal.set(triggerOptions);
339
- loadingSignal.set(true);
361
+ const selectedEndpoint = captureSelector();
340
362
  const params = triggerOptions?.params;
341
363
  const resolvedPath = (0, import_core4.resolvePath)(selectedEndpoint.path, params);
342
364
  const tags = (0, import_core4.resolveTags)(triggerOptions, resolvedPath);
343
- controller.setPluginOptions({ ...triggerOptions, tags });
365
+ const queryKey = stateManager.createQueryKey({
366
+ path: selectedEndpoint.path,
367
+ method: selectedEndpoint.method,
368
+ options: triggerOptions
369
+ });
370
+ const needsNewController = !currentController || currentQueryKey !== queryKey;
371
+ if (needsNewController) {
372
+ if (currentSubscription) {
373
+ currentSubscription();
374
+ }
375
+ const controller = (0, import_core4.createOperationController)({
376
+ operationType: "write",
377
+ path: selectedEndpoint.path,
378
+ method: selectedEndpoint.method,
379
+ tags,
380
+ stateManager,
381
+ eventEmitter,
382
+ pluginExecutor,
383
+ hookId,
384
+ fetchFn: async (fetchOpts) => {
385
+ const fetchParams = fetchOpts?.params;
386
+ const fetchResolvedPath = (0, import_core4.resolvePath)(
387
+ selectedEndpoint.path,
388
+ fetchParams
389
+ );
390
+ let current = api;
391
+ for (const segment of fetchResolvedPath) {
392
+ current = current[segment];
393
+ }
394
+ const method = current[selectedEndpoint.method];
395
+ return method(fetchOpts);
396
+ }
397
+ });
398
+ currentSubscription = controller.subscribe(() => {
399
+ const state = controller.getState();
400
+ dataSignal.set(state.data);
401
+ errorSignal.set(state.error);
402
+ const entry = stateManager.getCache(queryKey);
403
+ const newMeta = entry?.pluginResult ? Object.fromEntries(entry.pluginResult) : {};
404
+ metaSignal.set(newMeta);
405
+ });
406
+ currentController = controller;
407
+ currentQueryKey = queryKey;
408
+ }
409
+ lastTriggerOptionsSignal.set(triggerOptions);
410
+ loadingSignal.set(true);
411
+ currentController.setPluginOptions({ ...triggerOptions, tags });
344
412
  try {
345
- const response = await controller.execute(triggerOptions, {
413
+ const response = await currentController.execute(triggerOptions, {
346
414
  force: true
347
415
  });
348
416
  if (response.error) {
@@ -419,70 +487,26 @@ function createInjectInfiniteRead(options) {
419
487
  prevPageRequest,
420
488
  merger
421
489
  };
422
- const selectorResult = {
423
- call: null,
424
- selector: null
425
- };
426
- const selectorProxy = (0, import_core6.createSelectorProxy)(
427
- (result2) => {
428
- selectorResult.call = result2.call;
429
- selectorResult.selector = result2.selector;
430
- }
431
- );
432
- readFn(selectorProxy);
433
- const capturedCall = selectorResult.call;
434
- if (!capturedCall) {
435
- throw new Error(
436
- "injectInfiniteRead requires calling an HTTP method ($get). Example: injectInfiniteRead((api) => api.posts.$get())"
437
- );
438
- }
439
- const requestOptions = capturedCall.options;
440
- const initialRequest = {
441
- query: requestOptions?.query,
442
- params: requestOptions?.params,
443
- body: requestOptions?.body
444
- };
445
- const baseOptionsForKey = {
446
- ...capturedCall.options,
447
- query: void 0,
448
- params: void 0,
449
- body: void 0
450
- };
451
- const resolvedPath = (0, import_core6.resolvePath)(capturedCall.path, requestOptions?.params);
452
- const resolvedTags = (0, import_core6.resolveTags)({ tags, additionalTags }, resolvedPath);
453
- const controller = (0, import_core6.createInfiniteReadController)({
454
- path: capturedCall.path,
455
- method: capturedCall.method,
456
- tags: resolvedTags,
457
- initialRequest,
458
- baseOptionsForKey,
459
- canFetchNext: (ctx) => callbackRefs.canFetchNext(ctx),
460
- canFetchPrev: canFetchPrev ? (ctx) => callbackRefs.canFetchPrev?.(ctx) ?? false : void 0,
461
- nextPageRequest: (ctx) => callbackRefs.nextPageRequest(ctx),
462
- prevPageRequest: prevPageRequest ? (ctx) => callbackRefs.prevPageRequest?.(ctx) ?? {} : void 0,
463
- merger: (responses) => callbackRefs.merger(responses),
464
- stateManager,
465
- eventEmitter,
466
- pluginExecutor,
467
- hookId: `angular-${Math.random().toString(36).slice(2)}`,
468
- fetchFn: async (opts, abortSignal) => {
469
- const fetchPath = (0, import_core6.resolvePath)(capturedCall.path, opts.params);
470
- let current = api;
471
- for (const segment of fetchPath) {
472
- current = current[segment];
490
+ const captureSelector = () => {
491
+ const selectorResult = {
492
+ call: null,
493
+ selector: null
494
+ };
495
+ const selectorProxy = (0, import_core6.createSelectorProxy)(
496
+ (result2) => {
497
+ selectorResult.call = result2.call;
498
+ selectorResult.selector = result2.selector;
473
499
  }
474
- const method = current[capturedCall.method];
475
- const fetchOptions = {
476
- ...capturedCall.options,
477
- query: opts.query,
478
- params: opts.params,
479
- body: opts.body,
480
- signal: abortSignal
481
- };
482
- return method(fetchOptions);
500
+ );
501
+ readFn(selectorProxy);
502
+ if (!selectorResult.call) {
503
+ throw new Error(
504
+ "injectInfiniteRead requires calling an HTTP method ($get). Example: injectInfiniteRead((api) => api.posts.$get())"
505
+ );
483
506
  }
484
- });
485
- controller.setPluginOptions(pluginOpts);
507
+ return selectorResult.call;
508
+ };
509
+ const hookId = `angular-${Math.random().toString(36).slice(2)}`;
486
510
  const dataSignal = (0, import_core5.signal)(void 0);
487
511
  const allResponsesSignal = (0, import_core5.signal)(void 0);
488
512
  const errorSignal = (0, import_core5.signal)(void 0);
@@ -490,29 +514,18 @@ function createInjectInfiniteRead(options) {
490
514
  const canFetchNextSignal = (0, import_core5.signal)(false);
491
515
  const canFetchPrevSignal = (0, import_core5.signal)(false);
492
516
  const metaSignal = (0, import_core5.signal)({});
493
- const queryKey = stateManager.createQueryKey({
494
- path: capturedCall.path,
495
- method: capturedCall.method,
496
- options: baseOptionsForKey
497
- });
498
- const subscription = controller.subscribe(() => {
499
- const state = controller.getState();
500
- dataSignal.set(state.data);
501
- allResponsesSignal.set(state.allResponses);
502
- errorSignal.set(state.error);
503
- canFetchNextSignal.set(state.canFetchNext);
504
- canFetchPrevSignal.set(state.canFetchPrev);
505
- const entry = stateManager.getCache(queryKey);
506
- const newMeta = entry?.pluginResult ? Object.fromEntries(entry.pluginResult) : {};
507
- metaSignal.set(newMeta);
508
- });
509
517
  const fetchingNextSignal = (0, import_core5.signal)(false);
510
518
  const fetchingPrevSignal = (0, import_core5.signal)(false);
519
+ let currentController = null;
520
+ let currentQueryKey = null;
521
+ let currentSubscription = null;
522
+ let currentResolvedTags = [];
511
523
  let prevContext = null;
512
- let hasDoneInitialFetch = false;
513
524
  let isMounted = false;
525
+ let unsubInvalidate = null;
514
526
  const updateSignalsFromState = () => {
515
- const state = controller.getState();
527
+ if (!currentController) return;
528
+ const state = currentController.getState();
516
529
  dataSignal.set(state.data);
517
530
  allResponsesSignal.set(state.allResponses);
518
531
  errorSignal.set(state.error);
@@ -520,14 +533,15 @@ function createInjectInfiniteRead(options) {
520
533
  canFetchPrevSignal.set(state.canFetchPrev);
521
534
  };
522
535
  const triggerFetch = () => {
523
- const currentState = controller.getState();
536
+ if (!currentController) return;
537
+ const currentState = currentController.getState();
524
538
  const isFetching = (0, import_core5.untracked)(
525
539
  () => fetchingNextSignal() || fetchingPrevSignal()
526
540
  );
527
541
  if (currentState.data === void 0 && !isFetching) {
528
542
  loadingSignal.set(true);
529
543
  fetchingNextSignal.set(true);
530
- controller.fetchNext().finally(() => {
544
+ currentController.fetchNext().finally(() => {
531
545
  updateSignalsFromState();
532
546
  loadingSignal.set(false);
533
547
  fetchingNextSignal.set(false);
@@ -536,92 +550,230 @@ function createInjectInfiniteRead(options) {
536
550
  updateSignalsFromState();
537
551
  }
538
552
  };
539
- const unsubInvalidate = eventEmitter.on(
540
- "invalidate",
541
- (invalidatedTags) => {
542
- if (!getEnabled()) return;
543
- const hasMatch = invalidatedTags.some(
544
- (tag) => resolvedTags.includes(tag)
545
- );
546
- if (hasMatch) {
547
- loadingSignal.set(true);
548
- controller.refetch().finally(() => {
549
- updateSignalsFromState();
550
- loadingSignal.set(false);
551
- });
552
- }
553
+ const createController = (capturedCall, resolvedTags, queryKey) => {
554
+ if (currentSubscription) {
555
+ currentSubscription();
556
+ }
557
+ if (unsubInvalidate) {
558
+ unsubInvalidate();
553
559
  }
560
+ const requestOptions = capturedCall.options;
561
+ const baseOptionsForKey = {
562
+ ...capturedCall.options,
563
+ query: void 0,
564
+ params: void 0,
565
+ body: void 0
566
+ };
567
+ const initialRequest = {
568
+ query: requestOptions?.query,
569
+ params: requestOptions?.params,
570
+ body: requestOptions?.body
571
+ };
572
+ const controller = (0, import_core6.createInfiniteReadController)({
573
+ path: capturedCall.path,
574
+ method: capturedCall.method,
575
+ tags: resolvedTags,
576
+ initialRequest,
577
+ baseOptionsForKey,
578
+ canFetchNext: (ctx) => callbackRefs.canFetchNext(ctx),
579
+ canFetchPrev: canFetchPrev ? (ctx) => callbackRefs.canFetchPrev?.(ctx) ?? false : void 0,
580
+ nextPageRequest: (ctx) => callbackRefs.nextPageRequest(ctx),
581
+ prevPageRequest: prevPageRequest ? (ctx) => callbackRefs.prevPageRequest?.(ctx) ?? {} : void 0,
582
+ merger: (responses) => callbackRefs.merger(responses),
583
+ stateManager,
584
+ eventEmitter,
585
+ pluginExecutor,
586
+ hookId,
587
+ fetchFn: async (opts, abortSignal) => {
588
+ const fetchPath = (0, import_core6.resolvePath)(capturedCall.path, opts.params);
589
+ let current = api;
590
+ for (const segment of fetchPath) {
591
+ current = current[segment];
592
+ }
593
+ const method = current[capturedCall.method];
594
+ const fetchOptions = {
595
+ ...capturedCall.options,
596
+ query: opts.query,
597
+ params: opts.params,
598
+ body: opts.body,
599
+ signal: abortSignal
600
+ };
601
+ return method(fetchOptions);
602
+ }
603
+ });
604
+ controller.setPluginOptions(pluginOpts);
605
+ currentSubscription = controller.subscribe(() => {
606
+ const state = controller.getState();
607
+ dataSignal.set(state.data);
608
+ allResponsesSignal.set(state.allResponses);
609
+ errorSignal.set(state.error);
610
+ canFetchNextSignal.set(state.canFetchNext);
611
+ canFetchPrevSignal.set(state.canFetchPrev);
612
+ const entry = stateManager.getCache(queryKey);
613
+ const newMeta = entry?.pluginResult ? Object.fromEntries(entry.pluginResult) : {};
614
+ metaSignal.set(newMeta);
615
+ });
616
+ currentController = controller;
617
+ currentQueryKey = queryKey;
618
+ currentResolvedTags = resolvedTags;
619
+ unsubInvalidate = eventEmitter.on(
620
+ "invalidate",
621
+ (invalidatedTags) => {
622
+ if (!getEnabled() || !currentController) return;
623
+ const hasMatch = invalidatedTags.some(
624
+ (tag) => currentResolvedTags.includes(tag)
625
+ );
626
+ if (hasMatch) {
627
+ loadingSignal.set(true);
628
+ currentController.refetch().finally(() => {
629
+ updateSignalsFromState();
630
+ loadingSignal.set(false);
631
+ });
632
+ }
633
+ }
634
+ );
635
+ return controller;
636
+ };
637
+ const initialCapturedCall = captureSelector();
638
+ const initialRequestOptions = initialCapturedCall.options;
639
+ const initialResolvedPath = (0, import_core6.resolvePath)(
640
+ initialCapturedCall.path,
641
+ initialRequestOptions?.params
642
+ );
643
+ const initialResolvedTags = (0, import_core6.resolveTags)(
644
+ { tags, additionalTags },
645
+ initialResolvedPath
554
646
  );
647
+ const initialBaseOptionsForKey = {
648
+ ...initialCapturedCall.options,
649
+ query: void 0,
650
+ params: void 0,
651
+ body: void 0
652
+ };
653
+ const initialQueryKey = stateManager.createQueryKey({
654
+ path: initialCapturedCall.path,
655
+ method: initialCapturedCall.method,
656
+ options: initialBaseOptionsForKey
657
+ });
658
+ createController(initialCapturedCall, initialResolvedTags, initialQueryKey);
555
659
  (0, import_core5.effect)(
556
660
  () => {
557
661
  const isEnabled = getEnabled();
662
+ const capturedCall = captureSelector();
663
+ const requestOptions = capturedCall.options;
664
+ const resolvedPath = (0, import_core6.resolvePath)(
665
+ capturedCall.path,
666
+ requestOptions?.params
667
+ );
668
+ const resolvedTags = (0, import_core6.resolveTags)(
669
+ { tags, additionalTags },
670
+ resolvedPath
671
+ );
672
+ const baseOptionsForKey = {
673
+ ...capturedCall.options,
674
+ query: void 0,
675
+ params: void 0,
676
+ body: void 0
677
+ };
678
+ const queryKey = stateManager.createQueryKey({
679
+ path: capturedCall.path,
680
+ method: capturedCall.method,
681
+ options: baseOptionsForKey
682
+ });
683
+ const queryKeyChanged = queryKey !== currentQueryKey;
558
684
  if (!isEnabled) {
559
- if (isMounted) {
560
- controller.unmount();
685
+ if (isMounted && currentController) {
686
+ currentController.unmount();
561
687
  isMounted = false;
562
688
  }
689
+ loadingSignal.set(false);
563
690
  return;
564
691
  }
565
- if (!isMounted) {
692
+ if (queryKeyChanged) {
693
+ if (currentController && isMounted) {
694
+ prevContext = currentController.getContext();
695
+ currentController.unmount();
696
+ isMounted = false;
697
+ }
698
+ const controller = createController(
699
+ capturedCall,
700
+ resolvedTags,
701
+ queryKey
702
+ );
703
+ if (prevContext) {
704
+ controller.update(prevContext);
705
+ prevContext = null;
706
+ }
566
707
  controller.mount();
567
708
  isMounted = true;
568
- }
569
- if (!hasDoneInitialFetch) {
570
- hasDoneInitialFetch = true;
571
709
  (0, import_core5.untracked)(() => {
572
710
  triggerFetch();
573
711
  });
574
- }
575
- if (prevContext) {
712
+ } else if (!isMounted && currentController) {
713
+ currentController.mount();
714
+ isMounted = true;
576
715
  (0, import_core5.untracked)(() => {
577
- controller.update(prevContext);
578
- prevContext = null;
716
+ triggerFetch();
579
717
  });
580
718
  }
581
719
  },
582
720
  { allowSignalWrites: true }
583
721
  );
584
722
  destroyRef.onDestroy(() => {
585
- unsubInvalidate();
586
- });
587
- destroyRef.onDestroy(() => {
588
- subscription();
589
- if (isMounted) {
590
- controller.unmount();
723
+ if (unsubInvalidate) {
724
+ unsubInvalidate();
725
+ }
726
+ if (currentSubscription) {
727
+ currentSubscription();
728
+ }
729
+ if (currentController && isMounted) {
730
+ currentController.unmount();
591
731
  }
592
732
  });
593
733
  const fetchNext = async () => {
594
- if (!getEnabled()) return;
734
+ if (!currentController) return;
735
+ if (!isMounted) {
736
+ currentController.mount();
737
+ isMounted = true;
738
+ }
595
739
  fetchingNextSignal.set(true);
596
740
  try {
597
- await controller.fetchNext();
741
+ await currentController.fetchNext();
598
742
  updateSignalsFromState();
599
743
  } finally {
600
744
  fetchingNextSignal.set(false);
601
745
  }
602
746
  };
603
747
  const fetchPrev = async () => {
604
- if (!getEnabled()) return;
748
+ if (!currentController) return;
749
+ if (!isMounted) {
750
+ currentController.mount();
751
+ isMounted = true;
752
+ }
605
753
  fetchingPrevSignal.set(true);
606
754
  try {
607
- await controller.fetchPrev();
755
+ await currentController.fetchPrev();
608
756
  updateSignalsFromState();
609
757
  } finally {
610
758
  fetchingPrevSignal.set(false);
611
759
  }
612
760
  };
613
761
  const refetch = async () => {
614
- if (!getEnabled()) return;
762
+ if (!currentController) return;
763
+ if (!isMounted) {
764
+ currentController.mount();
765
+ isMounted = true;
766
+ }
615
767
  loadingSignal.set(true);
616
768
  try {
617
- await controller.refetch();
769
+ await currentController.refetch();
618
770
  updateSignalsFromState();
619
771
  } finally {
620
772
  loadingSignal.set(false);
621
773
  }
622
774
  };
623
775
  const abort = () => {
624
- controller.abort();
776
+ currentController?.abort();
625
777
  };
626
778
  const fetchingSignal = (0, import_core5.computed)(
627
779
  () => fetchingNextSignal() || fetchingPrevSignal()