Skip to content

[finding] ComponentMeta has two published declarations (base.ts + plugin-scope.ts), already diverged by tags/description, and the PluginComponentMeta alias has zero consumers #5893

Description

@claude

Noticed while retiring PluginComponentInput (#5674). Filed rather than fixed: it is out of that card's fence, and it is not the same shape as PluginComponentInput despite sitting on the adjacent line.

Measured

packages/types/src/index.ts publishes ComponentMeta twice, from two different declarations:

line spelling declaration
index.ts:99 ComponentMeta packages/types/src/base.ts:511
index.ts:921 ComponentMeta as PluginComponentMeta packages/types/src/plugin-scope.ts:149

These are structural copies, not an alias pair — which is exactly what makes this different from #5674. PluginComponentInput became a pure alias once #5671 converged its declaration; PluginComponentMeta still names a genuinely separate interface with a different key set.

The divergence is already live

Top-level keys, both declarations read off origin/main:

  • base.ts (11): label icon category inputs defaultProps examples isContainer resizable resizeConstraints tags description
  • plugin-scope.ts (9): the same nine, minus tags and description

resizeConstraints' six members are identical in both. So the delta is exactly two keys, and it is the same defect class #4972 recorded for ComponentInput — where the delta was min/max/step/placeholder — one release before it bit.

Why it is worth recording

#4580's ruling was written for this shape, and the wording is general: "a structural copy would reproduce the defect the moment either side moved." Either side has moved: tags and description exist on the published ComponentMeta and not on the plugin-facing twin, so a plugin author typing against the plugin-scope declaration cannot write two keys the main surface advertises.

There is already a test paying for the duplication. packages/types/src/__tests__/default-children-retired-contract-twins.test.ts asserts the same contract twice — once against ComponentMeta from base.ts (line 116) and once against ComponentMeta from plugin-scope.ts (line 131) — and its own header calls the second one "its plugin-facing twin". That file is the running cost of the copy.

Note this is not covered by #4972, which is closed and was scoped to ComponentInput's three copies plus WidgetInput. ComponentMeta is named nowhere in it.

Zero consumers at the published alias name

PluginComponentMeta has one occurrence repo-wide excluding node_modules//dist/: its own export line at index.ts:921. Nothing imports it.

Search scope: every root in the repo (packages/ apps/ content/ docs/ skills/ examples/ e2e/ scripts/ eslint-rules/ public/ .changeset/ and the root *.md), plus the sibling objectstack framework checkout. Control, searched identically so a broken search could not read as a clean one: AppMetadataPlugin, a neighbour in the same export type { ... } block, returns 12 hits including a real cross-package import at packages/core/src/registry/PluginSystem.ts:10; in the framework checkout the control SchemaRenderer returns 30 files and @object-ui/types 23. The apparatus finds names that are there.

The in-repo half is measurable; an importer on npm is not. That distinction is what #5674 was filed about and it applies here unchanged.

Possible directions

Not urgent: no user hits this today, the same way #4972's divergence was dormant until it wasn't. Recording it while the measurement is fresh.

Related: #4580 / #4548 (the ruling and the 19/35 probe), #4972 (the ComponentInput census), #5671 (the convergence PR), #5674 (the alias retirement this was found under).

Filed unassigned.


Generated by Claude Code


Generated by Claude Code

Metadata

Metadata

Assignees

Labels

domain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatpm:dispatched

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions