systemlink-cli 1.15.1__tar.gz → 1.15.2__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 (146) hide show
  1. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/PKG-INFO +1 -1
  2. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/pyproject.toml +1 -1
  3. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/_version.py +1 -1
  4. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/dff_click.py +92 -45
  5. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/LICENSE +0 -0
  6. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/dff-editor/editor.js +0 -0
  7. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/dff-editor/index.html +0 -0
  8. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/__init__.py +0 -0
  9. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/__main__.py +0 -0
  10. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/asset_click.py +0 -0
  11. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/cli_formatters.py +0 -0
  12. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/cli_utils.py +0 -0
  13. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/comment_click.py +0 -0
  14. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/completion_click.py +0 -0
  15. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/config.py +0 -0
  16. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/config_click.py +0 -0
  17. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/dataframe_click.py +0 -0
  18. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/dff_decorators.py +0 -0
  19. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/example_click.py +0 -0
  20. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/example_loader.py +0 -0
  21. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/example_provisioner.py +0 -0
  22. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/examples/README.md +0 -0
  23. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/examples/_schema/schema-v1.0.json +0 -0
  24. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/examples/demo-complete-workflow/README.md +0 -0
  25. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/examples/demo-complete-workflow/config.yaml +0 -0
  26. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/examples/demo-test-plans/README.md +0 -0
  27. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/examples/demo-test-plans/config.yaml +0 -0
  28. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/examples/exercise-5-1-parametric-insights/README.md +0 -0
  29. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/examples/exercise-5-1-parametric-insights/config.yaml +0 -0
  30. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/examples/exercise-7-1-test-plans/README.md +0 -0
  31. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/examples/exercise-7-1-test-plans/config.yaml +0 -0
  32. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/examples/spec-compliance-notebooks/README.md +0 -0
  33. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/examples/spec-compliance-notebooks/config.yaml +0 -0
  34. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/examples/spec-compliance-notebooks/notebooks/SpecAnalysis_ComplianceCalculation.ipynb +0 -0
  35. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/examples/spec-compliance-notebooks/notebooks/SpecComplianceCalculation.ipynb +0 -0
  36. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/examples/spec-compliance-notebooks/notebooks/SpecfileExtractionAndIngestion.ipynb +0 -0
  37. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/examples/spec-compliance-notebooks/spec_template.xlsx +0 -0
  38. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/feed_click.py +0 -0
  39. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/file_click.py +0 -0
  40. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/function_click.py +0 -0
  41. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/function_templates.py +0 -0
  42. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/main.py +0 -0
  43. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/mcp_click.py +0 -0
  44. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/mcp_reachability.py +0 -0
  45. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/mcp_server.py +0 -0
  46. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/notebook_click.py +0 -0
  47. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/platform.py +0 -0
  48. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/policy_click.py +0 -0
  49. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/policy_utils.py +0 -0
  50. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/profiles.py +0 -0
  51. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/response_handlers.py +0 -0
  52. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/rich_output.py +0 -0
  53. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/routine_click.py +0 -0
  54. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/skill_click.py +0 -0
  55. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/skills/slcli/SKILL.md +0 -0
  56. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/skills/slcli/references/analysis-recipes.md +0 -0
  57. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/skills/slcli/references/commands.md +0 -0
  58. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/skills/slcli/references/datasheet-workflow.md +0 -0
  59. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/skills/slcli/references/filtering.md +0 -0
  60. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/skills/slcli/references/import-specs.min.json +0 -0
  61. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/skills/slcli/references/job-debugging/overview.md +0 -0
  62. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/skills/slcli/references/nipkg/overview.md +0 -0
  63. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/skills/slcli/references/notebook/interfaces.md +0 -0
  64. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/skills/slcli/references/notebook/notebook-patterns.md +0 -0
  65. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/skills/slcli/references/notebook/overview.md +0 -0
  66. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/skills/slcli/references/python-test/overview.md +0 -0
  67. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/skills/slcli/references/routine-examples.md +0 -0
  68. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/skills/slcli/references/troubleshooting.md +0 -0
  69. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/skills/slcli/references/webapp/angular-ui-packages.md +0 -0
  70. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/skills/slcli/references/webapp/deployment.md +0 -0
  71. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/skills/slcli/references/webapp/layout-patterns.md +0 -0
  72. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/skills/slcli/references/webapp/nimble-angular.md +0 -0
  73. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/skills/slcli/references/webapp/overview.md +0 -0
  74. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/skills/slcli/references/webapp/systemlink-services.md +0 -0
  75. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/skills/slcli/references/webapp/troubleshooting.md +0 -0
  76. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/skills/slcli/scripts/spec_import_helper.py +0 -0
  77. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/spec_click.py +0 -0
  78. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/ssl_trust.py +0 -0
  79. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/state_click.py +0 -0
  80. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/system_click.py +0 -0
  81. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/system_query_utils.py +0 -0
  82. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/table_utils.py +0 -0
  83. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/tag_click.py +0 -0
  84. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/templates_click.py +0 -0
  85. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/testmonitor_click.py +0 -0
  86. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/universal_handlers.py +0 -0
  87. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/user_click.py +0 -0
  88. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/utils.py +0 -0
  89. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/web_editor.py +0 -0
  90. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/webapp_bootstrap.py +0 -0
  91. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/webapp_click.py +0 -0
  92. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/webapp_templates/angular/blank/.gitignore +0 -0
  93. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/webapp_templates/angular/blank/README.md +0 -0
  94. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/webapp_templates/angular/blank/angular.json +0 -0
  95. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/webapp_templates/angular/blank/package.json +0 -0
  96. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/webapp_templates/angular/blank/src/app/app-routing.module.ts +0 -0
  97. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/webapp_templates/angular/blank/src/app/app.component.html +0 -0
  98. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/webapp_templates/angular/blank/src/app/app.component.scss +0 -0
  99. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/webapp_templates/angular/blank/src/app/app.component.ts +0 -0
  100. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/webapp_templates/angular/blank/src/app/app.module.ts +0 -0
  101. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/webapp_templates/angular/blank/src/app/core/layout/app-shell.component.html +0 -0
  102. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/webapp_templates/angular/blank/src/app/core/layout/app-shell.component.scss +0 -0
  103. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/webapp_templates/angular/blank/src/app/core/layout/app-shell.component.ts +0 -0
  104. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/webapp_templates/angular/blank/src/app/core/state/app-view-state.service.ts +0 -0
  105. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/webapp_templates/angular/blank/src/app/core/systemlink/systemlink-context.service.ts +0 -0
  106. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/webapp_templates/angular/blank/src/app/core/systemlink/theme-sync.service.ts +0 -0
  107. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/webapp_templates/angular/blank/src/app/core/systemlink/webapp-home-data.service.ts +0 -0
  108. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/webapp_templates/angular/blank/src/app/features/assets/assets-page.component.html +0 -0
  109. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/webapp_templates/angular/blank/src/app/features/assets/assets-page.component.scss +0 -0
  110. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/webapp_templates/angular/blank/src/app/features/assets/assets-page.component.ts +0 -0
  111. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/webapp_templates/angular/blank/src/app/features/datasets/datasets-page.component.html +0 -0
  112. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/webapp_templates/angular/blank/src/app/features/datasets/datasets-page.component.scss +0 -0
  113. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/webapp_templates/angular/blank/src/app/features/datasets/datasets-page.component.ts +0 -0
  114. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/webapp_templates/angular/blank/src/app/features/home/home-page.component.html +0 -0
  115. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/webapp_templates/angular/blank/src/app/features/home/home-page.component.scss +0 -0
  116. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/webapp_templates/angular/blank/src/app/features/home/home-page.component.ts +0 -0
  117. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/webapp_templates/angular/blank/src/app/features/master-detail/master-detail-page.component.html +0 -0
  118. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/webapp_templates/angular/blank/src/app/features/master-detail/master-detail-page.component.scss +0 -0
  119. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/webapp_templates/angular/blank/src/app/features/master-detail/master-detail-page.component.ts +0 -0
  120. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/webapp_templates/angular/blank/src/app/features/operations/operations-page.component.html +0 -0
  121. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/webapp_templates/angular/blank/src/app/features/operations/operations-page.component.scss +0 -0
  122. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/webapp_templates/angular/blank/src/app/features/operations/operations-page.component.ts +0 -0
  123. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/webapp_templates/angular/blank/src/app/features/settings/settings-page.component.html +0 -0
  124. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/webapp_templates/angular/blank/src/app/features/settings/settings-page.component.scss +0 -0
  125. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/webapp_templates/angular/blank/src/app/features/settings/settings-page.component.ts +0 -0
  126. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/webapp_templates/angular/blank/src/app/shared/components/empty-state.component.html +0 -0
  127. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/webapp_templates/angular/blank/src/app/shared/components/empty-state.component.scss +0 -0
  128. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/webapp_templates/angular/blank/src/app/shared/components/empty-state.component.ts +0 -0
  129. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/webapp_templates/angular/blank/src/app/shared/components/error-banner.component.html +0 -0
  130. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/webapp_templates/angular/blank/src/app/shared/components/error-banner.component.scss +0 -0
  131. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/webapp_templates/angular/blank/src/app/shared/components/error-banner.component.ts +0 -0
  132. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/webapp_templates/angular/blank/src/app/shared/components/loading-state.component.html +0 -0
  133. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/webapp_templates/angular/blank/src/app/shared/components/loading-state.component.scss +0 -0
  134. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/webapp_templates/angular/blank/src/app/shared/components/loading-state.component.ts +0 -0
  135. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/webapp_templates/angular/blank/src/app/shared/states/view-state.model.ts +0 -0
  136. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/webapp_templates/angular/blank/src/assets/README.md +0 -0
  137. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/webapp_templates/angular/blank/src/index.html +0 -0
  138. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/webapp_templates/angular/blank/src/main.ts +0 -0
  139. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/webapp_templates/angular/blank/src/styles.scss +0 -0
  140. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/webapp_templates/angular/blank/tsconfig.app.json +0 -0
  141. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/webapp_templates/angular/blank/tsconfig.json +0 -0
  142. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/workflow_preview.py +0 -0
  143. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/workflows_click.py +0 -0
  144. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/workitem_click.py +0 -0
  145. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/workspace_click.py +0 -0
  146. {systemlink_cli-1.15.1 → systemlink_cli-1.15.2}/slcli/workspace_utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: systemlink-cli
3
- Version: 1.15.1
3
+ Version: 1.15.2
4
4
  Summary: SystemLink Integrator CLI - cross-platform CLI for SystemLink workflows and templates.
5
5
  License-File: LICENSE
6
6
  Author: Fred Visser
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "systemlink-cli"
3
- version = "1.15.1"
3
+ version = "1.15.2"
4
4
  description = "SystemLink Integrator CLI - cross-platform CLI for SystemLink workflows and templates."
5
5
  authors = ["Fred Visser <fred.visser@emerson.com>"]
6
6
  packages = [{ include = "slcli" }]
@@ -1,4 +1,4 @@
1
1
  """Version information for slcli."""
2
2
 
3
3
  # This file is auto-generated. Do not edit manually.
4
- __version__ = "1.15.1"
4
+ __version__ = "1.15.2"
@@ -49,6 +49,16 @@ VALID_FIELD_TYPES = [
49
49
  "LinkedResource",
50
50
  ]
51
51
 
52
+ _FIELD_TYPE_CANONICAL_MAP = {
53
+ "text": "TEXT",
54
+ "number": "NUMBER",
55
+ "boolean": "BOOLEAN",
56
+ "enum": "ENUM",
57
+ "datetime": "DATE_TIME",
58
+ "table": "TABLE",
59
+ "linkedresource": "LINKED_RESOURCE",
60
+ }
61
+
52
62
  # Help text for resource type parameter
53
63
  RESOURCE_TYPE_HELP = f"Resource type. Valid values: {', '.join(VALID_RESOURCE_TYPES)}"
54
64
 
@@ -162,13 +172,79 @@ def validate_field_type(field_type: str) -> None:
162
172
  Raises:
163
173
  click.ClickException: If the field type is not valid
164
174
  """
165
- if field_type not in VALID_FIELD_TYPES:
175
+ if not isinstance(field_type, str):
176
+ raise click.ClickException(
177
+ f"Invalid field type: '{field_type}'. Field type must be a string."
178
+ )
179
+
180
+ normalized_field_type = "".join(ch for ch in field_type if ch.isalnum()).lower()
181
+ if normalized_field_type not in _FIELD_TYPE_CANONICAL_MAP:
166
182
  valid_types_str = ", ".join(VALID_FIELD_TYPES)
167
183
  raise click.ClickException(
168
184
  f"Invalid field type: '{field_type}'. " f"Valid types are: {valid_types_str}"
169
185
  )
170
186
 
171
187
 
188
+ def _canonicalize_field_type(field_type: str) -> str:
189
+ """Convert user-facing or exported field type values to API enum values."""
190
+ validate_field_type(field_type)
191
+ normalized_field_type = "".join(ch for ch in field_type if ch.isalnum()).lower()
192
+ return _FIELD_TYPE_CANONICAL_MAP[normalized_field_type]
193
+
194
+
195
+ def _coerce_dff_payload_to_import_format(data: Any) -> Dict[str, Any]:
196
+ """Normalize imported/exported DFF payloads into the create/update envelope."""
197
+ if isinstance(data, list):
198
+ return {"configurations": data}
199
+
200
+ if isinstance(data, dict):
201
+ if "configuration" in data and "configurations" not in data:
202
+ configuration = data.get("configuration")
203
+ return {
204
+ "configurations": [configuration] if configuration is not None else [],
205
+ "groups": data.get("groups", []),
206
+ "fields": data.get("fields", []),
207
+ }
208
+
209
+ if "configurations" not in data:
210
+ return {"configurations": [data]}
211
+
212
+ return data
213
+
214
+ raise click.ClickException(
215
+ "Invalid custom field payload: root JSON value must be an object or array."
216
+ )
217
+
218
+
219
+ def _normalize_dff_payload_for_write(data: Any) -> Dict[str, Any]:
220
+ """Prepare DFF create/update payloads for API submission."""
221
+ normalized_data = _coerce_dff_payload_to_import_format(data)
222
+
223
+ configurations = normalized_data.get("configurations", [])
224
+ for i, config in enumerate(configurations):
225
+ if isinstance(config, dict):
226
+ resource_type = config.get("resourceType")
227
+ if resource_type:
228
+ try:
229
+ validate_resource_type(resource_type)
230
+ except click.ClickException as e:
231
+ raise click.ClickException(
232
+ f"Invalid resource type in configuration {i + 1}: {e.message}"
233
+ )
234
+
235
+ fields = normalized_data.get("fields", [])
236
+ for i, field in enumerate(fields):
237
+ if isinstance(field, dict):
238
+ field_type = field.get("type")
239
+ if field_type:
240
+ try:
241
+ field["type"] = _canonicalize_field_type(field_type)
242
+ except click.ClickException as e:
243
+ raise click.ClickException(f"Invalid field type in field {i + 1}: {e.message}")
244
+
245
+ return normalized_data
246
+
247
+
172
248
  def _query_all_groups(
173
249
  workspace_filter: Optional[str] = None, workspace_map: Optional[dict] = None
174
250
  ) -> List[Dict[str, Any]]:
@@ -441,41 +517,7 @@ def register_dff_commands(cli: Any) -> None:
441
517
  url = f"{get_base_url()}/nidynamicformfields/v1/configurations"
442
518
 
443
519
  try:
444
- data = load_json_file(input_file)
445
-
446
- # Ensure data is in the expected format
447
- if isinstance(data, dict) and "configurations" not in data:
448
- # Wrap single configuration
449
- data = {"configurations": [data]}
450
- elif isinstance(data, list):
451
- # Wrap list of configurations
452
- data = {"configurations": data}
453
-
454
- # Validate resource types in configurations
455
- configurations = data.get("configurations", [])
456
- for i, config in enumerate(configurations):
457
- if isinstance(config, dict):
458
- resource_type = config.get("resourceType")
459
- if resource_type:
460
- try:
461
- validate_resource_type(resource_type)
462
- except click.ClickException as e:
463
- raise click.ClickException(
464
- f"Invalid resource type in configuration {i + 1}: {e.message}"
465
- )
466
-
467
- # Validate field types in fields
468
- fields = data.get("fields", [])
469
- for i, field in enumerate(fields):
470
- if isinstance(field, dict):
471
- field_type = field.get("type")
472
- if field_type:
473
- try:
474
- validate_field_type(field_type)
475
- except click.ClickException as e:
476
- raise click.ClickException(
477
- f"Invalid field type in field {i + 1}: {e.message}"
478
- )
520
+ data = _normalize_dff_payload_for_write(load_json_file(input_file))
479
521
 
480
522
  # Make API request without automatic error handling to parse validation errors
481
523
  resp = make_api_request("POST", url, data, handle_errors=False)
@@ -523,6 +565,9 @@ def register_dff_commands(cli: Any) -> None:
523
565
 
524
566
  sys.exit(ExitCodes.GENERAL_ERROR)
525
567
 
568
+ except click.ClickException as exc:
569
+ click.echo(f"✗ {exc.message}", err=True)
570
+ sys.exit(ExitCodes.INVALID_INPUT)
526
571
  except requests.RequestException as exc:
527
572
  # Handle HTTP errors with detailed validation error parsing
528
573
  if hasattr(exc, "response") and exc.response is not None:
@@ -563,13 +608,7 @@ def register_dff_commands(cli: Any) -> None:
563
608
  url = f"{get_base_url()}/nidynamicformfields/v1/update-configurations"
564
609
 
565
610
  try:
566
- data = load_json_file(input_file)
567
-
568
- # Ensure data is in the expected format
569
- if isinstance(data, dict) and "configurations" not in data:
570
- data = {"configurations": [data]}
571
- elif isinstance(data, list):
572
- data = {"configurations": data}
611
+ data = _normalize_dff_payload_for_write(load_json_file(input_file))
573
612
 
574
613
  resp = make_api_request("POST", url, data, handle_errors=False)
575
614
  response_data = resp.json() if resp.text.strip() else {}
@@ -613,6 +652,9 @@ def register_dff_commands(cli: Any) -> None:
613
652
  f" - {config.get('name', 'Unknown')}: {config.get('id', '')}"
614
653
  )
615
654
 
655
+ except click.ClickException as exc:
656
+ click.echo(f"✗ {exc.message}", err=True)
657
+ sys.exit(ExitCodes.INVALID_INPUT)
616
658
  except requests.RequestException as exc:
617
659
  # Handle HTTP errors with detailed validation error parsing
618
660
  if hasattr(exc, "response") and exc.response is not None:
@@ -774,11 +816,16 @@ def register_dff_commands(cli: Any) -> None:
774
816
  full_url = f"{url}?{query_string}"
775
817
 
776
818
  resp = make_api_request("GET", full_url)
777
- data = resp.json()
819
+ data = _coerce_dff_payload_to_import_format(resp.json())
778
820
 
779
821
  # Generate output filename if not provided
780
822
  if not output:
781
- config_name = data.get("configuration", {}).get("name", f"config-{config_id}")
823
+ configurations = data.get("configurations", [])
824
+ config_name = (
825
+ configurations[0].get("name", f"config-{config_id}")
826
+ if configurations
827
+ else f"config-{config_id}"
828
+ )
782
829
  safe_name = sanitize_filename(config_name, f"config-{config_id}")
783
830
  output = f"{safe_name}.json"
784
831
 
File without changes