Skip to content

Commit 4201aaa

Browse files
committed
refactor: improvements to documentation and type definitions
1 parent 02b1efa commit 4201aaa

File tree

6 files changed

+103
-100
lines changed

6 files changed

+103
-100
lines changed

src/Serverless.d.ts

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
declare namespace Serverless {
2+
interface Instance {
3+
cli: {
4+
log(str: string): void
5+
}
6+
7+
config: {
8+
servicePath: string
9+
}
10+
11+
service: {
12+
provider: {
13+
name: string
14+
}
15+
functions: {
16+
[key: string]: Serverless.Function
17+
}
18+
package: Serverless.Package
19+
getAllFunctions(): string[]
20+
}
21+
22+
pluginManager: PluginManager
23+
}
24+
25+
interface Options {
26+
function?: string
27+
watch?: boolean
28+
extraServicePath?: string
29+
}
30+
31+
interface Function {
32+
handler: string
33+
package: Serverless.Package
34+
}
35+
36+
interface Package {
37+
include: string[]
38+
exclude: string[]
39+
artifact?: string
40+
individually?: boolean
41+
}
42+
43+
interface PluginManager {
44+
spawn(command: string): Promise<void>
45+
}
46+
}

src/index.ts

Lines changed: 53 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,23 @@
11
import * as path from 'path'
22
import * as fs from 'fs-extra'
3-
43
import * as _ from 'lodash'
54
import * as globby from 'globby'
65

7-
import { ServerlessOptions, ServerlessInstance, ServerlessFunction } from './types'
86
import * as typescript from './typescript'
9-
107
import { 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

1612
export 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) {

src/types.ts

Lines changed: 0 additions & 39 deletions
This file was deleted.

src/typescript.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import * as ts from 'typescript'
22
import * as fs from 'fs-extra'
33
import * as _ from 'lodash'
4-
import { ServerlessFunction } from './types'
54
import * as path from 'path'
65

76
export function makeDefaultTypescriptConfig() {
@@ -19,8 +18,7 @@ export function makeDefaultTypescriptConfig() {
1918
return defaultTypescriptConfig
2019
}
2120

22-
export function extractFileNames(cwd: string, provider: string, functions?: { [key: string]: ServerlessFunction }): string[] {
23-
21+
export function extractFileNames(cwd: string, provider: string, functions?: { [key: string]: Serverless.Function }): string[] {
2422
// The Google provider will use the entrypoint not from the definition of the
2523
// handler function, but instead from the package.json:main field, or via a
2624
// index.js file. This check reads the current package.json in the same way

src/watchFiles.ts

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,7 @@
11
import * as typescript from './typescript'
2-
import * as ts from 'typescript'
32
import { watchFile, unwatchFile, Stats} from 'fs'
4-
import { ServerlessOptions, ServerlessInstance, ServerlessFunction } from './types'
53

6-
export function watchFiles(
7-
rootFileNames: string[],
8-
originalServicePath: string,
9-
cb: () => void
10-
) {
4+
export function watchFiles(rootFileNames: string[], originalServicePath: string, cb: () => void) {
115
const tsConfig = typescript.getTypescriptConfig(originalServicePath)
126
let watchedFiles = typescript.getSourceFiles(rootFileNames, tsConfig)
137

@@ -18,7 +12,7 @@ export function watchFiles(
1812
function watchCallback(curr: Stats, prev: Stats) {
1913
// Check timestamp
2014
if (+curr.mtime <= +prev.mtime) {
21-
return
15+
return
2216
}
2317

2418
cb()

tests/typescript.extractFileName.test.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
import {extractFileNames} from '../src/typescript'
2-
import {ServerlessFunction} from '../src/types'
32
import * as path from 'path'
43

5-
const functions: { [key: string]: ServerlessFunction } = {
4+
const functions: { [key: string]: Serverless.Function } = {
65
hello: {
76
handler: 'tests/assets/hello.handler',
87
package: {

0 commit comments

Comments
 (0)