mxrb 0.1.3 → 0.1.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/bin/mxrb +455 -10
- data/docs/de-DE/README.md +1 -0
- data/docs/de-DE/oql-sql.md +42 -0
- data/docs/de-DE/project-structure.md +201 -2
- data/docs/de-DE/runtime-ruby.md +104 -0
- data/docs/de-DE/runtime-schema-migrations.md +44 -0
- data/docs/de-DE/validation-matrix.md +42 -4
- data/docs/en-US/README.md +1 -0
- data/docs/en-US/oql-sql.md +41 -0
- data/docs/en-US/project-structure.md +192 -2
- data/docs/en-US/runtime-ruby.md +100 -0
- data/docs/en-US/runtime-schema-migrations.md +41 -0
- data/docs/en-US/validation-matrix.md +39 -4
- data/docs/pt-BR/README.md +1 -0
- data/docs/pt-BR/oql-sql.md +41 -0
- data/docs/pt-BR/project-structure.md +197 -2
- data/docs/pt-BR/runtime-ruby.md +108 -0
- data/docs/pt-BR/runtime-schema-migrations.md +40 -0
- data/docs/pt-BR/validation-matrix.md +42 -5
- data/lib/mxrb/cli/help.rb +426 -0
- data/lib/mxrb/cli/release.rb +137 -0
- data/lib/mxrb/compiler/compatibility_analyzer.rb +1 -1
- data/lib/mxrb/compiler/data_grid_bundle_compiler.rb +8 -1
- data/lib/mxrb/compiler/domain_document_compiler.rb +3 -0
- data/lib/mxrb/compiler/gallery_bundle_compiler.rb +11 -1
- data/lib/mxrb/compiler/generic_widget_bundle_compiler.rb +76 -19
- data/lib/mxrb/compiler/legacy_custom_widget_compiler.rb +159 -0
- data/lib/mxrb/compiler/legacy_data_grid_compiler.rb +43 -7
- data/lib/mxrb/compiler/legacy_page_builder.rb +1248 -23
- data/lib/mxrb/compiler/page_bundle_compiler.rb +13 -4
- data/lib/mxrb/compiler/web_bundle_builder.rb +5 -1
- data/lib/mxrb/compiler/web_shell_materializer.rb +42 -2
- data/lib/mxrb/compiler/widget_package_extractor.rb +3 -0
- data/lib/mxrb/domain_diagram/lifecycle.rb +272 -0
- data/lib/mxrb/domain_diagram.rb +409 -0
- data/lib/mxrb/dsl/builder.rb +43 -9
- data/lib/mxrb/environment.rb +226 -0
- data/lib/mxrb/exporter.rb +89 -15
- data/lib/mxrb/http/server.rb +107 -0
- data/lib/mxrb/initializer.rb +80 -9
- data/lib/mxrb/integrity/validator.rb +14 -0
- data/lib/mxrb/io/bson_codec.rb +42 -1
- data/lib/mxrb/io/mpr_file.rb +146 -3
- data/lib/mxrb/model/attribute.rb +3 -0
- data/lib/mxrb/model/entity.rb +28 -2
- data/lib/mxrb/model/microflow.rb +3 -1
- data/lib/mxrb/model/page.rb +126 -15
- data/lib/mxrb/model/project.rb +3 -0
- data/lib/mxrb/modeler/catalog.rb +178 -0
- data/lib/mxrb/oql/reverse_translator.rb +394 -0
- data/lib/mxrb/oql/server.rb +4 -8
- data/lib/mxrb/oql.rb +23 -1
- data/lib/mxrb/project_lifecycle.rb +5 -2
- data/lib/mxrb/ruby_app/exporter.rb +1749 -0
- data/lib/mxrb/ruby_app/preset.rb +506 -0
- data/lib/mxrb/ruby_app/session_manager.rb +122 -0
- data/lib/mxrb/ruby_app.rb +1361 -0
- data/lib/mxrb/runtime/access_control.rb +408 -0
- data/lib/mxrb/runtime/native.rb +1015 -93
- data/lib/mxrb/runtime/scheduler.rb +396 -0
- data/lib/mxrb/runtime/schema_migrator.rb +598 -0
- data/lib/mxrb/runtime/shared_store.rb +335 -0
- data/lib/mxrb/runtime/sqlite_store.rb +729 -0
- data/lib/mxrb/scaffold/generator.rb +11 -3
- data/lib/mxrb/uml/activity_diagram.rb +118 -0
- data/lib/mxrb/uml/class_diagram.rb +118 -0
- data/lib/mxrb/uml/sequence_diagram.rb +112 -0
- data/lib/mxrb/uml/server.rb +146 -0
- data/lib/mxrb/uml/support.rb +35 -0
- data/lib/mxrb/version.rb +1 -1
- data/lib/mxrb/web_ui/assets/abnfDiagram-N423BO3Z-C4JD3cEC.js +1 -0
- data/lib/mxrb/web_ui/assets/arc-3Z53kgFp.js +1 -0
- data/lib/mxrb/web_ui/assets/architecture-TIHT7OUA-BStBTLea.js +1 -0
- data/lib/mxrb/web_ui/assets/architectureDiagram-T3A2C74G-DBwqnM4J.js +36 -0
- data/lib/mxrb/web_ui/assets/array-BifhSqXX.js +1 -0
- data/lib/mxrb/web_ui/assets/blockDiagram-VBNYF7ZC-DLtuHt-j.js +132 -0
- data/lib/mxrb/web_ui/assets/c4Diagram-5PPSVZJV-ConSk_pe.js +10 -0
- data/lib/mxrb/web_ui/assets/channel-BhPvD7Dt.js +1 -0
- data/lib/mxrb/web_ui/assets/chunk-2GRJ4B5K-D2HpWsf_.js +1 -0
- data/lib/mxrb/web_ui/assets/chunk-2Q5K7J3B-C1jixKkw.js +1 -0
- data/lib/mxrb/web_ui/assets/chunk-4I5QYGJK-CiIdNwaF.js +1 -0
- data/lib/mxrb/web_ui/assets/chunk-5RXB4S5H-Bu_AaEkE.js +231 -0
- data/lib/mxrb/web_ui/assets/chunk-5VM5RSS4-ZNzvKenW.js +15 -0
- data/lib/mxrb/web_ui/assets/chunk-6Q2QTUOP-wQkNmt_X.js +88 -0
- data/lib/mxrb/web_ui/assets/chunk-7BUUIJ7U-Bb538aSH.js +1 -0
- data/lib/mxrb/web_ui/assets/chunk-GF5L2VYU-G8MmiBzU.js +206 -0
- data/lib/mxrb/web_ui/assets/chunk-I66GZJ75-CulcrLPh.js +127 -0
- data/lib/mxrb/web_ui/assets/chunk-JQJVKLGR-ukjzcdlL.js +156 -0
- data/lib/mxrb/web_ui/assets/chunk-JWPE2WC7-DVXcaiue.js +1 -0
- data/lib/mxrb/web_ui/assets/chunk-KBJHAD2P-Wm35lYov.js +1 -0
- data/lib/mxrb/web_ui/assets/chunk-KEIR6QF5-BICK3FdT.js +161 -0
- data/lib/mxrb/web_ui/assets/chunk-NSK5VX7P-D2nYrCY4.js +2 -0
- data/lib/mxrb/web_ui/assets/chunk-QR6OTTB3-BrdIzg4Q.js +62 -0
- data/lib/mxrb/web_ui/assets/chunk-RYQCIY6F-CCfZMcW6.js +1 -0
- data/lib/mxrb/web_ui/assets/chunk-UBXNYLIW-BPEVYsFK.js +1 -0
- data/lib/mxrb/web_ui/assets/chunk-W5SLKNZC-2E6OPhA4.js +1 -0
- data/lib/mxrb/web_ui/assets/chunk-WRU74C26-CBIvOyWp.js +70 -0
- data/lib/mxrb/web_ui/assets/chunk-XXDRQBXY-pH58XAyl.js +1 -0
- data/lib/mxrb/web_ui/assets/chunk-Y2CYZVJY-DsF7k-Jl.js +1 -0
- data/lib/mxrb/web_ui/assets/classDiagram-JCYQIIEL-xiqo4D89.js +1 -0
- data/lib/mxrb/web_ui/assets/classDiagram-v2-OCEON4UE-xiqo4D89.js +1 -0
- data/lib/mxrb/web_ui/assets/cose-bilkent-JH36ORCC-t_flPpii.js +1 -0
- data/lib/mxrb/web_ui/assets/cynefin-VYW2F7L2-BIqktTEv.js +1 -0
- data/lib/mxrb/web_ui/assets/cynefinDiagram-MW4NZA55-C2d--lut.js +62 -0
- data/lib/mxrb/web_ui/assets/cytoscape.esm-B-NFISlW.js +321 -0
- data/lib/mxrb/web_ui/assets/dagre-Buvkdvvj.js +1 -0
- data/lib/mxrb/web_ui/assets/dagre-VZM6K2ZE-CSz2_tb5.js +4 -0
- data/lib/mxrb/web_ui/assets/defaultLocale-BFoDCU3G.js +1 -0
- data/lib/mxrb/web_ui/assets/diagram-7IWD3JNH-DCt7u7V_.js +30 -0
- data/lib/mxrb/web_ui/assets/diagram-B4RE2ZJO-DqZBqkMu.js +3 -0
- data/lib/mxrb/web_ui/assets/diagram-LBJQPF4R-ClIYbIsI.js +24 -0
- data/lib/mxrb/web_ui/assets/diagram-Q27KOJAE-DFxhvthJ.js +24 -0
- data/lib/mxrb/web_ui/assets/diagram-UB23O5K3-BSUTXptv.js +41 -0
- data/lib/mxrb/web_ui/assets/dist-D2qOEbeJ.js +1 -0
- data/lib/mxrb/web_ui/assets/domain-mGOZ1KCG.css +1 -0
- data/lib/mxrb/web_ui/assets/domain-qsjXhy4v.js +1 -0
- data/lib/mxrb/web_ui/assets/ebnfDiagram-BXEA7PRR-B5reICEi.js +1 -0
- data/lib/mxrb/web_ui/assets/erDiagram-JOGREHBK-Co5Mxn2p.js +85 -0
- data/lib/mxrb/web_ui/assets/eventmodeling-45OFAUF4-C1ylhSks.js +1 -0
- data/lib/mxrb/web_ui/assets/flowDiagram-UKHOOZJN-CHXaJIaS.js +1 -0
- data/lib/mxrb/web_ui/assets/ganttDiagram-PKOTCBZU-DPPPaWaz.js +292 -0
- data/lib/mxrb/web_ui/assets/gitGraph-TEB2WS4Q-qS77ywA9.js +1 -0
- data/lib/mxrb/web_ui/assets/gitGraphDiagram-DS77QQ5N-DpAv6-BT.js +106 -0
- data/lib/mxrb/web_ui/assets/graphlib-DS17s2tU.js +1 -0
- data/lib/mxrb/web_ui/assets/info-DKCQHKI2-C9VD1Y4e.js +1 -0
- data/lib/mxrb/web_ui/assets/infoDiagram-6WML65LV-Bk1kbcCy.js +2 -0
- data/lib/mxrb/web_ui/assets/init-C-OQMol4.js +1 -0
- data/lib/mxrb/web_ui/assets/ishikawaDiagram-WSZJBQD7-0gcISBFR.js +70 -0
- data/lib/mxrb/web_ui/assets/journeyDiagram-NVQOT4AX-Dt0RQnlh.js +139 -0
- data/lib/mxrb/web_ui/assets/jsx-runtime-DV0a5kSb.js +9 -0
- data/lib/mxrb/web_ui/assets/kanban-definition-27J2QSJJ-DIPQM7w9.js +89 -0
- data/lib/mxrb/web_ui/assets/katex-CXMH3UgJ.js +257 -0
- data/lib/mxrb/web_ui/assets/line-C0rYD-tL.js +1 -0
- data/lib/mxrb/web_ui/assets/linear-BPPxWorj.js +1 -0
- data/lib/mxrb/web_ui/assets/map-BaFkSB1l.js +1 -0
- data/lib/mxrb/web_ui/assets/mermaid-parser.core-B_UPzTxa.js +7 -0
- data/lib/mxrb/web_ui/assets/mindmap-definition-FAOFIHXS-CdJRSMuk.js +96 -0
- data/lib/mxrb/web_ui/assets/modeler-BNqHthwk.css +1 -0
- data/lib/mxrb/web_ui/assets/modeler-CQmqflbg.js +1 -0
- data/lib/mxrb/web_ui/assets/ordinal-BDEzSJ7C.js +1 -0
- data/lib/mxrb/web_ui/assets/packet-7NZHBO7P-CwQ4NSBs.js +1 -0
- data/lib/mxrb/web_ui/assets/path-fybaL0A-.js +1 -0
- data/lib/mxrb/web_ui/assets/pegDiagram-VL7TDLO6-D40S7ppx.js +1 -0
- data/lib/mxrb/web_ui/assets/pie-RZYD4A2V-CJroHMKh.js +1 -0
- data/lib/mxrb/web_ui/assets/pieDiagram-7S7Q4E2Y-QB54__BV.js +39 -0
- data/lib/mxrb/web_ui/assets/quadrantDiagram-CIZ2JOQS-DBhDS6ag.js +7 -0
- data/lib/mxrb/web_ui/assets/radar-I7S5WNFK-DdIUwd2d.js +1 -0
- data/lib/mxrb/web_ui/assets/railroad-3IZDKUUU-B1Lw6Xyq.js +1 -0
- data/lib/mxrb/web_ui/assets/railroad-abnf-AHOZXSZD-CQgQoeak.js +1 -0
- data/lib/mxrb/web_ui/assets/railroad-ebnf-EBAXGLYW-D7qEQ2x8.js +1 -0
- data/lib/mxrb/web_ui/assets/railroad-peg-LSFZ7HO6-C005Vxbb.js +1 -0
- data/lib/mxrb/web_ui/assets/railroadDiagram-AXF67PYL-BBP2qk7M.js +1 -0
- data/lib/mxrb/web_ui/assets/requirementDiagram-LRYGKXZP-D2cLsAoI.js +84 -0
- data/lib/mxrb/web_ui/assets/rough.esm-Dy-Kn_BL.js +1 -0
- data/lib/mxrb/web_ui/assets/sankeyDiagram-W5VNT64P-Bpi3FiP2.js +40 -0
- data/lib/mxrb/web_ui/assets/sequenceDiagram-SI44F4Z6-DCRcDlVe.js +162 -0
- data/lib/mxrb/web_ui/assets/sizeCapture-X5ZJPWSS-B0uUizjq.js +1 -0
- data/lib/mxrb/web_ui/assets/src-CvxfUak2.js +1 -0
- data/lib/mxrb/web_ui/assets/stateDiagram-OKZ733FA-C2GCEoxl.js +1 -0
- data/lib/mxrb/web_ui/assets/stateDiagram-v2-UEYNNEHI-D2gWgedh.js +1 -0
- data/lib/mxrb/web_ui/assets/swimlanes-SLNWSIFB-CRI9irEW.js +2 -0
- data/lib/mxrb/web_ui/assets/swimlanesDiagram-ULZ7WXOC-C5Wb_-hZ.js +8 -0
- data/lib/mxrb/web_ui/assets/theme-_mxc7BdY.css +1 -0
- data/lib/mxrb/web_ui/assets/timeline-definition-Z64GVDOM-B1-mNg-h.js +120 -0
- data/lib/mxrb/web_ui/assets/treeView-QDETBFTQ-7CTvIwKq.js +1 -0
- data/lib/mxrb/web_ui/assets/treemap-6X3UGDF4-CtL22pq5.js +1 -0
- data/lib/mxrb/web_ui/assets/uml-C3KAFGTq.js +51 -0
- data/lib/mxrb/web_ui/assets/uml-Dn-qd01X.css +1 -0
- data/lib/mxrb/web_ui/assets/vennDiagram-T6HMQDX7-BzVnUEAy.js +34 -0
- data/lib/mxrb/web_ui/assets/wardley-OPB4EBWU-JNi-QNag.js +1 -0
- data/lib/mxrb/web_ui/assets/wardleyDiagram-T6FBY63Y-BUwmAQ-B.js +78 -0
- data/lib/mxrb/web_ui/assets/xychartDiagram-ELKLHX3M-DEQS8sKp.js +7 -0
- data/lib/mxrb/web_ui/domain.html +15 -0
- data/lib/mxrb/web_ui/modeler.html +16 -0
- data/lib/mxrb/web_ui/uml.html +31 -0
- data/lib/mxrb/web_ui.rb +89 -0
- data/lib/mxrb/widget_certification.rb +208 -0
- data/lib/mxrb/writer.rb +200 -24
- data/lib/mxrb.rb +26 -1
- metadata +156 -5
|
@@ -157,15 +157,23 @@ module Mxrb
|
|
|
157
157
|
@transaction.write(path, lines.join)
|
|
158
158
|
end
|
|
159
159
|
|
|
160
|
-
def connect_project_dotenv(source)
|
|
160
|
+
def connect_project_dotenv(source) # rubocop:disable Metrics/MethodLength
|
|
161
|
+
return source if source.include?('Mxrb::Environment.load(root: __dir__).apply')
|
|
162
|
+
|
|
161
163
|
dotenv_line = 'Dotenv.load(File.join(__dir__, ".env"))'
|
|
162
164
|
return source if source.include?(dotenv_line)
|
|
163
165
|
|
|
164
166
|
lines = source.lines
|
|
165
167
|
require_line = lines.index { _1.match?(%r{^require ["']dotenv/load["']\s*$}) }
|
|
166
|
-
|
|
168
|
+
return lines.insert(require_line + 1, "#{dotenv_line}\n").join if require_line
|
|
169
|
+
|
|
170
|
+
mxrb_require = lines.index { _1.match?(/^require ["']mxrb["']\s*$/) }
|
|
171
|
+
unless mxrb_require
|
|
172
|
+
raise ArgumentError,
|
|
173
|
+
'project.rb must require mxrb or dotenv/load before scaffolding demo users'
|
|
174
|
+
end
|
|
167
175
|
|
|
168
|
-
lines.insert(
|
|
176
|
+
lines.insert(mxrb_require + 1, "\nMxrb::Environment.load(root: __dir__).apply\n").join
|
|
169
177
|
end
|
|
170
178
|
|
|
171
179
|
def security_initialization_error
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'support'
|
|
4
|
+
|
|
5
|
+
module Mxrb
|
|
6
|
+
module Uml
|
|
7
|
+
# Renders the native object/sequence-flow graph of one Mendix microflow.
|
|
8
|
+
# rubocop:disable Metrics
|
|
9
|
+
class ActivityDiagram
|
|
10
|
+
def initialize(microflow)
|
|
11
|
+
@microflow = microflow
|
|
12
|
+
@objects = Array(microflow.objects)
|
|
13
|
+
@flows = Array(microflow.flows)
|
|
14
|
+
@objects_by_id = @objects.to_h { [raw_object_id(_1), _1] }
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def to_mermaid
|
|
18
|
+
lines = ['flowchart TD']
|
|
19
|
+
@objects.each { lines << " #{mermaid_node(_1)}" }
|
|
20
|
+
@flows.each do |flow|
|
|
21
|
+
line = flow_line(flow, :mermaid)
|
|
22
|
+
lines << " #{line}" if line
|
|
23
|
+
end
|
|
24
|
+
"#{lines.join("\n")}\n"
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def to_plantuml
|
|
28
|
+
lines = ['@startuml', "title #{Support.plantuml_text(@microflow.name)}"]
|
|
29
|
+
@objects.each { lines << plantuml_node(_1) }
|
|
30
|
+
@flows.each do |flow|
|
|
31
|
+
line = flow_line(flow, :plantuml)
|
|
32
|
+
lines << line if line
|
|
33
|
+
end
|
|
34
|
+
lines << '@enduml'
|
|
35
|
+
"#{lines.join("\n")}\n"
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
private
|
|
39
|
+
|
|
40
|
+
def mermaid_node(object)
|
|
41
|
+
id = node_id(object)
|
|
42
|
+
label = Support.mermaid_text(object_label(object))
|
|
43
|
+
case object_type(object)
|
|
44
|
+
when 'StartEvent' then %(#{id}(["Start"]))
|
|
45
|
+
when 'EndEvent', 'ErrorEvent', 'ContinueEvent' then %(#{id}(["#{label}"]))
|
|
46
|
+
when 'DecisionMergeActivity', 'ExclusiveMerge' then %(#{id}{"#{label}"})
|
|
47
|
+
else %(#{id}["#{label}"])
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def plantuml_node(object)
|
|
52
|
+
id = node_id(object)
|
|
53
|
+
label = Support.plantuml_text(object_label(object))
|
|
54
|
+
shape = %w[DecisionMergeActivity ExclusiveMerge].include?(object_type(object)) ? 'choice' : 'state'
|
|
55
|
+
%(#{shape} "#{label}" as #{id})
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def flow_line(flow, format)
|
|
59
|
+
origin = pointer(flow, 'OriginPointer', 'Origin')
|
|
60
|
+
destination = pointer(flow, 'DestinationPointer', 'Destination')
|
|
61
|
+
return unless @objects_by_id.key?(origin) && @objects_by_id.key?(destination)
|
|
62
|
+
|
|
63
|
+
label = flow_label(flow)
|
|
64
|
+
if format == :mermaid
|
|
65
|
+
middle = label.empty? ? '-->' : %(-->|"#{Support.mermaid_text(label)}"|)
|
|
66
|
+
"#{node_id(@objects_by_id.fetch(origin))} #{middle} #{node_id(@objects_by_id.fetch(destination))}"
|
|
67
|
+
else
|
|
68
|
+
suffix = label.empty? ? '' : " : #{Support.plantuml_text(label)}"
|
|
69
|
+
"#{node_id(@objects_by_id.fetch(origin))} --> #{node_id(@objects_by_id.fetch(destination))}#{suffix}"
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def object_label(object)
|
|
74
|
+
type = object_type(object)
|
|
75
|
+
return 'Start' if type == 'StartEvent'
|
|
76
|
+
return Support.words(type) unless type == 'ActionActivity'
|
|
77
|
+
|
|
78
|
+
caption = object['Caption'] || object['caption']
|
|
79
|
+
action = object['Action'] || object['action'] || {}
|
|
80
|
+
generated = object['AutoGenerateCaption'] == true || caption.to_s == 'Activity'
|
|
81
|
+
return caption unless caption.to_s.empty? || generated
|
|
82
|
+
|
|
83
|
+
call = action['MicroflowCall'] || action['microflowCall'] || {}
|
|
84
|
+
target = call['Microflow'] || call['microflow']
|
|
85
|
+
return "Call #{target}" unless target.to_s.empty?
|
|
86
|
+
|
|
87
|
+
Support.words(action['$Type'] || action['Type'] || 'Action')
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def flow_label(flow)
|
|
91
|
+
direct = flow['Caption'] || flow['Label'] || flow['Condition']
|
|
92
|
+
return direct.to_s unless direct.to_s.empty?
|
|
93
|
+
|
|
94
|
+
value = flow['CaseValue'] || flow['caseValue']
|
|
95
|
+
value = Mxrb::IO::BsonCodec.parse_array(flow['CaseValues'])[:items].first if value.nil? && flow['CaseValues']
|
|
96
|
+
return '' if value.nil?
|
|
97
|
+
|
|
98
|
+
if value.is_a?(Hash)
|
|
99
|
+
return '' if (value['$Type'] || value['Type']).to_s.end_with?('$NoCase')
|
|
100
|
+
|
|
101
|
+
(value['StringRepresentation'] || value['Value'] || Support.words(value['$Type'])).to_s
|
|
102
|
+
else
|
|
103
|
+
value.to_s
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def pointer(flow, *keys)
|
|
108
|
+
value = keys.filter_map { flow[_1] }.first
|
|
109
|
+
Mxrb::IO::BsonCodec.extract_id(value).to_s
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def raw_object_id(object) = Mxrb::IO::BsonCodec.extract_id(object['$ID'] || object['ID']).to_s
|
|
113
|
+
def object_type(object) = (object['$Type'] || object['Type']).to_s.delete_prefix('Microflows$')
|
|
114
|
+
def node_id(object) = Support.identifier(raw_object_id(object), prefix: 'activity')
|
|
115
|
+
end
|
|
116
|
+
# rubocop:enable Metrics
|
|
117
|
+
end
|
|
118
|
+
end
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'support'
|
|
4
|
+
|
|
5
|
+
module Mxrb
|
|
6
|
+
module Uml
|
|
7
|
+
# Projects Mendix domain models as Mermaid and PlantUML class diagrams.
|
|
8
|
+
# rubocop:disable Metrics/AbcSize
|
|
9
|
+
class ClassDiagram
|
|
10
|
+
TYPES = {
|
|
11
|
+
string: 'String', integer: 'Integer', long: 'Long', float: 'Float',
|
|
12
|
+
decimal: 'Decimal', boolean: 'Boolean', datetime: 'DateTime',
|
|
13
|
+
autonumber: 'AutoNumber', hashstring: 'HashedString', binary: 'Binary',
|
|
14
|
+
enum: 'Enumeration'
|
|
15
|
+
}.freeze
|
|
16
|
+
|
|
17
|
+
def initialize(modules)
|
|
18
|
+
@modules = Array(modules)
|
|
19
|
+
@entities = @modules.flat_map(&:entities)
|
|
20
|
+
@module_by_entity = @modules.each_with_object({}) do |mod, result|
|
|
21
|
+
mod.entities.each { result[_1.id.to_s] = mod.name.to_s }
|
|
22
|
+
end
|
|
23
|
+
@entity_by_key = @entities.each_with_object({}) do |entity, result|
|
|
24
|
+
qualified = qualified_name(entity)
|
|
25
|
+
result[entity.id.to_s] = entity
|
|
26
|
+
result[qualified] = entity
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def to_mermaid
|
|
31
|
+
lines = ['classDiagram']
|
|
32
|
+
@entities.each { append_mermaid_class(lines, _1) }
|
|
33
|
+
associations.each { lines << mermaid_association(_1) }
|
|
34
|
+
"#{lines.join("\n")}\n"
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def to_plantuml
|
|
38
|
+
lines = ['@startuml', 'hide empty methods']
|
|
39
|
+
@entities.each { append_plantuml_class(lines, _1) }
|
|
40
|
+
associations.each { lines << plantuml_association(_1) }
|
|
41
|
+
lines << '@enduml'
|
|
42
|
+
"#{lines.join("\n")}\n"
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
private
|
|
46
|
+
|
|
47
|
+
def append_mermaid_class(lines, entity)
|
|
48
|
+
identifier = entity_identifier(entity)
|
|
49
|
+
lines << %(class #{identifier}["#{Support.mermaid_text(qualified_name(entity))}"])
|
|
50
|
+
lines << "class #{identifier} {"
|
|
51
|
+
entity.attributes.each do |attribute|
|
|
52
|
+
lines << " +#{attribute_type(attribute)} #{Support.mermaid_text(attribute.name)}"
|
|
53
|
+
end
|
|
54
|
+
lines << '}'
|
|
55
|
+
stereotype(entity).then { lines << "<<#{_1}>> #{identifier}" if _1 }
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def append_plantuml_class(lines, entity)
|
|
59
|
+
identifier = entity_identifier(entity)
|
|
60
|
+
suffix = stereotype(entity).then { _1 ? " <<#{_1}>>" : '' }
|
|
61
|
+
lines << %(class "#{Support.plantuml_text(qualified_name(entity))}" as #{identifier}#{suffix} {)
|
|
62
|
+
entity.attributes.each do |attribute|
|
|
63
|
+
lines << " +#{Support.plantuml_text(attribute.name)} : #{attribute_type(attribute)}"
|
|
64
|
+
end
|
|
65
|
+
lines << '}'
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def associations
|
|
69
|
+
@modules.flat_map(&:associations).filter_map do |association|
|
|
70
|
+
from = @entity_by_key[association.from_entity_id.to_s]
|
|
71
|
+
to = @entity_by_key[association.to_entity_id.to_s]
|
|
72
|
+
[association, from, to] if from && to
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def mermaid_association(tuple)
|
|
77
|
+
association, from, to = tuple
|
|
78
|
+
left, right = multiplicities(association)
|
|
79
|
+
label = Support.mermaid_text(association.name)
|
|
80
|
+
%(#{entity_identifier(from)} "#{left}" --> "#{right}" #{entity_identifier(to)} : #{label})
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def plantuml_association(tuple)
|
|
84
|
+
association, from, to = tuple
|
|
85
|
+
left, right = multiplicities(association)
|
|
86
|
+
label = Support.plantuml_text(association.name)
|
|
87
|
+
%(#{entity_identifier(from)} "#{left}" --> "#{right}" #{entity_identifier(to)} : #{label})
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def multiplicities(association)
|
|
91
|
+
association.association_type.to_sym == :ReferenceSet ? ['*', '*'] : %w[1 N]
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def attribute_type(attribute)
|
|
95
|
+
return Support.words(attribute.enumeration.to_s.split('.').last) unless attribute.enumeration.to_s.empty?
|
|
96
|
+
|
|
97
|
+
TYPES.fetch(attribute.type.to_sym, Support.words(attribute.type))
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def stereotype(entity)
|
|
101
|
+
return 'OQL View' if entity.respond_to?(:oql_view?) && entity.oql_view?
|
|
102
|
+
return 'DTO' unless entity.persistable == true
|
|
103
|
+
|
|
104
|
+
nil
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def qualified_name(entity)
|
|
108
|
+
value = entity.qualified_name.to_s
|
|
109
|
+
return value unless value.empty?
|
|
110
|
+
|
|
111
|
+
"#{@module_by_entity.fetch(entity.id.to_s)}.#{entity.name}"
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def entity_identifier(entity) = Support.identifier(qualified_name(entity), prefix: 'class')
|
|
115
|
+
end
|
|
116
|
+
# rubocop:enable Metrics/AbcSize
|
|
117
|
+
end
|
|
118
|
+
end
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'support'
|
|
4
|
+
|
|
5
|
+
module Mxrb
|
|
6
|
+
module Uml
|
|
7
|
+
# Builds call-chain sequence diagrams from the existing semantic index.
|
|
8
|
+
# rubocop:disable Metrics
|
|
9
|
+
class SequenceDiagram
|
|
10
|
+
CALLABLE_KINDS = %i[microflow nanoflow].freeze
|
|
11
|
+
MAX_DEPTH = 100
|
|
12
|
+
|
|
13
|
+
def initialize(index, root: nil, module_name: nil, depth: 2)
|
|
14
|
+
raise ArgumentError, 'choose either root or module_name' if root && module_name
|
|
15
|
+
raise ArgumentError, 'root or module_name is required' unless root || module_name
|
|
16
|
+
|
|
17
|
+
@index = index
|
|
18
|
+
@root = root
|
|
19
|
+
@module_name = module_name
|
|
20
|
+
@depth = Integer(depth)
|
|
21
|
+
raise ArgumentError, 'depth must be zero or greater' if @depth.negative?
|
|
22
|
+
raise ArgumentError, "depth cannot exceed #{MAX_DEPTH}" if @depth > MAX_DEPTH
|
|
23
|
+
|
|
24
|
+
@edges, @selected = root ? root_graph : module_graph
|
|
25
|
+
@participants = participants
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def to_mermaid
|
|
29
|
+
lines = ['sequenceDiagram']
|
|
30
|
+
@participants.each do |artifact|
|
|
31
|
+
lines << %( participant #{participant_id(artifact)} as #{Support.mermaid_text(artifact.qualified_name)})
|
|
32
|
+
end
|
|
33
|
+
@edges.each do |source, target|
|
|
34
|
+
lines << " #{participant_id(source)}->>#{participant_id(target)}: call"
|
|
35
|
+
end
|
|
36
|
+
append_mermaid_empty_note(lines) if @edges.empty?
|
|
37
|
+
"#{lines.join("\n")}\n"
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def to_plantuml
|
|
41
|
+
lines = ['@startuml']
|
|
42
|
+
@participants.each do |artifact|
|
|
43
|
+
lines << %(participant "#{Support.plantuml_text(artifact.qualified_name)}" as #{participant_id(artifact)})
|
|
44
|
+
end
|
|
45
|
+
@edges.each do |source, target|
|
|
46
|
+
lines << "#{participant_id(source)} -> #{participant_id(target)} : call"
|
|
47
|
+
end
|
|
48
|
+
lines << 'note "No call relationships found" as MXRB' if @edges.empty?
|
|
49
|
+
lines << '@enduml'
|
|
50
|
+
"#{lines.join("\n")}\n"
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
private
|
|
54
|
+
|
|
55
|
+
def root_graph
|
|
56
|
+
root = @index.find(@root)
|
|
57
|
+
raise ArgumentError, "microflow not found: #{@root}" unless root && CALLABLE_KINDS.include?(root.kind)
|
|
58
|
+
|
|
59
|
+
edges = []
|
|
60
|
+
visited = {}
|
|
61
|
+
visit = lambda do |source, level|
|
|
62
|
+
return if level >= @depth || visited.key?(source.id)
|
|
63
|
+
|
|
64
|
+
visited[source.id] = true
|
|
65
|
+
callees(source).each do |target|
|
|
66
|
+
edges << [source, target]
|
|
67
|
+
visit.call(target, level + 1)
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
visit.call(root, 0)
|
|
71
|
+
[edges.uniq { [_1.id, _2.id] }, [root]]
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def module_graph
|
|
75
|
+
sources = @index.artifacts.select do |artifact|
|
|
76
|
+
artifact.module_name == @module_name.to_s && CALLABLE_KINDS.include?(artifact.kind)
|
|
77
|
+
end
|
|
78
|
+
raise ArgumentError, "module not found or has no microflows: #{@module_name}" if sources.empty?
|
|
79
|
+
|
|
80
|
+
edges = sources.flat_map do |source|
|
|
81
|
+
callees(source).filter_map do |target|
|
|
82
|
+
[source, target] if target.module_name == @module_name.to_s
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
edges = edges.uniq { [_1.id, _2.id] }
|
|
86
|
+
[edges, sources]
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def callees(source)
|
|
90
|
+
@index.references_from(source).filter_map do |reference|
|
|
91
|
+
reference.target if reference.relation == :calls && CALLABLE_KINDS.include?(reference.target.kind)
|
|
92
|
+
end.uniq(&:id)
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def participants
|
|
96
|
+
(@selected + @edges.flatten).uniq(&:id).sort_by(&:qualified_name)
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def append_mermaid_empty_note(lines)
|
|
100
|
+
participant = @participants.first
|
|
101
|
+
lines << if participant
|
|
102
|
+
" Note over #{participant_id(participant)}: No call relationships found"
|
|
103
|
+
else
|
|
104
|
+
' Note over MXRB: No call relationships found'
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def participant_id(artifact) = Support.identifier(artifact.qualified_name, prefix: 'participant')
|
|
109
|
+
end
|
|
110
|
+
# rubocop:enable Metrics
|
|
111
|
+
end
|
|
112
|
+
end
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'json'
|
|
4
|
+
|
|
5
|
+
require_relative '../web_ui'
|
|
6
|
+
require_relative '../http/server'
|
|
7
|
+
require_relative '../modeler/catalog'
|
|
8
|
+
|
|
9
|
+
module Mxrb
|
|
10
|
+
module Uml
|
|
11
|
+
# Loopback-only unified viewer for class, activity, and sequence diagrams.
|
|
12
|
+
# rubocop:disable Metrics
|
|
13
|
+
class Server
|
|
14
|
+
LOOPBACK_HOSTS = %w[127.0.0.1 ::1 localhost].freeze
|
|
15
|
+
|
|
16
|
+
attr_reader :source, :host, :port
|
|
17
|
+
|
|
18
|
+
def initialize(source, host: '127.0.0.1', port: 4569)
|
|
19
|
+
@source = File.expand_path(source)
|
|
20
|
+
raise ArgumentError, "MPR not found: #{@source}" unless File.file?(@source)
|
|
21
|
+
|
|
22
|
+
@host = host.to_s
|
|
23
|
+
raise ArgumentError, 'UML server must bind to loopback' unless LOOPBACK_HOSTS.include?(@host)
|
|
24
|
+
|
|
25
|
+
@port = Integer(port)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def start
|
|
29
|
+
@server = Http::Server.new(host:, port:) { dispatch(_1, _2) }
|
|
30
|
+
@server.start { yield(_1) if block_given? }
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def shutdown = @server&.shutdown
|
|
34
|
+
|
|
35
|
+
private
|
|
36
|
+
|
|
37
|
+
def dispatch(request, response)
|
|
38
|
+
return render(response, 200, WebUi.page('uml'), 'text/html; charset=utf-8') \
|
|
39
|
+
if request.request_method == 'GET' && request.path == '/'
|
|
40
|
+
return render(response, 200, WebUi.page('modeler'), 'text/html; charset=utf-8') \
|
|
41
|
+
if request.request_method == 'GET' && request.path == '/modeler'
|
|
42
|
+
|
|
43
|
+
if request.request_method == 'GET' && request.path.start_with?('/assets/')
|
|
44
|
+
asset = WebUi.asset(request.path)
|
|
45
|
+
return render(response, 200, *asset) if asset
|
|
46
|
+
|
|
47
|
+
return json(response, 404, ok: false, error: 'not_found')
|
|
48
|
+
end
|
|
49
|
+
return json(response, 405, ok: false, error: 'method_not_allowed') unless request.request_method == 'GET'
|
|
50
|
+
|
|
51
|
+
payload = case request.path
|
|
52
|
+
when '/api/class' then class_payload(request.query)
|
|
53
|
+
when '/api/activity' then activity_payload(request.query)
|
|
54
|
+
when '/api/sequence' then sequence_payload(request.query)
|
|
55
|
+
when '/api/catalog' then catalog_payload
|
|
56
|
+
when '/api/project' then Modeler::Catalog.new(source).to_h
|
|
57
|
+
end
|
|
58
|
+
return json(response, 404, ok: false, error: 'not_found') unless payload
|
|
59
|
+
|
|
60
|
+
json(response, 200, payload)
|
|
61
|
+
rescue ArgumentError, KeyError, Mxrb::Error => e
|
|
62
|
+
json(response, 422, ok: false, error: e.message)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def class_payload(query)
|
|
66
|
+
selected = query.fetch('modules', '').split(',').map(&:strip).reject(&:empty?)
|
|
67
|
+
with_project do |project|
|
|
68
|
+
modules = project.modules
|
|
69
|
+
unless selected.empty?
|
|
70
|
+
unknown = selected - modules.map(&:name)
|
|
71
|
+
raise ArgumentError, "unknown modules: #{unknown.join(', ')}" unless unknown.empty?
|
|
72
|
+
|
|
73
|
+
modules = modules.select { selected.include?(_1.name) }
|
|
74
|
+
end
|
|
75
|
+
formats(ClassDiagram.new(modules))
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def activity_payload(query)
|
|
80
|
+
qualified = query.fetch('microflow') { raise ArgumentError, 'microflow is required' }
|
|
81
|
+
with_project do |project|
|
|
82
|
+
flow = find_microflow(project, qualified)
|
|
83
|
+
raise ArgumentError, "microflow not found: #{qualified}" unless flow
|
|
84
|
+
|
|
85
|
+
formats(ActivityDiagram.new(flow))
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def sequence_payload(query)
|
|
90
|
+
root = query['root']
|
|
91
|
+
module_name = query['module']
|
|
92
|
+
raise ArgumentError, 'root or module is required' if root.to_s.empty? && module_name.to_s.empty?
|
|
93
|
+
|
|
94
|
+
with_project do |project|
|
|
95
|
+
diagram = SequenceDiagram.new(
|
|
96
|
+
project.semantic_index,
|
|
97
|
+
root: root.to_s.empty? ? nil : root,
|
|
98
|
+
module_name: module_name.to_s.empty? ? nil : module_name,
|
|
99
|
+
depth: query.fetch('depth', 2)
|
|
100
|
+
)
|
|
101
|
+
formats(diagram)
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def catalog_payload
|
|
106
|
+
with_project do |project|
|
|
107
|
+
{
|
|
108
|
+
modules: project.modules.map(&:name).sort,
|
|
109
|
+
microflows: project.modules.flat_map do |mod|
|
|
110
|
+
mod.microflows.map { "#{mod.name}.#{_1.name}" }
|
|
111
|
+
end.sort
|
|
112
|
+
}
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def find_microflow(project, qualified)
|
|
117
|
+
module_name, flow_name = qualified.to_s.split('.', 2)
|
|
118
|
+
return unless flow_name
|
|
119
|
+
|
|
120
|
+
project.modules.find { _1.name == module_name }&.microflows&.find { _1.name == flow_name }
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def with_project
|
|
124
|
+
project = Model::Project.open(source)
|
|
125
|
+
yield project
|
|
126
|
+
ensure
|
|
127
|
+
project&.close
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def formats(diagram) = { mermaid: diagram.to_mermaid, plantuml: diagram.to_plantuml }
|
|
131
|
+
|
|
132
|
+
def json(response, status, payload)
|
|
133
|
+
render(response, status, JSON.generate(payload), 'application/json; charset=utf-8')
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def render(response, status, body, type)
|
|
137
|
+
response.status = status
|
|
138
|
+
response['Content-Type'] = type
|
|
139
|
+
response['Cache-Control'] = 'no-store'
|
|
140
|
+
response['X-Content-Type-Options'] = 'nosniff'
|
|
141
|
+
response.body = body
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
# rubocop:enable Metrics
|
|
145
|
+
end
|
|
146
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'digest'
|
|
4
|
+
|
|
5
|
+
module Mxrb
|
|
6
|
+
module Uml
|
|
7
|
+
# Shared, deterministic escaping and identifier helpers for text formats.
|
|
8
|
+
module Support
|
|
9
|
+
module_function
|
|
10
|
+
|
|
11
|
+
def identifier(value, prefix: 'n')
|
|
12
|
+
raw = value.to_s
|
|
13
|
+
body = raw.gsub(/[^A-Za-z0-9_]/, '_')
|
|
14
|
+
body = prefix if body.empty?
|
|
15
|
+
body = "#{prefix}_#{body}" unless body.match?(/\A[A-Za-z_]/)
|
|
16
|
+
body += "_#{Digest::SHA256.hexdigest(raw)[0, 8]}" unless body == raw
|
|
17
|
+
body
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def mermaid_text(value)
|
|
21
|
+
value.to_s.gsub('&', '&').gsub('<', '<').gsub('>', '>')
|
|
22
|
+
.gsub('"', '"').gsub(/[\r\n]+/, ' ')
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def plantuml_text(value)
|
|
26
|
+
value.to_s.gsub('\\') { '\\\\' }.gsub('"', '\\"').gsub(/[\r\n]+/, ' ')
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def words(value)
|
|
30
|
+
value.to_s.delete_prefix('Microflows$').delete_suffix('Action')
|
|
31
|
+
.gsub(/([a-z0-9])([A-Z])/, '\\1 \\2').tr('_', ' ').strip
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
data/lib/mxrb/version.rb
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{n as e}from"./chunk-Y2CYZVJY-DsF7k-Jl.js";import{m as t}from"./src-CvxfUak2.js";import"./chunk-I66GZJ75-CulcrLPh.js";import"./uml-C3KAFGTq.js";import{m as n,t as r}from"./mermaid-parser.core-B_UPzTxa.js";import{n as i,r as a,t as o}from"./chunk-6Q2QTUOP-wQkNmt_X.js";import{t as s}from"./chunk-JWPE2WC7-DVXcaiue.js";var c=n().RailroadAbnf.parser.LangiumParser,l=e(e=>{let t=e.alternatives.map(u);return t.length===1?t[0]:{type:`choice`,alternatives:t}},`transformAlternation`),u=e(e=>{let t=e.elements.map(f);return t.length===1?t[0]:{type:`sequence`,elements:t}},`transformConcatenation`),d=e(e=>{if(e.includes(`*`)){let[t,n]=e.split(`*`);return{min:t?parseInt(t,10):0,max:n?parseInt(n,10):1/0}}let t=parseInt(e,10);return{min:t,max:t}},`parseRepeat`),f=e(e=>{let t=p(e.primary);if(!e.repeat)return t;let{min:n,max:r}=d(e.repeat);return n===0&&r===1?{type:`optional`,element:t}:{type:`repetition`,element:t,min:n,max:r}},`transformElement`),p=e(e=>{switch(e.$type){case`AbnfStringLiteral`:return{type:`terminal`,value:e.value};case`AbnfNumVal`:return{type:`terminal`,value:e.value};case`AbnfRuleName`:return{type:`nonterminal`,name:e.name};case`AbnfGroup`:return l(e.element);case`AbnfOptionalGroup`:return{type:`optional`,element:l(e.element)};default:throw Error(`Unsupported ABNF primary node: ${e.$type}`)}},`transformPrimary`),m=e(e=>({name:e.name,definition:l(e.definition)}),`transformRule`),h=e(e=>{s(e,o),e.title&&o.setTitle(e.title),e.rules.map(e=>o.addRule(m(e)))},`populateDb`),g={parser:{parse:e(e=>{o.clear(),t.debug(`[ABNF Parser] Starting Langium parse`);let n=c.parse(e);if(n.lexerErrors.length>0||n.parserErrors.length>0)throw new r(n);let i=n.value;t.debug(`[ABNF Parser] Parsed rules:`,i.rules.length),h(i),t.debug(`[ABNF Parser] Parse complete`)},`parse`),parser:{yy:o}},db:o,renderer:a,styles:i};export{g as diagram};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{n as e,t}from"./path-fybaL0A-.js";import{a as n,c as r,d as i,f as a,i as o,l as s,m as c,n as l,o as u,p as d,r as f,u as p}from"./dist-D2qOEbeJ.js";function m(e){return e.innerRadius}function h(e){return e.outerRadius}function g(e){return e.startAngle}function _(e){return e.endAngle}function v(e){return e&&e.padAngle}function y(e,t,n,r,i,a,o,s){var c=n-e,l=r-t,u=o-i,d=s-a,f=d*c-u*l;if(!(f*f<1e-12))return f=(u*(t-a)-d*(e-i))/f,[e+f*c,t+f*l]}function b(e,t,n,r,i,a,o){var c=e-n,l=t-r,u=(o?a:-a)/d(c*c+l*l),f=u*l,p=-u*c,m=e+f,h=t+p,g=n+f,_=r+p,v=(m+g)/2,y=(h+_)/2,b=g-m,x=_-h,S=b*b+x*x,C=i-a,w=m*_-g*h,T=(x<0?-1:1)*d(s(0,C*C*S-w*w)),E=(w*x-b*T)/S,D=(-w*b-x*T)/S,O=(w*x+b*T)/S,k=(-w*b+x*T)/S,A=E-v,j=D-y,M=O-v,N=k-y;return A*A+j*j>M*M+N*N&&(E=O,D=k),{cx:E,cy:D,x01:-f,y01:-p,x11:E*(i/C-1),y11:D*(i/C-1)}}function x(){var s=m,x=h,S=e(0),C=null,w=g,T=_,E=v,D=null,O=t(k);function k(){var e,t,m=+s.apply(this,arguments),h=+x.apply(this,arguments),g=w.apply(this,arguments)-r,_=T.apply(this,arguments)-r,v=l(_-g),k=_>g;if(D||=e=O(),h<m&&(t=h,h=m,m=t),!(h>1e-12))D.moveTo(0,0);else if(v>c-1e-12)D.moveTo(h*u(g),h*a(g)),D.arc(0,0,h,g,_,!k),m>1e-12&&(D.moveTo(m*u(_),m*a(_)),D.arc(0,0,m,_,g,k));else{var A=g,j=_,M=g,N=_,P=v,F=v,I=E.apply(this,arguments)/2,L=I>1e-12&&(C?+C.apply(this,arguments):d(m*m+h*h)),R=p(l(h-m)/2,+S.apply(this,arguments)),z=R,B=R,V,H;if(L>1e-12){var U=o(L/m*a(I)),W=o(L/h*a(I));(P-=U*2)>1e-12?(U*=k?1:-1,M+=U,N-=U):(P=0,M=N=(g+_)/2),(F-=W*2)>1e-12?(W*=k?1:-1,A+=W,j-=W):(F=0,A=j=(g+_)/2)}var G=h*u(A),K=h*a(A),q=m*u(N),J=m*a(N);if(R>1e-12){var Y=h*u(j),X=h*a(j),Z=m*u(M),Q=m*a(M),$;if(v<i){if($=y(G,K,Z,Q,Y,X,q,J)){var ee=G-$[0],te=K-$[1],ne=Y-$[0],re=X-$[1],ie=1/a(f((ee*ne+te*re)/(d(ee*ee+te*te)*d(ne*ne+re*re)))/2),ae=d($[0]*$[0]+$[1]*$[1]);z=p(R,(m-ae)/(ie-1)),B=p(R,(h-ae)/(ie+1))}else z=B=0}}F>1e-12?B>1e-12?(V=b(Z,Q,G,K,h,B,k),H=b(Y,X,q,J,h,B,k),D.moveTo(V.cx+V.x01,V.cy+V.y01),B<R?D.arc(V.cx,V.cy,B,n(V.y01,V.x01),n(H.y01,H.x01),!k):(D.arc(V.cx,V.cy,B,n(V.y01,V.x01),n(V.y11,V.x11),!k),D.arc(0,0,h,n(V.cy+V.y11,V.cx+V.x11),n(H.cy+H.y11,H.cx+H.x11),!k),D.arc(H.cx,H.cy,B,n(H.y11,H.x11),n(H.y01,H.x01),!k))):(D.moveTo(G,K),D.arc(0,0,h,A,j,!k)):D.moveTo(G,K),!(m>1e-12)||!(P>1e-12)?D.lineTo(q,J):z>1e-12?(V=b(q,J,Y,X,m,-z,k),H=b(G,K,Z,Q,m,-z,k),D.lineTo(V.cx+V.x01,V.cy+V.y01),z<R?D.arc(V.cx,V.cy,z,n(V.y01,V.x01),n(H.y01,H.x01),!k):(D.arc(V.cx,V.cy,z,n(V.y01,V.x01),n(V.y11,V.x11),!k),D.arc(0,0,m,n(V.cy+V.y11,V.cx+V.x11),n(H.cy+H.y11,H.cx+H.x11),k),D.arc(H.cx,H.cy,z,n(H.y11,H.x11),n(H.y01,H.x01),!k))):D.arc(0,0,m,N,M,k)}if(D.closePath(),e)return D=null,e+``||null}return k.centroid=function(){var e=(+s.apply(this,arguments)+ +x.apply(this,arguments))/2,t=(+w.apply(this,arguments)+ +T.apply(this,arguments))/2-i/2;return[u(t)*e,a(t)*e]},k.innerRadius=function(t){return arguments.length?(s=typeof t==`function`?t:e(+t),k):s},k.outerRadius=function(t){return arguments.length?(x=typeof t==`function`?t:e(+t),k):x},k.cornerRadius=function(t){return arguments.length?(S=typeof t==`function`?t:e(+t),k):S},k.padRadius=function(t){return arguments.length?(C=t==null?null:typeof t==`function`?t:e(+t),k):C},k.startAngle=function(t){return arguments.length?(w=typeof t==`function`?t:e(+t),k):w},k.endAngle=function(t){return arguments.length?(T=typeof t==`function`?t:e(+t),k):T},k.padAngle=function(t){return arguments.length?(E=typeof t==`function`?t:e(+t),k):E},k.context=function(e){return arguments.length?(D=e??null,k):D},k}export{x as t};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import"./chunk-KEIR6QF5-BICK3FdT.js";import{M as e}from"./mermaid-parser.core-B_UPzTxa.js";export{e as createArchitectureServices};
|