From 8e91c2cba8d889508948da331cf911bedd6a1a6d Mon Sep 17 00:00:00 2001 From: ymc9 <104139426+ymc9@users.noreply.github.com> Date: Wed, 3 May 2023 14:12:49 -0700 Subject: [PATCH 1/8] chore: update README links --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 241039dc9..52000d3cc 100644 --- a/README.md +++ b/README.md @@ -133,8 +133,8 @@ The following diagram gives a high-level overview of how it works. ### Prisma schema extensions - [Custom attributes and functions](https://zenstack.dev/docs/reference/zmodel-language#custom-attributes-and-functions) -- Multi-file schema (coming soon) -- String-typed JSON field (coming soon) +- [Multi-file schema and model inheritance](https://zenstack.dev/docs/guides/multiple-schema) +- Strong-typed JSON field (coming soon) - 🙋🏻 [Request for an extension](https://go.zenstack.dev/chat) ## Examples From a70aa42273a4b4ea0aa5f40d586515c8f940ed72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chema=20Rold=C3=A1n?= Date: Sat, 1 Jul 2023 17:15:29 +0200 Subject: [PATCH 2/8] changes: add option to manage response middleware --- packages/server/src/express/middleware.ts | 25 +++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/packages/server/src/express/middleware.ts b/packages/server/src/express/middleware.ts index 4056cb0c0..f69329a37 100644 --- a/packages/server/src/express/middleware.ts +++ b/packages/server/src/express/middleware.ts @@ -14,6 +14,13 @@ export interface MiddlewareOptions extends AdapterBaseOptions { * Callback for getting a PrismaClient for the given request */ getPrisma: (req: Request, res: Response) => unknown | Promise; + /** + * This option is used to enable/disable the option to manage the response + * by the middleware. If set to true, the middleware will not send the + * response and the user will be responsible for sending the response. + * Defaults to true; + */ + manageCustomResponse?: boolean; } /** @@ -32,6 +39,12 @@ const factory = (options: MiddlewareOptions): Handler => { return async (request, response) => { const prisma = (await options.getPrisma(request, response)) as DbClientContract; + const { manageCustomResponse } = options; + + if (manageCustomResponse && !prisma) { + throw new Error('unable to get prisma from request context'); + } + if (!prisma) { response .status(500) @@ -53,6 +66,9 @@ const factory = (options: MiddlewareOptions): Handler => { } query = buildUrlQuery(rawQuery, useSuperJson); } catch { + if (manageCustomResponse) { + throw new Error('invalid query parameters'); + } response.status(400).json(marshalToObject({ message: 'invalid query parameters' }, useSuperJson)); return; } @@ -68,8 +84,17 @@ const factory = (options: MiddlewareOptions): Handler => { zodSchemas, logger: options.logger, }); + if (manageCustomResponse) { + return { + status: r.status, + body: r.body, + }; + } response.status(r.status).json(marshalToObject(r.body, useSuperJson)); } catch (err) { + if (manageCustomResponse) { + throw err; + } response .status(500) .json(marshalToObject({ message: `An unhandled error occurred: ${err}` }, useSuperJson)); From 73e0076f7e74d42b2a3a687427aaa972109b8456 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chema=20Rold=C3=A1n?= Date: Sat, 1 Jul 2023 17:16:56 +0200 Subject: [PATCH 3/8] changes: improve comment --- packages/server/src/express/middleware.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/server/src/express/middleware.ts b/packages/server/src/express/middleware.ts index f69329a37..ec6a71a80 100644 --- a/packages/server/src/express/middleware.ts +++ b/packages/server/src/express/middleware.ts @@ -18,7 +18,8 @@ export interface MiddlewareOptions extends AdapterBaseOptions { * This option is used to enable/disable the option to manage the response * by the middleware. If set to true, the middleware will not send the * response and the user will be responsible for sending the response. - * Defaults to true; + * + * Defaults to false; */ manageCustomResponse?: boolean; } From ebf8c26ed1bf527d9e28e8cc3d28c585bd46a867 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chema=20Rold=C3=A1n?= Date: Sat, 1 Jul 2023 17:51:18 +0200 Subject: [PATCH 4/8] changes: all paths return something --- packages/server/src/express/middleware.ts | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/packages/server/src/express/middleware.ts b/packages/server/src/express/middleware.ts index ec6a71a80..f7164574f 100644 --- a/packages/server/src/express/middleware.ts +++ b/packages/server/src/express/middleware.ts @@ -47,10 +47,9 @@ const factory = (options: MiddlewareOptions): Handler => { } if (!prisma) { - response + return response .status(500) .json(marshalToObject({ message: 'unable to get prisma from request context' }, useSuperJson)); - return; } let query: Record = {}; @@ -70,8 +69,7 @@ const factory = (options: MiddlewareOptions): Handler => { if (manageCustomResponse) { throw new Error('invalid query parameters'); } - response.status(400).json(marshalToObject({ message: 'invalid query parameters' }, useSuperJson)); - return; + return response.status(400).json(marshalToObject({ message: 'invalid query parameters' }, useSuperJson)); } try { @@ -91,12 +89,12 @@ const factory = (options: MiddlewareOptions): Handler => { body: r.body, }; } - response.status(r.status).json(marshalToObject(r.body, useSuperJson)); + return response.status(r.status).json(marshalToObject(r.body, useSuperJson)); } catch (err) { if (manageCustomResponse) { throw err; } - response + return response .status(500) .json(marshalToObject({ message: `An unhandled error occurred: ${err}` }, useSuperJson)); } From 1503fc1d1421f90223854f4a3ea401bbefaa6939 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chema=20Rold=C3=A1n?= Date: Sun, 2 Jul 2023 17:07:13 +0200 Subject: [PATCH 5/8] temp: added temporal express test for faster testing --- .../server/tests/adapter/express-temp.test.ts | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 packages/server/tests/adapter/express-temp.test.ts diff --git a/packages/server/tests/adapter/express-temp.test.ts b/packages/server/tests/adapter/express-temp.test.ts new file mode 100644 index 000000000..d74d1776b --- /dev/null +++ b/packages/server/tests/adapter/express-temp.test.ts @@ -0,0 +1,32 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +/// + +import { loadSchema } from '@zenstackhq/testtools'; +import bodyParser from 'body-parser'; +import express from 'express'; +import request from 'supertest'; +import RESTAPIHandler from '../../src/api/rest'; +import { ZenStackMiddleware } from '../../src/express'; +import { makeUrl, schema } from '../utils'; + +describe('Express adapter tests - rest handler with customMiddleware', () => { + it('run middleware', async () => { + const { prisma, zodSchemas, modelMeta } = await loadSchema(schema); + + const app = express(); + app.use(bodyParser.json()); + app.use( + '/api', + ZenStackMiddleware({ + getPrisma: () => prisma, + modelMeta, + zodSchemas, + handler: RESTAPIHandler({ endpoint: 'http://localhost/api' }), + manageCustomResponse: true, + }) + ); + + const r = await request(app).get(makeUrl('/api/post/1')); + expect(r.status).toBe(404); + }); +}); From d3448eeb8112ed94cec71423ecb21d291d777792 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chema=20Rold=C3=A1n?= Date: Mon, 3 Jul 2023 13:24:31 +0200 Subject: [PATCH 6/8] changes: added test for manage custom middleware --- packages/server/src/express/middleware.ts | 5 +-- .../server/tests/adapter/express-temp.test.ts | 32 ------------------- packages/server/tests/adapter/express.test.ts | 27 ++++++++++++++++ 3 files changed, 30 insertions(+), 34 deletions(-) delete mode 100644 packages/server/tests/adapter/express-temp.test.ts diff --git a/packages/server/src/express/middleware.ts b/packages/server/src/express/middleware.ts index f7164574f..3c97de74e 100644 --- a/packages/server/src/express/middleware.ts +++ b/packages/server/src/express/middleware.ts @@ -38,7 +38,7 @@ const factory = (options: MiddlewareOptions): Handler => { const requestHandler = options.handler || RPCAPIHandler(); const useSuperJson = options.useSuperJson === true; - return async (request, response) => { + return async (request, response, next) => { const prisma = (await options.getPrisma(request, response)) as DbClientContract; const { manageCustomResponse } = options; @@ -84,10 +84,11 @@ const factory = (options: MiddlewareOptions): Handler => { logger: options.logger, }); if (manageCustomResponse) { - return { + response.locals = { status: r.status, body: r.body, }; + return next(); } return response.status(r.status).json(marshalToObject(r.body, useSuperJson)); } catch (err) { diff --git a/packages/server/tests/adapter/express-temp.test.ts b/packages/server/tests/adapter/express-temp.test.ts deleted file mode 100644 index d74d1776b..000000000 --- a/packages/server/tests/adapter/express-temp.test.ts +++ /dev/null @@ -1,32 +0,0 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ -/// - -import { loadSchema } from '@zenstackhq/testtools'; -import bodyParser from 'body-parser'; -import express from 'express'; -import request from 'supertest'; -import RESTAPIHandler from '../../src/api/rest'; -import { ZenStackMiddleware } from '../../src/express'; -import { makeUrl, schema } from '../utils'; - -describe('Express adapter tests - rest handler with customMiddleware', () => { - it('run middleware', async () => { - const { prisma, zodSchemas, modelMeta } = await loadSchema(schema); - - const app = express(); - app.use(bodyParser.json()); - app.use( - '/api', - ZenStackMiddleware({ - getPrisma: () => prisma, - modelMeta, - zodSchemas, - handler: RESTAPIHandler({ endpoint: 'http://localhost/api' }), - manageCustomResponse: true, - }) - ); - - const r = await request(app).get(makeUrl('/api/post/1')); - expect(r.status).toBe(404); - }); -}); diff --git a/packages/server/tests/adapter/express.test.ts b/packages/server/tests/adapter/express.test.ts index df96ec7a2..f46b22cb7 100644 --- a/packages/server/tests/adapter/express.test.ts +++ b/packages/server/tests/adapter/express.test.ts @@ -251,3 +251,30 @@ describe('Express adapter tests - rest handler', () => { expect(await prisma.user.findMany()).toHaveLength(0); }); }); + +describe('Express adapter tests - rest handler with customMiddleware', () => { + it('run middleware', async () => { + const { prisma, zodSchemas, modelMeta } = await loadSchema(schema); + + const app = express(); + app.use(bodyParser.json()); + app.use( + '/api', + ZenStackMiddleware({ + getPrisma: () => prisma, + modelMeta, + zodSchemas, + handler: RESTAPIHandler({ endpoint: 'http://localhost/api' }), + manageCustomResponse: true, + }) + ); + + app.use((req, res) => { + res.status(res.locals.status).json({ message: res.locals.body }); + }); + + const r = await request(app).get(makeUrl('/api/post/1')); + expect(r.status).toBe(404); + expect(r.body).toHaveProperty('errors'); + }); +}); From 52983b9ac884e2c92500eb6215f86f454b166fb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chema=20Rold=C3=A1n?= Date: Mon, 3 Jul 2023 13:32:47 +0200 Subject: [PATCH 7/8] changes: fix everything about jest --- packages/server/tests/adapter/express.test.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/server/tests/adapter/express.test.ts b/packages/server/tests/adapter/express.test.ts index f46b22cb7..2c6438d85 100644 --- a/packages/server/tests/adapter/express.test.ts +++ b/packages/server/tests/adapter/express.test.ts @@ -275,6 +275,7 @@ describe('Express adapter tests - rest handler with customMiddleware', () => { const r = await request(app).get(makeUrl('/api/post/1')); expect(r.status).toBe(404); - expect(r.body).toHaveProperty('errors'); + console.log(r.body); + expect(r.body.message).toHaveProperty('errors'); }); }); From 86c08c9efd6f7058d1cea6dd0ede2e9fdae19252 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chema=20Rold=C3=A1n?= Date: Mon, 3 Jul 2023 13:34:31 +0200 Subject: [PATCH 8/8] changes: remove console.log --- packages/server/tests/adapter/express.test.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/server/tests/adapter/express.test.ts b/packages/server/tests/adapter/express.test.ts index 2c6438d85..0a964ef41 100644 --- a/packages/server/tests/adapter/express.test.ts +++ b/packages/server/tests/adapter/express.test.ts @@ -275,7 +275,6 @@ describe('Express adapter tests - rest handler with customMiddleware', () => { const r = await request(app).get(makeUrl('/api/post/1')); expect(r.status).toBe(404); - console.log(r.body); expect(r.body.message).toHaveProperty('errors'); }); });