slack-logs 3.0.3 → 3.0.5
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 +188 -0
- package/dist/index.d.ts +8 -25
- package/dist/index.js +1 -1
- package/dist/shared.d.ts +40 -0
- package/dist/slack-bot.d.ts +15 -0
- package/dist/webhook.d.ts +12 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -78,6 +78,29 @@ slack.logBlockMessage("Validation Message!", payload);
|
|
|
78
78
|
- if `slackLogConfig(...)` is used, env values are ignored for both fields
|
|
79
79
|
- `slackLogConfig(...)` does not ask for values interactively
|
|
80
80
|
|
|
81
|
+
### Required Slack webhook setup
|
|
82
|
+
|
|
83
|
+
- credential required: `Incoming Webhook URL`
|
|
84
|
+
- URL format: `https://hooks.slack.com/services/...`
|
|
85
|
+
- where to find it: Slack App Settings -> `Incoming Webhooks` -> `Webhook URLs for Your Workspace`
|
|
86
|
+
- enable `Incoming Webhooks` first in the app settings
|
|
87
|
+
- each webhook URL is tied to one Slack channel
|
|
88
|
+
- if you need different channels, create separate webhook URLs or use `slackbot`
|
|
89
|
+
|
|
90
|
+
### Create the Slack app / webhook if you don't have one
|
|
91
|
+
|
|
92
|
+
1. Go to `https://api.slack.com/apps`
|
|
93
|
+
2. Click `Create New App`
|
|
94
|
+
3. Select `From scratch`
|
|
95
|
+
4. Enter the app name and choose the workspace
|
|
96
|
+
5. Open `Incoming Webhooks`
|
|
97
|
+
6. Turn on `Activate Incoming Webhooks`
|
|
98
|
+
7. Click `Add New Webhook to Workspace`
|
|
99
|
+
8. Select the Slack channel
|
|
100
|
+
9. Click `Allow`
|
|
101
|
+
10. Copy the webhook URL from `Webhook URLs for Your Workspace`
|
|
102
|
+
11. Use it in `slackLogConfig({ webhookUrl: "..." })` or `SLACK_WEBHOOK_URL`
|
|
103
|
+
|
|
81
104
|
#### Option 2: Use environment variables
|
|
82
105
|
|
|
83
106
|
Use env values only when `slackLogConfig(...)` is not called.
|
|
@@ -267,3 +290,168 @@ slack.rawBody(payload);
|
|
|
267
290
|
```
|
|
268
291
|
|
|
269
292
|
If payload is invalid or sending fails, it logs a console error.
|
|
293
|
+
|
|
294
|
+
---
|
|
295
|
+
|
|
296
|
+
## Slack Bot
|
|
297
|
+
|
|
298
|
+
Use `slackbot` when you want the same logging helpers with bot-token based multi-channel support.
|
|
299
|
+
|
|
300
|
+
### Configuration
|
|
301
|
+
|
|
302
|
+
```
|
|
303
|
+
import { slackbot, slackBotConfig } from "slack-logs";
|
|
304
|
+
or
|
|
305
|
+
const { slackbot, slackBotConfig } = require("slack-logs");
|
|
306
|
+
|
|
307
|
+
slackBotConfig({
|
|
308
|
+
botToken: "xoxb-XXXXXXXXXX-XXXXXXXXXX-XXXXXXXXXXXXXXXXXXXXXXXX",
|
|
309
|
+
defaultChannelId: "C0123456789",
|
|
310
|
+
enableAlerts: true,
|
|
311
|
+
});
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
`slackBotConfig(...)` rules:
|
|
315
|
+
|
|
316
|
+
- `botToken` and `enableAlerts` are required
|
|
317
|
+
- `defaultChannelId` is optional if you pass `channelId` in method calls
|
|
318
|
+
- if `defaultChannelId` is not set in config, package falls back to `SLACK_BOT_DEFAULT_CHANNEL_ID`
|
|
319
|
+
|
|
320
|
+
### Required Slack app setup
|
|
321
|
+
|
|
322
|
+
- token required: `Bot User OAuth Access Token`
|
|
323
|
+
- token format: `xoxb-...`
|
|
324
|
+
- where to find it: Slack App Settings -> `OAuth & Permissions` -> `Bot User OAuth Access Token`
|
|
325
|
+
- important: the token appears only after you click `Install to Workspace`
|
|
326
|
+
- add scopes under `OAuth & Permissions` -> `Bot Token Scopes`
|
|
327
|
+
- required scope: `chat:write`
|
|
328
|
+
- optional scope: `chat:write.public` if you want to post in public channels without inviting the app first
|
|
329
|
+
- do not use `User Token Scopes`
|
|
330
|
+
- do not use app-level tokens (`xapp-...`) for this package
|
|
331
|
+
- if the app is not in a channel, invite it first unless you added `chat:write.public`
|
|
332
|
+
|
|
333
|
+
### Environment variables
|
|
334
|
+
|
|
335
|
+
Use env values only when `slackBotConfig(...)` is not called.
|
|
336
|
+
|
|
337
|
+
`.env` 🚨
|
|
338
|
+
|
|
339
|
+
```
|
|
340
|
+
...
|
|
341
|
+
SLACK_BOT_TOKEN="xoxb-XXXXXXXXXX-XXXXXXXXXX-XXXXXXXXXXXXXXXXXXXXXXXX"
|
|
342
|
+
SLACK_BOT_DEFAULT_CHANNEL_ID="C0123456789"
|
|
343
|
+
|
|
344
|
+
# Optional field.
|
|
345
|
+
# If not defined, logs are sent by default.
|
|
346
|
+
# true / True / TRUE sends logs.
|
|
347
|
+
# false / False / FALSE skips logs.
|
|
348
|
+
ENABLE_SLACK_BOT_LOGS=true
|
|
349
|
+
...
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
### Create the Slack app if you don't have one
|
|
353
|
+
|
|
354
|
+
1. Go to `https://api.slack.com/apps`
|
|
355
|
+
2. Click `Create New App`
|
|
356
|
+
3. Select `From scratch`
|
|
357
|
+
4. Enter the app name and choose the workspace
|
|
358
|
+
5. Open `OAuth & Permissions`
|
|
359
|
+
6. Under `Bot Token Scopes`, add `chat:write`
|
|
360
|
+
7. Optional: add `chat:write.public`
|
|
361
|
+
8. Click `Install to Workspace`
|
|
362
|
+
9. Copy the `Bot User OAuth Access Token` (`xoxb-...`)
|
|
363
|
+
10. Use it in `slackBotConfig({ botToken: "xoxb-..." })` or `SLACK_BOT_TOKEN`
|
|
364
|
+
|
|
365
|
+
### Methods
|
|
366
|
+
|
|
367
|
+
```
|
|
368
|
+
slackbot.log(label, data, channelId?);
|
|
369
|
+
slackbot.logBlockMessage(label, payload, errorType?, channelId?);
|
|
370
|
+
slackbot.rawBody(payload, channelId?);
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
### `slackbot.log(...)`
|
|
374
|
+
|
|
375
|
+
`slackbot.log(...)` uses the same payload format as `slack.log(...)`, so the output style is the same.
|
|
376
|
+
|
|
377
|
+
```
|
|
378
|
+
import { slackbot } from "slack-logs";
|
|
379
|
+
|
|
380
|
+
slackbot.log("Data Log with bold", "Here is *BOLD* message", "C0123456789");
|
|
381
|
+
slackbot.log("Highlight Log", "`Message`", "C0123456789");
|
|
382
|
+
slackbot.log("Emoji :rocket: Log", "Yeah :female-technologist::skin-tone-2:");
|
|
383
|
+
slackbot.log("Object Log", {id:"123", value:"Lorem Impulse"});
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+

|
|
387
|
+
|
|
388
|
+
### `slackbot.logBlockMessage(...)`
|
|
389
|
+
|
|
390
|
+
`slackbot.logBlockMessage(...)` uses the same payload format as `slack.logBlockMessage(...)`, so the same output examples apply.
|
|
391
|
+
|
|
392
|
+
```
|
|
393
|
+
import { LogLevel, slackbot } from "slack-logs";
|
|
394
|
+
|
|
395
|
+
const payload = [
|
|
396
|
+
{ title: "Title 1", value: "1234" },
|
|
397
|
+
{ title: "Title 2", value: 123 },
|
|
398
|
+
{ title: "Title 3", value: { id: 12 } },
|
|
399
|
+
{ title: "Title 4", value: [{ id: 12 }] },
|
|
400
|
+
];
|
|
401
|
+
|
|
402
|
+
slackbot.logBlockMessage("Custom Logs!", payload, LogLevel.DEFAULT, "C0123456789");
|
|
403
|
+
slackbot.logBlockMessage("Some Information Logs!", payload, LogLevel.INFO);
|
|
404
|
+
slackbot.logBlockMessage("Critical Alert!", payload, LogLevel.ERROR);
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+

|
|
408
|
+
|
|
409
|
+
### `slackbot.rawBody(...)`
|
|
410
|
+
|
|
411
|
+
Use `slackbot.rawBody(...)` when you want to send a custom Slack payload with an optional `channelId`.
|
|
412
|
+
|
|
413
|
+
```
|
|
414
|
+
import { slackbot } from "slack-logs";
|
|
415
|
+
|
|
416
|
+
const payload = {
|
|
417
|
+
blocks: [
|
|
418
|
+
{
|
|
419
|
+
type: "section",
|
|
420
|
+
text: {
|
|
421
|
+
type: "mrkdwn",
|
|
422
|
+
text: "Hello from custom payload",
|
|
423
|
+
},
|
|
424
|
+
},
|
|
425
|
+
{
|
|
426
|
+
type: "divider",
|
|
427
|
+
},
|
|
428
|
+
{
|
|
429
|
+
type: "actions",
|
|
430
|
+
elements: [
|
|
431
|
+
{
|
|
432
|
+
type: "button",
|
|
433
|
+
text: {
|
|
434
|
+
type: "plain_text",
|
|
435
|
+
text: "Open",
|
|
436
|
+
emoji: true,
|
|
437
|
+
},
|
|
438
|
+
value: "click_me_123",
|
|
439
|
+
url: "https://google.com",
|
|
440
|
+
},
|
|
441
|
+
],
|
|
442
|
+
},
|
|
443
|
+
],
|
|
444
|
+
};
|
|
445
|
+
|
|
446
|
+
slackbot.rawBody(payload, "C0123456789");
|
|
447
|
+
```
|
|
448
|
+
|
|
449
|
+
`slackbot.rawBody(...)` expects a plain object payload like:
|
|
450
|
+
|
|
451
|
+
```
|
|
452
|
+
{
|
|
453
|
+
"blocks": [...]
|
|
454
|
+
}
|
|
455
|
+
```
|
|
456
|
+
|
|
457
|
+
If payload is invalid or sending fails, it logs a console error.
|
package/dist/index.d.ts
CHANGED
|
@@ -1,30 +1,13 @@
|
|
|
1
|
+
import type { BlocksInterface, LogLevel } from "./shared";
|
|
1
2
|
interface Slack {
|
|
2
3
|
log(label: string, data: any): Promise<null | undefined>;
|
|
3
|
-
logBlockMessage(label: string, objectData: BlocksInterface[],
|
|
4
|
+
logBlockMessage(label: string, objectData: BlocksInterface[], errorType?: LogLevel): Promise<null | undefined>;
|
|
4
5
|
rawBody(payload: Record<string, any>): Promise<null | undefined>;
|
|
5
6
|
}
|
|
6
|
-
export
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
value: any;
|
|
13
|
-
}
|
|
14
|
-
export declare enum LogLevel {
|
|
15
|
-
DEFAULT = "DEFAULT",
|
|
16
|
-
SUCCESS = "SUCCESS",
|
|
17
|
-
INFO = "INFO",
|
|
18
|
-
WARN = "WARN",
|
|
19
|
-
ERROR = "ERROR"
|
|
20
|
-
}
|
|
21
|
-
export declare enum LogColor {
|
|
22
|
-
DEFAULT = "#B4B4B8",
|
|
23
|
-
SUCCESS = "#65B741",
|
|
24
|
-
INFO = "#40A2D8",
|
|
25
|
-
WARN = "#E3651D",
|
|
26
|
-
ERROR = "#FF0000"
|
|
27
|
-
}
|
|
28
|
-
export declare function slackLogConfig(config: SlackLogConfigOptions): void;
|
|
7
|
+
export type { SlackBotConfigOptions } from "./slack-bot";
|
|
8
|
+
export { slackBotConfig, slackbot } from "./slack-bot";
|
|
9
|
+
export type { BlocksInterface } from "./shared";
|
|
10
|
+
export { LogColor, LogLevel } from "./shared";
|
|
11
|
+
export type { SlackLogConfigOptions } from "./webhook";
|
|
12
|
+
export { slackLogConfig } from "./webhook";
|
|
29
13
|
export declare const slack: Slack;
|
|
30
|
-
export {};
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";function e(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}Object.defineProperty(exports,"__esModule",{value:!0});var o,t,
|
|
1
|
+
"use strict";function e(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}Object.defineProperty(exports,"__esModule",{value:!0});var o,t,n=e(require("axios"));exports.LogLevel=void 0,(o=exports.LogLevel||(exports.LogLevel={})).DEFAULT="DEFAULT",o.SUCCESS="SUCCESS",o.INFO="INFO",o.WARN="WARN",o.ERROR="ERROR",exports.LogColor=void 0,(t=exports.LogColor||(exports.LogColor={})).DEFAULT="#B4B4B8",t.SUCCESS="#65B741",t.INFO="#40A2D8",t.WARN="#E3651D",t.ERROR="#FF0000";const r={};function s(){const e=l();if(!e)return!1;return!!/^https:\/\/hooks\.slack\.com\/services\/[A-Za-z0-9]+\/[A-Za-z0-9]+\/[A-Za-z0-9]+$/.test(e)||(console.error(`🚨 Slack webhook URL does not look in correct format. Current value is "${e}", expected format is "https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX". 🚨`),!1)}function l(){return r.webhookUrl??process.env.SLACK_WEBHOOK_URL}async function a(e){if(!function(){if("boolean"==typeof r.enableAlerts)return r.enableAlerts;const e=(process?.env?.ENABLE_SLACK_LOGS??"").toString().trim();return!e||"true"===e.toLowerCase()||(e.toLowerCase(),!1)}())return null;const o=l();await n.default.post(o,JSON.stringify(e),{headers:{"Content-Type":"application/json"}}).catch((e=>{const o=e?.response?.data?.error||e?.response?.statusText||e?.message||"Unknown error";console.error(`🚨 Error sending log message to Slack: ${o}`)}))}const c={};const i={log:async(e,o,t)=>(await p(function(e,o){return{text:`*${e}:* ${JSON.stringify(o)}`}}(e,o),t),null),logBlockMessage:async(e,o,t=exports.LogLevel.DEFAULT,n)=>(await p(function(e,o,t=exports.LogLevel.DEFAULT){const n=[];return o?.length&&o.forEach((e=>{n.push({type:"section",text:{type:"mrkdwn",text:`*${e.title}:* ${JSON.stringify(e.value)}`}})})),{text:e,blocks:[{type:"divider"},{type:"header",text:{type:"plain_text",text:e,emoji:!0}},{type:"divider"}],attachments:[{color:exports.LogColor[t],blocks:n}]}}(e,o,t),n),null),rawBody:async(e,o)=>function(e){return!!e&&"object"==typeof e&&!Array.isArray(e)}(e)?(await p(e,o),null):(console.error('🚨 Invalid Slack payload for slackbot.rawBody(...). Expected an object like { "blocks": [...] } 🚨'),null)};function u(e,o){const t=("string"==typeof e.channel?e.channel:void 0)??o??c.defaultChannelId??process.env.SLACK_BOT_DEFAULT_CHANNEL_ID;return function(e){return!!e&&/^[CGD][A-Z0-9]+$/.test(e)}(t)?t:(console.error("🚨 Invalid Slack channel ID. Kindly pass a valid channelId or set 'defaultChannelId' in slackBotConfig(...) / 'SLACK_BOT_DEFAULT_CHANNEL_ID' in your .env file! 🚨"),null)}async function p(e,o){if(!function(){if("boolean"==typeof c.enableAlerts)return c.enableAlerts;const e=(process?.env?.ENABLE_SLACK_BOT_LOGS??process?.env?.ENABLE_SLACK_LOGS??"").toString().trim();return!e||"true"===e.toLowerCase()||(e.toLowerCase(),!1)}())return null;const t=c.botToken??process.env.SLACK_BOT_TOKEN;if(!function(e){return!!e&&/^xoxb-[A-Za-z0-9-]+$/.test(e)}(t))return console.error("🚨 Invalid Slack bot token. Kindly check slackBotConfig(...) or 'SLACK_BOT_TOKEN' in your .env file! 🚨"),null;const r=u(e,o);return r?await n.default.post("https://slack.com/api/chat.postMessage",{...e,channel:r},{headers:{Authorization:`Bearer ${t}`,"Content-Type":"application/json; charset=utf-8"}}).then((e=>{e?.data?.ok||console.error(`🚨 Error sending bot message to Slack: ${e?.data?.error||"Unknown error"}`)})).catch((e=>{const o=e?.response?.data?.error||e?.response?.statusText||e?.message||"Unknown error";console.error(`🚨 Error sending bot message to Slack: ${o}`)})):null}const d={...{async log(e,o){const t=JSON.stringify(o);if(!s())return console.error("🚨 Invalid Slack webhook URL. Kindly check slackLogConfig(...) or 'SLACK_WEBHOOK_URL' in your .env file! 🚨"),null;const n={text:`*${e}:* ${t}`};await a(n)},async logBlockMessage(e,o,t=exports.LogLevel.DEFAULT){if(!s())return console.error("🚨 Invalid Slack webhook URL. Kindly check slackLogConfig(...) or 'SLACK_WEBHOOK_URL' in your .env file! 🚨"),null;const n=exports.LogColor[t],r=[],l=[],c=[];r.push({type:"divider"}),r.push({type:"header",text:{type:"plain_text",text:e,emoji:!0}}),r.push({type:"divider"}),o?.length&&o.forEach((e=>{const o=JSON.stringify(e.value);c.push({type:"section",text:{type:"mrkdwn",text:`*${e.title}:* ${o}`}})})),l.push({color:n,blocks:c});const i={text:e,blocks:r,attachments:l};await a(i)},rawBody:async e=>s()?function(e){return!!e&&"object"==typeof e&&!Array.isArray(e)}(e)?void await a(e):(console.error('🚨 Invalid Slack payload for rawBody(...). Expected an object like { "blocks": [...] } 🚨'),null):(console.error("🚨 Invalid Slack webhook URL. Kindly check slackLogConfig(...) or 'SLACK_WEBHOOK_URL' in your .env file! 🚨"),null)}};exports.slack=d,exports.slackBotConfig=function(e){c.botToken=e.botToken,c.defaultChannelId=e.defaultChannelId,c.enableAlerts=e.enableAlerts},exports.slackLogConfig=function(e){r.webhookUrl=e.webhookUrl,r.enableAlerts=e.enableAlerts},exports.slackbot=i;
|
package/dist/shared.d.ts
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
export interface BlocksInterface {
|
|
2
|
+
title: string;
|
|
3
|
+
value: any;
|
|
4
|
+
}
|
|
5
|
+
export declare enum LogLevel {
|
|
6
|
+
DEFAULT = "DEFAULT",
|
|
7
|
+
SUCCESS = "SUCCESS",
|
|
8
|
+
INFO = "INFO",
|
|
9
|
+
WARN = "WARN",
|
|
10
|
+
ERROR = "ERROR"
|
|
11
|
+
}
|
|
12
|
+
export declare enum LogColor {
|
|
13
|
+
DEFAULT = "#B4B4B8",
|
|
14
|
+
SUCCESS = "#65B741",
|
|
15
|
+
INFO = "#40A2D8",
|
|
16
|
+
WARN = "#E3651D",
|
|
17
|
+
ERROR = "#FF0000"
|
|
18
|
+
}
|
|
19
|
+
export declare function buildLogPayload(label: string, data: any): {
|
|
20
|
+
text: string;
|
|
21
|
+
};
|
|
22
|
+
export declare function buildLogBlockPayload(label: string, objectData: BlocksInterface[], errorType?: LogLevel): {
|
|
23
|
+
text: string;
|
|
24
|
+
blocks: ({
|
|
25
|
+
type: string;
|
|
26
|
+
text?: undefined;
|
|
27
|
+
} | {
|
|
28
|
+
type: string;
|
|
29
|
+
text: {
|
|
30
|
+
type: string;
|
|
31
|
+
text: string;
|
|
32
|
+
emoji: boolean;
|
|
33
|
+
};
|
|
34
|
+
})[];
|
|
35
|
+
attachments: {
|
|
36
|
+
color: LogColor;
|
|
37
|
+
blocks: object[];
|
|
38
|
+
}[];
|
|
39
|
+
};
|
|
40
|
+
export declare function isValidRawPayload(payload: Record<string, any>): boolean;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { BlocksInterface } from "./shared";
|
|
2
|
+
import { LogLevel } from "./shared";
|
|
3
|
+
export interface SlackBotConfigOptions {
|
|
4
|
+
botToken: string;
|
|
5
|
+
defaultChannelId?: string;
|
|
6
|
+
enableAlerts: boolean;
|
|
7
|
+
}
|
|
8
|
+
interface SlackBot {
|
|
9
|
+
log(label: string, data: any, channelId?: string): Promise<null | undefined>;
|
|
10
|
+
logBlockMessage(label: string, objectData: BlocksInterface[], errorType?: LogLevel, channelId?: string): Promise<null | undefined>;
|
|
11
|
+
rawBody(payload: Record<string, any>, channelId?: string): Promise<null | undefined>;
|
|
12
|
+
}
|
|
13
|
+
export declare function slackBotConfig(config: SlackBotConfigOptions): void;
|
|
14
|
+
export declare const slackbot: SlackBot;
|
|
15
|
+
export {};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { LogLevel } from "./shared";
|
|
2
|
+
import type { BlocksInterface } from "./shared";
|
|
3
|
+
export interface SlackLogConfigOptions {
|
|
4
|
+
webhookUrl: string;
|
|
5
|
+
enableAlerts: boolean;
|
|
6
|
+
}
|
|
7
|
+
export declare function slackLogConfig(config: SlackLogConfigOptions): void;
|
|
8
|
+
export declare const slackWebhook: {
|
|
9
|
+
log(label: string, data: any): Promise<null | undefined>;
|
|
10
|
+
logBlockMessage(label: string, objectData: BlocksInterface[], errorType?: LogLevel): Promise<null | undefined>;
|
|
11
|
+
rawBody(payload: Record<string, any>): Promise<null | undefined>;
|
|
12
|
+
};
|