@bg-dev/nuxt-zenstack 0.0.4 → 0.0.6

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 (46) hide show
  1. package/dist/module.d.mts +2 -4
  2. package/dist/module.json +1 -1
  3. package/dist/module.mjs +28 -41
  4. package/dist/runtime/composables/common.d.ts +3 -7
  5. package/dist/runtime/composables/useZenstackCreate/index.d.ts +1 -1
  6. package/dist/runtime/composables/useZenstackDelete/index.d.ts +1 -1
  7. package/dist/runtime/composables/useZenstackRead/index.d.ts +1 -1
  8. package/dist/runtime/composables/useZenstackReadMany/index.d.ts +1 -1
  9. package/dist/runtime/composables/useZenstackReadMany/index.js +1 -1
  10. package/dist/runtime/composables/useZenstackRealtime/index.d.ts +6 -0
  11. package/dist/runtime/composables/useZenstackRealtime/index.js +53 -0
  12. package/dist/runtime/composables/useZenstackUpdate/index.d.ts +1 -1
  13. package/dist/runtime/server/api/models/[model]/[id].delete.d.ts +1 -1
  14. package/dist/runtime/server/api/models/[model]/[id].delete.js +11 -13
  15. package/dist/runtime/server/api/models/[model]/[id].get.d.ts +1 -1
  16. package/dist/runtime/server/api/models/[model]/[id].get.js +11 -14
  17. package/dist/runtime/server/api/models/[model]/[id].patch.d.ts +1 -1
  18. package/dist/runtime/server/api/models/[model]/[id].patch.js +11 -16
  19. package/dist/runtime/server/api/models/[model]/index.get.d.ts +2 -2
  20. package/dist/runtime/server/api/models/[model]/index.get.js +15 -11
  21. package/dist/runtime/server/api/models/[model]/index.post.d.ts +1 -1
  22. package/dist/runtime/server/api/models/[model]/index.post.js +11 -13
  23. package/dist/runtime/server/routes/realtime.d.ts +2 -0
  24. package/dist/runtime/server/routes/realtime.js +23 -0
  25. package/dist/runtime/server/utils/helpers.d.ts +9 -0
  26. package/dist/runtime/server/utils/helpers.js +39 -0
  27. package/dist/runtime/server/utils/index.d.ts +14 -7
  28. package/dist/runtime/server/utils/index.js +12 -42
  29. package/dist/runtime/server/utils/{error.d.ts → operations/common.d.ts} +2 -1
  30. package/dist/runtime/server/utils/{error.js → operations/common.js} +3 -0
  31. package/dist/runtime/server/utils/operations/create.d.ts +10 -0
  32. package/dist/runtime/server/utils/operations/create.js +15 -0
  33. package/dist/runtime/server/utils/operations/delete.d.ts +10 -0
  34. package/dist/runtime/server/utils/operations/delete.js +16 -0
  35. package/dist/runtime/server/utils/operations/findMany.d.ts +14 -0
  36. package/dist/runtime/server/utils/operations/findMany.js +14 -0
  37. package/dist/runtime/server/utils/operations/findUnique.d.ts +11 -0
  38. package/dist/runtime/server/utils/operations/findUnique.js +14 -0
  39. package/dist/runtime/server/utils/operations/update.d.ts +11 -0
  40. package/dist/runtime/server/utils/operations/update.js +19 -0
  41. package/dist/runtime/server/utils/parsers.d.ts +1 -0
  42. package/dist/runtime/server/utils/parsers.js +7 -1
  43. package/dist/runtime/types/index.d.ts +12 -0
  44. package/dist/runtime/types/index.js +0 -0
  45. package/dist/runtime/types/template.d.ts +52 -0
  46. package/package.json +3 -3
package/dist/module.d.mts CHANGED
@@ -1,9 +1,7 @@
1
1
  import * as _nuxt_schema from '@nuxt/schema';
2
- import { FetchPolicy } from '../dist/runtime/composables/common.js';
2
+ import { PublicModuleOptions, PrivateModuleOptions } from '../dist/runtime/types/index.js';
3
3
 
4
- interface ModuleOptions {
5
- apiPath: string;
6
- fetchPolicy: FetchPolicy;
4
+ interface ModuleOptions extends PublicModuleOptions, PrivateModuleOptions {
7
5
  }
8
6
  declare const _default: _nuxt_schema.NuxtModule<ModuleOptions, ModuleOptions, false>;
9
7
 
package/dist/module.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bg-dev/nuxt-zenstack",
3
- "version": "0.0.4",
3
+ "version": "0.0.6",
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, addTemplate, addServerTemplate, addTypeTemplate, addServerHandler, addImportsDir } from '@nuxt/kit';
1
+ import { defineNuxtModule, createResolver, addTemplate, addServerTemplate, addTypeTemplate, addServerHandler, addImportsDir, addServerImports, addImports } 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.4";
6
+ const version = "0.0.6";
7
7
 
8
8
  const module$1 = defineNuxtModule({
9
9
  meta: {
@@ -14,15 +14,24 @@ const module$1 = defineNuxtModule({
14
14
  // Default configuration options of the Nuxt module
15
15
  defaults: {
16
16
  apiPath: "/api/_zenstack",
17
- fetchPolicy: "cache-first"
17
+ fetchPolicy: "cache-first",
18
+ realtime: false,
19
+ baseUrl: "http://localhost:3000",
20
+ expose: {}
18
21
  },
19
22
  setup(_options, _nuxt) {
20
23
  _nuxt.options.runtimeConfig.public = defu(_nuxt.options.runtimeConfig.public, {
21
24
  zenstack: {
22
25
  apiPath: _options.apiPath,
23
- fetchPolicy: _options.fetchPolicy
26
+ fetchPolicy: _options.fetchPolicy,
27
+ realtime: _options.realtime,
28
+ baseUrl: _options.baseUrl
24
29
  }
25
30
  });
31
+ _nuxt.options.runtimeConfig.zenstack = {
32
+ expose: _options.expose,
33
+ ..._nuxt.options.runtimeConfig.zenstack ?? {}
34
+ };
26
35
  const resolver = createResolver(import.meta.url);
27
36
  addTemplate({
28
37
  write: true,
@@ -39,43 +48,7 @@ export { schema as zenstackSchema } from '~~/zenstack/schema'
39
48
  });
40
49
  addTypeTemplate({
41
50
  filename: "types/nuxt-zenstack.d.ts",
42
- getContents: () => `
43
- import type { ClientContract, ModelOperations, ModelResult, IncludeInput, WhereInput, FindManyArgs, SimplifiedPlainResult, SelectIncludeOmit, QueryOptions, CreateArgs, UpdateArgs } from '@zenstackhq/orm'
44
- import type { SchemaType } from '~~/zenstack/schema'
45
- import type { ModelDef } from '@zenstackhq/orm/schema'
46
- import type { H3Error } from 'h3'
47
- import { ORMError, RejectedByPolicyReason, ORMErrorReason } from '@zenstackhq/orm'
48
-
49
- type ItemGetPayload<Zmodel extends $Zmodel, Args extends SelectIncludeOmit<SchemaType, Zmodel, true>, Options extends QueryOptions<SchemaType> = QueryOptions<SchemaType>> = SimplifiedPlainResult<SchemaType, Zmodel, Args, Options>
50
-
51
- export type $Zschema = SchemaType
52
- export type $Zmodel = keyof SchemaType['models']
53
- export type $Zdef = ModelDef
54
- export type $Zoperations<Zmodel extends $Zmodel> = ModelOperations<SchemaType, Zmodel>
55
- export type $Zid<Zmodel extends $Zmodel> = ModelResult<SchemaType, Zmodel> extends { id: infer Id } ? Id : never
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
60
- export type $ZcreateData<Zmodel extends $Zmodel> = CreateArgs<SchemaType, Zmodel>['data']
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
- }
78
- `
51
+ src: resolver.resolve("./runtime/types/template.d.ts")
79
52
  });
80
53
  addServerHandler({
81
54
  route: joinURL(_options.apiPath, "models/:model"),
@@ -98,6 +71,20 @@ declare module 'h3' {
98
71
  handler: resolver.resolve("./runtime/server/api/models/[model]/[id].get")
99
72
  });
100
73
  addImportsDir(resolver.resolve("./runtime/composables"));
74
+ addServerImports({
75
+ from: resolver.resolve("./runtime/server/utils"),
76
+ name: "useZenstack"
77
+ });
78
+ if (_options.realtime) {
79
+ addServerHandler({
80
+ route: joinURL(_options.apiPath, "realtime"),
81
+ handler: resolver.resolve("./runtime/server/routes/realtime")
82
+ });
83
+ addImports({
84
+ from: resolver.resolve("./runtime/composables/useZenstackRealtime"),
85
+ name: "useZenstackRealtime"
86
+ });
87
+ }
101
88
  }
102
89
  });
103
90
 
@@ -1,11 +1,7 @@
1
- export type Status = 'idle' | 'pending' | 'success' | 'error';
2
- export type FetchPolicy = 'cache-first' | 'fetch-only' | 'cache-only' | 'cache-and-fetch';
3
- export declare function getConfig(): {
4
- apiPath: string;
5
- fetchPolicy: FetchPolicy;
6
- };
1
+ import type { PublicModuleOptions } from '../types/index.js';
2
+ export declare function getConfig(): PublicModuleOptions;
7
3
  /**
8
4
  * @param instance a custom fetch method created by `$fetch.create`
9
5
  */
10
6
  export declare function provideFetch(instance: typeof $fetch): void;
11
- export declare function getFetch(): import("nitropack/types").$Fetch<unknown, import("nitropack/types").NitroFetchRequest>;
7
+ export declare function getFetch(): import("nitropack").$Fetch<unknown, import("nitropack").NitroFetchRequest>;
@@ -1,5 +1,5 @@
1
1
  import type { $Zmodel, $Zitem, $ZcreateData, $Zerror } from '#build/types/nuxt-zenstack';
2
- import type { Status } from '../common.js';
2
+ import type { Status } from '../../types/index.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>;
@@ -1,5 +1,5 @@
1
1
  import type { $Zmodel, $Zitem, $Zid, $Zerror } from '#build/types/nuxt-zenstack';
2
- import type { Status } from '../common.js';
2
+ import type { Status } from '../../types/index.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>;
@@ -1,5 +1,5 @@
1
1
  import type { $Zmodel, $Zitem, $Zid, $Zinclude, $Zerror } from '#build/types/nuxt-zenstack';
2
- import type { Status, FetchPolicy } from '../common.js';
2
+ import type { Status, FetchPolicy } from '../../types/index.js';
3
3
  import type { Ref } from '#imports';
4
4
  type Options<Zinclude> = {
5
5
  /**
@@ -1,5 +1,5 @@
1
1
  import type { $Zmodel, $Zitem, $Zinclude, $Zwhere, $ZorderBy, $Zerror } from '#build/types/nuxt-zenstack';
2
- import type { Status, FetchPolicy } from '../common.js';
2
+ import type { Status, FetchPolicy } from '../../types/index.js';
3
3
  import type { MaybeRefOrGetter, Ref } from '#imports';
4
4
  type Options<Zinclude, Zwhere, ZorderBy> = {
5
5
  /**
@@ -81,7 +81,7 @@ export async function useZenstackReadMany(model, opts = {}) {
81
81
  } catch (err) {
82
82
  error.value = err.data;
83
83
  status.value = "error";
84
- canFetchMore.value = true;
84
+ canFetchMore.value = false;
85
85
  }
86
86
  }
87
87
  return { data, error, status, canFetchMore, refetch };
@@ -0,0 +1,6 @@
1
+ import type { $Zmodel } from '#build/types/nuxt-zenstack';
2
+ export declare function useZenstackRealtime(): {
3
+ subscribe: (models: $Zmodel[]) => void;
4
+ unsubscribe: (models: $Zmodel[]) => void;
5
+ getSubscriptions: () => (string | number | symbol)[];
6
+ };
@@ -0,0 +1,53 @@
1
+ import { useZenstackStore } from "../useZenstackStore/index.js";
2
+ import { useZenstackRead } from "../useZenstackRead/index.js";
3
+ import destr from "destr";
4
+ import { joinURL } from "ufo";
5
+ import { getConfig } from "../common.js";
6
+ export function useZenstackRealtime() {
7
+ const config = getConfig();
8
+ const url = joinURL(config.baseUrl, config.apiPath, "realtime");
9
+ const subscriptions = /* @__PURE__ */ new Set();
10
+ let eventSource = null;
11
+ function connect() {
12
+ if (eventSource)
13
+ return;
14
+ eventSource = new EventSource(url);
15
+ eventSource.onmessage = (event) => {
16
+ const data = destr(event.data);
17
+ if (data)
18
+ onMessage(data);
19
+ };
20
+ }
21
+ async function onMessage(data) {
22
+ if (!subscriptions.has(data.model))
23
+ return;
24
+ for (const id of data.ids) {
25
+ if (data.action === "delete") {
26
+ useZenstackStore().deleteOne(data.model, id);
27
+ } else {
28
+ await useZenstackRead(data.model, id, { fetchPolicy: "fetch-only" });
29
+ }
30
+ }
31
+ }
32
+ function disconnect() {
33
+ if (eventSource)
34
+ eventSource.close();
35
+ eventSource = null;
36
+ }
37
+ function subscribe(models) {
38
+ for (const model of models)
39
+ subscriptions.add(model);
40
+ if (subscriptions.size > 0)
41
+ connect();
42
+ }
43
+ function unsubscribe(models) {
44
+ for (const model of models)
45
+ subscriptions.delete(model);
46
+ if (subscriptions.size === 0)
47
+ disconnect();
48
+ }
49
+ function getSubscriptions() {
50
+ return Array.from(subscriptions);
51
+ }
52
+ return { subscribe, unsubscribe, getSubscriptions };
53
+ }
@@ -1,5 +1,5 @@
1
1
  import type { $Zmodel, $Zitem, $ZupdateData, $Zid, $Zerror } from '#build/types/nuxt-zenstack';
2
- import type { Status } from '../common.js';
2
+ import type { Status } from '../../types/index.js';
3
3
  import type { Ref } from '#imports';
4
4
  export declare function useZenstackUpdate<Zmodel extends $Zmodel, Zitem extends $Zitem<Zmodel>>(model: Zmodel): {
5
5
  data: Ref<Zitem | null>;
@@ -1,6 +1,6 @@
1
1
  declare const _default: import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<{
2
2
  data: {
3
3
  [x: string]: any;
4
- };
4
+ } & {};
5
5
  }>>;
6
6
  export default _default;
@@ -1,17 +1,15 @@
1
- import { defineEventHandler } from "h3";
2
- import { parseModel, parseId } from "../../../utils/parsers.js";
3
- import { getModelOperations } from "../../../utils/index.js";
4
- import { createError } from "../../../utils/error.js";
1
+ import { defineEventHandler, createError } from "h3";
2
+ import { parseModel, parseId, parseClient } from "../../../utils/parsers.js";
3
+ import { useZenstack } from "../../../utils/index.js";
4
+ import { getConfig } from "../../../utils/helpers.js";
5
5
  export default defineEventHandler(async (event) => {
6
6
  const model = parseModel(event);
7
+ const config = getConfig();
8
+ if (!config.expose[model]?.find((permission) => permission === "delete")) {
9
+ throw createError({ statusCode: 403, statusMessage: "Forbidden" });
10
+ }
11
+ const client = parseClient(event);
7
12
  const id = parseId(event, model);
8
- const operations = getModelOperations(event, model);
9
- const data = await operations.delete({
10
- where: {
11
- id
12
- }
13
- }).catch((err) => {
14
- throw createError(err);
15
- });
16
- return { data };
13
+ const zenstack = useZenstack();
14
+ return zenstack.delete({ client, model, id });
17
15
  });
@@ -1,6 +1,6 @@
1
1
  declare const _default: import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<{
2
2
  data: {
3
3
  [x: string]: any;
4
- } | null;
4
+ } & {};
5
5
  }>>;
6
6
  export default _default;
@@ -1,19 +1,16 @@
1
- import { parseModel, parseId, parseReadArgs } from "../../../utils/parsers.js";
2
- import { defineEventHandler } from "h3";
3
- import { getModelOperations } from "../../../utils/index.js";
4
- import { createError } from "../../../utils/error.js";
1
+ import { parseModel, parseId, parseReadArgs, parseClient } from "../../../utils/parsers.js";
2
+ import { defineEventHandler, createError } from "h3";
3
+ import { useZenstack } from "../../../utils/index.js";
4
+ import { getConfig } from "../../../utils/helpers.js";
5
5
  export default defineEventHandler(async (event) => {
6
6
  const model = parseModel(event);
7
+ const config = getConfig();
8
+ if (!config.expose[model]?.find((permission) => permission === "read")) {
9
+ throw createError({ statusCode: 403, statusMessage: "Forbidden" });
10
+ }
11
+ const client = parseClient(event);
7
12
  const id = parseId(event, model);
8
13
  const readArgs = parseReadArgs(event, model);
9
- const operations = getModelOperations(event, model);
10
- const data = await operations.findUnique({
11
- include: readArgs.include,
12
- where: {
13
- id
14
- }
15
- }).catch((err) => {
16
- throw createError(err);
17
- });
18
- return { data };
14
+ const zenstack = useZenstack();
15
+ return zenstack.findUnique({ client, model, id, include: readArgs.include });
19
16
  });
@@ -1,6 +1,6 @@
1
1
  declare const _default: import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<{
2
2
  data: {
3
3
  [x: string]: any;
4
- };
4
+ } & {};
5
5
  }>>;
6
6
  export default _default;
@@ -1,21 +1,16 @@
1
- import { parseModel, parseId, parseUpdateArgs } from "../../../utils/parsers.js";
2
- import { defineEventHandler } from "h3";
3
- import { getModelOperations, includeAll } from "../../../utils/index.js";
4
- import { createError } from "../../../utils/error.js";
1
+ import { parseModel, parseId, parseUpdateArgs, parseClient } from "../../../utils/parsers.js";
2
+ import { defineEventHandler, createError } from "h3";
3
+ import { useZenstack } from "../../../utils/index.js";
4
+ import { getConfig } from "../../../utils/helpers.js";
5
5
  export default defineEventHandler(async (event) => {
6
6
  const model = parseModel(event);
7
+ const config = getConfig();
8
+ if (!config.expose[model]?.find((permission) => permission === "update")) {
9
+ throw createError({ statusCode: 403, statusMessage: "Forbidden" });
10
+ }
11
+ const client = parseClient(event);
7
12
  const id = parseId(event, model);
8
13
  const updateArgs = await parseUpdateArgs(event, model);
9
- const operations = getModelOperations(event, model);
10
- const include = includeAll(model);
11
- const data = await operations.update({
12
- data: updateArgs.data,
13
- include,
14
- where: {
15
- id
16
- }
17
- }).catch((err) => {
18
- throw createError(err);
19
- });
20
- return { data };
14
+ const zenstack = useZenstack();
15
+ return zenstack.update({ client, model, id, data: updateArgs.data });
21
16
  });
@@ -1,6 +1,6 @@
1
1
  declare const _default: import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<{
2
- data: {
2
+ data: ({
3
3
  [x: string]: any;
4
- }[];
4
+ } & {})[];
5
5
  }>>;
6
6
  export default _default;
@@ -1,19 +1,23 @@
1
- import { parseModel, parseReadArgs } from "../../../utils/parsers.js";
2
- import { defineEventHandler } from "h3";
3
- import { getModelOperations } from "../../../utils/index.js";
4
- import { createError } from "../../../utils/error.js";
1
+ import { parseClient, parseModel, parseReadArgs } from "../../../utils/parsers.js";
2
+ import { defineEventHandler, createError } from "h3";
3
+ import { useZenstack } from "../../../utils/index.js";
4
+ import { getConfig } from "../../../utils/helpers.js";
5
5
  export default defineEventHandler(async (event) => {
6
6
  const model = parseModel(event);
7
+ const config = getConfig();
8
+ if (!config.expose[model]?.find((permission) => permission === "read")) {
9
+ throw createError({ statusCode: 403, statusMessage: "Forbidden" });
10
+ }
11
+ const client = parseClient(event);
7
12
  const readArgs = parseReadArgs(event, model);
8
- const operations = getModelOperations(event, model);
9
- const data = await operations.findMany({
10
- orderBy: readArgs.orderBy,
11
- include: readArgs.include,
13
+ const zenstack = useZenstack();
14
+ return zenstack.findMany({
15
+ client,
16
+ model,
12
17
  skip: readArgs.skip,
13
18
  take: readArgs.take,
19
+ include: readArgs.include,
20
+ orderBy: readArgs.orderBy,
14
21
  where: readArgs.where
15
- }).catch((err) => {
16
- throw createError(err);
17
22
  });
18
- return { data };
19
23
  });
@@ -1,6 +1,6 @@
1
1
  declare const _default: import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<{
2
2
  data: {
3
3
  [x: string]: any;
4
- };
4
+ } & {};
5
5
  }>>;
6
6
  export default _default;
@@ -1,17 +1,15 @@
1
- import { parseModel, parseCreateArgs } from "../../../utils/parsers.js";
2
- import { defineEventHandler } from "h3";
3
- import { getModelOperations, includeAll } from "../../../utils/index.js";
4
- import { createError } from "../../../utils/error.js";
1
+ import { parseModel, parseCreateArgs, parseClient } from "../../../utils/parsers.js";
2
+ import { defineEventHandler, createError } from "h3";
3
+ import { useZenstack } from "../../../utils/index.js";
4
+ import { getConfig } from "../../../utils/helpers.js";
5
5
  export default defineEventHandler(async (event) => {
6
6
  const model = parseModel(event);
7
+ const config = getConfig();
8
+ if (!config.expose[model]?.find((permission) => permission === "create")) {
9
+ throw createError({ statusCode: 403, statusMessage: "Forbidden" });
10
+ }
11
+ const client = parseClient(event);
7
12
  const createArgs = await parseCreateArgs(event, model);
8
- const operations = getModelOperations(event, model);
9
- const include = includeAll(model);
10
- const data = await operations.create({
11
- data: createArgs.data,
12
- include
13
- }).catch((err) => {
14
- throw createError(err);
15
- });
16
- return { data };
13
+ const zenstack = useZenstack();
14
+ return zenstack.create({ client, model, data: createArgs.data });
17
15
  });
@@ -0,0 +1,2 @@
1
+ declare const _default: import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<void>>;
2
+ export default _default;
@@ -0,0 +1,23 @@
1
+ import { defineEventHandler, createEventStream } from "h3";
2
+ import { useNitroApp } from "nitropack/runtime";
3
+ import { getConfig } from "../utils/helpers.js";
4
+ export default defineEventHandler(async (event) => {
5
+ const eventStream = createEventStream(event);
6
+ const nitroApp = useNitroApp();
7
+ const config = getConfig();
8
+ nitroApp.hooks.hook("zenstack:after_mutation", (action, model, items) => {
9
+ if (!config.expose[model]?.find((permission) => permission === "read")) {
10
+ return;
11
+ }
12
+ const message = {
13
+ model,
14
+ action,
15
+ ids: items.map((item) => item.id)
16
+ };
17
+ eventStream.push(JSON.stringify(message));
18
+ });
19
+ eventStream.onClosed(async () => {
20
+ await eventStream.close();
21
+ });
22
+ return eventStream.send();
23
+ });
@@ -0,0 +1,9 @@
1
+ import type { $Zmodel, $Zdef, $ZcreateData, $ZupdateData } from '#build/types/nuxt-zenstack';
2
+ import type { PrivateModuleOptions } from '../../types/index.js';
3
+ export declare function getModelDef(model: $Zmodel): $Zdef;
4
+ export declare function isIdString(model: $Zmodel): boolean;
5
+ export declare function getModels(): $Zmodel[];
6
+ export declare function isValidModel(model: $Zmodel): boolean;
7
+ export declare function sanitizeCreateData<Zmodel extends $Zmodel>(model: Zmodel, data: $ZcreateData<Zmodel>): $ZcreateData<Zmodel>;
8
+ export declare function sanitizeUpdateData<Zmodel extends $Zmodel>(model: Zmodel, data: $ZupdateData<Zmodel>): $ZupdateData<Zmodel>;
9
+ export declare function getConfig(): PrivateModuleOptions;
@@ -0,0 +1,39 @@
1
+ import { zenstackSchema } from "nuxt-zenstack-server.mjs";
2
+ import { useRuntimeConfig } from "#imports";
3
+ export function getModelDef(model) {
4
+ return zenstackSchema.models[model];
5
+ }
6
+ export function isIdString(model) {
7
+ const modelDef = getModelDef(model);
8
+ if (!modelDef.uniqueFields.id)
9
+ throw new Error(`Model ${model.toString()} does not have an id as a unique field`);
10
+ return modelDef.uniqueFields.id.type === "String";
11
+ }
12
+ export function getModels() {
13
+ return Object.keys(zenstackSchema.models);
14
+ }
15
+ export function isValidModel(model) {
16
+ return getModels().includes(model);
17
+ }
18
+ function getRelationalFields(model) {
19
+ const modelDef = getModelDef(model);
20
+ return Object.entries(modelDef.fields).filter(([_field, fieldDef]) => isValidModel(fieldDef.type)).map(([field]) => field);
21
+ }
22
+ export function sanitizeCreateData(model, data) {
23
+ const relationalFields = getRelationalFields(model);
24
+ relationalFields.forEach((field) => {
25
+ data[field] = void 0;
26
+ });
27
+ return data;
28
+ }
29
+ export function sanitizeUpdateData(model, data) {
30
+ const relationalFields = getRelationalFields(model);
31
+ relationalFields.forEach((field) => {
32
+ data[field] = void 0;
33
+ });
34
+ return data;
35
+ }
36
+ export function getConfig() {
37
+ const config = useRuntimeConfig();
38
+ return config.zenstack;
39
+ }
@@ -1,8 +1,15 @@
1
- import type { $Zmodel, $Zoperations, $Zdef } from '#build/types/nuxt-zenstack';
1
+ import { _delete } from './operations/delete.js';
2
+ import { update } from './operations/update.js';
3
+ import { findUnique } from './operations/findUnique.js';
4
+ import { findMany } from './operations/findMany.js';
5
+ import { create } from './operations/create.js';
6
+ import type { $Zclient } from '#build/types/nuxt-zenstack';
2
7
  import type { H3Event } from 'h3';
3
- export declare function getModelOperations<Zmodel extends $Zmodel>(event: H3Event, model: Zmodel): $Zoperations<Zmodel>;
4
- export declare function getModelDef(model: $Zmodel): $Zdef;
5
- export declare function isIdString(model: $Zmodel): boolean;
6
- export declare function getModels(): $Zmodel[];
7
- export declare function isValidModel(model: $Zmodel): boolean;
8
- export declare function includeAll<Zmodel extends $Zmodel>(model: Zmodel): boolean | import("@zenstackhq/orm").SelectIncludeOmit<SchemaType, any, boolean, true>;
8
+ export declare function useZenstack(): {
9
+ delete: typeof _delete;
10
+ update: typeof update;
11
+ findUnique: typeof findUnique;
12
+ findMany: typeof findMany;
13
+ create: typeof create;
14
+ setSessionClient: (event: H3Event, client: $Zclient) => void;
15
+ };
@@ -1,44 +1,14 @@
1
- import { zenstackSchema } from "nuxt-zenstack-server.mjs";
2
- function getClient(event) {
3
- if (event.context.zenstack?.client) {
4
- return event.context.zenstack.client;
1
+ import { _delete } from "./operations/delete.js";
2
+ import { update } from "./operations/update.js";
3
+ import { findUnique } from "./operations/findUnique.js";
4
+ import { findMany } from "./operations/findMany.js";
5
+ import { create } from "./operations/create.js";
6
+ export function useZenstack() {
7
+ function setSessionClient(event, client) {
8
+ if (event.context.zenstack)
9
+ event.context.zenstack.client = client;
10
+ else
11
+ event.context.zenstack = { client };
5
12
  }
6
- throw new Error("ZenStack client not provided");
7
- }
8
- export function getModelOperations(event, model) {
9
- const db = getClient(event);
10
- return db[model.toString().toLocaleLowerCase()];
11
- }
12
- export function getModelDef(model) {
13
- return zenstackSchema.models[model];
14
- }
15
- export function isIdString(model) {
16
- const modelDef = getModelDef(model);
17
- if (!modelDef.uniqueFields.id)
18
- throw new Error(`Model ${model.toString()} does not have an id as a unique field`);
19
- return modelDef.uniqueFields.id.type === "String";
20
- }
21
- export function getModels() {
22
- return Object.keys(zenstackSchema.models);
23
- }
24
- export function isValidModel(model) {
25
- return getModels().includes(model);
26
- }
27
- export function includeAll(model) {
28
- const include = {};
29
- const modelSet = /* @__PURE__ */ new Set();
30
- function iterate(_model, acc) {
31
- const modelDef = getModelDef(_model);
32
- for (const [field, fieldDef] of Object.entries(modelDef.fields)) {
33
- if (isValidModel(fieldDef.type) && !modelSet.has(fieldDef.type)) {
34
- acc["include"] ||= {};
35
- acc["include"][field] = {};
36
- modelSet.add(fieldDef.type);
37
- iterate(fieldDef.type, acc["include"][field]);
38
- }
39
- }
40
- }
41
- modelSet.add(model);
42
- iterate(model, include);
43
- return include["include"] ?? {};
13
+ return { delete: _delete, update, findUnique, findMany, create, setSessionClient };
44
14
  }
@@ -1,4 +1,4 @@
1
- import type { $ZormError } from '#build/types/nuxt-zenstack';
1
+ import type { $Zmodel, $Zoperations, $Zclient, $ZormError } from '#build/types/nuxt-zenstack';
2
2
  import { ORMErrorReason } from '@zenstackhq/orm';
3
3
  export declare function createError(ormError: $ZormError): import("h3").H3Error<{
4
4
  ormErrorReason: ORMErrorReason;
@@ -7,3 +7,4 @@ export declare function createError(ormError: $ZormError): import("h3").H3Error<
7
7
  model?: string;
8
8
  rejectedByPolicyReason?: import("@zenstackhq/orm").RejectedByPolicyReason;
9
9
  }>;
10
+ export declare function getModelOperations<Zmodel extends $Zmodel>(client: $Zclient, model: Zmodel): $Zoperations<Zmodel>;
@@ -47,3 +47,6 @@ export function createError(ormError) {
47
47
  };
48
48
  return createH3Error(error);
49
49
  }
50
+ export function getModelOperations(client, model) {
51
+ return client[model.toString().toLocaleLowerCase()];
52
+ }
@@ -0,0 +1,10 @@
1
+ import type { $Zclient, $Zmodel, $ZcreateData, $Zitem } from '#build/types/nuxt-zenstack';
2
+ type CreateArgs<Zmodel extends $Zmodel> = {
3
+ client: $Zclient;
4
+ model: Zmodel;
5
+ data: $ZcreateData<Zmodel>;
6
+ };
7
+ export declare function create<Zmodel extends $Zmodel>(args: CreateArgs<Zmodel>): Promise<{
8
+ data: $Zitem<Zmodel>;
9
+ }>;
10
+ export {};
@@ -0,0 +1,15 @@
1
+ import { getModelOperations, createError } from "./common.js";
2
+ import { sanitizeCreateData } from "../helpers.js";
3
+ import { useNitroApp } from "nitropack/runtime";
4
+ export async function create(args) {
5
+ const operations = getModelOperations(args.client, args.model);
6
+ const sanitizedData = sanitizeCreateData(args.model, args.data);
7
+ const data = await operations.create({
8
+ data: sanitizedData
9
+ }).catch((err) => {
10
+ throw createError(err);
11
+ });
12
+ const nitroApp = useNitroApp();
13
+ await nitroApp.hooks.callHook("zenstack:after_mutation", "create", args.model, [data]);
14
+ return { data };
15
+ }
@@ -0,0 +1,10 @@
1
+ import type { $Zclient, $Zmodel, $Zid, $Zitem } from '#build/types/nuxt-zenstack';
2
+ type DeleteArgs<Zmodel extends $Zmodel> = {
3
+ client: $Zclient;
4
+ model: Zmodel;
5
+ id: $Zid<Zmodel>;
6
+ };
7
+ export declare function _delete<Zmodel extends $Zmodel>(args: DeleteArgs<Zmodel>): Promise<{
8
+ data: $Zitem<Zmodel>;
9
+ }>;
10
+ export {};
@@ -0,0 +1,16 @@
1
+ import { getModelOperations, createError } from "./common.js";
2
+ import { useNitroApp } from "nitropack/runtime";
3
+ export async function _delete(args) {
4
+ const operations = getModelOperations(args.client, args.model);
5
+ const data = await operations.delete({
6
+ // @ts-expect-error id not known here
7
+ where: {
8
+ id: args.id
9
+ }
10
+ }).catch((err) => {
11
+ throw createError(err);
12
+ });
13
+ const nitroApp = useNitroApp();
14
+ await nitroApp.hooks.callHook("zenstack:after_mutation", "delete", args.model, [data]);
15
+ return { data };
16
+ }
@@ -0,0 +1,14 @@
1
+ import type { $Zclient, $Zmodel, $Zinclude, $ZorderBy, $Zwhere, $Zitem } from '#build/types/nuxt-zenstack';
2
+ type FindManyArgs<Zmodel extends $Zmodel> = {
3
+ client: $Zclient;
4
+ model: Zmodel;
5
+ include?: $Zinclude<Zmodel>;
6
+ orderBy?: $ZorderBy<Zmodel>;
7
+ where?: $Zwhere<Zmodel>;
8
+ skip?: number;
9
+ take?: number;
10
+ };
11
+ export declare function findMany<Zmodel extends $Zmodel>(args: FindManyArgs<Zmodel>): Promise<{
12
+ data: $Zitem<Zmodel, $Zinclude<Zmodel>>[];
13
+ }>;
14
+ export {};
@@ -0,0 +1,14 @@
1
+ import { getModelOperations, createError } from "./common.js";
2
+ export async function findMany(args) {
3
+ const operations = getModelOperations(args.client, args.model);
4
+ const data = await operations.findMany({
5
+ orderBy: args.orderBy,
6
+ include: args.include,
7
+ skip: args.skip,
8
+ take: args.take,
9
+ where: args.where
10
+ }).catch((err) => {
11
+ throw createError(err);
12
+ });
13
+ return { data };
14
+ }
@@ -0,0 +1,11 @@
1
+ import type { $Zclient, $Zmodel, $Zinclude, $Zid, $Zitem } from '#build/types/nuxt-zenstack';
2
+ type FindUniqueArgs<Zmodel extends $Zmodel> = {
3
+ client: $Zclient;
4
+ model: Zmodel;
5
+ id: $Zid<Zmodel>;
6
+ include?: $Zinclude<Zmodel>;
7
+ };
8
+ export declare function findUnique<Zmodel extends $Zmodel>(args: FindUniqueArgs<Zmodel>): Promise<{
9
+ data: $Zitem<Zmodel, $Zinclude<Zmodel>>;
10
+ }>;
11
+ export {};
@@ -0,0 +1,14 @@
1
+ import { getModelOperations, createError } from "./common.js";
2
+ export async function findUnique(args) {
3
+ const operations = getModelOperations(args.client, args.model);
4
+ const data = await operations.findUnique({
5
+ include: args.include,
6
+ // @ts-expect-error id not known here
7
+ where: {
8
+ id: args.id
9
+ }
10
+ }).catch((err) => {
11
+ throw createError(err);
12
+ });
13
+ return { data };
14
+ }
@@ -0,0 +1,11 @@
1
+ import type { $Zclient, $Zmodel, $Zid, $ZupdateData, $Zitem } from '#build/types/nuxt-zenstack';
2
+ type UpdateArgs<Zmodel extends $Zmodel> = {
3
+ client: $Zclient;
4
+ model: Zmodel;
5
+ id: $Zid<Zmodel>;
6
+ data: $ZupdateData<Zmodel>;
7
+ };
8
+ export declare function update<Zmodel extends $Zmodel>(args: UpdateArgs<Zmodel>): Promise<{
9
+ data: $Zitem<Zmodel>;
10
+ }>;
11
+ export {};
@@ -0,0 +1,19 @@
1
+ import { getModelOperations, createError } from "./common.js";
2
+ import { sanitizeUpdateData } from "../helpers.js";
3
+ import { useNitroApp } from "nitropack/runtime";
4
+ export async function update(args) {
5
+ const operations = getModelOperations(args.client, args.model);
6
+ const sanitizedData = sanitizeUpdateData(args.model, args.data);
7
+ const data = await operations.update({
8
+ data: sanitizedData,
9
+ // @ts-expect-error id not known here
10
+ where: {
11
+ id: args.id
12
+ }
13
+ }).catch((err) => {
14
+ throw createError(err);
15
+ });
16
+ const nitroApp = useNitroApp();
17
+ await nitroApp.hooks.callHook("zenstack:after_mutation", "update", args.model, [data]);
18
+ return { data };
19
+ }
@@ -7,6 +7,7 @@ type ReadArgs<Zmodel extends $Zmodel> = {
7
7
  skip?: number;
8
8
  take?: number;
9
9
  };
10
+ export declare function parseClient(event: H3Event): import("@zenstackhq/orm").ClientContract<SchemaType>;
10
11
  export declare function parseModel(event: H3Event): string | number | symbol;
11
12
  export declare function parseId(event: H3Event, model: $Zmodel): string | number;
12
13
  export declare function parseReadArgs<Zmodel extends $Zmodel>(event: H3Event, _model: Zmodel): ReadArgs<Zmodel>;
@@ -1,6 +1,12 @@
1
1
  import { getRouterParam, createError, getQuery, readBody } from "h3";
2
- import { isValidModel, isIdString } from "./index.js";
2
+ import { isValidModel, isIdString } from "./helpers.js";
3
3
  import { parse } from "superjson";
4
+ export function parseClient(event) {
5
+ if (event.context.zenstack?.client) {
6
+ return event.context.zenstack.client;
7
+ }
8
+ throw new Error("ZenStack client not provided");
9
+ }
4
10
  export function parseModel(event) {
5
11
  const model = getRouterParam(event, "model");
6
12
  if (isValidModel(model) === false) {
@@ -0,0 +1,12 @@
1
+ import type { $Zmodel } from '#build/types/nuxt-zenstack';
2
+ export type Status = 'idle' | 'pending' | 'success' | 'error';
3
+ export type FetchPolicy = 'cache-first' | 'fetch-only' | 'cache-only' | 'cache-and-fetch';
4
+ export interface PublicModuleOptions {
5
+ apiPath: string;
6
+ fetchPolicy: FetchPolicy;
7
+ realtime: boolean;
8
+ baseUrl: string;
9
+ }
10
+ export interface PrivateModuleOptions {
11
+ expose: Partial<Record<$Zmodel, Array<'create' | 'read' | 'update' | 'delete'>>>;
12
+ }
File without changes
@@ -0,0 +1,52 @@
1
+ import type { ClientContract, ModelOperations, ModelResult, IncludeInput, WhereInput, FindManyArgs, SimplifiedPlainResult, SelectIncludeOmit, QueryOptions, CreateArgs, UpdateArgs, ORMError, RejectedByPolicyReason, ORMErrorReason } from '@zenstackhq/orm'
2
+ import type { SchemaType } from '~~/zenstack/schema'
3
+ import type { ModelDef } from '@zenstackhq/orm/schema'
4
+ import type { H3Error } from 'h3'
5
+
6
+ type ItemGetPayload<Zmodel extends $Zmodel, Args extends SelectIncludeOmit<SchemaType, Zmodel, true>, Options extends QueryOptions<SchemaType> = QueryOptions<SchemaType>> = SimplifiedPlainResult<SchemaType, Zmodel, Args, Options>
7
+
8
+ export type $Zschema = SchemaType
9
+ export type $Zclient = ClientContract<SchemaType>
10
+ export type $Zmodel = keyof SchemaType['models']
11
+ export type $Zdef = ModelDef
12
+ export type $Zoperations<Zmodel extends $Zmodel> = ModelOperations<SchemaType, Zmodel>
13
+ export type $Zid<Zmodel extends $Zmodel> = ModelResult<SchemaType, Zmodel> extends { id: infer Id } ? Id : never
14
+ export type $Zinclude<Zmodel extends $Zmodel> = IncludeInput<SchemaType, Zmodel> | undefined
15
+ export type $Zitem<Zmodel extends $Zmodel, Zinclude extends $Zinclude = undefined> = ItemGetPayload<Zmodel, { include: Zinclude }>
16
+ export type $Zwhere<Zmodel extends $Zmodel> = WhereInput<SchemaType, Zmodel> | undefined
17
+ export type $ZorderBy<Zmodel extends $Zmodel> = FindManyArgs<SchemaType, Zmodel>['orderBy'] | undefined
18
+
19
+ type NonRelationalFields<Zmodel extends $Zmodel> = keyof $Zitem<Zmodel>
20
+ type CreateData<Zmodel extends $Zmodel> = CreateArgs<SchemaType, Zmodel>['data']
21
+ type UpdateData<Zmodel extends $Zmodel> = UpdateArgs<SchemaType, Zmodel>['data']
22
+
23
+ export type $ZcreateData<Zmodel extends $Zmodel> = Pick<CreateData<Zmodel>, NonRelationalFields<Zmodel>>
24
+ export type $ZupdateData<Zmodel extends $Zmodel> = Pick<UpdateData<Zmodel>, NonRelationalFields<Zmodel>>
25
+ export type $ZormError = ORMError
26
+ export type $Zerror = H3Error<{
27
+ ormErrorReason: ORMErrorReason
28
+ dbErrorCode?: unknown
29
+ dbErrorMessage?: string
30
+ model?: string
31
+ rejectedByPolicyReason?: RejectedByPolicyReason
32
+ }>
33
+
34
+ declare module 'h3' {
35
+ interface H3EventContext {
36
+ zenstack: {
37
+ client: ClientContract<SchemaType>
38
+ }
39
+ }
40
+ }
41
+
42
+ type RealtimeData = {
43
+ action: 'create' | 'update' | 'delete'
44
+ model: $Zmodel
45
+ ids: Array<number | string>
46
+ }
47
+
48
+ declare module 'nitropack' {
49
+ interface NitroRuntimeHooks {
50
+ 'zenstack:after_mutation': (action: 'create' | 'update' | 'delete', model: $Zmodel, items: Record<string, unknown>[]) => Promise<void> | void
51
+ }
52
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bg-dev/nuxt-zenstack",
3
- "version": "0.0.4",
3
+ "version": "0.0.6",
4
4
  "description": "ZenStack integration for Nuxt",
5
5
  "repository": {
6
6
  "url": "https://github.com/becem-gharbi/nuxt-zenstack"
@@ -42,7 +42,7 @@
42
42
  "dev:db:push": "cd playground && zen db push",
43
43
  "release": "npm run lint && npm run test && npm run prepack && changelogen --release && npm publish && git push --follow-tags",
44
44
  "lint": "eslint .",
45
- "test": "vitest run",
45
+ "test": "vitest run --no-file-parallelism",
46
46
  "test:watch": "vitest watch",
47
47
  "test:types": "vue-tsc --noEmit && cd playground && vue-tsc --noEmit",
48
48
  "test:db:push": "cd test/fixtures/basic && zen db push",
@@ -73,7 +73,7 @@
73
73
  "eslint": "^9.39.2",
74
74
  "libsql": "^0.5.22",
75
75
  "nuxt": "^4.2.2",
76
- "playwright-core": "^1.57.0",
76
+ "playwright-core": "^1.58.0",
77
77
  "typescript": "~5.9.3",
78
78
  "vitest": "^4.0.17",
79
79
  "vue-tsc": "^3.2.2"