Skip to content

Commit

Permalink
🧑‍💻 Improve env variables type safety and management
Browse files Browse the repository at this point in the history
Closes #679
  • Loading branch information
baptisteArno committed Aug 27, 2023
1 parent a23a8c4 commit 35bad01
Show file tree
Hide file tree
Showing 146 changed files with 1,518 additions and 1,297 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

0 comments on commit 35bad01

Please sign in to comment.