@bg-dev/nuxt-zenstack 0.0.1 → 0.0.2
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.json +1 -1
- package/dist/module.mjs +19 -15
- package/dist/runtime/composables/common.d.ts +13 -0
- package/dist/runtime/composables/common.js +5 -0
- package/dist/runtime/composables/index.d.ts +5 -0
- package/dist/runtime/composables/index.js +5 -0
- package/dist/runtime/composables/useZenstackCreate/index.d.ts +10 -0
- package/dist/runtime/composables/useZenstackCreate/index.js +38 -0
- package/dist/runtime/composables/useZenstackDelete/index.d.ts +10 -0
- package/dist/runtime/composables/useZenstackDelete/index.js +33 -0
- package/dist/runtime/composables/useZenstackRead/index.d.ts +30 -0
- package/dist/runtime/composables/useZenstackRead/index.js +62 -0
- package/dist/runtime/composables/useZenstackReadMany/index.d.ts +50 -0
- package/dist/runtime/composables/useZenstackReadMany/index.js +68 -0
- package/dist/runtime/composables/useZenstackStore/helpers.d.ts +5 -0
- package/dist/runtime/composables/useZenstackStore/helpers.js +16 -0
- package/dist/runtime/composables/useZenstackStore/index.d.ts +18 -0
- package/dist/runtime/composables/useZenstackStore/index.js +49 -0
- package/dist/runtime/composables/useZenstackStore/normalization.d.ts +5 -0
- package/dist/runtime/composables/useZenstackStore/normalization.js +31 -0
- package/dist/runtime/composables/useZenstackUpdate/index.d.ts +10 -0
- package/dist/runtime/composables/useZenstackUpdate/index.js +38 -0
- package/dist/runtime/server/api/{[model] → models/[model]}/[id].delete.js +2 -2
- package/dist/runtime/server/api/{[model] → models/[model]}/[id].get.js +2 -2
- package/dist/runtime/server/api/{[model] → models/[model]}/[id].patch.js +2 -2
- package/dist/runtime/server/api/{[model] → models/[model]}/index.get.js +2 -2
- package/dist/runtime/server/api/{[model] → models/[model]}/index.post.js +2 -2
- package/dist/runtime/server/utils/index.d.ts +1 -1
- package/dist/runtime/server/utils/index.js +4 -4
- package/package.json +5 -1
- /package/dist/runtime/server/api/{[model] → models/[model]}/[id].delete.d.ts +0 -0
- /package/dist/runtime/server/api/{[model] → models/[model]}/[id].get.d.ts +0 -0
- /package/dist/runtime/server/api/{[model] → models/[model]}/[id].patch.d.ts +0 -0
- /package/dist/runtime/server/api/{[model] → models/[model]}/index.get.d.ts +0 -0
- /package/dist/runtime/server/api/{[model] → models/[model]}/index.post.d.ts +0 -0
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { defineNuxtModule, createResolver, addServerImports, addTemplate, addServerTemplate, addTypeTemplate, addServerHandler } from '@nuxt/kit';
|
|
1
|
+
import { defineNuxtModule, createResolver, addServerImports, 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.2";
|
|
7
7
|
|
|
8
8
|
const module$1 = defineNuxtModule({
|
|
9
9
|
meta: {
|
|
@@ -13,7 +13,7 @@ const module$1 = defineNuxtModule({
|
|
|
13
13
|
},
|
|
14
14
|
// Default configuration options of the Nuxt module
|
|
15
15
|
defaults: {
|
|
16
|
-
apiPath: "/api/
|
|
16
|
+
apiPath: "/api/_zenstack"
|
|
17
17
|
},
|
|
18
18
|
setup(_options, _nuxt) {
|
|
19
19
|
_nuxt.options.runtimeConfig.public = defu(_nuxt.options.runtimeConfig.public, {
|
|
@@ -25,7 +25,7 @@ const module$1 = defineNuxtModule({
|
|
|
25
25
|
addServerImports({
|
|
26
26
|
from: resolver.resolve("./runtime/server/utils"),
|
|
27
27
|
name: "provideClient",
|
|
28
|
-
as: "
|
|
28
|
+
as: "provideZenstackClient"
|
|
29
29
|
});
|
|
30
30
|
addTemplate({
|
|
31
31
|
write: true,
|
|
@@ -45,9 +45,13 @@ export { schema as zenstackSchema } from '~~/zenstack/schema'
|
|
|
45
45
|
getContents: () => `
|
|
46
46
|
import type { ModelOperations, ModelResult, IncludeInput, WhereInput, FindManyArgs, SimplifiedPlainResult, SelectIncludeOmit, QueryOptions, CreateArgs, UpdateArgs } from '@zenstackhq/orm'
|
|
47
47
|
import type { SchemaType } from '~~/zenstack/schema'
|
|
48
|
+
import type { ModelDef } from '@zenstackhq/orm/schema'
|
|
49
|
+
|
|
48
50
|
type ItemGetPayload<Zmodel extends $Zmodel, Args extends SelectIncludeOmit<SchemaType, Zmodel, true>, Options extends QueryOptions<SchemaType> = QueryOptions<SchemaType>> = SimplifiedPlainResult<SchemaType, Zmodel, Args, Options>
|
|
51
|
+
|
|
49
52
|
export type $Zschema = SchemaType
|
|
50
53
|
export type $Zmodel = keyof SchemaType['models']
|
|
54
|
+
export type $Zdef = ModelDef
|
|
51
55
|
export type $Zoperations<Zmodel extends $Zmodel> = ModelOperations<SchemaType, Zmodel>
|
|
52
56
|
export type $Zid<Zmodel extends $Zmodel> = ModelResult<SchemaType, Zmodel> extends { id: infer Id } ? Id : never
|
|
53
57
|
export type $Zinclude<Zmodel extends $Zmodel> = IncludeInput<SchemaType, Zmodel>
|
|
@@ -56,29 +60,29 @@ export type $Zwhere<Zmodel extends $Zmodel> = WhereInput<SchemaType, Zmodel>
|
|
|
56
60
|
export type $ZorderBy<Zmodel extends $Zmodel> = FindManyArgs<SchemaType, Zmodel>['orderBy']
|
|
57
61
|
export type $ZcreateData<Zmodel extends $Zmodel> = CreateArgs<SchemaType, Zmodel>['data']
|
|
58
62
|
export type $ZupdateData<Zmodel extends $Zmodel> = UpdateArgs<SchemaType, Zmodel>['data']
|
|
59
|
-
export type $Zerror = {message: string, reason: string, rejectedByValidation: boolean, model: string}
|
|
60
63
|
`
|
|
61
64
|
});
|
|
62
65
|
addServerHandler({
|
|
63
|
-
route: joinURL(_options.apiPath, "/:model"),
|
|
64
|
-
handler: resolver.resolve("./runtime/server/api/[model]/index.get")
|
|
66
|
+
route: joinURL(_options.apiPath, "models/:model"),
|
|
67
|
+
handler: resolver.resolve("./runtime/server/api/models/[model]/index.get")
|
|
65
68
|
});
|
|
66
69
|
addServerHandler({
|
|
67
|
-
route: joinURL(_options.apiPath, "/:model"),
|
|
68
|
-
handler: resolver.resolve("./runtime/server/api/[model]/index.post")
|
|
70
|
+
route: joinURL(_options.apiPath, "models/:model"),
|
|
71
|
+
handler: resolver.resolve("./runtime/server/api/models/[model]/index.post")
|
|
69
72
|
});
|
|
70
73
|
addServerHandler({
|
|
71
|
-
route: joinURL(_options.apiPath, "/:model/:id"),
|
|
72
|
-
handler: resolver.resolve("./runtime/server/api/[model]/[id].patch")
|
|
74
|
+
route: joinURL(_options.apiPath, "models/:model/:id"),
|
|
75
|
+
handler: resolver.resolve("./runtime/server/api/models/[model]/[id].patch")
|
|
73
76
|
});
|
|
74
77
|
addServerHandler({
|
|
75
|
-
route: joinURL(_options.apiPath, "/:model/:id"),
|
|
76
|
-
handler: resolver.resolve("./runtime/server/api/[model]/[id].delete")
|
|
78
|
+
route: joinURL(_options.apiPath, "models/:model/:id"),
|
|
79
|
+
handler: resolver.resolve("./runtime/server/api/models/[model]/[id].delete")
|
|
77
80
|
});
|
|
78
81
|
addServerHandler({
|
|
79
|
-
route: joinURL(_options.apiPath, "/:model/:id"),
|
|
80
|
-
handler: resolver.resolve("./runtime/server/api/[model]/[id].get")
|
|
82
|
+
route: joinURL(_options.apiPath, "models/:model/:id"),
|
|
83
|
+
handler: resolver.resolve("./runtime/server/api/models/[model]/[id].get")
|
|
81
84
|
});
|
|
85
|
+
addImportsDir(resolver.resolve("./runtime/composables"));
|
|
82
86
|
}
|
|
83
87
|
});
|
|
84
88
|
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export type Status = 'idle' | 'pending' | 'success' | 'error';
|
|
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
|
+
export declare function getConfig(): {
|
|
12
|
+
apiPath: string;
|
|
13
|
+
};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { useZenstackCreate } from './useZenstackCreate/index.js';
|
|
2
|
+
export { useZenstackReadMany } from './useZenstackReadMany/index.js';
|
|
3
|
+
export { useZenstackRead } from './useZenstackRead/index.js';
|
|
4
|
+
export { useZenstackDelete } from './useZenstackDelete/index.js';
|
|
5
|
+
export { useZenstackUpdate } from './useZenstackUpdate/index.js';
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { useZenstackCreate } from "./useZenstackCreate/index.js";
|
|
2
|
+
export { useZenstackReadMany } from "./useZenstackReadMany/index.js";
|
|
3
|
+
export { useZenstackRead } from "./useZenstackRead/index.js";
|
|
4
|
+
export { useZenstackDelete } from "./useZenstackDelete/index.js";
|
|
5
|
+
export { useZenstackUpdate } from "./useZenstackUpdate/index.js";
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { $Zmodel, $Zitem, $ZcreateData } from '#build/types/nuxt-zenstack';
|
|
2
|
+
import type { Status, Error } from '../common.js';
|
|
3
|
+
import { type Ref } from '#imports';
|
|
4
|
+
export declare function useZenstackCreate<Zmodel extends $Zmodel, Zitem extends $Zitem<Zmodel>>(model: Zmodel): {
|
|
5
|
+
data: Ref<Zitem | null>;
|
|
6
|
+
error: Ref<Error | null>;
|
|
7
|
+
status: Ref<Status>;
|
|
8
|
+
mutate: (input: $ZcreateData<Zmodel>) => Promise<void>;
|
|
9
|
+
reset: () => void;
|
|
10
|
+
};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { getConfig } from "../common.js";
|
|
2
|
+
import { ref } from "#imports";
|
|
3
|
+
import { joinURL } from "ufo";
|
|
4
|
+
import { useZenstackStore } from "../useZenstackStore/index.js";
|
|
5
|
+
export function useZenstackCreate(model) {
|
|
6
|
+
const data = ref(null);
|
|
7
|
+
const error = ref(null);
|
|
8
|
+
const status = ref("idle");
|
|
9
|
+
const store = useZenstackStore();
|
|
10
|
+
const config = getConfig();
|
|
11
|
+
function reset() {
|
|
12
|
+
data.value = null;
|
|
13
|
+
error.value = null;
|
|
14
|
+
status.value = "idle";
|
|
15
|
+
}
|
|
16
|
+
async function mutate(input) {
|
|
17
|
+
const url = joinURL(config.apiPath, `/models/${model.toString()}`);
|
|
18
|
+
reset();
|
|
19
|
+
status.value = "pending";
|
|
20
|
+
try {
|
|
21
|
+
const res = await $fetch(url, {
|
|
22
|
+
method: "POST",
|
|
23
|
+
body: {
|
|
24
|
+
data: input
|
|
25
|
+
// TODO: maybe include relations
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
if (res.data)
|
|
29
|
+
store.setOne(model, res.data);
|
|
30
|
+
data.value = res.data;
|
|
31
|
+
status.value = "success";
|
|
32
|
+
} catch (err) {
|
|
33
|
+
error.value = err.data;
|
|
34
|
+
status.value = "error";
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return { data, error, status, mutate, reset };
|
|
38
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { $Zmodel, $Zitem, $Zid } from '#build/types/nuxt-zenstack';
|
|
2
|
+
import type { Status, Error } from '../common.js';
|
|
3
|
+
import { type Ref } from '#imports';
|
|
4
|
+
export declare function useZenstackDelete<Zmodel extends $Zmodel, Zitem extends $Zitem<Zmodel>>(model: Zmodel): {
|
|
5
|
+
data: Ref<Zitem | null>;
|
|
6
|
+
error: Ref<Error | null>;
|
|
7
|
+
status: Ref<Status>;
|
|
8
|
+
mutate: (id: $Zid<Zmodel>) => Promise<void>;
|
|
9
|
+
reset: () => void;
|
|
10
|
+
};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { ref } from "#imports";
|
|
2
|
+
import { joinURL } from "ufo";
|
|
3
|
+
import { useZenstackStore } from "../useZenstackStore/index.js";
|
|
4
|
+
import { getConfig } from "../common.js";
|
|
5
|
+
export function useZenstackDelete(model) {
|
|
6
|
+
const data = ref(null);
|
|
7
|
+
const error = ref(null);
|
|
8
|
+
const status = ref("idle");
|
|
9
|
+
const store = useZenstackStore();
|
|
10
|
+
const config = getConfig();
|
|
11
|
+
function reset() {
|
|
12
|
+
data.value = null;
|
|
13
|
+
error.value = null;
|
|
14
|
+
status.value = "idle";
|
|
15
|
+
}
|
|
16
|
+
async function mutate(id) {
|
|
17
|
+
const url = joinURL(config.apiPath, `/models/${model.toString()}/${id}`);
|
|
18
|
+
reset();
|
|
19
|
+
status.value = "pending";
|
|
20
|
+
try {
|
|
21
|
+
const res = await $fetch(url, {
|
|
22
|
+
method: "DELETE"
|
|
23
|
+
});
|
|
24
|
+
store.deleteOne(model, id);
|
|
25
|
+
data.value = res.data;
|
|
26
|
+
status.value = "success";
|
|
27
|
+
} catch (err) {
|
|
28
|
+
error.value = err.data;
|
|
29
|
+
status.value = "error";
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return { data, error, status, mutate, reset };
|
|
33
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { $Zmodel, $Zitem, $Zid, $Zinclude } from '#build/types/nuxt-zenstack';
|
|
2
|
+
import type { Status, FetchPolicy } from '../common.js';
|
|
3
|
+
import type { Ref, MaybeRefOrGetter } from '#imports';
|
|
4
|
+
type Options<Zmodel extends $Zmodel> = {
|
|
5
|
+
/**
|
|
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
|
+
* - `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.
|
|
8
|
+
* - `fetch-only` means that the query will only fetch the data from the server. The data will be stored in the srore when the query is resolved.
|
|
9
|
+
* - `cache-only` means that the query will only fetch the data from the store.
|
|
10
|
+
* @default 'cache-first'
|
|
11
|
+
*/
|
|
12
|
+
fetchPolicy?: FetchPolicy;
|
|
13
|
+
/**
|
|
14
|
+
* Whether to fetch the data immediately (when the composable is called).
|
|
15
|
+
* @default true
|
|
16
|
+
*/
|
|
17
|
+
immediate?: boolean;
|
|
18
|
+
/**
|
|
19
|
+
* The relations to include in the query.
|
|
20
|
+
* @default undefined
|
|
21
|
+
*/
|
|
22
|
+
include?: MaybeRefOrGetter<$Zinclude<Zmodel>>;
|
|
23
|
+
};
|
|
24
|
+
export declare function useZenstackRead<Zmodel extends $Zmodel, Zitem extends $Zitem<Zmodel>>(model: Zmodel, id: $Zid<Zmodel>, opts?: Options<Zmodel>): {
|
|
25
|
+
data: Ref<Zitem | null>;
|
|
26
|
+
error: Ref<Error | null>;
|
|
27
|
+
status: Ref<Status>;
|
|
28
|
+
refetch: () => Promise<void>;
|
|
29
|
+
};
|
|
30
|
+
export {};
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { ref, toValue, watch, isRef } from "#imports";
|
|
2
|
+
import { joinURL } from "ufo";
|
|
3
|
+
import { useZenstackStore } from "../useZenstackStore/index.js";
|
|
4
|
+
import { stringify } from "superjson";
|
|
5
|
+
import { getConfig } from "../common.js";
|
|
6
|
+
export function useZenstackRead(model, id, opts = {}) {
|
|
7
|
+
const data = ref(null);
|
|
8
|
+
const error = ref(null);
|
|
9
|
+
const status = ref("idle");
|
|
10
|
+
const store = useZenstackStore();
|
|
11
|
+
const config = getConfig();
|
|
12
|
+
opts.fetchPolicy ??= "cache-first";
|
|
13
|
+
opts.immediate ??= true;
|
|
14
|
+
switch (opts.fetchPolicy) {
|
|
15
|
+
case "cache-first":
|
|
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");
|
|
28
|
+
watch(store.state, () => updateData());
|
|
29
|
+
watch(watchedOptions, () => refetch());
|
|
30
|
+
if (opts.immediate)
|
|
31
|
+
refetch();
|
|
32
|
+
function updateData() {
|
|
33
|
+
data.value = store.getOne(model, id);
|
|
34
|
+
}
|
|
35
|
+
async function refetch() {
|
|
36
|
+
if (opts.fetchPolicy === "cache-only")
|
|
37
|
+
return;
|
|
38
|
+
const url = joinURL(config.apiPath, `/models/${model.toString()}/${id}`);
|
|
39
|
+
const json = stringify({
|
|
40
|
+
include: toValue(opts.include)
|
|
41
|
+
});
|
|
42
|
+
error.value = null;
|
|
43
|
+
status.value = "pending";
|
|
44
|
+
try {
|
|
45
|
+
const res = await $fetch(url, {
|
|
46
|
+
method: "GET",
|
|
47
|
+
query: {
|
|
48
|
+
q: json
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
if (res.data)
|
|
52
|
+
store.setOne(model, res.data);
|
|
53
|
+
else
|
|
54
|
+
store.deleteOne(model, id);
|
|
55
|
+
status.value = "success";
|
|
56
|
+
} catch (err) {
|
|
57
|
+
error.value = err.data;
|
|
58
|
+
status.value = "error";
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return { data, error, status, refetch };
|
|
62
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { $Zmodel, $Zitem, $Zinclude, $Zwhere, $ZorderBy } from '#build/types/nuxt-zenstack';
|
|
2
|
+
import type { Status, FetchPolicy } from '../common.js';
|
|
3
|
+
import type { MaybeRefOrGetter, Ref } from '#imports';
|
|
4
|
+
type Options<Zmodel extends $Zmodel> = {
|
|
5
|
+
/**
|
|
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
|
+
* - `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.
|
|
8
|
+
* - `fetch-only` means that the query will only fetch the data from the server. The data will be stored in the srore when the query is resolved.
|
|
9
|
+
* - `cache-only` means that the query will only fetch the data from the store.
|
|
10
|
+
* @default 'cache-first'
|
|
11
|
+
*/
|
|
12
|
+
fetchPolicy?: FetchPolicy;
|
|
13
|
+
/**
|
|
14
|
+
* Whether to fetch the data immediately (when the composable is called).
|
|
15
|
+
* @default true
|
|
16
|
+
*/
|
|
17
|
+
immediate?: boolean;
|
|
18
|
+
/**
|
|
19
|
+
* The relations to include in the query.
|
|
20
|
+
* @default undefined
|
|
21
|
+
*/
|
|
22
|
+
include?: MaybeRefOrGetter<$Zinclude<Zmodel>>;
|
|
23
|
+
/**
|
|
24
|
+
* The filter to apply to the query.
|
|
25
|
+
* @default undefined
|
|
26
|
+
*/
|
|
27
|
+
where?: MaybeRefOrGetter<$Zwhere<Zmodel>>;
|
|
28
|
+
/**
|
|
29
|
+
* The order to apply to the query.
|
|
30
|
+
* @default undefined
|
|
31
|
+
*/
|
|
32
|
+
orderBy?: MaybeRefOrGetter<$ZorderBy<Zmodel>>;
|
|
33
|
+
/**
|
|
34
|
+
* The number of items to skip.
|
|
35
|
+
* @default 0
|
|
36
|
+
*/
|
|
37
|
+
skip?: MaybeRefOrGetter<number>;
|
|
38
|
+
/**
|
|
39
|
+
* The number of items to take.
|
|
40
|
+
* @default 1000
|
|
41
|
+
*/
|
|
42
|
+
take?: MaybeRefOrGetter<number>;
|
|
43
|
+
};
|
|
44
|
+
export declare function useZenstackReadMany<Zmodel extends $Zmodel, Zitem extends $Zitem<Zmodel>>(model: Zmodel, opts?: Options<Zmodel>): {
|
|
45
|
+
data: Ref<Zitem[] | null>;
|
|
46
|
+
error: Ref<Error | null>;
|
|
47
|
+
status: Ref<Status>;
|
|
48
|
+
refetch: () => Promise<void>;
|
|
49
|
+
};
|
|
50
|
+
export {};
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { ref, toValue, watch, isRef } from "#imports";
|
|
2
|
+
import { joinURL } from "ufo";
|
|
3
|
+
import { useZenstackStore } from "../useZenstackStore/index.js";
|
|
4
|
+
import { stringify } from "superjson";
|
|
5
|
+
import { getConfig } from "../common.js";
|
|
6
|
+
export function useZenstackReadMany(model, opts = {}) {
|
|
7
|
+
const data = ref(null);
|
|
8
|
+
const error = ref(null);
|
|
9
|
+
const status = ref("idle");
|
|
10
|
+
const store = useZenstackStore();
|
|
11
|
+
const config = getConfig();
|
|
12
|
+
opts.fetchPolicy ??= "cache-first";
|
|
13
|
+
opts.immediate ??= true;
|
|
14
|
+
opts.skip ??= 0;
|
|
15
|
+
opts.take ??= 1e3;
|
|
16
|
+
switch (opts.fetchPolicy) {
|
|
17
|
+
case "cache-first":
|
|
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");
|
|
30
|
+
watch(store.state, () => updateData());
|
|
31
|
+
watch(watchedOptions, () => {
|
|
32
|
+
updateData();
|
|
33
|
+
refetch();
|
|
34
|
+
});
|
|
35
|
+
if (opts.immediate)
|
|
36
|
+
refetch();
|
|
37
|
+
function updateData() {
|
|
38
|
+
data.value = store.getMany(model);
|
|
39
|
+
}
|
|
40
|
+
async function refetch() {
|
|
41
|
+
if (opts.fetchPolicy === "cache-only")
|
|
42
|
+
return;
|
|
43
|
+
const url = joinURL(config.apiPath, `/models/${model.toString()}`);
|
|
44
|
+
const json = stringify({
|
|
45
|
+
include: toValue(opts.include),
|
|
46
|
+
where: toValue(opts.where),
|
|
47
|
+
orderBy: toValue(opts.orderBy),
|
|
48
|
+
skip: toValue(opts.skip),
|
|
49
|
+
take: toValue(opts.take)
|
|
50
|
+
});
|
|
51
|
+
error.value = null;
|
|
52
|
+
status.value = "pending";
|
|
53
|
+
try {
|
|
54
|
+
const res = await $fetch(url, {
|
|
55
|
+
method: "GET",
|
|
56
|
+
query: {
|
|
57
|
+
q: json
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
store.setMany(model, res.data);
|
|
61
|
+
status.value = "success";
|
|
62
|
+
} catch (err) {
|
|
63
|
+
error.value = err.data;
|
|
64
|
+
status.value = "error";
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return { data, error, status, refetch };
|
|
68
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { $Zmodel, $Zdef } from '#build/types/nuxt-zenstack';
|
|
2
|
+
export declare function getModelDef(model: $Zmodel): $Zdef;
|
|
3
|
+
export declare function isIdString(model: $Zmodel): boolean;
|
|
4
|
+
export declare function getModels(): $Zmodel[];
|
|
5
|
+
export declare function isValidModel(model: $Zmodel): boolean;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { zenstackSchema } from "#build/nuxt-zenstack.mjs";
|
|
2
|
+
export function getModelDef(model) {
|
|
3
|
+
return zenstackSchema.models[model];
|
|
4
|
+
}
|
|
5
|
+
export function isIdString(model) {
|
|
6
|
+
const def = getModelDef(model);
|
|
7
|
+
if (!def.uniqueFields.id)
|
|
8
|
+
throw new Error(`No id field for model ${model.toString()}`);
|
|
9
|
+
return def.uniqueFields.id.type === "String";
|
|
10
|
+
}
|
|
11
|
+
export function getModels() {
|
|
12
|
+
return Object.keys(zenstackSchema.models);
|
|
13
|
+
}
|
|
14
|
+
export function isValidModel(model) {
|
|
15
|
+
return getModels().includes(model);
|
|
16
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { $Zmodel, $Zid } from '#build/types/nuxt-zenstack';
|
|
2
|
+
export declare function useZenstackStore(): {
|
|
3
|
+
state: Readonly<import("vue").Ref<{
|
|
4
|
+
readonly [x: string]: {
|
|
5
|
+
readonly [x: string]: object;
|
|
6
|
+
};
|
|
7
|
+
}, {
|
|
8
|
+
readonly [x: string]: {
|
|
9
|
+
readonly [x: string]: object;
|
|
10
|
+
};
|
|
11
|
+
}>>;
|
|
12
|
+
setOne: (model: $Zmodel, input: object) => void;
|
|
13
|
+
setMany: (model: $Zmodel, input: object[]) => void;
|
|
14
|
+
getOne: <Zmodel extends $Zmodel>(model: Zmodel, input: $Zid<Zmodel>) => any;
|
|
15
|
+
getMany: (model: $Zmodel) => any;
|
|
16
|
+
deleteOne: <Model extends $Zmodel>(model: Model, id: $Zid<Model>) => void;
|
|
17
|
+
deleteMany: (model: $Zmodel) => void;
|
|
18
|
+
};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { generateNormalizrSchema, getNormalizrSchema } from "./normalization.js";
|
|
2
|
+
import { normalize, denormalize } from "normalizr";
|
|
3
|
+
import { defu } from "defu";
|
|
4
|
+
import { readonly, useState } from "#imports";
|
|
5
|
+
generateNormalizrSchema();
|
|
6
|
+
export function useZenstackStore() {
|
|
7
|
+
const state = useState("zenstack-store", () => ({}));
|
|
8
|
+
function setOne(model, input) {
|
|
9
|
+
const schema = getNormalizrSchema(model);
|
|
10
|
+
const res = normalize(input, schema);
|
|
11
|
+
state.value = defu(res.entities, state.value);
|
|
12
|
+
}
|
|
13
|
+
function setMany(model, input) {
|
|
14
|
+
const schema = [getNormalizrSchema(model)];
|
|
15
|
+
const res = normalize(input, schema);
|
|
16
|
+
state.value = defu(res.entities, state.value);
|
|
17
|
+
}
|
|
18
|
+
function getOne(model, input) {
|
|
19
|
+
const schema = getNormalizrSchema(model);
|
|
20
|
+
return denormalize(input, schema, state.value) ?? null;
|
|
21
|
+
}
|
|
22
|
+
function getMany(model) {
|
|
23
|
+
const input = Object.keys(state.value[model.toString()] ?? {});
|
|
24
|
+
const schema = [getNormalizrSchema(model)];
|
|
25
|
+
return denormalize(input, schema, state.value) ?? [];
|
|
26
|
+
}
|
|
27
|
+
function deleteOne(model, id) {
|
|
28
|
+
const newState = {};
|
|
29
|
+
for (const _model in state.value) {
|
|
30
|
+
for (const _id in state.value[_model]) {
|
|
31
|
+
if (_id == id && _model === model)
|
|
32
|
+
continue;
|
|
33
|
+
newState[_model] ||= {};
|
|
34
|
+
newState[_model][_id] = { ...state.value[_model][_id] };
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
state.value = newState;
|
|
38
|
+
}
|
|
39
|
+
function deleteMany(model) {
|
|
40
|
+
const newState = {};
|
|
41
|
+
for (const _model in state.value) {
|
|
42
|
+
if (_model === model)
|
|
43
|
+
continue;
|
|
44
|
+
newState[_model] = { ...state.value[_model] };
|
|
45
|
+
}
|
|
46
|
+
state.value = newState;
|
|
47
|
+
}
|
|
48
|
+
return { state: readonly(state), setOne, setMany, getOne, getMany, deleteOne, deleteMany };
|
|
49
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { schema as normalizrSchema } from 'normalizr';
|
|
2
|
+
import type { $Zmodel } from '#build/types/nuxt-zenstack';
|
|
3
|
+
declare function getNormalizrSchema(model: $Zmodel): normalizrSchema.Entity<any>;
|
|
4
|
+
declare function generateNormalizrSchema(): void;
|
|
5
|
+
export { getNormalizrSchema, generateNormalizrSchema };
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { schema as normalizrSchema } from "normalizr";
|
|
2
|
+
import { getModelDef, getModels, isValidModel } from "./helpers.js";
|
|
3
|
+
const NORMALIZR_SCHEMA = /* @__PURE__ */ new Map();
|
|
4
|
+
function getNormalizrSchema(model) {
|
|
5
|
+
const schema = NORMALIZR_SCHEMA.get(model);
|
|
6
|
+
if (!schema)
|
|
7
|
+
throw new Error(`Model ${model.toString()} not defined`);
|
|
8
|
+
return schema;
|
|
9
|
+
}
|
|
10
|
+
function generateNormalizrSchema() {
|
|
11
|
+
const models = getModels();
|
|
12
|
+
for (const model of models) {
|
|
13
|
+
NORMALIZR_SCHEMA.set(model, new normalizrSchema.Entity(model.toString()));
|
|
14
|
+
}
|
|
15
|
+
for (const model of models) {
|
|
16
|
+
const entity = getNormalizrSchema(model);
|
|
17
|
+
const modelDef = getModelDef(model);
|
|
18
|
+
const definition = {};
|
|
19
|
+
for (const field of Object.values(modelDef.fields)) {
|
|
20
|
+
if (isValidModel(field.type)) {
|
|
21
|
+
const relatedModel = field.type;
|
|
22
|
+
const relatedEntity = getNormalizrSchema(relatedModel);
|
|
23
|
+
definition[field.name] = field.array ? [relatedEntity] : relatedEntity;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
if (Object.keys(definition).length > 0) {
|
|
27
|
+
entity.define(definition);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
export { getNormalizrSchema, generateNormalizrSchema };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { $Zmodel, $Zitem, $ZupdateData, $Zid } from '#build/types/nuxt-zenstack';
|
|
2
|
+
import type { Status } from '../common.js';
|
|
3
|
+
import type { Ref } from '#imports';
|
|
4
|
+
export declare function useZenstackUpdate<Zmodel extends $Zmodel, Zitem extends $Zitem<Zmodel>>(model: Zmodel): {
|
|
5
|
+
data: Ref<Zitem | null>;
|
|
6
|
+
error: Ref<Error | null>;
|
|
7
|
+
status: Ref<Status>;
|
|
8
|
+
mutate: (id: $Zid<Zmodel>, input: $ZupdateData<Zmodel>) => Promise<void>;
|
|
9
|
+
reset: () => void;
|
|
10
|
+
};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { ref } from "#imports";
|
|
2
|
+
import { joinURL } from "ufo";
|
|
3
|
+
import { useZenstackStore } from "../useZenstackStore/index.js";
|
|
4
|
+
import { getConfig } from "../common.js";
|
|
5
|
+
export function useZenstackUpdate(model) {
|
|
6
|
+
const data = ref(null);
|
|
7
|
+
const error = ref(null);
|
|
8
|
+
const status = ref("idle");
|
|
9
|
+
const store = useZenstackStore();
|
|
10
|
+
const config = getConfig();
|
|
11
|
+
function reset() {
|
|
12
|
+
data.value = null;
|
|
13
|
+
error.value = null;
|
|
14
|
+
status.value = "idle";
|
|
15
|
+
}
|
|
16
|
+
async function mutate(id, input) {
|
|
17
|
+
const url = joinURL(config.apiPath, `/models/${model.toString()}/${id}`);
|
|
18
|
+
reset();
|
|
19
|
+
status.value = "pending";
|
|
20
|
+
try {
|
|
21
|
+
const res = await $fetch(url, {
|
|
22
|
+
method: "PATCH",
|
|
23
|
+
body: {
|
|
24
|
+
data: input
|
|
25
|
+
// TODO: maybe include relations
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
if (res.data)
|
|
29
|
+
store.setOne(model, res.data);
|
|
30
|
+
data.value = res.data;
|
|
31
|
+
status.value = "success";
|
|
32
|
+
} catch (err) {
|
|
33
|
+
error.value = err.data;
|
|
34
|
+
status.value = "error";
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return { data, error, status, mutate, reset };
|
|
38
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { defineEventHandler } from "h3";
|
|
2
|
-
import { parseModel, parseId } from "
|
|
3
|
-
import { getModelOperations } from "
|
|
2
|
+
import { parseModel, parseId } from "../../../utils/parsers.js";
|
|
3
|
+
import { getModelOperations } from "../../../utils/index.js";
|
|
4
4
|
export default defineEventHandler(async (event) => {
|
|
5
5
|
const model = parseModel(event);
|
|
6
6
|
const id = parseId(event, model);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { parseModel, parseId, parseReadArgs } from "
|
|
1
|
+
import { parseModel, parseId, parseReadArgs } from "../../../utils/parsers.js";
|
|
2
2
|
import { defineEventHandler } from "h3";
|
|
3
|
-
import { getModelOperations } from "
|
|
3
|
+
import { getModelOperations } from "../../../utils/index.js";
|
|
4
4
|
export default defineEventHandler(async (event) => {
|
|
5
5
|
const model = parseModel(event);
|
|
6
6
|
const id = parseId(event, model);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { parseModel, parseId, parseUpdateData } from "
|
|
1
|
+
import { parseModel, parseId, parseUpdateData } from "../../../utils/parsers.js";
|
|
2
2
|
import { defineEventHandler } from "h3";
|
|
3
|
-
import { getModelOperations } from "
|
|
3
|
+
import { getModelOperations } from "../../../utils/index.js";
|
|
4
4
|
export default defineEventHandler(async (event) => {
|
|
5
5
|
const model = parseModel(event);
|
|
6
6
|
const id = parseId(event, model);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { parseModel, parseReadArgs } from "
|
|
1
|
+
import { parseModel, parseReadArgs } from "../../../utils/parsers.js";
|
|
2
2
|
import { defineEventHandler } from "h3";
|
|
3
|
-
import { getModelOperations } from "
|
|
3
|
+
import { getModelOperations } from "../../../utils/index.js";
|
|
4
4
|
export default defineEventHandler(async (event) => {
|
|
5
5
|
const model = parseModel(event);
|
|
6
6
|
const readArgs = parseReadArgs(event, model);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { parseModel, parseCreateData } from "
|
|
1
|
+
import { parseModel, parseCreateData } from "../../../utils/parsers.js";
|
|
2
2
|
import { defineEventHandler } from "h3";
|
|
3
|
-
import { getModelOperations } from "
|
|
3
|
+
import { getModelOperations } from "../../../utils/index.js";
|
|
4
4
|
export default defineEventHandler(async (event) => {
|
|
5
5
|
const model = parseModel(event);
|
|
6
6
|
const createData = await parseCreateData(event, model);
|
|
@@ -3,9 +3,9 @@ import type { $Zschema, $Zmodel, $Zoperations } from '#build/types/nuxt-zenstack
|
|
|
3
3
|
declare let _client: ClientContract<$Zschema> | null;
|
|
4
4
|
export declare function provideClient(client: typeof _client): void;
|
|
5
5
|
export declare function getClient(): ClientContract<SchemaType>;
|
|
6
|
+
export declare function getModelOperations<Zmodel extends $Zmodel>(model: Zmodel): $Zoperations<Zmodel>;
|
|
6
7
|
export declare function getModelDef(model: $Zmodel): any;
|
|
7
8
|
export declare function isIdString(model: $Zmodel): boolean;
|
|
8
9
|
export declare function getModels(): $Zmodel[];
|
|
9
10
|
export declare function isValidModel(model: $Zmodel): boolean;
|
|
10
|
-
export declare function getModelOperations<Zmodel extends $Zmodel>(model: Zmodel): $Zoperations<Zmodel>;
|
|
11
11
|
export {};
|
|
@@ -9,6 +9,10 @@ export function getClient() {
|
|
|
9
9
|
}
|
|
10
10
|
throw new Error("ZenStack client not provided");
|
|
11
11
|
}
|
|
12
|
+
export function getModelOperations(model) {
|
|
13
|
+
const db = getClient();
|
|
14
|
+
return db[model.toString().toLocaleLowerCase()];
|
|
15
|
+
}
|
|
12
16
|
export function getModelDef(model) {
|
|
13
17
|
return zenstackSchema.models[model];
|
|
14
18
|
}
|
|
@@ -21,7 +25,3 @@ export function getModels() {
|
|
|
21
25
|
export function isValidModel(model) {
|
|
22
26
|
return getModels().includes(model);
|
|
23
27
|
}
|
|
24
|
-
export function getModelOperations(model) {
|
|
25
|
-
const db = getClient();
|
|
26
|
-
return db[model.toString().toLocaleLowerCase()];
|
|
27
|
-
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bg-dev/nuxt-zenstack",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.2",
|
|
4
4
|
"description": "ZenStack integration for Nuxt",
|
|
5
5
|
"repository": {
|
|
6
6
|
"url": "https://github.com/becem-gharbi/nuxt-zenstack"
|
|
@@ -36,6 +36,7 @@
|
|
|
36
36
|
"prepack": "nuxt-module-build build",
|
|
37
37
|
"dev": "npm run dev:prepare && nuxt dev playground",
|
|
38
38
|
"dev:build": "nuxt build playground",
|
|
39
|
+
"dev:preview": "nuxt preview playground",
|
|
39
40
|
"dev:prepare": "nuxt-module-build build --stub && nuxt-module-build prepare && nuxt prepare playground",
|
|
40
41
|
"dev:db:generate": "cd playground && zen generate",
|
|
41
42
|
"dev:db:push": "cd playground && zen db push",
|
|
@@ -52,6 +53,7 @@
|
|
|
52
53
|
"@nuxt/kit": "^4.2.2",
|
|
53
54
|
"@zenstackhq/orm": "3.2.1",
|
|
54
55
|
"defu": "^6.1.4",
|
|
56
|
+
"normalizr": "^3.6.2",
|
|
55
57
|
"superjson": "^2.2.6",
|
|
56
58
|
"ufo": "^1.6.3"
|
|
57
59
|
},
|
|
@@ -62,12 +64,14 @@
|
|
|
62
64
|
"@nuxt/module-builder": "^1.0.2",
|
|
63
65
|
"@nuxt/schema": "^4.2.2",
|
|
64
66
|
"@nuxt/test-utils": "^3.23.0",
|
|
67
|
+
"@nuxt/ui": "^4.3.0",
|
|
65
68
|
"@types/node": "latest",
|
|
66
69
|
"@zenstackhq/cli": "3.2.1",
|
|
67
70
|
"changelogen": "^0.6.2",
|
|
68
71
|
"eslint": "^9.39.2",
|
|
69
72
|
"libsql": "^0.5.22",
|
|
70
73
|
"nuxt": "^4.2.2",
|
|
74
|
+
"playwright-core": "^1.57.0",
|
|
71
75
|
"typescript": "~5.9.3",
|
|
72
76
|
"vitest": "^4.0.17",
|
|
73
77
|
"vue-tsc": "^3.2.2"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|