UNPKG

@backland/schema

Version:

TypeScript schema declaration and validation library with static type inference

177 lines (176 loc) 6.51 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.VariableType = exports.EnumType = void 0; exports.buildArgs = buildArgs; exports.configFields = void 0; exports.objectToQuery = objectToQuery; exports.stringifyArgs = stringifyArgs; class EnumType { constructor(value) { this.value = value; } } exports.EnumType = EnumType; class VariableType { constructor(value) { this.value = value; } toJSON() { return `$${this.value}`; } } exports.VariableType = VariableType; const configFields = ['__args', '__alias', '__aliasFor', '__variables', '__directives', '__on', '__all_on', '__typeName', '__name']; exports.configFields = configFields; function stringifyArgs(obj_from_json) { if (obj_from_json instanceof EnumType) { return obj_from_json.value; } // variables should be prefixed with dollar sign and not quoted else if (obj_from_json instanceof VariableType) { return `$${obj_from_json.value}`; } // Cheers to Derek: https://stackoverflow.com/questions/11233498/json-stringify-without-quotes-on-properties else if (typeof obj_from_json !== 'object' || obj_from_json === null) { // not an object, stringify using native function return JSON.stringify(obj_from_json); } else if (Array.isArray(obj_from_json)) { return `[${obj_from_json.map(item => stringifyArgs(item)).join(', ')}]`; } // Implements recursive object serialization according to JSON spec // but without quotes around the keys. const props = Object.keys(obj_from_json).map(key => `${key}: ${stringifyArgs(obj_from_json[key])}`).join(', '); return `{${props}}`; } function buildArgs(argsObj) { const args = []; for (const argName in argsObj) { args.push(`${argName}: ${stringifyArgs(argsObj[argName])}`); } return args.join(', '); } function buildVariables(varsObj) { const args = []; for (const varName in varsObj) { args.push(`$${varName}: ${varsObj[varName]}`); } return args.join(', '); } function buildDirectives(dirsObj) { const directiveName = Object.keys(dirsObj)[0]; const directiveValue = dirsObj[directiveName]; if (typeof directiveValue === 'boolean' || typeof directiveValue === 'object' && Object.keys(directiveValue).length === 0) { return directiveName; } else if (typeof directiveValue === 'object') { const args = []; for (const argName in directiveValue) { const argVal = stringifyArgs(directiveValue[argName]).replace(/"/g, ''); args.push(`${argName}: ${argVal}`); } return `${directiveName}(${args.join(', ')})`; } else { throw new Error(`Unsupported type for directive: ${typeof directiveValue}. Types allowed: object, boolean.\n` + `Offending object: ${JSON.stringify(dirsObj)}`); } } function getIndent(level) { return Array(level * 2 + 1).join(' '); } function filterNonConfigFields(fieldName, ignoreFields) { // Returns true if fieldName is not a 'configField'. return configFields.indexOf(fieldName) == -1 && ignoreFields.indexOf(fieldName) == -1; } function convertQuery(node, level, output, options) { Object.keys(node).filter(key => filterNonConfigFields(key, options.ignoreFields)).forEach(key => { let value = node[key]; if (typeof value === 'object') { if (Array.isArray(value)) { value = value.find(item => item && typeof item === 'object'); if (!value) { output.push([`${key}`, level]); return; } } const fieldCount = Object.keys(value).filter(keyCount => filterNonConfigFields(keyCount, options.ignoreFields)).length; const subFields = fieldCount > 0; const argsExist = typeof value.__args === 'object' && Object.keys(value.__args).length > 0; const directivesExist = typeof value.__directives === 'object'; const fullFragmentsExist = value.__all_on instanceof Array; const partialFragmentsExist = typeof value.__on === 'object'; let token = `${key}`; if (typeof value.__name === 'string') { token = `${token} ${value.__name}`; } if (typeof value.__aliasFor === 'string') { token = `${token}: ${value.__aliasFor}`; } if (typeof value.__variables === 'object' && Object.keys(value.__variables).length > 0) { token = `${token} (${buildVariables(value.__variables)})`; } else if (argsExist || directivesExist) { let argsStr = ''; let dirsStr = ''; if (directivesExist) { dirsStr = Object.entries(value.__directives).map(item => `@${buildDirectives({ [item[0]]: item[1] })}`).join(' '); } if (argsExist) { argsStr = `(${buildArgs(value.__args)})`; } const spacer = directivesExist && argsExist ? ' ' : ''; token = `${token} ${argsStr}${spacer}${dirsStr}`; } output.push([token + (subFields || partialFragmentsExist || fullFragmentsExist ? ' {' : ''), level]); convertQuery(value, level + 1, output, options); if (fullFragmentsExist) { value.__all_on.forEach(fullFragment => { output.push([`...${fullFragment}`, level + 1]); }); } if (partialFragmentsExist) { const inlineFragments = value.__on instanceof Array ? value.__on : [value.__on]; inlineFragments.forEach(inlineFragment => { const name = inlineFragment.__typeName; output.push([`... on ${name} {`, level + 1]); convertQuery(inlineFragment, level + 2, output, options); output.push(['}', level + 1]); }); } if (subFields || partialFragmentsExist || fullFragmentsExist) { output.push(['}', level]); } } else if (options.includeFalsyKeys === true || value) { output.push([`${key}`, level]); } }); } function objectToQuery(query, options = {}) { if (!query || typeof query != 'object') { throw new Error('query object not specified'); } if (Object.keys(query).length == 0) { throw new Error('query object has no data'); } if (!(options.ignoreFields instanceof Array)) { options.ignoreFields = []; } const queryLines = []; convertQuery(query, 0, queryLines, options); let output = ''; queryLines.forEach(([line, level]) => { if (options.pretty) { if (output) { output += '\n'; } output += getIndent(level) + line; } else { if (output) { output += ' '; } output += line; } }); return output; } //# sourceMappingURL=objectToQuery.js.map