Skip to content

feat: Generate TypeScript types#30

Draft
haveyaseen wants to merge 94 commits intomainfrom
generator-ts
Draft

feat: Generate TypeScript types#30
haveyaseen wants to merge 94 commits intomainfrom
generator-ts

Conversation

@haveyaseen
Copy link
Member

  • Add TypeScript transformer that converts Forst AST to .d.ts files
  • Implement proper type mapping from Forst to TypeScript types
  • Add generate command to create TypeScript client declarations
  • Support both single files and directories for generation
  • Generate module augmentation for @forst/sidecar client

- Add TypeScript transformer that converts Forst AST to .d.ts files
- Implement proper type mapping from Forst to TypeScript types
- Add generate command to create TypeScript client declarations
- Support both single files and directories for generation
- Generate module augmentation for @forst/sidecar client
- Add --log-level flag to dev command for controlling log verbosity
- Support trace, debug, info, warn, error log levels
- Default to info level if not specified
- Gracefully handle invalid log levels by falling back to info
- Add support for function metadata including streaming capability
- Improve function discovery to capture return types and parameters
- Add FunctionInfo struct for better type safety
- Support for detecting streaming functions in discovery
- Add streaming support to sidecar server for real-time data
- Improve type definitions for better TypeScript integration
- Add support for streaming function execution
- Enhance error handling and response types
- Add streaming function execution support to dev server
- Improve function discovery with metadata support
- Add proper error handling for streaming requests
- Support for chunked transfer encoding in responses
- Add comprehensive examples for client integration
- Include TypeScript client usage examples
- Add streaming function examples
- Demonstrate proper error handling and type safety
@haveyaseen haveyaseen changed the title feat(transformer): Generate TypeScript types feat: Generate TypeScript types Jul 12, 2025
…integration

- Refactor TypeScript transformer to generate Prisma-like client structure
- Add centralized types file generation
- Create per-package client wrappers with proper error handling
- Generate main ForstClient class exposing packages as properties
- Update generate command to create client package structure
- Rename ForstClient to ForstSidecarClient in sidecar package to avoid conflicts
- Add comprehensive logging to sidecar client for better debugging
- Create client integration example demonstrating new API
- Update Taskfile.yml to support new client generation workflow
- Add proper package.json configurations for generated client packages
- Add support for Contains constraint in ensure statements
- Fix ensure statement generation for type guards without constraints
- Implement structural type aliasing to map hash-based types to user-defined types
- Add comprehensive type emission scanning to ensure all referenced types are emitted
- Improve type guard compatibility checking using type checker's IsTypeCompatible
- Add fallback type emission for hash-based types found in generated code
- Enhance type aliasing logic to compare shape structures for identity
- Fix ensure condition transformation to handle type guard calls properly
- Add debug logging throughout type emission and aliasing process
- Use IsTypeCompatible for type guard checks, supporting hash-based/user-defined structural compatibility
- Enhance IsTypeCompatible to check for structural identity between shape types
- Apply type aliasing logic in both getTypeAliasNameForTypeNode and getGeneratedTypeNameForTypeNode
- Fixes ensure statement and type guard compatibility for shape literals
- Add getAliasedTypeNameForTypeNode helper for consistent type aliasing
- Update transformType and transformFunctionParams to use aliased names
- Fix TypeKind setting in type inference for hash-based types
- Update transformShapeNodeWithExpectedType to use aliased type names
- Set TypeKindHashBased in inferShapeType, InferAssertionType, and LookupAssertionType
- Ensures structural compatibility between hash-based and user-defined types is recognized
- Update return statement transformation to use expected return types from function signature
- Pass expected return types to transformShapeNodeWithExpectedType for struct literals in return values
- Ensures return statements use aliased type names instead of hash-based names
- Add bug report documenting the pointer field issue where transformer
  generates invalid Go syntax '&*User{name: "Alice"}' instead of
  correct '&User{name: "Alice"}'
- Fix pointer field logic in transformer to correctly wrap struct
  literals in & for pointer fields instead of emitting them directly
- Update pointer field logic to handle struct literals properly by
  wrapping them in & when they are in pointer fields
- Ensure pointer fields use correct Go syntax without double operators

This fixes the shape guard example compilation error where pointer
fields were generating invalid Go code with both & and * operators.
- Add bug report documenting the issue where transformer uses hash-based
  types instead of named types for shape literals
- Fix shape matching logic to prioritize expected types over structural
  matching when generating struct literals passed to functions
- Add validation using typechecker's ValidateShapeFields method to
  ensure compatibility between expected and actual types
- Update transformer to use named types when compatible, falling back
  to hash-based types only when necessary
- Add comprehensive unit tests to verify named type usage and hash-based
  type fallback behavior
- Split existing tests into focused test cases for better coverage

This fixes the shape guard example compilation errors where struct
literals used hash-based types instead of expected named types.
- Add bug report documenting the issue where nested shapes use hash-based
  types instead of expected named types like AppContext and User
- Fix field types extraction logic to handle assertion types properly
  by adding support for field.Assertion != nil cases
- Update nested shape transformation to extract base type from pointer
  types for inner struct transformations
- Add detailed logging to trace field types extraction and shape
  matching for debugging nested shape issues
- Ensure nested shapes use named types when compatible with expected
  type structure

This fixes the shape guard example compilation errors where nested
shapes used hash-based types instead of expected named types due to
improper field types extraction for assertion types.
- Add comprehensive test utilities for creating AST nodes in transformer
  tests including makeTypeDef, makeShape, makeShapeField, etc.
- Fix test expectations to accept nil field values since explicit
  types are used instead of actual values
- Update shape guard integration test to expect hash-based types when
  no BaseType is set
- Add minimal unit test reproducing shape guard type mismatch bug
- Ensure all transformer tests pass with updated test utilities and
  expectations

This improves test coverage and reliability for transformer
functionality, particularly for shape guard and type matching features.
- Add TypeScript transformer with client, function, output, type_mapping,
  and typedef modules
- Implement TypeScript code generation for Forst AST nodes
- Add type mapping between Forst and TypeScript types
- Support function transformation with parameter and return type handling
- Add typedef transformation for type definitions and aliases
- Include output formatting for TypeScript code generation

This provides the foundation for TypeScript code generation from
Forst source code, enabling TypeScript interoperability.
- Add comprehensive test for parsing shape guard assertions like
  AppMutation.Input({input: {name: String}})
- Test parsing of complex type assertions with nested shapes
- Verify correct AST structure for shape guard assertions
- Test field parsing for nested shapes in assertion arguments
- Ensure parser correctly handles shape guard syntax and structure

This improves test coverage for shape guard parsing functionality
and validates the parser's ability to handle complex type assertions.
- Add ValidateShapeFields method to typechecker for validating
  compatibility between expected and actual shape fields
- Improve type inference for assertion types and nested shapes
- Add better error handling and logging for type inference
- Enhance shape field lookup and validation logic
- Improve type unification for complex type structures
- Add support for validating shape field compatibility

This improves the typechecker's ability to validate shape
compatibility and provides better type inference for complex
type structures like shape guards.
- Add support for complex assertion types and nested shapes
- Improve type definitions for shape guard assertions
- Add better type representations for pointer and assertion types
- Enhance AST node structures for complex type relationships
- Add support for type constraints and refinements
- Improve type system representation for shape guards

This enhances the AST to better represent complex type structures
like shape guards and type assertions.
- Improve parsing of assertion types and nested shapes
- Add better support for shape guard syntax and structures
- Enhance field parsing for complex type definitions
- Add support for parsing type constraints and refinements
- Improve error handling and logging for complex parsing
- Add better AST construction for shape guard assertions

This improves the parser's ability to handle complex type
structures like shape guards and type assertions.
- Improve assertion type transformation and handling
- Add better support for shape guard transformations
- Enhance type guard transformation and validation
- Add support for complex type definitions and aliases
- Improve function parameter and return type handling
- Add better error handling and logging for transformations
- Enhance typedef expression transformation
- Add support for ensure statement transformations

This improves the Go transformer's ability to handle complex
type structures like shape guards and type assertions.
- Update basic_communication.ft example to reflect current
  language features and syntax
- Improve example to demonstrate proper shape guard usage
- Add better comments and documentation for the example
- Ensure example follows current Forst language conventions

This updates the example to be consistent with current
language features and provides better documentation.
- Improve server error handling and logging
- Add better type safety and validation
- Enhance server configuration and setup
- Add support for better error reporting
- Improve server stability and reliability

This enhances the sidecar server implementation with better
error handling and type safety.
- Update Cursor rules for better development experience
- Add gitignore patterns for generated files and build artifacts
- Improve development workflow documentation
- Add better project structure documentation
- Update development guidelines and best practices

This improves the development environment and project
documentation for better developer experience.
- Remove packages/client/examples/usage.ts as it's no longer needed
- Clean up unused example files to reduce repository clutter
- Remove outdated client example that doesn't match current API

This cleans up the repository by removing unused example files.
- Create ast/testing.go with all AST node creation functions
- Update all test_utils.go files to use centralized package
- Remove duplicate AST creation code across packages
- Standardize AST testing utilities across codebase
- Remove builder pattern from ast/testing.go
- Use direct function calls with consistent naming
- Update all test files to use centralized AST testing package
- Remove all wrapping make functions from test_utils.go files
- Replace testify/assert with standard Go testing
- Fix type issues and method names in tests
- Updated TestTransformExpression_StructLiteralWithPointerField to expect function call output instead of just struct literal
- Updated TestTransformExpression_StructLiteralWithIncompatibleType to reflect current transformer behavior (uses BaseType over structural matching)
- All tests now pass with the centralized AST testing package and Go testing assertions
…d nested shapes

- parseShapeTypeField: store nested shape types as Type with Assertion
- parseConstraintArgument: use parseShapeLiteral for shape literals in assertions
- parseShapeLiteral: treat identifiers after colon as type annotations when appropriate

This ensures shape guards and nested shape types are parsed as expected for typechecking and codegen.
…er field emission

- Struct literals now use named types instead of hash-based types when compatible
- Pointer fields in struct literals default to nil (Go idiomatic), not &Type{}
- All related unit tests updated to expect correct Go behavior
- Fixes hash-based type emission and pointer/value mismatch bugs
- All transformer unit tests now pass
- ensure bun install runs only once
- Add run: once to install:bun task to prevent parallel execution and EEXIST errors
- This ensures bun install is not run in parallel by multiple dependent tasks
- Fixes issues with symlink creation and file system conflicts during builds
- Replace simplistic IsShapeSuperset with robust IsShapeCompatibleWithNamedType
- Use existing resolveShapeFieldsFromAssertion for complex nested assertions
- Fix pointer field generation to avoid invalid &*Type{} syntax
- Ensure struct literals use base type for pointer fields (e.g., &User{} not &*User{})
- Maintain strict type compatibility while preserving named types when possible

Fixes shape guard example where AppMutation.Input(...) correctly resolves to
both ctx and input fields through proper constraint merging.

- fix(transformer): correct pointer/value handling, assertion field resolution, and hash-based type emission for nested struct literals

- Always add & for ReferenceNode in pointer context
- Preserve pointer context for nested struct literals
- Remove duplicate pointer wrapping logic
- Add expectedTypeForField parameter to buildFieldValue and propagate it
- Emit hash-based types in transformShapeNodeWithExpectedType
- Fix assertion field resolution in buildFieldsForExpectedType to use the actual type

This fixes pointer/value mismatches and ensures all referenced types are emitted in generated Go code, especially for shape guard and nested struct scenarios.
…apitalization

The executor was using ExportReturnStructFields=true which caused all struct
literals to have capitalized field names. This was incorrect for function
implementations where we should use the original field names from the type
definition.

Changed executor to use ExportReturnStructFields=false so that function
implementations use the correct field names while still allowing external
API types to be properly capitalized when needed.
- Add IsTypeGuardConstraint helper to TypeChecker for robust type guard detection
- Refactor ensure statement transformation to use the helper instead of iterating over Defs
- Fix negation logic: ensure statements now correctly negate type guard conditions
- Update transformer tests to use the new helper method
- Clean up debug logging from ensure statement transformation
- Update NewTestParser calls in shape_test.go to pass logger argument
- Fix build errors in parser unit tests by providing ast.SetupTestLogger()
- All parser unit tests now pass successfully
- Refactor TypeKind from int to string for better type safety
- Add helper functions for creating typed TypeNodes (NewBuiltinType, NewUserDefinedType, etc.)
- Improve type inference and registration with proper TypeKind handling
- Add new builtin constraints: NotEmptyConstraint and ValidConstraint
- Enhance error return statement generation with proper zero value handling
- Add comprehensive debug logging for type inference and transformation
- Improve struct literal generation with better named type handling
- Add robust field matching and wrapping for return statements
- Update parser to use new TypeNode constructors
- Enhance executor with debug output for generated Go code
- Replace Path field with FileID in Token struct for improved language server integration
- Update lexer tests to use FileID instead of testFilePath for consistency
- Modify parser context to use FileID instead of FilePath for better error reporting
- Update error message formatting to use FileID in parse errors
- Refactor function return type parsing to handle shape types properly
- Improve error statement transformation with better zero value handling
- Reduce retry count in sidecar client from 3 to 1 for faster failure detection
- Add comprehensive logging for debugging type inference and error handling

This change improves the compiler's integration with language servers by using
stable file identifiers instead of file paths, which can change during editing.
The refactoring also includes improvements to error handling and type inference
for better developer experience.
- Update TestFormatDebugEvent to expect 'file_id=' instead of 'file=' format
- Fix TestLSPServerDebugInfoForLLM to only expect available debug info fields
- Remove expectations for non-existent compilerState and phaseDetails fields
- Align test expectations with actual implementation after Path->FileID migration

These changes ensure integration tests pass after the recent migration
from file paths to file IDs for better LSP support.
…ed behavior

- Add specific check for main functions using isMainFunction() method
- Use os.Exit(1) for main functions to terminate process cleanly
- Use panic for non-main void functions to provide stack trace
- Separate logic for main vs other void functions for better error handling
- Maintain backward compatibility while improving error reporting

This change provides more appropriate error handling:
- Main functions terminate the process with exit code 1
- Other void functions panic to provide debugging information
- Better distinction between program termination vs runtime errors
This commit fixes critical bugs in the sidecar integration where functions
returning multiple values (result + error) were not being handled correctly.

- **Root Cause**: Discovery was using parser's empty `ReturnTypes` field instead of
  typechecker's inferred return types for functions without explicit annotations
- **Fix**: Modified discovery to use typechecker's inferred return types from function bodies
- **Impact**: Functions with `ensure` statements now correctly identified as returning 2 values

- **Root Cause**: Go module generation assumed single return values for all functions
- **Fix**: Added `HasMultipleReturns` flag to track functions returning multiple values
- **Impact**: Generated Go code now correctly handles both single and multiple return values

- **Root Cause**: Missing nil checks when accessing `s.ExplicitTypes[0]` in transformer
- **Fix**: Added proper bounds checking and nil validation
- **Impact**: Eliminated runtime panics during AST transformation

- **Root Cause**: `buildZeroCompositeLiteral` used `nil` for user-defined types
- **Fix**: Implemented recursive zero value generation for user-defined types
- **Impact**: Proper zero values generated for struct fields in error returns

- Added `HasMultipleReturns` field to `FunctionInfo` struct
- Modified `extractFunctionsFromNode` to use typechecker's inferred return types
- Updated `analyzeStreamingSupport` to accept typechecker parameter
- Added fallback logic when typechecker is unavailable

- Added `HasMultipleReturns` field to `CompiledFunction` struct
- Updated `createTempGoFile` and `createStreamingTempGoFile` to pass return info
- Modified `compileFunction` to set return type information from discovery

- Added `HasMultipleReturns` field to `ModuleConfig` struct
- Updated `generateStandardMainGo` to handle both single and multiple return values
- Added conditional logic for result/error vs single result handling

- Fixed `AssignmentNode` processing with proper nil checks
- Enhanced `buildZeroCompositeLiteral` with recursive zero value generation
- Improved error handling in statement transformation
- Set ExportReturnStructFields=true in executor to enable proper JSON marshalling
- Fix field name capitalization in buildFieldsForExpectedType, buildCompositeLiteralForReturn, buildZeroCompositeLiteral, and wrapVariableInNamedStruct
- Remove debug printf statement from generated main.go
- Update example files to use proper function signatures
- Fix executeGoCode function signature and improve logging

This ensures struct fields are properly capitalized (exported) so json.Marshal can include field values instead of producing empty objects.
- Add resolveTypeName function to discovery package for proper type conversion
- Move IsGoBuiltinType to typechecker package as standalone function
- Fix main.go template generation to handle built-in types correctly
- Remove duplicate isGoBuiltinType function from transformer/util.go
- Update type field handling to use centralized built-in type checking
- Fix parameter passing in generated main.go for built-in vs struct types

This ensures Forst built-in types (String, Int) are properly converted to Go types (string, int)
and fixes the "undefined: user_LsBa.string" compilation errors by using correct type names
without package prefixes for built-in types.
…ber decoding

- Change function parameter passing from object to array format for consistency
- Fix JSON number decoding issue where integers are decoded as float64 in Go
- Add type assertion logic to handle both float64 and int cases for numeric parameters
- Update client interfaces to use array format for function arguments
- Refactor main.go generation to extract parameters from JSON array input
- Add proper error handling for parameter type mismatches
- Update test cases to use array format for function calls

This fixes the issue where JSON numbers like 29 were being decoded as float64
instead of int, causing type assertion failures in generated Go code.
- Fix function context issues in transformer tests by creating proper function scopes
  * Add main function nodes to establish proper scope for function call tests
  * Use CheckTypes() and RestoreScope() to set up correct typechecker context
  * Transform function calls within established function scope instead of global scope

- Fix streaming support analysis in discovery package
  * Check original type names before hash-based conversion for "stream" and "channel" detection
  * Use ast.NewUserDefinedType() to create proper TypeNode instances in tests

- Update test expectations to match actual behavior
  * Change expected type names from Forst types ("String") to Go types ("string")
  * Adjust test assertions to account for shape matching logic behavior
  * Remove outdated expectations about type definitions in tc.Defs

- Fix function signature mismatches
  * Update function calls to include required *typechecker.TypeChecker parameter
  * Ensure all discovery package tests use correct function signatures

All unit tests now pass with proper function context handling and type resolution.
- Reorder fields in User, CreateUserRequest, and T_NGUd7jXQkPf interfaces
- Remove generated basic_communication.client.ts and types.ts files
- Clean up test client type definitions for better organization
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