@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.
- package/README.md +308 -37
- package/dist/cjs/client.js +54 -0
- package/dist/cjs/errors.js +28 -0
- package/dist/cjs/index.js +32 -0
- package/dist/cjs/resources/checkout.js +18 -0
- package/dist/cjs/resources/customers.js +1 -0
- package/dist/cjs/resources/subscriptions.js +18 -0
- package/dist/cjs/resources/webhooks.js +60 -0
- package/dist/cjs/types.js +2 -0
- package/dist/esm/client.js +45 -0
- package/dist/esm/errors.js +26 -0
- package/dist/esm/index.js +14 -0
- package/dist/esm/resources/checkout.js +14 -0
- package/dist/esm/resources/customers.js +1 -0
- package/dist/esm/resources/subscriptions.js +14 -0
- package/dist/esm/resources/webhooks.js +23 -0
- package/dist/esm/types.js +1 -0
- package/dist/index.cjs +480 -0
- package/dist/index.js +471 -29
- package/dist/types/client.d.ts +9 -0
- package/dist/types/client.d.ts.map +1 -0
- package/dist/types/errors.d.ts +15 -0
- package/dist/types/errors.d.ts.map +1 -0
- package/dist/types/index.d.ts +13 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/resources/checkout.d.ts +10 -0
- package/dist/types/resources/checkout.d.ts.map +1 -0
- package/dist/types/resources/customers.d.ts +1 -0
- package/dist/types/resources/customers.d.ts.map +1 -0
- package/dist/types/resources/subscriptions.d.ts +10 -0
- package/dist/types/resources/subscriptions.d.ts.map +1 -0
- package/dist/types/resources/webhooks.d.ts +9 -0
- package/dist/types/resources/webhooks.d.ts.map +1 -0
- package/dist/types/types.d.ts +44 -0
- package/dist/types/types.d.ts.map +1 -0
- package/package.json +51 -35
- package/src/client.ts +0 -64
- package/src/errors.ts +0 -31
- package/src/index.ts +0 -22
- package/src/resources/checkout.ts +0 -22
- package/src/resources/subscriptions.ts +0 -24
- package/src/resources/webhooks.ts +0 -42
- package/src/types.ts +0 -49
- package/tsconfig.json +0 -18
- /package/{src/resources/customers.ts → LICENCE} +0 -0
package/README.md
CHANGED
|
@@ -1,44 +1,315 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
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
|
-
//
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
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
|
-
|
|
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
|
-
//
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
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
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
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
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
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,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";
|