@credibledata/cred-cli 0.0.103 → 0.0.105

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 (430) hide show
  1. package/README.md +106 -1
  2. package/dist/agent-contract.spec.js +548 -0
  3. package/dist/agent-contract.spec.js.map +1 -0
  4. package/dist/browser.js +72 -0
  5. package/dist/browser.js.map +1 -0
  6. package/dist/browser.spec.js +125 -0
  7. package/dist/browser.spec.js.map +1 -0
  8. package/dist/client/api.js +4137 -1159
  9. package/dist/client/api.js.map +1 -1
  10. package/dist/client-codeassist/api.js +476 -0
  11. package/dist/client-codeassist/api.js.map +1 -0
  12. package/dist/client-codeassist/base.js +69 -0
  13. package/dist/client-codeassist/base.js.map +1 -0
  14. package/dist/client-codeassist/common.js +162 -0
  15. package/dist/client-codeassist/common.js.map +1 -0
  16. package/dist/client-codeassist/configuration.js +44 -0
  17. package/dist/client-codeassist/configuration.js.map +1 -0
  18. package/dist/client-codeassist/index.js +32 -0
  19. package/dist/client-codeassist/index.js.map +1 -0
  20. package/dist/clientconfiguration.js +17 -289
  21. package/dist/clientconfiguration.js.map +1 -1
  22. package/dist/clientconfiguration.spec.js +35 -96
  23. package/dist/clientconfiguration.spec.js.map +1 -1
  24. package/dist/commands/add.js +103 -3
  25. package/dist/commands/add.js.map +1 -1
  26. package/dist/commands/add.spec.js +113 -0
  27. package/dist/commands/add.spec.js.map +1 -0
  28. package/dist/commands/connection/createconnections.js +104 -7
  29. package/dist/commands/connection/createconnections.js.map +1 -1
  30. package/dist/commands/connection/createconnections.spec.js +35 -1
  31. package/dist/commands/connection/createconnections.spec.js.map +1 -1
  32. package/dist/commands/connection/deleteconnection.js +4 -2
  33. package/dist/commands/connection/deleteconnection.js.map +1 -1
  34. package/dist/commands/connection/deleteconnection.spec.js +6 -1
  35. package/dist/commands/connection/deleteconnection.spec.js.map +1 -1
  36. package/dist/commands/connection/listconnections.js +2 -0
  37. package/dist/commands/connection/listconnections.js.map +1 -1
  38. package/dist/commands/connection/updateconnection.js +365 -0
  39. package/dist/commands/connection/updateconnection.js.map +1 -0
  40. package/dist/commands/connection/updateconnection.spec.js +625 -0
  41. package/dist/commands/connection/updateconnection.spec.js.map +1 -0
  42. package/dist/commands/database/createdatabase.js +52 -0
  43. package/dist/commands/database/createdatabase.js.map +1 -0
  44. package/dist/commands/database/database.spec.js +267 -0
  45. package/dist/commands/database/database.spec.js.map +1 -0
  46. package/dist/commands/database/deletedatabase.js +91 -0
  47. package/dist/commands/database/deletedatabase.js.map +1 -0
  48. package/dist/commands/database/getdatabase.js +97 -0
  49. package/dist/commands/database/getdatabase.js.map +1 -0
  50. package/dist/commands/database/listdatabases.js +36 -0
  51. package/dist/commands/database/listdatabases.js.map +1 -0
  52. package/dist/commands/database/shared.js +125 -0
  53. package/dist/commands/database/shared.js.map +1 -0
  54. package/dist/commands/database/shared.spec.js +109 -0
  55. package/dist/commands/database/shared.spec.js.map +1 -0
  56. package/dist/commands/database/updatedatabase.js +39 -0
  57. package/dist/commands/database/updatedatabase.js.map +1 -0
  58. package/dist/commands/environment/createenvironment.js +59 -28
  59. package/dist/commands/environment/createenvironment.js.map +1 -1
  60. package/dist/commands/environment/createenvironment.spec.js +29 -0
  61. package/dist/commands/environment/createenvironment.spec.js.map +1 -1
  62. package/dist/commands/environment/deleteenvironment.js +3 -2
  63. package/dist/commands/environment/deleteenvironment.js.map +1 -1
  64. package/dist/commands/environment/deleteenvironment.spec.js +5 -1
  65. package/dist/commands/environment/deleteenvironment.spec.js.map +1 -1
  66. package/dist/commands/environment/getenvironment.js +1 -0
  67. package/dist/commands/environment/getenvironment.js.map +1 -1
  68. package/dist/commands/environment/listenvironments.js +40 -8
  69. package/dist/commands/environment/listenvironments.js.map +1 -1
  70. package/dist/commands/environment/listenvironments.spec.js +41 -2
  71. package/dist/commands/environment/listenvironments.spec.js.map +1 -1
  72. package/dist/commands/environment/setenvironment.js +145 -6
  73. package/dist/commands/environment/setenvironment.js.map +1 -1
  74. package/dist/commands/environment/setenvironment.spec.js +256 -8
  75. package/dist/commands/environment/setenvironment.spec.js.map +1 -1
  76. package/dist/commands/environment/updateenvironment.js +12 -8
  77. package/dist/commands/environment/updateenvironment.js.map +1 -1
  78. package/dist/commands/environment/updateenvironment.spec.js +36 -2
  79. package/dist/commands/environment/updateenvironment.spec.js.map +1 -1
  80. package/dist/commands/get.js +64 -1
  81. package/dist/commands/get.js.map +1 -1
  82. package/dist/commands/group/addmember.js +3 -1
  83. package/dist/commands/group/addmember.js.map +1 -1
  84. package/dist/commands/group/addmember.spec.js +7 -2
  85. package/dist/commands/group/addmember.spec.js.map +1 -1
  86. package/dist/commands/group/creategroup.js +2 -0
  87. package/dist/commands/group/creategroup.js.map +1 -1
  88. package/dist/commands/group/deletegroup.js +3 -1
  89. package/dist/commands/group/deletegroup.js.map +1 -1
  90. package/dist/commands/group/deletegroup.spec.js +7 -1
  91. package/dist/commands/group/deletegroup.spec.js.map +1 -1
  92. package/dist/commands/group/getgroup.js +2 -0
  93. package/dist/commands/group/getgroup.js.map +1 -1
  94. package/dist/commands/group/listgroups.js +2 -0
  95. package/dist/commands/group/listgroups.js.map +1 -1
  96. package/dist/commands/group/removemember.js +3 -1
  97. package/dist/commands/group/removemember.js.map +1 -1
  98. package/dist/commands/group/removemember.spec.js +7 -2
  99. package/dist/commands/group/removemember.spec.js.map +1 -1
  100. package/dist/commands/groupaccesstoken/deleteToken.js +2 -1
  101. package/dist/commands/groupaccesstoken/deleteToken.js.map +1 -1
  102. package/dist/commands/groupaccesstoken/groupContainer.js +2 -0
  103. package/dist/commands/groupaccesstoken/groupContainer.js.map +1 -1
  104. package/dist/commands/list.js +24 -4
  105. package/dist/commands/list.js.map +1 -1
  106. package/dist/commands/materialization/cancelrun.js +3 -1
  107. package/dist/commands/materialization/cancelrun.js.map +1 -1
  108. package/dist/commands/materialization/getindex.js +2 -0
  109. package/dist/commands/materialization/getindex.js.map +1 -1
  110. package/dist/commands/materialization/getmaterialization.js +2 -0
  111. package/dist/commands/materialization/getmaterialization.js.map +1 -1
  112. package/dist/commands/materialization/getpreaggregate.js +2 -0
  113. package/dist/commands/materialization/getpreaggregate.js.map +1 -1
  114. package/dist/commands/materialization/getrun.js +2 -0
  115. package/dist/commands/materialization/getrun.js.map +1 -1
  116. package/dist/commands/materialization/listindexes.js +2 -0
  117. package/dist/commands/materialization/listindexes.js.map +1 -1
  118. package/dist/commands/materialization/listmaterializations.js +2 -0
  119. package/dist/commands/materialization/listmaterializations.js.map +1 -1
  120. package/dist/commands/materialization/listpreaggregates.js +2 -0
  121. package/dist/commands/materialization/listpreaggregates.js.map +1 -1
  122. package/dist/commands/materialization/listruns.js +3 -1
  123. package/dist/commands/materialization/listruns.js.map +1 -1
  124. package/dist/commands/materialization/rerun.js +3 -1
  125. package/dist/commands/materialization/rerun.js.map +1 -1
  126. package/dist/commands/misc/inquirerHost.js +87 -0
  127. package/dist/commands/misc/inquirerHost.js.map +1 -0
  128. package/dist/commands/misc/inquirerHost.spec.js +91 -0
  129. package/dist/commands/misc/inquirerHost.spec.js.map +1 -0
  130. package/dist/commands/misc/login.js +348 -58
  131. package/dist/commands/misc/login.js.map +1 -1
  132. package/dist/commands/misc/login.spec.js +525 -7
  133. package/dist/commands/misc/login.spec.js.map +1 -1
  134. package/dist/commands/misc/logout.js +26 -3
  135. package/dist/commands/misc/logout.js.map +1 -1
  136. package/dist/commands/misc/logout.spec.js +52 -12
  137. package/dist/commands/misc/logout.spec.js.map +1 -1
  138. package/dist/commands/misc/resolveLoginTarget.spec.js +90 -0
  139. package/dist/commands/misc/resolveLoginTarget.spec.js.map +1 -0
  140. package/dist/commands/misc/scope.spec.js +108 -0
  141. package/dist/commands/misc/scope.spec.js.map +1 -0
  142. package/dist/commands/misc/set-access-token.js +1 -1
  143. package/dist/commands/misc/set-access-token.js.map +1 -1
  144. package/dist/commands/misc/set-access-token.spec.js +13 -2
  145. package/dist/commands/misc/set-access-token.spec.js.map +1 -1
  146. package/dist/commands/misc/setup.js +819 -0
  147. package/dist/commands/misc/setup.js.map +1 -0
  148. package/dist/commands/misc/setup.spec.js +783 -0
  149. package/dist/commands/misc/setup.spec.js.map +1 -0
  150. package/dist/commands/misc/status.js +168 -0
  151. package/dist/commands/misc/status.js.map +1 -0
  152. package/dist/commands/misc/status.spec.js +301 -0
  153. package/dist/commands/misc/status.spec.js.map +1 -0
  154. package/dist/commands/misc/token.js +57 -0
  155. package/dist/commands/misc/token.js.map +1 -0
  156. package/dist/commands/misc/token.spec.js +92 -0
  157. package/dist/commands/misc/token.spec.js.map +1 -0
  158. package/dist/commands/package/deletepackage.js +4 -2
  159. package/dist/commands/package/deletepackage.js.map +1 -1
  160. package/dist/commands/package/deletepackage.spec.js +7 -1
  161. package/dist/commands/package/deletepackage.spec.js.map +1 -1
  162. package/dist/commands/package/getpackage.js +142 -0
  163. package/dist/commands/package/getpackage.js.map +1 -0
  164. package/dist/commands/package/getpackage.spec.js +246 -0
  165. package/dist/commands/package/getpackage.spec.js.map +1 -0
  166. package/dist/commands/package/listpackages.js +2 -0
  167. package/dist/commands/package/listpackages.js.map +1 -1
  168. package/dist/commands/package/publish.archive.spec.js +570 -0
  169. package/dist/commands/package/publish.archive.spec.js.map +1 -0
  170. package/dist/commands/package/publish.js +780 -49
  171. package/dist/commands/package/publish.js.map +1 -1
  172. package/dist/commands/package/publish.spec.js +451 -8
  173. package/dist/commands/package/publish.spec.js.map +1 -1
  174. package/dist/commands/package/updatepackage.js +22 -19
  175. package/dist/commands/package/updatepackage.js.map +1 -1
  176. package/dist/commands/package/updatepackage.spec.js +36 -1
  177. package/dist/commands/package/updatepackage.spec.js.map +1 -1
  178. package/dist/commands/permission/createpermission.js +3 -1
  179. package/dist/commands/permission/createpermission.js.map +1 -1
  180. package/dist/commands/permission/deletepermission.js +6 -3
  181. package/dist/commands/permission/deletepermission.js.map +1 -1
  182. package/dist/commands/permission/getpermission.js +2 -0
  183. package/dist/commands/permission/getpermission.js.map +1 -1
  184. package/dist/commands/permission/listpermissions.js +2 -0
  185. package/dist/commands/permission/listpermissions.js.map +1 -1
  186. package/dist/commands/rm.js +21 -0
  187. package/dist/commands/rm.js.map +1 -1
  188. package/dist/commands/set.js +40 -6
  189. package/dist/commands/set.js.map +1 -1
  190. package/dist/commands/set.spec.js +123 -0
  191. package/dist/commands/set.spec.js.map +1 -0
  192. package/dist/commands/table/addtable.js +155 -0
  193. package/dist/commands/table/addtable.js.map +1 -0
  194. package/dist/commands/table/deletetable.js +45 -0
  195. package/dist/commands/table/deletetable.js.map +1 -0
  196. package/dist/commands/table/gettable.js +32 -0
  197. package/dist/commands/table/gettable.js.map +1 -0
  198. package/dist/commands/table/listtables.js +36 -0
  199. package/dist/commands/table/listtables.js.map +1 -0
  200. package/dist/commands/table/table.spec.js +304 -0
  201. package/dist/commands/table/table.spec.js.map +1 -0
  202. package/dist/commands/table/tablefile.js +195 -0
  203. package/dist/commands/table/tablefile.js.map +1 -0
  204. package/dist/commands/table/tablefile.spec.js +158 -0
  205. package/dist/commands/table/tablefile.spec.js.map +1 -0
  206. package/dist/commands/update.js +21 -0
  207. package/dist/commands/update.js.map +1 -1
  208. package/dist/commands/version/archive-unarchive-version.js +4 -2
  209. package/dist/commands/version/archive-unarchive-version.js.map +1 -1
  210. package/dist/commands/version/archive-unarchive-version.spec.js +6 -1
  211. package/dist/commands/version/archive-unarchive-version.spec.js.map +1 -1
  212. package/dist/commands/version/listversions.js +2 -0
  213. package/dist/commands/version/listversions.js.map +1 -1
  214. package/dist/common/UserGroupId.js +9 -4
  215. package/dist/common/UserGroupId.js.map +1 -1
  216. package/dist/common/UserGroupId.spec.js +5 -0
  217. package/dist/common/UserGroupId.spec.js.map +1 -1
  218. package/dist/constants.js +37 -143
  219. package/dist/constants.js.map +1 -1
  220. package/dist/index.js +487 -90
  221. package/dist/index.js.map +1 -1
  222. package/dist/logger.js +42 -9
  223. package/dist/logger.js.map +1 -1
  224. package/dist/session.js +56 -0
  225. package/dist/session.js.map +1 -0
  226. package/dist/session.spec.js +103 -0
  227. package/dist/session.spec.js.map +1 -0
  228. package/dist/setup-core/briefing.js +176 -0
  229. package/dist/setup-core/briefing.js.map +1 -0
  230. package/dist/setup-core/credstore.js +415 -0
  231. package/dist/setup-core/credstore.js.map +1 -0
  232. package/dist/setup-core/credstore.spec.js +238 -0
  233. package/dist/setup-core/credstore.spec.js.map +1 -0
  234. package/dist/setup-core/environments.js +267 -0
  235. package/dist/setup-core/environments.js.map +1 -0
  236. package/dist/setup-core/flow.e2e.js +165 -0
  237. package/dist/setup-core/flow.e2e.js.map +1 -0
  238. package/dist/setup-core/flow.js +765 -0
  239. package/dist/setup-core/flow.js.map +1 -0
  240. package/dist/setup-core/flow.spec.js +1348 -0
  241. package/dist/setup-core/flow.spec.js.map +1 -0
  242. package/dist/setup-core/folderconfig.js +283 -0
  243. package/dist/setup-core/folderconfig.js.map +1 -0
  244. package/dist/setup-core/git.js +97 -0
  245. package/dist/setup-core/git.js.map +1 -0
  246. package/dist/setup-core/host.js +77 -0
  247. package/dist/setup-core/host.js.map +1 -0
  248. package/dist/setup-core/importconnections.js +470 -0
  249. package/dist/setup-core/importconnections.js.map +1 -0
  250. package/dist/setup-core/importconnections.spec.js +594 -0
  251. package/dist/setup-core/importconnections.spec.js.map +1 -0
  252. package/dist/setup-core/liveness.js +94 -0
  253. package/dist/setup-core/liveness.js.map +1 -0
  254. package/dist/setup-core/liveness.spec.js +59 -0
  255. package/dist/setup-core/liveness.spec.js.map +1 -0
  256. package/dist/setup-core/localpublisherconfig.js +26 -0
  257. package/dist/setup-core/localpublisherconfig.js.map +1 -0
  258. package/dist/setup-core/localpublisherconfig.spec.js +29 -0
  259. package/dist/setup-core/localpublisherconfig.spec.js.map +1 -0
  260. package/dist/setup-core/mcpconfig.js +198 -0
  261. package/dist/setup-core/mcpconfig.js.map +1 -0
  262. package/dist/setup-core/mcpconfig.spec.js +205 -0
  263. package/dist/setup-core/mcpconfig.spec.js.map +1 -0
  264. package/dist/setup-core/packagemanifest.js +55 -0
  265. package/dist/setup-core/packagemanifest.js.map +1 -0
  266. package/dist/setup-core/ports.js +182 -0
  267. package/dist/setup-core/ports.js.map +1 -0
  268. package/dist/setup-core/ports.spec.js +173 -0
  269. package/dist/setup-core/ports.spec.js.map +1 -0
  270. package/dist/setup-core/publisherconfig.js +268 -0
  271. package/dist/setup-core/publisherconfig.js.map +1 -0
  272. package/dist/setup-core/publisherconfig.oracle.js +166 -0
  273. package/dist/setup-core/publisherconfig.oracle.js.map +1 -0
  274. package/dist/setup-core/publisherconfig.spec.js +277 -0
  275. package/dist/setup-core/publisherconfig.spec.js.map +1 -0
  276. package/dist/setup-core/publisherversion.js +26 -0
  277. package/dist/setup-core/publisherversion.js.map +1 -0
  278. package/dist/setup-core/readiness.spec.js +161 -0
  279. package/dist/setup-core/readiness.spec.js.map +1 -0
  280. package/dist/setup-core/readylines.js +169 -0
  281. package/dist/setup-core/readylines.js.map +1 -0
  282. package/dist/setup-core/readylines.spec.js +70 -0
  283. package/dist/setup-core/readylines.spec.js.map +1 -0
  284. package/dist/setup-core/refresh.js +348 -0
  285. package/dist/setup-core/refresh.js.map +1 -0
  286. package/dist/setup-core/refresh.spec.js +501 -0
  287. package/dist/setup-core/refresh.spec.js.map +1 -0
  288. package/dist/setup-core/skills.js +279 -0
  289. package/dist/setup-core/skills.js.map +1 -0
  290. package/dist/setup-core/skills.spec.js +334 -0
  291. package/dist/setup-core/skills.spec.js.map +1 -0
  292. package/dist/setup-core/supervisor.js +879 -0
  293. package/dist/setup-core/supervisor.js.map +1 -0
  294. package/dist/setup-core/supervisor.spec.js +833 -0
  295. package/dist/setup-core/supervisor.spec.js.map +1 -0
  296. package/dist/setup-core/writefile.js +61 -0
  297. package/dist/setup-core/writefile.js.map +1 -0
  298. package/dist/setup-core/writefile.spec.js +68 -0
  299. package/dist/setup-core/writefile.spec.js.map +1 -0
  300. package/dist/utils.js +409 -3
  301. package/dist/utils.js.map +1 -1
  302. package/dist/utils.spec.js +373 -2
  303. package/dist/utils.spec.js.map +1 -1
  304. package/dist/versioncheck-refresh.js +18 -0
  305. package/dist/versioncheck-refresh.js.map +1 -0
  306. package/dist/versioncheck.js +324 -0
  307. package/dist/versioncheck.js.map +1 -0
  308. package/dist/versioncheck.spec.js +587 -0
  309. package/dist/versioncheck.spec.js.map +1 -0
  310. package/node_modules/@credibledata/cli-auth/dist/index.d.ts +86 -0
  311. package/node_modules/@credibledata/cli-auth/dist/index.js +102 -0
  312. package/node_modules/@credibledata/cli-auth/package.json +19 -0
  313. package/package.json +18 -6
  314. package/.github/workflows/build.yml +0 -23
  315. package/.mocharc.json +0 -10
  316. package/.prettierignore +0 -2
  317. package/.prettierrc +0 -4
  318. package/README-DEV.md +0 -40
  319. package/coverage/coverage-summary.json +0 -40
  320. package/coverage/tmp/coverage-2152-1789496974457-0.json +0 -1
  321. package/coverage/tmp/coverage-2153-1789496954404-0.json +0 -1
  322. package/docker/Dockerfile.ci +0 -18
  323. package/docker-compose.yml +0 -18
  324. package/eslint.config.mjs +0 -45
  325. package/generate-client.sh +0 -27
  326. package/mocha.setup.ts +0 -4
  327. package/openapitools.json +0 -10
  328. package/src/client/.openapi-generator/FILES +0 -9
  329. package/src/client/.openapi-generator/VERSION +0 -1
  330. package/src/client/.openapi-generator-ignore +0 -23
  331. package/src/client/api.ts +0 -15999
  332. package/src/client/base.ts +0 -86
  333. package/src/client/common.ts +0 -150
  334. package/src/client/configuration.ts +0 -110
  335. package/src/client/git_push.sh +0 -57
  336. package/src/client/index.ts +0 -18
  337. package/src/clientconfiguration.spec.ts +0 -615
  338. package/src/clientconfiguration.ts +0 -364
  339. package/src/commands/add.ts +0 -191
  340. package/src/commands/connection/createconnections.spec.ts +0 -413
  341. package/src/commands/connection/createconnections.ts +0 -109
  342. package/src/commands/connection/deleteconnection.spec.ts +0 -189
  343. package/src/commands/connection/deleteconnection.ts +0 -57
  344. package/src/commands/connection/listconnections.spec.ts +0 -132
  345. package/src/commands/connection/listconnections.ts +0 -58
  346. package/src/commands/environment/createenvironment.spec.ts +0 -249
  347. package/src/commands/environment/createenvironment.ts +0 -73
  348. package/src/commands/environment/deleteenvironment.spec.ts +0 -152
  349. package/src/commands/environment/deleteenvironment.ts +0 -48
  350. package/src/commands/environment/getenvironment.spec.ts +0 -110
  351. package/src/commands/environment/getenvironment.ts +0 -43
  352. package/src/commands/environment/listenvironments.spec.ts +0 -123
  353. package/src/commands/environment/listenvironments.ts +0 -67
  354. package/src/commands/environment/setenvironment.spec.ts +0 -63
  355. package/src/commands/environment/setenvironment.ts +0 -14
  356. package/src/commands/environment/updateenvironment.spec.ts +0 -386
  357. package/src/commands/environment/updateenvironment.ts +0 -168
  358. package/src/commands/get.ts +0 -153
  359. package/src/commands/group/addmember.spec.ts +0 -257
  360. package/src/commands/group/addmember.ts +0 -85
  361. package/src/commands/group/creategroup.spec.ts +0 -146
  362. package/src/commands/group/creategroup.ts +0 -54
  363. package/src/commands/group/deletegroup.spec.ts +0 -120
  364. package/src/commands/group/deletegroup.ts +0 -45
  365. package/src/commands/group/getgroup.spec.ts +0 -129
  366. package/src/commands/group/getgroup.ts +0 -47
  367. package/src/commands/group/listgroups.spec.ts +0 -137
  368. package/src/commands/group/listgroups.ts +0 -45
  369. package/src/commands/group/removemember.spec.ts +0 -224
  370. package/src/commands/group/removemember.ts +0 -75
  371. package/src/commands/groupaccesstoken/createToken.spec.ts +0 -211
  372. package/src/commands/groupaccesstoken/createToken.ts +0 -72
  373. package/src/commands/groupaccesstoken/deleteToken.spec.ts +0 -147
  374. package/src/commands/groupaccesstoken/deleteToken.ts +0 -29
  375. package/src/commands/groupaccesstoken/groupContainer.ts +0 -83
  376. package/src/commands/groupaccesstoken/listTokens.spec.ts +0 -147
  377. package/src/commands/groupaccesstoken/listTokens.ts +0 -29
  378. package/src/commands/legacy.ts +0 -5
  379. package/src/commands/list.ts +0 -326
  380. package/src/commands/materialization/cancelrun.ts +0 -70
  381. package/src/commands/materialization/getindex.ts +0 -55
  382. package/src/commands/materialization/getmaterialization.ts +0 -57
  383. package/src/commands/materialization/getpreaggregate.ts +0 -58
  384. package/src/commands/materialization/getrun.ts +0 -55
  385. package/src/commands/materialization/listindexes.ts +0 -69
  386. package/src/commands/materialization/listmaterializations.ts +0 -53
  387. package/src/commands/materialization/listpreaggregates.ts +0 -74
  388. package/src/commands/materialization/listruns.ts +0 -77
  389. package/src/commands/materialization/rerun.ts +0 -123
  390. package/src/commands/misc/login.spec.ts +0 -371
  391. package/src/commands/misc/login.ts +0 -343
  392. package/src/commands/misc/logout.spec.ts +0 -32
  393. package/src/commands/misc/logout.ts +0 -9
  394. package/src/commands/misc/loopbackOAuth.ts +0 -127
  395. package/src/commands/misc/set-access-token.spec.ts +0 -95
  396. package/src/commands/misc/set-access-token.ts +0 -32
  397. package/src/commands/package/deletepackage.spec.ts +0 -164
  398. package/src/commands/package/deletepackage.ts +0 -58
  399. package/src/commands/package/listpackages.spec.ts +0 -163
  400. package/src/commands/package/listpackages.ts +0 -74
  401. package/src/commands/package/publish.spec.ts +0 -642
  402. package/src/commands/package/publish.ts +0 -236
  403. package/src/commands/package/updatepackage.spec.ts +0 -319
  404. package/src/commands/package/updatepackage.ts +0 -95
  405. package/src/commands/permission/createpermission.spec.ts +0 -507
  406. package/src/commands/permission/createpermission.ts +0 -181
  407. package/src/commands/permission/deletepermission.ts +0 -117
  408. package/src/commands/permission/getpermission.ts +0 -115
  409. package/src/commands/permission/listpermissions.ts +0 -101
  410. package/src/commands/permission/scope.ts +0 -180
  411. package/src/commands/rm.ts +0 -146
  412. package/src/commands/set.ts +0 -25
  413. package/src/commands/update.ts +0 -107
  414. package/src/commands/version/archive-unarchive-version.spec.ts +0 -456
  415. package/src/commands/version/archive-unarchive-version.ts +0 -108
  416. package/src/commands/version/listversions.spec.ts +0 -138
  417. package/src/commands/version/listversions.ts +0 -45
  418. package/src/common/UserGroupId.spec.ts +0 -115
  419. package/src/common/UserGroupId.ts +0 -137
  420. package/src/constants.spec.ts +0 -111
  421. package/src/constants.ts +0 -228
  422. package/src/index.ts +0 -378
  423. package/src/logger.spec.ts +0 -158
  424. package/src/logger.ts +0 -90
  425. package/src/polyfills/file.polyfill.ts +0 -6
  426. package/src/utils.spec.ts +0 -135
  427. package/src/utils.ts +0 -115
  428. package/src/validator.spec.ts +0 -51
  429. package/src/validator.ts +0 -44
  430. package/tsconfig.json +0 -17
@@ -45,6 +45,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
45
45
  return (mod && mod.__esModule) ? mod : { "default": mod };
46
46
  };
47
47
  Object.defineProperty(exports, "__esModule", { value: true });
48
+ const environments_1 = require("../../setup-core/environments");
48
49
  const child_process_1 = require("child_process");
49
50
  const axios_1 = __importDefault(require("axios"));
50
51
  const chai_1 = require("chai");
@@ -52,11 +53,15 @@ const fs_1 = __importDefault(require("fs"));
52
53
  const os_1 = __importDefault(require("os"));
53
54
  const path_1 = require("path");
54
55
  const sinon_1 = __importDefault(require("sinon"));
55
- const credConstants = __importStar(require("../../constants"));
56
+ const credEnvironments = __importStar(require("../../setup-core/environments"));
56
57
  const clientconfiguration_1 = require("../../clientconfiguration");
58
+ const logger_1 = require("../../logger");
57
59
  const login_1 = require("./login");
58
60
  const api_1 = require("../../client/api");
59
61
  const loopbackOAuth = __importStar(require("./loopbackOAuth"));
62
+ const utils = __importStar(require("../../utils"));
63
+ const browser = __importStar(require("../../browser"));
64
+ const refresh = __importStar(require("../../setup-core/refresh"));
60
65
  function createFakeIdToken(payload) {
61
66
  const header = Buffer.from(JSON.stringify({ alg: "none", typ: "JWT" })).toString("base64url");
62
67
  const body = Buffer.from(JSON.stringify(payload)).toString("base64url");
@@ -67,6 +72,8 @@ describe("login", () => {
67
72
  let tmpConfigFilePath;
68
73
  let axiosStub;
69
74
  let orgPermissionsStub;
75
+ let openStub;
76
+ let shouldOpenStub;
70
77
  const mockDeviceCodeResponse = {
71
78
  data: {
72
79
  verification_uri_complete: "https://example.com",
@@ -109,6 +116,9 @@ describe("login", () => {
109
116
  activeEnvironment: "production",
110
117
  }));
111
118
  axiosStub = sinon_1.default.stub(axios_1.default, "request");
119
+ // Never a real browser from a test run, even one started at a terminal.
120
+ openStub = sinon_1.default.stub(browser, "openInBrowser").resolves(true);
121
+ shouldOpenStub = sinon_1.default.stub(browser, "shouldOpenBrowser").returns(false);
112
122
  orgPermissionsStub = sinon_1.default
113
123
  .stub(api_1.OrganizationsApi.prototype, "getOrganization")
114
124
  .resolves(mockOrgPermissionsResponse);
@@ -134,6 +144,98 @@ describe("login", () => {
134
144
  (0, chai_1.expect)(config.getProject()).to.equal("bar");
135
145
  });
136
146
  });
147
+ it("opens the sign-in page for a person at a terminal, after printing it", function () {
148
+ return __awaiter(this, void 0, void 0, function* () {
149
+ this.timeout(2000);
150
+ shouldOpenStub.returns(true);
151
+ const info = sinon_1.default.stub(logger_1.logger, "info");
152
+ axiosStub
153
+ .onFirstCall()
154
+ .resolves(mockDeviceCodeResponse)
155
+ .onSecondCall()
156
+ .resolves(mockedAccessTokenResponse);
157
+ yield (0, login_1.login)("foo", "http://localhost", tmpConfigFilePath);
158
+ (0, chai_1.expect)(openStub.calledOnceWith("https://example.com")).to.equal(true);
159
+ // Printed first, so the link is there when the browser does not open.
160
+ const printed = info
161
+ .getCalls()
162
+ .findIndex((call) => String(call.args[0]) ===
163
+ "Please visit the following URL to login https://example.com and verify user code 123456.");
164
+ (0, chai_1.expect)(printed).to.be.greaterThan(-1);
165
+ (0, chai_1.expect)(info.calledWith(sinon_1.default.match("Opened your browser to sign in."))).to.equal(true);
166
+ });
167
+ });
168
+ it("only prints the link when no one is at a terminal", function () {
169
+ return __awaiter(this, void 0, void 0, function* () {
170
+ this.timeout(2000);
171
+ shouldOpenStub.returns(false);
172
+ axiosStub
173
+ .onFirstCall()
174
+ .resolves(mockDeviceCodeResponse)
175
+ .onSecondCall()
176
+ .resolves(mockedAccessTokenResponse);
177
+ yield (0, login_1.login)("foo", "http://localhost", tmpConfigFilePath);
178
+ (0, chai_1.expect)(openStub.called).to.equal(false);
179
+ });
180
+ });
181
+ it("stops polling on a final Auth0 answer instead of running out the clock", function () {
182
+ return __awaiter(this, void 0, void 0, function* () {
183
+ // `access_denied`, `expired_token`, `invalid_grant` are final for a
184
+ // device code; re-POSTing it can only fail again. The loop used to log
185
+ // and keep going for five minutes.
186
+ this.timeout(2000);
187
+ const exit = sinon_1.default.stub(process, "exit").callsFake(() => {
188
+ throw new Error("exited");
189
+ });
190
+ const errorLog = sinon_1.default.stub(logger_1.logger, "error");
191
+ axiosStub
192
+ .onFirstCall()
193
+ .resolves(mockDeviceCodeResponse)
194
+ .onSecondCall()
195
+ .rejects({
196
+ isAxiosError: true,
197
+ response: {
198
+ status: 403,
199
+ data: {
200
+ error: "access_denied",
201
+ error_description: "User denied the request",
202
+ },
203
+ },
204
+ });
205
+ yield (0, login_1.login)("foo", "http://localhost", tmpConfigFilePath).catch((error) => (0, chai_1.expect)(error.message).to.equal("exited"));
206
+ (0, chai_1.expect)(axiosStub.callCount, "no re-poll with a spent device code").to.equal(2);
207
+ (0, chai_1.expect)(exit.calledOnceWith(1)).to.equal(true);
208
+ (0, chai_1.expect)(errorLog.calledWith(sinon_1.default.match("User denied the request"))).to.equal(true);
209
+ });
210
+ });
211
+ it("keeps polling through a 5xx that carries no OAuth error code", function () {
212
+ return __awaiter(this, void 0, void 0, function* () {
213
+ // A proxy's 503 page says nothing about the device code, so it is a
214
+ // transport blip to retry, not a final answer to exit on.
215
+ this.timeout(4000);
216
+ const exit = sinon_1.default.stub(process, "exit").callsFake(() => {
217
+ throw new Error("exited");
218
+ });
219
+ sinon_1.default.stub(logger_1.logger, "error");
220
+ axiosStub
221
+ .onFirstCall()
222
+ .resolves(mockDeviceCodeResponse)
223
+ .onSecondCall()
224
+ .rejects({
225
+ isAxiosError: true,
226
+ message: "Request failed with status code 503",
227
+ response: { status: 503, data: "<html>Service Unavailable</html>" },
228
+ })
229
+ .onThirdCall()
230
+ .resolves(mockedAccessTokenResponse);
231
+ const config = new clientconfiguration_1.ClientConfiguration(tmpConfigFilePath);
232
+ config.setEnvironment("localhost");
233
+ yield (0, login_1.login)("test", "http://localhost", tmpConfigFilePath);
234
+ (0, chai_1.expect)(exit.called).to.equal(false);
235
+ (0, chai_1.expect)(axiosStub.callCount).to.equal(3);
236
+ (0, chai_1.expect)(config.getAccessToken()).to.equal(mockedAccessTokenResponse.data.access_token);
237
+ });
238
+ });
137
239
  it("should change the active organization when login succeeds", function () {
138
240
  return __awaiter(this, void 0, void 0, function* () {
139
241
  this.timeout(2000);
@@ -150,6 +252,297 @@ describe("login", () => {
150
252
  (0, chai_1.expect)(config.getOrganization()).to.equal("test");
151
253
  });
152
254
  });
255
+ /** An access token for localhost's API that expires `seconds` from now. */
256
+ function apiTokenExpiringIn(seconds) {
257
+ return createFakeIdToken({
258
+ aud: environments_1.auth0ConfigsByEnv.localhost.audience,
259
+ exp: Math.floor(Date.now() / 1000) + seconds,
260
+ });
261
+ }
262
+ function refreshResponse(body) {
263
+ return { status: 200, json: () => __awaiter(this, void 0, void 0, function* () { return body; }) };
264
+ }
265
+ // A live user session is not tied to an organization, so naming one is a
266
+ // switch. Signing in again asked for a second device code seconds after
267
+ // the first.
268
+ it("switches organization without signing in again when already signed in", function () {
269
+ return __awaiter(this, void 0, void 0, function* () {
270
+ const config = new clientconfiguration_1.ClientConfiguration(tmpConfigFilePath);
271
+ config.setEnvironment("localhost");
272
+ config.setOrganization("old-org");
273
+ config.setTokenPair({
274
+ accessToken: apiTokenExpiringIn(3600),
275
+ refreshToken: "refresh",
276
+ });
277
+ const fetchStub = sinon_1.default.stub(globalThis, "fetch");
278
+ yield (0, login_1.login)("new-org", "http://localhost", tmpConfigFilePath);
279
+ (0, chai_1.expect)(axiosStub.called, "no device-code request").to.equal(false);
280
+ (0, chai_1.expect)(orgPermissionsStub.firstCall.args[0]).to.equal("new-org");
281
+ (0, chai_1.expect)(new clientconfiguration_1.ClientConfiguration(tmpConfigFilePath).getOrganization()).to.equal("new-org");
282
+ // The token had an hour left, so there was nothing to renew.
283
+ (0, chai_1.expect)(fetchStub.called, "no refresh request").to.equal(false);
284
+ });
285
+ });
286
+ it("renews an expired token before switching, instead of signing in again", function () {
287
+ return __awaiter(this, void 0, void 0, function* () {
288
+ const config = new clientconfiguration_1.ClientConfiguration(tmpConfigFilePath);
289
+ config.setEnvironment("localhost");
290
+ config.setOrganization("old-org");
291
+ config.setTokenPair({
292
+ accessToken: apiTokenExpiringIn(-60),
293
+ refreshToken: "refresh",
294
+ });
295
+ const renewed = apiTokenExpiringIn(7200);
296
+ sinon_1.default
297
+ .stub(globalThis, "fetch")
298
+ .resolves(refreshResponse({ access_token: renewed }));
299
+ yield (0, login_1.login)("new-org", "http://localhost", tmpConfigFilePath);
300
+ (0, chai_1.expect)(axiosStub.called, "no device-code request").to.equal(false);
301
+ const after = new clientconfiguration_1.ClientConfiguration(tmpConfigFilePath);
302
+ (0, chai_1.expect)(after.getOrganization()).to.equal("new-org");
303
+ (0, chai_1.expect)(after.getApiAccessToken()).to.equal(renewed);
304
+ });
305
+ });
306
+ // A refresh token Auth0 refuses means the saved session is over. The
307
+ // switch must not report "already signed in" over it, and the sign-in that
308
+ // replaces it keeps the organization and environment the user had chosen.
309
+ it("signs in again when the saved session cannot be renewed, keeping the organization and environment", function () {
310
+ return __awaiter(this, void 0, void 0, function* () {
311
+ this.timeout(4000);
312
+ const config = new clientconfiguration_1.ClientConfiguration(tmpConfigFilePath);
313
+ config.setEnvironment("localhost");
314
+ config.setOrganization("acme");
315
+ config.setProject("analytics");
316
+ config.setTokenPair({
317
+ accessToken: apiTokenExpiringIn(-60),
318
+ refreshToken: "dead",
319
+ });
320
+ sinon_1.default
321
+ .stub(globalThis, "fetch")
322
+ .resolves(refreshResponse({ error: "invalid_grant" }));
323
+ let storedAtSignIn;
324
+ axiosStub.onFirstCall().callsFake(() => __awaiter(this, void 0, void 0, function* () {
325
+ storedAtSignIn = JSON.parse(fs_1.default.readFileSync(tmpConfigFilePath, "utf-8")).configPerEnvironment.localhost;
326
+ return mockDeviceCodeResponse;
327
+ }));
328
+ axiosStub.onSecondCall().resolves(mockedAccessTokenResponse);
329
+ const warnStub = sinon_1.default.stub(logger_1.logger, "warn");
330
+ yield (0, login_1.login)("acme", "https://admin.example", tmpConfigFilePath);
331
+ (0, chai_1.expect)(axiosStub.called, "fell through to the device sign-in").to.equal(true);
332
+ // Not the refresh's own "Run `cred login`": that is what is running.
333
+ (0, chai_1.expect)(warnStub.firstCall.args[0]).to.equal("Your saved session can no longer be renewed, so signing in again.");
334
+ // When the device-code sign-in started, only the tokens were gone.
335
+ (0, chai_1.expect)(storedAtSignIn).to.deep.equal({
336
+ organization: "acme",
337
+ project: "analytics",
338
+ });
339
+ const after = new clientconfiguration_1.ClientConfiguration(tmpConfigFilePath);
340
+ (0, chai_1.expect)(after.getEnvironment()).to.equal("localhost");
341
+ (0, chai_1.expect)(after.getOrganization()).to.equal("acme");
342
+ (0, chai_1.expect)(after.getProject()).to.equal("analytics");
343
+ (0, chai_1.expect)(after.getRefreshToken()).to.equal("mock-refresh-token");
344
+ });
345
+ });
346
+ // Auth0 unreachable is not a dead session. The token on disk is still
347
+ // valid, and a device-code sign-in would need the same Auth0.
348
+ it("switches on the token on disk when Auth0 cannot be reached and it is still valid", function () {
349
+ return __awaiter(this, void 0, void 0, function* () {
350
+ const config = new clientconfiguration_1.ClientConfiguration(tmpConfigFilePath);
351
+ config.setEnvironment("localhost");
352
+ config.setOrganization("old-org");
353
+ // Inside the renewal window, so a refresh is attempted, but still valid.
354
+ const onDisk = apiTokenExpiringIn(60);
355
+ config.setTokenPair({ accessToken: onDisk, refreshToken: "refresh" });
356
+ sinon_1.default
357
+ .stub(globalThis, "fetch")
358
+ .rejects(Object.assign(new Error("fetch failed"), { code: "ECONNREFUSED" }));
359
+ const warnStub = sinon_1.default.stub(logger_1.logger, "warn");
360
+ yield (0, login_1.login)("new-org", "http://localhost", tmpConfigFilePath);
361
+ (0, chai_1.expect)(axiosStub.called, "no device-code request").to.equal(false);
362
+ (0, chai_1.expect)(warnStub.firstCall.args[0]).to.equal(`Could not reach ${environments_1.auth0ConfigsByEnv.localhost.domain} to refresh your session. Continuing with the token on disk, which is still valid.`);
363
+ const after = new clientconfiguration_1.ClientConfiguration(tmpConfigFilePath);
364
+ (0, chai_1.expect)(after.getOrganization()).to.equal("new-org");
365
+ (0, chai_1.expect)(after.getApiAccessToken()).to.equal(onDisk);
366
+ });
367
+ });
368
+ it("signs in again when Auth0 cannot be reached and the token on disk has expired", function () {
369
+ return __awaiter(this, void 0, void 0, function* () {
370
+ this.timeout(4000);
371
+ const config = new clientconfiguration_1.ClientConfiguration(tmpConfigFilePath);
372
+ config.setEnvironment("localhost");
373
+ config.setTokenPair({
374
+ accessToken: apiTokenExpiringIn(-60),
375
+ refreshToken: "refresh",
376
+ });
377
+ sinon_1.default
378
+ .stub(globalThis, "fetch")
379
+ .rejects(Object.assign(new Error("fetch failed"), { code: "ECONNREFUSED" }));
380
+ axiosStub
381
+ .onFirstCall()
382
+ .resolves(mockDeviceCodeResponse)
383
+ .onSecondCall()
384
+ .resolves(mockedAccessTokenResponse);
385
+ yield (0, login_1.login)("new-org", "https://admin.example", tmpConfigFilePath);
386
+ (0, chai_1.expect)(axiosStub.called, "fell through to the device sign-in").to.equal(true);
387
+ });
388
+ });
389
+ // Another `cred` process holds the refresh lock past the wait. A device-code
390
+ // sign-in would race it for the same `~/.cred`, so stop and say to rerun.
391
+ it("stops instead of signing in when the renewal says to retry and the token on disk has expired", function () {
392
+ return __awaiter(this, void 0, void 0, function* () {
393
+ const config = new clientconfiguration_1.ClientConfiguration(tmpConfigFilePath);
394
+ config.setEnvironment("localhost");
395
+ config.setTokenPair({
396
+ accessToken: apiTokenExpiringIn(-60),
397
+ refreshToken: "refresh",
398
+ });
399
+ sinon_1.default.stub(refresh, "ensureFreshTokens").resolves({
400
+ status: "offline",
401
+ reason: "Another cred process has been renewing your session for over 25s.",
402
+ retry: "Run the command again in a moment.",
403
+ });
404
+ const errorStub = sinon_1.default.stub(logger_1.logger, "error");
405
+ const exitStub = sinon_1.default.stub(process, "exit").callsFake(() => {
406
+ throw new Error("exit");
407
+ });
408
+ yield (0, login_1.login)("new-org", "https://admin.example", tmpConfigFilePath).catch((error) => (0, chai_1.expect)(error.message).to.equal("exit"));
409
+ (0, chai_1.expect)(exitStub.calledOnceWithExactly(1)).to.equal(true);
410
+ (0, chai_1.expect)(errorStub.firstCall.args[0]).to.equal("Another cred process has been renewing your session for over 25s. Run the command again in a moment.");
411
+ (0, chai_1.expect)(axiosStub.called, "no device-code request").to.equal(false);
412
+ });
413
+ });
414
+ describe("with a saved session on localhost", () => {
415
+ let logStub;
416
+ beforeEach(() => {
417
+ logStub = sinon_1.default.stub(console, "log");
418
+ const config = new clientconfiguration_1.ClientConfiguration(tmpConfigFilePath);
419
+ config.setEnvironment("localhost");
420
+ config.setOrganization("old-org");
421
+ const payload = Buffer.from(JSON.stringify({
422
+ aud: environments_1.auth0ConfigsByEnv.localhost.audience,
423
+ exp: Math.floor(Date.now() / 1000) + 3600,
424
+ })).toString("base64url");
425
+ config.setTokenPair({
426
+ accessToken: `e30.${payload}.sig`,
427
+ refreshToken: "refresh",
428
+ });
429
+ });
430
+ const said = () => logStub.getCalls().map((call) => String(call.args[0]));
431
+ it("names the cell and says it switched only when the organization changed", function () {
432
+ return __awaiter(this, void 0, void 0, function* () {
433
+ yield (0, login_1.login)("new-org", "http://localhost", tmpConfigFilePath);
434
+ (0, chai_1.expect)(said()).to.eql([
435
+ "Already signed in to localhost, so this switched to new-org without signing in again. To sign in as someone else, pass --force.",
436
+ ]);
437
+ });
438
+ });
439
+ it("does not claim a switch when the organization was already selected", function () {
440
+ return __awaiter(this, void 0, void 0, function* () {
441
+ yield (0, login_1.login)("old-org", "http://localhost", tmpConfigFilePath);
442
+ (0, chai_1.expect)(said()).to.eql([
443
+ "Already signed in to localhost with old-org selected; nothing changed. To sign in as someone else, pass --force.",
444
+ ]);
445
+ });
446
+ });
447
+ it("does not claim a switch when the unreachable-server path writes the same organization", function () {
448
+ return __awaiter(this, void 0, void 0, function* () {
449
+ orgPermissionsStub.rejects(new Error("connection refused"));
450
+ yield (0, login_1.login)("old-org", "http://localhost", tmpConfigFilePath);
451
+ (0, chai_1.expect)(said().join("\n")).to.not.contain("switched");
452
+ (0, chai_1.expect)(said().join("\n")).to.contain("nothing changed");
453
+ });
454
+ });
455
+ it("keeps the selected environment when the unreachable-server path sees the same organization", function () {
456
+ return __awaiter(this, void 0, void 0, function* () {
457
+ new clientconfiguration_1.ClientConfiguration(tmpConfigFilePath).setProject("old-env");
458
+ orgPermissionsStub.rejects(new Error("connection refused"));
459
+ yield (0, login_1.login)("old-org", "http://localhost", tmpConfigFilePath);
460
+ (0, chai_1.expect)(new clientconfiguration_1.ClientConfiguration(tmpConfigFilePath).getProject()).to.equal("old-env");
461
+ });
462
+ });
463
+ it("--force signs in again instead of reusing the saved session", function () {
464
+ return __awaiter(this, void 0, void 0, function* () {
465
+ this.timeout(2000);
466
+ axiosStub
467
+ .onFirstCall()
468
+ .resolves(mockDeviceCodeResponse)
469
+ .onSecondCall()
470
+ .resolves(mockedAccessTokenResponse);
471
+ yield (0, login_1.login)("new-org", "http://localhost", tmpConfigFilePath, undefined, undefined, { force: true });
472
+ (0, chai_1.expect)(axiosStub.called, "a device-code sign-in").to.equal(true);
473
+ const stored = new clientconfiguration_1.ClientConfiguration(tmpConfigFilePath);
474
+ (0, chai_1.expect)(stored.getAccessToken()).to.equal("mock-access-token");
475
+ (0, chai_1.expect)(stored.getOrganization()).to.equal("new-org");
476
+ (0, chai_1.expect)(said()).to.eql([
477
+ "Login successful. Signed in to new-org on localhost.",
478
+ ]);
479
+ });
480
+ });
481
+ it("--force leaves the other cells' credentials alone", function () {
482
+ return __awaiter(this, void 0, void 0, function* () {
483
+ this.timeout(2000);
484
+ new clientconfiguration_1.ClientConfiguration(tmpConfigFilePath, "staging").setTokenPair({
485
+ accessToken: "staging-token",
486
+ });
487
+ axiosStub
488
+ .onFirstCall()
489
+ .resolves(mockDeviceCodeResponse)
490
+ .onSecondCall()
491
+ .resolves(mockedAccessTokenResponse);
492
+ yield (0, login_1.login)("new-org", "http://localhost", tmpConfigFilePath, undefined, "localhost", { force: true });
493
+ (0, chai_1.expect)(new clientconfiguration_1.ClientConfiguration(tmpConfigFilePath, "staging").getAccessToken()).to.equal("staging-token");
494
+ });
495
+ });
496
+ });
497
+ describe("bareCellWarning", () => {
498
+ it("names the global cell and both ways to stop depending on it", () => {
499
+ (0, chai_1.expect)((0, login_1.bareCellWarning)("staging", {
500
+ deployment: "videoamp",
501
+ from: "global",
502
+ })).to.equal("Your global cell is still videoamp; pass --cell staging on every command or run `cred set cell staging`.");
503
+ });
504
+ it("points at re-pinning, not `set cell`, in a pinned directory", () => {
505
+ (0, chai_1.expect)((0, login_1.bareCellWarning)("staging", {
506
+ deployment: "videoamp",
507
+ from: "folder",
508
+ })).to.equal("This directory is pinned to videoamp; pass --cell staging on every command here, or re-pin with `cred --cell staging init`.");
509
+ });
510
+ it("says nothing when bare commands already resolve to the cell logged in to", () => {
511
+ (0, chai_1.expect)((0, login_1.bareCellWarning)("staging", {
512
+ deployment: "staging",
513
+ from: "folder",
514
+ })).to.equal(undefined);
515
+ });
516
+ });
517
+ // The saved token passed its local checks but the server refused it: the
518
+ // switch must fall back to a real sign-in, or every retry fails the same way.
519
+ it("signs in again when the server rejects the saved session", function () {
520
+ return __awaiter(this, void 0, void 0, function* () {
521
+ this.timeout(4000);
522
+ const config = new clientconfiguration_1.ClientConfiguration(tmpConfigFilePath);
523
+ config.setEnvironment("localhost");
524
+ config.setTokenPair({
525
+ accessToken: apiTokenExpiringIn(3600),
526
+ refreshToken: "r",
527
+ });
528
+ orgPermissionsStub
529
+ .onFirstCall()
530
+ .rejects(Object.assign(new Error("Request failed with status code 401"), {
531
+ isAxiosError: true,
532
+ response: { status: 401 },
533
+ }))
534
+ .onSecondCall()
535
+ .resolves(mockOrgPermissionsResponse);
536
+ axiosStub
537
+ .onFirstCall()
538
+ .resolves(mockDeviceCodeResponse)
539
+ .onSecondCall()
540
+ .resolves(mockedAccessTokenResponse);
541
+ yield (0, login_1.login)("new-org", "https://admin.example", tmpConfigFilePath);
542
+ (0, chai_1.expect)(axiosStub.called, "fell through to the device sign-in").to.equal(true);
543
+ (0, chai_1.expect)(new clientconfiguration_1.ClientConfiguration(tmpConfigFilePath).getOrganization()).to.equal("new-org");
544
+ });
545
+ });
153
546
  it("should set an access token when login succeeds", function () {
154
547
  return __awaiter(this, void 0, void 0, function* () {
155
548
  this.timeout(2000);
@@ -200,7 +593,7 @@ describe("login", () => {
200
593
  return __awaiter(this, void 0, void 0, function* () {
201
594
  this.timeout(2000);
202
595
  const orgIdStub = sinon_1.default
203
- .stub(credConstants, "getAuth0OrganizationIdForCliLogin")
596
+ .stub(credEnvironments, "getAuth0OrganizationIdForCliLogin")
204
597
  .returns("org_nMRKafeSuxOiuJeG");
205
598
  const loopbackStub = sinon_1.default
206
599
  .stub(loopbackOAuth, "authorizationCodeViaLoopback")
@@ -223,7 +616,7 @@ describe("login", () => {
223
616
  return __awaiter(this, void 0, void 0, function* () {
224
617
  this.timeout(2000);
225
618
  const orgIdStub = sinon_1.default
226
- .stub(credConstants, "getAuth0OrganizationIdForCliLogin")
619
+ .stub(credEnvironments, "getAuth0OrganizationIdForCliLogin")
227
620
  .callsFake((name) => name.toLowerCase() === "videoamp"
228
621
  ? "org_nMRKafeSuxOiuJeG"
229
622
  : undefined);
@@ -246,7 +639,7 @@ describe("login", () => {
246
639
  return __awaiter(this, void 0, void 0, function* () {
247
640
  this.timeout(2000);
248
641
  const orgIdStub = sinon_1.default
249
- .stub(credConstants, "getAuth0OrganizationIdForCliLogin")
642
+ .stub(credEnvironments, "getAuth0OrganizationIdForCliLogin")
250
643
  .returns("org_nMRKafeSuxOiuJeG");
251
644
  sinon_1.default
252
645
  .stub(loopbackOAuth, "authorizationCodeViaLoopback")
@@ -282,10 +675,23 @@ describe("isLoginInvocation", () => {
282
675
  (0, chai_1.expect)((0, login_1.isLoginInvocation)(["node", "/x/index.js", "login", "myorg"])).to.be
283
676
  .true;
284
677
  });
678
+ // The global flag comes before the command, so it is argv[2].
679
+ it("is true when --non-interactive comes before login", () => {
680
+ (0, chai_1.expect)((0, login_1.isLoginInvocation)([
681
+ "node",
682
+ "/x/index.js",
683
+ "--non-interactive",
684
+ "login",
685
+ "myorg",
686
+ ])).to.be.true;
687
+ });
285
688
  it("is false for other commands (they stay fail-loud on a corrupt config)", () => {
286
689
  (0, chai_1.expect)((0, login_1.isLoginInvocation)(["node", "/x/index.js", "status"])).to.be.false;
287
690
  (0, chai_1.expect)((0, login_1.isLoginInvocation)(["node", "/x/index.js", "publish"])).to.be.false;
288
691
  (0, chai_1.expect)((0, login_1.isLoginInvocation)(["node", "/x/index.js"])).to.be.false;
692
+ // An argument to another command is not the command.
693
+ (0, chai_1.expect)((0, login_1.isLoginInvocation)(["node", "/x/index.js", "get", "login"])).to.be
694
+ .false;
289
695
  });
290
696
  });
291
697
  // Drives the real binary entrypoint (src/index.ts), not recoverIfCorrupt() in
@@ -324,18 +730,23 @@ describe("entrypoint recovery for a corrupt ~/.cred (real index.ts)", () => {
324
730
  let output = "";
325
731
  child.stdout.on("data", (d) => (output += d.toString()));
326
732
  child.stderr.on("data", (d) => (output += d.toString()));
733
+ // Registered now so it cannot be missed if the child exits on its own.
734
+ const closed = new Promise((r) => child.on("close", () => r()));
327
735
  // Recovery runs synchronously at module load, before login() touches the
328
736
  // network. It renames the corrupt file aside (.cred.corrupt-*) and THEN
329
737
  // rewrites .cred to a valid default. Gate on the rewrite, not the backup:
330
738
  // the backup appears first, so killing the instant it shows can catch the
331
739
  // child in the gap before .cred is rewritten — a flaky ENOENT on the read
332
740
  // below. resetComplete() only goes true once .cred is the valid default
333
- // (which implies the backup already happened). Then stop the process
334
- // (login otherwise blocks on the device-code flow).
741
+ // (which implies the backup already happened). The report is printed AFTER
742
+ // that rewrite, so also wait for it: a loaded CI runner can pause the child
743
+ // between the two, and killing it there leaves `output` empty. Then stop
744
+ // the process (login otherwise blocks on the device-code flow).
335
745
  const resetComplete = () => {
336
746
  try {
337
747
  return (JSON.parse(fs_1.default.readFileSync(credPath, "utf8"))
338
- .activeEnvironment === "production");
748
+ .activeEnvironment === "production" &&
749
+ /reset to defaults/.test(output));
339
750
  }
340
751
  catch (_a) {
341
752
  return false; // .cred absent or mid-rewrite
@@ -355,6 +766,8 @@ describe("entrypoint recovery for a corrupt ~/.cred (real index.ts)", () => {
355
766
  });
356
767
  });
357
768
  child.kill("SIGKILL");
769
+ // Let the stdio streams drain so everything the child wrote is in `output`.
770
+ yield closed;
358
771
  const backup = findBackup();
359
772
  (0, chai_1.expect)(backup, "corrupt config should be backed up aside").to.be.a("string");
360
773
  // The bad contents are preserved in the backup, not destroyed.
@@ -365,6 +778,111 @@ describe("entrypoint recovery for a corrupt ~/.cred (real index.ts)", () => {
365
778
  (0, chai_1.expect)(reset.configPerEnvironment).to.be.an("object");
366
779
  // The startup read no longer dead-ends on the structure error.
367
780
  (0, chai_1.expect)(output).to.not.match(/Invalid config structure/);
781
+ // And it SAYS so. `recoverIfCorrupt` returns the backup path instead of
782
+ // logging (setup-core owns no logger), which makes reporting the caller's
783
+ // job — and a caller that drops the return value resets a user's tokens
784
+ // and moves their file with no output at all. Asserting the absence of an
785
+ // error above cannot catch that; only asserting the presence of this can.
786
+ (0, chai_1.expect)(output, "the reset must be reported, not silent").to.match(/reset to defaults/);
787
+ (0, chai_1.expect)(output).to.contain(backup);
788
+ });
789
+ });
790
+ });
791
+ describe("login without an organization argument", () => {
792
+ let tmpConfigFilePath;
793
+ let axiosStub;
794
+ let listOrgsStub;
795
+ let selectStub;
796
+ const mockDeviceCode = {
797
+ data: {
798
+ verification_uri_complete: "https://example.com",
799
+ user_code: "123456",
800
+ device_code: "device-code-123",
801
+ interval: 1,
802
+ },
803
+ };
804
+ const mockTokens = {
805
+ data: {
806
+ id_token: createFakeIdToken({ name: "T", email: "t@example.com" }),
807
+ access_token: "mock-access-token",
808
+ refresh_token: "mock-refresh-token",
809
+ },
810
+ };
811
+ beforeEach(() => {
812
+ // Never a real browser from a test run, even one started at a terminal.
813
+ sinon_1.default.stub(browser, "shouldOpenBrowser").returns(false);
814
+ tmpConfigFilePath = (0, path_1.join)(fs_1.default.mkdtempSync((0, path_1.join)(os_1.default.tmpdir(), "cred-orgless-")), "cred.json");
815
+ fs_1.default.writeFileSync(tmpConfigFilePath, JSON.stringify({
816
+ configPerEnvironment: { localhost: {} },
817
+ activeEnvironment: "localhost",
818
+ }));
819
+ axiosStub = sinon_1.default
820
+ .stub(axios_1.default, "request")
821
+ .onFirstCall()
822
+ .resolves(mockDeviceCode)
823
+ .onSecondCall()
824
+ .resolves(mockTokens);
825
+ sinon_1.default
826
+ .stub(api_1.OrganizationsApi.prototype, "getOrganization")
827
+ .resolves({ status: 200, data: {} });
828
+ listOrgsStub = sinon_1.default.stub(api_1.OrganizationsApi.prototype, "listOrganizations");
829
+ selectStub = sinon_1.default.stub(utils, "selectFromList");
830
+ });
831
+ afterEach(() => {
832
+ sinon_1.default.restore();
833
+ fs_1.default.rmSync(tmpConfigFilePath, { force: true });
834
+ });
835
+ it("auto-selects when the user belongs to exactly one organization", function () {
836
+ return __awaiter(this, void 0, void 0, function* () {
837
+ this.timeout(2000);
838
+ listOrgsStub.resolves({ data: [{ name: "only-org" }] });
839
+ // selectFromList returns a single choice without prompting; assert the
840
+ // stored org rather than trusting the prompt was skipped by accident.
841
+ selectStub.callsFake((_msg, choices) => __awaiter(this, void 0, void 0, function* () { return choices.length === 1 ? choices[0].value : undefined; }));
842
+ yield (0, login_1.login)(undefined, "http://admin.ms2.localhost/api/v0", tmpConfigFilePath);
843
+ const config = new clientconfiguration_1.ClientConfiguration(tmpConfigFilePath);
844
+ (0, chai_1.expect)(config.getOrganization()).to.equal("only-org");
845
+ });
846
+ });
847
+ it("prompts when the user belongs to several organizations, and shows display names", function () {
848
+ return __awaiter(this, void 0, void 0, function* () {
849
+ this.timeout(2000);
850
+ listOrgsStub.resolves({
851
+ data: [{ name: "alpha", displayName: "Alpha Inc" }, { name: "beta" }],
852
+ });
853
+ selectStub.resolves("beta");
854
+ yield (0, login_1.login)(undefined, "http://admin.ms2.localhost/api/v0", tmpConfigFilePath);
855
+ (0, chai_1.expect)(selectStub.calledOnce).to.equal(true);
856
+ (0, chai_1.expect)(selectStub.getCall(0).args[1]).to.eql([
857
+ { name: "alpha (Alpha Inc)", value: "alpha" },
858
+ { name: "beta", value: "beta" },
859
+ ]);
860
+ (0, chai_1.expect)(new clientconfiguration_1.ClientConfiguration(tmpConfigFilePath).getOrganization()).to.equal("beta");
861
+ });
862
+ });
863
+ it("skips entries the control plane returned without a name", function () {
864
+ return __awaiter(this, void 0, void 0, function* () {
865
+ this.timeout(2000);
866
+ listOrgsStub.resolves({
867
+ data: [{ displayName: "No name" }, { name: "real" }],
868
+ });
869
+ selectStub.callsFake((_msg, choices) => __awaiter(this, void 0, void 0, function* () { return choices.length === 1 ? choices[0].value : undefined; }));
870
+ yield (0, login_1.login)(undefined, "http://admin.ms2.localhost/api/v0", tmpConfigFilePath);
871
+ (0, chai_1.expect)(selectStub.getCall(0).args[1]).to.eql([
872
+ { name: "real", value: "real" },
873
+ ]);
874
+ });
875
+ });
876
+ it("does not list organizations when one was named (scripted use stays one call)", function () {
877
+ return __awaiter(this, void 0, void 0, function* () {
878
+ this.timeout(2000);
879
+ yield (0, login_1.login)("given-org", "http://admin.ms2.localhost/api/v0", tmpConfigFilePath);
880
+ (0, chai_1.expect)(listOrgsStub.called).to.equal(false);
881
+ (0, chai_1.expect)(selectStub.called).to.equal(false);
882
+ // Assert the login actually completed, so this test cannot pass by
883
+ // failing early before it would have listed organizations.
884
+ (0, chai_1.expect)(new clientconfiguration_1.ClientConfiguration(tmpConfigFilePath).getOrganization()).to.equal("given-org");
885
+ (0, chai_1.expect)(axiosStub.called).to.equal(true);
368
886
  });
369
887
  });
370
888
  });