From da0304790578463ad490fd7f639f674b383a2097 Mon Sep 17 00:00:00 2001 From: Daniel Winter Date: Fri, 12 Dec 2025 07:54:04 +0100 Subject: [PATCH] Remove unused locale support from SDK MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Locale/i18n support was scaffolded but never implemented - see Preview.ts:398 which explicitly passed `undefined // locale not supported yet`. Removed from: - Types (StudioMessage, SDKMessage, FieldUpdateBase, ElementAttributes, etc.) - Core modules (Preview, FieldRegistry, ContentUpdater, OverlayManager) - Attribute helpers (createPreviewAttributes, PreviewFieldOptions) - React components (HygraphPreview, HygraphPreviewNextjs) - Tests (removed locale-specific test, updated attribute test) No breaking changes - locale was never documented or functional. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- src/core/ContentUpdater.test.ts | 27 --------------------------- src/core/ContentUpdater.ts | 10 +++------- src/core/FieldRegistry.ts | 27 ++++++++++----------------- src/core/OverlayManager.ts | 2 -- src/core/Preview.ts | 23 ++++++----------------- src/core/attributes.test.ts | 2 -- src/core/attributes.ts | 7 +------ src/react/HygraphPreview.tsx | 2 +- src/react/HygraphPreviewNextjs.tsx | 3 +-- src/types/index.ts | 14 ++++---------- 10 files changed, 26 insertions(+), 91 deletions(-) diff --git a/src/core/ContentUpdater.test.ts b/src/core/ContentUpdater.test.ts index ae8d2c7..f257102 100644 --- a/src/core/ContentUpdater.test.ts +++ b/src/core/ContentUpdater.test.ts @@ -44,33 +44,6 @@ describe('ContentUpdater', () => { expect(result.error).toBe('No matching elements found'); }); - it('respects locale when selecting elements', async () => { - const element = createPreviewElement({ - entryId: 'entry-locale', - fieldApiId: 'title', - locale: 'en', - textContent: 'Hello', - }); - - createPreviewElement({ - entryId: 'entry-locale', - fieldApiId: 'title', - locale: 'de', - textContent: 'Hallo', - }); - - const result = await updater.updateField({ - entryId: 'entry-locale', - fieldApiId: 'title', - locale: 'en', - fieldType: 'STRING', - newValue: 'Updated EN', - }); - - expect(result.success).toBe(true); - expect(element.textContent).toBe('Updated EN'); - }); - it('applies multi-format rich text updates based on element preference', async () => { const element = createPreviewElement({ entryId: 'entry-rich-text', diff --git a/src/core/ContentUpdater.ts b/src/core/ContentUpdater.ts index 1a622a7..cb0d7e1 100644 --- a/src/core/ContentUpdater.ts +++ b/src/core/ContentUpdater.ts @@ -36,7 +36,7 @@ export class ContentUpdater { try { // Debounce updates - const updateKey = `${update.entryId}:${update.fieldApiId}:${update.locale || ''}`; + const updateKey = `${update.entryId}:${update.fieldApiId}`; this.updateQueue.set(updateKey, update); // Wait for debounce delay @@ -52,7 +52,7 @@ export class ContentUpdater { this.updateQueue.delete(updateKey); // Find target elements - const elements = this.findElements(update.entryId, update.fieldApiId, update.locale); + const elements = this.findElements(update.entryId, update.fieldApiId); if (elements.length === 0) { return { success: false, error: 'No matching elements found' }; } @@ -79,7 +79,6 @@ export class ContentUpdater { console.log('[ContentUpdater] Updated field:', { entryId: update.entryId, fieldApiId: update.fieldApiId, - locale: update.locale, elementsCount: elements.length, }); } @@ -101,7 +100,7 @@ export class ContentUpdater { this.updateQueue.clear(); } - private findElements(entryId: string, fieldApiId?: string, locale?: string): HTMLElement[] { + private findElements(entryId: string, fieldApiId?: string): HTMLElement[] { const elements: HTMLElement[] = []; // Build selector @@ -109,9 +108,6 @@ export class ContentUpdater { if (fieldApiId) { selector += `[data-hygraph-field-api-id="${fieldApiId}"]`; } - if (locale) { - selector += `[data-hygraph-field-locale="${locale}"]`; - } const found = document.querySelectorAll(selector); elements.push(...Array.from(found)); diff --git a/src/core/FieldRegistry.ts b/src/core/FieldRegistry.ts index 154de16..c7f5912 100644 --- a/src/core/FieldRegistry.ts +++ b/src/core/FieldRegistry.ts @@ -25,13 +25,13 @@ export class FieldRegistry { /** * Get all elements for a specific field */ - getElementsForField(fieldApiId: string, locale?: string): RegisteredElement[] { + getElementsForField(fieldApiId: string): RegisteredElement[] { const elements: RegisteredElement[] = []; - // Search through all registry entries for matching fieldApiId and locale + // Search through all registry entries for matching fieldApiId for (const elementList of Object.values(this.registry)) { for (const element of elementList) { - if (element.fieldApiId === fieldApiId && element.locale === locale) { + if (element.fieldApiId === fieldApiId) { elements.push(element); } } @@ -43,15 +43,13 @@ export class FieldRegistry { /** * Get elements for a specific entry + field combination */ - getElementsForEntryField(entryId: string, fieldApiId: string, locale?: string): RegisteredElement[] { + getElementsForEntryField(entryId: string, fieldApiId: string): RegisteredElement[] { const elements: RegisteredElement[] = []; - // Search through all registry entries for matching entryId, fieldApiId, and locale + // Search through all registry entries for matching entryId and fieldApiId for (const elementList of Object.values(this.registry)) { for (const element of elementList) { - if (element.entryId === entryId && - element.fieldApiId === fieldApiId && - element.locale === locale) { + if (element.entryId === entryId && element.fieldApiId === fieldApiId) { elements.push(element); } } @@ -80,8 +78,8 @@ export class FieldRegistry { /** * Get specific element by exact match */ - getElement(entryId: string, fieldApiId?: string, locale?: string): RegisteredElement | null { - const key = this.createRegistryKey(entryId, fieldApiId, locale); + getElement(entryId: string, fieldApiId?: string): RegisteredElement | null { + const key = this.createRegistryKey(entryId, fieldApiId); const elements = this.registry[key]; return elements?.[0] || null; } @@ -132,7 +130,6 @@ export class FieldRegistry { attributeFilter: [ 'data-hygraph-entry-id', 'data-hygraph-field-api-id', - 'data-hygraph-field-locale', 'data-hygraph-component-chain', ], }); @@ -162,19 +159,17 @@ export class FieldRegistry { if (!entryId) return; const fieldApiId = element.getAttribute('data-hygraph-field-api-id') || undefined; - const locale = element.getAttribute('data-hygraph-field-locale') || undefined; const componentChainRaw = element.getAttribute('data-hygraph-component-chain') || undefined; const registeredElement: RegisteredElement = { element, entryId, fieldApiId, - locale, componentChainRaw, lastUpdated: Date.now(), }; - const key = this.createRegistryKey(entryId, fieldApiId, locale); + const key = this.createRegistryKey(entryId, fieldApiId); // Initialize array if it doesn't exist if (!this.registry[key]) { @@ -195,7 +190,6 @@ export class FieldRegistry { console.log(`[FieldRegistry] Registered element:`, { entryId, fieldApiId, - locale, element: element.tagName, }); } @@ -222,10 +216,9 @@ export class FieldRegistry { } } - private createRegistryKey(entryId: string, fieldApiId?: string, locale?: string): RegistryKey { + private createRegistryKey(entryId: string, fieldApiId?: string): RegistryKey { const parts = [entryId]; if (fieldApiId) parts.push(fieldApiId); - if (locale) parts.push(locale); return parts.join(':'); } diff --git a/src/core/OverlayManager.ts b/src/core/OverlayManager.ts index b9cb29f..75cc0d6 100644 --- a/src/core/OverlayManager.ts +++ b/src/core/OverlayManager.ts @@ -193,14 +193,12 @@ export class OverlayManager { // Get registered element data const entryId = hygraphElement.getAttribute('data-hygraph-entry-id'); const fieldApiId = hygraphElement.getAttribute('data-hygraph-field-api-id'); - const locale = hygraphElement.getAttribute('data-hygraph-field-locale'); if (entryId) { const registeredElement: RegisteredElement = { element: hygraphElement, entryId, fieldApiId: fieldApiId || undefined, - locale: locale || undefined, }; // Show overlay immediately diff --git a/src/core/Preview.ts b/src/core/Preview.ts index 43ada47..8fb117c 100644 --- a/src/core/Preview.ts +++ b/src/core/Preview.ts @@ -258,10 +258,9 @@ export class Preview { const entryId = element.getAttribute('data-hygraph-entry-id'); const fieldApiId = element.getAttribute('data-hygraph-field-api-id'); const format = element.getAttribute('data-hygraph-rich-text-format') as RichTextFormatType; - const locale = element.getAttribute('data-hygraph-field-locale') || ''; if (entryId && fieldApiId && format && ['html', 'markdown', 'text'].includes(format)) { - const fieldKey = `${entryId}:${fieldApiId}:${locale}`; + const fieldKey = `${entryId}:${fieldApiId}`; // Check for duplicate field usage (UNSUPPORTED) if (formatPreferences[fieldKey]) { @@ -373,20 +372,18 @@ export class Preview { entryId: message.entryId, fieldApiId: message.fieldApiId, componentChain: message.componentChain, - locale: message.locale, }); // Emit event for listeners this.emitEvent('preview:field-focus', { entryId: message.entryId, fieldApiId: message.fieldApiId, - locale: message.locale, }); // Use custom handler if provided if (this.config.onFieldFocus) { console.log('[Preview] Using custom onFieldFocus handler'); - this.config.onFieldFocus(message.fieldApiId, message.locale); + this.config.onFieldFocus(message.fieldApiId); return; } @@ -394,8 +391,7 @@ export class Preview { console.log('[Preview] Searching for field in registry...'); let elements = this.fieldRegistry.getElementsForEntryField( message.entryId, - message.fieldApiId, - undefined // locale not supported yet + message.fieldApiId ); console.log('[Preview] Initial registry search result:', { @@ -462,7 +458,6 @@ export class Preview { entryId: message.entryId, fieldApiId: message.fieldApiId, componentChain: message.componentChain, - locale: message.locale, }); // Debug: Log all registered elements @@ -529,7 +524,6 @@ export class Preview { private handleIframeEditClick(element: HTMLElement): void { const entryId = element.getAttribute('data-hygraph-entry-id'); const fieldApiId = element.getAttribute('data-hygraph-field-api-id') || undefined; - const locale = element.getAttribute('data-hygraph-field-locale') || undefined; const componentChain = this.parseComponentChain( element.getAttribute('data-hygraph-component-chain') || undefined ); @@ -542,7 +536,6 @@ export class Preview { type: 'field-click', entryId, fieldApiId, - locale, componentChain, timestamp: Date.now(), }; @@ -562,8 +555,7 @@ export class Preview { this.emitEvent('preview:field-click', { entryId, fieldApiId, - locale, - componentChain, + componentChain, mode: this.mode }); } @@ -571,7 +563,6 @@ export class Preview { private handleStandaloneEditClick(element: HTMLElement): void { const entryId = element.getAttribute('data-hygraph-entry-id'); const fieldApiId = element.getAttribute('data-hygraph-field-api-id') || undefined; - const locale = element.getAttribute('data-hygraph-field-locale') || undefined; const componentChain = this.parseComponentChain( element.getAttribute('data-hygraph-component-chain') || undefined ); @@ -584,7 +575,7 @@ export class Preview { } // Construct Studio resource route URL - const studioUrl = this.buildStudioUrl(entryId, fieldApiId, locale, componentChain); + const studioUrl = this.buildStudioUrl(entryId, fieldApiId, componentChain); // Open in new tab window.open(studioUrl, '_blank', 'noopener,noreferrer'); @@ -597,13 +588,12 @@ export class Preview { this.emitEvent('preview:field-click', { entryId, fieldApiId, - locale, componentChain, mode: this.mode }); } - private buildStudioUrl(entryId: string, fieldApiId?: string, locale?: string, componentChain?: ComponentChainLink[]): string { + private buildStudioUrl(entryId: string, fieldApiId?: string, componentChain?: ComponentChainLink[]): string { const baseUrl = (this.config.studioUrl || 'https://app.hygraph.com').replace(/\/+$/, ''); const params = new URLSearchParams({ endpoint: this.config.endpoint, @@ -611,7 +601,6 @@ export class Preview { }); if (fieldApiId) params.set('fieldApiId', fieldApiId); - if (locale) params.set('locale', locale); if (componentChain && componentChain.length > 0) { params.set('componentChain', JSON.stringify(componentChain)); } diff --git a/src/core/attributes.test.ts b/src/core/attributes.test.ts index 8d5a459..d27eb1f 100644 --- a/src/core/attributes.test.ts +++ b/src/core/attributes.test.ts @@ -13,13 +13,11 @@ describe('attributes helpers', () => { const attributes = createPreviewAttributes({ entryId: 'entry-1', fieldApiId: 'title', - locale: 'en', }); expect(attributes).toEqual({ 'data-hygraph-entry-id': 'entry-1', 'data-hygraph-field-api-id': 'title', - 'data-hygraph-field-locale': 'en', }); }); diff --git a/src/core/attributes.ts b/src/core/attributes.ts index cf079ec..f2f0bf0 100644 --- a/src/core/attributes.ts +++ b/src/core/attributes.ts @@ -3,12 +3,11 @@ import type { ComponentChainLink, ElementAttributes } from '../types'; export interface PreviewFieldOptions { entryId: string; fieldApiId?: string; - locale?: string; componentChain?: ComponentChainLink[]; } export function createPreviewAttributes(options: PreviewFieldOptions): ElementAttributes { - const { entryId, fieldApiId, locale, componentChain } = options; + const { entryId, fieldApiId, componentChain } = options; if (!entryId) { throw new Error('[Preview SDK] createPreviewAttributes requires an entryId'); @@ -22,10 +21,6 @@ export function createPreviewAttributes(options: PreviewFieldOptions): ElementAt attributes['data-hygraph-field-api-id'] = fieldApiId; } - if (locale) { - attributes['data-hygraph-field-locale'] = locale; - } - const serializedChain = serializeComponentChain(componentChain); if (serializedChain) { attributes['data-hygraph-component-chain'] = serializedChain; diff --git a/src/react/HygraphPreview.tsx b/src/react/HygraphPreview.tsx index 97de4c7..361626d 100644 --- a/src/react/HygraphPreview.tsx +++ b/src/react/HygraphPreview.tsx @@ -26,7 +26,7 @@ export interface HygraphPreviewProps extends PreviewConfig { onDisconnected?: () => void; onSave?: SaveCallback; onError?: (error: Error) => void; - onFieldFocus?: (fieldApiId: string, locale?: string) => void; + onFieldFocus?: (fieldApiId: string) => void; onFieldUpdate?: (update: import('../types').FieldUpdate) => void; } diff --git a/src/react/HygraphPreviewNextjs.tsx b/src/react/HygraphPreviewNextjs.tsx index c156adb..45faf3c 100644 --- a/src/react/HygraphPreviewNextjs.tsx +++ b/src/react/HygraphPreviewNextjs.tsx @@ -25,9 +25,8 @@ export interface HygraphPreviewNextjsProps extends Omit void; + onFieldFocus?: (fieldApiId: string) => void; /** * Optional custom field update handler diff --git a/src/types/index.ts b/src/types/index.ts index 26b36a3..b180b3f 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -21,7 +21,7 @@ export interface ComponentChainLink { export type StudioMessage = | { type: 'init'; studioOrigin: string; timestamp: number } | (FieldUpdate & { type: 'field-update'; timestamp: number }) - | { type: 'field-focus'; entryId: string; fieldApiId: string; componentChain?: ComponentChainLink[]; locale?: string; timestamp: number } + | { type: 'field-focus'; entryId: string; fieldApiId: string; componentChain?: ComponentChainLink[]; timestamp: number } | { type: 'content-saved'; entryId: string; timestamp: number } | { type: 'disconnect'; timestamp: number }; @@ -59,7 +59,6 @@ export type SDKMessage = type: 'field-click'; entryId: string; fieldApiId?: string; - locale?: string; componentChain?: ComponentChainLink[]; timestamp: number; }; @@ -89,7 +88,6 @@ export type FieldType = interface FieldUpdateBase { entryId: string; fieldApiId: string; - locale?: string; updateId?: string; } @@ -220,7 +218,7 @@ export interface PreviewConfig { allowedOrigins?: string[]; studioUrl?: string; // Allow custom Studio URL (for development) mode?: 'auto' | 'iframe' | 'standalone'; // Force specific mode - onFieldFocus?: (fieldApiId: string, locale?: string) => void; // Custom field focus handler + onFieldFocus?: (fieldApiId: string) => void; // Custom field focus handler onFieldUpdate?: (update: FieldUpdate) => void; // Custom field update handler // Studio sync capabilities @@ -274,7 +272,6 @@ export interface OverlayConfig { export interface ElementAttributes { 'data-hygraph-entry-id': string; 'data-hygraph-field-api-id'?: string; - 'data-hygraph-field-locale'?: string; 'data-hygraph-component-chain'?: string; } @@ -283,7 +280,6 @@ export interface RegisteredElement { element: HTMLElement; entryId: string; fieldApiId?: string; - locale?: string; componentChainRaw?: string; lastUpdated?: number; } @@ -300,11 +296,10 @@ export interface PreviewEvents { 'preview:ready': CustomEvent<{ preview: unknown }>; 'preview:connected': CustomEvent<{ studioOrigin: string }>; 'preview:disconnected': CustomEvent>; - 'preview:field-focus': CustomEvent<{ entryId: string; fieldApiId: string; locale?: string }>; + 'preview:field-focus': CustomEvent<{ entryId: string; fieldApiId: string }>; 'preview:field-click': CustomEvent<{ entryId: string; fieldApiId?: string; - locale?: string; componentChain?: ComponentChainLink[]; mode?: 'iframe' | 'standalone'; }>; @@ -332,7 +327,7 @@ export interface SubscriptionConfig { callback: SaveCallback; } -// Registry key format: "entryId:fieldApiId:locale?" +// Registry key format: "entryId:fieldApiId" export type RegistryKey = string; // Update result @@ -366,6 +361,5 @@ declare global { interface HTMLElement { 'data-hygraph-entry-id'?: string; 'data-hygraph-field-api-id'?: string; - 'data-hygraph-field-locale'?: string; } }