@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
package/lib/install/main.js
CHANGED
|
@@ -1,81 +1,67 @@
|
|
|
1
|
-
import { homedir } from 'os'
|
|
2
|
-
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
import { addErrorInfo } from '../error/info.js'
|
|
7
|
-
|
|
1
|
+
import { homedir } from 'os';
|
|
2
|
+
import { execa } from 'execa';
|
|
3
|
+
import { pathExists } from 'path-exists';
|
|
4
|
+
import { addErrorInfo } from '../error/info.js';
|
|
8
5
|
// Install Node.js dependencies in a specific directory
|
|
9
6
|
export const installDependencies = function ({ packageRoot, isLocal }) {
|
|
10
|
-
|
|
11
|
-
}
|
|
12
|
-
|
|
7
|
+
return runCommand({ packageRoot, isLocal, type: 'install' });
|
|
8
|
+
};
|
|
13
9
|
// Add new Node.js dependencies, with exact semver ranges
|
|
14
10
|
export const addExactDependencies = function ({ packageRoot, isLocal, packages }) {
|
|
15
|
-
|
|
16
|
-
}
|
|
17
|
-
|
|
11
|
+
return runCommand({ packageRoot, packages, isLocal, type: 'addExact' });
|
|
12
|
+
};
|
|
18
13
|
const runCommand = async function ({ packageRoot, packages = [], isLocal, type }) {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
}
|
|
29
|
-
|
|
14
|
+
try {
|
|
15
|
+
const [command, ...args] = await getCommand({ packageRoot, type, isLocal });
|
|
16
|
+
await execa(command, [...args, ...packages], { cwd: packageRoot, all: true });
|
|
17
|
+
}
|
|
18
|
+
catch (error) {
|
|
19
|
+
const message = getErrorMessage(error.all);
|
|
20
|
+
const errorA = new Error(`Error while installing dependencies in ${packageRoot}\n${message}`);
|
|
21
|
+
addErrorInfo(errorA, { type: 'dependencies' });
|
|
22
|
+
throw errorA;
|
|
23
|
+
}
|
|
24
|
+
};
|
|
30
25
|
// Retrieve the shell command to install or add dependencies
|
|
31
26
|
const getCommand = async function ({ packageRoot, type, isLocal }) {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
}
|
|
37
|
-
|
|
27
|
+
const manager = await getManager(type, packageRoot);
|
|
28
|
+
const command = COMMANDS[manager][type];
|
|
29
|
+
const commandA = addYarnCustomCache(command, manager, isLocal);
|
|
30
|
+
return commandA;
|
|
31
|
+
};
|
|
38
32
|
const getManager = async function (type, packageRoot) {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
return 'npm'
|
|
49
|
-
}
|
|
50
|
-
|
|
33
|
+
// `addDependencies()` always uses npm
|
|
34
|
+
if (type === 'addExact') {
|
|
35
|
+
return 'npm';
|
|
36
|
+
}
|
|
37
|
+
if (await pathExists(`${packageRoot}/yarn.lock`)) {
|
|
38
|
+
return 'yarn';
|
|
39
|
+
}
|
|
40
|
+
return 'npm';
|
|
41
|
+
};
|
|
51
42
|
const COMMANDS = {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
}
|
|
60
|
-
|
|
43
|
+
npm: {
|
|
44
|
+
addExact: ['npm', 'install', '--no-progress', '--no-audit', '--no-fund', '--save-exact'],
|
|
45
|
+
install: ['npm', 'install', '--no-progress', '--no-audit', '--no-fund'],
|
|
46
|
+
},
|
|
47
|
+
yarn: {
|
|
48
|
+
install: ['yarn', 'install', '--no-progress', '--non-interactive'],
|
|
49
|
+
},
|
|
50
|
+
};
|
|
61
51
|
// In CI, yarn uses a custom cache folder
|
|
62
52
|
const addYarnCustomCache = function (command, manager, isLocal) {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
const YARN_CI_CACHE_DIR = `${homedir()}/.yarn_cache`
|
|
71
|
-
|
|
53
|
+
if (manager !== 'yarn' || isLocal) {
|
|
54
|
+
return command;
|
|
55
|
+
}
|
|
56
|
+
return [...command, '--cache-folder', YARN_CI_CACHE_DIR];
|
|
57
|
+
};
|
|
58
|
+
const YARN_CI_CACHE_DIR = `${homedir()}/.yarn_cache`;
|
|
72
59
|
// Retrieve message to add to install errors
|
|
73
60
|
const getErrorMessage = function (allOutput) {
|
|
74
|
-
|
|
75
|
-
}
|
|
76
|
-
|
|
61
|
+
return allOutput.split('\n').filter(isNotNpmLogMessage).join('\n');
|
|
62
|
+
};
|
|
77
63
|
// Debug logs shown at the end of npm errors is not useful in Netlify Build
|
|
78
64
|
const isNotNpmLogMessage = function (line) {
|
|
79
|
-
|
|
80
|
-
}
|
|
81
|
-
const NPM_LOG_MESSAGES = ['complete log of this run', '-debug.log']
|
|
65
|
+
return NPM_LOG_MESSAGES.every((message) => !line.includes(message));
|
|
66
|
+
};
|
|
67
|
+
const NPM_LOG_MESSAGES = ['complete log of this run', '-debug.log'];
|
package/lib/install/missing.js
CHANGED
|
@@ -1,67 +1,54 @@
|
|
|
1
|
-
import { promises as fs } from 'fs'
|
|
2
|
-
import { normalize } from 'path'
|
|
3
|
-
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
import { logInstallMissingPlugins } from '../log/messages/install.js'
|
|
8
|
-
|
|
9
|
-
import { addExactDependencies } from './main.js'
|
|
10
|
-
|
|
1
|
+
import { promises as fs } from 'fs';
|
|
2
|
+
import { normalize } from 'path';
|
|
3
|
+
import { pathExists } from 'path-exists';
|
|
4
|
+
import { isFile } from 'path-type';
|
|
5
|
+
import { logInstallMissingPlugins } from '../log/messages/install.js';
|
|
6
|
+
import { addExactDependencies } from './main.js';
|
|
11
7
|
// Automatically install plugins if not already installed.
|
|
12
8
|
// Since this is done under the hood, we always use `npm` with specific `npm`
|
|
13
9
|
// options. We do not allow configure the package manager nor its options.
|
|
14
10
|
// Users requiring `yarn` or custom npm/yarn flags should install the plugin in
|
|
15
11
|
// their `package.json`.
|
|
16
12
|
export const installMissingPlugins = async function ({ missingPlugins, autoPluginsDir, mode, logs }) {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
}
|
|
23
|
-
|
|
13
|
+
const packages = missingPlugins.map(getPackage);
|
|
14
|
+
logInstallMissingPlugins(logs, packages);
|
|
15
|
+
await createAutoPluginsDir(logs, autoPluginsDir);
|
|
16
|
+
await addExactDependencies({ packageRoot: autoPluginsDir, isLocal: mode !== 'buildbot', packages });
|
|
17
|
+
};
|
|
24
18
|
// We pin the version without using semver ranges ^ nor ~
|
|
25
19
|
const getPackage = function ({ packageName, expectedVersion }) {
|
|
26
|
-
|
|
27
|
-
}
|
|
28
|
-
|
|
20
|
+
return `${packageName}@${expectedVersion}`;
|
|
21
|
+
};
|
|
29
22
|
const createAutoPluginsDir = async function (logs, autoPluginsDir) {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
}
|
|
33
|
-
|
|
23
|
+
await ensureDir(logs, autoPluginsDir);
|
|
24
|
+
await createPackageJson(autoPluginsDir);
|
|
25
|
+
};
|
|
34
26
|
// Create the directory if it does not exist
|
|
35
27
|
const ensureDir = async function (logs, autoPluginsDir) {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
await fs.mkdir(autoPluginsDir, { recursive: true })
|
|
47
|
-
}
|
|
48
|
-
|
|
28
|
+
if (await pathExists(autoPluginsDir)) {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
// If `.netlify` exists but is not a directory, we remove it first
|
|
32
|
+
const autoPluginsParent = normalize(`${autoPluginsDir}/..`);
|
|
33
|
+
if (await isFile(autoPluginsParent)) {
|
|
34
|
+
await fs.unlink(autoPluginsParent);
|
|
35
|
+
}
|
|
36
|
+
await fs.mkdir(autoPluginsDir, { recursive: true });
|
|
37
|
+
};
|
|
49
38
|
// Create a dummy `package.json` so we can run `npm install` and get a lock file
|
|
50
39
|
const createPackageJson = async function (autoPluginsDir) {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
}
|
|
59
|
-
|
|
40
|
+
const packageJsonPath = `${autoPluginsDir}/package.json`;
|
|
41
|
+
if (await pathExists(packageJsonPath)) {
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
const packageJsonContent = JSON.stringify(AUTO_PLUGINS_PACKAGE_JSON, null, 2);
|
|
45
|
+
await fs.writeFile(packageJsonPath, packageJsonContent);
|
|
46
|
+
};
|
|
60
47
|
const AUTO_PLUGINS_PACKAGE_JSON = {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
}
|
|
48
|
+
name: 'netlify-local-plugins',
|
|
49
|
+
description: 'This directory contains Build plugins that have been automatically installed by Netlify.',
|
|
50
|
+
version: '1.0.0',
|
|
51
|
+
private: true,
|
|
52
|
+
author: 'Netlify',
|
|
53
|
+
license: 'MIT',
|
|
54
|
+
};
|
package/lib/log/colors.js
CHANGED
|
@@ -1,34 +1,27 @@
|
|
|
1
|
-
import { inspect } from 'util'
|
|
2
|
-
|
|
3
|
-
import supportsColor from 'supports-color'
|
|
4
|
-
|
|
1
|
+
import { inspect } from 'util';
|
|
2
|
+
import supportsColor from 'supports-color';
|
|
5
3
|
// Plugin child processes use `stdio: 'pipe'` so they are always
|
|
6
4
|
// non-interactive even if the parent is an interactive TTY. This means they
|
|
7
5
|
// would normally lose colors. If the parent has colors, we pass an environment
|
|
8
6
|
// variable to the child process to force colors.
|
|
9
7
|
export const getParentColorEnv = function () {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
}
|
|
16
|
-
|
|
8
|
+
if (!hasColors()) {
|
|
9
|
+
return {};
|
|
10
|
+
}
|
|
11
|
+
return { FORCE_COLOR: '1' };
|
|
12
|
+
};
|
|
17
13
|
// Child processes and the buildbot relies on `FORCE_COLOR=1` to set colors.
|
|
18
14
|
// However `utils.inspect()` (used by `console.log()`) uses
|
|
19
15
|
// `process.stdout.hasColors` which is always `undefined` when the TTY is
|
|
20
16
|
// non-interactive. So we need to set `util.inspect.defaultOptions.colors`
|
|
21
17
|
// manually both in plugin processes.
|
|
22
18
|
export const setInspectColors = function () {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
inspect.defaultOptions.colors = true
|
|
30
|
-
}
|
|
31
|
-
|
|
19
|
+
if (!hasColors()) {
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
// `inspect.defaultOptions` requires direct mutation
|
|
23
|
+
inspect.defaultOptions.colors = true;
|
|
24
|
+
};
|
|
32
25
|
const hasColors = function () {
|
|
33
|
-
|
|
34
|
-
}
|
|
26
|
+
return supportsColor.stdout !== false;
|
|
27
|
+
};
|
package/lib/log/description.js
CHANGED
|
@@ -1,26 +1,21 @@
|
|
|
1
1
|
export const getBuildCommandDescription = function (buildCommandOrigin) {
|
|
2
|
-
|
|
3
|
-
}
|
|
4
|
-
|
|
2
|
+
return BUILD_COMMAND_DESCRIPTIONS[buildCommandOrigin];
|
|
3
|
+
};
|
|
5
4
|
const BUILD_COMMAND_DESCRIPTIONS = {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
}
|
|
10
|
-
|
|
5
|
+
ui: 'Build command from Netlify app',
|
|
6
|
+
config: 'build.command from netlify.toml',
|
|
7
|
+
inline: 'build.command from a plugin',
|
|
8
|
+
};
|
|
11
9
|
// Retrieve human-friendly plugin origin
|
|
12
10
|
export const getPluginOrigin = function (loadedFrom, origin) {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
return `from ${originName}`
|
|
20
|
-
}
|
|
21
|
-
|
|
11
|
+
const originName = PLUGIN_ORIGINS[origin];
|
|
12
|
+
if (loadedFrom === 'package.json') {
|
|
13
|
+
return `from ${originName} and package.json`;
|
|
14
|
+
}
|
|
15
|
+
return `from ${originName}`;
|
|
16
|
+
};
|
|
22
17
|
const PLUGIN_ORIGINS = {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
}
|
|
18
|
+
core: 'core',
|
|
19
|
+
ui: 'Netlify app',
|
|
20
|
+
config: 'netlify.toml',
|
|
21
|
+
};
|
package/lib/log/header.js
CHANGED
|
@@ -1,16 +1,14 @@
|
|
|
1
|
-
import stringWidth from 'string-width'
|
|
2
|
-
|
|
1
|
+
import stringWidth from 'string-width';
|
|
3
2
|
// Print a rectangular header
|
|
4
3
|
export const getHeader = function (message) {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
4
|
+
const messageWidth = stringWidth(message);
|
|
5
|
+
const headerWidth = Math.max(HEADER_MIN_WIDTH, messageWidth);
|
|
6
|
+
const line = '─'.repeat(headerWidth + PADDING_WIDTH * 2);
|
|
7
|
+
const paddingLeft = ' '.repeat(PADDING_WIDTH);
|
|
8
|
+
const paddingRight = ' '.repeat(PADDING_WIDTH + headerWidth - messageWidth);
|
|
9
|
+
return `${line}
|
|
11
10
|
${paddingLeft}${message}${paddingRight}
|
|
12
|
-
${line}
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
const
|
|
16
|
-
const PADDING_WIDTH = 2
|
|
11
|
+
${line}`;
|
|
12
|
+
};
|
|
13
|
+
const HEADER_MIN_WIDTH = 60;
|
|
14
|
+
const PADDING_WIDTH = 2;
|
package/lib/log/header_func.js
CHANGED
|
@@ -1,17 +1,13 @@
|
|
|
1
|
-
import { parseErrorInfo } from '../error/parse/parse.js'
|
|
2
|
-
|
|
3
|
-
import { logHeader, logErrorHeader } from './logger.js'
|
|
4
|
-
|
|
1
|
+
import { parseErrorInfo } from '../error/parse/parse.js';
|
|
2
|
+
import { logHeader, logErrorHeader } from './logger.js';
|
|
5
3
|
// Retrieve successful or error header depending on whether `error` exists
|
|
6
4
|
export const getLogHeaderFunc = function (error) {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
return logErrorHeader
|
|
17
|
-
}
|
|
5
|
+
if (error === undefined) {
|
|
6
|
+
return logHeader;
|
|
7
|
+
}
|
|
8
|
+
const { severity } = parseErrorInfo(error);
|
|
9
|
+
if (severity === 'none') {
|
|
10
|
+
return logHeader;
|
|
11
|
+
}
|
|
12
|
+
return logErrorHeader;
|
|
13
|
+
};
|
package/lib/log/logger.js
CHANGED
|
@@ -1,161 +1,130 @@
|
|
|
1
|
-
import { createWriteStream } from 'fs'
|
|
2
|
-
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
|
|
6
|
-
import {
|
|
7
|
-
import { serializeObject, serializeArray } from './serialize.js'
|
|
8
|
-
import { THEME } from './theme.js'
|
|
9
|
-
|
|
1
|
+
import { createWriteStream } from 'fs';
|
|
2
|
+
import figures from 'figures';
|
|
3
|
+
import indentString from 'indent-string';
|
|
4
|
+
import { getHeader } from './header.js';
|
|
5
|
+
import { serializeObject, serializeArray } from './serialize.js';
|
|
6
|
+
import { THEME } from './theme.js';
|
|
10
7
|
// When the `buffer` option is true, we return logs instead of printing them
|
|
11
8
|
// on the console. The logs are accumulated in a `logs` array variable.
|
|
12
9
|
export const getBufferLogs = function ({ buffer = false }) {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
}
|
|
19
|
-
|
|
10
|
+
if (!buffer) {
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
return { stdout: [], stderr: [] };
|
|
14
|
+
};
|
|
20
15
|
// Core logging utility, used by the other methods.
|
|
21
16
|
// This should be used instead of `console.log()` as it allows us to instrument
|
|
22
17
|
// how any build logs is being printed.
|
|
23
18
|
export const log = function (logs, string, { indent = false, color } = {}) {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
console.log(stringC)
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
const INDENT_SIZE = 2
|
|
39
|
-
|
|
19
|
+
const stringA = indent ? indentString(string, INDENT_SIZE) : string;
|
|
20
|
+
const stringB = String(stringA).replace(EMPTY_LINES_REGEXP, EMPTY_LINE);
|
|
21
|
+
const stringC = color === undefined ? stringB : color(stringB);
|
|
22
|
+
if (logs !== undefined) {
|
|
23
|
+
// `logs` is a stateful variable
|
|
24
|
+
logs.stdout.push(stringC);
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
console.log(stringC);
|
|
28
|
+
};
|
|
29
|
+
const INDENT_SIZE = 2;
|
|
40
30
|
// We need to add a zero width space character in empty lines. Otherwise the
|
|
41
31
|
// buildbot removes those due to a bug: https://github.com/netlify/buildbot/issues/595
|
|
42
|
-
const EMPTY_LINES_REGEXP = /^\s*$/gm
|
|
43
|
-
const EMPTY_LINE = '\u{200B}'
|
|
44
|
-
|
|
32
|
+
const EMPTY_LINES_REGEXP = /^\s*$/gm;
|
|
33
|
+
const EMPTY_LINE = '\u{200B}';
|
|
45
34
|
const serializeIndentedArray = function (array) {
|
|
46
|
-
|
|
47
|
-
}
|
|
48
|
-
|
|
35
|
+
return serializeArray(array.map(serializeIndentedItem));
|
|
36
|
+
};
|
|
49
37
|
const serializeIndentedItem = function (item) {
|
|
50
|
-
|
|
51
|
-
}
|
|
52
|
-
|
|
38
|
+
return indentString(item, INDENT_SIZE + 1).trimStart();
|
|
39
|
+
};
|
|
53
40
|
export const logError = function (logs, string, opts) {
|
|
54
|
-
|
|
55
|
-
}
|
|
56
|
-
|
|
41
|
+
log(logs, string, { color: THEME.errorLine, ...opts });
|
|
42
|
+
};
|
|
57
43
|
export const logWarning = function (logs, string, opts) {
|
|
58
|
-
|
|
59
|
-
}
|
|
60
|
-
|
|
44
|
+
log(logs, string, { color: THEME.warningLine, ...opts });
|
|
45
|
+
};
|
|
61
46
|
// Print a message that is under a header/subheader, i.e. indented
|
|
62
47
|
export const logMessage = function (logs, string, opts) {
|
|
63
|
-
|
|
64
|
-
}
|
|
65
|
-
|
|
48
|
+
log(logs, string, { indent: true, ...opts });
|
|
49
|
+
};
|
|
66
50
|
// Print an object
|
|
67
51
|
export const logObject = function (logs, object, opts) {
|
|
68
|
-
|
|
69
|
-
}
|
|
70
|
-
|
|
52
|
+
logMessage(logs, serializeObject(object), opts);
|
|
53
|
+
};
|
|
71
54
|
// Print an array
|
|
72
55
|
export const logArray = function (logs, array, opts) {
|
|
73
|
-
|
|
74
|
-
}
|
|
75
|
-
|
|
56
|
+
logMessage(logs, serializeIndentedArray(array), { color: THEME.none, ...opts });
|
|
57
|
+
};
|
|
76
58
|
// Print an array of errors
|
|
77
59
|
export const logErrorArray = function (logs, array, opts) {
|
|
78
|
-
|
|
79
|
-
}
|
|
80
|
-
|
|
60
|
+
logMessage(logs, serializeIndentedArray(array), { color: THEME.errorLine, ...opts });
|
|
61
|
+
};
|
|
81
62
|
// Print an array of warnings
|
|
82
63
|
export const logWarningArray = function (logs, array, opts) {
|
|
83
|
-
|
|
84
|
-
}
|
|
85
|
-
|
|
64
|
+
logMessage(logs, serializeIndentedArray(array), { color: THEME.warningLine, ...opts });
|
|
65
|
+
};
|
|
86
66
|
// Print a main section header
|
|
87
67
|
export const logHeader = function (logs, string, opts) {
|
|
88
|
-
|
|
89
|
-
}
|
|
90
|
-
|
|
68
|
+
log(logs, `\n${getHeader(string)}`, { color: THEME.header, ...opts });
|
|
69
|
+
};
|
|
91
70
|
// Print a main section header, when an error happened
|
|
92
71
|
export const logErrorHeader = function (logs, string, opts) {
|
|
93
|
-
|
|
94
|
-
}
|
|
95
|
-
|
|
72
|
+
logHeader(logs, string, { color: THEME.errorHeader, ...opts });
|
|
73
|
+
};
|
|
96
74
|
// Print a sub-section header
|
|
97
75
|
export const logSubHeader = function (logs, string, opts) {
|
|
98
|
-
|
|
99
|
-
}
|
|
100
|
-
|
|
76
|
+
log(logs, `\n${figures.pointer} ${string}`, { color: THEME.subHeader, ...opts });
|
|
77
|
+
};
|
|
101
78
|
// Print a sub-section header, when an error happened
|
|
102
79
|
export const logErrorSubHeader = function (logs, string, opts) {
|
|
103
|
-
|
|
104
|
-
}
|
|
105
|
-
|
|
80
|
+
logSubHeader(logs, string, { color: THEME.errorSubHeader, ...opts });
|
|
81
|
+
};
|
|
106
82
|
// Print a sub-section header, when a warning happened
|
|
107
83
|
export const logWarningSubHeader = function (logs, string, opts) {
|
|
108
|
-
|
|
109
|
-
}
|
|
110
|
-
|
|
84
|
+
logSubHeader(logs, string, { color: THEME.warningSubHeader, ...opts });
|
|
85
|
+
};
|
|
111
86
|
// Combines an array of elements into a single string, separated by a space,
|
|
112
87
|
// and with basic serialization of non-string types
|
|
113
88
|
const reduceLogLines = function (lines) {
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
if (typeof input === 'object') {
|
|
121
|
-
try {
|
|
122
|
-
return JSON.stringify(input)
|
|
123
|
-
} catch {
|
|
124
|
-
// Value could not be serialized to JSON, so we return the string
|
|
125
|
-
// representation.
|
|
126
|
-
return String(input)
|
|
89
|
+
return lines
|
|
90
|
+
.map((input) => {
|
|
91
|
+
if (input instanceof Error) {
|
|
92
|
+
return `${input.message} ${input.stack}`;
|
|
127
93
|
}
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
94
|
+
if (typeof input === 'object') {
|
|
95
|
+
try {
|
|
96
|
+
return JSON.stringify(input);
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
// Value could not be serialized to JSON, so we return the string
|
|
100
|
+
// representation.
|
|
101
|
+
return String(input);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return String(input);
|
|
131
105
|
})
|
|
132
|
-
|
|
133
|
-
}
|
|
134
|
-
|
|
106
|
+
.join(' ');
|
|
107
|
+
};
|
|
135
108
|
// Builds a function for logging data to the system logger (i.e. hidden from
|
|
136
109
|
// the user-facing build logs)
|
|
137
110
|
export const getSystemLogger = function (logs, debug, systemLogFile) {
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
111
|
+
// If the `debug` flag is used, we return a function that pipes system logs
|
|
112
|
+
// to the regular logger, as the intention is for them to end up in stdout.
|
|
113
|
+
if (debug) {
|
|
114
|
+
return (...args) => log(logs, reduceLogLines(args));
|
|
115
|
+
}
|
|
116
|
+
// If there's not a file descriptor configured for system logs and `debug`
|
|
117
|
+
// is not set, we return a no-op function that will swallow the errors.
|
|
118
|
+
if (!systemLogFile) {
|
|
119
|
+
return () => {
|
|
120
|
+
// no-op
|
|
121
|
+
};
|
|
149
122
|
}
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
})
|
|
159
|
-
|
|
160
|
-
return (...args) => fileDescriptor.write(`${reduceLogLines(args)}\n`)
|
|
161
|
-
}
|
|
123
|
+
// Return a function that writes to the file descriptor configured for system
|
|
124
|
+
// logs.
|
|
125
|
+
const fileDescriptor = createWriteStream(null, { fd: systemLogFile });
|
|
126
|
+
fileDescriptor.on('error', () => {
|
|
127
|
+
logError(logs, 'Could not write to system log file');
|
|
128
|
+
});
|
|
129
|
+
return (...args) => fileDescriptor.write(`${reduceLogLines(args)}\n`);
|
|
130
|
+
};
|