{"version":3,"sources":["../src/runtime/rpc-router.ts","../src/runtime/server.ts","../src/runtime/vercel-handler.ts"],"sourcesContent":["import type { FastifyInstance, FastifyReply, FastifyRequest } from 'fastify';\nimport type { RpcManifest, RpcServiceManifest } from '../rpc/types';\n\nexport type RpcServiceInstances = Record<string, Record<string, (...args: unknown[]) => unknown | Promise<unknown>>>;\n\nexport interface RegisterRpcRoutesOptions {\n    manifest: RpcManifest;\n    services: RpcServiceInstances;\n    authorize?: (request: FastifyRequest, service: RpcServiceManifest, methodName: string) => boolean | Promise<boolean>;\n}\n\nexport async function registerRpcRoutes(fastify: FastifyInstance, options: RegisterRpcRoutesOptions): Promise<void> {\n    const serviceMap = new Map(options.manifest.services.map((service) => [service.name, service]));\n\n    fastify.post('/rpc/:service/:method', async (request: FastifyRequest<{\n        Params: { service: string; method: string };\n        Body: { args?: unknown[] };\n    }>, reply: FastifyReply) => {\n        const service = serviceMap.get(request.params.service);\n        if (!service) {\n            reply.status(404);\n            return { error: 'WEXTS_RPC_SERVICE_NOT_FOUND' };\n        }\n\n        const method = service.methods.find((candidate) => candidate.name === request.params.method);\n        if (!method) {\n            reply.status(404);\n            return { error: 'WEXTS_RPC_METHOD_NOT_FOUND' };\n        }\n\n        if (method.requireAuth || service.requireAuth) {\n            const authorized = await options.authorize?.(request, service, method.name);\n            if (!authorized) {\n                reply.status(401);\n                return { error: 'WEXTS_RPC_AUTH_REQUIRED' };\n            }\n        }\n\n        const instance = options.services[service.name];\n        const handler = instance?.[method.handlerName];\n        if (!handler) {\n            reply.status(500);\n            return { error: 'WEXTS_RPC_HANDLER_NOT_BOUND' };\n        }\n\n        const args = Array.isArray(request.body?.args) ? request.body.args : [];\n        const data = await handler.apply(instance, args);\n        return { data };\n    });\n}\n","import * as fs from 'fs';\nimport * as path from 'path';\nimport Fastify, { FastifyInstance, FastifyServerOptions } from 'fastify';\nimport { registerWextsShield, type WextsShieldConfig, type WextsShieldRoutePolicy } from '@wexts/security';\nimport type { RpcManifest } from '../rpc/types';\nimport { registerRpcRoutes, type RpcServiceInstances } from './rpc-router';\nimport { WextsRuntimeError } from '../errors';\n\nexport interface WextsRuntimeConfig {\n    rootDir?: string;\n    port?: number;\n    host?: string;\n    dev?: boolean;\n    nextDir?: string;\n    nestAppModule?: unknown;\n    nestAppModulePath?: string;\n    rpcManifest?: RpcManifest;\n    rpcManifestPath?: string;\n    rpcServices?: RpcServiceInstances;\n    security?: WextsShieldConfig;\n    logger?: FastifyServerOptions['logger'];\n}\n\nexport interface WextsRuntimeServer {\n    fastify: FastifyInstance;\n    start: () => Promise<void>;\n    close: () => Promise<void>;\n}\n\nexport async function createWextsRuntimeServer(config: WextsRuntimeConfig = {}): Promise<WextsRuntimeServer> {\n    const rootDir = path.resolve(config.rootDir ?? process.cwd());\n    const fastify = Fastify({\n        logger: config.logger ?? true,\n        bodyLimit: config.security?.bodyLimitBytes ?? 1_048_576,\n        requestTimeout: config.security?.requestTimeoutMs ?? 30_000,\n    });\n\n    const manifest = config.rpcManifest ?? loadJson<RpcManifest>(rootDir, config.rpcManifestPath);\n    const routePolicies = [\n        ...(config.security?.routePolicies ?? []),\n        ...rpcPoliciesFromManifest(manifest),\n    ];\n\n    await registerWextsShield(fastify, {\n        ...config.security,\n        routePolicies,\n    });\n\n    fastify.get('/health', async () => ({\n        ok: true,\n        runtime: 'wexts',\n    }));\n\n    fastify.get('/api/health', async () => ({\n        ok: true,\n        runtime: 'wexts',\n        scope: 'api',\n    }));\n\n    if (manifest && config.rpcServices) {\n        await registerRpcRoutes(fastify, {\n            manifest,\n            services: config.rpcServices,\n            authorize: (request) => Boolean(request.headers.authorization || request.headers.cookie),\n        });\n    }\n\n    if (config.nestAppModule || config.nestAppModulePath) {\n        await mountNest(fastify, rootDir, config);\n    }\n\n    if (config.nextDir) {\n        await mountNext(fastify, rootDir, config);\n    }\n\n    const start = async () => {\n        await fastify.listen({\n            port: config.port ?? Number(process.env.PORT ?? 3000),\n            host: config.host ?? '0.0.0.0',\n        });\n    };\n\n    const close = async () => {\n        await fastify.close();\n    };\n\n    registerShutdown(close);\n\n    return {\n        fastify,\n        start,\n        close,\n    };\n}\n\nexport async function startWextsRuntime(config: WextsRuntimeConfig = {}): Promise<WextsRuntimeServer> {\n    const server = await createWextsRuntimeServer(config);\n    await server.start();\n    return server;\n}\n\nfunction rpcPoliciesFromManifest(manifest?: RpcManifest): WextsShieldRoutePolicy[] {\n    if (!manifest) return [];\n\n    return manifest.services.flatMap((service) => service.methods.map((method) => ({\n        path: `/rpc/${service.name}/${method.name}`,\n        methods: ['POST'],\n        mode: service.requireAuth || method.requireAuth ? 'requireAuth' : 'public',\n    })));\n}\n\nfunction loadJson<T>(rootDir: string, filePath?: string): T | undefined {\n    if (!filePath) return undefined;\n\n    const absolutePath = path.isAbsolute(filePath) ? filePath : path.join(rootDir, filePath);\n    if (!fs.existsSync(absolutePath)) return undefined;\n    return JSON.parse(fs.readFileSync(absolutePath, 'utf8')) as T;\n}\n\nasync function mountNest(fastify: FastifyInstance, rootDir: string, config: WextsRuntimeConfig): Promise<void> {\n    const [{ NestFactory }, { FastifyAdapter }] = await Promise.all([\n        import('@nestjs/core'),\n        import('@nestjs/platform-fastify'),\n    ]);\n    const AppModule = config.nestAppModule ?? await importModule(rootDir, config.nestAppModulePath!);\n    const moduleValue = (AppModule as { AppModule?: unknown }).AppModule ?? AppModule;\n    const nestApp = await NestFactory.create(moduleValue as never, new FastifyAdapter(fastify as never), {\n        logger: config.dev ? ['log', 'error', 'warn'] : ['error', 'warn'],\n    });\n    nestApp.setGlobalPrefix('api');\n    await nestApp.init();\n}\n\nasync function mountNext(fastify: FastifyInstance, rootDir: string, config: WextsRuntimeConfig): Promise<void> {\n    const nextModule = await import('next') as unknown as { default?: (options: unknown) => { prepare: () => Promise<void>; getRequestHandler: () => (req: unknown, res: unknown) => Promise<void> } };\n    const next = nextModule.default;\n    if (!next) {\n        throw new WextsRuntimeError({\n            code: 'WEXTS_RUNTIME_NEXT_MISSING',\n            message: 'Next.js could not be loaded. Install next or omit nextDir.',\n            suggestedFix: 'Install `next` in the application or remove `nextDir` from wexts.runtime.js.',\n            docsSlug: 'runtime',\n        });\n    }\n    const nextApp = next({\n        dev: config.dev ?? process.env.NODE_ENV !== 'production',\n        dir: path.isAbsolute(config.nextDir!) ? config.nextDir : path.join(rootDir, config.nextDir!),\n    });\n    await nextApp.prepare();\n    const handler = nextApp.getRequestHandler();\n\n    fastify.all('/*', async (request, reply) => {\n        await handler(request.raw, reply.raw);\n        reply.hijack();\n    });\n}\n\nasync function importModule(rootDir: string, modulePath: string): Promise<unknown> {\n    const absolutePath = path.isAbsolute(modulePath) ? modulePath : path.join(rootDir, modulePath);\n    return import(pathToFileUrl(absolutePath));\n}\n\nfunction pathToFileUrl(filePath: string): string {\n    return `file://${filePath}`;\n}\n\nfunction registerShutdown(close: () => Promise<void>): void {\n    const handler = async () => {\n        await close();\n        process.exit(0);\n    };\n\n    process.once('SIGINT', handler);\n    process.once('SIGTERM', handler);\n}\n","/**\n * Vercel / serverless handler adapter for the Wexts runtime.\n *\n * Creates a standard Node.js (req, res) handler that delegates to the\n * Fastify-backed Wexts runtime **without** calling fastify.listen().\n *\n * Usage:\n *   const handler = await createWextsHandler({ ... });\n *   export default handler;           // Vercel function entry\n */\n\nimport type { IncomingMessage, ServerResponse } from 'http';\nimport type { WextsRuntimeConfig } from './server';\nimport { createWextsRuntimeServer } from './server';\n\nexport type WextsHandler = (req: IncomingMessage, res: ServerResponse) => void;\n\n/**\n * Build a serverless-compatible handler from the Wexts runtime.\n * The returned function accepts Node http (req, res) and passes them\n * into the Fastify instance without ever calling listen().\n */\nexport async function createWextsHandler(\n    config: WextsRuntimeConfig = {},\n): Promise<WextsHandler> {\n    const server = await createWextsRuntimeServer({\n        ...config,\n        // Serverless does not use long-lived logging\n        logger: config.logger ?? false,\n    });\n\n    // Fastify exposes a raw Node handler via server.server (the http.Server)\n    // But we need to call .ready() first so all plugins are loaded.\n    await server.fastify.ready();\n\n    return (req: IncomingMessage, res: ServerResponse) => {\n        server.fastify.server.emit('request', req, res);\n    };\n}\n"],"mappings":"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","names":["registerRpcRoutes","fastify","options","serviceMap","Map","manifest","services","map","service","name","post","request","reply","get","params","status","error","method","methods","find","candidate","requireAuth","authorized","authorize","instance","handler","handlerName","args","Array","isArray","body","data","apply","fs","path","Fastify","registerWextsShield","createWextsRuntimeServer","config","rootDir","resolve","process","cwd","fastify","Fastify","logger","bodyLimit","security","bodyLimitBytes","requestTimeout","requestTimeoutMs","manifest","rpcManifest","loadJson","rpcManifestPath","routePolicies","rpcPoliciesFromManifest","registerWextsShield","get","ok","runtime","scope","rpcServices","registerRpcRoutes","services","authorize","request","Boolean","headers","authorization","cookie","nestAppModule","nestAppModulePath","mountNest","nextDir","mountNext","start","listen","port","Number","env","PORT","host","close","registerShutdown","startWextsRuntime","server","flatMap","service","methods","map","method","path","name","mode","requireAuth","filePath","undefined","absolutePath","isAbsolute","join","existsSync","JSON","parse","readFileSync","NestFactory","FastifyAdapter","Promise","all","AppModule","importModule","moduleValue","nestApp","create","dev","setGlobalPrefix","init","nextModule","next","default","WextsRuntimeError","code","message","suggestedFix","docsSlug","nextApp","NODE_ENV","dir","prepare","handler","getRequestHandler","reply","raw","hijack","modulePath","pathToFileUrl","exit","once","createWextsHandler","config","server","createWextsRuntimeServer","logger","fastify","ready","req","res","emit"]}