UNPKG

@getcronit/pylon

Version:

![Pylon cover](https://github.com/user-attachments/assets/c28e49b2-5672-4849-826e-8b2eab0360cc)

105 lines (104 loc) 4.63 kB
import { Context } from '@getcronit/pylon'; type Primitive = string | number | boolean | symbol | bigint | undefined | null | Date; /** * Recursively maps a GraphQL return type to a selection map for the `needs` object. * Allows boolean flags for selection and a special `__args` property for nested arguments. */ export type NeedsMap<T> = T extends Primitive ? boolean : T extends (...args: any[]) => infer Ret ? NeedsMap<Awaited<Ret>> : T extends Array<infer U> ? NeedsMap<U> : { [K in keyof T]?: NeedsMap<T[K]> | boolean; } & { __args?: Record<string, any>; }; /** * Maps over the properties of the resolved type within the registry. * Intercepting the lookup at the property level mitigates TS2589 * (Type instantiation is excessively deep and possibly infinite) during recursive type inference. */ type MapValue<V, P, R> = V extends Primitive ? V : V extends Array<infer U> ? Array<PatchSchema<U, P, R>> : V extends { __typename: infer Name; } ? Name extends keyof P ? P[Name & keyof P] extends (...args: any) => infer Res ? { [Prop in keyof Res]: PatchSchema<Res[Prop], P, R>; } : never : { [Prop in keyof V]: PatchSchema<V[Prop], P, R>; } : { [Prop in keyof V]: PatchSchema<V[Prop], P, R>; }; type MappedRegistry<R, P> = { [K in keyof R]: MapValue<R[K], P, R>; }; type PatchSchema<T, P, R> = T extends Primitive ? T : T extends (...args: infer Args) => infer Ret ? (...args: Args) => Ret extends Promise<any> ? Promise<PatchSchema<Awaited<Ret>, P, R>> : PatchSchema<Awaited<Ret>, P, R> : T extends Array<infer U> ? Array<PatchSchema<U, P, R>> : T extends { __typename: infer Name; } ? Name extends keyof R ? MappedRegistry<R, P>[Name & keyof R] : { [K in keyof T]: PatchSchema<T[K], P, R>; } : T extends object ? { [K in keyof T]: PatchSchema<T[K], P, R>; } : T; export interface GatewayContext<TRegistry extends { delegate: any; types: any; }> { delegate: <K extends keyof TRegistry['delegate'], TNeeds extends NeedsMap<TRegistry['delegate'][K]['return']> = NeedsMap<TRegistry['delegate'][K]['return']>>(key: K, ...opts: {} extends TRegistry['delegate'][K]['args'] ? [options?: { args?: TRegistry['delegate'][K]['args']; needs?: TNeeds; }] : [options: { args: TRegistry['delegate'][K]['args']; needs?: TNeeds; }]) => Promise<TRegistry['delegate'][K]['return']>; } declare class PylonGateway<TRegistry extends { delegate: any; types: any; }, TPatch extends Record<string, (data: any, api: any) => any>> { private config; private apiContext; constructor(config: { url: string; headers?: (ctx: any) => Record<string, string>; patches: TPatch; }); delegate<K extends keyof TRegistry['delegate'], TNeeds extends NeedsMap<TRegistry['delegate'][K]['return']> = NeedsMap<TRegistry['delegate'][K]['return']>>(key: K, ...opts: {} extends TRegistry['delegate'][K]['args'] ? [options?: { args?: TRegistry['delegate'][K]['args']; needs?: TNeeds; }] : [options: { args: TRegistry['delegate'][K]['args']; needs?: TNeeds; }]): Promise<PatchSchema<TRegistry['delegate'][K]['return'], TPatch, TRegistry['types']>>; } /** * Instantiates a factory for configuring a strongly-typed PylonGateway. * * Utilizes a generated type registry (`TRegistry`) mapping remote GraphQL typenames * to TypeScript interfaces, guaranteeing end-to-end type safety for configurations, * schema patches, and delegated execution payloads. * * @template TRegistry - Type map correlating GraphQL typenames to local TypeScript definitions. * @returns Gateway configuration interface. * * @example * * // Provision remote schema via CLI: pylon pull <url> -n <name> * * ```typescript * import { createGateway } from '@getcronit/pylon'; * import { RemoteRegistry } from './generated/remote'; * * const gateway = createGateway<RemoteRegistry>().configure({ * url: '[https://api.example.com/graphql](https://api.example.com/graphql)', * headers: (ctx) => ({ Authorization: ctx.token }), * patches: { * User: (data, api) => ({ ...data, fullName: `${data.firstName} ${data.lastName}` }) * } * }); * ``` */ export declare function createGateway<TRegistry extends { delegate: any; types: any; }>(): { configure: <TPatch extends { [K in keyof TPatch]: K extends keyof TRegistry["types"] ? (data: TRegistry["types"][K], api: GatewayContext<TRegistry>) => any : never; }>(config: { url: string; headers?: (ctx: Context) => Record<string, string>; patches: TPatch; }) => PylonGateway<TRegistry, TPatch>; }; export {};