From 3893d971daa420a5f8b58ccc2e5fdee5657c0fde Mon Sep 17 00:00:00 2001 From: ymc9 <104139426+ymc9@users.noreply.github.com> Date: Tue, 4 Jul 2023 20:10:39 +0800 Subject: [PATCH 1/2] chore: rename rest-api's option from manageCustomResponse to sendResponse --- packages/server/src/express/middleware.ts | 24 +++++++++++-------- packages/server/tests/adapter/express.test.ts | 2 +- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/packages/server/src/express/middleware.ts b/packages/server/src/express/middleware.ts index 7f7df5ddc..492004a66 100644 --- a/packages/server/src/express/middleware.ts +++ b/packages/server/src/express/middleware.ts @@ -14,14 +14,17 @@ 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. + * Controls if the middleware directly sends a response. If set to false, + * the response is stored in the `res.locals` object and then the middleware + * calls the `next()` function to pass the control to the next middleware. + * Subsequent middleware or request handlers need to make sure to send + * a response. * - * Defaults to false; + * Defaults to true; */ - manageCustomResponse?: boolean; + sendResponse?: boolean; } /** @@ -43,9 +46,9 @@ const factory = (options: MiddlewareOptions): Handler => { return async (request, response, next) => { const prisma = (await options.getPrisma(request, response)) as DbClientContract; - const { manageCustomResponse } = options; + const { sendResponse } = options; - if (manageCustomResponse && !prisma) { + if (sendResponse === false && !prisma) { throw new Error('unable to get prisma from request context'); } @@ -69,7 +72,7 @@ const factory = (options: MiddlewareOptions): Handler => { } query = buildUrlQuery(rawQuery, useSuperJson); } catch { - if (manageCustomResponse) { + if (sendResponse === false) { throw new Error('invalid query parameters'); } return response.status(400).json(marshalToObject({ message: 'invalid query parameters' }, useSuperJson)); @@ -86,7 +89,8 @@ const factory = (options: MiddlewareOptions): Handler => { zodSchemas, logger: options.logger, }); - if (manageCustomResponse) { + if (sendResponse === false) { + // attach response and pass control to the next middleware response.locals = { status: r.status, body: r.body, @@ -95,7 +99,7 @@ const factory = (options: MiddlewareOptions): Handler => { } return response.status(r.status).json(marshalToObject(r.body, useSuperJson)); } catch (err) { - if (manageCustomResponse) { + if (sendResponse === false) { throw err; } return response diff --git a/packages/server/tests/adapter/express.test.ts b/packages/server/tests/adapter/express.test.ts index 0a964ef41..7121edcf9 100644 --- a/packages/server/tests/adapter/express.test.ts +++ b/packages/server/tests/adapter/express.test.ts @@ -265,7 +265,7 @@ describe('Express adapter tests - rest handler with customMiddleware', () => { modelMeta, zodSchemas, handler: RESTAPIHandler({ endpoint: 'http://localhost/api' }), - manageCustomResponse: true, + sendResponse: false, }) ); From 41ff5889d459f73170dd01d290bf9e6f8fd91c96 Mon Sep 17 00:00:00 2001 From: ymc9 <104139426+ymc9@users.noreply.github.com> Date: Tue, 4 Jul 2023 20:33:54 +0800 Subject: [PATCH 2/2] fix: optimize the way how generated packages are loaded in test environment --- package.json | 4 ++-- .../runtime/src/enhancements/model-meta.ts | 18 +++++++++------- .../runtime/src/enhancements/policy/index.ts | 21 ++++++++++++++++++- 3 files changed, 33 insertions(+), 10 deletions(-) diff --git a/package.json b/package.json index 5d00c9db1..d27a7a01d 100644 --- a/package.json +++ b/package.json @@ -4,8 +4,8 @@ "description": "", "scripts": { "build": "pnpm -r build", - "test": "pnpm -r run test --silent", - "test-ci": "pnpm -r run test --silent", + "test": "ZENSTACK_TEST=1 pnpm -r run test --silent", + "test-ci": "ZENSTACK_TEST=1 pnpm -r run test --silent", "lint": "pnpm -r lint", "publish-all": "pnpm --filter \"./packages/**\" -r publish --access public", "publish-preview": "pnpm --filter \"./packages/**\" -r publish --registry http://localhost:4873" diff --git a/packages/runtime/src/enhancements/model-meta.ts b/packages/runtime/src/enhancements/model-meta.ts index 53fed4702..8109bbacc 100644 --- a/packages/runtime/src/enhancements/model-meta.ts +++ b/packages/runtime/src/enhancements/model-meta.ts @@ -1,20 +1,24 @@ /* eslint-disable @typescript-eslint/no-var-requires */ import { lowerCaseFirst } from 'lower-case-first'; -import { ModelMeta } from './types'; import path from 'path'; +import { ModelMeta } from './types'; /** * Load model meta from standard location. */ export function getDefaultModelMeta(): ModelMeta { try { - if (process.env.NODE_ENV === 'test') { - // handling the case when running as tests, resolve relative to CWD - return require(path.join(process.cwd(), 'node_modules', '.zenstack', 'model-meta')).default; - } else { - return require('.zenstack/model-meta').default; - } + // normal load + return require('.zenstack/model-meta').default; } catch { + if (process.env.ZENSTACK_TEST === '1') { + try { + // special handling for running as tests, try resolving relative to CWD + return require(path.join(process.cwd(), 'node_modules', '.zenstack', 'model-meta')).default; + } catch { + throw new Error('Model meta cannot be loaded. Please make sure "zenstack generate" has been run.'); + } + } throw new Error('Model meta cannot be loaded. Please make sure "zenstack generate" has been run.'); } } diff --git a/packages/runtime/src/enhancements/policy/index.ts b/packages/runtime/src/enhancements/policy/index.ts index 59c4fb453..1fbe249f1 100644 --- a/packages/runtime/src/enhancements/policy/index.ts +++ b/packages/runtime/src/enhancements/policy/index.ts @@ -1,5 +1,7 @@ +/* eslint-disable @typescript-eslint/no-var-requires */ /* eslint-disable @typescript-eslint/no-explicit-any */ +import path from 'path'; import { AuthUser, DbClientContract } from '../../types'; import { getDefaultModelMeta } from '../model-meta'; import { makeProxy } from '../proxy'; @@ -74,9 +76,18 @@ export function withPolicy( function getDefaultPolicy(): PolicyDef { try { - // eslint-disable-next-line @typescript-eslint/no-var-requires return require('.zenstack/policy').default; } catch { + if (process.env.ZENSTACK_TEST === '1') { + try { + // special handling for running as tests, try resolving relative to CWD + return require(path.join(process.cwd(), 'node_modules', '.zenstack', 'policy')).default; + } catch { + throw new Error( + 'Policy definition cannot be loaded from default location. Please make sure "zenstack generate" has been run.' + ); + } + } throw new Error( 'Policy definition cannot be loaded from default location. Please make sure "zenstack generate" has been run.' ); @@ -88,6 +99,14 @@ function getDefaultZodSchemas(): ZodSchemas | undefined { // eslint-disable-next-line @typescript-eslint/no-var-requires return require('.zenstack/zod'); } catch { + if (process.env.ZENSTACK_TEST === '1') { + try { + // special handling for running as tests, try resolving relative to CWD + return require(path.join(process.cwd(), 'node_modules', '.zenstack', 'zod')); + } catch { + return undefined; + } + } return undefined; } }