@better-auth/stripe 1.2.9-beta.8 → 1.2.9

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,17 +1,17 @@
1
1
 
2
- > @better-auth/stripe@1.2.9-beta.8 build /home/runner/work/better-auth/better-auth/packages/stripe
2
+ > @better-auth/stripe@1.2.9 build /home/runner/work/better-auth/better-auth/packages/stripe
3
3
  > unbuild
4
4
 
5
5
  [info] Automatically detected entries: src/index, src/client [esm] [cjs] [dts]
6
6
  [info] Building stripe
7
7
  [success] Build succeeded for stripe
8
- [log] dist/index.cjs (total size: 37.6 kB, chunk size: 37.6 kB, exports: stripe)
8
+ [log] dist/index.cjs (total size: 38.5 kB, chunk size: 38.5 kB, exports: stripe)
9
9
 
10
10
  [log] dist/client.cjs (total size: 224 B, chunk size: 224 B, exports: stripeClient)
11
11
 
12
- [log] dist/index.mjs (total size: 37.3 kB, chunk size: 37.3 kB, exports: stripe)
12
+ [log] dist/index.mjs (total size: 38.2 kB, chunk size: 38.2 kB, exports: stripe)
13
13
 
14
14
  [log] dist/client.mjs (total size: 197 B, chunk size: 197 B, exports: stripeClient)
15
15
 
16
- Σ Total dist size (byte size): 202 kB
16
+ Σ Total dist size (byte size): 204 kB
17
17
  [log]
package/dist/index.cjs CHANGED
@@ -306,6 +306,15 @@ const getUrl = (ctx, url) => {
306
306
  }
307
307
  return `${ctx.context.options.baseURL}${url.startsWith("/") ? url : `/${url}`}`;
308
308
  };
309
+ async function resolvePriceIdFromLookupKey(stripeClient, lookupKey) {
310
+ if (!lookupKey) return void 0;
311
+ const prices = await stripeClient.prices.list({
312
+ lookup_keys: [lookupKey],
313
+ active: true,
314
+ limit: 1
315
+ });
316
+ return prices.data[0]?.id;
317
+ }
309
318
  const stripe = (options) => {
310
319
  const client = options.stripeClient;
311
320
  const referenceMiddleware = (action) => plugins.createAuthMiddleware(async (ctx) => {
@@ -483,7 +492,7 @@ const stripe = (options) => {
483
492
  status: "active"
484
493
  }).then(
485
494
  (res) => res.data.find(
486
- (subscription2) => subscription2.id === ctx.body.subscriptionId
495
+ (subscription2) => subscription2.id === subscriptionToUpdate?.stripeSubscriptionId || ctx.body.subscriptionId
487
496
  )
488
497
  ).catch((e) => null) : null;
489
498
  const subscriptions = subscriptionToUpdate ? [subscriptionToUpdate] : await ctx.context.adapter.findMany({
@@ -498,7 +507,7 @@ const stripe = (options) => {
498
507
  const existingSubscription = subscriptions.find(
499
508
  (sub) => sub.status === "active" || sub.status === "trialing"
500
509
  );
501
- if (existingSubscription && existingSubscription.status === "active" && existingSubscription.plan === ctx.body.plan) {
510
+ if (existingSubscription && existingSubscription.status === "active" && existingSubscription.plan === ctx.body.plan && existingSubscription.seats === (ctx.body.seats || 1)) {
502
511
  throw new api.APIError("BAD_REQUEST", {
503
512
  message: STRIPE_ERROR_CODES.ALREADY_SUBSCRIBED_PLAN
504
513
  });
@@ -514,7 +523,7 @@ const stripe = (options) => {
514
523
  items: [
515
524
  {
516
525
  id: activeSubscription.items.data[0]?.id,
517
- quantity: 1,
526
+ quantity: ctx.body.seats || 1,
518
527
  price: ctx.body.annual ? plan.annualDiscountPriceId : plan.priceId
519
528
  }
520
529
  ]
@@ -561,6 +570,24 @@ const stripe = (options) => {
561
570
  const freeTrail = plan.freeTrial ? {
562
571
  trial_period_days: plan.freeTrial.days
563
572
  } : void 0;
573
+ let priceIdToUse = void 0;
574
+ if (ctx.body.annual) {
575
+ priceIdToUse = plan.annualDiscountPriceId;
576
+ if (!priceIdToUse && plan.annualDiscountLookupKey) {
577
+ priceIdToUse = await resolvePriceIdFromLookupKey(
578
+ client,
579
+ plan.annualDiscountLookupKey
580
+ );
581
+ }
582
+ } else {
583
+ priceIdToUse = plan.priceId;
584
+ if (!priceIdToUse && plan.lookupKey) {
585
+ priceIdToUse = await resolvePriceIdFromLookupKey(
586
+ client,
587
+ plan.lookupKey
588
+ );
589
+ }
590
+ }
564
591
  const checkoutSession = await client.checkout.sessions.create(
565
592
  {
566
593
  ...customerId ? {
@@ -581,7 +608,7 @@ const stripe = (options) => {
581
608
  cancel_url: getUrl(ctx, ctx.body.cancelUrl),
582
609
  line_items: [
583
610
  {
584
- price: ctx.body.annual ? plan.annualDiscountPriceId : plan.priceId,
611
+ price: priceIdToUse,
585
612
  quantity: ctx.body.seats || 1
586
613
  }
587
614
  ],
package/dist/index.d.cts CHANGED
@@ -656,19 +656,19 @@ declare const stripe: <O extends StripeOptions>(options: O) => {
656
656
  session: {
657
657
  session: Record<string, any> & {
658
658
  id: string;
659
- createdAt: Date;
660
- updatedAt: Date;
661
659
  token: string;
662
- expiresAt: Date;
663
660
  userId: string;
661
+ expiresAt: Date;
662
+ createdAt: Date;
663
+ updatedAt: Date;
664
664
  ipAddress?: string | null | undefined;
665
665
  userAgent?: string | null | undefined;
666
666
  };
667
667
  user: Record<string, any> & {
668
668
  id: string;
669
- email: string;
670
- emailVerified: boolean;
671
669
  name: string;
670
+ emailVerified: boolean;
671
+ email: string;
672
672
  createdAt: Date;
673
673
  updatedAt: Date;
674
674
  image?: string | null | undefined;
@@ -768,19 +768,19 @@ declare const stripe: <O extends StripeOptions>(options: O) => {
768
768
  session: {
769
769
  session: Record<string, any> & {
770
770
  id: string;
771
- createdAt: Date;
772
- updatedAt: Date;
773
771
  token: string;
774
- expiresAt: Date;
775
772
  userId: string;
773
+ expiresAt: Date;
774
+ createdAt: Date;
775
+ updatedAt: Date;
776
776
  ipAddress?: string | null | undefined;
777
777
  userAgent?: string | null | undefined;
778
778
  };
779
779
  user: Record<string, any> & {
780
780
  id: string;
781
- email: string;
782
- emailVerified: boolean;
783
781
  name: string;
782
+ emailVerified: boolean;
783
+ email: string;
784
784
  createdAt: Date;
785
785
  updatedAt: Date;
786
786
  image?: string | null | undefined;
@@ -836,19 +836,19 @@ declare const stripe: <O extends StripeOptions>(options: O) => {
836
836
  session: {
837
837
  session: Record<string, any> & {
838
838
  id: string;
839
- createdAt: Date;
840
- updatedAt: Date;
841
839
  token: string;
842
- expiresAt: Date;
843
840
  userId: string;
841
+ expiresAt: Date;
842
+ createdAt: Date;
843
+ updatedAt: Date;
844
844
  ipAddress?: string | null | undefined;
845
845
  userAgent?: string | null | undefined;
846
846
  };
847
847
  user: Record<string, any> & {
848
848
  id: string;
849
- email: string;
850
- emailVerified: boolean;
851
849
  name: string;
850
+ emailVerified: boolean;
851
+ email: string;
852
852
  createdAt: Date;
853
853
  updatedAt: Date;
854
854
  image?: string | null | undefined;
@@ -932,19 +932,19 @@ declare const stripe: <O extends StripeOptions>(options: O) => {
932
932
  session: {
933
933
  session: Record<string, any> & {
934
934
  id: string;
935
- createdAt: Date;
936
- updatedAt: Date;
937
935
  token: string;
938
- expiresAt: Date;
939
936
  userId: string;
937
+ expiresAt: Date;
938
+ createdAt: Date;
939
+ updatedAt: Date;
940
940
  ipAddress?: string | null | undefined;
941
941
  userAgent?: string | null | undefined;
942
942
  };
943
943
  user: Record<string, any> & {
944
944
  id: string;
945
- email: string;
946
- emailVerified: boolean;
947
945
  name: string;
946
+ emailVerified: boolean;
947
+ email: string;
948
948
  createdAt: Date;
949
949
  updatedAt: Date;
950
950
  image?: string | null | undefined;
@@ -998,9 +998,9 @@ declare const stripe: <O extends StripeOptions>(options: O) => {
998
998
  create: {
999
999
  after(user: {
1000
1000
  id: string;
1001
- email: string;
1002
- emailVerified: boolean;
1003
1001
  name: string;
1002
+ emailVerified: boolean;
1003
+ email: string;
1004
1004
  createdAt: Date;
1005
1005
  updatedAt: Date;
1006
1006
  image?: string | null | undefined;
package/dist/index.d.mts CHANGED
@@ -656,19 +656,19 @@ declare const stripe: <O extends StripeOptions>(options: O) => {
656
656
  session: {
657
657
  session: Record<string, any> & {
658
658
  id: string;
659
- createdAt: Date;
660
- updatedAt: Date;
661
659
  token: string;
662
- expiresAt: Date;
663
660
  userId: string;
661
+ expiresAt: Date;
662
+ createdAt: Date;
663
+ updatedAt: Date;
664
664
  ipAddress?: string | null | undefined;
665
665
  userAgent?: string | null | undefined;
666
666
  };
667
667
  user: Record<string, any> & {
668
668
  id: string;
669
- email: string;
670
- emailVerified: boolean;
671
669
  name: string;
670
+ emailVerified: boolean;
671
+ email: string;
672
672
  createdAt: Date;
673
673
  updatedAt: Date;
674
674
  image?: string | null | undefined;
@@ -768,19 +768,19 @@ declare const stripe: <O extends StripeOptions>(options: O) => {
768
768
  session: {
769
769
  session: Record<string, any> & {
770
770
  id: string;
771
- createdAt: Date;
772
- updatedAt: Date;
773
771
  token: string;
774
- expiresAt: Date;
775
772
  userId: string;
773
+ expiresAt: Date;
774
+ createdAt: Date;
775
+ updatedAt: Date;
776
776
  ipAddress?: string | null | undefined;
777
777
  userAgent?: string | null | undefined;
778
778
  };
779
779
  user: Record<string, any> & {
780
780
  id: string;
781
- email: string;
782
- emailVerified: boolean;
783
781
  name: string;
782
+ emailVerified: boolean;
783
+ email: string;
784
784
  createdAt: Date;
785
785
  updatedAt: Date;
786
786
  image?: string | null | undefined;
@@ -836,19 +836,19 @@ declare const stripe: <O extends StripeOptions>(options: O) => {
836
836
  session: {
837
837
  session: Record<string, any> & {
838
838
  id: string;
839
- createdAt: Date;
840
- updatedAt: Date;
841
839
  token: string;
842
- expiresAt: Date;
843
840
  userId: string;
841
+ expiresAt: Date;
842
+ createdAt: Date;
843
+ updatedAt: Date;
844
844
  ipAddress?: string | null | undefined;
845
845
  userAgent?: string | null | undefined;
846
846
  };
847
847
  user: Record<string, any> & {
848
848
  id: string;
849
- email: string;
850
- emailVerified: boolean;
851
849
  name: string;
850
+ emailVerified: boolean;
851
+ email: string;
852
852
  createdAt: Date;
853
853
  updatedAt: Date;
854
854
  image?: string | null | undefined;
@@ -932,19 +932,19 @@ declare const stripe: <O extends StripeOptions>(options: O) => {
932
932
  session: {
933
933
  session: Record<string, any> & {
934
934
  id: string;
935
- createdAt: Date;
936
- updatedAt: Date;
937
935
  token: string;
938
- expiresAt: Date;
939
936
  userId: string;
937
+ expiresAt: Date;
938
+ createdAt: Date;
939
+ updatedAt: Date;
940
940
  ipAddress?: string | null | undefined;
941
941
  userAgent?: string | null | undefined;
942
942
  };
943
943
  user: Record<string, any> & {
944
944
  id: string;
945
- email: string;
946
- emailVerified: boolean;
947
945
  name: string;
946
+ emailVerified: boolean;
947
+ email: string;
948
948
  createdAt: Date;
949
949
  updatedAt: Date;
950
950
  image?: string | null | undefined;
@@ -998,9 +998,9 @@ declare const stripe: <O extends StripeOptions>(options: O) => {
998
998
  create: {
999
999
  after(user: {
1000
1000
  id: string;
1001
- email: string;
1002
- emailVerified: boolean;
1003
1001
  name: string;
1002
+ emailVerified: boolean;
1003
+ email: string;
1004
1004
  createdAt: Date;
1005
1005
  updatedAt: Date;
1006
1006
  image?: string | null | undefined;
package/dist/index.d.ts CHANGED
@@ -656,19 +656,19 @@ declare const stripe: <O extends StripeOptions>(options: O) => {
656
656
  session: {
657
657
  session: Record<string, any> & {
658
658
  id: string;
659
- createdAt: Date;
660
- updatedAt: Date;
661
659
  token: string;
662
- expiresAt: Date;
663
660
  userId: string;
661
+ expiresAt: Date;
662
+ createdAt: Date;
663
+ updatedAt: Date;
664
664
  ipAddress?: string | null | undefined;
665
665
  userAgent?: string | null | undefined;
666
666
  };
667
667
  user: Record<string, any> & {
668
668
  id: string;
669
- email: string;
670
- emailVerified: boolean;
671
669
  name: string;
670
+ emailVerified: boolean;
671
+ email: string;
672
672
  createdAt: Date;
673
673
  updatedAt: Date;
674
674
  image?: string | null | undefined;
@@ -768,19 +768,19 @@ declare const stripe: <O extends StripeOptions>(options: O) => {
768
768
  session: {
769
769
  session: Record<string, any> & {
770
770
  id: string;
771
- createdAt: Date;
772
- updatedAt: Date;
773
771
  token: string;
774
- expiresAt: Date;
775
772
  userId: string;
773
+ expiresAt: Date;
774
+ createdAt: Date;
775
+ updatedAt: Date;
776
776
  ipAddress?: string | null | undefined;
777
777
  userAgent?: string | null | undefined;
778
778
  };
779
779
  user: Record<string, any> & {
780
780
  id: string;
781
- email: string;
782
- emailVerified: boolean;
783
781
  name: string;
782
+ emailVerified: boolean;
783
+ email: string;
784
784
  createdAt: Date;
785
785
  updatedAt: Date;
786
786
  image?: string | null | undefined;
@@ -836,19 +836,19 @@ declare const stripe: <O extends StripeOptions>(options: O) => {
836
836
  session: {
837
837
  session: Record<string, any> & {
838
838
  id: string;
839
- createdAt: Date;
840
- updatedAt: Date;
841
839
  token: string;
842
- expiresAt: Date;
843
840
  userId: string;
841
+ expiresAt: Date;
842
+ createdAt: Date;
843
+ updatedAt: Date;
844
844
  ipAddress?: string | null | undefined;
845
845
  userAgent?: string | null | undefined;
846
846
  };
847
847
  user: Record<string, any> & {
848
848
  id: string;
849
- email: string;
850
- emailVerified: boolean;
851
849
  name: string;
850
+ emailVerified: boolean;
851
+ email: string;
852
852
  createdAt: Date;
853
853
  updatedAt: Date;
854
854
  image?: string | null | undefined;
@@ -932,19 +932,19 @@ declare const stripe: <O extends StripeOptions>(options: O) => {
932
932
  session: {
933
933
  session: Record<string, any> & {
934
934
  id: string;
935
- createdAt: Date;
936
- updatedAt: Date;
937
935
  token: string;
938
- expiresAt: Date;
939
936
  userId: string;
937
+ expiresAt: Date;
938
+ createdAt: Date;
939
+ updatedAt: Date;
940
940
  ipAddress?: string | null | undefined;
941
941
  userAgent?: string | null | undefined;
942
942
  };
943
943
  user: Record<string, any> & {
944
944
  id: string;
945
- email: string;
946
- emailVerified: boolean;
947
945
  name: string;
946
+ emailVerified: boolean;
947
+ email: string;
948
948
  createdAt: Date;
949
949
  updatedAt: Date;
950
950
  image?: string | null | undefined;
@@ -998,9 +998,9 @@ declare const stripe: <O extends StripeOptions>(options: O) => {
998
998
  create: {
999
999
  after(user: {
1000
1000
  id: string;
1001
- email: string;
1002
- emailVerified: boolean;
1003
1001
  name: string;
1002
+ emailVerified: boolean;
1003
+ email: string;
1004
1004
  createdAt: Date;
1005
1005
  updatedAt: Date;
1006
1006
  image?: string | null | undefined;
package/dist/index.mjs CHANGED
@@ -304,6 +304,15 @@ const getUrl = (ctx, url) => {
304
304
  }
305
305
  return `${ctx.context.options.baseURL}${url.startsWith("/") ? url : `/${url}`}`;
306
306
  };
307
+ async function resolvePriceIdFromLookupKey(stripeClient, lookupKey) {
308
+ if (!lookupKey) return void 0;
309
+ const prices = await stripeClient.prices.list({
310
+ lookup_keys: [lookupKey],
311
+ active: true,
312
+ limit: 1
313
+ });
314
+ return prices.data[0]?.id;
315
+ }
307
316
  const stripe = (options) => {
308
317
  const client = options.stripeClient;
309
318
  const referenceMiddleware = (action) => createAuthMiddleware(async (ctx) => {
@@ -481,7 +490,7 @@ const stripe = (options) => {
481
490
  status: "active"
482
491
  }).then(
483
492
  (res) => res.data.find(
484
- (subscription2) => subscription2.id === ctx.body.subscriptionId
493
+ (subscription2) => subscription2.id === subscriptionToUpdate?.stripeSubscriptionId || ctx.body.subscriptionId
485
494
  )
486
495
  ).catch((e) => null) : null;
487
496
  const subscriptions = subscriptionToUpdate ? [subscriptionToUpdate] : await ctx.context.adapter.findMany({
@@ -496,7 +505,7 @@ const stripe = (options) => {
496
505
  const existingSubscription = subscriptions.find(
497
506
  (sub) => sub.status === "active" || sub.status === "trialing"
498
507
  );
499
- if (existingSubscription && existingSubscription.status === "active" && existingSubscription.plan === ctx.body.plan) {
508
+ if (existingSubscription && existingSubscription.status === "active" && existingSubscription.plan === ctx.body.plan && existingSubscription.seats === (ctx.body.seats || 1)) {
500
509
  throw new APIError("BAD_REQUEST", {
501
510
  message: STRIPE_ERROR_CODES.ALREADY_SUBSCRIBED_PLAN
502
511
  });
@@ -512,7 +521,7 @@ const stripe = (options) => {
512
521
  items: [
513
522
  {
514
523
  id: activeSubscription.items.data[0]?.id,
515
- quantity: 1,
524
+ quantity: ctx.body.seats || 1,
516
525
  price: ctx.body.annual ? plan.annualDiscountPriceId : plan.priceId
517
526
  }
518
527
  ]
@@ -559,6 +568,24 @@ const stripe = (options) => {
559
568
  const freeTrail = plan.freeTrial ? {
560
569
  trial_period_days: plan.freeTrial.days
561
570
  } : void 0;
571
+ let priceIdToUse = void 0;
572
+ if (ctx.body.annual) {
573
+ priceIdToUse = plan.annualDiscountPriceId;
574
+ if (!priceIdToUse && plan.annualDiscountLookupKey) {
575
+ priceIdToUse = await resolvePriceIdFromLookupKey(
576
+ client,
577
+ plan.annualDiscountLookupKey
578
+ );
579
+ }
580
+ } else {
581
+ priceIdToUse = plan.priceId;
582
+ if (!priceIdToUse && plan.lookupKey) {
583
+ priceIdToUse = await resolvePriceIdFromLookupKey(
584
+ client,
585
+ plan.lookupKey
586
+ );
587
+ }
588
+ }
562
589
  const checkoutSession = await client.checkout.sessions.create(
563
590
  {
564
591
  ...customerId ? {
@@ -579,7 +606,7 @@ const stripe = (options) => {
579
606
  cancel_url: getUrl(ctx, ctx.body.cancelUrl),
580
607
  line_items: [
581
608
  {
582
- price: ctx.body.annual ? plan.annualDiscountPriceId : plan.priceId,
609
+ price: priceIdToUse,
583
610
  quantity: ctx.body.seats || 1
584
611
  }
585
612
  ],
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@better-auth/stripe",
3
3
  "author": "Bereket Engida",
4
- "version": "1.2.9-beta.8",
4
+ "version": "1.2.9",
5
5
  "main": "dist/index.cjs",
6
6
  "license": "MIT",
7
7
  "keywords": [
@@ -35,7 +35,7 @@
35
35
  },
36
36
  "dependencies": {
37
37
  "zod": "^3.24.1",
38
- "better-auth": "^1.2.9-beta.8"
38
+ "better-auth": "^1.2.9"
39
39
  },
40
40
  "devDependencies": {
41
41
  "@types/better-sqlite3": "^7.6.12",
package/src/index.ts CHANGED
@@ -50,6 +50,19 @@ const getUrl = (ctx: GenericEndpointContext, url: string) => {
50
50
  }`;
51
51
  };
52
52
 
53
+ async function resolvePriceIdFromLookupKey(
54
+ stripeClient: Stripe,
55
+ lookupKey: string,
56
+ ): Promise<string | undefined> {
57
+ if (!lookupKey) return undefined;
58
+ const prices = await stripeClient.prices.list({
59
+ lookup_keys: [lookupKey],
60
+ active: true,
61
+ limit: 1,
62
+ });
63
+ return prices.data[0]?.id;
64
+ }
65
+
53
66
  export const stripe = <O extends StripeOptions>(options: O) => {
54
67
  const client = options.stripeClient;
55
68
 
@@ -268,7 +281,10 @@ export const stripe = <O extends StripeOptions>(options: O) => {
268
281
  })
269
282
  .then((res) =>
270
283
  res.data.find(
271
- (subscription) => subscription.id === ctx.body.subscriptionId,
284
+ (subscription) =>
285
+ subscription.id ===
286
+ subscriptionToUpdate?.stripeSubscriptionId ||
287
+ ctx.body.subscriptionId,
272
288
  ),
273
289
  )
274
290
  .catch((e) => null)
@@ -293,7 +309,8 @@ export const stripe = <O extends StripeOptions>(options: O) => {
293
309
  if (
294
310
  existingSubscription &&
295
311
  existingSubscription.status === "active" &&
296
- existingSubscription.plan === ctx.body.plan
312
+ existingSubscription.plan === ctx.body.plan &&
313
+ existingSubscription.seats === (ctx.body.seats || 1)
297
314
  ) {
298
315
  throw new APIError("BAD_REQUEST", {
299
316
  message: STRIPE_ERROR_CODES.ALREADY_SUBSCRIBED_PLAN,
@@ -312,7 +329,7 @@ export const stripe = <O extends StripeOptions>(options: O) => {
312
329
  items: [
313
330
  {
314
331
  id: activeSubscription.items.data[0]?.id as string,
315
- quantity: 1,
332
+ quantity: ctx.body.seats || 1,
316
333
  price: ctx.body.annual
317
334
  ? plan.annualDiscountPriceId
318
335
  : plan.priceId,
@@ -372,6 +389,24 @@ export const stripe = <O extends StripeOptions>(options: O) => {
372
389
  }
373
390
  : undefined;
374
391
 
392
+ let priceIdToUse: string | undefined = undefined;
393
+ if (ctx.body.annual) {
394
+ priceIdToUse = plan.annualDiscountPriceId;
395
+ if (!priceIdToUse && plan.annualDiscountLookupKey) {
396
+ priceIdToUse = await resolvePriceIdFromLookupKey(
397
+ client,
398
+ plan.annualDiscountLookupKey,
399
+ );
400
+ }
401
+ } else {
402
+ priceIdToUse = plan.priceId;
403
+ if (!priceIdToUse && plan.lookupKey) {
404
+ priceIdToUse = await resolvePriceIdFromLookupKey(
405
+ client,
406
+ plan.lookupKey,
407
+ );
408
+ }
409
+ }
375
410
  const checkoutSession = await client.checkout.sessions
376
411
  .create(
377
412
  {
@@ -397,9 +432,7 @@ export const stripe = <O extends StripeOptions>(options: O) => {
397
432
  cancel_url: getUrl(ctx, ctx.body.cancelUrl),
398
433
  line_items: [
399
434
  {
400
- price: ctx.body.annual
401
- ? plan.annualDiscountPriceId
402
- : plan.priceId,
435
+ price: priceIdToUse,
403
436
  quantity: ctx.body.seats || 1,
404
437
  },
405
438
  ],
@@ -11,6 +11,9 @@ import type { StripeOptions, Subscription } from "./types";
11
11
 
12
12
  describe("stripe", async () => {
13
13
  const mockStripe = {
14
+ prices: {
15
+ list: vi.fn().mockResolvedValue({ data: [{ id: "price_lookup_123" }] }),
16
+ },
14
17
  customers: {
15
18
  create: vi.fn().mockResolvedValue({ id: "cus_mock123" }),
16
19
  },
@@ -59,10 +62,12 @@ describe("stripe", async () => {
59
62
  {
60
63
  priceId: process.env.STRIPE_PRICE_ID_1!,
61
64
  name: "starter",
65
+ lookupKey: "lookup_key_123",
62
66
  },
63
67
  {
64
68
  priceId: process.env.STRIPE_PRICE_ID_2!,
65
69
  name: "premium",
70
+ lookupKey: "lookup_key_234",
66
71
  },
67
72
  ],
68
73
  },
@@ -700,4 +705,116 @@ describe("stripe", async () => {
700
705
 
701
706
  expect(onSubscriptionDeleted).toHaveBeenCalled();
702
707
  });
708
+
709
+ it("should allow seat upgrades for the same plan", async () => {
710
+ const userRes = await authClient.signUp.email(
711
+ {
712
+ ...testUser,
713
+ email: "seat-upgrade@email.com",
714
+ },
715
+ {
716
+ throw: true,
717
+ },
718
+ );
719
+
720
+ const headers = new Headers();
721
+ await authClient.signIn.email(
722
+ {
723
+ ...testUser,
724
+ email: "seat-upgrade@email.com",
725
+ },
726
+ {
727
+ throw: true,
728
+ onSuccess: setCookieToHeader(headers),
729
+ },
730
+ );
731
+
732
+ await authClient.subscription.upgrade({
733
+ plan: "starter",
734
+ seats: 1,
735
+ fetchOptions: {
736
+ headers,
737
+ },
738
+ });
739
+
740
+ await ctx.adapter.update({
741
+ model: "subscription",
742
+ update: {
743
+ status: "active",
744
+ },
745
+ where: [
746
+ {
747
+ field: "referenceId",
748
+ value: userRes.user.id,
749
+ },
750
+ ],
751
+ });
752
+
753
+ const upgradeRes = await authClient.subscription.upgrade({
754
+ plan: "starter",
755
+ seats: 5,
756
+ fetchOptions: {
757
+ headers,
758
+ },
759
+ });
760
+
761
+ expect(upgradeRes.data?.url).toBeDefined();
762
+ });
763
+
764
+ it("should prevent duplicate subscriptions with same plan and same seats", async () => {
765
+ const userRes = await authClient.signUp.email(
766
+ {
767
+ ...testUser,
768
+ email: "duplicate-prevention@email.com",
769
+ },
770
+ {
771
+ throw: true,
772
+ },
773
+ );
774
+
775
+ const headers = new Headers();
776
+ await authClient.signIn.email(
777
+ {
778
+ ...testUser,
779
+ email: "duplicate-prevention@email.com",
780
+ },
781
+ {
782
+ throw: true,
783
+ onSuccess: setCookieToHeader(headers),
784
+ },
785
+ );
786
+
787
+ await authClient.subscription.upgrade({
788
+ plan: "starter",
789
+ seats: 3,
790
+ fetchOptions: {
791
+ headers,
792
+ },
793
+ });
794
+
795
+ await ctx.adapter.update({
796
+ model: "subscription",
797
+ update: {
798
+ status: "active",
799
+ seats: 3,
800
+ },
801
+ where: [
802
+ {
803
+ field: "referenceId",
804
+ value: userRes.user.id,
805
+ },
806
+ ],
807
+ });
808
+
809
+ const upgradeRes = await authClient.subscription.upgrade({
810
+ plan: "starter",
811
+ seats: 3,
812
+ fetchOptions: {
813
+ headers,
814
+ },
815
+ });
816
+
817
+ expect(upgradeRes.error).toBeDefined();
818
+ expect(upgradeRes.error?.message).toContain("already subscribed");
819
+ });
703
820
  });