@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
JavaScript
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
};