11import { TypeScriptRenderer } from '../TypeScriptRenderer' ;
22import { TypeScriptPreset } from '../TypeScriptPreset' ;
3- import { getUniquePropertyName , DefaultPropertyNames } from '../../../helpers' ;
4- import { CommonModel } from '../../../models' ;
3+ import { getUniquePropertyName , DefaultPropertyNames , TypeHelpers , ModelKind } from '../../../helpers' ;
4+ import { CommonInputModel , CommonModel } from '../../../models' ;
55import renderExampleFunction from './utils/ExampleFunction' ;
66
77export interface TypeScriptCommonPresetOptions {
@@ -12,55 +12,66 @@ export interface TypeScriptCommonPresetOptions {
1212function realizePropertyFactory ( prop : string ) {
1313 return `$\{typeof ${ prop } === 'number' || typeof ${ prop } === 'boolean' ? ${ prop } : JSON.stringify(${ prop } )}` ;
1414}
15-
16- function renderMarshalProperties ( model : CommonModel , renderer : TypeScriptRenderer ) {
15+ function renderMarshalProperty ( modelInstanceVariable : string , model : CommonModel , inputModel : CommonInputModel ) {
16+ if ( model . $ref ) {
17+ const resolvedModel = inputModel . models [ model . $ref ] ;
18+ const propertyModelKind = TypeHelpers . extractKind ( resolvedModel ) ;
19+ //Referenced enums only need standard marshalling, so lets filter those away
20+ if ( propertyModelKind !== ModelKind . ENUM ) {
21+ return `$\{${ modelInstanceVariable } .marshal()}` ;
22+ }
23+ }
24+ return realizePropertyFactory ( modelInstanceVariable ) ;
25+ }
26+ function renderMarshalProperties ( model : CommonModel , renderer : TypeScriptRenderer , inputModel : CommonInputModel ) {
1727 const properties = model . properties || { } ;
1828 const propertyKeys = [ ...Object . entries ( properties ) ] ;
1929 const marshalProperties = propertyKeys . map ( ( [ prop , propModel ] ) => {
2030 const formattedPropertyName = renderer . nameProperty ( prop , propModel ) ;
2131 const modelInstanceVariable = `this.${ formattedPropertyName } ` ;
22- const propMarshalReference = `json += \`"${ prop } ": $\{this.${ formattedPropertyName } .marshal()},\`;` ;
23- const propMarshal = `json += \`"${ prop } ": ${ realizePropertyFactory ( modelInstanceVariable ) } ,\`;` ;
24- const propMarshalCode = propModel . $ref !== undefined ? propMarshalReference : propMarshal ;
25- return `if(this.${ formattedPropertyName } !== undefined) {
26- ${ propMarshalCode }
32+ const propMarshalCode = renderMarshalProperty ( modelInstanceVariable , propModel , inputModel ) ;
33+ const marshalCode = `json += \`"${ prop } ": ${ propMarshalCode } ,\`;` ;
34+ return `if(${ modelInstanceVariable } !== undefined) {
35+ ${ marshalCode }
2736}` ;
2837 } ) ;
2938 return marshalProperties . join ( '\n' ) ;
3039}
3140
32- function renderMarshalPatternProperties ( model : CommonModel , renderer : TypeScriptRenderer ) {
41+ function renderMarshalPatternProperties ( model : CommonModel , renderer : TypeScriptRenderer , inputModel : CommonInputModel ) {
3342 let marshalPatternProperties = '' ;
3443 if ( model . patternProperties !== undefined ) {
3544 for ( const [ pattern , patternModel ] of Object . entries ( model . patternProperties ) ) {
3645 let patternPropertyName = getUniquePropertyName ( model , `${ pattern } ${ DefaultPropertyNames . patternProperties } ` ) ;
3746 patternPropertyName = renderer . nameProperty ( patternPropertyName , patternModel ) ;
38- const patternPropertyMarshalReference = 'json += `"${key}": ${value.marshal()},`;' ;
39- const patternPropertyMarshal = `json += \`"$\{key}": ${ realizePropertyFactory ( 'value' ) } ,\`;` ;
47+ const modelInstanceVariable = 'value' ;
48+ const patternPropertyMarshalCode = renderMarshalProperty ( modelInstanceVariable , patternModel , inputModel ) ;
49+ const marshalCode = `json += \`"$\{key}": ${ patternPropertyMarshalCode } ,\`;` ;
4050 marshalPatternProperties += `if(this.${ patternPropertyName } !== undefined) {
4151 for (const [key, value] of this.${ patternPropertyName } .entries()) {
4252 //Only render pattern properties which are not already a property
4353 if(Object.keys(this).includes(String(key))) continue;
44- ${ patternModel . $ref !== undefined ? patternPropertyMarshalReference : patternPropertyMarshal }
54+ ${ marshalCode }
4555 }
4656}` ;
4757 }
4858 }
4959 return marshalPatternProperties ;
5060}
5161
52- function renderMarshalAdditionalProperties ( model : CommonModel , renderer : TypeScriptRenderer ) {
62+ function renderMarshalAdditionalProperties ( model : CommonModel , renderer : TypeScriptRenderer , inputModel : CommonInputModel ) {
5363 let marshalAdditionalProperties = '' ;
5464 if ( model . additionalProperties !== undefined ) {
5565 let additionalPropertyName = getUniquePropertyName ( model , DefaultPropertyNames . additionalProperties ) ;
5666 additionalPropertyName = renderer . nameProperty ( additionalPropertyName , model . additionalProperties ) ;
57- const additionalPropertyMarshalReference = 'json += `"${key}": ${value.marshal()},`;' ;
58- const additionalPropertyMarshal = `json += \`"$\{key}": ${ realizePropertyFactory ( 'value' ) } ,\`;` ;
67+ const modelInstanceVariable = 'value' ;
68+ const patternPropertyMarshalCode = renderMarshalProperty ( modelInstanceVariable , model . additionalProperties , inputModel ) ;
69+ const marshalCode = `json += \`"$\{key}": ${ patternPropertyMarshalCode } ,\`;` ;
5970 marshalAdditionalProperties = `if(this.${ additionalPropertyName } !== undefined) {
6071 for (const [key, value] of this.${ additionalPropertyName } .entries()) {
6172 //Only render additionalProperties which are not already a property
6273 if(Object.keys(this).includes(String(key))) continue;
63- ${ model . additionalProperties . $ref !== undefined ? additionalPropertyMarshalReference : additionalPropertyMarshal }
74+ ${ marshalCode }
6475 }
6576}` ;
6677 }
@@ -70,82 +81,100 @@ function renderMarshalAdditionalProperties(model: CommonModel, renderer: TypeScr
7081/**
7182 * Render `marshal` function based on model
7283 */
73- function renderMarshal ( { renderer, model } : {
84+ function renderMarshal ( { renderer, model, inputModel } : {
7485 renderer : TypeScriptRenderer ,
7586 model : CommonModel ,
87+ inputModel : CommonInputModel
7688} ) : string {
7789 return `public marshal() : string {
7890 let json = '{'
79- ${ renderer . indent ( renderMarshalProperties ( model , renderer ) ) }
80- ${ renderer . indent ( renderMarshalPatternProperties ( model , renderer ) ) }
81- ${ renderer . indent ( renderMarshalAdditionalProperties ( model , renderer ) ) }
91+ ${ renderer . indent ( renderMarshalProperties ( model , renderer , inputModel ) ) }
92+ ${ renderer . indent ( renderMarshalPatternProperties ( model , renderer , inputModel ) ) }
93+ ${ renderer . indent ( renderMarshalAdditionalProperties ( model , renderer , inputModel ) ) }
8294
8395 //Remove potential last comma
8496 return \`$\{json.charAt(json.length-1) === ',' ? json.slice(0, json.length-1) : json}}\`;
8597}` ;
8698}
8799
88- function renderUnmarshalProperties ( model : CommonModel , renderer : TypeScriptRenderer ) {
100+ function renderUnmarshalProperty ( modelInstanceVariable : string , model : CommonModel , inputModel : CommonInputModel , renderer : TypeScriptRenderer ) {
101+ if ( model . $ref ) {
102+ const resolvedModel = inputModel . models [ model . $ref ] ;
103+ const propertyModelKind = TypeHelpers . extractKind ( resolvedModel ) ;
104+ //Referenced enums only need standard marshalling, so lets filter those away
105+ if ( propertyModelKind !== ModelKind . ENUM ) {
106+ return `${ renderer . nameType ( model . $ref ) } .unmarshal(${ modelInstanceVariable } )` ;
107+ }
108+ }
109+ return `${ modelInstanceVariable } ` ;
110+ }
111+ function renderUnmarshalProperties ( model : CommonModel , renderer : TypeScriptRenderer , inputModel : CommonInputModel ) {
89112 const properties = model . properties || { } ;
90113 const propertyKeys = [ ...Object . entries ( properties ) ] ;
91114 const unmarshalProperties = propertyKeys . map ( ( [ prop , propModel ] ) => {
92115 const formattedPropertyName = renderer . nameProperty ( prop , propModel ) ;
93- const propUnmarshal = propModel . $ref !== undefined ? `${ renderer . nameType ( propModel . $ref ) } .unmarshal(obj["${ prop } "])` : `obj["${ prop } "]` ;
94- return `if (obj["${ prop } "] !== undefined) {
95- instance.${ formattedPropertyName } = ${ propUnmarshal } ;
116+ const modelInstanceVariable = `obj["${ prop } "]` ;
117+ const unmarshalCode = renderUnmarshalProperty ( modelInstanceVariable , propModel , inputModel , renderer ) ;
118+ return `if (${ modelInstanceVariable } !== undefined) {
119+ instance.${ formattedPropertyName } = ${ unmarshalCode } ;
96120}` ;
97121 } ) ;
98122 return unmarshalProperties . join ( '\n' ) ;
99123}
100124
101- function renderUnmarshalPatternProperties ( model : CommonModel , renderer : TypeScriptRenderer ) {
125+ function renderUnmarshalPatternProperties ( model : CommonModel , renderer : TypeScriptRenderer , inputModel : CommonInputModel ) {
102126 let unmarshalPatternProperties = '' ;
103127 let setPatternPropertiesMap = '' ;
104128 if ( model . patternProperties !== undefined ) {
105129 for ( const [ pattern , patternModel ] of Object . entries ( model . patternProperties ) ) {
106130 let patternPropertyName = getUniquePropertyName ( model , `${ pattern } ${ DefaultPropertyNames . patternProperties } ` ) ;
107131 patternPropertyName = renderer . nameProperty ( patternPropertyName , patternModel ) ;
108- setPatternPropertiesMap = `if (instance.${ patternPropertyName } === undefined) {instance.${ patternPropertyName } = new Map();}` ;
132+ const modelInstanceVariable = 'value as any' ;
133+ const unmarshalCode = renderUnmarshalProperty ( modelInstanceVariable , patternModel , inputModel , renderer ) ;
134+ setPatternPropertiesMap += `if (instance.${ patternPropertyName } === undefined) {instance.${ patternPropertyName } = new Map();}\n` ;
109135 unmarshalPatternProperties += `//Check all pattern properties
110136if (key.match(new RegExp('${ pattern } '))) {
111- instance.${ patternPropertyName } .set(key, value as any );
137+ instance.${ patternPropertyName } .set(key, ${ unmarshalCode } );
112138 continue;
113139}` ;
114140 }
115141 }
116142 return { unmarshalPatternProperties, setPatternPropertiesMap} ;
117143}
118144
119- function renderUnmarshalAdditionalProperties ( model : CommonModel , renderer : TypeScriptRenderer ) {
145+ function renderUnmarshalAdditionalProperties ( model : CommonModel , renderer : TypeScriptRenderer , inputModel : CommonInputModel ) {
120146 let unmarshalAdditionalProperties = '' ;
121147 let setAdditionalPropertiesMap = '' ;
122148 if ( model . additionalProperties !== undefined ) {
123149 let additionalPropertyName = getUniquePropertyName ( model , DefaultPropertyNames . additionalProperties ) ;
124150 additionalPropertyName = renderer . nameProperty ( additionalPropertyName , model . additionalProperties ) ;
125- const additionalPropertiesCast = model . additionalProperties . $ref !== undefined ? `${ renderer . nameType ( model . $id ) } .unmarshal(value)` : 'value as any' ;
151+ const modelInstanceVariable = 'value as any' ;
152+ const unmarshalCode = renderUnmarshalProperty ( modelInstanceVariable , model . additionalProperties , inputModel , renderer ) ;
126153 setAdditionalPropertiesMap = `if (instance.${ additionalPropertyName } === undefined) {instance.${ additionalPropertyName } = new Map();}` ;
127- unmarshalAdditionalProperties = `instance.${ additionalPropertyName } .set(key, ${ additionalPropertiesCast } );` ;
154+ unmarshalAdditionalProperties = `instance.${ additionalPropertyName } .set(key, ${ unmarshalCode } );` ;
128155 }
129156 return { unmarshalAdditionalProperties, setAdditionalPropertiesMap} ;
130157}
131158
132159/**
133160 * Render `unmarshal` function based on model
134161 */
135- function renderUnmarshal ( { renderer, model } : {
162+ function renderUnmarshal ( { renderer, model, inputModel } : {
136163 renderer : TypeScriptRenderer ,
137164 model : CommonModel ,
165+ inputModel : CommonInputModel
138166} ) : string {
139167 const properties = model . properties || { } ;
140- const { unmarshalPatternProperties, setPatternPropertiesMap} = renderUnmarshalPatternProperties ( model , renderer ) ;
141- const { unmarshalAdditionalProperties, setAdditionalPropertiesMap} = renderUnmarshalAdditionalProperties ( model , renderer ) ;
168+ const { unmarshalPatternProperties, setPatternPropertiesMap} = renderUnmarshalPatternProperties ( model , renderer , inputModel ) ;
169+ const { unmarshalAdditionalProperties, setAdditionalPropertiesMap} = renderUnmarshalAdditionalProperties ( model , renderer , inputModel ) ;
170+ const unmarshalProperties = renderUnmarshalProperties ( model , renderer , inputModel ) ;
142171 const formattedModelName = renderer . nameType ( model . $id ) ;
143172 const propertyNames = Object . keys ( properties ) . map ( ( prop => `"${ prop } "` ) ) ;
144173 return `public static unmarshal(json: string | object): ${ formattedModelName } {
145174 const obj = typeof json === "object" ? json : JSON.parse(json);
146175 const instance = new ${ formattedModelName } ({} as any);
147176
148- ${ renderer . indent ( renderUnmarshalProperties ( model , renderer ) ) }
177+ ${ renderer . indent ( unmarshalProperties ) }
149178
150179 //Not part of core properties
151180 ${ setPatternPropertiesMap }
@@ -165,13 +194,13 @@ ${renderer.indent(unmarshalAdditionalProperties, 4)}
165194 */
166195export const TS_COMMON_PRESET : TypeScriptPreset = {
167196 class : {
168- additionalContent ( { renderer, model, content, options } ) {
197+ additionalContent ( { renderer, model, content, options, inputModel } ) {
169198 options = options || { } ;
170199 const blocks : string [ ] = [ ] ;
171200
172201 if ( options . marshalling === true ) {
173- blocks . push ( renderMarshal ( { renderer, model } ) ) ;
174- blocks . push ( renderUnmarshal ( { renderer, model } ) ) ;
202+ blocks . push ( renderMarshal ( { renderer, model, inputModel } ) ) ;
203+ blocks . push ( renderUnmarshal ( { renderer, model, inputModel } ) ) ;
175204 }
176205
177206 if ( options . example === true ) {
0 commit comments