1
1
import * as path from 'path'
2
2
import * as fs from 'fs-extra'
3
-
4
3
import * as _ from 'lodash'
5
4
import * as globby from 'globby'
6
5
7
- import { ServerlessOptions , ServerlessInstance , ServerlessFunction } from './types'
8
6
import * as typescript from './typescript'
9
-
10
7
import { watchFiles } from './watchFiles'
11
8
12
- // Folders
13
- const serverlessFolder = '.serverless'
14
- const buildFolder = '.build'
9
+ const SERVERLESS_FOLDER = '.serverless'
10
+ const BUILD_FOLDER = '.build'
15
11
16
12
export class TypeScriptPlugin {
17
-
18
13
private originalServicePath : string
19
14
private isWatching : boolean
20
15
21
- serverless : ServerlessInstance
22
- options : ServerlessOptions
23
- commands : { [ key : string ] : any }
16
+ serverless : Serverless . Instance
17
+ options : Serverless . Options
24
18
hooks : { [ key : string ] : Function }
25
19
26
- constructor ( serverless : ServerlessInstance , options : ServerlessOptions ) {
20
+ constructor ( serverless : Serverless . Instance , options : Serverless . Options ) {
27
21
this . serverless = serverless
28
22
this . options = options
29
23
@@ -55,31 +49,42 @@ export class TypeScriptPlugin {
55
49
'after:invoke:local:invoke' : ( ) => {
56
50
if ( this . options . watch ) {
57
51
this . watchFunction ( )
58
- this . serverless . cli . log ( 'Waiting for changes ...' )
52
+ this . serverless . cli . log ( 'Waiting for changes...' )
59
53
}
60
54
}
61
55
}
62
56
}
63
57
64
58
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
68
69
}
69
70
70
71
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
+ )
72
77
}
73
78
74
79
prepare ( ) {
75
80
// 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 ]
79
83
fn . package = fn . package || {
80
84
exclude : [ ] ,
81
85
include : [ ] ,
82
86
}
87
+
83
88
// Add plugin to excluded packages or an empty array if exclude is undefined
84
89
fn . package . exclude = _ . uniq ( [ ...fn . package . exclude || [ ] , 'node_modules/serverless-plugin-typescript' ] )
85
90
}
@@ -106,9 +111,7 @@ export class TypeScriptPlugin {
106
111
this . serverless . cli . log ( `Watching typescript files...` )
107
112
108
113
this . isWatching = true
109
- watchFiles ( this . rootFileNames , this . originalServicePath , ( ) => {
110
- this . compileTs ( )
111
- } )
114
+ watchFiles ( this . rootFileNames , this . originalServicePath , this . compileTs )
112
115
}
113
116
114
117
async compileTs ( ) : Promise < string [ ] > {
@@ -119,25 +122,26 @@ export class TypeScriptPlugin {
119
122
// Save original service path and functions
120
123
this . originalServicePath = this . serverless . config . servicePath
121
124
// 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 )
123
126
}
124
127
125
128
const tsconfig = typescript . getTypescriptConfig (
126
129
this . originalServicePath ,
127
130
this . isWatching ? null : this . serverless . cli
128
131
)
129
132
130
- tsconfig . outDir = buildFolder
133
+ tsconfig . outDir = BUILD_FOLDER
131
134
132
135
const emitedFiles = await typescript . run ( this . rootFileNames , tsconfig )
133
136
await this . copyExtras ( )
134
137
this . serverless . cli . log ( 'Typescript compiled.' )
135
138
return emitedFiles
136
139
}
137
140
141
+ /** Link or copy extras such as node_modules or package.include definitions */
138
142
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' ) )
141
145
142
146
// Link or copy node_modules and package.json to .build so Serverless can
143
147
// exlcude devDeps during packaging
@@ -154,53 +158,58 @@ export class TypeScriptPlugin {
154
158
const files = await globby ( this . serverless . service . package . include )
155
159
156
160
for ( const filename of files ) {
157
- const destFileName = path . resolve ( path . join ( buildFolder , filename ) )
161
+ const destFileName = path . resolve ( path . join ( BUILD_FOLDER , filename ) )
158
162
const dirname = path . dirname ( destFileName )
159
163
160
164
if ( ! fs . existsSync ( dirname ) ) {
161
165
fs . mkdirpSync ( dirname )
162
166
}
163
167
164
168
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 ) ) )
166
170
}
167
171
}
168
172
}
169
173
}
170
174
175
+ /**
176
+ * Move built code to the serverless folder, taking into account individual
177
+ * packaging preferences.
178
+ */
171
179
async moveArtifacts ( ) : Promise < void > {
180
+ const { service } = this . serverless
181
+
172
182
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 )
175
185
)
176
186
177
187
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 (
181
190
this . originalServicePath ,
182
- serverlessFolder ,
191
+ SERVERLESS_FOLDER ,
183
192
path . basename ( fn . package . artifact )
184
193
)
185
194
return
186
195
}
187
196
188
- if ( this . serverless . service . package . individually ) {
189
- const functionNames = this . serverless . service . getAllFunctions ( )
197
+ if ( service . package . individually ) {
198
+ const functionNames = service . getAllFunctions ( )
190
199
functionNames . forEach ( name => {
191
- this . serverless . service . functions [ name ] . package . artifact = path . join (
200
+ service . functions [ name ] . package . artifact = path . join (
192
201
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 )
195
204
)
196
205
} )
197
206
return
198
207
}
199
208
200
- this . serverless . service . package . artifact = path . join (
209
+ service . package . artifact = path . join (
201
210
this . originalServicePath ,
202
- serverlessFolder ,
203
- path . basename ( this . serverless . service . package . artifact )
211
+ SERVERLESS_FOLDER ,
212
+ path . basename ( service . package . artifact )
204
213
)
205
214
}
206
215
@@ -209,18 +218,14 @@ export class TypeScriptPlugin {
209
218
// Restore service path
210
219
this . serverless . config . servicePath = this . originalServicePath
211
220
// Remove temp build folder
212
- fs . removeSync ( path . join ( this . originalServicePath , buildFolder ) )
221
+ fs . removeSync ( path . join ( this . originalServicePath , BUILD_FOLDER ) )
213
222
}
214
223
215
224
/**
216
225
* Attempt to symlink a given path or directory and copy if it fails with an
217
226
* `EPERM` error.
218
227
*/
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 > {
224
229
return fs . symlink ( srcPath , dstPath , type )
225
230
. catch ( error => {
226
231
if ( error . code === 'EPERM' && error . errno === - 4048 ) {
0 commit comments