From 57a601c9a105880c68c61a82aae1a054456c2a05 Mon Sep 17 00:00:00 2001 From: Daniel Bartholomae Date: Wed, 12 Aug 2020 16:11:11 +0200 Subject: [PATCH 1/8] chore: fix typo in file name of template --- .../middleware/new/package/examples/helloWorld.int-test.ts.t | 2 +- _templates/middleware/new/package/examples/helloWorld.ts.t | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/_templates/middleware/new/package/examples/helloWorld.int-test.ts.t b/_templates/middleware/new/package/examples/helloWorld.int-test.ts.t index 460fb99..28ae835 100644 --- a/_templates/middleware/new/package/examples/helloWorld.int-test.ts.t +++ b/_templates/middleware/new/package/examples/helloWorld.int-test.ts.t @@ -1,5 +1,5 @@ --- -to: packages/<%= h.inflection.dasherize(name.toLowerCase()) %>/examples/hellowWorld.int-test.ts +to: packages/<%= h.inflection.dasherize(name.toLowerCase()) %>/examples/helloWorld.int-test.ts --- import request from "supertest"; const server = request("http://localhost:3000/dev"); diff --git a/_templates/middleware/new/package/examples/helloWorld.ts.t b/_templates/middleware/new/package/examples/helloWorld.ts.t index 9b15abe..64b80e8 100644 --- a/_templates/middleware/new/package/examples/helloWorld.ts.t +++ b/_templates/middleware/new/package/examples/helloWorld.ts.t @@ -1,5 +1,5 @@ --- -to: packages/<%= h.inflection.dasherize(name.toLowerCase()) %>/examples/hellowWorld.ts +to: packages/<%= h.inflection.dasherize(name.toLowerCase()) %>/examples/helloWorld.ts --- import { <%=h.inflection.camelize(name, true) %> } from "../"; From 53ad43978ff79a56dd71dce12d1cdede93ffe886 Mon Sep 17 00:00:00 2001 From: Daniel Bartholomae Date: Wed, 12 Aug 2020 16:07:23 +0200 Subject: [PATCH 2/8] chore(http-header-normalizer): scaffold new middleware --- packages/http-header-normalizer/.eslintrc.js | 12 +++ packages/http-header-normalizer/.gitignore | 29 +++++++ packages/http-header-normalizer/LICENSE | 21 ++++++ packages/http-header-normalizer/README.md | 33 ++++++++ .../examples/helloWorld.int-test.ts | 8 ++ .../examples/helloWorld.ts | 12 +++ .../http-header-normalizer/jest.config.js | 2 + .../jest.integration.config.js | 2 + packages/http-header-normalizer/package.json | 75 +++++++++++++++++++ .../src/http-header-normalizer.test.ts | 14 ++++ .../src/http-header-normalizer.ts | 11 +++ packages/http-header-normalizer/src/index.ts | 2 + packages/http-header-normalizer/src/logger.ts | 3 + .../http-header-normalizer/test/.gitignore | 2 + .../http-header-normalizer/test/handler.ts | 8 ++ .../test/serverless.yml | 25 +++++++ .../test/source-map-install.js | 1 + .../http-header-normalizer/test/tsconfig.json | 23 ++++++ .../test/webpack.config.js | 29 +++++++ .../tsconfig.build.json | 9 +++ packages/http-header-normalizer/tsconfig.json | 7 ++ 21 files changed, 328 insertions(+) create mode 100644 packages/http-header-normalizer/.eslintrc.js create mode 100644 packages/http-header-normalizer/.gitignore create mode 100644 packages/http-header-normalizer/LICENSE create mode 100644 packages/http-header-normalizer/README.md create mode 100644 packages/http-header-normalizer/examples/helloWorld.int-test.ts create mode 100644 packages/http-header-normalizer/examples/helloWorld.ts create mode 100644 packages/http-header-normalizer/jest.config.js create mode 100644 packages/http-header-normalizer/jest.integration.config.js create mode 100644 packages/http-header-normalizer/package.json create mode 100644 packages/http-header-normalizer/src/http-header-normalizer.test.ts create mode 100644 packages/http-header-normalizer/src/http-header-normalizer.ts create mode 100644 packages/http-header-normalizer/src/index.ts create mode 100644 packages/http-header-normalizer/src/logger.ts create mode 100644 packages/http-header-normalizer/test/.gitignore create mode 100644 packages/http-header-normalizer/test/handler.ts create mode 100644 packages/http-header-normalizer/test/serverless.yml create mode 100644 packages/http-header-normalizer/test/source-map-install.js create mode 100644 packages/http-header-normalizer/test/tsconfig.json create mode 100644 packages/http-header-normalizer/test/webpack.config.js create mode 100644 packages/http-header-normalizer/tsconfig.build.json create mode 100644 packages/http-header-normalizer/tsconfig.json diff --git a/packages/http-header-normalizer/.eslintrc.js b/packages/http-header-normalizer/.eslintrc.js new file mode 100644 index 0000000..d739eab --- /dev/null +++ b/packages/http-header-normalizer/.eslintrc.js @@ -0,0 +1,12 @@ +module.exports = { + extends: [ + "plugin:@typescript-eslint/recommended", + "prettier/@typescript-eslint", + "plugin:prettier/recommended", + ], + parser: "@typescript-eslint/parser", + parserOptions: { + project: "tsconfig.json", + sourceType: "module", + }, +}; diff --git a/packages/http-header-normalizer/.gitignore b/packages/http-header-normalizer/.gitignore new file mode 100644 index 0000000..9c2857c --- /dev/null +++ b/packages/http-header-normalizer/.gitignore @@ -0,0 +1,29 @@ +# See https://help.github.com/ignore-files/ for more about ignoring files. + +# IDEs +.idea + +# dependencies +/node_modules + +# testing +/coverage + +# production +/build + +# misc +.DS_Store +.env.local +.env.development.local +.env.test.local +.env.production.local + +npm-debug.log* +package-lock.json +yarn-debug.log* +yarn-error.log* +yarn.lock + +# Built library +lib diff --git a/packages/http-header-normalizer/LICENSE b/packages/http-header-normalizer/LICENSE new file mode 100644 index 0000000..23bf97f --- /dev/null +++ b/packages/http-header-normalizer/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020 Daniel Bartholomae + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/packages/http-header-normalizer/README.md b/packages/http-header-normalizer/README.md new file mode 100644 index 0000000..702b3cb --- /dev/null +++ b/packages/http-header-normalizer/README.md @@ -0,0 +1,33 @@ +# @lambda-middleware/http-header-normalizer + +[![npm version](https://badge.fury.io/js/%40lambda-middleware%2Fhttp-header-normalizer.svg)](https://npmjs.org/package/@lambda-middleware/http-header-normalizer) +[![downloads](https://img.shields.io/npm/dw/%40lambda-middleware%2Fhttp-header-normalizer.svg)](https://npmjs.org/package/@lambda-middleware/http-header-normalizer) +[![open issues](https://img.shields.io/github/issues-raw/dbartholomae/lambda-middleware.svg)](https://github.com/dbartholomae/lambda-middleware/issues) +[![debug](https://img.shields.io/badge/debug-blue.svg)](https://github.com/visionmedia/debug#readme) +[![build status](https://github.com/dbartholomae/lambda-middleware/workflows/.github/workflows/build.yml/badge.svg?branch=master)](https://github.com/dbartholomae/lambda-middleware/actions?query=workflow%3A.github%2Fworkflows%2Fbuild.yml) +[![codecov](https://codecov.io/gh/dbartholomae/lambda-middleware/branch/master/graph/badge.svg)](https://codecov.io/gh/dbartholomae/lambda-middleware) +[![dependency status](https://david-dm.org/dbartholomae/lambda-middleware.svg?theme=shields.io)](https://david-dm.org/dbartholomae/lambda-middleware) +[![devDependency status](https://david-dm.org/dbartholomae/lambda-middleware/dev-status.svg)](https://david-dm.org/dbartholomae/lambda-middleware?type=dev) + +Middleware for AWS lambdas that normalizes headers to lower-case + +## Lambda middleware + +This middleware is part of the [lambda middleware series](https://dbartholomae.github.io/lambda-middleware/). It can be used independently. + +## Usage + +```typescript +import { http-header-normalizer } from "@lambda-middleware/http-header-normalizer"; + +// This is your AWS handler +async function helloWorld() { + return { + statusCode: 200, + body: "", + }; +} + +// Wrap the handler with the middleware +export const handler = http-header-normalizer()(helloWorld); +``` diff --git a/packages/http-header-normalizer/examples/helloWorld.int-test.ts b/packages/http-header-normalizer/examples/helloWorld.int-test.ts new file mode 100644 index 0000000..96b01a8 --- /dev/null +++ b/packages/http-header-normalizer/examples/helloWorld.int-test.ts @@ -0,0 +1,8 @@ +import request from "supertest"; +const server = request("http://localhost:3000/dev"); + +describe("Handler with no sniff middleware", () => { + it("returns 200", async () => { + await server.get("/hello").expect(200); + }); +}); diff --git a/packages/http-header-normalizer/examples/helloWorld.ts b/packages/http-header-normalizer/examples/helloWorld.ts new file mode 100644 index 0000000..aef7a1a --- /dev/null +++ b/packages/http-header-normalizer/examples/helloWorld.ts @@ -0,0 +1,12 @@ +import { http-header-normalizer } from "../"; + +// This is your AWS handler +async function helloWorld() { + return { + statusCode: 200, + body: "", + }; +} + +// Wrap the handler with the middleware +export const handler = http-header-normalizer()(helloWorld); diff --git a/packages/http-header-normalizer/jest.config.js b/packages/http-header-normalizer/jest.config.js new file mode 100644 index 0000000..b5929e6 --- /dev/null +++ b/packages/http-header-normalizer/jest.config.js @@ -0,0 +1,2 @@ +const baseConfig = require("../../jest.unit.config"); +module.exports = baseConfig; diff --git a/packages/http-header-normalizer/jest.integration.config.js b/packages/http-header-normalizer/jest.integration.config.js new file mode 100644 index 0000000..6f62d6b --- /dev/null +++ b/packages/http-header-normalizer/jest.integration.config.js @@ -0,0 +1,2 @@ +const baseConfig = require("../../jest.integration.config"); +module.exports = baseConfig; diff --git a/packages/http-header-normalizer/package.json b/packages/http-header-normalizer/package.json new file mode 100644 index 0000000..fb876de --- /dev/null +++ b/packages/http-header-normalizer/package.json @@ -0,0 +1,75 @@ +{ + "name": "@lambda-middleware/http-header-normalizer", + "version": "0.0.0", + "description": "Middleware for AWS lambdas that normalizes headers to lower-case", + "homepage": "https://dbartholomae.github.io/lambda-middleware/", + "license": "MIT", + "author": { + "name": "Daniel Bartholomae", + "email": "daniel@bartholomae.name", + "url": "" + }, + "files": [ + "lib" + ], + "main": "lib/index.js", + "keywords": [ + "aws", + "lambda", + "middleware", + "http", + "headers", + "normalizer" + ], + "types": "lib/index.d.ts", + "engines": { + "npm": ">= 4.0.0" + }, + "private": false, + "dependencies": { + "@lambda-middleware/utils": "*", + "debug": ">=4.1.0" + }, + "directories": { + "example": "examples" + }, + "scripts": { + "build": "rimraf ./lib && tsc --project tsconfig.build.json", + "lint": "eslint src/**/*.ts examples/**/*.ts", + "pretest": "npm run build", + "start": "cd test && serverless offline", + "test": "npm run lint && npm run test:unit && npm run test:integration && pkg-ok", + "test:integration": "concurrently --timeout 600000 --kill-others --success first \"cd test && serverless offline\" \"wait-on http://localhost:3000/dev/status && jest -c jest.integration.config.js\"", + "test:unit": "jest" + }, + "devDependencies": { + "@types/debug": "^4.1.5", + "@types/jest": "^25.2.1", + "@types/supertest": "^2.0.8", + "@types/aws-lambda": "^8.10.47", + "@typescript-eslint/parser": "^2.26.0", + "@typescript-eslint/eslint-plugin": "^2.26.0", + "aws-lambda": "^1.0.5", + "concurrently": "^5.1.0", + "eslint": "^6.8.0", + "eslint-config-prettier": "^6.10.1", + "eslint-plugin-prettier": "^3.1.2", + "jest": "^25.2.7", + "jest-junit": "^10.0.0", + "pkg-ok": "^2.3.1", + "prettier": "^2.0.2", + "prettier-config-standard": "^1.0.1", + "rimraf": "^3.0.2", + "serverless": "^1.67.0", + "serverless-offline": "^6.1.4", + "serverless-webpack": "^5.3.1", + "source-map-support": "^0.5.16", + "supertest": "^4.0.2", + "ts-jest": "^25.3.1", + "ts-loader": "^6.2.2", + "typescript": "^3.7.5", + "wait-on": "^5.2.0", + "webpack": "^4.41.5" + }, + "repository": "git@github.com:dbartholomae/lambda-middleware.git" +} diff --git a/packages/http-header-normalizer/src/http-header-normalizer.test.ts b/packages/http-header-normalizer/src/http-header-normalizer.test.ts new file mode 100644 index 0000000..7f1213d --- /dev/null +++ b/packages/http-header-normalizer/src/http-header-normalizer.test.ts @@ -0,0 +1,14 @@ +import { http-header-normalizer } from "./http-header-normalizer"; + +describe("http-header-normalizer", () => { + it("returns the handler's response", async () => { + const response = { + statusCode: 200, + body: "", + }; + const handler = jest.fn().mockResolvedValue(response); + expect(await noSniff()(handler)({} as any, {} as any)).toMatchObject( + response + ); + }); +}); diff --git a/packages/http-header-normalizer/src/http-header-normalizer.ts b/packages/http-header-normalizer/src/http-header-normalizer.ts new file mode 100644 index 0000000..1cac161 --- /dev/null +++ b/packages/http-header-normalizer/src/http-header-normalizer.ts @@ -0,0 +1,11 @@ +import { PromiseHandler } from "@lambda-middleware/utils"; +import { APIGatewayProxyResult, Context } from "aws-lambda"; +import { logger } from "./logger"; + +export const http-header-normalizer = () => ( + handler: PromiseHandler +) => async (event: E, context: Context): Promise => { + logger("Running handler"); + const response = await handler(event, context); + return response; +}; diff --git a/packages/http-header-normalizer/src/index.ts b/packages/http-header-normalizer/src/index.ts new file mode 100644 index 0000000..0faab71 --- /dev/null +++ b/packages/http-header-normalizer/src/index.ts @@ -0,0 +1,2 @@ +/* istanbul ignore next */ +export * from "./http-header-normalizer"; diff --git a/packages/http-header-normalizer/src/logger.ts b/packages/http-header-normalizer/src/logger.ts new file mode 100644 index 0000000..9c37005 --- /dev/null +++ b/packages/http-header-normalizer/src/logger.ts @@ -0,0 +1,3 @@ +import debugFactory, { IDebugger } from "debug"; + +export const logger: IDebugger = debugFactory("@lambda-middleware/http-header-normalizer"); diff --git a/packages/http-header-normalizer/test/.gitignore b/packages/http-header-normalizer/test/.gitignore new file mode 100644 index 0000000..9707102 --- /dev/null +++ b/packages/http-header-normalizer/test/.gitignore @@ -0,0 +1,2 @@ +# Files generated temporarily when running the middleware in a lambda for integration testing +.webpack \ No newline at end of file diff --git a/packages/http-header-normalizer/test/handler.ts b/packages/http-header-normalizer/test/handler.ts new file mode 100644 index 0000000..78ec7b7 --- /dev/null +++ b/packages/http-header-normalizer/test/handler.ts @@ -0,0 +1,8 @@ +export { handler as fullExample } from "../examples/helloWorld"; + +export async function status() { + return { + body: "", + statusCode: 200, + }; +} diff --git a/packages/http-header-normalizer/test/serverless.yml b/packages/http-header-normalizer/test/serverless.yml new file mode 100644 index 0000000..82a409d --- /dev/null +++ b/packages/http-header-normalizer/test/serverless.yml @@ -0,0 +1,25 @@ +service: + name: test-microservice + +plugins: + - serverless-webpack + - serverless-offline + +provider: + name: aws + runtime: nodejs8.10 + +functions: + hello: + handler: handler.fullExample + events: + - http: + method: get + path: hello + + status: + handler: handler.status + events: + - http: + method: get + path: status diff --git a/packages/http-header-normalizer/test/source-map-install.js b/packages/http-header-normalizer/test/source-map-install.js new file mode 100644 index 0000000..88f7432 --- /dev/null +++ b/packages/http-header-normalizer/test/source-map-install.js @@ -0,0 +1 @@ +require("source-map-support").install(); diff --git a/packages/http-header-normalizer/test/tsconfig.json b/packages/http-header-normalizer/test/tsconfig.json new file mode 100644 index 0000000..69943b2 --- /dev/null +++ b/packages/http-header-normalizer/test/tsconfig.json @@ -0,0 +1,23 @@ +{ + "compilerOptions": { + "baseUrl": ".", + "module": "esnext", + "esModuleInterop": true, + "target": "es5", + "lib": ["es6", "dom"], + "sourceMap": false, + "jsx": "react", + "moduleResolution": "node", + "rootDir": "../", + "forceConsistentCasingInFileNames": true, + "experimentalDecorators": true, + "emitDecoratorMetadata": true, + "noImplicitReturns": true, + "noImplicitThis": true, + "noImplicitAny": true, + "importHelpers": true, + "strictNullChecks": true, + "suppressImplicitAnyIndexErrors": true, + "noUnusedLocals": true + } +} diff --git a/packages/http-header-normalizer/test/webpack.config.js b/packages/http-header-normalizer/test/webpack.config.js new file mode 100644 index 0000000..5f51002 --- /dev/null +++ b/packages/http-header-normalizer/test/webpack.config.js @@ -0,0 +1,29 @@ +const path = require("path"); +const slsw = require("serverless-webpack"); + +const entries = {}; + +Object.keys(slsw.lib.entries).forEach( + (key) => (entries[key] = ["./source-map-install.js", slsw.lib.entries[key]]) +); + +module.exports = { + mode: slsw.lib.webpack.isLocal ? "development" : "production", + entry: entries, + devtool: "source-map", + resolve: { + extensions: [".js", ".jsx", ".json", ".ts", ".tsx"], + }, + output: { + libraryTarget: "commonjs", + path: path.join(__dirname, ".webpack"), + filename: "[name].js", + }, + target: "node", + module: { + rules: [ + // all files with a `.ts` or `.tsx` extension will be handled by `ts-loader` + { test: /\.tsx?$/, loader: "ts-loader" }, + ], + }, +}; diff --git a/packages/http-header-normalizer/tsconfig.build.json b/packages/http-header-normalizer/tsconfig.build.json new file mode 100644 index 0000000..9b876c7 --- /dev/null +++ b/packages/http-header-normalizer/tsconfig.build.json @@ -0,0 +1,9 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "lib", + "rootDir": "src" + }, + "include": ["src/**/*"], + "exclude": ["src/**/*.test.ts"] +} diff --git a/packages/http-header-normalizer/tsconfig.json b/packages/http-header-normalizer/tsconfig.json new file mode 100644 index 0000000..059316f --- /dev/null +++ b/packages/http-header-normalizer/tsconfig.json @@ -0,0 +1,7 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "baseUrl": "." + }, + "include": ["**/*"] +} From 149d3453083297d672d79f9dcb49f43e2f1c3058 Mon Sep 17 00:00:00 2001 From: Daniel Bartholomae Date: Wed, 12 Aug 2020 16:09:30 +0200 Subject: [PATCH 3/8] docs(http-header-normalizer): add to middleware list --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index e5354fc..f96245a 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,8 @@ This monorepo is a collection of middleware for AWS lambda functions. middleware. * [@lambda-middleware/no-sniff](/packages/no-sniff): A middleware for adding the content type options no-sniff header to AWS lambdas. +* [@lambda-middleware/http-header-normalizer](/packages/http-header-normalizer): Middleware for AWS lambdas that + normalizes headers to lower-case. ## Other packages From 83d1eeb7378eedba7b5bac775c03425e864e4fdb Mon Sep 17 00:00:00 2001 From: Daniel Bartholomae Date: Wed, 12 Aug 2020 16:33:30 +0200 Subject: [PATCH 4/8] chore: replace hardcoded name with var in template --- .../middleware/new/package/examples/helloWorld.int-test.ts.t | 2 +- _templates/middleware/new/package/src/middleware.test.ts.t | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/_templates/middleware/new/package/examples/helloWorld.int-test.ts.t b/_templates/middleware/new/package/examples/helloWorld.int-test.ts.t index 28ae835..447c8c0 100644 --- a/_templates/middleware/new/package/examples/helloWorld.int-test.ts.t +++ b/_templates/middleware/new/package/examples/helloWorld.int-test.ts.t @@ -4,7 +4,7 @@ to: packages/<%= h.inflection.dasherize(name.toLowerCase()) %>/examples/helloWor import request from "supertest"; const server = request("http://localhost:3000/dev"); -describe("Handler with no sniff middleware", () => { +describe("Handler with <%= h.inflection.dasherize(name) %> middleware", () => { it("returns 200", async () => { await server.get("/hello").expect(200); }); diff --git a/_templates/middleware/new/package/src/middleware.test.ts.t b/_templates/middleware/new/package/src/middleware.test.ts.t index e632398..3a5010a 100644 --- a/_templates/middleware/new/package/src/middleware.test.ts.t +++ b/_templates/middleware/new/package/src/middleware.test.ts.t @@ -10,7 +10,7 @@ describe("<%=h.inflection.camelize(name, true) %>", () => { body: "", }; const handler = jest.fn().mockResolvedValue(response); - expect(await noSniff()(handler)({} as any, {} as any)).toMatchObject( + expect(await <%=h.inflection.camelize(name, true) %>()(handler)({} as any, {} as any)).toMatchObject( response ); }); From bc0f8b8d9a3123af6b7a7ad2515462a270a17d94 Mon Sep 17 00:00:00 2001 From: Daniel Bartholomae Date: Wed, 12 Aug 2020 16:33:56 +0200 Subject: [PATCH 5/8] chore(http-header-normalizer): add middleware to rush config --- rush.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/rush.json b/rush.json index 69f42cb..1a4b334 100644 --- a/rush.json +++ b/rush.json @@ -47,5 +47,9 @@ "packageName": "@lambda-middleware/utils", "projectFolder": "packages/utils", "shouldPublish": true + }, { + "packageName": "@lambda-middleware/http-header-normalizer", + "projectFolder": "packages/http-header-normalizer", + "shouldPublish": true }] } From 9dacbd8d321afb020b64f54204522bf5fa331507 Mon Sep 17 00:00:00 2001 From: Daniel Bartholomae Date: Thu, 13 Aug 2020 10:47:00 +0200 Subject: [PATCH 6/8] chore: do not run ts-jest for js files --- jest.config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jest.config.js b/jest.config.js index 42fa3b3..3a5cc35 100644 --- a/jest.config.js +++ b/jest.config.js @@ -1,7 +1,7 @@ module.exports = { roots: ["/src"], transform: { - "^.+\\.(t|j)sx?$": "ts-jest", + "^.+\\.tsx?$": "ts-jest", }, testRegex: ".*(int-)?test\\.(t|j)sx?$", moduleFileExtensions: ["ts", "tsx", "js", "jsx", "json", "node"], From 666d56abf077bb37c8541d87a6e752ce3a21a035 Mon Sep 17 00:00:00 2001 From: Daniel Bartholomae Date: Thu, 13 Aug 2020 12:08:28 +0200 Subject: [PATCH 7/8] feat(http-header-normalizer): add middleware --- common/config/rush/yarn.lock | 121 +++++++++++------- packages/http-header-normalizer/README.md | 16 ++- .../examples/helloWorld.int-test.ts | 14 +- .../examples/helloWorld.ts | 13 +- packages/http-header-normalizer/package.json | 1 + .../src/http-header-normalizer.test.ts | 101 ++++++++++++++- .../src/http-header-normalizer.ts | 39 +++++- packages/http-header-normalizer/src/logger.ts | 4 +- 8 files changed, 240 insertions(+), 69 deletions(-) diff --git a/common/config/rush/yarn.lock b/common/config/rush/yarn.lock index 8d56eeb..e3c0d38 100644 --- a/common/config/rush/yarn.lock +++ b/common/config/rush/yarn.lock @@ -1000,6 +1000,39 @@ wait-on "^5.2.0" webpack "^4.41.5" +"@rush-temp/http-header-normalizer@file:./projects/http-header-normalizer.tgz": + version "0.0.0" + resolved "file:./projects/http-header-normalizer.tgz#a22144ea0a51e6f48bd299b046b9d7a37bc8e465" + dependencies: + "@types/aws-lambda" "^8.10.47" + "@types/debug" "^4.1.5" + "@types/jest" "^25.2.1" + "@types/supertest" "^2.0.8" + "@typescript-eslint/eslint-plugin" "^2.26.0" + "@typescript-eslint/parser" "^2.26.0" + aws-lambda "^1.0.5" + concurrently "^5.1.0" + debug ">=4.1.0" + eslint "^6.8.0" + eslint-config-prettier "^6.10.1" + eslint-plugin-prettier "^3.1.2" + jest "^25.2.7" + jest-junit "^10.0.0" + pkg-ok "^2.3.1" + prettier "^2.0.2" + prettier-config-standard "^1.0.1" + rimraf "^3.0.2" + serverless "^1.67.0" + serverless-offline "^6.1.4" + serverless-webpack "^5.3.1" + source-map-support "^0.5.16" + supertest "^4.0.2" + ts-jest "^25.3.1" + ts-loader "^6.2.2" + typescript "^3.7.5" + wait-on "^5.2.0" + webpack "^4.41.5" + "@rush-temp/ie-no-open@file:./projects/ie-no-open.tgz": version "0.0.0" resolved "file:./projects/ie-no-open.tgz#4bf132dac67ae18dff973d89ae4137cb1b91bdeb" @@ -1309,8 +1342,8 @@ shortid "^2.2.14" "@serverless/components@^2.33.4": - version "2.34.1" - resolved "https://registry.yarnpkg.com/@serverless/components/-/components-2.34.1.tgz#a33c02c8607aa935ee03b1ef8a7a8cdfb9477fac" + version "2.34.3" + resolved "https://registry.yarnpkg.com/@serverless/components/-/components-2.34.3.tgz#5764e225c5306cac7dc2b6496a8a3e16703c1a07" dependencies: "@serverless/inquirer" "^1.1.2" "@serverless/platform-client" "^1.1.1" @@ -1527,8 +1560,8 @@ resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82" "@types/aws-lambda@^8.10.47": - version "8.10.59" - resolved "https://registry.yarnpkg.com/@types/aws-lambda/-/aws-lambda-8.10.59.tgz#64f602aef1cac9b21a74aad6705bf350c4a5173a" + version "8.10.61" + resolved "https://registry.yarnpkg.com/@types/aws-lambda/-/aws-lambda-8.10.61.tgz#7471e08843dbdcf09b2494ac5b34c4d1a391e6d0" "@types/babel__core@^7.1.7": version "7.1.9" @@ -2213,21 +2246,18 @@ arrify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" -arrify@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/arrify/-/arrify-2.0.1.tgz#c9655e9331e0abcd588d2a7cad7e9956f66701fa" - asap@^2.0.0: version "2.0.6" resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" -asn1.js@^4.0.0: - version "4.10.1" - resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-4.10.1.tgz#b9c2bf5805f1e64aadeed6df3a2bfafb5a73f5a0" +asn1.js@^5.2.0: + version "5.4.1" + resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-5.4.1.tgz#11a980b84ebb91781ce35b0fdc2ee294e3783f07" dependencies: bn.js "^4.0.0" inherits "^2.0.1" minimalistic-assert "^1.0.0" + safer-buffer "^2.1.0" asn1@~0.2.3: version "0.2.4" @@ -2298,8 +2328,8 @@ aws-lambda@^1.0.5: watchpack "^2.0.0-beta.10" aws-sdk@*, aws-sdk@^2.726.0: - version "2.729.0" - resolved "https://registry.yarnpkg.com/aws-sdk/-/aws-sdk-2.729.0.tgz#3d850f7825b94b5d8b2aca58ec096973bc4c7e34" + version "2.732.0" + resolved "https://registry.yarnpkg.com/aws-sdk/-/aws-sdk-2.732.0.tgz#03305b69c0d7ea18767aa0d99a9458e1bed48d65" dependencies: buffer "4.9.2" events "1.1.1" @@ -2316,8 +2346,8 @@ aws-sign2@~0.7.0: resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" aws4@^1.8.0: - version "1.10.0" - resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.10.0.tgz#a17b3a8ea811060e74d47d306122400ad4497ae2" + version "1.10.1" + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.10.1.tgz#e1e82e4f3e999e2cfd61b161280d16a111f86428" axios@^0.19.2: version "0.19.2" @@ -2810,10 +2840,6 @@ camelcase@^5.0.0, camelcase@^5.3.1: version "5.3.1" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" -camelcase@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.0.0.tgz#5259f7c30e35e278f1bdc2a4d91230b37cad981e" - capture-exit@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/capture-exit/-/capture-exit-2.0.0.tgz#fb953bfaebeb781f62898239dabb426d08a509a4" @@ -2944,8 +2970,8 @@ cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: safe-buffer "^5.0.1" class-transformer-validator@>=0.8.0: - version "0.9.0" - resolved "https://registry.yarnpkg.com/class-transformer-validator/-/class-transformer-validator-0.9.0.tgz#966c419e5243f146f8c32e5b6c3dc90d6ef264f8" + version "0.9.1" + resolved "https://registry.yarnpkg.com/class-transformer-validator/-/class-transformer-validator-0.9.1.tgz#81af4bab5e13ce619a25a74cc70f723a8c4e2779" class-transformer@>=0.2.3: version "0.3.1" @@ -3557,8 +3583,8 @@ dateformat@^3.0.0: resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-3.0.3.tgz#a6e37499a4d9a9cf85ef5872044d62901c9889ae" dayjs@^1.8.32: - version "1.8.32" - resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.8.32.tgz#66c48b95c397d9f7907e89bd29f78b3d19d40294" + version "1.8.33" + resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.8.33.tgz#18bc4a2b6c1c6f4d67b4c4f2536c0b97e5b766f7" debug@3.1.0, debug@=3.1.0, debug@~3.1.0: version "3.1.0" @@ -4956,8 +4982,8 @@ globby@^9.2.0: slash "^2.0.0" google-libphonenumber@^3.2.8: - version "3.2.10" - resolved "https://registry.yarnpkg.com/google-libphonenumber/-/google-libphonenumber-3.2.10.tgz#021a314652747d736a39e2e60dc670f0431425ad" + version "3.2.11" + resolved "https://registry.yarnpkg.com/google-libphonenumber/-/google-libphonenumber-3.2.11.tgz#c5704513366b18f468a9505ea13e53f6fbcc9eec" got@^6.7.1: version "6.7.1" @@ -7070,16 +7096,14 @@ meow@^5.0.0: yargs-parser "^10.0.0" meow@^7.0.0: - version "7.0.1" - resolved "https://registry.yarnpkg.com/meow/-/meow-7.0.1.tgz#1ed4a0a50b3844b451369c48362eb0515f04c1dc" + version "7.1.0" + resolved "https://registry.yarnpkg.com/meow/-/meow-7.1.0.tgz#50ecbcdafa16f8b58fb7eb9675b933f6473b3a59" dependencies: "@types/minimist" "^1.2.0" - arrify "^2.0.1" - camelcase "^6.0.0" camelcase-keys "^6.2.2" decamelize-keys "^1.1.0" hard-rejection "^2.1.0" - minimist-options "^4.0.2" + minimist-options "4.1.0" normalize-package-data "^2.5.0" read-pkg-up "^7.0.1" redent "^3.0.0" @@ -7183,20 +7207,20 @@ minimatch@^3.0.2, minimatch@^3.0.4: dependencies: brace-expansion "^1.1.7" -minimist-options@^3.0.1: - version "3.0.2" - resolved "https://registry.yarnpkg.com/minimist-options/-/minimist-options-3.0.2.tgz#fba4c8191339e13ecf4d61beb03f070103f3d954" +minimist-options@4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/minimist-options/-/minimist-options-4.1.0.tgz#c0655713c53a8a2ebd77ffa247d342c40f010619" dependencies: arrify "^1.0.1" is-plain-obj "^1.1.0" + kind-of "^6.0.3" -minimist-options@^4.0.2: - version "4.1.0" - resolved "https://registry.yarnpkg.com/minimist-options/-/minimist-options-4.1.0.tgz#c0655713c53a8a2ebd77ffa247d342c40f010619" +minimist-options@^3.0.1: + version "3.0.2" + resolved "https://registry.yarnpkg.com/minimist-options/-/minimist-options-3.0.2.tgz#fba4c8191339e13ecf4d61beb03f070103f3d954" dependencies: arrify "^1.0.1" is-plain-obj "^1.1.0" - kind-of "^6.0.3" minimist@^1.1.1, minimist@^1.2.0, minimist@^1.2.5: version "1.2.5" @@ -8092,12 +8116,11 @@ parent-module@^1.0.0: callsites "^3.0.0" parse-asn1@^5.0.0, parse-asn1@^5.1.5: - version "5.1.5" - resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.5.tgz#003271343da58dc94cace494faef3d2147ecea0e" + version "5.1.6" + resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.6.tgz#385080a3ec13cb62a62d39409cb3e88844cdaed4" dependencies: - asn1.js "^4.0.0" + asn1.js "^5.2.0" browserify-aes "^1.0.0" - create-hash "^1.1.0" evp_bytestokey "^1.0.0" pbkdf2 "^3.0.3" safe-buffer "^5.1.1" @@ -9107,9 +9130,9 @@ serialize-error@>=5.0.0: dependencies: type-fest "^0.13.1" -serialize-javascript@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-3.1.0.tgz#8bf3a9170712664ef2561b44b691eafe399214ea" +serialize-javascript@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-4.0.0.tgz#b525e1238489a5ecfc42afacc3fe99e666f4b1aa" dependencies: randombytes "^2.1.0" @@ -9974,14 +9997,14 @@ terminal-link@^2.0.0: supports-hyperlinks "^2.0.0" terser-webpack-plugin@^1.4.3: - version "1.4.4" - resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-1.4.4.tgz#2c63544347324baafa9a56baaddf1634c8abfc2f" + version "1.4.5" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-1.4.5.tgz#a217aefaea330e734ffacb6120ec1fa312d6040b" dependencies: cacache "^12.0.2" find-cache-dir "^2.1.0" is-wsl "^1.1.0" schema-utils "^1.0.0" - serialize-javascript "^3.1.0" + serialize-javascript "^4.0.0" source-map "^0.6.1" terser "^4.1.2" webpack-sources "^1.4.0" @@ -10736,8 +10759,8 @@ widest-line@^3.1.0: string-width "^4.0.0" windows-release@^3.1.0: - version "3.3.1" - resolved "https://registry.yarnpkg.com/windows-release/-/windows-release-3.3.1.tgz#cb4e80385f8550f709727287bf71035e209c4ace" + version "3.3.3" + resolved "https://registry.yarnpkg.com/windows-release/-/windows-release-3.3.3.tgz#1c10027c7225743eec6b89df160d64c2e0293999" dependencies: execa "^1.0.0" diff --git a/packages/http-header-normalizer/README.md b/packages/http-header-normalizer/README.md index 702b3cb..4b2423e 100644 --- a/packages/http-header-normalizer/README.md +++ b/packages/http-header-normalizer/README.md @@ -9,7 +9,8 @@ [![dependency status](https://david-dm.org/dbartholomae/lambda-middleware.svg?theme=shields.io)](https://david-dm.org/dbartholomae/lambda-middleware) [![devDependency status](https://david-dm.org/dbartholomae/lambda-middleware/dev-status.svg)](https://david-dm.org/dbartholomae/lambda-middleware?type=dev) -Middleware for AWS lambdas that normalizes headers to lower-case +Middleware for AWS lambdas that normalizes headers to lower-case and referer to referrer and vice-versa. +If you are used to [the corresponding middy middleware](https://www.npmjs.com/package/@middy/http-header-normalizer), please note that this middleware acts differently as it does not hold an exception list and converts everything to lower-case. ## Lambda middleware @@ -18,16 +19,21 @@ This middleware is part of the [lambda middleware series](https://dbartholomae.g ## Usage ```typescript -import { http-header-normalizer } from "@lambda-middleware/http-header-normalizer"; +import { httpHeaderNormalizer } from "@lambda-middleware/http-header-normalizer"; +import { APIGatewayProxyEvent, APIGatewayProxyResult } from "aws-lambda"; // This is your AWS handler -async function helloWorld() { +async function helloWorld({ + headers, +}: APIGatewayProxyEvent): APIGatewayProxyResult { return { + body: JSON.stringify({ + msg: headers["custom-header"], + }), statusCode: 200, - body: "", }; } // Wrap the handler with the middleware -export const handler = http-header-normalizer()(helloWorld); +export const handler = httpHeaderNormalizer()(helloWorld); ``` diff --git a/packages/http-header-normalizer/examples/helloWorld.int-test.ts b/packages/http-header-normalizer/examples/helloWorld.int-test.ts index 96b01a8..89aad8c 100644 --- a/packages/http-header-normalizer/examples/helloWorld.int-test.ts +++ b/packages/http-header-normalizer/examples/helloWorld.int-test.ts @@ -1,8 +1,20 @@ import request from "supertest"; const server = request("http://localhost:3000/dev"); -describe("Handler with no sniff middleware", () => { +describe("Handler with httpHeaderNormalizer middleware", () => { it("returns 200", async () => { await server.get("/hello").expect(200); }); + + it("returns the header value for a lower-case custom-header", async () => { + const value = "value"; + const response = await server.get("/hello").set("custom-header", value); + expect(response.body.msg).toEqual(value); + }); + + it("returns the header value for an upper-case custom-header", async () => { + const value = "value"; + const response = await server.get("/hello").set("Custom-Header", value); + expect(response.body.msg).toEqual(value); + }); }); diff --git a/packages/http-header-normalizer/examples/helloWorld.ts b/packages/http-header-normalizer/examples/helloWorld.ts index aef7a1a..8d46816 100644 --- a/packages/http-header-normalizer/examples/helloWorld.ts +++ b/packages/http-header-normalizer/examples/helloWorld.ts @@ -1,12 +1,17 @@ -import { http-header-normalizer } from "../"; +import { httpHeaderNormalizer } from "../"; +import { APIGatewayProxyEvent, APIGatewayProxyResult } from "aws-lambda"; // This is your AWS handler -async function helloWorld() { +async function helloWorld({ + headers, +}: APIGatewayProxyEvent): APIGatewayProxyResult { return { + body: JSON.stringify({ + msg: headers["custom-header"], + }), statusCode: 200, - body: "", }; } // Wrap the handler with the middleware -export const handler = http-header-normalizer()(helloWorld); +export const handler = httpHeaderNormalizer()(helloWorld); diff --git a/packages/http-header-normalizer/package.json b/packages/http-header-normalizer/package.json index fb876de..e574cb8 100644 --- a/packages/http-header-normalizer/package.json +++ b/packages/http-header-normalizer/package.json @@ -27,6 +27,7 @@ }, "private": false, "dependencies": { + "@lambda-middleware/compose": "*", "@lambda-middleware/utils": "*", "debug": ">=4.1.0" }, diff --git a/packages/http-header-normalizer/src/http-header-normalizer.test.ts b/packages/http-header-normalizer/src/http-header-normalizer.test.ts index 7f1213d..daced68 100644 --- a/packages/http-header-normalizer/src/http-header-normalizer.test.ts +++ b/packages/http-header-normalizer/src/http-header-normalizer.test.ts @@ -1,4 +1,5 @@ -import { http-header-normalizer } from "./http-header-normalizer"; +import { httpHeaderNormalizer } from "./http-header-normalizer"; +import { createContext, createEvent } from "@lambda-middleware/utils"; describe("http-header-normalizer", () => { it("returns the handler's response", async () => { @@ -7,8 +8,102 @@ describe("http-header-normalizer", () => { body: "", }; const handler = jest.fn().mockResolvedValue(response); - expect(await noSniff()(handler)({} as any, {} as any)).toMatchObject( - response + expect( + await httpHeaderNormalizer()(handler)(createEvent({}), createContext()) + ).toMatchObject(response); + }); + + it("calls the handler with added lower-cased headers", async () => { + const handler = jest.fn().mockResolvedValue(undefined); + const event = createEvent({ + headers: { + "Custom-Header": "Custom value", + }, + }); + await httpHeaderNormalizer()(handler)(event, createContext()); + expect(handler).toHaveBeenCalledWith( + expect.objectContaining({ + headers: expect.objectContaining({ + "custom-header": "Custom value", + }), + }), + expect.anything() + ); + }); + + it("calls the handler with the original headers in rawHeaders", async () => { + const handler = jest.fn().mockResolvedValue(undefined); + const event = createEvent({ + headers: { + "Custom-Header": "Custom value", + }, + }); + await httpHeaderNormalizer()(handler)(event, createContext()); + expect(handler).toHaveBeenCalledWith( + expect.objectContaining({ + rawHeaders: expect.objectContaining({ + "Custom-Header": "Custom value", + }), + }), + expect.anything() ); }); + + describe("referer", () => { + it("if referer is set it calls the handler with referrer set to the same value", async () => { + const handler = jest.fn().mockResolvedValue(undefined); + const event = createEvent({ + headers: { + referer: "Custom value", + }, + }); + await httpHeaderNormalizer()(handler)(event, createContext()); + expect(handler).toHaveBeenCalledWith( + expect.objectContaining({ + headers: expect.objectContaining({ + referrer: "Custom value", + }), + }), + expect.anything() + ); + }); + + it("if referrer is set it calls the handler with referer set to the same value", async () => { + const handler = jest.fn().mockResolvedValue(undefined); + const event = createEvent({ + headers: { + referrer: "Custom value", + }, + }); + await httpHeaderNormalizer()(handler)(event, createContext()); + expect(handler).toHaveBeenCalledWith( + expect.objectContaining({ + headers: expect.objectContaining({ + referer: "Custom value", + }), + }), + expect.anything() + ); + }); + + it("if referer and referrer are set it calls the handler with the old values", async () => { + const handler = jest.fn().mockResolvedValue(undefined); + const event = createEvent({ + headers: { + referer: "Custom value", + referrer: "Other custom value", + }, + }); + await httpHeaderNormalizer()(handler)(event, createContext()); + expect(handler).toHaveBeenCalledWith( + expect.objectContaining({ + headers: expect.objectContaining({ + referer: "Custom value", + referrer: "Other custom value", + }), + }), + expect.anything() + ); + }); + }); }); diff --git a/packages/http-header-normalizer/src/http-header-normalizer.ts b/packages/http-header-normalizer/src/http-header-normalizer.ts index 1cac161..eb1ed8c 100644 --- a/packages/http-header-normalizer/src/http-header-normalizer.ts +++ b/packages/http-header-normalizer/src/http-header-normalizer.ts @@ -1,11 +1,38 @@ +import { compose } from "@lambda-middleware/compose"; import { PromiseHandler } from "@lambda-middleware/utils"; -import { APIGatewayProxyResult, Context } from "aws-lambda"; +import { APIGatewayProxyEvent, Context } from "aws-lambda"; import { logger } from "./logger"; -export const http-header-normalizer = () => ( - handler: PromiseHandler -) => async (event: E, context: Context): Promise => { +type HashMap = { [key: string]: Value }; + +function lowercaseKeys(object: HashMap): HashMap { + const newObject = {}; + for (const key in object) { + newObject[key.toLowerCase()] = object[key]; + } + return newObject; +} + +function addReferrer(headers: HashMap): HashMap { + return { + ...headers, + referrer: headers.referrer ?? headers.referer, + referer: headers.referer ?? headers.referrer, + }; +} + +function normalizeHeaders(headers: HashMap): HashMap { + return compose(addReferrer, lowercaseKeys)(headers); +} + +export const httpHeaderNormalizer = () => ( + handler: PromiseHandler }, R> +) => async (event: E, context: Context): Promise => { logger("Running handler"); - const response = await handler(event, context); - return response; + const normalizedEvent = { + ...event, + headers: normalizeHeaders(event.headers), + rawHeaders: event.headers, + }; + return handler(normalizedEvent, context); }; diff --git a/packages/http-header-normalizer/src/logger.ts b/packages/http-header-normalizer/src/logger.ts index 9c37005..34018fc 100644 --- a/packages/http-header-normalizer/src/logger.ts +++ b/packages/http-header-normalizer/src/logger.ts @@ -1,3 +1,5 @@ import debugFactory, { IDebugger } from "debug"; -export const logger: IDebugger = debugFactory("@lambda-middleware/http-header-normalizer"); +export const logger: IDebugger = debugFactory( + "@lambda-middleware/http-header-normalizer" +); From 540b4b4c4829cc1de7b0d0b5f718bde3e7763626 Mon Sep 17 00:00:00 2001 From: Daniel Bartholomae Date: Thu, 13 Aug 2020 12:28:48 +0200 Subject: [PATCH 8/8] chore: allow different casing in middleware names in template --- _templates/middleware/new/prompt.js | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/_templates/middleware/new/prompt.js b/_templates/middleware/new/prompt.js index f97f698..d1b46d3 100644 --- a/_templates/middleware/new/prompt.js +++ b/_templates/middleware/new/prompt.js @@ -1,10 +1,24 @@ +const uppercase = new RegExp("([A-Z])", "g"); +const underbar_prefix = new RegExp("^_"); + +function replaceAll(str, subStrs, by) { + let result = str; + for (const subStr of subStrs) { + result = result.split(subStr).join(by); + } + return result; +} + +function underscore(str) { + return replaceAll(str.replace(uppercase, "_$1"), ["-", " "], "_"); +} + module.exports = [ { type: "input", name: "name", - message: - "How do you want to call the middleware? Please separate with spaces, e. g. 'no sniff'", - result: (name) => name.toLowerCase(), + message: "How do you want to call the middleware?", + result: (name) => underscore(name), }, { type: "input",