@fitzzero/quickdraw-core 5.1.2 → 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 +793 -57
- package/dist/{admin-DWWrT1h6.d.ts → admin-CS7JB_UH.d.ts} +2 -2
- package/dist/{adminSchemas-D4bFKsrb.d.ts → adminSchemas-29cGgrg5.d.ts} +1 -1
- package/dist/{auth-DXiSJZaf.d.ts → auth-DtdYjrZ9.d.ts} +11 -7
- package/dist/{caller-BT-Mv4bD.d.ts → caller-BTwGl7vm.d.ts} +183 -15
- package/dist/chunk-2FDSKLBO.js +82 -0
- package/dist/chunk-2FDSKLBO.js.map +1 -0
- package/dist/{chunk-GSIPUNJL.js → chunk-64I6MYBC.js} +139 -792
- 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-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-DNP65TD5.js +832 -0
- package/dist/chunk-DNP65TD5.js.map +1 -0
- package/dist/{chunk-5CGO426C.js → chunk-GYLWEJHW.js} +5 -1
- package/dist/chunk-GYLWEJHW.js.map +1 -0
- package/dist/{chunk-AONAFOYU.js → chunk-I3JCFS7H.js} +25 -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-6K5BY47X.js → chunk-JVTONQFI.js} +1277 -277
- package/dist/chunk-JVTONQFI.js.map +1 -0
- package/dist/{chunk-RL4VKLBX.js → chunk-KKQANRLG.js} +2 -2
- package/dist/{chunk-RL4VKLBX.js.map → chunk-KKQANRLG.js.map} +1 -1
- package/dist/{chunk-GKH3LJ7N.js → chunk-MPQAT55F.js} +38 -205
- package/dist/chunk-MPQAT55F.js.map +1 -0
- package/dist/chunk-NX2V6SIL.js +202 -0
- package/dist/chunk-NX2V6SIL.js.map +1 -0
- package/dist/{chunk-7QCUX4TK.js → chunk-NZHA4TZD.js} +72 -175
- package/dist/chunk-NZHA4TZD.js.map +1 -0
- package/dist/{chunk-MBH6IDSM.js → chunk-OCZJ4EYV.js} +40 -17
- package/dist/chunk-OCZJ4EYV.js.map +1 -0
- package/dist/{chunk-RJ5I2VO3.js → chunk-PHCURHC7.js} +6 -6
- 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-LCC7HNFP.js → chunk-RZXJTDH5.js} +2 -2
- package/dist/{chunk-Z2LZ7IZ7.js → chunk-SN3OZVEQ.js} +5 -31
- package/dist/chunk-SN3OZVEQ.js.map +1 -0
- package/dist/{chunk-Z5ILULF2.js → chunk-SQ5VUG77.js} +4 -3
- package/dist/{chunk-Z5ILULF2.js.map → chunk-SQ5VUG77.js.map} +1 -1
- package/dist/chunk-STH5DLQP.js +1192 -0
- package/dist/chunk-STH5DLQP.js.map +1 -0
- package/dist/{chunk-NMXYENH4.js → chunk-VZFJTKIW.js} +6 -6
- package/dist/{chunk-753VJIUP.js → chunk-X4ZU4QH5.js} +43 -9
- 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-Z7I6SONO.js +825 -0
- package/dist/chunk-Z7I6SONO.js.map +1 -0
- package/dist/cli/quickdraw-docs.js +131 -113
- 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/core.js.map +1 -0
- package/dist/client/index.d.ts +30 -193
- package/dist/client/index.js +56 -217
- package/dist/client/index.js.map +1 -1
- package/dist/{clientTypes-hWcPUVS9.d.ts → clientTypes-CUUNJwWs.d.ts} +3 -3
- package/dist/{connection-CgijdGpT.d.ts → connection-2EeQ_Et0.d.ts} +16 -9
- package/dist/{createServer-Cp-Wk500.d.ts → createServer-Bx5HOcYK.d.ts} +37 -9
- package/dist/{createTestApp-BB_PkqQ7.d.ts → createTestApp-DAMANT79.d.ts} +36 -9
- package/dist/{envelope-DzWyIXjj.d.ts → envelope-BMBaxppV.d.ts} +200 -8
- package/dist/{http-DotQ5bj8.d.ts → http-YzLAar3w.d.ts} +15 -50
- package/dist/index.d.ts +7 -6
- package/dist/index.js +61 -28
- package/dist/index.js.map +1 -1
- package/dist/{infer-BmoZsL9a.d.ts → infer-Br62cnyW.d.ts} +39 -1
- package/dist/{metrics-DW80Exve.d.ts → metrics-CTVpw0gu.d.ts} +2 -2
- package/dist/parser.js +2 -1
- package/dist/prisma/index.d.ts +13 -6
- package/dist/prisma/index.js +155 -9
- package/dist/prisma/index.js.map +1 -1
- package/dist/remote-N7OUAGOW.js +15 -0
- package/dist/remote-N7OUAGOW.js.map +1 -0
- package/dist/server/auth/index.d.ts +3 -3
- package/dist/server/auth/index.js +5 -3
- package/dist/server/auth/index.js.map +1 -1
- package/dist/server/index.d.ts +140 -36
- package/dist/server/index.js +162 -55
- package/dist/server/index.js.map +1 -1
- package/dist/server/mcp/index.d.ts +34 -18
- package/dist/server/mcp/index.js +29 -12
- package/dist/server/mcp/index.js.map +1 -1
- package/dist/server/otel.d.ts +3 -3
- package/dist/{sharing-UDLn1049.d.ts → sharing-BrsmlDv_.d.ts} +3 -3
- package/dist/testing/client.d.ts +13 -13
- package/dist/testing/client.js +17 -10
- package/dist/testing/client.js.map +1 -1
- package/dist/testing/index.d.ts +49 -12
- package/dist/testing/index.js +102 -19
- package/dist/testing/index.js.map +1 -1
- package/dist/testing/mock.d.ts +5 -5
- package/dist/testing/mock.js +15 -9
- package/dist/tracked-BR5b2O-U.d.ts +43 -0
- package/dist/{types-CYliTP65.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-4YO5H5ON.js.map +0 -1
- package/dist/chunk-5CGO426C.js.map +0 -1
- package/dist/chunk-6K5BY47X.js.map +0 -1
- package/dist/chunk-753VJIUP.js.map +0 -1
- package/dist/chunk-7QCUX4TK.js.map +0 -1
- package/dist/chunk-AONAFOYU.js.map +0 -1
- package/dist/chunk-B2P7AZ25.js.map +0 -1
- package/dist/chunk-GKH3LJ7N.js.map +0 -1
- package/dist/chunk-GSIPUNJL.js.map +0 -1
- package/dist/chunk-MBH6IDSM.js.map +0 -1
- package/dist/chunk-RJ5I2VO3.js.map +0 -1
- package/dist/chunk-X5CWPX7H.js.map +0 -1
- package/dist/chunk-Z2LZ7IZ7.js.map +0 -1
- /package/dist/{chunk-LCC7HNFP.js.map → chunk-RZXJTDH5.js.map} +0 -0
- /package/dist/{chunk-NMXYENH4.js.map → chunk-VZFJTKIW.js.map} +0 -0
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/contract/validateRealtime.ts","../src/contract/validateContract.ts","../src/contract/defineContract.ts"],"sourcesContent":["// Definition-time checks of a contract's streams, channels and events (RFC\n// 0003 section 12.5), for `validateContract.ts`. The types catch the same\n// mistakes at compile time; these catch them for JavaScript callers and casts.\n// Every member name is checked against the names taken before it: methods,\n// collections, streams, channels and events share `qd.<service>.<name>`.\n\nimport { ACCESS_LEVELS, isAccessLevel } from \"./access\";\nimport { reservedRoomPrefix, socketIdShaped } from \"./names\";\nimport type { ChannelDef, EventDef, StreamDef } from \"./realtime\";\nimport { isScopedStream, STREAM_MAX_SEED } from \"./realtime\";\nimport { isStandardSchema } from \"./standardSchema\";\n\ntype Fail = (message: string) => never;\n\ntype UnknownRecord = Readonly<Record<string, unknown>>;\n\n/** The member names taken so far, and by what kind of member. */\nexport type TakenNames = Map<string, string>;\n\n/** What the realtime members are checked against. */\nexport interface RealtimeScope {\n readonly hasEntity: boolean;\n readonly collections: ReadonlySet<string>;\n readonly taken: TakenNames;\n readonly reserved: ReadonlySet<string>;\n}\n\nconst STREAM_KEYS: ReadonlySet<string> = new Set([\n \"item\",\n \"scope\",\n \"seed\",\n \"volatile\",\n \"access\",\n \"describe\",\n]);\nconst CHANNEL_KEYS: ReadonlySet<string> = new Set([\n \"payload\",\n \"ratePerSecond\",\n \"burst\",\n \"requires\",\n \"describe\",\n]);\nconst EVENT_KEYS: ReadonlySet<string> = new Set([\"payload\", \"describe\"]);\n\n/** The longest app room name `ctx.rooms.join` takes, so the longest prefix one can start with. */\nconst MAX_ROOM_LENGTH = 256;\n\nfunction isRecord(value: unknown): value is UnknownRecord {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction isName(value: unknown): value is string {\n return typeof value === \"string\" && value.length > 0;\n}\n\nfunction quote(names: Iterable<string>): string {\n return [...names].map((name) => `\"${name}\"`).join(\", \");\n}\n\n/** The members of an optional map: absent is empty, anything else must be a plain object. */\nfunction entriesOf(value: unknown, label: string, fail: Fail): [string, unknown][] {\n if (value === undefined) {\n return [];\n }\n if (!isRecord(value)) {\n fail(`${label} must be an object`);\n }\n return Object.entries(value);\n}\n\nfunction checkName(kind: string, name: string, scope: RealtimeScope, fail: Fail): void {\n if (scope.reserved.has(name) || name.startsWith(\"$\")) {\n fail(\n `${kind} \"${name}\" uses a reserved name; ${quote(scope.reserved)} and names starting with \"$\" are reserved`,\n );\n }\n const holder = scope.taken.get(name);\n if (holder !== undefined) {\n fail(\n `${kind} \"${name}\" has the same name as a ${holder}; the client exposes both as qd.<service>.${name}`,\n );\n }\n scope.taken.set(name, kind);\n}\n\nfunction checkMember(\n kind: string,\n name: string,\n value: unknown,\n schemaKey: \"item\" | \"payload\",\n keys: ReadonlySet<string>,\n fail: Fail,\n): UnknownRecord {\n if (!isRecord(value) || !isStandardSchema(value[schemaKey])) {\n fail(`${kind} \"${name}\" must be { ${schemaKey}: <Standard Schema>, ... }`);\n }\n for (const key of Object.keys(value)) {\n if (!keys.has(key)) {\n fail(`${kind} \"${name}\" has an unknown option \"${key}\"; the options are ${quote(keys)}`);\n }\n }\n if (value.describe !== undefined && !isName(value.describe)) {\n fail(`${kind} \"${name}\": describe must be a non-empty string`);\n }\n return value;\n}\n\n/** Why a literal room of the shape of a socket id names no app room (`socketIdShaped`). */\nfunction socketIdProblem(room: string): string {\n return `room \"${room}\" has the shape of a Socket.IO socket id (20 letters, digits, \"_\" or \"-\"), which ctx.rooms.join refuses: no socket is in it as an app room`;\n}\n\n/** Why `access: { room }` names no app room a subscriber could be in, or `undefined`. */\nfunction streamRoomProblem(access: UnknownRecord, scoped: boolean): string | undefined {\n const { room } = access;\n if (Object.keys(access).length !== 1) {\n return \"a room form is { room } and nothing else\";\n }\n if (typeof room === \"function\") {\n return scoped ? undefined : \"a room computed from the scope needs a scoped stream\";\n }\n if (scoped) {\n return \"a room for a scoped stream is a function of its scope, (scope) => room: a name or { prefix } admits a socket in that room to every scope\";\n }\n const name = isRecord(room) && Object.keys(room).length === 1 ? room.prefix : room;\n if (!isName(name) || name.length > MAX_ROOM_LENGTH) {\n return `room must be an app room's name, { prefix } or a function of the scope, of 1 to ${MAX_ROOM_LENGTH} characters`;\n }\n const reserved = reservedRoomPrefix(name);\n if (reserved !== undefined) {\n return `room \"${name}\" is no app room: names starting with \"${reserved}\" are the framework's own rooms`;\n }\n return typeof room === \"string\" && socketIdShaped(room) ? socketIdProblem(room) : undefined;\n}\n\n/** Why `access` is not a stream access form, or `undefined` when it is one. */\nfunction streamAccessProblem(access: unknown, scoped: boolean): string | undefined {\n if (access === \"public\" || access === \"authenticated\") {\n return undefined;\n }\n if (isRecord(access) && access.room !== undefined) {\n return streamRoomProblem(access, scoped);\n }\n const levels = isRecord(access)\n ? [\"service\", \"entry\", \"scope\"].filter((key) => access[key] !== undefined)\n : [];\n if (\n !isRecord(access) ||\n levels.length === 0 ||\n !levels.every((key) => isAccessLevel(access[key]))\n ) {\n return `must be \"public\", \"authenticated\", { service }, { entry } or { scope, of }, with levels among ${quote(ACCESS_LEVELS)}`;\n }\n const extra = Object.keys(access).find(\n (key) => ![\"service\", \"entry\", \"scope\", \"of\"].includes(key),\n );\n if (extra !== undefined) {\n return `has an unknown key \"${extra}\"`;\n }\n if (access.scope !== undefined) {\n const of: unknown = access.of;\n return levels.length === 1 && isRecord(of) && isName(of.name)\n ? undefined\n : \"a scope form is { scope, of: contract } and nothing else\";\n }\n return access.of === undefined ? undefined : \"of belongs to scope forms\";\n}\n\nfunction checkStream(name: string, value: unknown, fail: Fail): StreamDef {\n const owner = `stream \"${name}\"`;\n const stream = checkMember(\"stream\", name, value, \"item\", STREAM_KEYS, fail);\n if (name.includes(\":\")) {\n fail(`${owner} may not contain \":\"; it is part of the stream's room name`);\n }\n if (stream.scope !== undefined && !isName(stream.scope)) {\n fail(`${owner}: scope must be \"global\" or a non-empty name for what a scope value is`);\n }\n const { seed } = stream;\n if (\n seed !== undefined &&\n !(Number.isInteger(seed) && (seed as number) >= 0 && (seed as number) <= STREAM_MAX_SEED)\n ) {\n fail(`${owner}: seed must be a whole number from 0 to ${STREAM_MAX_SEED}`);\n }\n if (stream.volatile !== undefined && typeof stream.volatile !== \"boolean\") {\n fail(`${owner}: volatile must be a boolean`);\n }\n if (stream.access !== undefined) {\n const problem = streamAccessProblem(\n stream.access,\n isScopedStream(stream as Pick<StreamDef, \"scope\">),\n );\n if (problem !== undefined) {\n fail(`${owner}: access ${problem}`);\n }\n const access = stream.access as UnknownRecord | string;\n const rowForm = isRecord(access) && (access.entry !== undefined || access.scope !== undefined);\n if (rowForm && !isScopedStream(stream as Pick<StreamDef, \"scope\">)) {\n fail(`${owner}: entry and scope access check the scope's row, so the stream needs a scope`);\n }\n }\n return Object.freeze({ ...stream }) as unknown as StreamDef;\n}\n\nfunction isSelector(value: unknown): boolean {\n return isName(value) || typeof value === \"function\";\n}\n\nconst REQUIRES_FORMS = \"requires must be { entity }, { collection, scope } or { room }\";\n\n/** Checks `requires: { room: { prefix } }`: a prefix some app room's name could start with. */\nfunction checkRoomPrefix(owner: string, room: UnknownRecord, fail: Fail): void {\n const { prefix } = room;\n const extra = Object.keys(room).find((key) => key !== \"prefix\");\n if (extra !== undefined || !isName(prefix) || prefix.length > MAX_ROOM_LENGTH) {\n fail(\n `${owner}: requires.room as an object is { prefix }, a string of 1 to ${MAX_ROOM_LENGTH} characters`,\n );\n }\n const reserved = reservedRoomPrefix(prefix);\n if (reserved !== undefined) {\n fail(\n `${owner}: requires.room's prefix \"${prefix}\" names no app room: names starting with \"${reserved}\" are the framework's own rooms, which ctx.rooms.join refuses`,\n );\n }\n}\n\n/**\n * Checks `requires: { room }`: a function of the payload, the name of an\n * app room, which is never empty and never starts with a reserved prefix\n * (`ctx.rooms.join` refuses those, so no socket could ever be in it), or\n * `{ prefix }`, held to the same rule.\n */\nfunction checkRoomRequirement(owner: string, form: UnknownRecord, fail: Fail): void {\n if (form.entity !== undefined || form.collection !== undefined || form.scope !== undefined) {\n fail(`${owner}: ${REQUIRES_FORMS}`);\n }\n const { room } = form;\n if (typeof room === \"function\") {\n return;\n }\n if (isRecord(room)) {\n checkRoomPrefix(owner, room, fail);\n return;\n }\n if (!isName(room)) {\n fail(\n `${owner}: requires.room must be an app room's name, a function of the payload or { prefix }`,\n );\n }\n const prefix = reservedRoomPrefix(room);\n if (prefix !== undefined) {\n fail(\n `${owner}: requires.room \"${room}\" is not an app room: names starting with \"${prefix}\" are the framework's own rooms, which ctx.rooms.join refuses`,\n );\n }\n if (socketIdShaped(room)) {\n fail(`${owner}: requires.${socketIdProblem(room)}`);\n }\n}\n\nfunction checkRequires(owner: string, requires: unknown, scope: RealtimeScope, fail: Fail): void {\n if (requires === undefined) {\n return;\n }\n const form = isRecord(requires) ? requires : {};\n if (form.room !== undefined) {\n checkRoomRequirement(owner, form, fail);\n return;\n }\n if (form.entity !== undefined && form.collection === undefined && form.scope === undefined) {\n if (!isSelector(form.entity)) {\n fail(`${owner}: requires.entity must be a payload key or a function of the payload`);\n }\n if (!scope.hasEntity) {\n fail(`${owner}: requires.entity needs the contract's entity`);\n }\n return;\n }\n if (form.entity !== undefined || !isName(form.collection) || !isSelector(form.scope)) {\n fail(`${owner}: ${REQUIRES_FORMS}`);\n }\n if (!scope.collections.has(form.collection)) {\n fail(\n `${owner}: requires names unknown collection \"${form.collection}\"; the collections are ${quote(scope.collections)}`,\n );\n }\n}\n\nfunction checkChannel(name: string, value: unknown, scope: RealtimeScope, fail: Fail): ChannelDef {\n const owner = `channel \"${name}\"`;\n const channel = checkMember(\"channel\", name, value, \"payload\", CHANNEL_KEYS, fail);\n const positive = (rate: unknown, least: number): boolean =>\n rate === undefined || (typeof rate === \"number\" && Number.isFinite(rate) && rate >= least);\n if (!positive(channel.ratePerSecond, Number.MIN_VALUE)) {\n fail(`${owner}: ratePerSecond must be a number of messages above 0`);\n }\n if (!positive(channel.burst, 1)) {\n fail(`${owner}: burst must be a number of messages, at least 1`);\n }\n checkRequires(owner, channel.requires, scope, fail);\n return Object.freeze({ ...channel }) as unknown as ChannelDef;\n}\n\n/**\n * Checks the `streams`, `channels` and `events` of a contract definition,\n * taking their names in `scope.taken` after the methods and collections, and\n * returns them frozen.\n */\nexport function checkRealtime(\n def: UnknownRecord,\n scope: RealtimeScope,\n fail: Fail,\n): {\n readonly streams: Readonly<Record<string, StreamDef>>;\n readonly channels: Readonly<Record<string, ChannelDef>>;\n readonly events: Readonly<Record<string, EventDef>>;\n} {\n const streams: Record<string, StreamDef> = {};\n for (const [name, value] of entriesOf(def.streams, \"streams\", fail)) {\n checkName(\"stream\", name, scope, fail);\n streams[name] = checkStream(name, value, fail);\n }\n const channels: Record<string, ChannelDef> = {};\n for (const [name, value] of entriesOf(def.channels, \"channels\", fail)) {\n checkName(\"channel\", name, scope, fail);\n channels[name] = checkChannel(name, value, scope, fail);\n }\n const events: Record<string, EventDef> = {};\n for (const [name, value] of entriesOf(def.events, \"events\", fail)) {\n checkName(\"event\", name, scope, fail);\n const event = checkMember(\"event\", name, value, \"payload\", EVENT_KEYS, fail);\n events[name] = Object.freeze({ ...event }) as unknown as EventDef;\n }\n return {\n streams: Object.freeze(streams),\n channels: Object.freeze(channels),\n events: Object.freeze(events),\n };\n}\n","// Definition-time checks for `defineContract`. The types catch the same\n// mistakes at compile time; these catch them for JavaScript callers and casts,\n// and freeze the result so a contract cannot change after it is defined.\n\nimport { ACCESS_LEVELS, type AccessLevel, isAccessLevel } from \"./access\";\nimport {\n type CollectionDef,\n DEFAULT_COLLECTION_LIMIT,\n DEFAULT_COLLECTION_MAX_LIMIT,\n} from \"./collections\";\nimport type { AnyContract, RowSchema } from \"./defineContract\";\nimport type { MethodDef } from \"./methods\";\nimport { isStandardSchema } from \"./standardSchema\";\nimport { checkRealtime, type TakenNames } from \"./validateRealtime\";\n\ntype Fail = (message: string) => never;\n\ntype UnknownRecord = Readonly<Record<string, unknown>>;\n\n// `useEntity`, `useEntities` and `admin` are members the client proxy places\n// beside a service's methods and collections (RFC 0003 sections 11 and 12.4).\n// `then` would make a service's caller look like a promise: `await` and\n// `Promise.resolve` would call it, so the callers answer `undefined` for it.\nconst RESERVED_NAMES: ReadonlySet<string> = new Set([\n \"subscribe\",\n \"unsubscribe\",\n \"call\",\n \"useEntity\",\n \"useEntities\",\n \"admin\",\n \"then\",\n]);\n\nconst DEFINITION_KEYS: ReadonlySet<string> = new Set([\n \"describe\",\n \"entity\",\n \"projections\",\n \"fields\",\n \"methods\",\n \"collections\",\n \"streams\",\n \"channels\",\n \"events\",\n]);\n\nconst METHOD_KEYS: ReadonlySet<string> = new Set([\"kind\", \"input\", \"output\", \"watch\", \"describe\"]);\n\nconst COLLECTION_KEYS: ReadonlySet<string> = new Set([\n \"describe\",\n \"scope\",\n \"item\",\n \"order\",\n \"where\",\n \"limit\",\n \"maxLimit\",\n \"index\",\n \"views\",\n \"access\",\n]);\n\nfunction isRecord(value: unknown): value is UnknownRecord {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction quote(names: Iterable<string>): string {\n const list = [...names].map((name) => `\"${name}\"`);\n return list.length === 0 ? \"none\" : list.join(\", \");\n}\n\nfunction checkKeys(\n value: UnknownRecord,\n allowed: ReadonlySet<string>,\n owner: string,\n fail: Fail,\n): void {\n for (const key of Object.keys(value)) {\n if (!allowed.has(key)) {\n fail(`${owner} has an unknown option \"${key}\"; the options are ${quote(allowed)}`);\n }\n }\n}\n\n/** An optional map member: absent is empty, anything else must be a plain object. */\nfunction members(value: unknown, label: string, fail: Fail): UnknownRecord {\n if (value === undefined) {\n return {};\n }\n if (!isRecord(value)) {\n fail(`${label} must be an object`);\n }\n return value;\n}\n\nfunction checkMemberName(kind: \"method\" | \"collection\", name: string, fail: Fail): void {\n if (RESERVED_NAMES.has(name) || name.startsWith(\"$\")) {\n fail(\n `${kind} \"${name}\" uses a reserved name; ${quote(RESERVED_NAMES)} and names starting with \"$\" are reserved`,\n );\n }\n}\n\nfunction checkEntity(entity: unknown, fail: Fail): RowSchema | undefined {\n if (entity !== undefined && !isStandardSchema(entity)) {\n fail(\"entity must be a Standard Schema\");\n }\n return entity as RowSchema | undefined;\n}\n\nfunction checkProjections(\n value: unknown,\n hasEntity: boolean,\n fail: Fail,\n): Record<string, RowSchema> {\n const projections = members(value, \"projections\", fail);\n const checked: Record<string, RowSchema> = {};\n for (const [name, schema] of Object.entries(projections)) {\n if (!hasEntity) {\n fail(`projection \"${name}\" needs an entity; declare the contract's entity first`);\n }\n if (name === \"entity\") {\n fail(`a projection is named \"entity\", which is the implicit full-row projection`);\n }\n if (!isStandardSchema(schema)) {\n fail(`projection \"${name}\" must be a Standard Schema`);\n }\n checked[name] = schema as RowSchema;\n }\n return checked;\n}\n\nfunction checkFields(value: unknown, hasEntity: boolean, fail: Fail): Record<string, AccessLevel> {\n const fields = members(value, \"fields\", fail);\n const checked: Record<string, AccessLevel> = {};\n for (const [field, level] of Object.entries(fields)) {\n if (!hasEntity) {\n fail(`field \"${field}\" needs an entity; declare the contract's entity first`);\n }\n if (field === \"id\") {\n fail(`fields cannot restrict \"id\"; every subscriber receives it`);\n }\n if (!isAccessLevel(level)) {\n fail(`field \"${field}\" must map to one of ${quote(ACCESS_LEVELS)}`);\n }\n checked[field] = level;\n }\n return checked;\n}\n\n/** The projection a method output names, or undefined when the output is not a projection. */\nfunction projectionOf(output: unknown): unknown {\n if (typeof output === \"string\") {\n return output;\n }\n if (isRecord(output) && (output.kind === \"nullable\" || output.kind === \"list\")) {\n return output.projection;\n }\n return undefined;\n}\n\ninterface MethodScope {\n readonly projections: ReadonlySet<string>;\n readonly collections: ReadonlySet<string>;\n}\n\nfunction checkOutput(name: string, output: unknown, scope: MethodScope, fail: Fail): void {\n if (isStandardSchema(output)) {\n return;\n }\n const projection = projectionOf(output);\n if (typeof projection !== \"string\") {\n fail(\n `method \"${name}\": output must be a Standard Schema, a projection name, nullable(...) or listOf(...)`,\n );\n }\n if (!scope.projections.has(projection)) {\n fail(\n `method \"${name}\" returns unknown projection \"${projection}\"; the projections are ${quote(scope.projections)}`,\n );\n }\n}\n\n/**\n * `watch: { service: [models] }`: a non-empty list of distinct model names\n * and nothing else. Whether they are the service's models (its `model` and\n * `writes`) only `defineService` knows.\n */\nfunction checkServiceModels(name: string, watch: UnknownRecord, fail: Fail): void {\n const models: unknown = watch.service;\n const named =\n Array.isArray(models) &&\n models.length > 0 &&\n models.every((model) => typeof model === \"string\" && model !== \"\") &&\n new Set(models).size === models.length;\n if (!named || Object.keys(watch).length !== 1) {\n fail(\n `method \"${name}\": watch { service } lists the models of the service it watches, by the client's model name: { service: [\"gameScore\"] }`,\n );\n }\n}\n\nfunction checkWatch(name: string, method: UnknownRecord, scope: MethodScope, fail: Fail): void {\n const { watch } = method;\n if (watch === undefined) {\n return;\n }\n if (method.kind !== \"query\") {\n fail(`method \"${name}\" is a mutation; only a query can watch`);\n }\n if (watch === \"service\") {\n return;\n }\n if (isRecord(watch) && Object.hasOwn(watch, \"service\")) {\n checkServiceModels(name, watch, fail);\n return;\n }\n if (!isRecord(watch) || typeof watch.scope !== \"function\") {\n fail(\n `method \"${name}\": watch must be \"service\", { service: [models] }, or { collection, scope } with a scope function`,\n );\n }\n if (typeof watch.collection !== \"string\" || !scope.collections.has(watch.collection)) {\n fail(\n `method \"${name}\" watches unknown collection \"${String(watch.collection)}\"; the collections are ${quote(scope.collections)}`,\n );\n }\n}\n\nfunction checkMethod(name: string, method: unknown, scope: MethodScope, fail: Fail): MethodDef {\n checkMemberName(\"method\", name, fail);\n if (!isRecord(method) || (method.kind !== \"query\" && method.kind !== \"mutation\")) {\n fail(`method \"${name}\" must be declared with query(...) or mutation(...)`);\n }\n checkKeys(method, METHOD_KEYS, `method \"${name}\"`, fail);\n if (!isStandardSchema(method.input)) {\n fail(`method \"${name}\": input must be a Standard Schema`);\n }\n checkOutput(name, method.output, scope, fail);\n checkWatch(name, method, scope, fail);\n if (method.describe !== undefined && !isName(method.describe)) {\n fail(`method \"${name}\": describe must be a non-empty string`);\n }\n return method as unknown as MethodDef;\n}\n\nfunction checkMethods(value: unknown, scope: MethodScope, fail: Fail): Record<string, MethodDef> {\n const checked: Record<string, MethodDef> = {};\n for (const [name, method] of Object.entries(members(value, \"methods\", fail))) {\n checked[name] = checkMethod(name, method, scope, fail);\n }\n return checked;\n}\n\nfunction isName(value: unknown): value is string {\n return typeof value === \"string\" && value.length > 0;\n}\n\nfunction checkScope(owner: string, scope: unknown, fail: Fail): void {\n if (isName(scope)) {\n return;\n }\n const isVia =\n isRecord(scope) &&\n scope.kind === \"via\" &&\n isName(scope.model) &&\n isName(scope.entry) &&\n isName(scope.scope);\n if (!isVia) {\n fail(`${owner}: scope must be a column name or via({ model, entry, scope })`);\n }\n const { refreshEntry } = scope as { readonly refreshEntry?: unknown };\n if (refreshEntry !== undefined && typeof refreshEntry !== \"boolean\") {\n fail(`${owner}: via's refreshEntry must be true or false`);\n }\n}\n\nfunction isSortColumn(entry: unknown): entry is readonly [string, string] {\n return (\n Array.isArray(entry) &&\n entry.length === 2 &&\n isName(entry[0]) &&\n (entry[1] === \"asc\" || entry[1] === \"desc\")\n );\n}\n\nfunction checkOrder(owner: string, order: unknown, fail: Fail): void {\n if (!Array.isArray(order) || order.length === 0 || !order.every(isSortColumn)) {\n fail(`${owner}: order must be a list of [column, \"asc\" | \"desc\"] pairs ending with \"id\"`);\n }\n const last: unknown = order.at(-1);\n if (!isSortColumn(last) || last[0] !== \"id\") {\n fail(`${owner}: order must end with \"id\" so every row has a unique cursor position`);\n }\n}\n\nfunction checkWhere(owner: string, where: unknown, fail: Fail): void {\n if (where === undefined) {\n return;\n }\n const scalar = (value: unknown): boolean =>\n value === null || [\"string\", \"number\", \"boolean\"].includes(typeof value);\n if (!isRecord(where) || !Object.values(where).every(scalar)) {\n fail(`${owner}: where must map columns to strings, numbers, booleans or null`);\n }\n}\n\nfunction checkLimits(owner: string, collection: UnknownRecord, fail: Fail): void {\n const positive = (value: unknown): boolean =>\n value === undefined || (Number.isInteger(value) && (value as number) > 0);\n if (!positive(collection.limit) || !positive(collection.maxLimit)) {\n fail(`${owner}: limit and maxLimit must be positive integers`);\n }\n const limit = (collection.limit as number | undefined) ?? DEFAULT_COLLECTION_LIMIT;\n const maxLimit = (collection.maxLimit as number | undefined) ?? DEFAULT_COLLECTION_MAX_LIMIT;\n if (limit > maxLimit) {\n fail(`${owner}: limit (${limit}) is larger than maxLimit (${maxLimit})`);\n }\n}\n\nfunction checkIndexAndViews(owner: string, collection: UnknownRecord, fail: Fail): void {\n const { index, views } = collection;\n if (index !== undefined && (!Array.isArray(index) || !index.every(isName))) {\n fail(`${owner}: index must be a list of item field names`);\n }\n if (views === undefined) {\n return;\n }\n if (index === undefined) {\n fail(`${owner} declares views but no index; views read index rows`);\n }\n if (!isRecord(views) || !Object.values(views).every((view) => typeof view === \"function\")) {\n fail(`${owner}: views must map names to predicate functions`);\n }\n}\n\ninterface CollectionScope {\n readonly hasEntity: boolean;\n readonly projections: ReadonlySet<string>;\n readonly methods: ReadonlySet<string>;\n}\n\nfunction checkCollection(\n name: string,\n value: unknown,\n scope: CollectionScope,\n fail: Fail,\n): CollectionDef {\n const owner = `collection \"${name}\"`;\n checkMemberName(\"collection\", name, fail);\n if (name.includes(\":\")) {\n fail(\n `${owner} may not contain \":\"; a change topic is {collection}:{scope}, split at its first colon`,\n );\n }\n if (scope.methods.has(name)) {\n fail(`${owner} has the same name as a method; the client exposes both as qd.<service>.${name}`);\n }\n if (!scope.hasEntity) {\n fail(`${owner} needs an entity; declare the contract's entity first`);\n }\n if (!isRecord(value)) {\n fail(`${owner} must be an object`);\n }\n checkKeys(value, COLLECTION_KEYS, owner, fail);\n checkScope(owner, value.scope, fail);\n if (typeof value.item !== \"string\" || !scope.projections.has(value.item)) {\n fail(\n `${owner}: item \"${String(value.item)}\" is not a projection; the projections are ${quote(scope.projections)}`,\n );\n }\n checkOrder(owner, value.order, fail);\n checkWhere(owner, value.where, fail);\n checkLimits(owner, value, fail);\n checkIndexAndViews(owner, value, fail);\n if (value.access !== undefined && !isAccessLevel(value.access)) {\n fail(`${owner}: access must be one of ${quote(ACCESS_LEVELS)}`);\n }\n if (value.describe !== undefined && !isName(value.describe)) {\n fail(`${owner}: describe must be a non-empty string`);\n }\n return Object.freeze({ ...value }) as unknown as CollectionDef;\n}\n\nfunction checkCollections(\n value: unknown,\n scope: CollectionScope,\n fail: Fail,\n): Record<string, CollectionDef> {\n const checked: Record<string, CollectionDef> = {};\n for (const [name, collection] of Object.entries(members(value, \"collections\", fail))) {\n checked[name] = checkCollection(name, collection, scope, fail);\n }\n return checked;\n}\n\n/** The names methods and collections took: streams, channels and events may not take them too. */\nfunction takenNames(\n methods: Readonly<Record<string, MethodDef>>,\n collections: Readonly<Record<string, CollectionDef>>,\n): TakenNames {\n const taken: TakenNames = new Map();\n for (const name of Object.keys(methods)) {\n taken.set(name, \"method\");\n }\n for (const name of Object.keys(collections)) {\n taken.set(name, \"collection\");\n }\n return taken;\n}\n\n/** Checks a contract definition and returns the frozen contract. */\nexport function assembleContract(name: unknown, def: unknown): AnyContract {\n if (!isName(name)) {\n throw new TypeError(\"defineContract: the service name must be a non-empty string\");\n }\n if (/[:@]/u.test(name)) {\n throw new TypeError(\n `defineContract(\"${name}\"): the service name may not contain \":\" or \"@\": it is part of every room name of the service (qd:e:{service}:{id}@{level}, qd:c:{service}:{collection}:{scope}), which must split one way only`,\n );\n }\n const fail: Fail = (message) => {\n throw new TypeError(`defineContract(\"${name}\"): ${message}`);\n };\n if (!isRecord(def)) {\n fail(\"the definition must be an object\");\n }\n checkKeys(def, DEFINITION_KEYS, \"the contract\", fail);\n if (def.describe !== undefined && !isName(def.describe)) {\n fail(\"describe must be a non-empty string\");\n }\n const entity = checkEntity(def.entity, fail);\n const hasEntity = entity !== undefined;\n const projections = checkProjections(def.projections, hasEntity, fail);\n const projectionNames = new Set(Object.keys(projections));\n if (hasEntity) {\n projectionNames.add(\"entity\");\n }\n const collectionNames = new Set(Object.keys(members(def.collections, \"collections\", fail)));\n const methods = checkMethods(\n def.methods,\n { projections: projectionNames, collections: collectionNames },\n fail,\n );\n const collections = checkCollections(\n def.collections,\n { hasEntity, projections: projectionNames, methods: new Set(Object.keys(methods)) },\n fail,\n );\n const realtime = checkRealtime(\n def,\n {\n hasEntity,\n collections: collectionNames,\n taken: takenNames(methods, collections),\n reserved: RESERVED_NAMES,\n },\n fail,\n );\n return Object.freeze({\n name,\n ...(def.describe === undefined ? {} : { describe: def.describe as string }),\n entity,\n projections: Object.freeze(projections),\n fields: Object.freeze(checkFields(def.fields, hasEntity, fail)),\n methods: Object.freeze(methods),\n collections: Object.freeze(collections),\n ...realtime,\n });\n}\n","// `defineContract`: one schema source per service (RFC 0003 section 2). A\n// contract is plain data plus schemas, so browser code imports it without any\n// server code. Every server and client type is derived from it: see\n// `infer.ts`. In 4.1 the same information was spread over a hand-written\n// method map, an optional Zod schema per method, seven generics on\n// `BaseService` (4.1 `src/server/BaseService.ts:68-80`) and room-name\n// helpers.\n\nimport type { AccessLevel } from \"./access\";\nimport type { CollectionDef, OrderBy, ViaScope, ViewPredicate } from \"./collections\";\nimport type { MethodDef, ProjectionRef, ServiceWatch } from \"./methods\";\nimport type { ChannelDef, EventDef, StreamDef } from \"./realtime\";\nimport type { InferOutput, StandardSchemaV1 } from \"./standardSchema\";\nimport { assembleContract } from \"./validateContract\";\n\nexport type { ChannelDef, EventDef, StreamDef };\n\n/** A schema whose output is a row: an object with `id: string`. */\nexport type RowSchema = StandardSchemaV1<unknown, { readonly id: string }>;\n\n/**\n * A channel as `defineContract` takes it. `requires` is typed by the\n * channel's payload through the definition's context, so a function there\n * gets the parsed payload as its parameter type; the contract stores it as a\n * `ChannelDef`.\n */\nexport interface ChannelDefinition extends Omit<ChannelDef, \"requires\"> {\n readonly requires?: unknown;\n}\n\n/** The second argument of {@link defineContract}. */\nexport interface ContractDefinition {\n /**\n * What the service is for, in a sentence or two. The generated API docs\n * lead the service's page with it and list it in their index.\n */\n readonly describe?: string;\n /**\n * The full row; its output must contain `id: string`. Omit it for a service\n * without a model, which then has no projections, fields or collections.\n *\n * Typed `unknown` here on purpose: `defineContract` checks it through its\n * own `Entity` parameter. Constraining it here as well makes TypeScript\n * reject Zod 3 schemas whenever a collection declares `views`.\n */\n readonly entity?: unknown;\n /** Named lean shapes of the entity. `\"entity\"` itself is implicit. */\n readonly projections?: { readonly [name: string]: RowSchema };\n /** The minimum level a subscriber needs to receive each entity field. */\n readonly fields?: { readonly [field: string]: AccessLevel };\n /** Every method is a `query(...)` or a `mutation(...)`. */\n readonly methods?: { readonly [name: string]: MethodDef };\n /** Live lists of the entity, grouped by a scope value. */\n readonly collections?: { readonly [name: string]: CollectionDef };\n readonly streams?: { readonly [name: string]: StreamDef };\n readonly channels?: { readonly [name: string]: ChannelDefinition };\n readonly events?: { readonly [name: string]: EventDef };\n}\n\ntype Empty = Record<never, never>;\ntype MemberOf<Def, Key extends string, Absent> = Def extends { readonly [K in Key]: infer Value }\n ? Value\n : Absent;\n\n/**\n * A defined contract: the definition with every member present (an absent\n * one is `undefined` for `entity` and `{}` otherwise) plus the service name.\n */\nexport interface Contract<\n Name extends string = string,\n Def extends ContractDefinition = ContractDefinition,\n> {\n /** The service name, unchanged on the wire and in stored grants. */\n readonly name: Name;\n /** What the service is for; absent when the definition has none. */\n readonly describe?: string;\n readonly entity: MemberOf<Def, \"entity\", undefined>;\n readonly projections: MemberOf<Def, \"projections\", Empty>;\n readonly fields: MemberOf<Def, \"fields\", Empty>;\n readonly methods: MemberOf<Def, \"methods\", Empty>;\n readonly collections: MemberOf<Def, \"collections\", Empty>;\n readonly streams: MemberOf<Def, \"streams\", Empty>;\n readonly channels: MemberOf<Def, \"channels\", Empty>;\n readonly events: MemberOf<Def, \"events\", Empty>;\n}\n\n/** Any contract. Every contract `defineContract` returns is assignable to it. */\nexport interface AnyContract {\n readonly name: string;\n readonly describe?: string;\n readonly entity: RowSchema | undefined;\n readonly projections: { readonly [name: string]: RowSchema };\n readonly fields: { readonly [field: string]: AccessLevel };\n readonly methods: { readonly [name: string]: MethodDef };\n readonly collections: { readonly [name: string]: CollectionDef };\n readonly streams: { readonly [name: string]: StreamDef };\n readonly channels: { readonly [name: string]: ChannelDef };\n readonly events: { readonly [name: string]: EventDef };\n}\n\n// ---------------------------------------------------------------------------\n// Definition context: the types that check each member against the entity\n// and projections, and give `views` predicates their row type. `Entity`,\n// `Projections`, `Items` and `Indexes` are inferred from the plain-data parts\n// of the definition before TypeScript types the predicates; everything else\n// sits behind `NoInfer` so it checks without steering that inference.\n// ---------------------------------------------------------------------------\n\ntype SchemaOutput<Schema> = Schema extends StandardSchemaV1 ? InferOutput<Schema> : never;\n\ntype ProjectionRow<Entity, Projections, Name> = Name extends \"entity\"\n ? SchemaOutput<Entity>\n : Name extends keyof Projections\n ? SchemaOutput<Projections[Name]>\n : never;\n\n/** Entity columns whose values are strings: the columns a collection can be scoped by. */\ntype StringColumn<Row> = {\n [Column in keyof Row]-?: NonNullable<Row[Column]> extends string ? Column : never;\n}[keyof Row];\n\ntype IndexField<Item> = Exclude<keyof Item, \"id\">;\n\ntype IndexedFields<Index> = Index extends readonly (infer Field)[] ? Field : never;\n\n/** An index row: `id` plus the collection's `index` fields of the item. */\nexport type IndexRow<Item, Fields> = Pick<Item, Extract<keyof Item, \"id\" | Fields>>;\n\n// Without an entity any column name passes here, so the checks below report\n// \"collections need an entity\" instead of a column error. The `& string`\n// makes an error message list the allowed names rather than print the name of\n// the type that computes them.\ntype ColumnOf<Row> = [Row] extends [never] ? string : keyof Row & string;\ntype ScopeColumnOf<Row> = [Row] extends [never] ? string : StringColumn<Row> & string;\n\n// Every option of `CollectionDef` is listed, the plain ones too: when a\n// channel's `requires` holds a function, TypeScript checks the literal's\n// excess properties against this context alone, so an option missing here\n// (`access`, say) was reported as unknown.\ninterface CollectionContext<Row, Entity, Projections, Item, Index> {\n readonly describe?: string | undefined;\n readonly scope: NoInfer<ViaScope | ScopeColumnOf<Row>>;\n readonly item: Item;\n readonly order: NoInfer<OrderBy<ColumnOf<Row>>>;\n readonly where?: NoInfer<{ readonly [Column in ColumnOf<Row>]?: unknown }>;\n readonly limit?: number | undefined;\n readonly maxLimit?: number | undefined;\n readonly access?: NoInfer<AccessLevel> | undefined;\n readonly index?: NoInfer<\n readonly (IndexField<ProjectionRow<Entity, Projections, Item>> & string)[]\n >;\n readonly views?: NoInfer<{\n readonly [view: string]: ViewPredicate<\n IndexRow<ProjectionRow<Entity, Projections, Item>, IndexedFields<Index>>\n >;\n }>;\n}\n\n/** The payload keys a channel requirement may name: those holding a string. */\ntype PayloadKeyOf<Parsed> = [Parsed] extends [never]\n ? string\n : {\n [Key in keyof Parsed]-?: NonNullable<Parsed[Key]> extends string ? Key : never;\n }[keyof Parsed] &\n string;\n\ntype SelectorOf<Parsed> = PayloadKeyOf<Parsed> | ((payload: Parsed) => string | null | undefined);\n\n/** An app room's name, a function of the parsed payload that returns one, or `{ prefix }`. */\ntype RoomOf<Parsed> =\n | string\n | ((payload: Parsed) => string | null | undefined)\n | { readonly prefix: string };\n\n// One form at a time: the keys of the other forms are absent.\ninterface ChannelContext<Payload> {\n readonly payload: Payload;\n readonly requires?: NoInfer<\n | {\n readonly entity: SelectorOf<SchemaOutput<Payload>>;\n readonly collection?: undefined;\n readonly scope?: undefined;\n readonly room?: undefined;\n }\n | {\n readonly collection: string;\n readonly scope: SelectorOf<SchemaOutput<Payload>>;\n readonly entity?: undefined;\n readonly room?: undefined;\n }\n | {\n readonly room: RoomOf<SchemaOutput<Payload>>;\n readonly entity?: undefined;\n readonly collection?: undefined;\n readonly scope?: undefined;\n }\n >;\n}\n\ntype DefinitionContext<Entity, Projections, Items, Indexes, Payloads> = {\n readonly entity?: Entity;\n readonly projections?: Projections;\n readonly fields?: NoInfer<{\n readonly [Field in Exclude<keyof SchemaOutput<Entity>, \"id\">]?: AccessLevel;\n }>;\n readonly collections?: {\n readonly [Name in keyof Items]: CollectionContext<\n SchemaOutput<Entity>,\n Entity,\n Projections,\n Items[Name],\n Name extends keyof Indexes ? Indexes[Name] : undefined\n >;\n } & { readonly [Name in keyof Indexes]: { readonly index?: Indexes[Name] } };\n readonly channels?: { readonly [Name in keyof Payloads]: ChannelContext<Payloads[Name]> };\n};\n\n// ---------------------------------------------------------------------------\n// Definition checks: rules a structural type cannot state. A broken rule turns\n// the offending member's type into a message, which the compiler prints. A\n// message replaces a whole object (a collection, the fields map) rather than\n// one literal inside it: TypeScript would reduce two conflicting literals to\n// `never` and print that instead.\n// ---------------------------------------------------------------------------\n\n/**\n * Member names the protocol and the client proxy reserve, besides any name\n * starting with `$`: `useEntity`, `useEntities` and `admin` sit beside a\n * service's methods and collections on `qd.<service>`, and `then` would make\n * a service's caller look like a promise to `await`.\n */\nexport type ReservedMethodName =\n | \"subscribe\"\n | \"unsubscribe\"\n | \"call\"\n | \"useEntity\"\n | \"useEntities\"\n | \"admin\"\n | \"then\";\n\ntype Problem<Text extends string> = `defineContract: ${Text}`;\n\ntype IsReserved<Name> = Name extends ReservedMethodName | `$${string}` ? true : false;\n\ntype HasEntity<Def> = Def extends { readonly entity: object } ? true : false;\n\ntype DefinedRow<Def> = Def extends { readonly entity: infer Entity } ? SchemaOutput<Entity> : never;\n\ntype MethodsIn<Def> = MemberOf<Def, \"methods\", Empty>;\ntype CollectionsIn<Def> = MemberOf<Def, \"collections\", Empty>;\ntype ProjectionsIn<Def> = MemberOf<Def, \"projections\", Empty>;\ntype FieldsIn<Def> = MemberOf<Def, \"fields\", Empty>;\n\ntype ProjectionNameIn<Def> =\n | (HasEntity<Def> extends true ? \"entity\" : never)\n | (keyof ProjectionsIn<Def> & string);\n\ntype CheckKeys<Value, Allowed, Owner extends string> = {\n readonly [Key in keyof Value]: Key extends Allowed\n ? unknown\n : Problem<`\"${Key & string}\" is not a ${Owner} option`>;\n};\n\ninterface MethodCheck<Def> {\n readonly output: StandardSchemaV1 | ProjectionRef<ProjectionNameIn<Def> & string>;\n readonly watch?:\n | { readonly collection: keyof CollectionsIn<Def> & string }\n | ServiceWatch\n | undefined;\n}\n\ntype CheckMethods<Def> = {\n readonly [Name in keyof MethodsIn<Def>]: IsReserved<Name> extends true\n ? Problem<`\"${Name & string}\" is a reserved method name`>\n : MethodCheck<Def>;\n};\n\ntype Quoted<Names> = `\"${Names & string}\"`;\n\ntype CollectionProblem<Def, Name, Collection> =\n IsReserved<Name> extends true\n ? `\"${Name & string}\" is a reserved name`\n : Name extends keyof MethodsIn<Def>\n ? `collection \"${Name & string}\" has the same name as a method`\n : [Exclude<keyof Collection, keyof CollectionDef>] extends [never]\n ? Collection extends { readonly item: ProjectionNameIn<Def> }\n ? never\n : `collection \"${Name & string}\": item is not \"entity\" or a key of projections`\n : `collection \"${Name & string}\" has no option ${Quoted<Exclude<keyof Collection, keyof CollectionDef>>}`;\n\ntype MismatchedColumns<Row, Where> = {\n [Column in keyof Where]: Column extends keyof Row\n ? Where[Column] extends Row[Column]\n ? never\n : Column\n : Column;\n}[keyof Where];\n\ntype CheckWhere<Def, Collection> = Collection extends { readonly where: infer Where }\n ? [MismatchedColumns<DefinedRow<Def>, Where>] extends [never]\n ? unknown\n : {\n readonly where: Problem<`where: ${Quoted<MismatchedColumns<DefinedRow<Def>, Where>>} is not a field of the entity, or the value does not match its type`>;\n }\n : unknown;\n\ntype CheckViews<Collection> = Collection extends { readonly views: object }\n ? Collection extends { readonly index: readonly string[] }\n ? unknown\n : { readonly views: Problem<\"views read index rows, so the collection needs an index\"> }\n : unknown;\n\ntype CheckCollection<Def, Name, Collection> =\n HasEntity<Def> extends true\n ? [CollectionProblem<Def, Name, Collection>] extends [never]\n ? CheckWhere<Def, Collection> & CheckViews<Collection>\n : Problem<CollectionProblem<Def, Name, Collection>>\n : Problem<\"collections need an entity\">;\n\ntype CheckCollections<Def> = {\n readonly [Name in keyof CollectionsIn<Def>]: CheckCollection<Def, Name, CollectionsIn<Def>[Name]>;\n};\n\ntype CheckProjections<Def> = {\n readonly [Name in keyof ProjectionsIn<Def>]: HasEntity<Def> extends true\n ? Name extends \"entity\"\n ? Problem<`\"entity\" is implicit; give this projection another name`>\n : unknown\n : Problem<\"projections need an entity\">;\n};\n\ntype UnknownFields<Def> = Exclude<keyof FieldsIn<Def>, Exclude<keyof DefinedRow<Def>, \"id\">>;\n\ntype CheckFields<Def> = [keyof FieldsIn<Def>] extends [never]\n ? unknown\n : HasEntity<Def> extends true\n ? [UnknownFields<Def>] extends [never]\n ? unknown\n : Problem<`fields: ${Quoted<UnknownFields<Def>>} is not a field of the entity, or is \"id\", which every subscriber receives`>\n : Problem<\"fields need an entity\">;\n\ntype StreamsIn<Def> = MemberOf<Def, \"streams\", Empty>;\ntype ChannelsIn<Def> = MemberOf<Def, \"channels\", Empty>;\ntype EventsIn<Def> = MemberOf<Def, \"events\", Empty>;\n\n/**\n * Why a stream, channel or event cannot take `Name`: a reserved name, or one\n * a method, a collection or an `Earlier` realtime member took (they all sit\n * on `qd.<service>.<name>`).\n */\ntype RealtimeNameProblem<Def, Kind extends string, Name, Earlier> =\n IsReserved<Name> extends true\n ? `${Kind} \"${Name & string}\" uses a reserved name`\n : Name extends keyof MethodsIn<Def>\n ? `${Kind} \"${Name & string}\" has the same name as a method`\n : Name extends keyof CollectionsIn<Def>\n ? `${Kind} \"${Name & string}\" has the same name as a collection`\n : Name extends Earlier\n ? `${Kind} \"${Name & string}\" has the same name as another stream, channel or event`\n : never;\n\ntype CheckRealtimeNames<Def, Members, Kind extends string, Earlier> = {\n readonly [Name in keyof Members]: [RealtimeNameProblem<Def, Kind, Name, Earlier>] extends [never]\n ? unknown\n : Problem<RealtimeNameProblem<Def, Kind, Name, Earlier>>;\n};\n\n/** The keys of a channel's parsed payload, when its schema's output is known. */\ntype PayloadKeys<Channel> = Channel extends { readonly payload: infer Payload }\n ? [SchemaOutput<Payload>] extends [never]\n ? never\n : keyof SchemaOutput<Payload> & string\n : never;\n\n/**\n * Why a literal `requires.room` names no app room: a reserved name, or a key\n * of the payload (a string there is the room itself, not a payload key as in\n * the other forms, so naming a key is almost always meant as\n * `(payload) => payload.key`).\n */\ntype RoomProblem<Name, Room, Channel> = Room extends { readonly prefix: infer Prefix }\n ? Prefix extends `${\"qd:\" | \"user:\"}${string}`\n ? `channel \"${Name & string}\": requires.room's prefix \"${Prefix & string}\" names no app room: names starting with \"qd:\" or \"user:\" are the framework's own rooms`\n : never\n : string extends Room\n ? never\n : Room extends `${\"qd:\" | \"user:\"}${string}`\n ? `channel \"${Name & string}\": requires.room \"${Room & string}\" is not an app room: names starting with \"qd:\" or \"user:\" are the framework's own rooms`\n : Room extends PayloadKeys<Channel>\n ? `channel \"${Name & string}\": requires.room is a room's name and \"${Room & string}\" is a key of the payload; to read the room from the payload write (payload) => payload.${Room & string}, and for a fixed room of that name () => \"${Room & string}\"`\n : never;\n\n/** A channel's `requires` names a collection of the contract, a row of an entity it has, or an app room. */\ntype RequiresProblem<Def, Name, Channel> = Channel extends {\n readonly requires: { readonly collection: infer Collection };\n}\n ? Collection extends keyof CollectionsIn<Def>\n ? never\n : `channel \"${Name & string}\" requires unknown collection \"${Collection & string}\"`\n : Channel extends { readonly requires: { readonly entity: unknown } }\n ? HasEntity<Def> extends true\n ? never\n : `channel \"${Name & string}\": requires.entity needs the contract's entity`\n : Channel extends { readonly requires: { readonly room: infer Room } }\n ? RoomProblem<Name, Room, Channel>\n : never;\n\ntype CheckChannels<Def> = CheckRealtimeNames<\n Def,\n ChannelsIn<Def>,\n \"channel\",\n keyof StreamsIn<Def>\n> & {\n readonly [Name in keyof ChannelsIn<Def>]: [\n RequiresProblem<Def, Name, ChannelsIn<Def>[Name]>,\n ] extends [never]\n ? unknown\n : Problem<RequiresProblem<Def, Name, ChannelsIn<Def>[Name]>>;\n};\n\n/**\n * A scoped stream's `access: { room }` is a function of its scope (the 5.1\n * audit's RT-4): a name or `{ prefix }` would let a socket in that room read\n * every scope. As `IsScopedStream` reads it, a scope other than `\"global\"`\n * makes a stream scoped.\n */\ntype StreamRoomProblem<Name, Stream> = Stream extends {\n readonly scope: infer Scope extends string;\n readonly access: { readonly room: infer Room };\n}\n ? Scope extends \"global\"\n ? never\n : Room extends (...args: never[]) => unknown\n ? never\n : `stream \"${Name & string}\" is scoped: its access room is a function of the scope, (scope) => room; a name or { prefix } lets a socket in that room read every scope`\n : never;\n\ntype CheckStreams<Def> = CheckRealtimeNames<Def, StreamsIn<Def>, \"stream\", never> & {\n readonly [Name in keyof StreamsIn<Def>]: [StreamRoomProblem<Name, StreamsIn<Def>[Name]>] extends [\n never,\n ]\n ? unknown\n : Problem<StreamRoomProblem<Name, StreamsIn<Def>[Name]>>;\n};\n\ntype DefinitionChecks<Def> = CheckKeys<Def, keyof ContractDefinition, \"contract\"> & {\n readonly methods?: CheckMethods<Def>;\n readonly collections?: CheckCollections<Def>;\n readonly projections?: CheckProjections<Def>;\n readonly fields?: CheckFields<Def>;\n readonly streams?: CheckStreams<Def>;\n readonly channels?: CheckChannels<Def>;\n readonly events?: CheckRealtimeNames<\n Def,\n EventsIn<Def>,\n \"event\",\n keyof StreamsIn<Def> | keyof ChannelsIn<Def>\n >;\n};\n\n/**\n * Defines the contract of one service: its entity, projections, field tiers,\n * methods, collections, streams, channels and events.\n *\n * The rules are checked by type, so a mistake fails to compile where it is\n * written, and again when the contract is defined, so JavaScript callers and\n * casts get an error too. A Standard Schema does not expose its keys, so some\n * rules can only be checked by type: that `fields`, `scope`, `order`, `where`\n * and `index` name real fields, and that a view reads only index fields.\n *\n * The type parameters after `Def` only exist so TypeScript can type `views`\n * predicates and channel `requires` functions; never pass them.\n *\n * @example\n * export const task = defineContract(\"taskService\", {\n * entity: taskSchema,\n * projections: { card: taskCardSchema },\n * fields: { internalNotes: \"Admin\" },\n * methods: {\n * get: query({ input: z.object({ id: z.string() }), output: \"entity\" }),\n * rename: mutation({ input: renameSchema, output: \"entity\" }),\n * },\n * collections: {\n * byProject: {\n * scope: \"projectId\",\n * item: \"card\",\n * order: [[\"ordinal\", \"asc\"], [\"id\", \"asc\"]],\n * index: [\"status\", \"assigneeId\"],\n * views: { mine: (row, who) => row.assigneeId === who.userId },\n * },\n * },\n * });\n */\nexport function defineContract<\n const Name extends string,\n const Def extends ContractDefinition,\n Entity extends RowSchema = never,\n Projections = Empty,\n Items = Empty,\n Indexes = Empty,\n Payloads = Empty,\n>(\n name: Name,\n def: Def &\n DefinitionContext<Entity, Projections, Items, Indexes, Payloads> &\n NoInfer<DefinitionChecks<Def>>,\n): Contract<Name, Def> {\n return assembleContract(name, def) as unknown as Contract<Name, Def>;\n}\n"],"mappings":"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","names":["isRecord","quote","isName"]}
|
|
1
|
+
{"version":3,"sources":["../src/contract/validateRealtime.ts","../src/contract/validateContract.ts","../src/contract/defineContract.ts"],"sourcesContent":["// Definition-time checks of a contract's streams, channels and events (RFC\n// 0003 section 12.5), for `validateContract.ts`. The types catch the same\n// mistakes at compile time; these catch them for JavaScript callers and casts.\n// Every member name is checked against the names taken before it: methods,\n// collections, streams, channels and events share `qd.<service>.<name>`.\n\nimport { ACCESS_LEVELS, isAccessLevel } from \"./access\";\nimport { reservedRoomPrefix, socketIdShaped } from \"./names\";\nimport type { ChannelDef, EventDef, StreamDef } from \"./realtime\";\nimport { isScopedStream, STREAM_MAX_SEED } from \"./realtime\";\nimport { isStandardSchema } from \"./standardSchema\";\n\ntype Fail = (message: string) => never;\n\ntype UnknownRecord = Readonly<Record<string, unknown>>;\n\n/** The member names taken so far, and by what kind of member. */\nexport type TakenNames = Map<string, string>;\n\n/** What the realtime members are checked against. */\nexport interface RealtimeScope {\n readonly hasEntity: boolean;\n readonly collections: ReadonlySet<string>;\n readonly taken: TakenNames;\n readonly reserved: ReadonlySet<string>;\n}\n\nconst STREAM_KEYS: ReadonlySet<string> = new Set([\n \"item\",\n \"scope\",\n \"seed\",\n \"volatile\",\n \"access\",\n \"serve\",\n \"describe\",\n]);\nconst CHANNEL_KEYS: ReadonlySet<string> = new Set([\n \"payload\",\n \"ratePerSecond\",\n \"burst\",\n \"requires\",\n \"serve\",\n \"describe\",\n]);\nconst EVENT_KEYS: ReadonlySet<string> = new Set([\"payload\", \"describe\"]);\n\n/** The longest app room name `ctx.rooms.join` takes, so the longest prefix one can start with. */\nconst MAX_ROOM_LENGTH = 256;\n\nfunction isRecord(value: unknown): value is UnknownRecord {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction isName(value: unknown): value is string {\n return typeof value === \"string\" && value.length > 0;\n}\n\nfunction quote(names: Iterable<string>): string {\n return [...names].map((name) => `\"${name}\"`).join(\", \");\n}\n\n/** The members of an optional map: absent is empty, anything else must be a plain object. */\nfunction entriesOf(value: unknown, label: string, fail: Fail): [string, unknown][] {\n if (value === undefined) {\n return [];\n }\n if (!isRecord(value)) {\n fail(`${label} must be an object`);\n }\n return Object.entries(value);\n}\n\nfunction checkName(kind: string, name: string, scope: RealtimeScope, fail: Fail): void {\n if (scope.reserved.has(name) || name.startsWith(\"$\")) {\n fail(\n `${kind} \"${name}\" uses a reserved name; ${quote(scope.reserved)} and names starting with \"$\" are reserved`,\n );\n }\n const holder = scope.taken.get(name);\n if (holder !== undefined) {\n fail(\n `${kind} \"${name}\" has the same name as a ${holder}; the client exposes both as qd.<service>.${name}`,\n );\n }\n scope.taken.set(name, kind);\n}\n\nfunction checkMember(\n kind: string,\n name: string,\n value: unknown,\n schemaKey: \"item\" | \"payload\",\n keys: ReadonlySet<string>,\n fail: Fail,\n): UnknownRecord {\n if (!isRecord(value) || !isStandardSchema(value[schemaKey])) {\n fail(`${kind} \"${name}\" must be { ${schemaKey}: <Standard Schema>, ... }`);\n }\n for (const key of Object.keys(value)) {\n if (!keys.has(key)) {\n fail(`${kind} \"${name}\" has an unknown option \"${key}\"; the options are ${quote(keys)}`);\n }\n }\n if (value.describe !== undefined && !isName(value.describe)) {\n fail(`${kind} \"${name}\": describe must be a non-empty string`);\n }\n return value;\n}\n\n/** Why a literal room of the shape of a socket id names no app room (`socketIdShaped`). */\nfunction socketIdProblem(room: string): string {\n return `room \"${room}\" has the shape of a Socket.IO socket id (20 letters, digits, \"_\" or \"-\"), which ctx.rooms.join refuses: no socket is in it as an app room`;\n}\n\n/** Why `access: { room }` names no app room a subscriber could be in, or `undefined`. */\nfunction streamRoomProblem(access: UnknownRecord, scoped: boolean): string | undefined {\n const { room } = access;\n if (Object.keys(access).length !== 1) {\n return \"a room form is { room } and nothing else\";\n }\n if (typeof room === \"function\") {\n return scoped ? undefined : \"a room computed from the scope needs a scoped stream\";\n }\n if (scoped) {\n return \"a room for a scoped stream is a function of its scope, (scope) => room: a name or { prefix } admits a socket in that room to every scope\";\n }\n const name = isRecord(room) && Object.keys(room).length === 1 ? room.prefix : room;\n if (!isName(name) || name.length > MAX_ROOM_LENGTH) {\n return `room must be an app room's name, { prefix } or a function of the scope, of 1 to ${MAX_ROOM_LENGTH} characters`;\n }\n const reserved = reservedRoomPrefix(name);\n if (reserved !== undefined) {\n return `room \"${name}\" is no app room: names starting with \"${reserved}\" are the framework's own rooms`;\n }\n return typeof room === \"string\" && socketIdShaped(room) ? socketIdProblem(room) : undefined;\n}\n\n/** Why `access` is not a stream access form, or `undefined` when it is one. */\nfunction streamAccessProblem(access: unknown, scoped: boolean): string | undefined {\n if (access === \"public\" || access === \"authenticated\") {\n return undefined;\n }\n if (isRecord(access) && access.room !== undefined) {\n return streamRoomProblem(access, scoped);\n }\n const levels = isRecord(access)\n ? [\"service\", \"entry\", \"scope\"].filter((key) => access[key] !== undefined)\n : [];\n if (\n !isRecord(access) ||\n levels.length === 0 ||\n !levels.every((key) => isAccessLevel(access[key]))\n ) {\n return `must be \"public\", \"authenticated\", { service }, { entry } or { scope, of }, with levels among ${quote(ACCESS_LEVELS)}`;\n }\n const extra = Object.keys(access).find(\n (key) => ![\"service\", \"entry\", \"scope\", \"of\"].includes(key),\n );\n if (extra !== undefined) {\n return `has an unknown key \"${extra}\"`;\n }\n if (access.scope !== undefined) {\n const of: unknown = access.of;\n return levels.length === 1 && isRecord(of) && isName(of.name)\n ? undefined\n : \"a scope form is { scope, of: contract } and nothing else\";\n }\n return access.of === undefined ? undefined : \"of belongs to scope forms\";\n}\n\nfunction checkStream(name: string, value: unknown, fail: Fail): StreamDef {\n const owner = `stream \"${name}\"`;\n const stream = checkMember(\"stream\", name, value, \"item\", STREAM_KEYS, fail);\n if (name.includes(\":\")) {\n fail(`${owner} may not contain \":\"; it is part of the stream's room name`);\n }\n if (stream.scope !== undefined && !isName(stream.scope)) {\n fail(`${owner}: scope must be \"global\" or a non-empty name for what a scope value is`);\n }\n const { seed } = stream;\n if (\n seed !== undefined &&\n !(Number.isInteger(seed) && (seed as number) >= 0 && (seed as number) <= STREAM_MAX_SEED)\n ) {\n fail(`${owner}: seed must be a whole number from 0 to ${STREAM_MAX_SEED}`);\n }\n if (stream.volatile !== undefined && typeof stream.volatile !== \"boolean\") {\n fail(`${owner}: volatile must be a boolean`);\n }\n if (stream.access !== undefined) {\n const problem = streamAccessProblem(\n stream.access,\n isScopedStream(stream as Pick<StreamDef, \"scope\">),\n );\n if (problem !== undefined) {\n fail(`${owner}: access ${problem}`);\n }\n const access = stream.access as UnknownRecord | string;\n const rowForm = isRecord(access) && (access.entry !== undefined || access.scope !== undefined);\n if (rowForm && !isScopedStream(stream as Pick<StreamDef, \"scope\">)) {\n fail(`${owner}: entry and scope access check the scope's row, so the stream needs a scope`);\n }\n }\n const { access } = stream;\n const roomOfScope = isRecord(access) && typeof access.room === \"function\";\n checkServe(\n owner,\n stream,\n isScopedStream(stream as Pick<StreamDef, \"scope\">) && roomOfScope\n ? undefined\n : \"it has a scope, and access { room: (scope) => room }, the room whose host serves each scope\",\n fail,\n );\n return Object.freeze({ ...stream }) as unknown as StreamDef;\n}\n\n/**\n * Checks `serve`: `\"server\"` or `\"host\"`. A host-served member fails with\n * `needs`, what it lacks, unless that is `undefined`.\n */\nfunction checkServe(\n owner: string,\n member: UnknownRecord,\n needs: string | undefined,\n fail: Fail,\n): void {\n const { serve } = member;\n if (serve !== undefined && serve !== \"server\" && serve !== \"host\") {\n fail(`${owner}: serve must be \"server\" or \"host\"`);\n }\n if (serve === \"host\" && needs !== undefined) {\n fail(`${owner} is served by the room's host (serve: \"host\"): ${needs}`);\n }\n}\n\nfunction isSelector(value: unknown): boolean {\n return isName(value) || typeof value === \"function\";\n}\n\nconst REQUIRES_FORMS = \"requires must be { entity }, { collection, scope } or { room }\";\n\n/** Checks `requires: { room: { prefix } }`: a prefix some app room's name could start with. */\nfunction checkRoomPrefix(owner: string, room: UnknownRecord, fail: Fail): void {\n const { prefix } = room;\n const extra = Object.keys(room).find((key) => key !== \"prefix\");\n if (extra !== undefined || !isName(prefix) || prefix.length > MAX_ROOM_LENGTH) {\n fail(\n `${owner}: requires.room as an object is { prefix }, a string of 1 to ${MAX_ROOM_LENGTH} characters`,\n );\n }\n const reserved = reservedRoomPrefix(prefix);\n if (reserved !== undefined) {\n fail(\n `${owner}: requires.room's prefix \"${prefix}\" names no app room: names starting with \"${reserved}\" are the framework's own rooms, which ctx.rooms.join refuses`,\n );\n }\n}\n\n/**\n * Checks `requires: { room }`: a function of the payload, the name of an\n * app room, which is never empty and never starts with a reserved prefix\n * (`ctx.rooms.join` refuses those, so no socket could ever be in it), or\n * `{ prefix }`, held to the same rule.\n */\nfunction checkRoomRequirement(owner: string, form: UnknownRecord, fail: Fail): void {\n if (form.entity !== undefined || form.collection !== undefined || form.scope !== undefined) {\n fail(`${owner}: ${REQUIRES_FORMS}`);\n }\n const { room } = form;\n if (typeof room === \"function\") {\n return;\n }\n if (isRecord(room)) {\n checkRoomPrefix(owner, room, fail);\n return;\n }\n if (!isName(room)) {\n fail(\n `${owner}: requires.room must be an app room's name, a function of the payload or { prefix }`,\n );\n }\n const prefix = reservedRoomPrefix(room);\n if (prefix !== undefined) {\n fail(\n `${owner}: requires.room \"${room}\" is not an app room: names starting with \"${prefix}\" are the framework's own rooms, which ctx.rooms.join refuses`,\n );\n }\n if (socketIdShaped(room)) {\n fail(`${owner}: requires.${socketIdProblem(room)}`);\n }\n}\n\nfunction checkRequires(owner: string, requires: unknown, scope: RealtimeScope, fail: Fail): void {\n if (requires === undefined) {\n return;\n }\n const form = isRecord(requires) ? requires : {};\n if (form.room !== undefined) {\n checkRoomRequirement(owner, form, fail);\n return;\n }\n if (form.entity !== undefined && form.collection === undefined && form.scope === undefined) {\n if (!isSelector(form.entity)) {\n fail(`${owner}: requires.entity must be a payload key or a function of the payload`);\n }\n if (!scope.hasEntity) {\n fail(`${owner}: requires.entity needs the contract's entity`);\n }\n return;\n }\n if (form.entity !== undefined || !isName(form.collection) || !isSelector(form.scope)) {\n fail(`${owner}: ${REQUIRES_FORMS}`);\n }\n if (!scope.collections.has(form.collection)) {\n fail(\n `${owner}: requires names unknown collection \"${form.collection}\"; the collections are ${quote(scope.collections)}`,\n );\n }\n}\n\nfunction checkChannel(name: string, value: unknown, scope: RealtimeScope, fail: Fail): ChannelDef {\n const owner = `channel \"${name}\"`;\n const channel = checkMember(\"channel\", name, value, \"payload\", CHANNEL_KEYS, fail);\n const positive = (rate: unknown, least: number): boolean =>\n rate === undefined || (typeof rate === \"number\" && Number.isFinite(rate) && rate >= least);\n if (!positive(channel.ratePerSecond, Number.MIN_VALUE)) {\n fail(`${owner}: ratePerSecond must be a number of messages above 0`);\n }\n if (!positive(channel.burst, 1)) {\n fail(`${owner}: burst must be a number of messages, at least 1`);\n }\n checkRequires(owner, channel.requires, scope, fail);\n const { requires } = channel;\n checkServe(\n owner,\n channel,\n isRecord(requires) && requires.room !== undefined\n ? undefined\n : \"it requires { room }, the room whose host handles its messages\",\n fail,\n );\n return Object.freeze({ ...channel }) as unknown as ChannelDef;\n}\n\n/**\n * Checks the `streams`, `channels` and `events` of a contract definition,\n * taking their names in `scope.taken` after the methods and collections, and\n * returns them frozen.\n */\nexport function checkRealtime(\n def: UnknownRecord,\n scope: RealtimeScope,\n fail: Fail,\n): {\n readonly streams: Readonly<Record<string, StreamDef>>;\n readonly channels: Readonly<Record<string, ChannelDef>>;\n readonly events: Readonly<Record<string, EventDef>>;\n} {\n const streams: Record<string, StreamDef> = {};\n for (const [name, value] of entriesOf(def.streams, \"streams\", fail)) {\n checkName(\"stream\", name, scope, fail);\n streams[name] = checkStream(name, value, fail);\n }\n const channels: Record<string, ChannelDef> = {};\n for (const [name, value] of entriesOf(def.channels, \"channels\", fail)) {\n checkName(\"channel\", name, scope, fail);\n channels[name] = checkChannel(name, value, scope, fail);\n }\n const events: Record<string, EventDef> = {};\n for (const [name, value] of entriesOf(def.events, \"events\", fail)) {\n checkName(\"event\", name, scope, fail);\n const event = checkMember(\"event\", name, value, \"payload\", EVENT_KEYS, fail);\n events[name] = Object.freeze({ ...event }) as unknown as EventDef;\n }\n return {\n streams: Object.freeze(streams),\n channels: Object.freeze(channels),\n events: Object.freeze(events),\n };\n}\n","// Definition-time checks for `defineContract`. The types catch the same\n// mistakes at compile time; these catch them for JavaScript callers and casts,\n// and freeze the result so a contract cannot change after it is defined.\n\nimport { ACCESS_LEVELS, type AccessLevel, isAccessLevel } from \"./access\";\nimport {\n type CollectionDef,\n DEFAULT_COLLECTION_LIMIT,\n DEFAULT_COLLECTION_MAX_LIMIT,\n} from \"./collections\";\nimport type { AnyContract, RowSchema } from \"./defineContract\";\nimport type { MethodDef } from \"./methods\";\nimport { isStandardSchema } from \"./standardSchema\";\nimport { checkRealtime, type TakenNames } from \"./validateRealtime\";\n\ntype Fail = (message: string) => never;\n\ntype UnknownRecord = Readonly<Record<string, unknown>>;\n\n// `useEntity`, `useEntities` and `admin` are members the client proxy places\n// beside a service's methods and collections (RFC 0003 sections 11 and 12.4).\n// `then` would make a service's caller look like a promise: `await` and\n// `Promise.resolve` would call it, so the callers answer `undefined` for it.\nconst RESERVED_NAMES: ReadonlySet<string> = new Set([\n \"subscribe\",\n \"unsubscribe\",\n \"call\",\n \"useEntity\",\n \"useEntities\",\n \"admin\",\n \"then\",\n]);\n\nconst DEFINITION_KEYS: ReadonlySet<string> = new Set([\n \"describe\",\n \"entity\",\n \"projections\",\n \"fields\",\n \"methods\",\n \"collections\",\n \"streams\",\n \"channels\",\n \"events\",\n]);\n\nconst METHOD_KEYS: ReadonlySet<string> = new Set([\"kind\", \"input\", \"output\", \"watch\", \"describe\"]);\n\nconst COLLECTION_KEYS: ReadonlySet<string> = new Set([\n \"describe\",\n \"scope\",\n \"item\",\n \"order\",\n \"where\",\n \"limit\",\n \"maxLimit\",\n \"index\",\n \"views\",\n \"access\",\n]);\n\nfunction isRecord(value: unknown): value is UnknownRecord {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction quote(names: Iterable<string>): string {\n const list = [...names].map((name) => `\"${name}\"`);\n return list.length === 0 ? \"none\" : list.join(\", \");\n}\n\nfunction checkKeys(\n value: UnknownRecord,\n allowed: ReadonlySet<string>,\n owner: string,\n fail: Fail,\n): void {\n for (const key of Object.keys(value)) {\n if (!allowed.has(key)) {\n fail(`${owner} has an unknown option \"${key}\"; the options are ${quote(allowed)}`);\n }\n }\n}\n\n/** An optional map member: absent is empty, anything else must be a plain object. */\nfunction members(value: unknown, label: string, fail: Fail): UnknownRecord {\n if (value === undefined) {\n return {};\n }\n if (!isRecord(value)) {\n fail(`${label} must be an object`);\n }\n return value;\n}\n\nfunction checkMemberName(kind: \"method\" | \"collection\", name: string, fail: Fail): void {\n if (RESERVED_NAMES.has(name) || name.startsWith(\"$\")) {\n fail(\n `${kind} \"${name}\" uses a reserved name; ${quote(RESERVED_NAMES)} and names starting with \"$\" are reserved`,\n );\n }\n}\n\nfunction checkEntity(entity: unknown, fail: Fail): RowSchema | undefined {\n if (entity !== undefined && !isStandardSchema(entity)) {\n fail(\"entity must be a Standard Schema\");\n }\n return entity as RowSchema | undefined;\n}\n\nfunction checkProjections(\n value: unknown,\n hasEntity: boolean,\n fail: Fail,\n): Record<string, RowSchema> {\n const projections = members(value, \"projections\", fail);\n const checked: Record<string, RowSchema> = {};\n for (const [name, schema] of Object.entries(projections)) {\n if (!hasEntity) {\n fail(`projection \"${name}\" needs an entity; declare the contract's entity first`);\n }\n if (name === \"entity\") {\n fail(`a projection is named \"entity\", which is the implicit full-row projection`);\n }\n if (!isStandardSchema(schema)) {\n fail(`projection \"${name}\" must be a Standard Schema`);\n }\n checked[name] = schema as RowSchema;\n }\n return checked;\n}\n\nfunction checkFields(value: unknown, hasEntity: boolean, fail: Fail): Record<string, AccessLevel> {\n const fields = members(value, \"fields\", fail);\n const checked: Record<string, AccessLevel> = {};\n for (const [field, level] of Object.entries(fields)) {\n if (!hasEntity) {\n fail(`field \"${field}\" needs an entity; declare the contract's entity first`);\n }\n if (field === \"id\") {\n fail(`fields cannot restrict \"id\"; every subscriber receives it`);\n }\n if (!isAccessLevel(level)) {\n fail(`field \"${field}\" must map to one of ${quote(ACCESS_LEVELS)}`);\n }\n checked[field] = level;\n }\n return checked;\n}\n\n/** The projection a method output names, or undefined when the output is not a projection. */\nfunction projectionOf(output: unknown): unknown {\n if (typeof output === \"string\") {\n return output;\n }\n if (isRecord(output) && (output.kind === \"nullable\" || output.kind === \"list\")) {\n return output.projection;\n }\n return undefined;\n}\n\ninterface MethodScope {\n readonly projections: ReadonlySet<string>;\n readonly collections: ReadonlySet<string>;\n}\n\nfunction checkOutput(name: string, output: unknown, scope: MethodScope, fail: Fail): void {\n if (isStandardSchema(output)) {\n return;\n }\n const projection = projectionOf(output);\n if (typeof projection !== \"string\") {\n fail(\n `method \"${name}\": output must be a Standard Schema, a projection name, nullable(...) or listOf(...)`,\n );\n }\n if (!scope.projections.has(projection)) {\n fail(\n `method \"${name}\" returns unknown projection \"${projection}\"; the projections are ${quote(scope.projections)}`,\n );\n }\n}\n\n/**\n * `watch: { service: [models] }`: a non-empty list of distinct model names\n * and nothing else. Whether they are the service's models (its `model` and\n * `writes`) only `defineService` knows.\n */\nfunction checkServiceModels(name: string, watch: UnknownRecord, fail: Fail): void {\n const models: unknown = watch.service;\n const named =\n Array.isArray(models) &&\n models.length > 0 &&\n models.every((model) => typeof model === \"string\" && model !== \"\") &&\n new Set(models).size === models.length;\n if (!named || Object.keys(watch).length !== 1) {\n fail(\n `method \"${name}\": watch { service } lists the models of the service it watches, by the client's model name: { service: [\"gameScore\"] }`,\n );\n }\n}\n\nfunction checkWatch(name: string, method: UnknownRecord, scope: MethodScope, fail: Fail): void {\n const { watch } = method;\n if (watch === undefined) {\n return;\n }\n if (method.kind !== \"query\") {\n fail(`method \"${name}\" is a mutation; only a query can watch`);\n }\n if (watch === \"service\") {\n return;\n }\n if (isRecord(watch) && Object.hasOwn(watch, \"service\")) {\n checkServiceModels(name, watch, fail);\n return;\n }\n if (!isRecord(watch) || typeof watch.scope !== \"function\") {\n fail(\n `method \"${name}\": watch must be \"service\", { service: [models] }, or { collection, scope } with a scope function`,\n );\n }\n if (typeof watch.collection !== \"string\" || !scope.collections.has(watch.collection)) {\n fail(\n `method \"${name}\" watches unknown collection \"${String(watch.collection)}\"; the collections are ${quote(scope.collections)}`,\n );\n }\n}\n\nfunction checkMethod(name: string, method: unknown, scope: MethodScope, fail: Fail): MethodDef {\n checkMemberName(\"method\", name, fail);\n if (!isRecord(method) || (method.kind !== \"query\" && method.kind !== \"mutation\")) {\n fail(`method \"${name}\" must be declared with query(...) or mutation(...)`);\n }\n checkKeys(method, METHOD_KEYS, `method \"${name}\"`, fail);\n if (!isStandardSchema(method.input)) {\n fail(`method \"${name}\": input must be a Standard Schema`);\n }\n checkOutput(name, method.output, scope, fail);\n checkWatch(name, method, scope, fail);\n if (method.describe !== undefined && !isName(method.describe)) {\n fail(`method \"${name}\": describe must be a non-empty string`);\n }\n return method as unknown as MethodDef;\n}\n\nfunction checkMethods(value: unknown, scope: MethodScope, fail: Fail): Record<string, MethodDef> {\n const checked: Record<string, MethodDef> = {};\n for (const [name, method] of Object.entries(members(value, \"methods\", fail))) {\n checked[name] = checkMethod(name, method, scope, fail);\n }\n return checked;\n}\n\nfunction isName(value: unknown): value is string {\n return typeof value === \"string\" && value.length > 0;\n}\n\nfunction checkScope(owner: string, scope: unknown, fail: Fail): void {\n if (isName(scope)) {\n return;\n }\n const isVia =\n isRecord(scope) &&\n scope.kind === \"via\" &&\n isName(scope.model) &&\n isName(scope.entry) &&\n isName(scope.scope);\n if (!isVia) {\n fail(`${owner}: scope must be a column name or via({ model, entry, scope })`);\n }\n const { refreshEntry } = scope as { readonly refreshEntry?: unknown };\n if (refreshEntry !== undefined && typeof refreshEntry !== \"boolean\") {\n fail(`${owner}: via's refreshEntry must be true or false`);\n }\n}\n\nfunction isSortColumn(entry: unknown): entry is readonly [string, string] {\n return (\n Array.isArray(entry) &&\n entry.length === 2 &&\n isName(entry[0]) &&\n (entry[1] === \"asc\" || entry[1] === \"desc\")\n );\n}\n\nfunction checkOrder(owner: string, order: unknown, fail: Fail): void {\n if (!Array.isArray(order) || order.length === 0 || !order.every(isSortColumn)) {\n fail(`${owner}: order must be a list of [column, \"asc\" | \"desc\"] pairs ending with \"id\"`);\n }\n const last: unknown = order.at(-1);\n if (!isSortColumn(last) || last[0] !== \"id\") {\n fail(`${owner}: order must end with \"id\" so every row has a unique cursor position`);\n }\n}\n\nfunction checkWhere(owner: string, where: unknown, fail: Fail): void {\n if (where === undefined) {\n return;\n }\n const scalar = (value: unknown): boolean =>\n value === null || [\"string\", \"number\", \"boolean\"].includes(typeof value);\n if (!isRecord(where) || !Object.values(where).every(scalar)) {\n fail(`${owner}: where must map columns to strings, numbers, booleans or null`);\n }\n}\n\nfunction checkLimits(owner: string, collection: UnknownRecord, fail: Fail): void {\n const positive = (value: unknown): boolean =>\n value === undefined || (Number.isInteger(value) && (value as number) > 0);\n if (!positive(collection.limit) || !positive(collection.maxLimit)) {\n fail(`${owner}: limit and maxLimit must be positive integers`);\n }\n const limit = (collection.limit as number | undefined) ?? DEFAULT_COLLECTION_LIMIT;\n const maxLimit = (collection.maxLimit as number | undefined) ?? DEFAULT_COLLECTION_MAX_LIMIT;\n if (limit > maxLimit) {\n fail(`${owner}: limit (${limit}) is larger than maxLimit (${maxLimit})`);\n }\n}\n\nfunction checkIndexAndViews(owner: string, collection: UnknownRecord, fail: Fail): void {\n const { index, views } = collection;\n if (index !== undefined && (!Array.isArray(index) || !index.every(isName))) {\n fail(`${owner}: index must be a list of item field names`);\n }\n if (views === undefined) {\n return;\n }\n if (index === undefined) {\n fail(`${owner} declares views but no index; views read index rows`);\n }\n if (!isRecord(views) || !Object.values(views).every((view) => typeof view === \"function\")) {\n fail(`${owner}: views must map names to predicate functions`);\n }\n}\n\ninterface CollectionScope {\n readonly hasEntity: boolean;\n readonly projections: ReadonlySet<string>;\n readonly methods: ReadonlySet<string>;\n}\n\nfunction checkCollection(\n name: string,\n value: unknown,\n scope: CollectionScope,\n fail: Fail,\n): CollectionDef {\n const owner = `collection \"${name}\"`;\n checkMemberName(\"collection\", name, fail);\n if (name.includes(\":\")) {\n fail(\n `${owner} may not contain \":\"; a change topic is {collection}:{scope}, split at its first colon`,\n );\n }\n if (scope.methods.has(name)) {\n fail(`${owner} has the same name as a method; the client exposes both as qd.<service>.${name}`);\n }\n if (!scope.hasEntity) {\n fail(`${owner} needs an entity; declare the contract's entity first`);\n }\n if (!isRecord(value)) {\n fail(`${owner} must be an object`);\n }\n checkKeys(value, COLLECTION_KEYS, owner, fail);\n checkScope(owner, value.scope, fail);\n if (typeof value.item !== \"string\" || !scope.projections.has(value.item)) {\n fail(\n `${owner}: item \"${String(value.item)}\" is not a projection; the projections are ${quote(scope.projections)}`,\n );\n }\n checkOrder(owner, value.order, fail);\n checkWhere(owner, value.where, fail);\n checkLimits(owner, value, fail);\n checkIndexAndViews(owner, value, fail);\n if (value.access !== undefined && !isAccessLevel(value.access)) {\n fail(`${owner}: access must be one of ${quote(ACCESS_LEVELS)}`);\n }\n if (value.describe !== undefined && !isName(value.describe)) {\n fail(`${owner}: describe must be a non-empty string`);\n }\n return Object.freeze({ ...value }) as unknown as CollectionDef;\n}\n\nfunction checkCollections(\n value: unknown,\n scope: CollectionScope,\n fail: Fail,\n): Record<string, CollectionDef> {\n const checked: Record<string, CollectionDef> = {};\n for (const [name, collection] of Object.entries(members(value, \"collections\", fail))) {\n checked[name] = checkCollection(name, collection, scope, fail);\n }\n return checked;\n}\n\n/** The names methods and collections took: streams, channels and events may not take them too. */\nfunction takenNames(\n methods: Readonly<Record<string, MethodDef>>,\n collections: Readonly<Record<string, CollectionDef>>,\n): TakenNames {\n const taken: TakenNames = new Map();\n for (const name of Object.keys(methods)) {\n taken.set(name, \"method\");\n }\n for (const name of Object.keys(collections)) {\n taken.set(name, \"collection\");\n }\n return taken;\n}\n\n/** Checks a contract definition and returns the frozen contract. */\nexport function assembleContract(name: unknown, def: unknown): AnyContract {\n if (!isName(name)) {\n throw new TypeError(\"defineContract: the service name must be a non-empty string\");\n }\n if (/[:@]/u.test(name)) {\n throw new TypeError(\n `defineContract(\"${name}\"): the service name may not contain \":\" or \"@\": it is part of every room name of the service (qd:e:{service}:{id}@{level}, qd:c:{service}:{collection}:{scope}), which must split one way only`,\n );\n }\n const fail: Fail = (message) => {\n throw new TypeError(`defineContract(\"${name}\"): ${message}`);\n };\n if (!isRecord(def)) {\n fail(\"the definition must be an object\");\n }\n checkKeys(def, DEFINITION_KEYS, \"the contract\", fail);\n if (def.describe !== undefined && !isName(def.describe)) {\n fail(\"describe must be a non-empty string\");\n }\n const entity = checkEntity(def.entity, fail);\n const hasEntity = entity !== undefined;\n const projections = checkProjections(def.projections, hasEntity, fail);\n const projectionNames = new Set(Object.keys(projections));\n if (hasEntity) {\n projectionNames.add(\"entity\");\n }\n const collectionNames = new Set(Object.keys(members(def.collections, \"collections\", fail)));\n const methods = checkMethods(\n def.methods,\n { projections: projectionNames, collections: collectionNames },\n fail,\n );\n const collections = checkCollections(\n def.collections,\n { hasEntity, projections: projectionNames, methods: new Set(Object.keys(methods)) },\n fail,\n );\n const realtime = checkRealtime(\n def,\n {\n hasEntity,\n collections: collectionNames,\n taken: takenNames(methods, collections),\n reserved: RESERVED_NAMES,\n },\n fail,\n );\n return Object.freeze({\n name,\n ...(def.describe === undefined ? {} : { describe: def.describe as string }),\n entity,\n projections: Object.freeze(projections),\n fields: Object.freeze(checkFields(def.fields, hasEntity, fail)),\n methods: Object.freeze(methods),\n collections: Object.freeze(collections),\n ...realtime,\n });\n}\n","// `defineContract`: one schema source per service (RFC 0003 section 2). A\n// contract is plain data plus schemas, so browser code imports it without any\n// server code. Every server and client type is derived from it: see\n// `infer.ts`. In 4.1 the same information was spread over a hand-written\n// method map, an optional Zod schema per method, seven generics on\n// `BaseService` (4.1 `src/server/BaseService.ts:68-80`) and room-name\n// helpers.\n\nimport type { AccessLevel } from \"./access\";\nimport type { CollectionDef, OrderBy, ViaScope, ViewPredicate } from \"./collections\";\nimport type { MethodDef, ProjectionRef, ServiceWatch } from \"./methods\";\nimport type { ChannelDef, EventDef, StreamDef } from \"./realtime\";\nimport type { InferOutput, StandardSchemaV1 } from \"./standardSchema\";\nimport { assembleContract } from \"./validateContract\";\n\nexport type { ChannelDef, EventDef, StreamDef };\n\n/** A schema whose output is a row: an object with `id: string`. */\nexport type RowSchema = StandardSchemaV1<unknown, { readonly id: string }>;\n\n/**\n * A channel as `defineContract` takes it. `requires` is typed by the\n * channel's payload through the definition's context, so a function there\n * gets the parsed payload as its parameter type; the contract stores it as a\n * `ChannelDef`.\n */\nexport interface ChannelDefinition extends Omit<ChannelDef, \"requires\"> {\n readonly requires?: unknown;\n}\n\n/** The second argument of {@link defineContract}. */\nexport interface ContractDefinition {\n /**\n * What the service is for, in a sentence or two. The generated API docs\n * lead the service's page with it and list it in their index.\n */\n readonly describe?: string;\n /**\n * The full row; its output must contain `id: string`. Omit it for a service\n * without a model, which then has no projections, fields or collections.\n *\n * Typed `unknown` here on purpose: `defineContract` checks it through its\n * own `Entity` parameter. Constraining it here as well makes TypeScript\n * reject Zod 3 schemas whenever a collection declares `views`.\n */\n readonly entity?: unknown;\n /** Named lean shapes of the entity. `\"entity\"` itself is implicit. */\n readonly projections?: { readonly [name: string]: RowSchema };\n /** The minimum level a subscriber needs to receive each entity field. */\n readonly fields?: { readonly [field: string]: AccessLevel };\n /** Every method is a `query(...)` or a `mutation(...)`. */\n readonly methods?: { readonly [name: string]: MethodDef };\n /** Live lists of the entity, grouped by a scope value. */\n readonly collections?: { readonly [name: string]: CollectionDef };\n readonly streams?: { readonly [name: string]: StreamDef };\n readonly channels?: { readonly [name: string]: ChannelDefinition };\n readonly events?: { readonly [name: string]: EventDef };\n}\n\ntype Empty = Record<never, never>;\ntype MemberOf<Def, Key extends string, Absent> = Def extends { readonly [K in Key]: infer Value }\n ? Value\n : Absent;\n\n/**\n * A defined contract: the definition with every member present (an absent\n * one is `undefined` for `entity` and `{}` otherwise) plus the service name.\n */\nexport interface Contract<\n Name extends string = string,\n Def extends ContractDefinition = ContractDefinition,\n> {\n /** The service name, unchanged on the wire and in stored grants. */\n readonly name: Name;\n /** What the service is for; absent when the definition has none. */\n readonly describe?: string;\n readonly entity: MemberOf<Def, \"entity\", undefined>;\n readonly projections: MemberOf<Def, \"projections\", Empty>;\n readonly fields: MemberOf<Def, \"fields\", Empty>;\n readonly methods: MemberOf<Def, \"methods\", Empty>;\n readonly collections: MemberOf<Def, \"collections\", Empty>;\n readonly streams: MemberOf<Def, \"streams\", Empty>;\n readonly channels: MemberOf<Def, \"channels\", Empty>;\n readonly events: MemberOf<Def, \"events\", Empty>;\n}\n\n/** Any contract. Every contract `defineContract` returns is assignable to it. */\nexport interface AnyContract {\n readonly name: string;\n readonly describe?: string;\n readonly entity: RowSchema | undefined;\n readonly projections: { readonly [name: string]: RowSchema };\n readonly fields: { readonly [field: string]: AccessLevel };\n readonly methods: { readonly [name: string]: MethodDef };\n readonly collections: { readonly [name: string]: CollectionDef };\n readonly streams: { readonly [name: string]: StreamDef };\n readonly channels: { readonly [name: string]: ChannelDef };\n readonly events: { readonly [name: string]: EventDef };\n}\n\n// ---------------------------------------------------------------------------\n// Definition context: the types that check each member against the entity\n// and projections, and give `views` predicates their row type. `Entity`,\n// `Projections`, `Items` and `Indexes` are inferred from the plain-data parts\n// of the definition before TypeScript types the predicates; everything else\n// sits behind `NoInfer` so it checks without steering that inference.\n// ---------------------------------------------------------------------------\n\ntype SchemaOutput<Schema> = Schema extends StandardSchemaV1 ? InferOutput<Schema> : never;\n\ntype ProjectionRow<Entity, Projections, Name> = Name extends \"entity\"\n ? SchemaOutput<Entity>\n : Name extends keyof Projections\n ? SchemaOutput<Projections[Name]>\n : never;\n\n/** Entity columns whose values are strings: the columns a collection can be scoped by. */\ntype StringColumn<Row> = {\n [Column in keyof Row]-?: NonNullable<Row[Column]> extends string ? Column : never;\n}[keyof Row];\n\ntype IndexField<Item> = Exclude<keyof Item, \"id\">;\n\ntype IndexedFields<Index> = Index extends readonly (infer Field)[] ? Field : never;\n\n/** An index row: `id` plus the collection's `index` fields of the item. */\nexport type IndexRow<Item, Fields> = Pick<Item, Extract<keyof Item, \"id\" | Fields>>;\n\n// Without an entity any column name passes here, so the checks below report\n// \"collections need an entity\" instead of a column error. The `& string`\n// makes an error message list the allowed names rather than print the name of\n// the type that computes them.\ntype ColumnOf<Row> = [Row] extends [never] ? string : keyof Row & string;\ntype ScopeColumnOf<Row> = [Row] extends [never] ? string : StringColumn<Row> & string;\n\n// Every option of `CollectionDef` is listed, the plain ones too: when a\n// channel's `requires` holds a function, TypeScript checks the literal's\n// excess properties against this context alone, so an option missing here\n// (`access`, say) was reported as unknown.\ninterface CollectionContext<Row, Entity, Projections, Item, Index> {\n readonly describe?: string | undefined;\n readonly scope: NoInfer<ViaScope | ScopeColumnOf<Row>>;\n readonly item: Item;\n readonly order: NoInfer<OrderBy<ColumnOf<Row>>>;\n readonly where?: NoInfer<{ readonly [Column in ColumnOf<Row>]?: unknown }>;\n readonly limit?: number | undefined;\n readonly maxLimit?: number | undefined;\n readonly access?: NoInfer<AccessLevel> | undefined;\n readonly index?: NoInfer<\n readonly (IndexField<ProjectionRow<Entity, Projections, Item>> & string)[]\n >;\n readonly views?: NoInfer<{\n readonly [view: string]: ViewPredicate<\n IndexRow<ProjectionRow<Entity, Projections, Item>, IndexedFields<Index>>\n >;\n }>;\n}\n\n/** The payload keys a channel requirement may name: those holding a string. */\ntype PayloadKeyOf<Parsed> = [Parsed] extends [never]\n ? string\n : {\n [Key in keyof Parsed]-?: NonNullable<Parsed[Key]> extends string ? Key : never;\n }[keyof Parsed] &\n string;\n\ntype SelectorOf<Parsed> = PayloadKeyOf<Parsed> | ((payload: Parsed) => string | null | undefined);\n\n/** An app room's name, a function of the parsed payload that returns one, or `{ prefix }`. */\ntype RoomOf<Parsed> =\n | string\n | ((payload: Parsed) => string | null | undefined)\n | { readonly prefix: string };\n\n// One form at a time: the keys of the other forms are absent.\ninterface ChannelContext<Payload> {\n readonly payload: Payload;\n readonly requires?: NoInfer<\n | {\n readonly entity: SelectorOf<SchemaOutput<Payload>>;\n readonly collection?: undefined;\n readonly scope?: undefined;\n readonly room?: undefined;\n }\n | {\n readonly collection: string;\n readonly scope: SelectorOf<SchemaOutput<Payload>>;\n readonly entity?: undefined;\n readonly room?: undefined;\n }\n | {\n readonly room: RoomOf<SchemaOutput<Payload>>;\n readonly entity?: undefined;\n readonly collection?: undefined;\n readonly scope?: undefined;\n }\n >;\n}\n\ntype DefinitionContext<Entity, Projections, Items, Indexes, Payloads> = {\n readonly entity?: Entity;\n readonly projections?: Projections;\n readonly fields?: NoInfer<{\n readonly [Field in Exclude<keyof SchemaOutput<Entity>, \"id\">]?: AccessLevel;\n }>;\n readonly collections?: {\n readonly [Name in keyof Items]: CollectionContext<\n SchemaOutput<Entity>,\n Entity,\n Projections,\n Items[Name],\n Name extends keyof Indexes ? Indexes[Name] : undefined\n >;\n } & { readonly [Name in keyof Indexes]: { readonly index?: Indexes[Name] } };\n readonly channels?: { readonly [Name in keyof Payloads]: ChannelContext<Payloads[Name]> };\n};\n\n// ---------------------------------------------------------------------------\n// Definition checks: rules a structural type cannot state. A broken rule turns\n// the offending member's type into a message, which the compiler prints. A\n// message replaces a whole object (a collection, the fields map) rather than\n// one literal inside it: TypeScript would reduce two conflicting literals to\n// `never` and print that instead.\n// ---------------------------------------------------------------------------\n\n/**\n * Member names the protocol and the client proxy reserve, besides any name\n * starting with `$`: `useEntity`, `useEntities` and `admin` sit beside a\n * service's methods and collections on `qd.<service>`, and `then` would make\n * a service's caller look like a promise to `await`.\n */\nexport type ReservedMethodName =\n | \"subscribe\"\n | \"unsubscribe\"\n | \"call\"\n | \"useEntity\"\n | \"useEntities\"\n | \"admin\"\n | \"then\";\n\ntype Problem<Text extends string> = `defineContract: ${Text}`;\n\ntype IsReserved<Name> = Name extends ReservedMethodName | `$${string}` ? true : false;\n\ntype HasEntity<Def> = Def extends { readonly entity: object } ? true : false;\n\ntype DefinedRow<Def> = Def extends { readonly entity: infer Entity } ? SchemaOutput<Entity> : never;\n\ntype MethodsIn<Def> = MemberOf<Def, \"methods\", Empty>;\ntype CollectionsIn<Def> = MemberOf<Def, \"collections\", Empty>;\ntype ProjectionsIn<Def> = MemberOf<Def, \"projections\", Empty>;\ntype FieldsIn<Def> = MemberOf<Def, \"fields\", Empty>;\n\ntype ProjectionNameIn<Def> =\n | (HasEntity<Def> extends true ? \"entity\" : never)\n | (keyof ProjectionsIn<Def> & string);\n\ntype CheckKeys<Value, Allowed, Owner extends string> = {\n readonly [Key in keyof Value]: Key extends Allowed\n ? unknown\n : Problem<`\"${Key & string}\" is not a ${Owner} option`>;\n};\n\ninterface MethodCheck<Def> {\n readonly output: StandardSchemaV1 | ProjectionRef<ProjectionNameIn<Def> & string>;\n readonly watch?:\n | { readonly collection: keyof CollectionsIn<Def> & string }\n | ServiceWatch\n | undefined;\n}\n\ntype CheckMethods<Def> = {\n readonly [Name in keyof MethodsIn<Def>]: IsReserved<Name> extends true\n ? Problem<`\"${Name & string}\" is a reserved method name`>\n : MethodCheck<Def>;\n};\n\ntype Quoted<Names> = `\"${Names & string}\"`;\n\ntype CollectionProblem<Def, Name, Collection> =\n IsReserved<Name> extends true\n ? `\"${Name & string}\" is a reserved name`\n : Name extends keyof MethodsIn<Def>\n ? `collection \"${Name & string}\" has the same name as a method`\n : [Exclude<keyof Collection, keyof CollectionDef>] extends [never]\n ? Collection extends { readonly item: ProjectionNameIn<Def> }\n ? never\n : `collection \"${Name & string}\": item is not \"entity\" or a key of projections`\n : `collection \"${Name & string}\" has no option ${Quoted<Exclude<keyof Collection, keyof CollectionDef>>}`;\n\ntype MismatchedColumns<Row, Where> = {\n [Column in keyof Where]: Column extends keyof Row\n ? Where[Column] extends Row[Column]\n ? never\n : Column\n : Column;\n}[keyof Where];\n\ntype CheckWhere<Def, Collection> = Collection extends { readonly where: infer Where }\n ? [MismatchedColumns<DefinedRow<Def>, Where>] extends [never]\n ? unknown\n : {\n readonly where: Problem<`where: ${Quoted<MismatchedColumns<DefinedRow<Def>, Where>>} is not a field of the entity, or the value does not match its type`>;\n }\n : unknown;\n\ntype CheckViews<Collection> = Collection extends { readonly views: object }\n ? Collection extends { readonly index: readonly string[] }\n ? unknown\n : { readonly views: Problem<\"views read index rows, so the collection needs an index\"> }\n : unknown;\n\ntype CheckCollection<Def, Name, Collection> =\n HasEntity<Def> extends true\n ? [CollectionProblem<Def, Name, Collection>] extends [never]\n ? CheckWhere<Def, Collection> & CheckViews<Collection>\n : Problem<CollectionProblem<Def, Name, Collection>>\n : Problem<\"collections need an entity\">;\n\ntype CheckCollections<Def> = {\n readonly [Name in keyof CollectionsIn<Def>]: CheckCollection<Def, Name, CollectionsIn<Def>[Name]>;\n};\n\ntype CheckProjections<Def> = {\n readonly [Name in keyof ProjectionsIn<Def>]: HasEntity<Def> extends true\n ? Name extends \"entity\"\n ? Problem<`\"entity\" is implicit; give this projection another name`>\n : unknown\n : Problem<\"projections need an entity\">;\n};\n\ntype UnknownFields<Def> = Exclude<keyof FieldsIn<Def>, Exclude<keyof DefinedRow<Def>, \"id\">>;\n\ntype CheckFields<Def> = [keyof FieldsIn<Def>] extends [never]\n ? unknown\n : HasEntity<Def> extends true\n ? [UnknownFields<Def>] extends [never]\n ? unknown\n : Problem<`fields: ${Quoted<UnknownFields<Def>>} is not a field of the entity, or is \"id\", which every subscriber receives`>\n : Problem<\"fields need an entity\">;\n\ntype StreamsIn<Def> = MemberOf<Def, \"streams\", Empty>;\ntype ChannelsIn<Def> = MemberOf<Def, \"channels\", Empty>;\ntype EventsIn<Def> = MemberOf<Def, \"events\", Empty>;\n\n/**\n * Why a stream, channel or event cannot take `Name`: a reserved name, or one\n * a method, a collection or an `Earlier` realtime member took (they all sit\n * on `qd.<service>.<name>`).\n */\ntype RealtimeNameProblem<Def, Kind extends string, Name, Earlier> =\n IsReserved<Name> extends true\n ? `${Kind} \"${Name & string}\" uses a reserved name`\n : Name extends keyof MethodsIn<Def>\n ? `${Kind} \"${Name & string}\" has the same name as a method`\n : Name extends keyof CollectionsIn<Def>\n ? `${Kind} \"${Name & string}\" has the same name as a collection`\n : Name extends Earlier\n ? `${Kind} \"${Name & string}\" has the same name as another stream, channel or event`\n : never;\n\ntype CheckRealtimeNames<Def, Members, Kind extends string, Earlier> = {\n readonly [Name in keyof Members]: [RealtimeNameProblem<Def, Kind, Name, Earlier>] extends [never]\n ? unknown\n : Problem<RealtimeNameProblem<Def, Kind, Name, Earlier>>;\n};\n\n/** The keys of a channel's parsed payload, when its schema's output is known. */\ntype PayloadKeys<Channel> = Channel extends { readonly payload: infer Payload }\n ? [SchemaOutput<Payload>] extends [never]\n ? never\n : keyof SchemaOutput<Payload> & string\n : never;\n\n/**\n * Why a literal `requires.room` names no app room: a reserved name, or a key\n * of the payload (a string there is the room itself, not a payload key as in\n * the other forms, so naming a key is almost always meant as\n * `(payload) => payload.key`).\n */\ntype RoomProblem<Name, Room, Channel> = Room extends { readonly prefix: infer Prefix }\n ? Prefix extends `${\"qd:\" | \"user:\"}${string}`\n ? `channel \"${Name & string}\": requires.room's prefix \"${Prefix & string}\" names no app room: names starting with \"qd:\" or \"user:\" are the framework's own rooms`\n : never\n : string extends Room\n ? never\n : Room extends `${\"qd:\" | \"user:\"}${string}`\n ? `channel \"${Name & string}\": requires.room \"${Room & string}\" is not an app room: names starting with \"qd:\" or \"user:\" are the framework's own rooms`\n : Room extends PayloadKeys<Channel>\n ? `channel \"${Name & string}\": requires.room is a room's name and \"${Room & string}\" is a key of the payload; to read the room from the payload write (payload) => payload.${Room & string}, and for a fixed room of that name () => \"${Room & string}\"`\n : never;\n\n/** A channel's `requires` names a collection of the contract, a row of an entity it has, or an app room. */\ntype RequiresProblem<Def, Name, Channel> = Channel extends {\n readonly requires: { readonly collection: infer Collection };\n}\n ? Collection extends keyof CollectionsIn<Def>\n ? never\n : `channel \"${Name & string}\" requires unknown collection \"${Collection & string}\"`\n : Channel extends { readonly requires: { readonly entity: unknown } }\n ? HasEntity<Def> extends true\n ? never\n : `channel \"${Name & string}\": requires.entity needs the contract's entity`\n : Channel extends { readonly requires: { readonly room: infer Room } }\n ? RoomProblem<Name, Room, Channel>\n : never;\n\ntype CheckChannels<Def> = CheckRealtimeNames<\n Def,\n ChannelsIn<Def>,\n \"channel\",\n keyof StreamsIn<Def>\n> & {\n readonly [Name in keyof ChannelsIn<Def>]: [\n RequiresProblem<Def, Name, ChannelsIn<Def>[Name]>,\n ] extends [never]\n ? unknown\n : Problem<RequiresProblem<Def, Name, ChannelsIn<Def>[Name]>>;\n};\n\n/**\n * A scoped stream's `access: { room }` is a function of its scope (the 5.1\n * audit's RT-4): a name or `{ prefix }` would let a socket in that room read\n * every scope. As `IsScopedStream` reads it, a scope other than `\"global\"`\n * makes a stream scoped.\n */\ntype StreamRoomProblem<Name, Stream> = Stream extends {\n readonly scope: infer Scope extends string;\n readonly access: { readonly room: infer Room };\n}\n ? Scope extends \"global\"\n ? never\n : Room extends (...args: never[]) => unknown\n ? never\n : `stream \"${Name & string}\" is scoped: its access room is a function of the scope, (scope) => room; a name or { prefix } lets a socket in that room read every scope`\n : never;\n\ntype CheckStreams<Def> = CheckRealtimeNames<Def, StreamsIn<Def>, \"stream\", never> & {\n readonly [Name in keyof StreamsIn<Def>]: [StreamRoomProblem<Name, StreamsIn<Def>[Name]>] extends [\n never,\n ]\n ? unknown\n : Problem<StreamRoomProblem<Name, StreamsIn<Def>[Name]>>;\n};\n\ntype DefinitionChecks<Def> = CheckKeys<Def, keyof ContractDefinition, \"contract\"> & {\n readonly methods?: CheckMethods<Def>;\n readonly collections?: CheckCollections<Def>;\n readonly projections?: CheckProjections<Def>;\n readonly fields?: CheckFields<Def>;\n readonly streams?: CheckStreams<Def>;\n readonly channels?: CheckChannels<Def>;\n readonly events?: CheckRealtimeNames<\n Def,\n EventsIn<Def>,\n \"event\",\n keyof StreamsIn<Def> | keyof ChannelsIn<Def>\n >;\n};\n\n/**\n * Defines the contract of one service: its entity, projections, field tiers,\n * methods, collections, streams, channels and events.\n *\n * The rules are checked by type, so a mistake fails to compile where it is\n * written, and again when the contract is defined, so JavaScript callers and\n * casts get an error too. A Standard Schema does not expose its keys, so some\n * rules can only be checked by type: that `fields`, `scope`, `order`, `where`\n * and `index` name real fields, and that a view reads only index fields.\n *\n * The type parameters after `Def` only exist so TypeScript can type `views`\n * predicates and channel `requires` functions; never pass them.\n *\n * @example\n * export const task = defineContract(\"taskService\", {\n * entity: taskSchema,\n * projections: { card: taskCardSchema },\n * fields: { internalNotes: \"Admin\" },\n * methods: {\n * get: query({ input: z.object({ id: z.string() }), output: \"entity\" }),\n * rename: mutation({ input: renameSchema, output: \"entity\" }),\n * },\n * collections: {\n * byProject: {\n * scope: \"projectId\",\n * item: \"card\",\n * order: [[\"ordinal\", \"asc\"], [\"id\", \"asc\"]],\n * index: [\"status\", \"assigneeId\"],\n * views: { mine: (row, who) => row.assigneeId === who.userId },\n * },\n * },\n * });\n */\nexport function defineContract<\n const Name extends string,\n const Def extends ContractDefinition,\n Entity extends RowSchema = never,\n Projections = Empty,\n Items = Empty,\n Indexes = Empty,\n Payloads = Empty,\n>(\n name: Name,\n def: Def &\n DefinitionContext<Entity, Projections, Items, Indexes, Payloads> &\n NoInfer<DefinitionChecks<Def>>,\n): Contract<Name, Def> {\n return assembleContract(name, def) as unknown as Contract<Name, Def>;\n}\n"],"mappings":"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","names":["access","isRecord","quote","isName"]}
|
|
@@ -427,6 +427,12 @@ type StreamAccess = "public" | "authenticated" | {
|
|
|
427
427
|
readonly scope?: undefined;
|
|
428
428
|
readonly of?: undefined;
|
|
429
429
|
};
|
|
430
|
+
/**
|
|
431
|
+
* Who serves a channel or a stream: the server, or the host of the app room
|
|
432
|
+
* it names (host mode, RFC 0003 section 12.5), a client the app chose with
|
|
433
|
+
* `ctx.rooms.setHost`, over its peer links.
|
|
434
|
+
*/
|
|
435
|
+
type RealtimeServe = "server" | "host";
|
|
430
436
|
/** A server-to-client stream of append-only items (RFC 0003 section 12.5). */
|
|
431
437
|
interface StreamDef<Item extends StandardSchemaV1 = StandardSchemaV1> {
|
|
432
438
|
/** One item's schema. Pushed items are checked against it before they are sent. */
|
|
@@ -445,6 +451,14 @@ interface StreamDef<Item extends StandardSchemaV1 = StandardSchemaV1> {
|
|
|
445
451
|
readonly volatile?: boolean;
|
|
446
452
|
/** Who may subscribe. Without it the stream is closed. */
|
|
447
453
|
readonly access?: StreamAccess;
|
|
454
|
+
/**
|
|
455
|
+
* Who pushes the items: `"server"`, the default, or `"host"`, the host of
|
|
456
|
+
* the room `access: { room }` computes from the scope. The host's client
|
|
457
|
+
* pushes them over its peer links, keeping the latest `seed` per scope for
|
|
458
|
+
* a peer that subscribes later, and the server never sees them. A
|
|
459
|
+
* host-served stream has a scope and `access: { room: (scope) => room }`.
|
|
460
|
+
*/
|
|
461
|
+
readonly serve?: RealtimeServe | (string & Record<never, never>);
|
|
448
462
|
/** What the stream carries, in a sentence or two, for the generated docs. */
|
|
449
463
|
readonly describe?: string;
|
|
450
464
|
}
|
|
@@ -518,6 +532,14 @@ interface ChannelDef<Payload extends StandardSchemaV1 = StandardSchemaV1> {
|
|
|
518
532
|
* `access` (`"authenticated"` when any signed-in user may send it).
|
|
519
533
|
*/
|
|
520
534
|
readonly requires?: ChannelRequires;
|
|
535
|
+
/**
|
|
536
|
+
* Who handles a message: `"server"`, the default, or `"host"`, the host of
|
|
537
|
+
* the room `requires: { room }` names. The sender's client sends it over
|
|
538
|
+
* its peer link to that host, whose client checks it as the server checks
|
|
539
|
+
* a channel message; the server never sees it. A host-served channel
|
|
540
|
+
* requires a room and takes no server handler.
|
|
541
|
+
*/
|
|
542
|
+
readonly serve?: RealtimeServe | (string & Record<never, never>);
|
|
521
543
|
/** What a message says, in a sentence or two, for the generated docs. */
|
|
522
544
|
readonly describe?: string;
|
|
523
545
|
}
|
|
@@ -958,6 +980,22 @@ type StreamName<C extends AnyContract> = keyof C["streams"] & string;
|
|
|
958
980
|
type ChannelName<C extends AnyContract> = keyof C["channels"] & string;
|
|
959
981
|
/** The names of a contract's typed room events. */
|
|
960
982
|
type EventName<C extends AnyContract> = keyof C["events"] & string;
|
|
983
|
+
/** The names of a contract's channels the room's host handles (`serve: "host"`). */
|
|
984
|
+
type HostChannelName<C extends AnyContract> = {
|
|
985
|
+
readonly [K in ChannelName<C>]: C["channels"][K] extends {
|
|
986
|
+
readonly serve: "host";
|
|
987
|
+
} ? K : never;
|
|
988
|
+
}[ChannelName<C>];
|
|
989
|
+
/** The names of a contract's channels the server handles. */
|
|
990
|
+
type ServerChannelName<C extends AnyContract> = Exclude<ChannelName<C>, HostChannelName<C>>;
|
|
991
|
+
/** The names of a contract's streams the room's host pushes (`serve: "host"`). */
|
|
992
|
+
type HostStreamName<C extends AnyContract> = {
|
|
993
|
+
readonly [K in StreamName<C>]: C["streams"][K] extends {
|
|
994
|
+
readonly serve: "host";
|
|
995
|
+
} ? K : never;
|
|
996
|
+
}[StreamName<C>];
|
|
997
|
+
/** The names of a contract's streams the server pushes. */
|
|
998
|
+
type ServerStreamName<C extends AnyContract> = Exclude<StreamName<C>, HostStreamName<C>>;
|
|
961
999
|
/** The item type of a stream: what `push` takes and subscribers receive. */
|
|
962
1000
|
type StreamItemOf<C extends AnyContract, K extends StreamName<C>> = InferOutput<C["streams"][K]["item"]>;
|
|
963
1001
|
/**
|
|
@@ -974,4 +1012,4 @@ type ChannelInputOf<C extends AnyContract, K extends ChannelName<C>> = InferInpu
|
|
|
974
1012
|
/** The payload type of a custom event: what `ctx.rooms.emit` takes and `useEvent` receives. */
|
|
975
1013
|
type EventPayloadOf<C extends AnyContract, K extends EventName<C>> = InferOutput<C["events"][K]["payload"]>;
|
|
976
1014
|
|
|
977
|
-
export { isScopedStream as $, type AccessLevel as A, type ViaScope as B, type CollectionDef as C, DEFAULT_COLLECTION_LIMIT as D, type EntityProjection as E, type Viewer as F, type ViewPredicate as G, defineContract as H, type InferInput as I, type AnyContract as J, type Contract as K, type ContractDefinition as L, type MethodDef as M, type NullableProjection as N, type OrderBy as O, type ProjectionList as P, type QueryDef as Q, type IndexRow as R, StandardJSONSchemaV1 as S, TODO_SCHEMA_VENDOR as T, type ReservedMethodName as U, type ValidationIssue as V, type Watch as W, type RowSchema as X, CHANNEL_DEFAULT_RATE as Y, GLOBAL_STREAM as Z, STREAM_MAX_SEED as _, type ACE as a, type ChannelDef as a0, type ChannelRequires as a1, type EventDef as a2, type PayloadSelector as a3, type RoomPrefix as a4, type RoomSelector as a5, type StreamAccess as a6, type StreamDef as a7, type StreamRoom as a8, type ChannelInputOf as a9, type ViewName as aA, type ChannelName as aa, type ChannelPayloadOf as ab, type CollectionName as ac, type CollectionOf as ad, type ContractMap as ae, type EntityOf as af, type EventName as ag, type EventPayloadOf as ah, type FullProjectionOf as ai, type IndexFieldOf as aj, type IndexRowOf as ak, type InputOf as al, type IsScopedStream as am, type ItemOf as an, type KindOf as ao, type MethodName as ap, type MethodOf as aq, type OutputOf as ar, type ParsedInputOf as as, type ProjectionName as at, type ProjectionOf as au, type ReceivedRow as av, type ScopeOf as aw, type ServiceNameOf as ax, type StreamItemOf as ay, type StreamName as az, type ACL as b, type InferOutput as c, StandardSchemaV1 as d, type StandardSchemaWithJSON as e, StandardTypedV1 as f, type TodoSchemaOptions as g, hasJsonSchema as h, isStandardSchema as i, type ValidationResult as j, type MethodKind as k, listOf as l, mutation as m, nullable as n, type MethodOutput as o, type MutationDef as p, query as q, type ProjectionRef as r, type ServiceModelsWatch as s, todoSchema as t, type ServiceWatch as u, validate as v, DEFAULT_COLLECTION_MAX_LIMIT as w, via as x, type CollectionWhere as y, type SortDirection as z };
|
|
1015
|
+
export { isScopedStream as $, type AccessLevel as A, type ViaScope as B, type CollectionDef as C, DEFAULT_COLLECTION_LIMIT as D, type EntityProjection as E, type Viewer as F, type ViewPredicate as G, defineContract as H, type InferInput as I, type AnyContract as J, type Contract as K, type ContractDefinition as L, type MethodDef as M, type NullableProjection as N, type OrderBy as O, type ProjectionList as P, type QueryDef as Q, type IndexRow as R, StandardJSONSchemaV1 as S, TODO_SCHEMA_VENDOR as T, type ReservedMethodName as U, type ValidationIssue as V, type Watch as W, type RowSchema as X, CHANNEL_DEFAULT_RATE as Y, GLOBAL_STREAM as Z, STREAM_MAX_SEED as _, type ACE as a, type ChannelDef as a0, type ChannelRequires as a1, type EventDef as a2, type PayloadSelector as a3, type RoomPrefix as a4, type RoomSelector as a5, type StreamAccess as a6, type StreamDef as a7, type StreamRoom as a8, type ChannelInputOf as a9, type ViewName as aA, type ServerChannelName as aB, type ServerStreamName as aC, type HostStreamName as aD, type HostChannelName as aE, type ChannelName as aa, type ChannelPayloadOf as ab, type CollectionName as ac, type CollectionOf as ad, type ContractMap as ae, type EntityOf as af, type EventName as ag, type EventPayloadOf as ah, type FullProjectionOf as ai, type IndexFieldOf as aj, type IndexRowOf as ak, type InputOf as al, type IsScopedStream as am, type ItemOf as an, type KindOf as ao, type MethodName as ap, type MethodOf as aq, type OutputOf as ar, type ParsedInputOf as as, type ProjectionName as at, type ProjectionOf as au, type ReceivedRow as av, type ScopeOf as aw, type ServiceNameOf as ax, type StreamItemOf as ay, type StreamName as az, type ACL as b, type InferOutput as c, StandardSchemaV1 as d, type StandardSchemaWithJSON as e, StandardTypedV1 as f, type TodoSchemaOptions as g, hasJsonSchema as h, isStandardSchema as i, type ValidationResult as j, type MethodKind as k, listOf as l, mutation as m, nullable as n, type MethodOutput as o, type MutationDef as p, query as q, type ProjectionRef as r, type ServiceModelsWatch as s, todoSchema as t, type ServiceWatch as u, validate as v, DEFAULT_COLLECTION_MAX_LIMIT as w, via as x, type CollectionWhere as y, type SortDirection as z };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { k as MethodKind } from './infer-
|
|
1
|
+
import { k as MethodKind } from './infer-Br62cnyW.js';
|
|
2
2
|
import { a as ErrorCode } from './errors-S-bxEIBC.js';
|
|
3
|
-
import { T as Transport } from './types-
|
|
3
|
+
import { T as Transport } from './types-CLRCQGnO.js';
|
|
4
4
|
|
|
5
5
|
/** How a call ended: `"ok"`, `"not-modified"`, or the error code it failed with. */
|
|
6
6
|
type CallOutcome = "ok" | "not-modified" | ErrorCode;
|
package/dist/parser.js
CHANGED
package/dist/prisma/index.d.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { L as Logger } from '../logger-Yz93KzdV.js';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
import { T as Tracked } from '../tracked-BR5b2O-U.js';
|
|
3
|
+
export { a as TrackedTransaction } from '../tracked-BR5b2O-U.js';
|
|
4
|
+
export { C as CountArgs, F as FindManyArgs, c as StatementCount, S as StorageAdapter, a as StorageRow, b as StorageWhere, s as storageOf } from '../caller-BTwGl7vm.js';
|
|
5
|
+
import '../infer-Br62cnyW.js';
|
|
6
|
+
import '../types-CLRCQGnO.js';
|
|
7
|
+
import '../envelope-BMBaxppV.js';
|
|
5
8
|
import '../errors-S-bxEIBC.js';
|
|
6
|
-
import '../types-CYliTP65.js';
|
|
7
9
|
|
|
8
10
|
/** Options of {@link trackPrisma}. */
|
|
9
11
|
interface TrackPrismaOptions {
|
|
@@ -37,6 +39,11 @@ interface PrismaClientLike {
|
|
|
37
39
|
* Nested writes, raw SQL and database cascades are not seen; record those
|
|
38
40
|
* with `ctx.touch`.
|
|
39
41
|
*
|
|
42
|
+
* The result is a `Tracked<C>` (`tracked.ts`): still a `C`, but the
|
|
43
|
+
* untracked client is no `Tracked<C>`, so a helper that writes takes
|
|
44
|
+
* `db: Tracked<Db>` (or `TrackedTransaction<Db>`, which a transaction's `tx`
|
|
45
|
+
* is too) and the compiler refuses the untracked client there.
|
|
46
|
+
*
|
|
40
47
|
* Prefer interactive transactions (`db.$transaction(async (tx) => ...)`). An
|
|
41
48
|
* array-form `db.$transaction([...])` has no transaction client, so the rows
|
|
42
49
|
* a `deleteMany` or `updateMany` there reads first (and an `update`'s old
|
|
@@ -49,7 +56,7 @@ interface PrismaClientLike {
|
|
|
49
56
|
* export const qd = initQuickdraw<{ db: typeof db; principal: AppPrincipal }>();
|
|
50
57
|
* const server = qd.createServer({ app, services, db, auth });
|
|
51
58
|
*/
|
|
52
|
-
declare function trackPrisma<C extends PrismaClientLike>(client: C, options?: TrackPrismaOptions): C
|
|
59
|
+
declare function trackPrisma<C extends PrismaClientLike>(client: C, options?: TrackPrismaOptions): Tracked<C>;
|
|
53
60
|
|
|
54
61
|
/** One nested write found in a write's `data`. */
|
|
55
62
|
interface NestedWrite {
|
|
@@ -61,4 +68,4 @@ interface NestedWrite {
|
|
|
61
68
|
/** The nested writes in `data`, one per relation field that has one. */
|
|
62
69
|
declare function findNestedWrites(data: unknown): NestedWrite[];
|
|
63
70
|
|
|
64
|
-
export { type NestedWrite, type PrismaClientLike, type TrackPrismaOptions, findNestedWrites, trackPrisma };
|
|
71
|
+
export { type NestedWrite, type PrismaClientLike, type TrackPrismaOptions, Tracked, findNestedWrites, trackPrisma };
|