iris-relay 1.0.0 → 1.1.0
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 +178 -32
- package/dist/builder.d.ts +50 -0
- package/dist/builder.d.ts.map +1 -0
- package/dist/builder.js +94 -0
- package/dist/builder.js.map +1 -0
- package/dist/channels.d.ts +28 -0
- package/dist/channels.d.ts.map +1 -0
- package/dist/channels.js +56 -0
- package/dist/channels.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +84 -0
- package/dist/cli.js.map +1 -0
- package/dist/file.d.ts +12 -0
- package/dist/file.d.ts.map +1 -0
- package/dist/file.js +60 -0
- package/dist/file.js.map +1 -0
- package/dist/format.d.ts +30 -0
- package/dist/format.d.ts.map +1 -0
- package/dist/format.js +86 -0
- package/dist/format.js.map +1 -0
- package/dist/index.d.ts +8 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +14 -1
- package/dist/index.js.map +1 -1
- package/dist/middleware.d.ts +25 -0
- package/dist/middleware.d.ts.map +1 -0
- package/dist/middleware.js +74 -0
- package/dist/middleware.js.map +1 -0
- package/dist/relay.d.ts +13 -18
- package/dist/relay.d.ts.map +1 -1
- package/dist/relay.js +50 -35
- package/dist/relay.js.map +1 -1
- package/dist/types.d.ts +54 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/watch.d.ts +26 -0
- package/dist/watch.d.ts.map +1 -0
- package/dist/watch.js +70 -0
- package/dist/watch.js.map +1 -0
- package/package.json +14 -6
package/dist/file.js
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { resolveConfig, isDryRun } from "./relay.js";
|
|
2
|
+
import { createReadStream } from "node:fs";
|
|
3
|
+
import { basename } from "node:path";
|
|
4
|
+
import { stat } from "node:fs/promises";
|
|
5
|
+
const TG_API = "https://api.telegram.org";
|
|
6
|
+
/**
|
|
7
|
+
* Send a file to your Telegram chat via sendDocument API.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```ts
|
|
11
|
+
* import { relayFile } from "iris-relay";
|
|
12
|
+
* await relayFile("./logs/error.log", "Latest error log");
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
15
|
+
export async function relayFile(filePath, caption, config) {
|
|
16
|
+
const { botToken, chatId, silent, parseMode } = resolveConfig(config);
|
|
17
|
+
if (isDryRun()) {
|
|
18
|
+
console.log(`[iris-relay DRY RUN] 📎 File: ${filePath}${caption ? ` — ${caption}` : ""}`);
|
|
19
|
+
return { success: true, messageId: 0 };
|
|
20
|
+
}
|
|
21
|
+
// Check file exists
|
|
22
|
+
try {
|
|
23
|
+
await stat(filePath);
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
return { success: false, error: `File not found: ${filePath}` };
|
|
27
|
+
}
|
|
28
|
+
const form = new FormData();
|
|
29
|
+
form.append("chat_id", chatId);
|
|
30
|
+
// Read file as buffer
|
|
31
|
+
const fileStream = createReadStream(filePath);
|
|
32
|
+
const chunks = [];
|
|
33
|
+
for await (const chunk of fileStream) {
|
|
34
|
+
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
35
|
+
}
|
|
36
|
+
const fileBuffer = Buffer.concat(chunks);
|
|
37
|
+
const blob = new Blob([fileBuffer]);
|
|
38
|
+
form.append("document", blob, basename(filePath));
|
|
39
|
+
if (caption)
|
|
40
|
+
form.append("caption", caption);
|
|
41
|
+
if (parseMode)
|
|
42
|
+
form.append("parse_mode", parseMode);
|
|
43
|
+
if (silent)
|
|
44
|
+
form.append("disable_notification", "true");
|
|
45
|
+
try {
|
|
46
|
+
const res = await fetch(`${TG_API}/bot${botToken}/sendDocument`, {
|
|
47
|
+
method: "POST",
|
|
48
|
+
body: form,
|
|
49
|
+
});
|
|
50
|
+
const data = (await res.json());
|
|
51
|
+
if (!data.ok) {
|
|
52
|
+
return { success: false, error: data.description ?? `Telegram API error (${data.error_code})` };
|
|
53
|
+
}
|
|
54
|
+
return { success: true, messageId: data.result?.message_id };
|
|
55
|
+
}
|
|
56
|
+
catch (err) {
|
|
57
|
+
return { success: false, error: err instanceof Error ? err.message : String(err) };
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=file.js.map
|
package/dist/file.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file.js","sourceRoot":"","sources":["../src/file.ts"],"names":[],"mappings":"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"}
|
package/dist/format.d.ts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { RelayConfig, RelayResult, DeployMeta } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Relay a formatted error with stack trace to Telegram.
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* ```ts
|
|
7
|
+
* catch (err) { await relayError(err); }
|
|
8
|
+
* ```
|
|
9
|
+
*/
|
|
10
|
+
export declare function relayError(err: unknown, config?: RelayConfig): Promise<RelayResult>;
|
|
11
|
+
/**
|
|
12
|
+
* Relay a pretty-printed JSON object to Telegram.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```ts
|
|
16
|
+
* await relayJSON({ users: 42, status: "healthy" });
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
export declare function relayJSON(obj: unknown, label?: string, config?: RelayConfig): Promise<RelayResult>;
|
|
20
|
+
/**
|
|
21
|
+
* Send a deploy notification with optional git info.
|
|
22
|
+
* Auto-reads git branch/commit if not provided.
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```ts
|
|
26
|
+
* await relayDeploy({ app: "my-api", env: "production" });
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
export declare function relayDeploy(meta?: DeployMeta, config?: RelayConfig): Promise<RelayResult>;
|
|
30
|
+
//# sourceMappingURL=format.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../src/format.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAGvE;;;;;;;GAOG;AACH,wBAAsB,UAAU,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC,CAUzF;AAED;;;;;;;GAOG;AACH,wBAAsB,SAAS,CAAC,GAAG,EAAE,OAAO,EAAE,KAAK,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC,CAKxG;AAWD;;;;;;;;GAQG;AACH,wBAAsB,WAAW,CAAC,IAAI,CAAC,EAAE,UAAU,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC,CAsB/F"}
|
package/dist/format.js
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { relay } from "./relay.js";
|
|
2
|
+
import { execSync } from "node:child_process";
|
|
3
|
+
/**
|
|
4
|
+
* Relay a formatted error with stack trace to Telegram.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```ts
|
|
8
|
+
* catch (err) { await relayError(err); }
|
|
9
|
+
* ```
|
|
10
|
+
*/
|
|
11
|
+
export async function relayError(err, config) {
|
|
12
|
+
let message;
|
|
13
|
+
if (err instanceof Error) {
|
|
14
|
+
message = `🚨 <b>Error:</b> ${escapeHtml(err.message)}\n\n<pre>${escapeHtml(err.stack ?? "No stack trace")}</pre>`;
|
|
15
|
+
}
|
|
16
|
+
else {
|
|
17
|
+
message = `🚨 <b>Error:</b>\n<pre>${escapeHtml(String(err))}</pre>`;
|
|
18
|
+
}
|
|
19
|
+
return relay(message, { parseMode: "HTML", ...config });
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Relay a pretty-printed JSON object to Telegram.
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```ts
|
|
26
|
+
* await relayJSON({ users: 42, status: "healthy" });
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
export async function relayJSON(obj, label, config) {
|
|
30
|
+
const json = JSON.stringify(obj, null, 2);
|
|
31
|
+
const header = label ? `📋 <b>${escapeHtml(label)}</b>\n\n` : "";
|
|
32
|
+
const message = `${header}<pre>${escapeHtml(json)}</pre>`;
|
|
33
|
+
return relay(message, { parseMode: "HTML", ...config });
|
|
34
|
+
}
|
|
35
|
+
/** Try to read git info, returns undefined if git is not available */
|
|
36
|
+
function tryGit(cmd) {
|
|
37
|
+
try {
|
|
38
|
+
return execSync(cmd, { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
return undefined;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Send a deploy notification with optional git info.
|
|
46
|
+
* Auto-reads git branch/commit if not provided.
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* ```ts
|
|
50
|
+
* await relayDeploy({ app: "my-api", env: "production" });
|
|
51
|
+
* ```
|
|
52
|
+
*/
|
|
53
|
+
export async function relayDeploy(meta, config) {
|
|
54
|
+
const branch = meta?.branch ?? tryGit("git rev-parse --abbrev-ref HEAD");
|
|
55
|
+
const commit = meta?.commit ?? tryGit("git rev-parse --short HEAD");
|
|
56
|
+
const commitMsg = tryGit("git log -1 --pretty=%s");
|
|
57
|
+
const lines = ["🚀 <b>Deploy Notification</b>", ""];
|
|
58
|
+
if (meta?.app)
|
|
59
|
+
lines.push(`📦 <b>App:</b> ${escapeHtml(meta.app)}`);
|
|
60
|
+
if (meta?.env)
|
|
61
|
+
lines.push(`🌍 <b>Env:</b> ${escapeHtml(meta.env)}`);
|
|
62
|
+
if (meta?.version)
|
|
63
|
+
lines.push(`🏷️ <b>Version:</b> ${escapeHtml(meta.version)}`);
|
|
64
|
+
if (branch)
|
|
65
|
+
lines.push(`🌿 <b>Branch:</b> ${escapeHtml(branch)}`);
|
|
66
|
+
if (commit)
|
|
67
|
+
lines.push(`📝 <b>Commit:</b> <code>${escapeHtml(commit)}</code>${commitMsg ? ` — ${escapeHtml(commitMsg)}` : ""}`);
|
|
68
|
+
if (meta?.by)
|
|
69
|
+
lines.push(`👤 <b>By:</b> ${escapeHtml(meta.by)}`);
|
|
70
|
+
lines.push(`⏰ <b>Time:</b> ${new Date().toISOString()}`);
|
|
71
|
+
if (meta?.extra) {
|
|
72
|
+
for (const [key, value] of Object.entries(meta.extra)) {
|
|
73
|
+
lines.push(`• <b>${escapeHtml(key)}:</b> ${escapeHtml(value)}`);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return relay(lines.join("\n"), { parseMode: "HTML", ...config });
|
|
77
|
+
}
|
|
78
|
+
/** Escape HTML special characters for Telegram HTML parse mode */
|
|
79
|
+
function escapeHtml(text) {
|
|
80
|
+
return text
|
|
81
|
+
.replace(/&/g, "&")
|
|
82
|
+
.replace(/</g, "<")
|
|
83
|
+
.replace(/>/g, ">")
|
|
84
|
+
.replace(/"/g, """);
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=format.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format.js","sourceRoot":"","sources":["../src/format.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
-
export { relay, createRelay } from "./relay.js";
|
|
2
|
-
export
|
|
1
|
+
export { relay, createRelay, isDryRun } from "./relay.js";
|
|
2
|
+
export { relayError, relayJSON, relayDeploy } from "./format.js";
|
|
3
|
+
export { message, MessageBuilder } from "./builder.js";
|
|
4
|
+
export { relayFile } from "./file.js";
|
|
5
|
+
export { watchProcess, startHeartbeat } from "./watch.js";
|
|
6
|
+
export { irisMiddleware, irisErrorHandler } from "./middleware.js";
|
|
7
|
+
export { createChannels } from "./channels.js";
|
|
8
|
+
export type { RelayConfig, RelayResult, TelegramResponse, DeployMeta, HeartbeatOptions, MiddlewareOptions, Channel, } from "./types.js";
|
|
3
9
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAG1D,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAGjE,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAGvD,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAGtC,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAG1D,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAGnE,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAG/C,YAAY,EACR,WAAW,EACX,WAAW,EACX,gBAAgB,EAChB,UAAU,EACV,gBAAgB,EAChB,iBAAiB,EACjB,OAAO,GACV,MAAM,YAAY,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,15 @@
|
|
|
1
|
-
|
|
1
|
+
// Core
|
|
2
|
+
export { relay, createRelay, isDryRun } from "./relay.js";
|
|
3
|
+
// Formatters
|
|
4
|
+
export { relayError, relayJSON, relayDeploy } from "./format.js";
|
|
5
|
+
// Message builder
|
|
6
|
+
export { message, MessageBuilder } from "./builder.js";
|
|
7
|
+
// File relay
|
|
8
|
+
export { relayFile } from "./file.js";
|
|
9
|
+
// Process monitoring
|
|
10
|
+
export { watchProcess, startHeartbeat } from "./watch.js";
|
|
11
|
+
// Middleware
|
|
12
|
+
export { irisMiddleware, irisErrorHandler } from "./middleware.js";
|
|
13
|
+
// Multi-channel
|
|
14
|
+
export { createChannels } from "./channels.js";
|
|
2
15
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO;AACP,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE1D,aAAa;AACb,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAEjE,kBAAkB;AAClB,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAEvD,aAAa;AACb,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEtC,qBAAqB;AACrB,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAE1D,aAAa;AACb,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAEnE,gBAAgB;AAChB,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { MiddlewareOptions, RelayConfig } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Express/Fastify-compatible middleware that reports errors and slow requests to Telegram.
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* ```ts
|
|
7
|
+
* import express from "express";
|
|
8
|
+
* import { irisMiddleware } from "iris-relay";
|
|
9
|
+
*
|
|
10
|
+
* const app = express();
|
|
11
|
+
* app.use(irisMiddleware({ slowThreshold: 3000 }));
|
|
12
|
+
* ```
|
|
13
|
+
*/
|
|
14
|
+
export declare function irisMiddleware(options?: MiddlewareOptions): (req: any, res: any, next: any) => void;
|
|
15
|
+
/**
|
|
16
|
+
* Express error-handling middleware that sends error details to Telegram.
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```ts
|
|
20
|
+
* // Add AFTER all routes
|
|
21
|
+
* app.use(irisErrorHandler());
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
export declare function irisErrorHandler(config?: RelayConfig): (err: any, req: any, res: any, next: any) => void;
|
|
25
|
+
//# sourceMappingURL=middleware.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../src/middleware.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEjE;;;;;;;;;;;GAWG;AACH,wBAAgB,cAAc,CAAC,OAAO,CAAC,EAAE,iBAAiB,IAS9C,KAAK,GAAG,EAAE,KAAK,GAAG,EAAE,MAAM,GAAG,UAkCxC;AAED;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,CAAC,EAAE,WAAW,IACzC,KAAK,GAAG,EAAE,KAAK,GAAG,EAAE,KAAK,GAAG,EAAE,MAAM,GAAG,UAclD"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { relay } from "./relay.js";
|
|
2
|
+
/**
|
|
3
|
+
* Express/Fastify-compatible middleware that reports errors and slow requests to Telegram.
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* ```ts
|
|
7
|
+
* import express from "express";
|
|
8
|
+
* import { irisMiddleware } from "iris-relay";
|
|
9
|
+
*
|
|
10
|
+
* const app = express();
|
|
11
|
+
* app.use(irisMiddleware({ slowThreshold: 3000 }));
|
|
12
|
+
* ```
|
|
13
|
+
*/
|
|
14
|
+
export function irisMiddleware(options) {
|
|
15
|
+
const { slowThreshold = 3000, reportErrors = true, reportSlow = true, relay: relayConfig, } = options ?? {};
|
|
16
|
+
// Standard Express middleware signature
|
|
17
|
+
return (req, res, next) => {
|
|
18
|
+
const start = Date.now();
|
|
19
|
+
const method = req.method;
|
|
20
|
+
const url = req.originalUrl || req.url;
|
|
21
|
+
// Hook into response finish to check timing
|
|
22
|
+
res.on("finish", async () => {
|
|
23
|
+
const duration = Date.now() - start;
|
|
24
|
+
const status = res.statusCode;
|
|
25
|
+
// Report slow requests
|
|
26
|
+
if (reportSlow && duration > slowThreshold) {
|
|
27
|
+
const msg = `🐢 <b>Slow Request</b>\n\n` +
|
|
28
|
+
`<b>Method:</b> ${method}\n` +
|
|
29
|
+
`<b>URL:</b> <code>${escapeHtml(url)}</code>\n` +
|
|
30
|
+
`<b>Status:</b> ${status}\n` +
|
|
31
|
+
`<b>Duration:</b> ${duration}ms (threshold: ${slowThreshold}ms)`;
|
|
32
|
+
relay(msg, { parseMode: "HTML", silent: true, ...relayConfig }).catch(() => { });
|
|
33
|
+
}
|
|
34
|
+
// Report server errors (5xx)
|
|
35
|
+
if (reportErrors && status >= 500) {
|
|
36
|
+
const msg = `🔥 <b>Server Error ${status}</b>\n\n` +
|
|
37
|
+
`<b>Method:</b> ${method}\n` +
|
|
38
|
+
`<b>URL:</b> <code>${escapeHtml(url)}</code>\n` +
|
|
39
|
+
`<b>Duration:</b> ${duration}ms`;
|
|
40
|
+
relay(msg, { parseMode: "HTML", ...relayConfig }).catch(() => { });
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
next();
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Express error-handling middleware that sends error details to Telegram.
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* ```ts
|
|
51
|
+
* // Add AFTER all routes
|
|
52
|
+
* app.use(irisErrorHandler());
|
|
53
|
+
* ```
|
|
54
|
+
*/
|
|
55
|
+
export function irisErrorHandler(config) {
|
|
56
|
+
return (err, req, res, next) => {
|
|
57
|
+
const method = req.method;
|
|
58
|
+
const url = req.originalUrl || req.url;
|
|
59
|
+
const msg = `🚨 <b>Unhandled Error</b>\n\n` +
|
|
60
|
+
`<b>Method:</b> ${method}\n` +
|
|
61
|
+
`<b>URL:</b> <code>${escapeHtml(url)}</code>\n` +
|
|
62
|
+
`<b>Error:</b> ${escapeHtml(err.message ?? String(err))}\n\n` +
|
|
63
|
+
`<pre>${escapeHtml(err.stack ?? "No stack trace")}</pre>`;
|
|
64
|
+
relay(msg, { parseMode: "HTML", ...config }).catch(() => { });
|
|
65
|
+
next(err);
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
function escapeHtml(text) {
|
|
69
|
+
return text
|
|
70
|
+
.replace(/&/g, "&")
|
|
71
|
+
.replace(/</g, "<")
|
|
72
|
+
.replace(/>/g, ">");
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=middleware.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"middleware.js","sourceRoot":"","sources":["../src/middleware.ts"],"names":[],"mappings":"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"}
|
package/dist/relay.d.ts
CHANGED
|
@@ -1,27 +1,22 @@
|
|
|
1
1
|
import type { RelayConfig, RelayResult } from "./types.js";
|
|
2
|
+
/** Check if dry run mode is enabled */
|
|
3
|
+
export declare function isDryRun(): boolean;
|
|
4
|
+
export declare function resolveConfig(overrides?: RelayConfig): {
|
|
5
|
+
botToken: string;
|
|
6
|
+
chatId: string;
|
|
7
|
+
parseMode?: "HTML" | "Markdown" | "MarkdownV2";
|
|
8
|
+
disablePreview?: boolean;
|
|
9
|
+
silent?: boolean;
|
|
10
|
+
retries?: number;
|
|
11
|
+
retryDelay?: number;
|
|
12
|
+
};
|
|
2
13
|
/**
|
|
3
|
-
* Send a
|
|
4
|
-
*
|
|
5
|
-
* Reads `IRIS_BOT_TOKEN` and `IRIS_CHAT_ID` from env, or accepts them via config.
|
|
6
|
-
*
|
|
7
|
-
* @example
|
|
8
|
-
* ```ts
|
|
9
|
-
* import { relay } from "iris";
|
|
10
|
-
* await relay("Hello from my server!");
|
|
11
|
-
* ```
|
|
14
|
+
* Send a message to your Telegram chat.
|
|
15
|
+
* Supports dry run mode, retries with exponential backoff.
|
|
12
16
|
*/
|
|
13
17
|
export declare function relay(message: string, config?: RelayConfig): Promise<RelayResult>;
|
|
14
18
|
/**
|
|
15
19
|
* Create a pre-configured relay function with baked-in credentials.
|
|
16
|
-
*
|
|
17
|
-
* @example
|
|
18
|
-
* ```ts
|
|
19
|
-
* import { createRelay } from "iris";
|
|
20
|
-
*
|
|
21
|
-
* const send = createRelay({ botToken: "...", chatId: "..." });
|
|
22
|
-
* await send("Deploy successful ✅");
|
|
23
|
-
* await send("Build failed ❌");
|
|
24
|
-
* ```
|
|
25
20
|
*/
|
|
26
21
|
export declare function createRelay(config: RelayConfig): (message: string, overrides?: Partial<RelayConfig>) => Promise<RelayResult>;
|
|
27
22
|
//# sourceMappingURL=relay.d.ts.map
|
package/dist/relay.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"relay.d.ts","sourceRoot":"","sources":["../src/relay.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAoB,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"relay.d.ts","sourceRoot":"","sources":["../src/relay.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAoB,MAAM,YAAY,CAAC;AAO7E,uCAAuC;AACvC,wBAAgB,QAAQ,IAAI,OAAO,CAElC;AAED,wBAAgB,aAAa,CAAC,SAAS,CAAC,EAAE,WAAW;;;;;;;;EAUpD;AAOD;;;GAGG;AACH,wBAAsB,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC,CAiDvF;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,WAAW,IAEnC,SAAS,MAAM,EAAE,YAAY,OAAO,CAAC,WAAW,CAAC,KAAG,OAAO,CAAC,WAAW,CAAC,CAEnF"}
|
package/dist/relay.js
CHANGED
|
@@ -2,7 +2,11 @@ import { config } from "dotenv";
|
|
|
2
2
|
// Auto-load .env on import — true plug-and-play
|
|
3
3
|
config();
|
|
4
4
|
const TG_API = "https://api.telegram.org";
|
|
5
|
-
|
|
5
|
+
/** Check if dry run mode is enabled */
|
|
6
|
+
export function isDryRun() {
|
|
7
|
+
return process.env.XERO_DRY_RUN === "true" || process.env.XERO_DRY_RUN === "1";
|
|
8
|
+
}
|
|
9
|
+
export function resolveConfig(overrides) {
|
|
6
10
|
const botToken = overrides?.botToken
|
|
7
11
|
?? process.env.XERO_BOT_TOKEN;
|
|
8
12
|
const chatId = overrides?.chatId
|
|
@@ -13,47 +17,58 @@ function resolveConfig(overrides) {
|
|
|
13
17
|
throw new Error("iris: chatId is required — pass it in config or set XERO_CHAT_ID env var");
|
|
14
18
|
return { botToken, chatId, ...overrides };
|
|
15
19
|
}
|
|
20
|
+
/** Sleep helper for retry backoff */
|
|
21
|
+
function sleep(ms) {
|
|
22
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
23
|
+
}
|
|
16
24
|
/**
|
|
17
|
-
* Send a
|
|
18
|
-
*
|
|
19
|
-
* Reads `IRIS_BOT_TOKEN` and `IRIS_CHAT_ID` from env, or accepts them via config.
|
|
20
|
-
*
|
|
21
|
-
* @example
|
|
22
|
-
* ```ts
|
|
23
|
-
* import { relay } from "iris";
|
|
24
|
-
* await relay("Hello from my server!");
|
|
25
|
-
* ```
|
|
25
|
+
* Send a message to your Telegram chat.
|
|
26
|
+
* Supports dry run mode, retries with exponential backoff.
|
|
26
27
|
*/
|
|
27
28
|
export async function relay(message, config) {
|
|
28
|
-
const { botToken, chatId, parseMode, disablePreview, silent } = resolveConfig(config);
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
29
|
+
const { botToken, chatId, parseMode, disablePreview, silent, retries = 0, retryDelay = 1000 } = resolveConfig(config);
|
|
30
|
+
// Dry run — log to console instead
|
|
31
|
+
if (isDryRun()) {
|
|
32
|
+
console.log(`[iris-relay DRY RUN] → ${message}`);
|
|
33
|
+
return { success: true, messageId: 0 };
|
|
34
|
+
}
|
|
35
|
+
let lastError;
|
|
36
|
+
for (let attempt = 0; attempt <= retries; attempt++) {
|
|
37
|
+
if (attempt > 0) {
|
|
38
|
+
const delay = retryDelay * Math.pow(2, attempt - 1);
|
|
39
|
+
console.log(`[iris-relay] Retry ${attempt}/${retries} in ${delay}ms...`);
|
|
40
|
+
await sleep(delay);
|
|
41
|
+
}
|
|
42
|
+
try {
|
|
43
|
+
const res = await fetch(`${TG_API}/bot${botToken}/sendMessage`, {
|
|
44
|
+
method: "POST",
|
|
45
|
+
headers: { "Content-Type": "application/json" },
|
|
46
|
+
body: JSON.stringify({
|
|
47
|
+
chat_id: chatId,
|
|
48
|
+
text: message,
|
|
49
|
+
...(parseMode && { parse_mode: parseMode }),
|
|
50
|
+
...(disablePreview && { disable_web_page_preview: true }),
|
|
51
|
+
...(silent && { disable_notification: true }),
|
|
52
|
+
}),
|
|
53
|
+
});
|
|
54
|
+
const data = (await res.json());
|
|
55
|
+
if (data.ok) {
|
|
56
|
+
return { success: true, messageId: data.result?.message_id };
|
|
57
|
+
}
|
|
58
|
+
lastError = data.description ?? `Telegram API error (${data.error_code})`;
|
|
59
|
+
// Don't retry on 4xx client errors (bad token, bad chat id, etc.)
|
|
60
|
+
if (data.error_code && data.error_code >= 400 && data.error_code < 500) {
|
|
61
|
+
return { success: false, error: lastError };
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
catch (err) {
|
|
65
|
+
lastError = err instanceof Error ? err.message : String(err);
|
|
66
|
+
}
|
|
43
67
|
}
|
|
44
|
-
return { success:
|
|
68
|
+
return { success: false, error: lastError };
|
|
45
69
|
}
|
|
46
70
|
/**
|
|
47
71
|
* Create a pre-configured relay function with baked-in credentials.
|
|
48
|
-
*
|
|
49
|
-
* @example
|
|
50
|
-
* ```ts
|
|
51
|
-
* import { createRelay } from "iris";
|
|
52
|
-
*
|
|
53
|
-
* const send = createRelay({ botToken: "...", chatId: "..." });
|
|
54
|
-
* await send("Deploy successful ✅");
|
|
55
|
-
* await send("Build failed ❌");
|
|
56
|
-
* ```
|
|
57
72
|
*/
|
|
58
73
|
export function createRelay(config) {
|
|
59
74
|
const resolved = resolveConfig(config);
|
package/dist/relay.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"relay.js","sourceRoot":"","sources":["../src/relay.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAGhC,gDAAgD;AAChD,MAAM,EAAE,CAAC;AAET,MAAM,MAAM,GAAG,0BAA0B,CAAC;AAE1C,
|
|
1
|
+
{"version":3,"file":"relay.js","sourceRoot":"","sources":["../src/relay.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/** Core relay config */
|
|
1
2
|
export interface RelayConfig {
|
|
2
3
|
/** Telegram Bot API token from @BotFather */
|
|
3
4
|
botToken?: string;
|
|
@@ -9,6 +10,10 @@ export interface RelayConfig {
|
|
|
9
10
|
disablePreview?: boolean;
|
|
10
11
|
/** Send message silently (no notification sound) */
|
|
11
12
|
silent?: boolean;
|
|
13
|
+
/** Max retries on failure (default: 0) */
|
|
14
|
+
retries?: number;
|
|
15
|
+
/** Base delay in ms for exponential backoff (default: 1000) */
|
|
16
|
+
retryDelay?: number;
|
|
12
17
|
}
|
|
13
18
|
export interface TelegramResponse {
|
|
14
19
|
ok: boolean;
|
|
@@ -18,7 +23,7 @@ export interface TelegramResponse {
|
|
|
18
23
|
id: number;
|
|
19
24
|
type: string;
|
|
20
25
|
};
|
|
21
|
-
text
|
|
26
|
+
text?: string;
|
|
22
27
|
date: number;
|
|
23
28
|
};
|
|
24
29
|
description?: string;
|
|
@@ -29,4 +34,52 @@ export interface RelayResult {
|
|
|
29
34
|
messageId?: number;
|
|
30
35
|
error?: string;
|
|
31
36
|
}
|
|
37
|
+
/** Deploy metadata for relayDeploy() */
|
|
38
|
+
export interface DeployMeta {
|
|
39
|
+
/** App or service name */
|
|
40
|
+
app?: string;
|
|
41
|
+
/** Environment (production, staging, etc.) */
|
|
42
|
+
env?: string;
|
|
43
|
+
/** Version string */
|
|
44
|
+
version?: string;
|
|
45
|
+
/** Git branch */
|
|
46
|
+
branch?: string;
|
|
47
|
+
/** Git commit hash */
|
|
48
|
+
commit?: string;
|
|
49
|
+
/** Deployer name */
|
|
50
|
+
by?: string;
|
|
51
|
+
/** Custom extra fields */
|
|
52
|
+
extra?: Record<string, string>;
|
|
53
|
+
}
|
|
54
|
+
/** Heartbeat options */
|
|
55
|
+
export interface HeartbeatOptions {
|
|
56
|
+
/** Interval in ms (default: 60000 = 1 minute) */
|
|
57
|
+
interval?: number;
|
|
58
|
+
/** Custom message (default: "💓 Heartbeat — {app} is alive") */
|
|
59
|
+
message?: string;
|
|
60
|
+
/** App name for the heartbeat message */
|
|
61
|
+
app?: string;
|
|
62
|
+
}
|
|
63
|
+
/** Middleware options for Express/Fastify */
|
|
64
|
+
export interface MiddlewareOptions {
|
|
65
|
+
/** Slow request threshold in ms (default: 3000) */
|
|
66
|
+
slowThreshold?: number;
|
|
67
|
+
/** Report errors to Telegram (default: true) */
|
|
68
|
+
reportErrors?: boolean;
|
|
69
|
+
/** Report slow requests to Telegram (default: true) */
|
|
70
|
+
reportSlow?: boolean;
|
|
71
|
+
/** Relay config overrides */
|
|
72
|
+
relay?: RelayConfig;
|
|
73
|
+
}
|
|
74
|
+
/** Channel definition for multi-channel support */
|
|
75
|
+
export interface Channel {
|
|
76
|
+
name: string;
|
|
77
|
+
chatId: string;
|
|
78
|
+
/** Optional separate bot token per channel */
|
|
79
|
+
botToken?: string;
|
|
80
|
+
/** Default parse mode for this channel */
|
|
81
|
+
parseMode?: RelayConfig["parseMode"];
|
|
82
|
+
/** Send silently by default */
|
|
83
|
+
silent?: boolean;
|
|
84
|
+
}
|
|
32
85
|
//# sourceMappingURL=types.d.ts.map
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,WAAW;IACxB,6CAA6C;IAC7C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,4BAA4B;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,6DAA6D;IAC7D,SAAS,CAAC,EAAE,MAAM,GAAG,UAAU,GAAG,YAAY,CAAC;IAC/C,wCAAwC;IACxC,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,oDAAoD;IACpD,MAAM,CAAC,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,wBAAwB;AACxB,MAAM,WAAW,WAAW;IACxB,6CAA6C;IAC7C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,4BAA4B;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,6DAA6D;IAC7D,SAAS,CAAC,EAAE,MAAM,GAAG,UAAU,GAAG,YAAY,CAAC;IAC/C,wCAAwC;IACxC,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,oDAAoD;IACpD,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,0CAA0C;IAC1C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,+DAA+D;IAC/D,UAAU,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,gBAAgB;IAC7B,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,CAAC,EAAE;QACL,UAAU,EAAE,MAAM,CAAC;QACnB,IAAI,EAAE;YAAE,EAAE,EAAE,MAAM,CAAC;YAAC,IAAI,EAAE,MAAM,CAAA;SAAE,CAAC;QACnC,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,IAAI,EAAE,MAAM,CAAC;KAChB,CAAC;IACF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,WAAW;IACxB,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,wCAAwC;AACxC,MAAM,WAAW,UAAU;IACvB,0BAA0B;IAC1B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,8CAA8C;IAC9C,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,qBAAqB;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,iBAAiB;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,sBAAsB;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,oBAAoB;IACpB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,0BAA0B;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC;AAED,wBAAwB;AACxB,MAAM,WAAW,gBAAgB;IAC7B,iDAAiD;IACjD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gEAAgE;IAChE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,yCAAyC;IACzC,GAAG,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,6CAA6C;AAC7C,MAAM,WAAW,iBAAiB;IAC9B,mDAAmD;IACnD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,gDAAgD;IAChD,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,uDAAuD;IACvD,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,6BAA6B;IAC7B,KAAK,CAAC,EAAE,WAAW,CAAC;CACvB;AAED,mDAAmD;AACnD,MAAM,WAAW,OAAO;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,8CAA8C;IAC9C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,0CAA0C;IAC1C,SAAS,CAAC,EAAE,WAAW,CAAC,WAAW,CAAC,CAAC;IACrC,+BAA+B;IAC/B,MAAM,CAAC,EAAE,OAAO,CAAC;CACpB"}
|
package/dist/watch.d.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { RelayConfig, HeartbeatOptions } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Watch for uncaught exceptions and unhandled rejections.
|
|
4
|
+
* Sends crash reports to Telegram before the process exits.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```ts
|
|
8
|
+
* import { watchProcess } from "iris-relay";
|
|
9
|
+
* watchProcess(); // done — crashes get reported
|
|
10
|
+
* ```
|
|
11
|
+
*/
|
|
12
|
+
export declare function watchProcess(config?: RelayConfig): void;
|
|
13
|
+
/**
|
|
14
|
+
* Start sending periodic heartbeat messages.
|
|
15
|
+
* Returns a cleanup function to stop the heartbeat.
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```ts
|
|
19
|
+
* import { startHeartbeat } from "iris-relay";
|
|
20
|
+
*
|
|
21
|
+
* const stop = startHeartbeat({ interval: 60000, app: "my-api" });
|
|
22
|
+
* // Later: stop();
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
export declare function startHeartbeat(options?: HeartbeatOptions, config?: RelayConfig): () => void;
|
|
26
|
+
//# sourceMappingURL=watch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"watch.d.ts","sourceRoot":"","sources":["../src/watch.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEhE;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,IAAI,CA2BvD;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,cAAc,CAAC,OAAO,CAAC,EAAE,gBAAgB,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,MAAM,IAAI,CAiB3F"}
|