Skip to content

feat(swift): add Basic Catalog component schemas and registry - #2377

Open
pinieb wants to merge 4 commits into
a2ui-project:mainfrom
pinieb:pr/swift-basic-catalog-core
Open

feat(swift): add Basic Catalog component schemas and registry#2377
pinieb wants to merge 4 commits into
a2ui-project:mainfrom
pinieb:pr/swift-basic-catalog-core

Conversation

@pinieb

@pinieb pinieb commented Aug 24, 2026

Copy link
Copy Markdown
Collaborator

Summary

Adds the standard Basic Catalog component schemas and registry to the Swift Core SDK, defining all 18 standard A2UI components and 14 built-in client functions across supported specification versions (v0.9, and v0.9.1).

Note: This PR depends on the validation checks and property resolution changes in the base PR.

Key changes

  • Component schemas (BasicCatalogComponents.swift):

    • Implemented JSON schemas for all 18 standard Basic Catalog components:
      • Layout and containers: Row, Column, List, Card, Tabs, Modal, Divider
      • Display: Text, Image, Icon, Video, AudioPlayer
      • Inputs and controls: Button, TextField, CheckBox, ChoicePicker, Slider, DateTimeInput
    • Added BasicCatalogComponents.allComponents to expose the full list of ComponentAPI definitions.
  • Function registry (BasicFunctions.swift):

    • Added BasicFunctions.allFunctions aggregating all 14 standard client-side functions: and, email, formatCurrency, formatDate, formatNumber, formatString, length, not, numeric, openUrl, or, pluralize, regex, and required.
  • Catalog factory and constants (BasicCatalog.swift):

    • Defined canonical catalog URIs for v0.9, and v0.9.1.
    • Added standard themeSchema for Basic Catalog surfaces.
    • Added createCatalog helper and preconfigured instances (v09Catalog, v091Catalog, allCatalogs).

Verification

Ran the Swift test suite:

cd swift/core && swift test

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request introduces validation checks, nested property resolution, typed property accessors, and a pre-configured BasicCatalog containing standard components and functions. Feedback on these changes suggests optimizing performance by converting computed properties (allFunctions and allComponents) to static let constants, coercing .standard properties to .dynamicValue early in resolveProperty when a binding is detected, and removing a redundant object resolution block in SurfaceViewModel.swift.

Comment thread swift/core/Sources/A2UICore/Models/SurfaceViewModel.swift
Comment thread swift/core/Sources/A2UICore/Models/SurfaceViewModel.swift
Comment thread swift/core/Sources/BasicCatalog/BasicFunctions.swift Outdated
Comment thread swift/core/Sources/BasicCatalog/BasicCatalogComponents.swift Outdated
@pinieb
pinieb force-pushed the pr/swift-basic-catalog-core branch 5 times, most recently from a1570f3 to 5aea4db Compare August 25, 2026 19:09
@pinieb

pinieb commented Aug 25, 2026

Copy link
Copy Markdown
Collaborator Author

/gemini review - This has been rebased several times, and I think some of your initial comments were on changes in earlier branches. Could you please do a complete review again?

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request introduces the BasicCatalog module, which provides pre-configured catalog instances, 18 standard component API definitions, and basic client-side functions across supported A2UI specification versions. The feedback suggests optimizing allComponents in BasicCatalogComponents by changing it from a computed property to a static let constant to avoid unnecessary allocations.

Comment thread swift/core/Sources/BasicCatalog/BasicCatalogComponents.swift Outdated
@pinieb
pinieb force-pushed the pr/swift-basic-catalog-core branch 4 times, most recently from 3f7c35c to 4891f9b Compare August 25, 2026 20:13
@pinieb
pinieb marked this pull request as ready for review August 25, 2026 20:23
@pinieb
pinieb requested a review from jacobsimionato August 25, 2026 20:23
@pinieb
pinieb force-pushed the pr/swift-basic-catalog-core branch from 4891f9b to 0f53b44 Compare August 25, 2026 20:27
@pinieb
pinieb force-pushed the pr/swift-basic-catalog-core branch from 0f53b44 to b4c423c Compare August 25, 2026 22:39
@pinieb
pinieb force-pushed the pr/swift-basic-catalog-core branch from b4c423c to ea86585 Compare August 25, 2026 22:45
@pinieb
pinieb enabled auto-merge (squash) August 25, 2026 22:45
/// By conforming ``Catalog`` to `CatalogProtocol`, framework APIs like `MessageProcessor` and `SurfaceViewModel`
/// can accept `[any CatalogProtocol]` and erase them to ``AnyCatalog`` without requiring generic type parameters
/// or forcing callers into complex type-erasure acrobatics.
public protocol CatalogProtocol: Sendable {

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

@jacobsimionato Just wanted to call your attention to this one, since part of #2401 was ditching the CatalogAPI vs Implementation split. This isn't in there to split the Catalog across module boundaries anymore, but instead to support a slightly nicer API surface for clients.

Since MessageProcessor ends up erasing the Catalog types anyways, having this protocol lets clients hand in a heterogenous array of Catalog instances without first having to manually do the type erasure.

In multi-framework scenarios, it takes the call site from MessageProcessor(catalogs: [MyUIKitCatalog.impl.eraseToAnyCatalog(), FancySwiftUICatalog.impl.eraseToAnyCatalog(), SuperPizzazzCustomUIFramework.impl.eraseToAnyCatalog()]) to MessageProcessor(catalogs: [MyUIKitCatalog.impl, FancySwiftUICatalog.impl, SuperPizzazzCustomUIFramework.impl])

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

No worries! This solution sounds great to me - the majority of the code still follows the share structure, and this makes it ergonomic with Swift's type system.

@jacobsimionato jacobsimionato left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Thanks for iterating!!

var functions: [String: any FunctionImplementation] { get }

/// Converts this catalog to a schema-only representation.
func eraseToAnyCatalog() -> AnyCatalog

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I'm not a swift readability expert, but would toAnyCatalog() be a little neater?

public var api: ComponentAPI {
ComponentAPI(name: name, schema: schema)
/// The framework-agnostic API definition (``AnyComponentAPI``).
public var api: AnyComponentAPI {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I think we can remove this now, right? Because the object itself conforms to ComponentApi. You could return self here, but better to just have the callers use self directly I imagine!

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Swift] Refactor ComponentAPI to protocol and align ComponentImplementation and Catalog with blueprints

2 participants