@dodopayments/better-auth 1.4.4 → 1.5.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/dist/{chunk-47N33D2M.js → chunk-ARA27DRZ.js} +17 -32
- package/dist/chunk-ARA27DRZ.js.map +1 -0
- package/dist/{chunk-KXU6PYZF.js → chunk-DTOB4IQZ.js} +22 -45
- package/dist/chunk-DTOB4IQZ.js.map +1 -0
- package/dist/{chunk-BII7QAPD.js → chunk-R5TTSJK4.js} +22 -3
- package/dist/chunk-R5TTSJK4.js.map +1 -0
- package/dist/chunk-TOPOAYYO.js +23 -0
- package/dist/chunk-TOPOAYYO.js.map +1 -0
- package/dist/hooks/customer.cjs +21 -2
- package/dist/hooks/customer.cjs.map +1 -1
- package/dist/hooks/customer.js +1 -1
- package/dist/index.cjs +82 -77
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +11 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.js +18 -6
- package/dist/index.js.map +1 -1
- package/dist/plugins/portal.cjs +38 -44
- package/dist/plugins/portal.cjs.map +1 -1
- package/dist/plugins/portal.js +2 -1
- package/dist/plugins/usage.cjs +33 -31
- package/dist/plugins/usage.cjs.map +1 -1
- package/dist/plugins/usage.js +2 -1
- package/dist/utils.cjs +47 -0
- package/dist/utils.cjs.map +1 -0
- package/dist/utils.d.cts +13 -0
- package/dist/utils.d.ts +13 -0
- package/dist/utils.js +7 -0
- package/dist/utils.js.map +1 -0
- package/package.json +1 -1
- package/dist/chunk-47N33D2M.js.map +0 -1
- package/dist/chunk-BII7QAPD.js.map +0 -1
- package/dist/chunk-KXU6PYZF.js.map +0 -1
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getOrCreateCustomerId
|
|
3
|
+
} from "./chunk-TOPOAYYO.js";
|
|
4
|
+
|
|
1
5
|
// src/plugins/usage.ts
|
|
2
6
|
import {
|
|
3
7
|
APIError,
|
|
@@ -35,22 +39,16 @@ var usage = () => (dodopayments) => {
|
|
|
35
39
|
});
|
|
36
40
|
}
|
|
37
41
|
try {
|
|
38
|
-
const
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
customer = await createCustomer(
|
|
44
|
-
dodopayments,
|
|
45
|
-
ctx.context.session.user.email,
|
|
46
|
-
ctx.context.session.user.name
|
|
47
|
-
);
|
|
48
|
-
}
|
|
42
|
+
const customerId = await getOrCreateCustomerId(
|
|
43
|
+
dodopayments,
|
|
44
|
+
ctx.context.session,
|
|
45
|
+
ctx.context.internalAdapter
|
|
46
|
+
);
|
|
49
47
|
const result = await dodopayments.usageEvents.ingest({
|
|
50
48
|
events: [
|
|
51
49
|
{
|
|
52
50
|
event_id: ctx.body.event_id,
|
|
53
|
-
customer_id:
|
|
51
|
+
customer_id: customerId,
|
|
54
52
|
event_name: ctx.body.event_name,
|
|
55
53
|
timestamp: ctx.body.timestamp,
|
|
56
54
|
metadata: ctx.body.metadata
|
|
@@ -97,19 +95,13 @@ var usage = () => (dodopayments) => {
|
|
|
97
95
|
});
|
|
98
96
|
}
|
|
99
97
|
try {
|
|
100
|
-
const
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
customer = await createCustomer(
|
|
106
|
-
dodopayments,
|
|
107
|
-
ctx.context.session.user.email,
|
|
108
|
-
ctx.context.session.user.name
|
|
109
|
-
);
|
|
110
|
-
}
|
|
98
|
+
const customerId = await getOrCreateCustomerId(
|
|
99
|
+
dodopayments,
|
|
100
|
+
ctx.context.session,
|
|
101
|
+
ctx.context.internalAdapter
|
|
102
|
+
);
|
|
111
103
|
const meters = await dodopayments.usageEvents.list({
|
|
112
|
-
customer_id:
|
|
104
|
+
customer_id: customerId,
|
|
113
105
|
...ctx.query
|
|
114
106
|
});
|
|
115
107
|
return ctx.json({ items: meters.items });
|
|
@@ -127,15 +119,8 @@ var usage = () => (dodopayments) => {
|
|
|
127
119
|
)
|
|
128
120
|
};
|
|
129
121
|
};
|
|
130
|
-
async function createCustomer(dodopayments, email, name) {
|
|
131
|
-
const customer = await dodopayments.customers.create({
|
|
132
|
-
email,
|
|
133
|
-
name
|
|
134
|
-
});
|
|
135
|
-
return customer;
|
|
136
|
-
}
|
|
137
122
|
|
|
138
123
|
export {
|
|
139
124
|
usage
|
|
140
125
|
};
|
|
141
|
-
//# sourceMappingURL=chunk-
|
|
126
|
+
//# sourceMappingURL=chunk-ARA27DRZ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/plugins/usage.ts"],"sourcesContent":["import {\n APIError,\n createAuthEndpoint,\n sessionMiddleware,\n} from \"better-auth/api\";\nimport type { DodoPayments } from \"dodopayments\";\nimport { Event } from \"dodopayments/resources/usage-events.mjs\";\nimport { z } from \"zod/v3\";\nimport { getOrCreateCustomerId } from \"../utils\";\n\nconst EventInputSchema = z.object({\n event_id: z.string(),\n event_name: z.string(),\n metadata: z\n .record(z.union([z.string(), z.number(), z.boolean()]))\n .nullable()\n .optional(),\n timestamp: z\n // NOTE: coerce because the date object gets converted to a string over network requests\n // but we still want to enforce that it's a Date type\n .date({ coerce: true })\n .transform((d) => d.toISOString())\n .optional()\n .describe(\n \"Custom Timestamp. Defaults to current timestamp in UTC.\\\n Timestamps that are older that 1 hour or after 5 mins from\\\n current timestamp will be rejected.\",\n ),\n});\n\nexport const usage = () => (dodopayments: DodoPayments) => {\n return {\n // Ingest usage data\n dodoUsageIngest: createAuthEndpoint(\n \"/dodopayments/usage/ingest\",\n {\n method: \"POST\",\n body: EventInputSchema,\n use: [sessionMiddleware],\n },\n async (ctx): Promise<{ ingested_count: number }> => {\n if (!ctx.context.session?.user?.id) {\n throw new APIError(\"BAD_REQUEST\", {\n message: \"User not found\",\n });\n }\n\n if (!ctx.context.session?.user.emailVerified) {\n throw new APIError(\"UNAUTHORIZED\", {\n message: \"User email not verified\",\n });\n }\n\n try {\n const customerId = await getOrCreateCustomerId(\n dodopayments,\n ctx.context.session,\n ctx.context.internalAdapter,\n );\n\n const result = await dodopayments.usageEvents.ingest({\n events: [\n {\n event_id: ctx.body.event_id,\n customer_id: customerId,\n event_name: ctx.body.event_name,\n timestamp: ctx.body.timestamp,\n metadata: ctx.body.metadata,\n },\n ],\n });\n\n return ctx.json({ ingested_count: result.ingested_count });\n } catch (e: unknown) {\n if (e instanceof Error) {\n ctx.context.logger.error(\n `User usage ingestion error: ${e.message}`,\n );\n }\n\n throw new APIError(\"INTERNAL_SERVER_ERROR\", {\n message: \"Failed to record the user usage\",\n });\n }\n },\n ),\n\n // List usage meters\n dodoUsageMetersList: createAuthEndpoint(\n \"/dodopayments/usage/meters/list\",\n {\n method: \"GET\",\n query: z\n .object({\n page_number: z.coerce.number().optional(),\n page_size: z.coerce.number().optional(),\n event_name: z.string().optional(),\n meter_id: z.string().optional(),\n start: z.string().optional(),\n end: z.string().optional(),\n })\n .optional(),\n use: [sessionMiddleware],\n },\n async (ctx): Promise<{ items: Event[] }> => {\n if (!ctx.context.session?.user?.id) {\n throw new APIError(\"BAD_REQUEST\", {\n message: \"User not found\",\n });\n }\n\n if (!ctx.context.session?.user.emailVerified) {\n throw new APIError(\"UNAUTHORIZED\", {\n message: \"User email not verified\",\n });\n }\n\n try {\n const customerId = await getOrCreateCustomerId(\n dodopayments,\n ctx.context.session,\n ctx.context.internalAdapter,\n );\n\n const meters = await dodopayments.usageEvents.list({\n customer_id: customerId,\n ...ctx.query,\n });\n\n return ctx.json({ items: meters.items });\n } catch (e: unknown) {\n if (e instanceof Error) {\n ctx.context.logger.error(\n `User usage meter list error: ${e.message}`,\n );\n }\n\n throw new APIError(\"INTERNAL_SERVER_ERROR\", {\n message: \"Failed to fetch the user usage\",\n });\n }\n },\n ),\n };\n};\n\n"],"mappings":"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","names":[]}
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getOrCreateCustomerId
|
|
3
|
+
} from "./chunk-TOPOAYYO.js";
|
|
4
|
+
|
|
1
5
|
// src/plugins/portal.ts
|
|
2
6
|
import { APIError, createAuthEndpoint, sessionMiddleware } from "better-auth/api";
|
|
3
7
|
import { z } from "zod/v3";
|
|
@@ -21,20 +25,12 @@ var portal = () => (dodopayments) => {
|
|
|
21
25
|
});
|
|
22
26
|
}
|
|
23
27
|
try {
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
if (!customer) {
|
|
29
|
-
customer = await createCustomer(
|
|
30
|
-
dodopayments,
|
|
31
|
-
ctx.context.session.user.email,
|
|
32
|
-
ctx.context.session.user.name
|
|
33
|
-
);
|
|
34
|
-
}
|
|
35
|
-
const customerSession = await dodopayments.customers.customerPortal.create(
|
|
36
|
-
customer.customer_id
|
|
28
|
+
const customerId = await getOrCreateCustomerId(
|
|
29
|
+
dodopayments,
|
|
30
|
+
ctx.context.session,
|
|
31
|
+
ctx.context.internalAdapter
|
|
37
32
|
);
|
|
33
|
+
const customerSession = await dodopayments.customers.customerPortal.create(customerId);
|
|
38
34
|
return ctx.json({
|
|
39
35
|
url: customerSession.link,
|
|
40
36
|
redirect: true
|
|
@@ -81,19 +77,13 @@ var portal = () => (dodopayments) => {
|
|
|
81
77
|
});
|
|
82
78
|
}
|
|
83
79
|
try {
|
|
84
|
-
const
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
customer = await createCustomer(
|
|
90
|
-
dodopayments,
|
|
91
|
-
ctx.context.session.user.email,
|
|
92
|
-
ctx.context.session.user.name
|
|
93
|
-
);
|
|
94
|
-
}
|
|
80
|
+
const customerId = await getOrCreateCustomerId(
|
|
81
|
+
dodopayments,
|
|
82
|
+
ctx.context.session,
|
|
83
|
+
ctx.context.internalAdapter
|
|
84
|
+
);
|
|
95
85
|
const subscriptions = await dodopayments.subscriptions.list({
|
|
96
|
-
customer_id:
|
|
86
|
+
customer_id: customerId,
|
|
97
87
|
// page number is 0-indexed
|
|
98
88
|
page_number: ctx.query?.page ? ctx.query.page - 1 : void 0,
|
|
99
89
|
page_size: ctx.query?.limit,
|
|
@@ -147,19 +137,13 @@ var portal = () => (dodopayments) => {
|
|
|
147
137
|
});
|
|
148
138
|
}
|
|
149
139
|
try {
|
|
150
|
-
const
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
customer = await createCustomer(
|
|
156
|
-
dodopayments,
|
|
157
|
-
ctx.context.session.user.email,
|
|
158
|
-
ctx.context.session.user.name
|
|
159
|
-
);
|
|
160
|
-
}
|
|
140
|
+
const customerId = await getOrCreateCustomerId(
|
|
141
|
+
dodopayments,
|
|
142
|
+
ctx.context.session,
|
|
143
|
+
ctx.context.internalAdapter
|
|
144
|
+
);
|
|
161
145
|
const payments = await dodopayments.payments.list({
|
|
162
|
-
customer_id:
|
|
146
|
+
customer_id: customerId,
|
|
163
147
|
// page number is 0-indexed
|
|
164
148
|
page_number: ctx.query?.page ? ctx.query.page - 1 : void 0,
|
|
165
149
|
page_size: ctx.query?.limit,
|
|
@@ -180,15 +164,8 @@ var portal = () => (dodopayments) => {
|
|
|
180
164
|
)
|
|
181
165
|
};
|
|
182
166
|
};
|
|
183
|
-
async function createCustomer(dodopayments, email, name) {
|
|
184
|
-
const customer = await dodopayments.customers.create({
|
|
185
|
-
email,
|
|
186
|
-
name
|
|
187
|
-
});
|
|
188
|
-
return customer;
|
|
189
|
-
}
|
|
190
167
|
|
|
191
168
|
export {
|
|
192
169
|
portal
|
|
193
170
|
};
|
|
194
|
-
//# sourceMappingURL=chunk-
|
|
171
|
+
//# sourceMappingURL=chunk-DTOB4IQZ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/plugins/portal.ts"],"sourcesContent":["import type { DodoPayments } from \"dodopayments\";\nimport { APIError, createAuthEndpoint, sessionMiddleware } from \"better-auth/api\";\nimport { z } from \"zod/v3\";\nimport {\n CustomerPortalResponse,\n PaymentItems,\n SubscriptionItems,\n} from \"../types\";\nimport { getOrCreateCustomerId } from \"../utils\";\n\nexport const portal = () => (dodopayments: DodoPayments) => {\n return {\n dodoPortal: createAuthEndpoint(\n \"/dodopayments/customer/portal\",\n {\n method: \"GET\",\n use: [sessionMiddleware],\n },\n async (ctx): Promise<CustomerPortalResponse> => {\n if (!ctx.context.session?.user.id) {\n throw new APIError(\"BAD_REQUEST\", {\n message: \"User not found\",\n });\n }\n\n if (!ctx.context.session?.user.emailVerified) {\n throw new APIError(\"UNAUTHORIZED\", {\n message: \"User email not verified\",\n });\n }\n\n try {\n const customerId = await getOrCreateCustomerId(\n dodopayments,\n ctx.context.session,\n ctx.context.internalAdapter,\n );\n\n const customerSession =\n await dodopayments.customers.customerPortal.create(customerId);\n\n return ctx.json({\n url: customerSession.link,\n redirect: true,\n });\n } catch (e: unknown) {\n if (e instanceof Error) {\n ctx.context.logger.error(\n `DodoPayments customer portal creation failed. Error: ${e.message}`,\n );\n }\n\n throw new APIError(\"INTERNAL_SERVER_ERROR\", {\n message: \"Customer portal creation failed\",\n });\n }\n },\n ),\n dodoSubscriptions: createAuthEndpoint(\n \"/dodopayments/customer/subscriptions/list\",\n {\n method: \"GET\",\n query: z\n .object({\n page: z.coerce.number().optional(),\n limit: z.coerce.number().optional(),\n status: z\n .enum([\n \"active\",\n \"cancelled\",\n \"on_hold\",\n \"pending\",\n \"failed\",\n \"expired\",\n ])\n .optional(),\n })\n .optional(),\n use: [sessionMiddleware],\n },\n async (ctx): Promise<SubscriptionItems> => {\n if (!ctx.context.session.user.id) {\n throw new APIError(\"BAD_REQUEST\", {\n message: \"User not found\",\n });\n }\n\n if (!ctx.context.session?.user.emailVerified) {\n throw new APIError(\"UNAUTHORIZED\", {\n message: \"User email not verified\",\n });\n }\n\n try {\n const customerId = await getOrCreateCustomerId(\n dodopayments,\n ctx.context.session,\n ctx.context.internalAdapter,\n );\n\n const subscriptions = await dodopayments.subscriptions.list({\n customer_id: customerId,\n // page number is 0-indexed\n page_number: ctx.query?.page ? ctx.query.page - 1 : undefined,\n page_size: ctx.query?.limit,\n status: ctx.query?.status,\n });\n\n return ctx.json({ items: subscriptions.items });\n } catch (e: unknown) {\n if (e instanceof Error) {\n ctx.context.logger.error(\n `DodoPayments subscriptions list failed. Error: ${e.message}`,\n );\n }\n\n throw new APIError(\"INTERNAL_SERVER_ERROR\", {\n message: \"DodoPayments subscriptions list failed\",\n });\n }\n },\n ),\n dodoPayments: createAuthEndpoint(\n \"/dodopayments/customer/payments/list\",\n {\n method: \"GET\",\n query: z\n .object({\n page: z.coerce.number().optional(),\n limit: z.coerce.number().optional(),\n status: z\n .enum([\n \"succeeded\",\n \"failed\",\n \"cancelled\",\n \"processing\",\n \"requires_customer_action\",\n \"requires_merchant_action\",\n \"requires_payment_method\",\n \"requires_confirmation\",\n \"requires_capture\",\n \"partially_captured\",\n \"partially_captured_and_capturable\",\n ])\n .optional(),\n })\n .optional(),\n use: [sessionMiddleware],\n },\n async (ctx): Promise<PaymentItems> => {\n if (!ctx.context.session.user.id) {\n throw new APIError(\"BAD_REQUEST\", {\n message: \"User not found\",\n });\n }\n\n if (!ctx.context.session?.user.emailVerified) {\n throw new APIError(\"UNAUTHORIZED\", {\n message: \"User email not verified\",\n });\n }\n\n try {\n const customerId = await getOrCreateCustomerId(\n dodopayments,\n ctx.context.session,\n ctx.context.internalAdapter,\n );\n\n const payments = await dodopayments.payments.list({\n customer_id: customerId,\n // page number is 0-indexed\n page_number: ctx.query?.page ? ctx.query.page - 1 : undefined,\n page_size: ctx.query?.limit,\n status: ctx.query?.status,\n });\n\n return ctx.json({ items: payments.items });\n } catch (e: unknown) {\n if (e instanceof Error) {\n ctx.context.logger.error(\n `DodoPayments orders list failed. Error: ${e.message}`,\n );\n }\n\n throw new APIError(\"INTERNAL_SERVER_ERROR\", {\n message: \"Orders list failed\",\n });\n }\n },\n ),\n };\n};\n\n"],"mappings":"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","names":[]}
|
|
@@ -7,16 +7,26 @@ var onUserCreate = (options) => async (user, ctx) => {
|
|
|
7
7
|
email: user.email
|
|
8
8
|
});
|
|
9
9
|
const existingCustomer = customers.items[0];
|
|
10
|
+
let customerId;
|
|
10
11
|
if (existingCustomer) {
|
|
11
12
|
await options.client.customers.update(existingCustomer.customer_id, {
|
|
12
13
|
name: user.name
|
|
13
14
|
});
|
|
15
|
+
customerId = existingCustomer.customer_id;
|
|
14
16
|
} else {
|
|
15
|
-
await options.client.customers.create({
|
|
17
|
+
const newCustomer = await options.client.customers.create({
|
|
16
18
|
email: user.email,
|
|
17
19
|
name: user.name
|
|
18
|
-
});
|
|
20
|
+
}, { idempotencyKey: user.id });
|
|
21
|
+
customerId = newCustomer.customer_id;
|
|
19
22
|
}
|
|
23
|
+
ctx.context.internalAdapter.updateUser(user.id, {
|
|
24
|
+
dodoCustomerId: customerId
|
|
25
|
+
}).catch((e) => {
|
|
26
|
+
ctx.context.logger.warn(
|
|
27
|
+
`DodoPayments: failed to store dodoCustomerId for user ${user.id}. Error: ${e instanceof Error ? e.message : e}`
|
|
28
|
+
);
|
|
29
|
+
});
|
|
20
30
|
} catch (e) {
|
|
21
31
|
if (e instanceof Error) {
|
|
22
32
|
throw new APIError("INTERNAL_SERVER_ERROR", {
|
|
@@ -40,6 +50,15 @@ var onUserUpdate = (options) => async (user, ctx) => {
|
|
|
40
50
|
await options.client.customers.update(existingCustomer.customer_id, {
|
|
41
51
|
name: user.name
|
|
42
52
|
});
|
|
53
|
+
if (!user.dodoCustomerId) {
|
|
54
|
+
ctx.context.internalAdapter.updateUser(user.id, {
|
|
55
|
+
dodoCustomerId: existingCustomer.customer_id
|
|
56
|
+
}).catch((e) => {
|
|
57
|
+
ctx.context.logger.warn(
|
|
58
|
+
`DodoPayments: failed to backfill dodoCustomerId for user ${user.id}. Error: ${e instanceof Error ? e.message : e}`
|
|
59
|
+
);
|
|
60
|
+
});
|
|
61
|
+
}
|
|
43
62
|
}
|
|
44
63
|
} catch (e) {
|
|
45
64
|
if (e instanceof Error) {
|
|
@@ -59,4 +78,4 @@ export {
|
|
|
59
78
|
onUserCreate,
|
|
60
79
|
onUserUpdate
|
|
61
80
|
};
|
|
62
|
-
//# sourceMappingURL=chunk-
|
|
81
|
+
//# sourceMappingURL=chunk-R5TTSJK4.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/hooks/customer.ts"],"sourcesContent":["import type { GenericEndpointContext, User } from \"better-auth\";\nimport { APIError } from \"better-auth/api\";\nimport type { DodoPaymentsOptions } from \"../types\";\n\nexport const onUserCreate =\n (options: DodoPaymentsOptions) =>\n async (user: User, ctx: GenericEndpointContext | null) => {\n if (ctx && options.createCustomerOnSignUp) {\n try {\n const customers = await options.client.customers.list({\n email: user.email,\n });\n const existingCustomer = customers.items[0];\n\n let customerId: string;\n\n if (existingCustomer) {\n await options.client.customers.update(existingCustomer.customer_id, {\n name: user.name,\n });\n customerId = existingCustomer.customer_id;\n } else {\n // TODO: Add metadata to customer object via\n // getCustomerCreateParams option when it becomes\n // available in the API\n const newCustomer = await options.client.customers.create({\n email: user.email,\n name: user.name,\n }, { idempotencyKey: user.id });\n customerId = newCustomer.customer_id;\n }\n\n ctx.context.internalAdapter.updateUser(user.id, {\n dodoCustomerId: customerId,\n }).catch((e: unknown) => {\n ctx.context.logger.warn(\n `DodoPayments: failed to store dodoCustomerId for user ${user.id}. Error: ${e instanceof Error ? e.message : e}`,\n );\n });\n } catch (e: unknown) {\n if (e instanceof Error) {\n throw new APIError(\"INTERNAL_SERVER_ERROR\", {\n message: `DodoPayments customer creation failed. Error: ${e.message}`,\n });\n }\n\n throw new APIError(\"INTERNAL_SERVER_ERROR\", {\n message: `DodoPayments customer creation failed. Error: ${e}`,\n });\n }\n }\n };\n\nexport const onUserUpdate =\n (options: DodoPaymentsOptions) =>\n async (user: User, ctx: GenericEndpointContext | null) => {\n if (ctx && options.createCustomerOnSignUp) {\n try {\n const customers = await options.client.customers.list({\n email: user.email,\n });\n const existingCustomer = customers.items[0];\n\n if (existingCustomer) {\n // TODO: Add metadata to customer object via\n // getCustomerCreateParams option when it becomes\n // available in the API\n await options.client.customers.update(existingCustomer.customer_id, {\n name: user.name,\n });\n\n // Backfill dodoCustomerId if it doesn't exist\n if (!(user as User & { dodoCustomerId?: string }).dodoCustomerId) {\n ctx.context.internalAdapter.updateUser(user.id, {\n dodoCustomerId: existingCustomer.customer_id,\n }).catch((e: unknown) => {\n ctx.context.logger.warn(\n `DodoPayments: failed to backfill dodoCustomerId for user ${user.id}. Error: ${e instanceof Error ? e.message : e}`,\n );\n });\n }\n }\n } catch (e: unknown) {\n if (e instanceof Error) {\n ctx.context.logger.error(\n `DodoPayments customer update failed. Error: ${e.message}`,\n );\n } else {\n ctx.context.logger.error(\n `DodoPayments customer update failed. Error: ${e}`,\n );\n }\n }\n }\n };\n"],"mappings":";AACA,SAAS,gBAAgB;AAGlB,IAAM,eACX,CAAC,YACD,OAAO,MAAY,QAAuC;AACxD,MAAI,OAAO,QAAQ,wBAAwB;AACzC,QAAI;AACF,YAAM,YAAY,MAAM,QAAQ,OAAO,UAAU,KAAK;AAAA,QACpD,OAAO,KAAK;AAAA,MACd,CAAC;AACD,YAAM,mBAAmB,UAAU,MAAM,CAAC;AAE1C,UAAI;AAEJ,UAAI,kBAAkB;AACpB,cAAM,QAAQ,OAAO,UAAU,OAAO,iBAAiB,aAAa;AAAA,UAClE,MAAM,KAAK;AAAA,QACb,CAAC;AACD,qBAAa,iBAAiB;AAAA,MAChC,OAAO;AAIL,cAAM,cAAc,MAAM,QAAQ,OAAO,UAAU,OAAO;AAAA,UACxD,OAAO,KAAK;AAAA,UACZ,MAAM,KAAK;AAAA,QACb,GAAG,EAAE,gBAAgB,KAAK,GAAG,CAAC;AAC9B,qBAAa,YAAY;AAAA,MAC3B;AAEA,UAAI,QAAQ,gBAAgB,WAAW,KAAK,IAAI;AAAA,QAC9C,gBAAgB;AAAA,MAClB,CAAC,EAAE,MAAM,CAAC,MAAe;AACvB,YAAI,QAAQ,OAAO;AAAA,UACjB,yDAAyD,KAAK,EAAE,YAAY,aAAa,QAAQ,EAAE,UAAU,CAAC;AAAA,QAChH;AAAA,MACF,CAAC;AAAA,IACH,SAAS,GAAY;AACnB,UAAI,aAAa,OAAO;AACtB,cAAM,IAAI,SAAS,yBAAyB;AAAA,UAC1C,SAAS,iDAAiD,EAAE,OAAO;AAAA,QACrE,CAAC;AAAA,MACH;AAEA,YAAM,IAAI,SAAS,yBAAyB;AAAA,QAC1C,SAAS,iDAAiD,CAAC;AAAA,MAC7D,CAAC;AAAA,IACH;AAAA,EACF;AACF;AAEK,IAAM,eACX,CAAC,YACD,OAAO,MAAY,QAAuC;AACxD,MAAI,OAAO,QAAQ,wBAAwB;AACzC,QAAI;AACF,YAAM,YAAY,MAAM,QAAQ,OAAO,UAAU,KAAK;AAAA,QACpD,OAAO,KAAK;AAAA,MACd,CAAC;AACD,YAAM,mBAAmB,UAAU,MAAM,CAAC;AAE1C,UAAI,kBAAkB;AAIpB,cAAM,QAAQ,OAAO,UAAU,OAAO,iBAAiB,aAAa;AAAA,UAClE,MAAM,KAAK;AAAA,QACb,CAAC;AAGD,YAAI,CAAE,KAA4C,gBAAgB;AAChE,cAAI,QAAQ,gBAAgB,WAAW,KAAK,IAAI;AAAA,YAC9C,gBAAgB,iBAAiB;AAAA,UACnC,CAAC,EAAE,MAAM,CAAC,MAAe;AACvB,gBAAI,QAAQ,OAAO;AAAA,cACjB,4DAA4D,KAAK,EAAE,YAAY,aAAa,QAAQ,EAAE,UAAU,CAAC;AAAA,YACnH;AAAA,UACF,CAAC;AAAA,QACH;AAAA,MACF;AAAA,IACF,SAAS,GAAY;AACnB,UAAI,aAAa,OAAO;AACtB,YAAI,QAAQ,OAAO;AAAA,UACjB,+CAA+C,EAAE,OAAO;AAAA,QAC1D;AAAA,MACF,OAAO;AACL,YAAI,QAAQ,OAAO;AAAA,UACjB,+CAA+C,CAAC;AAAA,QAClD;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;","names":[]}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// src/utils.ts
|
|
2
|
+
async function getOrCreateCustomerId(dodopayments, session, internalAdapter) {
|
|
3
|
+
const dodoCustomerId = session.user["dodoCustomerId"];
|
|
4
|
+
if (dodoCustomerId) return dodoCustomerId;
|
|
5
|
+
const customers = await dodopayments.customers.list({
|
|
6
|
+
email: session.user.email
|
|
7
|
+
});
|
|
8
|
+
let customer = customers.items[0];
|
|
9
|
+
if (!customer) {
|
|
10
|
+
customer = await dodopayments.customers.create({
|
|
11
|
+
email: session.user.email,
|
|
12
|
+
name: session.user.name
|
|
13
|
+
}, { idempotencyKey: session.user.id });
|
|
14
|
+
}
|
|
15
|
+
internalAdapter.updateUser(session.user.id, { dodoCustomerId: customer.customer_id }).catch(() => {
|
|
16
|
+
});
|
|
17
|
+
return customer.customer_id;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export {
|
|
21
|
+
getOrCreateCustomerId
|
|
22
|
+
};
|
|
23
|
+
//# sourceMappingURL=chunk-TOPOAYYO.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/utils.ts"],"sourcesContent":["import type { DodoPayments } from \"dodopayments\";\n\nexport async function getOrCreateCustomerId(\n dodopayments: DodoPayments,\n session: { user: { id: string; email: string; name: string } & Record<string, unknown> },\n internalAdapter: { updateUser: (id: string, data: Record<string, unknown>) => Promise<unknown> },\n): Promise<string> {\n const dodoCustomerId = session.user[\"dodoCustomerId\"] as string | undefined;\n if (dodoCustomerId) return dodoCustomerId;\n\n // Fallback to get customer from email if dodoCustomerId doesn't exist\n const customers = await dodopayments.customers.list({\n email: session.user.email,\n });\n let customer = customers.items[0];\n\n if (!customer) {\n customer = await dodopayments.customers.create({\n email: session.user.email,\n name: session.user.name,\n }, { idempotencyKey: session.user.id });\n }\n\n internalAdapter\n .updateUser(session.user.id, { dodoCustomerId: customer.customer_id })\n .catch(() => {});\n\n return customer.customer_id;\n}\n"],"mappings":";AAEA,eAAsB,sBACpB,cACA,SACA,iBACiB;AACjB,QAAM,iBAAiB,QAAQ,KAAK,gBAAgB;AACpD,MAAI,eAAgB,QAAO;AAG3B,QAAM,YAAY,MAAM,aAAa,UAAU,KAAK;AAAA,IAClD,OAAO,QAAQ,KAAK;AAAA,EACtB,CAAC;AACD,MAAI,WAAW,UAAU,MAAM,CAAC;AAEhC,MAAI,CAAC,UAAU;AACb,eAAW,MAAM,aAAa,UAAU,OAAO;AAAA,MAC7C,OAAO,QAAQ,KAAK;AAAA,MACpB,MAAM,QAAQ,KAAK;AAAA,IACrB,GAAG,EAAE,gBAAgB,QAAQ,KAAK,GAAG,CAAC;AAAA,EACxC;AAEA,kBACG,WAAW,QAAQ,KAAK,IAAI,EAAE,gBAAgB,SAAS,YAAY,CAAC,EACpE,MAAM,MAAM;AAAA,EAAC,CAAC;AAEjB,SAAO,SAAS;AAClB;","names":[]}
|
package/dist/hooks/customer.cjs
CHANGED
|
@@ -32,16 +32,26 @@ var onUserCreate = (options) => async (user, ctx) => {
|
|
|
32
32
|
email: user.email
|
|
33
33
|
});
|
|
34
34
|
const existingCustomer = customers.items[0];
|
|
35
|
+
let customerId;
|
|
35
36
|
if (existingCustomer) {
|
|
36
37
|
await options.client.customers.update(existingCustomer.customer_id, {
|
|
37
38
|
name: user.name
|
|
38
39
|
});
|
|
40
|
+
customerId = existingCustomer.customer_id;
|
|
39
41
|
} else {
|
|
40
|
-
await options.client.customers.create({
|
|
42
|
+
const newCustomer = await options.client.customers.create({
|
|
41
43
|
email: user.email,
|
|
42
44
|
name: user.name
|
|
43
|
-
});
|
|
45
|
+
}, { idempotencyKey: user.id });
|
|
46
|
+
customerId = newCustomer.customer_id;
|
|
44
47
|
}
|
|
48
|
+
ctx.context.internalAdapter.updateUser(user.id, {
|
|
49
|
+
dodoCustomerId: customerId
|
|
50
|
+
}).catch((e) => {
|
|
51
|
+
ctx.context.logger.warn(
|
|
52
|
+
`DodoPayments: failed to store dodoCustomerId for user ${user.id}. Error: ${e instanceof Error ? e.message : e}`
|
|
53
|
+
);
|
|
54
|
+
});
|
|
45
55
|
} catch (e) {
|
|
46
56
|
if (e instanceof Error) {
|
|
47
57
|
throw new import_api.APIError("INTERNAL_SERVER_ERROR", {
|
|
@@ -65,6 +75,15 @@ var onUserUpdate = (options) => async (user, ctx) => {
|
|
|
65
75
|
await options.client.customers.update(existingCustomer.customer_id, {
|
|
66
76
|
name: user.name
|
|
67
77
|
});
|
|
78
|
+
if (!user.dodoCustomerId) {
|
|
79
|
+
ctx.context.internalAdapter.updateUser(user.id, {
|
|
80
|
+
dodoCustomerId: existingCustomer.customer_id
|
|
81
|
+
}).catch((e) => {
|
|
82
|
+
ctx.context.logger.warn(
|
|
83
|
+
`DodoPayments: failed to backfill dodoCustomerId for user ${user.id}. Error: ${e instanceof Error ? e.message : e}`
|
|
84
|
+
);
|
|
85
|
+
});
|
|
86
|
+
}
|
|
68
87
|
}
|
|
69
88
|
} catch (e) {
|
|
70
89
|
if (e instanceof Error) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/hooks/customer.ts"],"sourcesContent":["import type { GenericEndpointContext, User } from \"better-auth\";\nimport { APIError } from \"better-auth/api\";\nimport type { DodoPaymentsOptions } from \"../types\";\n\nexport const onUserCreate =\n (options: DodoPaymentsOptions) =>\n async (user: User, ctx: GenericEndpointContext | null) => {\n if (ctx && options.createCustomerOnSignUp) {\n try {\n const customers = await options.client.customers.list({\n email: user.email,\n });\n const existingCustomer = customers.items[0];\n\n if (existingCustomer) {\n await options.client.customers.update(existingCustomer.customer_id, {\n name: user.name,\n });\n } else {\n // TODO: Add metadata to customer object via\n // getCustomerCreateParams option when it becomes\n // available in the API\n await options.client.customers.create({\n email: user.email,\n name: user.name,\n });\n }\n } catch (e: unknown) {\n if (e instanceof Error) {\n throw new APIError(\"INTERNAL_SERVER_ERROR\", {\n message: `DodoPayments customer creation failed. Error: ${e.message}`,\n });\n }\n\n throw new APIError(\"INTERNAL_SERVER_ERROR\", {\n message: `DodoPayments customer creation failed. Error: ${e}`,\n });\n }\n }\n };\n\nexport const onUserUpdate =\n (options: DodoPaymentsOptions) =>\n async (user: User, ctx: GenericEndpointContext | null) => {\n if (ctx && options.createCustomerOnSignUp) {\n try {\n const customers = await options.client.customers.list({\n email: user.email,\n });\n const existingCustomer = customers.items[0];\n\n if (existingCustomer) {\n // TODO: Add metadata to customer object via\n // getCustomerCreateParams option when it becomes\n // available in the API\n await options.client.customers.update(existingCustomer.customer_id, {\n name: user.name,\n });\n }\n } catch (e: unknown) {\n if (e instanceof Error) {\n ctx.context.logger.error(\n `DodoPayments customer update failed. Error: ${e.message}`,\n );\n } else {\n ctx.context.logger.error(\n `DodoPayments customer update failed. Error: ${e}`,\n );\n }\n }\n }\n };\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,iBAAyB;AAGlB,IAAM,eACX,CAAC,YACD,OAAO,MAAY,QAAuC;AACxD,MAAI,OAAO,QAAQ,wBAAwB;AACzC,QAAI;AACF,YAAM,YAAY,MAAM,QAAQ,OAAO,UAAU,KAAK;AAAA,QACpD,OAAO,KAAK;AAAA,MACd,CAAC;AACD,YAAM,mBAAmB,UAAU,MAAM,CAAC;AAE1C,UAAI,kBAAkB;AACpB,cAAM,QAAQ,OAAO,UAAU,OAAO,iBAAiB,aAAa;AAAA,UAClE,MAAM,KAAK;AAAA,QACb,CAAC;AAAA,
|
|
1
|
+
{"version":3,"sources":["../../src/hooks/customer.ts"],"sourcesContent":["import type { GenericEndpointContext, User } from \"better-auth\";\nimport { APIError } from \"better-auth/api\";\nimport type { DodoPaymentsOptions } from \"../types\";\n\nexport const onUserCreate =\n (options: DodoPaymentsOptions) =>\n async (user: User, ctx: GenericEndpointContext | null) => {\n if (ctx && options.createCustomerOnSignUp) {\n try {\n const customers = await options.client.customers.list({\n email: user.email,\n });\n const existingCustomer = customers.items[0];\n\n let customerId: string;\n\n if (existingCustomer) {\n await options.client.customers.update(existingCustomer.customer_id, {\n name: user.name,\n });\n customerId = existingCustomer.customer_id;\n } else {\n // TODO: Add metadata to customer object via\n // getCustomerCreateParams option when it becomes\n // available in the API\n const newCustomer = await options.client.customers.create({\n email: user.email,\n name: user.name,\n }, { idempotencyKey: user.id });\n customerId = newCustomer.customer_id;\n }\n\n ctx.context.internalAdapter.updateUser(user.id, {\n dodoCustomerId: customerId,\n }).catch((e: unknown) => {\n ctx.context.logger.warn(\n `DodoPayments: failed to store dodoCustomerId for user ${user.id}. Error: ${e instanceof Error ? e.message : e}`,\n );\n });\n } catch (e: unknown) {\n if (e instanceof Error) {\n throw new APIError(\"INTERNAL_SERVER_ERROR\", {\n message: `DodoPayments customer creation failed. Error: ${e.message}`,\n });\n }\n\n throw new APIError(\"INTERNAL_SERVER_ERROR\", {\n message: `DodoPayments customer creation failed. Error: ${e}`,\n });\n }\n }\n };\n\nexport const onUserUpdate =\n (options: DodoPaymentsOptions) =>\n async (user: User, ctx: GenericEndpointContext | null) => {\n if (ctx && options.createCustomerOnSignUp) {\n try {\n const customers = await options.client.customers.list({\n email: user.email,\n });\n const existingCustomer = customers.items[0];\n\n if (existingCustomer) {\n // TODO: Add metadata to customer object via\n // getCustomerCreateParams option when it becomes\n // available in the API\n await options.client.customers.update(existingCustomer.customer_id, {\n name: user.name,\n });\n\n // Backfill dodoCustomerId if it doesn't exist\n if (!(user as User & { dodoCustomerId?: string }).dodoCustomerId) {\n ctx.context.internalAdapter.updateUser(user.id, {\n dodoCustomerId: existingCustomer.customer_id,\n }).catch((e: unknown) => {\n ctx.context.logger.warn(\n `DodoPayments: failed to backfill dodoCustomerId for user ${user.id}. Error: ${e instanceof Error ? e.message : e}`,\n );\n });\n }\n }\n } catch (e: unknown) {\n if (e instanceof Error) {\n ctx.context.logger.error(\n `DodoPayments customer update failed. Error: ${e.message}`,\n );\n } else {\n ctx.context.logger.error(\n `DodoPayments customer update failed. Error: ${e}`,\n );\n }\n }\n }\n };\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,iBAAyB;AAGlB,IAAM,eACX,CAAC,YACD,OAAO,MAAY,QAAuC;AACxD,MAAI,OAAO,QAAQ,wBAAwB;AACzC,QAAI;AACF,YAAM,YAAY,MAAM,QAAQ,OAAO,UAAU,KAAK;AAAA,QACpD,OAAO,KAAK;AAAA,MACd,CAAC;AACD,YAAM,mBAAmB,UAAU,MAAM,CAAC;AAE1C,UAAI;AAEJ,UAAI,kBAAkB;AACpB,cAAM,QAAQ,OAAO,UAAU,OAAO,iBAAiB,aAAa;AAAA,UAClE,MAAM,KAAK;AAAA,QACb,CAAC;AACD,qBAAa,iBAAiB;AAAA,MAChC,OAAO;AAIL,cAAM,cAAc,MAAM,QAAQ,OAAO,UAAU,OAAO;AAAA,UACxD,OAAO,KAAK;AAAA,UACZ,MAAM,KAAK;AAAA,QACb,GAAG,EAAE,gBAAgB,KAAK,GAAG,CAAC;AAC9B,qBAAa,YAAY;AAAA,MAC3B;AAEA,UAAI,QAAQ,gBAAgB,WAAW,KAAK,IAAI;AAAA,QAC9C,gBAAgB;AAAA,MAClB,CAAC,EAAE,MAAM,CAAC,MAAe;AACvB,YAAI,QAAQ,OAAO;AAAA,UACjB,yDAAyD,KAAK,EAAE,YAAY,aAAa,QAAQ,EAAE,UAAU,CAAC;AAAA,QAChH;AAAA,MACF,CAAC;AAAA,IACH,SAAS,GAAY;AACnB,UAAI,aAAa,OAAO;AACtB,cAAM,IAAI,oBAAS,yBAAyB;AAAA,UAC1C,SAAS,iDAAiD,EAAE,OAAO;AAAA,QACrE,CAAC;AAAA,MACH;AAEA,YAAM,IAAI,oBAAS,yBAAyB;AAAA,QAC1C,SAAS,iDAAiD,CAAC;AAAA,MAC7D,CAAC;AAAA,IACH;AAAA,EACF;AACF;AAEK,IAAM,eACX,CAAC,YACD,OAAO,MAAY,QAAuC;AACxD,MAAI,OAAO,QAAQ,wBAAwB;AACzC,QAAI;AACF,YAAM,YAAY,MAAM,QAAQ,OAAO,UAAU,KAAK;AAAA,QACpD,OAAO,KAAK;AAAA,MACd,CAAC;AACD,YAAM,mBAAmB,UAAU,MAAM,CAAC;AAE1C,UAAI,kBAAkB;AAIpB,cAAM,QAAQ,OAAO,UAAU,OAAO,iBAAiB,aAAa;AAAA,UAClE,MAAM,KAAK;AAAA,QACb,CAAC;AAGD,YAAI,CAAE,KAA4C,gBAAgB;AAChE,cAAI,QAAQ,gBAAgB,WAAW,KAAK,IAAI;AAAA,YAC9C,gBAAgB,iBAAiB;AAAA,UACnC,CAAC,EAAE,MAAM,CAAC,MAAe;AACvB,gBAAI,QAAQ,OAAO;AAAA,cACjB,4DAA4D,KAAK,EAAE,YAAY,aAAa,QAAQ,EAAE,UAAU,CAAC;AAAA,YACnH;AAAA,UACF,CAAC;AAAA,QACH;AAAA,MACF;AAAA,IACF,SAAS,GAAY;AACnB,UAAI,aAAa,OAAO;AACtB,YAAI,QAAQ,OAAO;AAAA,UACjB,+CAA+C,EAAE,OAAO;AAAA,QAC1D;AAAA,MACF,OAAO;AACL,YAAI,QAAQ,OAAO;AAAA,UACjB,+CAA+C,CAAC;AAAA,QAClD;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;","names":[]}
|
package/dist/hooks/customer.js
CHANGED
package/dist/index.cjs
CHANGED
|
@@ -38,16 +38,26 @@ var onUserCreate = (options) => async (user, ctx) => {
|
|
|
38
38
|
email: user.email
|
|
39
39
|
});
|
|
40
40
|
const existingCustomer = customers.items[0];
|
|
41
|
+
let customerId;
|
|
41
42
|
if (existingCustomer) {
|
|
42
43
|
await options.client.customers.update(existingCustomer.customer_id, {
|
|
43
44
|
name: user.name
|
|
44
45
|
});
|
|
46
|
+
customerId = existingCustomer.customer_id;
|
|
45
47
|
} else {
|
|
46
|
-
await options.client.customers.create({
|
|
48
|
+
const newCustomer = await options.client.customers.create({
|
|
47
49
|
email: user.email,
|
|
48
50
|
name: user.name
|
|
49
|
-
});
|
|
51
|
+
}, { idempotencyKey: user.id });
|
|
52
|
+
customerId = newCustomer.customer_id;
|
|
50
53
|
}
|
|
54
|
+
ctx.context.internalAdapter.updateUser(user.id, {
|
|
55
|
+
dodoCustomerId: customerId
|
|
56
|
+
}).catch((e) => {
|
|
57
|
+
ctx.context.logger.warn(
|
|
58
|
+
`DodoPayments: failed to store dodoCustomerId for user ${user.id}. Error: ${e instanceof Error ? e.message : e}`
|
|
59
|
+
);
|
|
60
|
+
});
|
|
51
61
|
} catch (e) {
|
|
52
62
|
if (e instanceof Error) {
|
|
53
63
|
throw new import_api.APIError("INTERNAL_SERVER_ERROR", {
|
|
@@ -71,6 +81,15 @@ var onUserUpdate = (options) => async (user, ctx) => {
|
|
|
71
81
|
await options.client.customers.update(existingCustomer.customer_id, {
|
|
72
82
|
name: user.name
|
|
73
83
|
});
|
|
84
|
+
if (!user.dodoCustomerId) {
|
|
85
|
+
ctx.context.internalAdapter.updateUser(user.id, {
|
|
86
|
+
dodoCustomerId: existingCustomer.customer_id
|
|
87
|
+
}).catch((e) => {
|
|
88
|
+
ctx.context.logger.warn(
|
|
89
|
+
`DodoPayments: failed to backfill dodoCustomerId for user ${user.id}. Error: ${e instanceof Error ? e.message : e}`
|
|
90
|
+
);
|
|
91
|
+
});
|
|
92
|
+
}
|
|
74
93
|
}
|
|
75
94
|
} catch (e) {
|
|
76
95
|
if (e instanceof Error) {
|
|
@@ -97,6 +116,27 @@ var dodopaymentsClient = () => {
|
|
|
97
116
|
// src/plugins/portal.ts
|
|
98
117
|
var import_api2 = require("better-auth/api");
|
|
99
118
|
var import_v3 = require("zod/v3");
|
|
119
|
+
|
|
120
|
+
// src/utils.ts
|
|
121
|
+
async function getOrCreateCustomerId(dodopayments2, session, internalAdapter) {
|
|
122
|
+
const dodoCustomerId = session.user["dodoCustomerId"];
|
|
123
|
+
if (dodoCustomerId) return dodoCustomerId;
|
|
124
|
+
const customers = await dodopayments2.customers.list({
|
|
125
|
+
email: session.user.email
|
|
126
|
+
});
|
|
127
|
+
let customer = customers.items[0];
|
|
128
|
+
if (!customer) {
|
|
129
|
+
customer = await dodopayments2.customers.create({
|
|
130
|
+
email: session.user.email,
|
|
131
|
+
name: session.user.name
|
|
132
|
+
}, { idempotencyKey: session.user.id });
|
|
133
|
+
}
|
|
134
|
+
internalAdapter.updateUser(session.user.id, { dodoCustomerId: customer.customer_id }).catch(() => {
|
|
135
|
+
});
|
|
136
|
+
return customer.customer_id;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// src/plugins/portal.ts
|
|
100
140
|
var portal = () => (dodopayments2) => {
|
|
101
141
|
return {
|
|
102
142
|
dodoPortal: (0, import_api2.createAuthEndpoint)(
|
|
@@ -117,20 +157,12 @@ var portal = () => (dodopayments2) => {
|
|
|
117
157
|
});
|
|
118
158
|
}
|
|
119
159
|
try {
|
|
120
|
-
const
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
if (!customer) {
|
|
125
|
-
customer = await createCustomer(
|
|
126
|
-
dodopayments2,
|
|
127
|
-
ctx.context.session.user.email,
|
|
128
|
-
ctx.context.session.user.name
|
|
129
|
-
);
|
|
130
|
-
}
|
|
131
|
-
const customerSession = await dodopayments2.customers.customerPortal.create(
|
|
132
|
-
customer.customer_id
|
|
160
|
+
const customerId = await getOrCreateCustomerId(
|
|
161
|
+
dodopayments2,
|
|
162
|
+
ctx.context.session,
|
|
163
|
+
ctx.context.internalAdapter
|
|
133
164
|
);
|
|
165
|
+
const customerSession = await dodopayments2.customers.customerPortal.create(customerId);
|
|
134
166
|
return ctx.json({
|
|
135
167
|
url: customerSession.link,
|
|
136
168
|
redirect: true
|
|
@@ -177,19 +209,13 @@ var portal = () => (dodopayments2) => {
|
|
|
177
209
|
});
|
|
178
210
|
}
|
|
179
211
|
try {
|
|
180
|
-
const
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
customer = await createCustomer(
|
|
186
|
-
dodopayments2,
|
|
187
|
-
ctx.context.session.user.email,
|
|
188
|
-
ctx.context.session.user.name
|
|
189
|
-
);
|
|
190
|
-
}
|
|
212
|
+
const customerId = await getOrCreateCustomerId(
|
|
213
|
+
dodopayments2,
|
|
214
|
+
ctx.context.session,
|
|
215
|
+
ctx.context.internalAdapter
|
|
216
|
+
);
|
|
191
217
|
const subscriptions = await dodopayments2.subscriptions.list({
|
|
192
|
-
customer_id:
|
|
218
|
+
customer_id: customerId,
|
|
193
219
|
// page number is 0-indexed
|
|
194
220
|
page_number: ctx.query?.page ? ctx.query.page - 1 : void 0,
|
|
195
221
|
page_size: ctx.query?.limit,
|
|
@@ -243,19 +269,13 @@ var portal = () => (dodopayments2) => {
|
|
|
243
269
|
});
|
|
244
270
|
}
|
|
245
271
|
try {
|
|
246
|
-
const
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
customer = await createCustomer(
|
|
252
|
-
dodopayments2,
|
|
253
|
-
ctx.context.session.user.email,
|
|
254
|
-
ctx.context.session.user.name
|
|
255
|
-
);
|
|
256
|
-
}
|
|
272
|
+
const customerId = await getOrCreateCustomerId(
|
|
273
|
+
dodopayments2,
|
|
274
|
+
ctx.context.session,
|
|
275
|
+
ctx.context.internalAdapter
|
|
276
|
+
);
|
|
257
277
|
const payments = await dodopayments2.payments.list({
|
|
258
|
-
customer_id:
|
|
278
|
+
customer_id: customerId,
|
|
259
279
|
// page number is 0-indexed
|
|
260
280
|
page_number: ctx.query?.page ? ctx.query.page - 1 : void 0,
|
|
261
281
|
page_size: ctx.query?.limit,
|
|
@@ -276,13 +296,6 @@ var portal = () => (dodopayments2) => {
|
|
|
276
296
|
)
|
|
277
297
|
};
|
|
278
298
|
};
|
|
279
|
-
async function createCustomer(dodopayments2, email, name) {
|
|
280
|
-
const customer = await dodopayments2.customers.create({
|
|
281
|
-
email,
|
|
282
|
-
name
|
|
283
|
-
});
|
|
284
|
-
return customer;
|
|
285
|
-
}
|
|
286
299
|
|
|
287
300
|
// src/plugins/checkout.ts
|
|
288
301
|
var import_api3 = require("better-auth/api");
|
|
@@ -558,22 +571,16 @@ var usage = () => (dodopayments2) => {
|
|
|
558
571
|
});
|
|
559
572
|
}
|
|
560
573
|
try {
|
|
561
|
-
const
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
customer = await createCustomer2(
|
|
567
|
-
dodopayments2,
|
|
568
|
-
ctx.context.session.user.email,
|
|
569
|
-
ctx.context.session.user.name
|
|
570
|
-
);
|
|
571
|
-
}
|
|
574
|
+
const customerId = await getOrCreateCustomerId(
|
|
575
|
+
dodopayments2,
|
|
576
|
+
ctx.context.session,
|
|
577
|
+
ctx.context.internalAdapter
|
|
578
|
+
);
|
|
572
579
|
const result = await dodopayments2.usageEvents.ingest({
|
|
573
580
|
events: [
|
|
574
581
|
{
|
|
575
582
|
event_id: ctx.body.event_id,
|
|
576
|
-
customer_id:
|
|
583
|
+
customer_id: customerId,
|
|
577
584
|
event_name: ctx.body.event_name,
|
|
578
585
|
timestamp: ctx.body.timestamp,
|
|
579
586
|
metadata: ctx.body.metadata
|
|
@@ -620,19 +627,13 @@ var usage = () => (dodopayments2) => {
|
|
|
620
627
|
});
|
|
621
628
|
}
|
|
622
629
|
try {
|
|
623
|
-
const
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
customer = await createCustomer2(
|
|
629
|
-
dodopayments2,
|
|
630
|
-
ctx.context.session.user.email,
|
|
631
|
-
ctx.context.session.user.name
|
|
632
|
-
);
|
|
633
|
-
}
|
|
630
|
+
const customerId = await getOrCreateCustomerId(
|
|
631
|
+
dodopayments2,
|
|
632
|
+
ctx.context.session,
|
|
633
|
+
ctx.context.internalAdapter
|
|
634
|
+
);
|
|
634
635
|
const meters = await dodopayments2.usageEvents.list({
|
|
635
|
-
customer_id:
|
|
636
|
+
customer_id: customerId,
|
|
636
637
|
...ctx.query
|
|
637
638
|
});
|
|
638
639
|
return ctx.json({ items: meters.items });
|
|
@@ -650,13 +651,6 @@ var usage = () => (dodopayments2) => {
|
|
|
650
651
|
)
|
|
651
652
|
};
|
|
652
653
|
};
|
|
653
|
-
async function createCustomer2(dodopayments2, email, name) {
|
|
654
|
-
const customer = await dodopayments2.customers.create({
|
|
655
|
-
email,
|
|
656
|
-
name
|
|
657
|
-
});
|
|
658
|
-
return customer;
|
|
659
|
-
}
|
|
660
654
|
|
|
661
655
|
// src/index.ts
|
|
662
656
|
var dodopayments = (options) => {
|
|
@@ -666,6 +660,17 @@ var dodopayments = (options) => {
|
|
|
666
660
|
}, {});
|
|
667
661
|
return {
|
|
668
662
|
id: "dodopayments",
|
|
663
|
+
schema: {
|
|
664
|
+
user: {
|
|
665
|
+
fields: {
|
|
666
|
+
dodoCustomerId: {
|
|
667
|
+
type: "string",
|
|
668
|
+
required: false,
|
|
669
|
+
input: false
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
},
|
|
669
674
|
endpoints: {
|
|
670
675
|
...plugins
|
|
671
676
|
},
|