@better-auth/stripe 1.3.8-beta.5 → 1.3.8-beta.8

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.3.8-beta.5 build /home/runner/work/better-auth/better-auth/packages/stripe
2
+ > @better-auth/stripe@1.3.8-beta.8 build /home/runner/work/better-auth/better-auth/packages/stripe
3
3
  > unbuild
4
4
 
5
5
  Browserslist: caniuse-lite is outdated. Please run:
@@ -8,13 +8,13 @@ Browserslist: caniuse-lite is outdated. Please run:
8
8
  [info] Automatically detected entries: src/index, src/client [esm] [cjs] [dts]
9
9
  [info] Building stripe
10
10
  [success] Build succeeded for stripe
11
- [log] dist/index.cjs (total size: 43.5 kB, chunk size: 43.5 kB, exports: stripe)
11
+ [log] dist/index.cjs (total size: 43.9 kB, chunk size: 43.9 kB, exports: stripe)
12
12
 
13
13
  [log] dist/client.cjs (total size: 224 B, chunk size: 224 B, exports: stripeClient)
14
14
 
15
- [log] dist/index.mjs (total size: 42.7 kB, chunk size: 42.7 kB, exports: stripe)
15
+ [log] dist/index.mjs (total size: 43 kB, chunk size: 43 kB, exports: stripe)
16
16
 
17
17
  [log] dist/client.mjs (total size: 197 B, chunk size: 197 B, exports: stripeClient)
18
18
 
19
- Σ Total dist size (byte size): 222 kB
19
+ Σ Total dist size (byte size): 224 kB
20
20
  [log]
package/dist/index.cjs CHANGED
@@ -272,6 +272,14 @@ const subscriptions = {
272
272
  type: "date",
273
273
  required: false
274
274
  },
275
+ trialStart: {
276
+ type: "date",
277
+ required: false
278
+ },
279
+ trialEnd: {
280
+ type: "date",
281
+ required: false
282
+ },
275
283
  cancelAtPeriodEnd: {
276
284
  type: "boolean",
277
285
  required: false,
@@ -1135,6 +1143,9 @@ const stripe = (options) => {
1135
1143
  {
1136
1144
  method: "POST",
1137
1145
  body: z__namespace.object({
1146
+ locale: z__namespace.custom((localization) => {
1147
+ return typeof localization === "string";
1148
+ }).optional(),
1138
1149
  referenceId: z__namespace.string().optional(),
1139
1150
  returnUrl: z__namespace.string().default("/")
1140
1151
  }),
@@ -1171,6 +1182,7 @@ const stripe = (options) => {
1171
1182
  }
1172
1183
  try {
1173
1184
  const { url } = await client.billingPortal.sessions.create({
1185
+ locale: ctx.body.locale,
1174
1186
  customer: customerId,
1175
1187
  return_url: getUrl(ctx, ctx.body.returnUrl)
1176
1188
  });
package/dist/index.d.cts CHANGED
@@ -35,6 +35,14 @@ declare const subscriptions: {
35
35
  type: "date";
36
36
  required: false;
37
37
  };
38
+ trialStart: {
39
+ type: "date";
40
+ required: false;
41
+ };
42
+ trialEnd: {
43
+ type: "date";
44
+ required: false;
45
+ };
38
46
  cancelAtPeriodEnd: {
39
47
  type: "boolean";
40
48
  required: false;
@@ -988,6 +996,7 @@ declare const stripe: <O extends StripeOptions>(options: O) => {
988
996
  readonly createBillingPortal: {
989
997
  <AsResponse extends boolean = false, ReturnHeaders extends boolean = false>(inputCtx_0: {
990
998
  body: {
999
+ locale?: Stripe.Checkout.Session.Locale | undefined;
991
1000
  referenceId?: string | undefined;
992
1001
  returnUrl?: string | undefined;
993
1002
  };
@@ -1022,6 +1031,7 @@ declare const stripe: <O extends StripeOptions>(options: O) => {
1022
1031
  options: {
1023
1032
  method: "POST";
1024
1033
  body: z.ZodObject<{
1034
+ locale: z.ZodOptional<z.ZodCustom<Stripe.Checkout.Session.Locale, Stripe.Checkout.Session.Locale>>;
1025
1035
  referenceId: z.ZodOptional<z.ZodString>;
1026
1036
  returnUrl: z.ZodDefault<z.ZodString>;
1027
1037
  }, z.core.$strip>;
package/dist/index.d.mts CHANGED
@@ -35,6 +35,14 @@ declare const subscriptions: {
35
35
  type: "date";
36
36
  required: false;
37
37
  };
38
+ trialStart: {
39
+ type: "date";
40
+ required: false;
41
+ };
42
+ trialEnd: {
43
+ type: "date";
44
+ required: false;
45
+ };
38
46
  cancelAtPeriodEnd: {
39
47
  type: "boolean";
40
48
  required: false;
@@ -988,6 +996,7 @@ declare const stripe: <O extends StripeOptions>(options: O) => {
988
996
  readonly createBillingPortal: {
989
997
  <AsResponse extends boolean = false, ReturnHeaders extends boolean = false>(inputCtx_0: {
990
998
  body: {
999
+ locale?: Stripe.Checkout.Session.Locale | undefined;
991
1000
  referenceId?: string | undefined;
992
1001
  returnUrl?: string | undefined;
993
1002
  };
@@ -1022,6 +1031,7 @@ declare const stripe: <O extends StripeOptions>(options: O) => {
1022
1031
  options: {
1023
1032
  method: "POST";
1024
1033
  body: z.ZodObject<{
1034
+ locale: z.ZodOptional<z.ZodCustom<Stripe.Checkout.Session.Locale, Stripe.Checkout.Session.Locale>>;
1025
1035
  referenceId: z.ZodOptional<z.ZodString>;
1026
1036
  returnUrl: z.ZodDefault<z.ZodString>;
1027
1037
  }, z.core.$strip>;
package/dist/index.d.ts CHANGED
@@ -35,6 +35,14 @@ declare const subscriptions: {
35
35
  type: "date";
36
36
  required: false;
37
37
  };
38
+ trialStart: {
39
+ type: "date";
40
+ required: false;
41
+ };
42
+ trialEnd: {
43
+ type: "date";
44
+ required: false;
45
+ };
38
46
  cancelAtPeriodEnd: {
39
47
  type: "boolean";
40
48
  required: false;
@@ -988,6 +996,7 @@ declare const stripe: <O extends StripeOptions>(options: O) => {
988
996
  readonly createBillingPortal: {
989
997
  <AsResponse extends boolean = false, ReturnHeaders extends boolean = false>(inputCtx_0: {
990
998
  body: {
999
+ locale?: Stripe.Checkout.Session.Locale | undefined;
991
1000
  referenceId?: string | undefined;
992
1001
  returnUrl?: string | undefined;
993
1002
  };
@@ -1022,6 +1031,7 @@ declare const stripe: <O extends StripeOptions>(options: O) => {
1022
1031
  options: {
1023
1032
  method: "POST";
1024
1033
  body: z.ZodObject<{
1034
+ locale: z.ZodOptional<z.ZodCustom<Stripe.Checkout.Session.Locale, Stripe.Checkout.Session.Locale>>;
1025
1035
  referenceId: z.ZodOptional<z.ZodString>;
1026
1036
  returnUrl: z.ZodDefault<z.ZodString>;
1027
1037
  }, z.core.$strip>;
package/dist/index.mjs CHANGED
@@ -256,6 +256,14 @@ const subscriptions = {
256
256
  type: "date",
257
257
  required: false
258
258
  },
259
+ trialStart: {
260
+ type: "date",
261
+ required: false
262
+ },
263
+ trialEnd: {
264
+ type: "date",
265
+ required: false
266
+ },
259
267
  cancelAtPeriodEnd: {
260
268
  type: "boolean",
261
269
  required: false,
@@ -1119,6 +1127,9 @@ const stripe = (options) => {
1119
1127
  {
1120
1128
  method: "POST",
1121
1129
  body: z.object({
1130
+ locale: z.custom((localization) => {
1131
+ return typeof localization === "string";
1132
+ }).optional(),
1122
1133
  referenceId: z.string().optional(),
1123
1134
  returnUrl: z.string().default("/")
1124
1135
  }),
@@ -1155,6 +1166,7 @@ const stripe = (options) => {
1155
1166
  }
1156
1167
  try {
1157
1168
  const { url } = await client.billingPortal.sessions.create({
1169
+ locale: ctx.body.locale,
1158
1170
  customer: customerId,
1159
1171
  return_url: getUrl(ctx, ctx.body.returnUrl)
1160
1172
  });
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@better-auth/stripe",
3
3
  "author": "Bereket Engida",
4
- "version": "1.3.8-beta.5",
4
+ "version": "1.3.8-beta.8",
5
5
  "main": "dist/index.cjs",
6
6
  "license": "MIT",
7
7
  "keywords": [
@@ -37,17 +37,16 @@
37
37
  }
38
38
  },
39
39
  "dependencies": {
40
- "zod": "^4.0.0",
41
- "better-auth": "^1.3.8-beta.5"
40
+ "zod": "^4.0.0"
42
41
  },
43
42
  "peerDependencies": {
44
- "stripe": "^18"
43
+ "stripe": "^18",
44
+ "better-auth": "1.3.8-beta.8"
45
45
  },
46
46
  "devDependencies": {
47
- "@types/better-sqlite3": "^7.6.12",
48
47
  "better-call": "1.0.15",
49
- "better-sqlite3": "^11.6.0",
50
- "stripe": "^18.0.0"
48
+ "stripe": "^18.0.0",
49
+ "better-auth": "1.3.8-beta.8"
51
50
  },
52
51
  "scripts": {
53
52
  "test": "vitest",
package/src/index.ts CHANGED
@@ -5,6 +5,7 @@ import {
5
5
  } from "better-auth";
6
6
  import { createAuthEndpoint, createAuthMiddleware } from "better-auth/plugins";
7
7
  import Stripe from "stripe";
8
+ import { type Stripe as StripeType } from "stripe";
8
9
  import * as z from "zod/v4";
9
10
  import {
10
11
  sessionMiddleware,
@@ -1039,6 +1040,11 @@ export const stripe = <O extends StripeOptions>(options: O) => {
1039
1040
  {
1040
1041
  method: "POST",
1041
1042
  body: z.object({
1043
+ locale: z
1044
+ .custom<StripeType.Checkout.Session.Locale>((localization) => {
1045
+ return typeof localization === "string";
1046
+ })
1047
+ .optional(),
1042
1048
  referenceId: z.string().optional(),
1043
1049
  returnUrl: z.string().default("/"),
1044
1050
  }),
@@ -1082,6 +1088,7 @@ export const stripe = <O extends StripeOptions>(options: O) => {
1082
1088
 
1083
1089
  try {
1084
1090
  const { url } = await client.billingPortal.sessions.create({
1091
+ locale: ctx.body.locale,
1085
1092
  customer: customerId,
1086
1093
  return_url: getUrl(ctx, ctx.body.returnUrl),
1087
1094
  });
package/src/schema.ts CHANGED
@@ -33,6 +33,14 @@ export const subscriptions = {
33
33
  type: "date",
34
34
  required: false,
35
35
  },
36
+ trialStart: {
37
+ type: "date",
38
+ required: false,
39
+ },
40
+ trialEnd: {
41
+ type: "date",
42
+ required: false,
43
+ },
36
44
  cancelAtPeriodEnd: {
37
45
  type: "boolean",
38
46
  required: false,
@@ -181,6 +181,8 @@ describe("stripe", async () => {
181
181
  status: "incomplete",
182
182
  periodStart: undefined,
183
183
  cancelAtPeriodEnd: undefined,
184
+ trialStart: undefined,
185
+ trialEnd: undefined,
184
186
  });
185
187
  });
186
188
 
@@ -356,6 +358,117 @@ describe("stripe", async () => {
356
358
  });
357
359
  });
358
360
 
361
+ it("should handle subscription webhook events with trial", async () => {
362
+ const { id: testReferenceId } = await ctx.adapter.create({
363
+ model: "user",
364
+ data: {
365
+ email: "test@email.com",
366
+ },
367
+ });
368
+ const { id: testSubscriptionId } = await ctx.adapter.create({
369
+ model: "subscription",
370
+ data: {
371
+ referenceId: testReferenceId,
372
+ stripeCustomerId: "cus_mock123",
373
+ status: "incomplete",
374
+ plan: "starter",
375
+ },
376
+ });
377
+ const mockCheckoutSessionEvent = {
378
+ type: "checkout.session.completed",
379
+ data: {
380
+ object: {
381
+ mode: "subscription",
382
+ subscription: testSubscriptionId,
383
+ metadata: {
384
+ referenceId: testReferenceId,
385
+ subscriptionId: testSubscriptionId,
386
+ },
387
+ },
388
+ },
389
+ };
390
+
391
+ const mockSubscription = {
392
+ id: testSubscriptionId,
393
+ status: "active",
394
+ items: {
395
+ data: [
396
+ {
397
+ price: { id: process.env.STRIPE_PRICE_ID_1 },
398
+ quantity: 1,
399
+ },
400
+ ],
401
+ },
402
+ current_period_start: Math.floor(Date.now() / 1000),
403
+ current_period_end: Math.floor(Date.now() / 1000) + 30 * 24 * 60 * 60,
404
+ trial_start: Math.floor(Date.now() / 1000),
405
+ trial_end: Math.floor(Date.now() / 1000) + 30 * 24 * 60 * 60,
406
+ };
407
+
408
+ const stripeForTest = {
409
+ ...stripeOptions.stripeClient,
410
+ subscriptions: {
411
+ ...stripeOptions.stripeClient.subscriptions,
412
+ retrieve: vi.fn().mockResolvedValue(mockSubscription),
413
+ },
414
+ webhooks: {
415
+ constructEventAsync: vi
416
+ .fn()
417
+ .mockResolvedValue(mockCheckoutSessionEvent),
418
+ },
419
+ };
420
+
421
+ const testOptions = {
422
+ ...stripeOptions,
423
+ stripeClient: stripeForTest as unknown as Stripe,
424
+ stripeWebhookSecret: "test_secret",
425
+ };
426
+
427
+ const testAuth = betterAuth({
428
+ baseURL: "http://localhost:3000",
429
+ database: memory,
430
+ emailAndPassword: {
431
+ enabled: true,
432
+ },
433
+ plugins: [stripe(testOptions)],
434
+ });
435
+
436
+ const testCtx = await testAuth.$context;
437
+
438
+ const mockRequest = new Request(
439
+ "http://localhost:3000/api/auth/stripe/webhook",
440
+ {
441
+ method: "POST",
442
+ headers: {
443
+ "stripe-signature": "test_signature",
444
+ },
445
+ body: JSON.stringify(mockCheckoutSessionEvent),
446
+ },
447
+ );
448
+ const response = await testAuth.handler(mockRequest);
449
+ expect(response.status).toBe(200);
450
+
451
+ const updatedSubscription = await testCtx.adapter.findOne<Subscription>({
452
+ model: "subscription",
453
+ where: [
454
+ {
455
+ field: "id",
456
+ value: testSubscriptionId,
457
+ },
458
+ ],
459
+ });
460
+
461
+ expect(updatedSubscription).toMatchObject({
462
+ id: testSubscriptionId,
463
+ status: "active",
464
+ periodStart: expect.any(Date),
465
+ periodEnd: expect.any(Date),
466
+ plan: "starter",
467
+ trialStart: expect.any(Date),
468
+ trialEnd: expect.any(Date),
469
+ });
470
+ });
471
+
359
472
  const { id: userId } = await ctx.adapter.create({
360
473
  model: "user",
361
474
  data: {