diff --git a/CLAUDE.md b/CLAUDE.md index ac39d32d..24b0eb85 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -38,6 +38,14 @@ is how a formatting failure reached CI. - **Lint and dead-code counts** are ratcheted: they may go down, never up. So are the services' loose values (`tools/loose-baseline.json`, at zero), and `tools/tsconfig.json` has `noImplicitAny` on: new service code is typed. +- **New code under `tools/` is TypeScript** (spec 013). A plain `.mjs` there would + be loaded by the type check without being checked, so `tools/load.spec.ts` + fails on one. +- **A service's new entry point is loaded under Node** by `tools/load.spec.ts`. + A module at the top of a service directory is picked up as it is (one in a + subdirectory only through whatever imports it); a new service directory joins + its `SERVICES` list; and a script that does its work when loaded (writes files, + starts a browser) joins `RUN_ON_LOAD`, so it is checked without being run. ## The node content service (`tools/content-node`) diff --git a/specs/013-server-types/tasks.md b/specs/013-server-types/tasks.md index d309fe9b..14a07ad4 100644 --- a/specs/013-server-types/tasks.md +++ b/specs/013-server-types/tasks.md @@ -75,7 +75,7 @@ Each task: rename to `.ts`, update imports, file names that name it (R3 list), f Measured 23 Oct with `checkJs` on: 1,229 errors in 47 `.mjs` files, 70 of them in the five tools and 1,159 in 42 specs. The tools are converted, typed, held at zero both counts, and still run as before (parity and the library guard directly under Node, the harness through its new `playwright.config.ts`, which also mends the README's command: it had found no tests since the harness stopped being called a spec) — #643. The specs go next, in batches: the ten check specs outside the content service (load, started, workflows, check-move, check-baseline-totals, the HAR, flaky and lint checks, and content-node's hermetic), 60 errors — #644. The content service's ten smallest (exporter, cache-headers, molecule-details-bound, component-of, diseases, participating-entities, interactors, query-ids, map-results, mapping), 139 — #645. The next eight (pathways-low, complexes, overview-export, schema-objects, orthology, query-attribute-endpoint, interactors-static, referrers), 183 — #647. Seven more (contained-events, pathways-of, flag, query-attribute, discover, diagram-search, references-mapping), 235 — #649. icon, facet-query and the Java parity spec, 151 — #650. query-search and species-search, 151 — #651. search and service, the last two, with the library-update spec, 252 — #652. No `.mjs` is left in `tools/`, and `tools/load.spec.ts` fails if one is added, so a new module is TypeScript and checked. T023 is complete. -- [ ] T024 `CLAUDE.md`: the rule for new service code (typed, and a load test entry for a new entry point) if one emerges. +- [x] T024 `CLAUDE.md`: the rule for new service code (typed, and a load test entry for a new entry point) if one emerges. Both emerged: new code under `tools/` is TypeScript, held by `tools/load.spec.ts`; and a new entry point is loaded under Node by the same spec, a new service directory joining `SERVICES` and a script that works when loaded joining `RUN_ON_LOAD`. Also from T023's review: the no-plain-JavaScript check matches any case and `.jsx`, and excludes only the one generated bundle; three comments name the `.ts` specs. — #653 --- diff --git a/tools/content-node/body.ts b/tools/content-node/body.ts index ef67fd3c..a303f82a 100644 --- a/tools/content-node/body.ts +++ b/tools/content-node/body.ts @@ -101,7 +101,7 @@ const JAVA_DECODERS = new Map( /** * How to read a body in a charset named in a Content-Type, lower-cased, or * undefined for one this cannot read -- Spring's 415. Latin-1, ASCII and the - * UTF family are read as the JDK reads them (orthology.spec.mjs holds the + * UTF family are read as the JDK reads them (orthology.spec.ts holds the * JDK's answers); any other charset by TextDecoder when it knows the name, * which for a body of stable ids reads the same. A charset only Java knows * (an EBCDIC code page) is refused here and read by Java. diff --git a/tools/content-node/exporters-endpoints.ts b/tools/content-node/exporters-endpoints.ts index 20525cfc..a4d821b0 100644 --- a/tools/content-node/exporters-endpoints.ts +++ b/tools/content-node/exporters-endpoints.ts @@ -406,7 +406,7 @@ export const exportersEndpoints: Endpoint[] = [ { path: '/ContentService/exporter/voronoi/{id}', // No sample, and none from --ids: Java has no such URL, so the parity - // harness has nothing to compare it with. overview-export.spec.mjs holds it. + // harness has nothing to compare it with. overview-export.spec.ts holds it. samplesOnly: true, /** * A species' overview, the Voronoi map the site shows (Reacfoam), drawn diff --git a/tools/content-node/java-hashmap.ts b/tools/content-node/java-hashmap.ts index 81d22931..e5511fed 100644 --- a/tools/content-node/java-hashmap.ts +++ b/tools/content-node/java-hashmap.ts @@ -8,7 +8,7 @@ * red-black tree ordered by hash then String.compareTo, whose root is moved * to the front and whose later keys are linked in after their parent -- so * eleven ids sharing a hash come out in Java's order, not arrival's. Checked - * against the JDK's own HashMap (orthology.spec.mjs). + * against the JDK's own HashMap (orthology.spec.ts). */ /** * One key in a bucket. A bucket that becomes a tree gives its nodes the tree diff --git a/tools/load.spec.ts b/tools/load.spec.ts index 90da04bc..f2d4f1b1 100644 --- a/tools/load.spec.ts +++ b/tools/load.spec.ts @@ -87,10 +87,10 @@ function loadUnderNode(files: string[]): string[] { */ it('holds no plain JavaScript module in tools/', () => { const plain = readdirSync(path.join(ROOT, 'tools'), { recursive: true, encoding: 'utf8' }) - .filter((file) => /\.(mjs|cjs|js)$/.test(file)) + .filter((file) => /\.(mjs|cjs|jsx?)$/i.test(file)) .filter((file) => !file.split(path.sep).includes('node_modules')) - // Generated by esbuild from harness.ts, and gitignored. - .filter((file) => !file.endsWith('harness.bundle.js')); + // Generated by esbuild from harness.ts, and gitignored: that one file only. + .filter((file) => file !== path.join('svg-export-harness', 'harness.bundle.js')); expect(plain).toEqual([]); });