node-lambda 0.20.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 +1 -1
- package/CHANGELOG.md +4 -0
- package/README.md +68 -68
- package/bin/node-lambda +3 -0
- package/lib/main.js +57 -20
- package/package.json +1 -1
- package/test/main.js +293 -108
package/CHANGELOG.md
CHANGED
|
@@ -440,3 +440,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
|
|
|
440
440
|
- fix(_uploadExisting): fix function update errors [#575](https://github.com/motdotla/node-lambda/pull/575)
|
|
441
441
|
- test: fix npm install test failing in some cases [#569](https://github.com/motdotla/node-lambda/pull/569)
|
|
442
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,24 +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
|
-
-
|
|
154
|
-
|
|
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
|
|
155
156
|
```
|
|
156
157
|
|
|
157
158
|
#### deploy
|
|
@@ -160,51 +161,50 @@ Bundles and deploys your application up to Amazon Lambda.
|
|
|
160
161
|
|
|
161
162
|
```
|
|
162
163
|
$ node-lambda deploy --help
|
|
163
|
-
|
|
164
|
-
Usage: deploy [options]
|
|
164
|
+
Usage: node-lambda deploy [options]
|
|
165
165
|
|
|
166
166
|
Deploy your application to Amazon Lambda
|
|
167
167
|
|
|
168
|
-
|
|
169
168
|
Options:
|
|
170
|
-
|
|
171
|
-
-e, --environment [
|
|
172
|
-
-E, --endpoint [AWS_ENDPOINT]
|
|
173
|
-
-a, --accessKey [
|
|
174
|
-
-s, --secretKey [
|
|
175
|
-
-P, --profile []
|
|
176
|
-
-k, --sessionToken []
|
|
177
|
-
-r, --region [us-east-1
|
|
178
|
-
-n, --functionName [
|
|
179
|
-
-H, --handler [
|
|
180
|
-
-o, --role [
|
|
181
|
-
-m, --memorySize [
|
|
182
|
-
-t, --timeout [
|
|
183
|
-
-d, --description [
|
|
184
|
-
-u, --runtime [
|
|
185
|
-
-p, --publish [
|
|
186
|
-
-L, --lambdaVersion []
|
|
187
|
-
-b, --vpcSubnets []
|
|
188
|
-
-g, --vpcSecurityGroups []
|
|
189
|
-
-K, --kmsKeyArn []
|
|
190
|
-
-Q, --deadLetterConfigTargetArn [] Lambda DLQ resource
|
|
191
|
-
-c, --tracingConfig [] Lambda tracing settings
|
|
192
|
-
-l, --layers []
|
|
193
|
-
-R, --retentionInDays []
|
|
194
|
-
-G, --sourceDirectory []
|
|
195
|
-
-I, --dockerImage []
|
|
196
|
-
-f, --configFile []
|
|
197
|
-
-S, --eventSourceFile []
|
|
198
|
-
-x, --excludeGlobs [
|
|
199
|
-
-D, --prebuiltDirectory [] Prebuilt directory
|
|
200
|
-
-T, --deployTimeout [
|
|
201
|
-
-z, --deployZipfile []
|
|
202
|
-
-B, --deployUseS3 []
|
|
203
|
-
-i, --imageUri []
|
|
204
|
-
-y, --proxy []
|
|
205
|
-
-A, --tags []
|
|
206
|
-
--silent
|
|
207
|
-
--no-optionalDependencies
|
|
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
|
|
208
208
|
```
|
|
209
209
|
|
|
210
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:
|
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 || ''
|
|
@@ -66,6 +67,7 @@ program.showSuggestionAfterError()
|
|
|
66
67
|
program
|
|
67
68
|
.command('deploy')
|
|
68
69
|
.description('Deploy your application to Amazon Lambda')
|
|
70
|
+
.option('--packageManager [PACKAGE_MANAGER]', 'Package manager used to install dependencies', PACKAGE_MANAGER)
|
|
69
71
|
.option('-e, --environment [AWS_ENVIRONMENT]', 'Choose environment {dev, staging, production}',
|
|
70
72
|
AWS_ENVIRONMENT)
|
|
71
73
|
.option('-E, --endpoint [AWS_ENDPOINT]', 'Choose endpoint (e.g. localstack, "http://127.0.0.1:4574")',
|
|
@@ -123,6 +125,7 @@ program
|
|
|
123
125
|
.command('package')
|
|
124
126
|
.alias('zip')
|
|
125
127
|
.description('Create zipped package for Amazon Lambda deployment')
|
|
128
|
+
.option('--packageManager [PACKAGE_MANAGER]', 'Package manager used to install dependencies', PACKAGE_MANAGER)
|
|
126
129
|
.option('-A, --packageDirectory [PACKAGE_DIRECTORY]', 'Local Package Directory', PACKAGE_DIRECTORY)
|
|
127
130
|
.option('-I, --dockerImage [DOCKER_IMAGE]', 'Docker image for npm ci', DOCKER_IMAGE)
|
|
128
131
|
.option('-n, --functionName [AWS_FUNCTION_NAME]', 'Lambda FunctionName', AWS_FUNCTION_NAME)
|
package/lib/main.js
CHANGED
|
@@ -385,31 +385,68 @@ 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
|
-
|
|
390
|
-
// https://nodejs.org/api/child_process.html#child_process_spawning_bat_and_cmd_files_on_windows
|
|
391
|
-
|
|
392
|
-
const installCommand = this._shouldUseNpmCi(codeDirectory)
|
|
393
|
-
? 'ci'
|
|
394
|
-
: 'install'
|
|
395
|
-
const npmInstallBaseOptions = [
|
|
388
|
+
_getNpmInstallCommand (program, codeDirectory) {
|
|
389
|
+
const installOptions = [
|
|
396
390
|
'-s',
|
|
397
|
-
|
|
391
|
+
this._shouldUseNpmCi(codeDirectory) ? 'ci' : 'install',
|
|
398
392
|
'--production',
|
|
399
393
|
'--no-audit'
|
|
400
394
|
]
|
|
401
395
|
|
|
402
396
|
if (program.optionalDependencies === false) {
|
|
403
|
-
|
|
397
|
+
installOptions.push('--no-optional')
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
if (!program.dockerImage) {
|
|
401
|
+
installOptions.push('--prefix', codeDirectory)
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
return {
|
|
405
|
+
packageManager: 'npm',
|
|
406
|
+
installOptions
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
_getYarnInstallCommand (program, codeDirectory) {
|
|
411
|
+
const installOptions = [
|
|
412
|
+
'-s',
|
|
413
|
+
'install',
|
|
414
|
+
'--production'
|
|
415
|
+
]
|
|
416
|
+
|
|
417
|
+
if (program.optionalDependencies === false) {
|
|
418
|
+
installOptions.push('--ignore-optional')
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
if (!program.dockerImage) {
|
|
422
|
+
installOptions.push('--cwd', codeDirectory)
|
|
404
423
|
}
|
|
405
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
|
|
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
|
+
|
|
406
443
|
const paramsOnContainer = (() => {
|
|
407
444
|
// with docker
|
|
408
445
|
let dockerVolumesOptions = []
|
|
409
446
|
program.dockerVolumes && program.dockerVolumes.split(' ').forEach((volume) => {
|
|
410
447
|
dockerVolumesOptions = dockerVolumesOptions.concat(['-v', volume])
|
|
411
448
|
})
|
|
412
|
-
const dockerCommand = [program.dockerImage,
|
|
449
|
+
const dockerCommand = [program.dockerImage, packageManager].concat(installOptions)
|
|
413
450
|
const dockerBaseOptions = [
|
|
414
451
|
'run', '--rm',
|
|
415
452
|
'-v', `${fs.realpathSync(codeDirectory)}:/var/task`,
|
|
@@ -429,17 +466,16 @@ Emulate only the body of the API Gateway event.
|
|
|
429
466
|
})()
|
|
430
467
|
|
|
431
468
|
const paramsOnHost = (() => {
|
|
432
|
-
// simple
|
|
433
|
-
const options = npmInstallBaseOptions.concat(['--prefix', codeDirectory])
|
|
469
|
+
// simple install
|
|
434
470
|
if (process.platform === 'win32') {
|
|
435
471
|
return {
|
|
436
472
|
command: 'cmd.exe',
|
|
437
|
-
options: ['/c',
|
|
473
|
+
options: ['/c', packageManager].concat(installOptions)
|
|
438
474
|
}
|
|
439
475
|
}
|
|
440
476
|
return {
|
|
441
|
-
command:
|
|
442
|
-
options
|
|
477
|
+
command: packageManager,
|
|
478
|
+
options: installOptions
|
|
443
479
|
}
|
|
444
480
|
})()
|
|
445
481
|
|
|
@@ -450,7 +486,7 @@ Emulate only the body of the API Gateway event.
|
|
|
450
486
|
env: process.env
|
|
451
487
|
}, (err) => {
|
|
452
488
|
if (err) return reject(err)
|
|
453
|
-
resolve()
|
|
489
|
+
resolve(packageManager)
|
|
454
490
|
})
|
|
455
491
|
})
|
|
456
492
|
}
|
|
@@ -518,7 +554,7 @@ Emulate only the body of the API Gateway event.
|
|
|
518
554
|
|
|
519
555
|
_codeDirectory () {
|
|
520
556
|
// Why realpathSync?:
|
|
521
|
-
// If tmpdir is symbolic link and npm>=7, `this.
|
|
557
|
+
// If tmpdir is symbolic link and npm>=7, `this._packageInstall()` may not work properly.
|
|
522
558
|
return path.join(fs.realpathSync(os.tmpdir()), `${path.basename(path.resolve('.'))}-lambda`)
|
|
523
559
|
}
|
|
524
560
|
|
|
@@ -691,8 +727,9 @@ they may not work as expected in the Lambda environment.
|
|
|
691
727
|
console.log('=> Moving files to temporary directory')
|
|
692
728
|
await this._fileCopy(program, lambdaSrcDirectory, codeDirectory, true)
|
|
693
729
|
if (!program.keepNodeModules) {
|
|
694
|
-
console.log(
|
|
695
|
-
await this.
|
|
730
|
+
console.log('=> Running package install')
|
|
731
|
+
const usedPackageManager = await this._packageInstall(program, codeDirectory)
|
|
732
|
+
console.log(`(Package manager used was '${usedPackageManager}'.)`)
|
|
696
733
|
}
|
|
697
734
|
await this._postInstallScript(program, codeDirectory)
|
|
698
735
|
console.log('=> Zipping deployment package')
|
package/package.json
CHANGED
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',
|
|
@@ -149,7 +150,7 @@ describe('lib/main', function () {
|
|
|
149
150
|
})
|
|
150
151
|
|
|
151
152
|
it('version should be set', () => {
|
|
152
|
-
assert.equal(lambda.version, '0.
|
|
153
|
+
assert.equal(lambda.version, '0.21.0')
|
|
153
154
|
})
|
|
154
155
|
|
|
155
156
|
describe('_codeDirectory', () => {
|
|
@@ -590,91 +591,251 @@ describe('lib/main', function () {
|
|
|
590
591
|
})
|
|
591
592
|
})
|
|
592
593
|
|
|
593
|
-
describe('
|
|
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 () {
|
|
594
708
|
_timeout({ this: this, sec: 60 }) // ci should be faster than install
|
|
595
709
|
|
|
596
710
|
// npm treats files as packages when installing, and so removes them.
|
|
597
711
|
// Test with `devDependencies` packages that are not installed with the `--production` option.
|
|
598
712
|
const nodeModulesMocha = path.join(codeDirectory, 'node_modules', 'mocha')
|
|
599
713
|
|
|
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
|
+
|
|
600
772
|
beforeEach(async () => {
|
|
601
773
|
await lambda._cleanDirectory(codeDirectory)
|
|
602
774
|
await lambda._fileCopy(program, '.', codeDirectory, false)
|
|
603
775
|
})
|
|
604
776
|
|
|
605
|
-
describe('
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
const contents = fs.readdirSync(path.join(codeDirectory, 'node_modules'))
|
|
610
|
-
assert.include(contents, 'dotenv')
|
|
611
|
-
|
|
612
|
-
// To remove and then install.
|
|
613
|
-
// beforeAwsSdkStat.ctimeMs < afterAwsSdkStat.ctimeMs
|
|
614
|
-
const afterAwsSdkStat = fs.statSync(path.join(codeDirectory, 'node_modules', 'aws-sdk'))
|
|
615
|
-
assert.isBelow(beforeAwsSdkStat.ctimeMs, afterAwsSdkStat.ctimeMs)
|
|
777
|
+
describe('Use npm', () => {
|
|
778
|
+
describe('when package-lock.json does exist', () => {
|
|
779
|
+
it('should use "npm ci"', () => testCleanAndInstall('npm'))
|
|
780
|
+
})
|
|
616
781
|
|
|
617
|
-
|
|
618
|
-
|
|
782
|
+
describe('when package-lock.json does not exist', () => {
|
|
783
|
+
beforeEach(() => {
|
|
784
|
+
return fs.removeSync(path.join(codeDirectory, 'package-lock.json'))
|
|
619
785
|
})
|
|
620
|
-
})
|
|
621
|
-
})
|
|
622
786
|
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
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')
|
|
791
|
+
|
|
792
|
+
const contents = fs.readdirSync(path.join(codeDirectory, 'node_modules'))
|
|
793
|
+
assert.include(contents, 'dotenv')
|
|
794
|
+
|
|
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
|
+
})
|
|
803
|
+
})
|
|
626
804
|
})
|
|
627
805
|
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
return lambda._npmInstall(program, codeDirectory).then(() => {
|
|
631
|
-
const contents = fs.readdirSync(path.join(codeDirectory, 'node_modules'))
|
|
632
|
-
assert.include(contents, 'dotenv')
|
|
806
|
+
describe('optionalDependencies', () => {
|
|
807
|
+
beforeEach(beforeEachOptionalDependencies)
|
|
633
808
|
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
assert.equal(beforeAwsSdkStat.ctimeMs, afterAwsSdkStat.ctimeMs)
|
|
809
|
+
describe('No `--no-optionalDependencies`', () => {
|
|
810
|
+
it('optionalDependencies is installed', () => testOptionalDependenciesIsInstalled('npm'))
|
|
811
|
+
})
|
|
638
812
|
|
|
639
|
-
|
|
640
|
-
|
|
813
|
+
describe('With `--no-optionalDependencies`', () => {
|
|
814
|
+
it('optionalDependency is NOT installed', () => testOptionalDependenciesIsNotInstalled('npm'))
|
|
641
815
|
})
|
|
642
816
|
})
|
|
643
817
|
})
|
|
644
818
|
|
|
645
|
-
describe('
|
|
646
|
-
|
|
647
|
-
const packageJsonPath = path.join(codeDirectory, 'package.json')
|
|
648
|
-
const packageJson = require(packageJsonPath)
|
|
649
|
-
packageJson.optionalDependencies = { npm: '*' }
|
|
650
|
-
fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson))
|
|
651
|
-
})
|
|
819
|
+
describe('Use yarn', () => {
|
|
820
|
+
it('should use "yarn install"', () => testCleanAndInstall('yarn'))
|
|
652
821
|
|
|
653
|
-
describe('
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
})
|
|
822
|
+
describe('optionalDependencies', () => {
|
|
823
|
+
beforeEach(beforeEachOptionalDependencies)
|
|
824
|
+
|
|
825
|
+
describe('No `--ignore-optionalDependencies`', () => {
|
|
826
|
+
it('optionalDependencies is installed', () => testOptionalDependenciesIsInstalled('yarn'))
|
|
659
827
|
})
|
|
660
|
-
})
|
|
661
828
|
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
const params = {
|
|
665
|
-
...program,
|
|
666
|
-
optionalDependencies: false
|
|
667
|
-
}
|
|
668
|
-
return lambda._npmInstall(params, codeDirectory).then(() => {
|
|
669
|
-
const contents = fs.readdirSync(path.join(codeDirectory, 'node_modules'))
|
|
670
|
-
assert.notInclude(contents, 'npm')
|
|
671
|
-
})
|
|
829
|
+
describe('With `--ignore-optionalDependencies`', () => {
|
|
830
|
+
it('optionalDependency is NOT installed', () => testOptionalDependenciesIsNotInstalled('yarn'))
|
|
672
831
|
})
|
|
673
832
|
})
|
|
674
833
|
})
|
|
675
834
|
})
|
|
676
835
|
|
|
677
|
-
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
|
+
|
|
678
839
|
beforeEach(() => {
|
|
679
840
|
// Since '\' can not be included in the file or directory name in Windows
|
|
680
841
|
const directoryName = process.platform === 'win32'
|
|
@@ -691,14 +852,21 @@ describe('lib/main', function () {
|
|
|
691
852
|
codeDirectory = lambda._codeDirectory()
|
|
692
853
|
})
|
|
693
854
|
|
|
694
|
-
|
|
695
|
-
|
|
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
|
+
}
|
|
696
867
|
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
assert.include(contents, 'node_modules')
|
|
700
|
-
})
|
|
701
|
-
})
|
|
868
|
+
it('npm adds node_modules', () => testFunc('npm'))
|
|
869
|
+
it('yarn adds node_modules', () => testFunc('yarn'))
|
|
702
870
|
})
|
|
703
871
|
|
|
704
872
|
describe('_postInstallScript', () => {
|
|
@@ -768,53 +936,70 @@ describe('lib/main', function () {
|
|
|
768
936
|
})
|
|
769
937
|
})
|
|
770
938
|
|
|
771
|
-
describe('_zip', ()
|
|
772
|
-
|
|
773
|
-
_timeout({ this: this, sec: 30 }) // give it time to build the node modules
|
|
774
|
-
return Promise.resolve().then(() => {
|
|
775
|
-
return lambda._cleanDirectory(codeDirectory)
|
|
776
|
-
}).then(() => {
|
|
777
|
-
return lambda._fileCopy(program, '.', codeDirectory, true)
|
|
778
|
-
}).then(() => {
|
|
779
|
-
return lambda._npmInstall(program, codeDirectory)
|
|
780
|
-
}).then(() => {
|
|
781
|
-
if (process.platform !== 'win32') {
|
|
782
|
-
fs.symlinkSync(
|
|
783
|
-
path.join(__dirname, '..', 'bin', 'node-lambda'),
|
|
784
|
-
path.join(codeDirectory, 'node-lambda-link')
|
|
785
|
-
)
|
|
786
|
-
}
|
|
787
|
-
})
|
|
788
|
-
})
|
|
939
|
+
describe('_zip', function () {
|
|
940
|
+
_timeout({ this: this, sec: 60 }) // give it time to zip
|
|
789
941
|
|
|
790
|
-
|
|
791
|
-
|
|
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
|
+
}
|
|
792
960
|
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
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
|
+
)
|
|
818
1003
|
})
|
|
819
1004
|
})
|
|
820
1005
|
|