diff --git a/package-lock.json b/package-lock.json index 860c7a5..b56b738 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,6 +18,7 @@ "zod": "^3.25.76" }, "bin": { + "schulcloud": "dist/bin/cli.js", "schulcloud-mcp": "dist/bin/stdio.js" }, "devDependencies": { @@ -981,7 +982,6 @@ "resolved": "https://registry.npmjs.org/express/-/express-5.2.1.tgz", "integrity": "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==", "license": "MIT", - "peer": true, "dependencies": { "accepts": "^2.0.0", "body-parser": "^2.2.1", @@ -1269,7 +1269,6 @@ "resolved": "https://registry.npmjs.org/hono/-/hono-4.13.7.tgz", "integrity": "sha512-c8/gF9ac8Y78/agExVocyLevgR+JlpNB444Py0FSX8pJoPdYUfUzRcXtYEYGwt6l19qIlVZPN5Mfsw9jFShmQQ==", "license": "MIT", - "peer": true, "engines": { "node": ">=16.9.0" } @@ -1873,7 +1872,6 @@ "resolved": "https://registry.npmjs.org/pg/-/pg-8.23.0.tgz", "integrity": "sha512-Ip2EQCngowJLGOfCwkFhPXU7/ljlhn6Rxlmy4XYfL2Y+vyRM59+8uR2xqRWKdYmbXmxCFOAmKxBuSUCdF34qLg==", "license": "MIT", - "peer": true, "dependencies": { "pg-connection-string": "^2.14.0", "pg-pool": "^3.14.0", @@ -2637,7 +2635,6 @@ "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", "license": "MIT", - "peer": true, "funding": { "url": "https://github.com/sponsors/colinhacks" } diff --git a/package.json b/package.json index 33fa6c0..53bd0cf 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,7 @@ "start": "node dist/bin/http.js", "stdio": "node dist/bin/stdio.js", "typecheck": "tsc -p tsconfig.json --noEmit", - "test": "node --test test/*.test.ts", + "test": "node --test --experimental-strip-types test/*.test.ts", "probe": "node --env-file=.env scripts/probe.mjs", "smoke": "node --env-file=.env scripts/smoke.mjs", "session-diagnose": "node --env-file=.env scripts/session-diagnose.mjs", diff --git a/scripts/probe.mjs b/scripts/probe.mjs index b336486..51d713c 100644 --- a/scripts/probe.mjs +++ b/scripts/probe.mjs @@ -7,7 +7,7 @@ * Read-only. Usage: `node --env-file=.env scripts/probe.mjs` */ import { loadConfig } from '../dist/config.js'; -import { SchulcloudClient, SchulcloudApiError } from '../dist/schulcloud/client.js'; +import { SchulcloudClient, SchulcloudApiError } from '../dist/core/client.js'; const config = loadConfig(); const client = new SchulcloudClient(config); diff --git a/scripts/session-diagnose.mjs b/scripts/session-diagnose.mjs index 57e8a17..f06d9af 100644 --- a/scripts/session-diagnose.mjs +++ b/scripts/session-diagnose.mjs @@ -19,7 +19,7 @@ * (default 150 — enough to pass the ~2 h mark where an open tab would strike). */ import { loadConfig } from '../dist/config.js'; -import { SchulcloudClient, SchulcloudApiError } from '../dist/schulcloud/client.js'; +import { SchulcloudClient, SchulcloudApiError } from '../dist/core/client.js'; const totalMinutes = Number(process.argv[2] ?? 150); const INTERVAL_MS = 10 * 60_000; diff --git a/src/config.ts b/src/config.ts index 0d4e86a..7413c83 100644 --- a/src/config.ts +++ b/src/config.ts @@ -6,6 +6,8 @@ * DevTools stays an obvious, mechanical step — see docs/AUTH.md. */ +import { resolve } from 'node:path'; + export interface Config { /** Instance base URL, no trailing slash, e.g. `https://schulcloud-thueringen.de`. */ baseUrl: string; @@ -76,7 +78,9 @@ export function loadConfig(): Config { requestTimeoutMs: int('REQUEST_TIMEOUT_MS', 30_000), keepaliveIntervalMs: intAllowingZero('KEEPALIVE_INTERVAL_MS', 30 * 60_000), databaseUrl: process.env.DATABASE_URL?.trim() || undefined, - mirrorDir: process.env.MIRROR_DIR?.trim() || '/var/lib/schulcloud-mcp/mirror', + // Absolute: res.sendFile rejects a relative path, and resolveWithin only + // returns an absolute path if the root it is given is one. + mirrorDir: resolve(process.env.MIRROR_DIR?.trim() || '/var/lib/schulcloud-mcp/mirror'), mirrorMaxBytes: int('MIRROR_MAX_BYTES', 64 * 1024 * 1024), crawlIntervalMs: intAllowingZero('CRAWL_INTERVAL_MS', 6 * 60 * 60_000), };