@netlify/zip-it-and-ship-it 9.20.0 → 9.22.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/dist/main.d.ts +18 -12
- package/dist/main.js +18 -15
- package/dist/runtimes/node/bundlers/esbuild/bundler.js +2 -11
- package/dist/runtimes/node/bundlers/index.js +7 -5
- package/dist/runtimes/node/bundlers/nft/index.js +51 -29
- package/dist/runtimes/node/bundlers/nft/transpile.d.ts +5 -4
- package/dist/runtimes/node/bundlers/nft/transpile.js +16 -4
- package/dist/runtimes/node/in_source_config/index.d.ts +22 -5
- package/dist/runtimes/node/in_source_config/index.js +27 -20
- package/dist/runtimes/node/index.js +9 -6
- package/dist/runtimes/node/parser/exports.d.ts +13 -3
- package/dist/runtimes/node/parser/exports.js +80 -44
- package/dist/runtimes/node/parser/helpers.d.ts +1 -0
- package/dist/runtimes/node/parser/helpers.js +4 -0
- package/dist/runtimes/node/utils/esm_cjs_compat.d.ts +7 -0
- package/dist/runtimes/node/utils/esm_cjs_compat.js +15 -0
- package/dist/runtimes/node/utils/module_format.d.ts +2 -0
- package/dist/runtimes/node/utils/module_format.js +2 -0
- package/dist/runtimes/node/utils/zip.js +3 -66
- package/dist/runtimes/runtime.d.ts +4 -2
- package/dist/utils/format_result.js +4 -4
- package/package.json +6 -7
- package/dist/runtimes/node/utils/tsconfig.d.ts +0 -7
- package/dist/runtimes/node/utils/tsconfig.js +0 -38
package/dist/main.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Config } from './config.js';
|
|
2
2
|
import { FeatureFlags } from './feature_flags.js';
|
|
3
|
+
import { ModuleFormat } from './runtimes/node/utils/module_format.js';
|
|
3
4
|
import { RuntimeName } from './runtimes/runtime.js';
|
|
4
5
|
export { Config, FunctionConfig } from './config.js';
|
|
5
6
|
export { zipFunction, zipFunctions, ZipFunctionOptions, ZipFunctionsOptions } from './zip.js';
|
|
@@ -16,6 +17,7 @@ export interface ListedFunction {
|
|
|
16
17
|
schedule?: string;
|
|
17
18
|
displayName?: string;
|
|
18
19
|
generator?: string;
|
|
20
|
+
inputModuleFormat?: ModuleFormat;
|
|
19
21
|
}
|
|
20
22
|
type ListedFunctionFile = ListedFunction & {
|
|
21
23
|
srcFile: string;
|
|
@@ -27,16 +29,20 @@ interface ListFunctionsOptions {
|
|
|
27
29
|
featureFlags?: FeatureFlags;
|
|
28
30
|
parseISC?: boolean;
|
|
29
31
|
}
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
config?: Config
|
|
33
|
-
configFileDirectories?: string[]
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
32
|
+
interface ListFunctionsOptions {
|
|
33
|
+
basePath?: string;
|
|
34
|
+
config?: Config;
|
|
35
|
+
configFileDirectories?: string[];
|
|
36
|
+
featureFlags?: FeatureFlags;
|
|
37
|
+
parseISC?: boolean;
|
|
38
|
+
}
|
|
39
|
+
export declare const listFunctions: (relativeSrcFolders: string | string[], { featureFlags: inputFeatureFlags, config, configFileDirectories, parseISC }?: ListFunctionsOptions) => Promise<ListedFunction[]>;
|
|
40
|
+
interface ListFunctionOptions {
|
|
41
|
+
basePath?: string;
|
|
42
|
+
config?: Config;
|
|
43
|
+
configFileDirectories?: string[];
|
|
44
|
+
featureFlags?: FeatureFlags;
|
|
45
|
+
parseISC?: boolean;
|
|
46
|
+
}
|
|
47
|
+
export declare const listFunction: (path: string, { featureFlags: inputFeatureFlags, config, configFileDirectories, parseISC }?: ListFunctionOptions) => Promise<ListedFunction | undefined>;
|
|
42
48
|
export declare const listFunctionsFiles: (relativeSrcFolders: string | string[], { basePath, config, configFileDirectories, featureFlags: inputFeatureFlags, parseISC, }?: ListFunctionsOptions) => Promise<ListedFunctionFile[]>;
|
package/dist/main.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { extname } from 'path';
|
|
2
2
|
import { getFlags } from './feature_flags.js';
|
|
3
3
|
import { getFunctionFromPath, getFunctionsFromPaths } from './runtimes/index.js';
|
|
4
|
-
import {
|
|
4
|
+
import { parseFile } from './runtimes/node/in_source_config/index.js';
|
|
5
5
|
import { RUNTIME } from './runtimes/runtime.js';
|
|
6
6
|
import { RuntimeCache } from './utils/cache.js';
|
|
7
7
|
import { listFunctionsDirectories, resolveFunctionsDirectories } from './utils/fs.js';
|
|
@@ -11,38 +11,38 @@ export { ARCHIVE_FORMAT } from './archive.js';
|
|
|
11
11
|
export { NODE_BUNDLER } from './runtimes/node/bundlers/types.js';
|
|
12
12
|
export { RUNTIME } from './runtimes/runtime.js';
|
|
13
13
|
export { MODULE_FORMAT } from './runtimes/node/utils/module_format.js';
|
|
14
|
-
const
|
|
15
|
-
// ISC is currently only supported in JavaScript and TypeScript functions
|
|
16
|
-
// and only supports scheduled functions.
|
|
14
|
+
const augmentWithStaticAnalysis = async (func) => {
|
|
17
15
|
if (func.runtime.name !== RUNTIME.JAVASCRIPT) {
|
|
18
16
|
return func;
|
|
19
17
|
}
|
|
20
|
-
const
|
|
18
|
+
const staticAnalysisResult = await parseFile(func.mainFile, {
|
|
21
19
|
functionName: func.name,
|
|
22
20
|
logger: getLogger(),
|
|
23
21
|
});
|
|
24
|
-
return { ...func,
|
|
22
|
+
return { ...func, staticAnalysisResult };
|
|
25
23
|
};
|
|
26
24
|
// List all Netlify Functions main entry files for a specific directory
|
|
27
|
-
export const listFunctions = async function (relativeSrcFolders, { featureFlags: inputFeatureFlags, config, configFileDirectories, parseISC = false
|
|
25
|
+
export const listFunctions = async function (relativeSrcFolders, { featureFlags: inputFeatureFlags, config, configFileDirectories, parseISC = false } = {}) {
|
|
28
26
|
const featureFlags = getFlags(inputFeatureFlags);
|
|
29
27
|
const srcFolders = resolveFunctionsDirectories(relativeSrcFolders);
|
|
30
28
|
const paths = await listFunctionsDirectories(srcFolders);
|
|
31
29
|
const cache = new RuntimeCache();
|
|
32
30
|
const functionsMap = await getFunctionsFromPaths(paths, { cache, config, configFileDirectories, featureFlags });
|
|
33
31
|
const functions = [...functionsMap.values()];
|
|
34
|
-
const augmentedFunctions = parseISC
|
|
32
|
+
const augmentedFunctions = parseISC
|
|
33
|
+
? await Promise.all(functions.map((func) => augmentWithStaticAnalysis(func)))
|
|
34
|
+
: functions;
|
|
35
35
|
return augmentedFunctions.map(getListedFunction);
|
|
36
36
|
};
|
|
37
37
|
// Finds a function at a specific path.
|
|
38
|
-
export const listFunction = async function (path, { featureFlags: inputFeatureFlags, config, configFileDirectories, parseISC = false
|
|
38
|
+
export const listFunction = async function (path, { featureFlags: inputFeatureFlags, config, configFileDirectories, parseISC = false } = {}) {
|
|
39
39
|
const featureFlags = getFlags(inputFeatureFlags);
|
|
40
40
|
const cache = new RuntimeCache();
|
|
41
41
|
const func = await getFunctionFromPath(path, { cache, config, configFileDirectories, featureFlags });
|
|
42
42
|
if (!func) {
|
|
43
43
|
return;
|
|
44
44
|
}
|
|
45
|
-
const augmentedFunction = parseISC ? await
|
|
45
|
+
const augmentedFunction = parseISC ? await augmentWithStaticAnalysis(func) : func;
|
|
46
46
|
return getListedFunction(augmentedFunction);
|
|
47
47
|
};
|
|
48
48
|
// List all Netlify Functions files for a specific directory
|
|
@@ -53,11 +53,13 @@ export const listFunctionsFiles = async function (relativeSrcFolders, { basePath
|
|
|
53
53
|
const cache = new RuntimeCache();
|
|
54
54
|
const functionsMap = await getFunctionsFromPaths(paths, { cache, config, configFileDirectories, featureFlags });
|
|
55
55
|
const functions = [...functionsMap.values()];
|
|
56
|
-
const augmentedFunctions = parseISC
|
|
56
|
+
const augmentedFunctions = parseISC
|
|
57
|
+
? await Promise.all(functions.map((func) => augmentWithStaticAnalysis(func)))
|
|
58
|
+
: functions;
|
|
57
59
|
const listedFunctionsFiles = await Promise.all(augmentedFunctions.map((func) => getListedFunctionFiles(func, { basePath, featureFlags })));
|
|
58
60
|
return listedFunctionsFiles.flat();
|
|
59
61
|
};
|
|
60
|
-
const getListedFunction = function ({ config, extension,
|
|
62
|
+
const getListedFunction = function ({ config, extension, staticAnalysisResult, mainFile, name, runtime, }) {
|
|
61
63
|
return {
|
|
62
64
|
displayName: config.name,
|
|
63
65
|
extension,
|
|
@@ -65,15 +67,16 @@ const getListedFunction = function ({ config, extension, inSourceConfig, mainFil
|
|
|
65
67
|
mainFile,
|
|
66
68
|
name,
|
|
67
69
|
runtime: runtime.name,
|
|
68
|
-
runtimeAPIVersion:
|
|
69
|
-
schedule:
|
|
70
|
+
runtimeAPIVersion: staticAnalysisResult ? staticAnalysisResult?.runtimeAPIVersion ?? 1 : undefined,
|
|
71
|
+
schedule: staticAnalysisResult?.schedule ?? config.schedule,
|
|
72
|
+
inputModuleFormat: staticAnalysisResult?.inputModuleFormat,
|
|
70
73
|
};
|
|
71
74
|
};
|
|
72
75
|
const getListedFunctionFiles = async function (func, options) {
|
|
73
76
|
const srcFiles = await getSrcFiles({
|
|
74
77
|
...func,
|
|
75
78
|
...options,
|
|
76
|
-
runtimeAPIVersion: func.
|
|
79
|
+
runtimeAPIVersion: func.staticAnalysisResult?.runtimeAPIVersion ?? 1,
|
|
77
80
|
});
|
|
78
81
|
return srcFiles.map((srcFile) => ({ ...getListedFunction(func), srcFile, extension: extname(srcFile) }));
|
|
79
82
|
};
|
|
@@ -6,6 +6,7 @@ import { FunctionBundlingUserError } from '../../../../utils/error.js';
|
|
|
6
6
|
import { getPathWithExtension, safeUnlink } from '../../../../utils/fs.js';
|
|
7
7
|
import { glob } from '../../../../utils/matching.js';
|
|
8
8
|
import { RUNTIME } from '../../../runtime.js';
|
|
9
|
+
import { CJS_SHIM } from '../../utils/esm_cjs_compat.js';
|
|
9
10
|
import { getFileExtensionForFormat, MODULE_FORMAT } from '../../utils/module_format.js';
|
|
10
11
|
import { NODE_BUNDLER } from '../types.js';
|
|
11
12
|
import { getBundlerTarget, getModuleFormat } from './bundler_target.js';
|
|
@@ -88,19 +89,9 @@ export const bundleJsFile = async function ({ additionalModulePaths, config, ext
|
|
|
88
89
|
});
|
|
89
90
|
// The extension of the output file.
|
|
90
91
|
const outputExtension = getFileExtensionForFormat(moduleFormat, featureFlags, runtimeAPIVersion);
|
|
91
|
-
// We add this banner so that calls to require() still work in ESM modules, especially when importing node built-ins
|
|
92
|
-
// We have to do this until this is fixed in esbuild: https://github.com/evanw/esbuild/pull/2067
|
|
93
|
-
const esmJSBanner = `
|
|
94
|
-
import {createRequire as ___nfyCreateRequire} from "module";
|
|
95
|
-
import {fileURLToPath as ___nfyFileURLToPath} from "url";
|
|
96
|
-
import {dirname as ___nfyPathDirname} from "path";
|
|
97
|
-
let __filename=___nfyFileURLToPath(import.meta.url);
|
|
98
|
-
let __dirname=___nfyPathDirname(___nfyFileURLToPath(import.meta.url));
|
|
99
|
-
let require=___nfyCreateRequire(import.meta.url);
|
|
100
|
-
`;
|
|
101
92
|
try {
|
|
102
93
|
const { metafile = { inputs: {}, outputs: {} }, warnings } = await build({
|
|
103
|
-
banner: moduleFormat === MODULE_FORMAT.ESM ? { js:
|
|
94
|
+
banner: moduleFormat === MODULE_FORMAT.ESM ? { js: CJS_SHIM } : undefined,
|
|
104
95
|
bundle: true,
|
|
105
96
|
entryPoints: [srcFile],
|
|
106
97
|
external,
|
|
@@ -22,18 +22,20 @@ export const getBundler = (name) => {
|
|
|
22
22
|
}
|
|
23
23
|
};
|
|
24
24
|
export const getBundlerName = async ({ config: { nodeBundler }, extension, featureFlags, mainFile, runtimeAPIVersion, }) => {
|
|
25
|
+
// For V2 functions, we force the bundler to NFT. The only exception is when
|
|
26
|
+
// a `none` override was provided.
|
|
27
|
+
if (runtimeAPIVersion === 2) {
|
|
28
|
+
return nodeBundler === NODE_BUNDLER.NONE ? NODE_BUNDLER.NONE : NODE_BUNDLER.NFT;
|
|
29
|
+
}
|
|
25
30
|
if (nodeBundler) {
|
|
26
31
|
return nodeBundler;
|
|
27
32
|
}
|
|
28
|
-
return await getDefaultBundler({ extension, featureFlags, mainFile
|
|
33
|
+
return await getDefaultBundler({ extension, featureFlags, mainFile });
|
|
29
34
|
};
|
|
30
35
|
const ESBUILD_EXTENSIONS = new Set(['.mjs', '.ts', '.tsx', '.cts', '.mts']);
|
|
31
36
|
// We use ZISI as the default bundler, except for certain extensions, for which
|
|
32
37
|
// esbuild is the only option.
|
|
33
|
-
const getDefaultBundler = async ({ extension, featureFlags, mainFile,
|
|
34
|
-
if (runtimeAPIVersion === 2) {
|
|
35
|
-
return NODE_BUNDLER.NFT;
|
|
36
|
-
}
|
|
38
|
+
const getDefaultBundler = async ({ extension, featureFlags, mainFile, }) => {
|
|
37
39
|
if (extension === MODULE_FILE_EXTENSION.MJS && featureFlags.zisi_pure_esm_mjs) {
|
|
38
40
|
return NODE_BUNDLER.NFT;
|
|
39
41
|
}
|
|
@@ -8,14 +8,13 @@ import { filterExcludedPaths, getPathsOfIncludedFiles } from '../../utils/includ
|
|
|
8
8
|
import { MODULE_FORMAT, MODULE_FILE_EXTENSION, tsExtensions } from '../../utils/module_format.js';
|
|
9
9
|
import { getNodeSupportMatrix } from '../../utils/node_version.js';
|
|
10
10
|
import { getClosestPackageJson } from '../../utils/package_json.js';
|
|
11
|
-
import { getModuleFormat as getModuleFormatFromTsConfig } from '../../utils/tsconfig.js';
|
|
12
11
|
import { processESM } from './es_modules.js';
|
|
13
12
|
import { transpileTS } from './transpile.js';
|
|
14
13
|
const appearsToBeModuleName = (name) => !name.startsWith('.');
|
|
15
14
|
const bundle = async ({ basePath, cache, config, featureFlags, mainFile, name, pluginsModulesPath, repositoryRoot = basePath, runtimeAPIVersion, }) => {
|
|
16
15
|
const { includedFiles = [], includedFilesBasePath } = config;
|
|
17
16
|
const { excludePatterns, paths: includedFilePaths } = await getPathsOfIncludedFiles(includedFiles, includedFilesBasePath || basePath);
|
|
18
|
-
const { aliases, mainFile: normalizedMainFile, moduleFormat,
|
|
17
|
+
const { aliases, bundledPaths = [], mainFile: normalizedMainFile, moduleFormat, rewrites, tracedPaths, } = await traceFilesAndTranspile({
|
|
19
18
|
basePath: repositoryRoot,
|
|
20
19
|
cache,
|
|
21
20
|
config,
|
|
@@ -27,15 +26,18 @@ const bundle = async ({ basePath, cache, config, featureFlags, mainFile, name, p
|
|
|
27
26
|
runtimeAPIVersion,
|
|
28
27
|
});
|
|
29
28
|
const includedPaths = filterExcludedPaths(includedFilePaths, excludePatterns);
|
|
30
|
-
const filteredIncludedPaths = [...filterExcludedPaths(
|
|
29
|
+
const filteredIncludedPaths = [...filterExcludedPaths(tracedPaths, excludePatterns), ...includedPaths];
|
|
31
30
|
const dirnames = filteredIncludedPaths.map((filePath) => normalize(dirname(filePath))).sort();
|
|
32
31
|
// Sorting the array to make the checksum deterministic.
|
|
33
32
|
const srcFiles = [...filteredIncludedPaths].sort();
|
|
33
|
+
// The inputs are the union of any traced paths (included as files in the end
|
|
34
|
+
// result) and any bundled paths (merged together in the bundle).
|
|
35
|
+
const inputs = bundledPaths.length === 0 ? tracedPaths : [...new Set([...tracedPaths, ...bundledPaths])];
|
|
34
36
|
return {
|
|
35
37
|
aliases,
|
|
36
38
|
basePath: getBasePath(dirnames),
|
|
37
39
|
includedFiles: includedPaths,
|
|
38
|
-
inputs
|
|
40
|
+
inputs,
|
|
39
41
|
mainFile: normalizedMainFile,
|
|
40
42
|
moduleFormat,
|
|
41
43
|
rewrites,
|
|
@@ -55,11 +57,17 @@ const getIgnoreFunction = (config) => {
|
|
|
55
57
|
* Returns the module format that should be used when transpiling a TypeScript
|
|
56
58
|
* file.
|
|
57
59
|
*/
|
|
58
|
-
const getTSModuleFormat = async (mainFile, repositoryRoot) => {
|
|
59
|
-
|
|
60
|
-
//
|
|
61
|
-
|
|
62
|
-
|
|
60
|
+
const getTSModuleFormat = async (mainFile, runtimeAPIVersion, repositoryRoot) => {
|
|
61
|
+
// TODO: This check should go away. We should always respect the format from
|
|
62
|
+
// the extension. We'll do this at a later stage, after we roll out the V2
|
|
63
|
+
// API with no side-effects on V1 functions.
|
|
64
|
+
if (runtimeAPIVersion === 2) {
|
|
65
|
+
if (extname(mainFile) === MODULE_FILE_EXTENSION.MTS) {
|
|
66
|
+
return MODULE_FORMAT.ESM;
|
|
67
|
+
}
|
|
68
|
+
if (extname(mainFile) === MODULE_FILE_EXTENSION.CTS) {
|
|
69
|
+
return MODULE_FORMAT.COMMONJS;
|
|
70
|
+
}
|
|
63
71
|
}
|
|
64
72
|
// At this point, we need to infer the module type from the `type` field in
|
|
65
73
|
// the closest `package.json`.
|
|
@@ -79,25 +87,28 @@ const getTypeScriptTransformer = async (runtimeAPIVersion, mainFile, repositoryR
|
|
|
79
87
|
if (!isTypeScript) {
|
|
80
88
|
return;
|
|
81
89
|
}
|
|
90
|
+
const format = await getTSModuleFormat(mainFile, runtimeAPIVersion, repositoryRoot);
|
|
82
91
|
const aliases = new Map();
|
|
83
92
|
const rewrites = new Map();
|
|
84
|
-
|
|
93
|
+
const transformer = {
|
|
94
|
+
aliases,
|
|
95
|
+
format,
|
|
96
|
+
rewrites,
|
|
97
|
+
};
|
|
85
98
|
if (runtimeAPIVersion === 2) {
|
|
99
|
+
// For V2 functions, we want to emit a main file with an unambiguous
|
|
100
|
+
// extension (i.e. `.cjs` or `.mjs`), so that the file is loaded with
|
|
101
|
+
// the correct format regardless of what is set in `package.json`.
|
|
102
|
+
const newExtension = format === MODULE_FORMAT.COMMONJS ? MODULE_FILE_EXTENSION.CJS : MODULE_FILE_EXTENSION.MJS;
|
|
103
|
+
const newMainFile = getPathWithExtension(mainFile, newExtension);
|
|
86
104
|
return {
|
|
87
|
-
|
|
105
|
+
...transformer,
|
|
88
106
|
bundle: true,
|
|
89
|
-
|
|
90
|
-
|
|
107
|
+
bundledPaths: [],
|
|
108
|
+
newMainFile,
|
|
91
109
|
};
|
|
92
110
|
}
|
|
93
|
-
|
|
94
|
-
// in `tsconfig.json` and `package.json`.
|
|
95
|
-
const format = await getTSModuleFormat(mainFile, repositoryRoot);
|
|
96
|
-
return {
|
|
97
|
-
aliases,
|
|
98
|
-
format,
|
|
99
|
-
rewrites,
|
|
100
|
-
};
|
|
111
|
+
return transformer;
|
|
101
112
|
};
|
|
102
113
|
const traceFilesAndTranspile = async function ({ basePath, cache, config, featureFlags, mainFile, pluginsModulesPath, name, repositoryRoot, runtimeAPIVersion, }) {
|
|
103
114
|
const tsTransformer = await getTypeScriptTransformer(runtimeAPIVersion, mainFile, repositoryRoot);
|
|
@@ -111,19 +122,29 @@ const traceFilesAndTranspile = async function ({ basePath, cache, config, featur
|
|
|
111
122
|
try {
|
|
112
123
|
const extension = extname(path);
|
|
113
124
|
if (tsExtensions.has(extension)) {
|
|
114
|
-
const
|
|
125
|
+
const { bundledPaths, transpiled } = await transpileTS({
|
|
115
126
|
bundle: tsTransformer?.bundle,
|
|
116
127
|
config,
|
|
117
128
|
name,
|
|
118
129
|
format: tsTransformer?.format,
|
|
119
130
|
path,
|
|
120
131
|
});
|
|
121
|
-
const
|
|
132
|
+
const isMainFile = path === mainFile;
|
|
133
|
+
// If this is the main file, the final path of the compiled file may
|
|
134
|
+
// have been set by the transformer. It's fine to do this, since the
|
|
135
|
+
// only place where this file will be imported from is our entry file
|
|
136
|
+
// and we'll know the right path to use.
|
|
137
|
+
const newPath = isMainFile && tsTransformer?.newMainFile
|
|
138
|
+
? tsTransformer.newMainFile
|
|
139
|
+
: getPathWithExtension(path, MODULE_FILE_EXTENSION.JS);
|
|
122
140
|
// Overriding the contents of the `.ts` file.
|
|
123
|
-
tsTransformer?.rewrites.set(path,
|
|
141
|
+
tsTransformer?.rewrites.set(path, transpiled);
|
|
124
142
|
// Rewriting the `.ts` path to `.js` in the bundle.
|
|
125
143
|
tsTransformer?.aliases.set(path, newPath);
|
|
126
|
-
|
|
144
|
+
// Registering the input files that were bundled into the transpiled
|
|
145
|
+
// file.
|
|
146
|
+
tsTransformer?.bundledPaths?.push(...bundledPaths);
|
|
147
|
+
return transpiled;
|
|
127
148
|
}
|
|
128
149
|
return await cachedReadFile(cache.fileCache, path);
|
|
129
150
|
}
|
|
@@ -150,14 +171,15 @@ const traceFilesAndTranspile = async function ({ basePath, cache, config, featur
|
|
|
150
171
|
}
|
|
151
172
|
},
|
|
152
173
|
});
|
|
153
|
-
const
|
|
174
|
+
const normalizedTracedPaths = [...dependencyPaths].map((path) => (basePath ? resolve(basePath, path) : resolve(path)));
|
|
154
175
|
if (tsTransformer) {
|
|
155
176
|
return {
|
|
156
177
|
aliases: tsTransformer.aliases,
|
|
157
|
-
|
|
178
|
+
bundledPaths: tsTransformer.bundledPaths,
|
|
179
|
+
mainFile: tsTransformer.newMainFile ?? getPathWithExtension(mainFile, MODULE_FILE_EXTENSION.JS),
|
|
158
180
|
moduleFormat: tsTransformer.format,
|
|
159
|
-
paths: normalizedDependencyPaths,
|
|
160
181
|
rewrites: tsTransformer.rewrites,
|
|
182
|
+
tracedPaths: normalizedTracedPaths,
|
|
161
183
|
};
|
|
162
184
|
}
|
|
163
185
|
const { moduleFormat, rewrites } = await processESM({
|
|
@@ -174,8 +196,8 @@ const traceFilesAndTranspile = async function ({ basePath, cache, config, featur
|
|
|
174
196
|
return {
|
|
175
197
|
mainFile,
|
|
176
198
|
moduleFormat,
|
|
177
|
-
paths: normalizedDependencyPaths,
|
|
178
199
|
rewrites,
|
|
200
|
+
tracedPaths: normalizedTracedPaths,
|
|
179
201
|
};
|
|
180
202
|
};
|
|
181
203
|
const getSrcFiles = async function ({ basePath, config, mainFile }) {
|
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
import type { FunctionConfig } from '../../../../config.js';
|
|
2
2
|
import { ModuleFormat } from '../../utils/module_format.js';
|
|
3
|
-
import type { TsConfig } from '../../utils/tsconfig.js';
|
|
4
3
|
interface TranspileESMToCJSOptions {
|
|
5
4
|
config: FunctionConfig;
|
|
6
5
|
name: string;
|
|
7
6
|
path: string;
|
|
8
|
-
tsConfig?: TsConfig;
|
|
9
7
|
}
|
|
10
|
-
export declare const transpileESMToCJS: ({ config, name, path
|
|
8
|
+
export declare const transpileESMToCJS: ({ config, name, path }: TranspileESMToCJSOptions) => Promise<string>;
|
|
11
9
|
interface TranspileTSOptions {
|
|
12
10
|
bundle?: boolean;
|
|
13
11
|
config: FunctionConfig;
|
|
@@ -15,5 +13,8 @@ interface TranspileTSOptions {
|
|
|
15
13
|
name: string;
|
|
16
14
|
path: string;
|
|
17
15
|
}
|
|
18
|
-
export declare const transpileTS: ({ bundle, config, format, name, path }: TranspileTSOptions) => Promise<
|
|
16
|
+
export declare const transpileTS: ({ bundle, config, format, name, path }: TranspileTSOptions) => Promise<{
|
|
17
|
+
bundledPaths: string[];
|
|
18
|
+
transpiled: string;
|
|
19
|
+
}>;
|
|
19
20
|
export {};
|
|
@@ -1,10 +1,12 @@
|
|
|
1
|
+
import { resolve } from 'path';
|
|
1
2
|
import { build } from 'esbuild';
|
|
2
3
|
import { FunctionBundlingUserError } from '../../../../utils/error.js';
|
|
3
4
|
import { RUNTIME } from '../../../runtime.js';
|
|
5
|
+
import { CJS_SHIM } from '../../utils/esm_cjs_compat.js';
|
|
4
6
|
import { MODULE_FORMAT } from '../../utils/module_format.js';
|
|
5
7
|
import { getBundlerTarget } from '../esbuild/bundler_target.js';
|
|
6
8
|
import { NODE_BUNDLER } from '../types.js';
|
|
7
|
-
export const transpileESMToCJS = async ({ config, name, path
|
|
9
|
+
export const transpileESMToCJS = async ({ config, name, path }) => {
|
|
8
10
|
// The version of ECMAScript to use as the build target. This will determine
|
|
9
11
|
// whether certain features are transpiled down or left untransformed.
|
|
10
12
|
const nodeTarget = getBundlerTarget(config.nodeVersion);
|
|
@@ -17,7 +19,6 @@ export const transpileESMToCJS = async ({ config, name, path, tsConfig }) => {
|
|
|
17
19
|
platform: 'node',
|
|
18
20
|
sourcemap: Boolean(config.nodeSourcemap),
|
|
19
21
|
target: [nodeTarget],
|
|
20
|
-
tsconfigRaw: tsConfig ? JSON.stringify(tsConfig) : undefined,
|
|
21
22
|
write: false,
|
|
22
23
|
});
|
|
23
24
|
return transpiled.outputFiles[0].text;
|
|
@@ -34,19 +35,30 @@ export const transpileTS = async ({ bundle = false, config, format, name, path }
|
|
|
34
35
|
// The version of ECMAScript to use as the build target. This will determine
|
|
35
36
|
// whether certain features are transpiled down or left untransformed.
|
|
36
37
|
const nodeTarget = getBundlerTarget(config.nodeVersion);
|
|
37
|
-
const bundleOptions =
|
|
38
|
+
const bundleOptions = {
|
|
39
|
+
bundle: false,
|
|
40
|
+
};
|
|
41
|
+
if (bundle) {
|
|
42
|
+
bundleOptions.bundle = true;
|
|
43
|
+
bundleOptions.packages = 'external';
|
|
44
|
+
if (format === MODULE_FORMAT.ESM) {
|
|
45
|
+
bundleOptions.banner = { js: CJS_SHIM };
|
|
46
|
+
}
|
|
47
|
+
}
|
|
38
48
|
try {
|
|
39
49
|
const transpiled = await build({
|
|
40
50
|
...bundleOptions,
|
|
41
51
|
entryPoints: [path],
|
|
42
52
|
format,
|
|
43
53
|
logLevel: 'error',
|
|
54
|
+
metafile: true,
|
|
44
55
|
platform: 'node',
|
|
45
56
|
sourcemap: Boolean(config.nodeSourcemap),
|
|
46
57
|
target: [nodeTarget],
|
|
47
58
|
write: false,
|
|
48
59
|
});
|
|
49
|
-
|
|
60
|
+
const bundledPaths = bundle ? Object.keys(transpiled.metafile.inputs).map((inputPath) => resolve(inputPath)) : [];
|
|
61
|
+
return { bundledPaths, transpiled: transpiled.outputFiles[0].text };
|
|
50
62
|
}
|
|
51
63
|
catch (error) {
|
|
52
64
|
throw FunctionBundlingUserError.addCustomErrorInfo(error, {
|
|
@@ -2,28 +2,45 @@ import type { ArgumentPlaceholder, Expression, SpreadElement, JSXNamespacedName
|
|
|
2
2
|
import { InvocationMode } from '../../../function.js';
|
|
3
3
|
import { Logger } from '../../../utils/logger.js';
|
|
4
4
|
import { Route } from '../../../utils/routes.js';
|
|
5
|
+
import type { ModuleFormat } from '../utils/module_format.js';
|
|
5
6
|
export declare const IN_SOURCE_CONFIG_MODULE = "@netlify/functions";
|
|
6
7
|
export type ISCValues = {
|
|
7
|
-
invocationMode?: InvocationMode;
|
|
8
8
|
routes?: Route[];
|
|
9
|
-
runtimeAPIVersion?: number;
|
|
10
9
|
schedule?: string;
|
|
11
10
|
methods?: string[];
|
|
12
11
|
};
|
|
12
|
+
export interface StaticAnalysisResult extends ISCValues {
|
|
13
|
+
inputModuleFormat?: ModuleFormat;
|
|
14
|
+
invocationMode?: InvocationMode;
|
|
15
|
+
runtimeAPIVersion?: number;
|
|
16
|
+
}
|
|
13
17
|
interface FindISCDeclarationsOptions {
|
|
14
18
|
functionName: string;
|
|
15
19
|
logger: Logger;
|
|
16
20
|
}
|
|
17
|
-
|
|
18
|
-
|
|
21
|
+
/**
|
|
22
|
+
* Loads a file at a given path, parses it into an AST, and returns a series of
|
|
23
|
+
* data points, such as in-source configuration properties and other metadata.
|
|
24
|
+
*/
|
|
25
|
+
export declare const parseFile: (sourcePath: string, { functionName, logger }: FindISCDeclarationsOptions) => Promise<StaticAnalysisResult>;
|
|
26
|
+
/**
|
|
27
|
+
* Takes a JS/TS source as a string, parses it into an AST, and returns a
|
|
28
|
+
* series of data points, such as in-source configuration properties and
|
|
29
|
+
* other metadata.
|
|
30
|
+
*/
|
|
31
|
+
export declare const parseSource: (source: string, { functionName, logger }: FindISCDeclarationsOptions) => StaticAnalysisResult;
|
|
19
32
|
export type ISCHandlerArg = ArgumentPlaceholder | Expression | SpreadElement | JSXNamespacedName;
|
|
20
33
|
export type ISCExportWithCallExpression = {
|
|
21
34
|
type: 'call-expression';
|
|
22
35
|
args: ISCHandlerArg[];
|
|
23
36
|
local: string;
|
|
24
37
|
};
|
|
38
|
+
export type ISCExportWithObject = {
|
|
39
|
+
type: 'object-expression';
|
|
40
|
+
object: Record<string, unknown>;
|
|
41
|
+
};
|
|
25
42
|
export type ISCExportOther = {
|
|
26
43
|
type: 'other';
|
|
27
44
|
};
|
|
28
|
-
export type ISCExport = ISCExportWithCallExpression | ISCExportOther;
|
|
45
|
+
export type ISCExport = ISCExportWithCallExpression | ISCExportWithObject | ISCExportOther;
|
|
29
46
|
export {};
|
|
@@ -5,7 +5,7 @@ import { getRoutes } from '../../../utils/routes.js';
|
|
|
5
5
|
import { RUNTIME } from '../../runtime.js';
|
|
6
6
|
import { NODE_BUNDLER } from '../bundlers/types.js';
|
|
7
7
|
import { createBindingsMethod } from '../parser/bindings.js';
|
|
8
|
-
import {
|
|
8
|
+
import { traverseNodes } from '../parser/exports.js';
|
|
9
9
|
import { getImports } from '../parser/imports.js';
|
|
10
10
|
import { safelyParseSource, safelyReadSource } from '../parser/index.js';
|
|
11
11
|
import { parse as parseSchedule } from './properties/schedule.js';
|
|
@@ -18,16 +18,6 @@ const validateScheduleFunction = (functionFound, scheduleFound, functionName) =>
|
|
|
18
18
|
throw new FunctionBundlingUserError('Unable to find cron expression for scheduled function. The cron expression (first argument) for the `schedule` helper needs to be accessible inside the file and cannot be imported.', { functionName, runtime: RUNTIME.JAVASCRIPT });
|
|
19
19
|
}
|
|
20
20
|
};
|
|
21
|
-
// Parses a JS/TS file and looks for in-source config declarations. It returns
|
|
22
|
-
// an array of all declarations found, with `property` indicating the name of
|
|
23
|
-
// the property and `data` its value.
|
|
24
|
-
export const findISCDeclarationsInPath = async (sourcePath, { functionName, logger }) => {
|
|
25
|
-
const source = await safelyReadSource(sourcePath);
|
|
26
|
-
if (source === null) {
|
|
27
|
-
return {};
|
|
28
|
-
}
|
|
29
|
-
return findISCDeclarations(source, { functionName, logger });
|
|
30
|
-
};
|
|
31
21
|
/**
|
|
32
22
|
* Normalizes method names into arrays of uppercase strings.
|
|
33
23
|
* (e.g. "get" becomes ["GET"])
|
|
@@ -45,7 +35,23 @@ const normalizeMethods = (input, name) => {
|
|
|
45
35
|
return method.toUpperCase();
|
|
46
36
|
});
|
|
47
37
|
};
|
|
48
|
-
|
|
38
|
+
/**
|
|
39
|
+
* Loads a file at a given path, parses it into an AST, and returns a series of
|
|
40
|
+
* data points, such as in-source configuration properties and other metadata.
|
|
41
|
+
*/
|
|
42
|
+
export const parseFile = async (sourcePath, { functionName, logger }) => {
|
|
43
|
+
const source = await safelyReadSource(sourcePath);
|
|
44
|
+
if (source === null) {
|
|
45
|
+
return {};
|
|
46
|
+
}
|
|
47
|
+
return parseSource(source, { functionName, logger });
|
|
48
|
+
};
|
|
49
|
+
/**
|
|
50
|
+
* Takes a JS/TS source as a string, parses it into an AST, and returns a
|
|
51
|
+
* series of data points, such as in-source configuration properties and
|
|
52
|
+
* other metadata.
|
|
53
|
+
*/
|
|
54
|
+
export const parseSource = (source, { functionName, logger }) => {
|
|
49
55
|
const ast = safelyParseSource(source);
|
|
50
56
|
if (ast === null) {
|
|
51
57
|
return {};
|
|
@@ -55,21 +61,22 @@ export const findISCDeclarations = (source, { functionName, logger }) => {
|
|
|
55
61
|
let scheduledFunctionFound = false;
|
|
56
62
|
let scheduleFound = false;
|
|
57
63
|
const getAllBindings = createBindingsMethod(ast.body);
|
|
58
|
-
const { configExport,
|
|
59
|
-
const isV2API = handlerExports.length === 0 &&
|
|
64
|
+
const { configExport, handlerExports, hasDefaultExport, inputModuleFormat } = traverseNodes(ast.body, getAllBindings);
|
|
65
|
+
const isV2API = handlerExports.length === 0 && hasDefaultExport;
|
|
60
66
|
if (isV2API) {
|
|
61
|
-
const
|
|
67
|
+
const result = {
|
|
68
|
+
inputModuleFormat,
|
|
62
69
|
runtimeAPIVersion: 2,
|
|
63
70
|
};
|
|
64
71
|
logger.system('detected v2 function');
|
|
65
72
|
if (typeof configExport.schedule === 'string') {
|
|
66
|
-
|
|
73
|
+
result.schedule = configExport.schedule;
|
|
67
74
|
}
|
|
68
75
|
if (configExport.method !== undefined) {
|
|
69
|
-
|
|
76
|
+
result.methods = normalizeMethods(configExport.method, functionName);
|
|
70
77
|
}
|
|
71
|
-
|
|
72
|
-
return
|
|
78
|
+
result.routes = getRoutes(configExport.path, functionName, result.methods ?? []);
|
|
79
|
+
return result;
|
|
73
80
|
}
|
|
74
81
|
const iscExports = handlerExports
|
|
75
82
|
.map((node) => {
|
|
@@ -107,6 +114,6 @@ export const findISCDeclarations = (source, { functionName, logger }) => {
|
|
|
107
114
|
validateScheduleFunction(scheduledFunctionFound, scheduleFound, functionName);
|
|
108
115
|
}
|
|
109
116
|
const mergedExports = iscExports.reduce((acc, obj) => ({ ...acc, ...obj }), {});
|
|
110
|
-
return { ...mergedExports, runtimeAPIVersion: 1 };
|
|
117
|
+
return { ...mergedExports, inputModuleFormat, runtimeAPIVersion: 1 };
|
|
111
118
|
};
|
|
112
119
|
//# sourceMappingURL=index.js.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { join } from 'path';
|
|
1
|
+
import { extname, join } from 'path';
|
|
2
2
|
import { copyFile } from 'cp-file';
|
|
3
3
|
import { INVOCATION_MODE } from '../../function.js';
|
|
4
4
|
import getInternalValue from '../../utils/get_internal_value.js';
|
|
@@ -6,7 +6,8 @@ import { RUNTIME } from '../runtime.js';
|
|
|
6
6
|
import { getBundler, getBundlerName } from './bundlers/index.js';
|
|
7
7
|
import { NODE_BUNDLER } from './bundlers/types.js';
|
|
8
8
|
import { findFunctionsInPaths, findFunctionInPath } from './finder.js';
|
|
9
|
-
import {
|
|
9
|
+
import { parseFile } from './in_source_config/index.js';
|
|
10
|
+
import { MODULE_FORMAT, MODULE_FILE_EXTENSION } from './utils/module_format.js';
|
|
10
11
|
import { getNodeRuntime, getNodeRuntimeForV2 } from './utils/node_runtime.js';
|
|
11
12
|
import { createAliases as createPluginsModulesPathAliases, getPluginsModulesPath } from './utils/plugin_modules_path.js';
|
|
12
13
|
import { zipNodeJs } from './utils/zip.js';
|
|
@@ -33,8 +34,8 @@ const zipFunction = async function ({ archiveFormat, basePath, cache, config = {
|
|
|
33
34
|
await copyFile(srcPath, destPath);
|
|
34
35
|
return { config, path: destPath, entryFilename: '' };
|
|
35
36
|
}
|
|
36
|
-
const
|
|
37
|
-
const runtimeAPIVersion =
|
|
37
|
+
const staticAnalysisResult = await parseFile(mainFile, { functionName: name, logger });
|
|
38
|
+
const runtimeAPIVersion = staticAnalysisResult.runtimeAPIVersion === 2 ? 2 : 1;
|
|
38
39
|
const pluginsModulesPath = await getPluginsModulesPath(srcDir);
|
|
39
40
|
const bundlerName = await getBundlerName({
|
|
40
41
|
config,
|
|
@@ -83,7 +84,7 @@ const zipFunction = async function ({ archiveFormat, basePath, cache, config = {
|
|
|
83
84
|
await cleanupFunction?.();
|
|
84
85
|
// Getting the invocation mode from ISC, in case the function is using the
|
|
85
86
|
// `stream` helper.
|
|
86
|
-
let { invocationMode } =
|
|
87
|
+
let { invocationMode } = staticAnalysisResult;
|
|
87
88
|
// If we're using the V2 API, force the invocation to "stream".
|
|
88
89
|
if (runtimeAPIVersion === 2) {
|
|
89
90
|
invocationMode = INVOCATION_MODE.Stream;
|
|
@@ -92,6 +93,7 @@ const zipFunction = async function ({ archiveFormat, basePath, cache, config = {
|
|
|
92
93
|
if (name.endsWith('-background')) {
|
|
93
94
|
invocationMode = INVOCATION_MODE.Background;
|
|
94
95
|
}
|
|
96
|
+
const outputModuleFormat = extname(finalMainFile) === MODULE_FILE_EXTENSION.MJS ? MODULE_FORMAT.ESM : MODULE_FORMAT.COMMONJS;
|
|
95
97
|
return {
|
|
96
98
|
bundler: bundlerName,
|
|
97
99
|
bundlerWarnings,
|
|
@@ -101,8 +103,9 @@ const zipFunction = async function ({ archiveFormat, basePath, cache, config = {
|
|
|
101
103
|
generator: config?.generator || getInternalValue(isInternal),
|
|
102
104
|
inputs,
|
|
103
105
|
includedFiles,
|
|
104
|
-
|
|
106
|
+
staticAnalysisResult,
|
|
105
107
|
invocationMode,
|
|
108
|
+
outputModuleFormat,
|
|
106
109
|
nativeNodeModules,
|
|
107
110
|
path: zipPath.path,
|
|
108
111
|
runtimeVersion: runtimeAPIVersion === 2 ? getNodeRuntimeForV2(config.nodeVersion) : getNodeRuntime(config.nodeVersion),
|
|
@@ -1,8 +1,18 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { Statement } from '@babel/types';
|
|
2
2
|
import type { ISCExport } from '../in_source_config/index.js';
|
|
3
3
|
import type { BindingMethod } from './bindings.js';
|
|
4
|
-
|
|
4
|
+
/**
|
|
5
|
+
* Traverses a list of nodes and returns:
|
|
6
|
+
*
|
|
7
|
+
* 1. Named `config` object export (ESM or CJS)
|
|
8
|
+
* 2. Whether there is a default export (ESM or CJS)
|
|
9
|
+
* 3. Named `handler` function exports (ESM or CJS)
|
|
10
|
+
* 4. The module format syntax used in the file: if any `import` or `export`
|
|
11
|
+
* declarations are found, this is ESM; if not, this is CJS
|
|
12
|
+
*/
|
|
13
|
+
export declare const traverseNodes: (nodes: Statement[], getAllBindings: BindingMethod) => {
|
|
5
14
|
configExport: Record<string, unknown>;
|
|
6
|
-
defaultExport: ExportDefaultDeclaration | undefined;
|
|
7
15
|
handlerExports: ISCExport[];
|
|
16
|
+
hasDefaultExport: boolean;
|
|
17
|
+
inputModuleFormat: "cjs";
|
|
8
18
|
};
|
|
@@ -1,39 +1,59 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
import { MODULE_FORMAT } from '../utils/module_format.js';
|
|
2
|
+
import { isESMImportExport, isModuleExports } from './helpers.js';
|
|
3
|
+
/**
|
|
4
|
+
* Traverses a list of nodes and returns:
|
|
5
|
+
*
|
|
6
|
+
* 1. Named `config` object export (ESM or CJS)
|
|
7
|
+
* 2. Whether there is a default export (ESM or CJS)
|
|
8
|
+
* 3. Named `handler` function exports (ESM or CJS)
|
|
9
|
+
* 4. The module format syntax used in the file: if any `import` or `export`
|
|
10
|
+
* declarations are found, this is ESM; if not, this is CJS
|
|
11
|
+
*/
|
|
12
|
+
export const traverseNodes = (nodes, getAllBindings) => {
|
|
7
13
|
const handlerExports = [];
|
|
8
14
|
let configExport = {};
|
|
9
|
-
let
|
|
15
|
+
let hasDefaultExport = false;
|
|
16
|
+
let inputModuleFormat = MODULE_FORMAT.COMMONJS;
|
|
10
17
|
nodes.forEach((node) => {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
18
|
+
if (isESMImportExport(node)) {
|
|
19
|
+
inputModuleFormat = MODULE_FORMAT.ESM;
|
|
20
|
+
}
|
|
21
|
+
const esmHandlerExports = getNamedESMExport(node, 'handler', getAllBindings);
|
|
22
|
+
if (esmHandlerExports.length !== 0) {
|
|
23
|
+
handlerExports.push(...esmHandlerExports);
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
const cjsHandlerExports = getCJSExports(node, 'handler');
|
|
27
|
+
if (cjsHandlerExports.length !== 0) {
|
|
28
|
+
handlerExports.push(...cjsHandlerExports);
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
if (isESMDefaultExport(node)) {
|
|
32
|
+
hasDefaultExport = true;
|
|
14
33
|
return;
|
|
15
34
|
}
|
|
16
|
-
const
|
|
17
|
-
if (
|
|
18
|
-
|
|
35
|
+
const cjsDefaultExports = getCJSExports(node, 'default');
|
|
36
|
+
if (cjsDefaultExports.length !== 0) {
|
|
37
|
+
hasDefaultExport = true;
|
|
19
38
|
return;
|
|
20
39
|
}
|
|
21
|
-
|
|
22
|
-
|
|
40
|
+
const esmConfig = parseConfigESMExport(node);
|
|
41
|
+
if (esmConfig !== undefined) {
|
|
42
|
+
configExport = esmConfig;
|
|
23
43
|
return;
|
|
24
44
|
}
|
|
25
|
-
const
|
|
26
|
-
if (
|
|
27
|
-
configExport =
|
|
45
|
+
const cjsConfigExports = getCJSExports(node, 'config');
|
|
46
|
+
if (cjsConfigExports.length !== 0 && cjsConfigExports[0].type === 'object-expression') {
|
|
47
|
+
configExport = cjsConfigExports[0].object;
|
|
28
48
|
}
|
|
29
49
|
});
|
|
30
|
-
return { configExport,
|
|
50
|
+
return { configExport, handlerExports, hasDefaultExport, inputModuleFormat };
|
|
31
51
|
};
|
|
32
52
|
// Finds the main handler export in a CJS AST.
|
|
33
|
-
const
|
|
53
|
+
const getCJSExports = (node, name) => {
|
|
34
54
|
const handlerPaths = [
|
|
35
|
-
['module', 'exports',
|
|
36
|
-
['exports',
|
|
55
|
+
['module', 'exports', name],
|
|
56
|
+
['exports', name],
|
|
37
57
|
];
|
|
38
58
|
return handlerPaths.flatMap((handlerPath) => {
|
|
39
59
|
if (!isModuleExports(node, handlerPath)) {
|
|
@@ -42,41 +62,50 @@ const getMainExportFromCJS = (node) => {
|
|
|
42
62
|
return getExportsFromExpression(node.expression.right);
|
|
43
63
|
});
|
|
44
64
|
};
|
|
45
|
-
|
|
46
|
-
|
|
65
|
+
/**
|
|
66
|
+
* Finds a named ESM export with a given name. It's capable of finding exports
|
|
67
|
+
* with a variable declaration (`export const foo = "bar"`), but also resolve
|
|
68
|
+
* bindings and find things like `const baz = "1"; export { baz as foo }`.
|
|
69
|
+
*/
|
|
70
|
+
const getNamedESMExport = (node, name, getAllBindings) => {
|
|
47
71
|
if (node.type !== 'ExportNamedDeclaration' || node.exportKind !== 'value') {
|
|
48
72
|
return [];
|
|
49
73
|
}
|
|
50
74
|
const { declaration, specifiers } = node;
|
|
51
75
|
if (specifiers?.length > 0) {
|
|
52
|
-
return getExportsFromBindings(specifiers, getAllBindings);
|
|
76
|
+
return getExportsFromBindings(specifiers, name, getAllBindings);
|
|
53
77
|
}
|
|
54
78
|
if (declaration?.type !== 'VariableDeclaration') {
|
|
55
79
|
return [];
|
|
56
80
|
}
|
|
57
81
|
const handlerDeclaration = declaration.declarations.find((childDeclaration) => {
|
|
58
82
|
const { id, type } = childDeclaration;
|
|
59
|
-
return type === 'VariableDeclarator' && id.type === 'Identifier' && id.name ===
|
|
83
|
+
return type === 'VariableDeclarator' && id.type === 'Identifier' && id.name === name;
|
|
60
84
|
});
|
|
61
85
|
const exports = getExportsFromExpression(handlerDeclaration?.init);
|
|
62
86
|
return exports;
|
|
63
87
|
};
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
88
|
+
/**
|
|
89
|
+
* Check if the node is an `ExportSpecifier` that has a named export with
|
|
90
|
+
* the given name, either as:
|
|
91
|
+
* - `export { handler }`, or
|
|
92
|
+
* - `export { x as "handler" }`
|
|
93
|
+
*/
|
|
94
|
+
const isNamedExport = (node, name) => {
|
|
68
95
|
const { type, exported } = node;
|
|
69
96
|
return (type === 'ExportSpecifier' &&
|
|
70
|
-
((exported.type === 'Identifier' && exported.name ===
|
|
71
|
-
(exported.type === 'StringLiteral' && exported.value ===
|
|
97
|
+
((exported.type === 'Identifier' && exported.name === name) ||
|
|
98
|
+
(exported.type === 'StringLiteral' && exported.value === name)));
|
|
72
99
|
};
|
|
73
100
|
// Returns whether a given node is a default export declaration.
|
|
74
|
-
const
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
const
|
|
101
|
+
const isESMDefaultExport = (node) => node.type === 'ExportDefaultDeclaration';
|
|
102
|
+
/**
|
|
103
|
+
* Finds a `config` named CJS export that maps to an object variable
|
|
104
|
+
* declaration, like:
|
|
105
|
+
*
|
|
106
|
+
* `export const config = { prop1: "value 1" }`
|
|
107
|
+
*/
|
|
108
|
+
const parseConfigESMExport = (node) => {
|
|
80
109
|
if (node.type === 'ExportNamedDeclaration' &&
|
|
81
110
|
node.declaration?.type === 'VariableDeclaration' &&
|
|
82
111
|
node.declaration.declarations[0].type === 'VariableDeclarator' &&
|
|
@@ -131,12 +160,15 @@ const parsePrimitive = (exp) => {
|
|
|
131
160
|
return null;
|
|
132
161
|
}
|
|
133
162
|
};
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
163
|
+
/**
|
|
164
|
+
* Tries to resolve the export with a given name from a binding (variable).
|
|
165
|
+
* For example, the following would resolve correctly to the handler function:
|
|
166
|
+
*
|
|
167
|
+
* `let handler; handler = () => {}; export { handler }`
|
|
168
|
+
*/
|
|
169
|
+
const getExportsFromBindings = (specifiers, name, getAllBindings) => {
|
|
170
|
+
const specifier = specifiers.find((node) => isNamedExport(node, name));
|
|
171
|
+
if (!specifier || specifier.type !== 'ExportSpecifier') {
|
|
140
172
|
return [];
|
|
141
173
|
}
|
|
142
174
|
const binding = getAllBindings().get(specifier.local.name);
|
|
@@ -152,6 +184,10 @@ const getExportsFromExpression = (node) => {
|
|
|
152
184
|
}
|
|
153
185
|
return [{ args, local: callee.name, type: 'call-expression' }];
|
|
154
186
|
}
|
|
187
|
+
case 'ObjectExpression': {
|
|
188
|
+
const object = parseObject(node);
|
|
189
|
+
return [{ object, type: 'object-expression' }];
|
|
190
|
+
}
|
|
155
191
|
default: {
|
|
156
192
|
if (node !== undefined) {
|
|
157
193
|
return [{ type: 'other' }];
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { AssignmentExpression, Expression, ExpressionStatement, ImportDeclaration, Statement } from '@babel/types';
|
|
2
|
+
export declare const isESMImportExport: (node: Statement) => boolean;
|
|
2
3
|
export declare const isImport: (node: Statement, importPath: string) => node is ImportDeclaration;
|
|
3
4
|
export declare const isModuleExports: (node: Statement, dotExpression?: string[]) => node is ExpressionStatement & {
|
|
4
5
|
expression: AssignmentExpression;
|
|
@@ -12,6 +12,10 @@ const isDotExpression = (node, expression) => {
|
|
|
12
12
|
}
|
|
13
13
|
return node.object.type === 'Identifier' && object[0] === node.object.name && property === node.property.name;
|
|
14
14
|
};
|
|
15
|
+
export const isESMImportExport = (node) => node.type === 'ImportDeclaration' ||
|
|
16
|
+
node.type === 'ExportNamedDeclaration' ||
|
|
17
|
+
node.type === 'ExportDefaultDeclaration' ||
|
|
18
|
+
node.type === 'ExportAllDeclaration';
|
|
15
19
|
export const isImport = (node, importPath) => node.type === 'ImportDeclaration' && node.source.value === importPath;
|
|
16
20
|
export const isModuleExports = (node, dotExpression = ['module', 'exports']) => node.type === 'ExpressionStatement' &&
|
|
17
21
|
node.expression.type === 'AssignmentExpression' &&
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This shim makes calls to `require`, `__filename` and `__dirname` work when
|
|
3
|
+
* bundling to ESM with esbuild.
|
|
4
|
+
*
|
|
5
|
+
* https://github.com/evanw/esbuild/pull/2067
|
|
6
|
+
*/
|
|
7
|
+
export declare const CJS_SHIM = "\nimport {createRequire as ___nfyCreateRequire} from \"module\";\nimport {fileURLToPath as ___nfyFileURLToPath} from \"url\";\nimport {dirname as ___nfyPathDirname} from \"path\";\nlet __filename=___nfyFileURLToPath(import.meta.url);\nlet __dirname=___nfyPathDirname(___nfyFileURLToPath(import.meta.url));\nlet require=___nfyCreateRequire(import.meta.url);\n";
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This shim makes calls to `require`, `__filename` and `__dirname` work when
|
|
3
|
+
* bundling to ESM with esbuild.
|
|
4
|
+
*
|
|
5
|
+
* https://github.com/evanw/esbuild/pull/2067
|
|
6
|
+
*/
|
|
7
|
+
export const CJS_SHIM = `
|
|
8
|
+
import {createRequire as ___nfyCreateRequire} from "module";
|
|
9
|
+
import {fileURLToPath as ___nfyFileURLToPath} from "url";
|
|
10
|
+
import {dirname as ___nfyPathDirname} from "path";
|
|
11
|
+
let __filename=___nfyFileURLToPath(import.meta.url);
|
|
12
|
+
let __dirname=___nfyPathDirname(___nfyFileURLToPath(import.meta.url));
|
|
13
|
+
let require=___nfyCreateRequire(import.meta.url);
|
|
14
|
+
`;
|
|
15
|
+
//# sourceMappingURL=esm_cjs_compat.js.map
|
|
@@ -8,8 +8,10 @@ export declare const MODULE_FORMAT: {
|
|
|
8
8
|
export type ModuleFormat = ObjectValues<typeof MODULE_FORMAT>;
|
|
9
9
|
export declare const MODULE_FILE_EXTENSION: {
|
|
10
10
|
readonly CJS: ".cjs";
|
|
11
|
+
readonly CTS: ".cts";
|
|
11
12
|
readonly JS: ".js";
|
|
12
13
|
readonly MJS: ".mjs";
|
|
14
|
+
readonly MTS: ".mts";
|
|
13
15
|
};
|
|
14
16
|
export type ModuleFileExtension = ObjectValues<typeof MODULE_FILE_EXTENSION>;
|
|
15
17
|
export declare const getFileExtensionForFormat: (moduleFormat: ModuleFormat, featureFlags: FeatureFlags, runtimeAPIVersion: number) => ModuleFileExtension;
|
|
@@ -5,8 +5,10 @@ export const MODULE_FORMAT = {
|
|
|
5
5
|
};
|
|
6
6
|
export const MODULE_FILE_EXTENSION = {
|
|
7
7
|
CJS: '.cjs',
|
|
8
|
+
CTS: '.cts',
|
|
8
9
|
JS: '.js',
|
|
9
10
|
MJS: '.mjs',
|
|
11
|
+
MTS: '.mts',
|
|
10
12
|
};
|
|
11
13
|
export const getFileExtensionForFormat = (moduleFormat, featureFlags, runtimeAPIVersion) => {
|
|
12
14
|
if (moduleFormat === MODULE_FORMAT.ESM && (runtimeAPIVersion === 2 || featureFlags.zisi_pure_esm_mjs)) {
|
|
@@ -1,18 +1,14 @@
|
|
|
1
1
|
import { Buffer } from 'buffer';
|
|
2
2
|
import { mkdir, rm, writeFile } from 'fs/promises';
|
|
3
3
|
import os from 'os';
|
|
4
|
-
import { basename,
|
|
4
|
+
import { basename, extname, join } from 'path';
|
|
5
5
|
import { getPath as getV2APIPath } from '@netlify/serverless-functions-api';
|
|
6
6
|
import { copyFile } from 'cp-file';
|
|
7
7
|
import pMap from 'p-map';
|
|
8
8
|
import { startZip, addZipFile, addZipContent, endZip, ARCHIVE_FORMAT, } from '../../../archive.js';
|
|
9
|
-
import { FunctionBundlingUserError } from '../../../utils/error.js';
|
|
10
9
|
import { cachedLstat, mkdirAndWriteFile } from '../../../utils/fs.js';
|
|
11
|
-
import { RUNTIME } from '../../runtime.js';
|
|
12
10
|
import { BOOTSTRAP_FILE_NAME, conflictsWithEntryFile, getEntryFile, isNamedLikeEntryFile, } from './entry_file.js';
|
|
13
|
-
import { tsExtensions, MODULE_FORMAT } from './module_format.js';
|
|
14
11
|
import { normalizeFilePath } from './normalize_path.js';
|
|
15
|
-
import { getClosestPackageJson } from './package_json.js';
|
|
16
12
|
// Taken from https://www.npmjs.com/package/cpy.
|
|
17
13
|
const COPY_FILE_CONCURRENCY = os.cpus().length === 0 ? 2 : os.cpus().length * 2;
|
|
18
14
|
// Sub-directory to place all user-defined files (i.e. everything other than
|
|
@@ -26,7 +22,7 @@ const addBootstrapFile = function (srcFiles, aliases) {
|
|
|
26
22
|
srcFiles.push(v2APIPath);
|
|
27
23
|
aliases.set(v2APIPath, BOOTSTRAP_FILE_NAME);
|
|
28
24
|
};
|
|
29
|
-
const createDirectory = async function ({ aliases = new Map(), basePath, destFolder, extension, featureFlags, filename, mainFile, moduleFormat,
|
|
25
|
+
const createDirectory = async function ({ aliases = new Map(), basePath, destFolder, extension, featureFlags, filename, mainFile, moduleFormat, rewrites = new Map(), runtimeAPIVersion, srcFiles, }) {
|
|
30
26
|
const { contents: entryContents, filename: entryFilename } = getEntryFile({
|
|
31
27
|
commonPrefix: basePath,
|
|
32
28
|
featureFlags,
|
|
@@ -59,22 +55,9 @@ const createDirectory = async function ({ aliases = new Map(), basePath, destFol
|
|
|
59
55
|
}
|
|
60
56
|
return copyFile(srcFile, absoluteDestPath);
|
|
61
57
|
}, { concurrency: COPY_FILE_CONCURRENCY });
|
|
62
|
-
if (tsExtensions.has(extension) && moduleFormat === MODULE_FORMAT.ESM && runtimeAPIVersion === 2) {
|
|
63
|
-
const packageJSON = await ensurePackageJSONWithModuleType({
|
|
64
|
-
basePath,
|
|
65
|
-
mainFile,
|
|
66
|
-
name,
|
|
67
|
-
repositoryRoot,
|
|
68
|
-
userNamespace: DEFAULT_USER_SUBDIRECTORY,
|
|
69
|
-
});
|
|
70
|
-
if (packageJSON) {
|
|
71
|
-
const absoluteDestPath = join(functionFolder, packageJSON.path);
|
|
72
|
-
await writeFile(absoluteDestPath, packageJSON.contents);
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
58
|
return { path: functionFolder, entryFilename };
|
|
76
59
|
};
|
|
77
|
-
const createZipArchive = async function ({ aliases = new Map(), basePath, cache, destFolder, extension, featureFlags, filename, mainFile, moduleFormat,
|
|
60
|
+
const createZipArchive = async function ({ aliases = new Map(), basePath, cache, destFolder, extension, featureFlags, filename, mainFile, moduleFormat, rewrites, runtimeAPIVersion, srcFiles, }) {
|
|
78
61
|
const destPath = join(destFolder, `${basename(filename, extension)}.zip`);
|
|
79
62
|
const { archive, output } = startZip(destPath);
|
|
80
63
|
// There is a naming conflict with the entry file if one of the supporting
|
|
@@ -114,18 +97,6 @@ const createZipArchive = async function ({ aliases = new Map(), basePath, cache,
|
|
|
114
97
|
if (runtimeAPIVersion === 2) {
|
|
115
98
|
addBootstrapFile(srcFiles, aliases);
|
|
116
99
|
}
|
|
117
|
-
if (tsExtensions.has(extension) && moduleFormat === MODULE_FORMAT.ESM && runtimeAPIVersion === 2) {
|
|
118
|
-
const packageJSON = await ensurePackageJSONWithModuleType({
|
|
119
|
-
basePath,
|
|
120
|
-
mainFile,
|
|
121
|
-
name,
|
|
122
|
-
repositoryRoot,
|
|
123
|
-
userNamespace,
|
|
124
|
-
});
|
|
125
|
-
if (packageJSON) {
|
|
126
|
-
addZipContent(archive, packageJSON.contents, packageJSON.path);
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
100
|
const deduplicatedSrcFiles = [...new Set(srcFiles)];
|
|
130
101
|
const srcFilesInfos = await Promise.all(deduplicatedSrcFiles.map((file) => addStat(cache, file)));
|
|
131
102
|
// We ensure this is not async, so that the archive's checksum is
|
|
@@ -158,40 +129,6 @@ const addStat = async function (cache, srcFile) {
|
|
|
158
129
|
const stat = await cachedLstat(cache.lstatCache, srcFile);
|
|
159
130
|
return { srcFile, stat };
|
|
160
131
|
};
|
|
161
|
-
const ensurePackageJSONWithModuleType = async function ({ basePath, mainFile, name, repositoryRoot, userNamespace, }) {
|
|
162
|
-
const functionDirectory = dirname(mainFile);
|
|
163
|
-
let packageJSON = null;
|
|
164
|
-
try {
|
|
165
|
-
packageJSON = await getClosestPackageJson(functionDirectory, repositoryRoot);
|
|
166
|
-
}
|
|
167
|
-
catch {
|
|
168
|
-
// There is no valid `package.json`. This is a no-op.
|
|
169
|
-
}
|
|
170
|
-
// If the closest `package.json` already has a `module` type, there's nothing
|
|
171
|
-
// else we need to do.
|
|
172
|
-
if (packageJSON?.contents?.type === 'module') {
|
|
173
|
-
return;
|
|
174
|
-
}
|
|
175
|
-
// If there is already a `package.json` adjacent to the function entry point,
|
|
176
|
-
// we won't simply overwrite it because that might cause unexpected problems.
|
|
177
|
-
// Instead, we fail the build and tell the user that we found contradictory
|
|
178
|
-
// configuration settings.
|
|
179
|
-
if (packageJSON !== null && dirname(packageJSON.path) === functionDirectory) {
|
|
180
|
-
throw new FunctionBundlingUserError(`The function defined in '${mainFile}' has a contradictory configuration: a 'tsconfig.json' file is defining the module format as ESM, but '${packageJSON.path}' specifies CommonJS. If you want to use ESM, consider adding '"type": "module"' to 'package.json'; if you'd like to use CommonJS, consider setting the 'compilerOptions.module' property in 'tsconfig.json' to 'commonjs'.`, {
|
|
181
|
-
functionName: name,
|
|
182
|
-
runtime: RUNTIME.JAVASCRIPT,
|
|
183
|
-
});
|
|
184
|
-
}
|
|
185
|
-
// To ensure that the entry file and any local imports run as ESM, plant a
|
|
186
|
-
// `package.json` with `"type": "module"` adjacent to the entry point.
|
|
187
|
-
const path = join(functionDirectory, 'package.json');
|
|
188
|
-
const normalizedPath = normalizeFilePath({ commonPrefix: basePath, path, userNamespace });
|
|
189
|
-
const contents = JSON.stringify({ type: 'module' });
|
|
190
|
-
return {
|
|
191
|
-
contents,
|
|
192
|
-
path: normalizedPath,
|
|
193
|
-
};
|
|
194
|
-
};
|
|
195
132
|
const zipJsFile = function ({ aliases = new Map(), archive, commonPrefix, rewrites = new Map(), stat, srcFile, userNamespace, }) {
|
|
196
133
|
const destPath = aliases.get(srcFile) || srcFile;
|
|
197
134
|
const normalizedDestPath = normalizeFilePath({ commonPrefix, path: destPath, userNamespace });
|
|
@@ -2,11 +2,12 @@ import type { ArchiveFormat } from '../archive.js';
|
|
|
2
2
|
import type { FunctionConfig } from '../config.js';
|
|
3
3
|
import type { FeatureFlags } from '../feature_flags.js';
|
|
4
4
|
import type { FunctionSource, InvocationMode, SourceFile } from '../function.js';
|
|
5
|
+
import type { ModuleFormat } from '../main.js';
|
|
5
6
|
import { ObjectValues } from '../types/utils.js';
|
|
6
7
|
import type { RuntimeCache } from '../utils/cache.js';
|
|
7
8
|
import { Logger } from '../utils/logger.js';
|
|
8
9
|
import type { NodeBundlerName } from './node/bundlers/types.js';
|
|
9
|
-
import type {
|
|
10
|
+
import type { StaticAnalysisResult } from './node/in_source_config/index.js';
|
|
10
11
|
export declare const RUNTIME: {
|
|
11
12
|
readonly GO: "go";
|
|
12
13
|
readonly JAVASCRIPT: "js";
|
|
@@ -39,11 +40,12 @@ export interface ZipFunctionResult {
|
|
|
39
40
|
generator?: string;
|
|
40
41
|
inputs?: string[];
|
|
41
42
|
includedFiles?: string[];
|
|
42
|
-
inSourceConfig?: ISCValues;
|
|
43
43
|
invocationMode?: InvocationMode;
|
|
44
|
+
outputModuleFormat?: ModuleFormat;
|
|
44
45
|
nativeNodeModules?: object;
|
|
45
46
|
path: string;
|
|
46
47
|
runtimeVersion?: string;
|
|
48
|
+
staticAnalysisResult?: StaticAnalysisResult;
|
|
47
49
|
entryFilename: string;
|
|
48
50
|
}
|
|
49
51
|
export type ZipFunction = (args: {
|
|
@@ -3,11 +3,11 @@ import { removeUndefined } from './remove_undefined.js';
|
|
|
3
3
|
export const formatZipResult = (archive) => {
|
|
4
4
|
const functionResult = {
|
|
5
5
|
...archive,
|
|
6
|
-
|
|
7
|
-
routes: archive.
|
|
6
|
+
staticAnalysisResult: undefined,
|
|
7
|
+
routes: archive.staticAnalysisResult?.routes,
|
|
8
8
|
runtime: archive.runtime.name,
|
|
9
|
-
schedule: archive.
|
|
10
|
-
runtimeAPIVersion: archive.
|
|
9
|
+
schedule: archive.staticAnalysisResult?.schedule ?? archive?.config?.schedule,
|
|
10
|
+
runtimeAPIVersion: archive.staticAnalysisResult?.runtimeAPIVersion,
|
|
11
11
|
};
|
|
12
12
|
return removeUndefined(functionResult);
|
|
13
13
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@netlify/zip-it-and-ship-it",
|
|
3
|
-
"version": "9.
|
|
3
|
+
"version": "9.22.0",
|
|
4
4
|
"description": "Zip it and ship it",
|
|
5
5
|
"main": "./dist/main.js",
|
|
6
6
|
"type": "module",
|
|
@@ -66,7 +66,6 @@
|
|
|
66
66
|
"execa": "^6.0.0",
|
|
67
67
|
"filter-obj": "^5.0.0",
|
|
68
68
|
"find-up": "^6.0.0",
|
|
69
|
-
"get-tsconfig": "^4.6.2",
|
|
70
69
|
"glob": "^8.0.3",
|
|
71
70
|
"is-builtin-module": "^3.1.0",
|
|
72
71
|
"is-path-inside": "^4.0.0",
|
|
@@ -96,12 +95,12 @@
|
|
|
96
95
|
"@types/is-ci": "3.0.1",
|
|
97
96
|
"@types/node": "14.18.63",
|
|
98
97
|
"@types/normalize-path": "3.0.0",
|
|
99
|
-
"@types/resolve": "1.20.
|
|
100
|
-
"@types/semver": "7.5.
|
|
98
|
+
"@types/resolve": "1.20.3",
|
|
99
|
+
"@types/semver": "7.5.3",
|
|
101
100
|
"@types/tmp": "0.2.4",
|
|
102
101
|
"@types/unixify": "1.0.0",
|
|
103
|
-
"@types/yargs": "17.0.
|
|
104
|
-
"@vitest/coverage-v8": "0.34.
|
|
102
|
+
"@types/yargs": "17.0.28",
|
|
103
|
+
"@vitest/coverage-v8": "0.34.6",
|
|
105
104
|
"adm-zip": "0.5.10",
|
|
106
105
|
"browserslist": "4.21.11",
|
|
107
106
|
"cardinal": "2.1.1",
|
|
@@ -113,7 +112,7 @@
|
|
|
113
112
|
"npm-run-all": "4.1.5",
|
|
114
113
|
"source-map-support": "0.5.21",
|
|
115
114
|
"typescript": "5.2.2",
|
|
116
|
-
"vitest": "0.34.
|
|
115
|
+
"vitest": "0.34.6"
|
|
117
116
|
},
|
|
118
117
|
"engines": {
|
|
119
118
|
"node": "^14.18.0 || >=16.0.0"
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
export type { TsConfigJson as TsConfig } from 'get-tsconfig';
|
|
2
|
-
/**
|
|
3
|
-
* Looks for a `tsconfig.json` file on a given path and, if one exists, returns
|
|
4
|
-
* the module format inferred from the `module` property. If no file is found
|
|
5
|
-
* or if no `module` property is defined, the function returns `undefined`.
|
|
6
|
-
*/
|
|
7
|
-
export declare const getModuleFormat: (path: string, boundary?: string) => "cjs" | "esm" | undefined;
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import { dirname, relative } from 'path';
|
|
2
|
-
import { getTsconfig } from 'get-tsconfig';
|
|
3
|
-
import { MODULE_FORMAT } from './module_format.js';
|
|
4
|
-
const esmModuleValues = new Set(['es6', 'es2015', 'es2020', 'es2022', 'esnext', 'node16', 'nodenext']);
|
|
5
|
-
/**
|
|
6
|
-
* Looks for a `tsconfig.json` file applicable to a given path and returns the
|
|
7
|
-
* contents as an object. If a boundary is set, we'll stop traversing the file
|
|
8
|
-
* system once that path is reached.
|
|
9
|
-
*/
|
|
10
|
-
const getTSConfigInProject = (path, boundary) => {
|
|
11
|
-
const file = getTsconfig(path);
|
|
12
|
-
if (!file) {
|
|
13
|
-
return;
|
|
14
|
-
}
|
|
15
|
-
// If there is a boundary defined and the file we found is outside of it,
|
|
16
|
-
// discard the file.
|
|
17
|
-
if (boundary !== undefined && relative(boundary, dirname(file.path)).startsWith('..')) {
|
|
18
|
-
return;
|
|
19
|
-
}
|
|
20
|
-
return file.config;
|
|
21
|
-
};
|
|
22
|
-
/**
|
|
23
|
-
* Looks for a `tsconfig.json` file on a given path and, if one exists, returns
|
|
24
|
-
* the module format inferred from the `module` property. If no file is found
|
|
25
|
-
* or if no `module` property is defined, the function returns `undefined`.
|
|
26
|
-
*/
|
|
27
|
-
export const getModuleFormat = (path, boundary) => {
|
|
28
|
-
const config = getTSConfigInProject(path, boundary);
|
|
29
|
-
if (!config) {
|
|
30
|
-
return;
|
|
31
|
-
}
|
|
32
|
-
const moduleProp = config.compilerOptions?.module;
|
|
33
|
-
if (!moduleProp) {
|
|
34
|
-
return;
|
|
35
|
-
}
|
|
36
|
-
return esmModuleValues.has(moduleProp) ? MODULE_FORMAT.ESM : MODULE_FORMAT.COMMONJS;
|
|
37
|
-
};
|
|
38
|
-
//# sourceMappingURL=tsconfig.js.map
|