Class: JekyllOpenAPI::Schema
- Inherits:
-
Object
- Object
- JekyllOpenAPI::Schema
- Defined in:
- lib/jekyll_openapi/schema.rb
Overview
Normalized, ref-aware view over a JSON-Schema node, shared by every schema renderer.
It centralises the two things that used to be copy-pasted (and drift) across
the TypeScript and XML renderers: the type inference that fills in an
omitted type, and the $ref following with cycle detection. A new
renderer (JSON example, HTML, …) implements formatting only — it never walks
raw hashes or re-infers types.
Schemas are immutable and carry the set of $ref pointers already followed
on the current path (seen), so following a self-referential schema stops
instead of looping, while genuine reuse (the same schema in two branches)
is never mistaken for a cycle.
Constant Summary collapse
- CYCLE =
Sentinel returned by #follow when a
$refpoints back onto the path. :cycle
Instance Attribute Summary collapse
-
#seen ⇒ Object
readonly
Returns the value of attribute seen.
Class Method Summary collapse
Instance Method Summary collapse
-
#[](key) ⇒ Object
Raw read, delegating through a Reference transparently.
-
#additional_properties ⇒ Schema?
The additionalProperties schema, only when it is a schema object (the boolean
true/falseforms carry no shape to render). -
#composition ⇒ Array(String, Array<Schema>)?
E.g.
-
#declared_type ⇒ Object
--- type ----------------------------------------------------------------.
- #description ⇒ Object
- #dig(*keys) ⇒ Object
-
#enum ⇒ Object
--- leaf metadata -------------------------------------------------------.
- #example ⇒ Object
- #examples ⇒ Object
-
#follow ⇒ Schema
Follow a
$refone hop. - #format ⇒ Object
-
#initialize(node, seen = []) ⇒ Schema
constructor
A new instance of Schema.
-
#items ⇒ Object
--- array ---------------------------------------------------------------.
-
#mapping? ⇒ Boolean
Whether this wraps something readable as a schema object.
-
#name ⇒ Object
Component name of a local ref, e.g.
-
#named_reference? ⇒ Boolean
A local $ref to a named component — the kind an HTML renderer links to rather than inlines.
-
#override_description ⇒ Object
The use-site description sitting beside a $ref (a 3.1 sibling override), if any.
- #pattern ⇒ Object
-
#properties ⇒ Object
--- object --------------------------------------------------------------.
- #raw ⇒ Object
-
#raw_reference? ⇒ Boolean
A plain
{"$ref" => "..."}hash that never went through the Dereferencer. -
#ref ⇒ Object
The raw pointer string, e.g.
-
#reference? ⇒ Boolean
A $ref node — either a linked Reference (produced by the Dereferencer) or a raw, un-dereferenced
{"$ref" => "..."}hash. - #required?(key) ⇒ Boolean
- #summary ⇒ Object
-
#type ⇒ Object
Single inferred type, mirroring what most tooling assumes when
typeis omitted. - #type_union? ⇒ Boolean
-
#with_type(single) ⇒ Object
A copy of this schema with
typepinned to one member of a type union. - #xml ⇒ Object
Constructor Details
#initialize(node, seen = []) ⇒ Schema
Returns a new instance of Schema.
29 30 31 32 |
# File 'lib/jekyll_openapi/schema.rb', line 29 def initialize(node, seen = []) @node = node @seen = seen end |
Instance Attribute Details
#seen ⇒ Object (readonly)
Returns the value of attribute seen.
27 28 29 |
# File 'lib/jekyll_openapi/schema.rb', line 27 def seen @seen end |
Class Method Details
.wrap(node, seen = []) ⇒ Object
23 24 25 |
# File 'lib/jekyll_openapi/schema.rb', line 23 def self.wrap(node, seen = []) node.is_a?(Schema) ? node : new(node, seen) end |
Instance Method Details
#[](key) ⇒ Object
Raw read, delegating through a Reference transparently.
101 102 103 |
# File 'lib/jekyll_openapi/schema.rb', line 101 def [](key) mapping? ? @node[key] : nil end |
#additional_properties ⇒ Schema?
Returns the additionalProperties schema, only when it is a
schema object (the boolean true/false forms carry no shape to render).
160 161 162 163 |
# File 'lib/jekyll_openapi/schema.rb', line 160 def additional_properties value = self["additionalProperties"] value.is_a?(Hash) || value.is_a?(Reference) ? child(value) : nil end |
#composition ⇒ Array(String, Array<Schema>)?
Returns e.g. ["oneOf", [Schema, ...]].
112 113 114 115 116 117 118 |
# File 'lib/jekyll_openapi/schema.rb', line 112 def composition %w[oneOf anyOf allOf].each do |keyword| members = self[keyword] return [keyword, members.map { |m| child(m) }] if members.is_a?(Array) end nil end |
#declared_type ⇒ Object
--- type ----------------------------------------------------------------
122 123 124 |
# File 'lib/jekyll_openapi/schema.rb', line 122 def declared_type self["type"] end |
#description ⇒ Object
177 |
# File 'lib/jekyll_openapi/schema.rb', line 177 def description = self["description"] |
#dig(*keys) ⇒ Object
105 106 107 |
# File 'lib/jekyll_openapi/schema.rb', line 105 def dig(*keys) mapping? ? @node.dig(*keys) : nil end |
#enum ⇒ Object
--- leaf metadata -------------------------------------------------------
173 |
# File 'lib/jekyll_openapi/schema.rb', line 173 def enum = self["enum"] |
#example ⇒ Object
178 |
# File 'lib/jekyll_openapi/schema.rb', line 178 def example = self["example"] |
#examples ⇒ Object
179 |
# File 'lib/jekyll_openapi/schema.rb', line 179 def examples = self["examples"] |
#follow ⇒ Schema
Follow a $ref one hop.
92 93 94 95 96 97 98 |
# File 'lib/jekyll_openapi/schema.rb', line 92 def follow return self unless reference? pointer = ref return CYCLE if @seen.include?(pointer) target = @node.is_a?(Reference) ? @node.resolve : nil target.nil? ? nil : Schema.new(target, @seen + [pointer]) end |
#format ⇒ Object
174 |
# File 'lib/jekyll_openapi/schema.rb', line 174 def format = self["format"] |
#items ⇒ Object
--- array ---------------------------------------------------------------
167 168 169 |
# File 'lib/jekyll_openapi/schema.rb', line 167 def items child(self["items"]) end |
#mapping? ⇒ Boolean
Whether this wraps something readable as a schema object.
39 40 41 |
# File 'lib/jekyll_openapi/schema.rb', line 39 def mapping? @node.is_a?(Hash) || @node.is_a?(Reference) end |
#name ⇒ Object
Component name of a local ref, e.g. "Pet" for "#/components/schemas/Pet"; nil for external refs or non-refs. Derived from the pointer alone, so it needs no dereferencing.
67 68 69 70 71 |
# File 'lib/jekyll_openapi/schema.rb', line 67 def name pointer = ref return nil unless pointer.is_a?(String) && pointer.start_with?("#") JSONPointer.unescape(pointer.delete_prefix("#").split("/").last) end |
#named_reference? ⇒ Boolean
A local $ref to a named component — the kind an HTML renderer links to rather than inlines. External refs (no local name) return false.
75 76 77 |
# File 'lib/jekyll_openapi/schema.rb', line 75 def named_reference? reference? && !name.nil? end |
#override_description ⇒ Object
The use-site description sitting beside a $ref (a 3.1 sibling override), if any. Lets a renderer annotate a link without expanding its target.
81 82 83 84 85 |
# File 'lib/jekyll_openapi/schema.rb', line 81 def override_description return @node.overrides["description"] if @node.is_a?(Reference) return @node["description"] if raw_reference? nil end |
#pattern ⇒ Object
175 |
# File 'lib/jekyll_openapi/schema.rb', line 175 def pattern = self["pattern"] |
#properties ⇒ Object
--- object --------------------------------------------------------------
150 151 152 |
# File 'lib/jekyll_openapi/schema.rb', line 150 def properties (self["properties"] || {}).map { |key, node| [key, child(node)] } end |
#raw ⇒ Object
34 35 36 |
# File 'lib/jekyll_openapi/schema.rb', line 34 def raw @node end |
#raw_reference? ⇒ Boolean
A plain {"$ref" => "..."} hash that never went through the Dereferencer.
53 54 55 |
# File 'lib/jekyll_openapi/schema.rb', line 53 def raw_reference? @node.is_a?(Hash) && @node["$ref"].is_a?(String) end |
#ref ⇒ Object
The raw pointer string, e.g. "#/components/schemas/Pet"; nil when not a ref.
58 59 60 61 62 |
# File 'lib/jekyll_openapi/schema.rb', line 58 def ref return @node.ref if @node.is_a?(Reference) return @node["$ref"] if raw_reference? nil end |
#reference? ⇒ Boolean
A $ref node — either a linked Reference (produced by the Dereferencer)
or a raw, un-dereferenced {"$ref" => "..."} hash. Link-mode rendering
only needs the pointer string, so it works on either form (see #ref/#name);
following a ref to inline its target still requires a linked Reference
(a raw ref carries no root to resolve against — see #follow).
48 49 50 |
# File 'lib/jekyll_openapi/schema.rb', line 48 def reference? @node.is_a?(Reference) || raw_reference? end |
#required?(key) ⇒ Boolean
154 155 156 |
# File 'lib/jekyll_openapi/schema.rb', line 154 def required?(key) Array(self["required"]).include?(key) end |
#summary ⇒ Object
176 |
# File 'lib/jekyll_openapi/schema.rb', line 176 def summary = self["summary"] |
#type ⇒ Object
Single inferred type, mirroring what most tooling assumes when type is
omitted. Returns nil for a type union (see #type_union?) or the unknown.
132 133 134 135 136 137 138 139 140 |
# File 'lib/jekyll_openapi/schema.rb', line 132 def type declared = declared_type return declared if declared.is_a?(String) return nil if declared.is_a?(Array) return "object" if self["properties"] || self["additionalProperties"] return "array" if self["items"] return "string" if self["enum"] nil end |
#type_union? ⇒ Boolean
126 127 128 |
# File 'lib/jekyll_openapi/schema.rb', line 126 def type_union? declared_type.is_a?(Array) end |
#with_type(single) ⇒ Object
A copy of this schema with type pinned to one member of a type union.
143 144 145 146 |
# File 'lib/jekyll_openapi/schema.rb', line 143 def with_type(single) node = @node.is_a?(Hash) ? @node.merge("type" => single) : @node Schema.new(node, @seen) end |
#xml ⇒ Object
180 |
# File 'lib/jekyll_openapi/schema.rb', line 180 def xml = self["xml"] || {} |