crnd 0.0.1 → 0.0.3

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
package/bin/crnd ADDED
@@ -0,0 +1,88 @@
1
+ #!/usr/bin/env node
2
+ const { platform, arch, env } = process;
3
+ const { execSync, spawnSync } = require("child_process");
4
+
5
+ function isMusl() {
6
+ if (platform !== "linux") {
7
+ return false;
8
+ }
9
+ try {
10
+ const output = execSync("ldd --version 2>&1", {
11
+ encoding: "utf8",
12
+ stdio: ["pipe", "pipe", "pipe"],
13
+ });
14
+ return output.toLowerCase().includes("musl");
15
+ } catch (err) {
16
+ // If ldd fails, check if we're on Alpine by looking at /etc/os-release
17
+ try {
18
+ const osRelease = require("fs").readFileSync("/etc/os-release", "utf8");
19
+ return osRelease.toLowerCase().includes("alpine");
20
+ } catch {
21
+ return false;
22
+ }
23
+ }
24
+ }
25
+
26
+ const PLATFORMS = {
27
+ win32: {
28
+ x64: "@crnd/cli-win32-x64/crnd.exe",
29
+ },
30
+ darwin: {
31
+ x64: "@crnd/cli-darwin-x64/crnd",
32
+ arm64: "@crnd/cli-darwin-arm64/crnd",
33
+ },
34
+ linux: {
35
+ x64: "@crnd/cli-linux-x64/crnd",
36
+ arm64: "@crnd/cli-linux-arm64/crnd",
37
+ },
38
+ "linux-musl": {
39
+ x64: "@crnd/cli-linux-x64-musl/crnd",
40
+ arm64: "@crnd/cli-linux-arm64-musl/crnd",
41
+ },
42
+ };
43
+
44
+ function getBinaryPath() {
45
+ // Allow override via environment variable
46
+ if (env.CRND_BINARY_PATH) {
47
+ return env.CRND_BINARY_PATH;
48
+ }
49
+
50
+ const platformKey = platform === "linux" && isMusl() ? "linux-musl" : platform;
51
+ const binPath = PLATFORMS[platformKey]?.[arch];
52
+
53
+ if (!binPath) {
54
+ console.error(
55
+ `crnd does not support your platform yet: ${platform} ${arch}\n` +
56
+ `If you think this is a bug, please open an issue at:\n` +
57
+ `https://github.com/ysm-dev/crnd/issues`
58
+ );
59
+ process.exit(1);
60
+ }
61
+
62
+ try {
63
+ return require.resolve(binPath);
64
+ } catch {
65
+ console.error(
66
+ `Could not find the crnd binary for your platform: ${platform} ${arch}\n\n` +
67
+ `This usually means the optional dependency was not installed.\n` +
68
+ `Try reinstalling with: npm install crnd\n\n` +
69
+ `If the problem persists, please open an issue at:\n` +
70
+ `https://github.com/ysm-dev/crnd/issues`
71
+ );
72
+ process.exit(1);
73
+ }
74
+ }
75
+
76
+ const binaryPath = getBinaryPath();
77
+
78
+ const result = spawnSync(binaryPath, process.argv.slice(2), {
79
+ stdio: "inherit",
80
+ shell: false,
81
+ });
82
+
83
+ if (result.error) {
84
+ console.error(`Failed to execute crnd: ${result.error.message}`);
85
+ process.exit(1);
86
+ }
87
+
88
+ process.exit(result.status ?? 0);
package/package.json CHANGED
@@ -1,24 +1,13 @@
1
1
  {
2
2
  "name": "crnd",
3
- "version": "0.0.1",
3
+ "version": "0.0.3",
4
4
  "description": "Agent-first CLI for cron scheduling and process management",
5
- "type": "module",
6
- "bin": {
7
- "crnd": "src/cli/main.ts"
8
- },
9
- "files": [
10
- "src",
11
- "drizzle"
12
- ],
13
- "scripts": {
14
- "dev": "bun run src/cli/main.ts",
15
- "build": "bun build ./src/cli/main.ts --compile --outfile dist/crnd",
16
- "lint": "biome lint .",
17
- "format": "biome format . --write",
18
- "check": "biome check .",
19
- "typecheck": "tsgo --noEmit",
20
- "test": "bun test"
5
+ "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/ysm-dev/crnd.git"
21
9
  },
10
+ "homepage": "https://github.com/ysm-dev/crnd#readme",
22
11
  "keywords": [
23
12
  "cron",
24
13
  "scheduler",
@@ -28,32 +17,19 @@
28
17
  "process-manager"
29
18
  ],
30
19
  "author": "ysm-dev",
31
- "license": "MIT",
32
- "repository": {
33
- "type": "git",
34
- "url": "git+https://github.com/ysm-dev/crnd.git"
35
- },
36
- "bugs": {
37
- "url": "https://github.com/ysm-dev/crnd/issues"
38
- },
39
- "homepage": "https://github.com/ysm-dev/crnd#readme",
40
- "dependencies": {
41
- "@hono/zod-validator": "^0.7.6",
42
- "@iarna/toml": "^2.2.5",
43
- "citty": "^0.2.0",
44
- "consola": "^3.4.2",
45
- "croner": "^9.1.0",
46
- "drizzle-orm": "^0.45.1",
47
- "drizzle-zod": "^0.8.3",
48
- "env-paths": "^4.0.0",
49
- "hono": "^4.11.7",
50
- "ulid": "^3.0.2",
51
- "zod": "^4.3.6"
20
+ "bin": {
21
+ "crnd": "bin/crnd"
52
22
  },
53
- "devDependencies": {
54
- "@biomejs/biome": "^2.3.13",
55
- "@typescript/native-preview": "7.0.0-dev.20260131.1",
56
- "bun-types": "^1.3.8",
57
- "drizzle-kit": "^0.31.8"
23
+ "files": [
24
+ "bin"
25
+ ],
26
+ "optionalDependencies": {
27
+ "@crnd/cli-darwin-arm64": "0.0.3",
28
+ "@crnd/cli-darwin-x64": "0.0.3",
29
+ "@crnd/cli-linux-x64": "0.0.3",
30
+ "@crnd/cli-linux-arm64": "0.0.3",
31
+ "@crnd/cli-linux-x64-musl": "0.0.3",
32
+ "@crnd/cli-linux-arm64-musl": "0.0.3",
33
+ "@crnd/cli-win32-x64": "0.0.3"
58
34
  }
59
35
  }
@@ -1,35 +0,0 @@
1
- CREATE TABLE IF NOT EXISTS "jobs" (
2
- "id" text PRIMARY KEY NOT NULL,
3
- "name" text NOT NULL UNIQUE,
4
- "description" text,
5
- "command" text NOT NULL,
6
- "cwd" text,
7
- "env" text,
8
- "schedule_type" text NOT NULL,
9
- "cron" text,
10
- "run_at" text,
11
- "timezone" text,
12
- "overlap_policy" text NOT NULL DEFAULT 'skip',
13
- "timeout_ms" integer,
14
- "paused" integer NOT NULL DEFAULT 0,
15
- "created_at" text NOT NULL DEFAULT CURRENT_TIMESTAMP,
16
- "updated_at" text NOT NULL DEFAULT CURRENT_TIMESTAMP,
17
- "last_run_at" text,
18
- "next_run_at" text
19
- );
20
-
21
- --> statement-breakpoint
22
-
23
- CREATE TABLE IF NOT EXISTS "runs" (
24
- "id" text PRIMARY KEY NOT NULL,
25
- "job_id" text NOT NULL REFERENCES "jobs"("id"),
26
- "status" text NOT NULL,
27
- "pid" integer,
28
- "exit_code" integer,
29
- "signal" text,
30
- "started_at" text,
31
- "ended_at" text,
32
- "stdout_path" text,
33
- "stderr_path" text,
34
- "error_message" text
35
- );
@@ -1,13 +0,0 @@
1
- CREATE TABLE IF NOT EXISTS "runs" (
2
- "id" text PRIMARY KEY NOT NULL,
3
- "job_id" text NOT NULL REFERENCES "jobs"("id"),
4
- "status" text NOT NULL,
5
- "pid" integer,
6
- "exit_code" integer,
7
- "signal" text,
8
- "started_at" text,
9
- "ended_at" text,
10
- "stdout_path" text,
11
- "stderr_path" text,
12
- "error_message" text
13
- );
@@ -1,20 +0,0 @@
1
- {
2
- "version": "5",
3
- "dialect": "sqlite",
4
- "entries": [
5
- {
6
- "idx": 0,
7
- "version": "0000",
8
- "when": 1700000000000,
9
- "tag": "0000_init",
10
- "breakpoints": true
11
- },
12
- {
13
- "idx": 1,
14
- "version": "0001",
15
- "when": 1700000001000,
16
- "tag": "0001_add_runs",
17
- "breakpoints": true
18
- }
19
- ]
20
- }
@@ -1,93 +0,0 @@
1
- import { defineCommand } from "citty";
2
- import createRpcClient from "../../shared/rpc/createRpcClient";
3
-
4
- export default function createDeleteCommand() {
5
- return defineCommand({
6
- meta: {
7
- name: "delete",
8
- description: "Delete a job",
9
- },
10
- args: {
11
- name: {
12
- type: "string",
13
- alias: "n",
14
- required: true,
15
- },
16
- force: {
17
- type: "boolean",
18
- alias: "f",
19
- },
20
- json: {
21
- type: "boolean",
22
- alias: "j",
23
- },
24
- },
25
- async run({ args }) {
26
- if (!args.force) {
27
- const payload = { status: "missing_force" };
28
- if (!process.stdout.isTTY || args.json) {
29
- console.log(JSON.stringify(payload));
30
- } else {
31
- console.log("delete: requires --force");
32
- }
33
- process.exitCode = 2;
34
- return;
35
- }
36
-
37
- const client = createRpcClient();
38
- if (!client) {
39
- const payload = { status: "unreachable" };
40
- if (!process.stdout.isTTY || args.json) {
41
- console.log(JSON.stringify(payload));
42
- } else {
43
- console.log("daemon: unreachable");
44
- }
45
- process.exitCode = 3;
46
- return;
47
- }
48
-
49
- try {
50
- const res = await client.jobs[":name"].$delete({
51
- param: { name: args.name },
52
- });
53
- if (res.status === 404) {
54
- const payload = { status: "not_found" };
55
- if (!process.stdout.isTTY || args.json) {
56
- console.log(JSON.stringify(payload));
57
- } else {
58
- console.log("delete: job not found");
59
- }
60
- process.exitCode = 1;
61
- return;
62
- }
63
-
64
- if (!res.ok) {
65
- const payload = { status: "error", code: res.status };
66
- if (!process.stdout.isTTY || args.json) {
67
- console.log(JSON.stringify(payload));
68
- } else {
69
- console.log(`delete: error (${res.status})`);
70
- }
71
- process.exitCode = 1;
72
- return;
73
- }
74
-
75
- const data = await res.json();
76
- if (!process.stdout.isTTY || args.json) {
77
- console.log(JSON.stringify(data));
78
- return;
79
- }
80
-
81
- console.log(`delete: removed (${data.jobId})`);
82
- } catch {
83
- const payload = { status: "unreachable" };
84
- if (!process.stdout.isTTY || args.json) {
85
- console.log(JSON.stringify(payload));
86
- } else {
87
- console.log("daemon: unreachable");
88
- }
89
- process.exitCode = 3;
90
- }
91
- },
92
- });
93
- }
@@ -1,93 +0,0 @@
1
- import { accessSync, constants, existsSync } from "node:fs";
2
- import { defineCommand } from "citty";
3
- import getAutostartPath from "../../daemon/autostart/getAutostartPath";
4
- import getJobsTomlPath from "../../shared/paths/getJobsTomlPath";
5
- import createRpcClient from "../../shared/rpc/createRpcClient";
6
-
7
- export default function createDoctorCommand() {
8
- return defineCommand({
9
- meta: {
10
- name: "doctor",
11
- description: "Check crnd health",
12
- },
13
- args: {
14
- json: {
15
- type: "boolean",
16
- alias: "j",
17
- },
18
- },
19
- async run({ args }) {
20
- const results: Array<{ check: string; ok: boolean; detail?: string }> =
21
- [];
22
- const client = createRpcClient();
23
-
24
- if (!client) {
25
- results.push({ check: "daemon", ok: false, detail: "unreachable" });
26
- } else {
27
- try {
28
- const res = await client.health.$get();
29
- results.push({
30
- check: "daemon",
31
- ok: res.ok,
32
- detail: res.ok ? "running" : `status ${res.status}`,
33
- });
34
- } catch {
35
- results.push({ check: "daemon", ok: false, detail: "unreachable" });
36
- }
37
- }
38
-
39
- const jobsToml = getJobsTomlPath();
40
- if (!existsSync(jobsToml)) {
41
- results.push({ check: "jobs.toml", ok: false, detail: "missing" });
42
- } else {
43
- try {
44
- accessSync(jobsToml, constants.R_OK | constants.W_OK);
45
- results.push({ check: "jobs.toml", ok: true });
46
- } catch {
47
- results.push({
48
- check: "jobs.toml",
49
- ok: false,
50
- detail: "not_readable",
51
- });
52
- }
53
- }
54
-
55
- const autostartPath = getAutostartPath();
56
- if (!autostartPath) {
57
- results.push({ check: "autostart", ok: false, detail: "unsupported" });
58
- } else if (process.platform === "win32") {
59
- const result = Bun.spawnSync([
60
- "schtasks",
61
- "/Query",
62
- "/TN",
63
- autostartPath,
64
- ]);
65
- results.push({
66
- check: "autostart",
67
- ok: result.success,
68
- detail: "task",
69
- });
70
- } else {
71
- results.push({
72
- check: "autostart",
73
- ok: existsSync(autostartPath),
74
- detail: autostartPath,
75
- });
76
- }
77
-
78
- const ok = results.every((item) => item.ok);
79
- if (!process.stdout.isTTY || args.json) {
80
- console.log(JSON.stringify({ ok, results }));
81
- } else {
82
- for (const item of results) {
83
- const detail = item.detail ? ` (${item.detail})` : "";
84
- console.log(`${item.check}: ${item.ok ? "ok" : "fail"}${detail}`);
85
- }
86
- }
87
-
88
- if (!ok) {
89
- process.exitCode = 1;
90
- }
91
- },
92
- });
93
- }
@@ -1,75 +0,0 @@
1
- import { writeFileSync } from "node:fs";
2
- import { defineCommand } from "citty";
3
- import createRpcClient from "../../shared/rpc/createRpcClient";
4
-
5
- export default function createExportCommand() {
6
- return defineCommand({
7
- meta: {
8
- name: "export",
9
- description: "Export jobs to TOML",
10
- },
11
- args: {
12
- output: {
13
- type: "string",
14
- alias: "o",
15
- },
16
- json: {
17
- type: "boolean",
18
- alias: "j",
19
- },
20
- },
21
- async run({ args }) {
22
- const client = createRpcClient();
23
- if (!client) {
24
- const payload = { status: "unreachable" };
25
- if (!process.stdout.isTTY || args.json) {
26
- console.log(JSON.stringify(payload));
27
- } else {
28
- console.log("daemon: unreachable");
29
- }
30
- process.exitCode = 3;
31
- return;
32
- }
33
-
34
- try {
35
- const res = await client.export.$post();
36
- if (!res.ok) {
37
- const payload = { status: "error", code: res.status };
38
- if (!process.stdout.isTTY || args.json) {
39
- console.log(JSON.stringify(payload));
40
- } else {
41
- console.log(`export: error (${res.status})`);
42
- }
43
- process.exitCode = 1;
44
- return;
45
- }
46
-
47
- const data = await res.json();
48
- if (args.output) {
49
- writeFileSync(args.output, data.toml, "utf-8");
50
- if (!process.stdout.isTTY || args.json) {
51
- console.log(JSON.stringify({ ok: true, output: args.output }));
52
- } else {
53
- console.log(`export: wrote ${args.output}`);
54
- }
55
- return;
56
- }
57
-
58
- if (!process.stdout.isTTY || args.json) {
59
- console.log(JSON.stringify(data));
60
- return;
61
- }
62
-
63
- console.log(data.toml);
64
- } catch {
65
- const payload = { status: "unreachable" };
66
- if (!process.stdout.isTTY || args.json) {
67
- console.log(JSON.stringify(payload));
68
- } else {
69
- console.log("daemon: unreachable");
70
- }
71
- process.exitCode = 3;
72
- }
73
- },
74
- });
75
- }
@@ -1,80 +0,0 @@
1
- import { readFileSync } from "node:fs";
2
- import { defineCommand } from "citty";
3
- import createRpcClient from "../../shared/rpc/createRpcClient";
4
-
5
- export default function createImportCommand() {
6
- return defineCommand({
7
- meta: {
8
- name: "import",
9
- description: "Import jobs from TOML",
10
- },
11
- args: {
12
- file: {
13
- type: "string",
14
- alias: "f",
15
- required: true,
16
- },
17
- json: {
18
- type: "boolean",
19
- alias: "j",
20
- },
21
- },
22
- async run({ args }) {
23
- const client = createRpcClient();
24
- if (!client) {
25
- const payload = { status: "unreachable" };
26
- if (!process.stdout.isTTY || args.json) {
27
- console.log(JSON.stringify(payload));
28
- } else {
29
- console.log("daemon: unreachable");
30
- }
31
- process.exitCode = 3;
32
- return;
33
- }
34
-
35
- let toml: string;
36
- try {
37
- toml = readFileSync(args.file, "utf-8");
38
- } catch {
39
- const payload = { status: "missing_file" };
40
- if (!process.stdout.isTTY || args.json) {
41
- console.log(JSON.stringify(payload));
42
- } else {
43
- console.log("import: failed to read file");
44
- }
45
- process.exitCode = 2;
46
- return;
47
- }
48
-
49
- try {
50
- const res = await client.import.$post({ json: { toml } });
51
- if (!res.ok) {
52
- const payload = { status: "error", code: res.status };
53
- if (!process.stdout.isTTY || args.json) {
54
- console.log(JSON.stringify(payload));
55
- } else {
56
- console.log(`import: error (${res.status})`);
57
- }
58
- process.exitCode = 1;
59
- return;
60
- }
61
-
62
- const data = await res.json();
63
- if (!process.stdout.isTTY || args.json) {
64
- console.log(JSON.stringify(data));
65
- return;
66
- }
67
-
68
- console.log("import: ok");
69
- } catch {
70
- const payload = { status: "unreachable" };
71
- if (!process.stdout.isTTY || args.json) {
72
- console.log(JSON.stringify(payload));
73
- } else {
74
- console.log("daemon: unreachable");
75
- }
76
- process.exitCode = 3;
77
- }
78
- },
79
- });
80
- }
@@ -1,89 +0,0 @@
1
- import { defineCommand } from "citty";
2
- import createRpcClient from "../../shared/rpc/createRpcClient";
3
-
4
- export default function createKillCommand() {
5
- return defineCommand({
6
- meta: {
7
- name: "kill",
8
- description: "Kill a running job",
9
- },
10
- args: {
11
- name: {
12
- type: "string",
13
- alias: "n",
14
- required: true,
15
- },
16
- json: {
17
- type: "boolean",
18
- alias: "j",
19
- },
20
- },
21
- async run({ args }) {
22
- const client = createRpcClient();
23
- if (!client) {
24
- const payload = { status: "unreachable" };
25
- if (!process.stdout.isTTY || args.json) {
26
- console.log(JSON.stringify(payload));
27
- } else {
28
- console.log("daemon: unreachable");
29
- }
30
- process.exitCode = 3;
31
- return;
32
- }
33
-
34
- try {
35
- const res = await client.jobs[":name"].kill.$post({
36
- param: { name: args.name },
37
- });
38
- if (res.status === 404) {
39
- const payload = { status: "not_found" };
40
- if (!process.stdout.isTTY || args.json) {
41
- console.log(JSON.stringify(payload));
42
- } else {
43
- console.log("kill: job not found");
44
- }
45
- process.exitCode = 1;
46
- return;
47
- }
48
-
49
- if (res.status === 409) {
50
- const payload = { status: "not_running" };
51
- if (!process.stdout.isTTY || args.json) {
52
- console.log(JSON.stringify(payload));
53
- } else {
54
- console.log("kill: no running job");
55
- }
56
- process.exitCode = 1;
57
- return;
58
- }
59
-
60
- if (!res.ok) {
61
- const payload = { status: "error", code: res.status };
62
- if (!process.stdout.isTTY || args.json) {
63
- console.log(JSON.stringify(payload));
64
- } else {
65
- console.log(`kill: error (${res.status})`);
66
- }
67
- process.exitCode = 1;
68
- return;
69
- }
70
-
71
- const data = await res.json();
72
- if (!process.stdout.isTTY || args.json) {
73
- console.log(JSON.stringify(data));
74
- return;
75
- }
76
-
77
- console.log(`kill: requested (${data.runId})`);
78
- } catch {
79
- const payload = { status: "unreachable" };
80
- if (!process.stdout.isTTY || args.json) {
81
- console.log(JSON.stringify(payload));
82
- } else {
83
- console.log("daemon: unreachable");
84
- }
85
- process.exitCode = 3;
86
- }
87
- },
88
- });
89
- }