This commit is contained in:
2025-11-03 18:42:04 -08:00
parent 30649488bb
commit eb084e1f07
12 changed files with 64 additions and 15 deletions

8
.env_dist Normal file
View File

@@ -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

1
.gitignore vendored
View File

@@ -5,3 +5,4 @@ target
.DS_Store .DS_Store
webui/src/wasm webui/src/wasm
webui/data webui/data
.env

30
Dockerfile Normal file
View File

@@ -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"]

10
docker-compose.yml Normal file
View File

@@ -0,0 +1,10 @@
services:
webui:
image: minimax
ports:
- "3000:3000"
volumes:
- ./data:/app/data
env_file:
- .env
restart: unless-stopped

View File

@@ -1,8 +1,8 @@
use wasm_bindgen::prelude::*; use wasm_bindgen::prelude::*;
mod ansi; mod ansi;
mod gamestate; mod minmaxgame;
mod gamestatehuman; mod minmaxgamehuman;
mod terminput; mod terminput;
#[global_allocator] #[global_allocator]

View File

@@ -9,7 +9,7 @@ use wasm_bindgen::prelude::*;
use crate::{ansi, terminput::TermInput}; use crate::{ansi, terminput::TermInput};
#[wasm_bindgen] #[wasm_bindgen]
pub struct GameStateHuman { pub struct MinMaxGameHuman {
/// Red player /// Red player
human: TermInput, human: TermInput,
@@ -26,7 +26,7 @@ pub struct GameStateHuman {
} }
#[wasm_bindgen] #[wasm_bindgen]
impl GameStateHuman { impl MinMaxGameHuman {
#[wasm_bindgen(constructor)] #[wasm_bindgen(constructor)]
pub fn new( pub fn new(
max_script: &str, max_script: &str,
@@ -34,7 +34,7 @@ impl GameStateHuman {
max_debug_callback: js_sys::Function, max_debug_callback: js_sys::Function,
game_state_callback: js_sys::Function, game_state_callback: js_sys::Function,
) -> Result<GameStateHuman, String> { ) -> Result<MinMaxGameHuman, String> {
Self::new_native( Self::new_native(
max_script, max_script,
move |s| { move |s| {

View File

@@ -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 filename = `${name}.rhai`;
const filepath = join(saveDir, filename); const filepath = join(saveDir, filename);

View File

@@ -6,7 +6,7 @@ import { SAVE_CONFIG } from "@/lib/saveConfig";
export async function GET() { export async function GET() {
try { 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 save directory doesn't exist, return empty array
if (!existsSync(saveDir)) { if (!existsSync(saveDir)) {

View File

@@ -52,7 +52,7 @@ export async function POST(request: NextRequest) {
} }
// Ensure save directory exists // Ensure save directory exists
const saveDir = join(process.cwd(), SAVE_CONFIG.SAVE_DIRECTORY); const saveDir = SAVE_CONFIG.SAVE_DIRECTORY;
if (!existsSync(saveDir)) { if (!existsSync(saveDir)) {
await mkdir(saveDir, { recursive: true }); await mkdir(saveDir, { recursive: true });
} }

View File

@@ -1,8 +1,8 @@
export const SAVE_CONFIG = { export const SAVE_CONFIG = {
ENABLE_SAVE: true, ENABLE_SAVE: process.env.ENABLE_SAVE === 'true' || true,
SAVE_SECRET: "save", SAVE_SECRET: process.env.SAVE_SECRET || "save",
SAVE_DIRECTORY: "./data/scripts", SAVE_DIRECTORY: process.env.SAVE_DIRECTORY || "./data/scripts",
MAX_FILENAME_LENGTH: 32, MAX_FILENAME_LENGTH: parseInt(process.env.MAX_FILENAME_LENGTH || "32"),
FILENAME_REGEX: /^[a-zA-Z0-9_\s-]+$/, FILENAME_REGEX: /^[a-zA-Z0-9_\s-]+$/,
} as const; } as const;

View File

@@ -1,8 +1,8 @@
import init, { GameState, GameStateHuman } from "../wasm/runner"; import init, { MinMaxGameHuman } from "../wasm/runner";
let wasmReady = false; let wasmReady = false;
let wasmInitPromise: Promise<void> | null = null; let wasmInitPromise: Promise<void> | null = null;
let currentGame: GameStateHuman | null = null; let currentGame: MinMaxGameHuman | null = null;
async function initWasm(): Promise<void> { async function initWasm(): Promise<void> {
if (wasmReady) return; if (wasmReady) return;
@@ -53,7 +53,7 @@ self.onmessage = async (event) => {
self.postMessage({ type: "terminal", line }); self.postMessage({ type: "terminal", line });
}; };
currentGame = new GameStateHuman( currentGame = new MinMaxGameHuman(
event_data.script, event_data.script,
appendOutput, appendOutput,
appendOutput, appendOutput,