@fitzzero/quickdraw-core 5.1.0 → 5.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (107) hide show
  1. package/README.md +533 -180
  2. package/dist/{admin-DKwkIh5i.d.ts → admin-DWWrT1h6.d.ts} +2 -2
  3. package/dist/{adminSchemas-2DUA_hZ8.d.ts → adminSchemas-D4bFKsrb.d.ts} +6 -4
  4. package/dist/{auth-BhWqdyb-.d.ts → auth-DXiSJZaf.d.ts} +42 -16
  5. package/dist/{caller-CXTFswBO.d.ts → caller-BT-Mv4bD.d.ts} +117 -22
  6. package/dist/{chunk-RT6OILOI.js → chunk-4D2DOGAW.js} +2 -14
  7. package/dist/chunk-4D2DOGAW.js.map +1 -0
  8. package/dist/chunk-5CGO426C.js +15 -0
  9. package/dist/chunk-5CGO426C.js.map +1 -0
  10. package/dist/{chunk-A6DJBGOG.js → chunk-6K5BY47X.js} +4594 -3481
  11. package/dist/chunk-6K5BY47X.js.map +1 -0
  12. package/dist/{chunk-VJTFXHOK.js → chunk-753VJIUP.js} +13 -15
  13. package/dist/chunk-753VJIUP.js.map +1 -0
  14. package/dist/{chunk-JZBCLNDU.js → chunk-7QCUX4TK.js} +4 -4
  15. package/dist/chunk-7QCUX4TK.js.map +1 -0
  16. package/dist/chunk-AK23XSWD.js +16 -0
  17. package/dist/chunk-AK23XSWD.js.map +1 -0
  18. package/dist/{chunk-3674EIRT.js → chunk-AONAFOYU.js} +14 -5
  19. package/dist/{chunk-3674EIRT.js.map → chunk-AONAFOYU.js.map} +1 -1
  20. package/dist/chunk-DKE6QO26.js +136 -0
  21. package/dist/chunk-DKE6QO26.js.map +1 -0
  22. package/dist/{chunk-H23KEFBA.js → chunk-DUBU3BB3.js} +30 -1
  23. package/dist/chunk-DUBU3BB3.js.map +1 -0
  24. package/dist/{chunk-CDKG4TFA.js → chunk-GKH3LJ7N.js} +1 -1
  25. package/dist/chunk-GKH3LJ7N.js.map +1 -0
  26. package/dist/{chunk-KNDDCVQJ.js → chunk-GSIPUNJL.js} +49 -9
  27. package/dist/chunk-GSIPUNJL.js.map +1 -0
  28. package/dist/{chunk-DD4SKCNO.js → chunk-LCC7HNFP.js} +12 -1
  29. package/dist/chunk-LCC7HNFP.js.map +1 -0
  30. package/dist/{chunk-2PWMUVC7.js → chunk-MBH6IDSM.js} +480 -12
  31. package/dist/chunk-MBH6IDSM.js.map +1 -0
  32. package/dist/{chunk-2UELNHDD.js → chunk-NMXYENH4.js} +10 -10
  33. package/dist/{chunk-2UELNHDD.js.map → chunk-NMXYENH4.js.map} +1 -1
  34. package/dist/chunk-NO4M6PO5.js +101 -0
  35. package/dist/chunk-NO4M6PO5.js.map +1 -0
  36. package/dist/{chunk-TBMKJ26R.js → chunk-NW6U45HX.js} +3 -1
  37. package/dist/chunk-NW6U45HX.js.map +1 -0
  38. package/dist/{chunk-REX5YPHX.js → chunk-RJ5I2VO3.js} +74 -19
  39. package/dist/chunk-RJ5I2VO3.js.map +1 -0
  40. package/dist/{chunk-QEKVYG5F.js → chunk-RL4VKLBX.js} +1 -1
  41. package/dist/{chunk-QEKVYG5F.js.map → chunk-RL4VKLBX.js.map} +1 -1
  42. package/dist/chunk-XH2IZVLT.js +62 -0
  43. package/dist/chunk-XH2IZVLT.js.map +1 -0
  44. package/dist/{chunk-4DIQHASK.js → chunk-Z5ILULF2.js} +26 -7
  45. package/dist/chunk-Z5ILULF2.js.map +1 -0
  46. package/dist/cli/quickdraw-docs.js +5 -3
  47. package/dist/cli/quickdraw-docs.js.map +1 -1
  48. package/dist/client/index.d.ts +30 -18
  49. package/dist/client/index.js +8 -6
  50. package/dist/client/index.js.map +1 -1
  51. package/dist/{clientTypes-Bc-G8n-U.d.ts → clientTypes-hWcPUVS9.d.ts} +3 -3
  52. package/dist/{connection-Cr1BU07W.d.ts → connection-CgijdGpT.d.ts} +8 -4
  53. package/dist/{createServer-CP9eDHZZ.d.ts → createServer-Cp-Wk500.d.ts} +36 -14
  54. package/dist/{createTestApp-UKVGEmOf.d.ts → createTestApp-BB_PkqQ7.d.ts} +16 -10
  55. package/dist/{envelope-Cp3YcVxC.d.ts → envelope-DzWyIXjj.d.ts} +18 -4
  56. package/dist/{http-Djj2Inuu.d.ts → http-DotQ5bj8.d.ts} +68 -17
  57. package/dist/index.d.ts +7 -7
  58. package/dist/index.js +37 -13
  59. package/dist/index.js.map +1 -1
  60. package/dist/{infer-Teo1xpsd.d.ts → infer-BmoZsL9a.d.ts} +43 -10
  61. package/dist/logger-Yz93KzdV.d.ts +30 -0
  62. package/dist/{metrics-BdBu5o8G.d.ts → metrics-DW80Exve.d.ts} +2 -2
  63. package/dist/origins-kvpxnVcW.d.ts +8 -0
  64. package/dist/prisma/index.d.ts +5 -5
  65. package/dist/prisma/index.js +130 -67
  66. package/dist/prisma/index.js.map +1 -1
  67. package/dist/{rateLimit-ZMIZJUZF.js → rateLimit-5RKBFLUR.js} +2 -2
  68. package/dist/server/auth/index.d.ts +82 -33
  69. package/dist/server/auth/index.js +273 -268
  70. package/dist/server/auth/index.js.map +1 -1
  71. package/dist/server/express/index.d.ts +9 -2
  72. package/dist/server/express/index.js +1 -1
  73. package/dist/server/index.d.ts +147 -67
  74. package/dist/server/index.js +520 -381
  75. package/dist/server/index.js.map +1 -1
  76. package/dist/server/mcp/index.d.ts +63 -17
  77. package/dist/server/mcp/index.js +256 -54
  78. package/dist/server/mcp/index.js.map +1 -1
  79. package/dist/server/otel.d.ts +3 -3
  80. package/dist/{sharing-DVa8W-yR.d.ts → sharing-UDLn1049.d.ts} +3 -3
  81. package/dist/testing/client.d.ts +14 -14
  82. package/dist/testing/client.js +9 -7
  83. package/dist/testing/client.js.map +1 -1
  84. package/dist/testing/index.d.ts +12 -12
  85. package/dist/testing/index.js +21 -12
  86. package/dist/testing/index.js.map +1 -1
  87. package/dist/testing/mock.d.ts +5 -5
  88. package/dist/testing/mock.js +8 -6
  89. package/dist/{types-Cu0vmx7c.d.ts → types-CYliTP65.d.ts} +1 -1
  90. package/dist/utils/index.d.ts +1 -1
  91. package/package.json +1 -1
  92. package/dist/chunk-2PWMUVC7.js.map +0 -1
  93. package/dist/chunk-4DIQHASK.js.map +0 -1
  94. package/dist/chunk-A6DJBGOG.js.map +0 -1
  95. package/dist/chunk-CDKG4TFA.js.map +0 -1
  96. package/dist/chunk-DD4SKCNO.js.map +0 -1
  97. package/dist/chunk-H23KEFBA.js.map +0 -1
  98. package/dist/chunk-JZBCLNDU.js.map +0 -1
  99. package/dist/chunk-KNDDCVQJ.js.map +0 -1
  100. package/dist/chunk-REX5YPHX.js.map +0 -1
  101. package/dist/chunk-RT6OILOI.js.map +0 -1
  102. package/dist/chunk-TBMKJ26R.js.map +0 -1
  103. package/dist/chunk-VJTFXHOK.js.map +0 -1
  104. package/dist/chunk-YSWH776Y.js +0 -13
  105. package/dist/chunk-YSWH776Y.js.map +0 -1
  106. package/dist/logger-BY28acW-.d.ts +0 -16
  107. /package/dist/{rateLimit-ZMIZJUZF.js.map → rateLimit-5RKBFLUR.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 } 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 `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 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 return reserved === undefined\n ? undefined\n : `room \"${name}\" is no app room: names starting with \"${reserved}\" are the framework's own rooms`;\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}\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 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\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?: CheckRealtimeNames<Def, StreamsIn<Def>, \"stream\", never>;\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 \"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"]}
@@ -296,7 +296,11 @@ interface ViaScope<Model extends string = string, Entry extends string = string,
296
296
  }
297
297
  /** What `via(...)` takes: the junction model, its entry and scope columns, and `refreshEntry`. */
298
298
  interface ViaOptions<Model extends string = string, Entry extends string = string, Scope extends string = string> {
299
- /** The junction model, as the database client names it: `"chatMember"`. */
299
+ /**
300
+ * The junction model, as the database client names it: `"chatMember"`. It
301
+ * needs an `id` column (keep the pair unique with `@@unique`, never a
302
+ * composite `@@id`), or its writes are not tracked and never move a scope.
303
+ */
300
304
  readonly model: Model;
301
305
  /** The junction column holding the entry's id: `"chatId"`. */
302
306
  readonly entry: Entry;
@@ -378,9 +382,12 @@ declare const STREAM_MAX_SEED = 1000;
378
382
  /** A channel's sustained rate when it declares none: messages per second per socket. */
379
383
  declare const CHANNEL_DEFAULT_RATE = 30;
380
384
  /**
381
- * The app room a stream's subscriber must be in (`access: { room }`): the
382
- * room's name, `{ prefix }` for any room whose name starts with it, or for a
383
- * scoped stream a function of the scope (`(worldId) => \`world:${worldId}\``).
385
+ * The app room a stream's subscriber must be in (`access: { room }`): for a
386
+ * global stream the room's name, or `{ prefix }` for any room whose name
387
+ * starts with it; for a scoped stream a function of the scope
388
+ * (`(worldId) => \`world:${worldId}\``), since a name or a prefix would let
389
+ * a socket in that room read every scope (`defineContract` refuses them
390
+ * there).
384
391
  */
385
392
  type StreamRoom = string | RoomPrefix | ((scope: string) => string | null | undefined);
386
393
  /**
@@ -391,7 +398,9 @@ type StreamRoom = string | RoomPrefix | ((scope: string) => string | null | unde
391
398
  * `{ room }` opens it to the sockets in an app room a method joined them to
392
399
  * (signed in or not), as a channel's `requires: { room }` does its messages:
393
400
  * a socket that leaves the room, or is taken out of it, leaves the feed too.
394
- * A stream that declares none is closed: no client may subscribe.
401
+ * A scoped stream computes that room from its scope; a name or `{ prefix }`
402
+ * serves a global stream only. A stream that declares none is closed: no
403
+ * client may subscribe.
395
404
  */
396
405
  type StreamAccess = "public" | "authenticated" | {
397
406
  readonly service: AccessLevel;
@@ -459,9 +468,10 @@ interface RoomPrefix {
459
468
  * (`(payload) => \`lobby:${payload.lobbyId}\``), or `{ prefix }`, any room
460
469
  * whose name starts with it (`{ prefix: "world:" }`). Unlike a
461
470
  * {@link PayloadSelector}, a string here is the room's name, not a payload
462
- * key. A name starting with `qd:` or `user:` is never an app room: a literal
463
- * one (or such a prefix) is refused when the contract is defined, and a
464
- * computed one drops the message.
471
+ * key. A name starting with `qd:` or `user:`, or one with the shape of a
472
+ * Socket.IO socket id (20 letters, digits, `_` or `-`), is never an app
473
+ * room: a literal one (or such a prefix) is refused when the contract is
474
+ * defined, and a computed one drops the message.
465
475
  */
466
476
  type RoomSelector = string | ((payload: never) => string | null | undefined) | RoomPrefix;
467
477
  /**
@@ -500,7 +510,13 @@ interface ChannelDef<Payload extends StandardSchemaV1 = StandardSchemaV1> {
500
510
  readonly ratePerSecond?: number;
501
511
  /** How many messages one socket may send at once. Default twice `ratePerSecond`. */
502
512
  readonly burst?: number;
503
- /** What the sender must already be subscribed to, or the app room it must be in. */
513
+ /**
514
+ * What the sender must already be subscribed to, or the app room it must
515
+ * be in. Without it every signed-in user may send the channel, about any
516
+ * row or room its payload names, and the server warns
517
+ * `channel-without-requires` unless the service declares the channel's
518
+ * `access` (`"authenticated"` when any signed-in user may send it).
519
+ */
504
520
  readonly requires?: ChannelRequires;
505
521
  /** What a message says, in a sentence or two, for the generated docs. */
506
522
  readonly describe?: string;
@@ -795,12 +811,29 @@ type CheckChannels<Def> = CheckRealtimeNames<Def, ChannelsIn<Def>, "channel", ke
795
811
  RequiresProblem<Def, Name, ChannelsIn<Def>[Name]>
796
812
  ] extends [never] ? unknown : Problem<RequiresProblem<Def, Name, ChannelsIn<Def>[Name]>>;
797
813
  };
814
+ /**
815
+ * A scoped stream's `access: { room }` is a function of its scope (the 5.1
816
+ * audit's RT-4): a name or `{ prefix }` would let a socket in that room read
817
+ * every scope. As `IsScopedStream` reads it, a scope other than `"global"`
818
+ * makes a stream scoped.
819
+ */
820
+ type StreamRoomProblem<Name, Stream> = Stream extends {
821
+ readonly scope: infer Scope extends string;
822
+ readonly access: {
823
+ readonly room: infer Room;
824
+ };
825
+ } ? Scope extends "global" ? never : Room extends (...args: never[]) => unknown ? never : `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` : never;
826
+ type CheckStreams<Def> = CheckRealtimeNames<Def, StreamsIn<Def>, "stream", never> & {
827
+ readonly [Name in keyof StreamsIn<Def>]: [StreamRoomProblem<Name, StreamsIn<Def>[Name]>] extends [
828
+ never
829
+ ] ? unknown : Problem<StreamRoomProblem<Name, StreamsIn<Def>[Name]>>;
830
+ };
798
831
  type DefinitionChecks<Def> = CheckKeys<Def, keyof ContractDefinition, "contract"> & {
799
832
  readonly methods?: CheckMethods<Def>;
800
833
  readonly collections?: CheckCollections<Def>;
801
834
  readonly projections?: CheckProjections<Def>;
802
835
  readonly fields?: CheckFields<Def>;
803
- readonly streams?: CheckRealtimeNames<Def, StreamsIn<Def>, "stream", never>;
836
+ readonly streams?: CheckStreams<Def>;
804
837
  readonly channels?: CheckChannels<Def>;
805
838
  readonly events?: CheckRealtimeNames<Def, EventsIn<Def>, "event", keyof StreamsIn<Def> | keyof ChannelsIn<Def>>;
806
839
  };
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Logger interface compatible with Winston and other loggers
3
+ */
4
+ interface Logger {
5
+ info(message: string, meta?: Record<string, unknown>): void;
6
+ warn(message: string, meta?: Record<string, unknown>): void;
7
+ error(message: string, meta?: Record<string, unknown>): void;
8
+ debug(message: string, meta?: Record<string, unknown>): void;
9
+ child(options: Record<string, unknown>): Logger;
10
+ }
11
+ /** A logger's levels, lowest first. */
12
+ type LogLevel = "debug" | "info" | "warn" | "error";
13
+ /** Options of {@link createConsoleLogger}. */
14
+ interface ConsoleLoggerOptions {
15
+ /**
16
+ * The lowest level written. Default `"info"` when `NODE_ENV` is
17
+ * `"production"` (read at each call), else `"debug"`.
18
+ */
19
+ readonly level?: LogLevel;
20
+ }
21
+ /**
22
+ * A logger that writes to the console from `level` up: by default every
23
+ * level, but `debug` when `NODE_ENV` is "production". `child` returns the
24
+ * same logger.
25
+ */
26
+ declare function createConsoleLogger(options?: ConsoleLoggerOptions): Logger;
27
+ /** The default console logger: every level, but `debug` in production. */
28
+ declare const consoleLogger: Logger;
29
+
30
+ export { type ConsoleLoggerOptions as C, type Logger as L, createConsoleLogger as a, type LogLevel as b, consoleLogger as c };
@@ -1,6 +1,6 @@
1
- import { k as MethodKind } from './infer-Teo1xpsd.js';
1
+ import { k as MethodKind } from './infer-BmoZsL9a.js';
2
2
  import { a as ErrorCode } from './errors-S-bxEIBC.js';
3
- import { T as Transport } from './types-Cu0vmx7c.js';
3
+ import { T as Transport } from './types-CYliTP65.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;
@@ -0,0 +1,8 @@
1
+ /**
2
+ * An allowed origin: exact (`"https://app.example.com"`), or a pattern over
3
+ * whole origins, anchored at both ends
4
+ * (`/^https:\/\/[a-z0-9-]+\.preview\.example\.com$/`).
5
+ */
6
+ type AllowedOrigin = string | RegExp;
7
+
8
+ export type { AllowedOrigin as A };
@@ -1,9 +1,9 @@
1
- import { L as Logger } from '../logger-BY28acW-.js';
2
- export { C as CountArgs, F as FindManyArgs, c as StatementCount, S as StorageAdapter, a as StorageRow, b as StorageWhere, s as storageOf } from '../caller-CXTFswBO.js';
3
- import '../envelope-Cp3YcVxC.js';
4
- import '../infer-Teo1xpsd.js';
1
+ import { L as Logger } from '../logger-Yz93KzdV.js';
2
+ export { C as CountArgs, F as FindManyArgs, c as StatementCount, S as StorageAdapter, a as StorageRow, b as StorageWhere, s as storageOf } from '../caller-BT-Mv4bD.js';
3
+ import '../envelope-DzWyIXjj.js';
4
+ import '../infer-BmoZsL9a.js';
5
5
  import '../errors-S-bxEIBC.js';
6
- import '../types-Cu0vmx7c.js';
6
+ import '../types-CYliTP65.js';
7
7
 
8
8
  /** Options of {@link trackPrisma}. */
9
9
  interface TrackPrismaOptions {