@microsoft/managed-apps-cli 0.9.2 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (188) hide show
  1. package/README.md +18 -342
  2. package/dist/ArgumentProvider.d.ts.map +1 -1
  3. package/dist/ArgumentProvider.js +8 -1
  4. package/dist/ArgumentProvider.js.map +1 -1
  5. package/dist/Authentication/NodeMsalAuthenticationProvider.js +20 -1
  6. package/dist/Authentication/NodeMsalAuthenticationProvider.js.map +1 -1
  7. package/dist/Cli.d.ts.map +1 -1
  8. package/dist/Cli.js +15 -3
  9. package/dist/Cli.js.map +1 -1
  10. package/dist/Constants/CommandRegistry.d.ts +1 -2
  11. package/dist/Constants/CommandRegistry.d.ts.map +1 -1
  12. package/dist/Constants/CommandRegistry.js +26 -45
  13. package/dist/Constants/CommandRegistry.js.map +1 -1
  14. package/dist/Constants/HelpStrings.d.ts +12 -8
  15. package/dist/Constants/HelpStrings.d.ts.map +1 -1
  16. package/dist/Constants/HelpStrings.js +98 -80
  17. package/dist/Constants/HelpStrings.js.map +1 -1
  18. package/dist/Errors/GitHubErrorMap.d.ts +43 -14
  19. package/dist/Errors/GitHubErrorMap.d.ts.map +1 -1
  20. package/dist/Errors/GitHubErrorMap.js +189 -147
  21. package/dist/Errors/GitHubErrorMap.js.map +1 -1
  22. package/dist/Logger/CliLogger.d.ts +2 -0
  23. package/dist/Logger/CliLogger.d.ts.map +1 -1
  24. package/dist/Logger/CliLogger.js +12 -3
  25. package/dist/Logger/CliLogger.js.map +1 -1
  26. package/dist/Logger/ConsoleWriter.d.ts +2 -0
  27. package/dist/Logger/ConsoleWriter.d.ts.map +1 -1
  28. package/dist/Logger/ConsoleWriter.js +17 -7
  29. package/dist/Logger/ConsoleWriter.js.map +1 -1
  30. package/dist/Types/Argument.types.d.ts +1 -0
  31. package/dist/Types/Argument.types.d.ts.map +1 -1
  32. package/dist/Types/Command.types.d.ts +6 -0
  33. package/dist/Types/Command.types.d.ts.map +1 -1
  34. package/dist/Types/Command.types.js +8 -0
  35. package/dist/Types/Command.types.js.map +1 -1
  36. package/dist/Utils/BuildVerbDescriptionTable.d.ts.map +1 -1
  37. package/dist/Utils/BuildVerbDescriptionTable.js +6 -2
  38. package/dist/Utils/BuildVerbDescriptionTable.js.map +1 -1
  39. package/dist/Utils/ConnectorIds.d.ts +12 -0
  40. package/dist/Utils/ConnectorIds.d.ts.map +1 -0
  41. package/dist/Utils/ConnectorIds.js +20 -0
  42. package/dist/Utils/ConnectorIds.js.map +1 -0
  43. package/dist/Utils/DcfRecovery.d.ts +7 -7
  44. package/dist/Utils/DcfRecovery.d.ts.map +1 -1
  45. package/dist/Utils/DcfRecovery.js +17 -37
  46. package/dist/Utils/DcfRecovery.js.map +1 -1
  47. package/dist/Utils/DownloadTemplate.d.ts +45 -0
  48. package/dist/Utils/DownloadTemplate.d.ts.map +1 -0
  49. package/dist/Utils/DownloadTemplate.js +161 -0
  50. package/dist/Utils/DownloadTemplate.js.map +1 -0
  51. package/dist/Utils/EnvVars.d.ts +1 -1
  52. package/dist/Utils/EnvVars.d.ts.map +1 -1
  53. package/dist/Utils/EnvVars.js.map +1 -1
  54. package/dist/Utils/EnvironmentRoutingUtils.d.ts +20 -1
  55. package/dist/Utils/EnvironmentRoutingUtils.d.ts.map +1 -1
  56. package/dist/Utils/EnvironmentRoutingUtils.js +78 -3
  57. package/dist/Utils/EnvironmentRoutingUtils.js.map +1 -1
  58. package/dist/Utils/GitErrorClassifier.d.ts +40 -0
  59. package/dist/Utils/GitErrorClassifier.d.ts.map +1 -0
  60. package/dist/Utils/GitErrorClassifier.js +120 -0
  61. package/dist/Utils/GitErrorClassifier.js.map +1 -0
  62. package/dist/Utils/GitRunner.d.ts +107 -0
  63. package/dist/Utils/GitRunner.d.ts.map +1 -0
  64. package/dist/Utils/GitRunner.js +89 -0
  65. package/dist/Utils/GitRunner.js.map +1 -0
  66. package/dist/Utils/GitUtils.d.ts +12 -0
  67. package/dist/Utils/GitUtils.d.ts.map +1 -1
  68. package/dist/Utils/GitUtils.js +83 -20
  69. package/dist/Utils/GitUtils.js.map +1 -1
  70. package/dist/Utils/GitVersionChecker.d.ts +38 -0
  71. package/dist/Utils/GitVersionChecker.d.ts.map +1 -0
  72. package/dist/Utils/GitVersionChecker.js +64 -0
  73. package/dist/Utils/GitVersionChecker.js.map +1 -0
  74. package/dist/Utils/MaafAppConfig.d.ts +22 -0
  75. package/dist/Utils/MaafAppConfig.d.ts.map +1 -0
  76. package/dist/Utils/MaafAppConfig.js +32 -0
  77. package/dist/Utils/MaafAppConfig.js.map +1 -0
  78. package/dist/Utils/NodeVersionChecker.d.ts +3 -6
  79. package/dist/Utils/NodeVersionChecker.d.ts.map +1 -1
  80. package/dist/Utils/NodeVersionChecker.js +9 -26
  81. package/dist/Utils/NodeVersionChecker.js.map +1 -1
  82. package/dist/Utils/Paging.d.ts +6 -0
  83. package/dist/Utils/Paging.d.ts.map +1 -1
  84. package/dist/Utils/Paging.js +36 -1
  85. package/dist/Utils/Paging.js.map +1 -1
  86. package/dist/Utils/PinCli.d.ts +28 -0
  87. package/dist/Utils/PinCli.d.ts.map +1 -0
  88. package/dist/Utils/PinCli.js +58 -0
  89. package/dist/Utils/PinCli.js.map +1 -0
  90. package/dist/Utils/RepoDetails.d.ts +29 -0
  91. package/dist/Utils/RepoDetails.d.ts.map +1 -0
  92. package/dist/Utils/RepoDetails.js +37 -0
  93. package/dist/Utils/RepoDetails.js.map +1 -0
  94. package/dist/Utils/RepoOption.d.ts +35 -0
  95. package/dist/Utils/RepoOption.d.ts.map +1 -0
  96. package/dist/Utils/RepoOption.js +36 -0
  97. package/dist/Utils/RepoOption.js.map +1 -0
  98. package/dist/Utils/ResolveCommand.d.ts.map +1 -1
  99. package/dist/Utils/ResolveCommand.js +6 -4
  100. package/dist/Utils/ResolveCommand.js.map +1 -1
  101. package/dist/Utils/Spinner.d.ts.map +1 -1
  102. package/dist/Utils/Spinner.js +3 -0
  103. package/dist/Utils/Spinner.js.map +1 -1
  104. package/dist/Verbs/AddAction.js +6 -6
  105. package/dist/Verbs/AddAction.js.map +1 -1
  106. package/dist/Verbs/AddConnector.d.ts +6 -4
  107. package/dist/Verbs/AddConnector.d.ts.map +1 -1
  108. package/dist/Verbs/AddConnector.js +54 -14
  109. package/dist/Verbs/AddConnector.js.map +1 -1
  110. package/dist/Verbs/AddConnectorFlows.d.ts +29 -16
  111. package/dist/Verbs/AddConnectorFlows.d.ts.map +1 -1
  112. package/dist/Verbs/AddConnectorFlows.js +73 -25
  113. package/dist/Verbs/AddConnectorFlows.js.map +1 -1
  114. package/dist/Verbs/AddDataSource.d.ts +3 -4
  115. package/dist/Verbs/AddDataSource.d.ts.map +1 -1
  116. package/dist/Verbs/AddDataSource.js +9 -20
  117. package/dist/Verbs/AddDataSource.js.map +1 -1
  118. package/dist/Verbs/AddTable.js +7 -7
  119. package/dist/Verbs/AddTable.js.map +1 -1
  120. package/dist/Verbs/AuthStatus.d.ts.map +1 -1
  121. package/dist/Verbs/AuthStatus.js +7 -4
  122. package/dist/Verbs/AuthStatus.js.map +1 -1
  123. package/dist/Verbs/BuildMaafApp.js +1 -1
  124. package/dist/Verbs/BuildMaafApp.js.map +1 -1
  125. package/dist/Verbs/ConnectorHelpers.d.ts +5 -4
  126. package/dist/Verbs/ConnectorHelpers.d.ts.map +1 -1
  127. package/dist/Verbs/ConnectorHelpers.js +14 -9
  128. package/dist/Verbs/ConnectorHelpers.js.map +1 -1
  129. package/dist/Verbs/CreateMaafApp.d.ts +25 -42
  130. package/dist/Verbs/CreateMaafApp.d.ts.map +1 -1
  131. package/dist/Verbs/CreateMaafApp.js +346 -268
  132. package/dist/Verbs/CreateMaafApp.js.map +1 -1
  133. package/dist/Verbs/DeployMaafApp.d.ts.map +1 -1
  134. package/dist/Verbs/DeployMaafApp.js +4 -4
  135. package/dist/Verbs/DeployMaafApp.js.map +1 -1
  136. package/dist/Verbs/Dev.js +1 -1
  137. package/dist/Verbs/Dev.js.map +1 -1
  138. package/dist/Verbs/GetMaafApp.d.ts.map +1 -1
  139. package/dist/Verbs/GetMaafApp.js +10 -0
  140. package/dist/Verbs/GetMaafApp.js.map +1 -1
  141. package/dist/Verbs/GetMaafBuildStatus.d.ts.map +1 -1
  142. package/dist/Verbs/GetMaafBuildStatus.js +52 -3
  143. package/dist/Verbs/GetMaafBuildStatus.js.map +1 -1
  144. package/dist/Verbs/GetSettings.js +1 -1
  145. package/dist/Verbs/GetSettings.js.map +1 -1
  146. package/dist/Verbs/Init.d.ts.map +1 -1
  147. package/dist/Verbs/Init.js +183 -60
  148. package/dist/Verbs/Init.js.map +1 -1
  149. package/dist/Verbs/ListConnectorActions.js +12 -9
  150. package/dist/Verbs/ListConnectorActions.js.map +1 -1
  151. package/dist/Verbs/ListConnectors.d.ts.map +1 -1
  152. package/dist/Verbs/ListConnectors.js +3 -2
  153. package/dist/Verbs/ListConnectors.js.map +1 -1
  154. package/dist/Verbs/ListMaafApps.js +3 -3
  155. package/dist/Verbs/ListMaafApps.js.map +1 -1
  156. package/dist/Verbs/MaafAppPermissions.d.ts.map +1 -1
  157. package/dist/Verbs/MaafAppPermissions.js +89 -17
  158. package/dist/Verbs/MaafAppPermissions.js.map +1 -1
  159. package/dist/Verbs/Pack.d.ts +1 -1
  160. package/dist/Verbs/RefreshDataSource.js +1 -1
  161. package/dist/Verbs/RefreshDataSource.js.map +1 -1
  162. package/dist/Verbs/RefreshGitAuth.d.ts.map +1 -1
  163. package/dist/Verbs/RefreshGitAuth.js +3 -15
  164. package/dist/Verbs/RefreshGitAuth.js.map +1 -1
  165. package/dist/Verbs/{DeleteDataSource.d.ts → RemoveDataSource.d.ts} +2 -2
  166. package/dist/Verbs/RemoveDataSource.d.ts.map +1 -0
  167. package/dist/Verbs/RemoveDataSource.js +158 -0
  168. package/dist/Verbs/RemoveDataSource.js.map +1 -0
  169. package/dist/Verbs/SetSetting.js +2 -2
  170. package/dist/Verbs/SetSetting.js.map +1 -1
  171. package/dist/Verbs/ShareLinkList.js +1 -1
  172. package/dist/Verbs/ShareLinkList.js.map +1 -1
  173. package/dist/Verbs/ShowMaafApp.d.ts +6 -0
  174. package/dist/Verbs/ShowMaafApp.d.ts.map +1 -1
  175. package/dist/Verbs/ShowMaafApp.js +10 -2
  176. package/dist/Verbs/ShowMaafApp.js.map +1 -1
  177. package/dist/Verbs/VerbConstants.d.ts +20 -23
  178. package/dist/Verbs/VerbConstants.d.ts.map +1 -1
  179. package/dist/Verbs/VerbConstants.js +20 -23
  180. package/dist/Verbs/VerbConstants.js.map +1 -1
  181. package/dist/Verbs/index.d.ts +1 -1
  182. package/dist/Verbs/index.d.ts.map +1 -1
  183. package/dist/Verbs/index.js +1 -1
  184. package/dist/Verbs/index.js.map +1 -1
  185. package/package.json +11 -9
  186. package/dist/Verbs/DeleteDataSource.d.ts.map +0 -1
  187. package/dist/Verbs/DeleteDataSource.js +0 -105
  188. package/dist/Verbs/DeleteDataSource.js.map +0 -1
@@ -1,7 +1,8 @@
1
1
  /*!
2
2
  * Copyright (C) Microsoft Corporation. All rights reserved.
3
3
  */
4
- import { execSync } from 'child_process';
4
+ import { execFileSync } from 'child_process';
5
+ import { runGit } from './GitRunner.js';
5
6
  /**
6
7
  * Reads the current branch and commit SHA from the working directory's git repo.
7
8
  * Returns null when git is unavailable or the directory is not a git repo.
@@ -9,28 +10,89 @@ import { execSync } from 'child_process';
9
10
  * literal string 'HEAD' and callers should not treat it as a branch name.
10
11
  */
11
12
  export function resolveGitDefaults() {
12
- try {
13
- const commitSha = execSync('git rev-parse HEAD', { stdio: 'pipe' }).toString().trim();
14
- const branch = execSync('git rev-parse --abbrev-ref HEAD', { stdio: 'pipe' }).toString().trim();
15
- return { branch, commitSha, detached: branch === 'HEAD' };
16
- }
17
- catch {
13
+ const sha = runGit(['rev-parse', 'HEAD'], {
14
+ captureStdout: true,
15
+ allowFailure: true,
16
+ emitStderr: false,
17
+ });
18
+ if (!sha.success)
18
19
  return null;
19
- }
20
+ const ref = runGit(['rev-parse', '--abbrev-ref', 'HEAD'], {
21
+ captureStdout: true,
22
+ allowFailure: true,
23
+ emitStderr: false,
24
+ });
25
+ if (!ref.success)
26
+ return null;
27
+ const commitSha = sha.stdout.trim();
28
+ const branch = ref.stdout.trim();
29
+ return { branch, commitSha, detached: branch === 'HEAD' };
20
30
  }
21
31
  /**
22
32
  * Reads the current git remote origin URL from the working directory's git repo.
23
33
  * Returns null when git is unavailable or the directory is not a git repo
24
34
  */
25
35
  export function getCurrentGitRemoteUrl() {
36
+ const result = runGit(['config', '--get', 'remote.origin.url'], {
37
+ captureStdout: true,
38
+ allowFailure: true,
39
+ emitStderr: false,
40
+ });
41
+ if (!result.success)
42
+ return undefined;
43
+ return result.stdout.trim() || undefined;
44
+ }
45
+ // Only allow transport schemes the platform actually returns: HTTPS clone URLs
46
+ // (native Azure DevOps and GitHub HTTPS) and SSH clone URLs. This blocks git's
47
+ // `ext::`, `fd::`, and similar protocols that can spawn external commands as
48
+ // transport helpers without the shell ever being involved.
49
+ const allowedGitRemoteSchemes = ['https://', 'ssh://', 'git@'];
50
+ function isSafeGitRemoteUrl(remoteUrl) {
51
+ return (allowedGitRemoteSchemes.some((scheme) => remoteUrl.startsWith(scheme)) &&
52
+ remoteUrl.trim() === remoteUrl &&
53
+ !remoteUrl.startsWith('-') &&
54
+ !/[\r\n\0]/.test(remoteUrl));
55
+ }
56
+ // A failing `execFileSync` sets `error.message` to
57
+ // "Command failed: git remote add origin <url>", embedding the remote URL
58
+ // verbatim. If that URL ever carries credentials (e.g. https://<PAT>@host/...),
59
+ // returning the raw message would leak the secret into telemetry. Redact any
60
+ // userinfo segment before surfacing the error to callers.
61
+ function scrubGitErrorMessage(message) {
62
+ return message.replace(/:\/\/[^@\s/]+@/g, '://[REDACTED]@');
63
+ }
64
+ /**
65
+ * Initializes a local git repository in the current working directory and
66
+ * optionally configures the origin remote in the supplied working directory.
67
+ * Returns true when `git init` succeeds, false when git is unavailable or the
68
+ * command fails for any reason (e.g. permissions). Callers should treat false as
69
+ * a soft failure — the app was already created; git can be initialized manually.
70
+ */
71
+ export function initializeLocalGitRepo(remoteUrl, cwd = process.cwd()) {
26
72
  try {
27
- const remoteUrl = execSync('git config --get remote.origin.url', { stdio: 'pipe' })
28
- .toString()
29
- .trim();
30
- return remoteUrl || undefined;
73
+ if (remoteUrl !== undefined && !isSafeGitRemoteUrl(remoteUrl)) {
74
+ return {
75
+ success: false,
76
+ error: 'Unsafe git remote URL.',
77
+ };
78
+ }
79
+ execFileSync('git', ['init'], { stdio: 'pipe', windowsHide: true, cwd });
80
+ if (remoteUrl) {
81
+ execFileSync('git', ['remote', 'add', 'origin', remoteUrl], {
82
+ stdio: 'pipe',
83
+ windowsHide: true,
84
+ cwd,
85
+ });
86
+ }
87
+ return {
88
+ success: true,
89
+ };
31
90
  }
32
- catch {
33
- return undefined;
91
+ catch (error) {
92
+ return {
93
+ success: false,
94
+ error: scrubGitErrorMessage(error instanceof Error ? error.message : String(error)),
95
+ };
34
96
  }
35
97
  }
36
98
  /**
@@ -39,12 +101,13 @@ export function getCurrentGitRemoteUrl() {
39
101
  * the check rather than treat it as a clean tree.
40
102
  */
41
103
  export function hasUncommittedChanges() {
42
- try {
43
- const status = execSync('git status --porcelain', { stdio: 'pipe' }).toString().trim();
44
- return status.length > 0;
45
- }
46
- catch {
104
+ const result = runGit(['status', '--porcelain'], {
105
+ captureStdout: true,
106
+ allowFailure: true,
107
+ emitStderr: false,
108
+ });
109
+ if (!result.success)
47
110
  return null;
48
- }
111
+ return result.stdout.trim().length > 0;
49
112
  }
50
113
  //# sourceMappingURL=GitUtils.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"GitUtils.js","sourceRoot":"","sources":["../../src/Utils/GitUtils.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAQzC;;;;;GAKG;AACH,MAAM,UAAU,kBAAkB;IAChC,IAAI,CAAC;QACH,MAAM,SAAS,GAAG,QAAQ,CAAC,oBAAoB,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,CAAC;QACtF,MAAM,MAAM,GAAG,QAAQ,CAAC,iCAAiC,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,CAAC;QAChG,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,KAAK,MAAM,EAAE,CAAC;IAC5D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,sBAAsB;IACpC,IAAI,CAAC;QACH,MAAM,SAAS,GAAG,QAAQ,CAAC,oCAAoC,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;aAChF,QAAQ,EAAE;aACV,IAAI,EAAE,CAAC;QACV,OAAO,SAAS,IAAI,SAAS,CAAC;IAChC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,qBAAqB;IACnC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,QAAQ,CAAC,wBAAwB,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,CAAC;QACvF,OAAO,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC;IAC3B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"GitUtils.js","sourceRoot":"","sources":["../../src/Utils/GitUtils.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAE7C,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAarC;;;;;GAKG;AACH,MAAM,UAAU,kBAAkB;IAChC,MAAM,GAAG,GAAG,MAAM,CAAC,CAAC,WAAW,EAAE,MAAM,CAAC,EAAE;QACxC,aAAa,EAAE,IAAI;QACnB,YAAY,EAAE,IAAI;QAClB,UAAU,EAAE,KAAK;KAClB,CAAC,CAAC;IACH,IAAI,CAAC,GAAG,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC;IAE9B,MAAM,GAAG,GAAG,MAAM,CAAC,CAAC,WAAW,EAAE,cAAc,EAAE,MAAM,CAAC,EAAE;QACxD,aAAa,EAAE,IAAI;QACnB,YAAY,EAAE,IAAI;QAClB,UAAU,EAAE,KAAK;KAClB,CAAC,CAAC;IACH,IAAI,CAAC,GAAG,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC;IAE9B,MAAM,SAAS,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;IACpC,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;IACjC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,KAAK,MAAM,EAAE,CAAC;AAC5D,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,sBAAsB;IACpC,MAAM,MAAM,GAAG,MAAM,CAAC,CAAC,QAAQ,EAAE,OAAO,EAAE,mBAAmB,CAAC,EAAE;QAC9D,aAAa,EAAE,IAAI;QACnB,YAAY,EAAE,IAAI;QAClB,UAAU,EAAE,KAAK;KAClB,CAAC,CAAC;IACH,IAAI,CAAC,MAAM,CAAC,OAAO;QAAE,OAAO,SAAS,CAAC;IACtC,OAAO,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,SAAS,CAAC;AAC3C,CAAC;AAED,+EAA+E;AAC/E,+EAA+E;AAC/E,6EAA6E;AAC7E,2DAA2D;AAC3D,MAAM,uBAAuB,GAAG,CAAC,UAAU,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;AAE/D,SAAS,kBAAkB,CAAC,SAAiB;IAC3C,OAAO,CACL,uBAAuB,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,SAAS,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;QACtE,SAAS,CAAC,IAAI,EAAE,KAAK,SAAS;QAC9B,CAAC,SAAS,CAAC,UAAU,CAAC,GAAG,CAAC;QAC1B,CAAC,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,CAC5B,CAAC;AACJ,CAAC;AAED,mDAAmD;AACnD,0EAA0E;AAC1E,gFAAgF;AAChF,6EAA6E;AAC7E,0DAA0D;AAC1D,SAAS,oBAAoB,CAAC,OAAe;IAC3C,OAAO,OAAO,CAAC,OAAO,CAAC,iBAAiB,EAAE,gBAAgB,CAAC,CAAC;AAC9D,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,sBAAsB,CACpC,SAAkB,EAClB,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE;IAEnB,IAAI,CAAC;QACH,IAAI,SAAS,KAAK,SAAS,IAAI,CAAC,kBAAkB,CAAC,SAAS,CAAC,EAAE,CAAC;YAC9D,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,KAAK,EAAE,wBAAwB;aAChC,CAAC;QACJ,CAAC;QACD,YAAY,CAAC,KAAK,EAAE,CAAC,MAAM,CAAC,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC;QACzE,IAAI,SAAS,EAAE,CAAC;YACd,YAAY,CAAC,KAAK,EAAE,CAAC,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,CAAC,EAAE;gBAC1D,KAAK,EAAE,MAAM;gBACb,WAAW,EAAE,IAAI;gBACjB,GAAG;aACJ,CAAC,CAAC;QACL,CAAC;QAED,OAAO;YACL,OAAO,EAAE,IAAI;SACd,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO;YACL,OAAO,EAAE,KAAK;YACd,KAAK,EAAE,oBAAoB,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;SACpF,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,qBAAqB;IACnC,MAAM,MAAM,GAAG,MAAM,CAAC,CAAC,QAAQ,EAAE,aAAa,CAAC,EAAE;QAC/C,aAAa,EAAE,IAAI;QACnB,YAAY,EAAE,IAAI;QAClB,UAAU,EAAE,KAAK;KAClB,CAAC,CAAC;IACH,IAAI,CAAC,MAAM,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC;IACjC,OAAO,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC;AACzC,CAAC"}
@@ -0,0 +1,38 @@
1
+ /*!
2
+ * Copyright (C) Microsoft Corporation. All rights reserved.
3
+ */
4
+ /**
5
+ * Preflight guard for `ms app create`: throws `ConfigurationError` when `git` is
6
+ * missing from PATH, or present but older than this package's `engines.git`
7
+ * range. Runs ahead of any server call so a local-tooling misconfiguration fails
8
+ * fast and never leaves an orphaned MAAF app + GRS repo behind.
9
+ *
10
+ * The floor lives in `engines.git` (currently `>=2.27.0`), bound by
11
+ * `git clone --sparse` + `git sparse-checkout set` in cone-mode-by-default — both
12
+ * landed in git 2.27.0 (Jun 2020). Every other git invocation in the verb
13
+ * (init/add/commit/push/clone/fetch/checkout, plus `-C` and `--filter=blob:none`)
14
+ * needs older versions, so 2.27.0 is the cumulative floor.
15
+ *
16
+ * Note that `engines.git` is NOT a recognised key in npm / bun / yarn / pnpm —
17
+ * none of them check it at install time (the only `engines` keys with built-in
18
+ * enforcement are `node` and the package manager's own name, and even those
19
+ * default to warn-not-fail). The runtime check below is the sole enforcement
20
+ * point; the manifest entry is documentation and the source of truth this
21
+ * function reads back.
22
+ *
23
+ * Failure postures, by input source:
24
+ * - `engines.git` lives in our own `package.json`, so a missing / invalid
25
+ * value would be a CLI bug. The runtime silently no-ops in that case —
26
+ * blocking a user over OUR misconfiguration would be the wrong trade.
27
+ * The `GitVersionChecker.test.ts` "engines.git is non-empty and a valid
28
+ * semver range" test fails the build if the manifest is broken, so the
29
+ * misconfig never reaches production.
30
+ * - `git --version` output comes from whatever git is on the user's PATH.
31
+ * Real-world dialects include `git version 2.45.2.windows.1`, `git version
32
+ * 2.39.5 (Apple Git-154)`, RC/dev suffixes, etc. `semver.coerce` extracts
33
+ * the leading `<major>.<minor>.<patch>` from any of them; if it can't, we
34
+ * fail open so a non-standard distribution doesn't get blocked over a
35
+ * format we couldn't predict.
36
+ */
37
+ export declare function ensureGitInstalled(): void;
38
+ //# sourceMappingURL=GitVersionChecker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GitVersionChecker.d.ts","sourceRoot":"","sources":["../../src/Utils/GitVersionChecker.ts"],"names":[],"mappings":"AAAA;;GAEG;AAQH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,wBAAgB,kBAAkB,IAAI,IAAI,CAuBzC"}
@@ -0,0 +1,64 @@
1
+ /*!
2
+ * Copyright (C) Microsoft Corporation. All rights reserved.
3
+ */
4
+ import semver from 'semver';
5
+ import packageJson from '../../package.json' with { type: 'json' };
6
+ import { ConfigurationError } from '../Errors/CliError.js';
7
+ import { runGit } from './GitRunner.js';
8
+ /**
9
+ * Preflight guard for `ms app create`: throws `ConfigurationError` when `git` is
10
+ * missing from PATH, or present but older than this package's `engines.git`
11
+ * range. Runs ahead of any server call so a local-tooling misconfiguration fails
12
+ * fast and never leaves an orphaned MAAF app + GRS repo behind.
13
+ *
14
+ * The floor lives in `engines.git` (currently `>=2.27.0`), bound by
15
+ * `git clone --sparse` + `git sparse-checkout set` in cone-mode-by-default — both
16
+ * landed in git 2.27.0 (Jun 2020). Every other git invocation in the verb
17
+ * (init/add/commit/push/clone/fetch/checkout, plus `-C` and `--filter=blob:none`)
18
+ * needs older versions, so 2.27.0 is the cumulative floor.
19
+ *
20
+ * Note that `engines.git` is NOT a recognised key in npm / bun / yarn / pnpm —
21
+ * none of them check it at install time (the only `engines` keys with built-in
22
+ * enforcement are `node` and the package manager's own name, and even those
23
+ * default to warn-not-fail). The runtime check below is the sole enforcement
24
+ * point; the manifest entry is documentation and the source of truth this
25
+ * function reads back.
26
+ *
27
+ * Failure postures, by input source:
28
+ * - `engines.git` lives in our own `package.json`, so a missing / invalid
29
+ * value would be a CLI bug. The runtime silently no-ops in that case —
30
+ * blocking a user over OUR misconfiguration would be the wrong trade.
31
+ * The `GitVersionChecker.test.ts` "engines.git is non-empty and a valid
32
+ * semver range" test fails the build if the manifest is broken, so the
33
+ * misconfig never reaches production.
34
+ * - `git --version` output comes from whatever git is on the user's PATH.
35
+ * Real-world dialects include `git version 2.45.2.windows.1`, `git version
36
+ * 2.39.5 (Apple Git-154)`, RC/dev suffixes, etc. `semver.coerce` extracts
37
+ * the leading `<major>.<minor>.<patch>` from any of them; if it can't, we
38
+ * fail open so a non-standard distribution doesn't get blocked over a
39
+ * format we couldn't predict.
40
+ */
41
+ export function ensureGitInstalled() {
42
+ // `runGit` with allowFailure turns a missing-git spawn failure into a
43
+ // structured result instead of a throw; emitStderr is off because we own the
44
+ // user-facing message here (the raw "command not found" stderr would be noise).
45
+ const result = runGit(['--version'], {
46
+ captureStdout: true,
47
+ allowFailure: true,
48
+ emitStderr: false,
49
+ });
50
+ if (!result.success) {
51
+ throw new ConfigurationError("'git' is required but was not found on PATH.");
52
+ }
53
+ const versionOutput = result.stdout;
54
+ const required = packageJson.engines.git;
55
+ if (!semver.validRange(required))
56
+ return;
57
+ const found = semver.coerce(versionOutput);
58
+ if (!found)
59
+ return;
60
+ if (semver.satisfies(found, required))
61
+ return;
62
+ throw new ConfigurationError(`Git ${required} is required (found ${found.version}). Please upgrade git.`);
63
+ }
64
+ //# sourceMappingURL=GitVersionChecker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GitVersionChecker.js","sourceRoot":"","sources":["../../src/Utils/GitVersionChecker.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,MAAM,MAAM,QAAQ,CAAC;AAE5B,OAAO,WAAW,MAAM,oBAAoB,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAC;AACnE,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,MAAM,UAAU,kBAAkB;IAChC,sEAAsE;IACtE,6EAA6E;IAC7E,gFAAgF;IAChF,MAAM,MAAM,GAAG,MAAM,CAAC,CAAC,WAAW,CAAC,EAAE;QACnC,aAAa,EAAE,IAAI;QACnB,YAAY,EAAE,IAAI;QAClB,UAAU,EAAE,KAAK;KAClB,CAAC,CAAC;IACH,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,MAAM,IAAI,kBAAkB,CAAC,8CAA8C,CAAC,CAAC;IAC/E,CAAC;IACD,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,CAAC;IAEpC,MAAM,QAAQ,GAAG,WAAW,CAAC,OAAO,CAAC,GAAG,CAAC;IACzC,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC;QAAE,OAAO;IACzC,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;IAC3C,IAAI,CAAC,KAAK;QAAE,OAAO;IACnB,IAAI,MAAM,CAAC,SAAS,CAAC,KAAK,EAAE,QAAQ,CAAC;QAAE,OAAO;IAE9C,MAAM,IAAI,kBAAkB,CAC1B,OAAO,QAAQ,uBAAuB,KAAK,CAAC,OAAO,wBAAwB,CAC5E,CAAC;AACJ,CAAC"}
@@ -0,0 +1,22 @@
1
+ /*!
2
+ * Copyright (C) Microsoft Corporation. All rights reserved.
3
+ */
4
+ import type { AppConfig, RepoType } from '@microsoft/managed-apps-common/config';
5
+ interface BuildMaafAppConfigOptions {
6
+ appId: string;
7
+ appDisplayName: string;
8
+ description: string | null | undefined;
9
+ environmentId: string;
10
+ repoType: RepoType;
11
+ cloud: AppConfig['cloud'];
12
+ buildPath?: string;
13
+ buildCommand?: string;
14
+ buildEntryPoint?: string;
15
+ repositoryId?: string;
16
+ externalRepoUrl?: string;
17
+ appSettings?: AppConfig['appSettings'];
18
+ connectionReferences?: AppConfig['connectionReferences'];
19
+ }
20
+ export declare function buildMaafAppConfig(options: BuildMaafAppConfigOptions): AppConfig;
21
+ export {};
22
+ //# sourceMappingURL=MaafAppConfig.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MaafAppConfig.d.ts","sourceRoot":"","sources":["../../src/Utils/MaafAppConfig.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,uCAAuC,CAAC;AAGjF,UAAU,yBAAyB;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IACvC,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,QAAQ,CAAC;IACnB,KAAK,EAAE,SAAS,CAAC,OAAO,CAAC,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,WAAW,CAAC,EAAE,SAAS,CAAC,aAAa,CAAC,CAAC;IACvC,oBAAoB,CAAC,EAAE,SAAS,CAAC,sBAAsB,CAAC,CAAC;CAC1D;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,yBAAyB,GAAG,SAAS,CA+BhF"}
@@ -0,0 +1,32 @@
1
+ /*!
2
+ * Copyright (C) Microsoft Corporation. All rights reserved.
3
+ */
4
+ import { VERSION } from '@microsoft/managed-apps-common/config';
5
+ export function buildMaafAppConfig(options) {
6
+ const appConfig = {
7
+ version: VERSION,
8
+ appId: options.appId,
9
+ appDisplayName: options.appDisplayName,
10
+ environmentId: options.environmentId,
11
+ description: options.description,
12
+ repoType: options.repoType,
13
+ cloud: options.cloud,
14
+ buildPath: options.buildPath ?? './dist',
15
+ buildCommand: options.buildCommand ?? 'npm run build',
16
+ buildEntryPoint: options.buildEntryPoint ?? 'index.html',
17
+ };
18
+ if (options.repositoryId) {
19
+ appConfig.repositoryId = options.repositoryId;
20
+ }
21
+ if (options.externalRepoUrl) {
22
+ appConfig.externalRepoUrl = options.externalRepoUrl;
23
+ }
24
+ if (options.connectionReferences !== undefined) {
25
+ appConfig.connectionReferences = options.connectionReferences;
26
+ }
27
+ if (options.appSettings !== undefined) {
28
+ appConfig.appSettings = options.appSettings;
29
+ }
30
+ return appConfig;
31
+ }
32
+ //# sourceMappingURL=MaafAppConfig.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MaafAppConfig.js","sourceRoot":"","sources":["../../src/Utils/MaafAppConfig.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,OAAO,EAAE,MAAM,uCAAuC,CAAC;AAkBhE,MAAM,UAAU,kBAAkB,CAAC,OAAkC;IACnE,MAAM,SAAS,GAAc;QAC3B,OAAO,EAAE,OAAO;QAChB,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,cAAc,EAAE,OAAO,CAAC,cAAc;QACtC,aAAa,EAAE,OAAO,CAAC,aAAa;QACpC,WAAW,EAAE,OAAO,CAAC,WAAW;QAChC,QAAQ,EAAE,OAAO,CAAC,QAAQ;QAC1B,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,SAAS,EAAE,OAAO,CAAC,SAAS,IAAI,QAAQ;QACxC,YAAY,EAAE,OAAO,CAAC,YAAY,IAAI,eAAe;QACrD,eAAe,EAAE,OAAO,CAAC,eAAe,IAAI,YAAY;KACzD,CAAC;IAEF,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC;QACzB,SAAS,CAAC,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC;IAChD,CAAC;IAED,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC;QAC5B,SAAS,CAAC,eAAe,GAAG,OAAO,CAAC,eAAe,CAAC;IACtD,CAAC;IAED,IAAI,OAAO,CAAC,oBAAoB,KAAK,SAAS,EAAE,CAAC;QAC/C,SAAS,CAAC,oBAAoB,GAAG,OAAO,CAAC,oBAAoB,CAAC;IAChE,CAAC;IAED,IAAI,OAAO,CAAC,WAAW,KAAK,SAAS,EAAE,CAAC;QACtC,SAAS,CAAC,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC;IAC9C,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC"}
@@ -2,12 +2,9 @@
2
2
  * Copyright (C) Microsoft Corporation. All rights reserved.
3
3
  */
4
4
  /**
5
- * Best-effort guard: warn (never throw) when the running Node.js is older than the
6
- * minimum declared in this package's `engines.node`. Mirrors `scripts/check-bun-version.ts`.
7
- * Emits via `printWarning` — stderr, so it can't corrupt a `--json` stdout envelope, with
8
- * NO_COLOR/TTY handled by `styleText`.
5
+ * Best-effort guard: warn (never throw) when the running Node.js doesn't satisfy this package's
6
+ * `engines.node` range. Mirrors `scripts/check-bun-version.ts`. Emits via `printWarning` — stderr,
7
+ * so it can't corrupt a `--json` stdout envelope, with NO_COLOR/TTY handled by `styleText`.
9
8
  */
10
9
  export declare function warnIfNodeVersionUnsupported(): void;
11
- /** Parse the leading `major.minor.patch` out of a version or range string (`>=24.5.0` → `[24, 5, 0]`). */
12
- export declare function parseVersion(value: string): number[];
13
10
  //# sourceMappingURL=NodeVersionChecker.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"NodeVersionChecker.d.ts","sourceRoot":"","sources":["../../src/Utils/NodeVersionChecker.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH;;;;;GAKG;AACH,wBAAgB,4BAA4B,IAAI,IAAI,CAWnD;AAED,0GAA0G;AAC1G,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAGpD"}
1
+ {"version":3,"file":"NodeVersionChecker.d.ts","sourceRoot":"","sources":["../../src/Utils/NodeVersionChecker.ts"],"names":[],"mappings":"AAAA;;GAEG;AAOH;;;;GAIG;AACH,wBAAgB,4BAA4B,IAAI,IAAI,CAWnD"}
@@ -1,38 +1,21 @@
1
1
  /*!
2
2
  * Copyright (C) Microsoft Corporation. All rights reserved.
3
3
  */
4
+ import semver from 'semver';
4
5
  import packageJson from '../../package.json' with { type: 'json' };
5
6
  import { printWarning } from './ConsoleOutput.js';
6
7
  /**
7
- * Best-effort guard: warn (never throw) when the running Node.js is older than the
8
- * minimum declared in this package's `engines.node`. Mirrors `scripts/check-bun-version.ts`.
9
- * Emits via `printWarning` — stderr, so it can't corrupt a `--json` stdout envelope, with
10
- * NO_COLOR/TTY handled by `styleText`.
8
+ * Best-effort guard: warn (never throw) when the running Node.js doesn't satisfy this package's
9
+ * `engines.node` range. Mirrors `scripts/check-bun-version.ts`. Emits via `printWarning` — stderr,
10
+ * so it can't corrupt a `--json` stdout envelope, with NO_COLOR/TTY handled by `styleText`.
11
11
  */
12
12
  export function warnIfNodeVersionUnsupported() {
13
- const required = packageJson.engines?.node;
14
- if (!required)
13
+ const required = packageJson.engines.node;
14
+ // `semver` lets the engine be any valid range (e.g. `>=24.11.0`, or `^24 || >=26` to allow 24 and
15
+ // 26 but not 25). An invalid range counts as unsupported; the check never throws.
16
+ if (Boolean(semver.validRange(required)) && semver.satisfies(process.versions.node, required)) {
15
17
  return;
16
- const requiredParts = parseVersion(required);
17
- if (requiredParts.length === 0)
18
- return;
19
- if (!isVersionLower(parseVersion(process.versions.node), requiredParts))
20
- return;
21
- printWarning(`Warning: Your Node.js version ${process.versions.node} doesn't match required version ${required}; please upgrade Node.js.`);
22
- }
23
- /** Parse the leading `major.minor.patch` out of a version or range string (`>=24.5.0` → `[24, 5, 0]`). */
24
- export function parseVersion(value) {
25
- const match = value.match(/(\d+)(?:\.(\d+))?(?:\.(\d+))?/);
26
- return match ? [Number(match[1]), Number(match[2] ?? 0), Number(match[3] ?? 0)] : [];
27
- }
28
- /** True when `actual` is strictly older than `required`, compared by major, then minor, then patch. */
29
- function isVersionLower(actual, required) {
30
- for (let i = 0; i < 3; i++) {
31
- const a = actual[i] ?? 0;
32
- const r = required[i] ?? 0;
33
- if (a !== r)
34
- return a < r;
35
18
  }
36
- return false;
19
+ printWarning(`Warning: Your Node.js version ${process.versions.node} doesn't match requirement ${required}; Please install a compatible Node.js version.`);
37
20
  }
38
21
  //# sourceMappingURL=NodeVersionChecker.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"NodeVersionChecker.js","sourceRoot":"","sources":["../../src/Utils/NodeVersionChecker.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,WAAW,MAAM,oBAAoB,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAC;AACnE,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE/C;;;;;GAKG;AACH,MAAM,UAAU,4BAA4B;IAC1C,MAAM,QAAQ,GAAG,WAAW,CAAC,OAAO,EAAE,IAAI,CAAC;IAC3C,IAAI,CAAC,QAAQ;QAAE,OAAO;IAEtB,MAAM,aAAa,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC;IAC7C,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO;IACvC,IAAI,CAAC,cAAc,CAAC,YAAY,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,aAAa,CAAC;QAAE,OAAO;IAEhF,YAAY,CACV,iCAAiC,OAAO,CAAC,QAAQ,CAAC,IAAI,mCAAmC,QAAQ,2BAA2B,CAC7H,CAAC;AACJ,CAAC;AAED,0GAA0G;AAC1G,MAAM,UAAU,YAAY,CAAC,KAAa;IACxC,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,+BAA+B,CAAC,CAAC;IAC3D,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AACvF,CAAC;AAED,uGAAuG;AACvG,SAAS,cAAc,CAAC,MAAgB,EAAE,QAAkB;IAC1D,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC3B,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QACzB,MAAM,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QAC3B,IAAI,CAAC,KAAK,CAAC;YAAE,OAAO,CAAC,GAAG,CAAC,CAAC;IAC5B,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
1
+ {"version":3,"file":"NodeVersionChecker.js","sourceRoot":"","sources":["../../src/Utils/NodeVersionChecker.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,MAAM,MAAM,QAAQ,CAAC;AAE5B,OAAO,WAAW,MAAM,oBAAoB,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAC;AACnE,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE/C;;;;GAIG;AACH,MAAM,UAAU,4BAA4B;IAC1C,MAAM,QAAQ,GAAG,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC;IAC1C,kGAAkG;IAClG,kFAAkF;IAClF,IAAI,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,IAAI,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,EAAE,CAAC;QAC9F,OAAO;IACT,CAAC;IAED,YAAY,CACV,iCAAiC,OAAO,CAAC,QAAQ,CAAC,IAAI,8BAA8B,QAAQ,gDAAgD,CAC7I,CAAC;AACJ,CAAC"}
@@ -8,6 +8,11 @@ export declare const PAGE_SIZE = 20;
8
8
  * Enter/Space = continue, Esc/q = exit, Ctrl+C = process exit.
9
9
  */
10
10
  export declare function waitForPageKey(): Promise<'continue' | 'exit'>;
11
+ /**
12
+ * Prints a paginated text blob in TTY mode (PAGE_SIZE lines per page,
13
+ * Enter/Esc to navigate) or the full text in non-TTY/piped mode.
14
+ */
15
+ export declare function printPagedText(text: string): Promise<void>;
11
16
  /**
12
17
  * Prints a paginated table in TTY mode (20 rows per page, Enter/Esc to navigate)
13
18
  * or a single full table in non-TTY/piped mode.
@@ -19,5 +24,6 @@ export declare function printPagedTable(options: {
19
24
  rows: string[][];
20
25
  emptyMessage?: string;
21
26
  totalLabel: string;
27
+ hint?: string;
22
28
  }): Promise<void>;
23
29
  //# sourceMappingURL=Paging.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Paging.d.ts","sourceRoot":"","sources":["../../src/Utils/Paging.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAGjD,eAAO,MAAM,SAAS,KAAK,CAAC;AAE5B;;;GAGG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAAC,UAAU,GAAG,MAAM,CAAC,CA2BnE;AAED;;;GAGG;AACH,wBAAsB,eAAe,CAAC,OAAO,EAAE;IAC7C,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,OAAO,EAAE,SAAS,EAAE,CAAC;IACrB,IAAI,EAAE,MAAM,EAAE,EAAE,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;CACpB,GAAG,OAAO,CAAC,IAAI,CAAC,CA4BhB"}
1
+ {"version":3,"file":"Paging.d.ts","sourceRoot":"","sources":["../../src/Utils/Paging.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAGjD,eAAO,MAAM,SAAS,KAAK,CAAC;AAE5B;;;GAGG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAAC,UAAU,GAAG,MAAM,CAAC,CA2BnE;AAED;;;GAGG;AACH,wBAAsB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA4BhE;AAED;;;GAGG;AACH,wBAAsB,eAAe,CAAC,OAAO,EAAE;IAC7C,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,OAAO,EAAE,SAAS,EAAE,CAAC;IACrB,IAAI,EAAE,MAAM,EAAE,EAAE,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,GAAG,OAAO,CAAC,IAAI,CAAC,CAkChB"}
@@ -35,16 +35,48 @@ export async function waitForPageKey() {
35
35
  process.stdin.on('keypress', handler);
36
36
  });
37
37
  }
38
+ /**
39
+ * Prints a paginated text blob in TTY mode (PAGE_SIZE lines per page,
40
+ * Enter/Esc to navigate) or the full text in non-TTY/piped mode.
41
+ */
42
+ export async function printPagedText(text) {
43
+ const lines = text.split(/\r?\n/);
44
+ if (!process.stdout.isTTY) {
45
+ for (const line of lines) {
46
+ console.log(line);
47
+ }
48
+ return;
49
+ }
50
+ const total = lines.length;
51
+ const totalPages = Math.max(1, Math.ceil(total / PAGE_SIZE));
52
+ for (let page = 0; page < totalPages; page++) {
53
+ const start = page * PAGE_SIZE;
54
+ const pageLines = lines.slice(start, start + PAGE_SIZE);
55
+ const isLastPage = page === totalPages - 1;
56
+ for (const line of pageLines) {
57
+ console.log(line);
58
+ }
59
+ if (isLastPage)
60
+ break;
61
+ console.log(styleText('dim', ' Press Enter for more, Esc or q to exit'));
62
+ const action = await waitForPageKey();
63
+ if (action === 'exit')
64
+ break;
65
+ }
66
+ }
38
67
  /**
39
68
  * Prints a paginated table in TTY mode (20 rows per page, Enter/Esc to navigate)
40
69
  * or a single full table in non-TTY/piped mode.
41
70
  */
42
71
  export async function printPagedTable(options) {
43
- const { title, metadata, columns, rows, emptyMessage, totalLabel } = options;
72
+ const { title, metadata, columns, rows, emptyMessage, totalLabel, hint } = options;
44
73
  const total = rows.length;
45
74
  if (!process.stdout.isTTY) {
46
75
  printTable({ title, metadata, columns, rows, emptyMessage });
47
76
  console.log(styleText('dim', ` Showing ${total} of ${total} ${totalLabel}`));
77
+ if (hint) {
78
+ console.log(styleText('dim', ` ${hint}`));
79
+ }
48
80
  return;
49
81
  }
50
82
  const totalPages = Math.max(1, Math.ceil(total / PAGE_SIZE));
@@ -54,6 +86,9 @@ export async function printPagedTable(options) {
54
86
  const isLastPage = page === totalPages - 1;
55
87
  printTable({ title, metadata, columns, rows: pageRows, emptyMessage });
56
88
  console.log(styleText('dim', ` Showing ${start + pageRows.length} of ${total} ${totalLabel}`));
89
+ if (hint) {
90
+ console.log(styleText('dim', ` ${hint}`));
91
+ }
57
92
  if (!isLastPage) {
58
93
  console.log(styleText('dim', ' Press Enter for more, Esc or q to exit'));
59
94
  }
@@ -1 +1 @@
1
- {"version":3,"file":"Paging.js","sourceRoot":"","sources":["../../src/Utils/Paging.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Paging.js","sourceRoot":"","sources":["../../src/Utils/Paging.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ /*!
2
+ * Copyright (C) Microsoft Corporation. All rights reserved.
3
+ */
4
+ /**
5
+ * Pins the running CLI into an app's `package.json` as a `devDependency` at the
6
+ * exact version of the CLI executing the command (read from this package's own
7
+ * manifest, so it always matches the running CLI).
8
+ *
9
+ * Used by `ms app create` (right after the template is scaffolded) and `ms app
10
+ * init` (binding an existing project) so the app carries a project-local `ms` at
11
+ * the version it was set up with — which `npx ms` / `pnpm exec` / `bun x` resolve
12
+ * ahead of any globally-installed CLI. The app therefore keeps building and
13
+ * deploying against the CLI it was created with, even if the developer's global
14
+ * CLI later moves to an incompatible version.
15
+ *
16
+ * Best-effort and non-fatal — the server-side app already exists by the time this
17
+ * runs:
18
+ * - No `package.json` in `appDir` (e.g. `ms app create` with a custom
19
+ * `--template` that isn't an npm project) → nothing to pin; return quietly.
20
+ * - Read / parse / write failure → warn (outside `--json` mode) and continue;
21
+ * the user can add the pin by hand.
22
+ *
23
+ * The entry overwrites any existing CLI `devDependencies` entry, and
24
+ * `devDependencies` is re-sorted alphabetically to match the npm convention so a
25
+ * later `install --save` won't reshuffle the file.
26
+ */
27
+ export declare function pinCliIntoAppPackageJson(appDir: string, jsonMode: boolean): void;
28
+ //# sourceMappingURL=PinCli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PinCli.d.ts","sourceRoot":"","sources":["../../src/Utils/PinCli.ts"],"names":[],"mappings":"AAAA;;GAEG;AAQH;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,GAAG,IAAI,CAiChF"}
@@ -0,0 +1,58 @@
1
+ /*!
2
+ * Copyright (C) Microsoft Corporation. All rights reserved.
3
+ */
4
+ import * as fs from 'fs';
5
+ import * as path from 'path';
6
+ import packageJson from '../../package.json' with { type: 'json' };
7
+ import { printWarning } from './ConsoleOutput.js';
8
+ /**
9
+ * Pins the running CLI into an app's `package.json` as a `devDependency` at the
10
+ * exact version of the CLI executing the command (read from this package's own
11
+ * manifest, so it always matches the running CLI).
12
+ *
13
+ * Used by `ms app create` (right after the template is scaffolded) and `ms app
14
+ * init` (binding an existing project) so the app carries a project-local `ms` at
15
+ * the version it was set up with — which `npx ms` / `pnpm exec` / `bun x` resolve
16
+ * ahead of any globally-installed CLI. The app therefore keeps building and
17
+ * deploying against the CLI it was created with, even if the developer's global
18
+ * CLI later moves to an incompatible version.
19
+ *
20
+ * Best-effort and non-fatal — the server-side app already exists by the time this
21
+ * runs:
22
+ * - No `package.json` in `appDir` (e.g. `ms app create` with a custom
23
+ * `--template` that isn't an npm project) → nothing to pin; return quietly.
24
+ * - Read / parse / write failure → warn (outside `--json` mode) and continue;
25
+ * the user can add the pin by hand.
26
+ *
27
+ * The entry overwrites any existing CLI `devDependencies` entry, and
28
+ * `devDependencies` is re-sorted alphabetically to match the npm convention so a
29
+ * later `install --save` won't reshuffle the file.
30
+ */
31
+ export function pinCliIntoAppPackageJson(appDir, jsonMode) {
32
+ const packageJsonPath = path.join(appDir, 'package.json');
33
+ // existsSync gate keeps the common "not an npm project" case off the warning
34
+ // path below — only genuine read/parse/write failures should warn.
35
+ if (!fs.existsSync(packageJsonPath)) {
36
+ return;
37
+ }
38
+ try {
39
+ const manifest = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
40
+ manifest.devDependencies = Object.fromEntries(Object.entries({
41
+ ...manifest.devDependencies,
42
+ [packageJson.name]: packageJson.version,
43
+ // Explicit 'en' locale keeps the sort order deterministic across hosts
44
+ // (a bare localeCompare follows the machine's default collation).
45
+ }).sort(([a], [b]) => a.localeCompare(b, 'en')));
46
+ // JSON.stringify drops the trailing newline every scaffolder emits; re-add it.
47
+ fs.writeFileSync(packageJsonPath, `${JSON.stringify(manifest, null, 2)}\n`);
48
+ }
49
+ catch (err) {
50
+ if (!jsonMode) {
51
+ printWarning(`Could not pin '${packageJson.name}' into ${packageJsonPath} ` +
52
+ `(${err instanceof Error ? err.message : String(err)}). Add ` +
53
+ `"${packageJson.name}": "${packageJson.version}" to devDependencies manually ` +
54
+ `to get a project-local CLI.`);
55
+ }
56
+ }
57
+ }
58
+ //# sourceMappingURL=PinCli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PinCli.js","sourceRoot":"","sources":["../../src/Utils/PinCli.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAE7B,OAAO,WAAW,MAAM,oBAAoB,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAC;AACnE,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE/C;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,UAAU,wBAAwB,CAAC,MAAc,EAAE,QAAiB;IACxE,MAAM,eAAe,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IAC1D,6EAA6E;IAC7E,mEAAmE;IACnE,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,eAAe,CAAC,EAAE,CAAC;QACpC,OAAO;IACT,CAAC;IAED,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,eAAe,EAAE,MAAM,CAAC,CAGnE,CAAC;QACF,QAAQ,CAAC,eAAe,GAAG,MAAM,CAAC,WAAW,CAC3C,MAAM,CAAC,OAAO,CAAC;YACb,GAAG,QAAQ,CAAC,eAAe;YAC3B,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,WAAW,CAAC,OAAO;YACvC,uEAAuE;YACvE,kEAAkE;SACnE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAChD,CAAC;QACF,+EAA+E;QAC/E,EAAE,CAAC,aAAa,CAAC,eAAe,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;IAC9E,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,YAAY,CACV,kBAAkB,WAAW,CAAC,IAAI,UAAU,eAAe,GAAG;gBAC5D,IAAI,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,SAAS;gBAC7D,IAAI,WAAW,CAAC,IAAI,OAAO,WAAW,CAAC,OAAO,gCAAgC;gBAC9E,6BAA6B,CAChC,CAAC;QACJ,CAAC;IACH,CAAC;AACH,CAAC"}
@@ -0,0 +1,29 @@
1
+ /*!
2
+ * Copyright (C) Microsoft Corporation. All rights reserved.
3
+ */
4
+ import type { MaafAppDefinition, ManagedAppRepoType } from '@microsoft/managed-apps-actions';
5
+ /** Display-ready repository classification + clone URL derived from a `MaafAppDefinition`. */
6
+ export type RepoDetails = {
7
+ /**
8
+ * Repository-type label for display. Known {@link ManagedAppRepoType} values
9
+ * are mapped to friendly labels; unknown/forward-compat values pass through
10
+ * as the raw server string (see {@link friendlyRepoType}).
11
+ */
12
+ repoType?: string;
13
+ /** Git clone URL for the backing repository, when applicable. */
14
+ cloneUrl?: string;
15
+ };
16
+ /**
17
+ * Maps the raw {@link ManagedAppRepoType} enum returned by the server to a
18
+ * human-friendly label for display. Unknown/forward-compat values fall through
19
+ * to the raw string; `undefined` (legacy apps with no source-control metadata)
20
+ * yields `undefined` so callers can omit the line entirely.
21
+ */
22
+ export declare function friendlyRepoType(repoType: ManagedAppRepoType | undefined): string | undefined;
23
+ /**
24
+ * Derives the display-ready {@link RepoDetails} from an app definition. Returns
25
+ * `undefined` when the app exposes no source-control metadata at all (no
26
+ * `repoType` and no `cloneUrl`), so callers can omit the lines entirely.
27
+ */
28
+ export declare function toRepoDetails(app: Pick<MaafAppDefinition, 'repoType' | 'cloneUrl'>): RepoDetails | undefined;
29
+ //# sourceMappingURL=RepoDetails.d.ts.map