@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.
Files changed (35) hide show
  1. package/dist/module.json +1 -1
  2. package/dist/module.mjs +19 -15
  3. package/dist/runtime/composables/common.d.ts +13 -0
  4. package/dist/runtime/composables/common.js +5 -0
  5. package/dist/runtime/composables/index.d.ts +5 -0
  6. package/dist/runtime/composables/index.js +5 -0
  7. package/dist/runtime/composables/useZenstackCreate/index.d.ts +10 -0
  8. package/dist/runtime/composables/useZenstackCreate/index.js +38 -0
  9. package/dist/runtime/composables/useZenstackDelete/index.d.ts +10 -0
  10. package/dist/runtime/composables/useZenstackDelete/index.js +33 -0
  11. package/dist/runtime/composables/useZenstackRead/index.d.ts +30 -0
  12. package/dist/runtime/composables/useZenstackRead/index.js +62 -0
  13. package/dist/runtime/composables/useZenstackReadMany/index.d.ts +50 -0
  14. package/dist/runtime/composables/useZenstackReadMany/index.js +68 -0
  15. package/dist/runtime/composables/useZenstackStore/helpers.d.ts +5 -0
  16. package/dist/runtime/composables/useZenstackStore/helpers.js +16 -0
  17. package/dist/runtime/composables/useZenstackStore/index.d.ts +18 -0
  18. package/dist/runtime/composables/useZenstackStore/index.js +49 -0
  19. package/dist/runtime/composables/useZenstackStore/normalization.d.ts +5 -0
  20. package/dist/runtime/composables/useZenstackStore/normalization.js +31 -0
  21. package/dist/runtime/composables/useZenstackUpdate/index.d.ts +10 -0
  22. package/dist/runtime/composables/useZenstackUpdate/index.js +38 -0
  23. package/dist/runtime/server/api/{[model] → models/[model]}/[id].delete.js +2 -2
  24. package/dist/runtime/server/api/{[model] → models/[model]}/[id].get.js +2 -2
  25. package/dist/runtime/server/api/{[model] → models/[model]}/[id].patch.js +2 -2
  26. package/dist/runtime/server/api/{[model] → models/[model]}/index.get.js +2 -2
  27. package/dist/runtime/server/api/{[model] → models/[model]}/index.post.js +2 -2
  28. package/dist/runtime/server/utils/index.d.ts +1 -1
  29. package/dist/runtime/server/utils/index.js +4 -4
  30. package/package.json +5 -1
  31. /package/dist/runtime/server/api/{[model] → models/[model]}/[id].delete.d.ts +0 -0
  32. /package/dist/runtime/server/api/{[model] → models/[model]}/[id].get.d.ts +0 -0
  33. /package/dist/runtime/server/api/{[model] → models/[model]}/[id].patch.d.ts +0 -0
  34. /package/dist/runtime/server/api/{[model] → models/[model]}/index.get.d.ts +0 -0
  35. /package/dist/runtime/server/api/{[model] → models/[model]}/index.post.d.ts +0 -0
package/dist/module.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bg-dev/nuxt-zenstack",
3
- "version": "0.0.1",
3
+ "version": "0.0.2",
4
4
  "configKey": "zenstack",
5
5
  "builder": {
6
6
  "@nuxt/module-builder": "1.0.2",
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.1";
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/models"
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: "provideZenStackClient"
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
+ import { useRuntimeConfig } from "#imports";
2
+ export function getConfig() {
3
+ const config = useRuntimeConfig();
4
+ return config.public.zenstack;
5
+ }
@@ -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 "../../utils/parsers.js";
3
- import { getModelOperations } from "../../utils/index.js";
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 "../../utils/parsers.js";
1
+ import { parseModel, parseId, parseReadArgs } from "../../../utils/parsers.js";
2
2
  import { defineEventHandler } from "h3";
3
- import { getModelOperations } from "../../utils/index.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, parseUpdateData } from "../../utils/parsers.js";
1
+ import { parseModel, parseId, parseUpdateData } from "../../../utils/parsers.js";
2
2
  import { defineEventHandler } from "h3";
3
- import { getModelOperations } from "../../utils/index.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, parseReadArgs } from "../../utils/parsers.js";
1
+ import { parseModel, parseReadArgs } from "../../../utils/parsers.js";
2
2
  import { defineEventHandler } from "h3";
3
- import { getModelOperations } from "../../utils/index.js";
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 "../../utils/parsers.js";
1
+ import { parseModel, parseCreateData } from "../../../utils/parsers.js";
2
2
  import { defineEventHandler } from "h3";
3
- import { getModelOperations } from "../../utils/index.js";
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.1",
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"