refactor: 리펙토링

This commit is contained in:
DongHyeonka
2026-08-01 19:39:59 +09:00
parent 9c959ea2a5
commit c6da03369c
171 changed files with 20329 additions and 782 deletions
@@ -1,65 +1,174 @@
import type { ApiOperation } from "../../../contracts/api-operations.ts";
import type { Result } from "../../../application/result.ts";
import type { ApiFailure, FailureKind } from "../../../contracts/errors.ts";
import type { FailureEffectCertainty } from "../../../contracts/errors.ts";
import {
createFailure,
kindForStatus,
} from "../../../contracts/errors.ts";
import type { HttpExecutionOutcome } from "../../../adapters/http/http-execution-v3.ts";
import { createReferenceFeatureInput } from "../application/reference-feature-api.ts";
import {
REFERENCE_FEATURE_CONTRACT,
REFERENCE_FEATURE_ID,
} from "../contracts/reference-feature-contract.ts";
import {
mapWithBoundaryRegistry,
type MappingResult,
} from "../../../contracts/boundary-mapper.ts";
import { validateWithRuntimeSchemaRegistry } from "../../../contracts/schema-registry.ts";
import { mapReferenceOperation } from "../contracts/reference-mapper.ts";
import {
createReferenceHttpGateway,
type RawReferenceHttpExecutor,
type ReferenceHttpRequest,
type ReferenceOperationId,
} from "./reference-http-gateway.ts";
type HttpContract = Readonly<{
getOperation(operationId: string): ApiOperation;
validatePayload(schemaId: string, value: unknown): ReturnType<
typeof validateWithRuntimeSchemaRegistry
>;
validateRequest(schemaId: string, value: unknown): ReturnType<
typeof validateWithRuntimeSchemaRegistry
>;
validatePath(schemaId: string, value: unknown): ReturnType<
typeof validateWithRuntimeSchemaRegistry
>;
mapPayload(operationId: string, payload: unknown): MappingResult<unknown>;
export type InstalledContractOperationExecutor = Readonly<{
execute(
operationId: string,
input: unknown,
context?: Readonly<{ signal?: AbortSignal }>,
): Promise<HttpExecutionOutcome<unknown, unknown>>;
}>;
type HttpExecutor = RawReferenceHttpExecutor;
/**
* The installed feature consumes the composed external-contract operation
* registry through one descriptor-driven executor. Legacy ApiOperation/schema
* registries are intentionally absent from this production composition seam.
*/
export function createReferenceFeatureInstalledInput(context: Readonly<{
createHttpClient(contract: HttpContract): HttpExecutor;
contractOperations: InstalledContractOperationExecutor;
}>) {
const operations =
REFERENCE_FEATURE_CONTRACT.apiOperations as Readonly<Record<string, ApiOperation>>;
const schemas = REFERENCE_FEATURE_CONTRACT.runtimeSchemas;
const mappers = REFERENCE_FEATURE_CONTRACT.mappers;
const validate = (schemaId: string, value: unknown) =>
validateWithRuntimeSchemaRegistry(schemaId, value, schemas);
const rawHttp = context.createHttpClient({
getOperation(operationId) {
const operation = operations[operationId];
if (!operation) {
throw new Error(`Unknown reference operation: ${operationId}`);
}
return operation;
},
validatePayload: validate,
validateRequest: validate,
validatePath: validate,
mapPayload(operationId, payload) {
const operation = operations[operationId];
if (!operation?.mapperId) {
return { ok: false, code: "MAPPING_INVARIANT_REJECTED" };
}
return mapWithBoundaryRegistry(operation.mapperId, payload, mappers);
const rawHttp: RawReferenceHttpExecutor = Object.freeze({
async execute(request) {
const operationId = request.operationId;
const input = inputFor(request);
const signal = "signal" in request ? request.signal : undefined;
const outcome = await context.contractOperations.execute(
operationId,
input,
signal === undefined ? {} : { signal },
);
return projectExecutionOutcome(operationId, outcome);
},
});
return Object.freeze({
featureId: REFERENCE_FEATURE_ID,
input: createReferenceFeatureInput(createReferenceHttpGateway(rawHttp)),
});
}
function inputFor(
request: ReferenceHttpRequest<ReferenceOperationId>,
): unknown {
switch (request.operationId) {
case "LIST_REFERENCE_RESOURCES":
return request.searchParams;
case "CREATE_REFERENCE_RESOURCE":
return request.body;
case "GET_REFERENCE_RESOURCE":
return request.pathParams;
}
}
function projectExecutionOutcome(
operationId: ReferenceOperationId,
outcome: HttpExecutionOutcome<unknown, unknown>,
): Result<unknown, ApiFailure> {
switch (outcome.kind) {
case "SUCCESS": {
const mapped = mapReferenceOperation(operationId, outcome.value);
return mapped.ok
? Object.freeze({ ok: true as const, value: mapped.value })
: failure(
"MAPPING_CONTRACT_VIOLATION",
operationId,
mapped.code,
{ effect: outcome.effect },
);
}
case "PROBLEM":
return failure(
kindForStatus(outcome.metadata.status),
operationId,
"CONTRACT_PROBLEM",
{ httpStatus: outcome.metadata.status, effect: outcome.effect },
);
case "UNAUTHENTICATED":
return failure("AUTH_REQUIRED", operationId, "UNAUTHENTICATED", {
effect: outcome.effect,
});
case "FORBIDDEN":
return failure("FORBIDDEN", operationId, "FORBIDDEN", {
effect: outcome.effect,
});
case "RATE_LIMITED":
return failure("RATE_LIMITED", operationId, "RATE_LIMITED", {
...(outcome.retryAfterMs === undefined
? {}
: { retryAfterMs: outcome.retryAfterMs }),
effect: outcome.effect,
});
case "CANCELLED":
return failure("REQUEST_ABORTED", operationId, "REQUEST_ABORTED", {
effect: outcome.effect,
});
case "TRANSPORT_FAILURE":
return failure(
outcome.failure.kind === "TIMEOUT"
? "REQUEST_TIMEOUT"
: outcome.failure.kind === "ABORTED_BY_SCOPE"
? "SCOPE_GENERATION_CHANGED"
: "NETWORK_UNREACHABLE",
operationId,
outcome.failure.kind,
{ effect: outcome.effect },
);
case "CONTRACT_VIOLATION":
return failure(
failureKindForViolation(outcome.violation.kind),
operationId,
outcome.violation.kind,
{ effect: outcome.effect },
);
}
}
function failureKindForViolation(
violation: Extract<
HttpExecutionOutcome<unknown, unknown>,
{ kind: "CONTRACT_VIOLATION" }
>["violation"]["kind"],
): FailureKind {
switch (violation) {
case "CONTENT_TYPE_MISMATCH":
return "CONTENT_TYPE_MISMATCH";
case "RESPONSE_TOO_LARGE":
return "RESPONSE_BODY_LIMIT";
case "UTF8_INVALID":
case "JSON_INVALID":
return "MALFORMED_JSON";
case "MAPPING_CONTRACT_VIOLATION":
return "MAPPING_CONTRACT_VIOLATION";
case "SCOPE_FENCED":
return "SCOPE_GENERATION_CHANGED";
case "SUCCESS_SCHEMA_INVALID":
case "PROBLEM_SCHEMA_INVALID":
case "VALIDATOR_RUNTIME_FAILURE":
return "SCHEMA_MISMATCH";
default:
return "ENVELOPE_MISMATCH";
}
}
function failure(
kind: FailureKind,
operationId: string,
code: string,
details: Readonly<{
httpStatus?: number;
retryAfterMs?: number;
effect?: FailureEffectCertainty;
}> = {},
): Result<never, ApiFailure> {
return Object.freeze({
ok: false as const,
error: createFailure(kind, operationId, 0, { code, ...details }),
});
}
@@ -25,6 +25,7 @@ type ReferenceOperationMap = Readonly<{
operationId: "CREATE_REFERENCE_RESOURCE";
routeId: "REFERENCE_RESOURCE_LIST";
body: ReferenceCreateCommand;
signal?: AbortSignal;
}>;
value: ReferenceResource;
}>;
@@ -71,11 +72,15 @@ export function createReferenceHttpGateway(
});
return projectListResult(result);
},
async create(command: ReferenceCreateCommand) {
async create(
command: ReferenceCreateCommand,
context?: Readonly<{ signal?: AbortSignal }>,
) {
const result = await http.execute({
operationId: "CREATE_REFERENCE_RESOURCE",
routeId: "REFERENCE_RESOURCE_LIST",
body: command,
signal: context?.signal,
});
return projectResourceResult("CREATE_REFERENCE_RESOURCE", result);
},