-
Notifications
You must be signed in to change notification settings - Fork 2
fix: improve typescript generator #331
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
base: main
Are you sure you want to change the base?
Changes from all commits
d3e9176
77035c9
e1f09c0
308b0eb
7c54f23
e3f7c4f
10cd347
7b14fba
6355315
b0f792e
cae72a5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,7 +4,9 @@ import { | |
| ConstrainedIntegerModel, | ||
| ConstrainedFloatModel, | ||
| ConstrainedBooleanModel, | ||
| ConstrainedArrayModel | ||
| ConstrainedArrayModel, | ||
| ConstrainedAnyModel, | ||
| ConstrainedUnionModel | ||
| } from '@asyncapi/modelina'; | ||
| import {TypeScriptRenderer} from '@asyncapi/modelina/lib/types/generators/typescript/TypeScriptRenderer'; | ||
| import { | ||
|
|
@@ -32,6 +34,55 @@ function isPrimitiveModel(model: ConstrainedMetaModel): boolean { | |
| ); | ||
| } | ||
|
|
||
| /** | ||
| * Check if the model is a null type (ConstrainedAnyModel with type: null in schema) | ||
| * Modelina converts null types to ConstrainedAnyModel | ||
| */ | ||
| function isNullModel(model: ConstrainedMetaModel): boolean { | ||
| if (!(model instanceof ConstrainedAnyModel)) { | ||
| return false; | ||
| } | ||
| // Check if the original input schema has type: null | ||
| const originalInput = model.originalInput; | ||
| return originalInput && originalInput.type === 'null'; | ||
| } | ||
|
|
||
| /** | ||
| * Check if the model is a date format string type (date or date-time) | ||
| * Note: 'time' format is NOT included because RFC 3339 time strings like "14:30:00" | ||
| * are not valid Date constructor arguments in JavaScript and would produce Invalid Date. | ||
| * Time values should remain as strings. | ||
| */ | ||
| function isDateFormatModel(model: ConstrainedMetaModel): boolean { | ||
| if (!(model instanceof ConstrainedStringModel)) { | ||
| return false; | ||
| } | ||
| const format = model.originalInput?.format; | ||
| return format === 'date' || format === 'date-time'; | ||
| } | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. FormatTime unmarshal returns string despite Date typeMedium Severity The Additional Locations (1) |
||
|
|
||
| /** | ||
| * Render marshal function for null type | ||
| */ | ||
| function renderNullMarshal(model: ConstrainedMetaModel): string { | ||
| return `export function marshal(payload: null): string { | ||
| return JSON.stringify(payload); | ||
| }`; | ||
| } | ||
|
|
||
| /** | ||
| * Render unmarshal function for null type | ||
| */ | ||
| function renderNullUnmarshal(model: ConstrainedMetaModel): string { | ||
| return `export function unmarshal(json: string): null { | ||
| const parsed = JSON.parse(json); | ||
| if (parsed !== null) { | ||
| throw new Error('Expected null value'); | ||
| } | ||
| return null; | ||
| }`; | ||
| } | ||
|
|
||
| /** | ||
| * Render marshal function for primitive types | ||
| */ | ||
|
|
@@ -52,6 +103,27 @@ function renderPrimitiveUnmarshal(model: ConstrainedMetaModel): string { | |
| }`; | ||
| } | ||
|
|
||
| /** | ||
| * Render unmarshal function for date format types | ||
| * Converts JSON string to JavaScript Date object | ||
| */ | ||
| function renderDateUnmarshal(model: ConstrainedMetaModel): string { | ||
| return `export function unmarshal(json: string): ${model.name} { | ||
| const parsed = JSON.parse(json); | ||
| return new Date(parsed); | ||
| }`; | ||
| } | ||
|
|
||
| /** | ||
| * Render marshal function for date format types | ||
| * Note: JSON.stringify(Date) calls Date.toJSON() which returns ISO string | ||
| */ | ||
| function renderDateMarshal(model: ConstrainedMetaModel): string { | ||
| return `export function marshal(payload: ${model.name}): string { | ||
| return JSON.stringify(payload); | ||
| }`; | ||
| } | ||
|
|
||
| /** | ||
| * Render marshal function for array types | ||
| */ | ||
|
|
@@ -86,11 +158,15 @@ function renderArrayMarshal(model: ConstrainedArrayModel): string { | |
| function renderArrayUnmarshal(model: ConstrainedArrayModel): string { | ||
| const valueModel = model.valueModel; | ||
|
|
||
| // Check if array items have an unmarshal method (object types) | ||
| // Check if array items have an unmarshal method (only object types do) | ||
cursor[bot] marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| // Exclude primitives, nested arrays, and union types - they don't have unmarshal methods | ||
| // Union types are just type aliases without static unmarshal methods | ||
| const hasItemUnmarshal = | ||
| valueModel.type !== 'string' && | ||
| valueModel.type !== 'number' && | ||
| valueModel.type !== 'boolean'; | ||
| valueModel.type !== 'boolean' && | ||
| !(valueModel instanceof ConstrainedArrayModel) && | ||
| !(valueModel instanceof ConstrainedUnionModel); | ||
|
|
||
| if (hasItemUnmarshal) { | ||
| const itemTypeName = valueModel.name; | ||
|
|
@@ -145,10 +221,19 @@ export function createPrimitivesPreset( | |
| }) { | ||
| // Handle primitive types (string, integer, float, boolean) | ||
| if (isPrimitiveModel(model)) { | ||
| // Use date-specific marshal/unmarshal for date formats | ||
| const isDate = isDateFormatModel(model); | ||
| const unmarshalFunc = isDate | ||
| ? renderDateUnmarshal(model) | ||
| : renderPrimitiveUnmarshal(model); | ||
| const marshalFunc = isDate | ||
| ? renderDateMarshal(model) | ||
| : renderPrimitiveMarshal(model); | ||
|
|
||
| return `${content} | ||
|
|
||
| ${renderPrimitiveUnmarshal(model)} | ||
| ${renderPrimitiveMarshal(model)} | ||
| ${unmarshalFunc} | ||
| ${marshalFunc} | ||
| ${options.includeValidation ? generateTypescriptValidationCode({model, renderer, asClassMethods: false, context: context as any}) : ''} | ||
| `; | ||
| } | ||
|
|
@@ -163,6 +248,16 @@ ${options.includeValidation ? generateTypescriptValidationCode({model, renderer, | |
| `; | ||
| } | ||
|
|
||
| // Handle null types (ConstrainedAnyModel with type: null in original schema) | ||
| if (isNullModel(model)) { | ||
| return `${content} | ||
|
|
||
| ${renderNullUnmarshal(model)} | ||
| ${renderNullMarshal(model)} | ||
| ${options.includeValidation ? generateTypescriptValidationCode({model, renderer, asClassMethods: false, context: context as any}) : ''} | ||
| `; | ||
| } | ||
|
|
||
| return content; | ||
| } | ||
| } | ||
|
|
||


Uh oh!
There was an error while loading. Please reload this page.