From bd0f39b3df3e68c39c84743d14557c57f10ffa5d Mon Sep 17 00:00:00 2001 From: Nicolas Froidure Date: Sun, 5 Apr 2020 10:39:24 +0200 Subject: [PATCH] refactor(builds): improve the builds --- .../src/__snapshots__/index.test.ts.snap | 15 +++ .../src/handlers/getParameters.ts | 96 +++++++++++++++++++ .../whook-example/src/handlers/putEcho.ts | 1 + .../services/__snapshots__/API.test.ts.snap | 81 ++++++++++++++++ .../src/commands/testHTTPFunction.ts | 10 +- .../src/wrappers/googleHTTPFunction.ts | 85 +++------------- .../whook/src/services/API_DEFINITIONS.ts | 2 +- 7 files changed, 211 insertions(+), 79 deletions(-) create mode 100644 packages/whook-example/src/handlers/getParameters.ts diff --git a/packages/whook-example/src/__snapshots__/index.test.ts.snap b/packages/whook-example/src/__snapshots__/index.test.ts.snap index 4e2f2df1..4cf01a09 100644 --- a/packages/whook-example/src/__snapshots__/index.test.ts.snap +++ b/packages/whook-example/src/__snapshots__/index.test.ts.snap @@ -210,6 +210,9 @@ Object { Array [ "💿 - Loading getOpenAPIWrapped initializer from /home/whoiam/projects/whook/packages/whook-example/src/handlers/getOpenAPI.ts.", ], + Array [ + "💿 - Loading getParametersWrapped initializer from /home/whoiam/projects/whook/packages/whook-example/src/handlers/getParameters.ts.", + ], Array [ "💿 - Loading getPingWrapped initializer from /home/whoiam/projects/whook/dist/handlers/getPing.js.", ], @@ -252,6 +255,9 @@ Object { Array [ "💿 - Service \\"getOpenAPIWrapped\\" found in: /home/whoiam/projects/whook/packages/whook-example/src/handlers/getOpenAPI.ts", ], + Array [ + "💿 - Service \\"getParametersWrapped\\" found in: /home/whoiam/projects/whook/packages/whook-example/src/handlers/getParameters.ts", + ], Array [ "💿 - Service \\"getPingWrapped\\" found in: /home/whoiam/projects/whook/dist/handlers/getPing.js", ], @@ -276,6 +282,9 @@ Object { Array [ "🔐 - Initializing the authorization wrapper for \\"getOpenAPI\\".", ], + Array [ + "🔐 - Initializing the authorization wrapper for \\"getParameters\\".", + ], Array [ "🔐 - Initializing the authorization wrapper for \\"getPing\\".", ], @@ -669,6 +678,12 @@ Object { Array [ "🛂 - Dynamic import of: /home/whoiam/projects/whook/packages/whook-example/src/handlers/getOpenAPI.ts", ], + Array [ + "🛂 - Dynamic import of: /home/whoiam/projects/whook/packages/whook-example/src/handlers/getParameters.ts", + ], + Array [ + "🛂 - Dynamic import of: /home/whoiam/projects/whook/packages/whook-example/src/handlers/getParameters.ts", + ], Array [ "🛂 - Dynamic import of: /home/whoiam/projects/whook/packages/whook-example/src/handlers/getTime.ts", ], diff --git a/packages/whook-example/src/handlers/getParameters.ts b/packages/whook-example/src/handlers/getParameters.ts new file mode 100644 index 00000000..09dddf9c --- /dev/null +++ b/packages/whook-example/src/handlers/getParameters.ts @@ -0,0 +1,96 @@ +import { autoHandler } from 'knifecycle'; +import type { + WhookResponse, + WhookAPIHandlerDefinition, + WhookAPIParameterDefinition, + WhookHandlerFunction, +} from '@whook/whook'; +import type { DelayService } from 'common-services'; + +export const pathParam1Parameter: WhookAPIParameterDefinition = { + name: 'pathParam1', + parameter: { + in: 'path', + name: 'pathParam1', + required: true, + description: 'Duration in milliseconds', + schema: { + type: 'number', + }, + }, +}; +export const pathParam2Parameter: WhookAPIParameterDefinition = { + name: 'pathParam2', + parameter: { + in: 'path', + name: 'pathParam2', + required: true, + description: 'Duration in milliseconds', + schema: { + type: 'array', + items: { + type: 'string', + }, + }, + }, +}; + +export const definition: WhookAPIHandlerDefinition = { + path: `/{${pathParam1Parameter.parameter.name}}/{${pathParam2Parameter.parameter.name}}`, + method: 'get', + operation: { + operationId: 'getParameters', + summary: 'An handler intended to test parameters.', + tags: ['example'], + parameters: [ + { + $ref: `#/components/parameters/${pathParam1Parameter.name}`, + }, + { + $ref: `#/components/parameters/${pathParam2Parameter.name}`, + }, + { + in: 'header', + name: 'aHeader', + schema: { + type: 'boolean', + }, + }, + ], + responses: { + 204: { + description: 'Delay expired', + }, + }, + }, +}; + +async function getParameters( + _, + { + aHeader, + pathParam1, + pathParam2, + }: { + aHeader: boolean; + pathParam1: number; + pathParam2: string[]; + }, +): Promise< + WhookResponse< + 200, + {}, + { aHeader: boolean; pathParam1: number; pathParam2: string[] } + > +> { + return { + status: 200, + body: { + aHeader, + pathParam1, + pathParam2, + }, + }; +} + +export default autoHandler(getParameters); diff --git a/packages/whook-example/src/handlers/putEcho.ts b/packages/whook-example/src/handlers/putEcho.ts index 3a0994d1..685f62a3 100644 --- a/packages/whook-example/src/handlers/putEcho.ts +++ b/packages/whook-example/src/handlers/putEcho.ts @@ -24,6 +24,7 @@ export const definition: WhookAPIHandlerDefinition = { tags: ['example'], requestBody: { description: 'The input sentence', + required: true, content: { 'application/json': { schema: echoSchema, diff --git a/packages/whook-example/src/services/__snapshots__/API.test.ts.snap b/packages/whook-example/src/services/__snapshots__/API.test.ts.snap index 0b45bec0..d5aa3ed0 100644 --- a/packages/whook-example/src/services/__snapshots__/API.test.ts.snap +++ b/packages/whook-example/src/services/__snapshots__/API.test.ts.snap @@ -16,6 +16,7 @@ Array [ "get /openAPI", "get /ping", "get /time", + "get /{pathParam1}/{pathParam2}", "put /echo", ] `; @@ -25,12 +26,14 @@ Array [ "get /delay", "get /ping", "get /time", + "get /{pathParam1}/{pathParam2}", "options /delay", "options /diag", "options /echo", "options /openAPI", "options /ping", "options /time", + "options /{pathParam1}/{pathParam2}", "put /echo", ] `; @@ -48,6 +51,7 @@ Array [ "get /openAPI", "get /ping", "get /time", + "get /{pathParam1}/{pathParam2}", "put /echo", ] `; @@ -74,6 +78,27 @@ Object { "type": "number", }, }, + "pathParam1": Object { + "description": "Duration in milliseconds", + "in": "path", + "name": "pathParam1", + "required": true, + "schema": Object { + "type": "number", + }, + }, + "pathParam2": Object { + "description": "Duration in milliseconds", + "in": "path", + "name": "pathParam2", + "required": true, + "schema": Object { + "items": Object { + "type": "string", + }, + "type": "array", + }, + }, }, "schemas": Object { "TimeSchema": Object { @@ -250,6 +275,7 @@ Object { }, }, "description": "The input sentence", + "required": true, }, "responses": Object { "200": Object { @@ -427,6 +453,61 @@ Object { }, }, }, + "/{pathParam1}/{pathParam2}": Object { + "get": Object { + "operationId": "getParameters", + "parameters": Array [ + Object { + "$ref": "#/components/parameters/pathParam1", + }, + Object { + "$ref": "#/components/parameters/pathParam2", + }, + Object { + "in": "header", + "name": "aHeader", + "schema": Object { + "type": "boolean", + }, + }, + ], + "responses": Object { + "204": Object { + "description": "Delay expired", + }, + }, + "summary": "An handler intended to test parameters.", + "tags": Array [ + "example", + ], + }, + "options": Object { + "operationId": "optionsWithCORS", + "parameters": Array [ + Object { + "$ref": "#/components/parameters/pathParam1", + }, + Object { + "$ref": "#/components/parameters/pathParam2", + }, + ], + "responses": Object { + "200": Object { + "description": "CORS sent.", + }, + }, + "summary": "Enable OPTIONS for CORS", + "tags": Array [ + "CORS", + ], + "x-whook": Object { + "private": true, + "sourceOperationId": "getParameters", + "suffix": "CORS", + "type": "http", + }, + }, + }, }, "servers": Array [ Object { diff --git a/packages/whook-gcp-functions/src/commands/testHTTPFunction.ts b/packages/whook-gcp-functions/src/commands/testHTTPFunction.ts index dca67eae..a2713694 100644 --- a/packages/whook-gcp-functions/src/commands/testHTTPFunction.ts +++ b/packages/whook-gcp-functions/src/commands/testHTTPFunction.ts @@ -91,6 +91,8 @@ async function initTestHTTPLambdaCommand({ throw new YError('E_OPERATION_NOT_FOUND'); } + const hasBody = !!OPERATION.requestBody; + const parameters = JSON.parse(rawParameters); const search = ((OPERATION.parameters || []) as OpenAPIV3.ParameterObject[]) .filter((p) => p.in === 'query') .reduce((accSearch, p) => { @@ -118,8 +120,6 @@ async function initTestHTTPLambdaCommand({ return part; }) .join(PATH_SEPARATOR); - const hasBody = !!OPERATION.requestBody; - const parameters = JSON.parse(rawParameters); const gcpfRequest = { method: OPERATION.method, originalUrl: path + (search ? SEARCH_SEPARATOR + search : ''), @@ -132,8 +132,10 @@ async function initTestHTTPLambdaCommand({ rawBody: Buffer.from( hasBody ? contentType === 'application/json' - ? JSON.stringify(parameters.body) - : parameters.body + ? parameters.body + ? JSON.stringify(parameters.body) + : '' + : parameters.body || '' : '', ), }; diff --git a/packages/whook-gcp-functions/src/wrappers/googleHTTPFunction.ts b/packages/whook-gcp-functions/src/wrappers/googleHTTPFunction.ts index b9722991..68e6c7ec 100644 --- a/packages/whook-gcp-functions/src/wrappers/googleHTTPFunction.ts +++ b/packages/whook-gcp-functions/src/wrappers/googleHTTPFunction.ts @@ -8,6 +8,7 @@ import { } from '@whook/http-router'; import { reuseSpecialProps, alsoInject } from 'knifecycle'; import Ajv from 'ajv'; +import bytes from 'bytes'; import HTTPError from 'yhttperror'; import { prepareParametersValidators, @@ -48,12 +49,10 @@ type HTTPWrapperDependencies = { OPERATION: WhookOperation; DECODERS?: typeof DEFAULT_DECODERS; ENCODERS?: typeof DEFAULT_ENCODERS; - PARSED_HEADERS?: string[]; PARSERS?: typeof DEFAULT_PARSERS; STRINGIFYERS?: typeof DEFAULT_STRINGIFYERS; QUERY_PARSER: WhookQueryStringParser; BUFFER_LIMIT?: string; - apm: APMService; obfuscator: ObfuscatorService; time?: TimeService; log?: LogService; @@ -62,10 +61,11 @@ type HTTPWrapperDependencies = { const SEARCH_SEPARATOR = '?'; const PATH_SEPARATOR = '/'; -const uuidPattern = - '^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$'; -export default function wrapHandlerForAWSHTTPLambda( +export default function wrapHandlerForAWSHTTPFunction< + D, + S extends WhookHandler +>( initHandler: ServiceInitializer, ): ServiceInitializer { return alsoInject( @@ -76,24 +76,22 @@ export default function wrapHandlerForAWSHTTPLambda( 'NODE_ENV', '?DECODERS', '?ENCODERS', - '?PARSED_HEADERS', '?PARSERS', '?STRINGIFYERS', '?BUFFER_LIMIT', 'QUERY_PARSER', - 'apm', 'obfuscator', '?log', '?time', ], reuseSpecialProps( initHandler, - initHandlerForAWSHTTPLambda.bind(null, initHandler), + initHandlerForAWSHTTPFunction.bind(null, initHandler), ), ); } -async function initHandlerForAWSHTTPLambda( +async function initHandlerForAWSHTTPFunction( initHandler, { OPERATION, @@ -102,7 +100,6 @@ async function initHandlerForAWSHTTPLambda( DEBUG_NODE_ENVS = DEFAULT_DEBUG_NODE_ENVS, DECODERS = DEFAULT_DECODERS, ENCODERS = DEFAULT_ENCODERS, - PARSED_HEADERS = [], log = noop, time = Date.now.bind(Date), ...services @@ -135,7 +132,7 @@ async function initHandlerForAWSHTTPLambda( log, }); - return handleForAWSHTTPLambda.bind( + return handleForAWSHTTPFunction.bind( null, { OPERATION, @@ -143,7 +140,6 @@ async function initHandlerForAWSHTTPLambda( DEBUG_NODE_ENVS, DECODERS, ENCODERS, - PARSED_HEADERS, log, time, ...services, @@ -160,7 +156,7 @@ async function initHandlerForAWSHTTPLambda( ); } -async function handleForAWSHTTPLambda( +async function handleForAWSHTTPFunction( { OPERATION, DEBUG_NODE_ENVS, @@ -170,14 +166,12 @@ async function handleForAWSHTTPLambda( PARSERS = DEFAULT_PARSERS, STRINGIFYERS = DEFAULT_STRINGIFYERS, BUFFER_LIMIT = DEFAULT_BUFFER_LIMIT, - PARSED_HEADERS, QUERY_PARSER, // TODO: Better handling of CORS in errors should // be found CORS, log, time, - apm, obfuscator, }: HTTPWrapperDependencies & { CORS: any }, { @@ -194,6 +188,7 @@ async function handleForAWSHTTPLambda( ) { const debugging = DEBUG_NODE_ENVS.includes(NODE_ENV); const startTime = time(); + const bufferLimit = bytes.parse(BUFFER_LIMIT); log( 'info', @@ -243,7 +238,7 @@ async function handleForAWSHTTPLambda( { DECODERS, PARSERS, - bufferLimit: BUFFER_LIMIT, + bufferLimit, }, operation, request.body, @@ -412,64 +407,6 @@ async function handleForAWSHTTPLambda( ), res, ); - - // log( - // 'debug', - // 'AWS_RESPONSE_EVENT', - // JSON.stringify({ - // ...awsResponse, - // body: obfuscateEventBody(obfuscator, awsResponse.body), - // headers: obfuscator.obfuscateSensibleHeaders(awsResponse.headers), - // }), - // ); - - // apm('CALL', { - // id: event.requestContext.requestId, - // transactionId: - // request.headers['x-transaction-id'] && - // new RegExp(uuidPattern).test(request.headers['x-transaction-id']) - // ? event.headers['x-transaction-id'] - // : event.requestContext.requestId, - // environment: NODE_ENV, - // method: event.requestContext.httpMethod, - // resourcePath: event.requestContext.resourcePath, - // path: event.requestContext.path, - // userAgent: - // event.requestContext.identity && event.requestContext.identity.userAgent, - // triggerTime: event.requestContext.requestTimeEpoch, - // lambdaName: OPERATION.operationId, - // parameters: obfuscator.obfuscateSensibleProps(parameters), - // status: response.status, - // headers: obfuscator.obfuscateSensibleHeaders( - // Object.keys(response.headers).reduce( - // (finalHeaders, headerName) => ({ - // ...finalHeaders, - // ...(PARSED_HEADERS.includes(headerName) - // ? {} - // : { - // [headerName]: response.headers[headerName], - // }), - // }), - // {}, - // ), - // ), - // bodyLength: awsResponse.body ? awsResponse.body.length : 0, - // type: responseLog.type, - // stack: responseLog.stack, - // code: responseLog.code, - // params: responseLog.params, - // startTime, - // endTime: time(), - // ...PARSED_HEADERS.reduce( - // (result, parsedHeader) => ({ - // ...result, - // ...(response.headers[parsedHeader] - // ? JSON.parse(response.headers[parsedHeader]) - // : {}), - // }), - // {}, - // ), - // }); } async function gcpfReqToRequest(req: any): Promise { diff --git a/packages/whook/src/services/API_DEFINITIONS.ts b/packages/whook/src/services/API_DEFINITIONS.ts index cae120ca..ff9f9908 100644 --- a/packages/whook/src/services/API_DEFINITIONS.ts +++ b/packages/whook/src/services/API_DEFINITIONS.ts @@ -64,7 +64,7 @@ export type WhookAPISchemaDefinition = { }; export type WhookAPIParameterDefinition = { name: string; - parameter: OpenAPIV3.ReferenceObject | OpenAPIV3.ParameterObject; + parameter: OpenAPIV3.ParameterObject; }; export type WhookAPIHandlerModule = { [name: string]: