@owlmeans/server-socket 0.1.18-rc.3 → 0.1.18-rc.31

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 CHANGED
@@ -1,69 +1,205 @@
1
1
  # @owlmeans/server-socket
2
2
 
3
- Server-side WebSocket connection handler and service for OwlMeans backends.
4
-
5
- ## Overview
6
-
7
- - `handleConnection()` wraps WebSocket business logic — analogous to `handleBody` but for WS connections
8
- - `appendSocketService()` + `createSocketMiddleware()` wire the WebSocket service into a server context
9
- - Used in viable for real-time thinking journal updates and file watching
10
- - The `Connection` interface (from `@owlmeans/socket`) is the runtime object passed to your handler
3
+ The server WebSocket carrier for OwlMeans backends: binds socket protocol declarations to connection
4
+ handlers on the Fastify API server. An application uses `connection(protocol, callback)` for push
5
+ and streaming channels — live notifications, file or job progress, RPC over one long-lived
6
+ connection. `@owlmeans/server-app`'s `makeContext` already registers the socket service and its
7
+ middleware. Request/response HTTP routes use `handlers<Context>()` from `@owlmeans/server-api`, the
8
+ browser side is `@owlmeans/client-socket`, and background work that must survive a restart belongs
9
+ in a queue (`@owlmeans/server-job`).
11
10
 
12
11
  ## Installation
13
12
 
14
13
  ```bash
15
- bun add @owlmeans/server-socket
14
+ bun add @owlmeans/server-socket@^0.1.18-rc.30
16
15
  ```
17
16
 
17
+ ## Concepts
18
+
19
+ - **Socket protocol** — a declaration whose route is built with `socket()` from `@owlmeans/route`.
20
+ The HTTP server skips it; the socket service mounts it as a `GET` WebSocket route.
21
+ - **Connection** — the `@owlmeans/socket` `Connection` model. This package assigns its `send`,
22
+ `close`, `authenticate` and `prepare`; the handler uses `notify`, `listen`, `observe`, `perform`,
23
+ `call` and `close`.
24
+ - **Upgrade-time guards** — the protocol's guards and gates run before the upgrade with the same
25
+ pipeline as HTTP, including organization-entity resolution, so a guarded socket arrives with
26
+ `request.auth` and `request.entity` set.
27
+ - **In-band authentication** — a socket that receives its token after the connection is open
28
+ assigns `conn.authenticate`; that code path establishes authentication and must resolve the entity
29
+ itself.
30
+ - **System frames** — on close, listeners receive `{ type: MessageType.System, event: 'close',
31
+ payload: { code } }`. A thrown callback closes the socket with code 1011; server shutdown closes
32
+ open sockets with 1001.
33
+
18
34
  ## Usage
19
35
 
20
- Handle a WebSocket connection on a module route:
36
+ ### Declare and bind
21
37
 
22
- ```typescript
23
- import { handleConnection } from '@owlmeans/server-socket'
24
- import type { Connection } from '@owlmeans/socket'
38
+ ```ts
39
+ // my-app-common
40
+ import { contract, protocol, typed } from '@owlmeans/entrypoint'
41
+ import { route, socket } from '@owlmeans/route'
42
+
43
+ export const projectProtocols = {
44
+ // ...base, list, create
45
+ events: protocol(
46
+ route('my-app:api:project:events', '/:id/events', socket({ parent: projectBase })),
47
+ contract.request({ params: typed<ProjectParams>(ProjectParamsSchema) }, typed<void>()),
48
+ ),
49
+ }
50
+ ```
25
51
 
26
- export const watch = handleConnection<Connection>(async (conn, context, req) => {
27
- const ctx = context as Context
28
- const projectId = req.params.id as string
52
+ ```ts
53
+ // my-app-api
54
+ import { bind } from '@owlmeans/server-app'
55
+ import { connection } from '@owlmeans/server-socket'
56
+ import { projectProtocols } from 'my-app-common'
57
+ import type { Context } from './context.js'
29
58
 
30
- // Observe events sent by the client
31
- const unsubscribe = conn.observe<FileEvent>('file-change', async (event) => {
32
- await ctx.fileStore().save({ projectId, ...event.payload })
59
+ const events = connection<typeof projectProtocols.events, Context>(projectProtocols.events,
60
+ async (conn, context, request) => {
61
+ await conn.notify('project:ready', { id: request.params.id })
33
62
  })
34
63
 
35
- // Push updates to the client
36
- const listener = ctx.fileStore().listen(record => {
37
- conn.notify('file-update', record)
64
+ export const appEntrypoints = [
65
+ bind(projectProtocols.events, events),
66
+ ]
67
+ ```
68
+
69
+ ### Push organization-scoped events and clean up
70
+
71
+ The parent declares `guards`, so authentication and the entity are resolved before the upgrade.
72
+
73
+ ```ts
74
+ import { requireEntityKey } from '@owlmeans/auth-common'
75
+ import { MessageType } from '@owlmeans/socket'
76
+ import type { EventMessage } from '@owlmeans/socket'
77
+
78
+ export const events = connection<typeof projectProtocols.events, Context>(projectProtocols.events,
79
+ async (conn, context, request) => {
80
+ const entityId = requireEntityKey(request)
81
+
82
+ // app-local pub/sub resource, one channel per organization
83
+ const unsubscribe = await context.projectEvents().subscribe(async event => {
84
+ if (event.projectId === request.params.id) {
85
+ await conn.notify('project:event', event)
86
+ }
87
+ }, { channel: entityId })
88
+
89
+ conn.listen(async raw => {
90
+ if (typeof raw !== 'object') return
91
+ const message = raw as EventMessage<void>
92
+ if (message.type === MessageType.System && message.event === 'close') {
93
+ await unsubscribe()
94
+ }
95
+ })
38
96
  })
39
- })
40
97
  ```
41
98
 
42
- ## API
99
+ ### Authenticate in-band
100
+
101
+ When the client cannot send a bearer on the upgrade request, it sends the token as the first auth
102
+ frame. The handler runs the guard itself and must call `attachEntity`.
103
+
104
+ ```ts
105
+ import { AUTH_HEADER, AuthenFailed, AuthenticationStage, AuthUnknown } from '@owlmeans/auth'
106
+ import type { Auth, AuthToken } from '@owlmeans/auth'
107
+ import { attachEntity, DEFAULT_GUARD, requireEntityKey } from '@owlmeans/auth-common'
108
+ import { provideResponse } from '@owlmeans/entrypoint'
109
+ import type { AbstractResponse, GuardService } from '@owlmeans/entrypoint'
110
+ import type { AuthenticateMethod } from '@owlmeans/socket'
43
111
 
44
- ### `handleConnection<T>(handler): RefedModuleHandler`
112
+ export const watch = connection<typeof projectProtocols.watch, Context>(projectProtocols.watch,
113
+ async (conn, context, request) => {
114
+ const timeout = setTimeout(() => void conn.close(), 5_000)
45
115
 
46
- Wraps a WebSocket handler. The handler receives `(conn: T, ctx, req, res)`.
116
+ conn.authenticate = (async (stage: AuthenticationStage, token: AuthToken) => {
117
+ if (stage !== AuthenticationStage.Authenticate) {
118
+ throw new AuthUnknown('stage')
119
+ }
47
120
 
48
- ```typescript
49
- handler: (conn: T, ctx: Context, req: AbstractRequest, res: AbstractResponse) => Promise<void>
121
+ request.headers[AUTH_HEADER] ??= token.token
122
+ const response: AbstractResponse<Auth> = provideResponse({ header: () => void 0 })
123
+ const guard = context.service<GuardService>(DEFAULT_GUARD)
124
+ if (!await guard.handle(request, response) || response.value == null) {
125
+ throw new AuthenFailed('guard')
126
+ }
127
+
128
+ request.auth = response.value
129
+ // This path establishes authentication, so it resolves the organization entity itself.
130
+ await attachEntity(context, request)
131
+ clearTimeout(timeout)
132
+
133
+ await startWatching(conn, context, requireEntityKey(request))
134
+
135
+ return [AuthenticationStage.Authenticated, true]
136
+ }) as AuthenticateMethod
137
+ })
50
138
  ```
51
139
 
52
- The `conn` object is a server-side `Connection` (from `@owlmeans/socket`).
140
+ ### RPC over a connection
141
+
142
+ ```ts
143
+ export const terminal = connection<typeof projectProtocols.terminal, Context>(projectProtocols.terminal,
144
+ async (conn, context, request) => {
145
+ const entityId = requireEntityKey(request)
53
146
 
54
- ### `appendSocketService<C, T>(context): void`
147
+ conn.perform('project:rename', async (id: string, name: string) => {
148
+ const project = await context.project().load({ id, entityId })
149
+ return project == null ? null : context.project().update({ ...project, name })
150
+ })
151
+ })
152
+ ```
55
153
 
56
- Registers the WebSocket service into the context. Called automatically by `makeContext()`.
154
+ The browser side calls it with `conn.call('project:rename', id, name)` on a
155
+ `@owlmeans/client-socket` connection.
57
156
 
58
- ### `createSocketMiddleware(): Middleware`
157
+ ### A context without `@owlmeans/server-app`
59
158
 
60
- Creates the middleware that initializes the socket service during context init.
159
+ ```ts
160
+ import { appendApiServer } from '@owlmeans/server-api'
161
+ import { appendSocketService, createSocketMiddleware } from '@owlmeans/server-socket'
61
162
 
62
- ## Related Packages
163
+ appendApiServer(context)
164
+ appendSocketService(context)
165
+ context.registerMiddleware(createSocketMiddleware())
166
+ ```
167
+
168
+ ## API
63
169
 
64
- - [`@owlmeans/socket`](../socket) — `Connection`, `MessageType`, `EventMessage` types
170
+ | Symbol | Kind | Purpose |
171
+ |---|---|---|
172
+ | `connection<Protocol, SocketContext, SocketConnection>(protocol, handler)` | function | Bind a socket protocol to `(connection, context, request, response) => Promise<void>`; returns `BoundEntrypointHandler<Protocol>` |
173
+ | `handleConnection(handler)` | function | Unbound compatibility wrapper returning a `RefedEntrypointHandler` |
174
+ | `appendSocketService(ctx, alias = DEFAULT_ALIAS)` | function | Register the socket service on a context that already has the API server |
175
+ | `createSocketService(alias?)` | function | Create the socket service; `update(apiServer)` registers `@fastify/websocket` and the socket routes |
176
+ | `createSocketMiddleware(web = 'api-server', socket = DEFAULT_ALIAS)` | function | Loading-stage context middleware that attaches the socket service to the API server once |
177
+ | `DEFAULT_ALIAS` | const | `'socket-server'` |
178
+ | `SocketService` | type | `InitializedService` with `update(api: ApiServer)` |
179
+ | `Config`, `Context` | type | `ServerConfig` and `ServerContext & ApiServerAppend` |
180
+
181
+ ## Common pitfalls
182
+
183
+ - Declare the route with `socket()`; without it the declaration is mounted as a plain HTTP `GET`.
184
+ - Bind with the same protocol object on both sides: `bind(p, connection(p, callback))`.
185
+ - Guards and gates are inherited from the protocol tree and enforced before the handler runs; do not
186
+ re-implement them inside the callback.
187
+ - A socket that authenticates on its own must call `attachEntity(context, request)`, or
188
+ `request.entity` stays empty and entity-keyed lookups silently find nothing.
189
+ - The token query parameter is used only to stamp `sender` / `recipient` on frames. It is not
190
+ verified — never treat it as authentication.
191
+ - Release subscriptions and watchers on the System `close` frame. Listeners also receive heartbeat
192
+ frames, so check `type` and `event` before acting.
193
+ - Do not expose Fastify request or socket objects through a shared contract.
194
+
195
+ ## Related packages
196
+
197
+ - [`@owlmeans/socket`](../socket) — `Connection`, `MessageType`, `EventMessage`
198
+ - [`@owlmeans/client-socket`](../client-socket) — the browser and native carrier
199
+ - [`@owlmeans/server-api`](../server-api) — the API server this service attaches to
200
+ - [`@owlmeans/server-entrypoint`](../server-entrypoint) — `bind()`
65
201
  - [`@owlmeans/server-app`](../server-app) — calls `appendSocketService` in `makeContext`
66
- - [`@owlmeans/client-socket`](../client-socket) — client-side counterpart
202
+ - [`@owlmeans/auth-common`](../auth-common) — `attachEntity`, `requireEntityKey`, `DEFAULT_GUARD`
67
203
 
68
204
  <!-- owlmeans:agent-guidance:start -->
69
205
  ## Agent guidance
@@ -73,7 +209,7 @@ This package ships embedded agent skills under `agent-meta/`. After installing y
73
209
  your project's skill store (`.agents/skills/`):
74
210
 
75
211
  ```sh
76
- npx @owlmeans/agent-skills
212
+ npx @owlmeans/agent-skills@^0.1.18-rc.24
77
213
  ```
78
214
 
79
215
  The embedded files are version-matched to this package release. Do not edit them
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "schemaVersion": 2,
3
3
  "package": "@owlmeans/server-socket",
4
- "version": "0.1.18-rc.0",
5
- "generatedAt": "2026-08-16T22:20:50.511Z",
4
+ "version": "0.1.18-rc.31",
5
+ "generatedAt": "2026-09-15T12:59:01.060Z",
6
6
  "canonicalRepo": "https://github.com/owlmeans/common",
7
7
  "entries": [
8
8
  {
@@ -1,32 +1,29 @@
1
1
  ---
2
2
  name: server-socket
3
- description: How to use @owlmeans/server-socket — Fastify WebSocket integration providing a socket service registered on the server context. Auto-invoked when importing server socket primitives or wiring WebSocket support.
4
- user-invocable: false
3
+ description: Bind OwlMeans socket protocol declarations to Fastify WebSocket handlers.
5
4
  ---
6
5
  <!-- AUTO-GENERATED — do not edit. Regenerate via sync-agent-meta. -->
7
6
 
8
- # @owlmeans/server-socket
7
+ # Socket protocol handlers
9
8
 
10
- **Layer:** Server
11
- **Install:** `"@owlmeans/server-socket": "^0.1.18-rc.0"` in `dependencies`
9
+ **Install:** `bun add @owlmeans/server-socket@^0.1.18-rc.30`
12
10
 
13
- ## Key Exports
11
+ Declare a socket route and its contract in the shared protocol package. Bind it on the server with
12
+ `connection()` and `bind()`.
14
13
 
15
- | Export | Description |
16
- |--------|-------------|
17
- | `makeSocketService()` | Factory for the WebSocket server service |
18
- | Middleware | Socket middleware for Fastify |
19
- | Helpers | Channel subscription / broadcast helpers |
20
- | Constants | Default channel names |
14
+ ```ts
15
+ import { bind } from '@owlmeans/server-entrypoint'
16
+ import { connection } from '@owlmeans/server-socket'
21
17
 
22
- ## Usage
23
-
24
- ```typescript
25
- import { makeSocketService } from '@owlmeans/server-socket'
26
- context.registerService(makeSocketService())
18
+ export const serverBindings = [
19
+ bind(streamProtocols.watch, connection(streamProtocols.watch,
20
+ async (connection, context, request) => {
21
+ await connection.send({ type: 'ready' })
22
+ }
23
+ )),
24
+ ]
27
25
  ```
28
26
 
29
- ## Depends On
30
-
31
- - `@owlmeans/socket`, `@owlmeans/server-context`, `@owlmeans/server-api`
32
- - `@fastify/websocket` (runtime)
27
+ The handler receives a typed connection, context, request and response boundary. Guards and gates
28
+ are inherited from the protocol tree and enforced before the WebSocket handler runs. Do not expose
29
+ Fastify request objects through a shared contract.
package/build/helper.d.ts CHANGED
@@ -1,7 +1,9 @@
1
- import type { AbstractRequest, AbstractResponse } from '@owlmeans/entrypoint';
1
+ import type { AbstractRequest, AbstractResponse, EntrypointProtocolDeclaration, HandlerRequest, RequestOf, ResponseOf } from '@owlmeans/entrypoint';
2
2
  import type { Context } from '@owlmeans/server-api';
3
- import type { RefedEntrypointHandler } from '@owlmeans/server-entrypoint';
3
+ import type { BoundEntrypointHandler, RefedEntrypointHandler } from '@owlmeans/server-entrypoint';
4
4
  import type { Connection } from '@owlmeans/socket';
5
5
  import type { WebSocket } from '@fastify/websocket';
6
+ /** Bind a socket protocol to its connection lifecycle without an alias lookup. */
7
+ export declare const connection: <Protocol extends EntrypointProtocolDeclaration, SocketContext extends Context = Context, SocketConnection extends Connection = Connection>(protocol: Protocol, handler: (connection: SocketConnection, context: SocketContext, request: HandlerRequest<RequestOf<Protocol>>, response: AbstractResponse<ResponseOf<Protocol>>) => Promise<void>) => BoundEntrypointHandler<Protocol>;
6
8
  export declare const handleConnection: <T extends Connection = Connection>(handler: (conn: T, ctx: Context, req: AbstractRequest<WebSocket>, res: AbstractResponse<any>) => Promise<void>) => RefedEntrypointHandler<AbstractResponse<any>>;
7
9
  //# sourceMappingURL=helper.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"helper.d.ts","sourceRoot":"","sources":["../src/helper.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AAC7E,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAA;AACnD,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAA;AACzE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAClD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAA;AAGnD,eAAO,MAAM,gBAAgB,EAAE,CAAC,CAAC,SAAS,UAAU,GAAG,UAAU,EAC/D,OAAO,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,eAAe,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,gBAAgB,CAAC,GAAG,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,KAC3G,sBAAsB,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAUhD,CAAA"}
1
+ {"version":3,"file":"helper.d.ts","sourceRoot":"","sources":["../src/helper.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,eAAe,EAAE,gBAAgB,EAAE,6BAA6B,EAAE,cAAc,EAAE,SAAS,EAAE,UAAU,EACxG,MAAM,sBAAsB,CAAA;AAC7B,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAA;AACnD,OAAO,KAAK,EAAE,sBAAsB,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAA;AACjG,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAClD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAA;AAGnD,kFAAkF;AAClF,eAAO,MAAM,UAAU,GACrB,QAAQ,SAAS,6BAA6B,EAC9C,aAAa,SAAS,OAAO,GAAG,OAAO,EACvC,gBAAgB,SAAS,UAAU,GAAG,UAAU,YAEtC,QAAQ,WACT,CACP,UAAU,EAAE,gBAAgB,EAC5B,OAAO,EAAE,aAAa,EACtB,OAAO,EAAE,cAAc,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,EAC5C,QAAQ,EAAE,gBAAgB,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,KAC7C,OAAO,CAAC,IAAI,CAAC,KACjB,sBAAsB,CAAC,QAAQ,CAkBhC,CAAA;AAEF,eAAO,MAAM,gBAAgB,EAAE,CAAC,CAAC,SAAS,UAAU,GAAG,UAAU,EAC/D,OAAO,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,eAAe,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,gBAAgB,CAAC,GAAG,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,KAC3G,sBAAsB,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAUhD,CAAA"}
package/build/helper.js CHANGED
@@ -1,5 +1,20 @@
1
1
  import { assertContext } from '@owlmeans/context';
2
2
  import { makeConnection } from './utils/connection.js';
3
+ /** Bind a socket protocol to its connection lifecycle without an alias lookup. */
4
+ export const connection = (protocol, handler) => ({
5
+ protocol,
6
+ bind: ref => async (request, response) => {
7
+ const context = assertContext(ref.ref?.ctx, protocol.alias);
8
+ try {
9
+ await handler(makeConnection(request, context), context, request, response);
10
+ response.resolve(undefined);
11
+ }
12
+ catch (error) {
13
+ response.reject(error);
14
+ }
15
+ return response.value;
16
+ },
17
+ });
3
18
  export const handleConnection = handler => ref => async (req, res) => {
4
19
  const ctx = assertContext(ref.ref?.ctx);
5
20
  try {
@@ -1 +1 @@
1
- {"version":3,"file":"helper.js","sourceRoot":"","sources":["../src/helper.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AAMjD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AAEtD,MAAM,CAAC,MAAM,gBAAgB,GAEwB,OAAO,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE;IACxF,MAAM,GAAG,GAAG,aAAa,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAY,CAAA;IAClD,IAAI,CAAC;QACH,MAAM,OAAO,CAAC,cAAc,CAAC,GAAG,EAAE,GAAG,CAAQ,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAA;IAC/D,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,GAAG,CAAC,MAAM,CAAC,CAAU,CAAC,CAAA;IACxB,CAAC;IAED,yDAAyD;IACzD,OAAO,GAAG,CAAC,KAAK,CAAA;AAClB,CAAC,CAAA"}
1
+ {"version":3,"file":"helper.js","sourceRoot":"","sources":["../src/helper.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AAQjD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AAEtD,kFAAkF;AAClF,MAAM,CAAC,MAAM,UAAU,GAAG,CAKxB,QAAkB,EAClB,OAKkB,EACgB,EAAE,CAAC,CAAC;IACtC,QAAQ;IACR,IAAI,EAAE,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE;QACvC,MAAM,OAAO,GAAG,aAAa,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,QAAQ,CAAC,KAAK,CAAkB,CAAA;QAC5E,IAAI,CAAC;YACH,MAAM,OAAO,CACX,cAAc,CAAC,OAAqC,EAAE,OAAO,CAAqB,EAClF,OAAO,EACP,OAAyD,EACzD,QAAkD,CACnD,CAAA;YACD,QAAQ,CAAC,OAAO,CAAC,SAAiC,CAAC,CAAA;QACrD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,QAAQ,CAAC,MAAM,CAAC,KAAc,CAAC,CAAA;QACjC,CAAC;QAED,OAAO,QAAQ,CAAC,KAAK,CAAA;IACvB,CAAC;CACF,CAAC,CAAA;AAEF,MAAM,CAAC,MAAM,gBAAgB,GAEwB,OAAO,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE;IACxF,MAAM,GAAG,GAAG,aAAa,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAY,CAAA;IAClD,IAAI,CAAC;QACH,MAAM,OAAO,CAAC,cAAc,CAAC,GAAG,EAAE,GAAG,CAAQ,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAA;IAC/D,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,GAAG,CAAC,MAAM,CAAC,CAAU,CAAC,CAAA;IACxB,CAAC;IAED,yDAAyD;IACzD,OAAO,GAAG,CAAC,KAAK,CAAA;AAClB,CAAC,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAC/C,OAAO,KAAK,EAAE,MAAM,EAAE,OAAO,EAAW,MAAM,sBAAsB,CAAA;AAWpE,eAAO,MAAM,mBAAmB,WAAW,MAAM,KAAmB,aA4GnE,CAAA;AAED,eAAO,MAAM,mBAAmB,GAAI,CAAC,SAAS,MAAM,EAAE,CAAC,SAAS,OAAO,CAAC,CAAC,CAAC,OACnE,CAAC,UAAS,MAAM,KACpB,CAOF,CAAA"}
1
+ {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAC/C,OAAO,KAAK,EAAE,MAAM,EAAE,OAAO,EAAW,MAAM,sBAAsB,CAAA;AAWpE,eAAO,MAAM,mBAAmB,WAAW,MAAM,KAAmB,aA0GnE,CAAA;AAED,eAAO,MAAM,mBAAmB,GAAI,CAAC,SAAS,MAAM,EAAE,CAAC,SAAS,OAAO,CAAC,CAAC,CAAC,OACnE,CAAC,UAAS,MAAM,KACpB,CAOF,CAAA"}
package/build/service.js CHANGED
@@ -20,8 +20,7 @@ export const createSocketService = (alias = DEFAULT_ALIAS) => {
20
20
  .filter(module => canServerModule(context, module) && !module.route.isIntermediate())
21
21
  .reduce(async (ctx, module) => {
22
22
  let context = await ctx;
23
- await module.resolve();
24
- if (!module.route.match(req)) {
23
+ if (!module.route.match(req, module.mount())) {
25
24
  return context;
26
25
  }
27
26
  if (reply.sent) {
@@ -55,12 +54,11 @@ export const createSocketService = (alias = DEFAULT_ALIAS) => {
55
54
  return context;
56
55
  }, Promise.resolve(context));
57
56
  });
58
- await Promise.all(ctx.entrypoints().filter(module => canServerModule(ctx, module) && !module.route.isIntermediate()).map(async (module) => {
59
- await module.resolve();
57
+ ctx.entrypoints().filter(module => canServerModule(ctx, module) && !module.route.isIntermediate()).forEach(module => {
60
58
  if (module.handle == null) {
61
59
  return;
62
60
  }
63
- server.get(module.getPath(), {
61
+ server.get(module.mount(), {
64
62
  schema: {
65
63
  querystring: module.filter?.query ?? {},
66
64
  params: module.filter?.params ?? {},
@@ -92,7 +90,7 @@ export const createSocketService = (alias = DEFAULT_ALIAS) => {
92
90
  }
93
91
  });
94
92
  });
95
- }));
93
+ });
96
94
  });
97
95
  }
98
96
  }, service => async () => {
@@ -1 +1 @@
1
- {"version":3,"file":"service.js","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"service.js","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@owlmeans/server-socket",
3
- "version": "0.1.18-rc.3",
3
+ "version": "0.1.18-rc.31",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -31,15 +31,15 @@
31
31
  },
32
32
  "dependencies": {
33
33
  "@fastify/websocket": "^11.0.1",
34
- "@owlmeans/auth": "^0.1.18-rc.3",
35
- "@owlmeans/basic-envelope": "^0.1.18-rc.3",
36
- "@owlmeans/context": "^0.1.18-rc.3",
37
- "@owlmeans/entrypoint": "^0.1.18-rc.3",
38
- "@owlmeans/server-api": "^0.1.18-rc.3",
39
- "@owlmeans/server-auth": "^0.1.18-rc.3",
40
- "@owlmeans/server-context": "^0.1.18-rc.3",
41
- "@owlmeans/server-entrypoint": "^0.1.18-rc.3",
42
- "@owlmeans/socket": "^0.1.18-rc.3"
34
+ "@owlmeans/auth": "^0.1.18-rc.21",
35
+ "@owlmeans/basic-envelope": "^0.1.18-rc.24",
36
+ "@owlmeans/context": "^0.1.18-rc.20",
37
+ "@owlmeans/entrypoint": "^0.1.18-rc.23",
38
+ "@owlmeans/server-api": "^0.1.18-rc.29",
39
+ "@owlmeans/server-auth": "^0.1.18-rc.31",
40
+ "@owlmeans/server-context": "^0.1.18-rc.24",
41
+ "@owlmeans/server-entrypoint": "^0.1.18-rc.23",
42
+ "@owlmeans/socket": "^0.1.18-rc.21"
43
43
  },
44
44
  "publishConfig": {
45
45
  "access": "public"
package/src/helper.ts CHANGED
@@ -1,11 +1,46 @@
1
1
  import { assertContext } from '@owlmeans/context'
2
- import type { AbstractRequest, AbstractResponse } from '@owlmeans/entrypoint'
2
+ import type {
3
+ AbstractRequest, AbstractResponse, EntrypointProtocolDeclaration, HandlerRequest, RequestOf, ResponseOf,
4
+ } from '@owlmeans/entrypoint'
3
5
  import type { Context } from '@owlmeans/server-api'
4
- import type { RefedEntrypointHandler } from '@owlmeans/server-entrypoint'
6
+ import type { BoundEntrypointHandler, RefedEntrypointHandler } from '@owlmeans/server-entrypoint'
5
7
  import type { Connection } from '@owlmeans/socket'
6
8
  import type { WebSocket } from '@fastify/websocket'
7
9
  import { makeConnection } from './utils/connection.js'
8
10
 
11
+ /** Bind a socket protocol to its connection lifecycle without an alias lookup. */
12
+ export const connection = <
13
+ Protocol extends EntrypointProtocolDeclaration,
14
+ SocketContext extends Context = Context,
15
+ SocketConnection extends Connection = Connection,
16
+ >(
17
+ protocol: Protocol,
18
+ handler: (
19
+ connection: SocketConnection,
20
+ context: SocketContext,
21
+ request: HandlerRequest<RequestOf<Protocol>>,
22
+ response: AbstractResponse<ResponseOf<Protocol>>,
23
+ ) => Promise<void>,
24
+ ): BoundEntrypointHandler<Protocol> => ({
25
+ protocol,
26
+ bind: ref => async (request, response) => {
27
+ const context = assertContext(ref.ref?.ctx, protocol.alias) as SocketContext
28
+ try {
29
+ await handler(
30
+ makeConnection(request as AbstractRequest<WebSocket>, context) as SocketConnection,
31
+ context,
32
+ request as unknown as HandlerRequest<RequestOf<Protocol>>,
33
+ response as AbstractResponse<ResponseOf<Protocol>>,
34
+ )
35
+ response.resolve(undefined as ResponseOf<Protocol>)
36
+ } catch (error) {
37
+ response.reject(error as Error)
38
+ }
39
+
40
+ return response.value
41
+ },
42
+ })
43
+
9
44
  export const handleConnection: <T extends Connection = Connection>(
10
45
  handler: (conn: T, ctx: Context, req: AbstractRequest<WebSocket>, res: AbstractResponse<any>) => Promise<void>
11
46
  ) => RefedEntrypointHandler<AbstractResponse<any>> = handler => ref => async (req, res) => {
package/src/service.ts CHANGED
@@ -27,9 +27,8 @@ export const createSocketService = (alias: string = DEFAULT_ALIAS): SocketServic
27
27
  .filter(module => canServerModule(context, module) && !module.route.isIntermediate())
28
28
  .reduce<Promise<Context>>(async (ctx, module) => {
29
29
  let context = await ctx
30
- await module.resolve()
31
30
 
32
- if (!module.route.match(req)) {
31
+ if (!module.route.match(req, module.mount())) {
33
32
  return context
34
33
  }
35
34
 
@@ -68,15 +67,14 @@ export const createSocketService = (alias: string = DEFAULT_ALIAS): SocketServic
68
67
  }, Promise.resolve(context))
69
68
  })
70
69
 
71
- await Promise.all(ctx.entrypoints<ServerEntrypoint<Request>>().filter(
70
+ ctx.entrypoints<ServerEntrypoint<Request>>().filter(
72
71
  module => canServerModule(ctx, module) && !module.route.isIntermediate()
73
- ).map(async module => {
74
- await module.resolve()
72
+ ).forEach(module => {
75
73
  if (module.handle == null) {
76
74
  return
77
75
  }
78
76
 
79
- server.get(module.getPath(), {
77
+ server.get(module.mount(), {
80
78
  schema: {
81
79
  querystring: module.filter?.query ?? {},
82
80
  params: module.filter?.params ?? {},
@@ -111,7 +109,7 @@ export const createSocketService = (alias: string = DEFAULT_ALIAS): SocketServic
111
109
  }
112
110
  })
113
111
  })
114
- }))
112
+ })
115
113
  })
116
114
  }
117
115
  }, service => async () => {
package/build/.gitkeep DELETED
File without changes