UNPKG

@sigiljs/sigil

Version:

TypeScript-first Node.js HTTP framework offering schema-driven routing, modifier-based middleware, plugin extensibility, and flexible response templating

125 lines (124 loc) 3.93 kB
import a from "../route/route.mjs"; import l from "./misc/attach-plugin-context.mjs"; import d from "../utils/safe-url.mjs"; import u from "./sigil-request-processor.mjs"; class r extends u { /** * Static helper to pair a schema definition with optional metadata. */ defineSchema = r.defineSchema; /** * Static helper to pair a handler with optional metadata. */ defineHandler = r.defineHandler; /** * Constructs a new Sigil instance with given options. * * @param options partial SigilOptions to configure core behavior. */ constructor(e) { super(e); } /** * Define request handler with metadata. * * TypeScript-only helper */ static defineHandler(e, t) { return t; } /** * Implements defineSchema overloads, returning the schema and optional metadata. * * @param schema schema to define. * @param meta optional metadata for documentation. * @returns tuple associating schema with its metadata. */ static defineSchema(e, t) { return [e, t]; } /** * Registers and configures a Sigil plugin. * Attaches framework context and prevents duplicate registration. * * @param plugin plugin constructor to instantiate. * @param config optional configuration for the plugin. */ addPlugin(e, t) { if (this.$plugins.has(e.name)) throw new Error(`Plugin with name "${e.name}" already registered.`); try { l(e, { sigilApi: this, responseTemplate: this.$responseTemplate, routes: this.$routes, debugOpts: this.$options.debug || {}, pluginConfig: t }); const s = new e(); this.$plugins.set(e.name, s); } catch (s) { this.logger({ message: `Failed to initialize plugin "${e?.name}" due to ${s?.name}: ${s?.message}`, level: "error", module: "registry", json: { milestone: "plugin", ok: !1, plugins: e?.name } }); } } /** * Mounts an existing Route instance at a given path. * Connects it to framework internals and returns the route. * * @param path base path for mounting the route (e.g., "/api"). * @param route route instance to mount. * @returns mounted Route instance. */ mount(e, t) { return this.$root.mount(e, t), this.$routes.add([e, t]), t.__$connectToSigil( this, () => this.$updateCallback(), { debug: this.$options.debug } ), t; } /** * Defines and mounts a new Route at the specified path. * Applies framework debug settings to the route. * * @param path base path for the new route. * @param options optional route configuration (modifiers, tags, debug). * @returns newly created and mounted Route instance. */ route(e, t) { const s = new a({ ...t, debug: t?.debug ?? this.$options.debug }); return this.$root.mount(e, s), this.$routes.add([e, s]), s.__$connectToSigil(this, () => this.$updateCallback()), s; } /** * Starts the HTTP server listening on the specified port and host. * Returns connection details and URL upon success. * * @param port TCP port number to listen on. * @param host hostname or IP address to bind (default "localhost"). * @returns promise resolving to host, port, and URL of the server. */ async listen(e, t = "localhost") { if (!this.$server) throw new Error("Cannot use internal server in the serverless mode"); const s = this.$options.server?.https?.cert ? "https" : "http", n = d(`${s}://${t}:${e}`); if (!n) throw new Error(`Invalid URL: ${s}://${t}:${e}`); return this.$initialized = !0, await this.$updateCallback(), await new Promise((i) => { const o = setInterval(() => { this.$pluginsInitialized && (i(), clearInterval(o)); }, 100); }), new Promise((i) => { this.$server.listen(e, t, () => i({ host: t, port: e, url: n })); }); } } export { r as default };