trailblazer-developer 0.0.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 +7 -0
- data/.gitignore +9 -0
- data/.rubocop-https---raw-githubusercontent-com-trailblazer-meta-master-rubocop-yml +115 -0
- data/.rubocop.yml +36 -0
- data/.travis.yml +6 -0
- data/Gemfile +12 -0
- data/README.md +17 -0
- data/Rakefile +14 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/trailblazer/developer.rb +12 -0
- data/lib/trailblazer/developer/activity.rb +51 -0
- data/lib/trailblazer/developer/client.rb +21 -0
- data/lib/trailblazer/developer/generate.rb +66 -0
- data/lib/trailblazer/developer/render/circuit.rb +51 -0
- data/lib/trailblazer/developer/version.rb +5 -0
- data/lib/trailblazer/developer/wtf.rb +92 -0
- data/lib/trailblazer/diagram/bpmn.rb +338 -0
- data/trailblazer-developer.gemspec +27 -0
- metadata +145 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 41c30437086de2bc9a0148eccf3db59603e484f92c032ff923cd0275fd369db0
|
|
4
|
+
data.tar.gz: bd45234bd028d5a5ef5348959da4b834ffdc6bf79af3821689718d76055ef4df
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: a66246114d6111e30c76993e18308675544b7623a8afcf732c9e0feab79cdda46dbcc3f789c20ea990c2276f1ef48321802b8f59c40706beab6480aa587bee80
|
|
7
|
+
data.tar.gz: 4bfdbbb63921aadf36c77c4c96a2da0e2efc0d283140b0263c504743bca92fbbc26a6f31ad7910bae09654e80a58c8d1deb53513fb1866c9e49bb060cc5ad313
|
data/.gitignore
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
AllCops:
|
|
2
|
+
TargetRubyVersion: 2.5.0
|
|
3
|
+
DisplayCopNames: true
|
|
4
|
+
Layout/CaseIndentation:
|
|
5
|
+
IndentOneStep: true
|
|
6
|
+
Layout/FirstArrayElementLineBreak:
|
|
7
|
+
Enabled: true
|
|
8
|
+
Layout/FirstHashElementLineBreak:
|
|
9
|
+
Enabled: true
|
|
10
|
+
Layout/FirstMethodArgumentLineBreak:
|
|
11
|
+
Enabled: true
|
|
12
|
+
Layout/FirstMethodParameterLineBreak:
|
|
13
|
+
Enabled: true
|
|
14
|
+
Layout/MultilineAssignmentLayout:
|
|
15
|
+
Enabled: true
|
|
16
|
+
EnforcedStyle: same_line
|
|
17
|
+
Layout/SpaceInsideHashLiteralBraces:
|
|
18
|
+
EnforcedStyle: no_space
|
|
19
|
+
Metrics/LineLength:
|
|
20
|
+
Max: 130
|
|
21
|
+
Metrics/ParameterLists:
|
|
22
|
+
Max: 5
|
|
23
|
+
Naming/VariableNumber:
|
|
24
|
+
EnforcedStyle: snake_case
|
|
25
|
+
Style/AndOr:
|
|
26
|
+
EnforcedStyle: conditionals
|
|
27
|
+
Style/AutoResourceCleanup:
|
|
28
|
+
Enabled: true
|
|
29
|
+
Style/CollectionMethods:
|
|
30
|
+
Enabled: true
|
|
31
|
+
Style/Documentation:
|
|
32
|
+
Enabled: false
|
|
33
|
+
Style/EmptyLiteral:
|
|
34
|
+
Enabled: false
|
|
35
|
+
Style/EmptyMethod:
|
|
36
|
+
EnforcedStyle: expanded
|
|
37
|
+
Style/FormatStringToken:
|
|
38
|
+
EnforcedStyle: template
|
|
39
|
+
Style/ImplicitRuntimeError:
|
|
40
|
+
Enabled: true
|
|
41
|
+
Style/MethodCalledOnDoEndBlock:
|
|
42
|
+
Enabled: true
|
|
43
|
+
Style/MethodDefParentheses:
|
|
44
|
+
EnforcedStyle: require_parentheses
|
|
45
|
+
Style/MissingElse:
|
|
46
|
+
Enabled: true
|
|
47
|
+
EnforcedStyle: case
|
|
48
|
+
Style/NumericLiterals:
|
|
49
|
+
Enabled: false
|
|
50
|
+
Style/OptionHash:
|
|
51
|
+
Enabled: true
|
|
52
|
+
Style/PercentLiteralDelimiters:
|
|
53
|
+
PreferredDelimiters:
|
|
54
|
+
"%w": "[]"
|
|
55
|
+
"%W": "[]"
|
|
56
|
+
"%i": "[]"
|
|
57
|
+
"%I": "[]"
|
|
58
|
+
"%r": "()"
|
|
59
|
+
Style/ReturnNil:
|
|
60
|
+
Enabled: true
|
|
61
|
+
Style/SafeNavigation:
|
|
62
|
+
Enabled: false
|
|
63
|
+
Style/Send:
|
|
64
|
+
Enabled: true
|
|
65
|
+
Style/SignalException:
|
|
66
|
+
EnforcedStyle: semantic
|
|
67
|
+
Style/StringLiterals:
|
|
68
|
+
EnforcedStyle: double_quotes
|
|
69
|
+
Style/StringLiteralsInInterpolation:
|
|
70
|
+
EnforcedStyle: double_quotes
|
|
71
|
+
Style/StringMethods:
|
|
72
|
+
Enabled: true
|
|
73
|
+
Style/SymbolArray:
|
|
74
|
+
Enabled: true
|
|
75
|
+
# this allows in rspec to have expect { } with multiple lines
|
|
76
|
+
Style/BlockDelimiters:
|
|
77
|
+
EnforcedStyle: braces_for_chaining
|
|
78
|
+
Layout/EndOfLine:
|
|
79
|
+
Enabled: false
|
|
80
|
+
# don't need these checks in test folders
|
|
81
|
+
Metrics/ModuleLength:
|
|
82
|
+
Exclude:
|
|
83
|
+
- "spec/**/*"
|
|
84
|
+
- "test/**/*"
|
|
85
|
+
Metrics/BlockLength:
|
|
86
|
+
Exclude:
|
|
87
|
+
- "spec/**/*"
|
|
88
|
+
- "test/**/*"
|
|
89
|
+
- "*.gemspec" # definitely not in the gemspec
|
|
90
|
+
Metrics/MethodLength:
|
|
91
|
+
Max: 20
|
|
92
|
+
Lint/UnreachableCode:
|
|
93
|
+
Description: 'Unreachable code.'
|
|
94
|
+
Enabled: false
|
|
95
|
+
Lint/Void:
|
|
96
|
+
Enabled: false
|
|
97
|
+
Layout/AlignHash:
|
|
98
|
+
EnforcedLastArgumentHashStyle: ignore_implicit
|
|
99
|
+
Metrics/AbcSize:
|
|
100
|
+
Max: 25
|
|
101
|
+
Style/LambdaCall:
|
|
102
|
+
Enabled: false
|
|
103
|
+
Style/Semicolon:
|
|
104
|
+
Enabled: false
|
|
105
|
+
Naming/UncommunicativeMethodParamName:
|
|
106
|
+
Enabled: false
|
|
107
|
+
Style/ClassAndModuleChildren:
|
|
108
|
+
Enabled: false
|
|
109
|
+
Layout/LeadingCommentSpace:
|
|
110
|
+
Exclude:
|
|
111
|
+
- 'test/docs/**/*'
|
|
112
|
+
Layout/AlignHash:
|
|
113
|
+
EnforcedHashRocketStyle: table
|
|
114
|
+
Style/FrozenStringLiteralComment:
|
|
115
|
+
Enabled: false
|
data/.rubocop.yml
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
inherit_from:
|
|
2
|
+
- https://raw.githubusercontent.com/trailblazer/meta/master/rubocop.yml
|
|
3
|
+
|
|
4
|
+
AllCops:
|
|
5
|
+
TargetRubyVersion: 2.1
|
|
6
|
+
Exclude:
|
|
7
|
+
- 'test/hash/bla.rb'
|
|
8
|
+
|
|
9
|
+
Metrics/LineLength:
|
|
10
|
+
Exclude:
|
|
11
|
+
- test/diagram_test.rb
|
|
12
|
+
|
|
13
|
+
Naming/MethodName:
|
|
14
|
+
Enabled: false
|
|
15
|
+
|
|
16
|
+
Style/ClassAndModuleChildren:
|
|
17
|
+
Enabled: false
|
|
18
|
+
|
|
19
|
+
# DISCUSS: user map instead of collect
|
|
20
|
+
Style/CollectionMethods:
|
|
21
|
+
Enabled: false
|
|
22
|
+
|
|
23
|
+
# DISCUSS: Use raise with an explicit exception class and message, rather than just a message
|
|
24
|
+
Style/ImplicitRuntimeError:
|
|
25
|
+
Enabled: false
|
|
26
|
+
|
|
27
|
+
Style/Lambda:
|
|
28
|
+
EnforcedStyle: literal
|
|
29
|
+
|
|
30
|
+
# DISCUSS: Use fail instead of raise to signal exceptions
|
|
31
|
+
Style/SignalException:
|
|
32
|
+
Enabled: false
|
|
33
|
+
|
|
34
|
+
# DISUSS: this could be false because we have if locals blabla
|
|
35
|
+
Bundler/DuplicatedGem:
|
|
36
|
+
Enabled: false
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
source "https://rubygems.org"
|
|
2
|
+
|
|
3
|
+
# Specify your gem's dependencies in trailblazer-developer.gemspec
|
|
4
|
+
gemspec
|
|
5
|
+
|
|
6
|
+
# gem "trailblazer-activity", ">= 0.7.1"
|
|
7
|
+
gem "trailblazer-activity", path: "../trailblazer-activity"
|
|
8
|
+
gem "trailblazer-activity-dsl-linear", path: "../trailblazer-activity-dsl-linear"
|
|
9
|
+
|
|
10
|
+
# gem "json"
|
|
11
|
+
|
|
12
|
+
gem "representable"
|
data/README.md
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Trailblazer::Developer
|
|
2
|
+
|
|
3
|
+
_Developer tools for Trailblazers._
|
|
4
|
+
|
|
5
|
+
## Documentation
|
|
6
|
+
|
|
7
|
+
Find the complete documentation on the project website: [http://trb.to/2.1#developer]
|
|
8
|
+
|
|
9
|
+
## Summary
|
|
10
|
+
|
|
11
|
+
The `developer` gem provides the following neat tools.
|
|
12
|
+
|
|
13
|
+
* Quick rendering of activities, including their taskWraps.
|
|
14
|
+
* `wtf?` mode™: Run a broken activity and trace where an exception happened.
|
|
15
|
+
* Connect to the visual TRB-editor: load, store, organize and render your app's activities.
|
|
16
|
+
* Generate {Intermediate} data structures from TRB-editor.js files.
|
|
17
|
+
* Debugging mode: run and debug workflows in the TRB-editor.
|
data/Rakefile
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
require "bundler/gem_tasks"
|
|
2
|
+
require "rake/testtask"
|
|
3
|
+
require "rubocop/rake_task"
|
|
4
|
+
|
|
5
|
+
Rake::TestTask.new(:test) do |t|
|
|
6
|
+
t.libs << "test"
|
|
7
|
+
t.libs << "lib"
|
|
8
|
+
t.test_files = FileList["test/**/*_test.rb"]
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
RuboCop::RakeTask.new(:rubocop)
|
|
12
|
+
|
|
13
|
+
desc "Running Tests"
|
|
14
|
+
task default: %i[test rubocop]
|
data/bin/console
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
require "bundler/setup"
|
|
4
|
+
require "trailblazer/developer"
|
|
5
|
+
|
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
|
8
|
+
|
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
|
10
|
+
# require "pry"
|
|
11
|
+
# Pry.start
|
|
12
|
+
|
|
13
|
+
require "irb"
|
|
14
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
require "trailblazer/developer/version"
|
|
2
|
+
|
|
3
|
+
module Trailblazer
|
|
4
|
+
module Developer
|
|
5
|
+
# Your code goes here...
|
|
6
|
+
end
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
require "trailblazer/developer/generate"
|
|
10
|
+
require "trailblazer/developer/render/circuit"
|
|
11
|
+
|
|
12
|
+
# require "trailblazer/developer/client"
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
module Trailblazer
|
|
2
|
+
module Developer
|
|
3
|
+
# Transforms an {Activity::Graph} into an abstract data structure that represents the graph via a
|
|
4
|
+
# well-defined API. The goal is to decouple graph internals from the presentation layer.
|
|
5
|
+
# The {Model} is usually passed into Renderer and Layouter, to render the bpmn:Diagram XML or JSON.
|
|
6
|
+
#
|
|
7
|
+
# It returns {Model} with {Task}s and {Flow}s.
|
|
8
|
+
module Activity
|
|
9
|
+
module Graph
|
|
10
|
+
class << self
|
|
11
|
+
Model = Struct.new(:id, :start_events, :end_events, :task, :sequence_flow)
|
|
12
|
+
Task = Struct.new(:id, :name, :options, :incoming, :outgoing)
|
|
13
|
+
# DISCUSS: direction ATM is the "condition" for the BPMN rendering.
|
|
14
|
+
Flow = Struct.new(:id, :sourceRef, :targetRef, :direction)
|
|
15
|
+
|
|
16
|
+
# @param Graph an object implementing the Activity::Graph interface
|
|
17
|
+
# @return Model Generic representation of the graph, ready for rendering.
|
|
18
|
+
def self.to_model(graph, id: "some-process") # rubocop:disable Metrics/AbcSize
|
|
19
|
+
start_events = graph.find_all("Start.default") # FIXME. this is a static assumption.
|
|
20
|
+
end_events = graph.find_all { |node| graph.successors(node).size.zero? }
|
|
21
|
+
tasks = graph.find_all { |_node| true }
|
|
22
|
+
tasks -= start_events
|
|
23
|
+
tasks -= end_events
|
|
24
|
+
|
|
25
|
+
# transform nodes into BPMN elements.
|
|
26
|
+
start_events = start_events.collect do |evt|
|
|
27
|
+
Task.new(evt[:id], evt[:id], evt, Incomings(graph, evt), Outgoings(graph, evt))
|
|
28
|
+
end
|
|
29
|
+
end_events = end_events.collect do |evt|
|
|
30
|
+
Task.new(evt[:id], evt[:id], evt, Incomings(graph, evt), Outgoings(graph, evt))
|
|
31
|
+
end
|
|
32
|
+
tasks = tasks.collect { |evt| Task.new(evt[:id], evt[:id], evt, Incomings(graph, evt), Outgoings(graph, evt)) }
|
|
33
|
+
edges = (start_events + end_events + tasks).collect { |task| [task.incoming, task.outgoing] }.flatten(2).uniq
|
|
34
|
+
|
|
35
|
+
Model.new(id, start_events, end_events, tasks, edges)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
private
|
|
39
|
+
|
|
40
|
+
def Outgoings(graph, source)
|
|
41
|
+
graph.successors(source).collect { |target, edge| Flow.new(edge[:id], source[:id], target[:id], edge[:_wrapped]) }
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def Incomings(graph, target)
|
|
45
|
+
graph.predecessors(target).collect { |source, edge| Flow.new(edge[:id], source[:id], target[:id], edge[:_wrapped]) }
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
require "faraday"
|
|
2
|
+
|
|
3
|
+
module Trailblazer::Developer
|
|
4
|
+
module Client
|
|
5
|
+
def self.push(operation:, name:)
|
|
6
|
+
xml = Trailblazer::Diagram::BPMN.to_xml(operation["__activity__"], operation["__sequence__"].map(&:id))
|
|
7
|
+
token = "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJub25lIn0.eyJpZCI6MywidXNlcm5hbWUiOiJhcG90b25pY2siLCJlbWFpbCI6Im5pY2tAdHJhaWxibGF6ZXIudG8ifQ." # rubocop:disable Metrics/LineLength
|
|
8
|
+
conn = Faraday.new(url: "https://api.trb.to")
|
|
9
|
+
response = conn.post do |req|
|
|
10
|
+
req.url "/dev/v1/import"
|
|
11
|
+
req.headers["Content-Type"] = "application/json"
|
|
12
|
+
req.headers["Authorization"] = token
|
|
13
|
+
require "base64"
|
|
14
|
+
|
|
15
|
+
req.body = %({ "name": "#{name}", "xml":"#{Base64.strict_encode64(xml)}" })
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
puts response.status.inspect
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
require "representable/hash"
|
|
2
|
+
|
|
3
|
+
module Trailblazer
|
|
4
|
+
module Developer
|
|
5
|
+
# Computes an {Intermediate} data structure from a TRB-editor.js file.
|
|
6
|
+
module Generate
|
|
7
|
+
module_function
|
|
8
|
+
|
|
9
|
+
Element = Struct.new(:id, :type, :linksTo, :data, :label)
|
|
10
|
+
Arrow = Struct.new(:target, :label)
|
|
11
|
+
|
|
12
|
+
module Representer
|
|
13
|
+
class Activity < Representable::Decorator
|
|
14
|
+
include Representable::Hash
|
|
15
|
+
|
|
16
|
+
collection :elements, class: Element do
|
|
17
|
+
property :id
|
|
18
|
+
property :type
|
|
19
|
+
collection :linksTo, class: Arrow, default: [] do
|
|
20
|
+
property :target
|
|
21
|
+
property :label
|
|
22
|
+
end
|
|
23
|
+
property :data, default: {}
|
|
24
|
+
property :label
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def call(hash)
|
|
30
|
+
elements = Representer::Activity.new(OpenStruct.new).from_hash(hash).elements
|
|
31
|
+
|
|
32
|
+
start_events = elements.find_all { |el| el.type == "Event" }
|
|
33
|
+
end_events = elements.find_all { |el| el.type == "EndEventTerminate" }# DISCUSS: TERMINATE?
|
|
34
|
+
|
|
35
|
+
inter = Activity::Schema::Intermediate
|
|
36
|
+
|
|
37
|
+
wiring = elements.collect { |el| [inter.TaskRef(el.id, el.data), el.linksTo.collect { |arrow| inter.Out(semantic_for(arrow.to_h), arrow.target) } ] }
|
|
38
|
+
wiring = Hash[wiring]
|
|
39
|
+
|
|
40
|
+
# end events need this stupid special handling
|
|
41
|
+
wiring = wiring.merge(Hash[
|
|
42
|
+
end_events.collect do |_end|
|
|
43
|
+
ref, outputs = wiring.find { |ref, _| ref.id == _end.id }
|
|
44
|
+
|
|
45
|
+
[ref, [inter.Out(semantic_for(_end.to_h), nil)]]
|
|
46
|
+
end
|
|
47
|
+
])
|
|
48
|
+
# pp wiring
|
|
49
|
+
|
|
50
|
+
inter.new(wiring, end_events.collect(&:id), start_events.collect(&:id))
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# private
|
|
54
|
+
|
|
55
|
+
# We currently use the {:label} field of an arrow to encode an output semantic.
|
|
56
|
+
# The {:symbol_style} part will be filtered out as semantic. Defaults to {:success}.
|
|
57
|
+
def semantic_for(label:nil, **)
|
|
58
|
+
return :success unless label
|
|
59
|
+
|
|
60
|
+
m = label.match(/:(\w+)/)
|
|
61
|
+
return m[1].to_sym
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
# [Inter::Out(:success, nil)]
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
module Trailblazer
|
|
2
|
+
module Developer
|
|
3
|
+
module Render
|
|
4
|
+
module Circuit
|
|
5
|
+
module_function
|
|
6
|
+
|
|
7
|
+
# Render an {Activity}'s circuit as a simple hash.
|
|
8
|
+
def call(activity, **options)
|
|
9
|
+
graph = Activity::Introspect::Graph(activity)
|
|
10
|
+
|
|
11
|
+
circuit_hash(graph, **options)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def circuit_hash(graph, **options)
|
|
15
|
+
content = graph.collect do |node|
|
|
16
|
+
conns = node.outgoings.collect do |outgoing|
|
|
17
|
+
" {#{outgoing.output.signal}} => #{inspect_with_matcher(outgoing.task, **options)}"
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
[ inspect_with_matcher(node.task, **options), conns.join("\n") ]
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
content = content.join("\n")
|
|
24
|
+
|
|
25
|
+
return "\n#{content}".gsub(/0x\w+/, "0x")#.gsub(/0.\d+/, "0.")
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# If Ruby had pattern matching, this function wasn't necessary.
|
|
29
|
+
def inspect_with_matcher(task, inspect_task: method(:inspect_task), inspect_end: method(:inspect_end))
|
|
30
|
+
return inspect_task.(task) unless task.kind_of?(Trailblazer::Activity::End)
|
|
31
|
+
inspect_end.(task)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def inspect_task(task)
|
|
35
|
+
task.inspect
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def inspect_end(task)
|
|
39
|
+
class_name = strip(task.class)
|
|
40
|
+
options = task.to_h
|
|
41
|
+
|
|
42
|
+
"#<#{class_name}/#{options[:semantic].inspect}>"
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def strip(string)
|
|
46
|
+
string.to_s.sub("Trailblazer::Activity::", "")
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
module Trailblazer::Developer
|
|
2
|
+
module_function
|
|
3
|
+
|
|
4
|
+
def wtf(activity, args)
|
|
5
|
+
Wtf.invoke(activity, args)
|
|
6
|
+
end
|
|
7
|
+
alias_method :wtf?, :wtf
|
|
8
|
+
|
|
9
|
+
module Wtf
|
|
10
|
+
module_function
|
|
11
|
+
|
|
12
|
+
# Run {activity} with tracing enabled and inject a mutable {Stack} instance.
|
|
13
|
+
# This allows to display the trace even when an exception happened
|
|
14
|
+
def invoke(activity, (ctx, flow_options))
|
|
15
|
+
flow_options ||= {} # Ruby sucks.
|
|
16
|
+
|
|
17
|
+
# this instance gets mutated with every step. unfortunately, there is
|
|
18
|
+
# no other way in Ruby to keep the trace even when an exception was thrown.
|
|
19
|
+
stack = Trailblazer::Activity::Trace::Stack.new
|
|
20
|
+
|
|
21
|
+
begin
|
|
22
|
+
returned_stack, _ = Trailblazer::Activity::Trace.invoke( activity,
|
|
23
|
+
[
|
|
24
|
+
ctx,
|
|
25
|
+
flow_options.merge(stack: stack)
|
|
26
|
+
]
|
|
27
|
+
)
|
|
28
|
+
rescue
|
|
29
|
+
|
|
30
|
+
# DISCUSS: we shouldn't use internal knowledge of the Stack/Level API here.
|
|
31
|
+
closest = stack.to_a
|
|
32
|
+
while closest.is_a?(Trailblazer::Activity::Trace::Level) && closest = closest.last do # FIXME: deep-dive via Stack API.
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# pp closest.task # this was the last executed task
|
|
36
|
+
|
|
37
|
+
handle(stack, $!, closest.task, activity, [ctx, flow_options])
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def exception_renderer(stack:, level:, input:, name:, closest_task:)
|
|
42
|
+
return [ level, %{#{fmt(fmt(name, :red), :bold)}} ] if input.task == closest_task
|
|
43
|
+
[ level, %{#{name}} ]
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# TODO: make this injectable
|
|
47
|
+
def handle(stack, exception, closest_task, activity, *args)
|
|
48
|
+
puts "[Trailblazer] Exception tracing"
|
|
49
|
+
puts "#{fmt(exception.inspect, :bold)}"
|
|
50
|
+
puts " #{exception.backtrace[0]}"
|
|
51
|
+
puts " #{exception.backtrace[1]}"
|
|
52
|
+
puts
|
|
53
|
+
puts Trailblazer::Activity::Trace::Present.(stack, closest_task: closest_task, renderer: method(:exception_renderer))
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def fmt(line, style)
|
|
59
|
+
String.send(style, line)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# Stolen from https://stackoverflow.com/questions/1489183/colorized-ruby-output
|
|
63
|
+
#
|
|
64
|
+
# TODO: this is just prototyping
|
|
65
|
+
module String
|
|
66
|
+
module_function
|
|
67
|
+
def black(str); "\e[30m#{str}\e[0m" end
|
|
68
|
+
def red(str); "\e[31m#{str}\e[0m" end
|
|
69
|
+
def green(str); "\e[32m#{str}\e[0m" end
|
|
70
|
+
def brown(str); "\e[33m#{str}\e[0m" end
|
|
71
|
+
def blue(str); "\e[34m#{str}\e[0m" end
|
|
72
|
+
def magenta(str); "\e[35m#{str}\e[0m" end
|
|
73
|
+
def cyan(str); "\e[36m#{str}\e[0m" end
|
|
74
|
+
def gray(str); "\e[37m#{str}\e[0m" end
|
|
75
|
+
|
|
76
|
+
def bg_black(str); "\e[40m#{str}\e[0m" end
|
|
77
|
+
def bg_red(str); "\e[41m#{str}\e[0m" end
|
|
78
|
+
def bg_green(str); "\e[42m#{str}\e[0m" end
|
|
79
|
+
def bg_brown(str); "\e[43m#{str}\e[0m" end
|
|
80
|
+
def bg_blue(str); "\e[44m#{str}\e[0m" end
|
|
81
|
+
def bg_magenta(str); "\e[45m#{str}\e[0m" end
|
|
82
|
+
def bg_cyan(str); "\e[46m#{str}\e[0m" end
|
|
83
|
+
def bg_gray(str); "\e[47m#{str}\e[0m" end
|
|
84
|
+
|
|
85
|
+
def bold(str); "\e[1m#{str}\e[22m" end
|
|
86
|
+
def italic(str); "\e[3m#{str}\e[23m" end
|
|
87
|
+
def underline(str); "\e[4m#{str}\e[24m" end
|
|
88
|
+
def blink(str); "\e[5m#{str}\e[25m" end
|
|
89
|
+
def reverse_color(str); "\e[7m#{str}\e[27m" end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
require "representable"
|
|
2
|
+
require "representable/xml"
|
|
3
|
+
|
|
4
|
+
require "trailblazer/developer/activity"
|
|
5
|
+
|
|
6
|
+
module Trailblazer
|
|
7
|
+
module Diagram
|
|
8
|
+
module BPMN # rubocop:disable Metrics/ModuleLength
|
|
9
|
+
Plane = Struct.new(:element, :shapes, :edges)
|
|
10
|
+
Shape = Struct.new(:id, :element, :bounds)
|
|
11
|
+
Edge = Struct.new(:id, :element, :waypoints)
|
|
12
|
+
Bounds = Struct.new(:x, :y, :width, :height)
|
|
13
|
+
Waypoint = Struct.new(:x, :y)
|
|
14
|
+
|
|
15
|
+
require "tsort"
|
|
16
|
+
# Helps sorting the tasks in a process "topologically", which is basically what the
|
|
17
|
+
# Sequence does for us, but this works for any kind of process.
|
|
18
|
+
# DISCUSS: should we work on the Model or Graph interface?
|
|
19
|
+
def self.topological_sort(model)
|
|
20
|
+
edges = {}
|
|
21
|
+
model.end_events.each { |task| edges[task.id] = {} }
|
|
22
|
+
model.sequence_flow.each do |edge|
|
|
23
|
+
edges[edge.sourceRef] ||= []
|
|
24
|
+
edges[edge.sourceRef] << edge.targetRef
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# g = {1=>[2, 3], 2=>[4], 3=>[2, 4], 4=>[]}
|
|
28
|
+
each_node = ->(&b) { edges.each_key(&b) }
|
|
29
|
+
each_child = ->(n, &b) { edges[n].each(&b) }
|
|
30
|
+
TSort.tsort(each_node, each_child).reverse #=> [4, 2, 3, 1]
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# FIXME: this should be called "linear layouter or something"
|
|
34
|
+
# Render an `Activity`'s circuit to a BPMN 2.0 XML `<process>` structure.
|
|
35
|
+
# @param activity Activity
|
|
36
|
+
# @param linear_task_ids [String] A list of task IDs that should be layouted sequentially in the provided order.
|
|
37
|
+
def self.to_xml(activity, linear_task_ids = nil) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
|
38
|
+
model = Trailblazer::Developer::Activity::Graph.to_model(activity.graph)
|
|
39
|
+
|
|
40
|
+
linear_task_ids ||= topological_sort(model)
|
|
41
|
+
|
|
42
|
+
# this layouter doesn't want End events in the linear part, we arrange them manually.
|
|
43
|
+
linear_task_ids -= model.end_events.map(&:id)
|
|
44
|
+
linear_task_ids -= model.start_events.map(&:id)
|
|
45
|
+
linear_tasks = linear_task_ids.collect do |id|
|
|
46
|
+
model.task.find { |task| task.id == id } || raise("task #{id} is not in model!")
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
start_x = 200
|
|
50
|
+
y_right = 200
|
|
51
|
+
y_left = 300
|
|
52
|
+
|
|
53
|
+
event_width = 54
|
|
54
|
+
|
|
55
|
+
shape_width = 81
|
|
56
|
+
shape_height = 54
|
|
57
|
+
shape_to_shape = 45
|
|
58
|
+
|
|
59
|
+
current = start_x
|
|
60
|
+
shapes = []
|
|
61
|
+
|
|
62
|
+
# add start.
|
|
63
|
+
shapes << Shape.new(
|
|
64
|
+
"Shape_#{model.start_events[0][:id]}",
|
|
65
|
+
model.start_events[0][:id],
|
|
66
|
+
Bounds.new(current, y_right, event_width, event_width)
|
|
67
|
+
)
|
|
68
|
+
current += event_width + shape_to_shape
|
|
69
|
+
|
|
70
|
+
# add tasks.
|
|
71
|
+
linear_tasks.each do |task|
|
|
72
|
+
is_right = %i[pass step].include?(task.options[:created_by])
|
|
73
|
+
|
|
74
|
+
shapes << Shape.new(
|
|
75
|
+
"Shape_#{task[:id]}",
|
|
76
|
+
task[:id],
|
|
77
|
+
Bounds.new(current, is_right ? y_right : y_left, shape_width, shape_height)
|
|
78
|
+
)
|
|
79
|
+
current += shape_width + shape_to_shape
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# add ends.
|
|
83
|
+
horizontal_end_offset = 90
|
|
84
|
+
|
|
85
|
+
defaults = {
|
|
86
|
+
"End.success" => {y: y_right},
|
|
87
|
+
"End.failure" => {y: y_left},
|
|
88
|
+
"End.pass_fast" => {y: y_right - 90},
|
|
89
|
+
"End.fail_fast" => {y: y_left + 90}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
success_end_events = []
|
|
93
|
+
failure_end_events = [] # rubocop:disable Lint/UselessAssignment
|
|
94
|
+
|
|
95
|
+
model.end_events.each do |evt|
|
|
96
|
+
id = evt[:id]
|
|
97
|
+
y = defaults[id] ? defaults[id][:y] : success_end_events.last + horizontal_end_offset
|
|
98
|
+
|
|
99
|
+
success_end_events << y
|
|
100
|
+
|
|
101
|
+
shapes << Shape.new("Shape_#{id}", id, Bounds.new(current, y, event_width, event_width))
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
edges = []
|
|
105
|
+
model.sequence_flow.each do |flow|
|
|
106
|
+
source = shapes.find { |shape| shape.id == "Shape_#{flow.sourceRef}" }.bounds
|
|
107
|
+
target = shapes.find { |shape| shape.id == "Shape_#{flow.targetRef}" }.bounds
|
|
108
|
+
|
|
109
|
+
edges << Edge.new("SequenceFlow_#{flow[:id]}", flow[:id], Path(source, target, target.x != current))
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
diagram = Struct.new(:plane).new(Plane.new(model.id, shapes, edges))
|
|
113
|
+
|
|
114
|
+
# render XML.
|
|
115
|
+
Representer::Definitions.new(Definitions.new(model, diagram)).to_xml
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def self.Path(source, target, do_straight_line) # rubocop:disable Metrics/AbcSize
|
|
119
|
+
if source.y == target.y # --->
|
|
120
|
+
[Waypoint.new(*fromRight(source)), Waypoint.new(*toLeft(target))]
|
|
121
|
+
elsif do_straight_line
|
|
122
|
+
[Waypoint.new(*fromBottom(source)), Waypoint.new(*toLeft(target))]
|
|
123
|
+
elsif target.y > source.y # target below source.
|
|
124
|
+
[
|
|
125
|
+
l = Waypoint.new(*fromBottom(source)),
|
|
126
|
+
r = Waypoint.new(l.x, target.y + target.height / 2),
|
|
127
|
+
Waypoint.new(target.x, r.y)
|
|
128
|
+
]
|
|
129
|
+
else # target above source.
|
|
130
|
+
[l = Waypoint.new(*fromTop(source)), r = Waypoint.new(l.x, target.y + target.height / 2), Waypoint.new(target.x, r.y)]
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def self.fromRight(left)
|
|
135
|
+
[left.x + left.width, left.y + left.height / 2]
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def self.toLeft(bounds)
|
|
139
|
+
[bounds.x, bounds.y + bounds.height / 2]
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def self.fromBottom(bounds)
|
|
143
|
+
[bounds.x + bounds.width / 2, bounds.y + bounds.height]
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def self.fromTop(bounds)
|
|
147
|
+
[bounds.x + bounds.width / 2, bounds.y]
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
Definitions = Struct.new(:process, :diagram)
|
|
151
|
+
|
|
152
|
+
# Representers for BPMN XML.
|
|
153
|
+
module Representer
|
|
154
|
+
class Task < Representable::Decorator
|
|
155
|
+
include Representable::XML
|
|
156
|
+
include Representable::XML::Namespace
|
|
157
|
+
namespace "http://www.omg.org/spec/BPMN/20100524/MODEL"
|
|
158
|
+
|
|
159
|
+
self.representation_wrap = :task # overridden via :as.
|
|
160
|
+
|
|
161
|
+
property :id, attribute: true
|
|
162
|
+
property :name, attribute: true
|
|
163
|
+
|
|
164
|
+
collection :outgoing, exec_context: :decorator
|
|
165
|
+
collection :incoming, exec_context: :decorator
|
|
166
|
+
|
|
167
|
+
def outgoing
|
|
168
|
+
represented.outgoing.collect { |edge| edge[:id] }
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
def incoming
|
|
172
|
+
represented.incoming.collect { |edge| edge[:id] }
|
|
173
|
+
end
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
class SequenceFlow < Representable::Decorator
|
|
177
|
+
include Representable::XML
|
|
178
|
+
include Representable::XML::Namespace
|
|
179
|
+
self.representation_wrap = :sequenceFlow
|
|
180
|
+
namespace "http://www.omg.org/spec/BPMN/20100524/MODEL"
|
|
181
|
+
|
|
182
|
+
property :id, attribute: true
|
|
183
|
+
property :sourceRef, attribute: true, exec_context: :decorator
|
|
184
|
+
property :targetRef, attribute: true, exec_context: :decorator
|
|
185
|
+
property :direction, as: :conditionExpression
|
|
186
|
+
|
|
187
|
+
def sourceRef
|
|
188
|
+
represented.sourceRef
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
def targetRef
|
|
192
|
+
represented.targetRef
|
|
193
|
+
end
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
class Process < Representable::Decorator
|
|
197
|
+
include Representable::XML
|
|
198
|
+
include Representable::XML::Namespace
|
|
199
|
+
self.representation_wrap = :process
|
|
200
|
+
|
|
201
|
+
namespace "http://www.omg.org/spec/BPMN/20100524/MODEL"
|
|
202
|
+
|
|
203
|
+
property :id, attribute: true
|
|
204
|
+
|
|
205
|
+
collection :start_events, as: :startEvent, decorator: Task
|
|
206
|
+
collection :end_events, as: :endEvent, decorator: Task
|
|
207
|
+
collection :task, decorator: Task
|
|
208
|
+
collection :sequence_flow, decorator: SequenceFlow, as: :sequenceFlow
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
module Diagram
|
|
212
|
+
class Bounds < Representable::Decorator
|
|
213
|
+
include Representable::XML
|
|
214
|
+
include Representable::XML::Namespace
|
|
215
|
+
self.representation_wrap = :Bounds
|
|
216
|
+
|
|
217
|
+
namespace "http://www.omg.org/spec/DD/20100524/DC"
|
|
218
|
+
|
|
219
|
+
property :x, attribute: true
|
|
220
|
+
property :y, attribute: true
|
|
221
|
+
property :width, attribute: true
|
|
222
|
+
property :height, attribute: true
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
class Diagram < Representable::Decorator
|
|
226
|
+
feature Representable::XML
|
|
227
|
+
feature Representable::XML::Namespace
|
|
228
|
+
self.representation_wrap = :BPMNDiagram
|
|
229
|
+
|
|
230
|
+
namespace "http://www.omg.org/spec/BPMN/20100524/DI"
|
|
231
|
+
|
|
232
|
+
property :plane, as: "BPMNPlane" do
|
|
233
|
+
self.representation_wrap = :plane
|
|
234
|
+
|
|
235
|
+
property :element, as: :bpmnElement, attribute: true
|
|
236
|
+
|
|
237
|
+
namespace "http://www.omg.org/spec/BPMN/20100524/DI"
|
|
238
|
+
|
|
239
|
+
collection :shapes, as: "BPMNShape" do
|
|
240
|
+
self.representation_wrap = :BPMNShape
|
|
241
|
+
namespace "http://www.omg.org/spec/BPMN/20100524/DI"
|
|
242
|
+
|
|
243
|
+
property :id, attribute: true
|
|
244
|
+
property :element, as: :bpmnElement, attribute: true
|
|
245
|
+
|
|
246
|
+
property :bounds, as: "Bounds", decorator: Bounds
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
collection :edges, as: "BPMNEdge" do
|
|
250
|
+
self.representation_wrap = :BPMNEdge
|
|
251
|
+
namespace "http://www.omg.org/spec/BPMN/20100524/DI"
|
|
252
|
+
|
|
253
|
+
property :id, attribute: true
|
|
254
|
+
property :element, as: :bpmnElement, attribute: true
|
|
255
|
+
|
|
256
|
+
# <di:waypoint xsi:type="dc:Point" x="136" y="118" />
|
|
257
|
+
collection :waypoints, as: :waypoint do
|
|
258
|
+
namespace "http://www.omg.org/spec/DD/20100524/DI"
|
|
259
|
+
|
|
260
|
+
property :type, as: "xsi:type", exec_context: :decorator, attribute: true
|
|
261
|
+
property :x, attribute: true
|
|
262
|
+
property :y, attribute: true
|
|
263
|
+
|
|
264
|
+
def type
|
|
265
|
+
"dc:Point"
|
|
266
|
+
end
|
|
267
|
+
end
|
|
268
|
+
end
|
|
269
|
+
end
|
|
270
|
+
|
|
271
|
+
# namespace "http://www.w3.org/2001/XMLSchema-instance" # xsi
|
|
272
|
+
end
|
|
273
|
+
end
|
|
274
|
+
|
|
275
|
+
class Definitions < Representable::Decorator
|
|
276
|
+
include Representable::XML
|
|
277
|
+
include Representable::XML::Namespace
|
|
278
|
+
self.representation_wrap = :definitions
|
|
279
|
+
|
|
280
|
+
namespace "http://www.omg.org/spec/BPMN/20100524/MODEL"
|
|
281
|
+
namespace_def bpmn: "http://www.omg.org/spec/BPMN/20100524/MODEL"
|
|
282
|
+
namespace_def bpmndi: "http://www.omg.org/spec/BPMN/20100524/DI"
|
|
283
|
+
namespace_def di: "http://www.omg.org/spec/DD/20100524/DI"
|
|
284
|
+
|
|
285
|
+
namespace_def dc: "http://www.omg.org/spec/DD/20100524/DC" # <cd:Bounds>
|
|
286
|
+
namespace_def xsi: "http://www.w3.org/2001/XMLSchema-instance" # used in waypoint.
|
|
287
|
+
|
|
288
|
+
property :process, decorator: Process
|
|
289
|
+
property :diagram, decorator: Diagram::Diagram, as: :BPMNDiagram
|
|
290
|
+
end
|
|
291
|
+
end
|
|
292
|
+
end
|
|
293
|
+
end
|
|
294
|
+
end
|
|
295
|
+
|
|
296
|
+
# <bpmndi:BPMNDiagram id="BPMNDiagram_1">
|
|
297
|
+
# <bpmndi:BPMNPlane id="BPMNPlane_1">
|
|
298
|
+
# <bpmndi:BPMNShape id="_BPMNShape_Task_2" bpmnElement="Task_2">
|
|
299
|
+
# <dc:Bounds x="100" y="100" width="36" height="36" />
|
|
300
|
+
# </bpmndi:BPMNShape>
|
|
301
|
+
# <bpmndi:BPMNShape id="_BPMNShape_Task_3" bpmnElement="Task_3">
|
|
302
|
+
# <dc:Bounds x="236" y="78" width="100" height="80" />
|
|
303
|
+
# </bpmndi:BPMNShape>
|
|
304
|
+
# <bpmndi:BPMNEdge id="_BPMNConnection_Flow_4" bpmnElement="Flow_4">
|
|
305
|
+
# <di:waypoint xsi:type="dc:Point" x="136" y="118" />
|
|
306
|
+
# <di:waypoint xsi:type="dc:Point" x="236" y="118" />
|
|
307
|
+
# </bpmndi:BPMNEdge>
|
|
308
|
+
# <bpmndi:BPMNShape id="_BPMNShape_Task_5" bpmnElement="Task_5">
|
|
309
|
+
# <dc:Bounds x="436" y="78" width="100" height="80" />
|
|
310
|
+
# </bpmndi:BPMNShape>
|
|
311
|
+
# <bpmndi:BPMNEdge id="_BPMNConnection_Flow_6" bpmnElement="Flow_6">
|
|
312
|
+
# <di:waypoint xsi:type="dc:Point" x="336" y="118" />
|
|
313
|
+
# <di:waypoint xsi:type="dc:Point" x="436" y="118" />
|
|
314
|
+
# </bpmndi:BPMNEdge>
|
|
315
|
+
# <bpmndi:BPMNShape id="_BPMNShape_Task_1" bpmnElement="Task_1">
|
|
316
|
+
# <dc:Bounds x="636" y="100" width="36" height="36" />
|
|
317
|
+
# </bpmndi:BPMNShape>
|
|
318
|
+
# <bpmndi:BPMNShape id="_BPMNShape_Task_8" bpmnElement="Task_8">
|
|
319
|
+
# <dc:Bounds x="636" y="266" width="100" height="80" />
|
|
320
|
+
# </bpmndi:BPMNShape>
|
|
321
|
+
# <bpmndi:BPMNEdge id="_BPMNConnection_Flow_7" bpmnElement="Flow_7">
|
|
322
|
+
# <di:waypoint xsi:type="dc:Point" x="536" y="118" />
|
|
323
|
+
# <di:waypoint xsi:type="dc:Point" x="636" y="118" />
|
|
324
|
+
# </bpmndi:BPMNEdge>
|
|
325
|
+
# <bpmndi:BPMNEdge id="_BPMNConnection_Flow_9" bpmnElement="Flow_9">
|
|
326
|
+
# <di:waypoint xsi:type="dc:Point" x="536" y="118" />
|
|
327
|
+
# <di:waypoint xsi:type="dc:Point" x="586" y="118" />
|
|
328
|
+
# <di:waypoint xsi:type="dc:Point" x="586" y="306" />
|
|
329
|
+
# <di:waypoint xsi:type="dc:Point" x="636" y="306" />
|
|
330
|
+
# </bpmndi:BPMNEdge>
|
|
331
|
+
# <bpmndi:BPMNEdge id="_BPMNConnection_Flow_10" bpmnElement="Flow_10">
|
|
332
|
+
# <di:waypoint xsi:type="dc:Point" x="686" y="266" />
|
|
333
|
+
# <di:waypoint xsi:type="dc:Point" x="686" y="201" />
|
|
334
|
+
# <di:waypoint xsi:type="dc:Point" x="654" y="201" />
|
|
335
|
+
# <di:waypoint xsi:type="dc:Point" x="654" y="136" />
|
|
336
|
+
# </bpmndi:BPMNEdge>
|
|
337
|
+
# </bpmndi:BPMNPlane>
|
|
338
|
+
# </bpmndi:BPMNDiagram>
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
lib = File.expand_path("lib", __dir__)
|
|
2
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
3
|
+
require "trailblazer/developer/version"
|
|
4
|
+
|
|
5
|
+
Gem::Specification.new do |spec|
|
|
6
|
+
spec.name = "trailblazer-developer"
|
|
7
|
+
spec.version = Trailblazer::Developer::VERSION
|
|
8
|
+
spec.authors = ["Nick Sutterer"]
|
|
9
|
+
spec.email = ["apotonick@gmail.com"]
|
|
10
|
+
|
|
11
|
+
spec.summary = "Developer tools for Trailblazer."
|
|
12
|
+
spec.description = "Developer tools for Trailblazer: debugger, tracing, visual editor integration."
|
|
13
|
+
spec.homepage = "http://trailblazer.to/gems/trailblazer/developer.html"
|
|
14
|
+
|
|
15
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
|
16
|
+
f.match(%r{^(test)/})
|
|
17
|
+
end
|
|
18
|
+
spec.require_paths = ["lib"]
|
|
19
|
+
|
|
20
|
+
spec.add_development_dependency "bundler"
|
|
21
|
+
spec.add_development_dependency "minitest", "~> 5.0"
|
|
22
|
+
spec.add_development_dependency "rake"
|
|
23
|
+
spec.add_development_dependency "rubocop"
|
|
24
|
+
|
|
25
|
+
spec.add_dependency "trailblazer-activity", "~> 0.8"
|
|
26
|
+
spec.add_dependency "representable"
|
|
27
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: trailblazer-developer
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.0.1
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Nick Sutterer
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2019-03-28 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: bundler
|
|
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'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: minitest
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - "~>"
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '5.0'
|
|
34
|
+
type: :development
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - "~>"
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '5.0'
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: rake
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - ">="
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: '0'
|
|
48
|
+
type: :development
|
|
49
|
+
prerelease: false
|
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - ">="
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: '0'
|
|
55
|
+
- !ruby/object:Gem::Dependency
|
|
56
|
+
name: rubocop
|
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
|
58
|
+
requirements:
|
|
59
|
+
- - ">="
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: '0'
|
|
62
|
+
type: :development
|
|
63
|
+
prerelease: false
|
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
65
|
+
requirements:
|
|
66
|
+
- - ">="
|
|
67
|
+
- !ruby/object:Gem::Version
|
|
68
|
+
version: '0'
|
|
69
|
+
- !ruby/object:Gem::Dependency
|
|
70
|
+
name: trailblazer-activity
|
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
|
72
|
+
requirements:
|
|
73
|
+
- - "~>"
|
|
74
|
+
- !ruby/object:Gem::Version
|
|
75
|
+
version: '0.8'
|
|
76
|
+
type: :runtime
|
|
77
|
+
prerelease: false
|
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
79
|
+
requirements:
|
|
80
|
+
- - "~>"
|
|
81
|
+
- !ruby/object:Gem::Version
|
|
82
|
+
version: '0.8'
|
|
83
|
+
- !ruby/object:Gem::Dependency
|
|
84
|
+
name: representable
|
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
|
86
|
+
requirements:
|
|
87
|
+
- - ">="
|
|
88
|
+
- !ruby/object:Gem::Version
|
|
89
|
+
version: '0'
|
|
90
|
+
type: :runtime
|
|
91
|
+
prerelease: false
|
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
93
|
+
requirements:
|
|
94
|
+
- - ">="
|
|
95
|
+
- !ruby/object:Gem::Version
|
|
96
|
+
version: '0'
|
|
97
|
+
description: 'Developer tools for Trailblazer: debugger, tracing, visual editor integration.'
|
|
98
|
+
email:
|
|
99
|
+
- apotonick@gmail.com
|
|
100
|
+
executables: []
|
|
101
|
+
extensions: []
|
|
102
|
+
extra_rdoc_files: []
|
|
103
|
+
files:
|
|
104
|
+
- ".gitignore"
|
|
105
|
+
- ".rubocop-https---raw-githubusercontent-com-trailblazer-meta-master-rubocop-yml"
|
|
106
|
+
- ".rubocop.yml"
|
|
107
|
+
- ".travis.yml"
|
|
108
|
+
- Gemfile
|
|
109
|
+
- README.md
|
|
110
|
+
- Rakefile
|
|
111
|
+
- bin/console
|
|
112
|
+
- bin/setup
|
|
113
|
+
- lib/trailblazer/developer.rb
|
|
114
|
+
- lib/trailblazer/developer/activity.rb
|
|
115
|
+
- lib/trailblazer/developer/client.rb
|
|
116
|
+
- lib/trailblazer/developer/generate.rb
|
|
117
|
+
- lib/trailblazer/developer/render/circuit.rb
|
|
118
|
+
- lib/trailblazer/developer/version.rb
|
|
119
|
+
- lib/trailblazer/developer/wtf.rb
|
|
120
|
+
- lib/trailblazer/diagram/bpmn.rb
|
|
121
|
+
- trailblazer-developer.gemspec
|
|
122
|
+
homepage: http://trailblazer.to/gems/trailblazer/developer.html
|
|
123
|
+
licenses: []
|
|
124
|
+
metadata: {}
|
|
125
|
+
post_install_message:
|
|
126
|
+
rdoc_options: []
|
|
127
|
+
require_paths:
|
|
128
|
+
- lib
|
|
129
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
130
|
+
requirements:
|
|
131
|
+
- - ">="
|
|
132
|
+
- !ruby/object:Gem::Version
|
|
133
|
+
version: '0'
|
|
134
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
135
|
+
requirements:
|
|
136
|
+
- - ">="
|
|
137
|
+
- !ruby/object:Gem::Version
|
|
138
|
+
version: '0'
|
|
139
|
+
requirements: []
|
|
140
|
+
rubyforge_project:
|
|
141
|
+
rubygems_version: 2.7.3
|
|
142
|
+
signing_key:
|
|
143
|
+
specification_version: 4
|
|
144
|
+
summary: Developer tools for Trailblazer.
|
|
145
|
+
test_files: []
|