@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,809 @@
1
+ // Element domain service. Owns the OData calls under
2
+ // /api/v1/Dimensions('{d}')/Hierarchies('{h}')/Elements(...) — create, update,
3
+ // delete, move, bulk upsert, ElementAttribute definition CRUD, plus the
4
+ // element-attribute VALUE read/write that goes through the
5
+ // `}ElementAttributes_{Dim}` control cube. Those last two methods route
6
+ // through CellService for the underlying MDX read and cellset PATCH.
7
+ //
8
+ // See docs/ARCHITECTURE.md for the layering.
9
+ import { mapSettledWithConcurrency } from "../../lib/concurrency.js";
10
+ import { TM1Error, TM1ErrorCode } from "../../types.js";
11
+ import { BatchUnsupportedError } from "./batch-service.js";
12
+ import { rethrowIfSystemic } from "./fallback.js";
13
+ // Max in-flight per-element REST calls within a single bulkUpsert pass. Bounds
14
+ // pressure on TM1's worker pool (mirrors the cap the feeder-audit fan-out uses)
15
+ // while removing the serialized 2-3N round-trips on an explicitly-bulk op.
16
+ const BULK_UPSERT_CONCURRENCY = 8;
17
+ // OData key encoder: double ' per OData literal rules, then percent-encode.
18
+ const enc = (s) => encodeURIComponent(String(s).replace(/'/g, "''"));
19
+ // TM1 signals "element already exists" with different HTTP statuses across
20
+ // versions: some return 409 Conflict, but v11.x (REST 11.8) returns 400 with
21
+ // the message "An element with name ... already exists". Detect both so bulk
22
+ // upsert stays idempotent (update existing) rather than throwing on re-upsert.
23
+ export function isAlreadyExists(err) {
24
+ if (err.httpStatus === 409)
25
+ return true;
26
+ if (err.httpStatus === 400) {
27
+ const text = `${err.message} ${err.details ?? ""}`.toLowerCase();
28
+ return text.includes("already exists");
29
+ }
30
+ return false;
31
+ }
32
+ // TM1 may report an element's Type as the enum name ("Numeric"|"String"|
33
+ // "Consolidated") or its ordinal (1|2|3). Normalize to the name so callers can
34
+ // compare against ElementCreate.type regardless of representation.
35
+ function normalizeElementType(t) {
36
+ switch (t) {
37
+ case 1:
38
+ case "1":
39
+ return "Numeric";
40
+ case 2:
41
+ case "2":
42
+ return "String";
43
+ case 3:
44
+ case "3":
45
+ return "Consolidated";
46
+ default:
47
+ return String(t);
48
+ }
49
+ }
50
+ /**
51
+ * Reject with the first failure in ELEMENT order (not response order), so the
52
+ * error a caller sees is the same one the per-request path would surface.
53
+ * Successful sub-requests in the same batch stay committed — TM1's $batch is
54
+ * non-atomic — exactly as the concurrent per-request path already leaves
55
+ * earlier writes committed when a later one fails.
56
+ */
57
+ function throwFirstFailure(results, indexOf) {
58
+ let firstIndex = Number.POSITIVE_INFINITY;
59
+ let firstError;
60
+ for (const r of results) {
61
+ if (r.ok)
62
+ continue;
63
+ const i = indexOf(r.id);
64
+ if (i < firstIndex) {
65
+ firstIndex = i;
66
+ firstError = r.error;
67
+ }
68
+ }
69
+ if (firstError)
70
+ throw firstError;
71
+ }
72
+ export class ElementService {
73
+ http;
74
+ cells;
75
+ batch;
76
+ constructor(http, cells,
77
+ // Optional so a caller (and the existing unit tests) can build an
78
+ // ElementService that only ever uses the per-request path. Production wires
79
+ // it, which turns bulkUpsert's N round-trips into a handful of $batch calls.
80
+ batch) {
81
+ this.http = http;
82
+ this.cells = cells;
83
+ this.batch = batch;
84
+ }
85
+ /**
86
+ * Create an element in a hierarchy. Consolidated elements may include
87
+ * Components inline; their target elements must already exist.
88
+ * POST /api/v1/Dimensions('{d}')/Hierarchies('{h}')/Elements
89
+ */
90
+ /**
91
+ * Set edge weights that differ from TM1's default.
92
+ *
93
+ * TM1 accepts `Weight` inside a Components link payload and ignores it: the
94
+ * edge is created with weight 1 whatever the body said. Verified live — a
95
+ * consolidation created with weight -1 read back as 1 from the Edges
96
+ * collection itself, so no reader could have recovered the intent. The
97
+ * weight lives on the Edge entity and has to be PATCHed once the link
98
+ * exists.
99
+ *
100
+ * Only deviating weights cost a request: consolidations are overwhelmingly
101
+ * all-1, and a PATCH that sets 1 to 1 is a round trip for nothing.
102
+ */
103
+ async applyEdgeWeights(dimensionName, hierarchyName, parentName, components) {
104
+ const base = `/api/v1/Dimensions('${enc(dimensionName)}')/Hierarchies('${enc(hierarchyName)}')`;
105
+ for (const c of components) {
106
+ if (c.weight === undefined || c.weight === 1)
107
+ continue;
108
+ await this.http.request("PATCH", `${base}/Edges(ParentName='${enc(parentName)}',ComponentName='${enc(c.name)}')`, { Weight: c.weight });
109
+ }
110
+ }
111
+ /**
112
+ * Does an element resolve in a hierarchy the way TI would resolve it?
113
+ * The key lookup is TM1's own name resolution: case- and space-insensitive,
114
+ * and it accepts an alias (verified on 11.8.03500: 'northamerica' and the
115
+ * alias 'NA' both resolve 'North America'). 404 → false; anything else,
116
+ * including a denial, is rethrown — "you may not look" is not "missing".
117
+ * GET /api/v1/Dimensions('{d}')/Hierarchies('{h}')/Elements('{e}')?$select=Name
118
+ */
119
+ async exists(dimensionName, hierarchyName, elementName) {
120
+ try {
121
+ await this.http.request("GET", `/api/v1/Dimensions('${enc(dimensionName)}')/Hierarchies('${enc(hierarchyName)}')/Elements('${enc(elementName)}')?$select=Name`);
122
+ return true;
123
+ }
124
+ catch (e) {
125
+ if (e instanceof TM1Error && e.code === TM1ErrorCode.NOT_FOUND)
126
+ return false;
127
+ throw e;
128
+ }
129
+ }
130
+ async create(dimensionName, hierarchyName, element) {
131
+ const path = `/api/v1/Dimensions('${enc(dimensionName)}')/Hierarchies('${enc(hierarchyName)}')/Elements`;
132
+ const body = {
133
+ Name: element.name,
134
+ Type: element.type,
135
+ };
136
+ if (element.type === "Consolidated" &&
137
+ element.components &&
138
+ element.components.length > 0) {
139
+ body.Components = element.components.map((c) => ({
140
+ "@odata.id": `Dimensions('${enc(dimensionName)}')/Hierarchies('${enc(hierarchyName)}')/Elements('${enc(c.name)}')`,
141
+ }));
142
+ }
143
+ await this.http.request("POST", path, body);
144
+ if (element.components && element.components.length > 0) {
145
+ await this.applyEdgeWeights(dimensionName, hierarchyName, element.name, element.components);
146
+ }
147
+ }
148
+ /**
149
+ * Update an existing element (rename, type change, replace components).
150
+ * PATCH /api/v1/Dimensions('{d}')/Hierarchies('{h}')/Elements('{name}')
151
+ */
152
+ async update(dimensionName, hierarchyName, elementName, update) {
153
+ const path = `/api/v1/Dimensions('${enc(dimensionName)}')/Hierarchies('${enc(hierarchyName)}')/Elements('${enc(elementName)}')`;
154
+ const body = {};
155
+ if (update.newName !== undefined) {
156
+ body.Name = update.newName;
157
+ }
158
+ if (update.type !== undefined) {
159
+ body.Type = update.type;
160
+ }
161
+ if (update.components !== undefined) {
162
+ body.Components = update.components.map((c) => ({
163
+ "@odata.id": `Dimensions('${enc(dimensionName)}')/Hierarchies('${enc(hierarchyName)}')/Elements('${enc(c.name)}')`,
164
+ }));
165
+ }
166
+ await this.http.request("PATCH", path, body);
167
+ if (update.components !== undefined) {
168
+ await this.applyEdgeWeights(dimensionName, hierarchyName,
169
+ // A rename in the same PATCH takes effect immediately, so the edge
170
+ // key must use the NEW parent name.
171
+ update.newName ?? elementName, update.components);
172
+ }
173
+ }
174
+ /**
175
+ * Delete an element. May fail if the element is referenced in rules.
176
+ * DELETE /api/v1/Dimensions('{d}')/Hierarchies('{h}')/Elements('{name}')
177
+ */
178
+ async delete(dimensionName, hierarchyName, elementName) {
179
+ const path = `/api/v1/Dimensions('${enc(dimensionName)}')/Hierarchies('${enc(hierarchyName)}')/Elements('${enc(elementName)}')`;
180
+ await this.http.request("DELETE", path);
181
+ }
182
+ /**
183
+ * What a bulkUpsert of `elements` would do, read-only: which elements it
184
+ * creates, which it updates, which change type in place (a Numeric ->
185
+ * Consolidated/String conversion discards leaf data), and which existing
186
+ * children a `components` list would drop — components REPLACE the child
187
+ * set, they do not append.
188
+ *
189
+ * Computed BEFORE any write on purpose: bulkUpsert's $batch pass commits its
190
+ * creates as it goes (TM1's $batch is non-atomic), so a plan worked out
191
+ * afterwards could only report damage, not prevent it.
192
+ *
193
+ * One filtered read per 40 names — `Elements?$filter=Name eq … or …` with
194
+ * the edges expanded — instead of loading the hierarchy.
195
+ */
196
+ async planBulkUpsert(dimensionName, hierarchyName, elements) {
197
+ const base = `/api/v1/Dimensions('${enc(dimensionName)}')/Hierarchies('${enc(hierarchyName)}')/Elements`;
198
+ const lit = (n) => `'${n.replace(/'/g, "''")}'`;
199
+ const current = new Map();
200
+ const names = [...new Set(elements.map((e) => e.name))];
201
+ for (let i = 0; i < names.length; i += 40) {
202
+ const chunk = names.slice(i, i + 40);
203
+ const filter = chunk.map((n) => `Name eq ${lit(n)}`).join(" or ");
204
+ const page = await this.http.request("GET", `${base}?$select=Name,Type&$expand=Edges($select=ComponentName)&$filter=${encodeURIComponent(filter)}`);
205
+ for (const e of page.value)
206
+ current.set(e.Name.toLowerCase(), {
207
+ type: e.Type,
208
+ children: (e.Edges ?? []).map((x) => x.ComponentName),
209
+ });
210
+ }
211
+ const plan = {
212
+ creates: [],
213
+ updates: [],
214
+ typeChanges: [],
215
+ removals: [],
216
+ };
217
+ for (const el of elements) {
218
+ const now = current.get(el.name.toLowerCase());
219
+ if (!now) {
220
+ plan.creates.push(el.name);
221
+ continue;
222
+ }
223
+ plan.updates.push(el.name);
224
+ if (now.type !== el.type)
225
+ plan.typeChanges.push({ name: el.name, from: now.type, to: el.type });
226
+ if (el.type === "Consolidated" &&
227
+ el.components &&
228
+ el.components.length > 0) {
229
+ const keep = new Set(el.components.map((c) => c.name.toLowerCase()));
230
+ const dropped = now.children.filter((c) => !keep.has(c.toLowerCase()));
231
+ if (dropped.length > 0)
232
+ plan.removals.push({ parent: el.name, children: dropped });
233
+ }
234
+ }
235
+ return plan;
236
+ }
237
+ /**
238
+ * Delete many elements of one hierarchy. Through `$batch` when the server
239
+ * has it (one DELETE sub-request per element, chunked by BatchService), else
240
+ * per request with bounded concurrency.
241
+ *
242
+ * Never all-or-nothing: TM1's `$batch` is non-atomic, so each element gets
243
+ * its own result and one missing name does not stop the rest. A systemic
244
+ * failure (auth, transport) still aborts the call.
245
+ *
246
+ * Falling back after BatchUnsupportedError is safe: that error is only raised
247
+ * before the first successful batch on the connection. Should a refused
248
+ * envelope still have removed some elements, their per-request replay
249
+ * reports NOT_FOUND instead of claiming a second delete.
250
+ */
251
+ async deleteMany(dimensionName, hierarchyName, elementNames) {
252
+ const pathOf = (name) => `/api/v1/Dimensions('${enc(dimensionName)}')/Hierarchies('${enc(hierarchyName)}')/Elements('${enc(name)}')`;
253
+ const failed = (elementName, e) => ({
254
+ elementName,
255
+ deleted: false,
256
+ error: { code: e.code, message: e.message },
257
+ });
258
+ if (this.batch && !this.batch.isKnownUnsupported) {
259
+ try {
260
+ const results = await this.batch.execute(elementNames.map((name, i) => ({
261
+ id: `d${i}`,
262
+ method: "DELETE",
263
+ path: pathOf(name),
264
+ })));
265
+ const byIndex = new Map(results.map((r) => [Number(r.id.slice(1)), r]));
266
+ return elementNames.map((elementName, i) => {
267
+ const r = byIndex.get(i);
268
+ if (r === undefined)
269
+ return failed(elementName, new TM1Error({
270
+ code: TM1ErrorCode.TM1_ERROR,
271
+ message: "No sub-response for this element in the $batch reply.",
272
+ }));
273
+ return r.ok
274
+ ? { elementName, deleted: true }
275
+ : failed(elementName, r.error);
276
+ });
277
+ }
278
+ catch (err) {
279
+ if (!(err instanceof BatchUnsupportedError))
280
+ throw err;
281
+ }
282
+ }
283
+ const settled = await mapSettledWithConcurrency(elementNames, BULK_UPSERT_CONCURRENCY, async (name) => {
284
+ await this.http.request("DELETE", pathOf(name));
285
+ });
286
+ return settled.map((r, i) => {
287
+ const elementName = elementNames[i];
288
+ if (r.status === "fulfilled")
289
+ return { elementName, deleted: true };
290
+ rethrowIfSystemic(r.reason);
291
+ return failed(elementName, r.reason);
292
+ });
293
+ }
294
+ /**
295
+ * Scan element names in a hierarchy with a hard cap, paginating server-side.
296
+ *
297
+ * A single bulk Elements fetch can exceed V8's max string length on large
298
+ * dimensions (response.text() buffers the whole body into one string), so
299
+ * this probes the total via $count on the first page, then pages by
300
+ * `pageSize` until either `maxScan` names are collected or the hierarchy is
301
+ * exhausted. Callers learn the true `total` and whether the scan was
302
+ * `truncated` — never a silent skip. Owns the V8-string-limit workaround so
303
+ * tools don't reimplement raw OData paging.
304
+ *
305
+ * `opts.filter` narrows the scan to names matching an OData predicate, and
306
+ * changes what the numbers mean: the server then evaluates every element and
307
+ * returns only the matches, so `scanned` becomes the hierarchy total (the
308
+ * server checked all of it) and `truncated` reports a capped MATCH set
309
+ * rather than a partial walk. That is the difference between an audit that
310
+ * examines the first 100k names and one that examines the dimension —
311
+ * see src/lib/naming/odata-filter.ts.
312
+ *
313
+ * GET /api/v1/Dimensions('{d}')/Hierarchies('{h}')/Elements?$select=Name
314
+ */
315
+ async scanElementNames(dimensionName, hierarchyName, opts) {
316
+ const { pageSize, maxScan, filter, scopeTotal } = opts;
317
+ const hierarchyPath = `/api/v1/Dimensions('${enc(dimensionName)}')/Hierarchies('${enc(hierarchyName)}')`;
318
+ const basePath = `${hierarchyPath}/Elements?$select=Name&$top=${pageSize}` +
319
+ (filter ? `&$filter=${encodeURIComponent(filter)}` : "");
320
+ // First page carries $count=true so we learn the total in one round-trip
321
+ // without the /$count endpoint (TM1 v11 returns text/plain there and
322
+ // rejects the Accept: application/json the shared HTTP client sends).
323
+ const firstPage = await this.http.request("GET", `${basePath}&$skip=0&$count=true`);
324
+ const total = firstPage["@odata.count"] ?? firstPage.value.length;
325
+ const scanLimit = Math.min(total, maxScan);
326
+ const names = [];
327
+ const firstSliceEnd = Math.min(firstPage.value.length, scanLimit);
328
+ for (let i = 0; i < firstSliceEnd; i++) {
329
+ names.push(firstPage.value[i].Name);
330
+ }
331
+ let skip = firstPage.value.length;
332
+ let lastPageSize = firstPage.value.length;
333
+ while (lastPageSize === pageSize && names.length < scanLimit) {
334
+ const page = await this.http.request("GET", `${basePath}&$skip=${skip}`);
335
+ const remaining = scanLimit - names.length;
336
+ const sliceEnd = Math.min(page.value.length, remaining);
337
+ for (let i = 0; i < sliceEnd; i++) {
338
+ names.push(page.value[i].Name);
339
+ }
340
+ lastPageSize = page.value.length;
341
+ skip += page.value.length;
342
+ }
343
+ if (filter === undefined) {
344
+ return {
345
+ names,
346
+ total,
347
+ scanned: names.length,
348
+ truncated: total > maxScan,
349
+ };
350
+ }
351
+ // With a filter, `total` above counted the MATCHES. The caller still wants
352
+ // to report how large the hierarchy was; when it already knows, that costs
353
+ // nothing, otherwise one 145-byte probe.
354
+ let inScope = scopeTotal;
355
+ if (inScope === undefined) {
356
+ const scopeProbe = await this.http.request("GET", `${hierarchyPath}/Elements?$select=Name&$top=0&$count=true`);
357
+ inScope = scopeProbe["@odata.count"] ?? total;
358
+ }
359
+ return {
360
+ names,
361
+ total: inScope,
362
+ scanned: inScope,
363
+ truncated: total > maxScan,
364
+ };
365
+ }
366
+ /**
367
+ * Add an element as a component of a new parent.
368
+ * POST /api/v1/Dimensions('{d}')/Hierarchies('{h}')/Elements('{newParent}')/Components
369
+ */
370
+ async move(dimensionName, hierarchyName, elementName, newParent, weight) {
371
+ const path = `/api/v1/Dimensions('${enc(dimensionName)}')/Hierarchies('${enc(hierarchyName)}')/Elements('${enc(newParent)}')/Components`;
372
+ const body = {
373
+ "@odata.id": `Dimensions('${enc(dimensionName)}')/Hierarchies('${enc(hierarchyName)}')/Elements('${enc(elementName)}')`,
374
+ };
375
+ await this.http.request("POST", path, body);
376
+ await this.applyEdgeWeights(dimensionName, hierarchyName, newParent, [
377
+ { name: elementName, ...(weight !== undefined ? { weight } : {}) },
378
+ ]);
379
+ }
380
+ /**
381
+ * Bulk upsert elements into a hierarchy. Two-pass to ensure leaves exist
382
+ * before consolidations reference them: pass 1 creates/upserts every element
383
+ * (PATCH on 409), pass 2 sets Components for Consolidated elements.
384
+ * POST/PATCH /api/v1/Dimensions('{d}')/Hierarchies('{h}')/Elements(...)
385
+ *
386
+ * Prefers OData `$batch` (a handful of round-trips) and falls back to the
387
+ * per-request fan-out when the server has no `$batch` endpoint. Both paths
388
+ * produce the identical result and the identical throw-on-any-failure
389
+ * contract; only the number of HTTP calls differs.
390
+ */
391
+ async bulkUpsert(dimensionName, hierarchyName, elements) {
392
+ if (this.batch && !this.batch.isKnownUnsupported) {
393
+ try {
394
+ return await this.bulkUpsertViaBatch(dimensionName, hierarchyName, elements);
395
+ }
396
+ catch (err) {
397
+ // ONLY "this server has no $batch" falls through. A sub-request failure
398
+ // is not an exception here (it is reported per item and rethrown as the
399
+ // element error), and a systemic transport/auth error propagates from
400
+ // BatchService — neither may silently re-drive the writes.
401
+ //
402
+ // Restarting on the per-request path cannot duplicate or lose work —
403
+ // but NOT because nothing was committed. TM1's $batch is non-atomic
404
+ // (verified live), so an envelope that fails mid-way leaves the
405
+ // sub-requests it already processed in place. What makes the restart
406
+ // safe is WHICH sub-requests those can be: BatchService raises
407
+ // BatchUnsupportedError only before the first successful batch on the
408
+ // connection, and the only pass that can run before that is pass 1a —
409
+ // create-only. Re-creating an element the failed batch already created
410
+ // just takes the "already exists" upsert branch, sees the type it was
411
+ // created with, and patches nothing.
412
+ //
413
+ // The destructive passes are unreachable here by construction: pass 1c
414
+ // (Type PATCH) and pass 2 (Components) only run after pass 1a returned
415
+ // a valid envelope, which sets supported=true and disables this
416
+ // fallback. A batch that fails AFTER one has succeeded (flaky gateway
417
+ // mid-chunk) propagates as a real error instead — which matters,
418
+ // because replaying an already-applied Type PATCH would re-probe, see
419
+ // the new type, and report no typeChange for a conversion that did
420
+ // discard leaf values.
421
+ //
422
+ // tests/unit/batch-fallback-safety.test.ts pins both halves of this.
423
+ if (!(err instanceof BatchUnsupportedError))
424
+ throw err;
425
+ }
426
+ }
427
+ return this.bulkUpsertPerRequest(dimensionName, hierarchyName, elements);
428
+ }
429
+ /**
430
+ * `$batch` implementation of bulkUpsert: four PASSES regardless of element
431
+ * count — create-all, read-type-of-the-ones-that-existed,
432
+ * patch-the-types-that-differ, then the consolidation Components patches.
433
+ * Each pass is chunked inside BatchService by request count AND serialized
434
+ * size, so N elements cost roughly 4 * ceil(N/200) calls instead of N —
435
+ * more when the sub-requests are large enough to hit the byte budget first.
436
+ */
437
+ async bulkUpsertViaBatch(dimensionName, hierarchyName, elements) {
438
+ const batch = this.batch;
439
+ const baseUrl = `/api/v1/Dimensions('${enc(dimensionName)}')/Hierarchies('${enc(hierarchyName)}')/Elements`;
440
+ // Correlate by element INDEX, not name: names are caller-supplied and could
441
+ // repeat, which would collapse two sub-responses onto one id.
442
+ const idOf = (i) => `e${i}`;
443
+ const indexOf = (id) => Number(id.slice(1));
444
+ // Pass 1a — create every element. TM1 runs the batch in payload order and
445
+ // continues past failures, so one response comes back per element.
446
+ const created = await batch.execute(elements.map((el, i) => ({
447
+ id: idOf(i),
448
+ method: "POST",
449
+ path: baseUrl,
450
+ body: { Name: el.name, Type: el.type },
451
+ })));
452
+ // Split the failures: "already exists" is the upsert path, anything else is
453
+ // a genuine error that must abort the whole op (same contract as the
454
+ // per-request path). Keep element order so the thrown error is the first
455
+ // failure in element order, not the first to be noticed.
456
+ const existing = [];
457
+ for (const r of created) {
458
+ if (r.ok)
459
+ continue;
460
+ const i = indexOf(r.id);
461
+ if (isAlreadyExists(r.error))
462
+ existing.push(i);
463
+ else
464
+ throw r.error;
465
+ }
466
+ // Pass 1b — read the current Type of the elements that already existed, so
467
+ // a type change can be reported (and skipped when it is a no-op). A failed
468
+ // probe means "type unreadable" and falls through to the unconditional
469
+ // PATCH below, matching the per-request path's behaviour on a NOT_FOUND.
470
+ const probed = await batch.execute(existing.map((i) => ({
471
+ id: idOf(i),
472
+ method: "GET",
473
+ path: `${baseUrl}('${enc(elements[i].name)}')?$select=Type`,
474
+ })));
475
+ const typeById = new Map();
476
+ for (const r of probed) {
477
+ // A transport/auth outage must NOT collapse into "type unreadable": that
478
+ // would silently PATCH the type below and discard the element's leaf cell
479
+ // values on a network blip or an expired session — and report nothing in
480
+ // typeChanges, because an unreadable prior type yields no entry. Same
481
+ // guard the per-request path applies to its probe; only a genuine,
482
+ // non-systemic failure (e.g. NOT_FOUND) may degrade to null.
483
+ if (!r.ok)
484
+ rethrowIfSystemic(r.error);
485
+ const raw = r.ok
486
+ ? r.body?.Type
487
+ : undefined;
488
+ typeById.set(indexOf(r.id), raw === undefined || raw === null ? null : normalizeElementType(raw));
489
+ }
490
+ // Pass 1c — patch the types that actually differ, plus the unreadable ones.
491
+ const typeChanges = [];
492
+ const patches = [];
493
+ for (const i of existing) {
494
+ const el = elements[i];
495
+ const from = typeById.get(i) ?? null;
496
+ if (from !== null && from === el.type)
497
+ continue;
498
+ patches.push({
499
+ id: idOf(i),
500
+ method: "PATCH",
501
+ path: `${baseUrl}('${enc(el.name)}')`,
502
+ body: { Type: el.type },
503
+ });
504
+ // A Numeric->Consolidated / Numeric->String conversion discards the
505
+ // element's leaf cell values, so report it rather than let it happen
506
+ // silently. An unreadable prior type yields no entry, as before.
507
+ if (from !== null)
508
+ typeChanges.push({ name: el.name, from, to: el.type });
509
+ }
510
+ throwFirstFailure(await batch.execute(patches), indexOf);
511
+ // Pass barrier: every leaf write above has settled before any consolidation
512
+ // references it via Components. Pass 1 already threw on any hard failure.
513
+ //
514
+ // Pass 2 — PATCH {Components:[...]} is FULL-REPLACE, not append (verified
515
+ // live vs TM1 v11). Consolidations with no/empty components are skipped, so
516
+ // an upsert that omits components leaves existing children intact.
517
+ const components = [];
518
+ for (const [i, el] of elements.entries()) {
519
+ if (el.type !== "Consolidated" ||
520
+ !el.components ||
521
+ el.components.length === 0)
522
+ continue;
523
+ components.push({
524
+ id: idOf(i),
525
+ method: "PATCH",
526
+ path: `${baseUrl}('${enc(el.name)}')`,
527
+ body: {
528
+ Components: el.components.map((c) => ({
529
+ "@odata.id": `Dimensions('${enc(dimensionName)}')/Hierarchies('${enc(hierarchyName)}')/Elements('${enc(c.name)}')`,
530
+ Weight: c.weight,
531
+ })),
532
+ },
533
+ });
534
+ }
535
+ throwFirstFailure(await batch.execute(components), indexOf);
536
+ // Pass 3 — the weights. TM1 accepts `Weight` inside the Components link
537
+ // above and ignores it: every edge it creates has weight 1 (measured, see
538
+ // applyEdgeWeights). The weight lives on the Edge entity and has to be
539
+ // PATCHed once the link exists, which is only true after pass 2. Only
540
+ // deviating weights cost a request.
541
+ //
542
+ // Own id space: one element can own several edges, and a repeated id makes
543
+ // v12 reject the whole envelope. `edgeOwner` maps each request back to the
544
+ // element that asked for it, so a failure still names the right one.
545
+ const edges = [];
546
+ const edgeOwner = [];
547
+ for (const [i, el] of elements.entries()) {
548
+ if (el.type !== "Consolidated" || !el.components)
549
+ continue;
550
+ for (const c of el.components) {
551
+ if (c.weight === undefined || c.weight === 1)
552
+ continue;
553
+ edges.push({
554
+ id: `e${edgeOwner.length}`,
555
+ method: "PATCH",
556
+ path: `/api/v1/Dimensions('${enc(dimensionName)}')/Hierarchies('${enc(hierarchyName)}')/Edges(ParentName='${enc(el.name)}',ComponentName='${enc(c.name)}')`,
557
+ body: { Weight: c.weight },
558
+ });
559
+ edgeOwner.push(i);
560
+ }
561
+ }
562
+ if (edges.length > 0) {
563
+ throwFirstFailure(await batch.execute(edges), (id) => edgeOwner[Number(id.slice(1))] ?? Number.POSITIVE_INFINITY);
564
+ }
565
+ return { typeChanges };
566
+ }
567
+ /**
568
+ * Per-request fallback for bulkUpsert, used when the server has no `$batch`.
569
+ * Fans the calls out with bounded concurrency.
570
+ */
571
+ async bulkUpsertPerRequest(dimensionName, hierarchyName, elements) {
572
+ const baseUrl = `/api/v1/Dimensions('${enc(dimensionName)}')/Hierarchies('${enc(hierarchyName)}')/Elements`;
573
+ // Pass 1: Create/upsert all elements without components. Same-type element
574
+ // writes are independent, so fan them out with bounded concurrency instead
575
+ // of one serialized round-trip each (was 2-3N sequential calls). The cap
576
+ // keeps constant pressure on TM1's worker pool. Each unit returns its
577
+ // type-change (or null); we collect them index-aligned AFTER settle so
578
+ // typeChanges stays in stable element order regardless of completion order.
579
+ const pass1 = await mapSettledWithConcurrency(elements, BULK_UPSERT_CONCURRENCY, async (el) => {
580
+ const body = { Name: el.name, Type: el.type };
581
+ try {
582
+ await this.http.request("POST", baseUrl, body);
583
+ return null;
584
+ }
585
+ catch (err) {
586
+ if (err instanceof TM1Error && isAlreadyExists(err)) {
587
+ // Element already exists. Patch the type only when it actually
588
+ // differs (avoids a pointless write), and surface the change: a
589
+ // Numeric->Consolidated / Numeric->String conversion discards the
590
+ // element's leaf cell values, so the caller must be told it happened
591
+ // rather than have it occur silently.
592
+ const existing = await this.http
593
+ .request("GET", `${baseUrl}('${enc(el.name)}')?$select=Type`)
594
+ .catch((e) => {
595
+ // A transport/auth outage here must NOT collapse into the
596
+ // unconditional-PATCH branch below: that would silently change the
597
+ // element type (discarding leaf values) on a network blip. Only a
598
+ // genuine "type unreadable" (e.g. NOT_FOUND) may fall through to null.
599
+ rethrowIfSystemic(e);
600
+ return null;
601
+ });
602
+ const from = existing ? normalizeElementType(existing.Type) : null;
603
+ if (from && from !== el.type) {
604
+ await this.http.request("PATCH", `${baseUrl}('${enc(el.name)}')`, { Type: el.type });
605
+ return { name: el.name, from, to: el.type };
606
+ }
607
+ if (!from) {
608
+ // Type unreadable — preserve prior behaviour and patch unconditionally.
609
+ await this.http.request("PATCH", `${baseUrl}('${enc(el.name)}')`, { Type: el.type });
610
+ }
611
+ return null;
612
+ }
613
+ throw err;
614
+ }
615
+ });
616
+ // Pass barrier: surface the first pass-1 failure (in element order) BEFORE
617
+ // any consolidation write. Pass 2 references leaves via Components, so it
618
+ // must not start until every leaf has settled — concurrency is safe within
619
+ // a pass but NOT across this barrier. Rejecting here preserves the prior
620
+ // "bulkUpsert throws if any element failed" contract.
621
+ const typeChanges = [];
622
+ for (const r of pass1) {
623
+ if (r.status === "rejected")
624
+ throw r.reason;
625
+ if (r.value)
626
+ typeChanges.push(r.value);
627
+ }
628
+ // Pass 2: Set components for consolidated elements.
629
+ // PATCH {Components:[...]} is FULL-REPLACE, not append (verified live vs
630
+ // TM1 v11: upserting [L3,L4] over existing [L1,L2] leaves the element with
631
+ // exactly {L3,L4}). Consolidations with no/empty components are skipped
632
+ // here, so an upsert that omits components leaves existing children intact
633
+ // — only a non-empty list rewrites the child set. Documented on the tool's
634
+ // `components` input so callers don't silently drop children. These writes
635
+ // are mutually independent (each targets a distinct element), so they fan
636
+ // out with the same bounded concurrency.
637
+ const consolidated = elements.filter((el) => el.type === "Consolidated" && el.components && el.components.length > 0);
638
+ const pass2 = await mapSettledWithConcurrency(consolidated, BULK_UPSERT_CONCURRENCY, async (el) => {
639
+ const path = `${baseUrl}('${enc(el.name)}')`;
640
+ const body = {
641
+ Components: el.components.map((c) => ({
642
+ "@odata.id": `Dimensions('${enc(dimensionName)}')/Hierarchies('${enc(hierarchyName)}')/Elements('${enc(c.name)}')`,
643
+ Weight: c.weight,
644
+ })),
645
+ };
646
+ await this.http.request("PATCH", path, body);
647
+ });
648
+ for (const r of pass2) {
649
+ if (r.status === "rejected")
650
+ throw r.reason;
651
+ }
652
+ // Pass 3: the weights, for the same reason as the $batch path — TM1 takes
653
+ // `Weight` in the Components link and ignores it, so every edge lands at 1
654
+ // until it is PATCHed on the Edge entity. Runs after pass 2 because the
655
+ // edge has to exist first.
656
+ const pass3 = await mapSettledWithConcurrency(consolidated, BULK_UPSERT_CONCURRENCY, (el) => this.applyEdgeWeights(dimensionName, hierarchyName, el.name, el.components));
657
+ for (const r of pass3) {
658
+ if (r.status === "rejected")
659
+ throw r.reason;
660
+ }
661
+ return { typeChanges };
662
+ }
663
+ /**
664
+ * List element-attribute definitions for a hierarchy.
665
+ * GET /api/v1/Dimensions('{d}')/Hierarchies('{h}')/ElementAttributes
666
+ */
667
+ async listAttributes(dimensionName, hierarchyName) {
668
+ const path = `/api/v1/Dimensions('${enc(dimensionName)}')/Hierarchies('${enc(hierarchyName)}')/ElementAttributes`;
669
+ const response = await this.http.request("GET", path);
670
+ return response.value.map((a) => ({
671
+ name: a.Name,
672
+ type: a.Type,
673
+ }));
674
+ }
675
+ /**
676
+ * Define a new element attribute on a hierarchy. Prefer TI prolog
677
+ * (DimensionElementInsert on `}ElementAttributes_{dim}`) for reproducible
678
+ * deployments — this REST path is for ad-hoc / debugging use.
679
+ * POST /api/v1/Dimensions('{d}')/Hierarchies('{h}')/ElementAttributes
680
+ */
681
+ async createAttribute(dimensionName, hierarchyName, attributeName, attributeType) {
682
+ const path = `/api/v1/Dimensions('${enc(dimensionName)}')/Hierarchies('${enc(hierarchyName)}')/ElementAttributes`;
683
+ await this.http.request("POST", path, {
684
+ Name: attributeName,
685
+ Type: attributeType,
686
+ });
687
+ }
688
+ /**
689
+ * Read all attribute values for one element via MDX on
690
+ * `}ElementAttributes_{Dim}`. Routes through CellService.executeMdx for the
691
+ * cellset round-trip.
692
+ */
693
+ async getAttributeValues(dimensionName, elementName) {
694
+ // Escape `]` → `]]` in every bracketed identifier: an element or dimension
695
+ // named e.g. `Foo]` would otherwise break out of its MDX identifier and
696
+ // shift the read onto arbitrary members (MDX injection).
697
+ const esc = (s) => s.replace(/]/g, "]]");
698
+ const dim = esc(dimensionName);
699
+ const elem = esc(elementName);
700
+ const ctrlCube = `}ElementAttributes_${dim}`;
701
+ const mdx = `SELECT {[}ElementAttributes_${dim}].MEMBERS} ON COLUMNS ` +
702
+ `FROM [${ctrlCube}] ` +
703
+ `WHERE ([${dim}].[${elem}])`;
704
+ const result = await this.cells.executeMdx(mdx);
705
+ const out = [];
706
+ const tuples = result.axes[0]?.tuples ?? [];
707
+ for (let i = 0; i < tuples.length; i++) {
708
+ const attrName = tuples[i].members[0]?.name ?? "";
709
+ const cell = result.cells[i];
710
+ out.push({
711
+ elementName,
712
+ attributeName: attrName,
713
+ value: cell?.value ?? null,
714
+ });
715
+ }
716
+ return out;
717
+ }
718
+ /**
719
+ * Attribute values for a window of elements — every element of the
720
+ * dimension's default hierarchy, name-sorted, `limit` at a time. One MDX
721
+ * against `}ElementAttributes_{Dim}` with the window pushed into the row set
722
+ * (`SUBSET(TM1SORT(TM1SUBSETALL(...)))`), so the query text stays short no
723
+ * matter how many elements a page holds — TM1's request entity limit can be
724
+ * as low as 32 KB. `total` comes from `$count` on the Elements collection.
725
+ *
726
+ * `attributeNames` narrows the columns; omitted, every attribute is read.
727
+ */
728
+ async getAttributeValuesPage(dimensionName, opts) {
729
+ const countPath = `/api/v1/Dimensions('${enc(dimensionName)}')/Hierarchies('${enc(dimensionName)}')/Elements?$select=Name&$top=1&$count=true`;
730
+ const counted = await this.http.request("GET", countPath);
731
+ const total = counted["@odata.count"] ?? 0;
732
+ if (opts.limit === 0 || opts.offset >= total)
733
+ return { total, items: [] };
734
+ const esc = (s) => s.replace(/]/g, "]]");
735
+ const dim = esc(dimensionName);
736
+ const attrDim = `[}ElementAttributes_${dim}].[}ElementAttributes_${dim}]`;
737
+ const columns = opts.attributeNames && opts.attributeNames.length > 0
738
+ ? `{${opts.attributeNames.map((a) => `${attrDim}.[${esc(a)}]`).join(", ")}}`
739
+ : `{TM1SUBSETALL(${attrDim})}`;
740
+ const mdx = `SELECT ${columns} ON COLUMNS, ` +
741
+ `SUBSET(TM1SORT({TM1SUBSETALL([${dim}].[${dim}])}, ASC), ${opts.offset}, ${opts.limit}) ON ROWS ` +
742
+ `FROM [}ElementAttributes_${dim}]`;
743
+ const result = await this.cells.executeMdx(mdx);
744
+ const attrs = (result.axes[0]?.tuples ?? []).map((t) => t.members[0]?.name ?? "");
745
+ const rows = result.axes[1]?.tuples ?? [];
746
+ // Cells are row-major: cell (r, c) sits at r * columns + c.
747
+ const items = rows.map((t, r) => {
748
+ const values = {};
749
+ attrs.forEach((a, c) => {
750
+ values[a] = result.cells[r * attrs.length + c]?.value ?? null;
751
+ });
752
+ return { elementName: t.members[0]?.name ?? "", values };
753
+ });
754
+ return { total, items };
755
+ }
756
+ /**
757
+ * Set a single attribute value. See {@link updateAttributeValues}.
758
+ */
759
+ async updateAttributeValue(dimensionName, elementName, attributeName, value) {
760
+ await this.updateAttributeValues(dimensionName, [
761
+ { elementName, attributeName, value },
762
+ ]);
763
+ }
764
+ /**
765
+ * Set attribute values by writing to the `}ElementAttributes_{Dim}` control
766
+ * cube — every update in ONE cellset write (CellService.writeCells).
767
+ *
768
+ * Values are coerced to the attribute's type, looked up once: a Numeric
769
+ * attribute takes a number or a numeric string (`"12.5"`), String and Alias
770
+ * attributes take the value as text. An unknown attribute or a non-numeric
771
+ * value for a Numeric attribute is a VALIDATION_ERROR that names it, raised
772
+ * before anything is written.
773
+ *
774
+ * Prefer TI processes (CellPutS / AttrPutS) for reproducible deployments;
775
+ * this REST-direct path is for ad-hoc / debugging use.
776
+ */
777
+ async updateAttributeValues(dimensionName, updates) {
778
+ if (updates.length === 0)
779
+ return;
780
+ const types = new Map((await this.listAttributes(dimensionName, dimensionName)).map((a) => [
781
+ a.name,
782
+ a.type,
783
+ ]));
784
+ const cells = updates.map((u) => {
785
+ const type = types.get(u.attributeName);
786
+ if (type === undefined) {
787
+ throw new TM1Error({
788
+ code: TM1ErrorCode.VALIDATION_ERROR,
789
+ message: `Attribute '${u.attributeName}' does not exist on dimension '${dimensionName}'.`,
790
+ hint: `Known attributes: ${[...types.keys()].join(", ") || "(none)"}. Create it first with tm1_create_element_attribute.`,
791
+ });
792
+ }
793
+ let value = String(u.value);
794
+ if (type === "Numeric") {
795
+ const n = typeof u.value === "number" ? u.value : Number(u.value.trim());
796
+ if (u.value === "" || !Number.isFinite(n)) {
797
+ throw new TM1Error({
798
+ code: TM1ErrorCode.VALIDATION_ERROR,
799
+ message: `Attribute '${u.attributeName}' is Numeric; '${String(u.value)}' (element '${u.elementName}') is not a number.`,
800
+ });
801
+ }
802
+ value = n;
803
+ }
804
+ return { elements: [u.elementName, u.attributeName], value };
805
+ });
806
+ await this.cells.writeCells(`}ElementAttributes_${dimensionName}`, [dimensionName, `}ElementAttributes_${dimensionName}`], cells);
807
+ }
808
+ }
809
+ //# sourceMappingURL=element-service.js.map