yarlo-plugin-board 0.1.2 → 0.2.1

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/source/index.ts CHANGED
@@ -1,16 +1,87 @@
1
+ import { spawn } from "node:child_process";
2
+ import { serve } from "@hono/node-server";
1
3
  import type { YarloPlugin } from "yarlo-types";
4
+ import { createBoardApp } from "./board-server.js";
5
+
6
+ const DEFAULT_PORT = 3847;
7
+
8
+ /**
9
+ * Parses `--port <n>` from plugin CLI args.
10
+ *
11
+ * @param args - Arguments after `yarlo board`
12
+ * @returns Valid TCP port
13
+ */
14
+ function parsePort(args: string[]): number {
15
+ const idx = args.indexOf("--port");
16
+ if (idx >= 0 && args[idx + 1]) {
17
+ const n = Number.parseInt(args[idx + 1]!, 10);
18
+ if (!Number.isNaN(n) && n > 0 && n < 65536) {
19
+ return n;
20
+ }
21
+ }
22
+
23
+ return DEFAULT_PORT;
24
+ }
25
+
26
+ /**
27
+ * Opens the given URL in the system default browser.
28
+ *
29
+ * @param url - HTTP URL to open
30
+ */
31
+ function openBrowser(url: string): void {
32
+ const platform = process.platform;
33
+ if (platform === "darwin") {
34
+ spawn("open", [url], { detached: true, stdio: "ignore" }).unref();
35
+ return;
36
+ }
37
+ if (platform === "win32") {
38
+ spawn("cmd", ["/c", "start", "", url], {
39
+ detached: true,
40
+ stdio: "ignore",
41
+ windowsHide: true,
42
+ }).unref();
43
+ return;
44
+ }
45
+ spawn("xdg-open", [url], { detached: true, stdio: "ignore" }).unref();
46
+ }
2
47
 
3
48
  const plugin: YarloPlugin = {
4
49
  name: "board",
5
- version: "0.1.2",
50
+ version: "0.2.1",
6
51
  description: "Kanban board view for yarlo tasks",
7
52
  commands: [
8
53
  {
9
54
  name: "board",
10
55
  description: "Open the task board in your browser",
11
- async run(_args, _ctx) {
12
- console.log("Board plugin - coming soon!");
13
- console.log("This will open a local web UI for managing tasks.");
56
+ async run(args, ctx) {
57
+ const port = parsePort(args);
58
+ const app = createBoardApp(ctx);
59
+ const server = serve(
60
+ {
61
+ fetch: app.fetch,
62
+ port,
63
+ hostname: "127.0.0.1",
64
+ },
65
+ (info) => {
66
+ const url = `http://127.0.0.1:${info.port}/`;
67
+ console.log(`Board running at ${url}`);
68
+ console.log("Press Ctrl+C to stop.");
69
+ openBrowser(url);
70
+ },
71
+ );
72
+
73
+ const shutdown = (): void => {
74
+ server.close(() => {
75
+ process.exit(0);
76
+ });
77
+ };
78
+
79
+ process.once("SIGINT", shutdown);
80
+ process.once("SIGTERM", shutdown);
81
+
82
+ await new Promise<void>(() => {
83
+ /* keep process alive until signals */
84
+ });
14
85
  },
15
86
  },
16
87
  ],
@@ -0,0 +1,28 @@
1
+ import type { YarloConfig } from "yarlo-types";
2
+
3
+ const DEFAULT_STATUS_OPTIONS = [
4
+ "backlog",
5
+ "todo",
6
+ "in_progress",
7
+ "done",
8
+ "cancelled",
9
+ ] as const;
10
+
11
+ /**
12
+ * Returns ordered status column keys for the Kanban board from `config.fields`.
13
+ *
14
+ * @param config - Loaded yarlo project configuration
15
+ * @returns Option list for the `status` single_select field, or sensible defaults
16
+ */
17
+ export function getStatusColumnOptions(config: YarloConfig): string[] {
18
+ const def = config.fields.find((f) => f.name === "status");
19
+ if (
20
+ def?.type === "single_select" &&
21
+ Array.isArray(def.options) &&
22
+ def.options.length > 0
23
+ ) {
24
+ return [...def.options];
25
+ }
26
+
27
+ return [...DEFAULT_STATUS_OPTIONS];
28
+ }
package/tsconfig.json CHANGED
@@ -4,5 +4,6 @@
4
4
  "outDir": "dist",
5
5
  "rootDir": "source"
6
6
  },
7
- "include": ["source"]
7
+ "include": ["source"],
8
+ "exclude": ["source/**/*.test.ts"]
8
9
  }
@@ -0,0 +1,14 @@
1
+ import path from "node:path";
2
+ import { fileURLToPath } from "node:url";
3
+ import { defineProject } from "vitest/config";
4
+
5
+ const root = path.dirname(fileURLToPath(import.meta.url));
6
+
7
+ export default defineProject({
8
+ root,
9
+ test: {
10
+ name: "yarlo-plugin-board",
11
+ environment: "node",
12
+ include: ["source/**/*.test.ts"],
13
+ },
14
+ });