diff --git a/.changeset/6910-retire-event-handlers-schema.md b/.changeset/6910-retire-event-handlers-schema.md new file mode 100644 index 0000000000..29b222ff49 --- /dev/null +++ b/.changeset/6910-retire-event-handlers-schema.md @@ -0,0 +1,41 @@ +--- +'@object-ui/types': minor +--- + +`EventHandlersSchema` is removed from `@object-ui/types` (objectui#6910). + +**FROM** `EventHandlersSchema`, a `z.record(z.string(), z.function())` exported +from the zod base module and re-exported from the zod barrel, **TO** *nothing*. +There is no replacement export, and deliberately so. + +**Nothing that worked stops working, because nothing could have worked.** Every +value the record accepted had to be a function, so no JSON document could ever +satisfy it, and nothing in this package composed it into a field. It could +therefore neither admit a correct authoring nor refuse a wrong one — an author +reading the published surface got no signal in either direction, which is the +shape ADR-0049 enforce-or-remove exists to delete. Ruled by the maintainer on +objectui#6124 (decision batch #8) and reconfirmed in batch #25. + +**What to author instead.** Behaviour is authored as a NODE TYPE — an `action:` +node with a declared action, the spelling PR #6498 established. The per-node +`on*` handler keys that do exist are declared through `handlerKeyRefusal()`, +which refuses every value, an authored object and a live function alike, and +carries that same remedy in its own message. The function-valued face is a +TypeScript prop shape and is untouched by this change: the `EventHandlers` +interface is still declared and still exported. + +**Not marked breaking, and that is a measurement rather than an assumption.** A +consumer census for this symbol scored zero live imports in each of objectui, +objectstack, cloud and hotcrm. The objectui and objectstack legs were re-taken +on this branch under a positive control that fires in the same corpus; the +cloud and hotcrm legs are carried forward from the published reading on +objectstack#15886 rather than re-taken here. That is a reading taken at this +commit and nothing re-derives it afterwards: a TypeScript consumer outside +those four repositories that imported the symbol gets a compile error naming +it, and the FROM/TO above is what such a consumer needs. + +⚠️ **No gate reports a second export of this shape.** Both standing instruments +are structurally blind to it — the `z.function()` census matches a +`key: z.function(` spelling and a record's VALUE type is not a key, and the zod +mirror parity ledger exempts index signatures by design. A NOTE at the former +declaration site, not a gate, is what records the absence. diff --git a/packages/types/src/__tests__/handler-keys-json-refusal-6124.test.ts b/packages/types/src/__tests__/handler-keys-json-refusal-6124.test.ts index 8e55fa8b55..3b0754e5d3 100644 --- a/packages/types/src/__tests__/handler-keys-json-refusal-6124.test.ts +++ b/packages/types/src/__tests__/handler-keys-json-refusal-6124.test.ts @@ -470,10 +470,12 @@ const RETIRED: readonly Site[] = [ const ALL_SITES: readonly Site[] = [...RUNTIME_SLOT, ...RETIRED]; -/** The nine mirror files the census covers; `base.zod.ts` holds only - * `EventHandlersSchema` (a record, objectui#6910's card) and no named key. - * `objectql.zod.ts` joined with objectui#6576 — it declared no handler key - * at all until `ObjectDataTableSchema.onRowClick`. */ +/** The nine mirror files the census covers; `base.zod.ts` is not among them — + * it declares no named handler key. The record-valued `EventHandlersSchema` + * that once stood there was never one either, and objectui#6910 retired it; + * the NOTE left at its site records why no JSON-authorable handler record + * replaces it. `objectql.zod.ts` joined with objectui#6576 — it declared no + * handler key at all until `ObjectDataTableSchema.onRowClick`. */ const MIRROR_FILES = [ 'complex.zod.ts', 'data-display.zod.ts', diff --git a/packages/types/src/__tests__/zod-mirror-parity.test.ts b/packages/types/src/__tests__/zod-mirror-parity.test.ts index 76843ae0fa..a3706d2f3a 100644 --- a/packages/types/src/__tests__/zod-mirror-parity.test.ts +++ b/packages/types/src/__tests__/zod-mirror-parity.test.ts @@ -3187,8 +3187,6 @@ const EXCLUSIONS: Readonly> = { "a bare vocabulary with no `.shape`; it is checked where a mirrored KEY declares it", 'base.zod.ts#HTMLAttributesSchema': "an index signature, not a declared key set — there are no keys to compare", - 'base.zod.ts#EventHandlersSchema': - "an index signature, not a declared key set — there are no keys to compare", 'complex.zod.ts#CalendarViewModeSchema': "a bare vocabulary with no `.shape`; it is checked where a mirrored KEY declares it", 'complex.zod.ts#DashboardWidgetTypeSchema': diff --git a/packages/types/src/zod/base.zod.ts b/packages/types/src/zod/base.zod.ts index 3e5229a96d..9b5b728e8f 100644 --- a/packages/types/src/zod/base.zod.ts +++ b/packages/types/src/zod/base.zod.ts @@ -718,9 +718,54 @@ export const ComponentConfigSchema = ComponentMetaSchema.extend({ export const HTMLAttributesSchema = z.record(z.string(), z.any()).describe('HTML attributes'); /** - * Event Handlers + * Event handlers — NOTE, not a declaration. There is deliberately no + * event-handlers const here (objectui#6910). + * + * `EventHandlersSchema`, a `z.record(z.string(), z.function())`, stood at this + * spot until objectui#6910 retired it under ADR-0049 enforce-or-remove + * (maintainer ruling on objectui#6124, decision batch #8, reconfirmed in batch + * #25). It was a published export of `@object-ui/types/zod` that **no JSON + * document could ever satisfy** — every value it accepted had to be a function + * — and that nothing in this package composed. It could therefore neither + * admit a correct authoring nor refuse a wrong one: an author reading the + * published surface got no signal in either direction, which is exactly the + * shape ADR-0049 exists to remove. + * + * Why no JSON-authorable replacement can be written here, i.e. why this is a + * NOTE and not a narrower schema: on the JSON face handlers are not values at + * all. The per-node `on*` handler keys that do exist are declared through + * `handlerKeyRefusal()` in `./tombstone.zod.ts`, which refuses EVERY value — + * an authored object and a live function alike — and carries the remedy in + * its own message: author behaviour as a NODE TYPE, an `action:` node with a + * declared action, the spelling PR #6498 established. A record of function + * values is that same unauthorable shape with the key set left open as well, + * so narrowing it could only make the refusal harder to read. The + * function-valued face is a TypeScript prop shape, declared as `EventHandlers` + * in `../base.ts`; a zod mirror of it would mirror something that never + * crosses the wire. + * + * ⚠️ `BaseSchema` declares NO `events` key, and this note asserted that it did + * until the claim was checked against the tree. AGENTS.md's abridged protocol + * sketch shows `events?: Record` and its action-system + * commandment authors one, but `BaseSchemaCore` declares no such member and + * nothing reads `schema.events`: whatever a document writes under that key, + * no renderer runs it. `BaseSchemaCore` is `.passthrough()`, so such a node is + * KEPT, judged by nothing and run by nothing. ⛔ Do not send an author there. + * ⛔ No count of authored `events` keys is stated here — objectui#9553 carries + * that census. A census answer frozen into a comment is the defect AGENTS.md + * commandment #9 forbids, and this note shipped one once already: the first + * version of this paragraph named a total that was wrong on the day it was + * written, and it reached the emitted `.d.ts` before review caught it. + * + * ⚠️ Do not conclude from a clean sweep that no second one of these exists. + * Both standing instruments are structurally blind to this shape: the + * `z.function()` census matches the `key: z.function(` spelling and a record's + * VALUE type is not a key, and `../__tests__/zod-mirror-parity.test.ts` + * exempts index signatures by design ("no keys to compare"). This note, not a + * gate, is what records the absence. + * + * Precedent of the same shape: objectstack#12009 / PR #13413. */ -export const EventHandlersSchema = z.record(z.string(), z.function()).describe('Event handlers'); /** * The two CSS passthrough attributes a node exposes: a Tailwind class string and diff --git a/packages/types/src/zod/index.zod.ts b/packages/types/src/zod/index.zod.ts index 34b4476d06..31ad271596 100644 --- a/packages/types/src/zod/index.zod.ts +++ b/packages/types/src/zod/index.zod.ts @@ -80,7 +80,6 @@ export { ComponentMetaSchema, ComponentConfigSchema, HTMLAttributesSchema, - EventHandlersSchema, ClassNameStylePropsSchema, } from './base.zod.js';