-
Notifications
You must be signed in to change notification settings - Fork 1.2k
/
useDatabase.js
158 lines (147 loc) · 4.92 KB
/
useDatabase.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
import { supabaseAdmin } from './supabase-admin';
import { stripe } from './stripe';
import { toDateTime } from './helpers';
// This entire file should be removed and moved to supabase-admin
// It's not a react hook, so it shouldn't have useDatabase format
// It should also properly catch and throw errors
const upsertProductRecord = async (product) => {
const productData = {
id: product.id,
active: product.active,
name: product.name,
description: product.description,
image: product.images?.[0] ?? null,
metadata: product.metadata
};
const { error } = await supabaseAdmin
.from('products')
.insert([productData], { upsert: true });
if (error) throw error;
console.log(`Product inserted/updated: ${product.id}`);
};
const upsertPriceRecord = async (price) => {
const priceData = {
id: price.id,
product_id: price.product,
active: price.active,
currency: price.currency,
description: price.nickname,
type: price.type,
unit_amount: price.unit_amount,
interval: price.recurring?.interval ?? null,
interval_count: price.recurring?.interval_count ?? null,
trial_period_days: price.recurring?.trial_period_days ?? null,
metadata: price.metadata
};
const { error } = await supabaseAdmin
.from('prices')
.insert([priceData], { upsert: true });
if (error) throw error;
console.log(`Price inserted/updated: ${price.id}`);
};
const createOrRetrieveCustomer = async ({ email, uuid }) => {
const { data, error } = await supabaseAdmin
.from('customers')
.select('stripe_customer_id')
.eq('id', uuid)
.single();
if (error) {
// No customer record found, let's create one.
const customerData = {
metadata: {
supabaseUUID: uuid
}
};
if (email) customerData.email = email;
const customer = await stripe.customers.create(customerData);
// Now insert the customer ID into our Supabase mapping table.
const { error: supabaseError } = await supabaseAdmin
.from('customers')
.insert([{ id: uuid, stripe_customer_id: customer.id }]);
if (supabaseError) throw supabaseError;
console.log(`New customer created and inserted for ${uuid}.`);
return customer.id;
}
if (data) return data.stripe_customer_id;
};
/**
* Copies the billing details from the payment method to the customer object.
*/
const copyBillingDetailsToCustomer = async (uuid, payment_method) => {
const customer = payment_method.customer;
const { name, phone, address } = payment_method.billing_details;
await stripe.customers.update(customer, { name, phone, address });
const { error } = await supabaseAdmin
.from('users')
.update({
billing_address: address,
payment_method: payment_method[payment_method.type]
})
.eq('id', uuid);
if (error) throw error;
};
const manageSubscriptionStatusChange = async (
subscriptionId,
customerId,
createAction = false
) => {
// Get customer's UUID from mapping table.
const {
data: { id: uuid },
error: noCustomerError
} = await supabaseAdmin
.from('customers')
.select('id')
.eq('stripe_customer_id', customerId)
.single();
if (noCustomerError) throw noCustomerError;
const subscription = await stripe.subscriptions.retrieve(subscriptionId, {
expand: ['default_payment_method']
});
// Upsert the latest status of the subscription object.
const subscriptionData = {
id: subscription.id,
user_id: uuid,
metadata: subscription.metadata,
status: subscription.status,
price_id: subscription.items.data[0].price.id,
quantity: subscription.quantity,
cancel_at_period_end: subscription.cancel_at_period_end,
cancel_at: subscription.cancel_at
? toDateTime(subscription.cancel_at)
: null,
canceled_at: subscription.canceled_at
? toDateTime(subscription.canceled_at)
: null,
current_period_start: toDateTime(subscription.current_period_start),
current_period_end: toDateTime(subscription.current_period_end),
created: toDateTime(subscription.created),
ended_at: subscription.ended_at ? toDateTime(subscription.ended_at) : null,
trial_start: subscription.trial_start
? toDateTime(subscription.trial_start)
: null,
trial_end: subscription.trial_end
? toDateTime(subscription.trial_end)
: null
};
const { error } = await supabaseAdmin
.from('subscriptions')
.insert([subscriptionData], { upsert: true });
if (error) throw error;
console.log(
`Inserted/updated subscription [${subscription.id}] for user [${uuid}]`
);
// For a new subscription copy the billing details to the customer object.
// NOTE: This is a costly operation and should happen at the very end.
if (createAction && subscription.default_payment_method)
await copyBillingDetailsToCustomer(
uuid,
subscription.default_payment_method
);
};
export {
upsertProductRecord,
upsertPriceRecord,
createOrRetrieveCustomer,
manageSubscriptionStatusChange
};