@netlify/config 19.0.0-rc → 19.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 (100) hide show
  1. package/bin.js +5 -0
  2. package/lib/api/build_settings.js +28 -0
  3. package/lib/api/client.js +12 -0
  4. package/lib/api/site_info.js +59 -0
  5. package/{src → lib}/base.js +10 -18
  6. package/lib/bin/flags.js +173 -0
  7. package/lib/bin/main.js +59 -0
  8. package/{src → lib}/build_dir.js +11 -15
  9. package/{src → lib}/cached_config.js +14 -17
  10. package/lib/case.js +18 -0
  11. package/lib/context.js +86 -0
  12. package/lib/default.js +27 -0
  13. package/lib/env/envelope.js +24 -0
  14. package/lib/env/git.js +23 -0
  15. package/lib/env/main.js +150 -0
  16. package/lib/error.js +28 -0
  17. package/lib/events.js +21 -0
  18. package/lib/files.js +83 -0
  19. package/{src → lib}/functions_config.js +36 -52
  20. package/lib/headers.js +20 -0
  21. package/lib/inline_config.js +8 -0
  22. package/lib/log/cleanup.js +64 -0
  23. package/lib/log/logger.js +36 -0
  24. package/lib/log/main.js +39 -0
  25. package/{src → lib}/log/messages.js +56 -95
  26. package/lib/log/options.js +29 -0
  27. package/lib/log/serialize.js +4 -0
  28. package/lib/log/theme.js +13 -0
  29. package/lib/main.js +210 -0
  30. package/{src → lib}/merge.js +25 -35
  31. package/lib/merge_normalize.js +24 -0
  32. package/lib/mutations/apply.js +66 -0
  33. package/{src → lib}/mutations/config_prop_name.js +6 -8
  34. package/lib/mutations/update.js +98 -0
  35. package/lib/normalize.js +32 -0
  36. package/lib/options/base.js +54 -0
  37. package/lib/options/branch.js +31 -0
  38. package/{src → lib}/options/feature_flags.js +7 -10
  39. package/lib/options/main.js +91 -0
  40. package/lib/options/repository_root.js +16 -0
  41. package/lib/origin.js +31 -0
  42. package/lib/parse.js +56 -0
  43. package/lib/path.js +41 -0
  44. package/lib/redirects.js +19 -0
  45. package/lib/simplify.js +77 -0
  46. package/{src → lib}/utils/group.js +5 -6
  47. package/lib/utils/remove_falsy.js +14 -0
  48. package/lib/utils/set.js +27 -0
  49. package/lib/utils/toml.js +20 -0
  50. package/lib/validate/context.js +38 -0
  51. package/lib/validate/example.js +30 -0
  52. package/lib/validate/helpers.js +25 -0
  53. package/{src → lib}/validate/identical.js +8 -12
  54. package/lib/validate/main.js +99 -0
  55. package/lib/validate/validations.js +275 -0
  56. package/package.json +21 -12
  57. package/src/api/build_settings.js +0 -41
  58. package/src/api/client.js +0 -15
  59. package/src/api/site_info.js +0 -67
  60. package/src/bin/flags.js +0 -181
  61. package/src/bin/main.js +0 -73
  62. package/src/case.js +0 -37
  63. package/src/context.js +0 -99
  64. package/src/default.js +0 -31
  65. package/src/env/envelope.js +0 -24
  66. package/src/env/git.js +0 -23
  67. package/src/env/main.js +0 -198
  68. package/src/error.js +0 -36
  69. package/src/events.js +0 -22
  70. package/src/files.js +0 -107
  71. package/src/headers.js +0 -30
  72. package/src/inline_config.js +0 -9
  73. package/src/log/cleanup.js +0 -92
  74. package/src/log/logger.js +0 -47
  75. package/src/log/main.js +0 -48
  76. package/src/log/options.js +0 -43
  77. package/src/log/serialize.js +0 -5
  78. package/src/log/theme.js +0 -14
  79. package/src/main.js +0 -285
  80. package/src/merge_normalize.js +0 -31
  81. package/src/mutations/apply.js +0 -78
  82. package/src/mutations/update.js +0 -117
  83. package/src/normalize.js +0 -36
  84. package/src/options/base.js +0 -66
  85. package/src/options/branch.js +0 -34
  86. package/src/options/main.js +0 -111
  87. package/src/options/repository_root.js +0 -21
  88. package/src/origin.js +0 -38
  89. package/src/parse.js +0 -69
  90. package/src/path.js +0 -52
  91. package/src/redirects.js +0 -29
  92. package/src/simplify.js +0 -103
  93. package/src/utils/remove_falsy.js +0 -18
  94. package/src/utils/set.js +0 -33
  95. package/src/utils/toml.js +0 -23
  96. package/src/validate/context.js +0 -57
  97. package/src/validate/example.js +0 -37
  98. package/src/validate/helpers.js +0 -31
  99. package/src/validate/main.js +0 -143
  100. package/src/validate/validations.js +0 -289
@@ -1,67 +0,0 @@
1
- import { getEnvelope } from '../env/envelope.js'
2
- import { throwUserError } from '../error.js'
3
- import { ERROR_CALL_TO_ACTION } from '../log/messages.js'
4
-
5
- // Retrieve Netlify Site information, if available.
6
- // Used to retrieve local build environment variables and UI build settings.
7
- // This is not used in production builds since the buildbot passes this
8
- // information instead.
9
- // Requires knowing the `siteId` and having the access `token`.
10
- // Silently ignore API errors. For example the network connection might be down,
11
- // but local builds should still work regardless.
12
- // eslint-disable-next-line complexity
13
- export const getSiteInfo = async function ({ api, siteId, mode, testOpts: { env: testEnv = true } = {} }) {
14
- if (api === undefined || mode === 'buildbot' || !testEnv) {
15
- const siteInfo = siteId === undefined ? {} : { id: siteId }
16
- return { siteInfo, accounts: [], addons: [] }
17
- }
18
-
19
- const [siteInfo, accounts, addons] = await Promise.all([
20
- getSite(api, siteId),
21
- getAccounts(api),
22
- getAddons(api, siteId),
23
- ])
24
-
25
- if (siteInfo.use_envelope) {
26
- const envelope = await getEnvelope({ api, accountId: siteInfo.account_slug, siteId })
27
- // eslint-disable-next-line fp/no-mutation
28
- siteInfo.build_settings.env = envelope
29
- }
30
-
31
- return { siteInfo, accounts, addons }
32
- }
33
-
34
- const getSite = async function (api, siteId) {
35
- if (siteId === undefined) {
36
- return {}
37
- }
38
-
39
- try {
40
- const site = await api.getSite({ siteId })
41
- return { ...site, id: siteId }
42
- } catch (error) {
43
- throwUserError(`Failed retrieving site data for site ${siteId}: ${error.message}. ${ERROR_CALL_TO_ACTION}`)
44
- }
45
- }
46
-
47
- const getAccounts = async function (api) {
48
- try {
49
- const accounts = await api.listAccountsForUser()
50
- return Array.isArray(accounts) ? accounts : []
51
- } catch (error) {
52
- throwUserError(`Failed retrieving user account: ${error.message}. ${ERROR_CALL_TO_ACTION}`)
53
- }
54
- }
55
-
56
- const getAddons = async function (api, siteId) {
57
- if (siteId === undefined) {
58
- return []
59
- }
60
-
61
- try {
62
- const addons = await api.listServiceInstancesForSite({ siteId })
63
- return Array.isArray(addons) ? addons : []
64
- } catch (error) {
65
- throwUserError(`Failed retrieving addons for site ${siteId}: ${error.message}. ${ERROR_CALL_TO_ACTION}`)
66
- }
67
- }
package/src/bin/flags.js DELETED
@@ -1,181 +0,0 @@
1
- import process from 'process'
2
-
3
- import filterObj from 'filter-obj'
4
- import yargs from 'yargs'
5
- import { hideBin } from 'yargs/helpers'
6
-
7
- import { normalizeCliFeatureFlags } from '../options/feature_flags.js'
8
-
9
- // Parse CLI flags
10
- export const parseFlags = function () {
11
- const { featureFlags: cliFeatureFlags = '', ...flags } = yargs(hideBin(process.argv))
12
- .options(FLAGS)
13
- .usage(USAGE)
14
- .parse()
15
- const featureFlags = normalizeCliFeatureFlags(cliFeatureFlags)
16
- const flagsA = { ...flags, featureFlags }
17
- const flagsB = filterObj(flagsA, isUserFlag)
18
- return flagsB
19
- }
20
-
21
- const jsonParse = function (value) {
22
- return value === undefined ? undefined : JSON.parse(value)
23
- }
24
-
25
- // List of CLI flags
26
- const FLAGS = {
27
- config: {
28
- string: true,
29
- describe: `Path to the configuration file.
30
- Defaults to any netlify.toml in the git repository root directory or the base directory`,
31
- },
32
- defaultConfig: {
33
- string: true,
34
- describe: `JSON configuration object containing default values.
35
- Each configuration default value is used unless overriden through the main configuration file.
36
- Default: none.`,
37
- coerce: jsonParse,
38
- hidden: true,
39
- },
40
- cachedConfig: {
41
- string: true,
42
- describe: `JSON configuration object returned by @netlify/config when --output=/ is used
43
- or when using @netlify/config programmatically.
44
- This is done as a performance optimization to cache the configuration loading logic.
45
- Default: none.`,
46
- coerce: jsonParse,
47
- hidden: true,
48
- },
49
- cachedConfigPath: {
50
- string: true,
51
- describe: `File path to the JSON configuration object returned by @netlify/config
52
- when --output=/path is used.
53
- This is done as a performance optimization to cache the configuration loading logic.
54
- Default: none.`,
55
- hidden: true,
56
- },
57
- inlineConfig: {
58
- string: true,
59
- describe: `JSON configuration object overriding the configuration file and other settings.
60
- Default: none.`,
61
- coerce: jsonParse,
62
- hidden: true,
63
- },
64
- configMutations: {
65
- array: true,
66
- describe: `Array of changes to apply to the configuration.
67
- Each change must be an object with three properties:
68
- - "keys": array of keys targetting the property to change
69
- - "value": new value of that property
70
- - "event": build event when this change was applied, e.g. "onPreBuild"
71
- Default: empty array.`,
72
- coerce: jsonParse,
73
- hidden: true,
74
- },
75
- cwd: {
76
- string: true,
77
- describe: `Current directory. Used to retrieve the configuration file.
78
- Default: current directory`,
79
- },
80
- repositoryRoot: {
81
- string: true,
82
- describe: `Git repository root directory. Used to retrieve the configuration file.
83
- Default: automatically guessed`,
84
- },
85
- output: {
86
- string: true,
87
- describe: `Where to output the JSON result.
88
- Default: "-" (stdout)`,
89
- },
90
- stable: {
91
- boolean: true,
92
- describe: `Sort keys printed in the output.
93
- Default: false`,
94
- default: false,
95
- },
96
- token: {
97
- string: true,
98
- describe: `Netlify API token for authentication.
99
- The NETLIFY_AUTH_TOKEN environment variable can be used as well.`,
100
- },
101
- host: {
102
- string: true,
103
- describe: `Host of the Netlify API.`,
104
- hidden: true,
105
- },
106
- scheme: {
107
- string: true,
108
- describe: `Scheme/protocol of the Netlify API.`,
109
- hidden: true,
110
- },
111
- pathPrefix: {
112
- string: true,
113
- describe: `Base path prefix of the Netlify API.`,
114
- hidden: true,
115
- },
116
- siteId: {
117
- string: true,
118
- describe: `Netlify Site ID.`,
119
- },
120
- context: {
121
- string: true,
122
- describe: `Build context.
123
- Default: 'production'`,
124
- },
125
- branch: {
126
- string: true,
127
- describe: `Repository branch.
128
- Default: automatically guessed`,
129
- },
130
- baseRelDir: {
131
- boolean: true,
132
- describe: `Feature flag meant for backward compatibility.
133
- When enabled, if the 'build.base' configuration property is defined, it is used
134
- to try to retrieve a second configuration file and discard the first one.
135
- Default: true`,
136
- hidden: true,
137
- },
138
- mode: {
139
- string: true,
140
- describe: `Environment in which this is loaded. Can be:
141
- - 'buildbot': within Netlify Buildbot
142
- - 'cli': within Netlify CLI
143
- - 'require': through import('@netlify/config')`,
144
- hidden: true,
145
- },
146
- debug: {
147
- boolean: true,
148
- describe: 'Print debugging information',
149
- hidden: true,
150
- },
151
- testOpts: {
152
- describe: 'Options for testing only',
153
- hidden: true,
154
- },
155
- featureFlags: {
156
- describe: 'Comma-separated list of feature flags to enable unreleased features',
157
- hidden: true,
158
- },
159
- offline: {
160
- boolean: true,
161
- describe: `Do not send requests to the Netlify API to retrieve site settings.
162
- Default: false`,
163
- },
164
- buffer: {
165
- boolean: true,
166
- describe: 'Buffer output instead of streaming it',
167
- hidden: true,
168
- },
169
- }
170
-
171
- const USAGE = `netlify-config [OPTIONS...]
172
-
173
- Retrieve and resolve the Netlify configuration.
174
- The result is printed as a JSON object on stdout.`
175
-
176
- // Remove `yargs`-specific options, shortcuts, dash-cased and aliases
177
- const isUserFlag = function (key, value) {
178
- return value !== undefined && !INTERNAL_KEYS.has(key) && key.length !== 1 && !key.includes('-')
179
- }
180
-
181
- const INTERNAL_KEYS = new Set(['help', 'version', '_', '$0'])
package/src/bin/main.js DELETED
@@ -1,73 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- import { promises as fs } from 'fs'
4
- import { dirname } from 'path'
5
- import process from 'process'
6
-
7
- import fastSafeStringify from 'fast-safe-stringify'
8
- import omit from 'omit.js'
9
-
10
- import { isUserError } from '../error.js'
11
- import { resolveConfig } from '../main.js'
12
-
13
- import { parseFlags } from './flags.js'
14
-
15
- // CLI entry point
16
- const runCli = async function () {
17
- try {
18
- const { stable, output = DEFAULT_OUTPUT, ...flags } = parseFlags()
19
- const result = await resolveConfig(flags)
20
- await handleCliSuccess(result, stable, output)
21
- } catch (error) {
22
- handleCliError(error)
23
- }
24
- }
25
-
26
- const DEFAULT_OUTPUT = '-'
27
-
28
- // The result is output as JSON on success (exit code 0)
29
- const handleCliSuccess = async function (result, stable, output) {
30
- const resultA = serializeApi(result)
31
- const resultB = omit.default(resultA, SECRET_PROPERTIES)
32
- const stringifyFunc = stable ? fastSafeStringify.stableStringify : JSON.stringify
33
- const resultJson = stringifyFunc(resultB, null, 2)
34
- await outputResult(resultJson, output)
35
- process.exitCode = 0
36
- }
37
-
38
- const outputResult = async function (resultJson, output) {
39
- if (output === '-') {
40
- console.log(resultJson)
41
- return
42
- }
43
-
44
- await fs.mkdir(dirname(output), { recursive: true })
45
- await fs.writeFile(output, resultJson)
46
- }
47
-
48
- // `api` is not JSON-serializable, so we remove it
49
- // We still indicate it as a boolean
50
- const serializeApi = function ({ api, ...result }) {
51
- if (api === undefined) {
52
- return result
53
- }
54
-
55
- return { ...result, hasApi: true }
56
- }
57
-
58
- const SECRET_PROPERTIES = ['token']
59
-
60
- const handleCliError = function (error) {
61
- // Errors caused by users do not show stack traces and have exit code 1
62
- if (isUserError(error)) {
63
- console.error(error.message)
64
- process.exitCode = 1
65
- return
66
- }
67
-
68
- // Internal errors / bugs have exit code 2
69
- console.error(error.stack)
70
- process.exitCode = 2
71
- }
72
-
73
- runCli()
package/src/case.js DELETED
@@ -1,37 +0,0 @@
1
- // Some properties can be optionally capitalized. We normalize them to lowercase
2
- export const normalizeConfigCase = function ({ Build, build = Build, ...config }) {
3
- const buildA = normalizeBuildCase(build)
4
- return { ...config, build: buildA }
5
- }
6
-
7
- const normalizeBuildCase = function ({
8
- Base,
9
- base = Base,
10
- Command,
11
- command = Command,
12
- Edge_functions: EdgeFunctions,
13
- edge_functions: edgeFunctions = EdgeFunctions,
14
- Environment,
15
- environment = Environment,
16
- Functions,
17
- functions = Functions,
18
- Ignore,
19
- ignore = Ignore,
20
- Processing,
21
- processing = Processing,
22
- Publish,
23
- publish = Publish,
24
- ...build
25
- } = {}) {
26
- return {
27
- ...build,
28
- base,
29
- command,
30
- edge_functions: edgeFunctions,
31
- environment,
32
- functions,
33
- ignore,
34
- processing,
35
- publish,
36
- }
37
- }
package/src/context.js DELETED
@@ -1,99 +0,0 @@
1
- import isPlainObj from 'is-plain-obj'
2
- import mapObj from 'map-obj'
3
-
4
- import { mergeConfigs } from './merge.js'
5
- import { normalizeBeforeConfigMerge } from './merge_normalize.js'
6
- import { validateContextsPluginsConfig } from './validate/context.js'
7
- import { validatePreContextConfig } from './validate/main.js'
8
-
9
- // Validate and normalize `config.context.*`
10
- export const normalizeContextProps = function ({ config, config: { context: contextProps }, origin }) {
11
- if (contextProps === undefined) {
12
- return config
13
- }
14
-
15
- validatePreContextConfig(config)
16
-
17
- const allContextProps = mapObj(contextProps, (key, contextConfig) => [key, addNamespace(contextConfig)])
18
- const normalizedContextProps = mapObj(allContextProps, (key, contextConfig) => [
19
- key,
20
- normalizeBeforeConfigMerge(contextConfig, origin),
21
- ])
22
- return { ...config, context: normalizedContextProps }
23
- }
24
-
25
- // Merge `config.context.{CONTEXT|BRANCH}.*` to `config.build.*` or `config.*`
26
- // CONTEXT is the `--context` CLI flag.
27
- // BRANCH is the `--branch` CLI flag.
28
- export const mergeContext = function ({
29
- config: { context: contextProps, ...config },
30
- config: { plugins },
31
- context,
32
- branch,
33
- logs,
34
- }) {
35
- if (contextProps === undefined) {
36
- return config
37
- }
38
-
39
- const contexts = [context, branch]
40
- validateContextsPluginsConfig({ contextProps, plugins, contexts, logs })
41
- const filteredContextProps = contexts.map((key) => contextProps[key]).filter(Boolean)
42
- return mergeConfigs([config, ...filteredContextProps])
43
- }
44
-
45
- // `config.context.{context}.*` properties are merged either to `config.*` or
46
- // to `config.build.*`. We distinguish between both by checking the property
47
- // name.
48
- const addNamespace = (contextConfig) => Object.entries(contextConfig).reduce(addNamespacedProperty, {})
49
-
50
- const addNamespacedProperty = function (contextConfig, [key, value]) {
51
- return isBuildProperty(key, value)
52
- ? { ...contextConfig, build: { ...contextConfig.build, [key]: value } }
53
- : { ...contextConfig, [key]: value }
54
- }
55
-
56
- const isBuildProperty = function (key, value) {
57
- return BUILD_PROPERTIES.has(key) && !isFunctionsConfig(key, value) && !isEdgeFunctionsConfig(key, value)
58
- }
59
-
60
- // All properties in `config.build.*`
61
- const BUILD_PROPERTIES = new Set([
62
- 'base',
63
- 'command',
64
- 'edge_functions',
65
- 'environment',
66
- 'functions',
67
- 'ignore',
68
- 'processing',
69
- 'publish',
70
- ])
71
-
72
- // `config.functions` is a plain object while `config.build.functions` is a
73
- // string.
74
- const isFunctionsConfig = function (key, value) {
75
- return key === 'functions' && isPlainObj(value)
76
- }
77
-
78
- // `config.edge_functions` is an array of objects while
79
- // `config.build.edge_functions` is a string.
80
- const isEdgeFunctionsConfig = function (key, value) {
81
- return key === 'edge_functions' && Array.isArray(value)
82
- }
83
-
84
- // Ensure that `inlineConfig` has higher priority than context properties by
85
- // assigining it to `context.*`. Still keep it at the top-level as well since
86
- // some properties are not handled context-sensitively by the API.
87
- // Takes into account that `context.{context}.build.*` is the same as
88
- // `context.{context}.*`
89
- export const ensureConfigPriority = function ({ build = {}, ...config }, context, branch) {
90
- return {
91
- ...config,
92
- build,
93
- context: {
94
- ...config.context,
95
- [context]: { ...config, ...build, build },
96
- [branch]: { ...config, ...build, build },
97
- },
98
- }
99
- }
package/src/default.js DELETED
@@ -1,31 +0,0 @@
1
- import { addBuildSettings } from './api/build_settings.js'
2
- import { logDefaultConfig } from './log/main.js'
3
-
4
- // Retrieve default configuration file. It has less priority and it also does
5
- // not get normalized, merged with contexts, etc.
6
- export const parseDefaultConfig = function ({ defaultConfig, base, baseRelDir, siteInfo, logs, debug }) {
7
- const defaultConfigB = addDefaultConfigBase(defaultConfig, base)
8
- const { defaultConfig: defaultConfigC, baseRelDir: baseRelDirA = DEFAULT_BASE_REL_DIR } = addBuildSettings({
9
- defaultConfig: defaultConfigB,
10
- baseRelDir,
11
- siteInfo,
12
- })
13
- logDefaultConfig(defaultConfigC, { logs, debug, baseRelDir: baseRelDirA })
14
- return { defaultConfig: defaultConfigC, baseRelDir: baseRelDirA }
15
- }
16
-
17
- // When the `base` was overridden, add it to `defaultConfig` so it behaves
18
- // as if it had been specified in the UI settings
19
- const addDefaultConfigBase = function (defaultConfig, base) {
20
- if (base === undefined) {
21
- return defaultConfig
22
- }
23
-
24
- const { build = {} } = defaultConfig
25
- return { ...defaultConfig, build: { ...build, base } }
26
- }
27
-
28
- // `baseRelDir` should default to `true` only if the option was not passed and
29
- // it could be retrieved from the `siteInfo`, which is why the default value
30
- // is assigned later than other properties.
31
- const DEFAULT_BASE_REL_DIR = true
@@ -1,24 +0,0 @@
1
- export const getEnvelope = async function ({ api, accountId, siteId }) {
2
- if (accountId === undefined) {
3
- return {}
4
- }
5
- try {
6
- const environmentVariables = await api.getEnvVars({ accountId, siteId })
7
- // eslint-disable-next-line fp/no-mutating-methods
8
- const sortedEnvVarsFromDevContext = environmentVariables
9
- .sort((left, right) => (left.key.toLowerCase() < right.key.toLowerCase() ? -1 : 1))
10
- .reduce((acc, cur) => {
11
- const envVar = cur.values.find((val) => ['dev', 'all'].includes(val.context))
12
- if (envVar && envVar.value) {
13
- return {
14
- ...acc,
15
- [cur.key]: envVar.value,
16
- }
17
- }
18
- return acc
19
- }, {})
20
- return sortedEnvVarsFromDevContext
21
- } catch {
22
- return {}
23
- }
24
- }
package/src/env/git.js DELETED
@@ -1,23 +0,0 @@
1
- import { execa } from 'execa'
2
-
3
- import { removeFalsy } from '../utils/remove_falsy.js'
4
-
5
- // Retrieve git-related information for use in environment variables.
6
- // git is optional and there might be not git repository.
7
- // We purposely keep this decoupled from the git utility.
8
- export const getGitEnv = async function (buildDir, branch) {
9
- const [COMMIT_REF, CACHED_COMMIT_REF] = await Promise.all([
10
- git(['rev-parse', 'HEAD'], buildDir),
11
- git(['rev-parse', 'HEAD^'], buildDir),
12
- ])
13
- const gitEnv = { BRANCH: branch, HEAD: branch, COMMIT_REF, CACHED_COMMIT_REF, PULL_REQUEST: 'false' }
14
- const gitEnvA = removeFalsy(gitEnv)
15
- return gitEnvA
16
- }
17
-
18
- const git = async function (args, cwd) {
19
- try {
20
- const { stdout } = await execa('git', args, { cwd })
21
- return stdout
22
- } catch {}
23
- }