foobara 0.0.86 → 0.0.88
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 +4 -4
- data/CHANGELOG.md +11 -0
- data/projects/builtin_types/src/email/transformers/downcase.rb +0 -3
- data/projects/builtin_types/src/email/validator_base.rb +5 -4
- data/projects/builtin_types/src/string/supported_transformers/downcase.rb +5 -1
- data/projects/command/src/transformed_command.rb +146 -80
- data/projects/command_connectors/src/command_connector/response.rb +5 -5
- data/projects/command_connectors/src/command_connector.rb +51 -13
- data/projects/command_connectors/src/command_registry/exposed_command.rb +5 -0
- data/projects/command_connectors/src/response_mutator.rb +24 -0
- data/projects/command_connectors/src/serializers/errors_serializer.rb +2 -2
- data/projects/detached_entity/src/concerns/associations.rb +25 -2
- data/projects/domain/src/domain_module_extension.rb +6 -2
- data/projects/entity/src/sensitive_value_removers/entity.rb +20 -4
- data/projects/model/src/extensions/type_declarations/handlers/extend_registered_model_type_declaration.rb +1 -1
- data/projects/model/src/sensitive_value_removers/model.rb +3 -5
- data/projects/type_declarations/src/attributes_transformers/only.rb +32 -0
- data/projects/type_declarations/src/attributes_transformers/reject.rb +32 -0
- data/projects/type_declarations/src/handlers/registered_type_declaration/to_type_transformer.rb +1 -1
- data/projects/type_declarations/src/remove_sensitive_values_transformer.rb +16 -17
- data/projects/type_declarations/src/typed_transformer.rb +83 -69
- data/projects/type_declarations/src/with_registries.rb +0 -4
- data/projects/value/src/mutator.rb +29 -0
- metadata +14 -11
- data/projects/type_declarations/src/attributes_transformer.rb +0 -33
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5abb6c21d367251512e93a28585ca52fbef92cbea5bd4b6f102f693ae7e42969
|
4
|
+
data.tar.gz: 2219f04cbb8cd7fa1b4f296fe229416cb344fd30bdd4fe529cb619b820a45f03
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: df26075b6ad2825133cd77b08e6c5813756fe130244b4d21ca0c312a734380c40668ce5a066e102a2b321a66f08ddf51a9a2499af1c243a603db40c3057aa60a
|
7
|
+
data.tar.gz: 8c4ef51ae4cb5fc93c31e3b739f0b919c91cad78944cbeeea25d324f607020aff47ff7ae8166e24fd17dc9aff61dab9962b29833d505e77f1833a8af40a56c1e
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,14 @@
|
|
1
|
+
# [0.0.88] - 2025-03-28
|
2
|
+
|
3
|
+
- Implement response mutator concept
|
4
|
+
- Break up #request_to_response for easier overriding/extension
|
5
|
+
- Add AttributesTransformers::Reject
|
6
|
+
- Fix problem causing downcase/regex processors to explode on allows_nil types
|
7
|
+
|
8
|
+
# [0.0.87] - 2025-03-26
|
9
|
+
|
10
|
+
- TypedTransformer refactor to reduce confusion and bugs
|
11
|
+
|
1
12
|
# [0.0.86] - 2025-03-23
|
2
13
|
|
3
14
|
- Add an AttributesTransformer.only method to quickly get a TypedTransformer (helpful with inputs_transformers)
|
@@ -5,9 +5,6 @@ module Foobara
|
|
5
5
|
# Seems like it might be cleaner to just assemble these parts in one place instead of in different files?
|
6
6
|
# Hard to say.
|
7
7
|
class Downcase < BuiltinTypes::String::SupportedTransformers::Downcase
|
8
|
-
def always_applicable?
|
9
|
-
true
|
10
|
-
end
|
11
8
|
end
|
12
9
|
end
|
13
10
|
end
|
@@ -27,10 +27,6 @@ module Foobara
|
|
27
27
|
end
|
28
28
|
end
|
29
29
|
|
30
|
-
def always_applicable?
|
31
|
-
true
|
32
|
-
end
|
33
|
-
|
34
30
|
def regex
|
35
31
|
# :nocov:
|
36
32
|
raise "subclass responsibility"
|
@@ -76,6 +72,11 @@ module Foobara
|
|
76
72
|
class_name = "#{name}::#{Util.classify(symbol)}"
|
77
73
|
|
78
74
|
Util.make_class(class_name, ValidatorBase) do
|
75
|
+
define_method :applicable? do |value|
|
76
|
+
# TODO: hmmm, I wonder how we can short-circuit these checks if :allows_nil matches??
|
77
|
+
value.is_a?(::String)
|
78
|
+
end
|
79
|
+
|
79
80
|
define_method :regex do
|
80
81
|
regex
|
81
82
|
end
|
@@ -3,7 +3,11 @@ module Foobara
|
|
3
3
|
# TODO: Rename to StringType to avoid needing to remember ::String elsewhere in the code
|
4
4
|
module String
|
5
5
|
module SupportedTransformers
|
6
|
-
class Downcase < Value::Transformer.subclass(
|
6
|
+
class Downcase < Value::Transformer.subclass(
|
7
|
+
transform: :downcase.to_proc,
|
8
|
+
name: "Downcase",
|
9
|
+
applicable?: ->(value) { value.respond_to?(:downcase) }
|
10
|
+
)
|
7
11
|
end
|
8
12
|
end
|
9
13
|
end
|
@@ -13,6 +13,10 @@ module Foobara
|
|
13
13
|
:pre_commit_transformers,
|
14
14
|
# TODO: get at least these serializers out of here...
|
15
15
|
:serializers,
|
16
|
+
# TODO: probably should also get these mutators out of here. But where should they live?
|
17
|
+
# On exposed command? On the command registry? On the command connector?
|
18
|
+
# This is the easiest place to implement them but feels awkward.
|
19
|
+
:response_mutators,
|
16
20
|
:allowed_rule,
|
17
21
|
:requires_authentication,
|
18
22
|
:authenticator
|
@@ -27,6 +31,7 @@ module Foobara
|
|
27
31
|
errors_transformers:,
|
28
32
|
pre_commit_transformers:,
|
29
33
|
serializers:,
|
34
|
+
response_mutators:,
|
30
35
|
allowed_rule:,
|
31
36
|
requires_authentication:,
|
32
37
|
authenticator:,
|
@@ -40,8 +45,7 @@ module Foobara
|
|
40
45
|
|
41
46
|
remover = Namespace.use scoped_namespace do
|
42
47
|
transformed_result_type = result_type_from_transformers(result_type, result_transformers)
|
43
|
-
|
44
|
-
remover_class.new(transformed_result_type).tap do |r|
|
48
|
+
remover_class.new(from: transformed_result_type).tap do |r|
|
45
49
|
r.scoped_path = ["SensitiveValueRemover", *transformed_result_type.scoped_full_path]
|
46
50
|
end
|
47
51
|
end
|
@@ -59,6 +63,7 @@ module Foobara
|
|
59
63
|
klass.errors_transformers = Util.array(errors_transformers)
|
60
64
|
klass.pre_commit_transformers = Util.array(pre_commit_transformers)
|
61
65
|
klass.serializers = Util.array(serializers)
|
66
|
+
klass.response_mutators = Util.array(response_mutators)
|
62
67
|
klass.allowed_rule = allowed_rule
|
63
68
|
klass.requires_authentication = requires_authentication
|
64
69
|
klass.authenticator = authenticator
|
@@ -71,25 +76,34 @@ module Foobara
|
|
71
76
|
to: :command_class
|
72
77
|
|
73
78
|
def inputs_type
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
79
|
+
return @inputs_type if defined?(@inputs_type)
|
80
|
+
|
81
|
+
@inputs_type = if inputs_transformer
|
82
|
+
if inputs_transformer.is_a?(Value::Processor::Pipeline)
|
83
|
+
inputs_transformer.processors.each do |transformer|
|
84
|
+
if transformer.is_a?(TypeDeclarations::TypedTransformer)
|
85
|
+
from_type = transformer.from_type
|
86
|
+
if from_type
|
87
|
+
@inputs_type = from_type
|
88
|
+
return from_type
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
command_class.inputs_type
|
94
|
+
else
|
95
|
+
inputs_transformer.from_type || command_class.inputs_type
|
96
|
+
end
|
97
|
+
else
|
98
|
+
command_class.inputs_type
|
99
|
+
end
|
85
100
|
end
|
86
101
|
|
87
102
|
def result_type_from_transformers(result_type, transformers)
|
88
|
-
|
103
|
+
transformers.reverse.each do |transformer|
|
89
104
|
if transformer.is_a?(Class) && transformer < TypeDeclarations::TypedTransformer
|
90
|
-
new_type = transformer.
|
91
|
-
|
92
|
-
result_type = new_type if new_type
|
105
|
+
new_type = transformer.to_type
|
106
|
+
return new_type if new_type
|
93
107
|
end
|
94
108
|
end
|
95
109
|
|
@@ -100,6 +114,18 @@ module Foobara
|
|
100
114
|
result_type_from_transformers(command_class.result_type, result_transformers)
|
101
115
|
end
|
102
116
|
|
117
|
+
def result_type_for_manifest
|
118
|
+
return @result_type_for_manifest if defined?(@result_type_for_manifest)
|
119
|
+
|
120
|
+
mutated_result_type = result_type
|
121
|
+
|
122
|
+
response_mutators&.reverse&.each do |mutator|
|
123
|
+
mutated_result_type = mutator.instance.result_type_from(mutated_result_type)
|
124
|
+
end
|
125
|
+
|
126
|
+
@result_type_for_manifest = mutated_result_type
|
127
|
+
end
|
128
|
+
|
103
129
|
def error_context_type_map
|
104
130
|
@error_context_type_map ||= begin
|
105
131
|
set = {}
|
@@ -199,12 +225,13 @@ module Foobara
|
|
199
225
|
end
|
200
226
|
end
|
201
227
|
|
228
|
+
response_mutators = self.response_mutators.map { |t| t.foobara_manifest(to_include:) }
|
229
|
+
|
202
230
|
command_class.foobara_manifest(to_include:, remove_sensitive:).merge(
|
203
231
|
Util.remove_blank(
|
204
232
|
types_depended_on: types,
|
205
233
|
inputs_type: inputs_type&.reference_or_declaration_data,
|
206
|
-
|
207
|
-
result_type: result_type&.reference_or_declaration_data(remove_sensitive:),
|
234
|
+
result_type: result_type_for_manifest&.reference_or_declaration_data(remove_sensitive:),
|
208
235
|
possible_errors: possible_errors_manifest(to_include:, remove_sensitive:),
|
209
236
|
capture_unknown_error:,
|
210
237
|
inputs_transformers:,
|
@@ -212,11 +239,94 @@ module Foobara
|
|
212
239
|
errors_transformers:,
|
213
240
|
pre_commit_transformers:,
|
214
241
|
serializers:,
|
242
|
+
response_mutators:,
|
215
243
|
requires_authentication:,
|
216
244
|
authenticator: authenticator&.manifest
|
217
245
|
)
|
218
246
|
)
|
219
247
|
end
|
248
|
+
|
249
|
+
def inputs_transformer
|
250
|
+
return @inputs_transformer if defined?(@inputs_transformer)
|
251
|
+
|
252
|
+
if inputs_transformers.empty?
|
253
|
+
@inputs_transformer = nil
|
254
|
+
return
|
255
|
+
end
|
256
|
+
|
257
|
+
@inputs_transformer = begin
|
258
|
+
transformers = transformers_to_processors(inputs_transformers,
|
259
|
+
command_class.inputs_type, direction: :to)
|
260
|
+
|
261
|
+
if transformers.size == 1
|
262
|
+
transformers.first
|
263
|
+
else
|
264
|
+
Value::Processor::Pipeline.new(processors: transformers)
|
265
|
+
end
|
266
|
+
end
|
267
|
+
end
|
268
|
+
|
269
|
+
def response_mutator
|
270
|
+
return @response_mutator if defined?(@response_mutator)
|
271
|
+
|
272
|
+
if response_mutators.empty?
|
273
|
+
@response_mutator = nil
|
274
|
+
return
|
275
|
+
end
|
276
|
+
|
277
|
+
@response_mutator = begin
|
278
|
+
transformers = transformers_to_processors(response_mutators, result_type, direction: :from)
|
279
|
+
|
280
|
+
if transformers.size == 1
|
281
|
+
transformers.first
|
282
|
+
else
|
283
|
+
Value::Processor::Pipeline.new(processors: transformers)
|
284
|
+
end
|
285
|
+
end
|
286
|
+
end
|
287
|
+
|
288
|
+
def result_transformer
|
289
|
+
return @result_transformer if defined?(@result_transformer)
|
290
|
+
|
291
|
+
if result_transformers.empty?
|
292
|
+
@result_transformer = nil
|
293
|
+
return
|
294
|
+
end
|
295
|
+
|
296
|
+
@result_transformer = begin
|
297
|
+
transformers = transformers_to_processors(result_transformers, command_class.result_type, direction: :from)
|
298
|
+
|
299
|
+
if transformers.size == 1
|
300
|
+
transformers.first
|
301
|
+
else
|
302
|
+
Value::Processor::Pipeline.new(processors: transformers)
|
303
|
+
end
|
304
|
+
end
|
305
|
+
end
|
306
|
+
|
307
|
+
# TODO: this is pretty messy with smells.
|
308
|
+
def transformers_to_processors(transformers, target_type, direction: :from, declaration_data: self)
|
309
|
+
transformers.map do |transformer|
|
310
|
+
if transformer.is_a?(Class)
|
311
|
+
if transformer < TypeDeclarations::TypedTransformer
|
312
|
+
transformer.new(direction => target_type).tap do |tx|
|
313
|
+
new_type = direction == :from ? tx.to_type : tx.from_type
|
314
|
+
target_type = new_type if new_type
|
315
|
+
end
|
316
|
+
else
|
317
|
+
transformer.new(declaration_data)
|
318
|
+
end
|
319
|
+
elsif transformer.is_a?(Value::Processor)
|
320
|
+
transformer
|
321
|
+
elsif transformer.respond_to?(:call)
|
322
|
+
Value::Transformer.create(transform: transformer)
|
323
|
+
else
|
324
|
+
# :nocov:
|
325
|
+
raise "Not sure how to apply #{inputs_transformer}"
|
326
|
+
# :nocov:
|
327
|
+
end
|
328
|
+
end
|
329
|
+
end
|
220
330
|
end
|
221
331
|
|
222
332
|
attr_accessor :command, :untransformed_inputs, :transformed_inputs, :outcome, :authenticated_user
|
@@ -259,49 +369,29 @@ module Foobara
|
|
259
369
|
end
|
260
370
|
|
261
371
|
def transform_inputs
|
262
|
-
self.transformed_inputs = if inputs_transformer
|
263
|
-
inputs_transformer.process_value!(untransformed_inputs)
|
372
|
+
self.transformed_inputs = if self.class.inputs_transformer
|
373
|
+
self.class.inputs_transformer.process_value!(untransformed_inputs)
|
264
374
|
else
|
265
375
|
untransformed_inputs
|
266
376
|
end
|
267
377
|
end
|
268
378
|
|
269
379
|
def transform_result
|
270
|
-
if result_transformer
|
271
|
-
self.outcome = Outcome.success(result_transformer.process_value!(result))
|
380
|
+
if self.class.result_transformer
|
381
|
+
self.outcome = Outcome.success(self.class.result_transformer.process_value!(result))
|
272
382
|
end
|
273
383
|
end
|
274
384
|
|
385
|
+
def mutate_response(response)
|
386
|
+
self.class.response_mutator&.process_value!(response)
|
387
|
+
end
|
388
|
+
|
275
389
|
def transform_errors
|
276
390
|
if errors_transformer
|
277
391
|
self.outcome = Outcome.errors(errors_transformer.process_value!(errors))
|
278
392
|
end
|
279
393
|
end
|
280
394
|
|
281
|
-
def inputs_transformer
|
282
|
-
return nil if inputs_transformers.empty?
|
283
|
-
|
284
|
-
transformers = transformers_to_processors(inputs_transformers, command_class.inputs_type)
|
285
|
-
|
286
|
-
if transformers.size == 1
|
287
|
-
transformers.first
|
288
|
-
else
|
289
|
-
Value::Processor::Pipeline.new(processors: transformers)
|
290
|
-
end
|
291
|
-
end
|
292
|
-
|
293
|
-
def result_transformer
|
294
|
-
return nil if result_transformers.empty?
|
295
|
-
|
296
|
-
transformers = transformers_to_processors(result_transformers, command_class.result_type)
|
297
|
-
|
298
|
-
if transformers.size == 1
|
299
|
-
transformers.first
|
300
|
-
else
|
301
|
-
Value::Processor::Pipeline.new(processors: transformers)
|
302
|
-
end
|
303
|
-
end
|
304
|
-
|
305
395
|
# TODO: let's get this out of here...
|
306
396
|
# we might want to have different serializers for different command instances of the same class.
|
307
397
|
# but currently serializers is set on the class. Since this class should not be concerned with serialization, we
|
@@ -309,7 +399,7 @@ module Foobara
|
|
309
399
|
def serializer
|
310
400
|
return nil if serializers.empty?
|
311
401
|
|
312
|
-
transformers = transformers_to_processors(serializers, nil)
|
402
|
+
transformers = self.class.transformers_to_processors(serializers, nil, declaration_data: self)
|
313
403
|
|
314
404
|
if transformers.size == 1
|
315
405
|
transformers.first
|
@@ -321,7 +411,8 @@ module Foobara
|
|
321
411
|
def errors_transformer
|
322
412
|
return nil if errors_transformers.empty?
|
323
413
|
|
324
|
-
transformers = transformers_to_processors(errors_transformers, nil
|
414
|
+
transformers = self.class.transformers_to_processors(errors_transformers, nil, direction: :from,
|
415
|
+
declaration_data: self)
|
325
416
|
|
326
417
|
if transformers.size == 1
|
327
418
|
transformers.first
|
@@ -334,7 +425,11 @@ module Foobara
|
|
334
425
|
def pre_commit_transformer
|
335
426
|
return nil if pre_commit_transformers.empty?
|
336
427
|
|
337
|
-
transformers = transformers_to_processors(
|
428
|
+
transformers = self.class.transformers_to_processors(
|
429
|
+
pre_commit_transformers,
|
430
|
+
nil,
|
431
|
+
declaration_data: self
|
432
|
+
)
|
338
433
|
|
339
434
|
if transformers.size == 1
|
340
435
|
transformers.first
|
@@ -343,29 +438,6 @@ module Foobara
|
|
343
438
|
end
|
344
439
|
end
|
345
440
|
|
346
|
-
def transformers_to_processors(transformers, from_type)
|
347
|
-
transformers.map do |transformer|
|
348
|
-
if transformer.is_a?(Class)
|
349
|
-
if transformer < TypeDeclarations::TypedTransformer
|
350
|
-
transformer.new(from_type).tap do |tx|
|
351
|
-
new_type = tx.type
|
352
|
-
from_type = new_type if new_type
|
353
|
-
end
|
354
|
-
else
|
355
|
-
transformer.new(self)
|
356
|
-
end
|
357
|
-
elsif transformer.is_a?(Value::Processor)
|
358
|
-
transformer
|
359
|
-
elsif transformer.respond_to?(:call)
|
360
|
-
Value::Transformer.create(transform: transformer)
|
361
|
-
else
|
362
|
-
# :nocov:
|
363
|
-
raise "Not sure how to apply #{inputs_transformer}"
|
364
|
-
# :nocov:
|
365
|
-
end
|
366
|
-
end
|
367
|
-
end
|
368
|
-
|
369
441
|
def construct_command
|
370
442
|
self.command = command_class.new(transformed_inputs)
|
371
443
|
end
|
@@ -453,13 +525,7 @@ module Foobara
|
|
453
525
|
end
|
454
526
|
|
455
527
|
# TODO: kill this
|
456
|
-
def serialize_result
|
457
|
-
body = if outcome.success?
|
458
|
-
outcome.result
|
459
|
-
else
|
460
|
-
outcome.errors
|
461
|
-
end
|
462
|
-
|
528
|
+
def serialize_result(body)
|
463
529
|
if serializer
|
464
530
|
serializer.process_value!(body)
|
465
531
|
else
|
@@ -1,14 +1,14 @@
|
|
1
1
|
module Foobara
|
2
2
|
class CommandConnector
|
3
3
|
class Response
|
4
|
-
attr_accessor :
|
5
|
-
:
|
6
|
-
:
|
4
|
+
attr_accessor :request,
|
5
|
+
:status,
|
6
|
+
:body
|
7
7
|
|
8
|
-
def initialize(
|
8
|
+
def initialize(request:, status: nil, body: nil)
|
9
|
+
self.request = request
|
9
10
|
self.status = status
|
10
11
|
self.body = body
|
11
|
-
self.request = request
|
12
12
|
end
|
13
13
|
|
14
14
|
foobara_delegate :command, :error, to: :request
|
@@ -95,6 +95,7 @@ module Foobara
|
|
95
95
|
:add_default_errors_transformer,
|
96
96
|
:add_default_pre_commit_transformer,
|
97
97
|
:add_default_serializer,
|
98
|
+
:add_default_response_mutator,
|
98
99
|
:allowed_rule,
|
99
100
|
:allowed_rules,
|
100
101
|
:transform_command_class,
|
@@ -232,16 +233,34 @@ module Foobara
|
|
232
233
|
end
|
233
234
|
|
234
235
|
def request_to_response(request)
|
235
|
-
|
236
|
-
|
236
|
+
self.class::Response.new(request:)
|
237
|
+
end
|
238
|
+
|
239
|
+
def set_response_status(response)
|
240
|
+
outcome = response.request.outcome
|
241
|
+
response.status = outcome.success? ? 0 : 1
|
242
|
+
end
|
237
243
|
|
238
|
-
|
244
|
+
def set_response_body(response)
|
245
|
+
outcome = response.request.outcome
|
246
|
+
# response.body = outcome.success? ? outcome.result : outcome.error_collection
|
247
|
+
response.body = outcome.success? ? outcome.result : outcome.error_collection
|
248
|
+
end
|
239
249
|
|
240
|
-
|
241
|
-
|
242
|
-
body = command.respond_to?(:serialize_result) ? command.serialize_result : request.response_body
|
250
|
+
def mutate_response(response)
|
251
|
+
command = response.command
|
243
252
|
|
244
|
-
|
253
|
+
if command.respond_to?(:mutate_response)
|
254
|
+
command.mutate_response(response)
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
258
|
+
def serialize_response_body(response)
|
259
|
+
command = response.command
|
260
|
+
|
261
|
+
if command.respond_to?(:serialize_result)
|
262
|
+
response.body = command.serialize_result(response.body)
|
263
|
+
end
|
245
264
|
end
|
246
265
|
|
247
266
|
def initialize(authenticator: nil, default_serializers: nil)
|
@@ -343,7 +362,12 @@ module Foobara
|
|
343
362
|
|
344
363
|
def build_response(request)
|
345
364
|
response = request_to_response(request)
|
346
|
-
|
365
|
+
|
366
|
+
set_response_status(response)
|
367
|
+
set_response_body(response)
|
368
|
+
mutate_response(response)
|
369
|
+
serialize_response_body(response)
|
370
|
+
|
347
371
|
response
|
348
372
|
end
|
349
373
|
|
@@ -387,14 +411,28 @@ module Foobara
|
|
387
411
|
additional_to_include.delete(o)
|
388
412
|
|
389
413
|
if o.is_a?(::Module)
|
390
|
-
if o.foobara_domain? || o.foobara_organization?
|
414
|
+
if o.foobara_domain? || o.foobara_organization?
|
415
|
+
unless o.foobara_root_namespace == command_registry
|
416
|
+
next
|
417
|
+
end
|
418
|
+
elsif o.is_a?(::Class) && o < Foobara::Command
|
391
419
|
next
|
392
420
|
end
|
393
|
-
elsif o.is_a?(Types::Type)
|
394
|
-
|
395
|
-
|
396
|
-
|
421
|
+
elsif o.is_a?(Types::Type)
|
422
|
+
if remove_sensitive && o.sensitive?
|
423
|
+
# :nocov:
|
424
|
+
raise UnexpectedSensitiveTypeInManifestError,
|
425
|
+
"Unexpected sensitive type in manifest: #{o.scoped_full_path}. Make sure these are not included."
|
397
426
|
# :nocov:
|
427
|
+
else
|
428
|
+
domain_name = o.foobara_domain.scoped_full_name
|
429
|
+
|
430
|
+
unless command_registry.foobara_registered?(domain_name)
|
431
|
+
domain = command_registry.build_and_register_exposed_domain(domain_name)
|
432
|
+
additional_to_include << domain
|
433
|
+
additional_to_include << domain.foobara_organization
|
434
|
+
end
|
435
|
+
end
|
398
436
|
end
|
399
437
|
|
400
438
|
object = o
|
@@ -12,6 +12,7 @@ module Foobara
|
|
12
12
|
:errors_transformers,
|
13
13
|
:pre_commit_transformers,
|
14
14
|
:serializers,
|
15
|
+
:response_mutators,
|
15
16
|
:allowed_rule,
|
16
17
|
:requires_authentication,
|
17
18
|
:authenticator,
|
@@ -27,6 +28,7 @@ module Foobara
|
|
27
28
|
result_transformers: nil,
|
28
29
|
errors_transformers: nil,
|
29
30
|
pre_commit_transformers: nil,
|
31
|
+
response_mutators: nil,
|
30
32
|
serializers: nil,
|
31
33
|
allowed_rule: nil,
|
32
34
|
requires_authentication: nil,
|
@@ -76,6 +78,7 @@ module Foobara
|
|
76
78
|
self.result_transformers = result_transformers
|
77
79
|
self.errors_transformers = errors_transformers
|
78
80
|
self.pre_commit_transformers = pre_commit_transformers
|
81
|
+
self.response_mutators = response_mutators
|
79
82
|
self.serializers = serializers
|
80
83
|
self.allowed_rule = allowed_rule
|
81
84
|
self.requires_authentication = requires_authentication
|
@@ -111,6 +114,7 @@ module Foobara
|
|
111
114
|
result_transformers,
|
112
115
|
errors_transformers,
|
113
116
|
pre_commit_transformers,
|
117
|
+
response_mutators,
|
114
118
|
serializers,
|
115
119
|
allowed_rule,
|
116
120
|
requires_authentication,
|
@@ -130,6 +134,7 @@ module Foobara
|
|
130
134
|
result_transformers:,
|
131
135
|
errors_transformers:,
|
132
136
|
pre_commit_transformers:,
|
137
|
+
response_mutators:,
|
133
138
|
serializers:,
|
134
139
|
allowed_rule:,
|
135
140
|
requires_authentication:,
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Foobara
|
2
|
+
module CommandConnectors
|
3
|
+
class ResponseMutator < Foobara::Value::Mutator
|
4
|
+
def result_type_declaration_from(_result_type)
|
5
|
+
# :nocov:
|
6
|
+
raise "subclass responsibility"
|
7
|
+
# :nocov:
|
8
|
+
end
|
9
|
+
|
10
|
+
def result_type_from(result_type)
|
11
|
+
declaration = result_type_declaration_from(result_type)
|
12
|
+
Domain.current.foobara_type_from_declaration(declaration)
|
13
|
+
end
|
14
|
+
|
15
|
+
def mutate
|
16
|
+
# :nocov:
|
17
|
+
raise "subclass responsibility"
|
18
|
+
# :nocov:
|
19
|
+
end
|
20
|
+
|
21
|
+
alias response declaration_data
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -4,12 +4,12 @@ module Foobara
|
|
4
4
|
module CommandConnectors
|
5
5
|
module Serializers
|
6
6
|
class ErrorsSerializer < Serializer
|
7
|
-
# TODO: always_applicable? instead?
|
8
7
|
def always_applicable?
|
9
8
|
!request.outcome.success?
|
10
9
|
end
|
11
10
|
|
12
|
-
def serialize(
|
11
|
+
def serialize(error_collection)
|
12
|
+
errors = error_collection.errors
|
13
13
|
errors.map(&:to_h)
|
14
14
|
end
|
15
15
|
end
|
@@ -123,6 +123,29 @@ module Foobara
|
|
123
123
|
end
|
124
124
|
end
|
125
125
|
|
126
|
+
def construct_deep_associations(
|
127
|
+
type = attributes_type,
|
128
|
+
path = DataPath.new,
|
129
|
+
result = {},
|
130
|
+
remove_sensitive: false
|
131
|
+
)
|
132
|
+
associations = construct_associations(type, path, result, remove_sensitive:)
|
133
|
+
|
134
|
+
deep = {}
|
135
|
+
|
136
|
+
associations.each_pair do |data_path, association_type|
|
137
|
+
deep[data_path] = association_type
|
138
|
+
|
139
|
+
entity_class = association_type.target_class
|
140
|
+
|
141
|
+
entity_class.deep_associations(remove_sensitive:).each_pair do |sub_data_path, sub_type|
|
142
|
+
deep["#{data_path}.#{sub_data_path}"] = sub_type
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
deep
|
147
|
+
end
|
148
|
+
|
126
149
|
# TODO: this big switch is a problem. Hard to create new types in other projects without being able
|
127
150
|
# to modify this switch. Figure out what to do.
|
128
151
|
def construct_associations(
|
@@ -224,8 +247,8 @@ module Foobara
|
|
224
247
|
types = types&.reject(&:sensitive?)
|
225
248
|
end
|
226
249
|
|
227
|
-
types.any? do |
|
228
|
-
contains_associations?(
|
250
|
+
types.any? do |key_or_value_type|
|
251
|
+
contains_associations?(key_or_value_type, false, remove_sensitive:)
|
229
252
|
end
|
230
253
|
end
|
231
254
|
end
|
@@ -231,9 +231,13 @@ module Foobara
|
|
231
231
|
end
|
232
232
|
end
|
233
233
|
|
234
|
-
def foobara_type_from_declaration(
|
234
|
+
def foobara_type_from_declaration(*args, **opts, &block)
|
235
|
+
if opts.empty? && block.nil? && args.size == 1 && args.first.is_a?(Types::Type)
|
236
|
+
return args.first
|
237
|
+
end
|
238
|
+
|
235
239
|
Foobara::Namespace.use self do
|
236
|
-
foobara_type_builder.type_for_declaration(
|
240
|
+
foobara_type_builder.type_for_declaration(*args, **opts, &block)
|
237
241
|
end
|
238
242
|
end
|
239
243
|
|
@@ -3,12 +3,28 @@ module Foobara
|
|
3
3
|
module SensitiveValueRemovers
|
4
4
|
class Entity < DetachedEntity::SensitiveValueRemovers::DetachedEntity
|
5
5
|
def transform(record)
|
6
|
-
|
6
|
+
if record.loaded? || record.created?
|
7
|
+
sanitized_record = super
|
7
8
|
|
8
|
-
|
9
|
-
|
9
|
+
sanitized_record.is_loaded = record.loaded?
|
10
|
+
sanitized_record.is_persisted = record.persisted?
|
10
11
|
|
11
|
-
|
12
|
+
sanitized_record
|
13
|
+
elsif record.persisted?
|
14
|
+
# We will assume that we do not need to clean up the primary key itself as
|
15
|
+
# we will assume we don't allow sensitive primary keys for now.
|
16
|
+
sanitized_record = to_type.target_class.build(record.class.primary_key_attribute => record.primary_key)
|
17
|
+
|
18
|
+
sanitized_record.is_persisted = true
|
19
|
+
sanitized_record.is_loaded = false
|
20
|
+
sanitized_record.is_built = false
|
21
|
+
|
22
|
+
sanitized_record
|
23
|
+
else
|
24
|
+
# :nocov:
|
25
|
+
raise "Not sure what to do with a record that isn't loaded, created, or persisted"
|
26
|
+
# :nocov:
|
27
|
+
end
|
12
28
|
end
|
13
29
|
|
14
30
|
def build_method
|
@@ -5,12 +5,10 @@ module Foobara
|
|
5
5
|
def transform(record)
|
6
6
|
attributes_type = from_type.element_types
|
7
7
|
|
8
|
-
sanitized_attributes,
|
8
|
+
sanitized_attributes, _changed = sanitize_value(attributes_type, record.attributes)
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
else
|
13
|
-
record
|
10
|
+
Namespace.use(to_type.created_in_namespace) do
|
11
|
+
to_type.target_class.send(build_method, sanitized_attributes)
|
14
12
|
end
|
15
13
|
end
|
16
14
|
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Foobara
|
2
|
+
class AttributesTransformers < TypeDeclarations::TypedTransformer
|
3
|
+
class << self
|
4
|
+
def only(*attribute_names)
|
5
|
+
transformer_class = Class.new(Only)
|
6
|
+
transformer_class.only_attributes = attribute_names
|
7
|
+
|
8
|
+
transformer_class
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
class Only < AttributesTransformers
|
13
|
+
class << self
|
14
|
+
attr_accessor :only_attributes
|
15
|
+
end
|
16
|
+
|
17
|
+
def to_type_declaration
|
18
|
+
from_declaration = from_type.declaration_data
|
19
|
+
TypeDeclarations::Attributes.only(from_declaration, *self.class.only_attributes)
|
20
|
+
end
|
21
|
+
|
22
|
+
def transform(inputs)
|
23
|
+
inputs = Util.symbolize_keys(inputs)
|
24
|
+
inputs.slice(*allowed_keys)
|
25
|
+
end
|
26
|
+
|
27
|
+
def allowed_keys
|
28
|
+
to_type.element_types.keys
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Foobara
|
2
|
+
class AttributesTransformers < TypeDeclarations::TypedTransformer
|
3
|
+
class << self
|
4
|
+
def reject(*attribute_names)
|
5
|
+
transformer_class = Class.new(Reject)
|
6
|
+
transformer_class.reject_attributes = attribute_names
|
7
|
+
|
8
|
+
transformer_class
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
class Reject < AttributesTransformers
|
13
|
+
class << self
|
14
|
+
attr_accessor :reject_attributes
|
15
|
+
end
|
16
|
+
|
17
|
+
def to_type_declaration
|
18
|
+
from_declaration = from_type.declaration_data
|
19
|
+
TypeDeclarations::Attributes.reject(from_declaration, *self.class.reject_attributes)
|
20
|
+
end
|
21
|
+
|
22
|
+
def transform(inputs)
|
23
|
+
inputs = Util.symbolize_keys(inputs)
|
24
|
+
inputs.slice(*allowed_keys)
|
25
|
+
end
|
26
|
+
|
27
|
+
def allowed_keys
|
28
|
+
to_type.element_types.keys
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
data/projects/type_declarations/src/handlers/registered_type_declaration/to_type_transformer.rb
CHANGED
@@ -15,7 +15,7 @@ module Foobara
|
|
15
15
|
end
|
16
16
|
|
17
17
|
def registered_type(strict_type_declaration)
|
18
|
-
|
18
|
+
lookup_type!(type_symbol(strict_type_declaration))
|
19
19
|
end
|
20
20
|
|
21
21
|
def target_classes(strict_type_declaration)
|
@@ -3,24 +3,21 @@ require_relative "typed_transformer"
|
|
3
3
|
module Foobara
|
4
4
|
module TypeDeclarations
|
5
5
|
class RemoveSensitiveValuesTransformer < TypedTransformer
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
6
|
+
def from(...)
|
7
|
+
super.tap do
|
8
|
+
associations = Foobara::DetachedEntity.construct_deep_associations(from_type)
|
9
|
+
|
10
|
+
associations&.values&.reverse&.each do |entity_type|
|
11
|
+
declaration = entity_type.declaration_data
|
12
|
+
sanitized_type_declaration = TypeDeclarations.remove_sensitive_types(declaration)
|
11
13
|
|
12
|
-
|
14
|
+
Domain.current.foobara_type_from_declaration(sanitized_type_declaration)
|
15
|
+
end
|
13
16
|
end
|
14
17
|
end
|
15
18
|
|
16
|
-
|
17
|
-
|
18
|
-
def initialize(...)
|
19
|
-
super
|
20
|
-
|
21
|
-
self.namespace = Namespace.current
|
22
|
-
|
23
|
-
type
|
19
|
+
def to_type_declaration
|
20
|
+
TypeDeclarations.remove_sensitive_types(from_type.declaration_data)
|
24
21
|
end
|
25
22
|
|
26
23
|
def transform(_value)
|
@@ -31,9 +28,11 @@ module Foobara
|
|
31
28
|
|
32
29
|
def sanitize_value(type, value)
|
33
30
|
if type.has_sensitive_types?
|
34
|
-
|
35
|
-
|
36
|
-
|
31
|
+
sanitized_value = Namespace.use to_type.created_in_namespace do
|
32
|
+
remover_class = TypeDeclarations.sensitive_value_remover_class_for_type(type)
|
33
|
+
remover = remover_class.new(from: type)
|
34
|
+
remover.process_value!(value)
|
35
|
+
end
|
37
36
|
|
38
37
|
[sanitized_value, sanitized_value != value]
|
39
38
|
else
|
@@ -3,87 +3,101 @@ module Foobara
|
|
3
3
|
# TODO: this should instead be a processor and have its own possible_errors
|
4
4
|
class TypedTransformer < Value::Transformer
|
5
5
|
class << self
|
6
|
-
|
7
|
-
|
8
|
-
# If we are a noop, then we are going to output D.type and we expect B.type
|
9
|
-
# We obviously have a problem if D is incompatible with our output type.
|
10
|
-
# We need to know B.output_type in order to say what we are going to output.
|
11
|
-
#
|
12
|
-
# Conversely, we need to know what D expects in order to say what we expect to receive (sometimes)
|
13
|
-
#
|
14
|
-
# So logic is... For C to say what its type is, it must know B's output_type.
|
15
|
-
# or... I guess for an inputs transformer, we need to know what D expects as its type, right?
|
16
|
-
# since we have an obligation be compatible with it.
|
17
|
-
#
|
18
|
-
# Use case 1: command line interface gets awkward with models
|
19
|
-
# 1. Command takes model A
|
20
|
-
# 2. we want an inputs transformer that takes A.attributes_type
|
21
|
-
# 3. Therefore its type is A.attributes_type
|
22
|
-
# 4. And also, its output type is A.attributes_type in this case since there's no need to actually create the
|
23
|
-
# models.
|
24
|
-
# 5. So to tell our type, we must know the type of what comes next.
|
25
|
-
#
|
26
|
-
# Use case 2:
|
27
|
-
# 1. Command takes foo: :integer but we want to take bar: :string
|
28
|
-
# 2. transformer has this hard-coded knowledge.
|
29
|
-
# 3. we don't need to receive either types to answer our input and output types.
|
30
|
-
#
|
31
|
-
# Use case 3: Changing a record into its primary key
|
32
|
-
# 1. Command has result type of A which is an Entity
|
33
|
-
# 2. transformer takes an A record and returns record.primary_key
|
34
|
-
# 3. To know the output type, we need to know the result type of the previous type.
|
35
|
-
# 4. To know the input type, we need to know the type of the previous transformer since they are the same.
|
36
|
-
# (however, by convention we can just use nil in this case.)
|
37
|
-
#
|
38
|
-
# Use case 4: document upload
|
39
|
-
# 1. Command takes input stream plus some document info
|
40
|
-
# 2. controller action receives temporary file path
|
41
|
-
# 3. transformer opens input stream and replaces file path with input stream
|
42
|
-
# 4. In this case, we have hard-coded types.
|
43
|
-
#
|
44
|
-
# Challenge: we seem to not know in advance if the transformer needs to know what comes before it or what comes
|
45
|
-
# after it. Unless we are writing a one-off transformer then we have hard-coded knowledge.
|
46
|
-
#
|
47
|
-
# Seems like input transformer really needs to know what comes next, the target type.
|
48
|
-
# Seems like output transformer might require to know what came previously
|
49
|
-
#
|
50
|
-
# Plan:
|
51
|
-
# 1. Both inputs transformer and result have similar structure... they have a relevant type that they transform.
|
52
|
-
# The difference is that the result takes previous steps output and transforms it to a different type, whereas
|
53
|
-
# the input transformer needs to know what comes next in order to communicate its types.
|
54
|
-
# So we might be able to get away with a transformed_type that accepts the from_type. And the calling code can
|
55
|
-
# interpret how it goes. This might create some awkwardness or confusion at least when creating one of the
|
56
|
-
# two types of transformer.
|
57
|
-
def type_declaration(_from_type)
|
58
|
-
# :nocov:
|
59
|
-
nil
|
60
|
-
# :nocov:
|
6
|
+
def requires_declaration_data?
|
7
|
+
false
|
61
8
|
end
|
62
9
|
|
63
|
-
def
|
64
|
-
|
10
|
+
def requires_parent_declaration_data?
|
11
|
+
false
|
12
|
+
end
|
65
13
|
|
66
|
-
|
67
|
-
|
68
|
-
dec
|
69
|
-
else
|
70
|
-
Domain.current.foobara_type_from_declaration(dec)
|
71
|
-
end
|
72
|
-
end
|
14
|
+
def from(...)
|
15
|
+
@from_type = Domain.current.foobara_type_from_declaration(...)
|
73
16
|
end
|
17
|
+
|
18
|
+
def to(...)
|
19
|
+
@to_type = Domain.current.foobara_type_from_declaration(...)
|
20
|
+
end
|
21
|
+
|
22
|
+
attr_reader :from_type, :to_type
|
23
|
+
end
|
24
|
+
|
25
|
+
def from_type_declaration
|
26
|
+
nil
|
27
|
+
end
|
28
|
+
|
29
|
+
def to_type_declaration
|
30
|
+
nil
|
31
|
+
end
|
32
|
+
|
33
|
+
def from_type
|
34
|
+
return @from_type if defined?(@from_type)
|
35
|
+
|
36
|
+
@from_type = self.class.from_type || if from_type_declaration
|
37
|
+
Domain.current.foobara_type_from_declaration(from_type_declaration)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def to_type
|
42
|
+
return @to_type if defined?(@to_type)
|
43
|
+
|
44
|
+
@to_type = self.class.to_type || if to_type_declaration
|
45
|
+
Domain.current.foobara_type_from_declaration(to_type_declaration)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def has_to_type?
|
50
|
+
!!to_type
|
74
51
|
end
|
75
52
|
|
76
|
-
|
53
|
+
def has_from_type?
|
54
|
+
!!from_type
|
55
|
+
end
|
56
|
+
|
57
|
+
def from(...)
|
58
|
+
@from_type = Domain.current.foobara_type_from_declaration(...)
|
59
|
+
end
|
60
|
+
|
61
|
+
def to(...)
|
62
|
+
@to_type = Domain.current.foobara_type_from_declaration(...)
|
63
|
+
end
|
77
64
|
|
78
|
-
def
|
79
|
-
|
65
|
+
def initialize(from: nil, to: nil)
|
66
|
+
super()
|
67
|
+
|
68
|
+
if from
|
69
|
+
self.from from
|
70
|
+
end
|
71
|
+
|
72
|
+
if to
|
73
|
+
self.to to
|
74
|
+
end
|
80
75
|
|
81
|
-
|
76
|
+
# we want to force these to be created now in the current name space if they are declarations
|
77
|
+
from_type
|
78
|
+
to_type
|
82
79
|
end
|
83
80
|
|
84
81
|
def process_value(value)
|
82
|
+
if has_from_type?
|
83
|
+
outcome = Namespace.use from_type.created_in_namespace do
|
84
|
+
from_type.process_value(value)
|
85
|
+
end
|
86
|
+
|
87
|
+
return outcome unless outcome.success?
|
88
|
+
|
89
|
+
value = outcome.result
|
90
|
+
end
|
91
|
+
|
85
92
|
output = transform(value)
|
86
|
-
|
93
|
+
|
94
|
+
if has_to_type?
|
95
|
+
Namespace.use to_type.created_in_namespace do
|
96
|
+
to_type.process_value(output)
|
97
|
+
end
|
98
|
+
else
|
99
|
+
Outcome.success(output)
|
100
|
+
end
|
87
101
|
end
|
88
102
|
end
|
89
103
|
end
|
@@ -12,10 +12,6 @@ module Foobara
|
|
12
12
|
Domain.current.foobara_type_builder.type_declaration_handler_for(...)
|
13
13
|
end
|
14
14
|
|
15
|
-
def lookup_absolute_type!(*, **opts, &)
|
16
|
-
Foobara::Namespace.global.foobara_lookup_type!(*, **opts.merge(mode: Namespace::LookupMode::ABSOLUTE), &)
|
17
|
-
end
|
18
|
-
|
19
15
|
def lookup_type!(...)
|
20
16
|
Foobara::Namespace.current.foobara_lookup_type!(...)
|
21
17
|
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Foobara
|
2
|
+
module Value
|
3
|
+
class Mutator < Processor
|
4
|
+
class << self
|
5
|
+
def foobara_manifest(to_include: Set.new, remove_sensitive: false)
|
6
|
+
super.merge(processor_type: :mutator)
|
7
|
+
end
|
8
|
+
|
9
|
+
def error_classes
|
10
|
+
[]
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def mutate(_value)
|
15
|
+
# :nocov:
|
16
|
+
raise "subclass responsibility"
|
17
|
+
# :nocov:
|
18
|
+
end
|
19
|
+
|
20
|
+
def process_value(value)
|
21
|
+
if applicable?(value)
|
22
|
+
mutate(value)
|
23
|
+
end
|
24
|
+
|
25
|
+
Outcome.success(value)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: foobara
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.88
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Miles Georgi
|
8
8
|
bindir: bin
|
9
9
|
cert_chain: []
|
10
|
-
date: 2025-03-
|
10
|
+
date: 2025-03-28 00:00:00.000000000 Z
|
11
11
|
dependencies:
|
12
12
|
- !ruby/object:Gem::Dependency
|
13
13
|
name: bigdecimal
|
@@ -27,30 +27,30 @@ dependencies:
|
|
27
27
|
name: foobara-lru-cache
|
28
28
|
requirement: !ruby/object:Gem::Requirement
|
29
29
|
requirements:
|
30
|
-
- - "
|
30
|
+
- - "~>"
|
31
31
|
- !ruby/object:Gem::Version
|
32
|
-
version:
|
32
|
+
version: 0.0.2
|
33
33
|
type: :runtime
|
34
34
|
prerelease: false
|
35
35
|
version_requirements: !ruby/object:Gem::Requirement
|
36
36
|
requirements:
|
37
|
-
- - "
|
37
|
+
- - "~>"
|
38
38
|
- !ruby/object:Gem::Version
|
39
|
-
version:
|
39
|
+
version: 0.0.2
|
40
40
|
- !ruby/object:Gem::Dependency
|
41
41
|
name: foobara-util
|
42
42
|
requirement: !ruby/object:Gem::Requirement
|
43
43
|
requirements:
|
44
|
-
- - "
|
44
|
+
- - "~>"
|
45
45
|
- !ruby/object:Gem::Version
|
46
|
-
version:
|
46
|
+
version: 0.0.11
|
47
47
|
type: :runtime
|
48
48
|
prerelease: false
|
49
49
|
version_requirements: !ruby/object:Gem::Requirement
|
50
50
|
requirements:
|
51
|
-
- - "
|
51
|
+
- - "~>"
|
52
52
|
- !ruby/object:Gem::Version
|
53
|
-
version:
|
53
|
+
version: 0.0.11
|
54
54
|
description: A command-centric and discoverable software framework with a focus on
|
55
55
|
domain concepts and abstracting away integration code
|
56
56
|
email:
|
@@ -179,6 +179,7 @@ files:
|
|
179
179
|
- projects/command_connectors/src/command_registry/exposed_command.rb
|
180
180
|
- projects/command_connectors/src/command_registry/exposed_domain.rb
|
181
181
|
- projects/command_connectors/src/command_registry/exposed_organization.rb
|
182
|
+
- projects/command_connectors/src/response_mutator.rb
|
182
183
|
- projects/command_connectors/src/serializer.rb
|
183
184
|
- projects/command_connectors/src/serializers/aggregate_serializer.rb
|
184
185
|
- projects/command_connectors/src/serializers/atomic_serializer.rb
|
@@ -359,7 +360,8 @@ files:
|
|
359
360
|
- projects/thread_parent/src/thread_parent.rb
|
360
361
|
- projects/type_declarations/lib/foobara/type_declarations.rb
|
361
362
|
- projects/type_declarations/src/attributes.rb
|
362
|
-
- projects/type_declarations/src/
|
363
|
+
- projects/type_declarations/src/attributes_transformers/only.rb
|
364
|
+
- projects/type_declarations/src/attributes_transformers/reject.rb
|
363
365
|
- projects/type_declarations/src/caster.rb
|
364
366
|
- projects/type_declarations/src/desugarizer.rb
|
365
367
|
- projects/type_declarations/src/dsl/attributes.rb
|
@@ -418,6 +420,7 @@ files:
|
|
418
420
|
- projects/value/lib/foobara/value.rb
|
419
421
|
- projects/value/src/caster.rb
|
420
422
|
- projects/value/src/data_error.rb
|
423
|
+
- projects/value/src/mutator.rb
|
421
424
|
- projects/value/src/processor.rb
|
422
425
|
- projects/value/src/processor/casting.rb
|
423
426
|
- projects/value/src/processor/multi.rb
|
@@ -1,33 +0,0 @@
|
|
1
|
-
module Foobara
|
2
|
-
class AttributesTransformer < TypeDeclarations::TypedTransformer
|
3
|
-
class << self
|
4
|
-
attr_accessor :only_attributes
|
5
|
-
|
6
|
-
def type_declaration(from_type)
|
7
|
-
from_declaration = from_type.declaration_data
|
8
|
-
to_declaration = TypeDeclarations::Attributes.only(from_declaration, *only_attributes)
|
9
|
-
|
10
|
-
if TypeDeclarations.declarations_equal?(from_declaration, to_declaration)
|
11
|
-
from_type
|
12
|
-
else
|
13
|
-
from_type.foobara_domain.foobara_type_from_declaration(to_declaration)
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
def only(*attribute_names)
|
18
|
-
transformer_class = Class.new(self)
|
19
|
-
transformer_class.only_attributes = attribute_names
|
20
|
-
|
21
|
-
transformer_class
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
def transform(inputs)
|
26
|
-
inputs.slice(*allowed_keys)
|
27
|
-
end
|
28
|
-
|
29
|
-
def allowed_keys
|
30
|
-
type.element_types.keys
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|