mirror of
https://github.com/supabase/supabase.git
synced 2026-10-13 13:19:09 +03:00
It's possible for individual PRs to pass typechecking, while the merge result fails it. To prevent errors from getting into production, we can fail the prod build if typecheck fails. Typecheck is still ignored on preview builds for efficiency, since those are blocked on the GitHub typecheck Action.
572 lines
16 KiB
JavaScript
572 lines
16 KiB
JavaScript
const { withSentryConfig } = require('@sentry/nextjs')
|
|
const withBundleAnalyzer = require('@next/bundle-analyzer')({
|
|
enabled: process.env.ANALYZE === 'true',
|
|
})
|
|
const { getCSP } = require('./csp')
|
|
|
|
// Required for nextjs standalone build
|
|
const path = require('path')
|
|
|
|
function getAssetPrefix() {
|
|
// If not force enabled, but not production env, disable CDN
|
|
if (process.env.FORCE_ASSET_CDN !== '1' && process.env.VERCEL_ENV !== 'production') {
|
|
return undefined
|
|
}
|
|
|
|
// Force disable CDN
|
|
if (process.env.FORCE_ASSET_CDN === '-1') {
|
|
return undefined
|
|
}
|
|
|
|
const SUPABASE_ASSETS_URL =
|
|
process.env.NEXT_PUBLIC_ENVIRONMENT === 'staging'
|
|
? 'https://frontend-assets.supabase.green'
|
|
: 'https://frontend-assets.supabase.com'
|
|
|
|
return `${SUPABASE_ASSETS_URL}/${process.env.SITE_NAME}/${process.env.VERCEL_GIT_COMMIT_SHA.substring(0, 12)}`
|
|
}
|
|
|
|
/**
|
|
* @type {import('next').NextConfig}
|
|
*/
|
|
const nextConfig = {
|
|
basePath: process.env.NEXT_PUBLIC_BASE_PATH,
|
|
assetPrefix: getAssetPrefix(),
|
|
output: 'standalone',
|
|
experimental: {
|
|
webpackBuildWorker: true,
|
|
},
|
|
async rewrites() {
|
|
return [
|
|
{
|
|
source: `/.well-known/vercel/flags`,
|
|
destination: `https://supabase.com/.well-known/vercel/flags`,
|
|
basePath: false,
|
|
},
|
|
]
|
|
},
|
|
async redirects() {
|
|
return [
|
|
...(process.env.NEXT_PUBLIC_IS_PLATFORM === 'true'
|
|
? [
|
|
{
|
|
source: '/',
|
|
has: [
|
|
{
|
|
type: 'query',
|
|
key: 'next',
|
|
value: 'new-project',
|
|
},
|
|
],
|
|
destination: '/new/new-project',
|
|
permanent: false,
|
|
},
|
|
{
|
|
source: '/',
|
|
destination: '/org',
|
|
permanent: false,
|
|
},
|
|
{
|
|
source: '/register',
|
|
destination: '/sign-up',
|
|
permanent: false,
|
|
},
|
|
{
|
|
source: '/signup',
|
|
destination: '/sign-up',
|
|
permanent: false,
|
|
},
|
|
{
|
|
source: '/signin',
|
|
destination: '/sign-in',
|
|
permanent: false,
|
|
},
|
|
{
|
|
source: '/login',
|
|
destination: '/sign-in',
|
|
permanent: false,
|
|
},
|
|
{
|
|
source: '/log-in',
|
|
destination: '/sign-in',
|
|
permanent: false,
|
|
},
|
|
]
|
|
: [
|
|
{
|
|
source: '/',
|
|
destination: '/project/default',
|
|
permanent: false,
|
|
},
|
|
{
|
|
source: '/register',
|
|
destination: '/project/default',
|
|
permanent: false,
|
|
},
|
|
{
|
|
source: '/signup',
|
|
destination: '/project/default',
|
|
permanent: false,
|
|
},
|
|
{
|
|
source: '/signin',
|
|
destination: '/project/default',
|
|
permanent: false,
|
|
},
|
|
{
|
|
source: '/login',
|
|
destination: '/project/default',
|
|
permanent: false,
|
|
},
|
|
{
|
|
source: '/log-in',
|
|
destination: '/project/default',
|
|
permanent: false,
|
|
},
|
|
]),
|
|
{
|
|
source: '/project/:ref/auth',
|
|
destination: '/project/:ref/auth/users',
|
|
permanent: true,
|
|
},
|
|
{
|
|
source: '/project/:ref/database',
|
|
destination: '/project/:ref/database/tables',
|
|
permanent: true,
|
|
},
|
|
{
|
|
source: '/project/:ref/database/graphiql',
|
|
destination: '/project/:ref/api/graphiql',
|
|
permanent: true,
|
|
},
|
|
{
|
|
source: '/project/:ref/storage',
|
|
destination: '/project/:ref/storage/buckets',
|
|
permanent: true,
|
|
},
|
|
{
|
|
source: '/project/:ref/settings/storage',
|
|
destination: '/project/:ref/storage/settings',
|
|
permanent: true,
|
|
},
|
|
{
|
|
source: '/project/:ref/settings/database',
|
|
destination: '/project/:ref/database/settings',
|
|
permanent: true,
|
|
},
|
|
{
|
|
source: '/project/:ref/settings',
|
|
destination: '/project/:ref/settings/general',
|
|
permanent: true,
|
|
},
|
|
{
|
|
source: '/project/:ref/auth/settings',
|
|
destination: '/project/:ref/auth/users',
|
|
permanent: true,
|
|
},
|
|
{
|
|
source: '/project/:ref/settings/billing/subscription',
|
|
has: [
|
|
{
|
|
type: 'query',
|
|
key: 'panel',
|
|
value: 'subscriptionPlan',
|
|
},
|
|
],
|
|
destination: '/org/_/billing?panel=subscriptionPlan',
|
|
permanent: true,
|
|
},
|
|
{
|
|
source: '/project/:ref/settings/billing/subscription',
|
|
has: [
|
|
{
|
|
type: 'query',
|
|
key: 'panel',
|
|
value: 'pitr',
|
|
},
|
|
],
|
|
destination: '/project/:ref/settings/addons?panel=pitr',
|
|
permanent: true,
|
|
},
|
|
{
|
|
source: '/project/:ref/settings/billing/subscription',
|
|
has: [
|
|
{
|
|
type: 'query',
|
|
key: 'panel',
|
|
value: 'computeInstance',
|
|
},
|
|
],
|
|
destination: '/project/:ref/settings/compute-and-disk',
|
|
permanent: true,
|
|
},
|
|
{
|
|
source: '/project/:ref/settings/billing/subscription',
|
|
has: [
|
|
{
|
|
type: 'query',
|
|
key: 'panel',
|
|
value: 'customDomain',
|
|
},
|
|
],
|
|
destination: '/project/:ref/settings/addons?panel=customDomain',
|
|
permanent: true,
|
|
},
|
|
{
|
|
source: '/project/:ref/settings/billing/subscription',
|
|
destination: '/org/_/billing',
|
|
permanent: true,
|
|
},
|
|
{
|
|
source: '/project/:ref/database/api-logs',
|
|
destination: '/project/:ref/logs/edge-logs',
|
|
permanent: true,
|
|
},
|
|
{
|
|
source: '/project/:ref/database/postgres-logs',
|
|
destination: '/project/:ref/logs/postgres-logs',
|
|
permanent: true,
|
|
},
|
|
{
|
|
source: '/project/:ref/database/postgrest-logs',
|
|
destination: '/project/:ref/logs/postgrest-logs',
|
|
permanent: true,
|
|
},
|
|
{
|
|
source: '/project/:ref/database/pgbouncer-logs',
|
|
destination: '/project/:ref/logs/pooler-logs',
|
|
permanent: true,
|
|
},
|
|
{
|
|
source: '/project/:ref/logs/pgbouncer-logs',
|
|
destination: '/project/:ref/logs/pooler-logs',
|
|
permanent: true,
|
|
},
|
|
{
|
|
source: '/project/:ref/database/realtime-logs',
|
|
destination: '/project/:ref/logs/realtime-logs',
|
|
permanent: true,
|
|
},
|
|
{
|
|
source: '/project/:ref/storage/logs',
|
|
destination: '/project/:ref/logs/storage-logs',
|
|
permanent: true,
|
|
},
|
|
{
|
|
source: '/project/:ref/auth/logs',
|
|
destination: '/project/:ref/logs/auth-logs',
|
|
permanent: true,
|
|
},
|
|
{
|
|
source: '/project/:ref/logs-explorer',
|
|
destination: '/project/:ref/logs/explorer',
|
|
permanent: true,
|
|
},
|
|
{
|
|
source: '/project/:ref/sql/templates',
|
|
destination: '/project/:ref/sql',
|
|
permanent: true,
|
|
},
|
|
{
|
|
source: '/org/:slug/settings',
|
|
destination: '/org/:slug/general',
|
|
permanent: true,
|
|
},
|
|
{
|
|
source: '/project/:ref/settings/billing/update',
|
|
destination: '/org/_/billing',
|
|
permanent: true,
|
|
},
|
|
{
|
|
source: '/project/:ref/settings/billing/update/free',
|
|
destination: '/org/_/billing',
|
|
permanent: true,
|
|
},
|
|
{
|
|
source: '/project/:ref/settings/billing/update/pro',
|
|
destination: '/org/_/billing',
|
|
permanent: true,
|
|
},
|
|
{
|
|
source: '/project/:ref/settings/billing/update/team',
|
|
destination: '/org/_/billing',
|
|
permanent: true,
|
|
},
|
|
{
|
|
source: '/project/:ref/settings/billing/update/enterprise',
|
|
destination: '/org/_/billing',
|
|
permanent: true,
|
|
},
|
|
{
|
|
permanent: true,
|
|
source: '/project/:ref/reports/linter',
|
|
destination: '/project/:ref/database/linter',
|
|
},
|
|
{
|
|
permanent: true,
|
|
source: '/project/:ref/query-performance',
|
|
destination: '/project/:ref/advisors/query-performance',
|
|
},
|
|
{
|
|
permanent: true,
|
|
source: '/project/:ref/database/query-performance',
|
|
destination: '/project/:ref/advisors/query-performance',
|
|
},
|
|
{
|
|
permanent: true,
|
|
source: '/project/:ref/auth/column-privileges',
|
|
destination: '/project/:ref/database/column-privileges',
|
|
},
|
|
{
|
|
permanent: true,
|
|
source: '/project/:ref/database/linter',
|
|
destination: '/project/:ref/database/security-advisor',
|
|
},
|
|
{
|
|
permanent: true,
|
|
source: '/project/:ref/database/security-advisor',
|
|
destination: '/project/:ref/advisors/security',
|
|
},
|
|
{
|
|
permanent: true,
|
|
source: '/project/:ref/database/performance-advisor',
|
|
destination: '/project/:ref/advisors/performance',
|
|
},
|
|
{
|
|
permanent: true,
|
|
source: '/project/:ref/database/webhooks',
|
|
destination: '/project/:ref/integrations/webhooks/overview',
|
|
},
|
|
{
|
|
permanent: true,
|
|
source: '/project/:ref/database/wrappers',
|
|
destination: '/project/:ref/integrations?category=wrapper',
|
|
},
|
|
{
|
|
permanent: true,
|
|
source: '/project/:ref/database/cron-jobs',
|
|
destination: '/project/:ref/integrations/cron',
|
|
},
|
|
{
|
|
permanent: true,
|
|
source: '/project/:ref/api/graphiql',
|
|
destination: '/project/:ref/integrations/graphiql',
|
|
},
|
|
{
|
|
permanent: true,
|
|
source: '/project/:ref/settings/vault/secrets',
|
|
destination: '/project/:ref/integrations/vault/secrets',
|
|
},
|
|
{
|
|
permanent: true,
|
|
source: '/project/:ref/settings/vault/keys',
|
|
destination: '/project/:ref/integrations/vault/keys',
|
|
},
|
|
{
|
|
permanent: true,
|
|
source: '/project/:ref/integrations/cron-jobs',
|
|
destination: '/project/:ref/integrations/cron',
|
|
},
|
|
{
|
|
permanent: true,
|
|
source: '/project/:ref/settings/warehouse',
|
|
destination: '/project/:ref/settings/general',
|
|
},
|
|
{
|
|
permanent: true,
|
|
source: '/project/:ref/settings/functions',
|
|
destination: '/project/:ref/functions/secrets',
|
|
},
|
|
{
|
|
source: '/org/:slug/invoices',
|
|
destination: '/org/:slug/billing#invoices',
|
|
permanent: true,
|
|
},
|
|
{
|
|
source: '/projects',
|
|
destination: '/organizations',
|
|
permanent: false,
|
|
},
|
|
|
|
...(process.env.NEXT_PUBLIC_BASE_PATH?.length
|
|
? [
|
|
{
|
|
source: '/',
|
|
destination: process.env.NEXT_PUBLIC_BASE_PATH,
|
|
basePath: false,
|
|
permanent: false,
|
|
},
|
|
]
|
|
: []),
|
|
]
|
|
},
|
|
async headers() {
|
|
return [
|
|
{
|
|
source: '/(.*?)',
|
|
headers: [
|
|
{
|
|
key: 'X-Frame-Options',
|
|
value: 'DENY',
|
|
},
|
|
{
|
|
key: 'X-Content-Type-Options',
|
|
value: 'no-sniff',
|
|
},
|
|
{
|
|
key: 'Strict-Transport-Security',
|
|
value:
|
|
process.env.NEXT_PUBLIC_IS_PLATFORM === 'true' && process.env.VERCEL === '1'
|
|
? 'max-age=31536000; includeSubDomains; preload'
|
|
: '',
|
|
},
|
|
{
|
|
key: 'Content-Security-Policy',
|
|
value:
|
|
process.env.NEXT_PUBLIC_IS_PLATFORM === 'true' ? getCSP() : "frame-ancestors 'none';",
|
|
},
|
|
{
|
|
key: 'Referrer-Policy',
|
|
value: 'strict-origin-when-cross-origin',
|
|
},
|
|
],
|
|
},
|
|
{
|
|
source: '/.well-known/vercel/flags',
|
|
headers: [
|
|
{
|
|
key: 'content-type',
|
|
value: 'application/json',
|
|
},
|
|
],
|
|
},
|
|
{
|
|
source: '/img/:slug*',
|
|
headers: [{ key: 'cache-control', value: 'public, max-age=2592000' }],
|
|
},
|
|
{
|
|
source: '/favicon/:slug*',
|
|
headers: [{ key: 'cache-control', value: 'public, max-age=86400' }],
|
|
},
|
|
{
|
|
source: '/(.*).ts',
|
|
headers: [{ key: 'content-type', value: 'text/typescript' }],
|
|
},
|
|
]
|
|
},
|
|
images: {
|
|
// to make Vercel avatars work without issue. Vercel uses SVGs for users who don't have set avatars.
|
|
dangerouslyAllowSVG: false,
|
|
remotePatterns: [
|
|
{
|
|
protocol: 'https',
|
|
hostname: 'github.com',
|
|
port: '',
|
|
pathname: '**',
|
|
},
|
|
{
|
|
protocol: 'https',
|
|
hostname: 'avatars.githubusercontent.com',
|
|
port: '',
|
|
pathname: '/u/*',
|
|
},
|
|
{
|
|
protocol: 'https',
|
|
hostname: 'api-frameworks.vercel.sh',
|
|
port: '',
|
|
pathname: '**',
|
|
},
|
|
{
|
|
protocol: 'https',
|
|
hostname: 'vercel.com',
|
|
port: '',
|
|
pathname: '**',
|
|
},
|
|
],
|
|
},
|
|
transpilePackages: [
|
|
'ui',
|
|
'ui-patterns',
|
|
'common',
|
|
'shared-data',
|
|
'api-types',
|
|
'icons',
|
|
'libpg-query',
|
|
],
|
|
turbopack: {
|
|
rules: {
|
|
'*.md': {
|
|
loaders: ['raw-loader'],
|
|
as: '*.js',
|
|
},
|
|
},
|
|
},
|
|
// Both configs for turbopack and webpack need to exist (and sync) because Nextjs still uses webpack for production building
|
|
webpack(config) {
|
|
config.module?.rules
|
|
.find((rule) => rule.oneOf)
|
|
.oneOf.forEach((rule) => {
|
|
if (rule.issuer?.and?.[0]?.toString().includes('_app')) {
|
|
const and = rule.issuer.and
|
|
rule.issuer.or = [/[\\/]node_modules[\\/]monaco-editor[\\/]/, { and }]
|
|
delete rule.issuer.and
|
|
}
|
|
})
|
|
|
|
// .md files to be loaded as raw text
|
|
config.module.rules.push({
|
|
test: /\.md$/,
|
|
type: 'asset/source',
|
|
})
|
|
|
|
return config
|
|
},
|
|
onDemandEntries: {
|
|
maxInactiveAge: 24 * 60 * 60 * 1000,
|
|
pagesBufferLength: 100,
|
|
},
|
|
typescript: {
|
|
// On previews, typechecking is run via GitHub Action only for efficiency
|
|
// On production, we turn it on to prevent errors from conflicting PRs getting into
|
|
// prod
|
|
ignoreBuildErrors: process.env.NEXT_PUBLIC_VERCEL_ENV === 'production' ? false : true,
|
|
},
|
|
eslint: {
|
|
// We are already running linting via GH action, this will skip linting during production build on Vercel
|
|
ignoreDuringBuilds: true,
|
|
},
|
|
}
|
|
|
|
// module.exports = withBundleAnalyzer(nextConfig)
|
|
// Make sure adding Sentry options is the last code to run before exporting, to
|
|
// ensure that your source maps include changes from all other Webpack plugins
|
|
module.exports =
|
|
process.env.NEXT_PUBLIC_IS_PLATFORM === 'true'
|
|
? withSentryConfig(withBundleAnalyzer(nextConfig), {
|
|
silent: true,
|
|
|
|
// For all available options, see:
|
|
// https://docs.sentry.io/platforms/javascript/guides/nextjs/manual-setup/
|
|
|
|
// Upload a larger set of source maps for prettier stack traces (increases build time)
|
|
widenClientFileUpload: true,
|
|
|
|
// Automatically annotate React components to show their full name in breadcrumbs and session replay
|
|
reactComponentAnnotation: {
|
|
enabled: true,
|
|
},
|
|
|
|
// Hides source maps from generated client bundles
|
|
hideSourceMaps: true,
|
|
|
|
// Automatically tree-shake Sentry logger statements to reduce bundle size
|
|
disableLogger: true,
|
|
|
|
// Enables automatic instrumentation of Vercel Cron Monitors. (Does not yet work with App Router route handlers.)
|
|
// See the following for more information:
|
|
// https://docs.sentry.io/product/crons/
|
|
// https://vercel.com/docs/cron-jobs
|
|
automaticVercelMonitors: true,
|
|
})
|
|
: nextConfig
|