Error statuses follow one rule: APIException takes a status and derives the code from it (BAD_REQUEST 400, UNAUTHORIZED 401, FORBIDDEN 403, NOT_FOUND 404, CONFLICT 409, RATE_LIMITED 429, SERVER_ERROR 500, BAD_GATEWAY 502), so a code can't contradict its status. That fixed real bugs: a wrong current password on change-password answered 401, on which authFetch signs the user out; editing or deleting someone else's comment or chat message answered 401 rather than 403; one invalid dump edit answered 422. A taken username is 409, like a taken email. Along the way: the database is created from schema.sql by connection.ts when the file doesn't exist, so every task works on a fresh checkout (dev and serve never ran db/init.ts, which is gone); the startup purge compared ISO dates with SQLite's datetime() as text and kept anything from the current UTC day, and now compares ISO cutoffs; the seeded admin's hash comes from lib/password.ts (split out of jwt.ts, which needs the JWT secret) rather than a copy of its format; avatar, thumbnail and playlist-cover uploads go through replaceUploadedFile, which writes beside the old file and renames over it before the record announces it (a failed avatar write lost the old avatar; a thumbnail was announced before it existed); upload.ts derives its size message from MAX_IMAGE_SIZE_BYTES and stops re-exporting the upload folders; ALLOWED_IMAGE_MIMES, which duplicated detectImageMime, is gone; the SPA fallback no longer calls next() after answering; a reply must answer a comment on the same dump (a foreign or unknown parent was a 500 or a cross-dump thread). 211 backend and 628 frontend tests pass. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
47 lines
2.0 KiB
JSON
47 lines
2.0 KiB
JSON
{
|
|
"tasks": {
|
|
"dev": "deno task icons public && deno run --env-file -A npm:vite & deno task server:start",
|
|
"build": "deno task i18n:extract && deno task i18n:compile && deno run --env-file -A npm:vite build",
|
|
"server:start": "deno run --env-file -A --watch api/main.ts",
|
|
"icons": "deno run --env-file -A api/scripts/generate-icons.ts",
|
|
"serve": "deno task build && deno task icons dist && deno task server:start",
|
|
"i18n:extract": "deno run -A npm:@lingui/cli extract --clean --overwrite --workers 1",
|
|
"i18n:compile": "deno run -A npm:@lingui/cli compile --workers 1",
|
|
"start": "deno task icons dist && deno run --env-file -A api/main.ts",
|
|
"test": "deno test -A api/ shared/",
|
|
"test:coverage": "deno test -A --coverage=coverage/api --clean api/ shared/",
|
|
"test:web": "deno run -A npm:vitest run",
|
|
"test:web:coverage": "deno run -A npm:vitest run --coverage",
|
|
"doc": "deno doc --html --name=gerbeur --output=docs mod.ts $(find api shared src \\( -name '*.ts' -o -name '*.tsx' \\) -not -path '*/test/*' -not -path 'src/locales/*')",
|
|
"doc:lint": "deno run --allow-run --allow-read --allow-env doc-lint.ts mod.ts $(find api shared src \\( -name '*.ts' -o -name '*.tsx' \\) -not -path '*/test/*' -not -path 'src/locales/*')"
|
|
},
|
|
"exports": "./mod.ts",
|
|
"nodeModulesDir": "auto",
|
|
"compilerOptions": {
|
|
"types": [
|
|
"react",
|
|
"react-dom",
|
|
"@types/react"
|
|
],
|
|
"lib": [
|
|
"dom",
|
|
"dom.iterable",
|
|
"deno.ns"
|
|
],
|
|
"jsx": "react-jsx",
|
|
"jsxImportSource": "react"
|
|
},
|
|
"imports": {
|
|
"@db/sqlite": "jsr:@db/sqlite@^0.13.0",
|
|
"@std/assert": "jsr:@std/assert@^1.0.19",
|
|
"@std/testing": "jsr:@std/testing@^1.0.21",
|
|
"@oak/oak": "jsr:@oak/oak@^17.2.0",
|
|
"@panva/jose": "jsr:@panva/jose@^6.2.12",
|
|
"@tajpouria/cors": "jsr:@tajpouria/cors@^1.2.1",
|
|
"nodemailer": "npm:nodemailer@^10.0.10",
|
|
"marked": "npm:marked@^18.0.14",
|
|
"@resvg/resvg-wasm": "npm:@resvg/resvg-wasm@^2.6.2"
|
|
},
|
|
"allowScripts": ["npm:@swc/core@1.16.2"]
|
|
}
|