serverless-plugin-include-dependencies
Advanced tools
Comparing version 4.1.0 to 5.0.0
@@ -16,8 +16,6 @@ 'use strict'; | ||
module.exports = function(filename, serverless) { | ||
module.exports = function(filename, serverless, cache) { | ||
const servicePath = serverless.config.servicePath; | ||
const modulePaths = new Set(); | ||
const filePaths = new Set(); | ||
const modulePaths = new Set(); | ||
const modulesToProcess = []; | ||
@@ -28,3 +26,8 @@ const localFilesToProcess = [filename]; | ||
const moduleName = requirePackageName(name.replace(/\\/, '/')); | ||
const cacheKey = `${basedir}:${name}`; | ||
if (cache && cache.has(cacheKey)) { | ||
return; | ||
} | ||
try { | ||
@@ -36,2 +39,7 @@ const pathToModule = resolve.sync(path.join(moduleName, 'package.json'), { basedir }); | ||
modulesToProcess.push(pkg); | ||
if (cache) { | ||
cache.add(cacheKey); | ||
} | ||
} else { | ||
@@ -50,5 +58,10 @@ // TODO: should we warn here? | ||
localFilesToProcess.push(resolved); | ||
if (cache) { | ||
cache.add(cacheKey); | ||
} | ||
return; | ||
} catch(e) { | ||
throw new Error(`[serverless-plugin-include-dependencies]: Could not find ${moduleName}`); | ||
throw new Error(`[serverless-plugin-include-dependencies]: Could not find npm package: ${moduleName}`); | ||
} | ||
@@ -55,0 +68,0 @@ } |
@@ -7,10 +7,18 @@ 'use strict'; | ||
const micromatch = require('micromatch'); | ||
const glob = require('glob'); | ||
const fs = require('fs'); | ||
const getDependencyList = require('./get-dependency-list'); | ||
function union(a, b) { | ||
const arr = a || []; | ||
return Array.from(new Set(arr.concat(b || []))); | ||
function union(a = [], b = []) { | ||
const existing = [].concat(a); | ||
const set = new Set(existing); | ||
[].concat(b).forEach(p => { | ||
if (set.has(p)) { | ||
return; | ||
} | ||
set.add(p); | ||
existing.push(p); | ||
}); | ||
return existing; | ||
} | ||
@@ -21,4 +29,4 @@ | ||
constructor(serverless, options) { | ||
if (!semver.satisfies(serverless.version, '>= 1.13')) { | ||
throw new Error('serverless-plugin-include-dependencies requires serverless 1.13 or higher!'); | ||
if (!semver.satisfies(serverless.version, '>= 2.32')) { | ||
throw new Error('serverless-plugin-include-dependencies requires serverless 2.32 or higher!'); | ||
} | ||
@@ -28,3 +36,7 @@ | ||
this.options = options; | ||
this.cache = new Set(); | ||
const service = this.serverless.service; | ||
this.individually = service.package && service.package.individually; | ||
this.hooks = { | ||
@@ -41,7 +53,7 @@ 'before:deploy:function:packageFunction': this.functionDeploy.bind(this), | ||
createDeploymentArtifacts() { | ||
const service = this.serverless.service; | ||
if (typeof service.functions === 'object') { | ||
Object.keys(service.functions).forEach(functionName => { | ||
this.processFunction(functionName); | ||
}); | ||
const { service = {} } = this.serverless; | ||
const { functions = {} } = service; | ||
for (const functionName in functions) { | ||
this.processFunction(functionName); | ||
} | ||
@@ -51,14 +63,11 @@ } | ||
processFunction(functionName) { | ||
const service = this.serverless.service; | ||
const { service = {} } = this.serverless; | ||
service.package = service.package || {}; | ||
service.package.patterns = union(['!node_modules/**'], service.package.patterns); | ||
const functionObject = service.functions[functionName]; | ||
const runtime = this.getFunctionRuntime(functionObject); | ||
functionObject.package = functionObject.package || {}; | ||
service.package = service.package || {}; | ||
service.package.exclude = union(service.package.exclude, ['node_modules/**']); | ||
if (runtime === 'provided' || runtime.match(/nodejs*/)) { | ||
this.processIncludes(functionObject); | ||
if (/(provided|nodejs)+/.test(runtime)) { | ||
this.processNodeFunction(functionObject); | ||
@@ -68,23 +77,2 @@ } | ||
includeGlobs(target, include, exclude) { | ||
include.forEach(includeGlob => { | ||
this.include(target, [includeGlob]); | ||
glob.sync(path.join(this.serverless.config.servicePath, includeGlob)) | ||
.filter(p => !exclude.some(e => { | ||
if (e.indexOf('node_modules') !== 0 || e === 'node_modules' || e === 'node_modules/**') { | ||
return false; | ||
} | ||
return micromatch.contains(p, e); | ||
})) | ||
.forEach(filePath => { | ||
var stat = fs.statSync(filePath); | ||
if (stat && stat.isFile()) { | ||
const dependencies = this.getDependencies(filePath, exclude); | ||
this.include(target, dependencies); | ||
} | ||
}); | ||
} | ||
); | ||
} | ||
getPluginOptions() { | ||
@@ -95,38 +83,16 @@ const service = this.serverless.service; | ||
processIncludes(functionObject) { | ||
const service = this.serverless.service; | ||
const options = this.getPluginOptions(); | ||
if (!options || !options.always) { | ||
return; | ||
} | ||
const include = union(options.always, []); | ||
if (service.package && service.package.individually) { | ||
const exclude = union(service.package.exclude, functionObject.package.exclude); | ||
this.includeGlobs(functionObject, include, exclude); | ||
} else { | ||
const exclude = service.package.exclude || []; | ||
this.includeGlobs(service, include, exclude); | ||
} | ||
} | ||
processNodeFunction(functionObject) { | ||
const service = this.serverless.service; | ||
const { service } = this.serverless; | ||
functionObject.package = functionObject.package || {}; | ||
const fileName = this.getHandlerFilename(functionObject.handler); | ||
const dependencies = this.getDependencies(fileName, service.package.patterns); | ||
if (service.package && service.package.individually) { | ||
const exclude = union(service.package.exclude, functionObject.package.exclude); | ||
const dependencies = this.getDependencies(fileName, exclude); | ||
this.include(functionObject, dependencies); | ||
} else { | ||
const exclude = service.package.exclude; | ||
const dependencies = this.getDependencies(fileName, exclude); | ||
this.include(service, dependencies); | ||
} | ||
const target = this.individually ? functionObject : service; | ||
target.package.patterns = union(target.package.patterns, dependencies); | ||
} | ||
getFunctionRuntime(functionObject) { | ||
const service = this.serverless.service; | ||
const { service } = this.serverless; | ||
@@ -136,32 +102,36 @@ const functionRuntime = functionObject.runtime; | ||
return functionRuntime || providerRuntime || 'nodejs4.3'; | ||
return functionRuntime || providerRuntime; | ||
} | ||
getHandlerFilename(handler) { | ||
const handlerPath = handler.slice(0, handler.lastIndexOf('.')); | ||
const lastDotIndex = handler.lastIndexOf('.'); | ||
const handlerPath = lastDotIndex !== -1 ? handler.slice(0, lastDotIndex) : 'index'; | ||
return require.resolve((path.join(this.serverless.config.servicePath, handlerPath))); | ||
} | ||
getDependencies(fileName, exclude) { | ||
getDependencies(fileName, patterns) { | ||
const servicePath = this.serverless.config.servicePath; | ||
const dependencies = this.getDependencyList(fileName); | ||
const relativeDependencies = dependencies.map(p => path.relative(servicePath, p)); | ||
const relativeDependencies = dependencies.map(p => path.relative(servicePath, p)); | ||
const exclusions = exclude.filter(e => { | ||
return !(e.indexOf('node_modules') !== 0 || e === 'node_modules' || e === 'node_modules/**'); | ||
const exclusions = patterns.filter(p => { | ||
return !(p.indexOf('!node_modules') !== 0 || p === '!node_modules' || p === '!node_modules/**'); | ||
}); | ||
return relativeDependencies.filter(p => { | ||
return !micromatch.some(p, exclusions); | ||
}); | ||
if (exclusions.length > 0) { | ||
return micromatch(relativeDependencies, exclusions); | ||
} | ||
return relativeDependencies; | ||
} | ||
getDependencyList(fileName) { | ||
if (!this.individually) { | ||
const options = this.getPluginOptions(); | ||
if (options && options.enableCaching) { | ||
return getDependencyList(fileName, this.serverless, this.cache); | ||
} | ||
} | ||
return getDependencyList(fileName, this.serverless); | ||
} | ||
include(target, dependencies) { | ||
target.package.include = union(target.package.include, dependencies); | ||
} | ||
}; |
{ | ||
"name": "serverless-plugin-include-dependencies", | ||
"version": "4.1.0", | ||
"version": "5.0.0", | ||
"engines": { | ||
@@ -25,12 +25,11 @@ "node": ">=4.0" | ||
"ava": "^3.0.0", | ||
"eslint": "^6.8.0", | ||
"eslint": "^7.30.0", | ||
"lodash": "^4.17.11", | ||
"nyc": "^15.0.0", | ||
"sinon": "^8.1.1", | ||
"sinon": "^11.1.1", | ||
"updater-contributors": "^0.1.2" | ||
}, | ||
"dependencies": { | ||
"glob": "^7.1.6", | ||
"micromatch": "^4.0.2", | ||
"precinct": "^6.2.0", | ||
"precinct": "^8.1.0", | ||
"read-pkg-up": "^7.0.1", | ||
@@ -37,0 +36,0 @@ "require-package-name": "^2.0.1", |
# serverless-plugin-include-dependencies | ||
> Note: This plugin no longer excludes the `aws-sdk` to stay in line with AWS best practices (bring your own SDK) | ||
This is a Serverless plugin that should make your deployed functions smaller. It does this by excluding `node_modules` then individually adds each module file that your handler depends on. | ||
This is a Serverless plugin that should make your deployed functions smaller. | ||
As of 5.0.0 this plugin uses the `package.patterns` property. `always` is no longer supported as it should be possible with just package.patterns | ||
It does this by enabling you to add your `node_modules` folder to the `exclude` list, then it individually adds each module that your handler depends on. | ||
> Note: This plugin no longer excludes the `aws-sdk` to stay in line with AWS best practices (bring your own SDK) | ||
@@ -20,3 +20,3 @@ If you use this plugin, you should disable the built-in Serverless option for excluding development dependencies, which is slower anyway: | ||
First install the plugin via NPM. | ||
First install the plugin via npm. | ||
@@ -41,13 +41,9 @@ ``` | ||
package: | ||
exclude: | ||
- node_modules/** # no need to add this yourself, this plugin does it for you | ||
patterns: | ||
- '!node_modules/**' # no need to add this, this plugin does it for you | ||
plugins: | ||
- serverless-plugin-common-excludes # this should go before serverless-plugin-include-dependencies | ||
- serverless-plugin-include-dependencies | ||
custom: | ||
includeDependencies: | ||
always: | ||
- 'src/lib/**' # (optional) always include these globs and their dependencies | ||
functions: | ||
@@ -68,18 +64,28 @@ foo: | ||
## Dependency caching (Experimental) | ||
When building a shared bundle for several functions, execution time can be reduced by enabling dependency caching. Caching is disabled by default and can be enabled using the `enableCaching` option: | ||
```yaml | ||
custom: | ||
includeDependencies: | ||
enableCaching: true | ||
``` | ||
## New In 2.0 - Exclusion Support | ||
Rather than including module folders (e.g. `node_modules/foo/**`, it now includes a list of actual files (e.g. `node_modules/foo/package.json`, `node_modules/foo/index.js`) and *uses the serverless package exclude* to filter these files. Excludes *must* start with `node_modules` to be considered by this plugin. | ||
Rather than including module folders (e.g. `node_modules/foo/**`, it now includes a list of actual files (e.g. `node_modules/foo/package.json`, `node_modules/foo/index.js`) and *uses the serverless package patterns* to filter these files. Patterns *must* start with `!node_modules` to be considered by this plugin. | ||
The following examples would filter files of your module dependencies: | ||
- `node_modules/**/README.*` | ||
- `node_modules/**/test/**` | ||
- `!node_modules/**/README.*` | ||
- `!node_modules/**/test/**` | ||
These would not: | ||
- `README` | ||
- `**/*.txt` | ||
- `!README` | ||
- `!**/*.txt` | ||
Even though normal matching libraries would match these rules, this library ignores them so that there's no chance of local excludes conflicting with node_modules excludes. | ||
Unless you know exactly where dependencies will be installed (e.g. several things could depend on aws-sdk) you probably want a rule more like `node_modules/**/aws-sdk/**` (which will exclude all instances of aws-sdk) and not `node_modules/aws-sdk/**` (which would only exclude a top-level aws-sdk) | ||
Unless you know exactly where dependencies will be installed (e.g. several things could depend on aws-sdk) you probably want a rule more like `!node_modules/**/foo/**` (which will exclude all instances of foo) and not `node_modules/foo/**` (which would only exclude a top-level foo) |
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
6
89
2
12258
198
+ Added@nodelib/fs.scandir@2.1.5(transitive)
+ Added@nodelib/fs.stat@2.0.5(transitive)
+ Added@nodelib/fs.walk@1.2.8(transitive)
+ Added@typescript-eslint/types@4.33.0(transitive)
+ Added@typescript-eslint/typescript-estree@4.33.0(transitive)
+ Added@typescript-eslint/visitor-keys@4.33.0(transitive)
+ Addedarray-union@2.1.0(transitive)
+ Addeddetective-postcss@4.0.0(transitive)
+ Addeddetective-typescript@7.0.2(transitive)
+ Addeddir-glob@3.0.1(transitive)
+ Addedeslint-visitor-keys@2.1.0(transitive)
+ Addedfast-glob@3.3.2(transitive)
+ Addedfastq@1.17.1(transitive)
+ Addedglob-parent@5.1.2(transitive)
+ Addedglobby@11.1.0(transitive)
+ Addedignore@5.3.1(transitive)
+ Addedmerge2@1.4.1(transitive)
+ Addednanoid@3.3.7(transitive)
+ Addedpath-type@4.0.0(transitive)
+ Addedpostcss@8.4.38(transitive)
+ Addedpostcss-values-parser@2.0.1(transitive)
+ Addedprecinct@8.3.1(transitive)
+ Addedqueue-microtask@1.2.3(transitive)
+ Addedreusify@1.0.4(transitive)
+ Addedrun-parallel@1.2.0(transitive)
+ Addedslash@3.0.0(transitive)
+ Addedsource-map-js@1.2.0(transitive)
- Removedglob@^7.1.6
- Removed@typescript-eslint/typescript-estree@2.34.0(transitive)
- Removedbalanced-match@1.0.2(transitive)
- Removedbrace-expansion@1.1.11(transitive)
- Removedconcat-map@0.0.1(transitive)
- Removeddetective-postcss@3.0.1(transitive)
- Removeddetective-typescript@5.8.0(transitive)
- Removedeslint-visitor-keys@1.3.0(transitive)
- Removedfs.realpath@1.0.0(transitive)
- Removedglob@7.2.3(transitive)
- Removedinflight@1.0.6(transitive)
- Removedinherits@2.0.4(transitive)
- Removedlodash@4.17.21(transitive)
- Removedminimatch@3.1.2(transitive)
- Removedonce@1.4.0(transitive)
- Removedpath-is-absolute@1.0.1(transitive)
- Removedpicocolors@0.2.1(transitive)
- Removedpostcss@7.0.39(transitive)
- Removedpostcss-values-parser@1.5.0(transitive)
- Removedprecinct@6.3.1(transitive)
- Removedwrappy@1.0.2(transitive)
Updatedprecinct@^8.1.0