mirror of
https://github.com/documenso/documenso.git
synced 2025-11-10 04:22:32 +10:00
feat: add vercel build script
This commit is contained in:
@ -7,8 +7,8 @@ NEXT_PRIVATE_GOOGLE_CLIENT_ID=""
|
|||||||
NEXT_PRIVATE_GOOGLE_CLIENT_SECRET=""
|
NEXT_PRIVATE_GOOGLE_CLIENT_SECRET=""
|
||||||
|
|
||||||
# [[APP]]
|
# [[APP]]
|
||||||
NEXT_PUBLIC_SITE_URL="http://localhost:3000"
|
NEXT_PUBLIC_WEBAPP_URL="http://localhost:3000"
|
||||||
NEXT_PUBLIC_APP_URL="http://localhost:3000"
|
NEXT_PUBLIC_MARKETING_URL="http://localhost:3001"
|
||||||
|
|
||||||
# [[DATABASE]]
|
# [[DATABASE]]
|
||||||
NEXT_PRIVATE_DATABASE_URL="postgres://documenso:password@127.0.0.1:54320/documenso"
|
NEXT_PRIVATE_DATABASE_URL="postgres://documenso:password@127.0.0.1:54320/documenso"
|
||||||
|
|||||||
@ -5,3 +5,4 @@
|
|||||||
# Statically hosted javascript files
|
# Statically hosted javascript files
|
||||||
apps/*/public/*.js
|
apps/*/public/*.js
|
||||||
apps/*/public/*.cjs
|
apps/*/public/*.cjs
|
||||||
|
scripts/
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const { withContentlayer } = require('next-contentlayer');
|
const { withContentlayer } = require('next-contentlayer');
|
||||||
|
const { remapVercelEnv } = require('../../scripts/remap-vercel-env.cjs');
|
||||||
|
|
||||||
const { parsed: env } = require('dotenv').config({
|
const { parsed: env } = require('dotenv').config({
|
||||||
path: path.join(__dirname, '../../.env.local'),
|
path: path.join(__dirname, '../../.env.local'),
|
||||||
|
|||||||
3
apps/marketing/process-env.d.ts
vendored
3
apps/marketing/process-env.d.ts
vendored
@ -1,6 +1,7 @@
|
|||||||
declare namespace NodeJS {
|
declare namespace NodeJS {
|
||||||
export interface ProcessEnv {
|
export interface ProcessEnv {
|
||||||
NEXT_PUBLIC_SITE_URL?: string;
|
NEXT_PUBLIC_WEBAPP_URL?: string;
|
||||||
|
NEXT_PUBLIC_MARKETING_URL?: string;
|
||||||
|
|
||||||
NEXT_PRIVATE_DATABASE_URL: string;
|
NEXT_PRIVATE_DATABASE_URL: string;
|
||||||
|
|
||||||
|
|||||||
@ -161,7 +161,7 @@ export default async function ClaimedPlanPage({ searchParams = {} }: ClaimedPlan
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<Link
|
<Link
|
||||||
href={`${process.env.NEXT_PUBLIC_APP_URL}/login`}
|
href={`${process.env.NEXT_PUBLIC_WEBAPP_URL}/login`}
|
||||||
target="_blank"
|
target="_blank"
|
||||||
className="mt-4 block"
|
className="mt-4 block"
|
||||||
>
|
>
|
||||||
|
|||||||
@ -21,12 +21,12 @@ export const metadata = {
|
|||||||
description:
|
description:
|
||||||
'Join Documenso, the open signing infrastructure, and get a 10x better signing experience. Pricing starts at $30/mo. forever! Sign in now and enjoy a faster, smarter, and more beautiful document signing process. Integrates with your favorite tools, customizable, and expandable. Support our mission and become a part of our open-source community.',
|
'Join Documenso, the open signing infrastructure, and get a 10x better signing experience. Pricing starts at $30/mo. forever! Sign in now and enjoy a faster, smarter, and more beautiful document signing process. Integrates with your favorite tools, customizable, and expandable. Support our mission and become a part of our open-source community.',
|
||||||
type: 'website',
|
type: 'website',
|
||||||
images: [`${process.env.NEXT_PUBLIC_SITE_URL}/opengraph-image.jpg`],
|
images: [`${process.env.NEXT_PUBLIC_MARKETING_URL}/opengraph-image.jpg`],
|
||||||
},
|
},
|
||||||
twitter: {
|
twitter: {
|
||||||
site: '@documenso',
|
site: '@documenso',
|
||||||
card: 'summary_large_image',
|
card: 'summary_large_image',
|
||||||
images: [`${process.env.NEXT_PUBLIC_SITE_URL}/opengraph-image.jpg`],
|
images: [`${process.env.NEXT_PUBLIC_MARKETING_URL}/opengraph-image.jpg`],
|
||||||
description:
|
description:
|
||||||
'Join Documenso, the open signing infrastructure, and get a 10x better signing experience. Pricing starts at $30/mo. forever! Sign in now and enjoy a faster, smarter, and more beautiful document signing process. Integrates with your favorite tools, customizable, and expandable. Support our mission and become a part of our open-source community.',
|
'Join Documenso, the open signing infrastructure, and get a 10x better signing experience. Pricing starts at $30/mo. forever! Sign in now and enjoy a faster, smarter, and more beautiful document signing process. Integrates with your favorite tools, customizable, and expandable. Support our mission and become a part of our open-source community.',
|
||||||
},
|
},
|
||||||
|
|||||||
@ -43,7 +43,7 @@ export default async function handler(
|
|||||||
|
|
||||||
if (user && user.Subscription.length > 0) {
|
if (user && user.Subscription.length > 0) {
|
||||||
return res.status(200).json({
|
return res.status(200).json({
|
||||||
redirectUrl: `${process.env.NEXT_PUBLIC_APP_URL}/login`,
|
redirectUrl: `${process.env.NEXT_PUBLIC_WEBAPP_URL}/login`,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -103,8 +103,8 @@ export default async function handler(
|
|||||||
mode: 'subscription',
|
mode: 'subscription',
|
||||||
metadata,
|
metadata,
|
||||||
allow_promotion_codes: true,
|
allow_promotion_codes: true,
|
||||||
success_url: `${process.env.NEXT_PUBLIC_SITE_URL}/claimed?sessionId={CHECKOUT_SESSION_ID}`,
|
success_url: `${process.env.NEXT_PUBLIC_MARKETING_URL}/claimed?sessionId={CHECKOUT_SESSION_ID}`,
|
||||||
cancel_url: `${process.env.NEXT_PUBLIC_SITE_URL}/pricing?email=${encodeURIComponent(
|
cancel_url: `${process.env.NEXT_PUBLIC_MARKETING_URL}/pricing?email=${encodeURIComponent(
|
||||||
email,
|
email,
|
||||||
)}&name=${encodeURIComponent(name)}&planId=${planId}&cancelled=true`,
|
)}&name=${encodeURIComponent(name)}&planId=${planId}&cancelled=true`,
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const { version } = require('./package.json');
|
const { version } = require('./package.json');
|
||||||
|
const { remapVercelEnv } = require('../../scripts/remap-vercel-env.cjs');
|
||||||
|
|
||||||
const { parsed: env } = require('dotenv').config({
|
const { parsed: env } = require('dotenv').config({
|
||||||
path: path.join(__dirname, '../../.env.local'),
|
path: path.join(__dirname, '../../.env.local'),
|
||||||
|
|||||||
3
apps/web/process-env.d.ts
vendored
3
apps/web/process-env.d.ts
vendored
@ -1,6 +1,7 @@
|
|||||||
declare namespace NodeJS {
|
declare namespace NodeJS {
|
||||||
export interface ProcessEnv {
|
export interface ProcessEnv {
|
||||||
NEXT_PUBLIC_SITE_URL?: string;
|
NEXT_PUBLIC_WEBAPP_URL?: string;
|
||||||
|
NEXT_PUBLIC_MARKETING_URL?: string;
|
||||||
|
|
||||||
NEXT_PRIVATE_DATABASE_URL: string;
|
NEXT_PRIVATE_DATABASE_URL: string;
|
||||||
|
|
||||||
|
|||||||
@ -35,7 +35,7 @@ export default async function BillingSettingsPage() {
|
|||||||
if (subscription.customerId) {
|
if (subscription.customerId) {
|
||||||
billingPortalUrl = await getPortalSession({
|
billingPortalUrl = await getPortalSession({
|
||||||
customerId: subscription.customerId,
|
customerId: subscription.customerId,
|
||||||
returnUrl: `${process.env.NEXT_PUBLIC_SITE_URL}/settings/billing`,
|
returnUrl: `${process.env.NEXT_PUBLIC_WEBAPP_URL}/settings/billing`,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -33,12 +33,12 @@ export const metadata = {
|
|||||||
description:
|
description:
|
||||||
'Join Documenso, the open signing infrastructure, and get a 10x better signing experience. Pricing starts at $30/mo. forever! Sign in now and enjoy a faster, smarter, and more beautiful document signing process. Integrates with your favorite tools, customizable, and expandable. Support our mission and become a part of our open-source community.',
|
'Join Documenso, the open signing infrastructure, and get a 10x better signing experience. Pricing starts at $30/mo. forever! Sign in now and enjoy a faster, smarter, and more beautiful document signing process. Integrates with your favorite tools, customizable, and expandable. Support our mission and become a part of our open-source community.',
|
||||||
type: 'website',
|
type: 'website',
|
||||||
images: [`${process.env.NEXT_PUBLIC_SITE_URL}/opengraph-image.jpg`],
|
images: [`${process.env.NEXT_PUBLIC_WEBAPP_URL}/opengraph-image.jpg`],
|
||||||
},
|
},
|
||||||
twitter: {
|
twitter: {
|
||||||
site: '@documenso',
|
site: '@documenso',
|
||||||
card: 'summary_large_image',
|
card: 'summary_large_image',
|
||||||
images: [`${process.env.NEXT_PUBLIC_SITE_URL}/opengraph-image.jpg`],
|
images: [`${process.env.NEXT_PUBLIC_WEBAPP_URL}/opengraph-image.jpg`],
|
||||||
description:
|
description:
|
||||||
'Join Documenso, the open signing infrastructure, and get a 10x better signing experience. Pricing starts at $30/mo. forever! Sign in now and enjoy a faster, smarter, and more beautiful document signing process. Integrates with your favorite tools, customizable, and expandable. Support our mission and become a part of our open-source community.',
|
'Join Documenso, the open signing infrastructure, and get a 10x better signing experience. Pricing starts at $30/mo. forever! Sign in now and enjoy a faster, smarter, and more beautiful document signing process. Integrates with your favorite tools, customizable, and expandable. Support our mission and become a part of our open-source community.',
|
||||||
},
|
},
|
||||||
|
|||||||
@ -21,7 +21,7 @@ export const getFlag = async (
|
|||||||
return LOCAL_FEATURE_FLAGS[flag] ?? true;
|
return LOCAL_FEATURE_FLAGS[flag] ?? true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const url = new URL(`${process.env.NEXT_PUBLIC_SITE_URL}/api/feature-flag/get`);
|
const url = new URL(`${process.env.NEXT_PUBLIC_WEBAPP_URL}/api/feature-flag/get`);
|
||||||
url.searchParams.set('flag', flag);
|
url.searchParams.set('flag', flag);
|
||||||
|
|
||||||
const response = await fetch(url, {
|
const response = await fetch(url, {
|
||||||
@ -54,7 +54,7 @@ export const getAllFlags = async (
|
|||||||
return LOCAL_FEATURE_FLAGS;
|
return LOCAL_FEATURE_FLAGS;
|
||||||
}
|
}
|
||||||
|
|
||||||
const url = new URL(`${process.env.NEXT_PUBLIC_SITE_URL}/api/feature-flag/all`);
|
const url = new URL(`${process.env.NEXT_PUBLIC_WEBAPP_URL}/api/feature-flag/all`);
|
||||||
|
|
||||||
return fetch(url, {
|
return fetch(url, {
|
||||||
headers: {
|
headers: {
|
||||||
|
|||||||
@ -43,7 +43,7 @@ export default async function handler(
|
|||||||
|
|
||||||
if (user && user.Subscription.length > 0) {
|
if (user && user.Subscription.length > 0) {
|
||||||
return res.status(200).json({
|
return res.status(200).json({
|
||||||
redirectUrl: `${process.env.NEXT_PUBLIC_APP_URL}/login`,
|
redirectUrl: `${process.env.NEXT_PUBLIC_WEBAPP_URL}/login`,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -103,8 +103,8 @@ export default async function handler(
|
|||||||
mode: 'subscription',
|
mode: 'subscription',
|
||||||
metadata,
|
metadata,
|
||||||
allow_promotion_codes: true,
|
allow_promotion_codes: true,
|
||||||
success_url: `${process.env.NEXT_PUBLIC_SITE_URL}/claimed?sessionId={CHECKOUT_SESSION_ID}`,
|
success_url: `${process.env.NEXT_PUBLIC_MARKETING_URL}/claimed?sessionId={CHECKOUT_SESSION_ID}`,
|
||||||
cancel_url: `${process.env.NEXT_PUBLIC_SITE_URL}/pricing?email=${encodeURIComponent(
|
cancel_url: `${process.env.NEXT_PUBLIC_MARKETING_URL}/pricing?email=${encodeURIComponent(
|
||||||
email,
|
email,
|
||||||
)}&name=${encodeURIComponent(name)}&planId=${planId}&cancelled=true`,
|
)}&name=${encodeURIComponent(name)}&planId=${planId}&cancelled=true`,
|
||||||
});
|
});
|
||||||
|
|||||||
BIN
assets/example.pdf
Normal file
BIN
assets/example.pdf
Normal file
Binary file not shown.
36
package-lock.json
generated
36
package-lock.json
generated
@ -3489,12 +3489,12 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@prisma/client": {
|
"node_modules/@prisma/client": {
|
||||||
"version": "5.0.0",
|
"version": "5.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/@prisma/client/-/client-5.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/@prisma/client/-/client-5.3.1.tgz",
|
||||||
"integrity": "sha512-XlO5ELNAQ7rV4cXIDJUNBEgdLwX3pjtt9Q/RHqDpGf43szpNJx2hJnggfFs7TKNx0cOFsl6KJCSfqr5duEU/bQ==",
|
"integrity": "sha512-ArOKjHwdFZIe1cGU56oIfy7wRuTn0FfZjGuU/AjgEBOQh+4rDkB6nF+AGHP8KaVpkBIiHGPQh3IpwQ3xDMdO0Q==",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@prisma/engines-version": "4.17.0-26.6b0aef69b7cdfc787f822ecd7cdc76d5f1991584"
|
"@prisma/engines-version": "5.3.1-2.61e140623197a131c2a6189271ffee05a7aa9a59"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=16.13"
|
"node": ">=16.13"
|
||||||
@ -3509,15 +3509,15 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@prisma/engines": {
|
"node_modules/@prisma/engines": {
|
||||||
"version": "5.0.0",
|
"version": "5.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-5.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-5.3.1.tgz",
|
||||||
"integrity": "sha512-kyT/8fd0OpWmhAU5YnY7eP31brW1q1YrTGoblWrhQJDiN/1K+Z8S1kylcmtjqx5wsUGcP1HBWutayA/jtyt+sg==",
|
"integrity": "sha512-6QkILNyfeeN67BNEPEtkgh3Xo2tm6D7V+UhrkBbRHqKw9CTaz/vvTP/ROwYSP/3JT2MtIutZm/EnhxUiuOPVDA==",
|
||||||
"hasInstallScript": true
|
"hasInstallScript": true
|
||||||
},
|
},
|
||||||
"node_modules/@prisma/engines-version": {
|
"node_modules/@prisma/engines-version": {
|
||||||
"version": "4.17.0-26.6b0aef69b7cdfc787f822ecd7cdc76d5f1991584",
|
"version": "5.3.1-2.61e140623197a131c2a6189271ffee05a7aa9a59",
|
||||||
"resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-4.17.0-26.6b0aef69b7cdfc787f822ecd7cdc76d5f1991584.tgz",
|
"resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-5.3.1-2.61e140623197a131c2a6189271ffee05a7aa9a59.tgz",
|
||||||
"integrity": "sha512-HHiUF6NixsldsP3JROq07TYBLEjXFKr6PdH8H4gK/XAoTmIplOJBCgrIUMrsRAnEuGyRoRLXKXWUb943+PFoKQ=="
|
"integrity": "sha512-y5qbUi3ql2Xg7XraqcXEdMHh0MocBfnBzDn5GbV1xk23S3Mq8MGs+VjacTNiBh3dtEdUERCrUUG7Z3QaJ+h79w=="
|
||||||
},
|
},
|
||||||
"node_modules/@protobufjs/aspromise": {
|
"node_modules/@protobufjs/aspromise": {
|
||||||
"version": "1.1.2",
|
"version": "1.1.2",
|
||||||
@ -14820,12 +14820,12 @@
|
|||||||
"integrity": "sha512-WuxUnVtlWL1OfZFQFuqvnvs6MiAGk9UNsBostyBOB0Is9wb5uRESevA6rnl/rkksXaGX3GzZhPup5d6Vp1nFew=="
|
"integrity": "sha512-WuxUnVtlWL1OfZFQFuqvnvs6MiAGk9UNsBostyBOB0Is9wb5uRESevA6rnl/rkksXaGX3GzZhPup5d6Vp1nFew=="
|
||||||
},
|
},
|
||||||
"node_modules/prisma": {
|
"node_modules/prisma": {
|
||||||
"version": "5.0.0",
|
"version": "5.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/prisma/-/prisma-5.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/prisma/-/prisma-5.3.1.tgz",
|
||||||
"integrity": "sha512-KYWk83Fhi1FH59jSpavAYTt2eoMVW9YKgu8ci0kuUnt6Dup5Qy47pcB4/TLmiPAbhGrxxSz7gsSnJcCmkyPANA==",
|
"integrity": "sha512-Wp2msQIlMPHe+5k5Od6xnsI/WNG7UJGgFUJgqv/ygc7kOECZapcSz/iU4NIEzISs3H1W9sFLjAPbg/gOqqtB7A==",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@prisma/engines": "5.0.0"
|
"@prisma/engines": "5.3.1"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
"prisma": "build/index.js"
|
"prisma": "build/index.js"
|
||||||
@ -18417,8 +18417,12 @@
|
|||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@prisma/client": "5.0.0",
|
"@prisma/client": "5.3.1",
|
||||||
"prisma": "5.0.0"
|
"prisma": "5.3.1"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"ts-node": "^10.9.1",
|
||||||
|
"typescript": "^5.1.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"packages/tailwind-config": {
|
"packages/tailwind-config": {
|
||||||
|
|||||||
@ -48,8 +48,8 @@ export const sendDocument = async ({ documentId, userId }: SendDocumentOptions)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const assetBaseUrl = process.env.NEXT_PUBLIC_SITE_URL || 'http://localhost:3000';
|
const assetBaseUrl = process.env.NEXT_PUBLIC_WEBAPP_URL || 'http://localhost:3000';
|
||||||
const signDocumentLink = `${process.env.NEXT_PUBLIC_SITE_URL}/sign/${recipient.token}`;
|
const signDocumentLink = `${process.env.NEXT_PUBLIC_WEBAPP_URL}/sign/${recipient.token}`;
|
||||||
|
|
||||||
const template = createElement(DocumentInviteEmailTemplate, {
|
const template = createElement(DocumentInviteEmailTemplate, {
|
||||||
documentName: document.title,
|
documentName: document.title,
|
||||||
|
|||||||
@ -8,8 +8,8 @@ export const getBaseUrl = () => {
|
|||||||
return `https://${process.env.VERCEL_URL}`;
|
return `https://${process.env.VERCEL_URL}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (process.env.NEXT_PUBLIC_SITE_URL) {
|
if (process.env.NEXT_PUBLIC_WEBAPP_URL) {
|
||||||
return `https://${process.env.NEXT_PUBLIC_SITE_URL}`;
|
return process.env.NEXT_PUBLIC_WEBAPP_URL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return `http://localhost:${process.env.PORT ?? 3000}`;
|
return `http://localhost:${process.env.PORT ?? 3000}`;
|
||||||
|
|||||||
52
packages/prisma/helper.ts
Normal file
52
packages/prisma/helper.ts
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
/// <reference types="@documenso/tsconfig/process-env.d.ts" />
|
||||||
|
|
||||||
|
export const getDatabaseUrl = () => {
|
||||||
|
if (process.env.NEXT_PRIVATE_DATABASE_URL) {
|
||||||
|
return process.env.NEXT_PRIVATE_DATABASE_URL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (process.env.POSTGRES_URL) {
|
||||||
|
process.env.NEXT_PRIVATE_DATABASE_URL = process.env.POSTGRES_URL;
|
||||||
|
process.env.NEXT_PRIVATE_DIRECT_DATABASE_URL = process.env.POSTGRES_URL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (process.env.DATABASE_URL) {
|
||||||
|
process.env.NEXT_PRIVATE_DATABASE_URL = process.env.DATABASE_URL;
|
||||||
|
process.env.NEXT_PRIVATE_DIRECT_DATABASE_URL = process.env.DATABASE_URL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (process.env.POSTGRES_PRISMA_URL) {
|
||||||
|
process.env.NEXT_PRIVATE_DATABASE_URL = process.env.POSTGRES_PRISMA_URL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (process.env.POSTGRES_URL_NON_POOLING) {
|
||||||
|
process.env.NEXT_PRIVATE_DIRECT_DATABASE_URL = process.env.POSTGRES_URL_NON_POOLING;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We change the protocol from `postgres:` to `https:` so we can construct a easily
|
||||||
|
// mofifiable URL.
|
||||||
|
const url = new URL(process.env.NEXT_PRIVATE_DATABASE_URL.replace('postgres://', 'https://'));
|
||||||
|
|
||||||
|
// If we're using a connection pool, we need to let Prisma know that
|
||||||
|
// we're using PgBouncer.
|
||||||
|
if (process.env.NEXT_PRIVATE_DATABASE_URL !== process.env.NEXT_PRIVATE_DIRECT_DATABASE_URL) {
|
||||||
|
url.searchParams.set('pgbouncer', 'true');
|
||||||
|
|
||||||
|
process.env.NEXT_PRIVATE_DATABASE_URL = url.toString().replace('https://', 'postgres://');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Support for neon.tech (Neon Database)
|
||||||
|
if (url.hostname.endsWith('neon.tech')) {
|
||||||
|
const [projectId, ...rest] = url.hostname.split('.');
|
||||||
|
|
||||||
|
if (!projectId.endsWith('-bouncer')) {
|
||||||
|
url.hostname = `${projectId}-pooler.${rest.join('.')}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
url.searchParams.set('pgbouncer', 'true');
|
||||||
|
|
||||||
|
process.env.NEXT_PRIVATE_DATABASE_URL = url.toString().replace('https://', 'postgres://');
|
||||||
|
}
|
||||||
|
|
||||||
|
return process.env.NEXT_PRIVATE_DATABASE_URL;
|
||||||
|
};
|
||||||
@ -1,5 +1,7 @@
|
|||||||
import { PrismaClient } from '@prisma/client';
|
import { PrismaClient } from '@prisma/client';
|
||||||
|
|
||||||
|
import { getDatabaseUrl } from './helper';
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
// We need `var` to declare a global variable in TypeScript
|
// We need `var` to declare a global variable in TypeScript
|
||||||
// eslint-disable-next-line no-var
|
// eslint-disable-next-line no-var
|
||||||
@ -7,9 +9,13 @@ declare global {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!globalThis.prisma) {
|
if (!globalThis.prisma) {
|
||||||
globalThis.prisma = new PrismaClient();
|
globalThis.prisma = new PrismaClient({ datasourceUrl: getDatabaseUrl() });
|
||||||
}
|
}
|
||||||
|
|
||||||
export const prisma = globalThis.prisma || new PrismaClient();
|
export const prisma =
|
||||||
|
globalThis.prisma ||
|
||||||
|
new PrismaClient({
|
||||||
|
datasourceUrl: getDatabaseUrl(),
|
||||||
|
});
|
||||||
|
|
||||||
export const getPrismaClient = () => prisma;
|
export const getPrismaClient = () => prisma;
|
||||||
|
|||||||
@ -9,10 +9,18 @@
|
|||||||
"format": "prisma format",
|
"format": "prisma format",
|
||||||
"prisma:generate": "prisma generate",
|
"prisma:generate": "prisma generate",
|
||||||
"prisma:migrate-dev": "prisma migrate dev",
|
"prisma:migrate-dev": "prisma migrate dev",
|
||||||
"prisma:migrate-deploy": "prisma migrate deploy"
|
"prisma:migrate-deploy": "prisma migrate deploy",
|
||||||
|
"prisma:seed": "prisma db seed"
|
||||||
|
},
|
||||||
|
"prisma": {
|
||||||
|
"seed": "ts-node --transpileOnly --skipProject ./seed-database.ts"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@prisma/client": "5.0.0",
|
"@prisma/client": "5.3.1",
|
||||||
"prisma": "5.0.0"
|
"prisma": "5.3.1"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"ts-node": "^10.9.1",
|
||||||
|
"typescript": "^5.1.6"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
82
packages/prisma/seed-database.ts
Normal file
82
packages/prisma/seed-database.ts
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
import { DocumentDataType, Role } from '@prisma/client';
|
||||||
|
import fs from 'node:fs';
|
||||||
|
import path from 'node:path';
|
||||||
|
|
||||||
|
import { hashSync } from '@documenso/lib/server-only/auth/hash';
|
||||||
|
|
||||||
|
import { prisma } from './index';
|
||||||
|
|
||||||
|
const seedDatabase = async () => {
|
||||||
|
const examplePdf = fs
|
||||||
|
.readFileSync(path.join(__dirname, '../../assets/example.pdf'))
|
||||||
|
.toString('base64');
|
||||||
|
|
||||||
|
const exampleUser = await prisma.user.upsert({
|
||||||
|
where: {
|
||||||
|
email: 'example@documenso.com',
|
||||||
|
},
|
||||||
|
create: {
|
||||||
|
name: 'Example User',
|
||||||
|
email: 'example@documenso.com',
|
||||||
|
password: hashSync('password'),
|
||||||
|
roles: [Role.USER],
|
||||||
|
},
|
||||||
|
update: {},
|
||||||
|
});
|
||||||
|
|
||||||
|
const adminUser = await prisma.user.upsert({
|
||||||
|
where: {
|
||||||
|
email: 'admin@documenso.com',
|
||||||
|
},
|
||||||
|
create: {
|
||||||
|
name: 'Admin User',
|
||||||
|
email: 'admin@documenso.com',
|
||||||
|
password: hashSync('password'),
|
||||||
|
roles: [Role.USER, Role.ADMIN],
|
||||||
|
},
|
||||||
|
update: {},
|
||||||
|
});
|
||||||
|
|
||||||
|
const examplePdfData = await prisma.documentData.upsert({
|
||||||
|
where: {
|
||||||
|
id: 'clmn0kv5k0000pe04vcqg5zla',
|
||||||
|
},
|
||||||
|
create: {
|
||||||
|
id: 'clmn0kv5k0000pe04vcqg5zla',
|
||||||
|
type: DocumentDataType.BYTES_64,
|
||||||
|
data: examplePdf,
|
||||||
|
initialData: examplePdf,
|
||||||
|
},
|
||||||
|
update: {},
|
||||||
|
});
|
||||||
|
|
||||||
|
await prisma.document.upsert({
|
||||||
|
where: {
|
||||||
|
id: 1,
|
||||||
|
},
|
||||||
|
create: {
|
||||||
|
id: 1,
|
||||||
|
title: 'Example Document',
|
||||||
|
documentDataId: examplePdfData.id,
|
||||||
|
userId: exampleUser.id,
|
||||||
|
Recipient: {
|
||||||
|
create: {
|
||||||
|
name: String(adminUser.name),
|
||||||
|
email: adminUser.email,
|
||||||
|
token: Math.random().toString(36).slice(2, 9),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
update: {},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
seedDatabase()
|
||||||
|
.then(() => {
|
||||||
|
console.log('Database seeded');
|
||||||
|
process.exit(0);
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.error(error);
|
||||||
|
process.exit(1);
|
||||||
|
});
|
||||||
17
packages/tsconfig/process-env.d.ts
vendored
17
packages/tsconfig/process-env.d.ts
vendored
@ -1,6 +1,7 @@
|
|||||||
declare namespace NodeJS {
|
declare namespace NodeJS {
|
||||||
export interface ProcessEnv {
|
export interface ProcessEnv {
|
||||||
NEXT_PUBLIC_SITE_URL?: string;
|
NEXT_PUBLIC_WEBAPP_URL?: string;
|
||||||
|
NEXT_PUBLIC_MARKETING_URL?: string;
|
||||||
|
|
||||||
NEXT_PRIVATE_GOOGLE_CLIENT_ID?: string;
|
NEXT_PRIVATE_GOOGLE_CLIENT_ID?: string;
|
||||||
NEXT_PRIVATE_GOOGLE_CLIENT_SECRET?: string;
|
NEXT_PRIVATE_GOOGLE_CLIENT_SECRET?: string;
|
||||||
@ -40,5 +41,19 @@ declare namespace NodeJS {
|
|||||||
|
|
||||||
NEXT_PRIVATE_SMTP_FROM_NAME?: string;
|
NEXT_PRIVATE_SMTP_FROM_NAME?: string;
|
||||||
NEXT_PRIVATE_SMTP_FROM_ADDRESS?: string;
|
NEXT_PRIVATE_SMTP_FROM_ADDRESS?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vercel environment variables
|
||||||
|
*/
|
||||||
|
VERCEL?: string;
|
||||||
|
VERCEL_ENV?: 'production' | 'development' | 'preview';
|
||||||
|
VERCEL_URL?: string;
|
||||||
|
|
||||||
|
DEPLOYMENT_TARGET?: 'webapp' | 'marketing';
|
||||||
|
|
||||||
|
POSTGRES_URL?: string;
|
||||||
|
DATABASE_URL?: string;
|
||||||
|
POSTGRES_PRISMA_URL?: string;
|
||||||
|
POSTGRES_URL_NON_POOLING?: string;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
45
scripts/remap-vercel-env.cjs
Normal file
45
scripts/remap-vercel-env.cjs
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
/** @typedef {import('@documenso/tsconfig/process-env')} */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remap Vercel environment variables to our defined Next.js environment variables.
|
||||||
|
*
|
||||||
|
* @deprecated This is no longer needed because we can't inject runtime environment variables via next.config.js
|
||||||
|
*
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
const remapVercelEnv = () => {
|
||||||
|
if (!process.env.VERCEL || !process.env.DEPLOYMENT_TARGET) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (process.env.POSTGRES_URL) {
|
||||||
|
process.env.NEXT_PRIVATE_DATABASE_URL = process.env.POSTGRES_URL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (process.env.POSTGRES_URL_NON_POOLING) {
|
||||||
|
process.env.NEXT_PRIVATE_DIRECT_DATABASE_URL = process.env.POSTGRES_URL_NON_POOLING;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we're using a connection pool, we need to let Prisma know that
|
||||||
|
// we're using PgBouncer.
|
||||||
|
if (process.env.NEXT_PRIVATE_DATABASE_URL !== process.env.NEXT_PRIVATE_DIRECT_DATABASE_URL) {
|
||||||
|
const url = new URL(process.env.NEXT_PRIVATE_DATABASE_URL);
|
||||||
|
|
||||||
|
url.searchParams.set('pgbouncer', 'true');
|
||||||
|
|
||||||
|
process.env.NEXT_PRIVATE_DATABASE_URL = url.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (process.env.VERCEL_ENV !== 'production' && process.env.DEPLOYMENT_TARGET === 'webapp') {
|
||||||
|
process.env.NEXTAUTH_URL = `https://${process.env.VERCEL_URL}`;
|
||||||
|
process.env.NEXT_PUBLIC_WEBAPP_URL = `https://${process.env.VERCEL_URL}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (process.env.VERCEL_ENV !== 'production' && process.env.DEPLOYMENT_TARGET === 'marketing') {
|
||||||
|
process.env.NEXT_PUBLIC_MARKETING_URL = `https://${process.env.VERCEL_URL}`;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
remapVercelEnv,
|
||||||
|
};
|
||||||
107
scripts/vercel.sh
Executable file
107
scripts/vercel.sh
Executable file
@ -0,0 +1,107 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# Exit on error.
|
||||||
|
set -eo pipefail
|
||||||
|
|
||||||
|
# Get the directory of this script, regardless of where it is called from.
|
||||||
|
SCRIPT_DIR="$(readlink -f "$(dirname "$0")")"
|
||||||
|
|
||||||
|
|
||||||
|
function log() {
|
||||||
|
echo "[VercelBuild]: $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
function build_webapp() {
|
||||||
|
log "Building webapp for $VERCEL_ENV"
|
||||||
|
|
||||||
|
remap_database_integration
|
||||||
|
|
||||||
|
npm run prisma:generate --workspace=@documenso/prisma
|
||||||
|
npm run prisma:migrate-deploy --workspace=@documenso/prisma
|
||||||
|
|
||||||
|
if [[ "$VERCEL_ENV" != "production" ]]; then
|
||||||
|
log "Seeding database for $VERCEL_ENV"
|
||||||
|
|
||||||
|
npm run prisma:seed --workspace=@documenso/prisma
|
||||||
|
fi
|
||||||
|
|
||||||
|
npm run build -- --filter @documenso/web
|
||||||
|
}
|
||||||
|
|
||||||
|
function remap_webapp_env() {
|
||||||
|
if [[ "$VERCEL_ENV" != "production" ]]; then
|
||||||
|
log "Remapping webapp environment variables for $VERCEL_ENV"
|
||||||
|
|
||||||
|
export NEXTAUTH_URL="https://$VERCEL_URL"
|
||||||
|
export NEXT_PUBLIC_WEBAPP_URL="https://$VERCEL_URL"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function build_marketing() {
|
||||||
|
log "Building marketing for $VERCEL_ENV"
|
||||||
|
|
||||||
|
remap_database_integration
|
||||||
|
|
||||||
|
npm run prisma:generate --workspace=@documenso/prisma
|
||||||
|
npm run build -- --filter @documenso/marketing
|
||||||
|
}
|
||||||
|
|
||||||
|
function remap_marketing_env() {
|
||||||
|
if [[ "$VERCEL_ENV" != "production" ]]; then
|
||||||
|
log "Remapping marketing environment variables for $VERCEL_ENV"
|
||||||
|
|
||||||
|
export NEXT_PUBLIC_MARKETING_URL="https://$VERCEL_URL"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function remap_database_integration() {
|
||||||
|
log "Remapping Supabase integration for $VERCEL_ENV"
|
||||||
|
|
||||||
|
if [[ ! -z "$POSTGRES_URL" ]]; then
|
||||||
|
export NEXT_PRIVATE_DATABASE_URL="$POSTGRES_URL"
|
||||||
|
export NEXT_PRIVATE_DIRECT_DATABASE_URL="$POSTGRES_URL"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ! -z "$DATABASE_URL" ]]; then
|
||||||
|
export NEXT_PRIVATE_DATABASE_URL="$DATABASE_URL"
|
||||||
|
export NEXT_PRIVATE_DIRECT_DATABASE_URL="$DATABASE_URL"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ! -z "$POSTGRES_URL_NON_POOLING" ]]; then
|
||||||
|
export NEXT_PRIVATE_DATABASE_URL="$POSTGRES_URL?pgbouncer=true"
|
||||||
|
export NEXT_PRIVATE_DIRECT_DATABASE_URL="$POSTGRES_URL_NON_POOLING"
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
if [[ "$NEXT_PRIVATE_DATABASE_URL" == *"neon.tech"* ]]; then
|
||||||
|
log "Remapping for Neon integration"
|
||||||
|
|
||||||
|
PROJECT_ID="$(echo "$PGHOST" | cut -d'.' -f1)"
|
||||||
|
PGBOUNCER_HOST="$(echo "$PGHOST" | sed "s/${PROJECT_ID}/${PROJECT_ID}-pooler/")"
|
||||||
|
|
||||||
|
export NEXT_PRIVATE_DATABASE_URL="postgres://${PGUSER}:${PGPASSWORD}@${PGBOUNCER_HOST}/${PGDATABASE}?pgbouncer=true"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Navigate to the root of the project.
|
||||||
|
cd "$SCRIPT_DIR/.."
|
||||||
|
|
||||||
|
# Check if the script is running on Vercel.
|
||||||
|
if [[ -z "$VERCEL" ]]; then
|
||||||
|
log "ERROR - This script must be run as part of the Vercel build process."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
case "$DEPLOYMENT_TARGET" in
|
||||||
|
"webapp")
|
||||||
|
build_webapp
|
||||||
|
;;
|
||||||
|
"marketing")
|
||||||
|
build_marketing
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
log "ERROR - Missing or invalid DEPLOYMENT_TARGET environment variable."
|
||||||
|
log "ERROR - DEPLOYMENT_TARGET must be either 'webapp' or 'marketing'."
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
30
turbo.json
30
turbo.json
@ -2,8 +2,13 @@
|
|||||||
"$schema": "https://turbo.build/schema.json",
|
"$schema": "https://turbo.build/schema.json",
|
||||||
"pipeline": {
|
"pipeline": {
|
||||||
"build": {
|
"build": {
|
||||||
"dependsOn": ["^build"],
|
"dependsOn": [
|
||||||
"outputs": [".next/**", "!.next/cache/**"]
|
"^build"
|
||||||
|
],
|
||||||
|
"outputs": [
|
||||||
|
".next/**",
|
||||||
|
"!.next/cache/**"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"lint": {},
|
"lint": {},
|
||||||
"dev": {
|
"dev": {
|
||||||
@ -11,20 +16,22 @@
|
|||||||
"persistent": true
|
"persistent": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"globalDependencies": ["**/.env.*local"],
|
"globalDependencies": [
|
||||||
|
"**/.env.*local"
|
||||||
|
],
|
||||||
"globalEnv": [
|
"globalEnv": [
|
||||||
"APP_VERSION",
|
"APP_VERSION",
|
||||||
"NEXTAUTH_URL",
|
"NEXTAUTH_URL",
|
||||||
"NEXTAUTH_SECRET",
|
"NEXTAUTH_SECRET",
|
||||||
"NEXT_PUBLIC_APP_URL",
|
"NEXT_PUBLIC_WEBAPP_URL",
|
||||||
"NEXT_PUBLIC_SITE_URL",
|
"NEXT_PUBLIC_MARKETING_URL",
|
||||||
"NEXT_PUBLIC_POSTHOG_KEY",
|
"NEXT_PUBLIC_POSTHOG_KEY",
|
||||||
"NEXT_PUBLIC_POSTHOG_HOST",
|
"NEXT_PUBLIC_POSTHOG_HOST",
|
||||||
"NEXT_PUBLIC_FEATURE_BILLING_ENABLED",
|
"NEXT_PUBLIC_FEATURE_BILLING_ENABLED",
|
||||||
"NEXT_PUBLIC_STRIPE_COMMUNITY_PLAN_YEARLY_PRICE_ID",
|
"NEXT_PUBLIC_STRIPE_COMMUNITY_PLAN_YEARLY_PRICE_ID",
|
||||||
"NEXT_PUBLIC_STRIPE_COMMUNITY_PLAN_MONTHLY_PRICE_ID",
|
"NEXT_PUBLIC_STRIPE_COMMUNITY_PLAN_MONTHLY_PRICE_ID",
|
||||||
"NEXT_PRIVATE_DATABASE_URL",
|
"NEXT_PRIVATE_DATABASE_URL",
|
||||||
"NEXT_PRIVATE_NEXT_AUTH_SECRET",
|
"NEXT_PRIVATE_DIRECT_DATABASE_URL",
|
||||||
"NEXT_PRIVATE_GOOGLE_CLIENT_ID",
|
"NEXT_PRIVATE_GOOGLE_CLIENT_ID",
|
||||||
"NEXT_PRIVATE_GOOGLE_CLIENT_SECRET",
|
"NEXT_PRIVATE_GOOGLE_CLIENT_SECRET",
|
||||||
"NEXT_PUBLIC_UPLOAD_TRANSPORT",
|
"NEXT_PUBLIC_UPLOAD_TRANSPORT",
|
||||||
@ -48,6 +55,15 @@
|
|||||||
"NEXT_PRIVATE_SMTP_SECURE",
|
"NEXT_PRIVATE_SMTP_SECURE",
|
||||||
"NEXT_PRIVATE_SMTP_FROM_NAME",
|
"NEXT_PRIVATE_SMTP_FROM_NAME",
|
||||||
"NEXT_PRIVATE_SMTP_FROM_ADDRESS",
|
"NEXT_PRIVATE_SMTP_FROM_ADDRESS",
|
||||||
"NEXT_PRIVATE_STRIPE_API_KEY"
|
"NEXT_PRIVATE_STRIPE_API_KEY",
|
||||||
|
|
||||||
|
"VERCEL",
|
||||||
|
"VERCEL_ENV",
|
||||||
|
"VERCEL_URL",
|
||||||
|
"DEPLOYMENT_TARGET",
|
||||||
|
"POSTGRES_URL",
|
||||||
|
"DATABASE_URL",
|
||||||
|
"POSTGRES_PRISMA_URL",
|
||||||
|
"POSTGRES_URL_NON_POOLING"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user