diff --git a/NEXT_STEPS.md b/NEXT_STEPS.md index 4913f2d..c92f3ee 100644 --- a/NEXT_STEPS.md +++ b/NEXT_STEPS.md @@ -30,6 +30,7 @@ Estado al cierre: - `arts/conn/connection.ts` delega apertura/cierre logico e `isConnected` en `connection-lifecycle.ts`. - `arts/conn/connection.ts` delega la programacion de reconnect y exhaustion en `connection-reconnect-runtime.ts`. - `libs/perm/evaluator.ts` delega helpers puros de resultado, dependencias y comparacion en `evaluator-helpers.ts`. + - `arts/http/engine-http.ts` delega la validacion preflight de `bodySchema` en `request-validation.ts`. - `arts/conn/connection.ts` delega decode/routing de frames entrantes en `connection-message-router.ts`. - `arts/conn/connection.ts` delega el intento open/auth/flush/join en `connection-connect.ts`. - `arts/conn/connection.ts` delega current transport, attach/detach y close en `connection-transport-runtime.ts`. diff --git a/src/arts/http/engine-http.ts b/src/arts/http/engine-http.ts index e37885d..bb99f58 100644 --- a/src/arts/http/engine-http.ts +++ b/src/arts/http/engine-http.ts @@ -13,7 +13,6 @@ import { HTTP_RESULT_KIND_NETWORK, HTTP_RESULT_KIND_VALIDATION, httpStatusErrorMessage, - requestBodyValidationErrorMessage, HTTP_DIAGNOSTIC_EVENTS } from './consts.ts'; import { emitHttpDiagnostic } from './diagnostics.ts'; @@ -24,7 +23,6 @@ import { resolveHttpCallRetry, type ResolvedHttpDefaults } from './engine-options.ts'; -import { HttpBodyValidationError } from './errors.ts'; import { runAfterResponse, runBeforeError, @@ -32,7 +30,8 @@ import { runBeforeRetry } from './hooks.ts'; import { computeRetryDelay, delayWithSignal, shouldRetryRequest } from './retry.ts'; -import { buildHttpFailure, buildOkOrValidation, runStandardValidate } from './results.ts'; +import { buildHttpFailure, buildOkOrValidation } from './results.ts'; +import { validateHttpRequestBody } from './request-validation.ts'; import { appendSearch, normalizeSearch, resolveUrl } from './search.ts'; import { attemptTimeoutSignal, @@ -115,25 +114,7 @@ async function execute( ? (init as HttpBodyRequestInit).bodySchema : undefined; - if (bodyInput !== undefined && bodySchema !== undefined) { - const validated = await runStandardValidate(bodySchema, bodyInput); - if (validated.issues !== undefined) { - const error = new HttpBodyValidationError( - requestBodyValidationErrorMessage(method, url), - validated.issues - ); - // Programmer error: log it before throwing so the failure is visible - // in the logger pipeline even when the caller's catch swallows the - // throw. - emitHttpDiagnostic(diagnostics, HTTP_DIAGNOSTIC_EVENTS.BODY_SCHEMA_REJECTED, { - method, - url, - issueCount: validated.issues.length, - error - }); - throw error; - } - } + await validateHttpRequestBody({ diagnostics, method, url, body: bodyInput, schema: bodySchema }); // URL resolution + search params. const fullUrl = appendSearch(resolveUrl(url, defaults.baseUrl), normalizeSearch(init?.search)); diff --git a/src/arts/http/request-validation.ts b/src/arts/http/request-validation.ts new file mode 100644 index 0000000..c4bdec0 --- /dev/null +++ b/src/arts/http/request-validation.ts @@ -0,0 +1,40 @@ +import type { StandardSchemaV1 } from '$libs/standard-schema'; +import { + HTTP_DIAGNOSTIC_EVENTS, + requestBodyValidationErrorMessage +} from './consts.ts'; +import { emitHttpDiagnostic, type HttpDiagnostics } from './diagnostics.ts'; +import { HttpBodyValidationError } from './errors.ts'; +import { runStandardValidate } from './results.ts'; +import type { HttpMethod } from './types.ts'; + +interface ValidateHttpRequestBodyInput { + readonly diagnostics: HttpDiagnostics; + readonly method: HttpMethod; + readonly url: string; + readonly body: unknown; + readonly schema: StandardSchemaV1 | undefined; +} + +export async function validateHttpRequestBody( + input: ValidateHttpRequestBodyInput +): Promise { + if (input.body === undefined || input.schema === undefined) return; + + const validated = await runStandardValidate(input.schema, input.body); + if (validated.issues === undefined) return; + + const error = new HttpBodyValidationError( + requestBodyValidationErrorMessage(input.method, input.url), + validated.issues + ); + // Programmer error: log it before throwing so the failure is visible in + // the logger pipeline even when the caller's catch swallows the throw. + emitHttpDiagnostic(input.diagnostics, HTTP_DIAGNOSTIC_EVENTS.BODY_SCHEMA_REJECTED, { + method: input.method, + url: input.url, + issueCount: validated.issues.length, + error + }); + throw error; +}