import * as plugins from './plugins.js'; import * as paths from './paths.js'; import { Reception } from './reception/classes.reception.js'; const manifestIconPng = Uint8Array.from(Buffer.from( 'iVBORw0KGgoAAAANSUhEUgAAAJAAAACQCAYAAADnRuK4AAABzklEQVR4nO3OMQ0AMAzAsEIc3aHrOOyJIuXw75lzN/mGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB+KGB6L2AK5GkZ1Ln/HeAAAAAElFTkSuQmCC', 'base64' )); const createManifestResponse = () => new Response(JSON.stringify({ name: 'idp.global', short_name: 'idp.global', start_url: '/', display: 'standalone', orientation: 'any', background_color: '#000000', theme_color: '#000000', icons: [], related_applications: [], scope: '/', lang: 'en', display_override: ['window-controls-overlay'], }), { headers: { 'Content-Type': 'application/json', 'Cache-Control': 'no-store', }, }); const createManifestIconResponse = () => new Response(manifestIconPng.slice(), { headers: { 'Content-Type': 'image/png', 'Content-Length': String(manifestIconPng.byteLength), 'Cache-Control': 'public, max-age=86400', }, }); export const runCli = async () => { const serviceQenv = new plugins.qenv.Qenv('./', './.nogit', false); // Create reception first so we can reference it in routes let reception: Reception; const websiteServer = new plugins.typedserver.utilityservers.UtilityWebsiteServer({ feedMetadata: null, domain: 'idp.global', serveDir: paths.distWebDir, securityHeaders: { csp: { defaultSrc: "'self'", scriptSrc: ["'self'", "'unsafe-inline'", "'unsafe-eval'", "https://cdn.paddle.com", "https://public.profitwell.com"], styleSrc: ["'self'", "'unsafe-inline'", "https://cdn.paddle.com", "https://assetbroker.lossless.one"], imgSrc: ["'self'", "data:", "https:"], fontSrc: ["'self'", "data:", "https://assetbroker.lossless.one"], connectSrc: ["'self'", "https://*.paddle.com", "https://buy.paddle.com", "https://checkout.paddle.com", "https://checkout-service.paddle.com", "https://cdn.paddle.com", "https://*.sentry.io", "https://public.profitwell.com", "wss:"], frameSrc: ["https://buy.paddle.com", "https://checkout.paddle.com", "https://*.paddle.com"], }, }, addCustomRoutes: async (typedserver) => { // Enable SPA fallback - serves index.html for non-file routes (e.g., /login, /dashboard) typedserver.options.spaFallback = true; // OIDC Discovery endpoint typedserver.addRoute('/.well-known/openid-configuration', 'GET', async (ctx) => { return new Response(JSON.stringify(reception.oidcManager.getDiscoveryDocument()), { headers: { 'Content-Type': 'application/json' }, }); }); // JWKS endpoint typedserver.addRoute('/.well-known/jwks.json', 'GET', async (ctx) => { return new Response(JSON.stringify(reception.oidcManager.getJwks()), { headers: { 'Content-Type': 'application/json' }, }); }); typedserver.addRoute('/manifest.json', 'GET', async () => createManifestResponse()); typedserver.addRoute('/manifest.json', 'HEAD', async () => createManifestResponse()); typedserver.addRoute('/idp-manifest.json', 'GET', async () => createManifestResponse()); typedserver.addRoute('/idp-manifest.json', 'HEAD', async () => createManifestResponse()); typedserver.addRoute('/assetbroker/manifest/favicon.png', 'GET', async () => createManifestIconResponse()); typedserver.addRoute('/assetbroker/manifest/icon-144x144.png', 'GET', async () => createManifestIconResponse()); typedserver.addRoute('/assetbroker/manifest/icon-512x512.png', 'GET', async () => createManifestIconResponse()); typedserver.addRoute('/assetbroker/manifest/icon-large.png', 'GET', async () => createManifestIconResponse()); typedserver.addRoute('/assetbroker/manifest/favicon.png', 'HEAD', async () => createManifestIconResponse()); typedserver.addRoute('/assetbroker/manifest/icon-144x144.png', 'HEAD', async () => createManifestIconResponse()); typedserver.addRoute('/assetbroker/manifest/icon-512x512.png', 'HEAD', async () => createManifestIconResponse()); typedserver.addRoute('/assetbroker/manifest/icon-large.png', 'HEAD', async () => createManifestIconResponse()); // OAuth Authorization endpoint typedserver.addRoute('/oauth/authorize', 'GET', async (ctx) => { return reception.oidcManager.handleAuthorize(ctx); }); // OAuth Token endpoint typedserver.addRoute('/oauth/token', 'POST', async (ctx) => { return reception.oidcManager.handleToken(ctx); }); // OAuth UserInfo endpoint (GET and POST) typedserver.addRoute('/oauth/userinfo', 'GET', async (ctx) => { return reception.oidcManager.handleUserInfo(ctx); }); typedserver.addRoute('/oauth/userinfo', 'POST', async (ctx) => { return reception.oidcManager.handleUserInfo(ctx); }); // OAuth Revocation endpoint typedserver.addRoute('/oauth/revoke', 'POST', async (ctx) => { return reception.oidcManager.handleRevoke(ctx); }); }, }); // lets add the reception routes reception = new Reception({ name: (await serviceQenv.getEnvVarOnDemand('INSTANCE_NAME')) || 'idp.global', mongoDescriptor: { mongoDbUrl: await serviceQenv.getEnvVarOnDemand('MONGODB_URL'), }, websiteServer: websiteServer, baseUrl: await serviceQenv.getEnvVarOnDemand('IDP_BASEURL'), }); await reception.start(); await websiteServer.start(2999); };