@riligar/agents-kit 1.16.0 → 1.18.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.
- package/.agent/skills/riligar-design-system/references/design-system.md +0 -7
- package/.agent/skills/riligar-dev-database/SKILL.md +45 -0
- package/.agent/skills/riligar-dev-database/references/connection.md +74 -0
- package/.agent/skills/riligar-dev-database/references/migrations.md +70 -0
- package/.agent/skills/riligar-dev-database/references/queries.md +173 -0
- package/.agent/skills/riligar-dev-database/references/schema.md +106 -0
- package/.agent/skills/riligar-dev-manager/SKILL.md +1 -0
- package/.agent/skills/riligar-infra-cloudfare/SKILL.md +8 -95
- package/.agent/skills/riligar-infra-stripe/SKILL.md +53 -10
- package/.agent/skills/riligar-infra-stripe/assets/stripe-client.js +69 -10
- package/.agent/skills/riligar-infra-stripe/assets/stripe-server.js +258 -79
- package/.agent/skills/riligar-infra-stripe/references/stripe-elysia.md +136 -55
- package/.agent/skills/riligar-infra-stripe/references/stripe-webhooks.md +67 -18
- package/.agent/skills/riligar-marketing-email/SKILL.md +0 -6
- package/.agent/skills/riligar-marketing-seo/SKILL.md +1 -7
- package/package.json +1 -1
|
@@ -151,7 +151,7 @@ Instrua o usuário:
|
|
|
151
151
|
>
|
|
152
152
|
> 1. Acesse https://dashboard.stripe.com/webhooks
|
|
153
153
|
> 2. Clique em "Add endpoint"
|
|
154
|
-
> 3. URL: `https://seu-dominio.com/webhook
|
|
154
|
+
> 3. URL: `https://seu-dominio.com/api/webhook`
|
|
155
155
|
> 4. Selecione os eventos:
|
|
156
156
|
> - `checkout.session.completed`
|
|
157
157
|
> - `customer.subscription.updated`
|
|
@@ -171,14 +171,15 @@ Gere todos os arquivos necessários usando os templates de [assets/](assets/):
|
|
|
171
171
|
| `routes/billing.js` | stripe-server.js (seção 2) |
|
|
172
172
|
| `routes/webhook.js` | stripe-server.js (seção 3) |
|
|
173
173
|
| `services/billing.js` | stripe-server.js (seção 4) |
|
|
174
|
-
| `config/stripe-prices.js` | Price IDs coletados |
|
|
174
|
+
| `config/stripe-prices.js` | Price IDs coletados (Step 9) |
|
|
175
|
+
| `config/plans.js` | PLAN_MAP + PLAN_LIMITS (Step 9) |
|
|
175
176
|
| `pages/Pricing.jsx` | stripe-client.js (seção 3) |
|
|
176
177
|
| `components/BillingSettings.jsx` | stripe-client.js (seção 4) |
|
|
177
178
|
| `hooks/useSubscription.js` | stripe-client.js (seção 2) |
|
|
178
179
|
|
|
179
|
-
### Step 9: Criar
|
|
180
|
+
### Step 9: Criar Configs de Planos e Preços
|
|
180
181
|
|
|
181
|
-
|
|
182
|
+
**A) Arquivo de preços (config/stripe-prices.js):**
|
|
182
183
|
|
|
183
184
|
```javascript
|
|
184
185
|
// config/stripe-prices.js
|
|
@@ -194,6 +195,12 @@ export const STRIPE_PRICES = {
|
|
|
194
195
|
name: 'Pro',
|
|
195
196
|
price: 99,
|
|
196
197
|
features: ['Projetos ilimitados', 'Suporte prioritário', '10GB storage']
|
|
198
|
+
},
|
|
199
|
+
enterprise: {
|
|
200
|
+
priceId: 'price_COLETADO_ENTERPRISE',
|
|
201
|
+
name: 'Enterprise',
|
|
202
|
+
price: 299,
|
|
203
|
+
features: ['Tudo do Pro', 'Storage ilimitado', 'SLA garantido']
|
|
197
204
|
}
|
|
198
205
|
}
|
|
199
206
|
|
|
@@ -201,6 +208,40 @@ export const getPrice = (plan) => STRIPE_PRICES[plan]
|
|
|
201
208
|
export const getPriceId = (plan) => STRIPE_PRICES[plan]?.priceId
|
|
202
209
|
```
|
|
203
210
|
|
|
211
|
+
**B) Arquivo de mapeamento e limites (config/plans.js):**
|
|
212
|
+
|
|
213
|
+
```javascript
|
|
214
|
+
// config/plans.js
|
|
215
|
+
|
|
216
|
+
// Mapeia Price IDs do Stripe para nomes de planos internos
|
|
217
|
+
export const PLAN_MAP = {
|
|
218
|
+
'price_COLETADO_STARTER': 'starter',
|
|
219
|
+
'price_COLETADO_PRO': 'pro',
|
|
220
|
+
'price_COLETADO_ENTERPRISE': 'enterprise',
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// Define limites de features por plano
|
|
224
|
+
export const PLAN_LIMITS = {
|
|
225
|
+
free: {
|
|
226
|
+
maxFlows: 1,
|
|
227
|
+
maxContacts: 100,
|
|
228
|
+
// Adicione outros limites conforme necessário
|
|
229
|
+
},
|
|
230
|
+
starter: {
|
|
231
|
+
maxFlows: 3,
|
|
232
|
+
maxContacts: 500,
|
|
233
|
+
},
|
|
234
|
+
pro: {
|
|
235
|
+
maxFlows: 15,
|
|
236
|
+
maxContacts: 5000,
|
|
237
|
+
},
|
|
238
|
+
enterprise: {
|
|
239
|
+
maxFlows: 55,
|
|
240
|
+
maxContacts: Infinity,
|
|
241
|
+
},
|
|
242
|
+
}
|
|
243
|
+
```
|
|
244
|
+
|
|
204
245
|
---
|
|
205
246
|
|
|
206
247
|
## Checklist Final
|
|
@@ -211,11 +252,13 @@ Ao completar o setup, confirme:
|
|
|
211
252
|
- [ ] Chaves no `.env.development` e `.env.production` (backend e frontend)
|
|
212
253
|
- [ ] Produtos criados no Stripe
|
|
213
254
|
- [ ] Price IDs configurados em `config/stripe-prices.js`
|
|
214
|
-
- [ ]
|
|
215
|
-
- [ ]
|
|
255
|
+
- [ ] `PLAN_MAP` e `PLAN_LIMITS` configurados em `config/plans.js`
|
|
256
|
+
- [ ] Schema do database atualizado (campos Stripe na tabela users)
|
|
257
|
+
- [ ] Webhook endpoint configurado no Stripe Dashboard (`/api/webhook`)
|
|
216
258
|
- [ ] Webhook secret nos arquivos de ambiente
|
|
217
|
-
- [ ] Rotas de billing funcionando
|
|
218
|
-
- [ ] Página de pricing criada
|
|
259
|
+
- [ ] Rotas de billing funcionando (`/api/billing/*`)
|
|
260
|
+
- [ ] Página de pricing criada (com token de auth no ky)
|
|
261
|
+
- [ ] `useSubscription` hook com header Authorization
|
|
219
262
|
- [ ] Testado com cartão 4242 4242 4242 4242
|
|
220
263
|
|
|
221
264
|
---
|
|
@@ -229,8 +272,8 @@ brew install stripe/stripe-cli/stripe
|
|
|
229
272
|
# Login
|
|
230
273
|
stripe login
|
|
231
274
|
|
|
232
|
-
# Forward webhooks
|
|
233
|
-
stripe listen --forward-to localhost:
|
|
275
|
+
# Forward webhooks (ajuste a porta conforme seu backend)
|
|
276
|
+
stripe listen --forward-to localhost:3333/api/webhook
|
|
234
277
|
|
|
235
278
|
# Testar checkout
|
|
236
279
|
stripe trigger checkout.session.completed
|
|
@@ -32,6 +32,20 @@ export const elementsAppearance = {
|
|
|
32
32
|
import { useState, useEffect } from 'react'
|
|
33
33
|
import ky from 'ky'
|
|
34
34
|
|
|
35
|
+
const api = ky.create({
|
|
36
|
+
prefixUrl: import.meta.env.VITE_API_URL || 'http://localhost:3333',
|
|
37
|
+
hooks: {
|
|
38
|
+
beforeRequest: [
|
|
39
|
+
request => {
|
|
40
|
+
const token = localStorage.getItem('auth:token')
|
|
41
|
+
if (token) {
|
|
42
|
+
request.headers.set('Authorization', `Bearer ${token}`)
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
],
|
|
46
|
+
},
|
|
47
|
+
})
|
|
48
|
+
|
|
35
49
|
export function useSubscription() {
|
|
36
50
|
const [subscription, setSubscription] = useState(null)
|
|
37
51
|
const [loading, setLoading] = useState(true)
|
|
@@ -40,7 +54,7 @@ export function useSubscription() {
|
|
|
40
54
|
const fetchSubscription = async () => {
|
|
41
55
|
setLoading(true)
|
|
42
56
|
try {
|
|
43
|
-
const data = await
|
|
57
|
+
const data = await api.get('api/billing/subscription').json()
|
|
44
58
|
setSubscription(data)
|
|
45
59
|
setError(null)
|
|
46
60
|
} catch (err) {
|
|
@@ -77,35 +91,52 @@ import { IconCheck } from '@tabler/icons-react'
|
|
|
77
91
|
import { useState } from 'react'
|
|
78
92
|
import ky from 'ky'
|
|
79
93
|
|
|
94
|
+
// Importar do arquivo de configuração centralizado
|
|
95
|
+
// import { STRIPE_PRICES } from '../config/stripe-prices'
|
|
96
|
+
|
|
80
97
|
const plans = [
|
|
81
98
|
{
|
|
82
99
|
name: 'Starter',
|
|
83
|
-
priceId: 'price_starter_monthly',
|
|
100
|
+
priceId: 'price_starter_monthly', // Substituir pelo valor de STRIPE_PRICES.starter.priceId
|
|
84
101
|
price: 29,
|
|
85
102
|
features: ['5 projetos', 'Suporte por email', '1GB de storage']
|
|
86
103
|
},
|
|
87
104
|
{
|
|
88
105
|
name: 'Pro',
|
|
89
|
-
priceId: 'price_pro_monthly',
|
|
106
|
+
priceId: 'price_pro_monthly', // Substituir pelo valor de STRIPE_PRICES.pro.priceId
|
|
90
107
|
price: 99,
|
|
91
108
|
popular: true,
|
|
92
109
|
features: ['Projetos ilimitados', 'Suporte prioritário', '10GB de storage', 'API access']
|
|
93
110
|
},
|
|
94
111
|
{
|
|
95
112
|
name: 'Enterprise',
|
|
96
|
-
priceId: 'price_enterprise_monthly',
|
|
113
|
+
priceId: 'price_enterprise_monthly', // Substituir pelo valor de STRIPE_PRICES.enterprise.priceId
|
|
97
114
|
price: 299,
|
|
98
115
|
features: ['Tudo do Pro', 'Suporte dedicado', 'Storage ilimitado', 'SLA garantido']
|
|
99
116
|
}
|
|
100
117
|
]
|
|
101
118
|
|
|
119
|
+
const api = ky.create({
|
|
120
|
+
prefixUrl: import.meta.env.VITE_API_URL || 'http://localhost:3333',
|
|
121
|
+
hooks: {
|
|
122
|
+
beforeRequest: [
|
|
123
|
+
request => {
|
|
124
|
+
const token = localStorage.getItem('auth:token')
|
|
125
|
+
if (token) {
|
|
126
|
+
request.headers.set('Authorization', `Bearer ${token}`)
|
|
127
|
+
}
|
|
128
|
+
},
|
|
129
|
+
],
|
|
130
|
+
},
|
|
131
|
+
})
|
|
132
|
+
|
|
102
133
|
export default function Pricing() {
|
|
103
134
|
const [loading, setLoading] = useState(null)
|
|
104
135
|
|
|
105
136
|
const handleCheckout = async (priceId) => {
|
|
106
137
|
setLoading(priceId)
|
|
107
138
|
try {
|
|
108
|
-
const { url } = await
|
|
139
|
+
const { url } = await api.post('api/billing/checkout', {
|
|
109
140
|
json: { priceId, mode: 'subscription' }
|
|
110
141
|
}).json()
|
|
111
142
|
window.location.href = url
|
|
@@ -178,12 +209,26 @@ import { Button, Card, Group, Stack, Text, Title, Badge, Divider } from '@mantin
|
|
|
178
209
|
import { useState, useEffect } from 'react'
|
|
179
210
|
import ky from 'ky'
|
|
180
211
|
|
|
212
|
+
const api = ky.create({
|
|
213
|
+
prefixUrl: import.meta.env.VITE_API_URL || 'http://localhost:3333',
|
|
214
|
+
hooks: {
|
|
215
|
+
beforeRequest: [
|
|
216
|
+
request => {
|
|
217
|
+
const token = localStorage.getItem('auth:token')
|
|
218
|
+
if (token) {
|
|
219
|
+
request.headers.set('Authorization', `Bearer ${token}`)
|
|
220
|
+
}
|
|
221
|
+
},
|
|
222
|
+
],
|
|
223
|
+
},
|
|
224
|
+
})
|
|
225
|
+
|
|
181
226
|
export default function BillingSettings() {
|
|
182
227
|
const [subscription, setSubscription] = useState(null)
|
|
183
228
|
const [loading, setLoading] = useState(false)
|
|
184
229
|
|
|
185
230
|
useEffect(() => {
|
|
186
|
-
|
|
231
|
+
api.get('api/billing/subscription').json()
|
|
187
232
|
.then(setSubscription)
|
|
188
233
|
.catch(console.error)
|
|
189
234
|
}, [])
|
|
@@ -191,7 +236,7 @@ export default function BillingSettings() {
|
|
|
191
236
|
const openPortal = async () => {
|
|
192
237
|
setLoading(true)
|
|
193
238
|
try {
|
|
194
|
-
const { url } = await
|
|
239
|
+
const { url } = await api.post('api/billing/portal').json()
|
|
195
240
|
window.location.href = url
|
|
196
241
|
} finally {
|
|
197
242
|
setLoading(false)
|
|
@@ -201,9 +246,9 @@ export default function BillingSettings() {
|
|
|
201
246
|
const cancelSubscription = async () => {
|
|
202
247
|
setLoading(true)
|
|
203
248
|
try {
|
|
204
|
-
await
|
|
249
|
+
await api.post('api/billing/subscription/cancel').json()
|
|
205
250
|
// Refresh subscription data
|
|
206
|
-
const data = await
|
|
251
|
+
const data = await api.get('api/billing/subscription').json()
|
|
207
252
|
setSubscription(data)
|
|
208
253
|
} finally {
|
|
209
254
|
setLoading(false)
|
|
@@ -356,12 +401,26 @@ import { IconDownload } from '@tabler/icons-react'
|
|
|
356
401
|
import { useState, useEffect } from 'react'
|
|
357
402
|
import ky from 'ky'
|
|
358
403
|
|
|
404
|
+
const api = ky.create({
|
|
405
|
+
prefixUrl: import.meta.env.VITE_API_URL || 'http://localhost:3333',
|
|
406
|
+
hooks: {
|
|
407
|
+
beforeRequest: [
|
|
408
|
+
request => {
|
|
409
|
+
const token = localStorage.getItem('auth:token')
|
|
410
|
+
if (token) {
|
|
411
|
+
request.headers.set('Authorization', `Bearer ${token}`)
|
|
412
|
+
}
|
|
413
|
+
},
|
|
414
|
+
],
|
|
415
|
+
},
|
|
416
|
+
})
|
|
417
|
+
|
|
359
418
|
export default function InvoiceList() {
|
|
360
419
|
const [invoices, setInvoices] = useState([])
|
|
361
420
|
const [loading, setLoading] = useState(true)
|
|
362
421
|
|
|
363
422
|
useEffect(() => {
|
|
364
|
-
|
|
423
|
+
api.get('api/billing/invoices').json()
|
|
365
424
|
.then(({ data }) => setInvoices(data))
|
|
366
425
|
.catch(console.error)
|
|
367
426
|
.finally(() => setLoading(false))
|