lite-command 3.1.5 → 3.2.1
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 +8 -0
- data/Gemfile.lock +1 -1
- data/README.md +42 -101
- data/lib/lite/command/base.rb +2 -1
- data/lib/lite/command/internals/attributes.rb +3 -3
- data/lib/lite/command/internals/calls.rb +0 -2
- data/lib/lite/command/internals/executions.rb +9 -16
- data/lib/lite/command/internals/hooks.rb +51 -0
- data/lib/lite/command/utils.rb +3 -1
- data/lib/lite/command/version.rb +1 -1
- data/lib/lite/command.rb +1 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e36dd86e0746fcaaa37f79e73a94b0ae406e1989c02105c6378c5f1ea8694165
|
4
|
+
data.tar.gz: a10c6bda6ce19982ef9b983faa7ffa7ad3063ae8fc627229dc725238475c86c3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f71e320cd7ec5b4c105900fd984c6f73fa30323ef734cf03b8b6333eebed459ac9c54234433864ce20b719ffa80eff6b3da9f4021257b965c7bc8380a3310518
|
7
|
+
data.tar.gz: 78563217138c0d55133d344e914a9edb59cf9e59aaece25af3d1486657741151737d21f33a054821b80f26e3fd6bc92934e27bc3b9b3287cce969017284fa495
|
data/CHANGELOG.md
CHANGED
@@ -6,6 +6,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
6
6
|
|
7
7
|
## [Unreleased]
|
8
8
|
|
9
|
+
## [3.2.1] - 2024-10-29
|
10
|
+
### Changed
|
11
|
+
- Allow if and unless evaluations to happen at the same time
|
12
|
+
|
13
|
+
## [3.2.0] - 2024-10-29
|
14
|
+
### Changed
|
15
|
+
- Move callbacks to hooks instead of try methods
|
16
|
+
|
9
17
|
## [3.1.5] - 2024-10-28
|
10
18
|
### Changed
|
11
19
|
- Renamed private `delegate` method to `delegates` to prevent rails clash
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -33,10 +33,9 @@ Or install it yourself as:
|
|
33
33
|
* [States](#states)
|
34
34
|
* [Statuses](#statuses)
|
35
35
|
* [Hooks](#hooks)
|
36
|
-
* [
|
37
|
-
* [Attribute Hooks](#attribute-hooks)
|
38
|
-
* [Execution Hooks](#execution-hooks)
|
36
|
+
* [Lifecycle Hooks](#lifecycle-hooks)
|
39
37
|
* [Status Hooks](#status-hooks)
|
38
|
+
* [State Hooks](#state-hooks)
|
40
39
|
* [Children](#children)
|
41
40
|
* [Throwing Faults](#throwing-faults)
|
42
41
|
* [Sequences](#sequences)
|
@@ -143,6 +142,10 @@ cmd.raise!(original: true) #=> raises Lite::Command::Fault
|
|
143
142
|
# On exception:
|
144
143
|
cmd.raise!(original: false) #=> raises Lite::Command::Error
|
145
144
|
cmd.raise!(original: true) #=> raises StandardError
|
145
|
+
|
146
|
+
# Access the exception objects directly
|
147
|
+
cmd.original_exception #=> <StandardError ...>
|
148
|
+
cmd.command_exception #=> <Lite::Command::Error ...>
|
146
149
|
```
|
147
150
|
|
148
151
|
### Dynamic Faults
|
@@ -286,10 +289,10 @@ cmd.context.decrypted_message #=> "Hola Mundo"
|
|
286
289
|
# With invalid options:
|
287
290
|
cmd = DecryptSecretMessage.call(encrypted_message: "idk", version: "v23")
|
288
291
|
cmd.status #=> "invalid"
|
289
|
-
cmd.reason #=> "Encrypted message is too short (minimum is 10 character). Version is not included in list
|
292
|
+
cmd.reason #=> "Encrypted message is too short (minimum is 10 character). Encrypted message has invalid magic numbers. Version is not included in list."
|
290
293
|
cmd.metadata #=> {
|
291
294
|
#=> user: ["is not included in list"],
|
292
|
-
#=> encrypted_message: ["is too short (minimum is 10 character)"]
|
295
|
+
#=> encrypted_message: ["is too short (minimum is 10 character)", "has invalid magic numbers"]
|
293
296
|
#=> }
|
294
297
|
```
|
295
298
|
|
@@ -361,9 +364,6 @@ cmd.status #=> "invalid"
|
|
361
364
|
cmd.reason #=> "Invalid message start value"
|
362
365
|
cmd.metadata #=> { i18n: "gb.invalid_start_value" }
|
363
366
|
|
364
|
-
cmd.original_exception #=> <RuntimeError ...>
|
365
|
-
cmd.command_exception #=> <DecryptSecretMessage::Error ...>
|
366
|
-
|
367
367
|
cmd.success? #=> false
|
368
368
|
cmd.noop? #=> false
|
369
369
|
cmd.invalid? #=> true
|
@@ -387,140 +387,81 @@ cmd.bad?("Other reason") #=> false
|
|
387
387
|
## Hooks
|
388
388
|
|
389
389
|
Use hooks to run arbituary code at transition points and on finalized internals.
|
390
|
-
|
391
|
-
|
390
|
+
All hooks are ran in the order they are defined. Hooks types can be defined
|
391
|
+
multiple times. Hooks are ran in the following order:
|
392
392
|
|
393
393
|
```ruby
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
-> 4. FooCommand.on_after_execution
|
404
|
-
-> 5. FooCommand.on_failure
|
405
|
-
-> 6. FooCommand.on_interrupted
|
394
|
+
1. after_initialize
|
395
|
+
2. on_pending
|
396
|
+
3. before_validation
|
397
|
+
4. after_validation
|
398
|
+
5. before_execution
|
399
|
+
6. on_executing
|
400
|
+
7. after_execution
|
401
|
+
8. on_[success, noop, invalid, failure, error]
|
402
|
+
9. on_[complete, interrupted]
|
406
403
|
```
|
407
404
|
|
408
|
-
###
|
405
|
+
### Lifecycle Hooks
|
409
406
|
|
410
|
-
Define
|
407
|
+
Define before and after callbacks to call around execution.
|
411
408
|
|
412
409
|
```ruby
|
413
410
|
class DecryptSecretMessage < Lite::Command::Base
|
414
411
|
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
def on_pending
|
422
|
-
# eg: Append additional contextual data
|
423
|
-
end
|
424
|
-
|
425
|
-
def on_executing
|
426
|
-
# eg: Insert inspection debugger
|
427
|
-
end
|
428
|
-
|
429
|
-
def on_complete
|
430
|
-
# eg: Log message for posterity
|
431
|
-
end
|
432
|
-
|
433
|
-
def on_interrupted
|
434
|
-
# eg: Report to APM with tags and metadata
|
435
|
-
end
|
436
|
-
|
437
|
-
end
|
438
|
-
```
|
439
|
-
|
440
|
-
### Attribute Hooks
|
441
|
-
|
442
|
-
Define before attribtue validation callbacks.
|
443
|
-
|
444
|
-
```ruby
|
445
|
-
class DecryptSecretMessage < Lite::Command::Base
|
412
|
+
after_initialize :some_method
|
413
|
+
before_validation :some_method
|
414
|
+
after_validation :some_method
|
415
|
+
before_execution :some_method
|
416
|
+
after_execution :some_method
|
446
417
|
|
447
418
|
def call
|
448
419
|
# ...
|
449
420
|
end
|
450
421
|
|
451
|
-
private
|
452
|
-
|
453
|
-
def on_before_validation
|
454
|
-
# eg: Normalize context data
|
455
|
-
end
|
456
|
-
|
457
422
|
end
|
458
423
|
```
|
459
424
|
|
460
|
-
###
|
425
|
+
### Status Hooks
|
461
426
|
|
462
|
-
Define
|
427
|
+
Define one or more callbacks that are called after execution for
|
428
|
+
specific statuses.
|
463
429
|
|
464
430
|
```ruby
|
465
431
|
class DecryptSecretMessage < Lite::Command::Base
|
466
432
|
|
433
|
+
on_success :some_method
|
434
|
+
on_noop :some_method
|
435
|
+
on_invalid :some_method
|
436
|
+
on_failure :some_method
|
437
|
+
on_error :some_method
|
438
|
+
|
467
439
|
def call
|
468
440
|
# ...
|
469
441
|
end
|
470
442
|
|
471
|
-
private
|
472
|
-
|
473
|
-
def on_before_execution
|
474
|
-
# eg: Append additional contextual data
|
475
|
-
end
|
476
|
-
|
477
|
-
def on_after_execution
|
478
|
-
# eg: Store results to database
|
479
|
-
end
|
480
|
-
|
481
443
|
end
|
482
444
|
```
|
483
445
|
|
484
|
-
###
|
446
|
+
### State Hooks
|
485
447
|
|
486
|
-
Define one or more callbacks that are called
|
487
|
-
specific statuses.
|
448
|
+
Define one or more callbacks that are called during transitions between states.
|
488
449
|
|
489
450
|
```ruby
|
490
451
|
class DecryptSecretMessage < Lite::Command::Base
|
491
452
|
|
453
|
+
on_pending :some_method
|
454
|
+
on_executing :some_method
|
455
|
+
on_complete :some_method
|
456
|
+
on_interrupted :some_method
|
457
|
+
|
492
458
|
def call
|
493
459
|
# ...
|
494
460
|
end
|
495
461
|
|
496
|
-
private
|
497
|
-
|
498
|
-
def on_success
|
499
|
-
# eg: Increment KPI counter
|
500
|
-
end
|
501
|
-
|
502
|
-
def on_noop(fault)
|
503
|
-
# eg: Log message for posterity
|
504
|
-
end
|
505
|
-
|
506
|
-
def on_invalid(fault)
|
507
|
-
# eg: Send metadata errors to frontend
|
508
|
-
end
|
509
|
-
|
510
|
-
def on_failure(fault)
|
511
|
-
# eg: Rollback record changes
|
512
|
-
end
|
513
|
-
|
514
|
-
def on_error(fault_or_exception)
|
515
|
-
# eg: Report to APM with tags and metadata
|
516
|
-
end
|
517
|
-
|
518
462
|
end
|
519
463
|
```
|
520
464
|
|
521
|
-
> [!NOTE]
|
522
|
-
> The `on_success` callback does **NOT** take any arguments.
|
523
|
-
|
524
465
|
## Children
|
525
466
|
|
526
467
|
When building complex commands, its best that you pass the parents context to the
|
data/lib/lite/command/base.rb
CHANGED
@@ -16,6 +16,7 @@ module Lite
|
|
16
16
|
base.include Internals::Faults
|
17
17
|
base.include Internals::Calls
|
18
18
|
base.include Internals::Executions
|
19
|
+
base.include Internals::Hooks
|
19
20
|
base.include Internals::Results
|
20
21
|
|
21
22
|
if Lite::Command.configuration.raise_dynamic_faults # rubocop:disable Style/GuardClause
|
@@ -34,7 +35,7 @@ module Lite
|
|
34
35
|
|
35
36
|
def initialize(context = {})
|
36
37
|
@context = Context.build(context)
|
37
|
-
|
38
|
+
run_hooks(:after_initialize)
|
38
39
|
end
|
39
40
|
|
40
41
|
end
|
@@ -52,9 +52,9 @@ module Lite
|
|
52
52
|
private
|
53
53
|
|
54
54
|
def validate_context_attributes
|
55
|
-
|
56
|
-
|
57
|
-
|
55
|
+
run_hooks(:before_validation)
|
56
|
+
invalid!(errors.full_messages.join(". "), metadata: errors.messages) unless valid?
|
57
|
+
run_hooks(:after_validation)
|
58
58
|
end
|
59
59
|
|
60
60
|
end
|
@@ -24,14 +24,12 @@ module Lite
|
|
24
24
|
|
25
25
|
def call(context = {})
|
26
26
|
instance = send(:new, context)
|
27
|
-
instance.validate
|
28
27
|
instance.send(:execute)
|
29
28
|
instance
|
30
29
|
end
|
31
30
|
|
32
31
|
def call!(context = {})
|
33
32
|
instance = send(:new, context)
|
34
|
-
instance.validate
|
35
33
|
instance.send(:execute!)
|
36
34
|
instance
|
37
35
|
end
|
@@ -50,16 +50,18 @@ module Lite
|
|
50
50
|
increment_execution_index
|
51
51
|
assign_execution_cmd_id
|
52
52
|
start_monotonic_time
|
53
|
-
|
53
|
+
run_hooks(:on_pending)
|
54
54
|
validate_context_attributes
|
55
|
-
|
55
|
+
run_hooks(:before_execution)
|
56
56
|
executing!
|
57
|
-
|
57
|
+
run_hooks(:on_executing)
|
58
58
|
end
|
59
59
|
|
60
60
|
def after_execution
|
61
61
|
send(:"#{success? ? COMPLETE : INTERRUPTED}!")
|
62
|
-
|
62
|
+
run_hooks(:after_execution)
|
63
|
+
run_hooks(:"on_#{status}")
|
64
|
+
run_hooks(:"on_#{state}")
|
63
65
|
stop_monotonic_time
|
64
66
|
append_execution_result
|
65
67
|
freeze_execution_objects
|
@@ -72,26 +74,17 @@ module Lite
|
|
72
74
|
end
|
73
75
|
|
74
76
|
def execute
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
fault(e, Utils.try(e, :type) || ERROR, metadata, exception: e)
|
79
|
-
after_execution
|
80
|
-
Utils.try(self, :"on_#{status}", e)
|
81
|
-
ensure
|
82
|
-
Utils.try(self, :"on_#{state}")
|
77
|
+
execute!
|
78
|
+
rescue StandardError
|
79
|
+
# Do nothing
|
83
80
|
end
|
84
81
|
|
85
82
|
def execute!
|
86
83
|
around_execution { call }
|
87
|
-
Utils.try(self, :on_success)
|
88
84
|
rescue StandardError => e
|
89
85
|
fault(e, Utils.try(e, :type) || ERROR, metadata, exception: e)
|
90
86
|
after_execution
|
91
|
-
Utils.try(self, :"on_#{status}", e)
|
92
87
|
raise(e)
|
93
|
-
else
|
94
|
-
Utils.try(self, :"on_#{state}")
|
95
88
|
end
|
96
89
|
|
97
90
|
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Lite
|
4
|
+
module Command
|
5
|
+
|
6
|
+
HOOKS = [
|
7
|
+
:after_initialize,
|
8
|
+
:before_validation,
|
9
|
+
:after_validation,
|
10
|
+
:before_execution,
|
11
|
+
:after_execution,
|
12
|
+
*STATUSES.map { |s| :"on_#{s}" },
|
13
|
+
*STATES.map { |s| :"on_#{s}" }
|
14
|
+
].freeze
|
15
|
+
|
16
|
+
module Internals
|
17
|
+
module Hooks
|
18
|
+
|
19
|
+
def self.included(base)
|
20
|
+
base.extend ClassMethods
|
21
|
+
end
|
22
|
+
|
23
|
+
module ClassMethods
|
24
|
+
|
25
|
+
def hooks
|
26
|
+
@hooks ||= Utils.try(superclass, :hooks).dup || {}
|
27
|
+
end
|
28
|
+
|
29
|
+
HOOKS.each do |h|
|
30
|
+
define_method(h) do |*method_names, &block|
|
31
|
+
method_names << block if block_given?
|
32
|
+
method_names.each { |mn| (hooks[h] ||= []) << mn }
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def run_hooks(hook)
|
41
|
+
hooks = self.class.hooks[hook]
|
42
|
+
return if hooks.nil?
|
43
|
+
|
44
|
+
hooks.each { |h| Utils.call(self, h) }
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
end
|
data/lib/lite/command/utils.rb
CHANGED
@@ -40,7 +40,9 @@ module Lite
|
|
40
40
|
end
|
41
41
|
|
42
42
|
def evaluate(object, options = {})
|
43
|
-
if options[:if]
|
43
|
+
if options[:if] && options[:unless]
|
44
|
+
call(object, options[:if]) && !call(object, options[:unless])
|
45
|
+
elsif options[:if]
|
44
46
|
call(object, options[:if])
|
45
47
|
elsif options[:unless]
|
46
48
|
!call(object, options[:unless])
|
data/lib/lite/command/version.rb
CHANGED
data/lib/lite/command.rb
CHANGED
@@ -16,6 +16,7 @@ require "lite/command/internals/attributes"
|
|
16
16
|
require "lite/command/internals/faults"
|
17
17
|
require "lite/command/internals/calls"
|
18
18
|
require "lite/command/internals/executions"
|
19
|
+
require "lite/command/internals/hooks"
|
19
20
|
require "lite/command/internals/results"
|
20
21
|
require "lite/command/base"
|
21
22
|
require "lite/command/step"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: lite-command
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.1
|
4
|
+
version: 3.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Juan Gomez
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-10-
|
11
|
+
date: 2024-10-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activemodel
|
@@ -201,6 +201,7 @@ files:
|
|
201
201
|
- lib/lite/command/internals/calls.rb
|
202
202
|
- lib/lite/command/internals/executions.rb
|
203
203
|
- lib/lite/command/internals/faults.rb
|
204
|
+
- lib/lite/command/internals/hooks.rb
|
204
205
|
- lib/lite/command/internals/results.rb
|
205
206
|
- lib/lite/command/internals/runtimes.rb
|
206
207
|
- lib/lite/command/sequence.rb
|