Summary
The sm new scaffold (in simple_module_cli==0.0.8) hard-codes outdated version pins:
client_app/package.json pins \"@simple-module-py/ui\": \"^0.0.3\" and \"@simple-module-py/i18n\": \"^0.0.3\". Both are at 0.0.8 on npm.pyproject.toml pins simple_module_hosting==0.0.7, simple_module_users==0.0.7, etc. All are at 0.0.8 on PyPI.pyproject.toml[dependency-groups].dev pins simple_module_test==0.0.7. Also at 0.0.8.
The npm side fails silently and with worse consequences: ^0.0.3 doesn't behave the way it does for ^1.2.3. Per the npm semver rules, when the major and minor are both zero, caret is locked to that exact patch — so \"^0.0.3\" resolves to 0.0.3 and never to 0.0.4..0.0.99. Result: a fresh npm install pulls @simple-module-py/ui@0.0.3 (with the broken exports map and missing deps from #114/#115) even though 0.0.8 shipped both fixes.
Reproduction
$ uvx --from simple_module_cli sm new my-app --db sqlite --preset standard -y --no-install
$ cd my-app && cat client_app/package.json | grep simple-module
\"@simple-module-py/i18n\": \"^0.0.3\",
\"@simple-module-py/ui\": \"^0.0.3\",
$ cat pyproject.toml | grep simple_module
dependencies = [\"simple_module_hosting==0.0.7\", \"simple_module_auth==0.0.7\", \"simple_module_users==0.0.7\", \"simple_module_dashboard==0.0.7\", \"simple_module_permissions==0.0.7\"]
dev = [\"simple_module_test==0.0.7\", \"pytest>=8.0\"]
$ make install # (after the dependency-group entry is fixed if test wasn't published)# uv pulls 0.0.7# npm pulls @simple-module-py/ui@0.0.3 — NOT 0.0.8
$ cd client_app && ls node_modules/@simple-module-py/ui/package.json && grep '\"version\"' node_modules/@simple-module-py/ui/package.json
\"version\": \"0.0.3\",
Root cause
The CLI ships a static template with hard-coded version strings. Every simple_module_cli release would have to bump those strings to match its own version, and they currently don't. As a result, version drift between simple_module_cli and the rest of the workspace silently downgrades users.
Worse, the npm pins use ^0.0.x syntax that defeats its own purpose. Even if the strings did keep up, anyone doing npm install --save @simple-module-py/ui@latest after the fact would be fine, but the standard make install flow won't bump them.
Proposed fix
Two complementary changes:
A. Tie the scaffold's pinned versions to the CLI's own version at scaffold time
Either:
A1. Have sm new substitute its own simple_module_cli.__version__ into the template at write time. Every PyPI/npm release is cut as a coordinated set (0.0.8 is consistent across simple_module_* PyPI and @simple-module-py/* npm), so a single version variable works.
A2. Have sm new query PyPI/npm at scaffold time for latest and substitute that. Adds a network dep and is harder to hermeticize, but always picks the latest.
(A1) is the cleanest — the version that exists on PyPI/npm under the same tag as the running CLI is the one that will work with it.
B. Don't use ^ for 0.0.x versions
For zero-major releases, switch to either:
Tilde (~0.0.8) is the conventional fix and matches what most pre-1.0 packages do. Once you ship 0.1.0+, caret can come back.
Suggested test
Add a regression test in the CLI repo that runs sm new into a tmpdir, then asserts:
importjson, re, tomllibfrompathlibimportPathimportsimple_module_clidest=Path(\"<scaffolded_dir>\")
v=simple_module_cli.__version__py=tomllib.loads((dest/ \"pyproject.toml\").read_text())
fordepinpy[\"project\"][\"dependencies\"]:
ifdep.startswith(\"simple_module_\"):
assertdep.endswith(f\"=={v}\"), depjs=json.loads((dest/ \"client_app/package.json\").read_text())
fork, specinjs[\"dependencies\"].items():
ifk.startswith(\"@simple-module-py/\"):
assertspecin (v, f\"~{v}\"), (k, spec)Workaround
Hand-bump every 0.0.7/^0.0.3 reference and re-run uv sync / npm install:
sed -i '''s/0\\.0\\.7/0.0.8/g' pyproject.toml
sed -i '''s/\\^0\\.0\\.3/0.0.8/g' client_app/package.json
rm -rf client_app/node_modules client_app/package-lock.json
uv sync && (cd client_app && npm install)
Related
Environment
simple_module_cli 0.0.8@simple-module-py/ui 0.0.8 (latest on npm)- All
simple_module_* PyPI packages at 0.0.8
Summary
The
sm newscaffold (insimple_module_cli==0.0.8) hard-codes outdated version pins:client_app/package.jsonpins\"@simple-module-py/ui\": \"^0.0.3\"and\"@simple-module-py/i18n\": \"^0.0.3\". Both are at0.0.8on npm.pyproject.tomlpinssimple_module_hosting==0.0.7,simple_module_users==0.0.7, etc. All are at0.0.8on PyPI.pyproject.toml[dependency-groups].devpinssimple_module_test==0.0.7. Also at0.0.8.The npm side fails silently and with worse consequences:
^0.0.3doesn't behave the way it does for^1.2.3. Per the npm semver rules, when the major and minor are both zero, caret is locked to that exact patch — so\"^0.0.3\"resolves to0.0.3and never to0.0.4..0.0.99. Result: a freshnpm installpulls@simple-module-py/ui@0.0.3(with the broken exports map and missing deps from #114/#115) even though0.0.8shipped both fixes.Reproduction
Root cause
The CLI ships a static template with hard-coded version strings. Every
simple_module_clirelease would have to bump those strings to match its own version, and they currently don't. As a result, version drift betweensimple_module_cliand the rest of the workspace silently downgrades users.Worse, the npm pins use
^0.0.xsyntax that defeats its own purpose. Even if the strings did keep up, anyone doingnpm install --save @simple-module-py/ui@latestafter the fact would be fine, but the standardmake installflow won't bump them.Proposed fix
Two complementary changes:
A. Tie the scaffold's pinned versions to the CLI's own version at scaffold time
Either:
A1. Have
sm newsubstitute its ownsimple_module_cli.__version__into the template at write time. Every PyPI/npm release is cut as a coordinated set (0.0.8is consistent acrosssimple_module_*PyPI and@simple-module-py/*npm), so a single version variable works.A2. Have
sm newquery PyPI/npm at scaffold time forlatestand substitute that. Adds a network dep and is harder to hermeticize, but always picks the latest.(A1) is the cleanest — the version that exists on PyPI/npm under the same tag as the running CLI is the one that will work with it.
B. Don't use
^for0.0.xversionsFor zero-major releases, switch to either:
Tilde (
~0.0.8) is the conventional fix and matches what most pre-1.0 packages do. Once you ship0.1.0+, caret can come back.Suggested test
Add a regression test in the CLI repo that runs
sm newinto a tmpdir, then asserts:Workaround
Hand-bump every
0.0.7/^0.0.3reference and re-runuv sync/npm install:Related
@simple-module-py/ui@0.0.8but only visible after the version pin is bumped.package.jsonreference module workspaces by*and avoid needing to keep version strings in sync at all.Environment
simple_module_cli0.0.8@simple-module-py/ui0.0.8 (latest on npm)simple_module_*PyPI packages at 0.0.8