@backland/schema
Version:
TypeScript schema declaration and validation library with static type inference
152 lines (149 loc) • 9.42 kB
JavaScript
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