@netlify/config 18.2.2 → 18.2.4-rc

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 (55) hide show
  1. package/package.json +8 -7
  2. package/src/api/build_settings.js +0 -41
  3. package/src/api/client.js +0 -15
  4. package/src/api/site_info.js +0 -67
  5. package/src/base.js +0 -34
  6. package/src/bin/flags.js +0 -181
  7. package/src/bin/main.js +0 -73
  8. package/src/build_dir.js +0 -26
  9. package/src/cached_config.js +0 -29
  10. package/src/case.js +0 -37
  11. package/src/context.js +0 -108
  12. package/src/default.js +0 -31
  13. package/src/env/envelope.js +0 -24
  14. package/src/env/git.js +0 -23
  15. package/src/env/main.js +0 -202
  16. package/src/error.js +0 -36
  17. package/src/events.js +0 -22
  18. package/src/files.js +0 -107
  19. package/src/functions_config.js +0 -83
  20. package/src/headers.js +0 -30
  21. package/src/inline_config.js +0 -9
  22. package/src/log/cleanup.js +0 -92
  23. package/src/log/logger.js +0 -47
  24. package/src/log/main.js +0 -48
  25. package/src/log/messages.js +0 -126
  26. package/src/log/options.js +0 -43
  27. package/src/log/serialize.js +0 -5
  28. package/src/log/theme.js +0 -14
  29. package/src/main.js +0 -285
  30. package/src/merge.js +0 -53
  31. package/src/merge_normalize.js +0 -31
  32. package/src/mutations/apply.js +0 -78
  33. package/src/mutations/config_prop_name.js +0 -16
  34. package/src/mutations/update.js +0 -117
  35. package/src/normalize.js +0 -36
  36. package/src/options/base.js +0 -66
  37. package/src/options/branch.js +0 -34
  38. package/src/options/feature_flags.js +0 -15
  39. package/src/options/main.js +0 -111
  40. package/src/options/repository_root.js +0 -21
  41. package/src/origin.js +0 -38
  42. package/src/parse.js +0 -69
  43. package/src/path.js +0 -52
  44. package/src/redirects.js +0 -29
  45. package/src/simplify.js +0 -103
  46. package/src/utils/group.js +0 -10
  47. package/src/utils/remove_falsy.js +0 -18
  48. package/src/utils/set.js +0 -33
  49. package/src/utils/toml.js +0 -23
  50. package/src/validate/context.js +0 -57
  51. package/src/validate/example.js +0 -37
  52. package/src/validate/helpers.js +0 -31
  53. package/src/validate/identical.js +0 -20
  54. package/src/validate/main.js +0 -143
  55. package/src/validate/validations.js +0 -289
package/src/simplify.js DELETED
@@ -1,103 +0,0 @@
1
- import isPlainObj from 'is-plain-obj'
2
- import mapObj from 'map-obj'
3
-
4
- import { removeFalsy } from './utils/remove_falsy.js'
5
-
6
- // Removes default values (empty objects and arrays) from the configuration.
7
- export const simplifyConfig = function ({
8
- build: { environment, processing: { css, html, images, js, ...processing } = {}, services, ...build } = {},
9
- functions,
10
- plugins,
11
- headers,
12
- redirects,
13
- context = {},
14
- ...config
15
- }) {
16
- const buildA = {
17
- ...build,
18
- ...simplifyEnvironment(environment),
19
- ...removeEmptyObject(
20
- {
21
- ...processing,
22
- ...removeEmptyObject(css, 'css'),
23
- ...removeEmptyObject(html, 'html'),
24
- ...removeEmptyObject(images, 'images'),
25
- ...removeEmptyObject(js, 'js'),
26
- },
27
- 'processing',
28
- ),
29
- ...removeEmptyObject(services, 'services'),
30
- }
31
- return removeFalsy({
32
- ...config,
33
- ...removeEmptyObject(simplifyFunctions(functions), 'functions'),
34
- ...removeEmptyObject(buildA, 'build'),
35
- ...removeEmptyArray(plugins, 'plugins'),
36
- ...removeEmptyArray(headers, 'headers'),
37
- ...removeEmptyArray(simplifyRedirects(redirects), 'redirects'),
38
- ...removeEmptyObject(simplifyContexts(context), 'context'),
39
- })
40
- }
41
-
42
- const simplifyEnvironment = function (environment) {
43
- return Array.isArray(environment)
44
- ? removeEmptyArray(environment, 'environment')
45
- : removeEmptyObject(environment, 'environment')
46
- }
47
-
48
- const simplifyContexts = function (contextProps) {
49
- return mapObj(contextProps, simplifyContextProps)
50
- }
51
-
52
- const simplifyContextProps = function (context, contextConfig) {
53
- return [context, simplifyConfig(contextConfig)]
54
- }
55
-
56
- const simplifyFunctions = function (functions) {
57
- return isPlainObj(functions) ? Object.entries(functions).reduce(simplifyFunction, {}) : functions
58
- }
59
-
60
- const simplifyFunction = function (functions, [key, value]) {
61
- return { ...functions, ...removeEmptyObject(value, key) }
62
- }
63
-
64
- const simplifyRedirects = function (redirects) {
65
- return Array.isArray(redirects) ? redirects.map(simplifyRedirect) : redirects
66
- }
67
-
68
- const simplifyRedirect = function (redirect) {
69
- if (!isPlainObj(redirect)) {
70
- return redirect
71
- }
72
-
73
- const { force, proxy, query, conditions, headers, ...redirectA } = redirect
74
- return {
75
- ...redirectA,
76
- ...removeDefaultValue(force, 'force', false),
77
- ...removeDefaultValue(proxy, 'proxy', false),
78
- ...removeEmptyObject(query, 'query'),
79
- ...removeEmptyObject(conditions, 'conditions'),
80
- ...removeEmptyObject(headers, 'headers'),
81
- }
82
- }
83
-
84
- const removeDefaultValue = function (value, propName, defaultValue) {
85
- return value === defaultValue ? {} : { [propName]: value }
86
- }
87
-
88
- export const removeEmptyObject = function (object, propName) {
89
- if (!isPlainObj(object)) {
90
- return {}
91
- }
92
-
93
- const objectA = removeFalsy(object)
94
- return Object.keys(objectA).length === 0 ? {} : { [propName]: objectA }
95
- }
96
-
97
- export const removeEmptyArray = function (array, propName) {
98
- if (!Array.isArray(array)) {
99
- return {}
100
- }
101
-
102
- return array.length === 0 ? {} : { [propName]: array }
103
- }
@@ -1,10 +0,0 @@
1
- // Group objects according to a key attribute.
2
- // The key must exist in each object and be a string.
3
- export const groupBy = function (objects, keyName) {
4
- const keys = [...new Set(objects.map((object) => object[keyName]))]
5
- return keys.map((key) => groupObjects(objects, keyName, key))
6
- }
7
-
8
- const groupObjects = function (objects, keyName, key) {
9
- return objects.filter((object) => object[keyName] === key)
10
- }
@@ -1,18 +0,0 @@
1
- import filterObj from 'filter-obj'
2
-
3
- // Remove falsy values from object
4
- export const removeFalsy = function (obj) {
5
- return filterObj(obj, (key, value) => isTruthy(value))
6
- }
7
-
8
- export const removeUndefined = function (obj) {
9
- return filterObj(obj, (key, value) => isDefined(value))
10
- }
11
-
12
- export const isTruthy = function (value) {
13
- return isDefined(value) && (typeof value !== 'string' || value.trim() !== '')
14
- }
15
-
16
- export const isDefined = function (value) {
17
- return value !== undefined && value !== null
18
- }
package/src/utils/set.js DELETED
@@ -1,33 +0,0 @@
1
- import isPlainObj from 'is-plain-obj'
2
-
3
- // Set a property deeply using an array of `keys` which can be either strings
4
- // (object properties) or integers (array indices).
5
- // Adds default values when intermediary properties are undefined or have the
6
- // wrong type. Also extends arrays when they are too small for a given index.
7
- // Does not mutate.
8
- export const setProp = function (parent, keys, value) {
9
- if (keys.length === 0) {
10
- return value
11
- }
12
-
13
- if (Number.isInteger(keys[0])) {
14
- return setArrayProp(parent, keys, value)
15
- }
16
-
17
- return setObjectProp(parent, keys, value)
18
- }
19
-
20
- const setArrayProp = function (parent, [index, ...keys], value) {
21
- const arrayParent = Array.isArray(parent) ? parent : []
22
- const missingItems = index - arrayParent.length + 1
23
- // eslint-disable-next-line unicorn/no-new-array
24
- const normalizedParent = missingItems > 0 ? [...arrayParent, ...new Array(missingItems)] : arrayParent
25
- const newValue = setProp(normalizedParent[index], keys, value)
26
- return [...normalizedParent.slice(0, index), newValue, ...normalizedParent.slice(index + 1)]
27
- }
28
-
29
- const setObjectProp = function (parent, [key, ...keys], value) {
30
- const objectParent = isPlainObj(parent) ? parent : {}
31
- const newValue = setProp(objectParent[key], keys, value)
32
- return { ...objectParent, [key]: newValue }
33
- }
package/src/utils/toml.js DELETED
@@ -1,23 +0,0 @@
1
- import { parse as loadToml } from 'toml'
2
- import tomlify from 'tomlify-j0.4'
3
-
4
- // Parse from TOML to JavaScript
5
- export const parseToml = function (configString) {
6
- const config = loadToml(configString)
7
- // `toml.parse()` returns a object with `null` prototype deeply, which can
8
- // sometimes create problems with some utilities. We convert it.
9
- // TOML can return Date instances, but JSON will stringify those, and we
10
- // don't use Date in netlify.toml, so this should be ok.
11
- return JSON.parse(JSON.stringify(config))
12
- }
13
-
14
- // Serialize JavaScript object to TOML
15
- export const serializeToml = function (object) {
16
- return tomlify.toToml(object, { space: 2, replace: replaceTomlValue })
17
- }
18
-
19
- // `tomlify-j0.4` serializes integers as floats, e.g. `200.0`.
20
- // This is a problem with `redirects[*].status`.
21
- const replaceTomlValue = function (key, value) {
22
- return Number.isInteger(value) ? String(value) : false
23
- }
@@ -1,57 +0,0 @@
1
- import { warnContextPluginConfig, throwContextPluginsConfig } from '../log/messages.js'
2
- import { UI_ORIGIN } from '../origin.js'
3
-
4
- // The only reason to specify both `[[plugins]]` and
5
- // `[[contexts.{context}.plugins]]` is to configure context-specific plugin
6
- // inputs.
7
- // The second cannot be used to enable a plugin for a specific context, because
8
- // it would be overridden by `[[plugins]]`.
9
- // We prevent against that mistake by printing a warning message when both are
10
- // used. We only do this when `[[plugins]]` is due to plugin being UI-installed.
11
- // We also fail the build when the following additional conditions apply:
12
- // - `package` is the only property in `[[contexts.{context}.plugins]]`, i.e.
13
- // there are no context-specific `inputs`
14
- // - The current build is not in `context`
15
- export const validateContextsPluginsConfig = function ({ contextProps, plugins, contexts, logs }) {
16
- Object.entries(contextProps).forEach(([givenContext, givenContextProps]) => {
17
- validateContextPluginsConfig({ givenContextProps, plugins, givenContext, contexts, logs })
18
- })
19
- }
20
-
21
- const validateContextPluginsConfig = function ({
22
- givenContextProps: { plugins: contextPlugins = [] },
23
- plugins,
24
- givenContext,
25
- contexts,
26
- logs,
27
- }) {
28
- contextPlugins.forEach((pluginConfig) => {
29
- validateContextPluginConfig({ pluginConfig, plugins, givenContext, contexts, logs })
30
- })
31
- }
32
-
33
- const validateContextPluginConfig = function ({
34
- pluginConfig: { package: packageName, inputs = {} },
35
- plugins = [],
36
- givenContext,
37
- contexts,
38
- logs,
39
- }) {
40
- if (!isContextFreePlugin(plugins, packageName)) {
41
- return
42
- }
43
-
44
- if (isPluginConfigError(contexts, givenContext, inputs)) {
45
- throwContextPluginsConfig(packageName, givenContext)
46
- }
47
-
48
- warnContextPluginConfig(logs, packageName, givenContext)
49
- }
50
-
51
- const isContextFreePlugin = function (plugins, packageName) {
52
- return plugins.some((plugin) => plugin.package === packageName && plugin.origin === UI_ORIGIN)
53
- }
54
-
55
- const isPluginConfigError = function (contexts, givenContext, inputs) {
56
- return contexts.every((context) => context !== givenContext) && Object.keys(inputs).length === 0
57
- }
@@ -1,37 +0,0 @@
1
- import indentString from 'indent-string'
2
-
3
- import { THEME } from '../log/theme.js'
4
- import { serializeToml } from '../utils/toml.js'
5
-
6
- // Print invalid value and example netlify.toml
7
- export const getExample = function ({ value, key, prevPath, example, formatInvalid }) {
8
- const exampleA = typeof example === 'function' ? example(value, key, prevPath) : example
9
- return `
10
- ${THEME.errorSubHeader('Invalid syntax')}
11
-
12
- ${indentString(getInvalidValue(value, prevPath, formatInvalid), 2)}
13
-
14
- ${THEME.subHeader('Valid syntax')}
15
-
16
- ${indentString(serializeToml(exampleA), 2)}`
17
- }
18
-
19
- const getInvalidValue = function (value, prevPath, formatInvalid) {
20
- // slice() is temporary, so it does not mutate
21
- // eslint-disable-next-line fp/no-mutating-methods
22
- const invalidValue = [...prevPath].reverse().reduce(setInvalidValuePart, value)
23
-
24
- // If `formatInvalid` is supplied, we use it to format the invalid value
25
- // before serializing it to TOML and printing it.
26
- const formattedInvalidValue = typeof formatInvalid === 'function' ? formatInvalid(invalidValue) : invalidValue
27
- const invalidValueA = serializeToml(formattedInvalidValue)
28
- return invalidValueA
29
- }
30
-
31
- const setInvalidValuePart = function (value, part) {
32
- if (Number.isInteger(part)) {
33
- return [value]
34
- }
35
-
36
- return value === undefined ? {} : { [part]: value }
37
- }
@@ -1,31 +0,0 @@
1
- import isPlainObj from 'is-plain-obj'
2
-
3
- export const isArrayOfObjects = function (value) {
4
- return Array.isArray(value) && value.every(isPlainObj)
5
- }
6
-
7
- export const isArrayOfStrings = function (value) {
8
- return Array.isArray(value) && value.every(isString)
9
- }
10
-
11
- export const isString = function (value) {
12
- return typeof value === 'string'
13
- }
14
-
15
- // Check an object valid properties, including legacy ones
16
- export const validProperties = function (propNames, legacyPropNames) {
17
- return {
18
- check: (value) => checkValidProperty(value, [...propNames, ...legacyPropNames]),
19
- message: `has unknown properties. Valid properties are:
20
- ${propNames.map((propName) => ` - ${propName}`).join('\n')}`,
21
- }
22
- }
23
-
24
- const checkValidProperty = function (value, propNames) {
25
- return Object.keys(value).every((propName) => propNames.includes(propName))
26
- }
27
-
28
- export const functionsDirectoryCheck = {
29
- formatInvalid: ({ functionsDirectory } = {}) => ({ functions: { directory: functionsDirectory } }),
30
- propertyName: 'functions.directory',
31
- }
@@ -1,20 +0,0 @@
1
- import { throwUserError } from '../error.js'
2
-
3
- // Validate that plugin are configured only once per origin
4
- // (`netlify.toml` or UI).
5
- // Exception: context-specific configuration since we allow context-specific
6
- // overrides. This does not validate them since contexts have not been merged
7
- // yet.
8
- export const validateIdenticalPlugins = function ({ plugins = [] }) {
9
- plugins.filter(hasIdenticalPlugin).forEach(throwIndenticalPlugin)
10
- }
11
-
12
- const hasIdenticalPlugin = function ({ package: packageName, origin }, index, plugins) {
13
- return plugins.slice(index + 1).some((pluginA) => packageName === pluginA.package && origin === pluginA.origin)
14
- }
15
-
16
- const throwIndenticalPlugin = function ({ package: packageName, origin }) {
17
- throwUserError(`Plugin "${packageName}" must not be specified twice in ${ORIGINS[origin]}`)
18
- }
19
-
20
- const ORIGINS = { config: 'netlify.toml', ui: 'the app' }
@@ -1,143 +0,0 @@
1
- import { throwUserError } from '../error.js'
2
- import { THEME } from '../log/theme.js'
3
-
4
- import { getExample } from './example.js'
5
- import {
6
- PRE_CASE_NORMALIZE_VALIDATIONS,
7
- PRE_MERGE_VALIDATIONS,
8
- PRE_CONTEXT_VALIDATIONS,
9
- PRE_NORMALIZE_VALIDATIONS,
10
- POST_NORMALIZE_VALIDATIONS,
11
- } from './validations.js'
12
-
13
- // Validate the configuration file, before case normalization.
14
- export const validatePreCaseNormalize = function (config) {
15
- validateConfig(config, PRE_CASE_NORMALIZE_VALIDATIONS)
16
- }
17
-
18
- // Validate the configuration file, before `defaultConfig` merge.
19
- export const validatePreMergeConfig = function (config) {
20
- validateConfig(config, PRE_MERGE_VALIDATIONS)
21
- }
22
-
23
- // Validate the configuration file, before context merge.
24
- export const validatePreContextConfig = function (config) {
25
- validateConfig(config, PRE_CONTEXT_VALIDATIONS)
26
- }
27
-
28
- // Validate the configuration file, before normalization.
29
- export const validatePreNormalizeConfig = function (config) {
30
- validateConfig(config, PRE_NORMALIZE_VALIDATIONS)
31
- }
32
-
33
- // Validate the configuration file, after normalization.
34
- export const validatePostNormalizeConfig = function (config) {
35
- validateConfig(config, POST_NORMALIZE_VALIDATIONS)
36
- }
37
-
38
- const validateConfig = function (config, validations) {
39
- try {
40
- validations.forEach(({ property, ...validation }) => {
41
- validateProperty(config, { ...validation, nextPath: property.split('.') })
42
- })
43
- } catch (error) {
44
- throwUserError(error)
45
- }
46
- }
47
-
48
- // Validate a single property in the configuration file.
49
- const validateProperty = function (
50
- parent,
51
- {
52
- nextPath: [propName, nextPropName, ...nextPath],
53
- prevPath = [propName],
54
- propPath = propName,
55
- key = propName,
56
- check,
57
- message,
58
- example,
59
- formatInvalid,
60
- propertyName,
61
- },
62
- ) {
63
- const value = parent[propName]
64
-
65
- if (nextPropName !== undefined) {
66
- return validateChild({
67
- value,
68
- nextPropName,
69
- prevPath,
70
- nextPath,
71
- propPath,
72
- key,
73
- check,
74
- message,
75
- example,
76
- formatInvalid,
77
- propertyName,
78
- })
79
- }
80
-
81
- if (value === undefined || (check !== undefined && check(value, key, prevPath))) {
82
- return
83
- }
84
-
85
- reportError({ prevPath, propPath, message, example, value, key, formatInvalid, propertyName })
86
- }
87
-
88
- const reportError = function ({
89
- prevPath,
90
- propPath,
91
- message,
92
- example,
93
- value,
94
- key,
95
- formatInvalid,
96
- propertyName = propPath,
97
- }) {
98
- throwUserError(`${THEME.highlightWords('Configuration property')} ${propertyName} ${message}
99
- ${getExample({ value, key, prevPath, example, formatInvalid })}`)
100
- }
101
-
102
- // Recurse over children (each part of the `property` array).
103
- const validateChild = function ({ value, nextPropName, prevPath, nextPath, propPath, ...rest }) {
104
- if (value === undefined) {
105
- return
106
- }
107
-
108
- if (nextPropName !== '*') {
109
- return validateProperty(value, {
110
- ...rest,
111
- prevPath: [...prevPath, nextPropName],
112
- nextPath: [nextPropName, ...nextPath],
113
- propPath: `${propPath}.${nextPropName}`,
114
- key: nextPropName,
115
- })
116
- }
117
-
118
- return Object.keys(value).forEach((childProp) => {
119
- validateChildProp({ childProp, value, nextPath, propPath, prevPath, ...rest })
120
- })
121
- }
122
-
123
- // Can use * to recurse over array|object elements.
124
- const validateChildProp = function ({ childProp, value, nextPath, propPath, prevPath, ...rest }) {
125
- if (Array.isArray(value)) {
126
- const key = Number(childProp)
127
- return validateProperty(value, {
128
- ...rest,
129
- prevPath: [...prevPath, key],
130
- nextPath: [key, ...nextPath],
131
- propPath: `${propPath}[${childProp}]`,
132
- key,
133
- })
134
- }
135
-
136
- validateProperty(value, {
137
- ...rest,
138
- prevPath: [...prevPath, childProp],
139
- nextPath: [childProp, ...nextPath],
140
- propPath: `${propPath}.${childProp}`,
141
- key: childProp,
142
- })
143
- }