Files
zitadel/apps/login/scripts/server.mjs
T
RamonandGitHub 057fb8dff2 fix(login): prettier setup (#11798)
# Which Problems Are Solved
Invalid formatting in the login codebase due to invalid prettier
configuration

# How the Problems Are Solved
Fxed .prettierignore wildcards for login source files

# Additional Changes
Removed .prettierrc file because there is already a prettier.config.mjs
file

# Additional Context
2026-03-10 13:30:20 +00:00

162 lines
5.1 KiB
JavaScript

import { accessSync, constants, readFileSync } from "node:fs";
import { createServer } from "node:https";
import { createRequire } from "node:module";
if (process.env.ZITADEL_TLS_ENABLED !== "true") {
// The build script must rename the Next.js-generated server.js to next-server.js.
// Validate that the file exists before importing to provide a clearer error if the build step fails.
try {
accessSync(new URL("./next-server.js", import.meta.url), constants.R_OK);
} catch (err) {
console.error(
'Unable to find or read "./next-server.js". Ensure the build script has renamed Next.js\'s server.js to next-server.js.',
err,
);
process.exit(1);
}
await import("./next-server.js");
} else {
const certPath = process.env.ZITADEL_TLS_CERTPATH;
const keyPath = process.env.ZITADEL_TLS_KEYPATH;
if (!certPath || !keyPath) {
console.error(
"ZITADEL_TLS_ENABLED is set to true but ZITADEL_TLS_CERTPATH or ZITADEL_TLS_KEYPATH are missing. Both must be set when TLS is enabled.",
);
process.exit(1);
}
try {
accessSync(certPath, constants.R_OK);
} catch (err) {
console.error(`Certificate file is not readable: ${certPath}`, err);
process.exit(1);
}
try {
accessSync(keyPath, constants.R_OK);
} catch (err) {
console.error(`Key file is not readable: ${keyPath}`, err);
process.exit(1);
}
const cert = readFileSync(certPath);
const key = readFileSync(keyPath);
// Requires Node.js >= 20.11.0 (or >= 21.2.0) for import.meta.dirname support.
const appDir = import.meta.dirname;
const requiredServerFilesPath = new URL(".next/required-server-files.json", import.meta.url);
let requiredServerFiles;
try {
accessSync(requiredServerFilesPath, constants.R_OK);
const requiredServerFilesContent = readFileSync(requiredServerFilesPath, "utf8");
requiredServerFiles = JSON.parse(requiredServerFilesContent);
} catch (err) {
console.error(
"Failed to load .next/required-server-files.json. The Next.js build may be incomplete or the file may contain invalid JSON.",
err,
);
process.exit(1);
}
process.env.__NEXT_PRIVATE_STANDALONE_CONFIG = JSON.stringify(requiredServerFiles.config);
process.env.NODE_ENV = "production";
process.chdir(appDir);
const currentPort = parseInt(process.env.PORT, 10) || 3000;
const hostname = process.env.HOSTNAME || "0.0.0.0";
// KEEP_ALIVE_TIMEOUT is expected to be in milliseconds.
// Reject values that are negative or unreasonably large to avoid resource issues.
const MAX_KEEP_ALIVE_TIMEOUT_MS = 10 * 60 * 1000; // 10 minutes
let keepAliveTimeout = parseInt(process.env.KEEP_ALIVE_TIMEOUT, 10);
if (
Number.isNaN(keepAliveTimeout) ||
!Number.isFinite(keepAliveTimeout) ||
keepAliveTimeout < 0 ||
keepAliveTimeout > MAX_KEEP_ALIVE_TIMEOUT_MS
) {
keepAliveTimeout = undefined;
}
const require = createRequire(import.meta.url);
require("next");
// NOTE: This imports an internal Next.js API that is not part of the public, semver-stable surface.
// - Verified with Next.js version 15.5.10 (see package.json).
// - This may break on Next.js upgrades; if Next.js is updated, re-check that
// `next/dist/server/lib/start-server` still exists and that `getRequestHandlers` behaves as expected.
// - This is currently required to support HTTPS with self-signed certificates in production mode,
// as there is no equivalent public API in Next.js at this time.
const { getRequestHandlers } = require("next/dist/server/lib/start-server");
const httpsServer = createServer({ key, cert });
if (keepAliveTimeout !== undefined) {
httpsServer.keepAliveTimeout = keepAliveTimeout;
}
const { requestHandler, upgradeHandler } = await getRequestHandlers({
dir: appDir,
port: currentPort,
isDev: false,
server: httpsServer,
hostname,
keepAliveTimeout,
});
httpsServer.on("request", async (req, res) => {
try {
await requestHandler(req, res);
} catch (err) {
res.statusCode = 500;
res.end("Internal Server Error");
console.error(`Failed to handle request for ${req.url}`);
console.error(err);
}
});
httpsServer.on("upgrade", async (req, socket, head) => {
try {
await upgradeHandler(req, socket, head);
} catch (err) {
socket.destroy();
console.error(`Failed to handle upgrade for ${req.url}`);
console.error(err);
}
});
httpsServer.on("error", (err) => {
console.error("Failed to start HTTPS server");
console.error(err);
process.exit(1);
});
let cleanupStarted = false;
const cleanup = () => {
if (cleanupStarted) return;
cleanupStarted = true;
httpsServer.close((err) => {
if (err) {
console.error(err);
process.exit(1);
} else {
process.exit(0);
}
});
};
if (!process.env.NEXT_MANUAL_SIG_HANDLE) {
process.on("SIGINT", cleanup);
process.on("SIGTERM", cleanup);
}
httpsServer.listen(currentPort, hostname, () => {
const formattedHost = hostname.includes(":") ? `[${hostname}]` : hostname;
const readyUrl = new URL(`https://${formattedHost}:${currentPort}`);
console.log(`> Ready on ${readyUrl}`);
});
}