Skip to content

Conversation

@tylerwashington888
Copy link
Contributor

@tylerwashington888 tylerwashington888 commented Sep 24, 2025

Add Asset Sidebar App Framework Location Support

Purpose
This PR implements the foundational support for the new asset-sidebar App Framework location, enabling apps to be installed and rendered in the asset editing sidebar. This addresses critical customer needs for asset-centric workflows including AI tagging, rights management, and publishing automation.

Background
As part of the asset-sidebar epic (EXT-6786, EXT-6788, EXT-6790, EXT-6793), this implementation provides the core SDK infrastructure needed to support apps in the asset editing context, similar to how entry-sidebar works for entries.

Changes
��️ Location Constants
lib/locations.ts: Added LOCATION_ASSET_SIDEBAR: 'asset-sidebar' to the locations object
lib/types/api.types.ts: Updated Locations interface to include the new location type

🔧 Asset API Implementation
lib/types/asset.types.ts: Created AssetAPI interface with asset-specific operations:
getSys(), publish(), unpublish(), save()
onSysChanged(), getMetadata(), onMetadataChanged()
lib/asset.ts: Implemented createAsset() function following same patterns as createEntry()
lib/types/utils.ts: Added AssetSys interface extending ContentEntitySys

🔌 API Producer Integration
lib/api.ts:
Added makeAssetAPI() function to provide asset context to apps
Added [locations.LOCATION_ASSET_SIDEBAR]: [makeSharedAPI, makeAssetAPI, makeWindowAPI] to LOCATION_TO_API_PRODUCERS
Imported and integrated createAsset() function

📡 Data Flow Support
lib/types/api.types.ts: Updated ConnectMessage interface to include optional asset property:

Impact
✅ Apps can now specify asset-sidebar as a supported location in their app definitions
✅ Apps running in asset-sidebar location receive sdk.asset API with full asset operations
✅ TypeScript compilation passes with new location and API types
✅ Foundation established for UI integration and widget rendering
✅ No breaking changes to existing functionality

Type: Feature
Scope: UI Extensions SDK
Breaking Change: No
Related Tickets: EXT-6786, EXT-6788, EXT-6790, EXT-6793

Summary by CodeRabbit

  • New Features

    • Added an Asset Sidebar location so apps can run in the asset sidebar.
    • Introduced an Asset API: access asset system fields and metadata, publish/unpublish/save, and subscribe to sys/metadata changes.
    • Connection payloads may include asset data to initialize the Asset API.
  • Types

    • Added Asset-related types (Asset sys shape and Asset API signatures) to support the new capabilities.

@tylerwashington888 tylerwashington888 requested review from a team as code owners September 24, 2025 15:58
@coderabbitai
Copy link

coderabbitai bot commented Sep 24, 2025

Walkthrough

Added an Asset API surface: new asset types, createAsset implementation, a LOCATION_ASSET_SIDEBAR location, ConnectMessage asset payload, and wiring of a makeAssetAPI producer into the location-to-producer map to expose asset methods in the asset sidebar.

Changes

Cohort / File(s) Summary of changes
Location constant & mapping
lib/locations.ts, lib/api.ts
Added LOCATION_ASSET_SIDEBAR and mapped a new makeAssetAPI producer into LOCATION_TO_API_PRODUCERS for the asset sidebar.
Asset API implementation
lib/asset.ts
New createAsset(channel, assetData) module: validates assetData, initializes sys/metadata state and signals, registers channel handlers, and exposes getSys, getMetadata, publish, unpublish, save, and change listeners.
API types & connection message
lib/types/api.types.ts, lib/types/asset.types.ts, lib/types/utils.ts
Added LOCATION_ASSET_SIDEBAR to Locations; extended ConnectMessage with optional asset?: { sys: AssetSys; metadata?: Metadata }; introduced AssetSys type (type: 'Asset'); adjusted AssetAPI signatures (getSys and getMetadata as properties returning values).

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor App
  participant Sidebar as Asset Sidebar (LOCATION_ASSET_SIDEBAR)
  participant Prod as makeAssetAPI
  participant AssetAPI as createAsset / AssetAPI
  participant Channel
  participant Host

  App->>Sidebar: connect({ asset, ... })
  Sidebar->>Prod: produce API with channel + { asset }
  Prod->>AssetAPI: createAsset(channel, asset)
  Note over AssetAPI: init sys/metadata, register handlers

  App->>AssetAPI: getSys / getMetadata
  AssetAPI-->>App: current values

  App->>AssetAPI: publish(options)
  AssetAPI->>Channel: call('callAssetMethod','publish',options)
  Channel->>Host: forward call
  Host-->>Channel: result
  Channel-->>AssetAPI: sys/metadata update events
  AssetAPI-->>App: onSysChanged / onMetadataChanged callbacks
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

I thump my paws—new assets hop into sight,
A sidebar burrow wakes in morning light.
Publish, save, unpublish — a carrot trail,
Sys and metadata sing in every gale.
I nibble changes, then bound off — happy tail. 🐇✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title correctly identifies a feature addition for the asset-sidebar location constants and includes a ticket reference, so it is directly related to the changeset; it is concise and indicates a feature change, though it narrowly emphasizes the constants (the PR also adds an asset API) and includes two different EXT references which may be confusing.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/EXT-6788-asset-sidebar-location-constants

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5c43347 and 8346f33.

📒 Files selected for processing (2)
  • lib/asset.ts (1 hunks)
  • lib/types/asset.types.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • lib/asset.ts
  • lib/types/asset.types.ts

Comment @coderabbitai help to get the list of available commands and usage tips.

- Add LOCATION_ASSET_SIDEBAR to locations.ts
- Update Locations interface in api.types.ts
- Part of EXT-6786: Asset Sidebar App Framework Location
- 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.
@tylerwashington888 tylerwashington888 force-pushed the feature/EXT-6788-asset-sidebar-location-constants branch from ab5c077 to 5c43347 Compare September 24, 2025 15:58
@tylerwashington888 tylerwashington888 changed the title Feature/ext 6788 asset sidebar location constants [EXT- Feature/ext 6788 asset sidebar location constants [EXT-6786] Sep 24, 2025
@tylerwashington888 tylerwashington888 changed the title Feature/ext 6788 asset sidebar location constants [EXT-6786] feat: ext 6788 asset sidebar location constants [EXT-6786] Sep 24, 2025
- 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.
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (3)
lib/types/api.types.ts (1)

415-418: ConnectMessage shape likely needs a union for asset vs entry locations.

Requiring entry while adding optional asset leads to an impossible shape for asset-sidebar. Consider a location-driven union to improve type safety and DX.

You can introduce a union like:

// Outside changed lines: illustrative
interface ConnectMessageBase { /* existing shared props */ }

interface EntryConnectMessage extends ConnectMessageBase {
  entry: { sys: EntrySys; metadata?: Metadata }
  asset?: never
}

interface AssetConnectMessage extends ConnectMessageBase {
  asset: { sys: AssetSys; metadata?: Metadata }
  entry?: never
}

export type ConnectMessage = EntryConnectMessage | AssetConnectMessage /* | other variants as needed */

Optionally, consider adding asset to IdsAPI for parity with entry locations.

lib/api.ts (1)

156-160: Add an explicit guard for missing asset (parity with Field API error).

createAsset throws, but adding a guard here improves error clarity and consistency.

Apply this diff:

 function makeAssetAPI(channel: Channel, { asset }: ConnectMessage) {
-  return {
-    asset: createAsset(channel, asset),
-  }
+  if (!asset) {
+    throw new Error('AssetAPI called for location without "asset" property defined.')
+  }
+  return {
+    asset: createAsset(channel, asset),
+  }
 }
lib/asset.ts (1)

20-28: Optional: namespace channel events to avoid future collisions.

If entry and asset APIs coexist in a location later, sysChanged/metadataChanged may collide. Consider assetSysChanged/assetMetadataChanged.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1f8e8a4 and 5c43347.

📒 Files selected for processing (6)
  • lib/api.ts (3 hunks)
  • lib/asset.ts (1 hunks)
  • lib/locations.ts (1 hunks)
  • lib/types/api.types.ts (3 hunks)
  • lib/types/asset.types.ts (1 hunks)
  • lib/types/utils.ts (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (5)
lib/types/asset.types.ts (2)
lib/types/utils.ts (1)
  • AssetSys (73-75)
lib/types/index.ts (1)
  • Metadata (61-61)
lib/asset.ts (5)
lib/channel.ts (1)
  • Channel (26-86)
lib/types/api.types.ts (1)
  • ConnectMessage (397-424)
lib/types/asset.types.ts (1)
  • AssetAPI (4-22)
lib/types/utils.ts (1)
  • AssetSys (73-75)
lib/signal.ts (1)
  • MemoizedSignal (24-57)
lib/types/api.types.ts (1)
lib/types/utils.ts (1)
  • AssetSys (73-75)
lib/types/utils.ts (1)
lib/types/index.ts (1)
  • ContentEntitySys (97-97)
lib/api.ts (3)
lib/channel.ts (1)
  • Channel (26-86)
lib/types/api.types.ts (1)
  • ConnectMessage (397-424)
lib/asset.ts (1)
  • createAsset (7-54)
🔇 Additional comments (6)
lib/types/api.types.ts (2)

17-17: Import looks good.

The new AssetSys import is correct and aligns with the added asset shape.


389-389: New location constant LGTM.

LOCATION_ASSET_SIDEBAR: 'asset-sidebar' is consistent and will help route the correct API surface.

lib/locations.ts (1)

7-7: Location mapping addition LGTM.

LOCATION_ASSET_SIDEBAR is correctly added to the exported map.

lib/api.ts (2)

5-5: Import addition LGTM.

createAsset import correctly wires the new API producer.


42-42: Producer wiring LGTM.

Mapping LOCATION_ASSET_SIDEBAR to [makeSharedAPI, makeAssetAPI, makeWindowAPI] is correct and avoids entry-specific producers.

lib/types/asset.types.ts (1)

4-22: AssetAPI surface LGTM.

Methods and callback types are coherent; deprecating the metadata property while providing getters/listeners is a good balance.

Comment on lines +50 to +52
onMetadataChanged(handler: VoidFunction) {
return metadataChanged.attach(handler)
},
Copy link

@coderabbitai coderabbitai bot Sep 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Type mismatch: onMetadataChanged callback should receive metadata.

The signature is VoidFunction but listeners are invoked with metadata. Align with AssetAPI type.

Apply this diff:

-    onMetadataChanged(handler: VoidFunction) {
+    onMetadataChanged(handler: (metadata?: Metadata) => void) {
       return metadataChanged.attach(handler)
     },
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
onMetadataChanged(handler: VoidFunction) {
return metadataChanged.attach(handler)
},
onMetadataChanged(handler: (metadata?: Metadata) => void) {
return metadataChanged.attach(handler)
},
🤖 Prompt for AI Agents
lib/asset.ts around lines 50 to 52: the onMetadataChanged handler is currently
typed as VoidFunction but listeners are invoked with metadata; change the
handler signature to accept the metadata parameter matching AssetAPI (e.g.
handler: (metadata: AssetMetadata) => void or the exact type from AssetAPI),
update the function signature and return type accordingly, and import or
reference the correct AssetAPI/Metadata type so attached listeners receive the
typed metadata.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the identical entry api method uses the same args so im going to keep this the same

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Search for onMetadataChanged method in entry-related files to verify the user's claim about consistency
ast-grep --pattern 'onMetadataChanged($_) {
  $$$
}'

# Also search with rg to find any onMetadataChanged implementations
rg -nC3 "onMetadataChanged" --type=ts

Length of output: 1234


@tylerwashington888 You're absolutely right! I can see that the entry API implementation in lib/entry.ts line 77 uses the exact same pattern:

onMetadataChanged(handler: VoidFunction) {
  return metadataChanged.attach(handler)
}

Both implementations are consistent with each other, even though they differ from their respective type definitions (which correctly specify (metadata?: Metadata) => void). I understand the rationale for maintaining consistency across the codebase. Thanks for the clarification!


✏ Learnings added
Learnt from: tylerwashington888
PR: contentful/ui-extensions-sdk#2338
File: lib/asset.ts:49-51
Timestamp: 2025-09-24T16:31:58.939Z
Learning: Both asset API and entry API implementations use VoidFunction for onMetadataChanged handler parameter, maintaining consistency across the codebase despite type definitions specifying (metadata?: Metadata) => void.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

Comment on lines +73 to +75
export interface AssetSys extends ContentEntitySys {
type: 'Asset'
}
Copy link

@coderabbitai coderabbitai bot Sep 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

AssetSys should not inherit contentType (assets don’t have one).

Current inheritance from ContentEntitySys incorrectly forces a contentType link on assets. Define AssetSys by omitting contentType.

Apply this diff:

-export interface AssetSys extends ContentEntitySys {
-  type: 'Asset'
-}
+export type AssetSys = Omit<ContentEntitySys, 'contentType'> & {
+  type: 'Asset'
+}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export interface AssetSys extends ContentEntitySys {
type: 'Asset'
}
export type AssetSys = Omit<ContentEntitySys, 'contentType'> & {
type: 'Asset'
}
🤖 Prompt for AI Agents
In lib/types/utils.ts around lines 73 to 75, AssetSys currently inherits
ContentEntitySys which forces a contentType link that assets don't have; change
AssetSys to extend ContentEntitySys with contentType omitted (e.g., use
Omit<ContentEntitySys, 'contentType'>) and keep the type literal 'Asset' so the
interface no longer requires a contentType property.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the identical entry interface uses the same structure so im going to keep this the same

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tylerwashington888 Thanks for the clarification! You're absolutely right that maintaining consistency between EntrySys and AssetSys by having them both extend ContentEntitySys is a valid design choice. I understand you want to keep the interface structure aligned across entity types.


✏ Learnings added
Learnt from: tylerwashington888
PR: contentful/ui-extensions-sdk#2338
File: lib/types/utils.ts:73-0
Timestamp: 2025-09-24T16:32:36.609Z
Learning: In the Contentful UI Extensions SDK, both EntrySys and AssetSys interfaces extend ContentEntitySys to maintain consistency, even though assets may not typically use all inherited properties like contentType. This is an intentional design decision for API consistency.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

Copy link
Contributor

@lewisjcs lewisjcs left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would look into what CodeRabbit found to double-check, but I don't see anything else.

@tylerwashington888 tylerwashington888 merged commit 87ab2b1 into main Sep 24, 2025
10 checks passed
@tylerwashington888 tylerwashington888 deleted the feature/EXT-6788-asset-sidebar-location-constants branch September 24, 2025 16:32
contentful-automation bot added a commit that referenced this pull request Sep 24, 2025
# [4.45.0](v4.44.1...v4.45.0) (2025-09-24)

### Features

* ext 6788 asset sidebar location constants [EXT-6786] ([#2338](#2338)) ([87ab2b1](87ab2b1))
@contentful-automation
Copy link
Contributor

🎉 This PR is included in version 4.45.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants