@bg-dev/nuxt-zenstack 0.0.2 → 0.0.4
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/module.d.mts +2 -0
- package/dist/module.json +1 -1
- package/dist/module.mjs +29 -14
- package/dist/runtime/composables/common.d.ts +6 -8
- package/dist/runtime/composables/common.js +7 -0
- package/dist/runtime/composables/index.d.ts +1 -0
- package/dist/runtime/composables/index.js +1 -0
- package/dist/runtime/composables/useZenstackCreate/index.d.ts +3 -3
- package/dist/runtime/composables/useZenstackCreate/index.js +10 -8
- package/dist/runtime/composables/useZenstackDelete/index.d.ts +3 -3
- package/dist/runtime/composables/useZenstackDelete/index.js +9 -4
- package/dist/runtime/composables/useZenstackRead/index.d.ts +7 -7
- package/dist/runtime/composables/useZenstackRead/index.js +38 -29
- package/dist/runtime/composables/useZenstackReadMany/index.d.ts +9 -8
- package/dist/runtime/composables/useZenstackReadMany/index.js +54 -34
- package/dist/runtime/composables/useZenstackReadMany/orderBy.d.ts +5 -0
- package/dist/runtime/composables/useZenstackReadMany/orderBy.js +25 -0
- package/dist/runtime/composables/useZenstackReadMany/where.d.ts +2 -0
- package/dist/runtime/composables/useZenstackReadMany/where.js +235 -0
- package/dist/runtime/composables/useZenstackStore/helpers.js +4 -4
- package/dist/runtime/composables/useZenstackStore/index.d.ts +34 -2
- package/dist/runtime/composables/useZenstackStore/index.js +27 -6
- package/dist/runtime/composables/useZenstackStore/normalization.d.ts +16 -3
- package/dist/runtime/composables/useZenstackStore/normalization.js +16 -3
- package/dist/runtime/composables/useZenstackUpdate/index.d.ts +2 -2
- package/dist/runtime/composables/useZenstackUpdate/index.js +10 -8
- package/dist/runtime/server/api/models/[model]/[id].delete.js +4 -1
- package/dist/runtime/server/api/models/[model]/[id].get.js +4 -1
- package/dist/runtime/server/api/models/[model]/[id].patch.js +10 -5
- package/dist/runtime/server/api/models/[model]/index.get.js +4 -1
- package/dist/runtime/server/api/models/[model]/index.post.js +10 -5
- package/dist/runtime/server/utils/error.d.ts +9 -0
- package/dist/runtime/server/utils/error.js +49 -0
- package/dist/runtime/server/utils/index.d.ts +5 -8
- package/dist/runtime/server/utils/index.js +27 -10
- package/dist/runtime/server/utils/parsers.d.ts +2 -2
- package/dist/runtime/server/utils/parsers.js +2 -2
- package/package.json +3 -1
package/dist/module.d.mts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import * as _nuxt_schema from '@nuxt/schema';
|
|
2
|
+
import { FetchPolicy } from '../dist/runtime/composables/common.js';
|
|
2
3
|
|
|
3
4
|
interface ModuleOptions {
|
|
4
5
|
apiPath: string;
|
|
6
|
+
fetchPolicy: FetchPolicy;
|
|
5
7
|
}
|
|
6
8
|
declare const _default: _nuxt_schema.NuxtModule<ModuleOptions, ModuleOptions, false>;
|
|
7
9
|
|
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { defineNuxtModule, createResolver,
|
|
1
|
+
import { defineNuxtModule, createResolver, addTemplate, addServerTemplate, addTypeTemplate, addServerHandler, addImportsDir } from '@nuxt/kit';
|
|
2
2
|
import { joinURL } from 'ufo';
|
|
3
3
|
import { defu } from 'defu';
|
|
4
4
|
|
|
5
5
|
const name = "@bg-dev/nuxt-zenstack";
|
|
6
|
-
const version = "0.0.
|
|
6
|
+
const version = "0.0.4";
|
|
7
7
|
|
|
8
8
|
const module$1 = defineNuxtModule({
|
|
9
9
|
meta: {
|
|
@@ -13,20 +13,17 @@ const module$1 = defineNuxtModule({
|
|
|
13
13
|
},
|
|
14
14
|
// Default configuration options of the Nuxt module
|
|
15
15
|
defaults: {
|
|
16
|
-
apiPath: "/api/_zenstack"
|
|
16
|
+
apiPath: "/api/_zenstack",
|
|
17
|
+
fetchPolicy: "cache-first"
|
|
17
18
|
},
|
|
18
19
|
setup(_options, _nuxt) {
|
|
19
20
|
_nuxt.options.runtimeConfig.public = defu(_nuxt.options.runtimeConfig.public, {
|
|
20
21
|
zenstack: {
|
|
21
|
-
apiPath: _options.apiPath
|
|
22
|
+
apiPath: _options.apiPath,
|
|
23
|
+
fetchPolicy: _options.fetchPolicy
|
|
22
24
|
}
|
|
23
25
|
});
|
|
24
26
|
const resolver = createResolver(import.meta.url);
|
|
25
|
-
addServerImports({
|
|
26
|
-
from: resolver.resolve("./runtime/server/utils"),
|
|
27
|
-
name: "provideClient",
|
|
28
|
-
as: "provideZenstackClient"
|
|
29
|
-
});
|
|
30
27
|
addTemplate({
|
|
31
28
|
write: true,
|
|
32
29
|
filename: "nuxt-zenstack.mjs",
|
|
@@ -43,9 +40,11 @@ export { schema as zenstackSchema } from '~~/zenstack/schema'
|
|
|
43
40
|
addTypeTemplate({
|
|
44
41
|
filename: "types/nuxt-zenstack.d.ts",
|
|
45
42
|
getContents: () => `
|
|
46
|
-
import type { ModelOperations, ModelResult, IncludeInput, WhereInput, FindManyArgs, SimplifiedPlainResult, SelectIncludeOmit, QueryOptions, CreateArgs, UpdateArgs } from '@zenstackhq/orm'
|
|
43
|
+
import type { ClientContract, ModelOperations, ModelResult, IncludeInput, WhereInput, FindManyArgs, SimplifiedPlainResult, SelectIncludeOmit, QueryOptions, CreateArgs, UpdateArgs } from '@zenstackhq/orm'
|
|
47
44
|
import type { SchemaType } from '~~/zenstack/schema'
|
|
48
45
|
import type { ModelDef } from '@zenstackhq/orm/schema'
|
|
46
|
+
import type { H3Error } from 'h3'
|
|
47
|
+
import { ORMError, RejectedByPolicyReason, ORMErrorReason } from '@zenstackhq/orm'
|
|
49
48
|
|
|
50
49
|
type ItemGetPayload<Zmodel extends $Zmodel, Args extends SelectIncludeOmit<SchemaType, Zmodel, true>, Options extends QueryOptions<SchemaType> = QueryOptions<SchemaType>> = SimplifiedPlainResult<SchemaType, Zmodel, Args, Options>
|
|
51
50
|
|
|
@@ -54,12 +53,28 @@ export type $Zmodel = keyof SchemaType['models']
|
|
|
54
53
|
export type $Zdef = ModelDef
|
|
55
54
|
export type $Zoperations<Zmodel extends $Zmodel> = ModelOperations<SchemaType, Zmodel>
|
|
56
55
|
export type $Zid<Zmodel extends $Zmodel> = ModelResult<SchemaType, Zmodel> extends { id: infer Id } ? Id : never
|
|
57
|
-
export type $Zinclude<Zmodel extends $Zmodel> = IncludeInput<SchemaType, Zmodel>
|
|
58
|
-
export type $Zitem<Zmodel extends $Zmodel, Zinclude extends $Zinclude
|
|
59
|
-
export type $Zwhere<Zmodel extends $Zmodel> = WhereInput<SchemaType, Zmodel>
|
|
60
|
-
export type $ZorderBy<Zmodel extends $Zmodel> = FindManyArgs<SchemaType, Zmodel>['orderBy']
|
|
56
|
+
export type $Zinclude<Zmodel extends $Zmodel> = IncludeInput<SchemaType, Zmodel> | undefined
|
|
57
|
+
export type $Zitem<Zmodel extends $Zmodel, Zinclude extends $Zinclude = undefined> = ItemGetPayload<Zmodel, { include: Zinclude }>
|
|
58
|
+
export type $Zwhere<Zmodel extends $Zmodel> = WhereInput<SchemaType, Zmodel> | undefined
|
|
59
|
+
export type $ZorderBy<Zmodel extends $Zmodel> = FindManyArgs<SchemaType, Zmodel>['orderBy'] | undefined
|
|
61
60
|
export type $ZcreateData<Zmodel extends $Zmodel> = CreateArgs<SchemaType, Zmodel>['data']
|
|
62
61
|
export type $ZupdateData<Zmodel extends $Zmodel> = UpdateArgs<SchemaType, Zmodel>['data']
|
|
62
|
+
export type $ZormError = ORMError
|
|
63
|
+
export type $Zerror = H3Error<{
|
|
64
|
+
ormErrorReason: ORMErrorReason
|
|
65
|
+
dbErrorCode?: unknown
|
|
66
|
+
dbErrorMessage?: string
|
|
67
|
+
model?: string
|
|
68
|
+
rejectedByPolicyReason?: RejectedByPolicyReason
|
|
69
|
+
}>
|
|
70
|
+
|
|
71
|
+
declare module 'h3' {
|
|
72
|
+
interface H3EventContext {
|
|
73
|
+
zenstack: {
|
|
74
|
+
client: ClientContract<SchemaType>
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
63
78
|
`
|
|
64
79
|
});
|
|
65
80
|
addServerHandler({
|
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
export type Status = 'idle' | 'pending' | 'success' | 'error';
|
|
2
2
|
export type FetchPolicy = 'cache-first' | 'fetch-only' | 'cache-only' | 'cache-and-fetch';
|
|
3
|
-
export type Error = {
|
|
4
|
-
error: boolean;
|
|
5
|
-
url: string;
|
|
6
|
-
statusCode: number;
|
|
7
|
-
statusMessage: string;
|
|
8
|
-
message: string;
|
|
9
|
-
stack?: string[];
|
|
10
|
-
};
|
|
11
3
|
export declare function getConfig(): {
|
|
12
4
|
apiPath: string;
|
|
5
|
+
fetchPolicy: FetchPolicy;
|
|
13
6
|
};
|
|
7
|
+
/**
|
|
8
|
+
* @param instance a custom fetch method created by `$fetch.create`
|
|
9
|
+
*/
|
|
10
|
+
export declare function provideFetch(instance: typeof $fetch): void;
|
|
11
|
+
export declare function getFetch(): import("nitropack/types").$Fetch<unknown, import("nitropack/types").NitroFetchRequest>;
|
|
@@ -3,3 +3,4 @@ export { useZenstackReadMany } from './useZenstackReadMany/index.js';
|
|
|
3
3
|
export { useZenstackRead } from './useZenstackRead/index.js';
|
|
4
4
|
export { useZenstackDelete } from './useZenstackDelete/index.js';
|
|
5
5
|
export { useZenstackUpdate } from './useZenstackUpdate/index.js';
|
|
6
|
+
export { provideFetch as provideZenstackFetch } from './common.js';
|
|
@@ -3,3 +3,4 @@ export { useZenstackReadMany } from "./useZenstackReadMany/index.js";
|
|
|
3
3
|
export { useZenstackRead } from "./useZenstackRead/index.js";
|
|
4
4
|
export { useZenstackDelete } from "./useZenstackDelete/index.js";
|
|
5
5
|
export { useZenstackUpdate } from "./useZenstackUpdate/index.js";
|
|
6
|
+
export { provideFetch as provideZenstackFetch } from "./common.js";
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import type { $Zmodel, $Zitem, $ZcreateData } from '#build/types/nuxt-zenstack';
|
|
2
|
-
import type { Status
|
|
1
|
+
import type { $Zmodel, $Zitem, $ZcreateData, $Zerror } from '#build/types/nuxt-zenstack';
|
|
2
|
+
import type { Status } from '../common.js';
|
|
3
3
|
import { type Ref } from '#imports';
|
|
4
4
|
export declare function useZenstackCreate<Zmodel extends $Zmodel, Zitem extends $Zitem<Zmodel>>(model: Zmodel): {
|
|
5
5
|
data: Ref<Zitem | null>;
|
|
6
|
-
error: Ref
|
|
6
|
+
error: Ref<$Zerror | null>;
|
|
7
7
|
status: Ref<Status>;
|
|
8
8
|
mutate: (input: $ZcreateData<Zmodel>) => Promise<void>;
|
|
9
9
|
reset: () => void;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getConfig } from "../common.js";
|
|
1
|
+
import { getConfig, getFetch } from "../common.js";
|
|
2
2
|
import { ref } from "#imports";
|
|
3
3
|
import { joinURL } from "ufo";
|
|
4
4
|
import { useZenstackStore } from "../useZenstackStore/index.js";
|
|
@@ -14,17 +14,19 @@ export function useZenstackCreate(model) {
|
|
|
14
14
|
status.value = "idle";
|
|
15
15
|
}
|
|
16
16
|
async function mutate(input) {
|
|
17
|
+
const _fetch = getFetch();
|
|
17
18
|
const url = joinURL(config.apiPath, `/models/${model.toString()}`);
|
|
19
|
+
const method = "POST";
|
|
20
|
+
const body = { data: input };
|
|
21
|
+
store.addToFetchHistory({
|
|
22
|
+
model: model.toString(),
|
|
23
|
+
method,
|
|
24
|
+
body: JSON.stringify(body)
|
|
25
|
+
});
|
|
18
26
|
reset();
|
|
19
27
|
status.value = "pending";
|
|
20
28
|
try {
|
|
21
|
-
const res = await
|
|
22
|
-
method: "POST",
|
|
23
|
-
body: {
|
|
24
|
-
data: input
|
|
25
|
-
// TODO: maybe include relations
|
|
26
|
-
}
|
|
27
|
-
});
|
|
29
|
+
const res = await _fetch(url, { method, body });
|
|
28
30
|
if (res.data)
|
|
29
31
|
store.setOne(model, res.data);
|
|
30
32
|
data.value = res.data;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import type { $Zmodel, $Zitem, $Zid } from '#build/types/nuxt-zenstack';
|
|
2
|
-
import type { Status
|
|
1
|
+
import type { $Zmodel, $Zitem, $Zid, $Zerror } from '#build/types/nuxt-zenstack';
|
|
2
|
+
import type { Status } from '../common.js';
|
|
3
3
|
import { type Ref } from '#imports';
|
|
4
4
|
export declare function useZenstackDelete<Zmodel extends $Zmodel, Zitem extends $Zitem<Zmodel>>(model: Zmodel): {
|
|
5
5
|
data: Ref<Zitem | null>;
|
|
6
|
-
error: Ref
|
|
6
|
+
error: Ref<$Zerror | null>;
|
|
7
7
|
status: Ref<Status>;
|
|
8
8
|
mutate: (id: $Zid<Zmodel>) => Promise<void>;
|
|
9
9
|
reset: () => void;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ref } from "#imports";
|
|
2
2
|
import { joinURL } from "ufo";
|
|
3
3
|
import { useZenstackStore } from "../useZenstackStore/index.js";
|
|
4
|
-
import { getConfig } from "../common.js";
|
|
4
|
+
import { getConfig, getFetch } from "../common.js";
|
|
5
5
|
export function useZenstackDelete(model) {
|
|
6
6
|
const data = ref(null);
|
|
7
7
|
const error = ref(null);
|
|
@@ -14,13 +14,18 @@ export function useZenstackDelete(model) {
|
|
|
14
14
|
status.value = "idle";
|
|
15
15
|
}
|
|
16
16
|
async function mutate(id) {
|
|
17
|
+
const _fetch = getFetch();
|
|
17
18
|
const url = joinURL(config.apiPath, `/models/${model.toString()}/${id}`);
|
|
19
|
+
const method = "DELETE";
|
|
20
|
+
store.addToFetchHistory({
|
|
21
|
+
model: model.toString(),
|
|
22
|
+
id,
|
|
23
|
+
method
|
|
24
|
+
});
|
|
18
25
|
reset();
|
|
19
26
|
status.value = "pending";
|
|
20
27
|
try {
|
|
21
|
-
const res = await
|
|
22
|
-
method: "DELETE"
|
|
23
|
-
});
|
|
28
|
+
const res = await _fetch(url, { method });
|
|
24
29
|
store.deleteOne(model, id);
|
|
25
30
|
data.value = res.data;
|
|
26
31
|
status.value = "success";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type { $Zmodel, $Zitem, $Zid, $Zinclude } from '#build/types/nuxt-zenstack';
|
|
1
|
+
import type { $Zmodel, $Zitem, $Zid, $Zinclude, $Zerror } from '#build/types/nuxt-zenstack';
|
|
2
2
|
import type { Status, FetchPolicy } from '../common.js';
|
|
3
|
-
import type { Ref
|
|
4
|
-
type Options<
|
|
3
|
+
import type { Ref } from '#imports';
|
|
4
|
+
type Options<Zinclude> = {
|
|
5
5
|
/**
|
|
6
6
|
* - `cache-first` means that the query will first try to fetch the data from the store. If the data is not found in the store, it will fetch the data from the server and update the store.
|
|
7
7
|
* - `cache-and-fetch` means that the query will first try to fetch the data from the cache. It will then fetch the data from the server and update the cache.
|
|
@@ -19,12 +19,12 @@ type Options<Zmodel extends $Zmodel> = {
|
|
|
19
19
|
* The relations to include in the query.
|
|
20
20
|
* @default undefined
|
|
21
21
|
*/
|
|
22
|
-
include?:
|
|
22
|
+
include?: Zinclude;
|
|
23
23
|
};
|
|
24
|
-
export declare function useZenstackRead<Zmodel extends $Zmodel, Zitem extends $Zitem<Zmodel>>(model: Zmodel, id: $Zid<Zmodel>, opts?: Options<
|
|
24
|
+
export declare function useZenstackRead<Zmodel extends $Zmodel, Zinclude extends $Zinclude<Zmodel>, Zitem extends $Zitem<Zmodel, Zinclude>>(model: Zmodel, id: $Zid<Zmodel>, opts?: Options<Zinclude>): Promise<{
|
|
25
25
|
data: Ref<Zitem | null>;
|
|
26
|
-
error: Ref
|
|
26
|
+
error: Ref<$Zerror | null>;
|
|
27
27
|
status: Ref<Status>;
|
|
28
28
|
refetch: () => Promise<void>;
|
|
29
|
-
}
|
|
29
|
+
}>;
|
|
30
30
|
export {};
|
|
@@ -1,57 +1,66 @@
|
|
|
1
|
-
import { ref,
|
|
1
|
+
import { ref, watch, useNuxtApp } from "#imports";
|
|
2
2
|
import { joinURL } from "ufo";
|
|
3
3
|
import { useZenstackStore } from "../useZenstackStore/index.js";
|
|
4
4
|
import { stringify } from "superjson";
|
|
5
|
-
import { getConfig } from "../common.js";
|
|
6
|
-
export function useZenstackRead(model, id, opts = {}) {
|
|
5
|
+
import { getConfig, getFetch } from "../common.js";
|
|
6
|
+
export async function useZenstackRead(model, id, opts = {}) {
|
|
7
7
|
const data = ref(null);
|
|
8
8
|
const error = ref(null);
|
|
9
9
|
const status = ref("idle");
|
|
10
10
|
const store = useZenstackStore();
|
|
11
11
|
const config = getConfig();
|
|
12
|
-
|
|
12
|
+
const nuxtApp = useNuxtApp();
|
|
13
|
+
const method = "GET";
|
|
14
|
+
opts.fetchPolicy ??= config.fetchPolicy;
|
|
13
15
|
opts.immediate ??= true;
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
updateData();
|
|
17
|
-
if (data.value) opts.immediate = false;
|
|
18
|
-
break;
|
|
19
|
-
case "cache-and-fetch":
|
|
20
|
-
updateData();
|
|
21
|
-
break;
|
|
22
|
-
case "cache-only":
|
|
23
|
-
updateData();
|
|
24
|
-
opts.immediate = false;
|
|
25
|
-
break;
|
|
26
|
-
}
|
|
27
|
-
const watchedOptions = [opts.include].filter((option) => isRef(option) || typeof option === "function");
|
|
16
|
+
if (opts.fetchPolicy !== "fetch-only")
|
|
17
|
+
updateData();
|
|
28
18
|
watch(store.state, () => updateData());
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
19
|
+
if (shouldFetchInitially())
|
|
20
|
+
await refetch();
|
|
21
|
+
function canFetchAutomatically() {
|
|
22
|
+
const entry = store.fetchHistory.value.find((entry2) => entry2.model === model && entry2.id === id && entry2.method === method && entry2.query === JSON.stringify(getQuery()));
|
|
23
|
+
if (entry?.ssr && nuxtApp.isHydrating)
|
|
24
|
+
return false;
|
|
25
|
+
if (opts.fetchPolicy === "cache-first" && entry)
|
|
26
|
+
return false;
|
|
27
|
+
return true;
|
|
28
|
+
}
|
|
29
|
+
function shouldFetchInitially() {
|
|
30
|
+
if (opts.immediate === false)
|
|
31
|
+
return false;
|
|
32
|
+
return canFetchAutomatically();
|
|
33
|
+
}
|
|
32
34
|
function updateData() {
|
|
33
35
|
data.value = store.getOne(model, id);
|
|
34
36
|
}
|
|
37
|
+
function getQuery() {
|
|
38
|
+
const json = stringify({
|
|
39
|
+
include: opts.include
|
|
40
|
+
});
|
|
41
|
+
return { q: json };
|
|
42
|
+
}
|
|
35
43
|
async function refetch() {
|
|
36
44
|
if (opts.fetchPolicy === "cache-only")
|
|
37
45
|
return;
|
|
46
|
+
const _fetch = getFetch();
|
|
38
47
|
const url = joinURL(config.apiPath, `/models/${model.toString()}/${id}`);
|
|
39
|
-
const
|
|
40
|
-
|
|
48
|
+
const query = getQuery();
|
|
49
|
+
store.addToFetchHistory({
|
|
50
|
+
model: model.toString(),
|
|
51
|
+
id,
|
|
52
|
+
method,
|
|
53
|
+
query: JSON.stringify(query)
|
|
41
54
|
});
|
|
42
55
|
error.value = null;
|
|
43
56
|
status.value = "pending";
|
|
44
57
|
try {
|
|
45
|
-
const res = await
|
|
46
|
-
method: "GET",
|
|
47
|
-
query: {
|
|
48
|
-
q: json
|
|
49
|
-
}
|
|
50
|
-
});
|
|
58
|
+
const res = await _fetch(url, { method, query });
|
|
51
59
|
if (res.data)
|
|
52
60
|
store.setOne(model, res.data);
|
|
53
61
|
else
|
|
54
62
|
store.deleteOne(model, id);
|
|
63
|
+
updateData();
|
|
55
64
|
status.value = "success";
|
|
56
65
|
} catch (err) {
|
|
57
66
|
error.value = err.data;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type { $Zmodel, $Zitem, $Zinclude, $Zwhere, $ZorderBy } from '#build/types/nuxt-zenstack';
|
|
1
|
+
import type { $Zmodel, $Zitem, $Zinclude, $Zwhere, $ZorderBy, $Zerror } from '#build/types/nuxt-zenstack';
|
|
2
2
|
import type { Status, FetchPolicy } from '../common.js';
|
|
3
3
|
import type { MaybeRefOrGetter, Ref } from '#imports';
|
|
4
|
-
type Options<
|
|
4
|
+
type Options<Zinclude, Zwhere, ZorderBy> = {
|
|
5
5
|
/**
|
|
6
6
|
* - `cache-first` means that the query will first try to fetch the data from the store. If the data is not found in the store, it will fetch the data from the server and update the store.
|
|
7
7
|
* - `cache-and-fetch` means that the query will first try to fetch the data from the cache. It will then fetch the data from the server and update the cache.
|
|
@@ -19,17 +19,17 @@ type Options<Zmodel extends $Zmodel> = {
|
|
|
19
19
|
* The relations to include in the query.
|
|
20
20
|
* @default undefined
|
|
21
21
|
*/
|
|
22
|
-
include?:
|
|
22
|
+
include?: Zinclude;
|
|
23
23
|
/**
|
|
24
24
|
* The filter to apply to the query.
|
|
25
25
|
* @default undefined
|
|
26
26
|
*/
|
|
27
|
-
where?: MaybeRefOrGetter
|
|
27
|
+
where?: MaybeRefOrGetter<Zwhere>;
|
|
28
28
|
/**
|
|
29
29
|
* The order to apply to the query.
|
|
30
30
|
* @default undefined
|
|
31
31
|
*/
|
|
32
|
-
orderBy?: MaybeRefOrGetter
|
|
32
|
+
orderBy?: MaybeRefOrGetter<ZorderBy>;
|
|
33
33
|
/**
|
|
34
34
|
* The number of items to skip.
|
|
35
35
|
* @default 0
|
|
@@ -41,10 +41,11 @@ type Options<Zmodel extends $Zmodel> = {
|
|
|
41
41
|
*/
|
|
42
42
|
take?: MaybeRefOrGetter<number>;
|
|
43
43
|
};
|
|
44
|
-
export declare function useZenstackReadMany<Zmodel extends $Zmodel, Zitem extends $Zitem<Zmodel>>(model: Zmodel, opts?: Options<
|
|
44
|
+
export declare function useZenstackReadMany<Zmodel extends $Zmodel, Zinclude extends $Zinclude<Zmodel>, Zitem extends $Zitem<Zmodel, Zinclude>, Zwhere extends $Zwhere<Zmodel>, ZorderBy extends $ZorderBy<Zmodel>>(model: Zmodel, opts?: Options<Zinclude, Zwhere, ZorderBy>): Promise<{
|
|
45
45
|
data: Ref<Zitem[] | null>;
|
|
46
|
-
error: Ref
|
|
46
|
+
error: Ref<$Zerror | null>;
|
|
47
47
|
status: Ref<Status>;
|
|
48
|
+
canFetchMore: Ref<boolean>;
|
|
48
49
|
refetch: () => Promise<void>;
|
|
49
|
-
}
|
|
50
|
+
}>;
|
|
50
51
|
export {};
|
|
@@ -1,68 +1,88 @@
|
|
|
1
|
-
import { ref, toValue, watch, isRef } from "#imports";
|
|
1
|
+
import { ref, toValue, watch, isRef, useNuxtApp } from "#imports";
|
|
2
2
|
import { joinURL } from "ufo";
|
|
3
3
|
import { useZenstackStore } from "../useZenstackStore/index.js";
|
|
4
4
|
import { stringify } from "superjson";
|
|
5
|
-
import { getConfig } from "../common.js";
|
|
6
|
-
|
|
5
|
+
import { getConfig, getFetch } from "../common.js";
|
|
6
|
+
import { sort } from "./orderBy.js";
|
|
7
|
+
import { matchesWhere } from "./where.js";
|
|
8
|
+
export async function useZenstackReadMany(model, opts = {}) {
|
|
7
9
|
const data = ref(null);
|
|
8
10
|
const error = ref(null);
|
|
9
11
|
const status = ref("idle");
|
|
12
|
+
const canFetchMore = ref(true);
|
|
10
13
|
const store = useZenstackStore();
|
|
11
14
|
const config = getConfig();
|
|
12
|
-
|
|
15
|
+
const nuxtApp = useNuxtApp();
|
|
16
|
+
const watchedOptions = [opts.where, opts.orderBy, opts.skip, opts.take].filter((option) => isRef(option) || typeof option === "function");
|
|
17
|
+
const method = "GET";
|
|
18
|
+
opts.fetchPolicy ??= config.fetchPolicy;
|
|
13
19
|
opts.immediate ??= true;
|
|
14
20
|
opts.skip ??= 0;
|
|
15
21
|
opts.take ??= 1e3;
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
updateData();
|
|
19
|
-
if (data.value?.length) opts.immediate = false;
|
|
20
|
-
break;
|
|
21
|
-
case "cache-and-fetch":
|
|
22
|
-
updateData();
|
|
23
|
-
break;
|
|
24
|
-
case "cache-only":
|
|
25
|
-
updateData();
|
|
26
|
-
opts.immediate = false;
|
|
27
|
-
break;
|
|
28
|
-
}
|
|
29
|
-
const watchedOptions = [opts.include, opts.where, opts.orderBy, opts.skip, opts.take].filter((option) => isRef(option) || typeof option === "function");
|
|
22
|
+
if (opts.fetchPolicy !== "fetch-only")
|
|
23
|
+
updateData();
|
|
30
24
|
watch(store.state, () => updateData());
|
|
31
25
|
watch(watchedOptions, () => {
|
|
32
26
|
updateData();
|
|
33
|
-
|
|
27
|
+
if (canFetchAutomatically())
|
|
28
|
+
refetch();
|
|
34
29
|
});
|
|
35
|
-
if (
|
|
36
|
-
refetch();
|
|
30
|
+
if (shouldFetchInitially())
|
|
31
|
+
await refetch();
|
|
32
|
+
function canFetchAutomatically() {
|
|
33
|
+
const entry = store.fetchHistory.value.find((entry2) => entry2.model === model && entry2.method === method && entry2.query === JSON.stringify(getQuery()));
|
|
34
|
+
if (entry?.ssr && nuxtApp.isHydrating)
|
|
35
|
+
return false;
|
|
36
|
+
if (opts.fetchPolicy === "cache-first" && entry)
|
|
37
|
+
return false;
|
|
38
|
+
return true;
|
|
39
|
+
}
|
|
40
|
+
function shouldFetchInitially() {
|
|
41
|
+
if (opts.immediate === false)
|
|
42
|
+
return false;
|
|
43
|
+
return canFetchAutomatically();
|
|
44
|
+
}
|
|
37
45
|
function updateData() {
|
|
38
|
-
|
|
46
|
+
const items = store.getMany(model);
|
|
47
|
+
const filteredItems = items.filter((el) => matchesWhere(el, toValue(opts.where)));
|
|
48
|
+
const orderedFilteredItems = sort(filteredItems, toValue(opts.orderBy));
|
|
49
|
+
data.value = orderedFilteredItems;
|
|
39
50
|
}
|
|
40
|
-
|
|
41
|
-
if (opts.fetchPolicy === "cache-only")
|
|
42
|
-
return;
|
|
43
|
-
const url = joinURL(config.apiPath, `/models/${model.toString()}`);
|
|
51
|
+
function getQuery() {
|
|
44
52
|
const json = stringify({
|
|
45
|
-
include:
|
|
53
|
+
include: opts.include,
|
|
46
54
|
where: toValue(opts.where),
|
|
47
55
|
orderBy: toValue(opts.orderBy),
|
|
48
56
|
skip: toValue(opts.skip),
|
|
49
57
|
take: toValue(opts.take)
|
|
50
58
|
});
|
|
59
|
+
return { q: json };
|
|
60
|
+
}
|
|
61
|
+
async function refetch() {
|
|
62
|
+
if (opts.fetchPolicy === "cache-only")
|
|
63
|
+
return;
|
|
64
|
+
const _fetch = getFetch();
|
|
65
|
+
const url = joinURL(config.apiPath, `/models/${model.toString()}`);
|
|
66
|
+
const query = getQuery();
|
|
67
|
+
store.addToFetchHistory({
|
|
68
|
+
model: model.toString(),
|
|
69
|
+
method,
|
|
70
|
+
query: JSON.stringify(query)
|
|
71
|
+
});
|
|
51
72
|
error.value = null;
|
|
52
73
|
status.value = "pending";
|
|
74
|
+
canFetchMore.value = false;
|
|
53
75
|
try {
|
|
54
|
-
const res = await
|
|
55
|
-
method: "GET",
|
|
56
|
-
query: {
|
|
57
|
-
q: json
|
|
58
|
-
}
|
|
59
|
-
});
|
|
76
|
+
const res = await _fetch(url, { method, query });
|
|
60
77
|
store.setMany(model, res.data);
|
|
78
|
+
updateData();
|
|
61
79
|
status.value = "success";
|
|
80
|
+
canFetchMore.value = res.data.length === toValue(opts.take);
|
|
62
81
|
} catch (err) {
|
|
63
82
|
error.value = err.data;
|
|
64
83
|
status.value = "error";
|
|
84
|
+
canFetchMore.value = true;
|
|
65
85
|
}
|
|
66
86
|
}
|
|
67
|
-
return { data, error, status, refetch };
|
|
87
|
+
return { data, error, status, canFetchMore, refetch };
|
|
68
88
|
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { $Zitem, $ZorderBy, $Zinclude, $Zmodel } from '#build/types/nuxt-zenstack';
|
|
2
|
+
/**
|
|
3
|
+
* @note Sort by relational fields not supported
|
|
4
|
+
*/
|
|
5
|
+
export declare function sort<Zmodel extends $Zmodel, Zinclude extends $Zinclude<Zmodel>, Zitem extends $Zitem<Zmodel, Zinclude>>(items: Zitem[], orderBy: $ZorderBy<Zmodel>): Zitem[];
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export function sort(items, orderBy) {
|
|
2
|
+
if (!items.length || !orderBy)
|
|
3
|
+
return items;
|
|
4
|
+
return items.sort((a, b) => {
|
|
5
|
+
const orderByArray = Array.isArray(orderBy) ? orderBy : [orderBy];
|
|
6
|
+
for (const orderByObj of orderByArray) {
|
|
7
|
+
const orderByEntries = Object.entries(orderByObj);
|
|
8
|
+
for (const [field, direction] of orderByEntries) {
|
|
9
|
+
if (direction !== "asc" && direction !== "desc") continue;
|
|
10
|
+
const aValue = a[field];
|
|
11
|
+
const bValue = b[field];
|
|
12
|
+
if (aValue == null && bValue == null) continue;
|
|
13
|
+
if (aValue == null) return 1;
|
|
14
|
+
if (bValue == null) return -1;
|
|
15
|
+
let comparison = 0;
|
|
16
|
+
if (aValue < bValue) comparison = -1;
|
|
17
|
+
else if (aValue > bValue) comparison = 1;
|
|
18
|
+
if (comparison !== 0) {
|
|
19
|
+
return direction === "asc" ? comparison : -comparison;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return 0;
|
|
24
|
+
});
|
|
25
|
+
}
|