From eb084e1f073d9c3673819808c1fa321a4320ece4 Mon Sep 17 00:00:00 2001 From: Mark Date: Mon, 3 Nov 2025 18:42:04 -0800 Subject: [PATCH] Deploy --- .env_dist | 8 +++++ .gitignore | 1 + Dockerfile | 30 +++++++++++++++++++ docker-compose.yml | 10 +++++++ rust/runner/src/lib.rs | 4 +-- .../src/{gamestate.rs => minmaxgame.rs} | 0 .../{gamestatehuman.rs => minmaxgamehuman.rs} | 6 ++-- webui/src/app/api/get-script/route.ts | 2 +- webui/src/app/api/list-scripts/route.ts | 2 +- webui/src/app/api/save-script/route.ts | 2 +- webui/src/lib/saveConfig.ts | 8 ++--- webui/src/lib/worker_human.ts | 6 ++-- 12 files changed, 64 insertions(+), 15 deletions(-) create mode 100644 .env_dist create mode 100644 Dockerfile create mode 100644 docker-compose.yml rename rust/runner/src/{gamestate.rs => minmaxgame.rs} (100%) rename rust/runner/src/{gamestatehuman.rs => minmaxgamehuman.rs} (98%) diff --git a/.env_dist b/.env_dist new file mode 100644 index 0000000..6cb3083 --- /dev/null +++ b/.env_dist @@ -0,0 +1,8 @@ +# Script saving configuration +ENABLE_SAVE=true +SAVE_SECRET=save +SAVE_DIRECTORY=./data/scripts +MAX_FILENAME_LENGTH=32 + +# Next.js environment +NODE_ENV=production \ No newline at end of file diff --git a/.gitignore b/.gitignore index e3a85a3..38ba468 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ target .DS_Store webui/src/wasm webui/data +.env diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..915e0fd --- /dev/null +++ b/Dockerfile @@ -0,0 +1,30 @@ +FROM rust:1.91 AS rust-builder + +WORKDIR /app +RUN cargo install wasm-pack + +COPY rust/ ./rust/ +WORKDIR /app/rust/rhai-codemirror +RUN wasm-pack build --target web --out-dir "../../webui/src/wasm/rhai-codemirror" + +WORKDIR /app/rust/runner +RUN wasm-pack build --target web --out-dir "../../webui/src/wasm/runner" + +FROM node:24-alpine AS app + +WORKDIR /app + +RUN npm install -g bun +COPY webui/package.json webui/bun.lock* ./webui/ + +WORKDIR /app/webui +RUN bun install --frozen-lockfile +COPY webui/ ./ +COPY --from=rust-builder /app/webui/src/wasm/ ./src/wasm/ + +RUN bun run build + +RUN mkdir -p ../data/scripts +EXPOSE 3000 + +CMD ["bun", "start"] diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..9b1bf73 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,10 @@ +services: + webui: + image: minimax + ports: + - "3000:3000" + volumes: + - ./data:/app/data + env_file: + - .env + restart: unless-stopped diff --git a/rust/runner/src/lib.rs b/rust/runner/src/lib.rs index a052f19..70a6f7f 100644 --- a/rust/runner/src/lib.rs +++ b/rust/runner/src/lib.rs @@ -1,8 +1,8 @@ use wasm_bindgen::prelude::*; mod ansi; -mod gamestate; -mod gamestatehuman; +mod minmaxgame; +mod minmaxgamehuman; mod terminput; #[global_allocator] diff --git a/rust/runner/src/gamestate.rs b/rust/runner/src/minmaxgame.rs similarity index 100% rename from rust/runner/src/gamestate.rs rename to rust/runner/src/minmaxgame.rs diff --git a/rust/runner/src/gamestatehuman.rs b/rust/runner/src/minmaxgamehuman.rs similarity index 98% rename from rust/runner/src/gamestatehuman.rs rename to rust/runner/src/minmaxgamehuman.rs index 87097d2..094bfa9 100644 --- a/rust/runner/src/gamestatehuman.rs +++ b/rust/runner/src/minmaxgamehuman.rs @@ -9,7 +9,7 @@ use wasm_bindgen::prelude::*; use crate::{ansi, terminput::TermInput}; #[wasm_bindgen] -pub struct GameStateHuman { +pub struct MinMaxGameHuman { /// Red player human: TermInput, @@ -26,7 +26,7 @@ pub struct GameStateHuman { } #[wasm_bindgen] -impl GameStateHuman { +impl MinMaxGameHuman { #[wasm_bindgen(constructor)] pub fn new( max_script: &str, @@ -34,7 +34,7 @@ impl GameStateHuman { max_debug_callback: js_sys::Function, game_state_callback: js_sys::Function, - ) -> Result { + ) -> Result { Self::new_native( max_script, move |s| { diff --git a/webui/src/app/api/get-script/route.ts b/webui/src/app/api/get-script/route.ts index 7c49849..a494a46 100644 --- a/webui/src/app/api/get-script/route.ts +++ b/webui/src/app/api/get-script/route.ts @@ -24,7 +24,7 @@ export async function GET(request: NextRequest) { ); } - const saveDir = join(process.cwd(), SAVE_CONFIG.SAVE_DIRECTORY); + const saveDir = SAVE_CONFIG.SAVE_DIRECTORY; const filename = `${name}.rhai`; const filepath = join(saveDir, filename); diff --git a/webui/src/app/api/list-scripts/route.ts b/webui/src/app/api/list-scripts/route.ts index 2586e39..97f3274 100644 --- a/webui/src/app/api/list-scripts/route.ts +++ b/webui/src/app/api/list-scripts/route.ts @@ -6,7 +6,7 @@ import { SAVE_CONFIG } from "@/lib/saveConfig"; export async function GET() { try { - const saveDir = join(process.cwd(), SAVE_CONFIG.SAVE_DIRECTORY); + const saveDir = SAVE_CONFIG.SAVE_DIRECTORY; // If save directory doesn't exist, return empty array if (!existsSync(saveDir)) { diff --git a/webui/src/app/api/save-script/route.ts b/webui/src/app/api/save-script/route.ts index 5c46a0d..61280dc 100644 --- a/webui/src/app/api/save-script/route.ts +++ b/webui/src/app/api/save-script/route.ts @@ -52,7 +52,7 @@ export async function POST(request: NextRequest) { } // Ensure save directory exists - const saveDir = join(process.cwd(), SAVE_CONFIG.SAVE_DIRECTORY); + const saveDir = SAVE_CONFIG.SAVE_DIRECTORY; if (!existsSync(saveDir)) { await mkdir(saveDir, { recursive: true }); } diff --git a/webui/src/lib/saveConfig.ts b/webui/src/lib/saveConfig.ts index c238e65..ac51840 100644 --- a/webui/src/lib/saveConfig.ts +++ b/webui/src/lib/saveConfig.ts @@ -1,8 +1,8 @@ export const SAVE_CONFIG = { - ENABLE_SAVE: true, - SAVE_SECRET: "save", + ENABLE_SAVE: process.env.ENABLE_SAVE === 'true' || true, + SAVE_SECRET: process.env.SAVE_SECRET || "save", - SAVE_DIRECTORY: "./data/scripts", - MAX_FILENAME_LENGTH: 32, + SAVE_DIRECTORY: process.env.SAVE_DIRECTORY || "./data/scripts", + MAX_FILENAME_LENGTH: parseInt(process.env.MAX_FILENAME_LENGTH || "32"), FILENAME_REGEX: /^[a-zA-Z0-9_\s-]+$/, } as const; diff --git a/webui/src/lib/worker_human.ts b/webui/src/lib/worker_human.ts index cb552ec..342637c 100644 --- a/webui/src/lib/worker_human.ts +++ b/webui/src/lib/worker_human.ts @@ -1,8 +1,8 @@ -import init, { GameState, GameStateHuman } from "../wasm/runner"; +import init, { MinMaxGameHuman } from "../wasm/runner"; let wasmReady = false; let wasmInitPromise: Promise | null = null; -let currentGame: GameStateHuman | null = null; +let currentGame: MinMaxGameHuman | null = null; async function initWasm(): Promise { if (wasmReady) return; @@ -53,7 +53,7 @@ self.onmessage = async (event) => { self.postMessage({ type: "terminal", line }); }; - currentGame = new GameStateHuman( + currentGame = new MinMaxGameHuman( event_data.script, appendOutput, appendOutput,