UNPKG

@graphql-tools/prisma-loader

Version:

A set of utils for faster development of GraphQL tools

216 lines (215 loc) • 10.5 kB
"use strict"; 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'; }