1- import { writeText , log , progress } from '@serverless/utils/log' ;
21import Serverless from 'serverless/lib/Serverless' ;
32import Provider from 'serverless/lib/plugins/aws/provider.js' ;
43import { forEach , last , merge } from 'lodash' ;
@@ -68,6 +67,23 @@ import terminalLink from 'terminal-link';
6867
6968const CONSOLE_BASE_URL = 'https://console.aws.amazon.com' ;
7069
70+ type Progress = {
71+ remove : ( ) => void ;
72+ } ;
73+
74+ type ServerlessPluginUtils = {
75+ log : {
76+ success : ( message : string ) => void ;
77+ warning : ( message : string ) => void ;
78+ error : ( message : string ) => void ;
79+ info : ( message : string ) => void ;
80+ } ;
81+ progress : {
82+ create : ( params : { name ?: string ; message : string } ) => Progress ;
83+ } ;
84+ writeText : ( message : string ) => void ;
85+ } ;
86+
7187class ServerlessAppsyncPlugin {
7288 private provider : Provider ;
7389 private gatheredData : {
@@ -90,6 +106,7 @@ class ServerlessAppsyncPlugin {
90106 constructor (
91107 public serverless : Serverless ,
92108 private options : Record < string , string > ,
109+ public utils : ServerlessPluginUtils ,
93110 ) {
94111 this . gatheredData = {
95112 apis : [ ] ,
@@ -98,7 +115,7 @@ class ServerlessAppsyncPlugin {
98115 this . serverless = serverless ;
99116 this . options = options ;
100117 this . provider = this . serverless . getProvider ( 'aws' ) ;
101-
118+ this . utils = utils ;
102119 // We are using a newer version of AJV than Serverless Framework
103120 // and some customizations (eg: custom errors, $merge, filter irrelevant errors)
104121 // For SF, just validate the type of input to allow us to use a custom
@@ -304,7 +321,7 @@ class ServerlessAppsyncPlugin {
304321 'appsync:validate-schema:run' : ( ) => {
305322 this . loadConfig ( ) ;
306323 this . validateSchemas ( ) ;
307- log . success ( 'AppSync schema valid' ) ;
324+ this . utils . log . success ( 'AppSync schema valid' ) ;
308325 } ,
309326 'appsync:get-introspection:run' : ( ) => this . getIntrospection ( ) ,
310327 'appsync:flush-cache:run' : ( ) => this . flushCache ( ) ,
@@ -327,7 +344,7 @@ class ServerlessAppsyncPlugin {
327344 this . initDomainCommand ( ) ,
328345 'appsync:domain:delete-record:run' : async ( ) => this . deleteRecord ( ) ,
329346 finalize : ( ) => {
330- writeText (
347+ this . utils . writeText (
331348 '\nLooking for a better AppSync development experience? Have you tried GraphBolt? https://graphbolt.dev' ,
332349 ) ;
333350 } ,
@@ -431,20 +448,22 @@ class ServerlessAppsyncPlugin {
431448 try {
432449 const filePath = path . resolve ( this . options . output ) ;
433450 fs . writeFileSync ( filePath , schema . toString ( ) ) ;
434- log . success ( `Introspection schema exported to ${ filePath } ` ) ;
451+ this . utils . log . success ( `Introspection schema exported to ${ filePath } ` ) ;
435452 } catch ( error ) {
436- log . error ( `Could not save to file: ${ ( error as Error ) . message } ` ) ;
453+ this . utils . log . error (
454+ `Could not save to file: ${ ( error as Error ) . message } ` ,
455+ ) ;
437456 }
438457 return ;
439458 }
440459
441- writeText ( schema . toString ( ) ) ;
460+ this . utils . writeText ( schema . toString ( ) ) ;
442461 }
443462
444463 async flushCache ( ) {
445464 const apiId = await this . getApiId ( ) ;
446465 await this . provider . request ( 'AppSync' , 'flushApiCache' , { apiId } ) ;
447- log . success ( 'Cache flushed successfully' ) ;
466+ this . utils . log . success ( 'Cache flushed successfully' ) ;
448467 }
449468
450469 async openConsole ( ) {
@@ -486,7 +505,7 @@ class ServerlessAppsyncPlugin {
486505
487506 events ?. forEach ( ( event ) => {
488507 const { timestamp, message } = event ;
489- writeText (
508+ this . utils . writeText (
490509 `${ chalk . gray (
491510 DateTime . fromMillis ( timestamp || 0 ) . toISO ( ) ,
492511 ) } \t${ message } `,
@@ -512,7 +531,7 @@ class ServerlessAppsyncPlugin {
512531 const domain = this . getDomain ( ) ;
513532
514533 if ( domain . useCloudFormation !== false ) {
515- log . warning (
534+ this . utils . log . warning (
516535 'You are using the CloudFormation integration for domain configuration.\n' +
517536 'To avoid CloudFormation drifts, you should not use it in combination with this command.\n' +
518537 'Set the `domain.useCloudFormation` attribute to false to use the CLI integration.\n' +
@@ -568,7 +587,7 @@ class ServerlessAppsyncPlugin {
568587 ( { DomainName } ) => DomainName === match ,
569588 ) ;
570589 if ( cert ) {
571- log . info (
590+ this . utils . log . info (
572591 `Found matching certificate for ${ match } : ${ cert . CertificateArn } ` ,
573592 ) ;
574593 return cert . CertificateArn ;
@@ -595,13 +614,13 @@ class ServerlessAppsyncPlugin {
595614 domainName : domain . name ,
596615 certificateArn,
597616 } ) ;
598- log . success ( `Domain '${ domain . name } ' created successfully` ) ;
617+ this . utils . log . success ( `Domain '${ domain . name } ' created successfully` ) ;
599618 } catch ( error ) {
600619 if (
601620 error instanceof this . serverless . classes . Error &&
602621 this . options . quiet
603622 ) {
604- log . error ( error . message ) ;
623+ this . utils . log . error ( error . message ) ;
605624 } else {
606625 throw error ;
607626 }
@@ -611,7 +630,7 @@ class ServerlessAppsyncPlugin {
611630 async deleteDomain ( ) {
612631 try {
613632 const domain = this . getDomain ( ) ;
614- log . warning ( `The domain '${ domain . name } will be deleted.` ) ;
633+ this . utils . log . warning ( `The domain '${ domain . name } will be deleted.` ) ;
615634 if ( ! this . options . yes && ! ( await confirmAction ( ) ) ) {
616635 return ;
617636 }
@@ -621,13 +640,13 @@ class ServerlessAppsyncPlugin {
621640 > ( 'AppSync' , 'deleteDomainName' , {
622641 domainName : domain . name ,
623642 } ) ;
624- log . success ( `Domain '${ domain . name } ' deleted successfully` ) ;
643+ this . utils . log . success ( `Domain '${ domain . name } ' deleted successfully` ) ;
625644 } catch ( error ) {
626645 if (
627646 error instanceof this . serverless . classes . Error &&
628647 this . options . quiet
629648 ) {
630- log . error ( error . message ) ;
649+ this . utils . log . error ( error . message ) ;
631650 } else {
632651 throw error ;
633652 }
@@ -663,8 +682,7 @@ class ServerlessAppsyncPlugin {
663682 message : string ;
664683 desiredStatus : 'SUCCESS' | 'NOT_FOUND' ;
665684 } ) {
666- const progressInstance = progress . create ( { message } ) ;
667-
685+ const progressInstance = this . utils . progress . create ( { message } ) ;
668686 let status : string ;
669687 do {
670688 status =
@@ -683,14 +701,14 @@ class ServerlessAppsyncPlugin {
683701 const assoc = await this . getApiAssocStatus ( domain . name ) ;
684702
685703 if ( assoc ?. associationStatus !== 'NOT_FOUND' && assoc ?. apiId !== apiId ) {
686- log . warning (
704+ this . utils . log . warning (
687705 `The domain ${ domain . name } is currently associated to another API (${ assoc ?. apiId } )` ,
688706 ) ;
689707 if ( ! this . options . yes && ! ( await confirmAction ( ) ) ) {
690708 return ;
691709 }
692710 } else if ( assoc ?. apiId === apiId ) {
693- log . success ( 'The domain is already associated to this API' ) ;
711+ this . utils . log . success ( 'The domain is already associated to this API' ) ;
694712 return ;
695713 }
696714
@@ -709,7 +727,9 @@ class ServerlessAppsyncPlugin {
709727 message,
710728 desiredStatus : 'SUCCESS' ,
711729 } ) ;
712- log . success ( `API successfully associated to domain '${ domain . name } '` ) ;
730+ this . utils . log . success (
731+ `API successfully associated to domain '${ domain . name } '` ,
732+ ) ;
713733 }
714734
715735 async disassocDomain ( ) {
@@ -718,7 +738,7 @@ class ServerlessAppsyncPlugin {
718738 const assoc = await this . getApiAssocStatus ( domain . name ) ;
719739
720740 if ( assoc ?. associationStatus === 'NOT_FOUND' ) {
721- log . warning (
741+ this . utils . log . warning (
722742 `The domain ${ domain . name } is currently not associated to any API` ,
723743 ) ;
724744 return ;
@@ -730,7 +750,7 @@ class ServerlessAppsyncPlugin {
730750 `Try running this command from that API's stack or stage, or use the --force / -f flag` ,
731751 ) ;
732752 }
733- log . warning (
753+ this . utils . log . warning (
734754 `The domain ${ domain . name } will be disassociated from API '${ apiId } '` ,
735755 ) ;
736756
@@ -752,7 +772,9 @@ class ServerlessAppsyncPlugin {
752772 desiredStatus : 'NOT_FOUND' ,
753773 } ) ;
754774
755- log . success ( `API successfully disassociated from domain '${ domain . name } '` ) ;
775+ this . utils . log . success (
776+ `API successfully disassociated from domain '${ domain . name } '` ,
777+ ) ;
756778 }
757779
758780 async getHostedZoneId ( ) {
@@ -798,7 +820,7 @@ class ServerlessAppsyncPlugin {
798820 }
799821
800822 async createRecord ( ) {
801- const progressInstance = progress . create ( {
823+ const progressInstance = this . utils . progress . create ( {
802824 message : 'Creating route53 record' ,
803825 } ) ;
804826
@@ -813,10 +835,10 @@ class ServerlessAppsyncPlugin {
813835 if ( changeId ) {
814836 await this . checkRoute53RecordStatus ( changeId ) ;
815837 progressInstance . remove ( ) ;
816- log . info (
838+ this . utils . log . info (
817839 `Alias record for '${ domain . name } ' was created in Hosted Zone '${ hostedZoneId } '` ,
818840 ) ;
819- log . success ( 'Route53 record created successfuly' ) ;
841+ this . utils . log . success ( 'Route53 record created successfuly' ) ;
820842 }
821843 }
822844
@@ -825,14 +847,14 @@ class ServerlessAppsyncPlugin {
825847 const appsyncDomainName = await this . getAppSyncDomainName ( ) ;
826848 const hostedZoneId = await this . getHostedZoneId ( ) ;
827849
828- log . warning (
850+ this . utils . log . warning (
829851 `Alias record for '${ domain . name } ' will be deleted from Hosted Zone '${ hostedZoneId } '` ,
830852 ) ;
831853 if ( ! this . options . yes && ! ( await confirmAction ( ) ) ) {
832854 return ;
833855 }
834856
835- const progressInstance = progress . create ( {
857+ const progressInstance = this . utils . progress . create ( {
836858 message : 'Deleting route53 record' ,
837859 } ) ;
838860
@@ -844,10 +866,10 @@ class ServerlessAppsyncPlugin {
844866 if ( changeId ) {
845867 await this . checkRoute53RecordStatus ( changeId ) ;
846868 progressInstance . remove ( ) ;
847- log . info (
869+ this . utils . log . info (
848870 `Alias record for '${ domain . name } ' was deleted from Hosted Zone '${ hostedZoneId } '` ,
849871 ) ;
850- log . success ( 'Route53 record deleted successfuly' ) ;
872+ this . utils . log . success ( 'Route53 record deleted successfuly' ) ;
851873 }
852874 }
853875
@@ -905,7 +927,7 @@ class ServerlessAppsyncPlugin {
905927 error instanceof this . serverless . classes . Error &&
906928 this . options . quiet
907929 ) {
908- log . error ( error . message ) ;
930+ this . utils . log . error ( error . message ) ;
909931 } else {
910932 throw error ;
911933 }
@@ -949,7 +971,7 @@ class ServerlessAppsyncPlugin {
949971 }
950972
951973 loadConfig ( ) {
952- log . info ( 'Loading AppSync config' ) ;
974+ this . utils . log . info ( 'Loading AppSync config' ) ;
953975
954976 const { appSync } = this . serverless . configurationInput ;
955977
@@ -969,15 +991,15 @@ class ServerlessAppsyncPlugin {
969991
970992 validateSchemas ( ) {
971993 try {
972- log . info ( 'Validating AppSync schema' ) ;
994+ this . utils . log . info ( 'Validating AppSync schema' ) ;
973995 if ( ! this . api ) {
974996 throw new this . serverless . classes . Error (
975997 'Could not load the API. This should not happen.' ,
976998 ) ;
977999 }
9781000 this . api . compileSchema ( ) ;
9791001 } catch ( error ) {
980- log . info ( 'Error' ) ;
1002+ this . utils . log . info ( 'Error' ) ;
9811003 if ( error instanceof GraphQLError ) {
9821004 this . handleError ( error . message ) ;
9831005 }
@@ -1057,7 +1079,7 @@ class ServerlessAppsyncPlugin {
10571079 if ( configValidationMode === 'error' ) {
10581080 throw new this . serverless . classes . Error ( message ) ;
10591081 } else if ( configValidationMode === 'warn' ) {
1060- log . warning ( message ) ;
1082+ this . utils . log . warning ( message ) ;
10611083 }
10621084 }
10631085}
0 commit comments