Repository navigation
fix(app-shell): a create flow never saves the spec seed's placeholder identity (objectui#12810) - #12847
Merged
Conversation
… identity (objectui#12810) buildCreateModeBody carries the create seed's structural defaults but no longer its placeholder identity (name, label, and any key bound to the spec's placeholder object, read from the seeds). A placeholder the type requires and the author left unset refuses Save at the client, named, before any request: a dataset with no base object is no longer saved as bound to the placeholder object. Adds the enumeration pin over every spec create seed and a page-level pin for the dataset create. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XVp19E1MYUTFM3dnkwz8gB
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 was referenced Oct 17, 2026
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 #12810
Clause-②: no (designer only; the package entry, its exports and types are unchanged)
What changes
A create flow no longer saves the spec create seed's placeholder identity. The seed module's header in
@objectstack/specsays each seed carries placeholder identity (name/label/ object binding) and that "a create flow overrides those from user input". The designer's create path spread the seed under the draft, so any of those the author left unset was saved as the seed's value. For a dataset with no base object, that was the seed's placeholder object, and every read of the dataset was then refused.buildCreateModeBody(createBody.ts) keeps the seed's structural defaults (a dataset'scountmeasure, a dashboard'swidgets, an action'stype/body, …) and drops its placeholder identity keys. Those values now come from the author's draft, or not at all.seedPlaceholderKeys:name,label, and every top-level key whose value is the spec's placeholder object. That value is read from the spec seeds (getMetadataCreateSeedoverlistMetadataCreateSeedTypes), not restated: the spec keeps itsPLACEHOLDER_OBJECTconstant andBUILTIN_METADATA_CREATE_SEEDSmodule-private, so the installed@objectstack/specexports only those two functions.mapping.targetObjectis found by its value.doSaveinResourceEditPage.tsx, used by every designer (the dataset designer has no gate of its own). After the existing empty-name refusal,unsetSeedPlaceholdersnames each placeholder key the author left blank that the LIVE server schema (the/meta/typesentry'srequired) requires. If there is one, Save is refused before any request, with the message "Set “object” before saving: a new item is never saved with the placeholder its template starts from." Reading the liverequiredkeeps this gate from being stricter than the server.engine.validation.seedPlaceholderUnset, in both tables of the designer catalogue (views/metadata-admin/i18n.ts, en-US and zh-CN).Per seed, from the enumeration pin
createBuildBodybuilds the body from the draft alone; the seed is not read (unchanged)Before this change, every "refused" and "saved without one" cell above saved the seed's value instead (
New Dataset, the placeholder object, …). A name was already refused when empty.Tests
createBody.seedPlaceholders-12810.test.ts, the enumeration pin. It iterates every entry oflistMetadataCreateSeedTypes(). (1) The per-type placeholder listing above must equal whatseedPlaceholderKeysfinds, so a new seed or a new placeholder turns it red until it is listed. (2) A placeholder object nested where the create flow cannot take it out (not top level, nocreateBuildBody) turns it red. (3) For each type, a pristine create draft yields a body with no placeholder value anywhere, and each key gets the fate its row lists. (4) Control: with the author's values set, they are carried, nothing is refused, and every other seed default is kept. It reads no source text.ResourceEditPage.seedPlaceholder-12810.test.tsx: the real page, the real dataset designer and a realMetadataClientover an in-memory server that records everyPUT. The types entry carries the spec seed and the dataset JSON schema. (a) LabelProbe Ds(Name derivesprobe_ds), no base object, Save → the refusal namesobject, and zeroPUTs. (b) With base objectcrm_accountpicked, onePUT:object: crm_account,label: Probe Ds, and no placeholder anywhere in the body.createBody.test.ts(existing): unchanged and green.Ablation
The mutation was made with
ablation-replace.mjs(--delete). It deleted the line inbuildCreateModeBodythat drops the placeholder keys. On disk: anchor count 1 → 0, blob3384b667c05e→44cc85612aac. Both new files then ran 16 failed / 19 passed: (a), all 14 seed-carrying rows of the pin's per-type test, and the datasetcounttest went red. (b), the controls andviewstayed green. After the restore, the blob equalsHEAD(3384b667c05e) andgit diff HEADis empty. A first attempt passed--replacement ''. The tool refused it as a no-op (its count did not move) and restored the file, so that run measured nothing; it is not counted.Gates
Reported in the os-dev report on the card, all on this branch's head.
Acceptance notes
measuresto[]the first time an object is picked (objectChangePatchfrom the empty value). So the normal create flow (pick an object, then save) savesmeasures: [], not the seed'scount. The page test saw this. This PR does not change that picker; it is reported to the seat.objectseed'spluralLabel(New Objects) is a label-family placeholder that the spec header does not list as identity. It is left as is; the create form derives it from the Label.Generated by Claude Code