2
0

build: 🏗️ Add docker image and deployment features

This commit is contained in:
Baptiste Arnaud
2022-03-12 07:53:37 +01:00
parent 1dbbc9a251
commit e886d1b079
30 changed files with 2020 additions and 2136 deletions

7
.dockerignore Normal file
View File

@ -0,0 +1,7 @@
Dockerfile
.dockerignore
node_modules
npm-debug.log
README.md
.next
.git

39
Dockerfile Normal file
View File

@ -0,0 +1,39 @@
# https://github.com/vercel/turborepo/issues/215#issuecomment-1027058056
FROM node:16-slim AS base
WORKDIR /app
ARG SCOPE
ENV SCOPE=${SCOPE}
FROM base AS pruner
RUN yarn global add turbo@1.1.5
COPY . .
RUN turbo prune --scope=${SCOPE} --docker
FROM base AS installer
COPY --from=pruner /app/out/json/ .
COPY --from=pruner /app/out/yarn.lock ./yarn.lock
RUN yarn install --frozen-lockfile
FROM base AS builder
COPY --from=installer /app/ .
COPY --from=pruner /app/out/full/ .
RUN apt-get -qy update && apt-get -qy install openssl
RUN yarn turbo run build --scope=${SCOPE} --include-dependencies --no-deps
RUN find . -name node_modules | xargs rm -rf
FROM base AS runner
WORKDIR /app
ENV NODE_ENV production
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs
COPY ./packages/db/prisma ./prisma
COPY --from=installer /app/node_modules ./node_modules
COPY --from=builder /app/apps/${SCOPE}/next.config.js ./
COPY --from=builder /app/apps/${SCOPE}/public ./public
COPY --from=builder /app/apps/${SCOPE}/package.json ./package.json
COPY --from=builder --chown=nextjs:nodejs /app/apps/${SCOPE}/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/apps/${SCOPE}/.next/static ./.next/static
USER nextjs
EXPOSE 3000
ENV PORT 3000
CMD ["node", "server.js"]

View File

@ -1,24 +1,80 @@
<p> <p>
<a href="https://typebot.io/#gh-light-mode-only" target="_blank"> <a href="https://typebot.io/#gh-light-mode-only" target="_blank">
<img src="./.github/readme-illustration-light.png" alt="Typebot illustration"> <img src="./.github/images/readme-illustration-light.png" alt="Typebot illustration">
</a> </a>
<a href="https://typebot.io/#gh-dark-mode-only" target="_blank"> <a href="https://typebot.io/#gh-dark-mode-only" target="_blank">
<img src="./.github/readme-illustration-dark.png" alt="Typebot illustration"> <img src="./.github/images/readme-illustration-dark.png" alt="Typebot illustration">
</a> </a>
</p> </p>
Typebot is an open-source alternative to Landbot. It allows you to create conversational apps (Lead qualification, Product launch, User onboarding, Customer support), embed them anywhere on your web apps, and collect results in real-time. Typebot is an open-source alternative to Landbot. It allows you to create conversational apps (Lead qualification, Product launch, User onboarding, Customer support), embed them anywhere on your web apps, and collect results in real-time.
## Features
- Text, image, video bubble messages
- Text, URL, email, phone number, date input fields
- Native integrations including Google Sheets, Webhooks, Send email (more to come)
- Conditional branching, URL redirections
- Beautiful animations
- Theme is 100% customizable
- Embed as a container, popup, or chat bubble with a native JS library
- In-depth analytics
#### VIDEO
## Getting started with Typebot ## Getting started with Typebot
The easiest way to get started with Typebot is with [the official managed service in the Cloud](https://app.typebot.io). It takes 1 minute to try out the builder for free. You'll have high availability, backups, security, and maintenance all managed for you by me, @baptisteArno, Typebot's founder. The easiest way to get started with Typebot is with [the official managed service in the Cloud](https://app.typebot.io).
It takes 1 minute to try out the builder for free. You'll have high availability, backups, security, and maintenance all managed for you by me, Baptiste Arnaud, Typebot's founder.
That's also the best way to support my work, open-source software, and you'll get great service! That's also the best way to support my work, open-source software, and you'll get great service!
## Self-hosting ## Self-hosting
Interested in self-hosting Typebot on your server? Take a look at our self-hosting installation instructions. Interested in self-hosting Typebot on your server? Take a look at the [self-hosting installation instructions](https://docs.typebot.io/self-hosting).
## Local setup
1. Clone the repo
```sh
git clone https://github.com/baptisteArno/typebot.io.git
```
2. Set up environment variables
Copy `apps/builder/.env.local.example` to `apps/builder/.env.local`
Copy `apps/viewer/.env.local.example` to `apps/viewer/.env.local`
3. Install packages and start the applications.
```sh
yarn
```
4. Make sure your have [docker-compose](https://docs.docker.com/compose/install/) installed
5. Start the applications:
```sh
yarn dev
```
Builder will be available at `http://localhost:3000`
Viewer will be available at `http://localhost:3001`
Database inspector will be available at `http://localhost:5555`
By default, you can easily authenticate in the builder using the "Github Sign In" button.
## Technology ## Technology
Typebot is a monorepo powered by TurboRepo. Apps are built with state-of-the-art web technologies. These include Typescript, Next.js, Prisma (PostgresDB), Chakra UI, TailwindCSS. Typebot is a Monorepo powered by [Turborepo](https://turborepo.org/). It is composed of 2 main applications:
- the builder, where you build your typebots
- the viewer, where your user answer the typebot
These apps are built with awesome web technologies including [Typescript](https://www.typescriptlang.org/), [Next.js](https://nextjs.org/), [Prisma](https://www.prisma.io/), [Chakra UI](https://chakra-ui.com/), [Tailwind CSS](https://tailwindcss.com/).

View File

@ -50,6 +50,9 @@ NEXT_PUBLIC_VIEWER_HOST=http://localhost:3001
# (Optional) Error tracking with Sentry # (Optional) Error tracking with Sentry
NEXT_PUBLIC_SENTRY_DSN= NEXT_PUBLIC_SENTRY_DSN=
SENTRY_AUTH_TOKEN=
SENTRY_PROJECT=
SENTRY_ORG=
# Vercel # Vercel
VERCEL_TOKEN= VERCEL_TOKEN=

View File

@ -8,7 +8,6 @@ module.exports = {
'plugin:@typescript-eslint/recommended', 'plugin:@typescript-eslint/recommended',
'plugin:react/recommended', 'plugin:react/recommended',
'next/core-web-vitals', 'next/core-web-vitals',
'prettier',
], ],
parser: '@typescript-eslint/parser', parser: '@typescript-eslint/parser',
parserOptions: { parserOptions: {
@ -23,10 +22,9 @@ module.exports = {
version: 'detect', // Tells eslint-plugin-react to automatically detect the version of React to use version: 'detect', // Tells eslint-plugin-react to automatically detect the version of React to use
}, },
}, },
plugins: ['prettier', 'react', '@typescript-eslint'], plugins: ['react', '@typescript-eslint'],
rules: { rules: {
'react/no-unescaped-entities': [0], 'react/no-unescaped-entities': [0],
'prettier/prettier': 'error',
'react/display-name': [0], 'react/display-name': [0],
}, },
} }

View File

@ -2,7 +2,9 @@
const { withSentryConfig } = require('@sentry/nextjs') const { withSentryConfig } = require('@sentry/nextjs')
const moduleExports = { const moduleExports = {
// Your existing module.exports experimental: {
outputStandalone: true,
},
} }
const sentryWebpackPluginOptions = { const sentryWebpackPluginOptions = {
@ -11,4 +13,6 @@ const sentryWebpackPluginOptions = {
// https://github.com/getsentry/sentry-webpack-plugin#options. // https://github.com/getsentry/sentry-webpack-plugin#options.
} }
module.exports = withSentryConfig(moduleExports, sentryWebpackPluginOptions) module.exports = process.env.SENTRY_AUTH_TOKEN
? withSentryConfig(moduleExports, sentryWebpackPluginOptions)
: moduleExports

View File

@ -3,6 +3,7 @@
"version": "0.1.0", "version": "0.1.0",
"license": "AGPL-3.0-or-later", "license": "AGPL-3.0-or-later",
"scripts": { "scripts": {
"dx": "yarn dev",
"dev": "next dev -p 3000", "dev": "next dev -p 3000",
"build": "next build", "build": "next build",
"start": "next start", "start": "next start",
@ -14,29 +15,29 @@
"workerDirectory": "public" "workerDirectory": "public"
}, },
"dependencies": { "dependencies": {
"@chakra-ui/css-reset": "^1.1.2", "@chakra-ui/css-reset": "^1.1.3",
"@chakra-ui/react": "^1.8.3", "@chakra-ui/react": "^1.8.6",
"@codemirror/basic-setup": "^0.19.1", "@codemirror/basic-setup": "^0.19.1",
"@codemirror/lang-css": "^0.19.3", "@codemirror/lang-css": "^0.19.3",
"@codemirror/lang-html": "^0.19.4", "@codemirror/lang-html": "^0.19.4",
"@codemirror/lang-javascript": "^0.19.7", "@codemirror/lang-javascript": "^0.19.7",
"@codemirror/lang-json": "^0.19.1", "@codemirror/lang-json": "^0.19.2",
"@codemirror/text": "^0.19.6", "@codemirror/text": "^0.19.6",
"@emotion/react": "^11.7.1", "@emotion/react": "^11.8.2",
"@emotion/styled": "^11.6.0", "@emotion/styled": "^11.8.1",
"@giphy/js-fetch-api": "^4.1.2", "@giphy/js-fetch-api": "^4.1.2",
"@giphy/js-types": "^4.1.0", "@giphy/js-types": "^4.1.0",
"@giphy/react-components": "^5.4.0", "@giphy/react-components": "^5.6.1",
"@googleapis/drive": "^2.2.0", "@googleapis/drive": "^2.3.0",
"@next-auth/prisma-adapter": "1.0.1", "@next-auth/prisma-adapter": "1.0.1",
"@sentry/nextjs": "^6.17.7", "@sentry/nextjs": "^6.18.2",
"@stripe/stripe-js": "^1.22.0", "@stripe/stripe-js": "^1.24.0",
"@udecode/plate-basic-marks": "^10.0.0", "@udecode/plate-basic-marks": "^10.2.2",
"@udecode/plate-common": "^7.0.2", "@udecode/plate-common": "^7.0.2",
"@udecode/plate-core": "^10.0.0", "@udecode/plate-core": "^10.2.2",
"@udecode/plate-link": "^10.0.0", "@udecode/plate-link": "^10.2.2",
"@udecode/plate-ui-link": "^10.0.0", "@udecode/plate-ui-link": "^10.2.2",
"@udecode/plate-ui-toolbar": "^10.0.0", "@udecode/plate-ui-toolbar": "^10.2.2",
"bot-engine": "*", "bot-engine": "*",
"browser-image-compression": "^1.0.17", "browser-image-compression": "^1.0.17",
"cuid": "^2.1.8", "cuid": "^2.1.8",
@ -45,20 +46,20 @@
"dequal": "^2.0.2", "dequal": "^2.0.2",
"focus-visible": "^5.2.0", "focus-visible": "^5.2.0",
"framer-motion": "^4", "framer-motion": "^4",
"google-auth-library": "^7.12.0", "google-auth-library": "^7.14.0",
"google-spreadsheet": "^3.2.0", "google-spreadsheet": "^3.2.0",
"got": "^12.0.1", "got": "^12.0.1",
"htmlparser2": "^7.2.0", "htmlparser2": "^7.2.0",
"immer": "^9.0.12", "immer": "^9.0.12",
"js-video-url-parser": "^0.5.1", "js-video-url-parser": "^0.5.1",
"jsonwebtoken": "^8.5.1", "jsonwebtoken": "^8.5.1",
"kbar": "^0.1.0-beta.27", "kbar": "^0.1.0-beta.30",
"micro": "^9.3.4", "micro": "^9.3.4",
"micro-cors": "^0.1.1", "micro-cors": "^0.1.1",
"minio": "^7.0.26", "minio": "^7.0.26",
"models": "*", "models": "*",
"msw": "^0.36.8", "msw": "^0.36.8",
"next": "^12.0.10", "next": "^12.1.0",
"next-auth": "4.2.1", "next-auth": "4.2.1",
"nodemailer": "^6.7.2", "nodemailer": "^6.7.2",
"nprogress": "^0.2.0", "nprogress": "^0.2.0",
@ -69,40 +70,39 @@
"react-draggable": "^4.4.4", "react-draggable": "^4.4.4",
"react-table": "^7.7.0", "react-table": "^7.7.0",
"short-uuid": "^4.2.0", "short-uuid": "^4.2.0",
"slate": "^0.72.8", "slate": "^0.73.1",
"slate-history": "^0.66.0", "slate-history": "^0.66.0",
"slate-hyperscript": "^0.67.0", "slate-hyperscript": "^0.67.0",
"slate-react": "^0.72.9", "slate-react": "^0.74.2",
"stripe": "^8.202.0", "stripe": "^8.209.0",
"styled-components": "^5.3.3", "styled-components": "^5.3.3",
"svg-round-corners": "^0.3.0", "svg-round-corners": "^0.3.0",
"swr": "^1.2.1", "swr": "^1.2.2",
"typebot-js": "^2.1.0", "typebot-js": "*",
"use-debounce": "^7.0.1", "use-debounce": "^7.0.1",
"use-immer": "^0.6.0", "use-immer": "^0.6.0",
"utils": "*" "utils": "*",
"prettier": "^2.5.1"
}, },
"devDependencies": { "devDependencies": {
"@playwright/test": "^1.19.0", "@types/prettier": "^2.4.4",
"@playwright/test": "^1.19.2",
"@types/google-spreadsheet": "^3.1.5", "@types/google-spreadsheet": "^3.1.5",
"@types/jsonwebtoken": "8.5.1", "@types/jsonwebtoken": "8.5.8",
"@types/micro-cors": "^0.1.2", "@types/micro-cors": "^0.1.2",
"@types/minio": "^7.0.12", "@types/minio": "^7.0.12",
"@types/node": "^17.0.17", "@types/node": "^17.0.21",
"@types/nodemailer": "^6.4.4",
"@types/nprogress": "^0.2.0", "@types/nprogress": "^0.2.0",
"@types/papaparse": "^5.3.2", "@types/papaparse": "^5.3.2",
"@types/prettier": "^2.4.4",
"@types/qs": "^6.9.7", "@types/qs": "^6.9.7",
"@types/react": "^17.0.39", "@types/react": "^17.0.40",
"@types/react-table": "^7.7.9", "@types/react-table": "^7.7.9",
"@typescript-eslint/eslint-plugin": "^5.11.0", "@typescript-eslint/eslint-plugin": "^5.14.0",
"dotenv": "^16.0.0", "dotenv": "^16.0.0",
"eslint": "<8.0.0", "eslint": "<8.0.0",
"eslint-config-next": "12.0.10", "eslint-config-next": "12.1.0",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-prettier": "^4.0.0",
"next-transpile-modules": "^9.0.0", "next-transpile-modules": "^9.0.0",
"prettier": "^2.5.1", "typescript": "^4.6.2"
"typescript": "^4.5.5"
} }
} }

View File

@ -1,5 +1,5 @@
// Forked from https://github.com/nextauthjs/adapters/blob/main/packages/prisma/src/index.ts // Forked from https://github.com/nextauthjs/adapters/blob/main/packages/prisma/src/index.ts
import type { PrismaClient, Prisma, Invitation } from 'db' import { PrismaClient, Prisma, Invitation, Plan } from 'db'
import { randomUUID } from 'crypto' import { randomUUID } from 'crypto'
import type { Adapter, AdapterUser } from 'next-auth/adapters' import type { Adapter, AdapterUser } from 'next-auth/adapters'
import cuid from 'cuid' import cuid from 'cuid'
@ -12,7 +12,12 @@ export function CustomAdapter(p: PrismaClient): Adapter {
where: { email: user.email }, where: { email: user.email },
}) })
const createdUser = await p.user.create({ const createdUser = await p.user.create({
data: { ...data, id: user.id, apiToken: randomUUID() }, data: {
...data,
id: user.id,
apiToken: randomUUID(),
plan: process.env.ADMIN_EMAIL === data.email ? Plan.PRO : Plan.FREE,
},
}) })
if (invitations.length > 0) if (invitations.length > 0)
await convertInvitationsToCollaborations(p, user, invitations) await convertInvitationsToCollaborations(p, user, invitations)

View File

@ -5,8 +5,6 @@ import { NextApiRequest, NextApiResponse } from 'next'
import { getAuthenticatedUser } from 'services/api/utils' import { getAuthenticatedUser } from 'services/api/utils'
import { methodNotAllowed, notAuthenticated } from 'utils' import { methodNotAllowed, notAuthenticated } from 'utils'
const adminEmail = 'contact@baptiste-arnaud.fr'
const handler = async (req: NextApiRequest, res: NextApiResponse) => { const handler = async (req: NextApiRequest, res: NextApiResponse) => {
const user = await getAuthenticatedUser(req) const user = await getAuthenticatedUser(req)
if (!user) return notAuthenticated(res) if (!user) return notAuthenticated(res)
@ -81,7 +79,7 @@ const parseWhereFilter = (
{ {
id: typebotId, id: typebotId,
ownerId: ownerId:
(type === 'read' && user.email === adminEmail) || (type === 'read' && user.email === process.env.ADMIN_EMAIL) ||
process.env.NEXT_PUBLIC_E2E_TEST process.env.NEXT_PUBLIC_E2E_TEST
? undefined ? undefined
: user.id, : user.id,

View File

@ -5,8 +5,6 @@ import { getAuthenticatedUser } from 'services/api/utils'
import { isFreePlan } from 'services/user/user' import { isFreePlan } from 'services/user/user'
import { methodNotAllowed, notAuthenticated } from 'utils' import { methodNotAllowed, notAuthenticated } from 'utils'
const adminEmail = 'contact@baptiste-arnaud.fr'
const handler = async (req: NextApiRequest, res: NextApiResponse) => { const handler = async (req: NextApiRequest, res: NextApiResponse) => {
const user = await getAuthenticatedUser(req) const user = await getAuthenticatedUser(req)
if (!user) return notAuthenticated(res) if (!user) return notAuthenticated(res)
@ -24,7 +22,9 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => {
: undefined, : undefined,
where: { where: {
typebotId, typebotId,
typebot: { ownerId: user.email === adminEmail ? undefined : user.id }, typebot: {
ownerId: user.email === process.env.ADMIN_EMAIL ? undefined : user.id,
},
answers: { some: {} }, answers: { some: {} },
isCompleted: isFreePlan(user) ? true : undefined, isCompleted: isFreePlan(user) ? true : undefined,
}, },

View File

@ -0,0 +1,4 @@
{
"label": "Self hosting",
"position": 6
}

View File

@ -0,0 +1,53 @@
# Self hosting
:::note
The easiest way to get started with Typebot is with [our official managed service in the Cloud](https://app.typebot.io). It takes 1 minute to create your free account. You'll have high availability, backups, security, and maintenance all managed for you by Typebot. The section below is for self-hosting Typebot on your server and managing your infrastructure.
:::
Typebot is composed of 2 Next.js applications you need to deploy:
- the builder, where you build your typebots
- the viewer, where your user answer the typebot
They are connected to a Database and an S3 bucket
## S3
Paste this bucket policy after replacing `<BUCKET_NAME>` with your bucket name:
```json
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PublicRead",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::<BUCKET_NAME>/public/*"
}
]
}
```
CORS config:
```json
[
{
"AllowedHeaders": ["*"],
"AllowedMethods": ["PUT", "POST"],
"AllowedOrigins": ["*"],
"ExposeHeaders": ["ETag"]
}
]
```
```
S3_ACCESS_KEY=minio
S3_SECRET_KEY=minio123
S3_BUCKET=typebot
S3_PORT=9000
S3_ENDPOINT=localhost
S3_SSL=false
```

View File

@ -15,9 +15,9 @@
"update-search": "docker run -it --rm --env-file=.env -e \"CONFIG=$(cat /Users/baptistearnaud/Dev/typebot-io/docs/docsearch-scrapper-config.json | jq -r tostring)\" algolia/docsearch-scraper" "update-search": "docker run -it --rm --env-file=.env -e \"CONFIG=$(cat /Users/baptistearnaud/Dev/typebot-io/docs/docsearch-scrapper-config.json | jq -r tostring)\" algolia/docsearch-scraper"
}, },
"dependencies": { "dependencies": {
"@docusaurus/core": "2.0.0-beta.15", "@docusaurus/core": "2.0.0-beta.17",
"@docusaurus/preset-classic": "2.0.0-beta.15", "@docusaurus/preset-classic": "2.0.0-beta.17",
"@docusaurus/theme-search-algolia": "^2.0.0-beta.15", "@docusaurus/theme-search-algolia": "^2.0.0-beta.17",
"@mdx-js/react": "^1.6.21", "@mdx-js/react": "^1.6.21",
"@svgr/webpack": "^5.5.0", "@svgr/webpack": "^5.5.0",
"clsx": "^1.1.1", "clsx": "^1.1.1",

View File

@ -8,28 +8,28 @@
"analyze": "cross-env ANALYZE=true next build" "analyze": "cross-env ANALYZE=true next build"
}, },
"dependencies": { "dependencies": {
"@chakra-ui/react": "^1.8.3", "@chakra-ui/react": "^1.8.6",
"@emotion/react": "^11.7.1", "@emotion/react": "^11.8.2",
"@emotion/styled": "^11.6.0", "@emotion/styled": "^11.8.1",
"focus-visible": "^5.2.0", "focus-visible": "^5.2.0",
"framer-motion": "^4", "framer-motion": "^4",
"keen-slider": "^6.6.3", "keen-slider": "^6.6.4",
"next": "^12.0.10", "next": "^12.1.0",
"notion-blocks-chakra-ui": "^0.0.15", "notion-blocks-chakra-ui": "^0.0.15",
"posthog-js": "1.17.8", "posthog-js": "1.17.9",
"react": "17.0.2", "react": "17.0.2",
"react-dom": "17.0.2", "react-dom": "17.0.2",
"typebot-js": "^2.0.21", "typebot-js": "^2.1.3",
"@notionhq/client": "^0.3.1" "@notionhq/client": "^0.3.1"
}, },
"devDependencies": { "devDependencies": {
"@next/bundle-analyzer": "^12.0.10", "@next/bundle-analyzer": "^12.1.0",
"@types/node": "^17.0.17", "@types/node": "^17.0.21",
"@types/react": "^17.0.39", "@types/react": "^17.0.40",
"autoprefixer": "^10.4.2", "autoprefixer": "^10.4.2",
"cross-env": "^7.0.3", "cross-env": "^7.0.3",
"eslint": "<8.0.0", "eslint": "<8.0.0",
"prettier": "^2.5.1", "prettier": "^2.5.1",
"typescript": "^4.5.5" "typescript": "^4.6.2"
} }
} }

View File

@ -8,7 +8,6 @@ module.exports = {
'plugin:@typescript-eslint/recommended', 'plugin:@typescript-eslint/recommended',
'plugin:react/recommended', 'plugin:react/recommended',
'next/core-web-vitals', 'next/core-web-vitals',
'prettier',
], ],
parser: '@typescript-eslint/parser', parser: '@typescript-eslint/parser',
parserOptions: { parserOptions: {
@ -23,9 +22,8 @@ module.exports = {
version: 'detect', // Tells eslint-plugin-react to automatically detect the version of React to use version: 'detect', // Tells eslint-plugin-react to automatically detect the version of React to use
}, },
}, },
plugins: ['prettier', 'react', '@typescript-eslint'], plugins: ['react', '@typescript-eslint'],
rules: { rules: {
'react/no-unescaped-entities': [0], 'react/no-unescaped-entities': [0],
'prettier/prettier': 'error',
}, },
} }

View File

@ -7,7 +7,9 @@
const { withSentryConfig } = require('@sentry/nextjs') const { withSentryConfig } = require('@sentry/nextjs')
const moduleExports = { const moduleExports = {
// Your existing module.exports experimental: {
outputStandalone: true,
},
} }
const sentryWebpackPluginOptions = { const sentryWebpackPluginOptions = {
@ -22,6 +24,6 @@ const sentryWebpackPluginOptions = {
// https://github.com/getsentry/sentry-webpack-plugin#options. // https://github.com/getsentry/sentry-webpack-plugin#options.
} }
// Make sure adding Sentry options is the last code to run before exporting, to module.exports = process.env.SENTRY_AUTH_TOKEN
// ensure that your source maps include changes from all other Webpack plugins ? withSentryConfig(moduleExports, sentryWebpackPluginOptions)
module.exports = withSentryConfig(moduleExports, sentryWebpackPluginOptions) : moduleExports

View File

@ -3,6 +3,7 @@
"license": "AGPL-3.0-or-later", "license": "AGPL-3.0-or-later",
"version": "0.1.0", "version": "0.1.0",
"scripts": { "scripts": {
"dx": "yarn dev",
"dev": "next dev -p 3001", "dev": "next dev -p 3001",
"build": "next build", "build": "next build",
"start": "next start", "start": "next start",
@ -11,31 +12,32 @@
"test:open": "PWDEBUG=1 yarn playwright test" "test:open": "PWDEBUG=1 yarn playwright test"
}, },
"dependencies": { "dependencies": {
"@sentry/nextjs": "^6.17.8", "@sentry/nextjs": "^6.18.2",
"bot-engine": "*", "bot-engine": "*",
"cors": "^2.8.5", "cors": "^2.8.5",
"db": "*", "db": "*",
"google-spreadsheet": "^3.2.0", "google-spreadsheet": "^3.2.0",
"got": "^12.0.1",
"qs": "^6.10.3",
"models": "*", "models": "*",
"next": "^12.0.10", "next": "^12.1.0",
"nodemailer": "^6.7.2", "nodemailer": "^6.7.2",
"react": "^17.0.2", "react": "^17.0.2",
"react-dom": "^17.0.2", "react-dom": "^17.0.2",
"utils": "*" "utils": "*"
}, },
"devDependencies": { "devDependencies": {
"@playwright/test": "^1.19.2",
"@types/cors": "^2.8.12", "@types/cors": "^2.8.12",
"@types/google-spreadsheet": "^3.1.5", "@types/google-spreadsheet": "^3.1.5",
"@types/node": "^17.0.17", "@types/node": "^17.0.21",
"@types/nodemailer": "^6.4.4", "@types/nodemailer": "^6.4.4",
"@types/react": "^17.0.39", "@types/react": "^17.0.40",
"@typescript-eslint/eslint-plugin": "^5.11.0", "@types/qs": "^6.9.7",
"@typescript-eslint/eslint-plugin": "^5.14.0",
"eslint": "<8.0.0", "eslint": "<8.0.0",
"eslint-config-next": "12.0.10", "eslint-config-next": "12.1.0",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-prettier": "^4.0.0",
"next-transpile-modules": "^9.0.0", "next-transpile-modules": "^9.0.0",
"prettier": "^2.5.1", "typescript": "^4.6.2"
"typescript": "^4.5.5"
} }
} }

38
docker-compose.dev.yml Normal file
View File

@ -0,0 +1,38 @@
version: '3.6'
services:
postgres:
image: postgres:13
ports:
- '5432:5432'
restart: always
volumes:
- db_data:/var/lib/postgresql/data
environment:
POSTGRES_DB: 'typebot'
POSTGRES_PASSWORD: 'typebot'
minio:
image: minio/minio
command: server /data
ports:
- '9000:9000'
environment:
MINIO_ROOT_USER: minio
MINIO_ROOT_PASSWORD: minio123
volumes:
- s3_data:/data
# This service just make sure a bucket with the right policies is created
createbuckets:
image: minio/mc
depends_on:
- minio
entrypoint: >
/bin/sh -c "
sleep 10;
/usr/bin/mc config host add minio http://minio:9000 minio minio123;
/usr/bin/mc mb minio/typebot;
/usr/bin/mc policy set public minio/typebot/public;
exit 0;
"
volumes:
db_data:
s3_data:

View File

@ -1,27 +1,37 @@
version: '3.6' version: '3.9'
services: services:
postgres: typebot_db:
image: postgres:13 image: postgres:13
ports:
- '5432:5432'
restart: always restart: always
volumes: volumes:
- db_data:/var/lib/postgresql/data - db_data:/var/lib/postgresql/data
environment: environment:
POSTGRES_DB: 'typebot' - POSTGRES_DB=typebot
POSTGRES_PASSWORD: '' - POSTGRES_PASSWORD=typebot
POSTGRES_HOST_AUTH_METHOD: trust typebot_builder:
minio: depends_on:
image: quay.io/minio/minio - typebot_db
command: server /data --console-address ":9001" build:
context: .
args:
- SCOPE=builder
ports: ports:
- '9000:9000' - '8080:3000'
- '9001:9001' env_file:
environment: - typebot-config.env
MINIO_ROOT_USER: minio command: 'sleep 10 && npx prisma migrate deploy && node server.js'
MINIO_ROOT_PASSWORD: minio123 typebot_viewer:
volumes: depends_on:
- s3_data:/data - typebot_db
restart: always
build:
context: .
args:
- SCOPE=viewer
ports:
- '8081:3000'
env_file:
- typebot-config.env
volumes: volumes:
db_data: db_data:
s3_data: s3_data:

View File

@ -7,16 +7,18 @@
"apps/*" "apps/*"
], ],
"scripts": { "scripts": {
"docker:up": "docker-compose up -d", "docker:up": "docker compose -f docker-compose.dev.yml up -d",
"db:nuke": "docker-compose down --volumes --remove-orphans", "docker:nuke": "docker compose -f docker-compose.dev.yml down --volumes --remove-orphans",
"dev": "yarn docker:up && turbo run dev --parallel", "dev:prepare": "turbo run build --scope=bot-engine --no-deps --include-dependencies",
"dev": "yarn docker:up && yarn dev:prepare && turbo run dx --parallel",
"dev:mocking": "yarn docker:up && NEXT_PUBLIC_E2E_TEST=enabled turbo run dev --parallel", "dev:mocking": "yarn docker:up && NEXT_PUBLIC_E2E_TEST=enabled turbo run dev --parallel",
"build": "yarn docker:up && turbo run build", "build": "yarn docker:up && turbo run build",
"test:builder": "cd apps/builder && yarn test", "test:builder": "cd apps/builder && yarn test",
"lint": "turbo run lint" "lint": "turbo run lint",
"db:migrate": "yarn workspace db migration:deploy"
}, },
"devDependencies": { "devDependencies": {
"turbo": "^1.1.5" "turbo": "^1.1.6"
}, },
"packageManager": "yarn@1.22.17" "packageManager": "yarn@1.22.17"
} }

View File

@ -11,41 +11,42 @@
"qs": "^6.10.3", "qs": "^6.10.3",
"react-frame-component": "5.2.2-alpha.1", "react-frame-component": "5.2.2-alpha.1",
"react-phone-number-input": "^3.1.46", "react-phone-number-input": "^3.1.46",
"react-scroll": "^1.8.4", "react-scroll": "^1.8.6",
"react-transition-group": "^4.4.2", "react-transition-group": "^4.4.2",
"utils": "*" "utils": "*"
}, },
"devDependencies": { "devDependencies": {
"@rollup/plugin-commonjs": "^21.0.1", "@rollup/plugin-commonjs": "^21.0.2",
"@rollup/plugin-json": "^4.1.0", "@rollup/plugin-json": "^4.1.0",
"@rollup/plugin-node-resolve": "^13.1.3", "@rollup/plugin-node-resolve": "^13.1.3",
"@rollup/plugin-typescript": "^8.3.0", "@rollup/plugin-typescript": "^8.3.1",
"@types/react": "^17.0.39", "@types/react": "^17.0.40",
"@types/react-phone-number-input": "^3.0.13", "@types/react-phone-number-input": "^3.0.13",
"@types/react-scroll": "^1.8.3", "@types/react-scroll": "^1.8.3",
"@types/react-transition-group": "^4.4.4", "@types/react-transition-group": "^4.4.4",
"autoprefixer": "^10.4.2", "autoprefixer": "^10.4.2",
"npm-run-all": "^4.1.5", "npm-run-all": "^4.1.5",
"postcss": "^8.4.6", "postcss": "^8.4.8",
"rollup": "^2.70.0", "rollup": "^2.70.0",
"rollup-plugin-dts": "^4.1.0", "rollup-plugin-dts": "^4.2.0",
"rollup-plugin-peer-deps-external": "^2.2.4", "rollup-plugin-peer-deps-external": "^2.2.4",
"rollup-plugin-postcss": "^4.0.2", "rollup-plugin-postcss": "^4.0.2",
"rollup-plugin-terser": "^7.0.2", "rollup-plugin-terser": "^7.0.2",
"tailwindcss": "^3.0.22", "tailwindcss": "^3.0.23",
"typescript": "^4.5.5", "typescript": "^4.6.2",
"@typescript-eslint/eslint-plugin": "^5.11.0", "@typescript-eslint/eslint-plugin": "^5.14.0",
"eslint": "<8.0.0", "eslint": "<8.0.0",
"eslint-config-next": "12.0.10", "eslint-config-next": "12.1.0",
"eslint-config-prettier": "^8.3.0", "eslint-config-prettier": "^8.5.0",
"eslint-plugin-prettier": "^4.0.0" "eslint-plugin-prettier": "^4.0.0",
"tslib": "^2.3.1"
}, },
"peerDependencies": { "peerDependencies": {
"react": "^17.0.2" "react": "^17.0.2"
}, },
"scripts": { "scripts": {
"build": "yarn rollup -c", "build": "yarn rollup -c",
"dev": "yarn rollup -c --watch", "dx": "yarn rollup -c --watch",
"lint": "eslint --fix -c ./.eslintrc.js \"./src/**/*.ts*\"" "lint": "eslint --fix -c ./.eslintrc.js \"./src/**/*.ts*\""
} }
} }

View File

@ -28,7 +28,7 @@ export default [
], ],
plugins: [ plugins: [
peerDepsExternal(), peerDepsExternal(),
resolve(), resolve({ preferBuiltins: true }),
json(), json(),
commonjs(), commonjs(),
typescript({ tsconfig: './tsconfig.json' }), typescript({ tsconfig: './tsconfig.json' }),

View File

@ -5,21 +5,22 @@
"main": "./index.ts", "main": "./index.ts",
"types": "./index.ts", "types": "./index.ts",
"devDependencies": { "devDependencies": {
"prisma": "^3.9.2", "prisma": "^3.10.0",
"ts-node": "^10.5.0", "ts-node": "^10.7.0",
"typescript": "^4.5.5", "typescript": "^4.6.2",
"dotenv-cli": "5.0.0" "dotenv-cli": "5.0.0"
}, },
"dependencies": { "dependencies": {
"@prisma/client": "^3.9.2" "@prisma/client": "^3.10.0"
}, },
"scripts": { "scripts": {
"dev": "dotenv -e ../../apps/builder/.env.local yarn prisma db push && yarn start:sutdio ", "dx": "dotenv -e ../../apps/builder/.env.local prisma db push && yarn start:sutdio ",
"start:sutdio": "dotenv -e ../../apps/builder/.env.local -v BROWSER=none yarn prisma studio", "build": "yarn generate:schema",
"build": "DATABASE_URL=$MIGRATION_DATABASE_URL yarn migration:deploy", "start:sutdio": "dotenv -e ../../apps/builder/.env.local -v BROWSER=none prisma studio",
"migration:push": "dotenv -e ../../apps/builder/.env.local yarn prisma db push", "generate:schema": "dotenv -e ../../apps/builder/.env.local prisma generate",
"migration:create": "dotenv -e ../../apps/builder/.env.local yarn prisma migrate dev", "migration:push": "dotenv -e ../../apps/builder/.env.local prisma db push",
"migration:reset": "dotenv -e ../../apps/builder/.env.local yarn prisma migrate reset", "migration:create": "dotenv -e ../../apps/builder/.env.local prisma migrate dev",
"migration:deploy": "yarn prisma migrate deploy" "migration:reset": "dotenv -e ../../apps/builder/.env.local prisma migrate reset",
"migration:deploy": "prisma migrate deploy"
} }
} }

View File

@ -6,14 +6,14 @@
"license": "AGPL-3.0-or-later", "license": "AGPL-3.0-or-later",
"private": true, "private": true,
"devDependencies": { "devDependencies": {
"typescript": "^4.5.5" "typescript": "^4.6.2"
}, },
"dependencies": { "dependencies": {
"next": "^12.0.10", "next": "^12.1.0",
"db": "*" "db": "*"
}, },
"scripts": { "scripts": {
"build": "tsc", "build": "tsc",
"dev": "tsc --watch --preserveWatchOutput" "dx": "tsc --watch --preserveWatchOutput"
} }
} }

View File

@ -23,7 +23,7 @@
"rollup-plugin-styles": "^4.0.0", "rollup-plugin-styles": "^4.0.0",
"rollup-plugin-terser": "^7.0.2", "rollup-plugin-terser": "^7.0.2",
"ts-jest": "^27.1.3", "ts-jest": "^27.1.3",
"ts-loader": "^9.2.7", "ts-loader": "^9.2.8",
"typescript": "^4.6.2" "typescript": "^4.6.2"
} }
} }

View File

@ -7,20 +7,21 @@
"module": "dist/esm/index.js", "module": "dist/esm/index.js",
"types": "dist/index.d.ts", "types": "dist/index.d.ts",
"devDependencies": { "devDependencies": {
"@rollup/plugin-commonjs": "^21.0.1", "@rollup/plugin-commonjs": "^21.0.2",
"@rollup/plugin-node-resolve": "^13.1.3", "@rollup/plugin-node-resolve": "^13.1.3",
"@rollup/plugin-typescript": "^8.3.0", "@rollup/plugin-typescript": "^8.3.1",
"rollup": "^2.67.2", "rollup": "^2.70.0",
"rollup-plugin-dts": "^4.1.0", "rollup-plugin-dts": "^4.2.0",
"rollup-plugin-peer-deps-external": "^2.2.4", "rollup-plugin-peer-deps-external": "^2.2.4",
"typescript": "^4.5.5" "tslib": "^2.3.1",
"typescript": "^4.6.2"
}, },
"dependencies": { "dependencies": {
"models": "*", "models": "*",
"next": "^12.0.10" "next": "^12.1.0"
}, },
"scripts": { "scripts": {
"build": "yarn rollup -c", "build": "yarn rollup -c",
"dev": "yarn rollup -c --watch" "dx": "yarn rollup -c --watch"
} }
} }

View File

@ -3,10 +3,10 @@
"version": "2.0.0", "version": "2.0.0",
"main": "index.js", "main": "index.js",
"repository": "https://github.com/typebot-io/wordpress.git", "repository": "https://github.com/typebot-io/wordpress.git",
"author": "Baptiste Arnaud <contact@baptiste-arnaud.fr>", "author": "baptisteArno",
"license": "MIT", "license": "MIT",
"devDependencies": { "devDependencies": {
"@prettier/plugin-php": "^0.17.3" "@prettier/plugin-php": "^0.18.3"
}, },
"scripts": { "scripts": {
"deploy": "yarn copy && yarn commit", "deploy": "yarn copy && yarn commit",

View File

@ -14,6 +14,9 @@
}, },
"dev": { "dev": {
"cache": false "cache": false
},
"dx": {
"cache": false
} }
} }
} }

11
typebot-config.env Normal file
View File

@ -0,0 +1,11 @@
# Shared
# MIGRATION_DATABASE_URL=
DATABASE_URL=postgresql://typebot:typebot@postgres:5432/typebot
NEXT_PUBLIC_VIEWER_HOST=http://localhost:8081
ENCRYPTION_SECRET=SgVkYp2s5v8y/B?E(H+MbQeThWmZq4t6
# Builder
ADMIN_EMAIL=contact@baptiste-arnaud.fr
NEXTAUTH_URL=http://localhost:8080
# Viewer

3634
yarn.lock

File diff suppressed because it is too large Load Diff