feat(import): resolve references and schema composition
This commit is contained in:
@@ -9,10 +9,10 @@ use serde_json::Value;
|
||||
/// The immutable contract used to normalize an OpenAPI source. These names
|
||||
/// deliberately travel with an import job: changing either contract must not
|
||||
/// silently reinterpret a pending preview.
|
||||
pub const NORMALIZER_VERSION: &str = "normalized-ir-v2";
|
||||
pub const PROJECTION_VERSION: &str = "preview-v2";
|
||||
pub const NORMALIZER_VERSION: &str = "normalized-ir-v3";
|
||||
pub const PROJECTION_VERSION: &str = "preview-v3";
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize)]
|
||||
pub struct SourceDigest(String);
|
||||
|
||||
impl SourceDigest {
|
||||
@@ -97,6 +97,19 @@ pub struct NormalizationConfig {
|
||||
pub max_collection_items: usize,
|
||||
pub max_aliases: usize,
|
||||
pub max_scalar_bytes: usize,
|
||||
/// Maximum number of reference hops followed from one source location.
|
||||
pub max_reference_depth: usize,
|
||||
/// Maximum number of `$ref` occurrences inspected across the bundle.
|
||||
pub max_references: usize,
|
||||
/// Maximum number of immutable external documents supplied to the pure resolver.
|
||||
pub max_reference_documents: usize,
|
||||
/// Maximum number of nodes copied while expanding resolved references.
|
||||
pub max_expanded_nodes: usize,
|
||||
pub max_external_document_bytes: usize,
|
||||
/// Signals that orchestration enabled external fetching. It never permits
|
||||
/// I/O in this crate; it only distinguishes default-deny from a missing or
|
||||
/// rejected supplied snapshot in exact findings.
|
||||
pub external_references_enabled: bool,
|
||||
}
|
||||
|
||||
impl Default for NormalizationConfig {
|
||||
@@ -110,6 +123,12 @@ impl Default for NormalizationConfig {
|
||||
max_collection_items: 10_000,
|
||||
max_aliases: 128,
|
||||
max_scalar_bytes: 256 * 1024,
|
||||
max_reference_depth: 32,
|
||||
max_references: 4_096,
|
||||
max_reference_documents: 32,
|
||||
max_expanded_nodes: 100_000,
|
||||
max_external_document_bytes: 256 * 1024,
|
||||
external_references_enabled: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -139,6 +158,38 @@ pub struct UnresolvedReference {
|
||||
pub location: SourceLocation,
|
||||
}
|
||||
|
||||
/// Immutable external input for the pure reference resolver. The caller owns
|
||||
/// URL policy and I/O; `crank-import` only consumes already verified bytes.
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct ExternalDocumentSnapshot {
|
||||
pub canonical_uri: String,
|
||||
pub digest: SourceDigest,
|
||||
pub document: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct ResolvedReferenceNode {
|
||||
pub snapshot_digest: SourceDigest,
|
||||
pub location: SourceLocation,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct ResolvedReferenceEdge {
|
||||
pub source: ResolvedReferenceNode,
|
||||
pub target: ResolvedReferenceNode,
|
||||
pub recursive: bool,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct ResolvedReferenceGraph {
|
||||
/// Sorted, deduplicated immutable dependency identities. Canonical URLs
|
||||
/// deliberately do not enter the IR or public diagnostics.
|
||||
#[serde(default)]
|
||||
pub dependency_digests: Vec<SourceDigest>,
|
||||
#[serde(default)]
|
||||
pub edges: Vec<ResolvedReferenceEdge>,
|
||||
}
|
||||
|
||||
/// An unresolved `$ref` preserved from the decoded source. This is deliberately
|
||||
/// broader than schema references: path items, reusable parameters and other
|
||||
/// object-level references remain available to a later resolution phase.
|
||||
@@ -213,9 +264,34 @@ pub struct NormalizedSchema {
|
||||
pub location: SourceLocation,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub description: Option<String>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub discriminator: Option<NormalizedDiscriminator>,
|
||||
#[serde(default)]
|
||||
pub constraints: NormalizedSchemaConstraints,
|
||||
pub kind: NormalizedSchemaKind,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
|
||||
pub struct NormalizedSchemaConstraints {
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub minimum: Option<f64>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub maximum: Option<f64>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub min_length: Option<u64>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub max_length: Option<u64>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub pattern: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct NormalizedDiscriminator {
|
||||
pub property_name: String,
|
||||
#[serde(default)]
|
||||
pub mapping: BTreeMap<String, String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "snake_case", tag = "type")]
|
||||
pub enum NormalizedSchemaKind {
|
||||
@@ -280,6 +356,8 @@ pub struct NormalizedIr {
|
||||
pub paths: Vec<NormalizedPath>,
|
||||
#[serde(default)]
|
||||
pub unresolved_references: Vec<NormalizedReference>,
|
||||
#[serde(default)]
|
||||
pub reference_graph: ResolvedReferenceGraph,
|
||||
pub source: ImportSourcePreview,
|
||||
#[serde(default)]
|
||||
pub operations: Vec<NormalizedOperation>,
|
||||
@@ -416,7 +494,7 @@ fn empty_source_location() -> SourceLocation {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum RestParameterLocation {
|
||||
Path,
|
||||
|
||||
Reference in New Issue
Block a user