Repository navigation
fix(plugin-grid): the import preview reads dates, rating/slider/progress/toggle and email as the server does (objectui#11889) - #11911
Merged
objectstack-fleet[bot] merged 3 commits intoOct 8, 2026
Conversation
…olean types, and email as the server does The cell check now marks a cell exactly where the server's import refuses it: - a date / datetime cell is read by a mirror of core's parseDateCell grammar and supported years, so 07/15/2026, July 15, 2026 and 1/2/26 are marked; - the boolean and numeric arms key on the spec's BOOLEAN_VALUE_TYPES and NUMERIC_VALUE_TYPES, so toggle, rating, slider and progress are checked; - an email cell is read by the record validator's EMAIL_RE, so a non-ASCII domain is no longer marked. Claude-Session: https://claude.ai/code/session_01DrKzdPdyLLBW3qpZ4vtk7z Co-authored-by: Claude <noreply@anthropic.com>
… (objectui#11889) Claude-Session: https://claude.ai/code/session_01DrKzdPdyLLBW3qpZ4vtk7z Co-authored-by: Claude <noreply@anthropic.com>
Contributor
✅ Console Performance Budget
The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it. 📦 Bundle Size Report
Size Limits
|
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.
Fixes #11889
Clause-②: no
What this changes
The Import Wizard preview's cell check (
checkImportCellinpackages/plugin-grid/src/ImportWizard.tsx) now marks a cell exactly where the server's import refuses it on the three legs the card names, so the import button (which counts the rows nobody flagged) counts what the import will write.date/datetimecell is judged byisImportableDateCellinimportCoercionContract.ts, a mirror of@objectstack/core'sparseDateCellgrammar (readIsoTemporalCell, thenreadYearFirstCell, withnamesRealCalendarDayand the clock ranges) plus core's supported years, which the engine's write validation applies to the stored value.07/15/2026,July 15, 2026and1/2/26are now markedinvalid_date;2026-07-15and2026/7/15are taken. The spec publishes neither the grammar nor the years, so both are restated beside the boolean tokens, with a paired inventory inimportCoercionContract.test.tsas the tripwire. A zone-bearing ISO cell is judged with the UTC setters, never with the browser's own date parser.BOOLEAN_VALUE_TYPESandNUMERIC_VALUE_TYPESfrom@objectstack/spec/data, the sets the server'scoerceFieldValuereads, instead of literal case lists. The arms run in the server's order (boolean, numeric, date, then the rest).emailcell is judged byisRecordEmail, a one-pass restatement of the record validator'sEMAIL_RE, which takes735431496@柴仟.comand still refusesa@b.isPlausibleEmail(the identity rule, not a package export) is removed: see the measurement below.No export, prop, accepted input or sentence changes;
cellRefusalMessageis untouched. Changeset:.changeset/11889-import-cell-check.md(@object-ui/plugin-gridpatch).What was measured
All server sources read at the tag
@objectstack/core@17.7.0(the same commit as@objectstack/objectql@17.7.0and@objectstack/spec@17.7.0,4e4e8814).@objectstack/spec17.7.0:NUMERIC_VALUE_TYPES= number, currency, percent, rating, slider, progress, summary;BOOLEAN_VALUE_TYPES= boolean, toggle. The range floor^17.5.0exports both as well (the 17.5.0 tarball'sdataentry), andcheck:spec-floorsjudged the built plugin-grid with no finding.date/datetime,parseDateCelltakesreadIsoTemporalCell(s) ?? readYearFirstCell(s)and nothing else. The supported years (date0001 to 9999,datetime1000 to 9999) are refused in two places, both withinvalid_date: at coercion only for a cell the reader already refuses (outsideYearschanges the sentence, not the verdict), and at the engine's write validation for a cell the reader takes (0500-07-15into adatetime). The mirror carries both. Atimecell has its own reader, and the preview does reachtime: see "Not in this PR".isImportableDateCellwith the published@objectstack/core17.7.0coerceFieldValuefollowed by the write door's temporal rule, over 43,212 (cell, kind) pairs (the server takes 3,395 of them). Disagreements: 0, under three host zones (UTC, Asia/Shanghai, America/New_York). Control: the oldDate.parserule disagrees on 16,107 of the same pairs, so the comparison can fail. The probe is not committed; the inventory is.summary): harmless. Neither host offers asummarytarget:importTargetFieldsdropsformula/summary, andExcelImportBardropsformula/summary/autonumber. The server's coercion reads the same set, so a host that did pass one would get the server's answer.record-validator.tsdeclaresEMAIL_RE = /^[^\s@]+@[^\s@.]+(?:\.[^\s@.]+)+$/and anemailcell passes coercion untouched. The mirror is a single pass (no pattern, no backtracking), andimportEmailValidation.test.tscompares it with that literal and keeps the adversarial-input timing pin.ObjectViewwiressys_userto/api/v1/auth/admin/import-usersfor an admin. But that target's email column reaches the wizard typedtext(identityImportFields), socheckImportCell's email arm never ran on it, before or after this PR. The identity endpoint appliesisLikelyEmailin its own dry run (its identity pre-validation runs fordryRun). So the record validator's rule applies alone in the email arm, andisPlausibleEmailhad no caller left.Tests
On
2867a40(this branch merged withorigin/main9844bbf):pnpm --workspace-concurrency=2 --filter "@object-ui/plugin-grid..." build: exit 0 (15 of 47 projects).pnpm --filter @object-ui/plugin-grid type-check: exit 0. The test program (tsconfig.test.json) lists all three edited test files.pnpm exec vitest run packages/plugin-grid/: 193 files, 1818 tests passed. This includes everyImportWizard*,importCoercionContract*,importParsers*andimportEmailValidation*suite. There is no*.guard.test.*in the package.check:control-bytes,check:new-line-citations(0 new),check:changeset-claims,check:pending-changeset-literals,check:spec-symbols,check:installed-pin-claims,check:phantom-deps,check:test-path-roots,check-changeset-presence,check-changeset-no-major: all exit 0.check:spec-floors: exit 1, NOT MEASURED for the workspace. All 13 findings areno-artifact, for packages outside this build closure. plugin-grid was built and judged, with no finding.New pins (
ImportWizard.cellCheck-11889.test.tsx): each spelling the card names, with a control per leg. The preview marks the cells and the import button readsImport 1 Rowfor each leg.Reverse check per leg. Each fix was committed first, then mutated through
ablation-replace.mjs(anchor hit 1 to 0 on disk, blob changed) and restored (blob equalsHEAD,git diff HEADempty):Date.parsedate 07/15/2026: expected undefined to deeply equal { code: 'invalid_date' …}, and the preview's row 2 date not markedbooleanandnumber/currency/percentcase listsexpected { code: 'invalid_email' … } to be undefined, and the preview's non-ASCII row markedThe first email run never acquired the shared verify lock (queue timeout, exit 99, tree restored), so it measured nothing. The second run is the one above.
Acceptance notes (not changed here)
0500-07-15in adatetime) reads "is not a valid date" in the preview, where the server names the range. A range sentence needs a newgrid.import.*key, andpackages/i18nis outside this card's fence. Handover: none.datetimeis read as UTC. The server reads it in the importing user's business timezone, which the wizard does not know. The two disagree only within a day of year 1000 or 9999.@objectstack/specexportsIMPORT_BOOLEAN_TRUE_TOKENS/IMPORT_BOOLEAN_FALSE_TOKENS(at 17.5.0 and 17.7.0) andIMPORT_REFERENCE_TYPES.importCoercionContract.tsstill mirrors the tokens under a "not published yet" note. The contents are identical today, so nothing is wrong yet. Handover: none.min/maxare not judged by the preview for any numeric type, as before, because the wizard's field shape does not carry them. The dry run judges them.Not in this PR (reported to the seat)
timecolumn is not checked.importTargetFieldspassestimefields through. The preview takes every cell (25:00,abc,10:00Z,9amall measured as taken), while the published 17.7.0 server refuses those four withinvalid_time. A fix needs core'stimerule mirrored and aninvalid_timerefusal with a sentence, which is outside this card's fence.text, so before Validate the button counts a row the identity endpoint refuses (INVALID_EMAIL).Session:
https://claude.ai/code/session_01DrKzdPdyLLBW3qpZ4vtk7zGenerated by Claude Code