@eventop/sdk 1.0.1 → 1.0.3

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.
Files changed (45) hide show
  1. package/README.md +308 -37
  2. package/dist/cjs/client.js +54 -0
  3. package/dist/cjs/errors.js +28 -0
  4. package/dist/cjs/index.js +32 -0
  5. package/dist/cjs/resources/checkout.js +18 -0
  6. package/dist/cjs/resources/customers.js +1 -0
  7. package/dist/cjs/resources/subscriptions.js +18 -0
  8. package/dist/cjs/resources/webhooks.js +60 -0
  9. package/dist/cjs/types.js +2 -0
  10. package/dist/esm/client.js +45 -0
  11. package/dist/esm/errors.js +26 -0
  12. package/dist/esm/index.js +14 -0
  13. package/dist/esm/resources/checkout.js +14 -0
  14. package/dist/esm/resources/customers.js +1 -0
  15. package/dist/esm/resources/subscriptions.js +14 -0
  16. package/dist/esm/resources/webhooks.js +23 -0
  17. package/dist/esm/types.js +1 -0
  18. package/dist/index.cjs +480 -0
  19. package/dist/index.js +471 -29
  20. package/dist/types/client.d.ts +9 -0
  21. package/dist/types/client.d.ts.map +1 -0
  22. package/dist/types/errors.d.ts +15 -0
  23. package/dist/types/errors.d.ts.map +1 -0
  24. package/dist/types/index.d.ts +13 -0
  25. package/dist/types/index.d.ts.map +1 -0
  26. package/dist/types/resources/checkout.d.ts +10 -0
  27. package/dist/types/resources/checkout.d.ts.map +1 -0
  28. package/dist/types/resources/customers.d.ts +1 -0
  29. package/dist/types/resources/customers.d.ts.map +1 -0
  30. package/dist/types/resources/subscriptions.d.ts +10 -0
  31. package/dist/types/resources/subscriptions.d.ts.map +1 -0
  32. package/dist/types/resources/webhooks.d.ts +9 -0
  33. package/dist/types/resources/webhooks.d.ts.map +1 -0
  34. package/dist/types/types.d.ts +44 -0
  35. package/dist/types/types.d.ts.map +1 -0
  36. package/package.json +51 -35
  37. package/src/client.ts +0 -64
  38. package/src/errors.ts +0 -31
  39. package/src/index.ts +0 -22
  40. package/src/resources/checkout.ts +0 -22
  41. package/src/resources/subscriptions.ts +0 -24
  42. package/src/resources/webhooks.ts +0 -42
  43. package/src/types.ts +0 -49
  44. package/tsconfig.json +0 -18
  45. /package/{src/resources/customers.ts → LICENCE} +0 -0
package/README.md CHANGED
@@ -1,44 +1,315 @@
1
- # Sdk for event api
2
- ```javascript
3
- import { Eventop } from '@eventop/sdk';
4
-
5
- // Initialize client
6
- const eventop = new Eventop({
7
- apiKey: process.env.EVENTOP_API_KEY!, // sk_test_... or sk_live_...
8
- // environment auto-detected from key prefix
9
- });
1
+ # eventop/sdk
2
+
3
+ React integration for eventopAI. Features register at the **call site**, not
4
+ inside component definitions — so any generic component works with any feature,
5
+ and you never touch the component itself.
6
+
7
+ ---
8
+
9
+ ## Install
10
+
11
+ ```bash
12
+ npm install @eventop/sdk
13
+ ```
14
+
15
+ ---
16
+
17
+ ## The mental model
18
+
19
+ ```jsx
20
+ // ❌ Old way — registration inside the component, breaks reusability
21
+ function ExportButton() {
22
+ useeventopFeature({ id: 'export', name: 'Export' }); // hardcoded
23
+ return <button>Export</button>;
24
+ }
10
25
 
11
- // Create checkout session
12
- const session = await eventop.checkout.create({
13
- planId: 'premium-monthly',
14
- customerEmail: 'user@example.com',
15
- customerId: 'user_123',
16
- successUrl: 'https://yourdomain.com/success',
17
- cancelUrl: 'https://yourdomain.com/pricing',
18
- metadata: {
19
- userId: '123',
20
- source: 'web',
21
- },
26
+ // New way — registration at the call site, component stays generic
27
+ function Button({ children, onClick }) {
28
+ return <button onClick={onClick}>{children}</button>;
29
+ }
30
+
31
+ // Different features, same component, different places in the app
32
+ <eventopTarget id="export" name="Export Design" description="Download as PNG or SVG">
33
+ <Button onClick={handleExport}>Export</Button>
34
+ </eventopTarget>
35
+
36
+ <eventopTarget id="download-report" name="Download Report" description="Save as PDF">
37
+ <Button onClick={handleDownload}>Download</Button>
38
+ </eventopTarget>
39
+ ```
40
+
41
+ ---
42
+
43
+ ## Quick start
44
+
45
+ ```jsx
46
+ // main.jsx — provider at the root, nothing else needed here
47
+ import { EventopAIProvider } from '@eventop/sdk';
48
+ import eventopAI from 'eventop-ai-sdk';
49
+
50
+ const provider = eventopAI.providers.custom(async ({ systemPrompt, messages }) => {
51
+ const res = await fetch('/api/guide', {
52
+ method: 'POST',
53
+ headers: { 'Content-Type': 'application/json' },
54
+ body: JSON.stringify({ systemPrompt, messages }),
55
+ });
56
+ return res.json();
22
57
  });
23
58
 
24
- console.log('Checkout URL:', session.url);
59
+ export default function App() {
60
+ return (
61
+ <eventopAIProvider
62
+ provider={provider}
63
+ appName="My App"
64
+ assistantName="AI Guide"
65
+ suggestions={['How do I export?', 'Invite a teammate']}
66
+ theme={{ mode: 'auto', tokens: { accent: '#6366f1' } }}
67
+ position={{ corner: 'bottom-right' }}
68
+ >
69
+ <YourApp />
70
+ </eventopAIProvider>
71
+ );
72
+ }
73
+ ```
74
+
75
+ ---
76
+
77
+ ## Components
78
+
79
+ ### `<eventopTarget>`
80
+
81
+ Wraps any component and registers it as a feature. Works with your own components,
82
+ shadcn, MUI, Radix — anything. The wrapped component does not need to accept refs
83
+ or know about eventopAI.
84
+
85
+ ```jsx
86
+ import { EventopTarget } from '@eventop/sdk';
87
+
88
+ // Simple feature
89
+ <EventopTarget id="export" name="Export Design" description="Download as PNG or SVG">
90
+ <Button>Export</Button>
91
+ </EventopTarget>
92
+
93
+ // With navigation — for features behind a route change
94
+ <EventopTarget
95
+ id="effects"
96
+ name="Effects Panel"
97
+ description="Apply shadows, blur and glow"
98
+ navigate={() => router.push('/canvas')}
99
+ navigateWaitFor="#canvas-stage"
100
+ >
101
+ <EffectsPanel />
102
+ </EventopTarget>
103
+
104
+ // Auto-advance the tour when clicked
105
+ <EventopTarget
106
+ id="open-settings"
107
+ name="Settings"
108
+ description="Open the workspace settings"
109
+ advanceOn={{ event: 'click', delay: 200 }}
110
+ >
111
+ <SettingsButton />
112
+ </EventopTarget>
113
+ ```
114
+
115
+ **Props:**
116
+
117
+ | Prop | Type | Required | Description |
118
+ |-------------------|----------|----------|-------------------------------------------------------|
119
+ | `id` | string | ✓ | Unique feature id |
120
+ | `name` | string | ✓ | Human-readable name (AI reads this) |
121
+ | `description` | string | | What it does (AI uses this to match user intent) |
122
+ | `navigate` | function | | Navigate here if component is not currently mounted |
123
+ | `navigateWaitFor` | string | | CSS selector to wait for after navigating |
124
+ | `advanceOn` | object | | `{ event, delay?, selector? }` — auto-advance the tour|
125
+ | `waitFor` | string | | CSS selector to wait for before showing this step |
126
+
127
+ ---
128
+
129
+ ### `<eventopStep>`
130
+
131
+ Registers one step in a multi-step flow. Can live **anywhere** in the component
132
+ tree — it does not need to be inside a `eventopTarget`. Steps self-assemble
133
+ into the correct sequence via the `index` prop.
134
+
135
+ ```jsx
136
+ import { EventopStep } from '@eventop/sdk';
137
+
138
+ // These three components are totally separate — different files, different parents
139
+ // They form a flow by sharing the same feature id and sequential indexes
140
+
141
+ // In CanvasStage.jsx
142
+ <EventopStep
143
+ feature="drop-shadow"
144
+ index={0}
145
+ advanceOn={{ selector: '.canvas-el', event: 'click', delay: 300 }}
146
+ >
147
+ <div className="canvas-stage">...</div>
148
+ </EventopStep>
149
+
150
+ // In Toolbar.jsx
151
+ <EventopStep
152
+ feature="drop-shadow"
153
+ index={1}
154
+ waitFor=".canvas-el.selected"
155
+ advanceOn={{ event: 'click', delay: 200 }}
156
+ >
157
+ <button id="btn-effects">Effects</button>
158
+ </EventopStep>
25
159
 
26
- // Verify webhook
27
- app.post('/webhooks/eventop', express.raw({ type: 'application/json' }), (req, res) => {
28
- const signature = req.headers['x-webhook-signature'] as string;
29
- const payload = req.body.toString();
160
+ // In EffectsPanel.jsx
161
+ <EventopStep
162
+ feature="drop-shadow"
163
+ index={2}
164
+ waitFor="#effects-panel.open"
165
+ advanceOn={{ event: 'click', delay: 300 }}
166
+ >
167
+ <button id="shadow-toggle">Shadow</button>
168
+ </EventopStep>
30
169
 
31
- try {
32
- const event = eventop.webhooks.constructEvent(
33
- payload,
34
- signature,
35
- process.env.WEBHOOK_SECRET!,
36
- );
170
+ // Only renders when shadow is on — SDK waits for it via waitFor
171
+ <EventopStep feature="drop-shadow" index={3} waitFor="#shadow-controls.visible">
172
+ <div id="shadow-controls">...</div>
173
+ </EventopStep>
174
+ ```
37
175
 
38
- console.log('Received event:', event.event);
39
- res.json({ received: true });
40
- } catch (err) {
41
- res.status(400).send('Webhook signature verification failed');
176
+ **Nested sub-steps:**
177
+
178
+ Pass `parentStep` to model steps that belong inside another step.
179
+ Useful for things like "open font picker → (select font family → select weight → set size)".
180
+
181
+ ```jsx
182
+ // Step 1: open font picker
183
+ <EventopStep feature="style-text" index={1}>
184
+ <FontPickerButton />
185
+ </EventopStep>
186
+
187
+ // Sub-steps of step 1 — run after step 1, in order
188
+ <EventopStep feature="style-text" index={0} parentStep={1} waitFor=".font-picker.open">
189
+ <FontFamilyList />
190
+ </EventopStep>
191
+ <EventopStep feature="style-text" index={1} parentStep={1} waitFor=".family-selected">
192
+ <FontWeightList />
193
+ </EventopStep>
194
+ ```
195
+
196
+ **Implicit feature id from `eventopTarget` ancestor:**
197
+
198
+ If `eventopStep` is inside a `eventopTarget`, it inherits the feature id:
199
+
200
+ ```jsx
201
+ <EventopTarget id="drop-shadow" name="Drop Shadow" description="...">
202
+ <div>
203
+ <EventopStep index={0} advanceOn={{ selector: '.el', event: 'click' }}>
204
+ <Canvas />
205
+ </EventopStep>
206
+ <EventopStep index={1} waitFor=".el.selected">
207
+ <EffectsButton />
208
+ </EventopStep>
209
+ </div>
210
+ </EventopTarget>
211
+ ```
212
+
213
+ **Props:**
214
+
215
+ | Prop | Type | Required | Description |
216
+ |--------------|--------|----------|----------------------------------------------------------|
217
+ | `feature` | string | * | Feature id this step belongs to (*not needed if inside `eventopTarget`) |
218
+ | `index` | number | ✓ | Position in the flow (0-based) |
219
+ | `parentStep` | number | | Parent step index — makes this a sub-step |
220
+ | `waitFor` | string | | CSS selector to wait for before showing |
221
+ | `advanceOn` | object | | `{ event, delay?, selector? }` — auto-advance |
222
+
223
+ ---
224
+
225
+ ### `useeventopAI`
226
+
227
+ Call SDK methods from inside any component. Use for `stepComplete()` and
228
+ `stepFail()` when you have async validation the tour should respect.
229
+
230
+ ```jsx
231
+ import { useeventopAI } from '@eventop/sdk';
232
+
233
+ function CheckoutStep() {
234
+ const { stepComplete, stepFail } = useeventopAI();
235
+
236
+ async function handleContinue() {
237
+ const ok = await validateCard(cardNumber);
238
+ if (ok) stepComplete(); // tour advances to next step
239
+ else stepFail('Invalid card number — please try again.');
42
240
  }
43
- });
44
- ```
241
+
242
+ return <button onClick={handleContinue}>Continue</button>;
243
+ }
244
+ ```
245
+
246
+ **Returns:**
247
+
248
+ | Method | Description |
249
+ |------------------|-----------------------------------------------------|
250
+ | `stepComplete()` | Advance the active tour step |
251
+ | `stepFail(msg)` | Block advancement and show error in the tooltip |
252
+ | `open()` | Open the chat panel |
253
+ | `close()` | Close the chat panel |
254
+ | `cancelTour()` | Hard cancel — no resume state saved |
255
+ | `resumeTour()` | Resume a paused tour from where it left off |
256
+ | `isActive()` | Returns true if a tour is running |
257
+ | `isPaused()` | Returns true if a tour is paused |
258
+ | `runTour(steps)` | Run a manual tour bypassing the AI |
259
+
260
+ ---
261
+
262
+ ### `useeventopTour`
263
+
264
+ React to tour state in your own UI. Reactive — updates every 300ms.
265
+
266
+ ```jsx
267
+ import { useeventopTour } from '@eventop/sdk';
268
+
269
+ function TourStatusBar() {
270
+ const { isActive, isPaused, resume, cancel } = useeventopTour();
271
+
272
+ if (!isActive && !isPaused) return null;
273
+
274
+ return (
275
+ <div className="tour-bar">
276
+ {isPaused ? (
277
+ <>
278
+ <span>⏸ Tour paused</span>
279
+ <button onClick={resume}>Resume</button>
280
+ </>
281
+ ) : (
282
+ <span>▶ Guided tour running</span>
283
+ )}
284
+ <button onClick={cancel}>End tour</button>
285
+ </div>
286
+ );
287
+ }
288
+ ```
289
+
290
+ ---
291
+
292
+ ## Screen navigation
293
+
294
+ Because `eventopTarget` only registers a feature while its component is mounted,
295
+ screen detection is automatic. If the Effects Panel is not rendered, the `effects`
296
+ feature simply does not exist in the registry — no `screen.check()` needed.
297
+
298
+ For features that live behind a route change, pass `navigate`:
299
+
300
+ ```jsx
301
+ // Only rendered on /canvas route
302
+ function EffectsPanel() {
303
+ return (
304
+ <EventopTarget
305
+ id="effects"
306
+ name="Effects Panel"
307
+ description="Apply shadows and blur"
308
+ navigate={() => router.push('/canvas')}
309
+ navigateWaitFor="#canvas-root"
310
+ >
311
+ <div id="effects-panel">...</div>
312
+ </EventopTarget>
313
+ );
314
+ }
315
+ ```
@@ -0,0 +1,54 @@
1
+ // import fetch from 'node-fetch';
2
+ // import { EventopConfig, Environment } from './types';
3
+ // import { EventopError, AuthenticationError } from './errors';
4
+ // export class EventopClient {
5
+ // private apiKey: string;
6
+ // private baseUrl: string;
7
+ // constructor(config: EventopConfig) {
8
+ // this.apiKey = config.apiKey;
9
+ // // Set base URL based on environment
10
+ // if (config.apiUrl) {
11
+ // this.baseUrl = config.apiUrl;
12
+ // } else {
13
+ // const env = config.environment || this.detectEnvironment();
14
+ // this.baseUrl =
15
+ // env === 'devnet'
16
+ // ? 'https://eventop-server-app-production.up.railway.app'
17
+ // : 'https://api.eventop.xyz';
18
+ // }
19
+ // }
20
+ // private detectEnvironment(): Environment {
21
+ // // Detect from API key prefix
22
+ // if (this.apiKey.startsWith('sk_test_')) {
23
+ // return 'devnet';
24
+ // } else if (this.apiKey.startsWith('sk_live_')) {
25
+ // return 'mainnet';
26
+ // }
27
+ // throw new AuthenticationError('Invalid API key format');
28
+ // }
29
+ // async request<T>(
30
+ // method: string,
31
+ // path: string,
32
+ // body?: any,
33
+ // ): Promise<T> {
34
+ // const url = `${this.baseUrl}${path}`;
35
+ // const headers: Record<string, string> = {
36
+ // 'Authorization': `Bearer ${this.apiKey}`,
37
+ // 'Content-Type': 'application/json',
38
+ // };
39
+ // const response = await fetch(url, {
40
+ // method,
41
+ // headers,
42
+ // body: body ? JSON.stringify(body) : undefined,
43
+ // });
44
+ // const data = await response.json();
45
+ // if (!response.ok) {
46
+ // throw new EventopError(
47
+ // data.message || 'Request failed',
48
+ // response.status,
49
+ // data.code,
50
+ // );
51
+ // }
52
+ // return data as T;
53
+ // }
54
+ // }
@@ -0,0 +1,28 @@
1
+ // export class EventopError extends Error {
2
+ // constructor(
3
+ // message: string,
4
+ // public statusCode?: number,
5
+ // public code?: string,
6
+ // ) {
7
+ // super(message);
8
+ // this.name = 'EventopError';
9
+ // }
10
+ // }
11
+ // export class AuthenticationError extends EventopError {
12
+ // constructor(message: string = 'Invalid API key') {
13
+ // super(message, 401, 'authentication_error');
14
+ // this.name = 'AuthenticationError';
15
+ // }
16
+ // }
17
+ // export class InvalidRequestError extends EventopError {
18
+ // constructor(message: string) {
19
+ // super(message, 400, 'invalid_request');
20
+ // this.name = 'InvalidRequestError';
21
+ // }
22
+ // }
23
+ // export class NotFoundError extends EventopError {
24
+ // constructor(message: string) {
25
+ // super(message, 404, 'not_found');
26
+ // this.name = 'NotFoundError';
27
+ // }
28
+ // }
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.Eventop = void 0;
18
+ const client_1 = require("./client");
19
+ const checkout_1 = require("./resources/checkout");
20
+ const subscriptions_1 = require("./resources/subscriptions");
21
+ const webhooks_1 = require("./resources/webhooks");
22
+ class Eventop {
23
+ constructor(config) {
24
+ const client = new client_1.EventopClient(config);
25
+ this.checkout = new checkout_1.Checkout(client);
26
+ this.subscriptions = new subscriptions_1.Subscriptions(client);
27
+ this.webhooks = new webhooks_1.Webhooks(client);
28
+ }
29
+ }
30
+ exports.Eventop = Eventop;
31
+ __exportStar(require("./types"), exports);
32
+ __exportStar(require("./errors"), exports);
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Checkout = void 0;
4
+ class Checkout {
5
+ constructor(client) {
6
+ this.client = client;
7
+ }
8
+ async create(params) {
9
+ return this.client.request('POST', '/checkout/create', params);
10
+ }
11
+ async get(sessionId) {
12
+ return this.client.request('GET', `/checkout/${sessionId}`);
13
+ }
14
+ async cancel(sessionId) {
15
+ return this.client.request('POST', `/checkout/${sessionId}/cancel`);
16
+ }
17
+ }
18
+ exports.Checkout = Checkout;
@@ -0,0 +1 @@
1
+ "use strict";
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Subscriptions = void 0;
4
+ class Subscriptions {
5
+ constructor(client) {
6
+ this.client = client;
7
+ }
8
+ async list() {
9
+ return this.client.request('GET', '/subscriptions');
10
+ }
11
+ async get(subscriptionId) {
12
+ return this.client.request('GET', `/subscriptions/${subscriptionId}`);
13
+ }
14
+ async cancel(subscriptionId) {
15
+ return this.client.request('POST', `/subscriptions/${subscriptionId}/cancel`);
16
+ }
17
+ }
18
+ exports.Subscriptions = Subscriptions;
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.Webhooks = void 0;
37
+ const crypto = __importStar(require("crypto"));
38
+ class Webhooks {
39
+ constructor(client) {
40
+ this.client = client;
41
+ }
42
+ verifySignature(payload, signature, secret) {
43
+ const payloadString = typeof payload === 'string' ? payload : JSON.stringify(payload);
44
+ const expectedSignature = crypto
45
+ .createHmac('sha256', secret)
46
+ .update(payloadString)
47
+ .digest('hex');
48
+ return crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expectedSignature));
49
+ }
50
+ constructEvent(payload, signature, secret) {
51
+ const payloadString = Buffer.isBuffer(payload)
52
+ ? payload.toString('utf8')
53
+ : payload;
54
+ if (!this.verifySignature(payloadString, signature, secret)) {
55
+ throw new Error('Invalid webhook signature');
56
+ }
57
+ return JSON.parse(payloadString);
58
+ }
59
+ }
60
+ exports.Webhooks = Webhooks;
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,45 @@
1
+ import fetch from 'node-fetch';
2
+ import { EventopError, AuthenticationError } from './errors';
3
+ export class EventopClient {
4
+ constructor(config) {
5
+ this.apiKey = config.apiKey;
6
+ // Set base URL based on environment
7
+ if (config.apiUrl) {
8
+ this.baseUrl = config.apiUrl;
9
+ }
10
+ else {
11
+ const env = config.environment || this.detectEnvironment();
12
+ this.baseUrl =
13
+ env === 'devnet'
14
+ ? 'https://eventop-server-app-production.up.railway.app'
15
+ : 'https://api.eventop.xyz';
16
+ }
17
+ }
18
+ detectEnvironment() {
19
+ // Detect from API key prefix
20
+ if (this.apiKey.startsWith('sk_test_')) {
21
+ return 'devnet';
22
+ }
23
+ else if (this.apiKey.startsWith('sk_live_')) {
24
+ return 'mainnet';
25
+ }
26
+ throw new AuthenticationError('Invalid API key format');
27
+ }
28
+ async request(method, path, body) {
29
+ const url = `${this.baseUrl}${path}`;
30
+ const headers = {
31
+ 'Authorization': `Bearer ${this.apiKey}`,
32
+ 'Content-Type': 'application/json',
33
+ };
34
+ const response = await fetch(url, {
35
+ method,
36
+ headers,
37
+ body: body ? JSON.stringify(body) : undefined,
38
+ });
39
+ const data = await response.json();
40
+ if (!response.ok) {
41
+ throw new EventopError(data.message || 'Request failed', response.status, data.code);
42
+ }
43
+ return data;
44
+ }
45
+ }
@@ -0,0 +1,26 @@
1
+ export class EventopError extends Error {
2
+ constructor(message, statusCode, code) {
3
+ super(message);
4
+ this.statusCode = statusCode;
5
+ this.code = code;
6
+ this.name = 'EventopError';
7
+ }
8
+ }
9
+ export class AuthenticationError extends EventopError {
10
+ constructor(message = 'Invalid API key') {
11
+ super(message, 401, 'authentication_error');
12
+ this.name = 'AuthenticationError';
13
+ }
14
+ }
15
+ export class InvalidRequestError extends EventopError {
16
+ constructor(message) {
17
+ super(message, 400, 'invalid_request');
18
+ this.name = 'InvalidRequestError';
19
+ }
20
+ }
21
+ export class NotFoundError extends EventopError {
22
+ constructor(message) {
23
+ super(message, 404, 'not_found');
24
+ this.name = 'NotFoundError';
25
+ }
26
+ }
@@ -0,0 +1,14 @@
1
+ import { EventopClient } from './client';
2
+ import { Checkout } from './resources/checkout';
3
+ import { Subscriptions } from './resources/subscriptions';
4
+ import { Webhooks } from './resources/webhooks';
5
+ export class Eventop {
6
+ constructor(config) {
7
+ const client = new EventopClient(config);
8
+ this.checkout = new Checkout(client);
9
+ this.subscriptions = new Subscriptions(client);
10
+ this.webhooks = new Webhooks(client);
11
+ }
12
+ }
13
+ export * from './types';
14
+ export * from './errors';
@@ -0,0 +1,14 @@
1
+ export class Checkout {
2
+ constructor(client) {
3
+ this.client = client;
4
+ }
5
+ async create(params) {
6
+ return this.client.request('POST', '/checkout/create', params);
7
+ }
8
+ async get(sessionId) {
9
+ return this.client.request('GET', `/checkout/${sessionId}`);
10
+ }
11
+ async cancel(sessionId) {
12
+ return this.client.request('POST', `/checkout/${sessionId}/cancel`);
13
+ }
14
+ }
@@ -0,0 +1 @@
1
+ "use strict";