@backland/schema
Version:
TypeScript schema declaration and validation library with static type inference
235 lines (204 loc) • 7.68 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.defaultTypesDest = exports.BacklandWatchTypesPubSub = void 0;
exports.writeTypes = writeTypes;
var _path = _interopRequireDefault(require("path"));
var _utils = require("@backland/utils");
var _fsExtra = require("fs-extra");
var _CircularDeps = require("../CircularDeps");
var _LiteralField = require("../fields/LiteralField");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
const {
serialize
} = _LiteralField.LiteralField.utils;
const BacklandWatchTypesPubSub = (0, _utils.mitt)();
exports.BacklandWatchTypesPubSub = BacklandWatchTypesPubSub;
const typesRecord = {};
const resolversRecord = {};
const customTypeRecord = {};
// APLICAR AOS RESOLVERS DA ENTITY, etc
BacklandWatchTypesPubSub.on('created', async event => {
var _event$graphType;
if ((_event$graphType = event.graphType) !== null && _event$graphType !== void 0 && _event$graphType.optionalId) {
typesRecord[`${event.graphType.id}`] = event.graphType;
}
if (event.resolver) {
resolversRecord[`${event.resolver.name}`] = event.resolver;
}
if (event.custom) {
customTypeRecord[event.custom.name] = event.custom;
}
save();
});
const defaultTypesDest = _path.default.resolve(_utils.Process.cwd(), 'src/generated/backland.d.ts');
exports.defaultTypesDest = defaultTypesDest;
async function writeTypes(options) {
const {
dest = defaultTypesDest
} = options || {};
(0, _fsExtra.ensureFileSync)(dest);
const creators = Object.keys(typesRecord).map(name => {
let txt = '';
const fn = [`function createType<Definition extends ObjectFieldInput>(name: "${name}",`, `definition: Definition):`, `GraphTypeRuntime<Definition,`, `RuntimeTypes["${name}"], "${name}">`, '\n'].join(' ');
const getTypeFn = [`function getType(name: "${name}"): GraphTypeRuntime<RuntimeDefinitions["${name}"], RuntimeTypes["${name}"], "${name}">`].join(' ');
txt += `\n export ${fn};\n`;
txt += `\n export ${getTypeFn};\n`;
txt += `\n export const Backland = { createType, getType };\n`;
return txt;
});
const resolvers = Object.keys(resolversRecord).map(name => {
let txt = '';
const fn = [`function createResolver<Context, Source>(`, `options: ResolverRuntimeConfig<Context, Source, RuntimeTypes["${name}Payload"], RuntimeTypes["${name}Input"], "${name}">`, `): ResolverRuntime<Context, Source, RuntimeTypes["${name}Payload"], RuntimeTypes["${name}Input"], "${name}">`].join(' ');
const getTypeFn = [`function getResolver(name: "${name}"): ResolverRuntime<Context, Source, RuntimeTypes["${name}Payload"], RuntimeTypes["${name}Input"], "${name}">`].join(' ');
txt += `\n export ${fn};\n`;
txt += `\n export ${getTypeFn};\n`;
txt += `\n export const Backland = { createResolver, getResolver };\n`;
return txt;
});
const head = [];
const body = [];
const footer = [];
Object.values(customTypeRecord).forEach(item => {
item.head && head.push(...item.head);
item.body && head.push(...item.body);
item.footer && head.push(...item.footer);
});
const typesInterface = await _CircularDeps.CircularDeps.objectToTypescript('RuntimeTypes', typesRecord);
let definitions = Object.entries(typesRecord).reduce((acc, [id, next]) => {
acc += `\n"${id}": ${serialize(next.definition)}\n;`;
return acc;
}, '');
definitions = `export interface RuntimeDefinitions {\n${definitions}\n}`;
let content = template({
creators,
definitions,
extraCustomBody: body,
extraCustomFooter: footer,
extraCustomHead: head,
resolvers,
typesInterface
});
content = await _CircularDeps.CircularDeps.prettier.format(content, {
parser: 'typescript',
singleQuote: true
});
(0, _fsExtra.writeFileSync)(dest, content);
}
function template({
typesInterface,
creators,
resolvers,
definitions,
extraCustomHead,
extraCustomBody,
extraCustomFooter
}) {
return `
/* tslint-disable */
/* tslint:disable */
/* eslint-disable */
declare global {
module '@backland/schema' {
export * from '@backland/schema';
import { ObjectFieldInput, ValidationCustomMessage, FieldDefinitionConfig } from '@backland/schema';
import { Merge } from '@backland/utils';
import {
GraphQLField,
GraphQLFieldConfig,
GraphQLResolveInfo,
} from 'graphql';
${extraCustomHead.join('\n')}
export class GraphTypeRuntime<Definition extends FieldDefinitionConfig, Type, Name> {
static __isGraphType: true;
readonly __isGraphType: true;
static reset(): Promise<void>;
readonly definition: Definition;
readonly id: Name;
clone<Ext, NewName>(
name: NewName,
extend?: Ext
): GraphTypeRuntime<Definition & Ext, Type, NewName>;
constructor(definition: Definition);
constructor(name: Name, definition: Definition);
parse(input: any, customMessage?: ValidationCustomMessage): Type;
graphQLType(...args: unknown[]): typeof import('graphql').GraphQLNamedType;
graphQLInputType(
...args: unknown[]
): typeof import('graphql').GraphQLNamedInputType;
graphQLInterface(
...args: unknown[]
): typeof import('graphql').GraphQLInterfaceType;
addRelation<FieldTypeDef, Name, Context = unknown, ArgsDef>(
options: Merge<
{ type: FieldTypeDef; name: Name },
ResolverConfigRuntime<Context, unknown, FieldTypeDef, ArgsDef>
>
): this;
print(): string[];
typescriptPrint(options?: unknown): Promise<string>;
}
export type ResolverKind = 'query' | 'mutation' | 'subscription';
export interface ResolverConfigRuntime<Context, Source, Type, Args, Name>
extends Omit<GraphQLFieldConfig<any, any>, 'resolve' | 'args' | 'type'> {
name: Name;
kind?: ResolverKind;
args?: unknown;
type: unknown;
resolve(
root: Source,
args: Args,
context: Context,
info: GraphQLResolveInfo
): Type | Promise<Type>;
}
export interface ResolverRuntime<Context, Source, Type, Args, Name>
extends Omit<GraphQLFieldConfig<any, any>, 'resolve' | 'args' | 'type'> {
__isResolver: true;
__isRelation: boolean;
__graphTypeId: string;
__relatedToGraphTypeId: string;
resolve(
root: Source,
args: Args,
context: Context,
info: GraphQLResolveInfo
): Type | Promise<Type>;
name: Name;
kind: 'query' | 'subscription' | 'mutation';
typeDef: any;
argsDef: any;
payloadType: GraphTypeRuntime<any, Type, any>;
argsType: GraphTypeRuntime<any, Args, any>;
type: any;
args: any;
asObjectField(name?: string): GraphQLField<any, any>;
}
${creators.join('\n')}
${resolvers.join('\n')}
${extraCustomBody.join('\n')}
${definitions}
${typesInterface}
${extraCustomFooter.join('\n')}
}
}
`;
}
let timeoutRef;
let timeoutMS = 2000;
function save() {
clearTimeout(timeoutRef);
if (process.env.backland_emit_interval) {
timeoutMS = +process.env.backland_emit_interval > 0 ? +process.env.backland_emit_interval : timeoutMS;
timeoutRef = setTimeout(() => {
writeTypes().catch(err => {
console.error('writeTypes:', err.message);
});
}, timeoutMS);
}
}
process.on('unhandledRejection', () => {
clearTimeout(timeoutRef);
});
//# sourceMappingURL=writeTypes.js.map