mirror of
https://github.com/morluto/rea.git
synced 2026-10-30 03:15:54 +00:00
268 lines
9.8 KiB
TypeScript
268 lines
9.8 KiB
TypeScript
import { z } from "zod";
|
|
|
|
import {
|
|
compareApplicationVersionsRequestSchema,
|
|
compareJavaScriptExportShapesRequestSchema,
|
|
compareSourceToBundleRequestSchema,
|
|
traceApplicationFeatureRequestSchema,
|
|
traceJavaScriptSemanticsRequestSchema,
|
|
type CompareApplicationVersionsRequest,
|
|
type CompareJavaScriptExportShapesRequest,
|
|
type CompareSourceToBundleRequest,
|
|
type TraceApplicationFeatureRequest,
|
|
type TraceJavaScriptSemanticsRequest,
|
|
} from "../contracts/applicationWorkflowInputContracts.js";
|
|
import type { Evidence } from "../domain/evidence.js";
|
|
import { AnalysisInputError, type AnalysisError } from "../domain/errors.js";
|
|
import { projectInputIssues } from "../domain/inputIssueProjection.js";
|
|
import { compareApplicationVersionsInputSchema } from "../domain/javascriptApplicationVersionComparisonSchemas.js";
|
|
import { compareJavaScriptExportShapesInputSchema } from "../domain/javascriptExportShapeComparisonSchemas.js";
|
|
import { traceApplicationFeatureInputSchema } from "../domain/javascriptFeatureTraceSchemas.js";
|
|
import { traceJavaScriptSemanticsInputSchema } from "../domain/javascriptSemanticTraceSchemas.js";
|
|
import { compareSourceToBundleInputSchema } from "../domain/sourceToBundleComparisonSchemas.js";
|
|
import { err, ok, type Result } from "../domain/result.js";
|
|
import {
|
|
resolveEvidenceReferences,
|
|
type EvidenceLookup,
|
|
type EvidenceSemanticIdentity,
|
|
} from "./EvidenceReferenceResolver.js";
|
|
|
|
const APPLICATION_GRAPH_IDENTITIES = [
|
|
{
|
|
operation: "analyze_javascript_application",
|
|
predicate: "rea.javascript-application-analysis",
|
|
},
|
|
{
|
|
operation: "reconcile_javascript_runtime",
|
|
predicate: "rea.javascript-runtime-reconciliation",
|
|
},
|
|
{
|
|
operation: "project_managed_application_graph",
|
|
predicate: "rea.managed-application-graph",
|
|
},
|
|
] as const satisfies readonly EvidenceSemanticIdentity[];
|
|
|
|
type TraceInput = z.output<typeof traceApplicationFeatureInputSchema>;
|
|
type SemanticTraceInput = z.output<typeof traceJavaScriptSemanticsInputSchema>;
|
|
type ComparisonInput = z.output<typeof compareApplicationVersionsInputSchema>;
|
|
type ExportShapeComparisonInput = z.output<
|
|
typeof compareJavaScriptExportShapesInputSchema
|
|
>;
|
|
type SourceToBundleInput = z.output<typeof compareSourceToBundleInputSchema>;
|
|
|
|
/** Parse and resolve one trace adapter request into its canonical domain input. */
|
|
export const resolveTraceApplicationFeatureRequest = (
|
|
input: unknown,
|
|
lookup?: EvidenceLookup,
|
|
): Result<TraceInput, AnalysisError> => {
|
|
const parsed = traceApplicationFeatureRequestSchema.safeParse(input);
|
|
return parsed.success
|
|
? resolveTraceApplicationFeatureRequestValidated(parsed.data, lookup)
|
|
: invalid("trace_application_feature", parsed.error, input);
|
|
};
|
|
|
|
/** Resolve a trace request already parsed by the caller-facing contract. */
|
|
export const resolveTraceApplicationFeatureRequestValidated = (
|
|
input: TraceApplicationFeatureRequest,
|
|
lookup?: EvidenceLookup,
|
|
): Result<TraceInput, AnalysisError> => {
|
|
const application = graphEvidence(input, lookup);
|
|
if (!application.ok) return application;
|
|
const native = resolveEvidenceReferences(
|
|
lookup,
|
|
input.native_observation_evidence_ids,
|
|
);
|
|
if (!native.ok) return native;
|
|
const raw = {
|
|
application: application.value,
|
|
native_observations: [...input.native_observations, ...native.value],
|
|
seed: input.seed,
|
|
direction: input.direction,
|
|
};
|
|
const parsed = traceApplicationFeatureInputSchema.safeParse(raw);
|
|
return parsed.success
|
|
? ok(parsed.data)
|
|
: invalid("trace_application_feature", parsed.error, raw);
|
|
};
|
|
|
|
/** Parse and resolve one semantic trace adapter request. */
|
|
export const resolveTraceJavaScriptSemanticsRequest = (
|
|
input: unknown,
|
|
lookup?: EvidenceLookup,
|
|
): Result<SemanticTraceInput, AnalysisError> => {
|
|
const parsed = traceJavaScriptSemanticsRequestSchema.safeParse(input);
|
|
return parsed.success
|
|
? resolveTraceJavaScriptSemanticsRequestValidated(parsed.data, lookup)
|
|
: invalid("trace_javascript_semantics", parsed.error, input);
|
|
};
|
|
|
|
/** Resolve a semantic trace request already parsed by its public contract. */
|
|
export const resolveTraceJavaScriptSemanticsRequestValidated = (
|
|
input: TraceJavaScriptSemanticsRequest,
|
|
lookup?: EvidenceLookup,
|
|
): Result<SemanticTraceInput, AnalysisError> => {
|
|
const application = graphEvidence(input, lookup);
|
|
if (!application.ok) return application;
|
|
const raw = { application: application.value, query: input.query };
|
|
const parsed = traceJavaScriptSemanticsInputSchema.safeParse(raw);
|
|
return parsed.success
|
|
? ok(parsed.data)
|
|
: invalid("trace_javascript_semantics", parsed.error, raw);
|
|
};
|
|
|
|
/** Parse and resolve one comparison adapter request into canonical input. */
|
|
export const resolveCompareApplicationVersionsRequest = (
|
|
input: unknown,
|
|
lookup?: EvidenceLookup,
|
|
): Result<ComparisonInput, AnalysisError> => {
|
|
const parsed = compareApplicationVersionsRequestSchema.safeParse(input);
|
|
return parsed.success
|
|
? resolveCompareApplicationVersionsRequestValidated(parsed.data, lookup)
|
|
: invalid("compare_application_versions", parsed.error, input);
|
|
};
|
|
|
|
/** Resolve a comparison request parsed by the caller-facing contract. */
|
|
export const resolveCompareApplicationVersionsRequestValidated = (
|
|
input: CompareApplicationVersionsRequest,
|
|
lookup?: EvidenceLookup,
|
|
): Result<ComparisonInput, AnalysisError> => {
|
|
const left = resolveApplicationGraphReference(input.left, lookup);
|
|
if (!left.ok) return left;
|
|
const right = resolveApplicationGraphReference(input.right, lookup);
|
|
if (!right.ok) return right;
|
|
const leftNative = resolveEvidenceReferences(
|
|
lookup,
|
|
input.left_native_observation_evidence_ids,
|
|
);
|
|
if (!leftNative.ok) return leftNative;
|
|
const rightNative = resolveEvidenceReferences(
|
|
lookup,
|
|
input.right_native_observation_evidence_ids,
|
|
);
|
|
if (!rightNative.ok) return rightNative;
|
|
const raw = {
|
|
left: left.value,
|
|
right: right.value,
|
|
left_native_observations: [
|
|
...input.left_native_observations,
|
|
...leftNative.value,
|
|
],
|
|
right_native_observations: [
|
|
...input.right_native_observations,
|
|
...rightNative.value,
|
|
],
|
|
};
|
|
const parsed = compareApplicationVersionsInputSchema.safeParse(raw);
|
|
return parsed.success
|
|
? ok(parsed.data)
|
|
: invalid("compare_application_versions", parsed.error, raw);
|
|
};
|
|
|
|
/** Parse and resolve one historical-source comparison adapter request. */
|
|
export const resolveCompareSourceToBundleRequest = (
|
|
input: unknown,
|
|
lookup?: EvidenceLookup,
|
|
): Result<SourceToBundleInput, AnalysisError> => {
|
|
const parsed = compareSourceToBundleRequestSchema.safeParse(input);
|
|
return parsed.success
|
|
? resolveCompareSourceToBundleRequestValidated(parsed.data, lookup)
|
|
: invalid("compare_source_to_bundle", parsed.error, input);
|
|
};
|
|
|
|
/** Resolve a historical-source comparison request parsed by its public contract. */
|
|
export const resolveCompareSourceToBundleRequestValidated = (
|
|
input: CompareSourceToBundleRequest,
|
|
lookup?: EvidenceLookup,
|
|
): Result<SourceToBundleInput, AnalysisError> => {
|
|
const application = graphEvidence(input, lookup);
|
|
if (!application.ok) return application;
|
|
const raw = {
|
|
reference: input.reference,
|
|
application: application.value,
|
|
};
|
|
const parsed = compareSourceToBundleInputSchema.safeParse(raw);
|
|
return parsed.success
|
|
? ok(parsed.data)
|
|
: invalid("compare_source_to_bundle", parsed.error, raw);
|
|
};
|
|
|
|
/** Parse and resolve an export-shape adapter request into canonical input. */
|
|
export const resolveCompareJavaScriptExportShapesRequest = (
|
|
input: unknown,
|
|
lookup?: EvidenceLookup,
|
|
): Result<ExportShapeComparisonInput, AnalysisError> => {
|
|
const parsed = compareJavaScriptExportShapesRequestSchema.safeParse(input);
|
|
return parsed.success
|
|
? resolveCompareJavaScriptExportShapesRequestValidated(parsed.data, lookup)
|
|
: invalid("compare_javascript_export_shapes", parsed.error, input);
|
|
};
|
|
|
|
/** Resolve an export-shape request already parsed by the adapter contract. */
|
|
export const resolveCompareJavaScriptExportShapesRequestValidated = (
|
|
input: CompareJavaScriptExportShapesRequest,
|
|
lookup?: EvidenceLookup,
|
|
): Result<ExportShapeComparisonInput, AnalysisError> => {
|
|
const left = graphEvidence(
|
|
typeof input.left === "string"
|
|
? { application_evidence_id: input.left }
|
|
: { application: input.left },
|
|
lookup,
|
|
);
|
|
if (!left.ok) return left;
|
|
const right = graphEvidence(
|
|
typeof input.right === "string"
|
|
? { application_evidence_id: input.right }
|
|
: { application: input.right },
|
|
lookup,
|
|
);
|
|
if (!right.ok) return right;
|
|
const raw = {
|
|
left: left.value,
|
|
right: right.value,
|
|
left_module_path: input.left_module_path,
|
|
left_export_name: input.left_export_name,
|
|
right_module_path: input.right_module_path,
|
|
right_export_name: input.right_export_name,
|
|
};
|
|
const parsed = compareJavaScriptExportShapesInputSchema.safeParse(raw);
|
|
return parsed.success
|
|
? ok(parsed.data)
|
|
: invalid("compare_javascript_export_shapes", parsed.error, raw);
|
|
};
|
|
|
|
const graphEvidence = (
|
|
source:
|
|
| { readonly application: Evidence }
|
|
| { readonly application_evidence_id: string },
|
|
lookup: EvidenceLookup | undefined,
|
|
) => {
|
|
if ("application" in source) return ok(source.application);
|
|
const resolved = resolveEvidenceReferences(
|
|
lookup,
|
|
[source.application_evidence_id],
|
|
APPLICATION_GRAPH_IDENTITIES,
|
|
);
|
|
return resolved.ok ? ok(resolved.value[0]) : resolved;
|
|
};
|
|
|
|
const resolveApplicationGraphReference = (
|
|
reference: Evidence | string,
|
|
lookup: EvidenceLookup | undefined,
|
|
) =>
|
|
typeof reference === "string"
|
|
? graphEvidence({ application_evidence_id: reference }, lookup)
|
|
: graphEvidence({ application: reference }, lookup);
|
|
|
|
const invalid = <Value>(
|
|
operation: string,
|
|
cause: z.ZodError,
|
|
input: unknown,
|
|
): Result<Value, AnalysisInputError> =>
|
|
err(
|
|
new AnalysisInputError(
|
|
operation,
|
|
undefined,
|
|
projectInputIssues(cause.issues, input),
|
|
),
|
|
);
|