nocode 0.0.3 → 0.0.4
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/.github/workflows/rubygem.yml +2 -0
- data/.rubocop.yml +0 -3
- data/CHANGELOG.md +5 -0
- data/README.md +4 -6
- data/lib/nocode/context.rb +2 -0
- data/lib/nocode/executor.rb +2 -2
- data/lib/nocode/step.rb +10 -2
- data/lib/nocode/step_registry.rb +6 -0
- data/lib/nocode/steps/copy.rb +2 -1
- data/lib/nocode/steps/delete.rb +1 -0
- data/lib/nocode/steps/deserialize/csv.rb +1 -0
- data/lib/nocode/steps/deserialize/json.rb +1 -0
- data/lib/nocode/steps/deserialize/yaml.rb +22 -0
- data/lib/nocode/steps/io/read.rb +1 -0
- data/lib/nocode/steps/io/write.rb +1 -0
- data/lib/nocode/steps/log.rb +1 -0
- data/lib/nocode/steps/serialize/csv.rb +2 -0
- data/lib/nocode/steps/serialize/json.rb +2 -0
- data/lib/nocode/steps/serialize/yaml.rb +19 -0
- data/lib/nocode/steps/set.rb +1 -0
- data/lib/nocode/steps/sleep.rb +1 -0
- data/lib/nocode/util/arrayable.rb +1 -0
- data/lib/nocode/util/class_loader.rb +1 -0
- data/lib/nocode/util/class_registry.rb +3 -0
- data/lib/nocode/util/dictionary.rb +1 -0
- data/lib/nocode/util/object_template.rb +44 -0
- data/lib/nocode/util/optionable.rb +14 -0
- data/lib/nocode/util/string_template.rb +6 -1
- data/lib/nocode/util.rb +1 -1
- data/lib/nocode/version.rb +1 -1
- data/lib/nocode.rb +2 -0
- data/nocode.gemspec +1 -0
- metadata +18 -2
- data/lib/nocode/object_template.rb +0 -34
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 884ab5737629463437ef0991555e1ea30faa8db0cd6d8c79da712942aa69011b
|
4
|
+
data.tar.gz: d8562fdf11b2a204e9ced685b434d6959bafe2dca605dd3795355aeed1ed5238
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 677aa00aba3a998a4cc616002420c9366ac945fabdfc336d948b5158c24eae6c9bfc1b8a7ee658718c5c55af4148c4f83656fddf8b45995002471ef7224870da
|
7
|
+
data.tar.gz: e4de53676eaebb1d9bd3738dbbbb6df777ce0fdf1674e9aa370176c2eca9d42d4672d6edd682a313b943f24d149566491d1d7322d9c30ed0cc352db7730e0f3f
|
data/.rubocop.yml
CHANGED
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -2,9 +2,7 @@
|
|
2
2
|
|
3
3
|
#### Execute Ruby code through YAML
|
4
4
|
|
5
|
-
[](https://github.com/mattruggio/nocode/actions/workflows/rubygem.yml)
|
6
|
-
|
7
|
-
**Warning**: This library is currently experimental.
|
5
|
+
[](https://badge.fury.io/rb/nocode) [](https://github.com/mattruggio/nocode/actions/workflows/rubygem.yml)
|
8
6
|
|
9
7
|
This is a proof of concept showing how a YAML interface could be draped over arbitrary Ruby code. The YAML contains a series of steps with each step mapping to a specific Ruby class. The Ruby classes just have one responsibility: to implement #perform.
|
10
8
|
|
@@ -113,16 +111,16 @@ Note: ensure you have proper authorization before trying to publish new versions
|
|
113
111
|
|
114
112
|
After code changes have successfully gone through the Pull Request review process then the following steps should be followed for publishing new versions:
|
115
113
|
|
116
|
-
1. Merge Pull Request into
|
114
|
+
1. Merge Pull Request into main
|
117
115
|
2. Update `version.rb` using [semantic versioning](https://semver.org/)
|
118
116
|
3. Install dependencies: `bundle`
|
119
117
|
4. Update `CHANGELOG.md` with release notes
|
120
|
-
5. Commit & push
|
118
|
+
5. Commit & push main to remote and ensure CI builds main successfully
|
121
119
|
6. Run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
122
120
|
|
123
121
|
## Code of Conduct
|
124
122
|
|
125
|
-
Everyone interacting in this codebase, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/mattruggio/nocode/blob/
|
123
|
+
Everyone interacting in this codebase, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/mattruggio/nocode/blob/main/CODE_OF_CONDUCT.md).
|
126
124
|
|
127
125
|
## License
|
128
126
|
|
data/lib/nocode/context.rb
CHANGED
data/lib/nocode/executor.rb
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative 'context'
|
4
|
-
require_relative 'object_template'
|
5
4
|
require_relative 'step_registry'
|
6
5
|
|
7
6
|
module Nocode
|
7
|
+
# Manages the lifecycle and executes a job.
|
8
8
|
class Executor
|
9
9
|
attr_reader :yaml, :io
|
10
10
|
|
@@ -38,7 +38,7 @@ module Nocode
|
|
38
38
|
private
|
39
39
|
|
40
40
|
def make_step(step, context)
|
41
|
-
step = ObjectTemplate.new(step).evaluate(context.to_h)
|
41
|
+
step = Util::ObjectTemplate.new(step).evaluate(context.to_h)
|
42
42
|
type = step['type'].to_s
|
43
43
|
name = step['name'].to_s
|
44
44
|
options = step['options'] || {}
|
data/lib/nocode/step.rb
CHANGED
@@ -1,14 +1,22 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Nocode
|
4
|
+
# Defines a running step. Steps should be sub-classes of this class as well as to implement
|
5
|
+
# #perform.
|
4
6
|
class Step
|
5
7
|
extend Forwardable
|
6
8
|
include Util::Arrayable
|
7
9
|
include Util::Optionable
|
8
10
|
|
9
|
-
attr_reader :
|
11
|
+
attr_reader :context,
|
12
|
+
:name,
|
13
|
+
:options,
|
14
|
+
:type
|
10
15
|
|
11
|
-
def_delegators :context,
|
16
|
+
def_delegators :context,
|
17
|
+
:io,
|
18
|
+
:parameters,
|
19
|
+
:registers
|
12
20
|
|
13
21
|
def initialize(
|
14
22
|
context: Context.new,
|
data/lib/nocode/step_registry.rb
CHANGED
@@ -2,7 +2,11 @@
|
|
2
2
|
|
3
3
|
require_relative 'step'
|
4
4
|
|
5
|
+
# This will execute the StepRegisty's load! method upon script evaluation.
|
5
6
|
module Nocode
|
7
|
+
# Provides a global place to register all valid steps by their types. By default the
|
8
|
+
# steps directory will be autoloaded and their paths will be used as their types. For example:
|
9
|
+
# for the class: steps/io/write, it would register as "io/write" type.
|
6
10
|
class StepRegistry < Util::ClassRegistry
|
7
11
|
include Singleton
|
8
12
|
|
@@ -22,9 +26,11 @@ module Nocode
|
|
22
26
|
def load!
|
23
27
|
files_loaded = Util::ClassLoader.new(DIR).load!
|
24
28
|
|
29
|
+
# Class the parent to load up the registry with the files we found.
|
25
30
|
load(files_loaded, PREFIX)
|
26
31
|
end
|
27
32
|
end
|
28
33
|
|
34
|
+
# Call upon class evaluation to autoload all classes.
|
29
35
|
StepRegistry.load!
|
30
36
|
end
|
data/lib/nocode/steps/copy.rb
CHANGED
@@ -2,11 +2,12 @@
|
|
2
2
|
|
3
3
|
module Nocode
|
4
4
|
module Steps
|
5
|
+
# Shallow-copy one register to another.
|
5
6
|
class Copy < Step
|
6
7
|
option :from_register, :to_register
|
7
8
|
|
8
9
|
def perform
|
9
|
-
registers[to_register_option] = registers[from_register_option]
|
10
|
+
registers[to_register_option] = registers[from_register_option].dup
|
10
11
|
end
|
11
12
|
end
|
12
13
|
end
|
data/lib/nocode/steps/delete.rb
CHANGED
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Nocode
|
4
|
+
module Steps
|
5
|
+
module Deserialize
|
6
|
+
# Take a specified register and parse it as YAML to produce Ruby object(s).
|
7
|
+
#
|
8
|
+
# NOTE: This will throw an error if unsafe YAML types are used. The only allowed types are
|
9
|
+
# array, hash, strings, numbers, booleans, nil. See:
|
10
|
+
# https://ruby-doc.org/stdlib-2.6.1/libdoc/psych/rdoc/Psych.html#method-c-safe_load
|
11
|
+
class Yaml < Step
|
12
|
+
option :register
|
13
|
+
|
14
|
+
def perform
|
15
|
+
input = registers[register_option]
|
16
|
+
|
17
|
+
registers[register_option] = YAML.safe_load(input)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/lib/nocode/steps/io/read.rb
CHANGED
data/lib/nocode/steps/log.rb
CHANGED
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Nocode
|
4
|
+
module Steps
|
5
|
+
module Serialize
|
6
|
+
# Take the contents of a register and serialize it as YAML. The serialized YAML
|
7
|
+
# will override the register specified.
|
8
|
+
class Yaml < Step
|
9
|
+
option :register
|
10
|
+
|
11
|
+
def perform
|
12
|
+
input = registers[register_option]
|
13
|
+
|
14
|
+
registers[register_option] = input.to_yaml
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/nocode/steps/set.rb
CHANGED
data/lib/nocode/steps/sleep.rb
CHANGED
@@ -2,6 +2,9 @@
|
|
2
2
|
|
3
3
|
module Nocode
|
4
4
|
module Util
|
5
|
+
# Create a type -> class constant interface. Classes can be registered as types. Types
|
6
|
+
# are snake-cased while class names are stored as pascal-cased. Then constant! can be called
|
7
|
+
# to retrieve the class constant by type.
|
5
8
|
class ClassRegistry
|
6
9
|
extend Forwardable
|
7
10
|
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'string_template'
|
4
|
+
|
5
|
+
module Nocode
|
6
|
+
module Util
|
7
|
+
# Built on top of StringTemplate but instead of only working for a string, this will
|
8
|
+
# recursively evaluate all strings within an object. Heuristics:
|
9
|
+
# - Strings evaluate using StringTemplate
|
10
|
+
# - Hashes will have their keys and values traversed
|
11
|
+
# - Arrays will have their entries traversed
|
12
|
+
# - All other types will simply return themselves
|
13
|
+
class ObjectTemplate
|
14
|
+
attr_reader :object
|
15
|
+
|
16
|
+
def initialize(object)
|
17
|
+
@object = object
|
18
|
+
|
19
|
+
freeze
|
20
|
+
end
|
21
|
+
|
22
|
+
def evaluate(values = {})
|
23
|
+
recursive_evaluate(object, values)
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def recursive_evaluate(expression, values)
|
29
|
+
case expression
|
30
|
+
when Array
|
31
|
+
expression.map { |o| recursive_evaluate(o, values) }
|
32
|
+
when Hash
|
33
|
+
expression.to_h do |k, v|
|
34
|
+
[recursive_evaluate(k, values), recursive_evaluate(v, values)]
|
35
|
+
end
|
36
|
+
when String
|
37
|
+
Util::StringTemplate.new(expression).evaluate(values)
|
38
|
+
else
|
39
|
+
expression
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -2,6 +2,20 @@
|
|
2
2
|
|
3
3
|
module Nocode
|
4
4
|
module Util
|
5
|
+
# Add on a DSL for classes. The DSL allows for a new class-level keyword called 'option'
|
6
|
+
# which can be used to describe what metadata values are important. Then instances
|
7
|
+
# can reference those option's values using magic _option methods. For example:
|
8
|
+
#
|
9
|
+
# class Animal
|
10
|
+
# include Optionable
|
11
|
+
# option :type
|
12
|
+
# attr_writer :options
|
13
|
+
# end
|
14
|
+
#
|
15
|
+
# animal = Animal.new
|
16
|
+
# animal.options = { 'type' => 'dog' }
|
17
|
+
#
|
18
|
+
# animal.type_option # -> should return 'dog'
|
5
19
|
module Optionable
|
6
20
|
def self.included(klass)
|
7
21
|
klass.extend(ClassMethods)
|
@@ -2,6 +2,11 @@
|
|
2
2
|
|
3
3
|
module Nocode
|
4
4
|
module Util
|
5
|
+
# Takes in an expression and interpolates in any parameters using << >> notation.
|
6
|
+
# For example:
|
7
|
+
# input = { 'person' => 'hops' }
|
8
|
+
# Nocode::Util::StringTemplate.new("Hello, << person.name >>!").evaluate(input)
|
9
|
+
# Should produce: "Hello, hops!"
|
5
10
|
class StringTemplate
|
6
11
|
LEFT_TOKEN = '<<'
|
7
12
|
RIGHT_TOKEN = '>>'
|
@@ -11,7 +16,7 @@ module Nocode
|
|
11
16
|
attr_reader :expression
|
12
17
|
|
13
18
|
def initialize(expression)
|
14
|
-
@expression = expression
|
19
|
+
@expression = expression.to_s
|
15
20
|
|
16
21
|
freeze
|
17
22
|
end
|
data/lib/nocode/util.rb
CHANGED
data/lib/nocode/version.rb
CHANGED
data/lib/nocode.rb
CHANGED
@@ -14,7 +14,9 @@ require 'nocode/util'
|
|
14
14
|
# Core
|
15
15
|
require 'nocode/executor'
|
16
16
|
|
17
|
+
# Establish main top-level namespace
|
17
18
|
module Nocode
|
19
|
+
# Default consumer entrypoint into the library.
|
18
20
|
class << self
|
19
21
|
def execute(yaml, io: $stdout)
|
20
22
|
Executor.new(yaml, io: io).execute
|
data/nocode.gemspec
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: nocode
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Matthew Ruggio
|
@@ -10,6 +10,20 @@ bindir: exe
|
|
10
10
|
cert_chain: []
|
11
11
|
date: 2022-02-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler-audit
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
13
27
|
- !ruby/object:Gem::Dependency
|
14
28
|
name: guard-rspec
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -162,18 +176,19 @@ files:
|
|
162
176
|
- lib/nocode.rb
|
163
177
|
- lib/nocode/context.rb
|
164
178
|
- lib/nocode/executor.rb
|
165
|
-
- lib/nocode/object_template.rb
|
166
179
|
- lib/nocode/step.rb
|
167
180
|
- lib/nocode/step_registry.rb
|
168
181
|
- lib/nocode/steps/copy.rb
|
169
182
|
- lib/nocode/steps/delete.rb
|
170
183
|
- lib/nocode/steps/deserialize/csv.rb
|
171
184
|
- lib/nocode/steps/deserialize/json.rb
|
185
|
+
- lib/nocode/steps/deserialize/yaml.rb
|
172
186
|
- lib/nocode/steps/io/read.rb
|
173
187
|
- lib/nocode/steps/io/write.rb
|
174
188
|
- lib/nocode/steps/log.rb
|
175
189
|
- lib/nocode/steps/serialize/csv.rb
|
176
190
|
- lib/nocode/steps/serialize/json.rb
|
191
|
+
- lib/nocode/steps/serialize/yaml.rb
|
177
192
|
- lib/nocode/steps/set.rb
|
178
193
|
- lib/nocode/steps/sleep.rb
|
179
194
|
- lib/nocode/util.rb
|
@@ -181,6 +196,7 @@ files:
|
|
181
196
|
- lib/nocode/util/class_loader.rb
|
182
197
|
- lib/nocode/util/class_registry.rb
|
183
198
|
- lib/nocode/util/dictionary.rb
|
199
|
+
- lib/nocode/util/object_template.rb
|
184
200
|
- lib/nocode/util/optionable.rb
|
185
201
|
- lib/nocode/util/string_template.rb
|
186
202
|
- lib/nocode/version.rb
|
@@ -1,34 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Nocode
|
4
|
-
class ObjectTemplate
|
5
|
-
attr_reader :object
|
6
|
-
|
7
|
-
def initialize(object)
|
8
|
-
@object = object
|
9
|
-
|
10
|
-
freeze
|
11
|
-
end
|
12
|
-
|
13
|
-
def evaluate(values = {})
|
14
|
-
recursive_evaluate(object, values)
|
15
|
-
end
|
16
|
-
|
17
|
-
private
|
18
|
-
|
19
|
-
def recursive_evaluate(expression, values)
|
20
|
-
case expression
|
21
|
-
when Array
|
22
|
-
expression.map { |o| recursive_evaluate(o, values) }
|
23
|
-
when Hash
|
24
|
-
expression.to_h do |k, v|
|
25
|
-
[recursive_evaluate(k, values), recursive_evaluate(v, values)]
|
26
|
-
end
|
27
|
-
when String
|
28
|
-
Util::StringTemplate.new(expression).evaluate(values)
|
29
|
-
else
|
30
|
-
expression
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|