@devosurf/tesser-server 0.1.0-alpha.3 → 0.1.0-alpha.4
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/main.js +33 -7
- package/dist/main.js.map +2 -2
- package/package.json +4 -4
- package/src/http/api.ts +33 -7
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@devosurf/tesser-server",
|
|
3
|
-
"version": "0.1.0-alpha.
|
|
3
|
+
"version": "0.1.0-alpha.4",
|
|
4
4
|
"description": "Tesser runtime, scheduler, credential broker, git-sync and control-plane.",
|
|
5
5
|
"license": "AGPL-3.0-only",
|
|
6
6
|
"type": "module",
|
|
@@ -20,9 +20,9 @@
|
|
|
20
20
|
"esbuild": "^0.28.1",
|
|
21
21
|
"hono": "^4.12.25",
|
|
22
22
|
"pg": "^8.21.0",
|
|
23
|
-
"@devosurf/tesser-brand": "0.1.0-alpha.
|
|
24
|
-
"@devosurf/tesser-sdk": "0.1.0-alpha.
|
|
25
|
-
"@devosurf/tesser-testing": "^0.1.0-alpha.
|
|
23
|
+
"@devosurf/tesser-brand": "0.1.0-alpha.4",
|
|
24
|
+
"@devosurf/tesser-sdk": "0.1.0-alpha.4",
|
|
25
|
+
"@devosurf/tesser-testing": "^0.1.0-alpha.4"
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
28
|
"@types/pg": "^8.20.0"
|
package/src/http/api.ts
CHANGED
|
@@ -234,7 +234,10 @@ export function createApi(deps: ApiDeps): Hono<ApiEnv> {
|
|
|
234
234
|
});
|
|
235
235
|
|
|
236
236
|
api.get("/runs", async (c) => {
|
|
237
|
-
const
|
|
237
|
+
const requestedLimit = Number(c.req.query("limit") ?? 50);
|
|
238
|
+
const requestedOffset = Number(c.req.query("offset") ?? 0);
|
|
239
|
+
const limit = Number.isFinite(requestedLimit) ? Math.min(Math.max(Math.trunc(requestedLimit), 1), 200) : 50;
|
|
240
|
+
const offset = Number.isFinite(requestedOffset) ? Math.max(Math.trunc(requestedOffset), 0) : 0;
|
|
238
241
|
const params: unknown[] = [c.get("workspaceId")];
|
|
239
242
|
let filter = "";
|
|
240
243
|
if (c.req.query("project")) {
|
|
@@ -249,16 +252,23 @@ export function createApi(deps: ApiDeps): Hono<ApiEnv> {
|
|
|
249
252
|
params.push(c.req.query("status"));
|
|
250
253
|
filter += ` AND r.status = $${params.length}`;
|
|
251
254
|
}
|
|
252
|
-
params
|
|
255
|
+
const countParams = [...params];
|
|
256
|
+
const total = Number((await deps.db.query<{ count: string }>(
|
|
257
|
+
`SELECT count(*)::text AS count
|
|
258
|
+
FROM runs r JOIN projects p ON p.id = r.project_id
|
|
259
|
+
WHERE p.workspace_id = $1 ${filter}`,
|
|
260
|
+
countParams,
|
|
261
|
+
)).rows[0]?.count ?? "0");
|
|
262
|
+
params.push(limit, offset);
|
|
253
263
|
const { rows } = await deps.db.query(
|
|
254
264
|
`SELECT r.id, p.name AS project, r.automation_id, r.env, r.status, r.attempt,
|
|
255
265
|
r.trigger->>'kind' AS trigger_kind, r.created_at, r.started_at, r.finished_at
|
|
256
266
|
FROM runs r JOIN projects p ON p.id = r.project_id
|
|
257
267
|
WHERE p.workspace_id = $1 ${filter}
|
|
258
|
-
ORDER BY r.created_at DESC LIMIT $${params.length}`,
|
|
268
|
+
ORDER BY r.created_at DESC LIMIT $${params.length - 1} OFFSET $${params.length}`,
|
|
259
269
|
params,
|
|
260
270
|
);
|
|
261
|
-
return c.json({ runs: rows });
|
|
271
|
+
return c.json({ runs: rows, total, limit, offset, truncated: offset + rows.length < total });
|
|
262
272
|
});
|
|
263
273
|
|
|
264
274
|
api.get("/runs/:id", async (c) => {
|
|
@@ -273,11 +283,27 @@ export function createApi(deps: ApiDeps): Hono<ApiEnv> {
|
|
|
273
283
|
FROM run_steps WHERE run_id = $1 ORDER BY started_at, occurrence`,
|
|
274
284
|
[c.req.param("id")],
|
|
275
285
|
);
|
|
276
|
-
const
|
|
277
|
-
|
|
286
|
+
const requestedLogLimit = Number(c.req.query("logLimit") ?? 100);
|
|
287
|
+
const requestedLogOffset = Number(c.req.query("logOffset") ?? 0);
|
|
288
|
+
const logLimit = Number.isFinite(requestedLogLimit) ? Math.min(Math.max(Math.trunc(requestedLogLimit), 1), 500) : 100;
|
|
289
|
+
const logOffset = Number.isFinite(requestedLogOffset) ? Math.max(Math.trunc(requestedLogOffset), 0) : 0;
|
|
290
|
+
const logsTotal = Number((await deps.db.query<{ count: string }>(
|
|
291
|
+
`SELECT count(*)::text AS count FROM run_logs WHERE run_id = $1`,
|
|
278
292
|
[c.req.param("id")],
|
|
293
|
+
)).rows[0]?.count ?? "0");
|
|
294
|
+
const logs = await deps.db.query(
|
|
295
|
+
`SELECT step, level, msg, meta, created_at FROM run_logs WHERE run_id = $1 ORDER BY id LIMIT $2 OFFSET $3`,
|
|
296
|
+
[c.req.param("id"), logLimit, logOffset],
|
|
279
297
|
);
|
|
280
|
-
return c.json({
|
|
298
|
+
return c.json({
|
|
299
|
+
run: rows[0],
|
|
300
|
+
steps: steps.rows,
|
|
301
|
+
logs: logs.rows,
|
|
302
|
+
logsTotal,
|
|
303
|
+
logsLimit: logLimit,
|
|
304
|
+
logsOffset: logOffset,
|
|
305
|
+
logsTruncated: logOffset + logs.rows.length < logsTotal,
|
|
306
|
+
});
|
|
281
307
|
});
|
|
282
308
|
|
|
283
309
|
api.get("/runs/:id/replay", async (c) => {
|