@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.
Files changed (266) hide show
  1. package/bin.js +5 -0
  2. package/lib/core/bin.js +66 -0
  3. package/lib/core/build.js +356 -0
  4. package/lib/core/config.js +121 -0
  5. package/lib/core/constants.js +116 -0
  6. package/lib/core/dev.js +27 -0
  7. package/lib/core/dry.js +21 -0
  8. package/lib/core/feature_flags.js +21 -0
  9. package/lib/core/flags.js +201 -0
  10. package/lib/core/lingering.js +68 -0
  11. package/lib/core/main.js +110 -0
  12. package/lib/core/missing_side_file.js +17 -0
  13. package/lib/core/normalize_flags.js +59 -0
  14. package/lib/core/severity.js +21 -0
  15. package/lib/core/types.js +8 -0
  16. package/lib/core/user_node_version.js +32 -0
  17. package/lib/env/changes.js +43 -0
  18. package/lib/env/main.js +14 -0
  19. package/lib/env/metadata.js +68 -0
  20. package/lib/error/api.js +37 -0
  21. package/lib/error/build.js +36 -0
  22. package/{src → lib}/error/cancel.js +5 -6
  23. package/lib/error/colors.js +9 -0
  24. package/lib/error/handle.js +46 -0
  25. package/lib/error/info.js +37 -0
  26. package/lib/error/monitor/location.js +16 -0
  27. package/lib/error/monitor/normalize.js +86 -0
  28. package/lib/error/monitor/print.js +20 -0
  29. package/lib/error/monitor/report.js +120 -0
  30. package/lib/error/monitor/start.js +61 -0
  31. package/lib/error/parse/clean_stack.js +70 -0
  32. package/lib/error/parse/location.js +50 -0
  33. package/lib/error/parse/normalize.js +24 -0
  34. package/lib/error/parse/parse.js +67 -0
  35. package/lib/error/parse/plugin.js +55 -0
  36. package/lib/error/parse/properties.js +16 -0
  37. package/lib/error/parse/serialize_log.js +34 -0
  38. package/lib/error/parse/serialize_status.js +18 -0
  39. package/lib/error/parse/stack.js +34 -0
  40. package/lib/error/report.js +27 -0
  41. package/lib/error/type.js +177 -0
  42. package/lib/install/functions.js +20 -0
  43. package/lib/install/local.js +45 -0
  44. package/lib/install/main.js +67 -0
  45. package/lib/install/missing.js +54 -0
  46. package/lib/log/colors.js +28 -0
  47. package/lib/log/description.js +21 -0
  48. package/lib/log/header.js +14 -0
  49. package/lib/log/header_func.js +13 -0
  50. package/lib/log/logger.js +140 -0
  51. package/lib/log/messages/compatibility.js +146 -0
  52. package/lib/log/messages/config.js +91 -0
  53. package/lib/log/messages/core.js +51 -0
  54. package/lib/log/messages/core_steps.js +75 -0
  55. package/lib/log/messages/dry.js +41 -0
  56. package/lib/log/messages/install.js +25 -0
  57. package/lib/log/messages/ipc.js +29 -0
  58. package/lib/log/messages/mutations.js +62 -0
  59. package/{src → lib}/log/messages/plugins.js +18 -32
  60. package/lib/log/messages/status.js +14 -0
  61. package/lib/log/messages/steps.js +18 -0
  62. package/lib/log/old_version.js +32 -0
  63. package/lib/log/serialize.js +10 -0
  64. package/lib/log/stream.js +68 -0
  65. package/lib/log/theme.js +27 -0
  66. package/lib/plugins/child/diff.js +46 -0
  67. package/lib/plugins/child/error.js +26 -0
  68. package/lib/plugins/child/lazy.js +15 -0
  69. package/lib/plugins/child/load.js +22 -0
  70. package/lib/plugins/child/logic.js +57 -0
  71. package/lib/plugins/child/main.js +37 -0
  72. package/lib/plugins/child/run.js +19 -0
  73. package/lib/plugins/child/status.js +63 -0
  74. package/lib/plugins/child/typescript.js +28 -0
  75. package/lib/plugins/child/utils.js +42 -0
  76. package/lib/plugins/child/validate.js +31 -0
  77. package/lib/plugins/compatibility.js +104 -0
  78. package/{src → lib}/plugins/error.js +31 -35
  79. package/{src → lib}/plugins/events.js +7 -12
  80. package/lib/plugins/expected_version.js +81 -0
  81. package/lib/plugins/internal.js +10 -0
  82. package/lib/plugins/ipc.js +120 -0
  83. package/lib/plugins/list.js +73 -0
  84. package/lib/plugins/load.js +50 -0
  85. package/lib/plugins/manifest/check.js +85 -0
  86. package/lib/plugins/manifest/load.js +38 -0
  87. package/lib/plugins/manifest/main.js +19 -0
  88. package/lib/plugins/manifest/path.js +24 -0
  89. package/lib/plugins/manifest/validate.js +91 -0
  90. package/lib/plugins/node_version.js +35 -0
  91. package/lib/plugins/options.js +70 -0
  92. package/lib/plugins/pinned_version.js +83 -0
  93. package/lib/plugins/resolve.js +110 -0
  94. package/lib/plugins/spawn.js +58 -0
  95. package/lib/plugins_core/add.js +35 -0
  96. package/lib/plugins_core/build_command.js +50 -0
  97. package/lib/plugins_core/deploy/buildbot_client.js +87 -0
  98. package/lib/plugins_core/deploy/index.js +49 -0
  99. package/{src → lib}/plugins_core/deploy/manifest.yml +0 -0
  100. package/lib/plugins_core/edge_functions/index.js +76 -0
  101. package/{src → lib}/plugins_core/edge_functions/lib/error.js +13 -17
  102. package/lib/plugins_core/edge_functions/validate_manifest/validate_edge_functions_manifest.js +21 -0
  103. package/lib/plugins_core/functions/error.js +123 -0
  104. package/lib/plugins_core/functions/feature_flags.js +6 -0
  105. package/lib/plugins_core/functions/index.js +114 -0
  106. package/lib/plugins_core/functions/utils.js +45 -0
  107. package/lib/plugins_core/functions/zisi.js +39 -0
  108. package/{src → lib}/plugins_core/functions_install/index.js +8 -11
  109. package/{src → lib}/plugins_core/functions_install/manifest.yml +0 -0
  110. package/lib/plugins_core/list.js +20 -0
  111. package/lib/report/statsd.js +31 -0
  112. package/lib/status/add.js +30 -0
  113. package/lib/status/colors.js +18 -0
  114. package/lib/status/load_error.js +10 -0
  115. package/lib/status/report.js +83 -0
  116. package/lib/status/success.js +14 -0
  117. package/lib/steps/core_step.js +59 -0
  118. package/lib/steps/error.js +65 -0
  119. package/lib/steps/get.js +43 -0
  120. package/lib/steps/plugin.js +55 -0
  121. package/lib/steps/return.js +25 -0
  122. package/lib/steps/run_core_steps.js +117 -0
  123. package/lib/steps/run_step.js +190 -0
  124. package/lib/steps/run_steps.js +96 -0
  125. package/lib/steps/update_config.js +66 -0
  126. package/lib/telemetry/main.js +97 -0
  127. package/lib/time/aggregate.js +109 -0
  128. package/lib/time/main.js +31 -0
  129. package/lib/time/measure.js +16 -0
  130. package/lib/time/report.js +24 -0
  131. package/lib/utils/errors.js +13 -0
  132. package/lib/utils/json.js +15 -0
  133. package/lib/utils/omit.js +3 -0
  134. package/lib/utils/package.js +24 -0
  135. package/lib/utils/remove_falsy.js +8 -0
  136. package/lib/utils/resolve.js +41 -0
  137. package/lib/utils/runtime.js +5 -0
  138. package/lib/utils/semver.js +28 -0
  139. package/package.json +41 -24
  140. package/types/config/netlify_config.d.ts +4 -4
  141. package/types/netlify_plugin_constants.d.ts +8 -8
  142. package/src/core/bin.js +0 -83
  143. package/src/core/build.js +0 -554
  144. package/src/core/config.js +0 -186
  145. package/src/core/constants.js +0 -156
  146. package/src/core/dev.js +0 -31
  147. package/src/core/dry.js +0 -39
  148. package/src/core/feature_flags.js +0 -22
  149. package/src/core/flags.js +0 -204
  150. package/src/core/lingering.js +0 -85
  151. package/src/core/main.js +0 -165
  152. package/src/core/missing_side_file.js +0 -29
  153. package/src/core/normalize_flags.js +0 -70
  154. package/src/core/severity.js +0 -22
  155. package/src/core/user_node_version.js +0 -41
  156. package/src/env/changes.js +0 -52
  157. package/src/env/main.js +0 -19
  158. package/src/env/metadata.js +0 -81
  159. package/src/error/api.js +0 -46
  160. package/src/error/build.js +0 -50
  161. package/src/error/colors.js +0 -11
  162. package/src/error/handle.js +0 -57
  163. package/src/error/info.js +0 -46
  164. package/src/error/monitor/location.js +0 -21
  165. package/src/error/monitor/normalize.js +0 -96
  166. package/src/error/monitor/print.js +0 -42
  167. package/src/error/monitor/report.js +0 -138
  168. package/src/error/monitor/start.js +0 -69
  169. package/src/error/parse/clean_stack.js +0 -87
  170. package/src/error/parse/location.js +0 -62
  171. package/src/error/parse/normalize.js +0 -29
  172. package/src/error/parse/parse.js +0 -97
  173. package/src/error/parse/plugin.js +0 -70
  174. package/src/error/parse/properties.js +0 -23
  175. package/src/error/parse/serialize_log.js +0 -42
  176. package/src/error/parse/serialize_status.js +0 -23
  177. package/src/error/parse/stack.js +0 -43
  178. package/src/error/type.js +0 -189
  179. package/src/install/functions.js +0 -28
  180. package/src/install/local.js +0 -62
  181. package/src/install/main.js +0 -81
  182. package/src/install/missing.js +0 -67
  183. package/src/log/colors.js +0 -34
  184. package/src/log/description.js +0 -26
  185. package/src/log/header.js +0 -16
  186. package/src/log/header_func.js +0 -17
  187. package/src/log/logger.js +0 -161
  188. package/src/log/messages/compatibility.js +0 -164
  189. package/src/log/messages/config.js +0 -107
  190. package/src/log/messages/core.js +0 -70
  191. package/src/log/messages/core_steps.js +0 -104
  192. package/src/log/messages/dry.js +0 -63
  193. package/src/log/messages/install.js +0 -20
  194. package/src/log/messages/ipc.js +0 -38
  195. package/src/log/messages/mutations.js +0 -82
  196. package/src/log/messages/status.js +0 -16
  197. package/src/log/messages/steps.js +0 -22
  198. package/src/log/old_version.js +0 -41
  199. package/src/log/serialize.js +0 -13
  200. package/src/log/stream.js +0 -85
  201. package/src/log/theme.js +0 -26
  202. package/src/plugins/child/diff.js +0 -55
  203. package/src/plugins/child/error.js +0 -32
  204. package/src/plugins/child/lazy.js +0 -18
  205. package/src/plugins/child/load.js +0 -29
  206. package/src/plugins/child/logic.js +0 -57
  207. package/src/plugins/child/main.js +0 -51
  208. package/src/plugins/child/run.js +0 -28
  209. package/src/plugins/child/status.js +0 -74
  210. package/src/plugins/child/typescript.js +0 -45
  211. package/src/plugins/child/utils.js +0 -56
  212. package/src/plugins/child/validate.js +0 -34
  213. package/src/plugins/compatibility.js +0 -128
  214. package/src/plugins/expected_version.js +0 -119
  215. package/src/plugins/ipc.js +0 -145
  216. package/src/plugins/list.js +0 -86
  217. package/src/plugins/load.js +0 -70
  218. package/src/plugins/manifest/check.js +0 -106
  219. package/src/plugins/manifest/load.js +0 -41
  220. package/src/plugins/manifest/main.js +0 -22
  221. package/src/plugins/manifest/path.js +0 -31
  222. package/src/plugins/manifest/validate.js +0 -108
  223. package/src/plugins/node_version.js +0 -50
  224. package/src/plugins/options.js +0 -88
  225. package/src/plugins/pinned_version.js +0 -131
  226. package/src/plugins/resolve.js +0 -152
  227. package/src/plugins/spawn.js +0 -66
  228. package/src/plugins_core/add.js +0 -49
  229. package/src/plugins_core/build_command.js +0 -75
  230. package/src/plugins_core/deploy/buildbot_client.js +0 -102
  231. package/src/plugins_core/deploy/index.js +0 -73
  232. package/src/plugins_core/edge_functions/index.js +0 -123
  233. package/src/plugins_core/edge_functions/lib/internal_manifest.js +0 -54
  234. package/src/plugins_core/edge_functions/validate_manifest/validate_edge_functions_manifest.js +0 -89
  235. package/src/plugins_core/functions/error.js +0 -163
  236. package/src/plugins_core/functions/feature_flags.js +0 -6
  237. package/src/plugins_core/functions/index.js +0 -160
  238. package/src/plugins_core/functions/utils.js +0 -66
  239. package/src/plugins_core/functions/zisi.js +0 -53
  240. package/src/plugins_core/list.js +0 -27
  241. package/src/status/add.js +0 -36
  242. package/src/status/colors.js +0 -23
  243. package/src/status/load_error.js +0 -11
  244. package/src/status/report.js +0 -137
  245. package/src/status/success.js +0 -18
  246. package/src/steps/core_step.js +0 -92
  247. package/src/steps/error.js +0 -102
  248. package/src/steps/get.js +0 -51
  249. package/src/steps/plugin.js +0 -85
  250. package/src/steps/return.js +0 -52
  251. package/src/steps/run_core_steps.js +0 -200
  252. package/src/steps/run_step.js +0 -304
  253. package/src/steps/run_steps.js +0 -179
  254. package/src/steps/update_config.js +0 -93
  255. package/src/telemetry/main.js +0 -136
  256. package/src/time/aggregate.js +0 -146
  257. package/src/time/main.js +0 -48
  258. package/src/time/measure.js +0 -22
  259. package/src/time/report.js +0 -59
  260. package/src/utils/errors.js +0 -12
  261. package/src/utils/json.js +0 -19
  262. package/src/utils/omit.js +0 -6
  263. package/src/utils/package.js +0 -23
  264. package/src/utils/remove_falsy.js +0 -10
  265. package/src/utils/resolve.js +0 -46
  266. package/src/utils/semver.js +0 -34
@@ -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,27 @@
1
+ import { isNetlifyMaintainedPlugin } from '../plugins/internal.js';
2
+ import { closeClient, normalizeTagName, startClient } from '../report/statsd.js';
3
+ import { getErrorInfo } from './info.js';
4
+ const TOP_PARENT_TAG = 'run_netlify_build';
5
+ // Record error rates of the build phase for monitoring.
6
+ // Sends to statsd daemon.
7
+ export const reportError = async function ({ error, statsdOpts: { host, port }, framework, }) {
8
+ if (host === undefined) {
9
+ return;
10
+ }
11
+ const [errorInfo] = getErrorInfo(error);
12
+ const pluginName = errorInfo.plugin ? normalizeTagName(errorInfo.plugin.packageName) : null;
13
+ // only send tracking if it is a known plugin
14
+ if (pluginName && !isNetlifyMaintainedPlugin(pluginName)) {
15
+ return;
16
+ }
17
+ const parent = pluginName ? pluginName : TOP_PARENT_TAG;
18
+ const stage = pluginName ? errorInfo.location?.event : errorInfo.stage;
19
+ const client = await startClient(host, port);
20
+ const frameworkTag = framework === undefined ? {} : { framework };
21
+ client.increment('buildbot.build.stage.error', 1, {
22
+ stage: stage ?? 'system',
23
+ parent,
24
+ ...frameworkTag,
25
+ });
26
+ await closeClient(client);
27
+ };
@@ -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
+ };
@@ -0,0 +1,45 @@
1
+ import { packageDirectory } from 'pkg-dir';
2
+ import { logInstallLocalPluginsDeps } from '../log/messages/install.js';
3
+ import { installDependencies } from './main.js';
4
+ // Install dependencies of local plugins.
5
+ // Users must add this plugin to their `netlify.toml` `plugins` to use this
6
+ // feature. We don't want to provide it by default because this makes build
7
+ // slow and buggy.
8
+ export const installLocalPluginsDependencies = async function ({ plugins, pluginsOptions, buildDir, mode, logs }) {
9
+ if (!plugins.some(isLocalInstallOptIn)) {
10
+ return;
11
+ }
12
+ const localPluginsOptions = getLocalPluginsOptions(pluginsOptions);
13
+ if (localPluginsOptions.length === 0) {
14
+ return;
15
+ }
16
+ const localPluginsOptionsA = await removeMainRoot(localPluginsOptions, buildDir);
17
+ if (localPluginsOptionsA.length === 0) {
18
+ return;
19
+ }
20
+ logInstallLocalPluginsDeps(logs, localPluginsOptionsA);
21
+ await Promise.all(localPluginsOptionsA.map(({ packageDir }) => installDependencies({ packageRoot: packageDir, isLocal: mode !== 'buildbot' })));
22
+ };
23
+ const isLocalInstallOptIn = function (plugin) {
24
+ return plugin.package === LOCAL_INSTALL_PLUGIN_NAME;
25
+ };
26
+ export const LOCAL_INSTALL_PLUGIN_NAME = '@netlify/plugin-local-install-core';
27
+ // Core plugins and non-local plugins already have their dependencies installed
28
+ const getLocalPluginsOptions = function (pluginsOptions) {
29
+ return pluginsOptions.filter(isLocalPlugin).filter(isUnique).filter(hasPackageDir);
30
+ };
31
+ const isLocalPlugin = function ({ loadedFrom }) {
32
+ return loadedFrom === 'local';
33
+ };
34
+ // Remove duplicates
35
+ const isUnique = function ({ packageDir }, index, pluginsOptions) {
36
+ return pluginsOptions.slice(index + 1).every((pluginOption) => pluginOption.packageDir !== packageDir);
37
+ };
38
+ const hasPackageDir = function ({ packageDir }) {
39
+ return packageDir !== undefined;
40
+ };
41
+ // We only install dependencies of local plugins that have their own `package.json`
42
+ const removeMainRoot = async function (localPluginsOptions, buildDir) {
43
+ const mainPackageDir = await packageDirectory({ cwd: buildDir });
44
+ return localPluginsOptions.filter(({ packageDir }) => packageDir !== mainPackageDir);
45
+ };
@@ -0,0 +1,67 @@
1
+ import { homedir } from 'os';
2
+ import { execa } from 'execa';
3
+ import { pathExists } from 'path-exists';
4
+ import { addErrorInfo } from '../error/info.js';
5
+ // Install Node.js dependencies in a specific directory
6
+ export const installDependencies = function ({ packageRoot, isLocal }) {
7
+ return runCommand({ packageRoot, isLocal, type: 'install' });
8
+ };
9
+ // Add new Node.js dependencies, with exact semver ranges
10
+ export const addExactDependencies = function ({ packageRoot, isLocal, packages }) {
11
+ return runCommand({ packageRoot, packages, isLocal, type: 'addExact' });
12
+ };
13
+ const runCommand = async function ({ packageRoot, packages = [], isLocal, type }) {
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
+ };
25
+ // Retrieve the shell command to install or add dependencies
26
+ const getCommand = async function ({ packageRoot, type, isLocal }) {
27
+ const manager = await getManager(type, packageRoot);
28
+ const command = COMMANDS[manager][type];
29
+ const commandA = addYarnCustomCache(command, manager, isLocal);
30
+ return commandA;
31
+ };
32
+ const getManager = async function (type, packageRoot) {
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
+ };
42
+ const COMMANDS = {
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
+ };
51
+ // In CI, yarn uses a custom cache folder
52
+ const addYarnCustomCache = function (command, manager, isLocal) {
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`;
59
+ // Retrieve message to add to install errors
60
+ const getErrorMessage = function (allOutput) {
61
+ return allOutput.split('\n').filter(isNotNpmLogMessage).join('\n');
62
+ };
63
+ // Debug logs shown at the end of npm errors is not useful in Netlify Build
64
+ const isNotNpmLogMessage = function (line) {
65
+ return NPM_LOG_MESSAGES.every((message) => !line.includes(message));
66
+ };
67
+ const NPM_LOG_MESSAGES = ['complete log of this run', '-debug.log'];