ultisuite-client/next.config.mjs
R3D347HR4Y 9ea2d3325d
Some checks are pending
E2E / Playwright e2e (push) Waiting to run
feat(auth): enhance authentication flows with embedded support and UI improvements
- Updated login and signup components to utilize AuthCard for better user experience during redirection.
- Introduced AuthentikEmbedDialog for seamless integration of Authentik's identity portal within the application.
- Enhanced password recovery and signup flows with dynamic theme handling and improved loading states.
- Refactored existing components to streamline authentication processes and improve maintainability.
2026-06-21 00:12:45 +02:00

161 lines
4.3 KiB
JavaScript

/*
* Copyright (c) 2026 Eliott Guillaumin
* All rights reserved.
*/
import path from "node:path"
import { fileURLToPath } from "node:url"
/** @type {import('next').NextConfig} */
const projectRoot = path.dirname(fileURLToPath(import.meta.url))
const ultiProxyOrigin = process.env.ULTI_PROXY_ORIGIN ?? "http://127.0.0.1"
/** "s" for https/wss when SECURE=s (or true/1). */
function suiteSecureSuffix() {
const secure = process.env.SECURE?.trim().toLowerCase()
if (secure === "s" || secure === "true" || secure === "1") return "s"
return ""
}
/** Derive browser-facing NEXT_PUBLIC_* URLs from PUBLIC_HOST + SECURE. */
function suitePublicEnv() {
const host = (
process.env.PUBLIC_HOST ??
process.env.DOMAIN ??
"localhost"
).trim()
const s = suiteSecureSuffix()
const devPort = process.env.NEXT_DEV_PORT?.trim() || "3004"
const hasPort = host.includes(":")
const origin =
s || hasPort ? `http${s}://${host}` : `http${s}://${host}:${devPort}`
return {
NEXT_PUBLIC_APP_URL: origin,
NEXT_PUBLIC_WS_URL: `ws${s}://${host}/ws`,
NEXT_PUBLIC_OIDC_ISSUER: `${origin}/auth/application/o/ulti/`,
NEXT_PUBLIC_ONLYOFFICE_URL: `${origin}/office`,
NEXT_PUBLIC_HOCUSPOCUS_URL: `ws${s}://${host}/collab/`,
NEXT_PUBLIC_AI_ORIGIN: origin,
NEXT_PUBLIC_ULTISPACE_ORIGIN: origin,
}
}
/** Hostnames allowed to load /_next/* in dev (tunnel, LAN, public dev domain). */
function allowedDevOrigins() {
const hosts = new Set(["127.0.0.1", "localhost"])
const publicHost = (
process.env.PUBLIC_HOST ??
process.env.DOMAIN ??
""
).trim()
if (publicHost) hosts.add(publicHost)
const derived = suitePublicEnv().NEXT_PUBLIC_APP_URL
if (derived) {
try {
hosts.add(new URL(derived).hostname)
} catch {
/* ignore invalid origin */
}
}
return [...hosts]
}
/**
* Mobile (Tauri) build: a fully static export with no server runtime. The
* server-only API route handlers are named `route.web.ts` and are excluded
* here by NOT registering the `web.ts` page extension (see `pageExtensions`),
* so they only compile for the web/standalone build.
*/
const isMobile = process.env.NEXT_PUBLIC_MOBILE === "1"
const webPageExtensions = ["web.tsx", "web.ts", "tsx", "ts", "jsx", "js"]
const mobilePageExtensions = ["tsx", "ts", "jsx", "js"]
/** @type {import('next').NextConfig} */
const baseConfig = {
outputFileTracingRoot: projectRoot,
allowedDevOrigins: allowedDevOrigins(),
env: suitePublicEnv(),
typescript: {
ignoreBuildErrors: true,
},
images: {
unoptimized: true,
},
turbopack: {
resolveAlias: {
canvas: "./lib/empty-module.mjs",
},
},
webpack: (config) => {
config.resolve.alias = {
...config.resolve.alias,
canvas: false,
}
return config
},
}
const webConfig = {
...baseConfig,
output: "standalone",
// Docker standalone tracing only — do not set turbopack.root to projectRoot:
// breaks Tailwind @import resolution (resolves from parent /Users/red/workdev).
pageExtensions: webPageExtensions,
async redirects() {
return [
{
source: "/mail/settings",
destination: "/settings",
permanent: true,
},
{
source: "/mail/settings/:section*",
destination: "/settings/:section*",
permanent: true,
},
{
source: "/compte",
destination: "/account",
permanent: true,
},
{
source: "/compte/:section*",
destination: "/account/:section*",
permanent: true,
},
]
},
async rewrites() {
return [
{
source: "/api/v1/:path*",
destination: `${ultiProxyOrigin}/api/v1/:path*`,
},
{
source: "/ai/:path*",
destination: `${ultiProxyOrigin}/ai/:path*`,
},
{
source: "/ai",
destination: `${ultiProxyOrigin}/ai`,
},
]
},
}
const mobileConfig = {
...baseConfig,
output: "export",
// Mobile shells navigate client-side; the static export serves the start
// route (e.g. /mail) and Next's router + native deep-links handle the rest.
trailingSlash: true,
pageExtensions: mobilePageExtensions,
// No rewrites/redirects: the bundle calls an absolute backend URL chosen at
// runtime by the server picker, and path redirects run client-side.
}
const nextConfig = isMobile ? mobileConfig : webConfig
export default nextConfig