Skip to content

Commit

Permalink
🧑‍💻 Improve env variables type safety and management (#718)
Browse files Browse the repository at this point in the history
Closes #679
  • Loading branch information
baptisteArno authored Aug 28, 2023
1 parent a23a8c4 commit 786e5cb
Show file tree
Hide file tree
Showing 148 changed files with 1,550 additions and 1,293 deletions.
2 changes: 1 addition & 1 deletion .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ Dockerfile
**/node_modules
npm-debug.log
README.md
.next
**/.next
.git
.github
.turbo
Expand Down
7 changes: 4 additions & 3 deletions apps/builder/.env.local.example → .env.dev.example
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
DATABASE_URL=postgresql://postgres:typebot@localhost:5432/typebot
# 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

DATABASE_URL=postgresql://postgres:typebot@localhost:5432/typebot

NEXTAUTH_URL=http://localhost:3000
NEXT_PUBLIC_VIEWER_URL=http://localhost:3001

Expand All @@ -14,5 +16,4 @@ S3_PORT=9000
S3_ENDPOINT=localhost
S3_SSL=false

# For more configuration options check out:
# https://docs.typebot.io/self-hosting/configuration
# For more configuration options check out: https://docs.typebot.io/self-hosting/configuration
10 changes: 10 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# 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=do+UspMmB/rewbX2K/rskFmtgGSSZ8Ta

DATABASE_URL=postgresql://postgres:typebot@typebot-db:5432/typebot

NEXTAUTH_URL=
NEXT_PUBLIC_VIEWER_URL=

ADMIN_EMAIL=
# For more configuration options check out: https://docs.typebot.io/self-hosting/configuration
5 changes: 3 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
node_modules
.next
.env
.env.local
workspace.code-workspace
.DS_Store
Expand Down Expand Up @@ -34,4 +33,6 @@ __env.js
typebotsToFix.json
**/scripts/logs

snapshots
snapshots

.env
6 changes: 1 addition & 5 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,7 @@ These apps are built with awesome web technologies including [Typescript](https:

2. Set up environment variables

Copy [`apps/builder/.env.local.example`](apps/builder/.env.local.example) to `apps/builder/.env.local`

Copy [`apps/viewer/.env.local.example`](apps/viewer/.env.local.example) to `apps/viewer/.env.local`

Copy [`packages/prisma/.env.example` ](packages/prisma/.env.example)to `packages/prisma/.env`
Copy [`.env.dev.example`](./.env.dev.example) to `.env`

Check out the [Configuration guide](https://docs.typebot.io/self-hosting/configuration) if you want to enable more options

Expand Down
14 changes: 7 additions & 7 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ RUN pnpm install
COPY --from=pruner /app/out/full/ .
COPY turbo.json turbo.json

RUN pnpm turbo run build:docker --filter=${SCOPE}...
ENV ENCRYPTION_SECRET=encryption_secret_placeholder123 DATABASE_URL=postgresql://postgres:typebot@typebot-db:5432/typebot NEXTAUTH_URL=http://localhost:3000 NEXT_PUBLIC_VIEWER_URL=http://localhost:3001
RUN pnpm turbo run build --filter=${SCOPE}...

FROM base AS runner
WORKDIR /app
Expand All @@ -32,16 +33,15 @@ RUN apt-get -qy update \
&& apt-get autoremove -yq \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
COPY ./packages/prisma ./packages/prisma
COPY ./apps/${SCOPE}/.env.docker ./apps/${SCOPE}/.env.production
COPY --from=builder /app/node_modules ./node_modules
COPY ./packages/prisma/postgresql ./packages/prisma/postgresql
COPY --from=builder /app/apps/${SCOPE}/public ./apps/${SCOPE}/public
COPY --from=builder --chown=node:node /app/apps/${SCOPE}/.next/standalone ./
COPY --from=builder --chown=node:node /app/apps/${SCOPE}/.next/static ./apps/${SCOPE}/.next/static
RUN pnpm install next-runtime-env prisma
RUN pnpm prisma generate --schema=packages/prisma/postgresql/schema.prisma;

COPY scripts/inject-runtime-env.sh scripts/${SCOPE}-entrypoint.sh ./
RUN chmod +x ./${SCOPE}-entrypoint.sh \
&& chmod +x ./inject-runtime-env.sh
COPY scripts/${SCOPE}-entrypoint.sh ./
RUN chmod +x ./${SCOPE}-entrypoint.sh
ENTRYPOINT ./${SCOPE}-entrypoint.sh

EXPOSE 3000
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ Typebot is an open-source chatbot builder. It allows you to create advanced chat
<a href="https://github.com/baptistearno/typebot.io/stargazers"><img src="https://img.shields.io/github/stars/baptistearno/typebot.io" alt="Github Stars"></a>
</a>
<a href="https://github.com/baptistearno/typebot.io/pulse"><img src="https://img.shields.io/github/commit-activity/m/baptistearno/typebot.io" alt="Commits per month"></a>
<a href="https://docs.typebot.io/self-hosting/docker">
<a href="https://docs.typebot.io/self-hosting/guides/docker">
<img src="https://img.shields.io/docker/pulls/baptistearno/typebot-builder">
</a>
<a href="https://github.com/baptistearno/typebot.io/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-AGPLv3-purple" alt="License">
Expand Down
13 changes: 0 additions & 13 deletions apps/builder/.env.docker

This file was deleted.

1 change: 0 additions & 1 deletion apps/builder/.eslintignore

This file was deleted.

19 changes: 14 additions & 5 deletions apps/builder/next.config.js → apps/builder/next.config.mjs
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
/* eslint-disable @typescript-eslint/no-var-requires */
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 { configureRuntimeEnv } from 'next-runtime-env/build/configure.js'
import { fileURLToPath } from 'url'

const __filename = fileURLToPath(import.meta.url)

const __dirname = dirname(__filename)

configureRuntimeEnv()

/** @type {import('next').NextConfig} */
const nextConfig = {
Expand All @@ -10,13 +18,14 @@ const nextConfig = {
'@typebot.io/lib',
'@typebot.io/schemas',
'@typebot.io/emails',
'@typebot.io/env',
],
i18n: {
defaultLocale: 'en',
locales: ['en', 'fr', 'pt', 'de'],
},
experimental: {
outputFileTracingRoot: path.join(__dirname, '../../'),
outputFileTracingRoot: join(__dirname, '../../'),
},
headers: async () => {
return [
Expand All @@ -38,7 +47,7 @@ const sentryWebpackPluginOptions = {
release: process.env.NEXT_PUBLIC_VERCEL_GIT_COMMIT_SHA + '-builder',
}

module.exports = process.env.NEXT_PUBLIC_SENTRY_DSN
export default process.env.NEXT_PUBLIC_SENTRY_DSN
? withSentryConfig(
{
...nextConfig,
Expand Down
18 changes: 10 additions & 8 deletions apps/builder/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,11 @@
"version": "0.1.0",
"license": "AGPL-3.0-or-later",
"scripts": {
"dev": "cross-env ENVSH_ENV=.env.local bash ../../scripts/inject-runtime-env.sh next dev -p 3000",
"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/builder/.env.docker ENVSH_OUTPUT=./apps/builder/public/__env.js bash scripts/inject-runtime-env.sh",
"start": "next start",
"lint": "next lint",
"test": "pnpm playwright test",
"dev": "dotenv -e ./.env -e ../../.env -- next dev -p 3000",
"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:show-report": "pnpm playwright show-report src/test/reporters"
},
"dependencies": {
Expand All @@ -30,13 +28,15 @@
"@paralleldrive/cuid2": "2.2.1",
"@sentry/nextjs": "7.58.1",
"@stripe/stripe-js": "1.54.1",
"@t3-oss/env-nextjs": "^0.6.0",
"@tanstack/react-query": "^4.29.19",
"@tanstack/react-table": "8.9.3",
"@trpc/client": "10.34.0",
"@trpc/next": "10.34.0",
"@trpc/react-query": "10.34.0",
"@trpc/server": "10.34.0",
"@typebot.io/emails": "workspace:*",
"@typebot.io/env": "workspace:*",
"@typebot.io/nextjs": "workspace:*",
"@udecode/plate-basic-marks": "21.1.5",
"@udecode/plate-common": "^21.1.5",
Expand Down Expand Up @@ -81,6 +81,7 @@
"qs": "6.11.2",
"react": "18.2.0",
"react-dom": "18.2.0",
"sharp": "^0.32.4",
"slate": "0.94.1",
"slate-history": "0.93.0",
"slate-hyperscript": "0.77.0",
Expand Down Expand Up @@ -112,7 +113,8 @@
"@types/qs": "6.9.7",
"@types/react": "18.2.15",
"@types/tinycolor2": "1.4.3",
"dotenv": "16.3.1",
"dotenv-cli": "^7.2.1",
"next-runtime-env": "^1.6.2",
"eslint": "8.44.0",
"eslint-config-custom": "workspace:*",
"superjson": "^1.12.4",
Expand Down
4 changes: 1 addition & 3 deletions apps/builder/sentry.client.config.js
Original file line number Diff line number Diff line change
@@ -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.',
Expand Down
4 changes: 1 addition & 3 deletions apps/builder/sentry.server.config.js
Original file line number Diff line number Diff line change
@@ -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 + '-builder',
})
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@ import { GiphyFetch } from '@giphy/js-fetch-api'
import { Grid } from '@giphy/react-components'
import { GiphyLogo } from '../logos/GiphyLogo'
import React, { useState } from 'react'
import { env, isEmpty } from '@typebot.io/lib'
import { TextInput } from '../inputs'
import { env } from '@typebot.io/env'

type GiphySearchFormProps = {
onSubmit: (url: string) => void
}

const giphyFetch = new GiphyFetch(env('GIPHY_API_KEY') as string)
const giphyFetch = new GiphyFetch(env.NEXT_PUBLIC_GIPHY_API_KEY ?? '')

export const GiphyPicker = ({ onSubmit }: GiphySearchFormProps) => {
const [inputValue, setInputValue] = useState('')
Expand All @@ -21,7 +21,7 @@ export const GiphyPicker = ({ onSubmit }: GiphySearchFormProps) => {
const fetchGifsTrending = (offset: number) =>
giphyFetch.trending({ offset, limit: 10 })

return isEmpty(env('GIPHY_API_KEY')) ? (
return !env.NEXT_PUBLIC_GIPHY_API_KEY ? (
<Text>NEXT_PUBLIC_GIPHY_API_KEY is missing in environment</Text>
) : (
<Stack spacing={4} pt="2">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,17 @@ import {
Text,
useColorModeValue,
} from '@chakra-ui/react'
import { env, isDefined, isEmpty } from '@typebot.io/lib'
import { isDefined } from '@typebot.io/lib'
import { useCallback, useEffect, useRef, useState } from 'react'
import { createApi } from 'unsplash-js'
import { Basic as UnsplashImage } from 'unsplash-js/dist/methods/photos/types'
import { TextInput } from '../inputs'
import { UnsplashLogo } from '../logos/UnsplashLogo'
import { TextLink } from '../TextLink'
import { env } from '@typebot.io/env'

const api = createApi({
accessKey: env('UNSPLASH_ACCESS_KEY') ?? '',
accessKey: env.NEXT_PUBLIC_UNSPLASH_ACCESS_KEY ?? '',
})

type Props = {
Expand Down Expand Up @@ -124,7 +125,7 @@ export const UnsplashPicker = ({ imageSize, onImageSelect }: Props) => {
searchRandomImages()
}, [])

if (isEmpty(env('UNSPLASH_ACCESS_KEY')))
if (!env.NEXT_PUBLIC_UNSPLASH_ACCESS_KEY)
return (
<Text>NEXT_PUBLIC_UNSPLASH_ACCESS_KEY is missing in environment</Text>
)
Expand All @@ -143,9 +144,7 @@ export const UnsplashPicker = ({ imageSize, onImageSelect }: Props) => {
/>
<Link
isExternal
href={`https://unsplash.com/?utm_source=${env(
'UNSPLASH_APP_NAME'
)}&utm_medium=referral`}
href={`https://unsplash.com/?utm_source=${env.NEXT_PUBLIC_UNSPLASH_APP_NAME}&utm_medium=referral`}
>
<UnsplashLogo width="80px" fill={unsplashLogoFillColor} />
</Link>
Expand Down Expand Up @@ -224,9 +223,7 @@ const UnsplashImage = ({ image, onClick }: UnsplashImageProps) => {
<TextLink
fontSize="xs"
isExternal
href={`https://unsplash.com/@${user.username}?utm_source=${env(
'UNSPLASH_APP_NAME'
)}&utm_medium=referral`}
href={`https://unsplash.com/@${user.username}?utm_source=${env.NEXT_PUBLIC_UNSPLASH_APP_NAME}&utm_medium=referral`}
noOfLines={1}
color="white"
>
Expand Down
5 changes: 3 additions & 2 deletions apps/builder/src/components/inputs/AutocompleteInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,15 @@ import {
} from '@chakra-ui/react'
import { useState, useRef, useEffect, ReactNode } from 'react'
import { useDebouncedCallback } from 'use-debounce'
import { env, isDefined } from '@typebot.io/lib'
import { isDefined } from '@typebot.io/lib'
import { useOutsideClick } from '@/hooks/useOutsideClick'
import { useParentModal } from '@/features/graph/providers/ParentModalProvider'
import { VariablesButton } from '@/features/variables/components/VariablesButton'
import { Variable } from '@typebot.io/schemas'
import { injectVariableInText } from '@/features/variables/helpers/injectVariableInTextInput'
import { focusInput } from '@/helpers/focusInput'
import { MoreInfoTooltip } from '../MoreInfoTooltip'
import { env } from '@typebot.io/env'

type Props = {
items: string[]
Expand Down Expand Up @@ -57,7 +58,7 @@ export const AutocompleteInput = ({

const onChange = useDebouncedCallback(
_onChange,
env('E2E_TEST') === 'true' ? 0 : debounceTimeout
env.NEXT_PUBLIC_E2E_TEST ? 0 : debounceTimeout
)

useEffect(() => {
Expand Down
4 changes: 2 additions & 2 deletions apps/builder/src/components/inputs/CodeEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { useEffect, useRef, useState } from 'react'
import { useDebouncedCallback } from 'use-debounce'
import { VariablesButton } from '@/features/variables/components/VariablesButton'
import { Variable } from '@typebot.io/schemas'
import { env } from '@typebot.io/lib'
import { env } from '@typebot.io/env'
import CodeMirror, { ReactCodeMirrorRef } from '@uiw/react-codemirror'
import { tokyoNight } from '@uiw/codemirror-theme-tokyo-night'
import { githubLight } from '@uiw/codemirror-theme-github'
Expand Down Expand Up @@ -53,7 +53,7 @@ export const CodeEditor = ({
_setValue(value)
onChange && onChange(value)
},
env('E2E_TEST') === 'true' ? 0 : debounceTimeout
env.NEXT_PUBLIC_E2E_TEST ? 0 : debounceTimeout
)

const handleVariableSelected = (variable?: Pick<Variable, 'id' | 'name'>) => {
Expand Down
4 changes: 2 additions & 2 deletions apps/builder/src/components/inputs/NumberInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
import { Variable, VariableString } from '@typebot.io/schemas'
import { useEffect, useState } from 'react'
import { useDebouncedCallback } from 'use-debounce'
import { env } from '@typebot.io/lib'
import { env } from '@typebot.io/env'
import { MoreInfoTooltip } from '../MoreInfoTooltip'

type Value<HasVariable> = HasVariable extends true | undefined
Expand Down Expand Up @@ -47,7 +47,7 @@ export const NumberInput = <HasVariable extends boolean>({

const onValueChangeDebounced = useDebouncedCallback(
onValueChange,
env('E2E_TEST') === 'true' ? 0 : debounceTimeout
env.NEXT_PUBLIC_E2E_TEST ? 0 : debounceTimeout
)

useEffect(
Expand Down
Loading

4 comments on commit 786e5cb

@vercel
Copy link

@vercel vercel bot commented on 786e5cb Aug 28, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

docs – ./apps/docs

docs.typebot.io
docs-git-main-typebot-io.vercel.app
docs-typebot-io.vercel.app

@vercel
Copy link

@vercel vercel bot commented on 786e5cb Aug 28, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

builder-v2 – ./apps/builder

builder-v2-git-main-typebot-io.vercel.app
builder-v2-typebot-io.vercel.app
app.typebot.io

@vercel
Copy link

@vercel vercel bot commented on 786e5cb Aug 28, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vercel
Copy link

@vercel vercel bot commented on 786e5cb Aug 28, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

viewer-v2 – ./apps/viewer

psmix.online
receita.info
rhino.cr8.ai
sheep.cr8.ai
snake.cr8.ai
svhm.mprs.in
tiger.cr8.ai
video.cr8.ai
webwhats.pro
yoda.riku.ai
zebra.cr8.ai
alvodelas.com
bemestar.club
bot.krdfy.com
cat.hidden.sg
cgcassets.com
cnvhub.com.br
drapamela.com
facelabko.com
filmylogy.com
goldorayo.com
rabbit.cr8.ai
shop.mexwa.my
signup.cr8.ai
start.taxt.co
theusm.com.br
turkey.cr8.ai
vhpage.cr8.ai
vitamyway.com
whatchat.site
www.wiccom.it
am.nigerias.io
an.nigerias.io
app.yvon.earth
ar.nigerias.io
bot.enreso.org
bot.mail2wa.me
bot.rslabs.pro
bots.bng.tools
bots.bridge.ai
chad.gocto.com
chat.hayuri.id
chat.uprize.hu
chatgpt.lam.ee
chicken.cr8.ai
drayumi.social
gollum.riku.ai
gsbulletin.com
journey.cr8.ai
kopibayane.com
ov2.wpwakanda.com
ov3.wpwakanda.com
pcb.drapamela.com
redeemchatgpt.com
softwarelucra.com
support.triplo.ai
test.eqfeqfeq.com
viewer.typebot.io
welcome.triplo.ai
www.thegymgame.it
zeropendencia.com
1988.bouclidom.com
a.onewebcenter.com
viewer-v2-typebot-io.vercel.app
mdb.assessoria.mauricio.progenbr.com
mdb.evento.autocadastro.progenbr.com
form.shopmercedesbenzsouthorlando.com
mdb.evento.equipeinterna.progenbr.com
bot.studiotecnicoimmobiliaremerelli.it
mdb.assessoria.boaventura.progenbr.com
mdb.assessoria.jtrebesqui.progenbr.com
pesquisa.escolamodacomproposito.com.br
anamnese.clinicaramosodontologia.com.br
gabinete.baleia.formulario.progenbr.com
mdb.assessoria.carreirinha.progenbr.com
chrome-os-inquiry-system.itschromeos.com
mdb.assessoria.paulomarques.progenbr.com
viewer-v2-git-main-typebot-io.vercel.app
main-menu-for-itschromeos.itschromeos.com
mdb.assessoria.qrcode.ademir.progenbr.com
mdb.assessoria.qrcode.arthur.progenbr.com
mdb.assessoria.qrcode.danilo.progenbr.com
mdb.assessoria.qrcode.marcao.progenbr.com
mdb.assessoria.qrcode.marcio.progenbr.com
mdb.assessoria.qrcode.aloisio.progenbr.com
mdb.assessoria.qrcode.girotto.progenbr.com
mdb.assessoria.qrcode.marinho.progenbr.com
mdb.assessoria.qrcode.rodrigo.progenbr.com
mdb.assessoria.carlosalexandre.progenbr.com
mdb.assessoria.qrcode.desideri.progenbr.com
mdb.assessoria.qrcode.fernanda.progenbr.com
mdb.assessoria.qrcode.jbatista.progenbr.com
mdb.assessoria.qrcode.mauricio.progenbr.com
mdb.assessoria.fernanda.regional.progenbr.com
mdb.assessoria.qrcode.boaventura.progenbr.com
mdb.assessoria.qrcode.jtrebesqui.progenbr.com
mdb.assessoria.qrcode.carreirinha.progenbr.com
mdb.assessoria.qrcode.paulomarques.progenbr.com
mdb.assessoria.qrcode.carlosalexandre.progenbr.com
mdb.assessoria.qrcode.fernanda.regional.progenbr.com

Please sign in to comment.