@bg-dev/nuxt-zenstack 0.0.1

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/README.md ADDED
@@ -0,0 +1,75 @@
1
+ # Nuxt ZenStack
2
+
3
+ [![npm version][npm-version-src]][npm-version-href]
4
+ [![npm downloads][npm-downloads-src]][npm-downloads-href]
5
+ [![License][license-src]][license-href]
6
+ [![Nuxt][nuxt-src]][nuxt-href]
7
+
8
+ ZenStack integration for Nuxt for doing amazing things.
9
+
10
+ - [✨  Release Notes](/CHANGELOG.md)
11
+ <!-- - [🏀 Online playground](https://stackblitz.com/github/your-org/@bg-dev/nuxt-zenstack?file=playground%2Fapp.vue) -->
12
+ <!-- - [📖 &nbsp;Documentation](https://example.com) -->
13
+
14
+ ## Features
15
+
16
+ <!-- Highlight some of the features your module provide here -->
17
+ - ⛰ &nbsp;Foo
18
+ - 🚠 &nbsp;Bar
19
+ - 🌲 &nbsp;Baz
20
+
21
+ ## Quick Setup
22
+
23
+ Install the module to your Nuxt application with one command:
24
+
25
+ ```bash
26
+ npx nuxt module add @bg-dev/nuxt-zenstack
27
+ ```
28
+
29
+ That's it! You can now use Nuxt ZenStack in your Nuxt app ✨
30
+
31
+
32
+ ## Contribution
33
+
34
+ <details>
35
+ <summary>Local development</summary>
36
+
37
+ ```bash
38
+ # Install dependencies
39
+ npm install
40
+
41
+ # Generate type stubs
42
+ npm run dev:prepare
43
+
44
+ # Develop with the playground
45
+ npm run dev
46
+
47
+ # Build the playground
48
+ npm run dev:build
49
+
50
+ # Run ESLint
51
+ npm run lint
52
+
53
+ # Run Vitest
54
+ npm run test
55
+ npm run test:watch
56
+
57
+ # Release new version
58
+ npm run release
59
+ ```
60
+
61
+ </details>
62
+
63
+
64
+ <!-- Badges -->
65
+ [npm-version-src]: https://img.shields.io/npm/v/@bg-dev/nuxt-zenstack/latest.svg?style=flat&colorA=020420&colorB=00DC82
66
+ [npm-version-href]: https://npmjs.com/package/@bg-dev/nuxt-zenstack
67
+
68
+ [npm-downloads-src]: https://img.shields.io/npm/dm/@bg-dev/nuxt-zenstack.svg?style=flat&colorA=020420&colorB=00DC82
69
+ [npm-downloads-href]: https://npm.chart.dev/@bg-dev/nuxt-zenstack
70
+
71
+ [license-src]: https://img.shields.io/npm/l/@bg-dev/nuxt-zenstack.svg?style=flat&colorA=020420&colorB=00DC82
72
+ [license-href]: https://npmjs.com/package/@bg-dev/nuxt-zenstack
73
+
74
+ [nuxt-src]: https://img.shields.io/badge/Nuxt-020420?logo=nuxt
75
+ [nuxt-href]: https://nuxt.com
@@ -0,0 +1,9 @@
1
+ import * as _nuxt_schema from '@nuxt/schema';
2
+
3
+ interface ModuleOptions {
4
+ apiPath: string;
5
+ }
6
+ declare const _default: _nuxt_schema.NuxtModule<ModuleOptions, ModuleOptions, false>;
7
+
8
+ export { _default as default };
9
+ export type { ModuleOptions };
@@ -0,0 +1,9 @@
1
+ {
2
+ "name": "@bg-dev/nuxt-zenstack",
3
+ "version": "0.0.1",
4
+ "configKey": "zenstack",
5
+ "builder": {
6
+ "@nuxt/module-builder": "1.0.2",
7
+ "unbuild": "3.6.1"
8
+ }
9
+ }
@@ -0,0 +1,85 @@
1
+ import { defineNuxtModule, createResolver, addServerImports, addTemplate, addServerTemplate, addTypeTemplate, addServerHandler } from '@nuxt/kit';
2
+ import { joinURL } from 'ufo';
3
+ import { defu } from 'defu';
4
+
5
+ const name = "@bg-dev/nuxt-zenstack";
6
+ const version = "0.0.1";
7
+
8
+ const module$1 = defineNuxtModule({
9
+ meta: {
10
+ name,
11
+ version,
12
+ configKey: "zenstack"
13
+ },
14
+ // Default configuration options of the Nuxt module
15
+ defaults: {
16
+ apiPath: "/api/models"
17
+ },
18
+ setup(_options, _nuxt) {
19
+ _nuxt.options.runtimeConfig.public = defu(_nuxt.options.runtimeConfig.public, {
20
+ zenstack: {
21
+ apiPath: _options.apiPath
22
+ }
23
+ });
24
+ const resolver = createResolver(import.meta.url);
25
+ addServerImports({
26
+ from: resolver.resolve("./runtime/server/utils"),
27
+ name: "provideClient",
28
+ as: "provideZenStackClient"
29
+ });
30
+ addTemplate({
31
+ write: true,
32
+ filename: "nuxt-zenstack.mjs",
33
+ getContents: () => `
34
+ export { schema as zenstackSchema } from '~~/zenstack/schema'
35
+ `
36
+ });
37
+ addServerTemplate({
38
+ filename: "nuxt-zenstack-server.mjs",
39
+ getContents: () => `
40
+ export { schema as zenstackSchema } from '~~/zenstack/schema'
41
+ `
42
+ });
43
+ addTypeTemplate({
44
+ filename: "types/nuxt-zenstack.d.ts",
45
+ getContents: () => `
46
+ import type { ModelOperations, ModelResult, IncludeInput, WhereInput, FindManyArgs, SimplifiedPlainResult, SelectIncludeOmit, QueryOptions, CreateArgs, UpdateArgs } from '@zenstackhq/orm'
47
+ import type { SchemaType } from '~~/zenstack/schema'
48
+ type ItemGetPayload<Zmodel extends $Zmodel, Args extends SelectIncludeOmit<SchemaType, Zmodel, true>, Options extends QueryOptions<SchemaType> = QueryOptions<SchemaType>> = SimplifiedPlainResult<SchemaType, Zmodel, Args, Options>
49
+ export type $Zschema = SchemaType
50
+ export type $Zmodel = keyof SchemaType['models']
51
+ export type $Zoperations<Zmodel extends $Zmodel> = ModelOperations<SchemaType, Zmodel>
52
+ export type $Zid<Zmodel extends $Zmodel> = ModelResult<SchemaType, Zmodel> extends { id: infer Id } ? Id : never
53
+ export type $Zinclude<Zmodel extends $Zmodel> = IncludeInput<SchemaType, Zmodel>
54
+ export type $Zitem<Zmodel extends $Zmodel, Zinclude extends $Zinclude<Zmodel> = never> = ItemGetPayload<Zmodel, { include: Zinclude }>
55
+ export type $Zwhere<Zmodel extends $Zmodel> = WhereInput<SchemaType, Zmodel>
56
+ export type $ZorderBy<Zmodel extends $Zmodel> = FindManyArgs<SchemaType, Zmodel>['orderBy']
57
+ export type $ZcreateData<Zmodel extends $Zmodel> = CreateArgs<SchemaType, Zmodel>['data']
58
+ export type $ZupdateData<Zmodel extends $Zmodel> = UpdateArgs<SchemaType, Zmodel>['data']
59
+ export type $Zerror = {message: string, reason: string, rejectedByValidation: boolean, model: string}
60
+ `
61
+ });
62
+ addServerHandler({
63
+ route: joinURL(_options.apiPath, "/:model"),
64
+ handler: resolver.resolve("./runtime/server/api/[model]/index.get")
65
+ });
66
+ addServerHandler({
67
+ route: joinURL(_options.apiPath, "/:model"),
68
+ handler: resolver.resolve("./runtime/server/api/[model]/index.post")
69
+ });
70
+ addServerHandler({
71
+ route: joinURL(_options.apiPath, "/:model/:id"),
72
+ handler: resolver.resolve("./runtime/server/api/[model]/[id].patch")
73
+ });
74
+ addServerHandler({
75
+ route: joinURL(_options.apiPath, "/:model/:id"),
76
+ handler: resolver.resolve("./runtime/server/api/[model]/[id].delete")
77
+ });
78
+ addServerHandler({
79
+ route: joinURL(_options.apiPath, "/:model/:id"),
80
+ handler: resolver.resolve("./runtime/server/api/[model]/[id].get")
81
+ });
82
+ }
83
+ });
84
+
85
+ export { module$1 as default };
@@ -0,0 +1,6 @@
1
+ declare const _default: import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<{
2
+ data: {
3
+ [x: string]: any;
4
+ };
5
+ }>>;
6
+ export default _default;
@@ -0,0 +1,14 @@
1
+ import { defineEventHandler } from "h3";
2
+ import { parseModel, parseId } from "../../utils/parsers.js";
3
+ import { getModelOperations } from "../../utils/index.js";
4
+ export default defineEventHandler(async (event) => {
5
+ const model = parseModel(event);
6
+ const id = parseId(event, model);
7
+ const operations = getModelOperations(model);
8
+ const data = await operations.delete({
9
+ where: {
10
+ id
11
+ }
12
+ });
13
+ return { data };
14
+ });
@@ -0,0 +1,6 @@
1
+ declare const _default: import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<{
2
+ data: {
3
+ [x: string]: any;
4
+ } | null;
5
+ }>>;
6
+ export default _default;
@@ -0,0 +1,16 @@
1
+ import { parseModel, parseId, parseReadArgs } from "../../utils/parsers.js";
2
+ import { defineEventHandler } from "h3";
3
+ import { getModelOperations } from "../../utils/index.js";
4
+ export default defineEventHandler(async (event) => {
5
+ const model = parseModel(event);
6
+ const id = parseId(event, model);
7
+ const readArgs = parseReadArgs(event, model);
8
+ const operations = getModelOperations(model);
9
+ const data = await operations.findUnique({
10
+ include: readArgs.include,
11
+ where: {
12
+ id
13
+ }
14
+ });
15
+ return { data };
16
+ });
@@ -0,0 +1,6 @@
1
+ declare const _default: import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<{
2
+ data: {
3
+ [x: string]: any;
4
+ };
5
+ }>>;
6
+ export default _default;
@@ -0,0 +1,16 @@
1
+ import { parseModel, parseId, parseUpdateData } from "../../utils/parsers.js";
2
+ import { defineEventHandler } from "h3";
3
+ import { getModelOperations } from "../../utils/index.js";
4
+ export default defineEventHandler(async (event) => {
5
+ const model = parseModel(event);
6
+ const id = parseId(event, model);
7
+ const updateData = await parseUpdateData(event, model);
8
+ const operations = getModelOperations(model);
9
+ const data = await operations.update({
10
+ data: updateData.data,
11
+ where: {
12
+ id
13
+ }
14
+ });
15
+ return { data };
16
+ });
@@ -0,0 +1,6 @@
1
+ declare const _default: import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<{
2
+ data: {
3
+ [x: string]: any;
4
+ }[];
5
+ }>>;
6
+ export default _default;
@@ -0,0 +1,16 @@
1
+ import { parseModel, parseReadArgs } from "../../utils/parsers.js";
2
+ import { defineEventHandler } from "h3";
3
+ import { getModelOperations } from "../../utils/index.js";
4
+ export default defineEventHandler(async (event) => {
5
+ const model = parseModel(event);
6
+ const readArgs = parseReadArgs(event, model);
7
+ const operations = getModelOperations(model);
8
+ const data = await operations.findMany({
9
+ orderBy: readArgs.orderBy,
10
+ include: readArgs.include,
11
+ skip: readArgs.skip,
12
+ take: readArgs.take,
13
+ where: readArgs.where
14
+ });
15
+ return { data };
16
+ });
@@ -0,0 +1,6 @@
1
+ declare const _default: import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<{
2
+ data: {
3
+ [x: string]: any;
4
+ };
5
+ }>>;
6
+ export default _default;
@@ -0,0 +1,12 @@
1
+ import { parseModel, parseCreateData } from "../../utils/parsers.js";
2
+ import { defineEventHandler } from "h3";
3
+ import { getModelOperations } from "../../utils/index.js";
4
+ export default defineEventHandler(async (event) => {
5
+ const model = parseModel(event);
6
+ const createData = await parseCreateData(event, model);
7
+ const operations = getModelOperations(model);
8
+ const data = await operations.create({
9
+ data: createData.data
10
+ });
11
+ return { data };
12
+ });
@@ -0,0 +1,3 @@
1
+ {
2
+ "extends": "../../../.nuxt/tsconfig.server.json",
3
+ }
@@ -0,0 +1,11 @@
1
+ import type { ClientContract } from '@zenstackhq/orm';
2
+ import type { $Zschema, $Zmodel, $Zoperations } from '#build/types/nuxt-zenstack';
3
+ declare let _client: ClientContract<$Zschema> | null;
4
+ export declare function provideClient(client: typeof _client): void;
5
+ export declare function getClient(): ClientContract<SchemaType>;
6
+ export declare function getModelDef(model: $Zmodel): any;
7
+ export declare function isIdString(model: $Zmodel): boolean;
8
+ export declare function getModels(): $Zmodel[];
9
+ export declare function isValidModel(model: $Zmodel): boolean;
10
+ export declare function getModelOperations<Zmodel extends $Zmodel>(model: Zmodel): $Zoperations<Zmodel>;
11
+ export {};
@@ -0,0 +1,27 @@
1
+ import { zenstackSchema } from "nuxt-zenstack-server.mjs";
2
+ let _client = null;
3
+ export function provideClient(client) {
4
+ _client = client;
5
+ }
6
+ export function getClient() {
7
+ if (_client) {
8
+ return _client;
9
+ }
10
+ throw new Error("ZenStack client not provided");
11
+ }
12
+ export function getModelDef(model) {
13
+ return zenstackSchema.models[model];
14
+ }
15
+ export function isIdString(model) {
16
+ return getModelDef(model).uniqueFields.id.type === "String";
17
+ }
18
+ export function getModels() {
19
+ return Object.keys(zenstackSchema.models);
20
+ }
21
+ export function isValidModel(model) {
22
+ return getModels().includes(model);
23
+ }
24
+ export function getModelOperations(model) {
25
+ const db = getClient();
26
+ return db[model.toString().toLocaleLowerCase()];
27
+ }
@@ -0,0 +1,19 @@
1
+ import type { H3Event } from 'h3';
2
+ import type { $Zmodel, $Zinclude, $Zwhere, $ZorderBy, $ZcreateData, $ZupdateData } from '#build/types/nuxt-zenstack';
3
+ type ReadArgs<Zmodel extends $Zmodel> = {
4
+ include?: $Zinclude<Zmodel>;
5
+ where?: $Zwhere<Zmodel>;
6
+ orderBy?: $ZorderBy<Zmodel>;
7
+ skip?: number;
8
+ take?: number;
9
+ };
10
+ export declare function parseModel(event: H3Event): string | number | symbol;
11
+ export declare function parseId(event: H3Event, model: $Zmodel): string | number;
12
+ export declare function parseReadArgs<Zmodel extends $Zmodel>(event: H3Event, _model: Zmodel): ReadArgs<Zmodel>;
13
+ export declare function parseCreateData<Zmodel extends $Zmodel>(event: H3Event, _model: Zmodel): Promise<{
14
+ data: $ZcreateData<Zmodel>;
15
+ }>;
16
+ export declare function parseUpdateData<Zmodel extends $Zmodel>(event: H3Event, _model: Zmodel): Promise<{
17
+ data: $ZupdateData<Zmodel>;
18
+ }>;
19
+ export {};
@@ -0,0 +1,28 @@
1
+ import { getRouterParam, createError, getQuery, readBody } from "h3";
2
+ import { isValidModel, isIdString } from "./index.js";
3
+ import { parse } from "superjson";
4
+ export function parseModel(event) {
5
+ const model = getRouterParam(event, "model");
6
+ if (isValidModel(model) === false) {
7
+ throw createError({ statusCode: 400, statusMessage: "Invalid model" });
8
+ }
9
+ return model;
10
+ }
11
+ export function parseId(event, model) {
12
+ const id = getRouterParam(event, "id");
13
+ const parsedId = isIdString(model) ? id : Number(id);
14
+ if (typeof parsedId === "number" && Number.isNaN(parsedId)) {
15
+ throw createError({ statusCode: 400, statusMessage: "Invalid id" });
16
+ }
17
+ return id;
18
+ }
19
+ export function parseReadArgs(event, _model) {
20
+ const query = getQuery(event);
21
+ return query?.q ? parse(query.q) : {};
22
+ }
23
+ export async function parseCreateData(event, _model) {
24
+ return readBody(event);
25
+ }
26
+ export async function parseUpdateData(event, _model) {
27
+ return readBody(event);
28
+ }
@@ -0,0 +1,3 @@
1
+ export { default } from './module.mjs'
2
+
3
+ export { type ModuleOptions } from './module.mjs'
package/package.json ADDED
@@ -0,0 +1,79 @@
1
+ {
2
+ "name": "@bg-dev/nuxt-zenstack",
3
+ "version": "0.0.1",
4
+ "description": "ZenStack integration for Nuxt",
5
+ "repository": {
6
+ "url": "https://github.com/becem-gharbi/nuxt-zenstack"
7
+ },
8
+ "author": {
9
+ "name": "Becem Gharbi"
10
+ },
11
+ "license": "MIT",
12
+ "type": "module",
13
+ "keywords": [
14
+ "nuxt",
15
+ "ZenStack",
16
+ "module"
17
+ ],
18
+ "exports": {
19
+ ".": {
20
+ "types": "./dist/types.d.mts",
21
+ "import": "./dist/module.mjs"
22
+ }
23
+ },
24
+ "main": "./dist/module.mjs",
25
+ "typesVersions": {
26
+ "*": {
27
+ ".": [
28
+ "./dist/types.d.mts"
29
+ ]
30
+ }
31
+ },
32
+ "files": [
33
+ "dist"
34
+ ],
35
+ "scripts": {
36
+ "prepack": "nuxt-module-build build",
37
+ "dev": "npm run dev:prepare && nuxt dev playground",
38
+ "dev:build": "nuxt build playground",
39
+ "dev:prepare": "nuxt-module-build build --stub && nuxt-module-build prepare && nuxt prepare playground",
40
+ "dev:db:generate": "cd playground && zen generate",
41
+ "dev:db:push": "cd playground && zen db push",
42
+ "release": "npm run lint && npm run test && npm run prepack && changelogen --release && npm publish && git push --follow-tags",
43
+ "lint": "eslint .",
44
+ "test": "vitest run",
45
+ "test:watch": "vitest watch",
46
+ "test:types": "vue-tsc --noEmit && cd playground && vue-tsc --noEmit",
47
+ "test:db:push": "cd test/fixtures/basic && zen db push",
48
+ "test:db:generate": "cd test/fixtures/basic && zen generate",
49
+ "typecheck": "nuxt typecheck"
50
+ },
51
+ "dependencies": {
52
+ "@nuxt/kit": "^4.2.2",
53
+ "@zenstackhq/orm": "3.2.1",
54
+ "defu": "^6.1.4",
55
+ "superjson": "^2.2.6",
56
+ "ufo": "^1.6.3"
57
+ },
58
+ "devDependencies": {
59
+ "@nuxt/devtools": "^3.1.1",
60
+ "@nuxt/eslint": "1.12.1",
61
+ "@nuxt/eslint-config": "^1.12.1",
62
+ "@nuxt/module-builder": "^1.0.2",
63
+ "@nuxt/schema": "^4.2.2",
64
+ "@nuxt/test-utils": "^3.23.0",
65
+ "@types/node": "latest",
66
+ "@zenstackhq/cli": "3.2.1",
67
+ "changelogen": "^0.6.2",
68
+ "eslint": "^9.39.2",
69
+ "libsql": "^0.5.22",
70
+ "nuxt": "^4.2.2",
71
+ "typescript": "~5.9.3",
72
+ "vitest": "^4.0.17",
73
+ "vue-tsc": "^3.2.2"
74
+ },
75
+ "publishConfig": {
76
+ "access": "public",
77
+ "tag": "latest"
78
+ }
79
+ }