Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 12 additions & 10 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
root = true

[*]
indent_style = space
end_of_line = lf

[*.{js,jsx}]
indent_style = space
end_of_line = lf
charset = utf-8
root = true

[*]
indent_style = space
indent_size = 2
end_of_line = lf

[*.{js,jsx}]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -453,6 +453,14 @@ Plugin commands are supported by the following providers. ⁇ indicates that com
| invoke local | ✔︎ | ✔︎ | ⁇ | ⁇ |
| invoke local --watch | ✔︎ | ✔︎ | ⁇ | ⁇ |

## Plugin support

The following serverless plugins are explicitly supported with `serverless-webpack`

| Plugin | NPM |
|-----------------------------------|-----|
| serverless-step-functions-offline | [![NPM][ico-step-functions-offline]][link-step-functions-offline] |

## For developers

The plugin exposes a complete lifecycle model that can be hooked by other plugins to extend
Expand Down Expand Up @@ -602,6 +610,8 @@ plugin when running a command or invoked by a hook.
[link-examples]: ./examples
[link-serverless-offline]: https://www.npmjs.com/package/serverless-offline
[link-serverless-dynamodb-local]: https://www.npmjs.com/package/serverless-dynamodb-local
[link-step-functions-offline]: https://www.npmjs.com/package/serverless-step-functions-offline
[ico-step-functions-offline]: https://img.shields.io/npm/v/serverless-step-functions-offline.svg

[comment]: # (Referenced issues)

Expand Down
7 changes: 6 additions & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const run = require('./lib/run');
const prepareLocalInvoke = require('./lib/prepareLocalInvoke');
const runPluginSupport = require('./lib/runPluginSupport');
const prepareOfflineInvoke = require('./lib/prepareOfflineInvoke');
const prepareStepOfflineInvoke = require('./lib/prepareStepOfflineInvoke');
const packExternalModules = require('./lib/packExternalModules');
const packageModules = require('./lib/packageModules');
const lib = require('./lib');
Expand Down Expand Up @@ -44,7 +45,8 @@ class ServerlessWebpack {
packageModules,
prepareLocalInvoke,
runPluginSupport,
prepareOfflineInvoke
prepareOfflineInvoke,
prepareStepOfflineInvoke
);

this.commands = {
Expand Down Expand Up @@ -153,6 +155,9 @@ class ServerlessWebpack {
.then(this.prepareOfflineInvoke)
.then(this.wpwatch),

'before:step-functions-offline:start': () => BbPromise.bind(this)
.then(this.prepareStepOfflineInvoke)
.then(this.compile)
};
}
}
Expand Down
24 changes: 24 additions & 0 deletions lib/prepareStepOfflineInvoke.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
'use strict';

const _ = require('lodash');
const path = require('path');

/**
* Special settings for use with serverless-step-functions-offline.
*/

module.exports = {
prepareStepOfflineInvoke() {
_.set(this.serverless, 'service.package.individually', false);

return this.serverless.pluginManager.spawn('webpack:validate')
.then(() => {
if (!this.options.location && !_.get(this.serverless, 'service.custom.stepFunctionsOffline.location')) {
_.set(this.serverless, 'service.custom.stepFunctionsOffline.location',
path.relative(this.serverless.config.servicePath, path.join(this.webpackOutputPath, 'service'))
);
}
return null;
});
}
};
1 change: 1 addition & 0 deletions tests/all.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ describe('serverless-webpack', () => {
require('./cleanup.test');
require('./wpwatch.test');
require('./runPluginSupport.test');
require('./prepareStepOfflineInvoke.test');
});
132 changes: 132 additions & 0 deletions tests/prepareStepOfflineInvoke.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
'use strict';

const _ = require('lodash');
const BbPromise = require('bluebird');
const chai = require('chai');
const sinon = require('sinon');
const Serverless = require('serverless');

chai.use(require('chai-as-promised'));
chai.use(require('sinon-chai'));

const expect = chai.expect;

describe('prepareStepOfflineInvoke', () => {
let serverless;
let baseModule;
let module;
let sandbox;

before(() => {
sandbox = sinon.createSandbox();
sandbox.usingPromise(BbPromise.Promise);

baseModule = require('../lib/prepareStepOfflineInvoke');
Object.freeze(baseModule);
});

beforeEach(() => {
serverless = new Serverless();
serverless.cli = {
log: sandbox.stub()
};
sandbox.stub(serverless.pluginManager, 'spawn');
module = _.assign({
serverless,
options: {},
}, baseModule);
});

afterEach(() => {
sandbox.restore();
});

it('should set service packaging explicitly', () => {
serverless.pluginManager.spawn.resolves();
serverless.config.servicePath = 'myPath';
module.webpackOutputPath = '.';
module.serverless.service.package = {};

return expect(module.prepareStepOfflineInvoke()).to.be.fulfilled
.then(() => {
expect(module.serverless.service.package).to.have.a.property('individually').that.is.false;
return null;
});
});

it('should switch to service packaging', () => {
serverless.pluginManager.spawn.resolves();
serverless.config.servicePath = 'myPath';
module.webpackOutputPath = '.';
module.serverless.service.package = {
individually: true
};

return expect(module.prepareStepOfflineInvoke()).to.be.fulfilled
.then(() => {
expect(module.serverless.service.package).to.have.a.property('individually').that.is.false;
return null;
});
});

it('should spawn webpack:validate', () => {
serverless.pluginManager.spawn.resolves();
serverless.config.servicePath = 'myPath';
module.webpackOutputPath = '.';

return expect(module.prepareStepOfflineInvoke()).to.be.fulfilled
.then(() => {
expect(serverless.pluginManager.spawn).to.have.been.calledOnce;
expect(serverless.pluginManager.spawn).to.have.been.calledWithExactly('webpack:validate');
return null;
});
});

it('should reject if spawn rejects', () => {
serverless.pluginManager.spawn.returns(BbPromise.reject(new Error('spawn failed')));
serverless.config.servicePath = 'myPath';
module.webpackOutputPath = '.';

return expect(module.prepareStepOfflineInvoke()).to.be.rejectedWith('spawn failed');
});

it('should set location if not given by user', () => {
serverless.pluginManager.spawn.resolves();
serverless.config.servicePath = '.';
module.webpackOutputPath = '.';

return expect(module.prepareStepOfflineInvoke()).to.be.fulfilled
.then(() => {
expect(serverless.service).to.have.a.nested.property('custom.stepFunctionsOffline.location', 'service');
return null;
});
});

it('should keep location if set in service config', () => {
serverless.pluginManager.spawn.resolves();
serverless.config.servicePath = '.';
module.webpackOutputPath = '.';
_.set(module.serverless, 'service.custom.stepFunctionsOffline.location', 'myLocation');

return expect(module.prepareStepOfflineInvoke()).to.be.fulfilled
.then(() => {
expect(serverless.service).to.have.a.nested.property('custom.stepFunctionsOffline.location', 'myLocation');
return null;
});
});

it('should keep location if set in options', () => {
serverless.pluginManager.spawn.resolves();
serverless.config.servicePath = '.';
module.webpackOutputPath = '.';
module.options = {
location: 'myLocation'
};

return expect(module.prepareStepOfflineInvoke()).to.be.fulfilled
.then(() => {
expect(serverless.service).to.not.have.a.nested.property('custom.stepFunctionsOffline.location');
return null;
});
});
});