@netlify/zip-it-and-ship-it 4.22.0 → 4.23.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/package.json +3 -2
- package/src/feature_flags.js +1 -0
- package/src/main.js +5 -2
- package/src/node_dependencies/index.js +49 -18
- package/src/runtimes/node/dynamic_imports/parser.js +6 -5
- package/src/runtimes/node/index.js +2 -1
- package/src/runtimes/node/list_imports.js +51 -0
- package/src/runtimes/node/src_files.js +9 -1
- package/src/runtimes/node/zip_zisi.js +2 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@netlify/zip-it-and-ship-it",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.23.0",
|
|
4
4
|
"description": "Zip it and ship it",
|
|
5
5
|
"main": "./src/main.js",
|
|
6
6
|
"bin": {
|
|
@@ -54,8 +54,8 @@
|
|
|
54
54
|
"url": "https://github.com/netlify/zip-it-and-ship-it/issues"
|
|
55
55
|
},
|
|
56
56
|
"dependencies": {
|
|
57
|
+
"@babel/parser": "^7.15.7",
|
|
57
58
|
"@netlify/esbuild": "^0.13.6",
|
|
58
|
-
"acorn": "^8.4.0",
|
|
59
59
|
"archiver": "^5.3.0",
|
|
60
60
|
"array-flat-polyfill": "^1.0.1",
|
|
61
61
|
"common-path-prefix": "^3.0.0",
|
|
@@ -68,6 +68,7 @@
|
|
|
68
68
|
"filter-obj": "^2.0.1",
|
|
69
69
|
"find-up": "^5.0.0",
|
|
70
70
|
"glob": "^7.1.6",
|
|
71
|
+
"is-builtin-module": "^3.1.0",
|
|
71
72
|
"junk": "^3.1.0",
|
|
72
73
|
"locate-path": "^6.0.0",
|
|
73
74
|
"make-dir": "^3.1.0",
|
package/src/feature_flags.js
CHANGED
|
@@ -5,6 +5,7 @@ const FLAGS = {
|
|
|
5
5
|
buildGoSource: Boolean(env.NETLIFY_EXPERIMENTAL_BUILD_GO_SOURCE),
|
|
6
6
|
buildRustSource: Boolean(env.NETLIFY_EXPERIMENTAL_BUILD_RUST_SOURCE),
|
|
7
7
|
defaultEsModulesToEsbuild: Boolean(env.NETLIFY_EXPERIMENTAL_DEFAULT_ES_MODULES_TO_ESBUILD),
|
|
8
|
+
parseWithEsbuild: false,
|
|
8
9
|
}
|
|
9
10
|
|
|
10
11
|
const getFlags = (input = {}, flags = FLAGS) =>
|
package/src/main.js
CHANGED
|
@@ -27,7 +27,7 @@ const listFunctionsFiles = async function (relativeSrcFolders, { config, feature
|
|
|
27
27
|
getPluginsModulesPath(srcFolders[0]),
|
|
28
28
|
])
|
|
29
29
|
const listedFunctionsFiles = await Promise.all(
|
|
30
|
-
[...functions.values()].map((func) => getListedFunctionFiles(func, { pluginsModulesPath })),
|
|
30
|
+
[...functions.values()].map((func) => getListedFunctionFiles(func, { featureFlags, pluginsModulesPath })),
|
|
31
31
|
)
|
|
32
32
|
|
|
33
33
|
// TODO: switch to Array.flat() once we drop support for Node.js < 11.0.0
|
|
@@ -41,9 +41,10 @@ const getListedFunction = function ({ runtime, name, mainFile, extension }) {
|
|
|
41
41
|
|
|
42
42
|
const getListedFunctionFiles = async function (
|
|
43
43
|
{ config, runtime, name, stat, mainFile, extension, srcPath, srcDir },
|
|
44
|
-
{ pluginsModulesPath },
|
|
44
|
+
{ featureFlags, pluginsModulesPath },
|
|
45
45
|
) {
|
|
46
46
|
const srcFiles = await getSrcFiles({
|
|
47
|
+
featureFlags,
|
|
47
48
|
runtime,
|
|
48
49
|
stat,
|
|
49
50
|
mainFile,
|
|
@@ -59,6 +60,7 @@ const getListedFunctionFiles = async function (
|
|
|
59
60
|
const getSrcFiles = function ({
|
|
60
61
|
bundler,
|
|
61
62
|
config,
|
|
63
|
+
featureFlags,
|
|
62
64
|
runtime,
|
|
63
65
|
stat,
|
|
64
66
|
mainFile,
|
|
@@ -77,6 +79,7 @@ const getSrcFiles = function ({
|
|
|
77
79
|
bundler,
|
|
78
80
|
config,
|
|
79
81
|
extension,
|
|
82
|
+
featureFlags,
|
|
80
83
|
srcPath,
|
|
81
84
|
mainFile,
|
|
82
85
|
srcDir,
|
|
@@ -4,6 +4,8 @@ const findUp = require('find-up')
|
|
|
4
4
|
const { not: notJunk } = require('junk')
|
|
5
5
|
const precinct = require('precinct')
|
|
6
6
|
|
|
7
|
+
const { listImports } = require('../runtimes/node/list_imports')
|
|
8
|
+
|
|
7
9
|
const { getPackageJson } = require('./package_json')
|
|
8
10
|
const { resolvePathPreserveSymlinks } = require('./resolve')
|
|
9
11
|
const { getExternalAndIgnoredModulesFromSpecialCases } = require('./special_cases')
|
|
@@ -23,10 +25,17 @@ const getPluginsModulesPath = (srcDir) => findUp(`${AUTO_PLUGINS_DIR}node_module
|
|
|
23
25
|
// Retrieve the paths to the Node.js files to zip.
|
|
24
26
|
// We only include the files actually needed by the function because AWS Lambda
|
|
25
27
|
// has a size limit for the zipped file. It also makes cold starts faster.
|
|
26
|
-
const listFilesUsingLegacyBundler = async function ({
|
|
28
|
+
const listFilesUsingLegacyBundler = async function ({
|
|
29
|
+
featureFlags,
|
|
30
|
+
srcPath,
|
|
31
|
+
mainFile,
|
|
32
|
+
srcDir,
|
|
33
|
+
stat,
|
|
34
|
+
pluginsModulesPath,
|
|
35
|
+
}) {
|
|
27
36
|
const [treeFiles, depFiles] = await Promise.all([
|
|
28
37
|
getTreeFiles(srcPath, stat),
|
|
29
|
-
getDependencies(mainFile, srcDir, pluginsModulesPath),
|
|
38
|
+
getDependencies(mainFile, srcDir, pluginsModulesPath, featureFlags),
|
|
30
39
|
])
|
|
31
40
|
const files = [...treeFiles, ...depFiles].map(normalize)
|
|
32
41
|
const uniqueFiles = [...new Set(files)]
|
|
@@ -43,19 +52,26 @@ const isNotJunk = function (file) {
|
|
|
43
52
|
}
|
|
44
53
|
|
|
45
54
|
// Retrieve all the files recursively required by a Node.js file
|
|
46
|
-
const getDependencies = async function (mainFile, srcDir, pluginsModulesPath) {
|
|
55
|
+
const getDependencies = async function (mainFile, srcDir, pluginsModulesPath, featureFlags) {
|
|
47
56
|
const packageJson = await getPackageJson(srcDir)
|
|
48
57
|
const state = getNewCache()
|
|
49
58
|
|
|
50
59
|
try {
|
|
51
|
-
return await getFileDependencies({ path: mainFile, packageJson,
|
|
60
|
+
return await getFileDependencies({ featureFlags, path: mainFile, packageJson, pluginsModulesPath, state })
|
|
52
61
|
} catch (error) {
|
|
53
62
|
error.message = `In file "${mainFile}"\n${error.message}`
|
|
54
63
|
throw error
|
|
55
64
|
}
|
|
56
65
|
}
|
|
57
66
|
|
|
58
|
-
const getFileDependencies = async function ({
|
|
67
|
+
const getFileDependencies = async function ({
|
|
68
|
+
featureFlags,
|
|
69
|
+
path,
|
|
70
|
+
packageJson,
|
|
71
|
+
pluginsModulesPath,
|
|
72
|
+
state,
|
|
73
|
+
treeShakeNext,
|
|
74
|
+
}) {
|
|
59
75
|
if (state.localFiles.has(path)) {
|
|
60
76
|
return []
|
|
61
77
|
}
|
|
@@ -63,16 +79,21 @@ const getFileDependencies = async function ({ path, packageJson, pluginsModulesP
|
|
|
63
79
|
state.localFiles.add(path)
|
|
64
80
|
|
|
65
81
|
const basedir = dirname(path)
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
const dependencies = precinct.paperwork(path, { includeCore: false })
|
|
82
|
+
const dependencies = featureFlags.parseWithEsbuild
|
|
83
|
+
? await listImports({ path })
|
|
84
|
+
: precinct.paperwork(path, { includeCore: false })
|
|
70
85
|
const depsPaths = await Promise.all(
|
|
71
|
-
dependencies
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
86
|
+
dependencies.filter(Boolean).map((dependency) =>
|
|
87
|
+
getImportDependencies({
|
|
88
|
+
dependency,
|
|
89
|
+
basedir,
|
|
90
|
+
featureFlags,
|
|
91
|
+
packageJson,
|
|
92
|
+
pluginsModulesPath,
|
|
93
|
+
state,
|
|
94
|
+
treeShakeNext,
|
|
95
|
+
}),
|
|
96
|
+
),
|
|
76
97
|
)
|
|
77
98
|
// TODO: switch to Array.flat() once we drop support for Node.js < 11.0.0
|
|
78
99
|
// eslint-disable-next-line unicorn/prefer-spread
|
|
@@ -82,20 +103,22 @@ const getFileDependencies = async function ({ path, packageJson, pluginsModulesP
|
|
|
82
103
|
const getImportDependencies = function ({
|
|
83
104
|
dependency,
|
|
84
105
|
basedir,
|
|
106
|
+
featureFlags,
|
|
85
107
|
packageJson,
|
|
108
|
+
pluginsModulesPath,
|
|
86
109
|
state,
|
|
87
110
|
treeShakeNext,
|
|
88
|
-
pluginsModulesPath,
|
|
89
111
|
}) {
|
|
90
112
|
const shouldTreeShakeNext = treeShakeNext || isNextOnNetlify(dependency)
|
|
91
113
|
if (shouldTreeShake(dependency, shouldTreeShakeNext)) {
|
|
92
114
|
return getTreeShakedDependencies({
|
|
93
115
|
dependency,
|
|
94
116
|
basedir,
|
|
117
|
+
featureFlags,
|
|
95
118
|
packageJson,
|
|
119
|
+
pluginsModulesPath,
|
|
96
120
|
state,
|
|
97
121
|
treeShakeNext: shouldTreeShakeNext,
|
|
98
|
-
pluginsModulesPath,
|
|
99
122
|
})
|
|
100
123
|
}
|
|
101
124
|
|
|
@@ -110,13 +133,21 @@ const isNextOnNetlify = function (dependency) {
|
|
|
110
133
|
const getTreeShakedDependencies = async function ({
|
|
111
134
|
dependency,
|
|
112
135
|
basedir,
|
|
136
|
+
featureFlags,
|
|
113
137
|
packageJson,
|
|
138
|
+
pluginsModulesPath,
|
|
114
139
|
state,
|
|
115
140
|
treeShakeNext,
|
|
116
|
-
pluginsModulesPath,
|
|
117
141
|
}) {
|
|
118
142
|
const path = await resolvePathPreserveSymlinks(dependency, [basedir, pluginsModulesPath].filter(Boolean))
|
|
119
|
-
const depsPath = await getFileDependencies({
|
|
143
|
+
const depsPath = await getFileDependencies({
|
|
144
|
+
featureFlags,
|
|
145
|
+
path,
|
|
146
|
+
packageJson,
|
|
147
|
+
pluginsModulesPath,
|
|
148
|
+
state,
|
|
149
|
+
treeShakeNext,
|
|
150
|
+
})
|
|
120
151
|
return [path, ...depsPath]
|
|
121
152
|
}
|
|
122
153
|
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
const { join, relative, resolve } = require('path')
|
|
2
2
|
|
|
3
|
-
const
|
|
3
|
+
const babel = require('@babel/parser')
|
|
4
4
|
|
|
5
|
-
const ECMA_VERSION = 2021
|
|
6
5
|
const GLOB_WILDCARD = '**'
|
|
7
6
|
|
|
8
7
|
// Transforms an array of glob nodes into a glob string including an absolute
|
|
@@ -56,8 +55,10 @@ const getWildcardFromASTNode = (node) => {
|
|
|
56
55
|
// - `includedPathsGlob`: A glob with the files to be included in the bundle
|
|
57
56
|
// - `type`: The expression type (e.g. "require", "import")
|
|
58
57
|
const parseExpression = ({ basePath, expression: rawExpression, resolveDir }) => {
|
|
59
|
-
const {
|
|
60
|
-
|
|
58
|
+
const { program } = babel.parse(rawExpression, {
|
|
59
|
+
sourceType: 'module',
|
|
60
|
+
})
|
|
61
|
+
const [topLevelExpression] = program.body
|
|
61
62
|
const { expression } = topLevelExpression
|
|
62
63
|
|
|
63
64
|
if (expression.type === 'CallExpression' && expression.callee.name === 'require') {
|
|
@@ -113,7 +114,7 @@ const parseBinaryExpression = (expression) => {
|
|
|
113
114
|
case 'BinaryExpression':
|
|
114
115
|
return parseBinaryExpression(operand)
|
|
115
116
|
|
|
116
|
-
case '
|
|
117
|
+
case 'StringLiteral':
|
|
117
118
|
return operand.value
|
|
118
119
|
|
|
119
120
|
default:
|
|
@@ -42,6 +42,7 @@ const zipFunction = async function ({
|
|
|
42
42
|
config = {},
|
|
43
43
|
destFolder,
|
|
44
44
|
extension,
|
|
45
|
+
featureFlags,
|
|
45
46
|
filename,
|
|
46
47
|
mainFile,
|
|
47
48
|
name,
|
|
@@ -49,7 +50,6 @@ const zipFunction = async function ({
|
|
|
49
50
|
srcDir,
|
|
50
51
|
srcPath,
|
|
51
52
|
stat,
|
|
52
|
-
featureFlags,
|
|
53
53
|
}) {
|
|
54
54
|
const bundler = config.nodeBundler || (await getDefaultBundler({ extension, mainFile, featureFlags }))
|
|
55
55
|
// If the file is a zip, we assume the function is bundled and ready to go.
|
|
@@ -67,6 +67,7 @@ const zipFunction = async function ({
|
|
|
67
67
|
config,
|
|
68
68
|
destFolder,
|
|
69
69
|
extension,
|
|
70
|
+
featureFlags,
|
|
70
71
|
filename,
|
|
71
72
|
mainFile,
|
|
72
73
|
pluginsModulesPath,
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
const esbuild = require('@netlify/esbuild')
|
|
2
|
+
const isBuiltinModule = require('is-builtin-module')
|
|
3
|
+
const { tmpName } = require('tmp-promise')
|
|
4
|
+
|
|
5
|
+
const { safeUnlink } = require('../../utils/fs')
|
|
6
|
+
|
|
7
|
+
const getListImportsPlugin = ({ imports, path }) => ({
|
|
8
|
+
name: 'list-imports',
|
|
9
|
+
setup(build) {
|
|
10
|
+
build.onResolve({ filter: /.*/ }, (args) => {
|
|
11
|
+
const isEntryPoint = args.path === path
|
|
12
|
+
const isImport = !isEntryPoint && !isBuiltinModule(args.path)
|
|
13
|
+
|
|
14
|
+
if (isImport) {
|
|
15
|
+
imports.add(args.path)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
return {
|
|
19
|
+
namespace: 'list-imports',
|
|
20
|
+
external: isImport,
|
|
21
|
+
}
|
|
22
|
+
})
|
|
23
|
+
},
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
const listImports = async ({ path }) => {
|
|
27
|
+
// We're not interested in the output that esbuild generates, we're just
|
|
28
|
+
// using it for its parsing capabilities in order to find import/require
|
|
29
|
+
// statements. However, if we don't give esbuild a path in `outfile`, it
|
|
30
|
+
// will pipe the output to stdout, which we also don't want. So we create
|
|
31
|
+
// a temporary file to serve as the esbuild output and then get rid of it
|
|
32
|
+
// when we're done.
|
|
33
|
+
const targetPath = await tmpName()
|
|
34
|
+
const imports = new Set()
|
|
35
|
+
|
|
36
|
+
try {
|
|
37
|
+
await esbuild.build({
|
|
38
|
+
entryPoints: [path],
|
|
39
|
+
bundle: true,
|
|
40
|
+
outfile: targetPath,
|
|
41
|
+
platform: 'node',
|
|
42
|
+
plugins: [getListImportsPlugin({ imports, path })],
|
|
43
|
+
})
|
|
44
|
+
} finally {
|
|
45
|
+
await safeUnlink(targetPath)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return [...imports]
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
module.exports = { listImports }
|
|
@@ -53,6 +53,7 @@ const getSrcFiles = async function ({ config, ...parameters }) {
|
|
|
53
53
|
const getSrcFilesAndExternalModules = async function ({
|
|
54
54
|
bundler,
|
|
55
55
|
externalNodeModules = [],
|
|
56
|
+
featureFlags,
|
|
56
57
|
includedFiles = [],
|
|
57
58
|
includedFilesBasePath,
|
|
58
59
|
mainFile,
|
|
@@ -64,7 +65,14 @@ const getSrcFilesAndExternalModules = async function ({
|
|
|
64
65
|
const includedFilePaths = await getPathsOfIncludedFiles(includedFiles, includedFilesBasePath)
|
|
65
66
|
|
|
66
67
|
if (bundler === JS_BUNDLER_ZISI) {
|
|
67
|
-
const paths = await listFilesUsingLegacyBundler({
|
|
68
|
+
const paths = await listFilesUsingLegacyBundler({
|
|
69
|
+
featureFlags,
|
|
70
|
+
srcPath,
|
|
71
|
+
mainFile,
|
|
72
|
+
srcDir,
|
|
73
|
+
stat,
|
|
74
|
+
pluginsModulesPath,
|
|
75
|
+
})
|
|
68
76
|
|
|
69
77
|
return {
|
|
70
78
|
moduleNames: [],
|
|
@@ -12,6 +12,7 @@ const zipZisi = async ({
|
|
|
12
12
|
config,
|
|
13
13
|
destFolder,
|
|
14
14
|
extension,
|
|
15
|
+
featureFlags,
|
|
15
16
|
filename,
|
|
16
17
|
mainFile,
|
|
17
18
|
pluginsModulesPath,
|
|
@@ -22,6 +23,7 @@ const zipZisi = async ({
|
|
|
22
23
|
const { paths: srcFiles } = await getSrcFilesAndExternalModules({
|
|
23
24
|
bundler: JS_BUNDLER_ZISI,
|
|
24
25
|
extension,
|
|
26
|
+
featureFlags,
|
|
25
27
|
includedFiles: config.includedFiles,
|
|
26
28
|
includedFilesBasePath: config.includedFilesBasePath || basePath,
|
|
27
29
|
mainFile,
|