@taskcast/server 0.3.0 → 1.0.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.ts +37 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +148 -9
- package/dist/index.js.map +1 -1
- package/dist/routes/admin.d.ts +15 -0
- package/dist/routes/admin.d.ts.map +1 -0
- package/dist/routes/admin.js +59 -0
- package/dist/routes/admin.js.map +1 -0
- package/dist/routes/sse.d.ts +5 -2
- package/dist/routes/sse.d.ts.map +1 -1
- package/dist/routes/sse.js +73 -6
- package/dist/routes/sse.js.map +1 -1
- package/dist/routes/tasks.d.ts +3 -2
- package/dist/routes/tasks.d.ts.map +1 -1
- package/dist/routes/tasks.js +216 -47
- package/dist/routes/tasks.js.map +1 -1
- package/dist/routes/worker-ws.d.ts +9 -1
- package/dist/routes/worker-ws.d.ts.map +1 -1
- package/dist/routes/worker-ws.js +21 -1
- package/dist/routes/worker-ws.js.map +1 -1
- package/dist/routes/workers.d.ts +3 -3
- package/dist/routes/workers.d.ts.map +1 -1
- package/dist/routes/workers.js +129 -20
- package/dist/routes/workers.js.map +1 -1
- package/dist/schemas.d.ts +359 -0
- package/dist/schemas.d.ts.map +1 -0
- package/dist/schemas.js +143 -0
- package/dist/schemas.js.map +1 -0
- package/dist/testing.d.ts +14 -0
- package/dist/testing.d.ts.map +1 -0
- package/dist/testing.js +20 -0
- package/dist/testing.js.map +1 -0
- package/package.json +9 -3
package/dist/index.d.ts
CHANGED
|
@@ -1,21 +1,52 @@
|
|
|
1
1
|
export { createAuthMiddleware, checkScope } from './auth.js';
|
|
2
2
|
export type { AuthConfig, AuthContext, JWTConfig } from './auth.js';
|
|
3
3
|
export { createTasksRouter } from './routes/tasks.js';
|
|
4
|
-
export { createSSERouter } from './routes/sse.js';
|
|
5
|
-
export {
|
|
4
|
+
export { createSSERouter, createSubscriberCounts, getSubscriberCount } from './routes/sse.js';
|
|
5
|
+
export type { SubscriberCounts } from './routes/sse.js';
|
|
6
|
+
export { createWorkersRouter, WorkerWSHandler, WorkerWSRegistry } from './routes/workers.js';
|
|
6
7
|
export type { WSLike, TaskSummary } from './routes/workers.js';
|
|
8
|
+
export { createAdminRouter } from './routes/admin.js';
|
|
9
|
+
export type { AdminRouteOptions } from './routes/admin.js';
|
|
7
10
|
export { WebhookDelivery } from './webhook.js';
|
|
8
|
-
|
|
11
|
+
export { TaskSchema, TaskEventSchema, WorkerSchema, ErrorSchema, CreateTaskSchema, TransitionSchema, PublishEventSchema, } from './schemas.js';
|
|
12
|
+
import type { Hono } from 'hono';
|
|
13
|
+
import { WorkerWSRegistry } from './routes/worker-ws.js';
|
|
9
14
|
import type { AuthConfig } from './auth.js';
|
|
10
|
-
import type { TaskEngine, WorkerManager } from '@taskcast/core';
|
|
15
|
+
import type { TaskEngine, WorkerManager, ShortTermStore, DisconnectPolicy, TaskcastConfig } from '@taskcast/core';
|
|
11
16
|
export interface TaskcastServerOptions {
|
|
12
17
|
engine: TaskEngine;
|
|
13
18
|
workerManager?: WorkerManager;
|
|
19
|
+
shortTermStore?: ShortTermStore;
|
|
14
20
|
auth?: AuthConfig;
|
|
21
|
+
config?: TaskcastConfig;
|
|
22
|
+
cors?: boolean | {
|
|
23
|
+
origin: string | string[];
|
|
24
|
+
};
|
|
25
|
+
scheduler?: {
|
|
26
|
+
enabled?: boolean;
|
|
27
|
+
checkIntervalMs?: number;
|
|
28
|
+
pausedColdAfterMs?: number;
|
|
29
|
+
blockedColdAfterMs?: number;
|
|
30
|
+
};
|
|
31
|
+
heartbeat?: {
|
|
32
|
+
enabled?: boolean;
|
|
33
|
+
checkIntervalMs?: number;
|
|
34
|
+
heartbeatTimeoutMs?: number;
|
|
35
|
+
defaultDisconnectPolicy?: DisconnectPolicy;
|
|
36
|
+
disconnectGraceMs?: number;
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
export interface TaskcastApp {
|
|
40
|
+
app: Hono;
|
|
41
|
+
wsRegistry?: WorkerWSRegistry;
|
|
42
|
+
stop(): void;
|
|
15
43
|
}
|
|
16
44
|
/**
|
|
17
|
-
* Creates
|
|
45
|
+
* Creates an OpenAPIHono app with all taskcast routes mounted.
|
|
18
46
|
* Can be used standalone or mounted into an existing Hono app.
|
|
47
|
+
*
|
|
48
|
+
* Returns a TaskcastApp with `app` (the Hono instance) and `stop()` to
|
|
49
|
+
* clean up scheduler/heartbeat timers.
|
|
19
50
|
*/
|
|
20
|
-
export declare function createTaskcastApp(opts: TaskcastServerOptions):
|
|
51
|
+
export declare function createTaskcastApp(opts: TaskcastServerOptions): TaskcastApp;
|
|
21
52
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,UAAU,EAAE,MAAM,WAAW,CAAA;AAC5D,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,WAAW,CAAA;AACnE,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,UAAU,EAAE,MAAM,WAAW,CAAA;AAC5D,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,WAAW,CAAA;AACnE,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AACrD,OAAO,EAAE,eAAe,EAAE,sBAAsB,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAA;AAC7F,YAAY,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAA;AACvD,OAAO,EAAE,mBAAmB,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAA;AAC5F,YAAY,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAA;AAC9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AACrD,YAAY,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AAC1D,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AAC9C,OAAO,EACL,UAAU,EAAE,eAAe,EAAE,YAAY,EAAE,WAAW,EACtD,gBAAgB,EAAE,gBAAgB,EAAE,kBAAkB,GACvD,MAAM,cAAc,CAAA;AAErB,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAQhC,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AAExD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAA;AAE3C,OAAO,KAAK,EAEV,UAAU,EACV,aAAa,EACb,cAAc,EACd,gBAAgB,EAChB,cAAc,EACf,MAAM,gBAAgB,CAAA;AAIvB,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,UAAU,CAAA;IAClB,aAAa,CAAC,EAAE,aAAa,CAAA;IAC7B,cAAc,CAAC,EAAE,cAAc,CAAA;IAC/B,IAAI,CAAC,EAAE,UAAU,CAAA;IACjB,MAAM,CAAC,EAAE,cAAc,CAAA;IACvB,IAAI,CAAC,EAAE,OAAO,GAAG;QAAE,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAA;KAAE,CAAA;IAC9C,SAAS,CAAC,EAAE;QACV,OAAO,CAAC,EAAE,OAAO,CAAA;QACjB,eAAe,CAAC,EAAE,MAAM,CAAA;QACxB,iBAAiB,CAAC,EAAE,MAAM,CAAA;QAC1B,kBAAkB,CAAC,EAAE,MAAM,CAAA;KAC5B,CAAA;IACD,SAAS,CAAC,EAAE;QACV,OAAO,CAAC,EAAE,OAAO,CAAA;QACjB,eAAe,CAAC,EAAE,MAAM,CAAA;QACxB,kBAAkB,CAAC,EAAE,MAAM,CAAA;QAC3B,uBAAuB,CAAC,EAAE,gBAAgB,CAAA;QAC1C,iBAAiB,CAAC,EAAE,MAAM,CAAA;KAC3B,CAAA;CACF;AAED,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,IAAI,CAAA;IACT,UAAU,CAAC,EAAE,gBAAgB,CAAA;IAC7B,IAAI,IAAI,IAAI,CAAA;CACb;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,qBAAqB,GAAG,WAAW,CA0I1E"}
|
package/dist/index.js
CHANGED
|
@@ -1,26 +1,165 @@
|
|
|
1
1
|
export { createAuthMiddleware, checkScope } from './auth.js';
|
|
2
2
|
export { createTasksRouter } from './routes/tasks.js';
|
|
3
|
-
export { createSSERouter } from './routes/sse.js';
|
|
4
|
-
export { createWorkersRouter, WorkerWSHandler } from './routes/workers.js';
|
|
3
|
+
export { createSSERouter, createSubscriberCounts, getSubscriberCount } from './routes/sse.js';
|
|
4
|
+
export { createWorkersRouter, WorkerWSHandler, WorkerWSRegistry } from './routes/workers.js';
|
|
5
|
+
export { createAdminRouter } from './routes/admin.js';
|
|
5
6
|
export { WebhookDelivery } from './webhook.js';
|
|
6
|
-
|
|
7
|
+
export { TaskSchema, TaskEventSchema, WorkerSchema, ErrorSchema, CreateTaskSchema, TransitionSchema, PublishEventSchema, } from './schemas.js';
|
|
8
|
+
import { OpenAPIHono } from '@hono/zod-openapi';
|
|
9
|
+
import { cors } from 'hono/cors';
|
|
10
|
+
import { apiReference } from '@scalar/hono-api-reference';
|
|
7
11
|
import { createAuthMiddleware } from './auth.js';
|
|
8
12
|
import { createTasksRouter } from './routes/tasks.js';
|
|
9
|
-
import { createSSERouter } from './routes/sse.js';
|
|
13
|
+
import { createSSERouter, createSubscriberCounts } from './routes/sse.js';
|
|
10
14
|
import { createWorkersRouter } from './routes/workers.js';
|
|
15
|
+
import { WorkerWSRegistry } from './routes/worker-ws.js';
|
|
16
|
+
import { createAdminRouter } from './routes/admin.js';
|
|
17
|
+
import { isTerminal, matchesWorkerRule } from '@taskcast/core';
|
|
18
|
+
import { TaskScheduler } from '@taskcast/core';
|
|
19
|
+
import { HeartbeatMonitor } from '@taskcast/core';
|
|
11
20
|
/**
|
|
12
|
-
* Creates
|
|
21
|
+
* Creates an OpenAPIHono app with all taskcast routes mounted.
|
|
13
22
|
* Can be used standalone or mounted into an existing Hono app.
|
|
23
|
+
*
|
|
24
|
+
* Returns a TaskcastApp with `app` (the Hono instance) and `stop()` to
|
|
25
|
+
* clean up scheduler/heartbeat timers.
|
|
14
26
|
*/
|
|
15
27
|
export function createTaskcastApp(opts) {
|
|
16
|
-
const app = new
|
|
28
|
+
const app = new OpenAPIHono();
|
|
29
|
+
// CORS middleware
|
|
30
|
+
if (opts.cors) {
|
|
31
|
+
const origin = opts.cors === true ? '*' : opts.cors.origin;
|
|
32
|
+
app.use('*', cors({ origin }));
|
|
33
|
+
}
|
|
17
34
|
app.get('/health', (c) => c.json({ ok: true }));
|
|
35
|
+
// Admin route is mounted BEFORE auth middleware so it bypasses JWT/custom auth.
|
|
36
|
+
// It authenticates via admin token independently.
|
|
37
|
+
if (opts.config) {
|
|
38
|
+
app.route('/admin', createAdminRouter({ config: opts.config, auth: opts.auth }));
|
|
39
|
+
}
|
|
40
|
+
const subscriberCounts = createSubscriberCounts();
|
|
18
41
|
app.use('*', createAuthMiddleware(opts.auth ?? { mode: 'none' }));
|
|
19
|
-
app.route('/tasks', createTasksRouter(opts.engine));
|
|
20
|
-
app.route('/tasks', createSSERouter(opts.engine));
|
|
42
|
+
app.route('/tasks', createTasksRouter(opts.engine, subscriberCounts));
|
|
43
|
+
app.route('/tasks', createSSERouter(opts.engine, subscriberCounts));
|
|
44
|
+
const cleanups = [];
|
|
45
|
+
// Wire scheduler
|
|
46
|
+
let scheduler;
|
|
47
|
+
if (opts.scheduler?.enabled !== false && opts.shortTermStore) {
|
|
48
|
+
const schedulerOpts = {
|
|
49
|
+
engine: opts.engine,
|
|
50
|
+
shortTermStore: opts.shortTermStore,
|
|
51
|
+
};
|
|
52
|
+
if (opts.scheduler?.checkIntervalMs !== undefined)
|
|
53
|
+
schedulerOpts.checkIntervalMs = opts.scheduler.checkIntervalMs;
|
|
54
|
+
if (opts.scheduler?.pausedColdAfterMs !== undefined)
|
|
55
|
+
schedulerOpts.pausedColdAfterMs = opts.scheduler.pausedColdAfterMs;
|
|
56
|
+
if (opts.scheduler?.blockedColdAfterMs !== undefined)
|
|
57
|
+
schedulerOpts.blockedColdAfterMs = opts.scheduler.blockedColdAfterMs;
|
|
58
|
+
scheduler = new TaskScheduler(schedulerOpts);
|
|
59
|
+
scheduler.start();
|
|
60
|
+
cleanups.push(() => scheduler.stop());
|
|
61
|
+
}
|
|
62
|
+
// Wire worker manager
|
|
63
|
+
let wsRegistry;
|
|
21
64
|
if (opts.workerManager) {
|
|
65
|
+
const wm = opts.workerManager;
|
|
66
|
+
wsRegistry = new WorkerWSRegistry();
|
|
67
|
+
// Auto-release capacity on terminal transitions
|
|
68
|
+
opts.engine.addTransitionListener((_task, _from, to) => {
|
|
69
|
+
if (isTerminal(to)) {
|
|
70
|
+
wm.releaseTask(_task.id).catch(() => { });
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
// Wire ws-offer/ws-race dispatch on pending transitions
|
|
74
|
+
async function dispatchToWS(task) {
|
|
75
|
+
if (task.assignMode === 'ws-offer') {
|
|
76
|
+
const result = await wm.dispatchTask(task.id);
|
|
77
|
+
if (result.matched && result.workerId) {
|
|
78
|
+
const handler = wsRegistry.get(result.workerId);
|
|
79
|
+
if (handler)
|
|
80
|
+
handler.offerTask(task);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
else if (task.assignMode === 'ws-race') {
|
|
84
|
+
const workers = await wm.listWorkers({ status: ['idle', 'busy'] });
|
|
85
|
+
for (const worker of workers) {
|
|
86
|
+
if (worker.connectionMode !== 'websocket')
|
|
87
|
+
continue;
|
|
88
|
+
if (!matchesWorkerRule(task, worker.matchRule))
|
|
89
|
+
continue;
|
|
90
|
+
const cost = task.cost ?? 1;
|
|
91
|
+
if (worker.usedSlots + cost > worker.capacity)
|
|
92
|
+
continue;
|
|
93
|
+
const handler = wsRegistry.get(worker.id);
|
|
94
|
+
if (handler)
|
|
95
|
+
handler.broadcastAvailable(task);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
// Dispatch on initial task creation
|
|
100
|
+
opts.engine.addCreationListener((task) => {
|
|
101
|
+
if (!task.assignMode || (task.assignMode !== 'ws-offer' && task.assignMode !== 'ws-race'))
|
|
102
|
+
return;
|
|
103
|
+
dispatchToWS(task).catch(() => { });
|
|
104
|
+
});
|
|
105
|
+
// Re-dispatch when task transitions back to pending (e.g. after decline)
|
|
106
|
+
opts.engine.addTransitionListener((task, _from, to) => {
|
|
107
|
+
if (to !== 'pending')
|
|
108
|
+
return;
|
|
109
|
+
if (!task.assignMode || (task.assignMode !== 'ws-offer' && task.assignMode !== 'ws-race'))
|
|
110
|
+
return;
|
|
111
|
+
// Fire-and-forget async dispatch
|
|
112
|
+
dispatchToWS(task).catch(() => { });
|
|
113
|
+
});
|
|
22
114
|
app.route('/workers', createWorkersRouter(opts.workerManager, opts.engine));
|
|
115
|
+
// Wire heartbeat monitor
|
|
116
|
+
if (opts.heartbeat?.enabled !== false && opts.shortTermStore) {
|
|
117
|
+
const monitorOpts = {
|
|
118
|
+
workerManager: wm,
|
|
119
|
+
engine: opts.engine,
|
|
120
|
+
shortTermStore: opts.shortTermStore,
|
|
121
|
+
};
|
|
122
|
+
if (opts.heartbeat?.checkIntervalMs !== undefined)
|
|
123
|
+
monitorOpts.checkIntervalMs = opts.heartbeat.checkIntervalMs;
|
|
124
|
+
if (opts.heartbeat?.heartbeatTimeoutMs !== undefined)
|
|
125
|
+
monitorOpts.heartbeatTimeoutMs = opts.heartbeat.heartbeatTimeoutMs;
|
|
126
|
+
if (opts.heartbeat?.defaultDisconnectPolicy !== undefined)
|
|
127
|
+
monitorOpts.defaultDisconnectPolicy = opts.heartbeat.defaultDisconnectPolicy;
|
|
128
|
+
if (opts.heartbeat?.disconnectGraceMs !== undefined)
|
|
129
|
+
monitorOpts.disconnectGraceMs = opts.heartbeat.disconnectGraceMs;
|
|
130
|
+
const monitor = new HeartbeatMonitor(monitorOpts);
|
|
131
|
+
monitor.start();
|
|
132
|
+
cleanups.push(() => monitor.stop());
|
|
133
|
+
}
|
|
23
134
|
}
|
|
24
|
-
|
|
135
|
+
// Register security scheme
|
|
136
|
+
app.openAPIRegistry.registerComponent('securitySchemes', 'Bearer', {
|
|
137
|
+
type: 'http',
|
|
138
|
+
scheme: 'bearer',
|
|
139
|
+
bearerFormat: 'JWT',
|
|
140
|
+
description: 'JWT Bearer token. Required scopes vary per endpoint.',
|
|
141
|
+
});
|
|
142
|
+
// OpenAPI spec endpoint
|
|
143
|
+
app.doc('/openapi.json', {
|
|
144
|
+
openapi: '3.1.0',
|
|
145
|
+
info: {
|
|
146
|
+
title: 'Taskcast API',
|
|
147
|
+
version: '0.3.0',
|
|
148
|
+
description: 'Unified long-lifecycle task tracking service for LLM streaming, agents, and async workloads.',
|
|
149
|
+
},
|
|
150
|
+
security: [{ Bearer: [] }],
|
|
151
|
+
});
|
|
152
|
+
// API documentation UI
|
|
153
|
+
app.get('/docs', apiReference({
|
|
154
|
+
url: '/openapi.json',
|
|
155
|
+
}));
|
|
156
|
+
return {
|
|
157
|
+
app: app,
|
|
158
|
+
...(wsRegistry !== undefined && { wsRegistry }),
|
|
159
|
+
stop() {
|
|
160
|
+
for (const fn of cleanups)
|
|
161
|
+
fn();
|
|
162
|
+
},
|
|
163
|
+
};
|
|
25
164
|
}
|
|
26
165
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,UAAU,EAAE,MAAM,WAAW,CAAA;AAE5D,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,UAAU,EAAE,MAAM,WAAW,CAAA;AAE5D,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AACrD,OAAO,EAAE,eAAe,EAAE,sBAAsB,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAA;AAE7F,OAAO,EAAE,mBAAmB,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAA;AAE5F,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AAErD,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AAC9C,OAAO,EACL,UAAU,EAAE,eAAe,EAAE,YAAY,EAAE,WAAW,EACtD,gBAAgB,EAAE,gBAAgB,EAAE,kBAAkB,GACvD,MAAM,cAAc,CAAA;AAGrB,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAC/C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAChC,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAA;AACzD,OAAO,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAA;AAChD,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AACrD,OAAO,EAAE,eAAe,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAA;AACzE,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAA;AACzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AACxD,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AAErD,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAA;AAS9D,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AAC9C,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;AA8BjD;;;;;;GAMG;AACH,MAAM,UAAU,iBAAiB,CAAC,IAA2B;IAC3D,MAAM,GAAG,GAAG,IAAI,WAAW,EAAE,CAAA;IAE7B,kBAAkB;IAClB,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;QACd,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAA;QAC1D,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAA;IAChC,CAAC;IAED,GAAG,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAA;IAE/C,gFAAgF;IAChF,kDAAkD;IAClD,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;QAChB,GAAG,CAAC,KAAK,CAAC,QAAQ,EAAE,iBAAiB,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAA;IAClF,CAAC;IAED,MAAM,gBAAgB,GAAG,sBAAsB,EAAE,CAAA;IAEjD,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,oBAAoB,CAAC,IAAI,CAAC,IAAI,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC,CAAA;IACjE,GAAG,CAAC,KAAK,CAAC,QAAQ,EAAE,iBAAiB,CAAC,IAAI,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC,CAAA;IACrE,GAAG,CAAC,KAAK,CAAC,QAAQ,EAAE,eAAe,CAAC,IAAI,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC,CAAA;IAEnE,MAAM,QAAQ,GAAsB,EAAE,CAAA;IAEtC,iBAAiB;IACjB,IAAI,SAAoC,CAAA;IACxC,IAAI,IAAI,CAAC,SAAS,EAAE,OAAO,KAAK,KAAK,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;QAC7D,MAAM,aAAa,GAAmD;YACpE,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,cAAc,EAAE,IAAI,CAAC,cAAc;SACpC,CAAA;QACD,IAAI,IAAI,CAAC,SAAS,EAAE,eAAe,KAAK,SAAS;YAAE,aAAa,CAAC,eAAe,GAAG,IAAI,CAAC,SAAS,CAAC,eAAe,CAAA;QACjH,IAAI,IAAI,CAAC,SAAS,EAAE,iBAAiB,KAAK,SAAS;YAAE,aAAa,CAAC,iBAAiB,GAAG,IAAI,CAAC,SAAS,CAAC,iBAAiB,CAAA;QACvH,IAAI,IAAI,CAAC,SAAS,EAAE,kBAAkB,KAAK,SAAS;YAAE,aAAa,CAAC,kBAAkB,GAAG,IAAI,CAAC,SAAS,CAAC,kBAAkB,CAAA;QAC1H,SAAS,GAAG,IAAI,aAAa,CAAC,aAAa,CAAC,CAAA;QAC5C,SAAS,CAAC,KAAK,EAAE,CAAA;QACjB,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,SAAU,CAAC,IAAI,EAAE,CAAC,CAAA;IACxC,CAAC;IAED,sBAAsB;IACtB,IAAI,UAAwC,CAAA;IAC5C,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;QACvB,MAAM,EAAE,GAAG,IAAI,CAAC,aAAa,CAAA;QAC7B,UAAU,GAAG,IAAI,gBAAgB,EAAE,CAAA;QAEnC,gDAAgD;QAChD,IAAI,CAAC,MAAM,CAAC,qBAAqB,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE;YACrD,IAAI,UAAU,CAAC,EAAE,CAAC,EAAE,CAAC;gBACnB,EAAE,CAAC,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAA;YAC1C,CAAC;QACH,CAAC,CAAC,CAAA;QAEF,wDAAwD;QACxD,KAAK,UAAU,YAAY,CAAC,IAAU;YACpC,IAAI,IAAI,CAAC,UAAU,KAAK,UAAU,EAAE,CAAC;gBACnC,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;gBAC7C,IAAI,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;oBACtC,MAAM,OAAO,GAAG,UAAW,CAAC,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAA;oBAChD,IAAI,OAAO;wBAAE,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,CAAA;gBACtC,CAAC;YACH,CAAC;iBAAM,IAAI,IAAI,CAAC,UAAU,KAAK,SAAS,EAAE,CAAC;gBACzC,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,CAAA;gBAClE,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;oBAC7B,IAAI,MAAM,CAAC,cAAc,KAAK,WAAW;wBAAE,SAAQ;oBACnD,IAAI,CAAC,iBAAiB,CAAC,IAAI,EAAE,MAAM,CAAC,SAAS,CAAC;wBAAE,SAAQ;oBACxD,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,CAAC,CAAA;oBAC3B,IAAI,MAAM,CAAC,SAAS,GAAG,IAAI,GAAG,MAAM,CAAC,QAAQ;wBAAE,SAAQ;oBACvD,MAAM,OAAO,GAAG,UAAW,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;oBAC1C,IAAI,OAAO;wBAAE,OAAO,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAA;gBAC/C,CAAC;YACH,CAAC;QACH,CAAC;QAED,oCAAoC;QACpC,IAAI,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAC,IAAI,EAAE,EAAE;YACvC,IAAI,CAAC,IAAI,CAAC,UAAU,IAAI,CAAC,IAAI,CAAC,UAAU,KAAK,UAAU,IAAI,IAAI,CAAC,UAAU,KAAK,SAAS,CAAC;gBAAE,OAAM;YACjG,YAAY,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAA;QACpC,CAAC,CAAC,CAAA;QAEF,yEAAyE;QACzE,IAAI,CAAC,MAAM,CAAC,qBAAqB,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE;YACpD,IAAI,EAAE,KAAK,SAAS;gBAAE,OAAM;YAC5B,IAAI,CAAC,IAAI,CAAC,UAAU,IAAI,CAAC,IAAI,CAAC,UAAU,KAAK,UAAU,IAAI,IAAI,CAAC,UAAU,KAAK,SAAS,CAAC;gBAAE,OAAM;YACjG,iCAAiC;YACjC,YAAY,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAA;QACpC,CAAC,CAAC,CAAA;QAEF,GAAG,CAAC,KAAK,CAAC,UAAU,EAAE,mBAAmB,CAAC,IAAI,CAAC,aAAa,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,CAAA;QAE3E,yBAAyB;QACzB,IAAI,IAAI,CAAC,SAAS,EAAE,OAAO,KAAK,KAAK,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;YAC7D,MAAM,WAAW,GAAsD;gBACrE,aAAa,EAAE,EAAE;gBACjB,MAAM,EAAE,IAAI,CAAC,MAAM;gBACnB,cAAc,EAAE,IAAI,CAAC,cAAc;aACpC,CAAA;YACD,IAAI,IAAI,CAAC,SAAS,EAAE,eAAe,KAAK,SAAS;gBAAE,WAAW,CAAC,eAAe,GAAG,IAAI,CAAC,SAAS,CAAC,eAAe,CAAA;YAC/G,IAAI,IAAI,CAAC,SAAS,EAAE,kBAAkB,KAAK,SAAS;gBAAE,WAAW,CAAC,kBAAkB,GAAG,IAAI,CAAC,SAAS,CAAC,kBAAkB,CAAA;YACxH,IAAI,IAAI,CAAC,SAAS,EAAE,uBAAuB,KAAK,SAAS;gBAAE,WAAW,CAAC,uBAAuB,GAAG,IAAI,CAAC,SAAS,CAAC,uBAAuB,CAAA;YACvI,IAAI,IAAI,CAAC,SAAS,EAAE,iBAAiB,KAAK,SAAS;gBAAE,WAAW,CAAC,iBAAiB,GAAG,IAAI,CAAC,SAAS,CAAC,iBAAiB,CAAA;YACrH,MAAM,OAAO,GAAG,IAAI,gBAAgB,CAAC,WAAW,CAAC,CAAA;YACjD,OAAO,CAAC,KAAK,EAAE,CAAA;YACf,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAA;QACrC,CAAC;IACH,CAAC;IAED,2BAA2B;IAC3B,GAAG,CAAC,eAAe,CAAC,iBAAiB,CAAC,iBAAiB,EAAE,QAAQ,EAAE;QACjE,IAAI,EAAE,MAAM;QACZ,MAAM,EAAE,QAAQ;QAChB,YAAY,EAAE,KAAK;QACnB,WAAW,EAAE,sDAAsD;KACpE,CAAC,CAAA;IAEF,wBAAwB;IACxB,GAAG,CAAC,GAAG,CAAC,eAAe,EAAE;QACvB,OAAO,EAAE,OAAO;QAChB,IAAI,EAAE;YACJ,KAAK,EAAE,cAAc;YACrB,OAAO,EAAE,OAAO;YAChB,WAAW,EAAE,8FAA8F;SAC5G;QACD,QAAQ,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;KAC3B,CAAC,CAAA;IAEF,uBAAuB;IACvB,GAAG,CAAC,GAAG,CAAC,OAAO,EAAE,YAAY,CAAC;QAC5B,GAAG,EAAE,eAAe;KACrB,CAAC,CAAC,CAAA;IAEH,OAAO;QACL,GAAG,EAAE,GAAsB;QAC3B,GAAG,CAAC,UAAU,KAAK,SAAS,IAAI,EAAE,UAAU,EAAE,CAAC;QAC/C,IAAI;YACF,KAAK,MAAM,EAAE,IAAI,QAAQ;gBAAE,EAAE,EAAE,CAAA;QACjC,CAAC;KACF,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Hono } from 'hono';
|
|
2
|
+
import type { TaskcastConfig } from '@taskcast/core';
|
|
3
|
+
import type { AuthConfig } from '../auth.js';
|
|
4
|
+
export interface AdminRouteOptions {
|
|
5
|
+
config: TaskcastConfig;
|
|
6
|
+
auth?: AuthConfig | undefined;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Creates the admin router with POST /token endpoint.
|
|
10
|
+
*
|
|
11
|
+
* This route is intentionally NOT behind the normal auth middleware.
|
|
12
|
+
* It authenticates via admin token and issues JWTs (when auth mode is jwt).
|
|
13
|
+
*/
|
|
14
|
+
export declare function createAdminRouter(opts: AdminRouteOptions): Hono;
|
|
15
|
+
//# sourceMappingURL=admin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"admin.d.ts","sourceRoot":"","sources":["../../src/routes/admin.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAE3B,OAAO,KAAK,EAAE,cAAc,EAAmB,MAAM,gBAAgB,CAAA;AACrE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAE5C,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,cAAc,CAAA;IACtB,IAAI,CAAC,EAAE,UAAU,GAAG,SAAS,CAAA;CAC9B;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,iBAAiB,GAAG,IAAI,CA2D/D"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { Hono } from 'hono';
|
|
2
|
+
import { SignJWT } from 'jose';
|
|
3
|
+
/**
|
|
4
|
+
* Creates the admin router with POST /token endpoint.
|
|
5
|
+
*
|
|
6
|
+
* This route is intentionally NOT behind the normal auth middleware.
|
|
7
|
+
* It authenticates via admin token and issues JWTs (when auth mode is jwt).
|
|
8
|
+
*/
|
|
9
|
+
export function createAdminRouter(opts) {
|
|
10
|
+
const router = new Hono();
|
|
11
|
+
router.post('/token', async (c) => {
|
|
12
|
+
// 1. If adminApi is not enabled, this endpoint does not exist
|
|
13
|
+
if (!opts.config.adminApi) {
|
|
14
|
+
return c.json({ error: 'Not found' }, 404);
|
|
15
|
+
}
|
|
16
|
+
// 2. Parse and validate request body
|
|
17
|
+
let body;
|
|
18
|
+
try {
|
|
19
|
+
body = await c.req.json();
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
return c.json({ error: 'Invalid request body' }, 400);
|
|
23
|
+
}
|
|
24
|
+
const adminToken = body.adminToken;
|
|
25
|
+
if (typeof adminToken !== 'string' || adminToken === '') {
|
|
26
|
+
return c.json({ error: 'Invalid admin token' }, 401);
|
|
27
|
+
}
|
|
28
|
+
// 3. Validate admin token — ALWAYS, regardless of server auth mode
|
|
29
|
+
if (adminToken !== opts.config.adminToken) {
|
|
30
|
+
return c.json({ error: 'Invalid admin token' }, 401);
|
|
31
|
+
}
|
|
32
|
+
// 4. Parse optional fields
|
|
33
|
+
const scopes = Array.isArray(body.scopes) ? body.scopes : ['*'];
|
|
34
|
+
const expiresIn = typeof body.expiresIn === 'number' && body.expiresIn > 0
|
|
35
|
+
? body.expiresIn
|
|
36
|
+
: 86400; // default: 24h
|
|
37
|
+
const expiresAt = Math.floor(Date.now() / 1000) + expiresIn;
|
|
38
|
+
// 5. If auth mode is JWT, sign a real token
|
|
39
|
+
if (opts.auth?.mode === 'jwt' && opts.auth.jwt?.secret) {
|
|
40
|
+
const secret = new TextEncoder().encode(opts.auth.jwt.secret);
|
|
41
|
+
const algorithm = opts.auth.jwt.algorithm ?? 'HS256';
|
|
42
|
+
const jwt = await new SignJWT({
|
|
43
|
+
sub: 'admin',
|
|
44
|
+
scope: scopes,
|
|
45
|
+
taskIds: '*',
|
|
46
|
+
})
|
|
47
|
+
.setProtectedHeader({ alg: algorithm })
|
|
48
|
+
.setExpirationTime(expiresAt)
|
|
49
|
+
.setIssuedAt()
|
|
50
|
+
.sign(secret);
|
|
51
|
+
return c.json({ token: jwt, expiresAt });
|
|
52
|
+
}
|
|
53
|
+
// 6. Non-JWT mode (e.g., "none"): still validated admin token above (double insurance!)
|
|
54
|
+
// Return placeholder since no JWT system is configured
|
|
55
|
+
return c.json({ token: '', expiresAt });
|
|
56
|
+
});
|
|
57
|
+
return router;
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=admin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"admin.js","sourceRoot":"","sources":["../../src/routes/admin.ts"],"names":[],"mappings":"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"}
|
package/dist/routes/sse.d.ts
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
import { Hono } from 'hono';
|
|
1
|
+
import type { Hono } from 'hono';
|
|
2
2
|
import type { TaskEngine } from '@taskcast/core';
|
|
3
|
-
export
|
|
3
|
+
export type SubscriberCounts = Map<string, number>;
|
|
4
|
+
export declare function createSubscriberCounts(): SubscriberCounts;
|
|
5
|
+
export declare function getSubscriberCount(counts: SubscriberCounts, taskId: string): number;
|
|
6
|
+
export declare function createSSERouter(engine: TaskEngine, subscriberCounts: SubscriberCounts): Hono;
|
|
4
7
|
//# sourceMappingURL=sse.d.ts.map
|
package/dist/routes/sse.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sse.d.ts","sourceRoot":"","sources":["../../src/routes/sse.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;
|
|
1
|
+
{"version":3,"file":"sse.d.ts","sourceRoot":"","sources":["../../src/routes/sse.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAOhC,OAAO,KAAK,EAAE,UAAU,EAAkD,MAAM,gBAAgB,CAAA;AAIhG,MAAM,MAAM,gBAAgB,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;AAElD,wBAAgB,sBAAsB,IAAI,gBAAgB,CAEzD;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,gBAAgB,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAEnF;AAmGD,wBAAgB,eAAe,CAAC,MAAM,EAAE,UAAU,EAAE,gBAAgB,EAAE,gBAAgB,GAAG,IAAI,CAyF5F"}
|
package/dist/routes/sse.js
CHANGED
|
@@ -1,7 +1,53 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { OpenAPIHono, createRoute, z } from '@hono/zod-openapi';
|
|
2
2
|
import { streamSSE } from 'hono/streaming';
|
|
3
3
|
import { applyFilteredIndex, matchesFilter, TERMINAL_STATUSES } from '@taskcast/core';
|
|
4
4
|
import { checkScope } from '../auth.js';
|
|
5
|
+
import { ErrorSchema } from '../schemas.js';
|
|
6
|
+
export function createSubscriberCounts() {
|
|
7
|
+
return new Map();
|
|
8
|
+
}
|
|
9
|
+
export function getSubscriberCount(counts, taskId) {
|
|
10
|
+
return counts.get(taskId) ?? 0;
|
|
11
|
+
}
|
|
12
|
+
function incrementSubscriberCount(counts, taskId) {
|
|
13
|
+
counts.set(taskId, (counts.get(taskId) ?? 0) + 1);
|
|
14
|
+
}
|
|
15
|
+
function decrementSubscriberCount(counts, taskId) {
|
|
16
|
+
const count = (counts.get(taskId) ?? 1) - 1;
|
|
17
|
+
if (count <= 0) {
|
|
18
|
+
counts.delete(taskId);
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
counts.set(taskId, count);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
// ─── Route Definition ──────────────────────────────────────────────────────
|
|
25
|
+
const sseRoute = createRoute({
|
|
26
|
+
method: 'get',
|
|
27
|
+
path: '/{taskId}/events',
|
|
28
|
+
tags: ['Events'],
|
|
29
|
+
summary: 'Subscribe to task events via SSE',
|
|
30
|
+
description: 'Server-Sent Events stream. Replays history then streams live. Closes on terminal status.',
|
|
31
|
+
security: [{ Bearer: [] }],
|
|
32
|
+
request: {
|
|
33
|
+
params: z.object({ taskId: z.string() }),
|
|
34
|
+
query: z.object({
|
|
35
|
+
types: z.string().optional().openapi({ description: 'Comma-separated type filter with wildcard support' }),
|
|
36
|
+
levels: z.string().optional().openapi({ description: 'Comma-separated level filter' }),
|
|
37
|
+
includeStatus: z.string().optional().openapi({ description: 'Include taskcast:status events (default: true)' }),
|
|
38
|
+
wrap: z.string().optional().openapi({ description: 'Wrap in SSEEnvelope (default: true)' }),
|
|
39
|
+
'since.id': z.string().optional(),
|
|
40
|
+
'since.index': z.string().optional(),
|
|
41
|
+
'since.timestamp': z.string().optional(),
|
|
42
|
+
}),
|
|
43
|
+
},
|
|
44
|
+
responses: {
|
|
45
|
+
200: { description: 'SSE event stream (text/event-stream)' },
|
|
46
|
+
403: { description: 'Forbidden', content: { 'application/json': { schema: ErrorSchema } } },
|
|
47
|
+
404: { description: 'Task not found', content: { 'application/json': { schema: ErrorSchema } } },
|
|
48
|
+
},
|
|
49
|
+
});
|
|
50
|
+
// ─── Helpers ───────────────────────────────────────────────────────────────
|
|
5
51
|
function parseFilter(query) {
|
|
6
52
|
const get = (k) => query[k];
|
|
7
53
|
const filter = {};
|
|
@@ -47,13 +93,16 @@ function toEnvelope(event, filteredIndex) {
|
|
|
47
93
|
env.seriesId = event.seriesId;
|
|
48
94
|
if (event.seriesMode !== undefined)
|
|
49
95
|
env.seriesMode = event.seriesMode;
|
|
96
|
+
if (event.seriesAccField !== undefined)
|
|
97
|
+
env.seriesAccField = event.seriesAccField;
|
|
50
98
|
return env;
|
|
51
99
|
}
|
|
52
100
|
const TERMINAL = new Set(TERMINAL_STATUSES);
|
|
53
|
-
export function createSSERouter(engine) {
|
|
54
|
-
const router = new
|
|
55
|
-
router.
|
|
56
|
-
|
|
101
|
+
export function createSSERouter(engine, subscriberCounts) {
|
|
102
|
+
const router = new OpenAPIHono();
|
|
103
|
+
const register = router.openapi.bind(router);
|
|
104
|
+
register(sseRoute, async (c) => {
|
|
105
|
+
const taskId = c.req.param('taskId');
|
|
57
106
|
const auth = c.get('auth');
|
|
58
107
|
if (!checkScope(auth, 'event:subscribe', taskId))
|
|
59
108
|
return c.json({ error: 'Forbidden' }, 403);
|
|
@@ -63,6 +112,14 @@ export function createSSERouter(engine) {
|
|
|
63
112
|
const filter = parseFilter(c.req.query());
|
|
64
113
|
const wrap = filter.wrap !== false; // default true
|
|
65
114
|
return streamSSE(c, async (stream) => {
|
|
115
|
+
incrementSubscriberCount(subscriberCounts, taskId);
|
|
116
|
+
let decremented = false;
|
|
117
|
+
const cleanup = () => {
|
|
118
|
+
if (!decremented) {
|
|
119
|
+
decremented = true;
|
|
120
|
+
decrementSubscriberCount(subscriberCounts, taskId);
|
|
121
|
+
}
|
|
122
|
+
};
|
|
66
123
|
const sendEvent = async (event, filteredIndex) => {
|
|
67
124
|
const payload = wrap ? toEnvelope(event, filteredIndex) : event;
|
|
68
125
|
await stream.writeSSE({
|
|
@@ -78,7 +135,14 @@ export function createSSERouter(engine) {
|
|
|
78
135
|
});
|
|
79
136
|
};
|
|
80
137
|
// Replay history
|
|
81
|
-
|
|
138
|
+
let history;
|
|
139
|
+
try {
|
|
140
|
+
history = await engine.getEvents(taskId);
|
|
141
|
+
}
|
|
142
|
+
catch {
|
|
143
|
+
cleanup();
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
82
146
|
const filtered = applyFilteredIndex(history, filter);
|
|
83
147
|
for (const { event, filteredIndex } of filtered) {
|
|
84
148
|
await sendEvent(event, filteredIndex);
|
|
@@ -86,6 +150,7 @@ export function createSSERouter(engine) {
|
|
|
86
150
|
// If task is already terminal, send done and close
|
|
87
151
|
if (TERMINAL.has(task.status)) {
|
|
88
152
|
await sendDone(task.status);
|
|
153
|
+
cleanup();
|
|
89
154
|
return;
|
|
90
155
|
}
|
|
91
156
|
// Subscribe to live events
|
|
@@ -101,12 +166,14 @@ export function createSSERouter(engine) {
|
|
|
101
166
|
const status = event.data.status;
|
|
102
167
|
if (TERMINAL.has(status)) {
|
|
103
168
|
await sendDone(status);
|
|
169
|
+
cleanup();
|
|
104
170
|
unsub();
|
|
105
171
|
resolve();
|
|
106
172
|
}
|
|
107
173
|
}
|
|
108
174
|
});
|
|
109
175
|
stream.onAbort(() => {
|
|
176
|
+
cleanup();
|
|
110
177
|
unsub();
|
|
111
178
|
resolve();
|
|
112
179
|
});
|
package/dist/routes/sse.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sse.js","sourceRoot":"","sources":["../../src/routes/sse.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"sse.js","sourceRoot":"","sources":["../../src/routes/sse.ts"],"names":[],"mappings":"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"}
|
package/dist/routes/tasks.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { Hono } from 'hono';
|
|
1
|
+
import type { Hono } from 'hono';
|
|
2
|
+
import type { SubscriberCounts } from './sse.js';
|
|
2
3
|
import type { TaskEngine } from '@taskcast/core';
|
|
3
|
-
export declare function createTasksRouter(engine: TaskEngine): Hono
|
|
4
|
+
export declare function createTasksRouter(engine: TaskEngine, subscriberCounts: SubscriberCounts): Hono;
|
|
4
5
|
//# sourceMappingURL=tasks.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tasks.d.ts","sourceRoot":"","sources":["../../src/routes/tasks.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;
|
|
1
|
+
{"version":3,"file":"tasks.d.ts","sourceRoot":"","sources":["../../src/routes/tasks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAKhC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAA;AAUhD,OAAO,KAAK,EAAE,UAAU,EAAsG,MAAM,gBAAgB,CAAA;AA+HpJ,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,UAAU,EAAE,gBAAgB,EAAE,gBAAgB,GAAG,IAAI,CAsN9F"}
|