Skip to content

Commit 90a3aeb

Browse files
authored
Merge pull request #30 from wyattjoh/google-functions-support
Added support for Google Cloud Functions
2 parents e24f577 + facd2b3 commit 90a3aeb

File tree

6 files changed

+69
-7
lines changed

6 files changed

+69
-7
lines changed

README.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,27 @@ All files from `package/include` will be included in the final build file. See [
5757

5858
## Usage
5959

60+
### Google Cloud Functions
61+
62+
When using with Google Cloud Functions via the [serverless-google-cloudfunctions](https://github.com/serverless/serverless-google-cloudfunctions)
63+
plugin, you simply have to provide a `main` field in your `package.json`:
64+
65+
```js
66+
{
67+
// ...
68+
"main": "handler.js",
69+
// ..
70+
}
71+
```
72+
73+
And this plugin will automatically compile your typescript correctly. Note
74+
that the field must refer to the compiled file name, namely, ending with a `.js`
75+
extension.
76+
77+
If a `main` field was not found, then this plugin will use `index.js`. Before
78+
compilation begins, it will check to see that the file indicated exists with a
79+
`.ts` extension before actually trying to compile it.
80+
6081
### Automatic compilation
6182

6283
The normal Serverless deploy procedure will automatically compile with Typescript:

example/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
{
2+
"main": "handler.js",
23
"dependencies": {
34
"lodash": "^4.17.4"
45
},

src/index.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ export class ServerlessPlugin {
6565
}
6666

6767
get rootFileNames() {
68-
return typescript.extractFileNames(this.functions)
68+
return typescript.extractFileNames(this.originalServicePath, this.serverless.service.provider.name, this.functions)
6969
}
7070

7171
prepare() {
@@ -118,15 +118,14 @@ export class ServerlessPlugin {
118118
this.serverless.config.servicePath = path.join(this.originalServicePath, buildFolder)
119119
}
120120

121-
const tsFileNames = typescript.extractFileNames(this.functions)
122121
const tsconfig = typescript.getTypescriptConfig(
123122
this.originalServicePath,
124123
this.isWatching ? null : this.serverless.cli
125124
)
126125

127126
tsconfig.outDir = buildFolder
128127

129-
const emitedFiles = await typescript.run(tsFileNames, tsconfig)
128+
const emitedFiles = await typescript.run(this.rootFileNames, tsconfig)
130129
await this.copyExtras()
131130
return emitedFiles
132131
}

src/types.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ export interface ServerlessInstance {
66
servicePath: string
77
}
88
service: {
9+
provider: {
10+
name: string
11+
}
912
functions: { [key: string]: ServerlessFunction }
1013
package: ServerlessPackage
1114
getAllFunctions: () => string[]

src/typescript.ts

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,35 @@ export function makeDefaultTypescriptConfig() {
1818
return defaultTypescriptConfig
1919
}
2020

21-
export function extractFileNames(functions: { [key: string]: ServerlessFunction }): string[] {
21+
export function extractFileNames(cwd: string, provider: string, functions?: { [key: string]: ServerlessFunction }): string[] {
22+
23+
// The Google provider will use the entrypoint not from the definition of the
24+
// handler function, but instead from the package.json:main field, or via a
25+
// index.js file. This check reads the current package.json in the same way
26+
// that we already read the tsconfig.json file, by inspecting the current
27+
// working directory. If the packageFile does not contain a valid main, then
28+
// it instead selects the index.js file.
29+
if (provider === 'google') {
30+
const packageFilePath = path.join(cwd, 'package.json')
31+
if (fs.existsSync(packageFilePath)) {
32+
33+
// Load in the package.json file.
34+
const packageFile = JSON.parse(fs.readFileSync(packageFilePath).toString())
35+
36+
// Either grab the package.json:main field, or use the index.ts file.
37+
// (This will be transpiled to index.js).
38+
const main = packageFile.main ? packageFile.main.replace(/\.js$/, '.ts') : 'index.ts'
39+
40+
// Check that the file indeed exists.
41+
if (!fs.existsSync(path.join(cwd, main))) {
42+
console.log(`Cannot locate entrypoint, ${main} not found`)
43+
throw new Error('Typescript compilation failed')
44+
}
45+
46+
return [main]
47+
}
48+
}
49+
2250
return _.values(functions)
2351
.map(fn => fn.handler)
2452
.map(h => {

tests/typescript.extractFileName.test.ts

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import {extractFileNames} from '../src/typescript'
22
import {ServerlessFunction} from '../src/types'
3+
import * as path from 'path'
34

45
const functions: { [key: string]: ServerlessFunction } = {
56
hello: {
@@ -26,9 +27,9 @@ const functions: { [key: string]: ServerlessFunction } = {
2627
}
2728

2829
describe('extractFileName', () => {
29-
it('get function filenames from serverless service', () => {
30+
it('get function filenames from serverless service for a non-google provider', () => {
3031
expect(
31-
extractFileNames(functions),
32+
extractFileNames(process.cwd(), 'aws', functions),
3233
).toEqual(
3334
[
3435
'my-folder/hello.ts',
@@ -37,5 +38,14 @@ describe('extractFileName', () => {
3738
],
3839
)
3940
})
40-
})
4141

42+
it('get function filename from serverless service for a google provider', () => {
43+
expect(
44+
extractFileNames(path.join(process.cwd(), 'example'), 'google')
45+
).toEqual(
46+
[
47+
'handler.ts'
48+
]
49+
)
50+
})
51+
})

0 commit comments

Comments
 (0)