Skip to content

chore: streamline toolchain, packaging and CI - #1

Open
Maximvdw wants to merge 8 commits into
mainfrom
chore/streamline
Open

chore: streamline toolchain, packaging and CI#1
Maximvdw wants to merge 8 commits into
mainfrom
chore/streamline

Conversation

@Maximvdw

@Maximvdw Maximvdw commented Aug 9, 2026

Copy link
Copy Markdown
Member

Brings this module onto the shared OpenHPS toolchain baseline, applied by the openhps-devtools codemod so every repository lands the same shape.

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, with npm ci in CI instead of the bare npm install/yarn install that silently rewrote lockfiles.

Packaging: types resolves to dist/types, the exports map lists types first in every condition and points import at dist/esm, and the redundant esm5 target is gone — its tsconfig used target es6 while the esm one used es2015, the same TypeScript alias. tslib is now declared, since the tsconfig sets both importHelpers and noEmitHelpers, a combination that always emits an import of it.

scripts/finalize-esm.mjs makes dist/esm genuinely loadable as ES modules: it writes the per-directory type markers — without which both Node and webpack parse the output as CommonJS and fail on the first import — and rewrites TypeScript's directory imports to the explicit file paths Node's ESM resolver requires.

Dependency policy: @openhps/* peer ranges gain an upper bound (>=1.0.16 <2") and every declared peer has a matching devDependency, so CI tests what consumers receive. scripts/check-peers.mjs` enforces both as part of lint.

CI: replaces a hand-forked main.yml with a thin caller onto OpenHPS/workflows. The fleet had 24 distinct variants of that file. Every job now installs its own dependency tree rather than depending on an actions/cache hit for node_modules, lint no longer waits on build, and the matrix covers Node 22 and 24.

Coverage moves from nyc to c8: nyc 18's spawn-wrap breaks down on Node 22, running the tests while reporting 0 passing and 0% coverage.

The ESM smoke test still resolves @openhps/core from the registry, where 1.0.16 ships the old dist/esm5 with directory imports. It passes against a locally built core and will pass here once core is released.

🤖 Generated with Claude Code

https://claude.ai/code/session_01FtN6Tx33QW5a6AtCH1zYQh

Maximvdw and others added 8 commits August 9, 2026 16:29
npm is the package manager fleet-wide. Every CI workflow previously ran a bare
`yarn install` or `npm install` rather than a frozen install, so lockfiles
silently churned in CI. Yarn 1.22 is unmaintained; npm ships with Node 22 and 24,
supports `overrides` for transitive CVE pinning, and can publish with
`--provenance`.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FtN6Tx33QW5a6AtCH1zYQh
tsconfig.bundle.esm5.json used target "es6" while tsconfig.bundle.esm.json used
"es2015" -- the same TypeScript alias, with the same module: es2020 -- so the
esm5 output was pure duplication, and exports.import pointed at it while dist/esm
went unreachable.

scripts/finalize-esm.mjs now post-processes dist/esm so it is genuinely loadable as
ES modules: it writes the per-directory "type" markers (without which both Node
and webpack read the output as CommonJS and fail on the first import statement) and
rewrites TypeScript's directory imports to explicit file paths, which Node's ESM
resolver requires.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FtN6Tx33QW5a6AtCH1zYQh
Replaces a hand-forked main.yml with a thin caller. The fleet had 24 distinct
variants of that file, Node was unpinned in 22 repositories, and 13 ran
`npm install` rather than `npm ci`.

Every job now installs its own dependency tree instead of depending on an
actions/cache hit for node_modules, lint no longer waits on build, and the matrix
covers Node 22 and 24. dependabot.yml and the auto-merge workflow arrive here for
the first time outside openhps-core.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FtN6Tx33QW5a6AtCH1zYQh
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.

Packaging is brought onto the fleet contract: `types` resolves to dist/types
rather than dist/cjs, the exports map lists `types` first in every condition and
points `import` at dist/esm, and tslib is declared -- the tsconfig sets both
importHelpers and noEmitHelpers, a combination that always emits an import of
tslib, which previously resolved only by hoisting.

@openhps/* peer ranges gain an upper bound (">=1.0.16 <2"), and every declared
peer now has a matching devDependency so CI tests what consumers receive;
scripts/check-peers.mjs enforces both as part of lint.

Coverage moves from nyc to c8: nyc 18's spawn-wrap breaks down on Node 22, running
the tests but reporting 0 passing and 0% coverage. cover:ci also 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.

standard-version is replaced by commit-and-tag-version (unmaintained since 2023),
and eslint-plugin-deprecation by @typescript-eslint/no-deprecated (archived).
CONTRIBUTING.md and SECURITY.md move to the org-wide OpenHPS/.github repository.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FtN6Tx33QW5a6AtCH1zYQh
Formatting only. The lint script was `eslint src/**`, so test/ had never been seen
by prettier; widening it to `eslint .` surfaced hundreds of formatting-only
findings. Kept separate so the toolchain diff stays reviewable.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FtN6Tx33QW5a6AtCH1zYQh
This scaffold is where the fleet's divergence came from. It generated new modules with
`types` pointing into `dist/cjs`, a flat `exports` map with no subpath keys,
`engines.node >=12`, `lint: eslint src/**`, an .eslintrc.js, a .gitconfig, a
Jenkinsfile, husky 4's package.json hook block, webpack 4, jenkins-mocha,
standard-version and nyc — so every module created from it started life off the shared
contract and drifted further from there.

It now emits exactly what the codemod produces for an existing module: the shared
tsconfig set, the eslint 9 flat config, .husky with lint-staged, .c8rc.json, the
mocha and multi-reporter configs, scripts/check-peers.mjs and scripts/finalize-esm.mjs,
dependabot.yml, and a ci.yml calling OpenHPS/workflows. package.json carries the
packaging contract — types resolving to dist/types, types first in every export
condition, import pointing at dist/esm, tslib declared, bounded @OpenHPS peer ranges
with matching devDependencies — and the toolchain versions come from the same policy
the codemod reads.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FtN6Tx33QW5a6AtCH1zYQh
The repository had no tests at all. These are the guard that stops the scaffold
re-seeding the drift the fleet just spent a migration undoing: they check the contract
— entry points, exports ordering, bounded peers, retired tooling absent, the shared
config files present — rather than exact dependency versions, which dependabot moves
and which are not what breaks generated packages.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FtN6Tx33QW5a6AtCH1zYQh
This is an executable, not a library surface: there is no docs/typedoc.json and no
`build:typedoc` script, so the Documentation job failed on a missing script.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FtN6Tx33QW5a6AtCH1zYQh
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