@super-line/server 0.3.0 → 0.5.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/dist/index.d.cts CHANGED
@@ -1,25 +1,16 @@
1
- import { Server, IncomingMessage } from 'node:http';
2
- import { ServerMessageDef, Serializer, ServerFrame, EmitData, ConnDescriptor, Adapter, PresenceStore, Contract, RoleOf, NodeStat, SharedEvents, SharedServerRequests, ClientInput, Output, SharedRequests, ServerInput, AnyData, RoleRequests, Events, DataOf, RoleTopics, SharedTopics, EventData } from '@super-line/core';
3
- import { WebSocket } from 'ws';
1
+ import { ServerMessageDef, RawConn, Serializer, ServerFrame, EmitData, ConnDescriptor, Adapter, PresenceStore, Contract, RoleOf, NodeStat, SharedEvents, SharedServerRequests, ClientInput, Output, SharedRequests, ServerInput, AnyData, RoleRequests, Events, DataOf, RoleTopics, AccessRules, Resource, Perms, SharedTopics, EventData, ServerTransport, Handshake, ServerStore } from '@super-line/core';
4
2
 
5
- /** Backpressure policy: what to do when a connection's send buffer grows too large. */
6
- interface Backpressure {
7
- /** Buffer size (bytes) above which {@link Backpressure.onExceed} kicks in. */
8
- maxBufferedBytes: number;
9
- /** `'close'` (default) drops the connection with code 1013; `'drop'` skips the frame. */
10
- onExceed?: 'close' | 'drop';
11
- }
12
3
  /**
13
4
  * A single client connection, passed to handlers as the third argument.
14
5
  *
15
- * Node-local: `conn` objects live on the node that accepted the upgrade, so don't
6
+ * Node-local: `conn` objects live on the node that accepted the connection, so don't
16
7
  * stash one to reach a user later — cross-node delivery goes through the Adapter
17
8
  * (use a per-user room instead). Generic over the events it may emit (scoped by
18
9
  * role), its `ctx`, and its `role`.
19
10
  */
20
11
  declare class Conn<Ev = Record<string, ServerMessageDef>, Ctx = unknown, Role extends string = string, Data = unknown> {
21
- /** The underlying `ws` socket. `conn.ws.terminate()` simulates a drop in tests. */
22
- readonly ws: WebSocket;
12
+ /** The underlying transport connection. `conn.terminate()` simulates a drop in tests. */
13
+ readonly raw: RawConn;
23
14
  /** Server-assigned unique id for this connection (stable for its lifetime). */
24
15
  readonly id: string;
25
16
  /** This connection's role (the literal resolved by `authenticate`). */
@@ -27,14 +18,17 @@ declare class Conn<Ev = Record<string, ServerMessageDef>, Ctx = unknown, Role ex
27
18
  /** The context `authenticate` returned for this connection. */
28
19
  readonly ctx: Ctx;
29
20
  private readonly serializer;
30
- private readonly backpressure?;
31
21
  /** Optional inspector tap: called with each `emit` so the server can mirror it to inspectors. */
32
22
  private readonly onEmit?;
33
23
  /** Namespaced channels (rooms + topics) this connection belongs to. */
34
24
  readonly channels: Set<string>;
35
25
  /** Mutable per-connection scratch state, typed per role by the contract's `data` schema. */
36
26
  data: Data;
37
- /** When this connection was accepted (`Date.now()` at the upgrade). */
27
+ /** The client↔server transport (wire) this connection was accepted on (set by the server at accept). */
28
+ transport?: string;
29
+ /** ACL identity for stores: `identify(conn) ?? conn.id`, set by the server at accept (always defined there). */
30
+ principal?: string;
31
+ /** When this connection was accepted (`Date.now()`). */
38
32
  readonly connectedAt: number;
39
33
  /** When the server last sent a heartbeat ping to this connection (managed by the server). */
40
34
  lastPingAt?: number;
@@ -43,26 +37,33 @@ declare class Conn<Ev = Record<string, ServerMessageDef>, Ctx = unknown, Role ex
43
37
  /** Pings sent since the last pong; drives reaping (managed by the server). */
44
38
  missedPongs: number;
45
39
  constructor(
46
- /** The underlying `ws` socket. `conn.ws.terminate()` simulates a drop in tests. */
47
- ws: WebSocket,
40
+ /** The underlying transport connection. `conn.terminate()` simulates a drop in tests. */
41
+ raw: RawConn,
48
42
  /** Server-assigned unique id for this connection (stable for its lifetime). */
49
43
  id: string,
50
44
  /** This connection's role (the literal resolved by `authenticate`). */
51
45
  role: Role,
52
46
  /** The context `authenticate` returned for this connection. */
53
- ctx: Ctx, serializer: Serializer, backpressure?: Backpressure | undefined,
47
+ ctx: Ctx, serializer: Serializer,
54
48
  /** Optional inspector tap: called with each `emit` so the server can mirror it to inspectors. */
55
49
  onEmit?: ((event: string, data: unknown) => void) | undefined);
56
- private overBackpressure;
57
50
  /** Encode and send a frame (unicast, e.g. req/res). */
58
51
  send(frame: ServerFrame): void;
59
52
  /** Forward an already-encoded frame (fan-out path; encoded once at the source). */
60
53
  sendRaw(payload: string | Uint8Array): void;
61
54
  /** Push an event to THIS connection (node-local). Scoped to the role's events. */
62
55
  emit<E extends keyof Ev>(event: E, data: EmitData<Ev[E]>): void;
63
- /** Close the underlying socket. */
56
+ /** Graceful close of the underlying transport connection. */
64
57
  close(): void;
58
+ /** Hard close with no handshake — used by heartbeat reaping. */
59
+ terminate(): void;
65
60
  }
61
+ /**
62
+ * The ACL principal for a connection: the stable `identify` key when configured, else the
63
+ * (random, per-connection) `conn.id`. Always returns a string — store access rules never key
64
+ * on `undefined`. Distinct from `identify`'s raw output (which may be undefined, used for presence).
65
+ */
66
+ declare function resolvePrincipal(conn: Conn, identify?: (conn: Conn) => string | undefined): string;
66
67
 
67
68
  /**
68
69
  * In-process pub/sub bus. Share one bus across multiple servers to simulate
@@ -217,23 +218,42 @@ interface RoleLens<C extends Contract, R extends RoleOf<C>> {
217
218
  /** Publish to a topic in role `R`'s surface (reaches that role's subscribers). */
218
219
  publish<T extends keyof RoleTopics<C, R>>(topic: T, data: EmitData<RoleTopics<C, R>[T]>): void;
219
220
  }
221
+ /**
222
+ * Server-side handle for one configured Store, reached via `srv.store.<name>`. The server is
223
+ * authoritative: it creates Resources, grants/revokes access, and may co-write. `data` is untyped
224
+ * (stores are off-contract — see ADR-0003); callers assert the shape.
225
+ */
226
+ interface ServerStoreHandle {
227
+ /** Create a Resource with initial data + access rules (deny-by-default for everyone unlisted). */
228
+ create(id: string, data: unknown, accessRules: AccessRules): Promise<void>;
229
+ /** Read a Resource (data + accessRules), or undefined if absent. */
230
+ read(id: string): Promise<Resource | undefined>;
231
+ /** Server co-write: replace the Resource's value (LWW), fanned out to subscribers with a `server` origin. */
232
+ write(id: string, data: unknown): Promise<void>;
233
+ /** Grant a principal read/write on a Resource. */
234
+ grant(id: string, principal: string, perms: Perms): Promise<void>;
235
+ /** Revoke a principal's access to a Resource entirely. */
236
+ revoke(id: string, principal: string): Promise<void>;
237
+ /** Delete a Resource. */
238
+ delete(id: string): Promise<void>;
239
+ /** All Resource ids in this store. */
240
+ list(): Promise<string[]>;
241
+ }
220
242
  /** Options for {@link createSuperLineServer}. */
221
243
  interface SuperLineServerOptions<C extends Contract, A extends AuthResult<C>> {
222
- /** The `http.Server` to attach to (compose with Express/Fastify/Hono). */
223
- server?: Server;
244
+ /** Client↔server transports to accept connections on (e.g. `webSocketServerTransport({ server })`). */
245
+ transports: ServerTransport[];
224
246
  /** Wire serializer; MUST match the client. Defaults to `jsonSerializer`. */
225
247
  serializer?: Serializer;
226
248
  /** Cross-node fan-out adapter. Defaults to a per-server in-memory adapter. */
227
249
  adapter?: Adapter;
228
- /** Only handle upgrades for this pathname; others are left untouched. */
229
- path?: string;
230
250
  /**
231
251
  * Friendly name for this node, surfaced in `srv.nodeName`, the cluster descriptor, and the
232
252
  * Control Center topology. Defaults to `SUPER_LINE_NODE_NAME` or a short slice of `nodeId`.
233
253
  */
234
254
  nodeName?: string;
235
- /** Runs at the HTTP upgrade. Return { role, ctx }, or throw to reject with 401. */
236
- authenticate: (req: IncomingMessage) => Awaitable<A>;
255
+ /** Authenticate a connection from its normalized {@link Handshake}. Return { role, ctx }, or throw to reject. */
256
+ authenticate: (handshake: Handshake) => Awaitable<A>;
237
257
  /** Stable user key for a connection (powers `cluster.byUser`, `isOnline`, and `toUser`). */
238
258
  identify?: (conn: Conn) => string | undefined;
239
259
  /** Extra fields merged into the connection's cluster descriptor (e.g. `{ plan }`). `ctx` is never auto-serialized. */
@@ -252,16 +272,20 @@ interface SuperLineServerOptions<C extends Contract, A extends AuthResult<C>> {
252
272
  interval?: number;
253
273
  maxMissed?: number;
254
274
  } | false;
255
- /** Guard against slow consumers: when a connection's send buffer exceeds the limit, close or drop. */
256
- backpressure?: Backpressure;
257
275
  /**
258
- * Read-only Control Center inspector channel, reached via the WS subprotocol
259
- * `superline.inspector.v1`. Connections on it bypass `authenticate` and are kept out of
260
- * presence, the heartbeat, and `local`/`cluster` results. **Default off; dev / trusted-network only.**
276
+ * Enable the read-only Control Center inspector: emit `msg.*` telemetry and accept inspector
277
+ * clients. The WS transport must also be created with `inspector: true` to negotiate the
278
+ * `superline.inspector.v1` subprotocol. **Default off; dev / trusted-network only.**
261
279
  */
262
280
  inspector?: boolean | {
263
281
  redact?: string[];
264
282
  };
283
+ /**
284
+ * Pluggable persisted-state Stores, keyed by name (`{ scene: crdtStoreServer(), config: memoryStoreServer() }`).
285
+ * Each is the server half of a Store pair; the client passes the matching client halves. Surfaced as
286
+ * `srv.store.<name>` and `client.store.<name>`. Stores are off-contract and untyped (ADR-0003).
287
+ */
288
+ stores?: Record<string, ServerStore>;
265
289
  /** Called once per accepted connection. */
266
290
  onConnection?: (conn: Conn, ctx: CtxUnion<A>) => void;
267
291
  /** Called when a connection closes, with the WebSocket close `code`. */
@@ -300,6 +324,8 @@ interface SuperLineServer<C extends Contract, A extends AuthResult<C>> {
300
324
  subscribe<T extends keyof SharedTopics<C>>(topic: T, handler: (data: EventData<SharedTopics<C>[T]>, meta: BusMeta) => void): () => void;
301
325
  /** Lens for role-scoped sends, e.g. forRole('user').publish('feed', data). */
302
326
  forRole<R extends RoleOf<C>>(role: R): RoleLens<C, R>;
327
+ /** Server-authoritative handle for a configured Store (`srv.store('scene').create(...)`). Throws `NOT_FOUND` if the name isn't configured. */
328
+ store(name: string): ServerStoreHandle;
303
329
  close(): Promise<void>;
304
330
  }
305
331
  /**
@@ -315,8 +341,8 @@ interface SuperLineServer<C extends Contract, A extends AuthResult<C>> {
315
341
  * @example
316
342
  * ```ts
317
343
  * const srv = createSuperLineServer(api, {
318
- * server,
319
- * authenticate: (req) => ({ role: 'user' as const, ctx: { id: '1' } }),
344
+ * transports: [webSocketServerTransport({ server })],
345
+ * authenticate: (h) => ({ role: 'user' as const, ctx: { id: '1' } }),
320
346
  * })
321
347
  * srv.implement({
322
348
  * shared: { join: async ({ room }, _ctx, conn) => { srv.room(room).add(conn); return { ok: true } } },
@@ -326,4 +352,4 @@ interface SuperLineServer<C extends Contract, A extends AuthResult<C>> {
326
352
  */
327
353
  declare function createSuperLineServer<C extends Contract, A extends AuthResult<C>>(contract: C, opts: SuperLineServerOptions<C, A>): SuperLineServer<C, A>;
328
354
 
329
- export { type AuthResult, type Backpressure, type BusMeta, type ClusterView, Conn, type ConnTarget, type Handlers, type LocalView, MemoryBus, type Middleware, type MiddlewareInfo, type RoleLens, type Room, type SuperLineServer, type SuperLineServerOptions, type UserTarget, createInMemoryAdapter, createSuperLineServer };
355
+ export { type AuthResult, type BusMeta, type ClusterView, Conn, type ConnTarget, type Handlers, type LocalView, MemoryBus, type Middleware, type MiddlewareInfo, type RoleLens, type Room, type ServerStoreHandle, type SuperLineServer, type SuperLineServerOptions, type UserTarget, createInMemoryAdapter, createSuperLineServer, resolvePrincipal };
package/dist/index.d.ts CHANGED
@@ -1,25 +1,16 @@
1
- import { Server, IncomingMessage } from 'node:http';
2
- import { ServerMessageDef, Serializer, ServerFrame, EmitData, ConnDescriptor, Adapter, PresenceStore, Contract, RoleOf, NodeStat, SharedEvents, SharedServerRequests, ClientInput, Output, SharedRequests, ServerInput, AnyData, RoleRequests, Events, DataOf, RoleTopics, SharedTopics, EventData } from '@super-line/core';
3
- import { WebSocket } from 'ws';
1
+ import { ServerMessageDef, RawConn, Serializer, ServerFrame, EmitData, ConnDescriptor, Adapter, PresenceStore, Contract, RoleOf, NodeStat, SharedEvents, SharedServerRequests, ClientInput, Output, SharedRequests, ServerInput, AnyData, RoleRequests, Events, DataOf, RoleTopics, AccessRules, Resource, Perms, SharedTopics, EventData, ServerTransport, Handshake, ServerStore } from '@super-line/core';
4
2
 
5
- /** Backpressure policy: what to do when a connection's send buffer grows too large. */
6
- interface Backpressure {
7
- /** Buffer size (bytes) above which {@link Backpressure.onExceed} kicks in. */
8
- maxBufferedBytes: number;
9
- /** `'close'` (default) drops the connection with code 1013; `'drop'` skips the frame. */
10
- onExceed?: 'close' | 'drop';
11
- }
12
3
  /**
13
4
  * A single client connection, passed to handlers as the third argument.
14
5
  *
15
- * Node-local: `conn` objects live on the node that accepted the upgrade, so don't
6
+ * Node-local: `conn` objects live on the node that accepted the connection, so don't
16
7
  * stash one to reach a user later — cross-node delivery goes through the Adapter
17
8
  * (use a per-user room instead). Generic over the events it may emit (scoped by
18
9
  * role), its `ctx`, and its `role`.
19
10
  */
20
11
  declare class Conn<Ev = Record<string, ServerMessageDef>, Ctx = unknown, Role extends string = string, Data = unknown> {
21
- /** The underlying `ws` socket. `conn.ws.terminate()` simulates a drop in tests. */
22
- readonly ws: WebSocket;
12
+ /** The underlying transport connection. `conn.terminate()` simulates a drop in tests. */
13
+ readonly raw: RawConn;
23
14
  /** Server-assigned unique id for this connection (stable for its lifetime). */
24
15
  readonly id: string;
25
16
  /** This connection's role (the literal resolved by `authenticate`). */
@@ -27,14 +18,17 @@ declare class Conn<Ev = Record<string, ServerMessageDef>, Ctx = unknown, Role ex
27
18
  /** The context `authenticate` returned for this connection. */
28
19
  readonly ctx: Ctx;
29
20
  private readonly serializer;
30
- private readonly backpressure?;
31
21
  /** Optional inspector tap: called with each `emit` so the server can mirror it to inspectors. */
32
22
  private readonly onEmit?;
33
23
  /** Namespaced channels (rooms + topics) this connection belongs to. */
34
24
  readonly channels: Set<string>;
35
25
  /** Mutable per-connection scratch state, typed per role by the contract's `data` schema. */
36
26
  data: Data;
37
- /** When this connection was accepted (`Date.now()` at the upgrade). */
27
+ /** The client↔server transport (wire) this connection was accepted on (set by the server at accept). */
28
+ transport?: string;
29
+ /** ACL identity for stores: `identify(conn) ?? conn.id`, set by the server at accept (always defined there). */
30
+ principal?: string;
31
+ /** When this connection was accepted (`Date.now()`). */
38
32
  readonly connectedAt: number;
39
33
  /** When the server last sent a heartbeat ping to this connection (managed by the server). */
40
34
  lastPingAt?: number;
@@ -43,26 +37,33 @@ declare class Conn<Ev = Record<string, ServerMessageDef>, Ctx = unknown, Role ex
43
37
  /** Pings sent since the last pong; drives reaping (managed by the server). */
44
38
  missedPongs: number;
45
39
  constructor(
46
- /** The underlying `ws` socket. `conn.ws.terminate()` simulates a drop in tests. */
47
- ws: WebSocket,
40
+ /** The underlying transport connection. `conn.terminate()` simulates a drop in tests. */
41
+ raw: RawConn,
48
42
  /** Server-assigned unique id for this connection (stable for its lifetime). */
49
43
  id: string,
50
44
  /** This connection's role (the literal resolved by `authenticate`). */
51
45
  role: Role,
52
46
  /** The context `authenticate` returned for this connection. */
53
- ctx: Ctx, serializer: Serializer, backpressure?: Backpressure | undefined,
47
+ ctx: Ctx, serializer: Serializer,
54
48
  /** Optional inspector tap: called with each `emit` so the server can mirror it to inspectors. */
55
49
  onEmit?: ((event: string, data: unknown) => void) | undefined);
56
- private overBackpressure;
57
50
  /** Encode and send a frame (unicast, e.g. req/res). */
58
51
  send(frame: ServerFrame): void;
59
52
  /** Forward an already-encoded frame (fan-out path; encoded once at the source). */
60
53
  sendRaw(payload: string | Uint8Array): void;
61
54
  /** Push an event to THIS connection (node-local). Scoped to the role's events. */
62
55
  emit<E extends keyof Ev>(event: E, data: EmitData<Ev[E]>): void;
63
- /** Close the underlying socket. */
56
+ /** Graceful close of the underlying transport connection. */
64
57
  close(): void;
58
+ /** Hard close with no handshake — used by heartbeat reaping. */
59
+ terminate(): void;
65
60
  }
61
+ /**
62
+ * The ACL principal for a connection: the stable `identify` key when configured, else the
63
+ * (random, per-connection) `conn.id`. Always returns a string — store access rules never key
64
+ * on `undefined`. Distinct from `identify`'s raw output (which may be undefined, used for presence).
65
+ */
66
+ declare function resolvePrincipal(conn: Conn, identify?: (conn: Conn) => string | undefined): string;
66
67
 
67
68
  /**
68
69
  * In-process pub/sub bus. Share one bus across multiple servers to simulate
@@ -217,23 +218,42 @@ interface RoleLens<C extends Contract, R extends RoleOf<C>> {
217
218
  /** Publish to a topic in role `R`'s surface (reaches that role's subscribers). */
218
219
  publish<T extends keyof RoleTopics<C, R>>(topic: T, data: EmitData<RoleTopics<C, R>[T]>): void;
219
220
  }
221
+ /**
222
+ * Server-side handle for one configured Store, reached via `srv.store.<name>`. The server is
223
+ * authoritative: it creates Resources, grants/revokes access, and may co-write. `data` is untyped
224
+ * (stores are off-contract — see ADR-0003); callers assert the shape.
225
+ */
226
+ interface ServerStoreHandle {
227
+ /** Create a Resource with initial data + access rules (deny-by-default for everyone unlisted). */
228
+ create(id: string, data: unknown, accessRules: AccessRules): Promise<void>;
229
+ /** Read a Resource (data + accessRules), or undefined if absent. */
230
+ read(id: string): Promise<Resource | undefined>;
231
+ /** Server co-write: replace the Resource's value (LWW), fanned out to subscribers with a `server` origin. */
232
+ write(id: string, data: unknown): Promise<void>;
233
+ /** Grant a principal read/write on a Resource. */
234
+ grant(id: string, principal: string, perms: Perms): Promise<void>;
235
+ /** Revoke a principal's access to a Resource entirely. */
236
+ revoke(id: string, principal: string): Promise<void>;
237
+ /** Delete a Resource. */
238
+ delete(id: string): Promise<void>;
239
+ /** All Resource ids in this store. */
240
+ list(): Promise<string[]>;
241
+ }
220
242
  /** Options for {@link createSuperLineServer}. */
221
243
  interface SuperLineServerOptions<C extends Contract, A extends AuthResult<C>> {
222
- /** The `http.Server` to attach to (compose with Express/Fastify/Hono). */
223
- server?: Server;
244
+ /** Client↔server transports to accept connections on (e.g. `webSocketServerTransport({ server })`). */
245
+ transports: ServerTransport[];
224
246
  /** Wire serializer; MUST match the client. Defaults to `jsonSerializer`. */
225
247
  serializer?: Serializer;
226
248
  /** Cross-node fan-out adapter. Defaults to a per-server in-memory adapter. */
227
249
  adapter?: Adapter;
228
- /** Only handle upgrades for this pathname; others are left untouched. */
229
- path?: string;
230
250
  /**
231
251
  * Friendly name for this node, surfaced in `srv.nodeName`, the cluster descriptor, and the
232
252
  * Control Center topology. Defaults to `SUPER_LINE_NODE_NAME` or a short slice of `nodeId`.
233
253
  */
234
254
  nodeName?: string;
235
- /** Runs at the HTTP upgrade. Return { role, ctx }, or throw to reject with 401. */
236
- authenticate: (req: IncomingMessage) => Awaitable<A>;
255
+ /** Authenticate a connection from its normalized {@link Handshake}. Return { role, ctx }, or throw to reject. */
256
+ authenticate: (handshake: Handshake) => Awaitable<A>;
237
257
  /** Stable user key for a connection (powers `cluster.byUser`, `isOnline`, and `toUser`). */
238
258
  identify?: (conn: Conn) => string | undefined;
239
259
  /** Extra fields merged into the connection's cluster descriptor (e.g. `{ plan }`). `ctx` is never auto-serialized. */
@@ -252,16 +272,20 @@ interface SuperLineServerOptions<C extends Contract, A extends AuthResult<C>> {
252
272
  interval?: number;
253
273
  maxMissed?: number;
254
274
  } | false;
255
- /** Guard against slow consumers: when a connection's send buffer exceeds the limit, close or drop. */
256
- backpressure?: Backpressure;
257
275
  /**
258
- * Read-only Control Center inspector channel, reached via the WS subprotocol
259
- * `superline.inspector.v1`. Connections on it bypass `authenticate` and are kept out of
260
- * presence, the heartbeat, and `local`/`cluster` results. **Default off; dev / trusted-network only.**
276
+ * Enable the read-only Control Center inspector: emit `msg.*` telemetry and accept inspector
277
+ * clients. The WS transport must also be created with `inspector: true` to negotiate the
278
+ * `superline.inspector.v1` subprotocol. **Default off; dev / trusted-network only.**
261
279
  */
262
280
  inspector?: boolean | {
263
281
  redact?: string[];
264
282
  };
283
+ /**
284
+ * Pluggable persisted-state Stores, keyed by name (`{ scene: crdtStoreServer(), config: memoryStoreServer() }`).
285
+ * Each is the server half of a Store pair; the client passes the matching client halves. Surfaced as
286
+ * `srv.store.<name>` and `client.store.<name>`. Stores are off-contract and untyped (ADR-0003).
287
+ */
288
+ stores?: Record<string, ServerStore>;
265
289
  /** Called once per accepted connection. */
266
290
  onConnection?: (conn: Conn, ctx: CtxUnion<A>) => void;
267
291
  /** Called when a connection closes, with the WebSocket close `code`. */
@@ -300,6 +324,8 @@ interface SuperLineServer<C extends Contract, A extends AuthResult<C>> {
300
324
  subscribe<T extends keyof SharedTopics<C>>(topic: T, handler: (data: EventData<SharedTopics<C>[T]>, meta: BusMeta) => void): () => void;
301
325
  /** Lens for role-scoped sends, e.g. forRole('user').publish('feed', data). */
302
326
  forRole<R extends RoleOf<C>>(role: R): RoleLens<C, R>;
327
+ /** Server-authoritative handle for a configured Store (`srv.store('scene').create(...)`). Throws `NOT_FOUND` if the name isn't configured. */
328
+ store(name: string): ServerStoreHandle;
303
329
  close(): Promise<void>;
304
330
  }
305
331
  /**
@@ -315,8 +341,8 @@ interface SuperLineServer<C extends Contract, A extends AuthResult<C>> {
315
341
  * @example
316
342
  * ```ts
317
343
  * const srv = createSuperLineServer(api, {
318
- * server,
319
- * authenticate: (req) => ({ role: 'user' as const, ctx: { id: '1' } }),
344
+ * transports: [webSocketServerTransport({ server })],
345
+ * authenticate: (h) => ({ role: 'user' as const, ctx: { id: '1' } }),
320
346
  * })
321
347
  * srv.implement({
322
348
  * shared: { join: async ({ room }, _ctx, conn) => { srv.room(room).add(conn); return { ok: true } } },
@@ -326,4 +352,4 @@ interface SuperLineServer<C extends Contract, A extends AuthResult<C>> {
326
352
  */
327
353
  declare function createSuperLineServer<C extends Contract, A extends AuthResult<C>>(contract: C, opts: SuperLineServerOptions<C, A>): SuperLineServer<C, A>;
328
354
 
329
- export { type AuthResult, type Backpressure, type BusMeta, type ClusterView, Conn, type ConnTarget, type Handlers, type LocalView, MemoryBus, type Middleware, type MiddlewareInfo, type RoleLens, type Room, type SuperLineServer, type SuperLineServerOptions, type UserTarget, createInMemoryAdapter, createSuperLineServer };
355
+ export { type AuthResult, type BusMeta, type ClusterView, Conn, type ConnTarget, type Handlers, type LocalView, MemoryBus, type Middleware, type MiddlewareInfo, type RoleLens, type Room, type ServerStoreHandle, type SuperLineServer, type SuperLineServerOptions, type UserTarget, createInMemoryAdapter, createSuperLineServer, resolvePrincipal };