optio-api 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +244 -0
- package/dist/_generated/optio-engine.d.ts +69 -0
- package/dist/_generated/optio-engine.d.ts.map +1 -0
- package/dist/_generated/optio-engine.js +31 -0
- package/dist/_generated/optio-engine.js.map +1 -0
- package/dist/adapters/express.d.ts +24 -0
- package/dist/adapters/express.d.ts.map +1 -0
- package/dist/adapters/express.js +186 -0
- package/dist/adapters/express.js.map +1 -0
- package/dist/adapters/fastify.d.ts +38 -0
- package/dist/adapters/fastify.d.ts.map +1 -0
- package/dist/adapters/fastify.js +473 -0
- package/dist/adapters/fastify.js.map +1 -0
- package/dist/adapters/nextjs-app.d.ts +29 -0
- package/dist/adapters/nextjs-app.d.ts.map +1 -0
- package/dist/adapters/nextjs-app.js +220 -0
- package/dist/adapters/nextjs-app.js.map +1 -0
- package/dist/adapters/nextjs-pages.d.ts +29 -0
- package/dist/adapters/nextjs-pages.d.ts.map +1 -0
- package/dist/adapters/nextjs-pages.js +189 -0
- package/dist/adapters/nextjs-pages.js.map +1 -0
- package/dist/auth.d.ts +10 -0
- package/dist/auth.d.ts.map +1 -0
- package/dist/auth.js +9 -0
- package/dist/auth.js.map +1 -0
- package/dist/context.d.ts +14 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +13 -0
- package/dist/context.js.map +1 -0
- package/dist/discovery.d.ts +10 -0
- package/dist/discovery.d.ts.map +1 -0
- package/dist/discovery.js +48 -0
- package/dist/discovery.js.map +1 -0
- package/dist/handlers.d.ts +110 -0
- package/dist/handlers.d.ts.map +1 -0
- package/dist/handlers.js +188 -0
- package/dist/handlers.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +22 -0
- package/dist/index.js.map +1 -0
- package/dist/metadata-filter-query.d.ts +13 -0
- package/dist/metadata-filter-query.d.ts.map +1 -0
- package/dist/metadata-filter-query.js +36 -0
- package/dist/metadata-filter-query.js.map +1 -0
- package/dist/optio-transports.d.ts +8 -0
- package/dist/optio-transports.d.ts.map +1 -0
- package/dist/optio-transports.js +37 -0
- package/dist/optio-transports.js.map +1 -0
- package/dist/process-id-resolver.d.ts +26 -0
- package/dist/process-id-resolver.d.ts.map +1 -0
- package/dist/process-id-resolver.js +31 -0
- package/dist/process-id-resolver.js.map +1 -0
- package/dist/resolve.d.ts +25 -0
- package/dist/resolve.d.ts.map +1 -0
- package/dist/resolve.js +16 -0
- package/dist/resolve.js.map +1 -0
- package/dist/sse-options.d.ts +28 -0
- package/dist/sse-options.d.ts.map +1 -0
- package/dist/sse-options.js +82 -0
- package/dist/sse-options.js.map +1 -0
- package/dist/stream-poller.d.ts +21 -0
- package/dist/stream-poller.d.ts.map +1 -0
- package/dist/stream-poller.js +146 -0
- package/dist/stream-poller.js.map +1 -0
- package/dist/types.d.ts +2 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/widget-proxy-core.d.ts +7 -0
- package/dist/widget-proxy-core.d.ts.map +1 -0
- package/dist/widget-proxy-core.js +56 -0
- package/dist/widget-proxy-core.js.map +1 -0
- package/dist/widget-upstream-registry.d.ts +27 -0
- package/dist/widget-upstream-registry.d.ts.map +1 -0
- package/dist/widget-upstream-registry.js +28 -0
- package/dist/widget-upstream-registry.js.map +1 -0
- package/package.json +100 -0
|
@@ -0,0 +1,473 @@
|
|
|
1
|
+
// @ts-nocheck — type inference for ts-rest router handlers requires the full
|
|
2
|
+
// monorepo type resolution. The adapter is tested via API integration tests.
|
|
3
|
+
import { initServer } from '@ts-rest/fastify';
|
|
4
|
+
import { initContract } from '@ts-rest/core';
|
|
5
|
+
import { processesContract } from 'optio-contracts';
|
|
6
|
+
import * as handlers from '../handlers.js';
|
|
7
|
+
import { findProcessByEitherId } from '../process-id-resolver.js';
|
|
8
|
+
import { createListPoller, createTreePoller } from '../stream-poller.js';
|
|
9
|
+
import { discoverInstances } from '../discovery.js';
|
|
10
|
+
import { resolveDb } from '../resolve.js';
|
|
11
|
+
import httpProxy from '@fastify/http-proxy';
|
|
12
|
+
import { createHash } from 'node:crypto';
|
|
13
|
+
import { checkAuth } from '../auth.js';
|
|
14
|
+
import { createWidgetUpstreamRegistry } from '../widget-upstream-registry.js';
|
|
15
|
+
import { resolveWidgetUpstream, applyInnerAuthHeaders, applyInnerAuthQuery, isWriteMethod, } from '../widget-proxy-core.js';
|
|
16
|
+
import { detectLegacyMetadataParams, formatLegacyMetadataMessage, } from '../metadata-filter-query.js';
|
|
17
|
+
import { parseSseOptions, checkLegacyMetadataParams, LegacyMetadataParamError, } from '../sse-options.js';
|
|
18
|
+
import { createOptioContext } from '../context.js';
|
|
19
|
+
const WIDGET_CACHE_TTL_MS = 5000;
|
|
20
|
+
// Widget URL scheme: /api/widget/<database>/<prefix>/<processId>/<subpath...>
|
|
21
|
+
// The database and prefix segments are required so the proxy can resolve the
|
|
22
|
+
// correct Mongo database/collection per request (iframe content emits
|
|
23
|
+
// relative URLs that would drop query params on navigation, so routing info
|
|
24
|
+
// must live in the path).
|
|
25
|
+
const WIDGET_URL_PATTERN = /^\/api\/widget\/([^/]+)\/([^/]+)\/([a-f0-9]{24})(?:\/|$|\?)/i;
|
|
26
|
+
const WIDGET_PREFIX_STRIP = /^\/api\/widget\/[^/]+\/[^/]+\/[a-f0-9]{24}/i;
|
|
27
|
+
function rewriteResponseHeaders(headers) {
|
|
28
|
+
// The proxy's purpose is to make the upstream embeddable in an iframe under
|
|
29
|
+
// optio-api's outer auth. Strip `X-Frame-Options` and any `frame-ancestors`
|
|
30
|
+
// CSP directive so upstreams (marimo, jupyter, internal tools) that default
|
|
31
|
+
// to anti-embedding headers don't block that. Clickjacking defense is
|
|
32
|
+
// provided by optio-api's authenticate callback: the proxy is unreachable
|
|
33
|
+
// without a valid session.
|
|
34
|
+
const out = { ...headers };
|
|
35
|
+
delete out['x-frame-options'];
|
|
36
|
+
const csp = out['content-security-policy'];
|
|
37
|
+
if (typeof csp === 'string') {
|
|
38
|
+
const stripped = csp
|
|
39
|
+
.split(';')
|
|
40
|
+
.map((d) => d.trim())
|
|
41
|
+
.filter((d) => d.length > 0 && !d.toLowerCase().startsWith('frame-ancestors'))
|
|
42
|
+
.join('; ');
|
|
43
|
+
if (stripped)
|
|
44
|
+
out['content-security-policy'] = stripped;
|
|
45
|
+
else
|
|
46
|
+
delete out['content-security-policy'];
|
|
47
|
+
}
|
|
48
|
+
return out;
|
|
49
|
+
}
|
|
50
|
+
function widgetProxyPrefix(database, prefix, processId) {
|
|
51
|
+
return `/api/widget/${encodeURIComponent(database)}/${encodeURIComponent(prefix)}/${processId}/`;
|
|
52
|
+
}
|
|
53
|
+
function injectBaseHref(html, proxyPrefix) {
|
|
54
|
+
// Inject two things right after <head>:
|
|
55
|
+
//
|
|
56
|
+
// 1. <base href="<proxyPrefix>"> — forces relative URLs in the page to
|
|
57
|
+
// resolve against the proxy root regardless of how deep the current
|
|
58
|
+
// document URL is. Required for SPAs (like opencode) whose HTML uses
|
|
59
|
+
// relative asset paths ("./assets/x.js") but are loaded via a routing-
|
|
60
|
+
// deep URL like /api/widget/<db>/<prefix>/<pid>/<workdir>/session/.
|
|
61
|
+
// Without it, assets resolve to `.../workdir/session/assets/x.js` and
|
|
62
|
+
// hit the upstream's SPA fallback with wrong MIME types.
|
|
63
|
+
//
|
|
64
|
+
// 2. An inline <script> that runs before the SPA bundle and strips the
|
|
65
|
+
// proxy prefix from `location.pathname` via history.replaceState.
|
|
66
|
+
// This makes the SPA's client-side router (e.g. @solidjs/router, react
|
|
67
|
+
// -router) see the application's intended URL space (`/:dir/session/`
|
|
68
|
+
// in opencode's case) rather than the proxy-nested one
|
|
69
|
+
// (`/api/widget/<db>/<prefix>/<pid>/:dir/session/`). `<base href>` is
|
|
70
|
+
// unaffected, so asset loading continues to work.
|
|
71
|
+
//
|
|
72
|
+
// Because the inline script violates `script-src 'self'` CSPs, we also
|
|
73
|
+
// return its SHA-256 so the caller can append `'sha256-…'` to the
|
|
74
|
+
// outgoing CSP's script-src directive.
|
|
75
|
+
const baseTag = `<base href="${proxyPrefix}">`;
|
|
76
|
+
// Escape regex-meta characters in the prefix for the runtime match.
|
|
77
|
+
const prefixLiteralForRegex = proxyPrefix
|
|
78
|
+
.replace(/\/$/, '') // the script uses the stripped form without trailing slash
|
|
79
|
+
.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
80
|
+
const scriptBody = `(function(){var r=new RegExp('^' + ${JSON.stringify(prefixLiteralForRegex)});` +
|
|
81
|
+
`var p=location.pathname;var m=p.match(r);` +
|
|
82
|
+
`if(m){history.replaceState(null,'',(p.slice(m[0].length)||'/')+location.search+location.hash);}` +
|
|
83
|
+
`})();`;
|
|
84
|
+
const stripScriptSha256 = createHash('sha256').update(scriptBody, 'utf-8').digest('base64');
|
|
85
|
+
const stripScript = `<script>${scriptBody}</script>`;
|
|
86
|
+
const injection = `${baseTag}${stripScript}`;
|
|
87
|
+
const m = html.match(/<head(\s[^>]*)?>/i);
|
|
88
|
+
const transformed = m
|
|
89
|
+
? html.replace(m[0], `${m[0]}${injection}`)
|
|
90
|
+
: `${injection}${html}`;
|
|
91
|
+
return { html: transformed, stripScriptSha256 };
|
|
92
|
+
}
|
|
93
|
+
// Extend the upstream CSP's script-src (or add one) with the SHA-256 of our
|
|
94
|
+
// injected inline script. Called only when HTML body rewriting has happened.
|
|
95
|
+
function appendScriptHashToCsp(csp, scriptHashBase64) {
|
|
96
|
+
const hashToken = `'sha256-${scriptHashBase64}'`;
|
|
97
|
+
const parts = csp
|
|
98
|
+
.split(';')
|
|
99
|
+
.map((d) => d.trim())
|
|
100
|
+
.filter((d) => d.length > 0);
|
|
101
|
+
let found = false;
|
|
102
|
+
const updated = parts.map((directive) => {
|
|
103
|
+
const lower = directive.toLowerCase();
|
|
104
|
+
if (lower.startsWith('script-src ') || lower === 'script-src') {
|
|
105
|
+
found = true;
|
|
106
|
+
return `${directive} ${hashToken}`;
|
|
107
|
+
}
|
|
108
|
+
return directive;
|
|
109
|
+
});
|
|
110
|
+
if (!found)
|
|
111
|
+
updated.push(`script-src ${hashToken}`);
|
|
112
|
+
return updated.join('; ');
|
|
113
|
+
}
|
|
114
|
+
function registerWidgetProxy(app, opts) {
|
|
115
|
+
const registry = createWidgetUpstreamRegistry({ ttlMs: opts.ttlMs ?? WIDGET_CACHE_TTL_MS });
|
|
116
|
+
function extractRouting(url) {
|
|
117
|
+
const m = url.match(WIDGET_URL_PATTERN);
|
|
118
|
+
if (!m)
|
|
119
|
+
return null;
|
|
120
|
+
try {
|
|
121
|
+
return {
|
|
122
|
+
database: decodeURIComponent(m[1]),
|
|
123
|
+
prefix: decodeURIComponent(m[2]),
|
|
124
|
+
processId: m[3],
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
catch {
|
|
128
|
+
return null;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
app.register(httpProxy, {
|
|
132
|
+
// Leave `upstream` unset (empty string) so that:
|
|
133
|
+
// - HTTP path: @fastify/reply-from uses replyOptions.getUpstream per-request (unaffected by base)
|
|
134
|
+
// - WS path: WebSocketProxy.findUpstream falls through to replyOptions.getUpstream (non-empty
|
|
135
|
+
// static upstream would override getUpstream and route all WS to a bogus host)
|
|
136
|
+
upstream: '',
|
|
137
|
+
prefix: '/api/widget',
|
|
138
|
+
rewritePrefix: '',
|
|
139
|
+
websocket: true,
|
|
140
|
+
// Use the Node.js http transport (not undici) so that getUpstream can override
|
|
141
|
+
// the connection target per-request via opts.url.hostname/port (undici uses
|
|
142
|
+
// the plugin-level baseUrl and ignores the per-request origin).
|
|
143
|
+
http: {},
|
|
144
|
+
// Passed through to @fastify/reply-from — suppresses its per-request
|
|
145
|
+
// "fetching from remote server" / "response received" INFO lines when the
|
|
146
|
+
// host app isn't running in verbose mode. Errors remain visible.
|
|
147
|
+
disableRequestLogging: !opts.verbose,
|
|
148
|
+
preHandler: async (req, reply) => {
|
|
149
|
+
const fullUrl = req.raw.url ?? req.url;
|
|
150
|
+
const routing = extractRouting(fullUrl);
|
|
151
|
+
if (!routing) {
|
|
152
|
+
reply.code(404).send({ message: 'Invalid widget URL' });
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
const { database, prefix, processId } = routing;
|
|
156
|
+
const authResult = await checkAuth(req, opts.authenticate, isWriteMethod(req.method));
|
|
157
|
+
if (authResult) {
|
|
158
|
+
reply.code(authResult.status).send(authResult.body);
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
let db;
|
|
162
|
+
try {
|
|
163
|
+
({ db } = resolveDb(opts.dbOpts, { database, prefix }));
|
|
164
|
+
}
|
|
165
|
+
catch {
|
|
166
|
+
reply.code(404).send({ message: 'Widget upstream not found' });
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
let upstream;
|
|
170
|
+
try {
|
|
171
|
+
upstream = await resolveWidgetUpstream(db, prefix, registry, processId);
|
|
172
|
+
}
|
|
173
|
+
catch (err) {
|
|
174
|
+
req.log.error({ err }, 'widget-proxy: upstream lookup failed');
|
|
175
|
+
reply.code(503).send({ message: 'Service Unavailable' });
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
if (!upstream) {
|
|
179
|
+
reply.code(404).send({ message: 'Widget upstream not found' });
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
// Store upstream on raw request for getUpstream + rewriteRequestHeaders to pick up
|
|
183
|
+
req.raw.__optioWidget = {
|
|
184
|
+
processId,
|
|
185
|
+
upstream,
|
|
186
|
+
proxyPrefix: widgetProxyPrefix(database, prefix, processId),
|
|
187
|
+
};
|
|
188
|
+
// Strip /api/widget/<database>/<prefix>/<processId> from the URL, leaving the sub-path.
|
|
189
|
+
// Then apply query-based inner auth if needed.
|
|
190
|
+
const stripped = fullUrl.replace(WIDGET_PREFIX_STRIP, '') || '/';
|
|
191
|
+
req.raw.url = applyInnerAuthQuery(upstream.innerAuth, stripped);
|
|
192
|
+
// Strip Accept-Encoding so the upstream returns uncompressed bodies.
|
|
193
|
+
// We need to rewrite text/html bodies in onResponse to inject <base href>,
|
|
194
|
+
// and handling gzip/br variants per upstream is more friction than the
|
|
195
|
+
// bandwidth savings are worth for a dev-tool reverse proxy.
|
|
196
|
+
delete req.raw.headers['accept-encoding'];
|
|
197
|
+
},
|
|
198
|
+
// Rewrite headers for outgoing WebSocket handshake (inner-auth injection).
|
|
199
|
+
// The Fastify request object is passed as the second argument, which has
|
|
200
|
+
// request.raw.__optioWidget set by preHandler (runs before the upgrade handshake).
|
|
201
|
+
wsClientOptions: {
|
|
202
|
+
rewriteRequestHeaders: (headers, req) => {
|
|
203
|
+
const widget = req.raw.__optioWidget;
|
|
204
|
+
if (!widget)
|
|
205
|
+
return headers;
|
|
206
|
+
return applyInnerAuthHeaders(widget.upstream.innerAuth, headers);
|
|
207
|
+
},
|
|
208
|
+
},
|
|
209
|
+
replyOptions: {
|
|
210
|
+
getUpstream: (req) => {
|
|
211
|
+
const widget = req.raw.__optioWidget;
|
|
212
|
+
return widget?.upstream.url ?? 'http://127.0.0.1/';
|
|
213
|
+
},
|
|
214
|
+
rewriteRequestHeaders: (req, headers) => {
|
|
215
|
+
const widget = req.raw.__optioWidget;
|
|
216
|
+
if (!widget)
|
|
217
|
+
return headers;
|
|
218
|
+
return applyInnerAuthHeaders(widget.upstream.innerAuth, headers);
|
|
219
|
+
},
|
|
220
|
+
rewriteHeaders: rewriteResponseHeaders,
|
|
221
|
+
// onResponse takes over the response forwarding so we can rewrite
|
|
222
|
+
// text/html bodies (inject <base href> — see injectBaseHref).
|
|
223
|
+
// Non-HTML responses stream through unchanged.
|
|
224
|
+
//
|
|
225
|
+
// We use reply.hijack() + reply.raw directly because fastify 5's
|
|
226
|
+
// reply.send() does not accept Node IncomingMessage streams, and the
|
|
227
|
+
// header/body coordination for a transformed HTML body is simpler on
|
|
228
|
+
// the raw ServerResponse anyway. reply-from does NOT auto-apply
|
|
229
|
+
// rewriteHeaders when onResponse is defined, so apply them here
|
|
230
|
+
// explicitly to the outgoing response.
|
|
231
|
+
onResponse: (request, reply, res) => {
|
|
232
|
+
// @fastify/reply-from passes a wrapper: res.stream is the Readable
|
|
233
|
+
// upstream body; res.headers / res.statusCode are the top-level fields.
|
|
234
|
+
const stream = res.stream;
|
|
235
|
+
reply.hijack();
|
|
236
|
+
const rawRes = reply.raw;
|
|
237
|
+
const statusCode = res.statusCode ?? 200;
|
|
238
|
+
const incomingHeaders = res.headers;
|
|
239
|
+
const contentType = String(incomingHeaders['content-type'] ?? '').toLowerCase();
|
|
240
|
+
if (!contentType.includes('text/html')) {
|
|
241
|
+
const outHeaders = rewriteResponseHeaders(incomingHeaders);
|
|
242
|
+
rawRes.writeHead(statusCode, outHeaders);
|
|
243
|
+
stream.pipe(rawRes);
|
|
244
|
+
stream.on('error', (err) => {
|
|
245
|
+
request.log.error({ err }, 'widget-proxy: upstream body read error');
|
|
246
|
+
if (!rawRes.headersSent)
|
|
247
|
+
rawRes.writeHead(502);
|
|
248
|
+
rawRes.end();
|
|
249
|
+
});
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
const widget = request.raw.__optioWidget;
|
|
253
|
+
const proxyPrefix = widget?.proxyPrefix ?? '/';
|
|
254
|
+
const chunks = [];
|
|
255
|
+
stream.on('data', (c) => {
|
|
256
|
+
chunks.push(c);
|
|
257
|
+
});
|
|
258
|
+
stream.on('end', () => {
|
|
259
|
+
const html = Buffer.concat(chunks).toString('utf-8');
|
|
260
|
+
const { html: transformed, stripScriptSha256 } = injectBaseHref(html, proxyPrefix);
|
|
261
|
+
const body = Buffer.from(transformed, 'utf-8');
|
|
262
|
+
// Rebuild headers: copy upstream, then override transform-affected ones.
|
|
263
|
+
const outHeaders = rewriteResponseHeaders(incomingHeaders);
|
|
264
|
+
outHeaders['content-length'] = String(body.byteLength);
|
|
265
|
+
// Drop content-encoding — we already decoded if upstream gzipped.
|
|
266
|
+
// (We also strip Accept-Encoding on the way out in preHandler so in
|
|
267
|
+
// practice upstream should send identity, but belt-and-braces.)
|
|
268
|
+
delete outHeaders['content-encoding'];
|
|
269
|
+
// If a CSP is present, allowlist our injected inline script by hash
|
|
270
|
+
// so it isn't blocked by `script-src 'self'`.
|
|
271
|
+
const csp = outHeaders['content-security-policy'];
|
|
272
|
+
if (typeof csp === 'string' && csp.length > 0) {
|
|
273
|
+
outHeaders['content-security-policy'] = appendScriptHashToCsp(csp, stripScriptSha256);
|
|
274
|
+
}
|
|
275
|
+
rawRes.writeHead(statusCode, outHeaders);
|
|
276
|
+
rawRes.end(body);
|
|
277
|
+
});
|
|
278
|
+
stream.on('error', (err) => {
|
|
279
|
+
request.log.error({ err }, 'widget-proxy: upstream body read error');
|
|
280
|
+
if (!rawRes.headersSent)
|
|
281
|
+
rawRes.writeHead(502);
|
|
282
|
+
rawRes.end();
|
|
283
|
+
});
|
|
284
|
+
},
|
|
285
|
+
// Map connection errors (ECONNREFUSED → InternalServerError/500 by default) to
|
|
286
|
+
// 502 Bad Gateway so callers get a meaningful gateway error.
|
|
287
|
+
// Full error detail is logged server-side; clients only see a fixed, non-leaking body.
|
|
288
|
+
onError: (reply, error) => {
|
|
289
|
+
reply.request.log.error({ err: error }, 'widget-proxy: upstream error');
|
|
290
|
+
const code = error?.statusCode === 500 ? 502 : (error?.statusCode ?? 502);
|
|
291
|
+
reply.code(code).send({ message: code === 502 ? 'Bad Gateway' : 'Upstream Error' });
|
|
292
|
+
},
|
|
293
|
+
},
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
const c = initContract();
|
|
297
|
+
const apiContract = c.router({ processes: processesContract }, { pathPrefix: '/api' });
|
|
298
|
+
export function registerOptioApi(app, opts) {
|
|
299
|
+
const explicit = 'ctx' in opts;
|
|
300
|
+
let ctx;
|
|
301
|
+
let redis;
|
|
302
|
+
let dbOpts;
|
|
303
|
+
if (explicit) {
|
|
304
|
+
ctx = opts.ctx;
|
|
305
|
+
dbOpts = ctx.dbOpts;
|
|
306
|
+
redis = ctx.redis;
|
|
307
|
+
}
|
|
308
|
+
else {
|
|
309
|
+
redis = opts.redis;
|
|
310
|
+
dbOpts = 'mongoClient' in opts && opts.mongoClient ? { mongoClient: opts.mongoClient } : { db: opts.db };
|
|
311
|
+
ctx = createOptioContext({ dbOpts, redis });
|
|
312
|
+
app.addHook('onClose', () => ctx.closeAll());
|
|
313
|
+
}
|
|
314
|
+
// Global auth enforcement. Runs before route handlers (and before the
|
|
315
|
+
// widget-proxy plugin's preHandler), so REST, SSE, discovery, and widget
|
|
316
|
+
// routes all pass through checkAuth here. The widget-proxy preHandler's
|
|
317
|
+
// own checkAuth call is left in place as defense in depth.
|
|
318
|
+
app.addHook('onRequest', async (req, reply) => {
|
|
319
|
+
const authResult = await checkAuth(req, opts.authenticate, isWriteMethod(req.method));
|
|
320
|
+
if (authResult) {
|
|
321
|
+
reply.code(authResult.status).send(authResult.body);
|
|
322
|
+
}
|
|
323
|
+
});
|
|
324
|
+
// Widget reverse-proxy lives under /api/widget/<database>/<prefix>/<processId>/…
|
|
325
|
+
// and is registered as an internal part of the Optio API surface so consumers
|
|
326
|
+
// only need one init call.
|
|
327
|
+
registerWidgetProxy(app, {
|
|
328
|
+
dbOpts,
|
|
329
|
+
authenticate: opts.authenticate,
|
|
330
|
+
verbose: opts.verbose,
|
|
331
|
+
});
|
|
332
|
+
const s = initServer();
|
|
333
|
+
const routes = s.router(apiContract.processes, {
|
|
334
|
+
list: async ({ query }) => {
|
|
335
|
+
const result = await handlers.listProcesses(ctx, query);
|
|
336
|
+
return { status: 200, body: result };
|
|
337
|
+
},
|
|
338
|
+
get: async ({ params, query }) => {
|
|
339
|
+
const result = await handlers.getProcess(ctx, query, params.id);
|
|
340
|
+
if (!result)
|
|
341
|
+
return { status: 404, body: { message: 'Process not found' } };
|
|
342
|
+
return { status: 200, body: result };
|
|
343
|
+
},
|
|
344
|
+
getTree: async ({ params, query }) => {
|
|
345
|
+
const result = await handlers.getProcessTree(ctx, query, params.id);
|
|
346
|
+
if (!result)
|
|
347
|
+
return { status: 404, body: { message: 'Process not found' } };
|
|
348
|
+
return { status: 200, body: result };
|
|
349
|
+
},
|
|
350
|
+
getLog: async ({ params, query }) => {
|
|
351
|
+
const result = await handlers.getProcessLog(ctx, query, params.id);
|
|
352
|
+
if (!result)
|
|
353
|
+
return { status: 404, body: { message: 'Process not found' } };
|
|
354
|
+
return { status: 200, body: result };
|
|
355
|
+
},
|
|
356
|
+
getTreeLog: async ({ params, query }) => {
|
|
357
|
+
const result = await handlers.getProcessTreeLog(ctx, query, params.id);
|
|
358
|
+
if (!result)
|
|
359
|
+
return { status: 404, body: { message: 'Process not found' } };
|
|
360
|
+
return { status: 200, body: result };
|
|
361
|
+
},
|
|
362
|
+
launch: async ({ params, query, body }) => {
|
|
363
|
+
const result = await handlers.launchProcess(ctx, query, params.id, body?.resume === true);
|
|
364
|
+
return result;
|
|
365
|
+
},
|
|
366
|
+
cancel: async ({ params, query }) => {
|
|
367
|
+
const result = await handlers.cancelProcess(ctx, query, params.id);
|
|
368
|
+
return result;
|
|
369
|
+
},
|
|
370
|
+
dismiss: async ({ params, query }) => {
|
|
371
|
+
const result = await handlers.dismissProcess(ctx, query, params.id);
|
|
372
|
+
return result;
|
|
373
|
+
},
|
|
374
|
+
resync: async ({ query, body }) => {
|
|
375
|
+
const result = await handlers.resyncProcesses(ctx, query, body.clean, body.metadataFilter);
|
|
376
|
+
return { status: 202, body: result };
|
|
377
|
+
},
|
|
378
|
+
});
|
|
379
|
+
// Pre-check for legacy metadata.* query params on GET /api/processes (list endpoint).
|
|
380
|
+
// Must run after onRequest (auth) but before ts-rest route handlers.
|
|
381
|
+
app.addHook('preHandler', async (request, reply) => {
|
|
382
|
+
if (request.method === 'GET' && request.url.split('?')[0] === '/api/processes') {
|
|
383
|
+
const legacyKeys = detectLegacyMetadataParams(request.query ?? {});
|
|
384
|
+
if (legacyKeys.length > 0) {
|
|
385
|
+
reply.code(400).send({ message: formatLegacyMetadataMessage(legacyKeys) });
|
|
386
|
+
return;
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
});
|
|
390
|
+
app.register(s.plugin(routes));
|
|
391
|
+
app.get('/api/optio/instances', async (_request, reply) => {
|
|
392
|
+
const instances = await discoverInstances(dbOpts, redis);
|
|
393
|
+
reply.send({ instances });
|
|
394
|
+
});
|
|
395
|
+
app.get('/api/processes/:id/tree/stream', async (request, reply) => {
|
|
396
|
+
const { id } = request.params;
|
|
397
|
+
let sseOpts;
|
|
398
|
+
try {
|
|
399
|
+
sseOpts = parseSseOptions(request.query ?? {});
|
|
400
|
+
}
|
|
401
|
+
catch (e) {
|
|
402
|
+
reply.code(400).send({ message: e.message });
|
|
403
|
+
return;
|
|
404
|
+
}
|
|
405
|
+
const { db, prefix } = resolveDb(dbOpts, sseOpts);
|
|
406
|
+
const col = db.collection(`${prefix}_processes`);
|
|
407
|
+
const proc = await findProcessByEitherId(col, id);
|
|
408
|
+
if (!proc) {
|
|
409
|
+
reply.code(404).send({ message: 'Process not found' });
|
|
410
|
+
return;
|
|
411
|
+
}
|
|
412
|
+
reply.raw.writeHead(200, {
|
|
413
|
+
'Content-Type': 'text/event-stream',
|
|
414
|
+
'Cache-Control': 'no-cache',
|
|
415
|
+
'Connection': 'keep-alive',
|
|
416
|
+
});
|
|
417
|
+
const sendEvent = (data) => {
|
|
418
|
+
reply.raw.write(`data: ${JSON.stringify(data)}\n\n`);
|
|
419
|
+
};
|
|
420
|
+
const poller = createTreePoller({
|
|
421
|
+
db,
|
|
422
|
+
prefix,
|
|
423
|
+
sendEvent,
|
|
424
|
+
onError: () => reply.raw.end(),
|
|
425
|
+
rootId: proc.rootId.toString(),
|
|
426
|
+
baseDepth: proc.depth,
|
|
427
|
+
maxDepth: sseOpts.maxDepth,
|
|
428
|
+
});
|
|
429
|
+
poller.start();
|
|
430
|
+
request.raw.on('close', () => poller.stop());
|
|
431
|
+
});
|
|
432
|
+
app.get('/api/processes/stream', async (request, reply) => {
|
|
433
|
+
const rawQuery = request.query ?? {};
|
|
434
|
+
try {
|
|
435
|
+
checkLegacyMetadataParams(rawQuery);
|
|
436
|
+
}
|
|
437
|
+
catch (e) {
|
|
438
|
+
if (e instanceof LegacyMetadataParamError) {
|
|
439
|
+
reply.code(400).send({ message: e.message });
|
|
440
|
+
return;
|
|
441
|
+
}
|
|
442
|
+
throw e;
|
|
443
|
+
}
|
|
444
|
+
let sseOpts;
|
|
445
|
+
try {
|
|
446
|
+
sseOpts = parseSseOptions(rawQuery);
|
|
447
|
+
}
|
|
448
|
+
catch (e) {
|
|
449
|
+
reply.code(400).send({ message: e.message });
|
|
450
|
+
return;
|
|
451
|
+
}
|
|
452
|
+
const { db, prefix } = resolveDb(dbOpts, sseOpts);
|
|
453
|
+
reply.raw.writeHead(200, {
|
|
454
|
+
'Content-Type': 'text/event-stream',
|
|
455
|
+
'Cache-Control': 'no-cache',
|
|
456
|
+
'Connection': 'keep-alive',
|
|
457
|
+
});
|
|
458
|
+
const sendEvent = (data) => {
|
|
459
|
+
reply.raw.write(`data: ${JSON.stringify(data)}\n\n`);
|
|
460
|
+
};
|
|
461
|
+
const poller = createListPoller({
|
|
462
|
+
db,
|
|
463
|
+
prefix,
|
|
464
|
+
sendEvent,
|
|
465
|
+
onError: () => reply.raw.end(),
|
|
466
|
+
metadataFilter: sseOpts.metadataFilter,
|
|
467
|
+
});
|
|
468
|
+
poller.start();
|
|
469
|
+
request.raw.on('close', () => poller.stop());
|
|
470
|
+
});
|
|
471
|
+
return explicit ? undefined : ctx;
|
|
472
|
+
}
|
|
473
|
+
//# sourceMappingURL=fastify.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fastify.js","sourceRoot":"","sources":["../../src/adapters/fastify.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { Db } from 'mongodb';
|
|
2
|
+
import type { MongoClient } from 'mongodb';
|
|
3
|
+
import type { Redis } from 'ioredis';
|
|
4
|
+
import type { AuthCallback } from '../auth.js';
|
|
5
|
+
import { type OptioContext } from '../context.js';
|
|
6
|
+
export interface OptioRouteHandlers {
|
|
7
|
+
GET: (request: Request) => Promise<Response>;
|
|
8
|
+
POST: (request: Request) => Promise<Response>;
|
|
9
|
+
/** Present only when called with sugar-form options (caller did not supply ctx). */
|
|
10
|
+
ctx?: OptioContext;
|
|
11
|
+
}
|
|
12
|
+
export type OptioApiOptions = (BaseOptioApiOptions & {
|
|
13
|
+
ctx: OptioContext;
|
|
14
|
+
}) | (BaseOptioApiOptions & {
|
|
15
|
+
redis: Redis;
|
|
16
|
+
} & ({
|
|
17
|
+
db: Db;
|
|
18
|
+
mongoClient?: never;
|
|
19
|
+
} | {
|
|
20
|
+
mongoClient: MongoClient;
|
|
21
|
+
db?: never;
|
|
22
|
+
}));
|
|
23
|
+
interface BaseOptioApiOptions {
|
|
24
|
+
prefix?: string;
|
|
25
|
+
authenticate: AuthCallback<Request>;
|
|
26
|
+
}
|
|
27
|
+
export declare function createOptioRouteHandlers(opts: OptioApiOptions): OptioRouteHandlers;
|
|
28
|
+
export {};
|
|
29
|
+
//# sourceMappingURL=nextjs-app.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nextjs-app.d.ts","sourceRoot":"","sources":["../../src/adapters/nextjs-app.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAC3C,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAMrC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAY/C,OAAO,EAAsB,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;AAEtE,MAAM,WAAW,kBAAkB;IACjC,GAAG,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC7C,IAAI,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC9C,oFAAoF;IACpF,GAAG,CAAC,EAAE,YAAY,CAAC;CACpB;AAED,MAAM,MAAM,eAAe,GACvB,CAAC,mBAAmB,GAAG;IAAE,GAAG,EAAE,YAAY,CAAA;CAAE,CAAC,GAC7C,CAAC,mBAAmB,GAAG;IAAE,KAAK,EAAE,KAAK,CAAA;CAAE,GAAG,CACtC;IAAE,EAAE,EAAE,EAAE,CAAC;IAAC,WAAW,CAAC,EAAE,KAAK,CAAA;CAAE,GAC/B;IAAE,WAAW,EAAE,WAAW,CAAC;IAAC,EAAE,CAAC,EAAE,KAAK,CAAA;CAAE,CAC3C,CAAC,CAAC;AAEP,UAAU,mBAAmB;IAC3B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,YAAY,CAAC,OAAO,CAAC,CAAC;CACrC;AAKD,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,eAAe,GAAG,kBAAkB,CAgOlF"}
|