-
Notifications
You must be signed in to change notification settings - Fork 0
/
jira-work-logger.ts
executable file
·137 lines (123 loc) · 4.58 KB
/
jira-work-logger.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
#!/usr/bin/env -S deno run -A
import { cliteRun, help, hidden } from "@jersou/clite";
import { DesktopWebApp } from "@jersou/desktop-web-app";
import assetsFromJson from "./assets_bundle.json" with { type: "json" };
import { getHamsterReport } from "./backend/hamster.ts";
import type { ConfigData, ToLogElement } from "./frontend/src/types.ts";
import { toText } from "@std/streams";
import { issueSummary, logElement, myLastIssues } from "./backend/jira.ts";
import $ from "@david/dax";
class JiraWorkLogger extends DesktopWebApp {
@help("Keep the server alive after the last client disconnects")
notExitIfNoClient = false;
@hidden()
sockets = new Set<WebSocket>();
@hidden()
issuesCache: { [key: string]: string } = {};
override routes = [
{
route: new URLPattern({ pathname: "/api/hamsterExport" }),
exec: async (_match: URLPatternResult, request: Request) => {
const params = new URL(request.url).searchParams;
const ignore = params.get("ignore");
const hamsterDaysToImport = Number(
params.get("hamsterDaysToImport") || 5,
);
const begin = new Date(
Date.now() - 1000 * 60 * 60 * 24 * hamsterDaysToImport,
).toISOString().substring(0, 10);
const end = new Date().toISOString().substring(0, 10);
console.log(
`%c[hamsterExport] hamsterDaysToImport=${hamsterDaysToImport} begin=${begin} end=${end}`,
"color:indigo",
);
const body = await getHamsterReport(begin, end, ignore);
return new Response(JSON.stringify(body));
},
},
{
route: new URLPattern({ pathname: "/api/stop" }),
exec: () => {
console.log("Stop");
setTimeout(() => Deno.exit(0), 100);
return new Response("stop ok");
},
},
{
route: new URLPattern({ pathname: "/api/myLastIssues" }),
exec: async (_match: URLPatternResult, request: Request) => {
const config: ConfigData = JSON.parse(await toText(request.body!));
const body = await myLastIssues(config);
return new Response(JSON.stringify(body));
},
},
{
route: new URLPattern({ pathname: "/issue/:issueKey" }),
exec: async (match: URLPatternResult, request: Request) => {
const issueKey = match.pathname.groups.issueKey;
if (issueKey) {
let issue;
if (this.issuesCache[issueKey]) {
console.log(`%c[jiraIssuesCache] ${issueKey}`, "color:green");
issue = this.issuesCache[issueKey];
} else {
const config: ConfigData = JSON.parse(await toText(request.body!));
issue = await issueSummary(config, issueKey);
this.issuesCache[issueKey] = issue;
}
return new Response(JSON.stringify(issue));
}
return new Response(null, { status: 404 });
},
},
{
route: new URLPattern({ pathname: "/createWorkLogs" }),
exec: async (_match: URLPatternResult, request: Request) => {
const { config, toLog }: { config: ConfigData; toLog: ToLogElement[] } =
JSON.parse(await toText(request.body!));
// sequence POSTs → otherwise Jira bugs on remaining and total logged (not updated)
for (const log of toLog) {
await logElement(config, log);
await $.sleep(800);
}
return new Response(JSON.stringify({ "status": "OK" }));
},
},
{ // WebSocket
route: new URLPattern({ pathname: "/api/events-ws" }),
exec: (_match: URLPatternResult, request: Request) => {
if (request.headers.get("upgrade") != "websocket") {
return new Response(null, { status: 501 });
}
const { socket, response } = Deno.upgradeWebSocket(request);
socket.addEventListener("open", () => {
this.sockets.add(socket);
console.log(`a client connected! ${this.sockets.size} clients`);
});
socket.addEventListener("close", () => {
this.sockets.delete(socket);
console.log(`a client disconnected! ${this.sockets.size} clients`);
if (!this.notExitIfNoClient && this.sockets.size === 0) {
console.log(`→ ExitIfNoClient → shutdown the server !`);
Deno.exit(0);
}
});
return response;
},
},
];
constructor() {
super({
assetsFromJson,
frontendPath: "frontend/dist",
openInBrowser: "google-chrome",
openInBrowserAppMode: true,
port: 8000,
});
}
override onListen = async () => {
};
}
if (import.meta.main) {
cliteRun(JiraWorkLogger, { meta: import.meta });
}