@dodopayments/better-auth 1.4.4 → 1.6.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.
Files changed (50) hide show
  1. package/README.md +75 -5
  2. package/dist/chunk-527Y7FSE.js +90 -0
  3. package/dist/chunk-527Y7FSE.js.map +1 -0
  4. package/dist/{chunk-47N33D2M.js → chunk-ARA27DRZ.js} +17 -32
  5. package/dist/chunk-ARA27DRZ.js.map +1 -0
  6. package/dist/{chunk-KXU6PYZF.js → chunk-DTOB4IQZ.js} +22 -45
  7. package/dist/chunk-DTOB4IQZ.js.map +1 -0
  8. package/dist/chunk-TOPOAYYO.js +23 -0
  9. package/dist/chunk-TOPOAYYO.js.map +1 -0
  10. package/dist/client.d.cts +1 -1
  11. package/dist/client.d.ts +1 -1
  12. package/dist/hooks/customer.cjs +39 -11
  13. package/dist/hooks/customer.cjs.map +1 -1
  14. package/dist/hooks/customer.d.cts +1 -1
  15. package/dist/hooks/customer.d.ts +1 -1
  16. package/dist/hooks/customer.js +1 -1
  17. package/dist/index.cjs +100 -86
  18. package/dist/index.cjs.map +1 -1
  19. package/dist/index.d.cts +13 -2
  20. package/dist/index.d.ts +13 -2
  21. package/dist/index.js +18 -6
  22. package/dist/index.js.map +1 -1
  23. package/dist/plugins/checkout.d.cts +1 -1
  24. package/dist/plugins/checkout.d.ts +1 -1
  25. package/dist/plugins/portal.cjs +38 -44
  26. package/dist/plugins/portal.cjs.map +1 -1
  27. package/dist/plugins/portal.d.cts +1 -1
  28. package/dist/plugins/portal.d.ts +1 -1
  29. package/dist/plugins/portal.js +2 -1
  30. package/dist/plugins/usage.cjs +33 -31
  31. package/dist/plugins/usage.cjs.map +1 -1
  32. package/dist/plugins/usage.js +2 -1
  33. package/dist/plugins/webhooks.d.cts +1 -1
  34. package/dist/plugins/webhooks.d.ts +1 -1
  35. package/dist/{types-4JE4OwKb.d.cts → types-3pb2RGTM.d.cts} +12 -1
  36. package/dist/{types-B9rx1bt7.d.ts → types-DygjjcRn.d.ts} +12 -1
  37. package/dist/types.cjs.map +1 -1
  38. package/dist/types.d.cts +1 -1
  39. package/dist/types.d.ts +1 -1
  40. package/dist/utils.cjs +47 -0
  41. package/dist/utils.cjs.map +1 -0
  42. package/dist/utils.d.cts +13 -0
  43. package/dist/utils.d.ts +13 -0
  44. package/dist/utils.js +7 -0
  45. package/dist/utils.js.map +1 -0
  46. package/package.json +1 -1
  47. package/dist/chunk-47N33D2M.js.map +0 -1
  48. package/dist/chunk-BII7QAPD.js +0 -62
  49. package/dist/chunk-BII7QAPD.js.map +0 -1
  50. package/dist/chunk-KXU6PYZF.js.map +0 -1
@@ -25,6 +25,27 @@ __export(portal_exports, {
25
25
  module.exports = __toCommonJS(portal_exports);
26
26
  var import_api = require("better-auth/api");
27
27
  var import_v3 = require("zod/v3");
28
+
29
+ // src/utils.ts
30
+ async function getOrCreateCustomerId(dodopayments, session, internalAdapter) {
31
+ const dodoCustomerId = session.user["dodoCustomerId"];
32
+ if (dodoCustomerId) return dodoCustomerId;
33
+ const customers = await dodopayments.customers.list({
34
+ email: session.user.email
35
+ });
36
+ let customer = customers.items[0];
37
+ if (!customer) {
38
+ customer = await dodopayments.customers.create({
39
+ email: session.user.email,
40
+ name: session.user.name
41
+ }, { idempotencyKey: session.user.id });
42
+ }
43
+ internalAdapter.updateUser(session.user.id, { dodoCustomerId: customer.customer_id }).catch(() => {
44
+ });
45
+ return customer.customer_id;
46
+ }
47
+
48
+ // src/plugins/portal.ts
28
49
  var portal = () => (dodopayments) => {
29
50
  return {
30
51
  dodoPortal: (0, import_api.createAuthEndpoint)(
@@ -45,20 +66,12 @@ var portal = () => (dodopayments) => {
45
66
  });
46
67
  }
47
68
  try {
48
- const customers = await dodopayments.customers.list({
49
- email: ctx.context.session?.user.email
50
- });
51
- let customer = customers.items[0];
52
- if (!customer) {
53
- customer = await createCustomer(
54
- dodopayments,
55
- ctx.context.session.user.email,
56
- ctx.context.session.user.name
57
- );
58
- }
59
- const customerSession = await dodopayments.customers.customerPortal.create(
60
- customer.customer_id
69
+ const customerId = await getOrCreateCustomerId(
70
+ dodopayments,
71
+ ctx.context.session,
72
+ ctx.context.internalAdapter
61
73
  );
74
+ const customerSession = await dodopayments.customers.customerPortal.create(customerId);
62
75
  return ctx.json({
63
76
  url: customerSession.link,
64
77
  redirect: true
@@ -105,19 +118,13 @@ var portal = () => (dodopayments) => {
105
118
  });
106
119
  }
107
120
  try {
108
- const customers = await dodopayments.customers.list({
109
- email: ctx.context.session?.user.email
110
- });
111
- let customer = customers.items[0];
112
- if (!customer) {
113
- customer = await createCustomer(
114
- dodopayments,
115
- ctx.context.session.user.email,
116
- ctx.context.session.user.name
117
- );
118
- }
121
+ const customerId = await getOrCreateCustomerId(
122
+ dodopayments,
123
+ ctx.context.session,
124
+ ctx.context.internalAdapter
125
+ );
119
126
  const subscriptions = await dodopayments.subscriptions.list({
120
- customer_id: customer.customer_id,
127
+ customer_id: customerId,
121
128
  // page number is 0-indexed
122
129
  page_number: ctx.query?.page ? ctx.query.page - 1 : void 0,
123
130
  page_size: ctx.query?.limit,
@@ -171,19 +178,13 @@ var portal = () => (dodopayments) => {
171
178
  });
172
179
  }
173
180
  try {
174
- const customers = await dodopayments.customers.list({
175
- email: ctx.context.session?.user.email
176
- });
177
- let customer = customers.items[0];
178
- if (!customer) {
179
- customer = await createCustomer(
180
- dodopayments,
181
- ctx.context.session.user.email,
182
- ctx.context.session.user.name
183
- );
184
- }
181
+ const customerId = await getOrCreateCustomerId(
182
+ dodopayments,
183
+ ctx.context.session,
184
+ ctx.context.internalAdapter
185
+ );
185
186
  const payments = await dodopayments.payments.list({
186
- customer_id: customer.customer_id,
187
+ customer_id: customerId,
187
188
  // page number is 0-indexed
188
189
  page_number: ctx.query?.page ? ctx.query.page - 1 : void 0,
189
190
  page_size: ctx.query?.limit,
@@ -204,13 +205,6 @@ var portal = () => (dodopayments) => {
204
205
  )
205
206
  };
206
207
  };
207
- async function createCustomer(dodopayments, email, name) {
208
- const customer = await dodopayments.customers.create({
209
- email,
210
- name
211
- });
212
- return customer;
213
- }
214
208
  // Annotate the CommonJS export names for ESM import in node:
215
209
  0 && (module.exports = {
216
210
  portal
@@ -1 +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\";\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 customers = await dodopayments.customers.list({\n email: ctx.context.session?.user.email,\n });\n let customer = customers.items[0];\n\n if (!customer) {\n // upsert the customer, if they don't exist in DodoPayments\n customer = await createCustomer(\n dodopayments,\n ctx.context.session.user.email,\n ctx.context.session.user.name,\n );\n }\n\n const customerSession =\n await dodopayments.customers.customerPortal.create(\n customer.customer_id,\n );\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 customers = await dodopayments.customers.list({\n email: ctx.context.session?.user.email,\n });\n let customer = customers.items[0];\n\n if (!customer) {\n // upsert the customer, if they don't exist in DodoPayments\n customer = await createCustomer(\n dodopayments,\n ctx.context.session.user.email,\n ctx.context.session.user.name,\n );\n }\n\n const subscriptions = await dodopayments.subscriptions.list({\n customer_id: customer.customer_id,\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 customers = await dodopayments.customers.list({\n email: ctx.context.session?.user.email,\n });\n let customer = customers.items[0];\n\n if (!customer) {\n // upsert the customer, if they don't exist in DodoPayments\n customer = await createCustomer(\n dodopayments,\n ctx.context.session.user.email,\n ctx.context.session.user.name,\n );\n }\n\n const payments = await dodopayments.payments.list({\n customer_id: customer.customer_id,\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\nasync function createCustomer(\n dodopayments: DodoPayments,\n email: string,\n name: string,\n) {\n const customer = await dodopayments.customers.create({\n email,\n name,\n });\n\n return customer;\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/plugins/portal.ts","../../src/utils.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","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":"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","names":[]}
@@ -1,7 +1,7 @@
1
1
  import 'better-auth';
2
2
  import 'dodopayments';
3
3
  import 'zod/v3';
4
- export { p as portal } from '../types-4JE4OwKb.cjs';
4
+ export { p as portal } from '../types-3pb2RGTM.cjs';
5
5
  import '@dodopayments/core/webhook';
6
6
  import './usage.cjs';
7
7
  import 'dodopayments/resources/usage-events.mjs';
@@ -1,7 +1,7 @@
1
1
  import 'better-auth';
2
2
  import 'dodopayments';
3
3
  import 'zod/v3';
4
- export { p as portal } from '../types-B9rx1bt7.js';
4
+ export { p as portal } from '../types-DygjjcRn.js';
5
5
  import '@dodopayments/core/webhook';
6
6
  import './usage.js';
7
7
  import 'dodopayments/resources/usage-events.mjs';
@@ -1,6 +1,7 @@
1
1
  import {
2
2
  portal
3
- } from "../chunk-KXU6PYZF.js";
3
+ } from "../chunk-DTOB4IQZ.js";
4
+ import "../chunk-TOPOAYYO.js";
4
5
  export {
5
6
  portal
6
7
  };
@@ -25,6 +25,27 @@ __export(usage_exports, {
25
25
  module.exports = __toCommonJS(usage_exports);
26
26
  var import_api = require("better-auth/api");
27
27
  var import_v3 = require("zod/v3");
28
+
29
+ // src/utils.ts
30
+ async function getOrCreateCustomerId(dodopayments, session, internalAdapter) {
31
+ const dodoCustomerId = session.user["dodoCustomerId"];
32
+ if (dodoCustomerId) return dodoCustomerId;
33
+ const customers = await dodopayments.customers.list({
34
+ email: session.user.email
35
+ });
36
+ let customer = customers.items[0];
37
+ if (!customer) {
38
+ customer = await dodopayments.customers.create({
39
+ email: session.user.email,
40
+ name: session.user.name
41
+ }, { idempotencyKey: session.user.id });
42
+ }
43
+ internalAdapter.updateUser(session.user.id, { dodoCustomerId: customer.customer_id }).catch(() => {
44
+ });
45
+ return customer.customer_id;
46
+ }
47
+
48
+ // src/plugins/usage.ts
28
49
  var EventInputSchema = import_v3.z.object({
29
50
  event_id: import_v3.z.string(),
30
51
  event_name: import_v3.z.string(),
@@ -55,22 +76,16 @@ var usage = () => (dodopayments) => {
55
76
  });
56
77
  }
57
78
  try {
58
- const customers = await dodopayments.customers.list({
59
- email: ctx.context.session.user.email
60
- });
61
- let customer = customers.items[0];
62
- if (!customer) {
63
- customer = await createCustomer(
64
- dodopayments,
65
- ctx.context.session.user.email,
66
- ctx.context.session.user.name
67
- );
68
- }
79
+ const customerId = await getOrCreateCustomerId(
80
+ dodopayments,
81
+ ctx.context.session,
82
+ ctx.context.internalAdapter
83
+ );
69
84
  const result = await dodopayments.usageEvents.ingest({
70
85
  events: [
71
86
  {
72
87
  event_id: ctx.body.event_id,
73
- customer_id: customer.customer_id,
88
+ customer_id: customerId,
74
89
  event_name: ctx.body.event_name,
75
90
  timestamp: ctx.body.timestamp,
76
91
  metadata: ctx.body.metadata
@@ -117,19 +132,13 @@ var usage = () => (dodopayments) => {
117
132
  });
118
133
  }
119
134
  try {
120
- const customers = await dodopayments.customers.list({
121
- email: ctx.context.session.user.email
122
- });
123
- let customer = customers.items[0];
124
- if (!customer) {
125
- customer = await createCustomer(
126
- dodopayments,
127
- ctx.context.session.user.email,
128
- ctx.context.session.user.name
129
- );
130
- }
135
+ const customerId = await getOrCreateCustomerId(
136
+ dodopayments,
137
+ ctx.context.session,
138
+ ctx.context.internalAdapter
139
+ );
131
140
  const meters = await dodopayments.usageEvents.list({
132
- customer_id: customer.customer_id,
141
+ customer_id: customerId,
133
142
  ...ctx.query
134
143
  });
135
144
  return ctx.json({ items: meters.items });
@@ -147,13 +156,6 @@ var usage = () => (dodopayments) => {
147
156
  )
148
157
  };
149
158
  };
150
- async function createCustomer(dodopayments, email, name) {
151
- const customer = await dodopayments.customers.create({
152
- email,
153
- name
154
- });
155
- return customer;
156
- }
157
159
  // Annotate the CommonJS export names for ESM import in node:
158
160
  0 && (module.exports = {
159
161
  usage
@@ -1 +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\";\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 customers = await dodopayments.customers.list({\n email: ctx.context.session.user.email,\n });\n\n let customer = customers.items[0];\n\n // upsert the customer, if they don't exist in DodoPayments\n if (!customer) {\n customer = await createCustomer(\n dodopayments,\n ctx.context.session.user.email,\n ctx.context.session.user.name,\n );\n }\n\n const result = await dodopayments.usageEvents.ingest({\n events: [\n {\n event_id: ctx.body.event_id,\n customer_id: customer.customer_id,\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 customers = await dodopayments.customers.list({\n email: ctx.context.session.user.email,\n });\n\n let customer = customers.items[0];\n\n // upsert the customer, if they don't exist in DodoPayments\n if (!customer) {\n customer = await createCustomer(\n dodopayments,\n ctx.context.session.user.email,\n ctx.context.session.user.name,\n );\n }\n\n const meters = await dodopayments.usageEvents.list({\n customer_id: customer.customer_id,\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\nasync function createCustomer(\n dodopayments: DodoPayments,\n email: string,\n name: string,\n) {\n const customer = await dodopayments.customers.create({\n email,\n name,\n });\n\n return customer;\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/plugins/usage.ts","../../src/utils.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","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":"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","names":[]}
@@ -1,6 +1,7 @@
1
1
  import {
2
2
  usage
3
- } from "../chunk-47N33D2M.js";
3
+ } from "../chunk-ARA27DRZ.js";
4
+ import "../chunk-TOPOAYYO.js";
4
5
  export {
5
6
  usage
6
7
  };
@@ -1,7 +1,7 @@
1
1
  import 'better-auth';
2
2
  import 'dodopayments';
3
3
  import '@dodopayments/core/webhook';
4
- export { w as webhooks } from '../types-4JE4OwKb.cjs';
4
+ export { w as webhooks } from '../types-3pb2RGTM.cjs';
5
5
  import 'zod/v3';
6
6
  import './usage.cjs';
7
7
  import 'dodopayments/resources/usage-events.mjs';
@@ -1,7 +1,7 @@
1
1
  import 'better-auth';
2
2
  import 'dodopayments';
3
3
  import '@dodopayments/core/webhook';
4
- export { w as webhooks } from '../types-B9rx1bt7.js';
4
+ export { w as webhooks } from '../types-DygjjcRn.js';
5
5
  import 'zod/v3';
6
6
  import './usage.js';
7
7
  import 'dodopayments/resources/usage-events.mjs';
@@ -1,6 +1,6 @@
1
1
  import DodoPayments, { DodoPayments as DodoPayments$1 } from 'dodopayments';
2
2
  import * as better_auth from 'better-auth';
3
- import { UnionToIntersection } from 'better-auth';
3
+ import { User, UnionToIntersection } from 'better-auth';
4
4
  import { z } from 'zod/v3';
5
5
  import { WebhookHandlerConfig } from '@dodopayments/core/webhook';
6
6
  import { usage } from './plugins/usage.cjs';
@@ -677,6 +677,17 @@ interface DodoPaymentsOptions {
677
677
  * Use DodoPayments plugins
678
678
  */
679
679
  use: DodoPaymentsPlugins;
680
+ /**
681
+ * Optionally provide additional fields (e.g. metadata, phone_number) to include when creating
682
+ * or updating a DodoPayments customer.
683
+ */
684
+ getCustomerParams?: (user: User) => {
685
+ metadata?: Record<string, string>;
686
+ phone_number?: string | null;
687
+ } | Promise<{
688
+ metadata?: Record<string, string>;
689
+ phone_number?: string | null;
690
+ }>;
680
691
  }
681
692
  type PaymentsList = Awaited<ReturnType<DodoPayments$1["payments"]["list"]>>;
682
693
  type SubscriptionsList = Awaited<ReturnType<DodoPayments$1["subscriptions"]["list"]>>;
@@ -1,6 +1,6 @@
1
1
  import DodoPayments, { DodoPayments as DodoPayments$1 } from 'dodopayments';
2
2
  import * as better_auth from 'better-auth';
3
- import { UnionToIntersection } from 'better-auth';
3
+ import { User, UnionToIntersection } from 'better-auth';
4
4
  import { z } from 'zod/v3';
5
5
  import { WebhookHandlerConfig } from '@dodopayments/core/webhook';
6
6
  import { usage } from './plugins/usage.js';
@@ -677,6 +677,17 @@ interface DodoPaymentsOptions {
677
677
  * Use DodoPayments plugins
678
678
  */
679
679
  use: DodoPaymentsPlugins;
680
+ /**
681
+ * Optionally provide additional fields (e.g. metadata, phone_number) to include when creating
682
+ * or updating a DodoPayments customer.
683
+ */
684
+ getCustomerParams?: (user: User) => {
685
+ metadata?: Record<string, string>;
686
+ phone_number?: string | null;
687
+ } | Promise<{
688
+ metadata?: Record<string, string>;
689
+ phone_number?: string | null;
690
+ }>;
680
691
  }
681
692
  type PaymentsList = Awaited<ReturnType<DodoPayments$1["payments"]["list"]>>;
682
693
  type SubscriptionsList = Awaited<ReturnType<DodoPayments$1["subscriptions"]["list"]>>;
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/types.ts"],"sourcesContent":["import type { DodoPayments } from \"dodopayments\";\n\nimport type { UnionToIntersection } from \"better-auth\";\nimport type { checkout } from \"./plugins/checkout\";\nimport type { portal } from \"./plugins/portal\";\nimport type { webhooks } from \"./plugins/webhooks\";\nimport { usage } from \"./plugins/usage\";\n\nexport type Product = {\n /**\n * Product Id from DodoPayments Product\n */\n productId: string;\n /**\n * Easily identifiable slug for the product\n */\n slug: string;\n};\n\nexport type DodoPaymentsPlugin =\n | ReturnType<typeof checkout>\n | ReturnType<typeof portal>\n | ReturnType<typeof webhooks>\n | ReturnType<typeof usage>;\n\nexport type DodoPaymentsPlugins = [DodoPaymentsPlugin, ...DodoPaymentsPlugin[]];\n\nexport type DodoPaymentsEndpoints = UnionToIntersection<\n ReturnType<DodoPaymentsPlugin>\n>;\n\nexport interface DodoPaymentsOptions {\n /**\n * DodoPayments Client\n */\n client: DodoPayments;\n /**\n * Enable customer creation when a user signs up\n */\n createCustomerOnSignUp?: boolean;\n /**\n * Use DodoPayments plugins\n */\n use: DodoPaymentsPlugins;\n}\n\ntype PaymentsList = Awaited<ReturnType<DodoPayments[\"payments\"][\"list\"]>>;\ntype SubscriptionsList = Awaited<\n ReturnType<DodoPayments[\"subscriptions\"][\"list\"]>\n>;\nexport type PaymentItems = { items: PaymentsList[\"items\"] };\nexport type SubscriptionItems = { items: SubscriptionsList[\"items\"] };\nexport type CustomerPortalResponse = { url: string; redirect: boolean };\nexport type CreateCheckoutResponse = { url: string; redirect: boolean };\nexport type WebhookResponse = { received: boolean };\n"],"mappings":";;;;;;;;;;;;;;;;AAAA;AAAA;","names":[]}
1
+ {"version":3,"sources":["../src/types.ts"],"sourcesContent":["import type { DodoPayments } from \"dodopayments\";\n\nimport type { UnionToIntersection, User } from \"better-auth\";\nimport type { checkout } from \"./plugins/checkout\";\nimport type { portal } from \"./plugins/portal\";\nimport type { webhooks } from \"./plugins/webhooks\";\nimport { usage } from \"./plugins/usage\";\n\nexport type Product = {\n /**\n * Product Id from DodoPayments Product\n */\n productId: string;\n /**\n * Easily identifiable slug for the product\n */\n slug: string;\n};\n\nexport type DodoPaymentsPlugin =\n | ReturnType<typeof checkout>\n | ReturnType<typeof portal>\n | ReturnType<typeof webhooks>\n | ReturnType<typeof usage>;\n\nexport type DodoPaymentsPlugins = [DodoPaymentsPlugin, ...DodoPaymentsPlugin[]];\n\nexport type DodoPaymentsEndpoints = UnionToIntersection<\n ReturnType<DodoPaymentsPlugin>\n>;\n\nexport interface DodoPaymentsOptions {\n /**\n * DodoPayments Client\n */\n client: DodoPayments;\n /**\n * Enable customer creation when a user signs up\n */\n createCustomerOnSignUp?: boolean;\n /**\n * Use DodoPayments plugins\n */\n use: DodoPaymentsPlugins;\n /**\n * Optionally provide additional fields (e.g. metadata, phone_number) to include when creating\n * or updating a DodoPayments customer.\n */\n getCustomerParams?: (user: User) => { metadata?: Record<string, string>; phone_number?: string | null } | Promise<{ metadata?: Record<string, string>; phone_number?: string | null }>;\n}\n\ntype PaymentsList = Awaited<ReturnType<DodoPayments[\"payments\"][\"list\"]>>;\ntype SubscriptionsList = Awaited<\n ReturnType<DodoPayments[\"subscriptions\"][\"list\"]>\n>;\nexport type PaymentItems = { items: PaymentsList[\"items\"] };\nexport type SubscriptionItems = { items: SubscriptionsList[\"items\"] };\nexport type CustomerPortalResponse = { url: string; redirect: boolean };\nexport type CreateCheckoutResponse = { url: string; redirect: boolean };\nexport type WebhookResponse = { received: boolean };\n"],"mappings":";;;;;;;;;;;;;;;;AAAA;AAAA;","names":[]}
package/dist/types.d.cts CHANGED
@@ -1,6 +1,6 @@
1
1
  import 'dodopayments';
2
2
  import 'better-auth';
3
- export { C as CreateCheckoutResponse, a as CustomerPortalResponse, e as DodoPaymentsEndpoints, D as DodoPaymentsOptions, c as DodoPaymentsPlugin, d as DodoPaymentsPlugins, P as PaymentItems, b as Product, S as SubscriptionItems, W as WebhookResponse } from './types-4JE4OwKb.cjs';
3
+ export { C as CreateCheckoutResponse, a as CustomerPortalResponse, e as DodoPaymentsEndpoints, D as DodoPaymentsOptions, c as DodoPaymentsPlugin, d as DodoPaymentsPlugins, P as PaymentItems, b as Product, S as SubscriptionItems, W as WebhookResponse } from './types-3pb2RGTM.cjs';
4
4
  import './plugins/usage.cjs';
5
5
  import 'zod/v3';
6
6
  import '@dodopayments/core/webhook';
package/dist/types.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import 'dodopayments';
2
2
  import 'better-auth';
3
- export { C as CreateCheckoutResponse, a as CustomerPortalResponse, e as DodoPaymentsEndpoints, D as DodoPaymentsOptions, c as DodoPaymentsPlugin, d as DodoPaymentsPlugins, P as PaymentItems, b as Product, S as SubscriptionItems, W as WebhookResponse } from './types-B9rx1bt7.js';
3
+ export { C as CreateCheckoutResponse, a as CustomerPortalResponse, e as DodoPaymentsEndpoints, D as DodoPaymentsOptions, c as DodoPaymentsPlugin, d as DodoPaymentsPlugins, P as PaymentItems, b as Product, S as SubscriptionItems, W as WebhookResponse } from './types-DygjjcRn.js';
4
4
  import './plugins/usage.js';
5
5
  import 'zod/v3';
6
6
  import '@dodopayments/core/webhook';
package/dist/utils.cjs ADDED
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/utils.ts
21
+ var utils_exports = {};
22
+ __export(utils_exports, {
23
+ getOrCreateCustomerId: () => getOrCreateCustomerId
24
+ });
25
+ module.exports = __toCommonJS(utils_exports);
26
+ async function getOrCreateCustomerId(dodopayments, session, internalAdapter) {
27
+ const dodoCustomerId = session.user["dodoCustomerId"];
28
+ if (dodoCustomerId) return dodoCustomerId;
29
+ const customers = await dodopayments.customers.list({
30
+ email: session.user.email
31
+ });
32
+ let customer = customers.items[0];
33
+ if (!customer) {
34
+ customer = await dodopayments.customers.create({
35
+ email: session.user.email,
36
+ name: session.user.name
37
+ }, { idempotencyKey: session.user.id });
38
+ }
39
+ internalAdapter.updateUser(session.user.id, { dodoCustomerId: customer.customer_id }).catch(() => {
40
+ });
41
+ return customer.customer_id;
42
+ }
43
+ // Annotate the CommonJS export names for ESM import in node:
44
+ 0 && (module.exports = {
45
+ getOrCreateCustomerId
46
+ });
47
+ //# sourceMappingURL=utils.cjs.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":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;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":[]}
@@ -0,0 +1,13 @@
1
+ import { DodoPayments } from 'dodopayments';
2
+
3
+ declare function getOrCreateCustomerId(dodopayments: DodoPayments, session: {
4
+ user: {
5
+ id: string;
6
+ email: string;
7
+ name: string;
8
+ } & Record<string, unknown>;
9
+ }, internalAdapter: {
10
+ updateUser: (id: string, data: Record<string, unknown>) => Promise<unknown>;
11
+ }): Promise<string>;
12
+
13
+ export { getOrCreateCustomerId };
@@ -0,0 +1,13 @@
1
+ import { DodoPayments } from 'dodopayments';
2
+
3
+ declare function getOrCreateCustomerId(dodopayments: DodoPayments, session: {
4
+ user: {
5
+ id: string;
6
+ email: string;
7
+ name: string;
8
+ } & Record<string, unknown>;
9
+ }, internalAdapter: {
10
+ updateUser: (id: string, data: Record<string, unknown>) => Promise<unknown>;
11
+ }): Promise<string>;
12
+
13
+ export { getOrCreateCustomerId };
package/dist/utils.js ADDED
@@ -0,0 +1,7 @@
1
+ import {
2
+ getOrCreateCustomerId
3
+ } from "./chunk-TOPOAYYO.js";
4
+ export {
5
+ getOrCreateCustomerId
6
+ };
7
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dodopayments/better-auth",
3
- "version": "1.4.4",
3
+ "version": "1.6.1",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -1 +0,0 @@
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\";\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 customers = await dodopayments.customers.list({\n email: ctx.context.session.user.email,\n });\n\n let customer = customers.items[0];\n\n // upsert the customer, if they don't exist in DodoPayments\n if (!customer) {\n customer = await createCustomer(\n dodopayments,\n ctx.context.session.user.email,\n ctx.context.session.user.name,\n );\n }\n\n const result = await dodopayments.usageEvents.ingest({\n events: [\n {\n event_id: ctx.body.event_id,\n customer_id: customer.customer_id,\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 customers = await dodopayments.customers.list({\n email: ctx.context.session.user.email,\n });\n\n let customer = customers.items[0];\n\n // upsert the customer, if they don't exist in DodoPayments\n if (!customer) {\n customer = await createCustomer(\n dodopayments,\n ctx.context.session.user.email,\n ctx.context.session.user.name,\n );\n }\n\n const meters = await dodopayments.usageEvents.list({\n customer_id: customer.customer_id,\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\nasync function createCustomer(\n dodopayments: DodoPayments,\n email: string,\n name: string,\n) {\n const customer = await dodopayments.customers.create({\n email,\n name,\n });\n\n return customer;\n}\n"],"mappings":"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","names":[]}