@@ -11,7 +11,6 @@ import {
11
11
nullableKeyword ,
12
12
objectKeyword ,
13
13
pluginVersion ,
14
- validEnumTypes ,
15
14
} from "./constants" ;
16
15
import { JSONSchema4 , JSONSchema4TypeName } from "json-schema" ;
17
16
import {
@@ -24,13 +23,15 @@ import {
24
23
GetColumnQuantifiers ,
25
24
getCommentIndexes ,
26
25
getDbLabel ,
26
+ RemoveNameQuantifiers ,
27
27
} from "./sharedUtils" ;
28
28
import {
29
29
DatabaseModel ,
30
30
ForeignKeyModel ,
31
31
PropertyModel ,
32
32
TableModel ,
33
33
} from "@funktechno/sqlsimpleparser/lib/types" ;
34
+ import { validJSONSchemaTypes } from "./constants-nosql" ;
34
35
35
36
/**
36
37
* convert db to openapi
@@ -58,14 +59,14 @@ export function dbToOpenApi(db: DatabaseModelResult): PartialOpenApiSchema {
58
59
let schemaKey = key ;
59
60
const entity = entities [ key ] ;
60
61
let commentIndexes = getCommentIndexes ( key ) ;
61
- let description = "" ;
62
+ let schemaDescription = "" ;
62
63
let formatValue = "" ;
63
64
if ( commentIndexes . start > - 1 && commentIndexes . end > - 1 ) {
64
65
let result = schemaKey . toString ( ) . trim ( ) ;
65
66
commentIndexes = getCommentIndexes ( result ) ;
66
67
const firstSpaceIndex = commentIndexes . start ;
67
68
const lastSpaceIndex = commentIndexes . end ;
68
- schemaKey = result . substring ( 0 , commentIndexes . beforeStart ) ;
69
+ schemaKey = result . substring ( 0 , commentIndexes . beforeStart ) . trim ( ) ;
69
70
result = result . substring ( firstSpaceIndex , lastSpaceIndex ) . trim ( ) ;
70
71
if ( result . indexOf ( formatKeyword ) !== - 1 ) {
71
72
const formatIndex = result . indexOf ( formatKeyword ) ;
@@ -75,7 +76,7 @@ export function dbToOpenApi(db: DatabaseModelResult): PartialOpenApiSchema {
75
76
result = result . substring ( 0 , formatIndex ) ;
76
77
}
77
78
if ( result ) {
78
- description = result ;
79
+ schemaDescription = result ;
79
80
}
80
81
}
81
82
if ( schema [ schemaKey ] ) {
@@ -87,8 +88,8 @@ export function dbToOpenApi(db: DatabaseModelResult): PartialOpenApiSchema {
87
88
additionalProperties : false ,
88
89
properties : { } ,
89
90
} ;
90
- if ( description ) {
91
- schema [ schemaKey ] . description = description . trim ( ) ;
91
+ if ( schemaDescription ) {
92
+ schema [ schemaKey ] . description = schemaDescription . trim ( ) ;
92
93
}
93
94
if ( formatValue ) {
94
95
schema [ schemaKey ] . format = formatValue . trim ( ) ;
@@ -108,26 +109,26 @@ export function dbToOpenApi(db: DatabaseModelResult): PartialOpenApiSchema {
108
109
const splitPropName = propName . split ( " " ) ;
109
110
if (
110
111
splitPropName . length == 2 &&
111
- validEnumTypes . indexOf ( splitPropName [ 0 ] ) !== - 1 &&
112
+ validJSONSchemaTypes . indexOf ( splitPropName [ 0 ] ) !== - 1 &&
112
113
splitPropName [ 1 ] == enumKeyword
113
114
) {
114
115
isEnum = true ;
115
116
type = splitPropName [ 0 ] as JSONSchema4TypeName ;
116
117
}
117
118
}
118
119
// extract desciption /** asdf */
119
- let description = "" ;
120
+ let propertyDescription = "" ;
120
121
let formatValue = "" ;
121
122
let enumValues : any [ ] | null = null ;
122
123
if (
123
124
attribute . attributeType ?. includes ( commentColumnQuantifiers . Start ) &&
124
125
attribute . attributeType ?. includes ( commentColumnQuantifiers . End )
125
126
) {
126
- let result = attribute . attributeType ;
127
- const commentIndexes = getCommentIndexes ( result ) ;
127
+ let attributeTypeResult = attribute . attributeType ;
128
+ const commentIndexes = getCommentIndexes ( attributeTypeResult ) ;
128
129
const firstSpaceIndex = commentIndexes . start ;
129
130
const lastSpaceIndex = commentIndexes . end ;
130
- const enumRaw = result
131
+ const enumRaw = attributeTypeResult
131
132
. substring ( 0 , commentIndexes . beforeStart )
132
133
. trim ( ) ;
133
134
if ( enumRaw ) {
@@ -141,16 +142,16 @@ export function dbToOpenApi(db: DatabaseModelResult): PartialOpenApiSchema {
141
142
) ;
142
143
}
143
144
}
144
- result = result . substring ( firstSpaceIndex , lastSpaceIndex ) ;
145
- if ( result . indexOf ( formatKeyword ) !== - 1 ) {
146
- const formatIndex = result . indexOf ( formatKeyword ) ;
147
- formatValue = result
145
+ attributeTypeResult = attributeTypeResult . substring ( firstSpaceIndex , lastSpaceIndex ) ;
146
+ if ( attributeTypeResult . indexOf ( formatKeyword ) !== - 1 ) {
147
+ const formatIndex = attributeTypeResult . indexOf ( formatKeyword ) ;
148
+ formatValue = attributeTypeResult
148
149
. substring ( formatIndex + formatKeyword . length )
149
150
. trim ( ) ;
150
- result = result . substring ( 0 , formatIndex ) ;
151
+ attributeTypeResult = attributeTypeResult . substring ( 0 , formatIndex ) ;
151
152
}
152
- if ( result ) {
153
- description = result ;
153
+ if ( attributeTypeResult . trim ( ) ) {
154
+ propertyDescription = attributeTypeResult . trim ( ) ;
154
155
}
155
156
156
157
// decription = attribute.attributeType?.replace("/**", "").replace("*/", "");
@@ -160,24 +161,92 @@ export function dbToOpenApi(db: DatabaseModelResult): PartialOpenApiSchema {
160
161
if ( enumValues ) {
161
162
schema [ schemaKey ] . enum = enumValues ;
162
163
}
163
- if ( description ) {
164
- schema [ schemaKey ] . description = description . trim ( ) ;
164
+ if ( propertyDescription . trim ( ) ) {
165
+ schema [ schemaKey ] . description = propertyDescription . trim ( ) ;
165
166
}
166
- if ( formatValue ) {
167
+ if ( formatValue . trim ( ) ) {
167
168
schema [ schemaKey ] . format = formatValue . trim ( ) ;
168
169
}
169
170
schema [ schemaKey ] . type = type ;
170
171
} else {
172
+ // check if type is jsonschema type
173
+ let $ref = null ;
174
+ let removeType = false ;
175
+ let items : JSONSchema4 | null = null ;
176
+ let additionalProperties : JSONSchema4 | null = null ;
177
+ if ( validJSONSchemaTypes . indexOf ( type ) === - 1 ) {
178
+ if ( type . indexOf ( "[]" ) != - 1 ) {
179
+ const itemsType = type . replace ( "[]" , "" ) as JSONSchema4TypeName ;
180
+ if ( validJSONSchemaTypes . indexOf ( itemsType ) != - 1 ) {
181
+ items = {
182
+ type : itemsType ,
183
+ } ;
184
+ type = "array" ;
185
+ }
186
+ }
187
+
188
+ if ( validJSONSchemaTypes . indexOf ( type ) != - 1 ) {
189
+ //
190
+ } else {
191
+ // else {
192
+ removeType = true ;
193
+ $ref = `#/components/schemas/${ RemoveNameQuantifiers ( type ) } ` ;
194
+ }
195
+ }
196
+ if ( [ "array" , "object" ] . indexOf ( type ) !== - 1 ) {
197
+ const relationships = db . getRelationships ( ) . filter ( x => x . entityA == key ) ;
198
+ const roleLookup = `[${ key } .${ propName } ]` ;
199
+ // FIND MATCH
200
+ const rel = relationships . find ( x => x . roleA . indexOf ( roleLookup ) != - 1 ) ;
201
+ if ( rel ) {
202
+ const commentFKIndexes = getCommentIndexes ( rel . entityB ) ;
203
+ const entityBName = rel . entityB . substring ( 0 , commentFKIndexes . beforeStart ) . trim ( ) ;
204
+ $ref = `#/components/schemas/${ entityBName } ` ;
205
+ }
206
+ if ( $ref ) {
207
+ // if array additionalProperties.$ref
208
+ if ( type == "array" ) {
209
+ items = {
210
+ $ref : $ref
211
+ } ;
212
+ }
213
+ // if object items.$ref
214
+ if ( type == "object" ) {
215
+ additionalProperties = {
216
+ $ref : $ref
217
+ } ;
218
+ }
219
+ }
220
+ }
221
+
171
222
const property : JSONSchema4 = {
172
223
title : `${ schemaKey } .${ propName } ` ,
173
- nullable : attribute . attributeType ?. includes ( "nullable" ) ?? false ,
174
224
type : type ,
175
225
} ;
176
- if ( description ) {
177
- property . description = description . trim ( ) ;
226
+ if ( additionalProperties ) {
227
+ property . additionalProperties = additionalProperties ;
228
+ }
229
+ if ( items ) {
230
+ property . items = items ;
178
231
}
179
- if ( formatValue ) {
180
- property . format = formatValue . trim ( ) ;
232
+ if ( attribute . attributeType ?. includes ( "nullable" ) ) {
233
+ property . nullable = true ;
234
+ }
235
+ if ( $ref && ! additionalProperties ?. $ref && ! items ?. $ref ) {
236
+ property [ "$ref" ] = $ref ;
237
+ }
238
+ if ( removeType ) {
239
+ delete property . type ;
240
+ }
241
+ // $ref properties don't have descriptions
242
+ if ( propertyDescription . trim ( ) && ! $ref ) {
243
+ // TODO: pull from proper location
244
+ property . description = propertyDescription . trim ( ) ;
245
+ }
246
+ if ( formatValue . trim ( ) ) {
247
+ if ( property . items ) {
248
+ ( property . items as JSONSchema4 ) . format = formatValue . trim ( ) ;
249
+ } else property . format = formatValue . trim ( ) ;
181
250
}
182
251
schema [ schemaKey ] . properties [ attribute . attributeName ! ] = property ;
183
252
}
@@ -191,7 +260,13 @@ export function dbToOpenApi(db: DatabaseModelResult): PartialOpenApiSchema {
191
260
return result ;
192
261
}
193
262
194
- // TODO: may need to make recursive for when schema property items is array
263
+ /**
264
+ * used in uml generation
265
+ * @param tableName
266
+ * @param propertyName
267
+ * @param property
268
+ * @returns
269
+ */
195
270
export function GeneratePropertyModel (
196
271
tableName : string ,
197
272
propertyName : string ,
@@ -200,9 +275,12 @@ export function GeneratePropertyModel(
200
275
let columnProperties = ( property . type ?? objectKeyword ) . toString ( ) ;
201
276
if ( columnProperties === arrayKeyword ) {
202
277
if ( property . items && typeof property . items === objectKeyword ) {
203
- if ( ( property . items as JSONSchema4 ) . format )
204
- columnProperties = `${ ( property . items as JSONSchema4 ) . format } []` ;
205
- else if ( ( property . items as JSONSchema4 ) . type )
278
+ if ( ( property . items as JSONSchema4 ) . format && ! property . format ) {
279
+ property . format = ( property . items as JSONSchema4 ) . format ;
280
+ // columnProperties = `${(property.items as JSONSchema4).format}[]`;
281
+ }
282
+ // else
283
+ if ( ( property . items as JSONSchema4 ) . type )
206
284
columnProperties = `${ ( property . items as JSONSchema4 ) . type } []` ;
207
285
}
208
286
}
@@ -225,7 +303,11 @@ export function GeneratePropertyModel(
225
303
} ;
226
304
return result ;
227
305
}
228
-
306
+ /**
307
+ * convert openapi schema to database model
308
+ * @param schemas
309
+ * @returns
310
+ */
229
311
export function ConvertOpenApiToDatabaseModel (
230
312
schemas : Record < string , OpenApiSchemaTypeDefinition >
231
313
) : DatabaseModel {
0 commit comments