@netlify/build 0.5.0 → 1.0.0-dl-test
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 +392 -0
- package/lib/core/config.js +124 -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 +17 -0
- package/lib/core/flags.js +206 -0
- package/lib/core/lingering.js +68 -0
- package/lib/core/main.js +114 -0
- package/lib/core/missing_side_file.js +17 -0
- package/lib/core/normalize_flags.js +62 -0
- package/lib/core/report_metrics.js +17 -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/lib/error/cancel.js +7 -0
- package/lib/error/colors.js +9 -0
- package/lib/error/handle.js +44 -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 +29 -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 +12 -0
- package/lib/log/header_func.js +13 -0
- package/lib/log/logger.js +140 -0
- package/lib/log/messages/compatibility.js +120 -0
- package/lib/log/messages/config.js +91 -0
- package/lib/log/messages/core.js +49 -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/lib/log/messages/plugins.js +25 -0
- package/lib/log/messages/status.js +14 -0
- package/lib/log/messages/steps.js +18 -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/lib/plugins/error.js +46 -0
- package/lib/plugins/events.js +12 -0
- 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 +55 -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/lib/plugins_core/deploy/manifest.yml +1 -0
- package/lib/plugins_core/edge_functions/index.js +106 -0
- package/lib/plugins_core/edge_functions/lib/error.js +17 -0
- package/lib/plugins_core/edge_functions/validate_manifest/validate_edge_functions_manifest.js +14 -0
- package/lib/plugins_core/functions/error.js +123 -0
- package/lib/plugins_core/functions/feature_flags.js +5 -0
- package/lib/plugins_core/functions/index.js +137 -0
- package/lib/plugins_core/functions/utils.js +45 -0
- package/lib/plugins_core/functions/zisi.js +64 -0
- package/lib/plugins_core/functions_install/index.js +10 -0
- package/lib/plugins_core/list.js +20 -0
- package/lib/plugins_core/save_artifacts/index.js +33 -0
- package/lib/report/statsd.js +56 -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 +62 -0
- package/lib/steps/error.js +65 -0
- package/lib/steps/get.js +44 -0
- package/lib/steps/plugin.js +55 -0
- package/lib/steps/return.js +27 -0
- package/lib/steps/run_core_steps.js +117 -0
- package/lib/steps/run_step.js +200 -0
- package/lib/steps/run_steps.js +102 -0
- package/lib/steps/update_config.js +66 -0
- package/lib/telemetry/main.js +94 -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 +30 -0
- package/lib/utils/errors.js +13 -0
- package/lib/utils/json.js +10 -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 +119 -56
- package/types/config/build.d.ts +52 -0
- package/types/config/functions.d.ts +36 -0
- package/types/config/inputs.d.ts +7 -0
- package/types/config/netlify_config.d.ts +58 -0
- package/types/index.d.ts +7 -0
- package/types/netlify_event_handler.d.ts +29 -0
- package/types/netlify_plugin.d.ts +29 -0
- package/types/netlify_plugin_constants.d.ts +51 -0
- package/types/netlify_plugin_options.d.ts +23 -0
- package/types/options/index.d.ts +1 -0
- package/types/options/netlify_plugin_build_util.d.ts +7 -0
- package/types/options/netlify_plugin_cache_util.d.ts +39 -0
- package/types/options/netlify_plugin_functions_util.d.ts +32 -0
- package/types/options/netlify_plugin_git_util.d.ts +41 -0
- package/types/options/netlify_plugin_run_util.d.ts +24 -0
- package/types/options/netlify_plugin_status_util.d.ts +24 -0
- package/types/options/netlify_plugin_utils.d.ts +15 -0
- package/types/utils/json_value.d.ts +1 -0
- package/types/utils/many.d.ts +6 -0
- package/README.md +0 -3
- package/src/core/bin.js +0 -139
- package/src/core/commands.js +0 -304
- package/src/core/config.js +0 -130
- package/src/core/constants.js +0 -86
- package/src/core/dry.js +0 -23
- package/src/core/main.js +0 -196
- package/src/env/changes.js +0 -49
- package/src/env/git.js +0 -27
- package/src/env/main.js +0 -97
- package/src/env/metadata.js +0 -81
- package/src/error/api.js +0 -32
- package/src/error/build.js +0 -32
- package/src/error/cancel.js +0 -22
- package/src/error/colors.js +0 -13
- package/src/error/info.js +0 -12
- package/src/error/monitor/normalize.js +0 -50
- package/src/error/monitor/print.js +0 -43
- package/src/error/monitor/report.js +0 -140
- package/src/error/monitor/start.js +0 -50
- package/src/error/parse/clean_stack.js +0 -86
- package/src/error/parse/location.js +0 -50
- package/src/error/parse/parse.js +0 -87
- package/src/error/parse/plugin.js +0 -68
- package/src/error/parse/properties.js +0 -20
- package/src/error/parse/serialize_log.js +0 -46
- package/src/error/parse/serialize_status.js +0 -28
- package/src/error/parse/stack.js +0 -45
- package/src/error/process.js +0 -13
- package/src/error/type.js +0 -143
- package/src/install/functions.js +0 -62
- package/src/install/local.js +0 -74
- package/src/install/main.js +0 -103
- package/src/install/missing.js +0 -86
- package/src/log/colors.js +0 -59
- package/src/log/description.js +0 -38
- package/src/log/header.js +0 -19
- package/src/log/logger.js +0 -55
- package/src/log/main.js +0 -290
- package/src/log/old_version.js +0 -45
- package/src/log/serialize.js +0 -15
- package/src/log/stream.js +0 -15
- package/src/log/theme.js +0 -32
- package/src/log/timer.js +0 -28
- package/src/plugins/child/api.js +0 -59
- package/src/plugins/child/error.js +0 -39
- package/src/plugins/child/load.js +0 -37
- package/src/plugins/child/logic.js +0 -31
- package/src/plugins/child/main.js +0 -48
- package/src/plugins/child/run.js +0 -30
- package/src/plugins/child/status.js +0 -53
- package/src/plugins/child/utils.js +0 -43
- package/src/plugins/child/validate.js +0 -71
- package/src/plugins/error.js +0 -73
- package/src/plugins/events.js +0 -77
- package/src/plugins/ipc.js +0 -136
- package/src/plugins/load.js +0 -66
- package/src/plugins/manifest/check.js +0 -80
- package/src/plugins/manifest/load.js +0 -54
- package/src/plugins/manifest/main.js +0 -24
- package/src/plugins/manifest/path.js +0 -12
- package/src/plugins/manifest/validate.js +0 -136
- package/src/plugins/node_version.js +0 -74
- package/src/plugins/options.js +0 -78
- package/src/plugins/package.js +0 -17
- package/src/plugins/resolve.js +0 -159
- package/src/plugins/spawn.js +0 -82
- package/src/plugins_core/cache/manifest.yml +0 -1
- package/src/plugins_core/cache/plugin.js +0 -75
- package/src/plugins_core/functions/manifest.yml +0 -1
- package/src/plugins_core/functions/plugin.js +0 -37
- package/src/plugins_core/functions_install/plugin.js +0 -14
- package/src/plugins_core/main.js +0 -38
- package/src/status/add.js +0 -56
- package/src/status/colors.js +0 -25
- package/src/status/report.js +0 -57
- package/src/telemetry/complete.js +0 -49
- package/src/telemetry/request.js +0 -28
- package/src/telemetry/track.js +0 -33
- package/src/utils/omit.js +0 -8
- package/src/utils/polyfills.js +0 -3
- package/src/utils/remove_falsy.js +0 -12
- package/src/utils/resolve.js +0 -39
- /package/{src → lib}/plugins_core/functions_install/manifest.yml +0 -0
|
@@ -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;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { getBuildCommandDescription, getPluginOrigin } from '../../log/description.js';
|
|
2
|
+
// Retrieve an error's location to print in logs.
|
|
3
|
+
// Each error type has its own logic (or none if there's no location to print).
|
|
4
|
+
export const getLocationInfo = function ({ stack, location, locationType }) {
|
|
5
|
+
// No location to print
|
|
6
|
+
if (locationType === undefined && stack === undefined) {
|
|
7
|
+
return;
|
|
8
|
+
}
|
|
9
|
+
// The location is only the stack trace
|
|
10
|
+
if (locationType === undefined) {
|
|
11
|
+
return stack;
|
|
12
|
+
}
|
|
13
|
+
const locationString = LOCATIONS[locationType](location);
|
|
14
|
+
return [locationString, stack].filter(Boolean).join('\n');
|
|
15
|
+
};
|
|
16
|
+
const getBuildCommandLocation = function ({ buildCommand, buildCommandOrigin }) {
|
|
17
|
+
const description = getBuildCommandDescription(buildCommandOrigin);
|
|
18
|
+
return `In ${description}:
|
|
19
|
+
${buildCommand}`;
|
|
20
|
+
};
|
|
21
|
+
const getFunctionsBundlingLocation = function ({ functionName, functionType }) {
|
|
22
|
+
if (functionType === 'edge') {
|
|
23
|
+
return 'While bundling edge function';
|
|
24
|
+
}
|
|
25
|
+
return `While bundling function "${functionName}"`;
|
|
26
|
+
};
|
|
27
|
+
const getCoreStepLocation = function ({ coreStepName }) {
|
|
28
|
+
return `During ${coreStepName}`;
|
|
29
|
+
};
|
|
30
|
+
const getBuildFailLocation = function ({ event, packageName, loadedFrom, origin }) {
|
|
31
|
+
const eventMessage = getEventMessage(event);
|
|
32
|
+
const pluginOrigin = getPluginOrigin(loadedFrom, origin);
|
|
33
|
+
return `${eventMessage} "${packageName}" ${pluginOrigin}`;
|
|
34
|
+
};
|
|
35
|
+
const getEventMessage = function (event) {
|
|
36
|
+
if (event === 'load') {
|
|
37
|
+
return `While loading`;
|
|
38
|
+
}
|
|
39
|
+
return `In "${event}" event in`;
|
|
40
|
+
};
|
|
41
|
+
const getApiLocation = function ({ endpoint, parameters }) {
|
|
42
|
+
return `While calling the Netlify API endpoint '${endpoint}' with:\n${JSON.stringify(parameters, null, 2)}`;
|
|
43
|
+
};
|
|
44
|
+
const LOCATIONS = {
|
|
45
|
+
buildCommand: getBuildCommandLocation,
|
|
46
|
+
functionsBundling: getFunctionsBundlingLocation,
|
|
47
|
+
coreStep: getCoreStepLocation,
|
|
48
|
+
buildFail: getBuildFailLocation,
|
|
49
|
+
api: getApiLocation,
|
|
50
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// Ensure error is an `Error` instance.
|
|
2
|
+
// If is an `Error` instance but is missing usual `Error` properties, we make
|
|
3
|
+
// sure its static properties are preserved.
|
|
4
|
+
export const normalizeError = function (error) {
|
|
5
|
+
if (Array.isArray(error)) {
|
|
6
|
+
return normalizeArray(error);
|
|
7
|
+
}
|
|
8
|
+
if (!(error instanceof Error)) {
|
|
9
|
+
return new Error(String(error));
|
|
10
|
+
}
|
|
11
|
+
if (typeof error.message !== 'string') {
|
|
12
|
+
error.message = String(error);
|
|
13
|
+
}
|
|
14
|
+
if (typeof error.stack !== 'string') {
|
|
15
|
+
Error.captureStackTrace(error, normalizeError);
|
|
16
|
+
}
|
|
17
|
+
return error;
|
|
18
|
+
};
|
|
19
|
+
// Some libraries throw arrays of Errors
|
|
20
|
+
const normalizeArray = function (errorArray) {
|
|
21
|
+
const [error, ...errors] = errorArray.map(normalizeError);
|
|
22
|
+
error.errors = errors;
|
|
23
|
+
return error;
|
|
24
|
+
};
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { serializeObject } from '../../log/serialize.js';
|
|
2
|
+
import { getErrorInfo } from '../info.js';
|
|
3
|
+
import { getTypeInfo } from '../type.js';
|
|
4
|
+
import { getLocationInfo } from './location.js';
|
|
5
|
+
import { normalizeError } from './normalize.js';
|
|
6
|
+
import { getPluginInfo } from './plugin.js';
|
|
7
|
+
import { getErrorProps } from './properties.js';
|
|
8
|
+
import { getStackInfo } from './stack.js';
|
|
9
|
+
// Add additional type-specific error information
|
|
10
|
+
export const getFullErrorInfo = function ({ error, colors, debug }) {
|
|
11
|
+
const basicErrorInfo = parseErrorInfo(error);
|
|
12
|
+
const { message, stack, errorProps, errorInfo, errorInfo: { location = {}, plugin = {}, tsConfig }, severity, title, stackType, locationType, showErrorProps, rawStack, errorMetadata, } = basicErrorInfo;
|
|
13
|
+
const titleA = getTitle(title, errorInfo);
|
|
14
|
+
const { message: messageA, stack: stackA } = getStackInfo({ message, stack, stackType, rawStack, severity, debug });
|
|
15
|
+
const pluginInfo = getPluginInfo(plugin, location);
|
|
16
|
+
const tsConfigInfo = getTsConfigInfo(tsConfig);
|
|
17
|
+
const locationInfo = getLocationInfo({ stack: stackA, location, locationType });
|
|
18
|
+
const errorPropsA = getErrorProps({ errorProps, showErrorProps, colors });
|
|
19
|
+
return {
|
|
20
|
+
...basicErrorInfo,
|
|
21
|
+
title: titleA,
|
|
22
|
+
message: messageA,
|
|
23
|
+
tsConfigInfo,
|
|
24
|
+
pluginInfo,
|
|
25
|
+
locationInfo,
|
|
26
|
+
errorProps: errorPropsA,
|
|
27
|
+
errorMetadata,
|
|
28
|
+
};
|
|
29
|
+
};
|
|
30
|
+
// Serialize the `tsConfig` error information
|
|
31
|
+
const getTsConfigInfo = function (tsConfig) {
|
|
32
|
+
if (tsConfig === undefined) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
return serializeObject(tsConfig);
|
|
36
|
+
};
|
|
37
|
+
// Parse error instance into all the basic properties containing information
|
|
38
|
+
export const parseErrorInfo = function (error) {
|
|
39
|
+
const { message, stack, ...errorProps } = normalizeError(error);
|
|
40
|
+
const [errorInfo, errorPropsA] = getErrorInfo(errorProps);
|
|
41
|
+
const { errorMetadata } = errorInfo;
|
|
42
|
+
const { type, severity, title, group, stackType, locationType, showErrorProps, showInBuildLog = true, rawStack, } = getTypeInfo(errorInfo);
|
|
43
|
+
const basicErrorInfo = {
|
|
44
|
+
message,
|
|
45
|
+
stack,
|
|
46
|
+
errorProps: errorPropsA,
|
|
47
|
+
errorInfo,
|
|
48
|
+
type,
|
|
49
|
+
severity,
|
|
50
|
+
title,
|
|
51
|
+
group,
|
|
52
|
+
stackType,
|
|
53
|
+
locationType,
|
|
54
|
+
showInBuildLog,
|
|
55
|
+
showErrorProps,
|
|
56
|
+
rawStack,
|
|
57
|
+
errorMetadata,
|
|
58
|
+
};
|
|
59
|
+
return basicErrorInfo;
|
|
60
|
+
};
|
|
61
|
+
// Retrieve title to print in logs
|
|
62
|
+
const getTitle = function (title, errorInfo) {
|
|
63
|
+
if (typeof title !== 'function') {
|
|
64
|
+
return title;
|
|
65
|
+
}
|
|
66
|
+
return title(errorInfo);
|
|
67
|
+
};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
// Retrieve plugin's package.json details to include in error messages.
|
|
2
|
+
// Please note `pluginPackageJson` has been normalized by `normalize-package-data`.
|
|
3
|
+
export const getPluginInfo = function ({ pluginPackageJson = {} }, { packageName, loadedFrom }) {
|
|
4
|
+
if (Object.keys(pluginPackageJson).length === 0) {
|
|
5
|
+
return;
|
|
6
|
+
}
|
|
7
|
+
return Object.entries(FIELDS)
|
|
8
|
+
.map(([name, getField]) => serializeField({ name, getField, pluginPackageJson, packageName, loadedFrom }))
|
|
9
|
+
.filter(Boolean)
|
|
10
|
+
.join('\n');
|
|
11
|
+
};
|
|
12
|
+
// Serialize a single package.json field
|
|
13
|
+
const serializeField = function ({ name, getField, pluginPackageJson, packageName, loadedFrom }) {
|
|
14
|
+
const field = getField(pluginPackageJson, { packageName, loadedFrom });
|
|
15
|
+
if (field === undefined) {
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
const nameA = `${name}:`.padEnd(NAME_PADDING);
|
|
19
|
+
return `${nameA}${field}`;
|
|
20
|
+
};
|
|
21
|
+
const NAME_PADDING = 16;
|
|
22
|
+
const getPackage = function (pluginPackageJson, { packageName }) {
|
|
23
|
+
return packageName;
|
|
24
|
+
};
|
|
25
|
+
const getVersion = function ({ version }) {
|
|
26
|
+
if (version === '') {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
return version;
|
|
30
|
+
};
|
|
31
|
+
export const getHomepage = function (pluginPackageJson = {}, { loadedFrom } = {}) {
|
|
32
|
+
return (getRepository(pluginPackageJson) ||
|
|
33
|
+
getNpmLink(pluginPackageJson, { loadedFrom }) ||
|
|
34
|
+
getIssuesLink(pluginPackageJson));
|
|
35
|
+
};
|
|
36
|
+
const getRepository = function ({ repository: { url } = {} }) {
|
|
37
|
+
return url;
|
|
38
|
+
};
|
|
39
|
+
const getNpmLink = function ({ name }, { loadedFrom }) {
|
|
40
|
+
if (!name || loadedFrom === 'local') {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
return `https://www.npmjs.com/package/${name}`;
|
|
44
|
+
};
|
|
45
|
+
const getIssuesLink = function ({ bugs: { url } = {} }) {
|
|
46
|
+
return url;
|
|
47
|
+
};
|
|
48
|
+
// List of package.json to serialize
|
|
49
|
+
const FIELDS = {
|
|
50
|
+
Package: getPackage,
|
|
51
|
+
Version: getVersion,
|
|
52
|
+
Repository: getRepository,
|
|
53
|
+
'npm link': getNpmLink,
|
|
54
|
+
'Report issues': getIssuesLink,
|
|
55
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { inspect } from 'util';
|
|
2
|
+
import { omit } from '../../utils/omit.js';
|
|
3
|
+
// In uncaught exceptions, print error static properties
|
|
4
|
+
export const getErrorProps = function ({ errorProps, showErrorProps, colors }) {
|
|
5
|
+
if (!showErrorProps) {
|
|
6
|
+
return;
|
|
7
|
+
}
|
|
8
|
+
const errorPropsA = omit(errorProps, CLEANED_ERROR_PROPS);
|
|
9
|
+
if (Object.keys(errorPropsA).length === 0) {
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
return inspect(errorPropsA, { colors, depth: INSPECT_MAX_DEPTH });
|
|
13
|
+
};
|
|
14
|
+
const INSPECT_MAX_DEPTH = 5;
|
|
15
|
+
// Remove error static properties that should not be logged
|
|
16
|
+
const CLEANED_ERROR_PROPS = ['requireStack'];
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { THEME } from '../../log/theme.js';
|
|
2
|
+
// Serialize an error object into a title|body string to print in logs
|
|
3
|
+
export const serializeLogError = function ({ fullErrorInfo: { title, severity, message, pluginInfo, locationInfo, tsConfigInfo, errorProps }, }) {
|
|
4
|
+
const body = getBody({ message, pluginInfo, locationInfo, tsConfigInfo, errorProps, severity });
|
|
5
|
+
return { title, body };
|
|
6
|
+
};
|
|
7
|
+
const getBody = function ({ message, pluginInfo, locationInfo, tsConfigInfo, errorProps, severity }) {
|
|
8
|
+
if (severity === 'none') {
|
|
9
|
+
return message;
|
|
10
|
+
}
|
|
11
|
+
return Object.entries({
|
|
12
|
+
message,
|
|
13
|
+
tsConfigInfo,
|
|
14
|
+
pluginInfo,
|
|
15
|
+
locationInfo,
|
|
16
|
+
errorProps,
|
|
17
|
+
})
|
|
18
|
+
.filter(blockHasValue)
|
|
19
|
+
.map(serializeBlock)
|
|
20
|
+
.join('\n\n');
|
|
21
|
+
};
|
|
22
|
+
const blockHasValue = function ([, value]) {
|
|
23
|
+
return value !== undefined;
|
|
24
|
+
};
|
|
25
|
+
const serializeBlock = function ([key, value]) {
|
|
26
|
+
return `${THEME.errorSubHeader(LOG_BLOCK_NAMES[key])}\n${value}`;
|
|
27
|
+
};
|
|
28
|
+
const LOG_BLOCK_NAMES = {
|
|
29
|
+
message: 'Error message',
|
|
30
|
+
pluginInfo: 'Plugin details',
|
|
31
|
+
locationInfo: 'Error location',
|
|
32
|
+
tsConfigInfo: 'TypeScript configuration',
|
|
33
|
+
errorProps: 'Error properties',
|
|
34
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// Serialize an error object to `statuses` properties
|
|
2
|
+
export const serializeErrorStatus = function ({ fullErrorInfo: { title, message, locationInfo, errorProps, errorMetadata }, state, }) {
|
|
3
|
+
const text = getText({ locationInfo, errorProps });
|
|
4
|
+
return { state, title, summary: message, text, extraData: errorMetadata };
|
|
5
|
+
};
|
|
6
|
+
const getText = function ({ locationInfo, errorProps }) {
|
|
7
|
+
const parts = [locationInfo, getErrorProps(errorProps)].filter(Boolean);
|
|
8
|
+
if (parts.length === 0) {
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
return parts.join('\n\n');
|
|
12
|
+
};
|
|
13
|
+
const getErrorProps = function (errorProps) {
|
|
14
|
+
if (errorProps === undefined) {
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
return `Error properties:\n${errorProps}`;
|
|
18
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { cleanStacks } from './clean_stack.js';
|
|
2
|
+
// Retrieve the stack trace
|
|
3
|
+
export const getStackInfo = function ({ message, stack, stackType, rawStack, severity, debug }) {
|
|
4
|
+
const { message: messageA, stack: stackA } = splitStackInfo({ message, stack, stackType });
|
|
5
|
+
const messageB = severity === 'none' ? messageA.replace(SUCCESS_ERROR_NAME, '') : messageA;
|
|
6
|
+
const stackB = cleanStacks({ stack: stackA, rawStack, debug });
|
|
7
|
+
return { message: messageB, stack: stackB };
|
|
8
|
+
};
|
|
9
|
+
const splitStackInfo = function ({ message, stack, stackType }) {
|
|
10
|
+
// Some errors should not show any stack trace
|
|
11
|
+
if (stackType === 'none') {
|
|
12
|
+
return { message };
|
|
13
|
+
}
|
|
14
|
+
// Some errors have their stack trace inside `error.message` instead of
|
|
15
|
+
// `error.stack` due to IPC
|
|
16
|
+
if (stackType === 'message') {
|
|
17
|
+
return splitStack(message);
|
|
18
|
+
}
|
|
19
|
+
return splitStack(stack);
|
|
20
|
+
};
|
|
21
|
+
const splitStack = function (string) {
|
|
22
|
+
const lines = string.split('\n');
|
|
23
|
+
const stackIndex = lines.findIndex(isStackTrace);
|
|
24
|
+
if (stackIndex === -1) {
|
|
25
|
+
return { message: string };
|
|
26
|
+
}
|
|
27
|
+
const messageA = lines.slice(0, stackIndex).join('\n');
|
|
28
|
+
const stackA = lines.slice(stackIndex).join('\n');
|
|
29
|
+
return { message: messageA, stack: stackA };
|
|
30
|
+
};
|
|
31
|
+
const isStackTrace = function (line) {
|
|
32
|
+
return line.trim().startsWith('at ');
|
|
33
|
+
};
|
|
34
|
+
const SUCCESS_ERROR_NAME = 'Error: ';
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { isNetlifyMaintainedPlugin } from '../plugins/internal.js';
|
|
2
|
+
import { closeClient, formatTags, normalizeTagName, startClient, validateStatsDOptions, } from '../report/statsd.js';
|
|
3
|
+
import { getErrorInfo } from './info.js';
|
|
4
|
+
const TOP_PARENT_TAG = 'run_netlify_build';
|
|
5
|
+
/**
|
|
6
|
+
* Record error rates of the build phase for monitoring.
|
|
7
|
+
* Sends to statsd daemon.
|
|
8
|
+
*/
|
|
9
|
+
export const reportError = async function (error, statsdOpts, framework) {
|
|
10
|
+
if (!validateStatsDOptions(statsdOpts)) {
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
const [errorInfo] = getErrorInfo(error);
|
|
14
|
+
const pluginName = errorInfo.plugin ? normalizeTagName(errorInfo.plugin.packageName) : null;
|
|
15
|
+
// only send tracking if it is a known plugin
|
|
16
|
+
if (pluginName && !isNetlifyMaintainedPlugin(pluginName)) {
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
const parent = pluginName ? pluginName : TOP_PARENT_TAG;
|
|
20
|
+
const stage = pluginName ? errorInfo.location?.event : errorInfo.stage;
|
|
21
|
+
const statsDTags = { stage: stage ?? 'system', parent };
|
|
22
|
+
// Do not add a framework tag if empty string or null/undefined
|
|
23
|
+
if (framework) {
|
|
24
|
+
statsDTags.framework = framework;
|
|
25
|
+
}
|
|
26
|
+
const client = await startClient(statsdOpts);
|
|
27
|
+
client.increment('buildbot.build.stage.error', 1, formatTags(statsDTags));
|
|
28
|
+
await closeClient(client);
|
|
29
|
+
};
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
// Retrieve error-type specific information
|
|
2
|
+
export const getTypeInfo = function ({ type }) {
|
|
3
|
+
const typeA = TYPES[type] === undefined ? DEFAULT_TYPE : type;
|
|
4
|
+
return { type: typeA, ...TYPES[typeA] };
|
|
5
|
+
};
|
|
6
|
+
// List of error types, and their related properties
|
|
7
|
+
// Related to build error logs:
|
|
8
|
+
// - `showInBuildLog`: `true` when we want this error to show in build logs (defaults to true)
|
|
9
|
+
// - `title`: main title shown in build error logs and in the UI (statuses)
|
|
10
|
+
// - `locationType`: retrieve a human-friendly location of the error, printed
|
|
11
|
+
// in build error logs
|
|
12
|
+
// - `showErrorProps`: `true` when the `Error` instance static properties
|
|
13
|
+
// should be printed in build error logs. Only useful when the `Error`
|
|
14
|
+
// instance was not created by us.
|
|
15
|
+
// - `rawStack`: `true` when the stack trace should be cleaned up
|
|
16
|
+
// - `stackType`: how the stack trace should appear in build error logs:
|
|
17
|
+
// - `none`: not printed
|
|
18
|
+
// - `stack`: printed as is
|
|
19
|
+
// - `message`: printed as is, but taken from `error.message`.
|
|
20
|
+
// Used when `error.stack` is not being correct due to the error being
|
|
21
|
+
// passed between different processes.
|
|
22
|
+
// - `severity`: error severity (also used by Bugsnag):
|
|
23
|
+
// - `success`: build success
|
|
24
|
+
// - `none`: not an error, e.g. build cancellation
|
|
25
|
+
// - `info`: user error
|
|
26
|
+
// - `warning`: community plugin error
|
|
27
|
+
// - `error`: system error, including core plugin error
|
|
28
|
+
// Related to Bugsnag:
|
|
29
|
+
// - `group`: main title shown in Bugsnag. Also used to group errors together
|
|
30
|
+
// in Bugsnag, combined with `error.message`.
|
|
31
|
+
// Defaults to `title`.
|
|
32
|
+
// New error types should be added to Bugsnag since we use it for automated
|
|
33
|
+
// monitoring (through its Slack integration). The steps in Bugsnag are:
|
|
34
|
+
// - Create a new bookmark. Try to re-use the search filter of an existing
|
|
35
|
+
// bookmark with a similar error type, but only changing the `errorClass`.
|
|
36
|
+
// Make sure to check the box "Share with my team".
|
|
37
|
+
// - Add the `errorClass` to the search filter of either the "All warnings" or
|
|
38
|
+
// "All errors" bookmark depending on whether we should get notified on Slack
|
|
39
|
+
// for new errors of that type. You must use the bookmark menu action "Update
|
|
40
|
+
// with current filters"
|
|
41
|
+
const TYPES = {
|
|
42
|
+
// Plugin called `utils.build.cancelBuild()`
|
|
43
|
+
cancelBuild: {
|
|
44
|
+
title: ({ location: { packageName } }) => `Build canceled by ${packageName}`,
|
|
45
|
+
stackType: 'stack',
|
|
46
|
+
locationType: 'buildFail',
|
|
47
|
+
severity: 'none',
|
|
48
|
+
},
|
|
49
|
+
// User configuration error (`@netlify/config`, wrong Node.js version)
|
|
50
|
+
resolveConfig: {
|
|
51
|
+
title: 'Configuration error',
|
|
52
|
+
stackType: 'none',
|
|
53
|
+
severity: 'info',
|
|
54
|
+
},
|
|
55
|
+
// Error while installing user packages (missing plugins, local plugins or functions dependencies)
|
|
56
|
+
dependencies: {
|
|
57
|
+
title: 'Dependencies installation error',
|
|
58
|
+
stackType: 'none',
|
|
59
|
+
severity: 'info',
|
|
60
|
+
},
|
|
61
|
+
// User misconfigured a plugin
|
|
62
|
+
pluginInput: {
|
|
63
|
+
title: ({ location: { packageName, input } }) => `Plugin "${packageName}" invalid input "${input}"`,
|
|
64
|
+
stackType: 'none',
|
|
65
|
+
locationType: 'buildFail',
|
|
66
|
+
severity: 'info',
|
|
67
|
+
},
|
|
68
|
+
// User package.json sets an unsupported plugin version
|
|
69
|
+
pluginUnsupportedVersion: {
|
|
70
|
+
title: 'Unsupported plugin version detected',
|
|
71
|
+
stackType: 'none',
|
|
72
|
+
severity: 'info',
|
|
73
|
+
},
|
|
74
|
+
// `build.command` non-0 exit code
|
|
75
|
+
buildCommand: {
|
|
76
|
+
title: '"build.command" failed',
|
|
77
|
+
group: ({ location: { buildCommand } }) => buildCommand,
|
|
78
|
+
stackType: 'message',
|
|
79
|
+
locationType: 'buildCommand',
|
|
80
|
+
severity: 'info',
|
|
81
|
+
},
|
|
82
|
+
// User error during Functions bundling
|
|
83
|
+
functionsBundling: {
|
|
84
|
+
title: ({ location: { functionName, functionType } }) => {
|
|
85
|
+
if (functionType === 'edge') {
|
|
86
|
+
return 'Bundling of edge function failed';
|
|
87
|
+
}
|
|
88
|
+
return `Bundling of function "${functionName}" failed`;
|
|
89
|
+
},
|
|
90
|
+
group: ({ location: { functionType = 'serverless' } }) => `Bundling of ${functionType} function failed`,
|
|
91
|
+
stackType: 'none',
|
|
92
|
+
locationType: 'functionsBundling',
|
|
93
|
+
severity: 'info',
|
|
94
|
+
},
|
|
95
|
+
// Plugin called `utils.build.failBuild()`
|
|
96
|
+
failBuild: {
|
|
97
|
+
title: ({ location: { packageName } }) => `Plugin "${packageName}" failed`,
|
|
98
|
+
stackType: 'stack',
|
|
99
|
+
locationType: 'buildFail',
|
|
100
|
+
severity: 'info',
|
|
101
|
+
},
|
|
102
|
+
// Plugin called `utils.build.failPlugin()`
|
|
103
|
+
failPlugin: {
|
|
104
|
+
title: ({ location: { packageName } }) => `Plugin "${packageName}" failed`,
|
|
105
|
+
stackType: 'stack',
|
|
106
|
+
locationType: 'buildFail',
|
|
107
|
+
severity: 'info',
|
|
108
|
+
},
|
|
109
|
+
// Plugin has an invalid shape
|
|
110
|
+
pluginValidation: {
|
|
111
|
+
title: ({ location: { packageName } }) => `Plugin "${packageName}" internal error`,
|
|
112
|
+
stackType: 'stack',
|
|
113
|
+
locationType: 'buildFail',
|
|
114
|
+
severity: 'warning',
|
|
115
|
+
},
|
|
116
|
+
// Plugin threw an uncaught exception
|
|
117
|
+
pluginInternal: {
|
|
118
|
+
title: ({ location: { packageName } }) => `Plugin "${packageName}" internal error`,
|
|
119
|
+
stackType: 'stack',
|
|
120
|
+
showErrorProps: true,
|
|
121
|
+
rawStack: true,
|
|
122
|
+
locationType: 'buildFail',
|
|
123
|
+
severity: 'warning',
|
|
124
|
+
},
|
|
125
|
+
// Bug while orchestrating child processes
|
|
126
|
+
ipc: {
|
|
127
|
+
title: ({ location: { packageName } }) => `Plugin "${packageName}" internal error`,
|
|
128
|
+
stackType: 'none',
|
|
129
|
+
locationType: 'buildFail',
|
|
130
|
+
severity: 'warning',
|
|
131
|
+
},
|
|
132
|
+
// Core plugin internal error
|
|
133
|
+
corePlugin: {
|
|
134
|
+
title: ({ location: { packageName } }) => `Plugin "${packageName}" internal error`,
|
|
135
|
+
stackType: 'stack',
|
|
136
|
+
showErrorProps: true,
|
|
137
|
+
rawStack: true,
|
|
138
|
+
locationType: 'buildFail',
|
|
139
|
+
severity: 'error',
|
|
140
|
+
},
|
|
141
|
+
// Core step internal error
|
|
142
|
+
coreStep: {
|
|
143
|
+
title: ({ location: { coreStepName } }) => `Internal error during "${coreStepName}"`,
|
|
144
|
+
stackType: 'stack',
|
|
145
|
+
showErrorProps: true,
|
|
146
|
+
rawStack: true,
|
|
147
|
+
locationType: 'coreStep',
|
|
148
|
+
severity: 'error',
|
|
149
|
+
},
|
|
150
|
+
// Request error when `@netlify/build` was calling Netlify API
|
|
151
|
+
api: {
|
|
152
|
+
title: ({ location: { endpoint } }) => `API error on "${endpoint}"`,
|
|
153
|
+
stackType: 'message',
|
|
154
|
+
showErrorProps: true,
|
|
155
|
+
locationType: 'api',
|
|
156
|
+
severity: 'error',
|
|
157
|
+
},
|
|
158
|
+
// `@netlify/build` threw an uncaught exception
|
|
159
|
+
exception: {
|
|
160
|
+
title: 'Core internal error',
|
|
161
|
+
stackType: 'stack',
|
|
162
|
+
showErrorProps: true,
|
|
163
|
+
rawStack: true,
|
|
164
|
+
severity: 'error',
|
|
165
|
+
},
|
|
166
|
+
// Errors related with the telemetry output
|
|
167
|
+
telemetry: {
|
|
168
|
+
showInBuildLog: false,
|
|
169
|
+
title: 'Telemetry error',
|
|
170
|
+
stackType: 'stack',
|
|
171
|
+
showErrorProps: true,
|
|
172
|
+
rawStack: true,
|
|
173
|
+
severity: 'error',
|
|
174
|
+
},
|
|
175
|
+
};
|
|
176
|
+
// When no error type matches, it's an uncaught exception, i.e. a bug
|
|
177
|
+
const DEFAULT_TYPE = 'exception';
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { dirname } from 'path';
|
|
2
|
+
import readdirp from 'readdirp';
|
|
3
|
+
import { logInstallFunctionDependencies } from '../log/messages/install.js';
|
|
4
|
+
import { installDependencies } from './main.js';
|
|
5
|
+
// Install dependencies of Netlify Functions
|
|
6
|
+
export const installFunctionDependencies = async function (functionsSrc, isLocal) {
|
|
7
|
+
const packagePaths = await getPackagePaths(functionsSrc);
|
|
8
|
+
if (packagePaths.length === 0) {
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
logInstallFunctionDependencies();
|
|
12
|
+
const packageRoots = packagePaths.map(getPackageRoot);
|
|
13
|
+
await Promise.all(packageRoots.map((packageRoot) => installDependencies({ packageRoot, isLocal })));
|
|
14
|
+
};
|
|
15
|
+
const getPackagePaths = function (functionsSrc) {
|
|
16
|
+
return readdirp.promise(functionsSrc, { depth: 1, fileFilter: 'package.json' });
|
|
17
|
+
};
|
|
18
|
+
const getPackageRoot = function ({ fullPath }) {
|
|
19
|
+
return dirname(fullPath);
|
|
20
|
+
};
|