@notifykit/sdk 1.2.0 → 2.0.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 +100 -26
- package/dist/client.d.ts +3 -1
- package/dist/client.js +103 -52
- package/package.json +3 -5
package/README.md
CHANGED
|
@@ -40,7 +40,7 @@ const webhookJob = await client.sendWebhook({
|
|
|
40
40
|
|
|
41
41
|
Emails are queued immediately (HTTP 202 Accepted) and delivered asynchronously. Use [getJob](#tracking-jobs) to confirm delivery.
|
|
42
42
|
|
|
43
|
-
> **Note:** On the **Free plan**, emails send from NotifyKit's shared SendGrid account (`noreply@notifykit.dev`). On **Indie/Startup plans**, connect your own SendGrid API key in the dashboard before sending emails.
|
|
43
|
+
> **Note:** On the **Free plan**, emails send from NotifyKit's shared SendGrid account (`noreply@notifykit.dev`). On **Indie/Startup plans**, connect your own SendGrid, Resend, or Postmark API key in the dashboard before sending emails.
|
|
44
44
|
|
|
45
45
|
### Basic Email
|
|
46
46
|
|
|
@@ -59,7 +59,7 @@ await client.sendEmail({
|
|
|
59
59
|
to: "user@example.com",
|
|
60
60
|
subject: "Welcome",
|
|
61
61
|
body: "<h1>Hello</h1>",
|
|
62
|
-
from: "hello@em.yourapp.com", // Must be a verified domain
|
|
62
|
+
from: "hello@em.yourapp.com", // Must be a verified sending domain
|
|
63
63
|
});
|
|
64
64
|
```
|
|
65
65
|
|
|
@@ -87,16 +87,18 @@ await client.sendEmail({
|
|
|
87
87
|
provider: "SENDGRID",
|
|
88
88
|
});
|
|
89
89
|
|
|
90
|
-
// Force
|
|
90
|
+
// Force Postmark first, then Resend if Postmark fails. No other providers tried.
|
|
91
91
|
await client.sendEmail({
|
|
92
92
|
to: "user@example.com",
|
|
93
93
|
subject: "Receipt",
|
|
94
94
|
body: "<h1>Thanks</h1>",
|
|
95
|
-
provider: "
|
|
95
|
+
provider: "POSTMARK",
|
|
96
96
|
fallback: "RESEND",
|
|
97
97
|
});
|
|
98
98
|
```
|
|
99
99
|
|
|
100
|
+
Valid provider values: `"SENDGRID"` | `"RESEND"` | `"POSTMARK"`
|
|
101
|
+
|
|
100
102
|
**Validation:**
|
|
101
103
|
|
|
102
104
|
| Case | Outcome |
|
|
@@ -104,6 +106,7 @@ await client.sendEmail({
|
|
|
104
106
|
| `fallback` set without `provider` | `400 Bad Request` |
|
|
105
107
|
| `provider` equals `fallback` | `400 Bad Request` |
|
|
106
108
|
| Requested `provider` or `fallback` not configured for your account | `400 Bad Request` |
|
|
109
|
+
| Either provider used on Free plan | `400 Bad Request` |
|
|
107
110
|
|
|
108
111
|
Forced routing is a contract: NotifyKit does **not** retry through providers you didn't authorize. The routing fields persist with the job, so manual or automatic retries replay the same attempt set.
|
|
109
112
|
|
|
@@ -130,7 +133,7 @@ await client.sendEmail({
|
|
|
130
133
|
|
|
131
134
|
## Sending Webhooks
|
|
132
135
|
|
|
133
|
-
Webhooks are queued immediately (HTTP 202 Accepted) and delivered asynchronously with automatic retries on failure.
|
|
136
|
+
Webhooks are queued immediately (HTTP 202 Accepted) and delivered asynchronously with automatic retries on failure. Payloads are capped at **10kb**.
|
|
134
137
|
|
|
135
138
|
### Basic Webhook
|
|
136
139
|
|
|
@@ -152,7 +155,6 @@ await client.sendWebhook({
|
|
|
152
155
|
method: "POST",
|
|
153
156
|
payload: { orderId: "12345" },
|
|
154
157
|
headers: {
|
|
155
|
-
"X-Webhook-Secret": process.env.WEBHOOK_SECRET!,
|
|
156
158
|
"X-Event-Type": "order.created",
|
|
157
159
|
},
|
|
158
160
|
idempotencyKey: "order-12345-webhook",
|
|
@@ -167,6 +169,50 @@ await client.sendWebhook({
|
|
|
167
169
|
|
|
168
170
|
---
|
|
169
171
|
|
|
172
|
+
## Webhook Signing
|
|
173
|
+
|
|
174
|
+
When a webhook signing secret is configured in your dashboard, NotifyKit signs every outgoing webhook delivery with HMAC-SHA256. Your receiving endpoint can verify this signature to confirm the request is genuine and hasn't been replayed.
|
|
175
|
+
|
|
176
|
+
**Headers sent with each delivery:**
|
|
177
|
+
|
|
178
|
+
| Header | Value |
|
|
179
|
+
| ----------------------- | ------------------------------ |
|
|
180
|
+
| `X-Webhook-Timestamp` | Unix timestamp (seconds) |
|
|
181
|
+
| `X-Webhook-Signature` | `t=<timestamp>,v1=<hex>` |
|
|
182
|
+
|
|
183
|
+
### Verifying Signatures
|
|
184
|
+
|
|
185
|
+
```typescript
|
|
186
|
+
import { verifyWebhookSignature } from "@notifykit/sdk";
|
|
187
|
+
|
|
188
|
+
app.post("/webhooks/notifykit", (req, res) => {
|
|
189
|
+
const valid = verifyWebhookSignature({
|
|
190
|
+
payload: req.rawBody, // raw string — NOT parsed JSON
|
|
191
|
+
timestamp: req.headers["x-webhook-timestamp"],
|
|
192
|
+
signature: req.headers["x-webhook-signature"],
|
|
193
|
+
secret: process.env.NOTIFYKIT_WEBHOOK_SECRET!,
|
|
194
|
+
tolerance: 300, // optional, default 300s (5 min)
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
if (!valid) return res.status(401).send("Invalid signature");
|
|
198
|
+
|
|
199
|
+
const event = req.body;
|
|
200
|
+
// handle event...
|
|
201
|
+
res.sendStatus(200);
|
|
202
|
+
});
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
> **Important:** Always use the **raw body string** (`req.rawBody`), not the parsed JSON object. Re-serializing a parsed object can produce a different byte sequence and will cause verification to fail.
|
|
206
|
+
|
|
207
|
+
The `tolerance` option rejects requests older than N seconds, protecting against replay attacks. Set it to `0` to disable the time check entirely.
|
|
208
|
+
|
|
209
|
+
**`verifyWebhookSignature` returns `false` (never throws) when:**
|
|
210
|
+
- The signature header is missing or malformed
|
|
211
|
+
- The timestamp is outside the tolerance window
|
|
212
|
+
- The HMAC digest does not match
|
|
213
|
+
|
|
214
|
+
---
|
|
215
|
+
|
|
170
216
|
## Tracking Jobs
|
|
171
217
|
|
|
172
218
|
Every notification returns a job ID you can use to track delivery status.
|
|
@@ -209,7 +255,7 @@ for (const log of status.deliveryLogs) {
|
|
|
209
255
|
}
|
|
210
256
|
```
|
|
211
257
|
|
|
212
|
-
For successful sends, the last entry's `usedProvider` is the provider that delivered. For failures, it's the last provider attempted. Webhook jobs return
|
|
258
|
+
For successful sends, the last entry's `usedProvider` is the provider that delivered. For failures, it's the last provider attempted. Webhook jobs and Free plan jobs return `null` for `usedProvider`.
|
|
213
259
|
|
|
214
260
|
### List Jobs with Filters
|
|
215
261
|
|
|
@@ -217,8 +263,8 @@ For successful sends, the last entry's `usedProvider` is the provider that deliv
|
|
|
217
263
|
const result = await client.listJobs({
|
|
218
264
|
page: 1,
|
|
219
265
|
limit: 20,
|
|
220
|
-
type: "email",
|
|
221
|
-
status: "failed", //
|
|
266
|
+
type: "email", // 'email' | 'webhook'
|
|
267
|
+
status: "failed", // 'pending' | 'processing' | 'completed' | 'failed'
|
|
222
268
|
});
|
|
223
269
|
|
|
224
270
|
console.log(`Total: ${result.pagination.total} jobs`);
|
|
@@ -266,27 +312,49 @@ try {
|
|
|
266
312
|
|
|
267
313
|
if (error.isStatus(400)) console.error("Bad request:", error.message);
|
|
268
314
|
if (error.isStatus(401)) console.error("Invalid API key");
|
|
269
|
-
if (error.isStatus(403))
|
|
270
|
-
console.error("Quota or permission error:", error.message);
|
|
315
|
+
if (error.isStatus(403)) console.error("Quota or permission error:", error.message);
|
|
271
316
|
if (error.isStatus(409)) console.error("Duplicate idempotency key");
|
|
272
|
-
if (error.isStatus(429))
|
|
317
|
+
if (error.isStatus(429)) {
|
|
318
|
+
console.error("Rate limit exceeded");
|
|
319
|
+
if (error.retryAfter) console.log(`Retry after ${error.retryAfter}s`);
|
|
320
|
+
}
|
|
273
321
|
}
|
|
274
322
|
}
|
|
275
323
|
```
|
|
276
324
|
|
|
325
|
+
### Automatic Retries & Timeouts
|
|
326
|
+
|
|
327
|
+
The SDK retries transient failures automatically:
|
|
328
|
+
|
|
329
|
+
- Retries up to **2 times** (3 attempts total) on **5xx**, **429**, and network errors, with backoff (~200ms → ~500ms).
|
|
330
|
+
- On **429**, it waits for the server's `retryAfter` (capped at 10s) before retrying.
|
|
331
|
+
- **Other 4xx errors** (e.g. 400, 401, 409) fail immediately — they are never retried.
|
|
332
|
+
- Non-idempotent requests (`sendEmail`, `sendWebhook`, `retryJob`) are **not** retried on a timeout or dropped connection, to avoid duplicate sends.
|
|
333
|
+
- Every request times out after **10 seconds**.
|
|
334
|
+
|
|
335
|
+
> This is distinct from NotifyKit's server-side **webhook delivery** retries (see [Sending Webhooks](#sending-webhooks)), which control how delivery to your endpoint is re-attempted.
|
|
336
|
+
|
|
277
337
|
---
|
|
278
338
|
|
|
279
339
|
## API Reference
|
|
280
340
|
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
|
284
|
-
|
|
|
285
|
-
| `
|
|
286
|
-
| `
|
|
287
|
-
| `
|
|
288
|
-
| `
|
|
289
|
-
| `
|
|
341
|
+
### `NotifyKitClient` methods
|
|
342
|
+
|
|
343
|
+
| Method | Description | Returns |
|
|
344
|
+
| ------------------------------- | ------------------------------- | ------------------------------- |
|
|
345
|
+
| `sendEmail(options)` | Send an email notification | `Promise<JobResponse>` |
|
|
346
|
+
| `sendWebhook(options)` | Send a webhook notification | `Promise<JobResponse>` |
|
|
347
|
+
| `getJob(jobId)` | Get job status and delivery logs | `Promise<JobStatus>` |
|
|
348
|
+
| `listJobs(options?)` | List jobs with optional filters | `Promise<{ data, pagination }>` |
|
|
349
|
+
| `retryJob(jobId)` | Retry a failed job | `Promise<RetryJobResponse>` |
|
|
350
|
+
| `ping()` | Test API connection | `Promise<string>` |
|
|
351
|
+
| `getApiInfo()` | Get API version info | `Promise<ApiInfo>` |
|
|
352
|
+
|
|
353
|
+
### Standalone utilities
|
|
354
|
+
|
|
355
|
+
| Function | Description |
|
|
356
|
+
| ------------------------------- | -------------------------------------------------- |
|
|
357
|
+
| `verifyWebhookSignature(options)` | Verify HMAC-SHA256 signature on incoming webhooks |
|
|
290
358
|
|
|
291
359
|
### TypeScript Types
|
|
292
360
|
|
|
@@ -296,7 +364,13 @@ import type {
|
|
|
296
364
|
SendEmailOptions,
|
|
297
365
|
SendWebhookOptions,
|
|
298
366
|
JobResponse,
|
|
367
|
+
JobStatus,
|
|
368
|
+
JobSummary,
|
|
369
|
+
DeliveryLog,
|
|
370
|
+
RetryJobResponse,
|
|
299
371
|
ApiInfo,
|
|
372
|
+
EmailProvider,
|
|
373
|
+
VerifyWebhookSignatureOptions,
|
|
300
374
|
} from "@notifykit/sdk";
|
|
301
375
|
```
|
|
302
376
|
|
|
@@ -304,11 +378,11 @@ import type {
|
|
|
304
378
|
|
|
305
379
|
## Plans
|
|
306
380
|
|
|
307
|
-
| Plan | Price
|
|
308
|
-
| ------- |
|
|
309
|
-
| Free | $0
|
|
310
|
-
| Indie | $
|
|
311
|
-
| Startup | $
|
|
381
|
+
| Plan | Price | Webhooks/month | Emails/month | Rate limit |
|
|
382
|
+
| ------- | ------- | -------------- | -------------------------- | ------------ |
|
|
383
|
+
| Free | $0 | 100 (shared) | 100 (shared with webhooks) | 5 req/min |
|
|
384
|
+
| Indie | $5/mo | 4,000 | Unlimited (via your key) | 50 req/min |
|
|
385
|
+
| Startup | $10/mo | 15,000 | Unlimited (via your key) | 200 req/min |
|
|
312
386
|
|
|
313
387
|
---
|
|
314
388
|
|
package/dist/client.d.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { NotifyKitConfig, SendEmailOptions, SendWebhookOptions, JobResponse, JobStatus, JobSummary, ApiInfo, PaginationMeta, RetryJobResponse } from './types';
|
|
2
2
|
export declare class NotifyKitClient {
|
|
3
|
-
private
|
|
3
|
+
private readonly baseUrl;
|
|
4
|
+
private readonly headers;
|
|
4
5
|
constructor(config: NotifyKitConfig);
|
|
6
|
+
private request;
|
|
5
7
|
/** Test API connection */
|
|
6
8
|
ping(): Promise<string>;
|
|
7
9
|
/** Get API information */
|
package/dist/client.js
CHANGED
|
@@ -1,94 +1,145 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
3
|
exports.NotifyKitClient = void 0;
|
|
7
|
-
const axios_1 = __importDefault(require("axios"));
|
|
8
4
|
const errors_1 = require("./errors");
|
|
5
|
+
/** Abort a request that hasn't responded within this window. */
|
|
6
|
+
const TIMEOUT_MS = 10000;
|
|
7
|
+
/** Backoff delays between retries; length also caps the retry count (2 retries / 3 attempts). */
|
|
8
|
+
const RETRY_DELAYS_MS = [200, 500];
|
|
9
|
+
/** Upper bound for a server-provided Retry-After so a caller can't be stalled indefinitely. */
|
|
10
|
+
const MAX_RETRY_AFTER_MS = 10000;
|
|
11
|
+
/**
|
|
12
|
+
* Methods we can safely re-send after a transport failure (timeout / dropped connection).
|
|
13
|
+
* A timed-out POST may already have been processed by the server, so retrying it could
|
|
14
|
+
* duplicate a notification — only idempotent methods are retried on transport errors.
|
|
15
|
+
*/
|
|
16
|
+
const IDEMPOTENT_METHODS = new Set(['GET', 'HEAD']);
|
|
17
|
+
function sleep(ms) {
|
|
18
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
19
|
+
}
|
|
20
|
+
/** Transient server states worth retrying regardless of HTTP method. */
|
|
21
|
+
function isRetryableStatus(status) {
|
|
22
|
+
return status >= 500 || status === 429;
|
|
23
|
+
}
|
|
24
|
+
function describeTransportError(err) {
|
|
25
|
+
if (err instanceof Error && err.name === 'TimeoutError')
|
|
26
|
+
return 'Request timed out';
|
|
27
|
+
if (err instanceof Error)
|
|
28
|
+
return err.message;
|
|
29
|
+
return 'Network error occurred';
|
|
30
|
+
}
|
|
31
|
+
/** Build a NotifyKitError from a non-OK (or success:false) response body. */
|
|
32
|
+
function toError(status, statusText, data) {
|
|
33
|
+
let message = statusText || 'Request failed';
|
|
34
|
+
let errors;
|
|
35
|
+
let retryAfter;
|
|
36
|
+
if (data) {
|
|
37
|
+
const detail = data.error ?? data.message;
|
|
38
|
+
if (Array.isArray(detail)) {
|
|
39
|
+
errors = detail;
|
|
40
|
+
message = data.error ? detail.join(', ') : 'Validation failed';
|
|
41
|
+
}
|
|
42
|
+
else if (detail != null) {
|
|
43
|
+
message = String(detail);
|
|
44
|
+
}
|
|
45
|
+
if (status === 429 && typeof data.retryAfter === 'number') {
|
|
46
|
+
retryAfter = data.retryAfter;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return new errors_1.NotifyKitError(message, status, data, errors, retryAfter);
|
|
50
|
+
}
|
|
9
51
|
class NotifyKitClient {
|
|
10
52
|
constructor(config) {
|
|
11
53
|
if (!config.apiKey) {
|
|
12
54
|
throw new Error('API key is required');
|
|
13
55
|
}
|
|
14
|
-
this.
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
56
|
+
this.baseUrl = (config.baseUrl ?? 'https://api.notifykit.dev').replace(/\/$/, '');
|
|
57
|
+
this.headers = {
|
|
58
|
+
'X-API-Key': config.apiKey,
|
|
59
|
+
'Content-Type': 'application/json',
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
async request(method, path, body) {
|
|
63
|
+
const retryTransport = IDEMPOTENT_METHODS.has(method);
|
|
64
|
+
for (let attempt = 0;; attempt++) {
|
|
65
|
+
const isLastAttempt = attempt >= RETRY_DELAYS_MS.length;
|
|
66
|
+
// --- Send ---
|
|
67
|
+
let res;
|
|
68
|
+
try {
|
|
69
|
+
res = await fetch(`${this.baseUrl}${path}`, {
|
|
70
|
+
method,
|
|
71
|
+
headers: this.headers,
|
|
72
|
+
body: body !== undefined ? JSON.stringify(body) : undefined,
|
|
73
|
+
signal: AbortSignal.timeout(TIMEOUT_MS),
|
|
74
|
+
});
|
|
25
75
|
}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
let message = error.message;
|
|
32
|
-
let errors = null;
|
|
33
|
-
if (data?.error) {
|
|
34
|
-
if (Array.isArray(data.error)) {
|
|
35
|
-
errors = data.error;
|
|
36
|
-
message = data.error.join(', ');
|
|
37
|
-
}
|
|
38
|
-
else {
|
|
39
|
-
message = data.error;
|
|
40
|
-
}
|
|
76
|
+
catch (err) {
|
|
77
|
+
// Transport failure: retry only idempotent requests, and only while attempts remain.
|
|
78
|
+
if (retryTransport && !isLastAttempt) {
|
|
79
|
+
await sleep(RETRY_DELAYS_MS[attempt]);
|
|
80
|
+
continue;
|
|
41
81
|
}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
message = data.message;
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
const retryAfter = statusCode === 429 && typeof data?.retryAfter === 'number' ? data.retryAfter : undefined;
|
|
52
|
-
throw new errors_1.NotifyKitError(message, statusCode, data, errors, retryAfter);
|
|
82
|
+
throw new errors_1.NotifyKitError(describeTransportError(err));
|
|
83
|
+
}
|
|
84
|
+
const data = await res.json().catch(() => null);
|
|
85
|
+
// --- Success ---
|
|
86
|
+
if (res.ok && data?.success !== false) {
|
|
87
|
+
return (data?.data ?? data);
|
|
53
88
|
}
|
|
54
|
-
|
|
55
|
-
|
|
89
|
+
// --- Failure ---
|
|
90
|
+
const error = toError(res.status, res.statusText, data);
|
|
91
|
+
// Retry transient server states (5xx / 429) for any method; a 4xx fails immediately.
|
|
92
|
+
if (isRetryableStatus(res.status) && !isLastAttempt) {
|
|
93
|
+
const delay = error.retryAfter != null
|
|
94
|
+
? Math.min(error.retryAfter * 1000, MAX_RETRY_AFTER_MS)
|
|
95
|
+
: RETRY_DELAYS_MS[attempt];
|
|
96
|
+
await sleep(delay);
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
throw error;
|
|
100
|
+
}
|
|
56
101
|
}
|
|
57
102
|
// ================================
|
|
58
103
|
// APP
|
|
59
104
|
// ================================
|
|
60
105
|
/** Test API connection */
|
|
61
106
|
async ping() {
|
|
62
|
-
return
|
|
107
|
+
return this.request('GET', '/api/v1/ping');
|
|
63
108
|
}
|
|
64
109
|
/** Get API information */
|
|
65
110
|
async getApiInfo() {
|
|
66
|
-
return
|
|
111
|
+
return this.request('GET', '/api/v1/info');
|
|
67
112
|
}
|
|
68
113
|
// ================================
|
|
69
114
|
// NOTIFICATIONS
|
|
70
115
|
// ================================
|
|
71
116
|
/** Send an email notification */
|
|
72
117
|
async sendEmail(options) {
|
|
73
|
-
return
|
|
118
|
+
return this.request('POST', '/api/v1/notifications/email', options);
|
|
74
119
|
}
|
|
75
120
|
/** Send a webhook notification */
|
|
76
121
|
async sendWebhook(options) {
|
|
77
|
-
return
|
|
122
|
+
return this.request('POST', '/api/v1/notifications/webhook', options);
|
|
78
123
|
}
|
|
79
124
|
/** Get job status by ID */
|
|
80
125
|
async getJob(jobId) {
|
|
81
|
-
return
|
|
126
|
+
return this.request('GET', `/api/v1/notifications/jobs/${jobId}`);
|
|
82
127
|
}
|
|
83
128
|
/** List jobs with optional filters */
|
|
84
129
|
async listJobs(options) {
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
130
|
+
let path = '/api/v1/notifications/jobs';
|
|
131
|
+
if (options) {
|
|
132
|
+
const params = new URLSearchParams(Object.entries(options)
|
|
133
|
+
.filter(([, v]) => v !== undefined)
|
|
134
|
+
.map(([k, v]) => [k, String(v)]));
|
|
135
|
+
if (params.size > 0)
|
|
136
|
+
path += `?${params}`;
|
|
137
|
+
}
|
|
138
|
+
return this.request('GET', path);
|
|
88
139
|
}
|
|
89
140
|
/** Retry a failed job */
|
|
90
141
|
async retryJob(jobId) {
|
|
91
|
-
return
|
|
142
|
+
return this.request('POST', `/api/v1/notifications/jobs/${jobId}/retry`);
|
|
92
143
|
}
|
|
93
144
|
}
|
|
94
145
|
exports.NotifyKitClient = NotifyKitClient;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@notifykit/sdk",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "Official NotifyKit SDK for Node.js",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
"prepublishOnly": "npm run build"
|
|
15
15
|
},
|
|
16
16
|
"engines": {
|
|
17
|
-
"node": ">=
|
|
17
|
+
"node": ">=18.0.0"
|
|
18
18
|
},
|
|
19
19
|
"keywords": [
|
|
20
20
|
"notifykit",
|
|
@@ -33,9 +33,7 @@
|
|
|
33
33
|
"url": "https://github.com/brayzonn/notifykit-sdk/issues"
|
|
34
34
|
},
|
|
35
35
|
"homepage": "https://github.com/brayzonn/notifykit-sdk#readme",
|
|
36
|
-
"dependencies": {
|
|
37
|
-
"axios": "^1.6.0"
|
|
38
|
-
},
|
|
36
|
+
"dependencies": {},
|
|
39
37
|
"devDependencies": {
|
|
40
38
|
"@types/node": "^20.0.0",
|
|
41
39
|
"typescript": "^5.0.0"
|