@@ -21,12 +21,14 @@ const TYPESCRIPT_PLUGIN_BUILD_DIR_WEBPACK = '.webpack/service'; //TODO detect fr
2121const TS_PLUGIN_ESBUILD = 'EsbuildServerlessPlugin'
2222const TYPESCRIPT_PLUGIN_BUILD_DIR_ESBUILD = '.esbuild/.build' ; //TODO detect from esbuild.config.js
2323
24- // Default edge port to use with host
25- const DEFAULT_EDGE_PORT = ' 4566' ;
24+ // Default AWS endpoint URL
25+ const DEFAULT_AWS_ENDPOINT_URL = "http://localhost: 4566" ;
2626
2727// Cache hostname to avoid unnecessary connection checks
2828var resolvedHostname = undefined ;
2929
30+ const awsEndpointUrl = process . env . AWS_ENDPOINT_URL || DEFAULT_AWS_ENDPOINT_URL ;
31+
3032class LocalstackPlugin {
3133 constructor ( serverless , options ) {
3234
@@ -136,17 +138,17 @@ class LocalstackPlugin {
136138 if ( this . detectTypescriptPluginType ( ) === TS_PLUGIN_WEBPACK ) {
137139 const p = this . serverless . pluginManager . plugins . find ( ( x ) => x . constructor . name === TS_PLUGIN_WEBPACK ) ;
138140 if (
139- this . shouldMountCode ( ) && (
140- ! p ||
141- ! p . serverless ||
142- ! p . serverless . configurationInput ||
143- ! p . serverless . configurationInput . custom ||
144- ! p . serverless . configurationInput . custom . webpack ||
145- ! p . serverless . configurationInput . custom . webpack . keepOutputDirectory
146- )
141+ this . shouldMountCode ( ) && (
142+ ! p ||
143+ ! p . serverless ||
144+ ! p . serverless . configurationInput ||
145+ ! p . serverless . configurationInput . custom ||
146+ ! p . serverless . configurationInput . custom . webpack ||
147+ ! p . serverless . configurationInput . custom . webpack . keepOutputDirectory
148+ )
147149 ) {
148150 throw new Error ( 'When mounting Lambda code, you must retain webpack output directory. '
149- + 'Set custom.webpack.keepOutputDirectory to true.' ) ;
151+ + 'Set custom.webpack.keepOutputDirectory to true.' ) ;
150152 }
151153 }
152154 }
@@ -158,7 +160,7 @@ class LocalstackPlugin {
158160 addHookInFirstPosition ( eventName , hookFunction ) {
159161 this . serverless . pluginManager . hooks [ eventName ] = this . serverless . pluginManager . hooks [ eventName ] || [ ] ;
160162 this . serverless . pluginManager . hooks [ eventName ] . unshift (
161- { pluginName : 'LocalstackPlugin' , hook : hookFunction . bind ( this , eventName ) } ) ;
163+ { pluginName : 'LocalstackPlugin' , hook : hookFunction . bind ( this , eventName ) } ) ;
162164 }
163165
164166 activatePlugin ( preHooks ) {
@@ -241,11 +243,11 @@ class LocalstackPlugin {
241243 this . getStageVariable ( ) ;
242244
243245 return this . startLocalStack ( ) . then (
244- ( ) => {
246+ ( ) => {
245247 this . patchServerlessSecrets ( ) ;
246248 this . patchS3BucketLocationResponse ( ) ;
247249 this . patchS3CreateBucketLocationConstraint ( ) ;
248- }
250+ }
249251 ) ;
250252 }
251253
@@ -298,17 +300,17 @@ class LocalstackPlugin {
298300
299301 // overwrite bound functions for specified hook names
300302 ( hookNames || [ ] ) . forEach (
301- ( hookName ) => {
302- plugin . hooks [ hookName ] = boundOverrideFunction ;
303- const slsHooks = this . serverless . pluginManager . hooks [ hookName ] || [ ] ;
304- slsHooks . forEach (
305- ( hookItem ) => {
306- if ( hookItem . pluginName === pluginName ) {
307- hookItem . hook = boundOverrideFunction ;
308- }
309- }
310- ) ;
311- }
303+ ( hookName ) => {
304+ plugin . hooks [ hookName ] = boundOverrideFunction ;
305+ const slsHooks = this . serverless . pluginManager . hooks [ hookName ] || [ ] ;
306+ slsHooks . forEach (
307+ ( hookItem ) => {
308+ if ( hookItem . pluginName === pluginName ) {
309+ hookItem . hook = boundOverrideFunction ;
310+ }
311+ }
312+ ) ;
313+ }
312314 ) ;
313315 }
314316
@@ -412,18 +414,18 @@ class LocalstackPlugin {
412414
413415 const getContainer = ( ) => {
414416 return exec ( 'docker ps' ) . then (
415- ( stdout ) => {
416- const exists = stdout . split ( '\n' ) . filter (
417- ( line ) => (
418- line . indexOf ( 'localstack/localstack' ) >= 0 ||
419- line . indexOf ( 'localstack/localstack-pro' ) >= 0 ||
420- line . indexOf ( 'localstack_localstack' ) >= 0
421- )
422- ) ;
423- if ( exists . length ) {
424- return exists [ 0 ] . replace ( '\t' , ' ' ) . split ( ' ' ) [ 0 ] ;
417+ ( stdout ) => {
418+ const exists = stdout . split ( '\n' ) . filter (
419+ ( line ) => (
420+ line . indexOf ( 'localstack/localstack' ) >= 0 ||
421+ line . indexOf ( 'localstack/localstack-pro' ) >= 0 ||
422+ line . indexOf ( 'localstack_localstack' ) >= 0
423+ )
424+ ) ;
425+ if ( exists . length ) {
426+ return exists [ 0 ] . replace ( '\t' , ' ' ) . split ( ' ' ) [ 0 ] ;
427+ }
425428 }
426- }
427429 )
428430 } ;
429431
@@ -438,13 +440,13 @@ class LocalstackPlugin {
438440 return this . sleep ( 4000 ) . then ( ( ) => {
439441 this . log ( `Checking state of LocalStack container ${ containerID } ` )
440442 return exec ( `docker logs "${ containerID } "` ) . then (
441- ( logs ) => {
442- const ready = logs . split ( '\n' ) . filter ( ( line ) => line . indexOf ( 'Ready.' ) >= 0 ) ;
443- if ( ready . length ) {
444- return Promise . resolve ( ) ;
443+ ( logs ) => {
444+ const ready = logs . split ( '\n' ) . filter ( ( line ) => line . indexOf ( 'Ready.' ) >= 0 ) ;
445+ if ( ready . length ) {
446+ return Promise . resolve ( ) ;
447+ }
448+ return checkStatus ( containerID , timeout ) ;
445449 }
446- return checkStatus ( containerID , timeout ) ;
447- }
448450 ) ;
449451 } ) ;
450452 }
@@ -483,17 +485,17 @@ class LocalstackPlugin {
483485 }
484486
485487 return getContainer ( ) . then (
486- ( containerID ) => {
487- if ( containerID ) {
488- return ;
489- }
488+ ( containerID ) => {
489+ if ( containerID ) {
490+ return ;
491+ }
490492
491- if ( this . config . docker && this . config . docker . compose_file ) {
493+ if ( this . config . docker && this . config . docker . compose_file ) {
492494 return startCompose ( ) ;
493- }
495+ }
494496
495- return startContainer ( ) ;
496- }
497+ return startContainer ( ) ;
498+ }
497499 ) ;
498500 }
499501
@@ -508,12 +510,12 @@ class LocalstackPlugin {
508510 const template = this . serverless . service . provider . compiledCloudFormationTemplate || { } ;
509511 const resources = template . Resources || { } ;
510512 Object . keys ( resources ) . forEach (
511- ( resName ) => {
512- const resEntry = resources [ resName ] ;
513- if ( resEntry . Type === 'AWS::Lambda::Function' ) {
514- resEntry . Properties . Handler = `${ this . getTSBuildDir ( ) } /${ resEntry . Properties . Handler } ` ;
513+ ( resName ) => {
514+ const resEntry = resources [ resName ] ;
515+ if ( resEntry . Type === 'AWS::Lambda::Function' ) {
516+ resEntry . Properties . Handler = `${ this . getTSBuildDir ( ) } /${ resEntry . Properties . Handler } ` ;
517+ }
515518 }
516- }
517519 ) ;
518520 }
519521
@@ -540,9 +542,9 @@ class LocalstackPlugin {
540542 }
541543
542544 /**
543- * Patch S3 createBucket invocation to not add a LocationContraint if the region is `us-east-1`
544- * The default SDK check was against endpoint and not the region directly.
545- */
545+ * Patch S3 createBucket invocation to not add a LocationContraint if the region is `us-east-1`
546+ * The default SDK check was against endpoint and not the region directly.
547+ */
546548 patchS3CreateBucketLocationConstraint ( ) {
547549 AWS . util . update ( AWS . S3 . prototype , {
548550 createBucket : function createBucket ( params , callback ) {
@@ -646,7 +648,7 @@ class LocalstackPlugin {
646648 else {
647649 this . endpoints = { }
648650 this . log ( "Skipping serverless-localstack:\ncustom.localstack.stages: " +
649- JSON . stringify ( this . config . stages ) + "\nstage: " + this . config . stage
651+ JSON . stringify ( this . config . stages ) + "\nstage: " + this . config . stage
650652 )
651653 }
652654 }
@@ -700,8 +702,23 @@ class LocalstackPlugin {
700702
701703 /* Utility functions below */
702704
705+ getEndpointPort ( ) {
706+ const url = new URL ( awsEndpointUrl ) ;
707+ return url . port ;
708+ }
709+
710+ getEndpointHostname ( ) {
711+ const url = new URL ( awsEndpointUrl ) ;
712+ return url . hostname ;
713+ }
714+
715+ getEndpointProtocol ( ) {
716+ const url = new URL ( awsEndpointUrl ) ;
717+ return url . protocol . replace ( ":" , "" ) ;
718+ }
719+
703720 getEdgePort ( ) {
704- return process . env . EDGE_PORT || this . config . edgePort || DEFAULT_EDGE_PORT ;
721+ return process . env . EDGE_PORT || this . config . edgePort || this . getEndpointPort ( ) ;
705722 }
706723
707724 /**
@@ -713,7 +730,7 @@ class LocalstackPlugin {
713730 return resolvedHostname ;
714731 }
715732
716- var hostname = process . env . LOCALSTACK_HOSTNAME || 'localhost' ;
733+ var hostname = process . env . LOCALSTACK_HOSTNAME || this . getEndpointHostname ( ) ;
717734 if ( this . config . host ) {
718735 hostname = this . config . host ;
719736 if ( hostname . indexOf ( "://" ) !== - 1 ) {
@@ -782,13 +799,19 @@ class LocalstackPlugin {
782799 return this . injectHostnameIntoLocalhostURL ( process . env . AWS_ENDPOINT_URL , hostname ) ;
783800 }
784801 hostname = hostname || 'localhost' ;
785- const proto = TRUE_VALUES . includes ( process . env . USE_SSL ) ? 'https' : 'http' ;
802+
803+ let proto = this . getEndpointProtocol ( ) ;
804+ if ( process . env . USE_SSL ) {
805+ proto = TRUE_VALUES . includes ( process . env . USE_SSL ) ? 'https' : 'http' ;
806+ } else if ( this . config . host ) {
807+ proto = this . config . host . split ( "://" ) [ 0 ] ;
808+ }
786809 const port = this . getEdgePort ( ) ;
787810 // little hack here - required to remove the default HTTPS port 443, as otherwise
788811 // routing for some platforms and ephemeral instances (e.g., on namespace.so) fails
789812 const isDefaultPort =
790- ( proto === 'http' && `${ port } ` === '80' ) ||
791- ( proto === 'https' && `${ port } ` === '443' ) ;
813+ ( proto === 'http' && `${ port } ` === '80' ) ||
814+ ( proto === 'https' && `${ port } ` === '443' ) ;
792815 if ( isDefaultPort ) {
793816 return `${ proto } ://${ hostname } ` ;
794817 }
@@ -850,14 +873,14 @@ class LocalstackPlugin {
850873 patchCustomResourceLambdaS3ForcePathStyle ( ) {
851874 const awsProvider = this . awsProvider ;
852875 const patchMarker = path . join (
853- awsProvider . serverless . serviceDir ,
854- '.serverless' ,
855- '.internal-custom-resources-patched'
876+ awsProvider . serverless . serviceDir ,
877+ '.serverless' ,
878+ '.internal-custom-resources-patched'
856879 ) ;
857880 const zipFilePath = path . join (
858- awsProvider . serverless . serviceDir ,
859- '.serverless' ,
860- awsProvider . naming . getCustomResourcesArtifactName ( )
881+ awsProvider . serverless . serviceDir ,
882+ '.serverless' ,
883+ awsProvider . naming . getCustomResourcesArtifactName ( )
861884 ) ;
862885
863886 function fileExists ( filePath ) {
0 commit comments