@qpqjs/cli 0.0.0-stage → 0.2.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 (549) hide show
  1. package/README.md +92 -2
  2. package/docker/cdk-deployer/Dockerfile +13 -0
  3. package/docker/dev-server/Dockerfile +47 -0
  4. package/lib/commonjs/bin/qpq.d.ts +2 -0
  5. package/lib/commonjs/bin/qpq.js +6 -0
  6. package/lib/commonjs/bin/qpq.js.map +1 -0
  7. package/lib/commonjs/bin/qpqCdkApp.d.ts +1 -0
  8. package/lib/commonjs/bin/qpqCdkApp.js +8 -0
  9. package/lib/commonjs/bin/qpqCdkApp.js.map +1 -0
  10. package/lib/commonjs/cli/commandMenu.d.ts +2 -0
  11. package/lib/commonjs/cli/commandMenu.js +81 -0
  12. package/lib/commonjs/cli/commandMenu.js.map +1 -0
  13. package/lib/commonjs/cli/commandRegistry.d.ts +10 -0
  14. package/lib/commonjs/cli/commandRegistry.js +177 -0
  15. package/lib/commonjs/cli/commandRegistry.js.map +1 -0
  16. package/lib/commonjs/cli/index.d.ts +1 -0
  17. package/lib/commonjs/cli/index.js +18 -0
  18. package/lib/commonjs/cli/index.js.map +1 -0
  19. package/lib/commonjs/cli/runCli.d.ts +1 -0
  20. package/lib/commonjs/cli/runCli.js +86 -0
  21. package/lib/commonjs/cli/runCli.js.map +1 -0
  22. package/lib/commonjs/commands/checkCircular.d.ts +1 -0
  23. package/lib/commonjs/commands/checkCircular.js +70 -0
  24. package/lib/commonjs/commands/checkCircular.js.map +1 -0
  25. package/lib/commonjs/commands/clearResources.d.ts +1 -0
  26. package/lib/commonjs/commands/clearResources.js +36 -0
  27. package/lib/commonjs/commands/clearResources.js.map +1 -0
  28. package/lib/commonjs/commands/go.d.ts +1 -0
  29. package/lib/commonjs/commands/go.js +30 -0
  30. package/lib/commonjs/commands/go.js.map +1 -0
  31. package/lib/commonjs/commands/goDev.d.ts +1 -0
  32. package/lib/commonjs/commands/goDev.js +46 -0
  33. package/lib/commonjs/commands/goDev.js.map +1 -0
  34. package/lib/commonjs/commands/goDevApi.d.ts +1 -0
  35. package/lib/commonjs/commands/goDevApi.js +158 -0
  36. package/lib/commonjs/commands/goDevApi.js.map +1 -0
  37. package/lib/commonjs/commands/goDevWeb.d.ts +4 -0
  38. package/lib/commonjs/commands/goDevWeb.js +144 -0
  39. package/lib/commonjs/commands/goDevWeb.js.map +1 -0
  40. package/lib/commonjs/commands/goDocker.d.ts +1 -0
  41. package/lib/commonjs/commands/goDocker.js +43 -0
  42. package/lib/commonjs/commands/goDocker.js.map +1 -0
  43. package/lib/commonjs/commands/hooks.d.ts +1 -0
  44. package/lib/commonjs/commands/hooks.js +39 -0
  45. package/lib/commonjs/commands/hooks.js.map +1 -0
  46. package/lib/commonjs/commands/migrate.d.ts +1 -0
  47. package/lib/commonjs/commands/migrate.js +70 -0
  48. package/lib/commonjs/commands/migrate.js.map +1 -0
  49. package/lib/commonjs/commands/prep.d.ts +1 -0
  50. package/lib/commonjs/commands/prep.js +28 -0
  51. package/lib/commonjs/commands/prep.js.map +1 -0
  52. package/lib/commonjs/commands/publish.d.ts +4 -0
  53. package/lib/commonjs/commands/publish.js +54 -0
  54. package/lib/commonjs/commands/publish.js.map +1 -0
  55. package/lib/commonjs/commands/scriptBuild.d.ts +1 -0
  56. package/lib/commonjs/commands/scriptBuild.js +46 -0
  57. package/lib/commonjs/commands/scriptBuild.js.map +1 -0
  58. package/lib/commonjs/commands/scriptBuilderLayer.d.ts +1 -0
  59. package/lib/commonjs/commands/scriptBuilderLayer.js +48 -0
  60. package/lib/commonjs/commands/scriptBuilderLayer.js.map +1 -0
  61. package/lib/commonjs/commands/scriptNew.d.ts +1 -0
  62. package/lib/commonjs/commands/scriptNew.js +35 -0
  63. package/lib/commonjs/commands/scriptNew.js.map +1 -0
  64. package/lib/commonjs/commands/setup.d.ts +1 -0
  65. package/lib/commonjs/commands/setup.js +102 -0
  66. package/lib/commonjs/commands/setup.js.map +1 -0
  67. package/lib/commonjs/commands/synth.d.ts +1 -0
  68. package/lib/commonjs/commands/synth.js +89 -0
  69. package/lib/commonjs/commands/synth.js.map +1 -0
  70. package/lib/commonjs/commands/teardown.d.ts +1 -0
  71. package/lib/commonjs/commands/teardown.js +33 -0
  72. package/lib/commonjs/commands/teardown.js.map +1 -0
  73. package/lib/commonjs/index.d.ts +1 -0
  74. package/lib/commonjs/index.js +18 -0
  75. package/lib/commonjs/index.js.map +1 -0
  76. package/lib/commonjs/lib/args.d.ts +3 -0
  77. package/lib/commonjs/lib/args.js +31 -0
  78. package/lib/commonjs/lib/args.js.map +1 -0
  79. package/lib/commonjs/lib/circularImports.d.ts +3 -0
  80. package/lib/commonjs/lib/circularImports.js +79 -0
  81. package/lib/commonjs/lib/circularImports.js.map +1 -0
  82. package/lib/commonjs/lib/clearResourcesPlan.d.ts +15 -0
  83. package/lib/commonjs/lib/clearResourcesPlan.js +79 -0
  84. package/lib/commonjs/lib/clearResourcesPlan.js.map +1 -0
  85. package/lib/commonjs/lib/deployPrompts.d.ts +26 -0
  86. package/lib/commonjs/lib/deployPrompts.js +118 -0
  87. package/lib/commonjs/lib/deployPrompts.js.map +1 -0
  88. package/lib/commonjs/lib/devServerEntry.d.ts +22 -0
  89. package/lib/commonjs/lib/devServerEntry.js +135 -0
  90. package/lib/commonjs/lib/devServerEntry.js.map +1 -0
  91. package/lib/commonjs/lib/devServerPorts.d.ts +13 -0
  92. package/lib/commonjs/lib/devServerPorts.js +36 -0
  93. package/lib/commonjs/lib/devServerPorts.js.map +1 -0
  94. package/lib/commonjs/lib/discovery.d.ts +10 -0
  95. package/lib/commonjs/lib/discovery.js +56 -0
  96. package/lib/commonjs/lib/discovery.js.map +1 -0
  97. package/lib/commonjs/lib/getDefaultHookJobs.d.ts +2 -0
  98. package/lib/commonjs/lib/getDefaultHookJobs.js +11 -0
  99. package/lib/commonjs/lib/getDefaultHookJobs.js.map +1 -0
  100. package/lib/commonjs/lib/getDeployTargetLabel.d.ts +2 -0
  101. package/lib/commonjs/lib/getDeployTargetLabel.js +12 -0
  102. package/lib/commonjs/lib/getDeployTargetLabel.js.map +1 -0
  103. package/lib/commonjs/lib/goDockerMode.d.ts +6 -0
  104. package/lib/commonjs/lib/goDockerMode.js +23 -0
  105. package/lib/commonjs/lib/goDockerMode.js.map +1 -0
  106. package/lib/commonjs/lib/hooks.d.ts +9 -0
  107. package/lib/commonjs/lib/hooks.js +178 -0
  108. package/lib/commonjs/lib/hooks.js.map +1 -0
  109. package/lib/commonjs/lib/keepOtherDevServersFlag.d.ts +1 -0
  110. package/lib/commonjs/lib/keepOtherDevServersFlag.js +11 -0
  111. package/lib/commonjs/lib/keepOtherDevServersFlag.js.map +1 -0
  112. package/lib/commonjs/lib/killChildWithEscalation.d.ts +10 -0
  113. package/lib/commonjs/lib/killChildWithEscalation.js +33 -0
  114. package/lib/commonjs/lib/killChildWithEscalation.js.map +1 -0
  115. package/lib/commonjs/lib/killStaleListeners.d.ts +17 -0
  116. package/lib/commonjs/lib/killStaleListeners.js +220 -0
  117. package/lib/commonjs/lib/killStaleListeners.js.map +1 -0
  118. package/lib/commonjs/lib/packageRoot.d.ts +1 -0
  119. package/lib/commonjs/lib/packageRoot.js +21 -0
  120. package/lib/commonjs/lib/packageRoot.js.map +1 -0
  121. package/lib/commonjs/lib/prompts.d.ts +15 -0
  122. package/lib/commonjs/lib/prompts.js +78 -0
  123. package/lib/commonjs/lib/prompts.js.map +1 -0
  124. package/lib/commonjs/lib/qpqConfigs.d.ts +4 -0
  125. package/lib/commonjs/lib/qpqConfigs.js +27 -0
  126. package/lib/commonjs/lib/qpqConfigs.js.map +1 -0
  127. package/lib/commonjs/lib/resolveAppSelection.d.ts +6 -0
  128. package/lib/commonjs/lib/resolveAppSelection.js +58 -0
  129. package/lib/commonjs/lib/resolveAppSelection.js.map +1 -0
  130. package/lib/commonjs/lib/resolveDeployment.d.ts +14 -0
  131. package/lib/commonjs/lib/resolveDeployment.js +58 -0
  132. package/lib/commonjs/lib/resolveDeployment.js.map +1 -0
  133. package/lib/commonjs/lib/runCommand.d.ts +14 -0
  134. package/lib/commonjs/lib/runCommand.js +103 -0
  135. package/lib/commonjs/lib/runCommand.js.map +1 -0
  136. package/lib/commonjs/lib/runTasks.d.ts +15 -0
  137. package/lib/commonjs/lib/runTasks.js +123 -0
  138. package/lib/commonjs/lib/runTasks.js.map +1 -0
  139. package/lib/commonjs/lib/setupStep.d.ts +16 -0
  140. package/lib/commonjs/lib/setupStep.js +3 -0
  141. package/lib/commonjs/lib/setupStep.js.map +1 -0
  142. package/lib/commonjs/lib/timing.d.ts +2 -0
  143. package/lib/commonjs/lib/timing.js +11 -0
  144. package/lib/commonjs/lib/timing.js.map +1 -0
  145. package/lib/commonjs/lib/typeWatcher.d.ts +2 -0
  146. package/lib/commonjs/lib/typeWatcher.js +59 -0
  147. package/lib/commonjs/lib/typeWatcher.js.map +1 -0
  148. package/lib/commonjs/lib/userScriptBuilderLayer.d.ts +23 -0
  149. package/lib/commonjs/lib/userScriptBuilderLayer.js +74 -0
  150. package/lib/commonjs/lib/userScriptBuilderLayer.js.map +1 -0
  151. package/lib/commonjs/lib/userScriptTemplate.d.ts +6 -0
  152. package/lib/commonjs/lib/userScriptTemplate.js +47 -0
  153. package/lib/commonjs/lib/userScriptTemplate.js.map +1 -0
  154. package/lib/commonjs/lib/views.d.ts +2 -0
  155. package/lib/commonjs/lib/views.js +31 -0
  156. package/lib/commonjs/lib/views.js.map +1 -0
  157. package/lib/commonjs/lib/webAddressingEnv.d.ts +7 -0
  158. package/lib/commonjs/lib/webAddressingEnv.js +16 -0
  159. package/lib/commonjs/lib/webAddressingEnv.js.map +1 -0
  160. package/lib/commonjs/platforms/aws/awsCredentials.d.ts +1 -0
  161. package/lib/commonjs/platforms/aws/awsCredentials.js +28 -0
  162. package/lib/commonjs/platforms/aws/awsCredentials.js.map +1 -0
  163. package/lib/commonjs/platforms/aws/cdkApp.d.ts +3 -0
  164. package/lib/commonjs/platforms/aws/cdkApp.js +31 -0
  165. package/lib/commonjs/platforms/aws/cdkApp.js.map +1 -0
  166. package/lib/commonjs/platforms/aws/clearResources.d.ts +2 -0
  167. package/lib/commonjs/platforms/aws/clearResources.js +167 -0
  168. package/lib/commonjs/platforms/aws/clearResources.js.map +1 -0
  169. package/lib/commonjs/platforms/aws/go.d.ts +2 -0
  170. package/lib/commonjs/platforms/aws/go.js +131 -0
  171. package/lib/commonjs/platforms/aws/go.js.map +1 -0
  172. package/lib/commonjs/platforms/aws/goDocker.d.ts +3 -0
  173. package/lib/commonjs/platforms/aws/goDocker.js +457 -0
  174. package/lib/commonjs/platforms/aws/goDocker.js.map +1 -0
  175. package/lib/commonjs/platforms/aws/goDockerManifest.d.ts +44 -0
  176. package/lib/commonjs/platforms/aws/goDockerManifest.js +38 -0
  177. package/lib/commonjs/platforms/aws/goDockerManifest.js.map +1 -0
  178. package/lib/commonjs/platforms/aws/index.d.ts +2 -0
  179. package/lib/commonjs/platforms/aws/index.js +23 -0
  180. package/lib/commonjs/platforms/aws/index.js.map +1 -0
  181. package/lib/commonjs/platforms/aws/prepareDeployment.d.ts +3 -0
  182. package/lib/commonjs/platforms/aws/prepareDeployment.js +10 -0
  183. package/lib/commonjs/platforms/aws/prepareDeployment.js.map +1 -0
  184. package/lib/commonjs/platforms/aws/publish.d.ts +4 -0
  185. package/lib/commonjs/platforms/aws/publish.js +66 -0
  186. package/lib/commonjs/platforms/aws/publish.js.map +1 -0
  187. package/lib/commonjs/platforms/aws/remote.d.ts +11 -0
  188. package/lib/commonjs/platforms/aws/remote.js +105 -0
  189. package/lib/commonjs/platforms/aws/remote.js.map +1 -0
  190. package/lib/commonjs/platforms/aws/setup/awsSetupContext.d.ts +12 -0
  191. package/lib/commonjs/platforms/aws/setup/awsSetupContext.js +20 -0
  192. package/lib/commonjs/platforms/aws/setup/awsSetupContext.js.map +1 -0
  193. package/lib/commonjs/platforms/aws/setup/awsSetupSteps.d.ts +8 -0
  194. package/lib/commonjs/platforms/aws/setup/awsSetupSteps.js +44 -0
  195. package/lib/commonjs/platforms/aws/setup/awsSetupSteps.js.map +1 -0
  196. package/lib/commonjs/platforms/aws/setup/buildBucketNamesStep.d.ts +4 -0
  197. package/lib/commonjs/platforms/aws/setup/buildBucketNamesStep.js +77 -0
  198. package/lib/commonjs/platforms/aws/setup/buildBucketNamesStep.js.map +1 -0
  199. package/lib/commonjs/platforms/aws/setup/buildCdkBootstrapSteps.d.ts +5 -0
  200. package/lib/commonjs/platforms/aws/setup/buildCdkBootstrapSteps.js +38 -0
  201. package/lib/commonjs/platforms/aws/setup/buildCdkBootstrapSteps.js.map +1 -0
  202. package/lib/commonjs/platforms/aws/setup/buildGithubDeployRoleStep.d.ts +4 -0
  203. package/lib/commonjs/platforms/aws/setup/buildGithubDeployRoleStep.js +55 -0
  204. package/lib/commonjs/platforms/aws/setup/buildGithubDeployRoleStep.js.map +1 -0
  205. package/lib/commonjs/platforms/aws/setup/buildGithubOidcProviderStep.d.ts +4 -0
  206. package/lib/commonjs/platforms/aws/setup/buildGithubOidcProviderStep.js +54 -0
  207. package/lib/commonjs/platforms/aws/setup/buildGithubOidcProviderStep.js.map +1 -0
  208. package/lib/commonjs/platforms/aws/setup/buildHostedZonesStep.d.ts +4 -0
  209. package/lib/commonjs/platforms/aws/setup/buildHostedZonesStep.js +63 -0
  210. package/lib/commonjs/platforms/aws/setup/buildHostedZonesStep.js.map +1 -0
  211. package/lib/commonjs/platforms/aws/setup/buildIamCapabilityStep.d.ts +4 -0
  212. package/lib/commonjs/platforms/aws/setup/buildIamCapabilityStep.js +48 -0
  213. package/lib/commonjs/platforms/aws/setup/buildIamCapabilityStep.js.map +1 -0
  214. package/lib/commonjs/platforms/aws/setup/buildIdentityStep.d.ts +4 -0
  215. package/lib/commonjs/platforms/aws/setup/buildIdentityStep.js +39 -0
  216. package/lib/commonjs/platforms/aws/setup/buildIdentityStep.js.map +1 -0
  217. package/lib/commonjs/platforms/aws/setup/buildStackSteps.d.ts +5 -0
  218. package/lib/commonjs/platforms/aws/setup/buildStackSteps.js +32 -0
  219. package/lib/commonjs/platforms/aws/setup/buildStackSteps.js.map +1 -0
  220. package/lib/commonjs/platforms/aws/setup/describeStackStatus.d.ts +4 -0
  221. package/lib/commonjs/platforms/aws/setup/describeStackStatus.js +32 -0
  222. package/lib/commonjs/platforms/aws/setup/describeStackStatus.js.map +1 -0
  223. package/lib/commonjs/platforms/aws/setup/index.d.ts +1 -0
  224. package/lib/commonjs/platforms/aws/setup/index.js +18 -0
  225. package/lib/commonjs/platforms/aws/setup/index.js.map +1 -0
  226. package/lib/commonjs/platforms/aws/stacks.d.ts +7 -0
  227. package/lib/commonjs/platforms/aws/stacks.js +94 -0
  228. package/lib/commonjs/platforms/aws/stacks.js.map +1 -0
  229. package/lib/commonjs/platforms/aws/teardown.d.ts +2 -0
  230. package/lib/commonjs/platforms/aws/teardown.js +59 -0
  231. package/lib/commonjs/platforms/aws/teardown.js.map +1 -0
  232. package/lib/commonjs/platforms/aws/viewsSync.d.ts +3 -0
  233. package/lib/commonjs/platforms/aws/viewsSync.js +77 -0
  234. package/lib/commonjs/platforms/aws/viewsSync.js.map +1 -0
  235. package/lib/commonjs/platforms/docker/QpqDockerPlatformSettings.d.ts +10 -0
  236. package/lib/commonjs/platforms/docker/QpqDockerPlatformSettings.js +3 -0
  237. package/lib/commonjs/platforms/docker/QpqDockerPlatformSettings.js.map +1 -0
  238. package/lib/commonjs/platforms/docker/getContainerPorts.d.ts +4 -0
  239. package/lib/commonjs/platforms/docker/getContainerPorts.js +12 -0
  240. package/lib/commonjs/platforms/docker/getContainerPorts.js.map +1 -0
  241. package/lib/commonjs/platforms/docker/getDefaultPortMappings.d.ts +3 -0
  242. package/lib/commonjs/platforms/docker/getDefaultPortMappings.js +10 -0
  243. package/lib/commonjs/platforms/docker/getDefaultPortMappings.js.map +1 -0
  244. package/lib/commonjs/platforms/docker/getDockerPlatformSettings.d.ts +14 -0
  245. package/lib/commonjs/platforms/docker/getDockerPlatformSettings.js +39 -0
  246. package/lib/commonjs/platforms/docker/getDockerPlatformSettings.js.map +1 -0
  247. package/lib/commonjs/platforms/docker/getImageName.d.ts +6 -0
  248. package/lib/commonjs/platforms/docker/getImageName.js +10 -0
  249. package/lib/commonjs/platforms/docker/getImageName.js.map +1 -0
  250. package/lib/commonjs/platforms/docker/go.d.ts +2 -0
  251. package/lib/commonjs/platforms/docker/go.js +261 -0
  252. package/lib/commonjs/platforms/docker/go.js.map +1 -0
  253. package/lib/commonjs/platforms/docker/index.d.ts +2 -0
  254. package/lib/commonjs/platforms/docker/index.js +43 -0
  255. package/lib/commonjs/platforms/docker/index.js.map +1 -0
  256. package/lib/commonjs/platforms/docker/parseMounts.d.ts +7 -0
  257. package/lib/commonjs/platforms/docker/parseMounts.js +27 -0
  258. package/lib/commonjs/platforms/docker/parseMounts.js.map +1 -0
  259. package/lib/commonjs/platforms/docker/parsePortMappings.d.ts +8 -0
  260. package/lib/commonjs/platforms/docker/parsePortMappings.js +26 -0
  261. package/lib/commonjs/platforms/docker/parsePortMappings.js.map +1 -0
  262. package/lib/commonjs/platforms/docker/resolvePortMappings.d.ts +8 -0
  263. package/lib/commonjs/platforms/docker/resolvePortMappings.js +23 -0
  264. package/lib/commonjs/platforms/docker/resolvePortMappings.js.map +1 -0
  265. package/lib/commonjs/platforms/docker/writeComposeFile.d.ts +20 -0
  266. package/lib/commonjs/platforms/docker/writeComposeFile.js +44 -0
  267. package/lib/commonjs/platforms/docker/writeComposeFile.js.map +1 -0
  268. package/lib/commonjs/platforms/index.d.ts +3 -0
  269. package/lib/commonjs/platforms/index.js +35 -0
  270. package/lib/commonjs/platforms/index.js.map +1 -0
  271. package/lib/commonjs/platforms/types.d.ts +21 -0
  272. package/lib/commonjs/platforms/types.js +9 -0
  273. package/lib/commonjs/platforms/types.js.map +1 -0
  274. package/lib/esm/bin/qpq.d.ts +2 -0
  275. package/lib/esm/bin/qpq.js +4 -0
  276. package/lib/esm/bin/qpq.js.map +1 -0
  277. package/lib/esm/bin/qpqCdkApp.d.ts +1 -0
  278. package/lib/esm/bin/qpqCdkApp.js +6 -0
  279. package/lib/esm/bin/qpqCdkApp.js.map +1 -0
  280. package/lib/esm/cli/commandMenu.d.ts +2 -0
  281. package/lib/esm/cli/commandMenu.js +67 -0
  282. package/lib/esm/cli/commandMenu.js.map +1 -0
  283. package/lib/esm/cli/commandRegistry.d.ts +10 -0
  284. package/lib/esm/cli/commandRegistry.js +161 -0
  285. package/lib/esm/cli/commandRegistry.js.map +1 -0
  286. package/lib/esm/cli/index.d.ts +1 -0
  287. package/lib/esm/cli/index.js +2 -0
  288. package/lib/esm/cli/index.js.map +1 -0
  289. package/lib/esm/cli/runCli.d.ts +1 -0
  290. package/lib/esm/cli/runCli.js +73 -0
  291. package/lib/esm/cli/runCli.js.map +1 -0
  292. package/lib/esm/commands/checkCircular.d.ts +1 -0
  293. package/lib/esm/commands/checkCircular.js +55 -0
  294. package/lib/esm/commands/checkCircular.js.map +1 -0
  295. package/lib/esm/commands/clearResources.d.ts +1 -0
  296. package/lib/esm/commands/clearResources.js +23 -0
  297. package/lib/esm/commands/clearResources.js.map +1 -0
  298. package/lib/esm/commands/go.d.ts +1 -0
  299. package/lib/esm/commands/go.js +16 -0
  300. package/lib/esm/commands/go.js.map +1 -0
  301. package/lib/esm/commands/goDev.d.ts +1 -0
  302. package/lib/esm/commands/goDev.js +33 -0
  303. package/lib/esm/commands/goDev.js.map +1 -0
  304. package/lib/esm/commands/goDevApi.d.ts +1 -0
  305. package/lib/esm/commands/goDevApi.js +142 -0
  306. package/lib/esm/commands/goDevApi.js.map +1 -0
  307. package/lib/esm/commands/goDevWeb.d.ts +4 -0
  308. package/lib/esm/commands/goDevWeb.js +129 -0
  309. package/lib/esm/commands/goDevWeb.js.map +1 -0
  310. package/lib/esm/commands/goDocker.d.ts +1 -0
  311. package/lib/esm/commands/goDocker.js +29 -0
  312. package/lib/esm/commands/goDocker.js.map +1 -0
  313. package/lib/esm/commands/hooks.d.ts +1 -0
  314. package/lib/esm/commands/hooks.js +26 -0
  315. package/lib/esm/commands/hooks.js.map +1 -0
  316. package/lib/esm/commands/migrate.d.ts +1 -0
  317. package/lib/esm/commands/migrate.js +57 -0
  318. package/lib/esm/commands/migrate.js.map +1 -0
  319. package/lib/esm/commands/prep.d.ts +1 -0
  320. package/lib/esm/commands/prep.js +15 -0
  321. package/lib/esm/commands/prep.js.map +1 -0
  322. package/lib/esm/commands/publish.d.ts +4 -0
  323. package/lib/esm/commands/publish.js +38 -0
  324. package/lib/esm/commands/publish.js.map +1 -0
  325. package/lib/esm/commands/scriptBuild.d.ts +1 -0
  326. package/lib/esm/commands/scriptBuild.js +29 -0
  327. package/lib/esm/commands/scriptBuild.js.map +1 -0
  328. package/lib/esm/commands/scriptBuilderLayer.d.ts +1 -0
  329. package/lib/esm/commands/scriptBuilderLayer.js +34 -0
  330. package/lib/esm/commands/scriptBuilderLayer.js.map +1 -0
  331. package/lib/esm/commands/scriptNew.d.ts +1 -0
  332. package/lib/esm/commands/scriptNew.js +19 -0
  333. package/lib/esm/commands/scriptNew.js.map +1 -0
  334. package/lib/esm/commands/setup.d.ts +1 -0
  335. package/lib/esm/commands/setup.js +88 -0
  336. package/lib/esm/commands/setup.js.map +1 -0
  337. package/lib/esm/commands/synth.d.ts +1 -0
  338. package/lib/esm/commands/synth.js +73 -0
  339. package/lib/esm/commands/synth.js.map +1 -0
  340. package/lib/esm/commands/teardown.d.ts +1 -0
  341. package/lib/esm/commands/teardown.js +20 -0
  342. package/lib/esm/commands/teardown.js.map +1 -0
  343. package/lib/esm/index.d.ts +1 -0
  344. package/lib/esm/index.js +2 -0
  345. package/lib/esm/index.js.map +1 -0
  346. package/lib/esm/lib/args.d.ts +3 -0
  347. package/lib/esm/lib/args.js +25 -0
  348. package/lib/esm/lib/args.js.map +1 -0
  349. package/lib/esm/lib/circularImports.d.ts +3 -0
  350. package/lib/esm/lib/circularImports.js +61 -0
  351. package/lib/esm/lib/circularImports.js.map +1 -0
  352. package/lib/esm/lib/clearResourcesPlan.d.ts +15 -0
  353. package/lib/esm/lib/clearResourcesPlan.js +65 -0
  354. package/lib/esm/lib/clearResourcesPlan.js.map +1 -0
  355. package/lib/esm/lib/deployPrompts.d.ts +26 -0
  356. package/lib/esm/lib/deployPrompts.js +103 -0
  357. package/lib/esm/lib/deployPrompts.js.map +1 -0
  358. package/lib/esm/lib/devServerEntry.d.ts +22 -0
  359. package/lib/esm/lib/devServerEntry.js +127 -0
  360. package/lib/esm/lib/devServerEntry.js.map +1 -0
  361. package/lib/esm/lib/devServerPorts.d.ts +13 -0
  362. package/lib/esm/lib/devServerPorts.js +27 -0
  363. package/lib/esm/lib/devServerPorts.js.map +1 -0
  364. package/lib/esm/lib/discovery.d.ts +10 -0
  365. package/lib/esm/lib/discovery.js +40 -0
  366. package/lib/esm/lib/discovery.js.map +1 -0
  367. package/lib/esm/lib/getDefaultHookJobs.d.ts +2 -0
  368. package/lib/esm/lib/getDefaultHookJobs.js +4 -0
  369. package/lib/esm/lib/getDefaultHookJobs.js.map +1 -0
  370. package/lib/esm/lib/getDeployTargetLabel.d.ts +2 -0
  371. package/lib/esm/lib/getDeployTargetLabel.js +8 -0
  372. package/lib/esm/lib/getDeployTargetLabel.js.map +1 -0
  373. package/lib/esm/lib/goDockerMode.d.ts +6 -0
  374. package/lib/esm/lib/goDockerMode.js +19 -0
  375. package/lib/esm/lib/goDockerMode.js.map +1 -0
  376. package/lib/esm/lib/hooks.d.ts +9 -0
  377. package/lib/esm/lib/hooks.js +154 -0
  378. package/lib/esm/lib/hooks.js.map +1 -0
  379. package/lib/esm/lib/keepOtherDevServersFlag.d.ts +1 -0
  380. package/lib/esm/lib/keepOtherDevServersFlag.js +8 -0
  381. package/lib/esm/lib/keepOtherDevServersFlag.js.map +1 -0
  382. package/lib/esm/lib/killChildWithEscalation.d.ts +10 -0
  383. package/lib/esm/lib/killChildWithEscalation.js +29 -0
  384. package/lib/esm/lib/killChildWithEscalation.js.map +1 -0
  385. package/lib/esm/lib/killStaleListeners.d.ts +17 -0
  386. package/lib/esm/lib/killStaleListeners.js +210 -0
  387. package/lib/esm/lib/killStaleListeners.js.map +1 -0
  388. package/lib/esm/lib/packageRoot.d.ts +1 -0
  389. package/lib/esm/lib/packageRoot.js +14 -0
  390. package/lib/esm/lib/packageRoot.js.map +1 -0
  391. package/lib/esm/lib/prompts.d.ts +15 -0
  392. package/lib/esm/lib/prompts.js +28 -0
  393. package/lib/esm/lib/prompts.js.map +1 -0
  394. package/lib/esm/lib/qpqConfigs.d.ts +4 -0
  395. package/lib/esm/lib/qpqConfigs.js +21 -0
  396. package/lib/esm/lib/qpqConfigs.js.map +1 -0
  397. package/lib/esm/lib/resolveAppSelection.d.ts +6 -0
  398. package/lib/esm/lib/resolveAppSelection.js +45 -0
  399. package/lib/esm/lib/resolveAppSelection.js.map +1 -0
  400. package/lib/esm/lib/resolveDeployment.d.ts +14 -0
  401. package/lib/esm/lib/resolveDeployment.js +45 -0
  402. package/lib/esm/lib/resolveDeployment.js.map +1 -0
  403. package/lib/esm/lib/runCommand.d.ts +14 -0
  404. package/lib/esm/lib/runCommand.js +92 -0
  405. package/lib/esm/lib/runCommand.js.map +1 -0
  406. package/lib/esm/lib/runTasks.d.ts +15 -0
  407. package/lib/esm/lib/runTasks.js +108 -0
  408. package/lib/esm/lib/runTasks.js.map +1 -0
  409. package/lib/esm/lib/setupStep.d.ts +16 -0
  410. package/lib/esm/lib/setupStep.js +2 -0
  411. package/lib/esm/lib/setupStep.js.map +1 -0
  412. package/lib/esm/lib/timing.d.ts +2 -0
  413. package/lib/esm/lib/timing.js +6 -0
  414. package/lib/esm/lib/timing.js.map +1 -0
  415. package/lib/esm/lib/typeWatcher.d.ts +2 -0
  416. package/lib/esm/lib/typeWatcher.js +51 -0
  417. package/lib/esm/lib/typeWatcher.js.map +1 -0
  418. package/lib/esm/lib/userScriptBuilderLayer.d.ts +23 -0
  419. package/lib/esm/lib/userScriptBuilderLayer.js +65 -0
  420. package/lib/esm/lib/userScriptBuilderLayer.js.map +1 -0
  421. package/lib/esm/lib/userScriptTemplate.d.ts +6 -0
  422. package/lib/esm/lib/userScriptTemplate.js +39 -0
  423. package/lib/esm/lib/userScriptTemplate.js.map +1 -0
  424. package/lib/esm/lib/views.d.ts +2 -0
  425. package/lib/esm/lib/views.js +14 -0
  426. package/lib/esm/lib/views.js.map +1 -0
  427. package/lib/esm/lib/webAddressingEnv.d.ts +7 -0
  428. package/lib/esm/lib/webAddressingEnv.js +11 -0
  429. package/lib/esm/lib/webAddressingEnv.js.map +1 -0
  430. package/lib/esm/platforms/aws/awsCredentials.d.ts +1 -0
  431. package/lib/esm/platforms/aws/awsCredentials.js +15 -0
  432. package/lib/esm/platforms/aws/awsCredentials.js.map +1 -0
  433. package/lib/esm/platforms/aws/cdkApp.d.ts +3 -0
  434. package/lib/esm/platforms/aws/cdkApp.js +22 -0
  435. package/lib/esm/platforms/aws/cdkApp.js.map +1 -0
  436. package/lib/esm/platforms/aws/clearResources.d.ts +2 -0
  437. package/lib/esm/platforms/aws/clearResources.js +151 -0
  438. package/lib/esm/platforms/aws/clearResources.js.map +1 -0
  439. package/lib/esm/platforms/aws/go.d.ts +2 -0
  440. package/lib/esm/platforms/aws/go.js +115 -0
  441. package/lib/esm/platforms/aws/go.js.map +1 -0
  442. package/lib/esm/platforms/aws/goDocker.d.ts +3 -0
  443. package/lib/esm/platforms/aws/goDocker.js +441 -0
  444. package/lib/esm/platforms/aws/goDocker.js.map +1 -0
  445. package/lib/esm/platforms/aws/goDockerManifest.d.ts +44 -0
  446. package/lib/esm/platforms/aws/goDockerManifest.js +26 -0
  447. package/lib/esm/platforms/aws/goDockerManifest.js.map +1 -0
  448. package/lib/esm/platforms/aws/index.d.ts +2 -0
  449. package/lib/esm/platforms/aws/index.js +20 -0
  450. package/lib/esm/platforms/aws/index.js.map +1 -0
  451. package/lib/esm/platforms/aws/prepareDeployment.d.ts +3 -0
  452. package/lib/esm/platforms/aws/prepareDeployment.js +6 -0
  453. package/lib/esm/platforms/aws/prepareDeployment.js.map +1 -0
  454. package/lib/esm/platforms/aws/publish.d.ts +4 -0
  455. package/lib/esm/platforms/aws/publish.js +50 -0
  456. package/lib/esm/platforms/aws/publish.js.map +1 -0
  457. package/lib/esm/platforms/aws/remote.d.ts +11 -0
  458. package/lib/esm/platforms/aws/remote.js +89 -0
  459. package/lib/esm/platforms/aws/remote.js.map +1 -0
  460. package/lib/esm/platforms/aws/setup/awsSetupContext.d.ts +12 -0
  461. package/lib/esm/platforms/aws/setup/awsSetupContext.js +16 -0
  462. package/lib/esm/platforms/aws/setup/awsSetupContext.js.map +1 -0
  463. package/lib/esm/platforms/aws/setup/awsSetupSteps.d.ts +8 -0
  464. package/lib/esm/platforms/aws/setup/awsSetupSteps.js +31 -0
  465. package/lib/esm/platforms/aws/setup/awsSetupSteps.js.map +1 -0
  466. package/lib/esm/platforms/aws/setup/buildBucketNamesStep.d.ts +4 -0
  467. package/lib/esm/platforms/aws/setup/buildBucketNamesStep.js +62 -0
  468. package/lib/esm/platforms/aws/setup/buildBucketNamesStep.js.map +1 -0
  469. package/lib/esm/platforms/aws/setup/buildCdkBootstrapSteps.d.ts +5 -0
  470. package/lib/esm/platforms/aws/setup/buildCdkBootstrapSteps.js +24 -0
  471. package/lib/esm/platforms/aws/setup/buildCdkBootstrapSteps.js.map +1 -0
  472. package/lib/esm/platforms/aws/setup/buildGithubDeployRoleStep.d.ts +4 -0
  473. package/lib/esm/platforms/aws/setup/buildGithubDeployRoleStep.js +40 -0
  474. package/lib/esm/platforms/aws/setup/buildGithubDeployRoleStep.js.map +1 -0
  475. package/lib/esm/platforms/aws/setup/buildGithubOidcProviderStep.d.ts +4 -0
  476. package/lib/esm/platforms/aws/setup/buildGithubOidcProviderStep.js +40 -0
  477. package/lib/esm/platforms/aws/setup/buildGithubOidcProviderStep.js.map +1 -0
  478. package/lib/esm/platforms/aws/setup/buildHostedZonesStep.d.ts +4 -0
  479. package/lib/esm/platforms/aws/setup/buildHostedZonesStep.js +49 -0
  480. package/lib/esm/platforms/aws/setup/buildHostedZonesStep.js.map +1 -0
  481. package/lib/esm/platforms/aws/setup/buildIamCapabilityStep.d.ts +4 -0
  482. package/lib/esm/platforms/aws/setup/buildIamCapabilityStep.js +34 -0
  483. package/lib/esm/platforms/aws/setup/buildIamCapabilityStep.js.map +1 -0
  484. package/lib/esm/platforms/aws/setup/buildIdentityStep.d.ts +4 -0
  485. package/lib/esm/platforms/aws/setup/buildIdentityStep.js +26 -0
  486. package/lib/esm/platforms/aws/setup/buildIdentityStep.js.map +1 -0
  487. package/lib/esm/platforms/aws/setup/buildStackSteps.d.ts +5 -0
  488. package/lib/esm/platforms/aws/setup/buildStackSteps.js +17 -0
  489. package/lib/esm/platforms/aws/setup/buildStackSteps.js.map +1 -0
  490. package/lib/esm/platforms/aws/setup/describeStackStatus.d.ts +4 -0
  491. package/lib/esm/platforms/aws/setup/describeStackStatus.js +17 -0
  492. package/lib/esm/platforms/aws/setup/describeStackStatus.js.map +1 -0
  493. package/lib/esm/platforms/aws/setup/index.d.ts +1 -0
  494. package/lib/esm/platforms/aws/setup/index.js +2 -0
  495. package/lib/esm/platforms/aws/setup/index.js.map +1 -0
  496. package/lib/esm/platforms/aws/stacks.d.ts +7 -0
  497. package/lib/esm/platforms/aws/stacks.js +72 -0
  498. package/lib/esm/platforms/aws/stacks.js.map +1 -0
  499. package/lib/esm/platforms/aws/teardown.d.ts +2 -0
  500. package/lib/esm/platforms/aws/teardown.js +46 -0
  501. package/lib/esm/platforms/aws/teardown.js.map +1 -0
  502. package/lib/esm/platforms/aws/viewsSync.d.ts +3 -0
  503. package/lib/esm/platforms/aws/viewsSync.js +60 -0
  504. package/lib/esm/platforms/aws/viewsSync.js.map +1 -0
  505. package/lib/esm/platforms/docker/QpqDockerPlatformSettings.d.ts +10 -0
  506. package/lib/esm/platforms/docker/QpqDockerPlatformSettings.js +2 -0
  507. package/lib/esm/platforms/docker/QpqDockerPlatformSettings.js.map +1 -0
  508. package/lib/esm/platforms/docker/getContainerPorts.d.ts +4 -0
  509. package/lib/esm/platforms/docker/getContainerPorts.js +8 -0
  510. package/lib/esm/platforms/docker/getContainerPorts.js.map +1 -0
  511. package/lib/esm/platforms/docker/getDefaultPortMappings.d.ts +3 -0
  512. package/lib/esm/platforms/docker/getDefaultPortMappings.js +6 -0
  513. package/lib/esm/platforms/docker/getDefaultPortMappings.js.map +1 -0
  514. package/lib/esm/platforms/docker/getDockerPlatformSettings.d.ts +14 -0
  515. package/lib/esm/platforms/docker/getDockerPlatformSettings.js +34 -0
  516. package/lib/esm/platforms/docker/getDockerPlatformSettings.js.map +1 -0
  517. package/lib/esm/platforms/docker/getImageName.d.ts +6 -0
  518. package/lib/esm/platforms/docker/getImageName.js +6 -0
  519. package/lib/esm/platforms/docker/getImageName.js.map +1 -0
  520. package/lib/esm/platforms/docker/go.d.ts +2 -0
  521. package/lib/esm/platforms/docker/go.js +242 -0
  522. package/lib/esm/platforms/docker/go.js.map +1 -0
  523. package/lib/esm/platforms/docker/index.d.ts +2 -0
  524. package/lib/esm/platforms/docker/index.js +31 -0
  525. package/lib/esm/platforms/docker/index.js.map +1 -0
  526. package/lib/esm/platforms/docker/parseMounts.d.ts +7 -0
  527. package/lib/esm/platforms/docker/parseMounts.js +23 -0
  528. package/lib/esm/platforms/docker/parseMounts.js.map +1 -0
  529. package/lib/esm/platforms/docker/parsePortMappings.d.ts +8 -0
  530. package/lib/esm/platforms/docker/parsePortMappings.js +21 -0
  531. package/lib/esm/platforms/docker/parsePortMappings.js.map +1 -0
  532. package/lib/esm/platforms/docker/resolvePortMappings.d.ts +8 -0
  533. package/lib/esm/platforms/docker/resolvePortMappings.js +18 -0
  534. package/lib/esm/platforms/docker/resolvePortMappings.js.map +1 -0
  535. package/lib/esm/platforms/docker/writeComposeFile.d.ts +20 -0
  536. package/lib/esm/platforms/docker/writeComposeFile.js +37 -0
  537. package/lib/esm/platforms/docker/writeComposeFile.js.map +1 -0
  538. package/lib/esm/platforms/index.d.ts +3 -0
  539. package/lib/esm/platforms/index.js +17 -0
  540. package/lib/esm/platforms/index.js.map +1 -0
  541. package/lib/esm/platforms/types.d.ts +21 -0
  542. package/lib/esm/platforms/types.js +6 -0
  543. package/lib/esm/platforms/types.js.map +1 -0
  544. package/package.json +71 -3
  545. package/templates/user-script/README.md +28 -0
  546. package/templates/user-script/gitignore +2 -0
  547. package/templates/user-script/package.json +16 -0
  548. package/templates/user-script/src/main.ts +15 -0
  549. package/templates/user-script/tsconfig.json +12 -0
@@ -0,0 +1,29 @@
1
+ // Above the dev server's 5s worst-case shutdown budget, below docker's 10s
2
+ // default stop grace, so a container stop still exits cleanly rather than
3
+ // being SIGKILLed by docker mid-escalation.
4
+ const DEFAULT_KILL_GRACE_MS = 6000;
5
+ /**
6
+ * SIGTERM the child, resolve once it has actually exited, and SIGKILL it if it
7
+ * has not gone within the grace window.
8
+ *
9
+ * Resolves rather than rejects on escalation: the caller's next move is the
10
+ * same either way (start the replacement), and a rejection would only give
11
+ * every call site a catch to write.
12
+ */
13
+ export const killChildWithEscalation = (child, graceMs = DEFAULT_KILL_GRACE_MS) => {
14
+ if (child.exitCode !== null || child.signalCode !== null) {
15
+ return Promise.resolve();
16
+ }
17
+ return new Promise((resolve) => {
18
+ const timer = setTimeout(() => {
19
+ console.warn(`Dev server did not exit within ${graceMs}ms — sending SIGKILL.`);
20
+ child.kill('SIGKILL');
21
+ }, graceMs);
22
+ child.once('exit', () => {
23
+ clearTimeout(timer);
24
+ resolve();
25
+ });
26
+ child.kill('SIGTERM');
27
+ });
28
+ };
29
+ //# sourceMappingURL=killChildWithEscalation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"killChildWithEscalation.js","sourceRoot":"","sources":["../../../src/lib/killChildWithEscalation.ts"],"names":[],"mappings":"AAWA,2EAA2E;AAC3E,0EAA0E;AAC1E,4CAA4C;AAC5C,MAAM,qBAAqB,GAAG,IAAI,CAAC;AAEnC;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,KAAmB,EAAE,OAAO,GAAG,qBAAqB,EAAiB,EAAE;IAC7G,IAAI,KAAK,CAAC,QAAQ,KAAK,IAAI,IAAI,KAAK,CAAC,UAAU,KAAK,IAAI,EAAE,CAAC;QACzD,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;IAC3B,CAAC;IAED,OAAO,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;QACnC,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;YAC5B,OAAO,CAAC,IAAI,CAAC,kCAAkC,OAAO,uBAAuB,CAAC,CAAC;YAC/E,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACxB,CAAC,EAAE,OAAO,CAAC,CAAC;QAEZ,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE;YACtB,YAAY,CAAC,KAAK,CAAC,CAAC;YACpB,OAAO,EAAE,CAAC;QACZ,CAAC,CAAC,CAAC;QAEH,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IACxB,CAAC,CAAC,CAAC;AACL,CAAC,CAAC","sourcesContent":["// Stopping the dev server child, with a hard backstop.\n//\n// The dev server now runs an ordered shutdown on SIGTERM (drain in-flight\n// work, then checkpoint the stores) instead of dying instantly. That is the\n// point - it is what stops a save-triggered restart eating a queue message\n// mid-story - but it means a bare `child.kill()` followed by waiting for exit\n// can now wait forever if a teardown wedges. Without escalation this would\n// trade a data-loss bug for a hung-restart bug, and the next launch would find\n// its ports still held.\nimport { ChildProcess } from 'child_process';\n\n// Above the dev server's 5s worst-case shutdown budget, below docker's 10s\n// default stop grace, so a container stop still exits cleanly rather than\n// being SIGKILLed by docker mid-escalation.\nconst DEFAULT_KILL_GRACE_MS = 6000;\n\n/**\n * SIGTERM the child, resolve once it has actually exited, and SIGKILL it if it\n * has not gone within the grace window.\n *\n * Resolves rather than rejects on escalation: the caller's next move is the\n * same either way (start the replacement), and a rejection would only give\n * every call site a catch to write.\n */\nexport const killChildWithEscalation = (child: ChildProcess, graceMs = DEFAULT_KILL_GRACE_MS): Promise<void> => {\n if (child.exitCode !== null || child.signalCode !== null) {\n return Promise.resolve();\n }\n\n return new Promise<void>((resolve) => {\n const timer = setTimeout(() => {\n console.warn(`Dev server did not exit within ${graceMs}ms — sending SIGKILL.`);\n child.kill('SIGKILL');\n }, graceMs);\n\n child.once('exit', () => {\n clearTimeout(timer);\n resolve();\n });\n\n child.kill('SIGTERM');\n });\n};\n"]}
@@ -0,0 +1,17 @@
1
+ export declare const isQpqCliCommand: (command: string) => boolean;
2
+ export declare const killOtherQpqDevProcesses: (root: string) => void;
3
+ /**
4
+ * Say what is holding these ports, without touching it.
5
+ *
6
+ * The other half of --keep-other-dev-servers: sparing a sibling checkout's dev
7
+ * server means this one cannot bind, and an unexplained EADDRINUSE is a worse
8
+ * experience than the silent kill it replaces. Naming the pid and the command
9
+ * turns "it just died" into something you can act on.
10
+ *
11
+ * Worded as a prediction, not a fact, because it IS one: this runs before the
12
+ * bundle step, so by the time anything binds - seconds later - the holder may
13
+ * well have gone. Stating "port in use" and then starting cleanly reads like
14
+ * the warning was wrong.
15
+ */
16
+ export declare const reportPortHolders: (ports: number[]) => void;
17
+ export declare const killStaleListeners: (ports: number[], isOurs: (command: string) => boolean) => void;
@@ -0,0 +1,210 @@
1
+ // Pre-start sweep shared by the dev-server commands: a previous run whose
2
+ // wrapper died without killing its listener (closed terminal, SIGKILL) leaves
3
+ // an orphaned process holding a dev port, and the next launch dies with
4
+ // EADDRINUSE. Before starting, kill any listener on the given ports whose
5
+ // command line matches `isOurs`. Anything else on the ports is left alone
6
+ // and reported — it's not ours.
7
+ import { execSync } from 'child_process';
8
+ import fs from 'fs';
9
+ import path from 'path';
10
+ // Matches any invocation of the qpq CLI itself, regardless of how it was
11
+ // launched: `node node_modules/.bin/qpq ...` (the npm-script shim, which has
12
+ // no .js extension), a direct `node .../lib/commonjs/bin/qpq.js` call, a
13
+ // global `qpq` shebang script, etc. Checks each whitespace-separated token's
14
+ // basename (extension stripped) rather than a fixed substring like
15
+ // 'bin/qpq.js', which only matches the last of those forms.
16
+ export const isQpqCliCommand = (command) => command
17
+ .trim()
18
+ .split(/\s+/)
19
+ .some((token) => {
20
+ const base = path.basename(token);
21
+ const withoutExt = base.endsWith('.js') ? base.slice(0, -3) : base;
22
+ return withoutExt === 'qpq';
23
+ });
24
+ // SIGTERM only requests termination — the caller (about to bind this same
25
+ // process's ports itself) needs it actually gone first. A stale dev server
26
+ // can be mid-startup when killed (still resolving config, not yet bound to
27
+ // every port it eventually binds) and keep running for a bit past the
28
+ // signal, going on to bind a LATER port — waiting for just the one port that
29
+ // matched isn't enough; wait for the whole pid to disappear so it can't bind
30
+ // anything else afterward. Poll synchronously (this whole sweep runs before
31
+ // anything async starts) via `kill(pid, 0)` — reliable and fast here because
32
+ // these are unrelated, previously-orphaned processes, not children of this
33
+ // one (a real child can sit as a zombie answering `kill(pid, 0)` until this
34
+ // process's own event loop reaps it, which a tight sync loop would starve;
35
+ // doesn't apply to a process we didn't spawn).
36
+ //
37
+ // The default covers the dev server's graceful shutdown (drain in-flight work,
38
+ // then checkpoint the stores) with room to spare — it used to be 3s, which was
39
+ // fine when the server died instantly and is not now. Returns whether the pid
40
+ // actually went, because a caller about to bind these ports has to escalate
41
+ // rather than hope: giving up while the old server still holds 8080 is exactly
42
+ // the EADDRINUSE this file exists to prevent.
43
+ const waitForPidGone = (pid, timeoutMs = 8000) => {
44
+ const deadline = Date.now() + timeoutMs;
45
+ while (Date.now() < deadline) {
46
+ try {
47
+ process.kill(pid, 0);
48
+ }
49
+ catch {
50
+ return true; // throws once the pid no longer exists
51
+ }
52
+ execSync('sleep 0.05');
53
+ }
54
+ return false;
55
+ };
56
+ // Last resort for a process that ignored, or wedged during, its graceful stop.
57
+ const killPidHard = (pid) => {
58
+ console.warn(`Process ${pid} did not exit gracefully — sending SIGKILL.`);
59
+ try {
60
+ process.kill(pid, 'SIGKILL');
61
+ }
62
+ catch {
63
+ return; // raced us and exited after all
64
+ }
65
+ waitForPidGone(pid, 2000);
66
+ };
67
+ // realpath'd: lsof reports the canonical path (e.g. /private/tmp on macOS,
68
+ // where /tmp is a symlink), so comparing against a caller-supplied root
69
+ // verbatim would false-negative whenever any component of the repo path is
70
+ // itself a symlink (a symlinked home directory, an NFS mount, etc).
71
+ const getProcessCwd = (pid) => {
72
+ try {
73
+ const line = execSync(`lsof -a -p ${pid} -d cwd -Fn`, { stdio: ['ignore', 'pipe', 'ignore'] })
74
+ .toString()
75
+ .split('\n')
76
+ .find((l) => l.startsWith('n'));
77
+ return line ? fs.realpathSync(line.slice(1)) : null;
78
+ }
79
+ catch {
80
+ return null; // pid gone, or we don't have permission to inspect it
81
+ }
82
+ };
83
+ // The sweep below must never target this process's own wrappers: launched as
84
+ // `npx qpq go:dev:api` (or via any shell whose -c string names qpq), the
85
+ // ancestor chain (`sh -c "npx ... qpq ..."`, `npm exec qpq ...`) matches
86
+ // isQpqCliCommand and shares our cwd, so excluding just process.pid isn't
87
+ // enough — SIGINTing an ancestor tears down our own tree. Walk ppid to the
88
+ // top and exclude the whole chain.
89
+ const getOwnAncestorPids = () => {
90
+ const ancestors = new Set();
91
+ let pid = process.pid;
92
+ while (pid > 1 && !ancestors.has(pid)) {
93
+ ancestors.add(pid);
94
+ try {
95
+ pid = Number(execSync(`ps -o ppid= -p ${pid}`, { stdio: ['ignore', 'pipe', 'ignore'] })
96
+ .toString()
97
+ .trim());
98
+ }
99
+ catch {
100
+ break;
101
+ }
102
+ }
103
+ return ancestors;
104
+ };
105
+ // killStaleListeners only sees processes currently BOUND to one of the given
106
+ // ports — it can't catch a still-running `qpq go:dev*` watcher whose spawned
107
+ // dev-server child already died (a crash, or us killing just the child):
108
+ // the watcher itself holds no port at that moment, so it's invisible to a
109
+ // port scan, yet it's still alive and can spawn a fresh child — and bind a
110
+ // port — moments later, racing whatever we're about to start. Close that gap
111
+ // by finding any OTHER qpq CLI process rooted in the same repo checkout
112
+ // (matched by cwd, not by port or command-line args, which vary by how it
113
+ // was invoked) and killing it outright, regardless of what it currently has
114
+ // bound. SIGINT (not SIGTERM) so goDevApiCommand/goDevWebCommand's own
115
+ // handler runs and tears down its child cleanly rather than orphaning it.
116
+ export const killOtherQpqDevProcesses = (root) => {
117
+ const resolvedRoot = fs.realpathSync(root);
118
+ const ownPids = getOwnAncestorPids();
119
+ let lines = [];
120
+ try {
121
+ lines = execSync('ps -axo pid=,command=', { stdio: ['ignore', 'pipe', 'ignore'] })
122
+ .toString()
123
+ .split('\n');
124
+ }
125
+ catch {
126
+ return;
127
+ }
128
+ for (const line of lines) {
129
+ const trimmed = line.trim();
130
+ if (!trimmed)
131
+ continue;
132
+ const spaceIndex = trimmed.indexOf(' ');
133
+ if (spaceIndex === -1)
134
+ continue;
135
+ const pid = Number(trimmed.slice(0, spaceIndex));
136
+ const command = trimmed.slice(spaceIndex + 1).trim();
137
+ if (!pid || ownPids.has(pid) || !isQpqCliCommand(command))
138
+ continue;
139
+ if (getProcessCwd(pid) !== resolvedRoot)
140
+ continue;
141
+ console.log(`Killing other qpq dev process for this repo (pid ${pid}): ${command}`);
142
+ process.kill(pid, 'SIGINT');
143
+ if (!waitForPidGone(pid)) {
144
+ killPidHard(pid);
145
+ }
146
+ }
147
+ };
148
+ // Whatever is currently listening on a port, as pid + command line. Empty when
149
+ // the port is free, or when lsof is unavailable.
150
+ const getPortListeners = (port) => {
151
+ let pids = [];
152
+ try {
153
+ pids = execSync(`lsof -t -iTCP:${port} -sTCP:LISTEN`, {
154
+ stdio: ['ignore', 'pipe', 'ignore'],
155
+ })
156
+ .toString()
157
+ .split('\n')
158
+ .map((line) => Number(line.trim()))
159
+ .filter(Boolean);
160
+ }
161
+ catch {
162
+ return []; // lsof exits non-zero when nothing is listening
163
+ }
164
+ return pids.flatMap((pid) => {
165
+ try {
166
+ return [{ pid, command: execSync(`ps -p ${pid} -o command=`).toString().trim() }];
167
+ }
168
+ catch {
169
+ return []; // already gone
170
+ }
171
+ });
172
+ };
173
+ /**
174
+ * Say what is holding these ports, without touching it.
175
+ *
176
+ * The other half of --keep-other-dev-servers: sparing a sibling checkout's dev
177
+ * server means this one cannot bind, and an unexplained EADDRINUSE is a worse
178
+ * experience than the silent kill it replaces. Naming the pid and the command
179
+ * turns "it just died" into something you can act on.
180
+ *
181
+ * Worded as a prediction, not a fact, because it IS one: this runs before the
182
+ * bundle step, so by the time anything binds - seconds later - the holder may
183
+ * well have gone. Stating "port in use" and then starting cleanly reads like
184
+ * the warning was wrong.
185
+ */
186
+ export const reportPortHolders = (ports) => {
187
+ for (const port of ports) {
188
+ for (const { pid, command } of getPortListeners(port)) {
189
+ console.warn(`Port ${port} is currently held by pid ${pid}: ${command}`);
190
+ console.warn(` Starting anyway. If it still holds port ${port} once this server binds, startup will fail with EADDRINUSE.`);
191
+ }
192
+ }
193
+ };
194
+ export const killStaleListeners = (ports, isOurs) => {
195
+ for (const port of ports) {
196
+ for (const { pid, command } of getPortListeners(port)) {
197
+ if (isOurs(command)) {
198
+ console.log(`Killing stale dev server on port ${port} (pid ${pid})`);
199
+ process.kill(pid);
200
+ if (!waitForPidGone(pid)) {
201
+ killPidHard(pid);
202
+ }
203
+ }
204
+ else {
205
+ console.warn(`Port ${port} is in use by an unrelated process (pid ${pid}: ${command}) — not killing it.`);
206
+ }
207
+ }
208
+ }
209
+ };
210
+ //# sourceMappingURL=killStaleListeners.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"killStaleListeners.js","sourceRoot":"","sources":["../../../src/lib/killStaleListeners.ts"],"names":[],"mappings":"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","sourcesContent":["// Pre-start sweep shared by the dev-server commands: a previous run whose\n// wrapper died without killing its listener (closed terminal, SIGKILL) leaves\n// an orphaned process holding a dev port, and the next launch dies with\n// EADDRINUSE. Before starting, kill any listener on the given ports whose\n// command line matches `isOurs`. Anything else on the ports is left alone\n// and reported — it's not ours.\nimport { execSync } from 'child_process';\nimport fs from 'fs';\nimport path from 'path';\n\n// Matches any invocation of the qpq CLI itself, regardless of how it was\n// launched: `node node_modules/.bin/qpq ...` (the npm-script shim, which has\n// no .js extension), a direct `node .../lib/commonjs/bin/qpq.js` call, a\n// global `qpq` shebang script, etc. Checks each whitespace-separated token's\n// basename (extension stripped) rather than a fixed substring like\n// 'bin/qpq.js', which only matches the last of those forms.\nexport const isQpqCliCommand = (command: string): boolean =>\n command\n .trim()\n .split(/\\s+/)\n .some((token) => {\n const base = path.basename(token);\n const withoutExt = base.endsWith('.js') ? base.slice(0, -3) : base;\n return withoutExt === 'qpq';\n });\n\n// SIGTERM only requests termination — the caller (about to bind this same\n// process's ports itself) needs it actually gone first. A stale dev server\n// can be mid-startup when killed (still resolving config, not yet bound to\n// every port it eventually binds) and keep running for a bit past the\n// signal, going on to bind a LATER port — waiting for just the one port that\n// matched isn't enough; wait for the whole pid to disappear so it can't bind\n// anything else afterward. Poll synchronously (this whole sweep runs before\n// anything async starts) via `kill(pid, 0)` — reliable and fast here because\n// these are unrelated, previously-orphaned processes, not children of this\n// one (a real child can sit as a zombie answering `kill(pid, 0)` until this\n// process's own event loop reaps it, which a tight sync loop would starve;\n// doesn't apply to a process we didn't spawn).\n//\n// The default covers the dev server's graceful shutdown (drain in-flight work,\n// then checkpoint the stores) with room to spare — it used to be 3s, which was\n// fine when the server died instantly and is not now. Returns whether the pid\n// actually went, because a caller about to bind these ports has to escalate\n// rather than hope: giving up while the old server still holds 8080 is exactly\n// the EADDRINUSE this file exists to prevent.\nconst waitForPidGone = (pid: number, timeoutMs = 8000): boolean => {\n const deadline = Date.now() + timeoutMs;\n while (Date.now() < deadline) {\n try {\n process.kill(pid, 0);\n } catch {\n return true; // throws once the pid no longer exists\n }\n execSync('sleep 0.05');\n }\n\n return false;\n};\n\n// Last resort for a process that ignored, or wedged during, its graceful stop.\nconst killPidHard = (pid: number): void => {\n console.warn(`Process ${pid} did not exit gracefully — sending SIGKILL.`);\n try {\n process.kill(pid, 'SIGKILL');\n } catch {\n return; // raced us and exited after all\n }\n waitForPidGone(pid, 2000);\n};\n\n// realpath'd: lsof reports the canonical path (e.g. /private/tmp on macOS,\n// where /tmp is a symlink), so comparing against a caller-supplied root\n// verbatim would false-negative whenever any component of the repo path is\n// itself a symlink (a symlinked home directory, an NFS mount, etc).\nconst getProcessCwd = (pid: number): string | null => {\n try {\n const line = execSync(`lsof -a -p ${pid} -d cwd -Fn`, { stdio: ['ignore', 'pipe', 'ignore'] })\n .toString()\n .split('\\n')\n .find((l) => l.startsWith('n'));\n return line ? fs.realpathSync(line.slice(1)) : null;\n } catch {\n return null; // pid gone, or we don't have permission to inspect it\n }\n};\n\n// The sweep below must never target this process's own wrappers: launched as\n// `npx qpq go:dev:api` (or via any shell whose -c string names qpq), the\n// ancestor chain (`sh -c \"npx ... qpq ...\"`, `npm exec qpq ...`) matches\n// isQpqCliCommand and shares our cwd, so excluding just process.pid isn't\n// enough — SIGINTing an ancestor tears down our own tree. Walk ppid to the\n// top and exclude the whole chain.\nconst getOwnAncestorPids = (): Set<number> => {\n const ancestors = new Set<number>();\n let pid = process.pid;\n while (pid > 1 && !ancestors.has(pid)) {\n ancestors.add(pid);\n try {\n pid = Number(\n execSync(`ps -o ppid= -p ${pid}`, { stdio: ['ignore', 'pipe', 'ignore'] })\n .toString()\n .trim(),\n );\n } catch {\n break;\n }\n }\n return ancestors;\n};\n\n// killStaleListeners only sees processes currently BOUND to one of the given\n// ports — it can't catch a still-running `qpq go:dev*` watcher whose spawned\n// dev-server child already died (a crash, or us killing just the child):\n// the watcher itself holds no port at that moment, so it's invisible to a\n// port scan, yet it's still alive and can spawn a fresh child — and bind a\n// port — moments later, racing whatever we're about to start. Close that gap\n// by finding any OTHER qpq CLI process rooted in the same repo checkout\n// (matched by cwd, not by port or command-line args, which vary by how it\n// was invoked) and killing it outright, regardless of what it currently has\n// bound. SIGINT (not SIGTERM) so goDevApiCommand/goDevWebCommand's own\n// handler runs and tears down its child cleanly rather than orphaning it.\nexport const killOtherQpqDevProcesses = (root: string): void => {\n const resolvedRoot = fs.realpathSync(root);\n const ownPids = getOwnAncestorPids();\n\n let lines: string[] = [];\n try {\n lines = execSync('ps -axo pid=,command=', { stdio: ['ignore', 'pipe', 'ignore'] })\n .toString()\n .split('\\n');\n } catch {\n return;\n }\n\n for (const line of lines) {\n const trimmed = line.trim();\n if (!trimmed) continue;\n\n const spaceIndex = trimmed.indexOf(' ');\n if (spaceIndex === -1) continue;\n\n const pid = Number(trimmed.slice(0, spaceIndex));\n const command = trimmed.slice(spaceIndex + 1).trim();\n\n if (!pid || ownPids.has(pid) || !isQpqCliCommand(command)) continue;\n if (getProcessCwd(pid) !== resolvedRoot) continue;\n\n console.log(`Killing other qpq dev process for this repo (pid ${pid}): ${command}`);\n process.kill(pid, 'SIGINT');\n if (!waitForPidGone(pid)) {\n killPidHard(pid);\n }\n }\n};\n\n// Whatever is currently listening on a port, as pid + command line. Empty when\n// the port is free, or when lsof is unavailable.\nconst getPortListeners = (port: number): { pid: number; command: string }[] => {\n let pids: number[] = [];\n try {\n pids = execSync(`lsof -t -iTCP:${port} -sTCP:LISTEN`, {\n stdio: ['ignore', 'pipe', 'ignore'],\n })\n .toString()\n .split('\\n')\n .map((line) => Number(line.trim()))\n .filter(Boolean);\n } catch {\n return []; // lsof exits non-zero when nothing is listening\n }\n\n return pids.flatMap((pid) => {\n try {\n return [{ pid, command: execSync(`ps -p ${pid} -o command=`).toString().trim() }];\n } catch {\n return []; // already gone\n }\n });\n};\n\n/**\n * Say what is holding these ports, without touching it.\n *\n * The other half of --keep-other-dev-servers: sparing a sibling checkout's dev\n * server means this one cannot bind, and an unexplained EADDRINUSE is a worse\n * experience than the silent kill it replaces. Naming the pid and the command\n * turns \"it just died\" into something you can act on.\n *\n * Worded as a prediction, not a fact, because it IS one: this runs before the\n * bundle step, so by the time anything binds - seconds later - the holder may\n * well have gone. Stating \"port in use\" and then starting cleanly reads like\n * the warning was wrong.\n */\nexport const reportPortHolders = (ports: number[]): void => {\n for (const port of ports) {\n for (const { pid, command } of getPortListeners(port)) {\n console.warn(`Port ${port} is currently held by pid ${pid}: ${command}`);\n console.warn(` Starting anyway. If it still holds port ${port} once this server binds, startup will fail with EADDRINUSE.`);\n }\n }\n};\n\nexport const killStaleListeners = (ports: number[], isOurs: (command: string) => boolean): void => {\n for (const port of ports) {\n for (const { pid, command } of getPortListeners(port)) {\n if (isOurs(command)) {\n console.log(`Killing stale dev server on port ${port} (pid ${pid})`);\n process.kill(pid);\n if (!waitForPidGone(pid)) {\n killPidHard(pid);\n }\n } else {\n console.warn(`Port ${port} is in use by an unrelated process (pid ${pid}: ${command}) — not killing it.`);\n }\n }\n }\n};\n"]}
@@ -0,0 +1 @@
1
+ export declare const getOwnPackageRoot: () => string;
@@ -0,0 +1,14 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+ // This package's root (works from src under ts-node and from lib/commonjs).
4
+ export const getOwnPackageRoot = () => {
5
+ let dir = __dirname;
6
+ while (!fs.existsSync(path.join(dir, 'package.json'))) {
7
+ const parent = path.dirname(dir);
8
+ if (parent === dir)
9
+ throw new Error('Could not locate the @qpqjs/cli package root');
10
+ dir = parent;
11
+ }
12
+ return dir;
13
+ };
14
+ //# sourceMappingURL=packageRoot.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"packageRoot.js","sourceRoot":"","sources":["../../../src/lib/packageRoot.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,4EAA4E;AAC5E,MAAM,CAAC,MAAM,iBAAiB,GAAG,GAAW,EAAE;IAC5C,IAAI,GAAG,GAAG,SAAS,CAAC;IACpB,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC,EAAE,CAAC;QACtD,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QACjC,IAAI,MAAM,KAAK,GAAG;YAAE,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAC;QACpF,GAAG,GAAG,MAAM,CAAC;IACf,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC,CAAC","sourcesContent":["import fs from 'fs';\nimport path from 'path';\n\n// This package's root (works from src under ts-node and from lib/commonjs).\nexport const getOwnPackageRoot = (): string => {\n let dir = __dirname;\n while (!fs.existsSync(path.join(dir, 'package.json'))) {\n const parent = path.dirname(dir);\n if (parent === dir) throw new Error('Could not locate the @qpqjs/cli package root');\n dir = parent;\n }\n return dir;\n};\n"]}
@@ -0,0 +1,15 @@
1
+ export declare const promptSelect: (message: string, choices: string[], defaultChoice?: string) => Promise<string>;
2
+ export declare const promptSelectDetailed: <T>(message: string, choices: {
3
+ name: string;
4
+ value: T;
5
+ short?: string;
6
+ description?: string;
7
+ }[]) => Promise<T>;
8
+ export declare const promptYesNo: (message: string) => Promise<boolean>;
9
+ export declare const promptText: (message: string) => Promise<string>;
10
+ export declare const promptCheckbox: <T>(message: string, choices: {
11
+ name: string;
12
+ value: T;
13
+ checked?: boolean;
14
+ description?: string;
15
+ }[]) => Promise<T[]>;
@@ -0,0 +1,28 @@
1
+ // Present a single-choice list prompt and return the selected value.
2
+ // @inquirer/prompts is imported lazily so commands only pay for it when
3
+ // actually prompting.
4
+ export const promptSelect = async (message, choices, defaultChoice) => {
5
+ const { select } = await import('@inquirer/prompts');
6
+ return select({ message, choices, default: defaultChoice });
7
+ };
8
+ // A single-choice list prompt over labelled values; a choice's optional
9
+ // `short` replaces its name in the answer line once picked, and its optional
10
+ // `description` renders under the list while it is highlighted.
11
+ export const promptSelectDetailed = async (message, choices) => {
12
+ const { select } = await import('@inquirer/prompts');
13
+ return select({ message, choices });
14
+ };
15
+ // A yes/no list prompt, returning true for "Yes".
16
+ export const promptYesNo = async (message) => (await promptSelect(message, ['No', 'Yes'])) === 'Yes';
17
+ // A free-text prompt — used where a y/n is too easy to fat-finger (destructive
18
+ // confirmations that require typing the target name back).
19
+ export const promptText = async (message) => {
20
+ const { input } = await import('@inquirer/prompts');
21
+ return input({ message });
22
+ };
23
+ // A multi-select checkbox prompt over labelled values; `checked` preselects a choice.
24
+ export const promptCheckbox = async (message, choices) => {
25
+ const { checkbox } = await import('@inquirer/prompts');
26
+ return checkbox({ message, choices });
27
+ };
28
+ //# sourceMappingURL=prompts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompts.js","sourceRoot":"","sources":["../../../src/lib/prompts.ts"],"names":[],"mappings":"AAAA,qEAAqE;AACrE,wEAAwE;AACxE,sBAAsB;AACtB,MAAM,CAAC,MAAM,YAAY,GAAG,KAAK,EAAE,OAAe,EAAE,OAAiB,EAAE,aAAsB,EAAmB,EAAE;IAChH,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,MAAM,CAAC,mBAAmB,CAAC,CAAC;IACrD,OAAO,MAAM,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,CAAC,CAAC;AAC9D,CAAC,CAAC;AAEF,wEAAwE;AACxE,6EAA6E;AAC7E,gEAAgE;AAChE,MAAM,CAAC,MAAM,oBAAoB,GAAG,KAAK,EACvC,OAAe,EACf,OAA2E,EAC/D,EAAE;IACd,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,MAAM,CAAC,mBAAmB,CAAC,CAAC;IACrD,OAAO,MAAM,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;AACtC,CAAC,CAAC;AAEF,kDAAkD;AAClD,MAAM,CAAC,MAAM,WAAW,GAAG,KAAK,EAAE,OAAe,EAAoB,EAAE,CAAC,CAAC,MAAM,YAAY,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,KAAK,KAAK,CAAC;AAE/H,+EAA+E;AAC/E,2DAA2D;AAC3D,MAAM,CAAC,MAAM,UAAU,GAAG,KAAK,EAAE,OAAe,EAAmB,EAAE;IACnE,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,MAAM,CAAC,mBAAmB,CAAC,CAAC;IACpD,OAAO,KAAK,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC;AAC5B,CAAC,CAAC;AAEF,sFAAsF;AACtF,MAAM,CAAC,MAAM,cAAc,GAAG,KAAK,EACjC,OAAe,EACf,OAA8E,EAChE,EAAE;IAChB,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,MAAM,CAAC,mBAAmB,CAAC,CAAC;IACvD,OAAO,QAAQ,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;AACxC,CAAC,CAAC","sourcesContent":["// Present a single-choice list prompt and return the selected value.\n// @inquirer/prompts is imported lazily so commands only pay for it when\n// actually prompting.\nexport const promptSelect = async (message: string, choices: string[], defaultChoice?: string): Promise<string> => {\n const { select } = await import('@inquirer/prompts');\n return select({ message, choices, default: defaultChoice });\n};\n\n// A single-choice list prompt over labelled values; a choice's optional\n// `short` replaces its name in the answer line once picked, and its optional\n// `description` renders under the list while it is highlighted.\nexport const promptSelectDetailed = async <T>(\n message: string,\n choices: { name: string; value: T; short?: string; description?: string }[],\n): Promise<T> => {\n const { select } = await import('@inquirer/prompts');\n return select({ message, choices });\n};\n\n// A yes/no list prompt, returning true for \"Yes\".\nexport const promptYesNo = async (message: string): Promise<boolean> => (await promptSelect(message, ['No', 'Yes'])) === 'Yes';\n\n// A free-text prompt — used where a y/n is too easy to fat-finger (destructive\n// confirmations that require typing the target name back).\nexport const promptText = async (message: string): Promise<string> => {\n const { input } = await import('@inquirer/prompts');\n return input({ message });\n};\n\n// A multi-select checkbox prompt over labelled values; `checked` preselects a choice.\nexport const promptCheckbox = async <T>(\n message: string,\n choices: { name: string; value: T; checked?: boolean; description?: string }[],\n): Promise<T[]> => {\n const { checkbox } = await import('@inquirer/prompts');\n return checkbox({ message, choices });\n};\n"]}
@@ -0,0 +1,4 @@
1
+ import { type QPQConfig } from '@qpqjs/core';
2
+ export declare const loadServiceQpqConfig: (appName: string, service: string) => QPQConfig;
3
+ export declare const getAppPrefix: (appName: string) => string;
4
+ export declare const getServiceNamesWithFederation: (appName: string, serviceNames: string[]) => string[];
@@ -0,0 +1,21 @@
1
+ import { qpqCoreUtils } from '@qpqjs/core';
2
+ import { getWorkspaceServiceQpqConfig } from '@qpqjs/deploy-aws';
3
+ import { getRoot, getServiceNames } from './discovery';
4
+ // Loads a service's live infrastructure.ts (qpq runs with ts-node hooks
5
+ // registered, so requiring TS works and `@scope/*` imports resolve through
6
+ // workspace symlinks).
7
+ export const loadServiceQpqConfig = (appName, service) => getWorkspaceServiceQpqConfig(getRoot(), appName, service);
8
+ export const getAppPrefix = (appName) => {
9
+ const services = getServiceNames(appName);
10
+ if (services.length === 0)
11
+ throw new Error(`No services found for app ${appName}`);
12
+ return qpqCoreUtils.getApplicationName(loadServiceQpqConfig(appName, services[0]));
13
+ };
14
+ // The subset of the given services that opt into module-federation publishing,
15
+ // i.e. declare defineFederatedModuleStore(...). Federation is a config setting,
16
+ // not a directory convention (unlike views/ backends), so detecting it means
17
+ // loading each service's config — which is why this lives here and not in the
18
+ // directory-only discovery module. Used by the deploy drivers to decide which
19
+ // backends to publish federated remotes for after a deploy.
20
+ export const getServiceNamesWithFederation = (appName, serviceNames) => serviceNames.filter((service) => !!qpqCoreUtils.getFederatedModuleStore(loadServiceQpqConfig(appName, service)));
21
+ //# sourceMappingURL=qpqConfigs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"qpqConfigs.js","sourceRoot":"","sources":["../../../src/lib/qpqConfigs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3D,OAAO,EAAE,4BAA4B,EAAE,MAAM,mBAAmB,CAAC;AAEjE,OAAO,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEvD,wEAAwE;AACxE,2EAA2E;AAC3E,uBAAuB;AACvB,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,OAAe,EAAE,OAAe,EAAa,EAAE,CAAC,4BAA4B,CAAC,OAAO,EAAE,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;AAE/I,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,OAAe,EAAU,EAAE;IACtD,MAAM,QAAQ,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC;IAC1C,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,6BAA6B,OAAO,EAAE,CAAC,CAAC;IACnF,OAAO,YAAY,CAAC,kBAAkB,CAAC,oBAAoB,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACrF,CAAC,CAAC;AAEF,+EAA+E;AAC/E,gFAAgF;AAChF,6EAA6E;AAC7E,8EAA8E;AAC9E,8EAA8E;AAC9E,4DAA4D;AAC5D,MAAM,CAAC,MAAM,6BAA6B,GAAG,CAAC,OAAe,EAAE,YAAsB,EAAY,EAAE,CACjG,YAAY,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,uBAAuB,CAAC,oBAAoB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC","sourcesContent":["import { type QPQConfig, qpqCoreUtils } from '@qpqjs/core';\nimport { getWorkspaceServiceQpqConfig } from '@qpqjs/deploy-aws';\n\nimport { getRoot, getServiceNames } from './discovery';\n\n// Loads a service's live infrastructure.ts (qpq runs with ts-node hooks\n// registered, so requiring TS works and `@scope/*` imports resolve through\n// workspace symlinks).\nexport const loadServiceQpqConfig = (appName: string, service: string): QPQConfig => getWorkspaceServiceQpqConfig(getRoot(), appName, service);\n\nexport const getAppPrefix = (appName: string): string => {\n const services = getServiceNames(appName);\n if (services.length === 0) throw new Error(`No services found for app ${appName}`);\n return qpqCoreUtils.getApplicationName(loadServiceQpqConfig(appName, services[0]));\n};\n\n// The subset of the given services that opt into module-federation publishing,\n// i.e. declare defineFederatedModuleStore(...). Federation is a config setting,\n// not a directory convention (unlike views/ backends), so detecting it means\n// loading each service's config — which is why this lives here and not in the\n// directory-only discovery module. Used by the deploy drivers to decide which\n// backends to publish federated remotes for after a deploy.\nexport const getServiceNamesWithFederation = (appName: string, serviceNames: string[]): string[] =>\n serviceNames.filter((service) => !!qpqCoreUtils.getFederatedModuleStore(loadServiceQpqConfig(appName, service)));\n"]}
@@ -0,0 +1,6 @@
1
+ export type ResolveAppOptions = {
2
+ argv: string[];
3
+ envVar?: string;
4
+ allowAll?: boolean;
5
+ };
6
+ export declare const resolveAppSelection: (options: ResolveAppOptions) => Promise<string>;
@@ -0,0 +1,45 @@
1
+ // One app-selection contract for every app-facing command (prep / synth / go /
2
+ // go:dev / go:dev:api / go:dev:web / publish). Resolution order:
3
+ // 1. --app <name> / --app=<name> on argv
4
+ // 2. npm_config_app (npm run x --app foo, no --)
5
+ // 3. an env var the command already honours (QPQ_DEV_APP / DEPLOY_APP_NAME)
6
+ // 4. exactly one app under apps/ -> auto-select
7
+ // 5. interactive prompt (TTY only)
8
+ // 6. otherwise: print the valid app list and exit non-zero
9
+ // An unknown name (from any source) also prints the list and exits non-zero.
10
+ // Commands that can meaningfully run for every app may pass allowAll to accept
11
+ // `--app all` (returned as the literal 'all').
12
+ import { getArgValue } from './args';
13
+ import { getAvailableApps } from './discovery';
14
+ import { promptSelect } from './prompts';
15
+ const exitWithAppList = (requested, availableApps) => {
16
+ if (requested)
17
+ console.error(`Unknown app '${requested}'.`);
18
+ console.error(`Valid apps: ${availableApps.join(', ')}`);
19
+ console.error(`Pass one with --app <name> (e.g. qpq <command> --app ${availableApps[0]}).`);
20
+ process.exit(1);
21
+ };
22
+ export const resolveAppSelection = async (options) => {
23
+ const availableApps = getAvailableApps();
24
+ if (availableApps.length === 0) {
25
+ console.error('No apps found under apps/.');
26
+ process.exit(1);
27
+ }
28
+ const requested = getArgValue(options.argv, '--app') || process.env.npm_config_app || (options.envVar ? process.env[options.envVar] : undefined);
29
+ if (requested) {
30
+ if (options.allowAll && requested === 'all')
31
+ return 'all';
32
+ if (!availableApps.includes(requested))
33
+ exitWithAppList(requested, availableApps);
34
+ return requested;
35
+ }
36
+ if (availableApps.length === 1) {
37
+ console.log(`Using app: ${availableApps[0]}`);
38
+ return availableApps[0];
39
+ }
40
+ if (process.stdin.isTTY) {
41
+ return promptSelect('Select app', options.allowAll ? [...availableApps, 'all'] : availableApps);
42
+ }
43
+ return exitWithAppList(undefined, availableApps);
44
+ };
45
+ //# sourceMappingURL=resolveAppSelection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolveAppSelection.js","sourceRoot":"","sources":["../../../src/lib/resolveAppSelection.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,iEAAiE;AACjE,2CAA2C;AAC3C,+EAA+E;AAC/E,kFAAkF;AAClF,kDAAkD;AAClD,qCAAqC;AACrC,6DAA6D;AAC7D,6EAA6E;AAC7E,+EAA+E;AAC/E,+CAA+C;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AACrC,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAUzC,MAAM,eAAe,GAAG,CAAC,SAA6B,EAAE,aAAuB,EAAS,EAAE;IACxF,IAAI,SAAS;QAAE,OAAO,CAAC,KAAK,CAAC,gBAAgB,SAAS,IAAI,CAAC,CAAC;IAC5D,OAAO,CAAC,KAAK,CAAC,eAAe,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACzD,OAAO,CAAC,KAAK,CAAC,wDAAwD,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAC5F,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,mBAAmB,GAAG,KAAK,EAAE,OAA0B,EAAmB,EAAE;IACvF,MAAM,aAAa,GAAG,gBAAgB,EAAE,CAAC;IACzC,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC/B,OAAO,CAAC,KAAK,CAAC,4BAA4B,CAAC,CAAC;QAC5C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,SAAS,GACb,WAAW,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IAEjI,IAAI,SAAS,EAAE,CAAC;QACd,IAAI,OAAO,CAAC,QAAQ,IAAI,SAAS,KAAK,KAAK;YAAE,OAAO,KAAK,CAAC;QAC1D,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,SAAS,CAAC;YAAE,eAAe,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC;QAClF,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC/B,OAAO,CAAC,GAAG,CAAC,cAAc,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAC9C,OAAO,aAAa,CAAC,CAAC,CAAC,CAAC;IAC1B,CAAC;IAED,IAAI,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QACxB,OAAO,YAAY,CAAC,YAAY,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,GAAG,aAAa,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC;IAClG,CAAC;IAED,OAAO,eAAe,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC;AACnD,CAAC,CAAC","sourcesContent":["// One app-selection contract for every app-facing command (prep / synth / go /\n// go:dev / go:dev:api / go:dev:web / publish). Resolution order:\n// 1. --app <name> / --app=<name> on argv\n// 2. npm_config_app (npm run x --app foo, no --)\n// 3. an env var the command already honours (QPQ_DEV_APP / DEPLOY_APP_NAME)\n// 4. exactly one app under apps/ -> auto-select\n// 5. interactive prompt (TTY only)\n// 6. otherwise: print the valid app list and exit non-zero\n// An unknown name (from any source) also prints the list and exits non-zero.\n// Commands that can meaningfully run for every app may pass allowAll to accept\n// `--app all` (returned as the literal 'all').\nimport { getArgValue } from './args';\nimport { getAvailableApps } from './discovery';\nimport { promptSelect } from './prompts';\n\nexport type ResolveAppOptions = {\n argv: string[];\n // Env var this command historically honours (e.g. QPQ_DEV_APP, DEPLOY_APP_NAME).\n envVar?: string;\n // Accept `--app all` and return 'all'.\n allowAll?: boolean;\n};\n\nconst exitWithAppList = (requested: string | undefined, availableApps: string[]): never => {\n if (requested) console.error(`Unknown app '${requested}'.`);\n console.error(`Valid apps: ${availableApps.join(', ')}`);\n console.error(`Pass one with --app <name> (e.g. qpq <command> --app ${availableApps[0]}).`);\n process.exit(1);\n};\n\nexport const resolveAppSelection = async (options: ResolveAppOptions): Promise<string> => {\n const availableApps = getAvailableApps();\n if (availableApps.length === 0) {\n console.error('No apps found under apps/.');\n process.exit(1);\n }\n\n const requested =\n getArgValue(options.argv, '--app') || process.env.npm_config_app || (options.envVar ? process.env[options.envVar] : undefined);\n\n if (requested) {\n if (options.allowAll && requested === 'all') return 'all';\n if (!availableApps.includes(requested)) exitWithAppList(requested, availableApps);\n return requested;\n }\n\n if (availableApps.length === 1) {\n console.log(`Using app: ${availableApps[0]}`);\n return availableApps[0];\n }\n\n if (process.stdin.isTTY) {\n return promptSelect('Select app', options.allowAll ? [...availableApps, 'all'] : availableApps);\n }\n\n return exitWithAppList(undefined, availableApps);\n};\n"]}
@@ -0,0 +1,14 @@
1
+ import { QpqAppDeployment } from '@qpqjs/core';
2
+ export declare const DEPLOYMENT_FLAG = "--deployment";
3
+ export type ResolvedDeployment = {
4
+ deploymentName: string;
5
+ deployment: QpqAppDeployment;
6
+ };
7
+ /**
8
+ * Selects an entry of the app's deploy.config.json and writes it into process.env
9
+ * (identity, environment, feature, settings) before any service config is loaded.
10
+ * The file is the source of truth: nothing in the shell overrides a value in it.
11
+ * The platform driver validates its own settings, so an aws entry missing its
12
+ * account or region fails here, not inside cdk.
13
+ */
14
+ export declare const resolveDeployment: (argv: string[], appName: string) => Promise<ResolvedDeployment>;
@@ -0,0 +1,45 @@
1
+ import { getQpqAppDeployConfig, getQpqAppDeployConfigPath, primeDeploymentEnv } from '@qpqjs/config-aws';
2
+ import { QpqDeployEnvVar } from '@qpqjs/core';
3
+ import { getPlatformDriver } from '../platforms';
4
+ import { getArgValue } from './args';
5
+ import { getRoot } from './discovery';
6
+ import { promptSelect } from './prompts';
7
+ export const DEPLOYMENT_FLAG = '--deployment';
8
+ // Which entry to use: the flag, then DEPLOY_NAME (set by a parent qpq command or CI: a
9
+ // selector, never a value), then the sole entry, then a prompt. Headless with several
10
+ // entries and no selection is an error rather than a guess.
11
+ const selectDeploymentName = async (argv, appName, configuredNames) => {
12
+ const requested = getArgValue(argv, DEPLOYMENT_FLAG) || process.env[QpqDeployEnvVar.deployName];
13
+ if (requested) {
14
+ if (!configuredNames.includes(requested)) {
15
+ console.error(`Unknown deployment '${requested}' in ${getQpqAppDeployConfigPath(getRoot(), appName)}. Configured: ${configuredNames.join(', ')}`);
16
+ process.exit(1);
17
+ }
18
+ return requested;
19
+ }
20
+ if (configuredNames.length === 1) {
21
+ console.log(`Using deployment: ${configuredNames[0]}`);
22
+ return configuredNames[0];
23
+ }
24
+ if (process.stdin.isTTY) {
25
+ return promptSelect('Select deployment', configuredNames);
26
+ }
27
+ console.error(`No deployment selected. Pass ${DEPLOYMENT_FLAG} <name>. Configured: ${configuredNames.join(', ')}`);
28
+ return process.exit(1);
29
+ };
30
+ /**
31
+ * Selects an entry of the app's deploy.config.json and writes it into process.env
32
+ * (identity, environment, feature, settings) before any service config is loaded.
33
+ * The file is the source of truth: nothing in the shell overrides a value in it.
34
+ * The platform driver validates its own settings, so an aws entry missing its
35
+ * account or region fails here, not inside cdk.
36
+ */
37
+ export const resolveDeployment = async (argv, appName) => {
38
+ const { deployments } = getQpqAppDeployConfig(getRoot(), appName);
39
+ const deploymentName = await selectDeploymentName(argv, appName, Object.keys(deployments));
40
+ const deployment = deployments[deploymentName];
41
+ primeDeploymentEnv(appName, deploymentName, deployment);
42
+ getPlatformDriver(deployment.platform).prepareDeployment(deploymentName, deployment);
43
+ return { deploymentName, deployment };
44
+ };
45
+ //# sourceMappingURL=resolveDeployment.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolveDeployment.js","sourceRoot":"","sources":["../../../src/lib/resolveDeployment.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,yBAAyB,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACzG,OAAO,EAAoB,eAAe,EAAE,MAAM,aAAa,CAAC;AAEhE,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AACtC,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAEzC,MAAM,CAAC,MAAM,eAAe,GAAG,cAAc,CAAC;AAO9C,uFAAuF;AACvF,sFAAsF;AACtF,4DAA4D;AAC5D,MAAM,oBAAoB,GAAG,KAAK,EAAE,IAAc,EAAE,OAAe,EAAE,eAAyB,EAAmB,EAAE;IACjH,MAAM,SAAS,GAAG,WAAW,CAAC,IAAI,EAAE,eAAe,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC;IAEhG,IAAI,SAAS,EAAE,CAAC;QACd,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;YACzC,OAAO,CAAC,KAAK,CAAC,uBAAuB,SAAS,QAAQ,yBAAyB,CAAC,OAAO,EAAE,EAAE,OAAO,CAAC,iBAAiB,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAClJ,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,IAAI,eAAe,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACjC,OAAO,CAAC,GAAG,CAAC,qBAAqB,eAAe,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QACvD,OAAO,eAAe,CAAC,CAAC,CAAC,CAAC;IAC5B,CAAC;IAED,IAAI,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QACxB,OAAO,YAAY,CAAC,mBAAmB,EAAE,eAAe,CAAC,CAAC;IAC5D,CAAC;IAED,OAAO,CAAC,KAAK,CAAC,gCAAgC,eAAe,wBAAwB,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACnH,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACzB,CAAC,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,KAAK,EAAE,IAAc,EAAE,OAAe,EAA+B,EAAE;IACtG,MAAM,EAAE,WAAW,EAAE,GAAG,qBAAqB,CAAC,OAAO,EAAE,EAAE,OAAO,CAAC,CAAC;IAClE,MAAM,cAAc,GAAG,MAAM,oBAAoB,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC;IAC3F,MAAM,UAAU,GAAG,WAAW,CAAC,cAAc,CAAC,CAAC;IAE/C,kBAAkB,CAAC,OAAO,EAAE,cAAc,EAAE,UAAU,CAAC,CAAC;IACxD,iBAAiB,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,iBAAiB,CAAC,cAAc,EAAE,UAAU,CAAC,CAAC;IAErF,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,CAAC;AACxC,CAAC,CAAC","sourcesContent":["import { getQpqAppDeployConfig, getQpqAppDeployConfigPath, primeDeploymentEnv } from '@qpqjs/config-aws';\nimport { QpqAppDeployment, QpqDeployEnvVar } from '@qpqjs/core';\n\nimport { getPlatformDriver } from '../platforms';\nimport { getArgValue } from './args';\nimport { getRoot } from './discovery';\nimport { promptSelect } from './prompts';\n\nexport const DEPLOYMENT_FLAG = '--deployment';\n\nexport type ResolvedDeployment = {\n deploymentName: string;\n deployment: QpqAppDeployment;\n};\n\n// Which entry to use: the flag, then DEPLOY_NAME (set by a parent qpq command or CI: a\n// selector, never a value), then the sole entry, then a prompt. Headless with several\n// entries and no selection is an error rather than a guess.\nconst selectDeploymentName = async (argv: string[], appName: string, configuredNames: string[]): Promise<string> => {\n const requested = getArgValue(argv, DEPLOYMENT_FLAG) || process.env[QpqDeployEnvVar.deployName];\n\n if (requested) {\n if (!configuredNames.includes(requested)) {\n console.error(`Unknown deployment '${requested}' in ${getQpqAppDeployConfigPath(getRoot(), appName)}. Configured: ${configuredNames.join(', ')}`);\n process.exit(1);\n }\n return requested;\n }\n\n if (configuredNames.length === 1) {\n console.log(`Using deployment: ${configuredNames[0]}`);\n return configuredNames[0];\n }\n\n if (process.stdin.isTTY) {\n return promptSelect('Select deployment', configuredNames);\n }\n\n console.error(`No deployment selected. Pass ${DEPLOYMENT_FLAG} <name>. Configured: ${configuredNames.join(', ')}`);\n return process.exit(1);\n};\n\n/**\n * Selects an entry of the app's deploy.config.json and writes it into process.env\n * (identity, environment, feature, settings) before any service config is loaded.\n * The file is the source of truth: nothing in the shell overrides a value in it.\n * The platform driver validates its own settings, so an aws entry missing its\n * account or region fails here, not inside cdk.\n */\nexport const resolveDeployment = async (argv: string[], appName: string): Promise<ResolvedDeployment> => {\n const { deployments } = getQpqAppDeployConfig(getRoot(), appName);\n const deploymentName = await selectDeploymentName(argv, appName, Object.keys(deployments));\n const deployment = deployments[deploymentName];\n\n primeDeploymentEnv(appName, deploymentName, deployment);\n getPlatformDriver(deployment.platform).prepareDeployment(deploymentName, deployment);\n\n return { deploymentName, deployment };\n};\n"]}
@@ -0,0 +1,14 @@
1
+ export type RunCommandOptions = {
2
+ env?: Record<string, string>;
3
+ cwd?: string;
4
+ logCommand?: boolean;
5
+ };
6
+ export declare const runCommand: (command: string, args: string[], options?: RunCommandOptions) => Promise<void>;
7
+ export declare const runCommandBestEffort: (command: string, args: string[], options?: RunCommandOptions) => Promise<void>;
8
+ export type RunCommandPrefixedOptions = {
9
+ env?: Record<string, string>;
10
+ cwd?: string;
11
+ color?: number;
12
+ };
13
+ export declare const nextPrefixColor: () => number;
14
+ export declare const runCommandPrefixed: (label: string, command: string, args: string[], options?: RunCommandPrefixedOptions) => Promise<void>;