UNPKG

@backland/schema

Version:

TypeScript schema declaration and validation library with static type inference

152 lines (149 loc) 9.42 kB
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; } function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); } function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); } function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } } function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; } import * as fs from 'fs-extra'; import { CircularDeps } from '../CircularDeps'; import { parseFieldDefinitionConfig } from '../ObjectType'; import { resolversTypescriptParts } from '../createGraphQLSchema'; import { getSchemaQueryTemplates } from './getQueryTemplates'; export function generateClientUtils(_x, _x2) { return _generateClientUtils.apply(this, arguments); } function _generateClientUtils() { _generateClientUtils = _asyncToGenerator(function* (schema, options) { var [tsParts, queryTemplates] = yield Promise.all([resolversTypescriptParts({ name: 'GraphQLInterfaces', options: {}, resolvers: schema.utils.resolvers }), getSchemaQueryTemplates(schema, options)]); var header = ['// Autogenerated, do not edit by hand', '/* istanbul ignore file */', '/* eslint-disable */', // "import { GraphType } from '@backland/schema';\n\n", '\nexport type GraphQLClientError = { message: string, path: string[] };\n', // '\nexport type ID = number | string;\n', // "\nexport type GraphQLClientResponse<Result> = {data: Result, errors: null} | {data: null, errors: GraphQLClientError[]}\n"]; var clientInterface = ""; clientInterface += "\nexport interface ExpectedGraphQLClient {\n"; var helpersText = "\n\n"; helpersText += "\nexport const graphqlClientHelpers = {\n"; var commonTypings = new Map(); // adding the input (args) and payload types for each resolver tsParts.lines.forEach(_ref => { var { payloadName, args, payload, inputName } = _ref; commonTypings.set(payloadName, "export type ".concat(payloadName, " = ").concat(payload.code)); commonTypings.set(inputName, "export type ".concat(inputName, " = ").concat(args.code)); }); // adding the GraphqlClient interface for each resolver tsParts.lines.forEach(_ref2 => { var { payloadName, inputName, resolver: { description, deprecationReason, name, args: resolverArgs } } = _ref2; clientInterface += description ? "/**\n".concat(description, "\n**/") : ''; clientInterface += deprecationReason ? "/**\n@deprecated\n".concat(deprecationReason, "\n**/") : ''; var argsText = resolverArgs ? "args: ".concat(inputName) : "args?: ".concat(inputName); clientInterface += "\n".concat(name, ": {").concat(argsText, ", payload: GraphQLClientResponse<").concat(payloadName, ">},"); clientInterface += "\n"; }); // adding the query and fragment texts for each resolver tsParts.lines.forEach(_ref3 => { var { payloadName, inputName, resolver: { name, typeDef, kind, argsDef } } = _ref3; helpersText += "\n".concat(name, ": {\n name: \"").concat(name, "\", \n"); helpersText += "kind: '".concat(kind, "',payload: ").concat(rehydrateType(payloadName, typeDef), ",\n"); helpersText += "\ninput: ".concat(rehydrateType(inputName, argsDef ? { object: argsDef } : { record: { keyType: 'string', type: 'unknown' } }), ",\n"); var resolverQueries = queryTemplates.queryByResolver[kind][name]; helpersText += "\noperation: ".concat(JSON.stringify({ query: resolverQueries.fullQuery, varNames: resolverQueries.argsParsed.vars.reduce((acc, next) => { return _objectSpread(_objectSpread({}, acc), {}, { [next.name]: _objectSpread(_objectSpread({}, next), {}, { // example -> "limit": "cashbackIntervals_limit" varName: next.varName.replace(/^\$/, '') }) }); }, {}) }, null, 2), " as const,\n"); helpersText += "\n},\n"; }); clientInterface += "\n}\n"; helpersText += "\n} as const;\n"; helpersText += genClientBody(); var result = [header.join('\n\n'), // [...commonTypings.values()].join('\n\n'), clientInterface, helpersText].join('\n'); return CircularDeps.prettier.format(result, { parser: 'typescript', singleQuote: true }); }); return _generateClientUtils.apply(this, arguments); } var creating = false; export function saveGraphQLClientUtils(_x3, _x4) { return _saveGraphQLClientUtils.apply(this, arguments); } function _saveGraphQLClientUtils() { _saveGraphQLClientUtils = _asyncToGenerator(function* (schema, DEST) { if (creating) return; creating = true; var exists = fs.existsSync(DEST); var now = Date.now(); var mtime = exists ? fs.statSync(DEST).mtimeMs : 0; var diff = now - mtime; if (diff < 3000) return; console.info("saveGraphQLTypescript in progress."); var ts = yield generateClientUtils(schema); if (exists) { yield fs.remove(DEST); } yield fs.ensureFile(DEST); yield fs.writeFile(DEST, ts); creating = false; console.info("generated in ".concat(DEST)); }); return _saveGraphQLClientUtils.apply(this, arguments); } function rehydrateType(name, field) { var parsed = parseFieldDefinitionConfig(field, { deep: { omitMeta: true } }); var json = JSON.stringify(parsed); return "GraphType.getOrSet(\"".concat(name, "\", ").concat(json, " as const)"); } function genClientBody() { return ['', 'export type GraphqlClientHelpers = typeof graphqlClientHelpers;', 'export type GraphQLEntry = GraphqlClientHelpers[keyof GraphqlClientHelpers];', '', "export type GraphQLFetchParams<K extends GraphQLEntry['name']> = {", ' operationInfo: GraphqlClientHelpers[K];', ' operationName: K;', " getBody: (args: ExpectedGraphQLClient[K]['args']) => {", ' query: string;', ' variables: Record<string, any>;', ' operationName: K;', ' };', " parseArgs: (args: ExpectedGraphQLClient[K]['args']) => Record<string, any>;", " mountBodyString(args: ExpectedGraphQLClient[K]['args']): string;", '};', '', "export function getGraphQLFetchHelpers<MethodName extends GraphQLEntry['name']>(", ' methodName: MethodName,', '): GraphQLFetchParams<MethodName> {', ' const helpers = graphqlClientHelpers[methodName];', '', ' function parseArgs(args: any) {', ' const vars: Record<string, any> = {};', ' const parsedArgs: any = helpers.input.parse(args || {}, (_, error) => {', ' return `\\nGraphQLClientArgumentsError: method ${methodName}: \\n${error.message}`;', ' });', '', ' Object.entries(helpers.operation.varNames).forEach(([inputVarName, { varName }]) => {', ' vars[varName] = parsedArgs[inputVarName];', ' });', '', ' return vars;', ' }', '', ' function getBody(args: any) {', ' const variables = parseArgs(args);', ' return {', ' query: helpers.operation.query,', ' variables,', ' operationName: methodName,', ' };', ' }', '', ' function mountBodyString(args: any) {', ' const body = getBody(args);', ' return JSON.stringify(body);', ' }', '', ' return {', ' operationInfo: helpers,', ' operationName: methodName,', ' parseArgs,', ' getBody,', ' mountBodyString,', ' };', '}', ''].join('\n'); } //# sourceMappingURL=generateClientUtils.js.map