import { Auth } from "./auth" import { Frontend } from "./frontend" export class Server { async getEnv(variables) { return Object.fromEntries( await Promise.all( variables.map(async variable => { const {state} = await Deno.permissions.query({ name: 'env', variable }) if (state === 'granted') { return [variable, Deno.env.get(variable)] } else { return [variable, undefined] } }) ) ) } async configure() { const env = await this.getEnv([ 'PORT', 'BASE_URL', 'GITEA_APP_BASE_URL', 'GITEA_API_BASE_URL', ]) this.port = env.PORT ?? 3000 this.baseUrl = env.BASE_URL ?? '/macchiato' this.giteaAppBaseUrl = ( env.GITEA_APP_BASE_URL ?? 'http://gitea:3000' ) this.giteaApiBaseUrl = ( env.GITEA_API_BASE_URL ?? 'http://gitea:3000/api/v1' ) } async init() { this.auth = new Auth() this.frontend = new Frontend({ appBaseUrl: this.giteaAppBaseUrl, apiBaseUrl: this.giteaApiBaseUrl, }) const promises = [] const repos = [ 'loader', 'editor', 'forms', 'menu', 'settings', 'dialog', 'storage', 'editor-lib-codemirror', ] for (const repo of repos) { promises.push(server.frontend.loadRepo( 'macchiato', repo, {srcPath: [], destPath: [repo]} )) } promises.push(server.frontend.loadRepo( 'macchiato', 'pages', {srcPath: [], destPath: []} )) promises.push(server.frontend.loadRepo( 'macchiato', 'server', { srcPath: [], destPath: ['server'], ref: 'shared-server' } )) await Promise.all(promises) this.frontend.files['/app.js'] = ( this.frontend.files['/server/app.js'] ) this.frontend.files['/'] = ( this.frontend.files['/index.html'] ) const sw = this.frontend.files['/sw.js'] const commit = ( this.frontend.files['/server/app.js'].commit ) sw.body = ( new TextEncoder().encode( new TextDecoder().decode(sw.body) + `\n// ${commit}\n` ) ) } async serveRequest(event) { const {pathname} = new URL(event.request.url) if (pathname === `${this.baseUrl}/api/auth`) { await this.auth.redirect(event) } else { await this.frontend.serve(event) } } async serveConn(conn) { const httpConn = Deno.serveHttp(conn) for await (const event of httpConn) { this.serveRequest(event) } } async serve() { await this.configure() await this.init() this.server = Deno.listen({ port: this.port, }) for await (const conn of this.server) { this.serveConn(conn) } } async run() { await this.configure() await this.init() await this.serve() } }