@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.
Files changed (475) hide show
  1. package/CHANGELOG.md +1211 -0
  2. package/LICENSE +21 -0
  3. package/NOTICE +34 -0
  4. package/README.md +276 -0
  5. package/dist/config.d.ts +35 -0
  6. package/dist/config.js +238 -0
  7. package/dist/http-transport.d.ts +8 -0
  8. package/dist/http-transport.js +132 -0
  9. package/dist/index.d.ts +18 -0
  10. package/dist/index.js +164 -0
  11. package/dist/lib/callgraph/callGraph.d.ts +124 -0
  12. package/dist/lib/callgraph/callGraph.js +334 -0
  13. package/dist/lib/callgraph/choreGraph.d.ts +23 -0
  14. package/dist/lib/callgraph/choreGraph.js +102 -0
  15. package/dist/lib/callgraph/dataFlow.d.ts +74 -0
  16. package/dist/lib/callgraph/dataFlow.js +271 -0
  17. package/dist/lib/callgraph/datasourceMembership.d.ts +31 -0
  18. package/dist/lib/callgraph/datasourceMembership.js +142 -0
  19. package/dist/lib/callgraph/lintTypes.d.ts +28 -0
  20. package/dist/lib/callgraph/lintTypes.js +2 -0
  21. package/dist/lib/callgraph/mdxMembers.d.ts +29 -0
  22. package/dist/lib/callgraph/mdxMembers.js +97 -0
  23. package/dist/lib/callgraph/referenceIndex.d.ts +179 -0
  24. package/dist/lib/callgraph/referenceIndex.js +584 -0
  25. package/dist/lib/callgraph/rulesLinter.d.ts +55 -0
  26. package/dist/lib/callgraph/rulesLinter.js +776 -0
  27. package/dist/lib/callgraph/rulesParser.d.ts +26 -0
  28. package/dist/lib/callgraph/rulesParser.js +71 -0
  29. package/dist/lib/callgraph/subsetUsage.d.ts +16 -0
  30. package/dist/lib/callgraph/subsetUsage.js +134 -0
  31. package/dist/lib/callgraph/tiParser.d.ts +21 -0
  32. package/dist/lib/callgraph/tiParser.js +672 -0
  33. package/dist/lib/callgraph/tiSignatures.d.ts +32 -0
  34. package/dist/lib/callgraph/tiSignatures.js +6185 -0
  35. package/dist/lib/callgraph/tm1-adapter.d.ts +32 -0
  36. package/dist/lib/callgraph/tm1-adapter.js +159 -0
  37. package/dist/lib/callgraph/types.d.ts +53 -0
  38. package/dist/lib/callgraph/types.js +2 -0
  39. package/dist/lib/callgraph/variableEnv.d.ts +86 -0
  40. package/dist/lib/callgraph/variableEnv.js +214 -0
  41. package/dist/lib/cell-address.d.ts +12 -0
  42. package/dist/lib/cell-address.js +71 -0
  43. package/dist/lib/complexity/antipatterns.d.ts +22 -0
  44. package/dist/lib/complexity/antipatterns.js +302 -0
  45. package/dist/lib/complexity/comment-classifier.d.ts +24 -0
  46. package/dist/lib/complexity/comment-classifier.js +43 -0
  47. package/dist/lib/complexity/cross-process.d.ts +78 -0
  48. package/dist/lib/complexity/cross-process.js +114 -0
  49. package/dist/lib/complexity/process-metrics.d.ts +78 -0
  50. package/dist/lib/complexity/process-metrics.js +278 -0
  51. package/dist/lib/complexity/rules-metrics.d.ts +31 -0
  52. package/dist/lib/complexity/rules-metrics.js +99 -0
  53. package/dist/lib/concurrency.d.ts +11 -0
  54. package/dist/lib/concurrency.js +27 -0
  55. package/dist/lib/control-name.d.ts +10 -0
  56. package/dist/lib/control-name.js +10 -0
  57. package/dist/lib/coordinate-error.d.ts +3 -0
  58. package/dist/lib/coordinate-error.js +29 -0
  59. package/dist/lib/credential-format.d.ts +23 -0
  60. package/dist/lib/credential-format.js +25 -0
  61. package/dist/lib/cube-stats/fetcher.d.ts +106 -0
  62. package/dist/lib/cube-stats/fetcher.js +194 -0
  63. package/dist/lib/feeders/brackets.d.ts +47 -0
  64. package/dist/lib/feeders/brackets.js +195 -0
  65. package/dist/lib/feeders/element-type-cache.d.ts +42 -0
  66. package/dist/lib/feeders/element-type-cache.js +86 -0
  67. package/dist/lib/feeders/static-heuristics.d.ts +101 -0
  68. package/dist/lib/feeders/static-heuristics.js +202 -0
  69. package/dist/lib/git-process.d.ts +67 -0
  70. package/dist/lib/git-process.js +243 -0
  71. package/dist/lib/mask-secrets.d.ts +10 -0
  72. package/dist/lib/mask-secrets.js +99 -0
  73. package/dist/lib/mdx.d.ts +3 -0
  74. package/dist/lib/mdx.js +13 -0
  75. package/dist/lib/naming/odata-filter.d.ts +15 -0
  76. package/dist/lib/naming/odata-filter.js +81 -0
  77. package/dist/lib/naming/rules.d.ts +34 -0
  78. package/dist/lib/naming/rules.js +215 -0
  79. package/dist/lib/pro-parser.d.ts +19 -0
  80. package/dist/lib/pro-parser.js +260 -0
  81. package/dist/lib/pro-serializer.d.ts +19 -0
  82. package/dist/lib/pro-serializer.js +170 -0
  83. package/dist/lib/process-parts-schema.d.ts +45 -0
  84. package/dist/lib/process-parts-schema.js +46 -0
  85. package/dist/lib/process-refs.d.ts +88 -0
  86. package/dist/lib/process-refs.js +441 -0
  87. package/dist/lib/rules-outline.d.ts +29 -0
  88. package/dist/lib/rules-outline.js +68 -0
  89. package/dist/lib/rules-patch.d.ts +6 -0
  90. package/dist/lib/rules-patch.js +59 -0
  91. package/dist/lib/safe-regex.d.ts +15 -0
  92. package/dist/lib/safe-regex.js +37 -0
  93. package/dist/lib/sample-cells.d.ts +48 -0
  94. package/dist/lib/sample-cells.js +146 -0
  95. package/dist/lib/slim-json-schema.d.ts +20 -0
  96. package/dist/lib/slim-json-schema.js +68 -0
  97. package/dist/lib/strip-comments.d.ts +23 -0
  98. package/dist/lib/strip-comments.js +61 -0
  99. package/dist/lib/tm1-events.d.ts +16 -0
  100. package/dist/lib/tm1-events.js +29 -0
  101. package/dist/lib/v12-compat/deprecated-ti.d.ts +17 -0
  102. package/dist/lib/v12-compat/deprecated-ti.js +257 -0
  103. package/dist/lib/v12-compat/scanner.d.ts +10 -0
  104. package/dist/lib/v12-compat/scanner.js +43 -0
  105. package/dist/lib/variables-ui-data.d.ts +26 -0
  106. package/dist/lib/variables-ui-data.js +77 -0
  107. package/dist/load-env.d.ts +2 -0
  108. package/dist/load-env.js +29 -0
  109. package/dist/logger.d.ts +4 -0
  110. package/dist/logger.js +60 -0
  111. package/dist/prompts/index.d.ts +3 -0
  112. package/dist/prompts/index.js +141 -0
  113. package/dist/resources/index.d.ts +5 -0
  114. package/dist/resources/index.js +237 -0
  115. package/dist/resources/list-handler.d.ts +40 -0
  116. package/dist/resources/list-handler.js +86 -0
  117. package/dist/resources/subscriptions.d.ts +19 -0
  118. package/dist/resources/subscriptions.js +80 -0
  119. package/dist/schemas/cells.d.ts +17 -0
  120. package/dist/schemas/cells.js +13 -0
  121. package/dist/schemas/common.d.ts +16 -0
  122. package/dist/schemas/common.js +14 -0
  123. package/dist/schemas/index.d.ts +10 -0
  124. package/dist/schemas/index.js +23 -0
  125. package/dist/schemas/metadata.d.ts +70 -0
  126. package/dist/schemas/metadata.js +47 -0
  127. package/dist/schemas/monitoring.d.ts +95 -0
  128. package/dist/schemas/monitoring.js +69 -0
  129. package/dist/schemas/processes.d.ts +74 -0
  130. package/dist/schemas/processes.js +66 -0
  131. package/dist/schemas/scheduling.d.ts +13 -0
  132. package/dist/schemas/scheduling.js +13 -0
  133. package/dist/schemas/security.d.ts +19 -0
  134. package/dist/schemas/security.js +16 -0
  135. package/dist/schemas/subsets.d.ts +12 -0
  136. package/dist/schemas/subsets.js +12 -0
  137. package/dist/schemas/views.d.ts +9 -0
  138. package/dist/schemas/views.js +9 -0
  139. package/dist/session-manager.d.ts +79 -0
  140. package/dist/session-manager.js +281 -0
  141. package/dist/tm1-client/connection/profile.d.ts +13 -0
  142. package/dist/tm1-client/connection/profile.js +99 -0
  143. package/dist/tm1-client/dispatcher.d.ts +5 -0
  144. package/dist/tm1-client/dispatcher.js +31 -0
  145. package/dist/tm1-client/http.d.ts +81 -0
  146. package/dist/tm1-client/http.js +547 -0
  147. package/dist/tm1-client/services/batch-service.d.ts +123 -0
  148. package/dist/tm1-client/services/batch-service.js +455 -0
  149. package/dist/tm1-client/services/cell-service.d.ts +71 -0
  150. package/dist/tm1-client/services/cell-service.js +333 -0
  151. package/dist/tm1-client/services/cellset-transform.d.ts +26 -0
  152. package/dist/tm1-client/services/cellset-transform.js +80 -0
  153. package/dist/tm1-client/services/chore-service.d.ts +68 -0
  154. package/dist/tm1-client/services/chore-service.js +179 -0
  155. package/dist/tm1-client/services/chore-status.d.ts +11 -0
  156. package/dist/tm1-client/services/chore-status.js +127 -0
  157. package/dist/tm1-client/services/cube-service.d.ts +134 -0
  158. package/dist/tm1-client/services/cube-service.js +294 -0
  159. package/dist/tm1-client/services/dimension-service.d.ts +118 -0
  160. package/dist/tm1-client/services/dimension-service.js +249 -0
  161. package/dist/tm1-client/services/element-service.d.ts +245 -0
  162. package/dist/tm1-client/services/element-service.js +809 -0
  163. package/dist/tm1-client/services/fallback.d.ts +44 -0
  164. package/dist/tm1-client/services/fallback.js +72 -0
  165. package/dist/tm1-client/services/file-service.d.ts +53 -0
  166. package/dist/tm1-client/services/file-service.js +218 -0
  167. package/dist/tm1-client/services/hierarchy-service.d.ts +129 -0
  168. package/dist/tm1-client/services/hierarchy-service.js +332 -0
  169. package/dist/tm1-client/services/monitoring-service.d.ts +34 -0
  170. package/dist/tm1-client/services/monitoring-service.js +123 -0
  171. package/dist/tm1-client/services/odata-page.d.ts +71 -0
  172. package/dist/tm1-client/services/odata-page.js +87 -0
  173. package/dist/tm1-client/services/process-service.d.ts +278 -0
  174. package/dist/tm1-client/services/process-service.js +874 -0
  175. package/dist/tm1-client/services/process-status.d.ts +21 -0
  176. package/dist/tm1-client/services/process-status.js +89 -0
  177. package/dist/tm1-client/services/security-service.d.ts +50 -0
  178. package/dist/tm1-client/services/security-service.js +93 -0
  179. package/dist/tm1-client/services/server-service.d.ts +116 -0
  180. package/dist/tm1-client/services/server-service.js +504 -0
  181. package/dist/tm1-client/services/subset-service.d.ts +37 -0
  182. package/dist/tm1-client/services/subset-service.js +122 -0
  183. package/dist/tm1-client/services/view-service.d.ts +46 -0
  184. package/dist/tm1-client/services/view-service.js +287 -0
  185. package/dist/tm1-client.d.ts +56 -0
  186. package/dist/tm1-client.js +126 -0
  187. package/dist/tools/analysis/analyze-callgraph.d.ts +28 -0
  188. package/dist/tools/analysis/analyze-callgraph.js +350 -0
  189. package/dist/tools/analysis/analyze-chore-graph.d.ts +2 -0
  190. package/dist/tools/analysis/analyze-chore-graph.js +148 -0
  191. package/dist/tools/analysis/analyze-object-usage.d.ts +2 -0
  192. package/dist/tools/analysis/analyze-object-usage.js +143 -0
  193. package/dist/tools/analysis/audit-complexity.d.ts +2 -0
  194. package/dist/tools/analysis/audit-complexity.js +255 -0
  195. package/dist/tools/analysis/audit-feeders.d.ts +2 -0
  196. package/dist/tools/analysis/audit-feeders.js +417 -0
  197. package/dist/tools/analysis/audit-naming.d.ts +2 -0
  198. package/dist/tools/analysis/audit-naming.js +379 -0
  199. package/dist/tools/analysis/check-v12-readiness.d.ts +2 -0
  200. package/dist/tools/analysis/check-v12-readiness.js +136 -0
  201. package/dist/tools/analysis/find-orphan-dimensions.d.ts +2 -0
  202. package/dist/tools/analysis/find-orphan-dimensions.js +55 -0
  203. package/dist/tools/analysis/invalidate-callgraph-cache.d.ts +2 -0
  204. package/dist/tools/analysis/invalidate-callgraph-cache.js +40 -0
  205. package/dist/tools/analysis/trace-data-flow.d.ts +2 -0
  206. package/dist/tools/analysis/trace-data-flow.js +138 -0
  207. package/dist/tools/annotations.d.ts +12 -0
  208. package/dist/tools/annotations.js +61 -0
  209. package/dist/tools/celldata/check-feeders.d.ts +2 -0
  210. package/dist/tools/celldata/check-feeders.js +48 -0
  211. package/dist/tools/celldata/check-writable-coords.d.ts +2 -0
  212. package/dist/tools/celldata/check-writable-coords.js +126 -0
  213. package/dist/tools/celldata/execute-mdx.d.ts +17 -0
  214. package/dist/tools/celldata/execute-mdx.js +126 -0
  215. package/dist/tools/celldata/get-cell-value.d.ts +2 -0
  216. package/dist/tools/celldata/get-cell-value.js +30 -0
  217. package/dist/tools/celldata/get-view-definition.d.ts +2 -0
  218. package/dist/tools/celldata/get-view-definition.js +29 -0
  219. package/dist/tools/celldata/get-view.d.ts +2 -0
  220. package/dist/tools/celldata/get-view.js +55 -0
  221. package/dist/tools/celldata/sample-cells.d.ts +2 -0
  222. package/dist/tools/celldata/sample-cells.js +101 -0
  223. package/dist/tools/celldata/trace-cell-calculation.d.ts +2 -0
  224. package/dist/tools/celldata/trace-cell-calculation.js +53 -0
  225. package/dist/tools/celldata/trace-feeders.d.ts +2 -0
  226. package/dist/tools/celldata/trace-feeders.js +44 -0
  227. package/dist/tools/celldata/write-cells.d.ts +2 -0
  228. package/dist/tools/celldata/write-cells.js +65 -0
  229. package/dist/tools/confirm.d.ts +10 -0
  230. package/dist/tools/confirm.js +64 -0
  231. package/dist/tools/define-tool.d.ts +51 -0
  232. package/dist/tools/define-tool.js +49 -0
  233. package/dist/tools/dimension-management/bulk-upsert-elements.d.ts +2 -0
  234. package/dist/tools/dimension-management/bulk-upsert-elements.js +103 -0
  235. package/dist/tools/dimension-management/create-dimension.d.ts +2 -0
  236. package/dist/tools/dimension-management/create-dimension.js +22 -0
  237. package/dist/tools/dimension-management/create-element-attribute.d.ts +2 -0
  238. package/dist/tools/dimension-management/create-element-attribute.js +26 -0
  239. package/dist/tools/dimension-management/create-element.d.ts +2 -0
  240. package/dist/tools/dimension-management/create-element.js +31 -0
  241. package/dist/tools/dimension-management/create-hierarchy.d.ts +2 -0
  242. package/dist/tools/dimension-management/create-hierarchy.js +22 -0
  243. package/dist/tools/dimension-management/delete-dimension.d.ts +2 -0
  244. package/dist/tools/dimension-management/delete-dimension.js +25 -0
  245. package/dist/tools/dimension-management/delete-element.d.ts +2 -0
  246. package/dist/tools/dimension-management/delete-element.js +26 -0
  247. package/dist/tools/dimension-management/delete-elements.d.ts +2 -0
  248. package/dist/tools/dimension-management/delete-elements.js +44 -0
  249. package/dist/tools/dimension-management/delete-hierarchy.d.ts +2 -0
  250. package/dist/tools/dimension-management/delete-hierarchy.js +35 -0
  251. package/dist/tools/dimension-management/get-element-attribute-values.d.ts +2 -0
  252. package/dist/tools/dimension-management/get-element-attribute-values.js +77 -0
  253. package/dist/tools/dimension-management/list-element-attributes.d.ts +2 -0
  254. package/dist/tools/dimension-management/list-element-attributes.js +31 -0
  255. package/dist/tools/dimension-management/move-element.d.ts +2 -0
  256. package/dist/tools/dimension-management/move-element.js +28 -0
  257. package/dist/tools/dimension-management/update-element-attribute-value.d.ts +2 -0
  258. package/dist/tools/dimension-management/update-element-attribute-value.js +80 -0
  259. package/dist/tools/dimension-management/update-element.d.ts +2 -0
  260. package/dist/tools/dimension-management/update-element.js +35 -0
  261. package/dist/tools/error-format.d.ts +22 -0
  262. package/dist/tools/error-format.js +130 -0
  263. package/dist/tools/fileops/delete-file.d.ts +2 -0
  264. package/dist/tools/fileops/delete-file.js +32 -0
  265. package/dist/tools/fileops/get-file-content.d.ts +2 -0
  266. package/dist/tools/fileops/get-file-content.js +76 -0
  267. package/dist/tools/fileops/list-files.d.ts +2 -0
  268. package/dist/tools/fileops/list-files.js +43 -0
  269. package/dist/tools/fileops/search-files.d.ts +2 -0
  270. package/dist/tools/fileops/search-files.js +76 -0
  271. package/dist/tools/fileops/upload-file.d.ts +2 -0
  272. package/dist/tools/fileops/upload-file.js +69 -0
  273. package/dist/tools/format.d.ts +57 -0
  274. package/dist/tools/format.js +157 -0
  275. package/dist/tools/hierarchy.d.ts +6 -0
  276. package/dist/tools/hierarchy.js +27 -0
  277. package/dist/tools/index.d.ts +4 -0
  278. package/dist/tools/index.js +263 -0
  279. package/dist/tools/local-file.d.ts +16 -0
  280. package/dist/tools/local-file.js +88 -0
  281. package/dist/tools/metadata/get-ancestors.d.ts +2 -0
  282. package/dist/tools/metadata/get-ancestors.js +36 -0
  283. package/dist/tools/metadata/get-descendants.d.ts +2 -0
  284. package/dist/tools/metadata/get-descendants.js +64 -0
  285. package/dist/tools/metadata/get-hierarchy.d.ts +2 -0
  286. package/dist/tools/metadata/get-hierarchy.js +130 -0
  287. package/dist/tools/metadata/list-chores.d.ts +2 -0
  288. package/dist/tools/metadata/list-chores.js +62 -0
  289. package/dist/tools/metadata/list-cubes.d.ts +2 -0
  290. package/dist/tools/metadata/list-cubes.js +128 -0
  291. package/dist/tools/metadata/list-dimensions.d.ts +2 -0
  292. package/dist/tools/metadata/list-dimensions.js +131 -0
  293. package/dist/tools/metadata/list-processes-grouped.d.ts +2 -0
  294. package/dist/tools/metadata/list-processes-grouped.js +96 -0
  295. package/dist/tools/metadata/list-processes.d.ts +2 -0
  296. package/dist/tools/metadata/list-processes.js +108 -0
  297. package/dist/tools/metadata/resolve-default-members.d.ts +2 -0
  298. package/dist/tools/metadata/resolve-default-members.js +46 -0
  299. package/dist/tools/model-building/check-cube-rule.d.ts +2 -0
  300. package/dist/tools/model-building/check-cube-rule.js +51 -0
  301. package/dist/tools/model-building/clear-cube.d.ts +2 -0
  302. package/dist/tools/model-building/clear-cube.js +46 -0
  303. package/dist/tools/model-building/create-cube.d.ts +2 -0
  304. package/dist/tools/model-building/create-cube.js +34 -0
  305. package/dist/tools/model-building/delete-cube.d.ts +2 -0
  306. package/dist/tools/model-building/delete-cube.js +27 -0
  307. package/dist/tools/model-building/get-all-cube-rules.d.ts +2 -0
  308. package/dist/tools/model-building/get-all-cube-rules.js +149 -0
  309. package/dist/tools/model-building/get-cube-rules.d.ts +2 -0
  310. package/dist/tools/model-building/get-cube-rules.js +69 -0
  311. package/dist/tools/model-building/rules-source.d.ts +21 -0
  312. package/dist/tools/model-building/rules-source.js +49 -0
  313. package/dist/tools/model-building/search-rules.d.ts +2 -0
  314. package/dist/tools/model-building/search-rules.js +132 -0
  315. package/dist/tools/model-building/set-cube-rules.d.ts +2 -0
  316. package/dist/tools/model-building/set-cube-rules.js +81 -0
  317. package/dist/tools/model-building/unload-cube.d.ts +2 -0
  318. package/dist/tools/model-building/unload-cube.js +23 -0
  319. package/dist/tools/operations/diagnose-process-error.d.ts +2 -0
  320. package/dist/tools/operations/diagnose-process-error.js +178 -0
  321. package/dist/tools/operations/error-log-helpers.d.ts +25 -0
  322. package/dist/tools/operations/error-log-helpers.js +57 -0
  323. package/dist/tools/operations/get-audit-log.d.ts +2 -0
  324. package/dist/tools/operations/get-audit-log.js +70 -0
  325. package/dist/tools/operations/get-cube-stats.d.ts +2 -0
  326. package/dist/tools/operations/get-cube-stats.js +107 -0
  327. package/dist/tools/operations/get-error-log-content.d.ts +2 -0
  328. package/dist/tools/operations/get-error-log-content.js +164 -0
  329. package/dist/tools/operations/get-jobs.d.ts +3 -0
  330. package/dist/tools/operations/get-jobs.js +51 -0
  331. package/dist/tools/operations/get-message-log.d.ts +2 -0
  332. package/dist/tools/operations/get-message-log.js +63 -0
  333. package/dist/tools/operations/get-server-info.d.ts +2 -0
  334. package/dist/tools/operations/get-server-info.js +180 -0
  335. package/dist/tools/operations/get-server-state.d.ts +2 -0
  336. package/dist/tools/operations/get-server-state.js +129 -0
  337. package/dist/tools/operations/get-sessions.d.ts +2 -0
  338. package/dist/tools/operations/get-sessions.js +76 -0
  339. package/dist/tools/operations/get-threads.d.ts +3 -0
  340. package/dist/tools/operations/get-threads.js +50 -0
  341. package/dist/tools/operations/get-transaction-log.d.ts +2 -0
  342. package/dist/tools/operations/get-transaction-log.js +63 -0
  343. package/dist/tools/operations/list-error-logs.d.ts +8 -0
  344. package/dist/tools/operations/list-error-logs.js +157 -0
  345. package/dist/tools/operations/save-data.d.ts +2 -0
  346. package/dist/tools/operations/save-data.js +50 -0
  347. package/dist/tools/pagination.d.ts +32 -0
  348. package/dist/tools/pagination.js +116 -0
  349. package/dist/tools/scheduling/create-chore.d.ts +2 -0
  350. package/dist/tools/scheduling/create-chore.js +93 -0
  351. package/dist/tools/scheduling/delete-chore.d.ts +2 -0
  352. package/dist/tools/scheduling/delete-chore.js +22 -0
  353. package/dist/tools/scheduling/execute-chore.d.ts +2 -0
  354. package/dist/tools/scheduling/execute-chore.js +52 -0
  355. package/dist/tools/scheduling/toggle-chore.d.ts +2 -0
  356. package/dist/tools/scheduling/toggle-chore.js +22 -0
  357. package/dist/tools/scheduling/update-chore.d.ts +2 -0
  358. package/dist/tools/scheduling/update-chore.js +71 -0
  359. package/dist/tools/schemas/common.d.ts +10 -0
  360. package/dist/tools/schemas/common.js +23 -0
  361. package/dist/tools/schemas/items-analysis.d.ts +394 -0
  362. package/dist/tools/schemas/items-analysis.js +419 -0
  363. package/dist/tools/schemas/items-cells.d.ts +70 -0
  364. package/dist/tools/schemas/items-cells.js +65 -0
  365. package/dist/tools/schemas/items-common.d.ts +18 -0
  366. package/dist/tools/schemas/items-common.js +39 -0
  367. package/dist/tools/schemas/items-fileops.d.ts +11 -0
  368. package/dist/tools/schemas/items-fileops.js +13 -0
  369. package/dist/tools/schemas/items-metadata.d.ts +262 -0
  370. package/dist/tools/schemas/items-metadata.js +184 -0
  371. package/dist/tools/schemas/items-monitoring.d.ts +79 -0
  372. package/dist/tools/schemas/items-monitoring.js +78 -0
  373. package/dist/tools/schemas/items-processes.d.ts +279 -0
  374. package/dist/tools/schemas/items-processes.js +235 -0
  375. package/dist/tools/schemas/items-scheduling.d.ts +25 -0
  376. package/dist/tools/schemas/items-scheduling.js +26 -0
  377. package/dist/tools/schemas/items-security.d.ts +19 -0
  378. package/dist/tools/schemas/items-security.js +12 -0
  379. package/dist/tools/schemas/items-subsets.d.ts +2 -0
  380. package/dist/tools/schemas/items-subsets.js +4 -0
  381. package/dist/tools/schemas/items-views.d.ts +38 -0
  382. package/dist/tools/schemas/items-views.js +26 -0
  383. package/dist/tools/schemas/items.d.ts +12 -0
  384. package/dist/tools/schemas/items.js +23 -0
  385. package/dist/tools/schemas/markdown-capable.d.ts +21 -0
  386. package/dist/tools/schemas/markdown-capable.js +58 -0
  387. package/dist/tools/schemas/output-schema.d.ts +24 -0
  388. package/dist/tools/schemas/output-schema.js +25 -0
  389. package/dist/tools/security/assign-client-group.d.ts +2 -0
  390. package/dist/tools/security/assign-client-group.js +20 -0
  391. package/dist/tools/security/create-client.d.ts +2 -0
  392. package/dist/tools/security/create-client.js +28 -0
  393. package/dist/tools/security/delete-client.d.ts +2 -0
  394. package/dist/tools/security/delete-client.js +22 -0
  395. package/dist/tools/security/get-client.d.ts +2 -0
  396. package/dist/tools/security/get-client.js +20 -0
  397. package/dist/tools/security/list-clients.d.ts +2 -0
  398. package/dist/tools/security/list-clients.js +86 -0
  399. package/dist/tools/security/list-groups.d.ts +2 -0
  400. package/dist/tools/security/list-groups.js +43 -0
  401. package/dist/tools/security/remove-client-group.d.ts +2 -0
  402. package/dist/tools/security/remove-client-group.js +27 -0
  403. package/dist/tools/security/update-client.d.ts +2 -0
  404. package/dist/tools/security/update-client.js +22 -0
  405. package/dist/tools/subsets/create-subset.d.ts +2 -0
  406. package/dist/tools/subsets/create-subset.js +44 -0
  407. package/dist/tools/subsets/delete-subset.d.ts +2 -0
  408. package/dist/tools/subsets/delete-subset.js +26 -0
  409. package/dist/tools/subsets/get-subset.d.ts +2 -0
  410. package/dist/tools/subsets/get-subset.js +29 -0
  411. package/dist/tools/subsets/list-subsets.d.ts +2 -0
  412. package/dist/tools/subsets/list-subsets.js +36 -0
  413. package/dist/tools/subsets/update-subset.d.ts +2 -0
  414. package/dist/tools/subsets/update-subset.js +33 -0
  415. package/dist/tools/ti-development/check-process-code.d.ts +2 -0
  416. package/dist/tools/ti-development/check-process-code.js +96 -0
  417. package/dist/tools/ti-development/compile-process.d.ts +2 -0
  418. package/dist/tools/ti-development/compile-process.js +32 -0
  419. package/dist/tools/ti-development/copy-process.d.ts +2 -0
  420. package/dist/tools/ti-development/copy-process.js +32 -0
  421. package/dist/tools/ti-development/delete-process.d.ts +2 -0
  422. package/dist/tools/ti-development/delete-process.js +26 -0
  423. package/dist/tools/ti-development/diff-process-with-file.d.ts +2 -0
  424. package/dist/tools/ti-development/diff-process-with-file.js +208 -0
  425. package/dist/tools/ti-development/diff-processes.d.ts +2 -0
  426. package/dist/tools/ti-development/diff-processes.js +312 -0
  427. package/dist/tools/ti-development/execute-process.d.ts +8 -0
  428. package/dist/tools/ti-development/execute-process.js +109 -0
  429. package/dist/tools/ti-development/export-process-to-git.d.ts +2 -0
  430. package/dist/tools/ti-development/export-process-to-git.js +113 -0
  431. package/dist/tools/ti-development/export-process-to-pro.d.ts +2 -0
  432. package/dist/tools/ti-development/export-process-to-pro.js +117 -0
  433. package/dist/tools/ti-development/get-all-processes-code.d.ts +2 -0
  434. package/dist/tools/ti-development/get-all-processes-code.js +131 -0
  435. package/dist/tools/ti-development/get-process-code.d.ts +2 -0
  436. package/dist/tools/ti-development/get-process-code.js +100 -0
  437. package/dist/tools/ti-development/get-process-datasource.d.ts +2 -0
  438. package/dist/tools/ti-development/get-process-datasource.js +20 -0
  439. package/dist/tools/ti-development/get-process-parameters.d.ts +2 -0
  440. package/dist/tools/ti-development/get-process-parameters.js +25 -0
  441. package/dist/tools/ti-development/get-process-variables.d.ts +2 -0
  442. package/dist/tools/ti-development/get-process-variables.js +38 -0
  443. package/dist/tools/ti-development/get-process.d.ts +2 -0
  444. package/dist/tools/ti-development/get-process.js +163 -0
  445. package/dist/tools/ti-development/import-pro-file.d.ts +2 -0
  446. package/dist/tools/ti-development/import-pro-file.js +153 -0
  447. package/dist/tools/ti-development/import-process-from-git.d.ts +2 -0
  448. package/dist/tools/ti-development/import-process-from-git.js +198 -0
  449. package/dist/tools/ti-development/install-pro-bundle.d.ts +2 -0
  450. package/dist/tools/ti-development/install-pro-bundle.js +288 -0
  451. package/dist/tools/ti-development/preflight.d.ts +39 -0
  452. package/dist/tools/ti-development/preflight.js +56 -0
  453. package/dist/tools/ti-development/process-backup.d.ts +29 -0
  454. package/dist/tools/ti-development/process-backup.js +118 -0
  455. package/dist/tools/ti-development/search-code.d.ts +2 -0
  456. package/dist/tools/ti-development/search-code.js +208 -0
  457. package/dist/tools/ti-development/upsert-process.d.ts +2 -0
  458. package/dist/tools/ti-development/upsert-process.js +167 -0
  459. package/dist/tools/ti-development/validate-process-refs.d.ts +2 -0
  460. package/dist/tools/ti-development/validate-process-refs.js +73 -0
  461. package/dist/tools/views/create-mdx-view.d.ts +2 -0
  462. package/dist/tools/views/create-mdx-view.js +21 -0
  463. package/dist/tools/views/create-native-view.d.ts +2 -0
  464. package/dist/tools/views/create-native-view.js +81 -0
  465. package/dist/tools/views/delete-view.d.ts +2 -0
  466. package/dist/tools/views/delete-view.js +23 -0
  467. package/dist/tools/views/list-views.d.ts +2 -0
  468. package/dist/tools/views/list-views.js +32 -0
  469. package/dist/tools/with-annotations.d.ts +6 -0
  470. package/dist/tools/with-annotations.js +339 -0
  471. package/dist/types.d.ts +409 -0
  472. package/dist/types.js +91 -0
  473. package/dist/version.d.ts +4 -0
  474. package/dist/version.js +18 -0
  475. package/package.json +107 -0
@@ -0,0 +1,547 @@
1
+ import { createConnectionProfile, } from "./connection/profile.js";
2
+ import { TM1Error, TM1ErrorCode } from "../types.js";
3
+ import { PRODUCT, VERSION } from "../version.js";
4
+ import { getTm1Dispatcher, tm1Fetch } from "./dispatcher.js";
5
+ import { tm1Events } from "../lib/tm1-events.js";
6
+ import { maskSecretValues } from "../lib/mask-secrets.js";
7
+ const MAX_NETWORK_RETRIES = 3;
8
+ const BACKOFF_BASE_MS = 1000;
9
+ const USER_AGENT = `${PRODUCT}/${VERSION}`;
10
+ // R2-22: any successful mutating HTTP call invalidates the callgraph
11
+ // reference-index cache. Cheap (Map.clear()) and rebuild is lazy on next
12
+ // read — over-invalidation on non-graph-affecting calls (write_cells,
13
+ // upload_file, CheckRules) costs at most one rebuild. The alternative —
14
+ // per-service hooks across 17 mutation methods — risks drift as new
15
+ // mutating methods are added.
16
+ function isSafeHttpMethod(method) {
17
+ return method === "GET" || method === "HEAD";
18
+ }
19
+ // Link an external AbortSignal (e.g. from RequestHandlerExtra.signal) to a
20
+ // locally-owned timeout AbortController. Returns an unsubscribe function the
21
+ // caller must invoke in `finally` to avoid leaking the listener after the
22
+ // request resolves. If the external signal is already aborted, propagates the
23
+ // reason immediately.
24
+ function linkAbortSignals(local, external) {
25
+ if (!external)
26
+ return () => undefined;
27
+ if (external.aborted) {
28
+ local.abort(external.reason);
29
+ return () => undefined;
30
+ }
31
+ const onAbort = () => local.abort(external.reason);
32
+ external.addEventListener("abort", onAbort, { once: true });
33
+ return () => external.removeEventListener("abort", onAbort);
34
+ }
35
+ export class TM1HttpClient {
36
+ // config is private: it carries credentials (TM1Config.password), so it must
37
+ // not be reachable as `client.config` from the service layer or leak into the
38
+ // compiled .d.ts public surface. Services get only what they need —
39
+ // `version` (numeric getter) for version-conditional paths and `logger`
40
+ // for structured logs.
41
+ config;
42
+ logger;
43
+ sessionManager;
44
+ // v11↔v12 URL-rerooting seam. v11: identity (paths unchanged). v12: rewrites
45
+ // `/api/v1/...` to the database-rooted `/{instance}/api/v1/Databases('{db}')/...`.
46
+ profile;
47
+ constructor(config, sessionManager, logger) {
48
+ this.config = config;
49
+ this.sessionManager = sessionManager;
50
+ this.logger = logger;
51
+ this.profile = createConnectionProfile(config);
52
+ }
53
+ /**
54
+ * TM1 major version (11 | 12) — the single numeric source of truth for
55
+ * version-conditional service code. Branch on this, never on the display
56
+ * string (`tm1Version`): a v12 connection can carry a "11.x"-looking
57
+ * TM1_VERSION string, but `version` is always authoritative.
58
+ */
59
+ get version() {
60
+ return this.config.version;
61
+ }
62
+ /**
63
+ * TM1 server version STRING (e.g. "11.8.…") — DISPLAY ONLY (server_info
64
+ * output, log fields, user-facing error messages). Do NOT branch on this;
65
+ * use the numeric `version` getter instead.
66
+ */
67
+ get tm1Version() {
68
+ return this.config.tm1Version;
69
+ }
70
+ /**
71
+ * Make an authenticated HTTP request to the TM1 REST API.
72
+ *
73
+ * - Ensures an active session via SessionManager
74
+ * - On 401: re-authenticates once and retries
75
+ * - On network error for safe methods (GET/HEAD): retries up to 3 times with exponential backoff (1s, 2s, 4s)
76
+ * - On network error for non-safe methods (POST/PUT/PATCH/DELETE): does NOT retry — these are not idempotent
77
+ * and a retry could spawn duplicate side-effects (e.g. parallel TI runs on tm1.Execute)
78
+ * - On other HTTP errors: classifies and throws TM1Error
79
+ */
80
+ /** @internal — for Service-layer use; not part of the public consumer API. */
81
+ async request(method, path, body, opts) {
82
+ const url = `${this.config.baseUrl}${this.profile.resolveApiPath(path)}`;
83
+ const isSafeMethod = isSafeHttpMethod(method);
84
+ const allowRetry = opts?.retry !== false;
85
+ const maxAttempts = isSafeMethod && allowRetry ? MAX_NETWORK_RETRIES : 0;
86
+ let lastError;
87
+ for (let attempt = 0; attempt <= maxAttempts; attempt++) {
88
+ if (attempt > 0) {
89
+ const delayMs = BACKOFF_BASE_MS * Math.pow(2, attempt - 1);
90
+ this.logger.warn({ attempt, delayMs, endpoint: path }, "Retrying after network error");
91
+ await sleep(delayMs);
92
+ }
93
+ try {
94
+ const cookie = await this.sessionManager.ensureSession();
95
+ const response = await this.executeRequest(url, method, cookie, body, opts?.timeoutMs, opts?.signal);
96
+ if (response.status === 401) {
97
+ this.logger.warn({ endpoint: path }, "Received 401, re-authenticating");
98
+ // Pass the cookie that got the 401 so a concurrent request that
99
+ // already rotated the session short-circuits to the fresh cookie
100
+ // instead of forcing another logout+login (staggered-401 churn).
101
+ const newCookie = await this.sessionManager.authenticate(cookie);
102
+ const retryResponse = await this.executeRequest(url, method, newCookie, body, opts?.timeoutMs, opts?.signal);
103
+ if (retryResponse.status === 401) {
104
+ throw new TM1Error({
105
+ code: TM1ErrorCode.AUTH_FAILED,
106
+ message: "Authentication failed after re-authentication attempt",
107
+ httpStatus: 401,
108
+ endpoint: path,
109
+ });
110
+ }
111
+ const retryResult = await this.handleResponse(retryResponse, path);
112
+ if (!isSafeMethod) {
113
+ tm1Events.emit("mutation", { method, path });
114
+ }
115
+ return retryResult;
116
+ }
117
+ const result = await this.handleResponse(response, path);
118
+ if (!isSafeMethod) {
119
+ tm1Events.emit("mutation", { method, path });
120
+ }
121
+ return result;
122
+ }
123
+ catch (error) {
124
+ if (error instanceof TM1Error) {
125
+ throw error;
126
+ }
127
+ if (isTimeoutError(error)) {
128
+ const ms = opts?.timeoutMs ?? this.config.requestTimeoutMs;
129
+ throw new TM1Error({
130
+ code: TM1ErrorCode.LOCK_TIMEOUT,
131
+ message: `Request to ${path} timed out after ${ms}ms`,
132
+ endpoint: path,
133
+ hint: isSafeMethod
134
+ ? "Query timed out — result set may be too large. Add filters or reduce scope. If a lock is suspected, use tm1_list_threads to diagnose."
135
+ : "Request timed out — TM1 server may be waiting on a lock held by another session. Use tm1_list_threads to diagnose and cancel the blocking thread.",
136
+ });
137
+ }
138
+ if (opts?.signal?.aborted) {
139
+ throw error;
140
+ }
141
+ if (this.isNetworkError(error)) {
142
+ lastError = error;
143
+ this.logger.error({ err: error, attempt, endpoint: path }, "Network error during request");
144
+ continue;
145
+ }
146
+ throw new TM1Error({
147
+ code: TM1ErrorCode.CONNECTION_FAILED,
148
+ message: error instanceof Error ? error.message : String(error),
149
+ endpoint: path,
150
+ });
151
+ }
152
+ }
153
+ throw new TM1Error({
154
+ code: TM1ErrorCode.CONNECTION_FAILED,
155
+ message: isSafeMethod
156
+ ? `Request failed after ${MAX_NETWORK_RETRIES} retries: ${lastError instanceof Error ? lastError.message : String(lastError)}`
157
+ : `Request failed (no retry for ${method}): ${lastError instanceof Error ? lastError.message : String(lastError)}`,
158
+ endpoint: path,
159
+ });
160
+ }
161
+ /**
162
+ * Make an authenticated HTTP request that returns raw text (not JSON).
163
+ * Used for file content downloads where the response is CSV/TXT/etc.
164
+ * Re-auths once on 401 like request().
165
+ */
166
+ /** @internal — for Service-layer use; not part of the public consumer API. */
167
+ async requestRaw(method, path, opts) {
168
+ const url = `${this.config.baseUrl}${this.profile.resolveApiPath(path)}`;
169
+ const effectiveTimeout = opts?.timeoutMs ?? this.config.requestTimeoutMs;
170
+ const cookie = await this.sessionManager.ensureSession();
171
+ const headers = {
172
+ Cookie: `TM1SessionId=${cookie}`,
173
+ Accept: "*/*",
174
+ "User-Agent": USER_AGENT,
175
+ "TM1-SessionContext": USER_AGENT,
176
+ "TM1-Session-Context": USER_AGENT,
177
+ };
178
+ const response = await this.withReauth((c) => {
179
+ const hdrs = { ...headers, Cookie: `TM1SessionId=${c}` };
180
+ return this.sendOnce(url, method, hdrs, undefined, effectiveTimeout, opts?.signal);
181
+ }, cookie, path, effectiveTimeout);
182
+ if (!response.ok) {
183
+ let body = "";
184
+ try {
185
+ body = await response.text();
186
+ }
187
+ catch {
188
+ /* ignore */
189
+ }
190
+ throw this.classifyHttpError(response.status, path, body || undefined);
191
+ }
192
+ const text = await response.text();
193
+ if (!isSafeHttpMethod(method)) {
194
+ tm1Events.emit("mutation", { method, path });
195
+ }
196
+ return text;
197
+ }
198
+ /**
199
+ * Make an authenticated HTTP request with a binary body (Buffer/Uint8Array).
200
+ * Used for blob/file uploads where the body is raw bytes (not JSON).
201
+ * Sends Content-Type: application/octet-stream by default.
202
+ * Re-auths once on 401 like request(). No network-error retries (non-safe methods).
203
+ */
204
+ /** @internal — for Service-layer use; not part of the public consumer API. */
205
+ async requestBinary(method, path, body, contentType = "application/octet-stream", opts) {
206
+ const url = `${this.config.baseUrl}${this.profile.resolveApiPath(path)}`;
207
+ const effectiveTimeout = opts?.timeoutMs ?? this.config.requestTimeoutMs;
208
+ const cookie = await this.sessionManager.ensureSession();
209
+ const response = await this.withReauth((c) => this.sendOnce(url, method, {
210
+ Cookie: `TM1SessionId=${c}`,
211
+ Accept: "application/json,*/*",
212
+ "Content-Type": contentType,
213
+ "User-Agent": USER_AGENT,
214
+ "TM1-SessionContext": USER_AGENT,
215
+ "TM1-Session-Context": USER_AGENT,
216
+ }, body, effectiveTimeout, opts?.signal), cookie, path, effectiveTimeout);
217
+ if (!response.ok) {
218
+ let errBody = "";
219
+ try {
220
+ errBody = await response.text();
221
+ }
222
+ catch {
223
+ /* ignore */
224
+ }
225
+ throw this.classifyHttpError(response.status, path, errBody || undefined);
226
+ }
227
+ if (!isSafeHttpMethod(method)) {
228
+ tm1Events.emit("mutation", { method, path });
229
+ }
230
+ }
231
+ /**
232
+ * Low-level single fetch with timeout + AbortSignal wiring.
233
+ * Does NOT handle 401, retries, or error classification — callers own that.
234
+ */
235
+ async sendOnce(url, method, headers, body, timeoutMs, externalSignal) {
236
+ const controller = new AbortController();
237
+ const timeout = setTimeout(() => controller.abort(new DOMException("Request timed out", "TimeoutError")), timeoutMs);
238
+ const unlink = linkAbortSignals(controller, externalSignal);
239
+ try {
240
+ return await tm1Fetch(url, {
241
+ method,
242
+ headers,
243
+ body,
244
+ signal: controller.signal,
245
+ dispatcher: getTm1Dispatcher(this.config),
246
+ });
247
+ }
248
+ finally {
249
+ clearTimeout(timeout);
250
+ unlink();
251
+ }
252
+ }
253
+ /**
254
+ * Wraps a send function with cookie-refresh-on-401 and timeout→LOCK_TIMEOUT mapping.
255
+ * Used by requestRaw and requestBinary (which have no network-retry loop).
256
+ * On 401: calls sessionManager.authenticate() and retries once with the new cookie.
257
+ * The caller is responsible for obtaining the initial cookie via ensureSession().
258
+ */
259
+ async withReauth(send, initialCookie, path, effectiveTimeout) {
260
+ let response;
261
+ try {
262
+ response = await send(initialCookie);
263
+ }
264
+ catch (err) {
265
+ if (isTimeoutError(err)) {
266
+ throw new TM1Error({
267
+ code: TM1ErrorCode.LOCK_TIMEOUT,
268
+ message: `Request to ${path} timed out after ${effectiveTimeout}ms`,
269
+ endpoint: path,
270
+ });
271
+ }
272
+ throw err;
273
+ }
274
+ if (response.status === 401) {
275
+ const newCookie = await this.sessionManager.authenticate(initialCookie);
276
+ try {
277
+ response = await send(newCookie);
278
+ }
279
+ catch (err) {
280
+ if (isTimeoutError(err)) {
281
+ throw new TM1Error({
282
+ code: TM1ErrorCode.LOCK_TIMEOUT,
283
+ message: `Request to ${path} timed out after ${effectiveTimeout}ms`,
284
+ endpoint: path,
285
+ });
286
+ }
287
+ throw err;
288
+ }
289
+ }
290
+ return response;
291
+ }
292
+ async executeRequest(url, method, cookie, body, timeoutMs, externalSignal) {
293
+ const headers = {
294
+ Cookie: `TM1SessionId=${cookie}`,
295
+ Accept: "application/json",
296
+ "Accept-Encoding": "gzip, deflate",
297
+ "User-Agent": USER_AGENT,
298
+ "TM1-SessionContext": USER_AGENT,
299
+ "TM1-Session-Context": USER_AGENT,
300
+ };
301
+ const isWriteMethod = method === "POST" || method === "PUT" || method === "PATCH";
302
+ if (body !== undefined || isWriteMethod) {
303
+ headers["Content-Type"] = "application/json";
304
+ }
305
+ const serializedBody = body !== undefined
306
+ ? JSON.stringify(body)
307
+ : isWriteMethod
308
+ ? ""
309
+ : undefined;
310
+ return this.sendOnce(url, method, headers, serializedBody, timeoutMs ?? this.config.requestTimeoutMs, externalSignal);
311
+ }
312
+ async handleResponse(response, endpoint) {
313
+ if (response.ok) {
314
+ const text = await response.text();
315
+ if (response.status === 204 || !text) {
316
+ return undefined;
317
+ }
318
+ this.logger.debug({ endpoint, status: response.status }, "Request successful");
319
+ try {
320
+ return JSON.parse(text);
321
+ }
322
+ catch {
323
+ throw new TM1Error({
324
+ code: TM1ErrorCode.TM1_ERROR,
325
+ message: `TM1 returned a non-JSON response body (status ${response.status}) for ${endpoint}. ` +
326
+ `This usually means a proxy or gateway returned HTML/text instead of the TM1 REST API.`,
327
+ httpStatus: response.status,
328
+ endpoint,
329
+ });
330
+ }
331
+ }
332
+ let details;
333
+ let errorBody;
334
+ try {
335
+ errorBody = await response.text();
336
+ if (errorBody) {
337
+ const parsed = JSON.parse(errorBody);
338
+ details = odataErrorText(parsed) ?? errorBody;
339
+ }
340
+ }
341
+ catch {
342
+ /* ignore parse errors */
343
+ }
344
+ const error = this.classifyHttpError(response.status, endpoint, details);
345
+ this.logger.error({ endpoint, status: response.status, code: error.code }, error.message);
346
+ throw error;
347
+ }
348
+ classifyHttpError(status, endpoint, details) {
349
+ return classifyHttpError(status, endpoint, details);
350
+ }
351
+ isNetworkError(error) {
352
+ return isNetworkErrorImpl(error);
353
+ }
354
+ }
355
+ /**
356
+ * Map an HTTP status + TM1 error text onto a TM1Error. Module-level (not just a
357
+ * TM1HttpClient method) because `$batch` sub-responses arrive as plain
358
+ * {status, body} records inside a 200 envelope — BatchService has to classify
359
+ * them itself, and must do it identically to a standalone request rather than
360
+ * with a drifting copy of these rules.
361
+ */
362
+ export function classifyHttpError(status, endpoint, rawDetails) {
363
+ // S4/S5: sanitize ONCE, here, where the server's own text enters our error
364
+ // model. Everything downstream reads the TM1Error this builds — the
365
+ // logger.error() in handleResponse and the MCP error envelope alike — so
366
+ // masking here covers both exits with no chance of one being forgotten.
367
+ //
368
+ // This is the gap key-based redaction cannot close: pino's `redact` masks a
369
+ // field NAMED password, but a TM1 failure such as
370
+ // "[ODBC Driver] login failed for PWD=hunter2" is a plain message string, and
371
+ // it went to the log and back to the client verbatim.
372
+ const details = rawDetails === undefined ? undefined : maskSecretValues(rawDetails);
373
+ {
374
+ // TM1 signals object-level security denial via the error MESSAGE, often
375
+ // with HTTP 400 (not 403) — e.g. reading a control cube as a non-admin
376
+ // returns 400 {"error":{"code":"65","message":"ObjectSecurityNoReadRights"}}.
377
+ // Classify by message so the caller gets PERMISSION_DENIED + its actionable
378
+ // hint instead of a generic TM1_ERROR. Verified live with a cube-only user.
379
+ if (details &&
380
+ /No(Read|Write|Admin)Rights|ObjectSecurity|SecurityAccess|not\s+authori[sz]ed/i.test(details)) {
381
+ return new TM1Error({
382
+ code: TM1ErrorCode.PERMISSION_DENIED,
383
+ message: details,
384
+ httpStatus: status,
385
+ endpoint,
386
+ details,
387
+ });
388
+ }
389
+ switch (status) {
390
+ case 401:
391
+ return new TM1Error({
392
+ code: TM1ErrorCode.AUTH_FAILED,
393
+ message: details ?? "Authentication failed",
394
+ httpStatus: status,
395
+ endpoint,
396
+ details,
397
+ });
398
+ case 403:
399
+ return new TM1Error({
400
+ code: TM1ErrorCode.PERMISSION_DENIED,
401
+ message: details ?? "Permission denied",
402
+ httpStatus: status,
403
+ endpoint,
404
+ details,
405
+ });
406
+ case 404:
407
+ return new TM1Error({
408
+ code: TM1ErrorCode.NOT_FOUND,
409
+ message: details ?? "Resource not found",
410
+ httpStatus: status,
411
+ endpoint,
412
+ details,
413
+ });
414
+ case 409:
415
+ return new TM1Error({
416
+ code: TM1ErrorCode.CONFLICT,
417
+ message: details ?? "Resource conflict",
418
+ httpStatus: status,
419
+ endpoint,
420
+ details,
421
+ });
422
+ default:
423
+ return new TM1Error({
424
+ code: TM1ErrorCode.TM1_ERROR,
425
+ message: details ?? `TM1 API error (HTTP ${status})`,
426
+ httpStatus: status,
427
+ endpoint,
428
+ details,
429
+ });
430
+ }
431
+ }
432
+ }
433
+ /**
434
+ * Is this a transient transport failure worth retrying (as opposed to our own
435
+ * timeout, a caller cancellation, or an application-level error)?
436
+ */
437
+ function isNetworkErrorImpl(error) {
438
+ {
439
+ // TimeoutError is our own request timeout — handled separately as LOCK_TIMEOUT,
440
+ // never treated as a retryable network blip.
441
+ if (error instanceof DOMException && error.name === "TimeoutError") {
442
+ return false;
443
+ }
444
+ // AbortError is never a retryable network blip. Our own request timeout
445
+ // aborts with name "TimeoutError" (handled above → LOCK_TIMEOUT). A plain
446
+ // "AbortError" can only come from a caller-supplied signal (cancellation),
447
+ // which must propagate immediately — retrying a cancelled request 3× is a
448
+ // bug. The request loop also guards opts.signal.aborted before reaching
449
+ // here; this is the defensive backstop for any other abort source. Match on
450
+ // name (not just DOMException) since some fetch impls throw a plain Error.
451
+ if (error instanceof Error && error.name === "AbortError") {
452
+ return false;
453
+ }
454
+ // Primary, robust path: undici surfaces the OS-level failure on the wrapped
455
+ // cause's `.code` (e.g. ECONNREFUSED, ENOTFOUND, ETIMEDOUT, ECONNRESET). Some
456
+ // raw socket errors expose `.code` directly. Classifying by code is stable
457
+ // across Node/undici versions and locale, unlike message-substring matching.
458
+ const causeCode = errorCodeOf(error.cause);
459
+ if (causeCode !== undefined && NETWORK_ERROR_CODES.has(causeCode)) {
460
+ return true;
461
+ }
462
+ const directCode = errorCodeOf(error);
463
+ if (directCode !== undefined && NETWORK_ERROR_CODES.has(directCode)) {
464
+ return true;
465
+ }
466
+ // Fallback: undici wraps every fetch-level network failure in
467
+ // `TypeError: fetch failed`. This catches wrappers whose cause carries no
468
+ // recognised code (or no cause at all) — preserves the old TypeError branch.
469
+ if (error instanceof TypeError) {
470
+ return true;
471
+ }
472
+ // Last-resort backstop: an error that stringified a network failure into its
473
+ // message without exposing a code or cause (rare, but the old code matched
474
+ // it — kept so nothing is silently dropped). Not the primary classifier.
475
+ if (error instanceof Error) {
476
+ const msg = error.message.toLowerCase();
477
+ return (msg.includes("fetch failed") ||
478
+ msg.includes("econnrefused") ||
479
+ msg.includes("enotfound") ||
480
+ msg.includes("etimedout") ||
481
+ msg.includes("network"));
482
+ }
483
+ return false;
484
+ }
485
+ }
486
+ /**
487
+ * OS/undici-level error codes that indicate a transient network failure worth
488
+ * retrying (connection refused, DNS failure, timeout, socket reset, etc.).
489
+ * undici exposes these on `err.cause.code`; raw sockets on `err.code`.
490
+ */
491
+ const NETWORK_ERROR_CODES = new Set([
492
+ "ECONNREFUSED", // connection actively refused (server down / wrong port)
493
+ "ENOTFOUND", // DNS: host not found
494
+ "EAI_AGAIN", // DNS: temporary resolution failure
495
+ "ETIMEDOUT", // OS-level connect/read timeout
496
+ "ECONNRESET", // socket reset by peer
497
+ "ECONNABORTED", // connection aborted mid-flight
498
+ "EPIPE", // broken pipe writing to a closed socket
499
+ "EHOSTUNREACH", // host unreachable
500
+ "ENETUNREACH", // network unreachable
501
+ "ENETDOWN", // network is down
502
+ "UND_ERR_CONNECT_TIMEOUT", // undici connect timeout
503
+ "UND_ERR_SOCKET", // undici socket error (e.g. other side closed)
504
+ ]);
505
+ /**
506
+ * Read a string `.code` off an unknown error-ish value, narrowing safely under
507
+ * strict TS (`cause`/`error` are `unknown`). Returns undefined if absent or not
508
+ * a string.
509
+ */
510
+ function errorCodeOf(value) {
511
+ if (typeof value !== "object" || value === null) {
512
+ return undefined;
513
+ }
514
+ const code = value.code;
515
+ return typeof code === "string" ? code : undefined;
516
+ }
517
+ /**
518
+ * Pull the message out of an OData error body. TM1 writes it two ways —
519
+ * `error.message` as a plain string, or `error.message.value` — so both are
520
+ * read, and anything else yields undefined so the caller can fall back to the
521
+ * raw body. Returning only strings matters: the previous chained-optional
522
+ * version could hand a whole object to a `string` field when `message` was an
523
+ * object without `value`.
524
+ */
525
+ function odataErrorText(parsed) {
526
+ if (typeof parsed !== "object" || parsed === null)
527
+ return undefined;
528
+ const err = parsed.error;
529
+ if (typeof err !== "object" || err === null)
530
+ return undefined;
531
+ const message = err.message;
532
+ if (typeof message === "string")
533
+ return message;
534
+ if (typeof message === "object" && message !== null) {
535
+ const value = message.value;
536
+ if (typeof value === "string")
537
+ return value;
538
+ }
539
+ return undefined;
540
+ }
541
+ function isTimeoutError(error) {
542
+ return error instanceof DOMException && error.name === "TimeoutError";
543
+ }
544
+ function sleep(ms) {
545
+ return new Promise((resolve) => setTimeout(resolve, ms));
546
+ }
547
+ //# sourceMappingURL=http.js.map
@@ -0,0 +1,123 @@
1
+ import { TM1Error } from "../../types.js";
2
+ import type { TM1HttpClient } from "../http.js";
3
+ /**
4
+ * Correlation id of the counter-probe's single sub-request. Namespaced so it
5
+ * can never collide with a caller id, and recognisable in a server-side log.
6
+ */
7
+ export declare const BATCH_PROBE_ID = "__tm1_mcp_batch_probe__";
8
+ export declare const BATCH_MAX_REQUESTS = 200;
9
+ export declare const BATCH_MAX_PAYLOAD_BYTES = 1000000;
10
+ export interface BatchRequest {
11
+ /** Caller-chosen correlation id. Must be unique within one execute() call. */
12
+ id: string;
13
+ method: "GET" | "POST" | "PATCH" | "DELETE";
14
+ /** Same `/api/v1/...` form the other services use; rerooted for v12 by the profile. */
15
+ path: string;
16
+ body?: unknown;
17
+ }
18
+ export type BatchSubResult = {
19
+ id: string;
20
+ status: number;
21
+ ok: true;
22
+ body: unknown;
23
+ } | {
24
+ id: string;
25
+ status: number;
26
+ ok: false;
27
+ error: TM1Error;
28
+ };
29
+ /**
30
+ * Thrown when the server cannot serve `$batch` at all (endpoint absent, method
31
+ * refused, or an envelope we cannot read). Distinct from a sub-request failure,
32
+ * which is reported per item. Callers catch ONLY this to fall back to their
33
+ * per-request path — never a sub-request error, and never a systemic
34
+ * transport/auth failure (those propagate).
35
+ *
36
+ * GUARANTEE for those callers: this is raised only before the first successful
37
+ * batch on the connection — i.e. only ever out of the caller's FIRST pass.
38
+ *
39
+ * What that does NOT mean: "nothing was committed". TM1's `$batch` is
40
+ * non-atomic (verified live against 11.8: a failing sub-request leaves its
41
+ * siblings in the same envelope committed), and an ambiguous status such as 500
42
+ * can arrive after the server already applied part of the envelope. A caller
43
+ * that restarts per-request MAY therefore re-issue writes that already took
44
+ * effect.
45
+ *
46
+ * The requirement on callers is therefore: THE FIRST PASS MUST BE REPLAY-SAFE.
47
+ * `ElementService.bulkUpsert` satisfies this because its first pass is
48
+ * create-only, and re-creating an existing element degrades to the upsert path.
49
+ * A future caller whose first pass mutates existing state must NOT rely on this
50
+ * error to fall back. See `BatchService.markUnsupported`.
51
+ */
52
+ export declare class BatchUnsupportedError extends Error {
53
+ constructor(reason: string);
54
+ }
55
+ export declare class BatchService {
56
+ private readonly http;
57
+ private supported;
58
+ private probeSpent;
59
+ constructor(http: TM1HttpClient);
60
+ /** True once a probe has established the server rejects `$batch` outright. */
61
+ get isKnownUnsupported(): boolean;
62
+ /**
63
+ * Record a "this server has no usable `$batch`" verdict — but ONLY while no
64
+ * batch has ever succeeded on this connection.
65
+ *
66
+ * That precondition is the whole safety argument for the caller's fallback.
67
+ * `BatchUnsupportedError` makes callers restart their operation on the
68
+ * per-request path. While `supported === null` no chunk has ever come back
69
+ * 200, so the failure can only be in the caller's FIRST pass. Note what that
70
+ * bounds: WHICH writes may be replayed, not WHETHER anything was committed —
71
+ * `$batch` is non-atomic, so sub-requests processed before the failure stay
72
+ * committed. Callers must keep that first pass replay-safe.
73
+ *
74
+ * Once `supported === true`, a later failure — a flaky gateway answering
75
+ * chunk 2 with HTML or a 400 — is a real error and is propagated verbatim, so
76
+ * a half-finished batch is never silently replayed. That is what keeps the
77
+ * destructive later passes (type PATCH, Components) out of the fallback
78
+ * window entirely: they only ever run after a batch has already succeeded.
79
+ *
80
+ * NOTE: for HTTP 400 the caller in `executeChunk` runs `counterProbe` BEFORE
81
+ * reaching here, so a payload-caused 400 never gets this far. This method
82
+ * still sees every other unsupported status directly.
83
+ *
84
+ * Returns the error to throw, or `undefined` when the verdict was refused.
85
+ */
86
+ private markUnsupported;
87
+ /**
88
+ * Settle an ambiguous first-call 400 by asking the endpoint the simplest
89
+ * question there is: one minimal, side-effect-free GET in a well-formed
90
+ * envelope.
91
+ *
92
+ * Judges the ENVELOPE only, exactly as `executeChunk` does — a readable
93
+ * `responses` array means `$batch` is served here, whatever status the probe's
94
+ * own sub-request came back with. That distinction is load-bearing: a
95
+ * locked-down account may well be refused `Configuration/ProductVersion`
96
+ * (reported INSIDE the envelope), and reading that as "no $batch" would
97
+ * reintroduce the very misdiagnosis this probe exists to remove.
98
+ *
99
+ * Returns `true` when `$batch` demonstrably works, `false` when the endpoint
100
+ * refuses even this envelope. THROWS on a systemic transport/auth/timeout
101
+ * failure: that proves nothing either way, so the caller must draw no
102
+ * conclusion and the outage surfaces instead — same rule `executeChunk`
103
+ * already applies via `rethrowIfSystemic`.
104
+ *
105
+ * Does not go through `execute`/`executeChunk`, so it cannot recurse into
106
+ * itself or into the unsupported-detection path.
107
+ */
108
+ private counterProbe;
109
+ /**
110
+ * Run `requests` in as few round-trips as possible and return one result per
111
+ * request, in the order given.
112
+ *
113
+ * A failing sub-request is DATA, not an exception: it comes back as
114
+ * `{ok:false, error}` so the caller can report partial success. Only a
115
+ * whole-envelope failure throws — `BatchUnsupportedError` if the server has no
116
+ * `$batch`, or the underlying TM1Error for a transport/auth/timeout failure.
117
+ *
118
+ * POST /api/v1/$batch
119
+ */
120
+ execute(requests: BatchRequest[]): Promise<BatchSubResult[]>;
121
+ private executeChunk;
122
+ }
123
+ //# sourceMappingURL=batch-service.d.ts.map