UNPKG

@roots/bud-server

Version:

Development server for @roots/bud

198 lines (197 loc) 6.36 kB
import { __decorate } from "tslib"; import { Service } from '@roots/bud-framework/service'; import { inject } from '@roots/bud-server/inject'; import { bind } from '@roots/bud-support/decorators/bind'; import { BudError } from '@roots/bud-support/errors'; /** * {@link BudServer} */ export class Server extends Service { /** * {@link BudServer.appliedMiddleware} */ appliedMiddleware = {}; /** * {@link BudServer.proxyUrl} * @readonly */ get proxyUrl() { return this.app.hooks.filter(`dev.proxyUrl`, new URL(`http://0.0.0.0`)); } /** * {@link BudServer.publicProxyUrl} * @readonly */ get publicProxyUrl() { return this.app.hooks.filter(`dev.publicProxyUrl`, this.proxyUrl); } /** * {@link BudServer.publicUrl} * @readonly */ get publicUrl() { return this.app.hooks.filter(`dev.publicUrl`, this.url); } /** * {@link BudServer.url} * @readonly */ get url() { const url = this.app.hooks.filter(`dev.url`, new URL(`http://0.0.0.0:3000`)); if (this.app.context.port) url.port = this.app.context.port; return url; } /** * {@link BudServer.applyMiddleware} */ async applyMiddleware() { await Promise.all(Object.entries(this.enabledMiddleware).map(async ([key, signifier]) => { if (this.app.context.hot === false && key === `hot`) { this.logger .scope(this.app.label, `server`, `middleware`, key) .log(`disabled`, `bud.context.hot is false`); return; } /** import middleware */ const { factory } = await this.app.module .import(signifier, import.meta.url) .catch(this.catch); /** save reference to middleware instance */ Object.defineProperty(this.appliedMiddleware, key, { value: factory(this.app), }); if (typeof this.appliedMiddleware[key] !== `function`) { this.logger .scope(this.app.label, `server`, `middleware`, key) .log(`unused`); return; } this.logger .scope(this.app.label, `server`, `middleware`, key) .log(`applied`) .info(this.appliedMiddleware[key]); /** apply middleware */ this.application.use(this.appliedMiddleware[key]); })).catch(this.catch); } /** * {@link Contract.catch} */ catch(error) { throw error; } /** * {@link BudServer.compilerBefore} */ async compilerBefore(bud) { await this.setConnection(); await this.injectScripts(); } /** * {@link BudServer.enabledMiddleware} * @readonly */ get enabledMiddleware() { return this.app.hooks.filter(`dev.middleware.enabled`, [])?.reduce((enabled, key) => ({ ...enabled, [key]: this.availableMiddleware?.[key], }), {}); } /** * {@link BudServer.injectScripts} */ async injectScripts() { if (!this.app.isDevelopment) return; const injectOn = async (instance) => inject(instance, Array.from(this.app.hooks.filter(`dev.client.scripts`) ?? [])); this.app.hasChildren ? Object.values(this.app.children).map(injectOn) : injectOn(this.app); } /** * {@link BudServer.register} */ async register(bud) { if (!bud.isDevelopment) return; this.availableMiddleware = { cookie: `@roots/bud-server/middleware/cookie`, dev: `@roots/bud-server/middleware/dev`, hot: `@roots/bud-server/middleware/hot`, proxy: `@roots/bud-server/middleware/proxy`, }; this.application = await bud.module .import(`@roots/bud-support/express`, import.meta.url) .then(app => app()); this.logger.log(`server.application`, this.application?.constructor.name); this.watcher = await import(`@roots/bud-server/server/watcher`).then(({ Watcher }) => new Watcher(() => bud)); this.logger.log(`server.watcher`, this.watcher?.constructor.name); bud.hooks.on(`dev.client.scripts`, await import(`@roots/bud-server/hooks`) .catch(this.catch) .then(result => result?.devClientScripts.callback)); this.application.set(`x-powered-by`, false); } /** * {@link BudServer.run} */ async run() { if (this.app.context.dry === true) return; await this.app.hooks.fire(`server.before`, this.app).catch(this.catch); await this.connection.createServer(this.application).catch(this.catch); await this.connection.listen(); await this.app.hooks.fire(`server.after`, this.app).catch(this.catch); } /** * {@link BudServer.serverBefore} */ async serverBefore(bud) { await this.setConnection(); await this.injectScripts(); await bud.compiler.compile(bud); await this.applyMiddleware(); await this.watcher.watch(); } /** * {@link BudServer.setConnection} */ async setConnection(connection) { if (connection) { this.connection = connection; return this.connection; } const isHttps = this.url.protocol === `https:`; this.connection = await this.app.module .import(isHttps ? `@roots/bud-server/server/https` : `@roots/bud-server/server/http`, import.meta.url) .then(({ Server }) => new Server(this.app)) .catch(this.catch); return this.connection; } } __decorate([ bind ], Server.prototype, "applyMiddleware", null); __decorate([ bind ], Server.prototype, "catch", null); __decorate([ bind ], Server.prototype, "compilerBefore", null); __decorate([ bind ], Server.prototype, "injectScripts", null); __decorate([ bind ], Server.prototype, "register", null); __decorate([ bind ], Server.prototype, "run", null); __decorate([ bind ], Server.prototype, "serverBefore", null); __decorate([ bind ], Server.prototype, "setConnection", null);