@spoosh/plugin-optimistic 0.6.0 → 0.6.1
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 +6 -8
- package/dist/index.d.ts +6 -8
- package/dist/index.js +142 -34
- package/dist/index.mjs +142 -34
- package/package.json +3 -3
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
|
|
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.
|
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
|
|
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.
|
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
|
|
62
|
-
|
|
63
|
-
return (0, import_core.generateTags)(pathSegments);
|
|
60
|
+
function isParameterSegment(segment) {
|
|
61
|
+
return segment.startsWith(":");
|
|
64
62
|
}
|
|
65
|
-
function
|
|
66
|
-
|
|
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,72 @@ 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('"type":"infinite-tracker"')) continue;
|
|
151
|
+
if (!key.includes(`"method":"${targetMethod}"`)) continue;
|
|
152
|
+
const actualPath = extractPathFromKey(key);
|
|
153
|
+
if (!actualPath) continue;
|
|
154
|
+
const { matches, params, paramMapping } = pathMatchesPattern(
|
|
155
|
+
actualPath,
|
|
156
|
+
targetPath
|
|
157
|
+
);
|
|
158
|
+
if (matches) {
|
|
159
|
+
results.push({ key, entry, extractedParams: params, paramMapping });
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
} else {
|
|
163
|
+
const allEntries = stateManager.getAllCacheEntries();
|
|
164
|
+
for (const { key, entry } of allEntries) {
|
|
165
|
+
if (key.includes('"type":"infinite-tracker"')) continue;
|
|
166
|
+
if (!key.includes(`"method":"${targetMethod}"`)) continue;
|
|
167
|
+
const actualPath = extractPathFromKey(key);
|
|
168
|
+
if (!actualPath) continue;
|
|
169
|
+
if (actualPath === targetPath) {
|
|
170
|
+
results.push({ key, entry, extractedParams: {}, paramMapping: {} });
|
|
171
|
+
} else if (hasPatternParams(actualPath)) {
|
|
172
|
+
const { matches, params, paramMapping } = pathMatchesPattern(
|
|
173
|
+
targetPath,
|
|
174
|
+
actualPath
|
|
175
|
+
);
|
|
176
|
+
if (matches) {
|
|
177
|
+
results.push({ key, entry, extractedParams: params, paramMapping });
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
return results;
|
|
183
|
+
}
|
|
93
184
|
function applyOptimisticUpdate(stateManager, target, t) {
|
|
94
185
|
if (!target.updater) return [];
|
|
95
|
-
const tags = extractTagsFromPath(target.path);
|
|
96
|
-
const targetSelfTag = getExactMatchPath(tags);
|
|
97
|
-
if (!targetSelfTag) return [];
|
|
98
186
|
const snapshots = [];
|
|
99
|
-
const
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
continue;
|
|
106
|
-
}
|
|
187
|
+
const matchingEntries = getMatchingEntries(
|
|
188
|
+
stateManager,
|
|
189
|
+
target.path,
|
|
190
|
+
target.method
|
|
191
|
+
);
|
|
192
|
+
for (const { key, entry, extractedParams, paramMapping } of matchingEntries) {
|
|
107
193
|
if (target.where) {
|
|
108
|
-
const options = extractOptionsFromKey(key);
|
|
109
|
-
|
|
194
|
+
const options = extractOptionsFromKey(key) ?? {};
|
|
195
|
+
const mappedParams = mapParamsToTargetNames(
|
|
196
|
+
options.params,
|
|
197
|
+
paramMapping
|
|
198
|
+
);
|
|
199
|
+
const mergedOptions = {
|
|
200
|
+
...options,
|
|
201
|
+
params: {
|
|
202
|
+
...extractedParams,
|
|
203
|
+
...mappedParams
|
|
204
|
+
}
|
|
205
|
+
};
|
|
206
|
+
if (!target.where(mergedOptions)) {
|
|
110
207
|
continue;
|
|
111
208
|
}
|
|
112
209
|
}
|
|
113
|
-
if (entry
|
|
210
|
+
if (entry?.state.data === void 0) {
|
|
114
211
|
continue;
|
|
115
212
|
}
|
|
116
213
|
const afterData = target.updater(entry.state.data, void 0);
|
|
@@ -233,24 +330,35 @@ function optimisticPlugin() {
|
|
|
233
330
|
const onSuccessSnapshots = [];
|
|
234
331
|
for (const target of onSuccessTargets) {
|
|
235
332
|
if (!target.updater) continue;
|
|
236
|
-
const
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
333
|
+
const matchingEntries = getMatchingEntries(
|
|
334
|
+
stateManager,
|
|
335
|
+
target.path,
|
|
336
|
+
target.method
|
|
337
|
+
);
|
|
338
|
+
for (const {
|
|
339
|
+
key,
|
|
340
|
+
entry,
|
|
341
|
+
extractedParams,
|
|
342
|
+
paramMapping
|
|
343
|
+
} of matchingEntries) {
|
|
247
344
|
if (target.where) {
|
|
248
|
-
const options = extractOptionsFromKey(key);
|
|
249
|
-
|
|
345
|
+
const options = extractOptionsFromKey(key) ?? {};
|
|
346
|
+
const mappedParams = mapParamsToTargetNames(
|
|
347
|
+
options.params,
|
|
348
|
+
paramMapping
|
|
349
|
+
);
|
|
350
|
+
const mergedOptions = {
|
|
351
|
+
...options,
|
|
352
|
+
params: {
|
|
353
|
+
...extractedParams,
|
|
354
|
+
...mappedParams
|
|
355
|
+
}
|
|
356
|
+
};
|
|
357
|
+
if (!target.where(mergedOptions)) {
|
|
250
358
|
continue;
|
|
251
359
|
}
|
|
252
360
|
}
|
|
253
|
-
if (entry
|
|
361
|
+
if (entry?.state.data === void 0) {
|
|
254
362
|
continue;
|
|
255
363
|
}
|
|
256
364
|
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
|
|
36
|
-
|
|
37
|
-
return generateTags(pathSegments);
|
|
34
|
+
function isParameterSegment(segment) {
|
|
35
|
+
return segment.startsWith(":");
|
|
38
36
|
}
|
|
39
|
-
function
|
|
40
|
-
|
|
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,72 @@ 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('"type":"infinite-tracker"')) continue;
|
|
125
|
+
if (!key.includes(`"method":"${targetMethod}"`)) continue;
|
|
126
|
+
const actualPath = extractPathFromKey(key);
|
|
127
|
+
if (!actualPath) continue;
|
|
128
|
+
const { matches, params, paramMapping } = pathMatchesPattern(
|
|
129
|
+
actualPath,
|
|
130
|
+
targetPath
|
|
131
|
+
);
|
|
132
|
+
if (matches) {
|
|
133
|
+
results.push({ key, entry, extractedParams: params, paramMapping });
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
} else {
|
|
137
|
+
const allEntries = stateManager.getAllCacheEntries();
|
|
138
|
+
for (const { key, entry } of allEntries) {
|
|
139
|
+
if (key.includes('"type":"infinite-tracker"')) continue;
|
|
140
|
+
if (!key.includes(`"method":"${targetMethod}"`)) continue;
|
|
141
|
+
const actualPath = extractPathFromKey(key);
|
|
142
|
+
if (!actualPath) continue;
|
|
143
|
+
if (actualPath === targetPath) {
|
|
144
|
+
results.push({ key, entry, extractedParams: {}, paramMapping: {} });
|
|
145
|
+
} else if (hasPatternParams(actualPath)) {
|
|
146
|
+
const { matches, params, paramMapping } = pathMatchesPattern(
|
|
147
|
+
targetPath,
|
|
148
|
+
actualPath
|
|
149
|
+
);
|
|
150
|
+
if (matches) {
|
|
151
|
+
results.push({ key, entry, extractedParams: params, paramMapping });
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
return results;
|
|
157
|
+
}
|
|
67
158
|
function applyOptimisticUpdate(stateManager, target, t) {
|
|
68
159
|
if (!target.updater) return [];
|
|
69
|
-
const tags = extractTagsFromPath(target.path);
|
|
70
|
-
const targetSelfTag = getExactMatchPath(tags);
|
|
71
|
-
if (!targetSelfTag) return [];
|
|
72
160
|
const snapshots = [];
|
|
73
|
-
const
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
continue;
|
|
80
|
-
}
|
|
161
|
+
const matchingEntries = getMatchingEntries(
|
|
162
|
+
stateManager,
|
|
163
|
+
target.path,
|
|
164
|
+
target.method
|
|
165
|
+
);
|
|
166
|
+
for (const { key, entry, extractedParams, paramMapping } of matchingEntries) {
|
|
81
167
|
if (target.where) {
|
|
82
|
-
const options = extractOptionsFromKey(key);
|
|
83
|
-
|
|
168
|
+
const options = extractOptionsFromKey(key) ?? {};
|
|
169
|
+
const mappedParams = mapParamsToTargetNames(
|
|
170
|
+
options.params,
|
|
171
|
+
paramMapping
|
|
172
|
+
);
|
|
173
|
+
const mergedOptions = {
|
|
174
|
+
...options,
|
|
175
|
+
params: {
|
|
176
|
+
...extractedParams,
|
|
177
|
+
...mappedParams
|
|
178
|
+
}
|
|
179
|
+
};
|
|
180
|
+
if (!target.where(mergedOptions)) {
|
|
84
181
|
continue;
|
|
85
182
|
}
|
|
86
183
|
}
|
|
87
|
-
if (entry
|
|
184
|
+
if (entry?.state.data === void 0) {
|
|
88
185
|
continue;
|
|
89
186
|
}
|
|
90
187
|
const afterData = target.updater(entry.state.data, void 0);
|
|
@@ -207,24 +304,35 @@ function optimisticPlugin() {
|
|
|
207
304
|
const onSuccessSnapshots = [];
|
|
208
305
|
for (const target of onSuccessTargets) {
|
|
209
306
|
if (!target.updater) continue;
|
|
210
|
-
const
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
307
|
+
const matchingEntries = getMatchingEntries(
|
|
308
|
+
stateManager,
|
|
309
|
+
target.path,
|
|
310
|
+
target.method
|
|
311
|
+
);
|
|
312
|
+
for (const {
|
|
313
|
+
key,
|
|
314
|
+
entry,
|
|
315
|
+
extractedParams,
|
|
316
|
+
paramMapping
|
|
317
|
+
} of matchingEntries) {
|
|
221
318
|
if (target.where) {
|
|
222
|
-
const options = extractOptionsFromKey(key);
|
|
223
|
-
|
|
319
|
+
const options = extractOptionsFromKey(key) ?? {};
|
|
320
|
+
const mappedParams = mapParamsToTargetNames(
|
|
321
|
+
options.params,
|
|
322
|
+
paramMapping
|
|
323
|
+
);
|
|
324
|
+
const mergedOptions = {
|
|
325
|
+
...options,
|
|
326
|
+
params: {
|
|
327
|
+
...extractedParams,
|
|
328
|
+
...mappedParams
|
|
329
|
+
}
|
|
330
|
+
};
|
|
331
|
+
if (!target.where(mergedOptions)) {
|
|
224
332
|
continue;
|
|
225
333
|
}
|
|
226
334
|
}
|
|
227
|
-
if (entry
|
|
335
|
+
if (entry?.state.data === void 0) {
|
|
228
336
|
continue;
|
|
229
337
|
}
|
|
230
338
|
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.
|
|
3
|
+
"version": "0.6.1",
|
|
4
4
|
"description": "Optimistic updates plugin for Spoosh - instant UI updates with automatic rollback",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -37,8 +37,8 @@
|
|
|
37
37
|
"@spoosh/plugin-invalidation": ">=0.7.0"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
|
-
"@spoosh/core": "0.
|
|
41
|
-
"@spoosh/plugin-invalidation": "0.
|
|
40
|
+
"@spoosh/core": "0.14.1",
|
|
41
|
+
"@spoosh/plugin-invalidation": "0.8.0",
|
|
42
42
|
"@spoosh/test-utils": "0.2.0"
|
|
43
43
|
},
|
|
44
44
|
"scripts": {
|