mxrb 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (237) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +21 -0
  3. data/README.de-DE.md +108 -0
  4. data/README.md +172 -0
  5. data/README.pt-BR.md +109 -0
  6. data/bin/mxrb +1613 -0
  7. data/docs/README.md +10 -0
  8. data/docs/de-DE/README.md +24 -0
  9. data/docs/de-DE/architectural-patterns.md +26 -0
  10. data/docs/de-DE/architectural-standard.md +48 -0
  11. data/docs/de-DE/architecture.md +76 -0
  12. data/docs/de-DE/compiler.md +162 -0
  13. data/docs/de-DE/conventions.md +19 -0
  14. data/docs/de-DE/design-system.md +52 -0
  15. data/docs/de-DE/entity-dsl.md +53 -0
  16. data/docs/de-DE/native-runtime-quality-report.md +74 -0
  17. data/docs/de-DE/oql-sql.md +211 -0
  18. data/docs/de-DE/platform-api-integration.md +36 -0
  19. data/docs/de-DE/platform-operations.md +243 -0
  20. data/docs/de-DE/project-structure.md +32 -0
  21. data/docs/de-DE/ruby-first-roadmap.md +116 -0
  22. data/docs/de-DE/scaffolds.md +59 -0
  23. data/docs/de-DE/semantic-refactoring.md +56 -0
  24. data/docs/de-DE/team-server.md +33 -0
  25. data/docs/de-DE/validation-matrix.md +64 -0
  26. data/docs/de-DE/vetclinic-acceptance.md +24 -0
  27. data/docs/de-DE/writing.md +138 -0
  28. data/docs/en-US/README.md +24 -0
  29. data/docs/en-US/architectural-patterns.md +151 -0
  30. data/docs/en-US/architectural-standard.md +89 -0
  31. data/docs/en-US/architecture.md +170 -0
  32. data/docs/en-US/compiler.md +157 -0
  33. data/docs/en-US/conventions.md +82 -0
  34. data/docs/en-US/design-system.md +163 -0
  35. data/docs/en-US/entity-dsl.md +53 -0
  36. data/docs/en-US/native-runtime-quality-report.md +73 -0
  37. data/docs/en-US/oql-sql.md +201 -0
  38. data/docs/en-US/platform-api-integration.md +36 -0
  39. data/docs/en-US/platform-operations.md +244 -0
  40. data/docs/en-US/project-structure.md +49 -0
  41. data/docs/en-US/ruby-first-roadmap.md +186 -0
  42. data/docs/en-US/scaffolds.md +57 -0
  43. data/docs/en-US/semantic-refactoring.md +198 -0
  44. data/docs/en-US/team-server.md +32 -0
  45. data/docs/en-US/validation-matrix.md +257 -0
  46. data/docs/en-US/vetclinic-acceptance.md +23 -0
  47. data/docs/en-US/writing.md +655 -0
  48. data/docs/pt-BR/README.md +24 -0
  49. data/docs/pt-BR/architectural-patterns.md +25 -0
  50. data/docs/pt-BR/architectural-standard.md +533 -0
  51. data/docs/pt-BR/architecture.md +300 -0
  52. data/docs/pt-BR/compiler.md +162 -0
  53. data/docs/pt-BR/conventions.md +19 -0
  54. data/docs/pt-BR/design-system.md +65 -0
  55. data/docs/pt-BR/entity-dsl.md +116 -0
  56. data/docs/pt-BR/native-runtime-quality-report.md +73 -0
  57. data/docs/pt-BR/oql-sql.md +208 -0
  58. data/docs/pt-BR/platform-api-integration.md +36 -0
  59. data/docs/pt-BR/platform-operations.md +260 -0
  60. data/docs/pt-BR/project-structure.md +32 -0
  61. data/docs/pt-BR/ruby-first-roadmap.md +239 -0
  62. data/docs/pt-BR/scaffolds.md +104 -0
  63. data/docs/pt-BR/semantic-refactoring.md +55 -0
  64. data/docs/pt-BR/team-server.md +59 -0
  65. data/docs/pt-BR/validation-matrix.md +86 -0
  66. data/docs/pt-BR/vetclinic-acceptance.md +50 -0
  67. data/docs/pt-BR/writing.md +177 -0
  68. data/examples/sudoku_evaluation.rb +14 -0
  69. data/examples/sudoku_functional_test.rb +28 -0
  70. data/lib/mxrb/architecture/graph.rb +124 -0
  71. data/lib/mxrb/architecture/validator.rb +98 -0
  72. data/lib/mxrb/benchmark.rb +33 -0
  73. data/lib/mxrb/compare.rb +390 -0
  74. data/lib/mxrb/compiler/adapter.rb +96 -0
  75. data/lib/mxrb/compiler/artifact_document_compiler.rb +102 -0
  76. data/lib/mxrb/compiler/artifact_materializer.rb +53 -0
  77. data/lib/mxrb/compiler/client_model_materializer.rb +42 -0
  78. data/lib/mxrb/compiler/code_action_document_compiler.rb +64 -0
  79. data/lib/mxrb/compiler/code_action_materializer.rb +35 -0
  80. data/lib/mxrb/compiler/code_action_type_compiler.rb +32 -0
  81. data/lib/mxrb/compiler/combo_box_bundle_compiler.rb +314 -0
  82. data/lib/mxrb/compiler/compatibility_analyzer.rb +169 -0
  83. data/lib/mxrb/compiler/constants_materializer.rb +111 -0
  84. data/lib/mxrb/compiler/data_grid_bundle_compiler.rb +290 -0
  85. data/lib/mxrb/compiler/database_connector_action_compiler.rb +280 -0
  86. data/lib/mxrb/compiler/deployment_asset_copier.rb +60 -0
  87. data/lib/mxrb/compiler/deployment_bootstrapper.rb +208 -0
  88. data/lib/mxrb/compiler/deployment_materializer.rb +43 -0
  89. data/lib/mxrb/compiler/deployment_metadata.rb +64 -0
  90. data/lib/mxrb/compiler/domain_document_compiler.rb +153 -0
  91. data/lib/mxrb/compiler/domain_model_materializer.rb +35 -0
  92. data/lib/mxrb/compiler/domain_security_compiler.rb +82 -0
  93. data/lib/mxrb/compiler/gallery_bundle_compiler.rb +190 -0
  94. data/lib/mxrb/compiler/generic_widget_bundle_compiler.rb +281 -0
  95. data/lib/mxrb/compiler/image_bundle_compiler.rb +216 -0
  96. data/lib/mxrb/compiler/java_proxy_generator.rb +509 -0
  97. data/lib/mxrb/compiler/legacy_data_grid_compiler.rb +267 -0
  98. data/lib/mxrb/compiler/legacy_page_builder.rb +287 -0
  99. data/lib/mxrb/compiler/mda.rb +99 -0
  100. data/lib/mxrb/compiler/microflow_document_compiler.rb +85 -0
  101. data/lib/mxrb/compiler/microflow_materializer.rb +48 -0
  102. data/lib/mxrb/compiler/microflow_node_compiler.rb +250 -0
  103. data/lib/mxrb/compiler/model_package.rb +116 -0
  104. data/lib/mxrb/compiler/model_values.rb +67 -0
  105. data/lib/mxrb/compiler/nanoflow_program_compiler.rb +483 -0
  106. data/lib/mxrb/compiler/navigation_document_compiler.rb +93 -0
  107. data/lib/mxrb/compiler/packager.rb +100 -0
  108. data/lib/mxrb/compiler/page_bundle_builder.rb +56 -0
  109. data/lib/mxrb/compiler/page_bundle_compiler.rb +2004 -0
  110. data/lib/mxrb/compiler/page_document_compiler.rb +77 -0
  111. data/lib/mxrb/compiler/portable_packager.rb +356 -0
  112. data/lib/mxrb/compiler/project_jar_archive.rb +84 -0
  113. data/lib/mxrb/compiler/project_jar_builder.rb +121 -0
  114. data/lib/mxrb/compiler/project_materializer.rb +139 -0
  115. data/lib/mxrb/compiler/project_model_orderer.rb +52 -0
  116. data/lib/mxrb/compiler/runtime_data_types.rb +31 -0
  117. data/lib/mxrb/compiler/runtime_model_schema.rb +90 -0
  118. data/lib/mxrb/compiler/schemas/runtime-10.24.0.73019.json +1052 -0
  119. data/lib/mxrb/compiler/schemas/runtime-11.json +1215 -0
  120. data/lib/mxrb/compiler/schemas/runtime-6.10.8.json +1148 -0
  121. data/lib/mxrb/compiler/schemas/runtime-7.17.0.json +1144 -0
  122. data/lib/mxrb/compiler/schemas/runtime-7.5.0.json +1215 -0
  123. data/lib/mxrb/compiler/schemas/runtime-9.6.1.29396.json +868 -0
  124. data/lib/mxrb/compiler/schemas/system-model-10.24.0.73019.b64 +1135 -0
  125. data/lib/mxrb/compiler/schemas/system-model-11.12.1.b64 +815 -0
  126. data/lib/mxrb/compiler/schemas/system-model-6.10.8.b64 +497 -0
  127. data/lib/mxrb/compiler/schemas/system-model-7.17.0.b64 +519 -0
  128. data/lib/mxrb/compiler/schemas/system-model-7.5.0.b64 +504 -0
  129. data/lib/mxrb/compiler/schemas/system-model-9.6.1.29396.b64 +816 -0
  130. data/lib/mxrb/compiler/security_materializer.rb +104 -0
  131. data/lib/mxrb/compiler/settings_document_compiler.rb +45 -0
  132. data/lib/mxrb/compiler/settings_materializer.rb +25 -0
  133. data/lib/mxrb/compiler/source_model.rb +128 -0
  134. data/lib/mxrb/compiler/system_model_seed.rb +88 -0
  135. data/lib/mxrb/compiler/system_queue_materializer.rb +54 -0
  136. data/lib/mxrb/compiler/system_text_materializer.rb +49 -0
  137. data/lib/mxrb/compiler/translation_materializer.rb +95 -0
  138. data/lib/mxrb/compiler/web_bundle_builder.rb +155 -0
  139. data/lib/mxrb/compiler/web_list_data_source.rb +139 -0
  140. data/lib/mxrb/compiler/web_operation_compiler.rb +614 -0
  141. data/lib/mxrb/compiler/web_shell_materializer.rb +194 -0
  142. data/lib/mxrb/compiler/widget_package_extractor.rb +63 -0
  143. data/lib/mxrb/doctor.rb +116 -0
  144. data/lib/mxrb/dsl/builder.rb +1636 -0
  145. data/lib/mxrb/errors.rb +18 -0
  146. data/lib/mxrb/evaluation.rb +131 -0
  147. data/lib/mxrb/exporter.rb +1716 -0
  148. data/lib/mxrb/frontend/migrator.rb +775 -0
  149. data/lib/mxrb/functional.rb +307 -0
  150. data/lib/mxrb/github/annotator.rb +161 -0
  151. data/lib/mxrb/initializer.rb +257 -0
  152. data/lib/mxrb/integrity/validator.rb +136 -0
  153. data/lib/mxrb/io/bson_codec.rb +145 -0
  154. data/lib/mxrb/io/mpr_file.rb +558 -0
  155. data/lib/mxrb/io/mxunit_codec.rb +42 -0
  156. data/lib/mxrb/marketplace.rb +380 -0
  157. data/lib/mxrb/model/association.rb +98 -0
  158. data/lib/mxrb/model/attribute.rb +100 -0
  159. data/lib/mxrb/model/connector.rb +17 -0
  160. data/lib/mxrb/model/design_materializer.rb +133 -0
  161. data/lib/mxrb/model/design_migration.rb +126 -0
  162. data/lib/mxrb/model/design_system.rb +111 -0
  163. data/lib/mxrb/model/domain_model.rb +51 -0
  164. data/lib/mxrb/model/entity.rb +180 -0
  165. data/lib/mxrb/model/menu.rb +38 -0
  166. data/lib/mxrb/model/microflow.rb +100 -0
  167. data/lib/mxrb/model/module.rb +142 -0
  168. data/lib/mxrb/model/navigation.rb +127 -0
  169. data/lib/mxrb/model/page.rb +410 -0
  170. data/lib/mxrb/model/project.rb +187 -0
  171. data/lib/mxrb/model/unit.rb +48 -0
  172. data/lib/mxrb/module_initializer.rb +75 -0
  173. data/lib/mxrb/official_marketplace/content_api.rb +292 -0
  174. data/lib/mxrb/official_marketplace/dependency_resolver.rb +329 -0
  175. data/lib/mxrb/official_marketplace/lifecycle.rb +367 -0
  176. data/lib/mxrb/official_marketplace/module_package_importer.rb +318 -0
  177. data/lib/mxrb/official_marketplace/widget_package_installer.rb +414 -0
  178. data/lib/mxrb/official_marketplace.rb +720 -0
  179. data/lib/mxrb/oql/analyzer.rb +155 -0
  180. data/lib/mxrb/oql/index_advisor.rb +85 -0
  181. data/lib/mxrb/oql/plan_analyzer.rb +185 -0
  182. data/lib/mxrb/oql/server.rb +132 -0
  183. data/lib/mxrb/oql/sql_server_plan_analyzer.rb +190 -0
  184. data/lib/mxrb/oql/sql_server_workload_analyzer.rb +80 -0
  185. data/lib/mxrb/oql/workload_analyzer.rb +175 -0
  186. data/lib/mxrb/oql/workload_baseline.rb +60 -0
  187. data/lib/mxrb/oql.rb +424 -0
  188. data/lib/mxrb/project_lifecycle.rb +76 -0
  189. data/lib/mxrb/protocols/plan.rb +86 -0
  190. data/lib/mxrb/protocols.rb +123 -0
  191. data/lib/mxrb/runtime/database_workspace.rb +677 -0
  192. data/lib/mxrb/runtime/docker_executor.rb +41 -0
  193. data/lib/mxrb/runtime/docker_workspace.rb +29 -0
  194. data/lib/mxrb/runtime/executor.rb +169 -0
  195. data/lib/mxrb/runtime/java_locator.rb +26 -0
  196. data/lib/mxrb/runtime/native.rb +474 -0
  197. data/lib/mxrb/runtime/sql_server_database.rb +146 -0
  198. data/lib/mxrb/runtime/toolchain.rb +82 -0
  199. data/lib/mxrb/scaffold/cli.rb +113 -0
  200. data/lib/mxrb/scaffold/generator.rb +246 -0
  201. data/lib/mxrb/scaffold/help.rb +80 -0
  202. data/lib/mxrb/scaffold/page_templates.rb +54 -0
  203. data/lib/mxrb/scaffold/recipes.rb +198 -0
  204. data/lib/mxrb/scaffold/registry.rb +82 -0
  205. data/lib/mxrb/scaffold/templates.rb +723 -0
  206. data/lib/mxrb/scaffold/transaction.rb +84 -0
  207. data/lib/mxrb/schema/tables.rb +55 -0
  208. data/lib/mxrb/semantic/analyzer.rb +473 -0
  209. data/lib/mxrb/semantic/batch_plan.rb +68 -0
  210. data/lib/mxrb/semantic/domain_mutator.rb +419 -0
  211. data/lib/mxrb/semantic/embedder.rb +51 -0
  212. data/lib/mxrb/semantic/extractor.rb +290 -0
  213. data/lib/mxrb/semantic/index.rb +623 -0
  214. data/lib/mxrb/semantic/inliner.rb +216 -0
  215. data/lib/mxrb/semantic/mover.rb +153 -0
  216. data/lib/mxrb/semantic/onnx_embedder.rb +34 -0
  217. data/lib/mxrb/semantic/remover.rb +70 -0
  218. data/lib/mxrb/semantic/renamer.rb +211 -0
  219. data/lib/mxrb/semantic/tfidf_embedder.rb +46 -0
  220. data/lib/mxrb/semantic/vec_store.rb +75 -0
  221. data/lib/mxrb/team_server.rb +390 -0
  222. data/lib/mxrb/templates/project/10.24.0.73019.json +32 -0
  223. data/lib/mxrb/templates/project/11.12.1.json +32 -0
  224. data/lib/mxrb/templates/project/6.10.8.json +50 -0
  225. data/lib/mxrb/templates/project/7.17.0.json +50 -0
  226. data/lib/mxrb/templates/project/7.5.0.json +50 -0
  227. data/lib/mxrb/templates/project/9.6.1.29396.json +50 -0
  228. data/lib/mxrb/version.rb +5 -0
  229. data/lib/mxrb/widget_package.rb +338 -0
  230. data/lib/mxrb/widget_synchronizer.rb +31 -0
  231. data/lib/mxrb/writer.rb +3775 -0
  232. data/lib/mxrb.rb +188 -0
  233. data/marketplace/catalog.json +10 -0
  234. data/marketplace/modules/shared-kernel/domain/README.md +4 -0
  235. data/marketplace/modules/shared-kernel/module.rb +5 -0
  236. data/marketplace/modules/shared-kernel/mxrb-module.json +9 -0
  237. metadata +447 -0
@@ -0,0 +1,655 @@
1
+ # Writing projects
2
+
3
+ [Português](../pt-BR/writing.md) · **English** · [Deutsch](../de-DE/writing.md)
4
+
5
+ For the complete module, layer and round-trip structure, see
6
+ [project architecture](architecture.md).
7
+
8
+ `mxrb generate` evaluates a Ruby definition and creates or updates the target
9
+ MPR. Existing modules, entities, attributes, associations, pages and
10
+ microflows are matched by name, so applying the same definition repeatedly
11
+ does not duplicate them.
12
+
13
+ Start from an empty directory with:
14
+
15
+ ```sh
16
+ mxrb init vet_clinic
17
+ cd vet_clinic
18
+ bundle install
19
+ bundle exec mxrb generate project.rb
20
+ bundle exec mxrb validate VetClinic.mpr
21
+ ```
22
+
23
+ `init` accepts snake_case or PascalCase and creates `Gemfile`, `project.rb`,
24
+ and the main `modules/VetClinic` module. The scaffold contains application code
25
+ only: `System` is implicit in the Runtime, while Administration and Atlas are
26
+ marketplace modules. The command aborts without changing an existing directory.
27
+
28
+ Add another application module from the project root with:
29
+
30
+ ```sh
31
+ mxrb module new appointments
32
+ ```
33
+
34
+ The command creates `modules/Appointments`, reuses the same domain/application
35
+ scaffold, and connects its `module.rb` in `project.rb`. It aborts atomically if
36
+ the module already exists or the project file cannot be updated. Use
37
+ `--target DIR` when running outside the project root.
38
+
39
+ Artifact, presentation, infrastructure, test, design, and CI generators are
40
+ listed in the [scaffold catalog](scaffolds.md). See the complete
41
+ [entity DSL reference](entity-dsl.md) for entity files.
42
+
43
+ ```ruby
44
+ # shop.rb
45
+ Mxrb.define("Shop.mpr") do
46
+ mendix_version "10.17.0"
47
+
48
+ self.module :Sales do
49
+ entity :Customer do
50
+ string :Name, documentation: "Customer display name"
51
+ end
52
+
53
+ entity :Order do
54
+ decimal :Total, default: 0
55
+ association "Sales.Customer", name: "Order_Customer"
56
+ end
57
+
58
+ page :OrderList do
59
+ title "Orders"
60
+ layout "Atlas_Default"
61
+ allowed_roles "Sales.User"
62
+ end
63
+
64
+ microflow :CreateOrder do
65
+ parameter :Order, type: :Order
66
+ return_type :Order
67
+ allowed_roles "Sales.User"
68
+ end
69
+ end
70
+ end
71
+ ```
72
+
73
+ Apply it using the path in the definition:
74
+
75
+ ```sh
76
+ bundle exec mxrb generate shop.rb
77
+ ```
78
+
79
+ Or override the output path:
80
+
81
+ ```sh
82
+ bundle exec mxrb generate shop.rb output/Shop.mpr
83
+ ```
84
+
85
+ ## Integrity validation
86
+
87
+ Run the internal integrity check after generation or round-trip work:
88
+
89
+ ```sh
90
+ bundle exec mxrb validate path/to/App.mpr
91
+ ```
92
+
93
+ For MPR v1, the validator reads unit contents directly from the SQLite
94
+ `Unit.Contents` column and checks the unit tree, content hashes, and
95
+ `$ID`/`$Type` identity. For MPR v2, it performs the same checks against the
96
+ external `.mxunit` payloads in `mprcontents/`.
97
+
98
+ Compare two MPRs structurally without external tooling:
99
+
100
+ ```sh
101
+ bundle exec mxrb compare original.mpr rebuilt.mpr
102
+ ```
103
+
104
+ The comparator reports differences in project metadata, security roles, unit
105
+ tree, modules, entities (including native attribute metadata and access rules),
106
+ associations, pages/widgets/events, menus, microflows, nanoflows and allowed
107
+ module roles. Microflow and nanoflow bodies are normalized before comparison:
108
+ volatile UUIDs and canvas coordinates are ignored, while objects, actions,
109
+ properties and control-flow edges remain part of the snapshot.
110
+
111
+ For external Mendix validation on Linux, use the `mx` and `mxbuild` binaries
112
+ matching the exact model version:
113
+
114
+ ```sh
115
+ mx check App.mpr --warnings --deprecations --best-practice --json check.json
116
+ mxbuild \
117
+ --java-home=/path/to/jdk-21 \
118
+ --java-exe-path=/path/to/jdk-21/bin/java \
119
+ --target=package \
120
+ --output=App.mda \
121
+ --write-errors=mxbuild-errors.json \
122
+ App.mpr
123
+ ```
124
+
125
+ Compare the diagnostic JSON with the original project, not merely the exit
126
+ code: `mx check` combines warnings, deprecations and recommendations into a
127
+ nonzero status even when there are zero errors.
128
+
129
+ ## Ruby model evaluations
130
+
131
+ Model expectations live in ordinary Ruby files:
132
+
133
+ ```ruby
134
+ # evaluation.rb
135
+ artifact "Sales.Order", kind: :entity
136
+ reference from: "Sales.Order_Overview", to: "Sales.Order"
137
+ no_call_cycles
138
+ no_missing_internal_references
139
+ maximum_unreferenced 20, severity: :warning
140
+ forbid_dependency from: :Domain, to: :Presentation
141
+
142
+ check "orders expose a status attribute" do |project|
143
+ project.find_artifact("Sales.Order.Status", kind: :attribute) != nil
144
+ end
145
+ ```
146
+
147
+ Run them with:
148
+
149
+ ```sh
150
+ bundle exec mxrb evaluate path/to/App.mpr evaluation.rb
151
+ ```
152
+
153
+ Error checks produce a failing exit status; warning checks affect the score but
154
+ do not fail the command. See `examples/sudoku_evaluation.rb` for an executable
155
+ example validated against the public Sudoku fixture.
156
+
157
+ ## Functional microflow tests
158
+
159
+ Runtime tests are ordinary Ruby files. The first functional slice verifies that
160
+ each selected microflow completes without an unhandled runtime exception:
161
+
162
+ ```ruby
163
+ # functional_test.rb
164
+ microflow "creates an order",
165
+ call: "Sales.ACT_CreateOrder",
166
+ before: { call: "Sales.TEST_Prepare" },
167
+ after: { call: "Sales.TEST_Cleanup" },
168
+ expect: {
169
+ return: "true",
170
+ count: { entity: "Sales.Order", xpath: "[Status = 'Open']", equals: 1 }
171
+ }
172
+ ```
173
+
174
+ The `pass:` values are Mendix expressions and must supply every parameter of
175
+ the target microflow. MXRB validates the names before compilation. No JUnit,
176
+ Java test module or MDL is involved: MXRB generates a temporary `MxrbTests`
177
+ module, executes it as the after-startup microflow and parses its structured
178
+ runtime log back into immutable Ruby results.
179
+
180
+ Run locally with the exact Mendix toolchain and Java selected by the project:
181
+
182
+ ```sh
183
+ JAVA_HOME=/path/to/zulu-21 \
184
+ bundle exec mxrb test App.mpr functional_test.rb
185
+ ```
186
+
187
+ Or keep JDK, MxBuild and runtime execution inside containers:
188
+
189
+ ```sh
190
+ bundle exec mxrb test App.mpr functional_test.rb --docker
191
+ ```
192
+
193
+ For the Ruby model Runtime, with no Java, `mx`, or `mxbuild`, use:
194
+
195
+ ```sh
196
+ bundle exec mxrb test App.mpr functional_test.rb --native
197
+ ```
198
+
199
+ Native mode currently interprets the core data path (create/change/retrieve,
200
+ commit/delete, variables, decisions, microflow calls, aggregates and logging)
201
+ in a transactional in-memory store. Unsupported Java, REST, UI and connector
202
+ activities fail explicitly and roll back the test case.
203
+
204
+ Docker mode builds one lightweight builder image per Java family and reuses it
205
+ for compatible Mendix versions. The exact Mendix toolchain is mounted
206
+ read-only because it is version-specific and licensed separately. The source
207
+ project is never changed: instrumentation, portable package, HSQLDB and
208
+ uploaded-file storage live in a temporary copy that is deleted after the run.
209
+
210
+ Inspect version selection and the planned container mounts without executing:
211
+
212
+ ```sh
213
+ bundle exec mxrb test App.mpr functional_test.rb --plan
214
+ ```
215
+
216
+ The Java executor now builds the deployment, `project.jar`, web bundles, and
217
+ portable Runtime package through MXRB's native compiler; it does not invoke
218
+ `mx` or `mxbuild`. Both execution modes stop at `[MXRB_TEST] DONE`, terminate
219
+ the Runtime, and return a failing exit status if any case failed, compilation
220
+ failed, the suite did not finish, or its aggregate timeout expired.
221
+ Use `--json result.json` and/or `--junit result.xml` for CI reports. JUnit is
222
+ only the XML interchange format here; MXRB writes it directly in Ruby and does
223
+ not install or execute the Java JUnit framework.
224
+
225
+ ## Test coverage
226
+
227
+ The default suite runs with `bundle exec rspec`. The strict coverage gate
228
+ uses Ruby's native `Coverage` API:
229
+
230
+ ```sh
231
+ MXRB_COVERAGE=1 MXRB_LINE_COVERAGE_MIN=100 MXRB_BRANCH_COVERAGE_MIN=100 bundle exec rspec
232
+ ```
233
+
234
+ It writes `coverage/coverage.json`; CI requires 100% lines and 100% branches,
235
+ while the helper defaults to 100/100 if no thresholds are supplied.
236
+ `bundle exec ruby script/branch_report.rb` lists an uncovered branch by source
237
+ file and line. `bundle exec rubocop` is the gradual static-quality gate.
238
+
239
+ ## Ruby module marketplace
240
+
241
+ ```sh
242
+ mxrb module search
243
+ mxrb module search security
244
+ mxrb module add shared-kernel
245
+ mxrb module add ./local-package --target ./exported-project
246
+ ```
247
+
248
+ Catalogs are JSON files loaded from the gem, a local path or HTTPS through
249
+ `--registry`. Packages contain `mxrb-module.json`; sources may be built in,
250
+ local directories or Git repositories. Installation uses a staging directory,
251
+ rejects unsafe paths and writes `.mxrb/modules.lock.json` with version, source,
252
+ ref and a SHA-256 digest of installed files.
253
+
254
+ ## Native baseline and editable deep structures
255
+
256
+ `mxrb export` writes `.mxrb/native_units.json` with the original BSON payloads
257
+ as a lossless baseline and `.mxrb/native_units.rb` with every payload expanded
258
+ as editable Ruby. The generated project loads both:
259
+ `project.rb` loads it with:
260
+
261
+ ```ruby
262
+ native_units File.join(__dir__, ".mxrb", "native_units.json")
263
+ evaluate File.join(__dir__, ".mxrb", "native_units.rb")
264
+ ```
265
+
266
+ Each Ruby entry uses `native_unit` and `deep_structure` to expose all BSON
267
+ fields, including binary values through `bson_binary`. Editing this Ruby hash
268
+ overrides the baseline before typed writers run. Images, constants, datasets,
269
+ services, project settings, templates and newly introduced Mendix unit types
270
+ therefore remain both lossless and directly editable even without a concise
271
+ typed abstraction.
272
+ Microflow/nanoflow bodies and page/widget trees have an additional editable
273
+ representation described below.
274
+
275
+ Every flow body in the current public matrix is exported as typed Ruby. The
276
+ exporter records a canonical `body_fingerprint`: if the body is unchanged,
277
+ MXRB reuses the exact native graph; if the Ruby body changes, the fingerprint
278
+ no longer matches and the writer regenerates that graph. The fingerprint line
279
+ is generated bookkeeping and normally should not be edited by hand.
280
+
281
+ Editable flow activities currently include:
282
+
283
+ ```ruby
284
+ create_object "Sales.Order", as: :order
285
+ change_object :order, set: { Status: "'Open'" }
286
+ retrieve_objects "Sales.Order", as: :orders, xpath: "[Active = true]", limit: 100
287
+ commit :order, with_events: false
288
+ delete :order
289
+ call_microflow "Sales.Process", as: :result, pass: { Order: :order }
290
+ create_variable :message, type: :string, value: "'Created'"
291
+ change_variable :message, to: "'Updated'"
292
+ show_message "Done", type: :information, blocking: true
293
+ log_message "Completed", level: :info, node: "'MXRB'"
294
+ decision "$order/Total > 100" do
295
+ on(true) { call_microflow "Sales.ApplyDiscount" }
296
+ end
297
+ loop_over :orders, as: :order do
298
+ commit :order
299
+ end
300
+ rescue_all { log_message "Failed", level: :error }
301
+ return_value :result
302
+ ```
303
+
304
+ The DSL also covers database/association retrieval and sorting, Java,
305
+ JavaScript, nanoflow and app-service calls, show/close page, REST calls,
306
+ aggregates, casts, rollback, list operations, validation feedback, boolean and
307
+ multi-value decisions, inheritance/type decisions, iterators, while loops,
308
+ error/continue events, annotations and nested flows.
309
+
310
+ For MPR v2 exports, the manifest records the source format and `mxrb generate`
311
+ creates `mprcontents/*.mxunit` automatically for the rebuilt project.
312
+
313
+ ## Page widgets
314
+
315
+ New pages and pages composed only of core controls use concise methods:
316
+ `text_box`, `number_input`, `text_area`, `check_box`, `date_picker`,
317
+ `reference_selector`, `drop_down`, `button`, `text`, `container`, `snippet`,
318
+ `tab_control`/`tab_page`, and `data_grid`/`column`. Tab pages may contain the
319
+ same nested widgets as containers. Inputs, actions and containers are written
320
+ using the Mendix 11 modern Forms model. `data_grid` emits Data Grid 2, while
321
+ `drop_down` and `reference_selector` emit Combo Box widgets.
322
+
323
+ Pluggable widgets need their `.mpk` packages in the project's `widgets/`
324
+ directory. Synchronize their version-specific schemas and apply the Ruby
325
+ properties in one command:
326
+
327
+ ```bash
328
+ bundle exec mxrb widgets sync project.rb MyApp.mpr
329
+ ```
330
+
331
+ Use `pluggable_widget` for another MPK by widget id and property map. Imported
332
+ widgets that MXRB does not recognize are emitted as `native_widget` with an
333
+ editable `deep_structure`, so export/generate preserves every native property.
334
+
335
+ Every imported page also exports its complete page internals as a structured
336
+ Ruby hash:
337
+
338
+ ```ruby
339
+ page :Dashboard do
340
+ title "Dashboard"
341
+ deep_structure({
342
+ "FormCall" => {
343
+ "$Type" => "Forms$LayoutCall",
344
+ "Arguments" => [
345
+ 2,
346
+ {
347
+ "$Type" => "Forms$FormCallArgument",
348
+ "Widgets" => [
349
+ 3,
350
+ {
351
+ "$Type" => "CustomWidgets$CustomWidget",
352
+ "Name" => "Map",
353
+ "Object" => { "Zoom" => 12 }
354
+ }
355
+ ]
356
+ }
357
+ ]
358
+ }
359
+ })
360
+ end
361
+ ```
362
+
363
+ The concise declarations remain an architectural/readability view; when
364
+ `deep_structure` is present, edit that hash for storage-level page changes.
365
+ It is intentionally verbose but not opaque: every property can be inspected
366
+ and changed as Ruby data. BSON binary values appear as
367
+ `bson_binary("...", subtype: :generic)`. The deep structure is authoritative
368
+ when present, so edits are written instead of being overwritten by the native
369
+ baseline.
370
+
371
+ Imported menu documents follow the same rule: concise `item` declarations are
372
+ emitted for readability and dependency analysis, while their complete native
373
+ caption/action/translation structure remains editable and authoritative.
374
+
375
+ Buttons can call microflows/nanoflows or native page actions:
376
+
377
+ ```ruby
378
+ button :saveButton, caption: "Save" do
379
+ on_click action: :save_changes
380
+ end
381
+ ```
382
+
383
+ Supported native actions are `:save_changes`, `:cancel_changes`, `:delete`,
384
+ and `:close_page`.
385
+
386
+ ## Navigation and security
387
+
388
+ Menu documents are exported as module-level presentation navigation:
389
+
390
+ ```ruby
391
+ menu :Submenu do
392
+ item "Accounts", page: "Administration.Account_Overview"
393
+ end
394
+ ```
395
+
396
+ Project security user roles are exported at `app/security/security.rb`:
397
+
398
+ ```ruby
399
+ security do
400
+ security_level "CheckEverything"
401
+ user_role :Administrator, module_roles: ["System.Administrator"], admin: true
402
+ end
403
+ ```
404
+
405
+ Module security roles are exported per module at `modules/<Module>/security/security.rb`:
406
+
407
+ ```ruby
408
+ module_role :User
409
+ module_role :Administrator, description: "Full module access"
410
+ ```
411
+
412
+ Page, microflow and nanoflow access can be edited with `allowed_roles`, using
413
+ qualified module role names:
414
+
415
+ ```ruby
416
+ page :Account_Overview do
417
+ allowed_roles "Administration.Administrator"
418
+ end
419
+
420
+ microflow :ChangeMyPassword do
421
+ allowed_roles "Administration.Administrator", "Administration.User"
422
+ allow_concurrent_execution false
423
+ mark_as_used true
424
+ excluded false
425
+ end
426
+ ```
427
+
428
+ `allow_concurrent_execution`, `mark_as_used` and `excluded` are exported
429
+ explicitly for every imported microflow/nanoflow. They are editable booleans,
430
+ so reference/example flows that are intentionally excluded are not silently
431
+ reactivated during regeneration.
432
+
433
+ Entity access rules support `create`, `delete`, `read`, `write` and `xpath`.
434
+ Rules that cannot be represented completely—particularly legacy rules without
435
+ resolvable role names—remain native as a complete collection rather than being
436
+ partially exported.
437
+
438
+ Attribute round-trip preserves version-specific key casing and native details
439
+ that are not yet first-class DSL options, including string length, enumeration
440
+ references, date localization and calculated-value definitions. `float` and
441
+ `binary` are accepted attribute types in addition to the existing types.
442
+
443
+ ## MPR v2
444
+
445
+ When an `mprcontents/` directory exists beside the MPR, unit contents are read
446
+ and written at:
447
+
448
+ ```text
449
+ mprcontents/aa/bb/aabbccdd-....mxunit
450
+ ```
451
+
452
+ Writes use a temporary file followed by an atomic rename, while SQLite keeps
453
+ `Contents` null and stores the content hash. The current codec accepts BSON
454
+ unit payloads. Mendix `.mxunit` encodings that are not BSON are rejected
455
+ explicitly; they are never silently replaced.
456
+
457
+ External tools such as `mxcli`
458
+ can still be useful as a manual comparison oracle when researching Studio Pro
459
+ behavior, but they are not part of the mxrb runtime or regression workflow.
460
+
461
+ See the [validation matrix](validation-matrix.md) for the public-project
462
+ round-trip matrix and the exact confidence boundary of the current engine.
463
+ # Semantic analysis in Ruby
464
+
465
+ MXRB does not require a separate query language. An opened MPR exposes its
466
+ semantic index directly as Ruby objects:
467
+
468
+ ```ruby
469
+ Mxrb.open("app.mpr") do |project|
470
+ project.references_to("Sales.Order").each do |reference|
471
+ puts "#{reference.source.qualified_name} (#{reference.relation})"
472
+ end
473
+
474
+ project.callers_of("Sales.Recalculate").each do |caller|
475
+ puts caller.qualified_name
476
+ end
477
+
478
+ project.callees_of("Sales.Checkout").each do |callee|
479
+ puts callee.qualified_name
480
+ end
481
+
482
+ project.impact_of("Sales.Order").artifacts.each do |affected|
483
+ puts affected.qualified_name
484
+ end
485
+ end
486
+ ```
487
+
488
+ The same operations have convenience commands: `mxrb refs`, `mxrb callers`,
489
+ `mxrb callees` and `mxrb impact`. The Ruby API is the source of truth.
490
+
491
+ When a project is opened with `readonly: false`, the first semantic-index build
492
+ stores a compact cache in the MPR. Later opens reuse it while unit contents and
493
+ containment remain unchanged. Semantic mutations invalidate the in-memory index,
494
+ and the persisted fingerprint prevents stale results after edits or moves.
495
+ Read-only projects can consume an existing cache but never create one.
496
+
497
+ ## Deep rename
498
+
499
+ Writing requires an explicitly writable project and can be reviewed before
500
+ touching the MPR:
501
+
502
+ ```ruby
503
+ Mxrb.open("app.mpr", readonly: false) do |project|
504
+ plan = project.plan_rename("Sales.Order", to: "Invoice")
505
+
506
+ plan.changes.each do |change|
507
+ puts "#{change.path.join(".")}: #{change.before} -> #{change.after}"
508
+ end
509
+
510
+ plan.apply!
511
+ end
512
+ ```
513
+
514
+ The plan updates the declaration and deep references, including Mendix member
515
+ paths such as `Sales.Order/Number`. The project index is rebuilt automatically
516
+ after applying it.
517
+
518
+ The equivalent CLI command only shows a preview:
519
+
520
+ ```sh
521
+ bundle exec mxrb rename app.mpr Sales.Order Invoice
522
+ ```
523
+
524
+ To write:
525
+
526
+ ```sh
527
+ bundle exec mxrb rename app.mpr Sales.Order Invoice --apply
528
+ ```
529
+
530
+ ## Safe removal
531
+
532
+ Removal is also previewed before writing:
533
+
534
+ ```ruby
535
+ Mxrb.open("app.mpr", readonly: false) do |project|
536
+ plan = project.plan_remove("Sales.UnusedFlow")
537
+ plan.apply! if plan.safe?
538
+ end
539
+ ```
540
+
541
+ `mxrb remove app.mpr Sales.UnusedFlow` reports incoming references and child
542
+ units. Adding `--apply` writes only when both collections are empty. Embedded
543
+ entities, attributes and associations require a typed domain-model mutation.
544
+
545
+ ## Safe move
546
+
547
+ Move a standalone unit between folders in its current module:
548
+
549
+ ```ruby
550
+ plan = project.plan_move("Sales.Process", to: "Sales.Automation")
551
+ plan.apply!
552
+ ```
553
+
554
+ The CLI equivalent is
555
+ `mxrb move app.mpr Sales.Process Sales.Automation [--apply]`. Folder cycles,
556
+ cross-module moves and non-container targets are rejected before writing.
557
+
558
+ ## Lint and coupling
559
+
560
+ The semantic report is a Ruby object:
561
+
562
+ ```ruby
563
+ report = Mxrb.open("app.mpr", &:analyze)
564
+
565
+ report.diagnostics.each do |diagnostic|
566
+ puts "#{diagnostic.severity}: #{diagnostic.message}"
567
+ end
568
+
569
+ report.module_dependencies.each do |dependency|
570
+ puts "#{dependency.from} -> #{dependency.to}: #{dependency.references.size}"
571
+ end
572
+ ```
573
+
574
+ Project-specific rules are Ruby as well:
575
+
576
+ ```ruby
577
+ public_name_rule = lambda do |_project, index|
578
+ index.artifacts.filter_map do |artifact|
579
+ next unless artifact.kind == :microflow
580
+ next if artifact.name.match?(/\A[A-Z]/)
581
+
582
+ Mxrb::Semantic::Diagnostic.new(
583
+ :public_name,
584
+ :warning,
585
+ "microflow must start with uppercase: #{artifact.qualified_name}",
586
+ [artifact],
587
+ {}
588
+ )
589
+ end
590
+ end
591
+
592
+ Mxrb.open("app.mpr") do |project|
593
+ report = project.analyze(rules: [public_name_rule])
594
+ end
595
+ ```
596
+
597
+ In the CLI, `mxrb lint app.mpr` shows diagnostics and
598
+ `mxrb report app.mpr` summarizes references and coupling between modules.
599
+ Built-in lint rules also cover persistent entities without access rules,
600
+ secured pages/flows without roles, undocumented public contracts, missing
601
+ navigation targets and duplicate module-role mappings. Custom Ruby rules are
602
+ appended to these checks.
603
+
604
+ The semantic index is fingerprinted and can be inspected or maintained without
605
+ guessing its state:
606
+
607
+ ```sh
608
+ mxrb cache status app.mpr
609
+ mxrb cache warm app.mpr --json
610
+ mxrb cache clear app.mpr
611
+ ```
612
+
613
+ ## Semantic diff for Git
614
+
615
+ `Mxrb.diff` returns typed changes without exposing unstable UUIDs and visual
616
+ coordinates:
617
+
618
+ ```ruby
619
+ result = Mxrb.diff("main.mpr", "feature.mpr")
620
+
621
+ result.changes.each do |change|
622
+ puts "#{change.operation} #{change.path.join(".")}"
623
+ end
624
+ ```
625
+
626
+ Each `Mxrb::Compare::Change` provides `operation`, `path`, `before` and `after`.
627
+ Convenience filters are available through `result.added`, `result.removed` and
628
+ `result.changed`.
629
+
630
+ ```sh
631
+ bundle exec mxrb diff main.mpr feature.mpr
632
+ ```
633
+
634
+ The command exits with status zero when the snapshots are semantically
635
+ identical and status one when differences exist.
636
+
637
+ ## Structural navigation
638
+
639
+ ```ruby
640
+ Mxrb.open("app.mpr") do |project|
641
+ matches = project.search_artifacts("order", kind: :microflow)
642
+ details = project.describe_artifact("Sales.CreateOrder")
643
+
644
+ details.incoming.each { puts "from #{_1.source.qualified_name}" }
645
+ details.outgoing.each { puts "to #{_1.target.qualified_name}" }
646
+ end
647
+ ```
648
+
649
+ In the CLI:
650
+
651
+ ```sh
652
+ bundle exec mxrb find app.mpr order
653
+ bundle exec mxrb describe app.mpr Sales.CreateOrder
654
+ bundle exec mxrb tree app.mpr Sales
655
+ ```
@@ -0,0 +1,24 @@
1
+ # Documentação do MXRB
2
+
3
+ **Português** · [English](../en-US/README.md) · [Deutsch](../de-DE/README.md)
4
+
5
+ - [Arquitetura de projetos](architecture.md)
6
+ - [Padrão arquitetural](architectural-standard.md)
7
+ - [Estrutura do projeto exportado](project-structure.md)
8
+ - [Padrões arquiteturais](architectural-patterns.md)
9
+ - [Refatoração semântica](semantic-refactoring.md)
10
+ - [Navegação e design system](design-system.md)
11
+ - [OQL, visão SQL e banco local](oql-sql.md)
12
+ - [Convenções](conventions.md)
13
+ - [Roadmap Ruby-first](ruby-first-roadmap.md)
14
+ - [Matriz de validação](validation-matrix.md)
15
+ - [Compilador nativo e Runtime](compiler.md)
16
+ - [Relatório de qualidade do build e Runtime](native-runtime-quality-report.md)
17
+ - [Criação e edição de projetos](writing.md)
18
+ - [Scaffolds de projeto](scaffolds.md)
19
+ - [DSL de entidades](entity-dsl.md)
20
+ - [Operação, lifecycle e Marketplace](platform-operations.md)
21
+ - [Avaliação de integração das APIs Mendix](platform-api-integration.md)
22
+ - [Aceitação end-to-end do VetClinic](vetclinic-acceptance.md)
23
+
24
+ [Voltar ao README do projeto](../../README.pt-BR.md)
@@ -0,0 +1,25 @@
1
+ # Padrões arquiteturais
2
+
3
+ **Português** · [English](../en-US/architectural-patterns.md) · [Deutsch](../de-DE/architectural-patterns.md)
4
+
5
+ O MXRB usa Ruby como única interface pública do modelo e organiza
6
+ responsabilidades em domínio, aplicação, apresentação e infraestrutura.
7
+
8
+ ```text
9
+ apresentação ─┐
10
+ ├─> aplicação ─> domínio
11
+ infraestrutura┘
12
+ ```
13
+
14
+ Entidades e regras guardam o estado de negócio. Microflows são casos de uso
15
+ quando coordenam esse estado. Páginas, navegação e nanoflows ficam em
16
+ apresentação; HTTP, banco externo, Java e integrações ficam em infraestrutura.
17
+
18
+ Repositórios são úteis em fronteiras externas reais, não como cerimônia ao
19
+ redor do CRUD Mendix comum. Chamadas e dependências permanecem visíveis no
20
+ grafo semântico e podem ser validadas contra o modelo real.
21
+
22
+ Security, navigation e design system são políticas transversais em `app/`.
23
+ A navegação declarada também é gravada no documento nativo Mendix.
24
+
25
+ [Voltar ao índice](README.md)