@fitzzero/quickdraw-core 5.1.1 → 5.1.3
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 +1308 -219
- package/dist/{admin-DKwkIh5i.d.ts → admin-CS7JB_UH.d.ts} +2 -2
- package/dist/{adminSchemas-2DUA_hZ8.d.ts → adminSchemas-29cGgrg5.d.ts} +6 -4
- package/dist/{auth-BhWqdyb-.d.ts → auth-DtdYjrZ9.d.ts} +51 -21
- package/dist/{caller-CXTFswBO.d.ts → caller-BTwGl7vm.d.ts} +296 -33
- package/dist/chunk-2FDSKLBO.js +82 -0
- package/dist/chunk-2FDSKLBO.js.map +1 -0
- package/dist/{chunk-RT6OILOI.js → chunk-4D2DOGAW.js} +2 -14
- package/dist/chunk-4D2DOGAW.js.map +1 -0
- package/dist/{chunk-OECZPRPW.js → chunk-64I6MYBC.js} +162 -775
- package/dist/chunk-64I6MYBC.js.map +1 -0
- package/dist/chunk-7473HK24.js +17 -0
- package/dist/chunk-7473HK24.js.map +1 -0
- package/dist/chunk-7Y5ROPXL.js +33 -0
- package/dist/chunk-7Y5ROPXL.js.map +1 -0
- package/dist/chunk-A2RBQD66.js +7 -0
- package/dist/chunk-A2RBQD66.js.map +1 -0
- package/dist/chunk-AK23XSWD.js +16 -0
- package/dist/chunk-AK23XSWD.js.map +1 -0
- package/dist/chunk-ASAMUGHG.js +651 -0
- package/dist/chunk-ASAMUGHG.js.map +1 -0
- package/dist/{chunk-B2P7AZ25.js → chunk-CYE4UBOB.js} +6 -4
- package/dist/chunk-CYE4UBOB.js.map +1 -0
- package/dist/chunk-DKE6QO26.js +136 -0
- package/dist/chunk-DKE6QO26.js.map +1 -0
- package/dist/chunk-DNP65TD5.js +832 -0
- package/dist/chunk-DNP65TD5.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-GYLWEJHW.js +19 -0
- package/dist/chunk-GYLWEJHW.js.map +1 -0
- package/dist/{chunk-SHEGLZEP.js → chunk-I3JCFS7H.js} +34 -13
- package/dist/chunk-I3JCFS7H.js.map +1 -0
- package/dist/{chunk-X5CWPX7H.js → chunk-IIQ3WMJK.js} +13 -2
- package/dist/chunk-IIQ3WMJK.js.map +1 -0
- package/dist/{chunk-RZTP4IEW.js → chunk-JVTONQFI.js} +6339 -4226
- package/dist/chunk-JVTONQFI.js.map +1 -0
- package/dist/{chunk-QEKVYG5F.js → chunk-KKQANRLG.js} +2 -2
- package/dist/chunk-KKQANRLG.js.map +1 -0
- package/dist/{chunk-CDKG4TFA.js → chunk-MPQAT55F.js} +38 -205
- package/dist/chunk-MPQAT55F.js.map +1 -0
- 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-NX2V6SIL.js +202 -0
- package/dist/chunk-NX2V6SIL.js.map +1 -0
- package/dist/{chunk-ZIVPHYRG.js → chunk-NZHA4TZD.js} +72 -175
- package/dist/chunk-NZHA4TZD.js.map +1 -0
- package/dist/{chunk-2PWMUVC7.js → chunk-OCZJ4EYV.js} +518 -27
- package/dist/chunk-OCZJ4EYV.js.map +1 -0
- package/dist/{chunk-REX5YPHX.js → chunk-PHCURHC7.js} +76 -21
- package/dist/chunk-PHCURHC7.js.map +1 -0
- package/dist/{chunk-4YO5H5ON.js → chunk-Q4OGQM5I.js} +4 -10
- package/dist/chunk-Q4OGQM5I.js.map +1 -0
- package/dist/chunk-QSU47XEX.js +13 -0
- package/dist/chunk-QSU47XEX.js.map +1 -0
- package/dist/{chunk-DD4SKCNO.js → chunk-RZXJTDH5.js} +13 -2
- package/dist/chunk-RZXJTDH5.js.map +1 -0
- package/dist/{chunk-Z2LZ7IZ7.js → chunk-SN3OZVEQ.js} +5 -31
- package/dist/chunk-SN3OZVEQ.js.map +1 -0
- package/dist/{chunk-4DIQHASK.js → chunk-SQ5VUG77.js} +28 -8
- package/dist/chunk-SQ5VUG77.js.map +1 -0
- package/dist/chunk-STH5DLQP.js +1192 -0
- package/dist/chunk-STH5DLQP.js.map +1 -0
- package/dist/{chunk-QCHKWIRS.js → chunk-VZFJTKIW.js} +13 -13
- package/dist/{chunk-QCHKWIRS.js.map → chunk-VZFJTKIW.js.map} +1 -1
- package/dist/{chunk-VSQBHPWH.js → chunk-X4ZU4QH5.js} +54 -22
- package/dist/chunk-X4ZU4QH5.js.map +1 -0
- package/dist/chunk-XD7SRDUY.js +188 -0
- package/dist/chunk-XD7SRDUY.js.map +1 -0
- package/dist/chunk-XH2IZVLT.js +62 -0
- package/dist/chunk-XH2IZVLT.js.map +1 -0
- package/dist/chunk-Z7I6SONO.js +825 -0
- package/dist/chunk-Z7I6SONO.js.map +1 -0
- package/dist/cli/quickdraw-docs.js +132 -112
- package/dist/cli/quickdraw-docs.js.map +1 -1
- package/dist/client/core.d.ts +387 -0
- package/dist/client/core.js +109 -0
- package/dist/client/index.d.ts +52 -203
- package/dist/client/index.js +59 -218
- package/dist/client/index.js.map +1 -1
- package/dist/{clientTypes-Bc-G8n-U.d.ts → clientTypes-CUUNJwWs.d.ts} +3 -3
- package/dist/{connection-Cr1BU07W.d.ts → connection-2EeQ_Et0.d.ts} +22 -11
- package/dist/{createServer-CP9eDHZZ.d.ts → createServer-Bx5HOcYK.d.ts} +67 -17
- package/dist/{createTestApp-UKVGEmOf.d.ts → createTestApp-DAMANT79.d.ts} +46 -13
- package/dist/{envelope-Cp3YcVxC.d.ts → envelope-BMBaxppV.d.ts} +216 -10
- package/dist/{http-Djj2Inuu.d.ts → http-YzLAar3w.d.ts} +76 -60
- package/dist/index.d.ts +8 -7
- package/dist/index.js +82 -25
- package/dist/index.js.map +1 -1
- package/dist/{infer-Teo1xpsd.d.ts → infer-Br62cnyW.d.ts} +82 -11
- package/dist/logger-Yz93KzdV.d.ts +30 -0
- package/dist/{metrics-BdBu5o8G.d.ts → metrics-CTVpw0gu.d.ts} +2 -2
- package/dist/origins-kvpxnVcW.d.ts +8 -0
- package/dist/parser.js +2 -1
- package/dist/prisma/index.d.ts +14 -7
- package/dist/prisma/index.js +279 -70
- package/dist/prisma/index.js.map +1 -1
- package/dist/{rateLimit-ZMIZJUZF.js → rateLimit-5RKBFLUR.js} +2 -2
- package/dist/rateLimit-5RKBFLUR.js.map +1 -0
- package/dist/remote-N7OUAGOW.js +15 -0
- package/dist/remote-N7OUAGOW.js.map +1 -0
- package/dist/server/auth/index.d.ts +82 -33
- package/dist/server/auth/index.js +277 -270
- 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 +268 -84
- package/dist/server/index.js +664 -418
- package/dist/server/index.js.map +1 -1
- package/dist/server/mcp/index.d.ts +89 -27
- package/dist/server/mcp/index.js +281 -62
- 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-BrsmlDv_.d.ts} +3 -3
- package/dist/testing/client.d.ts +14 -14
- package/dist/testing/client.js +19 -10
- package/dist/testing/client.js.map +1 -1
- package/dist/testing/index.d.ts +50 -13
- package/dist/testing/index.js +113 -21
- package/dist/testing/index.js.map +1 -1
- package/dist/testing/mock.d.ts +5 -5
- package/dist/testing/mock.js +17 -9
- package/dist/tracked-BR5b2O-U.d.ts +43 -0
- package/dist/{types-Cu0vmx7c.d.ts → types-CLRCQGnO.d.ts} +4 -3
- package/dist/types-tMagHbjy.d.ts +151 -0
- package/dist/utils/index.d.ts +16 -4
- package/dist/utils/index.js +6 -3
- package/package.json +5 -1
- package/dist/chunk-2PWMUVC7.js.map +0 -1
- package/dist/chunk-4DIQHASK.js.map +0 -1
- package/dist/chunk-4YO5H5ON.js.map +0 -1
- package/dist/chunk-B2P7AZ25.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-QEKVYG5F.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-SHEGLZEP.js.map +0 -1
- package/dist/chunk-TBMKJ26R.js.map +0 -1
- package/dist/chunk-VSQBHPWH.js.map +0 -1
- package/dist/chunk-X5CWPX7H.js.map +0 -1
- package/dist/chunk-YSWH776Y.js +0 -13
- package/dist/chunk-YSWH776Y.js.map +0 -1
- package/dist/chunk-Z2LZ7IZ7.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 → client/core.js.map} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/server/access/levels.ts","../src/server/emit/tiers.ts","../src/server/emit/projection.ts","../src/server/service.ts","../src/server/caller.ts","../src/server/access/kinds.ts","../src/server/pipeline/errors.ts","../src/server/pipeline/schemaOutput.ts","../src/server/pipeline/validation.ts","../src/server/context.ts"],"sourcesContent":["// Access level ordering, ported from 4.1's `isLevelSufficient`\n// (4.1 `src/server/BaseService.ts:554-562`): Public < Read < Moderate < Admin.\n\nimport { ACCESS_LEVELS, isAccessLevel, type AccessLevel } from \"../../contract/access\";\nimport type { Principal } from \"../types\";\n\nconst RANK: Readonly<Record<AccessLevel, number>> = Object.freeze({\n Public: 0,\n Read: 1,\n Moderate: 2,\n Admin: 3,\n});\n\n/**\n * True when `level` is at least `required`. A missing level (no grant) meets\n * nothing, not even `\"Public\"`: a grant has to exist to count.\n */\nexport function meetsLevel(level: AccessLevel | null | undefined, required: AccessLevel): boolean {\n if (level === null || level === undefined) {\n return false;\n }\n return (RANK[level] ?? -1) >= RANK[required];\n}\n\n/**\n * The higher of two levels; `null` (no level) is below every level. A value\n * that is not an access level counts as `null`, so it never raises a level.\n */\nexport function maxLevel(\n a: AccessLevel | null | undefined,\n b: AccessLevel | null | undefined,\n): AccessLevel | null {\n const left = isAccessLevel(a) ? a : null;\n const right = isAccessLevel(b) ? b : null;\n if (left === null || right === null) {\n return left ?? right;\n }\n return RANK[right] > RANK[left] ? right : left;\n}\n\n/** Every level that meets `required`, lowest first: `levelsAtLeast(\"Moderate\")` is `[\"Moderate\", \"Admin\"]`. */\nexport function levelsAtLeast(required: AccessLevel): readonly AccessLevel[] {\n return ACCESS_LEVELS.filter((level) => RANK[level] >= RANK[required]);\n}\n\n/** The principal's service-wide grant on `service`, from `serviceAccess`. */\nexport function serviceGrant(principal: Principal, service: string): AccessLevel | undefined {\n const grants = principal.serviceAccess;\n if (grants === null || grants === undefined || !Object.hasOwn(grants, service)) {\n return undefined;\n }\n return grants[service];\n}\n","// Field tiers (RFC 0003 section 6). A contract's `fields` map names the\n// minimum level a reader needs to receive a field (`{ notes: \"Admin\" }`);\n// every other field goes to anyone who may read the row. An entity frame is\n// built once and stripped once per occupied tier: subscribers join the room\n// of their own level, and levels that see the same fields share one stripped\n// frame. A method's result is stripped per caller, after any shared run\n// (section 9, step 6). 4.1 had two fixed tiers, \"elevated\" and everyone else\n// (4.1 `src/server/BaseService.ts:630-692`), and decided which by\n// overridable methods rather than by declared levels.\n\nimport type { AccessLevel } from \"../../contract/access\";\nimport { meetsLevel } from \"../access/levels\";\nimport type { RowLevel } from \"../access/policy\";\n\n/** The lowest level that may subscribe to a row, as in 4.1 (`requiredLevel = \"Read\"`). */\nexport const SUBSCRIBE_LEVEL: AccessLevel = \"Read\";\n\n/** The levels a subscriber can hold, lowest first: one entity room per level. */\nexport const SUBSCRIBER_LEVELS: readonly AccessLevel[] = Object.freeze([\n \"Read\",\n \"Moderate\",\n \"Admin\",\n]);\n\n/** Subscriber levels that receive the same fields, so one stripped frame serves them all. */\nexport interface TierGroup {\n readonly levels: readonly AccessLevel[];\n /** The projection's keys these levels do not receive. */\n readonly hidden: ReadonlySet<string>;\n}\n\n/** The contract's field tiers over one projection's keys. */\nexport interface Tiers {\n /** True when some key of the projection has a minimum level, so a reader's level matters. */\n readonly tiered: boolean;\n /** The keys a reader at `level` does not receive; `null` is no level, which meets no tier. */\n hidden(level: RowLevel): ReadonlySet<string>;\n /**\n * A one-letter name for the keys `hidden(level)` gives: two levels have the\n * same name exactly when they hide the same keys. Readers of a method's\n * result whose names agree on every row get the same stripped copy.\n */\n label(level: RowLevel): string;\n /** The subscriber levels, grouped by the keys they do not receive. */\n readonly groups: readonly TierGroup[];\n}\n\n/** What a reader at one level does not receive, and its name among the projection's hidden sets. */\ninterface Hiding {\n readonly hidden: ReadonlySet<string>;\n readonly label: string;\n}\n\nconst NOTHING: ReadonlySet<string> = Object.freeze(new Set<string>());\n\nfunction hiddenAt(\n fields: Readonly<Record<string, AccessLevel>>,\n keys: readonly string[],\n level: RowLevel,\n): ReadonlySet<string> {\n const hidden = keys.filter((key) => {\n const required = Object.hasOwn(fields, key) ? fields[key] : undefined;\n return required !== undefined && !meetsLevel(level, required);\n });\n return hidden.length === 0 ? NOTHING : Object.freeze(new Set(hidden));\n}\n\n/** The tiers of `fields` over `keys`. */\nexport function tiersOf(\n fields: Readonly<Record<string, AccessLevel>>,\n keys: readonly string[],\n): Tiers {\n const byLevel = new Map<RowLevel, Hiding>();\n // One name per distinct hidden set: `a`, `b`, ... (at most one per level).\n const labels = new Map<string, string>();\n const hiding = (level: RowLevel): Hiding => {\n let found = byLevel.get(level);\n if (found === undefined) {\n const set = hiddenAt(fields, keys, level);\n const signature = [...set].join(\"\\u0000\");\n const label = labels.get(signature) ?? String.fromCodePoint(97 + labels.size);\n labels.set(signature, label);\n found = { hidden: set, label };\n byLevel.set(level, found);\n }\n return found;\n };\n const hidden = (level: RowLevel): ReadonlySet<string> => hiding(level).hidden;\n const groups = new Map<string, { levels: AccessLevel[]; hidden: ReadonlySet<string> }>();\n for (const level of SUBSCRIBER_LEVELS) {\n const set = hidden(level);\n const signature = [...set].join(\"\\u0000\");\n const group = groups.get(signature);\n if (group === undefined) {\n groups.set(signature, { levels: [level], hidden: set });\n } else {\n group.levels.push(level);\n }\n }\n return Object.freeze({\n tiered: keys.some((key) => Object.hasOwn(fields, key)),\n hidden,\n label: (level: RowLevel) => hiding(level).label,\n groups: Object.freeze([...groups.values()].map((group) => Object.freeze(group))),\n });\n}\n\n/** `row` without the `hidden` keys: a copy when there are any, the row itself otherwise. */\nexport function strip<Row extends Readonly<Record<string, unknown>>>(\n row: Row,\n hidden: ReadonlySet<string>,\n): Row {\n if (hidden.size === 0) {\n return row;\n }\n const kept: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(row)) {\n if (!hidden.has(key)) {\n kept[key] = value;\n }\n }\n return kept as Row;\n}\n","// Projections (RFC 0003 sections 2 and 6): the wire shape of a row. A\n// projection's keys decide what a read selects, so a row is never loaded\n// wider than what is sent, and `Date` values go out as ISO strings. This\n// replaces 4.1's `toDto` (4.1 `src/server/BaseService.ts:615-617`), an\n// identity mapping that sent every column a handler happened to read.\n//\n// The keys come from the schema's Standard JSON Schema (Zod 4.2 or later):\n// the `properties` of its output's object schema. A schema that cannot\n// describe itself names its keys in the service's `project` option instead,\n// or the service fails when it is defined (section 2). `project` also gives a\n// projection a `select` of its own and a `map`, for relations and computed\n// fields: reads use that select, and `map` turns the row read into the\n// projection's row. The rowless check reads an input's keys here too, more\n// widely (`inputKeys`).\n\nimport type { AccessLevel } from \"../../contract/access\";\nimport type { AnyContract } from \"../../contract/defineContract\";\nimport type { MethodOutput } from \"../../contract/methods\";\nimport { hasJsonSchema, type StandardSchemaV1 } from \"../../contract/standardSchema\";\nimport type { RowLevel, RowLevels } from \"../access/policy\";\nimport type { StorageRow } from \"../storage\";\nimport { strip, tiersOf, type Tiers } from \"./tiers\";\n\ntype Fail = (message: string) => never;\n\ntype UnknownRecord = Readonly<Record<string, unknown>>;\n\n/** A projection as a service compiles it once, from its schema and its `project` option. */\nexport interface Projection {\n /** `\"entity\"`, or the name of one of the contract's projections. */\n readonly name: string;\n /** Its keys, `id` first. */\n readonly keys: readonly string[];\n /** The `select` its rows are read with: the one `project` gives it, or its keys. */\n readonly select: UnknownRecord;\n /** Turns a row read with `select` into the projection's row; absent for a plain projection. */\n readonly map: ((row: StorageRow) => unknown) | undefined;\n /** The contract's field tiers over the projection's keys. */\n readonly tiers: Tiers;\n}\n\n/** How a method's output names a projection: one row, one row or `null`, or a list. */\nexport interface ProjectedOutput {\n readonly projection: Projection;\n readonly kind: \"one\" | \"nullable\" | \"list\";\n}\n\nfunction isRecord(value: unknown): value is UnknownRecord {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\n/** A plain object or an array: what a projected value is made of. */\nfunction isPlain(value: unknown): value is object {\n if (typeof value !== \"object\" || value === null) {\n return false;\n }\n const prototype: unknown = Object.getPrototypeOf(value);\n return Array.isArray(value) || prototype === Object.prototype || prototype === null;\n}\n\n/**\n * The node a JSON Schema node stands for: the one its `$ref` names in the\n * document `root` (`#`, `#/definitions/<name>` or `#/$defs/<name>`), or\n * itself without one; `undefined` for a reference it cannot follow.\n */\nexport function referenced(node: UnknownRecord, root: UnknownRecord): UnknownRecord | undefined {\n const ref = node.$ref;\n if (typeof ref !== \"string\") {\n return node;\n }\n if (ref === \"#\") {\n return root;\n }\n const match = /^#\\/(definitions|\\$defs)\\/(.+)$/.exec(ref);\n const defs = match === null ? undefined : root[match[1] ?? \"\"];\n // A JSON Pointer writes \"~\" as \"~0\" and \"/\" as \"~1\" (RFC 6901): Zod does, for an id holding them.\n const name = (match?.[2] ?? \"\").replaceAll(\"~1\", \"/\").replaceAll(\"~0\", \"~\");\n const target = isRecord(defs) ? defs[name] : undefined;\n return isRecord(target) ? target : undefined;\n}\n\n/** `name` as a JSON Pointer token: \"~\" as \"~0\" and \"/\" as \"~1\" (RFC 6901). */\nexport function pointerToken(name: string): string {\n return name.replaceAll(\"~\", \"~0\").replaceAll(\"/\", \"~1\");\n}\n\n/**\n * The keys a schema's output has, read from its Standard JSON Schema, or\n * `undefined` when it cannot say: no JSON Schema (a Zod 3 schema), a value\n * JSON Schema cannot write (a `Date`, a transform), or a value that is not\n * one object (a union).\n */\nexport function schemaKeys(schema: StandardSchemaV1): readonly string[] | undefined {\n if (!hasJsonSchema(schema)) {\n return undefined;\n }\n let json: unknown;\n try {\n json = schema[\"~standard\"].jsonSchema.output({ target: \"draft-07\" });\n } catch {\n return undefined;\n }\n const described = isRecord(json) ? referenced(json, json) : undefined;\n const properties = described?.properties;\n return isRecord(properties) ? Object.keys(properties) : undefined;\n}\n\n/** The keywords whose members are the alternatives (`anyOf`, `oneOf`) or the parts (`allOf`) of a value. */\nconst BRANCHES = [\"anyOf\", \"oneOf\", \"allOf\"] as const;\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/** Adds to `keys` the top-level keys of every object `node` may be: its own and its branches'. */\nfunction addBranchKeys(\n node: unknown,\n root: UnknownRecord,\n keys: Set<string>,\n seen: Set<UnknownRecord>,\n): void {\n const target = isRecord(node) ? referenced(node, root) : undefined;\n if (target === undefined || seen.has(target)) {\n return;\n }\n seen.add(target);\n if (isRecord(target.properties)) {\n for (const key of Object.keys(target.properties)) {\n keys.add(key);\n }\n }\n for (const keyword of BRANCHES) {\n const members = target[keyword];\n if (Array.isArray(members)) {\n for (const member of members) {\n addBranchKeys(member, root, keys, seen);\n }\n }\n }\n}\n\n/**\n * The keys an input may have at its top level, read from its Standard JSON\n * Schema more widely than {@link schemaKeys}, for the rowless check\n * (`../access/rowless.ts`): a key that any branch of a union or an\n * intersection has counts (`anyOf`, `oneOf`, `allOf`, through `$ref`s and\n * past a `null` branch), since that branch may carry it, and a value JSON\n * Schema cannot write (a `Date`, a `Set`, a `bigint`, a custom type) is\n * written as any value rather than hiding the keys beside it. Empty for an\n * input that is no object (a bare string, an array, a record); `undefined`\n * when the schema has no JSON Schema (a Zod 3 schema) or cannot write one.\n */\nexport function inputKeys(schema: StandardSchemaV1): readonly string[] | undefined {\n if (!hasJsonSchema(schema)) {\n return undefined;\n }\n let json: unknown;\n try {\n json = schema[\"~standard\"].jsonSchema.input({\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 keys = new Set<string>();\n addBranchKeys(json, json, keys, new Set());\n return [...keys];\n}\n\nconst OPTION_KEYS = new Set([\"keys\", \"select\", \"map\"]);\n\nfunction checkKeyList(owner: string, keys: unknown, fail: Fail): readonly string[] {\n const valid =\n Array.isArray(keys) &&\n keys.every((key) => typeof key === \"string\" && key.length > 0) &&\n new Set(keys).size === keys.length;\n if (!valid) {\n fail(`${owner}: keys must be a list of distinct field names`);\n }\n if (!keys.includes(\"id\")) {\n fail(`${owner}: keys must include \"id\"; every row is keyed by it`);\n }\n return keys as readonly string[];\n}\n\n/** One projection's `project` entry, checked: unknown options, keys, select and map. */\nfunction checkOption(owner: string, option: unknown, fail: Fail): UnknownRecord {\n if (option === undefined) {\n return {};\n }\n if (!isRecord(option)) {\n fail(`${owner} must be { keys?, select?, map? }`);\n }\n const unknownKey = Object.keys(option).find((key) => !OPTION_KEYS.has(key));\n if (unknownKey !== undefined) {\n fail(`${owner} has an unknown option \"${unknownKey}\"; the options are keys, select and map`);\n }\n if (option.select !== undefined && !isRecord(option.select)) {\n fail(`${owner}: select must be a select object, as in { id: true, labels: { select: ... } }`);\n }\n if (option.map !== undefined && typeof option.map !== \"function\") {\n fail(`${owner}: map must be a function of the row its select reads`);\n }\n return option;\n}\n\nfunction keysFor(\n name: string,\n schema: StandardSchemaV1,\n option: UnknownRecord,\n fail: Fail,\n): readonly string[] {\n const owner = `projection \"${name}\"`;\n if (option.keys !== undefined) {\n return checkKeyList(owner, option.keys, fail);\n }\n const keys = schemaKeys(schema);\n if (keys === undefined) {\n fail(\n `${owner}: its schema cannot list its keys (it has no Standard JSON Schema the framework can read); use Zod 4.2 or later for it, or declare them with project: { ${name}: { keys: [...] } }`,\n );\n }\n return keys;\n}\n\nfunction compileOne(\n name: string,\n schema: StandardSchemaV1,\n option: unknown,\n fields: Readonly<Record<string, AccessLevel>>,\n fail: Fail,\n): Projection {\n const checked = checkOption(`projection \"${name}\"`, option, fail);\n const keys = keysFor(name, schema, checked, fail);\n const ordered = [\"id\", ...keys.filter((key) => key !== \"id\")];\n const select = isRecord(checked.select)\n ? { id: true, ...checked.select }\n : Object.fromEntries(ordered.map((key) => [key, true]));\n return Object.freeze({\n name,\n keys: Object.freeze(ordered),\n select: Object.freeze(select),\n map: checked.map as Projection[\"map\"],\n tiers: tiersOf(fields, ordered),\n });\n}\n\n/**\n * Compiles every projection of `contract` (the entity and its named\n * projections) with the service's `project` option. Fails, through `fail`,\n * for a projection whose keys cannot be found, a `project` entry naming no\n * projection, and a malformed entry.\n */\nexport function compileProjections(\n contract: AnyContract,\n option: unknown,\n fail: Fail,\n): ReadonlyMap<string, Projection> {\n if (option !== undefined && !isRecord(option)) {\n fail(\"project must map projection names to { keys?, select?, map? }\");\n }\n const options = option ?? {};\n const schemas = new Map<string, StandardSchemaV1>(Object.entries(contract.projections));\n if (contract.entity !== undefined) {\n schemas.set(\"entity\", contract.entity);\n }\n const unknownName = Object.keys(options).find((name) => !schemas.has(name));\n if (unknownName !== undefined) {\n fail(\n `project names \"${unknownName}\", which is not a projection of the contract; the projections are ${[...schemas.keys()].map((name) => `\"${name}\"`).join(\", \") || \"none\"}`,\n );\n }\n const compiled = new Map<string, Projection>();\n for (const [name, schema] of schemas) {\n compiled.set(name, compileOne(name, schema, options[name], contract.fields, fail));\n }\n return compiled;\n}\n\n/** The projection a method output names, or `undefined` when the output is a schema. */\nexport function projectedOutput(\n output: MethodOutput,\n projections: ReadonlyMap<string, Projection>,\n): ProjectedOutput | undefined {\n if (typeof output === \"string\") {\n const projection = projections.get(output);\n return projection === undefined ? undefined : { projection, kind: \"one\" };\n }\n if (!(\"kind\" in output)) {\n return undefined;\n }\n const projection = projections.get(output.projection);\n const kind = output.kind === \"nullable\" ? \"nullable\" : \"list\";\n return projection === undefined ? undefined : { projection, kind };\n}\n\n/**\n * `value` with every `Date` in it, at any depth of plain objects and arrays,\n * replaced by its ISO string. Anything else is kept as it is.\n */\nexport function isoDates(value: unknown): unknown {\n if (value instanceof Date) {\n return value.toISOString();\n }\n if (!isPlain(value)) {\n return value;\n }\n if (Array.isArray(value)) {\n return value.map(isoDates);\n }\n const copy: Record<string, unknown> = {};\n for (const [key, item] of Object.entries(value)) {\n copy[key] = isoDates(item);\n }\n return copy;\n}\n\n/** The members of `row` named by `keys` that it has, with their dates as ISO strings. */\nexport function pickKeys(row: UnknownRecord, keys: Iterable<string>): Record<string, unknown> {\n const picked: Record<string, unknown> = {};\n for (const key of keys) {\n if (Object.hasOwn(row, key)) {\n picked[key] = isoDates(row[key]);\n }\n }\n return picked;\n}\n\n/**\n * One row in the projection's shape: `map` applied (when the projection has\n * one), then its keys picked, dates as ISO strings. A value that is not an\n * object is returned as it is, for output validation to report.\n */\nexport function projectRow(projection: Projection, row: unknown): unknown {\n if (!isRecord(row)) {\n return row;\n }\n const source = projection.map === undefined ? row : projection.map(row);\n return isRecord(source) ? pickKeys(source, projection.keys) : source;\n}\n\n/** A method's result in its projection's shape: one row, `null`, or a list of rows. */\nexport function projectOutput(output: ProjectedOutput, value: unknown): unknown {\n if (output.kind === \"list\") {\n return Array.isArray(value)\n ? value.map((row: unknown) => projectRow(output.projection, row))\n : value;\n }\n if (value === null && output.kind === \"nullable\") {\n return null;\n }\n return projectRow(output.projection, value);\n}\n\n/** The ids of the rows in a projected value: one row, `null`, or a list. */\nexport function rowIds(value: unknown): string[] {\n const rows: readonly unknown[] = Array.isArray(value) ? value : [value];\n const ids: string[] = [];\n for (const row of rows) {\n if (isRecord(row) && typeof row.id === \"string\" && row.id.length > 0) {\n ids.push(row.id);\n }\n }\n return ids;\n}\n\n/** What one reader may see of a method's result, from {@link readerView}. */\nexport interface ReaderView {\n /**\n * Equal for two readers of one result exactly when every row hides the\n * same fields from both, so they may share one stripped copy.\n */\n readonly key: string;\n /** The result without the fields this reader does not receive: a copy of each row that hides any. */\n strip(): unknown;\n}\n\n/** The view of a reader who sees the whole value: a schema output, or a projection without tiers. */\nexport function wholeView(value: unknown): ReaderView {\n return { key: \"\", strip: () => value };\n}\n\n/**\n * A projected method result as one reader may see it: each row without the\n * fields its reader's level on that row does not reach (RFC 0003 section 6).\n * `levelsOf` answers the reader's level per row id; it is asked only when the\n * projection has tiered keys. Rows are copied, never changed in place, so a\n * shared run's result stays whole for the other callers.\n */\nexport async function readerView(\n output: ProjectedOutput,\n value: unknown,\n levelsOf: (ids: readonly string[]) => Promise<RowLevels>,\n): Promise<ReaderView> {\n const { tiers } = output.projection;\n if (!tiers.tiered || value === null || value === undefined) {\n return wholeView(value);\n }\n const ids = [...new Set(rowIds(value))];\n const levels: RowLevels = ids.length === 0 ? new Map() : await levelsOf(ids);\n const levelOf = (row: UnknownRecord): RowLevel =>\n typeof row.id === \"string\" ? (levels.get(row.id) ?? null) : null;\n const rows: readonly unknown[] = Array.isArray(value) ? value : [value];\n // A value that is not a row goes to every reader as it is.\n const key = rows.map((row) => (isRecord(row) ? tiers.label(levelOf(row)) : \"-\")).join(\"\");\n const one = (row: unknown): unknown =>\n isRecord(row) ? strip(row, tiers.hidden(levelOf(row))) : row;\n return { key, strip: () => (Array.isArray(value) ? value.map(one) : one(value)) };\n}\n","// A defined service as the pipeline reads it: its contract, and one checked\n// record per method holding the handler, the access form and the options.\n// `defineService.ts` builds these; the registry and the dispatcher read them.\n\nimport type { AnyContract } from \"../contract/defineContract\";\nimport type { MethodKind } from \"../contract/methods\";\nimport type { StandardSchemaV1 } from \"../contract/standardSchema\";\nimport type { Version } from \"../protocol/envelope\";\nimport type { AccessForm, AnyAccessPolicy, ClaimsCheck, WatchAccess } from \"./access/types\";\nimport type { ServiceCollection } from \"./collections/define\";\nimport type { AnyContext, ContextExtender } from \"./context\";\nimport type { ProjectedOutput, Projection } from \"./emit/projection\";\nimport type {\n HostLeaveHandler,\n RoomLeaveHandler,\n ServiceChannel,\n ServiceStream,\n} from \"./realtime/types\";\nimport type { MaybePromise, QuickdrawTypes } from \"./types\";\n\n/**\n * How identical concurrent calls of a query share one handler run (RFC 0003\n * section 9, step 6): `\"caller\"` among one principal's calls, `\"all\"` across\n * principals.\n */\nexport type ShareMode = \"caller\" | \"all\";\n\n/** A handler as the pipeline calls it, whatever its declared types. */\nexport type AnyHandler = (args: {\n readonly input: unknown;\n readonly ctx: AnyContext;\n readonly db: unknown;\n}) => unknown;\n\n/**\n * A method's own output schema, compiled from its JSON Schema when the\n * service is defined (`pipeline/schemaOutput.ts`).\n */\nexport interface SchemaOutput {\n /** The value reduced to what the schema declares; the value itself when nothing is dropped. */\n pick(value: unknown): unknown;\n /**\n * Each key the schema declares, at any depth, with the first path that\n * declares it (`email`, `user.email`, `[].email`; `{}` stands for any key\n * of a record): what the `tiered-field-in-output` warning reads.\n */\n keyPaths(): ReadonlyMap<string, string>;\n}\n\n/** One method of a defined service, checked and ready to dispatch. */\nexport interface ServiceMethod {\n readonly name: string;\n readonly kind: MethodKind;\n /** The contract's input schema. */\n readonly input: StandardSchemaV1;\n /**\n * The schema the handler's result is checked against in development and\n * tests, derived from the contract's `output`: the schema itself, or the\n * projection's schema, wrapped for `nullable` and `listOf`.\n */\n readonly output: StandardSchemaV1;\n /**\n * The projection the contract's `output` names, when it names one: the\n * handler's rows are projected through it before the output check, and\n * its field tiers are stripped per caller.\n */\n readonly projection: ProjectedOutput | undefined;\n /**\n * A schema output, compiled from its JSON Schema when the service was\n * defined (`pipeline/schemaOutput.ts`): the handler's result is reduced to\n * what the schema declares before the output check, on every transport.\n * `undefined` for a projection output, and for a schema without JSON\n * Schema (Zod 3), which is sent as the handler returns it.\n */\n readonly schemaOutput: SchemaOutput | undefined;\n readonly access: AccessForm;\n /**\n * The kinds of principal that may call the method (RFC 0003 section 4.1):\n * its own `kinds`, else its service's, else the app's (`initQuickdraw`);\n * `undefined` admits every kind. A principal of another kind, or without\n * one, gets `FORBIDDEN` before the access form is asked; an anonymous\n * caller is left to the form.\n */\n readonly kinds: readonly string[] | undefined;\n /**\n * The method's requirement on the caller's claims (RFC 0003 section 4.1,\n * `access/claims.ts`), checked right after `kinds`, outside the access\n * engine: `UNAUTHENTICATED` without a principal, `FORBIDDEN` unless it\n * returns `true`. It adds to the access form, and no grant passes it, a\n * service-wide `Admin` grant included. `undefined` when not declared.\n */\n readonly claims: ClaimsCheck | undefined;\n readonly handler: AnyHandler;\n readonly share: ShareMode | undefined;\n /** How long a shared result is reused after its run, in milliseconds. */\n readonly ttlMs: number | undefined;\n /** The method's time limit; the dispatcher's `callTimeoutMs` when unset. */\n readonly timeoutMs: number | undefined;\n /** The query's current version for \"not modified\" replies. */\n readonly version: ((input: unknown, ctx: AnyContext) => MaybePromise<Version>) | undefined;\n /**\n * True when the method said `rowless: true`: its access form is its whole\n * check on purpose, so every caller the form admits may reach any row its\n * input names (`defineService` refuses such a method otherwise; see\n * `buildService.ts`).\n */\n readonly rowless: boolean;\n}\n\n/**\n * One `affects` declaration of a service, checked (RFC 0003 sections 3 and\n * 5.3): a write to a row of the service's model also changes rows of\n * `service`, whose ids the written row's `columns` hold.\n */\nexport interface AffectsLink {\n /** The contract of the service whose rows the write affects. */\n readonly service: AnyContract;\n /** The columns of the service's own model the link reads; tracked writes report them. */\n readonly columns: readonly string[];\n /** The ids of the affected rows, from a written row's values of `columns`. */\n ids(values: Readonly<Record<string, unknown>>): readonly string[];\n}\n\n/**\n * A service defined with `qd.defineService(contract, definition)`. Pass it\n * to `qd.createServer` or to a dispatcher.\n */\nexport interface Service<\n T extends QuickdrawTypes = QuickdrawTypes,\n C extends AnyContract = AnyContract,\n> {\n /** The service name from the contract, unchanged on the wire and in stored grants. */\n readonly name: C[\"name\"];\n readonly contract: C;\n /** The database model the service's rows live in, named as the client names it: `\"task\"`. */\n readonly model: string | undefined;\n /** How a principal's level on one of the service's rows is found (RFC 0003 section 4.2). */\n readonly access: AnyAccessPolicy | undefined;\n /** Other models the service's handlers write, besides its own. */\n readonly writes: readonly string[];\n /** Rows of other services that a write to one of this service's rows changes too. */\n readonly affects: readonly AffectsLink[];\n /** The column whose time says when a row last changed, for \"not modified\" answers. */\n readonly versionColumn: string | undefined;\n /** The contract's projections (`\"entity\"` and the named ones), compiled with the service's `project` option. */\n readonly projections: ReadonlyMap<string, Projection>;\n /** The contract's collections, compiled with the service's `collections` option (RFC 0003 section 7.1). */\n readonly collections: ReadonlyMap<string, ServiceCollection>;\n /**\n * Who may watch the service's change topic (RFC 0003 section 11.3);\n * `undefined` when the service set none: the topic is closed to everyone.\n */\n readonly watchAccess: WatchAccess | undefined;\n /** Whether a service-wide `Admin` grant passes every access check of this service. */\n readonly adminBypass: boolean;\n /**\n * The kinds of principal the service admits (RFC 0003 section 4.1): its\n * own `kinds`, else the app's (`initQuickdraw`); `undefined` admits every\n * kind. Its methods narrow it, and its subscriptions (`qd:sub`,\n * `qd:col:sub`, `qd:watch`, `qd:stream:sub`) and channels check it.\n */\n readonly kinds: readonly string[] | undefined;\n /** The checked method records, by method name. */\n readonly methods: Readonly<Record<string, ServiceMethod>>;\n /** The contract's channels with the handlers `defineService` gave them (RFC 0003 section 12.5). */\n readonly channels: ReadonlyMap<string, ServiceChannel>;\n /** The contract's streams, with their access forms as the access engine decides them. */\n readonly streams: ReadonlyMap<string, ServiceStream>;\n /**\n * The service's own `onRoomLeave`: `createServer` runs it, beside every\n * other service's and its own option's, for each socket that leaves app\n * rooms. `undefined` when the service declares none.\n */\n readonly onRoomLeave: RoomLeaveHandler | undefined;\n /** The service's own `onHostLeave`: `createServer` runs it, beside the server's own, when a room's host leaves. */\n readonly onHostLeave?: HostLeaveHandler | undefined;\n /** Type-only: the app types the service was defined with. Never set. */\n readonly \"~types\"?: T;\n}\n\n/** Any defined service. */\nexport type AnyService = Service<QuickdrawTypes, AnyContract>;\n\n/** What a service keeps from the `initQuickdraw` call that defined it. */\nexport interface ServiceRuntime {\n /** The app's `context` option, or `undefined`. */\n readonly extendContext: ContextExtender | undefined;\n /** The app's `kinds` option, checked: what every service it defines admits by default. */\n readonly kinds: readonly string[] | undefined;\n /**\n * Makes `dispatcher` the one the instance's `qd.caller`, `qd.run`,\n * `qd.stream` and `qd.presence` go through, as its own `createServer`\n * does: for `createTestApp`, which creates its server itself.\n */\n readonly adopt?: (dispatcher: object) => void;\n}\n\nconst runtimes = new WeakMap<object, ServiceRuntime>();\n\n/** Marks `service` as defined by `defineService` with the given runtime. */\nexport function registerRuntime(service: AnyService, runtime: ServiceRuntime): void {\n runtimes.set(service, runtime);\n}\n\n/** The runtime of a service `defineService` returned, or `undefined` for anything else. */\nexport function runtimeOf(service: unknown): ServiceRuntime | undefined {\n return typeof service === \"object\" && service !== null ? runtimes.get(service) : undefined;\n}\n\n/** Why a service cannot run a handler, or `undefined` when it can. */\nexport type HandlerCheck = (service: AnyService) => string | undefined;\n\nconst handlerChecks = new WeakMap<object, HandlerCheck>();\n\n/**\n * Makes `defineService` run `check` on the service `handler` is given to, so\n * a handler that needs something of its service (a kit's need a model) fails\n * when the service is defined, not on its first call. Only the kits register\n * checks, so a handler with one is framework code (`isKitHandler`).\n */\nexport function checkWhenDefined(handler: object, check: HandlerCheck): void {\n handlerChecks.set(handler, check);\n}\n\n/** The kit handlers that write users' service-wide grants (`admin.handlers(c, { grants: true })`). */\nconst grantsEditors = new WeakSet<object>();\n\n/** Marks `handler` as one that writes users' service-wide grants: `createServer` checks where they are stored. */\nexport function markGrantsEditor(handler: object): void {\n grantsEditors.add(handler);\n}\n\n/** True for a handler that writes users' service-wide grants (`markGrantsEditor`). */\nexport function editsGrants(handler: object): boolean {\n return grantsEditors.has(handler);\n}\n\n/** Why `service` cannot run `handler`, from the check `checkWhenDefined` attached. */\nexport function handlerProblem(handler: object, service: AnyService): string | undefined {\n return handlerChecks.get(handler)?.(service);\n}\n\n/** What `createDispatcher` knows of the server a handler is served in. */\nexport interface ServedContext {\n readonly service: AnyService;\n /**\n * The dispatcher's `serviceAccessSource` (`createServer`'s\n * `auth.serviceAccessSource`): where users' service-wide grants live.\n */\n readonly grantsSource: { readonly model: string; readonly column: string } | undefined;\n}\n\n/** Why a handler cannot be served as `served` says, or `undefined` when it can. */\nexport type ServedCheck = (served: ServedContext) => string | undefined;\n\nconst servedChecks = new WeakMap<object, ServedCheck>();\n\n/**\n * Makes `createDispatcher` run `check` for each service it serves `handler`\n * in, once the dispatcher's options are known (the admin kit's grants\n * column, `serviceAccessSource`), so a clash fails when the dispatcher is\n * made, never on a call. Only the handler the kit made carries the check:\n * an app that wraps it serves the wrapper unchecked, and a clash then fails\n * its calls closed, `INTERNAL`, as `checkWhenDefined`'s would.\n */\nexport function checkWhenServed(handler: object, check: ServedCheck): void {\n servedChecks.set(handler, check);\n}\n\n/** Why `handler` cannot be served as `served` says, from the check `checkWhenServed` attached. */\nexport function servedProblem(handler: object, served: ServedContext): string | undefined {\n return servedChecks.get(handler)?.(served);\n}\n\n/**\n * True for a handler a kit made (it registered a check with\n * `checkWhenDefined`): framework code, whose statements the development\n * checks leave alone, because an app cannot change them.\n */\nexport function isKitHandler(handler: object): boolean {\n return handlerChecks.has(handler);\n}\n\nconst rowChecked = new WeakSet<object>();\n\n/**\n * Marks a kit handler that never reaches an existing row its input's `id`\n * names without checking the caller's level on that row itself, whatever its\n * access form says: the read/write kit's `update`, `delete` and `reorder`\n * (they need the method's row level on the row) and `create` (its `id`, when\n * it has one, names a new row; it checks the anchors it writes instead).\n * `defineService`'s rowless check leaves such a handler alone.\n */\nexport function checksRowsItself(handler: object): void {\n rowChecked.add(handler);\n}\n\n/** True for a handler marked with {@link checksRowsItself}. */\nexport function isRowChecked(handler: object): boolean {\n return rowChecked.has(handler);\n}\n\nconst callerDependent = new WeakSet<object>();\n\n/**\n * Marks a kit handler whose result is what the caller may see: a run shared\n * across principals (`share: \"all\"`) would hand one caller's result to every\n * other, so `defineService` refuses `\"all\"` on it. The read/write kit's\n * `list` and `getMany` (the rows the caller's level reaches), every search\n * handler, the admin kit's `adminList` and `adminGet` (fields above the\n * caller's grant are left out) and the sharing kit's `listShares` and\n * `listMembers` (input-only today, marked so a later change cannot leak).\n */\nexport function dependsOnCaller(handler: object): void {\n callerDependent.add(handler);\n}\n\n/** True for a handler marked with {@link dependsOnCaller}. */\nexport function isCallerDependent(handler: object): boolean {\n return callerDependent.has(handler);\n}\n","// 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`. The callers of a call's `ctx.services` pass\n// its `ctx.mcp` on, so a method an MCP call reaches through them sees the\n// same fields; `qd.caller` and the other in-process callers act outside any\n// MCP call and pass none.\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 { McpContext, 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 * The `ctx.mcp` every call carries: `ctx.services` passes the calling\n * method's, that very object, so a guard that reads it holds in the\n * methods it reaches. Each call's transport stays `\"internal\"`.\n */\n readonly mcp?: McpContext;\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/**\n * `principal` with the grants `grants` loads now, when it carries none and\n * there is a loader; else `principal` itself (`null`, or one that carries\n * grants, `{}` included). A failed load is `INTERNAL`, keeping the error as\n * `cause`. The MCP registry loads a principal the app gave a call so, at\n * each call, as an HTTP call's are loaded.\n */\nexport async function withCallerGrants(\n principal: Principal | null,\n grants: CallerGrants | undefined,\n): Promise<Principal | null> {\n if (principal === null || carriesGrants(principal) || grants === undefined) {\n return principal;\n }\n return await withLoadedGrants(principal, grants);\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). With `settings.mcp`, every call\n * carries it as its `ctx.mcp`.\n */\nexport function createCaller(\n resolve: () => Dispatch,\n principal: Principal | null,\n settings: CallerSettings = {},\n): object {\n const principalOfCall = principalOfCalls(principal, settings.grants);\n const { mcp } = settings;\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 ...(mcp === undefined ? {} : { mcp }),\n });\n }),\n );\n}\n","// Declared principal kinds (RFC 0003 section 4.1): which kinds of principal\n// (`principal.kind`: a user, an agent's token, a runner) may call a\n// service's methods and subscribe to its live data. `kinds` sits beside\n// `access`, never inside a form, at three levels that only narrow:\n// `initQuickdraw({ kinds })` for every service the instance defines,\n// `defineService(contract, { kinds })` within it, and a method's `kinds`\n// within its service's. A level that declares none takes the list above it;\n// `undefined` all the way up admits every kind.\n//\n// The check runs before the access form and outside the access engine, so an\n// app's own engine (which sees only the form) cannot skip it, and neither can\n// a service-wide `Admin` grant: a token of the wrong kind acting with\n// someone's Admin is exactly what it stops. A principal without a kind, or of\n// a kind the list does not name, gets `FORBIDDEN`. An anonymous caller\n// passes, and the form decides, as it always did (`UNAUTHENTICATED` where it\n// needs a principal); that is why a `\"public\"` method may not declare kinds\n// of its own: a caller of a refused kind would call it signed out.\n//\n// Calls check their method's list in the pipeline, whatever the transport.\n// `qd:sub`, `qd:col:sub`, `qd:watch` and `qd:stream:sub` check their\n// service's list, and a channel drops the message of a socket of another\n// kind, against a set made when the service is defined. A socket's kind is\n// set at its handshake and grant pushes keep it, so nothing is ever revoked\n// for a kind.\n\nimport { QuickdrawError } from \"../../protocol/errors\";\nimport type { Principal } from \"../types\";\n\ntype Fail = (message: string) => never;\n\n/** What a `kinds` option narrows: the kinds the level above admits, and who that is, for messages. */\nexport interface KindsAbove {\n /** `undefined` when the level above admits every kind. */\n readonly kinds: readonly string[] | undefined;\n /** Who admits them, as a message names it: `\"initQuickdraw\"`, `\"its service\"`. */\n readonly by: string;\n}\n\nfunction isKindList(value: unknown): value is readonly string[] {\n return (\n Array.isArray(value) &&\n value.length > 0 &&\n value.every((kind) => typeof kind === \"string\" && kind.length > 0)\n );\n}\n\n/**\n * A level's `kinds` option, checked and resolved: a non-empty list of kind\n * names within the kinds `above` admits, each kind once and frozen; what\n * `above` admits when the level declares none. Anything else fails.\n */\nexport function narrowKinds(\n value: unknown,\n above: KindsAbove | undefined,\n fail: Fail,\n): readonly string[] | undefined {\n if (value === undefined) {\n return above?.kinds;\n }\n if (!isKindList(value)) {\n fail(\n 'kinds must be a non-empty list of principal kinds (strings), such as [\"user\"]; leave it out to admit every kind',\n );\n }\n if (above?.kinds !== undefined) {\n const { kinds, by } = above;\n const wider = value.find((kind) => !kinds.includes(kind));\n if (wider !== undefined) {\n fail(\n `kinds may only narrow the kinds ${by} admits (${kinds.join(\", \")}), and \"${wider}\" is not one of them`,\n );\n }\n }\n return Object.freeze([...new Set(value)]);\n}\n\n/**\n * Refuses `principal` with `FORBIDDEN` unless `kinds` admits it: its kind is\n * one of them, or `kinds` is `undefined`. An anonymous caller (`null`)\n * passes, so the access form decides. `what` names the method\n * (`tokenService.mint`) or the service in the message.\n */\nexport function checkKind(\n kinds: readonly string[] | undefined,\n principal: Principal | null,\n what: string,\n): void {\n if (kinds === undefined || principal === null) {\n return;\n }\n const { kind } = principal;\n if (typeof kind === \"string\" && kinds.includes(kind)) {\n return;\n }\n throw new QuickdrawError(\n \"FORBIDDEN\",\n kind === undefined\n ? `${what} is not open to a principal without a kind`\n : `${what} is not open to principals of kind \"${String(kind)}\"`,\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 { ContextAccess, 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\"` and the\n * calling method's `ctx.mcp`, its writes join the calling method's unit of\n * work (one flush for both), and it is cancelled with `ctx.signal`. Typed by\n * the `contracts` of the app's types, like `qd.caller`; untyped without them.\n */\nexport type ContextServices<T extends QuickdrawTypes = QuickdrawTypes> = CallerFor<T>;\n\nexport type { ContextAccess, 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 or was made through the\n * `ctx.services` of a call that has it (nested calls too), which passes\n * the same object on. Such a call's `transport` is `\"internal\"`: to tell a\n * token's call apart, read `ctx.mcp`, not `ctx.transport`.\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 and\n * with its `ctx.mcp`: `await ctx.services.projectService.get({ id })`. See\n * {@link ContextServices}.\n */\n readonly services: ContextServices;\n /**\n * The caller's levels on rows of the app's services, as the access forms\n * count them (RFC 0003 section 4.3): `dispatcher.access` bound to\n * `ctx.principal`, with the grants this call runs with. For a `custom`\n * form that checks a row its key names only sometimes, or a parent its\n * input names: `await ctx.access.can(project, input.projectId, \"Moderate\")`.\n * See {@link ContextAccess}.\n */\n readonly access: ContextAccess;\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 /**\n * Every service of the dispatcher, by name: the kits lock the columns of a\n * membership table that any of their policies reads.\n */\n readonly services: ReadonlyMap<string, 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 /** The dispatcher's `serviceAccessSource`: where users' service-wide grants live (the admin kit's grants column). */\n readonly grantsSource?: { readonly model: string; readonly column: string };\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, and\n * `access` its policies, which `ctx.access` binds to the call's principal; a\n * context built without them gets a `touch` that does nothing, `rooms` that\n * join nothing and send nothing, a `presence` that sees nobody, and\n * `services` and `access` that throw `INTERNAL`. `kit` is kept beside the\n * 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 readonly access?: Pick<PolicyEngine, \"forCaller\">;\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, why: string): QuickdrawError {\n return new QuickdrawError(\"INTERNAL\", `${member} needs a dispatcher: ${why}`);\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\n/** A member of `ctx` that throws `INTERNAL` on use, for a context no dispatcher built. */\nfunction unavailable<T extends object>(member: string, why: string): T {\n return new Proxy(Object.freeze({}) as T, {\n get(_target, key) {\n if (typeof key === \"symbol\" || INSPECTED.has(key)) {\n return undefined;\n }\n throw notAvailable(`${member}.${key}`, why);\n },\n });\n}\n\nconst SERVICES = unavailable<ContextServices>(\n \"ctx.services\",\n \"it calls through the dispatcher that runs the method\",\n);\n\nconst ACCESS = unavailable<ContextAccess>(\n \"ctx.access\",\n \"it reads the access policies of the dispatcher that runs the method\",\n);\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 setHost: () => false,\n hostOf: () => null,\n clearHost: () => undefined,\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 and carrying `mcp`, the\n * calling call's `ctx.mcp`. The inner call's `ctx` is built from its\n * request, so its own `ctx.services` passes the same object on again.\n */\nfunction servicesOf(\n dispatch: Dispatch | undefined,\n principal: Principal | null,\n mcp: McpContext | undefined,\n): ((signal: AbortSignal) => ContextServices) | undefined {\n if (dispatch === undefined) {\n return undefined;\n }\n return (signal) => createCaller(() => dispatch, principal, { signal, mcp }) 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, access, ...own } = fields;\n const services = servicesOf(dispatch, own.principal, own.mcp);\n const base: AnyContext = Object.freeze({\n ...own,\n touch: own.touch ?? untracked,\n services: services?.(own.signal) ?? SERVICES,\n access: access?.forCaller(own.principal) ?? ACCESS,\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\n/** The members of `ctx` that say who the caller is, or answer as them. */\nexport type CallerMember = \"principal\" | \"services\" | \"mcp\" | \"access\";\n\nconst CALLER_MEMBERS: ReadonlySet<PropertyKey> = new Set<CallerMember>([\n \"principal\",\n \"services\",\n \"mcp\",\n \"access\",\n]);\n\n/**\n * The same `ctx`, calling `onRead` each time code reads one of the members\n * that say who the caller is: the development check of a `share: \"all\"`\n * run, whose result every caller gets. Reads return the very values, so\n * `ctx` stays as frozen as it was, and its kit runtime and service callers\n * stay registered for the proxy.\n */\nexport function watchCallerReads(\n ctx: AnyContext,\n onRead: (member: CallerMember) => void,\n): AnyContext {\n const watched = new Proxy(ctx, {\n get(target, key, receiver) {\n if (CALLER_MEMBERS.has(key)) {\n onRead(key as CallerMember);\n }\n return Reflect.get(target, key, receiver) as unknown;\n },\n });\n return withRuntime(watched, KIT_RUNTIMES.get(ctx), SERVICE_CALLERS.get(ctx));\n}\n"],"mappings":"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","names":["projection","isRecord","BRANCHES","UNREPRESENTABLE_AS_ANY"]}
|
|
@@ -1,16 +1,20 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ANY_FIELD,
|
|
3
3
|
modelKey
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-DUBU3BB3.js";
|
|
5
|
+
import {
|
|
6
|
+
consoleLogger,
|
|
7
|
+
errorText
|
|
8
|
+
} from "./chunk-DKE6QO26.js";
|
|
5
9
|
import {
|
|
6
10
|
PreEncoded,
|
|
7
11
|
createJsonParser
|
|
8
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-SN3OZVEQ.js";
|
|
9
13
|
import {
|
|
10
14
|
INTERNAL_MESSAGE,
|
|
11
15
|
QuickdrawError,
|
|
12
16
|
toWire
|
|
13
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-Q4OGQM5I.js";
|
|
14
18
|
|
|
15
19
|
// src/server/pipeline/request.ts
|
|
16
20
|
function toCallReply(result) {
|
|
@@ -29,11 +33,25 @@ function callReplyJson(reply, dataJson) {
|
|
|
29
33
|
|
|
30
34
|
// src/server/transports/auth.ts
|
|
31
35
|
var SOCKET_SESSIONS = /* @__PURE__ */ new WeakMap();
|
|
32
|
-
function recordSocketSession(socket, sessionId) {
|
|
33
|
-
|
|
36
|
+
function recordSocketSession(socket, sessionId, expiresAt) {
|
|
37
|
+
const time = expiresAt === void 0 ? Number.NaN : new Date(expiresAt).getTime();
|
|
38
|
+
SOCKET_SESSIONS.set(socket, {
|
|
39
|
+
id: sessionId,
|
|
40
|
+
expiresAt: Number.isNaN(time) ? void 0 : time
|
|
41
|
+
});
|
|
34
42
|
}
|
|
35
43
|
function socketSessionOf(socket) {
|
|
36
|
-
return SOCKET_SESSIONS.get(socket);
|
|
44
|
+
return SOCKET_SESSIONS.get(socket)?.id;
|
|
45
|
+
}
|
|
46
|
+
function socketSessionExpiryOf(socket) {
|
|
47
|
+
return SOCKET_SESSIONS.get(socket)?.expiresAt;
|
|
48
|
+
}
|
|
49
|
+
var SOCKET_AUTHS = /* @__PURE__ */ new WeakMap();
|
|
50
|
+
function markSocketAuth(authenticate, info) {
|
|
51
|
+
SOCKET_AUTHS.set(authenticate, Object.freeze({ ...info }));
|
|
52
|
+
}
|
|
53
|
+
function socketAuthOf(authenticate) {
|
|
54
|
+
return typeof authenticate === "function" ? SOCKET_AUTHS.get(authenticate) : void 0;
|
|
37
55
|
}
|
|
38
56
|
function isRefusal(error) {
|
|
39
57
|
return error instanceof QuickdrawError && error.code === "UNAUTHENTICATED";
|
|
@@ -109,7 +127,7 @@ function createGrantsSink(auth, refresh, logger) {
|
|
|
109
127
|
logger.error("Refreshing a user's written grants failed", {
|
|
110
128
|
category: "quickdraw.access",
|
|
111
129
|
userId,
|
|
112
|
-
error:
|
|
130
|
+
error: errorText(error)
|
|
113
131
|
});
|
|
114
132
|
}
|
|
115
133
|
})
|
|
@@ -126,7 +144,7 @@ async function createJWT(payload, secret, expiresIn = DEFAULT_EXPIRATION) {
|
|
|
126
144
|
const jwt = await new jose.SignJWT(payload).setProtectedHeader({ alg: "HS256" }).setIssuedAt().setExpirationTime(expiresIn).sign(secretKey);
|
|
127
145
|
return jwt;
|
|
128
146
|
}
|
|
129
|
-
async function
|
|
147
|
+
async function readVerifiedJWT(token, secret) {
|
|
130
148
|
try {
|
|
131
149
|
const secretKey = new TextEncoder().encode(secret);
|
|
132
150
|
const { payload } = await jose.jwtVerify(token, secretKey);
|
|
@@ -141,6 +159,17 @@ async function verifyJWT(token, secret) {
|
|
|
141
159
|
return null;
|
|
142
160
|
}
|
|
143
161
|
}
|
|
162
|
+
var warnedSessionToken = false;
|
|
163
|
+
async function verifyJWT(token, secret) {
|
|
164
|
+
const payload = await readVerifiedJWT(token, secret);
|
|
165
|
+
if (payload?.sid !== void 0 && process.env.NODE_ENV !== "production" && !warnedSessionToken) {
|
|
166
|
+
warnedSessionToken = true;
|
|
167
|
+
consoleLogger.warn(
|
|
168
|
+
"[quickdraw] verifyJWT verified a session token (it carries sid): verifyJWT checks the signature and expiry only, never the session store, so a signed-out or revoked session still passes. Check session tokens with liveSession({ sessions, jwtSecret }, token), bearerAuth(...) or socketAuth(...)."
|
|
169
|
+
);
|
|
170
|
+
}
|
|
171
|
+
return payload;
|
|
172
|
+
}
|
|
144
173
|
|
|
145
174
|
// src/server/auth/sessionCookie.ts
|
|
146
175
|
var SESSION_COOKIE = "session";
|
|
@@ -181,8 +210,8 @@ function sessionCookieNameFor(req, naming = {}) {
|
|
|
181
210
|
}
|
|
182
211
|
var SECURE_SESSION_COOKIES = Object.freeze([HOST_SESSION_COOKIE]);
|
|
183
212
|
var PLAIN_SESSION_COOKIES = Object.freeze([
|
|
184
|
-
|
|
185
|
-
|
|
213
|
+
HOST_SESSION_COOKIE,
|
|
214
|
+
SESSION_COOKIE
|
|
186
215
|
]);
|
|
187
216
|
function sessionCookieNamesFor(req, naming = {}) {
|
|
188
217
|
if (naming.cookieName !== void 0) {
|
|
@@ -219,13 +248,33 @@ function sessionCookie(res, options) {
|
|
|
219
248
|
}
|
|
220
249
|
};
|
|
221
250
|
}
|
|
251
|
+
function carriesHostSession(req) {
|
|
252
|
+
const header = req.headers.cookie;
|
|
253
|
+
if (typeof header === "string") {
|
|
254
|
+
return header.split(";").some((pair) => pair.trimStart().startsWith(`${HOST_SESSION_COOKIE}=`));
|
|
255
|
+
}
|
|
256
|
+
const cookies = Reflect.get(req, "cookies");
|
|
257
|
+
return typeof cookies === "object" && cookies !== null && Object.hasOwn(cookies, HOST_SESSION_COOKIE);
|
|
258
|
+
}
|
|
259
|
+
function clearStaleHostSession(res, req, written, sameSite) {
|
|
260
|
+
if (written === HOST_SESSION_COOKIE || !carriesHostSession(req)) {
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
263
|
+
res.clearCookie(HOST_SESSION_COOKIE, { httpOnly: true, secure: true, sameSite, path: "/" });
|
|
264
|
+
}
|
|
222
265
|
function setSessionCookie(res, jwt, options = {}) {
|
|
223
266
|
const { name, settings } = sessionCookie(res, options);
|
|
224
267
|
res.cookie(name, jwt, { ...settings, maxAge: options.maxAgeMs ?? DEFAULT_MAX_AGE_MS });
|
|
268
|
+
if (options.cookieName === void 0) {
|
|
269
|
+
clearStaleHostSession(res, requestOf(res), name, settings.sameSite);
|
|
270
|
+
}
|
|
225
271
|
}
|
|
226
272
|
function clearSessionCookie(res, options = {}) {
|
|
227
273
|
const { name, settings } = sessionCookie(res, options);
|
|
228
274
|
res.clearCookie(name, settings);
|
|
275
|
+
if (options.cookieName === void 0) {
|
|
276
|
+
clearStaleHostSession(res, requestOf(res), name, settings.sameSite);
|
|
277
|
+
}
|
|
229
278
|
}
|
|
230
279
|
|
|
231
280
|
// src/server/auth/restMiddleware.ts
|
|
@@ -251,7 +300,7 @@ function createRequireAuth(options) {
|
|
|
251
300
|
res.status(401).json({ error: "Authentication is not configured" });
|
|
252
301
|
return;
|
|
253
302
|
}
|
|
254
|
-
const payload = await
|
|
303
|
+
const payload = await readVerifiedJWT(token, secret);
|
|
255
304
|
if (!payload?.userId) {
|
|
256
305
|
res.status(401).json({ error: "Invalid or expired token" });
|
|
257
306
|
return;
|
|
@@ -437,18 +486,19 @@ function cookieToken(cookies, names) {
|
|
|
437
486
|
function transportCookieNaming(cookieName) {
|
|
438
487
|
return { cookieName, domain: cookieDomainFromEnv() };
|
|
439
488
|
}
|
|
440
|
-
function
|
|
489
|
+
function httpCredentialsOf(req, naming) {
|
|
441
490
|
const cookie = cookieToken(cookiesOf(req), sessionCookieNamesFor(req, naming));
|
|
442
|
-
if (cookie !== null) {
|
|
443
|
-
return { token: cookie, from: "cookie" };
|
|
444
|
-
}
|
|
445
491
|
const bearer = extractBearerOrCookieToken({
|
|
446
492
|
headers: { authorization: req.headers.authorization }
|
|
447
493
|
});
|
|
448
|
-
return
|
|
494
|
+
return { cookie, bearer: bearer === "" ? null : bearer };
|
|
449
495
|
}
|
|
450
|
-
function
|
|
451
|
-
|
|
496
|
+
function httpCredentialOf(req, naming) {
|
|
497
|
+
const { cookie, bearer } = httpCredentialsOf(req, naming);
|
|
498
|
+
if (cookie !== null) {
|
|
499
|
+
return { token: cookie, from: "cookie" };
|
|
500
|
+
}
|
|
501
|
+
return bearer === null ? null : { token: bearer, from: "bearer" };
|
|
452
502
|
}
|
|
453
503
|
|
|
454
504
|
export {
|
|
@@ -460,6 +510,9 @@ export {
|
|
|
460
510
|
acknowledge,
|
|
461
511
|
recordSocketSession,
|
|
462
512
|
socketSessionOf,
|
|
513
|
+
socketSessionExpiryOf,
|
|
514
|
+
markSocketAuth,
|
|
515
|
+
socketAuthOf,
|
|
463
516
|
isRefusal,
|
|
464
517
|
isForbiddenCredential,
|
|
465
518
|
isPrincipal,
|
|
@@ -467,6 +520,7 @@ export {
|
|
|
467
520
|
createPrincipalResolver,
|
|
468
521
|
createGrantsSink,
|
|
469
522
|
createJWT,
|
|
523
|
+
readVerifiedJWT,
|
|
470
524
|
verifyJWT,
|
|
471
525
|
SESSION_COOKIE,
|
|
472
526
|
HOST_SESSION_COOKIE,
|
|
@@ -474,6 +528,7 @@ export {
|
|
|
474
528
|
cookieDomainFromEnv,
|
|
475
529
|
sessionCookieNameFor,
|
|
476
530
|
sessionCookieNamesFor,
|
|
531
|
+
clearStaleHostSession,
|
|
477
532
|
setSessionCookie,
|
|
478
533
|
clearSessionCookie,
|
|
479
534
|
extractBearerOrCookieToken,
|
|
@@ -483,7 +538,7 @@ export {
|
|
|
483
538
|
cookiesOf,
|
|
484
539
|
cookieToken,
|
|
485
540
|
transportCookieNaming,
|
|
486
|
-
|
|
487
|
-
|
|
541
|
+
httpCredentialsOf,
|
|
542
|
+
httpCredentialOf
|
|
488
543
|
};
|
|
489
|
-
//# sourceMappingURL=chunk-
|
|
544
|
+
//# sourceMappingURL=chunk-PHCURHC7.js.map
|