diff --git a/.changeset/componentinput-reexport-4972.md b/.changeset/componentinput-reexport-4972.md new file mode 100644 index 000000000..910e0a734 --- /dev/null +++ b/.changeset/componentinput-reexport-4972.md @@ -0,0 +1,40 @@ +--- +'@object-ui/core': minor +'@object-ui/types': minor +--- + +`ComponentInput` is now declared once and re-exported, instead of restated in three +places (objectui#4972). + +`@object-ui/core`'s `ComponentInput` (`registry/Registry.ts`) and `@object-ui/types`' +plugin-scoped `ComponentInput` (`plugin-scope.ts`, published as `PluginComponentInput`) +were structural copies of the interface in `@object-ui/types`' `base.ts`. Both are now +re-exports of that one declaration, which is the disposition objectui#4580 ruled for the +identical shape — *a structural copy would reproduce the defect the moment either side +moved* — and the way `core/src/types/index.ts` already handles `SchemaNode`. + +Either side had already moved. `base.ts` declared thirteen keys; both copies declared +nine, so `min` / `max` / `step` / `placeholder` were missing from **the copy every +component registration actually imports**. Those four keys were unwritable at any real +registration — a plain TypeScript error at the call site — while `ComponentInputSchema` +(the zod schema) and `ComponentMeta.inputs` both accepted them. The publication face +advertised four keys the authoring face rejected. Measured over the repository, no +registration had tried to write one yet, so nothing a user hits was broken today; what +changes is that the four keys become writable, and there is no longer a second +declaration for the next widening to miss. + +`ComponentInput`'s arm vocabulary (`ComponentInputControlType`) was already a single +declaration imported by all three sites (objectui#3832); this converges the rest of the +interface. + +Measured, not assumed: `@object-ui/core`'s published entry `dist/index.d.ts` is +byte-identical across the change (sha256 `f6494f80…`, both legs). That gauge is reported +here only with its control — a probe that added a *required* key to `ComponentInput` left +the same file byte-identical, because `dist/index.d.ts` is a 63-line barrel of +`export *` lines that names `ComponentInput` zero times. The gauge that can actually fail +is the emitted declaration file: `dist/registry/Registry.d.ts` changes, as does +`@object-ui/types`' `dist/plugin-scope.d.ts`, and those two files are the *only* emitted +declarations that change in either package. + +`WidgetInput`'s union-arm capability is deliberately untouched — a different gate path +and a separate judgment. diff --git a/packages/core/src/registry/Registry.ts b/packages/core/src/registry/Registry.ts index 1e8dc6cec..ba2d0ea16 100644 --- a/packages/core/src/registry/Registry.ts +++ b/packages/core/src/registry/Registry.ts @@ -6,7 +6,7 @@ * LICENSE file in the root directory of this source tree. */ -import type { ComponentInputControlType } from '@object-ui/types'; +import type { ComponentInput } from '@object-ui/types'; import { PUBLIC_BLOCKS } from './public-blocks.js'; export type ComponentRenderer = T; @@ -15,29 +15,24 @@ export type ComponentRenderer = T; * What a registration DECLARES about one authorable prop. * * This is the declaration the component registrations themselves import, so it - * is the one an author's manifest is ultimately built from. It is structurally - * the third copy of `ComponentInput` (the others live in the types package's - * `base.ts` and `plugin-scope.ts`); the arm vocabulary of `type` is imported - * from there rather than re-spelled, so the union widening of objectui#3832 - * cannot land on two of the three and drift. + * is the one an author's manifest is ultimately built from — and it is now + * RE-EXPORTED from `@object-ui/types` rather than restated here + * (objectui#4972), the disposition objectui#4580 ruled for the identical + * shape: *a structural copy would reproduce the defect the moment either side + * moved.* This package already depends on `@object-ui/types`, so the edge + * exists and adds no cycle, and `src/types/index.ts` re-exports `SchemaNode` + * from there the same way. + * + * The copy this replaces had ALREADY moved, which is why the card is not + * hypothetical: it carried nine keys while `base.ts` carried thirteen, so + * `min` / `max` / `step` / `placeholder` were missing from *the copy every + * registration actually imports*. Those four keys were therefore unwritable at + * any real registration — a plain TS error — while `ComponentInputSchema` (the + * zod schema) and `ComponentMeta.inputs` both accepted them. The publication + * face advertised four keys the authoring face rejected; the divergence was + * dormant only because no registration had tried to write one yet. */ -export type ComponentInput = { - name: string; - /** - * Input control type — one coarse kind, or an array of them when the key's - * contract is a union (objectui#3832). A value passes the manifest gate when - * ANY declared arm accepts it; a value matching none is still reported. Full - * semantics: `ComponentInput.type` in the types package's `base.ts`. - */ - type: ComponentInputControlType | ComponentInputControlType[]; - label?: string; - defaultValue?: any; - required?: boolean; - enum?: string[] | { label: string; value: any }[]; - description?: string; - advanced?: boolean; - inputType?: string; -}; +export type { ComponentInput } from '@object-ui/types'; export type ComponentMeta = { label?: string; // Display name in designer diff --git a/packages/types/src/plugin-scope.ts b/packages/types/src/plugin-scope.ts index 2e2d916f4..513660949 100644 --- a/packages/types/src/plugin-scope.ts +++ b/packages/types/src/plugin-scope.ts @@ -16,7 +16,7 @@ * @packageDocumentation */ -import type { ComponentInputControlType } from './base.js'; +import type { ComponentInput } from './base.js'; /** * Plugin Scope Interface @@ -168,28 +168,15 @@ export interface ComponentMeta { /** * Component input definition * - * The plugin-scoped twin of `base.ts`' {@link ComponentInput}. The arm - * vocabulary is IMPORTED from there rather than re-spelled (objectui#3832): - * the two interfaces already have to move together, and a second copy of the - * eleven literals is the copy that drifts — the hazard objectui#4580's ruling - * settled by re-exporting one declaration instead of restating it. + * The plugin-scoped twin of `base.ts`' {@link ComponentInput} is no longer a + * twin: it is the SAME declaration, RE-EXPORTED rather than restated + * (objectui#4972). Only the arm vocabulary was shared before (objectui#3832); + * this finishes the job for the rest of the interface, per objectui#4580's + * ruling — *a structural copy would reproduce the defect the moment either + * side moved.* Re-exported under this name so that `index.ts`' public + * `ComponentInput as PluginComponentInput` alias keeps naming a real export. */ -export interface ComponentInput { - name: string; - /** - * Input control type — one coarse kind, or an array of them for a union key. - * Semantics, the array form's rules and why it exists: see - * `ComponentInput.type` in `base.ts`. - */ - type: ComponentInputControlType | ComponentInputControlType[]; - label?: string; - defaultValue?: any; - required?: boolean; - enum?: string[] | { label: string; value: any }[]; - description?: string; - advanced?: boolean; - inputType?: string; -} +export type { ComponentInput } from './base.js'; /** * Event handler type