@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.
- package/package.json +8 -7
- package/src/api/build_settings.js +0 -41
- package/src/api/client.js +0 -15
- package/src/api/site_info.js +0 -67
- package/src/base.js +0 -34
- package/src/bin/flags.js +0 -181
- package/src/bin/main.js +0 -73
- package/src/build_dir.js +0 -26
- package/src/cached_config.js +0 -29
- package/src/case.js +0 -37
- package/src/context.js +0 -108
- package/src/default.js +0 -31
- package/src/env/envelope.js +0 -24
- package/src/env/git.js +0 -23
- package/src/env/main.js +0 -202
- package/src/error.js +0 -36
- package/src/events.js +0 -22
- package/src/files.js +0 -107
- package/src/functions_config.js +0 -83
- package/src/headers.js +0 -30
- package/src/inline_config.js +0 -9
- package/src/log/cleanup.js +0 -92
- package/src/log/logger.js +0 -47
- package/src/log/main.js +0 -48
- package/src/log/messages.js +0 -126
- package/src/log/options.js +0 -43
- package/src/log/serialize.js +0 -5
- package/src/log/theme.js +0 -14
- package/src/main.js +0 -285
- package/src/merge.js +0 -53
- package/src/merge_normalize.js +0 -31
- package/src/mutations/apply.js +0 -78
- package/src/mutations/config_prop_name.js +0 -16
- package/src/mutations/update.js +0 -117
- package/src/normalize.js +0 -36
- package/src/options/base.js +0 -66
- package/src/options/branch.js +0 -34
- package/src/options/feature_flags.js +0 -15
- package/src/options/main.js +0 -111
- package/src/options/repository_root.js +0 -21
- package/src/origin.js +0 -38
- package/src/parse.js +0 -69
- package/src/path.js +0 -52
- package/src/redirects.js +0 -29
- package/src/simplify.js +0 -103
- package/src/utils/group.js +0 -10
- package/src/utils/remove_falsy.js +0 -18
- package/src/utils/set.js +0 -33
- package/src/utils/toml.js +0 -23
- package/src/validate/context.js +0 -57
- package/src/validate/example.js +0 -37
- package/src/validate/helpers.js +0 -31
- package/src/validate/identical.js +0 -20
- package/src/validate/main.js +0 -143
- package/src/validate/validations.js +0 -289
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
// Retrieve normalized property name
|
|
2
|
-
export const getPropName = function (keys) {
|
|
3
|
-
return keys.reduce(normalizeDynamicProp, '')
|
|
4
|
-
}
|
|
5
|
-
|
|
6
|
-
// Some properties are user-defined, i.e. we need to replace them with a "*" token
|
|
7
|
-
// Check if a property name is dynamic, such as `functions.{functionName}`, or
|
|
8
|
-
// is an array index.
|
|
9
|
-
// In those cases, we replace it by "*".
|
|
10
|
-
const normalizeDynamicProp = function (propName, key) {
|
|
11
|
-
const normalizedKey = Number.isInteger(key) || DYNAMIC_OBJECT_PROPS.has(propName) ? '*' : String(key)
|
|
12
|
-
return propName === '' ? normalizedKey : `${propName}.${normalizedKey}`
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
// Properties with dynamic children
|
|
16
|
-
const DYNAMIC_OBJECT_PROPS = new Set(['build.services', 'build.environment', 'functions', 'functions.*'])
|
package/src/mutations/update.js
DELETED
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
import { promises as fs } from 'fs'
|
|
2
|
-
|
|
3
|
-
import { pathExists } from 'path-exists'
|
|
4
|
-
|
|
5
|
-
import { ensureConfigPriority } from '../context.js'
|
|
6
|
-
import { addHeaders } from '../headers.js'
|
|
7
|
-
import { mergeConfigs } from '../merge.js'
|
|
8
|
-
import { parseOptionalConfig } from '../parse.js'
|
|
9
|
-
import { addRedirects } from '../redirects.js'
|
|
10
|
-
import { simplifyConfig } from '../simplify.js'
|
|
11
|
-
import { serializeToml } from '../utils/toml.js'
|
|
12
|
-
|
|
13
|
-
import { applyMutations } from './apply.js'
|
|
14
|
-
|
|
15
|
-
// Persist configuration changes to `netlify.toml`.
|
|
16
|
-
// If `netlify.toml` does not exist, creates it. Otherwise, merges the changes.
|
|
17
|
-
export const updateConfig = async function (
|
|
18
|
-
configMutations,
|
|
19
|
-
{ buildDir, configPath, headersPath, redirectsPath, context, branch, logs, featureFlags },
|
|
20
|
-
) {
|
|
21
|
-
if (configMutations.length === 0) {
|
|
22
|
-
return
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
const inlineConfig = applyMutations({}, configMutations)
|
|
26
|
-
const normalizedInlineConfig = ensureConfigPriority(inlineConfig, context, branch)
|
|
27
|
-
const updatedConfig = await mergeWithConfig(normalizedInlineConfig, configPath)
|
|
28
|
-
const configWithHeaders = await addHeaders({ config: updatedConfig, headersPath, logs, featureFlags })
|
|
29
|
-
const finalConfig = await addRedirects({ config: configWithHeaders, redirectsPath, logs, featureFlags })
|
|
30
|
-
const simplifiedConfig = simplifyConfig(finalConfig)
|
|
31
|
-
await backupConfig({ buildDir, configPath, headersPath, redirectsPath })
|
|
32
|
-
await Promise.all([
|
|
33
|
-
saveConfig(configPath, simplifiedConfig),
|
|
34
|
-
deleteSideFile(headersPath),
|
|
35
|
-
deleteSideFile(redirectsPath),
|
|
36
|
-
])
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
// If `netlify.toml` exists, deeply merges the configuration changes.
|
|
40
|
-
const mergeWithConfig = async function (normalizedInlineConfig, configPath) {
|
|
41
|
-
const config = await parseOptionalConfig(configPath)
|
|
42
|
-
const updatedConfig = mergeConfigs([config, normalizedInlineConfig])
|
|
43
|
-
return updatedConfig
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
// Serialize the changes to `netlify.toml`
|
|
47
|
-
const saveConfig = async function (configPath, simplifiedConfig) {
|
|
48
|
-
const serializedConfig = serializeToml(simplifiedConfig)
|
|
49
|
-
await fs.writeFile(configPath, serializedConfig)
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
// Deletes `_headers/_redirects` since they are merged to `netlify.toml`,
|
|
53
|
-
// to fix any priority problem.
|
|
54
|
-
const deleteSideFile = async function (filePath) {
|
|
55
|
-
if (filePath === undefined || !(await pathExists(filePath))) {
|
|
56
|
-
return
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
await fs.unlink(filePath)
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
// Modifications to `netlify.toml` and `_headers/_redirects` are only meant for
|
|
63
|
-
// the deploy API call. After it's been performed, we restore their former
|
|
64
|
-
// state.
|
|
65
|
-
// We do this by backing them up inside some sibling directory.
|
|
66
|
-
const backupConfig = async function ({ buildDir, configPath, headersPath, redirectsPath }) {
|
|
67
|
-
const tempDir = getTempDir(buildDir)
|
|
68
|
-
await fs.mkdir(tempDir, { recursive: true })
|
|
69
|
-
await Promise.all([
|
|
70
|
-
backupFile(configPath, `${tempDir}/netlify.toml`),
|
|
71
|
-
backupFile(headersPath, `${tempDir}/_headers`),
|
|
72
|
-
backupFile(redirectsPath, `${tempDir}/_redirects`),
|
|
73
|
-
])
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
export const restoreConfig = async function (configMutations, { buildDir, configPath, headersPath, redirectsPath }) {
|
|
77
|
-
if (configMutations.length === 0) {
|
|
78
|
-
return
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
const tempDir = getTempDir(buildDir)
|
|
82
|
-
await Promise.all([
|
|
83
|
-
copyOrDelete(`${tempDir}/netlify.toml`, configPath),
|
|
84
|
-
copyOrDelete(`${tempDir}/_headers`, headersPath),
|
|
85
|
-
copyOrDelete(`${tempDir}/_redirects`, redirectsPath),
|
|
86
|
-
])
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
const getTempDir = function (buildDir) {
|
|
90
|
-
return `${buildDir}/.netlify/deploy`
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
const backupFile = async function (original, backup) {
|
|
94
|
-
// this makes sure we don't restore stale files
|
|
95
|
-
await deleteNoError(backup)
|
|
96
|
-
|
|
97
|
-
if (!(await pathExists(original))) {
|
|
98
|
-
return
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
await fs.copyFile(original, backup)
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
const deleteNoError = async (path) => {
|
|
105
|
-
try {
|
|
106
|
-
await fs.unlink(path)
|
|
107
|
-
} catch {}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
const copyOrDelete = async function (src, dest) {
|
|
111
|
-
if (await pathExists(src)) {
|
|
112
|
-
await fs.copyFile(src, dest)
|
|
113
|
-
return
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
await deleteNoError(dest)
|
|
117
|
-
}
|
package/src/normalize.js
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import { normalizeFunctionsProps, WILDCARD_ALL } from './functions_config.js'
|
|
2
|
-
import { mergeConfigs } from './merge.js'
|
|
3
|
-
import { DEFAULT_ORIGIN } from './origin.js'
|
|
4
|
-
import { removeFalsy } from './utils/remove_falsy.js'
|
|
5
|
-
|
|
6
|
-
// Normalize configuration object
|
|
7
|
-
export const normalizeConfig = function (config) {
|
|
8
|
-
const configA = removeEmpty(config)
|
|
9
|
-
const { build, functions, plugins, ...configB } = mergeConfigs([DEFAULT_CONFIG, configA])
|
|
10
|
-
const { build: buildA, functions: functionsA, functionsDirectoryProps } = normalizeFunctionsProps(build, functions)
|
|
11
|
-
const pluginsA = plugins.map(normalizePlugin)
|
|
12
|
-
return { ...configB, build: buildA, functions: functionsA, plugins: pluginsA, ...functionsDirectoryProps }
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
// Remove empty strings.
|
|
16
|
-
// This notably ensures that empty strings in the build command are removed.
|
|
17
|
-
// Otherwise those would be run during builds, making the build fail.
|
|
18
|
-
const removeEmpty = function ({ build, ...config }) {
|
|
19
|
-
return removeFalsy({ ...config, build: removeFalsy(build) })
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
const DEFAULT_CONFIG = {
|
|
23
|
-
build: {
|
|
24
|
-
environment: {},
|
|
25
|
-
publish: '.',
|
|
26
|
-
publishOrigin: DEFAULT_ORIGIN,
|
|
27
|
-
processing: { css: {}, html: {}, images: {}, js: {} },
|
|
28
|
-
services: {},
|
|
29
|
-
},
|
|
30
|
-
functions: { [WILDCARD_ALL]: {} },
|
|
31
|
-
plugins: [],
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
const normalizePlugin = function ({ inputs = {}, ...plugin }) {
|
|
35
|
-
return removeFalsy({ ...plugin, inputs })
|
|
36
|
-
}
|
package/src/options/base.js
DELETED
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
import { promises as fs } from 'fs'
|
|
2
|
-
import { dirname, relative, sep } from 'path'
|
|
3
|
-
|
|
4
|
-
import { pathExists } from 'path-exists'
|
|
5
|
-
|
|
6
|
-
// Retrieve `base` override.
|
|
7
|
-
// This uses any directory below `repositoryRoot` and above (or equal to)
|
|
8
|
-
// `cwd` that has a `.netlify` or `netlify.toml`. This allows Netlify CLI users
|
|
9
|
-
// to `cd` into monorepo directories to change their base and build directories.
|
|
10
|
-
// Do all checks in parallel for speed
|
|
11
|
-
export const getBaseOverride = async function ({ repositoryRoot, cwd }) {
|
|
12
|
-
// Performance optimization
|
|
13
|
-
if (repositoryRoot === cwd) {
|
|
14
|
-
return {}
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
const [repositoryRootA, cwdA] = await Promise.all([fs.realpath(repositoryRoot), fs.realpath(cwd)])
|
|
18
|
-
const basePaths = getBasePaths(repositoryRootA, cwdA)
|
|
19
|
-
const basePath = await locatePath(basePaths)
|
|
20
|
-
|
|
21
|
-
if (basePath === undefined) {
|
|
22
|
-
return {}
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
// `base` starting with a `/` are relative to `repositoryRoot`, so we cannot
|
|
26
|
-
// return an absolute path
|
|
27
|
-
const base = relative(repositoryRoot, dirname(basePath))
|
|
28
|
-
// When `base` is explicitely overridden, `baseRelDir: true` makes more sense
|
|
29
|
-
// since we want `publish`, `functions` and `edge_functions` to be relative to it.
|
|
30
|
-
return { base, baseRelDir: true }
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
// Returns list of files to check for the existence of a `base`
|
|
34
|
-
const getBasePaths = function (repositoryRoot, cwd) {
|
|
35
|
-
const subdirs = getSubdirs(repositoryRoot, cwd)
|
|
36
|
-
const basePaths = subdirs.flatMap((subdir) => BASE_FILENAMES.map((filename) => `${subdir}/${filename}`))
|
|
37
|
-
return basePaths
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
// Retrieves list of directories between `repositoryRoot` and `cwd`, including
|
|
41
|
-
// `cwd` but excluding `repositoryRoot`
|
|
42
|
-
const getSubdirs = function (repositoryRoot, dir, subdirs = []) {
|
|
43
|
-
if (!dir.startsWith(`${repositoryRoot}${sep}`)) {
|
|
44
|
-
return subdirs
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
return getSubdirs(repositoryRoot, dirname(dir), [...subdirs, dir])
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
const BASE_FILENAMES = ['.netlify', 'netlify.toml', 'package.json']
|
|
51
|
-
|
|
52
|
-
// Returns the first path that exists.
|
|
53
|
-
// Like `locate-path` library but works with mixed files/directories
|
|
54
|
-
const locatePath = async function (paths) {
|
|
55
|
-
const results = await Promise.all(paths.map(returnIfExists))
|
|
56
|
-
const path = results.find(Boolean)
|
|
57
|
-
return path
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
const returnIfExists = async function (path) {
|
|
61
|
-
if (!(await pathExists(path))) {
|
|
62
|
-
return
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
return path
|
|
66
|
-
}
|
package/src/options/branch.js
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import { execaCommand } from 'execa'
|
|
2
|
-
|
|
3
|
-
// Find out git branch among (in priority order):
|
|
4
|
-
// - `branch` option
|
|
5
|
-
// - `BRANCH` environment variable
|
|
6
|
-
// - `HEAD` branch (using `git`)
|
|
7
|
-
// - `main` (using `git`)
|
|
8
|
-
// - 'master' (fallback)
|
|
9
|
-
export const getBranch = async function ({ branch, repositoryRoot }) {
|
|
10
|
-
if (branch) {
|
|
11
|
-
return branch
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
const headBranch = await getGitBranch(repositoryRoot, 'HEAD')
|
|
15
|
-
if (headBranch !== undefined) {
|
|
16
|
-
return headBranch
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
const mainBranch = await getGitBranch(repositoryRoot, 'main')
|
|
20
|
-
if (mainBranch !== undefined) {
|
|
21
|
-
return mainBranch
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
return FALLBACK_BRANCH
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
const getGitBranch = async function (repositoryRoot, gitRef) {
|
|
28
|
-
try {
|
|
29
|
-
const { stdout } = await execaCommand(`git rev-parse --abbrev-ref ${gitRef}`, { cwd: repositoryRoot })
|
|
30
|
-
return stdout
|
|
31
|
-
} catch {}
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
const FALLBACK_BRANCH = 'master'
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
// From CLI `--featureFlags=a,b,c` to programmatic `{ a: true, b: true, c: true }`
|
|
2
|
-
export const normalizeCliFeatureFlags = function (cliFeatureFlags) {
|
|
3
|
-
return Object.assign({}, ...cliFeatureFlags.split(',').filter(isNotEmpty).map(getFeatureFlag))
|
|
4
|
-
}
|
|
5
|
-
|
|
6
|
-
const isNotEmpty = function (name) {
|
|
7
|
-
return name.trim() !== ''
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
const getFeatureFlag = function (name) {
|
|
11
|
-
return { [name]: true }
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
// Default values for feature flags
|
|
15
|
-
export const DEFAULT_FEATURE_FLAGS = {}
|
package/src/options/main.js
DELETED
|
@@ -1,111 +0,0 @@
|
|
|
1
|
-
import { resolve } from 'path'
|
|
2
|
-
import process from 'process'
|
|
3
|
-
|
|
4
|
-
import { isDirectory } from 'path-type'
|
|
5
|
-
|
|
6
|
-
import { throwUserError } from '../error.js'
|
|
7
|
-
import { getBufferLogs } from '../log/logger.js'
|
|
8
|
-
import { logOpts } from '../log/main.js'
|
|
9
|
-
import { removeFalsy } from '../utils/remove_falsy.js'
|
|
10
|
-
|
|
11
|
-
import { getBaseOverride } from './base.js'
|
|
12
|
-
import { getBranch } from './branch.js'
|
|
13
|
-
import { DEFAULT_FEATURE_FLAGS } from './feature_flags.js'
|
|
14
|
-
import { getRepositoryRoot } from './repository_root.js'
|
|
15
|
-
|
|
16
|
-
// Assign default options
|
|
17
|
-
export const addDefaultOpts = function (opts = {}) {
|
|
18
|
-
const rawOpts = removeFalsy(opts)
|
|
19
|
-
|
|
20
|
-
const defaultOpts = getDefaultOpts(rawOpts)
|
|
21
|
-
const mergedOpts = {
|
|
22
|
-
...defaultOpts,
|
|
23
|
-
...rawOpts,
|
|
24
|
-
featureFlags: { ...defaultOpts.featureFlags, ...rawOpts.featureFlags },
|
|
25
|
-
}
|
|
26
|
-
const normalizedOpts = removeFalsy(mergedOpts)
|
|
27
|
-
|
|
28
|
-
const logs = getBufferLogs(normalizedOpts)
|
|
29
|
-
const normalizedOptsA = { ...normalizedOpts, logs }
|
|
30
|
-
|
|
31
|
-
logOpts(rawOpts, normalizedOptsA)
|
|
32
|
-
|
|
33
|
-
return normalizedOptsA
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
const getDefaultOpts = function ({ env: envOpt = {}, cwd: cwdOpt, defaultConfig = {} }) {
|
|
37
|
-
const combinedEnv = { ...process.env, ...envOpt }
|
|
38
|
-
return {
|
|
39
|
-
defaultConfig,
|
|
40
|
-
...getDefaultCwd(cwdOpt),
|
|
41
|
-
env: envOpt,
|
|
42
|
-
context: combinedEnv.CONTEXT || 'production',
|
|
43
|
-
branch: combinedEnv.BRANCH,
|
|
44
|
-
host: combinedEnv.NETLIFY_API_HOST,
|
|
45
|
-
token: combinedEnv.NETLIFY_AUTH_TOKEN,
|
|
46
|
-
siteId: combinedEnv.NETLIFY_SITE_ID,
|
|
47
|
-
deployId: combinedEnv.DEPLOY_ID || DEFAULT_DEPLOY_ID,
|
|
48
|
-
buildId: combinedEnv.BUILD_ID || DEFAULT_BUILD_ID,
|
|
49
|
-
mode: 'require',
|
|
50
|
-
offline: false,
|
|
51
|
-
debug: getDefaultDebug(combinedEnv, defaultConfig),
|
|
52
|
-
buffer: false,
|
|
53
|
-
featureFlags: DEFAULT_FEATURE_FLAGS,
|
|
54
|
-
inlineConfig: {},
|
|
55
|
-
configMutations: [],
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
// Local builds do not have any deploys, so some dummy ids are used instead
|
|
60
|
-
const DEFAULT_DEPLOY_ID = '0'
|
|
61
|
-
const DEFAULT_BUILD_ID = '0'
|
|
62
|
-
|
|
63
|
-
// --debug can be set using an environment variable `NETLIFY_BUILD_DEBUG` either
|
|
64
|
-
// locally or in the UI build settings
|
|
65
|
-
const getDefaultDebug = function (combinedEnv, { build: { environment = {} } = {} }) {
|
|
66
|
-
return Boolean(combinedEnv.NETLIFY_BUILD_DEBUG || environment.NETLIFY_BUILD_DEBUG)
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
// `process.cwd()` can throw, so only call it when needed
|
|
70
|
-
const getDefaultCwd = function (cwdOpt) {
|
|
71
|
-
if (cwdOpt !== undefined) {
|
|
72
|
-
return {}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
const cwd = process.cwd()
|
|
76
|
-
return { cwd }
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
// Normalize options
|
|
80
|
-
export const normalizeOpts = async function (opts) {
|
|
81
|
-
const repositoryRoot = await getRepositoryRoot(opts)
|
|
82
|
-
const optsA = { ...opts, repositoryRoot }
|
|
83
|
-
|
|
84
|
-
const branch = await getBranch(optsA)
|
|
85
|
-
const optsB = { ...optsA, branch }
|
|
86
|
-
|
|
87
|
-
const optsC = removeFalsy(optsB)
|
|
88
|
-
const optsD = await normalizeDirs(optsC)
|
|
89
|
-
|
|
90
|
-
const baseOverride = await getBaseOverride(optsD)
|
|
91
|
-
const optsE = { ...baseOverride, ...optsD }
|
|
92
|
-
return optsE
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
// Verify that options point to existing directories.
|
|
96
|
-
// Also resolve them to absolute file paths.
|
|
97
|
-
const normalizeDirs = async function (opts) {
|
|
98
|
-
const dirOpts = await Promise.all(DIR_OPTIONS.map((optName) => normalizeDir(opts, optName)))
|
|
99
|
-
return Object.assign({}, opts, ...dirOpts)
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
const DIR_OPTIONS = ['cwd', 'repositoryRoot']
|
|
103
|
-
|
|
104
|
-
const normalizeDir = async function (opts, optName) {
|
|
105
|
-
const path = opts[optName]
|
|
106
|
-
const resolvedPath = resolve(path)
|
|
107
|
-
if (!(await isDirectory(path))) {
|
|
108
|
-
throwUserError(`Option '${optName}' points to a non-existing directory: ${resolvedPath}`)
|
|
109
|
-
}
|
|
110
|
-
return { [optName]: resolvedPath }
|
|
111
|
-
}
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import { dirname } from 'path'
|
|
2
|
-
|
|
3
|
-
import { findUp } from 'find-up'
|
|
4
|
-
|
|
5
|
-
// Find out repository root among (in priority order):
|
|
6
|
-
// - `repositoryRoot` option
|
|
7
|
-
// - find a `.git` directory up from `cwd`
|
|
8
|
-
// - `cwd` (fallback)
|
|
9
|
-
export const getRepositoryRoot = async function ({ repositoryRoot, cwd }) {
|
|
10
|
-
if (repositoryRoot !== undefined) {
|
|
11
|
-
return repositoryRoot
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
const repositoryRootA = await findUp('.git', { cwd, type: 'directory' })
|
|
15
|
-
|
|
16
|
-
if (repositoryRootA === undefined) {
|
|
17
|
-
return cwd
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
return dirname(repositoryRootA)
|
|
21
|
-
}
|
package/src/origin.js
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import { isTruthy } from './utils/remove_falsy.js'
|
|
2
|
-
|
|
3
|
-
// `build.commandOrigin`, `build.publishOrigin` and `plugins[*].origin` constants
|
|
4
|
-
export const UI_ORIGIN = 'ui'
|
|
5
|
-
export const CONFIG_ORIGIN = 'config'
|
|
6
|
-
export const DEFAULT_ORIGIN = 'default'
|
|
7
|
-
export const INLINE_ORIGIN = 'inline'
|
|
8
|
-
|
|
9
|
-
// Add `build.commandOrigin`, `build.publishOrigin` and `plugins[*].origin`.
|
|
10
|
-
// This shows whether those properties came from the `ui` or from the `config`.
|
|
11
|
-
export const addOrigins = function (config, origin) {
|
|
12
|
-
const configA = addBuildCommandOrigin({ config, origin })
|
|
13
|
-
const configB = addBuildPublishOrigin({ config: configA, origin })
|
|
14
|
-
const configC = addConfigPluginOrigin({ config: configB, origin })
|
|
15
|
-
const configD = addHeadersOrigin({ config: configC, origin })
|
|
16
|
-
const configE = addRedirectsOrigin({ config: configD, origin })
|
|
17
|
-
return configE
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
const addBuildCommandOrigin = function ({ config, config: { build = {} }, origin }) {
|
|
21
|
-
return isTruthy(build.command) ? { ...config, build: { ...build, commandOrigin: origin } } : config
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
const addBuildPublishOrigin = function ({ config, config: { build = {} }, origin }) {
|
|
25
|
-
return isTruthy(build.publish) ? { ...config, build: { ...build, publishOrigin: origin } } : config
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
const addConfigPluginOrigin = function ({ config, config: { plugins }, origin }) {
|
|
29
|
-
return Array.isArray(plugins) ? { ...config, plugins: plugins.map((plugin) => ({ ...plugin, origin })) } : config
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
const addHeadersOrigin = function ({ config, config: { headers }, origin }) {
|
|
33
|
-
return isTruthy(headers) ? { ...config, headersOrigin: origin } : config
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
const addRedirectsOrigin = function ({ config, config: { redirects }, origin }) {
|
|
37
|
-
return isTruthy(redirects) ? { ...config, redirectsOrigin: origin } : config
|
|
38
|
-
}
|
package/src/parse.js
DELETED
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
import { promises as fs } from 'fs'
|
|
2
|
-
|
|
3
|
-
import { pathExists } from 'path-exists'
|
|
4
|
-
|
|
5
|
-
import { throwUserError } from './error.js'
|
|
6
|
-
import { throwOnInvalidTomlSequence } from './log/messages.js'
|
|
7
|
-
import { parseToml } from './utils/toml.js'
|
|
8
|
-
|
|
9
|
-
// Load the configuration file and parse it (TOML)
|
|
10
|
-
export const parseConfig = async function (configPath) {
|
|
11
|
-
if (configPath === undefined) {
|
|
12
|
-
return {}
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
if (!(await pathExists(configPath))) {
|
|
16
|
-
throwUserError('Configuration file does not exist')
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
return await readConfigPath(configPath)
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
// Same but `configPath` is required and `configPath` might point to a
|
|
23
|
-
// non-existing file.
|
|
24
|
-
export const parseOptionalConfig = async function (configPath) {
|
|
25
|
-
if (!(await pathExists(configPath))) {
|
|
26
|
-
return {}
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
return await readConfigPath(configPath)
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
const readConfigPath = async function (configPath) {
|
|
33
|
-
const configString = await readConfig(configPath)
|
|
34
|
-
|
|
35
|
-
validateTomlBlackslashes(configString)
|
|
36
|
-
|
|
37
|
-
try {
|
|
38
|
-
return parseToml(configString)
|
|
39
|
-
} catch (error) {
|
|
40
|
-
throwUserError('Could not parse configuration file', error)
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
// Reach the configuration file's raw content
|
|
45
|
-
const readConfig = async function (configPath) {
|
|
46
|
-
try {
|
|
47
|
-
return await fs.readFile(configPath, 'utf8')
|
|
48
|
-
} catch (error) {
|
|
49
|
-
throwUserError('Could not read configuration file', error)
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
const validateTomlBlackslashes = function (configString) {
|
|
54
|
-
const result = INVALID_TOML_BLACKSLASH.exec(configString)
|
|
55
|
-
if (result === null) {
|
|
56
|
-
return
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
const [, invalidTripleSequence, invalidSequence = invalidTripleSequence] = result
|
|
60
|
-
throwOnInvalidTomlSequence(invalidSequence)
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
// The TOML specification forbids unrecognized backslash sequences. However,
|
|
64
|
-
// `toml-node` does not respect the specification and do not fail on those.
|
|
65
|
-
// Therefore, we print a warning message.
|
|
66
|
-
// This only applies to " and """ strings, not ' nor '''
|
|
67
|
-
// Also, """ strings can use trailing backslashes.
|
|
68
|
-
const INVALID_TOML_BLACKSLASH =
|
|
69
|
-
/\n[a-zA-Z]+ *= *(?:(?:""".*(?<!\\)(\\[^"\\btnfruU\n]).*""")|(?:"(?!")[^\n]*(?<!\\)(\\[^"\\btnfruU])[^\n]*"))/su
|
package/src/path.js
DELETED
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import { resolve } from 'path'
|
|
2
|
-
|
|
3
|
-
import { findUp } from 'find-up'
|
|
4
|
-
import pLocate from 'p-locate'
|
|
5
|
-
import { pathExists } from 'path-exists'
|
|
6
|
-
|
|
7
|
-
// Configuration location can be:
|
|
8
|
-
// - a local path with the --config CLI flag
|
|
9
|
-
// - a `netlify.*` file in the `repositoryRoot/{base}`
|
|
10
|
-
// - a `netlify.*` file in the `repositoryRoot`
|
|
11
|
-
// - a `netlify.*` file in the current directory or any parent
|
|
12
|
-
export const getConfigPath = async function ({ configOpt, cwd, repositoryRoot, configBase }) {
|
|
13
|
-
const configPath = await pLocate(
|
|
14
|
-
[
|
|
15
|
-
searchConfigOpt(cwd, configOpt),
|
|
16
|
-
searchBaseConfigFile(repositoryRoot, configBase),
|
|
17
|
-
searchConfigFile(repositoryRoot),
|
|
18
|
-
findUp(FILENAME, { cwd }),
|
|
19
|
-
],
|
|
20
|
-
Boolean,
|
|
21
|
-
)
|
|
22
|
-
return configPath
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
// --config CLI flag
|
|
26
|
-
const searchConfigOpt = function (cwd, configOpt) {
|
|
27
|
-
if (configOpt === undefined) {
|
|
28
|
-
return
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
return resolve(cwd, configOpt)
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
// Look for `repositoryRoot/{base}/netlify.*`
|
|
35
|
-
const searchBaseConfigFile = function (repositoryRoot, configBase) {
|
|
36
|
-
if (configBase === undefined) {
|
|
37
|
-
return
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
return searchConfigFile(configBase)
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
// Look for several file extensions for `netlify.*`
|
|
44
|
-
const searchConfigFile = async function (cwd) {
|
|
45
|
-
const path = resolve(cwd, FILENAME)
|
|
46
|
-
if (!(await pathExists(path))) {
|
|
47
|
-
return
|
|
48
|
-
}
|
|
49
|
-
return path
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
const FILENAME = 'netlify.toml'
|
package/src/redirects.js
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import { resolve } from 'path'
|
|
2
|
-
|
|
3
|
-
import { parseAllRedirects } from 'netlify-redirect-parser'
|
|
4
|
-
|
|
5
|
-
import { warnRedirectsParsing } from './log/messages.js'
|
|
6
|
-
|
|
7
|
-
// Retrieve path to `_redirects` file (even if it does not exist yet)
|
|
8
|
-
export const getRedirectsPath = function ({ build: { publish } }) {
|
|
9
|
-
return resolve(publish, REDIRECTS_FILENAME)
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
const REDIRECTS_FILENAME = '_redirects'
|
|
13
|
-
|
|
14
|
-
// Add `config.redirects`
|
|
15
|
-
export const addRedirects = async function ({
|
|
16
|
-
config: { redirects: configRedirects, ...config },
|
|
17
|
-
redirectsPath,
|
|
18
|
-
logs,
|
|
19
|
-
featureFlags,
|
|
20
|
-
}) {
|
|
21
|
-
const { redirects, errors } = await parseAllRedirects({
|
|
22
|
-
redirectsFiles: [redirectsPath],
|
|
23
|
-
configRedirects,
|
|
24
|
-
minimal: true,
|
|
25
|
-
featureFlags,
|
|
26
|
-
})
|
|
27
|
-
warnRedirectsParsing(logs, errors)
|
|
28
|
-
return { ...config, redirects }
|
|
29
|
-
}
|