Skip to content

Sync JavaScript packages alongside Python and Rust members - #30

Draft
ncoop57 wants to merge 4 commits into
mainfrom
js-workspace
Draft

Sync JavaScript packages alongside Python and Rust members#30
ncoop57 wants to merge 4 commits into
mainfrom
js-workspace

Conversation

@ncoop57

@ncoop57 ncoop57 commented Sep 5, 2026

Copy link
Copy Markdown
Contributor

Draft until Nathan has reviewed it.

ws-sync now brings JavaScript packages into the workspace the way it brings in Python projects and Rust crates.

Discovery

  • A package.json in a workspace repo dir makes that dir a member (felt/package.json).
  • An immediate subdirectory with a package.json is also a member (mdhtml/wasm), unless it has its own lockfile (bun.lock, package-lock.json, yarn.lock, or pnpm-lock.yaml, a package that manages itself) or its root-relative path matches [tool.fastws].exclude (ghapi/examples).
  • A repo dir's own lockfile never opts it out. Every checkout is in the workspace.
  • Discovery skips node_modules, pkg, and _-prefixed dirs. Sync prints the members it adds, which makes a stray package visible the first time.

Sync

  • Each sync regenerates the workspaces list in the root package.json. It creates the file the first time a member exists and keeps entries that point outside the root or use globs.
  • After uv sync it runs the package manager's install at the root. Every member then resolves its siblings through the root node_modules symlinks, the npm analog of editable installs.
  • A member with a Cargo.toml beside its package.json is a native package (a wasm build). Sync runs its build script when pkg/ is missing or older than any source in the member's repo, the parent crate included. This is the JS analog of maturin develop.
  • The package manager is npm unless [tool.fastws] sets js = "bun". Both read the same workspaces field. Sync stops with a message when the chosen tool is not installed.
  • A checkout that is only a JS package is a valid member. Sync excludes it from the uv workspace like a Cargo-only crate and never treats it as a pending scaffold.

Refactors

  • _fastws_cfg moves from releases.py to core.py. Both modules share it.
  • _src_mtime takes a skip set. The JS staleness check uses it to ignore node_modules and pkg.
  • _pending_dirs extracts the pending-scaffold check that guards uv sync.

New tests in tests/test_sync.py cover discovery, excludes, tool selection, package.json regeneration, and the install-then-build pass.

A package.json in a workspace repo dir, or in an immediate subdirectory of one, makes that dir a JS member (felt/package.json, mdhtml/wasm/package.json); node_modules, pkg, and _-prefixed dirs are skipped. Each sync regenerates the workspaces list in the root package.json, creating it the first time a member exists and keeping entries that point outside the root or use globs, then runs the package manager's install at the root after uv sync so members resolve their siblings through the root node_modules symlinks: the npm analog of editable installs.

A member with a Cargo.toml beside its package.json is a native package. Sync runs its build script when pkg/ is missing or older than any source in the member's repo, the parent crate included: the JS analog of maturin develop. The package manager is npm unless [tool.fastws] sets js = "bun" or "pnpm".

A checkout that is only a JS package is a valid member: it is auto-excluded from the uv workspace like a Cargo-only crate and never counts as a pending scaffold, which is what stopped sync early on felt. _fastws_cfg moves from releases to core so both read the table the same way.

Claude-Session: https://claude.ai/code/session_01KCKXyYZu5R6fnPbTx3pMmo
A subdirectory of a repo dir joins the JS workspace only when a Cargo.toml sits beside its package.json, so example and frontend folders inside other repos (ghapi/examples, solveit/frontend) stay out, and `[tool.fastws].exclude` now applies to JS members too. `_js_tool` accepts npm or bun only, `_sync_js` stops with a message when the tool is not installed, and the package.json docstring says that only the list form of `workspaces` is managed. On the real workspace, `_npm_dirs` returns exactly felt and mdhtml/wasm.

Claude-Session: https://claude.ai/code/session_01KCKXyYZu5R6fnPbTx3pMmo
A subdirectory package is a member unless it has its own lockfile or matches an exclude path. The Cargo.toml check now only decides which members get a build.

Claude-Session: https://claude.ai/code/session_01KCKXyYZu5R6fnPbTx3pMmo
@ncoop57 ncoop57 changed the title ws-sync manages an npm workspace Sync JavaScript packages alongside Python and Rust members Sep 5, 2026
@ncoop57 ncoop57 added the enhancement New feature or request label Sep 5, 2026
A Vite app in the workspace must set server.fs.allow to the workspace root when a linked package fetches a file at runtime, such as a .wasm. The symlink resolves to the sibling checkout, which SvelteKit's default allow list does not cover.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant