Run the tests on Node 22.16, and fix what a fresh setup tripped over
Node 22.16 runs TypeScript only behind --experimental-strip-types (on by default from 22.18), so `npm test` failed on every file with ERR_UNKNOWN_FILE_EXTENSION. The flag is harmless on newer versions. probe and session-diagnose still imported dist/schulcloud/client.js, which the move to core/ renamed, so both scripts died at import. A relative MIRROR_DIR broke file serving: res.sendFile refuses a relative path, and resolveWithin returns an absolute path only when its root is one. The config resolves it once, at load. package-lock.json is what `npm install` records today: the `schulcloud` bin, and no stale peer flags. 101 tests. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
5
package-lock.json
generated
5
package-lock.json
generated
@@ -18,6 +18,7 @@
|
|||||||
"zod": "^3.25.76"
|
"zod": "^3.25.76"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
|
"schulcloud": "dist/bin/cli.js",
|
||||||
"schulcloud-mcp": "dist/bin/stdio.js"
|
"schulcloud-mcp": "dist/bin/stdio.js"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
@@ -981,7 +982,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/express/-/express-5.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/express/-/express-5.2.1.tgz",
|
||||||
"integrity": "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==",
|
"integrity": "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"accepts": "^2.0.0",
|
"accepts": "^2.0.0",
|
||||||
"body-parser": "^2.2.1",
|
"body-parser": "^2.2.1",
|
||||||
@@ -1269,7 +1269,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/hono/-/hono-4.13.7.tgz",
|
"resolved": "https://registry.npmjs.org/hono/-/hono-4.13.7.tgz",
|
||||||
"integrity": "sha512-c8/gF9ac8Y78/agExVocyLevgR+JlpNB444Py0FSX8pJoPdYUfUzRcXtYEYGwt6l19qIlVZPN5Mfsw9jFShmQQ==",
|
"integrity": "sha512-c8/gF9ac8Y78/agExVocyLevgR+JlpNB444Py0FSX8pJoPdYUfUzRcXtYEYGwt6l19qIlVZPN5Mfsw9jFShmQQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=16.9.0"
|
"node": ">=16.9.0"
|
||||||
}
|
}
|
||||||
@@ -1873,7 +1872,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/pg/-/pg-8.23.0.tgz",
|
"resolved": "https://registry.npmjs.org/pg/-/pg-8.23.0.tgz",
|
||||||
"integrity": "sha512-Ip2EQCngowJLGOfCwkFhPXU7/ljlhn6Rxlmy4XYfL2Y+vyRM59+8uR2xqRWKdYmbXmxCFOAmKxBuSUCdF34qLg==",
|
"integrity": "sha512-Ip2EQCngowJLGOfCwkFhPXU7/ljlhn6Rxlmy4XYfL2Y+vyRM59+8uR2xqRWKdYmbXmxCFOAmKxBuSUCdF34qLg==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"pg-connection-string": "^2.14.0",
|
"pg-connection-string": "^2.14.0",
|
||||||
"pg-pool": "^3.14.0",
|
"pg-pool": "^3.14.0",
|
||||||
@@ -2637,7 +2635,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz",
|
"resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz",
|
||||||
"integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==",
|
"integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"funding": {
|
"funding": {
|
||||||
"url": "https://github.com/sponsors/colinhacks"
|
"url": "https://github.com/sponsors/colinhacks"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
"start": "node dist/bin/http.js",
|
"start": "node dist/bin/http.js",
|
||||||
"stdio": "node dist/bin/stdio.js",
|
"stdio": "node dist/bin/stdio.js",
|
||||||
"typecheck": "tsc -p tsconfig.json --noEmit",
|
"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",
|
"probe": "node --env-file=.env scripts/probe.mjs",
|
||||||
"smoke": "node --env-file=.env scripts/smoke.mjs",
|
"smoke": "node --env-file=.env scripts/smoke.mjs",
|
||||||
"session-diagnose": "node --env-file=.env scripts/session-diagnose.mjs",
|
"session-diagnose": "node --env-file=.env scripts/session-diagnose.mjs",
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
* Read-only. Usage: `node --env-file=.env scripts/probe.mjs`
|
* Read-only. Usage: `node --env-file=.env scripts/probe.mjs`
|
||||||
*/
|
*/
|
||||||
import { loadConfig } from '../dist/config.js';
|
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 config = loadConfig();
|
||||||
const client = new SchulcloudClient(config);
|
const client = new SchulcloudClient(config);
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
* (default 150 — enough to pass the ~2 h mark where an open tab would strike).
|
* (default 150 — enough to pass the ~2 h mark where an open tab would strike).
|
||||||
*/
|
*/
|
||||||
import { loadConfig } from '../dist/config.js';
|
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 totalMinutes = Number(process.argv[2] ?? 150);
|
||||||
const INTERVAL_MS = 10 * 60_000;
|
const INTERVAL_MS = 10 * 60_000;
|
||||||
|
|||||||
@@ -6,6 +6,8 @@
|
|||||||
* DevTools stays an obvious, mechanical step — see docs/AUTH.md.
|
* DevTools stays an obvious, mechanical step — see docs/AUTH.md.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { resolve } from 'node:path';
|
||||||
|
|
||||||
export interface Config {
|
export interface Config {
|
||||||
/** Instance base URL, no trailing slash, e.g. `https://schulcloud-thueringen.de`. */
|
/** Instance base URL, no trailing slash, e.g. `https://schulcloud-thueringen.de`. */
|
||||||
baseUrl: string;
|
baseUrl: string;
|
||||||
@@ -76,7 +78,9 @@ export function loadConfig(): Config {
|
|||||||
requestTimeoutMs: int('REQUEST_TIMEOUT_MS', 30_000),
|
requestTimeoutMs: int('REQUEST_TIMEOUT_MS', 30_000),
|
||||||
keepaliveIntervalMs: intAllowingZero('KEEPALIVE_INTERVAL_MS', 30 * 60_000),
|
keepaliveIntervalMs: intAllowingZero('KEEPALIVE_INTERVAL_MS', 30 * 60_000),
|
||||||
databaseUrl: process.env.DATABASE_URL?.trim() || undefined,
|
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),
|
mirrorMaxBytes: int('MIRROR_MAX_BYTES', 64 * 1024 * 1024),
|
||||||
crawlIntervalMs: intAllowingZero('CRAWL_INTERVAL_MS', 6 * 60 * 60_000),
|
crawlIntervalMs: intAllowingZero('CRAWL_INTERVAL_MS', 6 * 60 * 60_000),
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user