@rdlabo/workers-hono-kit 0.6.14 → 0.6.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -53,6 +53,8 @@ export { extractStripeFailureReason, stripeFailureMessageJa, serializePaymentFai
53
53
  export type { StripeFailureReason, PaymentFailureSource, PaymentFailureRecord, PaymentFailureReason, IapFailureReason, PaymentDeclinedBody, } from './stripe/failure.js';
54
54
  export { classifyStripeReconcile } from './stripe/reconcile.js';
55
55
  export type { StripeReconcileAction } from './stripe/reconcile.js';
56
+ export { assertStripeCustomerUpdated, buildStripeReconcilePlan, stripePaymentIntent, STRIPE_RECONCILE_INVOICE_EXPAND, } from './stripe/subscription.js';
57
+ export type { StripeReconcilePaymentRow, StripeReconcilePlan } from './stripe/subscription.js';
56
58
  export { paymentFailureMessageJa, iapFailureKey, UNRESOLVED_PAYMENT_STATUSES } from './payment/failure.js';
57
59
  export type { PaymentFailureStatus, PaymentFailureType } from './payment/failure.js';
58
60
  export { classifyAppleRenewal, verifyAppleReceipt } from './iap/apple.js';
package/dist/index.js CHANGED
@@ -39,6 +39,7 @@ export { KVCache } from './cache/kv-cache.js';
39
39
  export { createStripeClient, verifyStripeWebhook } from './stripe/client.js';
40
40
  export { extractStripeFailureReason, stripeFailureMessageJa, serializePaymentFailure, serializeIapFailureReason, parsePaymentFailure, PaymentDeclinedError, toPaymentDeclinedError, } from './stripe/failure.js';
41
41
  export { classifyStripeReconcile } from './stripe/reconcile.js';
42
+ export { assertStripeCustomerUpdated, buildStripeReconcilePlan, stripePaymentIntent, STRIPE_RECONCILE_INVOICE_EXPAND, } from './stripe/subscription.js';
42
43
  // payment (provider-agnostic; web-standard only). reopenGuardedPaymentFailedSet is drizzle-based → './db'.
43
44
  export { paymentFailureMessageJa, iapFailureKey, UNRESOLVED_PAYMENT_STATUSES } from './payment/failure.js';
44
45
  // in-app purchase (Apple / Google)
@@ -0,0 +1,32 @@
1
+ import type Stripe from 'stripe';
2
+ import type { StripeReconcileAction } from './reconcile.js';
3
+ export declare const STRIPE_RECONCILE_INVOICE_EXPAND: readonly ["payments.data.payment.payment_intent", "customer"];
4
+ export interface StripeReconcilePaymentRow<TDate = Date> {
5
+ customerId: string;
6
+ recursionsId: string;
7
+ status: string;
8
+ detail: string;
9
+ limitAt: TDate;
10
+ createdAt: TDate;
11
+ }
12
+ export interface StripeReconcilePlan<TDate = Date> {
13
+ action: StripeReconcileAction;
14
+ paymentIntent: Stripe.PaymentIntent | null;
15
+ payment: StripeReconcilePaymentRow<TDate> | null;
16
+ }
17
+ export declare function stripePaymentIntent(invoice: Stripe.Invoice): Stripe.PaymentIntent | null;
18
+ export declare function buildStripeReconcilePlan<TDate = Date>(options: {
19
+ subscription: Stripe.Subscription;
20
+ invoice: Stripe.Invoice;
21
+ customerId: string;
22
+ formatDate?: (value: Date) => TDate;
23
+ }): StripeReconcilePlan<TDate>;
24
+ export declare function assertStripeCustomerUpdated(options: {
25
+ productId: string;
26
+ customerId: string;
27
+ subscriptionId: string;
28
+ updateCustomer: (receipt: string, productId: string, customerId: string) => Promise<number | {
29
+ affected: number;
30
+ }>;
31
+ countCustomer: (productId: string, customerId: string) => Promise<number>;
32
+ }): Promise<void>;
@@ -0,0 +1,54 @@
1
+ import { classifyStripeReconcile } from './reconcile.js';
2
+ export const STRIPE_RECONCILE_INVOICE_EXPAND = ['payments.data.payment.payment_intent', 'customer'];
3
+ export function stripePaymentIntent(invoice) {
4
+ const payment = invoice.payments?.data[0]?.payment;
5
+ // Stripe's generated type treats data[0] as present, but genuine trials return an empty payments array.
6
+ const paymentIntent = payment?.type === 'payment_intent' ? payment.payment_intent : null;
7
+ return typeof paymentIntent === 'object' && paymentIntent !== null ? paymentIntent : null;
8
+ }
9
+ export function buildStripeReconcilePlan(options) {
10
+ const { subscription, invoice, customerId } = options;
11
+ const formatDate = options.formatDate ?? ((value) => value);
12
+ const paymentIntent = stripePaymentIntent(invoice);
13
+ const action = classifyStripeReconcile({ ...subscription, latest_invoice: invoice });
14
+ let payment = null;
15
+ if (action === 'trial' || paymentIntent) {
16
+ const period = subscription.items.data.at(0);
17
+ if (!period) {
18
+ throw new Error(`Subscription has no items: ${subscription.id}`);
19
+ }
20
+ const dates = {
21
+ limitAt: formatDate(new Date(period.current_period_end * 1000)),
22
+ createdAt: formatDate(new Date(period.current_period_start * 1000)),
23
+ };
24
+ if (action === 'trial') {
25
+ payment = {
26
+ customerId,
27
+ recursionsId: invoice.id,
28
+ status: 'trialing',
29
+ detail: JSON.stringify(invoice),
30
+ ...dates,
31
+ };
32
+ }
33
+ else if (paymentIntent) {
34
+ payment = {
35
+ customerId,
36
+ recursionsId: paymentIntent.id,
37
+ status: paymentIntent.status,
38
+ detail: JSON.stringify(paymentIntent),
39
+ ...dates,
40
+ };
41
+ }
42
+ }
43
+ return { action, paymentIntent, payment };
44
+ }
45
+ export async function assertStripeCustomerUpdated(options) {
46
+ const updated = await options.updateCustomer(options.subscriptionId, options.productId, options.customerId);
47
+ const affected = typeof updated === 'number' ? updated : updated.affected;
48
+ if (affected !== 0) {
49
+ return;
50
+ }
51
+ if ((await options.countCustomer(options.productId, options.customerId)) === 0) {
52
+ throw new Error(`Customer not found: ${options.customerId}`);
53
+ }
54
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rdlabo/workers-hono-kit",
3
- "version": "0.6.14",
3
+ "version": "0.6.17",
4
4
  "private": false,
5
5
  "publishConfig": {
6
6
  "access": "public"