From e89780e02bb34abc45e11c254b952a721f66384a Mon Sep 17 00:00:00 2001 From: Tyler Date: Tue, 23 Sep 2025 15:18:02 -0600 Subject: [PATCH 1/3] feat: add ASSET_SIDEBAR location constants - Add LOCATION_ASSET_SIDEBAR to locations.ts - Update Locations interface in api.types.ts - Part of EXT-6786: Asset Sidebar App Framework Location --- lib/locations.ts | 1 + lib/types/api.types.ts | 1 + 2 files changed, 2 insertions(+) diff --git a/lib/locations.ts b/lib/locations.ts index 0f5d601194..23e604cb42 100644 --- a/lib/locations.ts +++ b/lib/locations.ts @@ -4,6 +4,7 @@ const locations: Locations = { LOCATION_ENTRY_FIELD: 'entry-field', LOCATION_ENTRY_FIELD_SIDEBAR: 'entry-field-sidebar', LOCATION_ENTRY_SIDEBAR: 'entry-sidebar', + LOCATION_ASSET_SIDEBAR: 'asset-sidebar', LOCATION_DIALOG: 'dialog', LOCATION_ENTRY_EDITOR: 'entry-editor', LOCATION_PAGE: 'page', diff --git a/lib/types/api.types.ts b/lib/types/api.types.ts index 7694fed922..1547037328 100644 --- a/lib/types/api.types.ts +++ b/lib/types/api.types.ts @@ -386,6 +386,7 @@ export interface Locations { LOCATION_ENTRY_FIELD: 'entry-field' LOCATION_ENTRY_FIELD_SIDEBAR: 'entry-field-sidebar' LOCATION_ENTRY_SIDEBAR: 'entry-sidebar' + LOCATION_ASSET_SIDEBAR: 'asset-sidebar' LOCATION_DIALOG: 'dialog' LOCATION_ENTRY_EDITOR: 'entry-editor' LOCATION_PAGE: 'page' From 5c43347820e19af35aa260ff02f46f1612bc5052 Mon Sep 17 00:00:00 2001 From: Tyler Date: Wed, 24 Sep 2025 09:43:42 -0600 Subject: [PATCH 2/3] feat: implement asset API integration - Added createAsset import and makeAssetAPI function to handle asset-related messages. - Updated LOCATION_TO_API_PRODUCERS to include asset sidebar API producers. - Enhanced ConnectMessage interface to support asset metadata and system information. - Introduced AssetSys interface for asset type representation. This change supports the new asset sidebar functionality. --- lib/api.ts | 8 ++++++ lib/asset.ts | 54 ++++++++++++++++++++++++++++++++++++++++ lib/types/api.types.ts | 6 ++++- lib/types/asset.types.ts | 22 ++++++++++++++++ lib/types/utils.ts | 4 +++ 5 files changed, 93 insertions(+), 1 deletion(-) create mode 100644 lib/asset.ts create mode 100644 lib/types/asset.types.ts diff --git a/lib/api.ts b/lib/api.ts index bf181c265b..1810f4589a 100644 --- a/lib/api.ts +++ b/lib/api.ts @@ -2,6 +2,7 @@ import { makeField } from './field' import { makeFieldLocale } from './field-locale' import createWindow from './window' import createEntry from './entry' +import createAsset from './asset' import createSpace from './space' import createDialogs from './dialogs' import createEditor from './editor' @@ -38,6 +39,7 @@ const LOCATION_TO_API_PRODUCERS: { [location: string]: ProducerFunc[] } = { [locations.LOCATION_ENTRY_FIELD]: DEFAULT_API_PRODUCERS, [locations.LOCATION_ENTRY_FIELD_SIDEBAR]: DEFAULT_API_PRODUCERS, [locations.LOCATION_ENTRY_SIDEBAR]: [makeSharedAPI, makeEntryAPI, makeEditorAPI, makeWindowAPI], + [locations.LOCATION_ASSET_SIDEBAR]: [makeSharedAPI, makeAssetAPI, makeWindowAPI], [locations.LOCATION_ENTRY_EDITOR]: [makeSharedAPI, makeEntryAPI, makeEditorAPI], [locations.LOCATION_DIALOG]: [makeSharedAPI, makeDialogAPI, makeWindowAPI], [locations.LOCATION_PAGE]: [makeSharedAPI], @@ -151,6 +153,12 @@ function makeDialogAPI(channel: Channel) { } } +function makeAssetAPI(channel: Channel, { asset }: ConnectMessage) { + return { + asset: createAsset(channel, asset), + } +} + function makeAppAPI(channel: Channel) { const app = createApp(channel) diff --git a/lib/asset.ts b/lib/asset.ts new file mode 100644 index 0000000000..2c29dc29b2 --- /dev/null +++ b/lib/asset.ts @@ -0,0 +1,54 @@ +import { Channel } from './channel' +import { MemoizedSignal } from './signal' +import { ConnectMessage, Metadata } from './types' +import { AssetAPI } from './types/asset.types' +import { AssetSys } from './types/utils' + +export default function createAsset( + channel: Channel, + assetData: ConnectMessage['asset'], +): AssetAPI { + if (!assetData) { + throw new Error('Asset data is required') + } + + let sys: AssetSys = assetData.sys + const sysChanged = new MemoizedSignal<[AssetSys]>(sys) + let metadata = assetData.metadata + const metadataChanged = new MemoizedSignal<[Metadata | undefined]>(metadata) + + channel.addHandler('sysChanged', (newSys: AssetSys) => { + sys = newSys + sysChanged.dispatch(sys) + }) + + channel.addHandler('metadataChanged', (newMetadata: Metadata) => { + metadata = newMetadata + metadataChanged.dispatch(metadata) + }) + + return { + getSys() { + return sys + }, + publish(options?: { skipUiValidation?: boolean }) { + return channel.call('callAssetMethod', 'publish', [options]) + }, + unpublish() { + return channel.call('callAssetMethod', 'unpublish') + }, + save() { + return channel.call('callAssetMethod', 'save') + }, + onSysChanged(handler: (sys: AssetSys) => void) { + return sysChanged.attach(handler) + }, + ...(metadata ? { metadata } : {}), + getMetadata() { + return metadata + }, + onMetadataChanged(handler: VoidFunction) { + return metadataChanged.attach(handler) + }, + } +} diff --git a/lib/types/api.types.ts b/lib/types/api.types.ts index 1547037328..168a0834db 100644 --- a/lib/types/api.types.ts +++ b/lib/types/api.types.ts @@ -14,7 +14,7 @@ import { import { EntryAPI } from './entry.types' import { SpaceAPI } from './space.types' import { WindowAPI } from './window.types' -import { EntrySys, Link, SerializedJSONValue } from './utils' +import { EntrySys, AssetSys, Link, SerializedJSONValue } from './utils' import { FieldAPI } from './field-locale.types' import { DialogsAPI } from './dialogs.types' import { AppConfigAPI } from './app.types' @@ -412,6 +412,10 @@ export interface ConnectMessage { sys: EntrySys metadata?: Metadata } + asset?: { + sys: AssetSys + metadata?: Metadata + } fieldInfo: EntryFieldInfo[] field?: FieldInfo hostnames: HostnamesAPI diff --git a/lib/types/asset.types.ts b/lib/types/asset.types.ts new file mode 100644 index 0000000000..526657a850 --- /dev/null +++ b/lib/types/asset.types.ts @@ -0,0 +1,22 @@ +import { Metadata } from './entities' +import { AssetSys } from './utils' + +export interface AssetAPI { + /** Returns sys for an asset. */ + getSys: () => AssetSys + /** Publish the asset */ + publish: (options?: { skipUiValidation?: boolean }) => Promise + /** Unpublish the asset */ + unpublish: () => Promise + /** Saves the current changes of the asset */ + save: () => Promise + /** Calls the callback with sys every time that sys changes. */ + onSysChanged: (callback: (sys: AssetSys) => void) => () => void + /** + * Optional metadata on an asset + * @deprecated + */ + metadata?: Metadata + getMetadata: () => Metadata | undefined + onMetadataChanged: (callback: (metadata?: Metadata) => void) => VoidFunction +} diff --git a/lib/types/utils.ts b/lib/types/utils.ts index e326941cb7..2e557273e7 100644 --- a/lib/types/utils.ts +++ b/lib/types/utils.ts @@ -70,6 +70,10 @@ export interface EntrySys extends ContentEntitySys { automationTags: Link<'Tag'>[] } +export interface AssetSys extends ContentEntitySys { + type: 'Asset' +} + export type FieldType = | 'Symbol' | 'Text' From 8346f33f02c58ac959f6aa29aa56240318cffac3 Mon Sep 17 00:00:00 2001 From: Tyler Date: Wed, 24 Sep 2025 10:02:57 -0600 Subject: [PATCH 3/3] refactor: remove deprecated metadata from AssetAPI interface - Removed the optional metadata property from the AssetAPI interface, marking it as deprecated. - Updated createAsset function to eliminate the metadata parameter, streamlining asset creation. This change enhances the clarity and usability of the asset API. --- lib/asset.ts | 1 - lib/types/asset.types.ts | 5 ----- 2 files changed, 6 deletions(-) diff --git a/lib/asset.ts b/lib/asset.ts index 2c29dc29b2..ec800adb79 100644 --- a/lib/asset.ts +++ b/lib/asset.ts @@ -43,7 +43,6 @@ export default function createAsset( onSysChanged(handler: (sys: AssetSys) => void) { return sysChanged.attach(handler) }, - ...(metadata ? { metadata } : {}), getMetadata() { return metadata }, diff --git a/lib/types/asset.types.ts b/lib/types/asset.types.ts index 526657a850..3c4bbd5ea2 100644 --- a/lib/types/asset.types.ts +++ b/lib/types/asset.types.ts @@ -12,11 +12,6 @@ export interface AssetAPI { save: () => Promise /** Calls the callback with sys every time that sys changes. */ onSysChanged: (callback: (sys: AssetSys) => void) => () => void - /** - * Optional metadata on an asset - * @deprecated - */ - metadata?: Metadata getMetadata: () => Metadata | undefined onMetadataChanged: (callback: (metadata?: Metadata) => void) => VoidFunction }