@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/log/main.js DELETED
@@ -1,48 +0,0 @@
1
- import { cleanupConfig, cleanupEnvironment } from './cleanup.js'
2
- import { logObject, logSubHeader } from './logger.js'
3
- import { cleanupConfigOpts } from './options.js'
4
-
5
- // Log options in debug mode.
6
- export const logOpts = function (opts, { logs, debug, cachedConfig, cachedConfigPath }) {
7
- // In production, print those in the first call to `@netlify/config`, not the
8
- // second one done inside `@netlify/build`
9
- if (!debug || cachedConfig !== undefined || cachedConfigPath !== undefined) {
10
- return
11
- }
12
-
13
- logSubHeader(logs, 'Initial build environment')
14
- logObject(logs, cleanupConfigOpts(opts))
15
- }
16
-
17
- // Log `defaultConfig` option in debug mode
18
- export const logDefaultConfig = function (defaultConfig, { logs, debug, baseRelDir }) {
19
- if (!debug || defaultConfig === undefined) {
20
- return
21
- }
22
-
23
- logSubHeader(logs, 'UI build settings')
24
- logObject(logs, cleanupConfig({ ...defaultConfig, baseRelDir }))
25
- }
26
-
27
- // Log `inlineConfig` option in debug mode
28
- export const logInlineConfig = function (initialConfig, { logs, debug }) {
29
- if (!debug || Object.keys(initialConfig).length === 0) {
30
- return
31
- }
32
-
33
- logSubHeader(logs, 'Configuration override')
34
- logObject(logs, cleanupConfig(initialConfig))
35
- }
36
-
37
- // Log return value of `@netlify/config` in debug mode
38
- export const logResult = function ({ configPath, buildDir, config, context, branch, env }, { logs, debug }) {
39
- if (!debug) {
40
- return
41
- }
42
-
43
- logSubHeader(logs, 'Resolved build environment')
44
- logObject(logs, { configPath, buildDir, context, branch, env: cleanupEnvironment(env) })
45
-
46
- logSubHeader(logs, 'Resolved config')
47
- logObject(logs, cleanupConfig(config))
48
- }
@@ -1,126 +0,0 @@
1
- import { throwUserError } from '../error.js'
2
-
3
- import { logWarning } from './logger.js'
4
-
5
- export const ERROR_CALL_TO_ACTION = `Double-check your login status with 'netlify status' or contact support with details of your error.`
6
-
7
- export const throwOnInvalidTomlSequence = function (invalidSequence) {
8
- throwUserError(
9
- `In netlify.toml, the following backslash should be escaped: ${invalidSequence}
10
- The following should be used instead: \\${invalidSequence}`,
11
- )
12
- }
13
-
14
- export const warnLegacyFunctionsDirectory = ({ config = {}, logs }) => {
15
- const { functionsDirectory, functionsDirectoryOrigin } = config
16
-
17
- if (functionsDirectoryOrigin !== 'config-v1') {
18
- return
19
- }
20
-
21
- logWarning(
22
- logs,
23
- `
24
- Detected functions directory configuration in netlify.toml under [build] settings.
25
- We recommend updating netlify.toml to set the functions directory under [functions] settings using the directory property. For example,
26
-
27
- [functions]
28
- directory = "${functionsDirectory}"`,
29
- )
30
- }
31
-
32
- export const warnContextPluginConfig = function (logs, packageName, context) {
33
- logWarning(
34
- logs,
35
- `
36
- "${packageName}" is installed in the UI, which means that it runs in all deploy contexts, regardless of file-based configuration.
37
- To run "${packageName}" in the ${context} context only, uninstall the plugin from the site plugins list.`,
38
- )
39
- }
40
-
41
- export const throwContextPluginsConfig = function (packageName, context) {
42
- throwUserError(
43
- `
44
- "${packageName}" is installed in the UI, which means that it runs in all deploy contexts, regardless of file-based configuration.
45
- To run "${packageName}" in the ${context} context only, uninstall the plugin from the site plugins list.
46
- To run "${packageName}" in all contexts, please remove the following section from "netlify.toml".
47
-
48
- [[context.${context}.plugins]]
49
- package = "${packageName}"
50
- `,
51
- )
52
- }
53
-
54
- export const warnHeadersParsing = function (logs, errors) {
55
- if (errors.length === 0) {
56
- return
57
- }
58
-
59
- const errorMessage = errors.map(getErrorMessage).join('\n\n')
60
- logWarning(
61
- logs,
62
- `
63
- Warning: some headers have syntax errors:
64
-
65
- ${errorMessage}`,
66
- )
67
- }
68
-
69
- // Headers with different cases are not currently the way users probably
70
- // intend them to be, so we print a warning message.
71
- // See issue at https://github.com/netlify/build/issues/2290
72
- export const warnHeadersCaseSensitivity = function (logs, headers) {
73
- const headersA = headers.flatMap(getHeaderNames).filter(isNotDuplicateHeaderName).map(addHeaderLowerCase)
74
- const differentCaseHeader = headersA.find(hasHeaderCaseDuplicate)
75
- if (differentCaseHeader === undefined) {
76
- return
77
- }
78
-
79
- const { forPath, headerName } = headersA.find((header) => isHeaderCaseDuplicate(header, differentCaseHeader))
80
- const sameForPath = forPath === differentCaseHeader.forPath ? ` for "${forPath}"` : ''
81
- logWarning(
82
- logs,
83
- `
84
- Warning: the same header is set twice with different cases${sameForPath}: "${headerName}" and "${differentCaseHeader.headerName}"`,
85
- )
86
- }
87
-
88
- const getHeaderNames = function ({ for: forPath, values = {} }) {
89
- return Object.keys(values).map((headerName) => ({ forPath, headerName }))
90
- }
91
-
92
- const isNotDuplicateHeaderName = function ({ headerName }, index, headers) {
93
- return headers.slice(index + 1).every((header) => header.headerName !== headerName)
94
- }
95
-
96
- const addHeaderLowerCase = function ({ forPath, headerName }) {
97
- const lowerHeaderName = headerName.toLowerCase()
98
- return { forPath, headerName, lowerHeaderName }
99
- }
100
-
101
- const hasHeaderCaseDuplicate = function ({ lowerHeaderName }, index, headers) {
102
- return headers.slice(index + 1).some((header) => header.lowerHeaderName === lowerHeaderName)
103
- }
104
-
105
- const isHeaderCaseDuplicate = function ({ headerName, lowerHeaderName }, differentCaseHeader) {
106
- return differentCaseHeader.headerName !== headerName && differentCaseHeader.lowerHeaderName === lowerHeaderName
107
- }
108
-
109
- export const warnRedirectsParsing = function (logs, errors) {
110
- if (errors.length === 0) {
111
- return
112
- }
113
-
114
- const errorMessage = errors.map(getErrorMessage).join('\n\n')
115
- logWarning(
116
- logs,
117
- `
118
- Warning: some redirects have syntax errors:
119
-
120
- ${errorMessage}`,
121
- )
122
- }
123
-
124
- const getErrorMessage = function ({ message }) {
125
- return message
126
- }
@@ -1,43 +0,0 @@
1
- import { DEFAULT_FEATURE_FLAGS } from '../options/feature_flags.js'
2
- import { removeEmptyArray } from '../simplify.js'
3
- import { removeFalsy } from '../utils/remove_falsy.js'
4
-
5
- // Use an allowlist to prevent printing confidential values.
6
- export const cleanupConfigOpts = function ({
7
- config,
8
- cwd,
9
- context,
10
- branch,
11
- mode,
12
- repositoryRoot,
13
- siteId,
14
- baseRelDir,
15
- env = {},
16
- featureFlags = {},
17
- }) {
18
- const envA = Object.keys(env)
19
- return removeFalsy({
20
- config,
21
- cwd,
22
- context,
23
- branch,
24
- mode,
25
- repositoryRoot,
26
- siteId,
27
- baseRelDir,
28
- ...removeEmptyArray(envA, 'env'),
29
- featureFlags: cleanFeatureFlags(featureFlags),
30
- })
31
- }
32
-
33
- // We only show feature flags related to `@netlify/config`.
34
- // Also, we only print enabled feature flags.
35
- const cleanFeatureFlags = function (featureFlags) {
36
- return Object.entries(featureFlags)
37
- .filter(shouldPrintFeatureFlag)
38
- .map(([featureFlagName]) => featureFlagName)
39
- }
40
-
41
- const shouldPrintFeatureFlag = function ([featureFlagName, enabled]) {
42
- return enabled && featureFlagName in DEFAULT_FEATURE_FLAGS
43
- }
@@ -1,5 +0,0 @@
1
- import { dump } from 'js-yaml'
2
-
3
- export const serializeObject = function (object) {
4
- return dump(object, { noRefs: true, sortKeys: true, lineWidth: Number.POSITIVE_INFINITY }).trimEnd()
5
- }
package/src/log/theme.js DELETED
@@ -1,14 +0,0 @@
1
- import chalk from 'chalk'
2
-
3
- // Color theme. Please use this instead of requiring chalk directly, to ensure
4
- // consistent colors.
5
- export const THEME = {
6
- // Single lines used as subheaders
7
- subHeader: chalk.cyan.bold,
8
- // Single lines used as subheaders indicating an error
9
- errorSubHeader: chalk.red.bold,
10
- // Same for warnings
11
- warningLine: chalk.yellowBright,
12
- // One of several words that should be highlighted inside a line
13
- highlightWords: chalk.cyan,
14
- }
package/src/main.js DELETED
@@ -1,285 +0,0 @@
1
- import { getApiClient } from './api/client.js'
2
- import { getSiteInfo } from './api/site_info.js'
3
- import { getInitialBase, getBase, addBase } from './base.js'
4
- import { getBuildDir } from './build_dir.js'
5
- import { getCachedConfig } from './cached_config.js'
6
- import { normalizeContextProps, mergeContext } from './context.js'
7
- import { parseDefaultConfig } from './default.js'
8
- import { getEnv } from './env/main.js'
9
- import { resolveConfigPaths } from './files.js'
10
- import { getHeadersPath, addHeaders } from './headers.js'
11
- import { getInlineConfig } from './inline_config.js'
12
- import { logResult } from './log/main.js'
13
- import { mergeConfigs } from './merge.js'
14
- import { normalizeBeforeConfigMerge, normalizeAfterConfigMerge } from './merge_normalize.js'
15
- import { addDefaultOpts, normalizeOpts } from './options/main.js'
16
- import { UI_ORIGIN, CONFIG_ORIGIN, INLINE_ORIGIN } from './origin.js'
17
- import { parseConfig } from './parse.js'
18
- import { getConfigPath } from './path.js'
19
- import { getRedirectsPath, addRedirects } from './redirects.js'
20
-
21
- export { DEV_EVENTS, EVENTS } from './events.js'
22
- export { cleanupConfig } from './log/cleanup.js'
23
- // eslint-disable-next-line import/max-dependencies
24
- export { updateConfig, restoreConfig } from './mutations/update.js'
25
-
26
- // Load the configuration file.
27
- // Takes an optional configuration file path as input and return the resolved
28
- // `config` together with related properties such as the `configPath`.
29
- export const resolveConfig = async function (opts) {
30
- const { cachedConfig, cachedConfigPath, host, scheme, pathPrefix, testOpts, token, offline, ...optsA } =
31
- addDefaultOpts(opts)
32
- // `api` is not JSON-serializable, so we cannot cache it inside `cachedConfig`
33
- const api = getApiClient({ token, offline, host, scheme, pathPrefix, testOpts })
34
-
35
- const parsedCachedConfig = await getCachedConfig({ cachedConfig, cachedConfigPath, token, api })
36
- if (parsedCachedConfig !== undefined) {
37
- return parsedCachedConfig
38
- }
39
-
40
- const {
41
- config: configOpt,
42
- defaultConfig,
43
- inlineConfig,
44
- configMutations,
45
- cwd,
46
- context,
47
- repositoryRoot,
48
- base,
49
- branch,
50
- siteId,
51
- deployId,
52
- buildId,
53
- baseRelDir,
54
- mode,
55
- debug,
56
- logs,
57
- featureFlags,
58
- } = await normalizeOpts(optsA)
59
-
60
- const { siteInfo, accounts, addons } = await getSiteInfo({ api, siteId, mode, testOpts })
61
-
62
- const { defaultConfig: defaultConfigA, baseRelDir: baseRelDirA } = parseDefaultConfig({
63
- defaultConfig,
64
- base,
65
- baseRelDir,
66
- siteInfo,
67
- logs,
68
- debug,
69
- })
70
- const inlineConfigA = getInlineConfig({ inlineConfig, configMutations, logs, debug })
71
-
72
- const { configPath, config, buildDir, redirectsPath, headersPath } = await loadConfig({
73
- configOpt,
74
- cwd,
75
- context,
76
- repositoryRoot,
77
- branch,
78
- defaultConfig: defaultConfigA,
79
- inlineConfig: inlineConfigA,
80
- baseRelDir: baseRelDirA,
81
- logs,
82
- featureFlags,
83
- })
84
-
85
- const env = await getEnv({
86
- api,
87
- mode,
88
- config,
89
- siteInfo,
90
- accounts,
91
- addons,
92
- buildDir,
93
- branch,
94
- deployId,
95
- buildId,
96
- context,
97
- })
98
-
99
- // @todo Remove in the next major version.
100
- const configA = addLegacyFunctionsDirectory(config)
101
-
102
- const result = {
103
- siteInfo,
104
- accounts,
105
- addons,
106
- env,
107
- configPath,
108
- redirectsPath,
109
- headersPath,
110
- buildDir,
111
- repositoryRoot,
112
- config: configA,
113
- context,
114
- branch,
115
- token,
116
- api,
117
- logs,
118
- }
119
- logResult(result, { logs, debug })
120
- return result
121
- }
122
-
123
- // Adds a `build.functions` property that mirrors `functionsDirectory`, for
124
- // backward compatibility.
125
- const addLegacyFunctionsDirectory = (config) => {
126
- if (!config.functionsDirectory) {
127
- return config
128
- }
129
-
130
- return {
131
- ...config,
132
- build: {
133
- ...config.build,
134
- functions: config.functionsDirectory,
135
- },
136
- }
137
- }
138
-
139
- // Try to load the configuration file in two passes.
140
- // The first pass uses the `defaultConfig`'s `build.base` (if defined).
141
- // The second pass uses the `build.base` from the first pass (if defined).
142
- const loadConfig = async function ({
143
- configOpt,
144
- cwd,
145
- context,
146
- repositoryRoot,
147
- branch,
148
- defaultConfig,
149
- inlineConfig,
150
- baseRelDir,
151
- logs,
152
- featureFlags,
153
- }) {
154
- const initialBase = getInitialBase({ repositoryRoot, defaultConfig, inlineConfig })
155
- const { configPath, config, buildDir, base, redirectsPath, headersPath } = await getFullConfig({
156
- configOpt,
157
- cwd,
158
- context,
159
- repositoryRoot,
160
- branch,
161
- defaultConfig,
162
- inlineConfig,
163
- baseRelDir,
164
- configBase: initialBase,
165
- logs,
166
- featureFlags,
167
- })
168
-
169
- // No second pass needed if:
170
- // - there is no `build.base` (in which case both `base` and `initialBase`
171
- // are `undefined`)
172
- // - `build.base` is the same as the `Base directory` UI setting (already
173
- // used in the first round)
174
- // - `baseRelDir` feature flag is not used. This feature flag was introduced
175
- // to ensure backward compatibility.
176
- if (!baseRelDir || base === initialBase) {
177
- return { configPath, config, buildDir, redirectsPath, headersPath }
178
- }
179
-
180
- const {
181
- configPath: configPathA,
182
- config: configA,
183
- buildDir: buildDirA,
184
- redirectsPath: redirectsPathA,
185
- headersPath: headersPathA,
186
- } = await getFullConfig({
187
- cwd,
188
- context,
189
- repositoryRoot,
190
- branch,
191
- defaultConfig,
192
- inlineConfig,
193
- baseRelDir,
194
- configBase: base,
195
- base,
196
- logs,
197
- featureFlags,
198
- })
199
- return {
200
- configPath: configPathA,
201
- config: configA,
202
- buildDir: buildDirA,
203
- redirectsPath: redirectsPathA,
204
- headersPath: headersPathA,
205
- }
206
- }
207
-
208
- // Load configuration file and normalize it, merge contexts, etc.
209
- const getFullConfig = async function ({
210
- configOpt,
211
- cwd,
212
- context,
213
- repositoryRoot,
214
- branch,
215
- defaultConfig,
216
- inlineConfig,
217
- baseRelDir,
218
- configBase,
219
- base,
220
- logs,
221
- featureFlags,
222
- }) {
223
- const configPath = await getConfigPath({ configOpt, cwd, repositoryRoot, configBase })
224
-
225
- try {
226
- const config = await parseConfig(configPath)
227
- const configA = mergeAndNormalizeConfig({
228
- config,
229
- defaultConfig,
230
- inlineConfig,
231
- context,
232
- branch,
233
- logs,
234
- })
235
- const {
236
- config: configB,
237
- buildDir,
238
- base: baseA,
239
- } = await resolveFiles({ config: configA, repositoryRoot, base, baseRelDir })
240
- const headersPath = getHeadersPath(configB)
241
- const configC = await addHeaders({ config: configB, headersPath, logs, featureFlags })
242
- const redirectsPath = getRedirectsPath(configC)
243
- const configD = await addRedirects({ config: configC, redirectsPath, logs, featureFlags })
244
- return { configPath, config: configD, buildDir, base: baseA, redirectsPath, headersPath }
245
- } catch (error) {
246
- const configName = configPath === undefined ? '' : ` file ${configPath}`
247
- error.message = `When resolving config${configName}:\n${error.message}`
248
- throw error
249
- }
250
- }
251
-
252
- // Merge:
253
- // - `--defaultConfig`: UI build settings and UI-installed plugins
254
- // - `inlineConfig`: Netlify CLI flags
255
- // Then merge context-specific configuration.
256
- // Before and after those steps, also performs validation and normalization.
257
- // Those need to be done at different stages depending on whether they should
258
- // happen before/after the merges mentioned above.
259
- const mergeAndNormalizeConfig = function ({ config, defaultConfig, inlineConfig, context, branch, logs }) {
260
- const configA = normalizeConfigAndContext(config, CONFIG_ORIGIN)
261
- const defaultConfigA = normalizeConfigAndContext(defaultConfig, UI_ORIGIN)
262
- const inlineConfigA = normalizeConfigAndContext(inlineConfig, INLINE_ORIGIN)
263
-
264
- const configB = mergeConfigs([defaultConfigA, configA])
265
- const configC = mergeContext({ config: configB, context, branch, logs })
266
- const configD = mergeConfigs([configC, inlineConfigA])
267
-
268
- const configE = normalizeAfterConfigMerge(configD)
269
- return configE
270
- }
271
-
272
- const normalizeConfigAndContext = function (config, origin) {
273
- const configA = normalizeBeforeConfigMerge(config, origin)
274
- const configB = normalizeContextProps({ config: configA, origin })
275
- return configB
276
- }
277
-
278
- // Find base directory, build directory and resolve all paths to absolute paths
279
- const resolveFiles = async function ({ config, repositoryRoot, base, baseRelDir }) {
280
- const baseA = getBase(base, repositoryRoot, config)
281
- const buildDir = await getBuildDir(repositoryRoot, baseA)
282
- const configA = await resolveConfigPaths({ config, repositoryRoot, buildDir, baseRelDir })
283
- const configB = addBase(configA, baseA)
284
- return { config: configB, buildDir, base: baseA }
285
- }
package/src/merge.js DELETED
@@ -1,53 +0,0 @@
1
- import deepmerge from 'deepmerge'
2
- import isPlainObj from 'is-plain-obj'
3
-
4
- import { groupBy } from './utils/group.js'
5
- import { removeUndefined } from './utils/remove_falsy.js'
6
-
7
- // Merge an array of configuration objects.
8
- // Last items have higher priority.
9
- // Configuration objects are deeply merged.
10
- // - Arrays are overridden, not concatenated.
11
- export const mergeConfigs = function (configs) {
12
- const cleanedConfigs = configs.map(removeUndefinedProps)
13
- return deepmerge.all(cleanedConfigs, { arrayMerge })
14
- }
15
-
16
- const removeUndefinedProps = function ({ build = {}, ...config }) {
17
- return removeUndefined({ ...config, build: removeUndefined(build) })
18
- }
19
-
20
- // By default `deepmerge` concatenates arrays. We use the `arrayMerge` option
21
- // to remove this behavior. Also, we merge some array properties differently,
22
- // such as `plugins`.
23
- const arrayMerge = function (arrayA, arrayB) {
24
- if (isPluginsProperty(arrayA) && isPluginsProperty(arrayB)) {
25
- return mergePlugins(arrayA, arrayB)
26
- }
27
-
28
- return arrayB
29
- }
30
-
31
- // `deepmerge` does not allow retrieving the name of the array property being
32
- // merged, so we need to do some heuristics.
33
- const isPluginsProperty = function (array) {
34
- return Array.isArray(array) && array.every(isPluginObject)
35
- }
36
-
37
- const isPluginObject = function (object) {
38
- return isPlainObj(object) && typeof object.package === 'string'
39
- }
40
-
41
- // Merge two `config.plugins`. Merge plugins with the same `plugin.package`.
42
- const mergePlugins = function (pluginsA, pluginsB) {
43
- const plugins = [...pluginsA, ...pluginsB]
44
- return groupBy(plugins, 'package').map(mergePluginConfigs)
45
- }
46
-
47
- const mergePluginConfigs = function (plugins) {
48
- return plugins.reduce(mergePluginsPair, {})
49
- }
50
-
51
- const mergePluginsPair = function (pluginA, pluginB) {
52
- return deepmerge(pluginA, pluginB, { arrayMerge })
53
- }
@@ -1,31 +0,0 @@
1
- import { normalizeConfigCase } from './case.js'
2
- import { normalizeConfig } from './normalize.js'
3
- import { addOrigins } from './origin.js'
4
- import { validateIdenticalPlugins } from './validate/identical.js'
5
- import {
6
- validatePreCaseNormalize,
7
- validatePreMergeConfig,
8
- validatePreNormalizeConfig,
9
- validatePostNormalizeConfig,
10
- } from './validate/main.js'
11
-
12
- // Perform validation and normalization logic to apply to all of:
13
- // - config, defaultConfig, inlineConfig
14
- // - context-specific configs
15
- // Therefore, this is performing before merging those together.
16
- export const normalizeBeforeConfigMerge = function (config, origin) {
17
- validatePreCaseNormalize(config)
18
- const configA = normalizeConfigCase(config)
19
- validatePreMergeConfig(configA)
20
- const configB = addOrigins(configA, origin)
21
- validateIdenticalPlugins(configB)
22
- return configB
23
- }
24
-
25
- // Validation and normalization logic performed after merging
26
- export const normalizeAfterConfigMerge = function (config) {
27
- validatePreNormalizeConfig(config)
28
- const configA = normalizeConfig(config)
29
- validatePostNormalizeConfig(configA)
30
- return configA
31
- }
@@ -1,78 +0,0 @@
1
- import { throwUserError } from '../error.js'
2
- import { EVENTS } from '../events.js'
3
- import { WILDCARD_ALL, FUNCTION_CONFIG_PROPERTIES } from '../functions_config.js'
4
- import { setProp } from '../utils/set.js'
5
-
6
- import { getPropName } from './config_prop_name.js'
7
-
8
- // Apply a series of mutations to `inlineConfig`.
9
- // Meant to be used to apply configuration changes at build time.
10
- // Those are applied on the `inlineConfig` object after `@netlify/config`
11
- // normalization. Therefore, this function also denormalizes (reverts that
12
- // normalization) so that the final `config` object can be serialized back to
13
- // a `netlify.toml`.
14
- export const applyMutations = function (inlineConfig, configMutations) {
15
- return configMutations.reduce(applyMutation, inlineConfig)
16
- }
17
-
18
- const applyMutation = function (inlineConfig, { keys, value, event }) {
19
- const propName = getPropName(keys)
20
- if (!(propName in MUTABLE_PROPS)) {
21
- throwUserError(`"netlifyConfig.${propName}" is read-only.`)
22
- }
23
-
24
- const { lastEvent, denormalize } = MUTABLE_PROPS[propName]
25
- validateEvent(lastEvent, event, propName)
26
-
27
- return denormalize === undefined ? setProp(inlineConfig, keys, value) : denormalize(inlineConfig, value, keys)
28
- }
29
-
30
- const validateEvent = function (lastEvent, event, propName) {
31
- if (EVENTS.indexOf(lastEvent) < EVENTS.indexOf(event)) {
32
- throwUserError(`"netlifyConfig.${propName}" cannot be modified after "${lastEvent}".`)
33
- }
34
- }
35
-
36
- // `functions['*'].*` has higher priority than `functions.*` so we convert the
37
- // latter to the former.
38
- const denormalizeFunctionsTopProps = function (
39
- { functions, functions: { [WILDCARD_ALL]: wildcardProps } = {}, ...inlineConfig },
40
- value,
41
- [, key],
42
- ) {
43
- return FUNCTION_CONFIG_PROPERTIES.has(key)
44
- ? {
45
- ...inlineConfig,
46
- functions: { ...functions, [WILDCARD_ALL]: { ...wildcardProps, [key]: value } },
47
- }
48
- : { ...inlineConfig, functions: { ...functions, [key]: value } }
49
- }
50
-
51
- // List of properties that are not read-only.
52
- const MUTABLE_PROPS = {
53
- 'build.command': { lastEvent: 'onPreBuild' },
54
- 'build.edge_functions': { lastEvent: 'onPostBuild' },
55
- 'build.environment': { lastEvent: 'onPostBuild' },
56
- 'build.environment.*': { lastEvent: 'onPostBuild' },
57
- 'build.functions': { lastEvent: 'onBuild' },
58
- 'build.processing': { lastEvent: 'onPostBuild' },
59
- 'build.processing.css': { lastEvent: 'onPostBuild' },
60
- 'build.processing.css.bundle': { lastEvent: 'onPostBuild' },
61
- 'build.processing.css.minify': { lastEvent: 'onPostBuild' },
62
- 'build.processing.html': { lastEvent: 'onPostBuild' },
63
- 'build.processing.html.pretty_urls': { lastEvent: 'onPostBuild' },
64
- 'build.processing.images': { lastEvent: 'onPostBuild' },
65
- 'build.processing.images.compress': { lastEvent: 'onPostBuild' },
66
- 'build.processing.js': { lastEvent: 'onPostBuild' },
67
- 'build.processing.js.bundle': { lastEvent: 'onPostBuild' },
68
- 'build.processing.js.minify': { lastEvent: 'onPostBuild' },
69
- 'build.processing.skip_processing': { lastEvent: 'onPostBuild' },
70
- 'build.publish': { lastEvent: 'onPostBuild' },
71
- 'build.services': { lastEvent: 'onPostBuild' },
72
- 'build.services.*': { lastEvent: 'onPostBuild' },
73
- edge_functions: { lastEvent: 'onPostBuild' },
74
- 'functions.*': { lastEvent: 'onBuild', denormalize: denormalizeFunctionsTopProps },
75
- 'functions.*.*': { lastEvent: 'onBuild' },
76
- headers: { lastEvent: 'onPostBuild' },
77
- redirects: { lastEvent: 'onPostBuild' },
78
- }