- Consolidated duplicate UndoManagers to single instance - Fixed connection promise to only resolve on 'connected' status - Fixed WebSocketProvider import (WebsocketProvider) - Added proper doc.destroy() cleanup - Renamed isPresenceInitialized property to avoid conflict Co-Authored-By: Paperclip <noreply@paperclip.ing>
177 lines
4.7 KiB
TypeScript
177 lines
4.7 KiB
TypeScript
/* eslint-disable @typescript-eslint/no-non-null-assertion */
|
|
import type { Unsubscribable } from '@trpc/server/observable';
|
|
import type {
|
|
AnyProcedure,
|
|
AnyRouter,
|
|
inferClientTypes,
|
|
inferProcedureInput,
|
|
InferrableClientTypes,
|
|
inferTransformedProcedureOutput,
|
|
ProcedureType,
|
|
RouterRecord,
|
|
} from '@trpc/server/unstable-core-do-not-import';
|
|
import {
|
|
createFlatProxy,
|
|
createRecursiveProxy,
|
|
} from '@trpc/server/unstable-core-do-not-import';
|
|
import type { CreateTRPCClientOptions } from './createTRPCUntypedClient';
|
|
import type { TRPCSubscriptionObserver } from './internals/TRPCUntypedClient';
|
|
import { TRPCUntypedClient } from './internals/TRPCUntypedClient';
|
|
import type { TRPCProcedureOptions } from './internals/types';
|
|
import type { TRPCClientError } from './TRPCClientError';
|
|
|
|
/**
|
|
* @public
|
|
* @deprecated use {@link TRPCClient} instead, will be removed in v12
|
|
**/
|
|
export type inferRouterClient<TRouter extends AnyRouter> = TRPCClient<TRouter>;
|
|
|
|
/**
|
|
* @public
|
|
* @deprecated use {@link TRPCClient} instead, will be removed in v12
|
|
**/
|
|
export type CreateTRPCClient<TRouter extends AnyRouter> = TRPCClient<TRouter>;
|
|
|
|
const untypedClientSymbol = Symbol.for('trpc_untypedClient');
|
|
|
|
/**
|
|
* @public
|
|
**/
|
|
export type TRPCClient<TRouter extends AnyRouter> = DecoratedProcedureRecord<
|
|
{
|
|
transformer: TRouter['_def']['_config']['$types']['transformer'];
|
|
errorShape: TRouter['_def']['_config']['$types']['errorShape'];
|
|
},
|
|
TRouter['_def']['record']
|
|
> & {
|
|
[untypedClientSymbol]: TRPCUntypedClient<TRouter>;
|
|
};
|
|
|
|
/** @internal */
|
|
export type TRPCResolverDef = {
|
|
input: any;
|
|
output: any;
|
|
transformer: boolean;
|
|
errorShape: any;
|
|
};
|
|
|
|
type coerceAsyncGeneratorToIterable<T> =
|
|
T extends AsyncGenerator<infer $T, infer $Return, infer $Next>
|
|
? AsyncIterable<$T, $Return, $Next>
|
|
: T;
|
|
|
|
/** @internal */
|
|
export type Resolver<TDef extends TRPCResolverDef> = (
|
|
input: TDef['input'],
|
|
opts?: TRPCProcedureOptions,
|
|
) => Promise<coerceAsyncGeneratorToIterable<TDef['output']>>;
|
|
|
|
/** @internal */
|
|
export type SubscriptionResolver<TDef extends TRPCResolverDef> = (
|
|
input: TDef['input'],
|
|
opts: Partial<
|
|
TRPCSubscriptionObserver<TDef['output'], TRPCClientError<TDef>>
|
|
> &
|
|
TRPCProcedureOptions,
|
|
) => Unsubscribable;
|
|
|
|
type DecorateProcedure<
|
|
TType extends ProcedureType,
|
|
TDef extends TRPCResolverDef,
|
|
> = TType extends 'query'
|
|
? {
|
|
query: Resolver<TDef>;
|
|
}
|
|
: TType extends 'mutation'
|
|
? {
|
|
mutate: Resolver<TDef>;
|
|
}
|
|
: TType extends 'subscription'
|
|
? {
|
|
subscribe: SubscriptionResolver<TDef>;
|
|
}
|
|
: never;
|
|
|
|
/**
|
|
* @internal
|
|
*/
|
|
type DecoratedProcedureRecord<
|
|
TRoot extends InferrableClientTypes,
|
|
TRecord extends RouterRecord,
|
|
> = {
|
|
[TKey in keyof TRecord]: TRecord[TKey] extends infer $Value
|
|
? $Value extends AnyProcedure
|
|
? DecorateProcedure<
|
|
$Value['_def']['type'],
|
|
{
|
|
input: inferProcedureInput<$Value>;
|
|
output: inferTransformedProcedureOutput<
|
|
inferClientTypes<TRoot>,
|
|
$Value
|
|
>;
|
|
errorShape: inferClientTypes<TRoot>['errorShape'];
|
|
transformer: inferClientTypes<TRoot>['transformer'];
|
|
}
|
|
>
|
|
: $Value extends RouterRecord
|
|
? DecoratedProcedureRecord<TRoot, $Value>
|
|
: never
|
|
: never;
|
|
};
|
|
|
|
const clientCallTypeMap: Record<
|
|
keyof DecorateProcedure<any, any>,
|
|
ProcedureType
|
|
> = {
|
|
query: 'query',
|
|
mutate: 'mutation',
|
|
subscribe: 'subscription',
|
|
};
|
|
|
|
/** @internal */
|
|
export const clientCallTypeToProcedureType = (
|
|
clientCallType: string,
|
|
): ProcedureType => {
|
|
return clientCallTypeMap[clientCallType as keyof typeof clientCallTypeMap];
|
|
};
|
|
|
|
/**
|
|
* @internal
|
|
*/
|
|
export function createTRPCClientProxy<TRouter extends AnyRouter>(
|
|
client: TRPCUntypedClient<TRouter>,
|
|
): TRPCClient<TRouter> {
|
|
const proxy = createRecursiveProxy<TRPCClient<TRouter>>(({ path, args }) => {
|
|
const pathCopy = [...path];
|
|
const procedureType = clientCallTypeToProcedureType(pathCopy.pop()!);
|
|
|
|
const fullPath = pathCopy.join('.');
|
|
|
|
return (client[procedureType] as any)(fullPath, ...(args as any));
|
|
});
|
|
return createFlatProxy<TRPCClient<TRouter>>((key) => {
|
|
if (key === untypedClientSymbol) {
|
|
return client;
|
|
}
|
|
return proxy[key];
|
|
});
|
|
}
|
|
|
|
export function createTRPCClient<TRouter extends AnyRouter>(
|
|
opts: CreateTRPCClientOptions<TRouter>,
|
|
): TRPCClient<TRouter> {
|
|
const client = new TRPCUntypedClient(opts);
|
|
const proxy = createTRPCClientProxy<TRouter>(client);
|
|
return proxy;
|
|
}
|
|
|
|
/**
|
|
* Get an untyped client from a proxy client
|
|
* @internal
|
|
*/
|
|
export function getUntypedClient<TRouter extends AnyRouter>(
|
|
client: TRPCClient<TRouter>,
|
|
): TRPCUntypedClient<TRouter> {
|
|
return client[untypedClientSymbol];
|
|
}
|