From eaf4029162428b4d080ff2fcb368247ef17732d5 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 25 Aug 2026 05:45:44 +0000 Subject: [PATCH 1/2] refactor(app-shell): delete dead metadataConverters module `packages/app-shell/src/utils/metadataConverters.ts` has zero importers, is not re-exported from the package barrel, and no `exports` subpath reaches it. Enforce-or-remove: it is not merely unused, it is a copy-paste source for two defects this lane just repaired --- a name-heuristic `isSystem` and a three-way `referenceTo` tolerance. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01CSoz9uGhaaSgiq3hshtN7L --- .../app-shell/src/utils/metadataConverters.ts | 139 ------------------ 1 file changed, 139 deletions(-) delete mode 100644 packages/app-shell/src/utils/metadataConverters.ts diff --git a/packages/app-shell/src/utils/metadataConverters.ts b/packages/app-shell/src/utils/metadataConverters.ts deleted file mode 100644 index 36e085f972..0000000000 --- a/packages/app-shell/src/utils/metadataConverters.ts +++ /dev/null @@ -1,139 +0,0 @@ -/** - * Metadata Converters - * - * Shared conversion functions for transforming raw metadata API objects - * (from the ObjectStack spec) to the UI types used by ObjectManager and - * FieldDesigner components. - * - * Extracted from ObjectManagerPage to enable reuse across pages. - * - * @module utils/metadataConverters - */ - -import type { ObjectDefinition, ObjectDefinitionRelationship, DesignerFieldDefinition, DesignerFieldType } from '@object-ui/types'; - -// --------------------------------------------------------------------------- -// Raw metadata shapes (from the ObjectStack API) -// --------------------------------------------------------------------------- - -/** Loose shape of a metadata object definition from the ObjectStack API. */ -export interface MetadataObject { - name?: string; - label?: string | { defaultValue?: string; key?: string }; - pluralLabel?: string; - plural_label?: string; - description?: string | { defaultValue?: string }; - icon?: string; - enabled?: boolean; - fields?: MetadataField[] | Record; - relationships?: Array<{ - object?: string; - relatedObject?: string; - type?: string; - label?: string; - name?: string; - foreign_key?: string; - foreignKey?: string; - }>; -} - -/** Loose shape of a metadata field definition from the ObjectStack API. */ -export interface MetadataField { - name?: string; - label?: string | { defaultValue?: string; key?: string }; - type?: string; - group?: string; - description?: string; - help?: string; - required?: boolean; - unique?: boolean; - readonly?: boolean; - hidden?: boolean; - defaultValue?: string; - default_value?: string; - placeholder?: string; - options?: Array; - externalId?: boolean; - trackHistory?: boolean; - track_history?: boolean; - // No `indexed` (objectui#4644): never a `FieldSchema` key, so the server - // never serves one — `FieldSchema.safeParse` rejects it by name. Reading it - // here only fed it back to a writer that then got a 422 on save. - reference_to?: string; - /** ObjectStack-convention key for the relational target (what the server serves). */ - reference?: string; - referenceTo?: string; - formula?: string; -} - -// --------------------------------------------------------------------------- -// Converters -// --------------------------------------------------------------------------- - -/** - * Convert a metadata object definition (from the API/spec) to the ObjectDefinition - * type used by the ObjectManager component. - */ -export function toObjectDefinition(obj: MetadataObject, index: number): ObjectDefinition { - const fields = Array.isArray(obj.fields) ? obj.fields : Object.values(obj.fields || {}); - return { - id: obj.name || `obj_${index}`, - name: obj.name || '', - label: typeof obj.label === 'object' ? obj.label.defaultValue || obj.label.key || '' : (obj.label || obj.name || ''), - pluralLabel: obj.pluralLabel || obj.plural_label || undefined, - description: typeof obj.description === 'object' ? obj.description.defaultValue : (obj.description || undefined), - icon: obj.icon || undefined, - // `group` and `sortOrder` are DISPLAY values of the Object Manager, derived - // here and belonging to the UI model only (objectui#6223). `ObjectSchema` - // has no object-level grouping or ordering key and refuses both BY NAME, so - // they must never be copied into an object payload — see the tombstones on - // `ObjectMetadataPayload`. Note what populates them: the `sys_` prefix and - // the array index, i.e. facts about this list, not about the object. - group: obj.name?.startsWith('sys_') ? 'System Objects' : 'Custom Objects', - sortOrder: index, - isSystem: obj.name?.startsWith('sys_') || false, - fieldCount: fields.length, - relationships: Array.isArray(obj.relationships) - ? obj.relationships.map((r) => ({ - relatedObject: r.object || r.relatedObject || '', - type: (r.type || 'one-to-many') as ObjectDefinitionRelationship['type'], - label: r.label || r.name || undefined, - foreignKey: r.foreign_key || r.foreignKey || undefined, - })) - : undefined, - }; -} - -/** - * Convert a metadata field definition to the DesignerFieldDefinition - * type used by the FieldDesigner component. - */ -export function toFieldDefinition(field: MetadataField, index: number): DesignerFieldDefinition { - return { - id: field.name || `fld_${index}`, - name: field.name || '', - label: typeof field.label === 'object' ? field.label.defaultValue || field.label.key || '' : (field.label || field.name || ''), - type: (field.type || 'text') as DesignerFieldType, - group: field.group || undefined, - sortOrder: index, - description: field.description || field.help || undefined, - required: field.required || false, - unique: field.unique || false, - readonly: field.readonly || false, - hidden: field.hidden || false, - defaultValue: field.defaultValue || field.default_value || undefined, - placeholder: field.placeholder || undefined, - options: Array.isArray(field.options) - ? field.options.map((opt) => - typeof opt === 'string' - ? { label: opt, value: opt } - : { label: opt.label || opt.value, value: opt.value, color: opt.color } - ) - : undefined, - isSystem: field.readonly === true && (field.name === 'id' || field.name === 'createdAt' || field.name === 'updatedAt'), - externalId: field.externalId || false, - trackHistory: field.trackHistory || field.track_history || false, - referenceTo: field.reference_to || field.reference || field.referenceTo || undefined, - formula: field.formula || undefined, - }; -} From 4473c31498fd8e14f107ffebeddbd39f1294913b Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 25 Aug 2026 05:51:03 +0000 Subject: [PATCH 2/2] chore: add changeset for the metadataConverters deletion Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01CSoz9uGhaaSgiq3hshtN7L --- .changeset/dead-metadata-converters-6224.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 .changeset/dead-metadata-converters-6224.md diff --git a/.changeset/dead-metadata-converters-6224.md b/.changeset/dead-metadata-converters-6224.md new file mode 100644 index 0000000000..63c5a43b3d --- /dev/null +++ b/.changeset/dead-metadata-converters-6224.md @@ -0,0 +1,12 @@ +--- +'@object-ui/app-shell': patch +--- + +Delete the dead `src/utils/metadataConverters.ts` module. It had zero importers, was not +re-exported from the package barrel, and no `exports` subpath reached it — `toObjectDefinition`, +`toFieldDefinition`, `MetadataObject` and `MetadataField` were never part of the published +surface, so nothing external can break. The module was removed rather than left alone because it +carried two patterns the live code no longer uses: a name-heuristic `isSystem` (the server's real +`system` flag is the source of truth) and a three-way `referenceTo` tolerance for a target the +spec spells `reference`. A dead copy that disagrees with the live one is what a future author +copies from.