@netlify/build
Version:
Netlify build module
63 lines (62 loc) • 2.86 kB
JavaScript
import { promises as fs } from 'fs';
import { resolve } from 'path';
import isPlainObject from 'is-plain-obj';
import mapObject, { mapObjectSkip } from 'map-obj';
import { FRAMEWORKS_API_CONFIG_ENDPOINT } from '../../utils/frameworks_api.js';
export const loadConfigFile = async (buildDir, packagePath) => {
const configPath = resolve(buildDir, packagePath ?? '', FRAMEWORKS_API_CONFIG_ENDPOINT);
try {
const data = await fs.readFile(configPath, 'utf8');
return JSON.parse(data);
}
catch (err) {
// If the file doesn't exist, this is a non-error.
if (err.code !== 'ENOENT') {
throw err;
}
}
// The first version of this API was called "Deploy Configuration API" and it
// had `.netlify/deploy` as its base directory. For backwards-compatibility,
// we need to support that path for the config file.
const legacyConfigPath = resolve(buildDir, packagePath ?? '', '.netlify/deploy/v1/config.json');
try {
const data = await fs.readFile(legacyConfigPath, 'utf8');
return JSON.parse(data);
}
catch (err) {
// If the file doesn't exist, this is a non-error.
if (err.code !== 'ENOENT') {
throw err;
}
}
};
/**
* Checks whether a property matches a template that may contain wildcards.
* Both the property and the template use a dot-notation represented as an
* array of strings.
* For example, the property `["build", "command"]` matches the templates
* `["build", "command"]` and `["build", "*"]`, but not `["functions"]`.
*/
const propertyMatchesTemplate = (property, template) => property.every((node, index) => template[index] === node || template[index] === '*');
/**
* Checks whether a property can be defined using the Deploy Configuration API.
*/
export const isAllowedProperty = (property, allowedProperties) => allowedProperties.some((template) => propertyMatchesTemplate(property, template));
/**
* Takes a candidate configuration object and returns a normalized version that
* includes only the properties that are present in an allow-list. It does so
* recursively, so `allowedProperties` can contain the full list of properties
* that the Deploy Configuration API can interact with.
*/
export const filterConfig = (obj, path, allowedProperties, systemLog) => mapObject(obj, (key, value) => {
const keyPath = [...path, key];
if (!isAllowedProperty(keyPath, allowedProperties)) {
systemLog(`Discarding property that is not supported by the Deploy Configuration API: ${keyPath.join('.')}`);
return mapObjectSkip;
}
if (!isPlainObject(value)) {
systemLog(`Loading property from Deploy Configuration API: ${keyPath.join('.')}`);
return [key, value];
}
return [key, filterConfig(value, keyPath, allowedProperties, systemLog)];
});