fix: correct the peer ranges, prove both ends in CI, and finish adapter parity - #56
Merged
Merged
Conversation
The Angular package declared `@angular/core` and `@angular/common` as `>=14 <22` while its form store imports `signal` and `computed`, which Angular introduced in 16. npm accepted an install on 14 or 15 and the package then threw on import - the manifest promised something it had not been able to do for a long time. The range is now `>=16 <22`, so the same install is refused up front. Verified both ways: Angular 16 and 21 import and share one registry with core, and an install against 15 is now rejected. Vue moves from `^3.0.0` to `^3.2.0`, because `useDynamicForm` now aborts whatever is still in flight when the owning effect scope is disposed. Without it an unmounted form held its request open until the response came back. `getCurrentScope` and `onScopeDispose` are both Vue 3.2, and the `getCurrentScope()` guard is for calling the composable outside a scope, which the tests do. Neither range was ever exercised at its floor - the suites only ever run against whatever the workspace installs. `scripts/verify-vue-peer-range.js` server-renders the packed tarballs under Vue 3.2 and the newest 3.x; `scripts/verify-angular-peer-range.js` installs them against Angular 16 and 21 and checks the package imports, its components evaluate, and the registry is shared. Both run in the CI verify job beside the React one. Angular is import-level rather than render-level on purpose: the published fesm2022 needs the CLI's linker to instantiate a component, and import-and-wire is the level that breaks across majors - which is precisely how a floor of 14 survived years of `signal()`. Angular 21 deprecates `@angular/platform-browser-dynamic`. It is gone from the package's devDependencies and from the demo app, which never used it (it bootstraps with `bootstrapApplication`), and the test setup initialises through `@angular/platform-browser/testing` instead. Removing that devDependency meant regenerating the lockfile, and npm on Windows prunes optional entries the Linux runners need while doing it - it dropped @emnapi/core, @emnapi/runtime, @noble/hashes and yaml, which is enough for Unknown command: "ci" Did you mean this? npm ci # Clean install a project To see a list of supported npm commands, run: npm help to refuse the lockfile on CI. They are restored here.
`collectFieldPaths`, `indexGroupPathMap` and the `ValidationContext` type shipped in core with 1.6.0 but reached none of the adapters, so typing a validator's `context` argument meant importing `@dynamic-field-kit/core` alongside the adapter - the exact thing the curated re-export list exists to avoid, and a drift the three lists are supposed to stay free of. The adapter READMEs list them, document the corrected peer ranges, and `scripts/add-dts-extensions.js` records that ng-packagr 21 emits one rolled-up d.ts with no relative specifiers left to rewrite, so the step is a no-op now and stays only as a guard.
Importing the package under Angular 16 proves it resolves and evaluates, but not the thing that actually breaks a consumer across majors. The published fesm2022 ships partial declarations, and a consumer's build links them with *its* Angular. If building the library on a newer Angular raised their `minVersion`, every consumer below that version would fail in the linker while installing and importing perfectly well - the failure would surface in their app, never here. So the check runs the floor's own `@angular/compiler-cli` linker over the bundle and asserts nothing is left partial. Against the ng-packagr 21 output the Angular 16 linker consumes all of it: the declarations still carry `minVersion` 12 and 14, because ng-packagr stamps what the emitted code needs, not the compiler that emitted it. Only the floor is linked. A newer linker accepting an older declaration is the direction that was never in doubt.
vannt-dev
force-pushed
the
fix/peer-ranges-and-adapter-parity
branch
from
September 3, 2026 19:10
9aa0439 to
8451c33
Compare
… exist
The docs carry dozens of copy-paste import statements and nothing checked
them, so a rename lands, the READMEs keep the old name, and the first person
to find out is a reader whose editor cannot resolve it.
This reads every `import { ... } from '@dynamic-field-kit/*'` inside a fenced
code block and asserts each name is exported, resolving the export list from
each package's built .d.ts through the TypeScript compiler so type-only
exports count. Prose is ignored - only fenced blocks are checked, because
they are what people copy - and a package that has not been built is skipped
rather than treated as exporting nothing.
Proven non-vacuous the way the peer range checks are: adding an import of a
name that does not exist exits 1 and names the file and line.
The docs pass as they stand. The one thing worth knowing about the extractor
is that the brace span must exclude braces - `import { h } from 'vue'` above
an import of this package was otherwise swallowed into one statement, and
every name in the first import was reported missing.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes the last items standing between
developand a 1.6.0 release. Two commits.1.
fix: declare the peer ranges the packages can actually satisfyAngular's declared floor was wrong, and would fail at runtime. The package declared
@angular/core/@angular/commonas>=14 <22, but the form store importssignalandcomputed, which Angular introduced in 16. npm accepted an install on 14 or 15 and the package then threw on import. Now>=16 <22, so the bad install is refused up front — verified by running the new script against Angular 15 and watching npm reject it.Vue moves to
^3.2.0, and gains the cleanup that motivates it.useDynamicFormnow aborts whatever is in flight when the owning effect scope is disposed; without it an unmounted form held its request open until the response arrived.getCurrentScope/onScopeDisposeare Vue 3.2, and thegetCurrentScope()guard covers calling the composable outside a scope, which the tests do. Test-first: the new test fails without the cleanup.Neither range was ever exercised at its floor — the suites only run against whatever the workspace installs. Two new scripts fix that, beside the React one that has existed since 1.5.0, all three in the CI verify job:
verify-vue-peer-range.jsverify-angular-peer-range.jsAngular is import-level rather than render-level on purpose: the published fesm2022 needs the CLI's linker to instantiate a component. Import-and-wire is the level that breaks across majors — precisely how a floor of 14 survived years of
signal().@angular/platform-browser-dynamicis gone. Angular 21 deprecates it. Removed from the package's devDependencies and from the demo app (which bootstraps withbootstrapApplicationand never used it); the test setup initialises through@angular/platform-browser/testing.2.
feat: re-export the new core helpers from every adaptercollectFieldPaths,indexGroupPathMapand theValidationContexttype shipped in core but reached none of the adapters, so typing a validator'scontextargument meant importing@dynamic-field-kit/corealongside the adapter — the drift the curated re-export lists exist to prevent. Adapter READMEs list them and document the corrected peer ranges.scripts/add-dts-extensions.jsrecords that ng-packagr 21 emits one rolled-up d.ts with nothing left to rewrite, so it is a no-op now and stays only as a guard.Verification
test:scripts/ coretest:typesarethetypeswrongon all four tarballsCJSResolvesToESMnode16ESM consumer against the packed tarballstscexit 0