Streamed mutations
A mutation that returns an async iterable fills in as it streams, with chunksOptions(), and stops on unmount or on demand; long jobs pair a mutation with a subscription.
On this page
A mutation that returns an async iterable (an AI reply, say) can fill in as it streams:
const const send: UseMutationResult<("ok" | "hi")[], (TrpcError<"BAD_REQUEST", InputValidationErrorData<{
readonly code: "invalid_type";
readonly expected: z.core.$ZodInvalidTypeExpected;
readonly path: readonly [] | readonly ["text"];
readonly message: string;
} | {
readonly code: "too_big";
readonly origin: "number" | "int" | "bigint" | "date" | "string" | "array" | "set" | "file" | (string & {});
readonly maximum: string | number;
readonly inclusive?: boolean | undefined;
readonly exact?: boolean | undefined;
readonly path: readonly [] | readonly ["text"];
readonly message: string;
} | {
readonly code: "too_small";
readonly origin: "number" | "int" | "bigint" | "date" | "string" | "array" | "set" | "file" | (string & {});
... 4 more ...;
readonly message: string;
} | ... 8 more ... | {
...;
}>> & {
...;
}) | (TrpcError<...> & {
...;
}), {
...;
}, undefined>
send = useMutation<("ok" | "hi")[], (TrpcError<"BAD_REQUEST", InputValidationErrorData<{
readonly code: "invalid_type";
readonly expected: z.core.$ZodInvalidTypeExpected;
readonly path: readonly [] | readonly ["text"];
readonly message: string;
} | {
readonly code: "too_big";
readonly origin: "number" | "int" | "bigint" | "date" | "string" | "array" | "set" | "file" | (string & {});
readonly maximum: string | number;
readonly inclusive?: boolean | undefined;
readonly exact?: boolean | undefined;
readonly path: readonly [] | readonly ["text"];
readonly message: string;
} | {
readonly code: "too_small";
readonly origin: "number" | "int" | "bigint" | "date" | "string" | "array" | "set" | "file" | (string & {});
... 4 more ...;
readonly message: string;
} | ... 8 more ... | {
...;
}>> & {
...;
}) | (TrpcError<...> & {
...;
}), {
...;
}, undefined>(options: UseMutationOptions<...>, queryClient?: QueryClient): UseMutationResult<...>
useMutation(const trpc: TrpcQueryUtils<TrpcClient<{
chat: {
send: BuildProcedure<InputDef<RootDef<Context, {}>, z.ZodObject<{
text: z.ZodString;
}, z.core.$strip>>, "mutation", {
output: AsyncGenerator<"ok" | "hi", void, unknown>;
errors: never;
services: never;
unmapped: never;
}>;
};
}, {}, undefined, LinksTypes<readonly [TrpcLink<{
form: JsonForm;
provides: "response";
}, any>]>>>
trpc.chat: TrpcQueryUtils<ClientRouter<{
send: BuildProcedure<InputDef<RootDef<Context, {}>, z.ZodObject<{
text: z.ZodString;
}, z.core.$strip>>, "mutation", {
output: AsyncGenerator<"ok" | "hi", void, unknown>;
errors: never;
services: never;
unmapped: never;
}>;
}, {}, undefined, LinksTypes<readonly [TrpcLink<{
form: JsonForm;
provides: "response";
}, any>]>>>
chat.send: MutationProcedureUtils<{
...;
}, AsyncIterable<...>, NonNullable<...>, Omit<...>>
send.MutationProcedureUtils<{ text: string; }, AsyncIterable<"ok" | "hi">, NonNullable<UnexpectedError | (TrpcError<"BAD_REQUEST", InputValidationErrorData<{ readonly code: "invalid_type"; readonly expected: $ZodInvalidTypeExpected; readonly path: readonly [] | readonly [...]; readonly message: string; } | ... 10 more ... | { ...; }>> & { ...; })>, Omit<...>>.streamedMutationOptions<undefined>(opts?: (ContextBag<Omit<NonNullable<{
signal?: AbortSignal | undefined;
} & BuiltinCallOptions & {}>, "signal" | "lastEventId">> & StreamedMutationOptions<"ok" | "hi", {
text: string;
}> & MutationOptionsIn<{
text: string;
}, ("ok" | "hi")[], NonNullable<UnexpectedError | (TrpcError<"BAD_REQUEST", InputValidationErrorData<{
readonly code: "invalid_type";
readonly expected: z.core.$ZodInvalidTypeExpected;
readonly path: readonly [] | readonly ["text"];
readonly message: string;
} | ... 10 more ... | {
...;
}>> & {
...;
})>, undefined>) | undefined): MutationOptionsOut<...>
streamedMutationOptions());
const const chunks: UseQueryResult<("ok" | "hi")[], NonNullable<UnexpectedError | (TrpcError<"BAD_REQUEST", InputValidationErrorData<{
readonly code: "invalid_type";
readonly expected: z.core.$ZodInvalidTypeExpected;
readonly path: readonly [] | readonly ["text"];
readonly message: string;
} | {
readonly code: "too_big";
readonly origin: "number" | "int" | "bigint" | "date" | "string" | "array" | "set" | "file" | (string & {});
readonly maximum: string | number;
readonly inclusive?: boolean | undefined;
readonly exact?: boolean | undefined;
readonly path: readonly [] | readonly ["text"];
readonly message: string;
} | {
readonly code: "too_small";
readonly origin: "number" | "int" | "bigint" | "date" | "string" | "array" | "set" | "file" | (string & {});
... 4 more ...;
readonly message: string;
} | ... 8 more ... | {
...;
}>> & {
...;
})>>
chunks = useQuery<("ok" | "hi")[], NonNullable<UnexpectedError | (TrpcError<"BAD_REQUEST", InputValidationErrorData<{
readonly code: "invalid_type";
readonly expected: z.core.$ZodInvalidTypeExpected;
readonly path: readonly [] | readonly ["text"];
readonly message: string;
} | {
readonly code: "too_big";
readonly origin: "number" | "int" | "bigint" | "date" | "string" | "array" | "set" | "file" | (string & {});
readonly maximum: string | number;
readonly inclusive?: boolean | undefined;
readonly exact?: boolean | undefined;
readonly path: readonly [] | readonly ["text"];
readonly message: string;
} | {
...;
} | ... 8 more ... | {
...;
}>> & {
...;
})>, ("ok" | "hi")[], TrpcQueryKey & {
...;
}>(options: UndefinedInitialDataOptions<...>, queryClient?: QueryClient): UseQueryResult<...> (+2 overloads)
useQuery(const trpc: TrpcQueryUtils<TrpcClient<{
chat: {
send: BuildProcedure<InputDef<RootDef<Context, {}>, z.ZodObject<{
text: z.ZodString;
}, z.core.$strip>>, "mutation", {
output: AsyncGenerator<"ok" | "hi", void, unknown>;
errors: never;
services: never;
unmapped: never;
}>;
};
}, {}, undefined, LinksTypes<readonly [TrpcLink<{
form: JsonForm;
provides: "response";
}, any>]>>>
trpc.chat: TrpcQueryUtils<ClientRouter<{
send: BuildProcedure<InputDef<RootDef<Context, {}>, z.ZodObject<{
text: z.ZodString;
}, z.core.$strip>>, "mutation", {
output: AsyncGenerator<"ok" | "hi", void, unknown>;
errors: never;
services: never;
unmapped: never;
}>;
}, {}, undefined, LinksTypes<readonly [TrpcLink<{
form: JsonForm;
provides: "response";
}, any>]>>>
chat.send: MutationProcedureUtils<{
...;
}, AsyncIterable<...>, NonNullable<...>, Omit<...>>
send.MutationProcedureUtils<{ text: string; }, AsyncIterable<"ok" | "hi">, NonNullable<UnexpectedError | (TrpcError<"BAD_REQUEST", InputValidationErrorData<{ readonly code: "invalid_type"; readonly expected: $ZodInvalidTypeExpected; readonly path: readonly [] | readonly [...]; readonly message: string; } | ... 10 more ... | { ...; }>> & { ...; })>, Omit<...>>.chunksOptions<("ok" | "hi")[]>(opts?: Omit<QueryOptionsIn<("ok" | "hi")[], NonNullable<UnexpectedError | (TrpcError<"BAD_REQUEST", InputValidationErrorData<{
readonly code: "invalid_type";
readonly expected: z.core.$ZodInvalidTypeExpected;
readonly path: readonly [] | readonly ["text"];
readonly message: string;
} | {
readonly code: "too_big";
readonly origin: "number" | "int" | "bigint" | "date" | "string" | "array" | "set" | "file" | (string & {});
readonly maximum: string | number;
readonly inclusive?: boolean | undefined;
readonly exact?: boolean | undefined;
readonly path: readonly [] | readonly ["text"];
readonly message: string;
} | ... 9 more ... | {
...;
}>> & {
...;
})>, ("ok" | "hi")[]>, "enabled"> | undefined): QueryOptionsOut<...>
chunksOptions());
const send: UseMutationResult<("ok" | "hi")[], (TrpcError<"BAD_REQUEST", InputValidationErrorData<{
readonly code: "invalid_type";
readonly expected: z.core.$ZodInvalidTypeExpected;
readonly path: readonly [] | readonly ["text"];
readonly message: string;
} | {
readonly code: "too_big";
readonly origin: "number" | "int" | "bigint" | "date" | "string" | "array" | "set" | "file" | (string & {});
readonly maximum: string | number;
readonly inclusive?: boolean | undefined;
readonly exact?: boolean | undefined;
readonly path: readonly [] | readonly ["text"];
readonly message: string;
} | {
readonly code: "too_small";
readonly origin: "number" | "int" | "bigint" | "date" | "string" | "array" | "set" | "file" | (string & {});
... 4 more ...;
readonly message: string;
} | ... 8 more ... | {
...;
}>> & {
...;
}) | (TrpcError<...> & {
...;
}), {
...;
}, undefined>
send.mutate: (variables: {
text: string;
}, options?: MutateOptions<("ok" | "hi")[], (TrpcError<"BAD_REQUEST", InputValidationErrorData<{
readonly code: "invalid_type";
readonly expected: z.core.$ZodInvalidTypeExpected;
readonly path: readonly [] | readonly ["text"];
readonly message: string;
} | {
readonly code: "too_big";
readonly origin: "number" | "int" | "bigint" | "date" | "string" | "array" | "set" | "file" | (string & {});
readonly maximum: string | number;
readonly inclusive?: boolean | undefined;
readonly exact?: boolean | undefined;
readonly path: readonly [] | readonly ["text"];
readonly message: string;
} | {
readonly code: "too_small";
... 5 more ...;
readonly message: string;
} | ... 8 more ... | {
...;
}>> & {
...;
}) | (TrpcError<...> & {
...;
}), {
text: string;
}, undefined> | undefined) => void
mutate({ text: stringtext });
// chunks.data: ['ok'] → ['ok', 'hi'], then send.data is ['ok', 'hi']chunksOptions() never fetches; it reads what the mutation writes to streamedMutationKey(). Each mutate starts the chunks over. Pass onChunk(chunk, chunks) to act on each one.
Stopping the stream
Resetting the mutation doesn't stop the stream on the server. Two options do, and in both data is the chunks so far:
// stop when the last chunksOptions() reader unmounts
const trpc: TrpcQueryUtils<TrpcClient<{
chat: {
send: BuildProcedure<InputDef<RootDef<Context, {}>, z.ZodObject<{
text: z.ZodString;
}, z.core.$strip>>, "mutation", {
output: AsyncGenerator<string, void, unknown>;
errors: never;
services: never;
unmapped: never;
}>;
};
}, {}, undefined, LinksTypes<readonly [TrpcLink<{
form: JsonForm;
provides: "response";
}, any>]>>>
trpc.chat: TrpcQueryUtils<ClientRouter<{
send: BuildProcedure<InputDef<RootDef<Context, {}>, z.ZodObject<{
text: z.ZodString;
}, z.core.$strip>>, "mutation", {
output: AsyncGenerator<string, void, unknown>;
errors: never;
services: never;
unmapped: never;
}>;
}, {}, undefined, LinksTypes<readonly [TrpcLink<{
form: JsonForm;
provides: "response";
}, any>]>>>
chat.send: MutationProcedureUtils<{
text: string;
}, AsyncIterable<string>, NonNullable<UnexpectedError | (TrpcError<"BAD_REQUEST", InputValidationErrorData<{
readonly code: "invalid_type";
readonly expected: z.core.$ZodInvalidTypeExpected;
readonly path: readonly [] | readonly ["text"];
readonly message: string;
} | {
readonly code: "too_big";
readonly origin: "number" | "int" | "bigint" | "date" | "string" | "array" | "set" | "file" | (string & {});
readonly maximum: string | number;
readonly inclusive?: boolean | undefined;
readonly exact?: boolean | undefined;
readonly path: readonly [] | readonly ["text"];
readonly message: string;
} | ... 9 more ... | {
...;
}>> & {
...;
})>, Omit<...>>
send.MutationProcedureUtils<{ text: string; }, AsyncIterable<string>, NonNullable<UnexpectedError | (TrpcError<"BAD_REQUEST", InputValidationErrorData<{ readonly code: "invalid_type"; readonly expected: $ZodInvalidTypeExpected; readonly path: readonly [] | readonly [...]; readonly message: string; } | ... 10 more ... | { ...; }>> & { ...; })>, Omit<...>>.streamedMutationOptions<unknown>(opts?: (ContextBag<Omit<NonNullable<{
signal?: AbortSignal | undefined;
} & BuiltinCallOptions & {}>, "signal" | "lastEventId">> & StreamedMutationOptions<string, {
text: string;
}> & MutationOptionsIn<{
text: string;
}, string[], NonNullable<UnexpectedError | (TrpcError<"BAD_REQUEST", InputValidationErrorData<{
readonly code: "invalid_type";
readonly expected: z.core.$ZodInvalidTypeExpected;
readonly path: readonly [] | readonly ["text"];
readonly message: string;
} | {
readonly code: "too_big";
... 5 more ...;
readonly message: string;
} | ... 9 more ... | {
...;
}>> & {
...;
})>, unknown>) | undefined): MutationOptionsOut<...>
streamedMutationOptions({ StreamedMutationOptions<TChunk, TInput = unknown>.abortWhenUnobserved?: boolean | undefinedabortWhenUnobserved: true });
// stop on demand: a function gives each mutate() its own signal
const const stop: React.RefObject<AbortController | undefined>stop = useRef<AbortController>(initialValue: AbortController | undefined): React.RefObject<AbortController | undefined> (+2 overloads)useRef<AbortController>(var undefinedundefined);
const trpc: TrpcQueryUtils<TrpcClient<{
chat: {
send: BuildProcedure<InputDef<RootDef<Context, {}>, z.ZodObject<{
text: z.ZodString;
}, z.core.$strip>>, "mutation", {
output: AsyncGenerator<string, void, unknown>;
errors: never;
services: never;
unmapped: never;
}>;
};
}, {}, undefined, LinksTypes<readonly [TrpcLink<{
form: JsonForm;
provides: "response";
}, any>]>>>
trpc.chat: TrpcQueryUtils<ClientRouter<{
send: BuildProcedure<InputDef<RootDef<Context, {}>, z.ZodObject<{
text: z.ZodString;
}, z.core.$strip>>, "mutation", {
output: AsyncGenerator<string, void, unknown>;
errors: never;
services: never;
unmapped: never;
}>;
}, {}, undefined, LinksTypes<readonly [TrpcLink<{
form: JsonForm;
provides: "response";
}, any>]>>>
chat.send: MutationProcedureUtils<{
text: string;
}, AsyncIterable<string>, NonNullable<UnexpectedError | (TrpcError<"BAD_REQUEST", InputValidationErrorData<{
readonly code: "invalid_type";
readonly expected: z.core.$ZodInvalidTypeExpected;
readonly path: readonly [] | readonly ["text"];
readonly message: string;
} | {
readonly code: "too_big";
readonly origin: "number" | "int" | "bigint" | "date" | "string" | "array" | "set" | "file" | (string & {});
readonly maximum: string | number;
readonly inclusive?: boolean | undefined;
readonly exact?: boolean | undefined;
readonly path: readonly [] | readonly ["text"];
readonly message: string;
} | ... 9 more ... | {
...;
}>> & {
...;
})>, Omit<...>>
send.MutationProcedureUtils<{ text: string; }, AsyncIterable<string>, NonNullable<UnexpectedError | (TrpcError<"BAD_REQUEST", InputValidationErrorData<{ readonly code: "invalid_type"; readonly expected: $ZodInvalidTypeExpected; readonly path: readonly [] | readonly [...]; readonly message: string; } | ... 10 more ... | { ...; }>> & { ...; })>, Omit<...>>.streamedMutationOptions<unknown>(opts?: (ContextBag<Omit<NonNullable<{
signal?: AbortSignal | undefined;
} & BuiltinCallOptions & {}>, "signal" | "lastEventId">> & StreamedMutationOptions<string, {
text: string;
}> & MutationOptionsIn<{
text: string;
}, string[], NonNullable<UnexpectedError | (TrpcError<"BAD_REQUEST", InputValidationErrorData<{
readonly code: "invalid_type";
readonly expected: z.core.$ZodInvalidTypeExpected;
readonly path: readonly [] | readonly ["text"];
readonly message: string;
} | {
readonly code: "too_big";
... 5 more ...;
readonly message: string;
} | ... 9 more ... | {
...;
}>> & {
...;
})>, unknown>) | undefined): MutationOptionsOut<...>
streamedMutationOptions({
StreamedMutationOptions<string, { text: string; }>.signal?: AbortSignal | ((variables: {
text: string;
}) => AbortSignal | undefined) | undefined
signal: () => (const stop: React.RefObject<AbortController | undefined>stop.React.RefObject<AbortController | undefined>.current: AbortController | undefinedcurrent = new var AbortController: new () => AbortControllerAbortController()).AbortController.signal: AbortSignalsignal,
});
const stop: React.RefObject<AbortController | undefined>stop.React.RefObject<AbortController | undefined>.current: AbortController | undefinedcurrent?.AbortController.abort(reason?: any): voidabort();Long jobs
A stream tied to one screen fits a streamed mutation. A job that should outlive the screen, be resumed after a reload, or be watched from several tabs fits a mutation that starts it, a tracked() subscription for its progress, and a mutation that cancels it:
const const job: {
start: BuildProcedure<InputDef<RootDef<Context, {}>, z.ZodObject<{
size: z.ZodNumber;
}, z.core.$strip>>, "mutation", {
output: {
id: string;
};
errors: never;
services: never;
unmapped: never;
}>;
progress: BuildProcedure<InputDef<RootDef<Context, {}>, z.ZodObject<{
id: z.ZodString;
}, z.core.$strip>>, "subscription", {
output: TrackedEnvelope<Step>;
errors: never;
services: never;
}>;
cancel: BuildProcedure<InputDef<RootDef<Context, {}>, z.ZodObject<...>>, "mutation", {
...;
}>;
}
job = {
start: BuildProcedure<InputDef<RootDef<Context, {}>, z.ZodObject<{
size: z.ZodNumber;
}, z.core.$strip>>, "mutation", {
output: {
id: string;
};
errors: never;
services: never;
unmapped: never;
}>
start: const t: TrpcRoot<Context, {}, RootDef<Context, {}>>t.TrpcRoot<Context, {}, RootDef<Context, {}>>.procedure: ProcedureBuilder<RootDef<Context, {}>>procedure.ProcedureBuilder<RootDef<Context, {}>>.input<z.ZodObject<{
size: z.ZodNumber;
}, z.core.$strip>>(schema: z.ZodObject<{
size: z.ZodNumber;
}, z.core.$strip>): ProcedureBuilder<InputDef<RootDef<Context, {}>, z.ZodObject<{
size: z.ZodNumber;
}, z.core.$strip>>> (+1 overload)
input(const Params: z.ZodObject<{
size: z.ZodNumber;
}, z.core.$strip>
Params).ProcedureBuilder<InputDef<RootDef<Context, {}>, ZodObject<{ size: ZodNumber; }, $strip>>>.mutation<Promise<{
id: string;
}>>(resolver: (opts: ResolverOpts<InputDef<RootDef<Context, {}>, z.ZodObject<{
size: z.ZodNumber;
}, z.core.$strip>>>) => Promise<{
id: string;
}>): BuildProcedure<InputDef<RootDef<Context, {}>, z.ZodObject<{
size: z.ZodNumber;
}, z.core.$strip>>, "mutation", {
output: {
id: string;
};
errors: never;
services: never;
unmapped: never;
}>
mutation((opts: ResolverOpts<InputDef<RootDef<Context, {}>, z.ZodObject<{
size: z.ZodNumber;
}, z.core.$strip>>>
opts) => const jobs: {
start(params: z.infer<typeof Params>): Promise<{
id: string;
}>;
watch(id: string, opts: {
after?: string;
}): AsyncIterable<Step>;
cancel(id: string): Promise<void>;
}
jobs.function start(params: z.infer<typeof Params>): Promise<{
id: string;
}>
start(opts: ResolverOpts<InputDef<RootDef<Context, {}>, z.ZodObject<{
size: z.ZodNumber;
}, z.core.$strip>>>
opts.ResolverOpts<InputDef<RootDef<Context, {}>, ZodObject<{ size: ZodNumber; }, $strip>>>.input: {
size: number;
}
input)), // { id }
progress: BuildProcedure<InputDef<RootDef<Context, {}>, z.ZodObject<{
id: z.ZodString;
}, z.core.$strip>>, "subscription", {
output: TrackedEnvelope<Step>;
errors: never;
services: never;
}>
progress: const t: TrpcRoot<Context, {}, RootDef<Context, {}>>t.TrpcRoot<Context, {}, RootDef<Context, {}>>.procedure: ProcedureBuilder<RootDef<Context, {}>>procedure
.ProcedureBuilder<RootDef<Context, {}>>.input<z.ZodObject<{
id: z.ZodString;
}, z.core.$strip>>(schema: z.ZodObject<{
id: z.ZodString;
}, z.core.$strip>): ProcedureBuilder<InputDef<RootDef<Context, {}>, z.ZodObject<{
id: z.ZodString;
}, z.core.$strip>>> (+1 overload)
input(import zz.function object<{
id: z.ZodString;
}>(shape?: {
id: z.ZodString;
} | undefined, params?: string | {
error?: string | z.core.$ZodErrorMap<NonNullable<z.core.$ZodIssueInvalidType<unknown> | z.core.$ZodIssueUnrecognizedKeys>> | undefined;
message?: string | undefined | undefined;
} | undefined): z.ZodObject<{
id: z.ZodString;
}, z.core.$strip>
object({ id: z.ZodStringid: import zz.function string(params?: string | z.core.$ZodStringParams): z.ZodString (+1 overload)string() }))
.ProcedureBuilder<InputDef<RootDef<Context, {}>, ZodObject<{ id: ZodString; }, $strip>>>.subscription<AsyncGenerator<TrackedEnvelope<Step>, void, unknown>>(resolver: (opts: SubscriptionResolverOpts<InputDef<RootDef<Context, {}>, z.ZodObject<{
id: z.ZodString;
}, z.core.$strip>>>) => AsyncGenerator<TrackedEnvelope<Step>, void, unknown>): BuildProcedure<InputDef<RootDef<Context, {}>, z.ZodObject<{
id: z.ZodString;
}, z.core.$strip>>, "subscription", {
output: TrackedEnvelope<Step>;
errors: never;
services: never;
}>
subscription(async function* (opts: SubscriptionResolverOpts<InputDef<RootDef<Context, {}>, z.ZodObject<{
id: z.ZodString;
}, z.core.$strip>>>
opts) {
const const steps: AsyncIterable<Step>steps = const jobs: {
start(params: z.infer<typeof Params>): Promise<{
id: string;
}>;
watch(id: string, opts: {
after?: string;
}): AsyncIterable<Step>;
cancel(id: string): Promise<void>;
}
jobs.function watch(id: string, opts: {
after?: string;
}): AsyncIterable<Step>
watch(opts: SubscriptionResolverOpts<InputDef<RootDef<Context, {}>, z.ZodObject<{
id: z.ZodString;
}, z.core.$strip>>>
opts.ResolverOpts<InputDef<RootDef<Context, {}>, ZodObject<{ id: ZodString; }, $strip>>>.input: {
id: string;
}
input.id: stringid, { after?: string | undefinedafter: opts: SubscriptionResolverOpts<InputDef<RootDef<Context, {}>, z.ZodObject<{
id: z.ZodString;
}, z.core.$strip>>>
opts.SubscriptionResolverOpts<TDef extends BuilderDef>.lastEventId: string | undefinedlastEventId });
for await (const const step: Stepstep of const steps: AsyncIterable<Step>steps) yield tracked<Step>(id: string, data: Step): TrackedEnvelope<Step>tracked(const step: Stepstep.Step.id: stringid, const step: Stepstep);
}),
cancel: BuildProcedure<InputDef<RootDef<Context, {}>, z.ZodObject<{
id: z.ZodString;
}, z.core.$strip>>, "mutation", {
output: void;
errors: never;
services: never;
unmapped: never;
}>
cancel: const t: TrpcRoot<Context, {}, RootDef<Context, {}>>t.TrpcRoot<Context, {}, RootDef<Context, {}>>.procedure: ProcedureBuilder<RootDef<Context, {}>>procedure
.ProcedureBuilder<RootDef<Context, {}>>.input<z.ZodObject<{
id: z.ZodString;
}, z.core.$strip>>(schema: z.ZodObject<{
id: z.ZodString;
}, z.core.$strip>): ProcedureBuilder<InputDef<RootDef<Context, {}>, z.ZodObject<{
id: z.ZodString;
}, z.core.$strip>>> (+1 overload)
input(import zz.function object<{
id: z.ZodString;
}>(shape?: {
id: z.ZodString;
} | undefined, params?: string | {
error?: string | z.core.$ZodErrorMap<NonNullable<z.core.$ZodIssueInvalidType<unknown> | z.core.$ZodIssueUnrecognizedKeys>> | undefined;
message?: string | undefined | undefined;
} | undefined): z.ZodObject<{
id: z.ZodString;
}, z.core.$strip>
object({ id: z.ZodStringid: import zz.function string(params?: string | z.core.$ZodStringParams): z.ZodString (+1 overload)string() }))
.ProcedureBuilder<InputDef<RootDef<Context, {}>, ZodObject<{ id: ZodString; }, $strip>>>.mutation<Promise<void>>(resolver: (opts: ResolverOpts<InputDef<RootDef<Context, {}>, z.ZodObject<{
id: z.ZodString;
}, z.core.$strip>>>) => Promise<void>): BuildProcedure<InputDef<RootDef<Context, {}>, z.ZodObject<{
id: z.ZodString;
}, z.core.$strip>>, "mutation", {
output: void;
errors: never;
services: never;
unmapped: never;
}>
mutation((opts: ResolverOpts<InputDef<RootDef<Context, {}>, z.ZodObject<{
id: z.ZodString;
}, z.core.$strip>>>
opts) => const jobs: {
start(params: z.infer<typeof Params>): Promise<{
id: string;
}>;
watch(id: string, opts: {
after?: string;
}): AsyncIterable<Step>;
cancel(id: string): Promise<void>;
}
jobs.function cancel(id: string): Promise<void>cancel(opts: ResolverOpts<InputDef<RootDef<Context, {}>, z.ZodObject<{
id: z.ZodString;
}, z.core.$strip>>>
opts.ResolverOpts<InputDef<RootDef<Context, {}>, ZodObject<{ id: ZodString; }, $strip>>>.input: {
id: string;
}
input.id: stringid)),
};
const const start: UseMutationResult<{
id: string;
}, (TrpcError<"BAD_REQUEST", InputValidationErrorData<{
readonly code: "unrecognized_keys";
readonly keys: readonly string[];
readonly path: readonly [] | readonly ["size"];
readonly message: string;
} | {
readonly code: "invalid_type";
readonly expected: z.core.$ZodInvalidTypeExpected;
readonly path: readonly [] | readonly ["size"];
readonly message: string;
} | {
readonly code: "too_big";
readonly origin: "number" | "int" | "bigint" | "date" | "string" | "array" | "set" | "file" | (string & {});
readonly maximum: string | number;
readonly inclusive?: boolean | undefined;
readonly exact?: boolean | undefined;
readonly path: readonly [] | readonly [...];
readonly message: string;
} | ... 8 more ... | {
...;
}>> & {
...;
}) | (TrpcError<...> & {
...;
}), {
...;
}, undefined>
start = useMutation<{
id: string;
}, (TrpcError<"BAD_REQUEST", InputValidationErrorData<{
readonly code: "unrecognized_keys";
readonly keys: readonly string[];
readonly path: readonly [] | readonly ["size"];
readonly message: string;
} | {
readonly code: "invalid_type";
readonly expected: z.core.$ZodInvalidTypeExpected;
readonly path: readonly [] | readonly ["size"];
readonly message: string;
} | {
readonly code: "too_big";
readonly origin: "number" | "int" | "bigint" | "date" | "string" | "array" | "set" | "file" | (string & {});
readonly maximum: string | number;
readonly inclusive?: boolean | undefined;
readonly exact?: boolean | undefined;
readonly path: readonly [] | readonly [...];
readonly message: string;
} | ... 8 more ... | {
...;
}>> & {
...;
}) | (TrpcError<...> & {
...;
}), {
...;
}, undefined>(options: UseMutationOptions<...>, queryClient?: QueryClient): UseMutationResult<...>
useMutation(const trpc: TrpcQueryUtils<TrpcClient<{
job: typeof job;
}, {}, undefined, LinksTypes<readonly [TrpcLink<{
form: JsonForm;
provides: "response";
}, any>]>>>
trpc.job: TrpcQueryUtils<ClientRouter<{
start: BuildProcedure<InputDef<RootDef<Context, {}>, z.ZodObject<{
size: z.ZodNumber;
}, z.core.$strip>>, "mutation", {
output: {
id: string;
};
errors: never;
services: never;
unmapped: never;
}>;
progress: BuildProcedure<InputDef<RootDef<Context, {}>, z.ZodObject<{
id: z.ZodString;
}, z.core.$strip>>, "subscription", {
output: TrackedEnvelope<Step>;
errors: never;
services: never;
}>;
cancel: BuildProcedure<InputDef<RootDef<Context, {}>, z.ZodObject<...>>, "mutation", {
...;
}>;
}, {}, undefined, LinksTypes<...>>>
job.start: MutationProcedureUtils<{
...;
}, {
id: string;
}, NonNullable<...>, Omit<...>>
start.MutationProcedureUtils<{ size: number; }, { id: string; }, NonNullable<UnexpectedError | (TrpcError<"BAD_REQUEST", InputValidationErrorData<{ readonly code: "unrecognized_keys"; readonly keys: readonly string[]; readonly path: readonly [] | readonly [...]; readonly message: string; } | ... 10 more ... | { ...; }>> & { ...; })>, Omit<...>>.mutationOptions<undefined>(opts?: (ContextBag<Omit<NonNullable<{
signal?: AbortSignal | undefined;
} & BuiltinCallOptions & {}>, "signal" | "lastEventId">> & MutationOptionsIn<{
size: number;
}, {
id: string;
}, NonNullable<UnexpectedError | (TrpcError<"BAD_REQUEST", InputValidationErrorData<{
readonly code: "unrecognized_keys";
readonly keys: readonly string[];
readonly path: readonly [] | readonly ["size"];
readonly message: string;
} | {
readonly code: "invalid_type";
readonly expected: z.core.$ZodInvalidTypeExpected;
readonly path: readonly [] | readonly ["size"];
readonly message: string;
} | ... 9 more ... | {
...;
}>> & {
...;
})>, undefined>) | undefined): MutationOptionsOut<...>
mutationOptions());
const const progress: UseSubscriptionResult<{
readonly id: string;
readonly data: {
id: string;
done: number;
};
}, NonNullable<UnexpectedError | (TrpcError<"BAD_REQUEST", InputValidationErrorData<{
readonly code: "unrecognized_keys";
readonly keys: readonly string[];
readonly path: readonly [] | readonly ["id"];
readonly message: string;
} | {
readonly code: "invalid_type";
readonly expected: z.core.$ZodInvalidTypeExpected;
readonly path: readonly [] | readonly ["id"];
readonly message: string;
} | {
readonly code: "too_big";
readonly origin: "number" | "int" | "bigint" | "date" | "string" | "array" | "set" | "file" | (string & {});
... 4 more ...;
readonly message: string;
} | ... 8 more ... | {
...;
}>> & {
...;
})>>
progress = useSubscription<{
readonly id: string;
readonly data: {
id: string;
done: number;
};
}, NonNullable<UnexpectedError | (TrpcError<"BAD_REQUEST", InputValidationErrorData<{
readonly code: "unrecognized_keys";
readonly keys: readonly string[];
readonly path: readonly [] | readonly ["id"];
readonly message: string;
} | {
readonly code: "invalid_type";
readonly expected: z.core.$ZodInvalidTypeExpected;
readonly path: readonly [] | readonly ["id"];
readonly message: string;
} | {
readonly code: "too_big";
readonly origin: "number" | "int" | "bigint" | "date" | "string" | "array" | "set" | "file" | (string & {});
... 4 more ...;
readonly message: string;
} | ... 8 more ... | {
...;
}>> & {
...;
})>>(options: TrpcSubscriptionOptions<...>): UseSubscriptionResult<...>
useSubscription(
const trpc: TrpcQueryUtils<TrpcClient<{
job: typeof job;
}, {}, undefined, LinksTypes<readonly [TrpcLink<{
form: JsonForm;
provides: "response";
}, any>]>>>
trpc.job: TrpcQueryUtils<ClientRouter<{
start: BuildProcedure<InputDef<RootDef<Context, {}>, z.ZodObject<{
size: z.ZodNumber;
}, z.core.$strip>>, "mutation", {
output: {
id: string;
};
errors: never;
services: never;
unmapped: never;
}>;
progress: BuildProcedure<InputDef<RootDef<Context, {}>, z.ZodObject<{
id: z.ZodString;
}, z.core.$strip>>, "subscription", {
output: TrackedEnvelope<Step>;
errors: never;
services: never;
}>;
cancel: BuildProcedure<InputDef<RootDef<Context, {}>, z.ZodObject<...>>, "mutation", {
...;
}>;
}, {}, undefined, LinksTypes<...>>>
job.progress: SubscriptionProcedureUtils<{
id: string;
}, {
readonly id: string;
readonly data: {
id: string;
done: number;
};
}, NonNullable<UnexpectedError | (TrpcError<"BAD_REQUEST", InputValidationErrorData<{
readonly code: "unrecognized_keys";
readonly keys: readonly string[];
readonly path: readonly [] | readonly ["id"];
readonly message: string;
} | {
readonly code: "invalid_type";
readonly expected: z.core.$ZodInvalidTypeExpected;
readonly path: readonly [] | readonly ["id"];
readonly message: string;
} | {
readonly code: "too_big";
readonly origin: "number" | "int" | "bigint" | "date" | "string" | "array" | "set" | "file" | (string & {});
... 4 more ...;
readonly message: string;
} | ... 8 more ... | {
...;
}>> & {
...;
})>, Omit<...>>
progress.SubscriptionProcedureUtils<{ id: string; }, { readonly id: string; readonly data: { id: string; done: number; }; }, NonNullable<UnexpectedError | (TrpcError<"BAD_REQUEST", InputValidationErrorData<{ readonly code: "unrecognized_keys"; readonly keys: readonly string[]; readonly path: readonly [] | readonly [...]; readonly message: string; } | ... 10 more ... | { ...; }>> & { ...; })>, Omit<...>>.subscriptionOptions(opts: {
input: {
id: string;
} | typeof skipToken;
} & ContextBag<Omit<NonNullable<{
signal?: AbortSignal | undefined;
} & BuiltinCallOptions & {} & {
lastEventId?: string | undefined;
}>, "signal" | "lastEventId">> & {
enabled?: boolean | undefined;
} & SubscriptionCallbacks<{
readonly id: string;
readonly data: {
id: string;
done: number;
};
}, NonNullable<UnexpectedError | (TrpcError<"BAD_REQUEST", InputValidationErrorData<{
readonly code: "unrecognized_keys";
readonly keys: readonly string[];
readonly path: readonly [] | readonly ["id"];
readonly message: string;
} | ... 10 more ... | {
...;
}>> & {
...;
})>>): TrpcSubscriptionOptions<...>
subscriptionOptions({
input: {
id: string;
} | typeof skipToken
input: const start: UseMutationResult<{
id: string;
}, (TrpcError<"BAD_REQUEST", InputValidationErrorData<{
readonly code: "unrecognized_keys";
readonly keys: readonly string[];
readonly path: readonly [] | readonly ["size"];
readonly message: string;
} | {
readonly code: "invalid_type";
readonly expected: z.core.$ZodInvalidTypeExpected;
readonly path: readonly [] | readonly ["size"];
readonly message: string;
} | {
readonly code: "too_big";
readonly origin: "number" | "int" | "bigint" | "date" | "string" | "array" | "set" | "file" | (string & {});
readonly maximum: string | number;
readonly inclusive?: boolean | undefined;
readonly exact?: boolean | undefined;
readonly path: readonly [] | readonly [...];
readonly message: string;
} | ... 8 more ... | {
...;
}>> & {
...;
}) | (TrpcError<...> & {
...;
}), {
...;
}, undefined>
start.data: {
id: string;
} | undefined
data ? { id: stringid: const start: Override<MutationObserverSuccessResult<{
id: string;
}, (TrpcError<"BAD_REQUEST", InputValidationErrorData<{
readonly code: "unrecognized_keys";
readonly keys: readonly string[];
readonly path: readonly [] | readonly ["size"];
readonly message: string;
} | {
readonly code: "invalid_type";
readonly expected: z.core.$ZodInvalidTypeExpected;
readonly path: readonly [] | readonly ["size"];
readonly message: string;
} | {
readonly code: "too_big";
readonly origin: "number" | "int" | "bigint" | "date" | "string" | "array" | "set" | "file" | (string & {});
readonly maximum: string | number;
readonly inclusive?: boolean | undefined;
readonly exact?: boolean | undefined;
readonly path: readonly [] | readonly [...];
readonly message: string;
} | ... 8 more ... | {
...;
}>> & {
...;
}) | (TrpcError<...> & {
...;
}), {
...;
}, undefined>, {
...;
}> & {
...;
}
start.data: {
id: string;
}
data.id: stringid } : const skipToken: typeof skipTokenskipToken,
}),
);Unsubscribing stops watching, not the job. Keep jobs in a Publisher so any instance can stream them.