@goniglep57/node 1.0.0 â 1.0.1
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/index.js +1 -0
- package/package.json +1 -1
- package/slack.js +184 -0
package/index.js
CHANGED
package/package.json
CHANGED
package/slack.js
ADDED
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Slack notification module for error alerting across all services
|
|
3
|
+
*
|
|
4
|
+
* Usage:
|
|
5
|
+
* const { slack } = require('@goniglep57/node')
|
|
6
|
+
*
|
|
7
|
+
* // Configure once at startup
|
|
8
|
+
* slack.configure({
|
|
9
|
+
* webhookUrl: process.env.SLACK_ERROR_WEBHOOK,
|
|
10
|
+
* serviceName: 'tonomo-front-end',
|
|
11
|
+
* environment: process.env.NODE_ENV || 'development'
|
|
12
|
+
* })
|
|
13
|
+
*
|
|
14
|
+
* // Send error notifications
|
|
15
|
+
* await slack.error('Database connection failed', { userId: 123 })
|
|
16
|
+
* await slack.warn('Rate limit approaching', { current: 90, max: 100 })
|
|
17
|
+
* await slack.info('Deployment complete')
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
let config = null
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Configure the Slack module
|
|
24
|
+
* @param {Object} options
|
|
25
|
+
* @param {string} options.webhookUrl - Slack incoming webhook URL
|
|
26
|
+
* @param {string} options.serviceName - Name of the service (e.g., 'tonomo-front-end')
|
|
27
|
+
* @param {string} [options.environment='production'] - Environment name
|
|
28
|
+
*/
|
|
29
|
+
const configure = (options) => {
|
|
30
|
+
const { webhookUrl, serviceName, environment = 'production' } = options
|
|
31
|
+
|
|
32
|
+
if (!webhookUrl) {
|
|
33
|
+
console.warn('[slack] No webhook URL provided, notifications will be disabled')
|
|
34
|
+
config = null
|
|
35
|
+
return { configured: false }
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (!serviceName) {
|
|
39
|
+
throw new Error('slack.configure requires serviceName')
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
config = {
|
|
43
|
+
webhookUrl,
|
|
44
|
+
serviceName,
|
|
45
|
+
environment
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return { configured: true }
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Check if Slack is configured
|
|
53
|
+
*/
|
|
54
|
+
const isConfigured = () => config !== null
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Send a notification to Slack
|
|
58
|
+
* @param {string} level - 'error', 'warn', or 'info'
|
|
59
|
+
* @param {string} message - The message
|
|
60
|
+
* @param {Object} [context={}] - Additional context
|
|
61
|
+
*/
|
|
62
|
+
const send = async (level, message, context = {}) => {
|
|
63
|
+
if (!config) {
|
|
64
|
+
return { sent: false, reason: 'not configured' }
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const emoji = {
|
|
68
|
+
error: 'đ¨',
|
|
69
|
+
warn: 'â ī¸',
|
|
70
|
+
info: 'âšī¸'
|
|
71
|
+
}[level] || 'đĸ'
|
|
72
|
+
|
|
73
|
+
const color = {
|
|
74
|
+
error: '#dc3545',
|
|
75
|
+
warn: '#ffc107',
|
|
76
|
+
info: '#17a2b8'
|
|
77
|
+
}[level] || '#6c757d'
|
|
78
|
+
|
|
79
|
+
try {
|
|
80
|
+
const contextLines = Object.entries(context)
|
|
81
|
+
.filter(([_, v]) => v !== undefined && v !== null)
|
|
82
|
+
.map(([key, value]) => {
|
|
83
|
+
const displayValue = typeof value === 'object'
|
|
84
|
+
? JSON.stringify(value).substring(0, 200)
|
|
85
|
+
: String(value).substring(0, 200)
|
|
86
|
+
return `âĸ *${key}:* ${displayValue}`
|
|
87
|
+
})
|
|
88
|
+
.join('\n')
|
|
89
|
+
|
|
90
|
+
const payload = {
|
|
91
|
+
attachments: [
|
|
92
|
+
{
|
|
93
|
+
color,
|
|
94
|
+
blocks: [
|
|
95
|
+
{
|
|
96
|
+
type: 'header',
|
|
97
|
+
text: {
|
|
98
|
+
type: 'plain_text',
|
|
99
|
+
text: `${emoji} ${config.serviceName} - ${level.toUpperCase()}`,
|
|
100
|
+
emoji: true
|
|
101
|
+
}
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
type: 'section',
|
|
105
|
+
text: {
|
|
106
|
+
type: 'mrkdwn',
|
|
107
|
+
text: `*Message:*\n${message}`
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
]
|
|
111
|
+
}
|
|
112
|
+
]
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
if (contextLines) {
|
|
116
|
+
payload.attachments[0].blocks.push({
|
|
117
|
+
type: 'section',
|
|
118
|
+
text: {
|
|
119
|
+
type: 'mrkdwn',
|
|
120
|
+
text: `*Context:*\n${contextLines}`
|
|
121
|
+
}
|
|
122
|
+
})
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
payload.attachments[0].blocks.push({
|
|
126
|
+
type: 'context',
|
|
127
|
+
elements: [
|
|
128
|
+
{
|
|
129
|
+
type: 'mrkdwn',
|
|
130
|
+
text: `đ ${config.environment} | â° ${new Date().toISOString()}`
|
|
131
|
+
}
|
|
132
|
+
]
|
|
133
|
+
})
|
|
134
|
+
|
|
135
|
+
const response = await fetch(config.webhookUrl, {
|
|
136
|
+
method: 'POST',
|
|
137
|
+
headers: { 'Content-Type': 'application/json' },
|
|
138
|
+
body: JSON.stringify(payload)
|
|
139
|
+
})
|
|
140
|
+
|
|
141
|
+
if (!response.ok) {
|
|
142
|
+
console.error('[slack] Failed to send notification:', response.status)
|
|
143
|
+
return { sent: false, reason: `HTTP ${response.status}` }
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
return { sent: true }
|
|
147
|
+
} catch (err) {
|
|
148
|
+
// Don't let Slack errors break the main flow
|
|
149
|
+
console.error('[slack] Error sending notification:', err.message)
|
|
150
|
+
return { sent: false, reason: err.message }
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Send an error notification
|
|
156
|
+
*/
|
|
157
|
+
const error = (message, context = {}) => send('error', message, context)
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Send a warning notification
|
|
161
|
+
*/
|
|
162
|
+
const warn = (message, context = {}) => send('warn', message, context)
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Send an info notification
|
|
166
|
+
*/
|
|
167
|
+
const info = (message, context = {}) => send('info', message, context)
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Reset configuration (useful for testing)
|
|
171
|
+
*/
|
|
172
|
+
const reset = () => {
|
|
173
|
+
config = null
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
module.exports = {
|
|
177
|
+
configure,
|
|
178
|
+
isConfigured,
|
|
179
|
+
send,
|
|
180
|
+
error,
|
|
181
|
+
warn,
|
|
182
|
+
info,
|
|
183
|
+
reset
|
|
184
|
+
}
|