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,177 @@
1
+ # Criação e edição de projetos
2
+
3
+ **Português** · [English](../en-US/writing.md) · [Deutsch](../de-DE/writing.md)
4
+
5
+ `mxrb generate` avalia uma definição Ruby e cria ou atualiza o MPR. Nomes
6
+ Mendix são chaves estáveis, portanto reaplicar a definição não duplica units.
7
+
8
+ Para iniciar em uma pasta vazia:
9
+
10
+ ```sh
11
+ mxrb init vet_clinic
12
+ cd vet_clinic
13
+ bundle install
14
+ bundle exec mxrb generate project.rb
15
+ bundle exec mxrb validate VetClinic.mpr
16
+ ```
17
+
18
+ `init` aceita snake_case ou PascalCase, cria `Gemfile`, `project.rb` e o módulo
19
+ principal em `modules/VetClinic`. O scaffold inclui somente código próprio: o
20
+ módulo `System` é implícito no Runtime; Administration e Atlas são módulos de
21
+ marketplace. O comando aborta sem alterar nada quando o diretório já existe.
22
+
23
+ Para adicionar outro módulo de aplicação a partir da raiz do projeto:
24
+
25
+ ```sh
26
+ mxrb module new appointments
27
+ ```
28
+
29
+ O comando cria `modules/Appointments`, reutiliza o mesmo scaffold de
30
+ domain/application e conecta o `module.rb` no `project.rb`. A operação aborta
31
+ atomicamente se o módulo já existir ou se o arquivo de projeto não puder ser
32
+ atualizado. Use `--target DIR` ao executar fora da raiz do projeto.
33
+
34
+ Os scaffolds de artefatos, apresentação, infraestrutura, testes, design e CI
35
+ estão no [catálogo de scaffolds](scaffolds.md). Para entidades, consulte a
36
+ [referência completa da DSL](entity-dsl.md).
37
+
38
+ ```ruby
39
+ Mxrb.define("Shop.mpr") do
40
+ mendix_version "11.12.1"
41
+ self.module :Sales do
42
+ entity :Order do
43
+ string :Number, documentation: "Número estável do pedido"
44
+ decimal :Total, default: 0
45
+ end
46
+ end
47
+ end
48
+ ```
49
+
50
+ ```sh
51
+ bundle exec mxrb generate shop.rb
52
+ bundle exec mxrb validate Shop.mpr
53
+ bundle exec mxrb export Shop.mpr exported-shop
54
+ bundle exec mxrb compare original.mpr rebuilt.mpr
55
+ ```
56
+
57
+ ## Avaliações de modelo
58
+
59
+ ```ruby
60
+ artifact "Sales.Order", kind: :entity
61
+ no_call_cycles
62
+ no_missing_internal_references
63
+ check("Order possui Total") do |project|
64
+ project.find_artifact("Sales.Order.Total", kind: :attribute)
65
+ end
66
+ ```
67
+
68
+ Execute com `mxrb evaluate App.mpr evaluation.rb`.
69
+
70
+ ## Testes funcionais
71
+
72
+ ```ruby
73
+ microflow "cria pedido",
74
+ call: "Sales.ACT_CreateOrder",
75
+ before: { call: "Sales.TEST_Preparar" },
76
+ after: { call: "Sales.TEST_Limpar" },
77
+ expect: {
78
+ return: "true",
79
+ count: { entity: "Sales.Order", xpath: "[Status = 'Open']", equals: 1 }
80
+ }
81
+ ```
82
+
83
+ Use `mxrb test App.mpr functional_test.rb`; acrescente `--docker` para executar
84
+ JDK, MxBuild e Runtime em containers descartáveis. Use `--native` para executar
85
+ o grafo do microflow no Runtime de modelo em Ruby, sem Java, `mx` ou `mxbuild`.
86
+ O modo nativo cobre CRUD, variáveis, decisões, chamadas, agregações e logs em
87
+ uma store transacional; Java, REST, UI e conectores ainda falham explicitamente
88
+ e fazem rollback. Não há JUnit nem MDL. O MPR original nunca é alterado.
89
+ Use `--json resultado.json` e/ou `--junit resultado.xml` para relatórios de CI.
90
+ JUnit é apenas o formato XML de intercâmbio neste caso; o MXRB o grava
91
+ diretamente em Ruby, sem instalar ou executar o framework Java JUnit.
92
+
93
+ ## Cobertura
94
+
95
+ ```sh
96
+ bundle exec rspec
97
+ MXRB_COVERAGE=1 bundle exec rspec
98
+ ```
99
+
100
+ ## Marketplace de módulos Ruby
101
+
102
+ ```sh
103
+ mxrb module search
104
+ mxrb module search security
105
+ mxrb module add shared-kernel
106
+ mxrb module add ./pacote-local --target ./projeto-exportado
107
+ ```
108
+
109
+ Catálogos JSON podem vir da gem, de um caminho local ou de HTTPS com
110
+ `--registry`. Pacotes possuem `mxrb-module.json` e podem ser embutidos,
111
+ diretórios locais ou repositórios Git. A instalação usa staging, rejeita
112
+ caminhos inseguros e grava `.mxrb/modules.lock.json` com versão, origem, ref e
113
+ SHA-256 dos arquivos instalados.
114
+
115
+ ## Baseline nativo e estruturas profundas
116
+
117
+ `mxrb export` grava `.mxrb/native_units.json` como baseline sem perdas e
118
+ `.mxrb/native_units.rb` com cada payload BSON expandido em Hashes Ruby
119
+ editáveis. Entradas `native_unit` expõem todos os campos de imagens, constantes,
120
+ datasets, serviços, configurações, templates e tipos futuros; valores binários
121
+ usam `bson_binary`. Alterações nesse Ruby sobrepõem o baseline antes das escritas
122
+ tipadas. Corpos de flow possuem `body_fingerprint`: o grafo nativo é reutilizado
123
+ quando o Ruby não mudou e regenerado após uma edição.
124
+
125
+ A DSL cobre criação/alteração/retrieve/commit/delete, chamadas de microflow,
126
+ Java, JavaScript, nanoflow e app service, páginas, REST, listas, decisões,
127
+ loops, eventos de erro e rescue.
128
+
129
+ ## Páginas, navegação e segurança
130
+
131
+ Controles core possuem métodos concisos: `text`, `text_box`, `number_input`,
132
+ `text_area`, `check_box`, `date_picker`, `button`, `container`, `snippet` e
133
+ `tab_control` com widgets dentro de cada `tab_page`. Esses controles usam o
134
+ modelo Forms moderno do Mendix 11. `data_grid` gera Data Grid 2; `drop_down` e
135
+ `reference_selector` geram Combo Box.
136
+
137
+ Widgets pluggable precisam dos `.mpk` em `widgets/`. Depois de instalar os
138
+ pacotes, sincronize o schema específico da versão e aplique as propriedades
139
+ Ruby com:
140
+
141
+ ```bash
142
+ bundle exec mxrb widgets sync project.rb MeuApp.mpr
143
+ ```
144
+
145
+ Para outros MPKs existe `pluggable_widget`, com widget id e mapa de
146
+ propriedades. Widgets importados ainda desconhecidos são preservados como
147
+ `native_widget` e `deep_structure`, sem perder configuração no ciclo
148
+ export/generate. Toda página importada também expõe `deep_structure({...})`.
149
+ Menus combinam DSL curta e estrutura profunda.
150
+ Project roles, module roles e `allowed_roles` são editáveis em Ruby.
151
+
152
+ ## MPR v2
153
+
154
+ O manifesto registra `format_version: v2`; a geração cria automaticamente os
155
+ arquivos `mprcontents/*.mxunit`.
156
+
157
+ ## Análise semântica
158
+
159
+ ```ruby
160
+ project.references_to("Sales.Order")
161
+ project.callers_of("Sales.Process")
162
+ project.impact_of("Sales.Order")
163
+ project.plan_rename("Sales.Order", to: "Invoice")
164
+ project.plan_remove("Sales.FluxoSemUso")
165
+ project.plan_move("Sales.Processar", to: "Sales.Automacao")
166
+ project.analyze
167
+ ```
168
+
169
+ Na CLI, use `refs`, `callers`, `callees`, `impact`, `rename`, `remove`, `move`,
170
+ `lint`, `report`, `diff`, `find`, `describe` e `tree`. O lint nativo verifica
171
+ acesso de entidades persistentes, papéis de páginas/flows, documentação de
172
+ contratos públicos, alvos de navegação e mapeamentos duplicados de module role.
173
+ Use `mxrb cache status|warm|clear app.mpr` para métricas e manutenção do índice.
174
+ Refatorações apenas
175
+ mostram a prévia, salvo quando `--apply` é informado. A remoção é bloqueada se
176
+ houver referências recebidas ou units filhas; movimentos ficam no mesmo
177
+ módulo e rejeitam ciclos de pastas.
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Executable model expectations: plain Ruby, no MDL.
4
+ artifact "Sudoku.Game", kind: :entity
5
+ artifact "Sudoku.Game_Play", kind: :page
6
+ artifact "Sudoku.ACT_DealGame", kind: :microflow
7
+
8
+ no_call_cycles
9
+ no_missing_internal_references
10
+ maximum_unreferenced 250, severity: :warning
11
+
12
+ check "Sudoku exposes its three domain entities" do |project|
13
+ project.search_artifacts("Sudoku.", kind: :entity).size == 3
14
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ # First functional slice: each microflow must complete without an unhandled
4
+ # runtime exception. The source project is never modified.
5
+ microflow "creates an easy game",
6
+ call: "Sudoku.ACT_NewEasy",
7
+ expect: {
8
+ count: [
9
+ { entity: "Sudoku.Game", equals: 1 },
10
+ { entity: "Sudoku.Cell", equals: 81 }
11
+ ]
12
+ }
13
+ microflow "creates a medium game",
14
+ call: "Sudoku.ACT_NewMedium",
15
+ expect: {
16
+ count: [
17
+ { entity: "Sudoku.Game", equals: 2 },
18
+ { entity: "Sudoku.Cell", equals: 162 }
19
+ ]
20
+ }
21
+ microflow "creates a hard game",
22
+ call: "Sudoku.ACT_NewHard",
23
+ expect: {
24
+ count: [
25
+ { entity: "Sudoku.Game", equals: 3 },
26
+ { entity: "Sudoku.Cell", equals: 243 }
27
+ ]
28
+ }
@@ -0,0 +1,124 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mxrb
4
+ module Architecture
5
+ Node = Data.define(:id, :module_name, :kind, :name, :metadata)
6
+ Edge = Data.define(:from, :to, :relation, :metadata)
7
+
8
+ class Graph
9
+ attr_reader :nodes, :edges
10
+
11
+ def initialize(definition)
12
+ @definition = definition
13
+ @nodes = {}
14
+ @edges = []
15
+ build
16
+ end
17
+
18
+ def node_id(module_name, kind, name)
19
+ "#{module_name}::#{kind}::#{name}"
20
+ end
21
+
22
+ def find(module_name, kind, name)
23
+ @nodes[node_id(module_name, kind, name)]
24
+ end
25
+
26
+ def dependencies_of(node)
27
+ @edges.select { _1.from == node.id }.filter_map { @nodes[_1.to] }
28
+ end
29
+
30
+ private
31
+
32
+ def build
33
+ @definition.fetch(:modules).each do |mod|
34
+ add_module_nodes(mod)
35
+ add_module_edges(mod)
36
+ end
37
+ end
38
+
39
+ def add_module_nodes(mod)
40
+ module_name = mod.fetch(:name)
41
+ {
42
+ entity: mod.fetch(:entities),
43
+ page: mod.fetch(:pages),
44
+ microflow: mod.fetch(:microflows),
45
+ nanoflow: mod.fetch(:nanoflows, []),
46
+ repository: mod.fetch(:repositories, [])
47
+ }.each do |kind, items|
48
+ items.each { add_node(module_name, kind, _1.fetch(:name), _1) }
49
+ end
50
+ end
51
+
52
+ def add_module_edges(mod)
53
+ module_name = mod.fetch(:name)
54
+ mod.fetch(:entities).each do |entity|
55
+ from = id(module_name, :entity, entity.fetch(:name))
56
+ entity.fetch(:associations, []).each do |association|
57
+ add_edge(from, ref(module_name, :entity, association.fetch(:target)), :association)
58
+ end
59
+ Array(entity[:lifecycle]).each do |callback|
60
+ add_edge(from, ref(module_name, :microflow, callback.fetch(:handler)), callback.fetch(:event))
61
+ end
62
+ end
63
+
64
+ mod.fetch(:pages).each do |page|
65
+ from = id(module_name, :page, page.fetch(:name))
66
+ if (source = page[:data_source])
67
+ add_edge(from, ref(module_name, source.fetch(:kind), source.fetch(:name)), :data_source)
68
+ end
69
+ page.fetch(:events, []).each do |event|
70
+ next if event.fetch(:kind).to_sym == :action
71
+
72
+ add_edge(from, ref(module_name, event.fetch(:kind), event.fetch(:handler)), event.fetch(:event),
73
+ target: event[:target])
74
+ end
75
+ page.fetch(:widgets, []).each do |widget|
76
+ widget.fetch(:events, []).each do |event|
77
+ next if event.fetch(:kind).to_sym == :action
78
+
79
+ add_edge(
80
+ from,
81
+ ref(module_name, event.fetch(:kind), event.fetch(:handler)),
82
+ event.fetch(:event),
83
+ target: widget.fetch(:name), widget_type: widget.fetch(:type)
84
+ )
85
+ end
86
+ end
87
+ end
88
+
89
+ (mod.fetch(:microflows) + mod.fetch(:nanoflows, [])).each do |flow|
90
+ from = id(module_name, flow.fetch(:runtime) == :client ? :nanoflow : :microflow, flow.fetch(:name))
91
+ flow.fetch(:calls, []).each do |call|
92
+ add_edge(from, ref(module_name, call.fetch(:kind), call.fetch(:name)), :calls)
93
+ end
94
+ flow.fetch(:repositories, []).each do |repository|
95
+ add_edge(from, ref(module_name, :repository, repository), :uses_repository)
96
+ end
97
+ end
98
+ end
99
+
100
+ def add_node(module_name, kind, name, metadata)
101
+ identifier = id(module_name, kind, name)
102
+ @nodes[identifier] = Node.new(identifier, module_name, kind, name, metadata)
103
+ end
104
+
105
+ def add_edge(from, to, relation, metadata = {})
106
+ @edges << Edge.new(from, to, relation.to_sym, metadata)
107
+ end
108
+
109
+ def id(module_name, kind, name)
110
+ node_id(module_name, kind, name)
111
+ end
112
+
113
+ def ref(current_module, kind, raw_name)
114
+ text = raw_name.to_s
115
+ if text.include?(".")
116
+ module_name, name = text.split(".", 2)
117
+ id(module_name, kind, name)
118
+ else
119
+ id(current_module, kind, text)
120
+ end
121
+ end
122
+ end
123
+ end
124
+ end
@@ -0,0 +1,98 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mxrb
4
+ module Architecture
5
+ class Validator
6
+ Result = Data.define(:errors, :warnings) do
7
+ def valid? = errors.empty?
8
+ end
9
+
10
+ def initialize(graph)
11
+ @graph = graph
12
+ end
13
+
14
+ def validate
15
+ errors = []
16
+ warnings = []
17
+ validate_targets(errors)
18
+ validate_layers(errors)
19
+ validate_cycles(errors)
20
+ Result.new(errors.freeze, warnings.freeze)
21
+ end
22
+
23
+ def validate!
24
+ result = validate
25
+ return result if result.valid?
26
+
27
+ raise ValidationError, "architecture validation failed:\n- #{result.errors.join("\n- ")}"
28
+ end
29
+
30
+ private
31
+
32
+ def validate_targets(errors)
33
+ @graph.edges.each do |edge|
34
+ next if @graph.nodes.key?(edge.to)
35
+ next if late_bound_page_nanoflow?(edge)
36
+ next if platform_owned_target?(edge.to)
37
+
38
+ errors << "#{edge.from} #{edge.relation} references missing #{edge.to}"
39
+ end
40
+ end
41
+
42
+ def late_bound_page_nanoflow?(edge)
43
+ from = @graph.nodes[edge.from]
44
+ from&.kind == :page && edge.to.include?("::nanoflow::")
45
+ end
46
+
47
+ def platform_owned_target?(target)
48
+ target.start_with?("System::")
49
+ end
50
+
51
+ def validate_layers(errors)
52
+ @graph.edges.each do |edge|
53
+ from = @graph.nodes[edge.from]
54
+ to = @graph.nodes[edge.to]
55
+ next unless from && to
56
+
57
+ if from.kind == :page && to.kind == :repository
58
+ errors << "#{from.id} cannot access repository #{to.id} directly"
59
+ end
60
+ if from.kind == :entity && edge.relation.to_s.start_with?("on_") && to.kind == :nanoflow
61
+ errors << "#{from.id} lifecycle cannot call client-side #{to.id}"
62
+ end
63
+ # Entity-to-entity associations are allowed cross-module in Mendix domain model
64
+ next if edge.relation == :association && from.kind == :entity && to.kind == :entity
65
+ if from.module_name != to.module_name && !to.metadata.fetch(:public, false)
66
+ errors << "#{from.id} references internal artifact #{to.id} from another module"
67
+ end
68
+ end
69
+ end
70
+
71
+ def validate_cycles(errors)
72
+ adjacency = Hash.new { |h, k| h[k] = [] }
73
+ @graph.edges.select { %i[calls].include?(_1.relation) }.each do |edge|
74
+ adjacency[edge.from] << edge.to if @graph.nodes.key?(edge.to)
75
+ end
76
+ visiting = {}
77
+ visited = {}
78
+ stack = []
79
+
80
+ visit = lambda do |node|
81
+ return if visited[node]
82
+ if visiting[node]
83
+ start = stack.index(node) || 0
84
+ errors << "call cycle detected: #{(stack[start..] + [node]).join(' -> ')}"
85
+ return
86
+ end
87
+ visiting[node] = true
88
+ stack << node
89
+ adjacency[node].each { visit.call(_1) }
90
+ stack.pop
91
+ visiting.delete(node)
92
+ visited[node] = true
93
+ end
94
+ @graph.nodes.each_key { visit.call(_1) }
95
+ end
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mxrb
4
+ BenchmarkResult = Data.define(:iterations, :open_seconds, :index_seconds, :validate_seconds, :units)
5
+
6
+ # Repeatable wall-clock benchmark for the main read-only MPR operations.
7
+ class Benchmark
8
+ def initialize(path, iterations: 3, clock: Process.method(:clock_gettime))
9
+ @path = File.expand_path(path)
10
+ @iterations = Integer(iterations)
11
+ @clock = clock
12
+ raise ArgumentError, 'iterations must be between 1 and 100' unless (1..100).cover?(@iterations)
13
+ end
14
+
15
+ def run
16
+ open_time, units = measure { Mxrb.open(@path) { _1.all_units.size } }
17
+ index_time, = measure { Mxrb.open(@path) { _1.semantic_index.artifacts.size } }
18
+ validate_time, = measure { Mxrb.validate(@path).valid? }
19
+ BenchmarkResult.new(@iterations, open_time, index_time, validate_time, units)
20
+ end
21
+
22
+ private
23
+
24
+ def measure
25
+ value = nil
26
+ started = now
27
+ @iterations.times { value = yield }
28
+ [((now - started) / @iterations).round(6), value]
29
+ end
30
+
31
+ def now = @clock.call(Process::CLOCK_MONOTONIC)
32
+ end
33
+ end