-
Notifications
You must be signed in to change notification settings - Fork 2
Typed resources #20
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
vlboiko
wants to merge
15
commits into
main
Choose a base branch
from
typed_resources
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Typed resources #20
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
- Create separate TypeRegistry instances for search, request, and response body generation - Prevents type name conflicts when the same nested objects appear in different schemas - Ensures consistent naming: ViewsRequestBody_* for request body, ViewResponseBody_* for response body - Fixes issue where SCHEMA=View and POST=views approaches were producing inconsistent results
- Change usePointers from true to false in generateRequestBodyFromSchema and generateResponseBodyFromSchema - Now both POST=views and SCHEMA=View approaches generate fields without pointers - Ensures consistent behavior between URL-based and schema-based generation
- Add toSingularCamelCase function to convert plural resource paths to singular - Update POST-based generation to use singular names (quotas -> Quota, views -> View) - Now both POST=quotas and SCHEMA=Quota generate QuotaResponseBody_* (consistent singular) - Fixes discrepancy where POST generated QuotasResponseBody_* and SCHEMA generated QuotaResponseBody_*
- Added formatGeneratedFiles function that runs go fmt on all generated Go files - Improved code readability with proper field alignment and consistent spacing - Added os/exec import for running go fmt command - Generator now automatically formats all generated files after creation
- Added 'Code generated by generate-typed-resources. DO NOT EDIT.' header to both templates - All generated files now clearly indicate they are auto-generated - Follows Go community convention for marking generated code - Helps prevent accidental manual editing of generated files
Major Changes: - Add +apibuilder:readOnly marker support for read-only resources - Rename requestBody → createBody and responseBody → model for clarity - Add validation to ensure resources have required markers - Create separate read-only template with only Get*/List*/Exists* methods Implementation Details: - Added ReadOnly field to VastResource struct - Updated apibuilder registry with new marker names (createBody:*, model:*) - Updated parser to handle both old and new marker names for compatibility - Added Section field to NestedType for proper template organization - Updated all generation functions to pass section parameter - Created readonly-resource.tpl template for read-only resources - Updated main resource.tpl to use new field names (CreateBody, Model) Validation: - Resources must have searchQuery and model markers - Non-read-only resources must also have createBody marker - Read-only resources skip createBody validation Example Usage: // +apibuilder:readOnly // +apibuilder:searchQuery:GET=versions // +apibuilder:model:SCHEMA=Version type Version struct { *VastResource } Generated Files: - version.go: Read-only resource with only Get*/List*/Exists* methods - quota.go, view.go, vippool.go: Full CRUD resources with CreateBody/Model types - rest.go: Updated to include all typed resources including Version Backward Compatibility: - Old marker names (requestBody, responseBody) still supported - Existing resources continue to work unchanged
Major Changes: - Reorganized examples into untyped/ and typed/ directories - Moved all existing examples to untyped/ directory - Created comprehensive typed examples for resources with apibuilder markers Untyped Examples (examples/untyped/): - All existing examples moved here - Traditional API using client.Params and Record/RecordSet - Manual type conversion with Fill() method - String-based field access Typed Examples (examples/typed/): - basic-usage/: Overview of typed client features - quota/: Full CRUD operations with type safety - view/: Type-safe view management with NFS protocols - vippool/: Type-safe VIP pool configuration - version/: Read-only resource demonstrating compile-time protection - rest-demo/: General typed client demonstration Updated Examples: - Updated existing typed examples to use new naming (CreateBody, Model) - Enhanced examples with comprehensive CRUD operations - Added proper error handling and context usage - Demonstrated read-only resource protection Documentation: - Main README.md: Overview of both approaches with migration guide - untyped/README.md: Detailed guide for traditional API - typed/README.md: Comprehensive guide for typed API with benefits Key Features Demonstrated: - Type safety and compile-time validation - IDE auto-completion and IntelliSense - Read-only resource protection - Automatic field validation - Context support for all operations - Migration path from untyped to typed API Benefits of Typed API: - Compile-time type checking prevents runtime errors - Better IDE support with auto-completion - Self-documenting code with typed structs - Automatic validation of required fields - Read-only protection prevents accidental modifications - Improved maintainability and refactoring support
Major Changes: - Added SetCtx convenience method to typed VMSRest client - Updated rest.tpl template to include the new method - Regenerated typed resources with the new method Implementation: - Added context import to rest.tpl template - Added SetCtx method that delegates to Untyped.SetCtx(ctx) - Method provides convenient shorthand for setting context Template Changes: // SetCtx sets the context for the underlying untyped client // This is a convenience method to avoid having to call r.Untyped.SetCtx(ctx) func (r *VMSRest) SetCtx(ctx context.Context) { r.Untyped.SetCtx(ctx) } Updated Examples: - Updated all typed examples to use new shorthand method - Changed from: typedClient.Untyped.SetCtx(ctx) - Changed to: typedClient.SetCtx(ctx) - Fixed compilation error in basic-usage example (RecordSet access) - Updated rest-demo example to use correct function name Documentation: - Added convenience methods section to typed README - Documented the new SetCtx shorthand method - Provided before/after comparison Benefits: - Cleaner, more intuitive API - Reduces need to access Untyped client directly - Maintains consistency with typed client design - Better developer experience Usage: // Before (still works) typedClient.Untyped.SetCtx(ctx) // After (recommended) typedClient.SetCtx(ctx)
Major Changes: - Added GetSession convenience method to typed VMSRest client - Updated rest.tpl template to include the new method - Regenerated typed resources with the new method Implementation: - Added GetSession method that returns r.Untyped.Session - Method provides convenient shorthand for accessing REST session Template Changes: // GetSession returns the REST session from the underlying untyped client // This is a convenience method to avoid having to call r.Untyped.Session func (r *VMSRest) GetSession() vast_client.RESTSession { return r.Untyped.Session } Updated Examples: - Enhanced basic-usage example to demonstrate GetSession usage - Shows how to access session configuration through the shorthand - Fixed variable naming conflicts in the example Documentation: - Added GetSession to convenience methods section in typed README - Provided before/after comparison for the new method - Documented proper usage with session.GetConfig() Benefits: - Cleaner API for accessing session information - Reduces need to access Untyped client directly - Consistent with other convenience methods - Better developer experience Usage: // Before (still works) session := typedClient.Untyped.Session // After (recommended) session := typedClient.GetSession() // Access session configuration config := session.GetConfig() fmt.Printf("Host: %s, Username: %s", config.Host, config.Username)
- Restored accidentally deleted README files from examples/ - Added GetSession method documentation to typed README - Updated convenience methods section with both SetCtx and GetSession - Provided usage examples for the new shorthand method
Root Cause: - NewParamsFromStruct panicked when passed nil due to reflect.Value.Field() being called on a zero reflect.Value - User passed nil to versionClient.List(nil) causing the panic Fixes Applied: 1. Fixed structToMap function (utils.go): - Prevents panic when calling Field() on zero reflect.Value - Returns empty map for nil inputs gracefully 2. Enhanced typed resource methods: - Added nil checks in all SearchParams methods - Automatically provides empty struct when nil is passed - Applied to both regular and read-only resource templates 3. Updated templates: - resource.tpl: Added nil checks to Get, List, Delete, Exists, Ensure, MustExists methods - readonly-resource.tpl: Added nil checks to Get, List, Exists, MustExists methods - All methods now handle: if req == nil { req = &{{.Name}}SearchParams{} } 4. Regenerated all typed resources with the fixes Benefits: - No more panics when passing nil to typed resource methods - More user-friendly API - nil parameters work as expected - Backward compatible - existing code continues to work - Consistent behavior across all typed resource methods Usage Examples: // These all work now without panics: versions, err := versionClient.List(nil) // ✅ Works versions, err := versionClient.List(&typed.VersionSearchParams{}) // ✅ Works quotas, err := quotaClient.List(nil) // ✅ Works The fix ensures that typed resources are more robust and user-friendly while maintaining type safety and the existing API contract.
Instead of adding nil checks in every typed resource method, the fix is now centralized in NewParamsFromStruct() function. Changes: - Modified NewParamsFromStruct() in serde.go to return empty Params when obj is nil - Removed all nil checks from resource templates (resource.tpl, readonly-resource.tpl) - Regenerated all typed resources with clean templates - The centralized approach is much cleaner and more maintainable Benefits: - Single point of nil handling instead of scattered checks - Cleaner generated code without repetitive nil checks - Same functionality - nil parameters work without panics - More maintainable - changes to nil handling logic only need to be made in one place Usage: // These all work without panics: versions, err := versionClient.List(nil) // ✅ Works quotas, err := quotaClient.List(nil) // ✅ Works
Added production-ready interceptor examples based on working implementation: New Examples: 1. examples/untyped/request-interceptors-with-id/main.go - Advanced interceptors with unique request ID generation - Atomic counter-based ID generation for thread safety - Context-based request ID propagation - Smart body logging (skips null/empty bodies) - Concurrent request demonstration 2. examples/typed/request-interceptors-with-id/main.go - Same features as untyped but with typed client - Demonstrates SetCtx() method usage - Type-safe request/response structures - Typed search parameters and create bodies 3. examples/INTERCEPTORS.md - Comprehensive documentation for all interceptor patterns - Usage examples and best practices - Integration guidance for logging frameworks Improvements to Existing Examples: - Updated examples/untyped/request-interceptors/main.go - Fixed null body logging issue that was printing 'null' - Added smart body detection and JSON compacting - Better error handling and logging format Key Features: ✓ Unique request ID generation using atomic counters ✓ Thread-safe concurrent request tracking ✓ Context-based ID propagation ✓ Smart body logging (skips null/empty) ✓ JSON compacting for readability ✓ Before/After request correlation ✓ Production-ready error handling ✓ Both typed and untyped client examples Usage Pattern: // Create context with request ID ctx := ContextWithRequestID(context.Background()) // For typed client typedClient.SetCtx(ctx) result, err := typedClient.Resource.Method(params) // For untyped client result, err := client.Resource.MethodWithContext(ctx, params) The interceptors automatically log with request ID correlation, making it easy to track request/response pairs in production logs.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Description
Brief description of what this PR does.
Type of Change
Please delete options that are not relevant.
Changes Made
Testing
Documentation
Code Quality
make fmt
andmake lint
locallyBreaking Changes
If this PR contains breaking changes, please describe them here and how users should adapt their code:
Additional Notes
Any additional information that reviewers should know about this PR.
Related Issues
Fixes #(issue number)
Closes #(issue number)
Relates to #(issue number)