This commit is contained in:
jonnybravo
2026-07-20 16:20:15 +02:00
parent 23ef289075
commit aeb7626194
30 changed files with 585 additions and 98 deletions

1
Caddyfile Normal file
View File

@@ -0,0 +1 @@
# Diese Datei wird für den direkten HostBetrieb ohne Caddy nicht benötigt.

View File

@@ -4,12 +4,15 @@ import os
import glob import glob
import datetime import datetime
import asyncio import asyncio
import traceback
# --- PFADE ABSOLUT DEFINIEREN --- # --- PFADE ABSOLUT DEFINIEREN ---
APP_DIR = os.path.dirname(os.path.abspath(__file__)) APP_DIR = os.path.dirname(os.path.abspath(__file__))
BASE_DIR = os.path.dirname(APP_DIR) BASE_DIR = os.path.dirname(APP_DIR)
PLAYBOOK_DIR = os.path.join(BASE_DIR, "playbooks") # Expliziter Pfad zum playbooks/ Ordner
PLAYBOOK_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "playbooks"))
print(f"Playbook directory: {PLAYBOOK_DIR}")
OUTPUT_DIR = os.path.join(BASE_DIR, "outputs") OUTPUT_DIR = os.path.join(BASE_DIR, "outputs")
# Sichere Ordner-Erstellung # Sichere Ordner-Erstellung
@@ -26,13 +29,34 @@ class AppState(rx.State):
output: str = "" output: str = ""
is_running: bool = False is_running: bool = False
error: str = "" error: str = ""
show_preview: bool = False
preview_content: str = ""
def toggle_preview(self):
"""Schaltet die Vorschau um."""
self.show_preview = not self.show_preview
if self.show_preview and self.selected_playbook:
self.load_preview()
def load_preview(self):
"""Lädt den Inhalt des ausgewählten Playbooks für die Vorschau."""
if not self.selected_playbook:
self.preview_content = "Wählen Sie ein Playbook"
return
try:
playbook_path = os.path.join(PLAYBOOK_DIR, self.selected_playbook)
with open(playbook_path, "r", encoding="utf-8") as f:
self.preview_content = f.read()
except Exception as e:
self.preview_content = f"Fehler beim Laden: {str(e)}"
# --- NEU: Für die Historie ---
past_runs: list[str] = [] past_runs: list[str] = []
selected_run: str = "" selected_run: str = ""
def set_selected_playbook(self, val: str): def set_selected_playbook(self, val: str):
self.selected_playbook = val self.selected_playbook = val
if self.show_preview:
self.load_preview()
def set_selected_run(self, val: str): def set_selected_run(self, val: str):
"""Setzt den ausgewählten alten Durchlauf und lädt dessen Inhalt.""" """Setzt den ausgewählten alten Durchlauf und lädt dessen Inhalt."""
@@ -53,23 +77,58 @@ class AppState(rx.State):
async def load_playbooks(self): async def load_playbooks(self):
"""Lädt alle Playbooks aus dem konfigurierten Ordner.""" """Lädt alle Playbooks aus dem konfigurierten Ordner."""
try: try:
playbook_files = glob.glob(os.path.join(PLAYBOOK_DIR, "*.yml")) + \ self.playbooks = []
glob.glob(os.path.join(PLAYBOOK_DIR, "*.yaml")) print(f"Searching for playbooks in: {PLAYBOOK_DIR}")
self.playbooks = [os.path.basename(p) for p in playbook_files]
if self.playbooks and not self.selected_playbook: if not os.path.exists(PLAYBOOK_DIR):
self.error = f"Playbook directory not found: {PLAYBOOK_DIR}"
print(self.error)
return
playbook_files = []
for ext in ("*.yml", "*.yaml"):
playbook_files.extend(glob.glob(os.path.join(PLAYBOOK_DIR, ext)))
print(f"Found playbook files: {playbook_files}")
self.playbooks = sorted([os.path.basename(p) for p in playbook_files])
if self.playbooks:
if not self.selected_playbook or self.selected_playbook not in self.playbooks:
self.selected_playbook = self.playbooks[0] self.selected_playbook = self.playbooks[0]
self.error = "" else:
self.selected_playbook = ""
self.error = "Keine Playbooks gefunden. Bitte legen Sie welche im playbooks/ Ordner ab."
print(f"Playbooks: {self.playbooks}")
print(f"Selected: {self.selected_playbook}")
except Exception as e: except Exception as e:
self.error = f"Fehler beim Laden der Playbooks: {str(e)}" self.error = f"Fehler beim Laden der Playbooks: {str(e)}"
print(f"Fehler in load_playbooks: {str(e)}")
print(f"Traceback: {traceback.format_exc()}")
async def load_past_runs(self): async def load_past_runs(self):
"""Scannt den outputs/ Ordner nach alten Logs und sortiert sie (neueste zuerst).""" """Scannt den outputs/ Ordner nach alten Logs, zeigt nur die 20 neuesten an und archiviert den Rest."""
try: try:
archive_dir = os.path.join(OUTPUT_DIR, "archiv")
os.makedirs(archive_dir, exist_ok=True)
log_files = glob.glob(os.path.join(OUTPUT_DIR, "*.txt")) log_files = glob.glob(os.path.join(OUTPUT_DIR, "*.txt"))
# Sortiert nach Dateiname absteigend (da Zeitstempel vorne steht, ist das neueste oben) sorted_files = sorted(log_files, key=os.path.getmtime, reverse=True)
self.past_runs = sorted([os.path.basename(l) for l in log_files], reverse=True)
for file in sorted_files[20:]:
try:
dest = os.path.join(archive_dir, os.path.basename(file))
os.rename(file, dest)
except Exception as e:
print(f"Fehler beim Archivieren von {file}: {str(e)}")
remaining_files = glob.glob(os.path.join(OUTPUT_DIR, "*.txt"))
self.past_runs = sorted([os.path.basename(l) for l in remaining_files],
key=lambda x: x.split("_")[0:2], reverse=True)[:20]
except Exception as e: except Exception as e:
self.error = f"Fehler beim Laden der Historie: {str(e)}" self.error = f"Fehler beim Laden der Historie: {str(e)}"
print(f"Fehler in load_past_runs: {str(e)}")
async def run_playbook(self): async def run_playbook(self):
"""Führt das ausgewählte Playbook asynchron aus und speichert den Output.""" """Führt das ausgewählte Playbook asynchron aus und speichert den Output."""
@@ -79,10 +138,13 @@ class AppState(rx.State):
self.is_running = True self.is_running = True
self.error = "" self.error = ""
self.output = "Wird ausgeführt..." self.output = f"Starte Ausführung von {self.selected_playbook}..."
print(f"Starte Playbook: {self.selected_playbook}")
yield yield
playbook_path = os.path.join(PLAYBOOK_DIR, self.selected_playbook) playbook_path = os.path.join(PLAYBOOK_DIR, self.selected_playbook)
print(f"Playbook Pfad: {playbook_path}")
timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S") timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
output_filename = f"{timestamp}_{self.selected_playbook.replace('.yml', '').replace('.yaml', '')}.txt" output_filename = f"{timestamp}_{self.selected_playbook.replace('.yml', '').replace('.yaml', '')}.txt"
output_path = os.path.join(OUTPUT_DIR, output_filename) output_path = os.path.join(OUTPUT_DIR, output_filename)
@@ -104,11 +166,9 @@ class AppState(rx.State):
output_text = stdout.decode() + stderr.decode() output_text = stdout.decode() + stderr.decode()
self.output = output_text self.output = output_text
# Output speichern
try: try:
with open(output_path, "w", encoding="utf-8") as f: with open(output_path, "w", encoding="utf-8") as f:
f.write(output_text) f.write(output_text)
# Direkt die Historie aktualisieren, damit das neue Log auftaucht
await self.load_past_runs() await self.load_past_runs()
except Exception as e: except Exception as e:
self.error = f"Fehler beim Speichern des Outputs: {str(e)}" self.error = f"Fehler beim Speichern des Outputs: {str(e)}"
@@ -116,7 +176,8 @@ class AppState(rx.State):
if proc.returncode != 0: if proc.returncode != 0:
self.error = f"Playbook wurde mit Fehlercode {proc.returncode} beendet." self.error = f"Playbook wurde mit Fehlercode {proc.returncode} beendet."
else: else:
self.error = "Playbook erfolgreich ausgeführt." self.error = ""
self.error = f"{self.selected_playbook} wurde erfolgreich ausgeführt!"
except asyncio.TimeoutError as e: except asyncio.TimeoutError as e:
self.error = str(e) self.error = str(e)
@@ -132,12 +193,12 @@ class AppState(rx.State):
def index(): def index():
return rx.container( return rx.container(
rx.heading("Ansible Playbook Runner", size="6"), rx.heading("Ansible Playbook Runner", size="6"),
# Ein Grid layout: Links Steuerung & Historie, rechts das große Log-Fenster
rx.grid( rx.grid(
# Linke Spalte (Bedienung)
rx.vstack( rx.vstack(
rx.text("Playbook auswählen:", font_weight="bold"), rx.text("Playbook auswählen:", font_weight="bold"),
rx.vstack(
rx.cond(
AppState.playbooks,
rx.select( rx.select(
AppState.playbooks, AppState.playbooks,
placeholder="Wählen Sie ein Playbook...", placeholder="Wählen Sie ein Playbook...",
@@ -145,17 +206,45 @@ def index():
on_change=AppState.set_selected_playbook, on_change=AppState.set_selected_playbook,
width="100%", width="100%",
), ),
rx.text("Keine Playbooks gefunden!", color="red")
),
rx.cond(
AppState.error,
rx.text(AppState.error, color="red"),
),
spacing="2"
),
rx.button( rx.button(
"Ausführen", rx.cond(
AppState.is_running,
rx.hstack(rx.spinner(), "Wird ausgeführt..."),
"Ausführen"
),
on_click=AppState.run_playbook, on_click=AppState.run_playbook,
disabled=AppState.is_running, disabled=AppState.is_running,
color_scheme="blue", color_scheme="blue",
width="100%", width="100%",
), ),
rx.divider(margin_y="1em"), rx.divider(margin_y="1em"),
rx.vstack(
# --- NEU: Historie Dropdown --- rx.button(
"Playbook-Vorschau anzeigen",
on_click=AppState.toggle_preview,
width="100%",
font_weight="bold"
),
rx.cond(
AppState.show_preview,
rx.code_block(
AppState.preview_content,
language="yaml",
width="100%",
max_height="300px",
)
),
width="100%",
spacing="2"
),
rx.text("Alte Durchläufe ansehen:", font_weight="bold"), rx.text("Alte Durchläufe ansehen:", font_weight="bold"),
rx.select( rx.select(
AppState.past_runs, AppState.past_runs,
@@ -164,17 +253,18 @@ def index():
on_change=AppState.set_selected_run, on_change=AppState.set_selected_run,
width="100%", width="100%",
), ),
rx.cond(
AppState.error,
rx.text( rx.text(
AppState.error, AppState.error,
color=rx.cond(AppState.error, "red", "transparent"), color="red",
margin_top="1em", margin_top="1em",
font_weight="bold"
),
), ),
align_items="stretch", align_items="stretch",
spacing="3", spacing="3",
), ),
# Rechte Spalte (Textausgabe)
rx.vstack( rx.vstack(
rx.text("Ausgabe / Log-Inhalt:", font_weight="bold"), rx.text("Ausgabe / Log-Inhalt:", font_weight="bold"),
rx.text_area( rx.text_area(
@@ -186,22 +276,34 @@ def index():
), ),
width="100%", width="100%",
), ),
columns="2", columns="1",
sm_columns="1",
md_columns="2",
spacing="5", spacing="5",
margin_top="2em", margin_top="2em",
width="100%",
), ),
padding="2em", padding="2em",
max_width="1200px", # Etwas breiter gemacht fürs Grid-Layout max_width="1200px",
margin="auto", margin="auto",
) )
app = rx.App() app = rx.App()
# Wichtig: Wir rufen beim Laden jetzt "load_data" auf, um beides zu laden app.add_page(
app.add_page(index, route="/", on_load=AppState.load_data) index,
route="/",
on_load=AppState.load_data,
meta=[]
)
if __name__ == "__main__": if __name__ == "__main__":
try: try:
app.run(debug=True) # Nur die benötigten Argumente übergeben; Ports/Hosts kommen aus rxconfig.py
app.run(
host="0.0.0.0",
reload=True,
log_level="debug",
)
except Exception as e: except Exception as e:
print(f"Fehler bei der Ausführung: {str(e)}") print(f"Fehler bei der Ausführung: {str(e)}")

View File

@@ -102,7 +102,14 @@ class AppState(rx.State):
if proc.returncode != 0: if proc.returncode != 0:
self.error = f"Playbook wurde mit Fehlercode {proc.returncode} beendet." self.error = f"Playbook wurde mit Fehlercode {proc.returncode} beendet."
else: else:
self.error = "Playbook erfolgreich ausgeführt." duration = (datetime.datetime.now() - start_time).total_seconds()
self.error = ""
rx.notify(
title="Erfolgreich ausgeführt",
description=f"{self.selected_playbook} in {duration:.2f} Sekunden abgeschlossen",
status="success",
duration=3000
)
except asyncio.TimeoutError as e: except asyncio.TimeoutError as e:
self.error = str(e) self.error = str(e)

19
certs/localhost.crt Normal file
View File

@@ -0,0 +1,19 @@
-----BEGIN CERTIFICATE-----
MIIDJTCCAg2gAwIBAgIUYAf7j9oARluWbEpoJCJtFHvb0aYwDQYJKoZIhvcNAQEL
BQAwFDESMBAGA1UEAwwJbG9jYWxob3N0MB4XDTI2MDcyMDA4NDkzM1oXDTI3MDcy
MDA4NDkzM1owFDESMBAGA1UEAwwJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEF
AAOCAQ8AMIIBCgKCAQEAwq+iVe568a/EVtsSIJOwkhHdRYDFwzyPoIkHzcZmFGS/
XK3E8K62DbcLNipU5kjY1s5S+HXU1Ac0lsWj5HBp43G4sOns8ugZvvhsHXqo8T5V
zQW/SGyxkPF2cACSHcdu7lgZ7+whoWl78fbpyOVd7QAKAk20sWg1MmvLSoyJI9f2
TRjp+pvB7jYkaIniKepE20ZWPIGeanbDz4M4JIkrRE/TE9TyZZeG1fJ4dKmcUU/F
lyOmj73a5Lao2co61ShjPqAAT2lysTYHFdntH7VgnmSCbge+Vna57zjGcBRBLPeO
P+QaFdGtQHNRocQoW+/vABIwXVbt5HsPGmqLY4c0WwIDAQABo28wbTAdBgNVHQ4E
FgQUkR8RYdiJVdQBSZrcUxhYVQ5yp0AwHwYDVR0jBBgwFoAUkR8RYdiJVdQBSZrc
UxhYVQ5yp0AwDwYDVR0TAQH/BAUwAwEB/zAaBgNVHREEEzARgglsb2NhbGhvc3SH
BH8AAAEwDQYJKoZIhvcNAQELBQADggEBALBYL7slIr90e3O3KA4BAssn4SkVeHkb
+bntJGJBX6AU658iStD43nJYY2lHtOlFESYdUUz/Pyb7ZUdPAjkFA0iLqlPs8cRa
eH9sxbdX7XIVh8Ro04d1OhOiyYzn4SNFL4WGMT6jEpnklSWElZIfluIjsAgYIxMJ
lWFN6xm6qOXfxqaEpnMHvwb5lqhDP03/lOhiPAtoP187H9uh/Q3/1S2bK5nO5DnP
y44KLl2q8V0csHEJGvkWr/2KVdKpg7wOfq8wLJKNbRAYT0htHywciJO8KTCb+g/J
SGBkGsqdLRMcWaAjXXQ2V4MxGDZeeRKJhnJynUowOABcoKnqJF/xOWA=
-----END CERTIFICATE-----

28
certs/localhost.key Normal file
View File

@@ -0,0 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDCr6JV7nrxr8RW
2xIgk7CSEd1FgMXDPI+giQfNxmYUZL9crcTwrrYNtws2KlTmSNjWzlL4ddTUBzSW
xaPkcGnjcbiw6ezy6Bm++GwdeqjxPlXNBb9IbLGQ8XZwAJIdx27uWBnv7CGhaXvx
9unI5V3tAAoCTbSxaDUya8tKjIkj1/ZNGOn6m8HuNiRoieIp6kTbRlY8gZ5qdsPP
gzgkiStET9MT1PJll4bV8nh0qZxRT8WXI6aPvdrktqjZyjrVKGM+oABPaXKxNgcV
2e0ftWCeZIJuB75WdrnvOMZwFEEs944/5BoV0a1Ac1GhxChb7+8AEjBdVu3kew8a
aotjhzRbAgMBAAECggEADUDipsHw6bIjBhysy73yJ8eCjkA5dlSRnIanmtkWSu4e
3uLPhOkH6MAcycew9upfpKPwHwz6e6Kv8FGtGhiTBNJRle2e3VxyoD8OMSWQCbhK
JAZvorEPl4PwoahQSimxAhXKUjx7f58MOokqGiyPK9q0U7rRgcBL2s5ezQjrLx7e
tXZGc7RmYJ061s1Fyy5raGZW9rpxZCGVjz87f4isDZgFyT2G6wCIxYv5bj6SRyR9
dHeKLOiUc1EJP38YYWxPu0+6gP9ltib7McLfoMlz5NgPlhHQJfY8stpgNtQlTQkQ
i+UAsK70MdsCgXNR01V4Flz344l1DiWphnEDPR9C3QKBgQDjQAFAQDHGELwWIuXp
4WSgXY7KVRvrB0o211MsBkR+vndFPpllHh2hqyMkW4Sfr8CdnF6cM1CC9HEz4Yx2
8RoV4uP/b0XUy99LzRlDq6DTuo2ZEJ8cD8QED/qvAHiloMn99RExhcheFZSZW+2R
DJ6BSMXr/wiSSIcJztMpOnIF9wKBgQDbUPlBsyKgmgyimNW2cU6NhVWUDETmvPI2
kK+7ZfRdqvAHfeHxuIu5fx2J2b1bjb9viN7/JXFPkSpBU3SZQbBOIDvbMVZUGkK2
/tfvj/ZUWpbv5hCDw1Vm04EMx8BSwDqrlCcFusaraptzMJbMLTBaiDbvnjxr3tEf
tnWE3hZbvQKBgB82BjX12yAx4jNEHcGuhCyGTPs7DzeLa8T2c+TjA3tI24a2H0lF
BprSr2Pp8eAgulqrRE89uPwTaIzQmIMpgASrgdbuSG/+hC+b/rFNnCwYPiRcpQ2s
mKZaL3rjnK5a1AM+Kltb3XYWjq81cf5u9kIZZZ2RDHNS5METF+tcrJZnAoGAV+Xa
IETFSgyzp68NaDN9QicAJ3fLXZa4lLnkVH0GNUw/KyF+nrxR86RImGkWBU2IPhFj
HmtJQJRzlP73qjyzhnxQwQbDDK4BswnsTW0rUp+EAt34HHb7EV0PSan9IK0+Vmno
QdmbqjPt3XrJ1Ub/LCmPqvWGTc1djxI3g2rnFxkCgYB4y7dxwx5QJ3fqaWlRLz12
EORm3BcqYbKAUdGgYAG2NnC1cDcNV2EGwA2Rx5hvuKcKxU9jwuv+nUtkzP7cTy+b
f/Tk5+pNIAks6bXWdPk0umCacbKu84bTjOlq1QUFBB6w6eQRO47fJ/csaUoWJgaT
MAE5zpu85O93rjEazmwDhQ==
-----END PRIVATE KEY-----

19
certs/new-cert.crt Normal file
View File

@@ -0,0 +1,19 @@
-----BEGIN CERTIFICATE-----
MIIDCTCCAfGgAwIBAgIUfnlGzePBRgG7jMsbfT6tBSsvdI0wDQYJKoZIhvcNAQEL
BQAwFDESMBAGA1UEAwwJbG9jYWxob3N0MB4XDTI2MDcyMDA4NDYzMVoXDTI3MDcy
MDA4NDYzMVowFDESMBAGA1UEAwwJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEF
AAOCAQ8AMIIBCgKCAQEAjzXH+Lzr0YsfceomsiTzkpczSjFs/n1mLt4L8dQWIBQ5
9K0+FCaRgNMx+SPHO7I2GPHRA4hoCUkD12PjzA9ZBpAj2+ojFYQ++nKdCp1bY9m/
4k5d/hK35Zf+lW+35KHTieUHXFSAK+5ialvUhVeyZcv/6GNRbNb2wWp+W2CMobNv
UldSrnDiYLSG+T3yiN//+aqJYQ+tjMqDYe2EiFR0ttYF4SUOVPfVr3ghXHMjaIHB
nq++BGVgWrL4y5hJTTPYN4f9OlmlkJq+hmGGnpNw8QcVVo6TPe2cLWIv7NHpDxfk
Nm2pm0iByneYX9vIrIExAv6Ntliy6+IC38YUbqicnwIDAQABo1MwUTAdBgNVHQ4E
FgQUUMOwmGMrursTKZdT94A69biQaOgwHwYDVR0jBBgwFoAUUMOwmGMrursTKZdT
94A69biQaOgwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAXa6e
GcNSHYjSIBpMRP7qcWEBsM1Bm5N882cBSQpEwT2r0MSAcrE5eywfpPry2a89nRM1
/cCmH+od3dssw4Y95MGULbMl9KOTWKTL6UsUux8gdNwhW55sQFwSNcMsXRE5SxwH
CBYRAqucfHmunVtHKRt4txdYgMJNpU0gtNuThp8Mp7jpsvC832n8rAFrWZHuKU02
lvUNw2oSWg+ffWWO2Ahp0FOrNlC6yjGqJxy5gm+7QJ3L+T71L/CgXSSLPpKU2IH8
a37iJyxEiQOckYmte96FVLidSXopR7KvJ9Vw/k//Z22+jmXVEUuqGjV1IfmTcCXG
GZbLdArIrfq4LiNrpQ==
-----END CERTIFICATE-----

28
certs/new-key.key Normal file
View File

@@ -0,0 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCPNcf4vOvRix9x
6iayJPOSlzNKMWz+fWYu3gvx1BYgFDn0rT4UJpGA0zH5I8c7sjYY8dEDiGgJSQPX
Y+PMD1kGkCPb6iMVhD76cp0KnVtj2b/iTl3+Erfll/6Vb7fkodOJ5QdcVIAr7mJq
W9SFV7Jly//oY1Fs1vbBan5bYIyhs29SV1KucOJgtIb5PfKI3//5qolhD62MyoNh
7YSIVHS21gXhJQ5U99WveCFccyNogcGer74EZWBasvjLmElNM9g3h/06WaWQmr6G
YYaek3DxBxVWjpM97ZwtYi/s0ekPF+Q2bambSIHKd5hf28isgTEC/o22WLLr4gLf
xhRuqJyfAgMBAAECggEAJAseqeFunr4bq3GJzLNVJHNuosE+0+xev/P94J8G9Iry
rTy/D5ZHb7t36+MP3Vv0lqGh//ggaxnX4CmRZ0YDm43CoLJUozE2IpWfJdFF86MV
0tDzgiNW6m+vURAdoesC0UV17UyNN8FXPrqfCfJxAYLvBR+eGj0ePL7fT4NE0dt1
hu5A5fhmQYfNKe/Hn68slYMJ6Hr9eZ6TaFgXLEQvS28Ok/H+roX5pcfwKQ7FFCSF
xzLk84tUG80U+FKmiqKOtkdvz6K9YFPI7IR25CmOLhAagDF59WQtqShDJVC7Nhuk
EFxzIAtP+rFnWGqjYFyTsJ7bBWoNY99sRZto0P6YgQKBgQDC7gvrpdcB+ZfBKFjD
5snENpxgh+VXe7/UDKYddJqxIP+lBgsdwSMOGxrPeI1IDi0T1Zh/5bNp/uwIHeem
PJTV8u5uNvpD705pmW1uUaNqs8LXhWtttlylxNI01M19IA8Uhd9I2h8rPw1rgBHK
0ltnTB1gwqdFF2Llk8J2U4elgQKBgQC8E6eCr/W66CHIY4BImWYK5K+abP2Doe5S
MmefYRbCxsKBH2HCEg43ubZ+KXoBBaR+TDIw/Zv3uOdjkbR4/CH8vM1tGaK9SMiD
g07xzuPd3IIqpQ1ajI3Np5V6Y+vcO8jjXpHgxCpmnaUq3fkxL4ST2Rfr3P5T16pj
/9JxUNiSHwKBgQC86CT1QcqUR2Yh8w/TCh4O4T267vf7SBonTfrOIOqpLemR68Fq
HHn0eaAJ4DJK2jIlPqKDj//HgR0M4K5WE+/JR5x5gx4WKBw9ikra1pMgHQV+B/aM
ZGZ038E3IePilucGZJZ266u5JWnD/GFBxYp/GOx/kSS5eGiHRCL4uQqEAQKBgQCr
/GUgEvxo0MGj16mFuhEgQQN7+dLSPpAKxmEP097Wep9/KE1jBNPPjZoeQJt6t8g2
XkM/nYq0u3eNC763LAmAbr6D1/+DjD0gVkEoyoKBbZXynUBa31EFEQyWAS28FUec
8+v+WCRV9i8FxjqMCeH4uXswisRfs0XzcArm6IFDDQKBgGs+OOUIs8pyaH1/Jy82
w3W5c0h8xWj+fCIn3Yb6A0IaudH3OyTwDoVsd1u9nSTakFtJAxD/Sym0yo0WG5hm
Sbs/b+rNlSh9G9BEmB7eH/mrJ3DgFUnUC/7XbYbQGNWVHK5uiU1IPcgvD8HW77hE
g7C2WtSeC0v73kW/QA8EKYBZ
-----END PRIVATE KEY-----

1
docker-compose.yml Normal file
View File

@@ -0,0 +1 @@
# Diese Datei wird für den direkten HostBetrieb ohne Docker nicht benötigt.

View File

@@ -0,0 +1,21 @@
PLAY [Hallo Welt ausgeben] *****************************************************
TASK [Gathering Facts] *********************************************************
ok: [localhost]
TASK [Hallo Welt ausgeben] *****************************************************
ok: [localhost] => {
"msg": "Hallo man-dan-05! Die Uhrzeit ist 2026-07-20T08:54:54Z"
}
TASK [Uhrzeit ausgeben] ********************************************************
ok: [localhost] => {
"msg": "Die Uhrzeit ist 2026-07-20T08:54:54Z"
}
PLAY RECAP *********************************************************************
localhost : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[WARNING]: No inventory was parsed, only implicit localhost is available
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'

View File

@@ -0,0 +1,21 @@
PLAY [Hallo Welt ausgeben] *****************************************************
TASK [Gathering Facts] *********************************************************
ok: [localhost]
TASK [Hallo Welt ausgeben] *****************************************************
ok: [localhost] => {
"msg": "Hallo man-dan-05! Die Uhrzeit ist 2026-07-20T08:58:37Z"
}
TASK [Uhrzeit ausgeben] ********************************************************
ok: [localhost] => {
"msg": "Die Uhrzeit ist 2026-07-20T08:58:37Z"
}
PLAY RECAP *********************************************************************
localhost : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[WARNING]: No inventory was parsed, only implicit localhost is available
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'

View File

@@ -0,0 +1,21 @@
PLAY [Hallo Welt ausgeben] *****************************************************
TASK [Gathering Facts] *********************************************************
ok: [localhost]
TASK [Hallo Welt ausgeben] *****************************************************
ok: [localhost] => {
"msg": "Hallo man-dan-05! Die Uhrzeit ist 2026-07-20T09:02:57Z"
}
TASK [Uhrzeit ausgeben] ********************************************************
ok: [localhost] => {
"msg": "Die Uhrzeit ist 2026-07-20T09:02:57Z"
}
PLAY RECAP *********************************************************************
localhost : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[WARNING]: No inventory was parsed, only implicit localhost is available
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'

View File

@@ -0,0 +1,21 @@
PLAY [Hallo Welt ausgeben] *****************************************************
TASK [Gathering Facts] *********************************************************
ok: [localhost]
TASK [Hallo Welt ausgeben] *****************************************************
ok: [localhost] => {
"msg": "Hallo man-dan-05! Die Uhrzeit ist 2026-07-20T09:03:32Z"
}
TASK [Uhrzeit ausgeben] ********************************************************
ok: [localhost] => {
"msg": "Die Uhrzeit ist 2026-07-20T09:03:32Z"
}
PLAY RECAP *********************************************************************
localhost : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[WARNING]: No inventory was parsed, only implicit localhost is available
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'

View File

@@ -0,0 +1,21 @@
PLAY [Hallo Welt ausgeben] *****************************************************
TASK [Gathering Facts] *********************************************************
ok: [localhost]
TASK [Hallo Welt ausgeben] *****************************************************
ok: [localhost] => {
"msg": "Hallo man-dan-05! Die Uhrzeit ist 2026-07-20T09:04:46Z"
}
TASK [Uhrzeit ausgeben] ********************************************************
ok: [localhost] => {
"msg": "Die Uhrzeit ist 2026-07-20T09:04:46Z"
}
PLAY RECAP *********************************************************************
localhost : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[WARNING]: No inventory was parsed, only implicit localhost is available
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'

View File

@@ -0,0 +1,21 @@
PLAY [Hallo Welt ausgeben] *****************************************************
TASK [Gathering Facts] *********************************************************
ok: [localhost]
TASK [Hallo Welt ausgeben] *****************************************************
ok: [localhost] => {
"msg": "Hallo man-dan-05! Die Uhrzeit ist 2026-07-20T09:10:03Z"
}
TASK [Uhrzeit ausgeben] ********************************************************
ok: [localhost] => {
"msg": "Die Uhrzeit ist 2026-07-20T09:10:03Z"
}
PLAY RECAP *********************************************************************
localhost : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[WARNING]: No inventory was parsed, only implicit localhost is available
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'

View File

@@ -0,0 +1,21 @@
PLAY [Hallo Welt ausgeben] *****************************************************
TASK [Gathering Facts] *********************************************************
ok: [localhost]
TASK [Hallo Welt ausgeben] *****************************************************
ok: [localhost] => {
"msg": "Hallo man-dan-05! Die Uhrzeit ist 2026-07-20T09:12:59Z"
}
TASK [Uhrzeit ausgeben] ********************************************************
ok: [localhost] => {
"msg": "Die Uhrzeit ist 2026-07-20T09:12:59Z"
}
PLAY RECAP *********************************************************************
localhost : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[WARNING]: No inventory was parsed, only implicit localhost is available
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'

View File

@@ -0,0 +1,21 @@
PLAY [Hallo Welt ausgeben] *****************************************************
TASK [Gathering Facts] *********************************************************
ok: [localhost]
TASK [Hallo Welt ausgeben] *****************************************************
ok: [localhost] => {
"msg": "Hallo man-dan-05! Die Uhrzeit ist 2026-07-20T09:13:08Z"
}
TASK [Uhrzeit ausgeben] ********************************************************
ok: [localhost] => {
"msg": "Die Uhrzeit ist 2026-07-20T09:13:08Z"
}
PLAY RECAP *********************************************************************
localhost : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[WARNING]: No inventory was parsed, only implicit localhost is available
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'

View File

@@ -0,0 +1,21 @@
PLAY [Hallo Welt ausgeben] *****************************************************
TASK [Gathering Facts] *********************************************************
ok: [localhost]
TASK [Hallo Welt ausgeben] *****************************************************
ok: [localhost] => {
"msg": "Hallo man-dan-05! Die Uhrzeit ist 2026-07-20T09:13:11Z"
}
TASK [Uhrzeit ausgeben] ********************************************************
ok: [localhost] => {
"msg": "Die Uhrzeit ist 2026-07-20T09:13:11Z"
}
PLAY RECAP *********************************************************************
localhost : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[WARNING]: No inventory was parsed, only implicit localhost is available
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'

View File

@@ -0,0 +1,21 @@
PLAY [Hallo Welt ausgeben] *****************************************************
TASK [Gathering Facts] *********************************************************
ok: [localhost]
TASK [Hallo Welt ausgeben] *****************************************************
ok: [localhost] => {
"msg": "Hallo man-dan-05! Die Uhrzeit ist 2026-07-20T09:13:16Z"
}
TASK [Uhrzeit ausgeben] ********************************************************
ok: [localhost] => {
"msg": "Die Uhrzeit ist 2026-07-20T09:13:16Z"
}
PLAY RECAP *********************************************************************
localhost : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[WARNING]: No inventory was parsed, only implicit localhost is available
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'

View File

@@ -0,0 +1,21 @@
PLAY [Hallo Welt ausgeben] *****************************************************
TASK [Gathering Facts] *********************************************************
ok: [localhost]
TASK [Hallo Welt ausgeben] *****************************************************
ok: [localhost] => {
"msg": "Hallo man-dan-05! Die Uhrzeit ist 2026-07-20T09:13:29Z"
}
TASK [Uhrzeit ausgeben] ********************************************************
ok: [localhost] => {
"msg": "Die Uhrzeit ist 2026-07-20T09:13:29Z"
}
PLAY RECAP *********************************************************************
localhost : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[WARNING]: No inventory was parsed, only implicit localhost is available
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'

View File

@@ -0,0 +1,21 @@
PLAY [Hallo Welt ausgeben] *****************************************************
TASK [Gathering Facts] *********************************************************
ok: [localhost]
TASK [Hallo Welt ausgeben] *****************************************************
ok: [localhost] => {
"msg": "Hallo man-dan-05! Die Uhrzeit ist 2026-07-20T14:18:02Z"
}
TASK [Uhrzeit ausgeben] ********************************************************
ok: [localhost] => {
"msg": "Die Uhrzeit ist 2026-07-20T14:18:02Z"
}
PLAY RECAP *********************************************************************
localhost : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[WARNING]: No inventory was parsed, only implicit localhost is available
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'

View File

@@ -0,0 +1,21 @@
PLAY [Hallo Welt ausgeben] *****************************************************
TASK [Gathering Facts] *********************************************************
ok: [localhost]
TASK [Hallo Welt ausgeben] *****************************************************
ok: [localhost] => {
"msg": "Hallo man-dan-05! Die Uhrzeit ist 2026-07-20T14:18:12Z"
}
TASK [Uhrzeit ausgeben] ********************************************************
ok: [localhost] => {
"msg": "Die Uhrzeit ist 2026-07-20T14:18:12Z"
}
PLAY RECAP *********************************************************************
localhost : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[WARNING]: No inventory was parsed, only implicit localhost is available
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'

View File

@@ -15,6 +15,7 @@
"react-helmet": "6.1.0", "react-helmet": "6.1.0",
"react-router": "7.15.0", "react-router": "7.15.0",
"react-router-dom": "7.15.0", "react-router-dom": "7.15.0",
"react-syntax-highlighter": "16.1.1",
"socket.io-client": "4.8.3", "socket.io-client": "4.8.3",
"sonner": "2.0.7", "sonner": "2.0.7",
"universal-cookie": "7.2.2", "universal-cookie": "7.2.2",
@@ -418,8 +419,14 @@
"@types/estree": ["@types/estree@1.0.9", "", {}, "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg=="], "@types/estree": ["@types/estree@1.0.9", "", {}, "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg=="],
"@types/hast": ["@types/hast@3.0.5", "", { "dependencies": { "@types/unist": "*" } }, "sha512-rp/ezSWaD1m44dPKICGhiskI13nVr7qTloFwDa/IYkhhf5nzwP+zIQcIJh3WIFSBOy/H1PzB40jPjMDksN4F+g=="],
"@types/parse-json": ["@types/parse-json@4.0.2", "", {}, "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw=="], "@types/parse-json": ["@types/parse-json@4.0.2", "", {}, "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw=="],
"@types/prismjs": ["@types/prismjs@1.26.6", "", {}, "sha512-vqlvI7qlMvcCBbVe0AKAb4f97//Hy0EBTaiW8AalRnG/xAN5zOiWWyrNqNXeq8+KAuvRewjCVY1+IPxk4RdNYw=="],
"@types/unist": ["@types/unist@3.0.3", "", {}, "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q=="],
"arg": ["arg@5.0.2", "", {}, "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg=="], "arg": ["arg@5.0.2", "", {}, "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg=="],
"aria-hidden": ["aria-hidden@1.2.6", "", { "dependencies": { "tslib": "^2.0.0" } }, "sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA=="], "aria-hidden": ["aria-hidden@1.2.6", "", { "dependencies": { "tslib": "^2.0.0" } }, "sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA=="],
@@ -444,10 +451,18 @@
"caniuse-lite": ["caniuse-lite@1.0.30001806", "", {}, "sha512-72Cuvd95zbSYPKq6Fhg8eDJRlzgWDf7/mtoZv6Qe/DYNCEBdNxoA3+rZAU2ZhGCpZlns3EssFavaZomckT5Uuw=="], "caniuse-lite": ["caniuse-lite@1.0.30001806", "", {}, "sha512-72Cuvd95zbSYPKq6Fhg8eDJRlzgWDf7/mtoZv6Qe/DYNCEBdNxoA3+rZAU2ZhGCpZlns3EssFavaZomckT5Uuw=="],
"character-entities": ["character-entities@2.0.2", "", {}, "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ=="],
"character-entities-legacy": ["character-entities-legacy@3.0.0", "", {}, "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ=="],
"character-reference-invalid": ["character-reference-invalid@2.0.1", "", {}, "sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw=="],
"chokidar": ["chokidar@4.0.3", "", { "dependencies": { "readdirp": "^4.0.1" } }, "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA=="], "chokidar": ["chokidar@4.0.3", "", { "dependencies": { "readdirp": "^4.0.1" } }, "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA=="],
"classnames": ["classnames@2.5.1", "", {}, "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow=="], "classnames": ["classnames@2.5.1", "", {}, "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow=="],
"comma-separated-tokens": ["comma-separated-tokens@2.0.3", "", {}, "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg=="],
"confbox": ["confbox@0.2.4", "", {}, "sha512-ysOGlgTFbN2/Y6Cg3Iye8YKulHw+R2fNXHrgSmXISQdMnomY6eNDprVdW9R5xBguEqI954+S6709UyiO7B+6OQ=="], "confbox": ["confbox@0.2.4", "", {}, "sha512-ysOGlgTFbN2/Y6Cg3Iye8YKulHw+R2fNXHrgSmXISQdMnomY6eNDprVdW9R5xBguEqI954+S6709UyiO7B+6OQ=="],
"convert-source-map": ["convert-source-map@1.9.0", "", {}, "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A=="], "convert-source-map": ["convert-source-map@1.9.0", "", {}, "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A=="],
@@ -460,6 +475,8 @@
"debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="], "debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="],
"decode-named-character-reference": ["decode-named-character-reference@1.3.0", "", { "dependencies": { "character-entities": "^2.0.0" } }, "sha512-GtpQYB283KrPp6nRw50q3U9/VfOutZOe103qlN7BPP6Ad27xYnOIWv4lPzo8HCAL+mMZofJ9KEy30fq6MfaK6Q=="],
"dedent": ["dedent@1.7.2", "", { "peerDependencies": { "babel-plugin-macros": "^3.1.0" }, "optionalPeers": ["babel-plugin-macros"] }, "sha512-WzMx3mW98SN+zn3hgemf4OzdmyNhhhKz5Ay0pUfQiMQ3e1g+xmTJWp/pKdwKVXhdSkAEGIIzqeuWrL3mV/AXbA=="], "dedent": ["dedent@1.7.2", "", { "peerDependencies": { "babel-plugin-macros": "^3.1.0" }, "optionalPeers": ["babel-plugin-macros"] }, "sha512-WzMx3mW98SN+zn3hgemf4OzdmyNhhhKz5Ay0pUfQiMQ3e1g+xmTJWp/pKdwKVXhdSkAEGIIzqeuWrL3mV/AXbA=="],
"detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="], "detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="],
@@ -488,10 +505,14 @@
"exsolve": ["exsolve@1.1.0", "", {}, "sha512-D+42+T12DdIlJM3uepa55qGiL3sYdLBOxIl2ifQCzCHz4c7eiolaHsi3BIqEr7JxBzxv2pYZQX9kw16ziMcEmw=="], "exsolve": ["exsolve@1.1.0", "", {}, "sha512-D+42+T12DdIlJM3uepa55qGiL3sYdLBOxIl2ifQCzCHz4c7eiolaHsi3BIqEr7JxBzxv2pYZQX9kw16ziMcEmw=="],
"fault": ["fault@1.0.4", "", { "dependencies": { "format": "^0.2.0" } }, "sha512-CJ0HCB5tL5fYTEA7ToAq5+kTwd++Borf1/bifxd9iT70QcXr4MRrO3Llf8Ifs70q+SJcGHFtnIE/Nw6giCtECA=="],
"fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="], "fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="],
"find-root": ["find-root@1.1.0", "", {}, "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng=="], "find-root": ["find-root@1.1.0", "", {}, "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng=="],
"format": ["format@0.2.2", "", {}, "sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww=="],
"fraction.js": ["fraction.js@5.3.4", "", {}, "sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ=="], "fraction.js": ["fraction.js@5.3.4", "", {}, "sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ=="],
"fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="], "fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="],
@@ -504,14 +525,30 @@
"hasown": ["hasown@2.0.4", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A=="], "hasown": ["hasown@2.0.4", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A=="],
"hast-util-parse-selector": ["hast-util-parse-selector@4.0.0", "", { "dependencies": { "@types/hast": "^3.0.0" } }, "sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A=="],
"hastscript": ["hastscript@9.0.1", "", { "dependencies": { "@types/hast": "^3.0.0", "comma-separated-tokens": "^2.0.0", "hast-util-parse-selector": "^4.0.0", "property-information": "^7.0.0", "space-separated-tokens": "^2.0.0" } }, "sha512-g7df9rMFX/SPi34tyGCyUBREQoKkapwdY/T04Qn9TDWfHhAYt4/I0gMVirzK5wEzeUqIjEB+LXC/ypb7Aqno5w=="],
"highlight.js": ["highlight.js@10.7.3", "", {}, "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A=="],
"highlightjs-vue": ["highlightjs-vue@1.0.0", "", {}, "sha512-PDEfEF102G23vHmPhLyPboFCD+BkMGu+GuJe2d9/eH4FsCwvgBpnc9n0pGE+ffKdph38s6foEZiEjdgHdzp+IA=="],
"hoist-non-react-statics": ["hoist-non-react-statics@3.3.2", "", { "dependencies": { "react-is": "^16.7.0" } }, "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw=="], "hoist-non-react-statics": ["hoist-non-react-statics@3.3.2", "", { "dependencies": { "react-is": "^16.7.0" } }, "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw=="],
"import-fresh": ["import-fresh@3.3.1", "", { "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" } }, "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ=="], "import-fresh": ["import-fresh@3.3.1", "", { "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" } }, "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ=="],
"is-alphabetical": ["is-alphabetical@2.0.1", "", {}, "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ=="],
"is-alphanumerical": ["is-alphanumerical@2.0.1", "", { "dependencies": { "is-alphabetical": "^2.0.0", "is-decimal": "^2.0.0" } }, "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw=="],
"is-arrayish": ["is-arrayish@0.2.1", "", {}, "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg=="], "is-arrayish": ["is-arrayish@0.2.1", "", {}, "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg=="],
"is-core-module": ["is-core-module@2.16.2", "", { "dependencies": { "hasown": "^2.0.3" } }, "sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA=="], "is-core-module": ["is-core-module@2.16.2", "", { "dependencies": { "hasown": "^2.0.3" } }, "sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA=="],
"is-decimal": ["is-decimal@2.0.1", "", {}, "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A=="],
"is-hexadecimal": ["is-hexadecimal@2.0.1", "", {}, "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg=="],
"isbot": ["isbot@5.1.40", "", {}, "sha512-yNeeynhhtIVRBk12tBV4eHNxwB42HzR4Q3Ea7vCOiJhImGaAIdIMrbJtacQlBizGLjUPw+akkFI5Dn9T70XoVQ=="], "isbot": ["isbot@5.1.40", "", {}, "sha512-yNeeynhhtIVRBk12tBV4eHNxwB42HzR4Q3Ea7vCOiJhImGaAIdIMrbJtacQlBizGLjUPw+akkFI5Dn9T70XoVQ=="],
"js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="], "js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="],
@@ -552,6 +589,8 @@
"loose-envify": ["loose-envify@1.4.0", "", { "dependencies": { "js-tokens": "^3.0.0 || ^4.0.0" }, "bin": { "loose-envify": "cli.js" } }, "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q=="], "loose-envify": ["loose-envify@1.4.0", "", { "dependencies": { "js-tokens": "^3.0.0 || ^4.0.0" }, "bin": { "loose-envify": "cli.js" } }, "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q=="],
"lowlight": ["lowlight@1.20.0", "", { "dependencies": { "fault": "^1.0.0", "highlight.js": "~10.7.0" } }, "sha512-8Ktj+prEb1RoCPkEOrPMYUN/nCggB7qAWe3a7OpMjWQkh3l2RD5wKRQ+o8Q8YuI9RG/xs95waaI/E6ym/7NsTw=="],
"lru-cache": ["lru-cache@5.1.1", "", { "dependencies": { "yallist": "^3.0.2" } }, "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w=="], "lru-cache": ["lru-cache@5.1.1", "", { "dependencies": { "yallist": "^3.0.2" } }, "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w=="],
"lucide-react": ["lucide-react@1.14.0", "", { "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-+1mdWcfSJVUsaTIjN9zoezmUhfXo5l0vP7ekBMPo3jcS/aIkxHnXqAPsByszMZx/Y8oQBRJxJx5xg+RH3urzxA=="], "lucide-react": ["lucide-react@1.14.0", "", { "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-+1mdWcfSJVUsaTIjN9zoezmUhfXo5l0vP7ekBMPo3jcS/aIkxHnXqAPsByszMZx/Y8oQBRJxJx5xg+RH3urzxA=="],
@@ -570,6 +609,8 @@
"parent-module": ["parent-module@1.0.1", "", { "dependencies": { "callsites": "^3.0.0" } }, "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g=="], "parent-module": ["parent-module@1.0.1", "", { "dependencies": { "callsites": "^3.0.0" } }, "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g=="],
"parse-entities": ["parse-entities@4.0.2", "", { "dependencies": { "@types/unist": "^2.0.0", "character-entities-legacy": "^3.0.0", "character-reference-invalid": "^2.0.0", "decode-named-character-reference": "^1.0.0", "is-alphanumerical": "^2.0.0", "is-decimal": "^2.0.0", "is-hexadecimal": "^2.0.0" } }, "sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw=="],
"parse-json": ["parse-json@5.2.0", "", { "dependencies": { "@babel/code-frame": "^7.0.0", "error-ex": "^1.3.1", "json-parse-even-better-errors": "^2.3.0", "lines-and-columns": "^1.1.6" } }, "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg=="], "parse-json": ["parse-json@5.2.0", "", { "dependencies": { "@babel/code-frame": "^7.0.0", "error-ex": "^1.3.1", "json-parse-even-better-errors": "^2.3.0", "lines-and-columns": "^1.1.6" } }, "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg=="],
"path-parse": ["path-parse@1.0.7", "", {}, "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="], "path-parse": ["path-parse@1.0.7", "", {}, "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="],
@@ -594,8 +635,12 @@
"prettier": ["prettier@3.9.5", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-/FVl766LpUfB5vXgCYOYa0MeV/441Ia99AeICQIQFTY/Nw0roZwULcXpku5i1/m5kt/baz+s4Zogspd839HSMg=="], "prettier": ["prettier@3.9.5", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-/FVl766LpUfB5vXgCYOYa0MeV/441Ia99AeICQIQFTY/Nw0roZwULcXpku5i1/m5kt/baz+s4Zogspd839HSMg=="],
"prismjs": ["prismjs@1.30.0", "", {}, "sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw=="],
"prop-types": ["prop-types@15.8.1", "", { "dependencies": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", "react-is": "^16.13.1" } }, "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg=="], "prop-types": ["prop-types@15.8.1", "", { "dependencies": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", "react-is": "^16.13.1" } }, "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg=="],
"property-information": ["property-information@7.2.0", "", {}, "sha512-IAtzIB6sUiWaJYrX9smp3V46pBGbBeLFRGdh25kg1334VcBlD8HzhPeNIWQH9zhGmo2itIe25EHt9dQP7G5hmg=="],
"radix-ui": ["radix-ui@1.6.2", "", { "dependencies": { "@radix-ui/primitive": "1.1.5", "@radix-ui/react-accessible-icon": "1.1.11", "@radix-ui/react-accordion": "1.2.16", "@radix-ui/react-alert-dialog": "1.1.19", "@radix-ui/react-arrow": "1.1.11", "@radix-ui/react-aspect-ratio": "1.1.11", "@radix-ui/react-avatar": "1.2.2", "@radix-ui/react-checkbox": "1.3.7", "@radix-ui/react-collapsible": "1.1.16", "@radix-ui/react-collection": "1.1.12", "@radix-ui/react-compose-refs": "1.1.3", "@radix-ui/react-context": "1.2.0", "@radix-ui/react-context-menu": "2.3.3", "@radix-ui/react-dialog": "1.1.19", "@radix-ui/react-direction": "1.1.2", "@radix-ui/react-dismissable-layer": "1.1.15", "@radix-ui/react-dropdown-menu": "2.1.20", "@radix-ui/react-focus-guards": "1.1.4", "@radix-ui/react-focus-scope": "1.1.12", "@radix-ui/react-form": "0.1.12", "@radix-ui/react-hover-card": "1.1.19", "@radix-ui/react-label": "2.1.11", "@radix-ui/react-menu": "2.1.20", "@radix-ui/react-menubar": "1.1.20", "@radix-ui/react-navigation-menu": "1.2.18", "@radix-ui/react-one-time-password-field": "0.1.12", "@radix-ui/react-password-toggle-field": "0.1.7", "@radix-ui/react-popover": "1.1.19", "@radix-ui/react-popper": "1.3.3", "@radix-ui/react-portal": "1.1.13", "@radix-ui/react-presence": "1.1.7", "@radix-ui/react-primitive": "2.1.7", "@radix-ui/react-progress": "1.1.12", "@radix-ui/react-radio-group": "1.4.3", "@radix-ui/react-roving-focus": "1.1.15", "@radix-ui/react-scroll-area": "1.2.14", "@radix-ui/react-select": "2.3.3", "@radix-ui/react-separator": "1.1.11", "@radix-ui/react-slider": "1.4.3", "@radix-ui/react-slot": "1.3.0", "@radix-ui/react-switch": "1.3.3", "@radix-ui/react-tabs": "1.1.17", "@radix-ui/react-toast": "1.2.19", "@radix-ui/react-toggle": "1.1.14", "@radix-ui/react-toggle-group": "1.1.15", "@radix-ui/react-toolbar": "1.1.15", "@radix-ui/react-tooltip": "1.2.12", "@radix-ui/react-use-callback-ref": "1.1.2", "@radix-ui/react-use-controllable-state": "1.2.3", "@radix-ui/react-use-effect-event": "0.0.3", "@radix-ui/react-use-escape-keydown": "1.1.3", "@radix-ui/react-use-is-hydrated": "0.1.1", "@radix-ui/react-use-layout-effect": "1.1.2", "@radix-ui/react-use-size": "1.1.2", "@radix-ui/react-visually-hidden": "1.2.7" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-OwYUjzMwiInCUxgAWpPsavXC3Kh4iyi/49uU1/qZTG3RQDlvegyk1GOMiGvSkjua1RDb3JD3fo3eroL9FV4GQw=="], "radix-ui": ["radix-ui@1.6.2", "", { "dependencies": { "@radix-ui/primitive": "1.1.5", "@radix-ui/react-accessible-icon": "1.1.11", "@radix-ui/react-accordion": "1.2.16", "@radix-ui/react-alert-dialog": "1.1.19", "@radix-ui/react-arrow": "1.1.11", "@radix-ui/react-aspect-ratio": "1.1.11", "@radix-ui/react-avatar": "1.2.2", "@radix-ui/react-checkbox": "1.3.7", "@radix-ui/react-collapsible": "1.1.16", "@radix-ui/react-collection": "1.1.12", "@radix-ui/react-compose-refs": "1.1.3", "@radix-ui/react-context": "1.2.0", "@radix-ui/react-context-menu": "2.3.3", "@radix-ui/react-dialog": "1.1.19", "@radix-ui/react-direction": "1.1.2", "@radix-ui/react-dismissable-layer": "1.1.15", "@radix-ui/react-dropdown-menu": "2.1.20", "@radix-ui/react-focus-guards": "1.1.4", "@radix-ui/react-focus-scope": "1.1.12", "@radix-ui/react-form": "0.1.12", "@radix-ui/react-hover-card": "1.1.19", "@radix-ui/react-label": "2.1.11", "@radix-ui/react-menu": "2.1.20", "@radix-ui/react-menubar": "1.1.20", "@radix-ui/react-navigation-menu": "1.2.18", "@radix-ui/react-one-time-password-field": "0.1.12", "@radix-ui/react-password-toggle-field": "0.1.7", "@radix-ui/react-popover": "1.1.19", "@radix-ui/react-popper": "1.3.3", "@radix-ui/react-portal": "1.1.13", "@radix-ui/react-presence": "1.1.7", "@radix-ui/react-primitive": "2.1.7", "@radix-ui/react-progress": "1.1.12", "@radix-ui/react-radio-group": "1.4.3", "@radix-ui/react-roving-focus": "1.1.15", "@radix-ui/react-scroll-area": "1.2.14", "@radix-ui/react-select": "2.3.3", "@radix-ui/react-separator": "1.1.11", "@radix-ui/react-slider": "1.4.3", "@radix-ui/react-slot": "1.3.0", "@radix-ui/react-switch": "1.3.3", "@radix-ui/react-tabs": "1.1.17", "@radix-ui/react-toast": "1.2.19", "@radix-ui/react-toggle": "1.1.14", "@radix-ui/react-toggle-group": "1.1.15", "@radix-ui/react-toolbar": "1.1.15", "@radix-ui/react-tooltip": "1.2.12", "@radix-ui/react-use-callback-ref": "1.1.2", "@radix-ui/react-use-controllable-state": "1.2.3", "@radix-ui/react-use-effect-event": "0.0.3", "@radix-ui/react-use-escape-keydown": "1.1.3", "@radix-ui/react-use-is-hydrated": "0.1.1", "@radix-ui/react-use-layout-effect": "1.1.2", "@radix-ui/react-use-size": "1.1.2", "@radix-ui/react-visually-hidden": "1.2.7" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-OwYUjzMwiInCUxgAWpPsavXC3Kh4iyi/49uU1/qZTG3RQDlvegyk1GOMiGvSkjua1RDb3JD3fo3eroL9FV4GQw=="],
"react": ["react@19.2.6", "", {}, "sha512-sfWGGfavi0xr8Pg0sVsyHMAOziVYKgPLNrS7ig+ivMNb3wbCBw3KxtflsGBAwD3gYQlE/AEZsTLgToRrSCjb0Q=="], "react": ["react@19.2.6", "", {}, "sha512-sfWGGfavi0xr8Pg0sVsyHMAOziVYKgPLNrS7ig+ivMNb3wbCBw3KxtflsGBAwD3gYQlE/AEZsTLgToRrSCjb0Q=="],
@@ -624,10 +669,14 @@
"react-style-singleton": ["react-style-singleton@2.2.3", "", { "dependencies": { "get-nonce": "^1.0.0", "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ=="], "react-style-singleton": ["react-style-singleton@2.2.3", "", { "dependencies": { "get-nonce": "^1.0.0", "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ=="],
"react-syntax-highlighter": ["react-syntax-highlighter@16.1.1", "", { "dependencies": { "@babel/runtime": "^7.28.4", "highlight.js": "^10.4.1", "highlightjs-vue": "^1.0.0", "lowlight": "^1.17.0", "prismjs": "^1.30.0", "refractor": "^5.0.0" }, "peerDependencies": { "react": ">= 0.14.0" } }, "sha512-PjVawBGy80C6YbC5DDZJeUjBmC7skaoEUdvfFQediQHgCL7aKyVHe57SaJGfQsloGDac+gCpTfRdtxzWWKmCXA=="],
"read-cache": ["read-cache@1.0.0", "", { "dependencies": { "pify": "^2.3.0" } }, "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA=="], "read-cache": ["read-cache@1.0.0", "", { "dependencies": { "pify": "^2.3.0" } }, "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA=="],
"readdirp": ["readdirp@4.1.2", "", {}, "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg=="], "readdirp": ["readdirp@4.1.2", "", {}, "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg=="],
"refractor": ["refractor@5.0.0", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/prismjs": "^1.0.0", "hastscript": "^9.0.0", "parse-entities": "^4.0.0" } }, "sha512-QXOrHQF5jOpjjLfiNk5GFnWhRXvxjUVnlFxkeDmewR5sXkr3iM46Zo+CnRR8B+MDVqkULW4EcLVcRBNOPXHosw=="],
"resolve": ["resolve@1.22.12", "", { "dependencies": { "es-errors": "^1.3.0", "is-core-module": "^2.16.1", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" } }, "sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA=="], "resolve": ["resolve@1.22.12", "", { "dependencies": { "es-errors": "^1.3.0", "is-core-module": "^2.16.1", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" } }, "sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA=="],
"resolve-from": ["resolve-from@4.0.0", "", {}, "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="], "resolve-from": ["resolve-from@4.0.0", "", {}, "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="],
@@ -652,6 +701,8 @@
"source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="], "source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="],
"space-separated-tokens": ["space-separated-tokens@2.0.2", "", {}, "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q=="],
"stylis": ["stylis@4.2.0", "", {}, "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw=="], "stylis": ["stylis@4.2.0", "", {}, "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw=="],
"supports-preserve-symlinks-flag": ["supports-preserve-symlinks-flag@1.0.0", "", {}, "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w=="], "supports-preserve-symlinks-flag": ["supports-preserve-symlinks-flag@1.0.0", "", {}, "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w=="],
@@ -692,6 +743,8 @@
"@react-router/dev/isbot": ["isbot@5.2.1", "", {}, "sha512-dJ+LpKyClQZ7NG+j3OensC/mAZkGpukE9YUrgPYvAZj2doVL0edfDgywTUh5CXa0o+nW9a1V9e5+CJTX8+SxRw=="], "@react-router/dev/isbot": ["isbot@5.2.1", "", {}, "sha512-dJ+LpKyClQZ7NG+j3OensC/mAZkGpukE9YUrgPYvAZj2doVL0edfDgywTUh5CXa0o+nW9a1V9e5+CJTX8+SxRw=="],
"parse-entities/@types/unist": ["@types/unist@2.0.11", "", {}, "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA=="],
"pkg-types/pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="], "pkg-types/pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="],
"vite/postcss": ["postcss@8.5.19", "", { "dependencies": { "nanoid": "^3.3.12", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-Mz8SaolMd8nB+G13WkORcxQKHZ/NE4xXevtkJHVuG+guo9/wYKlIMTKAqGdEmYOXR2ijPjTYNHssizdaVSUNdQ=="], "vite/postcss": ["postcss@8.5.19", "", { "dependencies": { "nanoid": "^3.3.12", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-Mz8SaolMd8nB+G13WkORcxQKHZ/NE4xXevtkJHVuG+guo9/wYKlIMTKAqGdEmYOXR2ijPjTYNHssizdaVSUNdQ=="],

View File

@@ -16,6 +16,7 @@
"react-helmet": "6.1.0", "react-helmet": "6.1.0",
"react-router": "7.15.0", "react-router": "7.15.0",
"react-router-dom": "7.15.0", "react-router-dom": "7.15.0",
"react-syntax-highlighter": "16.1.1",
"socket.io-client": "4.8.3", "socket.io-client": "4.8.3",
"sonner": "2.0.7", "sonner": "2.0.7",
"universal-cookie": "7.2.2" "universal-cookie": "7.2.2"

View File

@@ -1,16 +1,20 @@
import reflex as rx import reflex as rx
from reflex.plugins import SitemapPlugin from reflex.plugins import SitemapPlugin
from reflex_components_radix.plugin import RadixThemesPlugin
config = rx.Config( config = rx.Config(
appearance="dark",
app_name="app", app_name="app",
frontend_port=8080, frontend_port=3000,
backend_port=8081, backend_port=3001,
# Wichtig: Hier jetzt http:// statt https:// api_url="http://localhost:3001",
api_url="http://man-dan-05:8081", backend_host="0.0.0.0",
frontend_host="0.0.0.0",
# Sitemap-Warnung deaktivieren backend_ws_url="ws://localhost:3001/ws",
cors_allowed_origins=["http://localhost:3000"],
cors_credentials=True,
plugins=[RadixThemesPlugin()],
disable_plugins=[SitemapPlugin], disable_plugins=[SitemapPlugin],
vite_allowed_hosts=["localhost", "127.0.0.1"],
# Vite anweisen, den Hostnamen im Netzwerk zu akzeptieren env=rx.Env.DEV,
vite_allowed_hosts=["man-dan-05", "localhost", "127.0.0.1"]
) )

View File

@@ -1,38 +0,0 @@
import reflex as rx
from reflex.plugins import SitemapPlugin
import os
# --- AUTOMATISCHER VITE-PATCH FÜR LINUX ---
# Sucht die von Reflex generierte Vite-Konfiguration
VITE_CONFIG_PATH = os.path.join(os.path.dirname(__file__), ".web", "vite.config.js")
if os.path.exists(VITE_CONFIG_PATH):
try:
with open(VITE_CONFIG_PATH, "r", encoding="utf-8") as f:
content = f.read()
# Wenn der Host noch nicht erlaubt ist, patchen wir das 'server'-Objekt
if "allowedHosts" not in content:
# Wir fügen allowedHosts direkt in die Server-Konfiguration von Vite ein
patched_content = content.replace(
"server: {",
"server: {\n allowedHosts: ['man-dan-05', 'localhost', '127.0.0.1'],"
)
with open(VITE_CONFIG_PATH, "w", encoding="utf-8") as f:
f.write(patched_content)
print("[INFO] Vite-Sicherheitsblockade erfolgreich im Code gelöst!")
except Exception as e:
print(f"[WARNUNG] Patch fehlgeschlagen: {str(e)}")
config = rx.Config(
app_name="app",
frontend_port=8080,
backend_port=8081,
api_url="http://man-dan-05:8081",
# ssl_cert="certs/man-dan-05.crt",
#ssl_key="certs/man-dan-05.key",
disable_plugins=[SitemapPlugin],
)

11
weg
View File

@@ -1,11 +0,0 @@
// Konfiguration für Reflex
module.exports = {
// Pfade für die Reflex-Anwendung
paths: {
public: './public',
output: './dist'
},
// Weitere Konfigurationen...
plugins: [],
theme: {}
};