@commet/better-auth 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 +306 -0
- package/dist/client.cjs +197 -0
- package/dist/client.cjs.map +1 -0
- package/dist/client.d.cts +5 -0
- package/dist/client.d.ts +5 -0
- package/dist/client.js +172 -0
- package/dist/client.js.map +1 -0
- package/dist/index.cjs +1115 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +1366 -0
- package/dist/index.d.ts +1366 -0
- package/dist/index.js +1081 -0
- package/dist/index.js.map +1 -0
- package/package.json +74 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,1081 @@
|
|
|
1
|
+
// src/hooks/customer.ts
|
|
2
|
+
import { APIError } from "better-auth/api";
|
|
3
|
+
var onBeforeUserCreate = (options) => async (user, context) => {
|
|
4
|
+
if (!context || !options.createCustomerOnSignUp) {
|
|
5
|
+
return;
|
|
6
|
+
}
|
|
7
|
+
try {
|
|
8
|
+
const customParams = options.getCustomerCreateParams ? await options.getCustomerCreateParams({ user }, context.request) : {};
|
|
9
|
+
if (!user.email) {
|
|
10
|
+
throw new APIError("BAD_REQUEST", {
|
|
11
|
+
message: "An email is required to create a customer"
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
const existingCustomers = await options.client.customers.list({
|
|
15
|
+
search: user.email
|
|
16
|
+
});
|
|
17
|
+
const existingCustomer = existingCustomers.data?.find(
|
|
18
|
+
(c) => c.billingEmail === user.email
|
|
19
|
+
);
|
|
20
|
+
if (!existingCustomer) {
|
|
21
|
+
await options.client.customers.create({
|
|
22
|
+
email: user.email,
|
|
23
|
+
legalName: customParams.legalName ?? user.name,
|
|
24
|
+
displayName: customParams.displayName,
|
|
25
|
+
domain: customParams.domain,
|
|
26
|
+
metadata: customParams.metadata
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
} catch (e) {
|
|
30
|
+
if (e instanceof APIError) {
|
|
31
|
+
throw e;
|
|
32
|
+
}
|
|
33
|
+
if (e instanceof Error) {
|
|
34
|
+
throw new APIError("INTERNAL_SERVER_ERROR", {
|
|
35
|
+
message: `Commet customer creation failed: ${e.message}`
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
throw new APIError("INTERNAL_SERVER_ERROR", {
|
|
39
|
+
message: "Commet customer creation failed"
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
var onAfterUserCreate = (options) => async (user, context) => {
|
|
44
|
+
if (!context || !options.createCustomerOnSignUp) {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
try {
|
|
48
|
+
const existingCustomers = await options.client.customers.list({
|
|
49
|
+
search: user.email
|
|
50
|
+
});
|
|
51
|
+
const existingCustomer = existingCustomers.data?.find(
|
|
52
|
+
(c) => c.billingEmail === user.email
|
|
53
|
+
);
|
|
54
|
+
if (existingCustomer && existingCustomer.externalId !== user.id) {
|
|
55
|
+
await options.client.customers.update({
|
|
56
|
+
customerId: existingCustomer.id,
|
|
57
|
+
externalId: user.id
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
} catch (e) {
|
|
61
|
+
if (e instanceof Error) {
|
|
62
|
+
throw new APIError("INTERNAL_SERVER_ERROR", {
|
|
63
|
+
message: `Commet customer update failed: ${e.message}`
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
throw new APIError("INTERNAL_SERVER_ERROR", {
|
|
67
|
+
message: "Commet customer update failed"
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
var onUserUpdate = (options) => async (user, context) => {
|
|
72
|
+
if (!context || !options.createCustomerOnSignUp) {
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
try {
|
|
76
|
+
const existingCustomers = await options.client.customers.list({
|
|
77
|
+
externalId: user.id
|
|
78
|
+
});
|
|
79
|
+
const existingCustomer = existingCustomers.data?.[0];
|
|
80
|
+
if (existingCustomer) {
|
|
81
|
+
await options.client.customers.update({
|
|
82
|
+
customerId: existingCustomer.id,
|
|
83
|
+
email: user.email,
|
|
84
|
+
legalName: user.name ?? void 0
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
} catch (e) {
|
|
88
|
+
if (e instanceof Error) {
|
|
89
|
+
context.context.logger.error(
|
|
90
|
+
`Commet customer update failed: ${e.message}`
|
|
91
|
+
);
|
|
92
|
+
} else {
|
|
93
|
+
context.context.logger.error("Commet customer update failed");
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
var onUserDelete = (options) => async (user, context) => {
|
|
98
|
+
if (!context || !options.createCustomerOnSignUp) {
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
try {
|
|
102
|
+
const existingCustomers = await options.client.customers.list({
|
|
103
|
+
externalId: user.id
|
|
104
|
+
});
|
|
105
|
+
const existingCustomer = existingCustomers.data?.[0];
|
|
106
|
+
if (existingCustomer) {
|
|
107
|
+
await options.client.customers.archive(existingCustomer.id);
|
|
108
|
+
}
|
|
109
|
+
} catch (e) {
|
|
110
|
+
if (e instanceof Error) {
|
|
111
|
+
context?.context.logger.error(
|
|
112
|
+
`Commet customer archive failed: ${e.message}`
|
|
113
|
+
);
|
|
114
|
+
} else {
|
|
115
|
+
context?.context.logger.error("Commet customer archive failed");
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
// src/client.ts
|
|
121
|
+
var commetClient = () => {
|
|
122
|
+
return {
|
|
123
|
+
id: "commet-client",
|
|
124
|
+
$InferServerPlugin: {},
|
|
125
|
+
getActions: ($fetch) => {
|
|
126
|
+
return {
|
|
127
|
+
// Customer Portal
|
|
128
|
+
customer: {
|
|
129
|
+
/**
|
|
130
|
+
* Redirect to the Commet customer portal
|
|
131
|
+
*/
|
|
132
|
+
portal: async (fetchOptions) => {
|
|
133
|
+
const res = await $fetch("/commet/portal", {
|
|
134
|
+
method: "GET",
|
|
135
|
+
...fetchOptions
|
|
136
|
+
});
|
|
137
|
+
if (res.error) {
|
|
138
|
+
throw new Error(res.error.message);
|
|
139
|
+
}
|
|
140
|
+
const data = res.data;
|
|
141
|
+
if (data.redirect && typeof window !== "undefined") {
|
|
142
|
+
window.location.href = data.url;
|
|
143
|
+
}
|
|
144
|
+
return data;
|
|
145
|
+
}
|
|
146
|
+
},
|
|
147
|
+
// Subscription management
|
|
148
|
+
subscription: {
|
|
149
|
+
/**
|
|
150
|
+
* Get the current subscription for the authenticated user
|
|
151
|
+
*/
|
|
152
|
+
get: async (fetchOptions) => {
|
|
153
|
+
return $fetch("/commet/subscription", {
|
|
154
|
+
method: "GET",
|
|
155
|
+
...fetchOptions
|
|
156
|
+
});
|
|
157
|
+
},
|
|
158
|
+
/**
|
|
159
|
+
* Change the subscription plan (upgrade/downgrade)
|
|
160
|
+
*/
|
|
161
|
+
changePlan: async (data, fetchOptions) => {
|
|
162
|
+
return $fetch("/commet/subscription/change-plan", {
|
|
163
|
+
method: "POST",
|
|
164
|
+
body: data,
|
|
165
|
+
...fetchOptions
|
|
166
|
+
});
|
|
167
|
+
},
|
|
168
|
+
/**
|
|
169
|
+
* Cancel the subscription
|
|
170
|
+
*/
|
|
171
|
+
cancel: async (data, fetchOptions) => {
|
|
172
|
+
return $fetch("/commet/subscription/cancel", {
|
|
173
|
+
method: "POST",
|
|
174
|
+
body: data ?? {},
|
|
175
|
+
...fetchOptions
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
},
|
|
179
|
+
// Feature access
|
|
180
|
+
features: {
|
|
181
|
+
/**
|
|
182
|
+
* List all features for the authenticated user
|
|
183
|
+
*/
|
|
184
|
+
list: async (fetchOptions) => {
|
|
185
|
+
return $fetch("/commet/features", {
|
|
186
|
+
method: "GET",
|
|
187
|
+
...fetchOptions
|
|
188
|
+
});
|
|
189
|
+
},
|
|
190
|
+
/**
|
|
191
|
+
* Get a specific feature's access/usage
|
|
192
|
+
*/
|
|
193
|
+
get: async (data, fetchOptions) => {
|
|
194
|
+
return $fetch(`/commet/features/${data.code}`, {
|
|
195
|
+
method: "GET",
|
|
196
|
+
...fetchOptions
|
|
197
|
+
});
|
|
198
|
+
},
|
|
199
|
+
/**
|
|
200
|
+
* Check if a feature is enabled (boolean check)
|
|
201
|
+
*/
|
|
202
|
+
check: async (data, fetchOptions) => {
|
|
203
|
+
return $fetch(`/features/${data.code}/check`, {
|
|
204
|
+
method: "GET",
|
|
205
|
+
...fetchOptions
|
|
206
|
+
});
|
|
207
|
+
},
|
|
208
|
+
/**
|
|
209
|
+
* Check if user can use one more unit of a feature
|
|
210
|
+
* Returns { allowed: boolean, willBeCharged: boolean }
|
|
211
|
+
*/
|
|
212
|
+
canUse: async (data, fetchOptions) => {
|
|
213
|
+
return $fetch(`/features/${data.code}/can-use`, {
|
|
214
|
+
method: "GET",
|
|
215
|
+
...fetchOptions
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
},
|
|
219
|
+
// Usage tracking
|
|
220
|
+
usage: {
|
|
221
|
+
/**
|
|
222
|
+
* Track a usage event for the authenticated user
|
|
223
|
+
*/
|
|
224
|
+
track: async (data, fetchOptions) => {
|
|
225
|
+
return $fetch("/commet/usage/track", {
|
|
226
|
+
method: "POST",
|
|
227
|
+
body: data,
|
|
228
|
+
...fetchOptions
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
},
|
|
232
|
+
// Seat management
|
|
233
|
+
seats: {
|
|
234
|
+
/**
|
|
235
|
+
* List all seat balances for the authenticated user
|
|
236
|
+
*/
|
|
237
|
+
list: async (fetchOptions) => {
|
|
238
|
+
return $fetch("/commet/seats", {
|
|
239
|
+
method: "GET",
|
|
240
|
+
...fetchOptions
|
|
241
|
+
});
|
|
242
|
+
},
|
|
243
|
+
/**
|
|
244
|
+
* Add seats of a specific type
|
|
245
|
+
*/
|
|
246
|
+
add: async (data, fetchOptions) => {
|
|
247
|
+
return $fetch("/commet/seats/add", {
|
|
248
|
+
method: "POST",
|
|
249
|
+
body: data,
|
|
250
|
+
...fetchOptions
|
|
251
|
+
});
|
|
252
|
+
},
|
|
253
|
+
/**
|
|
254
|
+
* Remove seats of a specific type
|
|
255
|
+
*/
|
|
256
|
+
remove: async (data, fetchOptions) => {
|
|
257
|
+
return $fetch("/commet/seats/remove", {
|
|
258
|
+
method: "POST",
|
|
259
|
+
body: data,
|
|
260
|
+
...fetchOptions
|
|
261
|
+
});
|
|
262
|
+
},
|
|
263
|
+
/**
|
|
264
|
+
* Set seats to a specific count
|
|
265
|
+
*/
|
|
266
|
+
set: async (data, fetchOptions) => {
|
|
267
|
+
return $fetch("/commet/seats/set", {
|
|
268
|
+
method: "POST",
|
|
269
|
+
body: data,
|
|
270
|
+
...fetchOptions
|
|
271
|
+
});
|
|
272
|
+
},
|
|
273
|
+
/**
|
|
274
|
+
* Set all seat types at once
|
|
275
|
+
*/
|
|
276
|
+
setAll: async (data, fetchOptions) => {
|
|
277
|
+
return $fetch("/commet/seats/set-all", {
|
|
278
|
+
method: "POST",
|
|
279
|
+
body: data,
|
|
280
|
+
...fetchOptions
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
};
|
|
287
|
+
};
|
|
288
|
+
|
|
289
|
+
// src/plugins/portal.ts
|
|
290
|
+
import { APIError as APIError2, sessionMiddleware } from "better-auth/api";
|
|
291
|
+
import { createAuthEndpoint } from "better-auth/plugins";
|
|
292
|
+
var portal = ({ returnUrl } = {}) => (commet2) => {
|
|
293
|
+
return {
|
|
294
|
+
portal: createAuthEndpoint(
|
|
295
|
+
"/commet/portal",
|
|
296
|
+
{
|
|
297
|
+
method: "GET",
|
|
298
|
+
use: [sessionMiddleware]
|
|
299
|
+
},
|
|
300
|
+
async (ctx) => {
|
|
301
|
+
const userId = ctx.context.session?.user.id;
|
|
302
|
+
if (!userId) {
|
|
303
|
+
throw new APIError2("UNAUTHORIZED", {
|
|
304
|
+
message: "You must be logged in to access the customer portal"
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
try {
|
|
308
|
+
const portalAccess = await commet2.portal.getUrl({
|
|
309
|
+
externalId: userId
|
|
310
|
+
});
|
|
311
|
+
if (!portalAccess.success || !portalAccess.data) {
|
|
312
|
+
throw new APIError2("INTERNAL_SERVER_ERROR", {
|
|
313
|
+
message: portalAccess.message || "Failed to generate portal URL"
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
let portalUrl = portalAccess.data.portalUrl;
|
|
317
|
+
if (returnUrl) {
|
|
318
|
+
const url = new URL(portalUrl);
|
|
319
|
+
url.searchParams.set("return_url", returnUrl);
|
|
320
|
+
portalUrl = url.toString();
|
|
321
|
+
}
|
|
322
|
+
return ctx.json({
|
|
323
|
+
url: portalUrl,
|
|
324
|
+
redirect: true
|
|
325
|
+
});
|
|
326
|
+
} catch (e) {
|
|
327
|
+
if (e instanceof APIError2) {
|
|
328
|
+
throw e;
|
|
329
|
+
}
|
|
330
|
+
if (e instanceof Error) {
|
|
331
|
+
ctx.context.logger.error(
|
|
332
|
+
`Commet portal access failed: ${e.message}`
|
|
333
|
+
);
|
|
334
|
+
}
|
|
335
|
+
throw new APIError2("INTERNAL_SERVER_ERROR", {
|
|
336
|
+
message: "Failed to access customer portal"
|
|
337
|
+
});
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
)
|
|
341
|
+
};
|
|
342
|
+
};
|
|
343
|
+
|
|
344
|
+
// src/plugins/subscriptions.ts
|
|
345
|
+
import { APIError as APIError3, sessionMiddleware as sessionMiddleware2 } from "better-auth/api";
|
|
346
|
+
import { createAuthEndpoint as createAuthEndpoint2 } from "better-auth/plugins";
|
|
347
|
+
import { z } from "zod";
|
|
348
|
+
var ChangePlanSchema = z.object({
|
|
349
|
+
planId: z.string().optional(),
|
|
350
|
+
slug: z.string().optional(),
|
|
351
|
+
billingInterval: z.enum(["monthly", "quarterly", "yearly"]).optional()
|
|
352
|
+
});
|
|
353
|
+
var CancelSchema = z.object({
|
|
354
|
+
reason: z.string().optional(),
|
|
355
|
+
immediate: z.boolean().optional()
|
|
356
|
+
});
|
|
357
|
+
var subscriptions = (config = {}) => (commet2) => {
|
|
358
|
+
return {
|
|
359
|
+
getSubscription: createAuthEndpoint2(
|
|
360
|
+
"/commet/subscription",
|
|
361
|
+
{
|
|
362
|
+
method: "GET",
|
|
363
|
+
use: [sessionMiddleware2]
|
|
364
|
+
},
|
|
365
|
+
async (ctx) => {
|
|
366
|
+
const userId = ctx.context.session?.user.id;
|
|
367
|
+
if (!userId) {
|
|
368
|
+
throw new APIError3("UNAUTHORIZED", {
|
|
369
|
+
message: "You must be logged in to view subscription"
|
|
370
|
+
});
|
|
371
|
+
}
|
|
372
|
+
try {
|
|
373
|
+
const subscription = await commet2.subscriptions.get(userId);
|
|
374
|
+
if (!subscription.success) {
|
|
375
|
+
throw new APIError3("INTERNAL_SERVER_ERROR", {
|
|
376
|
+
message: subscription.message || "Failed to retrieve subscription"
|
|
377
|
+
});
|
|
378
|
+
}
|
|
379
|
+
return ctx.json(subscription.data ?? null);
|
|
380
|
+
} catch (e) {
|
|
381
|
+
if (e instanceof APIError3) {
|
|
382
|
+
throw e;
|
|
383
|
+
}
|
|
384
|
+
if (e instanceof Error) {
|
|
385
|
+
ctx.context.logger.error(
|
|
386
|
+
`Commet subscription get failed: ${e.message}`
|
|
387
|
+
);
|
|
388
|
+
}
|
|
389
|
+
throw new APIError3("INTERNAL_SERVER_ERROR", {
|
|
390
|
+
message: "Failed to retrieve subscription"
|
|
391
|
+
});
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
),
|
|
395
|
+
changePlan: createAuthEndpoint2(
|
|
396
|
+
"/commet/subscription/change-plan",
|
|
397
|
+
{
|
|
398
|
+
method: "POST",
|
|
399
|
+
body: ChangePlanSchema,
|
|
400
|
+
use: [sessionMiddleware2]
|
|
401
|
+
},
|
|
402
|
+
async (ctx) => {
|
|
403
|
+
const userId = ctx.context.session?.user.id;
|
|
404
|
+
if (!userId) {
|
|
405
|
+
throw new APIError3("UNAUTHORIZED", {
|
|
406
|
+
message: "You must be logged in to change plan"
|
|
407
|
+
});
|
|
408
|
+
}
|
|
409
|
+
let planId = ctx.body.planId;
|
|
410
|
+
if (ctx.body.slug && !planId) {
|
|
411
|
+
const plan = config.plans?.find((p) => p.slug === ctx.body.slug);
|
|
412
|
+
if (!plan) {
|
|
413
|
+
throw new APIError3("BAD_REQUEST", {
|
|
414
|
+
message: `Plan with slug "${ctx.body.slug}" not found`
|
|
415
|
+
});
|
|
416
|
+
}
|
|
417
|
+
planId = plan.planId;
|
|
418
|
+
}
|
|
419
|
+
if (!planId) {
|
|
420
|
+
throw new APIError3("BAD_REQUEST", {
|
|
421
|
+
message: "Either planId or slug must be provided"
|
|
422
|
+
});
|
|
423
|
+
}
|
|
424
|
+
try {
|
|
425
|
+
const currentSub = await commet2.subscriptions.get(userId);
|
|
426
|
+
if (!currentSub.success || !currentSub.data) {
|
|
427
|
+
throw new APIError3("BAD_REQUEST", {
|
|
428
|
+
message: "No active subscription found"
|
|
429
|
+
});
|
|
430
|
+
}
|
|
431
|
+
const result = await commet2.subscriptions.changePlan({
|
|
432
|
+
subscriptionId: currentSub.data.id,
|
|
433
|
+
planId,
|
|
434
|
+
billingInterval: ctx.body.billingInterval
|
|
435
|
+
});
|
|
436
|
+
if (!result.success) {
|
|
437
|
+
throw new APIError3("INTERNAL_SERVER_ERROR", {
|
|
438
|
+
message: result.message || "Failed to change plan"
|
|
439
|
+
});
|
|
440
|
+
}
|
|
441
|
+
return ctx.json(result.data ?? null);
|
|
442
|
+
} catch (e) {
|
|
443
|
+
if (e instanceof APIError3) {
|
|
444
|
+
throw e;
|
|
445
|
+
}
|
|
446
|
+
if (e instanceof Error) {
|
|
447
|
+
ctx.context.logger.error(
|
|
448
|
+
`Commet plan change failed: ${e.message}`
|
|
449
|
+
);
|
|
450
|
+
}
|
|
451
|
+
throw new APIError3("INTERNAL_SERVER_ERROR", {
|
|
452
|
+
message: "Failed to change plan"
|
|
453
|
+
});
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
),
|
|
457
|
+
cancelSubscription: createAuthEndpoint2(
|
|
458
|
+
"/commet/subscription/cancel",
|
|
459
|
+
{
|
|
460
|
+
method: "POST",
|
|
461
|
+
body: CancelSchema.optional(),
|
|
462
|
+
use: [sessionMiddleware2]
|
|
463
|
+
},
|
|
464
|
+
async (ctx) => {
|
|
465
|
+
const userId = ctx.context.session?.user.id;
|
|
466
|
+
if (!userId) {
|
|
467
|
+
throw new APIError3("UNAUTHORIZED", {
|
|
468
|
+
message: "You must be logged in to cancel subscription"
|
|
469
|
+
});
|
|
470
|
+
}
|
|
471
|
+
try {
|
|
472
|
+
const currentSub = await commet2.subscriptions.get(userId);
|
|
473
|
+
if (!currentSub.success || !currentSub.data) {
|
|
474
|
+
throw new APIError3("BAD_REQUEST", {
|
|
475
|
+
message: "No active subscription found"
|
|
476
|
+
});
|
|
477
|
+
}
|
|
478
|
+
const result = await commet2.subscriptions.cancel({
|
|
479
|
+
subscriptionId: currentSub.data.id,
|
|
480
|
+
reason: ctx.body?.reason,
|
|
481
|
+
immediate: ctx.body?.immediate
|
|
482
|
+
});
|
|
483
|
+
if (!result.success) {
|
|
484
|
+
throw new APIError3("INTERNAL_SERVER_ERROR", {
|
|
485
|
+
message: result.message || "Failed to cancel subscription"
|
|
486
|
+
});
|
|
487
|
+
}
|
|
488
|
+
return ctx.json(result.data ?? null);
|
|
489
|
+
} catch (e) {
|
|
490
|
+
if (e instanceof APIError3) {
|
|
491
|
+
throw e;
|
|
492
|
+
}
|
|
493
|
+
if (e instanceof Error) {
|
|
494
|
+
ctx.context.logger.error(
|
|
495
|
+
`Commet subscription cancel failed: ${e.message}`
|
|
496
|
+
);
|
|
497
|
+
}
|
|
498
|
+
throw new APIError3("INTERNAL_SERVER_ERROR", {
|
|
499
|
+
message: "Failed to cancel subscription"
|
|
500
|
+
});
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
)
|
|
504
|
+
};
|
|
505
|
+
};
|
|
506
|
+
|
|
507
|
+
// src/plugins/features.ts
|
|
508
|
+
import { APIError as APIError4, sessionMiddleware as sessionMiddleware3 } from "better-auth/api";
|
|
509
|
+
import { createAuthEndpoint as createAuthEndpoint3 } from "better-auth/plugins";
|
|
510
|
+
var features = (_config = {}) => (commet2) => {
|
|
511
|
+
return {
|
|
512
|
+
listFeatures: createAuthEndpoint3(
|
|
513
|
+
"/commet/features",
|
|
514
|
+
{
|
|
515
|
+
method: "GET",
|
|
516
|
+
use: [sessionMiddleware3]
|
|
517
|
+
},
|
|
518
|
+
async (ctx) => {
|
|
519
|
+
const userId = ctx.context.session?.user.id;
|
|
520
|
+
if (!userId) {
|
|
521
|
+
throw new APIError4("UNAUTHORIZED", {
|
|
522
|
+
message: "You must be logged in to view features"
|
|
523
|
+
});
|
|
524
|
+
}
|
|
525
|
+
try {
|
|
526
|
+
const result = await commet2.features.list(userId);
|
|
527
|
+
if (!result.success) {
|
|
528
|
+
throw new APIError4("INTERNAL_SERVER_ERROR", {
|
|
529
|
+
message: result.message || "Failed to list features"
|
|
530
|
+
});
|
|
531
|
+
}
|
|
532
|
+
return ctx.json(result.data ?? null);
|
|
533
|
+
} catch (e) {
|
|
534
|
+
if (e instanceof APIError4) {
|
|
535
|
+
throw e;
|
|
536
|
+
}
|
|
537
|
+
if (e instanceof Error) {
|
|
538
|
+
ctx.context.logger.error(
|
|
539
|
+
`Commet features list failed: ${e.message}`
|
|
540
|
+
);
|
|
541
|
+
}
|
|
542
|
+
throw new APIError4("INTERNAL_SERVER_ERROR", {
|
|
543
|
+
message: "Failed to list features"
|
|
544
|
+
});
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
),
|
|
548
|
+
getFeature: createAuthEndpoint3(
|
|
549
|
+
"/commet/features/:code",
|
|
550
|
+
{
|
|
551
|
+
method: "GET",
|
|
552
|
+
use: [sessionMiddleware3]
|
|
553
|
+
},
|
|
554
|
+
async (ctx) => {
|
|
555
|
+
const userId = ctx.context.session?.user.id;
|
|
556
|
+
const code = ctx.params?.code;
|
|
557
|
+
if (!userId) {
|
|
558
|
+
throw new APIError4("UNAUTHORIZED", {
|
|
559
|
+
message: "You must be logged in to view feature"
|
|
560
|
+
});
|
|
561
|
+
}
|
|
562
|
+
if (!code) {
|
|
563
|
+
throw new APIError4("BAD_REQUEST", {
|
|
564
|
+
message: "Feature code is required"
|
|
565
|
+
});
|
|
566
|
+
}
|
|
567
|
+
try {
|
|
568
|
+
const result = await commet2.features.get({
|
|
569
|
+
externalId: userId,
|
|
570
|
+
code
|
|
571
|
+
});
|
|
572
|
+
if (!result.success) {
|
|
573
|
+
throw new APIError4("INTERNAL_SERVER_ERROR", {
|
|
574
|
+
message: result.message || "Failed to get feature"
|
|
575
|
+
});
|
|
576
|
+
}
|
|
577
|
+
return ctx.json(result.data ?? null);
|
|
578
|
+
} catch (e) {
|
|
579
|
+
if (e instanceof APIError4) {
|
|
580
|
+
throw e;
|
|
581
|
+
}
|
|
582
|
+
if (e instanceof Error) {
|
|
583
|
+
ctx.context.logger.error(
|
|
584
|
+
`Commet feature get failed: ${e.message}`
|
|
585
|
+
);
|
|
586
|
+
}
|
|
587
|
+
throw new APIError4("INTERNAL_SERVER_ERROR", {
|
|
588
|
+
message: "Failed to get feature"
|
|
589
|
+
});
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
),
|
|
593
|
+
checkFeature: createAuthEndpoint3(
|
|
594
|
+
"/commet/features/:code/check",
|
|
595
|
+
{
|
|
596
|
+
method: "GET",
|
|
597
|
+
use: [sessionMiddleware3]
|
|
598
|
+
},
|
|
599
|
+
async (ctx) => {
|
|
600
|
+
const userId = ctx.context.session?.user.id;
|
|
601
|
+
const code = ctx.params?.code;
|
|
602
|
+
if (!userId) {
|
|
603
|
+
throw new APIError4("UNAUTHORIZED", {
|
|
604
|
+
message: "You must be logged in to check feature"
|
|
605
|
+
});
|
|
606
|
+
}
|
|
607
|
+
if (!code) {
|
|
608
|
+
throw new APIError4("BAD_REQUEST", {
|
|
609
|
+
message: "Feature code is required"
|
|
610
|
+
});
|
|
611
|
+
}
|
|
612
|
+
try {
|
|
613
|
+
const result = await commet2.features.check({
|
|
614
|
+
externalId: userId,
|
|
615
|
+
code
|
|
616
|
+
});
|
|
617
|
+
if (!result.success) {
|
|
618
|
+
throw new APIError4("INTERNAL_SERVER_ERROR", {
|
|
619
|
+
message: result.message || "Failed to check feature"
|
|
620
|
+
});
|
|
621
|
+
}
|
|
622
|
+
return ctx.json(result.data ?? null);
|
|
623
|
+
} catch (e) {
|
|
624
|
+
if (e instanceof APIError4) {
|
|
625
|
+
throw e;
|
|
626
|
+
}
|
|
627
|
+
if (e instanceof Error) {
|
|
628
|
+
ctx.context.logger.error(
|
|
629
|
+
`Commet feature check failed: ${e.message}`
|
|
630
|
+
);
|
|
631
|
+
}
|
|
632
|
+
throw new APIError4("INTERNAL_SERVER_ERROR", {
|
|
633
|
+
message: "Failed to check feature"
|
|
634
|
+
});
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
),
|
|
638
|
+
canUseFeature: createAuthEndpoint3(
|
|
639
|
+
"/commet/features/:code/can-use",
|
|
640
|
+
{
|
|
641
|
+
method: "GET",
|
|
642
|
+
use: [sessionMiddleware3]
|
|
643
|
+
},
|
|
644
|
+
async (ctx) => {
|
|
645
|
+
const userId = ctx.context.session?.user.id;
|
|
646
|
+
const code = ctx.params?.code;
|
|
647
|
+
if (!userId) {
|
|
648
|
+
throw new APIError4("UNAUTHORIZED", {
|
|
649
|
+
message: "You must be logged in to check feature usage"
|
|
650
|
+
});
|
|
651
|
+
}
|
|
652
|
+
if (!code) {
|
|
653
|
+
throw new APIError4("BAD_REQUEST", {
|
|
654
|
+
message: "Feature code is required"
|
|
655
|
+
});
|
|
656
|
+
}
|
|
657
|
+
try {
|
|
658
|
+
const result = await commet2.features.canUse({
|
|
659
|
+
externalId: userId,
|
|
660
|
+
code
|
|
661
|
+
});
|
|
662
|
+
if (!result.success) {
|
|
663
|
+
throw new APIError4("INTERNAL_SERVER_ERROR", {
|
|
664
|
+
message: result.message || "Failed to check feature usage"
|
|
665
|
+
});
|
|
666
|
+
}
|
|
667
|
+
return ctx.json(result.data ?? null);
|
|
668
|
+
} catch (e) {
|
|
669
|
+
if (e instanceof APIError4) {
|
|
670
|
+
throw e;
|
|
671
|
+
}
|
|
672
|
+
if (e instanceof Error) {
|
|
673
|
+
ctx.context.logger.error(
|
|
674
|
+
`Commet feature canUse failed: ${e.message}`
|
|
675
|
+
);
|
|
676
|
+
}
|
|
677
|
+
throw new APIError4("INTERNAL_SERVER_ERROR", {
|
|
678
|
+
message: "Failed to check feature usage"
|
|
679
|
+
});
|
|
680
|
+
}
|
|
681
|
+
}
|
|
682
|
+
)
|
|
683
|
+
};
|
|
684
|
+
};
|
|
685
|
+
|
|
686
|
+
// src/plugins/usage.ts
|
|
687
|
+
import { APIError as APIError5, sessionMiddleware as sessionMiddleware4 } from "better-auth/api";
|
|
688
|
+
import { createAuthEndpoint as createAuthEndpoint4 } from "better-auth/plugins";
|
|
689
|
+
import { z as z2 } from "zod";
|
|
690
|
+
var TrackEventSchema = z2.object({
|
|
691
|
+
eventType: z2.string(),
|
|
692
|
+
value: z2.number().optional(),
|
|
693
|
+
idempotencyKey: z2.string().optional(),
|
|
694
|
+
properties: z2.record(z2.string(), z2.string()).optional()
|
|
695
|
+
});
|
|
696
|
+
var usage = (_config = {}) => (commet2) => {
|
|
697
|
+
return {
|
|
698
|
+
trackUsage: createAuthEndpoint4(
|
|
699
|
+
"/commet/usage/track",
|
|
700
|
+
{
|
|
701
|
+
method: "POST",
|
|
702
|
+
body: TrackEventSchema,
|
|
703
|
+
use: [sessionMiddleware4]
|
|
704
|
+
},
|
|
705
|
+
async (ctx) => {
|
|
706
|
+
const userId = ctx.context.session?.user.id;
|
|
707
|
+
if (!userId) {
|
|
708
|
+
throw new APIError5("UNAUTHORIZED", {
|
|
709
|
+
message: "You must be logged in to track usage"
|
|
710
|
+
});
|
|
711
|
+
}
|
|
712
|
+
try {
|
|
713
|
+
const result = await commet2.usage.track(
|
|
714
|
+
{
|
|
715
|
+
externalId: userId,
|
|
716
|
+
eventType: ctx.body.eventType,
|
|
717
|
+
idempotencyKey: ctx.body.idempotencyKey,
|
|
718
|
+
properties: ctx.body.properties
|
|
719
|
+
},
|
|
720
|
+
{}
|
|
721
|
+
);
|
|
722
|
+
if (!result.success) {
|
|
723
|
+
throw new APIError5("INTERNAL_SERVER_ERROR", {
|
|
724
|
+
message: result.message || "Failed to track usage"
|
|
725
|
+
});
|
|
726
|
+
}
|
|
727
|
+
return ctx.json(result.data ?? null);
|
|
728
|
+
} catch (e) {
|
|
729
|
+
if (e instanceof APIError5) {
|
|
730
|
+
throw e;
|
|
731
|
+
}
|
|
732
|
+
if (e instanceof Error) {
|
|
733
|
+
ctx.context.logger.error(
|
|
734
|
+
`Commet usage track failed: ${e.message}`
|
|
735
|
+
);
|
|
736
|
+
}
|
|
737
|
+
throw new APIError5("INTERNAL_SERVER_ERROR", {
|
|
738
|
+
message: "Failed to track usage"
|
|
739
|
+
});
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
)
|
|
743
|
+
};
|
|
744
|
+
};
|
|
745
|
+
|
|
746
|
+
// src/plugins/seats.ts
|
|
747
|
+
import { APIError as APIError6, sessionMiddleware as sessionMiddleware5 } from "better-auth/api";
|
|
748
|
+
import { createAuthEndpoint as createAuthEndpoint5 } from "better-auth/plugins";
|
|
749
|
+
import { z as z3 } from "zod";
|
|
750
|
+
var SeatOperationSchema = z3.object({
|
|
751
|
+
seatType: z3.string(),
|
|
752
|
+
count: z3.number().min(1)
|
|
753
|
+
});
|
|
754
|
+
var SetAllSeatsSchema = z3.object({
|
|
755
|
+
seats: z3.record(z3.string(), z3.number())
|
|
756
|
+
});
|
|
757
|
+
var seats = (_config = {}) => (commet2) => {
|
|
758
|
+
return {
|
|
759
|
+
listSeats: createAuthEndpoint5(
|
|
760
|
+
"/commet/seats",
|
|
761
|
+
{
|
|
762
|
+
method: "GET",
|
|
763
|
+
use: [sessionMiddleware5]
|
|
764
|
+
},
|
|
765
|
+
async (ctx) => {
|
|
766
|
+
const userId = ctx.context.session?.user.id;
|
|
767
|
+
if (!userId) {
|
|
768
|
+
throw new APIError6("UNAUTHORIZED", {
|
|
769
|
+
message: "You must be logged in to view seats"
|
|
770
|
+
});
|
|
771
|
+
}
|
|
772
|
+
try {
|
|
773
|
+
const result = await commet2.seats.getAllBalances({
|
|
774
|
+
externalId: userId
|
|
775
|
+
});
|
|
776
|
+
if (!result.success) {
|
|
777
|
+
throw new APIError6("INTERNAL_SERVER_ERROR", {
|
|
778
|
+
message: result.message || "Failed to list seats"
|
|
779
|
+
});
|
|
780
|
+
}
|
|
781
|
+
return ctx.json(result.data ?? null);
|
|
782
|
+
} catch (e) {
|
|
783
|
+
if (e instanceof APIError6) {
|
|
784
|
+
throw e;
|
|
785
|
+
}
|
|
786
|
+
if (e instanceof Error) {
|
|
787
|
+
ctx.context.logger.error(
|
|
788
|
+
`Commet seats list failed: ${e.message}`
|
|
789
|
+
);
|
|
790
|
+
}
|
|
791
|
+
throw new APIError6("INTERNAL_SERVER_ERROR", {
|
|
792
|
+
message: "Failed to list seats"
|
|
793
|
+
});
|
|
794
|
+
}
|
|
795
|
+
}
|
|
796
|
+
),
|
|
797
|
+
addSeats: createAuthEndpoint5(
|
|
798
|
+
"/commet/seats/add",
|
|
799
|
+
{
|
|
800
|
+
method: "POST",
|
|
801
|
+
body: SeatOperationSchema,
|
|
802
|
+
use: [sessionMiddleware5]
|
|
803
|
+
},
|
|
804
|
+
async (ctx) => {
|
|
805
|
+
const userId = ctx.context.session?.user.id;
|
|
806
|
+
if (!userId) {
|
|
807
|
+
throw new APIError6("UNAUTHORIZED", {
|
|
808
|
+
message: "You must be logged in to add seats"
|
|
809
|
+
});
|
|
810
|
+
}
|
|
811
|
+
try {
|
|
812
|
+
const result = await commet2.seats.add(
|
|
813
|
+
{
|
|
814
|
+
externalId: userId,
|
|
815
|
+
seatType: ctx.body.seatType,
|
|
816
|
+
count: ctx.body.count
|
|
817
|
+
},
|
|
818
|
+
{}
|
|
819
|
+
);
|
|
820
|
+
if (!result.success) {
|
|
821
|
+
throw new APIError6("INTERNAL_SERVER_ERROR", {
|
|
822
|
+
message: result.message || "Failed to add seats"
|
|
823
|
+
});
|
|
824
|
+
}
|
|
825
|
+
return ctx.json(result.data ?? null);
|
|
826
|
+
} catch (e) {
|
|
827
|
+
if (e instanceof APIError6) {
|
|
828
|
+
throw e;
|
|
829
|
+
}
|
|
830
|
+
if (e instanceof Error) {
|
|
831
|
+
ctx.context.logger.error(`Commet seats add failed: ${e.message}`);
|
|
832
|
+
}
|
|
833
|
+
throw new APIError6("INTERNAL_SERVER_ERROR", {
|
|
834
|
+
message: "Failed to add seats"
|
|
835
|
+
});
|
|
836
|
+
}
|
|
837
|
+
}
|
|
838
|
+
),
|
|
839
|
+
removeSeats: createAuthEndpoint5(
|
|
840
|
+
"/commet/seats/remove",
|
|
841
|
+
{
|
|
842
|
+
method: "POST",
|
|
843
|
+
body: SeatOperationSchema,
|
|
844
|
+
use: [sessionMiddleware5]
|
|
845
|
+
},
|
|
846
|
+
async (ctx) => {
|
|
847
|
+
const userId = ctx.context.session?.user.id;
|
|
848
|
+
if (!userId) {
|
|
849
|
+
throw new APIError6("UNAUTHORIZED", {
|
|
850
|
+
message: "You must be logged in to remove seats"
|
|
851
|
+
});
|
|
852
|
+
}
|
|
853
|
+
try {
|
|
854
|
+
const result = await commet2.seats.remove(
|
|
855
|
+
{
|
|
856
|
+
externalId: userId,
|
|
857
|
+
seatType: ctx.body.seatType,
|
|
858
|
+
count: ctx.body.count
|
|
859
|
+
},
|
|
860
|
+
{}
|
|
861
|
+
);
|
|
862
|
+
if (!result.success) {
|
|
863
|
+
throw new APIError6("INTERNAL_SERVER_ERROR", {
|
|
864
|
+
message: result.message || "Failed to remove seats"
|
|
865
|
+
});
|
|
866
|
+
}
|
|
867
|
+
return ctx.json(result.data ?? null);
|
|
868
|
+
} catch (e) {
|
|
869
|
+
if (e instanceof APIError6) {
|
|
870
|
+
throw e;
|
|
871
|
+
}
|
|
872
|
+
if (e instanceof Error) {
|
|
873
|
+
ctx.context.logger.error(
|
|
874
|
+
`Commet seats remove failed: ${e.message}`
|
|
875
|
+
);
|
|
876
|
+
}
|
|
877
|
+
throw new APIError6("INTERNAL_SERVER_ERROR", {
|
|
878
|
+
message: "Failed to remove seats"
|
|
879
|
+
});
|
|
880
|
+
}
|
|
881
|
+
}
|
|
882
|
+
),
|
|
883
|
+
setSeats: createAuthEndpoint5(
|
|
884
|
+
"/commet/seats/set",
|
|
885
|
+
{
|
|
886
|
+
method: "POST",
|
|
887
|
+
body: SeatOperationSchema,
|
|
888
|
+
use: [sessionMiddleware5]
|
|
889
|
+
},
|
|
890
|
+
async (ctx) => {
|
|
891
|
+
const userId = ctx.context.session?.user.id;
|
|
892
|
+
if (!userId) {
|
|
893
|
+
throw new APIError6("UNAUTHORIZED", {
|
|
894
|
+
message: "You must be logged in to set seats"
|
|
895
|
+
});
|
|
896
|
+
}
|
|
897
|
+
try {
|
|
898
|
+
const result = await commet2.seats.set(
|
|
899
|
+
{
|
|
900
|
+
externalId: userId,
|
|
901
|
+
seatType: ctx.body.seatType,
|
|
902
|
+
count: ctx.body.count
|
|
903
|
+
},
|
|
904
|
+
{}
|
|
905
|
+
);
|
|
906
|
+
if (!result.success) {
|
|
907
|
+
throw new APIError6("INTERNAL_SERVER_ERROR", {
|
|
908
|
+
message: result.message || "Failed to set seats"
|
|
909
|
+
});
|
|
910
|
+
}
|
|
911
|
+
return ctx.json(result.data ?? null);
|
|
912
|
+
} catch (e) {
|
|
913
|
+
if (e instanceof APIError6) {
|
|
914
|
+
throw e;
|
|
915
|
+
}
|
|
916
|
+
if (e instanceof Error) {
|
|
917
|
+
ctx.context.logger.error(`Commet seats set failed: ${e.message}`);
|
|
918
|
+
}
|
|
919
|
+
throw new APIError6("INTERNAL_SERVER_ERROR", {
|
|
920
|
+
message: "Failed to set seats"
|
|
921
|
+
});
|
|
922
|
+
}
|
|
923
|
+
}
|
|
924
|
+
),
|
|
925
|
+
setAllSeats: createAuthEndpoint5(
|
|
926
|
+
"/commet/seats/set-all",
|
|
927
|
+
{
|
|
928
|
+
method: "POST",
|
|
929
|
+
body: SetAllSeatsSchema,
|
|
930
|
+
use: [sessionMiddleware5]
|
|
931
|
+
},
|
|
932
|
+
async (ctx) => {
|
|
933
|
+
const userId = ctx.context.session?.user.id;
|
|
934
|
+
if (!userId) {
|
|
935
|
+
throw new APIError6("UNAUTHORIZED", {
|
|
936
|
+
message: "You must be logged in to set seats"
|
|
937
|
+
});
|
|
938
|
+
}
|
|
939
|
+
try {
|
|
940
|
+
const result = await commet2.seats.setAll(
|
|
941
|
+
{
|
|
942
|
+
externalId: userId,
|
|
943
|
+
seats: ctx.body.seats
|
|
944
|
+
},
|
|
945
|
+
{}
|
|
946
|
+
);
|
|
947
|
+
if (!result.success) {
|
|
948
|
+
throw new APIError6("INTERNAL_SERVER_ERROR", {
|
|
949
|
+
message: result.message || "Failed to set all seats"
|
|
950
|
+
});
|
|
951
|
+
}
|
|
952
|
+
return ctx.json(result.data ?? null);
|
|
953
|
+
} catch (e) {
|
|
954
|
+
if (e instanceof APIError6) {
|
|
955
|
+
throw e;
|
|
956
|
+
}
|
|
957
|
+
if (e instanceof Error) {
|
|
958
|
+
ctx.context.logger.error(
|
|
959
|
+
`Commet seats set-all failed: ${e.message}`
|
|
960
|
+
);
|
|
961
|
+
}
|
|
962
|
+
throw new APIError6("INTERNAL_SERVER_ERROR", {
|
|
963
|
+
message: "Failed to set all seats"
|
|
964
|
+
});
|
|
965
|
+
}
|
|
966
|
+
}
|
|
967
|
+
)
|
|
968
|
+
};
|
|
969
|
+
};
|
|
970
|
+
|
|
971
|
+
// src/plugins/webhooks.ts
|
|
972
|
+
import { APIError as APIError7, createAuthEndpoint as createAuthEndpoint6 } from "better-auth/api";
|
|
973
|
+
var EVENT_HANDLER_MAP = {
|
|
974
|
+
"subscription.created": "onSubscriptionCreated",
|
|
975
|
+
"subscription.activated": "onSubscriptionActivated",
|
|
976
|
+
"subscription.canceled": "onSubscriptionCanceled",
|
|
977
|
+
"subscription.updated": "onSubscriptionUpdated"
|
|
978
|
+
};
|
|
979
|
+
var webhooks = (config) => (commet2) => {
|
|
980
|
+
return {
|
|
981
|
+
commetWebhooks: createAuthEndpoint6(
|
|
982
|
+
"/commet/webhooks",
|
|
983
|
+
{
|
|
984
|
+
method: "POST",
|
|
985
|
+
metadata: {
|
|
986
|
+
isAction: false
|
|
987
|
+
},
|
|
988
|
+
cloneRequest: true
|
|
989
|
+
},
|
|
990
|
+
async (ctx) => {
|
|
991
|
+
if (!ctx.request?.body) {
|
|
992
|
+
throw new APIError7("BAD_REQUEST", {
|
|
993
|
+
message: "Request body is required"
|
|
994
|
+
});
|
|
995
|
+
}
|
|
996
|
+
const rawBody = await ctx.request.text();
|
|
997
|
+
const signature = ctx.request.headers.get("x-commet-signature");
|
|
998
|
+
const payload = commet2.webhooks.verifyAndParse({
|
|
999
|
+
rawBody,
|
|
1000
|
+
signature,
|
|
1001
|
+
secret: config.secret
|
|
1002
|
+
});
|
|
1003
|
+
if (!payload) {
|
|
1004
|
+
ctx.context.logger.error("Invalid webhook signature");
|
|
1005
|
+
throw new APIError7("UNAUTHORIZED", {
|
|
1006
|
+
message: "Invalid webhook signature"
|
|
1007
|
+
});
|
|
1008
|
+
}
|
|
1009
|
+
try {
|
|
1010
|
+
const handlerKey = EVENT_HANDLER_MAP[payload.event];
|
|
1011
|
+
if (handlerKey) {
|
|
1012
|
+
const handler = config[handlerKey];
|
|
1013
|
+
if (handler) {
|
|
1014
|
+
await handler(payload);
|
|
1015
|
+
}
|
|
1016
|
+
}
|
|
1017
|
+
if (config.onPayload) {
|
|
1018
|
+
await config.onPayload(payload);
|
|
1019
|
+
}
|
|
1020
|
+
return ctx.json({ received: true });
|
|
1021
|
+
} catch (e) {
|
|
1022
|
+
if (e instanceof Error) {
|
|
1023
|
+
ctx.context.logger.error(
|
|
1024
|
+
`Commet webhook handler error: ${e.message}`
|
|
1025
|
+
);
|
|
1026
|
+
} else {
|
|
1027
|
+
ctx.context.logger.error("Commet webhook handler error");
|
|
1028
|
+
}
|
|
1029
|
+
throw new APIError7("INTERNAL_SERVER_ERROR", {
|
|
1030
|
+
message: "Webhook handler error"
|
|
1031
|
+
});
|
|
1032
|
+
}
|
|
1033
|
+
}
|
|
1034
|
+
)
|
|
1035
|
+
};
|
|
1036
|
+
};
|
|
1037
|
+
|
|
1038
|
+
// src/index.ts
|
|
1039
|
+
var commet = (options) => {
|
|
1040
|
+
const plugins = options.use.map((use) => use(options.client)).reduce((acc, plugin) => {
|
|
1041
|
+
Object.assign(acc, plugin);
|
|
1042
|
+
return acc;
|
|
1043
|
+
}, {});
|
|
1044
|
+
return {
|
|
1045
|
+
id: "commet",
|
|
1046
|
+
endpoints: {
|
|
1047
|
+
...plugins
|
|
1048
|
+
},
|
|
1049
|
+
init() {
|
|
1050
|
+
return {
|
|
1051
|
+
options: {
|
|
1052
|
+
databaseHooks: {
|
|
1053
|
+
user: {
|
|
1054
|
+
create: {
|
|
1055
|
+
before: onBeforeUserCreate(options),
|
|
1056
|
+
after: onAfterUserCreate(options)
|
|
1057
|
+
},
|
|
1058
|
+
update: {
|
|
1059
|
+
after: onUserUpdate(options)
|
|
1060
|
+
},
|
|
1061
|
+
delete: {
|
|
1062
|
+
after: onUserDelete(options)
|
|
1063
|
+
}
|
|
1064
|
+
}
|
|
1065
|
+
}
|
|
1066
|
+
}
|
|
1067
|
+
};
|
|
1068
|
+
}
|
|
1069
|
+
};
|
|
1070
|
+
};
|
|
1071
|
+
export {
|
|
1072
|
+
commet,
|
|
1073
|
+
commetClient,
|
|
1074
|
+
features,
|
|
1075
|
+
portal,
|
|
1076
|
+
seats,
|
|
1077
|
+
subscriptions,
|
|
1078
|
+
usage,
|
|
1079
|
+
webhooks
|
|
1080
|
+
};
|
|
1081
|
+
//# sourceMappingURL=index.js.map
|