@withvlibe/base-sdk 1.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 +369 -0
- package/dist/VlibeBaseAuth-ChuzgzDl.d.mts +562 -0
- package/dist/VlibeBaseAuth-ChuzgzDl.d.ts +562 -0
- package/dist/index.d.mts +158 -0
- package/dist/index.d.ts +158 -0
- package/dist/index.js +702 -0
- package/dist/index.mjs +673 -0
- package/dist/react.d.mts +96 -0
- package/dist/react.d.ts +96 -0
- package/dist/react.js +273 -0
- package/dist/react.mjs +245 -0
- package/package.json +73 -0
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,673 @@
|
|
|
1
|
+
// src/VlibeBaseDatabase.ts
|
|
2
|
+
import { createClient } from "@supabase/supabase-js";
|
|
3
|
+
var DEFAULT_BASE_URL = "https://vlibe.app";
|
|
4
|
+
var DEFAULT_SUPABASE_URL = "https://qoblysxhxtifxhgdlzgl.supabase.co";
|
|
5
|
+
function resolveBaseUrl(configBaseUrl) {
|
|
6
|
+
if (configBaseUrl) return configBaseUrl;
|
|
7
|
+
if (typeof process !== "undefined" && process.env) {
|
|
8
|
+
if (process.env.VLIBE_BASE_URL) return process.env.VLIBE_BASE_URL;
|
|
9
|
+
if (process.env.NEXT_PUBLIC_VLIBE_BASE_URL) return process.env.NEXT_PUBLIC_VLIBE_BASE_URL;
|
|
10
|
+
}
|
|
11
|
+
return DEFAULT_BASE_URL;
|
|
12
|
+
}
|
|
13
|
+
var VlibeBaseDatabase = class {
|
|
14
|
+
/**
|
|
15
|
+
* Create a new VlibeBaseDatabase instance
|
|
16
|
+
*
|
|
17
|
+
* @param config - Database configuration
|
|
18
|
+
* @throws Error if projectId or databaseToken is missing
|
|
19
|
+
*/
|
|
20
|
+
constructor(config) {
|
|
21
|
+
this.supabase = null;
|
|
22
|
+
this.subscriptions = /* @__PURE__ */ new Map();
|
|
23
|
+
if (!config.projectId) {
|
|
24
|
+
throw new Error("VlibeBaseDatabase: projectId is required");
|
|
25
|
+
}
|
|
26
|
+
if (!config.databaseToken) {
|
|
27
|
+
throw new Error("VlibeBaseDatabase: databaseToken is required");
|
|
28
|
+
}
|
|
29
|
+
this.projectId = config.projectId;
|
|
30
|
+
this.databaseToken = config.databaseToken;
|
|
31
|
+
this.baseUrl = resolveBaseUrl(config.baseUrl);
|
|
32
|
+
this.supabaseUrl = config.supabaseUrl || DEFAULT_SUPABASE_URL;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Initialize Supabase client for real-time subscriptions
|
|
36
|
+
*/
|
|
37
|
+
initSupabase() {
|
|
38
|
+
if (this.supabase) return;
|
|
39
|
+
this.supabase = createClient(this.supabaseUrl, this.databaseToken, {
|
|
40
|
+
realtime: {
|
|
41
|
+
params: {
|
|
42
|
+
eventsPerSecond: 10
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Make an authenticated API request
|
|
49
|
+
*/
|
|
50
|
+
async apiRequest(endpoint, options = {}) {
|
|
51
|
+
const url = `${this.baseUrl}/api/database/${this.projectId}${endpoint}`;
|
|
52
|
+
const response = await fetch(url, {
|
|
53
|
+
...options,
|
|
54
|
+
headers: {
|
|
55
|
+
"Content-Type": "application/json",
|
|
56
|
+
Authorization: `Bearer ${this.databaseToken}`,
|
|
57
|
+
...options.headers
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
const data = await response.json();
|
|
61
|
+
if (!response.ok) {
|
|
62
|
+
throw new Error(data.error || data.message || "API request failed");
|
|
63
|
+
}
|
|
64
|
+
return data;
|
|
65
|
+
}
|
|
66
|
+
// ============================================================================
|
|
67
|
+
// Table Operations
|
|
68
|
+
// ============================================================================
|
|
69
|
+
/**
|
|
70
|
+
* Create a new table
|
|
71
|
+
*/
|
|
72
|
+
async createTable(name, schema) {
|
|
73
|
+
const response = await this.apiRequest(
|
|
74
|
+
"/tables",
|
|
75
|
+
{
|
|
76
|
+
method: "POST",
|
|
77
|
+
body: JSON.stringify({ name, schema })
|
|
78
|
+
}
|
|
79
|
+
);
|
|
80
|
+
return response.data;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Get table information
|
|
84
|
+
*/
|
|
85
|
+
async getTable(name) {
|
|
86
|
+
try {
|
|
87
|
+
const response = await this.apiRequest(
|
|
88
|
+
`/tables/${name}`
|
|
89
|
+
);
|
|
90
|
+
return response.data;
|
|
91
|
+
} catch {
|
|
92
|
+
return null;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* List all tables
|
|
97
|
+
*/
|
|
98
|
+
async listTables() {
|
|
99
|
+
const response = await this.apiRequest(
|
|
100
|
+
"/tables"
|
|
101
|
+
);
|
|
102
|
+
return response.data;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Delete a table
|
|
106
|
+
*/
|
|
107
|
+
async deleteTable(name) {
|
|
108
|
+
await this.apiRequest(`/tables/${name}`, { method: "DELETE" });
|
|
109
|
+
return true;
|
|
110
|
+
}
|
|
111
|
+
// ============================================================================
|
|
112
|
+
// CRUD Operations
|
|
113
|
+
// ============================================================================
|
|
114
|
+
/**
|
|
115
|
+
* Insert a document into a collection
|
|
116
|
+
*/
|
|
117
|
+
async insert(collection, data) {
|
|
118
|
+
const response = await this.apiRequest(
|
|
119
|
+
`/collections/${collection}`,
|
|
120
|
+
{
|
|
121
|
+
method: "POST",
|
|
122
|
+
body: JSON.stringify(data)
|
|
123
|
+
}
|
|
124
|
+
);
|
|
125
|
+
return response.data;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Query documents from a collection
|
|
129
|
+
*/
|
|
130
|
+
async query(collection, options = {}) {
|
|
131
|
+
const params = new URLSearchParams();
|
|
132
|
+
if (options.limit) params.set("limit", String(options.limit));
|
|
133
|
+
if (options.offset) params.set("offset", String(options.offset));
|
|
134
|
+
if (options.orderBy) params.set("orderBy", options.orderBy);
|
|
135
|
+
if (options.orderDirection) params.set("orderDirection", options.orderDirection);
|
|
136
|
+
if (options.where) params.set("where", JSON.stringify(options.where));
|
|
137
|
+
const queryString = params.toString();
|
|
138
|
+
const endpoint = `/collections/${collection}${queryString ? `?${queryString}` : ""}`;
|
|
139
|
+
const response = await this.apiRequest(endpoint);
|
|
140
|
+
return response.data;
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Get a single document by ID
|
|
144
|
+
*/
|
|
145
|
+
async get(collection, id) {
|
|
146
|
+
try {
|
|
147
|
+
const response = await this.apiRequest(
|
|
148
|
+
`/collections/${collection}/${id}`
|
|
149
|
+
);
|
|
150
|
+
return response.data;
|
|
151
|
+
} catch {
|
|
152
|
+
return null;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Update a document
|
|
157
|
+
*/
|
|
158
|
+
async update(collection, id, data) {
|
|
159
|
+
const response = await this.apiRequest(
|
|
160
|
+
`/collections/${collection}/${id}`,
|
|
161
|
+
{
|
|
162
|
+
method: "PATCH",
|
|
163
|
+
body: JSON.stringify(data)
|
|
164
|
+
}
|
|
165
|
+
);
|
|
166
|
+
return response.data;
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Delete a document
|
|
170
|
+
*/
|
|
171
|
+
async delete(collection, id) {
|
|
172
|
+
await this.apiRequest(`/collections/${collection}/${id}`, {
|
|
173
|
+
method: "DELETE"
|
|
174
|
+
});
|
|
175
|
+
return true;
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Count documents in a collection
|
|
179
|
+
*/
|
|
180
|
+
async count(collection, where) {
|
|
181
|
+
const params = new URLSearchParams();
|
|
182
|
+
if (where) params.set("where", JSON.stringify(where));
|
|
183
|
+
const queryString = params.toString();
|
|
184
|
+
const endpoint = `/collections/${collection}/count${queryString ? `?${queryString}` : ""}`;
|
|
185
|
+
const response = await this.apiRequest(
|
|
186
|
+
endpoint
|
|
187
|
+
);
|
|
188
|
+
return response.data.count;
|
|
189
|
+
}
|
|
190
|
+
// ============================================================================
|
|
191
|
+
// Key-Value Store
|
|
192
|
+
// ============================================================================
|
|
193
|
+
/**
|
|
194
|
+
* Set a key-value pair
|
|
195
|
+
*/
|
|
196
|
+
async setKV(key, value) {
|
|
197
|
+
await this.apiRequest("/kv", {
|
|
198
|
+
method: "POST",
|
|
199
|
+
body: JSON.stringify({ key, value })
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Get a value by key
|
|
204
|
+
*/
|
|
205
|
+
async getKV(key) {
|
|
206
|
+
try {
|
|
207
|
+
const response = await this.apiRequest(
|
|
208
|
+
`/kv/${key}`
|
|
209
|
+
);
|
|
210
|
+
return response.data.value;
|
|
211
|
+
} catch {
|
|
212
|
+
return null;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Delete a key-value pair
|
|
217
|
+
*/
|
|
218
|
+
async deleteKV(key) {
|
|
219
|
+
await this.apiRequest(`/kv/${key}`, { method: "DELETE" });
|
|
220
|
+
return true;
|
|
221
|
+
}
|
|
222
|
+
// ============================================================================
|
|
223
|
+
// Real-time Subscriptions
|
|
224
|
+
// ============================================================================
|
|
225
|
+
/**
|
|
226
|
+
* Subscribe to real-time changes on a collection
|
|
227
|
+
*/
|
|
228
|
+
subscribe(collection, callback) {
|
|
229
|
+
this.initSupabase();
|
|
230
|
+
const channelName = `base:${this.projectId}:${collection}`;
|
|
231
|
+
const tableName = `project_${this.projectId.replace(/-/g, "_")}_${collection}`;
|
|
232
|
+
const channel = this.supabase.channel(channelName).on(
|
|
233
|
+
"postgres_changes",
|
|
234
|
+
{
|
|
235
|
+
event: "*",
|
|
236
|
+
schema: "public",
|
|
237
|
+
table: tableName
|
|
238
|
+
},
|
|
239
|
+
(payload) => {
|
|
240
|
+
callback({
|
|
241
|
+
eventType: payload.eventType,
|
|
242
|
+
new: payload.new,
|
|
243
|
+
old: payload.old,
|
|
244
|
+
table: collection
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
).subscribe();
|
|
248
|
+
this.subscriptions.set(channelName, channel);
|
|
249
|
+
return {
|
|
250
|
+
unsubscribe: () => {
|
|
251
|
+
channel.unsubscribe();
|
|
252
|
+
this.subscriptions.delete(channelName);
|
|
253
|
+
}
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* Unsubscribe from all subscriptions
|
|
258
|
+
*/
|
|
259
|
+
unsubscribeAll() {
|
|
260
|
+
for (const channel of this.subscriptions.values()) {
|
|
261
|
+
channel.unsubscribe();
|
|
262
|
+
}
|
|
263
|
+
this.subscriptions.clear();
|
|
264
|
+
}
|
|
265
|
+
// ============================================================================
|
|
266
|
+
// Utilities
|
|
267
|
+
// ============================================================================
|
|
268
|
+
/**
|
|
269
|
+
* Get the project ID
|
|
270
|
+
*/
|
|
271
|
+
getProjectId() {
|
|
272
|
+
return this.projectId;
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Get the base URL
|
|
276
|
+
*/
|
|
277
|
+
getBaseUrl() {
|
|
278
|
+
return this.baseUrl;
|
|
279
|
+
}
|
|
280
|
+
};
|
|
281
|
+
|
|
282
|
+
// src/VlibeBaseAuth.ts
|
|
283
|
+
var DEFAULT_BASE_URL2 = "https://vlibe.app";
|
|
284
|
+
function resolveBaseUrl2(configBaseUrl) {
|
|
285
|
+
if (configBaseUrl) return configBaseUrl;
|
|
286
|
+
if (typeof process !== "undefined" && process.env) {
|
|
287
|
+
if (process.env.VLIBE_BASE_URL) return process.env.VLIBE_BASE_URL;
|
|
288
|
+
if (process.env.NEXT_PUBLIC_VLIBE_BASE_URL) return process.env.NEXT_PUBLIC_VLIBE_BASE_URL;
|
|
289
|
+
}
|
|
290
|
+
return DEFAULT_BASE_URL2;
|
|
291
|
+
}
|
|
292
|
+
var VlibeBaseAuth = class {
|
|
293
|
+
/**
|
|
294
|
+
* Create a new VlibeBaseAuth instance
|
|
295
|
+
*
|
|
296
|
+
* @param config - Authentication configuration
|
|
297
|
+
* @throws Error if appId or appSecret is missing
|
|
298
|
+
*/
|
|
299
|
+
constructor(config) {
|
|
300
|
+
if (!config.appId) {
|
|
301
|
+
throw new Error("VlibeBaseAuth: appId is required");
|
|
302
|
+
}
|
|
303
|
+
if (!config.appSecret) {
|
|
304
|
+
throw new Error("VlibeBaseAuth: appSecret is required");
|
|
305
|
+
}
|
|
306
|
+
this.appId = config.appId;
|
|
307
|
+
this.appSecret = config.appSecret;
|
|
308
|
+
this.baseUrl = resolveBaseUrl2(config.baseUrl);
|
|
309
|
+
}
|
|
310
|
+
/**
|
|
311
|
+
* Verify a session token and get user information
|
|
312
|
+
*
|
|
313
|
+
* @param token - The session token from the SSO callback
|
|
314
|
+
* @returns The user object if valid, null otherwise
|
|
315
|
+
*/
|
|
316
|
+
async verifySession(token) {
|
|
317
|
+
if (!token) {
|
|
318
|
+
return null;
|
|
319
|
+
}
|
|
320
|
+
try {
|
|
321
|
+
const response = await fetch(`${this.baseUrl}/api/auth/sso/verify`, {
|
|
322
|
+
method: "POST",
|
|
323
|
+
headers: {
|
|
324
|
+
"Content-Type": "application/json"
|
|
325
|
+
},
|
|
326
|
+
body: JSON.stringify({
|
|
327
|
+
token,
|
|
328
|
+
appId: this.appId,
|
|
329
|
+
appSecret: this.appSecret,
|
|
330
|
+
appType: "base"
|
|
331
|
+
// Indicate this is a Base app
|
|
332
|
+
})
|
|
333
|
+
});
|
|
334
|
+
if (!response.ok) {
|
|
335
|
+
return null;
|
|
336
|
+
}
|
|
337
|
+
const data = await response.json();
|
|
338
|
+
if (data.valid && data.user) {
|
|
339
|
+
return data.user;
|
|
340
|
+
}
|
|
341
|
+
return null;
|
|
342
|
+
} catch (error) {
|
|
343
|
+
console.error("VlibeBaseAuth: Failed to verify session:", error);
|
|
344
|
+
return null;
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
/**
|
|
348
|
+
* Generate the SSO login URL to redirect unauthenticated users
|
|
349
|
+
*
|
|
350
|
+
* @param redirectPath - The path to redirect to after login
|
|
351
|
+
* @returns The full Vlibe SSO URL
|
|
352
|
+
*/
|
|
353
|
+
getLoginUrl(redirectPath = "/") {
|
|
354
|
+
const params = new URLSearchParams({
|
|
355
|
+
app_id: this.appId,
|
|
356
|
+
app_type: "base",
|
|
357
|
+
redirect: redirectPath
|
|
358
|
+
});
|
|
359
|
+
return `${this.baseUrl}/api/auth/sso?${params.toString()}`;
|
|
360
|
+
}
|
|
361
|
+
/**
|
|
362
|
+
* Generate the logout URL
|
|
363
|
+
*
|
|
364
|
+
* @param redirectPath - The path to redirect to after logout
|
|
365
|
+
* @returns The logout URL
|
|
366
|
+
*/
|
|
367
|
+
getLogoutUrl(redirectPath = "/") {
|
|
368
|
+
const params = new URLSearchParams({
|
|
369
|
+
app_id: this.appId,
|
|
370
|
+
redirect: redirectPath
|
|
371
|
+
});
|
|
372
|
+
return `${this.baseUrl}/api/auth/sso/logout?${params.toString()}`;
|
|
373
|
+
}
|
|
374
|
+
/**
|
|
375
|
+
* Check if user has access to a specific feature
|
|
376
|
+
*
|
|
377
|
+
* @param user - The Vlibe user object
|
|
378
|
+
* @param feature - The feature name to check
|
|
379
|
+
* @returns True if user has access to the feature
|
|
380
|
+
*/
|
|
381
|
+
hasFeature(user, feature) {
|
|
382
|
+
if (!user) return false;
|
|
383
|
+
if (user.subscriptionType === "platform") {
|
|
384
|
+
return true;
|
|
385
|
+
}
|
|
386
|
+
if (user.appAccess?.features) {
|
|
387
|
+
return user.appAccess.features.includes("*") || user.appAccess.features.includes(feature);
|
|
388
|
+
}
|
|
389
|
+
return false;
|
|
390
|
+
}
|
|
391
|
+
/**
|
|
392
|
+
* Check if user has an active subscription
|
|
393
|
+
*
|
|
394
|
+
* @param user - The Vlibe user object
|
|
395
|
+
* @returns True if user has any active subscription
|
|
396
|
+
*/
|
|
397
|
+
hasSubscription(user) {
|
|
398
|
+
return user?.subscriptionType !== null;
|
|
399
|
+
}
|
|
400
|
+
/**
|
|
401
|
+
* Get the subscription tier for a user
|
|
402
|
+
*
|
|
403
|
+
* @param user - The Vlibe user object
|
|
404
|
+
* @returns The tier name or null
|
|
405
|
+
*/
|
|
406
|
+
getTier(user) {
|
|
407
|
+
if (!user) return null;
|
|
408
|
+
if (user.subscriptionType === "platform") return "platform";
|
|
409
|
+
return user.appAccess?.tier || null;
|
|
410
|
+
}
|
|
411
|
+
/**
|
|
412
|
+
* Get the app ID
|
|
413
|
+
*/
|
|
414
|
+
getAppId() {
|
|
415
|
+
return this.appId;
|
|
416
|
+
}
|
|
417
|
+
/**
|
|
418
|
+
* Get the base URL
|
|
419
|
+
*/
|
|
420
|
+
getBaseUrl() {
|
|
421
|
+
return this.baseUrl;
|
|
422
|
+
}
|
|
423
|
+
};
|
|
424
|
+
|
|
425
|
+
// src/VlibeBasePayments.ts
|
|
426
|
+
var DEFAULT_BASE_URL3 = "https://vlibe.app";
|
|
427
|
+
function resolveBaseUrl3(configBaseUrl) {
|
|
428
|
+
if (configBaseUrl) return configBaseUrl;
|
|
429
|
+
if (typeof process !== "undefined" && process.env) {
|
|
430
|
+
if (process.env.VLIBE_BASE_URL) return process.env.VLIBE_BASE_URL;
|
|
431
|
+
if (process.env.NEXT_PUBLIC_VLIBE_BASE_URL) return process.env.NEXT_PUBLIC_VLIBE_BASE_URL;
|
|
432
|
+
}
|
|
433
|
+
return DEFAULT_BASE_URL3;
|
|
434
|
+
}
|
|
435
|
+
var VlibeBasePayments = class {
|
|
436
|
+
/**
|
|
437
|
+
* Create a new VlibeBasePayments instance
|
|
438
|
+
*
|
|
439
|
+
* @param config - Payments configuration
|
|
440
|
+
* @throws Error if appId or appSecret is missing
|
|
441
|
+
*
|
|
442
|
+
* @remarks
|
|
443
|
+
* This class should only be used server-side. Never expose your
|
|
444
|
+
* appSecret to the client.
|
|
445
|
+
*/
|
|
446
|
+
constructor(config) {
|
|
447
|
+
if (!config.appId) {
|
|
448
|
+
throw new Error("VlibeBasePayments: appId is required");
|
|
449
|
+
}
|
|
450
|
+
if (!config.appSecret) {
|
|
451
|
+
throw new Error("VlibeBasePayments: appSecret is required");
|
|
452
|
+
}
|
|
453
|
+
if (typeof window !== "undefined") {
|
|
454
|
+
console.warn(
|
|
455
|
+
"VlibeBasePayments: This class should only be used server-side. Never expose your appSecret to the client."
|
|
456
|
+
);
|
|
457
|
+
}
|
|
458
|
+
this.appId = config.appId;
|
|
459
|
+
this.appSecret = config.appSecret;
|
|
460
|
+
this.baseUrl = resolveBaseUrl3(config.baseUrl);
|
|
461
|
+
}
|
|
462
|
+
/**
|
|
463
|
+
* Make an authenticated API request
|
|
464
|
+
*/
|
|
465
|
+
async apiRequest(endpoint, options = {}) {
|
|
466
|
+
const url = `${this.baseUrl}/api/base/payments${endpoint}`;
|
|
467
|
+
const response = await fetch(url, {
|
|
468
|
+
...options,
|
|
469
|
+
headers: {
|
|
470
|
+
"Content-Type": "application/json",
|
|
471
|
+
"X-App-Id": this.appId,
|
|
472
|
+
"X-App-Secret": this.appSecret,
|
|
473
|
+
...options.headers
|
|
474
|
+
}
|
|
475
|
+
});
|
|
476
|
+
const data = await response.json();
|
|
477
|
+
if (!response.ok) {
|
|
478
|
+
throw new Error(data.error || data.message || "Payment API request failed");
|
|
479
|
+
}
|
|
480
|
+
return data;
|
|
481
|
+
}
|
|
482
|
+
// ============================================================================
|
|
483
|
+
// Stripe Connect
|
|
484
|
+
// ============================================================================
|
|
485
|
+
/**
|
|
486
|
+
* Get Stripe Connect onboarding URL
|
|
487
|
+
*
|
|
488
|
+
* Redirect users to this URL to connect their Stripe account.
|
|
489
|
+
*
|
|
490
|
+
* @param returnUrl - URL to return to after onboarding
|
|
491
|
+
* @returns The Stripe Connect onboarding URL
|
|
492
|
+
*/
|
|
493
|
+
async getConnectOnboardingUrl(returnUrl) {
|
|
494
|
+
const response = await this.apiRequest(
|
|
495
|
+
"/connect/onboard",
|
|
496
|
+
{
|
|
497
|
+
method: "POST",
|
|
498
|
+
body: JSON.stringify({ returnUrl })
|
|
499
|
+
}
|
|
500
|
+
);
|
|
501
|
+
return response.data.url;
|
|
502
|
+
}
|
|
503
|
+
/**
|
|
504
|
+
* Check Stripe Connect status
|
|
505
|
+
*
|
|
506
|
+
* @returns The current Stripe Connect status
|
|
507
|
+
*/
|
|
508
|
+
async getConnectStatus() {
|
|
509
|
+
const response = await this.apiRequest(
|
|
510
|
+
"/connect/status"
|
|
511
|
+
);
|
|
512
|
+
return response.data;
|
|
513
|
+
}
|
|
514
|
+
// ============================================================================
|
|
515
|
+
// Checkout
|
|
516
|
+
// ============================================================================
|
|
517
|
+
/**
|
|
518
|
+
* Create a checkout session for one-time payments
|
|
519
|
+
*
|
|
520
|
+
* @param options - Checkout options
|
|
521
|
+
* @returns The checkout session with URL to redirect user
|
|
522
|
+
*
|
|
523
|
+
* @remarks
|
|
524
|
+
* Transaction fees are automatically calculated based on your plan:
|
|
525
|
+
* - Free plan: 2% of transaction
|
|
526
|
+
* - Premium plan: 0.5% of transaction
|
|
527
|
+
*/
|
|
528
|
+
async createCheckout(options) {
|
|
529
|
+
const response = await this.apiRequest(
|
|
530
|
+
"/checkout",
|
|
531
|
+
{
|
|
532
|
+
method: "POST",
|
|
533
|
+
body: JSON.stringify({
|
|
534
|
+
amount: options.amount,
|
|
535
|
+
currency: options.currency || "usd",
|
|
536
|
+
userId: options.userId,
|
|
537
|
+
userEmail: options.userEmail,
|
|
538
|
+
description: options.description,
|
|
539
|
+
metadata: options.metadata,
|
|
540
|
+
successUrl: options.successUrl,
|
|
541
|
+
cancelUrl: options.cancelUrl
|
|
542
|
+
})
|
|
543
|
+
}
|
|
544
|
+
);
|
|
545
|
+
return response.data;
|
|
546
|
+
}
|
|
547
|
+
/**
|
|
548
|
+
* Get checkout session by ID
|
|
549
|
+
*
|
|
550
|
+
* @param sessionId - The checkout session ID
|
|
551
|
+
* @returns The checkout session details
|
|
552
|
+
*/
|
|
553
|
+
async getCheckoutSession(sessionId) {
|
|
554
|
+
try {
|
|
555
|
+
const response = await this.apiRequest(
|
|
556
|
+
`/checkout/${sessionId}`
|
|
557
|
+
);
|
|
558
|
+
return response.data;
|
|
559
|
+
} catch {
|
|
560
|
+
return null;
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
// ============================================================================
|
|
564
|
+
// Transactions
|
|
565
|
+
// ============================================================================
|
|
566
|
+
/**
|
|
567
|
+
* Get all transactions
|
|
568
|
+
*
|
|
569
|
+
* @param options - Query options
|
|
570
|
+
* @returns List of transactions
|
|
571
|
+
*/
|
|
572
|
+
async getTransactions(options = {}) {
|
|
573
|
+
const params = new URLSearchParams();
|
|
574
|
+
if (options.limit) params.set("limit", String(options.limit));
|
|
575
|
+
if (options.offset) params.set("offset", String(options.offset));
|
|
576
|
+
if (options.status) params.set("status", options.status);
|
|
577
|
+
const queryString = params.toString();
|
|
578
|
+
const endpoint = `/transactions${queryString ? `?${queryString}` : ""}`;
|
|
579
|
+
const response = await this.apiRequest(
|
|
580
|
+
endpoint
|
|
581
|
+
);
|
|
582
|
+
return response.data;
|
|
583
|
+
}
|
|
584
|
+
/**
|
|
585
|
+
* Get a single transaction
|
|
586
|
+
*
|
|
587
|
+
* @param transactionId - The transaction ID
|
|
588
|
+
* @returns The transaction details
|
|
589
|
+
*/
|
|
590
|
+
async getTransaction(transactionId) {
|
|
591
|
+
try {
|
|
592
|
+
const response = await this.apiRequest(
|
|
593
|
+
`/transactions/${transactionId}`
|
|
594
|
+
);
|
|
595
|
+
return response.data;
|
|
596
|
+
} catch {
|
|
597
|
+
return null;
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
/**
|
|
601
|
+
* Get transaction summary/stats
|
|
602
|
+
*
|
|
603
|
+
* @returns Transaction statistics
|
|
604
|
+
*/
|
|
605
|
+
async getTransactionStats() {
|
|
606
|
+
const response = await this.apiRequest("/transactions/stats");
|
|
607
|
+
return response.data;
|
|
608
|
+
}
|
|
609
|
+
// ============================================================================
|
|
610
|
+
// Refunds
|
|
611
|
+
// ============================================================================
|
|
612
|
+
/**
|
|
613
|
+
* Create a refund
|
|
614
|
+
*
|
|
615
|
+
* @param options - Refund options
|
|
616
|
+
* @returns The updated transaction
|
|
617
|
+
*
|
|
618
|
+
* @remarks
|
|
619
|
+
* Note: Transaction fees are not refunded when you issue a refund.
|
|
620
|
+
*/
|
|
621
|
+
async createRefund(options) {
|
|
622
|
+
const response = await this.apiRequest(
|
|
623
|
+
"/refunds",
|
|
624
|
+
{
|
|
625
|
+
method: "POST",
|
|
626
|
+
body: JSON.stringify(options)
|
|
627
|
+
}
|
|
628
|
+
);
|
|
629
|
+
return response.data;
|
|
630
|
+
}
|
|
631
|
+
// ============================================================================
|
|
632
|
+
// Utilities
|
|
633
|
+
// ============================================================================
|
|
634
|
+
/**
|
|
635
|
+
* Calculate the Vlibe fee for an amount
|
|
636
|
+
*
|
|
637
|
+
* @param amount - Amount in cents
|
|
638
|
+
* @param plan - The Base plan ('free' or 'premium')
|
|
639
|
+
* @returns The fee amount in cents
|
|
640
|
+
*/
|
|
641
|
+
calculateFee(amount, plan = "free") {
|
|
642
|
+
const feeRate = plan === "premium" ? 5e-3 : 0.02;
|
|
643
|
+
return Math.round(amount * feeRate);
|
|
644
|
+
}
|
|
645
|
+
/**
|
|
646
|
+
* Calculate net amount after fees
|
|
647
|
+
*
|
|
648
|
+
* @param amount - Gross amount in cents
|
|
649
|
+
* @param plan - The Base plan ('free' or 'premium')
|
|
650
|
+
* @returns The net amount in cents
|
|
651
|
+
*/
|
|
652
|
+
calculateNetAmount(amount, plan = "free") {
|
|
653
|
+
const fee = this.calculateFee(amount, plan);
|
|
654
|
+
return amount - fee;
|
|
655
|
+
}
|
|
656
|
+
/**
|
|
657
|
+
* Get the app ID
|
|
658
|
+
*/
|
|
659
|
+
getAppId() {
|
|
660
|
+
return this.appId;
|
|
661
|
+
}
|
|
662
|
+
/**
|
|
663
|
+
* Get the base URL
|
|
664
|
+
*/
|
|
665
|
+
getBaseUrl() {
|
|
666
|
+
return this.baseUrl;
|
|
667
|
+
}
|
|
668
|
+
};
|
|
669
|
+
export {
|
|
670
|
+
VlibeBaseAuth,
|
|
671
|
+
VlibeBaseDatabase,
|
|
672
|
+
VlibeBasePayments
|
|
673
|
+
};
|