Skip to content

Commit ba1128f

Browse files
authored
merge dev to main (#315)
2 parents 955e657 + dd62f8d commit ba1128f

File tree

37 files changed

+3234
-2117
lines changed

37 files changed

+3234
-2117
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "zenstack-monorepo",
3-
"version": "1.0.0-alpha.87",
3+
"version": "1.0.0-alpha.96",
44
"description": "",
55
"scripts": {
66
"build": "pnpm -r build",

packages/language/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@zenstackhq/language",
3-
"version": "1.0.0-alpha.87",
3+
"version": "1.0.0-alpha.96",
44
"displayName": "ZenStack modeling language compiler",
55
"description": "ZenStack modeling language compiler",
66
"homepage": "https://zenstack.dev",

packages/next/package.json

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@zenstackhq/next",
3-
"version": "1.0.0-alpha.87",
3+
"version": "1.0.0-alpha.96",
44
"displayName": "ZenStack Next.js integration",
55
"description": "ZenStack Next.js integration",
66
"homepage": "https://zenstack.dev",
@@ -21,12 +21,10 @@
2121
"author": "",
2222
"license": "MIT",
2323
"peerDependencies": {
24-
"next": "^12.3.1 || ^13",
25-
"react": "^17.0.2 || ^18"
24+
"next": "^12.3.1 || ^13"
2625
},
2726
"dependencies": {
2827
"@zenstackhq/runtime": "workspace:*",
29-
"@zenstackhq/testtools": "workspace:*",
3028
"tmp": "^0.2.1"
3129
},
3230
"devDependencies": {
@@ -40,6 +38,7 @@
4038
"superjson": "^1.11.0",
4139
"supertest": "^6.3.3",
4240
"ts-jest": "^29.0.5",
43-
"typescript": "^4.9.4"
41+
"typescript": "^4.9.4",
42+
"@zenstackhq/testtools": "workspace:*"
4443
}
4544
}

packages/plugins/openapi/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@zenstackhq/openapi",
33
"displayName": "ZenStack Plugin and Runtime for OpenAPI",
4-
"version": "1.0.0-alpha.87",
4+
"version": "1.0.0-alpha.96",
55
"description": "ZenStack plugin and runtime supporting OpenAPI",
66
"main": "index.js",
77
"repository": {

packages/plugins/openapi/src/generator.ts

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ export class OpenAPIGenerator {
5858
this.pruneComponents(components);
5959

6060
const openapi: OAPI.Document = {
61-
openapi: '3.1.0',
61+
openapi: this.getOption('specVersion', '3.1.0'),
6262
info: {
6363
title: this.getOption('title', 'ZenStack Generated API'),
6464
version: this.getOption('version', '1.0.0'),
@@ -180,6 +180,7 @@ export class OpenAPIGenerator {
180180
};
181181

182182
const definitions: OperationDefinition[] = [];
183+
const hasRelation = zmodel.fields.some((f) => isDataModel(f.$resolvedType?.decl));
183184

184185
if (ops['createOne']) {
185186
definitions.push({
@@ -191,7 +192,7 @@ export class OpenAPIGenerator {
191192
type: 'object',
192193
properties: {
193194
select: this.ref(`${model.name}Select`),
194-
include: this.ref(`${model.name}Include`),
195+
include: hasRelation ? this.ref(`${model.name}Include`) : undefined,
195196
data: this.ref(`${model.name}CreateInput`),
196197
},
197198
},
@@ -233,7 +234,7 @@ export class OpenAPIGenerator {
233234
type: 'object',
234235
properties: {
235236
select: this.ref(`${model.name}Select`),
236-
include: this.ref(`${model.name}Include`),
237+
include: hasRelation ? this.ref(`${model.name}Include`) : undefined,
237238
where: this.ref(`${model.name}WhereUniqueInput`),
238239
},
239240
},
@@ -254,7 +255,7 @@ export class OpenAPIGenerator {
254255
type: 'object',
255256
properties: {
256257
select: this.ref(`${model.name}Select`),
257-
include: this.ref(`${model.name}Include`),
258+
include: hasRelation ? this.ref(`${model.name}Include`) : undefined,
258259
where: this.ref(`${model.name}WhereInput`),
259260
},
260261
},
@@ -275,7 +276,7 @@ export class OpenAPIGenerator {
275276
type: 'object',
276277
properties: {
277278
select: this.ref(`${model.name}Select`),
278-
include: this.ref(`${model.name}Include`),
279+
include: hasRelation ? this.ref(`${model.name}Include`) : undefined,
279280
where: this.ref(`${model.name}WhereInput`),
280281
},
281282
},
@@ -296,7 +297,7 @@ export class OpenAPIGenerator {
296297
type: 'object',
297298
properties: {
298299
select: this.ref(`${model.name}Select`),
299-
include: this.ref(`${model.name}Include`),
300+
include: hasRelation ? this.ref(`${model.name}Include`) : undefined,
300301
where: this.ref(`${model.name}WhereUniqueInput`),
301302
data: this.ref(`${model.name}UpdateInput`),
302303
},
@@ -338,7 +339,7 @@ export class OpenAPIGenerator {
338339
type: 'object',
339340
properties: {
340341
select: this.ref(`${model.name}Select`),
341-
include: this.ref(`${model.name}Include`),
342+
include: hasRelation ? this.ref(`${model.name}Include`) : undefined,
342343
where: this.ref(`${model.name}WhereUniqueInput`),
343344
create: this.ref(`${model.name}CreateInput`),
344345
update: this.ref(`${model.name}UpdateInput`),
@@ -361,7 +362,7 @@ export class OpenAPIGenerator {
361362
type: 'object',
362363
properties: {
363364
select: this.ref(`${model.name}Select`),
364-
include: this.ref(`${model.name}Include`),
365+
include: hasRelation ? this.ref(`${model.name}Include`) : undefined,
365366
where: this.ref(`${model.name}WhereUniqueInput`),
366367
},
367368
},

packages/plugins/openapi/tests/openapi.test.ts

Lines changed: 80 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
1+
/* eslint-disable @typescript-eslint/no-explicit-any */
12
/// <reference types="@types/jest" />
23

34
import OpenAPIParser from '@readme/openapi-parser';
45
import { loadZModelAndDmmf } from '@zenstackhq/testtools';
56
import * as tmp from 'tmp';
7+
import * as fs from 'fs';
68
import generate from '../src';
9+
import YAML from 'yaml';
10+
import { isPlugin, Model, Plugin } from '@zenstackhq/sdk/ast';
11+
import { getLiteral } from '@zenstackhq/sdk';
712

813
describe('Open API Plugin Tests', () => {
914
it('run plugin', async () => {
@@ -68,10 +73,15 @@ model Bar {
6873
`);
6974

7075
const { name: output } = tmp.fileSync({ postfix: '.yaml' });
71-
generate(model, { schemaPath: modelFile, output }, dmmf);
76+
77+
const options = buildOptions(model, modelFile, output);
78+
generate(model, options, dmmf);
7279

7380
console.log('OpenAPI specification generated:', output);
7481

82+
const parsed = YAML.parse(fs.readFileSync(output, 'utf-8'));
83+
expect(parsed.openapi).toBe('3.1.0');
84+
7585
const api = await OpenAPIParser.validate(output);
7686
expect(api.paths?.['/user/findMany']?.['get']?.description).toBe('Find users matching the given conditions');
7787
const del = api.paths?.['/user/dodelete']?.['put'];
@@ -83,4 +93,73 @@ model Bar {
8393
expect(api.paths?.['/foo/findMany']).toBeUndefined();
8494
expect(api.paths?.['/bar/findMany']).toBeUndefined();
8595
});
96+
97+
it('options', async () => {
98+
const { model, dmmf, modelFile } = await loadZModelAndDmmf(`
99+
plugin openapi {
100+
provider = '${process.cwd()}/dist'
101+
specVersion = '3.0.0'
102+
title = 'My Awesome API'
103+
version = '1.0.0'
104+
description = 'awesome api'
105+
prefix = '/myapi'
106+
}
107+
108+
model User {
109+
id String @id
110+
}
111+
`);
112+
113+
const { name: output } = tmp.fileSync({ postfix: '.yaml' });
114+
const options = buildOptions(model, modelFile, output);
115+
generate(model, options, dmmf);
116+
117+
console.log('OpenAPI specification generated:', output);
118+
119+
const parsed = YAML.parse(fs.readFileSync(output, 'utf-8'));
120+
expect(parsed.openapi).toBe('3.0.0');
121+
122+
const api = await OpenAPIParser.validate(output);
123+
expect(api.info).toEqual(
124+
expect.objectContaining({
125+
title: 'My Awesome API',
126+
version: '1.0.0',
127+
description: 'awesome api',
128+
})
129+
);
130+
131+
expect(api.paths?.['/myapi/user/findMany']).toBeTruthy();
132+
});
133+
134+
it('v3.1.0 fields', async () => {
135+
const { model, dmmf, modelFile } = await loadZModelAndDmmf(`
136+
plugin openapi {
137+
provider = '${process.cwd()}/dist'
138+
summary = 'awesome api'
139+
}
140+
141+
model User {
142+
id String @id
143+
}
144+
`);
145+
146+
const { name: output } = tmp.fileSync({ postfix: '.yaml' });
147+
const options = buildOptions(model, modelFile, output);
148+
generate(model, options, dmmf);
149+
150+
console.log('OpenAPI specification generated:', output);
151+
152+
const parsed = YAML.parse(fs.readFileSync(output, 'utf-8'));
153+
expect(parsed.openapi).toBe('3.1.0');
154+
155+
const api = await OpenAPIParser.validate(output);
156+
expect((api.info as any).summary).toEqual('awesome api');
157+
});
86158
});
159+
160+
function buildOptions(model: Model, modelFile: string, output: string) {
161+
const optionFields = model.declarations.find((d): d is Plugin => isPlugin(d))?.fields || [];
162+
const options: any = { schemaPath: modelFile, output };
163+
optionFields.forEach((f) => (options[f.name] = getLiteral(f.value)));
164+
return options;
165+
}

packages/plugins/react/package.json

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@zenstackhq/react",
33
"displayName": "ZenStack plugin and runtime for ReactJS",
4-
"version": "1.0.0-alpha.87",
4+
"version": "1.0.0-alpha.96",
55
"description": "ZenStack plugin and runtime for ReactJS",
66
"main": "index.js",
77
"repository": {
@@ -29,22 +29,27 @@
2929
"change-case": "^4.1.2",
3030
"decimal.js": "^10.4.2",
3131
"superjson": "^1.11.0",
32-
"swr": "^2.0.3",
3332
"ts-morph": "^16.0.0"
3433
},
3534
"peerDependencies": {
3635
"react": "^17.0.2 || ^18",
37-
"react-dom": "^17.0.2 || ^18"
36+
"react-dom": "^17.0.2 || ^18",
37+
"swr": "2.x",
38+
"@tanstack/react-query": "4.x"
3839
},
3940
"devDependencies": {
41+
"@tanstack/react-query": "^4.28.0",
4042
"@types/jest": "^29.5.0",
4143
"@types/react": "^18.0.26",
4244
"@types/tmp": "^0.2.3",
45+
"@zenstackhq/testtools": "workspace:*",
4346
"copyfiles": "^2.4.1",
4447
"jest": "^29.5.0",
4548
"rimraf": "^3.0.2",
49+
"react": "^17.0.2 || ^18",
50+
"react-dom": "^17.0.2 || ^18",
51+
"swr": "^2.0.3",
4652
"ts-jest": "^29.0.5",
47-
"typescript": "^4.9.4",
48-
"@zenstackhq/testtools": "workspace:*"
53+
"typescript": "^4.9.4"
4954
}
5055
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import type { DMMF } from '@prisma/generator-helper';
2+
import { PluginError, type PluginOptions } from '@zenstackhq/sdk';
3+
import type { Model } from '@zenstackhq/sdk/ast';
4+
import { generate as reactQueryGenerate } from './react-query';
5+
import { generate as swrGenerate } from './swr';
6+
7+
export async function generate(model: Model, options: PluginOptions, dmmf: DMMF.Document) {
8+
const fetcher = (options.fetcher as string) ?? 'swr';
9+
switch (fetcher) {
10+
case 'swr':
11+
return swrGenerate(model, options, dmmf);
12+
case 'react-query':
13+
return reactQueryGenerate(model, options, dmmf);
14+
default:
15+
throw new PluginError(`Unknown "fetcher" option: ${fetcher}, use "swr" or "react-query"`);
16+
}
17+
}

0 commit comments

Comments
 (0)