@serverless-devs/s-framework
Version:
Serverless Devs Tool Framework Component For Alibaba Cloud
277 lines • 16 kB
JavaScript
;
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
Object.defineProperty(exports, "__esModule", { value: true });
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
var s_core_1 = require("@serverless-devs/s-core");
var static_1 = require("./static");
var fse = require('fs-extra');
var path = require('path');
var REGION = static_1.DEFAULT.REGION, SERVICE = static_1.DEFAULT.SERVICE, FUNCTION = static_1.DEFAULT.FUNCTION, TRIGGERS = static_1.DEFAULT.TRIGGERS, DOMAINS = static_1.DEFAULT.DOMAINS;
var Framework = /** @class */ (function (_super) {
__extends(Framework, _super);
function Framework(id) {
return _super.call(this, id) || this;
}
Framework.prototype.deploy = function (inputs) {
return __awaiter(this, void 0, void 0, function () {
var logger, fc, Project, Credentials, Properties, inputService, inputFunction, Service, Function, region, needNewDomains, triggerUserConfigState, state, autoDomain, outputDomains, outputTriggers, triggerIndex, tempDomains, domains, domainIndex, output;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
logger = new s_core_1.Log();
logger.log('Start deploying framework ...');
return [4 /*yield*/, this.load('fc', 'Component')];
case 1:
fc = _a.sent();
Project = inputs.Project, Credentials = inputs.Credentials, Properties = inputs.Properties;
inputService = inputs.Properties.Detail ? inputs.Properties.Detail.Service || {} : {};
inputFunction = inputs.Properties.Detail ? inputs.Properties.Detail.Function || {} : {};
Service = Object.assign(SERVICE, fc.state.Service || {}, inputService || {});
Function = Object.assign(FUNCTION, fc.state.Function || {}, inputFunction || {});
region = Properties.Region || REGION;
needNewDomains = false;
if ((region !== fc.state.Region) || (inputFunction.Name && fc.state.Function.Name !== inputFunction.Name) || (inputService.Name && fc.state.Service.Name !== inputService.Name)) {
needNewDomains = true;
}
if (inputs.Properties.Log) {
Service.Log = inputs.Properties.Log;
}
if (inputs.Properties.Environment) {
Function.Environment = inputs.Properties.Environment;
}
if (inputs.Properties.Domains && inputFunction.Triggers) {
/**
* 如果Domains和Triggers同时出现:
* 1. 系统没办法正确对应起关系
* 2. 系统没办法做进一步的同步变更
* 3. 逻辑将会变得混乱无比
* 所以出现这样的情况,理论是需要提醒并且退出操作!
*/
throw new Error('Properties.Domains and Properties.Detail.Function.Triggers cannot be set at the same time.');
}
triggerUserConfigState = inputFunction.Triggers ? true : false;
Function.Triggers = this.getTriggers(inputs.Properties.Domains, Function.Triggers, fc.state.Domains, needNewDomains);
Function.CodeUri = inputs.Properties.CodeUri || './';
logger.log('Bootstrap processing ...');
if (!!(inputs.Bootstrap.NoBootstrap && inputs.Bootstrap.NoBootstrap === true)) return [3 /*break*/, 3];
return [4 /*yield*/, this.handlerStartConfig(Function.CodeUri, inputs.Bootstrap.Content, inputs.Bootstrap.IsConfig)];
case 2:
_a.sent();
_a.label = 3;
case 3: return [4 /*yield*/, fc.deploy({
Args: inputs.Args,
State: fc.state,
Credentials: Credentials,
Project: Project,
Properties: {
Region: Properties.Region || REGION,
Function: Function,
Service: Service
}
})];
case 4:
state = _a.sent();
outputDomains = [];
outputTriggers = {};
for (triggerIndex = 0; triggerIndex < state.Triggers.length; triggerIndex++) {
tempDomains = state.Triggers[triggerIndex].Domains || [];
domains = typeof tempDomains === 'string' ? [tempDomains] : tempDomains;
for (domainIndex = 0; domainIndex < domains.length; domainIndex++) {
if (domains[domainIndex].endsWith('.test.functioncompute.com')) {
autoDomain = domains[domainIndex];
}
if (triggerUserConfigState) {
outputTriggers[state.Triggers[triggerIndex]['Name']] = {
'Protocols': state.Triggers[triggerIndex]['Type'],
'Domains': state.Triggers[triggerIndex]['Domains']
};
}
else {
outputDomains.push(domains[domainIndex]);
}
}
}
fc.state = { Function: Function, Service: Service, Domains: autoDomain, Region: Properties.Region || REGION };
return [4 /*yield*/, fc.save()];
case 5:
_a.sent();
output = {
Region: Properties.Region || REGION,
Service: state.Service,
Function: state.Function
};
if (triggerUserConfigState) {
output['Triggers'] = outputTriggers;
}
else {
output['Domains'] = outputDomains.length === 1 ? outputDomains[0] : outputDomains;
}
logger.log('Framework deployment completed.');
return [2 /*return*/, output];
}
});
});
};
Framework.prototype.remove = function (inputs) {
return __awaiter(this, void 0, void 0, function () {
var fc, Project, Credentials, Properties;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this.load('fc', 'Component')];
case 1:
fc = _a.sent();
Project = inputs.Project, Credentials = inputs.Credentials, Properties = inputs.Properties;
if (!Properties.Detail) {
Properties.Detail = {};
}
Properties.Detail.Region = Properties.Region;
Properties.Detail.Service = Object.assign(SERVICE, fc.state.Service || {}, Properties.Detail.Service || {});
Properties.Detail.Function = Object.assign(FUNCTION, fc.state.Function || {}, Properties.Detail.Function || {});
return [4 /*yield*/, fc.remove({
Project: Project,
Credentials: Credentials,
Properties: Properties.Detail,
State: fc.state,
Args: ''
})];
case 2:
_a.sent();
fc.state = {};
return [4 /*yield*/, fc.save()];
case 3:
_a.sent();
return [2 /*return*/];
}
});
});
};
Framework.prototype.handlerStartConfig = function (codeUri, bootstrapConfig, isConfig) {
return __awaiter(this, void 0, void 0, function () {
var bootstrapPath;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, fse.lstatSync(codeUri).isDirectory()];
case 1:
// 如果是文件,则不操作
if (!(_a.sent())) {
return [2 /*return*/];
}
bootstrapPath = path.resolve(codeUri + "/bootstrap");
return [4 /*yield*/, fse.pathExists(bootstrapPath)];
case 2:
// 如果bootstrap已经存在,并且startConfig不存在,则不进行操作
if ((_a.sent()) && !isConfig) {
return [2 /*return*/];
}
// 将bootstrap写入到项目
// await fse.writeFile(bootstrapPath, `#!/usr/bin/env bash\n\nexport PORT=9000\nnpx hexo server -p $PORT -s`);
return [4 /*yield*/, fse.writeFile(bootstrapPath, bootstrapConfig, { mode: '777', encoding: 'utf8' })];
case 3:
// 将bootstrap写入到项目
// await fse.writeFile(bootstrapPath, `#!/usr/bin/env bash\n\nexport PORT=9000\nnpx hexo server -p $PORT -s`);
_a.sent();
return [2 /*return*/];
}
});
});
};
Framework.prototype.getTriggers = function (propertiesDomains, functionTriggers, stateDomains, state) {
/**
* 1. 如果有下面有Triggers,则上面的自定义域名失效
* 原因是,系统没办法判断用户到底需要使用那个Trigger对应上面的自定义域名
* 2. 如果配置了自定义域名,那么就用用户配置的,如果没有配置,则使用系统生成的
* 3. 为了防止系统生成的域名变化,此处应该额外记录上次的域名状态
*
* todo: 域名状态与域名变更,这一部分是蛮重要的,在后期需要添加
* todo: 域名绑定是可以指定版本的,这一步骤,理论已经是默认支持的了,但是需要验证
*/
// 准备默认triggers
var tempTrigger = TRIGGERS;
var tempDomainsDefault = DOMAINS;
if (stateDomains) {
tempDomainsDefault[0].Domain = stateDomains;
}
tempTrigger[0].Parameters.Domains = propertiesDomains || tempDomainsDefault;
// 对functionTriggers进行检测,检测多个auto,返回报错
var autoCount = 0;
if (functionTriggers) {
for (var i = 0; i < functionTriggers.length; i++) {
/**
* 默认为HTTP触发器
* todo: 未来可以考虑支持更多
*/
functionTriggers[i].Type = 'HTTP';
var tempDomains = functionTriggers[i].Parameters.Domains || [];
for (var j = 0; j < tempDomains.length; j++) {
if (tempDomains[j].Domain == stateDomains && state) {
functionTriggers[i].Parameters.Domains[j].Domain = 'Auto';
}
if (String(tempDomains[j].Domain).toLowerCase() === 'auto' && !state) {
autoCount = autoCount + 1;
functionTriggers[i].Parameters.Domains[j].Domain = stateDomains;
}
else if (tempDomains[j].Domain && tempDomains[j].Domain.endsWith('.test.functioncompute.com')) {
autoCount = autoCount + 1;
}
if (autoCount === 2) {
throw new Error('Each function can only get one assigned domain name.');
}
}
}
return functionTriggers;
}
return tempTrigger;
};
return Framework;
}(s_core_1.Component));
module.exports = Framework;
//# sourceMappingURL=index.js.map