Merge branch '6-add-websocket-transport' into 7-add-resources-route

This commit is contained in:
2026-08-03 03:19:54 +00:00
4 changed files with 35 additions and 10 deletions
+20
View File
@@ -1,3 +1,23 @@
/**
* Success response status code.
*/
export const HTTP_STATUS_CODE_SUCCESS = 200;
/**
* Created response status code.
*/
export const HTTP_STATUS_CODE_CREATED = 201;
/**
* No content response status code.
*/
export const HTTP_STATUS_CODE_NO_CONTENT = 204;
/**
* Bad request response status code.
*/
export const HTTP_STATUS_CODE_BAD_REQUEST = 400;
/** /**
* HTTP status code for "Not Acceptable" error. * HTTP status code for "Not Acceptable" error.
*/ */
+2 -1
View File
@@ -1,5 +1,6 @@
import type { RouteSendOptions, RouteStream } from '../routes/types.ts'; import type { RouteSendOptions, RouteStream } from '../routes/types.ts';
import type { BaseStream } from './stream/base-stream.ts'; import type { BaseStream } from './stream/base-stream.ts';
import { HTTP_STATUS_CODE_NO_CONTENT, HTTP_STATUS_CODE_SUCCESS } from '../constants.ts';
/** /**
* Binds one application request to a connection-level stream. * Binds one application request to a connection-level stream.
@@ -44,7 +45,7 @@ export class ApplicationRouteStream implements RouteStream {
await this.connection.send({ await this.connection.send({
...(this.requestId === undefined ? {} : { id: this.requestId }), ...(this.requestId === undefined ? {} : { id: this.requestId }),
type, type,
statusCode: options.statusCode ?? (data === undefined ? 204 : 200), statusCode: options.statusCode ?? (data === undefined ? HTTP_STATUS_CODE_NO_CONTENT : HTTP_STATUS_CODE_SUCCESS),
body: data ?? null, body: data ?? null,
}); });
+8 -6
View File
@@ -3,13 +3,15 @@ import { streamSSE } from 'hono/streaming';
import { toExtendedJson, fromExtendedJson } from '@xo-cash/utils'; import { toExtendedJson, fromExtendedJson } from '@xo-cash/utils';
import type { Logger } from '../../utils/logger.ts'; import type { Logger } from '../../utils/logger.ts';
import { ApplicationError, normalizePublicError } from '../../errors/index.ts';
import type { ApplicationRequest, ApplicationRouter } from '../router.ts'; import type { ApplicationRequest, ApplicationRouter } from '../router.ts';
import { HonoSSEStream } from '../stream/hono-sse-stream.ts';
import { HttpRequestStream } from '../stream/http-request-stream.ts';
import type { StreamResponse } from '../stream/base-stream.ts'; import type { StreamResponse } from '../stream/base-stream.ts';
import type { AppEnv, TransportRouter } from './transport-router.ts'; import type { AppEnv, TransportRouter } from './transport-router.ts';
import { ApplicationError, normalizePublicError } from '../../errors/index.ts';
import { HTTP_STATUS_CODE_BAD_REQUEST, HTTP_STATUS_CODE_NO_CONTENT } from '../../constants.ts';
import { HonoSSEStream } from '../stream/hono-sse-stream.ts';
import { HttpRequestStream } from '../stream/http-request-stream.ts';
/** Hono context key where decoded Extended JSON bodies are stored. */ /** Hono context key where decoded Extended JSON bodies are stored. */
const PARSED_BODY_KEY = 'parsedBody'; const PARSED_BODY_KEY = 'parsedBody';
@@ -90,7 +92,7 @@ export class HttpTransportRouter implements TransportRouter {
c.set(PARSED_BODY_KEY, parsed); c.set(PARSED_BODY_KEY, parsed);
} catch (error) { } catch (error) {
debug('invalid Extended JSON request: %O', error); debug('invalid Extended JSON request: %O', error);
throw new ApplicationError(400, 'Invalid JSON in request body'); throw new ApplicationError(HTTP_STATUS_CODE_BAD_REQUEST, 'Invalid JSON in request body');
} }
} }
@@ -209,8 +211,8 @@ export class HttpTransportRouter implements TransportRouter {
* @param response - Buffered response from HttpRequestStream, if any. * @param response - Buffered response from HttpRequestStream, if any.
*/ */
private static toResponse(response: StreamResponse | undefined): Response { private static toResponse(response: StreamResponse | undefined): Response {
if (!response || response.statusCode === 204) { if (!response || response.statusCode === HTTP_STATUS_CODE_NO_CONTENT) {
return new Response(null, { status: 204 }); return new Response(null, { status: HTTP_STATUS_CODE_NO_CONTENT });
} }
return new Response(toExtendedJson(response.body), { return new Response(toExtendedJson(response.body), {
+5 -3
View File
@@ -7,11 +7,13 @@ import { toExtendedJson, fromExtendedJson } from '@xo-cash/utils';
import { z } from 'zod'; import { z } from 'zod';
import type { Logger } from '../../utils/logger.ts'; import type { Logger } from '../../utils/logger.ts';
import { ApplicationError, normalizePublicError } from '../../errors/index.ts';
import type { ApplicationRequest, ApplicationRouter } from '../router.ts'; import type { ApplicationRequest, ApplicationRouter } from '../router.ts';
import { WSStream } from '../stream/ws-stream.ts';
import type { AppEnv, UpgradeTransportRouter } from './transport-router.ts'; import type { AppEnv, UpgradeTransportRouter } from './transport-router.ts';
import { ApplicationError, normalizePublicError } from '../../errors/index.ts';
import { HTTP_STATUS_CODE_BAD_REQUEST } from '../../constants.ts';
import { WSStream } from '../stream/ws-stream.ts';
/** Default WebSocket upgrade path for application messages. */ /** Default WebSocket upgrade path for application messages. */
const WS_ROUTE = '/ws'; const WS_ROUTE = '/ws';
@@ -198,7 +200,7 @@ export class WsTransportRouter implements UpgradeTransportRouter {
try { try {
decoded = fromExtendedJson(payload); decoded = fromExtendedJson(payload);
} catch { } catch {
throw new ApplicationError(400, 'Invalid JSON in WebSocket message'); throw new ApplicationError(HTTP_STATUS_CODE_BAD_REQUEST, 'Invalid JSON in WebSocket message');
} }
const envelope = wsRequestSchema.parse(decoded); const envelope = wsRequestSchema.parse(decoded);