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