Skip to content

feat(genui): support ref schema resolution and validation via SchemaRegistry#998

Open
gspencergoog wants to merge 9 commits into
flutter:mainfrom
gspencergoog:fix-ref-validation
Open

feat(genui): support ref schema resolution and validation via SchemaRegistry#998
gspencergoog wants to merge 9 commits into
flutter:mainfrom
gspencergoog:fix-ref-validation

Conversation

@gspencergoog

Copy link
Copy Markdown
Collaborator

Summary

This PR enables validation of component definitions containing $ref schemas (such as references to common_types.json) by integrating a SchemaRegistry to compile and resolve external schema references.

Changes

  • Schema Validation & Reference Resolution:

    • Updated component validation logic in packages/genui/lib/src/model/schema_validation.dart to use json_schema_builder's robust schema validation (Schema.validate) instead of a basic hand-rolled implementation.
    • Modified validateComponents (in schema_validation.dart) and SurfaceDefinition.validate (in ui_models.dart) to be asynchronous to support the asynchronous reference validation interface of json_schema_builder.
    • Exported SchemaRegistry in packages/json_schema_builder/lib/json_schema_builder.dart to make it publicly accessible.
  • Embedded Schemas & build_runner Builder:

    • Added build and build_runner dev-dependencies to packages/genui/pubspec.yaml.
    • Implemented a custom build_runner builder in packages/genui/tool/schema_builder.dart and registered it in packages/genui/build.yaml. The builder automatically embeds common_types.json and server_to_client.json from the a2ui specification submodule into static string literals in lib/src/primitives/embedded_schemas.g.dart.
    • Updated SurfaceController._getSchemaRegistry to synchronously load and populate the registry with the embedded common types schema.
  • Testing and Bug Fixes:

    • Fixed an issue in packages/genui/test/catalog/core_widgets/button_test.dart where manual subscription cancellation on closed stream controllers caused the test runner to hang in FakeAsync zones. Refactored the test to use SurfaceController.dispose() for listener cleanup.
    • Updated unit tests in surface_controller_test.dart and ui_models_test.dart to align with the new asynchronous validation signature.

Impact & Risks

  • Breaking Change: The SurfaceDefinition.validate method now returns a Future<void> instead of void. Since this is primarily an internal component representation validation helper, the public integration surface impact is low, but tests that manually validate schemas must be updated to await the validation.
  • Added CHANGELOG.md entry in packages/genui documenting this change.

Testing

  1. Automatic Verification:

    • Run static analysis:
      dart analyze packages/genui
      Verify that there are no analyzer warnings or errors.
    • Run the full test suite:
      flutter test packages/genui
      Verify that all 279 tests (including the updated button validation and schema matching tests) compile and pass successfully.
  2. Re-generating Schemas:

    • Clean and run code generation:
      dart run build_runner build
      Verify that embedded_schemas.g.dart is correctly regenerated.

…egistry

- Changed `SurfaceDefinition.validate` and validation APIs to be asynchronous to support resolving `$ref` schemas.
- Integrated `SchemaRegistry` to validate component schemas using local assets or filesystem.
- Exported `SchemaRegistry` in `json_schema_builder`.
- Updated CHANGELOG.md for the breaking change.
- Fixed a button widget stream test issue where manual subscription cancellation caused test runner hangs.
- Created `packages/genui/tool/generate_embedded_schemas.dart` script to compile schema JSONs to Dart string constants.
- Generated `packages/genui/lib/src/primitives/embedded_schemas.dart` containing embedded A2UI schemas.
- Updated `SurfaceController._getSchemaRegistry` to load the common types schema synchronously from the embedded string literal.
- Unregistered the assets from `packages/genui/pubspec.yaml` and deleted the local asset files.
- Removed unused assets-related constants from `packages/genui/lib/src/primitives/constants.dart`.
- Integrated schema compilation into the standard Dart `build_runner` framework.
- Created `packages/genui/tool/schema_builder.dart` implementing the `Builder` interface to copy schemas from submodules at build time.
- Configured `packages/genui/build.yaml` to trigger `schema_builder` on `pubspec.yaml` changes.
- Added `build` and `build_runner` as dev_dependencies in `packages/genui/pubspec.yaml`.
- Deleted the temporary standalone `generate_embedded_schemas.dart` script.
@github-actions

github-actions Bot commented Jul 10, 2026

Copy link
Copy Markdown

Package publishing

If you have publishing permissions, you can use the links below to publish the changes after merging this PR.

Package Version Status Publish tag (post-merge)
package:a2ui_core 0.0.1-wip002 ready to publish a2ui_core-v0.0.1-wip002
package:genai_primitives 0.2.4 ready to publish genai_primitives-v0.2.4
package:genui 0.9.2 (error) pubspec version (0.9.2) and changelog (0.10.0) don't agree
package:genui_a2a 0.9.0 (error) pubspec version (0.9.0) and changelog (0.10.0) don't agree
package:json_schema_builder 0.1.6 ready to publish json_schema_builder-v0.1.6

Documentation at https://github.com/dart-lang/ecosystem/wiki/Publishing-automation.

- Renamed generated schemas file extension to `.g.dart` to follow Dart builder conventions.
- Updated SchemaBuilder implementation and build.yaml configurations to output to `.g.dart`.
- Updated import references in surface_controller.dart.
gemini-code-assist[bot]

This comment was marked as resolved.

…dation

- Updated button event handler to use StreamIterator to prevent synchronous race conditions.
- Configured schema builder to throw a descriptive StateError if the A2UI submodule is not checked out.
- Simplified button test mock stream to use Stream.error and wrapped test execution inside tester.runAsync.
- Optimized _getSchemaRegistry() in SurfaceController to be synchronous and removed redundant await calls.
- Bumped json_schema_builder version to 0.1.6 and documented public SchemaRegistry export in CHANGELOG.md.
gemini-code-assist[bot]

This comment was marked as resolved.

…a builder

- Changed schema builder's auto_apply policy to none in build.yaml to prevent breaking dependents.
- Added check during directory traversal in schema_builder.dart to throw a descriptive StateError if .gitmodules is not found.
- Updated missing schema source files handling to throw a StateError directly instead of failing silently.
gemini-code-assist[bot]

This comment was marked as resolved.

gspencergoog and others added 2 commits July 10, 2026 12:22
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
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.

1 participant