@graphql-tools/prisma-loader
Version:
A set of utils for faster development of GraphQL tools
216 lines (215 loc) • 10.5 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.Variables = void 0;
const tslib_1 = require("tslib");
const lodash_1 = tslib_1.__importDefault(require("lodash"));
const Output_js_1 = require("./Output.js");
class Variables {
constructor(fileName, options = {}, out = new Output_js_1.Output(), envVars) {
this.overwriteSyntax = /,/g;
this.envRefSyntax = /^env:/g;
this.selfRefSyntax = /^self:/g;
this.stringRefSyntax = /('.*')|(".*")/g;
this.optRefSyntax = /^opt:/g;
// eslint-disable-next-line
this.variableSyntax = new RegExp(
// eslint-disable-next-line
'\\${([ ~:a-zA-Z0-9._\'",\\-\\/\\(\\)]+?)}', 'g');
this.out = out;
this.fileName = fileName;
this.options = options;
this.envVars = envVars || process.env;
}
populateJson(json) {
this.json = json;
return this.populateObject(this.json).then(() => {
return Promise.resolve(this.json);
});
}
populateObject(objectToPopulate) {
const populateAll = [];
const deepMapValues = (object, callback, propertyPath) => {
const deepMapValuesIteratee = (value, key) => deepMapValues(value, callback, propertyPath ? propertyPath.concat(key) : [key]);
if (lodash_1.default.isArray(object)) {
return lodash_1.default.map(object, deepMapValuesIteratee);
}
else if (lodash_1.default.isObject(object) && !lodash_1.default.isDate(object) && !lodash_1.default.isFunction(object)) {
return lodash_1.default.extend({}, object, lodash_1.default.mapValues(object, deepMapValuesIteratee));
}
return callback(object, propertyPath);
};
deepMapValues(objectToPopulate, (property, propertyPath) => {
if (typeof property === 'string') {
const populateSingleProperty = this.populateProperty(property, true).then((newProperty) => lodash_1.default.set(objectToPopulate, propertyPath, newProperty));
populateAll.push(populateSingleProperty);
}
});
return Promise.all(populateAll).then(() => objectToPopulate);
}
populateProperty(propertyParam, populateInPlace) {
let property = populateInPlace ? propertyParam : lodash_1.default.cloneDeep(propertyParam);
const allValuesToPopulate = [];
let warned = false;
if (typeof property === 'string' && property.match(this.variableSyntax)) {
const matchedStrings = property.match(this.variableSyntax);
if (matchedStrings) {
for (const matchedString of matchedStrings) {
const variableString = matchedString
.replace(this.variableSyntax, (_, varName) => varName.trim())
.replace(/\s/g, '');
let singleValueToPopulate = null;
if (variableString.match(this.overwriteSyntax)) {
singleValueToPopulate = this.overwrite(variableString);
}
else {
singleValueToPopulate = this.getValueFromSource(variableString).then((valueToPopulate) => {
if (typeof valueToPopulate === 'object') {
return this.populateObject(valueToPopulate);
}
return valueToPopulate;
});
}
singleValueToPopulate = singleValueToPopulate.then(valueToPopulate => {
if (this.warnIfNotFound(variableString, valueToPopulate)) {
warned = true;
}
return this.populateVariable(property, matchedString, valueToPopulate).then((newProperty) => {
property = newProperty;
return Promise.resolve(property);
});
});
allValuesToPopulate.push(singleValueToPopulate);
}
}
return Promise.all(allValuesToPopulate).then(() => {
if (property !== this.json && !warned) {
return this.populateProperty(property);
}
return Promise.resolve(property);
});
}
return Promise.resolve(property);
}
populateVariable(propertyParam, matchedString, valueToPopulate) {
let property = propertyParam;
if (typeof valueToPopulate === 'string') {
// TODO: Replace `split` and `join` with `replaceAll` once Node v14 is no longer supported
property = property.split(matchedString).join(valueToPopulate);
}
else {
if (property !== matchedString) {
if (typeof valueToPopulate === 'number') {
// TODO: Replace `split` and `join` with `replaceAll` once Node v14 is no longer supported
property = property.split(matchedString).join(String(valueToPopulate));
}
else {
const errorMessage = [
'Trying to populate non string value into',
` a string for variable ${matchedString}.`,
' Please make sure the value of the property is a string.',
].join('');
this.out.warn(this.out.getErrorPrefix(this.fileName, 'warning') + errorMessage);
}
return Promise.resolve(property);
}
property = valueToPopulate;
}
return Promise.resolve(property);
}
overwrite(variableStringsString) {
let finalValue;
const variableStringsArray = variableStringsString.split(',');
const allValuesFromSource = variableStringsArray.map((variableString) => this.getValueFromSource(variableString));
return Promise.all(allValuesFromSource).then((valuesFromSources) => {
valuesFromSources.find((valueFromSource) => {
finalValue = valueFromSource;
return (finalValue !== null &&
typeof finalValue !== 'undefined' &&
!(typeof finalValue === 'object' && lodash_1.default.isEmpty(finalValue)));
});
return Promise.resolve(finalValue);
});
}
getValueFromSource(variableString) {
if (variableString.match(this.envRefSyntax)) {
return this.getValueFromEnv(variableString);
}
else if (variableString.match(this.optRefSyntax)) {
return this.getValueFromOptions(variableString);
}
else if (variableString.match(this.selfRefSyntax)) {
return this.getValueFromSelf(variableString);
}
else if (variableString.match(this.stringRefSyntax)) {
return this.getValueFromString(variableString);
}
const errorMessage = [
`Invalid variable reference syntax for variable ${variableString}.`,
' You can only reference env vars, options, & files.',
' You can check our docs for more info.',
].join('');
this.out.warn(this.out.getErrorPrefix(this.fileName, 'warning') + errorMessage);
return Promise.resolve();
}
getValueFromEnv(variableString) {
const requestedEnvVar = variableString.split(':')[1];
const valueToPopulate = requestedEnvVar !== '' || '' in this.envVars ? this.envVars[requestedEnvVar] : this.envVars;
return Promise.resolve(valueToPopulate);
}
getValueFromString(variableString) {
const valueToPopulate = variableString.replace(/^['"]|['"]$/g, '');
return Promise.resolve(valueToPopulate);
}
getValueFromOptions(variableString) {
const requestedOption = variableString.split(':')[1];
const valueToPopulate = requestedOption !== '' || '' in this.options ? this.options[requestedOption] : this.options;
return Promise.resolve(valueToPopulate);
}
getValueFromSelf(variableString) {
const valueToPopulate = this.json;
const deepProperties = variableString.split(':')[1].split('.');
return this.getDeepValue(deepProperties, valueToPopulate);
}
getDeepValue(deepProperties, valueToPopulate) {
return promiseReduce(deepProperties, (computedValueToPopulateParam, subProperty) => {
let computedValueToPopulate = computedValueToPopulateParam;
if (typeof computedValueToPopulate === 'undefined') {
computedValueToPopulate = {};
}
else if (subProperty !== '' || '' in computedValueToPopulate) {
computedValueToPopulate = computedValueToPopulate[subProperty];
}
if (typeof computedValueToPopulate === 'string' && computedValueToPopulate.match(this.variableSyntax)) {
return this.populateProperty(computedValueToPopulate);
}
return Promise.resolve(computedValueToPopulate);
}, valueToPopulate);
}
warnIfNotFound(variableString, valueToPopulate) {
if (valueToPopulate === null ||
typeof valueToPopulate === 'undefined' ||
(typeof valueToPopulate === 'object' && lodash_1.default.isEmpty(valueToPopulate))) {
let varType;
if (variableString.match(this.envRefSyntax)) {
varType = 'environment variable';
}
else if (variableString.match(this.optRefSyntax)) {
varType = 'option';
}
else if (variableString.match(this.selfRefSyntax)) {
varType = 'self reference';
}
this.out.warn(this.out.getErrorPrefix(this.fileName, 'warning') +
`A valid ${varType} to satisfy the declaration '${variableString}' could not be found.`);
return true;
}
return false;
}
}
exports.Variables = Variables;
function promiseReduce(values, callback, initialValue) {
return values.reduce((previous, value) => isPromise(previous) ? previous.then(resolved => callback(resolved, value)) : callback(previous, value), initialValue);
}
function isPromise(value) {
return typeof (value === null || value === void 0 ? void 0 : value.then) === 'function';
}
;