opinionated-machine 10.5.0 → 11.2.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/CHANGELOG.md +154 -0
- package/README.md +513 -52
- package/dist/lib/DIContext.d.ts +13 -1
- package/dist/lib/DIContext.js +28 -8
- package/dist/lib/DIContext.js.map +1 -1
- package/dist/lib/api-contracts/apiRouteBuilder.d.ts +47 -5
- package/dist/lib/api-contracts/apiRouteBuilder.js +57 -8
- package/dist/lib/api-contracts/apiRouteBuilder.js.map +1 -1
- package/dist/lib/api-contracts/apiSseConnectionRegistry.d.ts +182 -0
- package/dist/lib/api-contracts/apiSseConnectionRegistry.js +332 -0
- package/dist/lib/api-contracts/apiSseConnectionRegistry.js.map +1 -0
- package/dist/lib/api-contracts/index.d.ts +1 -0
- package/dist/lib/api-contracts/index.js +1 -0
- package/dist/lib/api-contracts/index.js.map +1 -1
- package/dist/lib/gateway/gatewayMetadata.d.ts +1 -0
- package/dist/lib/gateway/gatewayMetadata.js +11 -0
- package/dist/lib/gateway/gatewayMetadata.js.map +1 -1
- package/dist/lib/gateway/index.d.ts +1 -0
- package/dist/lib/gateway/index.js +1 -0
- package/dist/lib/gateway/index.js.map +1 -1
- package/dist/lib/gateway/manifest/buildManifest.d.ts +18 -0
- package/dist/lib/gateway/manifest/buildManifest.js +31 -0
- package/dist/lib/gateway/manifest/buildManifest.js.map +1 -1
- package/dist/lib/gateway/manifest/manifestSchema.d.ts +18 -0
- package/dist/lib/gateway/manifest/manifestSchema.js +27 -0
- package/dist/lib/gateway/manifest/manifestSchema.js.map +1 -1
- package/dist/lib/gateway/routeStreaming.d.ts +79 -0
- package/dist/lib/gateway/routeStreaming.js +70 -0
- package/dist/lib/gateway/routeStreaming.js.map +1 -0
- package/dist/lib/resolverFunctions.d.ts +7 -0
- package/dist/lib/resolverFunctions.js +13 -0
- package/dist/lib/resolverFunctions.js.map +1 -1
- package/dist/lib/routes/fastifyRouteBuilder.js +9 -2
- package/dist/lib/routes/fastifyRouteBuilder.js.map +1 -1
- package/dist/lib/sse/AbstractSSEController.d.ts +10 -0
- package/dist/lib/sse/AbstractSSEController.js +9 -0
- package/dist/lib/sse/AbstractSSEController.js.map +1 -1
- package/dist/lib/sse/eventIds.d.ts +138 -0
- package/dist/lib/sse/eventIds.js +155 -0
- package/dist/lib/sse/eventIds.js.map +1 -0
- package/dist/lib/sse/index.d.ts +3 -2
- package/dist/lib/sse/index.js +6 -2
- package/dist/lib/sse/index.js.map +1 -1
- package/dist/lib/sse/rooms/SSERoomEventPublisher.d.ts +121 -0
- package/dist/lib/sse/rooms/SSERoomEventPublisher.js +119 -0
- package/dist/lib/sse/rooms/SSERoomEventPublisher.js.map +1 -0
- package/dist/lib/sse/rooms/index.d.ts +1 -0
- package/dist/lib/sse/rooms/index.js +1 -0
- package/dist/lib/sse/rooms/index.js.map +1 -1
- package/dist/lib/testing/apiSseEventValidation.d.ts +1 -1
- package/dist/lib/testing/apiSseInjectHelpers.js +9 -10
- package/dist/lib/testing/apiSseInjectHelpers.js.map +1 -1
- package/dist/lib/testing/sseHttpClient.d.ts +10 -2
- package/dist/lib/testing/sseHttpClient.js +13 -6
- package/dist/lib/testing/sseHttpClient.js.map +1 -1
- package/dist/lib/testing/sseInjectClient.d.ts +1 -1
- package/dist/lib/testing/sseInjectClient.js +1 -1
- package/dist/lib/testing/sseInjectClient.js.map +1 -1
- package/dist/lib/testing/sseTestTypes.d.ts +1 -1
- package/package.json +13 -13
- package/dist/lib/sse/sseParser.d.ts +0 -167
- package/dist/lib/sse/sseParser.js +0 -225
- package/dist/lib/sse/sseParser.js.map +0 -1
|
@@ -0,0 +1,332 @@
|
|
|
1
|
+
export class ApiSseConnectionRegistry {
|
|
2
|
+
connections = new Map();
|
|
3
|
+
/** In-flight async joins per connection id. Empty for a synchronous verdict. */
|
|
4
|
+
pendingJoins = new Map();
|
|
5
|
+
broadcaster;
|
|
6
|
+
constructor(broadcaster) {
|
|
7
|
+
this.broadcaster = broadcaster;
|
|
8
|
+
broadcaster.registerSender((connectionId, message) => {
|
|
9
|
+
const connection = this.connections.get(connectionId);
|
|
10
|
+
return connection ? connection.send(message) : Promise.resolve(false);
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Register an active SSE connection with its send function.
|
|
15
|
+
* The send function must return `false` (not throw) on delivery failure so
|
|
16
|
+
* room broadcasts keep fanning out to the remaining connections.
|
|
17
|
+
*
|
|
18
|
+
* Pass `close` to make the connection evictable — without it {@link evict}
|
|
19
|
+
* can stop delivery but cannot terminate the stream.
|
|
20
|
+
*/
|
|
21
|
+
register(connectionId, send, close) {
|
|
22
|
+
this.connections.set(connectionId, { send, ...(close !== undefined ? { close } : {}) });
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Remove a connection: drops the sender, leaves all rooms, and clears the
|
|
26
|
+
* broadcaster's dedup cache for the connection.
|
|
27
|
+
*/
|
|
28
|
+
unregister(connectionId) {
|
|
29
|
+
// Drop the map entry too: a verdict that never resolves would otherwise
|
|
30
|
+
// keep the id and its tokens alive after the session is gone. Cancellation
|
|
31
|
+
// lives on the token object the join closure captured, so a late verdict
|
|
32
|
+
// still settles as cancelled without the map.
|
|
33
|
+
this.cancelPendingJoins(connectionId);
|
|
34
|
+
this.pendingJoins.delete(connectionId);
|
|
35
|
+
this.connections.delete(connectionId);
|
|
36
|
+
this.broadcaster.roomManager.leaveAll(connectionId);
|
|
37
|
+
this.broadcaster.cleanupConnection(connectionId);
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Record an async `authorizeJoin` verdict that is still in flight, so a
|
|
41
|
+
* revocation arriving before it resolves can cancel it.
|
|
42
|
+
*
|
|
43
|
+
* Pair every call with {@link settlePendingJoin}; the room wiring in
|
|
44
|
+
* {@link withSessionRooms} does this for routes.
|
|
45
|
+
*/
|
|
46
|
+
beginPendingJoin(connectionId, room) {
|
|
47
|
+
const pending = { room, cancelled: false };
|
|
48
|
+
const existing = this.pendingJoins.get(connectionId);
|
|
49
|
+
if (existing)
|
|
50
|
+
existing.push(pending);
|
|
51
|
+
else
|
|
52
|
+
this.pendingJoins.set(connectionId, [pending]);
|
|
53
|
+
return pending;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Retire an in-flight join.
|
|
57
|
+
*
|
|
58
|
+
* @returns `true` when the join is still valid and may be applied, `false`
|
|
59
|
+
* when it was cancelled while the verdict was pending.
|
|
60
|
+
*/
|
|
61
|
+
settlePendingJoin(connectionId, pending) {
|
|
62
|
+
const list = this.pendingJoins.get(connectionId);
|
|
63
|
+
if (list) {
|
|
64
|
+
const index = list.indexOf(pending);
|
|
65
|
+
if (index !== -1)
|
|
66
|
+
list.splice(index, 1);
|
|
67
|
+
if (list.length === 0)
|
|
68
|
+
this.pendingJoins.delete(connectionId);
|
|
69
|
+
}
|
|
70
|
+
return !pending.cancelled;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Cancel in-flight joins for a connection — all of them, or only those for
|
|
74
|
+
* one room. A cancelled join is dropped when its verdict resolves.
|
|
75
|
+
*
|
|
76
|
+
* @returns How many joins were cancelled.
|
|
77
|
+
*/
|
|
78
|
+
cancelPendingJoins(connectionId, room) {
|
|
79
|
+
const list = this.pendingJoins.get(connectionId);
|
|
80
|
+
if (!list)
|
|
81
|
+
return 0;
|
|
82
|
+
let cancelled = 0;
|
|
83
|
+
for (const pending of list) {
|
|
84
|
+
if (room !== undefined && pending.room !== room)
|
|
85
|
+
continue;
|
|
86
|
+
if (pending.cancelled)
|
|
87
|
+
continue;
|
|
88
|
+
pending.cancelled = true;
|
|
89
|
+
cancelled += 1;
|
|
90
|
+
}
|
|
91
|
+
return cancelled;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Terminate one connection: leave its rooms, stop delivering to it, and
|
|
95
|
+
* close its stream.
|
|
96
|
+
*
|
|
97
|
+
* This is the revocation path. Authorization is checked when a stream opens
|
|
98
|
+
* and then goes stale, so removing a principal's access has to be able to
|
|
99
|
+
* end the streams that access already opened; without a call like this, a
|
|
100
|
+
* revoked user keeps receiving broadcasts until they close the tab.
|
|
101
|
+
*
|
|
102
|
+
* A client that reconnects (as `@opinionated-machine/sse-fallback` does)
|
|
103
|
+
* comes back through the route's own authorization, so an eviction of a
|
|
104
|
+
* still-authorized principal costs a reconnect, not a broken surface.
|
|
105
|
+
*
|
|
106
|
+
* @returns `true` when a connection was registered under that id.
|
|
107
|
+
*/
|
|
108
|
+
evict(connectionId) {
|
|
109
|
+
const connection = this.connections.get(connectionId);
|
|
110
|
+
if (!connection)
|
|
111
|
+
return false;
|
|
112
|
+
// Leave rooms first: a broadcast racing the close must not reach a
|
|
113
|
+
// connection that is being revoked. An async join still awaiting its
|
|
114
|
+
// verdict has to go too, or it rejoins a room after the eviction.
|
|
115
|
+
// Deleting the map entry is safe for the same reason as in `unregister`.
|
|
116
|
+
this.cancelPendingJoins(connectionId);
|
|
117
|
+
this.pendingJoins.delete(connectionId);
|
|
118
|
+
this.broadcaster.roomManager.leaveAll(connectionId);
|
|
119
|
+
this.connections.delete(connectionId);
|
|
120
|
+
this.broadcaster.cleanupConnection(connectionId);
|
|
121
|
+
connection.close?.();
|
|
122
|
+
return true;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Remove one connection from one room, leaving its other rooms and its
|
|
126
|
+
* stream intact. For revoking access to a single scope.
|
|
127
|
+
*
|
|
128
|
+
* A join whose async `authorizeJoin` verdict is still pending counts as
|
|
129
|
+
* membership here: the connection is not in the room yet, but it is about to
|
|
130
|
+
* be, and letting that land after a revocation would undo it.
|
|
131
|
+
*
|
|
132
|
+
* @returns `true` when the connection was in the room, or was on its way in.
|
|
133
|
+
*/
|
|
134
|
+
evictFromRoom(room, connectionId) {
|
|
135
|
+
const cancelled = this.cancelPendingJoins(connectionId, room) > 0;
|
|
136
|
+
if (!this.broadcaster.roomManager.isInRoom(connectionId, room))
|
|
137
|
+
return cancelled;
|
|
138
|
+
this.broadcaster.roomManager.leave(connectionId, room);
|
|
139
|
+
return true;
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Evict every connection currently in a room, terminating their streams.
|
|
143
|
+
* For revoking a whole scope (a deleted project, a disbanded team).
|
|
144
|
+
*
|
|
145
|
+
* Only connections on THIS node are closed — room membership elsewhere in
|
|
146
|
+
* the cluster is another node's registry to evict, so a revocation event
|
|
147
|
+
* has to reach every node.
|
|
148
|
+
*
|
|
149
|
+
* Joins still awaiting an async `authorizeJoin` verdict are cancelled rather
|
|
150
|
+
* than evicted: they hold no membership yet, so the revocation just denies
|
|
151
|
+
* them the room and leaves their other rooms and their stream alone. They
|
|
152
|
+
* are not counted in the return value for the same reason.
|
|
153
|
+
*
|
|
154
|
+
* @returns How many connections were evicted here.
|
|
155
|
+
*/
|
|
156
|
+
closeRoom(room) {
|
|
157
|
+
let evicted = 0;
|
|
158
|
+
for (const connectionId of this.broadcaster.roomManager.getConnectionsInRoom(room)) {
|
|
159
|
+
if (this.evict(connectionId))
|
|
160
|
+
evicted += 1;
|
|
161
|
+
}
|
|
162
|
+
for (const connectionId of this.pendingJoins.keys()) {
|
|
163
|
+
this.cancelPendingJoins(connectionId, room);
|
|
164
|
+
}
|
|
165
|
+
return evicted;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
const registries = new WeakMap();
|
|
169
|
+
/**
|
|
170
|
+
* Get (or lazily create) the shared registry for a broadcaster.
|
|
171
|
+
* Ensures `registerSender` is called exactly once per broadcaster no matter
|
|
172
|
+
* how many routes opt into rooms.
|
|
173
|
+
*/
|
|
174
|
+
export function getApiSseConnectionRegistry(broadcaster) {
|
|
175
|
+
let registry = registries.get(broadcaster);
|
|
176
|
+
if (!registry) {
|
|
177
|
+
registry = new ApiSseConnectionRegistry(broadcaster);
|
|
178
|
+
registries.set(broadcaster, registry);
|
|
179
|
+
}
|
|
180
|
+
return registry;
|
|
181
|
+
}
|
|
182
|
+
const NOOP_ROOMS = { join: () => { }, leave: () => { } };
|
|
183
|
+
/**
|
|
184
|
+
* Room operations per live session.
|
|
185
|
+
*
|
|
186
|
+
* `@lokalise/fastify-api-contracts` owns the `SSESession` shape and has no
|
|
187
|
+
* `rooms` field, so the operations live beside the session rather than on it.
|
|
188
|
+
* The map is weak: entries disappear with the session object, independently of
|
|
189
|
+
* the explicit cleanup done on close.
|
|
190
|
+
*/
|
|
191
|
+
const sessionRooms = new WeakMap();
|
|
192
|
+
/**
|
|
193
|
+
* Room operations for an SSE session opened by a `buildApiRoute` route.
|
|
194
|
+
*
|
|
195
|
+
* Returns no-ops when the route did not pass `sseRooms` — mirroring the legacy
|
|
196
|
+
* `session.rooms` accessor, which is inert on controllers without a broadcaster.
|
|
197
|
+
*
|
|
198
|
+
* @example
|
|
199
|
+
* ```ts
|
|
200
|
+
* const session = sse.start('keepAlive')
|
|
201
|
+
* getSessionRooms(session).join(`project:${request.params.projectId}`)
|
|
202
|
+
* ```
|
|
203
|
+
*/
|
|
204
|
+
export function getSessionRooms(session) {
|
|
205
|
+
return sessionRooms.get(session) ?? NOOP_ROOMS;
|
|
206
|
+
}
|
|
207
|
+
function normalizeRoomsOptions(config) {
|
|
208
|
+
return 'broadcaster' in config ? config : { broadcaster: config };
|
|
209
|
+
}
|
|
210
|
+
/** Per-session lifetime timers, cleared when the session closes. */
|
|
211
|
+
const lifetimeTimers = new WeakMap();
|
|
212
|
+
/**
|
|
213
|
+
* Compose room wiring into a route's SSE lifecycle hooks.
|
|
214
|
+
*
|
|
215
|
+
* On connect the session is registered with the broadcaster's registry and its
|
|
216
|
+
* room operations are published for {@link getSessionRooms}; on close the
|
|
217
|
+
* connection is unregistered (rooms left, dedup cache cleared). The route's own
|
|
218
|
+
* `onConnect` / `onClose` hooks still run — room wiring is applied first on
|
|
219
|
+
* connect (so a hook can already join rooms) and last on close.
|
|
220
|
+
*
|
|
221
|
+
* `onConnect` is invoked synchronously by the package's `sse.start()`, so the
|
|
222
|
+
* registration is in place before `start()` returns to the handler.
|
|
223
|
+
*
|
|
224
|
+
* Pass {@link SSERoomsOptions} instead of a bare broadcaster to add an
|
|
225
|
+
* `authorizeJoin` scope check or a `maxSessionLifetimeMs` bound.
|
|
226
|
+
*/
|
|
227
|
+
export function withSessionRooms(config, options) {
|
|
228
|
+
const { broadcaster, authorizeJoin, maxSessionLifetimeMs } = normalizeRoomsOptions(config);
|
|
229
|
+
const registry = getApiSseConnectionRegistry(broadcaster);
|
|
230
|
+
const { onConnect, onClose } = options;
|
|
231
|
+
return {
|
|
232
|
+
...options,
|
|
233
|
+
onConnect: (session) => {
|
|
234
|
+
registry.register(session.id, (message) =>
|
|
235
|
+
// The session's `send` validates against the contract's event schemas and
|
|
236
|
+
// throws on a mismatch. A broadcaster sender must not throw — one bad
|
|
237
|
+
// message would abort the fan-out for every other connection — so the
|
|
238
|
+
// failure is logged and reported as an undelivered message instead.
|
|
239
|
+
session.send(message.event ?? '', message.data, { id: message.id, retry: message.retry }).catch((err) => {
|
|
240
|
+
session.request.log.error({ err, event: message.event }, 'SSE room broadcast rejected for connection');
|
|
241
|
+
return false;
|
|
242
|
+
}), () => session.close());
|
|
243
|
+
if (maxSessionLifetimeMs !== undefined) {
|
|
244
|
+
const timer = setTimeout(() => {
|
|
245
|
+
if (!session.isConnected())
|
|
246
|
+
return;
|
|
247
|
+
session.request.log.info({ connectionId: session.id, maxSessionLifetimeMs }, 'closing SSE session at its lifetime bound');
|
|
248
|
+
session.close();
|
|
249
|
+
}, maxSessionLifetimeMs);
|
|
250
|
+
timer.unref?.();
|
|
251
|
+
lifetimeTimers.set(session, timer);
|
|
252
|
+
}
|
|
253
|
+
const joinRoom = (room) => {
|
|
254
|
+
// Guard against startup races where the stream is already dead:
|
|
255
|
+
// joining such a session would leave stale room members behind.
|
|
256
|
+
if (!session.isConnected())
|
|
257
|
+
return;
|
|
258
|
+
broadcaster.roomManager.join(session.id, room);
|
|
259
|
+
};
|
|
260
|
+
const denied = (room, err) => {
|
|
261
|
+
session.request.log.warn({ connectionId: session.id, room, ...(err !== undefined ? { err } : {}) }, 'SSE room join refused by authorizeJoin');
|
|
262
|
+
};
|
|
263
|
+
const authorizeAndJoin = (room) => {
|
|
264
|
+
if (!authorizeJoin) {
|
|
265
|
+
joinRoom(room);
|
|
266
|
+
return;
|
|
267
|
+
}
|
|
268
|
+
let verdict;
|
|
269
|
+
try {
|
|
270
|
+
verdict = authorizeJoin(session, room);
|
|
271
|
+
}
|
|
272
|
+
catch (err) {
|
|
273
|
+
denied(room, err);
|
|
274
|
+
return;
|
|
275
|
+
}
|
|
276
|
+
if (verdict === true) {
|
|
277
|
+
joinRoom(room);
|
|
278
|
+
return;
|
|
279
|
+
}
|
|
280
|
+
if (verdict === false) {
|
|
281
|
+
denied(room);
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
284
|
+
// The verdict lands after join() has returned, so a leave, an eviction
|
|
285
|
+
// or a closed room in the meantime must be able to call it off —
|
|
286
|
+
// otherwise the resolved verdict re-adds the connection and quietly
|
|
287
|
+
// undoes the revocation. The registry owns that token because those
|
|
288
|
+
// calls come through it, not through this closure.
|
|
289
|
+
const pending = registry.beginPendingJoin(session.id, room);
|
|
290
|
+
void verdict.then((allowed) => {
|
|
291
|
+
if (!registry.settlePendingJoin(session.id, pending))
|
|
292
|
+
return;
|
|
293
|
+
if (allowed)
|
|
294
|
+
joinRoom(room);
|
|
295
|
+
else
|
|
296
|
+
denied(room);
|
|
297
|
+
}, (err) => {
|
|
298
|
+
registry.settlePendingJoin(session.id, pending);
|
|
299
|
+
denied(room, err);
|
|
300
|
+
});
|
|
301
|
+
};
|
|
302
|
+
sessionRooms.set(session, {
|
|
303
|
+
join: (room) => {
|
|
304
|
+
for (const name of Array.isArray(room) ? room : [room])
|
|
305
|
+
authorizeAndJoin(name);
|
|
306
|
+
},
|
|
307
|
+
leave: (room) => {
|
|
308
|
+
for (const name of Array.isArray(room) ? room : [room]) {
|
|
309
|
+
registry.cancelPendingJoins(session.id, name);
|
|
310
|
+
}
|
|
311
|
+
broadcaster.roomManager.leave(session.id, room);
|
|
312
|
+
},
|
|
313
|
+
});
|
|
314
|
+
return onConnect?.(session);
|
|
315
|
+
},
|
|
316
|
+
onClose: async (session, initiator) => {
|
|
317
|
+
try {
|
|
318
|
+
await onClose?.(session, initiator);
|
|
319
|
+
}
|
|
320
|
+
finally {
|
|
321
|
+
const timer = lifetimeTimers.get(session);
|
|
322
|
+
if (timer !== undefined) {
|
|
323
|
+
clearTimeout(timer);
|
|
324
|
+
lifetimeTimers.delete(session);
|
|
325
|
+
}
|
|
326
|
+
sessionRooms.delete(session);
|
|
327
|
+
registry.unregister(session.id);
|
|
328
|
+
}
|
|
329
|
+
},
|
|
330
|
+
};
|
|
331
|
+
}
|
|
332
|
+
//# sourceMappingURL=apiSseConnectionRegistry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apiSseConnectionRegistry.js","sourceRoot":"","sources":["../../../lib/api-contracts/apiSseConnectionRegistry.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export type { ApiHandlerContext, ApiHandlerReply, InferApiHandler, InferApiHandlerRequest, InferApiHandlerResult, InferContractResponseContentTypes, } from '@lokalise/fastify-api-contracts';
|
|
2
2
|
export { AbstractApiController } from './AbstractApiController.ts';
|
|
3
3
|
export { type ApiRouteOptions, buildApiRoute } from './apiRouteBuilder.ts';
|
|
4
|
+
export { ApiSseConnectionRegistry, getApiSseConnectionRegistry, getSessionRooms, type PendingJoin, type SSERoomsOptions, withSessionRooms, } from './apiSseConnectionRegistry.ts';
|
|
4
5
|
export { asApiControllerClass } from './asApiControllerClass.ts';
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { AbstractApiController } from "./AbstractApiController.js";
|
|
2
2
|
export { buildApiRoute } from "./apiRouteBuilder.js";
|
|
3
|
+
export { ApiSseConnectionRegistry, getApiSseConnectionRegistry, getSessionRooms, withSessionRooms, } from "./apiSseConnectionRegistry.js";
|
|
3
4
|
export { asApiControllerClass } from "./asApiControllerClass.js";
|
|
4
5
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../lib/api-contracts/index.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAA;AAClE,OAAO,EAAwB,aAAa,EAAE,MAAM,sBAAsB,CAAA;AAC1E,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../lib/api-contracts/index.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAA;AAClE,OAAO,EAAwB,aAAa,EAAE,MAAM,sBAAsB,CAAA;AAC1E,OAAO,EACL,wBAAwB,EACxB,2BAA2B,EAC3B,eAAe,EAGf,gBAAgB,GACjB,MAAM,+BAA+B,CAAA;AACtC,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAA"}
|
|
@@ -70,6 +70,7 @@ export declare const gatewayMetadataSchema: z.ZodObject<{
|
|
|
70
70
|
request: z.ZodOptional<z.ZodString>;
|
|
71
71
|
idle: z.ZodOptional<z.ZodString>;
|
|
72
72
|
connect: z.ZodOptional<z.ZodString>;
|
|
73
|
+
maxDuration: z.ZodOptional<z.ZodString>;
|
|
73
74
|
}, z.core.$strict>>;
|
|
74
75
|
retry: z.ZodOptional<z.ZodObject<{
|
|
75
76
|
attempts: z.ZodOptional<z.ZodNumber>;
|
|
@@ -37,6 +37,17 @@ const timeoutsSchema = z
|
|
|
37
37
|
request: durationSchema.optional(),
|
|
38
38
|
idle: durationSchema.optional(),
|
|
39
39
|
connect: durationSchema.optional(),
|
|
40
|
+
/**
|
|
41
|
+
* Hard ceiling on the total lifetime of one connection, for streaming
|
|
42
|
+
* routes where `request` is unusable (it would cut a healthy stream) and
|
|
43
|
+
* `idle` is disabled (heartbeats are the liveness bound).
|
|
44
|
+
*
|
|
45
|
+
* Authorization is checked when a stream opens and then goes stale: a user
|
|
46
|
+
* removed from a project keeps receiving events for as long as the stream
|
|
47
|
+
* lives. A finite lifetime forces a reconnect, which re-authorizes with a
|
|
48
|
+
* fresh token, so this is the revocation backstop. `'0s'` opts out.
|
|
49
|
+
*/
|
|
50
|
+
maxDuration: durationSchema.optional(),
|
|
40
51
|
})
|
|
41
52
|
.strict();
|
|
42
53
|
const retrySchema = z
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gatewayMetadata.js","sourceRoot":"","sources":["../../../lib/gateway/gatewayMetadata.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,QAAQ,CAAA;AAE1B;;;GAGG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,iBAAiB,EAAE;IAChE,OAAO,EAAE,4EAA4E;CACtF,CAAC,CAAA;AAGF;;;GAGG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC;IACrC,CAAC,CAAC,MAAM,EAAE;IACV,CAAC,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC;IAC/B,CAAC,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC;IAChC,CAAC,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC;CAChC,CAAC,CAAA;AAGF,MAAM,gBAAgB,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC,CAAA;AAE7F,MAAM,WAAW,GAAG,CAAC;KAClB,MAAM,CAAC;IACN,OAAO,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,eAAe,CAAC,CAAC,QAAQ,EAAE;IACzD,aAAa,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,eAAe,CAAC,CAAC,QAAQ,EAAE;IAC/D,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,eAAe,CAAC,CAAC,QAAQ,EAAE;IACvD,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,eAAe,CAAC,CAAC,QAAQ,EAAE;IAC7D,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;CAC5D,CAAC;KACD,MAAM,EAAE,CAAA;AAEX,MAAM,aAAa,GAAG,CAAC;KACpB,MAAM,CAAC;IACN,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAClC,aAAa,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CAClF,CAAC;KACD,MAAM,EAAE,CAAA;AAEX,MAAM,cAAc,GAAG,CAAC;KACrB,MAAM,CAAC;IACN,OAAO,EAAE,cAAc,CAAC,QAAQ,EAAE;IAClC,IAAI,EAAE,cAAc,CAAC,QAAQ,EAAE;IAC/B,OAAO,EAAE,cAAc,CAAC,QAAQ,EAAE;
|
|
1
|
+
{"version":3,"file":"gatewayMetadata.js","sourceRoot":"","sources":["../../../lib/gateway/gatewayMetadata.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,QAAQ,CAAA;AAE1B;;;GAGG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,iBAAiB,EAAE;IAChE,OAAO,EAAE,4EAA4E;CACtF,CAAC,CAAA;AAGF;;;GAGG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC;IACrC,CAAC,CAAC,MAAM,EAAE;IACV,CAAC,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC;IAC/B,CAAC,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC;IAChC,CAAC,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC;CAChC,CAAC,CAAA;AAGF,MAAM,gBAAgB,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC,CAAA;AAE7F,MAAM,WAAW,GAAG,CAAC;KAClB,MAAM,CAAC;IACN,OAAO,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,eAAe,CAAC,CAAC,QAAQ,EAAE;IACzD,aAAa,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,eAAe,CAAC,CAAC,QAAQ,EAAE;IAC/D,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,eAAe,CAAC,CAAC,QAAQ,EAAE;IACvD,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,eAAe,CAAC,CAAC,QAAQ,EAAE;IAC7D,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;CAC5D,CAAC;KACD,MAAM,EAAE,CAAA;AAEX,MAAM,aAAa,GAAG,CAAC;KACpB,MAAM,CAAC;IACN,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAClC,aAAa,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CAClF,CAAC;KACD,MAAM,EAAE,CAAA;AAEX,MAAM,cAAc,GAAG,CAAC;KACrB,MAAM,CAAC;IACN,OAAO,EAAE,cAAc,CAAC,QAAQ,EAAE;IAClC,IAAI,EAAE,cAAc,CAAC,QAAQ,EAAE;IAC/B,OAAO,EAAE,cAAc,CAAC,QAAQ,EAAE;IAClC;;;;;;;;;OASG;IACH,WAAW,EAAE,cAAc,CAAC,QAAQ,EAAE;CACvC,CAAC;KACD,MAAM,EAAE,CAAA;AAEX,MAAM,WAAW,GAAG,CAAC;KAClB,MAAM,CAAC;IACN,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;IAC5C,EAAE,EAAE,CAAC;SACF,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,eAAe,EAAE,iBAAiB,EAAE,OAAO,EAAE,eAAe,CAAC,CAAC,CAAC;SACpF,QAAQ,EAAE;IACb,aAAa,EAAE,cAAc,CAAC,QAAQ,EAAE;IACxC,OAAO,EAAE,CAAC;SACP,MAAM,CAAC,EAAE,IAAI,EAAE,cAAc,CAAC,QAAQ,EAAE,EAAE,GAAG,EAAE,cAAc,CAAC,QAAQ,EAAE,EAAE,CAAC;SAC3E,MAAM,EAAE;SACR,QAAQ,EAAE;CACd,CAAC;KACD,MAAM,EAAE,CAAA;AAEX,MAAM,oBAAoB,GAAG,CAAC;KAC3B,MAAM,CAAC;IACN,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE;IACtD,kBAAkB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE;IAC1D,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE;IACnD,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE,CAAC,QAAQ,EAAE;CACtD,CAAC;KACD,MAAM,EAAE,CAAA;AAEX,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC;IACjC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC;IACf,CAAC,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE;IACzC,CAAC,CAAC,MAAM,CAAC,EAAE,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE;IAC/C,CAAC,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE;IACxC,CAAC,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE;CAC/C,CAAC,CAAA;AAEF,MAAM,eAAe,GAAG,CAAC;KACtB,MAAM,CAAC;IACN,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;IACrC,GAAG,EAAE,cAAc;IACnB,GAAG,EAAE,kBAAkB,CAAC,QAAQ,EAAE;CACnC,CAAC;KACD,MAAM,EAAE,CAAA;AAEX,MAAM,aAAa,GAAG,CAAC;KACpB,MAAM,CAAC;IACN,OAAO,EAAE,CAAC;SACP,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC;SAC5F,QAAQ,EAAE;IACb,MAAM,EAAE,CAAC;SACN,MAAM,CAAC;QACN,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE;QACpB,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC;KACpC,CAAC;SACD,MAAM,EAAE;SACR,QAAQ,EAAE;CACd,CAAC;KACD,MAAM,EAAE,CAAA;AAEX,MAAM,UAAU,GAAG,CAAC;KACjB,MAAM,CAAC;IACN,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;IAC5B,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC,QAAQ,EAAE;IAC7C,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;IACvC,aAAa,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;IAC7C,WAAW,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;IACnC,MAAM,EAAE,cAAc,CAAC,QAAQ,EAAE;CAClC,CAAC;KACD,MAAM,EAAE,CAAA;AAEX,MAAM,UAAU,GAAG,CAAC;KACjB,MAAM,CAAC;IACN,QAAQ,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;IAChC,GAAG,EAAE,CAAC;SACH,MAAM,CAAC;QACN,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE;QAClB,SAAS,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;QACzC,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;KAC/B,CAAC;SACD,MAAM,EAAE;SACR,QAAQ,EAAE;IACb,IAAI,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;CAC7B,CAAC;KACD,MAAM,EAAE,CAAA;AAEX,MAAM,WAAW,GAAG,CAAC;KAClB,MAAM,CAAC;IACN,GAAG,EAAE,cAAc;IACnB,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;IACpD,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;CACrC,CAAC;KACD,MAAM,EAAE,CAAA;AAEX,MAAM,aAAa,GAAG,CAAC;KACpB,MAAM,CAAC;IACN,OAAO,EAAE,CAAC;SACP,MAAM,CAAC;QACN,GAAG,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;QAChD,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;KACvC,CAAC;SACD,MAAM,EAAE;SACR,QAAQ,EAAE;IACb,QAAQ,EAAE,CAAC;SACR,MAAM,CAAC;QACN,GAAG,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;QAChD,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;KACvC,CAAC;SACD,MAAM,EAAE;SACR,QAAQ,EAAE;CACd,CAAC;KACD,MAAM,EAAE,CAAA;AAEX,MAAM,gBAAgB,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAA;AAE3F;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC;KACnC,MAAM,CAAC;IACN,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACzB,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC/B,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;IAEpC,KAAK,EAAE,WAAW,CAAC,QAAQ,EAAE;IAC7B,OAAO,EAAE,aAAa,CAAC,QAAQ,EAAE;IAEjC,QAAQ,EAAE,cAAc,CAAC,QAAQ,EAAE;IACnC,KAAK,EAAE,WAAW,CAAC,QAAQ,EAAE;IAC7B,cAAc,EAAE,oBAAoB,CAAC,QAAQ,EAAE;IAE/C,SAAS,EAAE,eAAe,CAAC,QAAQ,EAAE;IACrC,OAAO,EAAE,aAAa,CAAC,QAAQ,EAAE;IAEjC,IAAI,EAAE,UAAU,CAAC,QAAQ,EAAE;IAC3B,IAAI,EAAE,UAAU,CAAC,QAAQ,EAAE;IAC3B,KAAK,EAAE,WAAW,CAAC,QAAQ,EAAE;IAE7B,OAAO,EAAE,aAAa,CAAC,QAAQ,EAAE;IAEjC,UAAU,EAAE,gBAAgB,CAAC,QAAQ,EAAE;CACxC,CAAC;KACD,MAAM,EAAE,CAAA"}
|
|
@@ -5,4 +5,5 @@ export type { ContractHeaderKey, ContractQueryKey, GatewayMetadata, } from './ga
|
|
|
5
5
|
export { type BuildGatewayManifestOptions, buildGatewayManifestFrom, type CollectedController, } from './manifest/buildManifest.ts';
|
|
6
6
|
export { type GatewayManifest, type GatewayManifestRoute, gatewayManifestRouteSchema, gatewayManifestSchema, } from './manifest/manifestSchema.ts';
|
|
7
7
|
export { normalizePath } from './manifest/pathNormalize.ts';
|
|
8
|
+
export { attachRouteStreamingMode, ROUTE_STREAMING_DEFAULT_MODE_SYMBOL, ROUTE_STREAMING_SYMBOL, type RouteStreamingDefaultMode, type RouteStreamingMode, readRouteStreamingDefaultMode, readRouteStreamingMode, } from './routeStreaming.ts';
|
|
8
9
|
export { readGatewayMetadata, withGatewayMetadata } from './withGatewayMetadata.ts';
|
|
@@ -4,5 +4,6 @@ export { GATEWAY_METADATA_SYMBOL } from "./gatewaySymbol.js";
|
|
|
4
4
|
export { buildGatewayManifestFrom, } from "./manifest/buildManifest.js";
|
|
5
5
|
export { gatewayManifestRouteSchema, gatewayManifestSchema, } from "./manifest/manifestSchema.js";
|
|
6
6
|
export { normalizePath } from "./manifest/pathNormalize.js";
|
|
7
|
+
export { attachRouteStreamingMode, ROUTE_STREAMING_DEFAULT_MODE_SYMBOL, ROUTE_STREAMING_SYMBOL, readRouteStreamingDefaultMode, readRouteStreamingMode, } from "./routeStreaming.js";
|
|
7
8
|
export { readGatewayMetadata, withGatewayMetadata } from "./withGatewayMetadata.js";
|
|
8
9
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../lib/gateway/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,oBAAoB,GACrB,MAAM,2BAA2B,CAAA;AAClC,OAAO,EAEL,cAAc,EAEd,qBAAqB,EAErB,eAAe,GAChB,MAAM,sBAAsB,CAAA;AAC7B,OAAO,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAA;AAM5D,OAAO,EAEL,wBAAwB,GAEzB,MAAM,6BAA6B,CAAA;AACpC,OAAO,EAGL,0BAA0B,EAC1B,qBAAqB,GACtB,MAAM,8BAA8B,CAAA;AACrC,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAA;AAC3D,OAAO,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../lib/gateway/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,oBAAoB,GACrB,MAAM,2BAA2B,CAAA;AAClC,OAAO,EAEL,cAAc,EAEd,qBAAqB,EAErB,eAAe,GAChB,MAAM,sBAAsB,CAAA;AAC7B,OAAO,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAA;AAM5D,OAAO,EAEL,wBAAwB,GAEzB,MAAM,6BAA6B,CAAA;AACpC,OAAO,EAGL,0BAA0B,EAC1B,qBAAqB,GACtB,MAAM,8BAA8B,CAAA;AACrC,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAA;AAC3D,OAAO,EACL,wBAAwB,EACxB,mCAAmC,EACnC,sBAAsB,EAGtB,6BAA6B,EAC7B,sBAAsB,GACvB,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAA"}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import type { AbstractController } from '../../AbstractController.ts';
|
|
2
2
|
import type { AbstractApiController } from '../../api-contracts/AbstractApiController.ts';
|
|
3
|
+
import type { AbstractDualModeController } from '../../dualmode/AbstractDualModeController.ts';
|
|
4
|
+
import type { AbstractSSEController } from '../../sse/AbstractSSEController.ts';
|
|
3
5
|
import type { GatewayMetadataValue } from '../gatewayMetadata.ts';
|
|
4
6
|
import { type GatewayManifest } from './manifestSchema.ts';
|
|
5
7
|
export type BuildGatewayManifestOptions = {
|
|
@@ -9,6 +11,14 @@ export type BuildGatewayManifestOptions = {
|
|
|
9
11
|
version?: string;
|
|
10
12
|
/** Service-wide metadata defaults; merged underneath controller- and route-level metadata. */
|
|
11
13
|
defaults?: GatewayMetadataValue;
|
|
14
|
+
/**
|
|
15
|
+
* Include routes from legacy `AbstractSSEController` /
|
|
16
|
+
* `AbstractDualModeController` controllers in the manifest (marked with
|
|
17
|
+
* `streaming: 'sse' | 'dual'`). Off by default so existing manifests don't
|
|
18
|
+
* silently gain routes; routes declared through `AbstractApiController` are
|
|
19
|
+
* always included regardless of this flag.
|
|
20
|
+
*/
|
|
21
|
+
includeStreamingControllers?: boolean;
|
|
12
22
|
};
|
|
13
23
|
/**
|
|
14
24
|
* Anything resolved from the DI container that may carry routes + gateway defaults.
|
|
@@ -26,6 +36,14 @@ type CollectedController = {
|
|
|
26
36
|
name: string;
|
|
27
37
|
kind: 'api';
|
|
28
38
|
controller: AbstractApiController<any>;
|
|
39
|
+
} | {
|
|
40
|
+
name: string;
|
|
41
|
+
kind: 'sse-legacy';
|
|
42
|
+
controller: AbstractSSEController<any>;
|
|
43
|
+
} | {
|
|
44
|
+
name: string;
|
|
45
|
+
kind: 'dualmode-legacy';
|
|
46
|
+
controller: AbstractDualModeController<any>;
|
|
29
47
|
};
|
|
30
48
|
/**
|
|
31
49
|
* Pure manifest builder. Takes already-resolved controllers; performs no DI.
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { merge } from 'ts-deepmerge';
|
|
2
|
+
import { buildFastifyRoute } from "../../routes/fastifyRouteBuilder.js";
|
|
3
|
+
import { readRouteStreamingDefaultMode, readRouteStreamingMode } from "../routeStreaming.js";
|
|
2
4
|
import { readGatewayMetadata } from "../withGatewayMetadata.js";
|
|
3
5
|
import { gatewayManifestSchema, } from "./manifestSchema.js";
|
|
4
6
|
import { normalizePath } from "./pathNormalize.js";
|
|
@@ -28,12 +30,40 @@ function collectRouteEntries(collected) {
|
|
|
28
30
|
const built = collected.controller.buildRoutes();
|
|
29
31
|
return Object.entries(built).map(([routeKey, route]) => ({ routeKey, route }));
|
|
30
32
|
}
|
|
33
|
+
if (collected.kind === 'sse-legacy' || collected.kind === 'dualmode-legacy') {
|
|
34
|
+
// Legacy streaming controllers return branded handler containers; build
|
|
35
|
+
// the Fastify RouteOptions from them (pure construction — no side
|
|
36
|
+
// effects, no registration) so path/method/streaming can be read.
|
|
37
|
+
const routeConfigs = collected.kind === 'sse-legacy'
|
|
38
|
+
? collected.controller.buildSSERoutes()
|
|
39
|
+
: collected.controller.buildDualModeRoutes();
|
|
40
|
+
return Object.entries(routeConfigs).map(([routeKey, routeConfig]) => ({
|
|
41
|
+
routeKey,
|
|
42
|
+
// biome-ignore lint/suspicious/noExplicitAny: overload selection erased at the manifest boundary
|
|
43
|
+
route: buildFastifyRoute(collected.controller, routeConfig),
|
|
44
|
+
}));
|
|
45
|
+
}
|
|
31
46
|
// AbstractApiController: routes is a Record — key becomes the routeKey.
|
|
32
47
|
return Object.entries(collected.controller.routes).map(([routeKey, route]) => ({
|
|
33
48
|
routeKey,
|
|
34
49
|
route,
|
|
35
50
|
}));
|
|
36
51
|
}
|
|
52
|
+
/**
|
|
53
|
+
* The manifest's streaming fields for one Fastify route, read back from the
|
|
54
|
+
* markers the route builders stamped.
|
|
55
|
+
*/
|
|
56
|
+
function readStreamingFields(route) {
|
|
57
|
+
const streaming = readRouteStreamingMode(route);
|
|
58
|
+
if (streaming === undefined)
|
|
59
|
+
return {};
|
|
60
|
+
const defaultMode = readRouteStreamingDefaultMode(route);
|
|
61
|
+
// Only a dual route negotiates, so a fallback branch is meaningless on an
|
|
62
|
+
// SSE-only one.
|
|
63
|
+
return streaming === 'dual' && defaultMode !== undefined
|
|
64
|
+
? { streaming, streamingDefaultMode: defaultMode }
|
|
65
|
+
: { streaming };
|
|
66
|
+
}
|
|
37
67
|
/**
|
|
38
68
|
* Pure manifest builder. Takes already-resolved controllers; performs no DI.
|
|
39
69
|
*
|
|
@@ -69,6 +99,7 @@ export function buildGatewayManifestFrom(controllers, options) {
|
|
|
69
99
|
path,
|
|
70
100
|
controller: collected.name,
|
|
71
101
|
routeKey,
|
|
102
|
+
...readStreamingFields(route),
|
|
72
103
|
metadata: merged,
|
|
73
104
|
});
|
|
74
105
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"buildManifest.js","sourceRoot":"","sources":["../../../../lib/gateway/manifest/buildManifest.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAE,MAAM,cAAc,CAAA;AAIpC,OAAO,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAA;AAC/D,OAAO,EAGL,qBAAqB,GACtB,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;
|
|
1
|
+
{"version":3,"file":"buildManifest.js","sourceRoot":"","sources":["../../../../lib/gateway/manifest/buildManifest.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAE,MAAM,cAAc,CAAA;AAIpC,OAAO,EAAE,iBAAiB,EAAE,MAAM,qCAAqC,CAAA;AAGvE,OAAO,EAAE,6BAA6B,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAA;AAC5F,OAAO,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAA;AAC/D,OAAO,EAGL,qBAAqB,GACtB,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAyClD,MAAM,YAAY,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,CAAU,CAAA;AAG1F,SAAS,eAAe,CAAC,MAA8B;IACrD,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CACb,+DAA+D,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,mCAAmC,CACpH,CAAA;IACH,CAAC;IACD,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,WAAW,EAAE,CAAA;IAC1C,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,KAAwB,CAAC,EAAE,CAAC;QACrD,MAAM,IAAI,KAAK,CAAC,4BAA4B,MAAM,uBAAuB,CAAC,CAAA;IAC5E,CAAC;IACD,OAAO,KAAwB,CAAA;AACjC,CAAC;AAED,SAAS,aAAa,CAAC,MAA+C;IACpE,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAA6B,EAAE,CAAC,CAAC,KAAK,SAAS,CAAC,CAAA;IAChF,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAA;IACnC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,OAAO,CAAC,CAAC,CAAyB,CAAA;IACnE,6EAA6E;IAC7E,gGAAgG;IAChG,OAAO,KAAK,CAAC,WAAW,CAAC,EAAE,WAAW,EAAE,KAAK,EAAE,EAAE,GAAI,OAAiB,CAAyB,CAAA;AACjG,CAAC;AAED,SAAS,mBAAmB,CAC1B,SAA8B;IAE9B,IAAI,SAAS,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;QAC9B,MAAM,KAAK,GAAG,SAAS,CAAC,UAAU,CAAC,WAAW,EAAkC,CAAA;QAChF,OAAO,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC,CAAA;IAChF,CAAC;IACD,IAAI,SAAS,CAAC,IAAI,KAAK,YAAY,IAAI,SAAS,CAAC,IAAI,KAAK,iBAAiB,EAAE,CAAC;QAC5E,wEAAwE;QACxE,kEAAkE;QAClE,kEAAkE;QAClE,MAAM,YAAY,GAChB,SAAS,CAAC,IAAI,KAAK,YAAY;YAC7B,CAAC,CAAC,SAAS,CAAC,UAAU,CAAC,cAAc,EAAE;YACvC,CAAC,CAAC,SAAS,CAAC,UAAU,CAAC,mBAAmB,EAAE,CAAA;QAChD,OAAO,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,EAAE,WAAW,CAAC,EAAE,EAAE,CAAC,CAAC;YACpE,QAAQ;YACR,iGAAiG;YACjG,KAAK,EAAE,iBAAiB,CAAC,SAAS,CAAC,UAAiB,EAAE,WAAkB,CAAC;SAC1E,CAAC,CAAC,CAAA;IACL,CAAC;IACD,wEAAwE;IACxE,OAAO,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC;QAC7E,QAAQ;QACR,KAAK;KACN,CAAC,CAAC,CAAA;AACL,CAAC;AAED;;;GAGG;AACH,SAAS,mBAAmB,CAC1B,KAAa;IAEb,MAAM,SAAS,GAAG,sBAAsB,CAAC,KAAK,CAAC,CAAA;IAC/C,IAAI,SAAS,KAAK,SAAS;QAAE,OAAO,EAAE,CAAA;IACtC,MAAM,WAAW,GAAG,6BAA6B,CAAC,KAAK,CAAC,CAAA;IACxD,0EAA0E;IAC1E,gBAAgB;IAChB,OAAO,SAAS,KAAK,MAAM,IAAI,WAAW,KAAK,SAAS;QACtD,CAAC,CAAC,EAAE,SAAS,EAAE,oBAAoB,EAAE,WAAW,EAAE;QAClD,CAAC,CAAC,EAAE,SAAS,EAAE,CAAA;AACnB,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,wBAAwB,CACtC,WAA+C,EAC/C,OAAoC;IAEpC,MAAM,MAAM,GAA2B,EAAE,CAAA;IACzC,wEAAwE;IACxE,yEAAyE;IACzE,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAkB,CAAA;IAE1C,KAAK,MAAM,SAAS,IAAI,WAAW,EAAE,CAAC;QACpC,MAAM,kBAAkB,GAAG,SAAS,CAAC,UAAU,CAAC,eAAe,CAAA;QAC/D,KAAK,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,mBAAmB,CAAC,SAAS,CAAC,EAAE,CAAC;YACjE,MAAM,aAAa,GAAG,mBAAmB,CAAC,KAAK,CAAC,CAAA;YAChD,MAAM,MAAM,GAAG,aAAa,CAAC,CAAC,OAAO,CAAC,QAAQ,EAAE,kBAAkB,EAAE,aAAa,CAAC,CAAC,CAAA;YAEnF,IAAI,KAAK,CAAC,GAAG,KAAK,SAAS,EAAE,CAAC;gBAC5B,MAAM,IAAI,KAAK,CACb,UAAU,SAAS,CAAC,IAAI,IAAI,QAAQ,4DAA4D,CACjG,CAAA;YACH,CAAC;YACD,MAAM,IAAI,GAAG,aAAa,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;YACrC,MAAM,MAAM,GAAG,eAAe,CAAC,KAAK,CAAC,MAAM,CAAC,CAAA;YAC5C,MAAM,MAAM,GAAG,GAAG,SAAS,CAAC,IAAI,IAAI,QAAQ,EAAE,CAAA;YAC9C,MAAM,EAAE,GAAG,MAAM,CAAC,EAAE,IAAI,MAAM,CAAA;YAE9B,MAAM,cAAc,GAAG,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;YACvC,IAAI,cAAc,EAAE,CAAC;gBACnB,MAAM,IAAI,KAAK,CACb,+BAA+B,EAAE,uBAAuB,cAAc,QAAQ,MAAM,8CAA8C,CACnI,CAAA;YACH,CAAC;YACD,QAAQ,CAAC,GAAG,CAAC,EAAE,EAAE,MAAM,CAAC,CAAA;YAExB,MAAM,CAAC,IAAI,CAAC;gBACV,EAAE;gBACF,MAAM;gBACN,IAAI;gBACJ,UAAU,EAAE,SAAS,CAAC,IAAI;gBAC1B,QAAQ;gBACR,GAAG,mBAAmB,CAAC,KAAK,CAAC;gBAC7B,QAAQ,EAAE,MAAM;aACjB,CAAC,CAAA;QACJ,CAAC;IACH,CAAC;IAED,4EAA4E;IAC5E,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CACnB,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CACpF,CAAA;IAED,MAAM,QAAQ,GAAG;QACf,eAAe,EAAE,GAAY;QAC7B,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,GAAG,CAAC,OAAO,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACtE,WAAW,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACrC,MAAM;KACP,CAAA;IAED,2EAA2E;IAC3E,oEAAoE;IACpE,4EAA4E;IAC5E,OAAO,qBAAqB,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAA;AAC9C,CAAC"}
|
|
@@ -13,6 +13,14 @@ export declare const gatewayManifestRouteSchema: z.ZodObject<{
|
|
|
13
13
|
path: z.ZodString;
|
|
14
14
|
controller: z.ZodString;
|
|
15
15
|
routeKey: z.ZodString;
|
|
16
|
+
streaming: z.ZodOptional<z.ZodEnum<{
|
|
17
|
+
sse: "sse";
|
|
18
|
+
dual: "dual";
|
|
19
|
+
}>>;
|
|
20
|
+
streamingDefaultMode: z.ZodOptional<z.ZodEnum<{
|
|
21
|
+
sse: "sse";
|
|
22
|
+
"non-sse": "non-sse";
|
|
23
|
+
}>>;
|
|
16
24
|
metadata: z.ZodObject<{
|
|
17
25
|
id: z.ZodOptional<z.ZodString>;
|
|
18
26
|
upstream: z.ZodOptional<z.ZodString>;
|
|
@@ -59,6 +67,7 @@ export declare const gatewayManifestRouteSchema: z.ZodObject<{
|
|
|
59
67
|
request: z.ZodOptional<z.ZodString>;
|
|
60
68
|
idle: z.ZodOptional<z.ZodString>;
|
|
61
69
|
connect: z.ZodOptional<z.ZodString>;
|
|
70
|
+
maxDuration: z.ZodOptional<z.ZodString>;
|
|
62
71
|
}, z.core.$strict>>;
|
|
63
72
|
retry: z.ZodOptional<z.ZodObject<{
|
|
64
73
|
attempts: z.ZodOptional<z.ZodNumber>;
|
|
@@ -169,6 +178,14 @@ export declare const gatewayManifestSchema: z.ZodObject<{
|
|
|
169
178
|
path: z.ZodString;
|
|
170
179
|
controller: z.ZodString;
|
|
171
180
|
routeKey: z.ZodString;
|
|
181
|
+
streaming: z.ZodOptional<z.ZodEnum<{
|
|
182
|
+
sse: "sse";
|
|
183
|
+
dual: "dual";
|
|
184
|
+
}>>;
|
|
185
|
+
streamingDefaultMode: z.ZodOptional<z.ZodEnum<{
|
|
186
|
+
sse: "sse";
|
|
187
|
+
"non-sse": "non-sse";
|
|
188
|
+
}>>;
|
|
172
189
|
metadata: z.ZodObject<{
|
|
173
190
|
id: z.ZodOptional<z.ZodString>;
|
|
174
191
|
upstream: z.ZodOptional<z.ZodString>;
|
|
@@ -215,6 +232,7 @@ export declare const gatewayManifestSchema: z.ZodObject<{
|
|
|
215
232
|
request: z.ZodOptional<z.ZodString>;
|
|
216
233
|
idle: z.ZodOptional<z.ZodString>;
|
|
217
234
|
connect: z.ZodOptional<z.ZodString>;
|
|
235
|
+
maxDuration: z.ZodOptional<z.ZodString>;
|
|
218
236
|
}, z.core.$strict>>;
|
|
219
237
|
retry: z.ZodOptional<z.ZodObject<{
|
|
220
238
|
attempts: z.ZodOptional<z.ZodNumber>;
|
|
@@ -12,6 +12,33 @@ export const gatewayManifestRouteSchema = z
|
|
|
12
12
|
controller: z.string(),
|
|
13
13
|
/** Key of the route inside the controller (`buildRoutes` map key, or array index for `AbstractApiController`). */
|
|
14
14
|
routeKey: z.string(),
|
|
15
|
+
/**
|
|
16
|
+
* How the route responds on the success path: `'sse'` (always streams) or
|
|
17
|
+
* `'dual'` (Accept-negotiated, stream or not). Absent for routes that
|
|
18
|
+
* answer in a single response. Generators use this to apply
|
|
19
|
+
* streaming-appropriate timeouts and disable response buffering.
|
|
20
|
+
*
|
|
21
|
+
* Success path only: a 4xx or 5xx is an ordinary JSON response on a
|
|
22
|
+
* streaming route too, so a generator may size timeouts from this but must
|
|
23
|
+
* not assume the content type of a failure.
|
|
24
|
+
*
|
|
25
|
+
* Additive optional field — manifests remain `manifestVersion: '1'`.
|
|
26
|
+
* Because the schemas are `.strict()`, generators must run against a
|
|
27
|
+
* library version that knows every field the manifest may carry (the
|
|
28
|
+
* gateway packages' peerDependency floor tracks this).
|
|
29
|
+
*/
|
|
30
|
+
streaming: z.enum(['sse', 'dual']).optional(),
|
|
31
|
+
/**
|
|
32
|
+
* For `streaming: 'dual'` routes, which branch serves a request whose
|
|
33
|
+
* `Accept` header names neither type (absent, or a wildcard). Mirrors the
|
|
34
|
+
* route's `defaultMode` option. Absent means `'non-sse'`.
|
|
35
|
+
*
|
|
36
|
+
* A generator that splits a dual route into a stream branch and a
|
|
37
|
+
* catch-all needs this: with `'sse'` the catch-all is the STREAM, and
|
|
38
|
+
* routing it as non-streaming would put a request timeout on a long-lived
|
|
39
|
+
* stream.
|
|
40
|
+
*/
|
|
41
|
+
streamingDefaultMode: z.enum(['non-sse', 'sse']).optional(),
|
|
15
42
|
/** Already-merged metadata: service defaults → controller defaults → route. */
|
|
16
43
|
metadata: gatewayMetadataSchema,
|
|
17
44
|
})
|