@vkontakte/api-schema-typescript-generator 0.9.0 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,10 +1,11 @@
1
+ import * as Schema from '../types/schema';
1
2
  import {
2
3
  Dictionary,
3
- JSONSchemaMethodInfoInterface,
4
- JSONSchemaMethodsDefinitionsInterface,
5
4
  ObjectType,
6
5
  RefsDictionary,
7
6
  } from '../types';
7
+ import { generateEnumAsUnionType } from './enums';
8
+ import { normalizeMethodInfo } from './methods';
8
9
  import { SchemaObject } from './SchemaObject';
9
10
  import {
10
11
  getInterfaceName, getMethodSection, getObjectNameByRef,
@@ -14,7 +15,7 @@ import {
14
15
  } from '../helpers';
15
16
  import { CodeBlocksArray, GeneratorResultInterface } from './BaseCodeBlock';
16
17
  import { TypeCodeBlock, TypeScriptCodeTypes } from './TypeCodeBlock';
17
- import { arrayToMap, isObject, sortArrayAlphabetically, uniqueArray } from '../utils';
18
+ import { isObject, sortArrayAlphabetically, uniqueArray } from '../utils';
18
19
  import {
19
20
  baseAPIParamsInterfaceName,
20
21
  baseBoolIntRef,
@@ -25,7 +26,7 @@ import {
25
26
  import path from 'path';
26
27
  import { CommentCodeBlock } from './CommentCodeBlock';
27
28
  import { consoleLogError, consoleLogErrorAndExit, consoleLogInfo } from '../log';
28
- import { generateImportsBlock, generateStandaloneEnum } from '../generator';
29
+ import { generateImportsBlock } from '../generator';
29
30
  import { generateTypeString } from './typeString';
30
31
 
31
32
  interface APITypingsGeneratorOptions {
@@ -43,7 +44,7 @@ interface APITypingsGeneratorOptions {
43
44
  */
44
45
  methodsPattern: string;
45
46
 
46
- methodsDefinitions: JSONSchemaMethodsDefinitionsInterface;
47
+ methodsDefinitions: Schema.API;
47
48
  objects: Dictionary<SchemaObject>;
48
49
  responses: Dictionary<SchemaObject>;
49
50
  }
@@ -55,7 +56,7 @@ export class APITypingsGenerator {
55
56
  this.methodsPattern = prepareMethodsPattern(options.methodsPattern);
56
57
 
57
58
  this.methodsDefinitions = options.methodsDefinitions;
58
- this.methodsList = options.methodsDefinitions.methods;
59
+ this.methodsList = options.methodsDefinitions.methods || [];
59
60
  this.objects = this.convertJSONSchemaDictionary(options.objects);
60
61
  this.responses = this.convertJSONSchemaDictionary(options.responses);
61
62
 
@@ -78,8 +79,8 @@ export class APITypingsGenerator {
78
79
  outDirPath!: APITypingsGeneratorOptions['outDirPath'];
79
80
  methodsPattern!: Dictionary<boolean>;
80
81
 
81
- methodsDefinitions!: JSONSchemaMethodsDefinitionsInterface;
82
- methodsList!: JSONSchemaMethodsDefinitionsInterface['methods'];
82
+ methodsDefinitions!: Schema.API;
83
+ methodsList!: NonNullable<Schema.API['methods']>;
83
84
  objects!: Dictionary<SchemaObject>;
84
85
  responses!: Dictionary<SchemaObject>;
85
86
 
@@ -117,7 +118,7 @@ export class APITypingsGenerator {
117
118
  this.resultFiles[path] = content;
118
119
  }
119
120
 
120
- private appendToFileMap(section: string, imports: Dictionary<boolean>, codeBlocks: CodeBlocksArray) {
121
+ private appendToFileMap(section: string, imports: RefsDictionary, codeBlocks: CodeBlocksArray) {
121
122
  const methodFile = this.methodFilesMap[section] || {
122
123
  imports: {},
123
124
  codeBlocks: [],
@@ -150,10 +151,11 @@ export class APITypingsGenerator {
150
151
  if (allOfItem.ref && !this.visitedRefs[allOfItem.ref]) {
151
152
  this.visitedRefs[allOfItem.ref] = true;
152
153
  const refName = allOfItem.ref;
153
- const objectName = getObjectNameByRef(refName);
154
- allOfItem = this.objects[objectName];
155
154
 
156
- if (!allOfItem) {
155
+ const tempAllOfItem = this.getObjectByRef(refName);
156
+ if (tempAllOfItem) {
157
+ allOfItem = tempAllOfItem;
158
+ } else {
157
159
  consoleLogErrorAndExit(`${refName} ref not found`);
158
160
  }
159
161
  }
@@ -180,11 +182,10 @@ export class APITypingsGenerator {
180
182
  if (allOfItem.properties) {
181
183
  additionalProperties = allOfItem.properties;
182
184
  } else if (allOfItem.ref) {
183
- const objectName = getObjectNameByRef(allOfItem.ref);
184
- const refObject = this.objects[objectName];
185
-
185
+ const refObject = this.getObjectByRef(allOfItem.ref);
186
186
  if (!refObject) {
187
187
  consoleLogErrorAndExit(`${object.name} ref object in allOf is not found`);
188
+ return;
188
189
  }
189
190
 
190
191
  additionalProperties = this.getObjectProperties(refObject, deep + 1);
@@ -206,7 +207,7 @@ export class APITypingsGenerator {
206
207
  }
207
208
  }
208
209
 
209
- /*
210
+ /**
210
211
  * Filter properties with same name
211
212
  * If an object uses allOf, some nested objects may have the same properties
212
213
  */
@@ -224,11 +225,10 @@ export class APITypingsGenerator {
224
225
  }
225
226
 
226
227
  private getObjectInterfaceCode(object: SchemaObject): GeneratorResultInterface | false {
227
- let imports: Dictionary<boolean> = {};
228
+ let imports: RefsDictionary = {};
228
229
  let codeBlocks: CodeBlocksArray = [];
229
230
 
230
231
  const properties = this.getObjectProperties(object);
231
- const requiredProperties = arrayToMap(object.required);
232
232
 
233
233
  const codeBlock = new TypeCodeBlock({
234
234
  type: TypeScriptCodeTypes.Interface,
@@ -249,7 +249,9 @@ export class APITypingsGenerator {
249
249
  value,
250
250
  codeBlocks: newCodeBlocks,
251
251
  description,
252
- } = generateTypeString(property, this.objects);
252
+ } = generateTypeString(property, this.objects, {
253
+ objectParentName: object.name,
254
+ });
253
255
 
254
256
  imports = { ...imports, ...newImports };
255
257
  codeBlocks = [...codeBlocks, ...newCodeBlocks];
@@ -258,7 +260,7 @@ export class APITypingsGenerator {
258
260
  name: property.name,
259
261
  description: [property.description, description].join(newLineChar),
260
262
  value,
261
- isRequired: isPatternProperty(property.name) || requiredProperties[property.name],
263
+ isRequired: isPatternProperty(property.name) || property.isRequired,
262
264
  });
263
265
  });
264
266
 
@@ -278,7 +280,7 @@ export class APITypingsGenerator {
278
280
  }
279
281
 
280
282
  if (object.enum) {
281
- const { codeBlocks } = generateStandaloneEnum(object);
283
+ const { codeBlocks } = generateEnumAsUnionType(object);
282
284
 
283
285
  return {
284
286
  codeBlocks: codeBlocks,
@@ -348,10 +350,14 @@ export class APITypingsGenerator {
348
350
  this.generateObjectsFromImports(imports);
349
351
  }
350
352
 
353
+ private getObjectByRef(ref: string): SchemaObject | undefined {
354
+ const refName = getObjectNameByRef(ref);
355
+ return this.objects[refName];
356
+ }
357
+
351
358
  private generateObjectsFromRefs(refs: RefsDictionary): void {
352
359
  Object.keys(refs).forEach((ref) => {
353
- const refName = getObjectNameByRef(ref);
354
- const refObject = this.objects[refName];
360
+ const refObject = this.getObjectByRef(ref);
355
361
  if (!refObject) {
356
362
  consoleLogInfo(`"${ref}" ref is not found`);
357
363
  return;
@@ -361,10 +367,9 @@ export class APITypingsGenerator {
361
367
  });
362
368
  }
363
369
 
364
- private generateObjectsFromImports(imports: Dictionary<boolean>) {
370
+ private generateObjectsFromImports(imports: RefsDictionary) {
365
371
  Object.keys(imports).forEach((ref) => {
366
- const refName = getObjectNameByRef(ref);
367
- const refObject = this.objects[refName];
372
+ const refObject = this.getObjectByRef(ref);
368
373
  if (!refObject) {
369
374
  consoleLogInfo(`"${ref}" ref is not found`);
370
375
  return;
@@ -374,52 +379,11 @@ export class APITypingsGenerator {
374
379
  });
375
380
  }
376
381
 
377
- private generateMethodParams(methodInfo: JSONSchemaMethodInfoInterface) {
382
+ private generateMethodParams(methodInfo: SchemaObject) {
378
383
  const section = getMethodSection(methodInfo.name);
379
384
  const interfaceName = `${methodInfo.name} params`;
380
385
 
381
- const parametersRaw = Array.isArray(methodInfo.parameters) ? methodInfo.parameters : [];
382
- const requiredParams = parametersRaw.reduce<Dictionary<boolean>>((acc, param) => {
383
- if (param.required) {
384
- acc[param.name] = true;
385
- }
386
- return acc;
387
- }, {});
388
-
389
- const properties = parametersRaw.map((paramRaw) => {
390
- paramRaw = { ...paramRaw };
391
-
392
- // For method params "boolean" type means 1 or 0
393
- // Real "false" boolean value will be detected by API as true
394
- if (paramRaw.type === 'boolean') {
395
- delete paramRaw.type;
396
- paramRaw.$ref = baseBoolIntRef;
397
- }
398
-
399
- // For parameters of the "array" type, VK API still accepts only a comma-separated string
400
- // This may change in the future when the VK API starts accepting a json body
401
- if (paramRaw.type === 'array') {
402
- paramRaw.type = 'string';
403
-
404
- if (!paramRaw.description) {
405
- paramRaw.description = '';
406
- }
407
-
408
- if (paramRaw.items) {
409
- if (paramRaw.items.$ref) {
410
- this.generateObjectsFromRefs({
411
- [paramRaw.items.$ref]: true,
412
- });
413
-
414
- paramRaw.description += newLineChar.repeat(2) + paramRaw.items.$ref;
415
- }
416
- }
417
- }
418
-
419
- return new SchemaObject(paramRaw.name, paramRaw, interfaceName);
420
- });
421
-
422
- let imports: Dictionary<boolean> = {};
386
+ let imports: RefsDictionary = {};
423
387
  let codeBlocks: CodeBlocksArray = [];
424
388
 
425
389
  const codeBlock = new TypeCodeBlock({
@@ -430,12 +394,12 @@ export class APITypingsGenerator {
430
394
  properties: [],
431
395
  });
432
396
 
433
- properties.forEach((property) => {
397
+ methodInfo.parameters.forEach((property) => {
434
398
  const {
435
399
  imports: newImports,
436
400
  value,
437
401
  codeBlocks: newCodeBlocks,
438
- } = generateTypeString(property, this.objects, { skipEnumNamesConstant: true });
402
+ } = generateTypeString(property, this.objects, { needEnumNamesConstant: false });
439
403
 
440
404
  imports = { ...imports, ...newImports };
441
405
  codeBlocks = [...codeBlocks, ...newCodeBlocks];
@@ -444,7 +408,7 @@ export class APITypingsGenerator {
444
408
  name: property.name,
445
409
  description: property.description,
446
410
  value,
447
- isRequired: requiredParams[property.name],
411
+ isRequired: property.isRequired,
448
412
  });
449
413
  });
450
414
 
@@ -452,24 +416,22 @@ export class APITypingsGenerator {
452
416
  this.generateObjectsFromImports(imports);
453
417
  }
454
418
 
455
- private getResponseObjectRef(object: SchemaObject): SchemaObject | undefined {
456
- const objectName = getObjectNameByRef(object.ref);
419
+ private getResponseObjectRef(ref: string): SchemaObject | undefined {
420
+ const objectName = getObjectNameByRef(ref);
457
421
 
458
422
  if (this.responses[objectName]) {
459
423
  return this.responses[objectName];
460
- } else if (this.objects[objectName]) {
461
- return this.objects[objectName];
462
424
  }
463
425
 
464
- return undefined;
426
+ return this.getObjectByRef(ref);
465
427
  }
466
428
 
467
429
  private getObjectCodeBlockAsType(object: SchemaObject): GeneratorResultInterface | false {
468
430
  let codeBlocks: CodeBlocksArray = [];
469
- let imports: Dictionary<boolean> = {};
431
+ let imports: RefsDictionary = {};
470
432
 
471
433
  if (object.enum) {
472
- const { codeBlocks: newCodeBlocks } = generateStandaloneEnum(object);
434
+ const { codeBlocks: newCodeBlocks } = generateEnumAsUnionType(object);
473
435
  codeBlocks = [
474
436
  ...newCodeBlocks,
475
437
  ];
@@ -501,38 +463,36 @@ export class APITypingsGenerator {
501
463
  }
502
464
 
503
465
  private getResponseCodeBlockAsType(object: SchemaObject, response: SchemaObject): GeneratorResultInterface | false {
504
- let codeBlocks: CodeBlocksArray = [];
505
- let imports: Dictionary<boolean> = {};
466
+ const {
467
+ imports,
468
+ value,
469
+ codeBlocks,
470
+ description,
471
+ } = generateTypeString(response, this.objects, {
472
+ objectParentName: ' ', // TODO: Refactor
473
+ });
506
474
 
507
- if (response.enum) {
508
- const { codeBlocks: newCodeBlocks } = generateStandaloneEnum(response);
509
- codeBlocks = [
510
- ...newCodeBlocks,
511
- ];
512
- } else {
513
- const { imports: newImports, value, codeBlocks: newCodeBlocks } = generateTypeString(response, this.objects);
514
- const codeBlock = new TypeCodeBlock({
515
- type: TypeScriptCodeTypes.Type,
516
- refName: object.name,
517
- interfaceName: getInterfaceName(object.name),
518
- description: object.description,
519
- needExport: true,
520
- properties: [],
521
- value,
522
- });
475
+ const codeBlock = new TypeCodeBlock({
476
+ type: TypeScriptCodeTypes.Type,
477
+ refName: object.name,
478
+ interfaceName: getInterfaceName(object.name),
479
+ description: [
480
+ object.description,
481
+ description || '',
482
+ ].join(newLineChar),
483
+ needExport: true,
484
+ properties: [],
485
+ value,
486
+ });
523
487
 
524
- imports = newImports;
525
- codeBlocks = [
488
+ return {
489
+ codeBlocks: [
526
490
  ...codeBlocks,
527
- ...newCodeBlocks,
528
491
  codeBlock,
529
- ];
530
- }
531
-
532
- return {
533
- codeBlocks,
492
+ ],
534
493
  imports,
535
494
  value: '',
495
+ description,
536
496
  };
537
497
  }
538
498
 
@@ -549,59 +509,31 @@ export class APITypingsGenerator {
549
509
  };
550
510
 
551
511
  const objectName = getObjectNameByRef(object.ref);
552
- let response: SchemaObject | undefined;
553
-
554
512
  if (nonBuildableRefs[objectName]) {
555
513
  return this.getObjectCodeBlockAsType(object);
556
- } else if (this.responses[objectName]) {
557
- response = this.responses[objectName];
558
-
559
- const { properties = [] } = response;
560
- const responseProperty = properties.find((property) => property.name === 'response');
561
-
562
- if (responseProperty) {
563
- response = responseProperty;
564
- if (response.ref) {
565
- return this.getResponseCodeBlockAsType(object, response);
566
- }
567
- } else {
568
- // Maybe this is a crutch?
569
- response.properties.forEach((property) => {
570
- if (response && property.parentObjectName === response.name) {
571
- response = property;
572
- return true;
573
- }
574
-
575
- return false;
576
- });
577
- }
578
- } else if (this.objects[objectName]) {
579
- response = this.objects[objectName];
514
+ }
580
515
 
581
- if (object.ref) {
582
- return this.getResponseCodeBlockAsType(object, object);
583
- }
516
+ let response = this.getResponseObjectRef(object.ref);
517
+ if (!response) {
518
+ consoleLogError(`response schema object "${object.name}" has no response`, object);
519
+ return false;
584
520
  }
585
521
 
586
- // @ts-ignore
587
- while (response && response.ref) {
588
- response = this.getResponseObjectRef(response);
522
+ // VK API JSON Schema specific heuristic
523
+ if (response.properties.length === 1 && response.properties[0].name === 'response') {
524
+ response = response.properties[0];
589
525
  }
590
526
 
591
- if (!response) {
592
- consoleLogErrorAndExit(`"${object.name}" has no response`);
593
- return false;
527
+ if (response.ref) {
528
+ return this.getResponseCodeBlockAsType(object, response);
594
529
  }
595
530
 
596
- response.originalName = response.name;
531
+ response = response.clone();
597
532
  response.setName(object.name);
598
533
 
599
- let result: GeneratorResultInterface | false;
600
-
601
534
  switch (response.type) {
602
535
  case 'object':
603
- result = this.getObjectInterfaceCode(response);
604
- break;
536
+ return this.getObjectInterfaceCode(response);
605
537
 
606
538
  case 'integer':
607
539
  case 'string':
@@ -610,11 +542,9 @@ export class APITypingsGenerator {
610
542
  return this.getResponseCodeBlockAsType(object, response);
611
543
 
612
544
  default:
613
- consoleLogErrorAndExit(response.name, 'unknown type');
545
+ consoleLogErrorAndExit(response.name, 'unknown type', response.type);
614
546
  return false;
615
547
  }
616
-
617
- return result;
618
548
  }
619
549
 
620
550
  public generateResponse(section: string, response: SchemaObject) {
@@ -629,39 +559,47 @@ export class APITypingsGenerator {
629
559
  this.generateObjectsFromImports(imports);
630
560
  }
631
561
 
632
- private generateMethodParamsAndResponses(methodInfo: JSONSchemaMethodInfoInterface) {
633
- const { name } = methodInfo;
634
- const section = getMethodSection(name);
562
+ private generateMethodParamsAndResponses(method: Schema.Method) {
563
+ const { name: methodName } = method;
564
+ const section = getMethodSection(methodName);
635
565
 
636
- if (!isObject(methodInfo.responses)) {
637
- consoleLogErrorAndExit(`"${name}" "responses" field is not an object.`);
566
+ if (!isObject(method.responses)) {
567
+ consoleLogErrorAndExit(`"${methodName}" "responses" field is not an object.`);
638
568
  return;
639
569
  }
640
570
 
641
- if (Object.keys(methodInfo.responses).length === 0) {
642
- consoleLogErrorAndExit(`"${name}" "responses" field is empty.`);
571
+ if (Object.keys(method.responses).length === 0) {
572
+ consoleLogErrorAndExit(`"${methodName}" "responses" field is empty.`);
643
573
  return;
644
574
  }
645
575
 
646
576
  // Comment with method name for visual sections in file
647
- const methodNameComment = new CommentCodeBlock([name]);
648
- if (methodInfo.description) {
577
+ const methodNameComment = new CommentCodeBlock([methodName]);
578
+ if (method.description) {
649
579
  methodNameComment.appendLines([
650
580
  '',
651
- methodInfo.description,
581
+ method.description,
652
582
  ]);
653
583
  }
654
584
  this.appendToFileMap(section, {}, [methodNameComment]);
655
585
 
656
- this.generateMethodParams(methodInfo);
586
+ const {
587
+ method: normalizedMethod,
588
+ parameterRefs,
589
+ } = normalizeMethodInfo(method);
590
+
591
+ method = normalizedMethod;
592
+ this.generateObjectsFromRefs(parameterRefs);
593
+
594
+ this.generateMethodParams(new SchemaObject(method.name, method));
657
595
 
658
- Object.entries(methodInfo.responses).forEach(([responseName, responseObject]) => {
659
- if (this.ignoredResponses[name] && this.ignoredResponses[name][responseName]) {
596
+ Object.entries(method.responses).forEach(([responseName, responseObject]) => {
597
+ if (this.ignoredResponses[methodName] && this.ignoredResponses[methodName][responseName]) {
660
598
  return;
661
599
  }
662
600
 
663
- responseObject.name = `${name}_${responseName}`;
664
- this.generateResponse(section, new SchemaObject(responseObject.name, responseObject));
601
+ const name = `${methodName}_${responseName}`;
602
+ this.generateResponse(section, new SchemaObject(name, responseObject));
665
603
  });
666
604
  }
667
605
 
@@ -1,4 +1,4 @@
1
- import { Dictionary } from '../types';
1
+ import { RefsDictionary } from '../types';
2
2
 
3
3
  export abstract class BaseCodeBlock {
4
4
  toString(): string {
@@ -10,7 +10,7 @@ export type CodeBlocksArray = BaseCodeBlock[];
10
10
 
11
11
  export interface GeneratorResultInterface {
12
12
  codeBlocks: CodeBlocksArray;
13
- imports: Dictionary<boolean>;
13
+ imports: RefsDictionary;
14
14
  value: string;
15
15
  description?: string;
16
16
  }
@@ -1,3 +1,4 @@
1
+ import { EnumLikeArray } from '../types';
1
2
  import { isObject, isString } from '../utils';
2
3
  import {
3
4
  transformPatternPropertyName,
@@ -45,6 +46,10 @@ export class SchemaObject {
45
46
  this.required = [];
46
47
  }
47
48
 
49
+ if (typeof object.required === 'boolean') {
50
+ this.isRequired = object.required;
51
+ }
52
+
48
53
  this.properties = [];
49
54
 
50
55
  if (object.properties) {
@@ -53,6 +58,14 @@ export class SchemaObject {
53
58
  });
54
59
  }
55
60
 
61
+ this.parameters = [];
62
+
63
+ if (Array.isArray(object.parameters)) {
64
+ object.parameters.forEach((parameter: any) => {
65
+ this.parameters.push(new SchemaObject(parameter.name, parameter, `${name} param`));
66
+ });
67
+ }
68
+
56
69
  if (object.patternProperties) {
57
70
  Object.entries(object.patternProperties).forEach(([propertyName, property]: [string, any]) => {
58
71
  this.properties.push(new SchemaObject(transformPatternPropertyName(propertyName), property, name));
@@ -70,25 +83,20 @@ export class SchemaObject {
70
83
  if (Array.isArray(object.allOf) && object.allOf.length > 0) {
71
84
  this.allOf = object.allOf.map((item: any) => new SchemaObject(name, item));
72
85
  }
73
-
74
- // Crutch
75
- // if (this.oneOf && this.oneOf.length === 1) {
76
- // this.allOf = [this.oneOf[0]];
77
- // this.oneOf = undefined;
78
- // }
79
86
  }
80
87
 
81
88
  name!: string;
82
- originalName!: string;
83
89
  parentObjectName!: string;
84
90
 
85
91
  type!: string | string[];
86
- readonly description!: string;
87
- readonly ref!: string;
92
+ description!: string;
93
+ ref!: string;
88
94
  required!: string[];
89
- readonly enum!: Array<string | number>;
90
- readonly enumNames!: Array<string | number>;
95
+ isRequired!: boolean;
96
+ readonly enum!: EnumLikeArray;
97
+ readonly enumNames!: EnumLikeArray;
91
98
  properties!: SchemaObject[];
99
+ parameters!: SchemaObject[];
92
100
  readonly items!: SchemaObject;
93
101
  readonly oneOf!: SchemaObject[];
94
102
  readonly allOf!: SchemaObject[];
@@ -97,7 +105,13 @@ export class SchemaObject {
97
105
  this.name = name;
98
106
 
99
107
  if (Array.isArray(this.properties)) {
100
- this.properties.forEach((property) => property.parentObjectName = name);
108
+ this.properties.forEach((property) => {
109
+ property.parentObjectName = name;
110
+ });
101
111
  }
102
112
  }
113
+
114
+ public clone() {
115
+ return Object.assign(Object.create(Object.getPrototypeOf(this)), this) as NonNullable<SchemaObject>;
116
+ }
103
117
  }
@@ -1,8 +1,8 @@
1
1
  import { BaseCodeBlock } from './BaseCodeBlock';
2
2
  import { newLineChar } from '../constants';
3
- import { areQuotesNeededForProperty } from '../helpers';
3
+ import { areQuotesNeededForProperty, joinCommentLines } from '../helpers';
4
4
  import { consoleLogErrorAndExit } from '../log';
5
- import { quoteJavaScriptValue, trimArray, trimStringDoubleSpaces } from '../utils';
5
+ import { quoteJavaScriptValue, trimStringDoubleSpaces } from '../utils';
6
6
 
7
7
  export enum TypeScriptCodeTypes {
8
8
  Interface = 'interface',
@@ -89,15 +89,11 @@ export class TypeCodeBlock extends BaseCodeBlock {
89
89
  ` ${quoteChar}${property.name}${quoteChar}${divider} ${value}${lineEnd}`,
90
90
  ];
91
91
 
92
- const propertyDescriptionLines = trimArray((property.description || '').trim().split(newLineChar));
93
- if (propertyDescriptionLines.length) {
94
- propertyCode.unshift([
95
- ' /**',
96
- ...propertyDescriptionLines.map((line) => {
97
- return ' ' + `* ${line}`.trim();
98
- }),
99
- ' */',
100
- ].join(newLineChar));
92
+ if (property.description) {
93
+ const commentLines = joinCommentLines(2, property.description);
94
+ if (commentLines.length) {
95
+ propertyCode.unshift(commentLines.join(newLineChar));
96
+ }
101
97
  }
102
98
 
103
99
  return propertyCode.join(newLineChar);
@@ -112,18 +108,17 @@ export class TypeCodeBlock extends BaseCodeBlock {
112
108
  let before: string[] = [];
113
109
  let code = '';
114
110
 
111
+ if (this.refName) {
112
+ before.push(`// ${this.refName}`);
113
+ }
114
+
115
115
  if (this.description) {
116
116
  before = [
117
- '/**',
118
- ` * ${this.description}`,
119
- ' */',
117
+ ...before,
118
+ ...joinCommentLines(0, this.description),
120
119
  ];
121
120
  }
122
121
 
123
- if (this.refName) {
124
- before.push(`// ${this.refName}`);
125
- }
126
-
127
122
  switch (this.type) {
128
123
  case TypeScriptCodeTypes.Interface: {
129
124
  if (!hasProperties) {