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/dist/board-server.d.ts +29 -0
- package/dist/board-server.d.ts.map +1 -0
- package/dist/board-server.js +153 -0
- package/dist/board-server.js.map +1 -0
- package/dist/board-ui.html +1060 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +65 -4
- package/dist/index.js.map +1 -1
- package/dist/status-field.d.ts +9 -0
- package/dist/status-field.d.ts.map +1 -0
- package/dist/status-field.js +23 -0
- package/dist/status-field.js.map +1 -0
- package/package.json +6 -3
- package/source/board-server.test.ts +164 -0
- package/source/board-server.ts +199 -0
- package/source/board-ui.html +1060 -0
- package/source/index.ts +75 -4
- package/source/status-field.ts +28 -0
- package/tsconfig.json +2 -1
- package/vitest.config.ts +14 -0
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { Hono } from "hono";
|
|
2
|
+
import type { YarloPluginContext } from "yarlo-types";
|
|
3
|
+
export type BoardTaskJson = {
|
|
4
|
+
id: string;
|
|
5
|
+
title: string;
|
|
6
|
+
status: unknown;
|
|
7
|
+
priority: unknown;
|
|
8
|
+
labels: unknown;
|
|
9
|
+
assignee: unknown;
|
|
10
|
+
due_date: unknown;
|
|
11
|
+
estimate: unknown;
|
|
12
|
+
updated_at: string;
|
|
13
|
+
};
|
|
14
|
+
export type BoardTaskDetailJson = {
|
|
15
|
+
id: string;
|
|
16
|
+
title: string;
|
|
17
|
+
content: string;
|
|
18
|
+
fields: Record<string, unknown>;
|
|
19
|
+
created_at: string;
|
|
20
|
+
updated_at: string;
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Builds the Hono app for the local board (HTML UI + JSON API).
|
|
24
|
+
*
|
|
25
|
+
* @param ctx - Plugin context with task operations and config
|
|
26
|
+
* @returns Configured Hono instance
|
|
27
|
+
*/
|
|
28
|
+
export declare function createBoardApp(ctx: YarloPluginContext): Hono;
|
|
29
|
+
//# sourceMappingURL=board-server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"board-server.d.ts","sourceRoot":"","sources":["../source/board-server.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,OAAO,KAAK,EAA0C,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAmB9F,MAAM,MAAM,aAAa,GAAG;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,OAAO,CAAC;IAChB,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,EAAE,OAAO,CAAC;IAChB,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,EAAE,OAAO,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAgDF;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,kBAAkB,GAAG,IAAI,CAqG5D"}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
import { Hono } from "hono";
|
|
5
|
+
import { z } from "zod";
|
|
6
|
+
import { getStatusColumnOptions } from "./status-field.js";
|
|
7
|
+
const patchBodySchema = z
|
|
8
|
+
.object({
|
|
9
|
+
status: z.string().min(1).optional(),
|
|
10
|
+
title: z.string().optional(),
|
|
11
|
+
content: z.string().optional(),
|
|
12
|
+
fields: z.record(z.unknown()).optional(),
|
|
13
|
+
})
|
|
14
|
+
.refine((d) => d.status !== undefined ||
|
|
15
|
+
d.title !== undefined ||
|
|
16
|
+
d.content !== undefined ||
|
|
17
|
+
d.fields !== undefined, { message: "At least one of status, title, content, or fields is required" });
|
|
18
|
+
/**
|
|
19
|
+
* Maps a task to a JSON-safe shape for the board UI (no file paths).
|
|
20
|
+
*
|
|
21
|
+
* @param task - Task from yarlo storage
|
|
22
|
+
* @returns Serializable board card payload
|
|
23
|
+
*/
|
|
24
|
+
function serializeBoardTask(task) {
|
|
25
|
+
const f = task.fields;
|
|
26
|
+
return {
|
|
27
|
+
id: task.id,
|
|
28
|
+
title: task.title,
|
|
29
|
+
status: f.status ?? null,
|
|
30
|
+
priority: f.priority ?? null,
|
|
31
|
+
labels: f.labels ?? null,
|
|
32
|
+
assignee: f.assignee ?? null,
|
|
33
|
+
due_date: f.due_date ?? null,
|
|
34
|
+
estimate: f.estimate ?? null,
|
|
35
|
+
updated_at: task.updated_at,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Full task payload for detail view and PATCH responses (no file_path).
|
|
40
|
+
*
|
|
41
|
+
* @param task - Task from yarlo storage
|
|
42
|
+
* @returns Serializable task detail
|
|
43
|
+
*/
|
|
44
|
+
function serializeBoardTaskDetail(task) {
|
|
45
|
+
return {
|
|
46
|
+
id: task.id,
|
|
47
|
+
title: task.title,
|
|
48
|
+
content: task.content,
|
|
49
|
+
fields: { ...task.fields },
|
|
50
|
+
created_at: task.created_at,
|
|
51
|
+
updated_at: task.updated_at,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
function isNotFoundMessage(msg) {
|
|
55
|
+
return (msg.includes("not found") ||
|
|
56
|
+
msg.includes("Ambiguous ID") ||
|
|
57
|
+
msg.includes("Ambiguous"));
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Builds the Hono app for the local board (HTML UI + JSON API).
|
|
61
|
+
*
|
|
62
|
+
* @param ctx - Plugin context with task operations and config
|
|
63
|
+
* @returns Configured Hono instance
|
|
64
|
+
*/
|
|
65
|
+
export function createBoardApp(ctx) {
|
|
66
|
+
const app = new Hono();
|
|
67
|
+
const moduleDir = path.dirname(fileURLToPath(import.meta.url));
|
|
68
|
+
app.get("/", async (c) => {
|
|
69
|
+
const htmlPath = path.join(moduleDir, "board-ui.html");
|
|
70
|
+
const html = await fs.readFile(htmlPath, "utf-8");
|
|
71
|
+
return c.html(html);
|
|
72
|
+
});
|
|
73
|
+
app.get("/api/board", async (c) => {
|
|
74
|
+
const columns = getStatusColumnOptions(ctx.config);
|
|
75
|
+
const tasks = await ctx.tasks.list();
|
|
76
|
+
const fieldDefinitions = ctx.config.fields;
|
|
77
|
+
return c.json({
|
|
78
|
+
columns,
|
|
79
|
+
tasks: tasks.map(serializeBoardTask),
|
|
80
|
+
fieldDefinitions,
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
app.get("/api/tasks/:id", async (c) => {
|
|
84
|
+
const id = c.req.param("id");
|
|
85
|
+
try {
|
|
86
|
+
const task = await ctx.tasks.get(id);
|
|
87
|
+
return c.json({ task: serializeBoardTaskDetail(task) });
|
|
88
|
+
}
|
|
89
|
+
catch (e) {
|
|
90
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
91
|
+
if (isNotFoundMessage(msg)) {
|
|
92
|
+
return c.json({ error: msg }, 404);
|
|
93
|
+
}
|
|
94
|
+
return c.json({ error: msg }, 500);
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
app.patch("/api/tasks/:id", async (c) => {
|
|
98
|
+
const id = c.req.param("id");
|
|
99
|
+
let body;
|
|
100
|
+
try {
|
|
101
|
+
body = await c.req.json();
|
|
102
|
+
}
|
|
103
|
+
catch {
|
|
104
|
+
return c.json({ error: "Invalid JSON body" }, 400);
|
|
105
|
+
}
|
|
106
|
+
const parsed = patchBodySchema.safeParse(body);
|
|
107
|
+
if (!parsed.success) {
|
|
108
|
+
const flat = parsed.error.flatten();
|
|
109
|
+
const refineMsg = parsed.error.errors.find((e) => e.code === "custom");
|
|
110
|
+
return c.json({
|
|
111
|
+
error: refineMsg?.message ?? "Validation failed",
|
|
112
|
+
details: flat,
|
|
113
|
+
}, 400);
|
|
114
|
+
}
|
|
115
|
+
const columns = getStatusColumnOptions(ctx.config);
|
|
116
|
+
const fieldPatch = {};
|
|
117
|
+
if (parsed.data.fields) {
|
|
118
|
+
Object.assign(fieldPatch, parsed.data.fields);
|
|
119
|
+
}
|
|
120
|
+
if (parsed.data.status !== undefined) {
|
|
121
|
+
fieldPatch.status = parsed.data.status;
|
|
122
|
+
}
|
|
123
|
+
const statusValue = typeof fieldPatch.status === "string" ? fieldPatch.status : undefined;
|
|
124
|
+
if (statusValue !== undefined && !columns.includes(statusValue)) {
|
|
125
|
+
return c.json({
|
|
126
|
+
error: `Invalid status: must be one of: ${columns.join(", ")}`,
|
|
127
|
+
}, 400);
|
|
128
|
+
}
|
|
129
|
+
const updateInput = {};
|
|
130
|
+
if (parsed.data.title !== undefined) {
|
|
131
|
+
updateInput.title = parsed.data.title;
|
|
132
|
+
}
|
|
133
|
+
if (parsed.data.content !== undefined) {
|
|
134
|
+
updateInput.content = parsed.data.content;
|
|
135
|
+
}
|
|
136
|
+
if (Object.keys(fieldPatch).length > 0) {
|
|
137
|
+
updateInput.fields = fieldPatch;
|
|
138
|
+
}
|
|
139
|
+
try {
|
|
140
|
+
const task = await ctx.tasks.update(id, updateInput);
|
|
141
|
+
return c.json({ task: serializeBoardTaskDetail(task) });
|
|
142
|
+
}
|
|
143
|
+
catch (e) {
|
|
144
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
145
|
+
if (isNotFoundMessage(msg)) {
|
|
146
|
+
return c.json({ error: msg }, 404);
|
|
147
|
+
}
|
|
148
|
+
return c.json({ error: msg }, 500);
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
return app;
|
|
152
|
+
}
|
|
153
|
+
//# sourceMappingURL=board-server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"board-server.js","sourceRoot":"","sources":["../source/board-server.ts"],"names":[],"mappings":"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"}
|