Skip to content

chore: streamline toolchain, packaging and CI - #1

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

chore: streamline toolchain, packaging and CI#1
Maximvdw wants to merge 7 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 7 commits August 9, 2026 13:01
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
The codemod stops at the monorepo root, so the workspace children were the last
packages in the fleet still pointing `module` at `dist/esm5`, shipping no `exports`
map, and declaring unbounded `@openhps/*` peer ranges. Each child now resolves
`types` to `dist/types`, lists `types` first in every export condition, points
`import` at `dist/esm` and runs the shared `finalize-esm` pass over it, and its
peers gain an upper bound with a matching devDependency so CI builds against what
consumers resolve.

`terser-webpack-plugin` is declared at the workspace root: every child's
webpack.config.js requires it directly, and `npm ci` against a lockfile with no such
entry does not provide the hoisted copy the configs had been relying on. That is what
broke the CI build.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FtN6Tx33QW5a6AtCH1zYQh
`src/nodes/index.ts` re-exported only `./source` and `./sink`, leaving `XRHitTest`
— a public class — unreachable from `@openhps/webxr`.

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