Skip to content

tRPC v12 isn’t on npm yet. The @trpc12/* packages on this site can’t be installed until it’s released. Use v11 today

tRPC

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<"PARSE_ERROR", undefined> & {
    readonly defined: false;
}) | (TrpcError<"BAD_REQUEST", undefined> & {
    readonly defined: false;
}) | (TrpcError<"UNSUPPORTED_PROTOCOL", undefined> & {
    readonly defined: false;
}) | (TrpcError<"UNAUTHORIZED", undefined> & {
    readonly defined: false;
}) | (TrpcError<"PAYMENT_REQUIRED", undefined> & {
    readonly defined: false;
}) | (TrpcError<"FORBIDDEN", undefined> & {
    readonly defined: false;
}) | (TrpcError<"NOT_FOUND", undefined> & {
    readonly defined: false;
}) | ... 18 more ... | (TrpcError<...> & {
    ...;
}), {
    ...;
}, undefined>
send
=
useMutation<("ok" | "hi")[], (TrpcError<"PARSE_ERROR", undefined> & {
    readonly defined: false;
}) | (TrpcError<"BAD_REQUEST", undefined> & {
    readonly defined: false;
}) | (TrpcError<"UNSUPPORTED_PROTOCOL", undefined> & {
    readonly defined: false;
}) | (TrpcError<"UNAUTHORIZED", undefined> & {
    readonly defined: false;
}) | (TrpcError<"PAYMENT_REQUIRED", undefined> & {
    readonly defined: false;
}) | (TrpcError<"FORBIDDEN", undefined> & {
    readonly defined: false;
}) | (TrpcError<"NOT_FOUND", undefined> & {
    readonly defined: false;
}) | ... 18 more ... | (TrpcError<...> & {
    ...;
}), {
    ...;
}, undefined>(options: UseMutationOptions<...>, queryClient?: QueryClient): UseMutationResult<...>
useMutation
(
const trpc: TrpcQueryUtils<TrpcClient<{
    chat: {
        send: Procedure<{
            type: "mutation";
            ctx: Context;
            meta: {};
            input: {
                text: string;
            };
            output: AsyncGenerator<"ok" | "hi", void, unknown>;
            errors: SchemaValidationError<z.ZodObject<{
                text: z.ZodString;
            }, z.core.$strip>>;
            services: never;
        }>;
    };
}, {}, undefined, LinksTypes<readonly [TrpcLink<{
    form: JsonForm;
    provides: "response";
}, any>]>>>
trpc
.
chat: TrpcQueryUtils<ClientRouter<{
    send: Procedure<{
        type: "mutation";
        ctx: Context;
        meta: {};
        input: {
            text: string;
        };
        output: AsyncGenerator<"ok" | "hi", void, unknown>;
        errors: SchemaValidationError<z.ZodObject<{
            text: z.ZodString;
        }, z.core.$strip>>;
        services: never;
    }>;
}, {}, undefined, LinksTypes<readonly [TrpcLink<{
    form: JsonForm;
    provides: "response";
}, any>]>>>
chat
.
send: MutationProcedureUtils<{
    ...;
}, AsyncIterable<...>, NonNullable<...>, Omit<...>>
send
.
MutationProcedureUtils<{ text: string; }, AsyncIterable<"ok" | "hi">, NonNullable<(TrpcError<"PARSE_ERROR", undefined> & { readonly defined: false; }) | ... 24 more ... | (TrpcError<...> & { ...; })>, Omit<...>>.streamedMutationOptions<undefined>(opts?: (ContextBag<Omit<NonNullable<{
    signal?: AbortSignal | undefined;
} & BuiltinCallOptions & {}>, "signal" | "lastEventId">> & StreamedMutationOptions<"ok" | "hi", {
    text: string;
}> & MutationOptionsIn<{
    text: string;
}, ("ok" | "hi")[], NonNullable<(TrpcError<"PARSE_ERROR", undefined> & {
    readonly defined: false;
}) | (TrpcError<"BAD_REQUEST", undefined> & {
    readonly defined: false;
}) | (TrpcError<"UNSUPPORTED_PROTOCOL", undefined> & {
    readonly defined: false;
}) | ... 22 more ... | (TrpcError<...> & {
    ...;
})>, undefined>) | undefined): MutationOptionsOut<...>
streamedMutationOptions
());
const
const chunks: UseQueryResult<("ok" | "hi")[], NonNullable<(TrpcError<"PARSE_ERROR", undefined> & {
    readonly defined: false;
}) | (TrpcError<"BAD_REQUEST", undefined> & {
    readonly defined: false;
}) | (TrpcError<"UNSUPPORTED_PROTOCOL", undefined> & {
    readonly defined: false;
}) | (TrpcError<"UNAUTHORIZED", undefined> & {
    readonly defined: false;
}) | (TrpcError<"PAYMENT_REQUIRED", undefined> & {
    readonly defined: false;
}) | (TrpcError<"FORBIDDEN", undefined> & {
    readonly defined: false;
}) | (TrpcError<"NOT_FOUND", undefined> & {
    readonly defined: false;
}) | ... 18 more ... | (TrpcError<...> & {
    ...;
})>>
chunks
=
useQuery<("ok" | "hi")[], NonNullable<(TrpcError<"PARSE_ERROR", undefined> & {
    readonly defined: false;
}) | (TrpcError<"BAD_REQUEST", undefined> & {
    readonly defined: false;
}) | (TrpcError<"UNSUPPORTED_PROTOCOL", undefined> & {
    readonly defined: false;
}) | (TrpcError<"UNAUTHORIZED", undefined> & {
    readonly defined: false;
}) | (TrpcError<"PAYMENT_REQUIRED", undefined> & {
    readonly defined: false;
}) | (TrpcError<"FORBIDDEN", undefined> & {
    readonly defined: false;
}) | (TrpcError<"NOT_FOUND", undefined> & {
    readonly defined: false;
}) | ... 18 more ... | (TrpcError<...> & {
    ...;
})>, ("ok" | "hi")[], TrpcQueryKey & {
    ...;
}>(options: UndefinedInitialDataOptions<...>, queryClient?: QueryClient): UseQueryResult<...> (+2 overloads)
useQuery
(
const trpc: TrpcQueryUtils<TrpcClient<{
    chat: {
        send: Procedure<{
            type: "mutation";
            ctx: Context;
            meta: {};
            input: {
                text: string;
            };
            output: AsyncGenerator<"ok" | "hi", void, unknown>;
            errors: SchemaValidationError<z.ZodObject<{
                text: z.ZodString;
            }, z.core.$strip>>;
            services: never;
        }>;
    };
}, {}, undefined, LinksTypes<readonly [TrpcLink<{
    form: JsonForm;
    provides: "response";
}, any>]>>>
trpc
.
chat: TrpcQueryUtils<ClientRouter<{
    send: Procedure<{
        type: "mutation";
        ctx: Context;
        meta: {};
        input: {
            text: string;
        };
        output: AsyncGenerator<"ok" | "hi", void, unknown>;
        errors: SchemaValidationError<z.ZodObject<{
            text: z.ZodString;
        }, z.core.$strip>>;
        services: never;
    }>;
}, {}, undefined, LinksTypes<readonly [TrpcLink<{
    form: JsonForm;
    provides: "response";
}, any>]>>>
chat
.
send: MutationProcedureUtils<{
    ...;
}, AsyncIterable<...>, NonNullable<...>, Omit<...>>
send
.
MutationProcedureUtils<{ text: string; }, AsyncIterable<"ok" | "hi">, NonNullable<(TrpcError<"PARSE_ERROR", undefined> & { readonly defined: false; }) | (TrpcError<"BAD_REQUEST", undefined> & { readonly defined: false; }) | ... 23 more ... | (TrpcError<...> & { ...; })>, Omit<...>>.chunksOptions<("ok" | "hi")[]>(opts?: Omit<QueryOptionsIn<("ok" | "hi")[], NonNullable<(TrpcError<"PARSE_ERROR", undefined> & {
    readonly defined: false;
}) | (TrpcError<"BAD_REQUEST", undefined> & {
    readonly defined: false;
}) | (TrpcError<"UNSUPPORTED_PROTOCOL", undefined> & {
    readonly defined: false;
}) | (TrpcError<"UNAUTHORIZED", undefined> & {
    readonly defined: false;
}) | (TrpcError<"PAYMENT_REQUIRED", undefined> & {
    readonly defined: false;
}) | (TrpcError<"FORBIDDEN", undefined> & {
    readonly defined: false;
}) | ... 19 more ... | (TrpcError<...> & {
    ...;
})>, ("ok" | "hi")[]>, "enabled"> | undefined): QueryOptionsOut<...>
chunksOptions
());
const send: UseMutationResult<("ok" | "hi")[], (TrpcError<"PARSE_ERROR", undefined> & {
    readonly defined: false;
}) | (TrpcError<"BAD_REQUEST", undefined> & {
    readonly defined: false;
}) | (TrpcError<"UNSUPPORTED_PROTOCOL", undefined> & {
    readonly defined: false;
}) | (TrpcError<"UNAUTHORIZED", undefined> & {
    readonly defined: false;
}) | (TrpcError<"PAYMENT_REQUIRED", undefined> & {
    readonly defined: false;
}) | (TrpcError<"FORBIDDEN", undefined> & {
    readonly defined: false;
}) | (TrpcError<"NOT_FOUND", undefined> & {
    readonly defined: false;
}) | ... 18 more ... | (TrpcError<...> & {
    ...;
}), {
    ...;
}, undefined>
send
.
mutate: (variables: {
    text: string;
}, options?: MutateOptions<("ok" | "hi")[], (TrpcError<"PARSE_ERROR", undefined> & {
    readonly defined: false;
}) | (TrpcError<"BAD_REQUEST", undefined> & {
    readonly defined: false;
}) | (TrpcError<"UNSUPPORTED_PROTOCOL", undefined> & {
    readonly defined: false;
}) | (TrpcError<"UNAUTHORIZED", undefined> & {
    readonly defined: false;
}) | (TrpcError<"PAYMENT_REQUIRED", undefined> & {
    readonly defined: false;
}) | (TrpcError<"FORBIDDEN", undefined> & {
    readonly defined: false;
}) | ... 19 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: Procedure<{
            type: "mutation";
            ctx: Context;
            meta: {};
            input: {
                text: string;
            };
            output: AsyncGenerator<string, void, unknown>;
            errors: SchemaValidationError<z.ZodObject<{
                text: z.ZodString;
            }, z.core.$strip>>;
            services: never;
        }>;
    };
}, {}, undefined, LinksTypes<readonly [TrpcLink<{
    form: JsonForm;
    provides: "response";
}, any>]>>>
trpc
.
chat: TrpcQueryUtils<ClientRouter<{
    send: Procedure<{
        type: "mutation";
        ctx: Context;
        meta: {};
        input: {
            text: string;
        };
        output: AsyncGenerator<string, void, unknown>;
        errors: SchemaValidationError<z.ZodObject<{
            text: z.ZodString;
        }, z.core.$strip>>;
        services: never;
    }>;
}, {}, undefined, LinksTypes<readonly [TrpcLink<{
    form: JsonForm;
    provides: "response";
}, any>]>>>
chat
.
send: MutationProcedureUtils<{
    text: string;
}, AsyncIterable<string>, NonNullable<(TrpcError<"PARSE_ERROR", undefined> & {
    readonly defined: false;
}) | (TrpcError<"BAD_REQUEST", undefined> & {
    readonly defined: false;
}) | (TrpcError<"UNSUPPORTED_PROTOCOL", undefined> & {
    readonly defined: false;
}) | (TrpcError<"UNAUTHORIZED", undefined> & {
    readonly defined: false;
}) | (TrpcError<"PAYMENT_REQUIRED", undefined> & {
    readonly defined: false;
}) | (TrpcError<"FORBIDDEN", undefined> & {
    readonly defined: false;
}) | ... 19 more ... | (TrpcError<...> & {
    ...;
})>, Omit<...>>
send
.
MutationProcedureUtils<{ text: string; }, AsyncIterable<string>, NonNullable<(TrpcError<"PARSE_ERROR", undefined> & { readonly defined: false; }) | (TrpcError<...> & { readonly defined: false; }) | ... 23 more ... | (TrpcError<...> & { ...; })>, Omit<...>>.streamedMutationOptions<unknown>(opts?: (ContextBag<Omit<NonNullable<{
    signal?: AbortSignal | undefined;
} & BuiltinCallOptions & {}>, "signal" | "lastEventId">> & StreamedMutationOptions<string, {
    text: string;
}> & MutationOptionsIn<{
    text: string;
}, string[], NonNullable<(TrpcError<"PARSE_ERROR", undefined> & {
    readonly defined: false;
}) | (TrpcError<"BAD_REQUEST", undefined> & {
    readonly defined: false;
}) | (TrpcError<"UNSUPPORTED_PROTOCOL", undefined> & {
    readonly defined: false;
}) | ... 22 more ... | (TrpcError<...> & {
    ...;
})>, 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: Procedure<{
            type: "mutation";
            ctx: Context;
            meta: {};
            input: {
                text: string;
            };
            output: AsyncGenerator<string, void, unknown>;
            errors: SchemaValidationError<z.ZodObject<{
                text: z.ZodString;
            }, z.core.$strip>>;
            services: never;
        }>;
    };
}, {}, undefined, LinksTypes<readonly [TrpcLink<{
    form: JsonForm;
    provides: "response";
}, any>]>>>
trpc
.
chat: TrpcQueryUtils<ClientRouter<{
    send: Procedure<{
        type: "mutation";
        ctx: Context;
        meta: {};
        input: {
            text: string;
        };
        output: AsyncGenerator<string, void, unknown>;
        errors: SchemaValidationError<z.ZodObject<{
            text: z.ZodString;
        }, z.core.$strip>>;
        services: never;
    }>;
}, {}, undefined, LinksTypes<readonly [TrpcLink<{
    form: JsonForm;
    provides: "response";
}, any>]>>>
chat
.
send: MutationProcedureUtils<{
    text: string;
}, AsyncIterable<string>, NonNullable<(TrpcError<"PARSE_ERROR", undefined> & {
    readonly defined: false;
}) | (TrpcError<"BAD_REQUEST", undefined> & {
    readonly defined: false;
}) | (TrpcError<"UNSUPPORTED_PROTOCOL", undefined> & {
    readonly defined: false;
}) | (TrpcError<"UNAUTHORIZED", undefined> & {
    readonly defined: false;
}) | (TrpcError<"PAYMENT_REQUIRED", undefined> & {
    readonly defined: false;
}) | (TrpcError<"FORBIDDEN", undefined> & {
    readonly defined: false;
}) | ... 19 more ... | (TrpcError<...> & {
    ...;
})>, Omit<...>>
send
.
MutationProcedureUtils<{ text: string; }, AsyncIterable<string>, NonNullable<(TrpcError<"PARSE_ERROR", undefined> & { readonly defined: false; }) | (TrpcError<...> & { readonly defined: false; }) | ... 23 more ... | (TrpcError<...> & { ...; })>, Omit<...>>.streamedMutationOptions<unknown>(opts?: (ContextBag<Omit<NonNullable<{
    signal?: AbortSignal | undefined;
} & BuiltinCallOptions & {}>, "signal" | "lastEventId">> & StreamedMutationOptions<string, {
    text: string;
}> & MutationOptionsIn<{
    text: string;
}, string[], NonNullable<(TrpcError<"PARSE_ERROR", undefined> & {
    readonly defined: false;
}) | (TrpcError<"BAD_REQUEST", undefined> & {
    readonly defined: false;
}) | (TrpcError<"UNSUPPORTED_PROTOCOL", undefined> & {
    readonly defined: false;
}) | ... 22 more ... | (TrpcError<...> & {
    ...;
})>, 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: Procedure<{
        type: "mutation";
        ctx: Context;
        meta: {};
        input: {
            size: number;
        };
        output: {
            id: string;
        };
        errors: SchemaValidationError<z.ZodObject<{
            size: z.ZodNumber;
        }, z.core.$strip>>;
        services: never;
    }>;
    progress: Procedure<{
        type: "subscription";
        ctx: Context;
        meta: {};
        input: {
            id: string;
        };
        output: TrackedEnvelope<Step>;
        errors: SchemaValidationError<z.ZodObject<{
            id: z.ZodString;
        }, z.core.$strip>>;
        services: never;
    }>;
    cancel: Procedure<...>;
}
job
= {
start: Procedure<{
    type: "mutation";
    ctx: Context;
    meta: {};
    input: {
        size: number;
    };
    output: {
        id: string;
    };
    errors: SchemaValidationError<z.ZodObject<{
        size: z.ZodNumber;
    }, z.core.$strip>>;
    services: 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;
}>): Procedure<{
    type: "mutation";
    ctx: Context;
    meta: {};
    input: {
        size: number;
    };
    output: {
        id: string;
    };
    errors: SchemaValidationError<z.ZodObject<{
        size: z.ZodNumber;
    }, z.core.$strip>>;
    services: 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: Procedure<{
    type: "subscription";
    ctx: Context;
    meta: {};
    input: {
        id: string;
    };
    output: TrackedEnvelope<Step>;
    errors: SchemaValidationError<z.ZodObject<{
        id: z.ZodString;
    }, z.core.$strip>>;
    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>): Procedure<{
    type: "subscription";
    ctx: Context;
    meta: {};
    input: {
        id: string;
    };
    output: TrackedEnvelope<Step>;
    errors: SchemaValidationError<z.ZodObject<{
        id: z.ZodString;
    }, z.core.$strip>>;
    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: Procedure<{
    type: "mutation";
    ctx: Context;
    meta: {};
    input: {
        id: string;
    };
    output: void;
    errors: SchemaValidationError<z.ZodObject<{
        id: z.ZodString;
    }, z.core.$strip>>;
    services: 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>): Procedure<{
    type: "mutation";
    ctx: Context;
    meta: {};
    input: {
        id: string;
    };
    output: void;
    errors: SchemaValidationError<z.ZodObject<{
        id: z.ZodString;
    }, z.core.$strip>>;
    services: 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", undefined> & {
    readonly defined: false;
}) | (TrpcError<"PARSE_ERROR", undefined> & {
    readonly defined: false;
}) | (TrpcError<"UNSUPPORTED_PROTOCOL", undefined> & {
    readonly defined: false;
}) | (TrpcError<"UNAUTHORIZED", undefined> & {
    readonly defined: false;
}) | (TrpcError<"PAYMENT_REQUIRED", undefined> & {
    readonly defined: false;
}) | (TrpcError<"FORBIDDEN", undefined> & {
    readonly defined: false;
}) | (TrpcError<"NOT_FOUND", undefined> & {
    readonly defined: false;
}) | ... 18 more ... | (TrpcError<...> & {
    ...;
}), {
    ...;
}, undefined>
start
=
useMutation<{
    id: string;
}, (TrpcError<"BAD_REQUEST", undefined> & {
    readonly defined: false;
}) | (TrpcError<"PARSE_ERROR", undefined> & {
    readonly defined: false;
}) | (TrpcError<"UNSUPPORTED_PROTOCOL", undefined> & {
    readonly defined: false;
}) | (TrpcError<"UNAUTHORIZED", undefined> & {
    readonly defined: false;
}) | (TrpcError<"PAYMENT_REQUIRED", undefined> & {
    readonly defined: false;
}) | (TrpcError<"FORBIDDEN", undefined> & {
    readonly defined: false;
}) | (TrpcError<"NOT_FOUND", undefined> & {
    readonly defined: false;
}) | ... 18 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: Procedure<{
        type: "mutation";
        ctx: Context;
        meta: {};
        input: {
            size: number;
        };
        output: {
            id: string;
        };
        errors: SchemaValidationError<z.ZodObject<{
            size: z.ZodNumber;
        }, z.core.$strip>>;
        services: never;
    }>;
    progress: Procedure<{
        type: "subscription";
        ctx: Context;
        meta: {};
        input: {
            id: string;
        };
        output: TrackedEnvelope<Step>;
        errors: SchemaValidationError<z.ZodObject<{
            id: z.ZodString;
        }, z.core.$strip>>;
        services: never;
    }>;
    cancel: Procedure<...>;
}, {}, undefined, LinksTypes<...>>>
job
.
start: MutationProcedureUtils<{
    ...;
}, {
    id: string;
}, NonNullable<...>, Omit<...>>
start
.
MutationProcedureUtils<{ size: number; }, { id: string; }, NonNullable<(TrpcError<"BAD_REQUEST", undefined> & { readonly defined: false; }) | (TrpcError<"PARSE_ERROR", undefined> & { readonly defined: false; }) | ... 23 more ... | (TrpcError<...> & { ...; })>, Omit<...>>.mutationOptions<undefined>(opts?: (ContextBag<Omit<NonNullable<{
    signal?: AbortSignal | undefined;
} & BuiltinCallOptions & {}>, "signal" | "lastEventId">> & MutationOptionsIn<{
    size: number;
}, {
    id: string;
}, NonNullable<(TrpcError<"BAD_REQUEST", undefined> & {
    readonly defined: false;
}) | (TrpcError<"PARSE_ERROR", undefined> & {
    readonly defined: false;
}) | (TrpcError<"UNSUPPORTED_PROTOCOL", undefined> & {
    readonly defined: false;
}) | (TrpcError<"UNAUTHORIZED", undefined> & {
    readonly defined: false;
}) | ... 21 more ... | (TrpcError<...> & {
    ...;
})>, undefined>) | undefined): MutationOptionsOut<...>
mutationOptions
());
const
const progress: UseSubscriptionResult<{
    readonly id: string;
    readonly data: {
        id: string;
        done: number;
    };
}, NonNullable<(TrpcError<"BAD_REQUEST", undefined> & {
    readonly defined: false;
}) | (TrpcError<"PARSE_ERROR", undefined> & {
    readonly defined: false;
}) | (TrpcError<"UNSUPPORTED_PROTOCOL", undefined> & {
    readonly defined: false;
}) | (TrpcError<"UNAUTHORIZED", undefined> & {
    readonly defined: false;
}) | (TrpcError<"PAYMENT_REQUIRED", undefined> & {
    readonly defined: false;
}) | (TrpcError<"FORBIDDEN", undefined> & {
    readonly defined: false;
}) | ... 19 more ... | (TrpcError<...> & {
    ...;
})>>
progress
=
useSubscription<{
    readonly id: string;
    readonly data: {
        id: string;
        done: number;
    };
}, NonNullable<(TrpcError<"BAD_REQUEST", undefined> & {
    readonly defined: false;
}) | (TrpcError<"PARSE_ERROR", undefined> & {
    readonly defined: false;
}) | (TrpcError<"UNSUPPORTED_PROTOCOL", undefined> & {
    readonly defined: false;
}) | (TrpcError<"UNAUTHORIZED", undefined> & {
    readonly defined: false;
}) | (TrpcError<"PAYMENT_REQUIRED", undefined> & {
    readonly defined: false;
}) | (TrpcError<"FORBIDDEN", undefined> & {
    readonly defined: false;
}) | ... 19 more ... | (TrpcError<...> & {
    ...;
})>>(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: Procedure<{
        type: "mutation";
        ctx: Context;
        meta: {};
        input: {
            size: number;
        };
        output: {
            id: string;
        };
        errors: SchemaValidationError<z.ZodObject<{
            size: z.ZodNumber;
        }, z.core.$strip>>;
        services: never;
    }>;
    progress: Procedure<{
        type: "subscription";
        ctx: Context;
        meta: {};
        input: {
            id: string;
        };
        output: TrackedEnvelope<Step>;
        errors: SchemaValidationError<z.ZodObject<{
            id: z.ZodString;
        }, z.core.$strip>>;
        services: never;
    }>;
    cancel: Procedure<...>;
}, {}, undefined, LinksTypes<...>>>
job
.
progress: SubscriptionProcedureUtils<{
    id: string;
}, {
    readonly id: string;
    readonly data: {
        id: string;
        done: number;
    };
}, NonNullable<(TrpcError<"BAD_REQUEST", undefined> & {
    readonly defined: false;
}) | (TrpcError<"PARSE_ERROR", undefined> & {
    readonly defined: false;
}) | (TrpcError<"UNSUPPORTED_PROTOCOL", undefined> & {
    readonly defined: false;
}) | (TrpcError<"UNAUTHORIZED", undefined> & {
    readonly defined: false;
}) | (TrpcError<"PAYMENT_REQUIRED", undefined> & {
    readonly defined: false;
}) | (TrpcError<"FORBIDDEN", undefined> & {
    readonly defined: false;
}) | ... 19 more ... | (TrpcError<...> & {
    ...;
})>, Omit<...>>
progress
.
SubscriptionProcedureUtils<{ id: string; }, { readonly id: string; readonly data: { id: string; done: number; }; }, NonNullable<(TrpcError<"BAD_REQUEST", undefined> & { readonly defined: false; }) | ... 24 more ... | (TrpcError<...> & { ...; })>, 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<(TrpcError<"BAD_REQUEST", undefined> & {
    readonly defined: false;
}) | (TrpcError<"PARSE_ERROR", undefined> & {
    readonly defined: false;
}) | ... 23 more ... | (TrpcError<...> & {
    ...;
})>>): TrpcSubscriptionOptions<...>
subscriptionOptions
({
input: {
    id: string;
} | typeof skipToken
input
:
const start: UseMutationResult<{
    id: string;
}, (TrpcError<"BAD_REQUEST", undefined> & {
    readonly defined: false;
}) | (TrpcError<"PARSE_ERROR", undefined> & {
    readonly defined: false;
}) | (TrpcError<"UNSUPPORTED_PROTOCOL", undefined> & {
    readonly defined: false;
}) | (TrpcError<"UNAUTHORIZED", undefined> & {
    readonly defined: false;
}) | (TrpcError<"PAYMENT_REQUIRED", undefined> & {
    readonly defined: false;
}) | (TrpcError<"FORBIDDEN", undefined> & {
    readonly defined: false;
}) | (TrpcError<"NOT_FOUND", undefined> & {
    readonly defined: false;
}) | ... 18 more ... | (TrpcError<...> & {
    ...;
}), {
    ...;
}, undefined>
start
.
data: {
    id: string;
} | undefined
data
? { id: stringid:
const start: Override<MutationObserverSuccessResult<{
    id: string;
}, (TrpcError<"BAD_REQUEST", undefined> & {
    readonly defined: false;
}) | (TrpcError<"PARSE_ERROR", undefined> & {
    readonly defined: false;
}) | (TrpcError<"UNSUPPORTED_PROTOCOL", undefined> & {
    readonly defined: false;
}) | (TrpcError<"UNAUTHORIZED", undefined> & {
    readonly defined: false;
}) | (TrpcError<"PAYMENT_REQUIRED", undefined> & {
    readonly defined: false;
}) | (TrpcError<"FORBIDDEN", undefined> & {
    readonly defined: false;
}) | (TrpcError<"NOT_FOUND", undefined> & {
    readonly defined: false;
}) | ... 18 more ... | (TrpcError<...> & {
    ...;
}), {
    ...;
}, undefined>, {
    ...;
}> & {
    ...;
}
start
.
data: {
    id: string;
}
data
.id: stringid } : const skipToken: typeof skipTokenskipToken,
}), );

Unsubscribing stops watching, not the job.