|
1 | 1 | import * as lambda from '@aws-cdk/aws-lambda';
|
2 | 2 | import * as cdk from '@aws-cdk/core';
|
| 3 | +import * as es from 'esbuild'; |
| 4 | +import * as path from 'path'; |
3 | 5 |
|
4 |
| -import { nodeMajorVersion } from './utils'; |
| 6 | +import { extractFileName, findProjectRoot, nodeMajorVersion } from './utils'; |
5 | 7 |
|
| 8 | +/** |
| 9 | + * Properties for a NodejsFunction |
| 10 | + */ |
6 | 11 | export interface NodejsFunctionProps extends lambda.FunctionOptions {
|
7 | 12 | /**
|
8 |
| - * The name of the exported handler in the entry file. |
| 13 | + * The root of the lambda project. If you specify this prop, ensure that |
| 14 | + * this path includes `entry` and any module/dependencies used by your |
| 15 | + * function otherwise bundling will not be possible. |
9 | 16 | *
|
10 |
| - * @default "handler" |
| 17 | + * @default = the closest path containing a .git folder |
| 18 | + */ |
| 19 | + readonly rootDir?: string; |
| 20 | + |
| 21 | + /** |
| 22 | + * The name of the method within your code that Lambda calls to execute your function. |
| 23 | + * |
| 24 | + * The format includes the file name and handler function. |
| 25 | + * For more information, see https://docs.aws.amazon.com/lambda/latest/dg/lambda-nodejs.html. |
| 26 | + * |
| 27 | + * @default = 'index.handler' |
11 | 28 | */
|
12 | 29 | readonly handler?: string;
|
| 30 | + |
13 | 31 | /**
|
14 | 32 | * The runtime environment. Only runtimes of the Node.js family are
|
15 | 33 | * supported.
|
16 | 34 | *
|
17 |
| - * @default - `NODEJS_12_X` if `process.versions.node` >= '12.0.0', |
| 35 | + * @default = `NODEJS_12_X` if `process.versions.node` >= '12.0.0', |
18 | 36 | * `NODEJS_10_X` otherwise.
|
19 | 37 | */
|
20 | 38 | readonly runtime?: lambda.Runtime;
|
| 39 | + |
| 40 | + /** |
| 41 | + * The esbuild bundler specific options. |
| 42 | + * |
| 43 | + * @default = { platform: 'node' } |
| 44 | + */ |
| 45 | + readonly esbuildOptions?: es.BuildOptions; |
21 | 46 | }
|
22 | 47 |
|
| 48 | +const BUILD_FOLDER = '.build'; |
| 49 | +const DEFAULT_BUILD_OPTIONS: es.BuildOptions = { |
| 50 | + bundle: true, |
| 51 | + target: 'es2017', |
| 52 | + external: ['aws-sdk'], |
| 53 | +}; |
| 54 | + |
| 55 | +/** |
| 56 | + * A Node.js Lambda function bundled using `esbuild` |
| 57 | + */ |
23 | 58 | export class NodejsFunction extends lambda.Function {
|
24 | 59 | constructor(scope: cdk.Construct, id: string, props: NodejsFunctionProps = {}) {
|
25 | 60 | if (props.runtime && props.runtime.family !== lambda.RuntimeFamily.NODEJS) {
|
26 | 61 | throw new Error('Only `NODEJS` runtimes are supported.');
|
27 | 62 | }
|
28 | 63 |
|
29 |
| - const handler = props.handler ?? 'handler'; |
| 64 | + const projectRoot = findProjectRoot(props.rootDir); |
| 65 | + if (!projectRoot) { |
| 66 | + throw new Error('Cannot find root directory. Please specify it with `rootDir` option.'); |
| 67 | + } |
| 68 | + |
| 69 | + const handler = props.handler ?? 'index.handler'; |
30 | 70 | const defaultRunTime = nodeMajorVersion() >= 12
|
31 | 71 | ? lambda.Runtime.NODEJS_12_X
|
32 | 72 | : lambda.Runtime.NODEJS_10_X;
|
33 | 73 | const runtime = props.runtime ?? defaultRunTime;
|
| 74 | + const entry = extractFileName(projectRoot, handler); |
| 75 | + |
| 76 | + es.buildSync({ |
| 77 | + ...DEFAULT_BUILD_OPTIONS, |
| 78 | + ...props.esbuildOptions, |
| 79 | + entryPoints: [entry], |
| 80 | + outdir: path.join(projectRoot, BUILD_FOLDER, path.dirname(entry)), |
| 81 | + platform: 'node', |
| 82 | + }); |
34 | 83 |
|
35 | 84 | super(scope, id, {
|
36 | 85 | ...props,
|
37 | 86 | runtime,
|
38 |
| - code: lambda.Code.fromInline('TODO'), |
39 |
| - handler: `index.${handler}`, |
| 87 | + code: lambda.Code.fromAsset(path.join(projectRoot, BUILD_FOLDER)), |
| 88 | + handler, |
40 | 89 | });
|
41 | 90 | }
|
42 | 91 | }
|
0 commit comments