@spoosh/plugin-optimistic 0.6.0 → 0.7.0

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.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { FindMatchingKey, HasParams, ExtractParamNames, Simplify, ExtractData, SpooshPlugin } from '@spoosh/core';
1
+ import { ReadPaths, FindMatchingKey, HasParams, ExtractParamNames, Simplify, ExtractData, SpooshPlugin } from '@spoosh/core';
2
2
 
3
3
  /**
4
4
  * Check if query exists in the method config.
@@ -94,22 +94,20 @@ type OptimisticBuilder<TData = unknown, TMethodConfig = unknown, TUserPath exten
94
94
  */
95
95
  ON_ERROR: IfNotUsed<"ON_ERROR", TUsed, (callback: (error: unknown) => void) => OptimisticBuilder<TData, TMethodConfig, TUserPath, TResponse, TTiming, TUsed | "ON_ERROR", TCompleted>>;
96
96
  };
97
- /**
98
- * Extract paths that have GET methods.
99
- */
100
- type ReadPaths<TSchema> = {
101
- [K in keyof TSchema & string]: "GET" extends keyof TSchema[K] ? K : never;
102
- }[keyof TSchema & string];
103
97
  /**
104
98
  * Path methods proxy for optimistic API - only GET.
99
+ * Resolves literal paths (e.g., "posts/1") to schema keys (e.g., "posts/:id") using FindMatchingKey.
100
+ * Uses TPath for param extraction to preserve user's param names.
105
101
  */
106
102
  type OptimisticPathMethods<TSchema, TPath extends string, TResponse> = FindMatchingKey<TSchema, TPath> extends infer TKey ? TKey extends keyof TSchema ? TSchema[TKey] extends infer TRoute ? "GET" extends keyof TRoute ? TRoute["GET"] extends infer TGetConfig ? {
107
103
  GET: () => OptimisticBuilder<ExtractData<TGetConfig>, TGetConfig, TPath, TResponse, "immediate", never, false>;
108
104
  } : never : never : never : never : never;
109
105
  /**
110
106
  * Helper type for creating the optimistic API proxy.
107
+ * Accepts both schema-defined paths (e.g., "posts/:id") and literal paths (e.g., "posts/1").
108
+ * Uses union with (string & {}) to allow any string while preserving autocomplete.
111
109
  */
112
- type OptimisticApiHelper<TSchema, TResponse = unknown> = <TPath extends ReadPaths<TSchema>>(path: TPath) => OptimisticPathMethods<TSchema, TPath, TResponse>;
110
+ type OptimisticApiHelper<TSchema, TResponse = unknown> = <TPath extends ReadPaths<TSchema> | (string & {})>(path: TPath) => OptimisticPathMethods<TSchema, TPath, TResponse>;
113
111
  /**
114
112
  * A generic OptimisticTarget that accepts any data/response types.
115
113
  * Used for the return type of the callback.
@@ -205,7 +203,7 @@ interface OptimisticWriteTriggerOptions<TSchema = unknown, TResponse = unknown>
205
203
  optimistic?: OptimisticCallbackFn<TSchema, TResponse>;
206
204
  }
207
205
  type OptimisticReadOptions = object;
208
- type OptimisticInfiniteReadOptions = object;
206
+ type OptimisticPagesOptions = object;
209
207
  interface OptimisticReadResult {
210
208
  isOptimistic: boolean;
211
209
  }
@@ -220,9 +218,9 @@ declare function optimisticPlugin(): SpooshPlugin<{
220
218
  readOptions: OptimisticReadOptions;
221
219
  writeOptions: OptimisticWriteOptions;
222
220
  writeTriggerOptions: OptimisticWriteTriggerOptions;
223
- infiniteReadOptions: OptimisticInfiniteReadOptions;
221
+ pagesOptions: OptimisticPagesOptions;
224
222
  readResult: OptimisticReadResult;
225
223
  writeResult: OptimisticWriteResult;
226
224
  }>;
227
225
 
228
- export { type AnyOptimisticTarget, type OptimisticApiHelper, type OptimisticBuilder, type OptimisticCallbackFn, type OptimisticInfiniteReadOptions, type OptimisticPluginConfig, type OptimisticReadOptions, type OptimisticReadResult, type OptimisticTarget, type OptimisticWriteOptions, type OptimisticWriteResult, type OptimisticWriteTriggerOptions, optimisticPlugin };
226
+ export { type AnyOptimisticTarget, type OptimisticApiHelper, type OptimisticBuilder, type OptimisticCallbackFn, type OptimisticPagesOptions, type OptimisticPluginConfig, type OptimisticReadOptions, type OptimisticReadResult, type OptimisticTarget, type OptimisticWriteOptions, type OptimisticWriteResult, type OptimisticWriteTriggerOptions, optimisticPlugin };
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { FindMatchingKey, HasParams, ExtractParamNames, Simplify, ExtractData, SpooshPlugin } from '@spoosh/core';
1
+ import { ReadPaths, FindMatchingKey, HasParams, ExtractParamNames, Simplify, ExtractData, SpooshPlugin } from '@spoosh/core';
2
2
 
3
3
  /**
4
4
  * Check if query exists in the method config.
@@ -94,22 +94,20 @@ type OptimisticBuilder<TData = unknown, TMethodConfig = unknown, TUserPath exten
94
94
  */
95
95
  ON_ERROR: IfNotUsed<"ON_ERROR", TUsed, (callback: (error: unknown) => void) => OptimisticBuilder<TData, TMethodConfig, TUserPath, TResponse, TTiming, TUsed | "ON_ERROR", TCompleted>>;
96
96
  };
97
- /**
98
- * Extract paths that have GET methods.
99
- */
100
- type ReadPaths<TSchema> = {
101
- [K in keyof TSchema & string]: "GET" extends keyof TSchema[K] ? K : never;
102
- }[keyof TSchema & string];
103
97
  /**
104
98
  * Path methods proxy for optimistic API - only GET.
99
+ * Resolves literal paths (e.g., "posts/1") to schema keys (e.g., "posts/:id") using FindMatchingKey.
100
+ * Uses TPath for param extraction to preserve user's param names.
105
101
  */
106
102
  type OptimisticPathMethods<TSchema, TPath extends string, TResponse> = FindMatchingKey<TSchema, TPath> extends infer TKey ? TKey extends keyof TSchema ? TSchema[TKey] extends infer TRoute ? "GET" extends keyof TRoute ? TRoute["GET"] extends infer TGetConfig ? {
107
103
  GET: () => OptimisticBuilder<ExtractData<TGetConfig>, TGetConfig, TPath, TResponse, "immediate", never, false>;
108
104
  } : never : never : never : never : never;
109
105
  /**
110
106
  * Helper type for creating the optimistic API proxy.
107
+ * Accepts both schema-defined paths (e.g., "posts/:id") and literal paths (e.g., "posts/1").
108
+ * Uses union with (string & {}) to allow any string while preserving autocomplete.
111
109
  */
112
- type OptimisticApiHelper<TSchema, TResponse = unknown> = <TPath extends ReadPaths<TSchema>>(path: TPath) => OptimisticPathMethods<TSchema, TPath, TResponse>;
110
+ type OptimisticApiHelper<TSchema, TResponse = unknown> = <TPath extends ReadPaths<TSchema> | (string & {})>(path: TPath) => OptimisticPathMethods<TSchema, TPath, TResponse>;
113
111
  /**
114
112
  * A generic OptimisticTarget that accepts any data/response types.
115
113
  * Used for the return type of the callback.
@@ -205,7 +203,7 @@ interface OptimisticWriteTriggerOptions<TSchema = unknown, TResponse = unknown>
205
203
  optimistic?: OptimisticCallbackFn<TSchema, TResponse>;
206
204
  }
207
205
  type OptimisticReadOptions = object;
208
- type OptimisticInfiniteReadOptions = object;
206
+ type OptimisticPagesOptions = object;
209
207
  interface OptimisticReadResult {
210
208
  isOptimistic: boolean;
211
209
  }
@@ -220,9 +218,9 @@ declare function optimisticPlugin(): SpooshPlugin<{
220
218
  readOptions: OptimisticReadOptions;
221
219
  writeOptions: OptimisticWriteOptions;
222
220
  writeTriggerOptions: OptimisticWriteTriggerOptions;
223
- infiniteReadOptions: OptimisticInfiniteReadOptions;
221
+ pagesOptions: OptimisticPagesOptions;
224
222
  readResult: OptimisticReadResult;
225
223
  writeResult: OptimisticWriteResult;
226
224
  }>;
227
225
 
228
- export { type AnyOptimisticTarget, type OptimisticApiHelper, type OptimisticBuilder, type OptimisticCallbackFn, type OptimisticInfiniteReadOptions, type OptimisticPluginConfig, type OptimisticReadOptions, type OptimisticReadResult, type OptimisticTarget, type OptimisticWriteOptions, type OptimisticWriteResult, type OptimisticWriteTriggerOptions, optimisticPlugin };
226
+ export { type AnyOptimisticTarget, type OptimisticApiHelper, type OptimisticBuilder, type OptimisticCallbackFn, type OptimisticPagesOptions, type OptimisticPluginConfig, type OptimisticReadOptions, type OptimisticReadResult, type OptimisticTarget, type OptimisticWriteOptions, type OptimisticWriteResult, type OptimisticWriteTriggerOptions, optimisticPlugin };
package/dist/index.js CHANGED
@@ -25,7 +25,6 @@ __export(src_exports, {
25
25
  module.exports = __toCommonJS(src_exports);
26
26
 
27
27
  // src/plugin.ts
28
- var import_core = require("@spoosh/core");
29
28
  var import_plugin_invalidation = require("@spoosh/plugin-invalidation");
30
29
  function createBuilder(state) {
31
30
  return {
@@ -58,12 +57,50 @@ function createOptimisticProxy() {
58
57
  });
59
58
  return ((path) => createMethodsProxy(path));
60
59
  }
61
- function extractTagsFromPath(path) {
62
- const pathSegments = path.split("/").filter(Boolean);
63
- return (0, import_core.generateTags)(pathSegments);
60
+ function isParameterSegment(segment) {
61
+ return segment.startsWith(":");
64
62
  }
65
- function getExactMatchPath(tags) {
66
- return tags.length > 0 ? tags[tags.length - 1] : void 0;
63
+ function pathMatchesPattern(actualPath, pattern) {
64
+ const actualSegments = actualPath.split("/").filter(Boolean);
65
+ const patternSegments = pattern.split("/").filter(Boolean);
66
+ if (actualSegments.length !== patternSegments.length) {
67
+ return { matches: false, params: {}, paramMapping: {} };
68
+ }
69
+ const params = {};
70
+ const paramMapping = {};
71
+ for (let i = 0; i < patternSegments.length; i++) {
72
+ const patternSeg = patternSegments[i];
73
+ const actualSeg = actualSegments[i];
74
+ if (isParameterSegment(patternSeg)) {
75
+ const targetParamName = patternSeg.slice(1);
76
+ if (isParameterSegment(actualSeg)) {
77
+ const actualParamName = actualSeg.slice(1);
78
+ paramMapping[targetParamName] = actualParamName;
79
+ continue;
80
+ }
81
+ params[targetParamName] = actualSeg;
82
+ } else if (isParameterSegment(actualSeg)) {
83
+ continue;
84
+ } else if (patternSeg !== actualSeg) {
85
+ return { matches: false, params: {}, paramMapping: {} };
86
+ }
87
+ }
88
+ return { matches: true, params, paramMapping };
89
+ }
90
+ function hasPatternParams(path) {
91
+ return path.split("/").some(isParameterSegment);
92
+ }
93
+ function extractPathFromKey(key) {
94
+ try {
95
+ const parsed = JSON.parse(key);
96
+ const path = parsed.path;
97
+ if (typeof path === "string") {
98
+ return path;
99
+ }
100
+ return null;
101
+ } catch {
102
+ return null;
103
+ }
67
104
  }
68
105
  function extractOptionsFromKey(key) {
69
106
  try {
@@ -82,6 +119,21 @@ function extractOptionsFromKey(key) {
82
119
  return null;
83
120
  }
84
121
  }
122
+ function mapParamsToTargetNames(actualParams, paramMapping) {
123
+ if (!actualParams) return {};
124
+ const result = {};
125
+ for (const [targetName, actualName] of Object.entries(paramMapping)) {
126
+ if (actualName in actualParams) {
127
+ result[targetName] = actualParams[actualName];
128
+ }
129
+ }
130
+ for (const [key, value] of Object.entries(actualParams)) {
131
+ if (!Object.values(paramMapping).includes(key)) {
132
+ result[key] = value;
133
+ }
134
+ }
135
+ return result;
136
+ }
85
137
  function resolveOptimisticTargets(context) {
86
138
  const pluginOptions = context.pluginOptions;
87
139
  if (!pluginOptions?.optimistic) return [];
@@ -90,27 +142,70 @@ function resolveOptimisticTargets(context) {
90
142
  const targets = Array.isArray(result) ? result : [result];
91
143
  return targets;
92
144
  }
145
+ function getMatchingEntries(stateManager, targetPath, targetMethod) {
146
+ const results = [];
147
+ if (hasPatternParams(targetPath)) {
148
+ const allEntries = stateManager.getAllCacheEntries();
149
+ for (const { key, entry } of allEntries) {
150
+ if (!key.includes(`"method":"${targetMethod}"`)) continue;
151
+ const actualPath = extractPathFromKey(key);
152
+ if (!actualPath) continue;
153
+ const { matches, params, paramMapping } = pathMatchesPattern(
154
+ actualPath,
155
+ targetPath
156
+ );
157
+ if (matches) {
158
+ results.push({ key, entry, extractedParams: params, paramMapping });
159
+ }
160
+ }
161
+ } else {
162
+ const allEntries = stateManager.getAllCacheEntries();
163
+ for (const { key, entry } of allEntries) {
164
+ if (!key.includes(`"method":"${targetMethod}"`)) continue;
165
+ const actualPath = extractPathFromKey(key);
166
+ if (!actualPath) continue;
167
+ if (actualPath === targetPath) {
168
+ results.push({ key, entry, extractedParams: {}, paramMapping: {} });
169
+ } else if (hasPatternParams(actualPath)) {
170
+ const { matches, params, paramMapping } = pathMatchesPattern(
171
+ targetPath,
172
+ actualPath
173
+ );
174
+ if (matches) {
175
+ results.push({ key, entry, extractedParams: params, paramMapping });
176
+ }
177
+ }
178
+ }
179
+ }
180
+ return results;
181
+ }
93
182
  function applyOptimisticUpdate(stateManager, target, t) {
94
183
  if (!target.updater) return [];
95
- const tags = extractTagsFromPath(target.path);
96
- const targetSelfTag = getExactMatchPath(tags);
97
- if (!targetSelfTag) return [];
98
184
  const snapshots = [];
99
- const entries = stateManager.getCacheEntriesBySelfTag(targetSelfTag);
100
- for (const { key, entry } of entries) {
101
- if (key.includes('"type":"infinite-tracker"')) {
102
- continue;
103
- }
104
- if (!key.includes(`"method":"${target.method}"`)) {
105
- continue;
106
- }
185
+ const matchingEntries = getMatchingEntries(
186
+ stateManager,
187
+ target.path,
188
+ target.method
189
+ );
190
+ for (const { key, entry, extractedParams, paramMapping } of matchingEntries) {
107
191
  if (target.where) {
108
- const options = extractOptionsFromKey(key);
109
- if (!options || !target.where(options)) {
192
+ const options = extractOptionsFromKey(key) ?? {};
193
+ const mappedParams = mapParamsToTargetNames(
194
+ options.params,
195
+ paramMapping
196
+ );
197
+ const mergedOptions = {
198
+ ...options,
199
+ params: {
200
+ ...extractedParams,
201
+ ...mappedParams
202
+ }
203
+ };
204
+ if (!target.where(mergedOptions)) {
110
205
  continue;
111
206
  }
112
207
  }
113
- if (entry.state.data === void 0) {
208
+ if (entry?.state.data === void 0) {
114
209
  continue;
115
210
  }
116
211
  const afterData = target.updater(entry.state.data, void 0);
@@ -233,24 +328,35 @@ function optimisticPlugin() {
233
328
  const onSuccessSnapshots = [];
234
329
  for (const target of onSuccessTargets) {
235
330
  if (!target.updater) continue;
236
- const tags = extractTagsFromPath(target.path);
237
- const targetSelfTag = getExactMatchPath(tags);
238
- if (!targetSelfTag) continue;
239
- const entries = stateManager.getCacheEntriesBySelfTag(targetSelfTag);
240
- for (const { key, entry } of entries) {
241
- if (key.includes('"type":"infinite-tracker"')) {
242
- continue;
243
- }
244
- if (!key.includes(`"method":"${target.method}"`)) {
245
- continue;
246
- }
331
+ const matchingEntries = getMatchingEntries(
332
+ stateManager,
333
+ target.path,
334
+ target.method
335
+ );
336
+ for (const {
337
+ key,
338
+ entry,
339
+ extractedParams,
340
+ paramMapping
341
+ } of matchingEntries) {
247
342
  if (target.where) {
248
- const options = extractOptionsFromKey(key);
249
- if (!options || !target.where(options)) {
343
+ const options = extractOptionsFromKey(key) ?? {};
344
+ const mappedParams = mapParamsToTargetNames(
345
+ options.params,
346
+ paramMapping
347
+ );
348
+ const mergedOptions = {
349
+ ...options,
350
+ params: {
351
+ ...extractedParams,
352
+ ...mappedParams
353
+ }
354
+ };
355
+ if (!target.where(mergedOptions)) {
250
356
  continue;
251
357
  }
252
358
  }
253
- if (entry.state.data === void 0) {
359
+ if (entry?.state.data === void 0) {
254
360
  continue;
255
361
  }
256
362
  const afterData = target.updater(entry.state.data, response.data);
package/dist/index.mjs CHANGED
@@ -1,5 +1,4 @@
1
1
  // src/plugin.ts
2
- import { generateTags } from "@spoosh/core";
3
2
  import "@spoosh/plugin-invalidation";
4
3
  function createBuilder(state) {
5
4
  return {
@@ -32,12 +31,50 @@ function createOptimisticProxy() {
32
31
  });
33
32
  return ((path) => createMethodsProxy(path));
34
33
  }
35
- function extractTagsFromPath(path) {
36
- const pathSegments = path.split("/").filter(Boolean);
37
- return generateTags(pathSegments);
34
+ function isParameterSegment(segment) {
35
+ return segment.startsWith(":");
38
36
  }
39
- function getExactMatchPath(tags) {
40
- return tags.length > 0 ? tags[tags.length - 1] : void 0;
37
+ function pathMatchesPattern(actualPath, pattern) {
38
+ const actualSegments = actualPath.split("/").filter(Boolean);
39
+ const patternSegments = pattern.split("/").filter(Boolean);
40
+ if (actualSegments.length !== patternSegments.length) {
41
+ return { matches: false, params: {}, paramMapping: {} };
42
+ }
43
+ const params = {};
44
+ const paramMapping = {};
45
+ for (let i = 0; i < patternSegments.length; i++) {
46
+ const patternSeg = patternSegments[i];
47
+ const actualSeg = actualSegments[i];
48
+ if (isParameterSegment(patternSeg)) {
49
+ const targetParamName = patternSeg.slice(1);
50
+ if (isParameterSegment(actualSeg)) {
51
+ const actualParamName = actualSeg.slice(1);
52
+ paramMapping[targetParamName] = actualParamName;
53
+ continue;
54
+ }
55
+ params[targetParamName] = actualSeg;
56
+ } else if (isParameterSegment(actualSeg)) {
57
+ continue;
58
+ } else if (patternSeg !== actualSeg) {
59
+ return { matches: false, params: {}, paramMapping: {} };
60
+ }
61
+ }
62
+ return { matches: true, params, paramMapping };
63
+ }
64
+ function hasPatternParams(path) {
65
+ return path.split("/").some(isParameterSegment);
66
+ }
67
+ function extractPathFromKey(key) {
68
+ try {
69
+ const parsed = JSON.parse(key);
70
+ const path = parsed.path;
71
+ if (typeof path === "string") {
72
+ return path;
73
+ }
74
+ return null;
75
+ } catch {
76
+ return null;
77
+ }
41
78
  }
42
79
  function extractOptionsFromKey(key) {
43
80
  try {
@@ -56,6 +93,21 @@ function extractOptionsFromKey(key) {
56
93
  return null;
57
94
  }
58
95
  }
96
+ function mapParamsToTargetNames(actualParams, paramMapping) {
97
+ if (!actualParams) return {};
98
+ const result = {};
99
+ for (const [targetName, actualName] of Object.entries(paramMapping)) {
100
+ if (actualName in actualParams) {
101
+ result[targetName] = actualParams[actualName];
102
+ }
103
+ }
104
+ for (const [key, value] of Object.entries(actualParams)) {
105
+ if (!Object.values(paramMapping).includes(key)) {
106
+ result[key] = value;
107
+ }
108
+ }
109
+ return result;
110
+ }
59
111
  function resolveOptimisticTargets(context) {
60
112
  const pluginOptions = context.pluginOptions;
61
113
  if (!pluginOptions?.optimistic) return [];
@@ -64,27 +116,70 @@ function resolveOptimisticTargets(context) {
64
116
  const targets = Array.isArray(result) ? result : [result];
65
117
  return targets;
66
118
  }
119
+ function getMatchingEntries(stateManager, targetPath, targetMethod) {
120
+ const results = [];
121
+ if (hasPatternParams(targetPath)) {
122
+ const allEntries = stateManager.getAllCacheEntries();
123
+ for (const { key, entry } of allEntries) {
124
+ if (!key.includes(`"method":"${targetMethod}"`)) continue;
125
+ const actualPath = extractPathFromKey(key);
126
+ if (!actualPath) continue;
127
+ const { matches, params, paramMapping } = pathMatchesPattern(
128
+ actualPath,
129
+ targetPath
130
+ );
131
+ if (matches) {
132
+ results.push({ key, entry, extractedParams: params, paramMapping });
133
+ }
134
+ }
135
+ } else {
136
+ const allEntries = stateManager.getAllCacheEntries();
137
+ for (const { key, entry } of allEntries) {
138
+ if (!key.includes(`"method":"${targetMethod}"`)) continue;
139
+ const actualPath = extractPathFromKey(key);
140
+ if (!actualPath) continue;
141
+ if (actualPath === targetPath) {
142
+ results.push({ key, entry, extractedParams: {}, paramMapping: {} });
143
+ } else if (hasPatternParams(actualPath)) {
144
+ const { matches, params, paramMapping } = pathMatchesPattern(
145
+ targetPath,
146
+ actualPath
147
+ );
148
+ if (matches) {
149
+ results.push({ key, entry, extractedParams: params, paramMapping });
150
+ }
151
+ }
152
+ }
153
+ }
154
+ return results;
155
+ }
67
156
  function applyOptimisticUpdate(stateManager, target, t) {
68
157
  if (!target.updater) return [];
69
- const tags = extractTagsFromPath(target.path);
70
- const targetSelfTag = getExactMatchPath(tags);
71
- if (!targetSelfTag) return [];
72
158
  const snapshots = [];
73
- const entries = stateManager.getCacheEntriesBySelfTag(targetSelfTag);
74
- for (const { key, entry } of entries) {
75
- if (key.includes('"type":"infinite-tracker"')) {
76
- continue;
77
- }
78
- if (!key.includes(`"method":"${target.method}"`)) {
79
- continue;
80
- }
159
+ const matchingEntries = getMatchingEntries(
160
+ stateManager,
161
+ target.path,
162
+ target.method
163
+ );
164
+ for (const { key, entry, extractedParams, paramMapping } of matchingEntries) {
81
165
  if (target.where) {
82
- const options = extractOptionsFromKey(key);
83
- if (!options || !target.where(options)) {
166
+ const options = extractOptionsFromKey(key) ?? {};
167
+ const mappedParams = mapParamsToTargetNames(
168
+ options.params,
169
+ paramMapping
170
+ );
171
+ const mergedOptions = {
172
+ ...options,
173
+ params: {
174
+ ...extractedParams,
175
+ ...mappedParams
176
+ }
177
+ };
178
+ if (!target.where(mergedOptions)) {
84
179
  continue;
85
180
  }
86
181
  }
87
- if (entry.state.data === void 0) {
182
+ if (entry?.state.data === void 0) {
88
183
  continue;
89
184
  }
90
185
  const afterData = target.updater(entry.state.data, void 0);
@@ -207,24 +302,35 @@ function optimisticPlugin() {
207
302
  const onSuccessSnapshots = [];
208
303
  for (const target of onSuccessTargets) {
209
304
  if (!target.updater) continue;
210
- const tags = extractTagsFromPath(target.path);
211
- const targetSelfTag = getExactMatchPath(tags);
212
- if (!targetSelfTag) continue;
213
- const entries = stateManager.getCacheEntriesBySelfTag(targetSelfTag);
214
- for (const { key, entry } of entries) {
215
- if (key.includes('"type":"infinite-tracker"')) {
216
- continue;
217
- }
218
- if (!key.includes(`"method":"${target.method}"`)) {
219
- continue;
220
- }
305
+ const matchingEntries = getMatchingEntries(
306
+ stateManager,
307
+ target.path,
308
+ target.method
309
+ );
310
+ for (const {
311
+ key,
312
+ entry,
313
+ extractedParams,
314
+ paramMapping
315
+ } of matchingEntries) {
221
316
  if (target.where) {
222
- const options = extractOptionsFromKey(key);
223
- if (!options || !target.where(options)) {
317
+ const options = extractOptionsFromKey(key) ?? {};
318
+ const mappedParams = mapParamsToTargetNames(
319
+ options.params,
320
+ paramMapping
321
+ );
322
+ const mergedOptions = {
323
+ ...options,
324
+ params: {
325
+ ...extractedParams,
326
+ ...mappedParams
327
+ }
328
+ };
329
+ if (!target.where(mergedOptions)) {
224
330
  continue;
225
331
  }
226
332
  }
227
- if (entry.state.data === void 0) {
333
+ if (entry?.state.data === void 0) {
228
334
  continue;
229
335
  }
230
336
  const afterData = target.updater(entry.state.data, response.data);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@spoosh/plugin-optimistic",
3
- "version": "0.6.0",
3
+ "version": "0.7.0",
4
4
  "description": "Optimistic updates plugin for Spoosh - instant UI updates with automatic rollback",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -33,13 +33,13 @@
33
33
  }
34
34
  },
35
35
  "peerDependencies": {
36
- "@spoosh/core": ">=0.13.1",
36
+ "@spoosh/core": ">=0.15.0",
37
37
  "@spoosh/plugin-invalidation": ">=0.7.0"
38
38
  },
39
39
  "devDependencies": {
40
- "@spoosh/core": "0.13.1",
41
- "@spoosh/plugin-invalidation": "0.7.0",
42
- "@spoosh/test-utils": "0.2.0"
40
+ "@spoosh/core": "0.15.0",
41
+ "@spoosh/plugin-invalidation": "0.9.0",
42
+ "@spoosh/test-utils": "0.3.0"
43
43
  },
44
44
  "scripts": {
45
45
  "dev": "tsup --watch",