From a3c265e5ba991a87117cf75de043eab6a4d6d8c8 Mon Sep 17 00:00:00 2001 From: Ben Balter Date: Sun, 27 Sep 2026 10:08:29 -0400 Subject: [PATCH] Type-check script/, worker/, e2e/, and tool configs tsconfig.astro.json only covers src/ and astro.config.mjs, so astro check never saw script/**/*.ts, worker/*.js, e2e/, vitest.config.ts, or playwright.config.ts. Add tsconfig.tooling.json (named so Astro and Vite don't pick it up as a root tsconfig.json), an npm run check:tooling script, and wire it into npm test and the CI check job. Fix the 7 errors it surfaced (all type noise, no runtime changes): - e2e/link-validation.spec.ts: drop unused fs/path imports - sync-document.ts: DocumentRecord as a type alias so it satisfies putRecord's index-signature record param - worker/index.test.js: JSDoc types for test helpers; ASSETS.fetch mock accepts RequestInfo | URL to match the binding's fetch signature Also drop the stale _site exclude from tsconfig.astro.json. Co-Authored-By: Claude Opus 5.5 --- .github/workflows/ci.yml | 4 ++++ e2e/link-validation.spec.ts | 2 -- package.json | 3 ++- script/standard-site/sync-document.ts | 4 ++-- tsconfig.astro.json | 3 +-- tsconfig.tooling.json | 27 +++++++++++++++++++++++++++ worker/index.test.js | 13 ++++++++----- 7 files changed, 44 insertions(+), 12 deletions(-) create mode 100644 tsconfig.tooling.json diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 61f0f2706..1009f43b0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -215,6 +215,10 @@ jobs: - name: Run Astro Check run: npm run check + # scripts, worker, e2e, and tool configs sit outside tsconfig.astro.json. + - name: Type-check tooling (script/, worker/, e2e/) + run: npm run check:tooling + vitest: name: Run Vitest Tests runs-on: ubuntu-latest diff --git a/e2e/link-validation.spec.ts b/e2e/link-validation.spec.ts index 5f4904e9b..efd2efe1d 100644 --- a/e2e/link-validation.spec.ts +++ b/e2e/link-validation.spec.ts @@ -1,6 +1,4 @@ import { test, expect, type APIRequestContext } from '@playwright/test'; -import fs from 'fs'; -import path from 'path'; /** * Link Validation Tests diff --git a/package.json b/package.json index 7fd47972f..eb20a805b 100644 --- a/package.json +++ b/package.json @@ -134,6 +134,7 @@ "dev": "astro dev", "preview": "astro preview", "check": "astro check --tsconfig tsconfig.astro.json", + "check:tooling": "tsc -p tsconfig.tooling.json", "validate-seo": "tsx script/validate-seo.ts", "check-content-integrity": "tsx script/check-content-integrity.ts", "vale-ai-tells": "vale --config=.vale-ai-tells.ini", @@ -153,7 +154,7 @@ "lint-yaml": "yamllint -c .yamllint.yml .github/workflows/ src/data/*.yml .yamllint.yml .markdown-lint.yml", "lint-html": "html-validate \"dist-astro/**/*.html\"", "super-linter": "script/super-linter", - "test": "npm run check && npm run lint-check && npm run test:vitest", + "test": "npm run check && npm run check:tooling && npm run lint-check && npm run test:vitest", "test:e2e": "playwright test", "test:e2e:accessibility": "playwright test e2e/accessibility-astro.spec.ts", "test:e2e:performance": "playwright test e2e/performance-astro.spec.ts", diff --git a/script/standard-site/sync-document.ts b/script/standard-site/sync-document.ts index 00727edd6..15c170ca4 100644 --- a/script/standard-site/sync-document.ts +++ b/script/standard-site/sync-document.ts @@ -64,7 +64,7 @@ function stripMarkdown(markdown: string): string { .trim(); } -interface DocumentRecord { +type DocumentRecord = { $type: 'site.standard.document'; site: string; title: string; @@ -73,7 +73,7 @@ interface DocumentRecord { description?: string; tags?: string[]; textContent?: string; -} +}; function buildRecord(postId: string, pubDate: Date, data: Record, body: string): DocumentRecord { const record: DocumentRecord = { diff --git a/tsconfig.astro.json b/tsconfig.astro.json index 2db2dbbc0..86e637f74 100644 --- a/tsconfig.astro.json +++ b/tsconfig.astro.json @@ -25,7 +25,6 @@ ], "exclude": [ "node_modules", - "dist-astro", - "_site" + "dist-astro" ] } diff --git a/tsconfig.tooling.json b/tsconfig.tooling.json new file mode 100644 index 000000000..e76ea3f3a --- /dev/null +++ b/tsconfig.tooling.json @@ -0,0 +1,27 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "ESNext", + "moduleResolution": "bundler", + "lib": ["ES2023", "DOM", "DOM.Iterable"], + "types": ["node"], + "resolveJsonModule": true, + "allowJs": true, + "checkJs": true, + "strict": true, + "skipLibCheck": true, + "noEmit": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noImplicitReturns": true, + "isolatedModules": true, + "esModuleInterop": true + }, + "include": [ + "script/**/*.ts", + "worker/**/*.js", + "e2e/**/*.ts", + "vitest.config.ts", + "playwright.config.ts" + ] +} diff --git a/worker/index.test.js b/worker/index.test.js index 35744a08f..55d4e8943 100644 --- a/worker/index.test.js +++ b/worker/index.test.js @@ -2,13 +2,16 @@ import { describe, it, expect, vi } from 'vitest'; import worker from './index.js'; -/** Fake ASSETS binding serving a fixed map of pathname -> body. */ +/** + * Fake ASSETS binding serving a fixed map of pathname -> body. + * @param {Record} [files] + */ function makeEnv(files = {}) { const writeDataPoint = vi.fn(); return { ASSETS: { - fetch: vi.fn(async (request) => { - const { pathname } = new URL(request.url); + fetch: vi.fn(async (/** @type {RequestInfo | URL} */ input) => { + const { pathname } = new URL(input instanceof Request ? input.url : input); return pathname in files ? new Response(files[pathname], { status: 200, headers: { 'Content-Type': 'text/html', 'Content-Security-Policy': "default-src 'self'" } }) : new Response('Not found', { status: 404 }); @@ -18,7 +21,7 @@ function makeEnv(files = {}) { }; } -const md = (path, init = {}) => +const md = (/** @type {string} */ path, /** @type {RequestInit} */ init = {}) => new Request(`https://ben.balter.com${path}`, { ...init, headers: { Accept: 'text/markdown', ...(init.headers ?? {}) }, @@ -85,7 +88,7 @@ describe('Markdown content negotiation', () => { }); describe('POST /api/event', () => { - const post = (body) => + const post = (/** @type {unknown} */ body) => new Request('https://ben.balter.com/api/event', { method: 'POST', body: typeof body === 'string' ? body : JSON.stringify(body),