UNPKG

godprotocol

Version:

A distributed computing environment for Web 4.0 — integrating AI, decentralisation, and virtual computation.

207 lines (161 loc) 4.91 kB
import Headers from "./Header.js"; let securities = { both: ["api_key", "auth_token"], api_key: ["api_key"], auth_token: ["auth_token"], all: ["api_key", "auth_token", "xplatform"], none: [], }; class Route_table extends Headers { constructor(gp) { super(); this.gp = gp; this.db_config = gp.db_config; this.api_key = gp.api_key; this.platform_uri = gp.platform_uri; this.versions = {}; this.validators = {}; } get_version = (version) => { let ver = this.versions[version]; if (!ver) return; this.active_version = version; return ver; }; init_version = async (version, config) => { this.versions[version] = { config, routes: {} }; this.active_version = version; }; // 🔌 extensibility register_validator = (name, fn) => { this.validators[name] = fn; }; load_routes = async (routes) => { for (let name in routes) { let { handler, ...config } = routes[name]; config.security = securities[config.security || "none"]; await this.add_route(name, handler, config); } }; add_route = async (name, handler, config) => { this.versions[this.active_version].routes[name] = { handler, config }; }; get_route = async (name) => { let version = this.versions[this.active_version]; let route = version.routes[name]; return route; }; check_validation = async (rule, data) => { let { prop, type, required, default: is_default } = rule; let data_value = data[prop]; data_value = data_value == null || data_value == undefined ? is_default : data_value; if (required && (data_value == null || data_value == is_default)) return { ok: false, message: `Field '${prop}' is required` }; if (data_value == null) { return { ok: true }; } if (type) { if (type.startsWith("/")) { } else { let type_of = typeof data_value; if (type_of !== type) return { ok: false, message: `Field '${prop}' must be of type '${type}' got '${type_of}'`, }; } } return { ok: true }; }; validate = async (schema, data) => { let { body: schema_body } = schema; let { body: data_body } = data; for (let prop in schema_body) { let rule = schema_body[prop]; if (prop === "$logic") { let or_logic = rule.or; if (or_logic) { for (let o = 0; o < or_logic.length; o++) { let or_rule = or_logic[o], or_rule_check; for (let proper of or_rule.properties) { or_rule_check = await this.check_validation( { prop: proper, ...or_rule }, data_body, ); if (or_rule_check?.ok) break; } if (or_rule.required && !or_rule_check?.ok) { return { ok: false, message: `At least one of the following fields is required: ${or_rule.properties.join( ", ", )}`, }; } } } let and_logic = rule.and; if (and_logic) { for (let a = 0; a < and_logic.length; a++) { let and_rule = and_logic[a]; for (let prop of and_rule.properties) { let and_rule_check = await this.check_validation( { prop, ...and_rule }, data_body, ); if (and_rule.required && !and_rule_check?.ok) { return { ok: false, message: `Field '${prop}' is required`, }; } } } } } let validation_result = await this.check_validation( { prop, ...rule }, data_body, ); if (!validation_result.ok) { return validation_result; } } return { ok: true }; }; get_route_config = async (name) => { let rot = await this.get_route(name); return rot.config; }; // ========================= // 🚀 EXECUTION PIPELINE // ========================= execute = async (name, payload) => { let route = await this.get_route(name); if (!route) { return { ok: false, status: 404, message: "Route not found", data: { path: `/${name}`, name }, }; } let { handler, config } = route; // 📜 schema if (config.schema) { let resp = await this.validate(config.schema, payload); // debug("Validation result for route", name, ":", resp); if (!resp.ok) return resp; } // ⚙️ middleware for (let middleware of config.middlewares || []) { let result = await middleware(payload); if (!result?.ok) return result; } // 🎯 handler return await handler(payload); }; } export default Route_table;