From 571fe3ef2cbd8feab87cda7e888786b506e9c6d9 Mon Sep 17 00:00:00 2001 From: johndoe6345789 Date: Sun, 18 Jan 2026 12:49:03 +0000 Subject: [PATCH] Add deprecation guidance and schema warnings --- JSON_COMPONENTS.md | 23 +++++++++++++++++++++++ json-components-registry.json | 8 ++++++-- src/lib/json-ui/component-registry.ts | 24 ++++++++++++++++++++++++ src/lib/schema-renderer.tsx | 23 +++++++++++++++++++++++ 4 files changed, 76 insertions(+), 2 deletions(-) diff --git a/JSON_COMPONENTS.md b/JSON_COMPONENTS.md index 03ae1d0..54311db 100644 --- a/JSON_COMPONENTS.md +++ b/JSON_COMPONENTS.md @@ -229,6 +229,29 @@ Priority for migration: 3. Components with good atomic design 4. Components without complex state management +## Deprecation & JSON Migration Process + +Use this process when retiring legacy components or renaming JSON component types. + +### Deprecation workflow +1. **Assess usage**: Identify schemas and component usage (search in `src/config/schemas` or project JSON). Flag any external consumers. +2. **Define a replacement**: Ensure a supported JSON-safe replacement exists (or create a wrapper) and document prop differences. +3. **Mark deprecated in the registry**: Update `json-components-registry.json` with `"status": "deprecated"` and optional `"deprecated"` metadata: + - `replacedBy`: the new component type to use. + - `message`: extra guidance for migrations. +4. **Update definitions**: If needed, adjust `src/lib/component-definitions.ts` to align defaults and prop expectations for the replacement. +5. **Communicate the change**: Add a note to release documentation or changelog and note the replacement. +6. **Set a removal window**: Target the next minor/major release for removal once migration is complete. + +### JSON migration checklist +- [ ] Replace deprecated component types in schemas with their replacements. +- [ ] Validate props against the replacement component definition. +- [ ] Run JSON renderer previews to confirm layout and bindings. +- [ ] Remove any legacy bindings or props that are no longer supported. + +### Runtime warning mechanism +The schema renderer emits a `console.warn` when a deprecated component type appears in a JSON schema. This warning uses the metadata in `json-components-registry.json` to suggest replacements and highlight remediation guidance. + ## Related Documentation - [PRD.md](./PRD.md) - Product requirements document diff --git a/json-components-registry.json b/json-components-registry.json index 94efde8..06c73dd 100644 --- a/json-components-registry.json +++ b/json-components-registry.json @@ -421,8 +421,12 @@ "category": "input", "canHaveChildren": false, "description": "Multi-line text input", - "status": "supported", - "source": "atoms" + "status": "deprecated", + "source": "atoms", + "deprecated": { + "replacedBy": "Textarea", + "message": "Prefer the shadcn/ui Textarea component for JSON schemas." + } }, { "type": "Toggle", diff --git a/src/lib/json-ui/component-registry.ts b/src/lib/json-ui/component-registry.ts index 2912d38..ba445ac 100644 --- a/src/lib/json-ui/component-registry.ts +++ b/src/lib/json-ui/component-registry.ts @@ -47,12 +47,19 @@ interface JsonRegistryEntry { type?: string export?: string source?: string + status?: string + deprecated?: DeprecatedComponentInfo } interface JsonComponentRegistry { components?: JsonRegistryEntry[] } +export interface DeprecatedComponentInfo { + replacedBy?: string + message?: string +} + const jsonRegistry = jsonComponentsRegistry as JsonComponentRegistry const buildRegistryFromNames = ( @@ -69,6 +76,19 @@ const buildRegistryFromNames = ( } const jsonRegistryEntries = jsonRegistry.components ?? [] +const deprecatedComponentInfo = jsonRegistryEntries.reduce>( + (acc, entry) => { + const entryName = entry.export ?? entry.name ?? entry.type + if (!entryName) { + return acc + } + if (entry.status === 'deprecated' || entry.deprecated) { + acc[entryName] = entry.deprecated ?? {} + } + return acc + }, + {} +) const atomRegistryNames = jsonRegistryEntries .filter((entry) => entry.source === 'atoms') .map((entry) => entry.export ?? entry.name ?? entry.type) @@ -237,3 +257,7 @@ export function getUIComponent(type: string): ComponentType | string | null export function hasComponent(type: string): boolean { return type in uiComponentRegistry } + +export function getDeprecatedComponentInfo(type: string): DeprecatedComponentInfo | null { + return deprecatedComponentInfo[type] ?? null +} diff --git a/src/lib/schema-renderer.tsx b/src/lib/schema-renderer.tsx index 136612c..02ed0fc 100644 --- a/src/lib/schema-renderer.tsx +++ b/src/lib/schema-renderer.tsx @@ -2,6 +2,7 @@ import { createElement, type ComponentType, type ReactNode } from 'react' import { cn } from '@/lib/utils' import { Component as ComponentSchema, Layout } from '@/schemas/ui-schema' import { useDataBinding, useEventHandlers, useComponentRegistry } from '@/hooks/ui' +import { getDeprecatedComponentInfo } from '@/lib/json-ui/component-registry' interface SchemaRendererProps { schema: ComponentSchema @@ -15,6 +16,26 @@ interface LayoutRendererProps { children: ReactNode } +const warnedDeprecatedComponents = new Set() + +const warnDeprecatedComponent = (schema: ComponentSchema) => { + const deprecatedInfo = getDeprecatedComponentInfo(schema.type) + if (!deprecatedInfo || warnedDeprecatedComponents.has(schema.type)) { + return + } + + const idSuffix = schema.id ? ` (id: ${schema.id})` : '' + const replacementHint = deprecatedInfo.replacedBy + ? ` Replace with "${deprecatedInfo.replacedBy}".` + : '' + const extraMessage = deprecatedInfo.message ? ` ${deprecatedInfo.message}` : '' + + console.warn( + `[SchemaRenderer] Deprecated component "${schema.type}" detected in schema${idSuffix}.${replacementHint}${extraMessage}` + ) + warnedDeprecatedComponents.add(schema.type) +} + function LayoutRenderer({ layout, children }: LayoutRendererProps) { const getLayoutClasses = () => { const classes: string[] = [] @@ -85,6 +106,8 @@ export function SchemaRenderer({ schema, data, functions = {}, componentRegistry ) } + warnDeprecatedComponent(schema) + const props = resolveProps(schema.props || {}) const events = resolveEvents(schema.events) const combinedProps = { ...props, ...events }