@fitzzero/quickdraw-core 5.0.1 → 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.
- package/README.md +303 -32
- package/dist/{admin-CBlTY0do.d.ts → admin-DKwkIh5i.d.ts} +2 -2
- package/dist/{adminSchemas-zji11V74.d.ts → adminSchemas-2DUA_hZ8.d.ts} +1 -1
- package/dist/{auth-CMyRkfjZ.d.ts → auth-BhWqdyb-.d.ts} +2 -2
- package/dist/{caller-BqCYnpmC.d.ts → caller-CXTFswBO.d.ts} +27 -5
- package/dist/{chunk-2XJFNVHW.js → chunk-2PWMUVC7.js} +1 -1
- package/dist/{chunk-2XJFNVHW.js.map → chunk-2PWMUVC7.js.map} +1 -1
- package/dist/{chunk-3JNMVB2V.js → chunk-2UELNHDD.js} +2 -2
- package/dist/{chunk-HQ6WIRE2.js → chunk-3674EIRT.js} +4 -4
- package/dist/{chunk-NS5PUHIZ.js → chunk-A6DJBGOG.js} +130 -23
- package/dist/chunk-A6DJBGOG.js.map +1 -0
- package/dist/{chunk-ZACRRYWL.js → chunk-JZBCLNDU.js} +4 -4
- package/dist/{chunk-O2PWC2YW.js → chunk-KNDDCVQJ.js} +3 -3
- package/dist/{chunk-5YRQ26LF.js → chunk-RT6OILOI.js} +1 -1
- package/dist/chunk-RT6OILOI.js.map +1 -0
- package/dist/{chunk-WVIRXYI4.js → chunk-VJTFXHOK.js} +2 -2
- package/dist/{chunk-WVIRXYI4.js.map → chunk-VJTFXHOK.js.map} +1 -1
- package/dist/chunk-XNLWBZIG.js +9 -0
- package/dist/chunk-XNLWBZIG.js.map +1 -0
- package/dist/cli/quickdraw-docs.js +241 -27
- package/dist/cli/quickdraw-docs.js.map +1 -1
- package/dist/client/index.d.ts +7 -7
- package/dist/client/index.js +4 -4
- package/dist/{clientTypes-DuZW_8mb.d.ts → clientTypes-Bc-G8n-U.d.ts} +3 -3
- package/dist/{connection-DuN8GvcD.d.ts → connection-Cr1BU07W.d.ts} +2 -2
- package/dist/{createServer-CGsJlxM8.d.ts → createServer-CP9eDHZZ.d.ts} +30 -9
- package/dist/{createTestApp-Cg2CZa1g.d.ts → createTestApp-UKVGEmOf.d.ts} +6 -6
- package/dist/{envelope-nf5eGB-a.d.ts → envelope-Cp3YcVxC.d.ts} +1 -1
- package/dist/{http-D3fSFQ57.d.ts → http-Djj2Inuu.d.ts} +6 -6
- package/dist/index.d.ts +6 -6
- package/dist/index.js +26 -6
- package/dist/index.js.map +1 -1
- package/dist/{infer-Dw21kmLw.d.ts → infer-Teo1xpsd.d.ts} +17 -0
- package/dist/{metrics-C0WvB7-I.d.ts → metrics-BdBu5o8G.d.ts} +2 -2
- package/dist/prisma/index.d.ts +4 -4
- package/dist/server/auth/index.d.ts +3 -3
- package/dist/server/index.d.ts +47 -26
- package/dist/server/index.js +62 -36
- package/dist/server/index.js.map +1 -1
- package/dist/server/mcp/index.d.ts +51 -11
- package/dist/server/mcp/index.js +129 -8
- package/dist/server/mcp/index.js.map +1 -1
- package/dist/server/otel.d.ts +3 -3
- package/dist/{sharing-CoreezAq.d.ts → sharing-DVa8W-yR.d.ts} +3 -3
- package/dist/testing/client.d.ts +13 -13
- package/dist/testing/client.js +5 -5
- package/dist/testing/index.d.ts +156 -12
- package/dist/testing/index.js +1036 -21
- package/dist/testing/index.js.map +1 -1
- package/dist/testing/mock.d.ts +5 -5
- package/dist/testing/mock.js +4 -4
- package/dist/{types-Bwg3kIEc.d.ts → types-Cu0vmx7c.d.ts} +8 -2
- package/dist/utils/index.d.ts +1 -1
- package/package.json +1 -1
- package/dist/chunk-5YRQ26LF.js.map +0 -1
- package/dist/chunk-NS5PUHIZ.js.map +0 -1
- /package/dist/{chunk-3JNMVB2V.js.map → chunk-2UELNHDD.js.map} +0 -0
- /package/dist/{chunk-HQ6WIRE2.js.map → chunk-3674EIRT.js.map} +0 -0
- /package/dist/{chunk-ZACRRYWL.js.map → chunk-JZBCLNDU.js.map} +0 -0
- /package/dist/{chunk-O2PWC2YW.js.map → chunk-KNDDCVQJ.js.map} +0 -0
|
@@ -347,6 +347,8 @@ interface CollectionWhere {
|
|
|
347
347
|
}
|
|
348
348
|
/** Any collection of any contract, as `defineContract` stores it. */
|
|
349
349
|
interface CollectionDef {
|
|
350
|
+
/** What the list holds, in a sentence or two, for the generated docs. */
|
|
351
|
+
readonly describe?: string | undefined;
|
|
350
352
|
/** A string column of the entity, or `via(...)` for a junction table. */
|
|
351
353
|
readonly scope: string | ViaScope;
|
|
352
354
|
/** The projection each item is sent as: `"entity"` or a named projection. */
|
|
@@ -434,6 +436,8 @@ interface StreamDef<Item extends StandardSchemaV1 = StandardSchemaV1> {
|
|
|
434
436
|
readonly volatile?: boolean;
|
|
435
437
|
/** Who may subscribe. Without it the stream is closed. */
|
|
436
438
|
readonly access?: StreamAccess;
|
|
439
|
+
/** What the stream carries, in a sentence or two, for the generated docs. */
|
|
440
|
+
readonly describe?: string;
|
|
437
441
|
}
|
|
438
442
|
/**
|
|
439
443
|
* Where a channel requirement finds its row id or scope value in the parsed
|
|
@@ -498,10 +502,14 @@ interface ChannelDef<Payload extends StandardSchemaV1 = StandardSchemaV1> {
|
|
|
498
502
|
readonly burst?: number;
|
|
499
503
|
/** What the sender must already be subscribed to, or the app room it must be in. */
|
|
500
504
|
readonly requires?: ChannelRequires;
|
|
505
|
+
/** What a message says, in a sentence or two, for the generated docs. */
|
|
506
|
+
readonly describe?: string;
|
|
501
507
|
}
|
|
502
508
|
/** A typed custom room event, delivered as `qd:event` (RFC 0003 section 8.3). */
|
|
503
509
|
interface EventDef<Payload extends StandardSchemaV1 = StandardSchemaV1> {
|
|
504
510
|
readonly payload: Payload;
|
|
511
|
+
/** What the event announces, in a sentence or two, for the generated docs. */
|
|
512
|
+
readonly describe?: string;
|
|
505
513
|
}
|
|
506
514
|
/** True when a stream has one feed per scope value; false for a global stream. */
|
|
507
515
|
declare function isScopedStream(def: Pick<StreamDef, "scope">): boolean;
|
|
@@ -521,6 +529,11 @@ interface ChannelDefinition extends Omit<ChannelDef, "requires"> {
|
|
|
521
529
|
}
|
|
522
530
|
/** The second argument of {@link defineContract}. */
|
|
523
531
|
interface ContractDefinition {
|
|
532
|
+
/**
|
|
533
|
+
* What the service is for, in a sentence or two. The generated API docs
|
|
534
|
+
* lead the service's page with it and list it in their index.
|
|
535
|
+
*/
|
|
536
|
+
readonly describe?: string;
|
|
524
537
|
/**
|
|
525
538
|
* The full row; its output must contain `id: string`. Omit it for a service
|
|
526
539
|
* without a model, which then has no projections, fields or collections.
|
|
@@ -567,6 +580,8 @@ type MemberOf<Def, Key extends string, Absent> = Def extends {
|
|
|
567
580
|
interface Contract<Name extends string = string, Def extends ContractDefinition = ContractDefinition> {
|
|
568
581
|
/** The service name, unchanged on the wire and in stored grants. */
|
|
569
582
|
readonly name: Name;
|
|
583
|
+
/** What the service is for; absent when the definition has none. */
|
|
584
|
+
readonly describe?: string;
|
|
570
585
|
readonly entity: MemberOf<Def, "entity", undefined>;
|
|
571
586
|
readonly projections: MemberOf<Def, "projections", Empty>;
|
|
572
587
|
readonly fields: MemberOf<Def, "fields", Empty>;
|
|
@@ -579,6 +594,7 @@ interface Contract<Name extends string = string, Def extends ContractDefinition
|
|
|
579
594
|
/** Any contract. Every contract `defineContract` returns is assignable to it. */
|
|
580
595
|
interface AnyContract {
|
|
581
596
|
readonly name: string;
|
|
597
|
+
readonly describe?: string;
|
|
582
598
|
readonly entity: RowSchema | undefined;
|
|
583
599
|
readonly projections: {
|
|
584
600
|
readonly [name: string]: RowSchema;
|
|
@@ -615,6 +631,7 @@ type IndexRow<Item, Fields> = Pick<Item, Extract<keyof Item, "id" | Fields>>;
|
|
|
615
631
|
type ColumnOf<Row> = [Row] extends [never] ? string : keyof Row & string;
|
|
616
632
|
type ScopeColumnOf<Row> = [Row] extends [never] ? string : StringColumn<Row> & string;
|
|
617
633
|
interface CollectionContext<Row, Entity, Projections, Item, Index> {
|
|
634
|
+
readonly describe?: string | undefined;
|
|
618
635
|
readonly scope: NoInfer<ViaScope | ScopeColumnOf<Row>>;
|
|
619
636
|
readonly item: Item;
|
|
620
637
|
readonly order: NoInfer<OrderBy<ColumnOf<Row>>>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { k as MethodKind } from './infer-
|
|
1
|
+
import { k as MethodKind } from './infer-Teo1xpsd.js';
|
|
2
2
|
import { a as ErrorCode } from './errors-S-bxEIBC.js';
|
|
3
|
-
import { T as Transport } from './types-
|
|
3
|
+
import { T as Transport } from './types-Cu0vmx7c.js';
|
|
4
4
|
|
|
5
5
|
/** How a call ended: `"ok"`, `"not-modified"`, or the error code it failed with. */
|
|
6
6
|
type CallOutcome = "ok" | "not-modified" | ErrorCode;
|
package/dist/prisma/index.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { L as Logger } from '../logger-BY28acW-.js';
|
|
2
|
-
export { C as CountArgs, F as FindManyArgs, c as StatementCount, S as StorageAdapter, a as StorageRow, b as StorageWhere, s as storageOf } from '../caller-
|
|
3
|
-
import '../envelope-
|
|
4
|
-
import '../infer-
|
|
2
|
+
export { C as CountArgs, F as FindManyArgs, c as StatementCount, S as StorageAdapter, a as StorageRow, b as StorageWhere, s as storageOf } from '../caller-CXTFswBO.js';
|
|
3
|
+
import '../envelope-Cp3YcVxC.js';
|
|
4
|
+
import '../infer-Teo1xpsd.js';
|
|
5
5
|
import '../errors-S-bxEIBC.js';
|
|
6
|
-
import '../types-
|
|
6
|
+
import '../types-Cu0vmx7c.js';
|
|
7
7
|
|
|
8
8
|
/** Options of {@link trackPrisma}. */
|
|
9
9
|
interface TrackPrismaOptions {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { L as Logger } from '../../logger-BY28acW-.js';
|
|
2
2
|
import { IncomingHttpHeaders, IncomingMessage, ServerResponse } from 'node:http';
|
|
3
|
-
import { M as MaybePromise, P as Principal } from '../../types-
|
|
4
|
-
import { b as AuthenticateRequest, H as HttpRequest } from '../../auth-
|
|
5
|
-
import '../../infer-
|
|
3
|
+
import { M as MaybePromise, P as Principal } from '../../types-Cu0vmx7c.js';
|
|
4
|
+
import { b as AuthenticateRequest, H as HttpRequest } from '../../auth-BhWqdyb-.js';
|
|
5
|
+
import '../../infer-Teo1xpsd.js';
|
|
6
6
|
import 'socket.io';
|
|
7
7
|
|
|
8
8
|
/**
|
package/dist/server/index.d.ts
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
import { J as AnyContract, at as ProjectionName, ai as FullProjectionOf, ac as CollectionName, ap as MethodName, d as StandardSchemaV1, c as InferOutput, N as NullableProjection, P as ProjectionList, aq as MethodOf, as as ParsedInputOf, ao as KindOf, A as AccessLevel, af as EntityOf, ar as OutputOf } from '../infer-
|
|
2
|
-
import { M as ModelName, v as PolicyFor, w as RowForms, x as AccessFor, H as HandlerContext, y as ModelColumn, z as WatchAccess, B as PublicAccess, E as HandlerArgs, G as CustomAccess, I as ShareMode, J as ChannelOptions, K as StreamOptions, u as RoomLeaveHandler, L as ChannelsRequired,
|
|
3
|
-
export { aI as ANY_FIELD, aA as AccessForm, aB as AccessRequest, _ as AffectsLink, p as AnyContext, A as AnyService, r as AppRooms, aC as AuthenticatedAccess, aq as CallOptions,
|
|
4
|
-
import { S as ServerOptions, Q as QuickdrawServer } from '../createServer-
|
|
5
|
-
export { C as ClusterClient,
|
|
6
|
-
import { ad as Version } from '../envelope-
|
|
7
|
-
import { Q as QuickdrawTypes, D as DbOf, c as PrincipalOf, M as MaybePromise, b as McpContextOf, C as ContextExtensionOf, P as Principal } from '../types-
|
|
8
|
-
export { a as McpContext, T as Transport } from '../types-
|
|
9
|
-
import { a as DispatcherOptions, D as Dispatcher, c as DispatcherCollections } from '../http-
|
|
10
|
-
export { o as AccessChange, p as AccessChangeListener, A as AccessOptions, d as ChangeLogOptions, C as ContractOfServices, j as DEFAULT_LIMITS, f as DbOfServices, h as DispatchRequest, i as DispatchResult, n as DispatcherAccess, k as DispatcherLimits, s as HttpMiddleware, H as HttpRouter, u as HttpRouterOptions, b as HttpTransportOptions, L as LimitsOptions, l as PipelineOptions, P as PrincipalOfServices, R as RegisteredMethod, g as Registry, S as SharedData, m as SubscriptionLimits, T as TrackingOptions, V as VersionRequest, q as VersionSource, e as createDispatcher, r as createHttpRouter, t as toCallReply } from '../http-
|
|
11
|
-
import { l as CrudMethodName, d as CrudContractOptions, S as ScalarFieldOf, N as NumberFieldOf, m as CrudMethods, H as AdminMethodsOf, w as AdminContractOptions, G as AdminMethods } from '../admin-
|
|
12
|
-
import { S as SearchContractOptions, T as TextFieldOf, b as SearchMethods, n as SharingMethodName, f as SharingByNameMethod, g as SharingContractOptions, o as SharingMethods } from '../sharing-
|
|
13
|
-
import { x as AdminNeverWritable, l as AdminFieldConfig } from '../adminSchemas-
|
|
14
|
-
export { a as CallOutcome, C as CallRecord } from '../metrics-
|
|
15
|
-
export { b as AuthenticateRequest, A as AuthenticateResult, c as HttpAuthenticateRequest, d as HttpCredentialSource, S as ServerAuth, e as ServiceAccessSource, a as ServiceGrants, f as SocketAuthenticateRequest, r as recordSocketSession } from '../auth-
|
|
1
|
+
import { J as AnyContract, at as ProjectionName, ai as FullProjectionOf, ac as CollectionName, ap as MethodName, d as StandardSchemaV1, c as InferOutput, N as NullableProjection, P as ProjectionList, aq as MethodOf, as as ParsedInputOf, ao as KindOf, A as AccessLevel, af as EntityOf, ar as OutputOf } from '../infer-Teo1xpsd.js';
|
|
2
|
+
import { M as ModelName, v as PolicyFor, w as RowForms, x as AccessFor, H as HandlerContext, y as ModelColumn, z as WatchAccess, B as PublicAccess, E as HandlerArgs, G as CustomAccess, I as ShareMode, J as ChannelOptions, K as StreamOptions, u as RoomLeaveHandler, L as ChannelsRequired, h as Service, N as BaseContext, O as CallerFor, l as RunContext, m as RunOptions, o as StreamHandle, P as Presence, n as ServerRooms, Q as AccessPolicy, T as AnyAccessPolicy, V as PolicyColumns, X as PolicyForeign, Y as PolicyTools, k as AccessFilter, Z as RowAccess, q as AccessEngine, b as StorageWhere } from '../caller-CXTFswBO.js';
|
|
3
|
+
export { aI as ANY_FIELD, aA as AccessForm, aB as AccessRequest, _ as AffectsLink, p as AnyContext, A as AnyService, r as AppRooms, aC as AuthenticatedAccess, aq as CallOptions, d as Caller, a9 as ChannelAccess, aa as ChannelContext, ab as ChannelHandler, ac as ChannelImplementation, ad as ChannelRoomOf, a4 as CollectionScope, a6 as ContextRooms, a7 as ContextServices, C as CountArgs, a3 as DEFAULT_BULK_THRESHOLD, i as DevWarning, D as DevWarningError, j as DevWarningKind, aD as EntryAccess, F as FindManyArgs, f as FlushInfo, e as FlushSink, at as ForeignColumns, au as ForeignColumnsOf, aE as IdKeyOf, aF as IdSelector, av as MembershipRead, ar as MethodCaller, aM as N_PLUS_ONE_STATEMENTS, aw as ParentLink, ax as PolicyKind, ay as PolicyReads, $ as ProjectedOutput, a0 as Projection, ae as RoomLeave, af as RoomLeaveReason, ag as RoomLeft, ah as RoomTarget, az as RowLevel, R as RowLevels, aG as ScopeAccess, aH as ServiceAccess, as as ServiceCaller, ai as ServiceChannel, a5 as ServiceCollection, g as ServiceMethod, aj as ServiceStream, c as StatementCount, S as StorageAdapter, a as StorageRow, ak as StreamImplementation, al as StreamPushArgs, am as StreamPushManyArgs, an as StreamSeed, ao as StreamSeedContext, t as StreamSubscriptions, ap as StreamValidation, a1 as TierGroup, a2 as Tiers, a8 as TouchOptions, aJ as UnitOfWork, U as UnitOfWorkFactory, aK as UnitOfWorkScope, W as WriteRecord, aL as formatDevWarning, s as storageOf } from '../caller-CXTFswBO.js';
|
|
4
|
+
import { S as ServerOptions, Q as QuickdrawServer } from '../createServer-CP9eDHZZ.js';
|
|
5
|
+
export { C as ClusterClient, u as ClusterOptions, D as DEFAULT_STALL_INTERVAL_MS, e as DEFAULT_STALL_MAX_MS, f as DEFAULT_STALL_THRESHOLD_MS, p as DisconnectUserOptions, E as EntitySubscription, a as EntitySubscriptions, H as HttpApp, I as IoRedisLike, L as LegacyReply, t as LegacyWireOptions, M as MIN_STALL_INTERVAL_MS, m as QuickdrawIo, n as QuickdrawServerSocket, o as QuickdrawSocketData, y as RateLimitOptions, z as RateLimiter, R as RotateOptions, g as STALL_RESOLUTION_MS, b as ScopeSubscription, c as ScopeSubscriptions, l as ServerOnlyOptions, h as SlowMethod, q as SocketCors, r as SocketOptions, s as SocketRateLimitOptions, i as StallReport, j as StallWatchdogOptions, T as TopicWatch, d as TopicWatches, w as applyRateLimitMiddleware, v as createRateLimiter, k as createServer, x as createTieredRateLimiter } from '../createServer-CP9eDHZZ.js';
|
|
6
|
+
import { ad as Version } from '../envelope-Cp3YcVxC.js';
|
|
7
|
+
import { Q as QuickdrawTypes, D as DbOf, d as PrincipalKindOf, c as PrincipalOf, M as MaybePromise, b as McpContextOf, C as ContextExtensionOf, P as Principal } from '../types-Cu0vmx7c.js';
|
|
8
|
+
export { a as McpContext, T as Transport } from '../types-Cu0vmx7c.js';
|
|
9
|
+
import { a as DispatcherOptions, D as Dispatcher, c as DispatcherCollections } from '../http-Djj2Inuu.js';
|
|
10
|
+
export { o as AccessChange, p as AccessChangeListener, A as AccessOptions, d as ChangeLogOptions, C as ContractOfServices, j as DEFAULT_LIMITS, f as DbOfServices, h as DispatchRequest, i as DispatchResult, n as DispatcherAccess, k as DispatcherLimits, s as HttpMiddleware, H as HttpRouter, u as HttpRouterOptions, b as HttpTransportOptions, L as LimitsOptions, l as PipelineOptions, P as PrincipalOfServices, R as RegisteredMethod, g as Registry, S as SharedData, m as SubscriptionLimits, T as TrackingOptions, V as VersionRequest, q as VersionSource, e as createDispatcher, r as createHttpRouter, t as toCallReply } from '../http-Djj2Inuu.js';
|
|
11
|
+
import { l as CrudMethodName, d as CrudContractOptions, S as ScalarFieldOf, N as NumberFieldOf, m as CrudMethods, H as AdminMethodsOf, w as AdminContractOptions, G as AdminMethods } from '../admin-DKwkIh5i.js';
|
|
12
|
+
import { S as SearchContractOptions, T as TextFieldOf, b as SearchMethods, n as SharingMethodName, f as SharingByNameMethod, g as SharingContractOptions, o as SharingMethods } from '../sharing-DVa8W-yR.js';
|
|
13
|
+
import { x as AdminNeverWritable, l as AdminFieldConfig } from '../adminSchemas-2DUA_hZ8.js';
|
|
14
|
+
export { a as CallOutcome, C as CallRecord } from '../metrics-BdBu5o8G.js';
|
|
15
|
+
export { b as AuthenticateRequest, A as AuthenticateResult, c as HttpAuthenticateRequest, d as HttpCredentialSource, S as ServerAuth, e as ServiceAccessSource, a as ServiceGrants, f as SocketAuthenticateRequest, r as recordSocketSession } from '../auth-BhWqdyb-.js';
|
|
16
16
|
import { Server } from 'socket.io';
|
|
17
17
|
import { L as Logger } from '../logger-BY28acW-.js';
|
|
18
18
|
import 'node:http';
|
|
@@ -34,16 +34,6 @@ declare const STREAM_MAX_SCOPES = 10000;
|
|
|
34
34
|
/** The most stream feeds one socket may subscribe to at once. */
|
|
35
35
|
declare const MAX_STREAMS_PER_SOCKET = 500;
|
|
36
36
|
|
|
37
|
-
/** 4.x's `ServiceResponse`, the shape every reply of the shim takes. */
|
|
38
|
-
type LegacyReply = {
|
|
39
|
-
readonly success: true;
|
|
40
|
-
readonly data: unknown;
|
|
41
|
-
} | {
|
|
42
|
-
readonly success: false;
|
|
43
|
-
readonly error: string;
|
|
44
|
-
readonly code: number;
|
|
45
|
-
};
|
|
46
|
-
|
|
47
37
|
/**
|
|
48
38
|
* A JSON column's value as a database client types it: structurally
|
|
49
39
|
* Prisma's `JsonValue` (and its `InputJsonValue` objects and arrays). A row
|
|
@@ -252,6 +242,16 @@ interface MutationOptions {
|
|
|
252
242
|
type MethodImplementation<T extends QuickdrawTypes, C extends AnyContract, M extends MethodName<C>, A, Rows extends RowForms = "all", Proj = Empty$2> = {
|
|
253
243
|
/** Who may call: `"public"`, `"authenticated"`, `{ service }`, `{ entry }`, `{ scope, of, id }` or `custom(fn)`. */
|
|
254
244
|
readonly access: AccessValue<A, MethodAccess<T, C, M, Rows>>;
|
|
245
|
+
/**
|
|
246
|
+
* The kinds of principal that may call this method (RFC 0003 section
|
|
247
|
+
* 4.1), within its service's `kinds` (or the app's): `kinds: ["user"]`
|
|
248
|
+
* keeps an agent's token out of a method that mints tokens. A principal
|
|
249
|
+
* of another kind, or without a `kind`, gets `FORBIDDEN` before `access`
|
|
250
|
+
* is asked, whatever its grants; an anonymous caller is left to `access`.
|
|
251
|
+
* Not on a `"public"` method, which a caller of any kind could call
|
|
252
|
+
* signed out. Leave it out for the service's list.
|
|
253
|
+
*/
|
|
254
|
+
readonly kinds?: readonly PrincipalKindOf<T>[];
|
|
255
255
|
/**
|
|
256
256
|
* Runs the method. For a projection output it returns the database row
|
|
257
257
|
* (or rows, or `null`), which the framework projects: only the
|
|
@@ -377,6 +377,18 @@ interface ServiceDefinition<T extends QuickdrawTypes, C extends AnyContract, A,
|
|
|
377
377
|
* service (RFC 0003 section 4.1). Default `true`.
|
|
378
378
|
*/
|
|
379
379
|
readonly adminBypass?: boolean;
|
|
380
|
+
/**
|
|
381
|
+
* The kinds of principal that may call the service's methods and
|
|
382
|
+
* subscribe to its live data (RFC 0003 section 4.1): `kinds: ["user"]`.
|
|
383
|
+
* Within the app's `initQuickdraw({ kinds })`, which the service takes
|
|
384
|
+
* when it leaves this out; a method's own `kinds` narrows it further. A
|
|
385
|
+
* principal of another kind, or without a `kind`, gets `FORBIDDEN` before
|
|
386
|
+
* any access form is asked, and a service-wide `Admin` grant does not
|
|
387
|
+
* pass it; an anonymous caller is left to the form. Its entity, collection,
|
|
388
|
+
* topic and stream subscriptions refuse such a principal the same way, and
|
|
389
|
+
* its channels drop its messages.
|
|
390
|
+
*/
|
|
391
|
+
readonly kinds?: readonly PrincipalKindOf<T>[];
|
|
380
392
|
}
|
|
381
393
|
/** `qd.defineService`, typed by the app's `QuickdrawTypes`. */
|
|
382
394
|
type DefineService<T extends QuickdrawTypes> = <C extends AnyContract, const Model extends ModelName<DbOf<T>> | undefined = undefined, Policy extends PolicyFor<DbOf<T>, Model> | undefined = undefined, const A extends MethodKeys<C> = AccessMap<T, C, RowFormsOf<Model, Policy>>, const Proj = Empty$2>(contract: C, definition: ServiceDefinition<T, C, A, Model, Policy, Proj> & CollectionsRequired<C> & ChannelsRequired<C>) => Service<T, C>;
|
|
@@ -390,6 +402,15 @@ type ContextFactory<T extends QuickdrawTypes> = (base: BaseContext<PrincipalOf<T
|
|
|
390
402
|
interface InitOptions<T extends QuickdrawTypes> {
|
|
391
403
|
/** Adds the app's fields to every handler's `ctx`. Required when the app's types declare `context`. */
|
|
392
404
|
readonly context?: ContextFactory<T>;
|
|
405
|
+
/**
|
|
406
|
+
* The kinds of principal every service this instance defines admits
|
|
407
|
+
* (RFC 0003 section 4.1), so a new service starts closed to the rest:
|
|
408
|
+
* `kinds: ["user", "agent"]`. A service's `kinds`, and a method's, may
|
|
409
|
+
* only narrow it. A principal of another kind, or without a `kind`, gets
|
|
410
|
+
* `FORBIDDEN` before any access form or `Admin` grant is asked; an
|
|
411
|
+
* anonymous caller is left to the form. Leave it out to admit every kind.
|
|
412
|
+
*/
|
|
413
|
+
readonly kinds?: readonly PrincipalKindOf<T>[];
|
|
393
414
|
}
|
|
394
415
|
/** `initQuickdraw`'s arguments: the options are required when `T` declares `context`. */
|
|
395
416
|
type InitArgs<T extends QuickdrawTypes> = T extends {
|
|
@@ -1557,4 +1578,4 @@ declare function decryptIfEncrypted(value: string): string;
|
|
|
1557
1578
|
/** Safe wrapper that returns `null` instead of throwing on invalid/stale ciphertext. */
|
|
1558
1579
|
declare function tryDecrypt(ciphertext: string, logger?: Logger): string | null;
|
|
1559
1580
|
|
|
1560
|
-
export { ADMIN_HIDDEN_FIELDS, AccessEngine, AccessFilter, AccessFor, type AccessMap, AccessPolicy, type AdminAccess, type AdminContract, type AdminDefaultAccess, type AdminFieldOf, type AdminFieldOverride, type AdminHandlersOptions, type AdminImplementations, type AdminOnCommitted, type AdminOnWrite, type AdminOutputOf, type AdminWrite, type AffectsOption, AnyAccessPolicy, BaseContext, type BasicAccessEngineOptions, CHANNEL_ABUSE_MULTIPLIER, CHANNEL_ABUSE_WINDOW_MS, CallerFor, ChannelOptions, ChannelsRequired, type CollectionOption, type CollectionOptions, type CollectionsRequired, ContextExtensionOf, type ContextFactory, type CrudAccess, type CrudCreateOf, type CrudHandlersOptions, type CrudImplementations, type CrudKindOf, type CrudMethodsOf, type CrudPrepare, CustomAccess, DbOf, type DefineService, Dispatcher, DispatcherCollections, DispatcherOptions, type EnvValidationResult, HandlerArgs, HandlerContext, type HandlerOutputOf, type HandlerRow, INDEX_MAX_ROWS, type InheritOptions, type InitArgs, type InitOptions, type JsonAclOptions, type JsonColumnValue, type KitContext, type KitHandler, type KitHandlerArgs,
|
|
1581
|
+
export { ADMIN_HIDDEN_FIELDS, AccessEngine, AccessFilter, AccessFor, type AccessMap, AccessPolicy, type AdminAccess, type AdminContract, type AdminDefaultAccess, type AdminFieldOf, type AdminFieldOverride, type AdminHandlersOptions, type AdminImplementations, type AdminOnCommitted, type AdminOnWrite, type AdminOutputOf, type AdminWrite, type AffectsOption, AnyAccessPolicy, BaseContext, type BasicAccessEngineOptions, CHANNEL_ABUSE_MULTIPLIER, CHANNEL_ABUSE_WINDOW_MS, CallerFor, ChannelOptions, ChannelsRequired, type CollectionOption, type CollectionOptions, type CollectionsRequired, ContextExtensionOf, type ContextFactory, type CrudAccess, type CrudCreateOf, type CrudHandlersOptions, type CrudImplementations, type CrudKindOf, type CrudMethodsOf, type CrudPrepare, CustomAccess, DbOf, type DefineService, Dispatcher, DispatcherCollections, DispatcherOptions, type EnvValidationResult, HandlerArgs, HandlerContext, type HandlerOutputOf, type HandlerRow, INDEX_MAX_ROWS, type InheritOptions, type InitArgs, type InitOptions, type JsonAclOptions, type JsonColumnValue, type KitContext, type KitHandler, type KitHandlerArgs, MAX_APP_ROOMS, MAX_ITEM_IDS, MAX_STREAMS_PER_SOCKET, MaybePromise, McpContextOf, type MembersOptions, type MethodAccess, type MethodImplementation, ModelColumn, ModelName, type NextOrdinalOptions, ORDINAL_STEP, PRESENCE_MAX_LAST_SEEN, PolicyFor, PolicyTools, Presence, Principal, type PrincipalFor, PrincipalKindOf, PrincipalOf, type ProjectCheck, type ProjectionOption, PublicAccess, type Quickdraw, QuickdrawServer, QuickdrawTypes, RESUME_MAX_AGE_MS, RESUME_MAX_DELTAS, type RedisAdapterOptions, type RedisAdapterResult, type ResolverMembership, type ResolverOptions, type ResolverReads, RoomLeaveHandler, RowAccess, type RowFor, RowForms, type RowFormsOf, RunContext, RunOptions, STREAM_MAX_SCOPES, type SearchAccess, type SearchContract, type SearchHandlersOptions, type SearchIdsOptions, type SearchImplementations, type SearchMethodsOf, type SearchStrategy, type SearchStrategyContext, ServerOptions, ServerRooms, Service, type ServiceDefinition, ShareMode, type SharingAccess, type SharingByNameOf, type SharingChange, type SharingChangeKind, type SharingContract, type SharingDefaultAccess, type SharingHandlersOptions, type SharingImplementations, type SharingKindOf, type SharingMethodsOf, type SharingOnChange, type SharingOptionsArgs, type SharingResolveUser, type SharingUserLookup, StorageWhere, StreamHandle, StreamOptions, type ValidateEnvOptions, WatchAccess, admin, anyOf, checkEnv, createBasicAccessEngine, crud, custom, decrypt, decryptIfEncrypted, displayNameOf, encrypt, everyone, inherit, initQuickdraw, isEncrypted, isRedisAdapterAvailable, jsonAcl, labelOf, meetsLevel, members, nextOrdinal, owner, requireEnv, requireRow, resolver, search, serviceGrant, setupRedisAdapter, sharing, tryDecrypt, validateEnv };
|
package/dist/server/index.js
CHANGED
|
@@ -51,6 +51,7 @@ import {
|
|
|
51
51
|
members,
|
|
52
52
|
membersWhere,
|
|
53
53
|
membershipOf,
|
|
54
|
+
narrowKinds,
|
|
54
55
|
orderByOf,
|
|
55
56
|
projectRow,
|
|
56
57
|
projectedOutput,
|
|
@@ -60,7 +61,7 @@ import {
|
|
|
60
61
|
serviceGrant,
|
|
61
62
|
strip,
|
|
62
63
|
watchAdapterClients
|
|
63
|
-
} from "../chunk-
|
|
64
|
+
} from "../chunk-A6DJBGOG.js";
|
|
64
65
|
import {
|
|
65
66
|
DevWarningError,
|
|
66
67
|
N_PLUS_ONE_STATEMENTS,
|
|
@@ -74,7 +75,7 @@ import {
|
|
|
74
75
|
crudSpecOf,
|
|
75
76
|
sharing,
|
|
76
77
|
sharingSpecOf
|
|
77
|
-
} from "../chunk-
|
|
78
|
+
} from "../chunk-2UELNHDD.js";
|
|
78
79
|
import "../chunk-QEKVYG5F.js";
|
|
79
80
|
import {
|
|
80
81
|
abortError,
|
|
@@ -83,7 +84,7 @@ import {
|
|
|
83
84
|
kitRuntimeOf,
|
|
84
85
|
outputSchemaOf,
|
|
85
86
|
schemaOutputOf
|
|
86
|
-
} from "../chunk-
|
|
87
|
+
} from "../chunk-2PWMUVC7.js";
|
|
87
88
|
import "../chunk-DD4SKCNO.js";
|
|
88
89
|
import {
|
|
89
90
|
recordSocketSession,
|
|
@@ -108,13 +109,13 @@ import {
|
|
|
108
109
|
entityRoom,
|
|
109
110
|
isAccessLevel,
|
|
110
111
|
reservedRoomPrefix
|
|
111
|
-
} from "../chunk-
|
|
112
|
+
} from "../chunk-VJTFXHOK.js";
|
|
112
113
|
import {
|
|
113
114
|
CHANNEL_DEFAULT_RATE,
|
|
114
115
|
DEFAULT_COLLECTION_LIMIT,
|
|
115
116
|
DEFAULT_COLLECTION_MAX_LIMIT,
|
|
116
117
|
isScopedStream
|
|
117
|
-
} from "../chunk-
|
|
118
|
+
} from "../chunk-RT6OILOI.js";
|
|
118
119
|
import "../chunk-47AEXVDM.js";
|
|
119
120
|
import "../chunk-Z2LZ7IZ7.js";
|
|
120
121
|
import {
|
|
@@ -385,7 +386,7 @@ function checkChannelAccess(owner2, access, fail5) {
|
|
|
385
386
|
}
|
|
386
387
|
return Object.freeze({ service: access.service });
|
|
387
388
|
}
|
|
388
|
-
function checkChannel(service, name, def, entry, fail5) {
|
|
389
|
+
function checkChannel(service, name, def, entry, kinds, fail5) {
|
|
389
390
|
const owner2 = `channel "${name}"`;
|
|
390
391
|
const implementation = typeof entry === "function" ? { handler: entry } : entry;
|
|
391
392
|
if (!isRecord2(implementation) || typeof implementation.handler !== "function") {
|
|
@@ -407,10 +408,11 @@ function checkChannel(service, name, def, entry, fail5) {
|
|
|
407
408
|
burst: def.burst ?? Math.max(1, ratePerSecond * 2),
|
|
408
409
|
requires: compileRequires(def),
|
|
409
410
|
access: checkChannelAccess(owner2, implementation.access, fail5),
|
|
411
|
+
kinds,
|
|
410
412
|
handler: implementation.handler
|
|
411
413
|
});
|
|
412
414
|
}
|
|
413
|
-
function compileChannels(contract, value, fail5) {
|
|
415
|
+
function compileChannels(contract, value, kinds, fail5) {
|
|
414
416
|
const declared = Object.entries(contract.channels);
|
|
415
417
|
if (value === void 0 && declared.length === 0) {
|
|
416
418
|
return /* @__PURE__ */ new Map();
|
|
@@ -423,12 +425,13 @@ function compileChannels(contract, value, fail5) {
|
|
|
423
425
|
fail5(`channels has no implementation for ${missing2.map((name) => `"${name}"`).join(", ")}`);
|
|
424
426
|
}
|
|
425
427
|
const channels = /* @__PURE__ */ new Map();
|
|
428
|
+
const admitted = kinds === void 0 ? void 0 : new Set(kinds);
|
|
426
429
|
for (const [name, entry] of Object.entries(value)) {
|
|
427
430
|
const def = Object.hasOwn(contract.channels, name) ? contract.channels[name] : void 0;
|
|
428
431
|
if (def === void 0) {
|
|
429
432
|
fail5(`"${name}" is not a channel of the contract`);
|
|
430
433
|
}
|
|
431
|
-
channels.set(name, checkChannel(contract.name, name, def, entry, fail5));
|
|
434
|
+
channels.set(name, checkChannel(contract.name, name, def, entry, admitted, fail5));
|
|
432
435
|
}
|
|
433
436
|
return channels;
|
|
434
437
|
}
|
|
@@ -615,7 +618,24 @@ function checkWatchAccess(value, fail5) {
|
|
|
615
618
|
}
|
|
616
619
|
return Object.freeze({ service: value.service });
|
|
617
620
|
}
|
|
618
|
-
function
|
|
621
|
+
function checkAppKinds(value) {
|
|
622
|
+
return narrowKinds(value, void 0, (message) => {
|
|
623
|
+
throw new TypeError(`initQuickdraw: ${message}`);
|
|
624
|
+
});
|
|
625
|
+
}
|
|
626
|
+
function checkMethodKinds(owner2, entry, data, fail5) {
|
|
627
|
+
if (entry.kinds !== void 0 && entry.access === "public") {
|
|
628
|
+
fail5(
|
|
629
|
+
`${owner2} is "public", so kinds cannot narrow who may call it: a caller of a kind it left out would call it signed out. Leave kinds out, or give it a form that needs a principal`
|
|
630
|
+
);
|
|
631
|
+
}
|
|
632
|
+
return narrowKinds(
|
|
633
|
+
entry.kinds,
|
|
634
|
+
{ kinds: data.kinds, by: "its service" },
|
|
635
|
+
(message) => fail5(`${owner2}: ${message}`)
|
|
636
|
+
);
|
|
637
|
+
}
|
|
638
|
+
function checkServiceData(definition, appKinds, fail5) {
|
|
619
639
|
const { model, access, versionColumn } = definition;
|
|
620
640
|
if (model !== void 0 && !isName(model)) {
|
|
621
641
|
fail5('model must be the database model the rows live in, as the client names it ("task")');
|
|
@@ -635,7 +655,8 @@ function checkServiceData(definition, fail5) {
|
|
|
635
655
|
writes: checkWrites(definition.writes, fail5),
|
|
636
656
|
affects: Object.freeze(checkAffects(definition.affects, model, fail5)),
|
|
637
657
|
versionColumn,
|
|
638
|
-
watchAccess: checkWatchAccess(definition.watchAccess, fail5)
|
|
658
|
+
watchAccess: checkWatchAccess(definition.watchAccess, fail5),
|
|
659
|
+
kinds: narrowKinds(definition.kinds, { kinds: appKinds, by: "initQuickdraw" }, fail5)
|
|
639
660
|
};
|
|
640
661
|
}
|
|
641
662
|
function checkWatchedModels(contract, name, models, data, fail5) {
|
|
@@ -671,7 +692,8 @@ var DEFINITION_KEYS = /* @__PURE__ */ new Set([
|
|
|
671
692
|
"channels",
|
|
672
693
|
"streams",
|
|
673
694
|
"onRoomLeave",
|
|
674
|
-
"adminBypass"
|
|
695
|
+
"adminBypass",
|
|
696
|
+
"kinds"
|
|
675
697
|
]);
|
|
676
698
|
var METHOD_KEYS = /* @__PURE__ */ new Set([
|
|
677
699
|
"access",
|
|
@@ -680,7 +702,8 @@ var METHOD_KEYS = /* @__PURE__ */ new Set([
|
|
|
680
702
|
"ttlMs",
|
|
681
703
|
"timeoutMs",
|
|
682
704
|
"version",
|
|
683
|
-
"rowless"
|
|
705
|
+
"rowless",
|
|
706
|
+
"kinds"
|
|
684
707
|
]);
|
|
685
708
|
function isRecord4(value) {
|
|
686
709
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
@@ -727,7 +750,7 @@ function checkQueryOptions(owner2, entry, kind, fail5) {
|
|
|
727
750
|
fail5(`${owner2}: version must be a function of (input, ctx)`);
|
|
728
751
|
}
|
|
729
752
|
}
|
|
730
|
-
function checkMethod(contract, projections, name, entry, fail5) {
|
|
753
|
+
function checkMethod(contract, projections, data, name, entry, fail5) {
|
|
731
754
|
const owner2 = `method "${name}"`;
|
|
732
755
|
const def = contract.methods[name];
|
|
733
756
|
if (def === void 0) {
|
|
@@ -753,6 +776,7 @@ function checkMethod(contract, projections, name, entry, fail5) {
|
|
|
753
776
|
fail5(`${owner2}: rowless must be true, or left out`);
|
|
754
777
|
}
|
|
755
778
|
checkQueryOptions(owner2, entry, def.kind, fail5);
|
|
779
|
+
const kinds = checkMethodKinds(owner2, entry, data, fail5);
|
|
756
780
|
const projection = projectedOutput(def.output, projections);
|
|
757
781
|
return Object.freeze({
|
|
758
782
|
name,
|
|
@@ -762,6 +786,7 @@ function checkMethod(contract, projections, name, entry, fail5) {
|
|
|
762
786
|
projection,
|
|
763
787
|
schemaOutput: projection === void 0 ? schemaOutputOf(def.output) : void 0,
|
|
764
788
|
access: entry.access,
|
|
789
|
+
kinds,
|
|
765
790
|
handler: entry.handler,
|
|
766
791
|
share: entry.share,
|
|
767
792
|
ttlMs: entry.ttlMs,
|
|
@@ -770,7 +795,7 @@ function checkMethod(contract, projections, name, entry, fail5) {
|
|
|
770
795
|
rowless: entry.rowless === true
|
|
771
796
|
});
|
|
772
797
|
}
|
|
773
|
-
function checkMethods(contract, projections, value, fail5) {
|
|
798
|
+
function checkMethods(contract, projections, data, value, fail5) {
|
|
774
799
|
if (!isRecord4(value)) {
|
|
775
800
|
fail5("methods must be an object with one implementation per contract method");
|
|
776
801
|
}
|
|
@@ -780,7 +805,7 @@ function checkMethods(contract, projections, value, fail5) {
|
|
|
780
805
|
}
|
|
781
806
|
const methods = {};
|
|
782
807
|
for (const [name, entry] of Object.entries(value)) {
|
|
783
|
-
methods[name] = checkMethod(contract, projections, name, entry, fail5);
|
|
808
|
+
methods[name] = checkMethod(contract, projections, data, name, entry, fail5);
|
|
784
809
|
}
|
|
785
810
|
return methods;
|
|
786
811
|
}
|
|
@@ -851,6 +876,23 @@ function checkHandlers(service, fail5) {
|
|
|
851
876
|
}
|
|
852
877
|
}
|
|
853
878
|
}
|
|
879
|
+
function createRuntime(options, adopt) {
|
|
880
|
+
if (options === void 0) {
|
|
881
|
+
return Object.freeze({ extendContext: void 0, kinds: void 0, adopt });
|
|
882
|
+
}
|
|
883
|
+
if (typeof options !== "object" || options === null) {
|
|
884
|
+
throw new TypeError("initQuickdraw: options must be an object");
|
|
885
|
+
}
|
|
886
|
+
const { context, kinds } = options;
|
|
887
|
+
if (context !== void 0 && typeof context !== "function") {
|
|
888
|
+
throw new TypeError("initQuickdraw: context must be a function of the base context");
|
|
889
|
+
}
|
|
890
|
+
return Object.freeze({
|
|
891
|
+
extendContext: context,
|
|
892
|
+
kinds: checkAppKinds(kinds),
|
|
893
|
+
adopt
|
|
894
|
+
});
|
|
895
|
+
}
|
|
854
896
|
function buildService(runtime, contract, definition) {
|
|
855
897
|
const checked2 = checkContract(contract);
|
|
856
898
|
const fail5 = (message) => {
|
|
@@ -867,7 +909,7 @@ function buildService(runtime, contract, definition) {
|
|
|
867
909
|
if (onRoomLeave !== void 0 && typeof onRoomLeave !== "function") {
|
|
868
910
|
fail5("onRoomLeave must be a function of the leave and a run context");
|
|
869
911
|
}
|
|
870
|
-
const data = checkServiceData(definition, fail5);
|
|
912
|
+
const data = checkServiceData(definition, runtime.kinds, fail5);
|
|
871
913
|
const projections = compileProjections(checked2, definition.project, fail5);
|
|
872
914
|
const collections = compileCollections(
|
|
873
915
|
checked2,
|
|
@@ -877,7 +919,7 @@ function buildService(runtime, contract, definition) {
|
|
|
877
919
|
fail5
|
|
878
920
|
);
|
|
879
921
|
checkWatches(checked2, collections, data, fail5);
|
|
880
|
-
const methods = checkMethods(checked2, projections, definition.methods, fail5);
|
|
922
|
+
const methods = checkMethods(checked2, projections, data, definition.methods, fail5);
|
|
881
923
|
checkRowForms(methods, data, fail5);
|
|
882
924
|
checkRowless(methods, data, fail5);
|
|
883
925
|
const service = Object.freeze({
|
|
@@ -888,7 +930,7 @@ function buildService(runtime, contract, definition) {
|
|
|
888
930
|
collections,
|
|
889
931
|
adminBypass,
|
|
890
932
|
methods: Object.freeze(methods),
|
|
891
|
-
channels: compileChannels(checked2, definition.channels, fail5),
|
|
933
|
+
channels: compileChannels(checked2, definition.channels, data.kinds, fail5),
|
|
892
934
|
streams: compileStreams(
|
|
893
935
|
checked2,
|
|
894
936
|
{ model: data.model, hasPolicy: data.access !== void 0 },
|
|
@@ -903,19 +945,6 @@ function buildService(runtime, contract, definition) {
|
|
|
903
945
|
}
|
|
904
946
|
|
|
905
947
|
// src/server/init.ts
|
|
906
|
-
function contextOption(options) {
|
|
907
|
-
if (options === void 0) {
|
|
908
|
-
return void 0;
|
|
909
|
-
}
|
|
910
|
-
if (typeof options !== "object" || options === null) {
|
|
911
|
-
throw new TypeError("initQuickdraw: options must be an object");
|
|
912
|
-
}
|
|
913
|
-
const { context } = options;
|
|
914
|
-
if (context !== void 0 && typeof context !== "function") {
|
|
915
|
-
throw new TypeError("initQuickdraw: context must be a function of the base context");
|
|
916
|
-
}
|
|
917
|
-
return context;
|
|
918
|
-
}
|
|
919
948
|
var NEEDS = Object.freeze({
|
|
920
949
|
"qd.collections.reset": "send through",
|
|
921
950
|
"qd.stream": "push through",
|
|
@@ -976,11 +1005,8 @@ function roomsOf(current) {
|
|
|
976
1005
|
}
|
|
977
1006
|
function initQuickdraw(...args) {
|
|
978
1007
|
let current;
|
|
979
|
-
const runtime =
|
|
980
|
-
|
|
981
|
-
adopt: (dispatcher) => {
|
|
982
|
-
current = dispatcher;
|
|
983
|
-
}
|
|
1008
|
+
const runtime = createRuntime(args[0], (dispatcher) => {
|
|
1009
|
+
current = dispatcher;
|
|
984
1010
|
});
|
|
985
1011
|
const qd = {
|
|
986
1012
|
defineService: ((contract, definition) => buildService(runtime, contract, definition)),
|