From 55b8e950838bbaa4686bbb30e8bc88b8ad75c53f Mon Sep 17 00:00:00 2001 From: Marcel Hoppe Date: Tue, 21 Jan 2020 15:27:42 +0100 Subject: [PATCH 1/2] feat: add custom inputs for lambda name - closes #232 --- README.md | 14 +++++ .../serverless-nextjs-component/README.md | 14 +++++ .../__tests__/custom-inputs.test.js | 60 +++++++++++++++++++ .../serverless-nextjs-component/serverless.js | 23 +++++-- 4 files changed, 107 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 6bd9d04f5f..7358b07ad5 100644 --- a/README.md +++ b/README.md @@ -175,6 +175,19 @@ myNextApplication: Note the maximum timeout allowed for Lambda@Edge is 30 seconds. See https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/lambda-requirements-limits.html +You can also set a custom name for **default** and **api** lambdas - if not the default is set by the [aws-lambda serverless component](https://github.com/serverless-components/aws-lambda) to the resource id: + +```yml +# serverless.yml + +myNextApplication: + component: serverless-next.js + inputs: + name: + defaultLambda: fooDefaultLambda + apiLambda: fooApiLambda +``` + ### Architecture ![architecture](./arch_no_grid.png) @@ -205,6 +218,7 @@ The fourth cache behaviour handles next API requests `api/*`. | nextStaticDir | `string` | `./` | If your `static` or `public` directory is not a direct child of `nextConfigDir` this is needed | | memory | `number\|object` | `512` | When assigned a number, both the default and api lambdas will assigned memory of that value. When assigned to an object, values for the default and api lambdas can be separately defined | | | timeout | `number\|object` | `10` | Same as above | +| name | `string\|object` | / | When assigned a string, both the default and api lambdas will assigned name of that value. When assigned to an object, values for the default and api lambdas can be separately defined | | build | `boolean\|object` | `true` | When true builds and deploys app, when false assume the app has been built and uses the `.next` `.serverless_nextjs` directories in `nextConfigDir` to deploy. If an object is passed `build` allows for overriding what script gets called and with what arguments. | | build.cmd | `string` | `node_modules/.bin/next` | Build command | | build.args | `Array\|string` | `['build']` | Arguments to pass to the build | diff --git a/packages/serverless-nextjs-component/README.md b/packages/serverless-nextjs-component/README.md index 6bd9d04f5f..7358b07ad5 100644 --- a/packages/serverless-nextjs-component/README.md +++ b/packages/serverless-nextjs-component/README.md @@ -175,6 +175,19 @@ myNextApplication: Note the maximum timeout allowed for Lambda@Edge is 30 seconds. See https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/lambda-requirements-limits.html +You can also set a custom name for **default** and **api** lambdas - if not the default is set by the [aws-lambda serverless component](https://github.com/serverless-components/aws-lambda) to the resource id: + +```yml +# serverless.yml + +myNextApplication: + component: serverless-next.js + inputs: + name: + defaultLambda: fooDefaultLambda + apiLambda: fooApiLambda +``` + ### Architecture ![architecture](./arch_no_grid.png) @@ -205,6 +218,7 @@ The fourth cache behaviour handles next API requests `api/*`. | nextStaticDir | `string` | `./` | If your `static` or `public` directory is not a direct child of `nextConfigDir` this is needed | | memory | `number\|object` | `512` | When assigned a number, both the default and api lambdas will assigned memory of that value. When assigned to an object, values for the default and api lambdas can be separately defined | | | timeout | `number\|object` | `10` | Same as above | +| name | `string\|object` | / | When assigned a string, both the default and api lambdas will assigned name of that value. When assigned to an object, values for the default and api lambdas can be separately defined | | build | `boolean\|object` | `true` | When true builds and deploys app, when false assume the app has been built and uses the `.next` `.serverless_nextjs` directories in `nextConfigDir` to deploy. If an object is passed `build` allows for overriding what script gets called and with what arguments. | | build.cmd | `string` | `node_modules/.bin/next` | Build command | | build.args | `Array\|string` | `['build']` | Arguments to pass to the build | diff --git a/packages/serverless-nextjs-component/__tests__/custom-inputs.test.js b/packages/serverless-nextjs-component/__tests__/custom-inputs.test.js index 3e4ccd4757..7864371163 100644 --- a/packages/serverless-nextjs-component/__tests__/custom-inputs.test.js +++ b/packages/serverless-nextjs-component/__tests__/custom-inputs.test.js @@ -196,4 +196,64 @@ describe("Custom inputs", () => { ); }); }); + + describe.each([ + [undefined, { defaultName: undefined, apiName: undefined }], + [{}, { defaultName: undefined, apiName: undefined }], + ["fooFunction", { defaultName: "fooFunction", apiName: "fooFunction" }], + [ + { defaultLambda: "fooFunction" }, + { defaultName: "fooFunction", apiName: undefined } + ], + [ + { apiLambda: "fooFunction" }, + { defaultName: undefined, apiName: "fooFunction" } + ], + [ + { defaultLambda: "fooFunction", apiLambda: "barFunction" }, + { defaultName: "fooFunction", apiName: "barFunction" } + ] + ])("Lambda name input", (inputName, expectedName) => { + let tmpCwd; + const fixturePath = path.join(__dirname, "./fixtures/generic-fixture"); + + beforeEach(async () => { + execa.mockResolvedValueOnce(); + + tmpCwd = process.cwd(); + process.chdir(fixturePath); + + mockCloudFront.mockResolvedValueOnce({ + url: "https://cloudfrontdistrib.amazonaws.com" + }); + + const component = new NextjsComponent(); + componentOutputs = await component.default({ + name: inputName + }); + }); + it(`sets default lambda name to ${expectedName.defaultName} and api lambda name to ${expectedName.apiName}`, () => { + const { defaultName, apiName } = expectedName; + + // Default Lambda + const expectedDefaultObject = { + code: path.join(fixturePath, DEFAULT_LAMBDA_CODE_DIR) + }; + if (defaultName) expectedDefaultObject.name = defaultName; + + expect(mockLambda).toBeCalledWith( + expect.objectContaining(expectedDefaultObject) + ); + + // Api Lambda + const expectedApiObject = { + code: path.join(fixturePath, API_LAMBDA_CODE_DIR) + }; + if (apiName) expectedApiObject.name = apiName; + + expect(mockLambda).toBeCalledWith( + expect.objectContaining(expectedApiObject) + ); + }); + }); }); diff --git a/packages/serverless-nextjs-component/serverless.js b/packages/serverless-nextjs-component/serverless.js index 0e51c2755a..135931e770 100644 --- a/packages/serverless-nextjs-component/serverless.js +++ b/packages/serverless-nextjs-component/serverless.js @@ -395,8 +395,13 @@ class NextjsComponent extends Component { ? inputs.timeout : (inputs.timeout && inputs.timeout[lambdaType]) || 10; + const getLambdaName = lambdaType => + typeof inputs.name === "string" + ? inputs.name + : inputs.name && inputs.name[lambdaType]; + if (hasAPIPages) { - apiEdgeLambdaOutputs = await apiEdgeLambda({ + const apiEdgeLambdaInput = { description: "API Lambda@Edge for Next CloudFront distribution", handler: "index.handler", code: join(nextConfigPath, API_LAMBDA_CODE_DIR), @@ -410,7 +415,11 @@ class NextjsComponent extends Component { }, memory: getLambdaMemory("apiLambda"), timeout: getLambdaTimeout("apiLambda") - }); + }; + const apiLambdaName = getLambdaName("apiLambda"); + if (apiLambdaName) apiEdgeLambdaInput.name = apiLambdaName; + + apiEdgeLambdaOutputs = await apiEdgeLambda(apiEdgeLambdaInput); apiEdgeLambdaPublishOutputs = await apiEdgeLambda.publishVersion(); @@ -431,7 +440,7 @@ class NextjsComponent extends Component { }; } - const defaultEdgeLambdaOutputs = await defaultEdgeLambda({ + const defaultEdgeLambdaInput = { description: "Default Lambda@Edge for Next CloudFront distribution", handler: "index.handler", code: join(nextConfigPath, DEFAULT_LAMBDA_CODE_DIR), @@ -445,7 +454,13 @@ class NextjsComponent extends Component { }, memory: getLambdaMemory("defaultLambda"), timeout: getLambdaTimeout("defaultLambda") - }); + }; + const defaultLambdaName = getLambdaName("defaultLambda"); + if (defaultLambdaName) defaultEdgeLambdaInput.name = defaultLambdaName; + + const defaultEdgeLambdaOutputs = await defaultEdgeLambda( + defaultEdgeLambdaInput + ); const defaultEdgeLambdaPublishOutputs = await defaultEdgeLambda.publishVersion(); From b3106b808ab3835ccbae56800845d4710b10ca73 Mon Sep 17 00:00:00 2001 From: Marcel Hoppe Date: Tue, 21 Jan 2020 15:43:41 +0100 Subject: [PATCH 2/2] Fix misaligned table fence --- README.md | 2 +- packages/serverless-nextjs-component/README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 7358b07ad5..02889fe8e2 100644 --- a/README.md +++ b/README.md @@ -218,7 +218,7 @@ The fourth cache behaviour handles next API requests `api/*`. | nextStaticDir | `string` | `./` | If your `static` or `public` directory is not a direct child of `nextConfigDir` this is needed | | memory | `number\|object` | `512` | When assigned a number, both the default and api lambdas will assigned memory of that value. When assigned to an object, values for the default and api lambdas can be separately defined | | | timeout | `number\|object` | `10` | Same as above | -| name | `string\|object` | / | When assigned a string, both the default and api lambdas will assigned name of that value. When assigned to an object, values for the default and api lambdas can be separately defined | +| name | `string\|object` | / | When assigned a string, both the default and api lambdas will assigned name of that value. When assigned to an object, values for the default and api lambdas can be separately defined | | build | `boolean\|object` | `true` | When true builds and deploys app, when false assume the app has been built and uses the `.next` `.serverless_nextjs` directories in `nextConfigDir` to deploy. If an object is passed `build` allows for overriding what script gets called and with what arguments. | | build.cmd | `string` | `node_modules/.bin/next` | Build command | | build.args | `Array\|string` | `['build']` | Arguments to pass to the build | diff --git a/packages/serverless-nextjs-component/README.md b/packages/serverless-nextjs-component/README.md index 7358b07ad5..02889fe8e2 100644 --- a/packages/serverless-nextjs-component/README.md +++ b/packages/serverless-nextjs-component/README.md @@ -218,7 +218,7 @@ The fourth cache behaviour handles next API requests `api/*`. | nextStaticDir | `string` | `./` | If your `static` or `public` directory is not a direct child of `nextConfigDir` this is needed | | memory | `number\|object` | `512` | When assigned a number, both the default and api lambdas will assigned memory of that value. When assigned to an object, values for the default and api lambdas can be separately defined | | | timeout | `number\|object` | `10` | Same as above | -| name | `string\|object` | / | When assigned a string, both the default and api lambdas will assigned name of that value. When assigned to an object, values for the default and api lambdas can be separately defined | +| name | `string\|object` | / | When assigned a string, both the default and api lambdas will assigned name of that value. When assigned to an object, values for the default and api lambdas can be separately defined | | build | `boolean\|object` | `true` | When true builds and deploys app, when false assume the app has been built and uses the `.next` `.serverless_nextjs` directories in `nextConfigDir` to deploy. If an object is passed `build` allows for overriding what script gets called and with what arguments. | | build.cmd | `string` | `node_modules/.bin/next` | Build command | | build.args | `Array\|string` | `['build']` | Arguments to pass to the build |