@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,294 @@
|
|
|
1
|
+
// Cube domain service. Owns the OData calls under /api/v1/Cubes(...) — listing,
|
|
2
|
+
// creating, deleting, rules, clear, unload. Held as `TM1Client.cubes` and
|
|
3
|
+
// reachable from there so call sites read like `client.cubes.list()` rather
|
|
4
|
+
// than `client.getCubes()`. The flat `getCubes/...` methods on TM1Client remain
|
|
5
|
+
// as deprecated wrappers during the migration period (Phase 1 of the
|
|
6
|
+
// god-class split — see docs/ARCHITECTURE.md).
|
|
7
|
+
import { TM1Error, TM1ErrorCode } from "../../types.js";
|
|
8
|
+
import { filterClause, nameFilterPredicates, pageClauses, readCount, } from "./odata-page.js";
|
|
9
|
+
import { classifyExecution } from "./process-status.js";
|
|
10
|
+
// OData key encoder: double ' per OData literal rules, then percent-encode.
|
|
11
|
+
const enc = (s) => encodeURIComponent(String(s).replace(/'/g, "''"));
|
|
12
|
+
export class CubeService {
|
|
13
|
+
http;
|
|
14
|
+
constructor(http) {
|
|
15
|
+
this.http = http;
|
|
16
|
+
}
|
|
17
|
+
async list(opts = {}) {
|
|
18
|
+
// Without a top-level $select TM1 returns every cube property — including
|
|
19
|
+
// the full Rules text — even on the light path. Pin $select=Name so
|
|
20
|
+
// list_cubes (and the other name/dimension-only callers) don't drag every
|
|
21
|
+
// cube's Rules blob over the wire. Only the includeRules path opts Rules in.
|
|
22
|
+
const select = opts.includeRules ? "Name,Rules" : "Name";
|
|
23
|
+
// Filters are only emitted on the paged path. Unpaged callers still get the
|
|
24
|
+
// whole collection and filter in-process, so their behaviour is unchanged.
|
|
25
|
+
const filter = opts.page === undefined ? "" : filterClause(nameFilterPredicates(opts));
|
|
26
|
+
const path = `/api/v1/Cubes?$select=${select}&$expand=Dimensions($select=Name)` +
|
|
27
|
+
`${filter}${pageClauses(opts.page)}`;
|
|
28
|
+
const response = await this.http.request("GET", path);
|
|
29
|
+
const items = response.value.map((c) => {
|
|
30
|
+
const cube = {
|
|
31
|
+
name: c.Name,
|
|
32
|
+
dimensions: c.Dimensions.map((d) => d.Name),
|
|
33
|
+
};
|
|
34
|
+
if (opts.includeRules) {
|
|
35
|
+
cube.hasRules = !!(c.Rules && c.Rules.trim().length > 0);
|
|
36
|
+
}
|
|
37
|
+
return cube;
|
|
38
|
+
});
|
|
39
|
+
return opts.page === undefined
|
|
40
|
+
? items
|
|
41
|
+
: { items, total: readCount(response) };
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Return ordered dimension-name list of a cube.
|
|
45
|
+
* GET /api/v1/Cubes('{name}')?$expand=Dimensions($select=Name)
|
|
46
|
+
*/
|
|
47
|
+
async getDimensionNames(cubeName) {
|
|
48
|
+
const path = `/api/v1/Cubes('${enc(cubeName)}')?$expand=Dimensions($select=Name)`;
|
|
49
|
+
const response = await this.http.request("GET", path);
|
|
50
|
+
return response.Dimensions.map((d) => d.Name);
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Cheap existence probe: a single GET with $select=Name (404 → false)
|
|
54
|
+
* instead of list(), which pulls every cube plus its dimensions just to
|
|
55
|
+
* check one name. Rethrows anything that isn't NOT_FOUND — in particular a
|
|
56
|
+
* denial, which is "you may not look", not "it is not there".
|
|
57
|
+
*
|
|
58
|
+
* Structural on purpose. The alternative — reading existence out of the
|
|
59
|
+
* error sentence of a failed query — is wrong on any server whose version
|
|
60
|
+
* or locale words that sentence differently, and TM1 does both.
|
|
61
|
+
* GET /api/v1/Cubes('{name}')?$select=Name
|
|
62
|
+
*/
|
|
63
|
+
async exists(cubeName) {
|
|
64
|
+
try {
|
|
65
|
+
await this.http.request("GET", `/api/v1/Cubes('${enc(cubeName)}')?$select=Name`);
|
|
66
|
+
return true;
|
|
67
|
+
}
|
|
68
|
+
catch (e) {
|
|
69
|
+
if (e instanceof TM1Error && e.code === TM1ErrorCode.NOT_FOUND)
|
|
70
|
+
return false;
|
|
71
|
+
throw e;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Create a new cube with the given dimensions (in order).
|
|
76
|
+
* POST /api/v1/Cubes
|
|
77
|
+
*/
|
|
78
|
+
async create(name, dimensionNames) {
|
|
79
|
+
await this.http.request("POST", "/api/v1/Cubes", {
|
|
80
|
+
Name: name,
|
|
81
|
+
Dimensions: dimensionNames.map((d) => ({
|
|
82
|
+
"@odata.id": `Dimensions('${enc(d)}')`,
|
|
83
|
+
})),
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Delete a cube.
|
|
88
|
+
* DELETE /api/v1/Cubes('{name}')
|
|
89
|
+
*/
|
|
90
|
+
async delete(name) {
|
|
91
|
+
await this.http.request("DELETE", `/api/v1/Cubes('${enc(name)}')`);
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Get the rules text for a cube.
|
|
95
|
+
* GET /api/v1/Cubes('{name}')/Rules
|
|
96
|
+
*/
|
|
97
|
+
async getRules(cubeName) {
|
|
98
|
+
const path = `/api/v1/Cubes('${enc(cubeName)}')/Rules`;
|
|
99
|
+
// TM1 returns 404/204 both for "cube missing" and "cube has no rules";
|
|
100
|
+
// an empty 200 body (response undefined) also means "no rules". For any
|
|
101
|
+
// of those, probe `/Cubes('X')?$select=Name` to disambiguate so callers
|
|
102
|
+
// get a clear NOT_FOUND for typos instead of a silently-empty rulesText.
|
|
103
|
+
const empty = async () => {
|
|
104
|
+
try {
|
|
105
|
+
await this.http.request("GET", `/api/v1/Cubes('${enc(cubeName)}')?$select=Name`);
|
|
106
|
+
}
|
|
107
|
+
catch (probeErr) {
|
|
108
|
+
if (probeErr instanceof TM1Error && probeErr.httpStatus === 404) {
|
|
109
|
+
throw new TM1Error({
|
|
110
|
+
code: TM1ErrorCode.NOT_FOUND,
|
|
111
|
+
message: `Cube '${cubeName}' does not exist.`,
|
|
112
|
+
httpStatus: 404,
|
|
113
|
+
endpoint: `/api/v1/Cubes('${cubeName}')`,
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
throw probeErr;
|
|
117
|
+
}
|
|
118
|
+
return { cubeName, rulesText: "", skipCheck: false };
|
|
119
|
+
};
|
|
120
|
+
try {
|
|
121
|
+
// TM1 11.8 returns rules text in the "value" field (not "Text")
|
|
122
|
+
const response = await this.http.request("GET", path);
|
|
123
|
+
const rulesText = response?.value ?? response?.Text ?? "";
|
|
124
|
+
if (rulesText === "")
|
|
125
|
+
return empty();
|
|
126
|
+
return {
|
|
127
|
+
cubeName,
|
|
128
|
+
rulesText,
|
|
129
|
+
skipCheck: rulesText.toUpperCase().includes("SKIPCHECK"),
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
catch (err) {
|
|
133
|
+
if (err instanceof TM1Error &&
|
|
134
|
+
(err.httpStatus === 404 || err.httpStatus === 204)) {
|
|
135
|
+
return empty();
|
|
136
|
+
}
|
|
137
|
+
throw err;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
async getAllRules(arg = false, top) {
|
|
141
|
+
const opts = typeof arg === "object" ? arg : { includeControl: arg };
|
|
142
|
+
const filter = opts.includeControl
|
|
143
|
+
? ""
|
|
144
|
+
: "&$filter=not startswith(Name,'}')";
|
|
145
|
+
const expand = opts.withDimensions
|
|
146
|
+
? "&$expand=Dimensions($select=Name)"
|
|
147
|
+
: "";
|
|
148
|
+
const cap = top !== undefined ? `&$orderby=Name&$top=${top}&$count=true` : "";
|
|
149
|
+
const path = `/api/v1/Cubes?$select=Name,Rules${expand}${filter}${cap}`;
|
|
150
|
+
const response = await this.http.request("GET", path);
|
|
151
|
+
const items = response.value.map((c) => {
|
|
152
|
+
const rulesText = c.Rules ?? "";
|
|
153
|
+
return {
|
|
154
|
+
cubeName: c.Name,
|
|
155
|
+
rulesText,
|
|
156
|
+
skipCheck: rulesText.toUpperCase().includes("SKIPCHECK"),
|
|
157
|
+
...(c.Dimensions
|
|
158
|
+
? { dimensions: c.Dimensions.map((d) => d.Name) }
|
|
159
|
+
: {}),
|
|
160
|
+
};
|
|
161
|
+
});
|
|
162
|
+
if (top !== undefined) {
|
|
163
|
+
return { items, total: response["@odata.count"] };
|
|
164
|
+
}
|
|
165
|
+
return items;
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Create or replace the rules for a cube.
|
|
169
|
+
* TM1 11.8 sets rules by PATCHing the Cube entity ({Rules: "...text..."}).
|
|
170
|
+
* PATCH/POST on /Cubes('{name}')/Rules returns 400 "not supported".
|
|
171
|
+
*
|
|
172
|
+
* There is no skipcheck switch to pass: SKIPCHECK is a line inside the rules
|
|
173
|
+
* text, so it travels in `rulesText` like every other statement.
|
|
174
|
+
*/
|
|
175
|
+
async updateRules(cubeName, rulesText) {
|
|
176
|
+
const cubePath = `/api/v1/Cubes('${enc(cubeName)}')`;
|
|
177
|
+
await this.http.request("PATCH", cubePath, { Rules: rulesText });
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Validate cube rule syntax without applying. Empty array = valid.
|
|
181
|
+
* POST /api/v1/Cubes('{name}')/tm1.CheckRules with { Rules: "..." }
|
|
182
|
+
*/
|
|
183
|
+
async checkRule(cubeName, ruleText) {
|
|
184
|
+
const path = `/api/v1/Cubes('${enc(cubeName)}')/tm1.CheckRules`;
|
|
185
|
+
const response = await this.http.request("POST", path, { Rules: ruleText });
|
|
186
|
+
return (response.value ?? []).map((e) => ({
|
|
187
|
+
message: e.Message,
|
|
188
|
+
...(e.LineNumber !== undefined ? { lineNumber: e.LineNumber } : {}),
|
|
189
|
+
}));
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Clear cube cells.
|
|
193
|
+
*
|
|
194
|
+
* A **full** clear runs an ephemeral TI with CubeClearData(). tm1.Clear is
|
|
195
|
+
* not an alternative on either build: 11.8 and 12.5 both answer
|
|
196
|
+
* "'tm1.Clear' resource can not be resolved on type 'Cube'" for a cube that
|
|
197
|
+
* exists, and neither declares a clear action anywhere in $metadata — Cube
|
|
198
|
+
* carries only Lock and Unlock. CubeClearData() is the only route measured
|
|
199
|
+
* to work.
|
|
200
|
+
*
|
|
201
|
+
* A **partial** clear would need tuple selectors, which only tm1.Clear
|
|
202
|
+
* offers, so no server reachable here can do one. Callers get
|
|
203
|
+
* UNSUPPORTED_OPERATION pointing at bedrock `}bedrock.cube.data.clear`
|
|
204
|
+
* rather than a request that is known to 404.
|
|
205
|
+
*/
|
|
206
|
+
async clear(cubeName, dimensions, tuples) {
|
|
207
|
+
const isFullClear = dimensions.every((_, i) => (tuples[i] ?? []).length === 0);
|
|
208
|
+
if (!isFullClear)
|
|
209
|
+
throw this.partialClearUnsupported(cubeName);
|
|
210
|
+
await this.clearViaTI(cubeName);
|
|
211
|
+
}
|
|
212
|
+
/** Same verdict for both versions: no tuple-selective clear on this server. */
|
|
213
|
+
partialClearUnsupported(cubeName) {
|
|
214
|
+
return new TM1Error({
|
|
215
|
+
code: TM1ErrorCode.UNSUPPORTED_OPERATION,
|
|
216
|
+
message: `Partial clearCube is not supported on TM1 ${this.http.tm1Version} (no tm1.Clear endpoint). Implement a TI process with bedrock '}bedrock.cube.data.clear' or custom CellPutN loop and call via tm1_execute_process.`,
|
|
217
|
+
endpoint: `/api/v1/Cubes('${cubeName}')/tm1.Clear`,
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Unload a cube from memory. Forces TM1 to discard the in-memory fed-cell
|
|
222
|
+
* index and reload from disk on next access. Required for feeder corrections
|
|
223
|
+
* to take effect — the fed-cell index is cumulative, so changes to existing
|
|
224
|
+
* feeders only become visible after an unload.
|
|
225
|
+
* POST /api/v1/Cubes('{cube}')/tm1.Unload
|
|
226
|
+
*/
|
|
227
|
+
async unload(cubeName) {
|
|
228
|
+
await this.http.request("POST", `/api/v1/Cubes('${enc(cubeName)}')/tm1.Unload`);
|
|
229
|
+
}
|
|
230
|
+
// 11.x fallback: deploy ephemeral TI with CubeClearData(), execute, delete.
|
|
231
|
+
async clearViaTI(cubeName) {
|
|
232
|
+
// Cap the sanitized cube name so the temp process name stays under TM1's
|
|
233
|
+
// ~256-char process-name limit (prefix + timestamp suffix add ~25 chars).
|
|
234
|
+
const safeName = cubeName.replace(/[^A-Za-z0-9_]/g, "_").slice(0, 200);
|
|
235
|
+
const procName = `}TempClear_${safeName}_${Date.now()}`;
|
|
236
|
+
const safeCube = cubeName.replace(/'/g, "''");
|
|
237
|
+
const prologCode = `CubeClearData('${safeCube}');`;
|
|
238
|
+
await this.http.request("POST", "/api/v1/Processes", {
|
|
239
|
+
Name: procName,
|
|
240
|
+
HasSecurityAccess: false,
|
|
241
|
+
PrologProcedure: prologCode,
|
|
242
|
+
MetadataProcedure: "",
|
|
243
|
+
DataProcedure: "",
|
|
244
|
+
EpilogProcedure: "",
|
|
245
|
+
DataSource: { Type: "None" },
|
|
246
|
+
});
|
|
247
|
+
try {
|
|
248
|
+
const result = await this.http.request("POST", `/api/v1/Processes('${enc(procName)}')/tm1.ExecuteWithReturn`, {});
|
|
249
|
+
// ExecuteWithReturn returns HTTP 200 even when the process aborts; the real
|
|
250
|
+
// outcome is in ProcessExecuteStatusCode. Without this check an aborted
|
|
251
|
+
// clear (e.g. lock, security) would be reported as a successful clear.
|
|
252
|
+
//
|
|
253
|
+
// This shares `classifyExecution` with ProcessService rather than
|
|
254
|
+
// re-deriving `status !== "CompletedSuccessfully"`, because the three
|
|
255
|
+
// groups mean three different things for a caller holding a cube:
|
|
256
|
+
//
|
|
257
|
+
// committed — the CubeClearData DID commit (measured: the committed
|
|
258
|
+
// statuses leave writes in place). Raising here would tell
|
|
259
|
+
// the model the cube still holds its data when it does
|
|
260
|
+
// not — the exact false reading this split exists to
|
|
261
|
+
// prevent — so the clear stands and the status goes to the
|
|
262
|
+
// log instead. Only reachable if TM1 attaches messages to
|
|
263
|
+
// a one-line CubeClearData prolog; not observed live.
|
|
264
|
+
// rolled back — nothing was cleared; the cube is untouched.
|
|
265
|
+
// indeterminate — no status code, or one this build cannot place
|
|
266
|
+
// (T-4). Unverified, and for a destructive operation that
|
|
267
|
+
// has to surface. A live v11/v12 server always sends the
|
|
268
|
+
// field (see tests/live/process.live.test.ts), so this is
|
|
269
|
+
// the defensive branch, not the normal path.
|
|
270
|
+
const verdict = classifyExecution(result?.ProcessExecuteStatusCode, undefined);
|
|
271
|
+
if (verdict.outcome === "completed_with_errors") {
|
|
272
|
+
this.http.logger.warn({ cube: cubeName, status: verdict.processErrorStatus }, "Cube clear via TI committed but TM1 reported a non-clean status; the cube IS cleared");
|
|
273
|
+
}
|
|
274
|
+
else if (verdict.outcome !== "succeeded") {
|
|
275
|
+
throw new TM1Error({
|
|
276
|
+
code: TM1ErrorCode.TM1_ERROR,
|
|
277
|
+
message: verdict.outcome === "rolled_back"
|
|
278
|
+
? `Cube clear via TI was rolled back for cube '${cubeName}' (status: ${verdict.processErrorStatus}). Nothing was cleared — the cube is unchanged.`
|
|
279
|
+
: `Cube clear via TI could not be confirmed for cube '${cubeName}': ${verdict.processErrorStatus} The clear may or may not have run — check the cube before retrying.`,
|
|
280
|
+
endpoint: `/api/v1/Processes('${enc(procName)}')/tm1.ExecuteWithReturn`,
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
finally {
|
|
285
|
+
try {
|
|
286
|
+
await this.http.request("DELETE", `/api/v1/Processes('${enc(procName)}')`);
|
|
287
|
+
}
|
|
288
|
+
catch (cleanupErr) {
|
|
289
|
+
this.http.logger.warn({ proc: procName, err: String(cleanupErr) }, "Failed to delete ephemeral clearCube TI process — manual cleanup needed");
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
//# sourceMappingURL=cube-service.js.map
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import type { Dimension } from "../../types.js";
|
|
2
|
+
import type { TM1HttpClient } from "../http.js";
|
|
3
|
+
import { type NameFilterOpts, type Paged, type PageOpts } from "./odata-page.js";
|
|
4
|
+
export type DefaultMemberSource = "defined" | "single_root" | "first_root" | "index_1";
|
|
5
|
+
export interface DefaultMemberResolution {
|
|
6
|
+
dimension: string;
|
|
7
|
+
hierarchy: string;
|
|
8
|
+
resolved: {
|
|
9
|
+
name: string;
|
|
10
|
+
level: number;
|
|
11
|
+
};
|
|
12
|
+
source: DefaultMemberSource;
|
|
13
|
+
confidence: "high" | "medium" | "low";
|
|
14
|
+
alternatives?: {
|
|
15
|
+
roots: Array<{
|
|
16
|
+
name: string;
|
|
17
|
+
level: number;
|
|
18
|
+
}>;
|
|
19
|
+
indexOne?: string;
|
|
20
|
+
};
|
|
21
|
+
warning?: string;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Decode a TM1 `}DimensionProperties.LAST_TIME_UPDATED` cell — a 14-digit
|
|
25
|
+
* `YYYYMMDDHHMMSS` stamp in server-local time — to a naive-local ISO string
|
|
26
|
+
* (no trailing `Z`, because the value carries no timezone). Returns null for
|
|
27
|
+
* blank or non-conforming values.
|
|
28
|
+
*/
|
|
29
|
+
export declare function decodeTm1Timestamp(raw: string | number | null | undefined): string | null;
|
|
30
|
+
/**
|
|
31
|
+
* Normalize a user `changedSince` filter (a date or datetime, interpreted as
|
|
32
|
+
* server-local — same basis as LAST_TIME_UPDATED) into the 14-digit form so
|
|
33
|
+
* the two compare by plain string ordering. Date-only pads to start-of-day;
|
|
34
|
+
* partial times pad missing fields with zero. Throws on fewer than 8 date
|
|
35
|
+
* digits (need at least a full YYYY-MM-DD).
|
|
36
|
+
*/
|
|
37
|
+
export declare function normalizeChangedSince(input: string): string;
|
|
38
|
+
export interface DimensionListOpts extends NameFilterOpts {
|
|
39
|
+
includeElementCount?: boolean;
|
|
40
|
+
includeElementStats?: boolean;
|
|
41
|
+
/** Set to slice server-side. Only legal when every active filter is in NameFilterOpts. */
|
|
42
|
+
page?: PageOpts;
|
|
43
|
+
}
|
|
44
|
+
export declare class DimensionService {
|
|
45
|
+
private readonly http;
|
|
46
|
+
constructor(http: TM1HttpClient);
|
|
47
|
+
/**
|
|
48
|
+
* List all dimensions with their hierarchy names.
|
|
49
|
+
* GET /api/v1/Dimensions?$expand=Hierarchies($select=Name)
|
|
50
|
+
*
|
|
51
|
+
* When opts.includeElementCount is true, the expand also requests
|
|
52
|
+
* `Elements($count=true;$top=0)` so each Hierarchy returns
|
|
53
|
+
* `Elements@odata.count` without paying for the full element list.
|
|
54
|
+
* Single round-trip — drop-in for audit workflows that previously
|
|
55
|
+
* called getHierarchy() N times just to size dimensions.
|
|
56
|
+
*
|
|
57
|
+
* When opts.includeElementStats is true, the expand fetches every
|
|
58
|
+
* Element's Type+Level so we can aggregate per-Type counts and maxLevel
|
|
59
|
+
* client-side. TM1 OData rejects `Type eq 'Numeric'` ($filter on enum
|
|
60
|
+
* properties) and exposes no nested `$apply=groupby`, so a single
|
|
61
|
+
* full-element scan is the cheapest path — still one round-trip, payload
|
|
62
|
+
* scales with total element count across all dimensions.
|
|
63
|
+
* Takes precedence over includeElementCount when both are set.
|
|
64
|
+
*/
|
|
65
|
+
list(opts?: {
|
|
66
|
+
includeElementCount?: boolean;
|
|
67
|
+
includeElementStats?: boolean;
|
|
68
|
+
}): Promise<Dimension[]>;
|
|
69
|
+
/**
|
|
70
|
+
* Paged variant: with `page` set the *outer* /Dimensions collection is
|
|
71
|
+
* sliced server-side, which is the only lever that bounds the
|
|
72
|
+
* includeElementStats payload — a 340-dimension model measured 218 MB on the
|
|
73
|
+
* full scan versus 101 MB for the first 50-dimension page. The nested
|
|
74
|
+
* Elements expand is still unbounded per dimension (TM1 has no nested
|
|
75
|
+
* aggregate that would give Type/Level counts without listing elements), so
|
|
76
|
+
* the win is proportional to how many dimensions the page holds, not
|
|
77
|
+
* constant.
|
|
78
|
+
*/
|
|
79
|
+
list(opts: DimensionListOpts & {
|
|
80
|
+
page: PageOpts;
|
|
81
|
+
}): Promise<Paged<Dimension>>;
|
|
82
|
+
/**
|
|
83
|
+
* Create a new dimension. TM1 11.8 does not auto-create the default
|
|
84
|
+
* hierarchy from the POST body — we issue an explicit follow-up POST
|
|
85
|
+
* and tolerate 409 (some versions create it automatically).
|
|
86
|
+
* POST /api/v1/Dimensions
|
|
87
|
+
*/
|
|
88
|
+
create(name: string): Promise<void>;
|
|
89
|
+
/**
|
|
90
|
+
* Delete a dimension and all its hierarchies.
|
|
91
|
+
* DELETE /api/v1/Dimensions('{name}')
|
|
92
|
+
*/
|
|
93
|
+
delete(name: string): Promise<void>;
|
|
94
|
+
/**
|
|
95
|
+
* Read per-dimension last-modified timestamps from the `}DimensionProperties`
|
|
96
|
+
* control cube (`LAST_TIME_UPDATED` measure) in a single MDX round-trip.
|
|
97
|
+
* Returns a Map of dimension name → raw `YYYYMMDDHHMMSS` string (server-local);
|
|
98
|
+
* decode with decodeTm1Timestamp(). Dimensions with a blank stamp are absent
|
|
99
|
+
* from the map. This is a schema-change stamp (structure), bumped on element /
|
|
100
|
+
* hierarchy / attribute edits — not a data-write stamp.
|
|
101
|
+
*/
|
|
102
|
+
getLastUpdatedMap(): Promise<Map<string, string>>;
|
|
103
|
+
/**
|
|
104
|
+
* Resolve a hierarchy's effective default member via a tiered cascade.
|
|
105
|
+
* Designed for view/slicer construction where iterating tm1_get_hierarchy
|
|
106
|
+
* across levels costs 3-8 round-trips per dimension.
|
|
107
|
+
*
|
|
108
|
+
* Tier 1: DefaultMember attribute (high confidence — explicitly maintained).
|
|
109
|
+
* Tier 2: parentless roots (derived, not maintained) — single or multiple = medium.
|
|
110
|
+
* Tier 3: insertion-order index 1 fallback (low confidence — flat/cyclic hierarchies).
|
|
111
|
+
*
|
|
112
|
+
* The `source` field tells callers whether the value is authoritative or inferred.
|
|
113
|
+
* `alternatives.roots` is populated when multiple roots exist so callers can
|
|
114
|
+
* disambiguate without a second round-trip.
|
|
115
|
+
*/
|
|
116
|
+
resolveDefaultMember(dimensionName: string, hierarchyName?: string): Promise<DefaultMemberResolution>;
|
|
117
|
+
}
|
|
118
|
+
//# sourceMappingURL=dimension-service.d.ts.map
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
// Dimension domain service. Owns the OData calls under /api/v1/Dimensions(...) —
|
|
2
|
+
// list, create, delete. Hierarchy and element operations live in their own
|
|
3
|
+
// sibling services. See docs/ARCHITECTURE.md for the layering.
|
|
4
|
+
import { TM1Error, TM1ErrorCode } from "../../types.js";
|
|
5
|
+
import { freeCellset } from "./cellset-transform.js";
|
|
6
|
+
import { filterClause, nameFilterPredicates, pageClauses, readCount, } from "./odata-page.js";
|
|
7
|
+
// OData key encoder: double ' per OData literal rules, then percent-encode.
|
|
8
|
+
const enc = (s) => encodeURIComponent(String(s).replace(/'/g, "''"));
|
|
9
|
+
/**
|
|
10
|
+
* Decode a TM1 `}DimensionProperties.LAST_TIME_UPDATED` cell — a 14-digit
|
|
11
|
+
* `YYYYMMDDHHMMSS` stamp in server-local time — to a naive-local ISO string
|
|
12
|
+
* (no trailing `Z`, because the value carries no timezone). Returns null for
|
|
13
|
+
* blank or non-conforming values.
|
|
14
|
+
*/
|
|
15
|
+
export function decodeTm1Timestamp(raw) {
|
|
16
|
+
if (raw === null || raw === undefined)
|
|
17
|
+
return null;
|
|
18
|
+
const s = String(raw).trim();
|
|
19
|
+
if (!/^\d{14}$/.test(s))
|
|
20
|
+
return null;
|
|
21
|
+
return (`${s.slice(0, 4)}-${s.slice(4, 6)}-${s.slice(6, 8)}` +
|
|
22
|
+
`T${s.slice(8, 10)}:${s.slice(10, 12)}:${s.slice(12, 14)}`);
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Normalize a user `changedSince` filter (a date or datetime, interpreted as
|
|
26
|
+
* server-local — same basis as LAST_TIME_UPDATED) into the 14-digit form so
|
|
27
|
+
* the two compare by plain string ordering. Date-only pads to start-of-day;
|
|
28
|
+
* partial times pad missing fields with zero. Throws on fewer than 8 date
|
|
29
|
+
* digits (need at least a full YYYY-MM-DD).
|
|
30
|
+
*/
|
|
31
|
+
export function normalizeChangedSince(input) {
|
|
32
|
+
const digits = input.replace(/\D/g, "");
|
|
33
|
+
if (digits.length < 8) {
|
|
34
|
+
throw new TM1Error({
|
|
35
|
+
code: TM1ErrorCode.VALIDATION_ERROR,
|
|
36
|
+
message: `Invalid changedSince '${input}': need at least a full date (e.g. 2026-04-01).`,
|
|
37
|
+
details: input,
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
return digits.padEnd(14, "0").slice(0, 14);
|
|
41
|
+
}
|
|
42
|
+
export class DimensionService {
|
|
43
|
+
http;
|
|
44
|
+
constructor(http) {
|
|
45
|
+
this.http = http;
|
|
46
|
+
}
|
|
47
|
+
async list(opts = {}) {
|
|
48
|
+
let expand;
|
|
49
|
+
if (opts?.includeElementStats) {
|
|
50
|
+
expand = "Hierarchies($select=Name;$expand=Elements($select=Type,Level))";
|
|
51
|
+
}
|
|
52
|
+
else if (opts?.includeElementCount) {
|
|
53
|
+
expand = "Hierarchies($select=Name;$expand=Elements($count=true;$top=0))";
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
expand = "Hierarchies($select=Name)";
|
|
57
|
+
}
|
|
58
|
+
// Filters are only emitted on the paged path; unpaged callers keep getting
|
|
59
|
+
// the whole collection and filter in-process, so nothing changes for them.
|
|
60
|
+
const filter = opts.page === undefined ? "" : filterClause(nameFilterPredicates(opts));
|
|
61
|
+
const path = `/api/v1/Dimensions?$expand=${expand}${filter}${pageClauses(opts.page)}`;
|
|
62
|
+
const response = await this.http.request("GET", path);
|
|
63
|
+
const items = response.value.map((d) => {
|
|
64
|
+
const dim = {
|
|
65
|
+
name: d.Name,
|
|
66
|
+
hierarchies: d.Hierarchies.map((h) => h.Name),
|
|
67
|
+
};
|
|
68
|
+
if (opts?.includeElementStats) {
|
|
69
|
+
dim.elementStats = Object.fromEntries(d.Hierarchies.map((h) => {
|
|
70
|
+
const elements = h.Elements ?? [];
|
|
71
|
+
let numeric = 0;
|
|
72
|
+
let consolidated = 0;
|
|
73
|
+
let stringCount = 0;
|
|
74
|
+
let maxLevel = 0;
|
|
75
|
+
for (const e of elements) {
|
|
76
|
+
if (e.Type === "Numeric")
|
|
77
|
+
numeric++;
|
|
78
|
+
else if (e.Type === "Consolidated")
|
|
79
|
+
consolidated++;
|
|
80
|
+
else if (e.Type === "String")
|
|
81
|
+
stringCount++;
|
|
82
|
+
if (e.Level > maxLevel)
|
|
83
|
+
maxLevel = e.Level;
|
|
84
|
+
}
|
|
85
|
+
return [
|
|
86
|
+
h.Name,
|
|
87
|
+
{
|
|
88
|
+
total: elements.length,
|
|
89
|
+
numeric,
|
|
90
|
+
consolidated,
|
|
91
|
+
string: stringCount,
|
|
92
|
+
maxLevel,
|
|
93
|
+
},
|
|
94
|
+
];
|
|
95
|
+
}));
|
|
96
|
+
}
|
|
97
|
+
else if (opts?.includeElementCount) {
|
|
98
|
+
dim.elementCounts = Object.fromEntries(d.Hierarchies.map((h) => [h.Name, h["Elements@odata.count"] ?? 0]));
|
|
99
|
+
}
|
|
100
|
+
return dim;
|
|
101
|
+
});
|
|
102
|
+
return opts.page === undefined
|
|
103
|
+
? items
|
|
104
|
+
: { items, total: readCount(response) };
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Create a new dimension. TM1 11.8 does not auto-create the default
|
|
108
|
+
* hierarchy from the POST body — we issue an explicit follow-up POST
|
|
109
|
+
* and tolerate 409 (some versions create it automatically).
|
|
110
|
+
* POST /api/v1/Dimensions
|
|
111
|
+
*/
|
|
112
|
+
async create(name) {
|
|
113
|
+
await this.http.request("POST", "/api/v1/Dimensions", { Name: name });
|
|
114
|
+
try {
|
|
115
|
+
await this.http.request("POST", `/api/v1/Dimensions('${enc(name)}')/Hierarchies`, { Name: name });
|
|
116
|
+
}
|
|
117
|
+
catch (err) {
|
|
118
|
+
if (err instanceof TM1Error && err.httpStatus === 409) {
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
throw err;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Delete a dimension and all its hierarchies.
|
|
126
|
+
* DELETE /api/v1/Dimensions('{name}')
|
|
127
|
+
*/
|
|
128
|
+
async delete(name) {
|
|
129
|
+
await this.http.request("DELETE", `/api/v1/Dimensions('${enc(name)}')`);
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Read per-dimension last-modified timestamps from the `}DimensionProperties`
|
|
133
|
+
* control cube (`LAST_TIME_UPDATED` measure) in a single MDX round-trip.
|
|
134
|
+
* Returns a Map of dimension name → raw `YYYYMMDDHHMMSS` string (server-local);
|
|
135
|
+
* decode with decodeTm1Timestamp(). Dimensions with a blank stamp are absent
|
|
136
|
+
* from the map. This is a schema-change stamp (structure), bumped on element /
|
|
137
|
+
* hierarchy / attribute edits — not a data-write stamp.
|
|
138
|
+
*/
|
|
139
|
+
async getLastUpdatedMap() {
|
|
140
|
+
const mdx = "SELECT {[}DimensionProperties].[LAST_TIME_UPDATED]} ON 0, " +
|
|
141
|
+
"NON EMPTY [}Dimensions].MEMBERS ON 1 FROM [}DimensionProperties]";
|
|
142
|
+
const res = await this.http.request("POST", "/api/v1/ExecuteMDX?$expand=Cells($select=Value),Axes($expand=Tuples($expand=Members($select=Name)))", { MDX: mdx });
|
|
143
|
+
try {
|
|
144
|
+
const map = new Map();
|
|
145
|
+
const rows = res.Axes?.[1]?.Tuples ?? [];
|
|
146
|
+
rows.forEach((tuple, i) => {
|
|
147
|
+
const name = tuple.Members[0]?.Name;
|
|
148
|
+
const value = res.Cells[i]?.Value;
|
|
149
|
+
if (name && value != null && String(value).trim() !== "") {
|
|
150
|
+
map.set(name, String(value));
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
return map;
|
|
154
|
+
}
|
|
155
|
+
finally {
|
|
156
|
+
// Free the session-scoped cellset best-effort so this metadata read doesn't
|
|
157
|
+
// leak TM1 server memory while keep-alive holds the session open.
|
|
158
|
+
await freeCellset(this.http, res.ID);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Resolve a hierarchy's effective default member via a tiered cascade.
|
|
163
|
+
* Designed for view/slicer construction where iterating tm1_get_hierarchy
|
|
164
|
+
* across levels costs 3-8 round-trips per dimension.
|
|
165
|
+
*
|
|
166
|
+
* Tier 1: DefaultMember attribute (high confidence — explicitly maintained).
|
|
167
|
+
* Tier 2: parentless roots (derived, not maintained) — single or multiple = medium.
|
|
168
|
+
* Tier 3: insertion-order index 1 fallback (low confidence — flat/cyclic hierarchies).
|
|
169
|
+
*
|
|
170
|
+
* The `source` field tells callers whether the value is authoritative or inferred.
|
|
171
|
+
* `alternatives.roots` is populated when multiple roots exist so callers can
|
|
172
|
+
* disambiguate without a second round-trip.
|
|
173
|
+
*/
|
|
174
|
+
async resolveDefaultMember(dimensionName, hierarchyName) {
|
|
175
|
+
const hier = hierarchyName ?? dimensionName;
|
|
176
|
+
const base = `/api/v1/Dimensions('${enc(dimensionName)}')/Hierarchies('${enc(hier)}')`;
|
|
177
|
+
// Tier 1: explicit DefaultMember attribute.
|
|
178
|
+
try {
|
|
179
|
+
const dm = await this.http.request("GET", `${base}/DefaultMember?$select=Name,Level`);
|
|
180
|
+
if (dm && dm.Name) {
|
|
181
|
+
return {
|
|
182
|
+
dimension: dimensionName,
|
|
183
|
+
hierarchy: hier,
|
|
184
|
+
resolved: { name: dm.Name, level: dm.Level ?? 0 },
|
|
185
|
+
source: "defined",
|
|
186
|
+
confidence: "high",
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
catch (err) {
|
|
191
|
+
// 404/204 = no default member set; fall through. Other errors bubble.
|
|
192
|
+
if (!(err instanceof TM1Error &&
|
|
193
|
+
(err.httpStatus === 404 || err.httpStatus === 204))) {
|
|
194
|
+
throw err;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
// Tier 2 & 3: enumerate elements with parents and classify.
|
|
198
|
+
const elementsResp = await this.http.request("GET", `${base}/Elements?$select=Name,Level&$expand=Parents($select=Name)`);
|
|
199
|
+
const elements = elementsResp?.value ?? [];
|
|
200
|
+
if (elements.length === 0) {
|
|
201
|
+
throw new TM1Error({
|
|
202
|
+
code: TM1ErrorCode.NOT_FOUND,
|
|
203
|
+
message: `Hierarchy '${dimensionName}.${hier}' has no elements or does not exist`,
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
const roots = elements.filter((e) => !e.Parents || e.Parents.length === 0);
|
|
207
|
+
// elements.length > 0 is guarded above
|
|
208
|
+
const indexOne = elements[0].Name;
|
|
209
|
+
if (roots.length === 1) {
|
|
210
|
+
return {
|
|
211
|
+
dimension: dimensionName,
|
|
212
|
+
hierarchy: hier,
|
|
213
|
+
resolved: { name: roots[0].Name, level: roots[0].Level },
|
|
214
|
+
source: "single_root",
|
|
215
|
+
// Derived server-fallback, not an explicitly maintained default → medium,
|
|
216
|
+
// never tier-1 high. High is reserved for source "defined".
|
|
217
|
+
confidence: "medium",
|
|
218
|
+
warning: "DefaultMember attribute not maintained — resolved via unique parentless root.",
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
if (roots.length > 1) {
|
|
222
|
+
// Highest level first, then alphabetical for determinism.
|
|
223
|
+
const sorted = [...roots].sort((a, b) => b.Level - a.Level || a.Name.localeCompare(b.Name));
|
|
224
|
+
return {
|
|
225
|
+
dimension: dimensionName,
|
|
226
|
+
hierarchy: hier,
|
|
227
|
+
resolved: { name: sorted[0].Name, level: sorted[0].Level },
|
|
228
|
+
source: "first_root",
|
|
229
|
+
confidence: "medium",
|
|
230
|
+
alternatives: {
|
|
231
|
+
roots: sorted.map((r) => ({ name: r.Name, level: r.Level })),
|
|
232
|
+
indexOne,
|
|
233
|
+
},
|
|
234
|
+
warning: `DefaultMember not maintained — ${roots.length} parentless roots found; selected highest-level. Inspect alternatives.roots to disambiguate.`,
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
// No roots: flat or cyclic hierarchy. TM1's own fallback is insertion-order index 1.
|
|
238
|
+
return {
|
|
239
|
+
dimension: dimensionName,
|
|
240
|
+
hierarchy: hier,
|
|
241
|
+
resolved: { name: indexOne, level: elements[0].Level ?? 0 },
|
|
242
|
+
source: "index_1",
|
|
243
|
+
confidence: "low",
|
|
244
|
+
alternatives: { roots: [], indexOne },
|
|
245
|
+
warning: "No parentless roots detected (flat or cyclic hierarchy). Falling back to first element by insertion order — verify suitability for view slicers.",
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
//# sourceMappingURL=dimension-service.js.map
|