next_station 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/.aiignore +36 -0
- data/.idea/.gitignore +10 -0
- data/.idea/inspectionProfiles/Project_Default.xml +8 -0
- data/.idea/junie.xml +6 -0
- data/.idea/modules.xml +8 -0
- data/.idea/next_station.iml +54 -0
- data/.idea/vcs.xml +6 -0
- data/AGENTS.md +157 -0
- data/Gemfile +11 -0
- data/PLUGIN_SYSTEM_GUIDE.md +521 -0
- data/README.md +790 -0
- data/TODO.txt +6 -0
- data/examples/plugin_http_example.rb +102 -0
- data/lib/next_station/config/errors.yml +149 -0
- data/lib/next_station/config.rb +49 -0
- data/lib/next_station/environment.rb +42 -0
- data/lib/next_station/errors.rb +21 -0
- data/lib/next_station/logging/formatters/console.rb +38 -0
- data/lib/next_station/logging/formatters/json.rb +80 -0
- data/lib/next_station/logging/subscribers/base.rb +70 -0
- data/lib/next_station/logging/subscribers/custom.rb +25 -0
- data/lib/next_station/logging/subscribers/operation.rb +41 -0
- data/lib/next_station/logging/subscribers/step.rb +54 -0
- data/lib/next_station/logging.rb +35 -0
- data/lib/next_station/operation/class_methods.rb +299 -0
- data/lib/next_station/operation/errors.rb +97 -0
- data/lib/next_station/operation/node.rb +49 -0
- data/lib/next_station/operation.rb +393 -0
- data/lib/next_station/plugins.rb +23 -0
- data/lib/next_station/result.rb +124 -0
- data/lib/next_station/state.rb +64 -0
- data/lib/next_station/types.rb +11 -0
- data/lib/next_station/version.rb +5 -0
- data/lib/next_station.rb +36 -0
- metadata +203 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 4919adb566091f3858358dc3678ba9b4bdde44ef42a6dcf854c94d59567230f1
|
|
4
|
+
data.tar.gz: 279c5c6c85214489b599be67fad370048ba49bb0862f388c6a99b1b21d390ac0
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: ab2769ab95a44b9f1a5cb760b742f6f7bf9180ba3e412d75e0b39436178d7a37b3b43e30c430487b42fd1d8751f1a852b9602e80727a817cdf32f8b59270e989
|
|
7
|
+
data.tar.gz: 20708b8341888222dabf110e877dcb30bbeb54b2fade8f0654875af6be4377e92d4b3d607f37775d612eb8a30efacc9e2e344edc16908ee7be171dc79d2d2f9f
|
data/.aiignore
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
|
|
2
|
+
spec/contract
|
|
3
|
+
todo.txt
|
|
4
|
+
|
|
5
|
+
# Ignore build output directories
|
|
6
|
+
target/
|
|
7
|
+
out/
|
|
8
|
+
|
|
9
|
+
# Ignore Maven wrapper files
|
|
10
|
+
.mvn/
|
|
11
|
+
|
|
12
|
+
# Ignore project files
|
|
13
|
+
.idea/
|
|
14
|
+
*.iml
|
|
15
|
+
doc/
|
|
16
|
+
.yardoc
|
|
17
|
+
# Ignore compiled Java class files
|
|
18
|
+
*.class
|
|
19
|
+
|
|
20
|
+
# Ignore all .java files except the ones from the 'src/main' folder
|
|
21
|
+
*.java
|
|
22
|
+
!src/main/**/*.java
|
|
23
|
+
|
|
24
|
+
# Ignore test reports and test directories
|
|
25
|
+
test-results/
|
|
26
|
+
allure-results/
|
|
27
|
+
|
|
28
|
+
# Ignore logs and temporary files
|
|
29
|
+
logs/
|
|
30
|
+
*.log
|
|
31
|
+
*.tmp
|
|
32
|
+
*.gem
|
|
33
|
+
tmp/
|
|
34
|
+
|
|
35
|
+
/log
|
|
36
|
+
/tmp
|
data/.idea/.gitignore
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
<component name="InspectionProjectProfileManager">
|
|
2
|
+
<profile version="1.0">
|
|
3
|
+
<option name="myName" value="Project Default" />
|
|
4
|
+
<inspection_tool class="RubyResolve" enabled="false" level="WARNING" enabled_by_default="false">
|
|
5
|
+
<option name="warnImplicitResults" value="false" />
|
|
6
|
+
</inspection_tool>
|
|
7
|
+
</profile>
|
|
8
|
+
</component>
|
data/.idea/junie.xml
ADDED
data/.idea/modules.xml
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<project version="4">
|
|
3
|
+
<component name="ProjectModuleManager">
|
|
4
|
+
<modules>
|
|
5
|
+
<module fileurl="file://$PROJECT_DIR$/.idea/next_station.iml" filepath="$PROJECT_DIR$/.idea/next_station.iml" />
|
|
6
|
+
</modules>
|
|
7
|
+
</component>
|
|
8
|
+
</project>
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<module type="RUBY_MODULE" version="4">
|
|
3
|
+
<component name="ModuleRunConfigurationManager">
|
|
4
|
+
<shared />
|
|
5
|
+
</component>
|
|
6
|
+
<component name="NewModuleRootManager">
|
|
7
|
+
<content url="file://$MODULE_DIR$">
|
|
8
|
+
<sourceFolder url="file://$MODULE_DIR$/features" isTestSource="true" />
|
|
9
|
+
<sourceFolder url="file://$MODULE_DIR$/spec" isTestSource="true" />
|
|
10
|
+
<sourceFolder url="file://$MODULE_DIR$/test" isTestSource="true" />
|
|
11
|
+
<excludeFolder url="file://$MODULE_DIR$/doc" />
|
|
12
|
+
</content>
|
|
13
|
+
<orderEntry type="jdk" jdkName="rbenv: 4.0.1" jdkType="RUBY_SDK" />
|
|
14
|
+
<orderEntry type="sourceFolder" forTests="false" />
|
|
15
|
+
<orderEntry type="library" scope="PROVIDED" name="ast (v2.4.3, rbenv: 4.0.1) [gem]" level="application" />
|
|
16
|
+
<orderEntry type="library" scope="PROVIDED" name="bigdecimal (v4.0.1, rbenv: 4.0.1) [gem]" level="application" />
|
|
17
|
+
<orderEntry type="library" scope="PROVIDED" name="bundler (v4.0.5, rbenv: 4.0.1) [gem]" level="application" />
|
|
18
|
+
<orderEntry type="library" scope="PROVIDED" name="concurrent-ruby (v1.3.6, rbenv: 4.0.1) [gem]" level="application" />
|
|
19
|
+
<orderEntry type="library" scope="PROVIDED" name="diff-lcs (v1.6.2, rbenv: 4.0.1) [gem]" level="application" />
|
|
20
|
+
<orderEntry type="library" scope="PROVIDED" name="dry-configurable (v1.3.0, rbenv: 4.0.1) [gem]" level="application" />
|
|
21
|
+
<orderEntry type="library" scope="PROVIDED" name="dry-core (v1.2.0, rbenv: 4.0.1) [gem]" level="application" />
|
|
22
|
+
<orderEntry type="library" scope="PROVIDED" name="dry-events (v1.1.0, rbenv: 4.0.1) [gem]" level="application" />
|
|
23
|
+
<orderEntry type="library" scope="PROVIDED" name="dry-inflector (v1.3.1, rbenv: 4.0.1) [gem]" level="application" />
|
|
24
|
+
<orderEntry type="library" scope="PROVIDED" name="dry-initializer (v3.2.0, rbenv: 4.0.1) [gem]" level="application" />
|
|
25
|
+
<orderEntry type="library" scope="PROVIDED" name="dry-logic (v1.6.0, rbenv: 4.0.1) [gem]" level="application" />
|
|
26
|
+
<orderEntry type="library" scope="PROVIDED" name="dry-monitor (v1.0.1, rbenv: 4.0.1) [gem]" level="application" />
|
|
27
|
+
<orderEntry type="library" scope="PROVIDED" name="dry-schema (v1.15.0, rbenv: 4.0.1) [gem]" level="application" />
|
|
28
|
+
<orderEntry type="library" scope="PROVIDED" name="dry-struct (v1.8.0, rbenv: 4.0.1) [gem]" level="application" />
|
|
29
|
+
<orderEntry type="library" scope="PROVIDED" name="dry-types (v1.9.0, rbenv: 4.0.1) [gem]" level="application" />
|
|
30
|
+
<orderEntry type="library" scope="PROVIDED" name="dry-validation (v1.11.1, rbenv: 4.0.1) [gem]" level="application" />
|
|
31
|
+
<orderEntry type="library" scope="PROVIDED" name="ice_nine (v0.11.2, rbenv: 4.0.1) [gem]" level="application" />
|
|
32
|
+
<orderEntry type="library" scope="PROVIDED" name="json (v2.18.0, rbenv: 4.0.1) [gem]" level="application" />
|
|
33
|
+
<orderEntry type="library" scope="PROVIDED" name="language_server-protocol (v3.17.0.5, rbenv: 4.0.1) [gem]" level="application" />
|
|
34
|
+
<orderEntry type="library" scope="PROVIDED" name="lint_roller (v1.1.0, rbenv: 4.0.1) [gem]" level="application" />
|
|
35
|
+
<orderEntry type="library" scope="PROVIDED" name="logger (v1.7.0, rbenv: 4.0.1) [gem]" level="application" />
|
|
36
|
+
<orderEntry type="library" scope="PROVIDED" name="parallel (v1.27.0, rbenv: 4.0.1) [gem]" level="application" />
|
|
37
|
+
<orderEntry type="library" scope="PROVIDED" name="parser (v3.3.10.1, rbenv: 4.0.1) [gem]" level="application" />
|
|
38
|
+
<orderEntry type="library" scope="PROVIDED" name="prism (v1.9.0, rbenv: 4.0.1) [gem]" level="application" />
|
|
39
|
+
<orderEntry type="library" scope="PROVIDED" name="racc (v1.8.1, rbenv: 4.0.1) [gem]" level="application" />
|
|
40
|
+
<orderEntry type="library" scope="PROVIDED" name="rainbow (v3.1.1, rbenv: 4.0.1) [gem]" level="application" />
|
|
41
|
+
<orderEntry type="library" scope="PROVIDED" name="regexp_parser (v2.11.3, rbenv: 4.0.1) [gem]" level="application" />
|
|
42
|
+
<orderEntry type="library" scope="PROVIDED" name="rspec (v3.13.2, rbenv: 4.0.1) [gem]" level="application" />
|
|
43
|
+
<orderEntry type="library" scope="PROVIDED" name="rspec-core (v3.13.6, rbenv: 4.0.1) [gem]" level="application" />
|
|
44
|
+
<orderEntry type="library" scope="PROVIDED" name="rspec-expectations (v3.13.5, rbenv: 4.0.1) [gem]" level="application" />
|
|
45
|
+
<orderEntry type="library" scope="PROVIDED" name="rspec-mocks (v3.13.7, rbenv: 4.0.1) [gem]" level="application" />
|
|
46
|
+
<orderEntry type="library" scope="PROVIDED" name="rspec-support (v3.13.7, rbenv: 4.0.1) [gem]" level="application" />
|
|
47
|
+
<orderEntry type="library" scope="PROVIDED" name="rubocop (v1.84.0, rbenv: 4.0.1) [gem]" level="application" />
|
|
48
|
+
<orderEntry type="library" scope="PROVIDED" name="rubocop-ast (v1.49.0, rbenv: 4.0.1) [gem]" level="application" />
|
|
49
|
+
<orderEntry type="library" scope="PROVIDED" name="ruby-progressbar (v1.13.0, rbenv: 4.0.1) [gem]" level="application" />
|
|
50
|
+
<orderEntry type="library" scope="PROVIDED" name="unicode-display_width (v3.2.0, rbenv: 4.0.1) [gem]" level="application" />
|
|
51
|
+
<orderEntry type="library" scope="PROVIDED" name="unicode-emoji (v4.2.0, rbenv: 4.0.1) [gem]" level="application" />
|
|
52
|
+
<orderEntry type="library" scope="PROVIDED" name="zeitwerk (v2.7.4, rbenv: 4.0.1) [gem]" level="application" />
|
|
53
|
+
</component>
|
|
54
|
+
</module>
|
data/.idea/vcs.xml
ADDED
data/AGENTS.md
ADDED
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
# Development Guidelines
|
|
2
|
+
|
|
3
|
+
This document defines the principles and conventions that should guide the development of this Ruby gem. The main goal is to produce code that is clean, readable, maintainable, and safe in concurrent environments, prioritizing long-term quality over short-term convenience.
|
|
4
|
+
|
|
5
|
+
## 0. What is the purpose of this gem?
|
|
6
|
+
|
|
7
|
+
> **Note:** This is just a high-level overview of the gem for reference. **Do not attempt to implement or write it from this description**—it’s meant to explain what the gem does, not how to build it.
|
|
8
|
+
|
|
9
|
+
NextStation is a lightweight, thread-safe toolkit for building Railway Oriented Programming (ROP) style operations in Ruby. It helps decouple business logic from controllers/models in both plain Ruby and Rails apps (without depending on Rails).
|
|
10
|
+
|
|
11
|
+
- Clean, SOLID-friendly DSL for defining operations and steps
|
|
12
|
+
- Immutable context, isolated operation state
|
|
13
|
+
- Explicit success/failure results with typed, localized errors
|
|
14
|
+
- Validations (dry-validation) and Results (dry-struct) integration
|
|
15
|
+
- Step controls: conditional skip, retries, and minimal branching
|
|
16
|
+
- Dependency Injection
|
|
17
|
+
- Plugins system with hook points (includes JSON Logging via semantic_logger)
|
|
18
|
+
- Introspection via class config helpers
|
|
19
|
+
|
|
20
|
+
## 1. Design Principles
|
|
21
|
+
|
|
22
|
+
### SOLID as a foundation
|
|
23
|
+
The application of SOLID principles should be favored whenever it is reasonable:
|
|
24
|
+
|
|
25
|
+
- Single Responsibility Principle (SRP)
|
|
26
|
+
Each class or module should have one clear responsibility.
|
|
27
|
+
- Open/Closed Principle (OCP)
|
|
28
|
+
Code should be open for extension but closed for modification.
|
|
29
|
+
- Liskov Substitution Principle (LSP)
|
|
30
|
+
Subtypes must be substitutable for their base types without unexpected behavior.
|
|
31
|
+
- Interface Segregation Principle (ISP)
|
|
32
|
+
Prefer small, focused interfaces over large, generic ones.
|
|
33
|
+
- Dependency Inversion Principle (DIP)
|
|
34
|
+
Depend on abstractions, not on concrete implementations.
|
|
35
|
+
|
|
36
|
+
SOLID principles are guidelines, not rigid rules.
|
|
37
|
+
Avoid forcing abstractions when they introduce unnecessary complexity, excessive nesting of files or directories, or an explosion of tiny classes.
|
|
38
|
+
|
|
39
|
+
## 2. Readability and Simplicity
|
|
40
|
+
|
|
41
|
+
- Code readability is a top priority.
|
|
42
|
+
- Prefer explicit and easy-to-understand code over clever or overly compact solutions.
|
|
43
|
+
- A new developer should be able to quickly understand the intent of the code.
|
|
44
|
+
- Use clear and descriptive names for classes, methods, and variables.
|
|
45
|
+
- Avoid comments that explain what the code does; the code should be self-explanatory.
|
|
46
|
+
- Comments should explain why a decision was made when it is not obvious.
|
|
47
|
+
- Yardoc comments are encouraged for public API. Must be updated to stay in sync with the current behavior if you
|
|
48
|
+
change that portion of the code.
|
|
49
|
+
|
|
50
|
+
## 3. RuboCop Conventions
|
|
51
|
+
|
|
52
|
+
- Code should follow RuboCop conventions as the general standard.
|
|
53
|
+
- Breaking a RuboCop rule is acceptable when:
|
|
54
|
+
- Following it introduces unnecessary complexity.
|
|
55
|
+
- It significantly harms readability.
|
|
56
|
+
- It forces unnatural or artificial code structures.
|
|
57
|
+
|
|
58
|
+
In such cases:
|
|
59
|
+
- The decision must be deliberate and justified.
|
|
60
|
+
- Prefer disabling rules locally (`# rubocop:disable`) rather than globally.
|
|
61
|
+
|
|
62
|
+
## 4. Thread Safety
|
|
63
|
+
|
|
64
|
+
The gem must be thread-safe by default, considering usage in concurrent environments.
|
|
65
|
+
|
|
66
|
+
Expected best practices:
|
|
67
|
+
|
|
68
|
+
- Avoid mutable global state.
|
|
69
|
+
- Do not use class variables (`@@`) unless strictly necessary and proven safe.
|
|
70
|
+
- Prefer immutable objects.
|
|
71
|
+
- Properly synchronize access to shared resources when required.
|
|
72
|
+
- Be cautious with memoization in concurrent contexts.
|
|
73
|
+
|
|
74
|
+
## 5. Framework-Agnostic Design (Rails Optional)
|
|
75
|
+
|
|
76
|
+
This gem is intended to be usable both in Rails and non-Rails environments.
|
|
77
|
+
|
|
78
|
+
Guidelines:
|
|
79
|
+
|
|
80
|
+
- Do not introduce dependencies that force users to install Rails-related gems.
|
|
81
|
+
- Avoid relying on Rails-specific libraries such as ActiveSupport, ActiveModel, etc.
|
|
82
|
+
- Use plain Ruby alternatives whenever possible.
|
|
83
|
+
- If Rails-specific integrations are needed, they should be:
|
|
84
|
+
- Optional
|
|
85
|
+
- Clearly isolated
|
|
86
|
+
- Loaded conditionally
|
|
87
|
+
|
|
88
|
+
The core functionality of the gem must remain framework-agnostic.
|
|
89
|
+
|
|
90
|
+
## 6. Code Structure
|
|
91
|
+
|
|
92
|
+
- Maintain a clear and consistent organization of files and modules.
|
|
93
|
+
- Modules should reflect the domain and intent of the code.
|
|
94
|
+
- Avoid oversized classes; split responsibilities when appropriate.
|
|
95
|
+
- Favor composition over inheritance.
|
|
96
|
+
|
|
97
|
+
## 7. Runtime Optimization (YJIT and JRuby)
|
|
98
|
+
This gem should be written with performance considerations for both **CRuby (with YJIT enabled)** and **JRuby**, without sacrificing readability or maintainability.
|
|
99
|
+
|
|
100
|
+
### YJIT Considerations (CRuby)
|
|
101
|
+
When writing code intended to benefit from YJIT:
|
|
102
|
+
|
|
103
|
+
- Avoid using OpenStruct
|
|
104
|
+
- Avoid redefining basic integer operations (i.e. +, -, <, >, etc.)
|
|
105
|
+
- Avoid redefining the meaning of nil, equality, etc.
|
|
106
|
+
- Avoid allocating objects in the hot parts of your code
|
|
107
|
+
- Minimize layers of indirection
|
|
108
|
+
- Avoid writing wrapper classes if you can (e.g. a class that only wraps a Ruby hash)
|
|
109
|
+
- Avoid methods that just call another method
|
|
110
|
+
- Ruby method calls are costly. Avoid things such as methods that only return a value from a hash
|
|
111
|
+
|
|
112
|
+
### JRuby Considerations
|
|
113
|
+
|
|
114
|
+
When targeting JRuby compatibility and performance:
|
|
115
|
+
|
|
116
|
+
- Avoid Ruby features with poor JVM performance characteristics (e.g., heavy use of `eval`).
|
|
117
|
+
- Prefer long-lived objects over frequent short-lived allocations when reasonable.
|
|
118
|
+
- Be mindful of object churn in hot paths.
|
|
119
|
+
- Avoid relying on MRI-specific behavior or undocumented internals.
|
|
120
|
+
- Ensure all code is compatible with JRuby’s threading and concurrency model.
|
|
121
|
+
|
|
122
|
+
## 8. Documentation Consistency
|
|
123
|
+
|
|
124
|
+
- Any functional or behavioral change must be reflected in the documentation.
|
|
125
|
+
- The README must be updated to stay in sync with the current behavior and API of the gem.
|
|
126
|
+
- Examples, usage instructions, and configuration options should accurately reflect the current implementation.
|
|
127
|
+
- Avoid specs that require excessive setup or deep object graphs.
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
## 9. RSpec Style and Structure
|
|
131
|
+
|
|
132
|
+
- Use `describe` for classes and modules.
|
|
133
|
+
- Use `context` to describe meaningful state or conditions.
|
|
134
|
+
- Use `it` blocks with clear, descriptive sentences.
|
|
135
|
+
- Prefer `let` over instance variables.
|
|
136
|
+
- Avoid excessive use of `before(:all)`; prefer `before(:each)`.
|
|
137
|
+
### Modification of existing specs:
|
|
138
|
+
If new behavior requires additional coverage:
|
|
139
|
+
- Add new test files or new examples.
|
|
140
|
+
- Test modifications are allowed only when they are strictly necessary to support new or explicitly requested functionality.
|
|
141
|
+
|
|
142
|
+
### Do NOT touch the human-generated specs.
|
|
143
|
+
- IMPORTANT: Files under `spec/contract/` are immutable and must never be modified by you.
|
|
144
|
+
|
|
145
|
+
### Ignore result of human-generated specs.
|
|
146
|
+
Spec under `spec/contract/` may fail as you do not control this. You must ignore the results of these specs.
|
|
147
|
+
- When running rspec or scpec commands, you can find a way to exclude those files during your test run.
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
## 10. Pragmatism
|
|
151
|
+
|
|
152
|
+
- These guidelines exist to improve the codebase, not to slow down development.
|
|
153
|
+
- When in doubt, choose and prefer the solution that is:
|
|
154
|
+
1. More readable
|
|
155
|
+
2. Simpler
|
|
156
|
+
3. Easier to maintain in the long term
|
|
157
|
+
- Dont forget to update the README.
|