node-lambda 0.18.0 → 0.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/workflow.yml +4 -3
- package/.travis.yml +2 -0
- package/CHANGELOG.md +23 -0
- package/README.md +69 -67
- package/bin/node-lambda +7 -6
- package/lib/main.js +132 -100
- package/package.json +15 -15
- package/test/main.js +328 -98
|
@@ -9,13 +9,14 @@ jobs:
|
|
|
9
9
|
strategy:
|
|
10
10
|
fail-fast: false
|
|
11
11
|
matrix:
|
|
12
|
-
node-version: [
|
|
12
|
+
node-version: [12.x, 14.x, 16.x, 17.x]
|
|
13
13
|
os: [ubuntu-latest, windows-latest, macos-latest]
|
|
14
14
|
steps:
|
|
15
|
-
- uses: actions/checkout@
|
|
16
|
-
- uses: actions/setup-node@
|
|
15
|
+
- uses: actions/checkout@v2
|
|
16
|
+
- uses: actions/setup-node@v2
|
|
17
17
|
with:
|
|
18
18
|
node-version: ${{ matrix.node-version }}
|
|
19
|
+
cache: 'npm'
|
|
19
20
|
- run: npm i -g npm
|
|
20
21
|
- run: node -v
|
|
21
22
|
- run: npm -v
|
package/.travis.yml
CHANGED
package/CHANGELOG.md
CHANGED
|
@@ -421,3 +421,26 @@ This project adheres to [Semantic Versioning](http://semver.org/).
|
|
|
421
421
|
- Upgrade packages [#538](https://github.com/motdotla/node-lambda/pull/538)
|
|
422
422
|
- Bump lodash from 4.17.15 to 4.17.19 [#536](https://github.com/motdotla/node-lambda/pull/536)
|
|
423
423
|
- Add build badge in README [#534](https://github.com/motdotla/node-lambda/pull/534)
|
|
424
|
+
|
|
425
|
+
## [0.19.0] - 2021-03-30
|
|
426
|
+
### Features
|
|
427
|
+
- feat: support `--no-optional` option in npm install [#557](https://github.com/motdotla/node-lambda/pull/557)
|
|
428
|
+
|
|
429
|
+
## [0.19.1] - 2021-04-24
|
|
430
|
+
### Bugfixes
|
|
431
|
+
- Fix errors caused by old proxy-agent [#564](https://github.com/motdotla/node-lambda/pull/564)
|
|
432
|
+
|
|
433
|
+
## [0.20.0] - 2021-09-25
|
|
434
|
+
### Features
|
|
435
|
+
- updated proxy-agent to 5.0.0 [#574](https://github.com/motdotla/node-lambda/pull/574)
|
|
436
|
+
- show suggestions after an error for an unknown command or option [#572](https://github.com/motdotla/node-lambda/pull/572)
|
|
437
|
+
- feat: drop nodejs10x from lambda runtime [#571](https://github.com/motdotla/node-lambda/pull/571)
|
|
438
|
+
|
|
439
|
+
### Bugfixes
|
|
440
|
+
- fix(_uploadExisting): fix function update errors [#575](https://github.com/motdotla/node-lambda/pull/575)
|
|
441
|
+
- test: fix npm install test failing in some cases [#569](https://github.com/motdotla/node-lambda/pull/569)
|
|
442
|
+
- Clean the tmp dir during `_archivePrebuilt` to match `_buildAndArchive` behavior [#518](https://github.com/motdotla/node-lambda/pull/518)
|
|
443
|
+
|
|
444
|
+
## [0.21.0] - 2021-11-10
|
|
445
|
+
### Features
|
|
446
|
+
- feat: support for yarn [#581](https://github.com/motdotla/node-lambda/pull/581)
|
package/README.md
CHANGED
|
@@ -64,6 +64,7 @@ $ echo -e ".env\ndeploy.env\nevent.json\n.lambda" >> .gitignore
|
|
|
64
64
|
##### Deploy env variables
|
|
65
65
|
|
|
66
66
|
```
|
|
67
|
+
PACKAGE_MANAGER // (default: 'npm')
|
|
67
68
|
AWS_ENVIRONMENT // (default: '')
|
|
68
69
|
AWS_ENDPOINT // (default: '')
|
|
69
70
|
CONFIG_FILE // (default: '')
|
|
@@ -109,23 +110,21 @@ Runs your Amazon Lambda index.js file locally. Passes `event.json` data to the A
|
|
|
109
110
|
|
|
110
111
|
```
|
|
111
112
|
$ node-lambda run --help
|
|
112
|
-
|
|
113
|
-
Usage: run|execute [options]
|
|
113
|
+
Usage: node-lambda run|execute [options]
|
|
114
114
|
|
|
115
115
|
Run your Amazon Lambda application locally
|
|
116
116
|
|
|
117
|
-
|
|
118
117
|
Options:
|
|
119
|
-
-
|
|
120
|
-
-
|
|
121
|
-
-
|
|
122
|
-
-
|
|
123
|
-
-
|
|
124
|
-
-
|
|
125
|
-
-
|
|
126
|
-
-
|
|
127
|
-
|
|
128
|
-
--
|
|
118
|
+
-H, --handler [AWS_HANDLER] Lambda Handler {index.handler} (default: "index.handler")
|
|
119
|
+
-j, --eventFile [EVENT_FILE] Event JSON File (default: "event.json")
|
|
120
|
+
-u, --runtime [AWS_RUNTIME] Lambda Runtime (default: "nodejs14.x")
|
|
121
|
+
-t, --timeout [AWS_RUN_TIMEOUT] Lambda Timeout (default: 3)
|
|
122
|
+
-f, --configFile [CONFIG_FILE] Path to file holding secret environment variables (e.g. "deploy.env") (default: "")
|
|
123
|
+
-x, --contextFile [CONTEXT_FILE] Context JSON File (default: "context.json")
|
|
124
|
+
-M, --enableRunMultipleEvents [ENABLE_RUN_MULTIPLE_EVENTS] Enable run multiple events (default: true)
|
|
125
|
+
-y, --proxy [PROXY] Proxy server (default: "")
|
|
126
|
+
--apiGateway Convert to API Gateway events (default: false)
|
|
127
|
+
-h, --help display help for command
|
|
129
128
|
```
|
|
130
129
|
|
|
131
130
|
#### package
|
|
@@ -134,23 +133,26 @@ Bundles your application into a local zip file.
|
|
|
134
133
|
|
|
135
134
|
```
|
|
136
135
|
$ node-lambda package --help
|
|
137
|
-
|
|
138
|
-
Usage: package|zip [options]
|
|
136
|
+
Usage: node-lambda package|zip [options]
|
|
139
137
|
|
|
140
138
|
Create zipped package for Amazon Lambda deployment
|
|
141
139
|
|
|
142
|
-
|
|
143
140
|
Options:
|
|
144
|
-
|
|
145
|
-
-A, --packageDirectory [
|
|
146
|
-
-I, --dockerImage [] Docker image for npm
|
|
147
|
-
-n, --functionName [
|
|
148
|
-
-H, --handler [
|
|
149
|
-
-e, --environment [
|
|
150
|
-
-x, --excludeGlobs [
|
|
151
|
-
|
|
152
|
-
-
|
|
153
|
-
-
|
|
141
|
+
--packageManager [PACKAGE_MANAGER] Package manager used to install dependencies (default: "npm", options: "npm", "yarn")
|
|
142
|
+
-A, --packageDirectory [PACKAGE_DIRECTORY] Local Package Directory
|
|
143
|
+
-I, --dockerImage [DOCKER_IMAGE] Docker image for npm ci (default: "")
|
|
144
|
+
-n, --functionName [AWS_FUNCTION_NAME] Lambda FunctionName (default: "node-lambda")
|
|
145
|
+
-H, --handler [AWS_HANDLER] Lambda Handler {index.handler} (default: "index.handler")
|
|
146
|
+
-e, --environment [AWS_ENVIRONMENT] Choose environment {dev, staging, production} (default: "")
|
|
147
|
+
-x, --excludeGlobs [EXCLUDE_GLOBS] Space-separated glob pattern(s) for additional exclude files (e.g.
|
|
148
|
+
"event.json dotenv.sample") (default: "")
|
|
149
|
+
-D, --prebuiltDirectory [PREBUILT_DIRECTORY] Prebuilt directory (default: "")
|
|
150
|
+
-m, --keepNodeModules [KEEP_NODE_MODULES] Keep the current node_modules directory. (default: false)
|
|
151
|
+
-v, --dockerVolumes [DOCKER_VOLUMES] Additional docker volumes to mount. Each volume definition has to be
|
|
152
|
+
separated by a space (e.g. "$HOME/.gitconfig:/etc/gitconfig
|
|
153
|
+
$HOME/.ssh:/root/.ssh") (default: "")
|
|
154
|
+
--no-optionalDependencies Run `npm install` with `--no-optional`
|
|
155
|
+
-h, --help display help for command
|
|
154
156
|
```
|
|
155
157
|
|
|
156
158
|
#### deploy
|
|
@@ -159,50 +161,50 @@ Bundles and deploys your application up to Amazon Lambda.
|
|
|
159
161
|
|
|
160
162
|
```
|
|
161
163
|
$ node-lambda deploy --help
|
|
162
|
-
|
|
163
|
-
Usage: deploy [options]
|
|
164
|
+
Usage: node-lambda deploy [options]
|
|
164
165
|
|
|
165
166
|
Deploy your application to Amazon Lambda
|
|
166
167
|
|
|
167
|
-
|
|
168
168
|
Options:
|
|
169
|
-
|
|
170
|
-
-e, --environment [
|
|
171
|
-
-E, --endpoint [AWS_ENDPOINT]
|
|
172
|
-
-a, --accessKey [
|
|
173
|
-
-s, --secretKey [
|
|
174
|
-
-P, --profile []
|
|
175
|
-
-k, --sessionToken []
|
|
176
|
-
-r, --region [us-east-1
|
|
177
|
-
-n, --functionName [
|
|
178
|
-
-H, --handler [
|
|
179
|
-
-o, --role [
|
|
180
|
-
-m, --memorySize [
|
|
181
|
-
-t, --timeout [
|
|
182
|
-
-d, --description [
|
|
183
|
-
-u, --runtime [
|
|
184
|
-
-p, --publish [
|
|
185
|
-
-L, --lambdaVersion []
|
|
186
|
-
-b, --vpcSubnets []
|
|
187
|
-
-g, --vpcSecurityGroups []
|
|
188
|
-
-K, --kmsKeyArn []
|
|
189
|
-
-Q, --deadLetterConfigTargetArn [] Lambda DLQ resource
|
|
190
|
-
-c, --tracingConfig [] Lambda tracing settings
|
|
191
|
-
-l, --layers []
|
|
192
|
-
-R, --retentionInDays []
|
|
193
|
-
-G, --sourceDirectory []
|
|
194
|
-
-I, --dockerImage []
|
|
195
|
-
-f, --configFile []
|
|
196
|
-
-S, --eventSourceFile []
|
|
197
|
-
-x, --excludeGlobs [
|
|
198
|
-
-D, --prebuiltDirectory [] Prebuilt directory
|
|
199
|
-
-T, --deployTimeout [
|
|
200
|
-
-z, --deployZipfile []
|
|
201
|
-
-B, --deployUseS3 []
|
|
202
|
-
-i, --imageUri []
|
|
203
|
-
-y, --proxy []
|
|
204
|
-
-A, --tags []
|
|
205
|
-
--silent
|
|
169
|
+
--packageManager [PACKAGE_MANAGER] Package manager used to install dependencies (default: "npm", options: "npm", "yarn")
|
|
170
|
+
-e, --environment [AWS_ENVIRONMENT] Choose environment {dev, staging, production} (default: "")
|
|
171
|
+
-E, --endpoint [AWS_ENDPOINT] Choose endpoint (e.g. localstack, "http://127.0.0.1:4574") (default: "")
|
|
172
|
+
-a, --accessKey [AWS_ACCESS_KEY_ID] AWS Access Key
|
|
173
|
+
-s, --secretKey [AWS_SECRET_ACCESS_KEY] AWS Secret Key
|
|
174
|
+
-P, --profile [AWS_PROFILE] AWS Profile (default: "")
|
|
175
|
+
-k, --sessionToken [AWS_SESSION_TOKEN] AWS Session Token (default: "")
|
|
176
|
+
-r, --region [AWS_REGION] AWS Region (default: "us-east-1,us-west-2,eu-west-1")
|
|
177
|
+
-n, --functionName [AWS_FUNCTION_NAME] Lambda FunctionName (default: "node-lambda")
|
|
178
|
+
-H, --handler [AWS_HANDLER] Lambda Handler {index.handler} (default: "index.handler")
|
|
179
|
+
-o, --role [AWS_ROLE] Amazon Role ARN (default: "missing")
|
|
180
|
+
-m, --memorySize [AWS_MEMORY_SIZE] Lambda Memory Size (default: 128)
|
|
181
|
+
-t, --timeout [AWS_TIMEOUT] Lambda Timeout (default: 60)
|
|
182
|
+
-d, --description [AWS_DESCRIPTION] Lambda Description (default: "Command line tool for locally running and remotely deploying your node.js applications to Amazon Lambda.")
|
|
183
|
+
-u, --runtime [AWS_RUNTIME] Lambda Runtime (default: "nodejs14.x")
|
|
184
|
+
-p, --publish [AWS_PUBLISH] Lambda Publish (default: false)
|
|
185
|
+
-L, --lambdaVersion [AWS_FUNCTION_VERSION] Lambda Function Version (default: "")
|
|
186
|
+
-b, --vpcSubnets [AWS_VPC_SUBNETS] Lambda Function VPC Subnet IDs (comma delimited) (default: "")
|
|
187
|
+
-g, --vpcSecurityGroups [AWS_VPC_SECURITY_GROUPS] Lambda VPC Security Group IDs (comma delimited) (default: "")
|
|
188
|
+
-K, --kmsKeyArn [AWS_KMS_KEY_ARN] Lambda KMS Key ARN (default: "")
|
|
189
|
+
-Q, --deadLetterConfigTargetArn [AWS_DLQ_TARGET_ARN] Lambda DLQ resource
|
|
190
|
+
-c, --tracingConfig [AWS_TRACING_CONFIG] Lambda tracing settings (default: "")
|
|
191
|
+
-l, --layers [AWS_LAYERS] Lambda Layers settings (e.g. "ARN1,ARN2[,..])" (default: "")
|
|
192
|
+
-R, --retentionInDays [AWS_LOGS_RETENTION_IN_DAYS] CloudWatchLogs retentionInDays settings (default: "")
|
|
193
|
+
-G, --sourceDirectory [SRC_DIRECTORY] Path to lambda source Directory (e.g. "./some-lambda") (default: "")
|
|
194
|
+
-I, --dockerImage [DOCKER_IMAGE] Docker image for npm ci (default: "")
|
|
195
|
+
-f, --configFile [CONFIG_FILE] Path to file holding secret environment variables (e.g. "deploy.env") (default: "")
|
|
196
|
+
-S, --eventSourceFile [EVENT_SOURCE_FILE] Path to file holding event source mapping variables (e.g. "event_sources.json") (default: "")
|
|
197
|
+
-x, --excludeGlobs [EXCLUDE_GLOBS] Space-separated glob pattern(s) for additional exclude files (e.g. "event.json dotenv.sample") (default: "")
|
|
198
|
+
-D, --prebuiltDirectory [PREBUILT_DIRECTORY] Prebuilt directory (default: "")
|
|
199
|
+
-T, --deployTimeout [DEPLOY_TIMEOUT] Deploy Timeout (default: 120000)
|
|
200
|
+
-z, --deployZipfile [DEPLOY_ZIPFILE] Deploy zipfile (default: "")
|
|
201
|
+
-B, --deployUseS3 [DEPLOY_USE_S3] Use S3 to deploy. (default: false)
|
|
202
|
+
-i, --imageUri [IMAGE_URI] URI of a container image in the Amazon ECR registry. (default: "")
|
|
203
|
+
-y, --proxy [PROXY] Proxy server (default: "")
|
|
204
|
+
-A, --tags [AWS_TAGS] Tags as key value pairs (e.g. "tagname1=tagvalue1,tagname2=tagvalue2)" (default: "")
|
|
205
|
+
--silent Silent or quiet mode (default: false)
|
|
206
|
+
--no-optionalDependencies Run `npm install` with `--no-optional`
|
|
207
|
+
-h, --help display help for command
|
|
206
208
|
```
|
|
207
209
|
|
|
208
210
|
If you are deploying to a custom endpoint you may also need to pass in an access key/secret. For localstack these can be anything, but cannot be blank:
|
|
@@ -217,7 +219,7 @@ AWS Lambda will let you set environment variables for your function. Use the sam
|
|
|
217
219
|
|
|
218
220
|
## Node.js Runtime Configuration
|
|
219
221
|
|
|
220
|
-
AWS Lambda now supports Node.js14
|
|
222
|
+
AWS Lambda now supports Node.js14 and Node.js 12. Please also check the [Lambda runtimes](https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtimes.html) page.
|
|
221
223
|
|
|
222
224
|
## To deploy a container image to Lambda
|
|
223
225
|
|
package/bin/node-lambda
CHANGED
|
@@ -11,6 +11,7 @@ const fs = require('fs')
|
|
|
11
11
|
const packageJson = fs.existsSync(path.join(process.cwd(), 'package.json')) ? require(path.join(process.cwd(), 'package.json')) : {}
|
|
12
12
|
const packageJsonName = packageJson.name || 'UnnamedFunction'
|
|
13
13
|
|
|
14
|
+
const PACKAGE_MANAGER = process.env.PACKAGE_MANAGER || 'npm'
|
|
14
15
|
const AWS_ENVIRONMENT = process.env.AWS_ENVIRONMENT || ''
|
|
15
16
|
const AWS_ENDPOINT = process.env.AWS_ENDPOINT || ''
|
|
16
17
|
const CONFIG_FILE = process.env.CONFIG_FILE || ''
|
|
@@ -61,9 +62,12 @@ const DOCKER_VOLUMES = process.env.DOCKER_VOLUMES || ''
|
|
|
61
62
|
const AWS_TAGS = process.env.AWS_TAGS || ''
|
|
62
63
|
const IMAGE_URI = process.env.IMAGE_URI || ''
|
|
63
64
|
|
|
65
|
+
program.showSuggestionAfterError()
|
|
66
|
+
|
|
64
67
|
program
|
|
65
68
|
.command('deploy')
|
|
66
69
|
.description('Deploy your application to Amazon Lambda')
|
|
70
|
+
.option('--packageManager [PACKAGE_MANAGER]', 'Package manager used to install dependencies', PACKAGE_MANAGER)
|
|
67
71
|
.option('-e, --environment [AWS_ENVIRONMENT]', 'Choose environment {dev, staging, production}',
|
|
68
72
|
AWS_ENVIRONMENT)
|
|
69
73
|
.option('-E, --endpoint [AWS_ENDPOINT]', 'Choose endpoint (e.g. localstack, "http://127.0.0.1:4574")',
|
|
@@ -109,6 +113,7 @@ program
|
|
|
109
113
|
.option('-y, --proxy [PROXY]', 'Proxy server', PROXY)
|
|
110
114
|
.option('-A, --tags [AWS_TAGS]', 'Tags as key value pairs (e.g. "tagname1=tagvalue1,tagname2=tagvalue2)"', AWS_TAGS)
|
|
111
115
|
.option('--silent', 'Silent or quiet mode', false)
|
|
116
|
+
.option('--no-optionalDependencies', 'Run `npm install` with `--no-optional`')
|
|
112
117
|
.action((prg) => {
|
|
113
118
|
if (prg.silent) {
|
|
114
119
|
console.log = () => {}
|
|
@@ -120,6 +125,7 @@ program
|
|
|
120
125
|
.command('package')
|
|
121
126
|
.alias('zip')
|
|
122
127
|
.description('Create zipped package for Amazon Lambda deployment')
|
|
128
|
+
.option('--packageManager [PACKAGE_MANAGER]', 'Package manager used to install dependencies', PACKAGE_MANAGER)
|
|
123
129
|
.option('-A, --packageDirectory [PACKAGE_DIRECTORY]', 'Local Package Directory', PACKAGE_DIRECTORY)
|
|
124
130
|
.option('-I, --dockerImage [DOCKER_IMAGE]', 'Docker image for npm ci', DOCKER_IMAGE)
|
|
125
131
|
.option('-n, --functionName [AWS_FUNCTION_NAME]', 'Lambda FunctionName', AWS_FUNCTION_NAME)
|
|
@@ -131,6 +137,7 @@ program
|
|
|
131
137
|
.option('-D, --prebuiltDirectory [PREBUILT_DIRECTORY]', 'Prebuilt directory', PREBUILT_DIRECTORY)
|
|
132
138
|
.option('-m, --keepNodeModules [KEEP_NODE_MODULES]', 'Keep the current node_modules directory.', KEEP_NODE_MODULES)
|
|
133
139
|
.option('-v, --dockerVolumes [DOCKER_VOLUMES]', 'Additional docker volumes to mount. Each volume definition has to be separated by a space (e.g. "$HOME/.gitconfig:/etc/gitconfig $HOME/.ssh:/root/.ssh")', DOCKER_VOLUMES)
|
|
140
|
+
.option('--no-optionalDependencies', 'Run `npm install` with `--no-optional`')
|
|
134
141
|
.action((prg) => lambda.package(prg))
|
|
135
142
|
|
|
136
143
|
program
|
|
@@ -157,12 +164,6 @@ program
|
|
|
157
164
|
.option('-x, --contextFile [CONTEXT_FILE]', 'Context JSON File', CONTEXT_FILE)
|
|
158
165
|
.action((prg) => lambda.setup(prg))
|
|
159
166
|
|
|
160
|
-
program.on('command:*', (cmd) => {
|
|
161
|
-
console.log(`Unknown command ${cmd}`)
|
|
162
|
-
console.log()
|
|
163
|
-
program.help()
|
|
164
|
-
})
|
|
165
|
-
|
|
166
167
|
program
|
|
167
168
|
.version(lambda.version)
|
|
168
169
|
.parse(process.argv)
|
package/lib/main.js
CHANGED
|
@@ -51,7 +51,7 @@ event_sources.json and ${program.eventFile} files as needed.`)
|
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
run (program) {
|
|
54
|
-
if (!['
|
|
54
|
+
if (!['nodejs12.x', 'nodejs14.x'].includes(program.runtime)) {
|
|
55
55
|
console.error(`Runtime [${program.runtime}] is not supported.`)
|
|
56
56
|
process.exit(254)
|
|
57
57
|
}
|
|
@@ -385,73 +385,108 @@ Emulate only the body of the API Gateway event.
|
|
|
385
385
|
return fs.existsSync(path.join(codeDirectory, 'package-lock.json'))
|
|
386
386
|
}
|
|
387
387
|
|
|
388
|
-
|
|
389
|
-
const
|
|
390
|
-
|
|
391
|
-
: 'install'
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
'run', '--rm',
|
|
395
|
-
'-v', `${fs.realpathSync(codeDirectory)}:/var/task`,
|
|
396
|
-
'-w', '/var/task'
|
|
388
|
+
_getNpmInstallCommand (program, codeDirectory) {
|
|
389
|
+
const installOptions = [
|
|
390
|
+
'-s',
|
|
391
|
+
this._shouldUseNpmCi(codeDirectory) ? 'ci' : 'install',
|
|
392
|
+
'--production',
|
|
393
|
+
'--no-audit'
|
|
397
394
|
]
|
|
398
395
|
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
})
|
|
396
|
+
if (program.optionalDependencies === false) {
|
|
397
|
+
installOptions.push('--no-optional')
|
|
398
|
+
}
|
|
403
399
|
|
|
404
|
-
|
|
400
|
+
if (!program.dockerImage) {
|
|
401
|
+
installOptions.push('--prefix', codeDirectory)
|
|
402
|
+
}
|
|
405
403
|
|
|
406
|
-
|
|
404
|
+
return {
|
|
405
|
+
packageManager: 'npm',
|
|
406
|
+
installOptions
|
|
407
|
+
}
|
|
408
|
+
}
|
|
407
409
|
|
|
408
|
-
|
|
410
|
+
_getYarnInstallCommand (program, codeDirectory) {
|
|
411
|
+
const installOptions = [
|
|
409
412
|
'-s',
|
|
410
|
-
|
|
411
|
-
'--production'
|
|
412
|
-
'--no-audit',
|
|
413
|
-
'--prefix', codeDirectory
|
|
413
|
+
'install',
|
|
414
|
+
'--production'
|
|
414
415
|
]
|
|
415
416
|
|
|
416
|
-
|
|
417
|
-
|
|
417
|
+
if (program.optionalDependencies === false) {
|
|
418
|
+
installOptions.push('--ignore-optional')
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
if (!program.dockerImage) {
|
|
422
|
+
installOptions.push('--cwd', codeDirectory)
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
return {
|
|
426
|
+
packageManager: 'yarn',
|
|
427
|
+
installOptions
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
_packageInstall (program, codeDirectory) {
|
|
432
|
+
// Run on windows:
|
|
433
|
+
// https://nodejs.org/api/child_process.html#child_process_spawning_bat_and_cmd_files_on_windows
|
|
418
434
|
|
|
435
|
+
const { packageManager, installOptions } = (() => {
|
|
436
|
+
// default npm
|
|
437
|
+
if (program.packageManager === 'yarn') {
|
|
438
|
+
return this._getYarnInstallCommand(program, codeDirectory)
|
|
439
|
+
}
|
|
440
|
+
return this._getNpmInstallCommand(program, codeDirectory)
|
|
441
|
+
})()
|
|
442
|
+
|
|
443
|
+
const paramsOnContainer = (() => {
|
|
419
444
|
// with docker
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
445
|
+
let dockerVolumesOptions = []
|
|
446
|
+
program.dockerVolumes && program.dockerVolumes.split(' ').forEach((volume) => {
|
|
447
|
+
dockerVolumesOptions = dockerVolumesOptions.concat(['-v', volume])
|
|
448
|
+
})
|
|
449
|
+
const dockerCommand = [program.dockerImage, packageManager].concat(installOptions)
|
|
450
|
+
const dockerBaseOptions = [
|
|
451
|
+
'run', '--rm',
|
|
452
|
+
'-v', `${fs.realpathSync(codeDirectory)}:/var/task`,
|
|
453
|
+
'-w', '/var/task'
|
|
454
|
+
]
|
|
455
|
+
const dockerOptions = dockerBaseOptions.concat(dockerVolumesOptions).concat(dockerCommand)
|
|
456
|
+
if (process.platform === 'win32') {
|
|
427
457
|
return {
|
|
428
|
-
command: '
|
|
429
|
-
options: dockerOptions
|
|
458
|
+
command: 'cmd.exe',
|
|
459
|
+
options: ['/c', 'docker'].concat(dockerOptions)
|
|
430
460
|
}
|
|
431
461
|
}
|
|
462
|
+
return {
|
|
463
|
+
command: 'docker',
|
|
464
|
+
options: dockerOptions
|
|
465
|
+
}
|
|
466
|
+
})()
|
|
432
467
|
|
|
433
|
-
|
|
468
|
+
const paramsOnHost = (() => {
|
|
469
|
+
// simple install
|
|
434
470
|
if (process.platform === 'win32') {
|
|
435
471
|
return {
|
|
436
472
|
command: 'cmd.exe',
|
|
437
|
-
options: ['/c',
|
|
438
|
-
.concat(npmInstallBaseOptions)
|
|
439
|
-
.concat(['--cwd', codeDirectory])
|
|
473
|
+
options: ['/c', packageManager].concat(installOptions)
|
|
440
474
|
}
|
|
441
475
|
}
|
|
442
476
|
return {
|
|
443
|
-
command:
|
|
444
|
-
options:
|
|
477
|
+
command: packageManager,
|
|
478
|
+
options: installOptions
|
|
445
479
|
}
|
|
446
480
|
})()
|
|
447
481
|
|
|
482
|
+
const params = program.dockerImage ? paramsOnContainer : paramsOnHost
|
|
448
483
|
return new Promise((resolve, reject) => {
|
|
449
484
|
execFile(params.command, params.options, {
|
|
450
485
|
maxBuffer: maxBufferSize,
|
|
451
486
|
env: process.env
|
|
452
487
|
}, (err) => {
|
|
453
488
|
if (err) return reject(err)
|
|
454
|
-
resolve()
|
|
489
|
+
resolve(packageManager)
|
|
455
490
|
})
|
|
456
491
|
})
|
|
457
492
|
}
|
|
@@ -519,7 +554,7 @@ Emulate only the body of the API Gateway event.
|
|
|
519
554
|
|
|
520
555
|
_codeDirectory () {
|
|
521
556
|
// Why realpathSync?:
|
|
522
|
-
// If tmpdir is symbolic link and npm>=7, `this.
|
|
557
|
+
// If tmpdir is symbolic link and npm>=7, `this._packageInstall()` may not work properly.
|
|
523
558
|
return path.join(fs.realpathSync(os.tmpdir()), `${path.basename(path.resolve('.'))}-lambda`)
|
|
524
559
|
}
|
|
525
560
|
|
|
@@ -531,28 +566,27 @@ Emulate only the body of the API Gateway event.
|
|
|
531
566
|
resolve()
|
|
532
567
|
})
|
|
533
568
|
})
|
|
534
|
-
}
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
569
|
+
}
|
|
570
|
+
return new Promise((resolve, reject) => {
|
|
571
|
+
fs.readdir(codeDirectory, (err, files) => {
|
|
572
|
+
if (err) return reject(err)
|
|
538
573
|
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
574
|
+
Promise.all(files.map(file => {
|
|
575
|
+
return new Promise((resolve, reject) => {
|
|
576
|
+
if (keepNodeModules && file === 'node_modules') {
|
|
577
|
+
resolve()
|
|
578
|
+
} else {
|
|
579
|
+
fs.remove(path.join(codeDirectory, file), err => {
|
|
580
|
+
if (err) return reject(err)
|
|
542
581
|
resolve()
|
|
543
|
-
}
|
|
544
|
-
|
|
545
|
-
if (err) return reject(err)
|
|
546
|
-
resolve()
|
|
547
|
-
})
|
|
548
|
-
}
|
|
549
|
-
})
|
|
550
|
-
})).then(() => {
|
|
551
|
-
resolve()
|
|
582
|
+
})
|
|
583
|
+
}
|
|
552
584
|
})
|
|
585
|
+
})).then(() => {
|
|
586
|
+
resolve()
|
|
553
587
|
})
|
|
554
588
|
})
|
|
555
|
-
}
|
|
589
|
+
})
|
|
556
590
|
}
|
|
557
591
|
|
|
558
592
|
_setRunTimeEnvironmentVars (program) {
|
|
@@ -568,7 +602,7 @@ Emulate only the body of the API Gateway event.
|
|
|
568
602
|
}
|
|
569
603
|
}
|
|
570
604
|
|
|
571
|
-
_uploadExisting (lambda, params) {
|
|
605
|
+
async _uploadExisting (lambda, params) {
|
|
572
606
|
const functionCodeParams = Object.assign({
|
|
573
607
|
FunctionName: params.FunctionName,
|
|
574
608
|
Publish: params.Publish
|
|
@@ -596,29 +630,30 @@ Emulate only the body of the API Gateway event.
|
|
|
596
630
|
delete functionConfigParams.Layers
|
|
597
631
|
}
|
|
598
632
|
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
const updateCodeRequest = lambda.updateFunctionCode(functionCodeParams, (err) => {
|
|
606
|
-
if (err) return reject(err)
|
|
607
|
-
resolve(configResponse)
|
|
608
|
-
})
|
|
633
|
+
const updateConfigRequest = lambda.updateFunctionConfiguration(functionConfigParams)
|
|
634
|
+
updateConfigRequest.on('retry', (response) => {
|
|
635
|
+
console.log(response.error.message)
|
|
636
|
+
console.log('=> Retrying')
|
|
637
|
+
})
|
|
638
|
+
const updateConfigResponse = await updateConfigRequest.promise()
|
|
609
639
|
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
640
|
+
// Wait for the `Configuration.LastUpdateStatus` to change from `InProgress` to `Successful`.
|
|
641
|
+
for (let i = 0; i < 10; i++) {
|
|
642
|
+
const data = await lambda.getFunction({ FunctionName: params.FunctionName }).promise()
|
|
643
|
+
if (data.Configuration.LastUpdateStatus === 'Successful') {
|
|
644
|
+
break
|
|
645
|
+
}
|
|
646
|
+
await new Promise((resolve) => setTimeout(resolve, 3000))
|
|
647
|
+
}
|
|
616
648
|
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
649
|
+
const updateCodeRequest = lambda.updateFunctionCode(functionCodeParams)
|
|
650
|
+
updateCodeRequest.on('retry', (response) => {
|
|
651
|
+
console.log(response.error.message)
|
|
652
|
+
console.log('=> Retrying')
|
|
621
653
|
})
|
|
654
|
+
await updateCodeRequest.promise()
|
|
655
|
+
|
|
656
|
+
return updateConfigResponse
|
|
622
657
|
}
|
|
623
658
|
|
|
624
659
|
_uploadNew (lambda, params) {
|
|
@@ -659,13 +694,17 @@ Emulate only the body of the API Gateway event.
|
|
|
659
694
|
_archivePrebuilt (program) {
|
|
660
695
|
const codeDirectory = this._codeDirectory()
|
|
661
696
|
|
|
662
|
-
return
|
|
663
|
-
|
|
664
|
-
|
|
697
|
+
return Promise.resolve().then(() => {
|
|
698
|
+
return this._cleanDirectory(codeDirectory, program.keepNodeModules)
|
|
699
|
+
}).then(() => {
|
|
700
|
+
return this._fileCopy(program, program.prebuiltDirectory, codeDirectory, false).then(() => {
|
|
701
|
+
console.log('=> Zipping deployment package')
|
|
702
|
+
return this._zip(program, codeDirectory)
|
|
703
|
+
})
|
|
665
704
|
})
|
|
666
705
|
}
|
|
667
706
|
|
|
668
|
-
_buildAndArchive (program) {
|
|
707
|
+
async _buildAndArchive (program) {
|
|
669
708
|
if (!fs.existsSync('.env')) {
|
|
670
709
|
console.warn('[Warning] `.env` file does not exist.')
|
|
671
710
|
console.info('Execute `node-lambda setup` as necessary and set it up.')
|
|
@@ -684,24 +723,17 @@ they may not work as expected in the Lambda environment.
|
|
|
684
723
|
const codeDirectory = this._codeDirectory()
|
|
685
724
|
const lambdaSrcDirectory = program.sourceDirectory ? program.sourceDirectory.replace(/\/$/, '') : '.'
|
|
686
725
|
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
}
|
|
699
|
-
}).then(() => {
|
|
700
|
-
return this._postInstallScript(program, codeDirectory)
|
|
701
|
-
}).then(() => {
|
|
702
|
-
console.log('=> Zipping deployment package')
|
|
703
|
-
return this._zip(program, codeDirectory)
|
|
704
|
-
})
|
|
726
|
+
await this._cleanDirectory(codeDirectory, program.keepNodeModules)
|
|
727
|
+
console.log('=> Moving files to temporary directory')
|
|
728
|
+
await this._fileCopy(program, lambdaSrcDirectory, codeDirectory, true)
|
|
729
|
+
if (!program.keepNodeModules) {
|
|
730
|
+
console.log('=> Running package install')
|
|
731
|
+
const usedPackageManager = await this._packageInstall(program, codeDirectory)
|
|
732
|
+
console.log(`(Package manager used was '${usedPackageManager}'.)`)
|
|
733
|
+
}
|
|
734
|
+
await this._postInstallScript(program, codeDirectory)
|
|
735
|
+
console.log('=> Zipping deployment package')
|
|
736
|
+
return this._zip(program, codeDirectory)
|
|
705
737
|
}
|
|
706
738
|
|
|
707
739
|
_listEventSourceMappings (lambda, params) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "node-lambda",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.21.0",
|
|
4
4
|
"description": "Command line tool for locally running and remotely deploying your node.js applications to Amazon Lambda.",
|
|
5
5
|
"main": "lib/main.js",
|
|
6
6
|
"directories": {
|
|
@@ -32,25 +32,25 @@
|
|
|
32
32
|
"author": "motdotla",
|
|
33
33
|
"license": "BSD-2-Clause",
|
|
34
34
|
"devDependencies": {
|
|
35
|
-
"aws-sdk-mock": "^5.1
|
|
36
|
-
"chai": "^4.
|
|
37
|
-
"mocha": "^
|
|
35
|
+
"aws-sdk-mock": "^5.2.1",
|
|
36
|
+
"chai": "^4.3.4",
|
|
37
|
+
"mocha": "^9.0.1",
|
|
38
38
|
"node-zip": "^1.1.1",
|
|
39
|
-
"standard": "^16.0.
|
|
39
|
+
"standard": "^16.0.3"
|
|
40
|
+
},
|
|
41
|
+
"engines": {
|
|
42
|
+
"node": ">= 10.0.0"
|
|
40
43
|
},
|
|
41
44
|
"dependencies": {
|
|
42
|
-
"archiver": "^5.
|
|
43
|
-
"aws-sdk": "^2.
|
|
44
|
-
"aws-xray-sdk-core": "^3.
|
|
45
|
-
"commander": "^
|
|
45
|
+
"archiver": "^5.3.0",
|
|
46
|
+
"aws-sdk": "^2.936.0",
|
|
47
|
+
"aws-xray-sdk-core": "^3.3.3",
|
|
48
|
+
"commander": "^8.2.0",
|
|
46
49
|
"continuation-local-storage": "^3.2.1",
|
|
47
|
-
"dotenv": "^
|
|
48
|
-
"fs-extra": "^
|
|
50
|
+
"dotenv": "^10.0.0",
|
|
51
|
+
"fs-extra": "^10.0.0",
|
|
49
52
|
"klaw": "^3.0.0",
|
|
50
53
|
"minimatch": "^3.0.4",
|
|
51
|
-
"proxy-agent": "^
|
|
52
|
-
},
|
|
53
|
-
"engines": {
|
|
54
|
-
"node": ">= 10.0.0"
|
|
54
|
+
"proxy-agent": "^5.0.0"
|
|
55
55
|
}
|
|
56
56
|
}
|
package/test/main.js
CHANGED
|
@@ -10,6 +10,7 @@ const awsMock = require('aws-sdk-mock')
|
|
|
10
10
|
awsMock.setSDK(path.resolve('node_modules/aws-sdk'))
|
|
11
11
|
|
|
12
12
|
const originalProgram = {
|
|
13
|
+
packageManager: 'npm',
|
|
13
14
|
environment: 'development',
|
|
14
15
|
accessKey: 'key',
|
|
15
16
|
secretKey: 'secret',
|
|
@@ -31,17 +32,18 @@ const originalProgram = {
|
|
|
31
32
|
contextFile: 'context.json',
|
|
32
33
|
deployTimeout: 120000,
|
|
33
34
|
prebuiltDirectory: '',
|
|
34
|
-
proxy: ''
|
|
35
|
+
proxy: '',
|
|
36
|
+
optionalDependencies: true
|
|
35
37
|
}
|
|
36
38
|
|
|
37
39
|
let program = {}
|
|
38
40
|
let codeDirectory = lambda._codeDirectory()
|
|
39
41
|
|
|
40
42
|
const _timeout = function (params) {
|
|
41
|
-
// Even if timeout is set for the whole test for Windows,
|
|
43
|
+
// Even if timeout is set for the whole test for Windows and Mac,
|
|
42
44
|
// if it is set in local it will be valid.
|
|
43
|
-
// For Windows, do not set it with local.
|
|
44
|
-
if (process.platform
|
|
45
|
+
// For Windows and Mac, do not set it with local.
|
|
46
|
+
if (!['win32', 'darwin'].includes(process.platform)) {
|
|
45
47
|
params.this.timeout(params.sec * 1000)
|
|
46
48
|
}
|
|
47
49
|
}
|
|
@@ -51,7 +53,7 @@ const lambdaMockSettings = {
|
|
|
51
53
|
addPermission: {},
|
|
52
54
|
getFunction: {
|
|
53
55
|
Code: {},
|
|
54
|
-
Configuration: {},
|
|
56
|
+
Configuration: { LastUpdateStatus: 'Successful' },
|
|
55
57
|
FunctionArn: 'Lambda.getFunction.mock.FunctionArn'
|
|
56
58
|
},
|
|
57
59
|
createFunction: {
|
|
@@ -129,8 +131,8 @@ const _awsRestore = () => {
|
|
|
129
131
|
|
|
130
132
|
/* global before, after, beforeEach, afterEach, describe, it */
|
|
131
133
|
describe('lib/main', function () {
|
|
132
|
-
if (process.platform
|
|
133
|
-
// It seems that it takes time for file operation in Windows.
|
|
134
|
+
if (['win32', 'darwin'].includes(process.platform)) {
|
|
135
|
+
// It seems that it takes time for file operation in Windows and Mac.
|
|
134
136
|
// So set `timeout(60000)` for the whole test.
|
|
135
137
|
this.timeout(60000)
|
|
136
138
|
}
|
|
@@ -148,7 +150,7 @@ describe('lib/main', function () {
|
|
|
148
150
|
})
|
|
149
151
|
|
|
150
152
|
it('version should be set', () => {
|
|
151
|
-
assert.equal(lambda.version, '0.
|
|
153
|
+
assert.equal(lambda.version, '0.21.0')
|
|
152
154
|
})
|
|
153
155
|
|
|
154
156
|
describe('_codeDirectory', () => {
|
|
@@ -589,65 +591,251 @@ describe('lib/main', function () {
|
|
|
589
591
|
})
|
|
590
592
|
})
|
|
591
593
|
|
|
592
|
-
describe('
|
|
593
|
-
|
|
594
|
+
describe('_getNpmInstallCommand', () => {
|
|
595
|
+
describe('when package-lock.json exists', () => {
|
|
596
|
+
const codeDirectory = '.'
|
|
597
|
+
|
|
598
|
+
it('npm ci', () => {
|
|
599
|
+
const { packageManager, installOptions } = lambda._getNpmInstallCommand(program, codeDirectory)
|
|
600
|
+
assert.equal(packageManager, 'npm')
|
|
601
|
+
assert.deepEqual(installOptions, ['-s', 'ci', '--production', '--no-audit', '--prefix', codeDirectory])
|
|
602
|
+
})
|
|
603
|
+
|
|
604
|
+
it('npm ci with "--no-optional"', () => {
|
|
605
|
+
const { packageManager, installOptions } = lambda._getNpmInstallCommand(
|
|
606
|
+
{
|
|
607
|
+
...program,
|
|
608
|
+
optionalDependencies: false
|
|
609
|
+
},
|
|
610
|
+
codeDirectory
|
|
611
|
+
)
|
|
612
|
+
assert.equal(packageManager, 'npm')
|
|
613
|
+
assert.deepEqual(
|
|
614
|
+
installOptions,
|
|
615
|
+
['-s', 'ci', '--production', '--no-audit', '--no-optional', '--prefix', codeDirectory]
|
|
616
|
+
)
|
|
617
|
+
})
|
|
618
|
+
|
|
619
|
+
it('npm ci on docker', () => {
|
|
620
|
+
const { packageManager, installOptions } = lambda._getNpmInstallCommand(
|
|
621
|
+
{
|
|
622
|
+
...program,
|
|
623
|
+
dockerImage: 'test'
|
|
624
|
+
},
|
|
625
|
+
codeDirectory
|
|
626
|
+
)
|
|
627
|
+
assert.equal(packageManager, 'npm')
|
|
628
|
+
assert.deepEqual(installOptions, ['-s', 'ci', '--production', '--no-audit'])
|
|
629
|
+
})
|
|
630
|
+
})
|
|
631
|
+
|
|
632
|
+
describe('when package-lock.json does not exist', () => {
|
|
633
|
+
const codeDirectory = './test'
|
|
634
|
+
|
|
635
|
+
it('npm install', () => {
|
|
636
|
+
const { packageManager, installOptions } = lambda._getNpmInstallCommand(program, './test')
|
|
637
|
+
assert.equal(packageManager, 'npm')
|
|
638
|
+
assert.deepEqual(installOptions, ['-s', 'install', '--production', '--no-audit', '--prefix', './test'])
|
|
639
|
+
})
|
|
640
|
+
|
|
641
|
+
it('npm install with "--no-optional"', () => {
|
|
642
|
+
const { packageManager, installOptions } = lambda._getNpmInstallCommand(
|
|
643
|
+
{
|
|
644
|
+
...program,
|
|
645
|
+
optionalDependencies: false
|
|
646
|
+
},
|
|
647
|
+
codeDirectory
|
|
648
|
+
)
|
|
649
|
+
assert.equal(packageManager, 'npm')
|
|
650
|
+
assert.deepEqual(
|
|
651
|
+
installOptions,
|
|
652
|
+
['-s', 'install', '--production', '--no-audit', '--no-optional', '--prefix', codeDirectory]
|
|
653
|
+
)
|
|
654
|
+
})
|
|
655
|
+
|
|
656
|
+
it('npm install on docker', () => {
|
|
657
|
+
const { packageManager, installOptions } = lambda._getNpmInstallCommand(
|
|
658
|
+
{
|
|
659
|
+
...program,
|
|
660
|
+
dockerImage: 'test'
|
|
661
|
+
},
|
|
662
|
+
codeDirectory
|
|
663
|
+
)
|
|
664
|
+
assert.equal(packageManager, 'npm')
|
|
665
|
+
assert.deepEqual(installOptions, ['-s', 'install', '--production', '--no-audit'])
|
|
666
|
+
})
|
|
667
|
+
})
|
|
668
|
+
})
|
|
669
|
+
|
|
670
|
+
describe('_getYarnInstallCommand', () => {
|
|
671
|
+
const codeDirectory = '.'
|
|
672
|
+
|
|
673
|
+
it('yarn install', () => {
|
|
674
|
+
const { packageManager, installOptions } = lambda._getYarnInstallCommand(program, codeDirectory)
|
|
675
|
+
assert.equal(packageManager, 'yarn')
|
|
676
|
+
assert.deepEqual(installOptions, ['-s', 'install', '--production', '--cwd', codeDirectory])
|
|
677
|
+
})
|
|
678
|
+
|
|
679
|
+
it('yarn install with "--no-optional"', () => {
|
|
680
|
+
const { packageManager, installOptions } = lambda._getYarnInstallCommand(
|
|
681
|
+
{
|
|
682
|
+
...program,
|
|
683
|
+
optionalDependencies: false
|
|
684
|
+
},
|
|
685
|
+
codeDirectory
|
|
686
|
+
)
|
|
687
|
+
assert.equal(packageManager, 'yarn')
|
|
688
|
+
assert.deepEqual(
|
|
689
|
+
installOptions,
|
|
690
|
+
['-s', 'install', '--production', '--ignore-optional', '--cwd', codeDirectory]
|
|
691
|
+
)
|
|
692
|
+
})
|
|
693
|
+
|
|
694
|
+
it('yarn install on docker', () => {
|
|
695
|
+
const { packageManager, installOptions } = lambda._getYarnInstallCommand(
|
|
696
|
+
{
|
|
697
|
+
...program,
|
|
698
|
+
dockerImage: 'test'
|
|
699
|
+
},
|
|
700
|
+
codeDirectory
|
|
701
|
+
)
|
|
702
|
+
assert.equal(packageManager, 'yarn')
|
|
703
|
+
assert.deepEqual(installOptions, ['-s', 'install', '--production'])
|
|
704
|
+
})
|
|
705
|
+
})
|
|
706
|
+
|
|
707
|
+
describe('_packageInstall', function () {
|
|
708
|
+
_timeout({ this: this, sec: 60 }) // ci should be faster than install
|
|
594
709
|
|
|
595
710
|
// npm treats files as packages when installing, and so removes them.
|
|
596
711
|
// Test with `devDependencies` packages that are not installed with the `--production` option.
|
|
597
712
|
const nodeModulesMocha = path.join(codeDirectory, 'node_modules', 'mocha')
|
|
598
713
|
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
714
|
+
const testCleanAndInstall = async (packageManager) => {
|
|
715
|
+
const beforeAwsSdkStat = fs.statSync(path.join(codeDirectory, 'node_modules', 'aws-sdk'))
|
|
716
|
+
|
|
717
|
+
const usedPackageManager = await lambda._packageInstall(
|
|
718
|
+
{
|
|
719
|
+
...program,
|
|
720
|
+
packageManager
|
|
721
|
+
},
|
|
722
|
+
codeDirectory
|
|
723
|
+
)
|
|
724
|
+
assert.equal(usedPackageManager, packageManager)
|
|
725
|
+
|
|
726
|
+
const contents = fs.readdirSync(path.join(codeDirectory, 'node_modules'))
|
|
727
|
+
assert.include(contents, 'dotenv')
|
|
728
|
+
|
|
729
|
+
// To remove and then install.
|
|
730
|
+
// beforeAwsSdkStat.ctimeMs < afterAwsSdkStat.ctimeMs
|
|
731
|
+
const afterAwsSdkStat = fs.statSync(path.join(codeDirectory, 'node_modules', 'aws-sdk'))
|
|
732
|
+
assert.isBelow(beforeAwsSdkStat.ctimeMs, afterAwsSdkStat.ctimeMs)
|
|
733
|
+
|
|
734
|
+
// Not installed with the `--production` option.
|
|
735
|
+
assert.isFalse(fs.existsSync(nodeModulesMocha))
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
const beforeEachOptionalDependencies = () => {
|
|
739
|
+
const packageJsonPath = path.join(codeDirectory, 'package.json')
|
|
740
|
+
const packageJson = require(packageJsonPath)
|
|
741
|
+
packageJson.optionalDependencies = { npm: '*' }
|
|
742
|
+
fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson))
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
const testOptionalDependenciesIsInstalled = async (packageManager) => {
|
|
746
|
+
const usedPackageManager = await lambda._packageInstall(
|
|
747
|
+
{
|
|
748
|
+
...program,
|
|
749
|
+
packageManager
|
|
750
|
+
},
|
|
751
|
+
codeDirectory
|
|
752
|
+
)
|
|
753
|
+
assert.equal(usedPackageManager, packageManager)
|
|
754
|
+
|
|
755
|
+
const contents = fs.readdirSync(path.join(codeDirectory, 'node_modules'))
|
|
756
|
+
assert.include(contents, 'npm')
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
const testOptionalDependenciesIsNotInstalled = async (packageManager) => {
|
|
760
|
+
const params = {
|
|
761
|
+
...program,
|
|
762
|
+
packageManager,
|
|
763
|
+
optionalDependencies: false
|
|
764
|
+
}
|
|
765
|
+
const usedPackageManager = await lambda._packageInstall(params, codeDirectory)
|
|
766
|
+
assert.equal(usedPackageManager, packageManager)
|
|
767
|
+
|
|
768
|
+
const contents = fs.readdirSync(path.join(codeDirectory, 'node_modules'))
|
|
769
|
+
assert.notInclude(contents, 'npm')
|
|
770
|
+
}
|
|
771
|
+
|
|
772
|
+
beforeEach(async () => {
|
|
773
|
+
await lambda._cleanDirectory(codeDirectory)
|
|
774
|
+
await lambda._fileCopy(program, '.', codeDirectory, false)
|
|
607
775
|
})
|
|
608
776
|
|
|
609
|
-
describe('
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
777
|
+
describe('Use npm', () => {
|
|
778
|
+
describe('when package-lock.json does exist', () => {
|
|
779
|
+
it('should use "npm ci"', () => testCleanAndInstall('npm'))
|
|
780
|
+
})
|
|
781
|
+
|
|
782
|
+
describe('when package-lock.json does not exist', () => {
|
|
783
|
+
beforeEach(() => {
|
|
784
|
+
return fs.removeSync(path.join(codeDirectory, 'package-lock.json'))
|
|
785
|
+
})
|
|
786
|
+
|
|
787
|
+
it('should use "npm install"', () => {
|
|
788
|
+
const beforeAwsSdkStat = fs.statSync(path.join(codeDirectory, 'node_modules', 'aws-sdk'))
|
|
789
|
+
return lambda._packageInstall(program, codeDirectory).then((usedPackageManager) => {
|
|
790
|
+
assert.equal(usedPackageManager, 'npm')
|
|
615
791
|
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
const afterAwsSdkStat = fs.statSync(path.join(codeDirectory, 'node_modules', 'aws-sdk'))
|
|
619
|
-
assert.isBelow(beforeAwsSdkStat.ctimeMs, afterAwsSdkStat.ctimeMs)
|
|
792
|
+
const contents = fs.readdirSync(path.join(codeDirectory, 'node_modules'))
|
|
793
|
+
assert.include(contents, 'dotenv')
|
|
620
794
|
|
|
621
|
-
|
|
622
|
-
|
|
795
|
+
// Installed packages will remain intact.
|
|
796
|
+
// beforeAwsSdkStat.ctimeMs === afterAwsSdkStat.ctimeMs
|
|
797
|
+
const afterAwsSdkStat = fs.statSync(path.join(codeDirectory, 'node_modules', 'aws-sdk'))
|
|
798
|
+
assert.equal(beforeAwsSdkStat.ctimeMs, afterAwsSdkStat.ctimeMs)
|
|
799
|
+
|
|
800
|
+
// Not installed with the `--production` option.
|
|
801
|
+
assert.isFalse(fs.existsSync(nodeModulesMocha))
|
|
802
|
+
})
|
|
623
803
|
})
|
|
624
804
|
})
|
|
625
|
-
})
|
|
626
805
|
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
806
|
+
describe('optionalDependencies', () => {
|
|
807
|
+
beforeEach(beforeEachOptionalDependencies)
|
|
808
|
+
|
|
809
|
+
describe('No `--no-optionalDependencies`', () => {
|
|
810
|
+
it('optionalDependencies is installed', () => testOptionalDependenciesIsInstalled('npm'))
|
|
811
|
+
})
|
|
812
|
+
|
|
813
|
+
describe('With `--no-optionalDependencies`', () => {
|
|
814
|
+
it('optionalDependency is NOT installed', () => testOptionalDependenciesIsNotInstalled('npm'))
|
|
815
|
+
})
|
|
630
816
|
})
|
|
817
|
+
})
|
|
631
818
|
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
return lambda._npmInstall(program, codeDirectory).then(() => {
|
|
635
|
-
const contents = fs.readdirSync(path.join(codeDirectory, 'node_modules'))
|
|
636
|
-
assert.include(contents, 'dotenv')
|
|
819
|
+
describe('Use yarn', () => {
|
|
820
|
+
it('should use "yarn install"', () => testCleanAndInstall('yarn'))
|
|
637
821
|
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
822
|
+
describe('optionalDependencies', () => {
|
|
823
|
+
beforeEach(beforeEachOptionalDependencies)
|
|
824
|
+
|
|
825
|
+
describe('No `--ignore-optionalDependencies`', () => {
|
|
826
|
+
it('optionalDependencies is installed', () => testOptionalDependenciesIsInstalled('yarn'))
|
|
827
|
+
})
|
|
642
828
|
|
|
643
|
-
|
|
644
|
-
|
|
829
|
+
describe('With `--ignore-optionalDependencies`', () => {
|
|
830
|
+
it('optionalDependency is NOT installed', () => testOptionalDependenciesIsNotInstalled('yarn'))
|
|
645
831
|
})
|
|
646
832
|
})
|
|
647
833
|
})
|
|
648
834
|
})
|
|
649
835
|
|
|
650
|
-
describe('
|
|
836
|
+
describe('_packageInstall (When codeDirectory contains characters to be escaped)', function () {
|
|
837
|
+
_timeout({ this: this, sec: 30 }) // give it time to build the node modules
|
|
838
|
+
|
|
651
839
|
beforeEach(() => {
|
|
652
840
|
// Since '\' can not be included in the file or directory name in Windows
|
|
653
841
|
const directoryName = process.platform === 'win32'
|
|
@@ -664,14 +852,21 @@ describe('lib/main', function () {
|
|
|
664
852
|
codeDirectory = lambda._codeDirectory()
|
|
665
853
|
})
|
|
666
854
|
|
|
667
|
-
|
|
668
|
-
|
|
855
|
+
const testFunc = async (packageManager) => {
|
|
856
|
+
const usedPackageManager = await lambda._packageInstall(
|
|
857
|
+
{
|
|
858
|
+
...program,
|
|
859
|
+
packageManager
|
|
860
|
+
},
|
|
861
|
+
codeDirectory
|
|
862
|
+
)
|
|
863
|
+
assert.equal(usedPackageManager, packageManager)
|
|
864
|
+
const contents = fs.readdirSync(codeDirectory)
|
|
865
|
+
assert.include(contents, 'node_modules')
|
|
866
|
+
}
|
|
669
867
|
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
assert.include(contents, 'node_modules')
|
|
673
|
-
})
|
|
674
|
-
})
|
|
868
|
+
it('npm adds node_modules', () => testFunc('npm'))
|
|
869
|
+
it('yarn adds node_modules', () => testFunc('yarn'))
|
|
675
870
|
})
|
|
676
871
|
|
|
677
872
|
describe('_postInstallScript', () => {
|
|
@@ -741,53 +936,70 @@ describe('lib/main', function () {
|
|
|
741
936
|
})
|
|
742
937
|
})
|
|
743
938
|
|
|
744
|
-
describe('_zip', ()
|
|
745
|
-
|
|
746
|
-
_timeout({ this: this, sec: 30 }) // give it time to build the node modules
|
|
747
|
-
return Promise.resolve().then(() => {
|
|
748
|
-
return lambda._cleanDirectory(codeDirectory)
|
|
749
|
-
}).then(() => {
|
|
750
|
-
return lambda._fileCopy(program, '.', codeDirectory, true)
|
|
751
|
-
}).then(() => {
|
|
752
|
-
return lambda._npmInstall(program, codeDirectory)
|
|
753
|
-
}).then(() => {
|
|
754
|
-
if (process.platform !== 'win32') {
|
|
755
|
-
fs.symlinkSync(
|
|
756
|
-
path.join(__dirname, '..', 'bin', 'node-lambda'),
|
|
757
|
-
path.join(codeDirectory, 'node-lambda-link')
|
|
758
|
-
)
|
|
759
|
-
}
|
|
760
|
-
})
|
|
761
|
-
})
|
|
939
|
+
describe('_zip', function () {
|
|
940
|
+
_timeout({ this: this, sec: 60 }) // give it time to zip
|
|
762
941
|
|
|
763
|
-
|
|
764
|
-
|
|
942
|
+
const beforeTask = async (packageManager) => {
|
|
943
|
+
await lambda._cleanDirectory(codeDirectory)
|
|
944
|
+
await lambda._fileCopy(program, '.', codeDirectory, true)
|
|
945
|
+
const usedPackageManager = await lambda._packageInstall(
|
|
946
|
+
{
|
|
947
|
+
...program,
|
|
948
|
+
packageManager
|
|
949
|
+
},
|
|
950
|
+
codeDirectory
|
|
951
|
+
)
|
|
952
|
+
assert.equal(usedPackageManager, packageManager)
|
|
953
|
+
if (process.platform !== 'win32') {
|
|
954
|
+
fs.symlinkSync(
|
|
955
|
+
path.join(__dirname, '..', 'bin', 'node-lambda'),
|
|
956
|
+
path.join(codeDirectory, 'node-lambda-link')
|
|
957
|
+
)
|
|
958
|
+
}
|
|
959
|
+
}
|
|
765
960
|
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
961
|
+
const testFunc = async (packageManager) => {
|
|
962
|
+
// setup
|
|
963
|
+
await beforeTask(packageManager)
|
|
964
|
+
|
|
965
|
+
// tests
|
|
966
|
+
const data = await lambda._zip(program, codeDirectory)
|
|
967
|
+
const archive = new Zip(data)
|
|
968
|
+
assert.include(archive.files['index.js'].name, 'index.js')
|
|
969
|
+
assert.include(archive.files['bin/node-lambda'].name, 'bin/node-lambda')
|
|
970
|
+
|
|
971
|
+
if (process.platform !== 'win32') {
|
|
972
|
+
const indexJsStat = fs.lstatSync('index.js')
|
|
973
|
+
const binNodeLambdaStat = fs.lstatSync(path.join('bin', 'node-lambda'))
|
|
974
|
+
assert.equal(
|
|
975
|
+
archive.files['index.js'].unixPermissions,
|
|
976
|
+
indexJsStat.mode
|
|
977
|
+
)
|
|
978
|
+
assert.equal(
|
|
979
|
+
archive.files['bin/node-lambda'].unixPermissions,
|
|
980
|
+
binNodeLambdaStat.mode
|
|
981
|
+
)
|
|
982
|
+
|
|
983
|
+
// isSymbolicLink
|
|
984
|
+
assert.include(archive.files['node-lambda-link'].name, 'node-lambda-link')
|
|
985
|
+
assert.equal(
|
|
986
|
+
archive.files['node-lambda-link'].unixPermissions & fs.constants.S_IFMT,
|
|
987
|
+
fs.constants.S_IFLNK
|
|
988
|
+
)
|
|
989
|
+
}
|
|
990
|
+
}
|
|
991
|
+
|
|
992
|
+
describe('Use npm', () => {
|
|
993
|
+
it(
|
|
994
|
+
'Compress the file. `index.js` and `bin/node-lambda` are included and the permission is also preserved.',
|
|
995
|
+
() => testFunc('npm')
|
|
996
|
+
)
|
|
997
|
+
})
|
|
998
|
+
describe('Use yarn', () => {
|
|
999
|
+
it(
|
|
1000
|
+
'Compress the file. `index.js` and `bin/node-lambda` are included and the permission is also preserved.',
|
|
1001
|
+
() => testFunc('yarn')
|
|
1002
|
+
)
|
|
791
1003
|
})
|
|
792
1004
|
})
|
|
793
1005
|
|
|
@@ -833,6 +1045,24 @@ describe('lib/main', function () {
|
|
|
833
1045
|
})
|
|
834
1046
|
})
|
|
835
1047
|
})
|
|
1048
|
+
|
|
1049
|
+
it('cleans the temporary directory before running `_archivePrebuilt`', function () {
|
|
1050
|
+
_timeout({ this: this, sec: 30 }) // give it time to zip
|
|
1051
|
+
const buildDir = '.build_' + Date.now()
|
|
1052
|
+
const codeDir = lambda._codeDirectory()
|
|
1053
|
+
const tmpFile = path.join(codeDir, 'deleteme')
|
|
1054
|
+
after(() => fs.removeSync(buildDir))
|
|
1055
|
+
|
|
1056
|
+
fs.mkdirSync(codeDir, { recursive: true })
|
|
1057
|
+
fs.writeFileSync(tmpFile, '...')
|
|
1058
|
+
fs.mkdirSync(buildDir)
|
|
1059
|
+
fs.writeFileSync(path.join(buildDir, 'test'), '...')
|
|
1060
|
+
|
|
1061
|
+
program.prebuiltDirectory = buildDir
|
|
1062
|
+
return lambda._archive(program).then((_data) => {
|
|
1063
|
+
assert.isNotTrue(fs.existsSync(tmpFile))
|
|
1064
|
+
})
|
|
1065
|
+
})
|
|
836
1066
|
})
|
|
837
1067
|
|
|
838
1068
|
describe('_readArchive', () => {
|