@fitzzero/quickdraw-core 5.1.1 → 5.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +533 -180
- package/dist/{admin-DKwkIh5i.d.ts → admin-DWWrT1h6.d.ts} +2 -2
- package/dist/{adminSchemas-2DUA_hZ8.d.ts → adminSchemas-D4bFKsrb.d.ts} +6 -4
- package/dist/{auth-BhWqdyb-.d.ts → auth-DXiSJZaf.d.ts} +42 -16
- package/dist/{caller-CXTFswBO.d.ts → caller-BT-Mv4bD.d.ts} +117 -22
- package/dist/{chunk-RT6OILOI.js → chunk-4D2DOGAW.js} +2 -14
- package/dist/chunk-4D2DOGAW.js.map +1 -0
- package/dist/chunk-5CGO426C.js +15 -0
- package/dist/chunk-5CGO426C.js.map +1 -0
- package/dist/{chunk-RZTP4IEW.js → chunk-6K5BY47X.js} +4594 -3481
- package/dist/chunk-6K5BY47X.js.map +1 -0
- package/dist/{chunk-VSQBHPWH.js → chunk-753VJIUP.js} +13 -15
- package/dist/chunk-753VJIUP.js.map +1 -0
- package/dist/{chunk-ZIVPHYRG.js → chunk-7QCUX4TK.js} +4 -4
- package/dist/chunk-7QCUX4TK.js.map +1 -0
- package/dist/chunk-AK23XSWD.js +16 -0
- package/dist/chunk-AK23XSWD.js.map +1 -0
- package/dist/{chunk-SHEGLZEP.js → chunk-AONAFOYU.js} +14 -5
- package/dist/{chunk-SHEGLZEP.js.map → chunk-AONAFOYU.js.map} +1 -1
- package/dist/chunk-DKE6QO26.js +136 -0
- package/dist/chunk-DKE6QO26.js.map +1 -0
- package/dist/{chunk-H23KEFBA.js → chunk-DUBU3BB3.js} +30 -1
- package/dist/chunk-DUBU3BB3.js.map +1 -0
- package/dist/{chunk-CDKG4TFA.js → chunk-GKH3LJ7N.js} +1 -1
- package/dist/chunk-GKH3LJ7N.js.map +1 -0
- package/dist/{chunk-OECZPRPW.js → chunk-GSIPUNJL.js} +49 -9
- package/dist/chunk-GSIPUNJL.js.map +1 -0
- package/dist/{chunk-DD4SKCNO.js → chunk-LCC7HNFP.js} +12 -1
- package/dist/chunk-LCC7HNFP.js.map +1 -0
- package/dist/{chunk-2PWMUVC7.js → chunk-MBH6IDSM.js} +480 -12
- package/dist/chunk-MBH6IDSM.js.map +1 -0
- package/dist/{chunk-QCHKWIRS.js → chunk-NMXYENH4.js} +10 -10
- package/dist/{chunk-QCHKWIRS.js.map → chunk-NMXYENH4.js.map} +1 -1
- package/dist/chunk-NO4M6PO5.js +101 -0
- package/dist/chunk-NO4M6PO5.js.map +1 -0
- package/dist/{chunk-TBMKJ26R.js → chunk-NW6U45HX.js} +3 -1
- package/dist/chunk-NW6U45HX.js.map +1 -0
- package/dist/{chunk-REX5YPHX.js → chunk-RJ5I2VO3.js} +74 -19
- package/dist/chunk-RJ5I2VO3.js.map +1 -0
- package/dist/{chunk-QEKVYG5F.js → chunk-RL4VKLBX.js} +1 -1
- package/dist/{chunk-QEKVYG5F.js.map → chunk-RL4VKLBX.js.map} +1 -1
- package/dist/chunk-XH2IZVLT.js +62 -0
- package/dist/chunk-XH2IZVLT.js.map +1 -0
- package/dist/{chunk-4DIQHASK.js → chunk-Z5ILULF2.js} +26 -7
- package/dist/chunk-Z5ILULF2.js.map +1 -0
- package/dist/cli/quickdraw-docs.js +5 -3
- package/dist/cli/quickdraw-docs.js.map +1 -1
- package/dist/client/index.d.ts +30 -18
- package/dist/client/index.js +8 -6
- package/dist/client/index.js.map +1 -1
- package/dist/{clientTypes-Bc-G8n-U.d.ts → clientTypes-hWcPUVS9.d.ts} +3 -3
- package/dist/{connection-Cr1BU07W.d.ts → connection-CgijdGpT.d.ts} +8 -4
- package/dist/{createServer-CP9eDHZZ.d.ts → createServer-Cp-Wk500.d.ts} +36 -14
- package/dist/{createTestApp-UKVGEmOf.d.ts → createTestApp-BB_PkqQ7.d.ts} +16 -10
- package/dist/{envelope-Cp3YcVxC.d.ts → envelope-DzWyIXjj.d.ts} +18 -4
- package/dist/{http-Djj2Inuu.d.ts → http-DotQ5bj8.d.ts} +68 -17
- package/dist/index.d.ts +7 -7
- package/dist/index.js +37 -13
- package/dist/index.js.map +1 -1
- package/dist/{infer-Teo1xpsd.d.ts → infer-BmoZsL9a.d.ts} +43 -10
- package/dist/logger-Yz93KzdV.d.ts +30 -0
- package/dist/{metrics-BdBu5o8G.d.ts → metrics-DW80Exve.d.ts} +2 -2
- package/dist/origins-kvpxnVcW.d.ts +8 -0
- package/dist/prisma/index.d.ts +5 -5
- package/dist/prisma/index.js +130 -67
- package/dist/prisma/index.js.map +1 -1
- package/dist/{rateLimit-ZMIZJUZF.js → rateLimit-5RKBFLUR.js} +2 -2
- package/dist/server/auth/index.d.ts +82 -33
- package/dist/server/auth/index.js +273 -268
- package/dist/server/auth/index.js.map +1 -1
- package/dist/server/express/index.d.ts +9 -2
- package/dist/server/express/index.js +1 -1
- package/dist/server/index.d.ts +147 -67
- package/dist/server/index.js +520 -381
- package/dist/server/index.js.map +1 -1
- package/dist/server/mcp/index.d.ts +63 -17
- package/dist/server/mcp/index.js +256 -54
- package/dist/server/mcp/index.js.map +1 -1
- package/dist/server/otel.d.ts +3 -3
- package/dist/{sharing-DVa8W-yR.d.ts → sharing-UDLn1049.d.ts} +3 -3
- package/dist/testing/client.d.ts +14 -14
- package/dist/testing/client.js +9 -7
- package/dist/testing/client.js.map +1 -1
- package/dist/testing/index.d.ts +12 -12
- package/dist/testing/index.js +21 -12
- package/dist/testing/index.js.map +1 -1
- package/dist/testing/mock.d.ts +5 -5
- package/dist/testing/mock.js +8 -6
- package/dist/{types-Cu0vmx7c.d.ts → types-CYliTP65.d.ts} +1 -1
- package/dist/utils/index.d.ts +1 -1
- package/package.json +1 -1
- package/dist/chunk-2PWMUVC7.js.map +0 -1
- package/dist/chunk-4DIQHASK.js.map +0 -1
- package/dist/chunk-CDKG4TFA.js.map +0 -1
- package/dist/chunk-DD4SKCNO.js.map +0 -1
- package/dist/chunk-H23KEFBA.js.map +0 -1
- package/dist/chunk-OECZPRPW.js.map +0 -1
- package/dist/chunk-REX5YPHX.js.map +0 -1
- package/dist/chunk-RT6OILOI.js.map +0 -1
- package/dist/chunk-RZTP4IEW.js.map +0 -1
- package/dist/chunk-TBMKJ26R.js.map +0 -1
- package/dist/chunk-VSQBHPWH.js.map +0 -1
- package/dist/chunk-YSWH776Y.js +0 -13
- package/dist/chunk-YSWH776Y.js.map +0 -1
- package/dist/chunk-ZIVPHYRG.js.map +0 -1
- package/dist/logger-BY28acW-.d.ts +0 -16
- /package/dist/{rateLimit-ZMIZJUZF.js.map → rateLimit-5RKBFLUR.js.map} +0 -0
package/dist/testing/mock.d.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { A as AccessLevel, ae as ContractMap, J as AnyContract, ap as MethodName, al as InputOf, ar as OutputOf, af as EntityOf, ac as CollectionName, aw as ScopeOf, an as ItemOf, az as StreamName, am as IsScopedStream, ay as StreamItemOf, aa as ChannelName, a9 as ChannelInputOf, ag as EventName, ah as EventPayloadOf } from '../infer-
|
|
1
|
+
import { A as AccessLevel, ae as ContractMap, J as AnyContract, ap as MethodName, al as InputOf, ar as OutputOf, af as EntityOf, ac as CollectionName, aw as ScopeOf, an as ItemOf, az as StreamName, am as IsScopedStream, ay as StreamItemOf, aa as ChannelName, a9 as ChannelInputOf, ag as EventName, ah as EventPayloadOf } from '../infer-BmoZsL9a.js';
|
|
2
2
|
import { QueryClient } from '@tanstack/react-query';
|
|
3
3
|
import { ReactNode, ReactElement } from 'react';
|
|
4
|
-
import { i as MethodMember, E as EntityMembers, C as CollectionMember, y as StreamMember, u as ChannelMember, v as EventMember, n as QuickdrawInvalidate } from '../clientTypes-
|
|
5
|
-
import { H as AdminMethodsOf } from '../admin-
|
|
4
|
+
import { i as MethodMember, E as EntityMembers, C as CollectionMember, y as StreamMember, u as ChannelMember, v as EventMember, n as QuickdrawInvalidate } from '../clientTypes-hWcPUVS9.js';
|
|
5
|
+
import { H as AdminMethodsOf } from '../admin-DWWrT1h6.js';
|
|
6
6
|
import { Q as QuickdrawError } from '../errors-S-bxEIBC.js';
|
|
7
7
|
import '../keys-CqKkljVN.js';
|
|
8
|
-
import '../adminSchemas-
|
|
9
|
-
import '../envelope-
|
|
8
|
+
import '../adminSchemas-D4bFKsrb.js';
|
|
9
|
+
import '../envelope-DzWyIXjj.js';
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
12
|
* How a mocked method answers. Until one of the `mock*` setters runs, every
|
package/dist/testing/mock.js
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createMockClient
|
|
3
|
-
} from "../chunk-
|
|
4
|
-
import "../chunk-
|
|
5
|
-
import "../chunk-
|
|
6
|
-
import "../chunk-
|
|
7
|
-
import "../chunk-
|
|
3
|
+
} from "../chunk-AONAFOYU.js";
|
|
4
|
+
import "../chunk-GSIPUNJL.js";
|
|
5
|
+
import "../chunk-GKH3LJ7N.js";
|
|
6
|
+
import "../chunk-753VJIUP.js";
|
|
7
|
+
import "../chunk-5CGO426C.js";
|
|
8
|
+
import "../chunk-4D2DOGAW.js";
|
|
9
|
+
import "../chunk-AK23XSWD.js";
|
|
8
10
|
import "../chunk-47AEXVDM.js";
|
|
9
11
|
import "../chunk-Z2LZ7IZ7.js";
|
|
10
|
-
import "../chunk-
|
|
12
|
+
import "../chunk-DKE6QO26.js";
|
|
11
13
|
import "../chunk-X5CWPX7H.js";
|
|
12
14
|
import "../chunk-4YO5H5ON.js";
|
|
13
15
|
export {
|
package/dist/utils/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { M as MethodQueryKey } from '../keys-CqKkljVN.js';
|
|
2
2
|
export { C as CollectionQueryKey, E as EntityQueryKey, K as KEY_ROOT, b as MethodKeyPrefix, S as ServiceKeyPrefix, c as collectionKey, e as entityKey, m as methodKey, a as methodKeyPrefix, s as serviceKeyPrefix } from '../keys-CqKkljVN.js';
|
|
3
3
|
import { QueryClient } from '@tanstack/react-query';
|
|
4
|
-
import { ae as ContractMap, ap as MethodName, J as AnyContract, ao as KindOf, al as InputOf, ar as OutputOf } from '../infer-
|
|
4
|
+
import { ae as ContractMap, ap as MethodName, J as AnyContract, ao as KindOf, al as InputOf, ar as OutputOf } from '../infer-BmoZsL9a.js';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Format a currency value for display.
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/server/caller.ts","../src/server/pipeline/errors.ts","../src/server/pipeline/schemaOutput.ts","../src/server/pipeline/validation.ts","../src/server/context.ts"],"sourcesContent":["// The in-process caller (RFC 0003 section 10): `caller.taskService.rename(input)`\n// runs the same pipeline as a socket call, with transport `\"internal\"`. Its\n// types come from the contracts: a method takes what a client would pass\n// (`InputOf`) and resolves with what a client would receive (`OutputOf`).\n// A failed call rejects with its `QuickdrawError`; an `INTERNAL` one keeps\n// the original error as `cause`.\n//\n// A caller through a server's dispatcher (`qd.caller`, `server.dispatcher.caller`)\n// gives a principal that carries no `serviceAccess` the grants the server's\n// `auth.loadServiceAccess` loads, as a socket's handshake and an HTTP call\n// do (finding F5.1 of the quickdraw-chat migration: an app's REST route ran\n// its in-process call with no grants at all): once per caller, at its first\n// call, and again after the server applied new grants to a user\n// (`access.refresh`, a written grant, another node's broadcast), as a\n// socket's are refreshed. A principal that carries grants, even `{}`, keeps\n// exactly those.\n\nimport type { AnyContract } from \"../contract/defineContract\";\nimport type { ContractMap, InputOf, MethodName, OutputOf } from \"../contract/infer\";\nimport { INTERNAL_MESSAGE, QuickdrawError } from \"../protocol/errors\";\nimport type { Dispatch } from \"./pipeline/pipeline\";\nimport type { DispatchRequest } from \"./pipeline/request\";\nimport type { ServerAuth } from \"./transports/auth\";\nimport type { Principal, QuickdrawTypes } from \"./types\";\n\n/** Options of one in-process call. */\nexport interface CallOptions {\n /** Cancels the call (queries only), like a client's `qd:cancel`. */\n readonly signal?: AbortSignal;\n}\n\n/** One method of the in-process caller. The input may be left out when the method accepts `undefined`. */\nexport type MethodCaller<C extends AnyContract, M extends MethodName<C>> = (\n ...args: undefined extends InputOf<C, M>\n ? [input?: InputOf<C, M>, options?: CallOptions]\n : [input: InputOf<C, M>, options?: CallOptions]\n) => Promise<OutputOf<C, M>>;\n\n/** The in-process caller of one service: one function per method. */\nexport type ServiceCaller<C extends AnyContract> = {\n readonly [M in MethodName<C>]: MethodCaller<C, M>;\n};\n\n/** The in-process caller of a set of contracts, by service name: `caller.taskService.rename(input)`. */\nexport type Caller<C extends AnyContract> = {\n readonly [Name in C[\"name\"]]: ServiceCaller<Extract<C, { readonly name: Name }>>;\n};\n\n/**\n * The type of `qd.caller(principal)`: typed from the app's `contracts` when\n * `QuickdrawTypes` declares them, and untyped (any service, method and\n * input) otherwise.\n */\nexport type CallerFor<T extends QuickdrawTypes> = T extends {\n readonly contracts: infer Contracts extends ContractMap;\n}\n ? Caller<Contracts[keyof Contracts]>\n : Caller<AnyContract>;\n\n/** Where the in-process callers of a server's dispatcher get the grants of a principal that carries none. */\nexport interface CallerGrants {\n /** The server's `auth.loadServiceAccess`. */\n readonly load: NonNullable<ServerAuth[\"loadServiceAccess\"]>;\n /**\n * Rises each time the server applies new grants to a user: a caller that\n * loaded its principal's grants before loads them again at its next call.\n */\n readonly version: () => number;\n}\n\nconst CALLER_GRANTS = new WeakMap<object, CallerGrants>();\n\n/**\n * Makes the in-process callers of `dispatcher` (its `caller`, and `qd.caller`\n * while it is the current one) load grants through `grants`: `createServer`\n * registers its `auth.loadServiceAccess`.\n */\nexport function setCallerGrants(dispatcher: object, grants: CallerGrants): void {\n CALLER_GRANTS.set(dispatcher, grants);\n}\n\n/** Where the callers of `dispatcher` load grants from, or `undefined` when they load none. */\nexport function callerGrantsOf(dispatcher: object | undefined): CallerGrants | undefined {\n return dispatcher === undefined ? undefined : CALLER_GRANTS.get(dispatcher);\n}\n\n/** How the calls of a {@link createCaller} run. */\nexport interface CallerSettings {\n /** Cancels every call too: `ctx.services` passes the calling method's `ctx.signal`. */\n readonly signal?: AbortSignal;\n /** Where to load a principal's grants from, asked at each call; `undefined` loads none. */\n readonly grants?: () => CallerGrants | undefined;\n}\n\ntype MethodFunction = (input?: unknown, options?: CallOptions) => Promise<unknown>;\n\nasync function invoke(resolve: () => Dispatch, request: DispatchRequest): Promise<unknown> {\n const result = await resolve()(request);\n if (!result.ok) {\n throw result.error;\n }\n return result.notModified === true ? undefined : result.data;\n}\n\n/**\n * A read-only object whose members are made on first access and kept. It is\n * never mistaken for a promise: `then` reads as `undefined`.\n */\nexport function lazyMembers<Member>(make: (name: string) => Member): object {\n const made = new Map<string, Member>();\n return new Proxy(Object.freeze({}), {\n get(_target, name) {\n if (typeof name !== \"string\" || name === \"then\") {\n return undefined;\n }\n let member = made.get(name);\n if (member === undefined) {\n member = make(name);\n made.set(name, member);\n }\n return member;\n },\n });\n}\n\n/** `signal`, and also `outer` when there is one: aborted when either is. */\nfunction bothSignals(outer: AbortSignal | undefined, signal: AbortSignal | undefined) {\n if (outer === undefined || signal === undefined) {\n return outer ?? signal;\n }\n return AbortSignal.any([outer, signal]);\n}\n\n/** True when `principal` carries grants of its own (`{}` included): they are kept as they are. */\nfunction carriesGrants(principal: Principal): boolean {\n return principal.serviceAccess !== undefined && principal.serviceAccess !== null;\n}\n\n/** `principal` with the grants `grants` loads (`{}` for none). A failed load is `INTERNAL`, keeping the error as `cause`. */\nasync function withLoadedGrants(principal: Principal, grants: CallerGrants): Promise<Principal> {\n let serviceAccess: Awaited<ReturnType<CallerGrants[\"load\"]>>;\n try {\n serviceAccess = await grants.load(principal.userId);\n } catch (error) {\n const failure = new QuickdrawError(\"INTERNAL\", INTERNAL_MESSAGE);\n failure.cause = error;\n throw failure;\n }\n return { ...principal, serviceAccess: serviceAccess ?? {} };\n}\n\n/** What each call of a caller runs as: the principal, or a promise of it while its grants load. */\ntype PrincipalOfCall = () => Principal | null | Promise<Principal>;\n\n/**\n * The principal each call of a caller runs as: `principal` itself when it is\n * `null`, carries grants, or `grants` gives no loader; else `principal` with\n * the grants loaded at the first call, kept until the server applied new\n * grants to a user (its version rose) or the loader changed. A load that\n * failed is not kept: the next call loads again.\n */\nfunction principalOfCalls(\n principal: Principal | null,\n grants: CallerSettings[\"grants\"],\n): PrincipalOfCall {\n if (principal === null || carriesGrants(principal) || grants === undefined) {\n return () => principal;\n }\n interface Held {\n readonly from: CallerGrants;\n readonly version: number;\n readonly loading: Promise<Principal>;\n loaded?: Principal;\n }\n let held: Held | undefined;\n return () => {\n const from = grants();\n if (from === undefined) {\n return principal;\n }\n const version = from.version();\n if (held?.from === from && held.version === version) {\n return held.loaded ?? held.loading;\n }\n const entry: Held = { from, version, loading: withLoadedGrants(principal, from) };\n held = entry;\n entry.loading.then(\n (loaded) => {\n entry.loaded = loaded;\n },\n () => {\n if (held === entry) {\n held = undefined;\n }\n },\n );\n return entry.loading;\n };\n}\n\n/**\n * Creates an in-process caller acting as `principal` (`null` for an\n * anonymous caller). `resolve` returns the dispatch function to call through;\n * it is asked on every call, so a caller made before its dispatcher exists\n * works once one does. Every call is also cancelled with `settings.signal`,\n * when given (`ctx.services` passes the calling method's `ctx.signal`). With\n * `settings.grants`, a principal that carries no grants calls with the ones\n * it loads (see the top of this file).\n */\nexport function createCaller(\n resolve: () => Dispatch,\n principal: Principal | null,\n settings: CallerSettings = {},\n): object {\n const principalOfCall = principalOfCalls(principal, settings.grants);\n return lazyMembers((service) =>\n lazyMembers<MethodFunction>((method) => async (input, options) => {\n const runAs = principalOfCall();\n return await invoke(resolve, {\n service,\n method,\n input,\n // Awaited only while grants load: a known principal is dispatched at once, as before.\n principal: runAs instanceof Promise ? await runAs : runAs,\n transport: \"internal\",\n signal: bothSignals(settings.signal, options?.signal),\n });\n }),\n );\n}\n","// How the pipeline turns whatever a stage or handler threw into the error the\n// caller receives (RFC 0003 section 3). A `QuickdrawError` with one of the\n// error codes passes through. Prisma's two known request errors that callers\n// can act on become `CONFLICT` and `NOT_FOUND`. Everything else becomes\n// `INTERNAL` with the generic message, keeping the original as `cause` for\n// the log and for in-process callers; `toWire` never sends it. That includes\n// a `QuickdrawError` whose code is not one of the error codes, which a cast or\n// a 4.x port (`new QuickdrawError(404, ...)`) can build: no transport has a\n// reply or an HTTP status for it.\n\nimport { INTERNAL_MESSAGE, isErrorCode, QuickdrawError } from \"../../protocol/errors\";\n\n/** The error a cancelled call settles with. */\nexport function cancelledError(): QuickdrawError {\n return new QuickdrawError(\"CANCELLED\", \"The call was cancelled\");\n}\n\n/** The error a call settles with when its handler runs past the time limit. */\nexport function timeoutError(timeoutMs: number): QuickdrawError {\n return new QuickdrawError(\"TIMEOUT\", `The call ran past its time limit of ${timeoutMs} ms`);\n}\n\n/** Throws `CANCELLED` when `signal` has aborted. */\nexport function throwIfCancelled(signal: AbortSignal | undefined): void {\n if (signal?.aborted === true) {\n throw cancelledError();\n }\n}\n\n/**\n * The error a call settles with once its signal aborted: the `TIMEOUT` error\n * its time limit aborted it with, or else `CANCELLED`.\n */\nexport function abortError(signal: AbortSignal): QuickdrawError {\n const reason: unknown = signal.reason;\n return reason instanceof QuickdrawError && reason.code === \"TIMEOUT\" ? reason : cancelledError();\n}\n\nfunction prismaError(error: unknown): QuickdrawError | undefined {\n if (!(error instanceof Error) || error.name !== \"PrismaClientKnownRequestError\") {\n return undefined;\n }\n const { code } = error as Error & { readonly code?: unknown };\n if (code === \"P2002\") {\n return new QuickdrawError(\"CONFLICT\", \"A unique constraint failed\");\n }\n if (code === \"P2025\") {\n return new QuickdrawError(\"NOT_FOUND\", \"Record not found\");\n }\n return undefined;\n}\n\n/**\n * The `QuickdrawError` a caller receives for `error`. Anything but a\n * `QuickdrawError` with a known code becomes another error that keeps the\n * original as `cause`, so it can be logged in full.\n */\nexport function toQuickdrawError(error: unknown): QuickdrawError {\n if (error instanceof QuickdrawError && isErrorCode(error.code)) {\n return error;\n }\n const mapped = prismaError(error) ?? new QuickdrawError(\"INTERNAL\", INTERNAL_MESSAGE);\n mapped.cause = error;\n return mapped;\n}\n","// Schema outputs (RFC 0003 section 9, step 8): a method whose output is a\n// schema of its own, not `\"entity\"` and not a projection, sends its result\n// reduced to what that schema's JSON Schema declares, on every transport and\n// whatever `outputValidation` is. A handler may return a whole row; only the\n// keys the schema declares leave the server. rc.5 and before sent what the\n// handler returned, so `{ id, name }` answered with `db.user.update(...)`\n// sent `email` too (the final review of the release candidates, item B).\n//\n// The reduction is compiled once per method, when its service is defined,\n// from the schema's Standard JSON Schema (draft-07, a value JSON Schema\n// cannot write read as any value): a call walks the compiled shapes and\n// never reads the schema. What a value keeps, by what the schema says there:\n//\n// | JSON Schema | A value there keeps |\n// |-------------------------------------------|------------------------------------------------------|\n// | an object with `properties` | the keys `properties` declares, each reduced by its |\n// | | own schema; another key only where |\n// | | `patternProperties` matches it or |\n// | | `additionalProperties` allows it (`true`, `{}`, or a |\n// | | schema that reduces its value) |\n// | an object declaring no key (a record, | every key, each value reduced by |\n// | `{ type: \"object\" }`) | `additionalProperties` when it is a schema |\n// | an array | its items, each reduced by `items` (a tuple's by |\n// | | position, the rest by `additionalItems`) |\n// | `anyOf`, `oneOf`, `allOf` | what any of its schemas keeps |\n// | `{}` (any value), `true`, a `$ref` it | everything, as it is |\n// | cannot follow | |\n// | a scalar (`string`, `const`, `enum`, ...) | a scalar as it is; a plain object there keeps no key |\n//\n// Only plain objects and arrays are reduced: a `Date`, a `Decimal` or a\n// class instance goes as it is. Nothing is copied unless a key or an item is\n// dropped, so a handler that returns exactly its schema's keys costs one\n// pass over them. An output without JSON Schema (a Zod 3 schema) cannot be\n// reduced and is sent as returned; in development its reply is checked for\n// keys the contract tiers instead (`emit/tieredOutputs.ts`).\n\nimport { hasJsonSchema, type StandardSchemaV1 } from \"../../contract/standardSchema\";\nimport type { SchemaOutput } from \"../service\";\n\ntype JsonNode = Readonly<Record<string, unknown>>;\n\n/** How the values at one place of an output are reduced. */\ninterface Shape {\n /** Any value: kept as it is. */\n readonly any: boolean;\n /** How a plain object there is reduced; without one, it keeps no key. */\n object: ObjectShape | undefined;\n /** How an array there is reduced; without one, each item is reduced by this shape. */\n array: ArrayShape | undefined;\n}\n\ninterface ObjectShape {\n /** The declared keys' shapes, in an object without a prototype: a lookup per key is a property read. */\n readonly properties: Readonly<Record<string, Shape | undefined>>;\n readonly patterns: readonly { readonly regex: RegExp; readonly shape: Shape }[];\n /** How the value of a key `properties` and `patterns` do not declare is reduced; `undefined` drops the key. */\n readonly additional: Shape | undefined;\n}\n\ninterface ArrayShape {\n readonly prefix: readonly Shape[];\n /** How the items past `prefix` are reduced; `undefined` drops them. */\n readonly rest: Shape | undefined;\n}\n\n/** Any value, kept as it is. */\nconst ANY: Shape = Object.freeze({ any: true, object: undefined, array: undefined });\n\n/** What one JSON Schema node declares on its own, before its `anyOf`, `oneOf`, `allOf` and `$ref`. */\ninterface Node {\n readonly id: number;\n any: boolean;\n object:\n | {\n properties: Map<string, Node>;\n patterns: { regex: RegExp; node: Node }[];\n additional: Node | undefined;\n }\n | undefined;\n array: { prefix: Node[]; rest: Node | undefined } | undefined;\n /** The schemas it is one of, or all of: its branches and the node its `$ref` names. */\n readonly members: Node[];\n}\n\nfunction isRecord(value: unknown): value is JsonNode {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\n/** True for an object literal, or `Object.create(null)`, of any realm: what a reduction may copy. */\nfunction isPlainObject(value: object): value is Readonly<Record<string, unknown>> {\n const prototype = Object.getPrototypeOf(value) as object | null;\n return (\n prototype === Object.prototype ||\n prototype === null ||\n Object.getPrototypeOf(prototype) === null\n );\n}\n\n/** The node a `$ref` names in the document: `#`, or a JSON Pointer into it; `undefined` when it names none. */\nfunction follow(ref: string, root: JsonNode): unknown {\n if (ref === \"#\") {\n return root;\n }\n if (!ref.startsWith(\"#/\")) {\n return undefined;\n }\n let node: unknown = root;\n for (const raw of ref.slice(2).split(\"/\")) {\n let part: string;\n try {\n part = decodeURIComponent(raw).replaceAll(\"~1\", \"/\").replaceAll(\"~0\", \"~\");\n } catch {\n return undefined;\n }\n node = isRecord(node) && Object.hasOwn(node, part) ? node[part] : undefined;\n }\n return node;\n}\n\nconst BRANCHES = [\"anyOf\", \"oneOf\", \"allOf\"] as const;\n\nfunction hasAny(node: JsonNode, keywords: readonly string[]): boolean {\n return keywords.some((keyword) => node[keyword] !== undefined);\n}\n\nfunction typesOf(node: JsonNode): readonly unknown[] | undefined {\n const { type } = node;\n if (typeof type === \"string\") {\n return [type];\n }\n return Array.isArray(type) ? type : undefined;\n}\n\nfunction patternOf(source: string): RegExp | undefined {\n try {\n return new RegExp(source, \"u\");\n } catch {\n try {\n return new RegExp(source);\n } catch {\n return undefined;\n }\n }\n}\n\n/** Every node `nodes` stand for: themselves and, through their members, the schemas they combine. */\nfunction expand(nodes: readonly Node[]): Node[] {\n const seen = new Set<Node>();\n const pending = [...nodes];\n for (let node = pending.pop(); node !== undefined; node = pending.pop()) {\n if (!seen.has(node)) {\n seen.add(node);\n pending.push(...node.members);\n }\n }\n return [...seen];\n}\n\n/**\n * Compiles one JSON Schema document: reads it into nodes (each JSON node\n * once, `$ref` cycles included), then builds the shapes calls walk, one per\n * set of nodes a value may meet, merged once.\n */\nclass Compiler {\n private next = 0;\n private readonly nodes = new Map<unknown, Node>();\n private readonly shapes = new Map<string, Shape>();\n\n constructor(private readonly root: JsonNode) {}\n\n private make(any: boolean): Node {\n this.next += 1;\n return { id: this.next, any, object: undefined, array: undefined, members: [] };\n }\n\n /** The node a JSON Schema value stands for. `true` and absent are any value. */\n read(value: unknown): Node {\n if (value === undefined || value === true) {\n return this.make(true);\n }\n if (!isRecord(value)) {\n // `false` (no value) and anything malformed: a scalar, which keeps no key of an object.\n return this.make(false);\n }\n const known = this.nodes.get(value);\n if (known !== undefined) {\n return known;\n }\n const node = this.make(false);\n this.nodes.set(value, node);\n this.readMembers(node, value);\n this.readParts(node, value);\n return node;\n }\n\n /** The node's `$ref` target and its `anyOf`, `oneOf` and `allOf` branches. */\n private readMembers(node: Node, json: JsonNode): void {\n const { $ref } = json;\n if (typeof $ref === \"string\") {\n const target = follow($ref, this.root);\n node.members.push(target === undefined ? this.make(true) : this.read(target));\n }\n for (const keyword of BRANCHES) {\n const members = json[keyword];\n if (!Array.isArray(members)) {\n continue;\n }\n for (const member of members) {\n const read = this.read(member);\n // A part of an `allOf` that allows any value adds nothing to the others.\n if (!(keyword === \"allOf\" && read.any && members.length > 1)) {\n node.members.push(read);\n }\n }\n }\n }\n\n /** What the node declares itself: an object, an array, a scalar, or any value. */\n private readParts(node: Node, json: JsonNode): void {\n const types = typesOf(json);\n const combined = node.members.length > 0;\n const objectKeywords = hasAny(json, [\n \"properties\",\n \"patternProperties\",\n \"additionalProperties\",\n ]);\n const arrayKeywords = hasAny(json, [\"items\", \"prefixItems\", \"additionalItems\"]);\n if (objectKeywords) {\n node.object = this.readObject(json);\n } else if (!combined && types?.includes(\"object\") === true) {\n // An object that declares no key, as a record does: every key.\n node.object = { properties: new Map(), patterns: [], additional: this.make(true) };\n }\n if (arrayKeywords) {\n node.array = this.readArray(json);\n } else if (!combined && types?.includes(\"array\") === true) {\n node.array = { prefix: [], rest: this.make(true) };\n }\n const scalar = types !== undefined || hasAny(json, [\"const\", \"enum\"]);\n node.any = !combined && !objectKeywords && !arrayKeywords && !scalar;\n }\n\n private readObject(json: JsonNode): NonNullable<Node[\"object\"]> {\n const properties = new Map<string, Node>();\n if (isRecord(json.properties)) {\n for (const [key, schema] of Object.entries(json.properties)) {\n properties.set(key, this.read(schema));\n }\n }\n const patterns: { regex: RegExp; node: Node }[] = [];\n let open = false;\n if (isRecord(json.patternProperties)) {\n for (const [source, schema] of Object.entries(json.patternProperties)) {\n const regex = patternOf(source);\n if (regex === undefined) {\n open = true;\n } else {\n patterns.push({ regex, node: this.read(schema) });\n }\n }\n }\n const { additionalProperties } = json;\n let additional: Node | undefined;\n if (open) {\n additional = this.make(true);\n } else if (additionalProperties === undefined) {\n // Properties declared and nothing said of the others: the declared keys only.\n additional =\n json.properties === undefined && json.patternProperties === undefined\n ? this.make(true)\n : undefined;\n } else {\n additional = additionalProperties === false ? undefined : this.read(additionalProperties);\n }\n return { properties, patterns, additional };\n }\n\n private readArray(json: JsonNode): NonNullable<Node[\"array\"]> {\n const { items, prefixItems, additionalItems } = json;\n if (Array.isArray(items)) {\n // draft-07's tuple: `items` by position, `additionalItems` past them.\n return {\n prefix: items.map((item: unknown) => this.read(item)),\n rest: additionalItems === false ? undefined : this.read(additionalItems),\n };\n }\n const prefix = Array.isArray(prefixItems)\n ? prefixItems.map((item: unknown) => this.read(item))\n : [];\n return { prefix, rest: items === false ? undefined : this.read(items) };\n }\n\n /** The shape of a value any of `nodes` describes. */\n shapeOf(nodes: readonly Node[]): Shape {\n const all = expand(nodes);\n if (all.some((node) => node.any)) {\n return ANY;\n }\n const key = all\n .map((node) => node.id)\n .sort((a, b) => a - b)\n .join(\",\");\n const known = this.shapes.get(key);\n if (known !== undefined) {\n return known;\n }\n // Registered before its parts are built, so a recursive schema meets itself.\n const shape: Shape = { any: false, object: undefined, array: undefined };\n this.shapes.set(key, shape);\n const objects = all.flatMap((node) => (node.object === undefined ? [] : [node.object]));\n const arrays = all.flatMap((node) => (node.array === undefined ? [] : [node.array]));\n shape.object = objects.length === 0 ? undefined : this.objectShapeOf(objects);\n shape.array = arrays.length === 0 ? undefined : this.arrayShapeOf(arrays);\n return shape;\n }\n\n private objectShapeOf(objects: readonly NonNullable<Node[\"object\"]>[]): ObjectShape {\n const keys = new Set(objects.flatMap((object) => [...object.properties.keys()]));\n const properties = Object.create(null) as Record<string, Shape>;\n for (const key of keys) {\n const nodes = objects.flatMap((object) => {\n const declared =\n object.properties.get(key) ??\n object.patterns.find(({ regex }) => regex.test(key))?.node ??\n object.additional;\n return declared === undefined ? [] : [declared];\n });\n properties[key] = this.shapeOf(nodes);\n }\n const patterns = objects.flatMap((object) =>\n object.patterns.map(({ regex, node }) => ({ regex, shape: this.shapeOf([node]) })),\n );\n const additional = objects.flatMap((object) =>\n object.additional === undefined ? [] : [object.additional],\n );\n return {\n properties,\n patterns,\n additional: additional.length === 0 ? undefined : this.shapeOf(additional),\n };\n }\n\n private arrayShapeOf(arrays: readonly NonNullable<Node[\"array\"]>[]): ArrayShape {\n const length = Math.max(...arrays.map((array) => array.prefix.length));\n const at = (index: number): Node[] =>\n arrays.flatMap((array) => {\n const node = index < array.prefix.length ? array.prefix[index] : array.rest;\n return node === undefined ? [] : [node];\n });\n const prefix = Array.from({ length }, (_, index) => this.shapeOf(at(index)));\n const rest = arrays.flatMap((array) => (array.rest === undefined ? [] : [array.rest]));\n return { prefix, rest: rest.length === 0 ? undefined : this.shapeOf(rest) };\n }\n}\n\n/** Marks a key or an item a reduction drops. */\nconst DROPPED: unique symbol = Symbol(\"dropped\");\n\n/** Sets `key` on a copy, `__proto__` too, as an own key. */\nfunction assign(copy: Record<string, unknown>, key: string, value: unknown): void {\n if (key === \"__proto__\") {\n Object.defineProperty(copy, key, {\n value,\n enumerable: true,\n writable: true,\n configurable: true,\n });\n } else {\n copy[key] = value;\n }\n}\n\nfunction shapeOfKey(object: ObjectShape, key: string): Shape | undefined {\n const declared = object.properties[key];\n if (declared !== undefined) {\n return declared;\n }\n for (const { regex, shape } of object.patterns) {\n if (regex.test(key)) {\n return shape;\n }\n }\n return object.additional;\n}\n\n/** `item` as `shape` keeps it, or `DROPPED`; a scalar is kept without a call. */\nfunction keep(shape: Shape | undefined, item: unknown): unknown {\n if (shape === undefined) {\n return DROPPED;\n }\n return shape.any || typeof item !== \"object\" || item === null ? item : reduce(shape, item);\n}\n\nfunction reduceObject(\n object: ObjectShape | undefined,\n value: Readonly<Record<string, unknown>>,\n): Readonly<Record<string, unknown>> {\n const keys = Object.keys(value);\n let copy: Record<string, unknown> | undefined;\n for (let index = 0; index < keys.length; index += 1) {\n const key = keys[index] as string;\n const item = value[key];\n const kept = keep(object === undefined ? undefined : shapeOfKey(object, key), item);\n if (copy === undefined) {\n if (kept === item) {\n continue;\n }\n copy = {};\n for (let earlier = 0; earlier < index; earlier += 1) {\n const name = keys[earlier] as string;\n assign(copy, name, value[name]);\n }\n }\n if (kept !== DROPPED) {\n assign(copy, key, kept);\n }\n }\n return copy ?? value;\n}\n\nfunction reduceArray(shape: Shape, value: readonly unknown[]): readonly unknown[] {\n const { array } = shape;\n let copy: unknown[] | undefined;\n for (let index = 0; index < value.length; index += 1) {\n const item: unknown = value[index];\n const kept = keep(\n array === undefined ? shape : index < array.prefix.length ? array.prefix[index] : array.rest,\n item,\n );\n if (copy === undefined) {\n if (kept === item) {\n continue;\n }\n copy = value.slice(0, index);\n }\n if (kept !== DROPPED) {\n copy.push(kept);\n }\n }\n return copy ?? value;\n}\n\n/** An object `value` as `shape` keeps it. */\nfunction reduce(shape: Shape, value: object): unknown {\n if (Array.isArray(value)) {\n return reduceArray(shape, value);\n }\n return isPlainObject(value) ? reduceObject(shape.object, value) : value;\n}\n\n/** Where a shape declares each key it names, at any depth: the shortest path found first. */\nfunction keyPaths(root: Shape): ReadonlyMap<string, string> {\n const paths = new Map<string, string>();\n const seen = new Set<Shape>();\n const queue: { readonly shape: Shape; readonly path: string }[] = [{ shape: root, path: \"\" }];\n for (let index = 0; index < queue.length; index += 1) {\n const { shape, path } = queue[index] as { readonly shape: Shape; readonly path: string };\n if (seen.has(shape)) {\n continue;\n }\n seen.add(shape);\n if (shape.object !== undefined) {\n for (const [key, child] of Object.entries(shape.object.properties)) {\n if (child === undefined) {\n continue;\n }\n const at = path === \"\" ? key : `${path}.${key}`;\n if (!paths.has(key)) {\n paths.set(key, at);\n }\n queue.push({ shape: child, path: at });\n }\n for (const { shape: child } of shape.object.patterns) {\n queue.push({ shape: child, path: `${path}{}` });\n }\n if (shape.object.additional !== undefined) {\n queue.push({ shape: shape.object.additional, path: `${path}{}` });\n }\n }\n if (shape.array !== undefined) {\n for (const child of shape.array.prefix) {\n queue.push({ shape: child, path: `${path}[]` });\n }\n if (shape.array.rest !== undefined) {\n queue.push({ shape: shape.array.rest, path: `${path}[]` });\n }\n }\n }\n return paths;\n}\n\n/** Writes values JSON Schema has no form for as `{}` (any value), keeping the keys beside them (Zod 4). */\nconst UNREPRESENTABLE_AS_ANY = Object.freeze({ unrepresentable: \"any\" });\n\n/**\n * Compiles a method's output schema (see the top of this file), or\n * `undefined` when it has no Standard JSON Schema or cannot write one: such\n * an output is sent as the handler returns it.\n */\nexport function compileSchemaOutput(schema: StandardSchemaV1): SchemaOutput | undefined {\n if (!hasJsonSchema(schema)) {\n return undefined;\n }\n let json: unknown;\n try {\n json = schema[\"~standard\"].jsonSchema.output({\n target: \"draft-07\",\n libraryOptions: UNREPRESENTABLE_AS_ANY,\n });\n } catch {\n return undefined;\n }\n if (!isRecord(json)) {\n return undefined;\n }\n const compiler = new Compiler(json);\n const root = compiler.shapeOf([compiler.read(json)]);\n let paths: ReadonlyMap<string, string> | undefined;\n return Object.freeze({\n pick: (value: unknown) => keep(root, value),\n keyPaths: () => (paths ??= keyPaths(root)),\n });\n}\n","// Input and output validation (RFC 0003 section 9, steps 3 and 8). Input\n// failures reach the caller as `VALIDATION` with `data.issues` in the wire\n// shape `{ path, message }[]`. 4.1 sent Zod's message as a code-400 string\n// (4.1 `src/server/ServiceRegistry.ts:296-305`), and only when the method\n// had a schema at all.\n\nimport type { AnyContract } from \"../../contract/defineContract\";\nimport type { MethodOutput } from \"../../contract/methods\";\nimport {\n isStandardSchema,\n validate,\n type StandardSchemaV1,\n type ValidationIssue,\n} from \"../../contract/standardSchema\";\nimport { QuickdrawError, type WireIssue } from \"../../protocol/errors\";\nimport type { SchemaOutput } from \"../service\";\nimport { compileSchemaOutput } from \"./schemaOutput\";\n\ntype PathSegment = NonNullable<ValidationIssue[\"path\"]>[number];\n\nfunction wireKey(key: PropertyKey): string | number {\n if (typeof key === \"symbol\") {\n return key.description ?? key.toString();\n }\n return key;\n}\n\nfunction wireSegment(segment: PathSegment): string | number {\n return typeof segment === \"object\" ? wireKey(segment.key) : wireKey(segment);\n}\n\n/**\n * Standard Schema issues in the wire shape of RFC 0003 section 3: each path\n * as object keys and array indexes (a `{ key }` segment becomes its key, a\n * symbol its description), and the message unchanged.\n */\nexport function toWireIssues(issues: readonly ValidationIssue[]): WireIssue[] {\n return issues.map((issue) => ({\n path: (issue.path ?? []).map(wireSegment),\n message: issue.message,\n }));\n}\n\n/** Validates a call's input. Resolves with the parsed input, or rejects with `VALIDATION`. */\nexport async function parseInput(\n schema: StandardSchemaV1,\n input: unknown,\n label: string,\n): Promise<unknown> {\n const result = await validate(schema, input);\n if (result.issues !== undefined) {\n throw new QuickdrawError(\"VALIDATION\", `Invalid input for ${label}`, {\n issues: toWireIssues(result.issues),\n });\n }\n return result.value;\n}\n\nfunction derivedSchema(validateValue: StandardSchemaV1.Props[\"validate\"]): StandardSchemaV1 {\n return Object.freeze({\n \"~standard\": Object.freeze({ version: 1, vendor: \"quickdraw\", validate: validateValue }),\n });\n}\n\nfunction nullableOf(inner: StandardSchemaV1): StandardSchemaV1 {\n return derivedSchema((value) =>\n value === null ? { value } : inner[\"~standard\"].validate(value),\n );\n}\n\nfunction listOfSchema(inner: StandardSchemaV1): StandardSchemaV1 {\n return derivedSchema(async (value) => {\n if (!Array.isArray(value)) {\n return { issues: [{ message: \"Expected an array\", path: [] }] };\n }\n const results = await Promise.all(value.map((item: unknown) => validate(inner, item)));\n const issues = results.flatMap((result, index) =>\n (result.issues ?? []).map((issue) => ({\n message: issue.message,\n path: [index, ...(issue.path ?? [])],\n })),\n );\n return issues.length > 0 ? { issues } : { value };\n });\n}\n\nfunction projectionSchema(contract: AnyContract, projection: string): StandardSchemaV1 {\n const found = projection === \"entity\" ? contract.entity : contract.projections[projection];\n if (found === undefined) {\n throw new TypeError(\n `defineService(\"${contract.name}\"): output names unknown projection \"${projection}\"`,\n );\n }\n return found;\n}\n\n/**\n * The schema a method's result is checked against: its `output` schema, or\n * the entity or projection schema it names, wrapped for `nullable(...)` and\n * `listOf(...)` (RFC 0003 section 17).\n */\nexport function outputSchemaOf(contract: AnyContract, output: MethodOutput): StandardSchemaV1 {\n if (isStandardSchema(output)) {\n return output;\n }\n if (typeof output === \"string\") {\n return projectionSchema(contract, output);\n }\n const row = projectionSchema(contract, output.projection);\n return output.kind === \"nullable\" ? nullableOf(row) : listOfSchema(row);\n}\n\n/**\n * A method output that is a schema of its own, compiled to reduce results to\n * what it declares (`schemaOutput.ts`); `undefined` for a projection output\n * or a schema without JSON Schema.\n */\nexport function schemaOutputOf(output: MethodOutput): SchemaOutput | undefined {\n return isStandardSchema(output) ? compileSchemaOutput(output) : undefined;\n}\n\n/** The problems with a handler's result, or `undefined` when it matches the method's output. */\nexport async function outputIssues(\n output: StandardSchemaV1,\n value: unknown,\n): Promise<WireIssue[] | undefined> {\n const result = await validate(output, value);\n return result.issues === undefined ? undefined : toWireIssues(result.issues);\n}\n","// The argument every handler receives, `{ input, ctx, db }` (RFC 0003\n// section 3). `ctx` replaces 4.1's `ServiceMethodContext` (`userId`,\n// `socketId`, `serviceAccess`; 4.1 `src/shared/types.ts:111-115`) and the\n// habit of overriding `defineMethod` to add fields: an app adds its own\n// fields once, through `initQuickdraw({ context })`.\n\nimport type { AnyContract } from \"../contract/defineContract\";\nimport type { Logger } from \"../contract/logger\";\nimport { QuickdrawError } from \"../protocol/errors\";\nimport type { DispatcherAccess, PolicyEngine } from \"./access/api\";\nimport { createCaller, type CallerFor } from \"./caller\";\nimport type { Dispatch } from \"./pipeline/pipeline\";\nimport type { ContextRooms, Presence } from \"./realtime/types\";\nimport type { AnyService } from \"./service\";\nimport type { StorageAdapter } from \"./storage\";\nimport type {\n ContextExtensionOf,\n DbOf,\n McpContext,\n McpContextOf,\n Principal,\n PrincipalOf,\n QuickdrawTypes,\n Transport,\n} from \"./types\";\n\n/** Options of `ctx.touch`. */\nexport interface TouchOptions {\n /** The rows were deleted rather than changed. */\n readonly removed?: boolean;\n}\n\n/**\n * `ctx.services`: in-process callers for the app's services (RFC 0003\n * sections 3 and 10), by service name: `ctx.services.projectService.get(input)`.\n * A call runs the whole pipeline (input check, access, handler, output\n * check) as the calling principal with transport `\"internal\"`, its writes\n * join the calling method's unit of work (one flush for both), and it is\n * cancelled with `ctx.signal`. Typed by the `contracts` of the app's types,\n * like `qd.caller`; untyped without them.\n */\nexport type ContextServices<T extends QuickdrawTypes = QuickdrawTypes> = CallerFor<T>;\n\nexport type { ContextRooms, Presence };\n\n/**\n * The fields of `ctx` the framework provides, whatever the app adds. `M` is\n * the type of `ctx.mcp`.\n */\nexport interface BaseContext<P = Principal, M = McpContext> {\n /**\n * Who is calling. `null` only in a `\"public\"` method called without\n * credentials; every other access form guarantees a principal.\n */\n readonly principal: P;\n /**\n * Aborts when the call is cancelled (a query whose callers all cancelled)\n * or runs past its time limit. Pass it to anything that can stop early.\n */\n readonly signal: AbortSignal;\n /** A logger bound to this call's service, method and request id. */\n readonly log: Logger;\n /** Identifies this call in logs and in its completion record. */\n readonly requestId: string;\n /** How the call arrived. */\n readonly transport: Transport;\n /**\n * The socket the call arrived on: its id, as the client socket's `id`,\n * `onRoomLeave`'s `socketId` and a channel handler's `ctx.socketId` name\n * it (a game keys a player's input by it). A call through the 4.x legacy\n * shim has it too: it arrived on a socket. `undefined` for a call that\n * did not arrive over a socket: HTTP, MCP, in process, `ctx.services`. In\n * a method that shares its runs (`share`), the first caller's.\n */\n readonly socketId?: string;\n /**\n * The fields the MCP bridge's `context` option produced for this call, such\n * as the scopes of the agent's token; typed by `QuickdrawTypes[\"mcp\"]`.\n * `undefined` unless the call arrived over MCP.\n */\n readonly mcp?: M;\n /**\n * Records writes the tracked database client cannot see, raw SQL and\n * database cascades (RFC 0003 section 5.2), as if the client had made\n * them here: inside an open `db.$transaction` they join it and are dropped\n * on rollback. `target` is the model name (`\"task\"`); `removed` marks the\n * rows deleted. Does nothing when the dispatcher's `db` is not tracked.\n */\n touch(\n target: string | AnyContract,\n ids: string | readonly string[],\n options?: TouchOptions,\n ): void;\n /**\n * In-process callers for the app's services, as this call's principal:\n * `await ctx.services.projectService.get({ id })`. See {@link ContextServices}.\n */\n readonly services: ContextServices;\n /**\n * App-defined rooms the calling socket joins and leaves (`join` answers\n * `false` for a call without a socket), and typed room events: `emit` and\n * `emitToUser` (RFC 0003 section 12.5).\n */\n readonly rooms: ContextRooms;\n /** Who is online, when they were last seen, and who is in a room (RFC 0003 section 12.5). */\n readonly presence: Presence;\n}\n\n/**\n * A handler's `ctx`: the framework's fields plus the app's own from\n * `initQuickdraw({ context })`. An app field cannot replace a framework field.\n */\nexport type HandlerContext<T extends QuickdrawTypes, P = PrincipalOf<T>> = Omit<\n ContextExtensionOf<T>,\n keyof BaseContext\n> &\n Omit<BaseContext<P, McpContextOf<T>>, \"services\"> & {\n /** In-process callers for the app's services, typed by its `contracts`. */\n readonly services: ContextServices<T>;\n };\n\n/** What a handler receives: the parsed input, the call's context and the app's database client. */\nexport interface HandlerArgs<T extends QuickdrawTypes, Input, P = PrincipalOf<T>> {\n /** The input after its schema ran: defaults applied, transforms done. */\n readonly input: Input;\n readonly ctx: HandlerContext<T, P>;\n /** The database client given to the dispatcher, passed through unchanged. */\n readonly db: DbOf<T>;\n}\n\n/** Any handler's `ctx`, as the pipeline handles it. */\nexport type AnyContext = BaseContext<Principal | null>;\n\n/**\n * What `qd.run(fn)` and `dispatcher.run(fn)` give `fn`: the part of a\n * handler's `ctx` that means something outside a method call. A job has no\n * caller, so `principal` is `null`. A `fn` that takes no parameter still\n * works.\n *\n * @example\n * await qd.run(async (ctx) => {\n * const ids = await renumberWithSql(projectId);\n * ctx.touch(\"task\", ids);\n * });\n */\nexport interface RunContext {\n /** `ctx.touch`: records rows the tracked client cannot see (raw SQL, cascades) in this run's unit of work. */\n readonly touch: BaseContext[\"touch\"];\n /** The dispatcher's logger, bound to this run's request id. */\n readonly log: Logger;\n readonly principal: null;\n}\n\n/** Options of `qd.run(fn, options)` and `dispatcher.run(fn, options)`. */\nexport interface RunOptions {\n /**\n * Run `fn` in a unit of work of its own even inside a method call or a\n * transaction: for background work a handler starts and does not await\n * (a push sent after the reply, pruning what it reports dead). Its writes\n * flush once `fn` settles, on their own, instead of joining the handler's\n * unit, which may have flushed long before (they would then flush as\n * ambient writes, with a development warning). A failed flush is logged.\n * Default `false`: inside an open unit of work or transaction, `fn` joins\n * it.\n *\n * @example\n * // in a handler, not awaited: the reply does not wait for the push\n * void qd.run(() => sendPushes(db, message), { detached: true }).catch((error) => {\n * ctx.log.error(\"Pushing the message failed\", { error: String(error) });\n * });\n */\n readonly detached?: boolean;\n}\n\n/** Builds the app's fields of `ctx` from the framework's: the `context` option of `initQuickdraw`. */\nexport type ContextExtender = (base: AnyContext) => object;\n\n/**\n * What the framework's kits (RFC 0003 section 12) know about the call a\n * `ctx` belongs to: the service whose method runs, and the dispatcher's\n * access policies and storage adapter. A kit's handlers are made before any\n * dispatcher exists, so they find these through `kitRuntimeOf(ctx)`. It is\n * never a member of `ctx`.\n */\nexport interface KitRuntime {\n readonly service: AnyService;\n /** `dispatcher.access`, and `resolve` for levels without service grants (a collection scope's). */\n readonly access: DispatcherAccess & Pick<PolicyEngine, \"resolve\">;\n readonly storage: StorageAdapter | undefined;\n /** How many sockets sit in a room, for the admin kit's subscriber counts. */\n readonly occupancy?: RoomOccupancy;\n /**\n * The revision a read made from now on is no older than (the search\n * kit's pages): the process's last one, or behind a cluster's counter the\n * counter's.\n */\n readonly claimRevision?: () => number | Promise<number>;\n /**\n * Runs `fn` in a detached unit of work of the dispatcher, as\n * `qd.run(fn, { detached: true })` does: a kit's work after its call (the\n * admin kit's `onCommitted`), whose writes flush on their own.\n */\n readonly runDetached?: (fn: () => unknown) => Promise<unknown>;\n}\n\n/** The sockets in a room (RFC 0003 section 6), as this process sees its rooms. */\nexport interface RoomOccupancy {\n /** This process's sockets in `room`: none without a server. */\n sockets(room: string): number;\n /**\n * `true` when this process sees every socket: its server has no cluster\n * adapter (Redis), or there is no server.\n */\n complete(): boolean;\n}\n\n/**\n * The per-call fields the dispatcher fills in. `touch` is the dispatcher's\n * (its tracked writes), `rooms` and `presence` its live data's, `dispatch`\n * its own dispatch function, which `ctx.services` calls through; a context\n * built without them gets a `touch` that does nothing, `rooms` that join\n * nothing and send nothing, a `presence` that sees nobody, and `services`\n * that throw `INTERNAL`. `kit` is kept beside the context, never on it.\n */\nexport type ContextFields = Pick<\n AnyContext,\n \"principal\" | \"signal\" | \"log\" | \"requestId\" | \"transport\" | \"socketId\" | \"mcp\"\n> &\n Partial<Pick<AnyContext, \"touch\" | \"rooms\" | \"presence\">> & {\n readonly kit?: KitRuntime;\n readonly dispatch?: Dispatch;\n };\n\nconst KIT_RUNTIMES = new WeakMap<object, KitRuntime>();\nconst SERVICE_CALLERS = new WeakMap<object, (signal: AbortSignal) => ContextServices>();\n\n/**\n * The kit runtime of the call `ctx` belongs to, or `undefined` for a\n * context no dispatcher built.\n */\nexport function kitRuntimeOf(ctx: object): KitRuntime | undefined {\n return KIT_RUNTIMES.get(ctx);\n}\n\nfunction withRuntime<Ctx extends object>(\n ctx: Ctx,\n runtime: KitRuntime | undefined,\n services: ((signal: AbortSignal) => ContextServices) | undefined,\n): Ctx {\n if (runtime !== undefined) {\n KIT_RUNTIMES.set(ctx, runtime);\n }\n if (services !== undefined) {\n SERVICE_CALLERS.set(ctx, services);\n }\n return ctx;\n}\n\n/** A signal that never aborts, for calls that cannot be cancelled. */\nexport const NEVER_ABORTED: AbortSignal = new AbortController().signal;\n\nfunction notAvailable(member: string): QuickdrawError {\n return new QuickdrawError(\n \"INTERNAL\",\n `${member} needs a dispatcher: it calls through the dispatcher that runs the method`,\n );\n}\n\nfunction untracked(): void {\n // Without tracked writes there is nothing to record.\n}\n\n// Names that inspection, serialization and test matchers read from any\n// object. They answer `undefined` so logging a `ctx` never throws.\nconst INSPECTED = new Set([\n \"then\",\n \"toJSON\",\n \"constructor\",\n \"toString\",\n \"valueOf\",\n \"asymmetricMatch\",\n \"$$typeof\",\n \"nodeType\",\n]);\n\nfunction unavailable(member: string): ContextServices {\n return new Proxy(Object.freeze({}), {\n get(_target, key) {\n if (typeof key === \"symbol\" || INSPECTED.has(key)) {\n return undefined;\n }\n throw notAvailable(`${member}.${key}`);\n },\n });\n}\n\nconst SERVICES: ContextServices = unavailable(\"ctx.services\");\n\n/** The `ctx.rooms` of a context no dispatcher built: no socket to join with, no server to send through. */\nconst NO_ROOMS: ContextRooms = Object.freeze({\n join: () => false,\n leave: ((_room: string, target?: unknown) =>\n target === undefined ? false : Promise.resolve()) as ContextRooms[\"leave\"],\n emit: untracked,\n emitToUser: untracked,\n size: () => 0,\n});\n\n/** The `ctx.presence` of a context no dispatcher built: no server, so nobody is online. */\nconst NO_PRESENCE: Presence = Object.freeze({\n isOnline: () => Promise.resolve(false),\n lastSeen: () => Promise.resolve(null),\n count: () => Promise.resolve(0),\n users: () => Promise.resolve([]),\n});\n\n/**\n * `ctx.services` for a signal: callers acting as `principal` through\n * `dispatch`, every call cancelled with the signal.\n */\nfunction servicesOf(\n dispatch: Dispatch | undefined,\n principal: Principal | null,\n): ((signal: AbortSignal) => ContextServices) | undefined {\n if (dispatch === undefined) {\n return undefined;\n }\n return (signal) => createCaller(() => dispatch, principal, { signal }) as ContextServices;\n}\n\n/**\n * Builds a call's `ctx`: the framework's fields, then the app's fields from\n * `extend`. The framework's fields win when the names collide.\n */\nexport function createContext(fields: ContextFields, extend?: ContextExtender): AnyContext {\n const { kit, dispatch, ...own } = fields;\n const services = servicesOf(dispatch, own.principal);\n const base: AnyContext = Object.freeze({\n ...own,\n touch: own.touch ?? untracked,\n services: services?.(own.signal) ?? SERVICES,\n rooms: own.rooms ?? NO_ROOMS,\n presence: own.presence ?? NO_PRESENCE,\n });\n if (extend === undefined) {\n return withRuntime(base, kit, services);\n }\n return withRuntime(Object.freeze({ ...extend(base), ...base }), kit, services);\n}\n\n/**\n * The same `ctx` with another signal: the one a handler run aborts. Its\n * `ctx.services` calls are cancelled with that signal.\n */\nexport function withSignal(ctx: AnyContext, signal: AbortSignal): AnyContext {\n const services = SERVICE_CALLERS.get(ctx);\n const next =\n services === undefined ? { ...ctx, signal } : { ...ctx, signal, services: services(signal) };\n return withRuntime(Object.freeze(next), KIT_RUNTIMES.get(ctx), services);\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/server/devWarnings.ts","../src/server/rev.ts","../src/server/uow/unitOfWork.ts","../src/server/uow/flush.ts","../src/server/uow/flushSink.ts","../src/server/uow/records.ts","../src/server/uow/statementChecks.ts"],"sourcesContent":["// Development warnings (RFC 0003 section 13): the slow or untracked patterns\n// a lint rule cannot see, because they only show while the code runs,\n// reported as they happen. Every warning has one format, names the call it\n// happened in, and is logged once per kind, service, method and subject:\n//\n// [quickdraw:n-plus-one] taskService.board: task.findUnique by id ran 10 times in one call...\n//\n// | Kind | Raised when | Subject |\n// |----------------------|--------------------------------------------------------------------|--------------------------|\n// | `n-plus-one` | a call ran 10 statements of one shape (model, operation, `where` | none |\n// | | keys), outside an array-form `$transaction` | |\n// | `unbounded-read` | a call ran `findMany` with neither `take` nor ids to read (`id`, | none |\n// | | `{ in }`, `{ equals }`) | |\n// | `oversized-response` | a reply was larger than `maxResponseBytes` | none |\n// | `nested-write` | a write's `data` wrote a related row, which is not tracked | model, field, operation |\n// | `ambient-write` | a tracked write ran outside any unit of work | model |\n// | `batch-read` | a write in an array-form `$transaction` read its rows outside it | model, operation |\n// | `batch-create-many` | a `createMany` in an array-form `$transaction` could not be traced | model |\n// | `repeated-call` | one connection called a method with the same input more than 10 | connection |\n// | | times within a second, or was refused `RATE_LIMITED` more than 30 | (`refused <connection>`) |\n// | | times within a minute: a client in a loop (`createLoopWatch`) | |\n// | `tiered-field-in- | a method's own output schema declares a field the contract tiers, | the field |\n// | output` | at any depth, which such an output never strips | |\n// | | (`emit/tieredOutputs.ts`); raised when a dispatcher is made, so a | |\n// | | strict test app fails to start; for an output without JSON Schema, | |\n// | | raised by the first reply that carries the field | |\n// | `resolver-without- | a service with a model has a `resolver` policy (alone or in | none (once per service) |\n// | reads` | `anyOf`) that declares no `reads`, so no tracked write re-checks | |\n// | | it (`access/resolverReads.ts`); raised when a dispatcher is made, | |\n// | | so a strict test app fails to start | |\n//\n// `nested-write`, `ambient-write`, `batch-read` and `batch-create-many` are\n// the write tracker's (`uow/unitOfWork.ts`), raised exactly where they were\n// before; they gained the format and the call. Only an app's\n// own statements are checked for the first two: the framework's reads through\n// the storage adapter, the tracker's own reads and the kits' handlers run\n// `quietly`, while the app's callbacks a kit calls (`prepare`, `onChange`,\n// `resolveUser`, a search strategy) run `checked`. A query by an `id` list\n// (`{ id: { in: ids } }`) is one query per list, not per row, so it never\n// counts toward an N+1. Warnings are off when NODE_ENV is \"production\". In a test app\n// made with `strictWarnings` (under vitest or jest) every warning raised in\n// one of its method calls throws a `DevWarningError` where it is raised\n// instead, so the test fails; warnings outside its calls (an ambient write\n// while seeding, say) are logged as usual.\n\nimport { AsyncLocalStorage } from \"node:async_hooks\";\nimport { createHash } from \"node:crypto\";\nimport { consoleLogger, type Logger } from \"../contract/logger\";\nimport type { CallOutcome } from \"./pipeline/metrics\";\n\n/** What a development warning is about. */\nexport type DevWarningKind =\n | \"n-plus-one\"\n | \"unbounded-read\"\n | \"oversized-response\"\n | \"nested-write\"\n | \"ambient-write\"\n | \"batch-read\"\n | \"batch-create-many\"\n | \"repeated-call\"\n | \"tiered-field-in-output\"\n | \"resolver-without-reads\";\n\n/** One development warning. */\nexport interface DevWarning {\n readonly kind: DevWarningKind;\n /** The service whose method call raised it; absent outside a call (a job, a script). */\n readonly service?: string;\n readonly method?: string;\n /**\n * What the warning is about within its call, for the once-only rule: the\n * model of an ambient write, the model, field and operation of a nested\n * write, the connection of a repeated call. Empty for the kinds that are\n * once per call site.\n */\n readonly subject?: string;\n /** What happened and what to do instead. */\n readonly message: string;\n /** Logged with the warning. */\n readonly meta?: Readonly<Record<string, unknown>>;\n}\n\n/** The statements of one shape a call may run before it is an N+1. */\nexport const N_PLUS_ONE_STATEMENTS = 10;\n\n/** The text a warning is logged and thrown with: `[quickdraw:<kind>] <service>.<method>: <message>`. */\nexport function formatDevWarning(warning: DevWarning): string {\n const where =\n warning.service === undefined || warning.method === undefined\n ? \"\"\n : ` ${warning.service}.${warning.method}:`;\n return `[quickdraw:${warning.kind}]${where} ${warning.message}`;\n}\n\n/** A development warning, thrown instead of logged by a test app made with `strictWarnings`. */\nexport class DevWarningError extends Error {\n override readonly name = \"DevWarningError\";\n readonly warning: DevWarning;\n\n constructor(warning: DevWarning) {\n super(formatDevWarning(warning));\n this.warning = warning;\n }\n}\n\n/**\n * Where development warnings go: one per dispatcher, which the write tracker\n * reports a call's warnings to as well.\n */\nexport interface DevWarnings {\n /** False when warnings are off: NODE_ENV is \"production\" and nothing made them strict. */\n readonly enabled: boolean;\n /** True when every warning throws: a strict test app's dispatcher. */\n readonly strict: boolean;\n /** Logs `warning` the first time its kind, service, method and subject come up; strict, throws it every time. */\n warn(warning: DevWarning): void;\n}\n\n/** Options of {@link createDevWarnings}. */\nexport interface DevWarningsOptions {\n readonly logger?: Logger;\n /** Default: on unless NODE_ENV is \"production\". */\n readonly development?: boolean;\n /** Throw every warning as a `DevWarningError` instead of logging it. */\n readonly strict?: boolean;\n}\n\nfunction onceKey(warning: DevWarning): string {\n return [warning.kind, warning.service ?? \"\", warning.method ?? \"\", warning.subject ?? \"\"].join(\n \"\\u0000\",\n );\n}\n\n/** Creates the development warnings of one dispatcher (or of a write tracker before one attaches). */\nexport function createDevWarnings(options: DevWarningsOptions = {}): DevWarnings {\n const logger = options.logger ?? consoleLogger;\n const strict = options.strict === true;\n const enabled = strict || (options.development ?? process.env.NODE_ENV !== \"production\");\n const warned = new Set<string>();\n return Object.freeze({\n enabled,\n strict,\n warn(warning: DevWarning): void {\n if (strict) {\n throw new DevWarningError(warning);\n }\n const key = onceKey(warning);\n if (!enabled || warned.has(key)) {\n return;\n }\n warned.add(key);\n logger.warn(formatDevWarning(warning), {\n category: \"quickdraw.dev\",\n warning: warning.kind,\n ...(warning.service === undefined ? {} : { service: warning.service }),\n ...(warning.method === undefined ? {} : { method: warning.method }),\n ...warning.meta,\n });\n },\n });\n}\n\n/**\n * The option `createTestApp({ strictWarnings })` sets on the server options\n * it passes on, so the dispatcher makes its warnings strict. A symbol, so it\n * survives the options being copied and is no option of the public types.\n */\nexport const STRICT_WARNINGS: unique symbol = Symbol(\"quickdraw.strictWarnings\");\n\n/** Whether `options` carry {@link STRICT_WARNINGS}. */\nexport function strictWarningsOf(options: object): boolean {\n return Reflect.get(options, STRICT_WARNINGS) === true;\n}\n\nconst QUIET = new AsyncLocalStorage<boolean>();\n\n/**\n * Runs `fn` with the development checks of statements off, awaiting its\n * result inside (a Prisma promise runs where it is awaited): the framework's\n * own reads and the kits' handlers, which an app cannot change.\n */\nexport async function quietly<T>(fn: () => T | PromiseLike<T>): Promise<T> {\n return await QUIET.run(true, async () => await fn());\n}\n\n/**\n * Runs `fn` with the development checks of statements on again, inside a\n * kit's quiet handler: the app's own callbacks a kit calls (`prepare`,\n * `onChange`, `resolveUser`, a search strategy) are the app's code, checked\n * like a handler's.\n */\nexport async function checked<T>(fn: () => T | PromiseLike<T>): Promise<T> {\n return await QUIET.run(false, async () => await fn());\n}\n\n/** True inside {@link quietly}, and not inside a {@link checked} within it. */\nexport function isQuiet(): boolean {\n return QUIET.getStore() === true;\n}\n\n// Loop warnings (`repeated-call`). Without them, a client re-issuing one\n// call (a mutation fired from an effect that its own result re-runs, a\n// refetch that triggers itself) is seen only as `RATE_LIMITED` once the\n// socket's 600-per-minute limiter trips, which says nothing about why. The\n// dispatcher's loop watch says it instead:\n//\n// - one connection (a socket, an MCP session) calls the same method with an\n// identical input more than 10 times within a second: once per\n// connection, service and method;\n// - one connection is refused `RATE_LIMITED` more than 30 times within a\n// minute, by the socket rate limiter or by a full query queue: once per\n// connection, at warn where a refusal on its own logs at debug.\n//\n// A test app made with `strictWarnings` throws them from the call that\n// crossed the line, once its reply was sent; a refusal outside any call is\n// logged even there. Calls without a connection (in-process, HTTP) are not\n// counted. Memory is bounded: the 10,000 most recently seen keys are kept.\n\n/** Identical calls one connection may make within {@link REPEATED_CALL_WINDOW_MS}. */\nexport const REPEATED_CALL_LIMIT = 10;\nexport const REPEATED_CALL_WINDOW_MS = 1_000;\n\n/** `RATE_LIMITED` refusals one connection may get within {@link REFUSAL_WINDOW_MS}. */\nexport const REFUSAL_LIMIT = 30;\nexport const REFUSAL_WINDOW_MS = 60_000;\n\nconst MAX_KEYS = 10_000;\n\n/** Inputs longer than this are keyed by their hash. */\nconst MAX_INPUT_KEY = 256;\n\n/** What a finished call is counted by. */\nexport interface CountedCall {\n readonly service: string;\n readonly method: string;\n readonly input: unknown;\n readonly connectionId?: string;\n}\n\n/** Counts each connection's calls and refusals, and warns when they look like a loop. */\nexport interface LoopWatch {\n /**\n * Counts one finished call and how it ended. Throws the warning in a test\n * app made with `strictWarnings`; call it once the reply was sent.\n */\n call(call: CountedCall, outcome: CallOutcome): void;\n /** Counts an event the socket rate limiter refused; never throws. */\n refused(connectionId: string, event: string): void;\n}\n\n/**\n * Counts events per key: returns how many fell within `windowMs` up to now,\n * once that is more than `limit`, else `undefined`. Keeps at most `limit + 1`\n * times per key and drops the least recently seen key past `MAX_KEYS`.\n */\nfunction createCounter(\n limit: number,\n windowMs: number,\n now: () => number,\n): (key: string) => number | undefined {\n const times = new Map<string, number[]>();\n return (key) => {\n const at = now();\n const recent = (times.get(key) ?? []).filter((time) => at - time < windowMs);\n recent.push(at);\n if (recent.length > limit + 1) {\n recent.shift();\n }\n times.delete(key);\n times.set(key, recent);\n if (times.size > MAX_KEYS) {\n const [oldest] = times.keys();\n times.delete(oldest ?? key);\n }\n return recent.length > limit ? recent.length : undefined;\n };\n}\n\n/** The input as a key: its JSON, hashed when long; `undefined` for an input JSON cannot write. */\nfunction inputKey(input: unknown): string | undefined {\n let text: string | undefined;\n try {\n text = JSON.stringify(input) ?? \"undefined\";\n } catch {\n return undefined;\n }\n return text.length <= MAX_INPUT_KEY ? text : createHash(\"sha1\").update(text).digest(\"base64url\");\n}\n\nconst OFF: LoopWatch = Object.freeze({\n call: () => undefined,\n refused: () => undefined,\n});\n\n/**\n * The loop watch of one dispatcher: it raises its `repeated-call` warnings\n * through `warnings`, and through a lenient copy logging to `logger` for\n * refusals outside any call.\n */\nexport function createLoopWatch(\n warnings: DevWarnings,\n logger: Logger,\n now: () => number = Date.now,\n): LoopWatch {\n if (!warnings.enabled) {\n return OFF;\n }\n const repeats = createCounter(REPEATED_CALL_LIMIT, REPEATED_CALL_WINDOW_MS, now);\n const refusals = createCounter(REFUSAL_LIMIT, REFUSAL_WINDOW_MS, now);\n const outside = warnings.strict ? createDevWarnings({ logger, development: true }) : warnings;\n const refusal = (sink: DevWarnings, connectionId: string, what: string): void => {\n const count = refusals(connectionId);\n if (count !== undefined) {\n sink.warn({\n kind: \"repeated-call\",\n subject: `refused ${connectionId}`,\n message:\n `connection ${connectionId} was refused RATE_LIMITED ${String(count)} times within a minute (the last: ${what}): ` +\n \"its client keeps calling while it is rate limited, as a loop does. The quickdraw client backs off on RATE_LIMITED; \" +\n \"find the call that repeats (a repeated-call warning names it) and stop the loop\",\n meta: { connectionId, refusals: count, windowMs: REFUSAL_WINDOW_MS },\n });\n }\n };\n return Object.freeze({\n call(call: CountedCall, outcome: CallOutcome): void {\n const { connectionId } = call;\n if (connectionId === undefined) {\n return;\n }\n if (outcome === \"RATE_LIMITED\") {\n refusal(warnings, connectionId, `${call.service}.${call.method}`);\n }\n const key = inputKey(call.input);\n const count =\n key === undefined\n ? undefined\n : repeats([connectionId, call.service, call.method, key].join(\"\\u0000\"));\n if (count === undefined) {\n return;\n }\n warnings.warn({\n kind: \"repeated-call\",\n service: call.service,\n method: call.method,\n subject: connectionId,\n message:\n `called ${String(count)} times within a second with the same input, on one connection (${connectionId}): ` +\n \"the client calls it in a loop, as a mutation fired from an effect or from render does, or a refetch that triggers itself. \" +\n \"Call it from an event handler, or guard the effect so it runs once per change\",\n meta: { connectionId, calls: count, windowMs: REPEATED_CALL_WINDOW_MS },\n });\n },\n refused(connectionId: string, event: string): void {\n refusal(outside, connectionId, event);\n },\n });\n}\n","// Revisions (RFC 0003 section 5.3, step 2): one per flush, per-process\n// monotonic, `max(Date.now() * 1000, last + 1)`: microseconds since the\n// epoch. A revision is taken before any row is read, so a payload is never\n// older than the revision it carries. Clients drop frames older than what\n// they hold, so two flushes in one millisecond must still get different\n// revisions, and a clock that steps back must not reuse one. In\n// microseconds a process takes a thousand revisions a millisecond and stays\n// on the clock, which `versionColumn` times are compared with (a time is its\n// milliseconds times 1,000: `emit/hub.ts`); revisions stay safe integers\n// (about 1.8e15, under 2^53).\n//\n// Behind a cluster adapter with a shared counter (`cluster/revisions.ts`),\n// flushes take their revisions from the counter instead, which keeps to\n// Valkey's clock in microseconds; the revisions it hands out are observed\n// here, so a revision this process takes later is never below one it\n// already sent.\n\nimport type { Revision } from \"../protocol/envelope\";\n\n/** Microseconds per millisecond: a revision is a time in microseconds. */\nexport const MICROS_PER_MS = 1000;\n\nlet last = 0;\n\n/** The clock as a revision: `Date.now()` in microseconds. */\nexport function clockRev(): Revision {\n return Date.now() * MICROS_PER_MS;\n}\n\n/** The next revision: the current time in microseconds, or one more than the last revision when that is later. */\nexport function nextRev(): Revision {\n last = Math.max(clockRev(), last + 1);\n return last;\n}\n\n/**\n * The revision a read made from now on is no older than, without taking a\n * new one: the last revision taken (one is taken when none was yet). Every\n * write whose flush took a revision up to it had committed before that\n * revision was taken, and any later flush takes a greater one. A read that\n * is not a flush (a subscription's rows) claims it rather than taking its\n * own, so reads do not push revisions ahead of the clock that\n * `versionColumn` times are compared with.\n */\nexport function currentRev(): Revision {\n return last === 0 ? nextRev() : last;\n}\n\n/** Records a revision taken elsewhere (the cluster's counter): later ones taken here are above it. */\nexport function observeRev(rev: Revision): void {\n last = Math.max(last, rev);\n}\n\n/**\n * The time a version column holds as a revision (microseconds since the\n * epoch: its milliseconds times 1,000), or `undefined` when it holds none. A\n * column holds a `Date`, a date string, or a number of milliseconds since\n * the epoch.\n */\nexport function versionTime(value: unknown): Revision | undefined {\n if (value instanceof Date) {\n const time = value.getTime();\n return Number.isNaN(time) ? undefined : time * MICROS_PER_MS;\n }\n if (typeof value === \"number\" && Number.isFinite(value)) {\n return value * MICROS_PER_MS;\n }\n if (typeof value === \"string\") {\n const time = Date.parse(value);\n return Number.isNaN(time) ? undefined : time * MICROS_PER_MS;\n }\n return undefined;\n}\n","// The tracked unit of work (RFC 0003 section 5.1). A write tracker holds the\n// writes of every unit of work in `AsyncLocalStorage` frames: a database\n// adapter (`trackPrisma` on `./prisma`) records each write into the frame\n// that is active where the write runs, and the dispatcher opens a unit per\n// handler run and flushes it after the response.\n//\n// Frames nest:\n//\n// - a unit's frame buffers the unit's writes until it flushes;\n// - a transaction's frame buffers its writes separately, and they join the\n// enclosing buffer only when the transaction commits; a rollback discards\n// them; an interactive transaction's frame also holds its transaction\n// client, so the adapter's own reads see the transaction's writes;\n// - a unit begun inside another open frame (an in-process call made from a\n// handler, `qd.run` inside a transaction) joins it: its writes go where\n// the enclosing frame's go, and its own flush does nothing; a detached\n// unit (`qd.run(fn, { detached: true })`, a handler's background work)\n// never joins: it starts a stack of its own and flushes on its own;\n// - `countStatements` frames only count.\n//\n// A write with no open buffer above it (a job that did not use `qd.run`, or\n// a handler's background work that outlived its unit's flush) is ambient: it\n// flushes on its own on the next tick, with a development warning.\n//\n// In development a method call's unit also checks the statements run in it\n// for N+1 shapes and unbounded reads (`statementChecks.ts`), and every\n// warning goes out in the shared format of `../devWarnings.ts`, naming the\n// call it happened in. A warning raised inside a method call goes to the\n// warnings of the dispatcher that runs the call (a strict test app's throw);\n// one raised elsewhere goes to the attached dispatcher's, never strictly.\n//\n// Dispatchers attach to the tracker as a stack: the last one attached\n// receives ambient writes and the warnings outside calls, and detaching it\n// (a server's `close()`) restores the one attached before.\n\nimport { AsyncLocalStorage } from \"node:async_hooks\";\nimport { randomUUID } from \"node:crypto\";\nimport { consoleLogger, type Logger } from \"../../contract/logger\";\nimport type { RunContext, RunOptions, TouchOptions } from \"../context\";\nimport { createDevWarnings, isQuiet, type DevWarning, type DevWarnings } from \"../devWarnings\";\nimport { flushWrites } from \"./flush\";\nimport { noFlushSink, type FlushSink } from \"./flushSink\";\nimport {\n createStatementChecks,\n type CallSite,\n type Statement,\n type StatementCheck,\n type StatementPlace,\n} from \"./statementChecks\";\nimport {\n ANY_FIELD,\n type UnitOfWork,\n type UnitOfWorkFactory,\n type UnitOfWorkScope,\n type WriteRecord,\n} from \"./types\";\n\n/** One level of the frame stack. Mutable flags close it once its unit flushed or its transaction settled. */\ninterface Frame {\n readonly parent: Frame | undefined;\n /** Where writes made here go; a frame without a buffer passes them up. */\n readonly buffer: WriteRecord[] | undefined;\n /** Writes in a unit's buffer are durable; a transaction's wait for its commit. */\n readonly durable: boolean;\n /** An interactive transaction's client, for the adapter's own reads. */\n tx: unknown;\n /** An array-form transaction: no client, and its operations cannot be rewritten. */\n readonly batch: boolean;\n /** Counts the statements issued in this frame and every frame inside it. */\n readonly count: ((statements: number) => void) | undefined;\n /** A method call's unit: the call warnings made inside it are about. */\n readonly call: CallSite | undefined;\n /** A method call's unit: its dispatcher's warnings, which those warnings go to. */\n readonly warnings: DevWarnings | undefined;\n /** A method call's unit in development: checks the statements run inside it. */\n readonly check: StatementCheck | undefined;\n open: boolean;\n}\n\n/** A warning the tracker raises; it adds the call it was raised in. */\nexport type TrackerWarning = Omit<DevWarning, \"service\" | \"method\">;\n\n/** An open transaction, from {@link WriteTracker.openTransaction}. */\nexport interface TrackedTransaction {\n /** Sets the interactive transaction's client, once the database has opened it. */\n setClient(tx: unknown): void;\n /** Runs `fn` inside the transaction's frame, awaiting its result there. */\n run<T>(fn: () => T | PromiseLike<T>): Promise<T>;\n /** The transaction committed: its writes join the enclosing buffer. */\n commit(): void;\n /** The transaction rolled back: its writes are dropped. */\n rollback(): void;\n}\n\n/** A statement count, from {@link WriteTracker.countStatements}. */\nexport interface StatementCount<T> {\n readonly value: T;\n readonly statements: number;\n}\n\n/** Options of {@link createWriteTracker}. */\nexport interface WriteTrackerOptions {\n /** Receives warnings until a dispatcher attaches its logger. Default: the console logger. */\n readonly logger?: Logger;\n /**\n * Raise development warnings: ambient, nested and batched writes, and the\n * checks of each method call's statements. Default: on unless `NODE_ENV`\n * is `\"production\"`.\n */\n readonly development?: boolean;\n}\n\n/**\n * Where a database adapter records writes, and the unit of work factory the\n * dispatcher opens units with. One tracker belongs to one tracked client.\n */\nexport interface WriteTracker {\n /** The units of work of handler runs and `qd.run` blocks: give it to the dispatcher. */\n readonly unitOfWork: UnitOfWorkFactory;\n /** Records writes where they ran: an open transaction, a unit of work, or the next tick's ambient flush. */\n record(writes: readonly WriteRecord[]): void;\n /** Records `ids` of `model` as changed, or as deleted with `removed`: `ctx.touch`. */\n touch(model: string, ids: readonly string[], options?: TouchOptions): void;\n /** Counts one statement in every open frame where it runs. */\n countStatement(): void;\n /** Opens a transaction frame inside the active one. */\n openTransaction(kind: \"interactive\" | \"batch\"): TrackedTransaction;\n /** The client of the open interactive transaction where this runs, or `undefined`. */\n transactionClient(): unknown;\n /** True inside an array-form transaction. */\n inBatch(): boolean;\n /** Runs `fn` and counts the statements it issued. */\n countStatements<T>(fn: () => T | PromiseLike<T>): Promise<StatementCount<T>>;\n /** Calls `listener` with each write once it is durable: in a unit of work, or flushing on its own. */\n onWrite(listener: (write: WriteRecord) => void): () => void;\n /**\n * Raises a development warning about the method call this runs in (none\n * outside a call): logged once, in the shared format, by the attached\n * dispatcher's warnings. Nothing outside development.\n */\n warn(warning: TrackerWarning): void;\n /**\n * Hands a statement the database client is about to run to the checks of\n * the method call it runs in (development only; nothing outside a call,\n * nor inside `quietly`).\n */\n observe(statement: Statement): void;\n /** The logger warnings go to: the attached dispatcher's, or the one given at creation. */\n readonly logger: Logger;\n}\n\n/** Where ambient writes flush and warnings outside a call go: the attached dispatcher's. */\ninterface Attachment {\n readonly sink: FlushSink;\n readonly logger: Logger;\n /** Never strict: warnings outside a method call only log. */\n readonly warnings: DevWarnings;\n}\n\ninterface TrackerState {\n readonly als: AsyncLocalStorage<Frame>;\n readonly listeners: Set<(write: WriteRecord) => void>;\n readonly development: boolean;\n /** Before any dispatcher attaches, and once every one detached. */\n readonly base: Attachment;\n /** The dispatchers attached, the current one last. */\n readonly attached: Attachment[];\n logger: Logger;\n warnings: DevWarnings;\n sink: FlushSink;\n ambient: WriteRecord[];\n /** Every statement counted since the tracker was created, wherever it ran. */\n issued: number;\n}\n\nconst ISSUED = new WeakMap<object, () => number>();\n\n/**\n * How many statements the tracked client of `unitOfWork` (a tracker's\n * `unitOfWork`, as `storage.unitOfWork` carries it) has counted since it was\n * created, in every async context: what `expectBudget` measures a test step\n * with. `undefined` for units of work no tracker made.\n */\nexport function statementsIssued(unitOfWork: object): number | undefined {\n return ISSUED.get(unitOfWork)?.();\n}\n\nfunction frameWhere(state: TrackerState, test: (frame: Frame) => boolean): Frame | undefined {\n for (let frame = state.als.getStore(); frame !== undefined; frame = frame.parent) {\n if (frame.open && test(frame)) {\n return frame;\n }\n }\n return undefined;\n}\n\nfunction warn(state: TrackerState, warning: TrackerWarning): void {\n if (!state.development) {\n return;\n }\n const frame = frameWhere(state, (candidate) => candidate.call !== undefined);\n if (frame?.call === undefined) {\n state.warnings.warn(warning);\n return;\n }\n (frame.warnings ?? state.warnings).warn({ ...warning, ...frame.call });\n}\n\n/** Where a statement runs: the innermost open buffer is a unit's, a batch's or an interactive transaction's. */\nfunction placeOf(state: TrackerState): StatementPlace {\n const open = frameWhere(state, (candidate) => candidate.buffer !== undefined);\n if (open?.batch === true) {\n return \"batch\";\n }\n return open?.tx === undefined ? \"unit\" : \"interactive\";\n}\n\nfunction observe(state: TrackerState, statement: Statement): void {\n if (!state.development || isQuiet()) {\n return;\n }\n const frame = frameWhere(state, (candidate) => candidate.check !== undefined);\n frame?.check?.(statement, placeOf(state));\n}\n\nfunction notify(state: TrackerState, writes: readonly WriteRecord[]): void {\n for (const listener of state.listeners) {\n for (const write of writes) {\n try {\n listener(write);\n } catch (error) {\n state.logger.error(\"An onWrite listener threw\", {\n category: \"quickdraw.writes\",\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\n }\n}\n\nfunction flushAmbient(state: TrackerState): void {\n const writes = state.ambient;\n state.ambient = [];\n const scope: UnitOfWorkScope = {\n requestId: randomUUID(),\n transport: \"internal\",\n sink: state.sink,\n };\n void flushWrites(writes, scope, state.logger);\n}\n\nfunction recordAmbient(state: TrackerState, writes: readonly WriteRecord[]): void {\n for (const model of new Set(writes.map((write) => write.model))) {\n warn(state, {\n kind: \"ambient-write\",\n subject: model,\n message: `A tracked write to ${model} ran outside any unit of work, so it flushes on its own; run jobs and scripts inside qd.run(...)`,\n meta: { model },\n });\n }\n if (state.ambient.length === 0) {\n setImmediate(() => flushAmbient(state));\n }\n state.ambient.push(...writes);\n notify(state, writes);\n}\n\n/**\n * `qd.run(fn)` made before any dispatcher exists (a boot-time seed written\n * before `createServer`): a unit of work no dispatcher opened, shared by\n * every tracked client. The writes each client makes in it are kept apart\n * from ambient writes (so they raise no warning) and flush once `fn`\n * settles, to the dispatcher that client is attached to by then: none\n * before any server exists, so they reach no one, as no socket could be\n * subscribed yet.\n */\ninterface LooseRun {\n /** The writes of each tracked client, until the run settles. */\n readonly writes: Map<TrackerState, WriteRecord[]>;\n /** False once the run settled: work it started and did not await writes as ambient then. */\n open: boolean;\n}\n\nconst looseRuns = new AsyncLocalStorage<LooseRun>();\n\n/** Keeps `writes` in the loose run this runs in, if any; false outside one. */\nfunction keptLoose(state: TrackerState, writes: readonly WriteRecord[]): boolean {\n const run = looseRuns.getStore();\n if (run === undefined || !run.open) {\n return false;\n }\n run.writes.set(state, [...(run.writes.get(state) ?? []), ...writes]);\n notify(state, writes);\n return true;\n}\n\n/**\n * `qd.run(fn)` before its instance created any dispatcher: `fn` runs in a\n * unit of work no dispatcher opened, with a context that records nothing\n * (no tracked client is known to `ctx.touch`) and logs to the console.\n */\nexport async function runBeforeAnyDispatcher<R>(\n fn: (ctx: RunContext) => R | PromiseLike<R>,\n options?: RunOptions,\n): Promise<R> {\n if (typeof fn !== \"function\") {\n throw new TypeError(\"run: pass the function to run inside a unit of work\");\n }\n if (options !== undefined && (typeof options !== \"object\" || options === null)) {\n throw new TypeError(\"run: options must be an object, { detached?: boolean }\");\n }\n const ctx: RunContext = Object.freeze({\n touch: () => undefined,\n log: consoleLogger.child({ requestId: randomUUID() }),\n principal: null,\n });\n return await runLoose(() => fn(ctx));\n}\n\n/**\n * Runs `fn` in a unit of work no dispatcher opened (`qd.run` before any\n * exists): every tracked client's writes in it flush once `fn` settles,\n * whether it resolved or threw, each to the dispatcher its client is\n * attached to then, which before any server is none.\n */\nasync function runLoose<T>(fn: () => T | PromiseLike<T>): Promise<T> {\n const run: LooseRun = { writes: new Map(), open: true };\n try {\n return await looseRuns.run(run, async () => await fn());\n } finally {\n run.open = false;\n const flushed = [...run.writes].map(async ([state, writes]) => {\n const scope: UnitOfWorkScope = {\n requestId: randomUUID(),\n transport: \"internal\",\n sink: state.sink,\n };\n await flushWrites(writes, scope, state.logger);\n });\n run.writes.clear();\n await Promise.all(flushed);\n }\n}\n\n/** Puts `writes` in the first open buffer at or above `from`, or flushes them on their own. */\nfunction deliver(\n state: TrackerState,\n writes: readonly WriteRecord[],\n from: Frame | undefined,\n): void {\n if (writes.length === 0) {\n return;\n }\n for (let frame = from; frame !== undefined; frame = frame.parent) {\n if (frame.open && frame.buffer !== undefined) {\n frame.buffer.push(...writes);\n if (frame.durable) {\n notify(state, writes);\n }\n return;\n }\n }\n if (!keptLoose(state, writes)) {\n recordAmbient(state, writes);\n }\n}\n\nfunction openTransaction(state: TrackerState, kind: \"interactive\" | \"batch\"): TrackedTransaction {\n const parent = state.als.getStore();\n const frame: Frame = {\n parent,\n buffer: [],\n durable: false,\n tx: undefined,\n batch: kind === \"batch\",\n count: undefined,\n call: undefined,\n warnings: undefined,\n check: undefined,\n open: true,\n };\n return {\n setClient: (tx) => {\n frame.tx = tx;\n },\n run: (fn) => state.als.run(frame, async () => await fn()),\n commit: () => {\n frame.open = false;\n deliver(state, frame.buffer ?? [], parent);\n },\n rollback: () => {\n frame.open = false;\n },\n };\n}\n\nasync function countStatements<T>(\n state: TrackerState,\n fn: () => T | PromiseLike<T>,\n): Promise<StatementCount<T>> {\n let statements = 0;\n const frame: Frame = {\n parent: state.als.getStore(),\n buffer: undefined,\n durable: false,\n tx: undefined,\n batch: false,\n count: (n) => {\n statements += n;\n },\n call: undefined,\n warnings: undefined,\n check: undefined,\n open: true,\n };\n try {\n const value = await state.als.run(frame, async () => await fn());\n return { value, statements };\n } finally {\n frame.open = false;\n }\n}\n\n/**\n * The method call a unit's scope names, the warnings of the dispatcher that\n * runs it (the tracker's own when that dispatcher's are off, as for a\n * production dispatcher over a development tracker), and in development the\n * checks of its statements.\n */\nfunction callOf(\n state: TrackerState,\n scope: UnitOfWorkScope,\n): Pick<Frame, \"call\" | \"warnings\" | \"check\"> {\n if (scope.service === undefined || scope.method === undefined) {\n return { call: undefined, warnings: undefined, check: undefined };\n }\n const call: CallSite = { service: scope.service, method: scope.method };\n const warnings = scope.warnings?.enabled === true ? scope.warnings : state.warnings;\n if (!state.development) {\n return { call, warnings, check: undefined };\n }\n return {\n call,\n warnings,\n check: createStatementChecks((warning) => warnings.warn({ ...warning, ...call })),\n };\n}\n\n/** A unit of work over the tracker's frames. */\nfunction createUnit(state: TrackerState, scope: UnitOfWorkScope): UnitOfWork {\n let statements = 0;\n let frame: Frame | undefined;\n let flushed = false;\n const writes: WriteRecord[] = [];\n return {\n get sqlStatements() {\n return statements;\n },\n run<T>(fn: () => T | PromiseLike<T>): Promise<T> {\n // Inside an open buffer (a transaction, another unit), this unit joins it, unless it is\n // detached: then it stands alone, outside every frame open where it was begun.\n const detached = scope.detached === true;\n const joins =\n !detached && frameWhere(state, (candidate) => candidate.buffer !== undefined) !== undefined;\n const own: Frame = {\n parent: detached ? undefined : state.als.getStore(),\n buffer: joins ? undefined : writes,\n durable: true,\n tx: undefined,\n batch: false,\n count: (n) => {\n statements += n;\n },\n ...callOf(state, scope),\n open: true,\n };\n frame = own;\n return state.als.run(own, async () => await fn());\n },\n async flush(): Promise<void> {\n if (flushed) {\n return;\n }\n flushed = true;\n if (frame !== undefined) {\n frame.open = false;\n }\n await flushWrites(writes.splice(0), scope, state.logger);\n },\n };\n}\n\nfunction touchWrites(\n model: string,\n ids: readonly string[],\n options: TouchOptions | undefined,\n): WriteRecord[] {\n const removed = options?.removed === true;\n return [...new Set(ids)].map((id) => ({\n model,\n id,\n op: removed ? \"delete\" : \"update\",\n fields: removed ? [] : [ANY_FIELD],\n }));\n}\n\n/**\n * The warnings an attaching dispatcher's give the tracker for warnings\n * outside its calls: its own, unless they are off (a tracker made with\n * `development: true` keeps warning under a production dispatcher, as it\n * always did) or strict (only a strict dispatcher's calls throw).\n */\nfunction outsideCalls(\n state: TrackerState,\n logger: Logger,\n warnings: DevWarnings | undefined,\n): DevWarnings {\n return warnings?.enabled === true && !warnings.strict\n ? warnings\n : createDevWarnings({ logger, development: state.development });\n}\n\n/** Makes `attachment` the current one, until the returned function detaches it. */\nfunction attach(state: TrackerState, attachment: Attachment): () => void {\n const follow = (): void => {\n const current = state.attached.at(-1) ?? state.base;\n state.sink = current.sink;\n state.logger = current.logger;\n state.warnings = current.warnings;\n };\n state.attached.push(attachment);\n follow();\n return () => {\n const index = state.attached.indexOf(attachment);\n if (index !== -1) {\n state.attached.splice(index, 1);\n follow();\n }\n };\n}\n\n/** Creates the write tracker of one tracked database client. */\nexport function createWriteTracker(options: WriteTrackerOptions = {}): WriteTracker {\n const development = options.development ?? process.env.NODE_ENV !== \"production\";\n const logger = options.logger ?? consoleLogger;\n const base: Attachment = {\n sink: noFlushSink,\n logger,\n warnings: createDevWarnings({ logger, development }),\n };\n const state: TrackerState = {\n als: new AsyncLocalStorage<Frame>(),\n listeners: new Set(),\n development,\n base,\n attached: [],\n ...base,\n ambient: [],\n issued: 0,\n };\n const touch = (model: string, ids: readonly string[], touchOptions?: TouchOptions): void =>\n deliver(state, touchWrites(model, ids, touchOptions), state.als.getStore());\n const unitOfWork: UnitOfWorkFactory = Object.freeze({\n begin: (scope: UnitOfWorkScope) => createUnit(state, scope),\n touch,\n attach: (sink: FlushSink, attached: Logger, warnings?: DevWarnings) =>\n attach(state, { sink, logger: attached, warnings: outsideCalls(state, attached, warnings) }),\n });\n ISSUED.set(unitOfWork, () => state.issued);\n return Object.freeze({\n unitOfWork,\n record: (writes: readonly WriteRecord[]) => deliver(state, writes, state.als.getStore()),\n touch,\n countStatement(): void {\n state.issued += 1;\n for (let frame = state.als.getStore(); frame !== undefined; frame = frame.parent) {\n if (frame.open) {\n frame.count?.(1);\n }\n }\n },\n openTransaction: (kind: \"interactive\" | \"batch\") => openTransaction(state, kind),\n transactionClient: () => frameWhere(state, (frame) => frame.tx !== undefined)?.tx,\n inBatch: () => frameWhere(state, (frame) => frame.buffer !== undefined)?.batch === true,\n countStatements: <T>(fn: () => T | PromiseLike<T>) => countStatements(state, fn),\n onWrite(listener: (write: WriteRecord) => void): () => void {\n state.listeners.add(listener);\n return () => {\n state.listeners.delete(listener);\n };\n },\n warn: (warning: TrackerWarning) => warn(state, warning),\n observe: (statement: Statement) => observe(state, statement),\n get logger() {\n return state.logger;\n },\n });\n}\n","// The flush (RFC 0003 section 5.3): once a handler has settled and its\n// response was sent, its unit of work merges the recorded writes per row,\n// takes one revision, and hands the batch to the dispatcher's sinks in the\n// order they were given. A sink that throws is logged with the rows it\n// failed on; every other sink then hears about it through `onFlushError`.\n// Nothing here rejects: the caller's response was already sent.\n//\n// A dispatcher runs its flushes one after another, in revision order\n// (`inRevisionOrder`): a flush's sinks run once every flush with a lower\n// revision has finished its own, so frames leave in revision order and a\n// client that merges a patch only \"when rev is newer\" never drops one.\n\nimport { AsyncLocalStorage } from \"node:async_hooks\";\nimport type { Logger } from \"../../contract/logger\";\nimport { describeError } from \"../pipeline/metrics\";\nimport { nextRev } from \"../rev\";\nimport { noFlushSink, type FlushInfo, type FlushSink } from \"./flushSink\";\nimport { mergeRecords } from \"./records\";\nimport type { UnitOfWorkScope, WriteRecord } from \"./types\";\n\n/** How many rows a failure's log entry names. */\nconst LOGGED_ROWS = 20;\n\nfunction logFailure(\n logger: Logger,\n message: string,\n writes: readonly WriteRecord[],\n info: FlushInfo,\n error: unknown,\n): void {\n logger.error(message, {\n category: \"quickdraw.flush\",\n requestId: info.requestId,\n service: info.service,\n method: info.method,\n rev: info.rev,\n rowCount: writes.length,\n rows: writes.slice(0, LOGGED_ROWS).map((write) => `${write.op} ${write.model} ${write.id}`),\n error: describeError(error),\n });\n}\n\n/**\n * Merges `records`, takes one revision and hands the batch to `scope.sink`.\n * With nothing recorded, or nothing left once merged (rows the unit created\n * and deleted again), no revision is taken and the sink is not called.\n * Never rejects; a sink's failure is logged.\n */\nexport async function flushWrites(\n records: readonly WriteRecord[],\n scope: UnitOfWorkScope,\n logger: Logger,\n): Promise<void> {\n const writes = mergeRecords(records);\n if (writes.length === 0) {\n return;\n }\n // The call's warnings stay with the unit: sinks see where the writes came from.\n const { sink, warnings: _warnings, detached: _detached, ...origin } = scope;\n const info: FlushInfo = { ...origin, rev: nextRev() };\n try {\n await sink.flush(writes, info);\n } catch (error) {\n logFailure(\n logger,\n \"Flushing writes failed; the response was already sent\",\n writes,\n info,\n error,\n );\n }\n}\n\ninterface Failure {\n readonly sink: FlushSink;\n readonly error: unknown;\n}\n\n/** Tells every sink but the one that failed, after all of them ran. */\nasync function reportFailures(\n sinks: readonly FlushSink[],\n failures: readonly Failure[],\n writes: readonly WriteRecord[],\n info: FlushInfo,\n logger: Logger,\n): Promise<void> {\n for (const sink of sinks) {\n const failure = failures.find((candidate) => candidate.sink !== sink);\n if (failure === undefined || sink.onFlushError === undefined) {\n continue;\n }\n try {\n await sink.onFlushError(writes, info, failure.error);\n } catch (error) {\n logFailure(\n logger,\n \"A flush sink failed to handle another sink's failure\",\n writes,\n info,\n error,\n );\n }\n }\n}\n\n/**\n * Where a dispatcher's flushes take their revision when it is not the one\n * `flushWrites` took: a cluster's shared counter (`../cluster/revisions.ts`).\n */\nexport interface FlushRevisions {\n /**\n * Called when a flush arrives: `undefined` to keep the flush's own\n * revision, or a function that resolves with the revision to use instead,\n * called when the flush's turn comes.\n */\n forFlush(): (() => Promise<number>) | undefined;\n}\n\n/**\n * A sink that runs the flushes it receives one at a time, in the order they\n * arrive, which is revision order: `flushWrites` takes a flush's revision\n * and hands the batch over in one synchronous step. A flush waits until the\n * flush before it has finished every sink; one that fails does not hold up\n * the next. A flush started from inside one of these runs (a sink that\n * writes through `qd.run`) runs at once instead: waiting for the run that\n * started it would never end.\n *\n * With `revisions` that hand out their own (a cluster's shared counter), a\n * flush asks for its revision when it arrives, and its sinks run with it\n * once its turn comes and the answer is in: still in arrival order, which\n * the revisions keep increasing.\n */\nexport function inRevisionOrder(sink: FlushSink, revisions?: FlushRevisions): FlushSink {\n const running = new AsyncLocalStorage<true>();\n let last: Promise<void> = Promise.resolve();\n return Object.freeze({\n flush(writes: readonly WriteRecord[], info: FlushInfo): Promise<void> {\n const shared = revisions?.forFlush();\n const flushOne =\n shared === undefined\n ? () => sink.flush(writes, info)\n : async () => await sink.flush(writes, { ...info, rev: await shared() });\n if (running.getStore() === true) {\n return flushOne();\n }\n const run = last.then(() => running.run(true, flushOne));\n last = run.catch(() => undefined);\n return run;\n },\n });\n}\n\n/**\n * One sink made of several: each batch goes to every sink in order, a sink\n * that throws is logged and the others still run, and once all have run\n * every sink but a failed one receives `onFlushError`. It never rejects. A\n * lone sink is returned as it is, and no sinks make one that does nothing.\n */\nexport function combineSinks(sinks: readonly FlushSink[], logger: Logger): FlushSink {\n const all = [...sinks];\n if (all.length === 0) {\n return noFlushSink;\n }\n if (all.length === 1 && all[0] !== undefined) {\n return all[0];\n }\n return Object.freeze({\n async flush(writes: readonly WriteRecord[], info: FlushInfo): Promise<void> {\n const failures: Failure[] = [];\n for (const sink of all) {\n try {\n await sink.flush(writes, info);\n } catch (error) {\n failures.push({ sink, error });\n logFailure(\n logger,\n \"A flush sink failed; the response was already sent\",\n writes,\n info,\n error,\n );\n }\n }\n if (failures.length > 0) {\n await reportFailures(all, failures, writes, info, logger);\n }\n },\n });\n}\n","// The flush sink seam (RFC 0003 section 5.3): where a unit of work's writes\n// go once the response is sent. The unit merges its writes per row and takes\n// one revision (`flush.ts`); each sink then turns the batch into what it\n// emits: entity frames, collection deltas, change signals, cache evictions.\n\nimport type { Revision } from \"../../protocol/envelope\";\nimport type { UnitOfWorkScope, WriteRecord } from \"./types\";\n\n/** What a sink learns about a flush besides its writes: where they came from, and the flush's revision. */\nexport interface FlushInfo extends Omit<UnitOfWorkScope, \"sink\" | \"warnings\" | \"detached\"> {\n /**\n * The flush's revision (RFC 0003 section 5.3, step 2), taken once for the\n * whole batch before any sink runs, so before any row is read.\n */\n readonly rev: Revision;\n}\n\n/**\n * Receives the writes of one unit of work after the response has been sent:\n * one record per row, merged. A failure is logged with the affected rows and\n * never fails the response.\n */\nexport interface FlushSink {\n flush(writes: readonly WriteRecord[], info: FlushInfo): Promise<void>;\n /**\n * Called when another sink failed to flush this batch, after every sink\n * ran, so this one can make up for what that one did not send (the\n * collections sink sends a `reset`). Its own failure is logged.\n */\n onFlushError?(\n writes: readonly WriteRecord[],\n info: FlushInfo,\n error: unknown,\n ): void | Promise<void>;\n}\n\n/** The default sink: there is nothing to emit until writes are tracked. */\nexport const noFlushSink: FlushSink = Object.freeze({\n flush: (): Promise<void> => Promise.resolve(),\n});\n","// Merging a unit of work's writes per row (RFC 0003 section 5.3, step 1).\n// A handler that updates one row ten times flushes one record, so a sink\n// reads that row once and a subscriber receives one frame.\n//\n// Per row, in the order the writes happened:\n//\n// - A row the unit created and then deleted is dropped: it never existed\n// outside the unit, so no sink, change log or topic hears of it. Its create\n// must be certain: an `upsert` that read nothing (`mayHaveExisted`) may\n// have updated a row that existed, whose delete is kept, with the values\n// the writes carry.\n// - Otherwise `delete` beats `create` beats `update`, read as \"the row's\n// final state\": a row whose last write deleted it is a `delete`; a row\n// that was created, or deleted and created again, is a `create`, which\n// sinks send whole; anything else is an `update`.\n// - `fields` are unioned.\n// - `before` keeps the earliest value of each column: the row as subscribers\n// last saw it, since nothing was emitted during the unit. A row the unit\n// created has none.\n// - `after` keeps the latest value of each column written since the row was\n// last deleted; a deleted row has none.\n\nimport { ANY_FIELD, type WriteRecord } from \"./types\";\n\ntype Values = Readonly<Record<string, unknown>>;\n\n/** One row's writes, oldest first. */\ntype History = readonly [WriteRecord, ...WriteRecord[]];\n\nfunction mergeFields(history: History): readonly string[] {\n const fields = new Set<string>();\n for (const record of history) {\n for (const field of record.fields) {\n fields.add(field);\n }\n }\n return fields.has(ANY_FIELD) ? [ANY_FIELD] : [...fields];\n}\n\n/** Merges value maps; with `keepFirst`, the first value of a key wins, otherwise the last. */\nfunction mergeValues(\n maps: readonly (Values | undefined)[],\n keepFirst: boolean,\n): Values | undefined {\n let merged: Record<string, unknown> | undefined;\n for (const values of maps) {\n if (values === undefined) {\n continue;\n }\n merged ??= {};\n for (const [key, value] of Object.entries(values)) {\n if (!keepFirst || !Object.hasOwn(merged, key)) {\n merged[key] = value;\n }\n }\n }\n return merged;\n}\n\nfunction finalOp(history: History): WriteRecord[\"op\"] {\n if (history[history.length - 1]?.op === \"delete\") {\n return \"delete\";\n }\n return history.some((record) => record.op === \"create\") ? \"create\" : \"update\";\n}\n\n/** The writes since the row was last deleted: what its `after` values describe. */\nfunction sinceLastDelete(history: History): readonly WriteRecord[] {\n let start = 0;\n history.forEach((record, index) => {\n if (record.op === \"delete\") {\n start = index + 1;\n }\n });\n return history.slice(start);\n}\n\n/** True when the row's first write certainly created it: not an upsert that read nothing. */\nfunction created(first: WriteRecord): boolean {\n return first.op === \"create\" && first.mayHaveExisted !== true;\n}\n\n/** The row's one merged record, or `undefined` for a row the unit created and deleted again. */\nfunction mergeRow(history: History): WriteRecord | undefined {\n const [first] = history;\n if (created(first) && history[history.length - 1]?.op === \"delete\") {\n return undefined;\n }\n if (history.length === 1) {\n return first;\n }\n const op = finalOp(history);\n const before = created(first)\n ? undefined\n : mergeValues(\n history.map((record) => record.before),\n true,\n );\n const after =\n op === \"delete\"\n ? undefined\n : mergeValues(\n sinceLastDelete(history).map((record) => record.after),\n false,\n );\n return {\n model: first.model,\n id: first.id,\n op,\n fields: mergeFields(history),\n ...(before === undefined ? {} : { before }),\n ...(after === undefined ? {} : { after }),\n };\n}\n\n/**\n * Merges a unit of work's writes into one record per row, in the order each\n * row was first written; a row the unit created and deleted again has none.\n * See the rules at the top of this file.\n */\nexport function mergeRecords(records: readonly WriteRecord[]): WriteRecord[] {\n const rows = new Map<string, [WriteRecord, ...WriteRecord[]]>();\n for (const record of records) {\n const key = `${record.model}\\u0000${record.id}`;\n const history = rows.get(key);\n if (history === undefined) {\n rows.set(key, [record]);\n } else {\n history.push(record);\n }\n }\n return [...rows.values()].flatMap((history) => mergeRow(history) ?? []);\n}\n","// The development checks of a method call's statements (`../devWarnings.ts`):\n// N+1 statements and unbounded reads. The tracked database client tells the\n// write tracker about each statement before it runs (`trackPrisma`'s hook),\n// and the tracker hands it to the checks of the innermost method call it\n// runs in. A statement outside a method call (a `qd.run` job, a flush, a\n// subscription) is not checked, and neither is one the framework runs\n// `quietly`.\n\nimport { N_PLUS_ONE_STATEMENTS, type DevWarning } from \"../devWarnings\";\n\n/** One statement the tracked database client is about to run. */\nexport interface Statement {\n /** The model, named as the client names it: `\"task\"`. */\n readonly model: string;\n /** The client operation: `\"findMany\"`. */\n readonly operation: string;\n readonly args: Readonly<Record<string, unknown>> | undefined;\n}\n\n/** The method call a unit of work runs. */\nexport interface CallSite {\n readonly service: string;\n readonly method: string;\n}\n\n/**\n * Where a statement runs: in the call's unit, inside an array-form\n * `$transaction([...])` (`\"batch\"`), or inside an interactive\n * `$transaction(async (tx) => ...)` (`\"interactive\"`).\n */\nexport type StatementPlace = \"unit\" | \"batch\" | \"interactive\";\n\n/** Checks one statement of a call, run at `place`. */\nexport type StatementCheck = (statement: Statement, place: StatementPlace) => void;\n\n/** Raises a warning about the call the checks belong to. */\nexport type RaiseWarning = (warning: Omit<DevWarning, \"service\" | \"method\">) => void;\n\nfunction isRecord(value: unknown): value is Readonly<Record<string, unknown>> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\n/** The keys a statement filters by, sorted: its shape besides the model and operation. */\nfunction whereKeys(statement: Statement): string[] {\n const where = statement.args?.where;\n return isRecord(where) ? Object.keys(where).sort() : [];\n}\n\n/**\n * Whether an `id` filter names the rows it reads: a value (equality), or\n * `{ in }` or `{ equals }`. `{ not }`, `{ notIn }` and comparisons leave\n * every other row.\n */\nfunction namesIds(filter: unknown): boolean {\n if (filter === undefined) {\n return false;\n }\n if (!isRecord(filter)) {\n return true;\n }\n return filter.in !== undefined || filter.equals !== undefined;\n}\n\n/**\n * A `findMany` that can return every row of its table: no `take`, and no\n * `id` filter that names its rows (a read by ids is bounded by the ids it\n * names). The same test as the lint rule `no-unbounded-read`, made on the\n * arguments the statement actually ran with.\n */\nexport function isUnboundedRead(statement: Statement): boolean {\n if (statement.operation !== \"findMany\") {\n return false;\n }\n const { take, where } = statement.args ?? {};\n if (take !== undefined && take !== null) {\n return false;\n }\n return !(isRecord(where) && namesIds(where.id));\n}\n\n/**\n * An update or delete of one row by its id inside an interactive\n * transaction: the sanctioned form of per-row writes whose data differs per\n * row (one that moves a row or changes who may see it must read the row\n * first, which an array-form `$transaction` cannot do inside the batch).\n */\nfunction isRowWriteInTransaction(statement: Statement, place: StatementPlace): boolean {\n if (place !== \"interactive\") {\n return false;\n }\n if (statement.operation !== \"update\" && statement.operation !== \"delete\") {\n return false;\n }\n const keys = whereKeys(statement);\n return keys.length === 1 && keys[0] === \"id\";\n}\n\n/**\n * A statement filtered by an `id` list (`{ id: { in: ids } }`): one query\n * per list, as in a loop over chunks of ids, so never an N+1. The lint rule\n * `no-db-call-in-loop` makes the same exception.\n */\nfunction readsIdList(statement: Statement): boolean {\n const where = statement.args?.where;\n const id = isRecord(where) ? where.id : undefined;\n return isRecord(id) && Array.isArray(id.in);\n}\n\nfunction nPlusOne(\n statement: Statement,\n keys: readonly string[],\n): Omit<DevWarning, \"service\" | \"method\"> {\n const label = `${statement.model}.${statement.operation}${keys.length === 0 ? \"\" : ` by ${keys.join(\", \")}`}`;\n return {\n kind: \"n-plus-one\",\n message:\n `${label} ran ${N_PLUS_ONE_STATEMENTS} times in one call, once per item (N+1); ` +\n \"read the rows in one query (findMany({ where: { id: { in: ids } } })), write them in one when every row gets the same data \" +\n \"(updateMany, createMany), or write each row by id inside an interactive transaction (db.$transaction(async (tx) => ...))\",\n meta: { model: statement.model, operation: statement.operation, where: keys },\n };\n}\n\nfunction unboundedRead(statement: Statement): Omit<DevWarning, \"service\" | \"method\"> {\n return {\n kind: \"unbounded-read\",\n message:\n `${statement.model}.findMany() without take reads every matching row, however many there are; ` +\n \"add take (with a cursor to page), or serve the list as a collection or the read/write kit's list\",\n meta: { model: statement.model },\n };\n}\n\n/**\n * The checks of one method call: warns once its statements of one shape\n * (model, operation and `where` keys) reach {@link N_PLUS_ONE_STATEMENTS}, and\n * at an unbounded read. Statements batched in an array-form `$transaction`\n * are sent together, which is the fix for an N+1, so they are not counted;\n * neither are updates and deletes by id inside an interactive transaction,\n * the form per-row writes take when each row's data differs, nor statements\n * filtered by an `id` list (one per chunk of ids).\n */\nexport function createStatementChecks(raise: RaiseWarning): StatementCheck {\n const shapes = new Map<string, number>();\n return (statement, place) => {\n if (isUnboundedRead(statement)) {\n raise(unboundedRead(statement));\n }\n if (place === \"batch\" || isRowWriteInTransaction(statement, place) || readsIdList(statement)) {\n return;\n }\n const keys = whereKeys(statement);\n const shape = `${statement.model}.${statement.operation}(${keys.join(\",\")})`;\n const seen = (shapes.get(shape) ?? 0) + 1;\n shapes.set(shape, seen);\n if (seen === N_PLUS_ONE_STATEMENTS) {\n raise(nPlusOne(statement, keys));\n }\n };\n}\n"],"mappings":"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","names":["AsyncLocalStorage","AsyncLocalStorage","AsyncLocalStorage","last","AsyncLocalStorage"]}
|