serverless-plugin-static-env
Version:
Replace environment variables with static strings before deployment. It is for Lambda @ Edge.
94 lines (93 loc) • 4.06 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
const fs_1 = __importDefault(require("fs"));
const util_1 = require("util");
const copyFile = util_1.promisify(fs_1.default.copyFile);
const readFile = util_1.promisify(fs_1.default.readFile);
const writeFile = util_1.promisify(fs_1.default.writeFile);
const unlink = util_1.promisify(fs_1.default.unlink);
const toStringEnvironment = (env) => env
? Object.fromEntries(Object.entries(env).map(([key, val]) => [key, String(val)]))
: {};
const getHandlerBaseFilePath = (func) => func.handler.substring(0, func.handler.lastIndexOf('.'));
const getHandlerFilePath = (func) => `${getHandlerBaseFilePath(func)}.js`;
const getEnvFilePath = (func) => `${getHandlerBaseFilePath(func)}-env.js`;
const getEnvFileRequire = (func) => {
const baseFilePath = getHandlerBaseFilePath(func);
const lastSlash = baseFilePath.lastIndexOf('/');
const baseName = lastSlash === -1 ? baseFilePath : baseFilePath.substring(lastSlash + 1);
return `./${baseName}-env`;
};
const shouldAddStaticEnv = (func) => {
var _a;
if (func.includeStaticEnv != null)
return func.includeStaticEnv;
const cloudFrontEvent = (_a = func.events) === null || _a === void 0 ? void 0 : _a.find((event) => event.cloudFront != null);
return cloudFrontEvent != null;
};
const buildEnvFile = (env) => Object.entries(env)
.map(([key, value]) => [
`process.env[${JSON.stringify(key)}]`,
JSON.stringify(value),
])
.map(([key, value]) => `${key} = ${key} == null ? ${value}: ${key};`)
.reduce((buff, line) => buff + line + '\n', '');
class ServerlessPlugin {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
constructor(serverless, options) {
this.serverless = serverless;
// this.options = options;
this.hooks = {
'package:initialize': this.beforeBuild.bind(this),
'package:finalize': this.afterBuild.bind(this),
};
}
_filesToBackup() {
return Object.values(this.serverless.service.functions)
.map((func) => shouldAddStaticEnv(func) ? [getHandlerFilePath(func)] : [])
.reduce((acc, files) => acc.concat(...files), []);
}
async _backupFiles() {
await Promise.all(this._filesToBackup().map(async (file) => {
await copyFile(`${file}`, `${file}.org`);
}));
}
async _restoreBackups() {
await Promise.all(this._filesToBackup().map(async (file) => {
copyFile(`${file}.org`, file);
unlink(`${file}.org`);
}));
}
async _deleteEnvFiles() {
await Promise.all(Object.values(this.serverless.service.functions)
.map((func) => (shouldAddStaticEnv(func) ? [getEnvFilePath(func)] : []))
.reduce((acc, files) => acc.concat(...files), [])
.map(async (file) => {
unlink(file);
}));
}
async beforeBuild() {
await this._backupFiles();
const serviceEnvironment = toStringEnvironment(this.serverless.service.provider.environment);
await Promise.all(Object.values(this.serverless.service.functions).map(async (func) => {
if (shouldAddStaticEnv(func)) {
const functionEnvironment = {
...serviceEnvironment,
...toStringEnvironment(func.environment),
};
const envFile = getEnvFilePath(func);
await writeFile(envFile, buildEnvFile(functionEnvironment), 'utf8');
const handlerPath = getHandlerFilePath(func);
const handlerSource = await readFile(handlerPath, 'utf8');
await writeFile(handlerPath, `require(${JSON.stringify(getEnvFileRequire(func))});\n${handlerSource}`, 'utf8');
}
}));
}
async afterBuild() {
await this._restoreBackups();
await this._deleteEnvFiles();
}
}
module.exports = ServerlessPlugin;