khala-cli 0.4.1 → 0.4.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.
- package/dist/{chunk-S72K3GSP.mjs → chunk-6OADQWV7.mjs} +31 -20
- package/dist/{chunk-YMDAY234.mjs → chunk-7CVU5OZ7.mjs} +1 -1
- package/dist/{chunk-PSN7P4AV.mjs → chunk-AK74S7EN.mjs} +4 -4
- package/dist/chunk-AUJEUKVM.mjs +121 -0
- package/dist/chunk-DC3OX6F4.mjs +52 -0
- package/dist/chunk-ENPBK5W2.mjs +187 -0
- package/dist/chunk-FA6Z65DW.mjs +19 -0
- package/dist/{chunk-KEGR6VEQ.mjs → chunk-FUU775QM.mjs} +81 -10
- package/dist/chunk-GE3RXO2X.mjs +26 -0
- package/dist/chunk-LHAMBQK7.mjs +144 -0
- package/dist/{chunk-EVLXC2WS.mjs → chunk-LN3G2LJV.mjs} +13 -10
- package/dist/{chunk-35KKPOKI.mjs → chunk-LQ6KNUNN.mjs} +87 -53
- package/dist/{chunk-CSIFRJFF.mjs → chunk-MU4FUENP.mjs} +3 -2
- package/dist/{chunk-L2HRDTA5.mjs → chunk-MZS7XFMC.mjs} +3 -3
- package/dist/{chunk-U5ZMOPUK.mjs → chunk-N5VYKQMR.mjs} +5 -46
- package/dist/{chunk-3SWCRLWX.mjs → chunk-OS2JLDL7.mjs} +172 -227
- package/dist/chunk-P5CP32X2.mjs +170 -0
- package/dist/{chunk-RX5HGJQT.mjs → chunk-PJ3E3IVH.mjs} +184 -126
- package/dist/chunk-SN3STAO2.mjs +190 -0
- package/dist/{chunk-B5BFL7OD.mjs → chunk-XEYKJMZL.mjs} +1 -1
- package/dist/{chunk-SR5BG7FL.mjs → chunk-ZKDDKUUA.mjs} +1 -1
- package/dist/{chunk-HAD5ZILW.mjs → chunk-ZRFXZK72.mjs} +1 -1
- package/dist/khala.mjs +12 -10
- package/dist/web/assets/apple-touch-icon-Du9V6qit.png +0 -0
- package/dist/web/assets/favicon-16x16-D5waNSZD.png +0 -0
- package/dist/web/assets/favicon-32x32-B9Ubw1Dx.png +0 -0
- package/dist/web/assets/favicon-zCD0pKtT.ico +0 -0
- package/dist/web/assets/local-Bk8hMIT-.js +9 -0
- package/dist/web/assets/{local-DHYvcQG0.css → local-vdvavyq0.css} +1 -1
- package/dist/web/index.html +7 -2
- package/package.json +1 -1
- package/dist/chunk-AVJKIJ34.mjs +0 -91
- package/dist/chunk-N6LMHR7P.mjs +0 -455
- package/dist/web/assets/local-DGdQ2afg.js +0 -9
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import { createRequire as __khalaCreateRequire } from 'node:module'; const require = __khalaCreateRequire(import.meta.url);
|
|
2
|
+
import {
|
|
3
|
+
decodeWith,
|
|
4
|
+
displayText,
|
|
5
|
+
fail,
|
|
6
|
+
label,
|
|
7
|
+
literal,
|
|
8
|
+
safeInteger,
|
|
9
|
+
utcTimestamp,
|
|
10
|
+
utf8Length,
|
|
11
|
+
version
|
|
12
|
+
} from "./chunk-SN3STAO2.mjs";
|
|
13
|
+
|
|
14
|
+
// ../contracts/src/m1/channel-event.ts
|
|
15
|
+
var CHANNEL_EVENT_TYPE = "com.khala.event.v1";
|
|
16
|
+
var CHANNEL_EVENT_STATUSES = ["info", "pending", "success", "failure", "attention"];
|
|
17
|
+
var MAX_CHANNEL_EVENT_BYTES = 4096;
|
|
18
|
+
function record(input, path) {
|
|
19
|
+
if (typeof input !== "object" || input === null || Array.isArray(input)) fail(path, "not_object");
|
|
20
|
+
const prototype = Object.getPrototypeOf(input);
|
|
21
|
+
if (prototype !== Object.prototype && prototype !== null) fail(path, "not_object");
|
|
22
|
+
const value = input;
|
|
23
|
+
return {
|
|
24
|
+
has: (key) => Object.hasOwn(value, key) && value[key] !== void 0,
|
|
25
|
+
field: (key) => Object.hasOwn(value, key) ? value[key] : fail(path ? `${path}.${key}` : key, "missing_field"),
|
|
26
|
+
at: (key) => path ? `${path}.${key}` : key
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
function nonempty(value, path) {
|
|
30
|
+
if (!value.length) fail(path, "empty");
|
|
31
|
+
return value;
|
|
32
|
+
}
|
|
33
|
+
function display(input, path, maxBytes, maxPoints) {
|
|
34
|
+
const value = nonempty(displayText(input, path, maxBytes), path);
|
|
35
|
+
if ([...value].length > maxPoints) fail(path, "too_long");
|
|
36
|
+
return value;
|
|
37
|
+
}
|
|
38
|
+
function matching(value, path, pattern) {
|
|
39
|
+
if (!pattern.test(value)) fail(path, "invalid_value");
|
|
40
|
+
return value;
|
|
41
|
+
}
|
|
42
|
+
function safely(read) {
|
|
43
|
+
try {
|
|
44
|
+
return read();
|
|
45
|
+
} catch {
|
|
46
|
+
return { ok: false, error: { path: "", code: "invalid_value" } };
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
function decodeChannelEvent(raw) {
|
|
50
|
+
return safely(() => decodeWith(() => {
|
|
51
|
+
let serialized;
|
|
52
|
+
try {
|
|
53
|
+
serialized = JSON.stringify(raw);
|
|
54
|
+
} catch {
|
|
55
|
+
fail("", "invalid_value");
|
|
56
|
+
}
|
|
57
|
+
if (serialized !== void 0 && utf8Length(serialized) > MAX_CHANNEL_EVENT_BYTES) fail("", "too_long");
|
|
58
|
+
const r = record(raw, "");
|
|
59
|
+
const v = version(r.field("v"), "v");
|
|
60
|
+
const kind = matching(nonempty(label(r.field("kind"), "kind", 128), "kind"), "kind", /^[a-z0-9_-]+(\.[a-z0-9_-]+)*$/);
|
|
61
|
+
const summary = display(r.field("summary"), "summary", 800, 200);
|
|
62
|
+
if (!summary.trim()) fail("summary", "empty");
|
|
63
|
+
const body = label(r.field("body"), "body", 1024);
|
|
64
|
+
return {
|
|
65
|
+
v,
|
|
66
|
+
kind,
|
|
67
|
+
summary,
|
|
68
|
+
body,
|
|
69
|
+
...r.has("status") ? { status: literal(r.field("status"), "status", CHANNEL_EVENT_STATUSES) } : {},
|
|
70
|
+
...r.has("subject") ? { subject: readSubject(r.field("subject")) } : {},
|
|
71
|
+
...r.has("actor") ? { actor: display(r.field("actor"), "actor", 256, 64) } : {},
|
|
72
|
+
...r.has("url") ? { url: readUrl(r.field("url")) } : {},
|
|
73
|
+
...r.has("occurred_at") ? { occurred_at: utcTimestamp(r.field("occurred_at"), "occurred_at") } : {},
|
|
74
|
+
...r.has("source") ? { source: readSource(r.field("source")) } : {},
|
|
75
|
+
...r.has("key") ? { key: nonempty(label(r.field("key"), "key", 200), "key") } : {}
|
|
76
|
+
};
|
|
77
|
+
}));
|
|
78
|
+
}
|
|
79
|
+
function readSubject(input) {
|
|
80
|
+
const r = record(input, "subject");
|
|
81
|
+
let pr;
|
|
82
|
+
if (r.has("pr")) {
|
|
83
|
+
pr = safeInteger(r.field("pr"), r.at("pr"));
|
|
84
|
+
if (pr === 0) fail(r.at("pr"), "invalid_value");
|
|
85
|
+
}
|
|
86
|
+
let branch;
|
|
87
|
+
if (r.has("branch")) {
|
|
88
|
+
branch = nonempty(label(r.field("branch"), r.at("branch"), 255), r.at("branch"));
|
|
89
|
+
if (branch.startsWith("refs/")) fail(r.at("branch"), "invalid_value");
|
|
90
|
+
}
|
|
91
|
+
return {
|
|
92
|
+
...r.has("ticket") ? { ticket: display(r.field("ticket"), r.at("ticket"), 256, 64) } : {},
|
|
93
|
+
...pr !== void 0 ? { pr } : {},
|
|
94
|
+
...branch !== void 0 ? { branch } : {},
|
|
95
|
+
...r.has("repo") ? { repo: matching(label(r.field("repo"), r.at("repo"), 140), r.at("repo"), /^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/) } : {},
|
|
96
|
+
...r.has("sha") ? { sha: matching(label(r.field("sha"), r.at("sha"), 64), r.at("sha"), /^[0-9a-f]{7,64}$/) } : {}
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
function readSource(input) {
|
|
100
|
+
const r = record(input, "source");
|
|
101
|
+
return {
|
|
102
|
+
system: nonempty(label(r.field("system"), r.at("system"), 32), r.at("system")),
|
|
103
|
+
...r.has("topic") ? { topic: label(r.field("topic"), r.at("topic"), 256) } : {},
|
|
104
|
+
...r.has("event_id") ? { event_id: label(r.field("event_id"), r.at("event_id"), 64) } : {}
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
function readUrl(input) {
|
|
108
|
+
if (typeof input !== "string") fail("url", "wrong_type");
|
|
109
|
+
if (utf8Length(input) > 2048) fail("url", "too_long");
|
|
110
|
+
try {
|
|
111
|
+
if (new URL(input).protocol !== "https:") fail("url", "invalid_value");
|
|
112
|
+
} catch {
|
|
113
|
+
fail("url", "invalid_value");
|
|
114
|
+
}
|
|
115
|
+
return input;
|
|
116
|
+
}
|
|
117
|
+
function formatChannelEventLine(content) {
|
|
118
|
+
const { summary, subject } = content;
|
|
119
|
+
const head = subject?.ticket ? `${subject.ticket} ${summary}` : summary;
|
|
120
|
+
const tail = subject?.branch ?? (subject?.pr !== void 0 ? `PR #${subject.pr}` : void 0);
|
|
121
|
+
return tail ? `${head} \xB7 ${tail}` : head;
|
|
122
|
+
}
|
|
123
|
+
function encodeChannelEvent(input) {
|
|
124
|
+
return safely(() => {
|
|
125
|
+
const checked = decodeWith(() => {
|
|
126
|
+
record(input, "");
|
|
127
|
+
return { ...input, v: 1, body: "" };
|
|
128
|
+
});
|
|
129
|
+
if (!checked.ok) return checked;
|
|
130
|
+
const decoded = decodeChannelEvent(checked.value);
|
|
131
|
+
if (!decoded.ok) return decoded;
|
|
132
|
+
return decodeChannelEvent({ ...decoded.value, body: formatChannelEventLine(decoded.value) });
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
function memberRenameContent(content, previous) {
|
|
136
|
+
const oldName = previous?.["displayname"];
|
|
137
|
+
const newName = content["displayname"];
|
|
138
|
+
if (previous?.["membership"] !== "join" || content["membership"] !== "join" || typeof oldName !== "string" || !oldName.trim() || typeof newName !== "string" || !newName.trim() || oldName === newName) return null;
|
|
139
|
+
const encoded = encodeChannelEvent({ kind: "member", summary: `${oldName} is now ${newName}`, status: "info", source: { system: "khala" } });
|
|
140
|
+
return encoded.ok ? encoded.value : null;
|
|
141
|
+
}
|
|
142
|
+
function statusFor(content) {
|
|
143
|
+
if (content.status !== void 0) return content.status;
|
|
144
|
+
switch (content.kind) {
|
|
145
|
+
case "ci.passed":
|
|
146
|
+
case "pr.merged":
|
|
147
|
+
case "agent.unblocked":
|
|
148
|
+
return "success";
|
|
149
|
+
case "ci.failed":
|
|
150
|
+
return "failure";
|
|
151
|
+
case "pr.ready_for_review":
|
|
152
|
+
case "pr.parked_ready":
|
|
153
|
+
return "pending";
|
|
154
|
+
case "agent.paused":
|
|
155
|
+
case "agent.blocked":
|
|
156
|
+
case "agent.pause.request":
|
|
157
|
+
return "attention";
|
|
158
|
+
default:
|
|
159
|
+
return content.kind.startsWith("agent.attention.") && !content.kind.endsWith(".resolved") ? "attention" : "info";
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
export {
|
|
164
|
+
CHANNEL_EVENT_TYPE,
|
|
165
|
+
decodeChannelEvent,
|
|
166
|
+
formatChannelEventLine,
|
|
167
|
+
encodeChannelEvent,
|
|
168
|
+
memberRenameContent,
|
|
169
|
+
statusFor
|
|
170
|
+
};
|