Repository navigation
feat(studio): external-object fields show their datasource and write state; no DDL controls on an external object - #27316
Merged
Conversation
…rite state; no DDL controls on an external object An object with an ADR-0015 `external` binding is never a DDL target. The object designer canvas and the field inspector now mark each field "From <datasource> · <write state>" and stop offering add field, bulk delete, rename, retype, duplicate and remove on such an object. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017ihL2c5z3q4h8inrn5kwqV
…aced beforeEach An arrow returning the mock handed vitest a cleanup hook, which called the rejecting mock after the test and failed it. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017ihL2c5z3q4h8inrn5kwqV
2 tasks
The Records grid's "+" column and the Form toolbar's Add field are not offered on an object with an ADR-0015 `external` binding, and the pillar shows where its fields come from. Reorder and the column editor stay. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017ihL2c5z3q4h8inrn5kwqV
…ield inspector; changeset names the pillar Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017ihL2c5z3q4h8inrn5kwqV
Contributor
Author
|
epic:#27261#1 · marchtian · session_017ihL2c5z3q4h8inrn5kwqV 维护者速读
席位意见:ACCEPT。PR 正文仍是第一轮文字(head 席位核对
|
9 tasks done
This was referenced Oct 29, 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.
Requested by 田騏 · project thread
Fixes #27279
Clause-②: no
Metadata-protocol: none
维护者速读
external绑定的外部对象:每个字段标「来自 数据源名 · 只读或可写」,画布顶部一条说明;不再出现「添加字段」、批量删除,字段检查器里 API 名与类型置灰、无复制与删除。external的对象的设计器界面,平台自有对象不变;不改元数据协议、不改服务端。回滚即还原本 PR。previews/external-object.tsx(判定与写入状态,含数据源读取)→previews/ObjectFormCanvas.tsx(隐藏加字段与批量删除)→inspectors/ObjectFieldInspector.tsx(ddlLocked一行决定四个控件)。pnpm --dir ui exec vitest run packages/app-shell/src/views/metadata-admin/previews/external-object.test.tsx,预期 11 passed;其中一条断言中文标记为「来自 plan_gantt · 只读」且无「添加字段」按钮。What changes
An object that carries an ADR-0015
externalbinding is never a DDL target (the runtime's own test is the same presence check,isFederatedObjectin@objectstack/objectql). The object designer underui/packages/app-shell/src/views/metadata-adminnow readsobject.external/object.datasourceand:Marks every field. Each field row on the canvas and the field inspector carry a badge "From DATASOURCE · STATE" (zh: 「来自 DATASOURCE · 只读」), and a note above the canvas names the datasource and says why fields cannot be reshaped there.
Write state, never guessed. ADR-0015 writes need both
datasource.external.allowWritesandobject.external.writable(the engine's write gate,assertWriteAllowed). Withoutwritable: trueon the object the state is settled from the object alone: Read-only, and no request is made. With it, the datasource is read through the metadata door (GET /meta/datasource/NAME, the same itemDatasourcePreviewreadsexternal.allowWritesfrom): both set ⇒ Writable, otherwise Read-only, and a datasource that cannot be read ⇒ "Writes unconfirmed" with a tooltip naming the missing half. The read is keyed on the datasource name, not on the client's identity (ui/AGENTS.mdchore: version packages #10).Hides the DDL affordances, each read from the code:
ObjectFormCanvasaddFieldObjectFormCanvasbulkDeleteObjectFieldInspectorsetKeyObjectFieldInspectorchangeTypeObjectFieldInspectorduplicateFieldObjectFieldInspectorremoveFieldThe label-to-API-name derivation (
deriveNameFor) is also off on an external object, since it renames the key. Kept: label, inline label rename, sections, ordering, bulk move-to-section, and the other display/validation settings, which change only platform metadata.Strings: six
designer.external.*rows in thestudionamespace of@object-ui/i18n(en+zh), the folder's existing i18n mechanism.Tests
previews/external-object.test.tsx(new, 11 cases): the binding reader; on the canvas, per-field and header badges "From plan_gantt · Read-only" with no datasource read, the zh mark 「来自 plan_gantt · 只读」 with no 「添加字段」, no Add field on an empty external object nor on a section header, bulk move kept and bulk delete dropped, the threewritable: trueoutcomes (allowWrites ⇒ Writable, no allowWrites ⇒ Read-only, read failure ⇒ unconfirmed); in the field inspector, API name and Type disabled, Duplicate and Remove absent, Label still editable. Each group has a platform-owned-object control case that keeps every control.Acceptance notes
views/studio-design/StudioDesignSurface.tsx(outside this card's file surface,views/metadata-admin/**) has its own add-field doors: the records grid's "+" column (onAddColumn→AddFieldPopover) and the Form layout designer'sonAddField. Its right rail reusesObjectFieldInspector, so there the badge shows and rename / retype / duplicate / remove are already gone, but the grid and form-designer "Add field" still show for an external object. Named in the dev report for a follow-up.writable: trueobjects; the canvas and the field inspector each read it once per datasource name.Verification
All readings at head
fdeadb17on a shared container.Affected tests and type-check
pnpm --dir ui exec vitest run packages/app-shell/src/views/metadata-admin/previews/external-object.test.tsx packages/app-shell/src/views/metadata-admin/previews/ObjectFormCanvas.test.tsx packages/app-shell/src/views/metadata-admin/inspectors/ packages/i18n/src/__tests__/studio-namespace.test.ts→ lock VERDICT command-exit 0, Test Files 204 passed (204), Tests 2833 passed, 1 skipped.pnpm --filter @object-ui/i18n --filter @object-ui/app-shell run type-check→ VERDICT command-exit 0 (bothtsc --noEmitandtsc -p tsconfig.test.json).pnpm --dir ui exec vitest run scripts/→ VERDICT command-exit 0, Test Files 174 passed, 2 skipped; Tests 4990 passed, 2 skipped. (An earlier run of the same command exited 1 on a 15 s timeout of the whole-tree sweep incheck-vi-mock-inherit.test.tsunder shared load; that file alone passed 83/83, and the full re-run above is green.)check:new-line-citations(0 new citations),check:i18n-dead-keys,check:i18n-keys,check:i18n-drift(6 keys added, 0 en values changed),check:control-bytes→ all exit 0.Derived gate families (dispatch-gates --commands)
node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --ran FILE→ 34 derived, 34 run, 0 NOT-MEASURED, 0 UNRUN; every command exit 0 (the list with exit codes is in the dev report). Also run outside the derivation:pnpm check:changeset-fixedexit 0. CI-owned type-check lanes and whole-tree families are left to CI.🤖 Generated with Claude Code
https://claude.ai/code/session_017ihL2c5z3q4h8inrn5kwqV