@better-auth/stripe 1.5.0-beta.1 → 1.5.0-beta.3
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/.turbo/turbo-build.log +9 -9
- package/CHANGELOG.md +15 -13
- package/LICENSE.md +15 -12
- package/dist/client.d.mts +106 -1
- package/dist/client.mjs +5 -2
- package/dist/error-codes-Bkj5yJMT.mjs +29 -0
- package/dist/{index-DpiQGYLJ.d.mts → index-BnHmwMru.d.mts} +314 -155
- package/dist/index.d.mts +1 -1
- package/dist/index.mjs +628 -231
- package/package.json +6 -6
- package/src/client.ts +1 -0
- package/src/error-codes.ts +16 -0
- package/src/hooks.ts +229 -53
- package/src/index.ts +142 -45
- package/src/middleware.ts +91 -45
- package/src/routes.ts +620 -300
- package/src/schema.ts +30 -0
- package/src/types.ts +105 -20
- package/src/utils.ts +36 -1
- package/test/stripe-organization.test.ts +1993 -0
- package/{src → test}/stripe.test.ts +3350 -1404
- package/dist/error-codes-qqooUh6R.mjs +0 -16
package/src/schema.ts
CHANGED
|
@@ -46,6 +46,18 @@ export const subscriptions = {
|
|
|
46
46
|
required: false,
|
|
47
47
|
defaultValue: false,
|
|
48
48
|
},
|
|
49
|
+
cancelAt: {
|
|
50
|
+
type: "date",
|
|
51
|
+
required: false,
|
|
52
|
+
},
|
|
53
|
+
canceledAt: {
|
|
54
|
+
type: "date",
|
|
55
|
+
required: false,
|
|
56
|
+
},
|
|
57
|
+
endedAt: {
|
|
58
|
+
type: "date",
|
|
59
|
+
required: false,
|
|
60
|
+
},
|
|
49
61
|
seats: {
|
|
50
62
|
type: "number",
|
|
51
63
|
required: false,
|
|
@@ -65,6 +77,17 @@ export const user = {
|
|
|
65
77
|
},
|
|
66
78
|
} satisfies BetterAuthPluginDBSchema;
|
|
67
79
|
|
|
80
|
+
export const organization = {
|
|
81
|
+
organization: {
|
|
82
|
+
fields: {
|
|
83
|
+
stripeCustomerId: {
|
|
84
|
+
type: "string",
|
|
85
|
+
required: false,
|
|
86
|
+
},
|
|
87
|
+
},
|
|
88
|
+
},
|
|
89
|
+
} satisfies BetterAuthPluginDBSchema;
|
|
90
|
+
|
|
68
91
|
export const getSchema = (options: StripeOptions) => {
|
|
69
92
|
let baseSchema = {};
|
|
70
93
|
|
|
@@ -79,6 +102,13 @@ export const getSchema = (options: StripeOptions) => {
|
|
|
79
102
|
};
|
|
80
103
|
}
|
|
81
104
|
|
|
105
|
+
if (options.organization?.enabled) {
|
|
106
|
+
baseSchema = {
|
|
107
|
+
...baseSchema,
|
|
108
|
+
...organization,
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
|
|
82
112
|
if (
|
|
83
113
|
options.schema &&
|
|
84
114
|
!options.subscription?.enabled &&
|
package/src/types.ts
CHANGED
|
@@ -4,8 +4,32 @@ import type {
|
|
|
4
4
|
Session,
|
|
5
5
|
User,
|
|
6
6
|
} from "better-auth";
|
|
7
|
+
import type { Organization } from "better-auth/plugins/organization";
|
|
7
8
|
import type Stripe from "stripe";
|
|
8
|
-
import type { subscriptions, user } from "./schema";
|
|
9
|
+
import type { organization, subscriptions, user } from "./schema";
|
|
10
|
+
|
|
11
|
+
export type AuthorizeReferenceAction =
|
|
12
|
+
| "upgrade-subscription"
|
|
13
|
+
| "list-subscription"
|
|
14
|
+
| "cancel-subscription"
|
|
15
|
+
| "restore-subscription"
|
|
16
|
+
| "billing-portal";
|
|
17
|
+
|
|
18
|
+
export type CustomerType = "user" | "organization";
|
|
19
|
+
|
|
20
|
+
export type WithStripeCustomerId = {
|
|
21
|
+
stripeCustomerId?: string;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
// TODO: Types extended by a plugin should be moved into that plugin.
|
|
25
|
+
export type WithActiveOrganizationId = {
|
|
26
|
+
activeOrganizationId?: string;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export type StripeCtxSession = {
|
|
30
|
+
session: Session & WithActiveOrganizationId;
|
|
31
|
+
user: User & WithStripeCustomerId;
|
|
32
|
+
};
|
|
9
33
|
|
|
10
34
|
export type StripePlan = {
|
|
11
35
|
/**
|
|
@@ -154,9 +178,26 @@ export interface Subscription {
|
|
|
154
178
|
*/
|
|
155
179
|
periodEnd?: Date | undefined;
|
|
156
180
|
/**
|
|
157
|
-
*
|
|
181
|
+
* Whether this subscription will (if status=active)
|
|
182
|
+
* or did (if status=canceled) cancel at the end of the current billing period.
|
|
158
183
|
*/
|
|
159
184
|
cancelAtPeriodEnd?: boolean | undefined;
|
|
185
|
+
/**
|
|
186
|
+
* If the subscription is scheduled to be canceled,
|
|
187
|
+
* this is the time at which the cancellation will take effect.
|
|
188
|
+
*/
|
|
189
|
+
cancelAt?: Date | undefined;
|
|
190
|
+
/**
|
|
191
|
+
* If the subscription has been canceled, this is the time when it was canceled.
|
|
192
|
+
*
|
|
193
|
+
* Note: If the subscription was canceled with `cancel_at_period_end`,
|
|
194
|
+
* this reflects the cancellation request time, not when the subscription actually ends.
|
|
195
|
+
*/
|
|
196
|
+
canceledAt?: Date | undefined;
|
|
197
|
+
/**
|
|
198
|
+
* If the subscription has ended, the date the subscription ended.
|
|
199
|
+
*/
|
|
200
|
+
endedAt?: Date | undefined;
|
|
160
201
|
/**
|
|
161
202
|
* A field to group subscriptions so you can have multiple subscriptions
|
|
162
203
|
* for one reference id
|
|
@@ -236,12 +277,7 @@ export type SubscriptionOptions = {
|
|
|
236
277
|
user: User & Record<string, any>;
|
|
237
278
|
session: Session & Record<string, any>;
|
|
238
279
|
referenceId: string;
|
|
239
|
-
action:
|
|
240
|
-
| "upgrade-subscription"
|
|
241
|
-
| "list-subscription"
|
|
242
|
-
| "cancel-subscription"
|
|
243
|
-
| "restore-subscription"
|
|
244
|
-
| "billing-portal";
|
|
280
|
+
action: AuthorizeReferenceAction;
|
|
245
281
|
},
|
|
246
282
|
ctx: GenericEndpointContext,
|
|
247
283
|
) => Promise<boolean>)
|
|
@@ -257,6 +293,18 @@ export type SubscriptionOptions = {
|
|
|
257
293
|
subscription: Subscription;
|
|
258
294
|
}) => Promise<void>)
|
|
259
295
|
| undefined;
|
|
296
|
+
/**
|
|
297
|
+
* A callback to run when a subscription is created
|
|
298
|
+
* @returns
|
|
299
|
+
*/
|
|
300
|
+
onSubscriptionCreated?:
|
|
301
|
+
| ((data: {
|
|
302
|
+
event: Stripe.Event;
|
|
303
|
+
stripeSubscription: Stripe.Subscription;
|
|
304
|
+
subscription: Subscription;
|
|
305
|
+
plan: StripePlan;
|
|
306
|
+
}) => Promise<void>)
|
|
307
|
+
| undefined;
|
|
260
308
|
/**
|
|
261
309
|
* parameters for session create params
|
|
262
310
|
*
|
|
@@ -284,14 +332,6 @@ export type SubscriptionOptions = {
|
|
|
284
332
|
options?: Stripe.RequestOptions;
|
|
285
333
|
})
|
|
286
334
|
| undefined;
|
|
287
|
-
/**
|
|
288
|
-
* Enable organization subscription
|
|
289
|
-
*/
|
|
290
|
-
organization?:
|
|
291
|
-
| {
|
|
292
|
-
enabled: boolean;
|
|
293
|
-
}
|
|
294
|
-
| undefined;
|
|
295
335
|
};
|
|
296
336
|
|
|
297
337
|
export interface StripeOptions {
|
|
@@ -319,7 +359,7 @@ export interface StripeOptions {
|
|
|
319
359
|
| ((
|
|
320
360
|
data: {
|
|
321
361
|
stripeCustomer: Stripe.Customer;
|
|
322
|
-
user: User &
|
|
362
|
+
user: User & WithStripeCustomerId;
|
|
323
363
|
},
|
|
324
364
|
ctx: GenericEndpointContext,
|
|
325
365
|
) => Promise<void>)
|
|
@@ -349,6 +389,49 @@ export interface StripeOptions {
|
|
|
349
389
|
} & SubscriptionOptions)
|
|
350
390
|
)
|
|
351
391
|
| undefined;
|
|
392
|
+
/**
|
|
393
|
+
* Organization Stripe integration
|
|
394
|
+
*
|
|
395
|
+
* Enable organizations to have their own Stripe customer ID
|
|
396
|
+
*/
|
|
397
|
+
organization?:
|
|
398
|
+
| {
|
|
399
|
+
/**
|
|
400
|
+
* Enable organization Stripe customer
|
|
401
|
+
*/
|
|
402
|
+
enabled: true;
|
|
403
|
+
/**
|
|
404
|
+
* A custom function to get the customer create params
|
|
405
|
+
* for organization customers.
|
|
406
|
+
*
|
|
407
|
+
* @param organization - the organization
|
|
408
|
+
* @param ctx - the context object
|
|
409
|
+
* @returns
|
|
410
|
+
*/
|
|
411
|
+
getCustomerCreateParams?:
|
|
412
|
+
| ((
|
|
413
|
+
organization: Organization,
|
|
414
|
+
ctx: GenericEndpointContext,
|
|
415
|
+
) => Promise<Partial<Stripe.CustomerCreateParams>>)
|
|
416
|
+
| undefined;
|
|
417
|
+
/**
|
|
418
|
+
* A callback to run after an organization customer has been created
|
|
419
|
+
*
|
|
420
|
+
* @param data - data containing stripeCustomer and organization
|
|
421
|
+
* @param ctx - the context object
|
|
422
|
+
* @returns
|
|
423
|
+
*/
|
|
424
|
+
onCustomerCreate?:
|
|
425
|
+
| ((
|
|
426
|
+
data: {
|
|
427
|
+
stripeCustomer: Stripe.Customer;
|
|
428
|
+
organization: Organization & WithStripeCustomerId;
|
|
429
|
+
},
|
|
430
|
+
ctx: GenericEndpointContext,
|
|
431
|
+
) => Promise<void>)
|
|
432
|
+
| undefined;
|
|
433
|
+
}
|
|
434
|
+
| undefined;
|
|
352
435
|
/**
|
|
353
436
|
* A callback to run after a stripe event is received
|
|
354
437
|
* @param event - Stripe Event
|
|
@@ -358,7 +441,9 @@ export interface StripeOptions {
|
|
|
358
441
|
/**
|
|
359
442
|
* Schema for the stripe plugin
|
|
360
443
|
*/
|
|
361
|
-
schema?:
|
|
444
|
+
schema?:
|
|
445
|
+
| InferOptionSchema<
|
|
446
|
+
typeof subscriptions & typeof user & typeof organization
|
|
447
|
+
>
|
|
448
|
+
| undefined;
|
|
362
449
|
}
|
|
363
|
-
|
|
364
|
-
export interface InputSubscription extends Omit<Subscription, "id"> {}
|
package/src/utils.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import type Stripe from "stripe";
|
|
2
|
+
import type { StripeOptions, Subscription } from "./types";
|
|
2
3
|
|
|
3
4
|
export async function getPlans(
|
|
4
5
|
subscriptionOptions: StripeOptions["subscription"],
|
|
@@ -33,3 +34,37 @@ export async function getPlanByName(options: StripeOptions, name: string) {
|
|
|
33
34
|
res?.find((plan) => plan.name.toLowerCase() === name.toLowerCase()),
|
|
34
35
|
);
|
|
35
36
|
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Checks if a subscription is in an available state (active or trialing)
|
|
40
|
+
*/
|
|
41
|
+
export function isActiveOrTrialing(
|
|
42
|
+
sub: Subscription | Stripe.Subscription,
|
|
43
|
+
): boolean {
|
|
44
|
+
return sub.status === "active" || sub.status === "trialing";
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Check if a subscription is scheduled to be canceled (DB subscription object)
|
|
49
|
+
*/
|
|
50
|
+
export function isPendingCancel(sub: Subscription): boolean {
|
|
51
|
+
return !!(sub.cancelAtPeriodEnd || sub.cancelAt);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Check if a Stripe subscription is scheduled to be canceled (Stripe API response)
|
|
56
|
+
*/
|
|
57
|
+
export function isStripePendingCancel(stripeSub: Stripe.Subscription): boolean {
|
|
58
|
+
return !!(stripeSub.cancel_at_period_end || stripeSub.cancel_at);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Escapes a value for use in Stripe search queries.
|
|
63
|
+
* Stripe search query uses double quotes for string values,
|
|
64
|
+
* and double quotes within the value need to be escaped with backslash.
|
|
65
|
+
*
|
|
66
|
+
* @see https://docs.stripe.com/search#search-query-language
|
|
67
|
+
*/
|
|
68
|
+
export function escapeStripeSearchValue(value: string): string {
|
|
69
|
+
return value.replace(/"/g, '\\"');
|
|
70
|
+
}
|