senro_usecaser 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.
- checksums.yaml +7 -0
- data/.rspec +3 -0
- data/.rubocop.yml +72 -0
- data/LICENSE +21 -0
- data/README.md +1069 -0
- data/Rakefile +12 -0
- data/Steepfile +24 -0
- data/examples/RBS_GENERATION.md +16 -0
- data/examples/namespace_demo.rb +751 -0
- data/examples/order_system.rb +1279 -0
- data/examples/sig/namespace_demo.rbs +279 -0
- data/examples/sig/order_system.rbs +685 -0
- data/lefthook.yml +31 -0
- data/lib/senro_usecaser/base.rb +660 -0
- data/lib/senro_usecaser/configuration.rb +149 -0
- data/lib/senro_usecaser/container.rb +315 -0
- data/lib/senro_usecaser/error.rb +88 -0
- data/lib/senro_usecaser/provider.rb +212 -0
- data/lib/senro_usecaser/result.rb +182 -0
- data/lib/senro_usecaser/version.rb +8 -0
- data/lib/senro_usecaser.rb +155 -0
- data/sig/generated/senro_usecaser/base.rbs +365 -0
- data/sig/generated/senro_usecaser/configuration.rbs +80 -0
- data/sig/generated/senro_usecaser/container.rbs +190 -0
- data/sig/generated/senro_usecaser/error.rbs +58 -0
- data/sig/generated/senro_usecaser/provider.rbs +153 -0
- data/sig/generated/senro_usecaser/result.rbs +109 -0
- data/sig/generated/senro_usecaser/version.rbs +6 -0
- data/sig/generated/senro_usecaser.rbs +113 -0
- data/sig/overrides.rbs +16 -0
- metadata +77 -0
|
@@ -0,0 +1,365 @@
|
|
|
1
|
+
# Generated from lib/senro_usecaser/base.rb with RBS::Inline
|
|
2
|
+
|
|
3
|
+
module SenroUsecaser
|
|
4
|
+
# Represents a step in an organized pipeline
|
|
5
|
+
class Step
|
|
6
|
+
attr_reader use_case_class: untyped
|
|
7
|
+
|
|
8
|
+
attr_reader if_condition: untyped
|
|
9
|
+
|
|
10
|
+
attr_reader unless_condition: untyped
|
|
11
|
+
|
|
12
|
+
attr_reader on_failure: untyped
|
|
13
|
+
|
|
14
|
+
attr_reader all_conditions: untyped
|
|
15
|
+
|
|
16
|
+
attr_reader any_conditions: untyped
|
|
17
|
+
|
|
18
|
+
attr_reader input_mapping: untyped
|
|
19
|
+
|
|
20
|
+
# rubocop:disable Metrics/ParameterLists
|
|
21
|
+
# : (singleton(Base), ?if_condition: (Symbol | Proc)?, ?unless_condition: (Symbol | Proc)?, ?on_failure: Symbol?,
|
|
22
|
+
# : ?all_conditions: Array[(Symbol | Proc)]?, ?any_conditions: Array[(Symbol | Proc)]?,
|
|
23
|
+
# : ?input_mapping: (Symbol | Proc)?) -> void
|
|
24
|
+
def initialize: (untyped use_case_class, ?if_condition: untyped, ?unless_condition: untyped, ?on_failure: untyped, ?all_conditions: untyped, ?any_conditions: untyped, ?input_mapping: untyped) -> untyped
|
|
25
|
+
|
|
26
|
+
# Checks if this step should be executed based on conditions
|
|
27
|
+
#
|
|
28
|
+
# : (untyped, untyped) -> bool
|
|
29
|
+
def should_execute?: (untyped, untyped) -> bool
|
|
30
|
+
|
|
31
|
+
# Maps the input for this step based on input_mapping configuration
|
|
32
|
+
#
|
|
33
|
+
# : (untyped, untyped) -> untyped
|
|
34
|
+
def map_input: (untyped, untyped) -> untyped
|
|
35
|
+
|
|
36
|
+
private
|
|
37
|
+
|
|
38
|
+
# : ((Symbol | Proc), untyped, untyped) -> bool
|
|
39
|
+
def evaluate_condition: (Symbol | Proc, untyped, untyped) -> bool
|
|
40
|
+
|
|
41
|
+
# : (untyped, untyped) -> bool
|
|
42
|
+
def all_conditions_met?: (untyped, untyped) -> bool
|
|
43
|
+
|
|
44
|
+
# : (untyped, untyped) -> bool
|
|
45
|
+
def any_condition_met?: (untyped, untyped) -> bool
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Base class for all UseCases
|
|
49
|
+
#
|
|
50
|
+
# @example Basic UseCase with keyword arguments
|
|
51
|
+
# class CreateUserUseCase < SenroUsecaser::Base
|
|
52
|
+
# def call(name:, email:)
|
|
53
|
+
# user = User.create(name: name, email: email)
|
|
54
|
+
# success(user)
|
|
55
|
+
# end
|
|
56
|
+
# end
|
|
57
|
+
#
|
|
58
|
+
# result = CreateUserUseCase.call(name: "Taro", email: "taro@example.com")
|
|
59
|
+
#
|
|
60
|
+
# @example With input/output classes (recommended for pipelines)
|
|
61
|
+
# class CreateUserUseCase < SenroUsecaser::Base
|
|
62
|
+
# input CreateUserInput
|
|
63
|
+
# output CreateUserOutput
|
|
64
|
+
#
|
|
65
|
+
# def call(input)
|
|
66
|
+
# user = User.create(name: input.name, email: input.email)
|
|
67
|
+
# success(CreateUserOutput.new(user: user))
|
|
68
|
+
# end
|
|
69
|
+
# end
|
|
70
|
+
#
|
|
71
|
+
# @example Pipeline with input/output chaining
|
|
72
|
+
# class StepA < SenroUsecaser::Base
|
|
73
|
+
# input AInput
|
|
74
|
+
# output AOutput
|
|
75
|
+
# def call(input)
|
|
76
|
+
# success(AOutput.new(value: input.value * 2))
|
|
77
|
+
# end
|
|
78
|
+
# end
|
|
79
|
+
#
|
|
80
|
+
# class StepB < SenroUsecaser::Base
|
|
81
|
+
# input AOutput # Receives StepA's output directly
|
|
82
|
+
# output BOutput
|
|
83
|
+
# def call(input)
|
|
84
|
+
# success(BOutput.new(result: input.value + 1))
|
|
85
|
+
# end
|
|
86
|
+
# end
|
|
87
|
+
#
|
|
88
|
+
# class Pipeline < SenroUsecaser::Base
|
|
89
|
+
# organize StepA, StepB
|
|
90
|
+
# end
|
|
91
|
+
class Base
|
|
92
|
+
# Declares a dependency to be injected from the container
|
|
93
|
+
#
|
|
94
|
+
# : (Symbol, ?Class) -> void
|
|
95
|
+
def self.depends_on: (Symbol, ?Class) -> void
|
|
96
|
+
|
|
97
|
+
# Returns the list of declared dependencies
|
|
98
|
+
#
|
|
99
|
+
# : () -> Array[Symbol]
|
|
100
|
+
def self.dependencies: () -> Array[Symbol]
|
|
101
|
+
|
|
102
|
+
# Returns the dependency type mapping
|
|
103
|
+
#
|
|
104
|
+
# : () -> Hash[Symbol, Class]
|
|
105
|
+
def self.dependency_types: () -> Hash[Symbol, Class]
|
|
106
|
+
|
|
107
|
+
# Sets the namespace for dependency resolution
|
|
108
|
+
#
|
|
109
|
+
# : ((Symbol | String)) -> void
|
|
110
|
+
def self.namespace: (Symbol | String) -> void
|
|
111
|
+
|
|
112
|
+
# Returns the declared namespace
|
|
113
|
+
#
|
|
114
|
+
# : () -> (Symbol | String)?
|
|
115
|
+
attr_reader use_case_namespace: untyped
|
|
116
|
+
|
|
117
|
+
# Declares a sequence of UseCases to execute as a pipeline
|
|
118
|
+
#
|
|
119
|
+
# @example Basic organize
|
|
120
|
+
# organize StepA, StepB, StepC
|
|
121
|
+
#
|
|
122
|
+
# @example With block and step
|
|
123
|
+
# organize do
|
|
124
|
+
# step StepA
|
|
125
|
+
# step StepB, if: :should_run?
|
|
126
|
+
# step StepC, on_failure: :continue
|
|
127
|
+
# end
|
|
128
|
+
#
|
|
129
|
+
# : (*Class, ?on_failure: Symbol) ?{ () -> void } -> void
|
|
130
|
+
def self.organize: (*Class, ?on_failure: Symbol) ?{ () -> void } -> void
|
|
131
|
+
|
|
132
|
+
# Defines a step in the organize block
|
|
133
|
+
#
|
|
134
|
+
# rubocop:disable Metrics/ParameterLists
|
|
135
|
+
# : (Class, ?if: (Symbol | Proc)?, ?unless: (Symbol | Proc)?, ?on_failure: Symbol?,
|
|
136
|
+
# : ?all: Array[(Symbol | Proc)]?, ?any: Array[(Symbol | Proc)]?,
|
|
137
|
+
# : ?input: (Symbol | Proc)?) -> void
|
|
138
|
+
def self.step: (untyped use_case_class, ?if: untyped, ?unless: untyped, ?on_failure: untyped, ?all: untyped, ?any: untyped, ?input: untyped) -> untyped
|
|
139
|
+
|
|
140
|
+
# Returns the list of organized steps
|
|
141
|
+
#
|
|
142
|
+
# : () -> Array[Step]?
|
|
143
|
+
attr_reader organized_steps: untyped
|
|
144
|
+
|
|
145
|
+
# Returns the failure handling strategy
|
|
146
|
+
#
|
|
147
|
+
# : () -> Symbol
|
|
148
|
+
def self.on_failure_strategy: () -> Symbol
|
|
149
|
+
|
|
150
|
+
# Adds extension modules with hooks
|
|
151
|
+
#
|
|
152
|
+
# : (*Module) -> void
|
|
153
|
+
def self.extend_with: (*Module) -> void
|
|
154
|
+
|
|
155
|
+
# Returns the list of extensions
|
|
156
|
+
#
|
|
157
|
+
# : () -> Array[Module]
|
|
158
|
+
def self.extensions: () -> Array[Module]
|
|
159
|
+
|
|
160
|
+
# Adds a before hook
|
|
161
|
+
#
|
|
162
|
+
# : () { (untyped) -> void } -> void
|
|
163
|
+
def self.before: () { (untyped) -> void } -> void
|
|
164
|
+
|
|
165
|
+
# Returns the list of before hooks
|
|
166
|
+
#
|
|
167
|
+
# : () -> Array[Proc]
|
|
168
|
+
def self.before_hooks: () -> Array[Proc]
|
|
169
|
+
|
|
170
|
+
# Adds an after hook
|
|
171
|
+
#
|
|
172
|
+
# : () { (untyped, Result[untyped]) -> void } -> void
|
|
173
|
+
def self.after: () { (untyped, Result[untyped]) -> void } -> void
|
|
174
|
+
|
|
175
|
+
# Returns the list of after hooks
|
|
176
|
+
#
|
|
177
|
+
# : () -> Array[Proc]
|
|
178
|
+
def self.after_hooks: () -> Array[Proc]
|
|
179
|
+
|
|
180
|
+
# Adds an around hook
|
|
181
|
+
#
|
|
182
|
+
# : () { (untyped) { () -> Result[untyped] } -> Result[untyped] } -> void
|
|
183
|
+
def self.around: () ?{ (?) -> untyped } -> untyped
|
|
184
|
+
|
|
185
|
+
# Returns the list of around hooks
|
|
186
|
+
#
|
|
187
|
+
# : () -> Array[Proc]
|
|
188
|
+
def self.around_hooks: () -> Array[Proc]
|
|
189
|
+
|
|
190
|
+
# Declares the expected input type for this UseCase
|
|
191
|
+
#
|
|
192
|
+
# : (Class) -> void
|
|
193
|
+
def self.input: (Class) -> void
|
|
194
|
+
|
|
195
|
+
# Returns the input class
|
|
196
|
+
#
|
|
197
|
+
# : () -> Class?
|
|
198
|
+
attr_reader input_class: untyped
|
|
199
|
+
|
|
200
|
+
# Declares the expected output type for this UseCase
|
|
201
|
+
#
|
|
202
|
+
# : ((Class | Hash[Symbol, Class])) -> void
|
|
203
|
+
def self.output: (Class | Hash[Symbol, Class]) -> void
|
|
204
|
+
|
|
205
|
+
# Returns the output schema
|
|
206
|
+
#
|
|
207
|
+
# : () -> (Class | Hash[Symbol, Class])?
|
|
208
|
+
attr_reader output_schema: untyped
|
|
209
|
+
|
|
210
|
+
# Calls the UseCase with the given input
|
|
211
|
+
#
|
|
212
|
+
# : [T] (?untyped, ?container: Container, **untyped) -> Result[T]
|
|
213
|
+
def self.call: [T] (?untyped, ?container: Container, **untyped) -> Result[T]
|
|
214
|
+
|
|
215
|
+
# Calls the UseCase and captures any exceptions as failures
|
|
216
|
+
#
|
|
217
|
+
# : [T] (?untyped, ?container: Container, **untyped) -> Result[T]
|
|
218
|
+
def self.call!: [T] (?untyped, ?container: Container, **untyped) -> Result[T]
|
|
219
|
+
|
|
220
|
+
# Calls the UseCase with custom exception handling options
|
|
221
|
+
#
|
|
222
|
+
# : [T] (input: untyped, ?container: Container, ?exception_classes: Array[Class], ?code: Symbol) -> Result[T]
|
|
223
|
+
def self.call_with_capture: [T] (input: untyped, ?container: Container, ?exception_classes: Array[Class], ?code: Symbol) -> Result[T]
|
|
224
|
+
|
|
225
|
+
# @api private
|
|
226
|
+
def self.inherited: (untyped subclass) -> untyped
|
|
227
|
+
|
|
228
|
+
private def self.copy_configuration_to: (untyped subclass) -> untyped
|
|
229
|
+
|
|
230
|
+
private def self.copy_hooks_to: (untyped subclass) -> untyped
|
|
231
|
+
|
|
232
|
+
# Initializes the UseCase with dependencies resolved from the container
|
|
233
|
+
#
|
|
234
|
+
# : (?container: Container?, ?dependencies: Hash[Symbol, untyped]) -> void
|
|
235
|
+
def initialize: (?container: Container?, ?dependencies: Hash[Symbol, untyped]) -> void
|
|
236
|
+
|
|
237
|
+
# Performs the UseCase with hooks
|
|
238
|
+
#
|
|
239
|
+
# : (untyped, ?capture_exceptions: bool) -> Result[untyped]
|
|
240
|
+
def perform: (untyped, ?capture_exceptions: bool) -> Result[untyped]
|
|
241
|
+
|
|
242
|
+
# Executes the UseCase logic
|
|
243
|
+
#
|
|
244
|
+
# : (?untyped input) -> Result[untyped]
|
|
245
|
+
def call: (?untyped input) -> Result[untyped]
|
|
246
|
+
|
|
247
|
+
private
|
|
248
|
+
|
|
249
|
+
# Creates a success Result with the given value
|
|
250
|
+
#
|
|
251
|
+
# : [T] (T) -> Result[T]
|
|
252
|
+
def success: [T] (T) -> Result[T]
|
|
253
|
+
|
|
254
|
+
# Creates a failure Result with the given errors
|
|
255
|
+
#
|
|
256
|
+
# : (*Error) -> Result[untyped]
|
|
257
|
+
def failure: (*Error) -> Result[untyped]
|
|
258
|
+
|
|
259
|
+
# Creates a failure Result from an exception
|
|
260
|
+
#
|
|
261
|
+
# : (Exception, ?code: Symbol) -> Result[untyped]
|
|
262
|
+
def failure_from_exception: (Exception, ?code: Symbol) -> Result[untyped]
|
|
263
|
+
|
|
264
|
+
# Executes a block and captures any exceptions as failures
|
|
265
|
+
#
|
|
266
|
+
# : [T] (*Class, ?code: Symbol) { () -> T } -> Result[T]
|
|
267
|
+
def capture: [T] (*Class, ?code: Symbol) { () -> T } -> Result[T]
|
|
268
|
+
|
|
269
|
+
# Executes the core logic with before/after/around hooks
|
|
270
|
+
#
|
|
271
|
+
# : (untyped) { () -> Result[untyped] } -> Result[untyped]
|
|
272
|
+
def execute_with_hooks: (untyped) { () -> Result[untyped] } -> Result[untyped]
|
|
273
|
+
|
|
274
|
+
# Wraps a non-Result value in Result.success
|
|
275
|
+
#
|
|
276
|
+
# : (untyped) -> Result[untyped]
|
|
277
|
+
def wrap_result: (untyped) -> Result[untyped]
|
|
278
|
+
|
|
279
|
+
# Builds the around hook chain
|
|
280
|
+
#
|
|
281
|
+
# : (untyped, Proc) -> Proc
|
|
282
|
+
def build_around_chain: (untyped, Proc) -> Proc
|
|
283
|
+
|
|
284
|
+
# Collects all around hooks from extensions and block-based hooks
|
|
285
|
+
#
|
|
286
|
+
# : () -> Array[Proc]
|
|
287
|
+
def collect_around_hooks: () -> Array[Proc]
|
|
288
|
+
|
|
289
|
+
# Runs all before hooks
|
|
290
|
+
#
|
|
291
|
+
# : (untyped) -> void
|
|
292
|
+
def run_before_hooks: (untyped) -> void
|
|
293
|
+
|
|
294
|
+
# Runs all after hooks
|
|
295
|
+
#
|
|
296
|
+
# : (untyped, Result[untyped]) -> void
|
|
297
|
+
def run_after_hooks: (untyped, Result[untyped]) -> void
|
|
298
|
+
|
|
299
|
+
# Resolves dependencies from the container
|
|
300
|
+
#
|
|
301
|
+
# : (Container, Hash[Symbol, untyped]) -> void
|
|
302
|
+
def resolve_dependencies: (Container, Hash[Symbol, untyped]) -> void
|
|
303
|
+
|
|
304
|
+
# Resolves a single dependency from the container
|
|
305
|
+
#
|
|
306
|
+
# : (Container, Symbol) -> untyped
|
|
307
|
+
def resolve_from_container: (Container, Symbol) -> untyped
|
|
308
|
+
|
|
309
|
+
# Returns the effective namespace for dependency resolution
|
|
310
|
+
#
|
|
311
|
+
# : () -> (Symbol | String)?
|
|
312
|
+
def effective_namespace: () -> (Symbol | String)?
|
|
313
|
+
|
|
314
|
+
# Infers namespace from the class's module structure
|
|
315
|
+
#
|
|
316
|
+
# : () -> String?
|
|
317
|
+
def infer_namespace_from_class: () -> String?
|
|
318
|
+
|
|
319
|
+
# Executes the organized UseCase pipeline
|
|
320
|
+
#
|
|
321
|
+
# : (untyped) -> Result[untyped]
|
|
322
|
+
def execute_pipeline: (untyped) -> Result[untyped]
|
|
323
|
+
|
|
324
|
+
# Executes pipeline with :stop strategy
|
|
325
|
+
#
|
|
326
|
+
# : (untyped) -> Result[untyped]
|
|
327
|
+
def execute_pipeline_stop: (untyped) -> Result[untyped]
|
|
328
|
+
|
|
329
|
+
# Executes pipeline with :continue strategy
|
|
330
|
+
#
|
|
331
|
+
# : (untyped) -> Result[untyped]
|
|
332
|
+
def execute_pipeline_continue: (untyped) -> Result[untyped]
|
|
333
|
+
|
|
334
|
+
# Executes pipeline with :collect strategy
|
|
335
|
+
#
|
|
336
|
+
# : (untyped) -> Result[untyped]
|
|
337
|
+
def execute_pipeline_collect: (untyped) -> Result[untyped]
|
|
338
|
+
|
|
339
|
+
# Updates collect state and checks if pipeline should stop
|
|
340
|
+
#
|
|
341
|
+
# : (Result[untyped], Step, Hash[Symbol, untyped]) -> bool
|
|
342
|
+
def should_stop_collect_pipeline?: (Result[untyped], Step, Hash[Symbol, untyped]) -> bool
|
|
343
|
+
|
|
344
|
+
# Builds the final result for collect mode
|
|
345
|
+
#
|
|
346
|
+
# : (Hash[Symbol, untyped]) -> Result[untyped]
|
|
347
|
+
def build_collect_result: (Hash[Symbol, untyped]) -> Result[untyped]
|
|
348
|
+
|
|
349
|
+
# Executes a single step in the pipeline
|
|
350
|
+
#
|
|
351
|
+
# : (Step, untyped) -> Result[untyped]
|
|
352
|
+
def execute_step: (Step, untyped) -> Result[untyped]
|
|
353
|
+
|
|
354
|
+
# Determines if a step failure should stop the pipeline
|
|
355
|
+
#
|
|
356
|
+
# : (Step) -> bool
|
|
357
|
+
def step_should_stop?: (Step) -> bool
|
|
358
|
+
|
|
359
|
+
# Calls a single UseCase in the pipeline
|
|
360
|
+
# Requires input_class to be defined for pipeline steps
|
|
361
|
+
#
|
|
362
|
+
# : (singleton(Base), untyped) -> Result[untyped]
|
|
363
|
+
def call_use_case: (singleton(Base), untyped) -> Result[untyped]
|
|
364
|
+
end
|
|
365
|
+
end
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# Generated from lib/senro_usecaser/configuration.rb with RBS::Inline
|
|
2
|
+
|
|
3
|
+
module SenroUsecaser
|
|
4
|
+
# Configuration for SenroUsecaser
|
|
5
|
+
#
|
|
6
|
+
# @example
|
|
7
|
+
# SenroUsecaser.configure do |config|
|
|
8
|
+
# config.providers = [CoreProvider, UserProvider]
|
|
9
|
+
# config.infer_namespace_from_module = true
|
|
10
|
+
# end
|
|
11
|
+
class Configuration
|
|
12
|
+
# List of provider classes to boot
|
|
13
|
+
# : () -> Array[singleton(Provider)]
|
|
14
|
+
attr_accessor providers: untyped
|
|
15
|
+
|
|
16
|
+
# Whether to infer namespace from module structure
|
|
17
|
+
# : () -> bool
|
|
18
|
+
attr_accessor infer_namespace_from_module: untyped
|
|
19
|
+
|
|
20
|
+
# : () -> void
|
|
21
|
+
def initialize: () -> void
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Environment detection
|
|
25
|
+
#
|
|
26
|
+
# @example
|
|
27
|
+
# SenroUsecaser.env.development?
|
|
28
|
+
# SenroUsecaser.env.production?
|
|
29
|
+
class Environment
|
|
30
|
+
# : (String) -> void
|
|
31
|
+
def initialize: (String) -> void
|
|
32
|
+
|
|
33
|
+
# : () -> String
|
|
34
|
+
attr_reader name: untyped
|
|
35
|
+
|
|
36
|
+
# : () -> bool
|
|
37
|
+
def development?: () -> bool
|
|
38
|
+
|
|
39
|
+
# : () -> bool
|
|
40
|
+
def test?: () -> bool
|
|
41
|
+
|
|
42
|
+
# : () -> bool
|
|
43
|
+
def production?: () -> bool
|
|
44
|
+
|
|
45
|
+
# : () -> String
|
|
46
|
+
def to_s: () -> String
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Provider boot manager
|
|
50
|
+
#
|
|
51
|
+
# Resolves provider dependencies and boots them in correct order.
|
|
52
|
+
class ProviderBooter
|
|
53
|
+
# Error raised when circular dependencies are detected
|
|
54
|
+
class CircularDependencyError < StandardError
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# : (Array[singleton(Provider)], Container) -> void
|
|
58
|
+
def initialize: (Array[singleton(Provider)], Container) -> void
|
|
59
|
+
|
|
60
|
+
# Boots all providers in dependency order
|
|
61
|
+
#
|
|
62
|
+
# : () -> void
|
|
63
|
+
def boot!: () -> void
|
|
64
|
+
|
|
65
|
+
# Shuts down all providers in reverse order
|
|
66
|
+
#
|
|
67
|
+
# : () -> void
|
|
68
|
+
def shutdown!: () -> void
|
|
69
|
+
|
|
70
|
+
private
|
|
71
|
+
|
|
72
|
+
# Topologically sorts providers based on dependencies
|
|
73
|
+
#
|
|
74
|
+
# : (Array[singleton(Provider)]) -> Array[singleton(Provider)]
|
|
75
|
+
def topological_sort: (Array[singleton(Provider)]) -> Array[singleton(Provider)]
|
|
76
|
+
|
|
77
|
+
# : (singleton(Provider), Array[singleton(Provider)], untyped, untyped) -> void
|
|
78
|
+
def visit: (singleton(Provider), Array[singleton(Provider)], untyped, untyped) -> void
|
|
79
|
+
end
|
|
80
|
+
end
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
# Generated from lib/senro_usecaser/container.rb with RBS::Inline
|
|
2
|
+
|
|
3
|
+
module SenroUsecaser
|
|
4
|
+
# Wrapper for singleton registrations that caches the result
|
|
5
|
+
class SingletonRegistration
|
|
6
|
+
# : (^(Container) -> untyped) -> void
|
|
7
|
+
def initialize: (^(Container) -> untyped) -> void
|
|
8
|
+
|
|
9
|
+
# : (Container) -> untyped
|
|
10
|
+
def call: (Container) -> untyped
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# DI Container with namespace support
|
|
14
|
+
#
|
|
15
|
+
# @example Basic usage
|
|
16
|
+
# container = SenroUsecaser::Container.new
|
|
17
|
+
# container.register(:logger, Logger.new)
|
|
18
|
+
# container.resolve(:logger) # => Logger instance
|
|
19
|
+
#
|
|
20
|
+
# @example With namespaces
|
|
21
|
+
# container = SenroUsecaser::Container.new
|
|
22
|
+
# container.register(:logger, Logger.new)
|
|
23
|
+
#
|
|
24
|
+
# container.namespace(:admin) do
|
|
25
|
+
# register(:user_repository, AdminUserRepository.new)
|
|
26
|
+
# end
|
|
27
|
+
#
|
|
28
|
+
# # From admin namespace, can resolve both admin and root dependencies
|
|
29
|
+
# container.resolve_in(:admin, :user_repository) # => AdminUserRepository
|
|
30
|
+
# container.resolve_in(:admin, :logger) # => Logger (from root)
|
|
31
|
+
class Container
|
|
32
|
+
# Error raised when a dependency cannot be resolved
|
|
33
|
+
class ResolutionError < StandardError
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Error raised when a dependency is already registered
|
|
37
|
+
class DuplicateRegistrationError < StandardError
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# : (?parent: Container?) -> void
|
|
41
|
+
def initialize: (?parent: Container?) -> void
|
|
42
|
+
|
|
43
|
+
# Creates a scoped child container that inherits from this container
|
|
44
|
+
#
|
|
45
|
+
# @example
|
|
46
|
+
# scoped = container.scope do
|
|
47
|
+
# register(:current_user, current_user)
|
|
48
|
+
# end
|
|
49
|
+
# scoped.resolve(:current_user) # => current_user
|
|
50
|
+
# scoped.resolve(:logger) # => resolved from parent
|
|
51
|
+
#
|
|
52
|
+
# : () ?{ () -> void } -> Container
|
|
53
|
+
def scope: () ?{ () -> void } -> Container
|
|
54
|
+
|
|
55
|
+
# Registers a dependency in the current namespace
|
|
56
|
+
#
|
|
57
|
+
# @example With value (returns same value every time)
|
|
58
|
+
# container.register(:logger, Logger.new)
|
|
59
|
+
#
|
|
60
|
+
# @example With block (lazy evaluation, called every time, receives container)
|
|
61
|
+
# container.register(:database) { |container| Database.connect }
|
|
62
|
+
#
|
|
63
|
+
# : (Symbol, ?untyped) ?{ (Container) -> untyped } -> void
|
|
64
|
+
def register: (Symbol, ?untyped) ?{ (Container) -> untyped } -> void
|
|
65
|
+
|
|
66
|
+
# Registers a lazy dependency (block is called every time on resolve)
|
|
67
|
+
#
|
|
68
|
+
# @example
|
|
69
|
+
# container.register_lazy(:connection) { |c| Database.connect }
|
|
70
|
+
#
|
|
71
|
+
# @example With dependency resolution
|
|
72
|
+
# container.register_lazy(:user_repository) do |container|
|
|
73
|
+
# UserRepository.new(current_user: container.resolve(:current_user))
|
|
74
|
+
# end
|
|
75
|
+
#
|
|
76
|
+
# : [T] (Symbol) { (Container) -> T } -> void
|
|
77
|
+
def register_lazy: [T] (Symbol) { (Container) -> T } -> void
|
|
78
|
+
|
|
79
|
+
# Registers a singleton dependency (block is called once and cached)
|
|
80
|
+
#
|
|
81
|
+
# @example
|
|
82
|
+
# container.register_singleton(:database) { |c| Database.connect }
|
|
83
|
+
# container.resolve(:database) # => same instance every time
|
|
84
|
+
#
|
|
85
|
+
# @example With dependency resolution
|
|
86
|
+
# container.register_singleton(:service) do |container|
|
|
87
|
+
# Service.new(logger: container.resolve(:logger))
|
|
88
|
+
# end
|
|
89
|
+
#
|
|
90
|
+
# : [T] (Symbol) { (Container) -> T } -> void
|
|
91
|
+
def register_singleton: [T] (Symbol) { (Container) -> T } -> void
|
|
92
|
+
|
|
93
|
+
# Resolves a dependency from the current namespace or its ancestors
|
|
94
|
+
#
|
|
95
|
+
# @example
|
|
96
|
+
# container.resolve(:logger)
|
|
97
|
+
#
|
|
98
|
+
# : [T] (Symbol) -> T
|
|
99
|
+
def resolve: [T] (Symbol) -> T
|
|
100
|
+
|
|
101
|
+
# Resolves a dependency from a specific namespace or its ancestors
|
|
102
|
+
#
|
|
103
|
+
# @example
|
|
104
|
+
# container.resolve_in(:admin, :logger)
|
|
105
|
+
# container.resolve_in("admin::reports", :generator)
|
|
106
|
+
#
|
|
107
|
+
# : [T] ((Symbol | String | Array[Symbol]), Symbol) -> T
|
|
108
|
+
def resolve_in: [T] (Symbol | String | Array[Symbol], Symbol) -> T
|
|
109
|
+
|
|
110
|
+
# Checks if a dependency is registered
|
|
111
|
+
#
|
|
112
|
+
# : (Symbol) -> bool
|
|
113
|
+
def registered?: (Symbol) -> bool
|
|
114
|
+
|
|
115
|
+
# Checks if a dependency is registered in a specific namespace or its ancestors
|
|
116
|
+
#
|
|
117
|
+
# : ((Symbol | String | Array[Symbol]), Symbol) -> bool
|
|
118
|
+
def registered_in?: (Symbol | String | Array[Symbol], Symbol) -> bool
|
|
119
|
+
|
|
120
|
+
# Creates a namespace scope for registering dependencies
|
|
121
|
+
#
|
|
122
|
+
# @example
|
|
123
|
+
# container.namespace(:admin) do
|
|
124
|
+
# register(:user_repository, AdminUserRepository.new)
|
|
125
|
+
#
|
|
126
|
+
# namespace(:reports) do
|
|
127
|
+
# register(:generator, ReportGenerator.new)
|
|
128
|
+
# end
|
|
129
|
+
# end
|
|
130
|
+
#
|
|
131
|
+
# : ((Symbol | String)) { () -> void } -> void
|
|
132
|
+
def namespace: (Symbol | String) { () -> void } -> void
|
|
133
|
+
|
|
134
|
+
# Returns all registered keys (including parent keys)
|
|
135
|
+
#
|
|
136
|
+
# : () -> Array[String]
|
|
137
|
+
def keys: () -> Array[String]
|
|
138
|
+
|
|
139
|
+
# Returns only keys registered in this container (excluding parent)
|
|
140
|
+
#
|
|
141
|
+
# : () -> Array[String]
|
|
142
|
+
def own_keys: () -> Array[String]
|
|
143
|
+
|
|
144
|
+
# Returns the parent container if any
|
|
145
|
+
#
|
|
146
|
+
# : () -> Container?
|
|
147
|
+
attr_reader parent: untyped
|
|
148
|
+
|
|
149
|
+
# Clears all registrations
|
|
150
|
+
#
|
|
151
|
+
# : () -> void
|
|
152
|
+
def clear!: () -> void
|
|
153
|
+
|
|
154
|
+
private
|
|
155
|
+
|
|
156
|
+
# : () -> String
|
|
157
|
+
def current_namespace_path: () -> String
|
|
158
|
+
|
|
159
|
+
# : (Symbol) -> String
|
|
160
|
+
def build_key: (Symbol) -> String
|
|
161
|
+
|
|
162
|
+
# : (Array[Symbol], Symbol) -> String
|
|
163
|
+
def build_key_with_namespace: (Array[Symbol], Symbol) -> String
|
|
164
|
+
|
|
165
|
+
# : ((Symbol | String | Array[Symbol])) -> Array[Symbol]
|
|
166
|
+
def normalize_namespace: (Symbol | String | Array[Symbol]) -> Array[Symbol]
|
|
167
|
+
|
|
168
|
+
# : (Array[Symbol]) -> Array[Symbol]
|
|
169
|
+
def normalize_array_namespace: (Array[Symbol]) -> Array[Symbol]
|
|
170
|
+
|
|
171
|
+
# : (Symbol) -> Array[Symbol]
|
|
172
|
+
def normalize_symbol_namespace: (Symbol) -> Array[Symbol]
|
|
173
|
+
|
|
174
|
+
# : (String) -> Array[Symbol]
|
|
175
|
+
def normalize_string_namespace: (String) -> Array[Symbol]
|
|
176
|
+
|
|
177
|
+
# : (String) -> void
|
|
178
|
+
def check_duplicate_registration!: (String) -> void
|
|
179
|
+
|
|
180
|
+
# Invokes a registration, passing the container for dependency resolution
|
|
181
|
+
#
|
|
182
|
+
# : (untyped) -> untyped
|
|
183
|
+
def invoke_registration: (untyped) -> untyped
|
|
184
|
+
|
|
185
|
+
# Finds a registration in this container or its parent chain
|
|
186
|
+
#
|
|
187
|
+
# : ((Symbol | String | Array[Symbol]), Symbol) -> untyped
|
|
188
|
+
def find_registration: (Symbol | String | Array[Symbol], Symbol) -> untyped
|
|
189
|
+
end
|
|
190
|
+
end
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# Generated from lib/senro_usecaser/error.rb with RBS::Inline
|
|
2
|
+
|
|
3
|
+
module SenroUsecaser
|
|
4
|
+
# Represents an error in a Result
|
|
5
|
+
#
|
|
6
|
+
# @example Basic error
|
|
7
|
+
# error = SenroUsecaser::Error.new(
|
|
8
|
+
# code: :invalid_email,
|
|
9
|
+
# message: "Email format is invalid",
|
|
10
|
+
# field: :email
|
|
11
|
+
# )
|
|
12
|
+
#
|
|
13
|
+
# @example Error from exception
|
|
14
|
+
# begin
|
|
15
|
+
# # some code that raises
|
|
16
|
+
# rescue => e
|
|
17
|
+
# error = SenroUsecaser::Error.new(
|
|
18
|
+
# code: :unexpected_error,
|
|
19
|
+
# message: e.message,
|
|
20
|
+
# cause: e
|
|
21
|
+
# )
|
|
22
|
+
# end
|
|
23
|
+
class Error
|
|
24
|
+
# : Symbol
|
|
25
|
+
attr_reader code: untyped
|
|
26
|
+
|
|
27
|
+
# : String
|
|
28
|
+
attr_reader message: untyped
|
|
29
|
+
|
|
30
|
+
# : Symbol?
|
|
31
|
+
attr_reader field: untyped
|
|
32
|
+
|
|
33
|
+
# : Exception?
|
|
34
|
+
attr_reader cause: untyped
|
|
35
|
+
|
|
36
|
+
# : (code: Symbol, message: String, ?field: Symbol?, ?cause: Exception?) -> void
|
|
37
|
+
def initialize: (code: Symbol, message: String, ?field: Symbol?, ?cause: Exception?) -> void
|
|
38
|
+
|
|
39
|
+
# Creates an Error from an exception
|
|
40
|
+
#
|
|
41
|
+
# : (Exception, ?code: Symbol) -> Error
|
|
42
|
+
def self.from_exception: (Exception, ?code: Symbol) -> Error
|
|
43
|
+
|
|
44
|
+
# Returns true if this error was caused by an exception
|
|
45
|
+
#
|
|
46
|
+
# : () -> bool
|
|
47
|
+
def caused_by_exception?: () -> bool
|
|
48
|
+
|
|
49
|
+
# : (Error) -> bool
|
|
50
|
+
def ==: (Error) -> bool
|
|
51
|
+
|
|
52
|
+
# : () -> String
|
|
53
|
+
def to_s: () -> String
|
|
54
|
+
|
|
55
|
+
# : () -> String
|
|
56
|
+
def inspect: () -> String
|
|
57
|
+
end
|
|
58
|
+
end
|