zova-module-a-model 5.0.9
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/LICENSE +21 -0
- package/package.json +67 -0
- package/src/api/index.ts +2 -0
- package/src/api/interface/index.ts +1 -0
- package/src/api/service/index.ts +1 -0
- package/src/assets/css/module.scss +1 -0
- package/src/bean/bean.model/bean.model.cookie.ts +30 -0
- package/src/bean/bean.model/bean.model.first.ts +3 -0
- package/src/bean/bean.model/bean.model.last.ts +13 -0
- package/src/bean/bean.model/bean.model.persister.ts +129 -0
- package/src/bean/bean.model/bean.model.query.ts +59 -0
- package/src/bean/bean.model/bean.model.useMutation.ts +21 -0
- package/src/bean/bean.model/bean.model.useQuery.ts +222 -0
- package/src/bean/virtual.model.ts +5 -0
- package/src/common/cookieStorage.ts +13 -0
- package/src/common/types.ts +58 -0
- package/src/component/.gitkeep +0 -0
- package/src/config/config.ts +14 -0
- package/src/config/constants.ts +1 -0
- package/src/config/errors.ts +1 -0
- package/src/config/index.ts +4 -0
- package/src/config/locale/en-us.ts +1 -0
- package/src/config/locale/zh-cn.ts +1 -0
- package/src/config/locales.ts +7 -0
- package/src/index.ts +9 -0
- package/src/local/storage.ts +31 -0
- package/src/monkey.ts +27 -0
- package/src/page/.gitkeep +0 -0
- package/src/resource/beans.ts +5 -0
- package/src/resource/components.ts +1 -0
- package/src/resource/index.ts +3 -0
- package/src/resource/scope.ts +32 -0
- package/src/resource/this.ts +4 -0
- package/src/routes.ts +3 -0
- package/src/types.ts +54 -0
- package/src/typings.ts +1 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2016-present Zova
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/package.json
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "zova-module-a-model",
|
|
3
|
+
"version": "5.0.9",
|
|
4
|
+
"title": "a-model",
|
|
5
|
+
"zovaModule": {
|
|
6
|
+
"capabilities": {
|
|
7
|
+
"monkey": true
|
|
8
|
+
},
|
|
9
|
+
"bundle": {
|
|
10
|
+
"vendors": [
|
|
11
|
+
{
|
|
12
|
+
"match": [
|
|
13
|
+
"@tanstack"
|
|
14
|
+
],
|
|
15
|
+
"output": "tanstack"
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"match": [
|
|
19
|
+
"js-cookie"
|
|
20
|
+
],
|
|
21
|
+
"output": "js-cookie"
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"match": [
|
|
25
|
+
"localforage"
|
|
26
|
+
],
|
|
27
|
+
"output": "localforage"
|
|
28
|
+
}
|
|
29
|
+
]
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
"type": "module",
|
|
33
|
+
"exports": {
|
|
34
|
+
".": {
|
|
35
|
+
"types": [
|
|
36
|
+
"./src/index.ts",
|
|
37
|
+
"./dist/index.d.ts"
|
|
38
|
+
],
|
|
39
|
+
"import": "./src/index.ts",
|
|
40
|
+
"default": "./dist/index.js"
|
|
41
|
+
},
|
|
42
|
+
"./*": "./*"
|
|
43
|
+
},
|
|
44
|
+
"description": "core",
|
|
45
|
+
"keywords": [
|
|
46
|
+
"Zova Module"
|
|
47
|
+
],
|
|
48
|
+
"author": "zhennann",
|
|
49
|
+
"license": "MIT",
|
|
50
|
+
"files": [
|
|
51
|
+
"dist",
|
|
52
|
+
"src"
|
|
53
|
+
],
|
|
54
|
+
"scripts": {
|
|
55
|
+
"clean": "tsc -b --clean",
|
|
56
|
+
"tsc:publish": "npm run clean && tsc -b",
|
|
57
|
+
"prepublishOnly": "npm run tsc:publish"
|
|
58
|
+
},
|
|
59
|
+
"dependencies": {
|
|
60
|
+
"@tanstack/query-persist-client-core": "^5.45.0",
|
|
61
|
+
"@tanstack/vue-query": "^5.45.0",
|
|
62
|
+
"@types/js-cookie": "^3.0.6",
|
|
63
|
+
"js-cookie": "^3.0.5",
|
|
64
|
+
"localforage": "^1.10.0"
|
|
65
|
+
},
|
|
66
|
+
"gitHead": "6633ccc421b46bbbc08a2a3a6ec7d92544a222de"
|
|
67
|
+
}
|
package/src/api/index.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const services = {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Query } from '@tanstack/vue-query';
|
|
2
|
+
import { BeanModelPersister } from './bean.model.persister.js';
|
|
3
|
+
|
|
4
|
+
export class BeanModelCookie<TScopeModule = unknown> extends BeanModelPersister<TScopeModule> {
|
|
5
|
+
$serializeCookie(obj?: Query) {
|
|
6
|
+
return String(obj?.state?.data ?? '');
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
$deserializeCookie(value?: string) {
|
|
10
|
+
return {
|
|
11
|
+
state: {
|
|
12
|
+
data: value,
|
|
13
|
+
dataUpdateCount: 0,
|
|
14
|
+
dataUpdatedAt: Date.now(),
|
|
15
|
+
error: null,
|
|
16
|
+
errorUpdateCount: 0,
|
|
17
|
+
errorUpdatedAt: 0,
|
|
18
|
+
fetchFailureCount: 0,
|
|
19
|
+
fetchFailureReason: null,
|
|
20
|
+
fetchMeta: null,
|
|
21
|
+
isInvalidated: false,
|
|
22
|
+
status: 'success',
|
|
23
|
+
fetchStatus: 'idle',
|
|
24
|
+
},
|
|
25
|
+
queryKey: undefined,
|
|
26
|
+
queryHash: undefined,
|
|
27
|
+
buster: this._getPersisterBuster(),
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { BeanBase, Cast } from 'zova';
|
|
2
|
+
import { BeanModelBase } from '../virtual.model.js';
|
|
3
|
+
import { ScopeModule, __ThisModule__ } from '../../resource/this.js';
|
|
4
|
+
|
|
5
|
+
export class BeanModelLast<TScopeModule = unknown> extends BeanBase<TScopeModule> {
|
|
6
|
+
get self() {
|
|
7
|
+
return Cast<BeanModelBase>(this);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
get scopeSelf(): ScopeModule {
|
|
11
|
+
return this.getScope(__ThisModule__);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { QueryMetaPersister } from '../../types.js';
|
|
2
|
+
import { experimental_createPersister } from '@tanstack/query-persist-client-core';
|
|
3
|
+
import { Query, QueryKey } from '@tanstack/vue-query';
|
|
4
|
+
import { cookieStorage } from '../../common/cookieStorage.js';
|
|
5
|
+
import localforage from 'localforage';
|
|
6
|
+
import { SymbolBeanFullName } from 'zova';
|
|
7
|
+
import { BeanModelLast } from './bean.model.last.js';
|
|
8
|
+
|
|
9
|
+
export class BeanModelPersister<TScopeModule = unknown> extends BeanModelLast<TScopeModule> {
|
|
10
|
+
$persisterLoad<T>(queryKey: QueryKey): T | undefined {
|
|
11
|
+
const query = this.self.$queryFind({ queryKey });
|
|
12
|
+
if (!query) return undefined;
|
|
13
|
+
const options = this._adjustPersisterOptions(query.meta?.persister);
|
|
14
|
+
if (!options) return undefined;
|
|
15
|
+
const storage = this._getPersisterStorage(options);
|
|
16
|
+
if (!storage) return undefined;
|
|
17
|
+
const storageKey = this._getPersisterStorageKey(options, query);
|
|
18
|
+
try {
|
|
19
|
+
const storedData = storage.getItem(storageKey);
|
|
20
|
+
if (!storedData) return undefined;
|
|
21
|
+
const persistedQuery = options.deserialize!(storedData as string);
|
|
22
|
+
|
|
23
|
+
if (persistedQuery.state.dataUpdatedAt) {
|
|
24
|
+
const queryAge = Date.now() - persistedQuery.state.dataUpdatedAt;
|
|
25
|
+
const expired = queryAge > options.maxAge!;
|
|
26
|
+
const busted = persistedQuery.buster !== options.buster;
|
|
27
|
+
if (expired || busted) {
|
|
28
|
+
storage.removeItem(storageKey);
|
|
29
|
+
} else {
|
|
30
|
+
// Set proper updatedAt, since resolving in the first pass overrides those values
|
|
31
|
+
query.setState({
|
|
32
|
+
dataUpdatedAt: persistedQuery.state.dataUpdatedAt,
|
|
33
|
+
errorUpdatedAt: persistedQuery.state.errorUpdatedAt,
|
|
34
|
+
});
|
|
35
|
+
return persistedQuery.state.data as T;
|
|
36
|
+
}
|
|
37
|
+
} else {
|
|
38
|
+
storage.removeItem(storageKey);
|
|
39
|
+
}
|
|
40
|
+
} catch (err) {
|
|
41
|
+
if (process.env.NODE_ENV === 'development') {
|
|
42
|
+
console.error(err);
|
|
43
|
+
console.warn('Encountered an error attempting to restore query cache from persisted location.');
|
|
44
|
+
}
|
|
45
|
+
storage.removeItem(storageKey);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
$persisterSave(queryKey: QueryKey) {
|
|
50
|
+
const query = this.self.$queryFind({ queryKey });
|
|
51
|
+
if (!query) return;
|
|
52
|
+
const options = this._adjustPersisterOptions(query.meta?.persister);
|
|
53
|
+
if (!options) return;
|
|
54
|
+
const storage = this._getPersisterStorage(options);
|
|
55
|
+
if (!storage) return;
|
|
56
|
+
const storageKey = this._getPersisterStorageKey(options, query);
|
|
57
|
+
const data = options.serialize!({
|
|
58
|
+
state: query.state,
|
|
59
|
+
queryKey: query.queryKey,
|
|
60
|
+
queryHash: query.queryHash,
|
|
61
|
+
buster: options.buster,
|
|
62
|
+
});
|
|
63
|
+
if (options.sync === true) {
|
|
64
|
+
storage.setItem(storageKey, data);
|
|
65
|
+
} else {
|
|
66
|
+
// Persist if we have storage defined, we use timeout to get proper state to be persisted
|
|
67
|
+
setTimeout(() => {
|
|
68
|
+
storage.setItem(storageKey, data);
|
|
69
|
+
}, 0);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
protected _createPersister(options?: QueryMetaPersister | boolean) {
|
|
74
|
+
options = this._adjustPersisterOptions(options);
|
|
75
|
+
if (!options) return undefined;
|
|
76
|
+
return experimental_createPersister({
|
|
77
|
+
storage: this._getPersisterStorage(options) as any,
|
|
78
|
+
maxAge: options.maxAge,
|
|
79
|
+
prefix: options.prefix,
|
|
80
|
+
buster: options.buster,
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
protected _adjustPersisterOptions(options?: QueryMetaPersister | boolean) {
|
|
85
|
+
if (options === false) return undefined;
|
|
86
|
+
if (options === undefined || options === true) {
|
|
87
|
+
options = {};
|
|
88
|
+
} else {
|
|
89
|
+
options = { ...options };
|
|
90
|
+
}
|
|
91
|
+
options.storage = options.storage ?? (options.sync ? 'local' : 'db');
|
|
92
|
+
options.maxAge =
|
|
93
|
+
options.maxAge ??
|
|
94
|
+
(options.sync ? this.scopeSelf.config.persister.sync.maxAge : this.scopeSelf.config.persister.async.maxAge);
|
|
95
|
+
options.prefix = options.prefix ?? this._getPersisterPrefix();
|
|
96
|
+
options.buster = options.buster ?? this._getPersisterBuster();
|
|
97
|
+
options.serialize = options.serialize ?? JSON.stringify;
|
|
98
|
+
options.deserialize = options.deserialize ?? JSON.parse;
|
|
99
|
+
return options;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
protected _getPersisterStorageKey(options: QueryMetaPersister, query: Query) {
|
|
103
|
+
if (options.storage === 'cookie') return String(query.queryKey[query.queryKey.length - 1]);
|
|
104
|
+
return `${options.prefix}-${query.queryHash}`;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
protected _getPersisterStorage(options?: QueryMetaPersister | boolean) {
|
|
108
|
+
options = this._adjustPersisterOptions(options);
|
|
109
|
+
if (!options) return undefined;
|
|
110
|
+
if (options.storage === 'cookie') return cookieStorage;
|
|
111
|
+
if (options.storage === 'local') return localStorage;
|
|
112
|
+
if (options.storage === 'db') return localforage;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
protected _getPersisterPrefix() {
|
|
116
|
+
return `${this.app.config.env.appName}-query`;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
protected _getPersisterBuster() {
|
|
120
|
+
return this.app.config.env.appVersion;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
protected _forceQueryKeyPrefix(queryKey?: QueryKey): QueryKey {
|
|
124
|
+
if (!queryKey) queryKey = [];
|
|
125
|
+
const prefix = queryKey[0];
|
|
126
|
+
if (prefix && typeof prefix === 'string' && prefix.split('.').length === 3) return queryKey;
|
|
127
|
+
return [this[SymbolBeanFullName]].concat(queryKey as any);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import {
|
|
2
|
+
DataTag,
|
|
3
|
+
DefaultError,
|
|
4
|
+
InvalidateOptions,
|
|
5
|
+
InvalidateQueryFilters,
|
|
6
|
+
Query,
|
|
7
|
+
QueryFilters,
|
|
8
|
+
QueryKey,
|
|
9
|
+
SetDataOptions,
|
|
10
|
+
Updater,
|
|
11
|
+
} from '@tanstack/vue-query';
|
|
12
|
+
import { MaybeRefDeep, NoUnknown } from '../../common/types.js';
|
|
13
|
+
import { Cast } from 'zova';
|
|
14
|
+
import { BeanModelCookie } from './bean.model.cookie.js';
|
|
15
|
+
|
|
16
|
+
export class BeanModelQuery<TScopeModule = unknown> extends BeanModelCookie<TScopeModule> {
|
|
17
|
+
$setQueryData<
|
|
18
|
+
TQueryFnData,
|
|
19
|
+
TTaggedQueryKey extends QueryKey,
|
|
20
|
+
TData = TTaggedQueryKey extends DataTag<unknown, infer TaggedValue> ? TaggedValue : TQueryFnData,
|
|
21
|
+
>(
|
|
22
|
+
queryKey: TTaggedQueryKey,
|
|
23
|
+
updater: Updater<NoInfer<TData> | undefined, NoInfer<TData> | undefined>,
|
|
24
|
+
persisterSave?: boolean,
|
|
25
|
+
options?: MaybeRefDeep<SetDataOptions>,
|
|
26
|
+
): TData | undefined;
|
|
27
|
+
$setQueryData<TQueryFnData, TData = NoUnknown<TQueryFnData>>(
|
|
28
|
+
queryKey: MaybeRefDeep<QueryKey>,
|
|
29
|
+
updater: Updater<NoInfer<TData> | undefined, NoInfer<TData> | undefined>,
|
|
30
|
+
persisterSave?: boolean,
|
|
31
|
+
options?: MaybeRefDeep<SetDataOptions>,
|
|
32
|
+
): TData | undefined;
|
|
33
|
+
$setQueryData(queryKey, updater, persisterSave, options) {
|
|
34
|
+
queryKey = this._forceQueryKeyPrefix(queryKey);
|
|
35
|
+
const data = this.$queryClient.setQueryData(queryKey, updater, options);
|
|
36
|
+
if (persisterSave) {
|
|
37
|
+
this.$persisterSave(queryKey);
|
|
38
|
+
}
|
|
39
|
+
return data;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
$queryFind<TQueryFnData = unknown, TError = DefaultError, TData = TQueryFnData>(
|
|
43
|
+
filters: QueryFilters,
|
|
44
|
+
): Query<TQueryFnData, TError, TData> | undefined {
|
|
45
|
+
filters = { ...filters };
|
|
46
|
+
Cast(filters).queryKey = this._forceQueryKeyPrefix(Cast(filters).queryKey);
|
|
47
|
+
return this.$queryClient.getQueryCache().find(filters as any);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
$invalidateQueries(
|
|
51
|
+
filters?: MaybeRefDeep<InvalidateQueryFilters>,
|
|
52
|
+
options?: MaybeRefDeep<InvalidateOptions>,
|
|
53
|
+
): Promise<void> {
|
|
54
|
+
if (!filters) filters = {};
|
|
55
|
+
const queryKey = this._forceQueryKeyPrefix(Cast(filters).queryKey);
|
|
56
|
+
filters = { ...filters, queryKey };
|
|
57
|
+
return this.$queryClient.invalidateQueries(filters, options);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import {
|
|
2
|
+
DefaultError,
|
|
3
|
+
MutationObserverOptions,
|
|
4
|
+
QueryClient,
|
|
5
|
+
UseMutationReturnType,
|
|
6
|
+
useMutation,
|
|
7
|
+
} from '@tanstack/vue-query';
|
|
8
|
+
import { BeanModelUseQuery } from './bean.model.useQuery.js';
|
|
9
|
+
import { MaybeRefDeep } from '../../common/types.js';
|
|
10
|
+
import { UnwrapNestedRefs } from 'vue';
|
|
11
|
+
|
|
12
|
+
export class BeanModelUseMutation<TScopeModule = unknown> extends BeanModelUseQuery<TScopeModule> {
|
|
13
|
+
$useMutation<TData = unknown, TVariables = void, TContext = unknown>(
|
|
14
|
+
mutationOptions: MaybeRefDeep<MutationObserverOptions<TData, DefaultError, TVariables, TContext>>,
|
|
15
|
+
queryClient?: QueryClient,
|
|
16
|
+
): UnwrapNestedRefs<UseMutationReturnType<TData, DefaultError, TVariables, TContext>> {
|
|
17
|
+
return this.ctx.meta.util.instanceScope(() => {
|
|
18
|
+
return useMutation(mutationOptions, queryClient) as any;
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
import {
|
|
2
|
+
DefaultError,
|
|
3
|
+
QueryKey,
|
|
4
|
+
useQuery,
|
|
5
|
+
QueryClient,
|
|
6
|
+
UseQueryReturnType,
|
|
7
|
+
UseQueryDefinedReturnType,
|
|
8
|
+
UseQueryOptions,
|
|
9
|
+
Query,
|
|
10
|
+
hashKey,
|
|
11
|
+
} from '@tanstack/vue-query';
|
|
12
|
+
import { UnwrapNestedRefs } from 'vue';
|
|
13
|
+
import { useComputed } from 'zova';
|
|
14
|
+
import { DefinedInitialQueryOptions, UndefinedInitialQueryOptions } from '../../common/types.js';
|
|
15
|
+
import { BeanModelQuery } from './bean.model.query.js';
|
|
16
|
+
|
|
17
|
+
const SymbolUseQueries = Symbol('SymbolUseQueries');
|
|
18
|
+
|
|
19
|
+
export class BeanModelUseQuery<TScopeModule = unknown> extends BeanModelQuery<TScopeModule> {
|
|
20
|
+
[SymbolUseQueries]: Record<string, unknown> = {};
|
|
21
|
+
|
|
22
|
+
$useQuery<TQueryFnData = unknown, TError = DefaultError, TData = TQueryFnData, TQueryKey extends QueryKey = QueryKey>(
|
|
23
|
+
options: UndefinedInitialQueryOptions<TQueryFnData, TError, TData, TQueryKey>,
|
|
24
|
+
queryClient?: QueryClient,
|
|
25
|
+
): UnwrapNestedRefs<UseQueryReturnType<TData, TError>>;
|
|
26
|
+
$useQuery<TQueryFnData = unknown, TError = DefaultError, TData = TQueryFnData, TQueryKey extends QueryKey = QueryKey>(
|
|
27
|
+
options: DefinedInitialQueryOptions<TQueryFnData, TError, TData, TQueryKey>,
|
|
28
|
+
queryClient?: QueryClient,
|
|
29
|
+
): UnwrapNestedRefs<UseQueryDefinedReturnType<TData, TError>>;
|
|
30
|
+
$useQuery<TQueryFnData = unknown, TError = DefaultError, TData = TQueryFnData, TQueryKey extends QueryKey = QueryKey>(
|
|
31
|
+
options: UseQueryOptions<TQueryFnData, TError, TData, TQueryFnData, TQueryKey>,
|
|
32
|
+
queryClient?: QueryClient,
|
|
33
|
+
): UnwrapNestedRefs<UseQueryReturnType<TData, TError>>;
|
|
34
|
+
$useQuery(options, queryClient) {
|
|
35
|
+
const queryKey = this.self._forceQueryKeyPrefix(options.queryKey);
|
|
36
|
+
const persister = this._createPersister(options.meta?.persister);
|
|
37
|
+
options = { ...options, queryKey, persister };
|
|
38
|
+
return this.ctx.meta.util.instanceScope(() => {
|
|
39
|
+
return useQuery(options, queryClient);
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
$useQueryExisting<
|
|
44
|
+
TQueryFnData = unknown,
|
|
45
|
+
TError = DefaultError,
|
|
46
|
+
TData = TQueryFnData,
|
|
47
|
+
TQueryKey extends QueryKey = QueryKey,
|
|
48
|
+
>(
|
|
49
|
+
options: UndefinedInitialQueryOptions<TQueryFnData, TError, TData, TQueryKey>,
|
|
50
|
+
queryClient?: QueryClient,
|
|
51
|
+
): UnwrapNestedRefs<UseQueryReturnType<TData, TError>>;
|
|
52
|
+
$useQueryExisting<
|
|
53
|
+
TQueryFnData = unknown,
|
|
54
|
+
TError = DefaultError,
|
|
55
|
+
TData = TQueryFnData,
|
|
56
|
+
TQueryKey extends QueryKey = QueryKey,
|
|
57
|
+
>(
|
|
58
|
+
options: DefinedInitialQueryOptions<TQueryFnData, TError, TData, TQueryKey>,
|
|
59
|
+
queryClient?: QueryClient,
|
|
60
|
+
): UnwrapNestedRefs<UseQueryDefinedReturnType<TData, TError>>;
|
|
61
|
+
$useQueryExisting<
|
|
62
|
+
TQueryFnData = unknown,
|
|
63
|
+
TError = DefaultError,
|
|
64
|
+
TData = TQueryFnData,
|
|
65
|
+
TQueryKey extends QueryKey = QueryKey,
|
|
66
|
+
>(
|
|
67
|
+
options: UseQueryOptions<TQueryFnData, TError, TData, TQueryFnData, TQueryKey>,
|
|
68
|
+
queryClient?: QueryClient,
|
|
69
|
+
): UnwrapNestedRefs<UseQueryReturnType<TData, TError>>;
|
|
70
|
+
$useQueryExisting(options, queryClient) {
|
|
71
|
+
const queryKey = this.self._forceQueryKeyPrefix(options.queryKey);
|
|
72
|
+
const queryHash = hashKey(queryKey);
|
|
73
|
+
if (!this[SymbolUseQueries][queryHash]) {
|
|
74
|
+
this[SymbolUseQueries][queryHash] = this.$useQuery(options, queryClient);
|
|
75
|
+
}
|
|
76
|
+
return this[SymbolUseQueries][queryHash];
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
$useQueryLocal<
|
|
80
|
+
TQueryFnData = unknown,
|
|
81
|
+
TError = DefaultError,
|
|
82
|
+
TData = TQueryFnData,
|
|
83
|
+
TQueryKey extends QueryKey = QueryKey,
|
|
84
|
+
>(options: UndefinedInitialQueryOptions<TQueryFnData, TError, TData, TQueryKey>, queryClient?: QueryClient): TData;
|
|
85
|
+
$useQueryLocal<
|
|
86
|
+
TQueryFnData = unknown,
|
|
87
|
+
TError = DefaultError,
|
|
88
|
+
TData = TQueryFnData,
|
|
89
|
+
TQueryKey extends QueryKey = QueryKey,
|
|
90
|
+
>(options: DefinedInitialQueryOptions<TQueryFnData, TError, TData, TQueryKey>, queryClient?: QueryClient): TData;
|
|
91
|
+
$useQueryLocal<
|
|
92
|
+
TQueryFnData = unknown,
|
|
93
|
+
TError = DefaultError,
|
|
94
|
+
TData = TQueryFnData,
|
|
95
|
+
TQueryKey extends QueryKey = QueryKey,
|
|
96
|
+
>(options: UseQueryOptions<TQueryFnData, TError, TData, TQueryFnData, TQueryKey>, queryClient?: QueryClient): TData;
|
|
97
|
+
$useQueryLocal(options, queryClient) {
|
|
98
|
+
options = this.app.meta.util.extend({}, options, {
|
|
99
|
+
enabled: false,
|
|
100
|
+
staleTime: Infinity,
|
|
101
|
+
meta: {
|
|
102
|
+
persister: { storage: 'local', sync: true },
|
|
103
|
+
},
|
|
104
|
+
});
|
|
105
|
+
const queryKey = options.queryKey;
|
|
106
|
+
const self = this;
|
|
107
|
+
return useComputed({
|
|
108
|
+
get() {
|
|
109
|
+
const query = self.$useQuery(options, queryClient) as any;
|
|
110
|
+
if (query.data.value === undefined) {
|
|
111
|
+
const data = self.$persisterLoad(queryKey);
|
|
112
|
+
if (data !== undefined) {
|
|
113
|
+
self.$setQueryData(queryKey, data);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return query.data;
|
|
117
|
+
},
|
|
118
|
+
set(value) {
|
|
119
|
+
self.$setQueryData(queryKey, value, true);
|
|
120
|
+
},
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
$useQueryCookie<
|
|
125
|
+
TQueryFnData = unknown,
|
|
126
|
+
TError = DefaultError,
|
|
127
|
+
TData = TQueryFnData,
|
|
128
|
+
TQueryKey extends QueryKey = QueryKey,
|
|
129
|
+
>(options: UndefinedInitialQueryOptions<TQueryFnData, TError, TData, TQueryKey>, queryClient?: QueryClient): TData;
|
|
130
|
+
$useQueryCookie<
|
|
131
|
+
TQueryFnData = unknown,
|
|
132
|
+
TError = DefaultError,
|
|
133
|
+
TData = TQueryFnData,
|
|
134
|
+
TQueryKey extends QueryKey = QueryKey,
|
|
135
|
+
>(options: DefinedInitialQueryOptions<TQueryFnData, TError, TData, TQueryKey>, queryClient?: QueryClient): TData;
|
|
136
|
+
$useQueryCookie<
|
|
137
|
+
TQueryFnData = unknown,
|
|
138
|
+
TError = DefaultError,
|
|
139
|
+
TData = TQueryFnData,
|
|
140
|
+
TQueryKey extends QueryKey = QueryKey,
|
|
141
|
+
>(options: UseQueryOptions<TQueryFnData, TError, TData, TQueryFnData, TQueryKey>, queryClient?: QueryClient): TData;
|
|
142
|
+
$useQueryCookie(options, queryClient) {
|
|
143
|
+
options = this.app.meta.util.extend(
|
|
144
|
+
{
|
|
145
|
+
meta: {
|
|
146
|
+
persister: {
|
|
147
|
+
serialize: (obj?: Query) => {
|
|
148
|
+
return this.$serializeCookie(obj);
|
|
149
|
+
},
|
|
150
|
+
deserialize: (value?: string) => {
|
|
151
|
+
return this.$deserializeCookie(value);
|
|
152
|
+
},
|
|
153
|
+
},
|
|
154
|
+
},
|
|
155
|
+
},
|
|
156
|
+
options,
|
|
157
|
+
{
|
|
158
|
+
enabled: false,
|
|
159
|
+
staleTime: Infinity,
|
|
160
|
+
meta: {
|
|
161
|
+
persister: { storage: 'cookie', sync: true },
|
|
162
|
+
},
|
|
163
|
+
},
|
|
164
|
+
);
|
|
165
|
+
const queryKey = options.queryKey;
|
|
166
|
+
const self = this;
|
|
167
|
+
return useComputed({
|
|
168
|
+
get() {
|
|
169
|
+
const query = self.$useQuery(options, queryClient) as any;
|
|
170
|
+
if (query.data.value === undefined) {
|
|
171
|
+
const data = self.$persisterLoad(queryKey);
|
|
172
|
+
if (data !== undefined) {
|
|
173
|
+
self.$setQueryData(queryKey, data);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
return query.data;
|
|
177
|
+
},
|
|
178
|
+
set(value) {
|
|
179
|
+
self.$setQueryData(queryKey, value, true);
|
|
180
|
+
},
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
$useQueryMem<
|
|
185
|
+
TQueryFnData = unknown,
|
|
186
|
+
TError = DefaultError,
|
|
187
|
+
TData = TQueryFnData,
|
|
188
|
+
TQueryKey extends QueryKey = QueryKey,
|
|
189
|
+
>(options: UndefinedInitialQueryOptions<TQueryFnData, TError, TData, TQueryKey>, queryClient?: QueryClient): TData;
|
|
190
|
+
$useQueryMem<
|
|
191
|
+
TQueryFnData = unknown,
|
|
192
|
+
TError = DefaultError,
|
|
193
|
+
TData = TQueryFnData,
|
|
194
|
+
TQueryKey extends QueryKey = QueryKey,
|
|
195
|
+
>(options: DefinedInitialQueryOptions<TQueryFnData, TError, TData, TQueryKey>, queryClient?: QueryClient): TData;
|
|
196
|
+
$useQueryMem<
|
|
197
|
+
TQueryFnData = unknown,
|
|
198
|
+
TError = DefaultError,
|
|
199
|
+
TData = TQueryFnData,
|
|
200
|
+
TQueryKey extends QueryKey = QueryKey,
|
|
201
|
+
>(options: UseQueryOptions<TQueryFnData, TError, TData, TQueryFnData, TQueryKey>, queryClient?: QueryClient): TData;
|
|
202
|
+
$useQueryMem(options, queryClient) {
|
|
203
|
+
options = this.app.meta.util.extend({}, options, {
|
|
204
|
+
enabled: false,
|
|
205
|
+
staleTime: Infinity,
|
|
206
|
+
meta: {
|
|
207
|
+
persister: false,
|
|
208
|
+
},
|
|
209
|
+
});
|
|
210
|
+
const queryKey = options.queryKey;
|
|
211
|
+
const self = this;
|
|
212
|
+
return useComputed({
|
|
213
|
+
get() {
|
|
214
|
+
const query = self.$useQuery(options, queryClient) as any;
|
|
215
|
+
return query.data;
|
|
216
|
+
},
|
|
217
|
+
set(value) {
|
|
218
|
+
self.$setQueryData(queryKey, value, false);
|
|
219
|
+
},
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import Cookies from 'js-cookie';
|
|
2
|
+
|
|
3
|
+
export const cookieStorage = {
|
|
4
|
+
getItem(key: string): string | undefined {
|
|
5
|
+
return Cookies.get(key);
|
|
6
|
+
},
|
|
7
|
+
setItem(key: string, value: string): void {
|
|
8
|
+
Cookies.set(key, value);
|
|
9
|
+
},
|
|
10
|
+
removeItem(key: string): void {
|
|
11
|
+
Cookies.remove(key);
|
|
12
|
+
},
|
|
13
|
+
};
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { DefaultError, QueryKey, UseQueryOptions } from '@tanstack/vue-query';
|
|
2
|
+
import { Ref, UnwrapRef } from 'vue';
|
|
3
|
+
import { Functionable } from 'zova';
|
|
4
|
+
|
|
5
|
+
export type NonUndefinedGuard<T> = T extends undefined ? never : T;
|
|
6
|
+
|
|
7
|
+
export type UndefinedInitialQueryOptions<
|
|
8
|
+
TQueryFnData = unknown,
|
|
9
|
+
TError = DefaultError,
|
|
10
|
+
TData = TQueryFnData,
|
|
11
|
+
TQueryKey extends QueryKey = QueryKey,
|
|
12
|
+
> = UseQueryOptions<TQueryFnData, TError, TData, TQueryFnData, TQueryKey> & {
|
|
13
|
+
initialData?: undefined;
|
|
14
|
+
};
|
|
15
|
+
export type DefinedInitialQueryOptions<
|
|
16
|
+
TQueryFnData = unknown,
|
|
17
|
+
TError = DefaultError,
|
|
18
|
+
TData = TQueryFnData,
|
|
19
|
+
TQueryKey extends QueryKey = QueryKey,
|
|
20
|
+
> = UseQueryOptions<TQueryFnData, TError, TData, TQueryFnData, TQueryKey> & {
|
|
21
|
+
initialData: NonUndefinedGuard<TQueryFnData> | (() => NonUndefinedGuard<TQueryFnData>);
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export type Primitive = string | number | boolean | bigint | symbol | undefined | null;
|
|
25
|
+
export type UnwrapLeaf =
|
|
26
|
+
| Primitive
|
|
27
|
+
| Functionable
|
|
28
|
+
| Date
|
|
29
|
+
| Error
|
|
30
|
+
| RegExp
|
|
31
|
+
| Map<any, any>
|
|
32
|
+
| WeakMap<any, any>
|
|
33
|
+
| Set<any>
|
|
34
|
+
| WeakSet<any>;
|
|
35
|
+
export type MaybeRef<T> = Ref<T> | T;
|
|
36
|
+
export type MaybeRefOrGetter<T> = MaybeRef<T> | (() => T);
|
|
37
|
+
export type MaybeRefDeep<T> = MaybeRef<
|
|
38
|
+
T extends Functionable
|
|
39
|
+
? T
|
|
40
|
+
: T extends object
|
|
41
|
+
? {
|
|
42
|
+
[Property in keyof T]: MaybeRefDeep<T[Property]>;
|
|
43
|
+
}
|
|
44
|
+
: T
|
|
45
|
+
>;
|
|
46
|
+
export type NoUnknown<T> = Equal<unknown, T> extends true ? never : T;
|
|
47
|
+
export type Equal<TTargetA, TTargetB> =
|
|
48
|
+
(<T>() => T extends TTargetA ? 1 : 2) extends <T>() => T extends TTargetB ? 1 : 2 ? true : false;
|
|
49
|
+
export type DeepUnwrapRef<T> = T extends UnwrapLeaf
|
|
50
|
+
? T
|
|
51
|
+
: T extends Ref<infer U>
|
|
52
|
+
? DeepUnwrapRef<U>
|
|
53
|
+
: T extends {}
|
|
54
|
+
? {
|
|
55
|
+
[Property in keyof T]: DeepUnwrapRef<T[Property]>;
|
|
56
|
+
}
|
|
57
|
+
: UnwrapRef<T>;
|
|
58
|
+
export type DistributiveOmit<T, TKeyOfAny extends keyof any> = T extends any ? Omit<T, TKeyOfAny> : never;
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const constants = null;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export enum Errors {}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default {};
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { BeanBase, Local } from 'zova';
|
|
2
|
+
import { ScopeModule } from '../resource/this.js';
|
|
3
|
+
import { VueQueryPlugin, VueQueryPluginOptions, defaultShouldDehydrateQuery } from '@tanstack/vue-query';
|
|
4
|
+
|
|
5
|
+
@Local()
|
|
6
|
+
export class Storage extends BeanBase<ScopeModule> {
|
|
7
|
+
protected async __init__() {
|
|
8
|
+
const vueQueryPluginOptions: VueQueryPluginOptions = {
|
|
9
|
+
queryClientConfig: {
|
|
10
|
+
defaultOptions: {
|
|
11
|
+
queries: {
|
|
12
|
+
retry: false,
|
|
13
|
+
refetchOnWindowFocus: false,
|
|
14
|
+
refetchOnMount: false,
|
|
15
|
+
refetchOnReconnect: false,
|
|
16
|
+
// gcTime: 1000 * 60 * 5,
|
|
17
|
+
},
|
|
18
|
+
dehydrate: {
|
|
19
|
+
shouldDehydrateQuery(query) {
|
|
20
|
+
if (query.meta?.ssr?.dehydrate === false) return false;
|
|
21
|
+
return defaultShouldDehydrateQuery(query);
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
this.app.vue.use(VueQueryPlugin, vueQueryPluginOptions);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
protected __dispose__() {}
|
|
31
|
+
}
|
package/src/monkey.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { BeanBase, BeanContainer, BeanSimple, IMonkeySystem } from 'zova';
|
|
2
|
+
import { Storage } from './local/storage.js';
|
|
3
|
+
import { useQueryClient } from '@tanstack/vue-query';
|
|
4
|
+
import { markRaw } from 'vue';
|
|
5
|
+
|
|
6
|
+
export class Monkey extends BeanSimple implements IMonkeySystem {
|
|
7
|
+
storage: Storage;
|
|
8
|
+
|
|
9
|
+
async appInitialize(bean: BeanContainer) {
|
|
10
|
+
// storage
|
|
11
|
+
this.storage = await bean._newBean(Storage, false);
|
|
12
|
+
}
|
|
13
|
+
async appInitialized(_bean: BeanContainer) {}
|
|
14
|
+
|
|
15
|
+
async beanInit(bean: BeanContainer, beanInstance: BeanBase) {
|
|
16
|
+
bean.defineProperty(beanInstance, '$queryClient', {
|
|
17
|
+
enumerable: false,
|
|
18
|
+
configurable: true,
|
|
19
|
+
get() {
|
|
20
|
+
return markRaw(useQueryClient());
|
|
21
|
+
},
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
async beanInited(_bean: BeanContainer, _beanInstance: BeanBase) {}
|
|
25
|
+
beanDispose(_bean: BeanContainer, _beanInstance: BeanBase) {}
|
|
26
|
+
beanDisposed(_bean: BeanContainer, _beanInstance: BeanBase) {}
|
|
27
|
+
}
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const components = {};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { BeanScopeBase, Scope, TypeLocaleBase, TypeModuleResource } from 'zova';
|
|
2
|
+
import { config, Errors, locales, constants } from '../config/index.js';
|
|
3
|
+
import { components } from './components.js';
|
|
4
|
+
import { services } from '../api/service/index.js';
|
|
5
|
+
|
|
6
|
+
@Scope()
|
|
7
|
+
export class ScopeModuleAModel extends BeanScopeBase {}
|
|
8
|
+
|
|
9
|
+
export interface ScopeModuleAModel
|
|
10
|
+
extends TypeModuleResource<
|
|
11
|
+
typeof components,
|
|
12
|
+
typeof config,
|
|
13
|
+
typeof Errors,
|
|
14
|
+
(typeof locales)[TypeLocaleBase],
|
|
15
|
+
typeof constants,
|
|
16
|
+
typeof services
|
|
17
|
+
> {}
|
|
18
|
+
|
|
19
|
+
import 'zova';
|
|
20
|
+
declare module 'zova' {
|
|
21
|
+
export interface IBeanScopeRecord {
|
|
22
|
+
'a-model': ScopeModuleAModel;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface IBeanScopeConfig {
|
|
26
|
+
'a-model': ReturnType<typeof config>;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface IBeanScopeLocale {
|
|
30
|
+
'a-model': (typeof locales)[TypeLocaleBase];
|
|
31
|
+
}
|
|
32
|
+
}
|
package/src/routes.ts
ADDED
package/src/types.ts
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import 'zova';
|
|
2
|
+
import { DefaultError, useMutation, useQuery, useQueryClient } from '@tanstack/vue-query';
|
|
3
|
+
import { UnwrapNestedRefs } from 'vue';
|
|
4
|
+
declare module 'zova' {
|
|
5
|
+
export interface BeanBase {
|
|
6
|
+
$queryClient: ReturnType<typeof useQueryClient>;
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
declare module '@tanstack/vue-query' {
|
|
11
|
+
export interface Register {
|
|
12
|
+
queryMeta: MyQueryMeta;
|
|
13
|
+
mutationMeta: MyQueryMeta;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface MyQueryMeta extends Record<string, unknown> {
|
|
18
|
+
ssr?: QueryMetaSSR;
|
|
19
|
+
persister?: QueryMetaPersister | boolean;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface QueryMetaSSR {
|
|
23
|
+
/** default is true */
|
|
24
|
+
dehydrate?: boolean;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export type QueryMetaPersisterStorage = 'cookie' | 'local' | 'db' | undefined;
|
|
28
|
+
|
|
29
|
+
export interface QueryMetaPersister {
|
|
30
|
+
/** default is false */
|
|
31
|
+
sync?: boolean;
|
|
32
|
+
/** default is db if async, local if sync */
|
|
33
|
+
storage?: QueryMetaPersisterStorage;
|
|
34
|
+
/** default is 24 hours */
|
|
35
|
+
maxAge?: number;
|
|
36
|
+
/**
|
|
37
|
+
* How to serialize the data to storage.
|
|
38
|
+
* @default `JSON.stringify`
|
|
39
|
+
*/
|
|
40
|
+
serialize?: (persistedQuery: any) => any;
|
|
41
|
+
/**
|
|
42
|
+
* How to deserialize the data from storage.
|
|
43
|
+
* @default `JSON.parse`
|
|
44
|
+
*/
|
|
45
|
+
deserialize?: (cachedString: any) => any;
|
|
46
|
+
prefix?: string;
|
|
47
|
+
buster?: string;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export type DataQuery<TData> = UnwrapNestedRefs<ReturnType<typeof useQuery<TData | undefined, Error | null>>>;
|
|
51
|
+
|
|
52
|
+
export type DataMutation<TData = unknown, TVariables = void, TContext = unknown> = UnwrapNestedRefs<
|
|
53
|
+
ReturnType<typeof useMutation<TData, DefaultError, TVariables, TContext>>
|
|
54
|
+
>;
|
package/src/typings.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|