From 4ffa620f3af4366f0ed4908a284b43c4440c9222 Mon Sep 17 00:00:00 2001 From: HexaField <10372036+HexaField@users.noreply.github.com> Date: Wed, 17 Jun 2026 04:38:46 +1000 Subject: [PATCH] =?UTF-8?q?refactor:=20align=20with=20AD4M=20PR=20#842=20?= =?UTF-8?q?=E2=80=94=20resolveLiteral=20replaces=20resolveLanguage?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.6 --- .../src/frameworks/solid/stores/AdamStore.tsx | 2 +- .../src/shared/perspectiveHelpers.ts | 2 +- .../app-framework/src/shared/syncHelpers.ts | 2 +- .../block-system/shared/src/serialization.ts | 17 +++++++++-------- packages/block-system/shared/src/utils.ts | 2 +- packages/models/src/blocks/AudioBlock.ts | 3 +-- packages/models/src/blocks/CollectionBlock.ts | 3 +-- packages/models/src/blocks/FileBlock.ts | 3 +-- packages/models/src/blocks/ImageBlock.ts | 3 +-- packages/models/src/entities/Space.ts | 5 ++--- packages/models/src/entities/Template.ts | 3 +-- packages/models/src/entities/Theme.ts | 5 ++--- packages/models/src/utils/fileTransforms.ts | 2 +- packages/models/src/utils/imageHelpers.ts | 2 +- 14 files changed, 24 insertions(+), 30 deletions(-) diff --git a/packages/app-framework/src/frameworks/solid/stores/AdamStore.tsx b/packages/app-framework/src/frameworks/solid/stores/AdamStore.tsx index 3e816114..e2df8e0b 100644 --- a/packages/app-framework/src/frameworks/solid/stores/AdamStore.tsx +++ b/packages/app-framework/src/frameworks/solid/stores/AdamStore.tsx @@ -48,7 +48,7 @@ export interface ModelManifestProperty { isCollection: boolean; required: boolean; writable: boolean; - resolveLanguage?: string; + resolveLiteral?: boolean; relatedModel?: string; } diff --git a/packages/app-framework/src/shared/perspectiveHelpers.ts b/packages/app-framework/src/shared/perspectiveHelpers.ts index 005e3001..77fb204f 100644 --- a/packages/app-framework/src/shared/perspectiveHelpers.ts +++ b/packages/app-framework/src/shared/perspectiveHelpers.ts @@ -84,7 +84,7 @@ export async function getModelManifest(perspective: PerspectiveProxy): Promise 1, required: (p.minCount ?? 0) >= 1, writable: p.writable ?? true, - ...(p.resolveLanguage !== undefined && { resolveLanguage: p.resolveLanguage }), + ...(p.resolveLiteral !== undefined && { resolveLiteral: p.resolveLiteral }), ...(p.class !== undefined && { relatedModel: shaclClassToLocalName(p.class) }), }), ), diff --git a/packages/app-framework/src/shared/syncHelpers.ts b/packages/app-framework/src/shared/syncHelpers.ts index 696e8d1b..716400e1 100644 --- a/packages/app-framework/src/shared/syncHelpers.ts +++ b/packages/app-framework/src/shared/syncHelpers.ts @@ -27,7 +27,7 @@ export interface SpaceSyncOptions { /** * Raw FileData for avatar/coverImage. * Use when syncing after an image update so the target gets the same FileData - * written through its own resolveLanguage pipeline, rather than copying a + * written through its own file-storage pipeline, rather than copying a * resolved data-URI string (which would be stored incorrectly). */ avatarData?: FileData; diff --git a/packages/block-system/shared/src/serialization.ts b/packages/block-system/shared/src/serialization.ts index bdfa588d..d0629e1f 100644 --- a/packages/block-system/shared/src/serialization.ts +++ b/packages/block-system/shared/src/serialization.ts @@ -1,5 +1,6 @@ import type { PerspectiveProxy } from '@coasys/ad4m'; import { Ad4mModel, getPropertiesMetadata } from '@coasys/ad4m'; +import { FILE_STORAGE_LANGUAGE } from '@we/models'; import type { CollectionBlock, FileData } from '@we/models'; import { getBlockModel, getRegisteredBlockModels } from './registry'; @@ -146,7 +147,7 @@ function isFileData(value: unknown): value is FileData { /** * Walk a serialized block node tree, upload any FileData values on - * resolveLanguage properties to file-storage, and return a patched copy + * file-storage properties (resolveLiteral: false) and return a patched copy * where those values are replaced with the resulting expression addresses * (e.g. "QmLang://QmHash"). This keeps the editorState blob small (CIDs * instead of raw base64 payloads) and ensures the AD4M model's create() @@ -164,9 +165,9 @@ async function preUploadFileAssets( if (ModelClass) { const propsMeta = getPropertiesMetadata(ModelClass); for (const [propName, meta] of Object.entries(propsMeta)) { - if (meta.resolveLanguage && isFileData(patched[propName])) { + if (meta.resolveLiteral === false && isFileData(patched[propName])) { // Upload the file and replace the FileData with the expression address - const expressionAddress = await perspective.createExpression(patched[propName], meta.resolveLanguage); + const expressionAddress = await perspective.createExpression(patched[propName], FILE_STORAGE_LANGUAGE); patched[propName] = expressionAddress; } } @@ -189,7 +190,7 @@ async function preUploadFileAssets( /** * Walk a serialized block node tree and resolve any expression-address strings - * on resolveLanguage properties to data URIs via the perspective. + * on file-storage properties (resolveLiteral: false) to data URIs via the perspective. * This is the read-side counterpart to preUploadFileAssets — called by * BlockRenderer before loading the editorState blob into Lexical so that * stored CIDs (e.g. "QmLang://QmHash") are replaced with renderable data URIs. @@ -205,9 +206,9 @@ export async function resolveExpressionAddresses( const propsMeta = getPropertiesMetadata(ModelClass); for (const [propName, meta] of Object.entries(propsMeta)) { const val = patched[propName]; - // Only attempt resolution for resolveLanguage properties that hold a - // non-empty string containing "://" — the hallmark of an expression address. - if (meta.resolveLanguage && typeof val === 'string' && val.includes('://')) { + // Only attempt resolution for file-storage properties (resolveLiteral: false) + // that hold a non-empty string containing "://" — the hallmark of an expression address. + if (meta.resolveLiteral === false && typeof val === 'string' && val.includes('://')) { try { const expr = await perspective.getExpression(val); if (expr?.data) { @@ -275,7 +276,7 @@ export async function createBlocks( // that FileData objects hit the deferred setProperty → createExpression → // executeAction path, which stores clean URI references in the triple graph. // (Passing pre-uploaded strings through initialValues → createSubject would - // JSON-encode them with quote characters, breaking resolveLanguage resolution.) + // JSON-encode them with quote characters, breaking file-storage resolution.) const patchedNode = await preUploadFileAssets(perspective, node); return Ad4mModel.transaction(perspective, async (tx) => { diff --git a/packages/block-system/shared/src/utils.ts b/packages/block-system/shared/src/utils.ts index f969a3c2..15e1630b 100644 --- a/packages/block-system/shared/src/utils.ts +++ b/packages/block-system/shared/src/utils.ts @@ -1,7 +1,7 @@ import type { SerializedBlockNode } from './types'; /** - * Decode an editorState data URL (returned by resolveLanguage) into a + * Decode an editorState data URL (returned by file-storage resolution) into a * SerializedBlockNode (Lexical root node JSON). * * The ad4m model system resolves FILE_STORAGE_LANGUAGE CIDs into diff --git a/packages/models/src/blocks/AudioBlock.ts b/packages/models/src/blocks/AudioBlock.ts index 29b62624..8fff64c5 100644 --- a/packages/models/src/blocks/AudioBlock.ts +++ b/packages/models/src/blocks/AudioBlock.ts @@ -1,6 +1,5 @@ import { fileToDataUri, Flag, Model, Property } from '@coasys/ad4m'; -import { FILE_STORAGE_LANGUAGE } from '../constants'; import { WeNode } from '../WeNode'; @Model({ name: 'AudioBlock' }) @@ -17,7 +16,7 @@ export class AudioBlock extends WeNode { @Property({ through: 'we://audio_url', required: true, - resolveLanguage: FILE_STORAGE_LANGUAGE, + resolveLiteral: false, transform: fileToDataUri, }) audioUrl: string = ''; diff --git a/packages/models/src/blocks/CollectionBlock.ts b/packages/models/src/blocks/CollectionBlock.ts index 02cebe2b..1b8f841a 100644 --- a/packages/models/src/blocks/CollectionBlock.ts +++ b/packages/models/src/blocks/CollectionBlock.ts @@ -1,6 +1,5 @@ import { Flag, HasMany, HasManyMethods, Model, Property } from '@coasys/ad4m'; -import { FILE_STORAGE_LANGUAGE } from '../constants'; import { WeNode } from '../WeNode'; @Model({ name: 'CollectionBlock' }) @@ -11,7 +10,7 @@ export class CollectionBlock extends WeNode { @HasMany({ through: 'we://children' }) children: string[] = []; - @Property({ through: 'we://editor_state', resolveLanguage: FILE_STORAGE_LANGUAGE }) + @Property({ through: 'we://editor_state', resolveLiteral: false }) editorState: string | null = null; @Property({ through: 'we://type' }) diff --git a/packages/models/src/blocks/FileBlock.ts b/packages/models/src/blocks/FileBlock.ts index 85c7365c..fb80db43 100644 --- a/packages/models/src/blocks/FileBlock.ts +++ b/packages/models/src/blocks/FileBlock.ts @@ -1,6 +1,5 @@ import { fileToDataUri, Flag, Model, Property } from '@coasys/ad4m'; -import { FILE_STORAGE_LANGUAGE } from '../constants'; import { WeNode } from '../WeNode'; @Model({ name: 'FileBlock' }) @@ -14,7 +13,7 @@ export class FileBlock extends WeNode { @Property({ through: 'we://name', required: true }) name: string = ''; - @Property({ through: 'we://url', required: true, resolveLanguage: FILE_STORAGE_LANGUAGE, transform: fileToDataUri }) + @Property({ through: 'we://url', required: true, resolveLiteral: false, transform: fileToDataUri }) url: string = ''; @Property({ through: 'we://mime_type' }) diff --git a/packages/models/src/blocks/ImageBlock.ts b/packages/models/src/blocks/ImageBlock.ts index 77b65e67..7c08b67a 100644 --- a/packages/models/src/blocks/ImageBlock.ts +++ b/packages/models/src/blocks/ImageBlock.ts @@ -1,6 +1,5 @@ import { fileToDataUri, Flag, Model, Property } from '@coasys/ad4m'; -import { FILE_STORAGE_LANGUAGE } from '../constants'; import { WeNode } from '../WeNode'; @Model({ name: 'ImageBlock' }) @@ -8,7 +7,7 @@ export class ImageBlock extends WeNode { @Flag({ through: 'we://flag', value: 'we://image_block' }) flag: string = ''; - @Property({ through: 'we://src', required: true, resolveLanguage: FILE_STORAGE_LANGUAGE, transform: fileToDataUri }) + @Property({ through: 'we://src', required: true, resolveLiteral: false, transform: fileToDataUri }) src: string = ''; @Property({ through: 'we://altText' }) diff --git a/packages/models/src/entities/Space.ts b/packages/models/src/entities/Space.ts index 84a945cb..98b39dca 100644 --- a/packages/models/src/entities/Space.ts +++ b/packages/models/src/entities/Space.ts @@ -1,7 +1,6 @@ import { fileToDataUri, Flag, HasOne, Model, Property } from '@coasys/ad4m'; import { LocationBlock } from '../blocks/LocationBlock'; -import { FILE_STORAGE_LANGUAGE } from '../constants'; import { WeNode } from '../WeNode'; @Model({ name: 'Space' }) @@ -27,10 +26,10 @@ export class Space extends WeNode { @Property({ through: 'we://discovery' }) discovery: string = 'hidden'; - @Property({ through: 'we://image', resolveLanguage: FILE_STORAGE_LANGUAGE, transform: fileToDataUri }) + @Property({ through: 'we://image', resolveLiteral: false, transform: fileToDataUri }) avatar?: string; - @Property({ through: 'we://thumbnail', resolveLanguage: FILE_STORAGE_LANGUAGE, transform: fileToDataUri }) + @Property({ through: 'we://thumbnail', resolveLiteral: false, transform: fileToDataUri }) coverImage?: string; @HasOne(() => LocationBlock, { through: 'we://location' }) diff --git a/packages/models/src/entities/Template.ts b/packages/models/src/entities/Template.ts index 8f701b2d..1a3b2833 100644 --- a/packages/models/src/entities/Template.ts +++ b/packages/models/src/entities/Template.ts @@ -1,6 +1,5 @@ import { Flag, HasMany, HasManyMethods, Model, Property } from '@coasys/ad4m'; -import { FILE_STORAGE_LANGUAGE } from '../constants'; import { WeNode } from '../WeNode'; import { ChatSession } from './ChatSession'; @@ -20,7 +19,7 @@ export class Template extends WeNode { @Property({ through: 'we://template_schema', - resolveLanguage: FILE_STORAGE_LANGUAGE, + resolveLiteral: false, }) schema: string | null = null; diff --git a/packages/models/src/entities/Theme.ts b/packages/models/src/entities/Theme.ts index 85e71789..a76d1975 100644 --- a/packages/models/src/entities/Theme.ts +++ b/packages/models/src/entities/Theme.ts @@ -1,6 +1,5 @@ import { Flag, Model, Property } from '@coasys/ad4m'; -import { FILE_STORAGE_LANGUAGE } from '../constants'; import { WeNode } from '../WeNode'; @Model({ name: 'Theme' }) @@ -23,14 +22,14 @@ export class Theme extends WeNode { /** Raw CSS string (e.g. [data-we-theme='x'] { ... } rules, ::part() selectors, etc.) */ @Property({ through: 'we://stylesheet', - resolveLanguage: FILE_STORAGE_LANGUAGE, + resolveLiteral: false, }) css: string | null = null; /** Structured token overrides (primaryHue, saturation, neutralSaturation, etc.) */ @Property({ through: 'we://token_overrides', - resolveLanguage: FILE_STORAGE_LANGUAGE, + resolveLiteral: false, }) overrides: string | null = null; } diff --git a/packages/models/src/utils/fileTransforms.ts b/packages/models/src/utils/fileTransforms.ts index da036bfb..2a8219ad 100644 --- a/packages/models/src/utils/fileTransforms.ts +++ b/packages/models/src/utils/fileTransforms.ts @@ -1,5 +1,5 @@ /** Decode a file-storage resolved value into a plain string. - * resolveLanguage always converts stored blobs to "data:;base64," strings. */ + * File-storage properties (resolveLiteral: false) convert stored blobs to "data:;base64," strings. */ export function decodeFileAsString(data: string | null | undefined): string { if (typeof data !== 'string' || !data.startsWith('data:') || !data.includes(';base64,')) return ''; try { diff --git a/packages/models/src/utils/imageHelpers.ts b/packages/models/src/utils/imageHelpers.ts index f9ff08c8..5bd316d5 100644 --- a/packages/models/src/utils/imageHelpers.ts +++ b/packages/models/src/utils/imageHelpers.ts @@ -105,7 +105,7 @@ export async function readFileAsFileData(file: File): Promise { /** * Reconstruct a FileData value object from a resolved data URI string. * - * After AgentProfile.findOne() / Space.findOne() the resolveLanguage transform + * After Space.findOne() the file-storage (resolveLiteral: false) transform * converts stored FileData objects to `data:;base64,` strings. * This function reverses that transform so the value can be safely passed back * through FILE_STORAGE_LANGUAGE — the storage is content-addressed