Plugin can extend the serverless.yml syntax with custom configuration:
service: app
provider:
name: aws
# ...
my-plugin:
my-plugin-config: fooTo do so, plugins must define schema validation (see below), and can retrieve configuration values via serverless.service:
class MyPlugin {
constructor(serverless) {
this.serverless = serverless;
this.hooks = {
'before:deploy': () => this.beforeDeploy(),
};
}
beforeDeploy() {
// `service` contains the (resolved) serverless.yml config
const service = this.serverless.service;
console.log('Provider name: ', service.provider.name);
console.log('Functions: ', service.functions);
console.log('Custom plugin config: ', service['my-plugin']['my-plugin-config']);
}
}
module.exports = MyPlugin;Note: configuration values are only resolved after plugins are initialized. Do not try to read configuration in the plugin constructor, as variables aren't resolved yet. Read configuration in lifecycle events only.
Any additional configuration defined by plugins in serverless.yml must come with validation rules.
Serverless Framework uses JSON schema validation backed by the AJV library. You can extend the base schema in plugins via:
defineTopLevelPropertydefineCustomPropertiesdefineFunctionEventdefineFunctionEventPropertiesdefineFunctionPropertiesdefineProvider
Use the following map to know which helper suits your needs:
custom:
my-plugin:
customProperty: foobar # <-- use defineCustomProperties
my-plugin: # <-- use defineTopLevelProperty
customProperty: foobar
provider:
name: new-provider # <-- use defineProvider
my-plugin:
customProperty: foobar
functions:
someFunc:
handler: handler.main
customProperty: foobar # <-- use defineFunctionProperties
events:
- yourPluginEvent: # <-- use defineFunctionEvent
customProperty: foobar
- http:
customProperty: foobar # <-- use defineFunctionEventPropertiesWe'll walk though those helpers. You may also want to check out examples from helpers tests
If your plugin requires additional top-level properties (like provider, custom, service...), you can use the defineTopLevelProperty helper to add their definition. For example:
# serverless.yml
service: my-service
myPlugin:
someProperty: foobarAdd validation for the myPlugin: section:
class MyPlugin {
constructor(serverless) {
// For reference on JSON schema, see https://github.com/ajv-validator/ajv
serverless.configSchemaHandler.defineTopLevelProperty('myPlugin', {
type: 'object',
properties: {
someProperty: { type: 'string' },
},
required: ['someProperty'],
});
}
}This way, if the user sets someProperty by mistake to false, the Framework would display an error:
Configuration error: yourPlugin.someProperty should be string
If your plugin depends on properties defined in the custom: section, you can use the defineCustomProperties helper. For example:
# serverless.yml
custom:
myCustomProperty: foobarAdd validation for the myCustomProperty property:
class MyPlugin {
constructor(serverless) {
// For reference on JSON schema, see https://github.com/ajv-validator/ajv
serverless.configSchemaHandler.defineCustomProperties({
type: 'object',
properties: {
myCustomProperty: { type: 'string' },
},
required: ['myCustomProperty'],
});
}
}This way, if the user sets myCustomProperty by mistake to false, the Framework would display an error:
Configuration error: custom.myCustomProperty should be string
If your plugin adds new properties to functions, you can use the defineFunctionProperties helper. For example:
# serverless.yml
functions:
foo:
handler: handler.main
someCustomProperty: my-property-valueAdd validation for the someCustomProperty property:
class MyPlugin {
constructor(serverless) {
// For reference on JSON schema, see https://github.com/ajv-validator/ajv
serverless.configSchemaHandler.defineFunctionProperties('providerName', {
properties: {
someCustomProperty: { type: 'string' },
anotherProperty: { type: 'number' },
},
required: ['someCustomProperty'],
});
}
}This way, if the user sets anotherProperty by mistake to hello, the Framework would display an error:
Configuration error at 'functions.foo.anotherProperty': should be number
If your plugin adds support to a new function event, you can use the defineFunctionEvent helper. For example:
# serverless.yml
functions:
someFunc:
handler: handler.main
events:
- myPluginEvent:
someProp: hello
anotherProp: 1Add validation for the myPluginEvent event:
class MyPlugin {
constructor(serverless) {
// For reference on JSON schema, see https://github.com/ajv-validator/ajv
serverless.configSchemaHandler.defineFunctionEvent('providerName', 'myPluginEvent', {
type: 'object',
properties: {
someProp: { type: 'string' },
anotherProp: { type: 'number' },
},
required: ['someProp'],
additionalProperties: false,
});
}
}This way, if the user sets anotherProp by mistake to some-string, the Framework would display an error:
Configuration error: functions.someFunc.events[0].myPluginEvent.anotherProp should be number
If your plugin adds new properties to a function event, you can use the defineFunctionEventProperties helper. For example:
# serverless.yml
functions:
foo:
handler: handler.main
events:
- http:
path: '/quote'
method: GET
documentation: Get a quoteIn the example above, the plugin adds a new documentation property on http events for aws. To validate that properties:
class MyPlugin {
constructor(serverless) {
// For reference on JSON schema, see https://github.com/ajv-validator/ajv
serverless.configSchemaHandler.defineFunctionEventProperties('aws', 'http', {
properties: {
documentation: { type: 'string' },
},
required: ['documentation'],
});
}
}This way, if the user sets documentation by mistake to false, the Framework would display an error:
Configuration error: functions.foo.events[0].http.documentation should be a string
If your plugin provides support for a new provider, register it via defineProvider:
class MyPlugin {
constructor(serverless) {
// For reference on JSON schema, see https://github.com/ajv-validator/ajv
serverless.configSchemaHandler.defineProvider('newProvider', {
// Eventual reusable schema definitions (will be put to top level "definitions" object)
definitions: {
// ...
},
// Top level "provider" properties
provider: {
properties: {
stage: { type: 'string' },
remoteFunctionData: { type: 'null' },
},
},
// Function level properties
function: {
properties: { handler: { type: 'string' } },
},
// Function events definitions (can be defined here or via `defineFunctionEvent` helper)
functionEvents: {
someEvent: {
name: 'someEvent',
schema: {
type: 'object',
properties: {
someRequiredStringProp: { type: 'string' },
someNumberProp: { type: 'number' },
},
required: ['someRequiredStringProp'],
additionalProperties: false,
},
},
},
// Definition for eventual top level "resources" section
resources: {
type: 'object',
properties: {
// ...
},
},
// Definition for eventual top level "layers" section
layers: {
type: 'object',
additionalProperties: {
type: 'object',
properties: {
// ...
},
},
},
});
}
}