Releases: dignite-projects/abp-modules
Release list
v10.0.0-rc.16
Fixed
-
The single "install with Yarn Classic and check for a duplicate" verification
build/verify-npm-single-copy.mjsperforms for issue #211 ran only after both Angular publish
steps inrelease.yml, so a real duplicate reaching consumers would be reported only once the
damage was already done - the same failure shapev10.0.0-rc.14's own post-publish crash exposed:
the check runs at all, but by the time it can fail, everything is already live on npmjs and GitHub
Packages, and a failure there can only skip the draft GitHub Release, not stop a bad publish.
verify-npm-single-copy.mjsnow supports two modes.packedinstalls the five tarballs the
workflow's ownnpm packsteps already produce, pointing each@dignite/*dependency at its
tarball with afile:path instead of a registry range - Yarn Classic resolves afile:
dependency's version from the tarball's ownpackage.jsonand reconciles it against every other
edge in the graph exactly as it would a registry-resolved copy, so it exercises the same
duplicate-vs-dedupe logic without anything published yet. A new "Verify packed Angular packages
install as a single copy each" step runs this immediately after the last pack step, with noif:
guard, so both aworkflow_dispatchpreview build and a tagged release get the real gate.
publishedis the previous behavior, kept as a lighter step after the npm publish - it still
catches what a local tarball cannot, such as a dist-tag pointing at the wrong version, but a
failure there is no longer the only line of defense. -
The new
packedmode above failed outright the first time it ran against a version that had
never been published anywhere (Couldn't find any versions for "@dignite/ng.file-explorer" that matches "^10.0.0-rc.16"), because it only pointed the top-level dependency at each tarball's
file:path - a sibling package's own packedpackage.json(e.g.
flex-fields-file-explorerdepending onflex-fields) still declares that edge as a plain semver
range, and Yarn Classic resolves afile:request and a semver-range request for the same package
name as two independent lookups rather than reusing one to satisfy the other. It went to the npm
registry for the range and failed, since nothing at that version exists there yet - exactly the
case this check exists to run before.verify-npm-single-copy.mjs'spackedmode now also sets
resolutionsto the same fivefile:paths, forcing every occurrence of a name in the tree onto
the local tarball regardless of what range asked for it. This doesn't weaken the check:
verify-version-lockstep.ps1already rejects a drifted internal range before this step ever runs,
so every internal@dignite/*range is already^<the current version>by the timepackedmode
installs. -
This repository's own
flex-fields/angularandfile-storing/angulardemo apps were themselves
carrying the exactng-zorro-antdduplicate6f039efdocumented as an accepted cost of
@abp/ng.componentspinning that package at~21.0.0-next.1(i.e.<21.1.0):21.3.3at each
workspace root, declared there only for the demo's own use, and21.0.2nested under
node_modules/@abp/ng.components/node_modules- two module-scopedNZ_CONFIG/NzConfigService
tokens, so a root-levelprovideNzConfig()/provideNzI18n()never reached the copy
@abp/ng.components's own controls (e.g.abp-tree) resolve. That duplication is inherent to
@dignite/ng.flex-fields's and@dignite/ng.file-explorer's published^21.0.0peer range - a
real downstream host may need21.3.xfor reasons the packages can't rule out, which is why that
peer range is untouched - but nothing required these two demo apps to actually be such a host:
they exist to exercise the published packages, not to prove a wide peer range works.ng-zorro-antd
is now narrowed to~21.0.2in bothflex-fields/angular/package.jsonand
file-storing/angular/package.json- inside@abp/ng.components's ceiling, and the same version
that was already nested - which collapses both workspaces back to a single copy. Both demo apps'
production builds (yarn build:prod) pass unchanged at the older version. A new
build/check-angular-package-duplicates.mjs, wired intoci.ymlimmediately after each of the
three Angular workspaces'yarn install --frozen-lockfilesteps, generalizes
verify-npm-single-copy.mjs's duplicate check from the five@dignite/*packages it covers to any
bare-or-scoped target list -ng-zorro-antdand@angular/cdkfor now, the latter reaching these
same packages by the same@abp/ng.componentsroute even though no version conflict currently
splits it.notifications/angularis checked too even though it declares neither package itself:
it depends on@abp/ng.components, which pulls both in transitively, so it is exposed to the same
failure mode the moment something else in that workspace narrows either range. Like its sibling
script, a target that matches nothing installed fails the run rather than passing vacuously - a
typo'd target or a check pointed at the wrongnode_modulesis otherwise indistinguishable from a
clean tree.
Added
flex-fields
- Two new built-in field types,
MatrixandTable— the first composite ones, whose
configuration declares whole field definitions inline.Matrixis a repeatable list of
polymorphic blocks (the admin declares named block types up front, each with its own sub-fields);
Tableis a homogeneous grid over one shared column schema. Both were written and proven in
Dignite.Site'sDignite.FlexFields.Siteand are ported here with the wire format unchanged —
registration keysMatrix/Table, configuration keysMatrix.BlockTypes/Table.Columns, and
camelCase{blockTypeName, values}/{values}value arrays — so fields already stored against
the Site implementation keep working as-is. They ship as built-ins rather than a bolt-on package
because, unlikeFileExplorerorCKEditor, they depend on nothing outside the kernel's own
vocabulary; what made them worth moving is that the two contracts below have to be answerable
without knowing either concrete type.Dignite.Abp.FlexFields.AbstractionsgainsMatrixFieldType/TableFieldTypeand their
configuration types, plus four kernel contracts they share:ICompositeFieldType
(GetInlineFields, so a host can ask "does this type contain other fields, and which" without
naming a concrete type — an interface rather than anIsCompositebool, because every caller
that asks also has to walk those fields),INormalizesValue(Normalize, the canonical wire
shape — deliberately not folded intoValidate, which returns only errors and never the parsed
value, so a value with the wrong key casing would otherwise validate cleanly and then be stored
verbatim and be unreadable to every camelCase reader downstream),InlineFieldDefinition
(one inline field; carriesRequired, which aFlexFieldDatacannot), and
CompositeFieldNesting(MaxDepth = 3and the bounded measurement that enforces it — a
configuration is a tree of unbounded depth and every reader of it recurses, so it is capped once
on write instead of guarded in each reader).Dignite.Abp.FlexFields.WebgainsViews/Shared/FlexFields/Matrix.cshtmlandTable.cshtml,
which recurse through the existing<flex-field-view>dispatch for each sub-field rather than
re-implementing rendering per type. NoSearch/partials: both types have
IndexValueType == null— a list of composite objects has no typed index column to decompose
into — so neither can be markedSearchable.@dignite/ng.flex-fieldsgains the matching config / control / view components
(ff-matrix-config|control|view,ff-table-config|control|view), registered in
BUILT_IN_FIELD_TYPES, so an existingprovideFlexFields()call already covers them.
FieldTypeDefinitiongains an optionalcompositeflag, which Matrix and Table set and the
config editors use to stop offering composite types once the nesting limit is reached; the
server'sCompositeFieldNestingremains the authority, that mirror is a courtesy.- Neither contract is invoked by the kernel — a host calls them, and the demo now shows both:
ProductAppServicenormalizes the value bag before validating and saving, and
ProductFieldAppServicerefuses a too-deeply-nested configuration on create and update. - Localization moved with them: the
FieldType:Matrix/FieldType:Table,Matrix:*,Table:*
andValidate:Matrix:*/Validate:Table:*texts now live in theFlexFieldsresource
(Dignite.Abp.FlexFields.Abstractions) instead of Site's ownFlexFieldsSiteresource, in all
four shipped cultures (en,ja,zh-Hans,zh-Hant). Three general validation keys the
Angular side's shared error-message helper needs came along with them:Validate:MinValue,
Validate:MaxValueandValidate:MaxLength.
v10.0.0-rc.14
Fixed
-
Every tag-triggered release since the npm Trusted Publishing migration (
v10.0.0-rc.12and
v10.0.0-rc.13, twice for the latter) crashed insiderelease.ymlbefore the job ever published
anything to NuGet.org or npm. The job's "Setup Node.js" step setregistry-url(needed for the
later OIDC-based npm publish steps), which makesactions/setup-node@v7write an
//registry.npmjs.org/:_authToken=${NODE_AUTH_TOKEN}placeholder into a generated.npmrc.
Nothing in the job has setNODE_AUTH_TOKENsince npm publishing became OIDC-based — npm's own
Trusted Publishing doesn't use it at all — but Yarn Classic (1.x, used by all three Angular
workspaces) eagerly substitutes every env-var placeholder in its resolved config on every
invocation, not just registry-touching ones, and throws when one is unset. A first fix dropped the
cache: yarnstep option that was triggering this during its internalyarn cache dirprobe; that
only moved the crash to the next yarn command Setup Node's cache change didn't touch — the job's
very first realyarn install— because the placeholder-bearing.npmrcstays active for every
step for the rest of the job, not just the one that wrote it. The actual fix movesregistry-url
off the early "Setup Node.js" step entirely, onto a secondactions/setup-node@v7call added right
after the last yarn command in the job (before the GitHub Packages and npmjs publish steps that
need it) — so no yarn command ever sees that.npmrcin the first place.ci.yml's
identical-looking "Setup Node.js" step never hit any of this because it never setsregistry-url. -
release.yml's "Publish pre-release Angular packages to GitHub Packages" step had no--tag
on itsnpm publishcall, and npm refuses to publish a pre-release version (every version this
repository has ever shipped so far) without one explicitly stated. Unlike the crash above, this
one only broke once the job got far enough to actually reach it. Added the same
--tag '${{ steps.channel.outputs.npm-tag }}'the sibling npmjs-publishing step already used. -
The GitHub Packages pre-release step appended its own registry/auth lines to the same
.npmrcactions/setup-node'sregistry-urlwrote for npmjs.org OIDC ($NPM_CONFIG_USERCONFIG,
read by "Publish tagged Angular packages to npm" later in the same job) — corrupting npm's parsing
of that shared file and breaking OIDC's registry detection there with a garbledENEEDAUTHerror
quoting both registries concatenated together. The GitHub Packages step now writes its auth to its
own scratch file, passed via--userconfigon just its ownnpm publishcalls, leaving the
OIDC-relevant file untouched for the rest of the job. -
The two Angular adapter packages declared their intra-repo siblings at a stale range, so
consumers could end up with two copies of@dignite/ng.flex-fieldsand no working field types.
flex-fields-ckeditorandflex-fields-file-explorerboth still asked for^10.0.0-rc.4while
every package in the repository shipped10.0.0-rc.13. That range admits an older sibling, so a
resolver is free to satisfy it with one rather than deduplicating against the copy already at the
root — and Yarn Classic does exactly that whenever npm'slatesttag sits on an older version
than the newest published one, which is the case today (latestis10.0.0-rc.11,nextis
10.0.0-rc.13). The result is not wasted bytes: Angular DI keys off object identity and
FLEX_FIELD_TYPESis a module-scopedInjectionToken, so two copies are two distinct DI keys —
provideCKEditorFieldType()registers into one whileFieldTypeResolverreads the other, and
every field type appears unregistered at runtime with nothing having failed at install or build
time. All three ranges now track the release version, and
.github/scripts/verify-version-lockstep.ps1— already the release's version-lockstep gate —
additionally fails the release if any@dignite/*dependency or peer dependency of a published
Angular package names anything other than the version being released, so this cannot drift again.
Note that clearing the duplicate for consumers still onlatestalso needs thelatestdist-tag
moved off10.0.0-rc.11. See #211. -
release.ymlnow verifies, after publishing, that a Yarn Classic install of the just-released
packages resolves exactly one copy of each. The packed-tarball smoke tests already in the
workflow install with npm, which deduplicates; all three Angular workspaces here and every
known downstream use Yarn Classic, which does not. That gap is what let the duplicate above
reach consumers with every existing check passing.build/verify-npm-single-copy.mjscloses it by
checking the resolved outcome rather than the manifests — so a duplicate arriving by some other
route (a transitive@dignite/*edge, a dist-tag that makes a caret resolve backwards) is caught
too. It runs after the npm publish step, since it resolves real versions from npmjs that do not
exist until then; a failure therefore cannot un-publish anything, it stops the draft GitHub Release
and reports that the just-published set does not install cleanly. -
A pre-release now also takes npm's
latestdist-tag, for as long as no stable release exists.
release.ymlpublished every pre-release undernextalone and reservedlatestfor a stable
version — of which there is none yet on the 10.x line.latestwas therefore left wherever it
happened to land before that convention took hold (10.0.0-rc.11, while10.0.0-rc.13was the
newest published), so a barenpm install @dignite/ng.flex-fieldshanded out a version two releases
behind, and Yarn Classic resolved intra-repo ranges backwards onto it — the second of the three
conditions behind #211. The tag had
been corrected by hand, but the workflow would have re-created the gap at the next pre-release.
build/resolve-npm-dist-tag.mjsnow decides it: a stable version always takeslatest, and a
pre-release takes it too only while the registry holds no stable release of these packages,
falling back tonextfrom the moment one exists. Reading the registry rather than flipping a flag
means the rule retires itself when10.0.0ships, instead of silently moving consumers off a stable
release onto a later10.1.0-rc.1. Thechanneloutput is unchanged and still means "is this a
pre-release" for the GitHub Packages mirror and the draft Release's own flag.
flex-fields
-
@dignite/ng.flex-fields'ng-zorro-antdpeer range rejected every release after21.0.x. It
was~21.0.0-next.1, which expands to>=21.0.0-next.1 <21.1.0-0— so21.1.0and everything
since, up to the current21.3.3, failed the peer. Under npm 7+ that is anERESOLVEinstall
error rather than a warning; Yarn Classic downgrades it to a warning, which is why it had not
surfaced. The range dated from when21.0.0-next.xwas the newest thing published and was never
revisited after21.0.0went stable. It is now^21.0.0, matching how.github/dependabot.yml
already reasons about this package (its major tracks Angular's, so majors are ignored and the
21.xline is meant to be tracked).flex-fields/angular's own dependency moves to^21.3.3
alongside it, so the workspace develops against a version the library claims to support — it had
been pinned to the same capped range and stuck on21.0.2whilefile-storing/angularwas already
on21.3.3. See #220. -
CKEditorControlComponent's theme bridge now resolves against<body>as well as<html>. A
custom property'svar()references are resolved against the element the property is declared on,
not against wherever it is eventually consumed, so the bridge's:rootdeclarations could only
ever see theme variables set on<html>. A host that marks its dark theme on<body>instead —
data-bs-theme="dark"on the body element, say — left the bridge resolving the light values, and
the editor stayed light while the rest of the page went dark. Both blocks are now declared on
:root, body, so either placement works. Coverage is unchanged: CKEditor's UI, including the
balloon/dropdown wrapper it appends directly under<body>, is entirely inside the body subtree. -
The
SelectandTreefield controls’ dropdown panels now follow a dark host. Both painted
their panel withvar(--lpx-content-bg, #fff), but--lpx-content-bgis a full LeptonX token
(@volosoft/ngx-lepton-x:#f0f4f7light,#121212dark). LeptonX Lite —@volo/ngx-lepton-x.lite,
which@abp/ng.theme.lepton-xwraps — never defines it: it ships 11--lpx-*tokens and this is
not one of them. The chain therefore fell straight through to the literal#fffand the panel
stayed white in every theme, while the options’ owncolor: var(--bs-body-color)did follow the
host — light grey text on white, unreadable. Both now fall back to--bs-secondary-bgfirst
(#e9eceflight,#343a40dark in Lite), the Bootstrap 5.3 “one step off the body surface” token
that every Bootstrap-based theme defines at:rootand redefines under[data-bs-theme=dark]—
the same chain shapeflex-fields-ckeditoralready uses for--ck-color-base-foreground. Light
mode moves from pure white to#e9ecef. -
The
Selectfield's multi-select tags were near-illegible in a dark host. ng-zorro hardcodes
the tag's entire chrome —background: #f5f5f5,border: 1px solid #f0f0f0, and
rgba(0, 0, 0, 0.45)on the remove icon — while the tag's label does follow the host, because this
file already setscolor: inheriton `.ant-se...
v10.0.0-rc.13
Added
build/check-angular-package-deps.mjs, a CI gate that fails when a built library imports a
package its ownpackage.jsondoes not declare. ng-packagr marks every bare specifier it does
not bundle as an external but never checks that the external is declared, so a library could
publish a bundle asking for a package it never named — nothing failed at build time, nothing
failed atnpm install, and the consumer met an unresolvable specifier the first time they built
their own app. The existingsmoke-test-angular-package.mjscannot see this class of defect: it
seeds the throwaway consumer with the demo app's dependency list, so every undeclared package is
already installed before the compile it verifies. All five libraries were failing this check when
it was written.
Changed
- npmjs publishing switched from a long-lived
NPM_TOKENsecret to npm Trusted Publishing (OIDC);
each of the five Angular packages now has its own Trusted Publisher configured on npmjs.com.
@dignite/ng.flex-fields-ckeditoris published to npmjs on tagged releases for the first time. - The GitHub Packages pre-release npm mirror now tolerates re-runs at an unchanged version,
treating "already published" as a skip instead of failing the step. - Dependencies a consumer cannot already have moved from
peerDependenciestodependencies.
Every ABP 10.5 + Angular 21 host is forced to setlegacy-peer-deps—@abp/ng.theme.shared
pins@swimlane/ngx-datatable@~22.0.0, whose Angular peer range stops at 20 — and under that
flag npm does not install peer dependencies at all. A peer the host does not already have is
therefore an unresolvable import discovered at the consumer's build, with nothing in
npm installto warn them. The evidence that the peer model never worked here: all five known
consumers (site,vault-extract, and this repository's own three demo apps) had hand-copied
the same peer lists into their ownpackage.json, at three differentng-zorro-antdranges.
Moved todependencies:ckeditor5,@ckeditor/ckeditor5-angular,markedand
@dignite/ng.flex-fieldsin@dignite/ng.flex-fields-ckeditor;@dignite/ng.flex-fieldsand
@dignite/ng.file-explorerin@dignite/ng.flex-fields-file-explorer;@microsoft/signalrin
@dignite/ng.notification-center. Packages an ABP Angular host has by construction
(@angular/*,rxjs,@abp/ng.*) or through ABP's own dependency tree (@ngx-validate/core,
ng-zorro-antd,@angular/cdk,@ng-bootstrap/ng-bootstrap,@swimlane/ngx-datatable) stay
peer dependencies: there the declaration states the tested range without risking a second copy
of a singleton in the consumer's tree. Consumers that were carrying those packages by hand can
drop them; consumers that were not no longer have to discover them.
Fixed
- Every Angular package imported at least one package it did not declare.
@ngx-validate/corein@dignite/ng.flex-fields,@dignite/ng.flex-fields-ckeditorand
@dignite/ng.flex-fields-file-explorer;rxjsin@dignite/ng.flex-fields-ckeditorand
@dignite/ng.notification-center;@swimlane/ngx-datatablein@dignite/ng.file-explorer; and
@ckeditor/ckeditor5-integrations-common, whoseEditorRelaxedConstructorappears in
@dignite/ng.flex-fields-ckeditor's published.d.ts, so a consumer compiling without
skipLibCheckneeded it resolvable. All now declared; the new dependency check keeps them so. flex-fields-ckeditorwas built and published byrelease.ymlbut never built byci.yml,
so a pull request that broke the CKEditor adapter stayed green until tag time. CI now builds it
alongside the other libraries.
flex-fields
CKEditorControlComponentnow follows the host theme, including dark mode. CKEditor 5 ships a
single stock light palette (--ck-color-base-background/-foreground/-border/-textin its own
:root) and every other--ck-color-*token derives from those four; the control set none of them,
so in a dark-themed host the editor stayed light unless the host added its own bridge (onlysite
had one). The control now maps those tokens, plus the two hardcoded toolbar-button hover/active
fills, to the host's theme variables — a LeptonX token when present, falling back to the Bootstrap
5.3 token every ABP Angular theme ships, then to CKEditor's stock literal — so hosts no longer need
a--ck-color-base-*bridge of their own.