@fantastic.dev/better-stripe 0.16.0 → 0.17.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 (57) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/README.md +60 -9
  3. package/dist/client/connect/refunds.d.ts +12 -0
  4. package/dist/client/connect/refunds.d.ts.map +1 -1
  5. package/dist/client/connect/refunds.js +8 -0
  6. package/dist/client/connect/refunds.js.map +1 -1
  7. package/dist/client/index.d.ts +5 -7
  8. package/dist/client/index.d.ts.map +1 -1
  9. package/dist/client/index.js +3 -0
  10. package/dist/client/index.js.map +1 -1
  11. package/dist/component/_generated/component.d.ts +36 -0
  12. package/dist/component/_generated/component.d.ts.map +1 -1
  13. package/dist/component/connect/queries.d.ts.map +1 -1
  14. package/dist/component/connect/queries.js +2 -1
  15. package/dist/component/connect/queries.js.map +1 -1
  16. package/dist/component/connect/schema.d.ts +2 -0
  17. package/dist/component/connect/schema.d.ts.map +1 -1
  18. package/dist/component/connect/schema.js +9 -0
  19. package/dist/component/connect/schema.js.map +1 -1
  20. package/dist/component/earnings/arithmetic.d.ts +3 -0
  21. package/dist/component/earnings/arithmetic.d.ts.map +1 -0
  22. package/dist/component/earnings/arithmetic.js +11 -0
  23. package/dist/component/earnings/arithmetic.js.map +1 -0
  24. package/dist/component/earnings/reads.d.ts.map +1 -1
  25. package/dist/component/earnings/reads.js +6 -0
  26. package/dist/component/earnings/reads.js.map +1 -1
  27. package/dist/component/earnings/triggers.d.ts +4 -0
  28. package/dist/component/earnings/triggers.d.ts.map +1 -1
  29. package/dist/component/earnings/triggers.js +17 -12
  30. package/dist/component/earnings/triggers.js.map +1 -1
  31. package/dist/component/refundHistory/queries.d.ts +28 -0
  32. package/dist/component/refundHistory/queries.d.ts.map +1 -0
  33. package/dist/component/refundHistory/queries.js +59 -0
  34. package/dist/component/refundHistory/queries.js.map +1 -0
  35. package/dist/component/schema.d.ts +2 -0
  36. package/dist/react/workflows/Costs.d.ts +1 -0
  37. package/dist/react/workflows/Costs.d.ts.map +1 -1
  38. package/dist/react/workflows/Costs.js +7 -3
  39. package/dist/react/workflows/Costs.js.map +1 -1
  40. package/docs/react-workflows.md +39 -3
  41. package/docs/read-contracts.md +13 -0
  42. package/package.json +1 -1
  43. package/src/client/connect/refunds.ts +28 -0
  44. package/src/client/index.ts +6 -7
  45. package/src/client/refund-history.test.ts +67 -0
  46. package/src/component/_generated/api.ts +4 -0
  47. package/src/component/_generated/component.ts +56 -0
  48. package/src/component/connect/queries.ts +2 -1
  49. package/src/component/connect/schema.ts +9 -0
  50. package/src/component/earnings/arithmetic.ts +10 -0
  51. package/src/component/earnings/reads.ts +6 -0
  52. package/src/component/earnings/triggers.ts +18 -13
  53. package/src/component/refund-history.test.ts +198 -0
  54. package/src/component/refundHistory/queries.ts +99 -0
  55. package/src/component/summary-arithmetic.test.ts +246 -0
  56. package/src/react/workflows/Costs.test.tsx +21 -0
  57. package/src/react/workflows/Costs.tsx +9 -3
@@ -1 +1 @@
1
- {"version":3,"file":"triggers.js","sourceRoot":"","sources":["../../../src/component/earnings/triggers.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"triggers.js","sourceRoot":"","sources":["../../../src/component/earnings/triggers.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ /** Host-authorized scopes are conjunctive; use the package React pagination binding. */
2
+ export declare const paginateRefunds: import("convex/server").RegisteredQuery<"public", {
3
+ accountId?: string | undefined;
4
+ paginationOpts: {
5
+ id?: number;
6
+ endCursor?: string | null;
7
+ maximumRowsRead?: number;
8
+ maximumBytesRead?: number;
9
+ numItems: number;
10
+ cursor: string | null;
11
+ };
12
+ status?: "canceled" | "failed" | "pending" | "requires_action" | "succeeded" | undefined;
13
+ stripePaymentIntentId?: string | undefined;
14
+ }, Promise<import("convex/server").PaginationResult<{
15
+ _creationTime: number;
16
+ _id: import("convex/values").GenericId<"refunds">;
17
+ accountId?: string | undefined;
18
+ amount: number;
19
+ currency: string;
20
+ failureReason?: string | undefined;
21
+ metadata?: any;
22
+ reason?: "duplicate" | "expired_uncaptured_charge" | "fraudulent" | "requested_by_customer" | undefined;
23
+ status: "canceled" | "failed" | "pending" | "requires_action" | "succeeded";
24
+ stripeChargeId?: string | undefined;
25
+ stripePaymentIntentId?: string | undefined;
26
+ stripeRefundId: string;
27
+ }>>>;
28
+ //# sourceMappingURL=queries.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queries.d.ts","sourceRoot":"","sources":["../../../src/component/refundHistory/queries.ts"],"names":[],"mappings":"AAeA,wFAAwF;AACxF,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;IA0B1B,CAAC"}
@@ -0,0 +1,59 @@
1
+ import { paginationOptsValidator, paginationResultValidator, } from "convex/server";
2
+ import { v } from "convex/values";
3
+ import { paginator } from "convex-helpers/server/pagination";
4
+ import { query } from "../_generated/server.js";
5
+ import schema from "../schema.js";
6
+ import { refundDocValidator, refundStatusValidator, } from "../connect/validators.js";
7
+ /** Host-authorized scopes are conjunctive; use the package React pagination binding. */
8
+ export const paginateRefunds = query({
9
+ args: {
10
+ accountId: v.optional(v.string()),
11
+ stripePaymentIntentId: v.optional(v.string()),
12
+ status: v.optional(refundStatusValidator),
13
+ paginationOpts: paginationOptsValidator,
14
+ },
15
+ returns: paginationResultValidator(refundDocValidator),
16
+ handler: (ctx, args) => {
17
+ const { paginationOpts } = args;
18
+ if (!Number.isSafeInteger(paginationOpts.numItems) ||
19
+ paginationOpts.numItems < 1 ||
20
+ paginationOpts.numItems > 100)
21
+ throw new Error("Refund history page size must be an integer from 1 to 100");
22
+ return scopedRefunds(ctx, args)
23
+ .order("desc")
24
+ .paginate({
25
+ ...paginationOpts,
26
+ maximumRowsRead: 200,
27
+ maximumBytesRead: 1_000_000,
28
+ });
29
+ },
30
+ });
31
+ function scopedRefunds(ctx, args) {
32
+ const { accountId, stripePaymentIntentId, status } = args;
33
+ const refunds = paginator(ctx.db, schema).query("refunds");
34
+ if (accountId !== undefined &&
35
+ stripePaymentIntentId !== undefined &&
36
+ status === undefined)
37
+ return refunds.withIndex("by_account_id_and_stripe_payment_intent_id", (q) => q
38
+ .eq("accountId", accountId)
39
+ .eq("stripePaymentIntentId", stripePaymentIntentId));
40
+ if (accountId !== undefined &&
41
+ stripePaymentIntentId !== undefined &&
42
+ status !== undefined)
43
+ return refunds.withIndex("by_account_id_and_stripe_payment_intent_id_and_status", (q) => q
44
+ .eq("accountId", accountId)
45
+ .eq("stripePaymentIntentId", stripePaymentIntentId)
46
+ .eq("status", status));
47
+ if (accountId !== undefined && status !== undefined)
48
+ return refunds.withIndex("by_account_id_and_status", (q) => q.eq("accountId", accountId).eq("status", status));
49
+ if (stripePaymentIntentId !== undefined && status !== undefined)
50
+ return refunds.withIndex("by_payment_intent_id_and_status", (q) => q.eq("stripePaymentIntentId", stripePaymentIntentId).eq("status", status));
51
+ if (accountId !== undefined)
52
+ return refunds.withIndex("by_account_id", (q) => q.eq("accountId", accountId));
53
+ if (stripePaymentIntentId !== undefined)
54
+ return refunds.withIndex("by_stripe_payment_intent_id", (q) => q.eq("stripePaymentIntentId", stripePaymentIntentId));
55
+ if (status !== undefined)
56
+ return refunds.withIndex("by_status", (q) => q.eq("status", status));
57
+ return refunds;
58
+ }
59
+ //# sourceMappingURL=queries.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queries.js","sourceRoot":"","sources":["../../../src/component/refundHistory/queries.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,uBAAuB,EACvB,yBAAyB,GAC1B,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,CAAC,EAAE,MAAM,eAAe,CAAC;AAClC,OAAO,EAAE,SAAS,EAAE,MAAM,kCAAkC,CAAC;AAE7D,OAAO,EAAE,KAAK,EAAiB,MAAM,yBAAyB,CAAC;AAC/D,OAAO,MAAM,MAAM,cAAc,CAAC;AAClC,OAAO,EACL,kBAAkB,EAClB,qBAAqB,GAEtB,MAAM,0BAA0B,CAAC;AAElC,wFAAwF;AACxF,MAAM,CAAC,MAAM,eAAe,GAAG,KAAK,CAAC;IACnC,IAAI,EAAE;QACJ,SAAS,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;QACjC,qBAAqB,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;QAC7C,MAAM,EAAE,CAAC,CAAC,QAAQ,CAAC,qBAAqB,CAAC;QACzC,cAAc,EAAE,uBAAuB;KACxC;IACD,OAAO,EAAE,yBAAyB,CAAC,kBAAkB,CAAC;IACtD,OAAO,EAAE,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE;QACrB,MAAM,EAAE,cAAc,EAAE,GAAG,IAAI,CAAC;QAChC,IACE,CAAC,MAAM,CAAC,aAAa,CAAC,cAAc,CAAC,QAAQ,CAAC;YAC9C,cAAc,CAAC,QAAQ,GAAG,CAAC;YAC3B,cAAc,CAAC,QAAQ,GAAG,GAAG;YAE7B,MAAM,IAAI,KAAK,CACb,2DAA2D,CAC5D,CAAC;QACJ,OAAO,aAAa,CAAC,GAAG,EAAE,IAAI,CAAC;aAC5B,KAAK,CAAC,MAAM,CAAC;aACb,QAAQ,CAAC;YACR,GAAG,cAAc;YACjB,eAAe,EAAE,GAAG;YACpB,gBAAgB,EAAE,SAAS;SAC5B,CAAC,CAAC;IACP,CAAC;CACF,CAAC,CAAC;AAEH,SAAS,aAAa,CACpB,GAAa,EACb,IAIC;IAED,MAAM,EAAE,SAAS,EAAE,qBAAqB,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IAC1D,MAAM,OAAO,GAAG,SAAS,CAAC,GAAG,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;IAC3D,IACE,SAAS,KAAK,SAAS;QACvB,qBAAqB,KAAK,SAAS;QACnC,MAAM,KAAK,SAAS;QAEpB,OAAO,OAAO,CAAC,SAAS,CACtB,4CAA4C,EAC5C,CAAC,CAAC,EAAE,EAAE,CACJ,CAAC;aACE,EAAE,CAAC,WAAW,EAAE,SAAS,CAAC;aAC1B,EAAE,CAAC,uBAAuB,EAAE,qBAAqB,CAAC,CACxD,CAAC;IACJ,IACE,SAAS,KAAK,SAAS;QACvB,qBAAqB,KAAK,SAAS;QACnC,MAAM,KAAK,SAAS;QAEpB,OAAO,OAAO,CAAC,SAAS,CACtB,uDAAuD,EACvD,CAAC,CAAC,EAAE,EAAE,CACJ,CAAC;aACE,EAAE,CAAC,WAAW,EAAE,SAAS,CAAC;aAC1B,EAAE,CAAC,uBAAuB,EAAE,qBAAqB,CAAC;aAClD,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC,CAC1B,CAAC;IACJ,IAAI,SAAS,KAAK,SAAS,IAAI,MAAM,KAAK,SAAS;QACjD,OAAO,OAAO,CAAC,SAAS,CAAC,0BAA0B,EAAE,CAAC,CAAC,EAAE,EAAE,CACzD,CAAC,CAAC,EAAE,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC,CAClD,CAAC;IACJ,IAAI,qBAAqB,KAAK,SAAS,IAAI,MAAM,KAAK,SAAS;QAC7D,OAAO,OAAO,CAAC,SAAS,CAAC,iCAAiC,EAAE,CAAC,CAAC,EAAE,EAAE,CAChE,CAAC,CAAC,EAAE,CAAC,uBAAuB,EAAE,qBAAqB,CAAC,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC,CAC1E,CAAC;IACJ,IAAI,SAAS,KAAK,SAAS;QACzB,OAAO,OAAO,CAAC,SAAS,CAAC,eAAe,EAAE,CAAC,CAAC,EAAE,EAAE,CAC9C,CAAC,CAAC,EAAE,CAAC,WAAW,EAAE,SAAS,CAAC,CAC7B,CAAC;IACJ,IAAI,qBAAqB,KAAK,SAAS;QACrC,OAAO,OAAO,CAAC,SAAS,CAAC,6BAA6B,EAAE,CAAC,CAAC,EAAE,EAAE,CAC5D,CAAC,CAAC,EAAE,CAAC,uBAAuB,EAAE,qBAAqB,CAAC,CACrD,CAAC;IACJ,IAAI,MAAM,KAAK,SAAS;QACtB,OAAO,OAAO,CAAC,SAAS,CAAC,WAAW,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC;IACvE,OAAO,OAAO,CAAC;AACjB,CAAC"}
@@ -674,6 +674,8 @@ declare const _default: import("convex/server").SchemaDefinition<{
674
674
  }, "required", "accountId" | "amount" | "currency" | "failureReason" | "metadata" | "reason" | "status" | "stripeChargeId" | "stripePaymentIntentId" | "stripeRefundId" | `metadata.${string}`>, {
675
675
  by_account_id: ["accountId", "_creationTime"];
676
676
  by_account_id_and_status: ["accountId", "status", "_creationTime"];
677
+ by_account_id_and_stripe_payment_intent_id: ["accountId", "stripePaymentIntentId", "_creationTime"];
678
+ by_account_id_and_stripe_payment_intent_id_and_status: ["accountId", "stripePaymentIntentId", "status", "_creationTime"];
677
679
  by_payment_intent_id_and_status: ["stripePaymentIntentId", "status", "_creationTime"];
678
680
  by_status: ["status", "_creationTime"];
679
681
  by_stripe_payment_intent_id: ["stripePaymentIntentId", "_creationTime"];
@@ -8,6 +8,7 @@ export type CostRecoveryRow = {
8
8
  amountDue: number;
9
9
  collectedAmount: number;
10
10
  invoicedAmount: number;
11
+ reservedAmount?: number;
11
12
  outstanding: number;
12
13
  currency: string;
13
14
  };
@@ -1 +1 @@
1
- {"version":3,"file":"Costs.d.ts","sourceRoot":"","sources":["../../../src/react/workflows/Costs.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,EAAc,KAAK,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAClE,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,kBAAkB,CAAC;AAEhE,MAAM,MAAM,eAAe,GAAG;IAC5B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,eAAe,EAAE,MAAM,CAAC;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AACF,wBAAgB,YAAY,CAAC,KAAK,EAAE,uBAAuB,CAAC,eAAe,CAAC,+BA0B3E;AACD,MAAM,MAAM,kBAAkB,GAAG;IAC/B,gBAAgB,EAAE,MAAM,CAAC;IACzB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB,CAAC;AACF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,OAAO,EAAE;QAAE,cAAc,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IACvE,SAAS,EAAE,kBAAkB,EAAE,CAAC;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;CACb,CAAC;AACF,MAAM,MAAM,2BAA2B,GAAG;IACxC,IAAI,EAAE,iBAAiB,GAAG,IAAI,GAAG,SAAS,CAAC;IAC3C,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,cAAc,CAAC,kBAAkB,CAAC,EAAE,CAAC;CAC/C,CAAC;AACF,wBAAgB,gBAAgB,CAAC,EAC/B,UAAU,EACV,QAAQ,GACT,EAAE;IACD,UAAU,EAAE,iBAAiB,GAAG,IAAI,GAAG,SAAS,CAAC;IACjD,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,2BAA2B,KAAK,SAAS,CAAC;CAC9D,+BA2DA"}
1
+ {"version":3,"file":"Costs.d.ts","sourceRoot":"","sources":["../../../src/react/workflows/Costs.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,EAAc,KAAK,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAClE,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,kBAAkB,CAAC;AAEhE,MAAM,MAAM,eAAe,GAAG;IAC5B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,eAAe,EAAE,MAAM,CAAC;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AACF,wBAAgB,YAAY,CAAC,KAAK,EAAE,uBAAuB,CAAC,eAAe,CAAC,+BA+B3E;AACD,MAAM,MAAM,kBAAkB,GAAG;IAC/B,gBAAgB,EAAE,MAAM,CAAC;IACzB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB,CAAC;AACF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,OAAO,EAAE;QAAE,cAAc,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IACvE,SAAS,EAAE,kBAAkB,EAAE,CAAC;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;CACb,CAAC;AACF,MAAM,MAAM,2BAA2B,GAAG;IACxC,IAAI,EAAE,iBAAiB,GAAG,IAAI,GAAG,SAAS,CAAC;IAC3C,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,cAAc,CAAC,kBAAkB,CAAC,EAAE,CAAC;CAC/C,CAAC;AACF,wBAAgB,gBAAgB,CAAC,EAC/B,UAAU,EACV,QAAQ,GACT,EAAE;IACD,UAAU,EAAE,iBAAiB,GAAG,IAAI,GAAG,SAAS,CAAC;IACjD,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,2BAA2B,KAAK,SAAS,CAAC;CAC9D,+BA2DA"}
@@ -3,18 +3,22 @@ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-run
3
3
  import { Collection } from "./Collection.js";
4
4
  import { formatPrice } from "../lib/price-helpers.js";
5
5
  export function CostRecovery(props) {
6
+ const reserved = props.rows?.some((row) => row.reservedAmount !== undefined);
6
7
  const columns = [
7
8
  { id: "payment", label: "Payment", cell: (row) => row.paymentIntentId },
8
9
  ...[
9
10
  ["amountDue", "Total cost"],
10
- ["collectedAmount", "Deducted from earnings"],
11
- ["invoicedAmount", "Added to invoice"],
11
+ ["collectedAmount", reserved ? "Collected" : "Deducted from earnings"],
12
+ [
13
+ reserved ? "reservedAmount" : "invoicedAmount",
14
+ reserved ? "Reserved" : "Added to invoice",
15
+ ],
12
16
  ["outstanding", "Outstanding"],
13
17
  ].map(([field, label]) => ({
14
18
  id: field,
15
19
  label,
16
20
  align: "end",
17
- cell: (row) => formatPrice(row[field], row.currency),
21
+ cell: (row) => formatPrice(row[field] ?? row.invoicedAmount, row.currency),
18
22
  })),
19
23
  ];
20
24
  return (_jsx(Collection, { emptyLabel: "No costs yet.", loadingLabel: "Loading costs\u2026", ...props, columns: props.columns ?? columns, getKey: (row) => row._id ?? row.id ?? row.paymentIntentId }));
@@ -1 +1 @@
1
- {"version":3,"file":"Costs.js","sourceRoot":"","sources":["../../../src/react/workflows/Costs.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Costs.js","sourceRoot":"","sources":["../../../src/react/workflows/Costs.tsx"],"names":[],"mappings":"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"}
@@ -391,6 +391,40 @@ Preview grouping performs no reads, writes or provider operations and cannot pro
391
391
  bank delivery or complete-account earnings. Authorize and bound the source read in
392
392
  the host; keep authoritative full-account aggregates separate.
393
393
 
394
+ ### Complete refund history (added after 0.16.0)
395
+
396
+ `BetterStripe.paginateRefunds(ctx, opts)` reads authoritative synchronized component
397
+ refund records. `RefundPageOptions` is exported from the main package entrypoint.
398
+ Pass `paginationOpts: { numItems, cursor }` with an integer page size from 1 to 100
399
+ and `null` for the initial cursor. The result has `page`, `isDone` and
400
+ `continueCursor`; feed the returned cursor into the next request until `isDone`.
401
+ Each request performs one bounded helper-compatible component paginate operation
402
+ in newest-first order. Bind the authorized host query with the package React
403
+ `useComponentPaginatedQuery`, matching the catalog and payout readers. Pinned
404
+ ranges may grow beyond the requested page size; reads cap at 200 rows or 1 MB
405
+ and return split hints for the hook. Existing `listRefunds` retains its
406
+ capped-array compatibility.
407
+
408
+ The host must authenticate the session and derive an authorized account/payment
409
+ scope before exposing this method through its reactive query. Optional
410
+ `stripeAccountId`, `stripePaymentIntentId` and `status` filters all apply together;
411
+ a mismatched account/payment pair returns no records. Do not expose an unscoped
412
+ reader to ordinary sellers, trust browser-supplied account IDs or treat this
413
+ component API as an authentication boundary.
414
+
415
+ Render returned records with `RefundHistory` or its render prop, retaining their
416
+ original amount, currency, status and charge/payment identifiers. Dojo supplies
417
+ translated Shadcn presentation and its application audit context. Loaded pages
418
+ and the existing 25-row Vite preview are incomplete until pagination finishes;
419
+ neither is a monetary aggregate. Grouped preview amounts remain explicitly
420
+ bounded, and authoritative monetary totals require currency-isolated aggregate
421
+ APIs. This reader performs no Stripe request, refund or ledger write.
422
+
423
+ This method is absent from public 0.16.0. Source acceptance does not publish it.
424
+ Host applications must wait for a separately verified published artifact and
425
+ package adoption before importing it; source merges alone do not satisfy that
426
+ consumer gate.
427
+
394
428
  ## Store-plan pricing editor
395
429
 
396
430
  `PlanPricingEditor` accepts a `plan` with `id`, `name`, `monthlyAmount` in minor
@@ -526,9 +560,11 @@ checking that the response still belongs to the mounted scope. `useOnboarding`
526
560
  uses this lifecycle for both create and continue navigation, including its
527
561
  `window.location.assign` fallback. An old response cannot navigate after unmount
528
562
  or scope replacement. Current requests preserve shared pending locks and errors.
529
- These APIs ship in the release containing the dispute-upload and stale-navigation
530
- implementation PR. Version 0.13.0 does not contain them. Consumers must upgrade
531
- to that release before removing their navigation guard or using the upload API.
563
+ `uploadDisputeEvidence`, `EvidenceUpload` and the onboarding navigation fix shipped
564
+ in [0.14.0](https://github.com/FantasticDevHQ/better-stripe/releases/tag/v0.14.0).
565
+ Version 0.13.0 does not contain them. Consumers must upgrade to
566
+ `@fantastic.dev/better-stripe@0.14.0` or later before using the upload API or relying
567
+ on the package's navigation guard.
532
568
  Production storage, session authorization, styling, translations and extended
533
569
  hosted onboarding verification remain application responsibilities.
534
570
 
@@ -94,6 +94,19 @@ earnings ledger does not determine settlement availability.
94
94
 
95
95
  ### Existing installations
96
96
 
97
+ Summary amounts, counts and derived net amounts must remain safe integers in the
98
+ public Number representation. Checked integer intermediates reject fractional,
99
+ non-finite or unsupported inputs/results before rounding. A rejected transfer,
100
+ payout, reversal or backfill page rolls back its source changes, markers and
101
+ summary updates together. Stored unsafe summary fields also fail closed on reads.
102
+
103
+ These guards prevent new precision loss; they do not repair summaries rounded by
104
+ an earlier release. An affected historical summary needs reconciliation against
105
+ its original records before reuse, even if a later rounded value appears safe.
106
+ The ordinary backfill below skips already-marked records and cannot repair that
107
+ case. Do not treat a successful backfill or a current safe-looking Number as
108
+ proof that previously unsupported arithmetic was exact.
109
+
97
110
  After deploying the optional marker fields and summary table, invoke
98
111
  `components.betterStripe.earnings.mutations.backfillCurrencyTotals` from a trusted
99
112
  server migration. Run separately for `kind: "earnings"` and `kind: "payouts"`,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fantastic.dev/better-stripe",
3
- "version": "0.16.0",
3
+ "version": "0.17.1",
4
4
  "description": "A Convex component for Stripe V2 Accounts API integration.",
5
5
  "keywords": [
6
6
  "stripe",
@@ -1,4 +1,5 @@
1
1
  import type Stripe from "stripe";
2
+ import type { PaginationOptions, PaginationResult } from "convex/server";
2
3
 
3
4
  import type { RefundStatus } from "../../component/connect/validators.js";
4
5
  import { throwStripeError } from "../errors.js";
@@ -12,6 +13,33 @@ import { type RefundActor, isRefundAuthorized } from "./refundActor.js";
12
13
 
13
14
  export type { RefundActor } from "./refundActor.js";
14
15
 
16
+ export type RefundListOptions = {
17
+ stripeAccountId?: string;
18
+ stripePaymentIntentId?: string;
19
+ status?: RefundStatus;
20
+ limit?: number;
21
+ };
22
+
23
+ export type RefundPageOptions = Omit<RefundListOptions, "limit"> & {
24
+ paginationOpts: PaginationOptions;
25
+ };
26
+
27
+ /** The host must authenticate/authorize scopes before exposing this reactive reader. */
28
+ export async function paginateRefunds(
29
+ component: Component,
30
+ ctx: RunCtx,
31
+ opts: RefundPageOptions,
32
+ ): Promise<PaginationResult<StripeComponentRefund>> {
33
+ const { stripeAccountId, ...rest } = opts;
34
+ return await ctx.runQuery(
35
+ componentRef(component, "refundHistory/queries/paginateRefunds"),
36
+ {
37
+ ...rest,
38
+ ...(stripeAccountId !== undefined ? { accountId: stripeAccountId } : {}),
39
+ },
40
+ );
41
+ }
42
+
15
43
  // =============================================================================
16
44
  // Refund methods
17
45
  // =============================================================================
@@ -79,7 +79,6 @@ import type { ComponentApi } from "../component/_generated/component.js";
79
79
  import type {
80
80
  DisputeStatus,
81
81
  PayoutStatus,
82
- RefundStatus,
83
82
  } from "../component/connect/validators.js";
84
83
  import type { SplitRecipient } from "../component/lib/fees.js";
85
84
  import * as checkoutImpl from "./billing/checkout.js";
@@ -89,6 +88,7 @@ import * as disputesImpl from "./connect/disputes.js";
89
88
  import * as paymentMethodsImpl from "./connect/paymentMethods.js";
90
89
  import * as payoutsImpl from "./connect/payouts.js";
91
90
  import * as refundsImpl from "./connect/refunds.js";
91
+ export type { RefundPageOptions } from "./connect/refunds.js";
92
92
  import * as transfersImpl from "./connect/transfers.js";
93
93
  import * as accountLinksImpl from "./core/accountLinks.js";
94
94
  import * as accountsImpl from "./core/accounts.js";
@@ -1360,16 +1360,15 @@ export class BetterStripe extends ReadContractClient {
1360
1360
 
1361
1361
  async listRefunds(
1362
1362
  ctx: RunCtx,
1363
- opts?: {
1364
- stripeAccountId?: string;
1365
- stripePaymentIntentId?: string;
1366
- status?: RefundStatus;
1367
- limit?: number;
1368
- },
1363
+ opts?: refundsImpl.RefundListOptions,
1369
1364
  ): Promise<StripeComponentRefund[]> {
1370
1365
  return refundsImpl.listRefunds(this.component, ctx, opts);
1371
1366
  }
1372
1367
 
1368
+ paginateRefunds(ctx: RunCtx, opts: refundsImpl.RefundPageOptions) {
1369
+ return refundsImpl.paginateRefunds(this.component, ctx, opts);
1370
+ }
1371
+
1373
1372
  // DISPUTE METHODS
1374
1373
 
1375
1374
  async getDisputeByStripeId(
@@ -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
+ });
@@ -24,6 +24,7 @@ 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_arithmetic from "../earnings/arithmetic.js";
27
28
  import type * as earnings_legacyReads from "../earnings/legacyReads.js";
28
29
  import type * as earnings_mutations from "../earnings/mutations.js";
29
30
  import type * as earnings_reads from "../earnings/reads.js";
@@ -36,6 +37,7 @@ import type * as lib_stripeFactory from "../lib/stripeFactory.js";
36
37
  import type * as products_mutations from "../products/mutations.js";
37
38
  import type * as products_queries from "../products/queries.js";
38
39
  import type * as products_validators from "../products/validators.js";
40
+ import type * as refundHistory_queries from "../refundHistory/queries.js";
39
41
  import type * as settlement_mutations from "../settlement/mutations.js";
40
42
  import type * as settlement_queries from "../settlement/queries.js";
41
43
  import type * as webhooks_mutations from "../webhooks/mutations.js";
@@ -66,6 +68,7 @@ const fullApi: ApiFromModules<{
66
68
  "costRecovery/mutations": typeof costRecovery_mutations;
67
69
  "costRecovery/queries": typeof costRecovery_queries;
68
70
  "costRecovery/reservations": typeof costRecovery_reservations;
71
+ "earnings/arithmetic": typeof earnings_arithmetic;
69
72
  "earnings/legacyReads": typeof earnings_legacyReads;
70
73
  "earnings/mutations": typeof earnings_mutations;
71
74
  "earnings/reads": typeof earnings_reads;
@@ -78,6 +81,7 @@ const fullApi: ApiFromModules<{
78
81
  "products/mutations": typeof products_mutations;
79
82
  "products/queries": typeof products_queries;
80
83
  "products/validators": typeof products_validators;
84
+ "refundHistory/queries": typeof refundHistory_queries;
81
85
  "settlement/mutations": typeof settlement_mutations;
82
86
  "settlement/queries": typeof settlement_queries;
83
87
  "webhooks/mutations": typeof webhooks_mutations;
@@ -2436,6 +2436,62 @@ export type ComponentApi<Name extends string | undefined = string | undefined> =
2436
2436
  >;
2437
2437
  };
2438
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
+ >;
2493
+ };
2494
+ };
2439
2495
  settlement: {
2440
2496
  mutations: {
2441
2497
  claimCommissionInvoice: FunctionReference<
@@ -3,6 +3,7 @@ import {
3
3
  getAccountPayouts as getAccountPayoutsLegacy,
4
4
  } from "../earnings/legacyReads.js";
5
5
  import { currencyTotals, previewSize } from "../earnings/reads.js";
6
+ import { addSummaryAmounts } from "../earnings/arithmetic.js";
6
7
  import { v } from "convex/values";
7
8
  import { paginator } from "convex-helpers/server/pagination";
8
9
  import schema from "../schema.js";
@@ -557,7 +558,7 @@ export const getAccountEarningsByCurrency = query({
557
558
  currency: r.currency,
558
559
  gross: r.gross,
559
560
  reversed: r.reversed,
560
- net: r.gross - r.reversed,
561
+ net: addSummaryAmounts(r.gross, -r.reversed),
561
562
  transferCount: r.count,
562
563
  })),
563
564
  transfers,
@@ -54,6 +54,15 @@ export const refundsTable = defineTable(refundFields)
54
54
  .index("by_account_id", ["accountId"])
55
55
  .index("by_status", ["status"])
56
56
  .index("by_account_id_and_status", ["accountId", "status"])
57
+ .index("by_account_id_and_stripe_payment_intent_id", [
58
+ "accountId",
59
+ "stripePaymentIntentId",
60
+ ])
61
+ .index("by_account_id_and_stripe_payment_intent_id_and_status", [
62
+ "accountId",
63
+ "stripePaymentIntentId",
64
+ "status",
65
+ ])
57
66
  .index("by_payment_intent_id_and_status", [
58
67
  "stripePaymentIntentId",
59
68
  "status",
@@ -0,0 +1,10 @@
1
+ /** Check exact integer arithmetic before converting back to the public Number representation. */
2
+ export function addSummaryAmounts(left: number, right: number): number {
3
+ if (!Number.isSafeInteger(left) || !Number.isSafeInteger(right))
4
+ throw new Error("Currency totals require safe integer amounts");
5
+ const result = BigInt(left) + BigInt(right);
6
+ const limit = BigInt(Number.MAX_SAFE_INTEGER);
7
+ if (result > limit || result < -limit)
8
+ throw new Error("Currency totals exceed supported safe integer bounds");
9
+ return Number(result);
10
+ }
@@ -1,4 +1,5 @@
1
1
  import type { QueryCtx } from "../_generated/server.js";
2
+ import { addSummaryAmounts } from "./arithmetic.js";
2
3
  export function previewSize(value = 50) {
3
4
  if (!Number.isInteger(value) || value < 0 || value > 100)
4
5
  throw new Error("Preview size must be an integer from 0 to 100");
@@ -37,5 +38,10 @@ export async function currencyTotals(
37
38
  .take(501);
38
39
  if (rows.length > 500)
39
40
  throw new Error("Account exceeds supported currency count");
41
+ for (const row of rows) {
42
+ for (const value of [row.gross, row.reversed, row.paidOut, row.count])
43
+ addSummaryAmounts(value, 0);
44
+ addSummaryAmounts(row.gross, -row.reversed);
45
+ }
40
46
  return rows;
41
47
  }
@@ -4,6 +4,7 @@ import {
4
4
  customMutation,
5
5
  } from "convex-helpers/server/customFunctions";
6
6
  import type { DataModel } from "../_generated/dataModel.js";
7
+ import { addSummaryAmounts } from "./arithmetic.js";
7
8
  import {
8
9
  mutation as rawMutation,
9
10
  type MutationCtx,
@@ -21,7 +22,7 @@ async function adjust(
21
22
  ctx: MutationCtx,
22
23
  kind: "earnings" | "payouts",
23
24
  value: Contribution,
24
- sign: number,
25
+ sign: 1 | -1,
25
26
  ) {
26
27
  const row = await ctx.db
27
28
  .query("currencyTotals")
@@ -33,11 +34,12 @@ async function adjust(
33
34
  )
34
35
  .unique();
35
36
  const totals = {
36
- gross: (row?.gross ?? 0) + sign * value.gross,
37
- reversed: (row?.reversed ?? 0) + sign * value.reversed,
38
- paidOut: (row?.paidOut ?? 0) + sign * value.paidOut,
39
- count: (row?.count ?? 0) + sign * value.count,
37
+ gross: addSummaryAmounts(row?.gross ?? 0, sign * value.gross),
38
+ reversed: addSummaryAmounts(row?.reversed ?? 0, sign * value.reversed),
39
+ paidOut: addSummaryAmounts(row?.paidOut ?? 0, sign * value.paidOut),
40
+ count: addSummaryAmounts(row?.count ?? 0, sign * value.count),
40
41
  };
42
+ addSummaryAmounts(totals.gross, -totals.reversed);
41
43
  if (row) {
42
44
  if (totals.count === 0) await ctx.db.delete("currencyTotals", row._id);
43
45
  else await ctx.db.patch("currencyTotals", row._id, totals);
@@ -72,14 +74,17 @@ triggers.register("transfers", async (ctx, change) => {
72
74
  triggers.register("payouts", async (ctx, change) => {
73
75
  const contribution = (
74
76
  row: NonNullable<typeof change.newDoc>,
75
- ): Contribution => ({
76
- accountId: row.accountId,
77
- currency: row.currency,
78
- gross: 0,
79
- reversed: 0,
80
- paidOut: row.status === "paid" ? row.amount : 0,
81
- count: 1,
82
- });
77
+ ): Contribution => {
78
+ const amount = addSummaryAmounts(row.amount, 0);
79
+ return {
80
+ accountId: row.accountId,
81
+ currency: row.currency,
82
+ gross: 0,
83
+ reversed: 0,
84
+ paidOut: row.status === "paid" ? amount : 0,
85
+ count: 1,
86
+ };
87
+ };
83
88
  if (change.oldDoc?.totalsRecorded)
84
89
  await adjust(ctx, "payouts", contribution(change.oldDoc), -1);
85
90
  if (change.newDoc) {