Skip to content

chore: streamline toolchain, packaging and CI - #318

Open
Maximvdw wants to merge 4 commits into
masterfrom
chore/streamline
Open

chore: streamline toolchain, packaging and CI#318
Maximvdw wants to merge 4 commits into
masterfrom
chore/streamline

Conversation

@Maximvdw

@Maximvdw Maximvdw commented Aug 8, 2026

Copy link
Copy Markdown
Member

Brings @openhps/core onto the shared OpenHPS toolchain baseline and fixes several packaging defects that were shipping.

Toolchain

TypeScript 5.9, ESLint 9 with a native flat config, typescript-eslint 8, prettier 3, mocha 11, chai 6, c8, typedoc 0.28, @types/node 24, engines.node >=22. npm replaces yarn fleet-wide.

TypeScript 7 and ESLint 10 are deliberately not adopted: typedoc 0.28 peers typescript 5.0-6.0, typescript-eslint 8 peers <6.1, and eslint-plugin-import@2.32 peers eslint <=9.

Packaging defects fixed

  • exports.import pointed at dist/esm5, leaving the modern dist/esm output unreachable to every consumer. The esm5 target was pure duplication: its tsconfig used target es6 while the esm one used es2015 — the same TypeScript alias, with the same module: es2020.
  • dist/esm had never been loadable by Node as ESM. Three causes, all needing to be fixed together: no type marker (Node read it as CommonJS), TypeScript-emitted directory imports (export * from './graph'ERR_UNSUPPORTED_DIR_IMPORT), and typedjson deep imports rewritten to a lib/esm path that cannot be loaded from an ES module at all — typedjson declares no "type": "module" and its ESM build uses extensionless internal imports. Its CommonJS build can be loaded, so the specifiers now keep pointing there and only gain the extension Node requires.
  • tslib was undeclared despite the tsconfig setting both importHelpers and noEmitHelpers, a combination that always emits import ... from "tslib". It resolved only by hoisting.
  • The files array shipped all three internal.* root shims but none of the lite.* ones, so @openhps/core/lite resolved to nothing from a published tarball.
  • shelljs was required by scripts/build.three.js but declared nowhere — one dependency-tree change away from breaking npm run build at its very first step. That script is now written on node:fs.
  • @types/three was 12 minors behind the three it describes, and build.three.js copies the types over the vendored sources, so the drift was baked into dist/types/three. Aligning them required switching Matrix{3,4}.elements to the fixed-length tuple types and dropping a dead Matrix re-export.
  • Circular, unused devDependencies on @openhps/geospatial and @openhps/video put two copies of core — with two reflect-metadata decorator registries — into core's own test tree.
  • lodash.clonedeep was loaded with a bare require in a file re-exported through the public barrel, which tsc leaves intact in ESM output: a ReferenceError for any native-ESM consumer. Replaced by an internal deep clone. structuredClone is not a substitute, since the serialization layer clones typedjson metadata holding constructor references and function hooks.

Testing and CI

  • Coverage moves from nyc to c8. nyc 18's spawn-wrap breaks down on Node 22: the tests visibly run while the parent process reports 0 passing and 0% (0/1 statements). Real measured figures are 85.8% statements, 85.97% branches, 73.75% functions, and thresholds are set from those rather than the previous 50/50/50/50, which was never enforceable.
  • cover:ci now writes a real test-results.xml. reporterEnabled had been sitting at the top level of .mocharc.json where mocha ignores it, so the JUnit file CI consumed had never been produced.
  • CI adopts the OpenHPS/workflows reusable workflow: Node 22 and 24 instead of EOL Node 18, every job installs its own dependency tree rather than depending on an actions/cache hit for node_modules, and lint no longer waits on build (it previously ran type-aware rules with src/three absent).
  • paper.yml filtered on './docs/paper/**'. GitHub path patterns are repository-root-relative and reject a leading ./, so those triggers had never once fired.

Supersedes #314, which could not be reopened after the OpenHPS/workflows repository was made public.

Verified locally

345 tests passing, lint clean (0 errors), publint no errors, all four bundle budgets met, and both require() and import() resolving 172 exports.

🤖 Generated with Claude Code

https://claude.ai/code/session_01FtN6Tx33QW5a6AtCH1zYQh

Maximvdw and others added 3 commits August 9, 2026 12:39
The build badge pointed at main.yml, which the reusable-workflow migration removed,
so it rendered as "no status". The TypeScript badge still advertised 4.0+ while the
package has been building with 5.x for some time; it now matches the 5.9 baseline.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FtN6Tx33QW5a6AtCH1zYQh
CI caught a regression this change introduced: declaring "type": "commonjs" makes
size-limit's webpack parse dist/web/openhps-core.es.min.js as CommonJS and fail
with "'import' and 'export' may appear only with sourceType: module". The local
run predated the type field, so only CI saw it.

Re-bundling an already-bundled artifact through webpack measures the wrong thing
anyway. @size-limit/file reports the compressed size of the emitted file, which is
what a budget on a published bundle should mean, and it has no parser to confuse.

Budgets are set from the measured brotli sizes with roughly 10% headroom. The
worker figure drops from 85 KB to 18 KB purely because the metric changed: webpack
was measuring the bundle plus its dependencies rather than the emitted file.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FtN6Tx33QW5a6AtCH1zYQh
`import/no-cycle` becomes a warning: it only started matching anything once the
TypeScript resolver was actually loaded, so pre-existing cycles must not block the
toolchain migration. `import/namespace` is off — it cannot validate computed access
into a namespace import and is one of the slowest rules in the set. The file globs
widen to `**/*.ts` so nested sources are covered, and CONTRIBUTING.md now points at
the org-level copy in OpenHPS/.github.
…rage

typedoc 0.28 removed the `media` option, so `build:typedoc` aborted with
`Unknown option 'media'`. The four coverage thresholds were carried over from the
nyc config and never re-derived; c8 measures 70.34% statements, 77.74% branches and
63.76% functions, so they are set just below those. They ratchet upwards only.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant