Use @t3-oss/env-nextjs for env variables

This commit is contained in:
Artur N
2024-06-12 12:19:04 -03:00
parent a2fed6ea32
commit 94f4bae0d3
9 changed files with 110 additions and 69 deletions

11
.env.example Normal file
View File

@@ -0,0 +1,11 @@
NEXTAUTH_SECRET=""
STRIPE_SECRET_KEY=""
KEYCLOAK_CLIENT_ID="app"
KEYCLOAK_CLIENT_SECRET="7JryN6EVIYtCwN4iHheacjp986Rfy5FJ"
KEYCLOAK_REALM_NAME="monerofund"
BTCPAY_URL=""
BTCPAY_STORE_ID=""
BTCPAY_API_KEY=""
SENDGRID_RECIPIENT=""
SENDGRID_VERIFIED_SENDER=""
SENDGRID_API_KEY=""

25
env.mjs
View File

@@ -8,7 +8,16 @@ export const env = createEnv({
* Will throw if you access these variables on the client.
*/
server: {
OPEN_AI_API_KEY: z.string().min(1),
STRIPE_SECRET_KEY: z.string().min(1),
KEYCLOAK_CLIENT_ID: z.string().min(1),
KEYCLOAK_CLIENT_SECRET: z.string().min(1),
KEYCLOAK_REALM_NAME: z.string().min(1),
BTCPAY_URL: z.string().min(1),
BTCPAY_STORE_ID: z.string().min(1),
BTCPAY_API_KEY: z.string().min(1),
SENDGRID_RECIPIENT: z.string().min(1),
SENDGRID_VERIFIED_SENDER: z.string().min(1),
SENDGRID_API_KEY: z.string().min(1),
},
/*
* Environment variables available on the client (and server).
@@ -25,9 +34,15 @@ export const env = createEnv({
* 💡 You'll get type errors if not all variables from `server` & `client` are included here.
*/
runtimeEnv: {
DATABASE_URL: process.env.DATABASE_URL,
OPEN_AI_API_KEY: process.env.OPEN_AI_API_KEY,
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY:
process.env.NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY,
STRIPE_SECRET_KEY: process.env.STRIPE_SECRET_KEY,
KEYCLOAK_CLIENT_ID: process.env.KEYCLOAK_CLIENT_ID,
KEYCLOAK_CLIENT_SECRET: process.env.KEYCLOAK_CLIENT_SECRET,
KEYCLOAK_REALM_NAME: process.env.KEYCLOAK_REALM_NAME,
BTCPAY_URL: process.env.BTCPAY_URL,
BTCPAY_STORE_ID: process.env.BTCPAY_STORE_ID,
BTCPAY_API_KEY: process.env.BTCPAY_API_KEY,
SENDGRID_RECIPIENT: process.env.SENDGRID_RECIPIENT,
SENDGRID_VERIFIED_SENDER: process.env.SENDGRID_VERIFIED_SENDER,
SENDGRID_API_KEY: process.env.SENDGRID_API_KEY,
},
})

34
package-lock.json generated
View File

@@ -22,7 +22,7 @@
"@sendgrid/mail": "^8.1.3",
"@stripe/react-stripe-js": "^2.7.1",
"@stripe/stripe-js": "^3.4.1",
"@t3-oss/env-nextjs": "^0.10.1",
"@t3-oss/env-nextjs": "^0.7.3",
"@tailwindcss/aspect-ratio": "^0.4.2",
"@tailwindcss/forms": "^0.5.7",
"@tanstack/react-query": "^5.40.1",
@@ -3794,11 +3794,11 @@
}
},
"node_modules/@t3-oss/env-core": {
"version": "0.10.1",
"resolved": "https://registry.npmjs.org/@t3-oss/env-core/-/env-core-0.10.1.tgz",
"integrity": "sha512-GcKZiCfWks5CTxhezn9k5zWX3sMDIYf6Kaxy2Gx9YEQftFcz8hDRN56hcbylyAO3t4jQnQ5ifLawINsNgCDpOg==",
"version": "0.7.3",
"resolved": "https://registry.npmjs.org/@t3-oss/env-core/-/env-core-0.7.3.tgz",
"integrity": "sha512-hhtj59TKC6TKVdwJ0CcbKsvkr9R8Pc/SNKd4IgGUIC9T9X6moB8EZZ3FTJdABA/h9UABCK4J+KsF8gzmvMvHPg==",
"peerDependencies": {
"typescript": ">=5.0.0",
"typescript": ">=4.7.2",
"zod": "^3.0.0"
},
"peerDependenciesMeta": {
@@ -3808,14 +3808,14 @@
}
},
"node_modules/@t3-oss/env-nextjs": {
"version": "0.10.1",
"resolved": "https://registry.npmjs.org/@t3-oss/env-nextjs/-/env-nextjs-0.10.1.tgz",
"integrity": "sha512-iy2qqJLnFh1RjEWno2ZeyTu0ufomkXruUsOZludzDIroUabVvHsrSjtkHqwHp1/pgPUzN3yBRHMILW162X7x2Q==",
"version": "0.7.3",
"resolved": "https://registry.npmjs.org/@t3-oss/env-nextjs/-/env-nextjs-0.7.3.tgz",
"integrity": "sha512-90TNffS17vjkQwfYyMUb4Zw9yqHwFV40f78qFug4JiQa5+N6DydTdlLOpzOcj8Cna/qpAVDwMSypofF/TVQDuA==",
"dependencies": {
"@t3-oss/env-core": "0.10.1"
"@t3-oss/env-core": "0.7.3"
},
"peerDependencies": {
"typescript": ">=5.0.0",
"typescript": ">=4.7.2",
"zod": "^3.0.0"
},
"peerDependenciesMeta": {
@@ -13581,17 +13581,17 @@
}
},
"@t3-oss/env-core": {
"version": "0.10.1",
"resolved": "https://registry.npmjs.org/@t3-oss/env-core/-/env-core-0.10.1.tgz",
"integrity": "sha512-GcKZiCfWks5CTxhezn9k5zWX3sMDIYf6Kaxy2Gx9YEQftFcz8hDRN56hcbylyAO3t4jQnQ5ifLawINsNgCDpOg==",
"version": "0.7.3",
"resolved": "https://registry.npmjs.org/@t3-oss/env-core/-/env-core-0.7.3.tgz",
"integrity": "sha512-hhtj59TKC6TKVdwJ0CcbKsvkr9R8Pc/SNKd4IgGUIC9T9X6moB8EZZ3FTJdABA/h9UABCK4J+KsF8gzmvMvHPg==",
"requires": {}
},
"@t3-oss/env-nextjs": {
"version": "0.10.1",
"resolved": "https://registry.npmjs.org/@t3-oss/env-nextjs/-/env-nextjs-0.10.1.tgz",
"integrity": "sha512-iy2qqJLnFh1RjEWno2ZeyTu0ufomkXruUsOZludzDIroUabVvHsrSjtkHqwHp1/pgPUzN3yBRHMILW162X7x2Q==",
"version": "0.7.3",
"resolved": "https://registry.npmjs.org/@t3-oss/env-nextjs/-/env-nextjs-0.7.3.tgz",
"integrity": "sha512-90TNffS17vjkQwfYyMUb4Zw9yqHwFV40f78qFug4JiQa5+N6DydTdlLOpzOcj8Cna/qpAVDwMSypofF/TVQDuA==",
"requires": {
"@t3-oss/env-core": "0.10.1"
"@t3-oss/env-core": "0.7.3"
}
},
"@tailwindcss/aspect-ratio": {

View File

@@ -99,4 +99,4 @@
"extensions": "js,jsx,tsx,ts,css,scss,md"
}
}
}
}

View File

@@ -3,15 +3,14 @@ import type { NextApiRequest, NextApiResponse } from 'next'
import { CURRENCY, MIN_AMOUNT } from '../../config'
import { fetchPostJSONAuthed } from '../../utils/api-helpers'
import { PayReq } from '../../utils/types'
import { env } from '../../env.mjs'
export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
if (req.method === 'POST') {
const { amount, project_name, project_slug, email, name }: PayReq =
req.body
const { amount, project_name, project_slug, email, name }: PayReq = req.body
const REDIRECT = 'http://monerofund.org/thankyou'
try {
@@ -28,12 +27,11 @@ export default async function handler(
}
let data = await fetchPostJSONAuthed(
`${process.env.BTCPAY_URL!}stores/${process.env.BTCPAY_STORE_ID
}/invoices`,
`token ${process.env.BTCPAY_API_KEY}`,
`${env.BTCPAY_URL}stores/${env.BTCPAY_STORE_ID}/invoices`,
`token ${env.BTCPAY_API_KEY}`,
{
amount: amount,
currency: "USD",
currency: 'USD',
metadata: {
orderId: project_slug,
project_name,

View File

@@ -1,8 +1,9 @@
import { NextApiRequest, NextApiResponse } from 'next/types'
import { env } from '../../env.mjs'
const SENDGRID_API_KEY = process.env.SENDGRID_API_KEY
const TO_ADDRESS = process.env.SENDGRID_RECEPIENT
const FROM_ADDRESS = process.env.SENDGRID_VERIFIED_SENDER
const SENDGRID_API_KEY = env.SENDGRID_API_KEY
const TO_ADDRESS = env.SENDGRID_RECIPIENT
const FROM_ADDRESS = env.SENDGRID_VERIFIED_SENDER
const sgMail = require('@sendgrid/mail')
sgMail.setApiKey(SENDGRID_API_KEY)
@@ -23,7 +24,7 @@ export default async function handler(
}
try {
console.log(process.env.SENDGRID_API_KEY)
console.log(env.SENDGRID_API_KEY)
const msg = {
to: TO_ADDRESS, // Change to your recipient
from: FROM_ADDRESS, // Change to your verified sender

View File

@@ -1,23 +1,22 @@
import { NextApiRequest, NextApiResponse } from 'next'
import Stripe from 'stripe'
import { CURRENCY, MIN_AMOUNT } from '../../config'
// import { formatAmountForStripe } from '../../utils/stripe-helpers'
import Stripe from 'stripe'
import { PayReq } from '../../utils/types'
import { env } from '../../env.mjs'
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!, {
const stripe = new Stripe(env.STRIPE_SECRET_KEY, {
// https://github.com/stripe/stripe-node#configuration
apiVersion: "2024-04-10",
apiVersion: '2024-04-10',
})
export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
const { amount, project_name, project_slug, email, name }: PayReq =
req.body
const { amount, project_name, project_slug, email, name }: PayReq = req.body
if (req.method === 'POST') {
try {
@@ -37,7 +36,7 @@ export default async function handler(
product_data: {
name: `MAGIC Grants donation: ${project_name}`,
},
unit_amount: amount*100,
unit_amount: amount * 100,
},
quantity: 1,
},

View File

@@ -1,8 +1,9 @@
import { keycloak } from '../services'
import { env } from '../../env.mjs'
export const authenticateKeycloakClient = () =>
keycloak.auth({
clientId: 'app',
clientSecret: '7JryN6EVIYtCwN4iHheacjp986Rfy5FJ',
clientId: env.KEYCLOAK_CLIENT_ID,
clientSecret: env.KEYCLOAK_CLIENT_SECRET,
grantType: 'client_credentials',
})

View File

@@ -1,3 +1,5 @@
import { env } from '../env.mjs'
export async function fetchGetJSON(url: string) {
try {
const data = await fetch(url).then((res) => res.json())
@@ -20,7 +22,7 @@ export async function fetchPostJSON(url: string, data?: {}) {
credentials: 'same-origin', // include, *same-origin, omit
headers: {
'Content-Type': 'application/json',
Authorization: `token ${process.env.BTCPAY_API_KEY}`,
Authorization: `token ${env.BTCPAY_API_KEY}`,
},
redirect: 'follow', // manual, *follow, error
referrerPolicy: 'no-referrer', // no-referrer, *client
@@ -58,19 +60,17 @@ export async function fetchPostJSONAuthed(
})
return await response.json() // parses JSON response into native JavaScript objects
} catch (err) {
if (err instanceof Error) {
if (err instanceof Error) {
throw new Error(err.message)
}
throw err
}
}
export async function fetchGetJSONAuthedBTCPay(
slug: string
) {
export async function fetchGetJSONAuthedBTCPay(slug: string) {
try {
const url = `${process.env.BTCPAY_URL!}stores/${process.env.BTCPAY_STORE_ID}/invoices`
const auth = `token ${process.env.BTCPAY_API_KEY}`
const url = `${env.BTCPAY_URL}stores/${env.BTCPAY_STORE_ID}/invoices`
const auth = `token ${env.BTCPAY_API_KEY}`
const response = await fetch(url, {
method: 'GET',
headers: {
@@ -85,13 +85,16 @@ export async function fetchGetJSONAuthedBTCPay(
let totaldonationsbtc = 0
let totaldonationsinfiatxmr = 0
let totaldonationsinfiatbtc = 0
for(let i=0;i<data.length;i++){
if (data[i].metadata.orderId != slug && data[i].metadata.orderId != `${slug}_STATIC`) {
for (let i = 0; i < data.length; i++) {
if (
data[i].metadata.orderId != slug &&
data[i].metadata.orderId != `${slug}_STATIC`
) {
continue
}
const id = data[i].id
const urliter = `${process.env.BTCPAY_URL!}stores/${process.env.BTCPAY_STORE_ID}/invoices/${id}/payment-methods`
const authiter = `token ${process.env.BTCPAY_API_KEY}`
const urliter = `${env.BTCPAY_URL}stores/${env.BTCPAY_STORE_ID}/invoices/${id}/payment-methods`
const authiter = `token ${env.BTCPAY_API_KEY}`
const responseiter = await fetch(urliter, {
method: 'GET',
headers: {
@@ -99,16 +102,24 @@ export async function fetchGetJSONAuthedBTCPay(
Authorization: authiter,
},
})
const dataiter = await responseiter.json();
if (dataiter[1].cryptoCode == 'XMR' && dataiter[1].paymentMethodPaid > 0) {
const dataiter = await responseiter.json()
if (
dataiter[1].cryptoCode == 'XMR' &&
dataiter[1].paymentMethodPaid > 0
) {
numdonationsxmr += dataiter[1].payments.length
totaldonationsxmr += Number(dataiter[1].paymentMethodPaid)
totaldonationsinfiatxmr += Number(dataiter[1].paymentMethodPaid) * Number(dataiter[1].rate)
totaldonationsinfiatxmr +=
Number(dataiter[1].paymentMethodPaid) * Number(dataiter[1].rate)
}
if (dataiter[0].cryptoCode == 'BTC' && dataiter[0].paymentMethodPaid > 0) {
if (
dataiter[0].cryptoCode == 'BTC' &&
dataiter[0].paymentMethodPaid > 0
) {
numdonationsbtc += dataiter[0].payments.length
totaldonationsbtc += Number(dataiter[0].paymentMethodPaid)
totaldonationsinfiatbtc += Number(dataiter[0].paymentMethodPaid) * Number(dataiter[0].rate)
totaldonationsinfiatbtc +=
Number(dataiter[0].paymentMethodPaid) * Number(dataiter[0].rate)
}
}
return await {
@@ -121,8 +132,8 @@ export async function fetchGetJSONAuthedBTCPay(
numdonations: numdonationsbtc,
totaldonationsinfiat: totaldonationsinfiatbtc,
totaldonations: totaldonationsbtc,
}
}
},
}
} catch (err) {
if (err instanceof Error) {
throw new Error(err.message)
@@ -131,12 +142,10 @@ export async function fetchGetJSONAuthedBTCPay(
}
}
export async function fetchGetJSONAuthedStripe(
slug: string
) {
export async function fetchGetJSONAuthedStripe(slug: string) {
try {
const url = "https://api.stripe.com/v1/charges"
const auth = `Bearer ${process.env.STRIPE_SECRET_KEY}`
const url = 'https://api.stripe.com/v1/charges'
const auth = `Bearer ${env.STRIPE_SECRET_KEY}`
const response = await fetch(url, {
method: 'GET',
headers: {
@@ -148,14 +157,21 @@ export async function fetchGetJSONAuthedStripe(
const dataext = data.data
let total = 0
let donations = 0
for(let i=0;i<dataext.length;i++){
if (dataext[i].metadata.project_slug == null || dataext[i].metadata.project_slug != slug) {
for (let i = 0; i < dataext.length; i++) {
if (
dataext[i].metadata.project_slug == null ||
dataext[i].metadata.project_slug != slug
) {
continue
}
total += Number(dataext[i].amount) / 100
donations += 1
}
return await { numdonations: donations, totaldonationsinfiat: total, totaldonations: total }
return await {
numdonations: donations,
totaldonationsinfiat: total,
totaldonations: total,
}
} catch (err) {
if (err instanceof Error) {
throw new Error(err.message)