Sitelet https://github.com/sdcorejs/sdcorejs-angular/pull/72
Skip to content

fix(table): read column fields that @sdcorejs/utils 1.2 rejects as paths; pin @sdcorejs/utils 1.2.5 - #72

Merged
sdcorejs merged 2 commits into
mainfrom
fix/table-field-path-fallback
Oct 2, 2026
Merged

sdcorejs merged 2 commits into
mainfrom
fix/table-field-path-fallback

Conversation

@sdcorejs

@sdcorejs sdcorejs commented Oct 1, 2026

Copy link
Copy Markdown
Owner

Summary

On main, SdTable fails the whole read with "Không thể tải dữ liệu" when a column or group field contains whitespace or *. Tables whose columns come from backend keys, such as import results with 'Số phòng ngủ' or 'Loại sản phẩm*', hit this.

The cause is @sdcorejs/utils 1.2. Its Utilities.getNestedValue throws UnsafePropertyPathError for those property paths. TableFormatService.format read the value outside the per-cell try.

The published 2.15 lines still pin utils 1.1.4, so this regression exists only on main.

This PR ports the @sd-angular/core fix (NSP-5745). It also pins @sdcorejs/utils 1.2.5 (sdcorejs-utils #15), which keeps cross-entry instanceof working in bundled apps.

Changes

  • components/table/src/services/field-value.util.ts (new, internal): resolveFieldValue.
    • A path that utils accepts returns the getNestedValue result.
    • A rejected path falls back to the 1.1.x dot-split lookup over own data properties.
    • The fallback never reads through __proto__, prototype or constructor, and never returns a prototype object.
    • Rejection is detected once per field with a cached probe, not with instanceof.
  • 13 column/group field reads now go through the resolver:
    • format and lazy-values (the cell read moved inside the per-cell try);
    • desktop cell;
    • SdGroupPipe;
    • aggregates (column and group);
    • quick search;
    • export;
    • local filter and sort.
  • rowKey, valueField and displayField reads are unchanged.
  • @sdcorejs/utils 1.2.4 → 1.2.5 in the v19–v22 workspaces and libraries and in the showcase.
    • Lockfiles change only the utils entry.
    • With 1.2.5, a cancelled file picker is recognised again in sd-upload-file, SdApiService.upload() and SdExcelService.upload() in application builds.
  • Docs:
    • sd-table.md: the field row now describes the fallback.
    • CHANGELOG.md [Unreleased] → ### Changed: the existing utils bullet now reads 1.1.4 → 1.2.5. It also notes the table field rule, the file-picker cancel fix and the errorName requirement for subclasses. No ### Fixed entry, because these regressions never shipped.
  • v20, v21 and v22 are regenerated with npm run sync.
  • Tests: 24 resolver specs, plus NSP-5745 cases in the read-state, format, local, group, aggregate, quick-search and export specs.
  • .sdcorejs: approved spec and plan (revision 2) and the execution record.
  • Separate commit: .gitignore ignores .sdcorejs/tmp.

Verification

All runs used Node 22.22.3.

  • TDD:
    • RED: the resolver spec failed to compile with TS2307, and the existing table specs had 8 new failures (UnsafePropertyPathError).
    • GREEN: all of those pass after the change.
  • v19 table specs plus the upload-file, api and excel specs: 892/892.
  • npm run build (v19): Built Angular Package.
  • npm run check:sync: v20, v21 and v22 match v19.
  • ESLint on the 16 changed v19 files: 0 problems.
  • npm ls @sdcorejs/utils resolves 1.2.5 in v19, v20, v21, v22 and the showcase.
  • Delivery convergence (sdcorejs): CONVERGED, with all 9 acceptance criteria automated. Branch-ready had no blockers.

Not run:

  • The full-library test:ci (the table suite and the utils consumer specs were run instead).
  • Separate builds of v20–v22 (they are sync output, covered by check:sync).

Review and repair

R1 (required) was fixed. The CHANGELOG first added ### Fixed entries for regressions that never shipped. The text now lives in the existing [Unreleased] utils bullet.

Two advisories are left for follow-up:

  • Quick-search dropdown filters[].field still goes through FilterUtilities.match, so the strict path rule applies there. These fields are developer-defined.
  • Running npm run sync on a core.autocrlf=true checkout writes CRLF into v22, whose .gitattributes says eol=lf. npm install in v20 and v21 also re-indents the lockfile. Both were corrected by hand here.

Notes for reviewer

  • Consumer impact from utils 1.2.5: a class that extends a @sdcorejs/utils error must declare static override readonly errorName: string. The library itself has no such subclass.
  • Rollback: revert the fix(table) commit.

🤖 Generated with Claude Code

nghiatt15 and others added 2 commits October 1, 2026 18:00
…ths; pin @sdcorejs/utils 1.2.5

Since @sdcorejs/utils 1.2, Utilities.getNestedValue throws UnsafePropertyPathError
for a property path with whitespace or "*". SdTable read row values with it, and
TableFormatService.format did so outside the per-cell try, so a table whose
columns come from backend keys ("Số phòng ngủ", "Loại sản phẩm*") failed the
whole read with "Không thể tải dữ liệu". The published 2.15 lines still pin
utils 1.1.4, so the regression exists only on main.

Add the internal resolveFieldValue (components/table/src/services/
field-value.util.ts), the same resolver as @sd-angular/core NSP-5745. A path
that utils accepts keeps the getNestedValue result. A rejected path falls back
to the 1.1.x dot-split lookup over own data properties, never through
__proto__/prototype/constructor and never into a prototype object. Rejection is
detected once per field with a probe instead of instanceof. Every column and
group field read uses it: format and lazy-values, desktop cell, SdGroupPipe,
aggregates, quick search, export, local filter and sort. rowKey, valueField and
displayField reads are unchanged.

Pin @sdcorejs/utils 1.2.5 on v19-v22 and the showcase. 1.2.5 keeps error
instanceof and name stable across bundled entry points, so a cancelled file
picker is recognised again in sd-upload-file, SdApiService.upload() and
SdExcelService.upload() in application builds. Lockfiles change only the
@sdcorejs/utils entry. sd-table.md and the [Unreleased] utils bullet describe
the rule; v20-v22 are rolled out with npm run sync.

Verification: v19 table + upload-file/api/excel specs 892/892; npm run build
(v19); npm run check:sync; eslint on the 16 changed v19 files; npm ls
@sdcorejs/utils = 1.2.5 in v19-v22 and showcase; delivery convergence
CONVERGED (all 9 acceptance criteria automated).

Refs NSP-5745

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The sdcorejs skill pack writes intermediate run output under .sdcorejs/tmp;
it is never a change artifact.

Verification: git check-ignore matches .sdcorejs/tmp/* and does not match
.sdcorejs/docs/**.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@sdcorejs
sdcorejs marked this pull request as ready for review October 2, 2026 00:12
@sdcorejs
sdcorejs merged commit 00ccf39 into main Oct 2, 2026
6 checks passed
@sdcorejs
sdcorejs deleted the fix/table-field-path-fallback branch October 2, 2026 00:12
sdcorejs pushed a commit that referenced this pull request Oct 2, 2026
Brings in #72 (table field reads, @sdcorejs/utils 1.2.5). The only
conflicts were the "Updated At" timestamps in versions/v*/SYNC-STATUS.md;
kept this branch's side. npm run sync on the merged tree produced no
content change, and npm run check:sync passes.

Verification: npm ci (v19); Karma icon, section, inform, data-state,
notify, confirm, image-editor and table specs 1128/1128.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.

2 participants