🧑💻 Improve env variables type safety and management (#718)
Closes #679
This commit is contained in:
@@ -1,3 +0,0 @@
|
||||
# Don't edit this file
|
||||
NEXT_PUBLIC_VIEWER_URL=
|
||||
NEXT_PUBLIC_E2E_TEST=
|
||||
@@ -1,15 +0,0 @@
|
||||
# Make sure to change this to your own random string of 32 characters (https://docs.typebot.io/self-hosting/docker#2-add-the-required-configuration)
|
||||
ENCRYPTION_SECRET=H+KbL/OFrqbEuDy/1zX8bsPG+spXri3S
|
||||
NEXT_PUBLIC_VIEWER_URL=http://localhost:3001
|
||||
DATABASE_URL=postgresql://postgres:typebot@localhost:5432/typebot
|
||||
NEXTAUTH_URL=http://localhost:3000
|
||||
|
||||
S3_ACCESS_KEY=minio
|
||||
S3_SECRET_KEY=minio123
|
||||
S3_BUCKET=typebot
|
||||
S3_PORT=9000
|
||||
S3_ENDPOINT=localhost
|
||||
S3_SSL=false
|
||||
|
||||
# For more configuration options check out:
|
||||
# https://docs.typebot.io/self-hosting/configuration
|
||||
@@ -1 +0,0 @@
|
||||
next.config.js
|
||||
@@ -1,5 +1,14 @@
|
||||
const { withSentryConfig } = require('@sentry/nextjs')
|
||||
const path = require('path')
|
||||
import { withSentryConfig } from '@sentry/nextjs'
|
||||
import { join, dirname } from 'path'
|
||||
import '@typebot.io/env/dist/env.mjs'
|
||||
import { fileURLToPath } from 'url'
|
||||
import { configureRuntimeEnv } from 'next-runtime-env/build/configure.js'
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url)
|
||||
|
||||
const __dirname = dirname(__filename)
|
||||
|
||||
configureRuntimeEnv()
|
||||
|
||||
const landingPagePaths = [
|
||||
'/',
|
||||
@@ -20,7 +29,7 @@ const nextConfig = {
|
||||
],
|
||||
output: 'standalone',
|
||||
experimental: {
|
||||
outputFileTracingRoot: path.join(__dirname, '../../'),
|
||||
outputFileTracingRoot: join(__dirname, '../../'),
|
||||
},
|
||||
async rewrites() {
|
||||
return {
|
||||
@@ -130,7 +139,7 @@ const sentryWebpackPluginOptions = {
|
||||
release: process.env.NEXT_PUBLIC_VERCEL_GIT_COMMIT_SHA + '-viewer',
|
||||
}
|
||||
|
||||
module.exports = process.env.NEXT_PUBLIC_SENTRY_DSN
|
||||
export default process.env.NEXT_PUBLIC_SENTRY_DSN
|
||||
? withSentryConfig(
|
||||
{
|
||||
...nextConfig,
|
||||
@@ -3,22 +3,20 @@
|
||||
"license": "AGPL-3.0-or-later",
|
||||
"version": "0.1.0",
|
||||
"scripts": {
|
||||
"dev": "cross-env ENVSH_ENV=.env.local bash ../../scripts/inject-runtime-env.sh next dev -p 3001",
|
||||
"build": "cross-env ENVSH_ENV=.env.local bash ../../scripts/inject-runtime-env.sh next build",
|
||||
"build:docker": "next build",
|
||||
"build:env": "cd ../.. && cross-env ENVSH_ENV=./apps/viewer/.env.docker ENVSH_OUTPUT=./apps/viewer/public/__env.js bash scripts/inject-runtime-env.sh",
|
||||
"start": "next start -p 3001",
|
||||
"lint": "next lint",
|
||||
"test": "pnpm playwright test",
|
||||
"dev": "dotenv -e ./.env -e ../../.env -- next dev -p 3001",
|
||||
"build": "dotenv -e ./.env -e ../../.env -- next build",
|
||||
"start": "dotenv -e ./.env -e ../../.env -- next start",
|
||||
"lint": "dotenv -e ./.env -e ../../.env -- next lint",
|
||||
"test": "dotenv -e ./.env -e ../../.env -- pnpm playwright test",
|
||||
"test:report": "pnpm playwright show-report"
|
||||
},
|
||||
"dependencies": {
|
||||
"@planetscale/database": "^1.8.0",
|
||||
"@sentry/nextjs": "7.58.1",
|
||||
"@trpc/server": "10.34.0",
|
||||
"@typebot.io/prisma": "workspace:*",
|
||||
"@typebot.io/nextjs": "workspace:*",
|
||||
"ai": "2.2.8",
|
||||
"@typebot.io/prisma": "workspace:*",
|
||||
"ai": "2.1.32",
|
||||
"aws-sdk": "2.1415.0",
|
||||
"bot-engine": "workspace:*",
|
||||
"cors": "2.8.5",
|
||||
@@ -43,6 +41,7 @@
|
||||
"@paralleldrive/cuid2": "2.2.1",
|
||||
"@playwright/test": "1.36.0",
|
||||
"@typebot.io/emails": "workspace:*",
|
||||
"@typebot.io/env": "workspace:*",
|
||||
"@typebot.io/lib": "workspace:*",
|
||||
"@typebot.io/schemas": "workspace:*",
|
||||
"@typebot.io/tsconfig": "workspace:*",
|
||||
@@ -53,7 +52,8 @@
|
||||
"@types/qs": "6.9.7",
|
||||
"@types/react": "18.2.15",
|
||||
"@types/sanitize-html": "2.9.0",
|
||||
"dotenv": "16.3.1",
|
||||
"dotenv-cli": "^7.2.1",
|
||||
"next-runtime-env": "^1.6.2",
|
||||
"eslint": "8.44.0",
|
||||
"eslint-config-custom": "workspace:*",
|
||||
"google-auth-library": "8.9.0",
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
import * as Sentry from '@sentry/nextjs'
|
||||
|
||||
const SENTRY_DSN = process.env.SENTRY_DSN || process.env.NEXT_PUBLIC_SENTRY_DSN
|
||||
|
||||
Sentry.init({
|
||||
dsn: SENTRY_DSN,
|
||||
dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
|
||||
ignoreErrors: [
|
||||
'ResizeObserver loop limit exceeded',
|
||||
'ResizeObserver loop completed with undelivered notifications.',
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
import * as Sentry from '@sentry/nextjs'
|
||||
|
||||
const SENTRY_DSN = process.env.SENTRY_DSN || process.env.NEXT_PUBLIC_SENTRY_DSN
|
||||
|
||||
Sentry.init({
|
||||
dsn: SENTRY_DSN,
|
||||
dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
|
||||
release: process.env.NEXT_PUBLIC_VERCEL_GIT_COMMIT_SHA + '-viewer',
|
||||
})
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React from 'react'
|
||||
import { getViewerUrl, isEmpty } from '@typebot.io/lib'
|
||||
import { getViewerUrl } from '@typebot.io/lib'
|
||||
|
||||
export const ErrorPage = ({ error }: { error: Error }) => {
|
||||
return (
|
||||
@@ -13,7 +13,7 @@ export const ErrorPage = ({ error }: { error: Error }) => {
|
||||
padding: '0 1rem',
|
||||
}}
|
||||
>
|
||||
{isEmpty(getViewerUrl()) ? (
|
||||
{!getViewerUrl() ? (
|
||||
<>
|
||||
<h1 style={{ fontWeight: 'bold', fontSize: '30px' }}>
|
||||
NEXT_PUBLIC_VIEWER_URL is missing
|
||||
|
||||
@@ -11,6 +11,7 @@ import {
|
||||
import { byId, isDefined } from '@typebot.io/lib'
|
||||
import { z } from 'zod'
|
||||
import { generatePresignedUrl } from '@typebot.io/lib/api/storage'
|
||||
import { env } from '@typebot.io/env'
|
||||
|
||||
export const getUploadUrl = publicProcedure
|
||||
.meta({
|
||||
@@ -39,11 +40,7 @@ export const getUploadUrl = publicProcedure
|
||||
})
|
||||
)
|
||||
.query(async ({ input: { typebotId, blockId, filePath, fileType } }) => {
|
||||
if (
|
||||
!process.env.S3_ENDPOINT ||
|
||||
!process.env.S3_ACCESS_KEY ||
|
||||
!process.env.S3_SECRET_KEY
|
||||
)
|
||||
if (!env.S3_ENDPOINT || !env.S3_ACCESS_KEY || !env.S3_SECRET_KEY)
|
||||
throw new TRPCError({
|
||||
code: 'INTERNAL_SERVER_ERROR',
|
||||
message:
|
||||
|
||||
@@ -10,6 +10,7 @@ import {
|
||||
} from '@typebot.io/lib/playwright/databaseActions'
|
||||
import { getTestAsset } from '@/test/utils/playwright'
|
||||
import { Plan } from '@typebot.io/prisma'
|
||||
import { env } from '@typebot.io/env'
|
||||
|
||||
const THREE_GIGABYTES = 3 * 1024 * 1024 * 1024
|
||||
|
||||
@@ -30,7 +31,7 @@ test('should work as expected', async ({ page, browser }) => {
|
||||
await expect(page.locator(`text="3"`)).toBeVisible()
|
||||
await page.locator('text="Upload 3 files"').click()
|
||||
await expect(page.locator(`text="3 files uploaded"`)).toBeVisible()
|
||||
await page.goto(`${process.env.NEXTAUTH_URL}/typebots/${typebotId}/results`)
|
||||
await page.goto(`${env.NEXTAUTH_URL}/typebots/${typebotId}/results`)
|
||||
await expect(page.getByRole('link', { name: 'api.json' })).toHaveAttribute(
|
||||
'href',
|
||||
/.+\/api\.json/
|
||||
@@ -52,7 +53,7 @@ test('should work as expected', async ({ page, browser }) => {
|
||||
const file = readFileSync(downloadPath as string).toString()
|
||||
const { data } = parse(file)
|
||||
expect(data).toHaveLength(2)
|
||||
expect((data[1] as unknown[])[1]).toContain(process.env.S3_ENDPOINT)
|
||||
expect((data[1] as unknown[])[1]).toContain(env.S3_ENDPOINT)
|
||||
|
||||
const urls = (
|
||||
await Promise.all(
|
||||
@@ -110,7 +111,7 @@ test.describe('Storage limit is reached', () => {
|
||||
await page.evaluate(() =>
|
||||
window.localStorage.setItem('workspaceId', 'starterWorkspace')
|
||||
)
|
||||
await page.goto(`${process.env.NEXTAUTH_URL}/typebots/${typebotId}/results`)
|
||||
await page.goto(`${env.NEXTAUTH_URL}/typebots/${typebotId}/results`)
|
||||
await expect(page.locator('text="150%"')).toBeVisible()
|
||||
})
|
||||
})
|
||||
|
||||
@@ -2,6 +2,7 @@ import { ExecuteIntegrationResponse } from '@/features/chat/types'
|
||||
import { extractVariablesFromText } from '@/features/variables/extractVariablesFromText'
|
||||
import { parseGuessedValueType } from '@/features/variables/parseGuessedValueType'
|
||||
import { parseVariables } from '@/features/variables/parseVariables'
|
||||
import { env } from '@typebot.io/env'
|
||||
import { isDefined } from '@typebot.io/lib'
|
||||
import {
|
||||
ChatwootBlock,
|
||||
@@ -30,7 +31,7 @@ const parseChatwootOpenCode = ({
|
||||
const openChatwoot = `${parseSetUserCode(user, resultId)}
|
||||
window.$chatwoot.setCustomAttributes({
|
||||
typebot_result_url: "${
|
||||
process.env.NEXTAUTH_URL
|
||||
env.NEXTAUTH_URL
|
||||
}/typebots/${typebotId}/results?id=${resultId}",
|
||||
});
|
||||
window.$chatwoot.toggle("open");
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
import { env } from '@typebot.io/env'
|
||||
|
||||
export const defaultTransportOptions = {
|
||||
host: process.env.SMTP_HOST,
|
||||
port: Number(process.env.SMTP_PORT),
|
||||
secure: process.env.SMTP_SECURE ? process.env.SMTP_SECURE === 'true' : false,
|
||||
host: env.SMTP_HOST,
|
||||
port: env.SMTP_PORT,
|
||||
secure: env.SMTP_SECURE,
|
||||
auth: {
|
||||
user: process.env.SMTP_USERNAME,
|
||||
pass: process.env.SMTP_PASSWORD,
|
||||
user: env.SMTP_USERNAME,
|
||||
pass: env.SMTP_PASSWORD,
|
||||
},
|
||||
}
|
||||
|
||||
export const defaultFrom = {
|
||||
name: process.env.SMTP_FROM?.split(' <')[0].replace(/"/g, ''),
|
||||
email: process.env.SMTP_FROM?.match(/<(.*)>/)?.pop(),
|
||||
name: env.NEXT_PUBLIC_SMTP_FROM?.split(' <')[0].replace(/"/g, ''),
|
||||
email: env.NEXT_PUBLIC_SMTP_FROM?.match(/<(.*)>/)?.pop(),
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import { decrypt } from '@typebot.io/lib/api'
|
||||
import { defaultFrom, defaultTransportOptions } from './constants'
|
||||
import { ExecuteIntegrationResponse } from '@/features/chat/types'
|
||||
import { findUniqueVariableValue } from '../../../variables/findUniqueVariableValue'
|
||||
import { env } from '@typebot.io/env'
|
||||
|
||||
export const executeSendEmailBlock = async (
|
||||
state: SessionState,
|
||||
@@ -186,7 +187,7 @@ const getEmailInfo = async (
|
||||
if (credentialsId === 'default')
|
||||
return {
|
||||
host: defaultTransportOptions.host,
|
||||
port: defaultTransportOptions.port,
|
||||
port: defaultTransportOptions.port ?? 22,
|
||||
username: defaultTransportOptions.auth.user,
|
||||
password: defaultTransportOptions.auth.pass,
|
||||
isTlsEnabled: undefined,
|
||||
@@ -226,7 +227,7 @@ const getEmailBody = async ({
|
||||
return {
|
||||
html: render(
|
||||
<DefaultBotNotificationEmail
|
||||
resultsUrl={`${process.env.NEXTAUTH_URL}/typebots/${typebot.id}/results`}
|
||||
resultsUrl={`${env.NEXTAUTH_URL}/typebots/${typebot.id}/results`}
|
||||
answers={omit(answers, 'submittedAt')}
|
||||
/>
|
||||
).html,
|
||||
|
||||
@@ -4,6 +4,7 @@ import { createId } from '@paralleldrive/cuid2'
|
||||
import { importTypebotInDatabase } from '@typebot.io/lib/playwright/databaseActions'
|
||||
import { getTestAsset } from '@/test/utils/playwright'
|
||||
import { SmtpCredentials } from '@typebot.io/schemas'
|
||||
import { env } from '@typebot.io/env'
|
||||
|
||||
export const mockSmtpCredentials: SmtpCredentials['data'] = {
|
||||
from: {
|
||||
@@ -34,7 +35,7 @@ test('should send an email', async ({ page }) => {
|
||||
await page.goto(`/${typebotId}-public`)
|
||||
await page.locator('text=Send email').click()
|
||||
await expect(page.getByText('Email sent!')).toBeVisible()
|
||||
await page.goto(`${process.env.NEXTAUTH_URL}/typebots/${typebotId}/results`)
|
||||
await page.goto(`${env.NEXTAUTH_URL}/typebots/${typebotId}/results`)
|
||||
await page.click('text="See logs"')
|
||||
await expect(page.locator('text="Email successfully sent"')).toBeVisible()
|
||||
})
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { getTestAsset } from '@/test/utils/playwright'
|
||||
import test, { expect } from '@playwright/test'
|
||||
import { env } from '@typebot.io/env'
|
||||
import { importTypebotInDatabase } from '@typebot.io/lib/playwright/databaseActions'
|
||||
|
||||
const typebotId = 'cl0ibhi7s0018n21aarlmg0cm'
|
||||
@@ -33,7 +34,7 @@ test('should work as expected', async ({ page }) => {
|
||||
await page.locator('input').fill('Hello there!')
|
||||
await page.locator('input').press('Enter')
|
||||
await expect(page.getByText('Cheers!')).toBeVisible()
|
||||
await page.goto(`${process.env.NEXTAUTH_URL}/typebots/${typebotId}/results`)
|
||||
await page.goto(`${env.NEXTAUTH_URL}/typebots/${typebotId}/results`)
|
||||
await expect(page.locator('text=Hello there!')).toBeVisible()
|
||||
})
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ import {
|
||||
Variable,
|
||||
VariableWithValue,
|
||||
} from '@typebot.io/schemas'
|
||||
import { env, isDefined, isNotEmpty, omit } from '@typebot.io/lib'
|
||||
import { isDefined, isNotEmpty, omit } from '@typebot.io/lib'
|
||||
import { prefillVariables } from '@/features/variables/prefillVariables'
|
||||
import { injectVariablesFromExistingResult } from '@/features/variables/injectVariablesFromExistingResult'
|
||||
import { deepParseVariables } from '@/features/variables/deepParseVariable'
|
||||
@@ -30,6 +30,7 @@ import { findTypebot } from '../queries/findTypebot'
|
||||
import { findPublicTypebot } from '../queries/findPublicTypebot'
|
||||
import { findResult } from '../queries/findResult'
|
||||
import { createId } from '@paralleldrive/cuid2'
|
||||
import { env } from '@typebot.io/env'
|
||||
|
||||
export const sendMessage = publicProcedure
|
||||
.meta({
|
||||
@@ -257,7 +258,7 @@ const getTypebot = async (
|
||||
userId?: string
|
||||
): Promise<StartTypebot> => {
|
||||
if (typeof typebot !== 'string') return typebot
|
||||
if (isPreview && !userId && env('E2E_TEST') !== 'true')
|
||||
if (isPreview && !userId && !env.NEXT_PUBLIC_E2E_TEST)
|
||||
throw new TRPCError({
|
||||
code: 'UNAUTHORIZED',
|
||||
message:
|
||||
|
||||
@@ -2,6 +2,7 @@ import { getTestAsset } from '@/test/utils/playwright'
|
||||
import test, { expect } from '@playwright/test'
|
||||
import { createId } from '@paralleldrive/cuid2'
|
||||
import { importTypebotInDatabase } from '@typebot.io/lib/playwright/databaseActions'
|
||||
import { env } from '@typebot.io/env'
|
||||
|
||||
test('Big groups should work as expected', async ({ page }) => {
|
||||
const typebotId = createId()
|
||||
@@ -15,7 +16,7 @@ test('Big groups should work as expected', async ({ page }) => {
|
||||
await page.locator('input').fill('26')
|
||||
await page.locator('input').press('Enter')
|
||||
await page.getByRole('button', { name: 'Yes' }).click()
|
||||
await page.goto(`${process.env.NEXTAUTH_URL}/typebots/${typebotId}/results`)
|
||||
await page.goto(`${env.NEXTAUTH_URL}/typebots/${typebotId}/results`)
|
||||
await expect(page.locator('text="Baptiste"')).toBeVisible()
|
||||
await expect(page.locator('text="26"')).toBeVisible()
|
||||
await expect(page.locator('text="Yes"')).toBeVisible()
|
||||
|
||||
@@ -4,7 +4,7 @@ import {
|
||||
User,
|
||||
WorkspaceRole,
|
||||
} from '@typebot.io/prisma'
|
||||
import { env } from '@typebot.io/lib'
|
||||
import { env } from '@typebot.io/env'
|
||||
|
||||
const parseWhereFilter = (
|
||||
typebotIds: string[] | string,
|
||||
@@ -24,8 +24,8 @@ const parseWhereFilter = (
|
||||
{
|
||||
id: typeof typebotIds === 'string' ? typebotIds : { in: typebotIds },
|
||||
workspace:
|
||||
(type === 'read' && user.email === process.env.ADMIN_EMAIL) ||
|
||||
env('E2E_TEST') === 'true'
|
||||
(type === 'read' && user.email === env.ADMIN_EMAIL) ||
|
||||
env.NEXT_PUBLIC_E2E_TEST
|
||||
? undefined
|
||||
: {
|
||||
members: {
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
export const isPlaneteScale = () =>
|
||||
process.env.DATABASE_URL?.includes('pscale_pw')
|
||||
import { env } from '@typebot.io/env'
|
||||
|
||||
export const isPlaneteScale = () => env.DATABASE_URL?.includes('pscale_pw')
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
import { isDefined } from '@typebot.io/lib/utils'
|
||||
import { env } from '@typebot.io/env'
|
||||
|
||||
export const isVercel = () => isDefined(process.env.NEXT_PUBLIC_VERCEL_ENV)
|
||||
export const isVercel = () => env.NEXT_PUBLIC_VERCEL_ENV
|
||||
|
||||
@@ -4,6 +4,7 @@ import { GoogleSheetsCredentials } from '@typebot.io/schemas'
|
||||
import { isDefined } from '@typebot.io/lib'
|
||||
import { decrypt, encrypt } from '@typebot.io/lib/api'
|
||||
import prisma from './prisma'
|
||||
import { env } from '@typebot.io/env'
|
||||
|
||||
export const getAuthenticatedGoogleClient = async (
|
||||
credentialsId: string
|
||||
@@ -18,9 +19,9 @@ export const getAuthenticatedGoogleClient = async (
|
||||
)) as GoogleSheetsCredentials['data']
|
||||
|
||||
const oauth2Client = new OAuth2Client(
|
||||
process.env.GOOGLE_CLIENT_ID,
|
||||
process.env.GOOGLE_CLIENT_SECRET,
|
||||
`${process.env.NEXTAUTH_URL}/api/credentials/google-sheets/callback`
|
||||
env.GOOGLE_CLIENT_ID,
|
||||
env.GOOGLE_CLIENT_SECRET,
|
||||
`${env.NEXTAUTH_URL}/api/credentials/google-sheets/callback`
|
||||
)
|
||||
oauth2Client.setCredentials(data)
|
||||
oauth2Client.on('tokens', updateTokens(credentialsId, data))
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import { env } from '@typebot.io/env'
|
||||
import { PrismaClient } from '@typebot.io/prisma'
|
||||
|
||||
declare const global: { prisma: PrismaClient }
|
||||
let prisma: PrismaClient
|
||||
|
||||
if (process.env.NODE_ENV === 'production') {
|
||||
if (env.NODE_ENV === 'production') {
|
||||
prisma = new PrismaClient()
|
||||
} else {
|
||||
if (!global.prisma) {
|
||||
|
||||
@@ -2,10 +2,11 @@ import { IncomingMessage } from 'http'
|
||||
import { ErrorPage } from '@/components/ErrorPage'
|
||||
import { NotFoundPage } from '@/components/NotFoundPage'
|
||||
import { GetServerSideProps, GetServerSidePropsContext } from 'next'
|
||||
import { env, getViewerUrl, isNotDefined } from '@typebot.io/lib'
|
||||
import { isNotDefined } from '@typebot.io/lib'
|
||||
import prisma from '../lib/prisma'
|
||||
import { TypebotPageProps, TypebotPageV2 } from '@/components/TypebotPageV2'
|
||||
import { TypebotPageV3, TypebotV3PageProps } from '@/components/TypebotPageV3'
|
||||
import { env } from '@typebot.io/env'
|
||||
|
||||
// Browsers that doesn't support ES modules and/or web components
|
||||
const incompatibleBrowsers = [
|
||||
@@ -24,7 +25,7 @@ const incompatibleBrowsers = [
|
||||
]
|
||||
|
||||
const log = (message: string) => {
|
||||
if (process.env.DEBUG !== 'true') return
|
||||
if (!env.DEBUG) return
|
||||
console.log(`[DEBUG] ${message}`)
|
||||
}
|
||||
|
||||
@@ -41,19 +42,18 @@ export const getServerSideProps: GetServerSideProps = async (
|
||||
log(`forwardedHost: ${forwardedHost}`)
|
||||
try {
|
||||
if (!host) return { props: {} }
|
||||
const viewerUrls = (getViewerUrl({ returnAll: true }) ?? '').split(',')
|
||||
const viewerUrls = env.NEXT_PUBLIC_VIEWER_URL
|
||||
log(`viewerUrls: ${viewerUrls}`)
|
||||
const isMatchingViewerUrl =
|
||||
env('E2E_TEST') === 'true'
|
||||
? true
|
||||
: viewerUrls.some(
|
||||
(url) =>
|
||||
host.split(':')[0].includes(url.split('//')[1].split(':')[0]) ||
|
||||
(forwardedHost &&
|
||||
forwardedHost
|
||||
.split(':')[0]
|
||||
.includes(url.split('//')[1].split(':')[0]))
|
||||
)
|
||||
const isMatchingViewerUrl = env.NEXT_PUBLIC_E2E_TEST
|
||||
? true
|
||||
: viewerUrls.some(
|
||||
(url) =>
|
||||
host.split(':')[0].includes(url.split('//')[1].split(':')[0]) ||
|
||||
(forwardedHost &&
|
||||
forwardedHost
|
||||
.split(':')[0]
|
||||
.includes(url.split('//')[1].split(':')[0]))
|
||||
)
|
||||
log(`isMatchingViewerUrl: ${isMatchingViewerUrl}`)
|
||||
const customDomain = `${forwardedHost ?? host}${
|
||||
pathname === '/' ? '' : pathname
|
||||
|
||||
@@ -4,7 +4,7 @@ import { Html, Head, Main, NextScript } from 'next/document'
|
||||
const Document = () => (
|
||||
<Html translate="no">
|
||||
<Head>
|
||||
<script src="/__env.js" />
|
||||
<script src="/__ENV.js" />
|
||||
</Head>
|
||||
<body>
|
||||
<Main />
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { getChatCompletionStream } from '@/features/blocks/integrations/openai/getChatCompletionStream'
|
||||
import { connect } from '@planetscale/database'
|
||||
import { env } from '@typebot.io/env'
|
||||
import { IntegrationBlockType, SessionState } from '@typebot.io/schemas'
|
||||
import { StreamingTextResponse } from 'ai'
|
||||
import { ChatCompletionRequestMessage } from 'openai'
|
||||
@@ -29,7 +30,7 @@ const handler = async (req: Request) => {
|
||||
|
||||
if (!messages) return new Response('No messages provided', { status: 400 })
|
||||
|
||||
const conn = connect({ url: process.env.DATABASE_URL })
|
||||
const conn = connect({ url: env.DATABASE_URL })
|
||||
|
||||
const chatSession = await conn.execute(
|
||||
'select state from ChatSession where id=?',
|
||||
|
||||
@@ -17,22 +17,23 @@ import { render } from '@faire/mjml-react/utils/render'
|
||||
import prisma from '@/lib/prisma'
|
||||
import { saveErrorLog } from '@/features/logs/saveErrorLog'
|
||||
import { saveSuccessLog } from '@/features/logs/saveSuccessLog'
|
||||
import { env } from '@typebot.io/env'
|
||||
|
||||
const cors = initMiddleware(Cors())
|
||||
|
||||
const defaultTransportOptions = {
|
||||
host: process.env.SMTP_HOST,
|
||||
port: Number(process.env.SMTP_PORT),
|
||||
secure: process.env.SMTP_SECURE ? process.env.SMTP_SECURE === 'true' : false,
|
||||
host: env.SMTP_HOST,
|
||||
port: env.SMTP_PORT,
|
||||
secure: env.SMTP_SECURE,
|
||||
auth: {
|
||||
user: process.env.SMTP_USERNAME,
|
||||
pass: process.env.SMTP_PASSWORD,
|
||||
user: env.SMTP_USERNAME,
|
||||
pass: env.SMTP_PASSWORD,
|
||||
},
|
||||
}
|
||||
|
||||
const defaultFrom = {
|
||||
name: process.env.SMTP_FROM?.split(' <')[0].replace(/"/g, ''),
|
||||
email: process.env.SMTP_FROM?.match(/<(.*)>/)?.pop(),
|
||||
name: env.NEXT_PUBLIC_SMTP_FROM?.split(' <')[0].replace(/"/g, ''),
|
||||
email: env.NEXT_PUBLIC_SMTP_FROM?.match(/<(.*)>/)?.pop(),
|
||||
}
|
||||
|
||||
const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||
@@ -159,7 +160,7 @@ const getEmailInfo = async (
|
||||
if (credentialsId === 'default')
|
||||
return {
|
||||
host: defaultTransportOptions.host,
|
||||
port: defaultTransportOptions.port,
|
||||
port: defaultTransportOptions.port as number,
|
||||
username: defaultTransportOptions.auth.user,
|
||||
password: defaultTransportOptions.auth.pass,
|
||||
isTlsEnabled: undefined,
|
||||
@@ -213,7 +214,7 @@ const getEmailBody = async ({
|
||||
return {
|
||||
html: render(
|
||||
<DefaultBotNotificationEmail
|
||||
resultsUrl={`${process.env.NEXTAUTH_URL}/typebots/${typebot.id}/results`}
|
||||
resultsUrl={`${env.NEXTAUTH_URL}/typebots/${typebot.id}/results`}
|
||||
answers={omit(answers, 'submittedAt')}
|
||||
/>
|
||||
).html,
|
||||
|
||||
Reference in New Issue
Block a user