@fantastic.dev/better-stripe 0.15.0 → 0.17.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.
Files changed (127) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/MIGRATION.md +6 -0
  3. package/README.md +15 -1
  4. package/dist/client/connect/payoutSnapshot.d.ts +2 -0
  5. package/dist/client/connect/payoutSnapshot.d.ts.map +1 -1
  6. package/dist/client/connect/payoutSnapshot.js +2 -0
  7. package/dist/client/connect/payoutSnapshot.js.map +1 -1
  8. package/dist/client/connect/refunds.d.ts +12 -0
  9. package/dist/client/connect/refunds.d.ts.map +1 -1
  10. package/dist/client/connect/refunds.js +8 -0
  11. package/dist/client/connect/refunds.js.map +1 -1
  12. package/dist/client/index.d.ts +8 -10
  13. package/dist/client/index.d.ts.map +1 -1
  14. package/dist/client/index.js +6 -3
  15. package/dist/client/index.js.map +1 -1
  16. package/dist/client/readContracts.d.ts +50 -0
  17. package/dist/client/readContracts.d.ts.map +1 -0
  18. package/dist/client/readContracts.js +24 -0
  19. package/dist/client/readContracts.js.map +1 -0
  20. package/dist/client/types/documents.d.ts +2 -0
  21. package/dist/client/types/documents.d.ts.map +1 -1
  22. package/dist/client/webhooks/processors.js +2 -0
  23. package/dist/client/webhooks/processors.js.map +1 -1
  24. package/dist/component/_generated/component.d.ts +213 -0
  25. package/dist/component/_generated/component.d.ts.map +1 -1
  26. package/dist/component/connect/mutations.d.ts +2 -0
  27. package/dist/component/connect/mutations.d.ts.map +1 -1
  28. package/dist/component/connect/mutations.js +8 -8
  29. package/dist/component/connect/mutations.js.map +1 -1
  30. package/dist/component/connect/queries.d.ts +102 -2
  31. package/dist/component/connect/queries.d.ts.map +1 -1
  32. package/dist/component/connect/queries.js +88 -45
  33. package/dist/component/connect/queries.js.map +1 -1
  34. package/dist/component/connect/schema.d.ts +14 -2
  35. package/dist/component/connect/schema.d.ts.map +1 -1
  36. package/dist/component/connect/schema.js +19 -1
  37. package/dist/component/connect/schema.js.map +1 -1
  38. package/dist/component/connect/validators.d.ts +13 -2
  39. package/dist/component/connect/validators.d.ts.map +1 -1
  40. package/dist/component/connect/validators.js +4 -0
  41. package/dist/component/connect/validators.js.map +1 -1
  42. package/dist/component/earnings/legacyReads.d.ts +51 -0
  43. package/dist/component/earnings/legacyReads.d.ts.map +1 -0
  44. package/dist/component/earnings/legacyReads.js +43 -0
  45. package/dist/component/earnings/legacyReads.js.map +1 -0
  46. package/dist/component/earnings/mutations.d.ts +9 -0
  47. package/dist/component/earnings/mutations.d.ts.map +1 -0
  48. package/dist/component/earnings/mutations.js +23 -0
  49. package/dist/component/earnings/mutations.js.map +1 -0
  50. package/dist/component/earnings/reads.d.ts +14 -0
  51. package/dist/component/earnings/reads.d.ts.map +1 -0
  52. package/dist/component/earnings/reads.js +28 -0
  53. package/dist/component/earnings/reads.js.map +1 -0
  54. package/dist/component/earnings/schema.d.ts +20 -0
  55. package/dist/component/earnings/schema.d.ts.map +1 -0
  56. package/dist/component/earnings/schema.js +12 -0
  57. package/dist/component/earnings/schema.js.map +1 -0
  58. package/dist/component/earnings/triggers.d.ts +1294 -0
  59. package/dist/component/earnings/triggers.d.ts.map +1 -0
  60. package/dist/component/earnings/triggers.js +68 -0
  61. package/dist/component/earnings/triggers.js.map +1 -0
  62. package/dist/component/products/queries.d.ts +47 -0
  63. package/dist/component/products/queries.d.ts.map +1 -1
  64. package/dist/component/products/queries.js +59 -0
  65. package/dist/component/products/queries.js.map +1 -1
  66. package/dist/component/refundHistory/queries.d.ts +28 -0
  67. package/dist/component/refundHistory/queries.d.ts.map +1 -0
  68. package/dist/component/refundHistory/queries.js +59 -0
  69. package/dist/component/refundHistory/queries.js.map +1 -0
  70. package/dist/component/schema.d.ts +33 -2
  71. package/dist/component/schema.js +2 -0
  72. package/dist/component/schema.js.map +1 -1
  73. package/dist/react/components/EarningsSummary.d.ts +3 -1
  74. package/dist/react/components/EarningsSummary.d.ts.map +1 -1
  75. package/dist/react/components/EarningsSummary.js +3 -3
  76. package/dist/react/components/EarningsSummary.js.map +1 -1
  77. package/dist/react/hooks/useCurrencyEarnings.d.ts +31 -0
  78. package/dist/react/hooks/useCurrencyEarnings.d.ts.map +1 -0
  79. package/dist/react/hooks/useCurrencyEarnings.js +30 -0
  80. package/dist/react/hooks/useCurrencyEarnings.js.map +1 -0
  81. package/dist/react/index.d.ts +3 -0
  82. package/dist/react/index.d.ts.map +1 -1
  83. package/dist/react/index.js +3 -0
  84. package/dist/react/index.js.map +1 -1
  85. package/dist/react/workflows/Costs.d.ts +1 -0
  86. package/dist/react/workflows/Costs.d.ts.map +1 -1
  87. package/dist/react/workflows/Costs.js +7 -3
  88. package/dist/react/workflows/Costs.js.map +1 -1
  89. package/docs/react-workflows.md +40 -0
  90. package/docs/read-contracts.md +136 -0
  91. package/package.json +3 -2
  92. package/src/client/connect/payoutSnapshot.test.ts +27 -0
  93. package/src/client/connect/payoutSnapshot.ts +4 -0
  94. package/src/client/connect/refunds.ts +28 -0
  95. package/src/client/index.ts +10 -11
  96. package/src/client/readContracts.ts +90 -0
  97. package/src/client/readPagination.test.ts +62 -0
  98. package/src/client/refund-history.test.ts +67 -0
  99. package/src/client/types/documents.ts +2 -0
  100. package/src/client/webhooks/payout-canceled.integration.test.ts +25 -0
  101. package/src/client/webhooks/processors.ts +2 -0
  102. package/src/component/_generated/api.ts +10 -0
  103. package/src/component/_generated/component.ts +257 -0
  104. package/src/component/connect/mutations.ts +8 -8
  105. package/src/component/connect/queries.ts +110 -48
  106. package/src/component/connect/schema.ts +19 -1
  107. package/src/component/connect/validators.ts +4 -0
  108. package/src/component/currency-migration.test.ts +119 -0
  109. package/src/component/currency-totals.test.ts +95 -0
  110. package/src/component/earnings/legacyReads.ts +59 -0
  111. package/src/component/earnings/mutations.ts +21 -0
  112. package/src/component/earnings/reads.ts +41 -0
  113. package/src/component/earnings/schema.ts +11 -0
  114. package/src/component/earnings/triggers.ts +91 -0
  115. package/src/component/products/queries.ts +74 -0
  116. package/src/component/public.test.ts +1 -1
  117. package/src/component/read-pagination.test.ts +193 -0
  118. package/src/component/refund-history.test.ts +198 -0
  119. package/src/component/refundHistory/queries.ts +99 -0
  120. package/src/component/schema.ts +2 -0
  121. package/src/react/components/EarningsSummary.tsx +5 -2
  122. package/src/react/hooks/useCurrencyEarnings.test.ts +59 -0
  123. package/src/react/hooks/useCurrencyEarnings.ts +73 -0
  124. package/src/react/index.ts +12 -0
  125. package/src/react/read-contracts.render.test.tsx +20 -0
  126. package/src/react/workflows/Costs.test.tsx +21 -0
  127. package/src/react/workflows/Costs.tsx +9 -3
@@ -0,0 +1,67 @@
1
+ import { componentsGeneric, type FunctionReference } from "convex/server";
2
+ import { expect, it } from "vitest";
3
+
4
+ import schema from "../component/schema.js";
5
+ import type { Component, RunCtx } from "./helpers.js";
6
+ import { BetterStripe, type RefundPageOptions } from "./index.js";
7
+ import { initConvexTest } from "./setup.test.js";
8
+
9
+ const modules = import.meta.glob("../component/**/*.{ts,js,tsx,jsx}");
10
+
11
+ it("reads multiple conjunctively scoped pages through the public client without provider credentials", async () => {
12
+ const t = initConvexTest();
13
+ t.registerComponent("betterStripe", schema, modules);
14
+ const component = componentsGeneric().betterStripe as unknown as Component;
15
+ const stripe = new BetterStripe(component, {});
16
+ const ctx = {
17
+ runQuery: (
18
+ ref: FunctionReference<"query">,
19
+ args: Record<string, unknown>,
20
+ ) => t.query(ref, args),
21
+ } as unknown as RunCtx;
22
+ for (let index = 0; index < 5; index++) {
23
+ await t.mutation(component.connect.mutations.upsertRefund, {
24
+ stripeRefundId: `re_${index}`,
25
+ accountId: index === 4 ? "acct_foreign" : "acct_owner",
26
+ stripePaymentIntentId: index === 3 ? "pi_foreign" : "pi_original",
27
+ stripeChargeId: "ch_original",
28
+ amount: 500,
29
+ currency: "jpy",
30
+ status: "succeeded",
31
+ });
32
+ }
33
+ const opts: RefundPageOptions = {
34
+ stripeAccountId: "acct_owner",
35
+ stripePaymentIntentId: "pi_original",
36
+ status: "succeeded",
37
+ paginationOpts: { numItems: 2, cursor: null },
38
+ };
39
+ const first = await stripe.paginateRefunds(ctx, opts);
40
+ expect(first.page).toHaveLength(2);
41
+ expect(first.isDone).toBe(false);
42
+ const last = await stripe.paginateRefunds(ctx, {
43
+ ...opts,
44
+ paginationOpts: { numItems: 2, cursor: first.continueCursor },
45
+ });
46
+ expect(last.isDone).toBe(true);
47
+ expect([...first.page, ...last.page]).toHaveLength(3);
48
+ for (const refund of [...first.page, ...last.page]) {
49
+ expect(refund).toMatchObject({
50
+ accountId: "acct_owner",
51
+ stripePaymentIntentId: "pi_original",
52
+ stripeChargeId: "ch_original",
53
+ amount: 500,
54
+ currency: "jpy",
55
+ status: "succeeded",
56
+ });
57
+ }
58
+ expect(
59
+ await stripe.paginateRefunds(ctx, {
60
+ ...opts,
61
+ stripeAccountId: "acct_absent",
62
+ }),
63
+ ).toMatchObject({ page: [], isDone: true });
64
+ expect(
65
+ await stripe.listRefunds(ctx, { stripeAccountId: "acct_owner", limit: 1 }),
66
+ ).toHaveLength(1);
67
+ });
@@ -124,6 +124,8 @@ export type StripeComponentPayout = {
124
124
  status: PayoutStatus;
125
125
  arrivalDate?: string;
126
126
  method?: string;
127
+ failureCode?: string;
128
+ failureMessage?: string;
127
129
  metadata?: Record<string, unknown>;
128
130
  };
129
131
 
@@ -190,3 +190,28 @@ it.each([
190
190
  expect(transport).not.toHaveBeenCalled();
191
191
  },
192
192
  );
193
+
194
+ it("persists signed failure details and clears them on a later snapshot", async () => {
195
+ const f = fixture("payout.failed", "failed");
196
+ f.event.data.object.failure_code = "account_closed";
197
+ f.event.data.object.failure_message = "Bank account closed";
198
+ expect((await f.deliver()).status).toBe(200);
199
+ const failed = await f.payout();
200
+ expect(failed).toMatchObject({
201
+ failureCode: "account_closed",
202
+ failureMessage: "Bank account closed",
203
+ accountId: "acct_qa_recipient",
204
+ });
205
+ expect((await f.deliver()).body).toMatchObject({ deduplicated: true });
206
+ expect(await f.payout()).toEqual(failed);
207
+ f.event.id = "evt_failure_cleared";
208
+ f.event.type = "payout.updated";
209
+ f.event.data.object.status = "pending";
210
+ f.event.data.object.failure_code = null;
211
+ f.event.data.object.failure_message = null;
212
+ expect((await f.deliver()).status).toBe(200);
213
+ const cleared = await f.payout();
214
+ expect(cleared?._id).toBe(failed?._id);
215
+ expect(cleared).not.toHaveProperty("failureCode");
216
+ expect(cleared).not.toHaveProperty("failureMessage");
217
+ });
@@ -921,6 +921,8 @@ async function handlePayoutEvent(
921
921
  "pending" | "paid" | "failed" | "canceled" | "in_transit",
922
922
  arrivalDate: epochToIso(payout.arrival_date),
923
923
  method: payout.method ?? undefined,
924
+ failureCode: payout.failure_code ?? undefined,
925
+ failureMessage: payout.failure_message ?? undefined,
924
926
  metadata: payout.metadata ?? undefined,
925
927
  });
926
928
  }
@@ -24,6 +24,10 @@ import type * as costRecovery_imports from "../costRecovery/imports.js";
24
24
  import type * as costRecovery_mutations from "../costRecovery/mutations.js";
25
25
  import type * as costRecovery_queries from "../costRecovery/queries.js";
26
26
  import type * as costRecovery_reservations from "../costRecovery/reservations.js";
27
+ import type * as earnings_legacyReads from "../earnings/legacyReads.js";
28
+ import type * as earnings_mutations from "../earnings/mutations.js";
29
+ import type * as earnings_reads from "../earnings/reads.js";
30
+ import type * as earnings_triggers from "../earnings/triggers.js";
27
31
  import type * as lib_fees from "../lib/fees.js";
28
32
  import type * as lib_idempotency from "../lib/idempotency.js";
29
33
  import type * as lib_paymentSeller from "../lib/paymentSeller.js";
@@ -32,6 +36,7 @@ import type * as lib_stripeFactory from "../lib/stripeFactory.js";
32
36
  import type * as products_mutations from "../products/mutations.js";
33
37
  import type * as products_queries from "../products/queries.js";
34
38
  import type * as products_validators from "../products/validators.js";
39
+ import type * as refundHistory_queries from "../refundHistory/queries.js";
35
40
  import type * as settlement_mutations from "../settlement/mutations.js";
36
41
  import type * as settlement_queries from "../settlement/queries.js";
37
42
  import type * as webhooks_mutations from "../webhooks/mutations.js";
@@ -62,6 +67,10 @@ const fullApi: ApiFromModules<{
62
67
  "costRecovery/mutations": typeof costRecovery_mutations;
63
68
  "costRecovery/queries": typeof costRecovery_queries;
64
69
  "costRecovery/reservations": typeof costRecovery_reservations;
70
+ "earnings/legacyReads": typeof earnings_legacyReads;
71
+ "earnings/mutations": typeof earnings_mutations;
72
+ "earnings/reads": typeof earnings_reads;
73
+ "earnings/triggers": typeof earnings_triggers;
65
74
  "lib/fees": typeof lib_fees;
66
75
  "lib/idempotency": typeof lib_idempotency;
67
76
  "lib/paymentSeller": typeof lib_paymentSeller;
@@ -70,6 +79,7 @@ const fullApi: ApiFromModules<{
70
79
  "products/mutations": typeof products_mutations;
71
80
  "products/queries": typeof products_queries;
72
81
  "products/validators": typeof products_validators;
82
+ "refundHistory/queries": typeof refundHistory_queries;
73
83
  "settlement/mutations": typeof settlement_mutations;
74
84
  "settlement/queries": typeof settlement_queries;
75
85
  "webhooks/mutations": typeof webhooks_mutations;
@@ -882,6 +882,8 @@ export type ComponentApi<Name extends string | undefined = string | undefined> =
882
882
  amount: number;
883
883
  arrivalDate?: string;
884
884
  currency: string;
885
+ failureCode?: string;
886
+ failureMessage?: string;
885
887
  metadata?: any;
886
888
  method?: string;
887
889
  status: "pending" | "paid" | "failed" | "canceled" | "in_transit";
@@ -965,6 +967,41 @@ export type ComponentApi<Name extends string | undefined = string | undefined> =
965
967
  sourceInvoiceId?: string;
966
968
  status: "pending" | "paid" | "failed" | "reversed";
967
969
  stripeTransferId: string;
970
+ totalsRecorded?: true;
971
+ }>;
972
+ },
973
+ Name
974
+ >;
975
+ getAccountEarningsByCurrency: FunctionReference<
976
+ "query",
977
+ "internal",
978
+ { destinationAccountId: string; previewLimit?: number },
979
+ {
980
+ totals: Array<{
981
+ currency: string;
982
+ gross: number;
983
+ net: number;
984
+ reversed: number;
985
+ transferCount: number;
986
+ }>;
987
+ transfers: Array<{
988
+ _creationTime: number;
989
+ _id: string;
990
+ amount: number;
991
+ currency: string;
992
+ destinationAccountId: string;
993
+ metadata?: any;
994
+ paymentId?: string;
995
+ reinstatement?: boolean;
996
+ reversalClaimedAmount?: number;
997
+ reversalStatus?: "partially_reversed" | "fully_reversed";
998
+ reversedAmount?: number;
999
+ role?: "store" | "affiliate" | "other";
1000
+ sourceChargeId?: string;
1001
+ sourceInvoiceId?: string;
1002
+ status: "pending" | "paid" | "failed" | "reversed";
1003
+ stripeTransferId: string;
1004
+ totalsRecorded?: true;
968
1005
  }>;
969
1006
  },
970
1007
  Name
@@ -983,10 +1020,41 @@ export type ComponentApi<Name extends string | undefined = string | undefined> =
983
1020
  amount: number;
984
1021
  arrivalDate?: string;
985
1022
  currency: string;
1023
+ failureCode?: string;
1024
+ failureMessage?: string;
1025
+ metadata?: any;
1026
+ method?: string;
1027
+ status: "pending" | "paid" | "failed" | "canceled" | "in_transit";
1028
+ stripePayoutId: string;
1029
+ totalsRecorded?: true;
1030
+ }>;
1031
+ },
1032
+ Name
1033
+ >;
1034
+ getAccountPayoutsByCurrency: FunctionReference<
1035
+ "query",
1036
+ "internal",
1037
+ { accountId: string; previewLimit?: number },
1038
+ {
1039
+ payouts: Array<{
1040
+ _creationTime: number;
1041
+ _id: string;
1042
+ accountId: string;
1043
+ amount: number;
1044
+ arrivalDate?: string;
1045
+ currency: string;
1046
+ failureCode?: string;
1047
+ failureMessage?: string;
986
1048
  metadata?: any;
987
1049
  method?: string;
988
1050
  status: "pending" | "paid" | "failed" | "canceled" | "in_transit";
989
1051
  stripePayoutId: string;
1052
+ totalsRecorded?: true;
1053
+ }>;
1054
+ totals: Array<{
1055
+ currency: string;
1056
+ paidOut: number;
1057
+ payoutCount: number;
990
1058
  }>;
991
1059
  },
992
1060
  Name
@@ -1072,10 +1140,13 @@ export type ComponentApi<Name extends string | undefined = string | undefined> =
1072
1140
  amount: number;
1073
1141
  arrivalDate?: string;
1074
1142
  currency: string;
1143
+ failureCode?: string;
1144
+ failureMessage?: string;
1075
1145
  metadata?: any;
1076
1146
  method?: string;
1077
1147
  status: "pending" | "paid" | "failed" | "canceled" | "in_transit";
1078
1148
  stripePayoutId: string;
1149
+ totalsRecorded?: true;
1079
1150
  } | null,
1080
1151
  Name
1081
1152
  >;
@@ -1090,10 +1161,13 @@ export type ComponentApi<Name extends string | undefined = string | undefined> =
1090
1161
  amount: number;
1091
1162
  arrivalDate?: string;
1092
1163
  currency: string;
1164
+ failureCode?: string;
1165
+ failureMessage?: string;
1093
1166
  metadata?: any;
1094
1167
  method?: string;
1095
1168
  status: "pending" | "paid" | "failed" | "canceled" | "in_transit";
1096
1169
  stripePayoutId: string;
1170
+ totalsRecorded?: true;
1097
1171
  } | null,
1098
1172
  Name
1099
1173
  >;
@@ -1164,6 +1238,7 @@ export type ComponentApi<Name extends string | undefined = string | undefined> =
1164
1238
  sourceInvoiceId?: string;
1165
1239
  status: "pending" | "paid" | "failed" | "reversed";
1166
1240
  stripeTransferId: string;
1241
+ totalsRecorded?: true;
1167
1242
  } | null,
1168
1243
  Name
1169
1244
  >;
@@ -1228,10 +1303,13 @@ export type ComponentApi<Name extends string | undefined = string | undefined> =
1228
1303
  amount: number;
1229
1304
  arrivalDate?: string;
1230
1305
  currency: string;
1306
+ failureCode?: string;
1307
+ failureMessage?: string;
1231
1308
  metadata?: any;
1232
1309
  method?: string;
1233
1310
  status: "pending" | "paid" | "failed" | "canceled" | "in_transit";
1234
1311
  stripePayoutId: string;
1312
+ totalsRecorded?: true;
1235
1313
  }>,
1236
1314
  Name
1237
1315
  >;
@@ -1295,6 +1373,7 @@ export type ComponentApi<Name extends string | undefined = string | undefined> =
1295
1373
  sourceInvoiceId?: string;
1296
1374
  status: "pending" | "paid" | "failed" | "reversed";
1297
1375
  stripeTransferId: string;
1376
+ totalsRecorded?: true;
1298
1377
  }>,
1299
1378
  Name
1300
1379
  >;
@@ -1319,6 +1398,7 @@ export type ComponentApi<Name extends string | undefined = string | undefined> =
1319
1398
  sourceInvoiceId?: string;
1320
1399
  status: "pending" | "paid" | "failed" | "reversed";
1321
1400
  stripeTransferId: string;
1401
+ totalsRecorded?: true;
1322
1402
  }>,
1323
1403
  Name
1324
1404
  >;
@@ -1340,6 +1420,44 @@ export type ComponentApi<Name extends string | undefined = string | undefined> =
1340
1420
  }>,
1341
1421
  Name
1342
1422
  >;
1423
+ paginatePayouts: FunctionReference<
1424
+ "query",
1425
+ "internal",
1426
+ {
1427
+ accountId: string;
1428
+ paginationOpts: {
1429
+ cursor: string | null;
1430
+ endCursor?: string | null;
1431
+ id?: number;
1432
+ maximumBytesRead?: number;
1433
+ maximumRowsRead?: number;
1434
+ numItems: number;
1435
+ };
1436
+ status?: "pending" | "paid" | "failed" | "canceled" | "in_transit";
1437
+ },
1438
+ {
1439
+ continueCursor: string;
1440
+ isDone: boolean;
1441
+ page: Array<{
1442
+ _creationTime: number;
1443
+ _id: string;
1444
+ accountId: string;
1445
+ amount: number;
1446
+ arrivalDate?: string;
1447
+ currency: string;
1448
+ failureCode?: string;
1449
+ failureMessage?: string;
1450
+ metadata?: any;
1451
+ method?: string;
1452
+ status: "pending" | "paid" | "failed" | "canceled" | "in_transit";
1453
+ stripePayoutId: string;
1454
+ totalsRecorded?: true;
1455
+ }>;
1456
+ pageStatus?: "SplitRecommended" | "SplitRequired" | null;
1457
+ splitCursor?: string | null;
1458
+ },
1459
+ Name
1460
+ >;
1343
1461
  paginateTransfersByAccount: FunctionReference<
1344
1462
  "query",
1345
1463
  "internal",
@@ -1374,6 +1492,7 @@ export type ComponentApi<Name extends string | undefined = string | undefined> =
1374
1492
  sourceInvoiceId?: string;
1375
1493
  status: "pending" | "paid" | "failed" | "reversed";
1376
1494
  stripeTransferId: string;
1495
+ totalsRecorded?: true;
1377
1496
  }>;
1378
1497
  pageStatus?: "SplitRecommended" | "SplitRequired" | null;
1379
1498
  splitCursor?: string | null;
@@ -2064,6 +2183,17 @@ export type ComponentApi<Name extends string | undefined = string | undefined> =
2064
2183
  >;
2065
2184
  };
2066
2185
  };
2186
+ earnings: {
2187
+ mutations: {
2188
+ backfillCurrencyTotals: FunctionReference<
2189
+ "mutation",
2190
+ "internal",
2191
+ { cursor: string | null; kind: "earnings" | "payouts" },
2192
+ { continueCursor: string; isDone: boolean },
2193
+ Name
2194
+ >;
2195
+ };
2196
+ };
2067
2197
  products: {
2068
2198
  mutations: {
2069
2199
  upsertPrice: FunctionReference<
@@ -2233,6 +2363,133 @@ export type ComponentApi<Name extends string | undefined = string | undefined> =
2233
2363
  }>,
2234
2364
  Name
2235
2365
  >;
2366
+ paginatePrices: FunctionReference<
2367
+ "query",
2368
+ "internal",
2369
+ {
2370
+ active?: boolean;
2371
+ paginationOpts: {
2372
+ cursor: string | null;
2373
+ endCursor?: string | null;
2374
+ id?: number;
2375
+ maximumBytesRead?: number;
2376
+ maximumRowsRead?: number;
2377
+ numItems: number;
2378
+ };
2379
+ productId?: string;
2380
+ },
2381
+ {
2382
+ continueCursor: string;
2383
+ isDone: boolean;
2384
+ page: Array<{
2385
+ _creationTime: number;
2386
+ _id: string;
2387
+ active: boolean;
2388
+ currency: string;
2389
+ interval?: "day" | "week" | "month" | "year";
2390
+ intervalCount?: number;
2391
+ metadata?: any;
2392
+ nickname?: string;
2393
+ productId: string;
2394
+ stripePriceId: string;
2395
+ stripeProductId: string;
2396
+ type: "one_time" | "recurring";
2397
+ unitAmount: number;
2398
+ }>;
2399
+ pageStatus?: "SplitRecommended" | "SplitRequired" | null;
2400
+ splitCursor?: string | null;
2401
+ },
2402
+ Name
2403
+ >;
2404
+ paginateProducts: FunctionReference<
2405
+ "query",
2406
+ "internal",
2407
+ {
2408
+ accountId?: string;
2409
+ active?: boolean;
2410
+ paginationOpts: {
2411
+ cursor: string | null;
2412
+ endCursor?: string | null;
2413
+ id?: number;
2414
+ maximumBytesRead?: number;
2415
+ maximumRowsRead?: number;
2416
+ numItems: number;
2417
+ };
2418
+ },
2419
+ {
2420
+ continueCursor: string;
2421
+ isDone: boolean;
2422
+ page: Array<{
2423
+ _creationTime: number;
2424
+ _id: string;
2425
+ accountId?: string;
2426
+ active: boolean;
2427
+ description?: string;
2428
+ metadata?: any;
2429
+ name: string;
2430
+ stripeProductId: string;
2431
+ }>;
2432
+ pageStatus?: "SplitRecommended" | "SplitRequired" | null;
2433
+ splitCursor?: string | null;
2434
+ },
2435
+ Name
2436
+ >;
2437
+ };
2438
+ };
2439
+ refundHistory: {
2440
+ queries: {
2441
+ paginateRefunds: FunctionReference<
2442
+ "query",
2443
+ "internal",
2444
+ {
2445
+ accountId?: string;
2446
+ paginationOpts: {
2447
+ cursor: string | null;
2448
+ endCursor?: string | null;
2449
+ id?: number;
2450
+ maximumBytesRead?: number;
2451
+ maximumRowsRead?: number;
2452
+ numItems: number;
2453
+ };
2454
+ status?:
2455
+ | "pending"
2456
+ | "requires_action"
2457
+ | "succeeded"
2458
+ | "failed"
2459
+ | "canceled";
2460
+ stripePaymentIntentId?: string;
2461
+ },
2462
+ {
2463
+ continueCursor: string;
2464
+ isDone: boolean;
2465
+ page: Array<{
2466
+ _creationTime: number;
2467
+ _id: string;
2468
+ accountId?: string;
2469
+ amount: number;
2470
+ currency: string;
2471
+ failureReason?: string;
2472
+ metadata?: any;
2473
+ reason?:
2474
+ | "duplicate"
2475
+ | "fraudulent"
2476
+ | "requested_by_customer"
2477
+ | "expired_uncaptured_charge";
2478
+ status:
2479
+ | "pending"
2480
+ | "requires_action"
2481
+ | "succeeded"
2482
+ | "failed"
2483
+ | "canceled";
2484
+ stripeChargeId?: string;
2485
+ stripePaymentIntentId?: string;
2486
+ stripeRefundId: string;
2487
+ }>;
2488
+ pageStatus?: "SplitRecommended" | "SplitRequired" | null;
2489
+ splitCursor?: string | null;
2490
+ },
2491
+ Name
2492
+ >;
2236
2493
  };
2237
2494
  };
2238
2495
  settlement: {
@@ -1,7 +1,7 @@
1
1
  import { v } from "convex/values";
2
2
 
3
3
  import type { Doc, Id } from "../_generated/dataModel";
4
- import { mutation } from "../_generated/server";
4
+ import { mutation } from "../earnings/triggers.js";
5
5
  import { feeRoutingFields } from "../lib/fees";
6
6
  import { computeReversalSlices, deriveReversalState } from "../lib/reversals";
7
7
  import { paymentSeller } from "../lib/paymentSeller";
@@ -121,6 +121,8 @@ export const upsertPayout = mutation({
121
121
  status: payoutStatusValidator,
122
122
  arrivalDate: v.optional(v.string()),
123
123
  method: v.optional(v.string()),
124
+ failureCode: v.optional(v.string()),
125
+ failureMessage: v.optional(v.string()),
124
126
  metadata: v.optional(v.any()),
125
127
  },
126
128
  returns: v.null(),
@@ -133,7 +135,11 @@ export const upsertPayout = mutation({
133
135
  .first();
134
136
 
135
137
  if (existing) {
136
- await ctx.db.patch("payouts", existing._id, args);
138
+ await ctx.db.patch("payouts", existing._id, {
139
+ ...args,
140
+ failureCode: args.failureCode,
141
+ failureMessage: args.failureMessage,
142
+ });
137
143
  } else {
138
144
  await ctx.db.insert("payouts", args);
139
145
  }
@@ -142,9 +148,7 @@ export const upsertPayout = mutation({
142
148
  },
143
149
  });
144
150
 
145
- // =============================================================================
146
151
  // REFUND MUTATIONS
147
- // =============================================================================
148
152
 
149
153
  export const upsertRefund = mutation({
150
154
  args: refundFields,
@@ -283,9 +287,7 @@ export const recordPaymentFeeRefund = mutation({
283
287
  },
284
288
  });
285
289
 
286
- // =============================================================================
287
290
  // DISPUTE MUTATIONS
288
- // =============================================================================
289
291
 
290
292
  export const upsertDispute = mutation({
291
293
  args: disputeFields,
@@ -311,9 +313,7 @@ export const upsertDispute = mutation({
311
313
  },
312
314
  });
313
315
 
314
- // =============================================================================
315
316
  // TRANSFER MUTATIONS (ledger — BTS-12)
316
- // =============================================================================
317
317
 
318
318
  export const upsertTransfer = mutation({
319
319
  args: transferFields,