ask-schema 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/lib/ask-schema.rb ADDED
@@ -0,0 +1,176 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "ask/schema/version"
4
+ require_relative "ask/schema/errors"
5
+ require_relative "ask/schema/helpers"
6
+ require_relative "ask/schema/validator"
7
+ require_relative "ask/schema/dsl"
8
+ require_relative "ask/schema/json_output"
9
+ require "json"
10
+
11
+ module Ask
12
+ # Build standards-compliant JSON Schema documents using a compact Ruby DSL.
13
+ #
14
+ # Supports both block-based and class-based usage patterns, with full support
15
+ # for JSON Schema Draft 07/2020-12 features including composition, conditionals,
16
+ # definitions, and validation.
17
+ #
18
+ # @example Block-based DSL
19
+ # schema = Ask::Schema.create do
20
+ # string :name, description: "Full name"
21
+ # integer :age, minimum: 0
22
+ # end
23
+ # schema.new("user").to_json_schema
24
+ #
25
+ # @example Class-based DSL
26
+ # class Product < Ask::Schema
27
+ # string :name, description: "Product name"
28
+ # number :price
29
+ # end
30
+ # Product.new("product").to_json_schema
31
+ class Schema
32
+ extend DSL
33
+ include JsonOutput
34
+
35
+ # Primitive JSON Schema types available in the DSL.
36
+ PRIMITIVE_TYPES = %i[string number integer boolean null].freeze
37
+
38
+ class << self
39
+ # Create a new Schema subclass from a DSL block.
40
+ #
41
+ # @param block [Proc] DSL block with type definitions
42
+ # @return [Class<Schema>] A dynamically-created Schema subclass
43
+ #
44
+ # @example
45
+ # schema = Ask::Schema.create do
46
+ # string :name
47
+ # integer :age
48
+ # end
49
+ def create(&block)
50
+ schema_class = Class.new(Schema)
51
+ schema_class.class_eval(&block)
52
+ schema_class
53
+ end
54
+
55
+ # Properties defined on this schema class (inheritable).
56
+ #
57
+ # @return [Hash{Symbol => Hash}] Property definitions keyed by name
58
+ def properties
59
+ @properties ||= {}
60
+ end
61
+
62
+ # Required property names for this schema class (inheritable).
63
+ #
64
+ # @return [Array<Symbol>] Required property names
65
+ def required_properties
66
+ @required_properties ||= []
67
+ end
68
+
69
+ # Named sub-schema definitions for `$defs`.
70
+ #
71
+ # @return [Hash{Symbol => Hash}] Named definitions keyed by symbol
72
+ def definitions
73
+ @definitions ||= {}
74
+ end
75
+
76
+ # Set or get the schema name used in JSON output.
77
+ #
78
+ # @param name [String, nil] The schema name
79
+ # @return [String, nil] The current schema name
80
+ def name(name = nil)
81
+ @schema_name = name if name
82
+ return @schema_name if defined?(@schema_name)
83
+
84
+ super()
85
+ end
86
+
87
+ # Set or get the schema description used in JSON output.
88
+ #
89
+ # @param description [String, nil] The schema description
90
+ # @return [String, nil] The current description
91
+ def description(description = nil)
92
+ @description = description if description
93
+ @description
94
+ end
95
+
96
+ # Set or get whether additional (undeclared) properties are allowed.
97
+ #
98
+ # @param value [Boolean, nil] True to allow additional properties
99
+ # @return [Boolean] Defaults to +false+
100
+ def additional_properties(value = nil)
101
+ return @additional_properties ||= false if value.nil?
102
+
103
+ @additional_properties = value
104
+ end
105
+
106
+ # Set or get strict mode for the schema.
107
+ #
108
+ # When strict, the schema includes `"strict": true` in output.
109
+ #
110
+ # @param args [Boolean, nil] The strict mode value
111
+ # @return [Boolean] Defaults to +true+
112
+ def strict(*args)
113
+ if args.empty?
114
+ instance_variable_defined?(:@strict) ? @strict : true
115
+ else
116
+ @strict = args.first
117
+ end
118
+ end
119
+
120
+ # Validate the schema definition, raising on circular references or other errors.
121
+ #
122
+ # @return [nil] if the schema is valid
123
+ # @raise [ValidationError] if the schema has circular references
124
+ def validate!
125
+ validator = Validator.new(self)
126
+ validator.validate!
127
+ end
128
+
129
+ # Check if the schema definition is valid.
130
+ #
131
+ # @return [Boolean] true if the schema has no validation errors
132
+ def valid?
133
+ validator = Validator.new(self)
134
+ validator.valid?
135
+ end
136
+ end
137
+
138
+ # Create a new schema instance.
139
+ #
140
+ # @param name [String, nil] Instance name (overrides class name in JSON output)
141
+ # @param description [String, nil] Instance description (overrides class description)
142
+ def initialize(name = nil, description: nil)
143
+ @name = name || self.class.name || "Schema"
144
+ @description = description
145
+ end
146
+
147
+ # Validate this schema instance.
148
+ #
149
+ # @return [nil] if valid
150
+ # @raise [ValidationError] if invalid
151
+ def validate!
152
+ self.class.validate!
153
+ end
154
+
155
+ # Check if this schema instance is valid.
156
+ #
157
+ # @return [Boolean]
158
+ def valid?
159
+ self.class.valid?
160
+ end
161
+
162
+ # Delegate DSL methods (string, number, integer, etc.) to the class level.
163
+ def method_missing(method_name, ...)
164
+ if respond_to_missing?(method_name)
165
+ self.class.send(method_name, ...)
166
+ else
167
+ super
168
+ end
169
+ end
170
+
171
+ # Check if a method can be delegated to the class level.
172
+ def respond_to_missing?(method_name, include_private = false)
173
+ %i[string number integer boolean array object any_of one_of null].include?(method_name) || super
174
+ end
175
+ end
176
+ end
metadata ADDED
@@ -0,0 +1,97 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ask-schema
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Kaka Ruto
8
+ bindir: bin
9
+ cert_chain: []
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: minitest
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - "~>"
17
+ - !ruby/object:Gem::Version
18
+ version: '5.25'
19
+ type: :development
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - "~>"
24
+ - !ruby/object:Gem::Version
25
+ version: '5.25'
26
+ - !ruby/object:Gem::Dependency
27
+ name: mocha
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - "~>"
31
+ - !ruby/object:Gem::Version
32
+ version: '3.1'
33
+ type: :development
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '3.1'
40
+ - !ruby/object:Gem::Dependency
41
+ name: rake
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: '13.0'
47
+ type: :development
48
+ prerelease: false
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '13.0'
54
+ description: A compact Ruby DSL for building standards-oriented JSON Schema documents.
55
+ Zero dependencies.
56
+ email:
57
+ - kaka@myrrlabs.com
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - LICENSE
63
+ - README.md
64
+ - lib/ask-schema.rb
65
+ - lib/ask/schema/dsl.rb
66
+ - lib/ask/schema/dsl/complex_types.rb
67
+ - lib/ask/schema/dsl/conditionals.rb
68
+ - lib/ask/schema/dsl/primitive_types.rb
69
+ - lib/ask/schema/dsl/schema_builders.rb
70
+ - lib/ask/schema/dsl/utilities.rb
71
+ - lib/ask/schema/errors.rb
72
+ - lib/ask/schema/helpers.rb
73
+ - lib/ask/schema/json_output.rb
74
+ - lib/ask/schema/validator.rb
75
+ - lib/ask/schema/version.rb
76
+ homepage: https://github.com/ask-rb/ask-schema
77
+ licenses:
78
+ - MIT
79
+ metadata: {}
80
+ rdoc_options: []
81
+ require_paths:
82
+ - lib
83
+ required_ruby_version: !ruby/object:Gem::Requirement
84
+ requirements:
85
+ - - ">="
86
+ - !ruby/object:Gem::Version
87
+ version: '3.2'
88
+ required_rubygems_version: !ruby/object:Gem::Requirement
89
+ requirements:
90
+ - - ">="
91
+ - !ruby/object:Gem::Version
92
+ version: '0'
93
+ requirements: []
94
+ rubygems_version: 4.0.3
95
+ specification_version: 4
96
+ summary: JSON Schema DSL for Ruby
97
+ test_files: []