add http-server part 6.2

This commit is contained in:
Christopher Hase 2025-04-10 14:36:39 +02:00
parent 325f961a99
commit c0f1a3db7e
19 changed files with 559 additions and 14 deletions

View file

@ -4,15 +4,18 @@ FROM forgejo.edf-bootstrap.cx.fg1.ffm.osc.live/devfw-cicd/node:20.18.1 AS build
WORKDIR /app
COPY package*.json ./
COPY . .
COPY tsconfig.json ./
COPY tsconfig.backend.json ./
COPY . .
RUN npm install -g npm@11.2.0
RUN npm install
#RUN npx tsc -p tsconfig.json
# Kompiliere zuerst den Backend-Code, sodass broker.mjs und andere Dateien erzeugt werden
RUN npx tsc -p tsconfig.backend.json
RUN npx tsc -p tsconfig.frontend.json
# Danach können wir die Frontend-Dateien auch kompilieren
RUN npx tsc -p tsconfig.frontend.json
# 2. Rust build-Stage
FROM forgejo.edf-bootstrap.cx.fg1.ffm.osc.live/devfw-cicd/rust:1.74.0 AS rust-build
@ -23,19 +26,19 @@ FROM forgejo.edf-bootstrap.cx.fg1.ffm.osc.live/devfw-cicd/node:20.18.1
WORKDIR /app
### NEW ###
# Kopiere Node-Modules und alle generierten Dateien
COPY --from=build /app/node_modules ./node_modules
COPY --from=build /app/dist ./dist
#COPY --from=build /app/index.html ./dist/
COPY --from=build /app/frontend/index.html ./dist/frontend/
COPY --from=rust-build /usr/local/cargo/bin/iching /usr/local/bin/iching
# Falls notwendig: Umbenennen von .js zu .mjs
RUN find dist/backend -name "*.js" -exec bash -c 'mv "$0" "${0%.js}.mjs"' {} \;
RUN find dist/frontend -name "*.js" -exec bash -c 'mv "$0" "${0%.js}.mjs"' {} \;
# Starte den Backend-Server
RUN node dist/backend/server.mjs &
#CMD ["npx", "http-server", "dist", "-p", "8080", "--mime", "application/javascript=js"]
# Starte den Frontend-Server
CMD ["npx", "http-server", "dist/frontend", "-p", "8080", "--mime", "application/javascript=js"]

131
backend/broker.js Normal file
View file

@ -0,0 +1,131 @@
import { exec } from 'child_process';
import * as fs from 'fs';
var config;
const nodemailer = require('nodemailer');
export function executeCommand() {
exec('iching divine', (error, stdout, stderr) => {
console.log(`Begin`);
if (error) {
console.error(`Error: ${error.message}`);
return;
}
if (stderr) {
console.error(`Stderr: ${stderr}`);
return;
}
//Load config once
if (config == undefined) {
config = loadConfig();
}
console.log(`Send E-Mail`);
sendEmail(stdout);
});
}
// Run function once initially, called from Dockerfile
executeCommand();
// Load the Configuration
function loadConfig() {
console.log(`Load Config`);
const data = fs.readFileSync('config.json', 'utf-8');
return JSON.parse(data);
}
// Send E-Mail
async function sendEmail(content) {
// Create Transporter
const transporter = nodemailer.createTransport({
host: config.mailHost,
port: config.mailPort,
secure: false
});
try {
const info = await transporter.sendMail({
from: '"The Oracle" <the.oracle@holy.mountain>',
to: config.emailReceiver,
subject: "Your Horoscope Is Ready",
text: content,
html: html(content)
});
console.log("E-Mail sent: ", info.messageId);
}
catch (error) {
console.error("Error Sending E-Mail:", error);
}
}
// Generate 1) Parse Tree and 2) HTML
export function html(inputText) {
const parseTree = parse(inputText);
const htmlOutput = render(parseTree);
return htmlOutput;
}
// Generate the Parse Tree
function parse(input) {
console.log("Parse input text");
const root = { type: "Root" };
var currentNode = root;
const lines = input.split("\n");
for (const line of lines) {
if (line.startsWith("Hexagram")) {
const hexagram = { type: "Hexagram" };
currentNode.child = hexagram;
currentNode = hexagram;
currentNode.value = "<h1>" + line + "</h1>";
}
else if (line.startsWith("Judgement")) {
const judgement = { type: "Judgement" };
currentNode.child = judgement;
currentNode = judgement;
currentNode.value = "<h3>" + line + "</h3>";
}
else if (line.startsWith("Images")) {
const images = { type: "Images" };
currentNode.child = images;
currentNode = images;
currentNode.value = "<h3>" + line + "</h3>";
}
else if (line.startsWith("~") && currentNode.type != "ChangingLines") {
const changingLines = { type: "ChangingLines" };
currentNode.child = changingLines;
currentNode = changingLines;
currentNode.value = line; // + "<br>"; TODO: try without this <br>
}
else {
currentNode.value = currentNode.value + line + "<br>";
}
}
return root;
}
// Generate HTML from Parse Tree
function render(node) {
if (node == undefined) {
console.log("Rendering of nodes finished!");
return "";
}
console.log("Render node" + node.type);
var outputHTML = "";
switch (node.type) {
case "Root":
return render(node.child);
case "Hexagram":
node.value = node.value?.replace("<h1>", "<div style=\"border: 1px dotted gray; border-radius: 10px; padding-left: 10px; padding-right: 10px; padding-top: 10px; padding-bottom: 10px; width: auto; display: inline-block; box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.2);\"><h1>");
node.value = node.value?.replace("</h1>", "</h1><div style=\"border: 1px solid gray; border-radius: 25px; padding-left: 30px; padding-right: 30px; padding-top: 20px; width: auto; display: inline-block; text-align: center; box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.2);\"><h2>");
node.value = node.value?.replace("<br>", " - ");
outputHTML = "<br><p>" + node.value + "</h2></div></p>";
outputHTML = outputHTML + render(node.child);
return outputHTML;
case "Images":
outputHTML = "<p>" + node.value + "</p></div>"; //EXTRA closing div (was opened at beginning of hexagram)
outputHTML = outputHTML + render(node.child);
return outputHTML;
case "ChangingLines":
const regex = new RegExp("~", "g");
node.value = node.value?.replace(regex, "");
//outputHTML = "<br><p><div style=\"border: 1px dashed gray; border-radius: 10px; padding-left: 10px; padding-right: 10px; padding-top: 10px; width: auto; display: inline-block; color: gray; text-align: center; box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.2);\">" + node.value + "</div></p><br>";
outputHTML = "<br><br><p><div style=\"padding-left: 20px; padding-right: 20px; padding-top: 20px; display: inline-block; color: gray; text-align: center;\">" + node.value + "</div></p><br>";
outputHTML = outputHTML + render(node.child);
return outputHTML;
default:
outputHTML = "<p>" + node.value + "</p>";
outputHTML = outputHTML + render(node.child);
return outputHTML;
}
}

131
backend/broker.mjs Normal file
View file

@ -0,0 +1,131 @@
import { exec } from 'child_process';
import * as fs from 'fs';
var config;
const nodemailer = require('nodemailer');
export function executeCommand() {
exec('iching divine', (error, stdout, stderr) => {
console.log(`Begin`);
if (error) {
console.error(`Error: ${error.message}`);
return;
}
if (stderr) {
console.error(`Stderr: ${stderr}`);
return;
}
//Load config once
if (config == undefined) {
config = loadConfig();
}
console.log(`Send E-Mail`);
sendEmail(stdout);
});
}
// Run function once initially, called from Dockerfile
executeCommand();
// Load the Configuration
function loadConfig() {
console.log(`Load Config`);
const data = fs.readFileSync('config.json', 'utf-8');
return JSON.parse(data);
}
// Send E-Mail
async function sendEmail(content) {
// Create Transporter
const transporter = nodemailer.createTransport({
host: config.mailHost,
port: config.mailPort,
secure: false
});
try {
const info = await transporter.sendMail({
from: '"The Oracle" <the.oracle@holy.mountain>',
to: config.emailReceiver,
subject: "Your Horoscope Is Ready",
text: content,
html: html(content)
});
console.log("E-Mail sent: ", info.messageId);
}
catch (error) {
console.error("Error Sending E-Mail:", error);
}
}
// Generate 1) Parse Tree and 2) HTML
export function html(inputText) {
const parseTree = parse(inputText);
const htmlOutput = render(parseTree);
return htmlOutput;
}
// Generate the Parse Tree
function parse(input) {
console.log("Parse input text");
const root = { type: "Root" };
var currentNode = root;
const lines = input.split("\n");
for (const line of lines) {
if (line.startsWith("Hexagram")) {
const hexagram = { type: "Hexagram" };
currentNode.child = hexagram;
currentNode = hexagram;
currentNode.value = "<h1>" + line + "</h1>";
}
else if (line.startsWith("Judgement")) {
const judgement = { type: "Judgement" };
currentNode.child = judgement;
currentNode = judgement;
currentNode.value = "<h3>" + line + "</h3>";
}
else if (line.startsWith("Images")) {
const images = { type: "Images" };
currentNode.child = images;
currentNode = images;
currentNode.value = "<h3>" + line + "</h3>";
}
else if (line.startsWith("~") && currentNode.type != "ChangingLines") {
const changingLines = { type: "ChangingLines" };
currentNode.child = changingLines;
currentNode = changingLines;
currentNode.value = line; // + "<br>"; TODO: try without this <br>
}
else {
currentNode.value = currentNode.value + line + "<br>";
}
}
return root;
}
// Generate HTML from Parse Tree
function render(node) {
if (node == undefined) {
console.log("Rendering of nodes finished!");
return "";
}
console.log("Render node" + node.type);
var outputHTML = "";
switch (node.type) {
case "Root":
return render(node.child);
case "Hexagram":
node.value = node.value?.replace("<h1>", "<div style=\"border: 1px dotted gray; border-radius: 10px; padding-left: 10px; padding-right: 10px; padding-top: 10px; padding-bottom: 10px; width: auto; display: inline-block; box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.2);\"><h1>");
node.value = node.value?.replace("</h1>", "</h1><div style=\"border: 1px solid gray; border-radius: 25px; padding-left: 30px; padding-right: 30px; padding-top: 20px; width: auto; display: inline-block; text-align: center; box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.2);\"><h2>");
node.value = node.value?.replace("<br>", " - ");
outputHTML = "<br><p>" + node.value + "</h2></div></p>";
outputHTML = outputHTML + render(node.child);
return outputHTML;
case "Images":
outputHTML = "<p>" + node.value + "</p></div>"; //EXTRA closing div (was opened at beginning of hexagram)
outputHTML = outputHTML + render(node.child);
return outputHTML;
case "ChangingLines":
const regex = new RegExp("~", "g");
node.value = node.value?.replace(regex, "");
//outputHTML = "<br><p><div style=\"border: 1px dashed gray; border-radius: 10px; padding-left: 10px; padding-right: 10px; padding-top: 10px; width: auto; display: inline-block; color: gray; text-align: center; box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.2);\">" + node.value + "</div></p><br>";
outputHTML = "<br><br><p><div style=\"padding-left: 20px; padding-right: 20px; padding-top: 20px; display: inline-block; color: gray; text-align: center;\">" + node.value + "</div></p><br>";
outputHTML = outputHTML + render(node.child);
return outputHTML;
default:
outputHTML = "<p>" + node.value + "</p>";
outputHTML = outputHTML + render(node.child);
return outputHTML;
}
}

21
backend/broker.test.js Normal file
View file

@ -0,0 +1,21 @@
"use strict";
/*import { html } from "./broker";
import { test, beforeAll, afterAll } from "@jest/globals";
jest.useFakeTimers();
test("Generate HTML for hexagram", () => {
expect(html("Hexagram No. 45 ䷬\nGathering Together [Massing]\n萃 (cuì)"))
.toBe("<br><p><div style=\"border: 1px dotted gray; border-radius: 10px; padding-left: 10px; padding-right: 10px; padding-top: 10px; padding-bottom: 10px; width: auto; display: inline-block; box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.2);\"><h1>Hexagram No. 45 ䷬</h1><div style=\"border: 1px solid gray; border-radius: 25px; padding-left: 30px; padding-right: 30px; padding-top: 20px; width: auto; display: inline-block; text-align: center; box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.2);\"><h2>Gathering Together [Massing] - 萃 (cuì)<br></h2></div></p>");
});
test("Generate HTML for judgement", () => {
expect(html("Judgement:\nGathering Together. Success.\nThe king approaches his temple.\nIt furthers one to see the great man.\nThis brings success. Perseverance furthers.\nTo bring great offerings creates good fortune.\nIt furthers one to undertake something."))
.toBe("<p><h3>Judgement:</h3>Gathering Together. Success.<br>The king approaches his temple.<br>It furthers one to see the great man.<br>This brings success. Perseverance furthers.<br>To bring great offerings creates good fortune.<br>It furthers one to undertake something.<br></p>");
});
test("Generate HTML for images", () => {
expect(html("Images:\nOver the earth, the lake:\nThe image of Gathering Together.\nThus the superior man renews his weapons\nIn order to meet the unforseen."))
.toBe("<p><h3>Images:</h3>Over the earth, the lake:<br>The image of Gathering Together.<br>Thus the superior man renews his weapons<br>In order to meet the unforseen.<br></p></div>");
});
*/

11
backend/server.js Normal file
View file

@ -0,0 +1,11 @@
import express from 'express';
import { executeCommand } from './broker.mjs';
const app = express();
const port = 8080;
app.post('/api/command', (req, res) => {
executeCommand();
res.status(200).send('Command executed');
});
app.listen(port, '0.0.0.0', () => {
console.log(`Server läuft auf http://0.0.0.0:${port}`);
});

View file

@ -1,5 +1,6 @@
import express from 'express';
import { executeCommand } from './broker.js';
import { executeCommand } from './broker.ts';
const app = express();
const port = 8080;

3
dist/backend/broker.d.ts vendored Normal file
View file

@ -0,0 +1,3 @@
export declare function executeCommand(): void;
export declare function html(inputText: string): string;
//# sourceMappingURL=broker.d.ts.map

1
dist/backend/broker.d.ts.map vendored Normal file
View file

@ -0,0 +1 @@
{"version":3,"file":"broker.d.ts","sourceRoot":"","sources":["../../backend/broker.ts"],"names":[],"mappings":"AAqBA,wBAAgB,cAAc,IAAI,IAAI,CAwBrC;AAwCD,wBAAgB,IAAI,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAK9C"}

131
dist/backend/broker.js vendored Normal file
View file

@ -0,0 +1,131 @@
import { exec } from 'child_process';
import * as fs from 'fs';
var config;
const nodemailer = require('nodemailer');
export function executeCommand() {
exec('iching divine', (error, stdout, stderr) => {
console.log(`Begin`);
if (error) {
console.error(`Error: ${error.message}`);
return;
}
if (stderr) {
console.error(`Stderr: ${stderr}`);
return;
}
//Load config once
if (config == undefined) {
config = loadConfig();
}
console.log(`Send E-Mail`);
sendEmail(stdout);
});
}
// Run function once initially, called from Dockerfile
executeCommand();
// Load the Configuration
function loadConfig() {
console.log(`Load Config`);
const data = fs.readFileSync('config.json', 'utf-8');
return JSON.parse(data);
}
// Send E-Mail
async function sendEmail(content) {
// Create Transporter
const transporter = nodemailer.createTransport({
host: config.mailHost,
port: config.mailPort,
secure: false
});
try {
const info = await transporter.sendMail({
from: '"The Oracle" <the.oracle@holy.mountain>',
to: config.emailReceiver,
subject: "Your Horoscope Is Ready",
text: content,
html: html(content)
});
console.log("E-Mail sent: ", info.messageId);
}
catch (error) {
console.error("Error Sending E-Mail:", error);
}
}
// Generate 1) Parse Tree and 2) HTML
export function html(inputText) {
const parseTree = parse(inputText);
const htmlOutput = render(parseTree);
return htmlOutput;
}
// Generate the Parse Tree
function parse(input) {
console.log("Parse input text");
const root = { type: "Root" };
var currentNode = root;
const lines = input.split("\n");
for (const line of lines) {
if (line.startsWith("Hexagram")) {
const hexagram = { type: "Hexagram" };
currentNode.child = hexagram;
currentNode = hexagram;
currentNode.value = "<h1>" + line + "</h1>";
}
else if (line.startsWith("Judgement")) {
const judgement = { type: "Judgement" };
currentNode.child = judgement;
currentNode = judgement;
currentNode.value = "<h3>" + line + "</h3>";
}
else if (line.startsWith("Images")) {
const images = { type: "Images" };
currentNode.child = images;
currentNode = images;
currentNode.value = "<h3>" + line + "</h3>";
}
else if (line.startsWith("~") && currentNode.type != "ChangingLines") {
const changingLines = { type: "ChangingLines" };
currentNode.child = changingLines;
currentNode = changingLines;
currentNode.value = line; // + "<br>"; TODO: try without this <br>
}
else {
currentNode.value = currentNode.value + line + "<br>";
}
}
return root;
}
// Generate HTML from Parse Tree
function render(node) {
if (node == undefined) {
console.log("Rendering of nodes finished!");
return "";
}
console.log("Render node" + node.type);
var outputHTML = "";
switch (node.type) {
case "Root":
return render(node.child);
case "Hexagram":
node.value = node.value?.replace("<h1>", "<div style=\"border: 1px dotted gray; border-radius: 10px; padding-left: 10px; padding-right: 10px; padding-top: 10px; padding-bottom: 10px; width: auto; display: inline-block; box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.2);\"><h1>");
node.value = node.value?.replace("</h1>", "</h1><div style=\"border: 1px solid gray; border-radius: 25px; padding-left: 30px; padding-right: 30px; padding-top: 20px; width: auto; display: inline-block; text-align: center; box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.2);\"><h2>");
node.value = node.value?.replace("<br>", " - ");
outputHTML = "<br><p>" + node.value + "</h2></div></p>";
outputHTML = outputHTML + render(node.child);
return outputHTML;
case "Images":
outputHTML = "<p>" + node.value + "</p></div>"; //EXTRA closing div (was opened at beginning of hexagram)
outputHTML = outputHTML + render(node.child);
return outputHTML;
case "ChangingLines":
const regex = new RegExp("~", "g");
node.value = node.value?.replace(regex, "");
//outputHTML = "<br><p><div style=\"border: 1px dashed gray; border-radius: 10px; padding-left: 10px; padding-right: 10px; padding-top: 10px; width: auto; display: inline-block; color: gray; text-align: center; box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.2);\">" + node.value + "</div></p><br>";
outputHTML = "<br><br><p><div style=\"padding-left: 20px; padding-right: 20px; padding-top: 20px; display: inline-block; color: gray; text-align: center;\">" + node.value + "</div></p><br>";
outputHTML = outputHTML + render(node.child);
return outputHTML;
default:
outputHTML = "<p>" + node.value + "</p>";
outputHTML = outputHTML + render(node.child);
return outputHTML;
}
}

2
dist/backend/broker.test.d.ts vendored Normal file
View file

@ -0,0 +1,2 @@
export {};
//# sourceMappingURL=broker.test.d.ts.map

1
dist/backend/broker.test.d.ts.map vendored Normal file
View file

@ -0,0 +1 @@
{"version":3,"file":"broker.test.d.ts","sourceRoot":"","sources":["../../backend/broker.test.ts"],"names":[],"mappings":""}

21
dist/backend/broker.test.js vendored Normal file
View file

@ -0,0 +1,21 @@
export {};
/*import { html } from "./broker";
import { test, beforeAll, afterAll } from "@jest/globals";
jest.useFakeTimers();
test("Generate HTML for hexagram", () => {
expect(html("Hexagram No. 45 ䷬\nGathering Together [Massing]\n萃 (cuì)"))
.toBe("<br><p><div style=\"border: 1px dotted gray; border-radius: 10px; padding-left: 10px; padding-right: 10px; padding-top: 10px; padding-bottom: 10px; width: auto; display: inline-block; box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.2);\"><h1>Hexagram No. 45 ䷬</h1><div style=\"border: 1px solid gray; border-radius: 25px; padding-left: 30px; padding-right: 30px; padding-top: 20px; width: auto; display: inline-block; text-align: center; box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.2);\"><h2>Gathering Together [Massing] - 萃 (cuì)<br></h2></div></p>");
});
test("Generate HTML for judgement", () => {
expect(html("Judgement:\nGathering Together. Success.\nThe king approaches his temple.\nIt furthers one to see the great man.\nThis brings success. Perseverance furthers.\nTo bring great offerings creates good fortune.\nIt furthers one to undertake something."))
.toBe("<p><h3>Judgement:</h3>Gathering Together. Success.<br>The king approaches his temple.<br>It furthers one to see the great man.<br>This brings success. Perseverance furthers.<br>To bring great offerings creates good fortune.<br>It furthers one to undertake something.<br></p>");
});
test("Generate HTML for images", () => {
expect(html("Images:\nOver the earth, the lake:\nThe image of Gathering Together.\nThus the superior man renews his weapons\nIn order to meet the unforseen."))
.toBe("<p><h3>Images:</h3>Over the earth, the lake:<br>The image of Gathering Together.<br>Thus the superior man renews his weapons<br>In order to meet the unforseen.<br></p></div>");
});
*/

2
dist/backend/server.d.ts vendored Normal file
View file

@ -0,0 +1,2 @@
export {};
//# sourceMappingURL=server.d.ts.map

1
dist/backend/server.d.ts.map vendored Normal file
View file

@ -0,0 +1 @@
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../backend/server.ts"],"names":[],"mappings":""}

11
dist/backend/server.js vendored Normal file
View file

@ -0,0 +1,11 @@
import express from 'express';
import { executeCommand } from './broker.mjs';
const app = express();
const port = 8080;
app.post('/api/command', (req, res) => {
executeCommand();
res.status(200).send('Command executed');
});
app.listen(port, '0.0.0.0', () => {
console.log(`Server läuft auf http://0.0.0.0:${port}`);
});

15
frontend/event.js Normal file
View file

@ -0,0 +1,15 @@
"use strict";
function handleClick() {
console.log("Der Button wurde geklickt!");
alert("Hallo von TypeScript!");
fetch("/api/command", { method: "POST" })
.then(res => res.text())
.then(text => console.log("Server sagt:", text));
/*fetch("https://192-168-197-2.c-one-infra.de/api/command", { method: "POST" })
.then(res => res.text())
.then(text => console.log("Server sagt:", text)); */
}
document.addEventListener("DOMContentLoaded", () => {
const button = document.getElementById("myButton");
button?.addEventListener("click", handleClick);
});

6
jest.config.js Normal file
View file

@ -0,0 +1,6 @@
"use strict";
module.exports = {
transform: {
"^.+\\.tsx?$": "ts-jest"
}
};

45
old.2.Dockerfile Normal file
View file

@ -0,0 +1,45 @@
# 1. Node.js Build-Stage
FROM forgejo.edf-bootstrap.cx.fg1.ffm.osc.live/devfw-cicd/node:20.18.1 AS build
WORKDIR /app
COPY package*.json ./
COPY . .
RUN npm install -g npm@11.2.0
RUN npm install
#RUN npx tsc -p tsconfig.json
RUN npx tsc -p tsconfig.backend.json
RUN npx tsc -p tsconfig.frontend.json
### NEW # Danach:
RUN find dist/backend -name "*.js" -exec bash -c 'mv "$0" "${0%.js}.mjs"' {} \;
# 2. Rust build-Stage
FROM forgejo.edf-bootstrap.cx.fg1.ffm.osc.live/devfw-cicd/rust:1.74.0 AS rust-build
RUN cargo install iching
# 3. Final runtime
FROM forgejo.edf-bootstrap.cx.fg1.ffm.osc.live/devfw-cicd/node:20.18.1
WORKDIR /app
### NEW ###
COPY --from=build /app/node_modules ./node_modules
COPY --from=build /app/dist ./dist
#COPY --from=build /app/index.html ./dist/
COPY --from=build /app/frontend/index.html ./dist/frontend/
COPY --from=rust-build /usr/local/cargo/bin/iching /usr/local/bin/iching
RUN find dist/backend -name "*.js" -exec bash -c 'mv "$0" "${0%.js}.mjs"' {} \;
RUN find dist/frontend -name "*.js" -exec bash -c 'mv "$0" "${0%.js}.mjs"' {} \;
RUN node dist/backend/server.mjs &
#CMD ["npx", "http-server", "dist", "-p", "8080", "--mime", "application/javascript=js"]
CMD ["npx", "http-server", "dist/frontend", "-p", "8080", "--mime", "application/javascript=js"]

View file

@ -1,9 +1,17 @@
{
"extends": "./tsconfig.json",
"extends": "./tsconfig.json", // Falls du eine allgemeine tsconfig hast
"compilerOptions": {
"outDir": "./dist/backend",
"module": "ESNext",
"moduleResolution": "node"
"outDir": "./dist/backend", // Zielordner für die kompilierte Backend-Dateien
"module": "NodeNext", // Setze das Modul auf NodeNext
"moduleResolution": "NodeNext", // NodeNext für die Modulauflösung
"target": "ES2020", // Moderne JavaScript-Syntax verwenden
"esModuleInterop": true, // Interoperabilität mit CommonJS- und ES-Modulen
"allowSyntheticDefaultImports": true, // Synthetische Default-Imports erlauben
"allowImportingTsExtensions": true,
"skipLibCheck": true, // Bibliotheken werden nicht überprüft (Optional)
"noEmit": true
},
"include": ["backend/**/*.ts"]
}
"include": [
"backend/**/*.ts" // Nur Dateien im backend-Ordner kompilieren
]
}