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/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
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file.js","sourceRoot":"","sources":["../src/file.ts"],"names":[],"mappings":"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"}
@@ -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, "&amp;")
82
+ .replace(/</g, "&lt;")
83
+ .replace(/>/g, "&gt;")
84
+ .replace(/"/g, "&quot;");
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 type { RelayConfig, RelayResult, TelegramResponse } from "./types.js";
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
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAChD,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC"}
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
- export { relay, createRelay } from "./relay.js";
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, "&amp;")
71
+ .replace(/</g, "&lt;")
72
+ .replace(/>/g, "&gt;");
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 one-off message to your Telegram chat.
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
@@ -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;AAkB7E;;;;;;;;;;GAUG;AACH,wBAAsB,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC,CAsBvF;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,WAAW,IAEnC,SAAS,MAAM,EAAE,YAAY,OAAO,CAAC,WAAW,CAAC,KAAG,OAAO,CAAC,WAAW,CAAC,CAEnF"}
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
- function resolveConfig(overrides) {
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 one-off message to your Telegram chat.
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
- const res = await fetch(`${TG_API}/bot${botToken}/sendMessage`, {
30
- method: "POST",
31
- headers: { "Content-Type": "application/json" },
32
- body: JSON.stringify({
33
- chat_id: chatId,
34
- text: message,
35
- ...(parseMode && { parse_mode: parseMode }),
36
- ...(disablePreview && { disable_web_page_preview: true }),
37
- ...(silent && { disable_notification: true }),
38
- }),
39
- });
40
- const data = (await res.json());
41
- if (!data.ok) {
42
- return { success: false, error: data.description ?? `Telegram API error (${data.error_code})` };
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: true, messageId: data.result?.message_id };
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,SAAS,aAAa,CAAC,SAAuB;IAC1C,MAAM,QAAQ,GAAG,SAAS,EAAE,QAAQ;WAC7B,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC;IAClC,MAAM,MAAM,GAAG,SAAS,EAAE,MAAM;WACzB,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC;IAChC,IAAI,CAAC,QAAQ;QAAE,MAAM,IAAI,KAAK,CAAC,8EAA8E,CAAC,CAAC;IAC/G,IAAI,CAAC,MAAM;QAAE,MAAM,IAAI,KAAK,CAAC,0EAA0E,CAAC,CAAC;IAEzG,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,SAAS,EAAE,CAAC;AAC9C,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,KAAK,CAAC,OAAe,EAAE,MAAoB;IAC7D,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,EAAE,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;IAEtF,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,MAAM,OAAO,QAAQ,cAAc,EAAE;QAC5D,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;QAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;YACjB,OAAO,EAAE,MAAM;YACf,IAAI,EAAE,OAAO;YACb,GAAG,CAAC,SAAS,IAAI,EAAE,UAAU,EAAE,SAAS,EAAE,CAAC;YAC3C,GAAG,CAAC,cAAc,IAAI,EAAE,wBAAwB,EAAE,IAAI,EAAE,CAAC;YACzD,GAAG,CAAC,MAAM,IAAI,EAAE,oBAAoB,EAAE,IAAI,EAAE,CAAC;SAChD,CAAC;KACL,CAAC,CAAC;IAEH,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAqB,CAAC;IAEpD,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC;QACX,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,WAAW,IAAI,uBAAuB,IAAI,CAAC,UAAU,GAAG,EAAE,CAAC;IACpG,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,CAAC,MAAM,EAAE,UAAU,EAAE,CAAC;AACjE,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,WAAW,CAAC,MAAmB;IAC3C,MAAM,QAAQ,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;IACvC,OAAO,CAAC,OAAe,EAAE,SAAgC,EAAwB,EAAE,CAC/E,KAAK,CAAC,OAAO,EAAE,EAAE,GAAG,QAAQ,EAAE,GAAG,SAAS,EAAE,CAAC,CAAC;AACtD,CAAC"}
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: string;
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
@@ -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;CACpB;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,EAAE,MAAM,CAAC;QACb,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"}
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"}
@@ -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"}