@netlify/build 27.20.4 → 27.20.6
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/lib/core/bin.js +42 -59
- package/lib/core/build.js +333 -536
- package/lib/core/config.js +94 -159
- package/lib/core/constants.js +95 -135
- package/lib/core/dev.js +26 -30
- package/lib/core/dry.js +18 -36
- package/lib/core/feature_flags.js +13 -16
- package/lib/core/flags.js +168 -169
- package/lib/core/lingering.js +44 -61
- package/lib/core/main.js +94 -136
- package/lib/core/missing_side_file.js +12 -24
- package/lib/core/normalize_flags.js +52 -63
- package/lib/core/severity.js +13 -15
- package/lib/core/user_node_version.js +26 -35
- package/lib/env/changes.js +29 -37
- package/lib/env/main.js +10 -15
- package/lib/env/metadata.js +63 -76
- package/lib/error/api.js +31 -40
- package/lib/error/build.js +27 -38
- package/lib/error/cancel.js +5 -6
- package/lib/error/colors.js +7 -9
- package/lib/error/handle.js +38 -49
- package/lib/error/info.js +26 -35
- package/lib/error/monitor/location.js +12 -17
- package/lib/error/monitor/normalize.js +75 -85
- package/lib/error/monitor/print.js +19 -41
- package/lib/error/monitor/report.js +102 -121
- package/lib/error/monitor/start.js +43 -56
- package/lib/error/parse/clean_stack.js +52 -69
- package/lib/error/parse/location.js +40 -52
- package/lib/error/parse/normalize.js +18 -23
- package/lib/error/parse/parse.js +59 -93
- package/lib/error/parse/plugin.js +42 -57
- package/lib/error/parse/properties.js +13 -20
- package/lib/error/parse/serialize_log.js +29 -37
- package/lib/error/parse/serialize_status.js +15 -23
- package/lib/error/parse/stack.js +29 -38
- package/lib/error/type.js +132 -150
- package/lib/install/functions.js +16 -24
- package/lib/install/local.js +31 -48
- package/lib/install/main.js +52 -66
- package/lib/install/missing.js +40 -53
- package/lib/log/colors.js +15 -22
- package/lib/log/description.js +16 -21
- package/lib/log/header.js +11 -13
- package/lib/log/header_func.js +11 -15
- package/lib/log/logger.js +88 -119
- package/lib/log/messages/compatibility.js +100 -158
- package/lib/log/messages/config.js +76 -92
- package/lib/log/messages/core.js +40 -60
- package/lib/log/messages/core_steps.js +63 -92
- package/lib/log/messages/dry.js +31 -53
- package/lib/log/messages/install.js +21 -28
- package/lib/log/messages/ipc.js +21 -30
- package/lib/log/messages/mutations.js +51 -71
- package/lib/log/messages/plugins.js +18 -31
- package/lib/log/messages/status.js +12 -14
- package/lib/log/messages/steps.js +14 -18
- package/lib/log/old_version.js +23 -32
- package/lib/log/serialize.js +7 -10
- package/lib/log/stream.js +48 -65
- package/lib/log/theme.js +22 -23
- package/lib/plugins/child/diff.js +31 -40
- package/lib/plugins/child/error.js +20 -26
- package/lib/plugins/child/lazy.js +11 -14
- package/lib/plugins/child/load.js +15 -22
- package/lib/plugins/child/logic.js +51 -58
- package/lib/plugins/child/main.js +32 -46
- package/lib/plugins/child/run.js +18 -27
- package/lib/plugins/child/status.js +52 -63
- package/lib/plugins/child/typescript.js +19 -36
- package/lib/plugins/child/utils.js +36 -49
- package/lib/plugins/child/validate.js +25 -28
- package/lib/plugins/compatibility.js +64 -92
- package/lib/plugins/error.js +29 -35
- package/lib/plugins/events.js +7 -12
- package/lib/plugins/expected_version.js +61 -99
- package/lib/plugins/ipc.js +79 -102
- package/lib/plugins/list.js +49 -62
- package/lib/plugins/load.js +44 -64
- package/lib/plugins/manifest/check.js +64 -85
- package/lib/plugins/manifest/load.js +34 -37
- package/lib/plugins/manifest/main.js +16 -21
- package/lib/plugins/manifest/path.js +18 -25
- package/lib/plugins/manifest/validate.js +77 -94
- package/lib/plugins/node_version.js +22 -42
- package/lib/plugins/options.js +45 -78
- package/lib/plugins/pinned_version.js +58 -106
- package/lib/plugins/resolve.js +91 -133
- package/lib/plugins/spawn.js +43 -61
- package/lib/plugins_core/add.js +26 -40
- package/lib/plugins_core/build_command.js +47 -72
- package/lib/plugins_core/deploy/buildbot_client.js +61 -87
- package/lib/plugins_core/deploy/index.js +47 -71
- package/lib/plugins_core/edge_functions/index.js +73 -116
- package/lib/plugins_core/edge_functions/lib/error.js +13 -17
- package/lib/plugins_core/edge_functions/lib/internal_manifest.js +45 -55
- package/lib/plugins_core/edge_functions/validate_manifest/validate_edge_functions_manifest.js +65 -80
- package/lib/plugins_core/functions/error.js +88 -128
- package/lib/plugins_core/functions/feature_flags.js +5 -5
- package/lib/plugins_core/functions/index.js +98 -145
- package/lib/plugins_core/functions/utils.js +36 -57
- package/lib/plugins_core/functions/zisi.js +35 -52
- package/lib/plugins_core/functions_install/index.js +8 -11
- package/lib/plugins_core/list.js +15 -22
- package/lib/status/add.js +26 -32
- package/lib/status/colors.js +14 -19
- package/lib/status/load_error.js +8 -9
- package/lib/status/report.js +72 -126
- package/lib/status/success.js +10 -14
- package/lib/steps/core_step.js +54 -89
- package/lib/steps/error.js +50 -87
- package/lib/steps/get.js +33 -41
- package/lib/steps/plugin.js +53 -83
- package/lib/steps/return.js +24 -51
- package/lib/steps/run_core_steps.js +119 -171
- package/lib/steps/run_step.js +154 -270
- package/lib/steps/run_steps.js +91 -174
- package/lib/steps/update_config.js +45 -72
- package/lib/telemetry/main.js +89 -128
- package/lib/time/aggregate.js +84 -110
- package/lib/time/main.js +23 -34
- package/lib/time/measure.js +11 -15
- package/lib/time/report.js +32 -44
- package/lib/utils/errors.js +10 -9
- package/lib/utils/json.js +11 -15
- package/lib/utils/omit.js +3 -4
- package/lib/utils/package.js +19 -22
- package/lib/utils/remove_falsy.js +5 -7
- package/lib/utils/resolve.js +30 -34
- package/lib/utils/runtime.js +4 -4
- package/lib/utils/semver.js +19 -25
- package/package.json +14 -7
|
@@ -1,65 +1,41 @@
|
|
|
1
|
-
import { handleBuildError } from '../error/handle.js'
|
|
2
|
-
import { getMajorVersion } from '../utils/semver.js'
|
|
3
|
-
|
|
1
|
+
import { handleBuildError } from '../error/handle.js';
|
|
2
|
+
import { getMajorVersion } from '../utils/semver.js';
|
|
4
3
|
// Retrieve plugin's pinned major versions by fetching the latest `PluginRun`
|
|
5
4
|
// Only applies to `netlify.toml`-only installed plugins.
|
|
6
5
|
export const addPinnedVersions = async function ({ pluginsOptions, api, siteInfo: { id: siteId }, sendStatus }) {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
return pluginsOptionsA
|
|
19
|
-
}
|
|
20
|
-
|
|
6
|
+
if (!sendStatus || api === undefined || !siteId) {
|
|
7
|
+
return pluginsOptions;
|
|
8
|
+
}
|
|
9
|
+
const packages = pluginsOptions.filter(shouldFetchPinVersion).map(getPackageName);
|
|
10
|
+
if (packages.length === 0) {
|
|
11
|
+
return pluginsOptions;
|
|
12
|
+
}
|
|
13
|
+
const pluginRuns = await api.getLatestPluginRuns({ site_id: siteId, packages, state: 'success' });
|
|
14
|
+
const pluginsOptionsA = pluginsOptions.map((pluginOption) => addPinnedVersion(pluginOption, pluginRuns));
|
|
15
|
+
return pluginsOptionsA;
|
|
16
|
+
};
|
|
21
17
|
const shouldFetchPinVersion = function ({ pinnedVersion, loadedFrom, origin }) {
|
|
22
|
-
|
|
23
|
-
}
|
|
24
|
-
|
|
18
|
+
return pinnedVersion === undefined && loadedFrom === 'auto_install' && origin === 'config';
|
|
19
|
+
};
|
|
25
20
|
const getPackageName = function ({ packageName }) {
|
|
26
|
-
|
|
27
|
-
}
|
|
28
|
-
|
|
21
|
+
return packageName;
|
|
22
|
+
};
|
|
29
23
|
const addPinnedVersion = function (pluginOptions, pluginRuns) {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
}
|
|
38
|
-
|
|
24
|
+
const foundPluginRun = pluginRuns.find((pluginRun) => pluginRun.package === pluginOptions.packageName);
|
|
25
|
+
if (foundPluginRun === undefined) {
|
|
26
|
+
return pluginOptions;
|
|
27
|
+
}
|
|
28
|
+
const pinnedVersion = getMajorVersion(foundPluginRun.version);
|
|
29
|
+
return pinnedVersion === undefined ? pluginOptions : { ...pluginOptions, pinnedVersion };
|
|
30
|
+
};
|
|
39
31
|
// Send an API request to pin plugins' major versions.
|
|
40
32
|
// Only applies to UI-installed plugins.
|
|
41
|
-
export const pinPlugins = async function ({
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
mode,
|
|
48
|
-
netlifyConfig,
|
|
49
|
-
errorMonitor,
|
|
50
|
-
logs,
|
|
51
|
-
debug,
|
|
52
|
-
testOpts,
|
|
53
|
-
sendStatus,
|
|
54
|
-
}) {
|
|
55
|
-
if ((mode !== 'buildbot' && !sendStatus) || api === undefined || !siteId) {
|
|
56
|
-
return
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
const pluginsOptionsA = pluginsOptions.filter((pluginOptions) => shouldPinVersion({ pluginOptions, failedPlugins }))
|
|
60
|
-
await Promise.all(
|
|
61
|
-
pluginsOptionsA.map((pluginOptions) =>
|
|
62
|
-
pinPlugin({
|
|
33
|
+
export const pinPlugins = async function ({ pluginsOptions, failedPlugins, api, siteInfo: { id: siteId }, childEnv, mode, netlifyConfig, errorMonitor, logs, debug, testOpts, sendStatus, }) {
|
|
34
|
+
if ((mode !== 'buildbot' && !sendStatus) || api === undefined || !siteId) {
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
const pluginsOptionsA = pluginsOptions.filter((pluginOptions) => shouldPinVersion({ pluginOptions, failedPlugins }));
|
|
38
|
+
await Promise.all(pluginsOptionsA.map((pluginOptions) => pinPlugin({
|
|
63
39
|
pluginOptions,
|
|
64
40
|
api,
|
|
65
41
|
childEnv,
|
|
@@ -70,62 +46,38 @@ export const pinPlugins = async function ({
|
|
|
70
46
|
debug,
|
|
71
47
|
testOpts,
|
|
72
48
|
siteId,
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
)
|
|
76
|
-
}
|
|
77
|
-
|
|
49
|
+
})));
|
|
50
|
+
};
|
|
78
51
|
// Only pin version if:
|
|
79
52
|
// - the plugin's version has not been pinned yet
|
|
80
53
|
// - the plugin was installed in the UI
|
|
81
54
|
// - both the build and the plugin succeeded
|
|
82
|
-
const shouldPinVersion = function ({
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
debug,
|
|
106
|
-
testOpts,
|
|
107
|
-
siteId,
|
|
108
|
-
}) {
|
|
109
|
-
const pinnedVersion = getMajorVersion(version)
|
|
110
|
-
try {
|
|
111
|
-
await api.updatePlugin({
|
|
112
|
-
package: encodeURIComponent(packageName),
|
|
113
|
-
site_id: siteId,
|
|
114
|
-
body: { pinned_version: pinnedVersion },
|
|
115
|
-
})
|
|
116
|
-
// Bitballoon API randomly fails with 502.
|
|
117
|
-
// Builds should be successful when this API call fails, but we still want
|
|
118
|
-
// to report the error both in logs and in error monitoring.
|
|
119
|
-
} catch (error) {
|
|
120
|
-
if (shouldIgnoreError(error)) {
|
|
121
|
-
return
|
|
55
|
+
const shouldPinVersion = function ({ pluginOptions: { packageName, pinnedVersion, loadedFrom, origin }, failedPlugins, }) {
|
|
56
|
+
return (pinnedVersion === undefined &&
|
|
57
|
+
loadedFrom === 'auto_install' &&
|
|
58
|
+
origin === 'ui' &&
|
|
59
|
+
!failedPlugins.includes(packageName));
|
|
60
|
+
};
|
|
61
|
+
const pinPlugin = async function ({ pluginOptions: { packageName, pluginPackageJson: { version }, }, api, childEnv, mode, netlifyConfig, errorMonitor, logs, debug, testOpts, siteId, }) {
|
|
62
|
+
const pinnedVersion = getMajorVersion(version);
|
|
63
|
+
try {
|
|
64
|
+
await api.updatePlugin({
|
|
65
|
+
package: encodeURIComponent(packageName),
|
|
66
|
+
site_id: siteId,
|
|
67
|
+
body: { pinned_version: pinnedVersion },
|
|
68
|
+
});
|
|
69
|
+
// Bitballoon API randomly fails with 502.
|
|
70
|
+
// Builds should be successful when this API call fails, but we still want
|
|
71
|
+
// to report the error both in logs and in error monitoring.
|
|
72
|
+
}
|
|
73
|
+
catch (error) {
|
|
74
|
+
if (shouldIgnoreError(error)) {
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
await handleBuildError(error, { errorMonitor, netlifyConfig, childEnv, mode, logs, debug, testOpts });
|
|
122
78
|
}
|
|
123
|
-
|
|
124
|
-
await handleBuildError(error, { errorMonitor, netlifyConfig, childEnv, mode, logs, debug, testOpts })
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
|
|
79
|
+
};
|
|
128
80
|
// Status is 404 if the plugin is uninstalled while the build is ongoing.
|
|
129
81
|
const shouldIgnoreError = function ({ status }) {
|
|
130
|
-
|
|
131
|
-
}
|
|
82
|
+
return status === 404;
|
|
83
|
+
};
|
package/lib/plugins/resolve.js
CHANGED
|
@@ -1,152 +1,110 @@
|
|
|
1
|
-
import { addErrorInfo } from '../error/info.js'
|
|
2
|
-
import { installMissingPlugins } from '../install/missing.js'
|
|
3
|
-
import { resolvePath, tryResolvePath } from '../utils/resolve.js'
|
|
4
|
-
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import { addPinnedVersions } from './pinned_version.js'
|
|
8
|
-
|
|
1
|
+
import { addErrorInfo } from '../error/info.js';
|
|
2
|
+
import { installMissingPlugins } from '../install/missing.js';
|
|
3
|
+
import { resolvePath, tryResolvePath } from '../utils/resolve.js';
|
|
4
|
+
import { addExpectedVersions } from './expected_version.js';
|
|
5
|
+
import { addPluginsNodeVersion } from './node_version.js';
|
|
6
|
+
import { addPinnedVersions } from './pinned_version.js';
|
|
9
7
|
// Try to find plugins in four places, by priority order:
|
|
10
8
|
// - already loaded (core plugins)
|
|
11
9
|
// - local plugin
|
|
12
10
|
// - external plugin already installed in `node_modules`, most likely through `package.json`
|
|
13
11
|
// - automatically installed by us, to `.netlify/plugins/`
|
|
14
|
-
export const resolvePluginsPath = async function ({
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
autoPluginsDir,
|
|
43
|
-
packageJson,
|
|
44
|
-
debug,
|
|
45
|
-
logs,
|
|
46
|
-
buildDir,
|
|
47
|
-
testOpts,
|
|
48
|
-
featureFlags,
|
|
49
|
-
})
|
|
50
|
-
const pluginsOptionsE = await handleMissingPlugins({
|
|
51
|
-
pluginsOptions: pluginsOptionsD,
|
|
52
|
-
autoPluginsDir,
|
|
53
|
-
mode,
|
|
54
|
-
logs,
|
|
55
|
-
})
|
|
56
|
-
return pluginsOptionsE
|
|
57
|
-
}
|
|
58
|
-
|
|
12
|
+
export const resolvePluginsPath = async function ({ pluginsOptions, siteInfo, buildDir, nodePath, packageJson, userNodeVersion, mode, api, logs, debug, sendStatus, testOpts, featureFlags, }) {
|
|
13
|
+
const autoPluginsDir = getAutoPluginsDir(buildDir);
|
|
14
|
+
const pluginsOptionsA = await Promise.all(pluginsOptions.map((pluginOptions) => resolvePluginPath({ pluginOptions, buildDir, autoPluginsDir })));
|
|
15
|
+
const pluginsOptionsB = addPluginsNodeVersion({
|
|
16
|
+
pluginsOptions: pluginsOptionsA,
|
|
17
|
+
nodePath,
|
|
18
|
+
userNodeVersion,
|
|
19
|
+
logs,
|
|
20
|
+
});
|
|
21
|
+
const pluginsOptionsC = await addPinnedVersions({ pluginsOptions: pluginsOptionsB, api, siteInfo, sendStatus });
|
|
22
|
+
const pluginsOptionsD = await addExpectedVersions({
|
|
23
|
+
pluginsOptions: pluginsOptionsC,
|
|
24
|
+
autoPluginsDir,
|
|
25
|
+
packageJson,
|
|
26
|
+
debug,
|
|
27
|
+
logs,
|
|
28
|
+
buildDir,
|
|
29
|
+
testOpts,
|
|
30
|
+
featureFlags,
|
|
31
|
+
});
|
|
32
|
+
const pluginsOptionsE = await handleMissingPlugins({
|
|
33
|
+
pluginsOptions: pluginsOptionsD,
|
|
34
|
+
autoPluginsDir,
|
|
35
|
+
mode,
|
|
36
|
+
logs,
|
|
37
|
+
});
|
|
38
|
+
return pluginsOptionsE;
|
|
39
|
+
};
|
|
59
40
|
// Find the path to the directory used to install plugins automatically.
|
|
60
41
|
// It is a subdirectory of `buildDir`, so that the plugin can require the
|
|
61
42
|
// project's dependencies (peer dependencies).
|
|
62
43
|
const getAutoPluginsDir = function (buildDir) {
|
|
63
|
-
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
const
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
// Previously automatically installed
|
|
95
|
-
const { path: automaticPath } = await tryResolvePath(packageName, autoPluginsDir)
|
|
96
|
-
if (automaticPath !== undefined) {
|
|
97
|
-
return { ...pluginOptions, pluginPath: automaticPath, loadedFrom: 'auto_install' }
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
// Happens if the plugin:
|
|
101
|
-
// - name is mispelled
|
|
102
|
-
// - is not in our official list
|
|
103
|
-
// - is in our official list but has not been installed by this site yet
|
|
104
|
-
return { ...pluginOptions, loadedFrom: 'auto_install' }
|
|
105
|
-
}
|
|
106
|
-
|
|
44
|
+
return `${buildDir}/${AUTO_PLUGINS_DIR}`;
|
|
45
|
+
};
|
|
46
|
+
const AUTO_PLUGINS_DIR = '.netlify/plugins/';
|
|
47
|
+
const resolvePluginPath = async function ({ pluginOptions, pluginOptions: { packageName, loadedFrom }, buildDir, autoPluginsDir, }) {
|
|
48
|
+
// Core plugins
|
|
49
|
+
if (loadedFrom !== undefined) {
|
|
50
|
+
return pluginOptions;
|
|
51
|
+
}
|
|
52
|
+
const localPackageName = normalizeLocalPackageName(packageName);
|
|
53
|
+
// Local plugins
|
|
54
|
+
if (localPackageName.startsWith('.')) {
|
|
55
|
+
const { path: localPath, error } = await tryResolvePath(localPackageName, buildDir);
|
|
56
|
+
validateLocalPluginPath(error, localPackageName);
|
|
57
|
+
return { ...pluginOptions, pluginPath: localPath, loadedFrom: 'local' };
|
|
58
|
+
}
|
|
59
|
+
// Plugin added to `package.json`
|
|
60
|
+
const { path: manualPath } = await tryResolvePath(packageName, buildDir);
|
|
61
|
+
if (manualPath !== undefined) {
|
|
62
|
+
return { ...pluginOptions, pluginPath: manualPath, loadedFrom: 'package.json' };
|
|
63
|
+
}
|
|
64
|
+
// Previously automatically installed
|
|
65
|
+
const { path: automaticPath } = await tryResolvePath(packageName, autoPluginsDir);
|
|
66
|
+
if (automaticPath !== undefined) {
|
|
67
|
+
return { ...pluginOptions, pluginPath: automaticPath, loadedFrom: 'auto_install' };
|
|
68
|
+
}
|
|
69
|
+
// Happens if the plugin:
|
|
70
|
+
// - name is mispelled
|
|
71
|
+
// - is not in our official list
|
|
72
|
+
// - is in our official list but has not been installed by this site yet
|
|
73
|
+
return { ...pluginOptions, loadedFrom: 'auto_install' };
|
|
74
|
+
};
|
|
107
75
|
// `packageName` starting with `/` are relative to the build directory
|
|
108
76
|
const normalizeLocalPackageName = function (packageName) {
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
}
|
|
115
|
-
|
|
77
|
+
if (packageName.startsWith('/')) {
|
|
78
|
+
return `.${packageName}`;
|
|
79
|
+
}
|
|
80
|
+
return packageName;
|
|
81
|
+
};
|
|
116
82
|
// When requiring a local plugin with an invalid file path
|
|
117
83
|
const validateLocalPluginPath = function (error, localPackageName) {
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
}
|
|
124
|
-
|
|
84
|
+
if (error !== undefined) {
|
|
85
|
+
error.message = `Plugin could not be found using local path: ${localPackageName}\n${error.message}`;
|
|
86
|
+
addErrorInfo(error, { type: 'resolveConfig' });
|
|
87
|
+
throw error;
|
|
88
|
+
}
|
|
89
|
+
};
|
|
125
90
|
// Install plugins from the official list that have not been previously installed.
|
|
126
91
|
// Print a warning if they have not been installed through the UI.
|
|
127
92
|
const handleMissingPlugins = async function ({ pluginsOptions, autoPluginsDir, mode, logs }) {
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
return await Promise.all(
|
|
136
|
-
pluginsOptions.map((pluginOptions) => resolveMissingPluginPath({ pluginOptions, autoPluginsDir })),
|
|
137
|
-
)
|
|
138
|
-
}
|
|
139
|
-
|
|
93
|
+
const missingPlugins = pluginsOptions.filter(isMissingPlugin);
|
|
94
|
+
if (missingPlugins.length === 0) {
|
|
95
|
+
return pluginsOptions;
|
|
96
|
+
}
|
|
97
|
+
await installMissingPlugins({ missingPlugins, autoPluginsDir, mode, logs });
|
|
98
|
+
return await Promise.all(pluginsOptions.map((pluginOptions) => resolveMissingPluginPath({ pluginOptions, autoPluginsDir })));
|
|
99
|
+
};
|
|
140
100
|
// Resolve the plugins that just got automatically installed
|
|
141
101
|
const resolveMissingPluginPath = async function ({ pluginOptions, pluginOptions: { packageName }, autoPluginsDir }) {
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
}
|
|
149
|
-
|
|
102
|
+
if (!isMissingPlugin(pluginOptions)) {
|
|
103
|
+
return pluginOptions;
|
|
104
|
+
}
|
|
105
|
+
const pluginPath = await resolvePath(packageName, autoPluginsDir);
|
|
106
|
+
return { ...pluginOptions, pluginPath };
|
|
107
|
+
};
|
|
150
108
|
const isMissingPlugin = function ({ isMissing }) {
|
|
151
|
-
|
|
152
|
-
}
|
|
109
|
+
return isMissing;
|
|
110
|
+
};
|
package/lib/plugins/spawn.js
CHANGED
|
@@ -1,21 +1,11 @@
|
|
|
1
|
-
import { fileURLToPath } from 'url'
|
|
2
|
-
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
logOutdatedPlugins,
|
|
10
|
-
logIncompatiblePlugins,
|
|
11
|
-
} from '../log/messages/compatibility.js'
|
|
12
|
-
import { measureDuration } from '../time/main.js'
|
|
13
|
-
|
|
14
|
-
import { getEventFromChild } from './ipc.js'
|
|
15
|
-
import { getSpawnInfo } from './options.js'
|
|
16
|
-
|
|
17
|
-
const CHILD_MAIN_FILE = fileURLToPath(new URL('child/main.js', import.meta.url))
|
|
18
|
-
|
|
1
|
+
import { fileURLToPath } from 'url';
|
|
2
|
+
import { execaNode } from 'execa';
|
|
3
|
+
import { addErrorInfo } from '../error/info.js';
|
|
4
|
+
import { logRuntime, logLoadingPlugins, logOutdatedPlugins, logIncompatiblePlugins, } from '../log/messages/compatibility.js';
|
|
5
|
+
import { measureDuration } from '../time/main.js';
|
|
6
|
+
import { getEventFromChild } from './ipc.js';
|
|
7
|
+
import { getSpawnInfo } from './options.js';
|
|
8
|
+
const CHILD_MAIN_FILE = fileURLToPath(new URL('child/main.js', import.meta.url));
|
|
19
9
|
// Start child processes used by all plugins
|
|
20
10
|
// We fire plugins through child processes so that:
|
|
21
11
|
// - each plugin is sandboxed, e.g. cannot access/modify its parent `process`
|
|
@@ -23,50 +13,42 @@ const CHILD_MAIN_FILE = fileURLToPath(new URL('child/main.js', import.meta.url))
|
|
|
23
13
|
// - logs can be buffered which allows manipulating them for log shipping,
|
|
24
14
|
// transforming and parallel plugins
|
|
25
15
|
const tStartPlugins = async function ({ pluginsOptions, buildDir, childEnv, logs, debug }) {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
return { childProcesses }
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export const startPlugins = measureDuration(tStartPlugins, 'start_plugins')
|
|
38
|
-
|
|
16
|
+
logRuntime(logs, pluginsOptions);
|
|
17
|
+
logLoadingPlugins(logs, pluginsOptions, debug);
|
|
18
|
+
logOutdatedPlugins(logs, pluginsOptions);
|
|
19
|
+
logIncompatiblePlugins(logs, pluginsOptions);
|
|
20
|
+
const childProcesses = await Promise.all(pluginsOptions.map(({ pluginDir, nodePath }) => startPlugin({ pluginDir, nodePath, buildDir, childEnv })));
|
|
21
|
+
return { childProcesses };
|
|
22
|
+
};
|
|
23
|
+
export const startPlugins = measureDuration(tStartPlugins, 'start_plugins');
|
|
39
24
|
const startPlugin = async function ({ pluginDir, nodePath, buildDir, childEnv }) {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
}
|
|
60
|
-
|
|
25
|
+
const childProcess = execaNode(CHILD_MAIN_FILE, {
|
|
26
|
+
cwd: buildDir,
|
|
27
|
+
preferLocal: true,
|
|
28
|
+
localDir: pluginDir,
|
|
29
|
+
nodePath,
|
|
30
|
+
execPath: nodePath,
|
|
31
|
+
env: childEnv,
|
|
32
|
+
extendEnv: false,
|
|
33
|
+
serialization: 'advanced',
|
|
34
|
+
});
|
|
35
|
+
try {
|
|
36
|
+
await getEventFromChild(childProcess, 'ready');
|
|
37
|
+
return { childProcess };
|
|
38
|
+
}
|
|
39
|
+
catch (error) {
|
|
40
|
+
const spawnInfo = getSpawnInfo();
|
|
41
|
+
addErrorInfo(error, spawnInfo);
|
|
42
|
+
throw error;
|
|
43
|
+
}
|
|
44
|
+
};
|
|
61
45
|
// Stop all plugins child processes
|
|
62
46
|
export const stopPlugins = function (childProcesses) {
|
|
63
|
-
|
|
64
|
-
}
|
|
65
|
-
|
|
47
|
+
childProcesses.forEach(stopPlugin);
|
|
48
|
+
};
|
|
66
49
|
const stopPlugin = function ({ childProcess }) {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
}
|
|
50
|
+
if (childProcess.connected) {
|
|
51
|
+
childProcess.disconnect();
|
|
52
|
+
}
|
|
53
|
+
childProcess.kill();
|
|
54
|
+
};
|
package/lib/plugins_core/add.js
CHANGED
|
@@ -1,49 +1,35 @@
|
|
|
1
|
-
import { listCorePlugins, isCorePlugin } from './list.js'
|
|
2
|
-
|
|
1
|
+
import { listCorePlugins, isCorePlugin } from './list.js';
|
|
3
2
|
// Add core plugins and user plugins together.
|
|
4
3
|
// Do not allow user override of core plugins.
|
|
5
4
|
export const addCorePlugins = function ({ netlifyConfig: { plugins }, constants }) {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
}
|
|
15
|
-
|
|
5
|
+
const corePlugins = listCorePlugins(constants);
|
|
6
|
+
const allCorePlugins = corePlugins
|
|
7
|
+
.map((corePlugin) => addCoreProperties(corePlugin, plugins))
|
|
8
|
+
.filter((corePlugin) => !isOptionalCore(corePlugin, plugins));
|
|
9
|
+
const userPlugins = plugins.filter(isUserPlugin);
|
|
10
|
+
const allPlugins = [...userPlugins, ...allCorePlugins];
|
|
11
|
+
const pluginsOptions = allPlugins.map(normalizePluginOptions);
|
|
12
|
+
return pluginsOptions;
|
|
13
|
+
};
|
|
16
14
|
const addCoreProperties = function (corePlugin, plugins) {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
}
|
|
20
|
-
|
|
15
|
+
const inputs = getCorePluginInputs(corePlugin, plugins);
|
|
16
|
+
return { ...corePlugin, inputs, loadedFrom: 'core', origin: 'core' };
|
|
17
|
+
};
|
|
21
18
|
// Core plugins can get inputs too
|
|
22
19
|
const getCorePluginInputs = function (corePlugin, plugins) {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
}
|
|
30
|
-
|
|
20
|
+
const configuredCorePlugin = plugins.find((plugin) => plugin.package === corePlugin.package);
|
|
21
|
+
if (configuredCorePlugin === undefined) {
|
|
22
|
+
return {};
|
|
23
|
+
}
|
|
24
|
+
return configuredCorePlugin.inputs;
|
|
25
|
+
};
|
|
31
26
|
// Optional core plugins requires user opt-in
|
|
32
27
|
const isOptionalCore = function (pluginA, plugins) {
|
|
33
|
-
|
|
34
|
-
}
|
|
35
|
-
|
|
28
|
+
return pluginA.optional && plugins.every((pluginB) => pluginB.package !== pluginA.package);
|
|
29
|
+
};
|
|
36
30
|
const isUserPlugin = function (plugin) {
|
|
37
|
-
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
pluginPath,
|
|
43
|
-
pinned_version: pinnedVersion,
|
|
44
|
-
loadedFrom,
|
|
45
|
-
origin,
|
|
46
|
-
inputs,
|
|
47
|
-
}) {
|
|
48
|
-
return { packageName, pluginPath, pinnedVersion, loadedFrom, origin, inputs }
|
|
49
|
-
}
|
|
31
|
+
return !isCorePlugin(plugin.package);
|
|
32
|
+
};
|
|
33
|
+
const normalizePluginOptions = function ({ package: packageName, pluginPath, pinned_version: pinnedVersion, loadedFrom, origin, inputs, }) {
|
|
34
|
+
return { packageName, pluginPath, pinnedVersion, loadedFrom, origin, inputs };
|
|
35
|
+
};
|