accounts
Version:
Tempo Accounts SDK
86 lines • 3.33 kB
JavaScript
import { Hono } from 'hono';
import * as RequestListener from './internal/requestListener.js';
export { auth } from './internal/handlers/auth.js';
export {} from './internal/handlers/session.js';
export { codeAuth } from './internal/handlers/codeAuth.js';
export { exchange } from './internal/handlers/exchange.js';
export { relay } from './internal/handlers/relay.js';
export { webAuthn } from './internal/handlers/webAuthn.js';
/**
* Mounts each sub-handler onto a fresh Hono app at `path` (default `/`) and
* returns a single composed handler. Routes are dispatched by Hono's trie
* — a deterministic match per path — instead of the older "try each handler
* in order until one returns non-404" loop.
*
* The returned handler preserves each sub-handler's route schema so the
* composed app stays usable from Hono's typed RPC client:
*
* ```ts
* import { hc } from 'hono/client'
*
* const app = Handler.compose(
* [Handler.exchange(), Handler.codeAuth({ store })],
* { path: '/api' },
* )
* type App = typeof app
*
* const client = hc<App>('https://wallet.example.com')
* await client.api.exchange.quote.$post({ json: { ... } }) // typed
* ```
*/
export function compose(handlers, options = {}) {
const mountPath = (options.path ?? '/');
const app = from(options);
for (const sub of handlers)
app.route(mountPath, sub);
app.notFound(() => new Response('Not Found', { status: 404 }));
return app;
}
/**
* Instantiates a new request handler.
*
* @param options - constructor options
* @returns Handler instance
*/
export function from(options = {}) {
const corsHeaders = corsToHeaders(options.cors);
const mergedHeaders = new Headers(corsHeaders);
for (const [key, value] of normalizeHeaders(options.headers).entries())
mergedHeaders.set(key, value);
const app = new Hono();
app.use(async (c, next) => {
if (c.req.method === 'OPTIONS')
return new Response(null, { headers: mergedHeaders });
await next();
for (const [key, value] of mergedHeaders.entries())
c.res.headers.set(key, value);
});
return Object.assign(app, {
listener: RequestListener.fromFetchHandler((request) => app.fetch(request)),
});
}
function normalizeHeaders(headers) {
if (!headers)
return new Headers();
if (headers instanceof Headers)
return headers;
return new Headers(headers);
}
function corsToHeaders(cors) {
if (cors === false)
return new Headers();
const config = cors === true || cors === undefined ? {} : cors;
const headers = new Headers();
const origin = Array.isArray(config.origin) ? config.origin.join(', ') : (config.origin ?? '*');
headers.set('Access-Control-Allow-Origin', origin);
headers.set('Access-Control-Allow-Methods', config.methods ?? 'GET, POST, PUT, DELETE, OPTIONS');
headers.set('Access-Control-Allow-Headers', config.headers ?? 'Content-Type');
if (config.credentials)
headers.set('Access-Control-Allow-Credentials', 'true');
if (config.exposeHeaders)
headers.set('Access-Control-Expose-Headers', config.exposeHeaders);
if (config.maxAge !== undefined)
headers.set('Access-Control-Max-Age', String(config.maxAge));
return headers;
}
//# sourceMappingURL=Handler.js.map