mirror of
https://github.com/morluto/rea
synced 2026-10-27 22:45:19 -04:00
282 lines
10 KiB
TypeScript
282 lines
10 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 { 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/v1",
|
|
},
|
|
{
|
|
operation: "analyze_javascript_application",
|
|
predicate: "rea.javascript-application-analysis/v2",
|
|
},
|
|
{
|
|
operation: "reconcile_javascript_runtime",
|
|
predicate: "rea.javascript-runtime-reconciliation/v1",
|
|
},
|
|
{
|
|
operation: "project_managed_application_graph",
|
|
predicate: "rea.managed-application-graph/v1",
|
|
},
|
|
] 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.application,
|
|
input.application_evidence_id,
|
|
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,
|
|
limits: input.limits,
|
|
};
|
|
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.application,
|
|
input.application_evidence_id,
|
|
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 = graphEvidence(input.left, input.left_evidence_id, lookup);
|
|
if (!left.ok) return left;
|
|
const right = graphEvidence(input.right, input.right_evidence_id, 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,
|
|
],
|
|
limits: input.limits,
|
|
...(input.unknown_registry_approved === undefined
|
|
? {}
|
|
: { unknown_registry_approved: input.unknown_registry_approved }),
|
|
};
|
|
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.application,
|
|
input.application_evidence_id,
|
|
lookup,
|
|
);
|
|
if (!application.ok) return application;
|
|
const raw = {
|
|
reference: input.reference,
|
|
application: application.value,
|
|
limits: input.limits,
|
|
...(input.unknown_registry_approved === undefined
|
|
? {}
|
|
: { unknown_registry_approved: input.unknown_registry_approved }),
|
|
};
|
|
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(input.left, input.left_evidence_id, lookup);
|
|
if (!left.ok) return left;
|
|
const right = graphEvidence(input.right, input.right_evidence_id, 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,
|
|
limits: input.limits,
|
|
...(input.unknown_registry_approved === undefined
|
|
? {}
|
|
: { unknown_registry_approved: input.unknown_registry_approved }),
|
|
};
|
|
const parsed = compareJavaScriptExportShapesInputSchema.safeParse(raw);
|
|
return parsed.success
|
|
? ok(parsed.data)
|
|
: invalid("compare_javascript_export_shapes", parsed.error, raw);
|
|
};
|
|
|
|
const graphEvidence = (
|
|
evidence:
|
|
| TraceApplicationFeatureRequest["application"]
|
|
| TraceJavaScriptSemanticsRequest["application"]
|
|
| CompareApplicationVersionsRequest["left"]
|
|
| CompareJavaScriptExportShapesRequest["left"]
|
|
| CompareSourceToBundleRequest["application"],
|
|
evidenceId: string | undefined,
|
|
lookup: EvidenceLookup | undefined,
|
|
) => {
|
|
if (evidence !== undefined) return ok(evidence);
|
|
const resolved = resolveEvidenceReferences(
|
|
lookup,
|
|
evidenceId === undefined ? [] : [evidenceId],
|
|
APPLICATION_GRAPH_IDENTITIES,
|
|
);
|
|
return resolved.ok ? ok(resolved.value[0]) : resolved;
|
|
};
|
|
|
|
const invalid = <Value>(
|
|
operation: string,
|
|
cause: z.ZodError,
|
|
input: unknown,
|
|
): Result<Value, AnalysisInputError> =>
|
|
err(
|
|
new AnalysisInputError(
|
|
operation,
|
|
undefined,
|
|
projectInputIssues(cause.issues, input),
|
|
),
|
|
);
|