UNPKG

convex

Version:

Client for the Convex Cloud

158 lines (157 loc) 5.79 kB
"use strict"; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); var router_exports = {}; __export(router_exports, { HttpRouter: () => HttpRouter, httpRouter: () => httpRouter }); module.exports = __toCommonJS(router_exports); var import_authentication_impl = require("./impl/authentication_impl.js"); var import_http_impl = require("./impl/http_impl.js"); var import_syscall = require("./impl/syscall.js"); const routableMethods = [ "GET", "POST", "PUT", "DELETE", "OPTIONS", "PATCH" ]; function normalizeMethod(method) { if (method === "HEAD") return "GET"; return method; } const httpRouter = () => new HttpRouter(); class HttpRouter { constructor() { this.exactRoutes = /* @__PURE__ */ new Map(); this.prefixRoutes = /* @__PURE__ */ new Map(); this.isRouter = true; this.route = (spec) => { if (!spec.handler) throw new Error(`route requires handler`); if (!spec.method) throw new Error(`route requires method`); const { method, handler } = spec; if (!routableMethods.includes(method)) { throw new Error( `'${method}' is not an allowed HTTP method (like GET, POST, PUT etc.)` ); } if ("path" in spec) { if (!spec.path.startsWith("/")) { throw new Error(`path '${spec.path}' does not start with a /`); } const prefixes = this.prefixRoutes.get(method) || /* @__PURE__ */ new Map(); for (const [prefix, _] of prefixes.entries()) { if (spec.path.startsWith(prefix)) { throw new Error( `${spec.method} path ${spec.path} is shadowed by pathPrefix ${prefix}` ); } } const methods = this.exactRoutes.has(spec.path) ? this.exactRoutes.get(spec.path) : /* @__PURE__ */ new Map(); if (methods.has(method)) { throw new Error( `Path '${spec.path}' for method ${method} already in use` ); } methods.set(method, handler); this.exactRoutes.set(spec.path, methods); } else { if (!spec.pathPrefix.startsWith("/")) { throw new Error(`path '${spec.pathPrefix}' does not start with a /`); } if (!spec.pathPrefix.endsWith("/")) { throw new Error(`pathPrefix ${spec.pathPrefix} must end with a /`); } const prefixes = this.prefixRoutes.get(method) || /* @__PURE__ */ new Map(); for (const [prefix, _] of prefixes.entries()) { if (spec.pathPrefix.startsWith(prefix)) { throw new Error( `${spec.method} pathPrefix ${spec.pathPrefix} is shadowed by pathPrefix ${prefix}` ); } } prefixes.set(spec.pathPrefix, handler); this.prefixRoutes.set(method, prefixes); } }; this.getRoutes = () => { const exactPaths = [...this.exactRoutes.keys()].sort(); const exact = exactPaths.flatMap( (path) => [...this.exactRoutes.get(path).keys()].sort().map( (method) => [path, method, this.exactRoutes.get(path).get(method)] ) ); const prefixPathMethods = [...this.prefixRoutes.keys()].sort(); const prefixes = prefixPathMethods.flatMap( (method) => [...this.prefixRoutes.get(method).keys()].sort().map( (pathPrefix) => [ `${pathPrefix}*`, method, this.prefixRoutes.get(method).get(pathPrefix) ] ) ); return [...exact, ...prefixes]; }; this.lookup = (path, method) => { method = normalizeMethod(method); const exactMatch = this.exactRoutes.get(path)?.get(method); if (exactMatch) return [exactMatch, method, path]; const prefixes = this.prefixRoutes.get(method) || /* @__PURE__ */ new Map(); for (const [pathPrefix, endpoint] of prefixes.entries()) { if (path.startsWith(pathPrefix)) { return [endpoint, method, `${pathPrefix}*`]; } } return null; }; this.runRequest = async (argsStr) => { const request = (0, import_syscall.performJsSyscall)("requestFromConvexJson", { convexJson: JSON.parse(argsStr) }); const pathname = new URL(request.url).pathname; const method = request.method; const match = this.lookup(pathname, method); if (!match) { const response2 = new Response(`No HttpEndpoint routed for ${pathname}`, { status: 404 }); return JSON.stringify( (0, import_syscall.performJsSyscall)("convexJsonFromResponse", { response: response2 }) ); } const [endpoint, _method, _path] = match; const calls = (0, import_http_impl.setupHttpCalls)(); const ctx = { ...calls, auth: (0, import_authentication_impl.setupAuth)() }; const response = await endpoint(ctx, request); return JSON.stringify( (0, import_syscall.performJsSyscall)("convexJsonFromResponse", { response }) ); }; } } //# sourceMappingURL=router.js.map