From 22bc7460df40e46968ee3495ff2b5b6f614b13c6 Mon Sep 17 00:00:00 2001 From: David Poeschl Date: Mon, 11 Mar 2024 10:32:23 -0700 Subject: [PATCH] Merge shared code for submission running (extension/sandbox) and team submission info (extension/web) (#16) * Unify submission execution implementations into submissionRunner * Unify contestMonitorTypes definitions between extension & web * Make line separator in entry use LF * Add entry.sh for sandbox * Fix web imports * Sandbox read from .env --------- Co-authored-by: orosmatthew --- .dockerignore | 22 + .../contestMonitor/contestStateSyncManager.ts | 2 +- extension/bwcontest/src/problemPanel.ts | 6 +- extension/bwcontest/src/run/cpp.ts | 146 --- extension/bwcontest/src/run/csharp.ts | 89 -- extension/bwcontest/src/run/types.ts | 31 - extension/bwcontest/tsconfig.json | 14 +- sandbox/Dockerfile | 31 +- sandbox/docker-compose.yml | 4 +- sandbox/docker/entry.sh | 3 + sandbox/package-lock.json | 1068 +++++++++++++++++ sandbox/package.json | 10 +- sandbox/src/index.ts | 68 +- sandbox/src/run/java.ts | 111 -- sandbox/src/run/types.d.ts | 16 - sandbox/tsconfig.json | 7 +- .../extensionWeb/.gitignore | 3 +- .../extensionWeb/contestMonitorTypes.cts | 0 shared/extensionWeb/package-lock.json | 10 + shared/extensionWeb/package.json | 9 + shared/extensionWeb/tsconfig.json | 14 + shared/submissionRunner/.gitignore | 2 + .../cpp.ts => shared/submissionRunner/cpp.cts | 6 +- .../submissionRunner/csharp.cts | 6 +- .../submissionRunner/java.cts | 12 +- shared/submissionRunner/package-lock.json | 118 ++ shared/submissionRunner/package.json | 15 + shared/submissionRunner/settings.cts | 1 + shared/submissionRunner/tsconfig.json | 14 + shared/submissionRunner/types.cts | 36 + web/Dockerfile | 26 +- web/docker-compose.yml | 4 +- web/docker/entry.sh | 1 + .../contestMonitorSharedTypes.ts | 29 - .../lib/contestMonitor/contestMonitorUtils.ts | 2 +- .../team/[session]/contestState/+server.ts | 2 +- .../api/team/[session]/submit/+server.ts | 2 +- web/svelte.config.js | 5 +- web/tsconfig.json | 1 + 39 files changed, 1443 insertions(+), 503 deletions(-) create mode 100644 .dockerignore delete mode 100644 extension/bwcontest/src/run/cpp.ts delete mode 100644 extension/bwcontest/src/run/csharp.ts delete mode 100644 extension/bwcontest/src/run/types.ts create mode 100644 sandbox/docker/entry.sh delete mode 100644 sandbox/src/run/java.ts delete mode 100644 sandbox/src/run/types.d.ts rename sandbox/.dockerignore => shared/extensionWeb/.gitignore (56%) rename extension/bwcontest/src/contestMonitor/contestMonitorSharedTypes.ts => shared/extensionWeb/contestMonitorTypes.cts (100%) create mode 100644 shared/extensionWeb/package-lock.json create mode 100644 shared/extensionWeb/package.json create mode 100644 shared/extensionWeb/tsconfig.json create mode 100644 shared/submissionRunner/.gitignore rename sandbox/src/run/cpp.ts => shared/submissionRunner/cpp.cts (95%) rename sandbox/src/run/csharp.ts => shared/submissionRunner/csharp.cts (93%) rename extension/bwcontest/src/run/java.ts => shared/submissionRunner/java.cts (94%) create mode 100644 shared/submissionRunner/package-lock.json create mode 100644 shared/submissionRunner/package.json create mode 100644 shared/submissionRunner/settings.cts create mode 100644 shared/submissionRunner/tsconfig.json create mode 100644 shared/submissionRunner/types.cts delete mode 100644 web/src/lib/contestMonitor/contestMonitorSharedTypes.ts diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..dc92f20 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,22 @@ +sandbox/node_modules +sandbox/build +sandbox/.env + +web/.DS_Store +web/node_modules +web/build +web/.svelte-kit +web/package +web/.env +web/.env.* +web/!.env.example +web/vite.config.js.timestamp-* +web/vite.config.ts.timestamp-* +web/temp +web/db + +shared/submissionRunner/node_modules +shared/submissionRunner/build + +shared/extensionWeb/node_modules +shared/extensionWeb/build \ No newline at end of file diff --git a/extension/bwcontest/src/contestMonitor/contestStateSyncManager.ts b/extension/bwcontest/src/contestMonitor/contestStateSyncManager.ts index 21972b6..f772cfb 100644 --- a/extension/bwcontest/src/contestMonitor/contestStateSyncManager.ts +++ b/extension/bwcontest/src/contestMonitor/contestStateSyncManager.ts @@ -7,7 +7,7 @@ import { ProblemNameForExtension, FullStateForExtension, SubmissionForExtension -} from './contestMonitorSharedTypes'; +} from '@extensionWeb/contestMonitorTypes.cjs'; import { LiteEvent } from '../utilities/LiteEvent'; export type ContestTeamState = { diff --git a/extension/bwcontest/src/problemPanel.ts b/extension/bwcontest/src/problemPanel.ts index 559418c..373dc86 100644 --- a/extension/bwcontest/src/problemPanel.ts +++ b/extension/bwcontest/src/problemPanel.ts @@ -2,11 +2,11 @@ import * as vscode from 'vscode'; import { getNonce } from './getNonce'; import urlJoin from 'url-join'; import { extensionSettings } from './extension'; -import { runJava } from './run/java'; +import { runJava } from '@submissionRunner/java.cjs'; import { join } from 'path'; import { submitProblem } from './submit'; -import { runCSharp } from './run/csharp'; -import { runCpp } from './run/cpp'; +import { runCSharp } from '@submissionRunner/csharp.cjs'; +import { runCpp } from '@submissionRunner/cpp.cjs'; import { TeamData } from './sharedTypes'; import outputPanelLog from './outputPanelLog'; import { recordInitialSubmission } from './contestMonitor/contestStateSyncManager'; diff --git a/extension/bwcontest/src/run/cpp.ts b/extension/bwcontest/src/run/cpp.ts deleted file mode 100644 index 1294614..0000000 --- a/extension/bwcontest/src/run/cpp.ts +++ /dev/null @@ -1,146 +0,0 @@ -import { join } from 'path'; -import { exec, spawn } from 'child_process'; -import { - timeoutSeconds, - type IRunner, - type IRunnerParams, - type IRunnerReturn, - type RunResult -} from './types'; -import kill = require('tree-kill'); -import * as os from 'os'; -import * as fs from 'fs-extra'; -import * as util from 'util'; - -const execPromise = util.promisify(exec); - -export type CppPlatform = 'VisualStudio' | 'GCC'; - -interface IRunnerParamsCpp extends IRunnerParams { - srcDir: string; - problemName: string; - input: string; - cppPlatform: CppPlatform; - outputCallback?: (data: string) => void; -} - -export const runCpp: IRunner = async function ( - params: IRunnerParamsCpp -): IRunnerReturn { - const tmpDir = os.tmpdir(); - const buildDir = join(tmpDir, 'bwcontest-cpp'); - if (fs.existsSync(buildDir)) { - fs.removeSync(buildDir); - } - fs.mkdirSync(buildDir); - - console.log(`- BUILD: ${params.problemName}`); - - const configureCommand = `cmake -S ${params.srcDir} -B ${buildDir}`; - try { - await execPromise(configureCommand); - } catch (e) { - const buildErrorText = e?.toString() ?? 'Unknown build errors.'; - console.log('Build errors: ' + buildErrorText); - return { - success: false, - runResult: { kind: 'CompileFailed', resultKindReason: buildErrorText } - }; - } - - const compileCommand = `cmake --build ${buildDir} --target ${params.problemName}`; - try { - await execPromise(compileCommand); - } catch (e) { - const buildErrorText = e?.toString() ?? 'Unknown build errors.'; - console.log('Build errors: ' + buildErrorText); - return { - success: false, - runResult: { kind: 'CompileFailed', resultKindReason: buildErrorText } - }; - } - - console.log(`- RUN: ${params.problemName}`); - - let runCommand = ''; - if (params.cppPlatform === 'VisualStudio') { - runCommand = `${join(buildDir, 'Debug', `${params.problemName}.exe`)}`; - } else { - runCommand = `${join(buildDir, params.problemName)}`; - } - try { - let outputBuffer = ''; - const child = spawn(runCommand, { shell: true }); - child.stdout.setEncoding('utf8'); - child.stdout.on('data', (data) => { - outputBuffer += data.toString(); - params.outputCallback?.(data.toString()); - }); - child.stderr.setEncoding('utf8'); - child.stderr.on('data', (data) => { - outputBuffer += data.toString(); - params.outputCallback?.(data.toString()); - }); - - const runStartTime = performance.now(); - child.stdin.write(params.input); - child.stdin.end(); - - let timeLimitExceeded = false; - let completedNormally = false; - - return { - success: true, - runResult: new Promise((resolve) => { - child.on('close', () => { - completedNormally = !timeLimitExceeded; - - const runEndTime = performance.now(); - const runtimeMilliseconds = Math.floor(runEndTime - runStartTime); - - if (completedNormally) { - clearTimeout(timeoutHandle); - resolve({ - kind: 'Completed', - output: outputBuffer, - exitCode: child.exitCode!, - runtimeMilliseconds - }); - } else { - console.log(`Process terminated, total sandbox time: ${runtimeMilliseconds}ms`); - resolve({ - kind: 'TimeLimitExceeded', - output: outputBuffer, - resultKindReason: `Timeout after ${timeoutSeconds} seconds` - }); - } - }); - - const timeoutHandle = setTimeout(() => { - if (completedNormally) { - return; - } - - console.log(`Run timed out after ${timeoutSeconds} seconds, killing process...`); - timeLimitExceeded = true; - - child.stdin.end(); - child.stdin.destroy(); - child.stdout.destroy(); - child.stderr.destroy(); - child.kill('SIGKILL'); - }, timeoutSeconds * 1000); - }), - killFunc() { - if (child.pid !== undefined) { - if (!completedNormally && !timeLimitExceeded) { - kill(child.pid); - params.outputCallback?.('\n[Manually stopped]'); - } - } - } - }; - } catch (error) { - return { success: false, runResult: { kind: 'RunError' } }; - } -}; diff --git a/extension/bwcontest/src/run/csharp.ts b/extension/bwcontest/src/run/csharp.ts deleted file mode 100644 index 305f624..0000000 --- a/extension/bwcontest/src/run/csharp.ts +++ /dev/null @@ -1,89 +0,0 @@ -import { spawn } from 'child_process'; -import kill = require('tree-kill'); -import { timeoutSeconds, type IRunner, type IRunnerReturn, type RunResult } from './types'; - -export const runCSharp: IRunner = async function (params: { - srcDir: string; - input: string; - outputCallback?: (data: string) => void; -}): IRunnerReturn { - console.log(`- RUN: ${params.srcDir}`); - const child = spawn('dotnet run', { shell: true, cwd: params.srcDir }); - - try { - let outputBuffer = ''; - child.stdout.setEncoding('utf8'); - child.stdout.on('data', (data) => { - outputBuffer += data.toString(); - params.outputCallback?.(data.toString()); - }); - child.stderr.setEncoding('utf8'); - child.stderr.on('data', (data) => { - outputBuffer += data.toString(); - params.outputCallback?.(data.toString()); - }); - - const runStartTime = performance.now(); - child.stdin.write(params.input); - child.stdin.end(); - - let timeLimitExceeded = false; - let completedNormally = false; - - return { - success: true, - runResult: new Promise((resolve) => { - child.on('close', () => { - completedNormally = !timeLimitExceeded; - - const runEndTime = performance.now(); - const runtimeMilliseconds = Math.floor(runEndTime - runStartTime); - - if (completedNormally) { - clearTimeout(timeoutHandle); - resolve({ - kind: 'Completed', - output: outputBuffer, - exitCode: child.exitCode!, - runtimeMilliseconds - }); - } else { - console.log(`Process terminated, total sandbox time: ${runtimeMilliseconds}ms`); - resolve({ - kind: 'TimeLimitExceeded', - output: outputBuffer, - resultKindReason: `Timeout after ${timeoutSeconds} seconds` - }); - } - }); - - const timeoutHandle = setTimeout(() => { - if (completedNormally) { - return; - } - - console.log(`Run timed out after ${timeoutSeconds} seconds, killing process...`); - timeLimitExceeded = true; - - child.stdin.end(); - child.stdin.destroy(); - child.stdout.destroy(); - child.stderr.destroy(); - if (child.pid !== undefined) { - kill(child.pid); - } - }, timeoutSeconds * 1000); - }), - killFunc() { - if (child.pid !== undefined) { - if (!completedNormally && !timeLimitExceeded) { - kill(child.pid); - params.outputCallback?.('\n[Manually stopped]'); - } - } - } - }; - } catch (error) { - return { success: false, runResult: { kind: 'RunError' } }; - } -}; diff --git a/extension/bwcontest/src/run/types.ts b/extension/bwcontest/src/run/types.ts deleted file mode 100644 index 9e04924..0000000 --- a/extension/bwcontest/src/run/types.ts +++ /dev/null @@ -1,31 +0,0 @@ -export const timeoutSeconds = 30; - -export type RunResultKind = - | 'CompileFailed' - | 'TimeLimitExceeded' - | 'Completed' - | 'SandboxError' - | 'RunError'; - -export type RunResult = { - kind: RunResultKind; - output?: string; - exitCode?: number; - runtimeMilliseconds?: number; - resultKindReason?: string; -}; - -export interface IRunnerParams { - srcDir: string; - input: string; - outputCallback?: (data: string) => void; -} - -export type IRunnerReturn = Promise< - | { success: true; killFunc: () => void; runResult: Promise } - | { success: false; runResult: RunResult } ->; - -export interface IRunner { - (params: T): IRunnerReturn; -} diff --git a/extension/bwcontest/tsconfig.json b/extension/bwcontest/tsconfig.json index 3da0623..4ad872d 100644 --- a/extension/bwcontest/tsconfig.json +++ b/extension/bwcontest/tsconfig.json @@ -6,11 +6,19 @@ "lib": ["ES2020"], "sourceMap": true, "rootDir": "src", - "strict": true /* enable all strict type-checking options */ + "strict": true, /* enable all strict type-checking options */ /* Additional Checks */ // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ // "noUnusedParameters": true, /* Report errors on unused parameters. */ + "paths": { + "@submissionRunner/*": ["../../shared/submissionRunner/*"], + "@extensionWeb/*": ["../../shared/extensionWeb/*"] + }, }, - "exclude": ["webviews"] -} + "exclude": ["webviews"], + "references": [ + { "path": "../../shared/submissionRunner" }, + { "path": "../../shared/extensionWeb" } + ] +} \ No newline at end of file diff --git a/sandbox/Dockerfile b/sandbox/Dockerfile index 9d0ec57..356df7f 100644 --- a/sandbox/Dockerfile +++ b/sandbox/Dockerfile @@ -1,6 +1,9 @@ FROM ubuntu:22.04 -WORKDIR /app +# Setup + +RUN mkdir sandbox +WORKDIR /app/sandbox RUN apt-get update @@ -20,10 +23,28 @@ ENV DOTNET_SKIP_FIRST_TIME_EXPERIENCE=true RUN git config --global user.name "Admin" RUN git config --global user.email noemail@example.com -WORKDIR /app +# Prep Sandbox -COPY package*.json ./ +WORKDIR /app/sandbox + +COPY ./sandbox/package*.json ./ RUN npm install -COPY . . +COPY ./sandbox/ . + +# Prep SubmissionRunner + +WORKDIR /app +RUN mkdir shared +RUN mkdir shared/submissionRunner +WORKDIR /app/shared/submissionRunner + +COPY ./shared/submissionRunner/package*.json . +RUN npm install +COPY ./shared/submissionRunner/ . + +# Build/Run + +WORKDIR /app/sandbox RUN npm run build -CMD ["node", "build"] \ No newline at end of file +RUN chmod +x ./docker/entry.sh +CMD ["./docker/entry.sh"] \ No newline at end of file diff --git a/sandbox/docker-compose.yml b/sandbox/docker-compose.yml index c2791b6..497292a 100644 --- a/sandbox/docker-compose.yml +++ b/sandbox/docker-compose.yml @@ -1,7 +1,9 @@ version: '3' services: sandbox: - build: . + build: + context: ../ + dockerfile: ./sandbox/Dockerfile environment: - ADMIN_URL=${ADMIN_URL} - REPO_URL=${REPO_URL} diff --git a/sandbox/docker/entry.sh b/sandbox/docker/entry.sh new file mode 100644 index 0000000..fe65d47 --- /dev/null +++ b/sandbox/docker/entry.sh @@ -0,0 +1,3 @@ +#!/bin/bash +# THIS FILE MUST USE LF LINE SEPARATORS! +node ./build/sandbox.cjs \ No newline at end of file diff --git a/sandbox/package-lock.json b/sandbox/package-lock.json index 8fc86ef..9979db5 100644 --- a/sandbox/package-lock.json +++ b/sandbox/package-lock.json @@ -11,16 +11,22 @@ "dependencies": { "dotenv": "^16.3.1", "fs-extra": "^11.2.0", + "rollup": "^4.12.1", "simple-git": "^3.22.0", "tree-kill": "^1.2.2", "url-join": "^5.0.0", "zod": "^3.22.4" }, "devDependencies": { + "@rollup/plugin-commonjs": "^25.0.7", + "@rollup/plugin-node-resolve": "^15.2.3", + "@rollup/plugin-terser": "^0.4.4", + "@rollup/plugin-typescript": "^11.1.6", "@types/fs-extra": "^11.0.4", "@types/node": "^20.11.2", "@typescript-eslint/eslint-plugin": "^7.0.1", "@typescript-eslint/parser": "^7.0.1", + "esbuild": "^0.19.11", "eslint": "^8.56.0", "prettier": "^3.2.2", "typescript": "^5.3.3" @@ -35,6 +41,374 @@ "node": ">=0.10.0" } }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.19.12.tgz", + "integrity": "sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.12.tgz", + "integrity": "sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.12.tgz", + "integrity": "sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.12.tgz", + "integrity": "sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.12.tgz", + "integrity": "sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.12.tgz", + "integrity": "sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.12.tgz", + "integrity": "sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.12.tgz", + "integrity": "sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.12.tgz", + "integrity": "sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.12.tgz", + "integrity": "sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.12.tgz", + "integrity": "sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.12.tgz", + "integrity": "sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.12.tgz", + "integrity": "sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.12.tgz", + "integrity": "sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.12.tgz", + "integrity": "sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.12.tgz", + "integrity": "sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.12.tgz", + "integrity": "sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.12.tgz", + "integrity": "sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.12.tgz", + "integrity": "sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.12.tgz", + "integrity": "sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.12.tgz", + "integrity": "sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.12.tgz", + "integrity": "sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.12.tgz", + "integrity": "sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, "node_modules/@eslint-community/eslint-utils": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", @@ -168,6 +542,64 @@ "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==", "dev": true }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.5.tgz", + "integrity": "sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, "node_modules/@kwsites/file-exists": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@kwsites/file-exists/-/file-exists-1.1.1.tgz", @@ -216,6 +648,318 @@ "node": ">= 8" } }, + "node_modules/@rollup/plugin-commonjs": { + "version": "25.0.7", + "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-25.0.7.tgz", + "integrity": "sha512-nEvcR+LRjEjsaSsc4x3XZfCCvZIaSMenZu/OiwOKGN2UhQpAYI7ru7czFvyWbErlpoGjnSX3D5Ch5FcMA3kRWQ==", + "dev": true, + "dependencies": { + "@rollup/pluginutils": "^5.0.1", + "commondir": "^1.0.1", + "estree-walker": "^2.0.2", + "glob": "^8.0.3", + "is-reference": "1.2.1", + "magic-string": "^0.30.3" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^2.68.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/plugin-commonjs/node_modules/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@rollup/plugin-commonjs/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@rollup/plugin-node-resolve": { + "version": "15.2.3", + "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-15.2.3.tgz", + "integrity": "sha512-j/lym8nf5E21LwBT4Df1VD6hRO2L2iwUeUmP7litikRsVp1H6NWx20NEp0Y7su+7XGc476GnXXc4kFeZNGmaSQ==", + "dev": true, + "dependencies": { + "@rollup/pluginutils": "^5.0.1", + "@types/resolve": "1.20.2", + "deepmerge": "^4.2.2", + "is-builtin-module": "^3.2.1", + "is-module": "^1.0.0", + "resolve": "^1.22.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^2.78.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/plugin-terser": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/@rollup/plugin-terser/-/plugin-terser-0.4.4.tgz", + "integrity": "sha512-XHeJC5Bgvs8LfukDwWZp7yeqin6ns8RTl2B9avbejt6tZqsqvVoWI7ZTQrcNsfKEDWBTnTxM8nMDkO2IFFbd0A==", + "dev": true, + "dependencies": { + "serialize-javascript": "^6.0.1", + "smob": "^1.0.0", + "terser": "^5.17.4" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^2.0.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/plugin-typescript": { + "version": "11.1.6", + "resolved": "https://registry.npmjs.org/@rollup/plugin-typescript/-/plugin-typescript-11.1.6.tgz", + "integrity": "sha512-R92yOmIACgYdJ7dJ97p4K69I8gg6IEHt8M7dUBxN3W6nrO8uUxX5ixl0yU/N3aZTi8WhPuICvOHXQvF6FaykAA==", + "dev": true, + "dependencies": { + "@rollup/pluginutils": "^5.1.0", + "resolve": "^1.22.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^2.14.0||^3.0.0||^4.0.0", + "tslib": "*", + "typescript": ">=3.7.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + }, + "tslib": { + "optional": true + } + } + }, + "node_modules/@rollup/pluginutils": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.0.tgz", + "integrity": "sha512-XTIWOPPcpvyKI6L1NHo0lFlCyznUEyPmPY1mc3KpPVDYulHSTvyeLNVW00QTLIAFNhR3kYnJTQHeGqU4M3n09g==", + "dev": true, + "dependencies": { + "@types/estree": "^1.0.0", + "estree-walker": "^2.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.12.1.tgz", + "integrity": "sha512-iU2Sya8hNn1LhsYyf0N+L4Gf9Qc+9eBTJJJsaOGUp+7x4n2M9dxTt8UvhJl3oeftSjblSlpCfvjA/IfP3g5VjQ==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.12.1.tgz", + "integrity": "sha512-wlzcWiH2Ir7rdMELxFE5vuM7D6TsOcJ2Yw0c3vaBR3VOsJFVTx9xvwnAvhgU5Ii8Gd6+I11qNHwndDscIm0HXg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.12.1.tgz", + "integrity": "sha512-YRXa1+aZIFN5BaImK+84B3uNK8C6+ynKLPgvn29X9s0LTVCByp54TB7tdSMHDR7GTV39bz1lOmlLDuedgTwwHg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.12.1.tgz", + "integrity": "sha512-opjWJ4MevxeA8FhlngQWPBOvVWYNPFkq6/25rGgG+KOy0r8clYwL1CFd+PGwRqqMFVQ4/Qd3sQu5t7ucP7C/Uw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.12.1.tgz", + "integrity": "sha512-uBkwaI+gBUlIe+EfbNnY5xNyXuhZbDSx2nzzW8tRMjUmpScd6lCQYKY2V9BATHtv5Ef2OBq6SChEP8h+/cxifQ==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.12.1.tgz", + "integrity": "sha512-0bK9aG1kIg0Su7OcFTlexkVeNZ5IzEsnz1ept87a0TUgZ6HplSgkJAnFpEVRW7GRcikT4GlPV0pbtVedOaXHQQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.12.1.tgz", + "integrity": "sha512-qB6AFRXuP8bdkBI4D7UPUbE7OQf7u5OL+R94JE42Z2Qjmyj74FtDdLGeriRyBDhm4rQSvqAGCGC01b8Fu2LthQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.12.1.tgz", + "integrity": "sha512-sHig3LaGlpNgDj5o8uPEoGs98RII8HpNIqFtAI8/pYABO8i0nb1QzT0JDoXF/pxzqO+FkxvwkHZo9k0NJYDedg==", + "cpu": [ + "riscv64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.12.1.tgz", + "integrity": "sha512-nD3YcUv6jBJbBNFvSbp0IV66+ba/1teuBcu+fBBPZ33sidxitc6ErhON3JNavaH8HlswhWMC3s5rgZpM4MtPqQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.12.1.tgz", + "integrity": "sha512-7/XVZqgBby2qp/cO0TQ8uJK+9xnSdJ9ct6gSDdEr4MfABrjTyrW6Bau7HQ73a2a5tPB7hno49A0y1jhWGDN9OQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.12.1.tgz", + "integrity": "sha512-CYc64bnICG42UPL7TrhIwsJW4QcKkIt9gGlj21gq3VV0LL6XNb1yAdHVp1pIi9gkts9gGcT3OfUYHjGP7ETAiw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.12.1.tgz", + "integrity": "sha512-LN+vnlZ9g0qlHGlS920GR4zFCqAwbv2lULrR29yGaWP9u7wF5L7GqWu9Ah6/kFZPXPUkpdZwd//TNR+9XC9hvA==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.12.1.tgz", + "integrity": "sha512-n+vkrSyphvmU0qkQ6QBNXCGr2mKjhP08mPRM/Xp5Ck2FV4NrHU+y6axzDeixUrCBHVUS51TZhjqrKBBsHLKb2Q==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@types/estree": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==" + }, "node_modules/@types/fs-extra": { "version": "11.0.4", "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-11.0.4.tgz", @@ -250,6 +994,12 @@ "undici-types": "~5.26.4" } }, + "node_modules/@types/resolve": { + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz", + "integrity": "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==", + "dev": true + }, "node_modules/@types/semver": { "version": "7.5.7", "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.7.tgz", @@ -555,6 +1305,24 @@ "node": ">=8" } }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, + "node_modules/builtin-modules": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", + "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==", + "dev": true, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -598,6 +1366,18 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, + "node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "node_modules/commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", + "dev": true + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -640,6 +1420,15 @@ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/dir-glob": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", @@ -675,6 +1464,44 @@ "url": "https://github.com/motdotla/dotenv?sponsor=1" } }, + "node_modules/esbuild": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.12.tgz", + "integrity": "sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.19.12", + "@esbuild/android-arm": "0.19.12", + "@esbuild/android-arm64": "0.19.12", + "@esbuild/android-x64": "0.19.12", + "@esbuild/darwin-arm64": "0.19.12", + "@esbuild/darwin-x64": "0.19.12", + "@esbuild/freebsd-arm64": "0.19.12", + "@esbuild/freebsd-x64": "0.19.12", + "@esbuild/linux-arm": "0.19.12", + "@esbuild/linux-arm64": "0.19.12", + "@esbuild/linux-ia32": "0.19.12", + "@esbuild/linux-loong64": "0.19.12", + "@esbuild/linux-mips64el": "0.19.12", + "@esbuild/linux-ppc64": "0.19.12", + "@esbuild/linux-riscv64": "0.19.12", + "@esbuild/linux-s390x": "0.19.12", + "@esbuild/linux-x64": "0.19.12", + "@esbuild/netbsd-x64": "0.19.12", + "@esbuild/openbsd-x64": "0.19.12", + "@esbuild/sunos-x64": "0.19.12", + "@esbuild/win32-arm64": "0.19.12", + "@esbuild/win32-ia32": "0.19.12", + "@esbuild/win32-x64": "0.19.12" + } + }, "node_modules/escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", @@ -842,6 +1669,12 @@ "node": ">=4.0" } }, + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true + }, "node_modules/esutils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", @@ -985,6 +1818,28 @@ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", "dev": true }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", @@ -1094,6 +1949,18 @@ "node": ">=8" } }, + "node_modules/hasown": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.1.tgz", + "integrity": "sha512-1/th4MHjnwncwXsIW6QMzlvYL9kG5e/CpVvLRZe4XPa8TOUNbCELqmvhDmnkNsAjwaG4+I8gJJL0JBvTTLO9qA==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/ignore": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", @@ -1144,6 +2011,33 @@ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true }, + "node_modules/is-builtin-module": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.2.1.tgz", + "integrity": "sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==", + "dev": true, + "dependencies": { + "builtin-modules": "^3.3.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-core-module": { + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", + "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", + "dev": true, + "dependencies": { + "hasown": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -1165,6 +2059,12 @@ "node": ">=0.10.0" } }, + "node_modules/is-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", + "integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==", + "dev": true + }, "node_modules/is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", @@ -1183,6 +2083,15 @@ "node": ">=8" } }, + "node_modules/is-reference": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz", + "integrity": "sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==", + "dev": true, + "dependencies": { + "@types/estree": "*" + } + }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -1285,6 +2194,18 @@ "node": ">=10" } }, + "node_modules/magic-string": { + "version": "0.30.8", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.8.tgz", + "integrity": "sha512-ISQTe55T2ao7XtlAStud6qwYPZjE4GK1S/BeVPus4jrq6JuOnQ00YKQC581RWhR122W7msZV263KzVeLoqidyQ==", + "dev": true, + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.4.15" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", @@ -1428,6 +2349,12 @@ "node": ">=8" } }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, "node_modules/path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", @@ -1502,6 +2429,32 @@ } ] }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "dev": true, + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", @@ -1536,6 +2489,37 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/rollup": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.12.1.tgz", + "integrity": "sha512-ggqQKvx/PsB0FaWXhIvVkSWh7a/PCLQAsMjBc+nA2M8Rv2/HG0X6zvixAB7KyZBRtifBUhy5k8voQX/mRnABPg==", + "dependencies": { + "@types/estree": "1.0.5" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.12.1", + "@rollup/rollup-android-arm64": "4.12.1", + "@rollup/rollup-darwin-arm64": "4.12.1", + "@rollup/rollup-darwin-x64": "4.12.1", + "@rollup/rollup-linux-arm-gnueabihf": "4.12.1", + "@rollup/rollup-linux-arm64-gnu": "4.12.1", + "@rollup/rollup-linux-arm64-musl": "4.12.1", + "@rollup/rollup-linux-riscv64-gnu": "4.12.1", + "@rollup/rollup-linux-x64-gnu": "4.12.1", + "@rollup/rollup-linux-x64-musl": "4.12.1", + "@rollup/rollup-win32-arm64-msvc": "4.12.1", + "@rollup/rollup-win32-ia32-msvc": "4.12.1", + "@rollup/rollup-win32-x64-msvc": "4.12.1", + "fsevents": "~2.3.2" + } + }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -1559,6 +2543,26 @@ "queue-microtask": "^1.2.2" } }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, "node_modules/semver": { "version": "7.6.0", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", @@ -1574,6 +2578,15 @@ "node": ">=10" } }, + "node_modules/serialize-javascript": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", + "dev": true, + "dependencies": { + "randombytes": "^2.1.0" + } + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -1618,6 +2631,31 @@ "node": ">=8" } }, + "node_modules/smob": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/smob/-/smob-1.4.1.tgz", + "integrity": "sha512-9LK+E7Hv5R9u4g4C3p+jjLstaLe11MDsL21UpYaCNmapvMkYhqCV4A/f/3gyH8QjMyh6l68q9xC85vihY9ahMQ==", + "dev": true + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, "node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", @@ -1654,6 +2692,36 @@ "node": ">=8" } }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/terser": { + "version": "5.29.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.29.1.tgz", + "integrity": "sha512-lZQ/fyaIGxsbGxApKmoPTODIzELy3++mXhS5hOqaAWZjQtpq/hFHAc+rm29NND1rYRxRWKcjuARNwULNXa5RtQ==", + "dev": true, + "dependencies": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.8.2", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", diff --git a/sandbox/package.json b/sandbox/package.json index 81890dc..57b6bac 100644 --- a/sandbox/package.json +++ b/sandbox/package.json @@ -5,18 +5,23 @@ "main": "index.js", "type": "module", "scripts": { - "build": "tsc", + "build": "esbuild src/index.ts --bundle --outfile=build/sandbox.cjs --format=cjs --platform=node", "format": "prettier --write .", "lint": "prettier --check . && eslint .", - "start": "node build" + "start": "node ./build/sandbox.cjs" }, "author": "", "license": "ISC", "devDependencies": { + "@rollup/plugin-commonjs": "^25.0.7", + "@rollup/plugin-node-resolve": "^15.2.3", + "@rollup/plugin-terser": "^0.4.4", + "@rollup/plugin-typescript": "^11.1.6", "@types/fs-extra": "^11.0.4", "@types/node": "^20.11.2", "@typescript-eslint/eslint-plugin": "^7.0.1", "@typescript-eslint/parser": "^7.0.1", + "esbuild": "^0.19.11", "eslint": "^8.56.0", "prettier": "^3.2.2", "typescript": "^5.3.3" @@ -24,6 +29,7 @@ "dependencies": { "dotenv": "^16.3.1", "fs-extra": "^11.2.0", + "rollup": "^4.12.1", "simple-git": "^3.22.0", "tree-kill": "^1.2.2", "url-join": "^5.0.0", diff --git a/sandbox/src/index.ts b/sandbox/src/index.ts index 822d1e9..b6bffbb 100644 --- a/sandbox/src/index.ts +++ b/sandbox/src/index.ts @@ -1,39 +1,19 @@ -import dotenv from 'dotenv'; +import 'dotenv/config'; import fs from 'fs-extra'; import urlJoin from 'url-join'; -import { z } from 'zod'; import os, { EOL } from 'os'; import { join } from 'path'; import { simpleGit, SimpleGit } from 'simple-git'; -import { runJava } from './run/java.js'; -import { runCSharp } from './run/csharp.js'; -import { runCpp } from './run/cpp.js'; - -export const timeoutSeconds = 30; - -const RunResultKind = z.enum([ - 'CompileFailed', - 'TimeLimitExceeded', - 'Completed', - 'SandboxError', - 'RunError' -]); -export type RunResultKind = z.infer; - -const RunResult = z - .object({ - kind: RunResultKind, - output: z.string().optional(), - exitCode: z.number().optional(), - runtimeMilliseconds: z.number().optional(), - resultKindReason: z.string().optional() - }) - .strict(); +import { runJava } from '@submissionRunner/java.cjs'; +import { runCSharp } from '@submissionRunner/csharp.cjs'; +import { runCpp } from '@submissionRunner/cpp.cjs'; +import { RunResult, RunResultZod } from '@submissionRunner/types.cjs'; +import { z } from 'zod'; const submissionPostData = z .object({ submissionId: z.number(), - result: RunResult + result: RunResultZod }) .strict(); @@ -59,7 +39,6 @@ const submissionGetData = z }) .strict(); -export type RunResult = z.infer; type SubmissionGetData = z.infer; type SubmissionPostData = z.infer; @@ -78,10 +57,12 @@ async function fetchQueuedSubmission(): Promise { return undefined; } - const data = submissionGetData.parse(await res.json()); + const json = await res.json(); + const data = submissionGetData.parse(json); if (!data.success) { return undefined; } + return data; } @@ -205,9 +186,14 @@ function validateEnv(): boolean { return process.env.ADMIN_URL !== undefined && process.env.REPO_URL !== undefined; } -dotenv.config(); - if (!validateEnv()) { + console.log(process.env); + console.log( + 'process.env.ADMIN_URL is ' + + process.env.ADMIN_URL + + ' and process.env.REPO_URL is ' + + process.env.REPO_URL + ); throw Error('Invalid environment'); } @@ -287,15 +273,17 @@ async function run() { break; case SubmissionProcessingResult.NoSubmissions: if (iterationsSinceProcessedSubmission > 0 && iterationsSinceProcessedSubmission % 6 == 0) { - const numMinutes = iterationsSinceProcessedSubmission / 6; - console.log( - `${numMinutes} minute${numMinutes > 1 ? 's' : ''} since ` + - `${ - anySubmissionsProcessed - ? `last submission processed` - : `sandbox startup with no submissions` - }` - ); + { + const numMinutes = iterationsSinceProcessedSubmission / 6; + console.log( + `${numMinutes} minute${numMinutes > 1 ? 's' : ''} since ` + + `${ + anySubmissionsProcessed + ? `last submission processed` + : `sandbox startup with no submissions` + }` + ); + } } await new Promise((resolve) => setTimeout(resolve, 10000)); diff --git a/sandbox/src/run/java.ts b/sandbox/src/run/java.ts deleted file mode 100644 index b2c94f8..0000000 --- a/sandbox/src/run/java.ts +++ /dev/null @@ -1,111 +0,0 @@ -import { join } from 'path'; -import { exec, spawn } from 'child_process'; -import util from 'util'; -import { RunResult, timeoutSeconds } from '../index.js'; -import { IRunner, IRunnerParams, IRunnerReturn } from './types.js'; -import kill from 'tree-kill'; - -const execPromise = util.promisify(exec); - -interface IRunnerParamsJava extends IRunnerParams { - srcDir: string; - mainFile: string; - mainClass: string; - input: string; - outputCallback?: (data: string) => void; -} - -export const runJava: IRunner = async function ( - params: IRunnerParamsJava -): IRunnerReturn { - console.log(`- BUILD: ${params.mainFile}`); - const compileCommand = `javac -cp ${join(params.srcDir, 'src')} ${params.mainFile} -d ${join(params.srcDir, 'build')}`; - - try { - await execPromise(compileCommand); - } catch (e) { - const buildErrorText = e?.toString() ?? 'Unknown build errors.'; - console.log('Build errors: ' + buildErrorText); - return { - success: false, - runResult: { kind: 'CompileFailed', resultKindReason: buildErrorText } - }; - } - - console.log(`- RUN: ${params.mainClass}`); - const runCommand = `java -cp "${join(params.srcDir, 'build')}" ${params.mainClass}`; - - try { - let outputBuffer = ''; - const child = spawn(runCommand, { shell: true }); - child.stdout.setEncoding('utf8'); - child.stdout.on('data', (data) => { - outputBuffer += data.toString(); - }); - child.stderr.setEncoding('utf8'); - child.stderr.on('data', (data) => { - outputBuffer += data.toString(); - }); - - const runStartTime = performance.now(); - child.stdin.write(params.input); - child.stdin.end(); - - let timeLimitExceeded = false; - let completedNormally = false; - - return { - success: true, - runResult: new Promise((resolve) => { - child.on('close', () => { - completedNormally = !timeLimitExceeded; - - const runEndTime = performance.now(); - const runtimeMilliseconds = Math.floor(runEndTime - runStartTime); - - if (completedNormally) { - clearTimeout(timeoutHandle); - resolve({ - kind: 'Completed', - output: outputBuffer, - exitCode: child.exitCode!, - runtimeMilliseconds - }); - } else { - console.log(`Process terminated, total sandbox time: ${runtimeMilliseconds}ms`); - resolve({ - kind: 'TimeLimitExceeded', - output: outputBuffer, - resultKindReason: `Timeout after ${timeoutSeconds} seconds` - }); - } - }); - - const timeoutHandle = setTimeout(() => { - if (completedNormally) { - return; - } - - console.log(`Run timed out after ${timeoutSeconds} seconds, killing process...`); - timeLimitExceeded = true; - - child.stdin.end(); - child.stdin.destroy(); - child.stdout.destroy(); - child.stderr.destroy(); - child.kill('SIGKILL'); - }, timeoutSeconds * 1000); - }), - killFunc() { - if (child.pid !== undefined) { - if (!completedNormally && !timeLimitExceeded) { - kill(child.pid); - params.outputCallback?.('\n[Manually stopped]'); - } - } - } - }; - } catch (error) { - return { success: false, runResult: { kind: 'RunError' } }; - } -}; diff --git a/sandbox/src/run/types.d.ts b/sandbox/src/run/types.d.ts deleted file mode 100644 index e24f300..0000000 --- a/sandbox/src/run/types.d.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { RunResult } from '../index.ts'; - -interface IRunnerParams { - srcDir: string; - input: string; - outputCallback?: (data: string) => void; -} - -type IRunnerReturn = Promise< - | { success: true; killFunc: () => void; runResult: Promise } - | { success: false; runResult: RunResult } ->; - -interface IRunner { - (params: T): IRunnerReturn; -} diff --git a/sandbox/tsconfig.json b/sandbox/tsconfig.json index 7e9b0cb..1965264 100644 --- a/sandbox/tsconfig.json +++ b/sandbox/tsconfig.json @@ -4,7 +4,10 @@ "sourceMap": true, "outDir": "./build", "esModuleInterop": true, - "strict": true + "strict": true, + "paths": { + "@submissionRunner/*": ["../shared/submissionRunner/*"] + } }, - "include": ["./src/**/*"] + "references": [{ "path": "../shared/submissionRunner" }] } diff --git a/sandbox/.dockerignore b/shared/extensionWeb/.gitignore similarity index 56% rename from sandbox/.dockerignore rename to shared/extensionWeb/.gitignore index c27e9ba..8c08c51 100644 --- a/sandbox/.dockerignore +++ b/shared/extensionWeb/.gitignore @@ -1,3 +1,2 @@ node_modules -build -.env \ No newline at end of file +/build diff --git a/extension/bwcontest/src/contestMonitor/contestMonitorSharedTypes.ts b/shared/extensionWeb/contestMonitorTypes.cts similarity index 100% rename from extension/bwcontest/src/contestMonitor/contestMonitorSharedTypes.ts rename to shared/extensionWeb/contestMonitorTypes.cts diff --git a/shared/extensionWeb/package-lock.json b/shared/extensionWeb/package-lock.json new file mode 100644 index 0000000..95b84d2 --- /dev/null +++ b/shared/extensionWeb/package-lock.json @@ -0,0 +1,10 @@ +{ + "name": "extensionWeb", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "devDependencies": {} + } + } +} diff --git a/shared/extensionWeb/package.json b/shared/extensionWeb/package.json new file mode 100644 index 0000000..babd48c --- /dev/null +++ b/shared/extensionWeb/package.json @@ -0,0 +1,9 @@ +{ + "scripts": { + "build": "tsc" + }, + "devDependencies": { + }, + "dependencies": { + } +} diff --git a/shared/extensionWeb/tsconfig.json b/shared/extensionWeb/tsconfig.json new file mode 100644 index 0000000..6a80e3d --- /dev/null +++ b/shared/extensionWeb/tsconfig.json @@ -0,0 +1,14 @@ +{ + "compilerOptions": { + "composite": true, + "target": "es2016", + "module": "commonjs", + "declaration": true, + "declarationMap": true, + "sourceMap": true, + "outDir": "./build", + "esModuleInterop": true, + "strict": true, + }, + "include": ["/**/*.cts"] +} \ No newline at end of file diff --git a/shared/submissionRunner/.gitignore b/shared/submissionRunner/.gitignore new file mode 100644 index 0000000..8c08c51 --- /dev/null +++ b/shared/submissionRunner/.gitignore @@ -0,0 +1,2 @@ +node_modules +/build diff --git a/sandbox/src/run/cpp.ts b/shared/submissionRunner/cpp.cts similarity index 95% rename from sandbox/src/run/cpp.ts rename to shared/submissionRunner/cpp.cts index 8cd03b8..9735a1c 100644 --- a/sandbox/src/run/cpp.ts +++ b/shared/submissionRunner/cpp.cts @@ -1,8 +1,8 @@ import { join } from 'path'; import { exec, spawn } from 'child_process'; import util from 'util'; -import { RunResult, timeoutSeconds } from '../index.js'; -import { IRunner, IRunnerParams, IRunnerReturn } from './types.js'; +import type { IRunner, IRunnerParams, IRunnerReturn, RunResult } from './types.cjs'; +import { timeoutSeconds } from './settings.cjs'; import kill from 'tree-kill'; import os from 'os'; import fs from 'fs-extra'; @@ -21,7 +21,7 @@ interface IRunnerParamsCpp extends IRunnerParams { export const runCpp: IRunner = async function ( params: IRunnerParamsCpp -): IRunnerReturn { +): Promise { const tmpDir = os.tmpdir(); const buildDir = join(tmpDir, 'bwcontest-cpp'); if (fs.existsSync(buildDir)) { diff --git a/sandbox/src/run/csharp.ts b/shared/submissionRunner/csharp.cts similarity index 93% rename from sandbox/src/run/csharp.ts rename to shared/submissionRunner/csharp.cts index c1ab4f6..17cced7 100644 --- a/sandbox/src/run/csharp.ts +++ b/shared/submissionRunner/csharp.cts @@ -1,13 +1,13 @@ import { spawn } from 'child_process'; import kill from 'tree-kill'; -import { RunResult, timeoutSeconds } from '../index.js'; -import { IRunner, IRunnerReturn } from './types.js'; +import type { IRunner, IRunnerReturn, RunResult } from './types.cjs'; +import { timeoutSeconds } from './settings.cjs'; export const runCSharp: IRunner = async function (params: { srcDir: string; input: string; outputCallback?: (data: string) => void; -}): IRunnerReturn { +}): Promise { console.log(`- RUN: ${params.srcDir}`); const child = spawn('dotnet run', { shell: true, cwd: params.srcDir }); diff --git a/extension/bwcontest/src/run/java.ts b/shared/submissionRunner/java.cts similarity index 94% rename from extension/bwcontest/src/run/java.ts rename to shared/submissionRunner/java.cts index 3626488..9ca3707 100644 --- a/extension/bwcontest/src/run/java.ts +++ b/shared/submissionRunner/java.cts @@ -1,13 +1,9 @@ import { join } from 'path'; import { exec, spawn } from 'child_process'; import * as util from 'util'; -import { - timeoutSeconds, - type IRunner, - type IRunnerParams, - type IRunnerReturn, - type RunResult -} from './types'; +import type { IRunner, IRunnerParams, IRunnerReturn, RunResult } from './types.cjs'; +import { timeoutSeconds } from './settings.cjs'; + import kill = require('tree-kill'); const execPromise = util.promisify(exec); @@ -22,7 +18,7 @@ interface IRunnerParamsJava extends IRunnerParams { export const runJava: IRunner = async function ( params: IRunnerParamsJava -): IRunnerReturn { +): Promise { console.log(`- BUILD: ${params.mainFile}`); const compileCommand = `javac -cp ${join(params.srcDir, 'src')} ${params.mainFile} -d ${join(params.srcDir, 'build')}`; diff --git a/shared/submissionRunner/package-lock.json b/shared/submissionRunner/package-lock.json new file mode 100644 index 0000000..3958d68 --- /dev/null +++ b/shared/submissionRunner/package-lock.json @@ -0,0 +1,118 @@ +{ + "name": "submissionRunner", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "dependencies": { + "fs-extra": "^11.2.0", + "tree-kill": "^1.2.2", + "typescript": "^5.4.2", + "zod": "^3.22.4" + }, + "devDependencies": { + "@types/fs-extra": "^11.0.4", + "@types/node": "20.x" + } + }, + "node_modules/@types/fs-extra": { + "version": "11.0.4", + "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-11.0.4.tgz", + "integrity": "sha512-yTbItCNreRooED33qjunPthRcSjERP1r4MqCZc7wv0u2sUkzTFp45tgUfS5+r7FrZPdmCCNflLhVSP/o+SemsQ==", + "dev": true, + "dependencies": { + "@types/jsonfile": "*", + "@types/node": "*" + } + }, + "node_modules/@types/jsonfile": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/@types/jsonfile/-/jsonfile-6.1.4.tgz", + "integrity": "sha512-D5qGUYwjvnNNextdU59/+fI+spnwtTFmyQP0h+PfIOSkNfpU6AOICUOkm4i0OnSk+NyjdPJrxCDro0sJsWlRpQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/node": { + "version": "20.11.25", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.25.tgz", + "integrity": "sha512-TBHyJxk2b7HceLVGFcpAUjsa5zIdsPWlR6XHfyGzd0SFu+/NFgQgMAl96MSDZgQDvJAvV6BKsFOrt6zIL09JDw==", + "dev": true, + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/fs-extra": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "bin": { + "tree-kill": "cli.js" + } + }, + "node_modules/typescript": { + "version": "5.4.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.2.tgz", + "integrity": "sha512-+2/g0Fds1ERlP6JsakQQDXjZdZMM+rqpamFZJEKh4kwTIn3iDkgKtby0CeNd5ATNZ4Ry1ax15TMx0W2V+miizQ==", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true + }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/zod": { + "version": "3.22.4", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.22.4.tgz", + "integrity": "sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + } + } +} diff --git a/shared/submissionRunner/package.json b/shared/submissionRunner/package.json new file mode 100644 index 0000000..9e2139e --- /dev/null +++ b/shared/submissionRunner/package.json @@ -0,0 +1,15 @@ +{ + "scripts": { + "build": "tsc" + }, + "devDependencies": { + "@types/node": "20.x", + "@types/fs-extra": "^11.0.4" + }, + "dependencies": { + "typescript": "^5.4.2", + "zod": "^3.22.4", + "tree-kill": "^1.2.2", + "fs-extra": "^11.2.0" + } +} diff --git a/shared/submissionRunner/settings.cts b/shared/submissionRunner/settings.cts new file mode 100644 index 0000000..394d79e --- /dev/null +++ b/shared/submissionRunner/settings.cts @@ -0,0 +1 @@ +export const timeoutSeconds = 30; \ No newline at end of file diff --git a/shared/submissionRunner/tsconfig.json b/shared/submissionRunner/tsconfig.json new file mode 100644 index 0000000..6a80e3d --- /dev/null +++ b/shared/submissionRunner/tsconfig.json @@ -0,0 +1,14 @@ +{ + "compilerOptions": { + "composite": true, + "target": "es2016", + "module": "commonjs", + "declaration": true, + "declarationMap": true, + "sourceMap": true, + "outDir": "./build", + "esModuleInterop": true, + "strict": true, + }, + "include": ["/**/*.cts"] +} \ No newline at end of file diff --git a/shared/submissionRunner/types.cts b/shared/submissionRunner/types.cts new file mode 100644 index 0000000..c8ec4b5 --- /dev/null +++ b/shared/submissionRunner/types.cts @@ -0,0 +1,36 @@ +import { z } from 'zod'; + +const RunResultKind = z.enum([ + 'CompileFailed', + 'TimeLimitExceeded', + 'Completed', + 'SandboxError', + 'RunError' +]); + +export type RunResultKind = z.infer; + +export const RunResultZod = z + .object({ + kind: RunResultKind, + output: z.string().optional(), + exitCode: z.number().optional(), + runtimeMilliseconds: z.number().optional(), + resultKindReason: z.string().optional() + }) + .strict(); + +export type RunResult = z.infer; + +export interface IRunnerParams { + srcDir: string; + input: string; + outputCallback?: (data: string) => void; +} + +export type IRunnerReturn = + { success: true; killFunc: () => void; runResult: Promise } | + { success: false; runResult: RunResult }; + +export type IRunner = + (params: T) => Promise; \ No newline at end of file diff --git a/web/Dockerfile b/web/Dockerfile index 67cb1bb..2482f81 100644 --- a/web/Dockerfile +++ b/web/Dockerfile @@ -1,6 +1,9 @@ FROM ubuntu:22.04 -WORKDIR /app +# Setup + +RUN mkdir web +WORKDIR /app/web RUN apt-get update RUN apt-get install curl -y @@ -11,9 +14,26 @@ RUN apt-get install nodejs git -y RUN git config --global user.name "Admin" RUN git config --global user.email noemail@example.com -COPY package*.json ./ +# Prep Web + +COPY ./web/package*.json ./ RUN npm install -COPY . . +COPY ./web/ . + +# Prep extensionWeb + +WORKDIR /app +RUN mkdir shared +RUN mkdir shared/extensionWeb +WORKDIR /app/shared/extensionWeb + +COPY ./shared/extensionWeb/package*.json . +RUN npm install +COPY ./shared/extensionWeb/ . + +# Env/Build/Run + +WORKDIR /app/web ENV PORT=3000 EXPOSE 3000 diff --git a/web/docker-compose.yml b/web/docker-compose.yml index 7364cc7..c68a7cd 100644 --- a/web/docker-compose.yml +++ b/web/docker-compose.yml @@ -10,7 +10,9 @@ services: - POSTGRES_DB=bwcontest restart: unless-stopped web: - build: . + build: + context: ../ + dockerfile: ./web/Dockerfile ports: - 3000:3000 - 7006:7006 diff --git a/web/docker/entry.sh b/web/docker/entry.sh index 12e9a71..0750beb 100644 --- a/web/docker/entry.sh +++ b/web/docker/entry.sh @@ -1,4 +1,5 @@ #!/bin/bash +# THIS FILE MUST USE LF LINE SEPARATORS! npx prisma db push --accept-data-loss npx prisma generate BODY_SIZE_LIMIT=Infinity INIT=true node build \ No newline at end of file diff --git a/web/src/lib/contestMonitor/contestMonitorSharedTypes.ts b/web/src/lib/contestMonitor/contestMonitorSharedTypes.ts deleted file mode 100644 index 2d6981f..0000000 --- a/web/src/lib/contestMonitor/contestMonitorSharedTypes.ts +++ /dev/null @@ -1,29 +0,0 @@ -export type FullStateForExtension = { - contestState: ContestStateForExtension; - submissions: SubmissionForExtension[]; -}; - -export type ProblemNameForExtension = { - id: number; - friendlyName: string; -}; - -export type ContestStateForExtension = { - startTime: Date | null; - endTime: Date | null; - problems: ProblemNameForExtension[]; - isActive: boolean; - isScoreboardFrozen: boolean; -}; - -export type SubmissionStateForExtension = 'Processing' | 'Correct' | 'Incorrect'; - -export type SubmissionForExtension = { - id: number; - contestId: number; - teamId: number; - problemId: number; - createdAt: Date; - state: SubmissionStateForExtension; - message: string | null; -}; diff --git a/web/src/lib/contestMonitor/contestMonitorUtils.ts b/web/src/lib/contestMonitor/contestMonitorUtils.ts index 4be6e9d..1cd0172 100644 --- a/web/src/lib/contestMonitor/contestMonitorUtils.ts +++ b/web/src/lib/contestMonitor/contestMonitorUtils.ts @@ -1,5 +1,5 @@ import type { SubmissionState } from '@prisma/client'; -import type { SubmissionStateForExtension } from './contestMonitorSharedTypes'; +import type { SubmissionStateForExtension } from '@extensionWeb/contestMonitorTypes.cjs'; export function convertSubmissionStateForExtension( state: SubmissionState diff --git a/web/src/routes/api/team/[session]/contestState/+server.ts b/web/src/routes/api/team/[session]/contestState/+server.ts index 8cfaeeb..f6ef2a5 100644 --- a/web/src/routes/api/team/[session]/contestState/+server.ts +++ b/web/src/routes/api/team/[session]/contestState/+server.ts @@ -5,7 +5,7 @@ import type { ContestStateForExtension, FullStateForExtension, SubmissionForExtension -} from '$lib/contestMonitor/contestMonitorSharedTypes'; +} from '@extensionWeb/contestMonitorTypes.cjs'; import { convertSubmissionStateForExtension } from '$lib/contestMonitor/contestMonitorUtils'; export const GET = (async ({ params }) => { diff --git a/web/src/routes/api/team/[session]/submit/+server.ts b/web/src/routes/api/team/[session]/submit/+server.ts index 4f0276f..8858243 100644 --- a/web/src/routes/api/team/[session]/submit/+server.ts +++ b/web/src/routes/api/team/[session]/submit/+server.ts @@ -3,7 +3,7 @@ import { error, json } from '@sveltejs/kit'; import type { RequestHandler } from './$types'; import { z } from 'zod'; import { SubmissionState } from '@prisma/client'; -import type { SubmissionForExtension } from '$lib/contestMonitor/contestMonitorSharedTypes'; +import type { SubmissionForExtension } from '@extensionWeb/contestMonitorTypes.cjs'; import { convertSubmissionStateForExtension } from '$lib/contestMonitor/contestMonitorUtils'; const submitPostData = z.object({ diff --git a/web/svelte.config.js b/web/svelte.config.js index e1d94e7..bb17a10 100644 --- a/web/svelte.config.js +++ b/web/svelte.config.js @@ -6,7 +6,10 @@ const config = { preprocess: vitePreprocess(), kit: { - adapter: adapter() + adapter: adapter(), + alias: { + '@extensionWeb/*': '../shared/extensionWeb/*' + } }, vitePlugin: { inspector: true diff --git a/web/tsconfig.json b/web/tsconfig.json index 6ae0c8c..61d2009 100644 --- a/web/tsconfig.json +++ b/web/tsconfig.json @@ -10,6 +10,7 @@ "sourceMap": true, "strict": true } + // Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias // // If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes