UNPKG

3.43 kBJavaScriptView Raw
1'use strict'
2
3const isPlainObj = require('is-plain-obj')
4const mapObj = require('map-obj')
5
6const { mergeConfigs } = require('./merge')
7const { normalizeBeforeConfigMerge } = require('./merge_normalize')
8const { validateContextsPluginsConfig } = require('./validate/context')
9const { validatePreContextConfig } = require('./validate/main')
10
11// Validate and normalize `config.context.*`
12const normalizeContextProps = function ({ config, config: { context: contextProps }, origin }) {
13 if (contextProps === undefined) {
14 return config
15 }
16
17 validatePreContextConfig(config)
18
19 const allContextProps = mapObj(contextProps, (key, contextConfig) => [key, addNamespace(contextConfig)])
20 const normalizedContextProps = mapObj(allContextProps, (key, contextConfig) => [
21 key,
22 normalizeBeforeConfigMerge(contextConfig, origin),
23 ])
24 return { ...config, context: normalizedContextProps }
25}
26
27// Merge `config.context.{CONTEXT|BRANCH}.*` to `config.build.*` or `config.*`
28// CONTEXT is the `--context` CLI flag.
29// BRANCH is the `--branch` CLI flag.
30const mergeContext = function ({
31 config: { context: contextProps, ...config },
32 config: { plugins },
33 context,
34 branch,
35 logs,
36}) {
37 if (contextProps === undefined) {
38 return config
39 }
40
41 const contexts = [context, branch]
42 validateContextsPluginsConfig({ contextProps, plugins, contexts, logs })
43 const filteredContextProps = contexts.map((key) => contextProps[key]).filter(Boolean)
44 return mergeConfigs([config, ...filteredContextProps])
45}
46
47// `config.context.{context}.*` properties are merged either to `config.*` or
48// to `config.build.*`. We distinguish between both by checking the property
49// name.
50const addNamespace = (contextConfig) => Object.entries(contextConfig).reduce(addNamespacedProperty, {})
51
52const addNamespacedProperty = function (contextConfig, [key, value]) {
53 return isBuildProperty(key, value)
54 ? { ...contextConfig, build: { ...contextConfig.build, [key]: value } }
55 : { ...contextConfig, [key]: value }
56}
57
58const isBuildProperty = function (key, value) {
59 return BUILD_PROPERTIES.has(key) && !isFunctionsConfig(key, value) && !isEdgeHandlersConfig(key, value)
60}
61
62// All properties in `config.build.*`
63const BUILD_PROPERTIES = new Set([
64 'base',
65 'command',
66 'edge_handlers',
67 'environment',
68 'functions',
69 'ignore',
70 'processing',
71 'publish',
72])
73
74// `config.functions` is a plain object while `config.build.functions` is a
75// string.
76const isFunctionsConfig = function (key, value) {
77 return key === 'functions' && isPlainObj(value)
78}
79
80// `config.edge_handlers` is an array of objects while
81// `config.build.edge_handlers` is a string.
82const isEdgeHandlersConfig = function (key, value) {
83 return key === 'edge_handlers' && Array.isArray(value)
84}
85
86// Ensure that `inlineConfig` has higher priority than context properties by
87// assigining it to `context.*`. Still keep it at the top-level as well since
88// some properties are not handled context-sensitively by the API.
89// Takes into account that `context.{context}.build.*` is the same as
90// `context.{context}.*`
91const ensureConfigPriority = function ({ build = {}, ...config }, context, branch) {
92 return {
93 ...config,
94 build,
95 context: {
96 ...config.context,
97 [context]: { ...config, ...build, build },
98 [branch]: { ...config, ...build, build },
99 },
100 }
101}
102
103module.exports = { normalizeContextProps, mergeContext, ensureConfigPriority }