11import * as path from 'path'
22import * as fs from 'fs-extra'
3-
43import * as _ from 'lodash'
54import * as globby from 'globby'
65
7- import { ServerlessOptions , ServerlessInstance , ServerlessFunction } from './types'
86import * as typescript from './typescript'
9-
107import { watchFiles } from './watchFiles'
118
12- // Folders
13- const serverlessFolder = '.serverless'
14- const buildFolder = '.build'
9+ const SERVERLESS_FOLDER = '.serverless'
10+ const BUILD_FOLDER = '.build'
1511
1612export class TypeScriptPlugin {
17-
1813 private originalServicePath : string
1914 private isWatching : boolean
2015
21- serverless : ServerlessInstance
22- options : ServerlessOptions
23- commands : { [ key : string ] : any }
16+ serverless : Serverless . Instance
17+ options : Serverless . Options
2418 hooks : { [ key : string ] : Function }
2519
26- constructor ( serverless : ServerlessInstance , options : ServerlessOptions ) {
20+ constructor ( serverless : Serverless . Instance , options : Serverless . Options ) {
2721 this . serverless = serverless
2822 this . options = options
2923
@@ -55,31 +49,42 @@ export class TypeScriptPlugin {
5549 'after:invoke:local:invoke' : ( ) => {
5650 if ( this . options . watch ) {
5751 this . watchFunction ( )
58- this . serverless . cli . log ( 'Waiting for changes ...' )
52+ this . serverless . cli . log ( 'Waiting for changes...' )
5953 }
6054 }
6155 }
6256 }
6357
6458 get functions ( ) {
65- return this . options . function
66- ? { [ this . options . function ] : this . serverless . service . functions [ this . options . function ] }
67- : this . serverless . service . functions
59+ const { options } = this
60+ const { service } = this . serverless
61+
62+ if ( options . function ) {
63+ return {
64+ [ options . function ] : service . functions [ this . options . function ]
65+ }
66+ }
67+
68+ return service . functions
6869 }
6970
7071 get rootFileNames ( ) {
71- return typescript . extractFileNames ( this . originalServicePath , this . serverless . service . provider . name , this . functions )
72+ return typescript . extractFileNames (
73+ this . originalServicePath ,
74+ this . serverless . service . provider . name ,
75+ this . functions
76+ )
7277 }
7378
7479 prepare ( ) {
7580 // exclude serverless-plugin-typescript
76- const functions = this . functions
77- for ( const fnName in functions ) {
78- const fn = functions [ fnName ]
81+ for ( const fnName in this . functions ) {
82+ const fn = this . functions [ fnName ]
7983 fn . package = fn . package || {
8084 exclude : [ ] ,
8185 include : [ ] ,
8286 }
87+
8388 // Add plugin to excluded packages or an empty array if exclude is undefined
8489 fn . package . exclude = _ . uniq ( [ ...fn . package . exclude || [ ] , 'node_modules/serverless-plugin-typescript' ] )
8590 }
@@ -106,9 +111,7 @@ export class TypeScriptPlugin {
106111 this . serverless . cli . log ( `Watching typescript files...` )
107112
108113 this . isWatching = true
109- watchFiles ( this . rootFileNames , this . originalServicePath , ( ) => {
110- this . compileTs ( )
111- } )
114+ watchFiles ( this . rootFileNames , this . originalServicePath , this . compileTs )
112115 }
113116
114117 async compileTs ( ) : Promise < string [ ] > {
@@ -119,25 +122,26 @@ export class TypeScriptPlugin {
119122 // Save original service path and functions
120123 this . originalServicePath = this . serverless . config . servicePath
121124 // Fake service path so that serverless will know what to zip
122- this . serverless . config . servicePath = path . join ( this . originalServicePath , buildFolder )
125+ this . serverless . config . servicePath = path . join ( this . originalServicePath , BUILD_FOLDER )
123126 }
124127
125128 const tsconfig = typescript . getTypescriptConfig (
126129 this . originalServicePath ,
127130 this . isWatching ? null : this . serverless . cli
128131 )
129132
130- tsconfig . outDir = buildFolder
133+ tsconfig . outDir = BUILD_FOLDER
131134
132135 const emitedFiles = await typescript . run ( this . rootFileNames , tsconfig )
133136 await this . copyExtras ( )
134137 this . serverless . cli . log ( 'Typescript compiled.' )
135138 return emitedFiles
136139 }
137140
141+ /** Link or copy extras such as node_modules or package.include definitions */
138142 async copyExtras ( ) {
139- const outPkgPath = path . resolve ( path . join ( buildFolder , 'package.json' ) )
140- const outModulesPath = path . resolve ( path . join ( buildFolder , 'node_modules' ) )
143+ const outPkgPath = path . resolve ( path . join ( BUILD_FOLDER , 'package.json' ) )
144+ const outModulesPath = path . resolve ( path . join ( BUILD_FOLDER , 'node_modules' ) )
141145
142146 // Link or copy node_modules and package.json to .build so Serverless can
143147 // exlcude devDeps during packaging
@@ -154,53 +158,58 @@ export class TypeScriptPlugin {
154158 const files = await globby ( this . serverless . service . package . include )
155159
156160 for ( const filename of files ) {
157- const destFileName = path . resolve ( path . join ( buildFolder , filename ) )
161+ const destFileName = path . resolve ( path . join ( BUILD_FOLDER , filename ) )
158162 const dirname = path . dirname ( destFileName )
159163
160164 if ( ! fs . existsSync ( dirname ) ) {
161165 fs . mkdirpSync ( dirname )
162166 }
163167
164168 if ( ! fs . existsSync ( destFileName ) ) {
165- fs . copySync ( path . resolve ( filename ) , path . resolve ( path . join ( buildFolder , filename ) ) )
169+ fs . copySync ( path . resolve ( filename ) , path . resolve ( path . join ( BUILD_FOLDER , filename ) ) )
166170 }
167171 }
168172 }
169173 }
170174
175+ /**
176+ * Move built code to the serverless folder, taking into account individual
177+ * packaging preferences.
178+ */
171179 async moveArtifacts ( ) : Promise < void > {
180+ const { service } = this . serverless
181+
172182 await fs . copy (
173- path . join ( this . originalServicePath , buildFolder , serverlessFolder ) ,
174- path . join ( this . originalServicePath , serverlessFolder )
183+ path . join ( this . originalServicePath , BUILD_FOLDER , SERVERLESS_FOLDER ) ,
184+ path . join ( this . originalServicePath , SERVERLESS_FOLDER )
175185 )
176186
177187 if ( this . options . function ) {
178- const fn = this . serverless . service . functions [ this . options . function ]
179- const basename = path . basename ( fn . package . artifact )
180- fn . package . artifact = path . join (
188+ const fn = service . functions [ this . options . function ]
189+ fn . package . artifact = path . join (
181190 this . originalServicePath ,
182- serverlessFolder ,
191+ SERVERLESS_FOLDER ,
183192 path . basename ( fn . package . artifact )
184193 )
185194 return
186195 }
187196
188- if ( this . serverless . service . package . individually ) {
189- const functionNames = this . serverless . service . getAllFunctions ( )
197+ if ( service . package . individually ) {
198+ const functionNames = service . getAllFunctions ( )
190199 functionNames . forEach ( name => {
191- this . serverless . service . functions [ name ] . package . artifact = path . join (
200+ service . functions [ name ] . package . artifact = path . join (
192201 this . originalServicePath ,
193- serverlessFolder ,
194- path . basename ( this . serverless . service . functions [ name ] . package . artifact )
202+ SERVERLESS_FOLDER ,
203+ path . basename ( service . functions [ name ] . package . artifact )
195204 )
196205 } )
197206 return
198207 }
199208
200- this . serverless . service . package . artifact = path . join (
209+ service . package . artifact = path . join (
201210 this . originalServicePath ,
202- serverlessFolder ,
203- path . basename ( this . serverless . service . package . artifact )
211+ SERVERLESS_FOLDER ,
212+ path . basename ( service . package . artifact )
204213 )
205214 }
206215
@@ -209,18 +218,14 @@ export class TypeScriptPlugin {
209218 // Restore service path
210219 this . serverless . config . servicePath = this . originalServicePath
211220 // Remove temp build folder
212- fs . removeSync ( path . join ( this . originalServicePath , buildFolder ) )
221+ fs . removeSync ( path . join ( this . originalServicePath , BUILD_FOLDER ) )
213222 }
214223
215224 /**
216225 * Attempt to symlink a given path or directory and copy if it fails with an
217226 * `EPERM` error.
218227 */
219- private async linkOrCopy (
220- srcPath : string ,
221- dstPath : string ,
222- type ?: 'dir' | 'junction' | 'file'
223- ) : Promise < void > {
228+ private async linkOrCopy ( srcPath : string , dstPath : string , type ?: fs . FsSymlinkType ) : Promise < void > {
224229 return fs . symlink ( srcPath , dstPath , type )
225230 . catch ( error => {
226231 if ( error . code === 'EPERM' && error . errno === - 4048 ) {
0 commit comments