Skip to content

Monorepo restructuring: standalone build, aligned dependencies, dist + source exports - #2

Merged
mkotelnikov merged 12 commits into
mainfrom
migration/monorepo-restructuring
Oct 4, 2026
Merged

mkotelnikov merged 12 commits into
mainfrom
migration/monorepo-restructuring

Conversation

@mkotelnikov

Copy link
Copy Markdown
Contributor

Part of the statewalker monorepo restructuring (layer 0). Each repository now builds, typechecks and tests on its own, with every @statewalker dependency taken from npm.

What changes

  • Internal references are workspace:^; external dependencies go through the pnpm catalog and are aligned on their latest versions across all statewalker repos (TypeScript 7, vitest 5, tsdown 0.23).
  • Public packages publish built dist with a source export condition pointing at the TypeScript source.
  • biome.json is a root config again. With "root": false biome ignored the file in a standalone checkout, which is why lint:check has failed on main.

Commits

  • build: reference convention (root turbo and changesets via catalog)
  • build: internal references as workspace:^
  • build: external dependencies at the latest version of their current line
  • build: vitest 5 and jsdom 30.1 (dependency wave 1)
  • build: tsdown 0.23 with TypeScript 7 (dependency wave 2)
  • build: dependency wave 3 (tooling and types majors)
  • chore(release): statewalker-shared, local release round
  • build: publish dist with a source condition (decision 1)
  • chore(release): statewalker-shared, local release round
  • chore(biome): make biome.json the root config, so lint runs standalone

Release order

The new versions are published to npm from this branch (next tag, install verified, then promoted to latest) before this PR is merged. When it is merged, the changesets release job finds every version already on npm and publishes nothing.

🤖 Generated with Claude Code

https://claude.ai/code/session_01DAiZN6XrTAdQpNN3eXEz2U

mkotelnikov and others added 12 commits October 3, 2026 13:35
- comply.py --prefer-catalog: @changesets/cli via catalog (^2.30.0);
  root turbo adopts the catalog value ^2.9.6 -> ^2.10.9
- prunecatalog.py: drop unused @vitest/coverage-v8

Verified against 2683c51: typecheck identical (0/9 red), tests 202 -> 202.
workspace:* publishes an exact version of a sibling package ("0.2.0");
workspace:^ links the local package the same way during development and
publishes a range ("^0.2.0"), so consumers can take compatible patches.
Wave 0 of the dependency update (tools/align.mjs): every external catalog entry
becomes ^<latest on npm within its breaking line>, the same value in every
statewalker repo. No breaking line is crossed (those are separate waves); peer
ranges, prerelease pins and documented exact pins are unchanged.
vitest, @vitest/* -> ^5.0.3; jsdom -> ^30.1.1, the same in every statewalker repo.
The jsdom 30.0.1 pin is gone: the mime.view.* failure under jsdom 30.1 came from
vitest 4's jsdom environment (its URL.createObjectURL read jsdom's internal
Blob._buffer, renamed in jsdom 30.1); vitest 5 reads the new field. Peer ranges
widened, not replaced (vitest "^4.x || ^5.0.3"), so published packages keep
accepting existing consumers.
tsdown ^0.23.0 (peer typescript "^5 || ^6 || ^7"), the same in every statewalker
repo; typescript ^7.0.2. tsdown 0.21 fails to build declarations with
TypeScript 7 (rolldown-plugin-dts), 0.22 / 0.23 do not.
Latest major, the same in every statewalker repo, where this repo uses it:
@changesets/cli ^3.0.3 (the existing .changeset/config.json works unchanged),
testcontainers ^12.2.0, @hono/node-server ^2.1.3, @types/node ^26.6.4,
@testing-library/jest-dom ^7.0.1 (6.10.0, which wave 0 had picked, is deprecated
by its maintainer as a breaking minor; 7 is the upgrade they recommend).
Versions from tools/releaseplan.mjs: minor on 0.x where a runtime or peer
dependency moved to another breaking line, patch where only the published
manifest changed (internal ranges ^x.y.z, dependency updates).
- @statewalker/shared-commands 0.2.2
- @statewalker/shared-logger-pino 0.1.2
- @statewalker/shared-logger 0.1.2
Every public package now exports built JavaScript and declarations
from dist, with a "source" condition pointing at the TypeScript file:
  { "source": "./src/x.ts", "types": "./dist/x.d.ts",
    "import": "./dist/x.js", "default": "./dist/x.js" }
Packages that exported raw source get an unbundled tsdown build (one
entry per exported module). src stays in "files" for the source
condition. CSS exports are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DAiZN6XrTAdQpNN3eXEz2U
Versions from tools/releaseplan.mjs: minor on 0.x where a runtime or peer
dependency moved to another breaking line, patch where only the published
manifest changed (internal ranges ^x.y.z, dependency updates).
- @statewalker/shared-adapters 0.1.2
- @statewalker/shared-baseclass 0.1.2
- @statewalker/shared-commands 0.2.3
- @statewalker/shared-generators 0.1.2
- @statewalker/shared-ids 0.1.2
- @statewalker/shared-logger-pino 0.1.3
- @statewalker/shared-logger 0.1.3
- @statewalker/shared-registry 0.1.2
- @statewalker/shared-slots 0.2.2

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DAiZN6XrTAdQpNN3eXEz2U
"root": false marked this config as nested under the umbrella workspace.
In a standalone checkout (CI, or a clone of this repo alone) biome then
found no root configuration and ignored the file: it formatted with its
defaults (tabs) and checked dist/, so lint:check failed on every file.
That is why CI on main has been red.

The config is now a root config, migrated to the installed biome, and
biome's safe fixes are applied (formatting, import order). Tools running
biome from the umbrella root should pass --config-path for each repo.
Remaining errors were fixed by hand (button types and a placeholder link
in demo pages, labels without controls, unsafe optional chaining in tests).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DAiZN6XrTAdQpNN3eXEz2U
Packages export their types from dist with a "source" condition, so a
package's types for its siblings are the built dist/*.d.ts. Typecheck
therefore needs the build first, the order the standalone check uses.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DAiZN6XrTAdQpNN3eXEz2U
TypeScript 7, tsdown 0.23 and vitest 5 need a newer Node than 20: tsdown
loads tsdown.config.ts with Node's type stripping, and the toolchain
uses Promise.withResolvers. Everything was verified locally on Node 24,
the version statewalker-sandbox's CI already uses.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DAiZN6XrTAdQpNN3eXEz2U
@mkotelnikov
mkotelnikov merged commit 68c33ac into main Oct 4, 2026
1 check passed
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