Skip to content

Commit c1b670b

Browse files
authored
Merge pull request #72 from serverless/add-function-handler-validation
Add function handler validation
2 parents 068bd9c + 2ce6441 commit c1b670b

File tree

2 files changed

+51
-1
lines changed

2 files changed

+51
-1
lines changed

shared/validate.js

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
'use strict';
22

33
const BbPromise = require('bluebird');
4+
const _ = require('lodash');
45

56
module.exports = {
67
validate() {
78
return BbPromise.bind(this)
89
.then(this.validateServicePath)
9-
.then(this.validateServiceName);
10+
.then(this.validateServiceName)
11+
.then(this.validateHandlers);
1012
},
1113

1214
validateServicePath() {
@@ -31,4 +33,22 @@ module.exports = {
3133

3234
return BbPromise.resolve();
3335
},
36+
37+
validateHandlers() {
38+
const functions = this.serverless.service.functions;
39+
40+
_.forEach(functions, (funcVal, funcKey) => {
41+
if (funcVal.handler.includes('/') || funcVal.handler.includes('.')) {
42+
const errorMessage = [
43+
`The "handler" property for the function "${funcKey}" is invalid.`,
44+
' Handlers should be plain strings referencing only the exported function name',
45+
' without characters such as "." or "/" (so e.g. "http" instead of "index.http").',
46+
' Do you want to nest your functions code in a subdirectory?',
47+
' Google solves this by utilizing the "main" config in the projects package.json file.',
48+
' Please check the docs for more info.',
49+
].join('');
50+
throw new Error(errorMessage);
51+
}
52+
});
53+
},
3454
};

shared/validate.test.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,23 +27,28 @@ describe('Validate', () => {
2727
describe('#validate()', () => {
2828
let validateServicePathStub;
2929
let validateServiceNameStub;
30+
let validateHandlersStub;
3031

3132
beforeEach(() => {
3233
validateServicePathStub = sinon.stub(googleCommand, 'validateServicePath')
3334
.returns(BbPromise.resolve());
3435
validateServiceNameStub = sinon.stub(googleCommand, 'validateServiceName')
3536
.returns(BbPromise.resolve());
37+
validateHandlersStub = sinon.stub(googleCommand, 'validateHandlers')
38+
.returns(BbPromise.resolve());
3639
});
3740

3841
afterEach(() => {
3942
googleCommand.validateServicePath.restore();
4043
googleCommand.validateServiceName.restore();
44+
googleCommand.validateHandlers.restore();
4145
});
4246

4347
it('should run promise chain', () => googleCommand
4448
.validate().then(() => {
4549
expect(validateServicePathStub.calledOnce).toEqual(true);
4650
expect(validateServiceNameStub.calledAfter(validateServicePathStub));
51+
expect(validateHandlersStub.calledAfter(validateServiceNameStub));
4752
}));
4853
});
4954

@@ -80,4 +85,29 @@ describe('Validate', () => {
8085
expect(() => googleCommand.validateServiceName()).not.toThrow(Error);
8186
});
8287
});
88+
89+
describe('#validateHandlers()', () => {
90+
it('should throw an error if the handler name contains an invalid character', () => {
91+
googleCommand.serverless.service.functions = {
92+
foo: {
93+
handler: 'invalid.handler',
94+
},
95+
bar: {
96+
handler: 'invalid/handler',
97+
},
98+
};
99+
100+
expect(() => googleCommand.validateHandlers()).toThrow(Error);
101+
});
102+
103+
it('should not throw an error if the function handler is valid', () => {
104+
googleCommand.serverless.service.functions = {
105+
foo: {
106+
handler: 'validHandler',
107+
},
108+
};
109+
110+
expect(() => googleCommand.validateHandlers()).not.toThrow(Error);
111+
});
112+
});
83113
});

0 commit comments

Comments
 (0)