crnd 0.0.1 → 0.0.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.
Files changed (122) hide show
  1. package/bin/crnd +88 -0
  2. package/package.json +19 -43
  3. package/drizzle/0000_init.sql +0 -35
  4. package/drizzle/0001_add_runs.sql +0 -13
  5. package/drizzle/meta/_journal.json +0 -20
  6. package/src/cli/commands/createDeleteCommand.ts +0 -93
  7. package/src/cli/commands/createDoctorCommand.ts +0 -93
  8. package/src/cli/commands/createExportCommand.ts +0 -75
  9. package/src/cli/commands/createImportCommand.ts +0 -80
  10. package/src/cli/commands/createKillCommand.ts +0 -89
  11. package/src/cli/commands/createListCommand.ts +0 -67
  12. package/src/cli/commands/createLogsCommand.ts +0 -125
  13. package/src/cli/commands/createPauseCommand.ts +0 -78
  14. package/src/cli/commands/createResetCommand.ts +0 -78
  15. package/src/cli/commands/createResumeCommand.ts +0 -78
  16. package/src/cli/commands/createRootCommand.ts +0 -50
  17. package/src/cli/commands/createRunOnceCommand.ts +0 -77
  18. package/src/cli/commands/createRunsCommand.ts +0 -106
  19. package/src/cli/commands/createScheduleCommand.ts +0 -184
  20. package/src/cli/commands/createShowCommand.ts +0 -92
  21. package/src/cli/commands/createStatusCommand.ts +0 -145
  22. package/src/cli/commands/createStopCommand.ts +0 -89
  23. package/src/cli/commands/createUpdateCommand.ts +0 -13
  24. package/src/cli/commands/daemon/createDaemonCommand.ts +0 -24
  25. package/src/cli/commands/daemon/createDaemonInstallCommand.ts +0 -144
  26. package/src/cli/commands/daemon/createDaemonServeCommand.ts +0 -14
  27. package/src/cli/commands/daemon/createDaemonStartCommand.ts +0 -73
  28. package/src/cli/commands/daemon/createDaemonStatusCommand.ts +0 -5
  29. package/src/cli/commands/daemon/createDaemonStopCommand.ts +0 -59
  30. package/src/cli/commands/daemon/createDaemonUninstallCommand.ts +0 -99
  31. package/src/cli/commands/daemon/createLaunchdPlist.ts +0 -34
  32. package/src/cli/commands/daemon/createSystemdService.ts +0 -24
  33. package/src/cli/commands/daemon/escapeXml.ts +0 -8
  34. package/src/cli/commands/daemon/getDaemonServiceArgs.ts +0 -10
  35. package/src/cli/commands/daemon/quoteWindowsArg.ts +0 -4
  36. package/src/cli/commands/getCommandArgs.ts +0 -8
  37. package/src/cli/commands/parseEnvArgs.ts +0 -28
  38. package/src/cli/getDaemonSpawnArgs.ts +0 -9
  39. package/src/cli/main.ts +0 -8
  40. package/src/daemon/autostart/ensureAutostart.ts +0 -30
  41. package/src/daemon/autostart/getAutostartPath.ts +0 -29
  42. package/src/daemon/autostart/getDaemonInstallArgs.ts +0 -10
  43. package/src/daemon/createLogger.ts +0 -13
  44. package/src/daemon/createShutdownHandler.ts +0 -29
  45. package/src/daemon/jobs/createJobsFileSync.ts +0 -113
  46. package/src/daemon/jobs/deleteJobByName.ts +0 -18
  47. package/src/daemon/jobs/upsertJob.ts +0 -85
  48. package/src/daemon/main.ts +0 -64
  49. package/src/daemon/runner/createRunOutputFds.ts +0 -18
  50. package/src/daemon/runner/getRunStatus.ts +0 -14
  51. package/src/daemon/runner/recordSkippedRun.ts +0 -27
  52. package/src/daemon/runner/recoverRunningRuns.ts +0 -36
  53. package/src/daemon/runner/runJob.ts +0 -94
  54. package/src/daemon/scheduler/createScheduler.ts +0 -45
  55. package/src/daemon/scheduler/createSchedulerState.ts +0 -8
  56. package/src/daemon/scheduler/loadJobs.ts +0 -10
  57. package/src/daemon/scheduler/runJobWithTracking.ts +0 -48
  58. package/src/daemon/scheduler/scheduleJob.ts +0 -32
  59. package/src/daemon/scheduler/unscheduleJob.ts +0 -11
  60. package/src/daemon/scheduler/updateNextRunAt.ts +0 -14
  61. package/src/daemon/server/createApp.ts +0 -76
  62. package/src/daemon/server/createAuthMiddleware.ts +0 -16
  63. package/src/daemon/server/routes/registerExportRoute.ts +0 -21
  64. package/src/daemon/server/routes/registerHealthRoute.ts +0 -16
  65. package/src/daemon/server/routes/registerImportRoute.ts +0 -22
  66. package/src/daemon/server/routes/registerJobRunsRoute.ts +0 -46
  67. package/src/daemon/server/routes/registerJobsDeleteRoute.ts +0 -37
  68. package/src/daemon/server/routes/registerJobsGetRoute.ts +0 -29
  69. package/src/daemon/server/routes/registerJobsKillRoute.ts +0 -45
  70. package/src/daemon/server/routes/registerJobsListRoute.ts +0 -13
  71. package/src/daemon/server/routes/registerJobsPauseRoute.ts +0 -53
  72. package/src/daemon/server/routes/registerJobsResetRoute.ts +0 -54
  73. package/src/daemon/server/routes/registerJobsResumeRoute.ts +0 -53
  74. package/src/daemon/server/routes/registerJobsRunRoute.ts +0 -37
  75. package/src/daemon/server/routes/registerJobsStopRoute.ts +0 -45
  76. package/src/daemon/server/routes/registerJobsUpsertRoute.ts +0 -30
  77. package/src/daemon/server/routes/registerRunGetRoute.ts +0 -25
  78. package/src/daemon/server/routes/registerRunLogsRoute.ts +0 -32
  79. package/src/daemon/server/routes/registerShutdownRoute.ts +0 -9
  80. package/src/daemon/server/startServer.ts +0 -23
  81. package/src/db/getMigrationsDir.ts +0 -5
  82. package/src/db/migrateDatabase.ts +0 -21
  83. package/src/db/openDatabase.ts +0 -12
  84. package/src/db/schema/jobs.ts +0 -26
  85. package/src/db/schema/jobsSchemas.ts +0 -10
  86. package/src/db/schema/runs.ts +0 -23
  87. package/src/db/schema/runsSchemas.ts +0 -10
  88. package/src/db/schema.ts +0 -5
  89. package/src/shared/auth/createToken.ts +0 -5
  90. package/src/shared/events/appendEvent.ts +0 -16
  91. package/src/shared/jobs/createCommandSchema.ts +0 -5
  92. package/src/shared/jobs/createEnvSchema.ts +0 -5
  93. package/src/shared/jobs/createJobInputSchema.ts +0 -31
  94. package/src/shared/jobs/createTomlJobSchema.ts +0 -31
  95. package/src/shared/jobs/formatJobRow.ts +0 -14
  96. package/src/shared/jobs/isOverlapPolicy.ts +0 -5
  97. package/src/shared/jobs/parseCommand.ts +0 -6
  98. package/src/shared/jobs/parseEnv.ts +0 -10
  99. package/src/shared/jobs/parseJobsToml.ts +0 -36
  100. package/src/shared/jobs/readJobsToml.ts +0 -17
  101. package/src/shared/jobs/serializeCommand.ts +0 -6
  102. package/src/shared/jobs/serializeEnv.ts +0 -6
  103. package/src/shared/jobs/serializeJobsToml.ts +0 -45
  104. package/src/shared/jobs/writeJobsToml.ts +0 -12
  105. package/src/shared/paths/ensureDir.ts +0 -6
  106. package/src/shared/paths/getConfigDir.ts +0 -6
  107. package/src/shared/paths/getEventsPath.ts +0 -6
  108. package/src/shared/paths/getJobRunsDir.ts +0 -7
  109. package/src/shared/paths/getJobsTomlPath.ts +0 -6
  110. package/src/shared/paths/getPaths.ts +0 -16
  111. package/src/shared/paths/getRunOutputPaths.ts +0 -10
  112. package/src/shared/paths/getRunsDir.ts +0 -7
  113. package/src/shared/paths/getStateDir.ts +0 -8
  114. package/src/shared/rpc/createRpcClient.ts +0 -20
  115. package/src/shared/runs/formatRunRow.ts +0 -6
  116. package/src/shared/state/daemonStateSchema.ts +0 -13
  117. package/src/shared/state/getDaemonStatePath.ts +0 -6
  118. package/src/shared/state/readDaemonState.ts +0 -14
  119. package/src/shared/state/removeDaemonState.ts +0 -9
  120. package/src/shared/state/writeDaemonState.ts +0 -8
  121. package/src/shared/utils/isRecord.ts +0 -5
  122. package/src/shared/version.ts +0 -5
@@ -1,46 +0,0 @@
1
- import { zValidator } from "@hono/zod-validator";
2
- import { desc, eq } from "drizzle-orm";
3
- import { Hono } from "hono";
4
- import { z } from "zod";
5
- import type openDatabase from "../../../db/openDatabase";
6
- import { jobs, runs } from "../../../db/schema";
7
- import formatRunRow from "../../../shared/runs/formatRunRow";
8
-
9
- type Db = ReturnType<typeof openDatabase>["orm"];
10
-
11
- const paramsSchema = z.object({
12
- name: z.string().min(1),
13
- });
14
-
15
- const querySchema = z.object({
16
- limit: z.string().optional(),
17
- });
18
-
19
- export default function registerJobRunsRoute(db: Db) {
20
- return new Hono().get(
21
- "/jobs/:name/runs",
22
- zValidator("param", paramsSchema),
23
- zValidator("query", querySchema),
24
- (c) => {
25
- const { name } = c.req.valid("param");
26
- const { limit } = c.req.valid("query");
27
- const row = db.select().from(jobs).where(eq(jobs.name, name)).get();
28
- if (!row) {
29
- return c.json({ error: "job_not_found" }, 404);
30
- }
31
-
32
- const parsedLimit = limit ? Number(limit) : 20;
33
- const safeLimit =
34
- Number.isFinite(parsedLimit) && parsedLimit > 0 ? parsedLimit : 20;
35
- const rows = db
36
- .select()
37
- .from(runs)
38
- .where(eq(runs.jobId, row.id))
39
- .orderBy(desc(runs.startedAt))
40
- .limit(safeLimit)
41
- .all();
42
-
43
- return c.json(rows.map(formatRunRow));
44
- },
45
- );
46
- }
@@ -1,37 +0,0 @@
1
- import { zValidator } from "@hono/zod-validator";
2
- import { Hono } from "hono";
3
- import { z } from "zod";
4
- import type openDatabase from "../../../db/openDatabase";
5
- import type createJobsFileSync from "../../jobs/createJobsFileSync";
6
- import deleteJobByName from "../../jobs/deleteJobByName";
7
- import type createScheduler from "../../scheduler/createScheduler";
8
-
9
- type Db = ReturnType<typeof openDatabase>["orm"];
10
- type Scheduler = ReturnType<typeof createScheduler>;
11
- type JobsFileSync = ReturnType<typeof createJobsFileSync>;
12
-
13
- const paramsSchema = z.object({
14
- name: z.string().min(1),
15
- });
16
-
17
- export default function registerJobsDeleteRoute(
18
- db: Db,
19
- scheduler: Scheduler,
20
- jobsFileSync: JobsFileSync,
21
- ) {
22
- return new Hono().delete(
23
- "/jobs/:name",
24
- zValidator("param", paramsSchema),
25
- (c) => {
26
- const { name } = c.req.valid("param");
27
- const jobId = deleteJobByName(db, name);
28
- if (!jobId) {
29
- return c.json({ error: "job_not_found" }, 404);
30
- }
31
-
32
- scheduler.remove(jobId);
33
- jobsFileSync.writeFromDb();
34
- return c.json({ ok: true, jobId });
35
- },
36
- );
37
- }
@@ -1,29 +0,0 @@
1
- import { zValidator } from "@hono/zod-validator";
2
- import { eq } from "drizzle-orm";
3
- import { Hono } from "hono";
4
- import { z } from "zod";
5
- import type openDatabase from "../../../db/openDatabase";
6
- import { jobs } from "../../../db/schema";
7
- import formatJobRow from "../../../shared/jobs/formatJobRow";
8
-
9
- type Db = ReturnType<typeof openDatabase>["orm"];
10
-
11
- const paramsSchema = z.object({
12
- name: z.string().min(1),
13
- });
14
-
15
- export default function registerJobsGetRoute(db: Db) {
16
- return new Hono().get(
17
- "/jobs/:name",
18
- zValidator("param", paramsSchema),
19
- (c) => {
20
- const { name } = c.req.valid("param");
21
- const row = db.select().from(jobs).where(eq(jobs.name, name)).get();
22
- if (!row) {
23
- return c.json({ error: "job_not_found" }, 404);
24
- }
25
-
26
- return c.json(formatJobRow(row));
27
- },
28
- );
29
- }
@@ -1,45 +0,0 @@
1
- import { zValidator } from "@hono/zod-validator";
2
- import { desc, eq } from "drizzle-orm";
3
- import { Hono } from "hono";
4
- import { z } from "zod";
5
- import type openDatabase from "../../../db/openDatabase";
6
- import { jobs, runs } from "../../../db/schema";
7
-
8
- type Db = ReturnType<typeof openDatabase>["orm"];
9
-
10
- const paramsSchema = z.object({
11
- name: z.string().min(1),
12
- });
13
-
14
- export default function registerJobsKillRoute(db: Db) {
15
- return new Hono().post(
16
- "/jobs/:name/kill",
17
- zValidator("param", paramsSchema),
18
- (c) => {
19
- const { name } = c.req.valid("param");
20
- const job = db.select().from(jobs).where(eq(jobs.name, name)).get();
21
- if (!job) {
22
- return c.json({ error: "job_not_found" }, 404);
23
- }
24
-
25
- const run = db
26
- .select()
27
- .from(runs)
28
- .where(eq(runs.jobId, job.id))
29
- .orderBy(desc(runs.startedAt))
30
- .get();
31
-
32
- if (!run || run.status !== "running" || !run.pid) {
33
- return c.json({ error: "run_not_running" }, 409);
34
- }
35
-
36
- try {
37
- process.kill(run.pid, "SIGKILL");
38
- } catch {
39
- return c.json({ error: "kill_failed" }, 500);
40
- }
41
-
42
- return c.json({ ok: true, runId: run.id });
43
- },
44
- );
45
- }
@@ -1,13 +0,0 @@
1
- import { Hono } from "hono";
2
- import type openDatabase from "../../../db/openDatabase";
3
- import { jobs } from "../../../db/schema";
4
- import formatJobRow from "../../../shared/jobs/formatJobRow";
5
-
6
- type Db = ReturnType<typeof openDatabase>["orm"];
7
-
8
- export default function registerJobsListRoute(db: Db) {
9
- return new Hono().get("/jobs", (c) => {
10
- const rows = db.select().from(jobs).all();
11
- return c.json(rows.map(formatJobRow));
12
- });
13
- }
@@ -1,53 +0,0 @@
1
- import { zValidator } from "@hono/zod-validator";
2
- import { eq } from "drizzle-orm";
3
- import { Hono } from "hono";
4
- import { z } from "zod";
5
- import type openDatabase from "../../../db/openDatabase";
6
- import { jobs } from "../../../db/schema";
7
- import appendEvent from "../../../shared/events/appendEvent";
8
- import formatJobRow from "../../../shared/jobs/formatJobRow";
9
- import type createJobsFileSync from "../../jobs/createJobsFileSync";
10
- import type createScheduler from "../../scheduler/createScheduler";
11
-
12
- type Db = ReturnType<typeof openDatabase>["orm"];
13
- type Scheduler = ReturnType<typeof createScheduler>;
14
- type JobsFileSync = ReturnType<typeof createJobsFileSync>;
15
-
16
- const paramsSchema = z.object({
17
- name: z.string().min(1),
18
- });
19
-
20
- export default function registerJobsPauseRoute(
21
- db: Db,
22
- scheduler: Scheduler,
23
- jobsFileSync: JobsFileSync,
24
- ) {
25
- return new Hono().post(
26
- "/jobs/:name/pause",
27
- zValidator("param", paramsSchema),
28
- (c) => {
29
- const { name } = c.req.valid("param");
30
- const row = db.select().from(jobs).where(eq(jobs.name, name)).get();
31
- if (!row) {
32
- return c.json({ error: "job_not_found" }, 404);
33
- }
34
-
35
- const now = new Date().toISOString();
36
- db.update(jobs)
37
- .set({ paused: true, nextRunAt: null, updatedAt: now })
38
- .where(eq(jobs.id, row.id))
39
- .run();
40
-
41
- const updated = db.select().from(jobs).where(eq(jobs.id, row.id)).get();
42
- if (!updated) {
43
- return c.json({ error: "job_not_found" }, 404);
44
- }
45
-
46
- const job = formatJobRow(updated);
47
- scheduler.remove(job.id);
48
- jobsFileSync.writeFromDb();
49
- appendEvent("job_paused", { jobId: job.id, name: job.name });
50
- return c.json(job);
51
- },
52
- );
53
- }
@@ -1,54 +0,0 @@
1
- import { zValidator } from "@hono/zod-validator";
2
- import { eq } from "drizzle-orm";
3
- import { Hono } from "hono";
4
- import { z } from "zod";
5
- import type openDatabase from "../../../db/openDatabase";
6
- import { jobs, runs } from "../../../db/schema";
7
- import appendEvent from "../../../shared/events/appendEvent";
8
- import formatJobRow from "../../../shared/jobs/formatJobRow";
9
- import type createJobsFileSync from "../../jobs/createJobsFileSync";
10
- import type createScheduler from "../../scheduler/createScheduler";
11
-
12
- type Db = ReturnType<typeof openDatabase>["orm"];
13
- type Scheduler = ReturnType<typeof createScheduler>;
14
- type JobsFileSync = ReturnType<typeof createJobsFileSync>;
15
-
16
- const paramsSchema = z.object({
17
- name: z.string().min(1),
18
- });
19
-
20
- export default function registerJobsResetRoute(
21
- db: Db,
22
- scheduler: Scheduler,
23
- jobsFileSync: JobsFileSync,
24
- ) {
25
- return new Hono().post(
26
- "/jobs/:name/reset",
27
- zValidator("param", paramsSchema),
28
- (c) => {
29
- const { name } = c.req.valid("param");
30
- const row = db.select().from(jobs).where(eq(jobs.name, name)).get();
31
- if (!row) {
32
- return c.json({ error: "job_not_found" }, 404);
33
- }
34
-
35
- db.delete(runs).where(eq(runs.jobId, row.id)).run();
36
- const now = new Date().toISOString();
37
- db.update(jobs)
38
- .set({ lastRunAt: null, nextRunAt: null, updatedAt: now })
39
- .where(eq(jobs.id, row.id))
40
- .run();
41
-
42
- const updated = db.select().from(jobs).where(eq(jobs.id, row.id)).get();
43
- if (!updated) {
44
- return c.json({ error: "job_not_found" }, 404);
45
- }
46
-
47
- const job = formatJobRow(updated);
48
- scheduler.upsert(job);
49
- jobsFileSync.writeFromDb();
50
- appendEvent("job_reset", { jobId: job.id, name: job.name });
51
- return c.json(job);
52
- },
53
- );
54
- }
@@ -1,53 +0,0 @@
1
- import { zValidator } from "@hono/zod-validator";
2
- import { eq } from "drizzle-orm";
3
- import { Hono } from "hono";
4
- import { z } from "zod";
5
- import type openDatabase from "../../../db/openDatabase";
6
- import { jobs } from "../../../db/schema";
7
- import appendEvent from "../../../shared/events/appendEvent";
8
- import formatJobRow from "../../../shared/jobs/formatJobRow";
9
- import type createJobsFileSync from "../../jobs/createJobsFileSync";
10
- import type createScheduler from "../../scheduler/createScheduler";
11
-
12
- type Db = ReturnType<typeof openDatabase>["orm"];
13
- type Scheduler = ReturnType<typeof createScheduler>;
14
- type JobsFileSync = ReturnType<typeof createJobsFileSync>;
15
-
16
- const paramsSchema = z.object({
17
- name: z.string().min(1),
18
- });
19
-
20
- export default function registerJobsResumeRoute(
21
- db: Db,
22
- scheduler: Scheduler,
23
- jobsFileSync: JobsFileSync,
24
- ) {
25
- return new Hono().post(
26
- "/jobs/:name/resume",
27
- zValidator("param", paramsSchema),
28
- (c) => {
29
- const { name } = c.req.valid("param");
30
- const row = db.select().from(jobs).where(eq(jobs.name, name)).get();
31
- if (!row) {
32
- return c.json({ error: "job_not_found" }, 404);
33
- }
34
-
35
- const now = new Date().toISOString();
36
- db.update(jobs)
37
- .set({ paused: false, updatedAt: now })
38
- .where(eq(jobs.id, row.id))
39
- .run();
40
-
41
- const updated = db.select().from(jobs).where(eq(jobs.id, row.id)).get();
42
- if (!updated) {
43
- return c.json({ error: "job_not_found" }, 404);
44
- }
45
-
46
- const job = formatJobRow(updated);
47
- scheduler.upsert(job);
48
- jobsFileSync.writeFromDb();
49
- appendEvent("job_resumed", { jobId: job.id, name: job.name });
50
- return c.json(job);
51
- },
52
- );
53
- }
@@ -1,37 +0,0 @@
1
- import { zValidator } from "@hono/zod-validator";
2
- import { eq } from "drizzle-orm";
3
- import { Hono } from "hono";
4
- import { z } from "zod";
5
- import type openDatabase from "../../../db/openDatabase";
6
- import { jobs } from "../../../db/schema";
7
- import formatJobRow from "../../../shared/jobs/formatJobRow";
8
- import type createScheduler from "../../scheduler/createScheduler";
9
-
10
- type Db = ReturnType<typeof openDatabase>["orm"];
11
- type Scheduler = ReturnType<typeof createScheduler>;
12
-
13
- const payloadSchema = z.object({
14
- name: z.string().min(1),
15
- });
16
-
17
- export default function registerJobsRunRoute(db: Db, scheduler: Scheduler) {
18
- return new Hono().post(
19
- "/jobs/run",
20
- zValidator("json", payloadSchema),
21
- (c) => {
22
- const payload = c.req.valid("json");
23
- const row = db
24
- .select()
25
- .from(jobs)
26
- .where(eq(jobs.name, payload.name))
27
- .get();
28
- if (!row) {
29
- return c.json({ error: "job_not_found" }, 404);
30
- }
31
-
32
- const job = formatJobRow(row);
33
- const runId = scheduler.runNow(job);
34
- return c.json({ ok: true, jobId: job.id, runId });
35
- },
36
- );
37
- }
@@ -1,45 +0,0 @@
1
- import { zValidator } from "@hono/zod-validator";
2
- import { desc, eq } from "drizzle-orm";
3
- import { Hono } from "hono";
4
- import { z } from "zod";
5
- import type openDatabase from "../../../db/openDatabase";
6
- import { jobs, runs } from "../../../db/schema";
7
-
8
- type Db = ReturnType<typeof openDatabase>["orm"];
9
-
10
- const paramsSchema = z.object({
11
- name: z.string().min(1),
12
- });
13
-
14
- export default function registerJobsStopRoute(db: Db) {
15
- return new Hono().post(
16
- "/jobs/:name/stop",
17
- zValidator("param", paramsSchema),
18
- (c) => {
19
- const { name } = c.req.valid("param");
20
- const job = db.select().from(jobs).where(eq(jobs.name, name)).get();
21
- if (!job) {
22
- return c.json({ error: "job_not_found" }, 404);
23
- }
24
-
25
- const run = db
26
- .select()
27
- .from(runs)
28
- .where(eq(runs.jobId, job.id))
29
- .orderBy(desc(runs.startedAt))
30
- .get();
31
-
32
- if (!run || run.status !== "running" || !run.pid) {
33
- return c.json({ error: "run_not_running" }, 409);
34
- }
35
-
36
- try {
37
- process.kill(run.pid, "SIGTERM");
38
- } catch {
39
- return c.json({ error: "stop_failed" }, 500);
40
- }
41
-
42
- return c.json({ ok: true, runId: run.id });
43
- },
44
- );
45
- }
@@ -1,30 +0,0 @@
1
- import { zValidator } from "@hono/zod-validator";
2
- import { Hono } from "hono";
3
- import type openDatabase from "../../../db/openDatabase";
4
- import createJobInputSchema from "../../../shared/jobs/createJobInputSchema";
5
- import type createJobsFileSync from "../../jobs/createJobsFileSync";
6
- import upsertJob from "../../jobs/upsertJob";
7
- import type createScheduler from "../../scheduler/createScheduler";
8
-
9
- type Db = ReturnType<typeof openDatabase>["orm"];
10
- type Scheduler = ReturnType<typeof createScheduler>;
11
- type JobsFileSync = ReturnType<typeof createJobsFileSync>;
12
-
13
- export default function registerJobsUpsertRoute(
14
- db: Db,
15
- scheduler: Scheduler,
16
- jobsFileSync: JobsFileSync,
17
- ) {
18
- const schema = createJobInputSchema();
19
- return new Hono().post("/jobs", zValidator("json", schema), (c) => {
20
- const input = c.req.valid("json");
21
- try {
22
- const result = upsertJob(db, input);
23
- scheduler.upsert(result.job);
24
- jobsFileSync.writeFromDb();
25
- return c.json(result.job);
26
- } catch {
27
- return c.json({ error: "job_not_saved" }, 500);
28
- }
29
- });
30
- }
@@ -1,25 +0,0 @@
1
- import { zValidator } from "@hono/zod-validator";
2
- import { eq } from "drizzle-orm";
3
- import { Hono } from "hono";
4
- import { z } from "zod";
5
- import type openDatabase from "../../../db/openDatabase";
6
- import { runs } from "../../../db/schema";
7
- import formatRunRow from "../../../shared/runs/formatRunRow";
8
-
9
- type Db = ReturnType<typeof openDatabase>["orm"];
10
-
11
- const paramsSchema = z.object({
12
- id: z.string().min(1),
13
- });
14
-
15
- export default function registerRunGetRoute(db: Db) {
16
- return new Hono().get("/runs/:id", zValidator("param", paramsSchema), (c) => {
17
- const { id } = c.req.valid("param");
18
- const row = db.select().from(runs).where(eq(runs.id, id)).get();
19
- if (!row) {
20
- return c.json({ error: "run_not_found" }, 404);
21
- }
22
-
23
- return c.json(formatRunRow(row));
24
- });
25
- }
@@ -1,32 +0,0 @@
1
- import { zValidator } from "@hono/zod-validator";
2
- import { eq } from "drizzle-orm";
3
- import { Hono } from "hono";
4
- import { z } from "zod";
5
- import type openDatabase from "../../../db/openDatabase";
6
- import { runs } from "../../../db/schema";
7
-
8
- type Db = ReturnType<typeof openDatabase>["orm"];
9
-
10
- const paramsSchema = z.object({
11
- id: z.string().min(1),
12
- });
13
-
14
- export default function registerRunLogsRoute(db: Db) {
15
- return new Hono().get(
16
- "/runs/:id/logs",
17
- zValidator("param", paramsSchema),
18
- (c) => {
19
- const { id } = c.req.valid("param");
20
- const row = db.select().from(runs).where(eq(runs.id, id)).get();
21
- if (!row) {
22
- return c.json({ error: "run_not_found" }, 404);
23
- }
24
-
25
- return c.json({
26
- runId: row.id,
27
- stdoutPath: row.stdoutPath,
28
- stderrPath: row.stderrPath,
29
- });
30
- },
31
- );
32
- }
@@ -1,9 +0,0 @@
1
- import { Hono } from "hono";
2
-
3
- export default function registerShutdownRoute(shutdown: () => void) {
4
- return new Hono().post("/daemon/shutdown", (c) => {
5
- const response = c.json({ ok: true });
6
- setTimeout(() => shutdown(), 10);
7
- return response;
8
- });
9
- }
@@ -1,23 +0,0 @@
1
- import type { Hono } from "hono";
2
-
3
- export default function startServer(app: Hono) {
4
- const basePort = 51337;
5
- const attempts = 25;
6
-
7
- for (let offset = 0; offset < attempts; offset += 1) {
8
- const port = basePort + offset;
9
- try {
10
- return Bun.serve({
11
- fetch: app.fetch,
12
- hostname: "127.0.0.1",
13
- port,
14
- });
15
- } catch (error) {
16
- if (offset === attempts - 1) {
17
- throw error;
18
- }
19
- }
20
- }
21
-
22
- throw new Error("Unable to bind to a local port");
23
- }
@@ -1,5 +0,0 @@
1
- import path from "node:path";
2
-
3
- export default function getMigrationsDir() {
4
- return path.join(process.cwd(), "drizzle");
5
- }
@@ -1,21 +0,0 @@
1
- import { existsSync } from "node:fs";
2
- import { migrate } from "drizzle-orm/bun-sqlite/migrator";
3
- import getMigrationsDir from "./getMigrationsDir";
4
- import openDatabase from "./openDatabase";
5
-
6
- type Db = ReturnType<typeof openDatabase>["orm"];
7
-
8
- export default function migrateDatabase(db?: Db) {
9
- const migrationsFolder = getMigrationsDir();
10
- if (!existsSync(migrationsFolder)) {
11
- return { migrated: false, reason: "missing_migrations" };
12
- }
13
-
14
- const orm = db ?? openDatabase().orm;
15
- try {
16
- migrate(orm, { migrationsFolder });
17
- return { migrated: true };
18
- } catch {
19
- return { migrated: false, reason: "migration_failed" };
20
- }
21
- }
@@ -1,12 +0,0 @@
1
- import { Database } from "bun:sqlite";
2
- import path from "node:path";
3
- import { drizzle } from "drizzle-orm/bun-sqlite";
4
- import getStateDir from "../shared/paths/getStateDir";
5
-
6
- export default function openDatabase() {
7
- const filename = path.join(getStateDir(), "crnd.db");
8
- const db = new Database(filename);
9
- db.exec("PRAGMA foreign_keys = ON;");
10
- db.exec("PRAGMA journal_mode = WAL;");
11
- return { db, orm: drizzle(db) };
12
- }
@@ -1,26 +0,0 @@
1
- import { sql } from "drizzle-orm";
2
- import { integer, sqliteTable, text } from "drizzle-orm/sqlite-core";
3
-
4
- const jobsTable = sqliteTable("jobs", {
5
- id: text("id").primaryKey(),
6
- name: text("name").notNull().unique(),
7
- description: text("description"),
8
- command: text("command").notNull(),
9
- cwd: text("cwd"),
10
- env: text("env"),
11
- scheduleType: text("schedule_type").notNull(),
12
- cron: text("cron"),
13
- runAt: text("run_at"),
14
- timezone: text("timezone"),
15
- overlapPolicy: text("overlap_policy").notNull().default("skip"),
16
- timeoutMs: integer("timeout_ms"),
17
- paused: integer("paused", { mode: "boolean" }).notNull().default(false),
18
- createdAt: text("created_at").notNull().default(sql`CURRENT_TIMESTAMP`),
19
- updatedAt: text("updated_at").notNull().default(sql`CURRENT_TIMESTAMP`),
20
- lastRunAt: text("last_run_at"),
21
- nextRunAt: text("next_run_at"),
22
- });
23
-
24
- export default function getJobsTable() {
25
- return jobsTable;
26
- }
@@ -1,10 +0,0 @@
1
- import { createInsertSchema, createSelectSchema } from "drizzle-zod";
2
- import getJobsTable from "./jobs";
3
-
4
- export default function createJobsSchemas() {
5
- const jobs = getJobsTable();
6
- return {
7
- insert: createInsertSchema(jobs),
8
- select: createSelectSchema(jobs),
9
- };
10
- }
@@ -1,23 +0,0 @@
1
- import { integer, sqliteTable, text } from "drizzle-orm/sqlite-core";
2
- import getJobsTable from "./jobs";
3
-
4
- const jobsTable = getJobsTable();
5
- const runsTable = sqliteTable("runs", {
6
- id: text("id").primaryKey(),
7
- jobId: text("job_id")
8
- .notNull()
9
- .references(() => jobsTable.id),
10
- status: text("status").notNull(),
11
- pid: integer("pid"),
12
- exitCode: integer("exit_code"),
13
- signal: text("signal"),
14
- startedAt: text("started_at"),
15
- endedAt: text("ended_at"),
16
- stdoutPath: text("stdout_path"),
17
- stderrPath: text("stderr_path"),
18
- errorMessage: text("error_message"),
19
- });
20
-
21
- export default function getRunsTable() {
22
- return runsTable;
23
- }
@@ -1,10 +0,0 @@
1
- import { createInsertSchema, createSelectSchema } from "drizzle-zod";
2
- import getRunsTable from "./runs";
3
-
4
- export default function createRunsSchemas() {
5
- const runs = getRunsTable();
6
- return {
7
- insert: createInsertSchema(runs),
8
- select: createSelectSchema(runs),
9
- };
10
- }
package/src/db/schema.ts DELETED
@@ -1,5 +0,0 @@
1
- import getJobsTable from "./schema/jobs";
2
- import getRunsTable from "./schema/runs";
3
-
4
- export const jobs = getJobsTable();
5
- export const runs = getRunsTable();