odata_duty 0.30.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.
- checksums.yaml +7 -0
- data/README.md +312 -0
- data/lib/generators/odata_duty/entity_set/entity_set_generator.rb +56 -0
- data/lib/generators/odata_duty/entity_set/templates/entity_set.rb.erb +20 -0
- data/lib/generators/odata_duty/entity_set/templates/entity_set_spec.rb.erb +38 -0
- data/lib/generators/odata_duty/entity_set/templates/entity_type.rb.erb +6 -0
- data/lib/generators/odata_duty/entity_set/templates/entity_type_spec.rb.erb +20 -0
- data/lib/generators/odata_duty/entity_set/templates/odata_active_record_concern.rb.erb +109 -0
- data/lib/generators/odata_duty/entity_set/templates/resolver.rb.erb +39 -0
- data/lib/generators/odata_duty/entity_set/templates/resolver_spec.rb.erb +50 -0
- data/lib/generators/odata_duty/install/install_generator.rb +60 -0
- data/lib/generators/odata_duty/install/templates/controller.rb.tt +43 -0
- data/lib/generators/odata_duty/install/templates/schema.rb.tt +16 -0
- data/lib/metadata.xml.erb +116 -0
- data/lib/odata_duty/complex_type.rb +70 -0
- data/lib/odata_duty/context_wrapper.rb +26 -0
- data/lib/odata_duty/create_complex_type_hash_wrapper.rb +49 -0
- data/lib/odata_duty/dynamic_object_wrapper.rb.erb +79 -0
- data/lib/odata_duty/edms.rb +122 -0
- data/lib/odata_duty/edmx_schema.rb +19 -0
- data/lib/odata_duty/entity_type.rb +72 -0
- data/lib/odata_duty/enum_type.rb +71 -0
- data/lib/odata_duty/errors.rb +52 -0
- data/lib/odata_duty/executor.rb +277 -0
- data/lib/odata_duty/filter.rb +76 -0
- data/lib/odata_duty/filter_predicate.rb +12 -0
- data/lib/odata_duty/mapper_builder.rb +86 -0
- data/lib/odata_duty/mcp_input_schemas.rb +59 -0
- data/lib/odata_duty/mcp_server_builder.rb +107 -0
- data/lib/odata_duty/oas2/collection_get_path.rb +97 -0
- data/lib/odata_duty/oas2/collection_post_path.rb +63 -0
- data/lib/odata_duty/oas2/individual_delete_path.rb +42 -0
- data/lib/odata_duty/oas2/individual_get_path.rb +37 -0
- data/lib/odata_duty/oas2/individual_patch_path.rb +63 -0
- data/lib/odata_duty/oas2.rb +113 -0
- data/lib/odata_duty/parslet_search_expression.rb +163 -0
- data/lib/odata_duty/property/collection_prop.rb +25 -0
- data/lib/odata_duty/property/single_prop.rb +131 -0
- data/lib/odata_duty/property.rb +49 -0
- data/lib/odata_duty/railtie.rb +11 -0
- data/lib/odata_duty/schema_builder/complex_type.rb +34 -0
- data/lib/odata_duty/schema_builder/container.rb +16 -0
- data/lib/odata_duty/schema_builder/data_type.rb +18 -0
- data/lib/odata_duty/schema_builder/endpoint.rb +117 -0
- data/lib/odata_duty/schema_builder/entity_set.rb +67 -0
- data/lib/odata_duty/schema_builder/entity_type.rb +49 -0
- data/lib/odata_duty/schema_builder/enum_type.rb +32 -0
- data/lib/odata_duty/schema_builder.rb +130 -0
- data/lib/odata_duty/set_resolver.rb +51 -0
- data/lib/odata_duty.rb +311 -0
- metadata +168 -0
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
module OdataDuty
|
|
2
|
+
class SetResolver
|
|
3
|
+
attr_reader :context
|
|
4
|
+
|
|
5
|
+
def initialize(context:, init_args:)
|
|
6
|
+
@context = context
|
|
7
|
+
return unless respond_to?(:od_after_init)
|
|
8
|
+
|
|
9
|
+
begin
|
|
10
|
+
call_od_after_init(init_args)
|
|
11
|
+
rescue InitArgsMismatchError => e
|
|
12
|
+
e.backtrace.insert(1, entity_set._defined_at_)
|
|
13
|
+
raise
|
|
14
|
+
rescue StandardError => e
|
|
15
|
+
e.backtrace.insert(2, entity_set._defined_at_)
|
|
16
|
+
raise
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def od_next_link_skiptoken(token = nil)
|
|
21
|
+
@od_next_link_skiptoken = token.to_s if token
|
|
22
|
+
@od_next_link_skiptoken
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
private
|
|
26
|
+
|
|
27
|
+
def call_od_after_init(init_args)
|
|
28
|
+
case init_args
|
|
29
|
+
when nil then od_after_init
|
|
30
|
+
when Hash then od_after_init(**init_args)
|
|
31
|
+
when Array then od_after_init(*init_args)
|
|
32
|
+
else od_after_init(init_args)
|
|
33
|
+
end
|
|
34
|
+
rescue ArgumentError => e
|
|
35
|
+
handle_init_args_error(e)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def handle_init_args_error(arg_error)
|
|
39
|
+
raise unless arg_error.backtrace.first.include?("od_after_init'")
|
|
40
|
+
|
|
41
|
+
err = InitArgsMismatchError.new(arg_error)
|
|
42
|
+
err.set_backtrace(arg_error.backtrace)
|
|
43
|
+
|
|
44
|
+
raise err
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def entity_set
|
|
48
|
+
context.endpoint.entity_set
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
data/lib/odata_duty.rb
ADDED
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
require 'odata_duty/errors'
|
|
2
|
+
require 'odata_duty/set_resolver'
|
|
3
|
+
require 'odata_duty/schema_builder'
|
|
4
|
+
require 'odata_duty/edmx_schema'
|
|
5
|
+
require 'odata_duty/executor'
|
|
6
|
+
require 'odata_duty/mcp_server_builder'
|
|
7
|
+
require 'odata_duty/oas2'
|
|
8
|
+
require 'odata_duty/property'
|
|
9
|
+
require 'odata_duty/enum_type'
|
|
10
|
+
require 'odata_duty/complex_type'
|
|
11
|
+
require 'odata_duty/entity_type'
|
|
12
|
+
require 'odata_duty/filter'
|
|
13
|
+
require 'odata_duty/filter_predicate'
|
|
14
|
+
require 'odata_duty/create_complex_type_hash_wrapper'
|
|
15
|
+
# :nocov: Rails is not loaded when this file is required in the test suite
|
|
16
|
+
require 'odata_duty/railtie' if defined?(Rails::Railtie)
|
|
17
|
+
# :nocov:
|
|
18
|
+
|
|
19
|
+
module OdataDuty
|
|
20
|
+
class EntitySet
|
|
21
|
+
def self.entity_type(entity_type = nil)
|
|
22
|
+
@entity_type = entity_type if entity_type
|
|
23
|
+
@entity_type
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def self.name(name = nil)
|
|
27
|
+
@name = name.to_s if name.is_a?(Symbol)
|
|
28
|
+
@name = name.to_str if name && !name.is_a?(Symbol)
|
|
29
|
+
@name
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def self.url(url = nil)
|
|
33
|
+
@url = url.to_s if url.is_a?(Symbol)
|
|
34
|
+
@url = url.to_str if url && !url.is_a?(Symbol)
|
|
35
|
+
@url
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
class Metadata
|
|
39
|
+
attr_reader :entity_set
|
|
40
|
+
|
|
41
|
+
def initialize(entity_set)
|
|
42
|
+
@entity_set = entity_set
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def metadata_types
|
|
46
|
+
[entity_type].map(&:__metadata).flat_map(&:metadata_types)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def name
|
|
50
|
+
entity_set.name ||
|
|
51
|
+
entity_set.to_s.split('::').last.sub(/EntitySet\z/, '').sub(/Set\z/, '')
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def entity_type
|
|
55
|
+
entity_set.entity_type
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def entity_type_name
|
|
59
|
+
entity_type.__metadata.name
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def kind
|
|
63
|
+
'EntitySet'
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def url
|
|
67
|
+
entity_set.url || name
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def new_entity_set(context:)
|
|
71
|
+
entity_set.new(context: context)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def collection(set_builder, context:, selected:)
|
|
75
|
+
begin
|
|
76
|
+
values = set_builder.collection
|
|
77
|
+
rescue NoMethodError
|
|
78
|
+
raise NoImplementationError, "collection not implemented for #{entity_set}"
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
mapper = entity_type.mapper(context, selected: selected)
|
|
82
|
+
|
|
83
|
+
values.map { |v| mapper.obj_to_hash(v, context) }
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def individual(set_builder, id, context:, selected:)
|
|
87
|
+
begin
|
|
88
|
+
result = set_builder.individual(converted_id(id))
|
|
89
|
+
rescue NoMethodError
|
|
90
|
+
raise NoImplementationError, "individual not implemented for #{entity_set}"
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
raise ResourceNotFoundError, "No such entity #{id}" unless result
|
|
94
|
+
|
|
95
|
+
entity_type.mapper(context, selected: selected).obj_to_hash(result, context)
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def create(context:)
|
|
99
|
+
wrapper = CreateComplexTypeHashWrapper.new(context.query_options, entity_type,
|
|
100
|
+
operation: :create, context: context)
|
|
101
|
+
result = entity_set.new(context: context)
|
|
102
|
+
.create(wrapper)
|
|
103
|
+
mapper = entity_type.mapper(context, selected: nil)
|
|
104
|
+
mapper.obj_to_hash(result, context)
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def update(id, context:)
|
|
108
|
+
wrapper = CreateComplexTypeHashWrapper.new(context.query_options, entity_type,
|
|
109
|
+
operation: :update, context: context)
|
|
110
|
+
result = entity_set.new(context: context).update(converted_id(id), wrapper)
|
|
111
|
+
raise ResourceNotFoundError, "No such entity #{id}" unless result
|
|
112
|
+
|
|
113
|
+
entity_type.mapper(context, selected: nil).obj_to_hash(result, context)
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def delete(id, context:)
|
|
117
|
+
result = entity_set.new(context: context).delete(converted_id(id))
|
|
118
|
+
raise ResourceNotFoundError, "No such entity #{id}" unless result
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def supports_search?
|
|
122
|
+
# Check if the entity set class supports search by looking for the od_search method
|
|
123
|
+
entity_set.method_defined?(:od_search)
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def supports_filter_or?
|
|
127
|
+
entity_set.method_defined?(:od_filter_or)
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def supports_collection?
|
|
131
|
+
# Check if the entity set class supports read by looking for the collection method
|
|
132
|
+
entity_set.method_defined?(:collection)
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def supports_individual?
|
|
136
|
+
# Check if the entity set class supports read-by-id via the individual method
|
|
137
|
+
entity_set.method_defined?(:individual)
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
def supports_count?
|
|
141
|
+
# Check if the entity set class supports counting via the count method
|
|
142
|
+
entity_set.method_defined?(:count)
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
def supports_create?
|
|
146
|
+
# Check if the entity set class supports create by looking for the create method
|
|
147
|
+
entity_set.method_defined?(:create)
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
def supports_update?
|
|
151
|
+
# Check if the entity set class supports update by looking for the update method
|
|
152
|
+
entity_set.method_defined?(:update)
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
def supports_delete?
|
|
156
|
+
# Check if the entity set class supports delete by looking for the delete method
|
|
157
|
+
entity_set.method_defined?(:delete)
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
def non_insertable_property_names
|
|
161
|
+
@non_insertable_property_names ||=
|
|
162
|
+
entity_type.properties.select(&:non_insertable?).map(&:name)
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
private
|
|
166
|
+
|
|
167
|
+
def converted_id(id)
|
|
168
|
+
entity_type.property_refs.first.convert(id, nil)
|
|
169
|
+
rescue OdataDuty::InvalidValue => e
|
|
170
|
+
raise InvalidPropertyReferenceValue, "Invalid individual id : #{e}"
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
def self.__metadata
|
|
175
|
+
Metadata.new(self)
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
attr_reader :context
|
|
179
|
+
|
|
180
|
+
def initialize(context:)
|
|
181
|
+
@context = context
|
|
182
|
+
od_after_init
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
def od_after_init; end
|
|
186
|
+
|
|
187
|
+
def od_next_link_skiptoken(token = nil)
|
|
188
|
+
@od_next_link_skiptoken = token.to_s if token
|
|
189
|
+
@od_next_link_skiptoken
|
|
190
|
+
end
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
class Schema
|
|
194
|
+
def self.namespace(name = nil)
|
|
195
|
+
@namespace = name if name
|
|
196
|
+
@namespace
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
def self.version(name = nil)
|
|
200
|
+
@version = name if name
|
|
201
|
+
@version
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
def self.title(name = nil)
|
|
205
|
+
@title = name if name
|
|
206
|
+
@title
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
def self.entity_sets(entity_sets = nil)
|
|
210
|
+
@entity_sets = entity_sets.uniq if entity_sets
|
|
211
|
+
@entity_sets
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
def self.base_url(url = nil)
|
|
215
|
+
@base_url = url if url
|
|
216
|
+
@base_url
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
class Metadata
|
|
220
|
+
attr_reader :schema
|
|
221
|
+
|
|
222
|
+
def initialize(schema)
|
|
223
|
+
@schema = schema
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
def version = schema.version
|
|
227
|
+
def title = schema.title
|
|
228
|
+
|
|
229
|
+
def namespace
|
|
230
|
+
schema.namespace
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
def entity_sets
|
|
234
|
+
schema.entity_sets.map(&:__metadata)
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
def metadata_types
|
|
238
|
+
@metadata_types ||= entity_sets.flat_map(&:metadata_types).uniq.map(&:__metadata)
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
def entity_types
|
|
242
|
+
metadata_types.select { |mt| mt.metadata_type == :entity }
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
def complex_types
|
|
246
|
+
metadata_types.select { |mt| mt.metadata_type == :complex }
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
def enum_types
|
|
250
|
+
metadata_types.select { |mt| mt.metadata_type == :enum }
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
def endpoints
|
|
254
|
+
entity_sets
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
def check_names
|
|
258
|
+
names = Set.new
|
|
259
|
+
(enum_types + complex_types + entity_types).each do |et|
|
|
260
|
+
raise "Duplicate #{et.name} type" if names.include?(et.name)
|
|
261
|
+
|
|
262
|
+
names << et.name
|
|
263
|
+
end
|
|
264
|
+
end
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
def self.__metadata
|
|
268
|
+
Metadata.new(self)
|
|
269
|
+
end
|
|
270
|
+
|
|
271
|
+
def self.metadata_xml
|
|
272
|
+
metadata = __metadata
|
|
273
|
+
metadata.check_names
|
|
274
|
+
|
|
275
|
+
ERB.new(File.read("#{__dir__}/metadata.xml.erb")).result(binding)
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
def self.index_hash(metadata_url)
|
|
279
|
+
{
|
|
280
|
+
'@odata.context': metadata_url,
|
|
281
|
+
value: endpoints.map do |e|
|
|
282
|
+
{ name: e.name, kind: e.kind, url: e.url }
|
|
283
|
+
end
|
|
284
|
+
}
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
def self.endpoints
|
|
288
|
+
__metadata.endpoints
|
|
289
|
+
end
|
|
290
|
+
|
|
291
|
+
def self.execute(url, context:, query_options: {})
|
|
292
|
+
Executor.execute(url: url, context: context, query_options: query_options, schema: self)
|
|
293
|
+
end
|
|
294
|
+
|
|
295
|
+
def self.create(url, context:, query_options: nil)
|
|
296
|
+
Executor.create(url: url, context: context, query_options: query_options, schema: self)
|
|
297
|
+
end
|
|
298
|
+
|
|
299
|
+
def self.update(url, context:, query_options: nil)
|
|
300
|
+
Executor.update(url: url, context: context, query_options: query_options, schema: self)
|
|
301
|
+
end
|
|
302
|
+
|
|
303
|
+
def self.delete(url, context:, query_options: nil)
|
|
304
|
+
Executor.delete(url: url, context: context, query_options: query_options, schema: self)
|
|
305
|
+
end
|
|
306
|
+
|
|
307
|
+
def self.to_mcp_server
|
|
308
|
+
McpServerBuilder.build(self)
|
|
309
|
+
end
|
|
310
|
+
end
|
|
311
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: odata_duty
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.30.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Grant Petersen-Speelman
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: exe
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2026-08-02 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: mcp
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - ">="
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: 0.20.0
|
|
20
|
+
- - "<"
|
|
21
|
+
- !ruby/object:Gem::Version
|
|
22
|
+
version: 1.0.0
|
|
23
|
+
type: :runtime
|
|
24
|
+
prerelease: false
|
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
26
|
+
requirements:
|
|
27
|
+
- - ">="
|
|
28
|
+
- !ruby/object:Gem::Version
|
|
29
|
+
version: 0.20.0
|
|
30
|
+
- - "<"
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: 1.0.0
|
|
33
|
+
- !ruby/object:Gem::Dependency
|
|
34
|
+
name: oj
|
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - ">="
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: 3.0.0
|
|
40
|
+
- - "<"
|
|
41
|
+
- !ruby/object:Gem::Version
|
|
42
|
+
version: 5.0.0
|
|
43
|
+
type: :runtime
|
|
44
|
+
prerelease: false
|
|
45
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
46
|
+
requirements:
|
|
47
|
+
- - ">="
|
|
48
|
+
- !ruby/object:Gem::Version
|
|
49
|
+
version: 3.0.0
|
|
50
|
+
- - "<"
|
|
51
|
+
- !ruby/object:Gem::Version
|
|
52
|
+
version: 5.0.0
|
|
53
|
+
- !ruby/object:Gem::Dependency
|
|
54
|
+
name: parslet
|
|
55
|
+
requirement: !ruby/object:Gem::Requirement
|
|
56
|
+
requirements:
|
|
57
|
+
- - "~>"
|
|
58
|
+
- !ruby/object:Gem::Version
|
|
59
|
+
version: '2.0'
|
|
60
|
+
type: :runtime
|
|
61
|
+
prerelease: false
|
|
62
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
63
|
+
requirements:
|
|
64
|
+
- - "~>"
|
|
65
|
+
- !ruby/object:Gem::Version
|
|
66
|
+
version: '2.0'
|
|
67
|
+
- !ruby/object:Gem::Dependency
|
|
68
|
+
name: uri
|
|
69
|
+
requirement: !ruby/object:Gem::Requirement
|
|
70
|
+
requirements:
|
|
71
|
+
- - ">="
|
|
72
|
+
- !ruby/object:Gem::Version
|
|
73
|
+
version: 1.0.0
|
|
74
|
+
- - "<"
|
|
75
|
+
- !ruby/object:Gem::Version
|
|
76
|
+
version: 2.0.0
|
|
77
|
+
type: :runtime
|
|
78
|
+
prerelease: false
|
|
79
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
80
|
+
requirements:
|
|
81
|
+
- - ">="
|
|
82
|
+
- !ruby/object:Gem::Version
|
|
83
|
+
version: 1.0.0
|
|
84
|
+
- - "<"
|
|
85
|
+
- !ruby/object:Gem::Version
|
|
86
|
+
version: 2.0.0
|
|
87
|
+
description: A unified DSL for exposing structured data and operations across analytics
|
|
88
|
+
tools (PowerBI), no-code platforms (PowerAutomate), and AI agents (via MCP).
|
|
89
|
+
email:
|
|
90
|
+
- grant@nexl.io
|
|
91
|
+
executables: []
|
|
92
|
+
extensions: []
|
|
93
|
+
extra_rdoc_files: []
|
|
94
|
+
files:
|
|
95
|
+
- README.md
|
|
96
|
+
- lib/generators/odata_duty/entity_set/entity_set_generator.rb
|
|
97
|
+
- lib/generators/odata_duty/entity_set/templates/entity_set.rb.erb
|
|
98
|
+
- lib/generators/odata_duty/entity_set/templates/entity_set_spec.rb.erb
|
|
99
|
+
- lib/generators/odata_duty/entity_set/templates/entity_type.rb.erb
|
|
100
|
+
- lib/generators/odata_duty/entity_set/templates/entity_type_spec.rb.erb
|
|
101
|
+
- lib/generators/odata_duty/entity_set/templates/odata_active_record_concern.rb.erb
|
|
102
|
+
- lib/generators/odata_duty/entity_set/templates/resolver.rb.erb
|
|
103
|
+
- lib/generators/odata_duty/entity_set/templates/resolver_spec.rb.erb
|
|
104
|
+
- lib/generators/odata_duty/install/install_generator.rb
|
|
105
|
+
- lib/generators/odata_duty/install/templates/controller.rb.tt
|
|
106
|
+
- lib/generators/odata_duty/install/templates/schema.rb.tt
|
|
107
|
+
- lib/metadata.xml.erb
|
|
108
|
+
- lib/odata_duty.rb
|
|
109
|
+
- lib/odata_duty/complex_type.rb
|
|
110
|
+
- lib/odata_duty/context_wrapper.rb
|
|
111
|
+
- lib/odata_duty/create_complex_type_hash_wrapper.rb
|
|
112
|
+
- lib/odata_duty/dynamic_object_wrapper.rb.erb
|
|
113
|
+
- lib/odata_duty/edms.rb
|
|
114
|
+
- lib/odata_duty/edmx_schema.rb
|
|
115
|
+
- lib/odata_duty/entity_type.rb
|
|
116
|
+
- lib/odata_duty/enum_type.rb
|
|
117
|
+
- lib/odata_duty/errors.rb
|
|
118
|
+
- lib/odata_duty/executor.rb
|
|
119
|
+
- lib/odata_duty/filter.rb
|
|
120
|
+
- lib/odata_duty/filter_predicate.rb
|
|
121
|
+
- lib/odata_duty/mapper_builder.rb
|
|
122
|
+
- lib/odata_duty/mcp_input_schemas.rb
|
|
123
|
+
- lib/odata_duty/mcp_server_builder.rb
|
|
124
|
+
- lib/odata_duty/oas2.rb
|
|
125
|
+
- lib/odata_duty/oas2/collection_get_path.rb
|
|
126
|
+
- lib/odata_duty/oas2/collection_post_path.rb
|
|
127
|
+
- lib/odata_duty/oas2/individual_delete_path.rb
|
|
128
|
+
- lib/odata_duty/oas2/individual_get_path.rb
|
|
129
|
+
- lib/odata_duty/oas2/individual_patch_path.rb
|
|
130
|
+
- lib/odata_duty/parslet_search_expression.rb
|
|
131
|
+
- lib/odata_duty/property.rb
|
|
132
|
+
- lib/odata_duty/property/collection_prop.rb
|
|
133
|
+
- lib/odata_duty/property/single_prop.rb
|
|
134
|
+
- lib/odata_duty/railtie.rb
|
|
135
|
+
- lib/odata_duty/schema_builder.rb
|
|
136
|
+
- lib/odata_duty/schema_builder/complex_type.rb
|
|
137
|
+
- lib/odata_duty/schema_builder/container.rb
|
|
138
|
+
- lib/odata_duty/schema_builder/data_type.rb
|
|
139
|
+
- lib/odata_duty/schema_builder/endpoint.rb
|
|
140
|
+
- lib/odata_duty/schema_builder/entity_set.rb
|
|
141
|
+
- lib/odata_duty/schema_builder/entity_type.rb
|
|
142
|
+
- lib/odata_duty/schema_builder/enum_type.rb
|
|
143
|
+
- lib/odata_duty/set_resolver.rb
|
|
144
|
+
homepage:
|
|
145
|
+
licenses: []
|
|
146
|
+
metadata:
|
|
147
|
+
rubygems_mfa_required: 'true'
|
|
148
|
+
post_install_message:
|
|
149
|
+
rdoc_options: []
|
|
150
|
+
require_paths:
|
|
151
|
+
- lib
|
|
152
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
153
|
+
requirements:
|
|
154
|
+
- - ">="
|
|
155
|
+
- !ruby/object:Gem::Version
|
|
156
|
+
version: 3.2.0
|
|
157
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
158
|
+
requirements:
|
|
159
|
+
- - ">="
|
|
160
|
+
- !ruby/object:Gem::Version
|
|
161
|
+
version: '0'
|
|
162
|
+
requirements: []
|
|
163
|
+
rubygems_version: 3.5.22
|
|
164
|
+
signing_key:
|
|
165
|
+
specification_version: 4
|
|
166
|
+
summary: A unified, intent-driven interface layer that serves automation, AI, and
|
|
167
|
+
developer platforms with minimal duplication.
|
|
168
|
+
test_files: []
|