@salesforce/b2c-tooling-sdk 0.3.0 → 0.4.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 (350) hide show
  1. package/README.md +180 -13
  2. package/data/scaffolds/cartridge/files/.project.ejs +17 -0
  3. package/data/scaffolds/cartridge/files/cartridge/cartridge.properties.ejs +4 -0
  4. package/data/scaffolds/cartridge/files/cartridge/controllers/Example.js.ejs +19 -0
  5. package/data/scaffolds/cartridge/files/cartridge/models/example.js.ejs +14 -0
  6. package/data/scaffolds/cartridge/files/cartridge/scripts/helpers/exampleHelpers.js.ejs +18 -0
  7. package/data/scaffolds/cartridge/files/cartridge/static/default/css/example.css +6 -0
  8. package/data/scaffolds/cartridge/files/cartridge/templates/default/example/show.isml.ejs +11 -0
  9. package/data/scaffolds/cartridge/scaffold.json +88 -0
  10. package/data/scaffolds/controller/files/controller.js.ejs +134 -0
  11. package/data/scaffolds/controller/files/template.isml.ejs +22 -0
  12. package/data/scaffolds/controller/scaffold.json +64 -0
  13. package/data/scaffolds/custom-api/files/api.json.ejs +11 -0
  14. package/data/scaffolds/custom-api/files/schema.yaml.ejs +188 -0
  15. package/data/scaffolds/custom-api/files/script.js.ejs +95 -0
  16. package/data/scaffolds/custom-api/scaffold.json +65 -0
  17. package/data/scaffolds/hook/files/hook.js.ejs +99 -0
  18. package/data/scaffolds/hook/files/hooks-entry.json.ejs +6 -0
  19. package/data/scaffolds/hook/scaffold.json +60 -0
  20. package/data/scaffolds/job-step/files/step-chunk.js.ejs +136 -0
  21. package/data/scaffolds/job-step/files/step-task.js.ejs +47 -0
  22. package/data/scaffolds/job-step/files/steptypes-entry.json.ejs +41 -0
  23. package/data/scaffolds/job-step/scaffold.json +64 -0
  24. package/data/scaffolds/page-designer-component/files/component.isml.ejs +23 -0
  25. package/data/scaffolds/page-designer-component/files/component.js.ejs +35 -0
  26. package/data/scaffolds/page-designer-component/files/component.json.ejs +50 -0
  27. package/data/scaffolds/page-designer-component/scaffold.json +66 -0
  28. package/data/scaffolds/service/files/service-http.js.ejs +245 -0
  29. package/data/scaffolds/service/files/service-sftp.js.ejs +371 -0
  30. package/data/scaffolds/service/files/service-soap.js.ejs +230 -0
  31. package/data/scaffolds/service/scaffold.json +83 -0
  32. package/data/script-api/dw.extensions.payments.SalesforcePaymentsMgr.md +48 -0
  33. package/data/script-api/dw.system.Request.md +5 -0
  34. package/data/script-api/dw.web.Cookie.md +108 -31
  35. package/data/script-api/index.json +2 -2
  36. package/data/script-api/index.md +1 -1
  37. package/dist/cjs/auth/oauth-implicit.d.ts +1 -0
  38. package/dist/cjs/auth/oauth-implicit.js +8 -3
  39. package/dist/cjs/auth/oauth-implicit.js.map +1 -1
  40. package/dist/cjs/auth/oauth.d.ts +1 -0
  41. package/dist/cjs/auth/oauth.js +8 -3
  42. package/dist/cjs/auth/oauth.js.map +1 -1
  43. package/dist/cjs/auth/types.d.ts +5 -0
  44. package/dist/cjs/auth/types.js.map +1 -1
  45. package/dist/cjs/cli/am-command.d.ts +74 -0
  46. package/dist/cjs/cli/am-command.js +189 -0
  47. package/dist/cjs/cli/am-command.js.map +1 -0
  48. package/dist/cjs/cli/base-command.d.ts +38 -0
  49. package/dist/cjs/cli/base-command.js +142 -0
  50. package/dist/cjs/cli/base-command.js.map +1 -1
  51. package/dist/cjs/cli/config.d.ts +9 -0
  52. package/dist/cjs/cli/config.js +19 -2
  53. package/dist/cjs/cli/config.js.map +1 -1
  54. package/dist/cjs/cli/index.d.ts +1 -0
  55. package/dist/cjs/cli/index.js +1 -0
  56. package/dist/cjs/cli/index.js.map +1 -1
  57. package/dist/cjs/cli/instance-command.d.ts +1 -0
  58. package/dist/cjs/cli/oauth-command.d.ts +21 -1
  59. package/dist/cjs/cli/oauth-command.js +52 -7
  60. package/dist/cjs/cli/oauth-command.js.map +1 -1
  61. package/dist/cjs/cli/ods-command.d.ts +5 -1
  62. package/dist/cjs/cli/ods-command.js +10 -4
  63. package/dist/cjs/cli/ods-command.js.map +1 -1
  64. package/dist/cjs/cli/webdav-command.d.ts +1 -0
  65. package/dist/cjs/clients/am-api.d.ts +491 -0
  66. package/dist/cjs/clients/am-api.js +944 -0
  67. package/dist/cjs/clients/am-api.js.map +1 -0
  68. package/dist/cjs/clients/am-apiclients-api.generated.d.ts +803 -0
  69. package/dist/cjs/clients/am-apiclients-api.generated.js +6 -0
  70. package/dist/cjs/clients/am-apiclients-api.generated.js.map +1 -0
  71. package/dist/cjs/clients/am-roles-api.generated.d.ts +298 -0
  72. package/dist/cjs/clients/am-roles-api.generated.js +6 -0
  73. package/dist/cjs/clients/am-roles-api.generated.js.map +1 -0
  74. package/dist/cjs/clients/am-users-api.generated.d.ts +891 -0
  75. package/dist/cjs/clients/am-users-api.generated.js +6 -0
  76. package/dist/cjs/clients/am-users-api.generated.js.map +1 -0
  77. package/dist/cjs/clients/index.d.ts +4 -2
  78. package/dist/cjs/clients/index.js +2 -1
  79. package/dist/cjs/clients/index.js.map +1 -1
  80. package/dist/cjs/clients/middleware-registry.d.ts +1 -1
  81. package/dist/cjs/clients/middleware-registry.js.map +1 -1
  82. package/dist/cjs/clients/middleware.d.ts +49 -2
  83. package/dist/cjs/clients/middleware.js +214 -2
  84. package/dist/cjs/clients/middleware.js.map +1 -1
  85. package/dist/cjs/clients/mrt.js +5 -1
  86. package/dist/cjs/clients/mrt.js.map +1 -1
  87. package/dist/cjs/config/dw-json.d.ts +104 -33
  88. package/dist/cjs/config/dw-json.js +167 -2
  89. package/dist/cjs/config/dw-json.js.map +1 -1
  90. package/dist/cjs/config/index.d.ts +6 -4
  91. package/dist/cjs/config/index.js +6 -2
  92. package/dist/cjs/config/index.js.map +1 -1
  93. package/dist/cjs/config/instance-manager.d.ts +97 -0
  94. package/dist/cjs/config/instance-manager.js +166 -0
  95. package/dist/cjs/config/instance-manager.js.map +1 -0
  96. package/dist/cjs/config/mapping.d.ts +63 -5
  97. package/dist/cjs/config/mapping.js +165 -20
  98. package/dist/cjs/config/mapping.js.map +1 -1
  99. package/dist/cjs/config/sources/dw-json-source.d.ts +17 -1
  100. package/dist/cjs/config/sources/dw-json-source.js +70 -3
  101. package/dist/cjs/config/sources/dw-json-source.js.map +1 -1
  102. package/dist/cjs/config/sources/package-json-source.js +6 -3
  103. package/dist/cjs/config/sources/package-json-source.js.map +1 -1
  104. package/dist/cjs/config/types.d.ts +72 -0
  105. package/dist/cjs/defaults.d.ts +6 -0
  106. package/dist/cjs/defaults.js +6 -0
  107. package/dist/cjs/defaults.js.map +1 -1
  108. package/dist/cjs/i18n/index.js +3 -0
  109. package/dist/cjs/i18n/index.js.map +1 -1
  110. package/dist/cjs/index.d.ts +8 -4
  111. package/dist/cjs/index.js +9 -3
  112. package/dist/cjs/index.js.map +1 -1
  113. package/dist/cjs/logging/logger.js +13 -1
  114. package/dist/cjs/logging/logger.js.map +1 -1
  115. package/dist/cjs/operations/content/asset-query.d.ts +22 -0
  116. package/dist/cjs/operations/content/asset-query.js +77 -0
  117. package/dist/cjs/operations/content/asset-query.js.map +1 -0
  118. package/dist/cjs/operations/content/export.d.ts +57 -0
  119. package/dist/cjs/operations/content/export.js +224 -0
  120. package/dist/cjs/operations/content/export.js.map +1 -0
  121. package/dist/cjs/operations/content/index.d.ts +43 -0
  122. package/dist/cjs/operations/content/index.js +48 -0
  123. package/dist/cjs/operations/content/index.js.map +1 -0
  124. package/dist/cjs/operations/content/library.d.ts +137 -0
  125. package/dist/cjs/operations/content/library.js +392 -0
  126. package/dist/cjs/operations/content/library.js.map +1 -0
  127. package/dist/cjs/operations/content/types.d.ts +144 -0
  128. package/dist/cjs/operations/content/types.js +7 -0
  129. package/dist/cjs/operations/content/types.js.map +1 -0
  130. package/dist/cjs/operations/mrt/b2c-config.js +19 -4
  131. package/dist/cjs/operations/mrt/b2c-config.js.map +1 -1
  132. package/dist/cjs/operations/mrt/index.d.ts +2 -0
  133. package/dist/cjs/operations/mrt/index.js +2 -0
  134. package/dist/cjs/operations/mrt/index.js.map +1 -1
  135. package/dist/cjs/operations/mrt/tail-logs.d.ts +130 -0
  136. package/dist/cjs/operations/mrt/tail-logs.js +223 -0
  137. package/dist/cjs/operations/mrt/tail-logs.js.map +1 -0
  138. package/dist/cjs/operations/ods/index.d.ts +2 -0
  139. package/dist/cjs/operations/ods/index.js +1 -0
  140. package/dist/cjs/operations/ods/index.js.map +1 -1
  141. package/dist/cjs/operations/ods/wait-for-sandbox.d.ts +64 -0
  142. package/dist/cjs/operations/ods/wait-for-sandbox.js +114 -0
  143. package/dist/cjs/operations/ods/wait-for-sandbox.js.map +1 -0
  144. package/dist/cjs/operations/orgs/index.d.ts +74 -0
  145. package/dist/cjs/operations/orgs/index.js +33 -0
  146. package/dist/cjs/operations/orgs/index.js.map +1 -0
  147. package/dist/cjs/operations/roles/index.d.ts +43 -0
  148. package/dist/cjs/operations/roles/index.js +48 -0
  149. package/dist/cjs/operations/roles/index.js.map +1 -0
  150. package/dist/cjs/operations/users/index.d.ts +143 -0
  151. package/dist/cjs/operations/users/index.js +141 -0
  152. package/dist/cjs/operations/users/index.js.map +1 -0
  153. package/dist/cjs/scaffold/engine.d.ts +68 -0
  154. package/dist/cjs/scaffold/engine.js +149 -0
  155. package/dist/cjs/scaffold/engine.js.map +1 -0
  156. package/dist/cjs/scaffold/executor.d.ts +36 -0
  157. package/dist/cjs/scaffold/executor.js +285 -0
  158. package/dist/cjs/scaffold/executor.js.map +1 -0
  159. package/dist/cjs/scaffold/index.d.ts +74 -0
  160. package/dist/cjs/scaffold/index.js +23 -0
  161. package/dist/cjs/scaffold/index.js.map +1 -0
  162. package/dist/cjs/scaffold/merge.d.ts +56 -0
  163. package/dist/cjs/scaffold/merge.js +183 -0
  164. package/dist/cjs/scaffold/merge.js.map +1 -0
  165. package/dist/cjs/scaffold/parameter-resolver.d.ts +86 -0
  166. package/dist/cjs/scaffold/parameter-resolver.js +179 -0
  167. package/dist/cjs/scaffold/parameter-resolver.js.map +1 -0
  168. package/dist/cjs/scaffold/registry.d.ts +45 -0
  169. package/dist/cjs/scaffold/registry.js +219 -0
  170. package/dist/cjs/scaffold/registry.js.map +1 -0
  171. package/dist/cjs/scaffold/sources.d.ts +45 -0
  172. package/dist/cjs/scaffold/sources.js +113 -0
  173. package/dist/cjs/scaffold/sources.js.map +1 -0
  174. package/dist/cjs/scaffold/types.d.ts +280 -0
  175. package/dist/cjs/scaffold/types.js +14 -0
  176. package/dist/cjs/scaffold/types.js.map +1 -0
  177. package/dist/cjs/scaffold/validation.d.ts +81 -0
  178. package/dist/cjs/scaffold/validation.js +250 -0
  179. package/dist/cjs/scaffold/validation.js.map +1 -0
  180. package/dist/cjs/scaffold/validators.d.ts +33 -0
  181. package/dist/cjs/scaffold/validators.js +334 -0
  182. package/dist/cjs/scaffold/validators.js.map +1 -0
  183. package/dist/cjs/telemetry/index.d.ts +26 -0
  184. package/dist/cjs/telemetry/index.js +32 -0
  185. package/dist/cjs/telemetry/index.js.map +1 -0
  186. package/dist/cjs/telemetry/telemetry.d.ts +90 -0
  187. package/dist/cjs/telemetry/telemetry.js +283 -0
  188. package/dist/cjs/telemetry/telemetry.js.map +1 -0
  189. package/dist/cjs/telemetry/types.d.ts +62 -0
  190. package/dist/cjs/telemetry/types.js +7 -0
  191. package/dist/cjs/telemetry/types.js.map +1 -0
  192. package/dist/esm/auth/oauth-implicit.d.ts +1 -0
  193. package/dist/esm/auth/oauth-implicit.js +8 -3
  194. package/dist/esm/auth/oauth-implicit.js.map +1 -1
  195. package/dist/esm/auth/oauth.d.ts +1 -0
  196. package/dist/esm/auth/oauth.js +8 -3
  197. package/dist/esm/auth/oauth.js.map +1 -1
  198. package/dist/esm/auth/types.d.ts +5 -0
  199. package/dist/esm/auth/types.js.map +1 -1
  200. package/dist/esm/cli/am-command.d.ts +74 -0
  201. package/dist/esm/cli/am-command.js +196 -0
  202. package/dist/esm/cli/am-command.js.map +1 -0
  203. package/dist/esm/cli/base-command.d.ts +38 -0
  204. package/dist/esm/cli/base-command.js +142 -0
  205. package/dist/esm/cli/base-command.js.map +1 -1
  206. package/dist/esm/cli/config.d.ts +9 -0
  207. package/dist/esm/cli/config.js +19 -2
  208. package/dist/esm/cli/config.js.map +1 -1
  209. package/dist/esm/cli/index.d.ts +1 -0
  210. package/dist/esm/cli/index.js +1 -0
  211. package/dist/esm/cli/index.js.map +1 -1
  212. package/dist/esm/cli/instance-command.d.ts +1 -0
  213. package/dist/esm/cli/oauth-command.d.ts +21 -1
  214. package/dist/esm/cli/oauth-command.js +52 -7
  215. package/dist/esm/cli/oauth-command.js.map +1 -1
  216. package/dist/esm/cli/ods-command.d.ts +5 -1
  217. package/dist/esm/cli/ods-command.js +10 -4
  218. package/dist/esm/cli/ods-command.js.map +1 -1
  219. package/dist/esm/cli/webdav-command.d.ts +1 -0
  220. package/dist/esm/clients/am-api.d.ts +491 -0
  221. package/dist/esm/clients/am-api.js +944 -0
  222. package/dist/esm/clients/am-api.js.map +1 -0
  223. package/dist/esm/clients/am-apiclients-api.generated.d.ts +803 -0
  224. package/dist/esm/clients/am-apiclients-api.generated.js +6 -0
  225. package/dist/esm/clients/am-apiclients-api.generated.js.map +1 -0
  226. package/dist/esm/clients/am-roles-api.generated.d.ts +298 -0
  227. package/dist/esm/clients/am-roles-api.generated.js +6 -0
  228. package/dist/esm/clients/am-roles-api.generated.js.map +1 -0
  229. package/dist/esm/clients/am-users-api.generated.d.ts +891 -0
  230. package/dist/esm/clients/am-users-api.generated.js +6 -0
  231. package/dist/esm/clients/am-users-api.generated.js.map +1 -0
  232. package/dist/esm/clients/index.d.ts +4 -2
  233. package/dist/esm/clients/index.js +2 -1
  234. package/dist/esm/clients/index.js.map +1 -1
  235. package/dist/esm/clients/middleware-registry.d.ts +1 -1
  236. package/dist/esm/clients/middleware-registry.js.map +1 -1
  237. package/dist/esm/clients/middleware.d.ts +49 -2
  238. package/dist/esm/clients/middleware.js +214 -2
  239. package/dist/esm/clients/middleware.js.map +1 -1
  240. package/dist/esm/clients/mrt.js +5 -1
  241. package/dist/esm/clients/mrt.js.map +1 -1
  242. package/dist/esm/config/dw-json.d.ts +104 -33
  243. package/dist/esm/config/dw-json.js +167 -2
  244. package/dist/esm/config/dw-json.js.map +1 -1
  245. package/dist/esm/config/index.d.ts +6 -4
  246. package/dist/esm/config/index.js +6 -2
  247. package/dist/esm/config/index.js.map +1 -1
  248. package/dist/esm/config/instance-manager.d.ts +97 -0
  249. package/dist/esm/config/instance-manager.js +166 -0
  250. package/dist/esm/config/instance-manager.js.map +1 -0
  251. package/dist/esm/config/mapping.d.ts +63 -5
  252. package/dist/esm/config/mapping.js +165 -20
  253. package/dist/esm/config/mapping.js.map +1 -1
  254. package/dist/esm/config/sources/dw-json-source.d.ts +17 -1
  255. package/dist/esm/config/sources/dw-json-source.js +70 -3
  256. package/dist/esm/config/sources/dw-json-source.js.map +1 -1
  257. package/dist/esm/config/sources/package-json-source.js +6 -3
  258. package/dist/esm/config/sources/package-json-source.js.map +1 -1
  259. package/dist/esm/config/types.d.ts +72 -0
  260. package/dist/esm/defaults.d.ts +6 -0
  261. package/dist/esm/defaults.js +6 -0
  262. package/dist/esm/defaults.js.map +1 -1
  263. package/dist/esm/i18n/index.js +3 -0
  264. package/dist/esm/i18n/index.js.map +1 -1
  265. package/dist/esm/index.d.ts +8 -4
  266. package/dist/esm/index.js +9 -3
  267. package/dist/esm/index.js.map +1 -1
  268. package/dist/esm/logging/logger.js +13 -1
  269. package/dist/esm/logging/logger.js.map +1 -1
  270. package/dist/esm/operations/content/asset-query.d.ts +22 -0
  271. package/dist/esm/operations/content/asset-query.js +77 -0
  272. package/dist/esm/operations/content/asset-query.js.map +1 -0
  273. package/dist/esm/operations/content/export.d.ts +57 -0
  274. package/dist/esm/operations/content/export.js +224 -0
  275. package/dist/esm/operations/content/export.js.map +1 -0
  276. package/dist/esm/operations/content/index.d.ts +43 -0
  277. package/dist/esm/operations/content/index.js +48 -0
  278. package/dist/esm/operations/content/index.js.map +1 -0
  279. package/dist/esm/operations/content/library.d.ts +137 -0
  280. package/dist/esm/operations/content/library.js +392 -0
  281. package/dist/esm/operations/content/library.js.map +1 -0
  282. package/dist/esm/operations/content/types.d.ts +144 -0
  283. package/dist/esm/operations/content/types.js +7 -0
  284. package/dist/esm/operations/content/types.js.map +1 -0
  285. package/dist/esm/operations/mrt/b2c-config.js +19 -4
  286. package/dist/esm/operations/mrt/b2c-config.js.map +1 -1
  287. package/dist/esm/operations/mrt/index.d.ts +2 -0
  288. package/dist/esm/operations/mrt/index.js +2 -0
  289. package/dist/esm/operations/mrt/index.js.map +1 -1
  290. package/dist/esm/operations/mrt/tail-logs.d.ts +130 -0
  291. package/dist/esm/operations/mrt/tail-logs.js +223 -0
  292. package/dist/esm/operations/mrt/tail-logs.js.map +1 -0
  293. package/dist/esm/operations/ods/index.d.ts +2 -0
  294. package/dist/esm/operations/ods/index.js +1 -0
  295. package/dist/esm/operations/ods/index.js.map +1 -1
  296. package/dist/esm/operations/ods/wait-for-sandbox.d.ts +64 -0
  297. package/dist/esm/operations/ods/wait-for-sandbox.js +114 -0
  298. package/dist/esm/operations/ods/wait-for-sandbox.js.map +1 -0
  299. package/dist/esm/operations/orgs/index.d.ts +74 -0
  300. package/dist/esm/operations/orgs/index.js +33 -0
  301. package/dist/esm/operations/orgs/index.js.map +1 -0
  302. package/dist/esm/operations/roles/index.d.ts +43 -0
  303. package/dist/esm/operations/roles/index.js +48 -0
  304. package/dist/esm/operations/roles/index.js.map +1 -0
  305. package/dist/esm/operations/users/index.d.ts +143 -0
  306. package/dist/esm/operations/users/index.js +141 -0
  307. package/dist/esm/operations/users/index.js.map +1 -0
  308. package/dist/esm/scaffold/engine.d.ts +68 -0
  309. package/dist/esm/scaffold/engine.js +149 -0
  310. package/dist/esm/scaffold/engine.js.map +1 -0
  311. package/dist/esm/scaffold/executor.d.ts +36 -0
  312. package/dist/esm/scaffold/executor.js +285 -0
  313. package/dist/esm/scaffold/executor.js.map +1 -0
  314. package/dist/esm/scaffold/index.d.ts +74 -0
  315. package/dist/esm/scaffold/index.js +23 -0
  316. package/dist/esm/scaffold/index.js.map +1 -0
  317. package/dist/esm/scaffold/merge.d.ts +56 -0
  318. package/dist/esm/scaffold/merge.js +183 -0
  319. package/dist/esm/scaffold/merge.js.map +1 -0
  320. package/dist/esm/scaffold/parameter-resolver.d.ts +86 -0
  321. package/dist/esm/scaffold/parameter-resolver.js +179 -0
  322. package/dist/esm/scaffold/parameter-resolver.js.map +1 -0
  323. package/dist/esm/scaffold/registry.d.ts +45 -0
  324. package/dist/esm/scaffold/registry.js +219 -0
  325. package/dist/esm/scaffold/registry.js.map +1 -0
  326. package/dist/esm/scaffold/sources.d.ts +45 -0
  327. package/dist/esm/scaffold/sources.js +113 -0
  328. package/dist/esm/scaffold/sources.js.map +1 -0
  329. package/dist/esm/scaffold/types.d.ts +280 -0
  330. package/dist/esm/scaffold/types.js +14 -0
  331. package/dist/esm/scaffold/types.js.map +1 -0
  332. package/dist/esm/scaffold/validation.d.ts +81 -0
  333. package/dist/esm/scaffold/validation.js +250 -0
  334. package/dist/esm/scaffold/validation.js.map +1 -0
  335. package/dist/esm/scaffold/validators.d.ts +33 -0
  336. package/dist/esm/scaffold/validators.js +334 -0
  337. package/dist/esm/scaffold/validators.js.map +1 -0
  338. package/dist/esm/telemetry/index.d.ts +26 -0
  339. package/dist/esm/telemetry/index.js +32 -0
  340. package/dist/esm/telemetry/index.js.map +1 -0
  341. package/dist/esm/telemetry/telemetry.d.ts +90 -0
  342. package/dist/esm/telemetry/telemetry.js +283 -0
  343. package/dist/esm/telemetry/telemetry.js.map +1 -0
  344. package/dist/esm/telemetry/types.d.ts +62 -0
  345. package/dist/esm/telemetry/types.js +7 -0
  346. package/dist/esm/telemetry/types.js.map +1 -0
  347. package/package.json +86 -17
  348. package/specs/am-apiclients-api-v1.yaml +965 -0
  349. package/specs/am-roles-api-v1.yaml +316 -0
  350. package/specs/am-users-api-v1.yaml +1102 -0
@@ -0,0 +1,944 @@
1
+ /*
2
+ * Copyright (c) 2025, Salesforce, Inc.
3
+ * SPDX-License-Identifier: Apache-2
4
+ * For full license text, see the license.txt file in the repo root or http://www.apache.org/licenses/LICENSE-2.0
5
+ */
6
+ /**
7
+ * Account Manager API client for B2C Commerce.
8
+ *
9
+ * Provides clients for the Account Manager REST APIs including users, roles, and organizations.
10
+ * Uses openapi-fetch with OAuth authentication middleware for users and roles,
11
+ * and fetch with OAuth for organizations.
12
+ *
13
+ * @module clients/am-api
14
+ */
15
+ import createClient from 'openapi-fetch';
16
+ import { createAuthMiddleware, createLoggingMiddleware } from './middleware.js';
17
+ import { globalMiddlewareRegistry } from './middleware-registry.js';
18
+ import { DEFAULT_ACCOUNT_MANAGER_HOST } from '../defaults.js';
19
+ import { getLogger } from '../logging/logger.js';
20
+ /**
21
+ * Regex for Account Manager role tenant filter format:
22
+ * ROLE_ENUM:realm_instance(,realm_instance)*(;ROLE_ENUM:...)*
23
+ * e.g. SALESFORCE_COMMERCE_API:abcd_prd or bm-admin:tenant1,tenant2;ECOM_USER:wxyz_stg
24
+ */
25
+ export const ROLE_TENANT_FILTER_PATTERN = /^(\w+:\w{4,}_\w{3,}(,\w{4,}_\w{3,})*(;)?)*$/;
26
+ /**
27
+ * Returns true if the value matches the Account Manager role tenant filter format.
28
+ */
29
+ export function isValidRoleTenantFilter(value) {
30
+ return value.length > 0 && ROLE_TENANT_FILTER_PATTERN.test(value);
31
+ }
32
+ /**
33
+ * Role name mappings between external and internal formats.
34
+ */
35
+ export const ROLE_NAMES_MAP = {
36
+ 'bm-admin': 'ECOM_ADMIN',
37
+ 'bm-user': 'ECOM_USER',
38
+ };
39
+ export const ROLE_NAMES_MAP_REVERSE = {
40
+ ECOM_ADMIN: 'bm-admin',
41
+ ECOM_USER: 'bm-user',
42
+ };
43
+ /**
44
+ * Maps the role name to an internal role ID accepted by the API.
45
+ */
46
+ export function mapToInternalRole(role) {
47
+ if (ROLE_NAMES_MAP[role]) {
48
+ return ROLE_NAMES_MAP[role];
49
+ }
50
+ return role.toUpperCase().replace(/-/g, '_');
51
+ }
52
+ /**
53
+ * Maps the internal role ID to role name.
54
+ */
55
+ export function mapFromInternalRole(roleID) {
56
+ if (ROLE_NAMES_MAP_REVERSE[roleID]) {
57
+ return ROLE_NAMES_MAP_REVERSE[roleID];
58
+ }
59
+ return roleID.toLowerCase().replace(/_/g, '-');
60
+ }
61
+ /**
62
+ * Creates a typed Account Manager Users API client.
63
+ *
64
+ * Returns the openapi-fetch client directly, with authentication
65
+ * handled via middleware. This gives full access to all openapi-fetch
66
+ * features with type-safe paths, parameters, and responses.
67
+ *
68
+ * @param config - Account Manager Users client configuration
69
+ * @param auth - Authentication strategy (typically OAuth)
70
+ * @returns Typed openapi-fetch client
71
+ *
72
+ * @example
73
+ * // Create Account Manager Users client with OAuth auth
74
+ * const oauthStrategy = new OAuthStrategy({
75
+ * clientId: 'your-client-id',
76
+ * clientSecret: 'your-client-secret',
77
+ * });
78
+ *
79
+ * const client = createAccountManagerUsersClient({}, oauthStrategy);
80
+ *
81
+ * // List users
82
+ * const { data, error } = await client.GET('/dw/rest/v1/users', {
83
+ * params: { query: { pageable: { size: 25, page: 0 } } }
84
+ * });
85
+ */
86
+ export function createAccountManagerUsersClient(config, auth) {
87
+ const hostname = config.hostname ?? DEFAULT_ACCOUNT_MANAGER_HOST;
88
+ const registry = config.middlewareRegistry ?? globalMiddlewareRegistry;
89
+ const client = createClient({
90
+ baseUrl: `https://${hostname}`,
91
+ });
92
+ // Core middleware: auth first
93
+ client.use(createAuthMiddleware(auth));
94
+ // Transform pageable query parameters from bracket notation to flattened format
95
+ // This is needed because the API expects size=X&page=Y, not pageable[size]=X&pageable[page]=Y
96
+ client.use(createPageableTransformMiddleware());
97
+ // Plugin middleware from registry
98
+ for (const middleware of registry.getMiddleware('am-users-api')) {
99
+ client.use(middleware);
100
+ }
101
+ // Logging middleware last (sees complete request with all modifications)
102
+ client.use(createLoggingMiddleware('AM-USERS'));
103
+ return client;
104
+ }
105
+ /**
106
+ * Retrieves details of a user by ID.
107
+ *
108
+ * @param client - Account Manager Users client
109
+ * @param userId - User ID (UUID)
110
+ * @param expand - Optional array of fields to expand (organizations, roles)
111
+ * @returns User details
112
+ * @throws Error if user is not found or request fails
113
+ */
114
+ export async function getUser(client, userId, expand) {
115
+ const result = await client.GET('/dw/rest/v1/users/{userId}', {
116
+ params: {
117
+ path: { userId },
118
+ query: expand && expand.length > 0 ? { expand } : undefined,
119
+ },
120
+ });
121
+ if (result.error) {
122
+ const error = result.error;
123
+ if (result.response?.status === 404) {
124
+ throw new Error(`User ${userId} not found`);
125
+ }
126
+ throw new Error(error.error?.message || `Failed to get user: ${JSON.stringify(result.error)}`);
127
+ }
128
+ if (!result.data) {
129
+ throw new Error('No data returned from API');
130
+ }
131
+ return result.data;
132
+ }
133
+ /**
134
+ * Lists users with pagination.
135
+ *
136
+ * @param client - Account Manager Users client
137
+ * @param options - List options (size, page)
138
+ * @returns Paginated user collection
139
+ * @throws Error if request fails
140
+ */
141
+ export async function listUsers(client, options = {}) {
142
+ const { size = 20, page = 0 } = options;
143
+ const result = await client.GET('/dw/rest/v1/users', {
144
+ params: {
145
+ query: {
146
+ pageable: {
147
+ size,
148
+ page,
149
+ },
150
+ },
151
+ },
152
+ });
153
+ if (result.error) {
154
+ const error = result.error;
155
+ // Check for pagination out-of-bounds error
156
+ const errorMessage = error.errors?.[0]?.message || error.error?.message;
157
+ if (errorMessage?.includes('fromIndex') && errorMessage?.includes('toIndex')) {
158
+ throw new Error(`Page ${page} is out of bounds. The requested page exceeds the available data. Try a lower page number.`);
159
+ }
160
+ throw new Error(errorMessage || `Failed to list users: ${JSON.stringify(result.error)}`);
161
+ }
162
+ return result.data || { content: [] };
163
+ }
164
+ /**
165
+ * Creates a new user.
166
+ *
167
+ * @param client - Account Manager Users client
168
+ * @param user - User details
169
+ * @returns Created user
170
+ * @throws Error if request fails
171
+ */
172
+ export async function createUser(client, user) {
173
+ const result = await client.POST('/dw/rest/v1/users', {
174
+ body: user,
175
+ });
176
+ if (result.error) {
177
+ const error = result.error;
178
+ throw new Error(error.error?.message || `Failed to create user: ${JSON.stringify(result.error)}`);
179
+ }
180
+ if (!result.data) {
181
+ throw new Error('No data returned from API');
182
+ }
183
+ return result.data;
184
+ }
185
+ /**
186
+ * Updates an existing user.
187
+ *
188
+ * @param client - Account Manager Users client
189
+ * @param userId - User ID
190
+ * @param changes - Changes to apply
191
+ * @returns Updated user
192
+ * @throws Error if request fails
193
+ */
194
+ export async function updateUser(client, userId, changes) {
195
+ const result = await client.PUT('/dw/rest/v1/users/{userId}', {
196
+ params: { path: { userId } },
197
+ body: changes,
198
+ });
199
+ if (result.error) {
200
+ const error = result.error;
201
+ throw new Error(error.error?.message || `Failed to update user: ${JSON.stringify(result.error)}`);
202
+ }
203
+ if (!result.data) {
204
+ throw new Error('No data returned from API');
205
+ }
206
+ return result.data;
207
+ }
208
+ /**
209
+ * Disables a user (soft delete - sets userState to DELETED).
210
+ * Users must be disabled before they can be purged.
211
+ *
212
+ * @param client - Account Manager Users client
213
+ * @param userId - User ID
214
+ * @throws Error if request fails
215
+ */
216
+ export async function deleteUser(client, userId) {
217
+ const result = await client.POST('/dw/rest/v1/users/{userId}/disable', {
218
+ params: { path: { userId } },
219
+ body: {},
220
+ });
221
+ if (result.error) {
222
+ const error = result.error;
223
+ throw new Error(error.error?.message || `Failed to delete user: ${JSON.stringify(result.error)}`);
224
+ }
225
+ }
226
+ /**
227
+ * Purges a user (hard delete).
228
+ * Users must be in DELETED state before they can be purged.
229
+ *
230
+ * @param client - Account Manager Users client
231
+ * @param userId - User ID
232
+ * @throws Error if request fails
233
+ */
234
+ export async function purgeUser(client, userId) {
235
+ const result = await client.DELETE('/dw/rest/v1/users/{userId}', {
236
+ params: { path: { userId } },
237
+ });
238
+ if (result.error) {
239
+ const error = result.error;
240
+ throw new Error(error.error?.message || `Failed to purge user: ${JSON.stringify(result.error)}`);
241
+ }
242
+ }
243
+ /**
244
+ * Resets a user to INITIAL state and sends activation instructions.
245
+ *
246
+ * @param client - Account Manager Users client
247
+ * @param userId - User ID
248
+ * @throws Error if request fails
249
+ */
250
+ export async function resetUser(client, userId) {
251
+ const result = await client.POST('/dw/rest/v1/users/{userId}/reset', {
252
+ params: { path: { userId } },
253
+ body: {},
254
+ });
255
+ if (result.error) {
256
+ const error = result.error;
257
+ throw new Error(error.error?.message || `Failed to reset user: ${JSON.stringify(result.error)}`);
258
+ }
259
+ }
260
+ /**
261
+ * Helper to find a user by login (email) from a list of users.
262
+ * This is a convenience function since the API doesn't have a direct search by login endpoint.
263
+ *
264
+ * @param client - Account Manager Users client
265
+ * @param login - User login (email)
266
+ * @returns User if found, undefined otherwise
267
+ * @throws Error if request fails
268
+ */
269
+ export async function findUserByLogin(client, login, expand) {
270
+ // Search through paginated results
271
+ let page = 0;
272
+ const pageSize = 100;
273
+ while (true) {
274
+ const result = await client.GET('/dw/rest/v1/users', {
275
+ params: {
276
+ query: {
277
+ pageable: {
278
+ page,
279
+ size: pageSize,
280
+ },
281
+ },
282
+ },
283
+ });
284
+ if (result.error) {
285
+ throw new Error(`Failed to search for user: ${JSON.stringify(result.error)}`);
286
+ }
287
+ const users = result.data?.content || [];
288
+ const found = users.find((u) => u.mail === login);
289
+ if (found) {
290
+ // If expand is requested, fetch the full user with expanded fields
291
+ if (expand && expand.length > 0 && found.id) {
292
+ return getUser(client, found.id, expand);
293
+ }
294
+ return found;
295
+ }
296
+ // If we got fewer results than page size, we've reached the end
297
+ if (users.length < pageSize) {
298
+ return undefined;
299
+ }
300
+ page++;
301
+ }
302
+ }
303
+ /**
304
+ * Creates a typed Account Manager Roles API client.
305
+ *
306
+ * Returns the openapi-fetch client directly, with authentication
307
+ * handled via middleware. This gives full access to all openapi-fetch
308
+ * features with type-safe paths, parameters, and responses.
309
+ *
310
+ * @param config - Account Manager Roles client configuration
311
+ * @param auth - Authentication strategy (typically OAuth)
312
+ * @returns Typed openapi-fetch client
313
+ *
314
+ * @example
315
+ * // Create Account Manager Roles client with OAuth auth
316
+ * const oauthStrategy = new OAuthStrategy({
317
+ * clientId: 'your-client-id',
318
+ * clientSecret: 'your-client-secret',
319
+ * });
320
+ *
321
+ * const client = createAccountManagerRolesClient({}, oauthStrategy);
322
+ *
323
+ * // List roles
324
+ * const { data, error } = await client.GET('/dw/rest/v1/roles', {
325
+ * params: { query: { pageable: { size: 25, page: 0 } } }
326
+ * });
327
+ */
328
+ export function createAccountManagerRolesClient(config, auth) {
329
+ const hostname = config.hostname ?? DEFAULT_ACCOUNT_MANAGER_HOST;
330
+ const registry = config.middlewareRegistry ?? globalMiddlewareRegistry;
331
+ const client = createClient({
332
+ baseUrl: `https://${hostname}`,
333
+ });
334
+ // Core middleware: auth first
335
+ client.use(createAuthMiddleware(auth));
336
+ // Transform pageable query parameters from bracket notation to flattened format
337
+ // This is needed because the API expects size=X&page=Y, not pageable[size]=X&pageable[page]=Y
338
+ client.use(createPageableTransformMiddleware());
339
+ // Plugin middleware from registry
340
+ for (const middleware of registry.getMiddleware('am-roles-api')) {
341
+ client.use(middleware);
342
+ }
343
+ // Logging middleware last (sees complete request with all modifications)
344
+ client.use(createLoggingMiddleware('AM-ROLES'));
345
+ return client;
346
+ }
347
+ /**
348
+ * Retrieves details of a role by ID.
349
+ *
350
+ * @param client - Account Manager Roles client
351
+ * @param roleId - Role ID
352
+ * @returns Role details
353
+ * @throws Error if role is not found or request fails
354
+ */
355
+ export async function getRole(client, roleId) {
356
+ const result = await client.GET('/dw/rest/v1/roles/{roleId}', {
357
+ params: { path: { roleId } },
358
+ });
359
+ if (result.error) {
360
+ const error = result.error;
361
+ if (result.response?.status === 404) {
362
+ throw new Error(`Role ${roleId} not found`);
363
+ }
364
+ throw new Error(error.error?.message || `Failed to get role: ${JSON.stringify(result.error)}`);
365
+ }
366
+ if (!result.data) {
367
+ throw new Error('No data returned from API');
368
+ }
369
+ return result.data;
370
+ }
371
+ /**
372
+ * Lists roles with pagination.
373
+ *
374
+ * @param client - Account Manager Roles client
375
+ * @param options - List options (size, page, roleTargetType)
376
+ * @returns Paginated role collection
377
+ * @throws Error if request fails
378
+ */
379
+ export async function listRoles(client, options = {}) {
380
+ const { size = 20, page = 0, roleTargetType } = options;
381
+ const result = await client.GET('/dw/rest/v1/roles', {
382
+ params: {
383
+ query: {
384
+ pageable: {
385
+ size,
386
+ page,
387
+ },
388
+ ...(roleTargetType && { roleTargetType }),
389
+ },
390
+ },
391
+ });
392
+ if (result.error) {
393
+ const error = result.error;
394
+ // Check for pagination out-of-bounds error
395
+ const errorMessage = error.errors?.[0]?.message || error.error?.message;
396
+ if (errorMessage?.includes('fromIndex') && errorMessage?.includes('toIndex')) {
397
+ throw new Error(`Page ${page} is out of bounds. The requested page exceeds the available data. Try a lower page number.`);
398
+ }
399
+ throw new Error(errorMessage || `Failed to list roles: ${JSON.stringify(result.error)}`);
400
+ }
401
+ return result.data || { content: [] };
402
+ }
403
+ /**
404
+ * Creates a typed Account Manager API Clients API client.
405
+ *
406
+ * @param config - Account Manager client configuration
407
+ * @param auth - Authentication strategy (typically OAuth)
408
+ * @returns Typed openapi-fetch client for API Clients API
409
+ */
410
+ export function createAccountManagerApiClientsClient(config, auth) {
411
+ const hostname = config.hostname ?? DEFAULT_ACCOUNT_MANAGER_HOST;
412
+ const registry = config.middlewareRegistry ?? globalMiddlewareRegistry;
413
+ const client = createClient({
414
+ baseUrl: `https://${hostname}`,
415
+ });
416
+ client.use(createAuthMiddleware(auth));
417
+ client.use(createPageableTransformMiddleware());
418
+ for (const middleware of registry.getMiddleware('am-apiclients-api')) {
419
+ client.use(middleware);
420
+ }
421
+ client.use(createLoggingMiddleware('AM-APICLIENTS'));
422
+ return client;
423
+ }
424
+ /**
425
+ * Lists API clients with pagination.
426
+ */
427
+ export async function listApiClients(client, options = {}) {
428
+ const { size = 20, page = 0 } = options;
429
+ const result = await client.GET('/dw/rest/v1/apiclients', {
430
+ params: {
431
+ query: {
432
+ pageable: {
433
+ size,
434
+ page,
435
+ },
436
+ },
437
+ },
438
+ });
439
+ if (result.error) {
440
+ const error = result.error;
441
+ const errorMessage = error.errors?.[0]?.message || error.error?.message;
442
+ throw new Error(errorMessage || `Failed to list API clients: ${JSON.stringify(result.error)}`);
443
+ }
444
+ return result.data || { content: [] };
445
+ }
446
+ /**
447
+ * Retrieves an API client by ID.
448
+ */
449
+ export async function getApiClient(client, apiClientId, expand) {
450
+ const result = await client.GET('/dw/rest/v1/apiclients/{apiClientId}', {
451
+ params: {
452
+ path: { apiClientId },
453
+ query: expand && expand.length > 0 ? { expand } : undefined,
454
+ },
455
+ });
456
+ if (result.error) {
457
+ const error = result.error;
458
+ if (result.response?.status === 404) {
459
+ throw new Error(`API client ${apiClientId} not found`);
460
+ }
461
+ throw new Error(error.error?.message || `Failed to get API client: ${JSON.stringify(result.error)}`);
462
+ }
463
+ if (!result.data) {
464
+ throw new Error('No data returned from API');
465
+ }
466
+ return result.data;
467
+ }
468
+ /**
469
+ * Creates a new API client.
470
+ * Omits active when false so the API uses its default (inactive); some implementations
471
+ * reject or mishandle explicit active: false and return "invalid argument APIClient".
472
+ */
473
+ export async function createApiClient(client, body) {
474
+ const wireBody = body.active === false
475
+ ? (() => {
476
+ const { active: _a, ...rest } = body;
477
+ return rest;
478
+ })()
479
+ : body;
480
+ const result = await client.POST('/dw/rest/v1/apiclients', {
481
+ body: wireBody,
482
+ });
483
+ if (result.error) {
484
+ const err = result.error;
485
+ const first = err.errors?.[0];
486
+ const fieldHint = first?.fieldErrors
487
+ ?.map((fe) => `${fe.field}: ${fe.defaultMessage ?? ''}`)
488
+ .filter(Boolean)
489
+ .join('; ') || first?.field;
490
+ const errorMessage = fieldHint
491
+ ? `${first?.message ?? err.error?.message ?? 'Bad Request'} (${fieldHint})`
492
+ : (first?.message ?? err.error?.message);
493
+ throw new Error(errorMessage || `Failed to create API client: ${JSON.stringify(result.error)}`);
494
+ }
495
+ if (!result.data) {
496
+ throw new Error('No data returned from API');
497
+ }
498
+ return result.data;
499
+ }
500
+ /**
501
+ * Updates an existing API client.
502
+ */
503
+ export async function updateApiClient(client, apiClientId, body) {
504
+ const result = await client.PUT('/dw/rest/v1/apiclients/{apiClientId}', {
505
+ params: { path: { apiClientId } },
506
+ body,
507
+ });
508
+ if (result.error) {
509
+ const err = result.error;
510
+ const first = err.errors?.[0];
511
+ const fieldHint = first?.fieldErrors
512
+ ?.map((fe) => `${fe.field}: ${fe.defaultMessage ?? ''}`)
513
+ .filter(Boolean)
514
+ .join('; ') || first?.field;
515
+ const errorMessage = fieldHint
516
+ ? `${first?.message ?? err.error?.message ?? 'Invalid request'} (${fieldHint})`
517
+ : (first?.message ?? err.error?.message);
518
+ throw new Error(errorMessage || `Failed to update API client: ${JSON.stringify(result.error)}`);
519
+ }
520
+ if (!result.data) {
521
+ throw new Error('No data returned from API');
522
+ }
523
+ return result.data;
524
+ }
525
+ /**
526
+ * Deletes an API client. Only clients disabled for at least 7 days can be deleted.
527
+ */
528
+ export async function deleteApiClient(client, apiClientId) {
529
+ const result = await client.DELETE('/dw/rest/v1/apiclients/{apiClientId}', {
530
+ params: { path: { apiClientId } },
531
+ });
532
+ if (result.error) {
533
+ const error = result.error;
534
+ if (result.response?.status === 412) {
535
+ throw new Error('API client must be disabled for at least 7 days before it can be deleted.');
536
+ }
537
+ throw new Error(error.error?.message || `Failed to delete API client: ${JSON.stringify(result.error)}`);
538
+ }
539
+ }
540
+ /**
541
+ * Changes the password for an API client.
542
+ */
543
+ export async function changeApiClientPassword(client, apiClientId, oldPassword, newPassword) {
544
+ const result = await client.PUT('/dw/rest/v1/apiclients/{apiClientId}/password', {
545
+ params: { path: { apiClientId } },
546
+ body: { old: oldPassword, new: newPassword },
547
+ });
548
+ if (result.error) {
549
+ const error = result.error;
550
+ throw new Error(error.error?.message || `Failed to change API client password: ${JSON.stringify(result.error)}`);
551
+ }
552
+ }
553
+ /**
554
+ * Transforms the API organization representation to an external format.
555
+ * Removes internal properties like 'links' that should not be exposed.
556
+ *
557
+ * @param org - The original organization object
558
+ * @returns The transformed organization object
559
+ */
560
+ function toExternalOrg(org) {
561
+ // Create a copy to avoid mutating the original
562
+ const transformed = { ...org };
563
+ // Always delete the links property
564
+ delete transformed.links;
565
+ return transformed;
566
+ }
567
+ /**
568
+ * Creates an Account Manager Organizations API client.
569
+ *
570
+ * @param config - Account Manager Organizations client configuration
571
+ * @param auth - Authentication strategy (typically OAuth)
572
+ * @returns Organizations API client
573
+ *
574
+ * @example
575
+ * const oauthStrategy = new OAuthStrategy({
576
+ * clientId: 'your-client-id',
577
+ * clientSecret: 'your-client-secret',
578
+ * });
579
+ *
580
+ * const client = createAccountManagerOrgsClient({}, oauthStrategy);
581
+ *
582
+ * // List organizations
583
+ * const orgs = await client.listOrgs({ size: 25, page: 0 });
584
+ *
585
+ * // Get organization by ID
586
+ * const org = await client.getOrg('org-id');
587
+ */
588
+ export function createAccountManagerOrgsClient(config, auth) {
589
+ const hostname = config.hostname ?? DEFAULT_ACCOUNT_MANAGER_HOST;
590
+ const baseUrl = `https://${hostname}/dw/rest/v1`;
591
+ const logger = getLogger();
592
+ const registry = config.middlewareRegistry ?? globalMiddlewareRegistry;
593
+ // Get middleware from registry for am-orgs-api
594
+ const pluginMiddleware = registry.getMiddleware('am-orgs-api');
595
+ /**
596
+ * Applies middleware chain to a request.
597
+ * Adapts openapi-fetch middleware to work with fetch requests.
598
+ */
599
+ async function applyMiddleware(request) {
600
+ let processedRequest = request;
601
+ // Apply auth middleware (core)
602
+ if (auth.getAuthorizationHeader) {
603
+ const authHeader = await auth.getAuthorizationHeader();
604
+ processedRequest.headers.set('Authorization', authHeader);
605
+ }
606
+ // Apply plugin middleware from registry
607
+ for (const middleware of pluginMiddleware) {
608
+ if (middleware.onRequest) {
609
+ // Create minimal openapi-fetch context
610
+ const result = await middleware.onRequest({
611
+ request: processedRequest,
612
+ schemaPath: '',
613
+ params: {},
614
+ id: '',
615
+ options: {
616
+ baseUrl: baseUrl,
617
+ parseAs: 'json',
618
+ querySerializer: (params) => new URLSearchParams(params).toString(),
619
+ bodySerializer: JSON.stringify,
620
+ fetch: fetch,
621
+ },
622
+ });
623
+ // Middleware can return Request or Response, but we only want Request here
624
+ if (result && result instanceof Request) {
625
+ processedRequest = result;
626
+ }
627
+ }
628
+ }
629
+ // Apply logging middleware (last, so it sees all modifications)
630
+ logger.debug({ method: processedRequest.method, url: processedRequest.url }, '[AM-ORGS] Making request');
631
+ logger.trace({
632
+ method: processedRequest.method,
633
+ url: processedRequest.url,
634
+ headers: Object.fromEntries(processedRequest.headers.entries()),
635
+ }, '[AM-ORGS] Request details');
636
+ return processedRequest;
637
+ }
638
+ /**
639
+ * Applies middleware chain to a response.
640
+ */
641
+ async function processResponse(request, response) {
642
+ let processedResponse = response;
643
+ // Apply plugin middleware from registry
644
+ for (const middleware of pluginMiddleware) {
645
+ if (middleware.onResponse) {
646
+ const result = await middleware.onResponse({
647
+ request,
648
+ response: processedResponse,
649
+ schemaPath: '',
650
+ params: {},
651
+ id: '',
652
+ options: {
653
+ baseUrl: baseUrl,
654
+ parseAs: 'json',
655
+ querySerializer: (params) => new URLSearchParams(params).toString(),
656
+ bodySerializer: JSON.stringify,
657
+ fetch: fetch,
658
+ },
659
+ });
660
+ if (result) {
661
+ processedResponse = result;
662
+ }
663
+ }
664
+ }
665
+ // Apply logging middleware (last)
666
+ logger.debug({ method: request.method, url: request.url, status: processedResponse.status }, '[AM-ORGS] Received response');
667
+ return processedResponse;
668
+ }
669
+ /**
670
+ * Makes an authenticated request to the Account Manager API with middleware support.
671
+ */
672
+ async function makeRequest(path, options = {}) {
673
+ const url = `${baseUrl}${path}`;
674
+ let request = new Request(url, {
675
+ ...options,
676
+ headers: new Headers(options.headers),
677
+ });
678
+ // Apply middleware chain to request
679
+ request = await applyMiddleware(request);
680
+ const response = await fetch(request);
681
+ // Apply middleware chain to response
682
+ const processedResponse = await processResponse(request, response);
683
+ // Handle errors
684
+ if (processedResponse.status === 401) {
685
+ throw new Error('Authentication invalid. Please (re-)authenticate.');
686
+ }
687
+ if (processedResponse.status === 403) {
688
+ throw new Error('Operation forbidden. Please make sure you have the permission to perform this operation.');
689
+ }
690
+ if (processedResponse.status >= 400) {
691
+ throw new Error(`Operation failed. Error code ${processedResponse.status}`);
692
+ }
693
+ if (!processedResponse.ok) {
694
+ throw new Error(`Request failed: ${processedResponse.statusText}`);
695
+ }
696
+ return processedResponse.json();
697
+ }
698
+ return {
699
+ async getOrg(orgId) {
700
+ logger.debug({ orgId }, '[AM-ORGS] Getting organization by ID');
701
+ try {
702
+ const org = await makeRequest(`/organizations/${orgId}`);
703
+ return toExternalOrg(org);
704
+ }
705
+ catch (error) {
706
+ if (error instanceof Error && error.message.includes('Error code 404')) {
707
+ throw new Error(`Organization ${orgId} not found`);
708
+ }
709
+ throw error;
710
+ }
711
+ },
712
+ async getOrgByName(name) {
713
+ logger.debug({ name }, '[AM-ORGS] Getting organization by name');
714
+ const encodedName = encodeURIComponent(name);
715
+ let result;
716
+ try {
717
+ result = await makeRequest(`/organizations/search/findByName?startsWith=${encodedName}&ignoreCase=false`);
718
+ }
719
+ catch (error) {
720
+ if (error instanceof Error && error.message.includes('Error code 404')) {
721
+ throw new Error(`Organization ${name} not found`);
722
+ }
723
+ throw error;
724
+ }
725
+ if (result.content.length === 0) {
726
+ throw new Error(`Organization ${name} not found`);
727
+ }
728
+ if (result.content.length > 1) {
729
+ // Attempt to find exact match
730
+ const exactMatch = result.content.find((org) => org.name === name);
731
+ if (exactMatch) {
732
+ return toExternalOrg(exactMatch);
733
+ }
734
+ throw new Error(`Organization name "${name}" is ambiguous. Multiple organizations found.`);
735
+ }
736
+ return toExternalOrg(result.content[0]);
737
+ },
738
+ async listOrgs(options = {}) {
739
+ const { size = 25, page = 0, all = false } = options;
740
+ const pageSize = all ? 5000 : size;
741
+ logger.debug({ size: pageSize, page }, '[AM-ORGS] Listing organizations');
742
+ const result = await makeRequest(`/organizations?page=${page}&size=${pageSize}`);
743
+ // Remove links from all organizations in the collection
744
+ return {
745
+ ...result,
746
+ content: result.content.map((org) => toExternalOrg(org)),
747
+ };
748
+ },
749
+ };
750
+ }
751
+ // ============================================================================
752
+ // Shared Utilities
753
+ // ============================================================================
754
+ /**
755
+ * Middleware to transform pageable query parameters from bracket notation
756
+ * (pageable[size]=X&pageable[page]=Y) to flattened format (size=X&page=Y)
757
+ * that the Account Manager API expects.
758
+ */
759
+ function createPageableTransformMiddleware() {
760
+ const logger = getLogger();
761
+ return {
762
+ async onRequest({ request }) {
763
+ const url = new URL(request.url);
764
+ // Check if URL has pageable[size] or pageable[page] parameters
765
+ const pageableSize = url.searchParams.get('pageable[size]');
766
+ const pageablePage = url.searchParams.get('pageable[page]');
767
+ if (pageableSize !== null || pageablePage !== null) {
768
+ // Remove the bracket notation parameters
769
+ url.searchParams.delete('pageable[size]');
770
+ url.searchParams.delete('pageable[page]');
771
+ // Add flattened parameters
772
+ if (pageableSize !== null) {
773
+ url.searchParams.set('size', pageableSize);
774
+ }
775
+ if (pageablePage !== null) {
776
+ url.searchParams.set('page', pageablePage);
777
+ }
778
+ logger.trace({
779
+ originalUrl: request.url,
780
+ transformedUrl: url.toString(),
781
+ size: pageableSize,
782
+ page: pageablePage,
783
+ }, '[AM] Transformed pageable query parameters from bracket to flattened notation');
784
+ return new Request(url.toString(), {
785
+ method: request.method,
786
+ headers: request.headers,
787
+ body: request.body,
788
+ });
789
+ }
790
+ return request;
791
+ },
792
+ };
793
+ }
794
+ /**
795
+ * Creates a unified Account Manager API client.
796
+ *
797
+ * This client provides direct access to all Account Manager API methods (users, roles, orgs)
798
+ * through a single interface, while internally using separate typed clients for type safety.
799
+ *
800
+ * @param config - Account Manager client configuration
801
+ * @param auth - Authentication strategy (typically OAuth)
802
+ * @returns Unified Account Manager client
803
+ *
804
+ * @example
805
+ * const oauthStrategy = new OAuthStrategy({
806
+ * clientId: 'your-client-id',
807
+ * clientSecret: 'your-client-secret',
808
+ * });
809
+ *
810
+ * const client = createAccountManagerClient({}, oauthStrategy);
811
+ *
812
+ * // Users API
813
+ * const users = await client.listUsers({ size: 25, page: 0 });
814
+ * const user = await client.getUser('user-id');
815
+ * await client.createUser({ mail: 'user@example.com', ... });
816
+ *
817
+ * // Roles API
818
+ * const roles = await client.listRoles({ size: 20, page: 0 });
819
+ * const role = await client.getRole('bm-admin');
820
+ *
821
+ * // Organizations API
822
+ * const orgs = await client.listOrgs({ size: 25, page: 0 });
823
+ * const org = await client.getOrg('org-id');
824
+ */
825
+ export function createAccountManagerClient(config, auth) {
826
+ // All three clients use the same config
827
+ // Create internal clients (all use the same config, however, specifications are different)
828
+ const usersClient = createAccountManagerUsersClient(config, auth);
829
+ const rolesClient = createAccountManagerRolesClient(config, auth);
830
+ const apiClientsClient = createAccountManagerApiClientsClient(config, auth);
831
+ const orgsClient = createAccountManagerOrgsClient(config, auth);
832
+ // Return unified client with all methods
833
+ return {
834
+ // Users API methods
835
+ getUser: (userId, expand) => getUser(usersClient, userId, expand),
836
+ listUsers: (options) => listUsers(usersClient, options),
837
+ createUser: (user) => createUser(usersClient, user),
838
+ updateUser: (userId, changes) => updateUser(usersClient, userId, changes),
839
+ deleteUser: (userId) => deleteUser(usersClient, userId),
840
+ purgeUser: (userId) => purgeUser(usersClient, userId),
841
+ resetUser: (userId) => resetUser(usersClient, userId),
842
+ findUserByLogin: (login, expand) => findUserByLogin(usersClient, login, expand),
843
+ grantRole: (userId, role, scope) => {
844
+ // Import grantRole from operations - it uses getUser internally which needs the client
845
+ return getUser(usersClient, userId).then((user) => {
846
+ // Build updated roles
847
+ const currentRoles = Array.isArray(user.roles)
848
+ ? user.roles.map((r) => (typeof r === 'string' ? r : r.roleEnumName || ''))
849
+ : [];
850
+ const updatedRoles = currentRoles.includes(role) ? currentRoles : [...currentRoles, role];
851
+ // Build updated roleTenantFilter
852
+ let roleTenantFilter = user.roleTenantFilter || '';
853
+ if (scope) {
854
+ const scopes = scope.split(',');
855
+ // Parse existing filter
856
+ const filters = roleTenantFilter.split(';').filter(Boolean);
857
+ const filterMap = new Map();
858
+ for (const filter of filters) {
859
+ const [r, tenants] = filter.split(':');
860
+ if (tenants) {
861
+ filterMap.set(r, tenants.split(','));
862
+ }
863
+ }
864
+ // Add new scopes
865
+ const existingScopes = filterMap.get(role) || [];
866
+ const allScopes = [...new Set([...existingScopes, ...scopes])];
867
+ filterMap.set(role, allScopes);
868
+ // Rebuild filter string
869
+ roleTenantFilter = Array.from(filterMap.entries())
870
+ .map(([r, tenants]) => `${r}:${tenants.join(',')}`)
871
+ .join(';');
872
+ }
873
+ return updateUser(usersClient, userId, {
874
+ roles: updatedRoles,
875
+ roleTenantFilter: roleTenantFilter || undefined,
876
+ });
877
+ });
878
+ },
879
+ revokeRole: (userId, role, scope) => {
880
+ // Import revokeRole logic - it uses getUser internally which needs the client
881
+ return getUser(usersClient, userId).then((user) => {
882
+ // Build updated roles
883
+ const currentRoles = Array.isArray(user.roles)
884
+ ? user.roles.map((r) => (typeof r === 'string' ? r : r.roleEnumName || ''))
885
+ : [];
886
+ let updatedRoles = currentRoles;
887
+ // Build updated roleTenantFilter
888
+ let roleTenantFilter = user.roleTenantFilter || '';
889
+ if (!scope) {
890
+ // Remove entire role
891
+ updatedRoles = currentRoles.filter((r) => r !== role);
892
+ // Remove role from filter
893
+ const filters = roleTenantFilter.split(';').filter(Boolean);
894
+ roleTenantFilter = filters.filter((filter) => !filter.startsWith(`${role}:`)).join(';');
895
+ }
896
+ else {
897
+ // Remove specific scope
898
+ const scopes = scope.split(',');
899
+ const filters = roleTenantFilter.split(';').filter(Boolean);
900
+ const filterMap = new Map();
901
+ for (const filter of filters) {
902
+ const [r, tenants] = filter.split(':');
903
+ if (tenants) {
904
+ filterMap.set(r, tenants.split(','));
905
+ }
906
+ }
907
+ const existingScopes = filterMap.get(role) || [];
908
+ const remainingScopes = existingScopes.filter((s) => !scopes.includes(s));
909
+ if (remainingScopes.length === 0) {
910
+ // No scopes left, remove role entirely
911
+ updatedRoles = currentRoles.filter((r) => r !== role);
912
+ filterMap.delete(role);
913
+ }
914
+ else {
915
+ filterMap.set(role, remainingScopes);
916
+ }
917
+ // Rebuild filter string
918
+ roleTenantFilter = Array.from(filterMap.entries())
919
+ .map(([r, tenants]) => `${r}:${tenants.join(',')}`)
920
+ .join(';');
921
+ }
922
+ return updateUser(usersClient, userId, {
923
+ roles: updatedRoles,
924
+ roleTenantFilter: roleTenantFilter || undefined,
925
+ });
926
+ });
927
+ },
928
+ // Roles API methods
929
+ getRole: (roleId) => getRole(rolesClient, roleId),
930
+ listRoles: (options) => listRoles(rolesClient, options),
931
+ // API Clients API methods
932
+ listApiClients: (options) => listApiClients(apiClientsClient, options),
933
+ getApiClient: (apiClientId, expand) => getApiClient(apiClientsClient, apiClientId, expand),
934
+ createApiClient: (body) => createApiClient(apiClientsClient, body),
935
+ updateApiClient: (apiClientId, body) => updateApiClient(apiClientsClient, apiClientId, body),
936
+ deleteApiClient: (apiClientId) => deleteApiClient(apiClientsClient, apiClientId),
937
+ changeApiClientPassword: (apiClientId, oldPassword, newPassword) => changeApiClientPassword(apiClientsClient, apiClientId, oldPassword, newPassword),
938
+ // Organizations API methods
939
+ getOrg: (orgId) => orgsClient.getOrg(orgId),
940
+ getOrgByName: (name) => orgsClient.getOrgByName(name),
941
+ listOrgs: (options) => orgsClient.listOrgs(options),
942
+ };
943
+ }
944
+ //# sourceMappingURL=am-api.js.map