@@ -25,7 +25,7 @@ import {
25
25
PrimitiveObject ,
26
26
createImportEquals ,
27
27
hasImport ,
28
- createNamedImport ,
28
+ createNamedImport , updateDecoratorArguments ,
29
29
} from '../utils/ast-utils' ;
30
30
import {
31
31
getTypeReferenceAsString ,
@@ -34,7 +34,7 @@ import {
34
34
import { EnumMetadataValuesMapOptions } from '../../schema-builder/metadata' ;
35
35
import { EnumOptions } from '../../type-factories' ;
36
36
37
- const ALLOWED_DECORATORS = [
37
+ const CLASS_DECORATORS = [
38
38
ObjectType . name ,
39
39
InterfaceType . name ,
40
40
InputType . name ,
@@ -77,19 +77,28 @@ export class ModelClassVisitor {
77
77
const visitNode = ( node : ts . Node ) : ts . Node => {
78
78
if (
79
79
ts . isClassDeclaration ( node ) &&
80
- hasDecorators ( node . decorators , ALLOWED_DECORATORS )
80
+ hasDecorators ( node . decorators , CLASS_DECORATORS )
81
81
) {
82
- const metadata = this . collectMetadataFromClassMembers (
82
+ const members = this . amendFieldsDecorators (
83
83
factory ,
84
84
node . members ,
85
85
pluginOptions ,
86
86
sourceFile . fileName ,
87
87
typeChecker ,
88
88
) ;
89
89
90
+ const metadata = this . collectMetadataFromClassMembers (
91
+ factory ,
92
+ members ,
93
+ pluginOptions ,
94
+ sourceFile . fileName ,
95
+ typeChecker ,
96
+ ) ;
97
+
90
98
return this . updateClassDeclaration (
91
99
factory ,
92
100
node ,
101
+ members ,
93
102
metadata ,
94
103
pluginOptions ,
95
104
) ;
@@ -273,7 +282,7 @@ export class ModelClassVisitor {
273
282
274
283
// get one of allowed decorators from list
275
284
return node . decorators . map ( ( decorator ) => {
276
- if ( ! ALLOWED_DECORATORS . includes ( getDecoratorName ( decorator ) ) ) {
285
+ if ( ! CLASS_DECORATORS . includes ( getDecoratorName ( decorator ) ) ) {
277
286
return decorator ;
278
287
}
279
288
@@ -399,12 +408,49 @@ export class ModelClassVisitor {
399
408
return inlineEnumName ;
400
409
}
401
410
402
- private collectMetadataFromClassMembers (
411
+ private amendFieldsDecorators (
403
412
f : ts . NodeFactory ,
404
413
members : ts . NodeArray < ts . ClassElement > ,
405
414
pluginOptions : PluginOptions ,
406
415
hostFilename : string , // sourceFile.fileName,
407
416
typeChecker : ts . TypeChecker | undefined ,
417
+ ) : ts . ClassElement [ ] {
418
+ return members . map ( ( member ) => {
419
+ if (
420
+ ( ts . isPropertyDeclaration ( member ) || ts . isGetAccessor ( member ) )
421
+ && hasDecorators ( member . decorators , [ Field . name ] )
422
+ ) {
423
+ try {
424
+ return updateDecoratorArguments ( f , member , Field . name , ( decoratorArguments ) => {
425
+ const options = this . getOptionsFromFieldDecoratorOrUndefined ( decoratorArguments ) ;
426
+
427
+ const { type, ...metadata } = this . createFieldMetadata (
428
+ f ,
429
+ member ,
430
+ typeChecker ,
431
+ hostFilename ,
432
+ pluginOptions ,
433
+ this . getTypeFromFieldDecoratorOrUndefined ( decoratorArguments ) ,
434
+ ) ;
435
+
436
+ const serializedMetadata = serializePrimitiveObjectToAst ( f , metadata as any ) ;
437
+ return [ type , options ? safelyMergeObjects ( f , serializedMetadata , options ) : serializedMetadata ]
438
+ } )
439
+ } catch ( e ) {
440
+ // omit error
441
+ }
442
+ }
443
+
444
+ return member ;
445
+ } ) ;
446
+ }
447
+
448
+ private collectMetadataFromClassMembers (
449
+ f : ts . NodeFactory ,
450
+ members : ts . ClassElement [ ] ,
451
+ pluginOptions : PluginOptions ,
452
+ hostFilename : string , // sourceFile.fileName,
453
+ typeChecker : ts . TypeChecker | undefined ,
408
454
) : ts . ObjectLiteralExpression {
409
455
const properties : ts . PropertyAssignment [ ] = [ ] ;
410
456
@@ -415,10 +461,10 @@ export class ModelClassVisitor {
415
461
ts . SyntaxKind . StaticKeyword ,
416
462
ts . SyntaxKind . PrivateKeyword ,
417
463
] ) &&
418
- ! hasDecorators ( member . decorators , [ HideField . name ] )
464
+ ! hasDecorators ( member . decorators , [ HideField . name , Field . name ] )
419
465
) {
420
466
try {
421
- const objectLiteralExpr = this . createDecoratorObjectLiteralExpr (
467
+ const metadata = this . createFieldMetadata (
422
468
f ,
423
469
member ,
424
470
typeChecker ,
@@ -429,7 +475,7 @@ export class ModelClassVisitor {
429
475
properties . push (
430
476
f . createPropertyAssignment (
431
477
f . createIdentifier ( member . name . getText ( ) ) ,
432
- objectLiteralExpr ,
478
+ serializePrimitiveObjectToAst ( f , metadata ) ,
433
479
) ,
434
480
) ;
435
481
} catch ( e ) {
@@ -444,6 +490,7 @@ export class ModelClassVisitor {
444
490
private updateClassDeclaration (
445
491
f : ts . NodeFactory ,
446
492
node : ts . ClassDeclaration ,
493
+ members : ts . ClassElement [ ] ,
447
494
propsMetadata : ts . ObjectLiteralExpression ,
448
495
pluginOptions : PluginOptions ,
449
496
) {
@@ -470,54 +517,49 @@ export class ModelClassVisitor {
470
517
node . name ,
471
518
node . typeParameters ,
472
519
node . heritageClauses ,
473
- [ ...node . members , method ] ,
520
+ [ ...members , method ] ,
474
521
) ;
475
522
}
476
523
477
- private getExplicitTypeInDecoratorOrNull (
478
- member : ts . PropertyDeclaration | ts . GetAccessorDeclaration ,
479
- ) : ts . ArrowFunction {
480
- const fieldDecorator = member . decorators ?. find (
481
- ( decorator ) => getDecoratorName ( decorator ) === Field . name ,
482
- ) ;
483
-
484
- if ( ! fieldDecorator ) {
485
- return null ;
524
+ private getOptionsFromFieldDecoratorOrUndefined (
525
+ decoratorArguments : ts . NodeArray < ts . Expression > ,
526
+ ) : ts . Expression | undefined {
527
+ if ( decoratorArguments . length > 1 ) {
528
+ return decoratorArguments [ 1 ] ;
486
529
}
487
530
488
- const expression = fieldDecorator . expression as ts . CallExpression ;
531
+ if ( decoratorArguments . length === 1 && ! ts . isArrowFunction ( decoratorArguments [ 0 ] ) ) {
532
+ return decoratorArguments [ 0 ] ;
533
+ }
534
+ }
489
535
536
+ private getTypeFromFieldDecoratorOrUndefined (
537
+ decoratorArguments : ts . NodeArray < ts . Expression > ,
538
+ ) : ts . ArrowFunction | undefined {
490
539
if (
491
- expression . arguments . length > 0
492
- && ts . isArrowFunction ( expression . arguments [ 0 ] )
540
+ decoratorArguments . length > 0 && ts . isArrowFunction ( decoratorArguments [ 0 ] )
493
541
) {
494
- return expression . arguments [ 0 ] ;
542
+ return decoratorArguments [ 0 ] ;
495
543
}
496
-
497
- return null
498
544
}
499
545
500
- private createDecoratorObjectLiteralExpr (
546
+ private createFieldMetadata (
501
547
f : ts . NodeFactory ,
502
548
node : ts . PropertyDeclaration | ts . GetAccessorDeclaration ,
503
549
typeChecker : ts . TypeChecker ,
504
550
hostFilename = '' ,
505
551
pluginOptions ?: PluginOptions ,
506
- ) : ts . ObjectLiteralExpression {
552
+ typeArrowFunction ?: ts . ArrowFunction ,
553
+ ) {
507
554
const type = typeChecker . getTypeAtLocation ( node ) ;
508
555
const isNullable =
509
556
! ! node . questionToken || isNull ( type ) || isUndefined ( type ) ;
510
557
511
- let typeArrowFunction : ts . ArrowFunction ;
512
- const t = this . getExplicitTypeInDecoratorOrNull ( node ) ;
513
-
514
- if ( t ) {
515
- typeArrowFunction = t ;
516
- } else {
558
+ if ( ! typeArrowFunction ) {
517
559
const inlineStringEnumTypeName =
518
560
this . getInlineStringEnumTypeOrUndefined ( node ) ;
519
561
520
- typeArrowFunction = f . createArrowFunction (
562
+ typeArrowFunction = typeArrowFunction || f . createArrowFunction (
521
563
undefined ,
522
564
undefined ,
523
565
[ ] ,
@@ -542,14 +584,13 @@ export class ModelClassVisitor {
542
584
? getJsDocDeprecation ( node )
543
585
: undefined ;
544
586
545
- const objectLiteral = serializePrimitiveObjectToAst ( f , {
587
+
588
+ return {
546
589
nullable : isNullable || undefined ,
547
590
type : typeArrowFunction ,
548
591
description,
549
592
deprecationReason,
550
- } ) ;
551
-
552
- return objectLiteral ;
593
+ } ;
553
594
}
554
595
555
596
private getTypeUsingTypeChecker (
0 commit comments