@h-rig/notifications-plugin 0.0.6-alpha.156
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/README.md +1 -0
- package/dist/src/index.d.ts +2 -0
- package/dist/src/index.js +74 -0
- package/dist/src/notifications.d.ts +31 -0
- package/dist/src/notifications.js +74 -0
- package/package.json +27 -0
package/README.md
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# @h-rig/notifications-plugin
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
// packages/notifications-plugin/src/notifications.ts
|
|
3
|
+
async function loadNotificationConfig(path) {
|
|
4
|
+
try {
|
|
5
|
+
const parsed = await Bun.file(path).json();
|
|
6
|
+
return {
|
|
7
|
+
targets: (parsed.targets || []).filter((target) => !!target && !!target.id && !!target.url)
|
|
8
|
+
};
|
|
9
|
+
} catch {
|
|
10
|
+
return { targets: [] };
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
async function dispatchEventToTargets(event, targets, deps = {}) {
|
|
14
|
+
const fetchFn = deps.fetch ?? globalThis.fetch;
|
|
15
|
+
const timeoutMs = resolveNotifyTimeoutMs();
|
|
16
|
+
let sent = 0;
|
|
17
|
+
for (const target of targets) {
|
|
18
|
+
if (target.enabled === false) {
|
|
19
|
+
continue;
|
|
20
|
+
}
|
|
21
|
+
if (target.events && target.events.length > 0 && !target.events.includes(event.type)) {
|
|
22
|
+
continue;
|
|
23
|
+
}
|
|
24
|
+
const payload = buildTargetPayload(target, event);
|
|
25
|
+
const controller = new AbortController;
|
|
26
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
27
|
+
try {
|
|
28
|
+
const response = await fetchFn(target.url, {
|
|
29
|
+
method: "POST",
|
|
30
|
+
headers: {
|
|
31
|
+
"Content-Type": "application/json",
|
|
32
|
+
...target.headers || {}
|
|
33
|
+
},
|
|
34
|
+
body: JSON.stringify(payload),
|
|
35
|
+
signal: controller.signal
|
|
36
|
+
});
|
|
37
|
+
if (response.ok) {
|
|
38
|
+
sent += 1;
|
|
39
|
+
} else {
|
|
40
|
+
console.error(`[runtime] failed to dispatch event ${event.type} to ${target.id}: ${response.status} ${response.statusText}`);
|
|
41
|
+
}
|
|
42
|
+
} catch (error) {
|
|
43
|
+
console.error(`[runtime] failed to dispatch event ${event.type} to ${target.id}`, error);
|
|
44
|
+
} finally {
|
|
45
|
+
clearTimeout(timer);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return sent;
|
|
49
|
+
}
|
|
50
|
+
function buildTargetPayload(target, event) {
|
|
51
|
+
if (target.type === "slack-webhook") {
|
|
52
|
+
return {
|
|
53
|
+
text: `[Rig] ${event.type} ${event.runId ? `(run ${event.runId})` : ""}`.trim(),
|
|
54
|
+
event
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
return {
|
|
58
|
+
source: "project-rig",
|
|
59
|
+
target: target.id,
|
|
60
|
+
summary: `${event.type}${event.runId ? `:${event.runId}` : ""}`,
|
|
61
|
+
event
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
function resolveNotifyTimeoutMs() {
|
|
65
|
+
const raw = process.env.RIG_NOTIFY_TIMEOUT_MS;
|
|
66
|
+
const parsed = raw ? Number.parseInt(raw, 10) : NaN;
|
|
67
|
+
return Number.isFinite(parsed) && parsed > 0 ? parsed : 1e4;
|
|
68
|
+
}
|
|
69
|
+
export {
|
|
70
|
+
resolveNotifyTimeoutMs,
|
|
71
|
+
loadNotificationConfig,
|
|
72
|
+
dispatchEventToTargets,
|
|
73
|
+
buildTargetPayload
|
|
74
|
+
};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export type RigEvent = {
|
|
2
|
+
id?: string;
|
|
3
|
+
runId?: string;
|
|
4
|
+
timestamp?: string;
|
|
5
|
+
type: string;
|
|
6
|
+
payload?: Record<string, unknown>;
|
|
7
|
+
};
|
|
8
|
+
export type NotificationTarget = {
|
|
9
|
+
id: string;
|
|
10
|
+
type: "slack-webhook" | "linear-webhook" | "notion-webhook" | "generic-webhook";
|
|
11
|
+
url: string;
|
|
12
|
+
enabled?: boolean;
|
|
13
|
+
events?: string[];
|
|
14
|
+
headers?: Record<string, string>;
|
|
15
|
+
};
|
|
16
|
+
export type NotificationConfig = {
|
|
17
|
+
targets: NotificationTarget[];
|
|
18
|
+
};
|
|
19
|
+
type NotificationFetchResponse = {
|
|
20
|
+
ok: boolean;
|
|
21
|
+
status?: number;
|
|
22
|
+
statusText?: string;
|
|
23
|
+
};
|
|
24
|
+
type NotificationFetch = (input: string, init: RequestInit) => Promise<NotificationFetchResponse>;
|
|
25
|
+
export declare function loadNotificationConfig(path: string): Promise<NotificationConfig>;
|
|
26
|
+
export declare function dispatchEventToTargets(event: RigEvent, targets: NotificationTarget[], deps?: {
|
|
27
|
+
fetch?: NotificationFetch;
|
|
28
|
+
}): Promise<number>;
|
|
29
|
+
export declare function buildTargetPayload(target: NotificationTarget, event: RigEvent): Record<string, unknown>;
|
|
30
|
+
export declare function resolveNotifyTimeoutMs(): number;
|
|
31
|
+
export {};
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
// packages/notifications-plugin/src/notifications.ts
|
|
3
|
+
async function loadNotificationConfig(path) {
|
|
4
|
+
try {
|
|
5
|
+
const parsed = await Bun.file(path).json();
|
|
6
|
+
return {
|
|
7
|
+
targets: (parsed.targets || []).filter((target) => !!target && !!target.id && !!target.url)
|
|
8
|
+
};
|
|
9
|
+
} catch {
|
|
10
|
+
return { targets: [] };
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
async function dispatchEventToTargets(event, targets, deps = {}) {
|
|
14
|
+
const fetchFn = deps.fetch ?? globalThis.fetch;
|
|
15
|
+
const timeoutMs = resolveNotifyTimeoutMs();
|
|
16
|
+
let sent = 0;
|
|
17
|
+
for (const target of targets) {
|
|
18
|
+
if (target.enabled === false) {
|
|
19
|
+
continue;
|
|
20
|
+
}
|
|
21
|
+
if (target.events && target.events.length > 0 && !target.events.includes(event.type)) {
|
|
22
|
+
continue;
|
|
23
|
+
}
|
|
24
|
+
const payload = buildTargetPayload(target, event);
|
|
25
|
+
const controller = new AbortController;
|
|
26
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
27
|
+
try {
|
|
28
|
+
const response = await fetchFn(target.url, {
|
|
29
|
+
method: "POST",
|
|
30
|
+
headers: {
|
|
31
|
+
"Content-Type": "application/json",
|
|
32
|
+
...target.headers || {}
|
|
33
|
+
},
|
|
34
|
+
body: JSON.stringify(payload),
|
|
35
|
+
signal: controller.signal
|
|
36
|
+
});
|
|
37
|
+
if (response.ok) {
|
|
38
|
+
sent += 1;
|
|
39
|
+
} else {
|
|
40
|
+
console.error(`[runtime] failed to dispatch event ${event.type} to ${target.id}: ${response.status} ${response.statusText}`);
|
|
41
|
+
}
|
|
42
|
+
} catch (error) {
|
|
43
|
+
console.error(`[runtime] failed to dispatch event ${event.type} to ${target.id}`, error);
|
|
44
|
+
} finally {
|
|
45
|
+
clearTimeout(timer);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return sent;
|
|
49
|
+
}
|
|
50
|
+
function buildTargetPayload(target, event) {
|
|
51
|
+
if (target.type === "slack-webhook") {
|
|
52
|
+
return {
|
|
53
|
+
text: `[Rig] ${event.type} ${event.runId ? `(run ${event.runId})` : ""}`.trim(),
|
|
54
|
+
event
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
return {
|
|
58
|
+
source: "project-rig",
|
|
59
|
+
target: target.id,
|
|
60
|
+
summary: `${event.type}${event.runId ? `:${event.runId}` : ""}`,
|
|
61
|
+
event
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
function resolveNotifyTimeoutMs() {
|
|
65
|
+
const raw = process.env.RIG_NOTIFY_TIMEOUT_MS;
|
|
66
|
+
const parsed = raw ? Number.parseInt(raw, 10) : NaN;
|
|
67
|
+
return Number.isFinite(parsed) && parsed > 0 ? parsed : 1e4;
|
|
68
|
+
}
|
|
69
|
+
export {
|
|
70
|
+
resolveNotifyTimeoutMs,
|
|
71
|
+
loadNotificationConfig,
|
|
72
|
+
dispatchEventToTargets,
|
|
73
|
+
buildTargetPayload
|
|
74
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@h-rig/notifications-plugin",
|
|
3
|
+
"version": "0.0.6-alpha.156",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "First-party notification policy/channels capability plugin for Rig.",
|
|
6
|
+
"license": "UNLICENSED",
|
|
7
|
+
"files": [
|
|
8
|
+
"dist",
|
|
9
|
+
"README.md"
|
|
10
|
+
],
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"types": "./dist/src/index.d.ts",
|
|
14
|
+
"import": "./dist/src/index.js"
|
|
15
|
+
},
|
|
16
|
+
"./notifications": {
|
|
17
|
+
"types": "./dist/src/notifications.d.ts",
|
|
18
|
+
"import": "./dist/src/notifications.js"
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"engines": {
|
|
22
|
+
"bun": ">=1.3.11"
|
|
23
|
+
},
|
|
24
|
+
"main": "./dist/src/index.js",
|
|
25
|
+
"module": "./dist/src/index.js",
|
|
26
|
+
"types": "./dist/src/index.d.ts"
|
|
27
|
+
}
|