@edgedev/create-edge-app 1.0.18 → 1.0.19
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/.env +11 -0
- package/.env.dev +11 -0
- package/app.vue +1 -1
- package/bin/cli.js +44 -0
- package/deploy.sh +1 -2
- package/emulator.sh +1 -0
- package/functions/.env.dev +7 -0
- package/functions/.env.prod +7 -0
- package/functions/config.js +21 -0
- package/functions/edgeFirebase.js +302 -0
- package/functions/index.js +4 -223
- package/functions/package-lock.json +552 -28
- package/functions/package.json +6 -2
- package/functions/stripe.js +97 -0
- package/package.json +1 -2
- package/plugins/edgeFirebaseFramework.ts +1 -1
package/functions/package.json
CHANGED
|
@@ -13,13 +13,17 @@
|
|
|
13
13
|
},
|
|
14
14
|
"main": "index.js",
|
|
15
15
|
"dependencies": {
|
|
16
|
+
"dotenv": "^16.3.1",
|
|
16
17
|
"firebase-admin": "^10.0.2",
|
|
17
18
|
"firebase-functions": "^4.2.1",
|
|
18
19
|
"form-data": "^4.0.0",
|
|
19
|
-
"formidable-serverless": "^1.1.1"
|
|
20
|
+
"formidable-serverless": "^1.1.1",
|
|
21
|
+
"openai": "^4.11.1",
|
|
22
|
+
"stripe": "^13.8.0",
|
|
23
|
+
"twilio": "^4.18.0"
|
|
20
24
|
},
|
|
21
25
|
"devDependencies": {
|
|
22
26
|
"firebase-functions-test": "^0.2.0"
|
|
23
27
|
},
|
|
24
28
|
"private": true
|
|
25
|
-
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
const stripe = require('stripe')(process.env.STRIPE_API_KEY)
|
|
2
|
+
const { onCall, HttpsError, logger, getFirestore, functions, admin, twilio, db } = require('./config.js')
|
|
3
|
+
|
|
4
|
+
exports.redirectToStripeBilling = onCall(async (request) => {
|
|
5
|
+
const data = request.data
|
|
6
|
+
const auth = request.auth
|
|
7
|
+
|
|
8
|
+
if (data.uid !== auth.uid) {
|
|
9
|
+
throw new HttpsError('failed-precondition', 'The function must be called by the user who is to be redirected.')
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const userDoc = await db.collection('staged-users').doc(data.uid).get()
|
|
13
|
+
if (!userDoc.exists) {
|
|
14
|
+
throw new HttpsError('not-found', 'No user found for the provided ID.')
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const collectionPaths = userDoc.data().collectionPaths
|
|
18
|
+
if (!collectionPaths || collectionPaths.length === 0) {
|
|
19
|
+
throw new HttpsError('not-found', 'No collection paths found for the user.')
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const orgDoc = await db.doc(collectionPaths[0].replace('-', '/')).get()
|
|
23
|
+
if (!orgDoc.exists) {
|
|
24
|
+
throw new HttpsError('not-found', 'No organization found for the user.')
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const stripeCustomerId = orgDoc.data().stripeCustomerId
|
|
28
|
+
if (!stripeCustomerId) {
|
|
29
|
+
throw new HttpsError('not-found', 'No Stripe customer ID found for the organization.')
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const session = await stripe.billingPortal.sessions.create({
|
|
33
|
+
customer: stripeCustomerId,
|
|
34
|
+
return_url: process.env.STRIPE_RETURN_URL,
|
|
35
|
+
})
|
|
36
|
+
return { url: session.url }
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
exports.stripeWebhook = functions.https.onRequest(async (request, response) => {
|
|
40
|
+
let event
|
|
41
|
+
|
|
42
|
+
try {
|
|
43
|
+
event = stripe.webhooks.constructEvent(request.rawBody, request.headers['stripe-signature'], process.env.STRIPE_SECRET)
|
|
44
|
+
}
|
|
45
|
+
catch (err) {
|
|
46
|
+
await db.collection('stripe').add({
|
|
47
|
+
message: err.message,
|
|
48
|
+
name: err.name,
|
|
49
|
+
stack: err.stack,
|
|
50
|
+
})
|
|
51
|
+
response.status(400).send(`Webhook Error: ${err.message}`)
|
|
52
|
+
return
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const session = event.data.object
|
|
56
|
+
const client_reference_id = session.client_reference_id
|
|
57
|
+
|
|
58
|
+
let docRef
|
|
59
|
+
if (client_reference_id) {
|
|
60
|
+
// Check if client_reference_id exists
|
|
61
|
+
docRef = db.collection('organizations').doc(client_reference_id)
|
|
62
|
+
}
|
|
63
|
+
else if (session.customer) {
|
|
64
|
+
// If client_reference_id doesn't exist, check if session.customer exists
|
|
65
|
+
const orgsSnapshot = await db.collection('organizations').where('stripeCustomerId', '==', session.customer).get()
|
|
66
|
+
if (!orgsSnapshot.empty) {
|
|
67
|
+
docRef = orgsSnapshot.docs[0].ref
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (docRef) {
|
|
72
|
+
const doc = await docRef.get()
|
|
73
|
+
if (doc.exists) {
|
|
74
|
+
// Record any event related to the client_reference_id
|
|
75
|
+
const date = new Date()
|
|
76
|
+
const formattedDate = `${date.getFullYear()}${(`0${date.getMonth() + 1}`).slice(-2)}${(`0${date.getDate()}`).slice(-2)}${(`0${date.getHours()}`).slice(-2)}${(`0${date.getMinutes()}`).slice(-2)}${(`0${date.getSeconds()}`).slice(-2)}${(`00${date.getMilliseconds()}`).slice(-3)}`
|
|
77
|
+
const docId = `${event.type}-${formattedDate}`
|
|
78
|
+
await docRef.collection('stripe').doc(docId).set({ session, event })
|
|
79
|
+
|
|
80
|
+
// Handle subscription events
|
|
81
|
+
|
|
82
|
+
if (session.customer) {
|
|
83
|
+
await docRef.update({ stripeCustomerId: session.customer })
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (['customer.subscription.created', 'customer.subscription.updated', 'customer.subscription.deleted'].includes(event.type)) {
|
|
87
|
+
await docRef.update({ stripeSubscription: session.status })
|
|
88
|
+
}
|
|
89
|
+
response.json({ received: true })
|
|
90
|
+
return
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// If no matching organization, store to a root collection called 'stripe'
|
|
95
|
+
await db.collection('stripe').add(session)
|
|
96
|
+
response.json({ received: true })
|
|
97
|
+
})
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@edgedev/create-edge-app",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.19",
|
|
4
4
|
"description": "Create Edge Starter App",
|
|
5
5
|
"bin": {
|
|
6
6
|
"create-edge-app": "./bin/cli.js"
|
|
@@ -30,7 +30,6 @@
|
|
|
30
30
|
"dependencies": {
|
|
31
31
|
"@chenfengyuan/vue-number-input": "2",
|
|
32
32
|
"@edgedev/firebase": "latest",
|
|
33
|
-
"@edgedev/firebase-framework": "latest",
|
|
34
33
|
"maska": "^2.1.9"
|
|
35
34
|
}
|
|
36
35
|
}
|