import type { Hono } from 'hono'; import type { CryptoProvider } from '@shade/core'; import { createPrekeyRoutes } from './routes.js'; import { MemoryPrekeyStore } from './memory-store.js'; import type { PrekeyStore } from './store.js'; import type { PrekeyServerEvents } from './events.js'; import { KeyTransparencyService, type KeyTransparencyConfig, } from './kt-integration.js'; export { createPrekeyRoutes } from './routes.js'; export { MemoryPrekeyStore } from './memory-store.js'; export type { PrekeyStore } from './store.js'; export { verifyPayload, signPayload, canonicalizePayload, validateAddress } from './auth.js'; export { KeyTransparencyService, encodeSthForWire, encodeProofForWire } from './kt-integration.js'; export type { KeyTransparencyConfig } from './kt-integration.js'; export { createKTRoutes } from './kt-routes.js'; /** * Create a standalone Shade Prekey Server. * * Requires a CryptoProvider for signature verification on write routes. * * Standalone: * const crypto = new SubtleCryptoProvider(); * const server = createPrekeyServer({ crypto }); * export default { port: 3900, fetch: server.fetch }; * * Embedded in another Hono app: * const app = new Hono(); * app.route('/shade', createPrekeyServer({ crypto })); */ export function createPrekeyServer(options: { crypto: CryptoProvider; store?: PrekeyStore; disableRateLimit?: boolean; events?: PrekeyServerEvents; /** Existing KT service (already initialized via `KeyTransparencyService.create`). */ keyTransparency?: KeyTransparencyService; }): Hono { const store = options.store ?? new MemoryPrekeyStore(); const routesOptions: Parameters[2] = {}; if (options.disableRateLimit !== undefined) { routesOptions.disableRateLimit = options.disableRateLimit; } if (options.events !== undefined) { routesOptions.events = options.events; } if (options.keyTransparency !== undefined) { routesOptions.keyTransparency = options.keyTransparency; } return createPrekeyRoutes(store, options.crypto, routesOptions); } /** * Convenience: create both the KT service and the prekey server in one call. * Async because `KeyTransparencyService.create` reads existing state. */ export async function createPrekeyServerWithKT(options: { crypto: CryptoProvider; store?: PrekeyStore; disableRateLimit?: boolean; events?: PrekeyServerEvents; keyTransparency: KeyTransparencyConfig; }): Promise<{ app: Hono; kt: KeyTransparencyService }> { const kt = await KeyTransparencyService.create(options.crypto, options.keyTransparency); const passOpts: Parameters[0] = { crypto: options.crypto, keyTransparency: kt, }; if (options.store !== undefined) passOpts.store = options.store; if (options.disableRateLimit !== undefined) passOpts.disableRateLimit = options.disableRateLimit; if (options.events !== undefined) passOpts.events = options.events; const app = createPrekeyServer(passOpts); return { app, kt }; } export { RateLimiter, MemoryRateLimitStore } from './rate-limit.js'; export type { RateLimitStore, RateLimitConfig } from './rate-limit.js'; export { PrekeyServerEvents, shortHash as serverShortHash } from './events.js'; export type { PrekeyServerEvent, PrekeyServerEventName, PrekeyServerEventMap, PrekeyServerEventListener } from './events.js';