@spoosh/plugin-optimistic 0.7.2 → 0.8.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/README.md +40 -39
- package/dist/index.d.mts +103 -103
- package/dist/index.d.ts +103 -103
- package/dist/index.js +162 -225
- package/dist/index.mjs +160 -223
- package/package.json +4 -4
package/dist/index.mjs
CHANGED
|
@@ -3,82 +3,58 @@ import {
|
|
|
3
3
|
createSpooshPlugin
|
|
4
4
|
} from "@spoosh/core";
|
|
5
5
|
import "@spoosh/plugin-invalidation";
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
...state,
|
|
9
|
-
WHERE(predicate) {
|
|
10
|
-
return createBuilder({ ...state, where: predicate });
|
|
11
|
-
},
|
|
12
|
-
UPDATE_CACHE(updater) {
|
|
13
|
-
return createBuilder({ ...state, updater });
|
|
14
|
-
},
|
|
15
|
-
ON_SUCCESS() {
|
|
16
|
-
return createBuilder({ ...state, timing: "onSuccess" });
|
|
17
|
-
},
|
|
18
|
-
NO_ROLLBACK() {
|
|
19
|
-
return createBuilder({ ...state, rollbackOnError: false });
|
|
20
|
-
},
|
|
21
|
-
ON_ERROR(callback) {
|
|
22
|
-
return createBuilder({ ...state, onError: callback });
|
|
23
|
-
}
|
|
24
|
-
};
|
|
25
|
-
}
|
|
26
|
-
function createOptimisticProxy() {
|
|
27
|
-
const createMethodsProxy = (path) => ({
|
|
28
|
-
GET: () => createBuilder({
|
|
29
|
-
path,
|
|
30
|
-
method: "GET",
|
|
31
|
-
timing: "immediate",
|
|
32
|
-
rollbackOnError: true
|
|
33
|
-
})
|
|
34
|
-
});
|
|
35
|
-
return ((path) => createMethodsProxy(path));
|
|
36
|
-
}
|
|
6
|
+
|
|
7
|
+
// src/utils/path.ts
|
|
37
8
|
function isParameterSegment(segment) {
|
|
38
9
|
return segment.startsWith(":");
|
|
39
10
|
}
|
|
40
|
-
function pathMatchesPattern(
|
|
41
|
-
const
|
|
11
|
+
function pathMatchesPattern(resolvedPath, pattern) {
|
|
12
|
+
const resolvedSegments = resolvedPath.split("/").filter(Boolean);
|
|
42
13
|
const patternSegments = pattern.split("/").filter(Boolean);
|
|
43
|
-
if (
|
|
44
|
-
return { matches: false, params: {}
|
|
14
|
+
if (resolvedSegments.length !== patternSegments.length) {
|
|
15
|
+
return { matches: false, params: {} };
|
|
45
16
|
}
|
|
46
17
|
const params = {};
|
|
47
|
-
const paramMapping = {};
|
|
48
18
|
for (let i = 0; i < patternSegments.length; i++) {
|
|
49
19
|
const patternSeg = patternSegments[i];
|
|
50
|
-
const
|
|
20
|
+
const resolvedSeg = resolvedSegments[i];
|
|
51
21
|
if (isParameterSegment(patternSeg)) {
|
|
52
|
-
const
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
continue;
|
|
57
|
-
}
|
|
58
|
-
params[targetParamName] = actualSeg;
|
|
59
|
-
} else if (isParameterSegment(actualSeg)) {
|
|
60
|
-
continue;
|
|
61
|
-
} else if (patternSeg !== actualSeg) {
|
|
62
|
-
return { matches: false, params: {}, paramMapping: {} };
|
|
22
|
+
const paramName = patternSeg.slice(1);
|
|
23
|
+
params[paramName] = resolvedSeg;
|
|
24
|
+
} else if (patternSeg !== resolvedSeg) {
|
|
25
|
+
return { matches: false, params: {} };
|
|
63
26
|
}
|
|
64
27
|
}
|
|
65
|
-
return { matches: true, params
|
|
66
|
-
}
|
|
67
|
-
function hasPatternParams(path) {
|
|
68
|
-
return path.split("/").some(isParameterSegment);
|
|
28
|
+
return { matches: true, params };
|
|
69
29
|
}
|
|
70
|
-
|
|
30
|
+
|
|
31
|
+
// src/utils/cache-key.ts
|
|
32
|
+
import { generateSelfTagFromKey } from "@spoosh/core";
|
|
33
|
+
function formatCacheKeyForTrace(key) {
|
|
34
|
+
const resolvedPath = generateSelfTagFromKey(key);
|
|
35
|
+
if (!resolvedPath) return "unknown";
|
|
71
36
|
try {
|
|
72
37
|
const parsed = JSON.parse(key);
|
|
73
|
-
const
|
|
74
|
-
|
|
75
|
-
|
|
38
|
+
const opts = parsed.options ?? parsed.pageRequest;
|
|
39
|
+
const query = opts?.query;
|
|
40
|
+
if (!query || Object.keys(query).length === 0) {
|
|
41
|
+
return resolvedPath;
|
|
76
42
|
}
|
|
77
|
-
|
|
43
|
+
const queryString = Object.entries(query).map(
|
|
44
|
+
([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(String(v))}`
|
|
45
|
+
).join("&");
|
|
46
|
+
return `${resolvedPath}?${queryString}`;
|
|
78
47
|
} catch {
|
|
79
|
-
return
|
|
48
|
+
return resolvedPath;
|
|
80
49
|
}
|
|
81
50
|
}
|
|
51
|
+
function stringifyParams(params) {
|
|
52
|
+
const result = {};
|
|
53
|
+
for (const [key, value] of Object.entries(params)) {
|
|
54
|
+
result[key] = String(value);
|
|
55
|
+
}
|
|
56
|
+
return result;
|
|
57
|
+
}
|
|
82
58
|
function extractOptionsFromKey(key) {
|
|
83
59
|
try {
|
|
84
60
|
const parsed = JSON.parse(key);
|
|
@@ -89,103 +65,117 @@ function extractOptionsFromKey(key) {
|
|
|
89
65
|
result.query = opts.query;
|
|
90
66
|
}
|
|
91
67
|
if (opts.params) {
|
|
92
|
-
result.params = opts.params;
|
|
68
|
+
result.params = stringifyParams(opts.params);
|
|
93
69
|
}
|
|
94
70
|
return Object.keys(result).length > 0 ? result : null;
|
|
95
71
|
} catch {
|
|
96
72
|
return null;
|
|
97
73
|
}
|
|
98
74
|
}
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
75
|
+
|
|
76
|
+
// src/plugin.ts
|
|
77
|
+
import { generateSelfTagFromKey as generateSelfTagFromKey2 } from "@spoosh/core";
|
|
78
|
+
|
|
79
|
+
// src/builder/index.ts
|
|
80
|
+
function createBuilder(state, isConfirmed = false) {
|
|
81
|
+
return {
|
|
82
|
+
...state,
|
|
83
|
+
filter(predicate) {
|
|
84
|
+
return createBuilder({ ...state, filter: predicate }, isConfirmed);
|
|
85
|
+
},
|
|
86
|
+
set(updater) {
|
|
87
|
+
if (isConfirmed) {
|
|
88
|
+
return createBuilder(
|
|
89
|
+
{
|
|
90
|
+
...state,
|
|
91
|
+
confirmedUpdater: updater
|
|
92
|
+
},
|
|
93
|
+
isConfirmed
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
return createBuilder(
|
|
97
|
+
{
|
|
98
|
+
...state,
|
|
99
|
+
immediateUpdater: updater
|
|
100
|
+
},
|
|
101
|
+
isConfirmed
|
|
102
|
+
);
|
|
103
|
+
},
|
|
104
|
+
confirmed() {
|
|
105
|
+
return createBuilder(state, true);
|
|
106
|
+
},
|
|
107
|
+
disableRollback() {
|
|
108
|
+
return createBuilder({ ...state, rollbackOnError: false }, isConfirmed);
|
|
109
|
+
},
|
|
110
|
+
onError(callback) {
|
|
111
|
+
return createBuilder({ ...state, onError: callback }, isConfirmed);
|
|
110
112
|
}
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
function createCacheProxy() {
|
|
116
|
+
return ((path) => createBuilder({
|
|
117
|
+
path,
|
|
118
|
+
rollbackOnError: true
|
|
119
|
+
}));
|
|
113
120
|
}
|
|
121
|
+
|
|
122
|
+
// src/plugin.ts
|
|
114
123
|
function resolveOptimisticTargets(context) {
|
|
115
124
|
const pluginOptions = context.pluginOptions;
|
|
116
125
|
if (!pluginOptions?.optimistic) return [];
|
|
117
|
-
const
|
|
118
|
-
const result = pluginOptions.optimistic(
|
|
126
|
+
const cacheProxy = createCacheProxy();
|
|
127
|
+
const result = pluginOptions.optimistic(cacheProxy);
|
|
119
128
|
const targets = Array.isArray(result) ? result : [result];
|
|
120
129
|
return targets;
|
|
121
130
|
}
|
|
122
|
-
function getMatchingEntries(stateManager, targetPath
|
|
131
|
+
function getMatchingEntries(stateManager, targetPath) {
|
|
123
132
|
const results = [];
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
targetPath
|
|
133
|
-
);
|
|
134
|
-
if (matches) {
|
|
135
|
-
results.push({ key, entry, extractedParams: params, paramMapping });
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
} else {
|
|
139
|
-
const allEntries = stateManager.getAllCacheEntries();
|
|
140
|
-
for (const { key, entry } of allEntries) {
|
|
141
|
-
if (!key.includes(`"method":"${targetMethod}"`)) continue;
|
|
142
|
-
const actualPath = extractPathFromKey(key);
|
|
143
|
-
if (!actualPath) continue;
|
|
144
|
-
if (actualPath === targetPath) {
|
|
145
|
-
results.push({ key, entry, extractedParams: {}, paramMapping: {} });
|
|
146
|
-
} else if (hasPatternParams(actualPath)) {
|
|
147
|
-
const { matches, params, paramMapping } = pathMatchesPattern(
|
|
148
|
-
targetPath,
|
|
149
|
-
actualPath
|
|
150
|
-
);
|
|
151
|
-
if (matches) {
|
|
152
|
-
results.push({ key, entry, extractedParams: params, paramMapping });
|
|
153
|
-
}
|
|
154
|
-
}
|
|
133
|
+
const allEntries = stateManager.getAllCacheEntries();
|
|
134
|
+
for (const { key, entry } of allEntries) {
|
|
135
|
+
if (!key.includes(`"method":"GET"`)) continue;
|
|
136
|
+
const resolvedPath = generateSelfTagFromKey2(key);
|
|
137
|
+
if (!resolvedPath) continue;
|
|
138
|
+
const { matches, params } = pathMatchesPattern(resolvedPath, targetPath);
|
|
139
|
+
if (matches) {
|
|
140
|
+
results.push({ key, entry, extractedParams: params });
|
|
155
141
|
}
|
|
156
142
|
}
|
|
157
143
|
return results;
|
|
158
144
|
}
|
|
159
|
-
function
|
|
160
|
-
if (!target.updater) return [];
|
|
145
|
+
function applyUpdate(stateManager, target, updater, response, t) {
|
|
161
146
|
const snapshots = [];
|
|
162
|
-
const matchingEntries = getMatchingEntries(
|
|
163
|
-
|
|
164
|
-
target.path
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
for (const { key, entry, extractedParams
|
|
168
|
-
if (target.
|
|
147
|
+
const matchingEntries = getMatchingEntries(stateManager, target.path);
|
|
148
|
+
if (matchingEntries.length === 0) {
|
|
149
|
+
t?.skip(`Skipped ${target.path} (no cache entry)`);
|
|
150
|
+
return [];
|
|
151
|
+
}
|
|
152
|
+
for (const { key, entry, extractedParams } of matchingEntries) {
|
|
153
|
+
if (target.filter) {
|
|
169
154
|
const options = extractOptionsFromKey(key) ?? {};
|
|
170
|
-
const mappedParams = mapParamsToTargetNames(
|
|
171
|
-
options.params,
|
|
172
|
-
paramMapping
|
|
173
|
-
);
|
|
174
155
|
const mergedOptions = {
|
|
175
156
|
...options,
|
|
176
157
|
params: {
|
|
177
|
-
...
|
|
178
|
-
...
|
|
158
|
+
...options.params,
|
|
159
|
+
...extractedParams
|
|
179
160
|
}
|
|
180
161
|
};
|
|
181
|
-
|
|
162
|
+
try {
|
|
163
|
+
if (!target.filter(mergedOptions)) {
|
|
164
|
+
t?.skip(
|
|
165
|
+
`Skipped ${formatCacheKeyForTrace(key)} (filter not matched)`
|
|
166
|
+
);
|
|
167
|
+
continue;
|
|
168
|
+
}
|
|
169
|
+
} catch {
|
|
170
|
+
t?.skip(`Skipped ${formatCacheKeyForTrace(key)} (filter error)`);
|
|
182
171
|
continue;
|
|
183
172
|
}
|
|
184
173
|
}
|
|
185
174
|
if (entry?.state.data === void 0) {
|
|
175
|
+
t?.skip(`Skipped ${formatCacheKeyForTrace(key)} (no cached data)`);
|
|
186
176
|
continue;
|
|
187
177
|
}
|
|
188
|
-
const afterData =
|
|
178
|
+
const afterData = updater(entry.state.data, response);
|
|
189
179
|
snapshots.push({ key, previousData: entry.state.data, afterData });
|
|
190
180
|
stateManager.setCache(key, {
|
|
191
181
|
previousData: entry.state.data,
|
|
@@ -195,14 +185,10 @@ function applyOptimisticUpdate(stateManager, target, t) {
|
|
|
195
185
|
}
|
|
196
186
|
});
|
|
197
187
|
stateManager.setMeta(key, { isOptimistic: true });
|
|
198
|
-
t?.log("Marked as optimistic", {
|
|
199
|
-
color: "info",
|
|
200
|
-
info: [{ value: { isOptimistic: true } }]
|
|
201
|
-
});
|
|
202
188
|
}
|
|
203
189
|
return snapshots;
|
|
204
190
|
}
|
|
205
|
-
function confirmOptimistic(stateManager, snapshots
|
|
191
|
+
function confirmOptimistic(stateManager, snapshots) {
|
|
206
192
|
for (const { key } of snapshots) {
|
|
207
193
|
const entry = stateManager.getCache(key);
|
|
208
194
|
if (entry) {
|
|
@@ -210,14 +196,10 @@ function confirmOptimistic(stateManager, snapshots, t) {
|
|
|
210
196
|
previousData: void 0
|
|
211
197
|
});
|
|
212
198
|
stateManager.setMeta(key, { isOptimistic: false });
|
|
213
|
-
t?.log("Optimistic confirmed", {
|
|
214
|
-
color: "success",
|
|
215
|
-
info: [{ value: { isOptimistic: false } }]
|
|
216
|
-
});
|
|
217
199
|
}
|
|
218
200
|
}
|
|
219
201
|
}
|
|
220
|
-
function rollbackOptimistic(stateManager, snapshots
|
|
202
|
+
function rollbackOptimistic(stateManager, snapshots) {
|
|
221
203
|
for (const { key, previousData } of snapshots) {
|
|
222
204
|
const entry = stateManager.getCache(key);
|
|
223
205
|
if (entry) {
|
|
@@ -229,28 +211,12 @@ function rollbackOptimistic(stateManager, snapshots, t) {
|
|
|
229
211
|
}
|
|
230
212
|
});
|
|
231
213
|
stateManager.setMeta(key, { isOptimistic: false });
|
|
232
|
-
t?.log("Optimistic rolled back", {
|
|
233
|
-
color: "warning",
|
|
234
|
-
info: [{ value: { isOptimistic: false } }]
|
|
235
|
-
});
|
|
236
214
|
}
|
|
237
215
|
}
|
|
238
216
|
}
|
|
239
|
-
function
|
|
240
|
-
const
|
|
241
|
-
|
|
242
|
-
if (snapshots.length === 1) {
|
|
243
|
-
return mode === "apply" || mode === "onSuccess" ? { before: first.previousData, after: first.afterData, label } : { before: first.afterData, after: first.previousData, label };
|
|
244
|
-
}
|
|
245
|
-
return mode === "apply" || mode === "onSuccess" ? {
|
|
246
|
-
before: snapshots.map((s) => ({ key: s.key, data: s.previousData })),
|
|
247
|
-
after: snapshots.map((s) => ({ key: s.key, data: s.afterData })),
|
|
248
|
-
label
|
|
249
|
-
} : {
|
|
250
|
-
before: snapshots.map((s) => ({ key: s.key, data: s.afterData })),
|
|
251
|
-
after: snapshots.map((s) => ({ key: s.key, data: s.previousData })),
|
|
252
|
-
label
|
|
253
|
-
};
|
|
217
|
+
function buildSingleDiff(snapshot, mode = "apply") {
|
|
218
|
+
const label = mode === "apply" ? "Optimistic update" : mode === "rollback" ? "Rollback optimistic" : "Confirmed update";
|
|
219
|
+
return mode === "apply" || mode === "confirmed" ? { before: snapshot.previousData, after: snapshot.afterData, label } : { before: snapshot.afterData, after: snapshot.previousData, label };
|
|
254
220
|
}
|
|
255
221
|
var PLUGIN_NAME = "spoosh:optimistic";
|
|
256
222
|
function optimisticPlugin() {
|
|
@@ -267,28 +233,37 @@ function optimisticPlugin() {
|
|
|
267
233
|
return next();
|
|
268
234
|
}
|
|
269
235
|
context.plugins.get("spoosh:invalidation")?.setDefaultMode("none");
|
|
270
|
-
const
|
|
271
|
-
const
|
|
272
|
-
|
|
273
|
-
const snapshots =
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
236
|
+
const allImmediateSnapshots = [];
|
|
237
|
+
for (const target of targets) {
|
|
238
|
+
if (!target.immediateUpdater) continue;
|
|
239
|
+
const snapshots = applyUpdate(
|
|
240
|
+
stateManager,
|
|
241
|
+
target,
|
|
242
|
+
target.immediateUpdater,
|
|
243
|
+
void 0,
|
|
244
|
+
t
|
|
245
|
+
);
|
|
246
|
+
for (const snapshot of snapshots) {
|
|
247
|
+
t?.log(
|
|
248
|
+
`Applied optimistic update to ${formatCacheKeyForTrace(snapshot.key)}`,
|
|
249
|
+
{ diff: buildSingleDiff(snapshot) }
|
|
250
|
+
);
|
|
251
|
+
}
|
|
252
|
+
allImmediateSnapshots.push(...snapshots);
|
|
280
253
|
}
|
|
281
254
|
const response = await next();
|
|
282
255
|
if (response.error) {
|
|
283
256
|
const shouldRollback = targets.some(
|
|
284
|
-
(
|
|
257
|
+
(target) => target.rollbackOnError && target.immediateUpdater
|
|
285
258
|
);
|
|
286
|
-
if (shouldRollback &&
|
|
287
|
-
rollbackOptimistic(stateManager,
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
259
|
+
if (shouldRollback && allImmediateSnapshots.length > 0) {
|
|
260
|
+
rollbackOptimistic(stateManager, allImmediateSnapshots);
|
|
261
|
+
for (const snapshot of allImmediateSnapshots) {
|
|
262
|
+
t?.log(`Rolled back ${formatCacheKeyForTrace(snapshot.key)}`, {
|
|
263
|
+
color: "warning",
|
|
264
|
+
diff: buildSingleDiff(snapshot, "rollback")
|
|
265
|
+
});
|
|
266
|
+
}
|
|
292
267
|
}
|
|
293
268
|
for (const target of targets) {
|
|
294
269
|
if (target.onError) {
|
|
@@ -296,66 +271,28 @@ function optimisticPlugin() {
|
|
|
296
271
|
}
|
|
297
272
|
}
|
|
298
273
|
} else {
|
|
299
|
-
if (
|
|
300
|
-
confirmOptimistic(stateManager,
|
|
274
|
+
if (allImmediateSnapshots.length > 0) {
|
|
275
|
+
confirmOptimistic(stateManager, allImmediateSnapshots);
|
|
301
276
|
}
|
|
302
|
-
const
|
|
303
|
-
(target)
|
|
304
|
-
|
|
305
|
-
const onSuccessSnapshots = [];
|
|
306
|
-
for (const target of onSuccessTargets) {
|
|
307
|
-
if (!target.updater) continue;
|
|
308
|
-
const matchingEntries = getMatchingEntries(
|
|
277
|
+
for (const target of targets) {
|
|
278
|
+
if (!target.confirmedUpdater) continue;
|
|
279
|
+
const snapshots = applyUpdate(
|
|
309
280
|
stateManager,
|
|
310
|
-
target
|
|
311
|
-
target.
|
|
281
|
+
target,
|
|
282
|
+
target.confirmedUpdater,
|
|
283
|
+
response.data,
|
|
284
|
+
t
|
|
312
285
|
);
|
|
313
|
-
for (const {
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
if (target.where) {
|
|
320
|
-
const options = extractOptionsFromKey(key) ?? {};
|
|
321
|
-
const mappedParams = mapParamsToTargetNames(
|
|
322
|
-
options.params,
|
|
323
|
-
paramMapping
|
|
324
|
-
);
|
|
325
|
-
const mergedOptions = {
|
|
326
|
-
...options,
|
|
327
|
-
params: {
|
|
328
|
-
...extractedParams,
|
|
329
|
-
...mappedParams
|
|
330
|
-
}
|
|
331
|
-
};
|
|
332
|
-
if (!target.where(mergedOptions)) {
|
|
333
|
-
continue;
|
|
286
|
+
for (const snapshot of snapshots) {
|
|
287
|
+
t?.log(
|
|
288
|
+
`Applied confirmed update to ${formatCacheKeyForTrace(snapshot.key)}`,
|
|
289
|
+
{
|
|
290
|
+
color: "success",
|
|
291
|
+
diff: buildSingleDiff(snapshot, "confirmed")
|
|
334
292
|
}
|
|
335
|
-
|
|
336
|
-
if (entry?.state.data === void 0) {
|
|
337
|
-
continue;
|
|
338
|
-
}
|
|
339
|
-
const afterData = target.updater(entry.state.data, response.data);
|
|
340
|
-
onSuccessSnapshots.push({
|
|
341
|
-
key,
|
|
342
|
-
previousData: entry.state.data,
|
|
343
|
-
afterData
|
|
344
|
-
});
|
|
345
|
-
stateManager.setCache(key, {
|
|
346
|
-
state: {
|
|
347
|
-
...entry.state,
|
|
348
|
-
data: afterData
|
|
349
|
-
}
|
|
350
|
-
});
|
|
293
|
+
);
|
|
351
294
|
}
|
|
352
295
|
}
|
|
353
|
-
if (onSuccessSnapshots.length > 0) {
|
|
354
|
-
t?.log(`Applied ${onSuccessSnapshots.length} onSuccess update(s)`, {
|
|
355
|
-
color: "success",
|
|
356
|
-
diff: buildSnapshotDiff(onSuccessSnapshots, "onSuccess")
|
|
357
|
-
});
|
|
358
|
-
}
|
|
359
296
|
}
|
|
360
297
|
return response;
|
|
361
298
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@spoosh/plugin-optimistic",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.1",
|
|
4
4
|
"description": "Optimistic updates plugin for Spoosh - instant UI updates with automatic rollback",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -33,12 +33,12 @@
|
|
|
33
33
|
}
|
|
34
34
|
},
|
|
35
35
|
"peerDependencies": {
|
|
36
|
-
"@spoosh/core": ">=0.
|
|
36
|
+
"@spoosh/core": ">=0.17.0",
|
|
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.17.1",
|
|
41
|
+
"@spoosh/plugin-invalidation": "0.10.0",
|
|
42
42
|
"@spoosh/test-utils": "0.3.0"
|
|
43
43
|
},
|
|
44
44
|
"scripts": {
|