Skip to content

feat: add rich signatures, schema expansion, and examples#4

Merged
mberrishdev merged 1 commit into
mainfrom
feature/rich-signatures-schemas
Apr 19, 2026
Merged

feat: add rich signatures, schema expansion, and examples#4
mberrishdev merged 1 commit into
mainfrom
feature/rich-signatures-schemas

Conversation

@mberrishdev
Copy link
Copy Markdown
Owner

@mberrishdev mberrishdev commented Apr 19, 2026

Note

Medium Risk
Changes the shape and contents of hubdocs.json (new fields for signatures/parameters/schemas/examples) and adds reflection-based schema generation, which could break existing consumers or produce unexpected output for complex types/nullability.

Overview
HubDocs metadata output is expanded: hub and client methods now include full Signature, typed Parameters (with nullability), and example invocations/return examples, and hubs expose a new Schemas section describing discovered DTO/enums used by method parameters/returns.

Reflection/type formatting was upgraded to use C# keyword aliases (e.g. int, string), handle Task/Task<T> return signatures, and derive nullable reference info via NullabilityInfoContext; unit tests were updated accordingly.

The UI (hubdocs.html) now renders signatures, examples, pre-fills Try It inputs from examples, and shows the new schema browser. The sample ChatHub adds a rich-message payload + enum and new SendRichMessage/ReceiveRichMessage methods to exercise the schema output.

Reviewed by Cursor Bugbot for commit 4fffeed. Bugbot is set up for automated code reviews on this repo. Configure here.

@mberrishdev mberrishdev merged commit c681950 into main Apr 19, 2026
3 checks passed
@mberrishdev mberrishdev deleted the feature/rich-signatures-schemas branch April 19, 2026 18:16
Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 3 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 4fffeed. Configure here.

Comment thread src/HubDocs/Extensions.cs
if (nullable)
return "null";

var normalized = NormalizeType(type);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Collection examples show element value instead of array

High Severity

CreateExampleLiteral calls NormalizeType which unwraps collection types (e.g. List<string>string, int[]int) before the simple-type checks run. The collection check on lines 466–475 uses the original type, but execution never reaches it because the normalized element type already matched a simple-type branch. For example, List<int> returns "123" and List<string> returns "\"example\"" instead of "[]". This visibly affects the sample ChatHub.JoinRoom roles parameter and ChatMessagePayload.Tags property.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 4fffeed. Configure here.

Comment thread src/HubDocs/Extensions.cs
return $"{FormatType(type.GetElementType()!)}[]";

if (TryGetKeywordAlias(type, out var alias))
return alias;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Nullable keyword-aliased types missing question mark suffix

Medium Severity

FormatTypeWithNullability returns the keyword alias immediately when TryGetKeywordAlias matches, without considering the nullableReference flag. For nullable reference types with keyword aliases (e.g. string?, object?), the output is "string" instead of "string?". The nullability suffix logic on lines 257–258 and 268–269 is only reachable for types that don't have a keyword alias.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 4fffeed. Configure here.

Comment thread src/HubDocs/Extensions.cs

public static class Extensions
{
private static readonly NullabilityInfoContext NullabilityContext = new();
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Static NullabilityInfoContext is not thread-safe

Medium Severity

NullabilityInfoContext is stored as a private static readonly field and accessed from the /hubdocs/hubdocs.json HTTP endpoint handler, which can serve concurrent requests. NullabilityInfoContext is not thread-safe — its internal dictionary cache can throw InvalidOperationException or ArgumentException when accessed concurrently. Creating a new instance per invocation avoids this.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 4fffeed. Configure here.

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