The Dotenv Refactor (#2275)

* dotenv refactoring

* dotenv fixes

* Env variables cleanup

* Updates e2e variables

* Moves environment file to types

* Removes conflicting configs

* Readds missing variables

* Fixes

* More fixes

* Update .env.example

* Update yarn.lock

* Update turbo.json

* Fixes e2e

* Temp fix

* disables cache for lint

* Please work

* I'm getting desperate here.

* Matches node versions

* Take 2

* Revert "Take 2"

This reverts commit a735f47f23.

* Update .env.example
This commit is contained in:
Omar López 2022-03-25 17:39:38 -07:00 committed by GitHub
parent 2d7e1ccc05
commit ec58a9dd70
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
42 changed files with 498 additions and 243 deletions

View File

@ -1,2 +1,151 @@
# It now lives at `apps/web/.env.example`
# DATABASE_URL got moved to `packages/prisma/.env.example`
# ********** INDEX **********
#
# - LICENSE
# - DATABASE
# - SHARED
# - NEXTAUTH
# - E-MAIL SETTINGS
# - APP STORE
# - DAILY.CO VIDEO
# - GOOGLE CALENDAR/MEET/LOGIN
# - OFFICE 365
# - STRIPE
# - TANDEM
# - ZOOM
# - LICENSE *************************************************************************************************
# Set this value to 'agree' to accept our license:
# LICENSE: https://github.com/calendso/calendso/blob/main/LICENSE
#
# Summary of terms:
# - The codebase has to stay open source, whether it was modified or not
# - You can not repackage or sell the codebase
# - Acquire a commercial license to remove these terms by visiting: cal.com/sales
NEXT_PUBLIC_LICENSE_CONSENT=''
# ***********************************************************************************************************
# - DATABASE ************************************************************************************************
# ⚠️ ⚠️ ⚠️ DATABASE_URL got moved to `packages/prisma/.env.example` ⚠️ ⚠️ ⚠️
# ***********************************************************************************************************
# - SHARED **************************************************************************************************
NEXT_PUBLIC_WEBAPP_URL='http://localhost:3000'
# Change to 'http://localhost:3001' if running the website simultaneously
NEXT_PUBLIC_WEBSITE_URL='http://localhost:3000'
# To enable SAML login, set both these variables
# @see https://github.com/calcom/cal.com/tree/main/packages/ee#setting-up-saml-login
# SAML_DATABASE_URL="postgresql://postgres:@localhost:5450/cal-saml"
SAML_DATABASE_URL=
# SAML_ADMINS='pro@example.com'
SAML_ADMINS=
# If you use Heroku to deploy Postgres (or use self-signed certs for Postgres) then uncomment the follow line.
# @see https://devcenter.heroku.com/articles/connecting-heroku-postgres#connecting-in-node-js
# PGSSLMODE='no-verify'
PGSSLMODE=
# - NEXTAUTH
# @see: https://github.com/calendso/calendso/issues/263
# Required for Vercel hosting - set NEXTAUTH_URL to equal your BASE_URL
# NEXTAUTH_URL='http://localhost:3000'
NEXTAUTH_URL=
JWT_SECRET='secret'
# Used for cross-domain cookie authentication
NEXTAUTH_COOKIE_DOMAIN=.example.com
# Remove this var if you don't want Cal to collect anonymous usage
NEXT_PUBLIC_TELEMETRY_KEY=js.2pvs2bbpqq1zxna97wcml.oi2jzirnbj1ev4tc57c5r
# ApiKey for cronjobs
CRON_API_KEY='0cc0e6c35519bba620c9360cfe3e68d0'
# Application Key for symmetric encryption and decryption
# must be 32 bytes for AES256 encryption algorithm
# You can use: `openssl rand -base64 24` to generate one
CALENDSO_ENCRYPTION_KEY=
# Intercom Config
NEXT_PUBLIC_INTERCOM_APP_ID=
# Zendesk Config
NEXT_PUBLIC_ZENDESK_KEY=
# Help Scout Config
NEXT_PUBLIC_HELPSCOUT_KEY=
# This is used so we can bypass emails in auth flows for E2E testing
# Set it to "1" if you need to run E2E tests locally
NEXT_PUBLIC_IS_E2E=
# Used for internal billing system
NEXT_PUBLIC_STRIPE_PRO_PLAN_PRODUCT=
NEXT_PUBLIC_STRIPE_PRO_PLAN_PRICE=
NEXT_PUBLIC_STRIPE_PREMIUM_PLAN_PRICE=
NEXT_PUBLIC_STRIPE_FREE_PLAN_PRICE=
# ***********************************************************************************************************
# - E-MAIL SETTINGS *****************************************************************************************
# Cal uses nodemailer (@see https://nodemailer.com/about/) to provide email sending. As such we are trying to
# allow access to the nodemailer transports from the .env file. E-mail templates are accessible within lib/emails/
# Configures the global From: header whilst sending emails.
EMAIL_FROM='notifications@yourselfhostedcal.com'
# Configure SMTP settings (@see https://nodemailer.com/smtp/).
# Note: The below configuration for Office 365 has been verified to work.
EMAIL_SERVER_HOST='smtp.office365.com'
EMAIL_SERVER_PORT=587
EMAIL_SERVER_USER='<office365_emailAddress>'
# Keep in mind that if you have 2FA enabled, you will need to provision an App Password.
EMAIL_SERVER_PASSWORD='<office365_password>'
# The following configuration for Gmail has been verified to work.
# EMAIL_SERVER_HOST='smtp.gmail.com'
# EMAIL_SERVER_PORT=465
# EMAIL_SERVER_USER='<gmail_emailAddress>'
## You will need to provision an App Password.
## @see https://support.google.com/accounts/answer/185833
# EMAIL_SERVER_PASSWORD='<gmail_app_password>'
# **********************************************************************************************************
# - APP STORE **********************************************************************************************
# - DAILY.CO VIDEO
DAILY_API_KEY=
DAILY_SCALE_PLAN=''
# - GOOGLE CALENDAR/MEET/LOGIN
# Needed to enable Google Calendar integration and Login with Google
# @see https://github.com/calendso/calendso#obtaining-the-google-api-credentials
GOOGLE_API_CREDENTIALS='{}'
# To enable Login with Google you need to:
# 1. Set `GOOGLE_API_CREDENTIALS` above
# 2. Set `GOOGLE_LOGIN_ENABLED` to `true`
# When self-hosting please ensure you configure the Google integration as an Internal app so no one else can login to your instance
# @see https://support.google.com/cloud/answer/6158849#public-and-internal&zippy=%2Cpublic-and-internal-applications
GOOGLE_LOGIN_ENABLED=false
# - OFFICE 365
# Used for the Office 365 / Outlook.com Calendar / MS Teams integration
# @see https://github.com/calcom/cal.com/#Obtaining-Microsoft-Graph-Client-ID-and-Secret
MS_GRAPH_CLIENT_ID=
MS_GRAPH_CLIENT_SECRET=
# - STRIPE
NEXT_PUBLIC_STRIPE_PUBLIC_KEY= # pk_test_...
STRIPE_PRIVATE_KEY= # sk_test_...
STRIPE_WEBHOOK_SECRET= # whsec_...
STRIPE_CLIENT_ID= # ca_...
PAYMENT_FEE_FIXED=10 # Take 10 additional cents commission
PAYMENT_FEE_PERCENTAGE=0.005 # Take 0.5% commission
# - TANDEM
# Used for the Tandem integration -- contact support@tandem.chat to for API access.
TANDEM_CLIENT_ID=""
TANDEM_CLIENT_SECRET=""
TANDEM_BASE_URL="https://tandem.chat"
# - ZOOM
# Used for the Zoom integration
# @see https://github.com/calcom/cal.com/#obtaining-zoom-client-id-and-secret
ZOOM_CLIENT_ID=
ZOOM_CLIENT_SECRET=
# *********************************************************************************************************

View File

@ -6,7 +6,6 @@ on:
jobs:
types:
name: Check types
strategy:
matrix:
node: ["14.x"]

View File

@ -1,6 +1,6 @@
name: E2E test
on:
pull_request_target:
pull_request:
branches:
- main
paths-ignore:
@ -9,9 +9,16 @@ jobs:
test:
timeout-minutes: 10
name: Testing ${{ matrix.node }} and ${{ matrix.os }}
strategy:
matrix:
node: ["14.x"]
os: [ubuntu-latest]
runs-on: ${{ matrix.os }}
env:
DATABASE_URL: postgresql://postgres:@localhost:5432/calendso
BASE_URL: http://localhost:3000
NEXT_PUBLIC_WEBAPP_URL: http://localhost:3000
NEXT_PUBLIC_WEBSITE_URL: http://localhost:3000
JWT_SECRET: secret
GOOGLE_API_CREDENTIALS: ${{ secrets.CI_GOOGLE_API_CREDENTIALS }}
GOOGLE_LOGIN_ENABLED: true
@ -25,12 +32,13 @@ jobs:
PAYMENT_FEE_FIXED: 10
SAML_DATABASE_URL: postgresql://postgres:@localhost:5432/calendso
SAML_ADMINS: pro@example.com
# NEXTAUTH_URL: xxx
EMAIL_FROM: e2e@cal.com
EMAIL_SERVER_HOST: ${{ secrets.CI_EMAIL_SERVER_HOST }}
EMAIL_SERVER_PORT: ${{ secrets.CI_EMAIL_SERVER_PORT }}
EMAIL_SERVER_USER: ${{ secrets.CI_EMAIL_SERVER_USER }}
EMAIL_SERVER_PASSWORD: ${{ secrets.CI_EMAIL_SERVER_PASSWORD }}
NEXTAUTH_URL: http://localhost:3000/api/auth
NEXT_PUBLIC_IS_E2E: 1
# EMAIL_FROM: e2e@cal.com
# EMAIL_SERVER_HOST: ${{ secrets.CI_EMAIL_SERVER_HOST }}
# EMAIL_SERVER_PORT: ${{ secrets.CI_EMAIL_SERVER_PORT }}
# EMAIL_SERVER_USER: ${{ secrets.CI_EMAIL_SERVER_USER }}
# EMAIL_SERVER_PASSWORD: ${{ secrets.CI_EMAIL_SERVER_PASSWORD }}
# MS_GRAPH_CLIENT_ID: xxx
# MS_GRAPH_CLIENT_SECRET: xxx
# ZOOM_CLIENT_ID: xxx
@ -43,25 +51,19 @@ jobs:
POSTGRES_DB: calendso
ports:
- 5432:5432
runs-on: ${{ matrix.os }}
strategy:
matrix:
node: ["14.x"]
os: [ubuntu-latest]
steps:
- name: Checkout repo
uses: actions/checkout@v2
with:
ref: ${{ github.event.pull_request.head.sha }}
fetch-depth: 2
fetch-depth: 0
- name: Use Node ${{ matrix.node }}
uses: actions/setup-node@v2
with:
cache: "yarn"
cache-dependency-path: yarn.lock
node-version: ${{ matrix.node }}
# cache: "yarn"
# cache-dependency-path: yarn.lock
- name: Turbo Cache
id: turbo-cache

View File

@ -1,25 +1,28 @@
name: Lint
on:
pull_request_target:
pull_request:
branches:
- main
jobs:
lint:
runs-on: ubuntu-latest
strategy:
matrix:
node: ["14.x"]
os: [ubuntu-latest]
runs-on: ${{ matrix.os }}
steps:
- name: Checkout repo
uses: actions/checkout@v2
with:
ref: ${{ github.event.pull_request.head.sha }}
fetch-depth: 2
fetch-depth: 0
- name: Use Node.js 14.x
uses: actions/setup-node@v2
with:
node-version: 14.x
cache: "yarn"
cache-dependency-path: yarn.lock
node-version: ${{ matrix.node }}
# cache: "yarn"
# cache-dependency-path: yarn.lock
- name: Install deps
if: steps.yarn-cache.outputs.cache-hit != 'true'

View File

@ -1,109 +0,0 @@
# Set this value to 'agree' to accept our license:
# LICENSE: https://github.com/calendso/calendso/blob/main/LICENSE
#
# Summary of terms:
# - The codebase has to stay open source, whether it was modified or not
# - You can not repackage or sell the codebase
# - Acquire a commercial license to remove these terms by visiting: cal.com/sales
NEXT_PUBLIC_LICENSE_CONSENT=''
# ⚠️ ⚠️ ⚠️ DATABASE_URL got moved to `packages/prisma/.env.example` ⚠️ ⚠️ ⚠️
# Needed to enable Google Calendar integration and Login with Google
# @see https://github.com/calendso/calendso#obtaining-the-google-api-credentials
GOOGLE_API_CREDENTIALS='{}'
# To enable Login with Google you need to:
# 1. Set `GOOGLE_API_CREDENTIALS` above
# 2. Set `GOOGLE_LOGIN_ENABLED` to `true`
# When self-hosting please ensure you configure the Google integration as an Internal app so no one else can login to your instance
# @see https://support.google.com/cloud/answer/6158849#public-and-internal&zippy=%2Cpublic-and-internal-applications
GOOGLE_LOGIN_ENABLED=false
BASE_URL='http://localhost:3000'
NEXT_PUBLIC_APP_URL='http://localhost:3000'
JWT_SECRET='secret'
# This is used so we can bypass emails in auth flows for E2E testing
# To enable SAML login, set both these variables
# @see https://github.com/calcom/cal.com/tree/main/packages/ee#setting-up-saml-login
# SAML_DATABASE_URL="postgresql://postgres:@localhost:5450/cal-saml"
# SAML_ADMINS='pro@example.com'
# If you use Heroku to deploy Postgres (or use self-signed certs for Postgres) then uncomment the follow line.
# @see https://devcenter.heroku.com/articles/connecting-heroku-postgres#connecting-in-node-js
##PGSSLMODE='no-verify'
# @see: https://github.com/calendso/calendso/issues/263
# Required for Vercel hosting - set NEXTAUTH_URL to equal your BASE_URL
# NEXTAUTH_URL='http://localhost:3000'
# Remove this var if you don't want Cal to collect anonymous usage
NEXT_PUBLIC_TELEMETRY_KEY=js.2pvs2bbpqq1zxna97wcml.oi2jzirnbj1ev4tc57c5r
# Used for the Office 365 / Outlook.com Calendar integration
MS_GRAPH_CLIENT_ID=
MS_GRAPH_CLIENT_SECRET=
# Used for the Zoom integration
ZOOM_CLIENT_ID=
ZOOM_CLIENT_SECRET=
#Used for the Daily integration
DAILY_API_KEY=
DAILY_SCALE_PLAN=''
# Used for the Tandem integration -- contact support@tandem.chat to for API access.
TANDEM_CLIENT_ID=""
TANDEM_CLIENT_SECRET=""
TANDEM_BASE_URL="https://tandem.chat"
# E-mail settings
# Cal uses nodemailer (@see https://nodemailer.com/about/) to provide email sending. As such we are trying to
# allow access to the nodemailer transports from the .env file. E-mail templates are accessible within lib/emails/
# Configures the global From: header whilst sending emails.
EMAIL_FROM='notifications@yourselfhostedcal.com'
# Configure SMTP settings (@see https://nodemailer.com/smtp/).
# Note: The below configuration for Office 365 has been verified to work.
EMAIL_SERVER_HOST='smtp.office365.com'
EMAIL_SERVER_PORT=587
EMAIL_SERVER_USER='<office365_emailAddress>'
# Keep in mind that if you have 2FA enabled, you will need to provision an App Password.
EMAIL_SERVER_PASSWORD='<office365_password>'
# The following configuration for Gmail has been verified to work.
# EMAIL_SERVER_HOST='smtp.gmail.com'
# EMAIL_SERVER_PORT=465
# EMAIL_SERVER_USER='<gmail_emailAddress>'
## You will need to provision an App Password.
## @see https://support.google.com/accounts/answer/185833
# EMAIL_SERVER_PASSWORD='<gmail_app_password>'
# ApiKey for cronjobs
CRON_API_KEY='0cc0e6c35519bba620c9360cfe3e68d0'
# Stripe Config
NEXT_PUBLIC_STRIPE_PUBLIC_KEY= # pk_test_...
STRIPE_PRIVATE_KEY= # sk_test_...
STRIPE_CLIENT_ID= # ca_...
STRIPE_WEBHOOK_SECRET= # whsec_...
PAYMENT_FEE_PERCENTAGE=0.005 # Take 0.5% commission
PAYMENT_FEE_FIXED=10 # Take 10 additional cents commission
# Application Key for symmetric encryption and decryption
# must be 32 bytes for AES256 encryption algorithm
CALENDSO_ENCRYPTION_KEY=
# Intercom Config
NEXT_PUBLIC_INTERCOM_APP_ID=
# Zendesk Config
NEXT_PUBLIC_ZENDESK_KEY=
# Help Scout Config
NEXT_PUBLIC_HELPSCOUT_KEY=
# Set it to "1" if you need to run E2E tests locally
NEXT_PUBLIC_IS_E2E=

View File

@ -298,7 +298,7 @@ export default function Shell(props: {
</div>
<small style={{ fontSize: "0.5rem" }} className="mx-3 mt-1 mb-2 hidden opacity-50 lg:block">
&copy; {new Date().getFullYear()} Cal.com, Inc. v.{pkg.version + "-"}
{process.env.NEXT_PUBLIC_APP_URL === "https://cal.com" ? "h" : "sh"}
{process.env.NEXT_PUBLIC_WEBSITE_URL === "https://cal.com" ? "h" : "sh"}
<span className="lowercase">-{user && user.plan}</span>
</small>
</div>
@ -437,12 +437,7 @@ function UserDropdown({ small }: { small?: boolean }) {
)}>
<img
className="rounded-full"
src={
(process.env.NEXT_PUBLIC_APP_URL || process.env.NEXT_PUBLIC_BASE_URL) +
"/" +
user?.username +
"/avatar.png"
}
src={process.env.NEXT_PUBLIC_WEBSITE_URL + "/" + user?.username + "/avatar.png"}
alt={user?.username || "Nameless User"}
/>
{!user?.away && (
@ -496,7 +491,7 @@ function UserDropdown({ small }: { small?: boolean }) {
<a
target="_blank"
rel="noopener noreferrer"
href={`${process.env.NEXT_PUBLIC_APP_URL}/${user.username}`}
href={`${process.env.NEXT_PUBLIC_WEBSITE_URL}/${user.username}`}
className="flex items-center px-4 py-2 text-sm text-gray-700">
<ExternalLinkIcon className="h-5 w-5 text-gray-500 ltr:mr-3 rtl:ml-3" /> {t("view_public_page")}
</a>

View File

@ -139,7 +139,7 @@ const AvailabilityPage = ({ profile, eventType, workingHours, previousPage }: Pr
.filter((user) => user.name !== profile.name)
.map((user) => ({
title: user.name,
image: `${process.env.NEXT_PUBLIC_APP_URL}/${user.username}/avatar.png`,
image: `${process.env.NEXT_PUBLIC_WEBSITE_URL}/${user.username}/avatar.png`,
alt: user.name || undefined,
})),
].filter((item) => !!item.image) as { image: string; alt?: string; title?: string }[]
@ -189,7 +189,7 @@ const AvailabilityPage = ({ profile, eventType, workingHours, previousPage }: Pr
.map((user) => ({
title: user.name,
alt: user.name,
image: `${process.env.NEXT_PUBLIC_APP_URL}/${user.username}/avatar.png`,
image: `${process.env.NEXT_PUBLIC_WEBSITE_URL}/${user.username}/avatar.png`,
})),
].filter((item) => !!item.image) as { image: string; alt?: string; title?: string }[]
}

View File

@ -191,7 +191,7 @@ export default function CreateEventTypeButton(props: Props) {
required
addOnLeading={
<InputLeading>
{process.env.NEXT_PUBLIC_APP_URL}/{pageSlug}/
{process.env.NEXT_PUBLIC_WEBSITE_URL}/{pageSlug}/
</InputLeading>
}
{...register("slug")}

View File

@ -67,7 +67,7 @@ const constructImage = (name: string, description: string, username: string): st
return (
encodeURIComponent("Meet **" + name + "** <br>" + description).replace(/'/g, "%27") +
".png?md=1&images=https%3A%2F%2Fcal.com%2Flogo-white.svg&images=" +
(process.env.NEXT_PUBLIC_APP_URL || process.env.BASE_URL) +
(process.env.NEXT_PUBLIC_WEBSITE_URL || process.env.NEXT_PUBLIC_WEBAPP_URL) +
"/" +
username +
"/avatar.png"

View File

@ -72,7 +72,7 @@ export default function TeamListItem(props: Props) {
<div className="ml-3 inline-block">
<span className="text-sm font-bold text-neutral-700">{team.name}</span>
<span className="block text-xs text-gray-400">
{process.env.NEXT_PUBLIC_APP_URL}/team/{team.slug}
{process.env.NEXT_PUBLIC_WEBSITE_URL}/team/{team.slug}
</span>
</div>
</div>
@ -112,7 +112,7 @@ export default function TeamListItem(props: Props) {
<Tooltip content={t("copy_link_team")}>
<Button
onClick={() => {
navigator.clipboard.writeText(process.env.NEXT_PUBLIC_APP_URL + "/team/" + team.slug);
navigator.clipboard.writeText(process.env.NEXT_PUBLIC_WEBSITE_URL + "/team/" + team.slug);
showToast(t("link_copied"), "success");
}}
className="h-10 w-10 transition-none"
@ -143,7 +143,7 @@ export default function TeamListItem(props: Props) {
</DropdownMenuItem>
)}
<DropdownMenuItem>
<Link href={`${process.env.NEXT_PUBLIC_APP_URL}/team/${team.slug}`} passHref={true}>
<Link href={`${process.env.NEXT_PUBLIC_WEBSITE_URL}/team/${team.slug}`} passHref={true}>
<a target="_blank">
<Button
color="minimal"

View File

@ -91,7 +91,7 @@ export default function TeamSettings(props: Props) {
id="team-url"
addOnLeading={
<span className="inline-flex items-center rounded-l-sm border border-r-0 border-gray-300 bg-gray-50 px-3 text-sm text-gray-500">
{process.env.NEXT_PUBLIC_APP_URL}/{"team/"}
{process.env.NEXT_PUBLIC_WEBSITE_URL}/{"team/"}
</span>
}
ref={teamUrlRef}

View File

@ -20,7 +20,7 @@ export default function TeamSettingsRightSidebar(props: { team: TeamWithMembers;
const utils = trpc.useContext();
const router = useRouter();
const permalink = `${process.env.NEXT_PUBLIC_APP_URL}/team/${props.team?.slug}`;
const permalink = `${process.env.NEXT_PUBLIC_WEBSITE_URL}/team/${props.team?.slug}`;
const deleteTeamMutation = trpc.useMutation("viewer.teams.delete", {
async onSuccess() {

View File

@ -16,6 +16,6 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
await upgradeTeam(session.user.id, Number(req.query.team));
// redirect to team screen
res.redirect(302, `${process.env.NEXT_PUBLIC_APP_URL}/settings/teams/${req.query.team}?upgraded=true`);
res.redirect(302, `${process.env.NEXT_PUBLIC_WEBAPP_URL}/settings/teams/${req.query.team}?upgraded=true`);
}
}

View File

@ -59,7 +59,7 @@ ${this.getWhen()}
${this.getLocation()}
${this.getAdditionalNotes()}
${this.calEvent.organizer.language.translate("confirm_or_reject_request")}
${process.env.BASE_URL} + "/bookings/upcoming"
${process.env.NEXT_PUBLIC_WEBAPP_URL} + "/bookings/upcoming"
`.replace(/(<([^>]+)>)/gi, "");
}
@ -167,7 +167,7 @@ ${process.env.BASE_URL} + "/bookings/upcoming"
protected getManageLink(): string {
const manageText = this.calEvent.organizer.language.translate("confirm_or_reject_request");
const manageLink = process.env.BASE_URL + "/bookings/upcoming";
const manageLink = process.env.NEXT_PUBLIC_WEBAPP_URL + "/bookings/upcoming";
return `<a style="color: #FFFFFF; text-decoration: none;" href="${manageLink}" target="_blank">${manageText} <img src="${linkIcon()}" width="12px"></img></a>`;
}
}

View File

@ -59,7 +59,7 @@ ${this.getWhen()}
${this.getLocation()}
${this.getAdditionalNotes()}
${this.calEvent.organizer.language.translate("confirm_or_reject_request")}
${process.env.BASE_URL} + "/bookings/upcoming"
${process.env.NEXT_PUBLIC_WEBAPP_URL} + "/bookings/upcoming"
`.replace(/(<([^>]+)>)/gi, "");
}
@ -166,7 +166,7 @@ ${process.env.BASE_URL} + "/bookings/upcoming"
protected getManageLink(): string {
const manageText = this.calEvent.organizer.language.translate("confirm_or_reject_request");
const manageLink = process.env.BASE_URL + "/bookings/upcoming";
const manageLink = process.env.NEXT_PUBLIC_WEBAPP_URL + "/bookings/upcoming";
return `<a style="color: #FFFFFF; text-decoration: none;" href="${manageLink}" target="_blank">${manageText} <img src="${linkIcon()}" width="12px"></img></a>`;
}
}

View File

@ -1,3 +1,5 @@
require("dotenv").config({ path: "../../.env" });
const withTM = require("next-transpile-modules")([
"@calcom/app-store",
"@calcom/core",
@ -10,16 +12,15 @@ const withTM = require("next-transpile-modules")([
const { i18n } = require("./next-i18next.config");
// So we can test deploy previews preview
if (process.env.VERCEL_URL && !process.env.BASE_URL) {
process.env.BASE_URL = "https://" + process.env.VERCEL_URL;
if (process.env.VERCEL_URL && !process.env.NEXT_PUBLIC_WEBAPP_URL) {
process.env.NEXT_PUBLIC_WEBAPP_URL = "https://" + process.env.VERCEL_URL;
}
if (process.env.BASE_URL) {
process.env.NEXTAUTH_URL = process.env.BASE_URL + "/api/auth";
if (process.env.NEXT_PUBLIC_WEBAPP_URL) {
process.env.NEXTAUTH_URL = process.env.NEXT_PUBLIC_WEBAPP_URL + "/api/auth";
}
if (!process.env.NEXT_PUBLIC_APP_URL) {
process.env.NEXT_PUBLIC_APP_URL = process.env.BASE_URL;
if (!process.env.NEXT_PUBLIC_WEBSITE_URL) {
process.env.NEXT_PUBLIC_WEBSITE_URL = process.env.NEXT_PUBLIC_WEBAPP_URL;
}
process.env.NEXT_PUBLIC_BASE_URL = process.env.BASE_URL;
if (!process.env.EMAIL_FROM) {
console.warn(
@ -60,8 +61,8 @@ if (process.env.ANALYZE === "true") {
plugins.push(withTM);
// prettier-ignore
module.exports = () => plugins.reduce((acc, next) => next(acc), {
/** @type {import("next").NextConfig} */
const nextConfig = {
i18n,
eslint: {
// This allows production builds to successfully complete even if the project has ESLint errors.
@ -85,7 +86,7 @@ module.exports = () => plugins.reduce((acc, next) => next(acc), {
source: "/:user/avatar.png",
destination: "/api/user/avatar?username=:user",
},
]
];
},
async redirects() {
return [
@ -100,10 +101,12 @@ module.exports = () => plugins.reduce((acc, next) => next(acc), {
permanent: true,
},
{
source: '/call/:path*',
destination: '/video/:path*',
permanent: false
}
source: "/call/:path*",
destination: "/video/:path*",
permanent: false,
},
];
},
});
};
module.exports = () => plugins.reduce((acc, next) => next(acc), nextConfig);

View File

@ -39,7 +39,7 @@ export default function Custom404() {
const isSubpage = router.asPath.includes("/", 2);
const isSignup = router.asPath.includes("/signup");
const isCalcom = process.env.NEXT_PUBLIC_BASE_URL === "https://app.cal.com";
const isCalcom = process.env.NEXT_PUBLIC_WEBAPP_URL === "https://app.cal.com";
return (
<>
@ -53,7 +53,7 @@ export default function Custom404() {
/>
<div className="min-h-screen bg-white px-4" data-testid="404-page">
<main className="mx-auto max-w-xl pt-16 pb-6 sm:pt-24">
{isSignup && process.env.NEXT_PUBLIC_BASE_URL !== "https://app.cal.com" ? (
{isSignup && process.env.NEXT_PUBLIC_WEBAPP_URL !== "https://app.cal.com" ? (
<div>
<div>
<p className="text-sm font-semibold uppercase tracking-wide text-black">

View File

@ -55,7 +55,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
passwordRequest = createdResetPasswordRequest;
}
const resetLink = `${process.env.BASE_URL}/auth/forgot-password/${passwordRequest.id}`;
const resetLink = `${process.env.NEXT_PUBLIC_WEBAPP_URL}/auth/forgot-password/${passwordRequest.id}`;
const passwordEmail: PasswordReset = {
language: t,
user: maybeUser,
@ -67,9 +67,9 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
/** So we can test the password reset flow on CI */
if (process.env.NEXT_PUBLIC_IS_E2E) {
return res.status(201).json({ message: "Reset Requested", resetLink });
} else {
return res.status(201).json({ message: "Reset Requested" });
}
return res.status(201).json({ message: "Reset Requested" });
} catch (reason) {
// console.error(reason);
return res.status(500).json({ message: "Unable to create password reset request" });

View File

@ -31,7 +31,7 @@ function IframeEmbedContainer() {
// doesn't need suspense as it should already be loaded
const user = trpc.useQuery(["viewer.me"]).data;
const iframeTemplate = `<iframe src="${process.env.NEXT_PUBLIC_BASE_URL}/${user?.username}" frameborder="0" allowfullscreen></iframe>`;
const iframeTemplate = `<iframe src="${process.env.NEXT_PUBLIC_WEBAPP_URL}/${user?.username}" frameborder="0" allowfullscreen></iframe>`;
const htmlTemplate = `<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>${t(
"schedule_a_meeting"
)}</title><style>body {margin: 0;}iframe {height: calc(100vh - 4px);width: calc(100vw - 4px);box-sizing: border-box;}</style></head><body>${iframeTemplate}</body></html>`;

View File

@ -2,6 +2,7 @@ import debounce from "lodash/debounce";
import { GetServerSidePropsContext } from "next";
import { getCsrfToken } from "next-auth/react";
import Link from "next/link";
import { useRouter } from "next/router";
import React, { SyntheticEvent } from "react";
import Button from "@calcom/ui/Button";
@ -18,6 +19,7 @@ export default function ForgotPassword({ csrfToken }: { csrfToken: string }) {
const [error, setError] = React.useState<{ message: string } | null>(null);
const [success, setSuccess] = React.useState(false);
const [email, setEmail] = React.useState("");
const router = useRouter();
const handleChange = (e: SyntheticEvent) => {
const target = e.target as typeof e.target & { value: string };
@ -38,7 +40,7 @@ export default function ForgotPassword({ csrfToken }: { csrfToken: string }) {
if (!res.ok) {
setError(json);
} else if ("resetLink" in json) {
window.location = json.resetLink;
router.push(json.resetLink);
} else {
setSuccess(true);
}

View File

@ -9,12 +9,12 @@ import { useForm } from "react-hook-form";
import { Alert } from "@calcom/ui/Alert";
import Button from "@calcom/ui/Button";
import { EmailField, PasswordField, Form } from "@calcom/ui/form/fields";
import { EmailField, Form, PasswordField } from "@calcom/ui/form/fields";
import { ErrorCode, getSession } from "@lib/auth";
import { WEBSITE_URL } from "@lib/config/constants";
import { WEBAPP_URL, WEBSITE_URL } from "@lib/config/constants";
import { useLocale } from "@lib/hooks/useLocale";
import { isSAMLLoginEnabled, hostedCal, samlTenantID, samlProductID } from "@lib/saml";
import { hostedCal, isSAMLLoginEnabled, samlProductID, samlTenantID } from "@lib/saml";
import { collectPageParameters, telemetryEventTypes, useTelemetry } from "@lib/telemetry";
import { inferSSRProps } from "@lib/types/inferSSRProps";
@ -64,7 +64,7 @@ export default function Login({
// If not absolute URL, make it absolute
if (/"\//.test(callbackUrl)) callbackUrl = callbackUrl.substring(1);
if (!/^https?:\/\//.test(callbackUrl)) {
callbackUrl = `${WEBSITE_URL}/${callbackUrl}`;
callbackUrl = `${WEBAPP_URL}/${callbackUrl}`;
}
const LoginFooter = (

View File

@ -91,7 +91,7 @@ export default function Signup({ email }: Props) {
<TextField
addOnLeading={
<span className="inline-flex items-center rounded-l-sm border border-r-0 border-gray-300 bg-gray-50 px-3 text-sm text-gray-500">
{process.env.NEXT_PUBLIC_APP_URL}/
{process.env.NEXT_PUBLIC_WEBSITE_URL}/
</span>
}
labelProps={{ className: "block text-sm font-medium text-gray-700" }}

View File

@ -158,8 +158,8 @@ const getStripePremiumUsernameUrl = async ({
quantity: 1,
},
],
success_url: `${process.env.NEXT_PUBLIC_APP_BASE_URL}${successDestination}&session_id={CHECKOUT_SESSION_ID}`,
cancel_url: process.env.NEXT_PUBLIC_APP_BASE_URL || "https://app.cal.com",
success_url: `${process.env.NEXT_PUBLIC_WEBAPP_URL}${successDestination}&session_id={CHECKOUT_SESSION_ID}`,
cancel_url: process.env.NEXT_PUBLIC_WEBAPP_URL || "https://app.cal.com",
allow_promotion_codes: true,
});

View File

@ -393,7 +393,7 @@ const EventTypePage = (props: inferSSRProps<typeof getServerSideProps>) => {
endDate: new Date(eventType.periodEndDate || Date.now()),
});
const permalink = `${process.env.NEXT_PUBLIC_APP_URL}/${
const permalink = `${process.env.NEXT_PUBLIC_WEBSITE_URL}/${
team ? `team/${team.slug}` : eventType.users[0].username
}/${eventType.slug}`;
@ -408,7 +408,7 @@ const EventTypePage = (props: inferSSRProps<typeof getServerSideProps>) => {
}) => ({
value: `${id || ""}`,
label: `${name || ""}`,
avatar: `${process.env.NEXT_PUBLIC_APP_URL}/${username}/avatar.png`,
avatar: `${process.env.NEXT_PUBLIC_WEBSITE_URL}/${username}/avatar.png`,
});
const formMethods = useForm<{
@ -895,7 +895,7 @@ const EventTypePage = (props: inferSSRProps<typeof getServerSideProps>) => {
<div className="w-full">
<div className="flex rounded-sm shadow-sm">
<span className="inline-flex items-center rounded-l-sm border border-r-0 border-gray-300 bg-gray-50 px-3 text-sm text-gray-500">
{process.env.NEXT_PUBLIC_APP_URL?.replace(/^(https?:|)\/\//, "")}/
{process.env.NEXT_PUBLIC_WEBSITE_URL?.replace(/^(https?:|)\/\//, "")}/
{team ? "team/" + team.slug : eventType.users[0].username}/
</span>
<input
@ -1994,7 +1994,7 @@ export const getServerSideProps = async (context: GetServerSidePropsContext) =>
const teamMembers = eventTypeObject.team
? eventTypeObject.team.members.map((member) => {
const user = member.user;
user.avatar = `${process.env.NEXT_PUBLIC_APP_URL}/${user.username}/avatar.png`;
user.avatar = `${process.env.NEXT_PUBLIC_WEBSITE_URL}/${user.username}/avatar.png`;
return user;
})
: [];

View File

@ -223,13 +223,13 @@ export const EventTypeList = ({ group, readOnly, types }: EventTypeListProps): J
truncateAfter={4}
items={type.users.map((organizer) => ({
alt: organizer.name || "",
image: `${process.env.NEXT_PUBLIC_APP_URL}/${organizer.username}/avatar.png`,
image: `${process.env.NEXT_PUBLIC_WEBSITE_URL}/${organizer.username}/avatar.png`,
}))}
/>
)}
<Tooltip content={t("preview")}>
<a
href={`${process.env.NEXT_PUBLIC_APP_URL}/${group.profile.slug}/${type.slug}`}
href={`${process.env.NEXT_PUBLIC_WEBSITE_URL}/${group.profile.slug}/${type.slug}`}
target="_blank"
rel="noreferrer"
className="btn-icon appearance-none">
@ -242,7 +242,7 @@ export const EventTypeList = ({ group, readOnly, types }: EventTypeListProps): J
onClick={() => {
showToast(t("link_copied"), "success");
navigator.clipboard.writeText(
`${process.env.NEXT_PUBLIC_APP_URL}/${group.profile.slug}/${type.slug}`
`${process.env.NEXT_PUBLIC_WEBSITE_URL}/${group.profile.slug}/${type.slug}`
);
}}
className="btn-icon">
@ -320,7 +320,8 @@ export const EventTypeList = ({ group, readOnly, types }: EventTypeListProps): J
</DropdownMenuTrigger>
<DropdownMenuContent portalled>
<DropdownMenuItem>
<Link href={`${process.env.NEXT_PUBLIC_APP_URL}/${group.profile.slug}/${type.slug}`}>
<Link
href={`${process.env.NEXT_PUBLIC_WEBSITE_URL}/${group.profile.slug}/${type.slug}`}>
<a target="_blank">
<Button
color="minimal"
@ -342,7 +343,7 @@ export const EventTypeList = ({ group, readOnly, types }: EventTypeListProps): J
StartIcon={ClipboardCopyIcon}
onClick={() => {
navigator.clipboard.writeText(
`${process.env.NEXT_PUBLIC_APP_URL}/${group.profile.slug}/${type.slug}`
`${process.env.NEXT_PUBLIC_WEBSITE_URL}/${group.profile.slug}/${type.slug}`
);
showToast(t("link_copied"), "success");
}}>
@ -363,7 +364,7 @@ export const EventTypeList = ({ group, readOnly, types }: EventTypeListProps): J
.share({
title: t("share"),
text: t("share_event"),
url: `${process.env.NEXT_PUBLIC_APP_URL}/${group.profile.slug}/${type.slug}`,
url: `${process.env.NEXT_PUBLIC_WEBSITE_URL}/${group.profile.slug}/${type.slug}`,
})
.then(() => showToast(t("link_shared"), "success"))
.catch(() => showToast(t("failed"), "error"));
@ -463,8 +464,8 @@ const EventTypeListHeading = ({ profile, membershipCount }: EventTypeListHeading
</span>
)}
{profile?.slug && (
<Link href={`${process.env.NEXT_PUBLIC_APP_URL}/${profile.slug}`}>
<a className="block text-xs text-neutral-500">{`${process.env.NEXT_PUBLIC_APP_URL?.replace(
<Link href={`${process.env.NEXT_PUBLIC_WEBSITE_URL}/${profile.slug}`}>
<a className="block text-xs text-neutral-500">{`${process.env.NEXT_PUBLIC_WEBSITE_URL?.replace(
"https://",
""
)}/${profile.slug}`}</a>

View File

@ -253,7 +253,7 @@ export default function Onboarding(props: inferSSRProps<typeof getServerSideProp
}>({ resolver: zodResolver(schema), mode: "onSubmit" });
const fetchUsername = async (username: string) => {
const response = await fetch(`${process.env.NEXT_PUBLIC_APP_URL}/api/username`, {
const response = await fetch(`${process.env.NEXT_PUBLIC_WEBSITE_URL}/api/username`, {
credentials: "include",
headers: {
"Content-Type": "application/json",

View File

@ -127,7 +127,7 @@ function SettingsView(props: ComponentProps<typeof Settings> & { localeProp: str
}).catch((e) => {
console.error(`Error Removing user: ${props.user.id}, email: ${props.user.email} :`, e);
});
if (process.env.NEXT_PUBLIC_BASE_URL === "https://app.cal.com") {
if (process.env.NEXT_PUBLIC_WEBAPP_URL === "https://app.cal.com") {
signOut({ callbackUrl: "/auth/logout?survey=true" });
} else {
signOut({ callbackUrl: "/auth/logout" });
@ -232,7 +232,7 @@ function SettingsView(props: ComponentProps<typeof Settings> & { localeProp: str
name="username"
addOnLeading={
<span className="inline-flex items-center rounded-l-sm border border-r-0 border-gray-300 bg-gray-50 px-3 text-sm text-gray-500">
{process.env.NEXT_PUBLIC_APP_URL}/
{process.env.NEXT_PUBLIC_WEBSITE_URL}/
</span>
}
ref={usernameRef}

View File

@ -12,7 +12,7 @@ test("Can reset forgotten password", async ({ page }) => {
page.waitForNavigation({
url: "/auth/forgot-password/*",
}),
page.press('input[type="email"]', "Enter"),
page.press('input[name="email"]', "Enter"),
]);
// Wait for page to fully load

View File

@ -30,7 +30,7 @@ import { viewerTeamsRouter } from "./viewer/teams";
import { webhookRouter } from "./viewer/webhook";
const checkUsername =
process.env.NEXT_PUBLIC_APP_URL === "https://cal.com" ? checkPremiumUsername : checkRegularUsername;
process.env.NEXT_PUBLIC_WEBSITE_URL === "https://cal.com" ? checkPremiumUsername : checkRegularUsername;
// things that unauthenticated users can query about themselves
const publicViewerRouter = createRouter()
@ -762,8 +762,8 @@ const loggedInViewerRouter = createProtectedRouter()
try {
return await apiController.config({
encodedRawMetadata,
defaultRedirectUrl: `${process.env.BASE_URL}/api/auth/saml/idp`,
redirectUrl: JSON.stringify([`${process.env.BASE_URL}/*`]),
defaultRedirectUrl: `${process.env.NEXT_PUBLIC_WEBAPP_URL}/api/auth/saml/idp`,
redirectUrl: JSON.stringify([`${process.env.NEXT_PUBLIC_WEBAPP_URL}/*`]),
tenant: teamId ? tenantPrefix + teamId : samlTenantID,
product: samlProductID,
});

View File

@ -8,9 +8,7 @@
"@server/*": ["server/*"],
"@ee/*": ["ee/*"],
"@prisma/client/*": ["@calcom/prisma/client/*"]
},
"typeRoots": ["./types", "@calcom/types"],
"types": ["@types/jest"]
}
},
"include": [
"next-env.d.ts",

View File

@ -15,15 +15,17 @@
"db-studio": "yarn workspace @calcom/prisma db-studio",
"deploy": "turbo run deploy",
"dev": "turbo run dev --scope=\"@calcom/web\"",
"docs-dev": "turbo run dev --scope=\"@calcom/docs\"",
"docs-build": "turbo run dev --scope=\"@calcom/docs\" --include-dependencies",
"docs-start": "turbo run dev --scope=\"@calcom/docs\"",
"dx": "turbo run dx",
"dev:website": "yarn predev && turbo run dev --scope=\"@calcom/web\" --scope=\"@calcom/website\"",
"docs-dev": "yarn predev && turbo run dev --scope=\"@calcom/docs\"",
"docs-build": "turbo run build --scope=\"@calcom/docs\" --include-dependencies",
"docs-start": "turbo run start --scope=\"@calcom/docs\"",
"dx": "yarn predev && turbo run dx",
"format": "prettier --write \"**/*.{ts,tsx,md}\"",
"heroku-postbuild": "turbo run @calcom/web#build",
"lint": "turbo run lint",
"lint:report": "turbo run lint:report",
"pre-commit": "lint-staged",
"predev": "dotenv-checker --schema .env.example --env .env",
"prepare": "husky install",
"start": "turbo run start --scope=\"@calcom/web\"",
"test": "turbo run test",
@ -32,6 +34,7 @@
"type-check": "turbo run type-check"
},
"devDependencies": {
"dotenv-checker": "^1.1.5",
"husky": "^7.0.1",
"lint-staged": "^12.3.5",
"prettier": "^2.5.1"

View File

@ -1,4 +0,0 @@
# Place these on `apps/web/.env`
# @see https://github.com/calcom/cal.com/#Obtaining-Microsoft-Graph-Client-ID-and-Secret
MS_GRAPH_CLIENT_CLIENT_ID=
MS_GRAPH_CLIENT_CLIENT_SECRET=

View File

@ -12,7 +12,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
return;
}
const return_url = `${process.env.BASE_URL}/settings/billing`;
const return_url = `${process.env.NEXT_PUBLIC_WEBAPP_URL}/settings/billing`;
const stripeSession = await stripe.billingPortal.sessions.create({
customer: customerId,
return_url,

View File

@ -1,4 +0,0 @@
# Place these on `apps/web/.env`
# @see https://github.com/calcom/cal.com/#obtaining-zoom-client-id-and-secret
ZOOM_CLIENT_ID=
ZOOM_CLIENT_SECRET=

View File

@ -1,6 +1,9 @@
export const BASE_URL = process.env.BASE_URL || `https://${process.env.VERCEL_URL}`;
export const WEBSITE_URL = process.env.NEXT_PUBLIC_APP_URL || "https://cal.com";
export const WEBAPP_URL = process.env.NEXT_PUBLIC_WEBAPP_URL || `https://${process.env.VERCEL_URL}`;
/** @deprecated use `WEBAPP_URL` */
export const BASE_URL = WEBAPP_URL;
export const WEBSITE_URL = process.env.NEXT_PUBLIC_WEBSITE_URL || "https://cal.com";
export const IS_PRODUCTION = process.env.NODE_ENV === "production";
export const TRIAL_LIMIT_DAYS = 14;
export const HOSTED_CAL_FEATURES = process.env.HOSTED_CAL_FEATURES || BASE_URL === "https://app.cal.com";
export const NEXT_PUBLIC_BASE_URL = process.env.NEXT_PUBLIC_BASE_URL || `https://${process.env.VERCEL_URL}`;
/** @deprecated use `WEBAPP_URL` */
export const NEXT_PUBLIC_BASE_URL = process.env.NEXT_PUBLIC_WEBAPP_URL || `https://${process.env.VERCEL_URL}`;

View File

@ -5,6 +5,8 @@ import { uuid } from "short-uuid";
import { hashPassword } from "@calcom/lib/auth";
import { DEFAULT_SCHEDULE, getAvailabilityFromSchedule } from "@calcom/lib/availability";
require("dotenv").config({ path: "../../.env" });
const prisma = new PrismaClient();
async function createUserAndEventType(opts: {
@ -51,7 +53,7 @@ async function createUserAndEventType(opts: {
});
console.log(
`👤 Upserted '${opts.user.username}' with email "${opts.user.email}" & password "${opts.user.password}". Booking page 👉 ${process.env.BASE_URL}/${opts.user.username}`
`👤 Upserted '${opts.user.username}' with email "${opts.user.email}" & password "${opts.user.password}". Booking page 👉 ${process.env.NEXT_PUBLIC_WEBAPP_URL}/${opts.user.username}`
);
for (const eventTypeInput of opts.eventTypes) {
@ -75,7 +77,7 @@ async function createUserAndEventType(opts: {
if (eventType) {
console.log(
`\t📆 Event type ${eventTypeData.slug} already seems seeded - ${process.env.BASE_URL}/${user.username}/${eventTypeData.slug}`
`\t📆 Event type ${eventTypeData.slug} already seems seeded - ${process.env.NEXT_PUBLIC_WEBAPP_URL}/${user.username}/${eventTypeData.slug}`
);
continue;
}
@ -84,7 +86,7 @@ async function createUserAndEventType(opts: {
});
console.log(
`\t📆 Event type ${eventTypeData.slug}, length ${eventTypeData.length}min - ${process.env.BASE_URL}/${user.username}/${eventTypeData.slug}`
`\t📆 Event type ${eventTypeData.slug}, length ${eventTypeData.length}min - ${process.env.NEXT_PUBLIC_WEBAPP_URL}/${user.username}/${eventTypeData.slug}`
);
for (const bookingInput of bookingInputs) {
await prisma.booking.create({
@ -146,7 +148,9 @@ async function createTeamAndAddUsers(
return;
}
console.log(`🏢 Created team '${teamInput.name}' - ${process.env.BASE_URL}/team/${team.slug}`);
console.log(
`🏢 Created team '${teamInput.name}' - ${process.env.NEXT_PUBLIC_WEBAPP_URL}/team/${team.slug}`
);
for (const user of users) {
const { role = MembershipRole.OWNER, id, username } = user;

View File

@ -29,7 +29,7 @@ export function createPaymentLink(opts: {
}): string {
const { paymentUid, name, date, absolute = true } = opts;
let link = "";
if (absolute) link = process.env.NEXT_PUBLIC_APP_URL!;
if (absolute) link = process.env.NEXT_PUBLIC_WEBSITE_URL!;
const query = stringify({ date, name });
return link + `/payment/${paymentUid}?${query}`;
}

View File

@ -241,8 +241,8 @@ async function createCheckoutSession(
payment_method_types: ["card"],
customer: customerId,
line_items,
success_url: `${process.env.NEXT_PUBLIC_APP_URL}/api/teams/${teamId}/upgrade?session_id={CHECKOUT_SESSION_ID}`,
cancel_url: `${process.env.NEXT_PUBLIC_APP_URL}/`,
success_url: `${process.env.NEXT_PUBLIC_WEBAPP_URL}/api/teams/${teamId}/upgrade?session_id={CHECKOUT_SESSION_ID}`,
cancel_url: `${process.env.NEXT_PUBLIC_WEBAPP_URL}/`,
allow_promotion_codes: true,
};

View File

@ -1,10 +1,23 @@
declare namespace NodeJS {
interface ProcessEnv {
/**
* Set this value to 'agree' to accept our license:
* LICENSE: https://github.com/calendso/calendso/blob/main/LICENSE
*
* Summary of terms:
* - The codebase has to stay open source, whether it was modified or not
* - You can not repackage or sell the codebase
* - Acquire a commercial license to remove these terms by visiting: cal.com/sales
**/
readonly NEXT_PUBLIC_LICENSE_CONSENT: "agree" | undefined;
readonly CALENDSO_ENCRYPTION_KEY: string | undefined;
readonly DATABASE_URL: string | undefined;
readonly GOOGLE_API_CREDENTIALS: string | undefined;
/** @deprecated use `NEXT_PUBLIC_WEBAPP_URL` */
readonly BASE_URL: string | undefined;
/** @deprecated use `NEXT_PUBLIC_WEBAPP_URL` */
readonly NEXT_PUBLIC_BASE_URL: string | undefined;
/** @deprecated use `NEXT_PUBLIC_WEBSITE_URL` */
readonly NEXT_PUBLIC_APP_URL: string | undefined;
readonly JWT_SECRET: string | undefined;
readonly NEXT_PUBLIC_TELEMETRY_KEY: string | undefined;
@ -24,10 +37,26 @@ declare namespace NodeJS {
readonly STRIPE_WEBHOOK_SECRET: string | undefined;
readonly PAYMENT_FEE_PERCENTAGE: number | undefined;
readonly PAYMENT_FEE_FIXED: number | undefined;
readonly CALENDSO_ENCRYPTION_KEY: string | undefined;
readonly NEXT_PUBLIC_INTERCOM_APP_ID: string | undefined;
readonly TANDEM_CLIENT_ID: string | undefined;
readonly TANDEM_CLIENT_SECRET: string | undefined;
readonly TANDEM_BASE_URL: string | undefined;
readonly WEBSITE_BASE_URL: string | undefined;
/** @deprecated use `NEXT_PUBLIC_WEBSITE_URL` */
readonly NEXT_PUBLIC_WEBSITE_BASE_URL: string;
readonly NEXT_PUBLIC_WEBSITE_URL: string;
readonly APP_BASE_URL: string | undefined;
/** @deprecated use `NEXT_PUBLIC_WEBAPP_URL` */
readonly NEXT_PUBLIC_APP_BASE_URL: string;
readonly NEXT_PUBLIC_WEBAPP_URL: string;
/** The Environment that the app is deployed an running on. */
readonly VERCEL_ENV: "production" | "preview" | "development" | undefined;
/** The URL of the deployment. Example: my-site-7q03y4pi5.vercel.app. */
readonly VERCEL_URL: string | undefined;
/**
* This is used so we can bypass emails in auth flows for E2E testing.
* Set it to "1" if you need to run E2E tests locally
**/
readonly NEXT_PUBLIC_IS_E2E: 1 | undefined;
}
}

View File

@ -1,3 +1,4 @@
import { loadEnvConfig } from "@next/env";
import { Browser, chromium } from "@playwright/test";
import fs from "fs";
@ -25,6 +26,7 @@ async function loginAsUser(username: string, browser: Browser) {
}
async function globalSetup(/* config: FullConfig */) {
loadEnvConfig(process.env.PWD);
const browser = await chromium.launch();
await loginAsUser("onboarding", browser);
// await loginAsUser("free-first-hidden", browser);

View File

@ -1,7 +1,7 @@
{
"$schema": "https://turborepo.org/schema.json",
"baseBranch": "origin/main",
"globalDependencies": ["apps/web/.env", "packages/prisma/.env"],
"globalDependencies": [".env", "packages/prisma/.env"],
"pipeline": {
"@calcom/prisma#build": {
"dependsOn": ["$DATABASE_URL"],
@ -20,7 +20,6 @@
"@calcom/web#build": {
"dependsOn": [
"^build",
"$BASE_URL",
"$CALENDSO_ENCRYPTION_KEY",
"$CRON_API_KEY",
"$DAILY_API_KEY",
@ -36,11 +35,20 @@
"$JWT_SECRET",
"$MS_GRAPH_CLIENT_ID",
"$MS_GRAPH_CLIENT_SECRET",
"$NEXT_PUBLIC_APP_URL",
"$NEXT_PUBLIC_HELPSCOUT_KEY",
"$NEXT_PUBLIC_INTERCOM_APP_ID",
"$NEXT_PUBLIC_IS_E2E",
"$NEXT_PUBLIC_LICENSE_CONSENT",
"$NEXT_PUBLIC_STRIPE_FREE_PLAN_PRICE",
"$NEXT_PUBLIC_STRIPE_PREMIUM_PLAN_PRICE",
"$NEXT_PUBLIC_STRIPE_PRO_PLAN_PRICE",
"$NEXT_PUBLIC_STRIPE_PRO_PLAN_PRODUCT",
"$NEXT_PUBLIC_STRIPE_PUBLIC_KEY",
"$NEXT_PUBLIC_TELEMETRY_KEY",
"$NEXT_PUBLIC_WEBAPP_URL",
"$NEXT_PUBLIC_WEBSITE_URL",
"$NEXT_PUBLIC_ZENDESK_KEY",
"$NEXTAUTH_COOKIE_DOMAIN",
"$NEXTAUTH_URL",
"$PAYMENT_FEE_FIXED",
"$PAYMENT_FEE_PERCENTAGE",
@ -53,7 +61,6 @@
"$TANDEM_BASE_URL",
"$TANDEM_CLIENT_ID",
"$TANDEM_CLIENT_SECRET",
"$WEBSITE_BASE_URL",
"$ZOOM_CLIENT_ID",
"$ZOOM_CLIENT_SECRET"
],
@ -101,7 +108,7 @@
},
"test-e2e": {
"cache": false,
"dependsOn": ["test", "@calcom/web#build", "@calcom/prisma#db-reset"]
"dependsOn": ["@calcom/web#test", "@calcom/web#build", "@calcom/prisma#db-reset"]
},
"type-check": {
"outputs": []

182
yarn.lock
View File

@ -3755,6 +3755,11 @@
dependencies:
stripe "*"
"@types/tinycolor2@^1.4.0":
version "1.4.3"
resolved "https://registry.yarnpkg.com/@types/tinycolor2/-/tinycolor2-1.4.3.tgz#ed4a0901f954b126e6a914b4839c77462d56e706"
integrity sha512-Kf1w9NE5HEgGxCRyIcRXR/ZYtDv0V8FVPtYHwLxl0O+maGX0erE77pQlD0gpP+/KByMZ87mOA79SjifhSB3PjQ==
"@types/unist@*", "@types/unist@^2.0.0", "@types/unist@^2.0.2":
version "2.0.6"
resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.6.tgz#250a7b16c3b91f672a24552ec64678eeb1d3a08d"
@ -4604,6 +4609,15 @@ bl@^1.0.0:
readable-stream "^2.3.5"
safe-buffer "^5.1.1"
bl@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a"
integrity sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==
dependencies:
buffer "^5.5.0"
inherits "^2.0.4"
readable-stream "^3.4.0"
bl@~0.8.1:
version "0.8.2"
resolved "https://registry.yarnpkg.com/bl/-/bl-0.8.2.tgz#c9b6bca08d1bc2ea00fc8afb4f1a5fd1e1c66e4e"
@ -5061,7 +5075,7 @@ chalk@2.3.0:
escape-string-regexp "^1.0.5"
supports-color "^4.0.0"
chalk@4.1.2, chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.2:
chalk@4.1.2, chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.1, chalk@^4.1.2:
version "4.1.2"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01"
integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==
@ -5118,6 +5132,11 @@ character-reference-invalid@^2.0.0:
resolved "https://registry.yarnpkg.com/character-reference-invalid/-/character-reference-invalid-2.0.1.tgz#85c66b041e43b47210faf401278abf808ac45cb9"
integrity sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==
chardet@^0.7.0:
version "0.7.0"
resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e"
integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==
chokidar@^3.5.3:
version "3.5.3"
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd"
@ -5221,6 +5240,11 @@ cli-highlight@^2.1.11:
parse5-htmlparser2-tree-adapter "^6.0.0"
yargs "^16.0.0"
cli-spinners@^2.5.0:
version "2.6.1"
resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.6.1.tgz#adc954ebe281c37a6319bfa401e6dd2488ffb70d"
integrity sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g==
cli-truncate@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-2.1.0.tgz#c39e28bf05edcde5be3b98992a22deed5a2b93c7"
@ -5237,6 +5261,11 @@ cli-truncate@^3.1.0:
slice-ansi "^5.0.0"
string-width "^5.0.0"
cli-width@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-3.0.0.tgz#a2f48437a2caa9a22436e794bf071ec9e61cedf6"
integrity sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==
clipboardy@1.2.2:
version "1.2.2"
resolved "https://registry.yarnpkg.com/clipboardy/-/clipboardy-1.2.2.tgz#2ce320b9ed9be1514f79878b53ff9765420903e2"
@ -5270,6 +5299,11 @@ clone-response@1.0.2, clone-response@^1.0.2:
dependencies:
mimic-response "^1.0.0"
clone@^1.0.2:
version "1.0.4"
resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e"
integrity sha1-2jCcwmPfFZlMaIypAheco8fNfH4=
clone@~0.1.9:
version "0.1.19"
resolved "https://registry.yarnpkg.com/clone/-/clone-0.1.19.tgz#613fb68639b26a494ac53253e15b1a6bd88ada85"
@ -5368,6 +5402,11 @@ commander@8.3.0, commander@^8.3.0:
resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66"
integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==
commander@9.1.0:
version "9.1.0"
resolved "https://registry.yarnpkg.com/commander/-/commander-9.1.0.tgz#a6b263b2327f2e188c6402c42623327909f2dbec"
integrity sha512-i0/MaqBtdbnJ4XQs4Pmyb+oFQl+q0lsAmokVUH92SlSw4fkeAcG3bVon+Qt7hmtF+u3Het6o4VgrcY3qAoEB6w==
commander@^2.8.1:
version "2.20.3"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
@ -5807,6 +5846,13 @@ deepmerge@^4.2.2:
resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955"
integrity sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==
defaults@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.3.tgz#c656051e9817d9ff08ed881477f3fe4019f3ef7d"
integrity sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=
dependencies:
clone "^1.0.2"
defer-to-connect@^1.0.1:
version "1.1.3"
resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-1.1.3.tgz#331ae050c08dcf789f8c83a7b81f0ed94f4ac591"
@ -6015,6 +6061,18 @@ domexception@^2.0.1:
dependencies:
webidl-conversions "^5.0.0"
dotenv-checker@^1.1.5:
version "1.1.5"
resolved "https://registry.yarnpkg.com/dotenv-checker/-/dotenv-checker-1.1.5.tgz#0bdd140ce50c560d70fb8103ffe1a14c9ad65c74"
integrity sha512-Cid4rHVKUD2WroyMLZbsaATc/messNAdtRjkzHk3wL716dBCfeHxpTVJAcjO5BP+7AFXx9Nnzd1vBBomIDr7uA==
dependencies:
app-root-path "^3.0.0"
chalk "4.1.2"
commander "9.1.0"
deepmerge "^4.2.2"
gradient-string "2.0.0"
inquirer "8.2.1"
dotenv@^8.2.0:
version "8.6.0"
resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-8.6.0.tgz#061af664d19f7f4d8fc6e4ff9b584ce237adcb8b"
@ -6902,6 +6960,15 @@ extension-port-stream@^2.0.1:
dependencies:
webextension-polyfill-ts "^0.22.0"
external-editor@^3.0.3:
version "3.1.0"
resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495"
integrity sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==
dependencies:
chardet "^0.7.0"
iconv-lite "^0.4.24"
tmp "^0.0.33"
extglob@^2.0.4:
version "2.0.4"
resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543"
@ -7009,6 +7076,13 @@ fd-slicer@~1.1.0:
dependencies:
pend "~1.2.0"
figures@^3.0.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af"
integrity sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==
dependencies:
escape-string-regexp "^1.0.5"
file-entry-cache@^6.0.1:
version "6.0.1"
resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027"
@ -7577,6 +7651,14 @@ graceful-fs@^4.1.10, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0,
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.9.tgz#041b05df45755e587a24942279b9d113146e1c96"
integrity sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==
gradient-string@2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/gradient-string/-/gradient-string-2.0.0.tgz#0333846e88e6011bdd12fa73d0fa2a60dfd34f51"
integrity sha512-xa+FXy1bOfJWqA4xKlKTfVXxuOwNRwvsO7Tj8oi/6Rodfgo4ENKApVOU95KxTKb7eML9E9eA2Uqq3C9LtVPM5w==
dependencies:
chalk "^4.1.2"
tinygradient "^1.1.5"
grapheme-splitter@^1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz#9cf3a665c6247479896834af35cf1dbb4400767e"
@ -7954,7 +8036,7 @@ iconv-lite@0.4.19:
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b"
integrity sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==
iconv-lite@0.4.24:
iconv-lite@0.4.24, iconv-lite@^0.4.24:
version "0.4.24"
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==
@ -8077,6 +8159,26 @@ input-format@^0.3.7:
dependencies:
prop-types "^15.7.2"
inquirer@8.2.1:
version "8.2.1"
resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-8.2.1.tgz#e00022e3e8930a92662f760f020686530a84671d"
integrity sha512-pxhBaw9cyTFMjwKtkjePWDhvwzvrNGAw7En4hottzlPvz80GZaMZthdDU35aA6/f5FRZf3uhE057q8w1DE3V2g==
dependencies:
ansi-escapes "^4.2.1"
chalk "^4.1.1"
cli-cursor "^3.1.0"
cli-width "^3.0.0"
external-editor "^3.0.3"
figures "^3.0.0"
lodash "^4.17.21"
mute-stream "0.0.8"
ora "^5.4.1"
run-async "^2.4.0"
rxjs "^7.5.5"
string-width "^4.1.0"
strip-ansi "^6.0.0"
through "^2.3.6"
internal-slot@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.3.tgz#7347e307deeea2faac2ac6205d4bc7d34967f59c"
@ -8355,6 +8457,11 @@ is-hexadecimal@^2.0.0:
resolved "https://registry.yarnpkg.com/is-hexadecimal/-/is-hexadecimal-2.0.1.tgz#86b5bf668fca307498d319dfc03289d781a90027"
integrity sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==
is-interactive@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/is-interactive/-/is-interactive-1.0.0.tgz#cea6e6ae5c870a7b0a0004070b7b587e0252912e"
integrity sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==
is-natural-number@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/is-natural-number/-/is-natural-number-4.0.1.tgz#ab9d76e1db4ced51e35de0c72ebecf09f734cde8"
@ -8491,6 +8598,11 @@ is-typedarray@^1.0.0, is-typedarray@~1.0.0:
resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a"
integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=
is-unicode-supported@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7"
integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==
is-weakref@^1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2"
@ -9956,6 +10068,14 @@ lodash@4.17.21, lodash@4.x, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, l
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
log-symbols@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503"
integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==
dependencies:
chalk "^4.1.0"
is-unicode-supported "^0.1.0"
log-update@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/log-update/-/log-update-4.0.0.tgz#589ecd352471f2a1c0c570287543a64dfd20e0a1"
@ -10985,6 +11105,11 @@ multihashes@^0.4.15, multihashes@~0.4.15:
multibase "^0.7.0"
varint "^5.0.0"
mute-stream@0.0.8:
version "0.0.8"
resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d"
integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==
mysql2@2.3.3:
version "2.3.3"
resolved "https://registry.yarnpkg.com/mysql2/-/mysql2-2.3.3.tgz#944f3deca4b16629052ff8614fbf89d5552545a0"
@ -11561,6 +11686,26 @@ optionator@^0.9.1:
type-check "^0.4.0"
word-wrap "^1.2.3"
ora@^5.4.1:
version "5.4.1"
resolved "https://registry.yarnpkg.com/ora/-/ora-5.4.1.tgz#1b2678426af4ac4a509008e5e4ac9e9959db9e18"
integrity sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==
dependencies:
bl "^4.1.0"
chalk "^4.1.0"
cli-cursor "^3.1.0"
cli-spinners "^2.5.0"
is-interactive "^1.0.0"
is-unicode-supported "^0.1.0"
log-symbols "^4.1.0"
strip-ansi "^6.0.0"
wcwidth "^1.0.1"
os-tmpdir@~1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=
otplib@^12.0.1:
version "12.0.1"
resolved "https://registry.yarnpkg.com/otplib/-/otplib-12.0.1.tgz#c1d3060ab7aadf041ed2960302f27095777d1f73"
@ -12832,7 +12977,7 @@ readable-stream@^2.0.0, readable-stream@^2.2.2, readable-stream@^2.3.0, readable
string_decoder "~1.1.1"
util-deprecate "~1.0.1"
readable-stream@^3.6.0:
readable-stream@^3.4.0, readable-stream@^3.6.0:
version "3.6.0"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198"
integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==
@ -13231,6 +13376,11 @@ rsvp@^4.8.4:
resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-4.8.5.tgz#c8f155311d167f68f21e168df71ec5b083113734"
integrity sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA==
run-async@^2.4.0:
version "2.4.1"
resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455"
integrity sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==
run-parallel@^1.1.9:
version "1.2.0"
resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee"
@ -14194,7 +14344,7 @@ throat@^6.0.1:
resolved "https://registry.yarnpkg.com/throat/-/throat-6.0.1.tgz#d514fedad95740c12c2d7fc70ea863eb51ade375"
integrity sha512-8hmiGIJMDlwjg7dlJ4yKGLK8EsYqKgPWbG3b4wjJddKNwc7N7Dpn08Df4szr/sZdMVeOstrdYSsqzX6BYbcB+w==
through@^2.3.8:
through@^2.3.6, through@^2.3.8:
version "2.3.8"
resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=
@ -14229,11 +14379,19 @@ tiny-warning@^1.0.0, tiny-warning@^1.0.3:
resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754"
integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==
tinycolor2@^1.4.1:
tinycolor2@^1.0.0, tinycolor2@^1.4.1:
version "1.4.2"
resolved "https://registry.yarnpkg.com/tinycolor2/-/tinycolor2-1.4.2.tgz#3f6a4d1071ad07676d7fa472e1fac40a719d8803"
integrity sha512-vJhccZPs965sV/L2sU4oRQVAos0pQXwsvTLkWYdqJ+a8Q5kPFzJTuOFwy7UniPli44NKQGAglksjvOcpo95aZA==
tinygradient@^1.1.5:
version "1.1.5"
resolved "https://registry.yarnpkg.com/tinygradient/-/tinygradient-1.1.5.tgz#0fb855ceb18d96b21ba780b51a8012033b2530ef"
integrity sha512-8nIfc2vgQ4TeLnk2lFj4tRLvvJwEfQuabdsmvDdQPT0xlk9TaNtpGd6nNRxXoK6vQhN6RSzj+Cnp5tTQmpxmbw==
dependencies:
"@types/tinycolor2" "^1.4.0"
tinycolor2 "^1.0.0"
title@^3.4.2:
version "3.4.4"
resolved "https://registry.yarnpkg.com/title/-/title-3.4.4.tgz#5c0ab11fd69643bc05dc006bba52aaf5c1630f5e"
@ -14249,6 +14407,13 @@ titleize@1.0.0:
resolved "https://registry.yarnpkg.com/titleize/-/titleize-1.0.0.tgz#7d350722061830ba6617631e0cfd3ea08398d95a"
integrity sha1-fTUHIgYYMLpmF2MeDP0+oIOY2Vo=
tmp@^0.0.33:
version "0.0.33"
resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9"
integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==
dependencies:
os-tmpdir "~1.0.2"
tmpl@1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc"
@ -15163,6 +15328,13 @@ warning@^4.0.3:
dependencies:
loose-envify "^1.0.0"
wcwidth@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8"
integrity sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=
dependencies:
defaults "^1.0.3"
web3-bzz@1.7.1:
version "1.7.1"
resolved "https://registry.yarnpkg.com/web3-bzz/-/web3-bzz-1.7.1.tgz#ea1e7d27050eca089bc5d71b7f7688d20b68a25d"