datex-studio-cli 0.4.4__tar.gz → 0.4.6__tar.gz

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 (172) hide show
  1. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/PKG-INFO +1 -1
  2. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/pyproject.toml +1 -1
  3. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/__init__.py +1 -1
  4. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/cli.py +25 -16
  5. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/commands/crm.py +257 -90
  6. datex_studio_cli-0.4.6/src/dxs/utils/update_check.py +208 -0
  7. datex_studio_cli-0.4.4/src/dxs/utils/update_check.py +0 -310
  8. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/.gitignore +0 -0
  9. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/README.md +0 -0
  10. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/report-creator.skill +0 -0
  11. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/scripts/analyze_corpus.py +0 -0
  12. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/scripts/generate_rdlx_schema.py +0 -0
  13. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/__main__.py +0 -0
  14. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/commands/__init__.py +0 -0
  15. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/commands/api.py +0 -0
  16. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/commands/auth.py +0 -0
  17. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/commands/branch.py +0 -0
  18. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/commands/config.py +0 -0
  19. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/commands/configuration.py +0 -0
  20. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/commands/datasource.py +0 -0
  21. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/commands/devops.py +0 -0
  22. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/commands/document.py +0 -0
  23. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/commands/endpoint.py +0 -0
  24. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/commands/env.py +0 -0
  25. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/commands/explore.py +0 -0
  26. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/commands/function.py +0 -0
  27. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/commands/marketplace.py +0 -0
  28. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/commands/odata.py +0 -0
  29. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/commands/organization.py +0 -0
  30. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/commands/proxy.py +0 -0
  31. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/commands/release_notes.py +0 -0
  32. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/commands/repo.py +0 -0
  33. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/commands/report/__init__.py +0 -0
  34. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/commands/report/add_cmds.py +0 -0
  35. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/commands/report/api.py +0 -0
  36. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/commands/report/batch.py +0 -0
  37. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/commands/report/create.py +0 -0
  38. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/commands/report/data.py +0 -0
  39. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/commands/report/dataset.py +0 -0
  40. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/commands/report/edit.py +0 -0
  41. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/commands/report/folder.py +0 -0
  42. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/commands/report/preview.py +0 -0
  43. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/commands/report/schema_cmds.py +0 -0
  44. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/commands/schema.py +0 -0
  45. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/commands/servicepack.py +0 -0
  46. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/commands/source.py +0 -0
  47. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/commands/studio.py +0 -0
  48. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/commands/telemetry.py +0 -0
  49. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/commands/user.py +0 -0
  50. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/context.py +0 -0
  51. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/core/__init__.py +0 -0
  52. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/core/api/__init__.py +0 -0
  53. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/core/api/app_config.py +0 -0
  54. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/core/api/client.py +0 -0
  55. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/core/api/endpoints.py +0 -0
  56. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/core/api/metadata_models.py +0 -0
  57. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/core/api/models.py +0 -0
  58. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/core/auth/__init__.py +0 -0
  59. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/core/auth/decorators.py +0 -0
  60. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/core/auth/msal_client.py +0 -0
  61. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/core/auth/token_cache.py +0 -0
  62. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/core/cache.py +0 -0
  63. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/core/datasource/__init__.py +0 -0
  64. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/core/datasource/flow_generator.py +0 -0
  65. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/core/datasource/flow_models.py +0 -0
  66. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/core/datasource/generator.py +0 -0
  67. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/core/datasource/models.py +0 -0
  68. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/core/datasource/parsers.py +0 -0
  69. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/core/datasource/resolver.py +0 -0
  70. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/core/datasource/type_def_parser.py +0 -0
  71. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/core/datasource/validator.py +0 -0
  72. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/core/designer/__init__.py +0 -0
  73. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/core/designer/flow_models.py +0 -0
  74. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/core/designer/models.py +0 -0
  75. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/core/designer/parsers.py +0 -0
  76. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/core/devops/__init__.py +0 -0
  77. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/core/devops/client.py +0 -0
  78. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/core/devops/helpers.py +0 -0
  79. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/core/devops/models.py +0 -0
  80. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/core/dynamics/__init__.py +0 -0
  81. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/core/dynamics/client.py +0 -0
  82. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/core/dynamics/metadata_cache.py +0 -0
  83. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/core/footprint/__init__.py +0 -0
  84. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/core/footprint/client.py +0 -0
  85. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/core/footprint/edmx_parser.py +0 -0
  86. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/core/footprint/metadata.py +0 -0
  87. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/core/function/__init__.py +0 -0
  88. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/core/function/generator.py +0 -0
  89. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/core/function/models.py +0 -0
  90. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/core/function/validator.py +0 -0
  91. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/core/graph.py +0 -0
  92. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/core/output/__init__.py +0 -0
  93. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/core/output/csv_fmt.py +0 -0
  94. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/core/output/formatter.py +0 -0
  95. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/core/output/json_fmt.py +0 -0
  96. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/core/output/redaction.py +0 -0
  97. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/core/output/yaml_fmt.py +0 -0
  98. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/core/release_notes.py +0 -0
  99. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/core/responses.py +0 -0
  100. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/core/telemetry/__init__.py +0 -0
  101. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/core/telemetry/config.py +0 -0
  102. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/core/telemetry/identity.py +0 -0
  103. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/core/telemetry/recorder.py +0 -0
  104. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/core/telemetry/scrubber.py +0 -0
  105. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/core/telemetry/sender.py +0 -0
  106. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/models/__init__.py +0 -0
  107. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/report/__init__.py +0 -0
  108. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/report/datasource_binding.py +0 -0
  109. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/report/engine.py +0 -0
  110. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/report/field_parser.py +0 -0
  111. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/report/folder.py +0 -0
  112. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/report/manifest.py +0 -0
  113. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/report/models.py +0 -0
  114. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/report/preview.py +0 -0
  115. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/report/preview_arjs.py +0 -0
  116. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/report/schema.py +0 -0
  117. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/report/svg_renderer.py +0 -0
  118. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/report/templates/__init__.py +0 -0
  119. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/report/templates/bill_of_lading.rdlx-json +0 -0
  120. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/report/templates/shipping_label.rdlx-json +0 -0
  121. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/report/validate_arjs.py +0 -0
  122. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/report/validator.py +0 -0
  123. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/report/wrapper.py +0 -0
  124. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/utils/__init__.py +0 -0
  125. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/utils/click_options.py +0 -0
  126. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/utils/config.py +0 -0
  127. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/utils/errors.py +0 -0
  128. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/utils/filtering.py +0 -0
  129. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/utils/image.py +0 -0
  130. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/utils/paths.py +0 -0
  131. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/utils/resolvers.py +0 -0
  132. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/utils/responses.py +0 -0
  133. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/utils/restricted.py +0 -0
  134. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/utils/sorting.py +0 -0
  135. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/web/__init__.py +0 -0
  136. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/web/app.py +0 -0
  137. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/web/design.py +0 -0
  138. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/web/proxy_app.py +0 -0
  139. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/web/static/404/index.html +0 -0
  140. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/web/static/404.html +0 -0
  141. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/web/static/_next/static/UgyAMtPjH-Pt0RYWOHzIT/_buildManifest.js +0 -0
  142. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/web/static/_next/static/UgyAMtPjH-Pt0RYWOHzIT/_ssgManifest.js +0 -0
  143. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/web/static/_next/static/chunks/0b24cca5-c1e1c8810348f107.js +0 -0
  144. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/web/static/_next/static/chunks/255-102f2e5b2e3dc2ef.js +0 -0
  145. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/web/static/_next/static/chunks/4bd1b696-c023c6e3521b1417.js +0 -0
  146. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/web/static/_next/static/chunks/538-84e2e111415f1fda.js +0 -0
  147. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/web/static/_next/static/chunks/697-0e000ab410d9f470.js +0 -0
  148. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/web/static/_next/static/chunks/871-1acacdb7b4022abf.js +0 -0
  149. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/web/static/_next/static/chunks/8b8f67fc-6295949a4b5485a4.js +0 -0
  150. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/web/static/_next/static/chunks/909-c88abba3cf0caec3.js +0 -0
  151. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/web/static/_next/static/chunks/app/_not-found/page-ea1be7001c230704.js +0 -0
  152. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/web/static/_next/static/chunks/app/design/capture/page-a5e129c2d223432c.js +0 -0
  153. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/web/static/_next/static/chunks/app/design/page-21ba66a3dd3b03f0.js +0 -0
  154. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/web/static/_next/static/chunks/app/layout-2cc6eac09e476c91.js +0 -0
  155. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/web/static/_next/static/chunks/app/page-20c358395882cdac.js +0 -0
  156. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/web/static/_next/static/chunks/framework-de98b93a850cfc71.js +0 -0
  157. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/web/static/_next/static/chunks/main-0f18f91200dac003.js +0 -0
  158. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/web/static/_next/static/chunks/main-app-b69998d8941231d8.js +0 -0
  159. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/web/static/_next/static/chunks/pages/_app-7d307437aca18ad4.js +0 -0
  160. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/web/static/_next/static/chunks/pages/_error-cb2a52f75f2162e2.js +0 -0
  161. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/web/static/_next/static/chunks/polyfills-42372ed130431b0a.js +0 -0
  162. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/web/static/_next/static/chunks/webpack-2b297ada5306c17f.js +0 -0
  163. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/web/static/_next/static/css/360c657de5e04df8.css +0 -0
  164. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/web/static/design/capture/index.html +0 -0
  165. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/web/static/design/capture/index.txt +0 -0
  166. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/web/static/design/index.html +0 -0
  167. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/web/static/design/index.txt +0 -0
  168. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/web/static/index.html +0 -0
  169. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/web/static/index.txt +0 -0
  170. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/web/static/render-cli.js +0 -0
  171. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/web/static/report-preview.html +0 -0
  172. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.6}/src/dxs/web/static/report-validate.html +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: datex-studio-cli
3
- Version: 0.4.4
3
+ Version: 0.4.6
4
4
  Summary: CLI for Datex Studio low-code platform, designed for LLM-based AI agents
5
5
  Project-URL: Homepage, https://github.com/datex/datex-studio-cli
6
6
  Project-URL: Documentation, https://github.com/datex/datex-studio-cli
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "datex-studio-cli"
7
- version = "0.4.4"
7
+ version = "0.4.6"
8
8
  description = "CLI for Datex Studio low-code platform, designed for LLM-based AI agents"
9
9
  readme = "README.md"
10
10
  license = "MIT"
@@ -1,4 +1,4 @@
1
1
  """Datex Studio CLI - Command-line interface for Datex Studio platform."""
2
2
 
3
- __version__ = "0.4.4"
3
+ __version__ = "0.4.6"
4
4
  __app_name__ = "dxs"
@@ -507,18 +507,20 @@ def _ctx_extras(dxs_ctx: "DxsContext | None") -> dict[str, Any]:
507
507
 
508
508
 
509
509
  @cli.command("update")
510
- @click.option(
511
- "--check",
512
- "check_only",
513
- is_flag=True,
514
- default=False,
515
- help="Print whether an update is available without prompting to install",
516
- )
517
- def update_cmd(check_only: bool) -> None:
518
- """Check PyPI for a newer release and optionally upgrade in place."""
510
+ def update_cmd() -> None:
511
+ """Check PyPI for a newer release and print the upgrade command.
512
+
513
+ This command never performs the upgrade itself — run the printed
514
+ command in a fresh shell. This avoids the running-binary file-lock
515
+ issues that any in-process upgrade hits on Windows.
516
+ """
517
+ import time
518
+
519
519
  from dxs.utils.update_check import (
520
+ PACKAGE_NAME,
520
521
  _fetch_latest_version,
521
- _run_upgrade,
522
+ _read_cache,
523
+ _write_cache,
522
524
  detect_upgrade_command,
523
525
  is_newer,
524
526
  )
@@ -536,12 +538,19 @@ def update_cmd(check_only: bool) -> None:
536
538
  return
537
539
 
538
540
  upgrade_cmd = detect_upgrade_command()
539
- click.echo(f"Upgrade command: {upgrade_cmd}", err=True)
540
- if check_only:
541
- return
542
-
543
- if click.confirm("Upgrade now?", default=True, err=True):
544
- sys.exit(_run_upgrade(upgrade_cmd))
541
+ click.echo("", err=True)
542
+ click.echo(f" A new release of dxs is available: {__version__} → {latest}", err=True)
543
+ click.echo(f" To upgrade, run: {upgrade_cmd}", err=True)
544
+ click.echo(f" https://pypi.org/project/{PACKAGE_NAME}/{latest}/", err=True)
545
+
546
+ # Refresh the cache and suppress the auto-banner for the next dedupe
547
+ # window — the user has explicitly seen the news.
548
+ now = time.time()
549
+ cache = _read_cache() or {}
550
+ cache["latest"] = latest
551
+ cache["checked_at"] = now
552
+ cache["last_notified_at"] = now
553
+ _write_cache(cache)
545
554
 
546
555
 
547
556
  # Register commands when module loads
@@ -505,32 +505,60 @@ def _format_annotation(annotation: dict[str, Any]) -> dict[str, Any]:
505
505
 
506
506
  @click.group()
507
507
  def crm() -> None:
508
- """Dynamics CRM commands.
508
+ """Dynamics CRM / Dataverse commands.
509
509
 
510
- Commands for interacting with Dynamics CRM / Dataverse.
510
+ Query support cases, accounts, and activities - or run raw OData against
511
+ any Dataverse entity.
511
512
 
512
513
  \b
513
514
  Setup (one-time):
514
- 1. Configure your CRM URL:
515
- dxs config set dynamics_crm_url https://yourorg.crm.dynamics.com
516
- 2. Login to grant Dynamics CRM consent:
517
- dxs auth login
515
+ dxs config set dynamics_crm_url https://yourorg.crm.dynamics.com
516
+ dxs auth login # grant Dynamics CRM consent
518
517
 
519
518
  \b
520
- Available subcommands:
521
- account Account (company) management
522
- activity Activity queries (portal comments, emails)
523
- case Support case (incident) management
524
- odata Generic OData query against any Dataverse entity
519
+ Pick a command:
520
+ case Support cases (incidents): search, get, query, types
521
+ account Accounts (companies): list, search
522
+ activity Portal comments & emails - by date range or ticket
523
+ metadata Discover entities, fields, and relationships
524
+ picklist Resolve option-set (picklist) integer values <-> labels
525
+ odata Raw OData against ANY entity (escape hatch)
526
+
527
+ \b
528
+ Exploring an unfamiliar org/entity? Discover schema before you query:
529
+ 1. dxs crm metadata entities --search <keyword> # find the entity
530
+ 2. dxs crm metadata <entity> --search <keyword> # find field names
531
+ 3. dxs crm picklist <entity> <field> # enum values for filters
532
+ 4. dxs crm odata <entity> -f "<filter>" --count-only # size it first
533
+ 5. dxs crm odata <entity> -f "<filter>" -s "<fields>" --limit 25
534
+
535
+ \b
536
+ Working efficiently (keeps responses small - matters for agents):
537
+ - Prefer case/account/activity over odata: they pre-select fields
538
+ and format output (HTML->markdown, lookups resolved).
539
+ - WITHOUT --limit, queries auto-paginate and return ALL matching
540
+ rows. Set --limit, or run --count-only first to size the result.
541
+ - Always narrow odata with -f/--filter and -s/--select.
542
+ - metadata is capped at 10 rows; use --search/--skip, not blind dumps.
543
+ - Output is concise by default; pass global --full only when needed.
525
544
  """
526
545
  pass
527
546
 
528
547
 
529
548
  @click.group()
530
549
  def case() -> None:
531
- """Support case commands.
550
+ """Support case (incident) commands.
551
+
552
+ Search and read support cases. These helpers pre-select sensible fields
553
+ and convert HTML descriptions/notes to markdown - prefer them over
554
+ 'dxs crm odata incidents' for everyday case work.
532
555
 
533
- Search and view support cases (incidents) from Dynamics CRM.
556
+ \b
557
+ Subcommands:
558
+ search Find cases by text, account, status, date, or type
559
+ get Fetch one case by ticket number (+ activity / notes)
560
+ query Custom OData over incidents (full field control)
561
+ types List case-type picklist values
534
562
 
535
563
  \b
536
564
  Examples:
@@ -538,7 +566,8 @@ def case() -> None:
538
566
  dxs crm case get C260303_0017 --include-activity # With comments & emails
539
567
  dxs crm case search "shipping" # Search all cases
540
568
  dxs crm case search "CAS-001" # Search by case number
541
- dxs crm case search --status active # List active cases
569
+ dxs crm case search --status active --limit 25 # Cap the result
570
+ dxs crm case search --account "Contoso" --count-only # Size before fetching
542
571
  """
543
572
  pass
544
573
 
@@ -1092,15 +1121,17 @@ def _format_account(account: dict[str, Any]) -> dict[str, Any]:
1092
1121
 
1093
1122
  @click.group()
1094
1123
  def account() -> None:
1095
- """Account commands.
1124
+ """Account (company) commands.
1096
1125
 
1097
- List and search for accounts (companies) in Dynamics CRM.
1126
+ List and search accounts. Returns active accounts with a curated field
1127
+ set; for other account fields drop down to 'dxs crm odata accounts'.
1098
1128
 
1099
1129
  \b
1100
1130
  Examples:
1101
- dxs crm account list # List accounts
1131
+ dxs crm account list --limit 25 # First 25 (omit --limit = ALL)
1102
1132
  dxs crm account search "Contoso" # Search by name
1103
1133
  dxs crm account search "Texas" -l 10 # Search with limit
1134
+ dxs crm account list --count-only # Just the count
1104
1135
  """
1105
1136
  pass
1106
1137
 
@@ -1292,8 +1323,67 @@ def _get_localized_label(obj: dict[str, Any] | None) -> str | None:
1292
1323
  return None
1293
1324
 
1294
1325
 
1295
- def _list_entities(ctx: "DxsContext") -> None:
1296
- """List all entity definitions in Dynamics CRM."""
1326
+ # Default page size for metadata exploration. Entity catalogs and attribute
1327
+ # lists are large enough to blow out an agent's context window if returned in
1328
+ # full, so callers must opt into more via --limit/--skip (or --limit 0 for all).
1329
+ DEFAULT_METADATA_LIMIT = 10
1330
+
1331
+
1332
+ def _paginate_metadata(
1333
+ items: list[dict[str, Any]],
1334
+ limit: int | None,
1335
+ skip: int,
1336
+ ) -> tuple[list[dict[str, Any]], dict[str, Any]]:
1337
+ """Window a metadata list by skip/limit and build pagination metadata.
1338
+
1339
+ Applies ``DEFAULT_METADATA_LIMIT`` when ``limit`` is None so unbounded
1340
+ metadata listings can't flood the caller's context. ``limit <= 0`` means
1341
+ "no limit" (return everything from ``skip`` onward).
1342
+
1343
+ Args:
1344
+ items: Full list of formatted metadata records (after any search filter).
1345
+ limit: Page size, or None to apply the default, or <= 0 for unlimited.
1346
+ skip: Number of records to skip from the start.
1347
+
1348
+ Returns:
1349
+ Tuple of (page, metadata_kwargs). ``metadata_kwargs`` carries
1350
+ ``total_count`` (matched before windowing), ``skip``, ``limit``,
1351
+ ``has_more``, and a ``pagination_hint`` string when truncated.
1352
+ """
1353
+ effective_limit = DEFAULT_METADATA_LIMIT if limit is None else limit
1354
+ matched = len(items)
1355
+ skip = max(skip, 0)
1356
+
1357
+ if effective_limit <= 0:
1358
+ page = items[skip:]
1359
+ else:
1360
+ page = items[skip : skip + effective_limit]
1361
+
1362
+ end = skip + len(page)
1363
+ has_more = end < matched
1364
+
1365
+ meta: dict[str, Any] = {
1366
+ "total_count": matched,
1367
+ "skip": skip,
1368
+ "limit": effective_limit if effective_limit > 0 else None,
1369
+ "has_more": has_more,
1370
+ }
1371
+ if has_more:
1372
+ meta["pagination_hint"] = (
1373
+ f"Showing {skip + 1}-{end} of {matched}. "
1374
+ f"Use --skip {end} for the next page, --limit 0 for all, "
1375
+ "or --search <text> to narrow."
1376
+ )
1377
+ return page, meta
1378
+
1379
+
1380
+ def _list_entities(
1381
+ ctx: "DxsContext",
1382
+ search: str | None = None,
1383
+ limit: int | None = None,
1384
+ skip: int = 0,
1385
+ ) -> None:
1386
+ """List entity definitions in Dynamics CRM (search + paginate)."""
1297
1387
  client = DynamicsClient()
1298
1388
 
1299
1389
  ctx.log("Fetching entity definitions...")
@@ -1315,19 +1405,32 @@ def _list_entities(ctx: "DxsContext") -> None:
1315
1405
  }
1316
1406
  )
1317
1407
 
1318
- ctx.output(list_response(items=formatted_entities, semantic_key="entities"))
1408
+ if search:
1409
+ needle = search.lower()
1410
+ formatted_entities = [
1411
+ e
1412
+ for e in formatted_entities
1413
+ if needle in (e.get("name") or "").lower()
1414
+ or needle in (e.get("display_name") or "").lower()
1415
+ or needle in (e.get("description") or "").lower()
1416
+ ]
1417
+
1418
+ page, page_meta = _paginate_metadata(formatted_entities, limit, skip)
1319
1419
 
1420
+ ctx.output(list_response(items=page, semantic_key="entities", **page_meta))
1320
1421
 
1321
- def _get_entity_metadata(
1422
+
1423
+ def _get_entity_fields(
1322
1424
  ctx: "DxsContext",
1323
1425
  entity_name: str,
1324
- relationships: bool,
1325
1426
  search: str | None = None,
1427
+ limit: int | None = None,
1428
+ skip: int = 0,
1326
1429
  ) -> None:
1327
- """Get metadata for a specific entity."""
1430
+ """Output the field/attribute metadata for an entity (search + paginate)."""
1328
1431
  client = DynamicsClient()
1329
1432
 
1330
- ctx.log(f"Fetching metadata for '{entity_name}'...")
1433
+ ctx.log(f"Fetching fields for '{entity_name}'...")
1331
1434
 
1332
1435
  result = client.get_entity_fields(entity_name)
1333
1436
 
@@ -1357,57 +1460,71 @@ def _get_entity_metadata(
1357
1460
  or needle in (f.get("description") or "").lower()
1358
1461
  ]
1359
1462
 
1360
- # Output fields
1361
- ctx.output(list_response(items=formatted_fields, semantic_key="fields"))
1362
-
1363
- # Add relationships if requested
1364
- if relationships:
1365
- ctx.log("Fetching relationships...")
1366
- rels = client.get_entity_relationships(entity_name)
1367
-
1368
- formatted_relationships = []
1369
-
1370
- # Format ManyToOne relationships (lookups - this entity references another)
1371
- for rel in rels.get("many_to_one", []):
1372
- formatted_relationships.append(
1373
- {
1374
- "name": rel.get("ReferencingAttribute"),
1375
- "schema_name": rel.get("SchemaName"),
1376
- "target_entity": rel.get("ReferencedEntity"),
1377
- "target_attribute": rel.get("ReferencedAttribute"),
1378
- "type": "ManyToOne",
1379
- }
1380
- )
1463
+ field_page, field_meta = _paginate_metadata(formatted_fields, limit, skip)
1464
+ ctx.output(list_response(items=field_page, semantic_key="fields", **field_meta))
1381
1465
 
1382
- # Format OneToMany relationships (this entity is referenced by others)
1383
- for rel in rels.get("one_to_many", []):
1384
- formatted_relationships.append(
1385
- {
1386
- "name": rel.get("SchemaName"),
1387
- "referencing_entity": rel.get("ReferencingEntity"),
1388
- "referencing_attribute": rel.get("ReferencingAttribute"),
1389
- "type": "OneToMany",
1390
- }
1391
- )
1392
1466
 
1393
- if search:
1394
- needle = search.lower()
1395
- formatted_relationships = [
1396
- r
1397
- for r in formatted_relationships
1398
- if any(
1399
- needle in (r.get(k) or "").lower()
1400
- for k in (
1401
- "name",
1402
- "schema_name",
1403
- "target_entity",
1404
- "referencing_entity",
1405
- "referencing_attribute",
1406
- )
1467
+ def _get_entity_relationships(
1468
+ ctx: "DxsContext",
1469
+ entity_name: str,
1470
+ search: str | None = None,
1471
+ limit: int | None = None,
1472
+ skip: int = 0,
1473
+ ) -> None:
1474
+ """Output ONLY the relationship metadata for an entity (search + paginate).
1475
+
1476
+ Relationships are returned on their own — fields are not mixed in — so the
1477
+ output (and skip/limit windowing) stays unambiguous.
1478
+ """
1479
+ client = DynamicsClient()
1480
+
1481
+ ctx.log(f"Fetching relationships for '{entity_name}'...")
1482
+ rels = client.get_entity_relationships(entity_name)
1483
+
1484
+ formatted_relationships = []
1485
+
1486
+ # Format ManyToOne relationships (lookups - this entity references another)
1487
+ for rel in rels.get("many_to_one", []):
1488
+ formatted_relationships.append(
1489
+ {
1490
+ "name": rel.get("ReferencingAttribute"),
1491
+ "schema_name": rel.get("SchemaName"),
1492
+ "target_entity": rel.get("ReferencedEntity"),
1493
+ "target_attribute": rel.get("ReferencedAttribute"),
1494
+ "type": "ManyToOne",
1495
+ }
1496
+ )
1497
+
1498
+ # Format OneToMany relationships (this entity is referenced by others)
1499
+ for rel in rels.get("one_to_many", []):
1500
+ formatted_relationships.append(
1501
+ {
1502
+ "name": rel.get("SchemaName"),
1503
+ "referencing_entity": rel.get("ReferencingEntity"),
1504
+ "referencing_attribute": rel.get("ReferencingAttribute"),
1505
+ "type": "OneToMany",
1506
+ }
1507
+ )
1508
+
1509
+ if search:
1510
+ needle = search.lower()
1511
+ formatted_relationships = [
1512
+ r
1513
+ for r in formatted_relationships
1514
+ if any(
1515
+ needle in (r.get(k) or "").lower()
1516
+ for k in (
1517
+ "name",
1518
+ "schema_name",
1519
+ "target_entity",
1520
+ "referencing_entity",
1521
+ "referencing_attribute",
1407
1522
  )
1408
- ]
1523
+ )
1524
+ ]
1409
1525
 
1410
- ctx.output(list_response(items=formatted_relationships, semantic_key="relationships"))
1526
+ rel_page, rel_meta = _paginate_metadata(formatted_relationships, limit, skip)
1527
+ ctx.output(list_response(items=rel_page, semantic_key="relationships", **rel_meta))
1411
1528
 
1412
1529
 
1413
1530
  @click.command("metadata")
@@ -1417,16 +1534,30 @@ def _get_entity_metadata(
1417
1534
  "-r",
1418
1535
  is_flag=True,
1419
1536
  default=False,
1420
- help="Include navigation properties (relationships to other entities)",
1537
+ help="Return ONLY the entity's relationships (navigation properties) "
1538
+ "instead of its fields. Requires a specific entity (not 'entities').",
1421
1539
  )
1422
1540
  @click.option(
1423
1541
  "--search",
1424
1542
  "-S",
1425
1543
  type=str,
1426
1544
  default=None,
1427
- help="Filter fields (and relationships) by case-insensitive substring "
1545
+ help="Filter entities/fields/relationships by case-insensitive substring "
1428
1546
  "match on name, display_name, or description.",
1429
1547
  )
1548
+ @click.option(
1549
+ "--limit",
1550
+ "-l",
1551
+ type=int,
1552
+ default=None,
1553
+ help=f"Max records to return (default: {DEFAULT_METADATA_LIMIT}). Use 0 for no limit.",
1554
+ )
1555
+ @click.option(
1556
+ "--skip",
1557
+ type=int,
1558
+ default=0,
1559
+ help="Number of records to skip (for paging past the default limit).",
1560
+ )
1430
1561
  @click.pass_obj
1431
1562
  @require_auth
1432
1563
  def metadata(
@@ -1434,6 +1565,8 @@ def metadata(
1434
1565
  entity_name: str | None,
1435
1566
  relationships: bool,
1436
1567
  search: str | None,
1568
+ limit: int | None,
1569
+ skip: int,
1437
1570
  ) -> None:
1438
1571
  """Entity metadata exploration.
1439
1572
 
@@ -1441,7 +1574,14 @@ def metadata(
1441
1574
  Useful for understanding the data model and constructing OData queries.
1442
1575
 
1443
1576
  Use "entities" as the argument to list all available entities.
1444
- Use any other entity name to show its fields.
1577
+ Use any other entity name to show its fields, or add --relationships to
1578
+ show its relationships instead. Fields and relationships are never mixed
1579
+ in one response.
1580
+
1581
+ Results are capped at 10 records by default to protect your context
1582
+ window. Narrow with --search, page with --skip, or pass --limit 0 to
1583
+ return everything. The response metadata reports total_count, has_more,
1584
+ and a pagination_hint when results are truncated.
1445
1585
 
1446
1586
  \b
1447
1587
  Arguments:
@@ -1449,10 +1589,12 @@ def metadata(
1449
1589
 
1450
1590
  \b
1451
1591
  Examples:
1452
- dxs crm metadata entities # List all entities
1453
- dxs crm metadata incident # Fields for cases
1454
- dxs crm metadata account # Fields for accounts
1455
- dxs crm metadata incident --relationships # Include navigation properties
1592
+ dxs crm metadata entities # First 10 entities
1593
+ dxs crm metadata entities --search shipment # Find entities by keyword
1594
+ dxs crm metadata entities --skip 10 # Next page of entities
1595
+ dxs crm metadata incident # First 10 fields for cases
1596
+ dxs crm metadata incident --limit 0 # ALL fields (no cap)
1597
+ dxs crm metadata incident --relationships # ONLY relationships (not fields)
1456
1598
  dxs crm metadata incident -r # Short form
1457
1599
  dxs crm metadata incident --search priority # Filter fields by keyword
1458
1600
  """
@@ -1462,11 +1604,26 @@ def metadata(
1462
1604
  return
1463
1605
 
1464
1606
  if entity_name == "entities":
1607
+ if relationships:
1608
+ from dxs.utils.errors import ValidationError
1609
+
1610
+ raise ValidationError(
1611
+ message="--relationships requires a specific entity, not 'entities'.",
1612
+ code="DXS-CRM-002",
1613
+ suggestions=[
1614
+ "List entities first: dxs crm metadata entities --search <keyword>",
1615
+ "Then inspect one entity's relationships: "
1616
+ "dxs crm metadata <entity> --relationships",
1617
+ ],
1618
+ )
1465
1619
  # Special case: list all entities
1466
- _list_entities(ctx)
1620
+ _list_entities(ctx, search=search, limit=limit, skip=skip)
1621
+ elif relationships:
1622
+ # Show ONLY relationships for the specified entity (fields not mixed in)
1623
+ _get_entity_relationships(ctx, entity_name, search=search, limit=limit, skip=skip)
1467
1624
  else:
1468
1625
  # Show fields for the specified entity
1469
- _get_entity_metadata(ctx, entity_name, relationships, search=search)
1626
+ _get_entity_fields(ctx, entity_name, search=search, limit=limit, skip=skip)
1470
1627
 
1471
1628
 
1472
1629
  # Register metadata as subcommand of crm
@@ -1481,8 +1638,10 @@ crm.add_command(metadata)
1481
1638
  def picklist(ctx: "DxsContext", entity_name: str, attribute_name: str) -> None:
1482
1639
  """Show option set (picklist) values for an entity attribute.
1483
1640
 
1484
- Lists the integer values and labels for a picklist/state/status field.
1485
- Useful for building OData filters that need numeric picklist values.
1641
+ Lists the integer values and labels for a picklist/state/status field -
1642
+ use these numbers when building OData --filter expressions (e.g.
1643
+ 'statecode eq 0'). Picklist fields are usually suffixed 'code'; find
1644
+ candidates with 'dxs crm metadata <entity> --search code'.
1486
1645
 
1487
1646
  \b
1488
1647
  Examples:
@@ -1762,12 +1921,17 @@ def _activity_ticket_options(f: Any) -> Any:
1762
1921
  def activity() -> None:
1763
1922
  """Activity queries (portal comments, emails).
1764
1923
 
1765
- Query customer-authored activities across all cases or for a specific ticket.
1924
+ Query customer-authored activities across all cases (by date range) or
1925
+ for a specific ticket. HTML bodies are stripped to plain text and
1926
+ truncated for token-efficient sentiment scanning.
1927
+
1928
+ \b
1929
+ Subcommands:
1930
+ portalcomment Portal comment queries (query | ticket)
1931
+ email Email queries (query | ticket)
1766
1932
 
1767
1933
  \b
1768
- Available subcommands:
1769
- portalcomment Portal comment queries
1770
- email Email queries
1934
+ Tip: 'query' requires --since; add --count-only to size a range first.
1771
1935
  """
1772
1936
  pass
1773
1937
 
@@ -2238,14 +2402,17 @@ def crm_odata(
2238
2402
  batch_size: int | None,
2239
2403
  count_only: bool,
2240
2404
  ) -> None:
2241
- """Execute an OData query against any Dataverse entity.
2405
+ """Execute a raw OData query against any Dataverse entity.
2406
+
2407
+ The escape hatch for entities/fields the case/account/activity helpers
2408
+ don't cover. Returns raw API data with no field curation or HTML
2409
+ conversion - discover field names first with 'dxs crm metadata <entity>'.
2242
2410
 
2243
2411
  ENTITY is the entity path without leading slash (e.g., contacts,
2244
2412
  annotations, EntityDefinitions(...)/Attributes(...)).
2245
2413
 
2246
- Returns raw API response data no formatting or HTML conversion.
2247
- Use this for exploring picklist metadata, querying arbitrary entities,
2248
- or running Dataverse queries beyond the built-in case/account commands.
2414
+ WARNING: without --limit this auto-paginates and returns ALL matching
2415
+ rows. Run --count-only first, then set --limit.
2249
2416
 
2250
2417
  \b
2251
2418
  Examples: