@better-auth/stripe 1.4.9 → 1.5.0-beta.1

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.
@@ -1,5 +1,5 @@
1
1
 
2
- > @better-auth/stripe@1.4.9 build /home/runner/work/better-auth/better-auth/packages/stripe
2
+ > @better-auth/stripe@1.5.0-beta.1 build /home/runner/work/better-auth/better-auth/packages/stripe
3
3
  > tsdown
4
4
 
5
5
  ℹ tsdown v0.17.2 powered by rolldown v1.0.0-beta.53
@@ -7,10 +7,11 @@
7
7
  ℹ entry: src/index.ts, src/client.ts
8
8
  ℹ tsconfig: tsconfig.json
9
9
  ℹ Build start
10
- ℹ dist/index.mjs 40.70 kB │ gzip: 7.59 kB
11
- ℹ dist/client.mjs  0.26 kB │ gzip: 0.20 kB
12
- ℹ dist/client.d.mts  0.62 kB │ gzip: 0.35 kB
13
- ℹ dist/index.d.mts  0.21 kB │ gzip: 0.14 kB
14
- ℹ dist/index-DQa3pHPd.d.mts 24.89 kB │ gzip: 4.83 kB
15
- ℹ 5 files, total: 66.68 kB
16
- ✔ Build complete in 23325ms
10
+ ℹ dist/index.mjs 40.12 kB │ gzip: 7.63 kB
11
+ ℹ dist/client.mjs  0.35 kB │ gzip: 0.25 kB
12
+ ℹ dist/error-codes-qqooUh6R.mjs  0.72 kB │ gzip: 0.42 kB
13
+ ℹ dist/client.d.mts  2.97 kB │ gzip: 0.79 kB
14
+ ℹ dist/index.d.mts  0.21 kB │ gzip: 0.14 kB
15
+ ℹ dist/index-DpiQGYLJ.d.mts 25.42 kB │ gzip: 4.88 kB
16
+ ℹ 6 files, total: 69.80 kB
17
+ ✔ Build complete in 16274ms
package/dist/client.d.mts CHANGED
@@ -1,5 +1,41 @@
1
- import { n as stripe } from "./index-DQa3pHPd.mjs";
1
+ import { n as stripe } from "./index-DpiQGYLJ.mjs";
2
2
 
3
+ //#region src/error-codes.d.ts
4
+ declare const STRIPE_ERROR_CODES: {
5
+ readonly SUBSCRIPTION_NOT_FOUND: {
6
+ code: "SUBSCRIPTION_NOT_FOUND";
7
+ message: "Subscription not found";
8
+ };
9
+ readonly SUBSCRIPTION_PLAN_NOT_FOUND: {
10
+ code: "SUBSCRIPTION_PLAN_NOT_FOUND";
11
+ message: "Subscription plan not found";
12
+ };
13
+ readonly ALREADY_SUBSCRIBED_PLAN: {
14
+ code: "ALREADY_SUBSCRIBED_PLAN";
15
+ message: "You're already subscribed to this plan";
16
+ };
17
+ readonly UNABLE_TO_CREATE_CUSTOMER: {
18
+ code: "UNABLE_TO_CREATE_CUSTOMER";
19
+ message: "Unable to create customer";
20
+ };
21
+ readonly FAILED_TO_FETCH_PLANS: {
22
+ code: "FAILED_TO_FETCH_PLANS";
23
+ message: "Failed to fetch plans";
24
+ };
25
+ readonly EMAIL_VERIFICATION_REQUIRED: {
26
+ code: "EMAIL_VERIFICATION_REQUIRED";
27
+ message: "Email verification is required before you can subscribe to a plan";
28
+ };
29
+ readonly SUBSCRIPTION_NOT_ACTIVE: {
30
+ code: "SUBSCRIPTION_NOT_ACTIVE";
31
+ message: "Subscription is not active";
32
+ };
33
+ readonly SUBSCRIPTION_NOT_SCHEDULED_FOR_CANCELLATION: {
34
+ code: "SUBSCRIPTION_NOT_SCHEDULED_FOR_CANCELLATION";
35
+ message: "Subscription is not scheduled for cancellation";
36
+ };
37
+ };
38
+ //#endregion
3
39
  //#region src/client.d.ts
4
40
  declare const stripeClient: <O extends {
5
41
  subscription: boolean;
@@ -17,9 +53,42 @@ declare const stripeClient: <O extends {
17
53
  stripeWebhookSecret: string;
18
54
  }>>;
19
55
  pathMethods: {
20
- "/subscription/restore": "POST";
21
56
  "/subscription/billing-portal": "POST";
22
57
  };
58
+ $ERROR_CODES: {
59
+ readonly SUBSCRIPTION_NOT_FOUND: {
60
+ code: "SUBSCRIPTION_NOT_FOUND";
61
+ message: "Subscription not found";
62
+ };
63
+ readonly SUBSCRIPTION_PLAN_NOT_FOUND: {
64
+ code: "SUBSCRIPTION_PLAN_NOT_FOUND";
65
+ message: "Subscription plan not found";
66
+ };
67
+ readonly ALREADY_SUBSCRIBED_PLAN: {
68
+ code: "ALREADY_SUBSCRIBED_PLAN";
69
+ message: "You're already subscribed to this plan";
70
+ };
71
+ readonly UNABLE_TO_CREATE_CUSTOMER: {
72
+ code: "UNABLE_TO_CREATE_CUSTOMER";
73
+ message: "Unable to create customer";
74
+ };
75
+ readonly FAILED_TO_FETCH_PLANS: {
76
+ code: "FAILED_TO_FETCH_PLANS";
77
+ message: "Failed to fetch plans";
78
+ };
79
+ readonly EMAIL_VERIFICATION_REQUIRED: {
80
+ code: "EMAIL_VERIFICATION_REQUIRED";
81
+ message: "Email verification is required before you can subscribe to a plan";
82
+ };
83
+ readonly SUBSCRIPTION_NOT_ACTIVE: {
84
+ code: "SUBSCRIPTION_NOT_ACTIVE";
85
+ message: "Subscription is not active";
86
+ };
87
+ readonly SUBSCRIPTION_NOT_SCHEDULED_FOR_CANCELLATION: {
88
+ code: "SUBSCRIPTION_NOT_SCHEDULED_FOR_CANCELLATION";
89
+ message: "Subscription is not scheduled for cancellation";
90
+ };
91
+ };
23
92
  };
24
93
  //#endregion
25
- export { stripeClient };
94
+ export { STRIPE_ERROR_CODES, stripeClient };
package/dist/client.mjs CHANGED
@@ -1,14 +1,14 @@
1
+ import { t as STRIPE_ERROR_CODES } from "./error-codes-qqooUh6R.mjs";
2
+
1
3
  //#region src/client.ts
2
4
  const stripeClient = (options) => {
3
5
  return {
4
6
  id: "stripe-client",
5
7
  $InferServerPlugin: {},
6
- pathMethods: {
7
- "/subscription/restore": "POST",
8
- "/subscription/billing-portal": "POST"
9
- }
8
+ pathMethods: { "/subscription/billing-portal": "POST" },
9
+ $ERROR_CODES: STRIPE_ERROR_CODES
10
10
  };
11
11
  };
12
12
 
13
13
  //#endregion
14
- export { stripeClient };
14
+ export { STRIPE_ERROR_CODES, stripeClient };
@@ -0,0 +1,16 @@
1
+ import { defineErrorCodes } from "@better-auth/core/utils";
2
+
3
+ //#region src/error-codes.ts
4
+ const STRIPE_ERROR_CODES = defineErrorCodes({
5
+ SUBSCRIPTION_NOT_FOUND: "Subscription not found",
6
+ SUBSCRIPTION_PLAN_NOT_FOUND: "Subscription plan not found",
7
+ ALREADY_SUBSCRIBED_PLAN: "You're already subscribed to this plan",
8
+ UNABLE_TO_CREATE_CUSTOMER: "Unable to create customer",
9
+ FAILED_TO_FETCH_PLANS: "Failed to fetch plans",
10
+ EMAIL_VERIFICATION_REQUIRED: "Email verification is required before you can subscribe to a plan",
11
+ SUBSCRIPTION_NOT_ACTIVE: "Subscription is not active",
12
+ SUBSCRIPTION_NOT_SCHEDULED_FOR_CANCELLATION: "Subscription is not scheduled for cancellation"
13
+ });
14
+
15
+ //#endregion
16
+ export { STRIPE_ERROR_CODES as t };
@@ -646,7 +646,7 @@ declare const stripe: <O extends StripeOptions>(options: O) => {
646
646
  };
647
647
  use: ((inputContext: better_call0.MiddlewareInputContext<better_call0.MiddlewareOptions>) => Promise<void>)[];
648
648
  }, {
649
- status: ("OK" | "CREATED" | "ACCEPTED" | "NO_CONTENT" | "MULTIPLE_CHOICES" | "MOVED_PERMANENTLY" | "FOUND" | "SEE_OTHER" | "NOT_MODIFIED" | "TEMPORARY_REDIRECT" | "BAD_REQUEST" | "UNAUTHORIZED" | "PAYMENT_REQUIRED" | "FORBIDDEN" | "NOT_FOUND" | "METHOD_NOT_ALLOWED" | "NOT_ACCEPTABLE" | "PROXY_AUTHENTICATION_REQUIRED" | "REQUEST_TIMEOUT" | "CONFLICT" | "GONE" | "LENGTH_REQUIRED" | "PRECONDITION_FAILED" | "PAYLOAD_TOO_LARGE" | "URI_TOO_LONG" | "UNSUPPORTED_MEDIA_TYPE" | "RANGE_NOT_SATISFIABLE" | "EXPECTATION_FAILED" | "I'M_A_TEAPOT" | "MISDIRECTED_REQUEST" | "UNPROCESSABLE_ENTITY" | "LOCKED" | "FAILED_DEPENDENCY" | "TOO_EARLY" | "UPGRADE_REQUIRED" | "PRECONDITION_REQUIRED" | "TOO_MANY_REQUESTS" | "REQUEST_HEADER_FIELDS_TOO_LARGE" | "UNAVAILABLE_FOR_LEGAL_REASONS" | "INTERNAL_SERVER_ERROR" | "NOT_IMPLEMENTED" | "BAD_GATEWAY" | "SERVICE_UNAVAILABLE" | "GATEWAY_TIMEOUT" | "HTTP_VERSION_NOT_SUPPORTED" | "VARIANT_ALSO_NEGOTIATES" | "INSUFFICIENT_STORAGE" | "LOOP_DETECTED" | "NOT_EXTENDED" | "NETWORK_AUTHENTICATION_REQUIRED") | better_call0.Status;
649
+ status: ("NOT_FOUND" | "FOUND" | "OK" | "CREATED" | "ACCEPTED" | "NO_CONTENT" | "MULTIPLE_CHOICES" | "MOVED_PERMANENTLY" | "SEE_OTHER" | "NOT_MODIFIED" | "TEMPORARY_REDIRECT" | "BAD_REQUEST" | "UNAUTHORIZED" | "PAYMENT_REQUIRED" | "FORBIDDEN" | "METHOD_NOT_ALLOWED" | "NOT_ACCEPTABLE" | "PROXY_AUTHENTICATION_REQUIRED" | "REQUEST_TIMEOUT" | "CONFLICT" | "GONE" | "LENGTH_REQUIRED" | "PRECONDITION_FAILED" | "PAYLOAD_TOO_LARGE" | "URI_TOO_LONG" | "UNSUPPORTED_MEDIA_TYPE" | "RANGE_NOT_SATISFIABLE" | "EXPECTATION_FAILED" | "I'M_A_TEAPOT" | "MISDIRECTED_REQUEST" | "UNPROCESSABLE_ENTITY" | "LOCKED" | "FAILED_DEPENDENCY" | "TOO_EARLY" | "UPGRADE_REQUIRED" | "PRECONDITION_REQUIRED" | "TOO_MANY_REQUESTS" | "REQUEST_HEADER_FIELDS_TOO_LARGE" | "UNAVAILABLE_FOR_LEGAL_REASONS" | "INTERNAL_SERVER_ERROR" | "NOT_IMPLEMENTED" | "BAD_GATEWAY" | "SERVICE_UNAVAILABLE" | "GATEWAY_TIMEOUT" | "HTTP_VERSION_NOT_SUPPORTED" | "VARIANT_ALSO_NEGOTIATES" | "INSUFFICIENT_STORAGE" | "LOOP_DETECTED" | "NOT_EXTENDED" | "NETWORK_AUTHENTICATION_REQUIRED") | better_call0.Status;
650
650
  body: ({
651
651
  message?: string;
652
652
  code?: string;
@@ -732,14 +732,38 @@ declare const stripe: <O extends StripeOptions>(options: O) => {
732
732
  schema: {};
733
733
  options: NoInfer<O>;
734
734
  $ERROR_CODES: {
735
- readonly SUBSCRIPTION_NOT_FOUND: "Subscription not found";
736
- readonly SUBSCRIPTION_PLAN_NOT_FOUND: "Subscription plan not found";
737
- readonly ALREADY_SUBSCRIBED_PLAN: "You're already subscribed to this plan";
738
- readonly UNABLE_TO_CREATE_CUSTOMER: "Unable to create customer";
739
- readonly FAILED_TO_FETCH_PLANS: "Failed to fetch plans";
740
- readonly EMAIL_VERIFICATION_REQUIRED: "Email verification is required before you can subscribe to a plan";
741
- readonly SUBSCRIPTION_NOT_ACTIVE: "Subscription is not active";
742
- readonly SUBSCRIPTION_NOT_SCHEDULED_FOR_CANCELLATION: "Subscription is not scheduled for cancellation";
735
+ readonly SUBSCRIPTION_NOT_FOUND: {
736
+ code: "SUBSCRIPTION_NOT_FOUND";
737
+ message: "Subscription not found";
738
+ };
739
+ readonly SUBSCRIPTION_PLAN_NOT_FOUND: {
740
+ code: "SUBSCRIPTION_PLAN_NOT_FOUND";
741
+ message: "Subscription plan not found";
742
+ };
743
+ readonly ALREADY_SUBSCRIBED_PLAN: {
744
+ code: "ALREADY_SUBSCRIBED_PLAN";
745
+ message: "You're already subscribed to this plan";
746
+ };
747
+ readonly UNABLE_TO_CREATE_CUSTOMER: {
748
+ code: "UNABLE_TO_CREATE_CUSTOMER";
749
+ message: "Unable to create customer";
750
+ };
751
+ readonly FAILED_TO_FETCH_PLANS: {
752
+ code: "FAILED_TO_FETCH_PLANS";
753
+ message: "Failed to fetch plans";
754
+ };
755
+ readonly EMAIL_VERIFICATION_REQUIRED: {
756
+ code: "EMAIL_VERIFICATION_REQUIRED";
757
+ message: "Email verification is required before you can subscribe to a plan";
758
+ };
759
+ readonly SUBSCRIPTION_NOT_ACTIVE: {
760
+ code: "SUBSCRIPTION_NOT_ACTIVE";
761
+ message: "Subscription is not active";
762
+ };
763
+ readonly SUBSCRIPTION_NOT_SCHEDULED_FOR_CANCELLATION: {
764
+ code: "SUBSCRIPTION_NOT_SCHEDULED_FOR_CANCELLATION";
765
+ message: "Subscription is not scheduled for cancellation";
766
+ };
743
767
  };
744
768
  };
745
769
  type StripePlugin<O extends StripeOptions> = ReturnType<typeof stripe<O>>;
package/dist/index.d.mts CHANGED
@@ -1,2 +1,2 @@
1
- import { a as SubscriptionOptions, i as Subscription, n as stripe, r as StripePlan, t as StripePlugin } from "./index-DQa3pHPd.mjs";
1
+ import { a as SubscriptionOptions, i as Subscription, n as stripe, r as StripePlan, t as StripePlugin } from "./index-DpiQGYLJ.mjs";
2
2
  export { StripePlan, StripePlugin, Subscription, SubscriptionOptions, stripe };
package/dist/index.mjs CHANGED
@@ -1,8 +1,10 @@
1
+ import { t as STRIPE_ERROR_CODES$1 } from "./error-codes-qqooUh6R.mjs";
1
2
  import { defineErrorCodes } from "@better-auth/core/utils";
2
3
  import { defu } from "defu";
3
4
  import { createAuthEndpoint, createAuthMiddleware } from "@better-auth/core/api";
5
+ import { APIError } from "@better-auth/core/error";
4
6
  import { HIDE_METADATA, logger } from "better-auth";
5
- import { APIError, getSessionFromCtx, originCheck, sessionMiddleware } from "better-auth/api";
7
+ import { APIError as APIError$1, getSessionFromCtx, originCheck, sessionMiddleware } from "better-auth/api";
6
8
  import * as z from "zod/v4";
7
9
  import { mergeSchema } from "better-auth/db";
8
10
 
@@ -188,11 +190,11 @@ async function onSubscriptionDeleted(ctx, options, event) {
188
190
  //#region src/middleware.ts
189
191
  const referenceMiddleware = (subscriptionOptions, action) => createAuthMiddleware(async (ctx) => {
190
192
  const session = ctx.context.session;
191
- if (!session) throw new APIError("UNAUTHORIZED");
193
+ if (!session) throw new APIError$1("UNAUTHORIZED");
192
194
  const referenceId = ctx.body?.referenceId || ctx.query?.referenceId || session.user.id;
193
195
  if (referenceId !== session.user.id && !subscriptionOptions.authorizeReference) {
194
196
  logger.error(`Passing referenceId into a subscription action isn't allowed if subscription.authorizeReference isn't defined in your stripe plugin config.`);
195
- throw new APIError("BAD_REQUEST", { message: "Reference id is not allowed. Read server logs for more details." });
197
+ throw new APIError$1("BAD_REQUEST", { message: "Reference id is not allowed. Read server logs for more details." });
196
198
  }
197
199
  /**
198
200
  * if referenceId is the same as the active session user's id
@@ -203,21 +205,11 @@ const referenceMiddleware = (subscriptionOptions, action) => createAuthMiddlewar
203
205
  session: session.session,
204
206
  referenceId,
205
207
  action
206
- }, ctx) || sameReference : true)) throw new APIError("UNAUTHORIZED", { message: "Unauthorized" });
208
+ }, ctx) || sameReference : true)) throw new APIError$1("UNAUTHORIZED", { message: "Unauthorized" });
207
209
  });
208
210
 
209
211
  //#endregion
210
212
  //#region src/routes.ts
211
- const STRIPE_ERROR_CODES$1 = defineErrorCodes({
212
- SUBSCRIPTION_NOT_FOUND: "Subscription not found",
213
- SUBSCRIPTION_PLAN_NOT_FOUND: "Subscription plan not found",
214
- ALREADY_SUBSCRIBED_PLAN: "You're already subscribed to this plan",
215
- UNABLE_TO_CREATE_CUSTOMER: "Unable to create customer",
216
- FAILED_TO_FETCH_PLANS: "Failed to fetch plans",
217
- EMAIL_VERIFICATION_REQUIRED: "Email verification is required before you can subscribe to a plan",
218
- SUBSCRIPTION_NOT_ACTIVE: "Subscription is not active",
219
- SUBSCRIPTION_NOT_SCHEDULED_FOR_CANCELLATION: "Subscription is not scheduled for cancellation"
220
- });
221
213
  const upgradeSubscriptionBodySchema = z.object({
222
214
  plan: z.string().meta({ description: "The name of the plan to upgrade to. Eg: \"pro\"" }),
223
215
  annual: z.boolean().meta({ description: "Whether to upgrade to an annual plan. Eg: true" }).optional(),
@@ -261,10 +253,10 @@ const upgradeSubscription = (options) => {
261
253
  ]
262
254
  }, async (ctx) => {
263
255
  const { user: user$1, session } = ctx.context.session;
264
- if (!user$1.emailVerified && subscriptionOptions.requireEmailVerification) throw new APIError("BAD_REQUEST", { message: STRIPE_ERROR_CODES$1.EMAIL_VERIFICATION_REQUIRED });
256
+ if (!user$1.emailVerified && subscriptionOptions.requireEmailVerification) throw APIError.from("BAD_REQUEST", STRIPE_ERROR_CODES$1.EMAIL_VERIFICATION_REQUIRED);
265
257
  const referenceId = ctx.body.referenceId || user$1.id;
266
258
  const plan = await getPlanByName(options, ctx.body.plan);
267
- if (!plan) throw new APIError("BAD_REQUEST", { message: STRIPE_ERROR_CODES$1.SUBSCRIPTION_PLAN_NOT_FOUND });
259
+ if (!plan) throw APIError.from("BAD_REQUEST", STRIPE_ERROR_CODES$1.SUBSCRIPTION_PLAN_NOT_FOUND);
268
260
  let subscriptionToUpdate = ctx.body.subscriptionId ? await ctx.context.adapter.findOne({
269
261
  model: "subscription",
270
262
  where: [{
@@ -279,7 +271,7 @@ const upgradeSubscription = (options) => {
279
271
  }]
280
272
  }) : null;
281
273
  if (ctx.body.subscriptionId && subscriptionToUpdate && subscriptionToUpdate.referenceId !== referenceId) subscriptionToUpdate = null;
282
- if (ctx.body.subscriptionId && !subscriptionToUpdate) throw new APIError("BAD_REQUEST", { message: STRIPE_ERROR_CODES$1.SUBSCRIPTION_NOT_FOUND });
274
+ if (ctx.body.subscriptionId && !subscriptionToUpdate) throw APIError.from("BAD_REQUEST", STRIPE_ERROR_CODES$1.SUBSCRIPTION_NOT_FOUND);
283
275
  let customerId = subscriptionToUpdate?.stripeCustomerId || user$1.stripeCustomerId;
284
276
  if (!customerId) try {
285
277
  let stripeCustomer = (await client.customers.list({
@@ -305,7 +297,7 @@ const upgradeSubscription = (options) => {
305
297
  customerId = stripeCustomer.id;
306
298
  } catch (e) {
307
299
  ctx.context.logger.error(e);
308
- throw new APIError("BAD_REQUEST", { message: STRIPE_ERROR_CODES$1.UNABLE_TO_CREATE_CUSTOMER });
300
+ throw APIError.from("BAD_REQUEST", STRIPE_ERROR_CODES$1.UNABLE_TO_CREATE_CUSTOMER);
309
301
  }
310
302
  const subscriptions$1 = subscriptionToUpdate ? [subscriptionToUpdate] : await ctx.context.adapter.findMany({
311
303
  model: "subscription",
@@ -321,7 +313,7 @@ const upgradeSubscription = (options) => {
321
313
  return false;
322
314
  });
323
315
  const incompleteSubscription = subscriptions$1.find((sub) => sub.status === "incomplete");
324
- if (activeOrTrialingSubscription && activeOrTrialingSubscription.status === "active" && activeOrTrialingSubscription.plan === ctx.body.plan && activeOrTrialingSubscription.seats === (ctx.body.seats || 1)) throw new APIError("BAD_REQUEST", { message: STRIPE_ERROR_CODES$1.ALREADY_SUBSCRIBED_PLAN });
316
+ if (activeOrTrialingSubscription && activeOrTrialingSubscription.status === "active" && activeOrTrialingSubscription.plan === ctx.body.plan && activeOrTrialingSubscription.seats === (ctx.body.seats || 1)) throw APIError.from("BAD_REQUEST", STRIPE_ERROR_CODES$1.ALREADY_SUBSCRIBED_PLAN);
325
317
  if (activeSubscription && customerId) {
326
318
  let dbSubscription = await ctx.context.adapter.findOne({
327
319
  model: "subscription",
@@ -563,7 +555,7 @@ const cancelSubscription = (options) => {
563
555
  }]
564
556
  }).then((subs) => subs.find((sub) => sub.status === "active" || sub.status === "trialing"));
565
557
  if (ctx.body.subscriptionId && subscription && subscription.referenceId !== referenceId) subscription = void 0;
566
- if (!subscription || !subscription.stripeCustomerId) throw ctx.error("BAD_REQUEST", { message: STRIPE_ERROR_CODES$1.SUBSCRIPTION_NOT_FOUND });
558
+ if (!subscription || !subscription.stripeCustomerId) throw APIError.from("BAD_REQUEST", STRIPE_ERROR_CODES$1.SUBSCRIPTION_NOT_FOUND);
567
559
  const activeSubscriptions = await client.subscriptions.list({ customer: subscription.stripeCustomerId }).then((res) => res.data.filter((sub) => sub.status === "active" || sub.status === "trialing"));
568
560
  if (!activeSubscriptions.length) {
569
561
  /**
@@ -577,10 +569,10 @@ const cancelSubscription = (options) => {
577
569
  value: referenceId
578
570
  }]
579
571
  });
580
- throw ctx.error("BAD_REQUEST", { message: STRIPE_ERROR_CODES$1.SUBSCRIPTION_NOT_FOUND });
572
+ throw APIError.from("BAD_REQUEST", STRIPE_ERROR_CODES$1.SUBSCRIPTION_NOT_FOUND);
581
573
  }
582
574
  const activeSubscription = activeSubscriptions.find((sub) => sub.id === subscription.stripeSubscriptionId);
583
- if (!activeSubscription) throw ctx.error("BAD_REQUEST", { message: STRIPE_ERROR_CODES$1.SUBSCRIPTION_NOT_FOUND });
575
+ if (!activeSubscription) throw APIError.from("BAD_REQUEST", STRIPE_ERROR_CODES$1.SUBSCRIPTION_NOT_FOUND);
584
576
  const { url } = await client.billingPortal.sessions.create({
585
577
  customer: subscription.stripeCustomerId,
586
578
  return_url: getUrl(ctx, `${ctx.context.baseURL}/subscription/cancel/callback?callbackURL=${encodeURIComponent(ctx.body?.returnUrl || "/")}&subscriptionId=${encodeURIComponent(subscription.id)}`),
@@ -642,11 +634,11 @@ const restoreSubscription = (options) => {
642
634
  }]
643
635
  }).then((subs) => subs.find((sub) => sub.status === "active" || sub.status === "trialing"));
644
636
  if (ctx.body.subscriptionId && subscription && subscription.referenceId !== referenceId) subscription = void 0;
645
- if (!subscription || !subscription.stripeCustomerId) throw ctx.error("BAD_REQUEST", { message: STRIPE_ERROR_CODES$1.SUBSCRIPTION_NOT_FOUND });
646
- if (subscription.status != "active" && subscription.status != "trialing") throw ctx.error("BAD_REQUEST", { message: STRIPE_ERROR_CODES$1.SUBSCRIPTION_NOT_ACTIVE });
647
- if (!subscription.cancelAtPeriodEnd) throw ctx.error("BAD_REQUEST", { message: STRIPE_ERROR_CODES$1.SUBSCRIPTION_NOT_SCHEDULED_FOR_CANCELLATION });
637
+ if (!subscription || !subscription.stripeCustomerId) throw APIError.from("BAD_REQUEST", STRIPE_ERROR_CODES$1.SUBSCRIPTION_NOT_FOUND);
638
+ if (subscription.status != "active" && subscription.status != "trialing") throw APIError.from("BAD_REQUEST", STRIPE_ERROR_CODES$1.SUBSCRIPTION_NOT_ACTIVE);
639
+ if (!subscription.cancelAtPeriodEnd) throw APIError.from("BAD_REQUEST", STRIPE_ERROR_CODES$1.SUBSCRIPTION_NOT_SCHEDULED_FOR_CANCELLATION);
648
640
  const activeSubscription = await client.subscriptions.list({ customer: subscription.stripeCustomerId }).then((res) => res.data.filter((sub) => sub.status === "active" || sub.status === "trialing")[0]);
649
- if (!activeSubscription) throw ctx.error("BAD_REQUEST", { message: STRIPE_ERROR_CODES$1.SUBSCRIPTION_NOT_FOUND });
641
+ if (!activeSubscription) throw APIError.from("BAD_REQUEST", STRIPE_ERROR_CODES$1.SUBSCRIPTION_NOT_FOUND);
650
642
  try {
651
643
  const newSub = await client.subscriptions.update(activeSubscription.id, { cancel_at_period_end: false });
652
644
  await ctx.context.adapter.update({
@@ -663,7 +655,7 @@ const restoreSubscription = (options) => {
663
655
  return ctx.json(newSub);
664
656
  } catch (error) {
665
657
  ctx.context.logger.error("Error restoring subscription", error);
666
- throw new APIError("BAD_REQUEST", { message: STRIPE_ERROR_CODES$1.UNABLE_TO_CREATE_CUSTOMER });
658
+ throw APIError.from("BAD_REQUEST", STRIPE_ERROR_CODES$1.UNABLE_TO_CREATE_CUSTOMER);
667
659
  }
668
660
  });
669
661
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@better-auth/stripe",
3
3
  "author": "Bereket Engida",
4
- "version": "1.4.9",
4
+ "version": "1.5.0-beta.1",
5
5
  "type": "module",
6
6
  "main": "dist/index.mjs",
7
7
  "types": "dist/index.d.mts",
@@ -50,15 +50,15 @@
50
50
  },
51
51
  "peerDependencies": {
52
52
  "stripe": "^18 || ^19 || ^20",
53
- "@better-auth/core": "1.4.9",
54
- "better-auth": "1.4.9"
53
+ "@better-auth/core": "1.5.0-beta.1",
54
+ "better-auth": "1.5.0-beta.1"
55
55
  },
56
56
  "devDependencies": {
57
57
  "better-call": "1.1.7",
58
58
  "stripe": "^20.0.0",
59
59
  "tsdown": "^0.17.2",
60
- "@better-auth/core": "1.4.9",
61
- "better-auth": "1.4.9"
60
+ "@better-auth/core": "1.5.0-beta.1",
61
+ "better-auth": "1.5.0-beta.1"
62
62
  },
63
63
  "scripts": {
64
64
  "test": "vitest",
package/src/client.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import type { BetterAuthClientPlugin } from "better-auth";
2
+ import { STRIPE_ERROR_CODES } from "./error-codes";
2
3
  import type { stripe } from "./index";
3
4
 
4
5
  export const stripeClient = <
@@ -28,8 +29,9 @@ export const stripeClient = <
28
29
  >
29
30
  >,
30
31
  pathMethods: {
31
- "/subscription/restore": "POST",
32
32
  "/subscription/billing-portal": "POST",
33
33
  },
34
+ $ERROR_CODES: STRIPE_ERROR_CODES,
34
35
  } satisfies BetterAuthClientPlugin;
35
36
  };
37
+ export * from "./error-codes";
@@ -0,0 +1,14 @@
1
+ import { defineErrorCodes } from "@better-auth/core/utils";
2
+
3
+ export const STRIPE_ERROR_CODES = defineErrorCodes({
4
+ SUBSCRIPTION_NOT_FOUND: "Subscription not found",
5
+ SUBSCRIPTION_PLAN_NOT_FOUND: "Subscription plan not found",
6
+ ALREADY_SUBSCRIBED_PLAN: "You're already subscribed to this plan",
7
+ UNABLE_TO_CREATE_CUSTOMER: "Unable to create customer",
8
+ FAILED_TO_FETCH_PLANS: "Failed to fetch plans",
9
+ EMAIL_VERIFICATION_REQUIRED:
10
+ "Email verification is required before you can subscribe to a plan",
11
+ SUBSCRIPTION_NOT_ACTIVE: "Subscription is not active",
12
+ SUBSCRIPTION_NOT_SCHEDULED_FOR_CANCELLATION:
13
+ "Subscription is not scheduled for cancellation",
14
+ });
package/src/routes.ts CHANGED
@@ -1,9 +1,8 @@
1
1
  import { createAuthEndpoint } from "@better-auth/core/api";
2
- import { defineErrorCodes } from "@better-auth/core/utils";
2
+ import { APIError } from "@better-auth/core/error";
3
3
  import type { GenericEndpointContext } from "better-auth";
4
4
  import { HIDE_METADATA } from "better-auth";
5
5
  import {
6
- APIError,
7
6
  getSessionFromCtx,
8
7
  originCheck,
9
8
  sessionMiddleware,
@@ -11,6 +10,7 @@ import {
11
10
  import type Stripe from "stripe";
12
11
  import type { Stripe as StripeType } from "stripe";
13
12
  import * as z from "zod/v4";
13
+ import { STRIPE_ERROR_CODES } from "./error-codes";
14
14
  import {
15
15
  onCheckoutSessionCompleted,
16
16
  onSubscriptionDeleted,
@@ -25,19 +25,6 @@ import type {
25
25
  } from "./types";
26
26
  import { getPlanByName, getPlanByPriceInfo, getPlans } from "./utils";
27
27
 
28
- const STRIPE_ERROR_CODES = defineErrorCodes({
29
- SUBSCRIPTION_NOT_FOUND: "Subscription not found",
30
- SUBSCRIPTION_PLAN_NOT_FOUND: "Subscription plan not found",
31
- ALREADY_SUBSCRIBED_PLAN: "You're already subscribed to this plan",
32
- UNABLE_TO_CREATE_CUSTOMER: "Unable to create customer",
33
- FAILED_TO_FETCH_PLANS: "Failed to fetch plans",
34
- EMAIL_VERIFICATION_REQUIRED:
35
- "Email verification is required before you can subscribe to a plan",
36
- SUBSCRIPTION_NOT_ACTIVE: "Subscription is not active",
37
- SUBSCRIPTION_NOT_SCHEDULED_FOR_CANCELLATION:
38
- "Subscription is not scheduled for cancellation",
39
- });
40
-
41
28
  const upgradeSubscriptionBodySchema = z.object({
42
29
  /**
43
30
  * The name of the plan to subscribe
@@ -171,16 +158,18 @@ export const upgradeSubscription = (options: StripeOptions) => {
171
158
  async (ctx) => {
172
159
  const { user, session } = ctx.context.session;
173
160
  if (!user.emailVerified && subscriptionOptions.requireEmailVerification) {
174
- throw new APIError("BAD_REQUEST", {
175
- message: STRIPE_ERROR_CODES.EMAIL_VERIFICATION_REQUIRED,
176
- });
161
+ throw APIError.from(
162
+ "BAD_REQUEST",
163
+ STRIPE_ERROR_CODES.EMAIL_VERIFICATION_REQUIRED,
164
+ );
177
165
  }
178
166
  const referenceId = ctx.body.referenceId || user.id;
179
167
  const plan = await getPlanByName(options, ctx.body.plan);
180
168
  if (!plan) {
181
- throw new APIError("BAD_REQUEST", {
182
- message: STRIPE_ERROR_CODES.SUBSCRIPTION_PLAN_NOT_FOUND,
183
- });
169
+ throw APIError.from(
170
+ "BAD_REQUEST",
171
+ STRIPE_ERROR_CODES.SUBSCRIPTION_PLAN_NOT_FOUND,
172
+ );
184
173
  }
185
174
  let subscriptionToUpdate = ctx.body.subscriptionId
186
175
  ? await ctx.context.adapter.findOne<Subscription>({
@@ -208,9 +197,10 @@ export const upgradeSubscription = (options: StripeOptions) => {
208
197
  }
209
198
 
210
199
  if (ctx.body.subscriptionId && !subscriptionToUpdate) {
211
- throw new APIError("BAD_REQUEST", {
212
- message: STRIPE_ERROR_CODES.SUBSCRIPTION_NOT_FOUND,
213
- });
200
+ throw APIError.from(
201
+ "BAD_REQUEST",
202
+ STRIPE_ERROR_CODES.SUBSCRIPTION_NOT_FOUND,
203
+ );
214
204
  }
215
205
 
216
206
  let customerId =
@@ -254,9 +244,10 @@ export const upgradeSubscription = (options: StripeOptions) => {
254
244
  customerId = stripeCustomer.id;
255
245
  } catch (e: any) {
256
246
  ctx.context.logger.error(e);
257
- throw new APIError("BAD_REQUEST", {
258
- message: STRIPE_ERROR_CODES.UNABLE_TO_CREATE_CUSTOMER,
259
- });
247
+ throw APIError.from(
248
+ "BAD_REQUEST",
249
+ STRIPE_ERROR_CODES.UNABLE_TO_CREATE_CUSTOMER,
250
+ );
260
251
  }
261
252
  }
262
253
 
@@ -315,9 +306,10 @@ export const upgradeSubscription = (options: StripeOptions) => {
315
306
  activeOrTrialingSubscription.plan === ctx.body.plan &&
316
307
  activeOrTrialingSubscription.seats === (ctx.body.seats || 1)
317
308
  ) {
318
- throw new APIError("BAD_REQUEST", {
319
- message: STRIPE_ERROR_CODES.ALREADY_SUBSCRIBED_PLAN,
320
- });
309
+ throw APIError.from(
310
+ "BAD_REQUEST",
311
+ STRIPE_ERROR_CODES.ALREADY_SUBSCRIBED_PLAN,
312
+ );
321
313
  }
322
314
 
323
315
  if (activeSubscription && customerId) {
@@ -732,9 +724,10 @@ export const cancelSubscription = (options: StripeOptions) => {
732
724
  }
733
725
 
734
726
  if (!subscription || !subscription.stripeCustomerId) {
735
- throw ctx.error("BAD_REQUEST", {
736
- message: STRIPE_ERROR_CODES.SUBSCRIPTION_NOT_FOUND,
737
- });
727
+ throw APIError.from(
728
+ "BAD_REQUEST",
729
+ STRIPE_ERROR_CODES.SUBSCRIPTION_NOT_FOUND,
730
+ );
738
731
  }
739
732
  const activeSubscriptions = await client.subscriptions
740
733
  .list({
@@ -759,17 +752,19 @@ export const cancelSubscription = (options: StripeOptions) => {
759
752
  },
760
753
  ],
761
754
  });
762
- throw ctx.error("BAD_REQUEST", {
763
- message: STRIPE_ERROR_CODES.SUBSCRIPTION_NOT_FOUND,
764
- });
755
+ throw APIError.from(
756
+ "BAD_REQUEST",
757
+ STRIPE_ERROR_CODES.SUBSCRIPTION_NOT_FOUND,
758
+ );
765
759
  }
766
760
  const activeSubscription = activeSubscriptions.find(
767
761
  (sub) => sub.id === subscription.stripeSubscriptionId,
768
762
  );
769
763
  if (!activeSubscription) {
770
- throw ctx.error("BAD_REQUEST", {
771
- message: STRIPE_ERROR_CODES.SUBSCRIPTION_NOT_FOUND,
772
- });
764
+ throw APIError.from(
765
+ "BAD_REQUEST",
766
+ STRIPE_ERROR_CODES.SUBSCRIPTION_NOT_FOUND,
767
+ );
773
768
  }
774
769
  const { url } = await client.billingPortal.sessions
775
770
  .create({
@@ -893,23 +888,25 @@ export const restoreSubscription = (options: StripeOptions) => {
893
888
  subscription = undefined;
894
889
  }
895
890
  if (!subscription || !subscription.stripeCustomerId) {
896
- throw ctx.error("BAD_REQUEST", {
897
- message: STRIPE_ERROR_CODES.SUBSCRIPTION_NOT_FOUND,
898
- });
891
+ throw APIError.from(
892
+ "BAD_REQUEST",
893
+ STRIPE_ERROR_CODES.SUBSCRIPTION_NOT_FOUND,
894
+ );
899
895
  }
900
896
  if (
901
897
  subscription.status != "active" &&
902
898
  subscription.status != "trialing"
903
899
  ) {
904
- throw ctx.error("BAD_REQUEST", {
905
- message: STRIPE_ERROR_CODES.SUBSCRIPTION_NOT_ACTIVE,
906
- });
900
+ throw APIError.from(
901
+ "BAD_REQUEST",
902
+ STRIPE_ERROR_CODES.SUBSCRIPTION_NOT_ACTIVE,
903
+ );
907
904
  }
908
905
  if (!subscription.cancelAtPeriodEnd) {
909
- throw ctx.error("BAD_REQUEST", {
910
- message:
911
- STRIPE_ERROR_CODES.SUBSCRIPTION_NOT_SCHEDULED_FOR_CANCELLATION,
912
- });
906
+ throw APIError.from(
907
+ "BAD_REQUEST",
908
+ STRIPE_ERROR_CODES.SUBSCRIPTION_NOT_SCHEDULED_FOR_CANCELLATION,
909
+ );
913
910
  }
914
911
 
915
912
  const activeSubscription = await client.subscriptions
@@ -923,9 +920,10 @@ export const restoreSubscription = (options: StripeOptions) => {
923
920
  )[0],
924
921
  );
925
922
  if (!activeSubscription) {
926
- throw ctx.error("BAD_REQUEST", {
927
- message: STRIPE_ERROR_CODES.SUBSCRIPTION_NOT_FOUND,
928
- });
923
+ throw APIError.from(
924
+ "BAD_REQUEST",
925
+ STRIPE_ERROR_CODES.SUBSCRIPTION_NOT_FOUND,
926
+ );
929
927
  }
930
928
 
931
929
  try {
@@ -953,9 +951,10 @@ export const restoreSubscription = (options: StripeOptions) => {
953
951
  return ctx.json(newSub);
954
952
  } catch (error) {
955
953
  ctx.context.logger.error("Error restoring subscription", error);
956
- throw new APIError("BAD_REQUEST", {
957
- message: STRIPE_ERROR_CODES.UNABLE_TO_CREATE_CUSTOMER,
958
- });
954
+ throw APIError.from(
955
+ "BAD_REQUEST",
956
+ STRIPE_ERROR_CODES.UNABLE_TO_CREATE_CUSTOMER,
957
+ );
959
958
  }
960
959
  },
961
960
  );