@kudosapi/sdk 0.1.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/LICENSE +21 -0
- package/README.md +152 -0
- package/dist/index.d.mts +105 -0
- package/dist/index.d.ts +105 -0
- package/dist/index.js +155 -0
- package/dist/index.mjs +128 -0
- package/package.json +53 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 KudosAPI
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
# @kudosapi/sdk
|
|
2
|
+
|
|
3
|
+
Official SDK for [KudosAPI](https://kudosapi.com) - Get positive notifications when good things happen in your app.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @kudosapi/sdk
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
import { Kudos } from '@kudosapi/sdk';
|
|
15
|
+
|
|
16
|
+
const kudos = new Kudos({ apiKey: 'kudo_live_xxx' });
|
|
17
|
+
|
|
18
|
+
// Track a sale
|
|
19
|
+
await kudos.track({
|
|
20
|
+
type: 'sale',
|
|
21
|
+
title: 'New Pro subscription',
|
|
22
|
+
value: 99,
|
|
23
|
+
currency: 'USD',
|
|
24
|
+
data: { customer: 'jane@example.com' }
|
|
25
|
+
});
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Configuration
|
|
29
|
+
|
|
30
|
+
```typescript
|
|
31
|
+
const kudos = new Kudos({
|
|
32
|
+
apiKey: 'kudo_live_xxx', // Required: Your project API key
|
|
33
|
+
baseUrl: 'https://api.kudosapi.com', // Optional: API base URL
|
|
34
|
+
timeout: 5000, // Optional: Request timeout in ms (default: 5000)
|
|
35
|
+
debug: false // Optional: Enable debug logging
|
|
36
|
+
});
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Methods
|
|
40
|
+
|
|
41
|
+
### `track(event, options?)`
|
|
42
|
+
|
|
43
|
+
Send a custom event.
|
|
44
|
+
|
|
45
|
+
```typescript
|
|
46
|
+
await kudos.track({
|
|
47
|
+
type: 'sale', // Required: Event type
|
|
48
|
+
title: 'New sale!', // Optional: Human-readable title
|
|
49
|
+
value: 49.00, // Optional: Numeric value
|
|
50
|
+
currency: 'USD', // Optional: ISO currency code
|
|
51
|
+
data: { ... } // Optional: Additional data
|
|
52
|
+
});
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Options:
|
|
56
|
+
- `fireAndForget`: Set to `true` to return immediately without waiting for a response.
|
|
57
|
+
|
|
58
|
+
### `sale(amount, currency, data?)`
|
|
59
|
+
|
|
60
|
+
Convenience method for tracking sales.
|
|
61
|
+
|
|
62
|
+
```typescript
|
|
63
|
+
await kudos.sale(99.00, 'USD', { customer: 'jane@example.com' });
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### `signup(data?)`
|
|
67
|
+
|
|
68
|
+
Convenience method for tracking signups.
|
|
69
|
+
|
|
70
|
+
```typescript
|
|
71
|
+
await kudos.signup({ source: 'landing_page' });
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### `milestone(title, value?, data?)`
|
|
75
|
+
|
|
76
|
+
Convenience method for tracking milestones.
|
|
77
|
+
|
|
78
|
+
```typescript
|
|
79
|
+
await kudos.milestone('100 customers!', 100);
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Fire and Forget
|
|
83
|
+
|
|
84
|
+
For non-blocking event tracking, use fire-and-forget mode:
|
|
85
|
+
|
|
86
|
+
```typescript
|
|
87
|
+
// Returns immediately, doesn't wait for response
|
|
88
|
+
kudos.track({ type: 'pageview' }, { fireAndForget: true });
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## Error Handling
|
|
92
|
+
|
|
93
|
+
The SDK handles errors gracefully and returns structured error responses:
|
|
94
|
+
|
|
95
|
+
```typescript
|
|
96
|
+
const result = await kudos.track({ type: 'sale' });
|
|
97
|
+
|
|
98
|
+
if (!result.success) {
|
|
99
|
+
console.error(result.error); // Error message
|
|
100
|
+
console.error(result.code); // Error code (e.g., 'INVALID_API_KEY')
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### Error Codes
|
|
105
|
+
|
|
106
|
+
| Code | Description |
|
|
107
|
+
|------|-------------|
|
|
108
|
+
| `MISSING_API_KEY` | No API key provided |
|
|
109
|
+
| `INVALID_API_KEY` | API key is invalid |
|
|
110
|
+
| `INVALID_PAYLOAD` | Request body is malformed |
|
|
111
|
+
| `PAYLOAD_TOO_LARGE` | Request exceeds 100KB limit |
|
|
112
|
+
| `RATE_LIMITED` | Too many requests |
|
|
113
|
+
| `INTERNAL_ERROR` | Server error |
|
|
114
|
+
| `TIMEOUT` | Request timed out |
|
|
115
|
+
| `NETWORK_ERROR` | Network connection failed |
|
|
116
|
+
|
|
117
|
+
## TypeScript
|
|
118
|
+
|
|
119
|
+
Full TypeScript support is included:
|
|
120
|
+
|
|
121
|
+
```typescript
|
|
122
|
+
import { Kudos, TrackEventData, TrackResponse } from '@kudosapi/sdk';
|
|
123
|
+
|
|
124
|
+
const event: TrackEventData = {
|
|
125
|
+
type: 'sale',
|
|
126
|
+
value: 99,
|
|
127
|
+
currency: 'USD'
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
const result: TrackResponse = await kudos.track(event);
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
## Publishing (Maintainers)
|
|
134
|
+
|
|
135
|
+
To publish a new version to npm:
|
|
136
|
+
|
|
137
|
+
1. **Update version** in `packages/sdk/package.json`
|
|
138
|
+
2. **Run the deploy script** from the repo root:
|
|
139
|
+
```bash
|
|
140
|
+
./scripts/deploy-sdk-npm.sh
|
|
141
|
+
```
|
|
142
|
+
3. **When prompted**, enter your npm 2FA code (from your authenticator app):
|
|
143
|
+
```bash
|
|
144
|
+
cd packages/sdk && npm publish --access public --otp=YOUR_6_DIGIT_CODE
|
|
145
|
+
cd ../.. && git checkout dev
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
The deploy script will checkout `master`, run tests, build, and prompt for publish confirmation.
|
|
149
|
+
|
|
150
|
+
## License
|
|
151
|
+
|
|
152
|
+
MIT
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration options for the KudosAPI client
|
|
3
|
+
*/
|
|
4
|
+
interface KudosConfig {
|
|
5
|
+
/** Your KudosAPI API key */
|
|
6
|
+
apiKey: string;
|
|
7
|
+
/** Custom API base URL (defaults to https://api.kudosapi.com) */
|
|
8
|
+
baseUrl?: string;
|
|
9
|
+
/** Request timeout in milliseconds (defaults to 5000) */
|
|
10
|
+
timeout?: number;
|
|
11
|
+
/** Enable debug logging (defaults to false) */
|
|
12
|
+
debug?: boolean;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Event data to track
|
|
16
|
+
*/
|
|
17
|
+
interface TrackEventData {
|
|
18
|
+
/** Event type identifier (e.g., "sale", "signup", "milestone") */
|
|
19
|
+
type: string;
|
|
20
|
+
/** Optional human-readable title for display */
|
|
21
|
+
title?: string;
|
|
22
|
+
/** Optional numeric value (e.g., sale amount) */
|
|
23
|
+
value?: number;
|
|
24
|
+
/** Optional ISO currency code if value is monetary (e.g., "USD") */
|
|
25
|
+
currency?: string;
|
|
26
|
+
/** Optional additional event data */
|
|
27
|
+
data?: Record<string, unknown>;
|
|
28
|
+
/** Optional timestamp override (ISO 8601 format) */
|
|
29
|
+
timestamp?: string;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Successful response from the API
|
|
33
|
+
*/
|
|
34
|
+
interface TrackSuccessResponse {
|
|
35
|
+
success: true;
|
|
36
|
+
eventId: string;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Error response from the API
|
|
40
|
+
*/
|
|
41
|
+
interface TrackErrorResponse {
|
|
42
|
+
success: false;
|
|
43
|
+
error: string;
|
|
44
|
+
code: string;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Response from the track method
|
|
48
|
+
*/
|
|
49
|
+
type TrackResponse = TrackSuccessResponse | TrackErrorResponse;
|
|
50
|
+
/**
|
|
51
|
+
* Options for the track method
|
|
52
|
+
*/
|
|
53
|
+
interface TrackOptions {
|
|
54
|
+
/** If true, don't wait for response (fire and forget) */
|
|
55
|
+
fireAndForget?: boolean;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* KudosAPI Client
|
|
60
|
+
*
|
|
61
|
+
* @example
|
|
62
|
+
* ```ts
|
|
63
|
+
* import { Kudos } from '@kudosapi/sdk';
|
|
64
|
+
*
|
|
65
|
+
* const kudos = new Kudos({ apiKey: 'kudo_live_xxx' });
|
|
66
|
+
*
|
|
67
|
+
* // Track an event
|
|
68
|
+
* await kudos.track({
|
|
69
|
+
* type: 'sale',
|
|
70
|
+
* title: 'New Pro subscription',
|
|
71
|
+
* value: 99,
|
|
72
|
+
* currency: 'USD',
|
|
73
|
+
* data: { customer: 'john@example.com' }
|
|
74
|
+
* });
|
|
75
|
+
* ```
|
|
76
|
+
*/
|
|
77
|
+
declare class Kudos {
|
|
78
|
+
private apiKey;
|
|
79
|
+
private baseUrl;
|
|
80
|
+
private timeout;
|
|
81
|
+
private debug;
|
|
82
|
+
constructor(config: KudosConfig);
|
|
83
|
+
/**
|
|
84
|
+
* Track an event
|
|
85
|
+
*
|
|
86
|
+
* @param event - The event data to track
|
|
87
|
+
* @param options - Optional tracking options
|
|
88
|
+
* @returns Promise with the API response (unless fireAndForget is true)
|
|
89
|
+
*/
|
|
90
|
+
track(event: TrackEventData, options?: TrackOptions): Promise<TrackResponse | void>;
|
|
91
|
+
/**
|
|
92
|
+
* Convenience method to track a sale
|
|
93
|
+
*/
|
|
94
|
+
sale(amount: number, currency: string, data?: Record<string, unknown>): Promise<TrackResponse | void>;
|
|
95
|
+
/**
|
|
96
|
+
* Convenience method to track a signup
|
|
97
|
+
*/
|
|
98
|
+
signup(data?: Record<string, unknown>): Promise<TrackResponse | void>;
|
|
99
|
+
/**
|
|
100
|
+
* Convenience method to track a milestone
|
|
101
|
+
*/
|
|
102
|
+
milestone(title: string, value?: number, data?: Record<string, unknown>): Promise<TrackResponse | void>;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export { Kudos, type KudosConfig, type TrackErrorResponse, type TrackEventData, type TrackOptions, type TrackResponse, type TrackSuccessResponse };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration options for the KudosAPI client
|
|
3
|
+
*/
|
|
4
|
+
interface KudosConfig {
|
|
5
|
+
/** Your KudosAPI API key */
|
|
6
|
+
apiKey: string;
|
|
7
|
+
/** Custom API base URL (defaults to https://api.kudosapi.com) */
|
|
8
|
+
baseUrl?: string;
|
|
9
|
+
/** Request timeout in milliseconds (defaults to 5000) */
|
|
10
|
+
timeout?: number;
|
|
11
|
+
/** Enable debug logging (defaults to false) */
|
|
12
|
+
debug?: boolean;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Event data to track
|
|
16
|
+
*/
|
|
17
|
+
interface TrackEventData {
|
|
18
|
+
/** Event type identifier (e.g., "sale", "signup", "milestone") */
|
|
19
|
+
type: string;
|
|
20
|
+
/** Optional human-readable title for display */
|
|
21
|
+
title?: string;
|
|
22
|
+
/** Optional numeric value (e.g., sale amount) */
|
|
23
|
+
value?: number;
|
|
24
|
+
/** Optional ISO currency code if value is monetary (e.g., "USD") */
|
|
25
|
+
currency?: string;
|
|
26
|
+
/** Optional additional event data */
|
|
27
|
+
data?: Record<string, unknown>;
|
|
28
|
+
/** Optional timestamp override (ISO 8601 format) */
|
|
29
|
+
timestamp?: string;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Successful response from the API
|
|
33
|
+
*/
|
|
34
|
+
interface TrackSuccessResponse {
|
|
35
|
+
success: true;
|
|
36
|
+
eventId: string;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Error response from the API
|
|
40
|
+
*/
|
|
41
|
+
interface TrackErrorResponse {
|
|
42
|
+
success: false;
|
|
43
|
+
error: string;
|
|
44
|
+
code: string;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Response from the track method
|
|
48
|
+
*/
|
|
49
|
+
type TrackResponse = TrackSuccessResponse | TrackErrorResponse;
|
|
50
|
+
/**
|
|
51
|
+
* Options for the track method
|
|
52
|
+
*/
|
|
53
|
+
interface TrackOptions {
|
|
54
|
+
/** If true, don't wait for response (fire and forget) */
|
|
55
|
+
fireAndForget?: boolean;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* KudosAPI Client
|
|
60
|
+
*
|
|
61
|
+
* @example
|
|
62
|
+
* ```ts
|
|
63
|
+
* import { Kudos } from '@kudosapi/sdk';
|
|
64
|
+
*
|
|
65
|
+
* const kudos = new Kudos({ apiKey: 'kudo_live_xxx' });
|
|
66
|
+
*
|
|
67
|
+
* // Track an event
|
|
68
|
+
* await kudos.track({
|
|
69
|
+
* type: 'sale',
|
|
70
|
+
* title: 'New Pro subscription',
|
|
71
|
+
* value: 99,
|
|
72
|
+
* currency: 'USD',
|
|
73
|
+
* data: { customer: 'john@example.com' }
|
|
74
|
+
* });
|
|
75
|
+
* ```
|
|
76
|
+
*/
|
|
77
|
+
declare class Kudos {
|
|
78
|
+
private apiKey;
|
|
79
|
+
private baseUrl;
|
|
80
|
+
private timeout;
|
|
81
|
+
private debug;
|
|
82
|
+
constructor(config: KudosConfig);
|
|
83
|
+
/**
|
|
84
|
+
* Track an event
|
|
85
|
+
*
|
|
86
|
+
* @param event - The event data to track
|
|
87
|
+
* @param options - Optional tracking options
|
|
88
|
+
* @returns Promise with the API response (unless fireAndForget is true)
|
|
89
|
+
*/
|
|
90
|
+
track(event: TrackEventData, options?: TrackOptions): Promise<TrackResponse | void>;
|
|
91
|
+
/**
|
|
92
|
+
* Convenience method to track a sale
|
|
93
|
+
*/
|
|
94
|
+
sale(amount: number, currency: string, data?: Record<string, unknown>): Promise<TrackResponse | void>;
|
|
95
|
+
/**
|
|
96
|
+
* Convenience method to track a signup
|
|
97
|
+
*/
|
|
98
|
+
signup(data?: Record<string, unknown>): Promise<TrackResponse | void>;
|
|
99
|
+
/**
|
|
100
|
+
* Convenience method to track a milestone
|
|
101
|
+
*/
|
|
102
|
+
milestone(title: string, value?: number, data?: Record<string, unknown>): Promise<TrackResponse | void>;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export { Kudos, type KudosConfig, type TrackErrorResponse, type TrackEventData, type TrackOptions, type TrackResponse, type TrackSuccessResponse };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
Kudos: () => Kudos
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(index_exports);
|
|
26
|
+
|
|
27
|
+
// src/client.ts
|
|
28
|
+
var DEFAULT_BASE_URL = "https://api.kudosapi.com";
|
|
29
|
+
var DEFAULT_TIMEOUT = 5e3;
|
|
30
|
+
var MAX_PAYLOAD_SIZE = 100 * 1024;
|
|
31
|
+
var Kudos = class {
|
|
32
|
+
constructor(config) {
|
|
33
|
+
if (!config.apiKey) {
|
|
34
|
+
throw new Error("KudosAPI: apiKey is required");
|
|
35
|
+
}
|
|
36
|
+
this.apiKey = config.apiKey;
|
|
37
|
+
this.baseUrl = config.baseUrl || DEFAULT_BASE_URL;
|
|
38
|
+
this.timeout = config.timeout || DEFAULT_TIMEOUT;
|
|
39
|
+
this.debug = config.debug || false;
|
|
40
|
+
if (typeof process !== "undefined" && process.env?.NODE_ENV === "production" && config.apiKey.startsWith("kudo_test_")) {
|
|
41
|
+
console.warn(
|
|
42
|
+
"[KudosAPI] Warning: Using a test API key in production. Events will not be processed."
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Track an event
|
|
48
|
+
*
|
|
49
|
+
* @param event - The event data to track
|
|
50
|
+
* @param options - Optional tracking options
|
|
51
|
+
* @returns Promise with the API response (unless fireAndForget is true)
|
|
52
|
+
*/
|
|
53
|
+
async track(event, options) {
|
|
54
|
+
const { fireAndForget = false } = options || {};
|
|
55
|
+
const url = `${this.baseUrl}/api/events`;
|
|
56
|
+
const body = JSON.stringify(event);
|
|
57
|
+
const payloadSize = new TextEncoder().encode(body).length;
|
|
58
|
+
if (payloadSize > MAX_PAYLOAD_SIZE) {
|
|
59
|
+
const error = `Payload too large (${Math.round(payloadSize / 1024)}KB). Maximum size is 100KB.`;
|
|
60
|
+
if (this.debug) {
|
|
61
|
+
console.error("[KudosAPI]", error);
|
|
62
|
+
}
|
|
63
|
+
if (fireAndForget) return;
|
|
64
|
+
return {
|
|
65
|
+
success: false,
|
|
66
|
+
error,
|
|
67
|
+
code: "PAYLOAD_TOO_LARGE"
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
const controller = new AbortController();
|
|
71
|
+
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
|
|
72
|
+
try {
|
|
73
|
+
if (this.debug) {
|
|
74
|
+
console.log("[KudosAPI] Tracking event:", event);
|
|
75
|
+
console.log("[KudosAPI] Note: Ensure event data does not contain sensitive PII.");
|
|
76
|
+
}
|
|
77
|
+
const fetchPromise = fetch(url, {
|
|
78
|
+
method: "POST",
|
|
79
|
+
headers: {
|
|
80
|
+
"Content-Type": "application/json",
|
|
81
|
+
Authorization: `Bearer ${this.apiKey}`
|
|
82
|
+
},
|
|
83
|
+
body,
|
|
84
|
+
signal: controller.signal
|
|
85
|
+
});
|
|
86
|
+
if (fireAndForget) {
|
|
87
|
+
fetchPromise.catch((error) => {
|
|
88
|
+
if (this.debug) {
|
|
89
|
+
console.error("[KudosAPI] Fire-and-forget error:", error);
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
const response = await fetchPromise;
|
|
95
|
+
const data = await response.json();
|
|
96
|
+
if (this.debug) {
|
|
97
|
+
console.log("[KudosAPI] Response:", data);
|
|
98
|
+
}
|
|
99
|
+
return data;
|
|
100
|
+
} catch (error) {
|
|
101
|
+
if (error instanceof Error && error.name === "AbortError") {
|
|
102
|
+
return {
|
|
103
|
+
success: false,
|
|
104
|
+
error: "Request timed out",
|
|
105
|
+
code: "TIMEOUT"
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
if (this.debug) {
|
|
109
|
+
console.error("[KudosAPI] Error:", error);
|
|
110
|
+
}
|
|
111
|
+
return {
|
|
112
|
+
success: false,
|
|
113
|
+
error: error instanceof Error ? error.message : "Unknown error",
|
|
114
|
+
code: "NETWORK_ERROR"
|
|
115
|
+
};
|
|
116
|
+
} finally {
|
|
117
|
+
clearTimeout(timeoutId);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Convenience method to track a sale
|
|
122
|
+
*/
|
|
123
|
+
async sale(amount, currency, data) {
|
|
124
|
+
return this.track({
|
|
125
|
+
type: "sale",
|
|
126
|
+
value: amount,
|
|
127
|
+
currency,
|
|
128
|
+
data
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Convenience method to track a signup
|
|
133
|
+
*/
|
|
134
|
+
async signup(data) {
|
|
135
|
+
return this.track({
|
|
136
|
+
type: "signup",
|
|
137
|
+
data
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Convenience method to track a milestone
|
|
142
|
+
*/
|
|
143
|
+
async milestone(title, value, data) {
|
|
144
|
+
return this.track({
|
|
145
|
+
type: "milestone",
|
|
146
|
+
title,
|
|
147
|
+
value,
|
|
148
|
+
data
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
};
|
|
152
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
153
|
+
0 && (module.exports = {
|
|
154
|
+
Kudos
|
|
155
|
+
});
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
// src/client.ts
|
|
2
|
+
var DEFAULT_BASE_URL = "https://api.kudosapi.com";
|
|
3
|
+
var DEFAULT_TIMEOUT = 5e3;
|
|
4
|
+
var MAX_PAYLOAD_SIZE = 100 * 1024;
|
|
5
|
+
var Kudos = class {
|
|
6
|
+
constructor(config) {
|
|
7
|
+
if (!config.apiKey) {
|
|
8
|
+
throw new Error("KudosAPI: apiKey is required");
|
|
9
|
+
}
|
|
10
|
+
this.apiKey = config.apiKey;
|
|
11
|
+
this.baseUrl = config.baseUrl || DEFAULT_BASE_URL;
|
|
12
|
+
this.timeout = config.timeout || DEFAULT_TIMEOUT;
|
|
13
|
+
this.debug = config.debug || false;
|
|
14
|
+
if (typeof process !== "undefined" && process.env?.NODE_ENV === "production" && config.apiKey.startsWith("kudo_test_")) {
|
|
15
|
+
console.warn(
|
|
16
|
+
"[KudosAPI] Warning: Using a test API key in production. Events will not be processed."
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Track an event
|
|
22
|
+
*
|
|
23
|
+
* @param event - The event data to track
|
|
24
|
+
* @param options - Optional tracking options
|
|
25
|
+
* @returns Promise with the API response (unless fireAndForget is true)
|
|
26
|
+
*/
|
|
27
|
+
async track(event, options) {
|
|
28
|
+
const { fireAndForget = false } = options || {};
|
|
29
|
+
const url = `${this.baseUrl}/api/events`;
|
|
30
|
+
const body = JSON.stringify(event);
|
|
31
|
+
const payloadSize = new TextEncoder().encode(body).length;
|
|
32
|
+
if (payloadSize > MAX_PAYLOAD_SIZE) {
|
|
33
|
+
const error = `Payload too large (${Math.round(payloadSize / 1024)}KB). Maximum size is 100KB.`;
|
|
34
|
+
if (this.debug) {
|
|
35
|
+
console.error("[KudosAPI]", error);
|
|
36
|
+
}
|
|
37
|
+
if (fireAndForget) return;
|
|
38
|
+
return {
|
|
39
|
+
success: false,
|
|
40
|
+
error,
|
|
41
|
+
code: "PAYLOAD_TOO_LARGE"
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
const controller = new AbortController();
|
|
45
|
+
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
|
|
46
|
+
try {
|
|
47
|
+
if (this.debug) {
|
|
48
|
+
console.log("[KudosAPI] Tracking event:", event);
|
|
49
|
+
console.log("[KudosAPI] Note: Ensure event data does not contain sensitive PII.");
|
|
50
|
+
}
|
|
51
|
+
const fetchPromise = fetch(url, {
|
|
52
|
+
method: "POST",
|
|
53
|
+
headers: {
|
|
54
|
+
"Content-Type": "application/json",
|
|
55
|
+
Authorization: `Bearer ${this.apiKey}`
|
|
56
|
+
},
|
|
57
|
+
body,
|
|
58
|
+
signal: controller.signal
|
|
59
|
+
});
|
|
60
|
+
if (fireAndForget) {
|
|
61
|
+
fetchPromise.catch((error) => {
|
|
62
|
+
if (this.debug) {
|
|
63
|
+
console.error("[KudosAPI] Fire-and-forget error:", error);
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
const response = await fetchPromise;
|
|
69
|
+
const data = await response.json();
|
|
70
|
+
if (this.debug) {
|
|
71
|
+
console.log("[KudosAPI] Response:", data);
|
|
72
|
+
}
|
|
73
|
+
return data;
|
|
74
|
+
} catch (error) {
|
|
75
|
+
if (error instanceof Error && error.name === "AbortError") {
|
|
76
|
+
return {
|
|
77
|
+
success: false,
|
|
78
|
+
error: "Request timed out",
|
|
79
|
+
code: "TIMEOUT"
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
if (this.debug) {
|
|
83
|
+
console.error("[KudosAPI] Error:", error);
|
|
84
|
+
}
|
|
85
|
+
return {
|
|
86
|
+
success: false,
|
|
87
|
+
error: error instanceof Error ? error.message : "Unknown error",
|
|
88
|
+
code: "NETWORK_ERROR"
|
|
89
|
+
};
|
|
90
|
+
} finally {
|
|
91
|
+
clearTimeout(timeoutId);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Convenience method to track a sale
|
|
96
|
+
*/
|
|
97
|
+
async sale(amount, currency, data) {
|
|
98
|
+
return this.track({
|
|
99
|
+
type: "sale",
|
|
100
|
+
value: amount,
|
|
101
|
+
currency,
|
|
102
|
+
data
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Convenience method to track a signup
|
|
107
|
+
*/
|
|
108
|
+
async signup(data) {
|
|
109
|
+
return this.track({
|
|
110
|
+
type: "signup",
|
|
111
|
+
data
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Convenience method to track a milestone
|
|
116
|
+
*/
|
|
117
|
+
async milestone(title, value, data) {
|
|
118
|
+
return this.track({
|
|
119
|
+
type: "milestone",
|
|
120
|
+
title,
|
|
121
|
+
value,
|
|
122
|
+
data
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
export {
|
|
127
|
+
Kudos
|
|
128
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@kudosapi/sdk",
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"description": "Official SDK for KudosAPI - Get positive notifications when good things happen in your app",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"module": "./dist/index.mjs",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.mjs",
|
|
12
|
+
"require": "./dist/index.js"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist"
|
|
17
|
+
],
|
|
18
|
+
"scripts": {
|
|
19
|
+
"build": "tsup src/index.ts --format cjs,esm --dts",
|
|
20
|
+
"dev": "tsup src/index.ts --format cjs,esm --dts --watch",
|
|
21
|
+
"test": "vitest run",
|
|
22
|
+
"typecheck": "tsc --noEmit"
|
|
23
|
+
},
|
|
24
|
+
"keywords": [
|
|
25
|
+
"kudos",
|
|
26
|
+
"kudosapi",
|
|
27
|
+
"notifications",
|
|
28
|
+
"positive",
|
|
29
|
+
"events",
|
|
30
|
+
"analytics",
|
|
31
|
+
"saas",
|
|
32
|
+
"indie-hacker",
|
|
33
|
+
"motivation",
|
|
34
|
+
"dopamine"
|
|
35
|
+
],
|
|
36
|
+
"author": "KudosAPI",
|
|
37
|
+
"license": "MIT",
|
|
38
|
+
"repository": {
|
|
39
|
+
"type": "git",
|
|
40
|
+
"url": "https://github.com/kudosapi/sdk"
|
|
41
|
+
},
|
|
42
|
+
"homepage": "https://kudosapi.com",
|
|
43
|
+
"bugs": {
|
|
44
|
+
"url": "https://github.com/kudosapi/sdk/issues"
|
|
45
|
+
},
|
|
46
|
+
"engines": {
|
|
47
|
+
"node": ">=18.0.0"
|
|
48
|
+
},
|
|
49
|
+
"devDependencies": {
|
|
50
|
+
"tsup": "^8.0.0",
|
|
51
|
+
"typescript": "^5.0.0"
|
|
52
|
+
}
|
|
53
|
+
}
|