feat: local-cpl-sim.mjs
This commit is contained in:
@@ -6,6 +6,6 @@ NEXT_PUBLIC_USE_MOCK_BACKEND_LOOP_START=false
|
||||
NEXT_PUBLIC_EXPORT_STATIC=false
|
||||
NEXT_PUBLIC_USE_CGI=false
|
||||
# App-Versionsnummer
|
||||
NEXT_PUBLIC_APP_VERSION=1.6.832
|
||||
NEXT_PUBLIC_APP_VERSION=1.6.833
|
||||
NEXT_PUBLIC_CPL_MODE=json # json (Entwicklungsumgebung) oder jsSimulatedProd (CPL ->CGI-Interface-Simulator) oder production (CPL-> CGI-Interface Platzhalter)
|
||||
|
||||
|
||||
@@ -5,5 +5,5 @@ NEXT_PUBLIC_CPL_API_PATH=/CPL
|
||||
NEXT_PUBLIC_EXPORT_STATIC=true
|
||||
NEXT_PUBLIC_USE_CGI=true
|
||||
# App-Versionsnummer
|
||||
NEXT_PUBLIC_APP_VERSION=1.6.832
|
||||
NEXT_PUBLIC_APP_VERSION=1.6.833
|
||||
NEXT_PUBLIC_CPL_MODE=production
|
||||
@@ -1,3 +1,8 @@
|
||||
## [1.6.833] – 2025-09-04
|
||||
|
||||
- test: npx playwright test erfolgreich
|
||||
|
||||
---
|
||||
## [1.6.832] – 2025-09-03
|
||||
|
||||
- refactoring: test files
|
||||
|
||||
4
package-lock.json
generated
4
package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "cpl-v4",
|
||||
"version": "1.6.832",
|
||||
"version": "1.6.833",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "cpl-v4",
|
||||
"version": "1.6.832",
|
||||
"version": "1.6.833",
|
||||
"dependencies": {
|
||||
"@fontsource/roboto": "^5.1.0",
|
||||
"@headlessui/react": "^2.2.4",
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
{
|
||||
"name": "cpl-v4",
|
||||
"version": "1.6.832",
|
||||
"version": "1.6.833",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "next dev -p 3000",
|
||||
"clean": "rimraf .next out",
|
||||
"build": "npm run clean && cross-env EXPORT_STATIC=true next build",
|
||||
"postbuild": "copy LICENSE_ICONIFY.txt out\\LICENSE_ICONIFY.txt",
|
||||
"serve:sim": "node ./scripts/local-cpl-sim.mjs",
|
||||
"start": "next start",
|
||||
"typecheck": "tsc --noEmit",
|
||||
"check": "npm run lint && npm run typecheck",
|
||||
|
||||
137
scripts/local-cpl-sim.mjs
Normal file
137
scripts/local-cpl-sim.mjs
Normal file
@@ -0,0 +1,137 @@
|
||||
// Minimal local simulator for testing SAN01 replacement only.
|
||||
// - Serves the exported "out" folder.
|
||||
// - For text files (.html, .js, .json, .css, .txt) replaces <%=SAN01%> -> "ismail" on the fly.
|
||||
// - Supports mapping /CPL?/path to /path in the export.
|
||||
|
||||
import http from "http";
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
|
||||
const PORT = process.env.PORT ? Number(process.env.PORT) : 3030;
|
||||
const ROOT = path.join(process.cwd(), "out");
|
||||
|
||||
function exists(p) {
|
||||
try {
|
||||
fs.accessSync(p, fs.constants.F_OK);
|
||||
return true;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function contentTypeByExt(ext) {
|
||||
switch (ext) {
|
||||
case ".html":
|
||||
return "text/html; charset=utf-8";
|
||||
case ".js":
|
||||
return "application/javascript; charset=utf-8";
|
||||
case ".json":
|
||||
return "application/json; charset=utf-8";
|
||||
case ".css":
|
||||
return "text/css; charset=utf-8";
|
||||
case ".txt":
|
||||
return "text/plain; charset=utf-8";
|
||||
case ".svg":
|
||||
return "image/svg+xml";
|
||||
case ".png":
|
||||
return "image/png";
|
||||
case ".jpg":
|
||||
case ".jpeg":
|
||||
return "image/jpeg";
|
||||
case ".ico":
|
||||
return "image/x-icon";
|
||||
default:
|
||||
return "application/octet-stream";
|
||||
}
|
||||
}
|
||||
|
||||
function isTextExt(ext) {
|
||||
return [".html", ".js", ".json", ".css", ".txt", ".svg"].includes(ext);
|
||||
}
|
||||
|
||||
function sendFileWithSAN01Replace(res, filePath) {
|
||||
const ext = path.extname(filePath).toLowerCase();
|
||||
const type = contentTypeByExt(ext);
|
||||
if (isTextExt(ext)) {
|
||||
try {
|
||||
let content = fs.readFileSync(filePath, "utf8");
|
||||
content = content.replace(/<%=SAN01%>/g, "ismail");
|
||||
res.writeHead(200, { "Content-Type": type });
|
||||
res.end(content);
|
||||
return;
|
||||
} catch {
|
||||
// fall through to stream as binary if read fails
|
||||
}
|
||||
}
|
||||
res.writeHead(200, { "Content-Type": type });
|
||||
fs.createReadStream(filePath).pipe(res);
|
||||
}
|
||||
|
||||
function notFound(res) {
|
||||
res.writeHead(404, { "Content-Type": "text/plain; charset=utf-8" });
|
||||
res.end("Not Found");
|
||||
}
|
||||
|
||||
const server = http.createServer((req, res) => {
|
||||
try {
|
||||
const url = new URL(req.url, `http://localhost:${PORT}`);
|
||||
const pathname = decodeURIComponent(url.pathname);
|
||||
const rawQuery = req.url.includes("?") ? req.url.split("?")[1] : "";
|
||||
|
||||
// Minimal CPL? mapping: /CPL?/CPL/... -> /CPL/...
|
||||
if (pathname === "/CPL" && rawQuery) {
|
||||
const q = decodeURIComponent(rawQuery);
|
||||
if (q.startsWith("/")) {
|
||||
const rel = q.replace(/^\/+/, "");
|
||||
const target = path.join(ROOT, rel);
|
||||
if (exists(target) && fs.statSync(target).isFile()) {
|
||||
return sendFileWithSAN01Replace(res, target);
|
||||
}
|
||||
if (exists(target) && fs.statSync(target).isDirectory()) {
|
||||
const indexFile = path.join(target, "index.html");
|
||||
if (exists(indexFile))
|
||||
return sendFileWithSAN01Replace(res, indexFile);
|
||||
}
|
||||
return notFound(res);
|
||||
}
|
||||
// Non-file commands: just 200 OK
|
||||
res.writeHead(200, { "Content-Type": "text/plain; charset=utf-8" });
|
||||
res.end("OK");
|
||||
return;
|
||||
}
|
||||
|
||||
// Static serving from export
|
||||
let filePath = path.join(ROOT, pathname);
|
||||
|
||||
if (pathname.endsWith("/")) {
|
||||
filePath = path.join(filePath, "index.html");
|
||||
if (exists(filePath)) return sendFileWithSAN01Replace(res, filePath);
|
||||
}
|
||||
|
||||
if (exists(filePath) && fs.statSync(filePath).isFile()) {
|
||||
return sendFileWithSAN01Replace(res, filePath);
|
||||
}
|
||||
|
||||
const htmlVariant = filePath + ".html";
|
||||
if (exists(htmlVariant)) {
|
||||
return sendFileWithSAN01Replace(res, htmlVariant);
|
||||
}
|
||||
|
||||
// Fallback: out/index.html
|
||||
const fallback = path.join(ROOT, "index.html");
|
||||
if (exists(fallback)) return sendFileWithSAN01Replace(res, fallback);
|
||||
|
||||
return notFound(res);
|
||||
} catch (err) {
|
||||
res.writeHead(500, { "Content-Type": "text/plain; charset=utf-8" });
|
||||
res.end(
|
||||
"Internal Server Error\n" + (err && err.stack ? err.stack : String(err))
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
server.listen(PORT, () => {
|
||||
console.log(`Local CPL simulator running on http://localhost:${PORT}`);
|
||||
console.log(`Serving from: ${ROOT}`);
|
||||
console.log("Replacing <%=SAN01%> -> ismail in text responses");
|
||||
});
|
||||
Reference in New Issue
Block a user