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,139 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'digest'
4
+
5
+ module Mxrb
6
+ module Compiler
7
+ ProjectMaterialization = Data.define(:model_path, :modules, :documents)
8
+
9
+ # Rebuilds the Runtime project/module index after native document materialization.
10
+ class ProjectMaterializer # rubocop:disable Metrics/ClassLength
11
+ EDITORIAL_TYPES = %w[
12
+ Projects$ModuleSettings Security$ModuleSecurity Folders$Folder Projects$Folder
13
+ ].freeze
14
+
15
+ def initialize(mpr_path, deployment:)
16
+ @mpr_path = File.expand_path(mpr_path)
17
+ @deployment = File.expand_path(deployment)
18
+ end
19
+
20
+ def materialize
21
+ source = SourceModel.read(@mpr_path)
22
+ path = File.join(@deployment, 'model', 'model.mdp')
23
+ package = ModelPackage.read(path)
24
+ project = compile_project(source, package, project_unit(source))
25
+ package = write_modules(source, package)
26
+ package = package.upsert(project)
27
+ package = ensure_deployment_header(package, source)
28
+ package = ProjectModelOrderer.new(package, project).order
29
+ package.write(path)
30
+ result(path, project)
31
+ end
32
+
33
+ private
34
+
35
+ def compile_project(source, package, unit)
36
+ existing = package.find(unit.id)&.document
37
+ {
38
+ '$ID' => unit.document['$ID'], '$Type' => unit.document['$Type'],
39
+ 'ProjectDocuments' => project_documents(source, package, existing),
40
+ 'Modules' => preserved_modules(source, existing, package) + compiled_modules(source, package)
41
+ }
42
+ end
43
+
44
+ def project_documents(source, package, existing)
45
+ units = source.units.select { _1.containment == 'ProjectDocuments' }
46
+ source_documents = units.filter_map { reference(_1, package) }
47
+ source_ids = source_documents.filter_map { IO::BsonCodec.extract_id(_1['$ID']) }
48
+ preserved = Array(existing&.fetch('ProjectDocuments', nil)).reject do |document|
49
+ source_ids.include?(IO::BsonCodec.extract_id(document['$ID']))
50
+ end
51
+ preserved + source_documents
52
+ end
53
+
54
+ def compile_module(source, package, module_unit) # rubocop:disable Metrics/AbcSize
55
+ units = source.units.select { _1.module_name == module_unit.document['Name'] }
56
+ domain = units.find { _1.document['$Type'] == 'DomainModels$DomainModel' }
57
+ documents = units.reject { skip_document?(_1, module_unit, domain) }
58
+ .filter_map { reference(_1, package) }
59
+ {
60
+ '$ID' => module_unit.document['$ID'], '$Type' => module_unit.document['$Type'],
61
+ 'DomainModel' => reference(domain, package), 'AllDocuments' => documents
62
+ }
63
+ end
64
+
65
+ def skip_document?(unit, module_unit, domain)
66
+ unit == module_unit || unit == domain || EDITORIAL_TYPES.include?(unit.document['$Type'])
67
+ end
68
+
69
+ def reference(unit, package)
70
+ return nil unless unit && package.find(unit.id)
71
+
72
+ { '$ID' => unit.document['$ID'], '$Type' => unit.document['$Type'] }
73
+ end
74
+
75
+ def project_unit(source)
76
+ source.units.find { _1.document['$Type'] == 'Projects$Project' } ||
77
+ raise(CompilationError, 'MPR has no project document')
78
+ end
79
+
80
+ def preserved_modules(source, existing, package)
81
+ return seeded_modules(source, package) unless existing
82
+
83
+ source_ids = source.units_of('Projects$ModuleImpl').map(&:id)
84
+ existing.fetch('Modules').reject { source_ids.include?(IO::BsonCodec.extract_id(_1['$ID'])) }
85
+ end
86
+
87
+ def seeded_modules(source, package)
88
+ return [] unless package.find(SystemModelSeed::MODULE_ID)
89
+
90
+ seed = SystemModelSeed.for(source.version)
91
+ [seed.module_reference]
92
+ end
93
+
94
+ def compiled_modules(source, package)
95
+ source.units_of('Projects$ModuleImpl').map { compile_module(source, package, _1) }
96
+ end
97
+
98
+ def write_modules(source, package)
99
+ source.units_of('Projects$ModuleImpl').reduce(package) do |result, unit|
100
+ document = {
101
+ '$ID' => unit.document['$ID'], '$Type' => unit.document['$Type'],
102
+ 'Name' => unit.document['Name']
103
+ }
104
+ result.upsert(document)
105
+ end
106
+ end
107
+
108
+ def result(path, project)
109
+ modules = project.fetch('Modules')
110
+ ProjectMaterialization.new(
111
+ model_path: path, modules: modules.length, documents: document_count(modules)
112
+ )
113
+ end
114
+
115
+ def document_count(modules) = modules.sum { _1.fetch('AllDocuments').length }
116
+
117
+ def deployment_header?(package)
118
+ package.documents.any? do |document|
119
+ document['$Type'] == 'Projects$Project' && document.key?('DeploymentID')
120
+ end
121
+ end
122
+
123
+ def ensure_deployment_header(package, source)
124
+ return package if deployment_header?(package)
125
+
126
+ package.with_appended(deployment_header(source, project_unit(source)))
127
+ end
128
+
129
+ def deployment_header(source, unit)
130
+ {
131
+ '$ID' => unit.document['$ID'], '$Type' => unit.document['$Type'],
132
+ 'DeploymentID' => Digest::SHA256.hexdigest(unit.id)[0, 16].to_i(16).to_s,
133
+ 'RuntimeVersion' => source.version, 'ModelVersion' => 'unversioned',
134
+ 'SprintrProjectName' => File.basename(source.path, File.extname(source.path))
135
+ }
136
+ end
137
+ end # rubocop:enable Metrics/ClassLength
138
+ end
139
+ end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mxrb
4
+ module Compiler
5
+ # Orders model documents so containers precede children during Runtime resolution.
6
+ class ProjectModelOrderer
7
+ def initialize(package, project)
8
+ @package = package
9
+ @project = project
10
+ end
11
+
12
+ def order
13
+ ordered = [@project, deployment_header]
14
+ ordered.concat(resolve(@project.fetch('ProjectDocuments')))
15
+ @project.fetch('Modules').each { append_module(ordered, _1) }
16
+ ordered.compact!
17
+ ordered.concat(remaining(ordered))
18
+ ModelPackage.from_documents(ordered)
19
+ end
20
+
21
+ private
22
+
23
+ def append_module(ordered, mod)
24
+ ordered.concat(resolve([mod]))
25
+ ordered.concat(resolve([mod.fetch('DomainModel')]))
26
+ ordered.concat(resolve(mod.fetch('AllDocuments')))
27
+ end
28
+
29
+ def resolve(references)
30
+ Array(references).filter_map do |reference|
31
+ next unless reference
32
+
33
+ id = IO::BsonCodec.extract_id(reference['$ID'])
34
+ @package.entries.find { _1.id == id && !header?(_1.document) }&.document
35
+ end
36
+ end
37
+
38
+ def deployment_header = @package.documents.find { header?(_1) }
39
+
40
+ def remaining(ordered)
41
+ used = ordered.map(&:object_id)
42
+ @package.documents.reject do |document|
43
+ used.include?(document.object_id) || document.equal?(@project) || header?(document)
44
+ end
45
+ end
46
+
47
+ def header?(document)
48
+ document['$Type'] == 'Projects$Project' && document.key?('DeploymentID')
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mxrb
4
+ module Compiler
5
+ # Maps editable MPR data-type documents to Runtime type identifiers.
6
+ module RuntimeDataTypes
7
+ SCALARS = {
8
+ 'DataTypes$VoidType' => 'Void', 'DataTypes$StringType' => 'String',
9
+ 'DataTypes$BooleanType' => 'Boolean', 'DataTypes$IntegerType' => 'Integer',
10
+ 'DataTypes$DecimalType' => 'Decimal', 'DataTypes$DateTimeType' => 'DateTime'
11
+ }.freeze
12
+
13
+ private
14
+
15
+ def data_type(document) # rubocop:disable Metrics/AbcSize
16
+ return 'Void' unless document
17
+ return SCALARS.fetch(document['$Type']) if SCALARS.key?(document['$Type'])
18
+ return document['Entity'].to_s if document['$Type'] == 'DataTypes$ObjectType'
19
+ return "[#{document['Entity']}]" if document['$Type'] == 'DataTypes$ListType'
20
+ return "##{document['Enumeration']}" if document['$Type'] == 'DataTypes$EnumerationType'
21
+ return 'Unknown' if document['$Type'] == 'DataTypes$UnknownType'
22
+
23
+ raise CompilationError, "unsupported Runtime data type #{document['$Type']}"
24
+ end # rubocop:enable Metrics/AbcSize
25
+
26
+ def data_type_document?(value)
27
+ value.is_a?(Hash) && value['$Type'].to_s.start_with?('DataTypes$')
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,90 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+
5
+ module Mxrb
6
+ module Compiler
7
+ # Learns ordered Runtime BSON fields and existing compiled values from model.mdp.
8
+ class RuntimeModelSchema
9
+ DEFAULT_FIELDS = JSON.parse(
10
+ File.read(File.join(__dir__, 'schemas', 'runtime-11.json'))
11
+ ).transform_values(&:freeze).freeze
12
+ AUDITED_FIELDS = Dir[File.join(__dir__, 'schemas', 'runtime-*.json')].sort.reduce(DEFAULT_FIELDS) do |all, path|
13
+ all.merge(JSON.parse(File.read(path)).transform_values(&:freeze))
14
+ end.freeze
15
+ def self.builtin_fields(version)
16
+ return DEFAULT_FIELDS unless version
17
+
18
+ seed_version = SystemModelSeed.seed_version_for(version)
19
+ path = schema_path(seed_version)
20
+ return DEFAULT_FIELDS unless path
21
+
22
+ versioned = JSON.parse(File.read(path)).transform_values(&:freeze)
23
+ AUDITED_FIELDS.merge(versioned).freeze
24
+ end
25
+
26
+ def self.schema_path(version)
27
+ exact = File.join(__dir__, 'schemas', "runtime-#{version}.json")
28
+ major = File.join(__dir__, 'schemas', "runtime-#{version.to_s.split('.').first}.json")
29
+ [exact, major].find { File.file?(_1) }
30
+ end
31
+
32
+ def initialize(package, version: nil)
33
+ @by_id = {}
34
+ @by_qualified_name = {}
35
+ @fields = Hash.new { |hash, key| hash[key] = [] }
36
+ @builtin_fields = self.class.builtin_fields(version)
37
+ @versioned_fields = versioned_fields(version)
38
+ package.documents.each { index(_1) }
39
+ end
40
+
41
+ def counterpart(source)
42
+ @by_id[IO::BsonCodec.extract_id(source['$ID'])]
43
+ end
44
+
45
+ def counterpart_id(id) = @by_id[IO::BsonCodec.extract_id(id)]
46
+ def named(qualified_name) = @by_qualified_name[qualified_name]
47
+
48
+ def fields_for(source) # rubocop:disable Metrics/AbcSize
49
+ return @versioned_fields.fetch(source['$Type']) if @versioned_fields.key?(source['$Type'])
50
+
51
+ existing = counterpart(source)
52
+ return existing.keys if existing && existing['$Type'] == source['$Type']
53
+ return @builtin_fields.fetch(source['$Type']) if @builtin_fields.key?(source['$Type'])
54
+
55
+ candidates = @fields.fetch(source['$Type'], [])
56
+ raise CompilationError, "no Runtime schema for #{source['$Type']}" if candidates.empty?
57
+
58
+ candidates.max_by(&:length)
59
+ end # rubocop:enable Metrics/AbcSize
60
+
61
+ private
62
+
63
+ def versioned_fields(version)
64
+ return {} unless version
65
+
66
+ seed_version = SystemModelSeed.seed_version_for(version)
67
+ path = self.class.schema_path(seed_version)
68
+ path ? JSON.parse(File.read(path)) : {}
69
+ end
70
+
71
+ def index(value)
72
+ case value
73
+ when Hash then index_document(value)
74
+ when Array then value.each { index(_1) }
75
+ end
76
+ end
77
+
78
+ def index_document(document)
79
+ type = document['$Type']
80
+ if type
81
+ @fields[type] << document.keys unless @fields[type].include?(document.keys)
82
+ id = IO::BsonCodec.extract_id(document['$ID'])
83
+ @by_id[id] = document if id
84
+ @by_qualified_name[document['QualifiedName']] = document if document['QualifiedName']
85
+ end
86
+ document.each_value { index(_1) }
87
+ end
88
+ end
89
+ end
90
+ end