@pnp/cli-microsoft365 7.3.0-beta.ca3f7f5 → 7.3.0-beta.d293309

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 (253) hide show
  1. package/allCommands.json +1 -1
  2. package/allCommandsFull.json +1 -1
  3. package/dist/Auth.js +3 -4
  4. package/dist/Command.js +10 -13
  5. package/dist/api.js +2 -3
  6. package/dist/autocomplete.js +4 -6
  7. package/dist/chili/chili.js +1 -2
  8. package/dist/cli/cli.js +880 -0
  9. package/dist/index.js +2 -2
  10. package/dist/m365/aad/commands/administrativeunit/administrativeunit-member-list.js +138 -0
  11. package/dist/m365/aad/commands/administrativeunit/administrativeunit-remove.js +2 -2
  12. package/dist/m365/aad/commands/app/app-get.js +2 -2
  13. package/dist/m365/aad/commands/app/app-remove.js +3 -3
  14. package/dist/m365/aad/commands/app/app-role-add.js +2 -2
  15. package/dist/m365/aad/commands/app/app-role-list.js +2 -2
  16. package/dist/m365/aad/commands/app/app-role-remove.js +4 -4
  17. package/dist/m365/aad/commands/app/app-set.js +2 -2
  18. package/dist/m365/aad/commands/approleassignment/approleassignment-add.js +2 -2
  19. package/dist/m365/aad/commands/approleassignment/approleassignment-remove.js +2 -2
  20. package/dist/m365/aad/commands/group/group-list.js +2 -2
  21. package/dist/m365/aad/commands/group/group-remove.js +2 -2
  22. package/dist/m365/aad/commands/groupsetting/groupsetting-remove.js +2 -2
  23. package/dist/m365/aad/commands/m365group/m365group-recyclebinitem-clear.js +2 -2
  24. package/dist/m365/aad/commands/m365group/m365group-recyclebinitem-remove.js +3 -3
  25. package/dist/m365/aad/commands/m365group/m365group-recyclebinitem-restore.js +2 -2
  26. package/dist/m365/aad/commands/m365group/m365group-remove.js +2 -2
  27. package/dist/m365/aad/commands/m365group/m365group-teamify.js +2 -2
  28. package/dist/m365/aad/commands/m365group/m365group-user-remove.js +2 -2
  29. package/dist/m365/aad/commands/oauth2grant/oauth2grant-remove.js +2 -2
  30. package/dist/m365/aad/commands/siteclassification/siteclassification-disable.js +2 -2
  31. package/dist/m365/aad/commands/sp/sp-add.js +2 -2
  32. package/dist/m365/aad/commands/sp/sp-get.js +2 -2
  33. package/dist/m365/aad/commands/user/user-get.js +2 -2
  34. package/dist/m365/aad/commands/user/user-license-remove.js +2 -2
  35. package/dist/m365/aad/commands/user/user-recyclebinitem-clear.js +2 -2
  36. package/dist/m365/aad/commands/user/user-recyclebinitem-remove.js +2 -2
  37. package/dist/m365/aad/commands/user/user-remove.js +2 -2
  38. package/dist/m365/aad/commands.js +1 -0
  39. package/dist/m365/app/commands/app-get.js +2 -2
  40. package/dist/m365/app/commands/app-open.js +2 -2
  41. package/dist/m365/app/commands/permission/permission-list.js +2 -2
  42. package/dist/m365/base/AppCommand.js +2 -2
  43. package/dist/m365/booking/commands/business/business-get.js +2 -2
  44. package/dist/m365/cli/commands/cli-doctor.js +2 -2
  45. package/dist/m365/cli/commands/cli-reconsent.js +2 -2
  46. package/dist/m365/cli/commands/config/config-get.js +2 -2
  47. package/dist/m365/cli/commands/config/config-list.js +2 -2
  48. package/dist/m365/cli/commands/config/config-reset.js +3 -3
  49. package/dist/m365/cli/commands/config/config-set.js +4 -4
  50. package/dist/m365/commands/docs.js +2 -2
  51. package/dist/m365/commands/login.js +4 -4
  52. package/dist/m365/commands/setup.js +8 -8
  53. package/dist/m365/context/commands/context-remove.js +2 -2
  54. package/dist/m365/context/commands/option/option-remove.js +2 -2
  55. package/dist/m365/external/commands/connection/connection-doctor.js +1 -2
  56. package/dist/m365/external/commands/connection/connection-remove.js +3 -3
  57. package/dist/m365/flow/commands/flow-remove.js +2 -2
  58. package/dist/m365/flow/commands/owner/owner-list.js +2 -2
  59. package/dist/m365/flow/commands/owner/owner-remove.js +2 -2
  60. package/dist/m365/flow/commands/run/run-cancel.js +2 -2
  61. package/dist/m365/flow/commands/run/run-resubmit.js +2 -2
  62. package/dist/m365/graph/commands/changelog/changelog-list.js +3 -3
  63. package/dist/m365/graph/commands/schemaextension/schemaextension-remove.js +2 -2
  64. package/dist/m365/outlook/commands/message/message-list.js +2 -2
  65. package/dist/m365/outlook/commands/message/message-move.js +2 -2
  66. package/dist/m365/pa/commands/app/app-consent-set.js +2 -2
  67. package/dist/m365/pa/commands/app/app-get.js +2 -2
  68. package/dist/m365/pa/commands/app/app-permission-remove.js +2 -2
  69. package/dist/m365/pa/commands/app/app-remove.js +2 -2
  70. package/dist/m365/planner/commands/bucket/bucket-get.js +2 -2
  71. package/dist/m365/planner/commands/bucket/bucket-remove.js +3 -3
  72. package/dist/m365/planner/commands/bucket/bucket-set.js +2 -2
  73. package/dist/m365/planner/commands/plan/plan-remove.js +2 -2
  74. package/dist/m365/planner/commands/roster/roster-member-remove.js +3 -3
  75. package/dist/m365/planner/commands/roster/roster-remove.js +2 -2
  76. package/dist/m365/planner/commands/task/task-checklistitem-add.js +2 -2
  77. package/dist/m365/planner/commands/task/task-checklistitem-list.js +2 -2
  78. package/dist/m365/planner/commands/task/task-checklistitem-remove.js +2 -2
  79. package/dist/m365/planner/commands/task/task-get.js +3 -3
  80. package/dist/m365/planner/commands/task/task-reference-remove.js +2 -2
  81. package/dist/m365/planner/commands/task/task-remove.js +4 -4
  82. package/dist/m365/pp/commands/aibuildermodel/aibuildermodel-get.js +2 -2
  83. package/dist/m365/pp/commands/aibuildermodel/aibuildermodel-remove.js +3 -3
  84. package/dist/m365/pp/commands/card/card-clone.js +2 -2
  85. package/dist/m365/pp/commands/card/card-get.js +2 -2
  86. package/dist/m365/pp/commands/card/card-remove.js +3 -3
  87. package/dist/m365/pp/commands/chatbot/chatbot-get.js +2 -2
  88. package/dist/m365/pp/commands/chatbot/chatbot-remove.js +3 -3
  89. package/dist/m365/pp/commands/dataverse/dataverse-table-remove.js +2 -2
  90. package/dist/m365/pp/commands/dataverse/dataverse-table-row-remove.js +2 -2
  91. package/dist/m365/pp/commands/managementapp/managementapp-add.js +2 -2
  92. package/dist/m365/pp/commands/solution/solution-get.js +2 -2
  93. package/dist/m365/pp/commands/solution/solution-list.js +2 -2
  94. package/dist/m365/pp/commands/solution/solution-publish.js +2 -2
  95. package/dist/m365/pp/commands/solution/solution-publisher-remove.js +3 -3
  96. package/dist/m365/pp/commands/solution/solution-remove.js +3 -3
  97. package/dist/m365/purview/commands/retentionevent/retentionevent-remove.js +2 -2
  98. package/dist/m365/purview/commands/retentioneventtype/retentioneventtype-remove.js +2 -2
  99. package/dist/m365/purview/commands/retentionlabel/retentionlabel-remove.js +2 -2
  100. package/dist/m365/spfx/commands/project/project-permissions-grant.js +2 -2
  101. package/dist/m365/spo/commands/app/app-add.js +2 -2
  102. package/dist/m365/spo/commands/app/app-remove.js +2 -2
  103. package/dist/m365/spo/commands/app/app-retract.js +2 -2
  104. package/dist/m365/spo/commands/app/app-uninstall.js +2 -2
  105. package/dist/m365/spo/commands/applicationcustomizer/applicationcustomizer-get.js +2 -2
  106. package/dist/m365/spo/commands/applicationcustomizer/applicationcustomizer-remove.js +3 -3
  107. package/dist/m365/spo/commands/applicationcustomizer/applicationcustomizer-set.js +2 -2
  108. package/dist/m365/spo/commands/cdn/cdn-origin-remove.js +2 -2
  109. package/dist/m365/spo/commands/commandset/commandset-get.js +2 -2
  110. package/dist/m365/spo/commands/commandset/commandset-remove.js +3 -3
  111. package/dist/m365/spo/commands/commandset/commandset-set.js +2 -2
  112. package/dist/m365/spo/commands/contenttype/contenttype-add.js +2 -2
  113. package/dist/m365/spo/commands/contenttype/contenttype-field-remove.js +2 -2
  114. package/dist/m365/spo/commands/contenttype/contenttype-remove.js +2 -2
  115. package/dist/m365/spo/commands/customaction/customaction-clear.js +2 -2
  116. package/dist/m365/spo/commands/customaction/customaction-get.js +3 -3
  117. package/dist/m365/spo/commands/customaction/customaction-remove.js +3 -3
  118. package/dist/m365/spo/commands/eventreceiver/eventreceiver-get.js +2 -2
  119. package/dist/m365/spo/commands/eventreceiver/eventreceiver-remove.js +3 -3
  120. package/dist/m365/spo/commands/field/field-remove.js +2 -2
  121. package/dist/m365/spo/commands/file/file-checkout-undo.js +2 -2
  122. package/dist/m365/spo/commands/file/file-remove.js +2 -2
  123. package/dist/m365/spo/commands/file/file-rename.js +2 -2
  124. package/dist/m365/spo/commands/file/file-retentionlabel-remove.js +2 -2
  125. package/dist/m365/spo/commands/file/file-roleassignment-add.js +5 -5
  126. package/dist/m365/spo/commands/file/file-roleassignment-remove.js +5 -5
  127. package/dist/m365/spo/commands/file/file-roleinheritance-break.js +3 -3
  128. package/dist/m365/spo/commands/file/file-roleinheritance-reset.js +3 -3
  129. package/dist/m365/spo/commands/file/file-sharinginfo-get.js +2 -2
  130. package/dist/m365/spo/commands/file/file-sharinglink-clear.js +3 -3
  131. package/dist/m365/spo/commands/file/file-sharinglink-list.js +2 -2
  132. package/dist/m365/spo/commands/file/file-sharinglink-remove.js +2 -2
  133. package/dist/m365/spo/commands/file/file-version-clear.js +2 -2
  134. package/dist/m365/spo/commands/file/file-version-remove.js +2 -2
  135. package/dist/m365/spo/commands/file/file-version-restore.js +2 -2
  136. package/dist/m365/spo/commands/folder/folder-remove.js +2 -2
  137. package/dist/m365/spo/commands/folder/folder-retentionlabel-remove.js +2 -2
  138. package/dist/m365/spo/commands/folder/folder-roleassignment-add.js +4 -4
  139. package/dist/m365/spo/commands/folder/folder-roleassignment-remove.js +4 -4
  140. package/dist/m365/spo/commands/folder/folder-roleinheritance-break.js +2 -2
  141. package/dist/m365/spo/commands/folder/folder-roleinheritance-reset.js +2 -2
  142. package/dist/m365/spo/commands/group/group-list.js +2 -2
  143. package/dist/m365/spo/commands/group/group-member-remove.js +9 -9
  144. package/dist/m365/spo/commands/group/group-remove.js +2 -2
  145. package/dist/m365/spo/commands/group/group-set.js +2 -2
  146. package/dist/m365/spo/commands/homesite/homesite-remove.js +2 -2
  147. package/dist/m365/spo/commands/hubsite/hubsite-connect.js +2 -2
  148. package/dist/m365/spo/commands/hubsite/hubsite-disconnect.js +3 -3
  149. package/dist/m365/spo/commands/hubsite/hubsite-get.js +4 -4
  150. package/dist/m365/spo/commands/hubsite/hubsite-rights-revoke.js +2 -2
  151. package/dist/m365/spo/commands/hubsite/hubsite-unregister.js +2 -2
  152. package/dist/m365/spo/commands/knowledgehub/knowledgehub-remove.js +2 -2
  153. package/dist/m365/spo/commands/list/list-contenttype-remove.js +2 -2
  154. package/dist/m365/spo/commands/list/list-remove.js +2 -2
  155. package/dist/m365/spo/commands/list/list-retentionlabel-remove.js +2 -2
  156. package/dist/m365/spo/commands/list/list-roleassignment-remove.js +4 -4
  157. package/dist/m365/spo/commands/list/list-roleinheritance-break.js +2 -2
  158. package/dist/m365/spo/commands/list/list-roleinheritance-reset.js +2 -2
  159. package/dist/m365/spo/commands/list/list-view-field-remove.js +2 -2
  160. package/dist/m365/spo/commands/list/list-view-remove.js +2 -2
  161. package/dist/m365/spo/commands/list/list-webhook-remove.js +2 -2
  162. package/dist/m365/spo/commands/listitem/listitem-attachment-remove.js +2 -2
  163. package/dist/m365/spo/commands/listitem/listitem-list.js +2 -2
  164. package/dist/m365/spo/commands/listitem/listitem-remove.js +2 -2
  165. package/dist/m365/spo/commands/listitem/listitem-retentionlabel-remove.js +2 -2
  166. package/dist/m365/spo/commands/listitem/listitem-roleassignment-add.js +4 -4
  167. package/dist/m365/spo/commands/listitem/listitem-roleassignment-remove.js +4 -4
  168. package/dist/m365/spo/commands/listitem/listitem-roleinheritance-break.js +2 -2
  169. package/dist/m365/spo/commands/listitem/listitem-roleinheritance-reset.js +2 -2
  170. package/dist/m365/spo/commands/navigation/navigation-node-remove.js +2 -2
  171. package/dist/m365/spo/commands/orgassetslibrary/orgassetslibrary-remove.js +2 -2
  172. package/dist/m365/spo/commands/orgnewssite/orgnewssite-remove.js +2 -2
  173. package/dist/m365/spo/commands/page/page-add.js +4 -4
  174. package/dist/m365/spo/commands/page/page-column-get.js +2 -2
  175. package/dist/m365/spo/commands/page/page-column-list.js +2 -2
  176. package/dist/m365/spo/commands/page/page-remove.js +2 -2
  177. package/dist/m365/spo/commands/page/page-section-get.js +2 -2
  178. package/dist/m365/spo/commands/page/page-section-list.js +2 -2
  179. package/dist/m365/spo/commands/page/page-set.js +5 -5
  180. package/dist/m365/spo/commands/propertybag/propertybag-remove.js +2 -2
  181. package/dist/m365/spo/commands/roledefinition/roledefinition-remove.js +2 -2
  182. package/dist/m365/spo/commands/serviceprincipal/serviceprincipal-permissionrequest-approve.js +2 -2
  183. package/dist/m365/spo/commands/serviceprincipal/serviceprincipal-set.js +2 -2
  184. package/dist/m365/spo/commands/site/site-apppermission-remove.js +2 -2
  185. package/dist/m365/spo/commands/site/site-hubsite-disconnect.js +2 -2
  186. package/dist/m365/spo/commands/site/site-recyclebinitem-clear.js +2 -2
  187. package/dist/m365/spo/commands/site/site-recyclebinitem-move.js +2 -2
  188. package/dist/m365/spo/commands/site/site-recyclebinitem-remove.js +2 -2
  189. package/dist/m365/spo/commands/site/site-remove.js +2 -2
  190. package/dist/m365/spo/commands/site/site-set.js +3 -3
  191. package/dist/m365/spo/commands/sitedesign/sitedesign-get.js +2 -2
  192. package/dist/m365/spo/commands/sitedesign/sitedesign-remove.js +2 -2
  193. package/dist/m365/spo/commands/sitedesign/sitedesign-rights-revoke.js +2 -2
  194. package/dist/m365/spo/commands/sitedesign/sitedesign-task-remove.js +2 -2
  195. package/dist/m365/spo/commands/sitescript/sitescript-remove.js +2 -2
  196. package/dist/m365/spo/commands/spo-search.js +2 -2
  197. package/dist/m365/spo/commands/storageentity/storageentity-remove.js +2 -2
  198. package/dist/m365/spo/commands/tenant/tenant-appcatalog-add.js +5 -5
  199. package/dist/m365/spo/commands/tenant/tenant-applicationcustomizer-add.js +5 -5
  200. package/dist/m365/spo/commands/tenant/tenant-applicationcustomizer-get.js +2 -2
  201. package/dist/m365/spo/commands/tenant/tenant-applicationcustomizer-remove.js +3 -3
  202. package/dist/m365/spo/commands/tenant/tenant-applicationcustomizer-set.js +4 -4
  203. package/dist/m365/spo/commands/tenant/tenant-commandset-add.js +5 -5
  204. package/dist/m365/spo/commands/tenant/tenant-commandset-get.js +2 -2
  205. package/dist/m365/spo/commands/tenant/tenant-commandset-remove.js +3 -3
  206. package/dist/m365/spo/commands/tenant/tenant-recyclebinitem-remove.js +2 -2
  207. package/dist/m365/spo/commands/term/term-get.js +2 -2
  208. package/dist/m365/spo/commands/term/term-list.js +2 -2
  209. package/dist/m365/spo/commands/theme/theme-remove.js +2 -2
  210. package/dist/m365/spo/commands/user/user-remove.js +2 -2
  211. package/dist/m365/spo/commands/userprofile/userprofile-get.js +2 -2
  212. package/dist/m365/spo/commands/web/web-remove.js +2 -2
  213. package/dist/m365/spo/commands/web/web-roleassignment-add.js +4 -4
  214. package/dist/m365/spo/commands/web/web-roleassignment-remove.js +4 -4
  215. package/dist/m365/spo/commands/web/web-roleinheritance-break.js +2 -2
  216. package/dist/m365/spo/commands/web/web-roleinheritance-reset.js +2 -2
  217. package/dist/m365/teams/commands/app/app-install.js +32 -5
  218. package/dist/m365/teams/commands/app/app-remove.js +3 -3
  219. package/dist/m365/teams/commands/app/app-uninstall.js +2 -2
  220. package/dist/m365/teams/commands/app/app-update.js +2 -2
  221. package/dist/m365/teams/commands/cache/cache-remove.js +2 -2
  222. package/dist/m365/teams/commands/channel/channel-add.js +2 -2
  223. package/dist/m365/teams/commands/channel/channel-member-add.js +2 -2
  224. package/dist/m365/teams/commands/channel/channel-member-remove.js +3 -3
  225. package/dist/m365/teams/commands/channel/channel-member-set.js +2 -2
  226. package/dist/m365/teams/commands/channel/channel-remove.js +2 -2
  227. package/dist/m365/teams/commands/chat/chat-get.js +3 -3
  228. package/dist/m365/teams/commands/chat/chat-member-remove.js +2 -2
  229. package/dist/m365/teams/commands/chat/chat-message-send.js +3 -3
  230. package/dist/m365/teams/commands/meeting/meeting-attendancereport-list.js +2 -2
  231. package/dist/m365/teams/commands/tab/tab-remove.js +2 -2
  232. package/dist/m365/teams/commands/team/team-app-list.js +3 -3
  233. package/dist/m365/teams/commands/team/team-remove.js +2 -2
  234. package/dist/m365/teams/commands/user/user-app-list.js +2 -2
  235. package/dist/m365/teams/commands/user/user-app-remove.js +3 -3
  236. package/dist/m365/tenant/commands/people/people-profilecardproperty-remove.js +2 -2
  237. package/dist/m365/todo/commands/list/list-remove.js +2 -2
  238. package/dist/m365/todo/commands/task/task-get.js +2 -2
  239. package/dist/m365/todo/commands/task/task-list.js +2 -2
  240. package/dist/m365/todo/commands/task/task-remove.js +2 -2
  241. package/dist/m365/viva/commands/connections/connections-app-create.js +2 -2
  242. package/dist/m365/yammer/commands/group/group-user-remove.js +2 -2
  243. package/dist/m365/yammer/commands/message/message-like-set.js +2 -2
  244. package/dist/m365/yammer/commands/message/message-remove.js +2 -2
  245. package/dist/m365/yammer/commands/yammer-search.js +2 -2
  246. package/dist/telemetry.js +2 -2
  247. package/dist/utils/aadAdministrativeUnit.js +2 -2
  248. package/dist/utils/aadGroup.js +3 -3
  249. package/dist/utils/prompt.js +4 -7
  250. package/docs/docs/cmd/aad/administrativeunit/administrativeunit-member-list.mdx +312 -0
  251. package/docs/docs/cmd/teams/app/app-install.mdx +11 -2
  252. package/package.json +1 -1
  253. package/dist/cli/Cli.js +0 -858
@@ -0,0 +1,880 @@
1
+ import Configstore from 'configstore';
2
+ import fs from 'fs';
3
+ import minimist from 'minimist';
4
+ import { createRequire } from 'module';
5
+ import ora from 'ora';
6
+ import os from 'os';
7
+ import path from 'path';
8
+ import { fileURLToPath, pathToFileURL } from 'url';
9
+ import Command, { CommandError } from '../Command.js';
10
+ import config from '../config.js';
11
+ import request from '../request.js';
12
+ import { settingsNames } from '../settingsNames.js';
13
+ import { telemetry } from '../telemetry.js';
14
+ import { app } from '../utils/app.js';
15
+ import { formatting } from '../utils/formatting.js';
16
+ import { md } from '../utils/md.js';
17
+ import { validation } from '../utils/validation.js';
18
+ import { prompt } from '../utils/prompt.js';
19
+ import { timings } from './timings.js';
20
+ const require = createRequire(import.meta.url);
21
+ const __dirname = fileURLToPath(new URL('.', import.meta.url));
22
+ let _config;
23
+ // we assign it through exported function to support mocking
24
+ // eslint-disable-next-line prefer-const
25
+ let spinner = ora();
26
+ const commands = [];
27
+ /**
28
+ * Command to execute
29
+ */
30
+ let commandToExecute;
31
+ /**
32
+ * Name of the command specified through args
33
+ */
34
+ let currentCommandName;
35
+ let optionsFromArgs;
36
+ const defaultHelpMode = 'options';
37
+ const helpModes = ['options', 'examples', 'remarks', 'response', 'full'];
38
+ function getConfig() {
39
+ if (!_config) {
40
+ _config = new Configstore(config.configstoreName);
41
+ }
42
+ return _config;
43
+ }
44
+ function getSettingWithDefaultValue(settingName, defaultValue) {
45
+ const configuredValue = cli.getConfig().get(settingName);
46
+ if (typeof configuredValue === 'undefined') {
47
+ return defaultValue;
48
+ }
49
+ else {
50
+ return configuredValue;
51
+ }
52
+ }
53
+ async function execute(rawArgs) {
54
+ const start = process.hrtime.bigint();
55
+ // for completion commands we also need information about commands' options
56
+ const loadAllCommandInfo = rawArgs.indexOf('completion') > -1;
57
+ cli.loadAllCommandsInfo(loadAllCommandInfo);
58
+ // check if help for a specific command has been requested using the
59
+ // 'm365 help xyz' format. If so, remove 'help' from the array of words
60
+ // to use lazy loading commands but keep track of the fact that help should
61
+ // be displayed
62
+ let showHelp = false;
63
+ if (rawArgs.length > 0 && rawArgs[0] === 'help') {
64
+ showHelp = true;
65
+ rawArgs.shift();
66
+ }
67
+ // parse args to see if a command has been specified
68
+ const parsedArgs = minimist(rawArgs);
69
+ // load command
70
+ await cli.loadCommandFromArgs(parsedArgs._);
71
+ if (cli.commandToExecute) {
72
+ // we have found a command to execute. Parse args again taking into
73
+ // account short and long options, option types and whether the command
74
+ // supports known and unknown options or not
75
+ try {
76
+ cli.optionsFromArgs = {
77
+ options: getCommandOptionsFromArgs(rawArgs, cli.commandToExecute)
78
+ };
79
+ }
80
+ catch (e) {
81
+ const optionsWithoutShorts = removeShortOptions({ options: parsedArgs });
82
+ return cli.closeWithError(e.message, optionsWithoutShorts, false);
83
+ }
84
+ }
85
+ else {
86
+ // we need this to properly support displaying commands
87
+ // from the current group
88
+ cli.optionsFromArgs = {
89
+ options: parsedArgs
90
+ };
91
+ }
92
+ // show help if no match found, help explicitly requested or
93
+ // no command specified
94
+ if (!cli.commandToExecute ||
95
+ showHelp ||
96
+ parsedArgs.h ||
97
+ parsedArgs.help) {
98
+ if (parsedArgs.output !== 'none') {
99
+ printHelp(await getHelpMode(parsedArgs));
100
+ }
101
+ return Promise.resolve();
102
+ }
103
+ delete cli.optionsFromArgs.options._;
104
+ delete cli.optionsFromArgs.options['--'];
105
+ try {
106
+ // replace values staring with @ with file contents
107
+ loadOptionValuesFromFiles(cli.optionsFromArgs);
108
+ }
109
+ catch (e) {
110
+ return cli.closeWithError(e, cli.optionsFromArgs);
111
+ }
112
+ const startProcessing = process.hrtime.bigint();
113
+ try {
114
+ // process options before passing them on to validation stage
115
+ const contextCommandOptions = await loadOptionsFromContext(cli.commandToExecute.options, cli.optionsFromArgs.options.debug);
116
+ cli.optionsFromArgs.options = { ...contextCommandOptions, ...cli.optionsFromArgs.options };
117
+ await cli.commandToExecute.command.processOptions(cli.optionsFromArgs.options);
118
+ const endProcessing = process.hrtime.bigint();
119
+ timings.options.push(Number(endProcessing - startProcessing));
120
+ }
121
+ catch (e) {
122
+ const endProcessing = process.hrtime.bigint();
123
+ timings.options.push(Number(endProcessing - startProcessing));
124
+ return cli.closeWithError(e.message, cli.optionsFromArgs, false);
125
+ }
126
+ // if output not specified, set the configured output value (if any)
127
+ if (cli.optionsFromArgs.options.output === undefined) {
128
+ cli.optionsFromArgs.options.output = cli.getSettingWithDefaultValue(settingsNames.output, 'json');
129
+ }
130
+ const startValidation = process.hrtime.bigint();
131
+ const validationResult = await cli.commandToExecute.command.validate(cli.optionsFromArgs, cli.commandToExecute);
132
+ const endValidation = process.hrtime.bigint();
133
+ timings.validation.push(Number(endValidation - startValidation));
134
+ if (validationResult !== true) {
135
+ return cli.closeWithError(validationResult, cli.optionsFromArgs, true);
136
+ }
137
+ const end = process.hrtime.bigint();
138
+ timings.core.push(Number(end - start));
139
+ try {
140
+ await cli.executeCommand(cli.commandToExecute.command, cli.optionsFromArgs);
141
+ const endTotal = process.hrtime.bigint();
142
+ timings.total.push(Number(endTotal - start));
143
+ printTimings(rawArgs);
144
+ process.exit(0);
145
+ }
146
+ catch (err) {
147
+ const endTotal = process.hrtime.bigint();
148
+ timings.total.push(Number(endTotal - start));
149
+ printTimings(rawArgs);
150
+ await cli.closeWithError(err, cli.optionsFromArgs);
151
+ /* c8 ignore next */
152
+ }
153
+ }
154
+ function printTimings(rawArgs) {
155
+ if (rawArgs.some(arg => arg === '--debug')) {
156
+ cli.error('');
157
+ cli.error('Timings:');
158
+ Object.getOwnPropertyNames(timings).forEach(key => {
159
+ cli.error(`${key}: ${timings[key].reduce((a, b) => a + b, 0) / 1e6}ms`);
160
+ });
161
+ }
162
+ }
163
+ async function executeCommand(command, args) {
164
+ const logger = {
165
+ log: async (message) => {
166
+ if (args.options.output !== 'none') {
167
+ const output = await cli.formatOutput(command, message, args.options);
168
+ cli.log(output);
169
+ }
170
+ },
171
+ logRaw: async (message) => {
172
+ if (args.options.output !== 'none') {
173
+ cli.log(message);
174
+ }
175
+ },
176
+ logToStderr: async (message) => {
177
+ if (args.options.output !== 'none') {
178
+ cli.error(message);
179
+ }
180
+ }
181
+ };
182
+ if (args.options.debug) {
183
+ await logger.logToStderr(`Executing command ${command.name} with options ${JSON.stringify(args)}`);
184
+ }
185
+ // store the current command name, if any and set the name to the name of
186
+ // the command to execute
187
+ const parentCommandName = cli.currentCommandName;
188
+ cli.currentCommandName = command.getCommandName(cli.currentCommandName);
189
+ const showSpinner = cli.getSettingWithDefaultValue(settingsNames.showSpinner, true) && args.options.output !== 'none';
190
+ // don't show spinner if running tests
191
+ /* c8 ignore next 3 */
192
+ if (showSpinner && typeof global.it === 'undefined') {
193
+ cli.spinner.start();
194
+ }
195
+ const startCommand = process.hrtime.bigint();
196
+ try {
197
+ await command.action(logger, args);
198
+ if (args.options.debug || args.options.verbose) {
199
+ const chalk = (await import('chalk')).default;
200
+ await logger.logToStderr(chalk.green('DONE'));
201
+ }
202
+ }
203
+ finally {
204
+ // restore the original command name
205
+ cli.currentCommandName = parentCommandName;
206
+ /* c8 ignore next 3 */
207
+ if (cli.spinner.isSpinning) {
208
+ cli.spinner.stop();
209
+ }
210
+ const endCommand = process.hrtime.bigint();
211
+ timings.command.push(Number(endCommand - startCommand));
212
+ }
213
+ }
214
+ async function executeCommandWithOutput(command, args, listener) {
215
+ const log = [];
216
+ const logErr = [];
217
+ const logger = {
218
+ log: async (message) => {
219
+ const formattedMessage = await cli.formatOutput(command, message, args.options);
220
+ if (listener && listener.stdout) {
221
+ listener.stdout(formattedMessage);
222
+ }
223
+ log.push(formattedMessage);
224
+ },
225
+ logRaw: async (message) => {
226
+ const formattedMessage = await cli.formatOutput(command, message, args.options);
227
+ if (listener && listener.stdout) {
228
+ listener.stdout(formattedMessage);
229
+ }
230
+ log.push(formattedMessage);
231
+ },
232
+ logToStderr: async (message) => {
233
+ if (listener && listener.stderr) {
234
+ listener.stderr(message);
235
+ }
236
+ logErr.push(message);
237
+ }
238
+ };
239
+ if (args.options.debug && args.options.output !== 'none') {
240
+ const message = `Executing command ${command.name} with options ${JSON.stringify(args)}`;
241
+ if (listener && listener.stderr) {
242
+ listener.stderr(message);
243
+ }
244
+ logErr.push(message);
245
+ }
246
+ // store the current command name, if any and set the name to the name of
247
+ // the command to execute
248
+ const parentCommandName = cli.currentCommandName;
249
+ cli.currentCommandName = command.getCommandName();
250
+ // store the current logger if any
251
+ const currentLogger = request.logger;
252
+ try {
253
+ await command.action(logger, args);
254
+ return ({
255
+ stdout: log.join(os.EOL),
256
+ stderr: logErr.join(os.EOL)
257
+ });
258
+ }
259
+ catch (err) {
260
+ // restoring the command and logger is done here instead of in a 'finally' because there were issues with the code coverage tool
261
+ // restore the original command name
262
+ cli.currentCommandName = parentCommandName;
263
+ // restore the original logger
264
+ request.logger = currentLogger;
265
+ throw {
266
+ error: err,
267
+ stderr: logErr.join(os.EOL)
268
+ };
269
+ }
270
+ /* c8 ignore next */
271
+ finally {
272
+ // restore the original command name
273
+ cli.currentCommandName = parentCommandName;
274
+ // restore the original logger
275
+ request.logger = currentLogger;
276
+ }
277
+ }
278
+ function loadAllCommandsInfo(loadFull = false) {
279
+ const commandsInfoFileName = loadFull ? 'allCommandsFull.json' : 'allCommands.json';
280
+ cli.commands = require(path.join(__dirname, '..', '..', commandsInfoFileName));
281
+ }
282
+ /**
283
+ * Loads command files into CLI based on the specified arguments.
284
+ *
285
+ * @param commandNameWords Array of words specified as args
286
+ */
287
+ async function loadCommandFromArgs(commandNameWords) {
288
+ if (commandNameWords.length === 0) {
289
+ return;
290
+ }
291
+ cli.currentCommandName = commandNameWords.join(' ');
292
+ const commandFilePath = cli.commands
293
+ .find(c => c.name === cli.currentCommandName ||
294
+ c.aliases?.find(a => a === cli.currentCommandName))?.file ?? '';
295
+ if (commandFilePath) {
296
+ await cli.loadCommandFromFile(commandFilePath);
297
+ }
298
+ }
299
+ async function loadOptionsFromContext(commandOptions, debug) {
300
+ const filePath = '.m365rc.json';
301
+ let m365rc = {};
302
+ if (!fs.existsSync(filePath)) {
303
+ return;
304
+ }
305
+ if (debug) {
306
+ await cli.error('found .m365rc.json file');
307
+ }
308
+ try {
309
+ const fileContents = fs.readFileSync(filePath, 'utf8');
310
+ if (fileContents) {
311
+ m365rc = JSON.parse(fileContents);
312
+ }
313
+ }
314
+ catch (e) {
315
+ await cli.closeWithError(`Error parsing ${filePath}`, { options: {} });
316
+ /* c8 ignore next */
317
+ }
318
+ if (!m365rc.context) {
319
+ return;
320
+ }
321
+ if (debug) {
322
+ await cli.error('found context in .m365rc.json file');
323
+ }
324
+ const context = m365rc.context;
325
+ const foundOptions = {};
326
+ await commandOptions.forEach(async (option) => {
327
+ if (context[option.name]) {
328
+ foundOptions[option.name] = context[option.name];
329
+ if (debug) {
330
+ await cli.error(`returning ${option.name} option from context`);
331
+ }
332
+ }
333
+ });
334
+ return foundOptions;
335
+ }
336
+ /**
337
+ * Loads command from the specified file into CLI. If can't find the file
338
+ * or the file doesn't contain a command, loads all available commands.
339
+ *
340
+ * @param commandFilePathUrl File path of the file with command to load
341
+ */
342
+ async function loadCommandFromFile(commandFileUrl) {
343
+ const commandsFolder = path.join(__dirname, '../m365');
344
+ const filePath = path.join(commandsFolder, commandFileUrl);
345
+ if (!fs.existsSync(filePath)) {
346
+ // reset command name
347
+ cli.currentCommandName = undefined;
348
+ return;
349
+ }
350
+ try {
351
+ const command = await import(pathToFileURL(filePath).toString());
352
+ if (command.default instanceof Command) {
353
+ const commandInfo = cli.commands.find(c => c.file === commandFileUrl);
354
+ cli.commandToExecute = cli.getCommandInfo(command.default, commandFileUrl, commandInfo?.help);
355
+ }
356
+ }
357
+ catch { }
358
+ }
359
+ function getCommandInfo(command, filePath = '', helpFilePath = '') {
360
+ return {
361
+ aliases: command.alias(),
362
+ name: command.name,
363
+ description: command.description,
364
+ command: command,
365
+ options: getCommandOptions(command),
366
+ defaultProperties: command.defaultProperties(),
367
+ file: filePath,
368
+ help: helpFilePath
369
+ };
370
+ }
371
+ function getCommandOptions(command) {
372
+ const options = [];
373
+ command.options.forEach(option => {
374
+ const required = option.option.indexOf('<') > -1;
375
+ const optionArgs = option.option.split(/[ ,|]+/);
376
+ let short;
377
+ let long;
378
+ let name = '';
379
+ optionArgs.forEach(o => {
380
+ if (o.startsWith('--')) {
381
+ long = o.replace('--', '');
382
+ name = long;
383
+ }
384
+ else if (o.startsWith('-')) {
385
+ short = o.replace('-', '');
386
+ name = short;
387
+ }
388
+ });
389
+ options.push({
390
+ autocomplete: option.autocomplete,
391
+ long: long,
392
+ name: name,
393
+ required: required,
394
+ short: short
395
+ });
396
+ });
397
+ return options;
398
+ }
399
+ function getCommandOptionsFromArgs(args, commandInfo) {
400
+ const minimistOptions = {
401
+ alias: {}
402
+ };
403
+ let argsToParse = args;
404
+ if (commandInfo) {
405
+ const commandTypes = commandInfo.command.types;
406
+ if (commandTypes) {
407
+ minimistOptions.string = commandTypes.string;
408
+ // minimist will parse unused boolean options to 'false' (unused options => options that are not included in the args)
409
+ // But in the CLI booleans are nullable. They can can be true, false or undefined.
410
+ // For this reason we only pass boolean types that are actually used as arg.
411
+ minimistOptions.boolean = commandTypes.boolean.filter(optionName => args.some(arg => `--${optionName}` === arg || `-${optionName}` === arg));
412
+ }
413
+ minimistOptions.alias = {};
414
+ commandInfo.options.forEach(option => {
415
+ if (option.short && option.long) {
416
+ minimistOptions.alias[option.short] = option.long;
417
+ }
418
+ });
419
+ argsToParse = getRewrittenArgs(args, commandTypes);
420
+ }
421
+ return minimist(argsToParse, minimistOptions);
422
+ }
423
+ /**
424
+ * Rewrites arguments (if necessary) before passing them into minimist.
425
+ * Currently only boolean values are checked and fixed.
426
+ * Args are only checked and rewritten if the option has been added to the 'types.boolean' array.
427
+ */
428
+ function getRewrittenArgs(args, commandTypes) {
429
+ const booleanTypes = commandTypes.boolean;
430
+ if (booleanTypes.length === 0) {
431
+ return args;
432
+ }
433
+ return args.map((arg, index, array) => {
434
+ if (arg.startsWith('-') || index === 0) {
435
+ return arg;
436
+ }
437
+ // This line checks if the current arg is a value that belongs to a boolean option.
438
+ if (booleanTypes.some(t => `--${t}` === array[index - 1] || `-${t}` === array[index - 1])) {
439
+ const rewrittenBoolean = formatting.rewriteBooleanValue(arg);
440
+ if (!validation.isValidBoolean(rewrittenBoolean)) {
441
+ const optionName = array[index - 1];
442
+ throw new Error(`The value '${arg}' for option '${optionName}' is not a valid boolean`);
443
+ }
444
+ return rewrittenBoolean;
445
+ }
446
+ return arg;
447
+ });
448
+ }
449
+ async function formatOutput(command, logStatement, options) {
450
+ if (logStatement instanceof Date) {
451
+ return logStatement.toString();
452
+ }
453
+ let logStatementType = typeof logStatement;
454
+ if (logStatementType === 'undefined') {
455
+ return logStatement;
456
+ }
457
+ // we need to get the list of object's properties to see if the specified
458
+ // JMESPath query (if any) filters object's properties or not. We need to
459
+ // know this in order to decide if we should use default command's
460
+ // properties or custom ones from JMESPath
461
+ const originalObject = Array.isArray(logStatement) ? getFirstNonUndefinedArrayItem(logStatement) : logStatement;
462
+ const originalProperties = originalObject && typeof originalObject !== 'string' ? Object.getOwnPropertyNames(originalObject) : [];
463
+ if (options.query &&
464
+ !options.help) {
465
+ const jmespath = await import('jmespath');
466
+ try {
467
+ logStatement = jmespath.search(logStatement, options.query);
468
+ }
469
+ catch (e) {
470
+ const message = `JMESPath query error. ${e.message}. See https://jmespath.org/specification.html for more information`;
471
+ await cli.closeWithError(message, { options }, false);
472
+ /* c8 ignore next */
473
+ }
474
+ // we need to update the statement type in case the JMESPath query
475
+ // returns an object of different shape than the original message to log
476
+ // #2095
477
+ logStatementType = typeof logStatement;
478
+ }
479
+ if (!options.output || options.output === 'json') {
480
+ return command.getJsonOutput(logStatement);
481
+ }
482
+ if (logStatement instanceof CommandError) {
483
+ const chalk = (await import('chalk')).default;
484
+ return chalk.red(`Error: ${logStatement.message}`);
485
+ }
486
+ let arrayType = '';
487
+ if (!Array.isArray(logStatement)) {
488
+ logStatement = [logStatement];
489
+ arrayType = logStatementType;
490
+ }
491
+ else {
492
+ for (let i = 0; i < logStatement.length; i++) {
493
+ if (Array.isArray(logStatement[i])) {
494
+ arrayType = 'array';
495
+ break;
496
+ }
497
+ const t = typeof logStatement[i];
498
+ if (t !== 'undefined') {
499
+ arrayType = t;
500
+ break;
501
+ }
502
+ }
503
+ }
504
+ if (arrayType !== 'object') {
505
+ return logStatement.join(os.EOL);
506
+ }
507
+ // if output type has been set to 'text', process the retrieved
508
+ // data so that returned objects contain only default properties specified
509
+ // on the current command. If there is no current command or the
510
+ // command doesn't specify default properties, return original data
511
+ if (cli.shouldTrimOutput(options.output)) {
512
+ const currentCommand = cli.commandToExecute;
513
+ if (arrayType === 'object' &&
514
+ currentCommand && currentCommand.defaultProperties) {
515
+ // the log statement contains the same properties as the original object
516
+ // so it can be filtered following the default properties specified on
517
+ // the command
518
+ if (JSON.stringify(originalProperties) === JSON.stringify(Object.getOwnPropertyNames(logStatement[0]))) {
519
+ // in some cases we return properties wrapped in `value` array
520
+ // returned by the API. We'll remove it in the future, but for now
521
+ // we'll use a workaround to drop the `value` array here
522
+ if (logStatement[0].value &&
523
+ Array.isArray(logStatement[0].value)) {
524
+ logStatement = logStatement[0].value;
525
+ }
526
+ logStatement = logStatement.map((s) => formatting.filterObject(s, currentCommand.defaultProperties));
527
+ }
528
+ }
529
+ }
530
+ switch (options.output) {
531
+ case 'csv':
532
+ return command.getCsvOutput(logStatement, options);
533
+ case 'md':
534
+ return command.getMdOutput(logStatement, command, options);
535
+ default:
536
+ return command.getTextOutput(logStatement);
537
+ }
538
+ }
539
+ function getFirstNonUndefinedArrayItem(arr) {
540
+ for (let i = 0; i < arr.length; i++) {
541
+ const a = arr[i];
542
+ if (typeof a !== 'undefined') {
543
+ return a;
544
+ }
545
+ }
546
+ return undefined;
547
+ }
548
+ function printHelp(helpMode, exitCode = 0) {
549
+ const properties = {};
550
+ if (cli.commandToExecute) {
551
+ properties.command = cli.commandToExecute.name;
552
+ printCommandHelp(helpMode);
553
+ }
554
+ else {
555
+ cli.log();
556
+ cli.log(`CLI for Microsoft 365 v${app.packageJson().version}`);
557
+ cli.log(`${app.packageJson().description} `);
558
+ cli.log();
559
+ properties.command = 'commandList';
560
+ cli.printAvailableCommands();
561
+ }
562
+ telemetry.trackEvent('help', properties);
563
+ process.exit(exitCode);
564
+ }
565
+ function printCommandHelp(helpMode) {
566
+ const docsRootDir = path.join(__dirname, '..', '..', 'docs');
567
+ const helpFilePath = path.join(docsRootDir, 'docs', 'cmd', cli.commandToExecute.help);
568
+ if (fs.existsSync(helpFilePath)) {
569
+ let helpContents = fs.readFileSync(helpFilePath, 'utf8');
570
+ helpContents = getHelpSection(helpMode, helpContents);
571
+ helpContents = md.md2plain(helpContents, docsRootDir);
572
+ cli.log();
573
+ cli.log(helpContents);
574
+ }
575
+ }
576
+ async function getHelpMode(options) {
577
+ const { h, help } = options;
578
+ if (!h && !help) {
579
+ return cli.getSettingWithDefaultValue(settingsNames.helpMode, defaultHelpMode);
580
+ }
581
+ // user passed -h or --help, let's see if they passed a specific mode
582
+ // or requested the default
583
+ const helpMode = h ?? help;
584
+ if (typeof helpMode === 'boolean' || typeof helpMode !== 'string') {
585
+ // requested default mode or passed a number, let's use default
586
+ return cli.getSettingWithDefaultValue(settingsNames.helpMode, defaultHelpMode);
587
+ }
588
+ else {
589
+ const lowerCaseHelpMode = helpMode.toLowerCase();
590
+ if (cli.helpModes.indexOf(lowerCaseHelpMode) < 0) {
591
+ await cli.closeWithError(`Unknown help mode ${helpMode}. Allowed values are ${cli.helpModes.join(', ')} `, { options }, false);
592
+ /* c8 ignore next 2 */
593
+ return ''; // noop
594
+ }
595
+ else {
596
+ return lowerCaseHelpMode;
597
+ }
598
+ }
599
+ }
600
+ function getHelpSection(helpMode, helpContents) {
601
+ if (helpMode === 'full') {
602
+ return helpContents;
603
+ }
604
+ // options is the first section, so get help up to options
605
+ const titleAndUsage = helpContents.substring(0, helpContents.indexOf('## Options'));
606
+ // find the requested section
607
+ const sectionLines = [];
608
+ const sectionName = helpMode[0].toUpperCase() + helpMode.substring(1);
609
+ const lines = helpContents.split('\n');
610
+ for (let i = 0; i < lines.length; i++) {
611
+ const line = lines[i];
612
+ if (line.indexOf(`## ${sectionName}`) === 0) {
613
+ sectionLines.push(line);
614
+ }
615
+ else if (sectionLines.length > 0) {
616
+ if (line.indexOf('## ') === 0) {
617
+ // we've reached the next section, stop
618
+ break;
619
+ }
620
+ else {
621
+ sectionLines.push(line);
622
+ }
623
+ }
624
+ }
625
+ return titleAndUsage + sectionLines.join('\n');
626
+ }
627
+ function printAvailableCommands() {
628
+ // commands that match the current group
629
+ const commandsToPrint = {};
630
+ // sub-commands in the current group
631
+ const commandGroupsToPrint = {};
632
+ // current command group, eg. 'spo', 'spo site'
633
+ let currentGroup = '';
634
+ const addToList = (commandName, command) => {
635
+ const pos = commandName.indexOf(' ', currentGroup.length + 1);
636
+ if (pos === -1) {
637
+ commandsToPrint[commandName] = command;
638
+ }
639
+ else {
640
+ const subCommandsGroup = commandName.substr(0, pos);
641
+ if (!commandGroupsToPrint[subCommandsGroup]) {
642
+ commandGroupsToPrint[subCommandsGroup] = 0;
643
+ }
644
+ commandGroupsToPrint[subCommandsGroup]++;
645
+ }
646
+ };
647
+ // get current command group
648
+ if (cli.optionsFromArgs &&
649
+ cli.optionsFromArgs.options &&
650
+ cli.optionsFromArgs.options._ &&
651
+ cli.optionsFromArgs.options._.length > 0) {
652
+ currentGroup = cli.optionsFromArgs.options._.join(' ');
653
+ if (currentGroup) {
654
+ currentGroup += ' ';
655
+ }
656
+ }
657
+ const getCommandsForGroup = () => {
658
+ for (let i = 0; i < cli.commands.length; i++) {
659
+ const command = cli.commands[i];
660
+ if (command.name.startsWith(currentGroup)) {
661
+ addToList(command.name, command);
662
+ }
663
+ if (command.aliases) {
664
+ for (let j = 0; j < command.aliases.length; j++) {
665
+ const alias = command.aliases[j];
666
+ if (alias.startsWith(currentGroup)) {
667
+ addToList(alias, command);
668
+ }
669
+ }
670
+ }
671
+ }
672
+ };
673
+ getCommandsForGroup();
674
+ if (Object.keys(commandsToPrint).length === 0 &&
675
+ Object.keys(commandGroupsToPrint).length === 0) {
676
+ // specified string didn't match any commands. Reset group and try again
677
+ currentGroup = '';
678
+ getCommandsForGroup();
679
+ }
680
+ const namesOfCommandsToPrint = Object.keys(commandsToPrint);
681
+ if (namesOfCommandsToPrint.length > 0) {
682
+ // determine the length of the longest command name to pad strings + ' [options]'
683
+ const maxLength = Math.max(...namesOfCommandsToPrint.map(s => s.length)) + 10;
684
+ cli.log(`Commands:`);
685
+ cli.log();
686
+ const sortedCommandNamesToPrint = Object.getOwnPropertyNames(commandsToPrint).sort();
687
+ sortedCommandNamesToPrint.forEach(commandName => {
688
+ cli.log(` ${`${commandName} [options]`.padEnd(maxLength, ' ')} ${commandsToPrint[commandName].description}`);
689
+ });
690
+ }
691
+ const namesOfCommandGroupsToPrint = Object.keys(commandGroupsToPrint);
692
+ if (namesOfCommandGroupsToPrint.length > 0) {
693
+ if (namesOfCommandsToPrint.length > 0) {
694
+ cli.log();
695
+ }
696
+ // determine the longest command group name to pad strings + ' *'
697
+ const maxLength = Math.max(...namesOfCommandGroupsToPrint.map(s => s.length)) + 2;
698
+ cli.log(`Commands groups:`);
699
+ cli.log();
700
+ // sort commands groups (because of aliased commands)
701
+ const sortedCommandGroupsToPrint = Object
702
+ .keys(commandGroupsToPrint)
703
+ .sort()
704
+ .reduce((object, key) => {
705
+ object[key] = commandGroupsToPrint[key];
706
+ return object;
707
+ }, {});
708
+ for (const commandGroup in sortedCommandGroupsToPrint) {
709
+ cli.log(` ${`${commandGroup} *`.padEnd(maxLength, ' ')} ${commandGroupsToPrint[commandGroup]} command${commandGroupsToPrint[commandGroup] === 1 ? '' : 's'}`);
710
+ }
711
+ }
712
+ cli.log();
713
+ }
714
+ async function closeWithError(error, args, showHelpIfEnabled = false) {
715
+ let exitCode = 1;
716
+ if (args.options.output === 'none') {
717
+ return process.exit(exitCode);
718
+ }
719
+ const chalk = (await import('chalk')).default;
720
+ let errorMessage = error instanceof CommandError ? error.message : error;
721
+ if ((!args.options.output || args.options.output === 'json') &&
722
+ !cli.getSettingWithDefaultValue(settingsNames.printErrorsAsPlainText, true)) {
723
+ errorMessage = JSON.stringify({ error: errorMessage });
724
+ }
725
+ else {
726
+ errorMessage = chalk.red(`Error: ${errorMessage}`);
727
+ }
728
+ if (error instanceof CommandError && error.code) {
729
+ exitCode = error.code;
730
+ }
731
+ await cli.error(errorMessage);
732
+ if (showHelpIfEnabled &&
733
+ await cli.getSettingWithDefaultValue(settingsNames.showHelpOnFailure, showHelpIfEnabled)) {
734
+ printHelp(await getHelpMode(args.options), exitCode);
735
+ }
736
+ else {
737
+ process.exit(exitCode);
738
+ }
739
+ // will never be run. Required for testing where we're stubbing process.exit
740
+ /* c8 ignore next */
741
+ throw new Error(errorMessage);
742
+ /* c8 ignore next */
743
+ }
744
+ function log(message, ...optionalParams) {
745
+ const spinnerSpinning = cli.spinner.isSpinning;
746
+ /* c8 ignore next 3 */
747
+ if (spinnerSpinning) {
748
+ cli.spinner.stop();
749
+ }
750
+ if (message) {
751
+ console.log(message, ...optionalParams);
752
+ }
753
+ else {
754
+ console.log();
755
+ }
756
+ // Restart the spinner if it was running before the log
757
+ /* c8 ignore next 3 */
758
+ if (spinnerSpinning) {
759
+ cli.spinner.start();
760
+ }
761
+ }
762
+ async function error(message, ...optionalParams) {
763
+ const spinnerSpinning = cli.spinner.isSpinning;
764
+ /* c8 ignore next 3 */
765
+ if (spinnerSpinning) {
766
+ cli.spinner.stop();
767
+ }
768
+ const errorOutput = cli.getSettingWithDefaultValue(settingsNames.errorOutput, 'stderr');
769
+ if (errorOutput === 'stdout') {
770
+ console.log(message, ...optionalParams);
771
+ }
772
+ else {
773
+ console.error(message, ...optionalParams);
774
+ }
775
+ // Restart the spinner if it was running before the log
776
+ /* c8 ignore next 3 */
777
+ if (spinnerSpinning) {
778
+ cli.spinner.start();
779
+ }
780
+ }
781
+ async function promptForSelection(config) {
782
+ const spinnerSpinning = cli.spinner.isSpinning;
783
+ /* c8 ignore next 3 */
784
+ if (spinnerSpinning) {
785
+ cli.spinner.stop();
786
+ }
787
+ const answer = await prompt.forSelection(config);
788
+ cli.error('');
789
+ // Restart the spinner if it was running before the prompt
790
+ /* c8 ignore next 3 */
791
+ if (spinnerSpinning) {
792
+ cli.spinner.start();
793
+ }
794
+ return answer;
795
+ }
796
+ async function promptForConfirmation(config) {
797
+ const spinnerSpinning = cli.spinner.isSpinning;
798
+ /* c8 ignore next 3 */
799
+ if (spinnerSpinning) {
800
+ cli.spinner.stop();
801
+ }
802
+ const answer = await prompt.forConfirmation(config);
803
+ cli.error('');
804
+ // Restart the spinner if it was running before the prompt
805
+ /* c8 ignore next 3 */
806
+ if (spinnerSpinning) {
807
+ cli.spinner.start();
808
+ }
809
+ return answer;
810
+ }
811
+ async function handleMultipleResultsFound(message, values) {
812
+ const prompt = cli.getSettingWithDefaultValue(settingsNames.prompt, true);
813
+ if (!prompt) {
814
+ throw new Error(`${message} Found: ${Object.keys(values).join(', ')}.`);
815
+ }
816
+ cli.error(`🌶️ ${message} `);
817
+ const choices = Object.keys(values).map((choice) => { return { name: choice, value: choice }; });
818
+ const response = await cli.promptForSelection({ message: `Please choose one:`, choices });
819
+ return values[response];
820
+ }
821
+ function removeShortOptions(args) {
822
+ const filteredArgs = JSON.parse(JSON.stringify(args));
823
+ const optionsToRemove = Object.getOwnPropertyNames(args.options)
824
+ .filter(option => option.length === 1 || option === '--');
825
+ optionsToRemove.forEach(option => delete filteredArgs.options[option]);
826
+ return filteredArgs;
827
+ }
828
+ function loadOptionValuesFromFiles(args) {
829
+ const optionNames = Object.getOwnPropertyNames(args.options);
830
+ optionNames.forEach(option => {
831
+ const value = args.options[option];
832
+ if (!value ||
833
+ typeof value !== 'string' ||
834
+ !value.startsWith('@')) {
835
+ return;
836
+ }
837
+ const filePath = value.substr(1);
838
+ // if the file doesn't exist, leave as-is, if it exists replace with
839
+ // contents from the file
840
+ if (fs.existsSync(filePath)) {
841
+ args.options[option] = fs.readFileSync(filePath, 'utf-8');
842
+ }
843
+ });
844
+ }
845
+ function shouldTrimOutput(output) {
846
+ return output === 'text';
847
+ }
848
+ export const cli = {
849
+ closeWithError,
850
+ commands,
851
+ commandToExecute,
852
+ getConfig,
853
+ currentCommandName,
854
+ error,
855
+ execute,
856
+ executeCommand,
857
+ executeCommandWithOutput,
858
+ formatOutput,
859
+ getCommandInfo,
860
+ getSettingWithDefaultValue,
861
+ handleMultipleResultsFound,
862
+ helpModes,
863
+ loadAllCommandsInfo,
864
+ loadCommandFromArgs,
865
+ loadCommandFromFile,
866
+ log,
867
+ optionsFromArgs,
868
+ printAvailableCommands,
869
+ promptForConfirmation,
870
+ promptForSelection,
871
+ shouldTrimOutput,
872
+ spinner
873
+ };
874
+ const spinnerOptions = {
875
+ text: 'Running command...',
876
+ /* c8 ignore next 1 */
877
+ stream: cli.getSettingWithDefaultValue('errorOutput', 'stderr') === 'stderr' ? process.stderr : process.stdout
878
+ };
879
+ cli.spinner = ora(spinnerOptions);
880
+ //# sourceMappingURL=cli.js.map