serverless-easy-env
v1.1.0
Published
Simplifying stage and environment wise variables and values
Downloads
80
Maintainers
Readme
Serverless Easy Env
Simplifying stage and environment wise variables and values
Table of Contents
Installation
npm install serverless-easy-env -D
Quick Usage
The values that a variable should take on for each env or stage that you use can be specified under
custom.serverless-easy-env.envResolutions
.In addition to writing values directly you can also specify resolution or variable strings. They should be specified without the
${
and}
, so the plugin will only resolve them if they are referenced by the current env or stage otherwise they will remain as simple strings.- For example if all your variables for the env
local
useenv:
prefix (serverless environment variables) then even if variables for other stages usessm:
prefix they will not be resolved so you won't need aws credentials to be configured to run sls offline --stage local.
- For example if all your variables for the env
You can ask the easy env plugin for the current value of the env variable using the
${easyenv:variable-name}
syntaxThe current env to use to resolve env variables is fetched using the
sls:stage
variable which is defined by serverless as${opt:stage, self:provider.stage, "dev"}
(reference). You may override it usingcustom.serverless-easy-env.env
or capture groups that are covered in featuresIn addition to per env values for env variables, you can specify a
default
as well which increases convenience greatly. If an env specific value is not specified for some env variable then the default value is checked. If that is not found either then an error might be thrown
Sample usage for serverless.ts and serverless yaml follow, followed by the resolved sls file viewed by running sls print
Serverless ts
import type { AWS } from '@serverless/typescript';
const createServerlessConfiguration: () => Promise<AWS> = async () => {
return {
service: 'sample-service',
custom: {
'serverless-easy-env': {
envResolutions: {
apiKeys: {
prod: ['ssm:apiKeyOnSsm', 'ssm:apiKeyOnSsm2'],
default: ['env:API_KEY']
},
datadogEnabled: {
prod: true,
stg: true,
dev: false,
local: false,
},
someValueLikeSecurityGroups: {
local: ['random-name'],
default: ['ssm:abc', 'ssm:def']
},
},
},
},
provider: {
name: 'aws',
runtime: 'nodejs18.x',
apiGateway: {
apiKeys: '${easyenv:apiKeys}' as never,
},
vpc: {
securityGroupIds: '${easyenv:someValueLikeSecurityGroups}',
} as never,
},
plugins: [
'serverless-easy-env',
'serverless-offline',
],
package: {
patterns: ['!**/*', 'src/**/*', '.env.easy*'],
},
functions: {
main: {
handler: 'src/main.handler',
events: [
{
http: {
method: 'GET',
path: '/',
cors: true,
},
},
],
},
},
};
};
module.exports = createServerlessConfiguration();
Serverless yml
service: sample-service
custom:
serverless-easy-env:
envResolutions:
apiKeys:
prod:
- ssm:apiKeyOnSsm
- ssm:apiKeyOnSsm2
default:
- env:API_KEY
datadogEnabled:
prod: true
stg: true
dev: false
local: false
someValueLikeSecurityGroups:
local:
- random-name
default:
- ssm:abc
- ssm:def
provider:
name: aws
runtime: nodejs18.x
apiGateway:
apiKeys:
- ${easyenv:apiKeys}
vpc:
securityGroupIds: ${easyenv:someValueLikeSecurityGroups}
plugins:
- serverless-easy-env
- serverless-offline
package:
patterns:
- '!**/*'
- src/**/*
- .env.easy*
functions:
main:
handler: src/main.handler
events:
- http:
method: GET
path: /
cors: true
Resolved Serverless File
Running sls print --stage local
service: sample-service
custom:
serverless-easy-env:
envResolutions:
apiKeys:
prod:
- ssm:apiKeyOnSsm
- ssm:apiKeyOnSsm2
default:
- env:API_KEY
datadogEnabled:
prod: true
stg: true
dev: false
local: false
someValueLikeSecurityGroups:
local:
- random-name
default:
- ssm:abc
- ssm:def
provider:
name: aws
runtime: nodejs18.x
apiGateway:
apiKeys:
- some-api-key-that-exported-in-env
vpc:
securityGroupIds:
- random-name
stage: dev
region: us-east-1
versionFunctions: true
plugins:
- serverless-easy-env
- serverless-offline
package:
patterns:
- '!**/*'
- src/**/*
- .env.easy*
artifactsS3KeyDirname: serverless/sample-service/local/code-artifacts
functions:
main:
handler: src/main.handler
events:
- http:
method: GET
path: /
cors: true
name: sample-service-local-main
Features
Read Dot Env
By default the plugin will read the .env
file to supplement the env resolutions that are performed using the env:
prefix. It will look for a .env file in the same directory as from which the node process was started (which is usually the same as the directory of the serverless file or from which the serverless command in invoked).
You can disable this behavior using the
custom.serverless-easy-env.loadDotEnv
option which is true by default.The path to the env file can be explicitly specified via the
custom.serverless-easy-env.loadDotEnvFilePath
option. It is.env
by default and resolved against the directory mentioned before.
Deep Object and Array Resolution
Variable strings even when deeply nested will get resolved
In short,
envResolutions:
someEnvVariable:
prod:
someKey1:
- ssm:apiKeyOnSsm
- ssm:apiKeyOnSsm2
someKey2:
nestedKey2:
oneMoreNestedKey2:
- ssm:arrayElementOne
dev:
- env:SOME_ENV_VARIABLE
or
envResolutions: {
someEnvVariable: {
prod: {
someKey1: [
'ssm:apiKeyOnSsm',
'ssm:apiKeyOnSsm2',
],
someKey2: {
nestedKey2: {
oneMoreNestedKey2; ['ssm:arrayElementOne'],
},
},
},
default: ['env:SOME_ENV_VARIABLE']
},
}
will work.
Output Env File
This is useful if you have a lot of env variables that you want to become part of the lambda env variables and are not able to fit them into the 4 KB limit by AWS (reference). You can include the file in the lambda code package using
patterns:
- .env.easy*
and then load in the lambda or cloud function using, for example
import { config } from 'dotenv';
config({ path: '.env.easy'});
This file is generated during packaging and deployment using serverless hooks. It is also generated before start when using serverless offline start. You can also create it anytime using the serverless command sls write-env
.
By default the complete resolved values of all the variables in envResolutions are written to a
.env.easy
file. This file is created in the same folder from which the sls command is invoked or node process starts.You can turn of this behavior using
custom.serverless-easy-env.writeEnvFile: false
By default the file is written in a manner so that it can be read by dotenv, however, this means that if the resolved value of some variable as an object or array, it can get written weirdly. To avoid this you can change env file type to JSON
Env file type can be controlled using
custom.serverless-easy-env.envFileType
. The only two supported values arejson
anddotenv
. When json is selected, the default file name is going to be.env.easy.json
The file name of the env file can be controlled through
custom.serverless-easy-env.envFileName
and will override any default
Env Matchers
This feature is useful if you want to be flexible with your stage name but want them to be mapped onto certain envs that you specified in the envResolutions
. A case in point is when you want to deploy your stack under a different stage name like prod-v2
but want to reuse all env variables from ssm from prod
. The active env is then determined by first passing the value of ${sls:stage}
or custom.serverless-easy-env.env
through the regex patterns specified under custom.serverless-easy-env.envMatchers
. The first to match is taken as the active env, otherwise the value itself becomes the active env. The active env can always be fetched using ${easyenv:activeEnv}
.
The keys are the env names which should correspond to those under envResolutions
and their values are regex patterns in a string. The regex pattern is tested for a full match meaning that if you want capture all stages that start with local
(example: local-my-name
) under the env local
then a pattern of local.*
must be supplied. Just local
will not work.
envMatchers: {
local: 'local.*',
}
All Options Example
service: sample-service
custom:
serverless-easy-env:
writeEnvFile: true
envFileType: json
envFileName: .env.easy.generated.json
envResolutions:
apiKeys:
prod:
- ssm:apiKeyOnSsm
- ssm:apiKeyOnSsm2
default:
- env:API_KEY
datadogEnabled:
prod: true
stg: true
dev: false
local: false
someValueLikeSecurityGroups:
local:
- random-name
default:
- ssm:abc
- ssm:def
aSelfReference:
default: easyenv:datadogEnabled
envMatchers:
local: 'local.*'
loadDotEnv: true
loadDotEnvFilePath: .env.with-non-normal-path
provider:
name: aws
runtime: nodejs18.x
apiGateway:
apiKeys:
- ${easyenv:apiKeys}
vpc:
securityGroupIds: ${easyenv:someValueLikeSecurityGroups}
randomValue: ${easyenv:aSelfReference}
activeEnv: ${easyenv:activeEnv}
plugins:
- serverless-easy-env
- serverless-offline
package:
patterns:
- '!**/*'
- src/**/*
- .env.easy*
functions:
main:
handler: src/main.handler
events:
- http:
method: GET
path: /
cors: true