@fitzzero/quickdraw-core 5.0.0 → 5.1.0

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 (68) hide show
  1. package/README.md +343 -49
  2. package/dist/{admin-BiU4LRZS.d.ts → admin-DKwkIh5i.d.ts} +25 -10
  3. package/dist/{adminSchemas-k5a1Ov7b.d.ts → adminSchemas-2DUA_hZ8.d.ts} +15 -9
  4. package/dist/{auth-CMyRkfjZ.d.ts → auth-BhWqdyb-.d.ts} +2 -2
  5. package/dist/{caller-DHzK3oiI.d.ts → caller-CXTFswBO.d.ts} +28 -6
  6. package/dist/{chunk-2XJFNVHW.js → chunk-2PWMUVC7.js} +1 -1
  7. package/dist/{chunk-2XJFNVHW.js.map → chunk-2PWMUVC7.js.map} +1 -1
  8. package/dist/{chunk-5IC5VZ7T.js → chunk-2UELNHDD.js} +3 -3
  9. package/dist/{chunk-XFDOGTMC.js → chunk-3674EIRT.js} +4 -4
  10. package/dist/{chunk-DNCAI3KY.js → chunk-4DIQHASK.js} +1 -1
  11. package/dist/chunk-4DIQHASK.js.map +1 -0
  12. package/dist/{chunk-LLLYILEP.js → chunk-A6DJBGOG.js} +411 -43
  13. package/dist/chunk-A6DJBGOG.js.map +1 -0
  14. package/dist/{chunk-B2UQ27GH.js → chunk-CDKG4TFA.js} +25 -5
  15. package/dist/{chunk-B2UQ27GH.js.map → chunk-CDKG4TFA.js.map} +1 -1
  16. package/dist/{chunk-IRGAGRVG.js → chunk-JZBCLNDU.js} +4 -4
  17. package/dist/{chunk-XUSN5WKU.js → chunk-KNDDCVQJ.js} +4 -4
  18. package/dist/{chunk-5YRQ26LF.js → chunk-RT6OILOI.js} +1 -1
  19. package/dist/chunk-RT6OILOI.js.map +1 -0
  20. package/dist/{chunk-7QIY2DDX.js → chunk-VJTFXHOK.js} +2 -2
  21. package/dist/{chunk-7QIY2DDX.js.map → chunk-VJTFXHOK.js.map} +1 -1
  22. package/dist/chunk-XNLWBZIG.js +9 -0
  23. package/dist/chunk-XNLWBZIG.js.map +1 -0
  24. package/dist/cli/quickdraw-docs.js +241 -27
  25. package/dist/cli/quickdraw-docs.js.map +1 -1
  26. package/dist/client/index.d.ts +7 -7
  27. package/dist/client/index.js +5 -5
  28. package/dist/{clientTypes-B3o_99Xq.d.ts → clientTypes-Bc-G8n-U.d.ts} +3 -3
  29. package/dist/{connection-DuN8GvcD.d.ts → connection-Cr1BU07W.d.ts} +2 -2
  30. package/dist/{createServer-DUacdfKl.d.ts → createServer-CP9eDHZZ.d.ts} +30 -9
  31. package/dist/{createTestApp-DFLXoTKm.d.ts → createTestApp-UKVGEmOf.d.ts} +6 -6
  32. package/dist/{envelope-nf5eGB-a.d.ts → envelope-Cp3YcVxC.d.ts} +1 -1
  33. package/dist/{http--uoooIH5.d.ts → http-Djj2Inuu.d.ts} +6 -6
  34. package/dist/index.d.ts +6 -6
  35. package/dist/index.js +27 -7
  36. package/dist/index.js.map +1 -1
  37. package/dist/{infer-Dw21kmLw.d.ts → infer-Teo1xpsd.d.ts} +17 -0
  38. package/dist/{metrics-C0WvB7-I.d.ts → metrics-BdBu5o8G.d.ts} +2 -2
  39. package/dist/prisma/index.d.ts +4 -4
  40. package/dist/prisma/index.js +1 -1
  41. package/dist/server/auth/index.d.ts +14 -5
  42. package/dist/server/auth/index.js +0 -5
  43. package/dist/server/auth/index.js.map +1 -1
  44. package/dist/server/index.d.ts +120 -33
  45. package/dist/server/index.js +146 -193
  46. package/dist/server/index.js.map +1 -1
  47. package/dist/server/mcp/index.d.ts +51 -11
  48. package/dist/server/mcp/index.js +129 -8
  49. package/dist/server/mcp/index.js.map +1 -1
  50. package/dist/server/otel.d.ts +3 -3
  51. package/dist/{sharing-n4ss-ONM.d.ts → sharing-DVa8W-yR.d.ts} +3 -3
  52. package/dist/testing/client.d.ts +13 -13
  53. package/dist/testing/client.js +6 -6
  54. package/dist/testing/index.d.ts +156 -12
  55. package/dist/testing/index.js +1037 -22
  56. package/dist/testing/index.js.map +1 -1
  57. package/dist/testing/mock.d.ts +5 -5
  58. package/dist/testing/mock.js +5 -5
  59. package/dist/{types-Bwg3kIEc.d.ts → types-Cu0vmx7c.d.ts} +8 -2
  60. package/dist/utils/index.d.ts +1 -1
  61. package/package.json +1 -1
  62. package/dist/chunk-5YRQ26LF.js.map +0 -1
  63. package/dist/chunk-DNCAI3KY.js.map +0 -1
  64. package/dist/chunk-LLLYILEP.js.map +0 -1
  65. /package/dist/{chunk-5IC5VZ7T.js.map → chunk-2UELNHDD.js.map} +0 -0
  66. /package/dist/{chunk-XFDOGTMC.js.map → chunk-3674EIRT.js.map} +0 -0
  67. /package/dist/{chunk-IRGAGRVG.js.map → chunk-JZBCLNDU.js.map} +0 -0
  68. /package/dist/{chunk-XUSN5WKU.js.map → chunk-KNDDCVQJ.js.map} +0 -0
@@ -1,11 +1,11 @@
1
1
  import { IncomingMessage, ServerResponse, Server as Server$1 } from 'node:http';
2
- import { a as DispatcherOptions, H as HttpRouter, b as HttpTransportOptions, P as PrincipalOfServices, D as Dispatcher } from './http--uoooIH5.js';
3
- import { P as Principal } from './types-Bwg3kIEc.js';
4
- import { r as AppRooms, t as StreamSubscriptions, A as AnyService, u as RoomLeaveHandler } from './caller-DHzK3oiI.js';
5
- import { S as ServerAuth, a as ServiceGrants } from './auth-CMyRkfjZ.js';
2
+ import { a as DispatcherOptions, H as HttpRouter, b as HttpTransportOptions, P as PrincipalOfServices, D as Dispatcher } from './http-Djj2Inuu.js';
3
+ import { P as Principal } from './types-Cu0vmx7c.js';
4
+ import { r as AppRooms, t as StreamSubscriptions, A as AnyService, u as RoomLeaveHandler } from './caller-CXTFswBO.js';
5
+ import { S as ServerAuth, a as ServiceGrants } from './auth-BhWqdyb-.js';
6
6
  import { Server, DefaultEventsMap, Socket, ServerOptions as ServerOptions$1 } from 'socket.io';
7
- import { g as PROTOCOL_VERSION } from './envelope-nf5eGB-a.js';
8
- import { A as AccessLevel } from './infer-Dw21kmLw.js';
7
+ import { g as PROTOCOL_VERSION } from './envelope-Cp3YcVxC.js';
8
+ import { A as AccessLevel } from './infer-Teo1xpsd.js';
9
9
  import { L as Logger } from './logger-BY28acW-.js';
10
10
 
11
11
  /** One live collection subscription, as `socket.data.collections[room]` records it. */
@@ -347,6 +347,25 @@ declare function createTieredRateLimiter(tiers: Record<string, RateLimitOptions>
347
347
  /** The socket rate limiter's options, as `createServer` takes them. */
348
348
  type SocketRateLimitOptions = Omit<RateLimitOptions, "logger" | "ackPayload">;
349
349
 
350
+ /** 4.x's `ServiceResponse`, the shape every reply of the shim takes. */
351
+ type LegacyReply = {
352
+ readonly success: true;
353
+ readonly data: unknown;
354
+ } | {
355
+ readonly success: false;
356
+ readonly error: string;
357
+ readonly code: number;
358
+ };
359
+ /** `createServer`'s `legacyWire` as an object: what the shim serves beyond the services' own names. */
360
+ interface LegacyWireOptions {
361
+ /**
362
+ * Old service names 4.x clients still call, each mapped to the registered
363
+ * service it now names, e.g. `{ taskService: "cardService" }`. A key may
364
+ * not be a registered service's name or contain `:`.
365
+ */
366
+ readonly aliases?: Readonly<Record<string, string>>;
367
+ }
368
+
350
369
  /** Options of `server.access.disconnectUser`. */
351
370
  interface DisconnectUserOptions {
352
371
  /** End only the sockets that authenticated with this session (`recordSocketSession`). */
@@ -397,9 +416,11 @@ interface ServerOnlyOptions<P extends Principal = Principal> {
397
416
  /**
398
417
  * Serve 4.x clients, which connect without `auth.qd`, through the legacy
399
418
  * shim: request/response calls only. Default `false`: they are refused with
400
- * `PROTOCOL_MISMATCH`.
419
+ * `PROTOCOL_MISMATCH`. `{ aliases: { taskService: "cardService" } }` also
420
+ * serves a renamed service under its old name, to 4.x clients only, and
421
+ * logs each caller of an old name once.
401
422
  */
402
- readonly legacyWire?: boolean;
423
+ readonly legacyWire?: boolean | LegacyWireOptions;
403
424
  /**
404
425
  * The socket rate limiter (`createRateLimiter`'s options), or `false` for
405
426
  * none. Default: 600 events per minute per socket. `qd:ch` (channels keep
@@ -558,4 +579,4 @@ interface QuickdrawServer<S extends readonly AnyService[] = readonly AnyService[
558
579
  */
559
580
  declare function createServer<const S extends readonly AnyService[]>(options: ServerOptions<S>): QuickdrawServer<S>;
560
581
 
561
- export { type ClusterClient as C, DEFAULT_STALL_INTERVAL_MS as D, type EntitySubscription as E, type HttpApp as H, type IoRedisLike as I, MIN_STALL_INTERVAL_MS as M, type QuickdrawServer as Q, type RotateOptions as R, type ServerOptions as S, type TopicWatch as T, type EntitySubscriptions as a, type ScopeSubscription as b, type ScopeSubscriptions as c, type TopicWatches as d, DEFAULT_STALL_MAX_MS as e, DEFAULT_STALL_THRESHOLD_MS as f, STALL_RESOLUTION_MS as g, type SlowMethod as h, type StallReport as i, type StallWatchdogOptions as j, createServer as k, type ServerOnlyOptions as l, type QuickdrawIo as m, type QuickdrawServerSocket as n, type QuickdrawSocketData as o, type DisconnectUserOptions as p, type SocketCors as q, type SocketOptions as r, type SocketRateLimitOptions as s, type ClusterOptions as t, createRateLimiter as u, applyRateLimitMiddleware as v, createTieredRateLimiter as w, type RateLimitOptions as x, type RateLimiter as y };
582
+ export { type ClusterClient as C, DEFAULT_STALL_INTERVAL_MS as D, type EntitySubscription as E, type HttpApp as H, type IoRedisLike as I, type LegacyReply as L, MIN_STALL_INTERVAL_MS as M, type QuickdrawServer as Q, type RotateOptions as R, type ServerOptions as S, type TopicWatch as T, type EntitySubscriptions as a, type ScopeSubscription as b, type ScopeSubscriptions as c, type TopicWatches as d, DEFAULT_STALL_MAX_MS as e, DEFAULT_STALL_THRESHOLD_MS as f, STALL_RESOLUTION_MS as g, type SlowMethod as h, type StallReport as i, type StallWatchdogOptions as j, createServer as k, type ServerOnlyOptions as l, type QuickdrawIo as m, type QuickdrawServerSocket as n, type QuickdrawSocketData as o, type DisconnectUserOptions as p, type SocketCors as q, type SocketOptions as r, type SocketRateLimitOptions as s, type LegacyWireOptions as t, type ClusterOptions as u, createRateLimiter as v, applyRateLimitMiddleware as w, createTieredRateLimiter as x, type RateLimitOptions as y, type RateLimiter as z };
@@ -1,9 +1,9 @@
1
- import { f as ServerEventName, a9 as ServerToClientEvents, a1 as EventFrame, S as SERVER_EVENTS, aa as StreamFrame, k as HelloFrame } from './envelope-nf5eGB-a.js';
2
- import { A as AnyService, i as Caller } from './caller-DHzK3oiI.js';
3
- import { S as ServerOptions, Q as QuickdrawServer } from './createServer-DUacdfKl.js';
4
- import { P as PrincipalOfServices, C as ContractOfServices } from './http--uoooIH5.js';
5
- import { J as AnyContract, ag as EventName, ah as EventPayloadOf, az as StreamName, ay as StreamItemOf } from './infer-Dw21kmLw.js';
6
- import { C as CallRecord } from './metrics-C0WvB7-I.js';
1
+ import { f as ServerEventName, a9 as ServerToClientEvents, a1 as EventFrame, S as SERVER_EVENTS, aa as StreamFrame, k as HelloFrame } from './envelope-Cp3YcVxC.js';
2
+ import { A as AnyService, d as Caller } from './caller-CXTFswBO.js';
3
+ import { S as ServerOptions, Q as QuickdrawServer } from './createServer-CP9eDHZZ.js';
4
+ import { P as PrincipalOfServices, C as ContractOfServices } from './http-Djj2Inuu.js';
5
+ import { J as AnyContract, ag as EventName, ah as EventPayloadOf, az as StreamName, ay as StreamItemOf } from './infer-Teo1xpsd.js';
6
+ import { C as CallRecord } from './metrics-BdBu5o8G.js';
7
7
  import { Socket } from 'socket.io-client';
8
8
 
9
9
  /** The payload of a v5 server event, by its name. */
@@ -1,4 +1,4 @@
1
- import { A as AccessLevel } from './infer-Dw21kmLw.js';
1
+ import { A as AccessLevel } from './infer-Teo1xpsd.js';
2
2
  import { W as WireError } from './errors-S-bxEIBC.js';
3
3
 
4
4
  /**
@@ -1,12 +1,12 @@
1
1
  import { IncomingMessage, ServerResponse } from 'node:http';
2
2
  import { L as Logger } from './logger-BY28acW-.js';
3
- import { J as AnyContract, A as AccessLevel } from './infer-Dw21kmLw.js';
4
- import { P as Principal, T as Transport, a as McpContext, D as DbOf, c as PrincipalOf, M as MaybePromise } from './types-Bwg3kIEc.js';
5
- import { A as AnyService, j as ServiceMethod, R as RowLevels, k as AccessFilter, i as Caller, l as RunContext, m as RunOptions, P as Presence, n as ServerRooms, o as StreamHandle, p as AnyContext, S as StorageAdapter, U as UnitOfWorkFactory, d as FlushSink, q as AccessEngine } from './caller-DHzK3oiI.js';
6
- import { ad as Version, x as CallReply } from './envelope-nf5eGB-a.js';
3
+ import { J as AnyContract, A as AccessLevel } from './infer-Teo1xpsd.js';
4
+ import { P as Principal, T as Transport, a as McpContext, D as DbOf, c as PrincipalOf, M as MaybePromise } from './types-Cu0vmx7c.js';
5
+ import { A as AnyService, g as ServiceMethod, R as RowLevels, k as AccessFilter, d as Caller, l as RunContext, m as RunOptions, P as Presence, n as ServerRooms, o as StreamHandle, p as AnyContext, S as StorageAdapter, U as UnitOfWorkFactory, e as FlushSink, q as AccessEngine } from './caller-CXTFswBO.js';
6
+ import { ad as Version, x as CallReply } from './envelope-Cp3YcVxC.js';
7
7
  import { Q as QuickdrawError } from './errors-S-bxEIBC.js';
8
- import { C as CallRecord } from './metrics-C0WvB7-I.js';
9
- import { S as ServerAuth } from './auth-CMyRkfjZ.js';
8
+ import { C as CallRecord } from './metrics-BdBu5o8G.js';
9
+ import { S as ServerAuth } from './auth-BhWqdyb-.js';
10
10
 
11
11
  /** How one call ended. The dispatcher's `call` resolves with it and never rejects. */
12
12
  type DispatchResult = {
package/dist/index.d.ts CHANGED
@@ -1,12 +1,12 @@
1
- export { a as ACE, b as ACL, A as AccessLevel, J as AnyContract, Y as CHANNEL_DEFAULT_RATE, a0 as ChannelDef, a9 as ChannelInputOf, aa as ChannelName, ab as ChannelPayloadOf, a1 as ChannelRequires, C as CollectionDef, ac as CollectionName, ad as CollectionOf, y as CollectionWhere, K as Contract, L as ContractDefinition, ae as ContractMap, D as DEFAULT_COLLECTION_LIMIT, w as DEFAULT_COLLECTION_MAX_LIMIT, af as EntityOf, E as EntityProjection, a2 as EventDef, ag as EventName, ah as EventPayloadOf, ai as FullProjectionOf, Z as GLOBAL_STREAM, aj as IndexFieldOf, R as IndexRow, ak as IndexRowOf, I as InferInput, c as InferOutput, al as InputOf, am as IsScopedStream, an as ItemOf, ao as KindOf, M as MethodDef, k as MethodKind, ap as MethodName, aq as MethodOf, o as MethodOutput, p as MutationDef, N as NullableProjection, O as OrderBy, ar as OutputOf, as as ParsedInputOf, a3 as PayloadSelector, P as ProjectionList, at as ProjectionName, au as ProjectionOf, r as ProjectionRef, Q as QueryDef, av as ReceivedRow, U as ReservedMethodName, a4 as RoomPrefix, a5 as RoomSelector, X as RowSchema, _ as STREAM_MAX_SEED, aw as ScopeOf, s as ServiceModelsWatch, ax as ServiceNameOf, u as ServiceWatch, z as SortDirection, S as StandardJSONSchemaV1, d as StandardSchemaV1, e as StandardSchemaWithJSON, f as StandardTypedV1, a6 as StreamAccess, a7 as StreamDef, ay as StreamItemOf, az as StreamName, a8 as StreamRoom, T as TODO_SCHEMA_VENDOR, g as TodoSchemaOptions, V as ValidationIssue, j as ValidationResult, B as ViaScope, aA as ViewName, G as ViewPredicate, F as Viewer, W as Watch, H as defineContract, h as hasJsonSchema, $ as isScopedStream, i as isStandardSchema, l as listOf, m as mutation, n as nullable, q as query, t as todoSchema, v as validate, x as via } from './infer-Dw21kmLw.js';
1
+ export { a as ACE, b as ACL, A as AccessLevel, J as AnyContract, Y as CHANNEL_DEFAULT_RATE, a0 as ChannelDef, a9 as ChannelInputOf, aa as ChannelName, ab as ChannelPayloadOf, a1 as ChannelRequires, C as CollectionDef, ac as CollectionName, ad as CollectionOf, y as CollectionWhere, K as Contract, L as ContractDefinition, ae as ContractMap, D as DEFAULT_COLLECTION_LIMIT, w as DEFAULT_COLLECTION_MAX_LIMIT, af as EntityOf, E as EntityProjection, a2 as EventDef, ag as EventName, ah as EventPayloadOf, ai as FullProjectionOf, Z as GLOBAL_STREAM, aj as IndexFieldOf, R as IndexRow, ak as IndexRowOf, I as InferInput, c as InferOutput, al as InputOf, am as IsScopedStream, an as ItemOf, ao as KindOf, M as MethodDef, k as MethodKind, ap as MethodName, aq as MethodOf, o as MethodOutput, p as MutationDef, N as NullableProjection, O as OrderBy, ar as OutputOf, as as ParsedInputOf, a3 as PayloadSelector, P as ProjectionList, at as ProjectionName, au as ProjectionOf, r as ProjectionRef, Q as QueryDef, av as ReceivedRow, U as ReservedMethodName, a4 as RoomPrefix, a5 as RoomSelector, X as RowSchema, _ as STREAM_MAX_SEED, aw as ScopeOf, s as ServiceModelsWatch, ax as ServiceNameOf, u as ServiceWatch, z as SortDirection, S as StandardJSONSchemaV1, d as StandardSchemaV1, e as StandardSchemaWithJSON, f as StandardTypedV1, a6 as StreamAccess, a7 as StreamDef, ay as StreamItemOf, az as StreamName, a8 as StreamRoom, T as TODO_SCHEMA_VENDOR, g as TodoSchemaOptions, V as ValidationIssue, j as ValidationResult, B as ViaScope, aA as ViewName, G as ViewPredicate, F as Viewer, W as Watch, H as defineContract, h as hasJsonSchema, $ as isScopedStream, i as isStandardSchema, l as listOf, m as mutation, n as nullable, q as query, t as todoSchema, v as validate, x as via } from './infer-Teo1xpsd.js';
2
2
  export { L as Logger, c as consoleLogger } from './logger-BY28acW-.js';
3
- export { A as ADMIN_METHODS, w as AdminContractOptions, x as AdminCreateDef, y as AdminDeleteDef, z as AdminGetDef, D as AdminListDef, E as AdminMetaDef, F as AdminMethodName, G as AdminMethods, H as AdminMethodsOf, J as AdminReemitDef, K as AdminSubscribersDef, M as AdminTag, O as AdminUpdateDef, B as BulkPatch, t as BulkResult, s as CRUD_MAX_IDS, C as CRUD_METHODS, a as CrudBulkDelete, b as CrudBulkUpdate, d as CrudContractOptions, e as CrudCreate, f as CrudDelete, g as CrudGet, h as CrudGetMany, i as CrudInputOptions, j as CrudList, k as CrudListOptions, l as CrudMethodName, m as CrudMethods, n as CrudReorder, o as CrudReorderOptions, p as CrudTag, q as CrudToggle, r as CrudUpdate, I as IdInput, u as IdsInput, P as KitSchema, L as ListInput, N as NumberFieldOf, R as ReorderInput, S as ScalarFieldOf, W as WithId, v as admin, c as crud } from './admin-BiU4LRZS.js';
4
- export { o as ADMIN_DEFAULT_PAGE_SIZE, A as ADMIN_FIELD_TYPES, p as ADMIN_MAX_PAGE, q as ADMIN_MAX_PAGE_SIZE, k as ADMIN_NEVER_WRITABLE, r as AdminCreateInput, s as AdminCreateQuery, t as AdminData, l as AdminFieldConfig, m as AdminFieldType, u as AdminListInput, v as AdminListQuery, w as AdminMetaInput, x as AdminNeverWritable, y as AdminPage, n as AdminServiceMeta, z as AdminSubscribers, B as AdminUpdateInput, C as AdminUpdateQuery, F as FilterValue, L as LIST_DEFAULT_LIMIT, a as LIST_MAX_LIMIT, b as ListPage, c as ListQuery, d as ListSort, S as SEARCH_DEFAULT_LIMIT, e as SEARCH_DEFAULT_MIN_LENGTH, f as SEARCH_MAX_LIMIT, g as SEARCH_MAX_QUERY_LENGTH, h as SearchInput, i as SearchPage, j as SearchQuery, D as SubscriberLevel } from './adminSchemas-k5a1Ov7b.js';
5
- export { A as AclMethodName, I as InviteByNameInput, z as InviteByNameQuery, B as InviteInput, C as InviteQuery, L as LeaveInput, D as ListMembersInput, E as ListMembersQuery, F as Member, G as MemberInput, M as MembersMethodName, H as MembersPage, y as SHARE_LEVELS, d as SHARING_METHODS, S as SearchContractOptions, a as SearchDef, b as SearchMethods, c as SearchTag, J as SetRoleInput, K as ShareByNameInput, N as ShareByNameQuery, O as ShareInput, P as ShareLevel, f as SharingByNameMethod, g as SharingContractOptions, h as SharingDefOf, i as SharingInvite, j as SharingInviteByName, k as SharingLeave, l as SharingListMembers, m as SharingListShares, n as SharingMethodName, o as SharingMethods, p as SharingMode, q as SharingRemove, r as SharingSetLevel, t as SharingSetRole, u as SharingShare, v as SharingShareByName, w as SharingTag, x as SharingUnshare, T as TextFieldOf, U as UnshareInput, Q as UserLookupInput, s as search, e as sharing } from './sharing-n4ss-ONM.js';
6
- export { q as AccessFrame, A as AuthenticationRefused, C as CLIENT_EVENTS, r as CallEnvelope, v as CallId, w as CallNotModified, x as CallReply, y as CallSuccess, z as CancelFrame, B as ChangedFrame, D as ChannelFrame, d as ClientEventName, E as ClientToServerEvents, F as CollectionDelta, G as CollectionFrame, I as CollectionItemsReply, J as CollectionItemsRequest, K as CollectionResumed, L as CollectionScopeRef, M as CollectionSnapshot, N as CollectionSubscribe, O as CollectionSubscribeReply, T as EntityFrame, U as EntityNotModified, V as EntityPatch, W as EntityRemove, X as EntityResult, Y as EntityRow, Z as EntitySubscribe, _ as EntitySubscribeReply, $ as EntityUnsubscribe, a0 as EntityUpdate, a1 as EventFrame, a2 as Failure, H as HandshakeAuth, k as HelloFrame, l as HelloLimits, m as HelloSubscriptionLimits, a3 as Ok, P as PROTOCOL_MISMATCH, g as PROTOCOL_VERSION, a4 as PresenceFrame, n as ProtocolMismatch, Q as QdHandshake, R as RESERVED_ROOM_PREFIXES, a5 as Revision, a7 as RevokeReason, a6 as RevokedFrame, a8 as RotateFrame, S as SERVER_EVENTS, a as SERVICE_TOPIC, f as ServerEventName, a9 as ServerToClientEvents, aa as StreamFrame, ab as StreamSubscribe, ac as StreamSubscribeReply, ad as Version, ae as WatchFrame, af as WireIndexRow, c as collectionRoom, b as collectionTopic, e as entityRoom, i as isAuthenticationRefused, o as isCallEnvelope, p as isCancel, h as isProtocolMismatch, j as isQdHandshake, s as streamRoom, t as topicRoom, u as userRoom } from './envelope-nf5eGB-a.js';
3
+ export { A as ADMIN_METHODS, w as AdminContractOptions, x as AdminCreateDef, y as AdminDeleteDef, z as AdminGetDef, D as AdminListDef, E as AdminMetaDef, F as AdminMethodName, G as AdminMethods, H as AdminMethodsOf, J as AdminReemitDef, K as AdminSubscribersDef, M as AdminTag, O as AdminUpdateDef, B as BulkPatch, t as BulkResult, s as CRUD_MAX_IDS, C as CRUD_METHODS, a as CrudBulkDelete, b as CrudBulkUpdate, d as CrudContractOptions, e as CrudCreate, f as CrudDelete, g as CrudGet, h as CrudGetMany, i as CrudInputOptions, j as CrudList, k as CrudListOptions, l as CrudMethodName, m as CrudMethods, n as CrudReorder, o as CrudReorderOptions, p as CrudTag, q as CrudToggle, r as CrudUpdate, I as IdInput, u as IdsInput, P as KitSchema, L as ListInput, N as NumberFieldOf, R as ReorderInput, S as ScalarFieldOf, W as WithId, v as admin, c as crud } from './admin-DKwkIh5i.js';
4
+ export { o as ADMIN_DEFAULT_PAGE_SIZE, A as ADMIN_FIELD_TYPES, p as ADMIN_MAX_PAGE, q as ADMIN_MAX_PAGE_SIZE, k as ADMIN_NEVER_WRITABLE, r as AdminCreateInput, s as AdminCreateQuery, t as AdminData, l as AdminFieldConfig, m as AdminFieldType, u as AdminListInput, v as AdminListQuery, w as AdminMetaInput, x as AdminNeverWritable, y as AdminPage, n as AdminServiceMeta, z as AdminSubscribers, B as AdminUpdateInput, C as AdminUpdateQuery, D as AdminWritable, F as FilterValue, L as LIST_DEFAULT_LIMIT, a as LIST_MAX_LIMIT, b as ListPage, c as ListQuery, d as ListSort, S as SEARCH_DEFAULT_LIMIT, e as SEARCH_DEFAULT_MIN_LENGTH, f as SEARCH_MAX_LIMIT, g as SEARCH_MAX_QUERY_LENGTH, h as SearchInput, i as SearchPage, j as SearchQuery, E as SubscriberLevel } from './adminSchemas-2DUA_hZ8.js';
5
+ export { A as AclMethodName, I as InviteByNameInput, z as InviteByNameQuery, B as InviteInput, C as InviteQuery, L as LeaveInput, D as ListMembersInput, E as ListMembersQuery, F as Member, G as MemberInput, M as MembersMethodName, H as MembersPage, y as SHARE_LEVELS, d as SHARING_METHODS, S as SearchContractOptions, a as SearchDef, b as SearchMethods, c as SearchTag, J as SetRoleInput, K as ShareByNameInput, N as ShareByNameQuery, O as ShareInput, P as ShareLevel, f as SharingByNameMethod, g as SharingContractOptions, h as SharingDefOf, i as SharingInvite, j as SharingInviteByName, k as SharingLeave, l as SharingListMembers, m as SharingListShares, n as SharingMethodName, o as SharingMethods, p as SharingMode, q as SharingRemove, r as SharingSetLevel, t as SharingSetRole, u as SharingShare, v as SharingShareByName, w as SharingTag, x as SharingUnshare, T as TextFieldOf, U as UnshareInput, Q as UserLookupInput, s as search, e as sharing } from './sharing-DVa8W-yR.js';
6
+ export { q as AccessFrame, A as AuthenticationRefused, C as CLIENT_EVENTS, r as CallEnvelope, v as CallId, w as CallNotModified, x as CallReply, y as CallSuccess, z as CancelFrame, B as ChangedFrame, D as ChannelFrame, d as ClientEventName, E as ClientToServerEvents, F as CollectionDelta, G as CollectionFrame, I as CollectionItemsReply, J as CollectionItemsRequest, K as CollectionResumed, L as CollectionScopeRef, M as CollectionSnapshot, N as CollectionSubscribe, O as CollectionSubscribeReply, T as EntityFrame, U as EntityNotModified, V as EntityPatch, W as EntityRemove, X as EntityResult, Y as EntityRow, Z as EntitySubscribe, _ as EntitySubscribeReply, $ as EntityUnsubscribe, a0 as EntityUpdate, a1 as EventFrame, a2 as Failure, H as HandshakeAuth, k as HelloFrame, l as HelloLimits, m as HelloSubscriptionLimits, a3 as Ok, P as PROTOCOL_MISMATCH, g as PROTOCOL_VERSION, a4 as PresenceFrame, n as ProtocolMismatch, Q as QdHandshake, R as RESERVED_ROOM_PREFIXES, a5 as Revision, a7 as RevokeReason, a6 as RevokedFrame, a8 as RotateFrame, S as SERVER_EVENTS, a as SERVICE_TOPIC, f as ServerEventName, a9 as ServerToClientEvents, aa as StreamFrame, ab as StreamSubscribe, ac as StreamSubscribeReply, ad as Version, ae as WatchFrame, af as WireIndexRow, c as collectionRoom, b as collectionTopic, e as entityRoom, i as isAuthenticationRefused, o as isCallEnvelope, p as isCancel, h as isProtocolMismatch, j as isQdHandshake, s as streamRoom, t as topicRoom, u as userRoom } from './envelope-Cp3YcVxC.js';
7
7
  export { E as ERROR_CODES, a as ErrorCode, Q as QuickdrawError, R as RateLimitedErrorData, V as ValidationErrorData, W as WireError, b as WireIssue, f as fromWire, h as httpStatus, i as isErrorCode, t as toWire } from './errors-S-bxEIBC.js';
8
8
 
9
9
  /** The published version of `@fitzzero/quickdraw-core`. Kept in step with package.json. */
10
- declare const QUICKDRAW_VERSION = "5.0.0";
10
+ declare const QUICKDRAW_VERSION = "5.1.0";
11
11
 
12
12
  export { QUICKDRAW_VERSION };
package/dist/index.js CHANGED
@@ -4,7 +4,7 @@ import {
4
4
  SHARING_METHODS,
5
5
  crud,
6
6
  sharing
7
- } from "./chunk-5IC5VZ7T.js";
7
+ } from "./chunk-2UELNHDD.js";
8
8
  import {
9
9
  isCallEnvelope,
10
10
  isCancel
@@ -29,7 +29,7 @@ import {
29
29
  nullable,
30
30
  query,
31
31
  search
32
- } from "./chunk-B2UQ27GH.js";
32
+ } from "./chunk-CDKG4TFA.js";
33
33
  import {
34
34
  ACCESS_LEVELS,
35
35
  CLIENT_EVENTS,
@@ -50,7 +50,7 @@ import {
50
50
  streamRoom,
51
51
  topicRoom,
52
52
  userRoom
53
- } from "./chunk-7QIY2DDX.js";
53
+ } from "./chunk-VJTFXHOK.js";
54
54
  import {
55
55
  CHANNEL_DEFAULT_RATE,
56
56
  DEFAULT_COLLECTION_LIMIT,
@@ -59,7 +59,7 @@ import {
59
59
  STREAM_MAX_SEED,
60
60
  isScopedStream,
61
61
  via
62
- } from "./chunk-5YRQ26LF.js";
62
+ } from "./chunk-RT6OILOI.js";
63
63
  import {
64
64
  TODO_SCHEMA_VENDOR,
65
65
  hasJsonSchema,
@@ -80,14 +80,22 @@ import {
80
80
  } from "./chunk-4YO5H5ON.js";
81
81
 
82
82
  // src/contract/validateRealtime.ts
83
- var STREAM_KEYS = /* @__PURE__ */ new Set(["item", "scope", "seed", "volatile", "access"]);
83
+ var STREAM_KEYS = /* @__PURE__ */ new Set([
84
+ "item",
85
+ "scope",
86
+ "seed",
87
+ "volatile",
88
+ "access",
89
+ "describe"
90
+ ]);
84
91
  var CHANNEL_KEYS = /* @__PURE__ */ new Set([
85
92
  "payload",
86
93
  "ratePerSecond",
87
94
  "burst",
88
- "requires"
95
+ "requires",
96
+ "describe"
89
97
  ]);
90
- var EVENT_KEYS = /* @__PURE__ */ new Set(["payload"]);
98
+ var EVENT_KEYS = /* @__PURE__ */ new Set(["payload", "describe"]);
91
99
  var MAX_ROOM_LENGTH = 256;
92
100
  function isRecord(value) {
93
101
  return typeof value === "object" && value !== null && !Array.isArray(value);
@@ -130,6 +138,9 @@ function checkMember(kind, name, value, schemaKey, keys, fail) {
130
138
  fail(`${kind} "${name}" has an unknown option "${key}"; the options are ${quote(keys)}`);
131
139
  }
132
140
  }
141
+ if (value.describe !== void 0 && !isName(value.describe)) {
142
+ fail(`${kind} "${name}": describe must be a non-empty string`);
143
+ }
133
144
  return value;
134
145
  }
135
146
  function streamRoomProblem(access, scoped) {
@@ -320,6 +331,7 @@ var RESERVED_NAMES = /* @__PURE__ */ new Set([
320
331
  "then"
321
332
  ]);
322
333
  var DEFINITION_KEYS = /* @__PURE__ */ new Set([
334
+ "describe",
323
335
  "entity",
324
336
  "projections",
325
337
  "fields",
@@ -331,6 +343,7 @@ var DEFINITION_KEYS = /* @__PURE__ */ new Set([
331
343
  ]);
332
344
  var METHOD_KEYS = /* @__PURE__ */ new Set(["kind", "input", "output", "watch", "describe"]);
333
345
  var COLLECTION_KEYS = /* @__PURE__ */ new Set([
346
+ "describe",
334
347
  "scope",
335
348
  "item",
336
349
  "order",
@@ -588,6 +601,9 @@ function checkCollection(name, value, scope, fail) {
588
601
  if (value.access !== void 0 && !isAccessLevel(value.access)) {
589
602
  fail(`${owner}: access must be one of ${quote2(ACCESS_LEVELS)}`);
590
603
  }
604
+ if (value.describe !== void 0 && !isName2(value.describe)) {
605
+ fail(`${owner}: describe must be a non-empty string`);
606
+ }
591
607
  return Object.freeze({ ...value });
592
608
  }
593
609
  function checkCollections(value, scope, fail) {
@@ -618,6 +634,9 @@ function assembleContract(name, def) {
618
634
  fail("the definition must be an object");
619
635
  }
620
636
  checkKeys(def, DEFINITION_KEYS, "the contract", fail);
637
+ if (def.describe !== void 0 && !isName2(def.describe)) {
638
+ fail("describe must be a non-empty string");
639
+ }
621
640
  const entity = checkEntity(def.entity, fail);
622
641
  const hasEntity = entity !== void 0;
623
642
  const projections = checkProjections(def.projections, hasEntity, fail);
@@ -648,6 +667,7 @@ function assembleContract(name, def) {
648
667
  );
649
668
  return Object.freeze({
650
669
  name,
670
+ ...def.describe === void 0 ? {} : { describe: def.describe },
651
671
  entity,
652
672
  projections: Object.freeze(projections),
653
673
  fields: Object.freeze(checkFields(def.fields, hasEntity, fail)),
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([\"item\", \"scope\", \"seed\", \"volatile\", \"access\"]);\nconst CHANNEL_KEYS: ReadonlySet<string> = new Set([\n \"payload\",\n \"ratePerSecond\",\n \"burst\",\n \"requires\",\n]);\nconst EVENT_KEYS: ReadonlySet<string> = new Set([\"payload\"]);\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 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 \"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 \"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 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 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 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 * 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 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 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 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 } 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"]}