@netlify/zip-it-and-ship-it 4.23.3 → 4.23.5-setup-typescript-4

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.
Files changed (136) hide show
  1. package/dist/archive.d.ts +8 -0
  2. package/dist/archive.js +39 -0
  3. package/dist/bin.d.ts +2 -0
  4. package/dist/bin.js +67 -0
  5. package/dist/config.d.ts +4 -0
  6. package/dist/config.js +26 -0
  7. package/dist/feature_flags.d.ts +12 -0
  8. package/dist/feature_flags.js +10 -0
  9. package/dist/main.d.ts +15 -0
  10. package/dist/main.js +80 -0
  11. package/dist/manifest.d.ts +4 -0
  12. package/dist/manifest.js +25 -0
  13. package/dist/node_dependencies/index.d.ts +15 -0
  14. package/dist/node_dependencies/index.js +132 -0
  15. package/dist/node_dependencies/module.d.ts +1 -0
  16. package/dist/node_dependencies/module.js +10 -0
  17. package/dist/node_dependencies/nested.d.ts +10 -0
  18. package/{src → dist}/node_dependencies/nested.js +39 -60
  19. package/dist/node_dependencies/package_json.d.ts +1 -0
  20. package/dist/node_dependencies/package_json.js +29 -0
  21. package/dist/node_dependencies/published.d.ts +1 -0
  22. package/dist/node_dependencies/published.js +42 -0
  23. package/dist/node_dependencies/resolve.d.ts +2 -0
  24. package/dist/node_dependencies/resolve.js +114 -0
  25. package/dist/node_dependencies/side_files.d.ts +1 -0
  26. package/dist/node_dependencies/side_files.js +14 -0
  27. package/dist/node_dependencies/special_cases.d.ts +6 -0
  28. package/dist/node_dependencies/special_cases.js +44 -0
  29. package/dist/node_dependencies/traverse.d.ts +39 -0
  30. package/dist/node_dependencies/traverse.js +120 -0
  31. package/dist/node_dependencies/tree_files.d.ts +3 -0
  32. package/dist/node_dependencies/tree_files.js +32 -0
  33. package/dist/node_dependencies/tree_shake.d.ts +1 -0
  34. package/{src → dist}/node_dependencies/tree_shake.js +8 -12
  35. package/dist/runtimes/detect_runtime.d.ts +4 -0
  36. package/dist/runtimes/detect_runtime.js +27 -0
  37. package/dist/runtimes/go/builder.d.ts +12 -0
  38. package/dist/runtimes/go/builder.js +39 -0
  39. package/dist/runtimes/go/index.d.ts +18 -0
  40. package/dist/runtimes/go/index.js +78 -0
  41. package/dist/runtimes/index.d.ts +9 -0
  42. package/dist/runtimes/index.js +87 -0
  43. package/dist/runtimes/node/base_path.d.ts +1 -0
  44. package/dist/runtimes/node/base_path.js +8 -0
  45. package/dist/runtimes/node/bundler.d.ts +20 -0
  46. package/dist/runtimes/node/bundler.js +135 -0
  47. package/dist/runtimes/node/bundler_target.d.ts +1 -0
  48. package/dist/runtimes/node/bundler_target.js +16 -0
  49. package/dist/runtimes/node/detect_es_module.d.ts +3 -0
  50. package/dist/runtimes/node/detect_es_module.js +28 -0
  51. package/dist/runtimes/node/dynamic_imports/parser.d.ts +8 -0
  52. package/dist/runtimes/node/dynamic_imports/parser.js +135 -0
  53. package/dist/runtimes/node/dynamic_imports/plugin.d.ts +10 -0
  54. package/dist/runtimes/node/dynamic_imports/plugin.js +102 -0
  55. package/dist/runtimes/node/finder.d.ts +12 -0
  56. package/dist/runtimes/node/finder.js +82 -0
  57. package/dist/runtimes/node/index.d.ts +16 -0
  58. package/dist/runtimes/node/index.js +118 -0
  59. package/dist/runtimes/node/list_imports.d.ts +4 -0
  60. package/dist/runtimes/node/list_imports.js +68 -0
  61. package/dist/runtimes/node/native_modules/detector.d.ts +7 -0
  62. package/dist/runtimes/node/native_modules/detector.js +14 -0
  63. package/dist/runtimes/node/native_modules/plugin.d.ts +4 -0
  64. package/dist/runtimes/node/native_modules/plugin.js +65 -0
  65. package/dist/runtimes/node/src_files.d.ts +20 -0
  66. package/dist/runtimes/node/src_files.js +84 -0
  67. package/dist/runtimes/node/zip_esbuild.d.ts +22 -0
  68. package/dist/runtimes/node/zip_esbuild.js +95 -0
  69. package/dist/runtimes/node/zip_zisi.d.ts +20 -0
  70. package/dist/runtimes/node/zip_zisi.js +42 -0
  71. package/dist/runtimes/rust/builder.d.ts +9 -0
  72. package/dist/runtimes/rust/builder.js +100 -0
  73. package/dist/runtimes/rust/constants.d.ts +2 -0
  74. package/dist/runtimes/rust/constants.js +3 -0
  75. package/dist/runtimes/rust/index.d.ts +20 -0
  76. package/dist/runtimes/rust/index.js +101 -0
  77. package/dist/utils/consts.d.ts +8 -0
  78. package/dist/utils/consts.js +10 -0
  79. package/dist/utils/fs.d.ts +14 -0
  80. package/dist/utils/fs.js +86 -0
  81. package/dist/utils/polyfills.d.ts +1 -0
  82. package/{src → dist}/utils/polyfills.js +1 -1
  83. package/dist/utils/remove_falsy.d.ts +1 -0
  84. package/dist/utils/remove_falsy.js +9 -0
  85. package/dist/utils/shell.d.ts +2 -0
  86. package/dist/utils/shell.js +2 -0
  87. package/dist/zip.d.ts +15 -0
  88. package/dist/zip.js +116 -0
  89. package/dist/zip_binary.d.ts +7 -0
  90. package/dist/zip_binary.js +20 -0
  91. package/dist/zip_node.d.ts +4 -0
  92. package/dist/zip_node.js +143 -0
  93. package/package.json +19 -13
  94. package/src/archive.js +0 -36
  95. package/src/bin.js +0 -53
  96. package/src/config.js +0 -32
  97. package/src/feature_flags.js +0 -20
  98. package/src/main.js +0 -91
  99. package/src/manifest.js +0 -22
  100. package/src/node_dependencies/index.js +0 -161
  101. package/src/node_dependencies/module.js +0 -13
  102. package/src/node_dependencies/package_json.js +0 -21
  103. package/src/node_dependencies/published.js +0 -37
  104. package/src/node_dependencies/resolve.js +0 -108
  105. package/src/node_dependencies/side_files.js +0 -18
  106. package/src/node_dependencies/special_cases.js +0 -42
  107. package/src/node_dependencies/traverse.js +0 -147
  108. package/src/node_dependencies/tree_files.js +0 -20
  109. package/src/runtimes/detect_runtime.js +0 -20
  110. package/src/runtimes/go/builder.js +0 -37
  111. package/src/runtimes/go/index.js +0 -89
  112. package/src/runtimes/index.js +0 -96
  113. package/src/runtimes/node/base_path.js +0 -11
  114. package/src/runtimes/node/bundler.js +0 -151
  115. package/src/runtimes/node/bundler_target.js +0 -22
  116. package/src/runtimes/node/detect_es_module.js +0 -24
  117. package/src/runtimes/node/dynamic_imports/parser.js +0 -162
  118. package/src/runtimes/node/dynamic_imports/plugin.js +0 -116
  119. package/src/runtimes/node/finder.js +0 -93
  120. package/src/runtimes/node/index.js +0 -122
  121. package/src/runtimes/node/list_imports.js +0 -59
  122. package/src/runtimes/node/native_modules/detector.js +0 -21
  123. package/src/runtimes/node/native_modules/plugin.js +0 -77
  124. package/src/runtimes/node/src_files.js +0 -99
  125. package/src/runtimes/node/zip_esbuild.js +0 -119
  126. package/src/runtimes/node/zip_zisi.js +0 -50
  127. package/src/runtimes/rust/builder.js +0 -114
  128. package/src/runtimes/rust/constants.js +0 -4
  129. package/src/runtimes/rust/index.js +0 -112
  130. package/src/utils/consts.js +0 -10
  131. package/src/utils/fs.js +0 -88
  132. package/src/utils/remove_falsy.js +0 -12
  133. package/src/utils/shell.js +0 -3
  134. package/src/zip.js +0 -161
  135. package/src/zip_binary.js +0 -11
  136. package/src/zip_node.js +0 -179
@@ -0,0 +1,87 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ const { extname, basename } = require('path');
11
+ const { getConfigForFunction } = require('../config');
12
+ const goRuntime = require('./go');
13
+ const jsRuntime = require('./node');
14
+ const rustRuntime = require('./rust');
15
+ /**
16
+ * Finds functions for a list of paths using a specific runtime. The return
17
+ * value is an object containing an array of the functions found (`functions`)
18
+ * and an array with the paths that haven't been recognized by the runtime
19
+ * (`remainingPaths`).
20
+ *
21
+ * @param {Boolean} dedupe
22
+ * @param {Object} fsCache
23
+ * @param {Array<String>} paths
24
+ * @param {Object} runtime
25
+ * @returns {Promise<Object>}
26
+ */
27
+ const findFunctionsInRuntime = function ({ dedupe = false, featureFlags, fsCache, paths, runtime }) {
28
+ return __awaiter(this, void 0, void 0, function* () {
29
+ const functions = yield runtime.findFunctionsInPaths({ featureFlags, fsCache, paths });
30
+ // If `dedupe` is true, we use the function name (`filename`) as the map key,
31
+ // so that `function-1.js` will overwrite `function-1.go`. Otherwise, we use
32
+ // `srcPath`, so that both functions are returned.
33
+ const key = dedupe ? 'name' : 'srcPath';
34
+ // Augmenting the function objects with additional information.
35
+ const augmentedFunctions = functions.map((func) => [
36
+ func[key],
37
+ Object.assign(Object.assign({}, func), { extension: extname(func.mainFile), filename: basename(func.srcPath), runtime }),
38
+ ]);
39
+ const usedPaths = new Set(augmentedFunctions.map(([path]) => path));
40
+ const remainingPaths = paths.filter((path) => !usedPaths.has(path));
41
+ return { functions: augmentedFunctions, remainingPaths };
42
+ });
43
+ };
44
+ /**
45
+ * Gets a list of functions found in a list of paths.
46
+ *
47
+ * @param {Object} config
48
+ * @param {Boolean} dedupe
49
+ * @param {String} path
50
+ * @returns {Promise<Map>}
51
+ */
52
+ const getFunctionsFromPaths = (paths, { config, dedupe = false, featureFlags } = {}) => __awaiter(this, void 0, void 0, function* () {
53
+ // An object to cache filesystem operations. This allows different functions
54
+ // to perform IO operations on the same file (i.e. getting its stats or its
55
+ // contents) without duplicating work.
56
+ const fsCache = {};
57
+ // The order of this array determines the priority of the runtimes. If a path
58
+ // is used by the first time, it won't be made available to the subsequent
59
+ // runtimes.
60
+ const runtimes = [jsRuntime, goRuntime, rustRuntime];
61
+ // We cycle through the ordered array of runtimes, passing each one of them
62
+ // through `findFunctionsInRuntime`. For each iteration, we collect all the
63
+ // functions found plus the list of paths that still need to be evaluated,
64
+ // using them as the input for the next iteration until the last runtime.
65
+ const { functions } = yield runtimes.reduce((aggregate, runtime) => __awaiter(this, void 0, void 0, function* () {
66
+ const { functions: aggregateFunctions, remainingPaths: aggregatePaths } = yield aggregate;
67
+ const { functions: runtimeFunctions, remainingPaths: runtimePaths } = yield findFunctionsInRuntime({
68
+ dedupe,
69
+ featureFlags,
70
+ fsCache,
71
+ paths: aggregatePaths,
72
+ runtime,
73
+ });
74
+ return {
75
+ functions: [...aggregateFunctions, ...runtimeFunctions],
76
+ remainingPaths: runtimePaths,
77
+ };
78
+ }), { functions: [], remainingPaths: paths });
79
+ const functionsWithConfig = functions.map(([name, func]) => [
80
+ name,
81
+ Object.assign(Object.assign({}, func), { config: getConfigForFunction({ config, func }) }),
82
+ ]);
83
+ return new Map(functionsWithConfig);
84
+ });
85
+ module.exports = {
86
+ getFunctionsFromPaths,
87
+ };
@@ -0,0 +1 @@
1
+ export function getBasePath(dirnames: any): any;
@@ -0,0 +1,8 @@
1
+ const commonPathPrefix = require('common-path-prefix');
2
+ const getBasePath = (dirnames) => {
3
+ if (dirnames.length === 1) {
4
+ return dirnames[0];
5
+ }
6
+ return commonPathPrefix(dirnames);
7
+ };
8
+ module.exports = { getBasePath };
@@ -0,0 +1,20 @@
1
+ export function bundleJsFile({ additionalModulePaths, basePath, config, externalModules, ignoredModules, name, srcDir, srcFile, }: {
2
+ additionalModulePaths: any;
3
+ basePath: any;
4
+ config: any;
5
+ externalModules?: any[];
6
+ ignoredModules?: any[];
7
+ name: any;
8
+ srcDir: any;
9
+ srcFile: any;
10
+ }): Promise<{
11
+ additionalPaths: any[];
12
+ bundlePaths: Map<any, any>;
13
+ cleanTempFiles: () => Promise<void>;
14
+ inputs: string[];
15
+ nativeNodeModules: {};
16
+ nodeModulesWithDynamicImports: any[];
17
+ warnings: esbuild.Message[];
18
+ }>;
19
+ export const ESBUILD_LOG_LIMIT: 10;
20
+ import esbuild = require("@netlify/esbuild");
@@ -0,0 +1,135 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ const { basename, dirname, extname, resolve, join } = require('path');
11
+ const esbuild = require('@netlify/esbuild');
12
+ const { tmpName } = require('tmp-promise');
13
+ const { JS_BUNDLER_ESBUILD, RUNTIME_JS } = require('../../utils/consts');
14
+ const { getPathWithExtension, safeUnlink } = require('../../utils/fs');
15
+ const { getBundlerTarget } = require('./bundler_target');
16
+ const { getDynamicImportsPlugin } = require('./dynamic_imports/plugin');
17
+ const { getNativeModulesPlugin } = require('./native_modules/plugin');
18
+ // Maximum number of log messages that an esbuild instance will produce. This
19
+ // limit is important to avoid out-of-memory errors due to too much data being
20
+ // sent in the Go<>Node IPC channel.
21
+ const ESBUILD_LOG_LIMIT = 10;
22
+ // When resolving imports with no extension (e.g. require('./foo')), these are
23
+ // the extensions that esbuild will look for, in this order.
24
+ const RESOLVE_EXTENSIONS = ['.js', '.jsx', '.mjs', '.cjs', '.ts', '.json'];
25
+ // eslint-disable-next-line max-statements
26
+ const bundleJsFile = function ({ additionalModulePaths, basePath, config, externalModules = [], ignoredModules = [], name, srcDir, srcFile, }) {
27
+ return __awaiter(this, void 0, void 0, function* () {
28
+ // We use a temporary directory as the destination for esbuild files to avoid
29
+ // any naming conflicts with files generated by other functions.
30
+ const targetDirectory = yield tmpName();
31
+ // De-duping external and ignored modules.
32
+ const external = [...new Set([...externalModules, ...ignoredModules])];
33
+ // To be populated by the native modules plugin with the names, versions and
34
+ // paths of any Node modules with native dependencies.
35
+ const nativeNodeModules = {};
36
+ // To be populated by the dynamic imports plugin with the names of the Node
37
+ // modules that include imports with dynamic expressions.
38
+ const nodeModulesWithDynamicImports = new Set();
39
+ // To be populated by the dynamic imports plugin with any paths (in a glob
40
+ // format) to be included in the bundle in order to make a dynamic import
41
+ // work at runtime.
42
+ const dynamicImportsIncludedPaths = new Set();
43
+ // The list of esbuild plugins to enable for this build.
44
+ const plugins = [
45
+ getNativeModulesPlugin(nativeNodeModules),
46
+ getDynamicImportsPlugin({
47
+ basePath,
48
+ includedPaths: dynamicImportsIncludedPaths,
49
+ moduleNames: nodeModulesWithDynamicImports,
50
+ processImports: config.processDynamicNodeImports !== false,
51
+ srcDir,
52
+ }),
53
+ ];
54
+ // The version of ECMAScript to use as the build target. This will determine
55
+ // whether certain features are transpiled down or left untransformed.
56
+ const nodeTarget = getBundlerTarget(config.nodeVersion);
57
+ // esbuild will format `sources` relative to the sourcemap file, which lives
58
+ // in `destFolder`. We use `sourceRoot` to establish that relation. They are
59
+ // URLs, not paths, so even on Windows they should use forward slashes.
60
+ const sourceRoot = targetDirectory.replace(/\\/g, '/');
61
+ try {
62
+ const { metafile, warnings } = yield esbuild.build({
63
+ bundle: true,
64
+ entryPoints: [srcFile],
65
+ external,
66
+ logLevel: 'warning',
67
+ logLimit: ESBUILD_LOG_LIMIT,
68
+ metafile: true,
69
+ nodePaths: additionalModulePaths,
70
+ outdir: targetDirectory,
71
+ platform: 'node',
72
+ plugins,
73
+ resolveExtensions: RESOLVE_EXTENSIONS,
74
+ sourcemap: Boolean(config.nodeSourcemap),
75
+ sourceRoot,
76
+ target: [nodeTarget],
77
+ });
78
+ const bundlePaths = getBundlePaths({
79
+ destFolder: targetDirectory,
80
+ outputs: metafile.outputs,
81
+ srcFile,
82
+ });
83
+ const inputs = Object.keys(metafile.inputs).map((path) => resolve(path));
84
+ const cleanTempFiles = getCleanupFunction([...bundlePaths.keys()]);
85
+ return {
86
+ additionalPaths: [...dynamicImportsIncludedPaths],
87
+ bundlePaths,
88
+ cleanTempFiles,
89
+ inputs,
90
+ nativeNodeModules,
91
+ nodeModulesWithDynamicImports: [...nodeModulesWithDynamicImports],
92
+ warnings,
93
+ };
94
+ }
95
+ catch (error) {
96
+ error.customErrorInfo = {
97
+ type: 'functionsBundling',
98
+ location: { bundler: JS_BUNDLER_ESBUILD, functionName: name, runtime: RUNTIME_JS },
99
+ };
100
+ throw error;
101
+ }
102
+ });
103
+ };
104
+ // Takes the `outputs` object produced by esbuild and returns a Map with the
105
+ // absolute paths of the generated files as keys, and the paths that those
106
+ // files should take in the generated bundle as values. This is compatible
107
+ // with the `aliases` format used upstream.
108
+ const getBundlePaths = ({ destFolder, outputs, srcFile }) => {
109
+ const bundleFilename = `${basename(srcFile, extname(srcFile))}.js`;
110
+ const mainFileDirectory = dirname(srcFile);
111
+ const bundlePaths = new Map();
112
+ // The paths returned by esbuild are relative to the current directory, which
113
+ // is a problem on Windows if the target directory is in a different drive
114
+ // letter. To get around that, instead of using `path.resolve`, we compute
115
+ // the absolute path by joining `destFolder` with the `basename` of each
116
+ // entry of the `outputs` object.
117
+ Object.entries(outputs).forEach(([path, output]) => {
118
+ const filename = basename(path);
119
+ const extension = extname(path);
120
+ const absolutePath = join(destFolder, filename);
121
+ if (output.entryPoint && basename(output.entryPoint) === basename(srcFile)) {
122
+ // Ensuring the main file has a `.js` extension.
123
+ const normalizedSrcFile = getPathWithExtension(srcFile, '.js');
124
+ bundlePaths.set(absolutePath, normalizedSrcFile);
125
+ }
126
+ else if (extension === '.js' || filename === `${bundleFilename}.map`) {
127
+ bundlePaths.set(absolutePath, join(mainFileDirectory, filename));
128
+ }
129
+ });
130
+ return bundlePaths;
131
+ };
132
+ const getCleanupFunction = (paths) => () => __awaiter(this, void 0, void 0, function* () {
133
+ yield Promise.all(paths.filter(Boolean).map(safeUnlink));
134
+ });
135
+ module.exports = { bundleJsFile, ESBUILD_LOG_LIMIT };
@@ -0,0 +1 @@
1
+ export function getBundlerTarget(suppliedVersion: any): any;
@@ -0,0 +1,16 @@
1
+ const DEFAULT_VERSION = 'node12';
2
+ const versionMap = {
3
+ '8.x': 'node8',
4
+ '10.x': 'node10',
5
+ '12.x': 'node12',
6
+ '14.x': 'node14',
7
+ };
8
+ const getBundlerTarget = (suppliedVersion) => {
9
+ const version = normalizeVersion(suppliedVersion);
10
+ return versionMap[version] || DEFAULT_VERSION;
11
+ };
12
+ const normalizeVersion = (version) => {
13
+ const match = version && version.match(/^nodejs(.*)$/);
14
+ return match ? match[1] : version;
15
+ };
16
+ module.exports = { getBundlerTarget };
@@ -0,0 +1,3 @@
1
+ export function detectEsModule({ mainFile }: {
2
+ mainFile: any;
3
+ }): Promise<boolean>;
@@ -0,0 +1,28 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ const { readFile } = require('fs');
11
+ const { promisify } = require('util');
12
+ const pReadFile = promisify(readFile);
13
+ const { init, parse } = require('es-module-lexer');
14
+ const detectEsModule = ({ mainFile }) => __awaiter(this, void 0, void 0, function* () {
15
+ if (!mainFile) {
16
+ return false;
17
+ }
18
+ try {
19
+ const [mainFileContents] = yield Promise.all([pReadFile(mainFile, 'utf8'), init]);
20
+ const [imports, exports] = parse(mainFileContents);
21
+ return imports.length !== 0 || exports.length !== 0;
22
+ }
23
+ catch (_a) {
24
+ // If there are any problems with init or parsing, assume it's not an ES module
25
+ return false;
26
+ }
27
+ });
28
+ module.exports = { detectEsModule };
@@ -0,0 +1,8 @@
1
+ export function parseExpression({ basePath, expression: rawExpression, resolveDir }: {
2
+ basePath: any;
3
+ expression: any;
4
+ resolveDir: any;
5
+ }): {
6
+ includedPathsGlob: string;
7
+ type: any;
8
+ };
@@ -0,0 +1,135 @@
1
+ const { join, relative, resolve } = require('path');
2
+ const babel = require('@babel/parser');
3
+ const GLOB_WILDCARD = '**';
4
+ // Transforms an array of glob nodes into a glob string including an absolute
5
+ // path.
6
+ //
7
+ // Example: ["./files/", "*", ".json"] => "/home/ntl/files/*.json"
8
+ const getAbsoluteGlob = ({ basePath, globNodes, resolveDir }) => {
9
+ if (!validateGlobNodes(globNodes)) {
10
+ return null;
11
+ }
12
+ const globStarIndex = globNodes.indexOf(GLOB_WILDCARD);
13
+ const [staticPath, dynamicPath] = globStarIndex === -1
14
+ ? [globNodes.join(''), '']
15
+ : [globNodes.slice(0, globStarIndex).join(''), globNodes.slice(globStarIndex).join('')];
16
+ const absoluteStaticPath = resolve(resolveDir, staticPath);
17
+ const relativeStaticPath = relative(basePath, absoluteStaticPath);
18
+ const absoluteGlob = join(relativeStaticPath, dynamicPath);
19
+ return absoluteGlob;
20
+ };
21
+ // Returns GLOB_WILDCARD for AST nodes that are accepted as part of a dynamic
22
+ // expression and convertable to a wildcard character. This determines whether
23
+ // we convert an expression or leave it alone. For example:
24
+ //
25
+ // - `./files/${someVariable}`: Convert `someVariable` to GLOB_WILDCARD
26
+ // - `./files/${[some, array]}`: Don't convert expression
27
+ //
28
+ // The following AST nodes are converted to a wildcard:
29
+ //
30
+ // - CallExpression: `someFunction()`
31
+ // - ConditionalExpression: `someCond ? someValue : otherValue`
32
+ // - Identifier: `someVariable`
33
+ // - MemberExpression: `someArray[index]` or `someObject.property`
34
+ const getWildcardFromASTNode = (node) => {
35
+ switch (node.type) {
36
+ case 'CallExpression':
37
+ case 'ConditionalExpression':
38
+ case 'Identifier':
39
+ case 'MemberExpression':
40
+ return GLOB_WILDCARD;
41
+ default:
42
+ throw new Error('Expression member not supported');
43
+ }
44
+ };
45
+ // Tries to parse an expression, returning an object with:
46
+ // - `includedPathsGlob`: A glob with the files to be included in the bundle
47
+ // - `type`: The expression type (e.g. "require", "import")
48
+ const parseExpression = ({ basePath, expression: rawExpression, resolveDir }) => {
49
+ const { program } = babel.parse(rawExpression, {
50
+ sourceType: 'module',
51
+ });
52
+ const [topLevelExpression] = program.body;
53
+ const { expression } = topLevelExpression;
54
+ if (expression.type === 'CallExpression' && expression.callee.name === 'require') {
55
+ try {
56
+ const includedPathsGlob = parseRequire({ basePath, expression, resolveDir });
57
+ return {
58
+ includedPathsGlob,
59
+ type: expression.callee.name,
60
+ };
61
+ }
62
+ catch (_) {
63
+ // no-op
64
+ }
65
+ }
66
+ };
67
+ // Parses a `require()` and returns a glob string with an absolute path.
68
+ const parseRequire = ({ basePath, expression, resolveDir }) => {
69
+ const { arguments: args = [] } = expression;
70
+ const argType = args.length === 0 ? null : args[0].type;
71
+ if (argType === 'BinaryExpression') {
72
+ try {
73
+ const globNodes = parseBinaryExpression(args[0]);
74
+ return getAbsoluteGlob({ basePath, globNodes, resolveDir });
75
+ }
76
+ catch (_) {
77
+ // no-op
78
+ }
79
+ }
80
+ if (argType === 'TemplateLiteral') {
81
+ const globNodes = parseTemplateLiteral(args[0]);
82
+ return getAbsoluteGlob({ basePath, globNodes, resolveDir });
83
+ }
84
+ };
85
+ // Transforms a binary expression AST node into an array of glob nodes, where
86
+ // static parts will be left untouched and identifiers will be replaced by
87
+ // `GLOB_WILDCARD`.
88
+ //
89
+ // Example: './files/' + lang + '.json' => ["./files/", "**", ".json"]
90
+ const parseBinaryExpression = (expression) => {
91
+ const { left, operator, right } = expression;
92
+ if (operator !== '+') {
93
+ throw new Error('Expression operator not supported');
94
+ }
95
+ const operands = [left, right].flatMap((operand) => {
96
+ switch (operand.type) {
97
+ case 'BinaryExpression':
98
+ return parseBinaryExpression(operand);
99
+ case 'StringLiteral':
100
+ return operand.value;
101
+ default:
102
+ return getWildcardFromASTNode(operand);
103
+ }
104
+ });
105
+ return operands;
106
+ };
107
+ // Transforms a template literal AST node into an array of glob nodes, where
108
+ // static parts will be left untouched and identifiers will be replaced by
109
+ // `GLOB_WILDCARD`.
110
+ //
111
+ // Example: `./files/${lang}.json` => ["./files/", "**", ".json"]
112
+ const parseTemplateLiteral = (expression) => {
113
+ const { expressions, quasis } = expression;
114
+ const parts = [...expressions, ...quasis].sort((partA, partB) => partA.start - partB.start);
115
+ const globNodes = parts.map((part) => {
116
+ switch (part.type) {
117
+ case 'TemplateElement':
118
+ return part.value.cooked;
119
+ default:
120
+ return getWildcardFromASTNode(part);
121
+ }
122
+ });
123
+ return globNodes.filter(Boolean);
124
+ };
125
+ // For our purposes, we consider a glob to be valid if all the nodes are
126
+ // strings and the first node is static (i.e. not a wildcard character).
127
+ const validateGlobNodes = (globNodes) => {
128
+ if (!globNodes) {
129
+ return false;
130
+ }
131
+ const hasStrings = globNodes.every((node) => typeof node === 'string');
132
+ const hasStaticHead = globNodes[0] !== GLOB_WILDCARD;
133
+ return hasStrings && hasStaticHead;
134
+ };
135
+ module.exports = { parseExpression };
@@ -0,0 +1,10 @@
1
+ export function getDynamicImportsPlugin({ basePath, includedPaths, moduleNames, processImports, srcDir }: {
2
+ basePath: any;
3
+ includedPaths: any;
4
+ moduleNames: any;
5
+ processImports: any;
6
+ srcDir: any;
7
+ }): {
8
+ name: string;
9
+ setup(build: any): void;
10
+ };
@@ -0,0 +1,102 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ const { basename, join, relative } = require('path');
11
+ const findUp = require('find-up');
12
+ const readPackageJson = require('read-package-json-fast');
13
+ const unixify = require('unixify');
14
+ const { parseExpression } = require('./parser');
15
+ // This plugin intercepts module imports using dynamic expressions and does a
16
+ // couple of things with them. First of all, it figures out whether the call
17
+ // is being made from within a Node module, and if so it adds the name of the
18
+ // module to `moduleNames`, so that we can warn the user of potential runtime
19
+ // issues. Secondly, it parses the dynamic expressions and tries to include in
20
+ // the bundle all the files that are possibly needed to make the import work at
21
+ // runtime. This is not always possible, but we do our best.
22
+ const getDynamicImportsPlugin = ({ basePath, includedPaths, moduleNames, processImports, srcDir }) => ({
23
+ name: 'dynamic-imports',
24
+ setup(build) {
25
+ const cache = new Map();
26
+ // eslint-disable-next-line complexity
27
+ build.onDynamicImport({}, (args) => __awaiter(this, void 0, void 0, function* () {
28
+ const { expression, resolveDir } = args;
29
+ // Don't attempt to parse the expression if the base path isn't defined,
30
+ // since we won't be able to generate the globs for the included paths.
31
+ // Also don't parse the expression if we're not interested in processing
32
+ // the dynamic import expressions.
33
+ if (basePath && processImports) {
34
+ const { includedPathsGlob, type: expressionType } = parseExpression({ basePath, expression, resolveDir }) || {};
35
+ if (includedPathsGlob) {
36
+ // The parser has found a glob of paths that should be included in the
37
+ // bundle to make this import work, so we add it to `includedPaths`.
38
+ includedPaths.add(includedPathsGlob);
39
+ // Create the shim that will handle the import at runtime.
40
+ const contents = getShimContents({ expressionType, resolveDir, srcDir });
41
+ // This is the only branch where we actually solve a dynamic import.
42
+ // eslint-disable-next-line max-depth
43
+ if (contents) {
44
+ return {
45
+ contents,
46
+ };
47
+ }
48
+ }
49
+ }
50
+ // If we're here, it means we weren't able to solve the dynamic import.
51
+ // We add it to the list of modules with dynamic imports, which allows
52
+ // consumers like Netlify Build or CLI to advise users on how to proceed.
53
+ yield registerModuleWithDynamicImports({ cache, moduleNames, resolveDir, srcDir });
54
+ }));
55
+ },
56
+ });
57
+ const getPackageName = ({ resolveDir, srcDir }) => __awaiter(this, void 0, void 0, function* () {
58
+ const packageJsonPath = yield findUp((directory) => __awaiter(this, void 0, void 0, function* () {
59
+ // We stop traversing if we're about to leave the boundaries of the
60
+ // function directory or any node_modules directory.
61
+ if (directory === srcDir || basename(directory) === 'node_modules') {
62
+ return findUp.stop;
63
+ }
64
+ const path = join(directory, 'package.json');
65
+ const hasPackageJson = yield findUp.exists(path);
66
+ return hasPackageJson ? path : false;
67
+ }), { cwd: resolveDir });
68
+ if (packageJsonPath !== undefined) {
69
+ const { name } = yield readPackageJson(packageJsonPath);
70
+ return name;
71
+ }
72
+ });
73
+ const getPackageNameCached = ({ cache, resolveDir, srcDir }) => {
74
+ if (!cache.has(resolveDir)) {
75
+ cache.set(resolveDir, getPackageName({ resolveDir, srcDir }));
76
+ }
77
+ return cache.get(resolveDir);
78
+ };
79
+ const getShimContents = ({ expressionType, resolveDir, srcDir }) => {
80
+ // The shim needs to modify the path of the import, since originally it was
81
+ // relative to wherever the importer sat in the file tree (i.e. anywhere in
82
+ // the user space or inside `node_modules`), but at runtime paths must be
83
+ // relative to the main bundle file, since esbuild will flatten everything
84
+ // into a single file.
85
+ const relativeResolveDir = relative(srcDir, resolveDir);
86
+ const requireArg = relativeResolveDir ? `\`./${unixify(relativeResolveDir)}/$\{args}\`` : 'args';
87
+ if (expressionType === 'require') {
88
+ return `module.exports = args => require(${requireArg})`;
89
+ }
90
+ };
91
+ const registerModuleWithDynamicImports = ({ cache, moduleNames, resolveDir, srcDir }) => __awaiter(this, void 0, void 0, function* () {
92
+ try {
93
+ const packageName = yield getPackageNameCached({ cache, resolveDir, srcDir });
94
+ if (packageName !== undefined) {
95
+ moduleNames.add(packageName);
96
+ }
97
+ }
98
+ catch (_) {
99
+ // no-op
100
+ }
101
+ });
102
+ module.exports = { getDynamicImportsPlugin };
@@ -0,0 +1,12 @@
1
+ /// <reference types="node" />
2
+ export function findFunctionsInPaths({ paths }: {
3
+ paths: any;
4
+ }): Promise<any[]>;
5
+ export function getFunctionAtPath(srcPath: any): Promise<{
6
+ extension: string;
7
+ mainFile: any;
8
+ name: string;
9
+ srcDir: any;
10
+ srcPath: any;
11
+ stat: import("fs").Stats;
12
+ }>;
@@ -0,0 +1,82 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ const { lstat } = require('fs');
11
+ const { join, dirname, basename, extname } = require('path');
12
+ const { promisify } = require('util');
13
+ const locatePath = require('locate-path');
14
+ const pLstat = promisify(lstat);
15
+ // List of extensions that this runtime will look for, in order of precedence.
16
+ const allowedExtensions = ['.js', '.zip', '.cjs', '.mjs', '.ts'];
17
+ // Sorting function, compatible with the callback of Array.sort, which sorts
18
+ // entries by extension according to their position in `allowedExtensions`.
19
+ // It places extensions with a higher precedence last in the array, so that
20
+ // they "win" when the array is flattened into a Map.
21
+ const sortByExtension = (fA, fB) => {
22
+ const indexA = allowedExtensions.indexOf(fA.extension);
23
+ const indexB = allowedExtensions.indexOf(fB.extension);
24
+ return indexB - indexA;
25
+ };
26
+ const findFunctionsInPaths = function ({ paths }) {
27
+ return __awaiter(this, void 0, void 0, function* () {
28
+ const functions = yield Promise.all(paths.map(getFunctionAtPath));
29
+ // It's fine to mutate the array since its scope is local to this function.
30
+ const sortedFunctions = functions.filter(Boolean).sort((fA, fB) => {
31
+ // We first sort the functions array to put directories first. This is so
32
+ // that `{name}/{name}.js` takes precedence over `{name}.js`.
33
+ const directorySort = Number(fA.stat.isDirectory()) - Number(fB.stat.isDirectory());
34
+ if (directorySort !== 0) {
35
+ return directorySort;
36
+ }
37
+ // If the functions have the same name, we sort them according to the order
38
+ // defined in `allowedExtensions`.
39
+ if (fA.name === fB.name) {
40
+ return sortByExtension(fA, fB);
41
+ }
42
+ return 0;
43
+ });
44
+ return sortedFunctions;
45
+ });
46
+ };
47
+ const getFunctionAtPath = function (srcPath) {
48
+ return __awaiter(this, void 0, void 0, function* () {
49
+ const filename = basename(srcPath);
50
+ if (filename === 'node_modules') {
51
+ return;
52
+ }
53
+ const stat = yield pLstat(srcPath);
54
+ const mainFile = yield getMainFile(srcPath, filename, stat);
55
+ if (mainFile === undefined) {
56
+ return;
57
+ }
58
+ const extension = extname(srcPath);
59
+ const srcDir = stat.isDirectory() ? srcPath : dirname(srcPath);
60
+ const name = basename(srcPath, extname(srcPath));
61
+ return { extension, mainFile, name, srcDir, srcPath, stat };
62
+ });
63
+ };
64
+ // Each `srcPath` can also be a directory with an `index` file or a file using
65
+ // the same filename as its directory.
66
+ const getMainFile = function (srcPath, filename, stat) {
67
+ if (stat.isDirectory()) {
68
+ return locatePath([
69
+ join(srcPath, `${filename}.js`),
70
+ join(srcPath, 'index.js'),
71
+ join(srcPath, `${filename}.mjs`),
72
+ join(srcPath, 'index.mjs'),
73
+ join(srcPath, `${filename}.ts`),
74
+ join(srcPath, 'index.ts'),
75
+ ], { type: 'file' });
76
+ }
77
+ const extension = extname(srcPath);
78
+ if (allowedExtensions.includes(extension)) {
79
+ return srcPath;
80
+ }
81
+ };
82
+ module.exports = { findFunctionsInPaths, getFunctionAtPath };