@ffschrattenecker/tm1-mcp-server 6.0.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.
- package/CHANGELOG.md +1211 -0
- package/LICENSE +21 -0
- package/NOTICE +34 -0
- package/README.md +276 -0
- package/dist/config.d.ts +35 -0
- package/dist/config.js +238 -0
- package/dist/http-transport.d.ts +8 -0
- package/dist/http-transport.js +132 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.js +164 -0
- package/dist/lib/callgraph/callGraph.d.ts +124 -0
- package/dist/lib/callgraph/callGraph.js +334 -0
- package/dist/lib/callgraph/choreGraph.d.ts +23 -0
- package/dist/lib/callgraph/choreGraph.js +102 -0
- package/dist/lib/callgraph/dataFlow.d.ts +74 -0
- package/dist/lib/callgraph/dataFlow.js +271 -0
- package/dist/lib/callgraph/datasourceMembership.d.ts +31 -0
- package/dist/lib/callgraph/datasourceMembership.js +142 -0
- package/dist/lib/callgraph/lintTypes.d.ts +28 -0
- package/dist/lib/callgraph/lintTypes.js +2 -0
- package/dist/lib/callgraph/mdxMembers.d.ts +29 -0
- package/dist/lib/callgraph/mdxMembers.js +97 -0
- package/dist/lib/callgraph/referenceIndex.d.ts +179 -0
- package/dist/lib/callgraph/referenceIndex.js +584 -0
- package/dist/lib/callgraph/rulesLinter.d.ts +55 -0
- package/dist/lib/callgraph/rulesLinter.js +776 -0
- package/dist/lib/callgraph/rulesParser.d.ts +26 -0
- package/dist/lib/callgraph/rulesParser.js +71 -0
- package/dist/lib/callgraph/subsetUsage.d.ts +16 -0
- package/dist/lib/callgraph/subsetUsage.js +134 -0
- package/dist/lib/callgraph/tiParser.d.ts +21 -0
- package/dist/lib/callgraph/tiParser.js +672 -0
- package/dist/lib/callgraph/tiSignatures.d.ts +32 -0
- package/dist/lib/callgraph/tiSignatures.js +6185 -0
- package/dist/lib/callgraph/tm1-adapter.d.ts +32 -0
- package/dist/lib/callgraph/tm1-adapter.js +159 -0
- package/dist/lib/callgraph/types.d.ts +53 -0
- package/dist/lib/callgraph/types.js +2 -0
- package/dist/lib/callgraph/variableEnv.d.ts +86 -0
- package/dist/lib/callgraph/variableEnv.js +214 -0
- package/dist/lib/cell-address.d.ts +12 -0
- package/dist/lib/cell-address.js +71 -0
- package/dist/lib/complexity/antipatterns.d.ts +22 -0
- package/dist/lib/complexity/antipatterns.js +302 -0
- package/dist/lib/complexity/comment-classifier.d.ts +24 -0
- package/dist/lib/complexity/comment-classifier.js +43 -0
- package/dist/lib/complexity/cross-process.d.ts +78 -0
- package/dist/lib/complexity/cross-process.js +114 -0
- package/dist/lib/complexity/process-metrics.d.ts +78 -0
- package/dist/lib/complexity/process-metrics.js +278 -0
- package/dist/lib/complexity/rules-metrics.d.ts +31 -0
- package/dist/lib/complexity/rules-metrics.js +99 -0
- package/dist/lib/concurrency.d.ts +11 -0
- package/dist/lib/concurrency.js +27 -0
- package/dist/lib/control-name.d.ts +10 -0
- package/dist/lib/control-name.js +10 -0
- package/dist/lib/coordinate-error.d.ts +3 -0
- package/dist/lib/coordinate-error.js +29 -0
- package/dist/lib/credential-format.d.ts +23 -0
- package/dist/lib/credential-format.js +25 -0
- package/dist/lib/cube-stats/fetcher.d.ts +106 -0
- package/dist/lib/cube-stats/fetcher.js +194 -0
- package/dist/lib/feeders/brackets.d.ts +47 -0
- package/dist/lib/feeders/brackets.js +195 -0
- package/dist/lib/feeders/element-type-cache.d.ts +42 -0
- package/dist/lib/feeders/element-type-cache.js +86 -0
- package/dist/lib/feeders/static-heuristics.d.ts +101 -0
- package/dist/lib/feeders/static-heuristics.js +202 -0
- package/dist/lib/git-process.d.ts +67 -0
- package/dist/lib/git-process.js +243 -0
- package/dist/lib/mask-secrets.d.ts +10 -0
- package/dist/lib/mask-secrets.js +99 -0
- package/dist/lib/mdx.d.ts +3 -0
- package/dist/lib/mdx.js +13 -0
- package/dist/lib/naming/odata-filter.d.ts +15 -0
- package/dist/lib/naming/odata-filter.js +81 -0
- package/dist/lib/naming/rules.d.ts +34 -0
- package/dist/lib/naming/rules.js +215 -0
- package/dist/lib/pro-parser.d.ts +19 -0
- package/dist/lib/pro-parser.js +260 -0
- package/dist/lib/pro-serializer.d.ts +19 -0
- package/dist/lib/pro-serializer.js +170 -0
- package/dist/lib/process-parts-schema.d.ts +45 -0
- package/dist/lib/process-parts-schema.js +46 -0
- package/dist/lib/process-refs.d.ts +88 -0
- package/dist/lib/process-refs.js +441 -0
- package/dist/lib/rules-outline.d.ts +29 -0
- package/dist/lib/rules-outline.js +68 -0
- package/dist/lib/rules-patch.d.ts +6 -0
- package/dist/lib/rules-patch.js +59 -0
- package/dist/lib/safe-regex.d.ts +15 -0
- package/dist/lib/safe-regex.js +37 -0
- package/dist/lib/sample-cells.d.ts +48 -0
- package/dist/lib/sample-cells.js +146 -0
- package/dist/lib/slim-json-schema.d.ts +20 -0
- package/dist/lib/slim-json-schema.js +68 -0
- package/dist/lib/strip-comments.d.ts +23 -0
- package/dist/lib/strip-comments.js +61 -0
- package/dist/lib/tm1-events.d.ts +16 -0
- package/dist/lib/tm1-events.js +29 -0
- package/dist/lib/v12-compat/deprecated-ti.d.ts +17 -0
- package/dist/lib/v12-compat/deprecated-ti.js +257 -0
- package/dist/lib/v12-compat/scanner.d.ts +10 -0
- package/dist/lib/v12-compat/scanner.js +43 -0
- package/dist/lib/variables-ui-data.d.ts +26 -0
- package/dist/lib/variables-ui-data.js +77 -0
- package/dist/load-env.d.ts +2 -0
- package/dist/load-env.js +29 -0
- package/dist/logger.d.ts +4 -0
- package/dist/logger.js +60 -0
- package/dist/prompts/index.d.ts +3 -0
- package/dist/prompts/index.js +141 -0
- package/dist/resources/index.d.ts +5 -0
- package/dist/resources/index.js +237 -0
- package/dist/resources/list-handler.d.ts +40 -0
- package/dist/resources/list-handler.js +86 -0
- package/dist/resources/subscriptions.d.ts +19 -0
- package/dist/resources/subscriptions.js +80 -0
- package/dist/schemas/cells.d.ts +17 -0
- package/dist/schemas/cells.js +13 -0
- package/dist/schemas/common.d.ts +16 -0
- package/dist/schemas/common.js +14 -0
- package/dist/schemas/index.d.ts +10 -0
- package/dist/schemas/index.js +23 -0
- package/dist/schemas/metadata.d.ts +70 -0
- package/dist/schemas/metadata.js +47 -0
- package/dist/schemas/monitoring.d.ts +95 -0
- package/dist/schemas/monitoring.js +69 -0
- package/dist/schemas/processes.d.ts +74 -0
- package/dist/schemas/processes.js +66 -0
- package/dist/schemas/scheduling.d.ts +13 -0
- package/dist/schemas/scheduling.js +13 -0
- package/dist/schemas/security.d.ts +19 -0
- package/dist/schemas/security.js +16 -0
- package/dist/schemas/subsets.d.ts +12 -0
- package/dist/schemas/subsets.js +12 -0
- package/dist/schemas/views.d.ts +9 -0
- package/dist/schemas/views.js +9 -0
- package/dist/session-manager.d.ts +79 -0
- package/dist/session-manager.js +281 -0
- package/dist/tm1-client/connection/profile.d.ts +13 -0
- package/dist/tm1-client/connection/profile.js +99 -0
- package/dist/tm1-client/dispatcher.d.ts +5 -0
- package/dist/tm1-client/dispatcher.js +31 -0
- package/dist/tm1-client/http.d.ts +81 -0
- package/dist/tm1-client/http.js +547 -0
- package/dist/tm1-client/services/batch-service.d.ts +123 -0
- package/dist/tm1-client/services/batch-service.js +455 -0
- package/dist/tm1-client/services/cell-service.d.ts +71 -0
- package/dist/tm1-client/services/cell-service.js +333 -0
- package/dist/tm1-client/services/cellset-transform.d.ts +26 -0
- package/dist/tm1-client/services/cellset-transform.js +80 -0
- package/dist/tm1-client/services/chore-service.d.ts +68 -0
- package/dist/tm1-client/services/chore-service.js +179 -0
- package/dist/tm1-client/services/chore-status.d.ts +11 -0
- package/dist/tm1-client/services/chore-status.js +127 -0
- package/dist/tm1-client/services/cube-service.d.ts +134 -0
- package/dist/tm1-client/services/cube-service.js +294 -0
- package/dist/tm1-client/services/dimension-service.d.ts +118 -0
- package/dist/tm1-client/services/dimension-service.js +249 -0
- package/dist/tm1-client/services/element-service.d.ts +245 -0
- package/dist/tm1-client/services/element-service.js +809 -0
- package/dist/tm1-client/services/fallback.d.ts +44 -0
- package/dist/tm1-client/services/fallback.js +72 -0
- package/dist/tm1-client/services/file-service.d.ts +53 -0
- package/dist/tm1-client/services/file-service.js +218 -0
- package/dist/tm1-client/services/hierarchy-service.d.ts +129 -0
- package/dist/tm1-client/services/hierarchy-service.js +332 -0
- package/dist/tm1-client/services/monitoring-service.d.ts +34 -0
- package/dist/tm1-client/services/monitoring-service.js +123 -0
- package/dist/tm1-client/services/odata-page.d.ts +71 -0
- package/dist/tm1-client/services/odata-page.js +87 -0
- package/dist/tm1-client/services/process-service.d.ts +278 -0
- package/dist/tm1-client/services/process-service.js +874 -0
- package/dist/tm1-client/services/process-status.d.ts +21 -0
- package/dist/tm1-client/services/process-status.js +89 -0
- package/dist/tm1-client/services/security-service.d.ts +50 -0
- package/dist/tm1-client/services/security-service.js +93 -0
- package/dist/tm1-client/services/server-service.d.ts +116 -0
- package/dist/tm1-client/services/server-service.js +504 -0
- package/dist/tm1-client/services/subset-service.d.ts +37 -0
- package/dist/tm1-client/services/subset-service.js +122 -0
- package/dist/tm1-client/services/view-service.d.ts +46 -0
- package/dist/tm1-client/services/view-service.js +287 -0
- package/dist/tm1-client.d.ts +56 -0
- package/dist/tm1-client.js +126 -0
- package/dist/tools/analysis/analyze-callgraph.d.ts +28 -0
- package/dist/tools/analysis/analyze-callgraph.js +350 -0
- package/dist/tools/analysis/analyze-chore-graph.d.ts +2 -0
- package/dist/tools/analysis/analyze-chore-graph.js +148 -0
- package/dist/tools/analysis/analyze-object-usage.d.ts +2 -0
- package/dist/tools/analysis/analyze-object-usage.js +143 -0
- package/dist/tools/analysis/audit-complexity.d.ts +2 -0
- package/dist/tools/analysis/audit-complexity.js +255 -0
- package/dist/tools/analysis/audit-feeders.d.ts +2 -0
- package/dist/tools/analysis/audit-feeders.js +417 -0
- package/dist/tools/analysis/audit-naming.d.ts +2 -0
- package/dist/tools/analysis/audit-naming.js +379 -0
- package/dist/tools/analysis/check-v12-readiness.d.ts +2 -0
- package/dist/tools/analysis/check-v12-readiness.js +136 -0
- package/dist/tools/analysis/find-orphan-dimensions.d.ts +2 -0
- package/dist/tools/analysis/find-orphan-dimensions.js +55 -0
- package/dist/tools/analysis/invalidate-callgraph-cache.d.ts +2 -0
- package/dist/tools/analysis/invalidate-callgraph-cache.js +40 -0
- package/dist/tools/analysis/trace-data-flow.d.ts +2 -0
- package/dist/tools/analysis/trace-data-flow.js +138 -0
- package/dist/tools/annotations.d.ts +12 -0
- package/dist/tools/annotations.js +61 -0
- package/dist/tools/celldata/check-feeders.d.ts +2 -0
- package/dist/tools/celldata/check-feeders.js +48 -0
- package/dist/tools/celldata/check-writable-coords.d.ts +2 -0
- package/dist/tools/celldata/check-writable-coords.js +126 -0
- package/dist/tools/celldata/execute-mdx.d.ts +17 -0
- package/dist/tools/celldata/execute-mdx.js +126 -0
- package/dist/tools/celldata/get-cell-value.d.ts +2 -0
- package/dist/tools/celldata/get-cell-value.js +30 -0
- package/dist/tools/celldata/get-view-definition.d.ts +2 -0
- package/dist/tools/celldata/get-view-definition.js +29 -0
- package/dist/tools/celldata/get-view.d.ts +2 -0
- package/dist/tools/celldata/get-view.js +55 -0
- package/dist/tools/celldata/sample-cells.d.ts +2 -0
- package/dist/tools/celldata/sample-cells.js +101 -0
- package/dist/tools/celldata/trace-cell-calculation.d.ts +2 -0
- package/dist/tools/celldata/trace-cell-calculation.js +53 -0
- package/dist/tools/celldata/trace-feeders.d.ts +2 -0
- package/dist/tools/celldata/trace-feeders.js +44 -0
- package/dist/tools/celldata/write-cells.d.ts +2 -0
- package/dist/tools/celldata/write-cells.js +65 -0
- package/dist/tools/confirm.d.ts +10 -0
- package/dist/tools/confirm.js +64 -0
- package/dist/tools/define-tool.d.ts +51 -0
- package/dist/tools/define-tool.js +49 -0
- package/dist/tools/dimension-management/bulk-upsert-elements.d.ts +2 -0
- package/dist/tools/dimension-management/bulk-upsert-elements.js +103 -0
- package/dist/tools/dimension-management/create-dimension.d.ts +2 -0
- package/dist/tools/dimension-management/create-dimension.js +22 -0
- package/dist/tools/dimension-management/create-element-attribute.d.ts +2 -0
- package/dist/tools/dimension-management/create-element-attribute.js +26 -0
- package/dist/tools/dimension-management/create-element.d.ts +2 -0
- package/dist/tools/dimension-management/create-element.js +31 -0
- package/dist/tools/dimension-management/create-hierarchy.d.ts +2 -0
- package/dist/tools/dimension-management/create-hierarchy.js +22 -0
- package/dist/tools/dimension-management/delete-dimension.d.ts +2 -0
- package/dist/tools/dimension-management/delete-dimension.js +25 -0
- package/dist/tools/dimension-management/delete-element.d.ts +2 -0
- package/dist/tools/dimension-management/delete-element.js +26 -0
- package/dist/tools/dimension-management/delete-elements.d.ts +2 -0
- package/dist/tools/dimension-management/delete-elements.js +44 -0
- package/dist/tools/dimension-management/delete-hierarchy.d.ts +2 -0
- package/dist/tools/dimension-management/delete-hierarchy.js +35 -0
- package/dist/tools/dimension-management/get-element-attribute-values.d.ts +2 -0
- package/dist/tools/dimension-management/get-element-attribute-values.js +77 -0
- package/dist/tools/dimension-management/list-element-attributes.d.ts +2 -0
- package/dist/tools/dimension-management/list-element-attributes.js +31 -0
- package/dist/tools/dimension-management/move-element.d.ts +2 -0
- package/dist/tools/dimension-management/move-element.js +28 -0
- package/dist/tools/dimension-management/update-element-attribute-value.d.ts +2 -0
- package/dist/tools/dimension-management/update-element-attribute-value.js +80 -0
- package/dist/tools/dimension-management/update-element.d.ts +2 -0
- package/dist/tools/dimension-management/update-element.js +35 -0
- package/dist/tools/error-format.d.ts +22 -0
- package/dist/tools/error-format.js +130 -0
- package/dist/tools/fileops/delete-file.d.ts +2 -0
- package/dist/tools/fileops/delete-file.js +32 -0
- package/dist/tools/fileops/get-file-content.d.ts +2 -0
- package/dist/tools/fileops/get-file-content.js +76 -0
- package/dist/tools/fileops/list-files.d.ts +2 -0
- package/dist/tools/fileops/list-files.js +43 -0
- package/dist/tools/fileops/search-files.d.ts +2 -0
- package/dist/tools/fileops/search-files.js +76 -0
- package/dist/tools/fileops/upload-file.d.ts +2 -0
- package/dist/tools/fileops/upload-file.js +69 -0
- package/dist/tools/format.d.ts +57 -0
- package/dist/tools/format.js +157 -0
- package/dist/tools/hierarchy.d.ts +6 -0
- package/dist/tools/hierarchy.js +27 -0
- package/dist/tools/index.d.ts +4 -0
- package/dist/tools/index.js +263 -0
- package/dist/tools/local-file.d.ts +16 -0
- package/dist/tools/local-file.js +88 -0
- package/dist/tools/metadata/get-ancestors.d.ts +2 -0
- package/dist/tools/metadata/get-ancestors.js +36 -0
- package/dist/tools/metadata/get-descendants.d.ts +2 -0
- package/dist/tools/metadata/get-descendants.js +64 -0
- package/dist/tools/metadata/get-hierarchy.d.ts +2 -0
- package/dist/tools/metadata/get-hierarchy.js +130 -0
- package/dist/tools/metadata/list-chores.d.ts +2 -0
- package/dist/tools/metadata/list-chores.js +62 -0
- package/dist/tools/metadata/list-cubes.d.ts +2 -0
- package/dist/tools/metadata/list-cubes.js +128 -0
- package/dist/tools/metadata/list-dimensions.d.ts +2 -0
- package/dist/tools/metadata/list-dimensions.js +131 -0
- package/dist/tools/metadata/list-processes-grouped.d.ts +2 -0
- package/dist/tools/metadata/list-processes-grouped.js +96 -0
- package/dist/tools/metadata/list-processes.d.ts +2 -0
- package/dist/tools/metadata/list-processes.js +108 -0
- package/dist/tools/metadata/resolve-default-members.d.ts +2 -0
- package/dist/tools/metadata/resolve-default-members.js +46 -0
- package/dist/tools/model-building/check-cube-rule.d.ts +2 -0
- package/dist/tools/model-building/check-cube-rule.js +51 -0
- package/dist/tools/model-building/clear-cube.d.ts +2 -0
- package/dist/tools/model-building/clear-cube.js +46 -0
- package/dist/tools/model-building/create-cube.d.ts +2 -0
- package/dist/tools/model-building/create-cube.js +34 -0
- package/dist/tools/model-building/delete-cube.d.ts +2 -0
- package/dist/tools/model-building/delete-cube.js +27 -0
- package/dist/tools/model-building/get-all-cube-rules.d.ts +2 -0
- package/dist/tools/model-building/get-all-cube-rules.js +149 -0
- package/dist/tools/model-building/get-cube-rules.d.ts +2 -0
- package/dist/tools/model-building/get-cube-rules.js +69 -0
- package/dist/tools/model-building/rules-source.d.ts +21 -0
- package/dist/tools/model-building/rules-source.js +49 -0
- package/dist/tools/model-building/search-rules.d.ts +2 -0
- package/dist/tools/model-building/search-rules.js +132 -0
- package/dist/tools/model-building/set-cube-rules.d.ts +2 -0
- package/dist/tools/model-building/set-cube-rules.js +81 -0
- package/dist/tools/model-building/unload-cube.d.ts +2 -0
- package/dist/tools/model-building/unload-cube.js +23 -0
- package/dist/tools/operations/diagnose-process-error.d.ts +2 -0
- package/dist/tools/operations/diagnose-process-error.js +178 -0
- package/dist/tools/operations/error-log-helpers.d.ts +25 -0
- package/dist/tools/operations/error-log-helpers.js +57 -0
- package/dist/tools/operations/get-audit-log.d.ts +2 -0
- package/dist/tools/operations/get-audit-log.js +70 -0
- package/dist/tools/operations/get-cube-stats.d.ts +2 -0
- package/dist/tools/operations/get-cube-stats.js +107 -0
- package/dist/tools/operations/get-error-log-content.d.ts +2 -0
- package/dist/tools/operations/get-error-log-content.js +164 -0
- package/dist/tools/operations/get-jobs.d.ts +3 -0
- package/dist/tools/operations/get-jobs.js +51 -0
- package/dist/tools/operations/get-message-log.d.ts +2 -0
- package/dist/tools/operations/get-message-log.js +63 -0
- package/dist/tools/operations/get-server-info.d.ts +2 -0
- package/dist/tools/operations/get-server-info.js +180 -0
- package/dist/tools/operations/get-server-state.d.ts +2 -0
- package/dist/tools/operations/get-server-state.js +129 -0
- package/dist/tools/operations/get-sessions.d.ts +2 -0
- package/dist/tools/operations/get-sessions.js +76 -0
- package/dist/tools/operations/get-threads.d.ts +3 -0
- package/dist/tools/operations/get-threads.js +50 -0
- package/dist/tools/operations/get-transaction-log.d.ts +2 -0
- package/dist/tools/operations/get-transaction-log.js +63 -0
- package/dist/tools/operations/list-error-logs.d.ts +8 -0
- package/dist/tools/operations/list-error-logs.js +157 -0
- package/dist/tools/operations/save-data.d.ts +2 -0
- package/dist/tools/operations/save-data.js +50 -0
- package/dist/tools/pagination.d.ts +32 -0
- package/dist/tools/pagination.js +116 -0
- package/dist/tools/scheduling/create-chore.d.ts +2 -0
- package/dist/tools/scheduling/create-chore.js +93 -0
- package/dist/tools/scheduling/delete-chore.d.ts +2 -0
- package/dist/tools/scheduling/delete-chore.js +22 -0
- package/dist/tools/scheduling/execute-chore.d.ts +2 -0
- package/dist/tools/scheduling/execute-chore.js +52 -0
- package/dist/tools/scheduling/toggle-chore.d.ts +2 -0
- package/dist/tools/scheduling/toggle-chore.js +22 -0
- package/dist/tools/scheduling/update-chore.d.ts +2 -0
- package/dist/tools/scheduling/update-chore.js +71 -0
- package/dist/tools/schemas/common.d.ts +10 -0
- package/dist/tools/schemas/common.js +23 -0
- package/dist/tools/schemas/items-analysis.d.ts +394 -0
- package/dist/tools/schemas/items-analysis.js +419 -0
- package/dist/tools/schemas/items-cells.d.ts +70 -0
- package/dist/tools/schemas/items-cells.js +65 -0
- package/dist/tools/schemas/items-common.d.ts +18 -0
- package/dist/tools/schemas/items-common.js +39 -0
- package/dist/tools/schemas/items-fileops.d.ts +11 -0
- package/dist/tools/schemas/items-fileops.js +13 -0
- package/dist/tools/schemas/items-metadata.d.ts +262 -0
- package/dist/tools/schemas/items-metadata.js +184 -0
- package/dist/tools/schemas/items-monitoring.d.ts +79 -0
- package/dist/tools/schemas/items-monitoring.js +78 -0
- package/dist/tools/schemas/items-processes.d.ts +279 -0
- package/dist/tools/schemas/items-processes.js +235 -0
- package/dist/tools/schemas/items-scheduling.d.ts +25 -0
- package/dist/tools/schemas/items-scheduling.js +26 -0
- package/dist/tools/schemas/items-security.d.ts +19 -0
- package/dist/tools/schemas/items-security.js +12 -0
- package/dist/tools/schemas/items-subsets.d.ts +2 -0
- package/dist/tools/schemas/items-subsets.js +4 -0
- package/dist/tools/schemas/items-views.d.ts +38 -0
- package/dist/tools/schemas/items-views.js +26 -0
- package/dist/tools/schemas/items.d.ts +12 -0
- package/dist/tools/schemas/items.js +23 -0
- package/dist/tools/schemas/markdown-capable.d.ts +21 -0
- package/dist/tools/schemas/markdown-capable.js +58 -0
- package/dist/tools/schemas/output-schema.d.ts +24 -0
- package/dist/tools/schemas/output-schema.js +25 -0
- package/dist/tools/security/assign-client-group.d.ts +2 -0
- package/dist/tools/security/assign-client-group.js +20 -0
- package/dist/tools/security/create-client.d.ts +2 -0
- package/dist/tools/security/create-client.js +28 -0
- package/dist/tools/security/delete-client.d.ts +2 -0
- package/dist/tools/security/delete-client.js +22 -0
- package/dist/tools/security/get-client.d.ts +2 -0
- package/dist/tools/security/get-client.js +20 -0
- package/dist/tools/security/list-clients.d.ts +2 -0
- package/dist/tools/security/list-clients.js +86 -0
- package/dist/tools/security/list-groups.d.ts +2 -0
- package/dist/tools/security/list-groups.js +43 -0
- package/dist/tools/security/remove-client-group.d.ts +2 -0
- package/dist/tools/security/remove-client-group.js +27 -0
- package/dist/tools/security/update-client.d.ts +2 -0
- package/dist/tools/security/update-client.js +22 -0
- package/dist/tools/subsets/create-subset.d.ts +2 -0
- package/dist/tools/subsets/create-subset.js +44 -0
- package/dist/tools/subsets/delete-subset.d.ts +2 -0
- package/dist/tools/subsets/delete-subset.js +26 -0
- package/dist/tools/subsets/get-subset.d.ts +2 -0
- package/dist/tools/subsets/get-subset.js +29 -0
- package/dist/tools/subsets/list-subsets.d.ts +2 -0
- package/dist/tools/subsets/list-subsets.js +36 -0
- package/dist/tools/subsets/update-subset.d.ts +2 -0
- package/dist/tools/subsets/update-subset.js +33 -0
- package/dist/tools/ti-development/check-process-code.d.ts +2 -0
- package/dist/tools/ti-development/check-process-code.js +96 -0
- package/dist/tools/ti-development/compile-process.d.ts +2 -0
- package/dist/tools/ti-development/compile-process.js +32 -0
- package/dist/tools/ti-development/copy-process.d.ts +2 -0
- package/dist/tools/ti-development/copy-process.js +32 -0
- package/dist/tools/ti-development/delete-process.d.ts +2 -0
- package/dist/tools/ti-development/delete-process.js +26 -0
- package/dist/tools/ti-development/diff-process-with-file.d.ts +2 -0
- package/dist/tools/ti-development/diff-process-with-file.js +208 -0
- package/dist/tools/ti-development/diff-processes.d.ts +2 -0
- package/dist/tools/ti-development/diff-processes.js +312 -0
- package/dist/tools/ti-development/execute-process.d.ts +8 -0
- package/dist/tools/ti-development/execute-process.js +109 -0
- package/dist/tools/ti-development/export-process-to-git.d.ts +2 -0
- package/dist/tools/ti-development/export-process-to-git.js +113 -0
- package/dist/tools/ti-development/export-process-to-pro.d.ts +2 -0
- package/dist/tools/ti-development/export-process-to-pro.js +117 -0
- package/dist/tools/ti-development/get-all-processes-code.d.ts +2 -0
- package/dist/tools/ti-development/get-all-processes-code.js +131 -0
- package/dist/tools/ti-development/get-process-code.d.ts +2 -0
- package/dist/tools/ti-development/get-process-code.js +100 -0
- package/dist/tools/ti-development/get-process-datasource.d.ts +2 -0
- package/dist/tools/ti-development/get-process-datasource.js +20 -0
- package/dist/tools/ti-development/get-process-parameters.d.ts +2 -0
- package/dist/tools/ti-development/get-process-parameters.js +25 -0
- package/dist/tools/ti-development/get-process-variables.d.ts +2 -0
- package/dist/tools/ti-development/get-process-variables.js +38 -0
- package/dist/tools/ti-development/get-process.d.ts +2 -0
- package/dist/tools/ti-development/get-process.js +163 -0
- package/dist/tools/ti-development/import-pro-file.d.ts +2 -0
- package/dist/tools/ti-development/import-pro-file.js +153 -0
- package/dist/tools/ti-development/import-process-from-git.d.ts +2 -0
- package/dist/tools/ti-development/import-process-from-git.js +198 -0
- package/dist/tools/ti-development/install-pro-bundle.d.ts +2 -0
- package/dist/tools/ti-development/install-pro-bundle.js +288 -0
- package/dist/tools/ti-development/preflight.d.ts +39 -0
- package/dist/tools/ti-development/preflight.js +56 -0
- package/dist/tools/ti-development/process-backup.d.ts +29 -0
- package/dist/tools/ti-development/process-backup.js +118 -0
- package/dist/tools/ti-development/search-code.d.ts +2 -0
- package/dist/tools/ti-development/search-code.js +208 -0
- package/dist/tools/ti-development/upsert-process.d.ts +2 -0
- package/dist/tools/ti-development/upsert-process.js +167 -0
- package/dist/tools/ti-development/validate-process-refs.d.ts +2 -0
- package/dist/tools/ti-development/validate-process-refs.js +73 -0
- package/dist/tools/views/create-mdx-view.d.ts +2 -0
- package/dist/tools/views/create-mdx-view.js +21 -0
- package/dist/tools/views/create-native-view.d.ts +2 -0
- package/dist/tools/views/create-native-view.js +81 -0
- package/dist/tools/views/delete-view.d.ts +2 -0
- package/dist/tools/views/delete-view.js +23 -0
- package/dist/tools/views/list-views.d.ts +2 -0
- package/dist/tools/views/list-views.js +32 -0
- package/dist/tools/with-annotations.d.ts +6 -0
- package/dist/tools/with-annotations.js +339 -0
- package/dist/types.d.ts +409 -0
- package/dist/types.js +91 -0
- package/dist/version.d.ts +4 -0
- package/dist/version.js +18 -0
- package/package.json +107 -0
|
@@ -0,0 +1,874 @@
|
|
|
1
|
+
// Process domain service. Owns the OData calls under /api/v1/Processes(...) —
|
|
2
|
+
// listing, executing, code/parameters/variables/datasource CRUD, plus the
|
|
3
|
+
// CompileProcess (server-side syntax check, with and without saving).
|
|
4
|
+
//
|
|
5
|
+
// See docs/ARCHITECTURE.md for the layering.
|
|
6
|
+
import { TM1Error, TM1ErrorCode } from "../../types.js";
|
|
7
|
+
import { isUnsupportedQueryShape, rethrowIfSystemic, rethrowIfSystemicOrDenied, } from "./fallback.js";
|
|
8
|
+
import { classifyExecution } from "./process-status.js";
|
|
9
|
+
import { ignoredColumnsOf } from "../../lib/variables-ui-data.js";
|
|
10
|
+
import { filterClause, nameFilterPredicates, pageClauses, readCount, } from "./odata-page.js";
|
|
11
|
+
// OData key encoder: double ' per OData literal rules, then percent-encode.
|
|
12
|
+
const enc = (s) => encodeURIComponent(String(s).replace(/'/g, "''"));
|
|
13
|
+
function decodeVariable(v) {
|
|
14
|
+
return {
|
|
15
|
+
name: v.Name,
|
|
16
|
+
type: v.Type === "Numeric" ? "Numeric" : "String",
|
|
17
|
+
position: v.Position,
|
|
18
|
+
...(v.StartByte !== undefined ? { startByte: v.StartByte } : {}),
|
|
19
|
+
...(v.EndByte !== undefined ? { endByte: v.EndByte } : {}),
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
// Encode a TI parameter for the OData write body.
|
|
23
|
+
//
|
|
24
|
+
// `Type` uses the tm1.ProcessVariableType enum (String=1, Numeric=2 — verified
|
|
25
|
+
// against the live $metadata). On v11 TM1 actually ignores this field and
|
|
26
|
+
// classifies the parameter from the JSON type of `Value`, so the decisive part
|
|
27
|
+
// is coercing `Value` to match the declared `type`: a Numeric parameter whose
|
|
28
|
+
// defaultValue arrived as the string "0" would otherwise be stored as String.
|
|
29
|
+
function encodeParameter(p) {
|
|
30
|
+
const numeric = p.type === "Numeric";
|
|
31
|
+
let value;
|
|
32
|
+
if (numeric) {
|
|
33
|
+
const n = Number(p.defaultValue);
|
|
34
|
+
value = Number.isFinite(n) ? n : 0;
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
value = String(p.defaultValue);
|
|
38
|
+
}
|
|
39
|
+
return {
|
|
40
|
+
Name: p.name,
|
|
41
|
+
Type: numeric ? 2 : 1,
|
|
42
|
+
Value: value,
|
|
43
|
+
...(p.prompt ? { Prompt: p.prompt } : {}),
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* The OData query shapes `fetchForCallgraph` will accept, richest first. Each
|
|
48
|
+
* later entry gives up something the previous one asked for, so a stricter or
|
|
49
|
+
* older TM1 that cannot parse one shape can still be served by the next.
|
|
50
|
+
*
|
|
51
|
+
* The list is a ladder of CAPABILITY, nothing else: walking down it is only
|
|
52
|
+
* ever a valid response to the server rejecting the query shape itself.
|
|
53
|
+
*/
|
|
54
|
+
const CALLGRAPH_QUERY_SHAPES = [
|
|
55
|
+
(f) => `/api/v1/Processes?$select=Name,PrologProcedure,MetadataProcedure,DataProcedure,EpilogProcedure,Parameters${f}`,
|
|
56
|
+
(f) => `/api/v1/Processes?$select=Name,PrologProcedure,MetadataProcedure,DataProcedure,EpilogProcedure,Parameters&$expand=Parameters($select=Name,Value,Type)${f}`,
|
|
57
|
+
(f) => `/api/v1/Processes?$expand=Parameters${f}`,
|
|
58
|
+
// Last resort: no parameter metadata at all. Callgraph edges still resolve;
|
|
59
|
+
// parameter-default folding degrades.
|
|
60
|
+
(f) => `/api/v1/Processes?$select=Name,PrologProcedure,MetadataProcedure,DataProcedure,EpilogProcedure${f}`,
|
|
61
|
+
];
|
|
62
|
+
export class ProcessService {
|
|
63
|
+
http;
|
|
64
|
+
/**
|
|
65
|
+
* Index into `CALLGRAPH_QUERY_SHAPES` that this connection answered, or
|
|
66
|
+
* `null` while unprobed — the same tri-state verdict `BatchService.supported`
|
|
67
|
+
* keeps, for the same reason. Probing costs up to four full `/Processes`
|
|
68
|
+
* scans, so it must be paid once per connection and not once per callgraph
|
|
69
|
+
* build (P7).
|
|
70
|
+
*/
|
|
71
|
+
callgraphShape = null;
|
|
72
|
+
constructor(http) {
|
|
73
|
+
this.http = http;
|
|
74
|
+
}
|
|
75
|
+
async list(opts = {}) {
|
|
76
|
+
// Filters are only emitted on the paged path; unpaged callers keep getting
|
|
77
|
+
// the whole collection and filter in-process. The degraded Name-only
|
|
78
|
+
// retry below reuses the same query — dropping it there would turn a
|
|
79
|
+
// paged request into a silent full, unfiltered fetch.
|
|
80
|
+
const query = opts.page === undefined
|
|
81
|
+
? ""
|
|
82
|
+
: `${filterClause(nameFilterPredicates(opts))}${pageClauses(opts.page)}`;
|
|
83
|
+
const wrap = (items, total) => opts.page === undefined ? items : { items, total };
|
|
84
|
+
// Parameters is a structural (complex) property, not a navigation property
|
|
85
|
+
// — TM1 v11 rejects $expand=Parameters with a syntax error. Use $select
|
|
86
|
+
// instead, which returns Parameters inline. Param.Type comes back as the
|
|
87
|
+
// already-decoded string "Numeric" / "String" (not the legacy int code).
|
|
88
|
+
try {
|
|
89
|
+
const response = await this.http.request("GET", `/api/v1/Processes?$select=Name,Parameters${query}`);
|
|
90
|
+
return wrap(response.value.map((p) => ({
|
|
91
|
+
name: p.Name,
|
|
92
|
+
parameters: (p.Parameters ?? []).map((param) => ({
|
|
93
|
+
name: param.Name,
|
|
94
|
+
type: param.Type === "Numeric" ? "Numeric" : "String",
|
|
95
|
+
defaultValue: param.Value,
|
|
96
|
+
...(param.Prompt ? { prompt: param.Prompt } : {}),
|
|
97
|
+
})),
|
|
98
|
+
})), readCount(response));
|
|
99
|
+
}
|
|
100
|
+
catch (e) {
|
|
101
|
+
rethrowIfSystemic(e);
|
|
102
|
+
const response = await this.http.request("GET", `/api/v1/Processes?$select=Name${query}`);
|
|
103
|
+
return wrap(response.value.map((p) => ({
|
|
104
|
+
name: p.Name,
|
|
105
|
+
parameters: [],
|
|
106
|
+
})), readCount(response));
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Execute a TI process with optional parameters. opts.timeoutMs overrides
|
|
111
|
+
* the 30s default for long-running TI runs.
|
|
112
|
+
* POST /api/v1/Processes('{name}')/tm1.ExecuteWithReturn?$expand=ErrorLogFile
|
|
113
|
+
*/
|
|
114
|
+
async execute(processName, params, opts) {
|
|
115
|
+
// $expand=ErrorLogFile is REQUIRED, not an optimization: ErrorLogFile is a
|
|
116
|
+
// navigation property on ProcessExecuteResult, so an unexpanded call returns
|
|
117
|
+
// only ProcessExecuteStatusCode and the filename is silently absent. Measured
|
|
118
|
+
// on 11.8.02900.8 and 12.5.9 — both omit the key entirely without it, and both
|
|
119
|
+
// return {"Filename": ...} with it (v11 `TM1ProcessError_*.log`, v12
|
|
120
|
+
// `ProcessLog_*.jsonl`).
|
|
121
|
+
const path = `/api/v1/Processes('${enc(processName)}')/tm1.ExecuteWithReturn?$expand=ErrorLogFile`;
|
|
122
|
+
const body = {};
|
|
123
|
+
if (params && Object.keys(params).length > 0) {
|
|
124
|
+
body.Parameters = Object.entries(params).map(([name, value]) => ({
|
|
125
|
+
Name: name,
|
|
126
|
+
Value: value,
|
|
127
|
+
}));
|
|
128
|
+
}
|
|
129
|
+
try {
|
|
130
|
+
// ExecuteWithReturn returns HTTP 200 even when the process aborts; the
|
|
131
|
+
// real outcome is in ProcessExecuteStatusCode. The plain tm1.Execute
|
|
132
|
+
// action also 2xx-es on CompletedWithMinorErrors/HasMinorErrors, which
|
|
133
|
+
// made partial failures (bad records + error log) invisible.
|
|
134
|
+
const response = await this.http.request("POST", path, body, opts);
|
|
135
|
+
return classifyExecution(response?.ProcessExecuteStatusCode, response?.ErrorLogFile?.Filename);
|
|
136
|
+
}
|
|
137
|
+
catch (error) {
|
|
138
|
+
// Systemic transport/auth failures (LOCK_TIMEOUT, CONNECTION_FAILED,
|
|
139
|
+
// AUTH_FAILED) must propagate: a timed-out TI run is still executing
|
|
140
|
+
// server-side, so reporting {success:false} would invite a duplicate run.
|
|
141
|
+
rethrowIfSystemic(error);
|
|
142
|
+
// The call itself errored, so TM1 never reported a status — and an error
|
|
143
|
+
// raised mid-run says nothing about whether the run committed. That is
|
|
144
|
+
// `indeterminate` by definition, not a rollback we can promise; the
|
|
145
|
+
// server's own text rides along in processErrorStatus so the caller still
|
|
146
|
+
// sees WHY.
|
|
147
|
+
if (error instanceof TM1Error) {
|
|
148
|
+
return {
|
|
149
|
+
success: false,
|
|
150
|
+
outcome: "indeterminate",
|
|
151
|
+
processErrorStatus: error.details ?? error.message,
|
|
152
|
+
errorLogFile: undefined,
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
throw error;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Persist in-memory cube data to disk — SaveDataAll (all cubes) or
|
|
160
|
+
* CubeSaveData (single cube). The REST API exposes no native SaveData
|
|
161
|
+
* action ($metadata verified), so this routes through the service-root
|
|
162
|
+
* ExecuteProcessWithReturn (available since 11.3) with an unbound TI
|
|
163
|
+
* process — no persistent process object is created. v11-only: both TI
|
|
164
|
+
* functions are removed in v12 (cloud engine persists automatically).
|
|
165
|
+
* POST /api/v1/ExecuteProcessWithReturn
|
|
166
|
+
*/
|
|
167
|
+
async saveData(cubeName, opts) {
|
|
168
|
+
const prolog = cubeName !== undefined
|
|
169
|
+
? `CubeSaveData('${cubeName.replace(/'/g, "''")}');`
|
|
170
|
+
: "SaveDataAll;";
|
|
171
|
+
const body = {
|
|
172
|
+
Process: {
|
|
173
|
+
Name: "}tm1-mcp-save-data",
|
|
174
|
+
HasSecurityAccess: false,
|
|
175
|
+
PrologProcedure: prolog,
|
|
176
|
+
MetadataProcedure: "",
|
|
177
|
+
DataProcedure: "",
|
|
178
|
+
EpilogProcedure: "",
|
|
179
|
+
DataSource: { Type: "None" },
|
|
180
|
+
},
|
|
181
|
+
};
|
|
182
|
+
try {
|
|
183
|
+
const response = await this.http.request("POST",
|
|
184
|
+
// See executeProcess: without $expand the ErrorLogFile nav property is
|
|
185
|
+
// never serialized, on either version.
|
|
186
|
+
"/api/v1/ExecuteProcessWithReturn?$expand=ErrorLogFile", body, opts);
|
|
187
|
+
return classifyExecution(response?.ProcessExecuteStatusCode, response?.ErrorLogFile?.Filename);
|
|
188
|
+
}
|
|
189
|
+
catch (error) {
|
|
190
|
+
// Systemic transport/auth failures (LOCK_TIMEOUT, CONNECTION_FAILED,
|
|
191
|
+
// AUTH_FAILED) must propagate: a timed-out TI run is still executing
|
|
192
|
+
// server-side, so reporting {success:false} would invite a duplicate run.
|
|
193
|
+
rethrowIfSystemic(error);
|
|
194
|
+
// The call itself errored, so TM1 never reported a status — and an error
|
|
195
|
+
// raised mid-run says nothing about whether the run committed. That is
|
|
196
|
+
// `indeterminate` by definition, not a rollback we can promise; the
|
|
197
|
+
// server's own text rides along in processErrorStatus so the caller still
|
|
198
|
+
// sees WHY.
|
|
199
|
+
if (error instanceof TM1Error) {
|
|
200
|
+
return {
|
|
201
|
+
success: false,
|
|
202
|
+
outcome: "indeterminate",
|
|
203
|
+
processErrorStatus: error.details ?? error.message,
|
|
204
|
+
errorLogFile: undefined,
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
throw error;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Get the parameters of a TI process.
|
|
212
|
+
* GET /api/v1/Processes('{name}')/Parameters
|
|
213
|
+
*/
|
|
214
|
+
async getParameters(processName) {
|
|
215
|
+
const path = `/api/v1/Processes('${enc(processName)}')/Parameters`;
|
|
216
|
+
// TM1 v11 returns Type as the decoded string "Numeric" / "String"
|
|
217
|
+
// (not the legacy int code 1 / 2). The old `=== 1` check silently
|
|
218
|
+
// classified every Numeric parameter as String.
|
|
219
|
+
const response = await this.http.request("GET", path);
|
|
220
|
+
return response.value.map((param) => ({
|
|
221
|
+
name: param.Name,
|
|
222
|
+
type: param.Type === "Numeric" ? "Numeric" : "String",
|
|
223
|
+
defaultValue: param.Value,
|
|
224
|
+
...(param.Prompt ? { prompt: param.Prompt } : {}),
|
|
225
|
+
}));
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Create a new empty TI process.
|
|
229
|
+
* POST /api/v1/Processes with body {"Name": "..."}
|
|
230
|
+
* Throws CONFLICT (409) if a process with the same name already exists.
|
|
231
|
+
*/
|
|
232
|
+
async create(name) {
|
|
233
|
+
await this.http.request("POST", "/api/v1/Processes", { Name: name });
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* Cheap existence probe: a single GET with $select=Name (404 → false)
|
|
237
|
+
* instead of list(), which pulls every process plus its parameters just to
|
|
238
|
+
* check one name. Rethrows anything that isn't NOT_FOUND.
|
|
239
|
+
*/
|
|
240
|
+
async exists(name) {
|
|
241
|
+
try {
|
|
242
|
+
await this.http.request("GET", `/api/v1/Processes('${enc(name)}')?$select=Name`);
|
|
243
|
+
return true;
|
|
244
|
+
}
|
|
245
|
+
catch (e) {
|
|
246
|
+
if (e instanceof TM1Error && e.code === TM1ErrorCode.NOT_FOUND)
|
|
247
|
+
return false;
|
|
248
|
+
throw e;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* Copy a TI process to a new name. Strips read-only / server-managed fields
|
|
253
|
+
* before re-POSTing to avoid TM1 rejecting the body.
|
|
254
|
+
*/
|
|
255
|
+
async copy(sourceName, targetName) {
|
|
256
|
+
const path = `/api/v1/Processes('${enc(sourceName)}')`;
|
|
257
|
+
const source = await this.http.request("GET", path);
|
|
258
|
+
delete source["@odata.context"];
|
|
259
|
+
delete source["@odata.etag"];
|
|
260
|
+
delete source["Attributes"];
|
|
261
|
+
delete source["LocalizedAttributes"];
|
|
262
|
+
// `UIData` and `VariablesUIData` are undeclared in $metadata on both
|
|
263
|
+
// versions, so the plain GET above never returns them. Without the second
|
|
264
|
+
// request the copy silently loses every ignored datasource column (the
|
|
265
|
+
// ignore flag lives ONLY in VariablesUIData) and the Architect action
|
|
266
|
+
// settings — measured on 11.8 and 12.5.
|
|
267
|
+
const ui = await this.getUIData(sourceName);
|
|
268
|
+
if (ui.uiData !== undefined)
|
|
269
|
+
source.UIData = ui.uiData;
|
|
270
|
+
if (ui.variablesUIData !== undefined)
|
|
271
|
+
source.VariablesUIData = ui.variablesUIData;
|
|
272
|
+
source.Name = targetName;
|
|
273
|
+
await this.http.request("POST", "/api/v1/Processes", source);
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* The two UI-only properties TM1 stores but does not declare: `UIData`
|
|
277
|
+
* (Architect cube/data action settings) and `VariablesUIData` (per-column
|
|
278
|
+
* state, including which columns are ignored). Both have to be named in
|
|
279
|
+
* `$select`; a server that rejects the query shape yields an empty result
|
|
280
|
+
* rather than an error, since neither is required to use the process.
|
|
281
|
+
*/
|
|
282
|
+
async getUIData(processName) {
|
|
283
|
+
const path = `/api/v1/Processes('${enc(processName)}')` +
|
|
284
|
+
`?$select=UIData,VariablesUIData`;
|
|
285
|
+
try {
|
|
286
|
+
const r = await this.http.request("GET", path);
|
|
287
|
+
return {
|
|
288
|
+
...(r.UIData !== undefined ? { uiData: r.UIData } : {}),
|
|
289
|
+
...(r.VariablesUIData !== undefined
|
|
290
|
+
? { variablesUIData: r.VariablesUIData }
|
|
291
|
+
: {}),
|
|
292
|
+
};
|
|
293
|
+
}
|
|
294
|
+
catch (e) {
|
|
295
|
+
rethrowIfSystemic(e);
|
|
296
|
+
if (!isUnsupportedQueryShape(e))
|
|
297
|
+
throw e;
|
|
298
|
+
return {};
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* Run the callgraph fetch against the query shape this connection accepts,
|
|
303
|
+
* discovering it on first use.
|
|
304
|
+
*
|
|
305
|
+
* The discovery loop used to catch EVERY error and move on to the next,
|
|
306
|
+
* broader query. That turned an expired session, a request timeout or a
|
|
307
|
+
* security denial into three more full-collection scans (~4 × 30 s worst
|
|
308
|
+
* case, P7) and — worse — let a later shape that happened to answer mask the
|
|
309
|
+
* real first error (K6/T-9). Two guards now bound it:
|
|
310
|
+
*
|
|
311
|
+
* - `rethrowIfSystemicOrDenied` — transport/auth/timeout failures and
|
|
312
|
+
* permission denials leave immediately. A denial in particular must never
|
|
313
|
+
* become an empty process list: the callgraph would cache "this model has
|
|
314
|
+
* no processes" as truth.
|
|
315
|
+
* - `isUnsupportedQueryShape` — of what is left, only TM1 refusing the
|
|
316
|
+
* query shape justifies asking again in another form.
|
|
317
|
+
*/
|
|
318
|
+
async fetchCallgraphBody(filter) {
|
|
319
|
+
const shapeAt = (i) => {
|
|
320
|
+
const build = CALLGRAPH_QUERY_SHAPES[i];
|
|
321
|
+
if (build === undefined)
|
|
322
|
+
throw new Error(`No callgraph query shape at index ${i}`);
|
|
323
|
+
return build(filter);
|
|
324
|
+
};
|
|
325
|
+
if (this.callgraphShape !== null) {
|
|
326
|
+
try {
|
|
327
|
+
return await this.http.request("GET", shapeAt(this.callgraphShape));
|
|
328
|
+
}
|
|
329
|
+
catch (e) {
|
|
330
|
+
// A shape this server has already answered cannot suddenly be
|
|
331
|
+
// "unsupported" — mirrors BatchService, where a 400 after the first
|
|
332
|
+
// success means the request was bad, not the feature missing. Drop the
|
|
333
|
+
// verdict so a genuinely changed server is re-probed next call, and let
|
|
334
|
+
// the error surface instead of silently re-walking the ladder.
|
|
335
|
+
this.callgraphShape = null;
|
|
336
|
+
throw e;
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
let lastErr;
|
|
340
|
+
for (let i = 0; i < CALLGRAPH_QUERY_SHAPES.length; i++) {
|
|
341
|
+
try {
|
|
342
|
+
const body = await this.http.request("GET", shapeAt(i));
|
|
343
|
+
this.callgraphShape = i;
|
|
344
|
+
return body;
|
|
345
|
+
}
|
|
346
|
+
catch (e) {
|
|
347
|
+
rethrowIfSystemicOrDenied(e);
|
|
348
|
+
if (!isUnsupportedQueryShape(e))
|
|
349
|
+
throw e;
|
|
350
|
+
lastErr = e;
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
throw lastErr instanceof Error
|
|
354
|
+
? lastErr
|
|
355
|
+
: new Error(String(lastErr ?? "Processes fetch failed"));
|
|
356
|
+
}
|
|
357
|
+
/**
|
|
358
|
+
* Fetch every TI process with code AND parameter metadata for callgraph
|
|
359
|
+
* indexing. Single round trip once the connection's usable OData query shape
|
|
360
|
+
* is known — see `fetchCallgraphBody` for the discovery rules.
|
|
361
|
+
*/
|
|
362
|
+
async fetchForCallgraph(includeControl = false) {
|
|
363
|
+
const filter = includeControl ? "" : "&$filter=not startswith(Name,'}')";
|
|
364
|
+
const body = await this.fetchCallgraphBody(filter);
|
|
365
|
+
return (body.value ?? [])
|
|
366
|
+
.map((p) => {
|
|
367
|
+
const parameters = (p.Parameters ?? [])
|
|
368
|
+
.map((x) => String(x.Name ?? ""))
|
|
369
|
+
.filter((n) => n !== "");
|
|
370
|
+
const parameterDefaults = new Map();
|
|
371
|
+
for (const x of p.Parameters ?? []) {
|
|
372
|
+
if (x.Name &&
|
|
373
|
+
x.Value !== undefined &&
|
|
374
|
+
x.Value !== null &&
|
|
375
|
+
x.Value !== "") {
|
|
376
|
+
parameterDefaults.set(String(x.Name), String(x.Value));
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
return {
|
|
380
|
+
name: String(p.Name ?? ""),
|
|
381
|
+
prolog: String(p.PrologProcedure ?? ""),
|
|
382
|
+
metadata: String(p.MetadataProcedure ?? ""),
|
|
383
|
+
data: String(p.DataProcedure ?? ""),
|
|
384
|
+
epilog: String(p.EpilogProcedure ?? ""),
|
|
385
|
+
parameters,
|
|
386
|
+
parameterDefaults,
|
|
387
|
+
};
|
|
388
|
+
})
|
|
389
|
+
.filter((p) => p.name !== "");
|
|
390
|
+
}
|
|
391
|
+
async getAllCode(includeControl = false, top) {
|
|
392
|
+
const filter = includeControl ? "" : "&$filter=not startswith(Name,'}')";
|
|
393
|
+
const cap = top !== undefined ? `&$orderby=Name&$top=${top}&$count=true` : "";
|
|
394
|
+
const path = `/api/v1/Processes?$select=Name,PrologProcedure,MetadataProcedure,DataProcedure,EpilogProcedure,HasSecurityAccess${filter}${cap}`;
|
|
395
|
+
const response = await this.http.request("GET", path);
|
|
396
|
+
const items = response.value.map((p) => ({
|
|
397
|
+
name: p.Name,
|
|
398
|
+
prolog: p.PrologProcedure ?? "",
|
|
399
|
+
metadata: p.MetadataProcedure ?? "",
|
|
400
|
+
data: p.DataProcedure ?? "",
|
|
401
|
+
epilog: p.EpilogProcedure ?? "",
|
|
402
|
+
hasSecurityAccess: p.HasSecurityAccess === true,
|
|
403
|
+
}));
|
|
404
|
+
if (top !== undefined) {
|
|
405
|
+
return { items, total: response["@odata.count"] };
|
|
406
|
+
}
|
|
407
|
+
return items;
|
|
408
|
+
}
|
|
409
|
+
/**
|
|
410
|
+
* Get the code of all four tabs of a TI process.
|
|
411
|
+
* GET /api/v1/Processes('{name}')
|
|
412
|
+
*/
|
|
413
|
+
async getCode(processName) {
|
|
414
|
+
const path = `/api/v1/Processes('${enc(processName)}')`;
|
|
415
|
+
const response = await this.http.request("GET", path);
|
|
416
|
+
return {
|
|
417
|
+
prolog: response.PrologProcedure,
|
|
418
|
+
metadata: response.MetadataProcedure,
|
|
419
|
+
data: response.DataProcedure,
|
|
420
|
+
epilog: response.EpilogProcedure,
|
|
421
|
+
};
|
|
422
|
+
}
|
|
423
|
+
/**
|
|
424
|
+
* Read deploy-relevant entity metadata not covered by getCode/params/
|
|
425
|
+
* vars/datasource. Currently only HasSecurityAccess (functional elevation).
|
|
426
|
+
* GET /api/v1/Processes('{name}')?$select=HasSecurityAccess
|
|
427
|
+
*/
|
|
428
|
+
async getDeployMeta(processName) {
|
|
429
|
+
const path = `/api/v1/Processes('${enc(processName)}')?$select=HasSecurityAccess`;
|
|
430
|
+
const response = await this.http.request("GET", path);
|
|
431
|
+
return { hasSecurityAccess: response.HasSecurityAccess === true };
|
|
432
|
+
}
|
|
433
|
+
/**
|
|
434
|
+
* Update one or more code tabs of a TI process (partial update).
|
|
435
|
+
* PATCH /api/v1/Processes('{name}') with only the tabs to update.
|
|
436
|
+
*/
|
|
437
|
+
async updateCode(processName, code) {
|
|
438
|
+
const path = `/api/v1/Processes('${enc(processName)}')`;
|
|
439
|
+
const body = {};
|
|
440
|
+
if (code.prolog !== undefined)
|
|
441
|
+
body.PrologProcedure = code.prolog;
|
|
442
|
+
if (code.metadata !== undefined)
|
|
443
|
+
body.MetadataProcedure = code.metadata;
|
|
444
|
+
if (code.data !== undefined)
|
|
445
|
+
body.DataProcedure = code.data;
|
|
446
|
+
if (code.epilog !== undefined)
|
|
447
|
+
body.EpilogProcedure = code.epilog;
|
|
448
|
+
await this.http.request("PATCH", path, body);
|
|
449
|
+
}
|
|
450
|
+
/**
|
|
451
|
+
* Read the whole process code as TM1's native `#region <Tab>` / `#endregion`
|
|
452
|
+
* blob. GET /api/v1/Processes('{name}')/Code/$value (text/plain). Empty tabs
|
|
453
|
+
* are omitted by the server; newlines are CRLF.
|
|
454
|
+
*/
|
|
455
|
+
async getCodeBlob(processName) {
|
|
456
|
+
const path = `/api/v1/Processes('${enc(processName)}')/Code/$value`;
|
|
457
|
+
return this.http.requestRaw("GET", path);
|
|
458
|
+
}
|
|
459
|
+
/**
|
|
460
|
+
* Write the whole process code from a native `#region` blob. PATCH
|
|
461
|
+
* /api/v1/Processes('{name}') { Code }. The server parses the region markers
|
|
462
|
+
* and does a FULL replace of all four tabs — tabs whose region is absent are
|
|
463
|
+
* cleared. `$value` PUT is not supported by TM1, so this JSON PATCH is the
|
|
464
|
+
* only write path.
|
|
465
|
+
*/
|
|
466
|
+
async updateCodeBlob(processName, blob) {
|
|
467
|
+
const path = `/api/v1/Processes('${enc(processName)}')`;
|
|
468
|
+
await this.http.request("PATCH", path, { Code: blob });
|
|
469
|
+
}
|
|
470
|
+
/**
|
|
471
|
+
* Set HasSecurityAccess flag on process.
|
|
472
|
+
* PATCH /api/v1/Processes('{name}') { HasSecurityAccess }.
|
|
473
|
+
*/
|
|
474
|
+
async updateSecurityAccess(processName, hasSecurityAccess) {
|
|
475
|
+
const path = `/api/v1/Processes('${enc(processName)}')`;
|
|
476
|
+
await this.http.request("PATCH", path, {
|
|
477
|
+
HasSecurityAccess: hasSecurityAccess,
|
|
478
|
+
});
|
|
479
|
+
}
|
|
480
|
+
/**
|
|
481
|
+
* Get the data source configuration of a TI process.
|
|
482
|
+
* GET /api/v1/Processes('{name}') and extract the DataSource field.
|
|
483
|
+
*/
|
|
484
|
+
/**
|
|
485
|
+
* Read a process datasource. The ODBC password is redacted by default so it
|
|
486
|
+
* cannot reach the caller or the model; `includeSecrets` returns it verbatim
|
|
487
|
+
* and is meant for export paths that write straight to a file.
|
|
488
|
+
*
|
|
489
|
+
* Measured on 11.8: the value on the wire is a server-bound ciphertext
|
|
490
|
+
* (`W0br…==`) that TM1 stores unchanged when written back, so it survives a
|
|
491
|
+
* round trip on the same instance but decrypts to nothing on another one.
|
|
492
|
+
* TM1 v12 returns the password in plain text.
|
|
493
|
+
*/
|
|
494
|
+
async getDataSource(processName, opts) {
|
|
495
|
+
const path = `/api/v1/Processes('${enc(processName)}')`;
|
|
496
|
+
const response = await this.http.request("GET", path);
|
|
497
|
+
const ds = response.DataSource;
|
|
498
|
+
// ds.Type is a raw string from the OData response. Surface (don't silently
|
|
499
|
+
// swallow) a type this client version doesn't know — a future TM1 API
|
|
500
|
+
// value would otherwise be cast to DataSource["type"] and could break a
|
|
501
|
+
// downstream switch (e.g. the .pro serializer's type map). Pass it through
|
|
502
|
+
// for forward-compat reads, but log so the gap is observable.
|
|
503
|
+
const KNOWN_DATASOURCE_TYPES = [
|
|
504
|
+
"None",
|
|
505
|
+
"TM1CubeView",
|
|
506
|
+
"TM1DimensionSubset",
|
|
507
|
+
"ASCII",
|
|
508
|
+
"ODBC",
|
|
509
|
+
"TM1Process",
|
|
510
|
+
];
|
|
511
|
+
if (!KNOWN_DATASOURCE_TYPES.includes(ds.Type)) {
|
|
512
|
+
this.http.logger.warn({ processName, dataSourceType: ds.Type }, "Unknown TI datasource type from TM1; passing through unchanged");
|
|
513
|
+
}
|
|
514
|
+
return {
|
|
515
|
+
type: ds.Type,
|
|
516
|
+
...(ds.dataSourceNameForServer !== undefined
|
|
517
|
+
? { dataSourceNameForServer: ds.dataSourceNameForServer }
|
|
518
|
+
: {}),
|
|
519
|
+
...(ds.dataSourceNameForClient !== undefined
|
|
520
|
+
? { dataSourceNameForClient: ds.dataSourceNameForClient }
|
|
521
|
+
: {}),
|
|
522
|
+
...(ds.asciiDelimiterType !== undefined
|
|
523
|
+
? { asciiDelimiterType: ds.asciiDelimiterType }
|
|
524
|
+
: {}),
|
|
525
|
+
...(ds.asciiDelimiterChar !== undefined
|
|
526
|
+
? { asciiDelimiterChar: ds.asciiDelimiterChar }
|
|
527
|
+
: {}),
|
|
528
|
+
...(ds.asciiQuoteCharacter !== undefined
|
|
529
|
+
? { asciiQuoteCharacter: ds.asciiQuoteCharacter }
|
|
530
|
+
: {}),
|
|
531
|
+
...(ds.asciiHeaderRecords !== undefined
|
|
532
|
+
? { asciiHeaderRecords: ds.asciiHeaderRecords }
|
|
533
|
+
: {}),
|
|
534
|
+
...(ds.asciiDecimalSeparator !== undefined
|
|
535
|
+
? { asciiDecimalSeparator: ds.asciiDecimalSeparator }
|
|
536
|
+
: {}),
|
|
537
|
+
...(ds.asciiThousandSeparator !== undefined
|
|
538
|
+
? { asciiThousandSeparator: ds.asciiThousandSeparator }
|
|
539
|
+
: {}),
|
|
540
|
+
...(ds.usesUnicode !== undefined ? { usesUnicode: ds.usesUnicode } : {}),
|
|
541
|
+
...(ds.userName !== undefined ? { userName: ds.userName } : {}),
|
|
542
|
+
// Never surface the ODBC datasource password to the caller/LLM — return a
|
|
543
|
+
// presence marker so the field stays observable without leaking the credential.
|
|
544
|
+
...(ds.password !== undefined
|
|
545
|
+
? {
|
|
546
|
+
password: opts?.includeSecrets
|
|
547
|
+
? ds.password
|
|
548
|
+
: ds.password
|
|
549
|
+
? "[redacted]"
|
|
550
|
+
: "",
|
|
551
|
+
}
|
|
552
|
+
: {}),
|
|
553
|
+
...(ds.query !== undefined ? { query: ds.query } : {}),
|
|
554
|
+
...(ds.view !== undefined ? { view: ds.view } : {}),
|
|
555
|
+
...(ds.subset !== undefined ? { subset: ds.subset } : {}),
|
|
556
|
+
};
|
|
557
|
+
}
|
|
558
|
+
/**
|
|
559
|
+
* Bulk-fetch the datasource of every process in one OData call, projected to
|
|
560
|
+
* the few fields data-flow analysis needs (type + source object). Credentials
|
|
561
|
+
* are never selected. Used by tm1_trace_data_flow to detect view-sourced reads
|
|
562
|
+
* that leave no CellGet in the code and so never reach the reference index.
|
|
563
|
+
* GET /api/v1/Processes?$select=Name,DataSource
|
|
564
|
+
*/
|
|
565
|
+
async listDataSources(includeControl = false) {
|
|
566
|
+
const filter = includeControl ? "" : "&$filter=not startswith(Name,'}')";
|
|
567
|
+
const path = `/api/v1/Processes?$select=Name,DataSource${filter}`;
|
|
568
|
+
const response = await this.http.request("GET", path);
|
|
569
|
+
return response.value
|
|
570
|
+
.filter((p) => typeof p.Name === "string")
|
|
571
|
+
.map((p) => {
|
|
572
|
+
const ds = p.DataSource;
|
|
573
|
+
return {
|
|
574
|
+
name: p.Name,
|
|
575
|
+
type: ds?.Type ?? "None",
|
|
576
|
+
...(ds?.dataSourceNameForServer !== undefined
|
|
577
|
+
? { sourceName: ds.dataSourceNameForServer }
|
|
578
|
+
: {}),
|
|
579
|
+
...(ds?.view !== undefined ? { view: ds.view } : {}),
|
|
580
|
+
...(ds?.subset !== undefined ? { subset: ds.subset } : {}),
|
|
581
|
+
};
|
|
582
|
+
});
|
|
583
|
+
}
|
|
584
|
+
/**
|
|
585
|
+
* Update the data source configuration of a TI process.
|
|
586
|
+
* PATCH /api/v1/Processes('{name}') with DataSource object.
|
|
587
|
+
*/
|
|
588
|
+
async updateDataSource(processName, dataSource) {
|
|
589
|
+
const path = `/api/v1/Processes('${enc(processName)}')`;
|
|
590
|
+
const dsBody = { Type: dataSource.type };
|
|
591
|
+
if (dataSource.dataSourceNameForServer !== undefined)
|
|
592
|
+
dsBody.dataSourceNameForServer = dataSource.dataSourceNameForServer;
|
|
593
|
+
if (dataSource.dataSourceNameForClient !== undefined)
|
|
594
|
+
dsBody.dataSourceNameForClient = dataSource.dataSourceNameForClient;
|
|
595
|
+
if (dataSource.asciiDelimiterType !== undefined)
|
|
596
|
+
dsBody.asciiDelimiterType = dataSource.asciiDelimiterType;
|
|
597
|
+
if (dataSource.asciiDelimiterChar !== undefined)
|
|
598
|
+
dsBody.asciiDelimiterChar = dataSource.asciiDelimiterChar;
|
|
599
|
+
if (dataSource.asciiQuoteCharacter !== undefined)
|
|
600
|
+
dsBody.asciiQuoteCharacter = dataSource.asciiQuoteCharacter;
|
|
601
|
+
if (dataSource.asciiHeaderRecords !== undefined)
|
|
602
|
+
dsBody.asciiHeaderRecords = dataSource.asciiHeaderRecords;
|
|
603
|
+
if (dataSource.asciiDecimalSeparator !== undefined)
|
|
604
|
+
dsBody.asciiDecimalSeparator = dataSource.asciiDecimalSeparator;
|
|
605
|
+
if (dataSource.asciiThousandSeparator !== undefined)
|
|
606
|
+
dsBody.asciiThousandSeparator = dataSource.asciiThousandSeparator;
|
|
607
|
+
if (dataSource.usesUnicode !== undefined) {
|
|
608
|
+
if (acceptsUsesUnicode(dataSource.type)) {
|
|
609
|
+
dsBody.usesUnicode = dataSource.usesUnicode;
|
|
610
|
+
}
|
|
611
|
+
else {
|
|
612
|
+
this.http.logger.warn({ processName, dataSourceType: dataSource.type }, "DataSource.usesUnicode applies to ODBC sources only and is being dropped from the PATCH (TM1 rejects it as 'unprocessed properties' for other types)");
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
if (dataSource.userName !== undefined)
|
|
616
|
+
dsBody.userName = dataSource.userName;
|
|
617
|
+
if (dataSource.password !== undefined)
|
|
618
|
+
dsBody.password = dataSource.password;
|
|
619
|
+
if (dataSource.query !== undefined)
|
|
620
|
+
dsBody.query = dataSource.query;
|
|
621
|
+
if (dataSource.view !== undefined)
|
|
622
|
+
dsBody.view = dataSource.view;
|
|
623
|
+
if (dataSource.subset !== undefined)
|
|
624
|
+
dsBody.subset = dataSource.subset;
|
|
625
|
+
await this.http.request("PATCH", path, { DataSource: dsBody });
|
|
626
|
+
}
|
|
627
|
+
/**
|
|
628
|
+
* Get the variables (column-mapped names) of a TI process.
|
|
629
|
+
* GET /api/v1/Processes('{name}')/Variables
|
|
630
|
+
*/
|
|
631
|
+
async getVariables(processName) {
|
|
632
|
+
return (await this.getVariableLayout(processName)).variables;
|
|
633
|
+
}
|
|
634
|
+
/**
|
|
635
|
+
* Variables PLUS the columns the process ignores, in one request.
|
|
636
|
+
*
|
|
637
|
+
* `Variables` alone is an incomplete picture of the datasource: a column set
|
|
638
|
+
* to "Ignore" carries no variable and is simply absent from the list, which
|
|
639
|
+
* is why the remaining positions have gaps. The ignore flag lives in
|
|
640
|
+
* `VariablesUIData` — one entry per source column, undeclared in $metadata on
|
|
641
|
+
* both versions, so it must be named in `$select`.
|
|
642
|
+
*
|
|
643
|
+
* GET /api/v1/Processes('{name}')?$select=Variables,VariablesUIData
|
|
644
|
+
*/
|
|
645
|
+
async getVariableLayout(processName) {
|
|
646
|
+
const path = `/api/v1/Processes('${enc(processName)}')` +
|
|
647
|
+
`?$select=Variables,VariablesUIData`;
|
|
648
|
+
try {
|
|
649
|
+
const r = await this.http.request("GET", path);
|
|
650
|
+
return {
|
|
651
|
+
variables: (r.Variables ?? []).map(decodeVariable),
|
|
652
|
+
ignoredColumns: ignoredColumnsOf(r.VariablesUIData),
|
|
653
|
+
...(r.VariablesUIData !== undefined
|
|
654
|
+
? { variablesUIData: r.VariablesUIData }
|
|
655
|
+
: {}),
|
|
656
|
+
};
|
|
657
|
+
}
|
|
658
|
+
catch (e) {
|
|
659
|
+
rethrowIfSystemic(e);
|
|
660
|
+
if (!isUnsupportedQueryShape(e))
|
|
661
|
+
throw e;
|
|
662
|
+
// A server that will not answer the $select still answers the plain
|
|
663
|
+
// collection — variables without the ignore information beat no answer.
|
|
664
|
+
const response = await this.http.request("GET", `/api/v1/Processes('${enc(processName)}')/Variables`);
|
|
665
|
+
return {
|
|
666
|
+
variables: response.value.map(decodeVariable),
|
|
667
|
+
ignoredColumns: [],
|
|
668
|
+
};
|
|
669
|
+
}
|
|
670
|
+
}
|
|
671
|
+
/**
|
|
672
|
+
* Variables of every process, in ONE request.
|
|
673
|
+
*
|
|
674
|
+
* `Variables` is a complex-typed property, not a navigation collection, so
|
|
675
|
+
* the process list can carry it directly — no `$expand`, and no follow-up
|
|
676
|
+
* call per process. `getVariables` above answers the same question for a
|
|
677
|
+
* single process and stays the right tool when that is all you need.
|
|
678
|
+
*
|
|
679
|
+
* The difference is not cosmetic: asking per process costs one round trip
|
|
680
|
+
* each, which on a 221-process model measured as 221 extra requests against
|
|
681
|
+
* a single 147 KB one. Whole-model analyses (audit_complexity) use this.
|
|
682
|
+
*
|
|
683
|
+
* GET /api/v1/Processes?$select=Name,Variables
|
|
684
|
+
*/
|
|
685
|
+
async getAllVariables(includeControl = false) {
|
|
686
|
+
const filter = includeControl ? "" : "&$filter=not startswith(Name,'}')";
|
|
687
|
+
const path = `/api/v1/Processes?$select=Name,Variables${filter}`;
|
|
688
|
+
const response = await this.http.request("GET", path);
|
|
689
|
+
const byProcess = new Map();
|
|
690
|
+
for (const p of response.value) {
|
|
691
|
+
// A process without variables comes back with the property omitted
|
|
692
|
+
// rather than as an empty array.
|
|
693
|
+
byProcess.set(p.Name, (p.Variables ?? []).map(decodeVariable));
|
|
694
|
+
}
|
|
695
|
+
return byProcess;
|
|
696
|
+
}
|
|
697
|
+
/**
|
|
698
|
+
* Update the variables of a TI process (column-name mapping for ASCII/ODBC sources).
|
|
699
|
+
* Required after setting an ASCII DataSource.
|
|
700
|
+
* PATCH /api/v1/Processes('{name}') with Variables array.
|
|
701
|
+
*/
|
|
702
|
+
async updateVariables(processName, vars, variablesUIData) {
|
|
703
|
+
const path = `/api/v1/Processes('${enc(processName)}')`;
|
|
704
|
+
const body = {
|
|
705
|
+
Variables: vars.map((v) => ({
|
|
706
|
+
Name: v.name,
|
|
707
|
+
Type: v.type,
|
|
708
|
+
Position: v.position,
|
|
709
|
+
StartByte: v.startByte ?? 0,
|
|
710
|
+
EndByte: v.endByte ?? 0,
|
|
711
|
+
})),
|
|
712
|
+
};
|
|
713
|
+
// Patching Variables alone leaves whatever VariablesUIData the process
|
|
714
|
+
// already has (measured on 12.5), which is right for an edit that keeps the
|
|
715
|
+
// column layout and wrong for one that changes it — hence the explicit
|
|
716
|
+
// parameter for callers that carry the source layout (git/.pro import).
|
|
717
|
+
if (variablesUIData !== undefined)
|
|
718
|
+
body.VariablesUIData = variablesUIData;
|
|
719
|
+
await this.http.request("PATCH", path, body);
|
|
720
|
+
}
|
|
721
|
+
/**
|
|
722
|
+
* Update the parameters of a TI process.
|
|
723
|
+
* PATCH /api/v1/Processes('{name}') with Parameters array.
|
|
724
|
+
*/
|
|
725
|
+
async updateParameters(processName, params) {
|
|
726
|
+
const path = `/api/v1/Processes('${enc(processName)}')`;
|
|
727
|
+
const body = {
|
|
728
|
+
Parameters: params.map(encodeParameter),
|
|
729
|
+
};
|
|
730
|
+
await this.http.request("PATCH", path, body);
|
|
731
|
+
}
|
|
732
|
+
/**
|
|
733
|
+
* Delete a TI process.
|
|
734
|
+
* DELETE /api/v1/Processes('{name}')
|
|
735
|
+
*/
|
|
736
|
+
async delete(processName) {
|
|
737
|
+
const path = `/api/v1/Processes('${enc(processName)}')`;
|
|
738
|
+
await this.http.request("DELETE", path);
|
|
739
|
+
}
|
|
740
|
+
/**
|
|
741
|
+
* Compile a saved TI process to check syntax without executing it.
|
|
742
|
+
* POST /api/v1/Processes('{name}')/tm1.Compile
|
|
743
|
+
*/
|
|
744
|
+
async compile(processName) {
|
|
745
|
+
const path = `/api/v1/Processes('${enc(processName)}')/tm1.Compile`;
|
|
746
|
+
try {
|
|
747
|
+
const response = await this.http.request("POST", path, {});
|
|
748
|
+
const errors = (response?.value ?? []).map((e) => ({
|
|
749
|
+
lineNumber: e.LineNumber,
|
|
750
|
+
procedure: e.Procedure,
|
|
751
|
+
message: e.Message ?? "",
|
|
752
|
+
}));
|
|
753
|
+
return { success: errors.length === 0, errors };
|
|
754
|
+
}
|
|
755
|
+
catch (err) {
|
|
756
|
+
// Systemic transport/auth failures must propagate rather than be reported
|
|
757
|
+
// as a compile failure — an outage is not a broken process.
|
|
758
|
+
rethrowIfSystemic(err);
|
|
759
|
+
if (err instanceof TM1Error) {
|
|
760
|
+
return {
|
|
761
|
+
success: false,
|
|
762
|
+
errors: [{ message: err.details ?? err.message }],
|
|
763
|
+
};
|
|
764
|
+
}
|
|
765
|
+
throw err;
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
/**
|
|
769
|
+
* Validate a TI process WITHOUT saving it on the server. Mirrors tm1py's
|
|
770
|
+
* compile_process_with_body. Returns CompileResult identical to compile()
|
|
771
|
+
* for callers that already handle that shape.
|
|
772
|
+
* POST /api/v1/CompileProcess body { Process: <full process body> }
|
|
773
|
+
*/
|
|
774
|
+
async check(input) {
|
|
775
|
+
const path = "/api/v1/CompileProcess";
|
|
776
|
+
const processBody = {
|
|
777
|
+
Name: input.name ?? "_compile_check",
|
|
778
|
+
PrologProcedure: input.prolog ?? "",
|
|
779
|
+
MetadataProcedure: input.metadata ?? "",
|
|
780
|
+
DataProcedure: input.data ?? "",
|
|
781
|
+
EpilogProcedure: input.epilog ?? "",
|
|
782
|
+
};
|
|
783
|
+
if (input.parameters) {
|
|
784
|
+
processBody.Parameters = input.parameters.map(encodeParameter);
|
|
785
|
+
}
|
|
786
|
+
if (input.variables) {
|
|
787
|
+
processBody.Variables = input.variables.map((v) => ({
|
|
788
|
+
Name: v.name,
|
|
789
|
+
Type: v.type,
|
|
790
|
+
Position: v.position,
|
|
791
|
+
StartByte: v.startByte ?? 0,
|
|
792
|
+
EndByte: v.endByte ?? 0,
|
|
793
|
+
}));
|
|
794
|
+
}
|
|
795
|
+
if (input.dataSource) {
|
|
796
|
+
const ds = input.dataSource;
|
|
797
|
+
const dsBody = { Type: ds.type };
|
|
798
|
+
if (ds.dataSourceNameForServer !== undefined)
|
|
799
|
+
dsBody.dataSourceNameForServer = ds.dataSourceNameForServer;
|
|
800
|
+
if (ds.dataSourceNameForClient !== undefined)
|
|
801
|
+
dsBody.dataSourceNameForClient = ds.dataSourceNameForClient;
|
|
802
|
+
if (ds.asciiDelimiterType !== undefined)
|
|
803
|
+
dsBody.asciiDelimiterType = ds.asciiDelimiterType;
|
|
804
|
+
if (ds.asciiDelimiterChar !== undefined)
|
|
805
|
+
dsBody.asciiDelimiterChar = ds.asciiDelimiterChar;
|
|
806
|
+
if (ds.asciiQuoteCharacter !== undefined)
|
|
807
|
+
dsBody.asciiQuoteCharacter = ds.asciiQuoteCharacter;
|
|
808
|
+
if (ds.asciiHeaderRecords !== undefined)
|
|
809
|
+
dsBody.asciiHeaderRecords = ds.asciiHeaderRecords;
|
|
810
|
+
if (ds.asciiDecimalSeparator !== undefined)
|
|
811
|
+
dsBody.asciiDecimalSeparator = ds.asciiDecimalSeparator;
|
|
812
|
+
if (ds.asciiThousandSeparator !== undefined)
|
|
813
|
+
dsBody.asciiThousandSeparator = ds.asciiThousandSeparator;
|
|
814
|
+
// usesUnicode: ODBC-only, on every version — see acceptsUsesUnicode().
|
|
815
|
+
if (ds.usesUnicode !== undefined && acceptsUsesUnicode(ds.type)) {
|
|
816
|
+
dsBody.usesUnicode = ds.usesUnicode;
|
|
817
|
+
}
|
|
818
|
+
if (ds.userName !== undefined)
|
|
819
|
+
dsBody.userName = ds.userName;
|
|
820
|
+
if (ds.password !== undefined)
|
|
821
|
+
dsBody.password = ds.password;
|
|
822
|
+
if (ds.query !== undefined)
|
|
823
|
+
dsBody.query = ds.query;
|
|
824
|
+
if (ds.view !== undefined)
|
|
825
|
+
dsBody.view = ds.view;
|
|
826
|
+
if (ds.subset !== undefined)
|
|
827
|
+
dsBody.subset = ds.subset;
|
|
828
|
+
processBody.DataSource = dsBody;
|
|
829
|
+
}
|
|
830
|
+
else {
|
|
831
|
+
processBody.DataSource = { Type: "None" };
|
|
832
|
+
}
|
|
833
|
+
try {
|
|
834
|
+
const response = await this.http.request("POST", path, { Process: processBody });
|
|
835
|
+
const errors = (response?.value ?? []).map((e) => ({
|
|
836
|
+
lineNumber: e.LineNumber,
|
|
837
|
+
procedure: e.Procedure,
|
|
838
|
+
message: e.Message ?? "",
|
|
839
|
+
}));
|
|
840
|
+
return { success: errors.length === 0, errors };
|
|
841
|
+
}
|
|
842
|
+
catch (err) {
|
|
843
|
+
// Systemic transport/auth failures must propagate rather than be reported
|
|
844
|
+
// as a compile failure — an outage is not a broken process.
|
|
845
|
+
rethrowIfSystemic(err);
|
|
846
|
+
if (err instanceof TM1Error) {
|
|
847
|
+
return {
|
|
848
|
+
success: false,
|
|
849
|
+
errors: [{ message: err.details ?? err.message }],
|
|
850
|
+
};
|
|
851
|
+
}
|
|
852
|
+
throw err;
|
|
853
|
+
}
|
|
854
|
+
}
|
|
855
|
+
}
|
|
856
|
+
/**
|
|
857
|
+
* `usesUnicode` is an ODBC datasource setting, not a version-specific one.
|
|
858
|
+
*
|
|
859
|
+
* It was carried here as "v12-only, TM1 11.x rejects it", which had it exactly
|
|
860
|
+
* backwards. TM1 validates datasource properties per source type: 11.8 rejects
|
|
861
|
+
* usesUnicode for an ASCII source ("unprocessed properties") but accepts it for
|
|
862
|
+
* an ODBC one, returns it from a plain GET, and writes it to the .pro file as
|
|
863
|
+
* line 559 (`usesUnicode: true` → `559,1`, `false` → `559,0`) — measured on
|
|
864
|
+
* both. On 12.5 the property is never returned for any source type, so there is
|
|
865
|
+
* no evidence it exists there; sending it costs nothing, since v12 silently
|
|
866
|
+
* ignores properties it does not know.
|
|
867
|
+
*
|
|
868
|
+
* Gating on the source type therefore serves both versions correctly, which
|
|
869
|
+
* gating on the version never did.
|
|
870
|
+
*/
|
|
871
|
+
function acceptsUsesUnicode(type) {
|
|
872
|
+
return type === "ODBC";
|
|
873
|
+
}
|
|
874
|
+
//# sourceMappingURL=process-service.js.map
|