@pulsealarm/pulse-event-sdk 0.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.
@@ -0,0 +1,28 @@
1
+ name: Publish Package to npmjs
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - main
7
+
8
+ jobs:
9
+ publish:
10
+ runs-on: ubuntu-latest
11
+ steps:
12
+ - name: Checkout Repository
13
+ uses: actions/checkout@v4
14
+
15
+ - name: Setup Node.js
16
+ uses: actions/setup-node@v4
17
+ with:
18
+ node-version: '20'
19
+ registry-url: 'https://registry.npmjs.org'
20
+
21
+ - name: Install Dependencies
22
+ run: npm install
23
+
24
+ - name: Publish to NPM
25
+ # 'npm publish' komutu otomatik olarak .npmrc içindeki token'ı kullanır
26
+ run: npm publish --access public
27
+ env:
28
+ NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
package/README.md ADDED
@@ -0,0 +1,326 @@
1
+ # Pulse Event SDK (JavaScript)
2
+
3
+ Framework-agnostic, non-blocking event and error tracking SDK for:
4
+ - Browser apps
5
+ - Node.js services
6
+ - React / Vue
7
+ - Express / Fastify
8
+ - Next.js / Nuxt
9
+ - Custom integrations
10
+
11
+ ## Features
12
+
13
+ - Non-blocking event delivery (queue + background flush)
14
+ - Dynamic webhook endpoint updates (`setEndpoint`, `setWebhookCredentials`)
15
+ - Manual custom event tracking
16
+ - Manual exception capture (`captureException`, `captureError`)
17
+ - Global runtime error handlers (browser + Node.js)
18
+ - Automatic `session_id` generation when missing
19
+ - Lightweight adapters for modern frameworks
20
+ - TypeScript support
21
+ - Fully tested
22
+ - 100% code coverage
23
+
24
+ ## Installation
25
+
26
+ ```bash
27
+ npm install
28
+ ```
29
+
30
+ ## Quick Start (Core SDK)
31
+
32
+ ```js
33
+ import { createPulseClient } from "pulse-event-sdk";
34
+
35
+ const pulse = createPulseClient({
36
+ baseUrl: "https://pulsealarm.dev",
37
+ projectCode: "PUL",
38
+ webhookToken: "1b6ab14728893skXd2e4926f16869290c1c44ddz3xb3",
39
+ defaults: {
40
+ environment: "production",
41
+ app_version: "2.3.1",
42
+ platform: "web"
43
+ }
44
+ });
45
+
46
+ pulse.track({
47
+ title: "Payment failed for order #1234",
48
+ description: "Stripe returned card_declined error during checkout",
49
+ level: "error",
50
+ type: "exception",
51
+ timestamp: "2026-02-11T14:30:00Z",
52
+ data: {
53
+ stack_trace: "Error: card_declined\n at processPayment (checkout.js:42)",
54
+ user_agent: "Mozilla/5.0...",
55
+ any_key: "any_value"
56
+ },
57
+ session_id: "sess_abc123",
58
+ customer_id: "cust_456",
59
+ ip_address: "203.0.113.10",
60
+ request_url: "https://myapp.com/api/checkout",
61
+ country: "Turkey",
62
+ country_code: "TR",
63
+ tags: ["payment", "critical-path"],
64
+ revenue: {
65
+ currency: "USD",
66
+ price: 49.99
67
+ },
68
+ group: true,
69
+ resolved: false
70
+ });
71
+ ```
72
+
73
+ ## Dynamic Endpoint
74
+
75
+ ```js
76
+ import { buildWebhookEndpoint } from "pulse-event-sdk";
77
+
78
+ pulse.setEndpoint(
79
+ buildWebhookEndpoint("https://pulsealarm.dev", "PUL", "new-token")
80
+ );
81
+ ```
82
+
83
+ ```js
84
+ pulse.setWebhookCredentials("PUL", "new-token");
85
+ ```
86
+
87
+ ## Webhook Credentials (Project + Token)
88
+
89
+ - `projectCode` is your project identifier (example: `PUL`).
90
+ - `webhookToken` is your webhook token.
91
+ - SDK builds endpoint as: `${baseUrl}/webhook/${projectCode}/${webhookToken}`.
92
+
93
+ ```js
94
+ import { createPulseClient, buildWebhookEndpoint } from "pulse-event-sdk";
95
+
96
+ const endpoint = buildWebhookEndpoint(
97
+ "https://pulsealarm.dev",
98
+ "PUL",
99
+ "1b6ab14728893skXd2e4926f16869290c1c44ddz3xb3"
100
+ );
101
+
102
+ const pulse = createPulseClient({
103
+ projectCode: "PUL",
104
+ webhookToken: "1b6ab14728893skXd2e4926f16869290c1c44ddz3xb3"
105
+ });
106
+ ```
107
+
108
+ ## Session Tracking
109
+
110
+ - If `session_id` is not provided, SDK auto-generates `sess_*`.
111
+ - In browsers, generated session ID is reused in the same tab via `sessionStorage`.
112
+ - If you pass `session_id` explicitly in an event, it is preserved.
113
+
114
+ ```js
115
+ console.log(pulse.getSessionId());
116
+ ```
117
+
118
+ ## Custom Event Tracking
119
+
120
+ ```js
121
+ pulse.event("checkout.step.completed", {
122
+ level: "info",
123
+ tags: ["checkout"]
124
+ });
125
+ ```
126
+
127
+ ## Manual Exception Capture
128
+
129
+ ```js
130
+ try {
131
+ doPayment();
132
+ } catch (error) {
133
+ pulse.captureException(error, {
134
+ tags: ["payment"],
135
+ request_url: window.location.href
136
+ });
137
+ }
138
+ ```
139
+
140
+ ## Global Error Capture
141
+
142
+ ```js
143
+ pulse.installGlobalHandlers();
144
+ ```
145
+
146
+ - Browser: `error` and `unhandledrejection`
147
+ - Node.js: `uncaughtException` and `unhandledRejection`
148
+
149
+ ## Runtime-Specific Usage
150
+
151
+ ### Node.js service
152
+
153
+ ```js
154
+ import { createPulseClient } from "pulse-event-sdk";
155
+
156
+ const pulse = createPulseClient({
157
+ baseUrl: "https://pulsealarm.dev",
158
+ projectCode: "PUL",
159
+ webhookToken: "1b6ab14728893skXd2e4926f16869290c1c44ddz3xb3",
160
+ defaults: { platform: "server", environment: "production" }
161
+ });
162
+
163
+ pulse.installGlobalHandlers();
164
+ pulse.event("worker.started");
165
+
166
+ process.on("SIGTERM", () => {
167
+ pulse.close();
168
+ process.exit(0);
169
+ });
170
+ ```
171
+
172
+ ### Browser app
173
+
174
+ ```js
175
+ const pulse = createPulseClient({
176
+ baseUrl: "https://pulsealarm.dev",
177
+ projectCode: "PUL",
178
+ webhookToken: "1b6ab14728893skXd2e4926f16869290c1c44ddz3xb3",
179
+ defaults: { platform: "web" }
180
+ });
181
+
182
+ pulse.installGlobalHandlers();
183
+ ```
184
+
185
+ ## React Integration
186
+
187
+ ```jsx
188
+ import { usePulse, PulseErrorBoundary, withPulseErrorBoundary } from "pulse-event-sdk/react";
189
+ ```
190
+
191
+ Error boundary component:
192
+
193
+ ```jsx
194
+ <PulseErrorBoundary pulse={pulse} fallback={<div>Something failed</div>}>
195
+ <Checkout />
196
+ </PulseErrorBoundary>
197
+ ```
198
+
199
+ HOC wrapper:
200
+
201
+ ```jsx
202
+ const SafeCheckout = withPulseErrorBoundary(Checkout, { pulse });
203
+ ```
204
+
205
+ ## Vue Integration
206
+
207
+ ```js
208
+ import { createPulseVuePlugin } from "pulse-event-sdk/vue";
209
+
210
+ app.use(
211
+ createPulseVuePlugin({
212
+ baseUrl: "https://pulsealarm.dev",
213
+ projectCode: "PUL",
214
+ webhookToken: "1b6ab14728893skXd2e4926f16869290c1c44ddz3xb3",
215
+ defaults: { platform: "web", environment: "production" }
216
+ })
217
+ );
218
+ ```
219
+
220
+ The plugin also configures `app.config.errorHandler` automatically.
221
+
222
+ ## Express Integration
223
+
224
+ ```js
225
+ import {
226
+ createExpressPulseRequestMiddleware,
227
+ createExpressPulseErrorMiddleware
228
+ } from "pulse-event-sdk/express";
229
+
230
+ app.use(createExpressPulseRequestMiddleware(pulse));
231
+ app.use(createExpressPulseErrorMiddleware(pulse));
232
+ ```
233
+
234
+ ## Fastify Integration
235
+
236
+ ```js
237
+ import { createFastifyPulsePlugin } from "pulse-event-sdk/fastify";
238
+
239
+ await fastify.register(createFastifyPulsePlugin(pulse));
240
+ ```
241
+
242
+ ## Next.js Integration
243
+
244
+ Pages router API handler:
245
+
246
+ ```js
247
+ import { withPulseApiHandler } from "pulse-event-sdk/next";
248
+
249
+ export default withPulseApiHandler(async function handler(req, res) {
250
+ throw new Error("boom");
251
+ }, pulse);
252
+ ```
253
+
254
+ App router route handler:
255
+
256
+ ```js
257
+ import { withPulseRouteHandler } from "pulse-event-sdk/next";
258
+
259
+ export const POST = withPulseRouteHandler(async function POST(request) {
260
+ throw new Error("boom");
261
+ }, pulse);
262
+ ```
263
+
264
+ ## Nuxt Integration
265
+
266
+ ```js
267
+ import { createNuxtPulsePlugin } from "pulse-event-sdk/nuxt";
268
+
269
+ export default defineNuxtPlugin((nuxtApp) => {
270
+ createNuxtPulsePlugin(pulse)(nuxtApp);
271
+ });
272
+ ```
273
+
274
+ ## Event Payload Schema
275
+
276
+ - `title` (required): `string`
277
+ - `description`: `string`
278
+ - `level`: `error | warning | info | fatal | debug`
279
+ - `type`: `exception | event | log`
280
+ - `timestamp`: ISO-8601 `string`
281
+ - `data`: `object`
282
+ - `session_id`: `string`
283
+ - `customer_id`: `string`
284
+ - `ip_address`: `string`
285
+ - `request_url`: `string`
286
+ - `country`: `string`
287
+ - `country_code`: `string`
288
+ - `tags`: `string[]`
289
+ - `revenue`: `{ currency: string, price: number }`
290
+ - `group`: `boolean`
291
+ - `resolved`: `boolean`
292
+ - `environment`: `production | staging | development | test`
293
+ - `app_version`: `string`
294
+ - `platform`: `web | ios | android | server | desktop`
295
+
296
+ ## CLI Testing
297
+
298
+ Run all tests:
299
+
300
+ ```bash
301
+ npm test
302
+ ```
303
+
304
+ Run Node quickstart example:
305
+
306
+ ```bash
307
+ node ./examples/node-quickstart.js
308
+ ```
309
+
310
+ Send raw payload to webhook:
311
+
312
+ ```bash
313
+ PROJECT_CODE="PUL"
314
+ WEBHOOK_TOKEN="1b6ab14728893skXd2e4926f16869290c1c44ddz3xb3"
315
+ BASE_URL="https://pulsealarm.dev"
316
+
317
+ curl -X POST "${BASE_URL}/webhook/${PROJECT_CODE}/${WEBHOOK_TOKEN}" \
318
+ -H "Content-Type: application/json" \
319
+ -d '{"title":"CLI test event"}'
320
+ ```
321
+
322
+ ## Notes
323
+
324
+ - `track()` is non-blocking: events go to queue, then flush in background. 1000 events per minute.
325
+ - Browser attempts best-effort flush via `sendBeacon` on page exit/hidden state.
326
+ - In Node.js, call `pulse.close()` before shutdown for cleaner flush behavior.
@@ -0,0 +1,49 @@
1
+ import { createPulseClient } from "../src/index.js";
2
+
3
+ const pulse = createPulseClient({
4
+ baseUrl: "https://pulsealarm.dev",
5
+ projectCode: "PUL",
6
+ webhookToken: "1b6ab14728893skXd2e4926f16869290c1c44ddz3xb3",
7
+ defaults: {
8
+ environment: "production",
9
+ app_version: "2.3.1",
10
+ platform: "web"
11
+ }
12
+ });
13
+
14
+ pulse.installGlobalHandlers();
15
+
16
+ pulse.track({
17
+ title: "Payment failed for order #1234",
18
+ description: "Stripe returned card_declined error during checkout",
19
+ level: "error",
20
+ type: "exception",
21
+ data: {
22
+ stack_trace: "Error: card_declined\n at processPayment (checkout.js:42)",
23
+ user_agent: navigator.userAgent,
24
+ any_key: "any_value"
25
+ },
26
+ session_id: "sess_abc123",
27
+ customer_id: "cust_456",
28
+ request_url: window.location.href,
29
+ country: "Turkey",
30
+ country_code: "TR",
31
+ tags: ["payment", "critical-path"],
32
+ revenue: {
33
+ currency: "USD",
34
+ price: 49.99
35
+ },
36
+ group: true,
37
+ resolved: false
38
+ });
39
+
40
+ try {
41
+ throw new Error("Checkout service unavailable");
42
+ } catch (error) {
43
+ pulse.captureException(error, {
44
+ tags: ["checkout"],
45
+ data: {
46
+ order_id: 1234
47
+ }
48
+ });
49
+ }
@@ -0,0 +1,37 @@
1
+ import { createPulseClient } from "../src/index.js";
2
+
3
+ const pulse = createPulseClient({
4
+ baseUrl: "https://pulsealarm.dev",
5
+ projectCode: "PUL",
6
+ webhookToken: "1b6ab14728893skXd2e4926f16869290c1c44ddz3xb3",
7
+ defaults: {
8
+ environment: "production",
9
+ app_version: "2.3.1",
10
+ platform: "server"
11
+ },
12
+ debug: true
13
+ });
14
+
15
+ pulse.installGlobalHandlers();
16
+
17
+ pulse.event("worker.started", {
18
+ level: "info",
19
+ tags: ["worker"]
20
+ });
21
+
22
+ try {
23
+ throw new Error("Background job failed");
24
+ } catch (error) {
25
+ pulse.captureError(error, {
26
+ request_url: "/jobs/reconcile",
27
+ session_id: "sess_worker_1",
28
+ customer_id: "cust_456",
29
+ data: {
30
+ job_name: "reconcile"
31
+ }
32
+ });
33
+ }
34
+
35
+ setTimeout(() => {
36
+ pulse.close();
37
+ }, 1500);
@@ -0,0 +1,33 @@
1
+ import { useEffect } from "react";
2
+ import { usePulse } from "pulse-event-sdk/react";
3
+
4
+ export default function CheckoutPage() {
5
+ const pulse = usePulse({
6
+ baseUrl: "https://pulsealarm.dev",
7
+ projectCode: "PUL",
8
+ webhookToken: "1b6ab14728893skXd2e4926f16869290c1c44ddz3xb3",
9
+ defaults: { platform: "web", environment: "production" }
10
+ });
11
+
12
+ useEffect(() => {
13
+ pulse.event("checkout.page_opened", { level: "info", tags: ["checkout"] });
14
+ pulse.installGlobalHandlers();
15
+ return () => pulse.close();
16
+ }, [pulse]);
17
+
18
+ return (
19
+ <button
20
+ onClick={() => {
21
+ try {
22
+ throw new Error("Payment form validation failed");
23
+ } catch (error) {
24
+ pulse.captureException(error, {
25
+ tags: ["payment", "validation"]
26
+ });
27
+ }
28
+ }}
29
+ >
30
+ Pay
31
+ </button>
32
+ );
33
+ }
@@ -0,0 +1,16 @@
1
+ import { createApp } from "vue";
2
+ import { createPulseVuePlugin } from "pulse-event-sdk/vue";
3
+ import App from "./App.vue";
4
+
5
+ const app = createApp(App);
6
+
7
+ app.use(
8
+ createPulseVuePlugin({
9
+ baseUrl: "https://pulsealarm.dev",
10
+ projectCode: "PUL",
11
+ webhookToken: "1b6ab14728893skXd2e4926f16869290c1c44ddz3xb3",
12
+ defaults: { platform: "web", environment: "production" }
13
+ })
14
+ );
15
+
16
+ app.mount("#app");
package/package.json ADDED
@@ -0,0 +1,28 @@
1
+ {
2
+ "name": "@pulsealarm/pulse-event-sdk",
3
+ "version": "0.1.0",
4
+ "description": "Non-blocking event/error SDK for browser and Node.js",
5
+ "type": "module",
6
+ "main": "./src/index.js",
7
+ "exports": {
8
+ ".": "./src/index.js",
9
+ "./react": "./src/integrations/react.js",
10
+ "./vue": "./src/integrations/vue.js",
11
+ "./express": "./src/integrations/express.js",
12
+ "./fastify": "./src/integrations/fastify.js",
13
+ "./next": "./src/integrations/next.js",
14
+ "./nuxt": "./src/integrations/nuxt.js"
15
+ },
16
+ "scripts": {
17
+ "check": "node ./examples/node-quickstart.js",
18
+ "test": "node --test"
19
+ },
20
+ "keywords": [
21
+ "event",
22
+ "monitoring",
23
+ "sdk",
24
+ "error-tracking",
25
+ "javascript"
26
+ ],
27
+ "license": "MIT"
28
+ }