@netlify/build 29.0.0-rc → 29.0.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/bin.js +5 -0
- package/lib/core/bin.js +66 -0
- package/lib/core/build.js +356 -0
- package/lib/core/config.js +121 -0
- package/lib/core/constants.js +116 -0
- package/lib/core/dev.js +27 -0
- package/lib/core/dry.js +21 -0
- package/lib/core/feature_flags.js +21 -0
- package/lib/core/flags.js +201 -0
- package/lib/core/lingering.js +68 -0
- package/lib/core/main.js +110 -0
- package/lib/core/missing_side_file.js +17 -0
- package/lib/core/normalize_flags.js +59 -0
- package/lib/core/severity.js +21 -0
- package/lib/core/types.js +8 -0
- package/lib/core/user_node_version.js +32 -0
- package/lib/env/changes.js +43 -0
- package/lib/env/main.js +14 -0
- package/lib/env/metadata.js +68 -0
- package/lib/error/api.js +37 -0
- package/lib/error/build.js +36 -0
- package/{src → lib}/error/cancel.js +5 -6
- package/lib/error/colors.js +9 -0
- package/lib/error/handle.js +46 -0
- package/lib/error/info.js +37 -0
- package/lib/error/monitor/location.js +16 -0
- package/lib/error/monitor/normalize.js +86 -0
- package/lib/error/monitor/print.js +20 -0
- package/lib/error/monitor/report.js +120 -0
- package/lib/error/monitor/start.js +61 -0
- package/lib/error/parse/clean_stack.js +70 -0
- package/lib/error/parse/location.js +50 -0
- package/lib/error/parse/normalize.js +24 -0
- package/lib/error/parse/parse.js +67 -0
- package/lib/error/parse/plugin.js +55 -0
- package/lib/error/parse/properties.js +16 -0
- package/lib/error/parse/serialize_log.js +34 -0
- package/lib/error/parse/serialize_status.js +18 -0
- package/lib/error/parse/stack.js +34 -0
- package/lib/error/report.js +27 -0
- package/lib/error/type.js +177 -0
- package/lib/install/functions.js +20 -0
- package/lib/install/local.js +45 -0
- package/lib/install/main.js +67 -0
- package/lib/install/missing.js +54 -0
- package/lib/log/colors.js +28 -0
- package/lib/log/description.js +21 -0
- package/lib/log/header.js +14 -0
- package/lib/log/header_func.js +13 -0
- package/lib/log/logger.js +140 -0
- package/lib/log/messages/compatibility.js +146 -0
- package/lib/log/messages/config.js +91 -0
- package/lib/log/messages/core.js +51 -0
- package/lib/log/messages/core_steps.js +75 -0
- package/lib/log/messages/dry.js +41 -0
- package/lib/log/messages/install.js +25 -0
- package/lib/log/messages/ipc.js +29 -0
- package/lib/log/messages/mutations.js +62 -0
- package/{src → lib}/log/messages/plugins.js +18 -32
- package/lib/log/messages/status.js +14 -0
- package/lib/log/messages/steps.js +18 -0
- package/lib/log/old_version.js +32 -0
- package/lib/log/serialize.js +10 -0
- package/lib/log/stream.js +68 -0
- package/lib/log/theme.js +27 -0
- package/lib/plugins/child/diff.js +46 -0
- package/lib/plugins/child/error.js +26 -0
- package/lib/plugins/child/lazy.js +15 -0
- package/lib/plugins/child/load.js +22 -0
- package/lib/plugins/child/logic.js +57 -0
- package/lib/plugins/child/main.js +37 -0
- package/lib/plugins/child/run.js +19 -0
- package/lib/plugins/child/status.js +63 -0
- package/lib/plugins/child/typescript.js +28 -0
- package/lib/plugins/child/utils.js +42 -0
- package/lib/plugins/child/validate.js +31 -0
- package/lib/plugins/compatibility.js +104 -0
- package/{src → lib}/plugins/error.js +31 -35
- package/{src → lib}/plugins/events.js +7 -12
- package/lib/plugins/expected_version.js +81 -0
- package/lib/plugins/internal.js +10 -0
- package/lib/plugins/ipc.js +120 -0
- package/lib/plugins/list.js +73 -0
- package/lib/plugins/load.js +50 -0
- package/lib/plugins/manifest/check.js +85 -0
- package/lib/plugins/manifest/load.js +38 -0
- package/lib/plugins/manifest/main.js +19 -0
- package/lib/plugins/manifest/path.js +24 -0
- package/lib/plugins/manifest/validate.js +91 -0
- package/lib/plugins/node_version.js +35 -0
- package/lib/plugins/options.js +70 -0
- package/lib/plugins/pinned_version.js +83 -0
- package/lib/plugins/resolve.js +110 -0
- package/lib/plugins/spawn.js +58 -0
- package/lib/plugins_core/add.js +35 -0
- package/lib/plugins_core/build_command.js +50 -0
- package/lib/plugins_core/deploy/buildbot_client.js +87 -0
- package/lib/plugins_core/deploy/index.js +49 -0
- package/{src → lib}/plugins_core/deploy/manifest.yml +0 -0
- package/lib/plugins_core/edge_functions/index.js +76 -0
- package/{src → lib}/plugins_core/edge_functions/lib/error.js +13 -17
- package/lib/plugins_core/edge_functions/validate_manifest/validate_edge_functions_manifest.js +21 -0
- package/lib/plugins_core/functions/error.js +123 -0
- package/lib/plugins_core/functions/feature_flags.js +6 -0
- package/lib/plugins_core/functions/index.js +114 -0
- package/lib/plugins_core/functions/utils.js +45 -0
- package/lib/plugins_core/functions/zisi.js +39 -0
- package/{src → lib}/plugins_core/functions_install/index.js +8 -11
- package/{src → lib}/plugins_core/functions_install/manifest.yml +0 -0
- package/lib/plugins_core/list.js +20 -0
- package/lib/report/statsd.js +31 -0
- package/lib/status/add.js +30 -0
- package/lib/status/colors.js +18 -0
- package/lib/status/load_error.js +10 -0
- package/lib/status/report.js +83 -0
- package/lib/status/success.js +14 -0
- package/lib/steps/core_step.js +59 -0
- package/lib/steps/error.js +65 -0
- package/lib/steps/get.js +43 -0
- package/lib/steps/plugin.js +55 -0
- package/lib/steps/return.js +25 -0
- package/lib/steps/run_core_steps.js +117 -0
- package/lib/steps/run_step.js +190 -0
- package/lib/steps/run_steps.js +96 -0
- package/lib/steps/update_config.js +66 -0
- package/lib/telemetry/main.js +97 -0
- package/lib/time/aggregate.js +109 -0
- package/lib/time/main.js +31 -0
- package/lib/time/measure.js +16 -0
- package/lib/time/report.js +24 -0
- package/lib/utils/errors.js +13 -0
- package/lib/utils/json.js +15 -0
- package/lib/utils/omit.js +3 -0
- package/lib/utils/package.js +24 -0
- package/lib/utils/remove_falsy.js +8 -0
- package/lib/utils/resolve.js +41 -0
- package/lib/utils/runtime.js +5 -0
- package/lib/utils/semver.js +28 -0
- package/package.json +41 -24
- package/types/config/netlify_config.d.ts +4 -4
- package/types/netlify_plugin_constants.d.ts +8 -8
- package/src/core/bin.js +0 -83
- package/src/core/build.js +0 -554
- package/src/core/config.js +0 -186
- package/src/core/constants.js +0 -156
- package/src/core/dev.js +0 -31
- package/src/core/dry.js +0 -39
- package/src/core/feature_flags.js +0 -22
- package/src/core/flags.js +0 -204
- package/src/core/lingering.js +0 -85
- package/src/core/main.js +0 -165
- package/src/core/missing_side_file.js +0 -29
- package/src/core/normalize_flags.js +0 -70
- package/src/core/severity.js +0 -22
- package/src/core/user_node_version.js +0 -41
- package/src/env/changes.js +0 -52
- package/src/env/main.js +0 -19
- package/src/env/metadata.js +0 -81
- package/src/error/api.js +0 -46
- package/src/error/build.js +0 -50
- package/src/error/colors.js +0 -11
- package/src/error/handle.js +0 -57
- package/src/error/info.js +0 -46
- package/src/error/monitor/location.js +0 -21
- package/src/error/monitor/normalize.js +0 -96
- package/src/error/monitor/print.js +0 -42
- package/src/error/monitor/report.js +0 -138
- package/src/error/monitor/start.js +0 -69
- package/src/error/parse/clean_stack.js +0 -87
- package/src/error/parse/location.js +0 -62
- package/src/error/parse/normalize.js +0 -29
- package/src/error/parse/parse.js +0 -97
- package/src/error/parse/plugin.js +0 -70
- package/src/error/parse/properties.js +0 -23
- package/src/error/parse/serialize_log.js +0 -42
- package/src/error/parse/serialize_status.js +0 -23
- package/src/error/parse/stack.js +0 -43
- package/src/error/type.js +0 -189
- package/src/install/functions.js +0 -28
- package/src/install/local.js +0 -62
- package/src/install/main.js +0 -81
- package/src/install/missing.js +0 -67
- package/src/log/colors.js +0 -34
- package/src/log/description.js +0 -26
- package/src/log/header.js +0 -16
- package/src/log/header_func.js +0 -17
- package/src/log/logger.js +0 -161
- package/src/log/messages/compatibility.js +0 -164
- package/src/log/messages/config.js +0 -107
- package/src/log/messages/core.js +0 -70
- package/src/log/messages/core_steps.js +0 -104
- package/src/log/messages/dry.js +0 -63
- package/src/log/messages/install.js +0 -20
- package/src/log/messages/ipc.js +0 -38
- package/src/log/messages/mutations.js +0 -82
- package/src/log/messages/status.js +0 -16
- package/src/log/messages/steps.js +0 -22
- package/src/log/old_version.js +0 -41
- package/src/log/serialize.js +0 -13
- package/src/log/stream.js +0 -85
- package/src/log/theme.js +0 -26
- package/src/plugins/child/diff.js +0 -55
- package/src/plugins/child/error.js +0 -32
- package/src/plugins/child/lazy.js +0 -18
- package/src/plugins/child/load.js +0 -29
- package/src/plugins/child/logic.js +0 -57
- package/src/plugins/child/main.js +0 -51
- package/src/plugins/child/run.js +0 -28
- package/src/plugins/child/status.js +0 -74
- package/src/plugins/child/typescript.js +0 -45
- package/src/plugins/child/utils.js +0 -56
- package/src/plugins/child/validate.js +0 -34
- package/src/plugins/compatibility.js +0 -128
- package/src/plugins/expected_version.js +0 -119
- package/src/plugins/ipc.js +0 -145
- package/src/plugins/list.js +0 -86
- package/src/plugins/load.js +0 -70
- package/src/plugins/manifest/check.js +0 -106
- package/src/plugins/manifest/load.js +0 -41
- package/src/plugins/manifest/main.js +0 -22
- package/src/plugins/manifest/path.js +0 -31
- package/src/plugins/manifest/validate.js +0 -108
- package/src/plugins/node_version.js +0 -50
- package/src/plugins/options.js +0 -88
- package/src/plugins/pinned_version.js +0 -131
- package/src/plugins/resolve.js +0 -152
- package/src/plugins/spawn.js +0 -66
- package/src/plugins_core/add.js +0 -49
- package/src/plugins_core/build_command.js +0 -75
- package/src/plugins_core/deploy/buildbot_client.js +0 -102
- package/src/plugins_core/deploy/index.js +0 -73
- package/src/plugins_core/edge_functions/index.js +0 -123
- package/src/plugins_core/edge_functions/lib/internal_manifest.js +0 -54
- package/src/plugins_core/edge_functions/validate_manifest/validate_edge_functions_manifest.js +0 -89
- package/src/plugins_core/functions/error.js +0 -163
- package/src/plugins_core/functions/feature_flags.js +0 -6
- package/src/plugins_core/functions/index.js +0 -160
- package/src/plugins_core/functions/utils.js +0 -66
- package/src/plugins_core/functions/zisi.js +0 -53
- package/src/plugins_core/list.js +0 -27
- package/src/status/add.js +0 -36
- package/src/status/colors.js +0 -23
- package/src/status/load_error.js +0 -11
- package/src/status/report.js +0 -137
- package/src/status/success.js +0 -18
- package/src/steps/core_step.js +0 -92
- package/src/steps/error.js +0 -102
- package/src/steps/get.js +0 -51
- package/src/steps/plugin.js +0 -85
- package/src/steps/return.js +0 -52
- package/src/steps/run_core_steps.js +0 -200
- package/src/steps/run_step.js +0 -304
- package/src/steps/run_steps.js +0 -179
- package/src/steps/update_config.js +0 -93
- package/src/telemetry/main.js +0 -136
- package/src/time/aggregate.js +0 -146
- package/src/time/main.js +0 -48
- package/src/time/measure.js +0 -22
- package/src/time/report.js +0 -59
- package/src/utils/errors.js +0 -12
- package/src/utils/json.js +0 -19
- package/src/utils/omit.js +0 -6
- package/src/utils/package.js +0 -23
- package/src/utils/remove_falsy.js +0 -10
- package/src/utils/resolve.js +0 -46
- package/src/utils/semver.js +0 -34
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { env } from 'process';
|
|
2
|
+
import filterObj from 'filter-obj';
|
|
3
|
+
// Retrieve enviroment variables used in error monitoring
|
|
4
|
+
export const getEnvMetadata = function (childEnv = env) {
|
|
5
|
+
return filterObj(childEnv, isEnvMetadata);
|
|
6
|
+
};
|
|
7
|
+
const isEnvMetadata = function (name) {
|
|
8
|
+
return ENVIRONMENT_VARIABLES.has(name);
|
|
9
|
+
};
|
|
10
|
+
// This is sorted by most useful in debugging to least
|
|
11
|
+
const ENVIRONMENT_VARIABLES = new Set([
|
|
12
|
+
// URL and IDs
|
|
13
|
+
'BUILD_ID',
|
|
14
|
+
'DEPLOY_ID',
|
|
15
|
+
'SITE_NAME',
|
|
16
|
+
'SITE_ID',
|
|
17
|
+
'REPOSITORY_URL',
|
|
18
|
+
'URL',
|
|
19
|
+
'DEPLOY_URL',
|
|
20
|
+
'DEPLOY_PRIME_URL',
|
|
21
|
+
// Git
|
|
22
|
+
'HEAD',
|
|
23
|
+
'COMMIT_REF',
|
|
24
|
+
'CACHED_COMMIT_REF',
|
|
25
|
+
'BRANCH',
|
|
26
|
+
'CONTEXT',
|
|
27
|
+
'PULL_REQUEST',
|
|
28
|
+
'REVIEW_ID',
|
|
29
|
+
// Node
|
|
30
|
+
'NODE_VERSION',
|
|
31
|
+
'AWS_LAMBDA_JS_RUNTIME',
|
|
32
|
+
'NPM_VERSION',
|
|
33
|
+
'YARN_VERSION',
|
|
34
|
+
'NPM_FLAGS',
|
|
35
|
+
'YARN_FLAGS',
|
|
36
|
+
'NVM_FLAGS',
|
|
37
|
+
'NODE_ENV',
|
|
38
|
+
// Go
|
|
39
|
+
'GO_VERSION',
|
|
40
|
+
'GO_IMPORT_PATH',
|
|
41
|
+
'GOCACHE',
|
|
42
|
+
'GOPATH',
|
|
43
|
+
'GOROOT',
|
|
44
|
+
// Ruby
|
|
45
|
+
'RUBY_VERSION',
|
|
46
|
+
'GEM_HOME',
|
|
47
|
+
'GEM_PATH',
|
|
48
|
+
'GIMME_GCO_ENABLED',
|
|
49
|
+
'GIMME_ENV_PREFIX',
|
|
50
|
+
'GIMME_GO_PREFIX',
|
|
51
|
+
'GIMME_NO_ENV_ALIAS',
|
|
52
|
+
'GIMME_TYPE',
|
|
53
|
+
'IRBRC',
|
|
54
|
+
'MY_RUBY_HOME',
|
|
55
|
+
// Hugo
|
|
56
|
+
'HUGO_VERSION',
|
|
57
|
+
// Java
|
|
58
|
+
'JAVA_VERSION',
|
|
59
|
+
// PHP
|
|
60
|
+
'PHP_VERSION',
|
|
61
|
+
// Python
|
|
62
|
+
'PIPENV_DEFAULT_PYTHON_VERSION',
|
|
63
|
+
'PIPENV_RUNTIME',
|
|
64
|
+
'PIPENV_VENV_IN_PROJECT',
|
|
65
|
+
// Git LFS
|
|
66
|
+
'GIT_LFS_ENABLED',
|
|
67
|
+
'GIT_LFS_FETCH_INCLUDE',
|
|
68
|
+
]);
|
package/lib/error/api.js
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import isPlainObj from 'is-plain-obj';
|
|
2
|
+
import mapObj from 'map-obj';
|
|
3
|
+
import { addErrorInfo } from './info.js';
|
|
4
|
+
// Wrap `api.*` methods so that they add more error information
|
|
5
|
+
export const addApiErrorHandlers = function (api) {
|
|
6
|
+
if (api === undefined) {
|
|
7
|
+
return;
|
|
8
|
+
}
|
|
9
|
+
return mapObj(api, addErrorHandler);
|
|
10
|
+
};
|
|
11
|
+
const addErrorHandler = function (key, value) {
|
|
12
|
+
if (typeof value !== 'function') {
|
|
13
|
+
return [key, value];
|
|
14
|
+
}
|
|
15
|
+
const valueA = apiMethodHandler.bind(null, key, value);
|
|
16
|
+
return [key, valueA];
|
|
17
|
+
};
|
|
18
|
+
const apiMethodHandler = async function (endpoint, method, parameters, ...args) {
|
|
19
|
+
try {
|
|
20
|
+
return await method(parameters, ...args);
|
|
21
|
+
}
|
|
22
|
+
catch (error) {
|
|
23
|
+
redactError(error);
|
|
24
|
+
addErrorInfo(error, { type: 'api', location: { endpoint, parameters } });
|
|
25
|
+
throw error;
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
// Redact API token from the build logs
|
|
29
|
+
const redactError = function (error) {
|
|
30
|
+
if (error instanceof Error &&
|
|
31
|
+
isPlainObj(error.data) &&
|
|
32
|
+
isPlainObj(error.data.headers) &&
|
|
33
|
+
typeof error.data.headers.Authorization === 'string') {
|
|
34
|
+
error.data.headers.Authorization = error.data.headers.Authorization.replace(HEX_REGEXP, 'HEX');
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
const HEX_REGEXP = /[\da-f]{6,}/g;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import safeJsonStringify from 'safe-json-stringify';
|
|
2
|
+
import { CUSTOM_ERROR_KEY } from './info.js';
|
|
3
|
+
// Retrieve error information from child process and re-build it in current
|
|
4
|
+
// process. We need this since errors static properties are not kept by
|
|
5
|
+
// `v8.serialize()`.
|
|
6
|
+
export const jsonToError = function ({ name, message, stack, ...errorProps }) {
|
|
7
|
+
const error = new Error('');
|
|
8
|
+
assignErrorProps(error, { name, message, stack });
|
|
9
|
+
// Assign static error properties (if any)
|
|
10
|
+
// We need to mutate the `error` directly to preserve its `name`, `stack`, etc.
|
|
11
|
+
Object.assign(error, errorProps);
|
|
12
|
+
return error;
|
|
13
|
+
};
|
|
14
|
+
// Make sure `name`, `message` and `stack` are not enumerable
|
|
15
|
+
const assignErrorProps = function (error, values) {
|
|
16
|
+
ERROR_PROPS.forEach((name) => {
|
|
17
|
+
assignErrorProp(error, name, values[name]);
|
|
18
|
+
});
|
|
19
|
+
};
|
|
20
|
+
const ERROR_PROPS = ['name', 'message', 'stack'];
|
|
21
|
+
const assignErrorProp = function (error, name, value) {
|
|
22
|
+
// `Object.defineProperty()` requires direct mutation
|
|
23
|
+
Object.defineProperty(error, name, { value, enumerable: false, writable: true, configurable: true });
|
|
24
|
+
};
|
|
25
|
+
// Inverse of `jsonToError()`.
|
|
26
|
+
export const errorToJson = function (error) {
|
|
27
|
+
const { name, message, stack, [CUSTOM_ERROR_KEY]: customError, ...errorProps } = error;
|
|
28
|
+
// diagnosticText is not enumerable in TSError so we need to grab it manually. destructuring won't work.
|
|
29
|
+
if (error.diagnosticText) {
|
|
30
|
+
errorProps.diagnosticText = error.diagnosticText;
|
|
31
|
+
}
|
|
32
|
+
return {
|
|
33
|
+
...safeJsonStringify.ensureProperties(errorProps),
|
|
34
|
+
...safeJsonStringify.ensureProperties({ name, message, stack, [CUSTOM_ERROR_KEY]: customError }),
|
|
35
|
+
};
|
|
36
|
+
};
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
// Cancel builds, for example when a plugin uses `utils.build.cancelBuild()`
|
|
2
2
|
export const cancelBuild = async function ({ api, deployId }) {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
}
|
|
3
|
+
if (api === undefined || !deployId) {
|
|
4
|
+
return;
|
|
5
|
+
}
|
|
6
|
+
await api.cancelSiteDeploy({ deploy_id: deployId });
|
|
7
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import stripAnsi from 'strip-ansi';
|
|
2
|
+
// Remove ANSI sequences from `error.message`
|
|
3
|
+
export const removeErrorColors = function (error) {
|
|
4
|
+
if (!(error instanceof Error)) {
|
|
5
|
+
return;
|
|
6
|
+
}
|
|
7
|
+
error.message = stripAnsi(error.message);
|
|
8
|
+
error.stack = stripAnsi(error.stack);
|
|
9
|
+
};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { cwd as getCwd } from 'process';
|
|
2
|
+
import { pathExists } from 'path-exists';
|
|
3
|
+
import { logBuildError } from '../log/messages/core.js';
|
|
4
|
+
import { logOldCliVersionError } from '../log/old_version.js';
|
|
5
|
+
import { removeErrorColors } from './colors.js';
|
|
6
|
+
import { getErrorInfo } from './info.js';
|
|
7
|
+
import { reportBuildError } from './monitor/report.js';
|
|
8
|
+
import { parseErrorInfo } from './parse/parse.js';
|
|
9
|
+
// Logs and reports a build failure
|
|
10
|
+
export const handleBuildError = async function (error, { errorMonitor, netlifyConfig, childEnv, mode, logs, debug, testOpts }) {
|
|
11
|
+
const basicErrorInfo = parseErrorInfo(error);
|
|
12
|
+
if (await isCancelCrash(error)) {
|
|
13
|
+
return basicErrorInfo;
|
|
14
|
+
}
|
|
15
|
+
removeErrorColors(error);
|
|
16
|
+
// Some errors, such as telemetry ones, should not be logged
|
|
17
|
+
if (basicErrorInfo.showInBuildLog) {
|
|
18
|
+
logBuildError({ error, netlifyConfig, mode, logs, debug, testOpts });
|
|
19
|
+
}
|
|
20
|
+
logOldCliVersionError({ mode, testOpts });
|
|
21
|
+
await reportBuildError({ error, errorMonitor, childEnv, logs, testOpts });
|
|
22
|
+
return basicErrorInfo;
|
|
23
|
+
};
|
|
24
|
+
// When builds are canceled, the whole filesystem is being deleted.
|
|
25
|
+
// However, the process (and build) keeps going. Because no files exist anymore,
|
|
26
|
+
// the build eventually crashes with a randomly odd error. Those should not be
|
|
27
|
+
// logged nor reported.
|
|
28
|
+
// However builds canceled with `utils.build.cancelBuild()` should still show
|
|
29
|
+
// "Build canceled by ..."
|
|
30
|
+
const isCancelCrash = async function (error) {
|
|
31
|
+
const [{ type }] = getErrorInfo(error);
|
|
32
|
+
if (type === 'cancelBuild') {
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
try {
|
|
36
|
+
// TODO: find a better way to detect that the build is being cancelled.
|
|
37
|
+
// Otherwise bugs due to (for example) the build command removing
|
|
38
|
+
// `process.cwd` are currently not logged/reported.
|
|
39
|
+
const cwd = getCwd();
|
|
40
|
+
return !(await pathExists(cwd));
|
|
41
|
+
// `process.cwd()` fails when the current directory does not exist
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
return true;
|
|
45
|
+
}
|
|
46
|
+
};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
// Add information related to an error without colliding with existing properties
|
|
2
|
+
export const addDefaultErrorInfo = function (error, info) {
|
|
3
|
+
if (!canHaveErrorInfo(error)) {
|
|
4
|
+
return;
|
|
5
|
+
}
|
|
6
|
+
error[CUSTOM_ERROR_KEY] = { ...info, ...error[CUSTOM_ERROR_KEY] };
|
|
7
|
+
};
|
|
8
|
+
// Retrieve error information added by our system
|
|
9
|
+
export const addErrorInfo = function (error, info) {
|
|
10
|
+
if (!canHaveErrorInfo(error)) {
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
error[CUSTOM_ERROR_KEY] = { ...error[CUSTOM_ERROR_KEY], ...info };
|
|
14
|
+
};
|
|
15
|
+
export const getErrorInfo = function (error) {
|
|
16
|
+
if (!isBuildError(error)) {
|
|
17
|
+
return [{}, error];
|
|
18
|
+
}
|
|
19
|
+
const { [CUSTOM_ERROR_KEY]: errorInfo, ...errorA } = error;
|
|
20
|
+
return [errorInfo, errorA];
|
|
21
|
+
};
|
|
22
|
+
// Change error type from one to another
|
|
23
|
+
export const changeErrorType = function (error, oldType, newType) {
|
|
24
|
+
const [{ type }] = getErrorInfo(error);
|
|
25
|
+
if (type === oldType) {
|
|
26
|
+
addErrorInfo(error, { type: newType });
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
export const isBuildError = function (error) {
|
|
30
|
+
return canHaveErrorInfo(error) && error[CUSTOM_ERROR_KEY] !== undefined;
|
|
31
|
+
};
|
|
32
|
+
// Exceptions that are not objects (including `Error` instances) cannot have an
|
|
33
|
+
// `CUSTOM_ERROR_KEY` property
|
|
34
|
+
const canHaveErrorInfo = function (error) {
|
|
35
|
+
return error != null;
|
|
36
|
+
};
|
|
37
|
+
export const CUSTOM_ERROR_KEY = 'customErrorInfo';
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// Retrieve plugin's location and build logs
|
|
2
|
+
export const getLocationMetadata = function (location, envMetadata) {
|
|
3
|
+
const buildLogs = getBuildLogs(envMetadata);
|
|
4
|
+
if (buildLogs === undefined && location === undefined) {
|
|
5
|
+
return;
|
|
6
|
+
}
|
|
7
|
+
return { buildLogs, ...location };
|
|
8
|
+
};
|
|
9
|
+
// Retrieve the URL to the build logs
|
|
10
|
+
const getBuildLogs = function ({ SITE_NAME, DEPLOY_ID }) {
|
|
11
|
+
if (SITE_NAME === undefined || DEPLOY_ID === undefined) {
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
return `${NETLIFY_ORIGIN}/sites/${SITE_NAME}/deploys/${DEPLOY_ID}`;
|
|
15
|
+
};
|
|
16
|
+
const NETLIFY_ORIGIN = 'https://app.netlify.com';
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
// We group errors by `error.message`. However some `error.message` contain
|
|
2
|
+
// unique IDs, etc. which defeats that grouping. So we normalize those to make
|
|
3
|
+
// them consistent
|
|
4
|
+
export const normalizeGroupingMessage = function (message, type) {
|
|
5
|
+
const messageA = removeDependenciesLogs(message, type);
|
|
6
|
+
const messageB = NORMALIZE_REGEXPS.reduce(normalizeMessage, messageA);
|
|
7
|
+
// If this is a functions bundling error, we'll use additional normalization
|
|
8
|
+
// rules to group errors more aggressively.
|
|
9
|
+
if (type === 'functionsBundling') {
|
|
10
|
+
return FUNCTIONS_BUNDLING_REGEXPS.reduce(normalizeMessage, messageB);
|
|
11
|
+
}
|
|
12
|
+
return messageB;
|
|
13
|
+
};
|
|
14
|
+
// Discard debug/info installation information
|
|
15
|
+
const removeDependenciesLogs = function (message, type) {
|
|
16
|
+
if (type !== 'dependencies') {
|
|
17
|
+
return message;
|
|
18
|
+
}
|
|
19
|
+
return message.split('\n').filter(isErrorLine).join('\n');
|
|
20
|
+
};
|
|
21
|
+
const isErrorLine = function (line) {
|
|
22
|
+
return ERROR_LINES.some((errorLine) => line.startsWith(errorLine));
|
|
23
|
+
};
|
|
24
|
+
const ERROR_LINES = [
|
|
25
|
+
// Prefix for npm
|
|
26
|
+
'npm ERR!',
|
|
27
|
+
// Prefix for Yarn
|
|
28
|
+
'error',
|
|
29
|
+
];
|
|
30
|
+
const normalizeMessage = function (message, [regExp, replacement]) {
|
|
31
|
+
return message.replace(regExp, replacement);
|
|
32
|
+
};
|
|
33
|
+
const NORMALIZE_REGEXPS = [
|
|
34
|
+
// Base64 URL
|
|
35
|
+
[/(data:[^;]+;base64),[\w+/-=]+/g, 'dataURI'],
|
|
36
|
+
// File paths
|
|
37
|
+
[/(["'`, ]|^)([^"'`, \n]*[/\\][^"'`, \n]*)(?=["'`, ]|$)/gm, '$1/file/path'],
|
|
38
|
+
// Semantic versions
|
|
39
|
+
[/\d+\.\d+\.\d+(-\d+)?/g, '1.0.0'],
|
|
40
|
+
[/version "[^"]+"/g, 'version "1.0.0"'],
|
|
41
|
+
// Cypress plugin prints the user's platform
|
|
42
|
+
[/^Platform: .*/gm, ''],
|
|
43
|
+
// URLs
|
|
44
|
+
[/https?:[\w.+~!$&'()*,;=:@/?#]+/g, 'https://domain.com'],
|
|
45
|
+
// Numbers, e.g. number of issues/problems
|
|
46
|
+
[/\d+/g, '0'],
|
|
47
|
+
// Hexadecimal strings
|
|
48
|
+
[/[\da-fA-F-]{6,}/g, 'hex'],
|
|
49
|
+
// On unknown inputs, we print the inputs
|
|
50
|
+
[/(does not accept any inputs but you specified: ).*/, '$1'],
|
|
51
|
+
[/(Unknown inputs for plugin).*/, '$1'],
|
|
52
|
+
[/(Plugin inputs should be one of: ).*/, '$1'],
|
|
53
|
+
// On required inputs, we print the inputs
|
|
54
|
+
[/^Plugin inputs[^]*/gm, ''],
|
|
55
|
+
[/(Required inputs for plugin).*/gm, '$1'],
|
|
56
|
+
// Netlify Functions validation check
|
|
57
|
+
[/(should target a directory, not a regular file):.*/, '$1'],
|
|
58
|
+
// zip-it-and-ship-it error when there is an `import()` but dependencies
|
|
59
|
+
// were not installed
|
|
60
|
+
[/(Cannot find module) '([^']+)'/g, "$1 'moduleName'"],
|
|
61
|
+
[/(A Netlify Function is using) "[^"]+"/g, '$1 "moduleName"'],
|
|
62
|
+
// Deploy upload errors include the filename
|
|
63
|
+
[/(Upload cancelled).*/g, '$1'],
|
|
64
|
+
[/(aborting upload of file).*/g, '$1'],
|
|
65
|
+
// netlify-plugin-inline-critical-css errors prints a list of file paths
|
|
66
|
+
[/Searched in: .*/g, ''],
|
|
67
|
+
// netlify-plugin-subfont prints font name in errors
|
|
68
|
+
[/(is not supported yet): .*/, '$1'],
|
|
69
|
+
// netlify-plugin-subfont prints generic information in every error that
|
|
70
|
+
// is highly build-specific
|
|
71
|
+
[/^(vers?ions|Plugin configuration|Subfont called with): {[^}]+}/gm, ''],
|
|
72
|
+
[/^Resolved entry points: \[[^\]]+]/gm, ''],
|
|
73
|
+
// netlify-plugin-minify-html parse error
|
|
74
|
+
[/(Parse Error):[^]*/, '$1'],
|
|
75
|
+
// Multiple empty lines
|
|
76
|
+
[/^\s*$/gm, ''],
|
|
77
|
+
];
|
|
78
|
+
const FUNCTIONS_BUNDLING_REGEXPS = [
|
|
79
|
+
// String literals and identifiers
|
|
80
|
+
[/"([^"]+)"/g, '""'],
|
|
81
|
+
[/'([^']+)'/g, "''"],
|
|
82
|
+
[/`([^`]+)`/g, '``'],
|
|
83
|
+
// Rust crates
|
|
84
|
+
[/(?:Downloaded \S+ v[\d.]+\s*)+/gm, 'Downloaded crates'],
|
|
85
|
+
[/(?:Compiling \S+ v[\d.]+\s*)+/gm, 'Compiled crates'],
|
|
86
|
+
];
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { log } from '../../log/logger.js';
|
|
2
|
+
// Print event payload instead of sending actual request during tests
|
|
3
|
+
export const printEventForTest = function ({ name: errorClass, message: errorMessage }, { context, groupingHash, severity, unhandled, _metadata: { location, plugin: { packageName, homepage } = {}, pluginPackageJson, tsConfig, env: { BUILD_ID } = {}, other, }, }, logs) {
|
|
4
|
+
const eventString = JSON.stringify({
|
|
5
|
+
errorClass,
|
|
6
|
+
errorMessage,
|
|
7
|
+
context,
|
|
8
|
+
groupingHash,
|
|
9
|
+
severity,
|
|
10
|
+
unhandled,
|
|
11
|
+
location,
|
|
12
|
+
packageName,
|
|
13
|
+
pluginPackageJson: pluginPackageJson !== undefined,
|
|
14
|
+
homepage,
|
|
15
|
+
tsConfig,
|
|
16
|
+
BUILD_ID,
|
|
17
|
+
other,
|
|
18
|
+
}, null, 2);
|
|
19
|
+
log(logs, `\nError monitoring payload:\n${eventString}`);
|
|
20
|
+
};
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { type as osType, freemem, totalmem } from 'os';
|
|
2
|
+
import { promisify } from 'util';
|
|
3
|
+
import osName from 'os-name';
|
|
4
|
+
import { getEnvMetadata } from '../../env/metadata.js';
|
|
5
|
+
import { log } from '../../log/logger.js';
|
|
6
|
+
import { parseErrorInfo } from '../parse/parse.js';
|
|
7
|
+
import { getHomepage } from '../parse/plugin.js';
|
|
8
|
+
import { getLocationMetadata } from './location.js';
|
|
9
|
+
import { normalizeGroupingMessage } from './normalize.js';
|
|
10
|
+
import { printEventForTest } from './print.js';
|
|
11
|
+
// Report a build failure for monitoring purpose
|
|
12
|
+
export const reportBuildError = async function ({ error, errorMonitor, childEnv, logs, testOpts }) {
|
|
13
|
+
if (errorMonitor === undefined) {
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
const { errorInfo, type, severity, title, group = title } = parseErrorInfo(error);
|
|
17
|
+
const severityA = getSeverity(severity, errorInfo);
|
|
18
|
+
const groupA = getGroup(group, errorInfo);
|
|
19
|
+
const groupingHash = getGroupingHash(groupA, error, type, errorInfo);
|
|
20
|
+
const metadata = getMetadata(errorInfo, childEnv, groupingHash);
|
|
21
|
+
const app = getApp();
|
|
22
|
+
const eventProps = getEventProps({ severity: severityA, group: groupA, groupingHash, metadata, app });
|
|
23
|
+
const errorName = updateErrorName(error, type);
|
|
24
|
+
try {
|
|
25
|
+
await reportError({ errorMonitor, error, logs, testOpts, eventProps });
|
|
26
|
+
}
|
|
27
|
+
finally {
|
|
28
|
+
error.name = errorName;
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
// Plugin authors test their plugins as local plugins. Errors there are more
|
|
32
|
+
// like development errors, and should be reported as `info` only.
|
|
33
|
+
const getSeverity = function (severity, { location: { loadedFrom } = {} }) {
|
|
34
|
+
if (loadedFrom === 'local' || severity === 'none') {
|
|
35
|
+
return 'info';
|
|
36
|
+
}
|
|
37
|
+
return severity;
|
|
38
|
+
};
|
|
39
|
+
const getGroup = function (group, errorInfo) {
|
|
40
|
+
if (typeof group !== 'function') {
|
|
41
|
+
return group;
|
|
42
|
+
}
|
|
43
|
+
return group(errorInfo);
|
|
44
|
+
};
|
|
45
|
+
const getGroupingHash = function (group, error, type, errorInfo = {}) {
|
|
46
|
+
// If the error has a `normalizedMessage`, we use it as the grouping hash.
|
|
47
|
+
if (errorInfo.normalizedMessage) {
|
|
48
|
+
return errorInfo.normalizedMessage;
|
|
49
|
+
}
|
|
50
|
+
const message = error instanceof Error && typeof error.message === 'string' ? error.message : String(error);
|
|
51
|
+
const messageA = normalizeGroupingMessage(message, type);
|
|
52
|
+
return `${group}\n${messageA}`;
|
|
53
|
+
};
|
|
54
|
+
const getMetadata = function ({ location, plugin, tsConfig }, childEnv, groupingHash) {
|
|
55
|
+
const pluginMetadata = getPluginMetadata({ location, plugin });
|
|
56
|
+
const envMetadata = getEnvMetadata(childEnv);
|
|
57
|
+
const locationMetadata = getLocationMetadata(location, envMetadata);
|
|
58
|
+
return { location: locationMetadata, ...pluginMetadata, tsConfig, env: envMetadata, other: { groupingHash } };
|
|
59
|
+
};
|
|
60
|
+
const getPluginMetadata = function ({ location, plugin }) {
|
|
61
|
+
if (plugin === undefined) {
|
|
62
|
+
return {};
|
|
63
|
+
}
|
|
64
|
+
const { pluginPackageJson, ...pluginA } = plugin;
|
|
65
|
+
const homepage = getHomepage(pluginPackageJson, location);
|
|
66
|
+
return { plugin: { ...pluginA, homepage }, pluginPackageJson };
|
|
67
|
+
};
|
|
68
|
+
const getApp = function () {
|
|
69
|
+
return {
|
|
70
|
+
osName: osType(),
|
|
71
|
+
osVersion: osName(),
|
|
72
|
+
freeMemory: freemem(),
|
|
73
|
+
totalMemory: totalmem(),
|
|
74
|
+
};
|
|
75
|
+
};
|
|
76
|
+
// `error.name` is shown proeminently in the Bugsnag UI. We need to update it to
|
|
77
|
+
// match error `type` since it is more granular and useful.
|
|
78
|
+
// But we change it back after Bugsnag is done reporting.
|
|
79
|
+
const updateErrorName = function (error, type) {
|
|
80
|
+
const { name } = error;
|
|
81
|
+
// This might fail if `name` is a getter or is non-writable.
|
|
82
|
+
try {
|
|
83
|
+
error.name = type;
|
|
84
|
+
}
|
|
85
|
+
catch {
|
|
86
|
+
// continue regardless error
|
|
87
|
+
}
|
|
88
|
+
return name;
|
|
89
|
+
};
|
|
90
|
+
const reportError = async function ({ errorMonitor, error, logs, testOpts, eventProps }) {
|
|
91
|
+
if (testOpts.errorMonitor) {
|
|
92
|
+
printEventForTest(error, eventProps, logs);
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
try {
|
|
96
|
+
await promisify(errorMonitor.notify)(error, (event) => onError(event, eventProps));
|
|
97
|
+
// Failsafe
|
|
98
|
+
}
|
|
99
|
+
catch {
|
|
100
|
+
log(logs, `Error monitor could not notify\n${error.stack}`);
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
const getEventProps = function ({ severity, group, groupingHash, metadata, app }) {
|
|
104
|
+
// `unhandled` is used to calculate Releases "stabiity score", which is
|
|
105
|
+
// basically the percentage of unhandled errors. Since we handle all errors,
|
|
106
|
+
// we need to implement this according to error types.
|
|
107
|
+
const unhandled = severity === 'error';
|
|
108
|
+
return { severity, context: group, groupingHash, _metadata: metadata, app, unhandled };
|
|
109
|
+
};
|
|
110
|
+
// Add more information to Bugsnag events
|
|
111
|
+
const onError = function (event, eventProps) {
|
|
112
|
+
// Bugsnag client requires directly mutating the `event`
|
|
113
|
+
Object.assign(event, {
|
|
114
|
+
...eventProps,
|
|
115
|
+
unhandled: event.unhandled || eventProps.unhandled,
|
|
116
|
+
_metadata: { ...event._metadata, ...eventProps._metadata },
|
|
117
|
+
app: { ...event.app, ...eventProps.app },
|
|
118
|
+
});
|
|
119
|
+
return true;
|
|
120
|
+
};
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { fileURLToPath } from 'url';
|
|
2
|
+
import Bugsnag from '@bugsnag/js';
|
|
3
|
+
import memoizeOne from 'memoize-one';
|
|
4
|
+
import { log } from '../../log/logger.js';
|
|
5
|
+
import { ROOT_PACKAGE_JSON } from '../../utils/json.js';
|
|
6
|
+
const projectRoot = fileURLToPath(new URL('../../..', import.meta.url));
|
|
7
|
+
// Start a client to monitor errors
|
|
8
|
+
export const startErrorMonitor = function (config) {
|
|
9
|
+
const { flags: { mode }, logs, bugsnagKey, } = config;
|
|
10
|
+
if (!bugsnagKey) {
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
const isTest = isBugsnagTest(bugsnagKey);
|
|
14
|
+
const releaseStage = getReleaseStage(mode);
|
|
15
|
+
const logger = getLogger(logs, isTest);
|
|
16
|
+
try {
|
|
17
|
+
const errorMonitor = startBugsnag({
|
|
18
|
+
apiKey: bugsnagKey,
|
|
19
|
+
appVersion: `${ROOT_PACKAGE_JSON.name} ${ROOT_PACKAGE_JSON.version}`,
|
|
20
|
+
appType: ROOT_PACKAGE_JSON.name,
|
|
21
|
+
releaseStage,
|
|
22
|
+
logger,
|
|
23
|
+
projectRoot,
|
|
24
|
+
});
|
|
25
|
+
// Allows knowing the percentage of failed builds per release
|
|
26
|
+
if (!isTest) {
|
|
27
|
+
errorMonitor.startSession();
|
|
28
|
+
}
|
|
29
|
+
return errorMonitor;
|
|
30
|
+
// Failsafe
|
|
31
|
+
}
|
|
32
|
+
catch (error) {
|
|
33
|
+
log(logs, `Error monitor could not start\n${error.stack}`);
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
const isBugsnagTest = function (bugsnagKey) {
|
|
37
|
+
return bugsnagKey === BUGSNAG_TEST_KEY;
|
|
38
|
+
};
|
|
39
|
+
const BUGSNAG_TEST_KEY = '00000000000000000000000000000000';
|
|
40
|
+
// Bugsnag.start() caches a global instance and warns on duplicate calls.
|
|
41
|
+
// This ensures the warning message is not shown when calling the main function
|
|
42
|
+
// several times.
|
|
43
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
44
|
+
// @ts-ignore
|
|
45
|
+
const startBugsnag = memoizeOne(Bugsnag.start.bind(Bugsnag), () => true);
|
|
46
|
+
// Based the release stage on the `mode`
|
|
47
|
+
const getReleaseStage = function (mode = DEFAULT_RELEASE_STAGE) {
|
|
48
|
+
return mode;
|
|
49
|
+
};
|
|
50
|
+
const DEFAULT_RELEASE_STAGE = 'unknown';
|
|
51
|
+
// We don't want Bugsnag logs except on warnings/errors.
|
|
52
|
+
// We also want to use our own `log` utility, unprefixed.
|
|
53
|
+
// In tests, we don't print Bugsnag because it sometimes randomly fails to
|
|
54
|
+
// send sessions, which prints warning messags in test snapshots.
|
|
55
|
+
const getLogger = function (logs, isTest) {
|
|
56
|
+
const logFunc = isTest ? noop : log.bind(null, logs);
|
|
57
|
+
return { debug: noop, info: noop, warn: logFunc, error: logFunc };
|
|
58
|
+
};
|
|
59
|
+
const noop = function () {
|
|
60
|
+
// this is a noop function
|
|
61
|
+
};
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { cwd } from 'process';
|
|
2
|
+
import cleanStack from 'clean-stack';
|
|
3
|
+
import stripAnsi from 'strip-ansi';
|
|
4
|
+
// Clean stack traces:
|
|
5
|
+
// - remove our internal code, e.g. the logic spawning plugins
|
|
6
|
+
// - remove node modules and Node.js internals
|
|
7
|
+
// - strip process.cwd()
|
|
8
|
+
// - remove colors
|
|
9
|
+
// Keep non stack trace lines as is.
|
|
10
|
+
// We do not use libraries that patch `Error.prepareStackTrace()` because they
|
|
11
|
+
// tend to create issues.
|
|
12
|
+
export const cleanStacks = function ({ stack, rawStack, debug }) {
|
|
13
|
+
if (stack === undefined) {
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
// Internal errors / bugs keep their full stack trace
|
|
17
|
+
// Same in debug mode
|
|
18
|
+
if (rawStack || debug) {
|
|
19
|
+
return stack;
|
|
20
|
+
}
|
|
21
|
+
return stack.split('\n').reduce(cleanStackLine, '').replace(INITIAL_NEWLINES, '');
|
|
22
|
+
};
|
|
23
|
+
const cleanStackLine = function (lines, line) {
|
|
24
|
+
const lineA = line.replace(getCwd(), '');
|
|
25
|
+
const lineB = stripAnsi(lineA);
|
|
26
|
+
if (!STACK_LINE_REGEXP.test(lineB)) {
|
|
27
|
+
return `${lines}\n${lineA}`;
|
|
28
|
+
}
|
|
29
|
+
if (shouldRemoveStackLine(lineB)) {
|
|
30
|
+
return lines;
|
|
31
|
+
}
|
|
32
|
+
const lineC = cleanStack(lineB);
|
|
33
|
+
if (lineC === '') {
|
|
34
|
+
return lines;
|
|
35
|
+
}
|
|
36
|
+
return `${lines}\n${lineC}`;
|
|
37
|
+
};
|
|
38
|
+
// `process.cwd()` can sometimes fail: directory name too long, current
|
|
39
|
+
// directory has been removed, access denied.
|
|
40
|
+
const getCwd = function () {
|
|
41
|
+
try {
|
|
42
|
+
return cwd();
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
return '';
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
// Check if a line is part of a stack trace
|
|
49
|
+
const STACK_LINE_REGEXP = /^\s+at /;
|
|
50
|
+
const shouldRemoveStackLine = function (line) {
|
|
51
|
+
const lineA = normalizePathSlashes(line);
|
|
52
|
+
return INTERNAL_STACK_STRINGS.some((stackString) => lineA.includes(stackString)) || INTERNAL_STACK_REGEXP.test(lineA);
|
|
53
|
+
};
|
|
54
|
+
const INTERNAL_STACK_STRINGS = [
|
|
55
|
+
// Anonymous function
|
|
56
|
+
'<anonymous>',
|
|
57
|
+
'(index 0)',
|
|
58
|
+
// nyc internal code
|
|
59
|
+
'node_modules/append-transform',
|
|
60
|
+
'node_modules/signal-exit',
|
|
61
|
+
// Node internals
|
|
62
|
+
'(node:',
|
|
63
|
+
];
|
|
64
|
+
// This is only needed for local builds and tests
|
|
65
|
+
const INTERNAL_STACK_REGEXP = /(lib\/|tests\/helpers\/|tests\/.*\/tests.js|node_modules)/;
|
|
66
|
+
const INITIAL_NEWLINES = /^\n+/;
|
|
67
|
+
const normalizePathSlashes = function (line) {
|
|
68
|
+
return line.replace(BACKLASH_REGEXP, '/');
|
|
69
|
+
};
|
|
70
|
+
const BACKLASH_REGEXP = /\\/g;
|