@fly/edge
Version:
Fly's TypeScript Edge
104 lines • 13.3 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.buildAppFromConfig = exports.buildCdn = exports.isCdnConfig = exports.isItemConfig = exports.AppConfigKey = void 0;
/** @module Config */
const backends_1 = require("./backends");
const util_1 = require("../util");
const rules_1 = require("./rules");
const middleware_1 = require("./middleware");
exports.AppConfigKey = "flyEdge";
function isItemConfig(input) {
if (!util_1.isObject(input)) {
throw new Error("must be an object");
}
if (typeof input.type !== "string" || input.type.length == 0) {
throw new Error("must have a type property specifying a backend");
}
return true;
}
exports.isItemConfig = isItemConfig;
function isCdnConfig(input) {
if (!util_1.isObject(input)) {
throw new Error("config must be an object");
}
const { backendConfigs = {}, ruleConfigs = [], middlewareConfigs = [] } = input;
if (!util_1.isObject(backendConfigs)) {
throw new Error("backends property must be a map of keys -> Backend definition");
}
for (const [key, cfg] of Object.entries(backendConfigs)) {
try {
if (isItemConfig(cfg)) {
backends_1.validateBackend(cfg);
}
}
catch (error) {
throw new Error(`backend config for ${key} is invalid: ${error.message || error}`);
}
}
if (!(ruleConfigs instanceof Array)) {
throw new Error("rules property must be an array of Rule definitions");
}
for (const [idx, cfg] of ruleConfigs.entries()) {
try {
rules_1.validateRule(cfg);
}
catch (error) {
throw new Error(`rule at index ${idx} is invalid: ${error.message || error}`);
}
}
if (!(middlewareConfigs instanceof Array)) {
throw new Error("middleware property must be an array of Middleware definitions");
}
for (const [idx, cfg] of middlewareConfigs.entries()) {
try {
if (isItemConfig(cfg)) {
middleware_1.validateMiddleware(cfg);
}
}
catch (error) {
throw new Error(`middleware at index ${idx} is invalid: ${error.message || error}`);
}
}
return true;
}
exports.isCdnConfig = isCdnConfig;
function buildCdn(config) {
const backends = new Map();
for (const [key, cfg] of Object.entries(config.backends)) {
const b = backends_1.buildBackend(cfg);
backends.set(key, b);
}
console.log("Built backends:", Object.getOwnPropertyNames(config.backends));
let fn = rules_1.buildRules(backends, config.rules);
const middleware = config.middleware;
if (middleware && middleware.length > 0) {
for (let i = middleware.length - 1; i >= 0; i--) {
fn = middleware_1.buildMiddleware(fn, middleware[i]);
}
}
return Object.assign(fn, {
backends: backends
});
}
exports.buildCdn = buildCdn;
function buildAppFromConfig(c) {
try {
const config = c || app.config[exports.AppConfigKey] || app.config['flyCDN']; // support flyCDN config key for a while
if (!config) {
throw new Error("flyApp config property not found");
}
if (!isCdnConfig(config)) {
// This is unreachable because isCdnConfig throws but typescript can't infer that so we throw too
throw new Error("App config not supported");
}
return buildCdn(config);
}
catch (error) {
const fn = (...args) => {
return Promise.resolve(new Response(`Invalid App Config: ${error.message || error}`));
};
return Object.assign(fn, { backends: new Map() });
}
}
exports.buildAppFromConfig = buildAppFromConfig;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvY29uZmlnL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLHFCQUFxQjtBQUNyQix5Q0FBMkQ7QUFDM0Qsa0NBQW1DO0FBR25DLG1DQUE2RDtBQUM3RCw2Q0FBbUU7QUFHdEQsUUFBQSxZQUFZLEdBQUcsU0FBUyxDQUFDO0FBZXRDLFNBQWdCLFlBQVksQ0FBQyxLQUFjO0lBQ3pDLElBQUksQ0FBQyxlQUFRLENBQUMsS0FBSyxDQUFDLEVBQUU7UUFDcEIsTUFBTSxJQUFJLEtBQUssQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDO0tBQ3RDO0lBRUQsSUFBSSxPQUFPLEtBQUssQ0FBQyxJQUFJLEtBQUssUUFBUSxJQUFJLEtBQUssQ0FBQyxJQUFJLENBQUMsTUFBTSxJQUFJLENBQUMsRUFBRTtRQUM1RCxNQUFNLElBQUksS0FBSyxDQUFDLGdEQUFnRCxDQUFDLENBQUM7S0FDbkU7SUFFRCxPQUFPLElBQUksQ0FBQTtBQUNiLENBQUM7QUFWRCxvQ0FVQztBQUVELFNBQWdCLFdBQVcsQ0FBQyxLQUFjO0lBQ3hDLElBQUksQ0FBQyxlQUFRLENBQUMsS0FBSyxDQUFDLEVBQUU7UUFDcEIsTUFBTSxJQUFJLEtBQUssQ0FBQywwQkFBMEIsQ0FBQyxDQUFBO0tBQzVDO0lBRUQsTUFBTSxFQUFFLGNBQWMsR0FBRyxFQUFHLEVBQUUsV0FBVyxHQUFHLEVBQUUsRUFBRSxpQkFBaUIsR0FBRyxFQUFFLEVBQUUsR0FBRyxLQUFLLENBQUM7SUFFakYsSUFBSSxDQUFDLGVBQVEsQ0FBQyxjQUFjLENBQUMsRUFBRTtRQUM3QixNQUFNLElBQUksS0FBSyxDQUFDLCtEQUErRCxDQUFDLENBQUM7S0FDbEY7SUFFRCxLQUFLLE1BQU0sQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLElBQUksTUFBTSxDQUFDLE9BQU8sQ0FBQyxjQUFjLENBQUMsRUFBRTtRQUN2RCxJQUFJO1lBQ0YsSUFB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b0JBQVksQ0FBQyxJQUFJLEdBQUcsQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyx3Q0FBd0M7UUFDOUcsSUFBSSxDQUFDLE1BQU0sRUFBRTtZQUNYLE1BQU0sSUFBSSxLQUFLLENBQUMsa0NBQWtDLENBQUMsQ0FBQztTQUNyRDtRQUNELElBQUksQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFDLEVBQUU7WUFDeEIsaUdBQWlHO1lBQ2pHLE1BQU0sSUFBSSxLQUFLLENBQUMsMEJBQTBCLENBQUMsQ0FBQztTQUM3QztRQUNELE9BQU8sUUFBUSxDQUFDLE1BQU0sQ0FBQyxDQUFBO0tBQ3hCO0lBQUMsT0FBTyxLQUFLLEVBQUU7UUFDZCxNQUFNLEVBQUUsR0FBRyxDQUFDLEdBQUcsSUFBVyxFQUFFLEVBQUU7WUFDNUIsT0FBTyxPQUFPLENBQUMsT0FBTyxDQUFDLElBQUksUUFBUSxDQUFDLHVCQUF1QixLQUFLLENBQUMsT0FBTyxJQUFJLEtBQUssRUFBRSxDQUFDLENBQUMsQ0FBQztRQUN4RixDQUFDLENBQUE7UUFDRCxPQUFPLE1BQU0sQ0FBQyxNQUFNLENBQUMsRUFBRSxFQUFFLEVBQUUsUUFBUSxFQUFFLElBQUksR0FBRyxFQUF5QixFQUFDLENBQUMsQ0FBQTtLQUN4RTtBQUNILENBQUM7QUFqQkQsZ0RBaUJDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqIEBtb2R1bGUgQ29uZmlnICovXG5pbXBvcnQgeyB2YWxpZGF0ZUJhY2tlbmQsIGJ1aWxkQmFja2VuZCB9IGZyb20gXCIuL2JhY2tlbmRzXCI7XG5pbXBvcnQgeyBpc09iamVjdCB9IGZyb20gXCIuLi91dGlsXCI7XG5pbXBvcnQgeyBGZXRjaEZ1bmN0aW9uIH0gZnJvbSBcIi4uL2ZldGNoXCI7XG5pbXBvcnQgeyBQcm94eUZ1bmN0aW9uIH0gZnJvbSBcIi4uL3Byb3h5XCI7XG5pbXBvcnQgeyBSdWxlSW5mbywgdmFsaWRhdGVSdWxlLCBidWlsZFJ1bGVzIH0gZnJvbSBcIi4vcnVsZXNcIjtcbmltcG9ydCB7IGJ1aWxkTWlkZGxld2FyZSwgdmFsaWRhdGVNaWRkbGV3YXJlIH0gZnJvbSBcIi4vbWlkZGxld2FyZVwiO1xuaW1wb3J0IHsgc3RyaW5naWZ5IH0gZnJvbSBcInF1ZXJ5c3RyaW5nXCI7XG5cbmV4cG9ydCBjb25zdCBBcHBDb25maWdLZXkgPSBcImZseUVkZ2VcIjtcblxuZXhwb3J0IGludGVyZmFjZSBDZG5Db25maWcge1xuICBiYWNrZW5kczogeyBba2V5OiBzdHJpbmddOiBJdGVtQ29uZmlnIH0sXG4gIG1pZGRsZXdhcmU6IEl0ZW1Db25maWdbXSxcbiAgcnVsZXM6IFJ1bGVJbmZvW11cbn1cblxuZXhwb3J0IGludGVyZmFjZSBJdGVtQ29uZmlnIHtcbiAgdHlwZTogc3RyaW5nO1xuICBbcHJvcDogc3RyaW5nXTogdW5rbm93bjtcbn1cblxuZXhwb3J0IHR5cGUgQmFja2VuZFByb3hpZXMgPSBNYXA8c3RyaW5nLCBQcm94eUZ1bmN0aW9uPjtcblxuZXhwb3J0IGZ1bmN0aW9uIGlzSXRlbUNvbmZpZyhpbnB1dDogdW5rbm93bik6IGlucHV0IGlzIEl0ZW1Db25maWcge1xuICBpZiAoIWlzT2JqZWN0KGlucHV0KSkge1xuICAgIHRocm93IG5ldyBFcnJvcihcIm11c3QgYmUgYW4gb2JqZWN0XCIpO1xuICB9XG5cbiAgaWYgKHR5cGVvZiBpbnB1dC50eXBlICE9PSBcInN0cmluZ1wiIHx8IGlucHV0LnR5cGUubGVuZ3RoID09IDApIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJtdXN0IGhhdmUgYSB0eXBlIHByb3BlcnR5IHNwZWNpZnlpbmcgYSBiYWNrZW5kXCIpO1xuICB9XG5cbiAgcmV0dXJuIHRydWVcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGlzQ2RuQ29uZmlnKGlucHV0OiB1bmtub3duKTogaW5wdXQgaXMgQ2RuQ29uZmlnIHtcbiAgaWYgKCFpc09iamVjdChpbnB1dCkpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJjb25maWcgbXVzdCBiZSBhbiBvYmplY3RcIilcbiAgfVxuXG4gIGNvbnN0IHsgYmFja2VuZENvbmZpZ3MgPSB7IH0sIHJ1bGVDb25maWdzID0gW10sIG1pZGRsZXdhcmVDb25maWdzID0gW10gfSA9IGlucHV0O1xuXG4gIGlmICghaXNPYmplY3QoYmFja2VuZENvbmZpZ3MpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFwiYmFja2VuZHMgcHJvcGVydHkgbXVzdCBiZSBhIG1hcCBvZiBrZXlzIC0+IEJhY2tlbmQgZGVmaW5pdGlvblwiKTtcbiAgfVxuXG4gIGZvciAoY29uc3QgW2tleSwgY2ZnXSBvZiBPYmplY3QuZW50cmllcyhiYWNrZW5kQ29uZmlncykpIHtcbiAgICB0cnkge1xuICAgICAgaWYgKGlzSXRlbUNvbmZpZyhjZmcpKSB7XG4gICAgICAgIHZhbGlkYXRlQmFja2VuZChjZmcpO1xuICAgICAgfVxuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYGJhY2tlbmQgY29uZmlnIGZvciAke2tleX0gaXMgaW52YWxpZDogJHtlcnJvci5tZXNzYWdlIHx8IGVycm9yfWApXG4gICAgfVxuICB9XG5cbiAgaWYgKCEocnVsZUNvbmZpZ3MgaW5zdGFuY2VvZiBBcnJheSkpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJydWxlcyBwcm9wZXJ0eSBtdXN0IGJlIGFuIGFycmF5IG9mIFJ1bGUgZGVmaW5pdGlvbnNcIik7XG4gIH1cblxuICBmb3IgKGNvbnN0IFtpZHgsIGNmZ10gb2YgcnVsZUNvbmZpZ3MuZW50cmllcygpKSB7XG4gICAgdHJ5IHtcbiAgICAgIHZhbGlkYXRlUnVsZShjZmcpXG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgcnVsZSBhdCBpbmRleCAke2lkeH0gaXMgaW52YWxpZDogJHtlcnJvci5tZXNzYWdlIHx8IGVycm9yfWApXG4gICAgfVxuICB9XG5cbiAgaWYgKCEobWlkZGxld2FyZUNvbmZpZ3MgaW5zdGFuY2VvZiBBcnJheSkpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJtaWRkbGV3YXJlIHByb3BlcnR5IG11c3QgYmUgYW4gYXJyYXkgb2YgTWlkZGxld2FyZSBkZWZpbml0aW9uc1wiKTtcbiAgfVxuXG4gIGZvciAoY29uc3QgW2lkeCwgY2ZnXSBvZiBtaWRkbGV3YXJlQ29uZmlncy5lbnRyaWVzKCkpIHtcbiAgICB0cnkge1xuICAgICAgaWYgKGlzSXRlbUNvbmZpZyhjZmcpKSB7XG4gICAgICAgIHZhbGlkYXRlTWlkZGxld2FyZShjZmcpO1xuICAgICAgfVxuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYG1pZGRsZXdhcmUgYXQgaW5kZXggJHtpZHh9IGlzIGludmFsaWQ6ICR7ZXJyb3IubWVzc2FnZSB8fCBlcnJvcn1gKVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiB0cnVlO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gYnVpbGRDZG4oY29uZmlnOiBDZG5Db25maWcpIHtcbiAgY29uc3QgYmFja2VuZHMgPSBuZXcgTWFwPHN0cmluZywgUHJveHlGdW5jdGlvbj4oKTtcblxuICBmb3IgKGNvbnN0IFtrZXksIGNmZ10gb2YgT2JqZWN0LmVudHJpZXMoY29uZmlnLmJhY2tlbmRzKSkge1xuICAgIGNvbnN0IGIgPSBidWlsZEJhY2tlbmQoY2ZnKTtcbiAgICBiYWNrZW5kcy5zZXQoa2V5LCBiKTtcbiAgfVxuICBjb25zb2xlLmxvZyhcIkJ1aWx0IGJhY2tlbmRzOlwiLCBPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyhjb25maWcuYmFja2VuZHMpKTtcblxuICBsZXQgZm4gPSBidWlsZFJ1bGVzKGJhY2tlbmRzLCBjb25maWcucnVsZXMpXG4gIFxuICBjb25zdCBtaWRkbGV3YXJlID0gY29uZmlnLm1pZGRsZXdhcmU7XG4gIGlmIChtaWRkbGV3YXJlICYmIG1pZGRsZXdhcmUubGVuZ3RoID4gMCkge1xuICAgIGZvciAobGV0IGkgPSBtaWRkbGV3YXJlLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICBmbiA9IGJ1aWxkTWlkZGxld2FyZShmbiwgbWlkZGxld2FyZVtpXSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIE9iamVjdC5hc3NpZ24oZm4sIHtcbiAgICBiYWNrZW5kczogYmFja2VuZHNcbiAgfSlcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGJ1aWxkQXBwRnJvbUNvbmZpZyhjPzogYW55KSB7XG4gIHRyeSB7XG4gICAgY29uc3QgY29uZmlnID0gYyB8fCBhcHAuY29uZmlnW0FwcENvbmZpZ0tleV0gfHwgYXBwLmNvbmZpZ1snZmx5Q0ROJ107IC8vIHN1cHBvcnQgZmx5Q0ROIGNvbmZpZyBrZXkgZm9yIGEgd2hpbGVcbiAgICBpZiAoIWNvbmZpZykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiZmx5QXBwIGNvbmZpZyBwcm9wZXJ0eSBub3QgZm91bmRcIik7XG4gICAgfVxuICAgIGlmICghaXNDZG5Db25maWcoY29uZmlnKSkge1xuICAgICAgLy8gVGhpcyBpcyB1bnJlYWNoYWJsZSBiZWNhdXNlIGlzQ2RuQ29uZmlnIHRocm93cyBidXQgdHlwZXNjcmlwdCBjYW4ndCBpbmZlciB0aGF0IHNvIHdlIHRocm93IHRvb1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiQXBwIGNvbmZpZyBub3Qgc3VwcG9ydGVkXCIpO1xuICAgIH1cbiAgICByZXR1cm4gYnVpbGRDZG4oY29uZmlnKVxuICB9IGNhdGNoIChlcnJvcikge1xuICAgIGNvbnN0IGZuID0gKC4uLmFyZ3M6IGFueVtdKSA9PiB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKG5ldyBSZXNwb25zZShgSW52YWxpZCBBcHAgQ29uZmlnOiAke2Vycm9yLm1lc3NhZ2UgfHwgZXJyb3J9YCkpO1xuICAgIH1cbiAgICByZXR1cm4gT2JqZWN0LmFzc2lnbihmbiwgeyBiYWNrZW5kczogbmV3IE1hcDxzdHJpbmcsIFByb3h5RnVuY3Rpb24+KCl9KVxuICB9XG59XG4iXX0=