1import { assert, it } from "@effect/vitest";
2import * as NodeSqliteClient from "@t3tools/shared/nodeSqliteClient";
3import * as Effect from "effect/Effect";
4import * as Layer from "effect/Layer";
5import * as SqlClient from "effect/sql/SqlClient";
6
7import { runMigrations } from "../Migrations.ts";
8
9const layer = it.layer(Layer.mergeAll(NodeSqliteClient.layer({ filename: ":memory:" })));
10
11layer("057_ScheduledTaskWebhooks", (it) => {
12 it.effect("keeps existing scheduled tasks and adds webhook storage", () =>
13 Effect.gen(function* () {
14 const sql = yield* SqlClient.SqlClient;
15 yield* runMigrations({ toMigrationInclusive: 56 });
16 yield* sql`INSERT INTO scheduled_tasks ${sql.insert({
17 task_id: "existing",
18 title: "task",
19 prompt: "Run",
20 enabled: 1,
21 schedule_json: '{"type":"interval","everyMs":60000}',
22 project_id: "project",
23 thread_id: null,
24 workspace_strategy_json: '{"type":"root"}',
25 model_selection_json: '{"instanceId":"codex","model":"gpt-5"}',
26 runtime_mode: "full-access",
27 interaction_mode: "default",
28 created_by: "user",
29 creation_source: "web",
30 created_at: "2026-10-01T00:00:00.000Z",
31 updated_at: "2026-10-01T00:00:00.000Z",
32 next_run_at: null,
33 last_run_at: null,
34 last_run_status: "never",
35 last_run_error: null,
36 run_count: 0,
37 })}`;
38 yield* runMigrations({ toMigrationInclusive: 57 });
39
40 const rows = yield* sql<{
41 task_id: string;
42 webhook_token: string | null;
43 }>`SELECT task_id, webhook_token FROM scheduled_tasks`;
44 assert.deepEqual(rows, [{ task_id: "existing", webhook_token: null }]);
45 const deliveries = yield* sql<{
46 count: number;
47 }>`SELECT COUNT(*) AS count FROM scheduled_task_webhook_deliveries`;
48 assert.equal(deliveries[0]?.count, 0);
49 }),
50 );
51});