@qpqjs/cli 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (284) hide show
  1. package/lib/commonjs/cli/commandMenu.js +5 -4
  2. package/lib/commonjs/cli/commandMenu.js.map +1 -1
  3. package/lib/commonjs/cli/runCli.js +15 -7
  4. package/lib/commonjs/cli/runCli.js.map +1 -1
  5. package/lib/commonjs/commands/checkCircular.js +15 -7
  6. package/lib/commonjs/commands/checkCircular.js.map +1 -1
  7. package/lib/commonjs/commands/clearResources.js +8 -14
  8. package/lib/commonjs/commands/clearResources.js.map +1 -1
  9. package/lib/commonjs/commands/go.js +3 -7
  10. package/lib/commonjs/commands/go.js.map +1 -1
  11. package/lib/commonjs/commands/goDev.js +4 -2
  12. package/lib/commonjs/commands/goDev.js.map +1 -1
  13. package/lib/commonjs/commands/goDevApi.js +23 -20
  14. package/lib/commonjs/commands/goDevApi.js.map +1 -1
  15. package/lib/commonjs/commands/goDevWeb.js +13 -8
  16. package/lib/commonjs/commands/goDevWeb.js.map +1 -1
  17. package/lib/commonjs/commands/goDocker.js +10 -13
  18. package/lib/commonjs/commands/goDocker.js.map +1 -1
  19. package/lib/commonjs/commands/hooks.js +4 -2
  20. package/lib/commonjs/commands/hooks.js.map +1 -1
  21. package/lib/commonjs/commands/migrate.js +11 -9
  22. package/lib/commonjs/commands/migrate.js.map +1 -1
  23. package/lib/commonjs/commands/prep.js +4 -2
  24. package/lib/commonjs/commands/prep.js.map +1 -1
  25. package/lib/commonjs/commands/publish.js +4 -7
  26. package/lib/commonjs/commands/publish.js.map +1 -1
  27. package/lib/commonjs/commands/scriptBuild.js +7 -5
  28. package/lib/commonjs/commands/scriptBuild.js.map +1 -1
  29. package/lib/commonjs/commands/scriptBuilderLayer.js +6 -4
  30. package/lib/commonjs/commands/scriptBuilderLayer.js.map +1 -1
  31. package/lib/commonjs/commands/scriptNew.js +7 -5
  32. package/lib/commonjs/commands/scriptNew.js.map +1 -1
  33. package/lib/commonjs/commands/setup.js +14 -22
  34. package/lib/commonjs/commands/setup.js.map +1 -1
  35. package/lib/commonjs/commands/synth.js +16 -20
  36. package/lib/commonjs/commands/synth.js.map +1 -1
  37. package/lib/commonjs/commands/teardown.js +8 -14
  38. package/lib/commonjs/commands/teardown.js.map +1 -1
  39. package/lib/commonjs/lib/CliError.d.ts +4 -0
  40. package/lib/commonjs/lib/CliError.js +14 -0
  41. package/lib/commonjs/lib/CliError.js.map +1 -0
  42. package/lib/commonjs/lib/circularImports.d.ts +0 -1
  43. package/lib/commonjs/lib/circularImports.js +5 -6
  44. package/lib/commonjs/lib/circularImports.js.map +1 -1
  45. package/lib/commonjs/lib/clearResourcesPlan.d.ts +0 -1
  46. package/lib/commonjs/lib/clearResourcesPlan.js +12 -13
  47. package/lib/commonjs/lib/clearResourcesPlan.js.map +1 -1
  48. package/lib/commonjs/lib/deployPrompts.d.ts +2 -1
  49. package/lib/commonjs/lib/deployPrompts.js +16 -16
  50. package/lib/commonjs/lib/deployPrompts.js.map +1 -1
  51. package/lib/commonjs/lib/devServerEntry.js +5 -4
  52. package/lib/commonjs/lib/devServerEntry.js.map +1 -1
  53. package/lib/commonjs/lib/devServerPorts.js +2 -4
  54. package/lib/commonjs/lib/devServerPorts.js.map +1 -1
  55. package/lib/commonjs/lib/discovery.d.ts +0 -2
  56. package/lib/commonjs/lib/discovery.js +11 -44
  57. package/lib/commonjs/lib/discovery.js.map +1 -1
  58. package/lib/commonjs/lib/hooks.js +5 -3
  59. package/lib/commonjs/lib/hooks.js.map +1 -1
  60. package/lib/commonjs/lib/killChildWithEscalation.js +3 -1
  61. package/lib/commonjs/lib/killChildWithEscalation.js.map +1 -1
  62. package/lib/commonjs/lib/killStaleListeners.js +24 -37
  63. package/lib/commonjs/lib/killStaleListeners.js.map +1 -1
  64. package/lib/commonjs/lib/out.d.ts +11 -0
  65. package/lib/commonjs/lib/out.js +30 -0
  66. package/lib/commonjs/lib/out.js.map +1 -0
  67. package/lib/commonjs/lib/prompts.d.ts +1 -0
  68. package/lib/commonjs/lib/prompts.js +15 -2
  69. package/lib/commonjs/lib/prompts.js.map +1 -1
  70. package/lib/commonjs/lib/qpqConfigs.js +4 -4
  71. package/lib/commonjs/lib/qpqConfigs.js.map +1 -1
  72. package/lib/commonjs/lib/requireDriverCapability.d.ts +7 -0
  73. package/lib/commonjs/lib/requireDriverCapability.js +17 -0
  74. package/lib/commonjs/lib/requireDriverCapability.js.map +1 -0
  75. package/lib/commonjs/lib/resolveAppSelection.d.ts +1 -0
  76. package/lib/commonjs/lib/resolveAppSelection.js +19 -12
  77. package/lib/commonjs/lib/resolveAppSelection.js.map +1 -1
  78. package/lib/commonjs/lib/resolveCommandContext.d.ts +12 -0
  79. package/lib/commonjs/lib/resolveCommandContext.js +26 -0
  80. package/lib/commonjs/lib/resolveCommandContext.js.map +1 -0
  81. package/lib/commonjs/lib/resolveDeployment.d.ts +0 -1
  82. package/lib/commonjs/lib/resolveDeployment.js +15 -10
  83. package/lib/commonjs/lib/resolveDeployment.js.map +1 -1
  84. package/lib/commonjs/lib/runCommand.d.ts +20 -0
  85. package/lib/commonjs/lib/runCommand.js +64 -34
  86. package/lib/commonjs/lib/runCommand.js.map +1 -1
  87. package/lib/commonjs/lib/runTasks.js +8 -4
  88. package/lib/commonjs/lib/runTasks.js.map +1 -1
  89. package/lib/commonjs/lib/timing.js +5 -3
  90. package/lib/commonjs/lib/timing.js.map +1 -1
  91. package/lib/commonjs/lib/typeWatcher.d.ts +2 -1
  92. package/lib/commonjs/lib/typeWatcher.js +6 -13
  93. package/lib/commonjs/lib/typeWatcher.js.map +1 -1
  94. package/lib/commonjs/lib/userScriptBuilderLayer.d.ts +0 -2
  95. package/lib/commonjs/lib/userScriptBuilderLayer.js +7 -8
  96. package/lib/commonjs/lib/userScriptBuilderLayer.js.map +1 -1
  97. package/lib/commonjs/lib/views.js +3 -2
  98. package/lib/commonjs/lib/views.js.map +1 -1
  99. package/lib/commonjs/lib/webAddressingEnv.d.ts +0 -2
  100. package/lib/commonjs/lib/webAddressingEnv.js +4 -4
  101. package/lib/commonjs/lib/webAddressingEnv.js.map +1 -1
  102. package/lib/commonjs/platforms/aws/awsCredentials.js +3 -1
  103. package/lib/commonjs/platforms/aws/awsCredentials.js.map +1 -1
  104. package/lib/commonjs/platforms/aws/cdkApp.js +1 -1
  105. package/lib/commonjs/platforms/aws/cdkApp.js.map +1 -1
  106. package/lib/commonjs/platforms/aws/clearResources.js +16 -26
  107. package/lib/commonjs/platforms/aws/clearResources.js.map +1 -1
  108. package/lib/commonjs/platforms/aws/getDeployEnv.d.ts +1 -0
  109. package/lib/commonjs/platforms/aws/getDeployEnv.js +12 -0
  110. package/lib/commonjs/platforms/aws/getDeployEnv.js.map +1 -0
  111. package/lib/commonjs/platforms/aws/go.js +17 -15
  112. package/lib/commonjs/platforms/aws/go.js.map +1 -1
  113. package/lib/commonjs/platforms/aws/goDocker.js +29 -26
  114. package/lib/commonjs/platforms/aws/goDocker.js.map +1 -1
  115. package/lib/commonjs/platforms/aws/goDockerManifest.js +6 -1
  116. package/lib/commonjs/platforms/aws/goDockerManifest.js.map +1 -1
  117. package/lib/commonjs/platforms/aws/publish.js +13 -11
  118. package/lib/commonjs/platforms/aws/publish.js.map +1 -1
  119. package/lib/commonjs/platforms/aws/remote.js +8 -7
  120. package/lib/commonjs/platforms/aws/remote.js.map +1 -1
  121. package/lib/commonjs/platforms/aws/setup/buildBucketNamesStep.js +4 -4
  122. package/lib/commonjs/platforms/aws/setup/buildBucketNamesStep.js.map +1 -1
  123. package/lib/commonjs/platforms/aws/setup/buildGithubDeployRoleStep.js +4 -3
  124. package/lib/commonjs/platforms/aws/setup/buildGithubDeployRoleStep.js.map +1 -1
  125. package/lib/commonjs/platforms/aws/stacks.d.ts +0 -1
  126. package/lib/commonjs/platforms/aws/stacks.js +21 -33
  127. package/lib/commonjs/platforms/aws/stacks.js.map +1 -1
  128. package/lib/commonjs/platforms/aws/teardown.js +9 -7
  129. package/lib/commonjs/platforms/aws/teardown.js.map +1 -1
  130. package/lib/commonjs/platforms/aws/viewsSync.js +23 -11
  131. package/lib/commonjs/platforms/aws/viewsSync.js.map +1 -1
  132. package/lib/commonjs/platforms/docker/go.js +20 -18
  133. package/lib/commonjs/platforms/docker/go.js.map +1 -1
  134. package/lib/commonjs/platforms/docker/index.js +5 -4
  135. package/lib/commonjs/platforms/docker/index.js.map +1 -1
  136. package/lib/commonjs/platforms/docker/parseMounts.js +3 -2
  137. package/lib/commonjs/platforms/docker/parseMounts.js.map +1 -1
  138. package/lib/commonjs/platforms/index.js +4 -2
  139. package/lib/commonjs/platforms/index.js.map +1 -1
  140. package/lib/commonjs/platforms/types.d.ts +2 -2
  141. package/lib/commonjs/platforms/types.js.map +1 -1
  142. package/lib/esm/cli/commandMenu.js +5 -4
  143. package/lib/esm/cli/commandMenu.js.map +1 -1
  144. package/lib/esm/cli/runCli.js +15 -7
  145. package/lib/esm/cli/runCli.js.map +1 -1
  146. package/lib/esm/commands/checkCircular.js +15 -7
  147. package/lib/esm/commands/checkCircular.js.map +1 -1
  148. package/lib/esm/commands/clearResources.js +8 -14
  149. package/lib/esm/commands/clearResources.js.map +1 -1
  150. package/lib/esm/commands/go.js +3 -7
  151. package/lib/esm/commands/go.js.map +1 -1
  152. package/lib/esm/commands/goDev.js +4 -2
  153. package/lib/esm/commands/goDev.js.map +1 -1
  154. package/lib/esm/commands/goDevApi.js +21 -18
  155. package/lib/esm/commands/goDevApi.js.map +1 -1
  156. package/lib/esm/commands/goDevWeb.js +12 -8
  157. package/lib/esm/commands/goDevWeb.js.map +1 -1
  158. package/lib/esm/commands/goDocker.js +10 -13
  159. package/lib/esm/commands/goDocker.js.map +1 -1
  160. package/lib/esm/commands/hooks.js +4 -2
  161. package/lib/esm/commands/hooks.js.map +1 -1
  162. package/lib/esm/commands/migrate.js +9 -7
  163. package/lib/esm/commands/migrate.js.map +1 -1
  164. package/lib/esm/commands/prep.js +4 -2
  165. package/lib/esm/commands/prep.js.map +1 -1
  166. package/lib/esm/commands/publish.js +4 -7
  167. package/lib/esm/commands/publish.js.map +1 -1
  168. package/lib/esm/commands/scriptBuild.js +7 -5
  169. package/lib/esm/commands/scriptBuild.js.map +1 -1
  170. package/lib/esm/commands/scriptBuilderLayer.js +6 -4
  171. package/lib/esm/commands/scriptBuilderLayer.js.map +1 -1
  172. package/lib/esm/commands/scriptNew.js +7 -5
  173. package/lib/esm/commands/scriptNew.js.map +1 -1
  174. package/lib/esm/commands/setup.js +14 -22
  175. package/lib/esm/commands/setup.js.map +1 -1
  176. package/lib/esm/commands/synth.js +18 -22
  177. package/lib/esm/commands/synth.js.map +1 -1
  178. package/lib/esm/commands/teardown.js +8 -14
  179. package/lib/esm/commands/teardown.js.map +1 -1
  180. package/lib/esm/lib/CliError.d.ts +4 -0
  181. package/lib/esm/lib/CliError.js +11 -0
  182. package/lib/esm/lib/CliError.js.map +1 -0
  183. package/lib/esm/lib/circularImports.d.ts +0 -1
  184. package/lib/esm/lib/circularImports.js +4 -4
  185. package/lib/esm/lib/circularImports.js.map +1 -1
  186. package/lib/esm/lib/clearResourcesPlan.d.ts +0 -1
  187. package/lib/esm/lib/clearResourcesPlan.js +12 -12
  188. package/lib/esm/lib/clearResourcesPlan.js.map +1 -1
  189. package/lib/esm/lib/deployPrompts.d.ts +2 -1
  190. package/lib/esm/lib/deployPrompts.js +17 -17
  191. package/lib/esm/lib/deployPrompts.js.map +1 -1
  192. package/lib/esm/lib/devServerEntry.js +5 -4
  193. package/lib/esm/lib/devServerEntry.js.map +1 -1
  194. package/lib/esm/lib/devServerPorts.js +2 -3
  195. package/lib/esm/lib/devServerPorts.js.map +1 -1
  196. package/lib/esm/lib/discovery.d.ts +0 -2
  197. package/lib/esm/lib/discovery.js +10 -38
  198. package/lib/esm/lib/discovery.js.map +1 -1
  199. package/lib/esm/lib/hooks.js +5 -3
  200. package/lib/esm/lib/hooks.js.map +1 -1
  201. package/lib/esm/lib/killChildWithEscalation.js +3 -1
  202. package/lib/esm/lib/killChildWithEscalation.js.map +1 -1
  203. package/lib/esm/lib/killStaleListeners.js +24 -37
  204. package/lib/esm/lib/killStaleListeners.js.map +1 -1
  205. package/lib/esm/lib/out.d.ts +11 -0
  206. package/lib/esm/lib/out.js +26 -0
  207. package/lib/esm/lib/out.js.map +1 -0
  208. package/lib/esm/lib/prompts.d.ts +1 -0
  209. package/lib/esm/lib/prompts.js +13 -1
  210. package/lib/esm/lib/prompts.js.map +1 -1
  211. package/lib/esm/lib/qpqConfigs.js +4 -4
  212. package/lib/esm/lib/qpqConfigs.js.map +1 -1
  213. package/lib/esm/lib/requireDriverCapability.d.ts +7 -0
  214. package/lib/esm/lib/requireDriverCapability.js +13 -0
  215. package/lib/esm/lib/requireDriverCapability.js.map +1 -0
  216. package/lib/esm/lib/resolveAppSelection.d.ts +1 -0
  217. package/lib/esm/lib/resolveAppSelection.js +17 -11
  218. package/lib/esm/lib/resolveAppSelection.js.map +1 -1
  219. package/lib/esm/lib/resolveCommandContext.d.ts +12 -0
  220. package/lib/esm/lib/resolveCommandContext.js +12 -0
  221. package/lib/esm/lib/resolveCommandContext.js.map +1 -0
  222. package/lib/esm/lib/resolveDeployment.d.ts +0 -1
  223. package/lib/esm/lib/resolveDeployment.js +13 -8
  224. package/lib/esm/lib/resolveDeployment.js.map +1 -1
  225. package/lib/esm/lib/runCommand.d.ts +20 -0
  226. package/lib/esm/lib/runCommand.js +52 -31
  227. package/lib/esm/lib/runCommand.js.map +1 -1
  228. package/lib/esm/lib/runTasks.js +8 -4
  229. package/lib/esm/lib/runTasks.js.map +1 -1
  230. package/lib/esm/lib/timing.js +5 -3
  231. package/lib/esm/lib/timing.js.map +1 -1
  232. package/lib/esm/lib/typeWatcher.d.ts +2 -1
  233. package/lib/esm/lib/typeWatcher.js +6 -13
  234. package/lib/esm/lib/typeWatcher.js.map +1 -1
  235. package/lib/esm/lib/userScriptBuilderLayer.d.ts +0 -2
  236. package/lib/esm/lib/userScriptBuilderLayer.js +5 -5
  237. package/lib/esm/lib/userScriptBuilderLayer.js.map +1 -1
  238. package/lib/esm/lib/views.js +3 -2
  239. package/lib/esm/lib/views.js.map +1 -1
  240. package/lib/esm/lib/webAddressingEnv.d.ts +0 -2
  241. package/lib/esm/lib/webAddressingEnv.js +1 -1
  242. package/lib/esm/lib/webAddressingEnv.js.map +1 -1
  243. package/lib/esm/platforms/aws/awsCredentials.js +3 -1
  244. package/lib/esm/platforms/aws/awsCredentials.js.map +1 -1
  245. package/lib/esm/platforms/aws/cdkApp.js +1 -1
  246. package/lib/esm/platforms/aws/cdkApp.js.map +1 -1
  247. package/lib/esm/platforms/aws/clearResources.js +16 -25
  248. package/lib/esm/platforms/aws/clearResources.js.map +1 -1
  249. package/lib/esm/platforms/aws/getDeployEnv.d.ts +1 -0
  250. package/lib/esm/platforms/aws/getDeployEnv.js +8 -0
  251. package/lib/esm/platforms/aws/getDeployEnv.js.map +1 -0
  252. package/lib/esm/platforms/aws/go.js +17 -15
  253. package/lib/esm/platforms/aws/go.js.map +1 -1
  254. package/lib/esm/platforms/aws/goDocker.js +29 -26
  255. package/lib/esm/platforms/aws/goDocker.js.map +1 -1
  256. package/lib/esm/platforms/aws/goDockerManifest.js +6 -1
  257. package/lib/esm/platforms/aws/goDockerManifest.js.map +1 -1
  258. package/lib/esm/platforms/aws/publish.js +13 -11
  259. package/lib/esm/platforms/aws/publish.js.map +1 -1
  260. package/lib/esm/platforms/aws/remote.js +9 -7
  261. package/lib/esm/platforms/aws/remote.js.map +1 -1
  262. package/lib/esm/platforms/aws/setup/buildBucketNamesStep.js +2 -2
  263. package/lib/esm/platforms/aws/setup/buildBucketNamesStep.js.map +1 -1
  264. package/lib/esm/platforms/aws/setup/buildGithubDeployRoleStep.js +4 -3
  265. package/lib/esm/platforms/aws/setup/buildGithubDeployRoleStep.js.map +1 -1
  266. package/lib/esm/platforms/aws/stacks.d.ts +0 -1
  267. package/lib/esm/platforms/aws/stacks.js +22 -30
  268. package/lib/esm/platforms/aws/stacks.js.map +1 -1
  269. package/lib/esm/platforms/aws/teardown.js +9 -7
  270. package/lib/esm/platforms/aws/teardown.js.map +1 -1
  271. package/lib/esm/platforms/aws/viewsSync.js +22 -10
  272. package/lib/esm/platforms/aws/viewsSync.js.map +1 -1
  273. package/lib/esm/platforms/docker/go.js +21 -19
  274. package/lib/esm/platforms/docker/go.js.map +1 -1
  275. package/lib/esm/platforms/docker/index.js +5 -4
  276. package/lib/esm/platforms/docker/index.js.map +1 -1
  277. package/lib/esm/platforms/docker/parseMounts.js +3 -2
  278. package/lib/esm/platforms/docker/parseMounts.js.map +1 -1
  279. package/lib/esm/platforms/index.js +4 -2
  280. package/lib/esm/platforms/index.js.map +1 -1
  281. package/lib/esm/platforms/types.d.ts +2 -2
  282. package/lib/esm/platforms/types.js.map +1 -1
  283. package/package.json +28 -15
  284. package/templates/user-script/README.md +1 -1
@@ -10,23 +10,16 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.setupCommand = void 0;
13
- // `qpq setup` — takes a cloud environment from empty to deployed, in order, with
14
- // every step checked first so the menu shows what is already in place and a
15
- // rerun on a half-set-up account is safe. The platform (from the deployment's
16
- // entry in deploy.config.json) contributes the steps.
17
- // --check print each step's status and exit, run nothing
18
- // --yes run every step without the menu
19
- // --only a,b run only the named step ids (no menu)
20
13
  const args_1 = require("../lib/args");
14
+ const out_1 = require("../lib/out");
21
15
  const prompts_1 = require("../lib/prompts");
22
- const resolveAppSelection_1 = require("../lib/resolveAppSelection");
23
- const resolveDeployment_1 = require("../lib/resolveDeployment");
24
- const platforms_1 = require("../platforms");
16
+ const resolveCommandContext_1 = require("../lib/resolveCommandContext");
17
+ const out = (0, out_1.createOutput)('setup');
25
18
  const statusLabel = (result) => (result === null ? '?' : result.done ? 'done' : 'todo');
26
19
  const printChecklist = (checked) => {
27
20
  for (const { step, result } of checked) {
28
21
  const detail = (result === null || result === void 0 ? void 0 : result.detail) ? ` ${result.detail}` : '';
29
- console.log(` [${statusLabel(result).padEnd(4)}] ${step.name}${detail}`);
22
+ out.log(` [${statusLabel(result).padEnd(4)}] ${step.name}${detail}`);
30
23
  }
31
24
  };
32
25
  const checkAll = (steps) => __awaiter(void 0, void 0, void 0, function* () {
@@ -63,40 +56,39 @@ const selectFromArgs = (steps, argv) => {
63
56
  const ids = only.split(',').map((id) => id.trim());
64
57
  const unknown = ids.filter((id) => !steps.some((step) => step.id === id));
65
58
  if (unknown.length > 0) {
66
- console.error(`Unknown setup step id(s): ${unknown.join(', ')}. Known: ${steps.map((step) => step.id).join(', ')}`);
59
+ out.error(`Unknown setup step id(s): ${unknown.join(', ')}. Known: ${steps.map((step) => step.id).join(', ')}`);
67
60
  process.exit(1);
68
61
  }
69
62
  return steps.filter((step) => ids.includes(step.id));
70
63
  };
71
64
  const setupCommand = (argv) => __awaiter(void 0, void 0, void 0, function* () {
72
65
  var _a;
73
- const appName = yield (0, resolveAppSelection_1.resolveAppSelection)({ argv, envVar: 'DEPLOY_APP_NAME' });
74
- const { deploymentName, deployment } = yield (0, resolveDeployment_1.resolveDeployment)(argv, appName);
75
- const driver = (0, platforms_1.getPlatformDriver)(deployment.platform);
66
+ const { appName, deploymentName, deployment, driver } = yield (0, resolveCommandContext_1.resolveCommandContext)(argv);
67
+ // Nothing to set up is a normal outcome here, not a refused command.
76
68
  if (!driver.setupSteps) {
77
- console.log(`The '${deployment.platform}' platform has nothing to set up for deployment '${deploymentName}'.`);
69
+ out.log(`The '${deployment.platform}' platform has nothing to set up for deployment '${deploymentName}'.`);
78
70
  return;
79
71
  }
80
72
  const steps = yield driver.setupSteps(appName, deploymentName);
81
- console.log(`\nSetup for app '${appName}', deployment '${deploymentName}' (${deployment.platform})\n`);
73
+ out.log(`\nSetup for app '${appName}', deployment '${deploymentName}' (${deployment.platform})\n`);
82
74
  const checked = yield checkAll(steps);
83
75
  printChecklist(checked);
84
- console.log('');
76
+ out.log('');
85
77
  if (argv.includes('--check')) {
86
78
  return;
87
79
  }
88
80
  const toRun = (_a = selectFromArgs(steps, argv)) !== null && _a !== void 0 ? _a : (yield chooseSteps(checked));
89
81
  if (toRun.length === 0) {
90
- console.log('Nothing selected.');
82
+ out.log('Nothing selected.');
91
83
  return;
92
84
  }
93
85
  for (const step of toRun) {
94
- console.log(`\n== ${step.name}\n`);
86
+ out.log(`\n== ${step.name}\n`);
95
87
  yield step.run();
96
88
  }
97
- console.log('\nSetup complete. Final state:\n');
89
+ out.log('\nSetup complete. Final state:\n');
98
90
  printChecklist(yield checkAll(steps));
99
- console.log(`\nNext: deploy the services with npx qpq go:docker all all --app ${appName} --deployment ${deploymentName}`);
91
+ out.log(`\nNext: deploy the services with npx qpq go:docker all all --app ${appName} --deployment ${deploymentName}`);
100
92
  });
101
93
  exports.setupCommand = setupCommand;
102
94
  //# sourceMappingURL=setup.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"setup.js","sourceRoot":"","sources":["../../../src/commands/setup.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,iFAAiF;AACjF,4EAA4E;AAC5E,8EAA8E;AAC9E,sDAAsD;AACtD,gEAAgE;AAChE,iDAAiD;AACjD,uDAAuD;AACvD,sCAA0C;AAC1C,4CAAgD;AAChD,oEAAiE;AACjE,gEAA6D;AAE7D,4CAAiD;AAIjD,MAAM,WAAW,GAAG,CAAC,MAA+B,EAAU,EAAE,CAAC,CAAC,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;AAEzH,MAAM,cAAc,GAAG,CAAC,OAAsB,EAAQ,EAAE;IACtD,KAAK,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,OAAO,EAAE,CAAC;QACvC,MAAM,MAAM,GAAG,CAAA,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,MAAM,EAAC,CAAC,CAAC,KAAK,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC1D,OAAO,CAAC,GAAG,CAAC,MAAM,WAAW,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,IAAI,GAAG,MAAM,EAAE,CAAC,CAAC;IAC5E,CAAC;AACH,CAAC,CAAC;AAEF,MAAM,QAAQ,GAAG,CAAO,KAAkB,EAA0B,EAAE;IACpE,MAAM,OAAO,GAAkB,EAAE,CAAC;IAClC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,CAAC;YACH,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QACrD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,iBAAiB,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;QACrI,CAAC;IACH,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC,CAAA,CAAC;AAEF,8EAA8E;AAC9E,MAAM,WAAW,GAAG,CAAO,OAAsB,EAAwB,EAAE;IACzE,MAAM,MAAM,GAAG,MAAM,IAAA,wBAAc,EACjC,yDAAyD,EACzD,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,CAAC;QACjC,IAAI,EAAE,IAAI,WAAW,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,IAAI,EAAE;QACvD,KAAK,EAAE,IAAI;QACX,OAAO,EAAE,CAAC,CAAA,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,IAAI,CAAA;QACtB,WAAW,EAAE,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,MAAM;KAC5B,CAAC,CAAC,CACJ,CAAC;IAEF,qEAAqE;IACrE,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC;AACjF,CAAC,CAAA,CAAC;AAEF,MAAM,cAAc,GAAG,CAAC,KAAkB,EAAE,IAAc,EAAsB,EAAE;IAChF,IAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;QAC3B,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,IAAI,GAAG,IAAA,kBAAW,EAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IACzC,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC;IACnD,MAAM,OAAO,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC;IAC1E,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,OAAO,CAAC,KAAK,CAAC,6BAA6B,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACpH,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;AACvD,CAAC,CAAC;AAEK,MAAM,YAAY,GAAG,CAAO,IAAc,EAAiB,EAAE;;IAClE,MAAM,OAAO,GAAG,MAAM,IAAA,yCAAmB,EAAC,EAAE,IAAI,EAAE,MAAM,EAAE,iBAAiB,EAAE,CAAC,CAAC;IAC/E,MAAM,EAAE,cAAc,EAAE,UAAU,EAAE,GAAG,MAAM,IAAA,qCAAiB,EAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAC9E,MAAM,MAAM,GAAG,IAAA,6BAAiB,EAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;IAEtD,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC;QACvB,OAAO,CAAC,GAAG,CAAC,QAAQ,UAAU,CAAC,QAAQ,oDAAoD,cAAc,IAAI,CAAC,CAAC;QAC/G,OAAO;IACT,CAAC;IAED,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC;IAE/D,OAAO,CAAC,GAAG,CAAC,oBAAoB,OAAO,kBAAkB,cAAc,MAAM,UAAU,CAAC,QAAQ,KAAK,CAAC,CAAC;IACvG,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,KAAK,CAAC,CAAC;IACtC,cAAc,CAAC,OAAO,CAAC,CAAC;IACxB,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAEhB,IAAI,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;QAC7B,OAAO;IACT,CAAC;IAED,MAAM,KAAK,GAAG,MAAA,cAAc,CAAC,KAAK,EAAE,IAAI,CAAC,mCAAI,CAAC,MAAM,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC;IAC1E,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;QACjC,OAAO;IACT,CAAC;IAED,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC;QACnC,MAAM,IAAI,CAAC,GAAG,EAAE,CAAC;IACnB,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,kCAAkC,CAAC,CAAC;IAChD,cAAc,CAAC,MAAM,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC;IACtC,OAAO,CAAC,GAAG,CAAC,qEAAqE,OAAO,iBAAiB,cAAc,EAAE,CAAC,CAAC;AAC7H,CAAC,CAAA,CAAC;AAnCW,QAAA,YAAY,gBAmCvB","sourcesContent":["// `qpq setup` — takes a cloud environment from empty to deployed, in order, with\n// every step checked first so the menu shows what is already in place and a\n// rerun on a half-set-up account is safe. The platform (from the deployment's\n// entry in deploy.config.json) contributes the steps.\n// --check print each step's status and exit, run nothing\n// --yes run every step without the menu\n// --only a,b run only the named step ids (no menu)\nimport { getArgValue } from '../lib/args';\nimport { promptCheckbox } from '../lib/prompts';\nimport { resolveAppSelection } from '../lib/resolveAppSelection';\nimport { resolveDeployment } from '../lib/resolveDeployment';\nimport { SetupCheckResult, SetupStep } from '../lib/setupStep';\nimport { getPlatformDriver } from '../platforms';\n\ntype CheckedStep = { step: SetupStep; result: SetupCheckResult | null };\n\nconst statusLabel = (result: SetupCheckResult | null): string => (result === null ? '?' : result.done ? 'done' : 'todo');\n\nconst printChecklist = (checked: CheckedStep[]): void => {\n for (const { step, result } of checked) {\n const detail = result?.detail ? ` ${result.detail}` : '';\n console.log(` [${statusLabel(result).padEnd(4)}] ${step.name}${detail}`);\n }\n};\n\nconst checkAll = async (steps: SetupStep[]): Promise<CheckedStep[]> => {\n const checked: CheckedStep[] = [];\n for (const step of steps) {\n try {\n checked.push({ step, result: await step.check() });\n } catch (error) {\n checked.push({ step, result: { done: false, detail: `check failed: ${error instanceof Error ? error.message : String(error)}` } });\n }\n }\n return checked;\n};\n\n// Steps not yet done are preselected; done ones can still be picked to rerun.\nconst chooseSteps = async (checked: CheckedStep[]): Promise<SetupStep[]> => {\n const chosen = await promptCheckbox(\n 'Setup steps to run (space toggles, enter runs in order)',\n checked.map(({ step, result }) => ({\n name: `[${statusLabel(result).padEnd(4)}] ${step.name}`,\n value: step,\n checked: !result?.done,\n description: result?.detail,\n })),\n );\n\n // Always run in checklist order, whatever order they were ticked in.\n return checked.map(({ step }) => step).filter((step) => chosen.includes(step));\n};\n\nconst selectFromArgs = (steps: SetupStep[], argv: string[]): SetupStep[] | null => {\n if (argv.includes('--yes')) {\n return steps;\n }\n\n const only = getArgValue(argv, '--only');\n if (!only) {\n return null;\n }\n\n const ids = only.split(',').map((id) => id.trim());\n const unknown = ids.filter((id) => !steps.some((step) => step.id === id));\n if (unknown.length > 0) {\n console.error(`Unknown setup step id(s): ${unknown.join(', ')}. Known: ${steps.map((step) => step.id).join(', ')}`);\n process.exit(1);\n }\n\n return steps.filter((step) => ids.includes(step.id));\n};\n\nexport const setupCommand = async (argv: string[]): Promise<void> => {\n const appName = await resolveAppSelection({ argv, envVar: 'DEPLOY_APP_NAME' });\n const { deploymentName, deployment } = await resolveDeployment(argv, appName);\n const driver = getPlatformDriver(deployment.platform);\n\n if (!driver.setupSteps) {\n console.log(`The '${deployment.platform}' platform has nothing to set up for deployment '${deploymentName}'.`);\n return;\n }\n\n const steps = await driver.setupSteps(appName, deploymentName);\n\n console.log(`\\nSetup for app '${appName}', deployment '${deploymentName}' (${deployment.platform})\\n`);\n const checked = await checkAll(steps);\n printChecklist(checked);\n console.log('');\n\n if (argv.includes('--check')) {\n return;\n }\n\n const toRun = selectFromArgs(steps, argv) ?? (await chooseSteps(checked));\n if (toRun.length === 0) {\n console.log('Nothing selected.');\n return;\n }\n\n for (const step of toRun) {\n console.log(`\\n== ${step.name}\\n`);\n await step.run();\n }\n\n console.log('\\nSetup complete. Final state:\\n');\n printChecklist(await checkAll(steps));\n console.log(`\\nNext: deploy the services with npx qpq go:docker all all --app ${appName} --deployment ${deploymentName}`);\n};\n"]}
1
+ {"version":3,"file":"setup.js","sourceRoot":"","sources":["../../../src/commands/setup.ts"],"names":[],"mappings":"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","sourcesContent":["// `qpq setup`, takes a cloud environment from empty to deployed, in order, with\n// every step checked first so the menu shows what is already in place and a\n// rerun on a half-set-up account is safe. The platform (from the deployment's\n// entry in deploy.config.json) contributes the steps.\n// --check print each step's status and exit, run nothing\n// --yes run every step without the menu\n// --only a,b run only the named step ids (no menu)\nimport { Nullable } from '@qpqjs/core';\n\nimport { getArgValue } from '../lib/args';\nimport { createOutput } from '../lib/out';\nimport { promptCheckbox } from '../lib/prompts';\nimport { resolveCommandContext } from '../lib/resolveCommandContext';\nimport { SetupCheckResult, SetupStep } from '../lib/setupStep';\n\nconst out = createOutput('setup');\n\ntype CheckedStep = { step: SetupStep; result: Nullable<SetupCheckResult> };\n\nconst statusLabel = (result: Nullable<SetupCheckResult>): string => (result === null ? '?' : result.done ? 'done' : 'todo');\n\nconst printChecklist = (checked: CheckedStep[]): void => {\n for (const { step, result } of checked) {\n const detail = result?.detail ? ` ${result.detail}` : '';\n out.log(` [${statusLabel(result).padEnd(4)}] ${step.name}${detail}`);\n }\n};\n\nconst checkAll = async (steps: SetupStep[]): Promise<CheckedStep[]> => {\n const checked: CheckedStep[] = [];\n for (const step of steps) {\n try {\n checked.push({ step, result: await step.check() });\n } catch (error) {\n checked.push({ step, result: { done: false, detail: `check failed: ${error instanceof Error ? error.message : String(error)}` } });\n }\n }\n return checked;\n};\n\n// Steps not yet done are preselected; done ones can still be picked to rerun.\nconst chooseSteps = async (checked: CheckedStep[]): Promise<SetupStep[]> => {\n const chosen = await promptCheckbox(\n 'Setup steps to run (space toggles, enter runs in order)',\n checked.map(({ step, result }) => ({\n name: `[${statusLabel(result).padEnd(4)}] ${step.name}`,\n value: step,\n checked: !result?.done,\n description: result?.detail,\n })),\n );\n\n // Always run in checklist order, whatever order they were ticked in.\n return checked.map(({ step }) => step).filter((step) => chosen.includes(step));\n};\n\nconst selectFromArgs = (steps: SetupStep[], argv: string[]): Nullable<SetupStep[]> => {\n if (argv.includes('--yes')) {\n return steps;\n }\n\n const only = getArgValue(argv, '--only');\n if (!only) {\n return null;\n }\n\n const ids = only.split(',').map((id) => id.trim());\n const unknown = ids.filter((id) => !steps.some((step) => step.id === id));\n if (unknown.length > 0) {\n out.error(`Unknown setup step id(s): ${unknown.join(', ')}. Known: ${steps.map((step) => step.id).join(', ')}`);\n process.exit(1);\n }\n\n return steps.filter((step) => ids.includes(step.id));\n};\n\nexport const setupCommand = async (argv: string[]): Promise<void> => {\n const { appName, deploymentName, deployment, driver } = await resolveCommandContext(argv);\n\n // Nothing to set up is a normal outcome here, not a refused command.\n if (!driver.setupSteps) {\n out.log(`The '${deployment.platform}' platform has nothing to set up for deployment '${deploymentName}'.`);\n return;\n }\n\n const steps = await driver.setupSteps(appName, deploymentName);\n\n out.log(`\\nSetup for app '${appName}', deployment '${deploymentName}' (${deployment.platform})\\n`);\n const checked = await checkAll(steps);\n printChecklist(checked);\n out.log('');\n\n if (argv.includes('--check')) {\n return;\n }\n\n const toRun = selectFromArgs(steps, argv) ?? (await chooseSteps(checked));\n if (toRun.length === 0) {\n out.log('Nothing selected.');\n return;\n }\n\n for (const step of toRun) {\n out.log(`\\n== ${step.name}\\n`);\n await step.run();\n }\n\n out.log('\\nSetup complete. Final state:\\n');\n printChecklist(await checkAll(steps));\n out.log(`\\nNext: deploy the services with npx qpq go:docker all all --app ${appName} --deployment ${deploymentName}`);\n};\n"]}
@@ -13,7 +13,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
13
13
  };
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
15
  exports.synthCommand = void 0;
16
- // `qpq synth [service]` — synthesizes each backend service's QPQ config to
16
+ // `qpq synth [service]`, synthesizes each backend service's QPQ config to
17
17
  // dist/apps/<app>/infrastructure/<module>-config.json.
18
18
  //
19
19
  // Runs with ts-node hooks registered (see runCli), which transpiles each
@@ -24,52 +24,48 @@ const fs_1 = __importDefault(require("fs"));
24
24
  const path_1 = __importDefault(require("path"));
25
25
  const args_1 = require("../lib/args");
26
26
  const discovery_1 = require("../lib/discovery");
27
+ const out_1 = require("../lib/out");
27
28
  const qpqConfigs_1 = require("../lib/qpqConfigs");
28
29
  const resolveAppSelection_1 = require("../lib/resolveAppSelection");
29
30
  const resolveDeployment_1 = require("../lib/resolveDeployment");
31
+ const out = (0, out_1.createOutput)('synth');
30
32
  const processConfig = (folderName, appName) => {
31
- console.log(`Processing infrastructure: [${folderName}] for app [${appName}]`);
33
+ out.log(`Processing infrastructure: [${folderName}] for app [${appName}]`);
32
34
  const qpqConfig = (0, qpqConfigs_1.loadServiceQpqConfig)(appName, folderName);
33
35
  const moduleName = core_1.qpqCoreUtils.getApplicationModuleName(qpqConfig);
34
- const directoryPath = path_1.default.join((0, discovery_1.getRoot)(), 'dist', 'apps', appName, 'infrastructure');
36
+ const directoryPath = (0, core_1.getInfrastructureConfigPath)((0, discovery_1.getRoot)(), appName);
35
37
  fs_1.default.mkdirSync(directoryPath, { recursive: true });
36
38
  fs_1.default.writeFileSync(path_1.default.join(directoryPath, `${moduleName}-config.json`), JSON.stringify(qpqConfig, null, 2));
37
- console.log(` -> ${appName}/infrastructure/${moduleName}-config.json`);
39
+ out.log(` -> ${appName}/infrastructure/${moduleName}-config.json`);
38
40
  };
39
41
  const synthCommand = (argv) => __awaiter(void 0, void 0, void 0, function* () {
40
42
  const [specifiedServiceName] = (0, args_1.getPositionalArgs)(argv, ['--app', '--deployment']);
41
- const hasExplicitApp = argv.includes('--app') || argv.some((a) => a.startsWith('--app=')) || !!process.env.npm_config_app || !!process.env.DEPLOY_APP_NAME;
42
43
  let appNames;
43
- if (specifiedServiceName && !hasExplicitApp) {
44
- // A bare service name is unambiguous — synth it in whichever app owns it.
44
+ if (specifiedServiceName && !(0, resolveAppSelection_1.getRequestedAppName)(argv, core_1.QpqDeployEnvVar.deployAppName)) {
45
+ // A bare service name is unambiguous, synth it in whichever app owns it.
45
46
  const appWithService = (0, discovery_1.getAvailableApps)().find((appName) => (0, discovery_1.getServiceNamesWithSubdir)(appName, 'service').includes(specifiedServiceName));
46
47
  if (!appWithService) {
47
- console.error(`Service '${specifiedServiceName}' not found in any app`);
48
+ out.error(`Service '${specifiedServiceName}' not found in any app`);
48
49
  process.exit(1);
49
50
  }
50
51
  appNames = [appWithService];
51
52
  }
52
53
  else {
53
- const selection = yield (0, resolveAppSelection_1.resolveAppSelection)({
54
- argv,
55
- envVar: 'DEPLOY_APP_NAME',
56
- allowAll: true,
57
- });
54
+ const selection = yield (0, resolveAppSelection_1.resolveAppSelection)({ argv, envVar: core_1.QpqDeployEnvVar.deployAppName, allowAll: true });
58
55
  appNames = selection === 'all' ? (0, discovery_1.getAvailableApps)() : [selection];
59
56
  }
60
- console.log(`QPQ synthesizing apps: ${appNames.join(', ')}`);
57
+ out.log(`QPQ synthesizing apps: ${appNames.join(', ')}`);
61
58
  for (const appName of appNames) {
62
59
  // Service configs read the deployment env vars at require time, so the
63
60
  // deployment is resolved (and primed) before any infrastructure.ts loads.
64
61
  yield (0, resolveDeployment_1.resolveDeployment)(argv, appName);
65
62
  // Validate a specified service against the app's discovered services before it
66
- // reaches loadServiceQpqConfig -> require. The bare-service-name branch above
67
- // already checks this; the --app/env branch used to skip it, letting a typo hit
68
- // a cryptic module-resolution error and a `../` value normalize into an arbitrary
69
- // require target. Both paths now validate identically.
63
+ // reaches loadServiceQpqConfig -> require, exactly as the bare-service-name branch
64
+ // above does: an unchecked typo hits a cryptic module-resolution error and a `../`
65
+ // value normalizes into an arbitrary require target.
70
66
  const appServices = (0, discovery_1.getServiceNamesWithSubdir)(appName, 'service');
71
67
  if (specifiedServiceName && !appServices.includes(specifiedServiceName)) {
72
- console.error(`Service '${specifiedServiceName}' not found in app '${appName}'`);
68
+ out.error(`Service '${specifiedServiceName}' not found in app '${appName}'`);
73
69
  process.exitCode = 1;
74
70
  continue;
75
71
  }
@@ -79,7 +75,7 @@ const synthCommand = (argv) => __awaiter(void 0, void 0, void 0, function* () {
79
75
  processConfig(folderName, appName);
80
76
  }
81
77
  catch (error) {
82
- console.error(`Failed to process ${folderName} in ${appName}:`, error);
78
+ out.error(`Failed to process ${folderName} in ${appName}:`, error);
83
79
  process.exitCode = 1;
84
80
  }
85
81
  }
@@ -1 +1 @@
1
- {"version":3,"file":"synth.js","sourceRoot":"","sources":["../../../src/commands/synth.ts"],"names":[],"mappings":"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","sourcesContent":["// `qpq synth [service]` — synthesizes each backend service's QPQ config to\n// dist/apps/<app>/infrastructure/<module>-config.json.\n//\n// Runs with ts-node hooks registered (see runCli), which transpiles each\n// service's infrastructure.ts on require. Cross-package `@scope/*` imports\n// resolve through the workspace node_modules symlinks to already-built dist.\nimport { qpqCoreUtils } from '@qpqjs/core';\n\nimport fs from 'fs';\nimport path from 'path';\n\nimport { getPositionalArgs } from '../lib/args';\nimport { getAvailableApps, getRoot, getServiceNamesWithSubdir } from '../lib/discovery';\nimport { loadServiceQpqConfig } from '../lib/qpqConfigs';\nimport { resolveAppSelection } from '../lib/resolveAppSelection';\nimport { resolveDeployment } from '../lib/resolveDeployment';\n\nconst processConfig = (folderName: string, appName: string): void => {\n console.log(`Processing infrastructure: [${folderName}] for app [${appName}]`);\n const qpqConfig = loadServiceQpqConfig(appName, folderName);\n const moduleName = qpqCoreUtils.getApplicationModuleName(qpqConfig);\n\n const directoryPath = path.join(getRoot(), 'dist', 'apps', appName, 'infrastructure');\n fs.mkdirSync(directoryPath, { recursive: true });\n fs.writeFileSync(path.join(directoryPath, `${moduleName}-config.json`), JSON.stringify(qpqConfig, null, 2));\n console.log(` -> ${appName}/infrastructure/${moduleName}-config.json`);\n};\n\nexport const synthCommand = async (argv: string[]): Promise<void> => {\n const [specifiedServiceName] = getPositionalArgs(argv, ['--app', '--deployment']);\n\n const hasExplicitApp =\n argv.includes('--app') || argv.some((a) => a.startsWith('--app=')) || !!process.env.npm_config_app || !!process.env.DEPLOY_APP_NAME;\n\n let appNames: string[];\n if (specifiedServiceName && !hasExplicitApp) {\n // A bare service name is unambiguous — synth it in whichever app owns it.\n const appWithService = getAvailableApps().find((appName) => getServiceNamesWithSubdir(appName, 'service').includes(specifiedServiceName));\n if (!appWithService) {\n console.error(`Service '${specifiedServiceName}' not found in any app`);\n process.exit(1);\n }\n appNames = [appWithService];\n } else {\n const selection = await resolveAppSelection({\n argv,\n envVar: 'DEPLOY_APP_NAME',\n allowAll: true,\n });\n appNames = selection === 'all' ? getAvailableApps() : [selection];\n }\n\n console.log(`QPQ synthesizing apps: ${appNames.join(', ')}`);\n\n for (const appName of appNames) {\n // Service configs read the deployment env vars at require time, so the\n // deployment is resolved (and primed) before any infrastructure.ts loads.\n await resolveDeployment(argv, appName);\n\n // Validate a specified service against the app's discovered services before it\n // reaches loadServiceQpqConfig -> require. The bare-service-name branch above\n // already checks this; the --app/env branch used to skip it, letting a typo hit\n // a cryptic module-resolution error and a `../` value normalize into an arbitrary\n // require target. Both paths now validate identically.\n const appServices = getServiceNamesWithSubdir(appName, 'service');\n if (specifiedServiceName && !appServices.includes(specifiedServiceName)) {\n console.error(`Service '${specifiedServiceName}' not found in app '${appName}'`);\n process.exitCode = 1;\n continue;\n }\n\n const serviceNames = specifiedServiceName ? [specifiedServiceName] : appServices;\n\n for (const folderName of serviceNames) {\n try {\n processConfig(folderName, appName);\n } catch (error) {\n console.error(`Failed to process ${folderName} in ${appName}:`, error);\n process.exitCode = 1;\n }\n }\n }\n};\n"]}
1
+ {"version":3,"file":"synth.js","sourceRoot":"","sources":["../../../src/commands/synth.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,0EAA0E;AAC1E,uDAAuD;AACvD,EAAE;AACF,yEAAyE;AACzE,2EAA2E;AAC3E,6EAA6E;AAC7E,sCAAyF;AAEzF,4CAAoB;AACpB,gDAAwB;AAExB,sCAAgD;AAChD,gDAAwF;AACxF,oCAA0C;AAC1C,kDAAyD;AACzD,oEAAsF;AACtF,gEAA6D;AAE7D,MAAM,GAAG,GAAG,IAAA,kBAAY,EAAC,OAAO,CAAC,CAAC;AAElC,MAAM,aAAa,GAAG,CAAC,UAAkB,EAAE,OAAe,EAAQ,EAAE;IAClE,GAAG,CAAC,GAAG,CAAC,+BAA+B,UAAU,cAAc,OAAO,GAAG,CAAC,CAAC;IAC3E,MAAM,SAAS,GAAG,IAAA,iCAAoB,EAAC,OAAO,EAAE,UAAU,CAAC,CAAC;IAC5D,MAAM,UAAU,GAAG,mBAAY,CAAC,wBAAwB,CAAC,SAAS,CAAC,CAAC;IAEpE,MAAM,aAAa,GAAG,IAAA,kCAA2B,EAAC,IAAA,mBAAO,GAAE,EAAE,OAAO,CAAC,CAAC;IACtE,YAAE,CAAC,SAAS,CAAC,aAAa,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACjD,YAAE,CAAC,aAAa,CAAC,cAAI,CAAC,IAAI,CAAC,aAAa,EAAE,GAAG,UAAU,cAAc,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IAC5G,GAAG,CAAC,GAAG,CAAC,QAAQ,OAAO,mBAAmB,UAAU,cAAc,CAAC,CAAC;AACtE,CAAC,CAAC;AAEK,MAAM,YAAY,GAAG,CAAO,IAAc,EAAiB,EAAE;IAClE,MAAM,CAAC,oBAAoB,CAAC,GAAG,IAAA,wBAAiB,EAAC,IAAI,EAAE,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC,CAAC;IAElF,IAAI,QAAkB,CAAC;IACvB,IAAI,oBAAoB,IAAI,CAAC,IAAA,yCAAmB,EAAC,IAAI,EAAE,sBAAe,CAAC,aAAa,CAAC,EAAE,CAAC;QACtF,yEAAyE;QACzE,MAAM,cAAc,GAAG,IAAA,4BAAgB,GAAE,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,IAAA,qCAAyB,EAAC,OAAO,EAAE,SAAS,CAAC,CAAC,QAAQ,CAAC,oBAAoB,CAAC,CAAC,CAAC;QAC1I,IAAI,CAAC,cAAc,EAAE,CAAC;YACpB,GAAG,CAAC,KAAK,CAAC,YAAY,oBAAoB,wBAAwB,CAAC,CAAC;YACpE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QACD,QAAQ,GAAG,CAAC,cAAc,CAAC,CAAC;IAC9B,CAAC;SAAM,CAAC;QACN,MAAM,SAAS,GAAG,MAAM,IAAA,yCAAmB,EAAC,EAAE,IAAI,EAAE,MAAM,EAAE,sBAAe,CAAC,aAAa,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;QAC7G,QAAQ,GAAG,SAAS,KAAK,KAAK,CAAC,CAAC,CAAC,IAAA,4BAAgB,GAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IACpE,CAAC;IAED,GAAG,CAAC,GAAG,CAAC,0BAA0B,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAEzD,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,uEAAuE;QACvE,0EAA0E;QAC1E,MAAM,IAAA,qCAAiB,EAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAEvC,+EAA+E;QAC/E,mFAAmF;QACnF,mFAAmF;QACnF,qDAAqD;QACrD,MAAM,WAAW,GAAG,IAAA,qCAAyB,EAAC,OAAO,EAAE,SAAS,CAAC,CAAC;QAClE,IAAI,oBAAoB,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,oBAAoB,CAAC,EAAE,CAAC;YACxE,GAAG,CAAC,KAAK,CAAC,YAAY,oBAAoB,uBAAuB,OAAO,GAAG,CAAC,CAAC;YAC7E,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;YACrB,SAAS;QACX,CAAC;QAED,MAAM,YAAY,GAAG,oBAAoB,CAAC,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC;QAEjF,KAAK,MAAM,UAAU,IAAI,YAAY,EAAE,CAAC;YACtC,IAAI,CAAC;gBACH,aAAa,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;YACrC,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,GAAG,CAAC,KAAK,CAAC,qBAAqB,UAAU,OAAO,OAAO,GAAG,EAAE,KAAK,CAAC,CAAC;gBACnE,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;YACvB,CAAC;QACH,CAAC;IACH,CAAC;AACH,CAAC,CAAA,CAAC;AA9CW,QAAA,YAAY,gBA8CvB","sourcesContent":["// `qpq synth [service]`, synthesizes each backend service's QPQ config to\n// dist/apps/<app>/infrastructure/<module>-config.json.\n//\n// Runs with ts-node hooks registered (see runCli), which transpiles each\n// service's infrastructure.ts on require. Cross-package `@scope/*` imports\n// resolve through the workspace node_modules symlinks to already-built dist.\nimport { getInfrastructureConfigPath, qpqCoreUtils, QpqDeployEnvVar } from '@qpqjs/core';\n\nimport fs from 'fs';\nimport path from 'path';\n\nimport { getPositionalArgs } from '../lib/args';\nimport { getAvailableApps, getRoot, getServiceNamesWithSubdir } from '../lib/discovery';\nimport { createOutput } from '../lib/out';\nimport { loadServiceQpqConfig } from '../lib/qpqConfigs';\nimport { getRequestedAppName, resolveAppSelection } from '../lib/resolveAppSelection';\nimport { resolveDeployment } from '../lib/resolveDeployment';\n\nconst out = createOutput('synth');\n\nconst processConfig = (folderName: string, appName: string): void => {\n out.log(`Processing infrastructure: [${folderName}] for app [${appName}]`);\n const qpqConfig = loadServiceQpqConfig(appName, folderName);\n const moduleName = qpqCoreUtils.getApplicationModuleName(qpqConfig);\n\n const directoryPath = getInfrastructureConfigPath(getRoot(), appName);\n fs.mkdirSync(directoryPath, { recursive: true });\n fs.writeFileSync(path.join(directoryPath, `${moduleName}-config.json`), JSON.stringify(qpqConfig, null, 2));\n out.log(` -> ${appName}/infrastructure/${moduleName}-config.json`);\n};\n\nexport const synthCommand = async (argv: string[]): Promise<void> => {\n const [specifiedServiceName] = getPositionalArgs(argv, ['--app', '--deployment']);\n\n let appNames: string[];\n if (specifiedServiceName && !getRequestedAppName(argv, QpqDeployEnvVar.deployAppName)) {\n // A bare service name is unambiguous, synth it in whichever app owns it.\n const appWithService = getAvailableApps().find((appName) => getServiceNamesWithSubdir(appName, 'service').includes(specifiedServiceName));\n if (!appWithService) {\n out.error(`Service '${specifiedServiceName}' not found in any app`);\n process.exit(1);\n }\n appNames = [appWithService];\n } else {\n const selection = await resolveAppSelection({ argv, envVar: QpqDeployEnvVar.deployAppName, allowAll: true });\n appNames = selection === 'all' ? getAvailableApps() : [selection];\n }\n\n out.log(`QPQ synthesizing apps: ${appNames.join(', ')}`);\n\n for (const appName of appNames) {\n // Service configs read the deployment env vars at require time, so the\n // deployment is resolved (and primed) before any infrastructure.ts loads.\n await resolveDeployment(argv, appName);\n\n // Validate a specified service against the app's discovered services before it\n // reaches loadServiceQpqConfig -> require, exactly as the bare-service-name branch\n // above does: an unchecked typo hits a cryptic module-resolution error and a `../`\n // value normalizes into an arbitrary require target.\n const appServices = getServiceNamesWithSubdir(appName, 'service');\n if (specifiedServiceName && !appServices.includes(specifiedServiceName)) {\n out.error(`Service '${specifiedServiceName}' not found in app '${appName}'`);\n process.exitCode = 1;\n continue;\n }\n\n const serviceNames = specifiedServiceName ? [specifiedServiceName] : appServices;\n\n for (const folderName of serviceNames) {\n try {\n processConfig(folderName, appName);\n } catch (error) {\n out.error(`Failed to process ${folderName} in ${appName}:`, error);\n process.exitCode = 1;\n }\n }\n }\n};\n"]}
@@ -10,24 +10,18 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.teardownCommand = void 0;
13
- // `qpq teardown` — interactive destroy, the counterpart of `qpq go`. Resolves
13
+ // `qpq teardown`, interactive destroy, the counterpart of `qpq go`. Resolves
14
14
  // the app + deployment the same way, asks which services to tear down (with
15
- // a typed confirmation — this deletes stored data), then hands off to the
15
+ // a typed confirmation, this deletes stored data), then hands off to the
16
16
  // platform driver to destroy the web, api and inf stacks in that order.
17
17
  const deployPrompts_1 = require("../lib/deployPrompts");
18
- const resolveAppSelection_1 = require("../lib/resolveAppSelection");
19
- const resolveDeployment_1 = require("../lib/resolveDeployment");
20
- const platforms_1 = require("../platforms");
18
+ const requireDriverCapability_1 = require("../lib/requireDriverCapability");
19
+ const resolveCommandContext_1 = require("../lib/resolveCommandContext");
21
20
  const teardownCommand = (argv) => __awaiter(void 0, void 0, void 0, function* () {
22
- const appName = yield (0, resolveAppSelection_1.resolveAppSelection)({ argv, envVar: 'DEPLOY_APP_NAME' });
23
- const { deployment } = yield (0, resolveDeployment_1.resolveDeployment)(argv, appName);
24
- const driver = (0, platforms_1.getPlatformDriver)(deployment.platform);
25
- if (!driver.teardown) {
26
- console.error(`The '${deployment.platform}' platform has no teardown strategy.`);
27
- process.exit(1);
28
- }
29
- const plan = yield (0, deployPrompts_1.promptTeardownPlan)(appName);
30
- yield driver.teardown(appName, plan);
21
+ const context = yield (0, resolveCommandContext_1.resolveCommandContext)(argv);
22
+ const teardown = (0, requireDriverCapability_1.requireDriverCapability)(context, 'teardown');
23
+ const plan = yield (0, deployPrompts_1.promptTeardownPlan)(context.appName);
24
+ yield teardown(context.appName, plan);
31
25
  });
32
26
  exports.teardownCommand = teardownCommand;
33
27
  //# sourceMappingURL=teardown.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"teardown.js","sourceRoot":"","sources":["../../../src/commands/teardown.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,8EAA8E;AAC9E,4EAA4E;AAC5E,0EAA0E;AAC1E,wEAAwE;AACxE,wDAA0D;AAC1D,oEAAiE;AACjE,gEAA6D;AAC7D,4CAAiD;AAE1C,MAAM,eAAe,GAAG,CAAO,IAAc,EAAiB,EAAE;IACrE,MAAM,OAAO,GAAG,MAAM,IAAA,yCAAmB,EAAC,EAAE,IAAI,EAAE,MAAM,EAAE,iBAAiB,EAAE,CAAC,CAAC;IAC/E,MAAM,EAAE,UAAU,EAAE,GAAG,MAAM,IAAA,qCAAiB,EAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAC9D,MAAM,MAAM,GAAG,IAAA,6BAAiB,EAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;IAEtD,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;QACrB,OAAO,CAAC,KAAK,CAAC,QAAQ,UAAU,CAAC,QAAQ,sCAAsC,CAAC,CAAC;QACjF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,IAAI,GAAG,MAAM,IAAA,kCAAkB,EAAC,OAAO,CAAC,CAAC;IAE/C,MAAM,MAAM,CAAC,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;AACvC,CAAC,CAAA,CAAC;AAbW,QAAA,eAAe,mBAa1B","sourcesContent":["// `qpq teardown` — interactive destroy, the counterpart of `qpq go`. Resolves\n// the app + deployment the same way, asks which services to tear down (with\n// a typed confirmation — this deletes stored data), then hands off to the\n// platform driver to destroy the web, api and inf stacks in that order.\nimport { promptTeardownPlan } from '../lib/deployPrompts';\nimport { resolveAppSelection } from '../lib/resolveAppSelection';\nimport { resolveDeployment } from '../lib/resolveDeployment';\nimport { getPlatformDriver } from '../platforms';\n\nexport const teardownCommand = async (argv: string[]): Promise<void> => {\n const appName = await resolveAppSelection({ argv, envVar: 'DEPLOY_APP_NAME' });\n const { deployment } = await resolveDeployment(argv, appName);\n const driver = getPlatformDriver(deployment.platform);\n\n if (!driver.teardown) {\n console.error(`The '${deployment.platform}' platform has no teardown strategy.`);\n process.exit(1);\n }\n\n const plan = await promptTeardownPlan(appName);\n\n await driver.teardown(appName, plan);\n};\n"]}
1
+ {"version":3,"file":"teardown.js","sourceRoot":"","sources":["../../../src/commands/teardown.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,6EAA6E;AAC7E,4EAA4E;AAC5E,yEAAyE;AACzE,wEAAwE;AACxE,wDAA0D;AAC1D,4EAAyE;AACzE,wEAAqE;AAE9D,MAAM,eAAe,GAAG,CAAO,IAAc,EAAiB,EAAE;IACrE,MAAM,OAAO,GAAG,MAAM,IAAA,6CAAqB,EAAC,IAAI,CAAC,CAAC;IAClD,MAAM,QAAQ,GAAG,IAAA,iDAAuB,EAAC,OAAO,EAAE,UAAU,CAAC,CAAC;IAE9D,MAAM,IAAI,GAAG,MAAM,IAAA,kCAAkB,EAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IAEvD,MAAM,QAAQ,CAAC,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;AACxC,CAAC,CAAA,CAAC;AAPW,QAAA,eAAe,mBAO1B","sourcesContent":["// `qpq teardown`, interactive destroy, the counterpart of `qpq go`. Resolves\n// the app + deployment the same way, asks which services to tear down (with\n// a typed confirmation, this deletes stored data), then hands off to the\n// platform driver to destroy the web, api and inf stacks in that order.\nimport { promptTeardownPlan } from '../lib/deployPrompts';\nimport { requireDriverCapability } from '../lib/requireDriverCapability';\nimport { resolveCommandContext } from '../lib/resolveCommandContext';\n\nexport const teardownCommand = async (argv: string[]): Promise<void> => {\n const context = await resolveCommandContext(argv);\n const teardown = requireDriverCapability(context, 'teardown');\n\n const plan = await promptTeardownPlan(context.appName);\n\n await teardown(context.appName, plan);\n};\n"]}
@@ -0,0 +1,4 @@
1
+ export declare class CliError extends Error {
2
+ readonly exitCode: number;
3
+ constructor(message: string, exitCode?: number);
4
+ }
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CliError = void 0;
4
+ // A failure the command layer turns into an exit code and one line of output. Library code
5
+ // throws this instead of printing and exiting itself, so it stays usable from anywhere.
6
+ class CliError extends Error {
7
+ constructor(message, exitCode = 1) {
8
+ super(message);
9
+ this.name = 'CliError';
10
+ this.exitCode = exitCode;
11
+ }
12
+ }
13
+ exports.CliError = CliError;
14
+ //# sourceMappingURL=CliError.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CliError.js","sourceRoot":"","sources":["../../../src/lib/CliError.ts"],"names":[],"mappings":";;;AAAA,2FAA2F;AAC3F,wFAAwF;AACxF,MAAa,QAAS,SAAQ,KAAK;IAGjC,YAAY,OAAe,EAAE,WAAmB,CAAC;QAC/C,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,UAAU,CAAC;QACvB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC3B,CAAC;CACF;AARD,4BAQC","sourcesContent":["// A failure the command layer turns into an exit code and one line of output. Library code\n// throws this instead of printing and exiting itself, so it stays usable from anywhere.\nexport class CliError extends Error {\n readonly exitCode: number;\n\n constructor(message: string, exitCode: number = 1) {\n super(message);\n this.name = 'CliError';\n this.exitCode = exitCode;\n }\n}\n"]}
@@ -1,3 +1,2 @@
1
1
  export type ImportCycle = string[];
2
- export declare const getWorkspaceDirectories: (root: string) => string[];
3
2
  export declare const findWorkspaceImportCycles: (root: string) => Promise<ImportCycle[]>;
@@ -12,7 +12,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
12
12
  return (mod && mod.__esModule) ? mod : { "default": mod };
13
13
  };
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
- exports.findWorkspaceImportCycles = exports.getWorkspaceDirectories = void 0;
15
+ exports.findWorkspaceImportCycles = void 0;
16
16
  // Source-level circular import detection over the consumer repo's npm
17
17
  // workspaces, powered by madge (AST-based dependency graph + cycle detection).
18
18
  // Complements the rspack CircularCheckRspackPlugin (which needs a bundle to
@@ -20,7 +20,7 @@ exports.findWorkspaceImportCycles = exports.getWorkspaceDirectories = void 0;
20
20
  // flows like `npm run validate-ts` with no bundling.
21
21
  //
22
22
  // Scope: each workspace's src, relative imports. Cross-package cycles are
23
- // already impossible — TypeScript project references refuse to build them — so
23
+ // already impossible, TypeScript project references refuse to build them, so
24
24
  // every runtime-relevant cycle lives inside one package's src. Type-only
25
25
  // imports are skipped (skipTypeImports): tsc erases them, so they never create
26
26
  // a runtime cycle.
@@ -29,7 +29,7 @@ const path_1 = __importDefault(require("path"));
29
29
  // madge ships no type definitions; declare the narrow slice we use.
30
30
  // eslint-disable-next-line @typescript-eslint/no-require-imports
31
31
  const madge = require('madge');
32
- // Expand npm workspace globs (plain path segments and `*` segments only — the
32
+ // Expand npm workspace globs (plain path segments and `*` segments only, the
33
33
  // only forms npm workspaces use in practice) into existing directories.
34
34
  const expandWorkspaceGlob = (root, pattern) => {
35
35
  let candidates = [root];
@@ -54,14 +54,13 @@ const getWorkspaceDirectories = (root) => {
54
54
  const patterns = (_a = packageJson.workspaces) !== null && _a !== void 0 ? _a : [];
55
55
  return patterns.flatMap((pattern) => expandWorkspaceGlob(root, pattern));
56
56
  };
57
- exports.getWorkspaceDirectories = getWorkspaceDirectories;
58
57
  const findWorkspaceImportCycles = (root) => __awaiter(void 0, void 0, void 0, function* () {
59
- const sourceDirs = (0, exports.getWorkspaceDirectories)(root)
58
+ const sourceDirs = getWorkspaceDirectories(root)
60
59
  .map((dir) => path_1.default.join(dir, 'src'))
61
60
  .filter((dir) => fs_1.default.existsSync(dir));
62
61
  // Excludes: node_modules and built output (dist/lib), declaration files
63
62
  // (type-only, can't cycle at runtime), and anything madge resolves to outside
64
- // the repo root (linked framework packages — their cycles surface through the
63
+ // the repo root (linked framework packages, their cycles surface through the
65
64
  // rspack CircularCheckRspackPlugin instead, this command owns the consumer
66
65
  // repo). Out-of-root paths start with '..' because baseDir is the repo root.
67
66
  const result = yield madge(sourceDirs, {
@@ -1 +1 @@
1
- {"version":3,"file":"circularImports.js","sourceRoot":"","sources":["../../../src/lib/circularImports.ts"],"names":[],"mappings":"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","sourcesContent":["// Source-level circular import detection over the consumer repo's npm\n// workspaces, powered by madge (AST-based dependency graph + cycle detection).\n// Complements the rspack CircularCheckRspackPlugin (which needs a bundle to\n// run): this scans TypeScript sources directly, so it can run inside tsc-only\n// flows like `npm run validate-ts` with no bundling.\n//\n// Scope: each workspace's src, relative imports. Cross-package cycles are\n// already impossible — TypeScript project references refuse to build them — so\n// every runtime-relevant cycle lives inside one package's src. Type-only\n// imports are skipped (skipTypeImports): tsc erases them, so they never create\n// a runtime cycle.\nimport fs from 'fs';\nimport path from 'path';\n\n// madge ships no type definitions; declare the narrow slice we use.\n// eslint-disable-next-line @typescript-eslint/no-require-imports\nconst madge = require('madge') as (paths: string[], config: object) => Promise<{ circular(): string[][] }>;\n\nexport type ImportCycle = string[];\n\n// Expand npm workspace globs (plain path segments and `*` segments only — the\n// only forms npm workspaces use in practice) into existing directories.\nconst expandWorkspaceGlob = (root: string, pattern: string): string[] => {\n let candidates = [root];\n\n for (const segment of pattern.split('/')) {\n if (segment === '*') {\n candidates = candidates.flatMap((dir) =>\n fs.existsSync(dir)\n ? fs\n .readdirSync(dir, { withFileTypes: true })\n .filter((entry) => entry.isDirectory())\n .map((entry) => path.join(dir, entry.name))\n : [],\n );\n } else {\n candidates = candidates.map((dir) => path.join(dir, segment));\n }\n }\n\n return candidates.filter((dir) => fs.existsSync(dir) && fs.statSync(dir).isDirectory());\n};\n\nexport const getWorkspaceDirectories = (root: string): string[] => {\n const packageJson = JSON.parse(fs.readFileSync(path.join(root, 'package.json'), 'utf8'));\n const patterns: string[] = packageJson.workspaces ?? [];\n return patterns.flatMap((pattern) => expandWorkspaceGlob(root, pattern));\n};\n\nexport const findWorkspaceImportCycles = async (root: string): Promise<ImportCycle[]> => {\n const sourceDirs = getWorkspaceDirectories(root)\n .map((dir) => path.join(dir, 'src'))\n .filter((dir) => fs.existsSync(dir));\n\n // Excludes: node_modules and built output (dist/lib), declaration files\n // (type-only, can't cycle at runtime), and anything madge resolves to outside\n // the repo root (linked framework packages — their cycles surface through the\n // rspack CircularCheckRspackPlugin instead, this command owns the consumer\n // repo). Out-of-root paths start with '..' because baseDir is the repo root.\n const result = await madge(sourceDirs, {\n baseDir: root,\n fileExtensions: ['ts', 'tsx'],\n excludeRegExp: [/node_modules/, /(^|\\/)(dist|lib)\\//, /\\.d\\.ts$/, /^\\.\\./],\n detectiveOptions: {\n ts: { skipTypeImports: true },\n tsx: { skipTypeImports: true },\n },\n });\n\n return result.circular();\n};\n"]}
1
+ {"version":3,"file":"circularImports.js","sourceRoot":"","sources":["../../../src/lib/circularImports.ts"],"names":[],"mappings":"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","sourcesContent":["// Source-level circular import detection over the consumer repo's npm\n// workspaces, powered by madge (AST-based dependency graph + cycle detection).\n// Complements the rspack CircularCheckRspackPlugin (which needs a bundle to\n// run): this scans TypeScript sources directly, so it can run inside tsc-only\n// flows like `npm run validate-ts` with no bundling.\n//\n// Scope: each workspace's src, relative imports. Cross-package cycles are\n// already impossible, TypeScript project references refuse to build them, so\n// every runtime-relevant cycle lives inside one package's src. Type-only\n// imports are skipped (skipTypeImports): tsc erases them, so they never create\n// a runtime cycle.\nimport fs from 'fs';\nimport path from 'path';\n\n// madge ships no type definitions; declare the narrow slice we use.\n// eslint-disable-next-line @typescript-eslint/no-require-imports\nconst madge = require('madge') as (paths: string[], config: object) => Promise<{ circular(): string[][] }>;\n\nexport type ImportCycle = string[];\n\n// Expand npm workspace globs (plain path segments and `*` segments only, the\n// only forms npm workspaces use in practice) into existing directories.\nconst expandWorkspaceGlob = (root: string, pattern: string): string[] => {\n let candidates = [root];\n\n for (const segment of pattern.split('/')) {\n if (segment === '*') {\n candidates = candidates.flatMap((dir) =>\n fs.existsSync(dir)\n ? fs\n .readdirSync(dir, { withFileTypes: true })\n .filter((entry) => entry.isDirectory())\n .map((entry) => path.join(dir, entry.name))\n : [],\n );\n } else {\n candidates = candidates.map((dir) => path.join(dir, segment));\n }\n }\n\n return candidates.filter((dir) => fs.existsSync(dir) && fs.statSync(dir).isDirectory());\n};\n\nconst getWorkspaceDirectories = (root: string): string[] => {\n const packageJson = JSON.parse(fs.readFileSync(path.join(root, 'package.json'), 'utf8'));\n const patterns: string[] = packageJson.workspaces ?? [];\n return patterns.flatMap((pattern) => expandWorkspaceGlob(root, pattern));\n};\n\nexport const findWorkspaceImportCycles = async (root: string): Promise<ImportCycle[]> => {\n const sourceDirs = getWorkspaceDirectories(root)\n .map((dir) => path.join(dir, 'src'))\n .filter((dir) => fs.existsSync(dir));\n\n // Excludes: node_modules and built output (dist/lib), declaration files\n // (type-only, can't cycle at runtime), and anything madge resolves to outside\n // the repo root (linked framework packages, their cycles surface through the\n // rspack CircularCheckRspackPlugin instead, this command owns the consumer\n // repo). Out-of-root paths start with '..' because baseDir is the repo root.\n const result = await madge(sourceDirs, {\n baseDir: root,\n fileExtensions: ['ts', 'tsx'],\n excludeRegExp: [/node_modules/, /(^|\\/)(dist|lib)\\//, /\\.d\\.ts$/, /^\\.\\./],\n detectiveOptions: {\n ts: { skipTypeImports: true },\n tsx: { skipTypeImports: true },\n },\n });\n\n return result.circular();\n};\n"]}
@@ -11,5 +11,4 @@ export type ClearResourcesPlan = {
11
11
  appName: string;
12
12
  resources: ClearableResource[];
13
13
  };
14
- export declare const getClearableResources: (appName: string) => ClearableResource[];
15
14
  export declare const promptClearResourcesPlan: (appName: string) => Promise<ClearResourcesPlan>;
@@ -9,7 +9,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
9
9
  });
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.promptClearResourcesPlan = exports.getClearableResources = void 0;
12
+ exports.promptClearResourcesPlan = void 0;
13
13
  // The question flow for `qpq clear-resources`: enumerate every service's OWNED
14
14
  // data resources (storage drives -> buckets, key value stores -> tables) from
15
15
  // its live qpq config, multi-select which to empty, then type the deploy
@@ -19,24 +19,25 @@ exports.promptClearResourcesPlan = exports.getClearableResources = void 0;
19
19
  // the service that owns it.
20
20
  const core_1 = require("@qpqjs/core");
21
21
  const discovery_1 = require("./discovery");
22
+ const getDeployTargetLabel_1 = require("./getDeployTargetLabel");
22
23
  const prompts_1 = require("./prompts");
23
24
  const qpqConfigs_1 = require("./qpqConfigs");
24
- const getDeployTargetLabel_1 = require("./getDeployTargetLabel");
25
+ const out_1 = require("./out");
26
+ const out = (0, out_1.createOutput)('clear-resources-plan');
25
27
  // Every owned data resource across the app's services, in service order.
26
28
  const getClearableResources = (appName) => {
27
29
  const resources = [];
28
30
  for (const service of (0, discovery_1.getServiceNames)(appName)) {
29
31
  const qpqConfig = (0, qpqConfigs_1.loadServiceQpqConfig)(appName, service);
30
- for (const drive of core_1.qpqCoreUtils.getOwnedStorageDrives(qpqConfig)) {
32
+ for (const drive of core_1.qpqCoreUtils.getOwnedStorageDriveConfigs(qpqConfig)) {
31
33
  resources.push({ service, kind: 'storageDrive', resourceName: drive.storageDrive });
32
34
  }
33
- for (const store of core_1.qpqCoreUtils.getOwnedKeyValueStores(qpqConfig)) {
35
+ for (const store of core_1.qpqCoreUtils.getOwnedKeyValueStoreConfigs(qpqConfig)) {
34
36
  resources.push({ service, kind: 'keyValueStore', resourceName: store.keyValueStoreName });
35
37
  }
36
38
  }
37
39
  return resources;
38
40
  };
39
- exports.getClearableResources = getClearableResources;
40
41
  const BY_SERVICE = 'By service — empty everything the selected services own';
41
42
  const BY_RESOURCE = 'By resource — pick individual buckets/tables';
42
43
  // Service mode: pick services, take every resource each one owns.
@@ -53,24 +54,22 @@ const pickByResource = (clearable) => (0, prompts_1.promptCheckbox)('Select reso
53
54
  })));
54
55
  const promptClearResourcesPlan = (appName) => __awaiter(void 0, void 0, void 0, function* () {
55
56
  const deployInfo = (0, getDeployTargetLabel_1.getDeployTargetLabel)();
56
- const clearable = (0, exports.getClearableResources)(appName);
57
+ const clearable = getClearableResources(appName);
57
58
  if (clearable.length === 0) {
58
- console.log('No storage drives or key value stores found in this app.');
59
+ out.log('No storage drives or key value stores found in this app.');
59
60
  return { kind: 'cancelled' };
60
61
  }
61
62
  const mode = yield (0, prompts_1.promptSelect)('How do you want to select what to empty?', [BY_SERVICE, BY_RESOURCE]);
62
63
  const resources = mode === BY_SERVICE ? yield pickByService(clearable) : yield pickByResource(clearable);
63
64
  if (resources.length === 0) {
64
- console.log('Nothing selected. Exiting!');
65
+ out.log('Nothing selected. Exiting!');
65
66
  return { kind: 'cancelled' };
66
67
  }
67
- console.log(`\nThis will EMPTY (delete all stored data from) ${resources.length} resource(s) in [${deployInfo}]:`);
68
+ out.log(`\nThis will EMPTY (delete all stored data from) ${resources.length} resource(s) in [${deployInfo}]:`);
68
69
  for (const resource of resources) {
69
- console.log(` ${resource.service} — ${resource.resourceName} (${resource.kind === 'storageDrive' ? 'bucket' : 'table'})`);
70
+ out.log(` ${resource.service} — ${resource.resourceName} (${resource.kind === 'storageDrive' ? 'bucket' : 'table'})`);
70
71
  }
71
- const confirmation = yield (0, prompts_1.promptText)(`Type '${deployInfo}' to confirm`);
72
- if (confirmation !== deployInfo) {
73
- console.log('Confirmation did not match. Exiting!');
72
+ if (!(yield (0, prompts_1.promptTypedConfirmation)(deployInfo))) {
74
73
  return { kind: 'cancelled' };
75
74
  }
76
75
  return { kind: 'resources', appName, resources };
@@ -1 +1 @@
1
- {"version":3,"file":"clearResourcesPlan.js","sourceRoot":"","sources":["../../../src/lib/clearResourcesPlan.ts"],"names":[],"mappings":"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","sourcesContent":["// The question flow for `qpq clear-resources`: enumerate every service's OWNED\n// data resources (storage drives -> buckets, key value stores -> tables) from\n// its live qpq config, multi-select which to empty, then type the deploy\n// target back to confirm - emptying deletes stored data, so a y/n prompt\n// isn't enough friction. Owned-only so a cross-module ref (e.g. a membership\n// table every service declares against one owner) appears exactly once, on\n// the service that owns it.\nimport { qpqCoreUtils } from '@qpqjs/core';\n\nimport { getServiceNames } from './discovery';\nimport { promptCheckbox, promptSelect, promptText } from './prompts';\nimport { loadServiceQpqConfig } from './qpqConfigs';\nimport { getDeployTargetLabel } from './getDeployTargetLabel';\n\nexport type ClearableResourceKind = 'storageDrive' | 'keyValueStore';\n\nexport type ClearableResource = {\n service: string;\n kind: ClearableResourceKind;\n // The config-level resource name (e.g. 'templateTestAssets', 'userTenantLinks');\n // the platform driver resolves it to the concrete runtime name (bucket/table).\n resourceName: string;\n};\n\nexport type ClearResourcesPlan =\n | { kind: 'cancelled' }\n // Empty (not destroy) the selected resources' stored data.\n | { kind: 'resources'; appName: string; resources: ClearableResource[] };\n\n// Every owned data resource across the app's services, in service order.\nexport const getClearableResources = (appName: string): ClearableResource[] => {\n const resources: ClearableResource[] = [];\n\n for (const service of getServiceNames(appName)) {\n const qpqConfig = loadServiceQpqConfig(appName, service);\n\n for (const drive of qpqCoreUtils.getOwnedStorageDrives(qpqConfig)) {\n resources.push({ service, kind: 'storageDrive', resourceName: drive.storageDrive });\n }\n\n for (const store of qpqCoreUtils.getOwnedKeyValueStores(qpqConfig)) {\n resources.push({ service, kind: 'keyValueStore', resourceName: store.keyValueStoreName });\n }\n }\n\n return resources;\n};\n\nconst BY_SERVICE = 'By service — empty everything the selected services own';\nconst BY_RESOURCE = 'By resource — pick individual buckets/tables';\n\n// Service mode: pick services, take every resource each one owns.\nconst pickByService = async (clearable: ClearableResource[]): Promise<ClearableResource[]> => {\n const services = [...new Set(clearable.map((resource) => resource.service))];\n\n const countFor = (service: string) => clearable.filter((resource) => resource.service === service).length;\n\n const picked = await promptCheckbox(\n 'Select services to EMPTY (every bucket/table the service owns)',\n services.map((service) => ({ name: `${service} (${countFor(service)} resources)`, value: service })),\n );\n\n return clearable.filter((resource) => picked.includes(resource.service));\n};\n\n// Resource mode: pick individual buckets/tables.\nconst pickByResource = (clearable: ClearableResource[]): Promise<ClearableResource[]> =>\n promptCheckbox(\n 'Select resources to EMPTY (all stored data will be deleted)',\n clearable.map((resource) => ({\n name: `${resource.service} — ${resource.resourceName} (${resource.kind === 'storageDrive' ? 'bucket' : 'table'})`,\n value: resource,\n })),\n );\n\nexport const promptClearResourcesPlan = async (appName: string): Promise<ClearResourcesPlan> => {\n const deployInfo = getDeployTargetLabel();\n\n const clearable = getClearableResources(appName);\n\n if (clearable.length === 0) {\n console.log('No storage drives or key value stores found in this app.');\n return { kind: 'cancelled' };\n }\n\n const mode = await promptSelect('How do you want to select what to empty?', [BY_SERVICE, BY_RESOURCE]);\n\n const resources = mode === BY_SERVICE ? await pickByService(clearable) : await pickByResource(clearable);\n\n if (resources.length === 0) {\n console.log('Nothing selected. Exiting!');\n return { kind: 'cancelled' };\n }\n\n console.log(`\\nThis will EMPTY (delete all stored data from) ${resources.length} resource(s) in [${deployInfo}]:`);\n for (const resource of resources) {\n console.log(` ${resource.service} — ${resource.resourceName} (${resource.kind === 'storageDrive' ? 'bucket' : 'table'})`);\n }\n\n const confirmation = await promptText(`Type '${deployInfo}' to confirm`);\n\n if (confirmation !== deployInfo) {\n console.log('Confirmation did not match. Exiting!');\n return { kind: 'cancelled' };\n }\n\n return { kind: 'resources', appName, resources };\n};\n"]}
1
+ {"version":3,"file":"clearResourcesPlan.js","sourceRoot":"","sources":["../../../src/lib/clearResourcesPlan.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,+EAA+E;AAC/E,8EAA8E;AAC9E,yEAAyE;AACzE,yEAAyE;AACzE,6EAA6E;AAC7E,2EAA2E;AAC3E,4BAA4B;AAC5B,sCAA2C;AAE3C,2CAA8C;AAC9C,iEAA8D;AAC9D,uCAAkF;AAClF,6CAAoD;AACpD,+BAAqC;AAErC,MAAM,GAAG,GAAG,IAAA,kBAAY,EAAC,sBAAsB,CAAC,CAAC;AAiBjD,yEAAyE;AACzE,MAAM,qBAAqB,GAAG,CAAC,OAAe,EAAuB,EAAE;IACrE,MAAM,SAAS,GAAwB,EAAE,CAAC;IAE1C,KAAK,MAAM,OAAO,IAAI,IAAA,2BAAe,EAAC,OAAO,CAAC,EAAE,CAAC;QAC/C,MAAM,SAAS,GAAG,IAAA,iCAAoB,EAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAEzD,KAAK,MAAM,KAAK,IAAI,mBAAY,CAAC,2BAA2B,CAAC,SAAS,CAAC,EAAE,CAAC;YACxE,SAAS,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,cAAc,EAAE,YAAY,EAAE,KAAK,CAAC,YAAY,EAAE,CAAC,CAAC;QACtF,CAAC;QAED,KAAK,MAAM,KAAK,IAAI,mBAAY,CAAC,4BAA4B,CAAC,SAAS,CAAC,EAAE,CAAC;YACzE,SAAS,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,eAAe,EAAE,YAAY,EAAE,KAAK,CAAC,iBAAiB,EAAE,CAAC,CAAC;QAC5F,CAAC;IACH,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC,CAAC;AAEF,MAAM,UAAU,GAAG,yDAAyD,CAAC;AAC7E,MAAM,WAAW,GAAG,8CAA8C,CAAC;AAEnE,kEAAkE;AAClE,MAAM,aAAa,GAAG,CAAO,SAA8B,EAAgC,EAAE;IAC3F,MAAM,QAAQ,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IAE7E,MAAM,QAAQ,GAAG,CAAC,OAAe,EAAE,EAAE,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,OAAO,KAAK,OAAO,CAAC,CAAC,MAAM,CAAC;IAE1G,MAAM,MAAM,GAAG,MAAM,IAAA,wBAAc,EACjC,gEAAgE,EAChE,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,GAAG,OAAO,KAAK,QAAQ,CAAC,OAAO,CAAC,aAAa,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC,CACrG,CAAC;IAEF,OAAO,SAAS,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;AAC3E,CAAC,CAAA,CAAC;AAEF,iDAAiD;AACjD,MAAM,cAAc,GAAG,CAAC,SAA8B,EAAgC,EAAE,CACtF,IAAA,wBAAc,EACZ,6DAA6D,EAC7D,SAAS,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;IAC3B,IAAI,EAAE,GAAG,QAAQ,CAAC,OAAO,MAAM,QAAQ,CAAC,YAAY,KAAK,QAAQ,CAAC,IAAI,KAAK,cAAc,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,GAAG;IACjH,KAAK,EAAE,QAAQ;CAChB,CAAC,CAAC,CACJ,CAAC;AAEG,MAAM,wBAAwB,GAAG,CAAO,OAAe,EAA+B,EAAE;IAC7F,MAAM,UAAU,GAAG,IAAA,2CAAoB,GAAE,CAAC;IAE1C,MAAM,SAAS,GAAG,qBAAqB,CAAC,OAAO,CAAC,CAAC;IAEjD,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC3B,GAAG,CAAC,GAAG,CAAC,0DAA0D,CAAC,CAAC;QACpE,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC;IAC/B,CAAC;IAED,MAAM,IAAI,GAAG,MAAM,IAAA,sBAAY,EAAC,0CAA0C,EAAE,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC,CAAC;IAEvG,MAAM,SAAS,GAAG,IAAI,KAAK,UAAU,CAAC,CAAC,CAAC,MAAM,aAAa,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,MAAM,cAAc,CAAC,SAAS,CAAC,CAAC;IAEzG,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC3B,GAAG,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC;QACtC,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC;IAC/B,CAAC;IAED,GAAG,CAAC,GAAG,CAAC,mDAAmD,SAAS,CAAC,MAAM,oBAAoB,UAAU,IAAI,CAAC,CAAC;IAC/G,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;QACjC,GAAG,CAAC,GAAG,CAAC,KAAK,QAAQ,CAAC,OAAO,MAAM,QAAQ,CAAC,YAAY,KAAK,QAAQ,CAAC,IAAI,KAAK,cAAc,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,GAAG,CAAC,CAAC;IACzH,CAAC;IAED,IAAI,CAAC,CAAC,MAAM,IAAA,iCAAuB,EAAC,UAAU,CAAC,CAAC,EAAE,CAAC;QACjD,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC;IAC/B,CAAC;IAED,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC;AACnD,CAAC,CAAA,CAAC;AA7BW,QAAA,wBAAwB,4BA6BnC","sourcesContent":["// The question flow for `qpq clear-resources`: enumerate every service's OWNED\n// data resources (storage drives -> buckets, key value stores -> tables) from\n// its live qpq config, multi-select which to empty, then type the deploy\n// target back to confirm - emptying deletes stored data, so a y/n prompt\n// isn't enough friction. Owned-only so a cross-module ref (e.g. a membership\n// table every service declares against one owner) appears exactly once, on\n// the service that owns it.\nimport { qpqCoreUtils } from '@qpqjs/core';\n\nimport { getServiceNames } from './discovery';\nimport { getDeployTargetLabel } from './getDeployTargetLabel';\nimport { promptCheckbox, promptSelect, promptTypedConfirmation } from './prompts';\nimport { loadServiceQpqConfig } from './qpqConfigs';\nimport { createOutput } from './out';\n\nconst out = createOutput('clear-resources-plan');\n\nexport type ClearableResourceKind = 'storageDrive' | 'keyValueStore';\n\nexport type ClearableResource = {\n service: string;\n kind: ClearableResourceKind;\n // The config-level resource name (e.g. 'templateTestAssets', 'userTenantLinks');\n // the platform driver resolves it to the concrete runtime name (bucket/table).\n resourceName: string;\n};\n\nexport type ClearResourcesPlan =\n | { kind: 'cancelled' }\n // Empty (not destroy) the selected resources' stored data.\n | { kind: 'resources'; appName: string; resources: ClearableResource[] };\n\n// Every owned data resource across the app's services, in service order.\nconst getClearableResources = (appName: string): ClearableResource[] => {\n const resources: ClearableResource[] = [];\n\n for (const service of getServiceNames(appName)) {\n const qpqConfig = loadServiceQpqConfig(appName, service);\n\n for (const drive of qpqCoreUtils.getOwnedStorageDriveConfigs(qpqConfig)) {\n resources.push({ service, kind: 'storageDrive', resourceName: drive.storageDrive });\n }\n\n for (const store of qpqCoreUtils.getOwnedKeyValueStoreConfigs(qpqConfig)) {\n resources.push({ service, kind: 'keyValueStore', resourceName: store.keyValueStoreName });\n }\n }\n\n return resources;\n};\n\nconst BY_SERVICE = 'By service — empty everything the selected services own';\nconst BY_RESOURCE = 'By resource — pick individual buckets/tables';\n\n// Service mode: pick services, take every resource each one owns.\nconst pickByService = async (clearable: ClearableResource[]): Promise<ClearableResource[]> => {\n const services = [...new Set(clearable.map((resource) => resource.service))];\n\n const countFor = (service: string) => clearable.filter((resource) => resource.service === service).length;\n\n const picked = await promptCheckbox(\n 'Select services to EMPTY (every bucket/table the service owns)',\n services.map((service) => ({ name: `${service} (${countFor(service)} resources)`, value: service })),\n );\n\n return clearable.filter((resource) => picked.includes(resource.service));\n};\n\n// Resource mode: pick individual buckets/tables.\nconst pickByResource = (clearable: ClearableResource[]): Promise<ClearableResource[]> =>\n promptCheckbox(\n 'Select resources to EMPTY (all stored data will be deleted)',\n clearable.map((resource) => ({\n name: `${resource.service} — ${resource.resourceName} (${resource.kind === 'storageDrive' ? 'bucket' : 'table'})`,\n value: resource,\n })),\n );\n\nexport const promptClearResourcesPlan = async (appName: string): Promise<ClearResourcesPlan> => {\n const deployInfo = getDeployTargetLabel();\n\n const clearable = getClearableResources(appName);\n\n if (clearable.length === 0) {\n out.log('No storage drives or key value stores found in this app.');\n return { kind: 'cancelled' };\n }\n\n const mode = await promptSelect('How do you want to select what to empty?', [BY_SERVICE, BY_RESOURCE]);\n\n const resources = mode === BY_SERVICE ? await pickByService(clearable) : await pickByResource(clearable);\n\n if (resources.length === 0) {\n out.log('Nothing selected. Exiting!');\n return { kind: 'cancelled' };\n }\n\n out.log(`\\nThis will EMPTY (delete all stored data from) ${resources.length} resource(s) in [${deployInfo}]:`);\n for (const resource of resources) {\n out.log(` ${resource.service} — ${resource.resourceName} (${resource.kind === 'storageDrive' ? 'bucket' : 'table'})`);\n }\n\n if (!(await promptTypedConfirmation(deployInfo))) {\n return { kind: 'cancelled' };\n }\n\n return { kind: 'resources', appName, resources };\n};\n"]}
@@ -1,3 +1,4 @@
1
+ import { Nullable } from '@qpqjs/core';
1
2
  export type StackType = 'all' | 'inf' | 'api' | 'web' | 'views';
2
3
  export type DeployPlan = {
3
4
  kind: 'cancelled';
@@ -14,7 +15,7 @@ export type DeployPlan = {
14
15
  services: string[];
15
16
  stacks: StackType;
16
17
  };
17
- export declare const buildDeployPlanFromArgs: (appName: string, argv: string[]) => DeployPlan | null;
18
+ export declare const buildDeployPlanFromArgs: (appName: string, argv: string[]) => Nullable<DeployPlan>;
18
19
  export declare const promptDeployPlan: (appName: string) => Promise<DeployPlan>;
19
20
  export type TeardownPlan = {
20
21
  kind: 'cancelled';