zova-module-a-model 5.1.37 → 5.1.39
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/.metadata/index.d.ts +7 -7
- package/dist/.metadata/index.d.ts.map +1 -1
- package/dist/.metadata/this.d.ts +1 -1
- package/dist/bean/bean.model/bean.model.cookie.d.ts +2 -2
- package/dist/bean/bean.model/bean.model.first.d.ts +1 -1
- package/dist/bean/bean.model/bean.model.last.d.ts +3 -3
- package/dist/bean/bean.model/bean.model.local.d.ts +1 -1
- package/dist/bean/bean.model/bean.model.persister.d.ts +15 -6
- package/dist/bean/bean.model/bean.model.persister.d.ts.map +1 -1
- package/dist/bean/bean.model/bean.model.query.d.ts +2 -2
- package/dist/bean/bean.model/bean.model.query.d.ts.map +1 -1
- package/dist/bean/bean.model/bean.model.useMutation.d.ts +2 -2
- package/dist/bean/bean.model/bean.model.useQuery.d.ts +3 -3
- package/dist/bean/bean.model/bean.model.useQuery.d.ts.map +1 -1
- package/dist/bean/bean.model/bean.model.useState.d.ts +3 -3
- package/dist/bean/bean.model/bean.model.useState.d.ts.map +1 -1
- package/dist/bean/bean.model/bean.model.useStateGeneral.d.ts +3 -3
- package/dist/bean/bean.modelBase.d.ts +1 -1
- package/dist/common/cookieWrapper.d.ts +1 -1
- package/dist/config/config.d.ts +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.js +501 -68
- package/dist/index.js.map +1 -1
- package/dist/lib/index.d.ts +3 -2
- package/dist/lib/index.d.ts.map +1 -1
- package/dist/lib/model.d.ts +1 -1
- package/dist/lib/modelPersistence.d.ts +39 -0
- package/dist/lib/modelPersistence.d.ts.map +1 -0
- package/dist/lib/persistenceQueue.d.ts +14 -0
- package/dist/lib/persistenceQueue.d.ts.map +1 -0
- package/dist/lib/queryRefetch.d.ts +1 -1
- package/dist/lib/utils.d.ts +1 -1
- package/dist/monkey.d.ts.map +1 -1
- package/dist/service/storage.d.ts +15 -0
- package/dist/service/storage.d.ts.map +1 -1
- package/dist/types/index.d.ts +2 -2
- package/dist/types/query.d.ts +2 -0
- package/dist/types/query.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/.metadata/index.ts +7 -7
- package/src/.metadata/this.ts +1 -1
- package/src/bean/bean.model/bean.model.cookie.ts +2 -2
- package/src/bean/bean.model/bean.model.first.ts +1 -1
- package/src/bean/bean.model/bean.model.last.ts +4 -4
- package/src/bean/bean.model/bean.model.local.ts +1 -1
- package/src/bean/bean.model/bean.model.persister.ts +336 -92
- package/src/bean/bean.model/bean.model.query.ts +13 -8
- package/src/bean/bean.model/bean.model.useMutation.ts +2 -2
- package/src/bean/bean.model/bean.model.useQuery.ts +8 -6
- package/src/bean/bean.model/bean.model.useState.ts +20 -4
- package/src/bean/bean.model/bean.model.useStateGeneral.ts +4 -4
- package/src/bean/bean.modelBase.ts +1 -1
- package/src/common/cookieWrapper.ts +3 -3
- package/src/config/config.ts +1 -1
- package/src/index.ts +3 -3
- package/src/lib/index.ts +3 -2
- package/src/lib/model.ts +1 -1
- package/src/lib/modelPersistence.ts +204 -0
- package/src/lib/persistenceQueue.ts +50 -0
- package/src/lib/queryRefetch.ts +1 -1
- package/src/lib/utils.ts +1 -1
- package/src/monkey.ts +6 -1
- package/src/service/storage.ts +47 -2
- package/src/types/index.ts +2 -2
- package/src/types/query.ts +3 -0
package/dist/index.js
CHANGED
|
@@ -2,8 +2,9 @@ import { BeanBase, BeanInfo, BeanScopeBase, BeanSimple, SymbolBeanFullName, Virt
|
|
|
2
2
|
import { Bean, Scope, Service } from "zova-module-a-bean";
|
|
3
3
|
import { QueryCache, QueryClient, VueQueryPlugin, defaultShouldDehydrateQuery, dehydrate, hashKey, hydrate, useMutation, useQuery, useQueryClient } from "@tanstack/vue-query";
|
|
4
4
|
import localforage from "localforage";
|
|
5
|
+
import { CancelledError, notifyManager } from "@tanstack/query-core";
|
|
5
6
|
import { experimental_createQueryPersister } from "@tanstack/query-persist-client-core";
|
|
6
|
-
import { markRaw } from "vue";
|
|
7
|
+
import { markRaw, shallowRef } from "vue";
|
|
7
8
|
//#region src/lib/queryRefetch.ts
|
|
8
9
|
function createQueryRefetch(refetch, getQuery) {
|
|
9
10
|
return async (refetchOptions) => {
|
|
@@ -26,6 +27,56 @@ function resolveMaxAgeTime(maxAge, query) {
|
|
|
26
27
|
return typeof maxAge === "function" ? maxAge(query) : maxAge;
|
|
27
28
|
}
|
|
28
29
|
//#endregion
|
|
30
|
+
//#region src/lib/persistenceQueue.ts
|
|
31
|
+
var PersistenceQueue = class {
|
|
32
|
+
constructor() {
|
|
33
|
+
this._tail = Promise.resolve();
|
|
34
|
+
this._sequence = 0;
|
|
35
|
+
this._failure = void 0;
|
|
36
|
+
this._generation = 0;
|
|
37
|
+
this._keyGenerations = /* @__PURE__ */ new Map();
|
|
38
|
+
}
|
|
39
|
+
generation(key) {
|
|
40
|
+
return `${this._generation}:${this._keyGenerations.get(key) ?? 0}`;
|
|
41
|
+
}
|
|
42
|
+
invalidate(key) {
|
|
43
|
+
this._keyGenerations.set(key, (this._keyGenerations.get(key) ?? 0) + 1);
|
|
44
|
+
}
|
|
45
|
+
invalidateAll() {
|
|
46
|
+
this._generation++;
|
|
47
|
+
this._keyGenerations.clear();
|
|
48
|
+
}
|
|
49
|
+
enqueue(operation) {
|
|
50
|
+
const sequence = ++this._sequence;
|
|
51
|
+
const result = this._tail.then(operation);
|
|
52
|
+
this._tail = result.catch((error) => {
|
|
53
|
+
this._failure ??= {
|
|
54
|
+
sequence,
|
|
55
|
+
error
|
|
56
|
+
};
|
|
57
|
+
});
|
|
58
|
+
return result;
|
|
59
|
+
}
|
|
60
|
+
async flush() {
|
|
61
|
+
const sequence = this._sequence;
|
|
62
|
+
await this._tail;
|
|
63
|
+
if (this._failure && this._failure.sequence <= sequence) {
|
|
64
|
+
const { error } = this._failure;
|
|
65
|
+
this._failure = void 0;
|
|
66
|
+
throw error;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
var queues = /* @__PURE__ */ new WeakMap();
|
|
71
|
+
function getPersistenceQueue(storage) {
|
|
72
|
+
let queue = queues.get(storage);
|
|
73
|
+
if (!queue) {
|
|
74
|
+
queue = new PersistenceQueue();
|
|
75
|
+
queues.set(storage, queue);
|
|
76
|
+
}
|
|
77
|
+
return queue;
|
|
78
|
+
}
|
|
79
|
+
//#endregion
|
|
29
80
|
//#region src/.metadata/this.ts
|
|
30
81
|
var __ThisModule__ = "a-model";
|
|
31
82
|
//#endregion
|
|
@@ -57,6 +108,149 @@ var CookieWrapper = class extends BeanSimple {
|
|
|
57
108
|
}
|
|
58
109
|
};
|
|
59
110
|
//#endregion
|
|
111
|
+
//#region src/lib/modelPersistence.ts
|
|
112
|
+
var normalize = (value) => value == null ? null : String(value);
|
|
113
|
+
function getModelPersistenceStorageKey(appName, scope, logicalKey) {
|
|
114
|
+
return JSON.stringify([
|
|
115
|
+
"zova-model-db",
|
|
116
|
+
1,
|
|
117
|
+
appName,
|
|
118
|
+
scope,
|
|
119
|
+
logicalKey
|
|
120
|
+
]);
|
|
121
|
+
}
|
|
122
|
+
function isModelPersistenceDb(options) {
|
|
123
|
+
if (options === false) return false;
|
|
124
|
+
const persister = options && typeof options === "object" ? options : {};
|
|
125
|
+
return (persister.storage ?? (persister.sync ? "local" : "db")) === "db";
|
|
126
|
+
}
|
|
127
|
+
function emptyQueryState() {
|
|
128
|
+
return {
|
|
129
|
+
data: void 0,
|
|
130
|
+
dataUpdateCount: 0,
|
|
131
|
+
dataUpdatedAt: 0,
|
|
132
|
+
error: null,
|
|
133
|
+
errorUpdateCount: 0,
|
|
134
|
+
errorUpdatedAt: 0,
|
|
135
|
+
fetchFailureCount: 0,
|
|
136
|
+
fetchFailureReason: null,
|
|
137
|
+
fetchMeta: null,
|
|
138
|
+
isInvalidated: false,
|
|
139
|
+
status: "pending",
|
|
140
|
+
fetchStatus: "idle"
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
/** App-owned identity; independent of the module providing the current Passport. */
|
|
144
|
+
var ModelPersistenceContext = class {
|
|
145
|
+
constructor(_queryClient, siteId) {
|
|
146
|
+
this._queryClient = _queryClient;
|
|
147
|
+
this._epoch = 0;
|
|
148
|
+
this._version = shallowRef(0);
|
|
149
|
+
this._scope = void 0;
|
|
150
|
+
this._registered = false;
|
|
151
|
+
this._hydrated = /* @__PURE__ */ new Set();
|
|
152
|
+
this._listeners = /* @__PURE__ */ new Set();
|
|
153
|
+
markRaw(this);
|
|
154
|
+
this._scope = Object.freeze([
|
|
155
|
+
null,
|
|
156
|
+
normalize(siteId),
|
|
157
|
+
null
|
|
158
|
+
]);
|
|
159
|
+
}
|
|
160
|
+
get epoch() {
|
|
161
|
+
this._version.value;
|
|
162
|
+
return this._epoch;
|
|
163
|
+
}
|
|
164
|
+
capture() {
|
|
165
|
+
return Object.freeze({
|
|
166
|
+
scope: this._scope,
|
|
167
|
+
epoch: this.epoch
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
current(token) {
|
|
171
|
+
return token.epoch === this.epoch && token.scope === this._scope;
|
|
172
|
+
}
|
|
173
|
+
markHydrated(queries) {
|
|
174
|
+
if (!this._registered) for (const query of queries) this._hydrated.add(query);
|
|
175
|
+
}
|
|
176
|
+
touch(query) {
|
|
177
|
+
if (query) this._hydrated.delete(query);
|
|
178
|
+
}
|
|
179
|
+
subscribe(listener) {
|
|
180
|
+
this._listeners.add(listener);
|
|
181
|
+
return () => this._listeners.delete(listener);
|
|
182
|
+
}
|
|
183
|
+
update(values, options = {}) {
|
|
184
|
+
const scope = Object.freeze([
|
|
185
|
+
normalize(values.instanceId),
|
|
186
|
+
normalize(values.siteId),
|
|
187
|
+
normalize(values.userId)
|
|
188
|
+
]);
|
|
189
|
+
const adopt = !this._registered && options.initial === true;
|
|
190
|
+
this._registered = true;
|
|
191
|
+
if (scope.every((value, index) => value === this._scope[index])) {
|
|
192
|
+
this._hydrated.clear();
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
const affected = this._queryClient.getQueryCache().getAll().filter((query) => isModelPersistenceDb(query.meta?.persister) && !(adopt && this._hydrated.has(query)));
|
|
196
|
+
this._scope = scope;
|
|
197
|
+
this._hydrated.clear();
|
|
198
|
+
this._invalidate(affected);
|
|
199
|
+
if (options.refetchActive === false) return;
|
|
200
|
+
const token = this.capture();
|
|
201
|
+
Promise.resolve().then(() => {
|
|
202
|
+
if (this.current(token)) return this._queryClient.refetchQueries({
|
|
203
|
+
type: "active",
|
|
204
|
+
predicate: (query) => affected.includes(query)
|
|
205
|
+
});
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
clear() {
|
|
209
|
+
this._hydrated.clear();
|
|
210
|
+
this._invalidate(this._queryClient.getQueryCache().getAll());
|
|
211
|
+
}
|
|
212
|
+
_invalidate(queries) {
|
|
213
|
+
this._epoch++;
|
|
214
|
+
for (const query of queries) query.cancel({
|
|
215
|
+
silent: true,
|
|
216
|
+
revert: false
|
|
217
|
+
});
|
|
218
|
+
notifyManager.batch(() => {
|
|
219
|
+
for (const query of queries) {
|
|
220
|
+
query.setOptions({
|
|
221
|
+
...query.options,
|
|
222
|
+
initialData: void 0,
|
|
223
|
+
initialDataUpdatedAt: void 0
|
|
224
|
+
});
|
|
225
|
+
for (const observer of query.observers) observer.setOptions({
|
|
226
|
+
...observer.options,
|
|
227
|
+
initialData: void 0,
|
|
228
|
+
initialDataUpdatedAt: void 0,
|
|
229
|
+
placeholderData: void 0
|
|
230
|
+
});
|
|
231
|
+
query.setState(emptyQueryState());
|
|
232
|
+
}
|
|
233
|
+
});
|
|
234
|
+
this._version.value++;
|
|
235
|
+
const token = this.capture();
|
|
236
|
+
for (const listener of this._listeners) listener(token);
|
|
237
|
+
}
|
|
238
|
+
/** Keep later observer option reapplication from reinstalling an old identity. */
|
|
239
|
+
guardOptions(options) {
|
|
240
|
+
if (!isModelPersistenceDb(options.meta?.persister)) return options;
|
|
241
|
+
const token = this.capture();
|
|
242
|
+
const initialData = options.initialData;
|
|
243
|
+
const initialDataUpdatedAt = options.initialDataUpdatedAt;
|
|
244
|
+
const placeholderData = options.placeholderData;
|
|
245
|
+
return {
|
|
246
|
+
...options,
|
|
247
|
+
initialData: () => this.current(token) ? typeof initialData === "function" ? initialData() : initialData : void 0,
|
|
248
|
+
initialDataUpdatedAt: () => this.current(token) ? typeof initialDataUpdatedAt === "function" ? initialDataUpdatedAt() : initialDataUpdatedAt : void 0,
|
|
249
|
+
placeholderData: (...args) => this.current(token) ? typeof placeholderData === "function" ? placeholderData(...args) : placeholderData : void 0
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
};
|
|
253
|
+
//#endregion
|
|
60
254
|
//#region src/lib/queryPersister.ts
|
|
61
255
|
function createQueryPersister(persisterFn) {
|
|
62
256
|
return (queryFn, context, query) => {
|
|
@@ -86,50 +280,102 @@ var BeanModelLast = class extends BeanBase {
|
|
|
86
280
|
//#endregion
|
|
87
281
|
//#region src/bean/bean.model/bean.model.persister.ts
|
|
88
282
|
var BeanModelPersister = class extends BeanModelLast {
|
|
89
|
-
|
|
90
|
-
|
|
283
|
+
constructor(...args) {
|
|
284
|
+
super(...args);
|
|
285
|
+
this._persisterRestoreErrors = /* @__PURE__ */ new Set();
|
|
286
|
+
}
|
|
287
|
+
$persisterError(queryKey) {
|
|
288
|
+
const query = this.self.$queryFind({ queryKey });
|
|
289
|
+
const options = this._adjustPersisterOptions(query?.meta?.persister);
|
|
290
|
+
return !!options && this._persisterRestoreErrors.has(this._getPersisterStorageKey(options, query, queryKey));
|
|
291
|
+
}
|
|
292
|
+
_persisterLoad_inner(storedData, query, options) {
|
|
293
|
+
if (!storedData) return { remove: false };
|
|
91
294
|
const persistedQuery = options.deserialize ? options.deserialize(storedData, options.deserializeDefault) : options.deserializeDefault(storedData);
|
|
92
295
|
if (persistedQuery.state.dataUpdatedAt) {
|
|
93
296
|
const expired = Date.now() - persistedQuery.state.dataUpdatedAt > (resolveMaxAgeTime(options.maxAge, query) ?? Infinity);
|
|
94
297
|
const busted = persistedQuery.buster !== options.buster;
|
|
95
|
-
if (expired
|
|
96
|
-
|
|
97
|
-
|
|
298
|
+
if (!expired && !busted) return {
|
|
299
|
+
data: persistedQuery.state.data,
|
|
300
|
+
remove: false,
|
|
301
|
+
timestamps: {
|
|
98
302
|
dataUpdatedAt: persistedQuery.state.dataUpdatedAt,
|
|
99
303
|
errorUpdatedAt: persistedQuery.state.errorUpdatedAt
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
304
|
+
}
|
|
305
|
+
};
|
|
306
|
+
}
|
|
307
|
+
return { remove: true };
|
|
104
308
|
}
|
|
105
309
|
$persisterLoad(queryKey) {
|
|
310
|
+
const ctx = this.ctx;
|
|
311
|
+
if (ctx?.disposed) return void 0;
|
|
312
|
+
const persistence = this.$modelPersistence;
|
|
106
313
|
const query = this.self.$queryFind({ queryKey });
|
|
107
314
|
if (!query) return void 0;
|
|
108
315
|
const options = this._adjustPersisterOptions(query.meta?.persister);
|
|
109
316
|
if (!options) return void 0;
|
|
110
317
|
const storage = this._getPersisterStorage(options, query);
|
|
111
318
|
if (!storage) return void 0;
|
|
112
|
-
const
|
|
319
|
+
const token = persistence.capture();
|
|
320
|
+
if (options.storage === "db") persistence.touch(query);
|
|
321
|
+
const storageKey = this._getPersisterStorageKey(options, query, void 0, token);
|
|
322
|
+
this._persisterRestoreErrors.delete(storageKey);
|
|
323
|
+
const queue = getPersistenceQueue(storage);
|
|
324
|
+
const generation = queue.generation(storageKey);
|
|
325
|
+
const current = () => !ctx?.disposed && generation === queue.generation(storageKey) && (options.storage !== "db" || persistence.current(token));
|
|
326
|
+
if (!options.sync) return queue.enqueue(async () => {
|
|
327
|
+
if (!current()) return void 0;
|
|
328
|
+
const storedData = await storage.getItem(storageKey);
|
|
329
|
+
if (!current()) return void 0;
|
|
330
|
+
try {
|
|
331
|
+
const result = this._persisterLoad_inner(storedData, query, options);
|
|
332
|
+
if (!current()) return void 0;
|
|
333
|
+
if (result.timestamps) query.setState(result.timestamps);
|
|
334
|
+
if (result.remove) await storage.removeItem(storageKey);
|
|
335
|
+
return current() ? result.data : void 0;
|
|
336
|
+
} catch {
|
|
337
|
+
if (!current()) return void 0;
|
|
338
|
+
this._persisterRestoreErrors.add(storageKey);
|
|
339
|
+
await storage.removeItem(storageKey);
|
|
340
|
+
this._reportPersisterError("restore");
|
|
341
|
+
return;
|
|
342
|
+
}
|
|
343
|
+
}).catch(() => {
|
|
344
|
+
if (current()) {
|
|
345
|
+
this._persisterRestoreErrors.add(storageKey);
|
|
346
|
+
this._reportPersisterError("restore");
|
|
347
|
+
}
|
|
348
|
+
});
|
|
113
349
|
try {
|
|
114
|
-
const
|
|
115
|
-
if (
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
350
|
+
const result = this._persisterLoad_inner(storage.getItem(storageKey), query, options);
|
|
351
|
+
if (result.timestamps) query.setState(result.timestamps);
|
|
352
|
+
if (result.remove) storage.removeItem(storageKey);
|
|
353
|
+
return result.data;
|
|
354
|
+
} catch {
|
|
355
|
+
this._persisterRestoreErrors.add(storageKey);
|
|
356
|
+
this._reportPersisterError("restore");
|
|
357
|
+
try {
|
|
358
|
+
storage.removeItem(storageKey);
|
|
359
|
+
} catch {
|
|
360
|
+
this._reportPersisterError("remove");
|
|
123
361
|
}
|
|
124
|
-
storage.removeItem(storageKey);
|
|
125
362
|
}
|
|
126
363
|
}
|
|
364
|
+
$persisterGeneration(queryKey) {
|
|
365
|
+
const query = this.self.$queryFind({ queryKey });
|
|
366
|
+
const options = this._adjustPersisterOptions(query?.meta?.persister);
|
|
367
|
+
if (!options) return "";
|
|
368
|
+
const storage = this._getPersisterStorage(options, query);
|
|
369
|
+
if (!storage) return "";
|
|
370
|
+
const storageKey = this._getPersisterStorageKey(options, query, queryKey);
|
|
371
|
+
return `${options.storage === "db" ? this.$modelPersistence.epoch : ""}:${storageKey}:${getPersistenceQueue(storage).generation(storageKey)}`;
|
|
372
|
+
}
|
|
127
373
|
$persisterSave(queryKey) {
|
|
128
374
|
const query = this.self.$queryFind({ queryKey });
|
|
129
|
-
if (!query) return;
|
|
375
|
+
if (!query) return Promise.resolve();
|
|
130
376
|
const options = this._adjustPersisterOptions(query.meta?.persister);
|
|
131
|
-
if (!options) return;
|
|
132
|
-
this._persisterSave(query, options);
|
|
377
|
+
if (!options) return Promise.resolve();
|
|
378
|
+
return this._persisterSave(query, options);
|
|
133
379
|
}
|
|
134
380
|
$persisterSaveTo(queryKey, storageTarget, value) {
|
|
135
381
|
const query = this.self.$queryFind({ queryKey });
|
|
@@ -144,13 +390,9 @@ var BeanModelPersister = class extends BeanModelLast {
|
|
|
144
390
|
sync: true,
|
|
145
391
|
serializeDefault: (obj) => storageTarget === "cookie" ? String(obj?.state?.data ?? "") : JSON.stringify(obj?.state?.data)
|
|
146
392
|
});
|
|
147
|
-
if (
|
|
148
|
-
this._persisterSave(query, options, value);
|
|
393
|
+
if (options) this._persisterSave(query, options, value);
|
|
149
394
|
}
|
|
150
|
-
|
|
151
|
-
const storage = this._getPersisterStorage(options, query);
|
|
152
|
-
if (!storage) return;
|
|
153
|
-
const storageKey = this._getPersisterStorageKey(options, query);
|
|
395
|
+
_serializePersister(query, options, value) {
|
|
154
396
|
const params = {
|
|
155
397
|
state: value === void 0 ? query.state : {
|
|
156
398
|
...query.state,
|
|
@@ -160,42 +402,183 @@ var BeanModelPersister = class extends BeanModelLast {
|
|
|
160
402
|
queryHash: query.queryHash,
|
|
161
403
|
buster: options.buster
|
|
162
404
|
};
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
405
|
+
return options.serialize ? options.serialize(params, options.serializeDefault) : options.serializeDefault(params);
|
|
406
|
+
}
|
|
407
|
+
_persisterSave(query, options, value) {
|
|
408
|
+
const storage = this._getPersisterStorage(options, query);
|
|
409
|
+
if (!storage) return Promise.resolve();
|
|
410
|
+
if (options.storage === "db") this.$modelPersistence.touch(query);
|
|
411
|
+
const storageKey = this._getPersisterStorageKey(options, query);
|
|
412
|
+
const queue = getPersistenceQueue(storage);
|
|
413
|
+
queue.invalidate(storageKey);
|
|
414
|
+
let data;
|
|
415
|
+
try {
|
|
416
|
+
data = this._serializePersister(query, options, value);
|
|
417
|
+
} catch (error) {
|
|
418
|
+
return this._handlePersisterOperation(queue.enqueue(() => {
|
|
419
|
+
throw error;
|
|
420
|
+
}), "save");
|
|
421
|
+
}
|
|
422
|
+
if (options.sync === true && options.storage !== "db") try {
|
|
166
423
|
storage.setItem(storageKey, data);
|
|
167
|
-
|
|
424
|
+
return Promise.resolve();
|
|
425
|
+
} catch (error) {
|
|
426
|
+
return this._handlePersisterOperation(Promise.reject(error), "save");
|
|
427
|
+
}
|
|
428
|
+
return this._handlePersisterOperation(queue.enqueue(async () => {
|
|
429
|
+
await storage.setItem(storageKey, data);
|
|
430
|
+
}), "save");
|
|
168
431
|
}
|
|
169
|
-
$persisterRemove(queryKey) {
|
|
432
|
+
$persisterRemove(queryKey, persister) {
|
|
170
433
|
const query = this.self.$queryFind({ queryKey });
|
|
171
|
-
if (!query) return;
|
|
172
|
-
const options = this._adjustPersisterOptions(query
|
|
173
|
-
if (!options) return;
|
|
434
|
+
if (!query && !persister) return Promise.resolve();
|
|
435
|
+
const options = this._adjustPersisterOptions(persister ?? query?.meta?.persister);
|
|
436
|
+
if (!options) return Promise.resolve();
|
|
174
437
|
const storage = this._getPersisterStorage(options, query);
|
|
175
|
-
if (!storage) return;
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
438
|
+
if (!storage) return Promise.resolve();
|
|
439
|
+
if (options.storage === "db") this.$modelPersistence.touch(query);
|
|
440
|
+
const storageKey = this._getPersisterStorageKey(options, query, queryKey);
|
|
441
|
+
const queue = getPersistenceQueue(storage);
|
|
442
|
+
queue.invalidate(storageKey);
|
|
443
|
+
if (options.sync === true && options.storage !== "db") try {
|
|
179
444
|
storage.removeItem(storageKey);
|
|
180
|
-
|
|
445
|
+
return Promise.resolve();
|
|
446
|
+
} catch (error) {
|
|
447
|
+
return this._handlePersisterOperation(Promise.reject(error), "remove");
|
|
448
|
+
}
|
|
449
|
+
return this._handlePersisterOperation(queue.enqueue(async () => {
|
|
450
|
+
await storage.removeItem(storageKey);
|
|
451
|
+
}), "remove");
|
|
452
|
+
}
|
|
453
|
+
async $persisterFlush() {
|
|
454
|
+
if (process.env.SERVER) return;
|
|
455
|
+
await getPersistenceQueue(localforage).flush();
|
|
456
|
+
}
|
|
457
|
+
_handlePersisterOperation(operation, action) {
|
|
458
|
+
operation.catch(() => this._reportPersisterError(action));
|
|
459
|
+
return operation;
|
|
460
|
+
}
|
|
461
|
+
_reportPersisterError(action) {
|
|
462
|
+
if (process.env.DEV) console.warn(`Encountered an error attempting to ${action} persisted query cache.`);
|
|
181
463
|
}
|
|
182
464
|
_createPersister(options) {
|
|
183
465
|
options = this._adjustPersisterOptions(options);
|
|
184
466
|
if (!options) return void 0;
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
467
|
+
if (options.storage === "db") return this._createDbPersister(options);
|
|
468
|
+
const storage = this._getPersisterStorage(options);
|
|
469
|
+
const persisterOptions = options;
|
|
470
|
+
return createQueryPersister((queryFn, context, query) => {
|
|
471
|
+
const queue = storage ? getPersistenceQueue(storage) : void 0;
|
|
472
|
+
const storageKey = `${persisterOptions.prefix}-${query.queryHash}`;
|
|
473
|
+
const generation = queue?.generation(storageKey);
|
|
474
|
+
const current = () => generation === queue?.generation(storageKey);
|
|
475
|
+
const orderedStorage = storage && queue && !persisterOptions.sync ? {
|
|
476
|
+
getItem: (key) => queue.enqueue(() => current() ? storage.getItem(key) : void 0),
|
|
477
|
+
setItem: (key, data) => this._handlePersisterOperation(queue.enqueue(async () => {
|
|
478
|
+
if (current()) await storage.setItem(key, data);
|
|
479
|
+
}), "save"),
|
|
480
|
+
removeItem: (key) => this._handlePersisterOperation(queue.enqueue(async () => {
|
|
481
|
+
if (current()) await storage.removeItem(key);
|
|
482
|
+
}), "remove")
|
|
483
|
+
} : storage;
|
|
484
|
+
return experimental_createQueryPersister({
|
|
485
|
+
storage: orderedStorage,
|
|
486
|
+
maxAge: persisterOptions.maxAge,
|
|
487
|
+
refetchOnRestore: persisterOptions.refetchOnRestore,
|
|
488
|
+
prefix: persisterOptions.prefix,
|
|
489
|
+
buster: persisterOptions.buster
|
|
490
|
+
}).persisterFn(queryFn, context, query);
|
|
491
|
+
});
|
|
492
|
+
}
|
|
493
|
+
_createDbPersister(options) {
|
|
494
|
+
const ctx = this.ctx;
|
|
495
|
+
const persistence = this.$modelPersistence;
|
|
496
|
+
return async (queryFn, context, query) => {
|
|
497
|
+
if (ctx?.disposed) throw new CancelledError({
|
|
498
|
+
silent: true,
|
|
499
|
+
revert: false
|
|
500
|
+
});
|
|
501
|
+
persistence.touch(query);
|
|
502
|
+
const token = persistence.capture();
|
|
503
|
+
const storage = this._getPersisterStorage(options, query);
|
|
504
|
+
const queue = storage && getPersistenceQueue(storage);
|
|
505
|
+
const storageKey = this._getPersisterStorageKey(options, query, void 0, token);
|
|
506
|
+
const generation = queue?.generation(storageKey);
|
|
507
|
+
const current = () => !ctx?.disposed && persistence.current(token) && generation === queue?.generation(storageKey);
|
|
508
|
+
const assertCurrent = () => {
|
|
509
|
+
if (!current()) throw new CancelledError({
|
|
510
|
+
silent: true,
|
|
511
|
+
revert: false
|
|
512
|
+
});
|
|
513
|
+
};
|
|
514
|
+
const bypass = query.state.fetchMeta?.bypassPersister === true;
|
|
515
|
+
if (!bypass && storage && queue && query.state.data === void 0) {
|
|
516
|
+
this._persisterRestoreErrors.delete(storageKey);
|
|
517
|
+
const restored = await queue.enqueue(async () => {
|
|
518
|
+
if (!current()) return void 0;
|
|
519
|
+
try {
|
|
520
|
+
const storedData = await storage.getItem(storageKey);
|
|
521
|
+
if (!current()) return void 0;
|
|
522
|
+
const result = this._persisterLoad_inner(storedData, query, options);
|
|
523
|
+
if (!current()) return void 0;
|
|
524
|
+
if (result.remove) await storage.removeItem(storageKey);
|
|
525
|
+
return current() ? result : void 0;
|
|
526
|
+
} catch {
|
|
527
|
+
if (current()) {
|
|
528
|
+
this._persisterRestoreErrors.add(storageKey);
|
|
529
|
+
await storage.removeItem(storageKey);
|
|
530
|
+
this._reportPersisterError("restore");
|
|
531
|
+
}
|
|
532
|
+
return;
|
|
533
|
+
}
|
|
534
|
+
}).catch(() => {
|
|
535
|
+
if (current()) {
|
|
536
|
+
this._persisterRestoreErrors.add(storageKey);
|
|
537
|
+
this._reportPersisterError("restore");
|
|
538
|
+
}
|
|
539
|
+
});
|
|
540
|
+
assertCurrent();
|
|
541
|
+
if (restored?.data !== void 0) {
|
|
542
|
+
notifyManager.schedule(() => {
|
|
543
|
+
if (!current()) return;
|
|
544
|
+
if (restored.timestamps) query.setState(restored.timestamps);
|
|
545
|
+
if (options.refetchOnRestore === "always" || options.refetchOnRestore === true && query.isStale()) query.fetch().catch(() => void 0);
|
|
546
|
+
});
|
|
547
|
+
return restored.data;
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
assertCurrent();
|
|
551
|
+
let result;
|
|
552
|
+
try {
|
|
553
|
+
result = await queryFn(context);
|
|
554
|
+
} catch (error) {
|
|
555
|
+
assertCurrent();
|
|
556
|
+
throw error;
|
|
557
|
+
}
|
|
558
|
+
assertCurrent();
|
|
559
|
+
if (!bypass && storage && queue) notifyManager.schedule(() => {
|
|
560
|
+
if (!current()) return;
|
|
561
|
+
let data;
|
|
562
|
+
try {
|
|
563
|
+
data = this._serializePersister(query, options, result);
|
|
564
|
+
} catch (error) {
|
|
565
|
+
this._handlePersisterOperation(queue.enqueue(() => {
|
|
566
|
+
throw error;
|
|
567
|
+
}), "save");
|
|
568
|
+
return;
|
|
569
|
+
}
|
|
570
|
+
this._handlePersisterOperation(queue.enqueue(async () => {
|
|
571
|
+
if (current()) await storage.setItem(storageKey, data);
|
|
572
|
+
}), "save");
|
|
573
|
+
});
|
|
574
|
+
return result;
|
|
575
|
+
};
|
|
193
576
|
}
|
|
194
577
|
_adjustPersisterOptions(options) {
|
|
195
578
|
if (options === false) return void 0;
|
|
196
|
-
|
|
197
|
-
else options = { ...options };
|
|
579
|
+
options = options === void 0 || options === true ? {} : { ...options };
|
|
198
580
|
options.storage = options.storage ?? (options.sync ? "local" : "db");
|
|
581
|
+
if (options.storage === "db") options.sync = false;
|
|
199
582
|
options.maxAge = options.maxAge ?? this.scopeSelf.config.persister.maxAge[options.storage];
|
|
200
583
|
options.refetchOnRestore = options.refetchOnRestore ?? this.scopeSelf.config.persister.refetchOnRestore;
|
|
201
584
|
options.prefix = options.prefix ?? this._getPersisterPrefix();
|
|
@@ -204,9 +587,10 @@ var BeanModelPersister = class extends BeanModelLast {
|
|
|
204
587
|
options.deserializeDefault = options.deserializeDefault ?? JSON.parse;
|
|
205
588
|
return options;
|
|
206
589
|
}
|
|
207
|
-
_getPersisterStorageKey(options, query) {
|
|
208
|
-
|
|
209
|
-
|
|
590
|
+
_getPersisterStorageKey(options, query, queryKey, token) {
|
|
591
|
+
const key = query?.queryKey ?? this._forceQueryKeyPrefix(queryKey);
|
|
592
|
+
const logicalKey = options.storageKeySimplify ? String(key[key.length - 1]) : `${options.prefix}-${query?.queryHash ?? hashKey(key)}`;
|
|
593
|
+
return options.storage === "db" ? getModelPersistenceStorageKey(this.sys.env.APP_NAME ?? "", (token ?? this.$modelPersistence.capture()).scope, logicalKey) : logicalKey;
|
|
210
594
|
}
|
|
211
595
|
_getPersisterStorage(options, query) {
|
|
212
596
|
options = this._adjustPersisterOptions(options);
|
|
@@ -331,9 +715,13 @@ var BeanModelQuery = class extends BeanModelCookie {
|
|
|
331
715
|
})?.setData(value);
|
|
332
716
|
}
|
|
333
717
|
async $clear() {
|
|
334
|
-
const
|
|
335
|
-
|
|
336
|
-
|
|
718
|
+
const queue = getPersistenceQueue(localforage);
|
|
719
|
+
queue.invalidateAll();
|
|
720
|
+
const clear = process.env.SERVER ? Promise.resolve() : queue.enqueue(async () => {
|
|
721
|
+
await localforage.clear();
|
|
722
|
+
});
|
|
723
|
+
this.$modelPersistence.clear();
|
|
724
|
+
await clear;
|
|
337
725
|
}
|
|
338
726
|
$normalizeFilters(filters) {
|
|
339
727
|
if (!filters) filters = {};
|
|
@@ -350,10 +738,10 @@ var BeanModelUseQuery = class extends BeanModelQuery {
|
|
|
350
738
|
$useQuery(options, queryClient) {
|
|
351
739
|
const queryKey = this.self._forceQueryKeyPrefix(options.queryKey);
|
|
352
740
|
const persister = this._createPersister(options.meta?.persister);
|
|
353
|
-
options = Object.assign({}, options, {
|
|
741
|
+
options = this.$modelPersistence.guardOptions(Object.assign({}, options, {
|
|
354
742
|
queryKey,
|
|
355
743
|
persister
|
|
356
|
-
});
|
|
744
|
+
}));
|
|
357
745
|
if ((typeof options.meta?.persister === "object" && options.meta?.persister?.sync) !== true) {
|
|
358
746
|
const staleTime = options.staleTime ?? this.scopeSelf.config.query.staleTime.async;
|
|
359
747
|
const queryCacheExists = this.$queryFind({ queryKey })?.state.data !== void 0;
|
|
@@ -501,16 +889,24 @@ var BeanModelUseState = class extends BeanModelUseQuery {
|
|
|
501
889
|
return this[SymbolUseQueries][queryHash];
|
|
502
890
|
}
|
|
503
891
|
_handleAsyncDataGet(options, queryClient, persister) {
|
|
892
|
+
if (this.ctx?.disposed) return void 0;
|
|
893
|
+
this.$modelPersistence.epoch;
|
|
504
894
|
const query = this.$useStateData(options, queryClient);
|
|
505
895
|
if (query.data !== void 0) return query.data;
|
|
506
896
|
return this._handleAsyncDataGet_inner(options, queryClient, persister);
|
|
507
897
|
}
|
|
508
898
|
async _handleAsyncDataGet_inner(options, queryClient, persister) {
|
|
899
|
+
const ctx = this.ctx;
|
|
900
|
+
if (ctx?.disposed) return void 0;
|
|
901
|
+
const persistence = this.$modelPersistence;
|
|
509
902
|
const queryKey = options.queryKey;
|
|
903
|
+
const token = persistence.capture();
|
|
510
904
|
const query = this.$useStateData(options, queryClient);
|
|
511
905
|
if (persister) {
|
|
906
|
+
const generation = this.$persisterGeneration(queryKey);
|
|
512
907
|
const data = await this.$persisterLoad(queryKey);
|
|
513
|
-
if (
|
|
908
|
+
if (ctx?.disposed || !persistence.current(token) || generation !== this.$persisterGeneration(queryKey)) return;
|
|
909
|
+
if (data !== void 0 && query.data === void 0) this.$setQueryData(queryKey, data, false);
|
|
514
910
|
}
|
|
515
911
|
if (query.data === void 0) this._handleSyncDataGet_defaultData(queryKey, options);
|
|
516
912
|
return query.data;
|
|
@@ -595,6 +991,31 @@ var ServiceStorage = (_dec$1 = Service(), _dec2$1 = BeanInfo({ module: "a-model"
|
|
|
595
991
|
constructor(...args) {
|
|
596
992
|
super(...args);
|
|
597
993
|
this._queryClient = void 0;
|
|
994
|
+
this._persistence = void 0;
|
|
995
|
+
}
|
|
996
|
+
get epoch() {
|
|
997
|
+
return this._persistence.epoch;
|
|
998
|
+
}
|
|
999
|
+
capture() {
|
|
1000
|
+
return this._persistence.capture();
|
|
1001
|
+
}
|
|
1002
|
+
current(token) {
|
|
1003
|
+
return this._persistence.current(token);
|
|
1004
|
+
}
|
|
1005
|
+
update(values, options) {
|
|
1006
|
+
this._persistence.update(values, options);
|
|
1007
|
+
}
|
|
1008
|
+
subscribe(listener) {
|
|
1009
|
+
return this._persistence.subscribe(listener);
|
|
1010
|
+
}
|
|
1011
|
+
clear() {
|
|
1012
|
+
this._persistence.clear();
|
|
1013
|
+
}
|
|
1014
|
+
touch(query) {
|
|
1015
|
+
this._persistence.touch(query);
|
|
1016
|
+
}
|
|
1017
|
+
guardOptions(options) {
|
|
1018
|
+
return this._persistence.guardOptions(options);
|
|
598
1019
|
}
|
|
599
1020
|
async moduleLoaded() {
|
|
600
1021
|
const options = deepExtend({}, this.scope.config.queryClientConfig.defaultOptions);
|
|
@@ -603,10 +1024,12 @@ var ServiceStorage = (_dec$1 = Service(), _dec2$1 = BeanInfo({ module: "a-model"
|
|
|
603
1024
|
options.queries.gcTime = Infinity;
|
|
604
1025
|
}
|
|
605
1026
|
const queryCache = new QueryCache();
|
|
606
|
-
const
|
|
1027
|
+
const queryClient = this._queryClient = new QueryClient({
|
|
607
1028
|
defaultOptions: options,
|
|
608
1029
|
queryCache
|
|
609
|
-
})
|
|
1030
|
+
});
|
|
1031
|
+
this._persistence = new ModelPersistenceContext(queryClient, this.sys.env.SITE_ID);
|
|
1032
|
+
const vueQueryPluginOptions = { queryClient };
|
|
610
1033
|
this.app.vue.use(VueQueryPlugin, vueQueryPluginOptions);
|
|
611
1034
|
}
|
|
612
1035
|
async appInitialize() {
|
|
@@ -616,7 +1039,14 @@ var ServiceStorage = (_dec$1 = Service(), _dec2$1 = BeanInfo({ module: "a-model"
|
|
|
616
1039
|
} });
|
|
617
1040
|
this._queryClient?.clear();
|
|
618
1041
|
});
|
|
619
|
-
if (process.env.CLIENT && this.ctx.meta.$ssr.isRuntimeSsrPreHydration)
|
|
1042
|
+
if (process.env.CLIENT && this.ctx.meta.$ssr.isRuntimeSsrPreHydration) {
|
|
1043
|
+
const state = this.ctx.meta.$ssr.stateDefer.query;
|
|
1044
|
+
hydrate(this._queryClient, state);
|
|
1045
|
+
this._persistence.markHydrated((state?.queries ?? []).flatMap((item) => {
|
|
1046
|
+
const query = this._queryClient.getQueryCache().get(item.queryHash);
|
|
1047
|
+
return query ? [query] : [];
|
|
1048
|
+
}));
|
|
1049
|
+
}
|
|
620
1050
|
}
|
|
621
1051
|
}) || _class$1) || _class$1);
|
|
622
1052
|
//#endregion
|
|
@@ -679,6 +1109,11 @@ var Monkey = class extends BeanSimple {
|
|
|
679
1109
|
if (this._moduleSelf === module) await (await this.getStorage()).moduleLoaded();
|
|
680
1110
|
}
|
|
681
1111
|
async beanInit(bean, beanInstance) {
|
|
1112
|
+
bean.defineProperty(beanInstance, "$modelPersistence", {
|
|
1113
|
+
enumerable: false,
|
|
1114
|
+
configurable: true,
|
|
1115
|
+
get: () => this._storage
|
|
1116
|
+
});
|
|
682
1117
|
bean.defineProperty(beanInstance, "$queryClient", {
|
|
683
1118
|
enumerable: false,
|
|
684
1119
|
configurable: true,
|
|
@@ -690,8 +1125,6 @@ var Monkey = class extends BeanSimple {
|
|
|
690
1125
|
};
|
|
691
1126
|
//#endregion
|
|
692
1127
|
//#region src/.metadata/index.ts
|
|
693
|
-
/** monkey: end */
|
|
694
|
-
/** scope: begin */
|
|
695
1128
|
var _dec;
|
|
696
1129
|
var _dec2;
|
|
697
1130
|
var _class;
|
|
@@ -742,6 +1175,6 @@ async function _QueryEnsureLoadedInner(fn) {
|
|
|
742
1175
|
return query;
|
|
743
1176
|
}
|
|
744
1177
|
//#endregion
|
|
745
|
-
export { $QueriesEnsureLoaded, $QueryEnsureFresh, $QueryEnsureLoaded, $QueryGetFresh, BeanModelBase, Model, Monkey, ScopeModuleAModel, ServiceStorage, config, resolveMaxAgeTime, resolveStaleTime };
|
|
1178
|
+
export { $QueriesEnsureLoaded, $QueryEnsureFresh, $QueryEnsureLoaded, $QueryGetFresh, BeanModelBase, Model, ModelPersistenceContext, Monkey, ScopeModuleAModel, ServiceStorage, config, getModelPersistenceStorageKey, isModelPersistenceDb, resolveMaxAgeTime, resolveStaleTime };
|
|
746
1179
|
|
|
747
1180
|
//# sourceMappingURL=index.js.map
|