quidproquo-cli 0.1.5

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 (268) hide show
  1. package/README.md +3 -0
  2. package/docker/cdk-deployer/Dockerfile +13 -0
  3. package/docker/dev-server/Dockerfile +48 -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/index.d.ts +1 -0
  11. package/lib/commonjs/cli/index.js +18 -0
  12. package/lib/commonjs/cli/index.js.map +1 -0
  13. package/lib/commonjs/cli/runCli.d.ts +1 -0
  14. package/lib/commonjs/cli/runCli.js +80 -0
  15. package/lib/commonjs/cli/runCli.js.map +1 -0
  16. package/lib/commonjs/commands/go.d.ts +1 -0
  17. package/lib/commonjs/commands/go.js +28 -0
  18. package/lib/commonjs/commands/go.js.map +1 -0
  19. package/lib/commonjs/commands/goDev.d.ts +1 -0
  20. package/lib/commonjs/commands/goDev.js +143 -0
  21. package/lib/commonjs/commands/goDev.js.map +1 -0
  22. package/lib/commonjs/commands/goDevWeb.d.ts +1 -0
  23. package/lib/commonjs/commands/goDevWeb.js +122 -0
  24. package/lib/commonjs/commands/goDevWeb.js.map +1 -0
  25. package/lib/commonjs/commands/goDocker.d.ts +1 -0
  26. package/lib/commonjs/commands/goDocker.js +32 -0
  27. package/lib/commonjs/commands/goDocker.js.map +1 -0
  28. package/lib/commonjs/commands/hooks.d.ts +1 -0
  29. package/lib/commonjs/commands/hooks.js +26 -0
  30. package/lib/commonjs/commands/hooks.js.map +1 -0
  31. package/lib/commonjs/commands/prep.d.ts +1 -0
  32. package/lib/commonjs/commands/prep.js +28 -0
  33. package/lib/commonjs/commands/prep.js.map +1 -0
  34. package/lib/commonjs/commands/publish.d.ts +4 -0
  35. package/lib/commonjs/commands/publish.js +54 -0
  36. package/lib/commonjs/commands/publish.js.map +1 -0
  37. package/lib/commonjs/commands/synth.d.ts +1 -0
  38. package/lib/commonjs/commands/synth.js +79 -0
  39. package/lib/commonjs/commands/synth.js.map +1 -0
  40. package/lib/commonjs/commands/teardown.d.ts +1 -0
  41. package/lib/commonjs/commands/teardown.js +33 -0
  42. package/lib/commonjs/commands/teardown.js.map +1 -0
  43. package/lib/commonjs/index.d.ts +1 -0
  44. package/lib/commonjs/index.js +18 -0
  45. package/lib/commonjs/index.js.map +1 -0
  46. package/lib/commonjs/lib/args.d.ts +2 -0
  47. package/lib/commonjs/lib/args.js +21 -0
  48. package/lib/commonjs/lib/args.js.map +1 -0
  49. package/lib/commonjs/lib/deployEnv.d.ts +6 -0
  50. package/lib/commonjs/lib/deployEnv.js +76 -0
  51. package/lib/commonjs/lib/deployEnv.js.map +1 -0
  52. package/lib/commonjs/lib/deployPrompts.d.ts +25 -0
  53. package/lib/commonjs/lib/deployPrompts.js +83 -0
  54. package/lib/commonjs/lib/deployPrompts.js.map +1 -0
  55. package/lib/commonjs/lib/devServerEntry.d.ts +1 -0
  56. package/lib/commonjs/lib/devServerEntry.js +53 -0
  57. package/lib/commonjs/lib/devServerEntry.js.map +1 -0
  58. package/lib/commonjs/lib/discovery.d.ts +10 -0
  59. package/lib/commonjs/lib/discovery.js +56 -0
  60. package/lib/commonjs/lib/discovery.js.map +1 -0
  61. package/lib/commonjs/lib/hooks.d.ts +2 -0
  62. package/lib/commonjs/lib/hooks.js +45 -0
  63. package/lib/commonjs/lib/hooks.js.map +1 -0
  64. package/lib/commonjs/lib/packageRoot.d.ts +1 -0
  65. package/lib/commonjs/lib/packageRoot.js +21 -0
  66. package/lib/commonjs/lib/packageRoot.js.map +1 -0
  67. package/lib/commonjs/lib/prompts.d.ts +3 -0
  68. package/lib/commonjs/lib/prompts.js +64 -0
  69. package/lib/commonjs/lib/prompts.js.map +1 -0
  70. package/lib/commonjs/lib/qpqConfigs.d.ts +3 -0
  71. package/lib/commonjs/lib/qpqConfigs.js +19 -0
  72. package/lib/commonjs/lib/qpqConfigs.js.map +1 -0
  73. package/lib/commonjs/lib/resolveAppSelection.d.ts +6 -0
  74. package/lib/commonjs/lib/resolveAppSelection.js +58 -0
  75. package/lib/commonjs/lib/resolveAppSelection.js.map +1 -0
  76. package/lib/commonjs/lib/rspackRun.d.ts +2 -0
  77. package/lib/commonjs/lib/rspackRun.js +23 -0
  78. package/lib/commonjs/lib/rspackRun.js.map +1 -0
  79. package/lib/commonjs/lib/runCommand.d.ts +13 -0
  80. package/lib/commonjs/lib/runCommand.js +78 -0
  81. package/lib/commonjs/lib/runCommand.js.map +1 -0
  82. package/lib/commonjs/lib/runTasks.d.ts +10 -0
  83. package/lib/commonjs/lib/runTasks.js +42 -0
  84. package/lib/commonjs/lib/runTasks.js.map +1 -0
  85. package/lib/commonjs/lib/timing.d.ts +2 -0
  86. package/lib/commonjs/lib/timing.js +11 -0
  87. package/lib/commonjs/lib/timing.js.map +1 -0
  88. package/lib/commonjs/lib/views.d.ts +2 -0
  89. package/lib/commonjs/lib/views.js +32 -0
  90. package/lib/commonjs/lib/views.js.map +1 -0
  91. package/lib/commonjs/platforms/aws/awsCredentials.d.ts +1 -0
  92. package/lib/commonjs/platforms/aws/awsCredentials.js +28 -0
  93. package/lib/commonjs/platforms/aws/awsCredentials.js.map +1 -0
  94. package/lib/commonjs/platforms/aws/cdkApp.d.ts +2 -0
  95. package/lib/commonjs/platforms/aws/cdkApp.js +19 -0
  96. package/lib/commonjs/platforms/aws/cdkApp.js.map +1 -0
  97. package/lib/commonjs/platforms/aws/go.d.ts +2 -0
  98. package/lib/commonjs/platforms/aws/go.js +116 -0
  99. package/lib/commonjs/platforms/aws/go.js.map +1 -0
  100. package/lib/commonjs/platforms/aws/goDocker.d.ts +2 -0
  101. package/lib/commonjs/platforms/aws/goDocker.js +287 -0
  102. package/lib/commonjs/platforms/aws/goDocker.js.map +1 -0
  103. package/lib/commonjs/platforms/aws/identity.d.ts +2 -0
  104. package/lib/commonjs/platforms/aws/identity.js +26 -0
  105. package/lib/commonjs/platforms/aws/identity.js.map +1 -0
  106. package/lib/commonjs/platforms/aws/index.d.ts +2 -0
  107. package/lib/commonjs/platforms/aws/index.js +19 -0
  108. package/lib/commonjs/platforms/aws/index.js.map +1 -0
  109. package/lib/commonjs/platforms/aws/publish.d.ts +4 -0
  110. package/lib/commonjs/platforms/aws/publish.js +66 -0
  111. package/lib/commonjs/platforms/aws/publish.js.map +1 -0
  112. package/lib/commonjs/platforms/aws/remote.d.ts +11 -0
  113. package/lib/commonjs/platforms/aws/remote.js +106 -0
  114. package/lib/commonjs/platforms/aws/remote.js.map +1 -0
  115. package/lib/commonjs/platforms/aws/stacks.d.ts +7 -0
  116. package/lib/commonjs/platforms/aws/stacks.js +91 -0
  117. package/lib/commonjs/platforms/aws/stacks.js.map +1 -0
  118. package/lib/commonjs/platforms/aws/teardown.d.ts +2 -0
  119. package/lib/commonjs/platforms/aws/teardown.js +59 -0
  120. package/lib/commonjs/platforms/aws/teardown.js.map +1 -0
  121. package/lib/commonjs/platforms/aws/viewsSync.d.ts +2 -0
  122. package/lib/commonjs/platforms/aws/viewsSync.js +39 -0
  123. package/lib/commonjs/platforms/aws/viewsSync.js.map +1 -0
  124. package/lib/commonjs/platforms/docker/go.d.ts +2 -0
  125. package/lib/commonjs/platforms/docker/go.js +160 -0
  126. package/lib/commonjs/platforms/docker/go.js.map +1 -0
  127. package/lib/commonjs/platforms/docker/index.d.ts +2 -0
  128. package/lib/commonjs/platforms/docker/index.js +27 -0
  129. package/lib/commonjs/platforms/docker/index.js.map +1 -0
  130. package/lib/commonjs/platforms/index.d.ts +4 -0
  131. package/lib/commonjs/platforms/index.js +39 -0
  132. package/lib/commonjs/platforms/index.js.map +1 -0
  133. package/lib/commonjs/platforms/types.d.ts +16 -0
  134. package/lib/commonjs/platforms/types.js +9 -0
  135. package/lib/commonjs/platforms/types.js.map +1 -0
  136. package/lib/esm/bin/qpq.d.ts +2 -0
  137. package/lib/esm/bin/qpq.js +4 -0
  138. package/lib/esm/bin/qpq.js.map +1 -0
  139. package/lib/esm/bin/qpqCdkApp.d.ts +1 -0
  140. package/lib/esm/bin/qpqCdkApp.js +6 -0
  141. package/lib/esm/bin/qpqCdkApp.js.map +1 -0
  142. package/lib/esm/cli/index.d.ts +1 -0
  143. package/lib/esm/cli/index.js +2 -0
  144. package/lib/esm/cli/index.js.map +1 -0
  145. package/lib/esm/cli/runCli.d.ts +1 -0
  146. package/lib/esm/cli/runCli.js +67 -0
  147. package/lib/esm/cli/runCli.js.map +1 -0
  148. package/lib/esm/commands/go.d.ts +1 -0
  149. package/lib/esm/commands/go.js +15 -0
  150. package/lib/esm/commands/go.js.map +1 -0
  151. package/lib/esm/commands/goDev.d.ts +1 -0
  152. package/lib/esm/commands/goDev.js +127 -0
  153. package/lib/esm/commands/goDev.js.map +1 -0
  154. package/lib/esm/commands/goDevWeb.d.ts +1 -0
  155. package/lib/esm/commands/goDevWeb.js +107 -0
  156. package/lib/esm/commands/goDevWeb.js.map +1 -0
  157. package/lib/esm/commands/goDocker.d.ts +1 -0
  158. package/lib/esm/commands/goDocker.js +19 -0
  159. package/lib/esm/commands/goDocker.js.map +1 -0
  160. package/lib/esm/commands/hooks.d.ts +1 -0
  161. package/lib/esm/commands/hooks.js +13 -0
  162. package/lib/esm/commands/hooks.js.map +1 -0
  163. package/lib/esm/commands/prep.d.ts +1 -0
  164. package/lib/esm/commands/prep.js +15 -0
  165. package/lib/esm/commands/prep.js.map +1 -0
  166. package/lib/esm/commands/publish.d.ts +4 -0
  167. package/lib/esm/commands/publish.js +38 -0
  168. package/lib/esm/commands/publish.js.map +1 -0
  169. package/lib/esm/commands/synth.d.ts +1 -0
  170. package/lib/esm/commands/synth.js +63 -0
  171. package/lib/esm/commands/synth.js.map +1 -0
  172. package/lib/esm/commands/teardown.d.ts +1 -0
  173. package/lib/esm/commands/teardown.js +20 -0
  174. package/lib/esm/commands/teardown.js.map +1 -0
  175. package/lib/esm/index.d.ts +1 -0
  176. package/lib/esm/index.js +2 -0
  177. package/lib/esm/index.js.map +1 -0
  178. package/lib/esm/lib/args.d.ts +2 -0
  179. package/lib/esm/lib/args.js +16 -0
  180. package/lib/esm/lib/args.js.map +1 -0
  181. package/lib/esm/lib/deployEnv.d.ts +6 -0
  182. package/lib/esm/lib/deployEnv.js +60 -0
  183. package/lib/esm/lib/deployEnv.js.map +1 -0
  184. package/lib/esm/lib/deployPrompts.d.ts +25 -0
  185. package/lib/esm/lib/deployPrompts.js +69 -0
  186. package/lib/esm/lib/deployPrompts.js.map +1 -0
  187. package/lib/esm/lib/devServerEntry.d.ts +1 -0
  188. package/lib/esm/lib/devServerEntry.js +46 -0
  189. package/lib/esm/lib/devServerEntry.js.map +1 -0
  190. package/lib/esm/lib/discovery.d.ts +10 -0
  191. package/lib/esm/lib/discovery.js +40 -0
  192. package/lib/esm/lib/discovery.js.map +1 -0
  193. package/lib/esm/lib/hooks.d.ts +2 -0
  194. package/lib/esm/lib/hooks.js +27 -0
  195. package/lib/esm/lib/hooks.js.map +1 -0
  196. package/lib/esm/lib/packageRoot.d.ts +1 -0
  197. package/lib/esm/lib/packageRoot.js +14 -0
  198. package/lib/esm/lib/packageRoot.js.map +1 -0
  199. package/lib/esm/lib/prompts.d.ts +3 -0
  200. package/lib/esm/lib/prompts.js +16 -0
  201. package/lib/esm/lib/prompts.js.map +1 -0
  202. package/lib/esm/lib/qpqConfigs.d.ts +3 -0
  203. package/lib/esm/lib/qpqConfigs.js +14 -0
  204. package/lib/esm/lib/qpqConfigs.js.map +1 -0
  205. package/lib/esm/lib/resolveAppSelection.d.ts +6 -0
  206. package/lib/esm/lib/resolveAppSelection.js +45 -0
  207. package/lib/esm/lib/resolveAppSelection.js.map +1 -0
  208. package/lib/esm/lib/rspackRun.d.ts +2 -0
  209. package/lib/esm/lib/rspackRun.js +19 -0
  210. package/lib/esm/lib/rspackRun.js.map +1 -0
  211. package/lib/esm/lib/runCommand.d.ts +13 -0
  212. package/lib/esm/lib/runCommand.js +69 -0
  213. package/lib/esm/lib/runCommand.js.map +1 -0
  214. package/lib/esm/lib/runTasks.d.ts +10 -0
  215. package/lib/esm/lib/runTasks.js +28 -0
  216. package/lib/esm/lib/runTasks.js.map +1 -0
  217. package/lib/esm/lib/timing.d.ts +2 -0
  218. package/lib/esm/lib/timing.js +6 -0
  219. package/lib/esm/lib/timing.js.map +1 -0
  220. package/lib/esm/lib/views.d.ts +2 -0
  221. package/lib/esm/lib/views.js +15 -0
  222. package/lib/esm/lib/views.js.map +1 -0
  223. package/lib/esm/platforms/aws/awsCredentials.d.ts +1 -0
  224. package/lib/esm/platforms/aws/awsCredentials.js +15 -0
  225. package/lib/esm/platforms/aws/awsCredentials.js.map +1 -0
  226. package/lib/esm/platforms/aws/cdkApp.d.ts +2 -0
  227. package/lib/esm/platforms/aws/cdkApp.js +11 -0
  228. package/lib/esm/platforms/aws/cdkApp.js.map +1 -0
  229. package/lib/esm/platforms/aws/go.d.ts +2 -0
  230. package/lib/esm/platforms/aws/go.js +100 -0
  231. package/lib/esm/platforms/aws/go.js.map +1 -0
  232. package/lib/esm/platforms/aws/goDocker.d.ts +2 -0
  233. package/lib/esm/platforms/aws/goDocker.js +271 -0
  234. package/lib/esm/platforms/aws/goDocker.js.map +1 -0
  235. package/lib/esm/platforms/aws/identity.d.ts +2 -0
  236. package/lib/esm/platforms/aws/identity.js +22 -0
  237. package/lib/esm/platforms/aws/identity.js.map +1 -0
  238. package/lib/esm/platforms/aws/index.d.ts +2 -0
  239. package/lib/esm/platforms/aws/index.js +16 -0
  240. package/lib/esm/platforms/aws/index.js.map +1 -0
  241. package/lib/esm/platforms/aws/publish.d.ts +4 -0
  242. package/lib/esm/platforms/aws/publish.js +50 -0
  243. package/lib/esm/platforms/aws/publish.js.map +1 -0
  244. package/lib/esm/platforms/aws/remote.d.ts +11 -0
  245. package/lib/esm/platforms/aws/remote.js +90 -0
  246. package/lib/esm/platforms/aws/remote.js.map +1 -0
  247. package/lib/esm/platforms/aws/stacks.d.ts +7 -0
  248. package/lib/esm/platforms/aws/stacks.js +69 -0
  249. package/lib/esm/platforms/aws/stacks.js.map +1 -0
  250. package/lib/esm/platforms/aws/teardown.d.ts +2 -0
  251. package/lib/esm/platforms/aws/teardown.js +46 -0
  252. package/lib/esm/platforms/aws/teardown.js.map +1 -0
  253. package/lib/esm/platforms/aws/viewsSync.d.ts +2 -0
  254. package/lib/esm/platforms/aws/viewsSync.js +25 -0
  255. package/lib/esm/platforms/aws/viewsSync.js.map +1 -0
  256. package/lib/esm/platforms/docker/go.d.ts +2 -0
  257. package/lib/esm/platforms/docker/go.js +143 -0
  258. package/lib/esm/platforms/docker/go.js.map +1 -0
  259. package/lib/esm/platforms/docker/index.d.ts +2 -0
  260. package/lib/esm/platforms/docker/index.js +15 -0
  261. package/lib/esm/platforms/docker/index.js.map +1 -0
  262. package/lib/esm/platforms/index.d.ts +4 -0
  263. package/lib/esm/platforms/index.js +20 -0
  264. package/lib/esm/platforms/index.js.map +1 -0
  265. package/lib/esm/platforms/types.d.ts +16 -0
  266. package/lib/esm/platforms/types.js +6 -0
  267. package/lib/esm/platforms/types.js.map +1 -0
  268. package/package.json +63 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"publish.js","sourceRoot":"","sources":["../../../../src/platforms/aws/publish.ts"],"names":[],"mappings":"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","sourcesContent":["// AWS federated remote publishing — build each backend service as a\n// module-federation remote and publish it into that service's federated code\n// bucket (see ./remote for the three-phase mechanics).\nimport { isAwsCredentialsValid } from './awsCredentials';\nimport { buildRemote, deployRemoteManifest, resolvePublishTarget, uploadRemoteVersion } from './remote';\n\nconst requireAwsCredentials = async (): Promise<void> => {\n if (!(await isAwsCredentialsValid())) {\n console.error('AWS credentials are not valid. Configure them and retry.');\n process.exit(1);\n }\n};\n\nexport const awsPublishBuild = async (appName: string, serviceNames: string[]): Promise<void> => {\n console.log(`Building federated remotes for [${appName}]: ${serviceNames.join(', ')}`);\n\n for (const serviceName of serviceNames) {\n await buildRemote(appName, serviceName);\n }\n\n console.log('Done. Next: qpq publish:upload, then qpq publish:deploy.');\n};\n\nexport const awsPublishUpload = async (appName: string, serviceNames: string[]): Promise<void> => {\n await requireAwsCredentials();\n\n // Resolve every target up front - a missing build fails the whole step\n // before a single byte is uploaded.\n const targets = serviceNames.map((serviceName) => resolvePublishTarget(appName, serviceName));\n\n console.log(`Uploading federated remotes for [${appName}]: ${serviceNames.join(', ')}`);\n await Promise.all(targets.map((target) => uploadRemoteVersion(target)));\n\n console.log('Done. Run qpq publish:deploy to flip lambdas to the new versions.');\n};\n\nexport const awsPublishDeploy = async (appName: string, serviceNames: string[]): Promise<void> => {\n await requireAwsCredentials();\n\n const targets = serviceNames.map((serviceName) => resolvePublishTarget(appName, serviceName));\n\n console.log(`Deploying federated remote manifests for [${appName}]: ${serviceNames.join(', ')}`);\n await Promise.all(targets.map((target) => deployRemoteManifest(target)));\n\n console.log('Done. New lambda cold starts will federate these services from S3.');\n};\n\nexport const awsPublish = async (appName: string, serviceNames: string[]): Promise<void> => {\n await requireAwsCredentials();\n\n console.log(`Publishing federated remotes for [${appName}]: ${serviceNames.join(', ')}`);\n\n // 1. Build everything first - any build failure bails before any upload,\n // so the buckets never end up with a half-published set of services.\n for (const serviceName of serviceNames) {\n await buildRemote(appName, serviceName);\n }\n const targets = serviceNames.map((serviceName) => resolvePublishTarget(appName, serviceName));\n\n // 2. Upload all version dirs in parallel - manifests untouched, nothing live yet.\n await Promise.all(targets.map((target) => uploadRemoteVersion(target)));\n\n // 3. Every version dir is fully uploaded - flip the manifests, in parallel.\n await Promise.all(targets.map((target) => deployRemoteManifest(target)));\n\n console.log('Done. New lambda cold starts will federate these services from S3.');\n};\n"]}
@@ -0,0 +1,11 @@
1
+ export type RemotePublishTarget = {
2
+ serviceName: string;
3
+ publishPath: string;
4
+ manifestHash: string;
5
+ bucketName: string;
6
+ servicePrefix: string;
7
+ };
8
+ export declare const buildRemote: (appName: string, serviceName: string) => Promise<void>;
9
+ export declare const resolvePublishTarget: (appName: string, serviceName: string) => RemotePublishTarget;
10
+ export declare const uploadRemoteVersion: (target: RemotePublishTarget) => Promise<void>;
11
+ export declare const deployRemoteManifest: (target: RemotePublishTarget) => Promise<void>;
@@ -0,0 +1,90 @@
1
+ // Build a backend service as a module-federation remote and publish it into the
2
+ // shared federated-code storage drive, under the service's own prefix. After this
3
+ // runs, the already-deployed lambdas load their stories from the bucket (quidproquo's
4
+ // dynamicModuleLoader tries the federated store first, falls back to the bundled
5
+ // code when nothing's published).
6
+ //
7
+ // The store is one storage drive shared across services (via `owner`). Each service
8
+ // opts in with defineFederatedModuleStore(<driveName>) and its lambdas read from
9
+ // s3://<bucket>/<service>. Read access comes from the storage drive's own grants, so
10
+ // the drive + a deploy of each service must exist before publishing. The bucket name
11
+ // resolves from the same service config the deploy used, so it always matches.
12
+ //
13
+ // Publishing is split into three phases so they can run as separate commands
14
+ // (publish:build / publish:upload / publish:deploy) or chained by `qpq publish`:
15
+ // buildRemote - rspack the remote + lay out service-remote-published/
16
+ // uploadRemoteVersion - sync the hashed version dir (everything BUT manifest.json)
17
+ // deployRemoteManifest - upload manifest.json, atomically flipping lambdas over
18
+ // Version files always land before the manifest that references them, so a reading
19
+ // lambda never sees a manifest whose files aren't all present yet.
20
+ import { awsNamingUtils } from 'quidproquo-actionprocessor-awslambda';
21
+ import { qpqCoreUtils } from 'quidproquo-core';
22
+ import { getServiceRemoteRspackConfig, publishFederatedRemote } from 'quidproquo-deploy-rspack';
23
+ import fs from 'fs';
24
+ import path from 'path';
25
+ import { getRoot, getServiceDirectory } from '../../lib/discovery';
26
+ import { loadServiceQpqConfig } from '../../lib/qpqConfigs';
27
+ import { runRspack } from '../../lib/rspackRun';
28
+ import { runCommand } from '../../lib/runCommand';
29
+ const getPublishPath = (appName, serviceName) => path.join(getRoot(), 'dist', 'apps', appName, 'services', serviceName, 'service-remote-published');
30
+ // Resolve the shared store bucket from the service's defineFederatedModuleStore
31
+ // setting (same derivation the lambda env var uses) and the per-service prefix
32
+ // so many services share one bucket.
33
+ const resolveRemoteStore = (appName, serviceName) => {
34
+ const qpqConfig = loadServiceQpqConfig(appName, serviceName);
35
+ const federatedStore = qpqCoreUtils.getFederatedModuleStore(qpqConfig);
36
+ if (!federatedStore) {
37
+ throw new Error(`service [${serviceName}] has no defineFederatedModuleStore(...) - add it (and the matching storage drive) to opt into federation`);
38
+ }
39
+ const storageDrive = qpqCoreUtils.getStorageDriveByName(federatedStore.storageDrive, qpqConfig);
40
+ if (!storageDrive) {
41
+ throw new Error(`defineFederatedModuleStore references storage drive [${federatedStore.storageDrive}] which service [${serviceName}] does not declare`);
42
+ }
43
+ const bucketName = awsNamingUtils.resolveConfigRuntimeResourceNameFromConfig(storageDrive.owner?.resourceNameOverride || storageDrive.storageDrive, qpqConfig, storageDrive.owner);
44
+ const servicePrefix = qpqCoreUtils.getApplicationModuleName(qpqConfig);
45
+ return { bucketName, servicePrefix };
46
+ };
47
+ // Phase 1: rspack the federated remote container and lay out the publishable
48
+ // version dir + manifest.json under service-remote-published/. Validates the
49
+ // federation config up front so a misconfigured service fails before the build.
50
+ export const buildRemote = async (appName, serviceName) => {
51
+ resolveRemoteStore(appName, serviceName);
52
+ const serviceDir = path.join(getServiceDirectory(appName, serviceName), 'service');
53
+ const qpqConfig = loadServiceQpqConfig(appName, serviceName);
54
+ console.log(`Building federated remote: [${serviceName}]`);
55
+ const config = getServiceRemoteRspackConfig(qpqConfig, serviceDir);
56
+ await runRspack(config);
57
+ const remoteBuildPath = config.output.path;
58
+ publishFederatedRemote(qpqConfig, remoteBuildPath, getPublishPath(appName, serviceName));
59
+ };
60
+ // Resolve a publish target from a prior buildRemote's on-disk output.
61
+ export const resolvePublishTarget = (appName, serviceName) => {
62
+ const publishPath = getPublishPath(appName, serviceName);
63
+ const manifestPath = path.join(publishPath, 'manifest.json');
64
+ if (!fs.existsSync(manifestPath)) {
65
+ throw new Error(`no built remote found for [${serviceName}] (missing ${manifestPath}) - run \`qpq publish:build --app ${appName}\` first`);
66
+ }
67
+ const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf-8'));
68
+ return {
69
+ serviceName,
70
+ publishPath,
71
+ manifestHash: manifest.hash,
72
+ ...resolveRemoteStore(appName, serviceName),
73
+ };
74
+ };
75
+ // Phase 2: upload the hashed version dir - everything EXCEPT manifest.json, so
76
+ // nothing referenced by a live manifest changes. Safe to run concurrently across
77
+ // services - each writes only under its own prefix.
78
+ export const uploadRemoteVersion = async (target) => {
79
+ const { serviceName, publishPath, manifestHash, bucketName, servicePrefix } = target;
80
+ console.log(`Uploading [${serviceName}] version [${manifestHash}] to [s3://${bucketName}/${servicePrefix}/${manifestHash}]`);
81
+ await runCommand('aws', ['s3', 'sync', path.join(publishPath, manifestHash), `s3://${bucketName}/${servicePrefix}/${manifestHash}`]);
82
+ };
83
+ // Phase 3: upload manifest.json, the pointer lambdas read - this is the moment
84
+ // the new version goes live. Only run once the version dir is fully uploaded.
85
+ export const deployRemoteManifest = async (target) => {
86
+ const { serviceName, publishPath, manifestHash, bucketName, servicePrefix } = target;
87
+ console.log(`Deploying [${serviceName}] manifest for version [${manifestHash}] to [s3://${bucketName}/${servicePrefix}/manifest.json]`);
88
+ await runCommand('aws', ['s3', 'cp', path.join(publishPath, 'manifest.json'), `s3://${bucketName}/${servicePrefix}/manifest.json`]);
89
+ };
90
+ //# sourceMappingURL=remote.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remote.js","sourceRoot":"","sources":["../../../../src/platforms/aws/remote.ts"],"names":[],"mappings":"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","sourcesContent":["// Build a backend service as a module-federation remote and publish it into the\n// shared federated-code storage drive, under the service's own prefix. After this\n// runs, the already-deployed lambdas load their stories from the bucket (quidproquo's\n// dynamicModuleLoader tries the federated store first, falls back to the bundled\n// code when nothing's published).\n//\n// The store is one storage drive shared across services (via `owner`). Each service\n// opts in with defineFederatedModuleStore(<driveName>) and its lambdas read from\n// s3://<bucket>/<service>. Read access comes from the storage drive's own grants, so\n// the drive + a deploy of each service must exist before publishing. The bucket name\n// resolves from the same service config the deploy used, so it always matches.\n//\n// Publishing is split into three phases so they can run as separate commands\n// (publish:build / publish:upload / publish:deploy) or chained by `qpq publish`:\n// buildRemote - rspack the remote + lay out service-remote-published/\n// uploadRemoteVersion - sync the hashed version dir (everything BUT manifest.json)\n// deployRemoteManifest - upload manifest.json, atomically flipping lambdas over\n// Version files always land before the manifest that references them, so a reading\n// lambda never sees a manifest whose files aren't all present yet.\nimport { awsNamingUtils } from 'quidproquo-actionprocessor-awslambda';\nimport { qpqCoreUtils } from 'quidproquo-core';\nimport { getServiceRemoteRspackConfig, publishFederatedRemote } from 'quidproquo-deploy-rspack';\n\nimport fs from 'fs';\nimport path from 'path';\n\nimport { getRoot, getServiceDirectory } from '../../lib/discovery';\nimport { loadServiceQpqConfig } from '../../lib/qpqConfigs';\nimport { runRspack } from '../../lib/rspackRun';\nimport { runCommand } from '../../lib/runCommand';\n\n// Everything the upload/deploy phases need to publish a built remote. Resolved\n// from the on-disk build output + service config, so each phase can run in its\n// own process without handing state between commands.\nexport type RemotePublishTarget = {\n serviceName: string;\n publishPath: string;\n manifestHash: string;\n bucketName: string;\n servicePrefix: string;\n};\n\nconst getPublishPath = (appName: string, serviceName: string): string =>\n path.join(getRoot(), 'dist', 'apps', appName, 'services', serviceName, 'service-remote-published');\n\n// Resolve the shared store bucket from the service's defineFederatedModuleStore\n// setting (same derivation the lambda env var uses) and the per-service prefix\n// so many services share one bucket.\nconst resolveRemoteStore = (appName: string, serviceName: string): { bucketName: string; servicePrefix: string } => {\n const qpqConfig = loadServiceQpqConfig(appName, serviceName);\n\n const federatedStore = qpqCoreUtils.getFederatedModuleStore(qpqConfig);\n if (!federatedStore) {\n throw new Error(\n `service [${serviceName}] has no defineFederatedModuleStore(...) - add it (and the matching storage drive) to opt into federation`,\n );\n }\n const storageDrive = qpqCoreUtils.getStorageDriveByName(federatedStore.storageDrive, qpqConfig);\n if (!storageDrive) {\n throw new Error(\n `defineFederatedModuleStore references storage drive [${federatedStore.storageDrive}] which service [${serviceName}] does not declare`,\n );\n }\n const bucketName = awsNamingUtils.resolveConfigRuntimeResourceNameFromConfig(\n storageDrive.owner?.resourceNameOverride || storageDrive.storageDrive,\n qpqConfig,\n storageDrive.owner,\n );\n const servicePrefix = qpqCoreUtils.getApplicationModuleName(qpqConfig);\n\n return { bucketName, servicePrefix };\n};\n\n// Phase 1: rspack the federated remote container and lay out the publishable\n// version dir + manifest.json under service-remote-published/. Validates the\n// federation config up front so a misconfigured service fails before the build.\nexport const buildRemote = async (appName: string, serviceName: string): Promise<void> => {\n resolveRemoteStore(appName, serviceName);\n\n const serviceDir = path.join(getServiceDirectory(appName, serviceName), 'service');\n const qpqConfig = loadServiceQpqConfig(appName, serviceName);\n\n console.log(`Building federated remote: [${serviceName}]`);\n const config = getServiceRemoteRspackConfig(qpqConfig, serviceDir);\n await runRspack(config);\n\n const remoteBuildPath = config.output!.path as string;\n publishFederatedRemote(qpqConfig, remoteBuildPath, getPublishPath(appName, serviceName));\n};\n\n// Resolve a publish target from a prior buildRemote's on-disk output.\nexport const resolvePublishTarget = (appName: string, serviceName: string): RemotePublishTarget => {\n const publishPath = getPublishPath(appName, serviceName);\n const manifestPath = path.join(publishPath, 'manifest.json');\n\n if (!fs.existsSync(manifestPath)) {\n throw new Error(`no built remote found for [${serviceName}] (missing ${manifestPath}) - run \\`qpq publish:build --app ${appName}\\` first`);\n }\n const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf-8')) as {\n hash: string;\n };\n\n return {\n serviceName,\n publishPath,\n manifestHash: manifest.hash,\n ...resolveRemoteStore(appName, serviceName),\n };\n};\n\n// Phase 2: upload the hashed version dir - everything EXCEPT manifest.json, so\n// nothing referenced by a live manifest changes. Safe to run concurrently across\n// services - each writes only under its own prefix.\nexport const uploadRemoteVersion = async (target: RemotePublishTarget): Promise<void> => {\n const { serviceName, publishPath, manifestHash, bucketName, servicePrefix } = target;\n\n console.log(`Uploading [${serviceName}] version [${manifestHash}] to [s3://${bucketName}/${servicePrefix}/${manifestHash}]`);\n await runCommand('aws', ['s3', 'sync', path.join(publishPath, manifestHash), `s3://${bucketName}/${servicePrefix}/${manifestHash}`]);\n};\n\n// Phase 3: upload manifest.json, the pointer lambdas read - this is the moment\n// the new version goes live. Only run once the version dir is fully uploaded.\nexport const deployRemoteManifest = async (target: RemotePublishTarget): Promise<void> => {\n const { serviceName, publishPath, manifestHash, bucketName, servicePrefix } = target;\n\n console.log(`Deploying [${serviceName}] manifest for version [${manifestHash}] to [s3://${bucketName}/${servicePrefix}/manifest.json]`);\n await runCommand('aws', ['s3', 'cp', path.join(publishPath, 'manifest.json'), `s3://${bucketName}/${servicePrefix}/manifest.json`]);\n};\n"]}
@@ -0,0 +1,7 @@
1
+ export declare const deployStack: (stackName: string, env?: Record<string, string>) => Promise<void>;
2
+ export declare const deployServiceStack: (serviceName: string, stackName: string, appName: string) => Promise<void>;
3
+ export declare const destroyStack: (stackName: string, env?: Record<string, string>) => Promise<void>;
4
+ export declare const destroyServiceStack: (serviceName: string, stackName: string, appName: string) => Promise<void>;
5
+ export declare const deployDomainStack: (appName: string) => Promise<void>;
6
+ export declare const deployAccountStack: (appName: string) => Promise<void>;
7
+ export declare const deployBootstrapStack: (appName: string) => Promise<void>;
@@ -0,0 +1,69 @@
1
+ // Host-side `cdk deploy` helpers. No cdk.json anywhere: the CDK app command is
2
+ // passed via --app and runs quidproquo-deploy-awscdk's generic workspace app
3
+ // (bin/qpq-cdk-app.js) under ts-node hooks, with DEPLOY_* in the env.
4
+ import { qpqDeployAwsCdkUtils } from 'quidproquo-deploy-awscdk';
5
+ import path from 'path';
6
+ import { getRoot, getServiceNames } from '../../lib/discovery';
7
+ import { getAppPrefix, loadServiceQpqConfig } from '../../lib/qpqConfigs';
8
+ import { runCommand } from '../../lib/runCommand';
9
+ import { logTimeEnd, logTimeStart } from '../../lib/timing';
10
+ import { getCdkAppCommand } from './cdkApp';
11
+ export const deployStack = async (stackName, env = {}) => {
12
+ logTimeStart(stackName);
13
+ await runCommand('npx', ['cdk', 'deploy', stackName, '--require-approval', 'never', '--app', `'${getCdkAppCommand()}'`, '--output', path.join('dist', 'qpq', 'cdk.out')], {
14
+ cwd: getRoot(),
15
+ env,
16
+ });
17
+ logTimeEnd(stackName);
18
+ };
19
+ export const deployServiceStack = (serviceName, stackName, appName) => deployStack(stackName, {
20
+ DEPLOY_SERVICE_NAME: serviceName,
21
+ DEPLOY_APP_NAME: appName,
22
+ });
23
+ // `cdk destroy` still synths the app to find the stack, so it runs the same
24
+ // generic workspace app with the same DEPLOY_* env as deploys — meaning the
25
+ // service bundles under dist/ must exist for asset resolution to succeed.
26
+ export const destroyStack = async (stackName, env = {}) => {
27
+ logTimeStart(stackName);
28
+ await runCommand('npx', ['cdk', 'destroy', stackName, '--force', '--app', `'${getCdkAppCommand()}'`, '--output', path.join('dist', 'qpq', 'cdk.out')], {
29
+ cwd: getRoot(),
30
+ env,
31
+ });
32
+ logTimeEnd(stackName);
33
+ };
34
+ export const destroyServiceStack = (serviceName, stackName, appName) => destroyStack(stackName, {
35
+ DEPLOY_SERVICE_NAME: serviceName,
36
+ DEPLOY_APP_NAME: appName,
37
+ });
38
+ export const deployDomainStack = async (appName) => {
39
+ const qpqConfig = loadServiceQpqConfig(appName, getServiceNames(appName)[0]);
40
+ const stackName = qpqDeployAwsCdkUtils.getDomainStackName(qpqConfig);
41
+ console.log('Deploy Domain: ', stackName);
42
+ await deployStack(stackName, {
43
+ DEPLOY_SERVICE_NAME: '',
44
+ DEPLOY_APP_NAME: appName,
45
+ });
46
+ };
47
+ // Account-level guardrails stack - statically named (one per AWS account,
48
+ // app-agnostic), so no config load is needed to know the name. Callers decide
49
+ // whether an actor deploy should include it (bootstrap skips it; the explicit
50
+ // 'account' menu option always deploys).
51
+ export const deployAccountStack = async (appName) => {
52
+ const stackName = qpqDeployAwsCdkUtils.getAccountStackName();
53
+ console.log('Deploy Account: ', stackName);
54
+ await deployStack(stackName, {
55
+ DEPLOY_SERVICE_NAME: '',
56
+ DEPLOY_APP_NAME: appName,
57
+ });
58
+ };
59
+ export const deployBootstrapStack = async (appName) => {
60
+ const appPrefix = getAppPrefix(appName);
61
+ const stackName = process.env.ACTOR_NAME
62
+ ? `${appPrefix}-${process.env.ENVIRONMENT}-${process.env.ACTOR_NAME}-bs`
63
+ : `${appPrefix}-${process.env.ENVIRONMENT}-bs`;
64
+ await deployStack(stackName, {
65
+ DEPLOY_SERVICE_NAME: '',
66
+ DEPLOY_APP_NAME: appName,
67
+ });
68
+ };
69
+ //# sourceMappingURL=stacks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stacks.js","sourceRoot":"","sources":["../../../../src/platforms/aws/stacks.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,6EAA6E;AAC7E,sEAAsE;AACtE,OAAO,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAEhE,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,OAAO,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAC/D,OAAO,EAAE,YAAY,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC1E,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAC5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAE5C,MAAM,CAAC,MAAM,WAAW,GAAG,KAAK,EAAE,SAAiB,EAAE,MAA8B,EAAE,EAAiB,EAAE;IACtG,YAAY,CAAC,SAAS,CAAC,CAAC;IACxB,MAAM,UAAU,CACd,KAAK,EACL,CAAC,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,oBAAoB,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,gBAAgB,EAAE,GAAG,EAAE,UAAU,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,SAAS,CAAC,CAAC,EAChJ;QACE,GAAG,EAAE,OAAO,EAAE;QACd,GAAG;KACJ,CACF,CAAC;IACF,UAAU,CAAC,SAAS,CAAC,CAAC;AACxB,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,WAAmB,EAAE,SAAiB,EAAE,OAAe,EAAiB,EAAE,CAC3G,WAAW,CAAC,SAAS,EAAE;IACrB,mBAAmB,EAAE,WAAW;IAChC,eAAe,EAAE,OAAO;CACzB,CAAC,CAAC;AAEL,4EAA4E;AAC5E,4EAA4E;AAC5E,0EAA0E;AAC1E,MAAM,CAAC,MAAM,YAAY,GAAG,KAAK,EAAE,SAAiB,EAAE,MAA8B,EAAE,EAAiB,EAAE;IACvG,YAAY,CAAC,SAAS,CAAC,CAAC;IACxB,MAAM,UAAU,CACd,KAAK,EACL,CAAC,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,OAAO,EAAE,IAAI,gBAAgB,EAAE,GAAG,EAAE,UAAU,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,SAAS,CAAC,CAAC,EAC7H;QACE,GAAG,EAAE,OAAO,EAAE;QACd,GAAG;KACJ,CACF,CAAC;IACF,UAAU,CAAC,SAAS,CAAC,CAAC;AACxB,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,WAAmB,EAAE,SAAiB,EAAE,OAAe,EAAiB,EAAE,CAC5G,YAAY,CAAC,SAAS,EAAE;IACtB,mBAAmB,EAAE,WAAW;IAChC,eAAe,EAAE,OAAO;CACzB,CAAC,CAAC;AAEL,MAAM,CAAC,MAAM,iBAAiB,GAAG,KAAK,EAAE,OAAe,EAAiB,EAAE;IACxE,MAAM,SAAS,GAAG,oBAAoB,CAAC,OAAO,EAAE,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC7E,MAAM,SAAS,GAAG,oBAAoB,CAAC,kBAAkB,CAAC,SAAS,CAAC,CAAC;IACrE,OAAO,CAAC,GAAG,CAAC,iBAAiB,EAAE,SAAS,CAAC,CAAC;IAC1C,MAAM,WAAW,CAAC,SAAS,EAAE;QAC3B,mBAAmB,EAAE,EAAE;QACvB,eAAe,EAAE,OAAO;KACzB,CAAC,CAAC;AACL,CAAC,CAAC;AAEF,0EAA0E;AAC1E,8EAA8E;AAC9E,8EAA8E;AAC9E,yCAAyC;AACzC,MAAM,CAAC,MAAM,kBAAkB,GAAG,KAAK,EAAE,OAAe,EAAiB,EAAE;IACzE,MAAM,SAAS,GAAG,oBAAoB,CAAC,mBAAmB,EAAE,CAAC;IAC7D,OAAO,CAAC,GAAG,CAAC,kBAAkB,EAAE,SAAS,CAAC,CAAC;IAC3C,MAAM,WAAW,CAAC,SAAS,EAAE;QAC3B,mBAAmB,EAAE,EAAE;QACvB,eAAe,EAAE,OAAO;KACzB,CAAC,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,oBAAoB,GAAG,KAAK,EAAE,OAAe,EAAiB,EAAE;IAC3E,MAAM,SAAS,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC;IACxC,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,UAAU;QACtC,CAAC,CAAC,GAAG,SAAS,IAAI,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,OAAO,CAAC,GAAG,CAAC,UAAU,KAAK;QACxE,CAAC,CAAC,GAAG,SAAS,IAAI,OAAO,CAAC,GAAG,CAAC,WAAW,KAAK,CAAC;IACjD,MAAM,WAAW,CAAC,SAAS,EAAE;QAC3B,mBAAmB,EAAE,EAAE;QACvB,eAAe,EAAE,OAAO;KACzB,CAAC,CAAC;AACL,CAAC,CAAC","sourcesContent":["// Host-side `cdk deploy` helpers. No cdk.json anywhere: the CDK app command is\n// passed via --app and runs quidproquo-deploy-awscdk's generic workspace app\n// (bin/qpq-cdk-app.js) under ts-node hooks, with DEPLOY_* in the env.\nimport { qpqDeployAwsCdkUtils } from 'quidproquo-deploy-awscdk';\n\nimport path from 'path';\n\nimport { getRoot, getServiceNames } from '../../lib/discovery';\nimport { getAppPrefix, loadServiceQpqConfig } from '../../lib/qpqConfigs';\nimport { runCommand } from '../../lib/runCommand';\nimport { logTimeEnd, logTimeStart } from '../../lib/timing';\nimport { getCdkAppCommand } from './cdkApp';\n\nexport const deployStack = async (stackName: string, env: Record<string, string> = {}): Promise<void> => {\n logTimeStart(stackName);\n await runCommand(\n 'npx',\n ['cdk', 'deploy', stackName, '--require-approval', 'never', '--app', `'${getCdkAppCommand()}'`, '--output', path.join('dist', 'qpq', 'cdk.out')],\n {\n cwd: getRoot(),\n env,\n },\n );\n logTimeEnd(stackName);\n};\n\nexport const deployServiceStack = (serviceName: string, stackName: string, appName: string): Promise<void> =>\n deployStack(stackName, {\n DEPLOY_SERVICE_NAME: serviceName,\n DEPLOY_APP_NAME: appName,\n });\n\n// `cdk destroy` still synths the app to find the stack, so it runs the same\n// generic workspace app with the same DEPLOY_* env as deploys — meaning the\n// service bundles under dist/ must exist for asset resolution to succeed.\nexport const destroyStack = async (stackName: string, env: Record<string, string> = {}): Promise<void> => {\n logTimeStart(stackName);\n await runCommand(\n 'npx',\n ['cdk', 'destroy', stackName, '--force', '--app', `'${getCdkAppCommand()}'`, '--output', path.join('dist', 'qpq', 'cdk.out')],\n {\n cwd: getRoot(),\n env,\n },\n );\n logTimeEnd(stackName);\n};\n\nexport const destroyServiceStack = (serviceName: string, stackName: string, appName: string): Promise<void> =>\n destroyStack(stackName, {\n DEPLOY_SERVICE_NAME: serviceName,\n DEPLOY_APP_NAME: appName,\n });\n\nexport const deployDomainStack = async (appName: string): Promise<void> => {\n const qpqConfig = loadServiceQpqConfig(appName, getServiceNames(appName)[0]);\n const stackName = qpqDeployAwsCdkUtils.getDomainStackName(qpqConfig);\n console.log('Deploy Domain: ', stackName);\n await deployStack(stackName, {\n DEPLOY_SERVICE_NAME: '',\n DEPLOY_APP_NAME: appName,\n });\n};\n\n// Account-level guardrails stack - statically named (one per AWS account,\n// app-agnostic), so no config load is needed to know the name. Callers decide\n// whether an actor deploy should include it (bootstrap skips it; the explicit\n// 'account' menu option always deploys).\nexport const deployAccountStack = async (appName: string): Promise<void> => {\n const stackName = qpqDeployAwsCdkUtils.getAccountStackName();\n console.log('Deploy Account: ', stackName);\n await deployStack(stackName, {\n DEPLOY_SERVICE_NAME: '',\n DEPLOY_APP_NAME: appName,\n });\n};\n\nexport const deployBootstrapStack = async (appName: string): Promise<void> => {\n const appPrefix = getAppPrefix(appName);\n const stackName = process.env.ACTOR_NAME\n ? `${appPrefix}-${process.env.ENVIRONMENT}-${process.env.ACTOR_NAME}-bs`\n : `${appPrefix}-${process.env.ENVIRONMENT}-bs`;\n await deployStack(stackName, {\n DEPLOY_SERVICE_NAME: '',\n DEPLOY_APP_NAME: appName,\n });\n};\n"]}
@@ -0,0 +1,2 @@
1
+ import { TeardownPlan } from '../../lib/deployPrompts';
2
+ export declare const awsTeardown: (appName: string, plan: TeardownPlan) => Promise<void>;
@@ -0,0 +1,46 @@
1
+ // AWS sequential teardown (`qpq teardown`) — the stack phases of `qpq go` in
2
+ // reverse. Per phase it destroys every selected service's web, then api, then
3
+ // inf CDK stacks. Phases don't cross-reference each other's CFN outputs
4
+ // (values flow through SSM), so this order is prudence, not a hard dependency.
5
+ // Bootstrap, domain and account stacks are deliberately out of scope — they
6
+ // outlive any one service and are torn down by hand if ever.
7
+ import { qpqDeployAwsCdkUtils } from 'quidproquo-deploy-awscdk';
8
+ import { synthCommand } from '../../commands/synth';
9
+ import { loadServiceQpqConfig } from '../../lib/qpqConfigs';
10
+ import { logTimeEnd, logTimeStart } from '../../lib/timing';
11
+ import { isAwsCredentialsValid } from './awsCredentials';
12
+ import { destroyServiceStack } from './stacks';
13
+ const teardownPhases = [
14
+ { label: 'Web', getStackName: qpqDeployAwsCdkUtils.getWebStackName },
15
+ { label: 'Api', getStackName: qpqDeployAwsCdkUtils.getApiStackName },
16
+ { label: 'Inf', getStackName: qpqDeployAwsCdkUtils.getInfStackName },
17
+ ];
18
+ export const awsTeardown = async (appName, plan) => {
19
+ if (plan.kind === 'cancelled') {
20
+ return;
21
+ }
22
+ const { services } = plan;
23
+ console.log('\n\nRunning automated teardown\n\n');
24
+ console.log('Executing for services');
25
+ console.log(services.join(', '));
26
+ if ((await isAwsCredentialsValid()) === false) {
27
+ console.log('Credentials are expired or invalid.');
28
+ return;
29
+ }
30
+ logTimeStart('totalTime');
31
+ // The stack-name utils and the cdk app both read the synthed QPQ configs.
32
+ await services.reduce(async (cur, service) => {
33
+ await cur;
34
+ await synthCommand([service, '--app', appName]);
35
+ }, Promise.resolve());
36
+ for (const { label, getStackName } of teardownPhases) {
37
+ await services.reduce(async (cur, service) => {
38
+ await cur;
39
+ const qpqConfigForService = loadServiceQpqConfig(appName, service);
40
+ console.log(`Destroy ${label}: `, service);
41
+ await destroyServiceStack(service, getStackName(qpqConfigForService), appName);
42
+ }, Promise.resolve());
43
+ }
44
+ logTimeEnd('totalTime');
45
+ };
46
+ //# sourceMappingURL=teardown.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"teardown.js","sourceRoot":"","sources":["../../../../src/platforms/aws/teardown.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,8EAA8E;AAC9E,wEAAwE;AACxE,+EAA+E;AAC/E,4EAA4E;AAC5E,6DAA6D;AAC7D,OAAO,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAEhE,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAEpD,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAC5D,OAAO,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAE/C,MAAM,cAAc,GAAG;IACrB,EAAE,KAAK,EAAE,KAAK,EAAE,YAAY,EAAE,oBAAoB,CAAC,eAAe,EAAE;IACpE,EAAE,KAAK,EAAE,KAAK,EAAE,YAAY,EAAE,oBAAoB,CAAC,eAAe,EAAE;IACpE,EAAE,KAAK,EAAE,KAAK,EAAE,YAAY,EAAE,oBAAoB,CAAC,eAAe,EAAE;CACrE,CAAC;AAEF,MAAM,CAAC,MAAM,WAAW,GAAG,KAAK,EAAE,OAAe,EAAE,IAAkB,EAAiB,EAAE;IACtF,IAAI,IAAI,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;QAC9B,OAAO;IACT,CAAC;IAED,MAAM,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC;IAE1B,OAAO,CAAC,GAAG,CAAC,oCAAoC,CAAC,CAAC;IAClD,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAC;IACtC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IAEjC,IAAI,CAAC,MAAM,qBAAqB,EAAE,CAAC,KAAK,KAAK,EAAE,CAAC;QAC9C,OAAO,CAAC,GAAG,CAAC,qCAAqC,CAAC,CAAC;QACnD,OAAO;IACT,CAAC;IAED,YAAY,CAAC,WAAW,CAAC,CAAC;IAE1B,0EAA0E;IAC1E,MAAM,QAAQ,CAAC,MAAM,CAAC,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE;QAC3C,MAAM,GAAG,CAAC;QACV,MAAM,YAAY,CAAC,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;IAClD,CAAC,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;IAEtB,KAAK,MAAM,EAAE,KAAK,EAAE,YAAY,EAAE,IAAI,cAAc,EAAE,CAAC;QACrD,MAAM,QAAQ,CAAC,MAAM,CAAC,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE;YAC3C,MAAM,GAAG,CAAC;YACV,MAAM,mBAAmB,GAAG,oBAAoB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YACnE,OAAO,CAAC,GAAG,CAAC,WAAW,KAAK,IAAI,EAAE,OAAO,CAAC,CAAC;YAC3C,MAAM,mBAAmB,CAAC,OAAO,EAAE,YAAY,CAAC,mBAAmB,CAAC,EAAE,OAAO,CAAC,CAAC;QACjF,CAAC,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;IACxB,CAAC;IAED,UAAU,CAAC,WAAW,CAAC,CAAC;AAC1B,CAAC,CAAC","sourcesContent":["// AWS sequential teardown (`qpq teardown`) — the stack phases of `qpq go` in\n// reverse. Per phase it destroys every selected service's web, then api, then\n// inf CDK stacks. Phases don't cross-reference each other's CFN outputs\n// (values flow through SSM), so this order is prudence, not a hard dependency.\n// Bootstrap, domain and account stacks are deliberately out of scope — they\n// outlive any one service and are torn down by hand if ever.\nimport { qpqDeployAwsCdkUtils } from 'quidproquo-deploy-awscdk';\n\nimport { synthCommand } from '../../commands/synth';\nimport { TeardownPlan } from '../../lib/deployPrompts';\nimport { loadServiceQpqConfig } from '../../lib/qpqConfigs';\nimport { logTimeEnd, logTimeStart } from '../../lib/timing';\nimport { isAwsCredentialsValid } from './awsCredentials';\nimport { destroyServiceStack } from './stacks';\n\nconst teardownPhases = [\n { label: 'Web', getStackName: qpqDeployAwsCdkUtils.getWebStackName },\n { label: 'Api', getStackName: qpqDeployAwsCdkUtils.getApiStackName },\n { label: 'Inf', getStackName: qpqDeployAwsCdkUtils.getInfStackName },\n];\n\nexport const awsTeardown = async (appName: string, plan: TeardownPlan): Promise<void> => {\n if (plan.kind === 'cancelled') {\n return;\n }\n\n const { services } = plan;\n\n console.log('\\n\\nRunning automated teardown\\n\\n');\n console.log('Executing for services');\n console.log(services.join(', '));\n\n if ((await isAwsCredentialsValid()) === false) {\n console.log('Credentials are expired or invalid.');\n return;\n }\n\n logTimeStart('totalTime');\n\n // The stack-name utils and the cdk app both read the synthed QPQ configs.\n await services.reduce(async (cur, service) => {\n await cur;\n await synthCommand([service, '--app', appName]);\n }, Promise.resolve());\n\n for (const { label, getStackName } of teardownPhases) {\n await services.reduce(async (cur, service) => {\n await cur;\n const qpqConfigForService = loadServiceQpqConfig(appName, service);\n console.log(`Destroy ${label}: `, service);\n await destroyServiceStack(service, getStackName(qpqConfigForService), appName);\n }, Promise.resolve());\n }\n\n logTimeEnd('totalTime');\n};\n"]}
@@ -0,0 +1,2 @@
1
+ export declare const getViewsS3Destinations: (appName: string, serviceName: string) => string[];
2
+ export declare const syncViewsToS3: (appName: string, serviceName: string) => Promise<void>;
@@ -0,0 +1,25 @@
1
+ // Views upload to S3. Bucket names resolve from the shell service's config.
2
+ // shell is the module-federation host: its bundle is the root website, so it
3
+ // syncs to the 'website' bucket root AND to its prefix in the shared 'views'
4
+ // bucket (where every other service's views live).
5
+ import { awsNamingUtils } from 'quidproquo-actionprocessor-awslambda';
6
+ import { loadServiceQpqConfig } from '../../lib/qpqConfigs';
7
+ import { runCommand } from '../../lib/runCommand';
8
+ import { getViewsDistDir } from '../../lib/views';
9
+ export const getViewsS3Destinations = (appName, serviceName) => {
10
+ const shellConfig = loadServiceQpqConfig(appName, 'shell');
11
+ const viewsBucketName = awsNamingUtils.getConfigRuntimeResourceNameFromConfig('views', shellConfig);
12
+ const destinations = [`s3://${viewsBucketName}/${serviceName}`];
13
+ if (serviceName === 'shell') {
14
+ const websiteBucketName = awsNamingUtils.getConfigRuntimeResourceNameFromConfig('website', shellConfig);
15
+ destinations.push(`s3://${websiteBucketName}`);
16
+ }
17
+ return destinations;
18
+ };
19
+ export const syncViewsToS3 = async (appName, serviceName) => {
20
+ for (const destination of getViewsS3Destinations(appName, serviceName)) {
21
+ console.log(`Copying [${serviceName}] views to [${destination}]`);
22
+ await runCommand('aws', ['s3', 'sync', getViewsDistDir(appName, serviceName), destination]);
23
+ }
24
+ };
25
+ //# sourceMappingURL=viewsSync.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"viewsSync.js","sourceRoot":"","sources":["../../../../src/platforms/aws/viewsSync.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,6EAA6E;AAC7E,6EAA6E;AAC7E,mDAAmD;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,sCAAsC,CAAC;AAEtE,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAElD,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,OAAe,EAAE,WAAmB,EAAY,EAAE;IACvF,MAAM,WAAW,GAAG,oBAAoB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAC3D,MAAM,eAAe,GAAG,cAAc,CAAC,sCAAsC,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;IAEpG,MAAM,YAAY,GAAG,CAAC,QAAQ,eAAe,IAAI,WAAW,EAAE,CAAC,CAAC;IAEhE,IAAI,WAAW,KAAK,OAAO,EAAE,CAAC;QAC5B,MAAM,iBAAiB,GAAG,cAAc,CAAC,sCAAsC,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;QACxG,YAAY,CAAC,IAAI,CAAC,QAAQ,iBAAiB,EAAE,CAAC,CAAC;IACjD,CAAC;IAED,OAAO,YAAY,CAAC;AACtB,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,aAAa,GAAG,KAAK,EAAE,OAAe,EAAE,WAAmB,EAAiB,EAAE;IACzF,KAAK,MAAM,WAAW,IAAI,sBAAsB,CAAC,OAAO,EAAE,WAAW,CAAC,EAAE,CAAC;QACvE,OAAO,CAAC,GAAG,CAAC,YAAY,WAAW,eAAe,WAAW,GAAG,CAAC,CAAC;QAClE,MAAM,UAAU,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,eAAe,CAAC,OAAO,EAAE,WAAW,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC;IAC9F,CAAC;AACH,CAAC,CAAC","sourcesContent":["// Views upload to S3. Bucket names resolve from the shell service's config.\n// shell is the module-federation host: its bundle is the root website, so it\n// syncs to the 'website' bucket root AND to its prefix in the shared 'views'\n// bucket (where every other service's views live).\nimport { awsNamingUtils } from 'quidproquo-actionprocessor-awslambda';\n\nimport { loadServiceQpqConfig } from '../../lib/qpqConfigs';\nimport { runCommand } from '../../lib/runCommand';\nimport { getViewsDistDir } from '../../lib/views';\n\nexport const getViewsS3Destinations = (appName: string, serviceName: string): string[] => {\n const shellConfig = loadServiceQpqConfig(appName, 'shell');\n const viewsBucketName = awsNamingUtils.getConfigRuntimeResourceNameFromConfig('views', shellConfig);\n\n const destinations = [`s3://${viewsBucketName}/${serviceName}`];\n\n if (serviceName === 'shell') {\n const websiteBucketName = awsNamingUtils.getConfigRuntimeResourceNameFromConfig('website', shellConfig);\n destinations.push(`s3://${websiteBucketName}`);\n }\n\n return destinations;\n};\n\nexport const syncViewsToS3 = async (appName: string, serviceName: string): Promise<void> => {\n for (const destination of getViewsS3Destinations(appName, serviceName)) {\n console.log(`Copying [${serviceName}] views to [${destination}]`);\n await runCommand('aws', ['s3', 'sync', getViewsDistDir(appName, serviceName), destination]);\n }\n};\n"]}
@@ -0,0 +1,2 @@
1
+ import { DeployPlan } from '../../lib/deployPrompts';
2
+ export declare const dockerGo: (appName: string, plan: DeployPlan) => Promise<void>;
@@ -0,0 +1,143 @@
1
+ // Docker platform deploy (`qpq go` with platform 'docker') — proof-of-concept
2
+ // self-hosting: bakes the QPQ dev server (a full local platform emulation)
3
+ // plus every service of the app and its pre-built views into one docker image.
4
+ //
5
+ // 1. Build workspace packages, then the dev-server bundle (all services).
6
+ // 2. Build every views microfrontend with a same-origin module-federation
7
+ // remote base (/views/<svc>), mirroring the AWS website/views layout.
8
+ // 3. Assemble an image context under dist/qpq/docker-image/<app>/ — server
9
+ // bundle, web root, a workspaces-stripped package.json for runtime deps,
10
+ // and the locally-built quidproquo packages as a vendor overlay.
11
+ // 4. docker build, then print the run command.
12
+ //
13
+ // Not production-grade (single process, sqlite, in-memory queues) — it's the
14
+ // whole product on one box with one command.
15
+ import { getAppServiceQpqConfigs, getDevServerRspackConfig } from 'quidproquo-deploy-rspack';
16
+ import fs from 'fs';
17
+ import path from 'path';
18
+ import { writeDevServerEntry } from '../../lib/devServerEntry';
19
+ import { getRoot, getServiceNamesWithViews } from '../../lib/discovery';
20
+ import { runAppHook } from '../../lib/hooks';
21
+ import { getOwnPackageRoot } from '../../lib/packageRoot';
22
+ import { runRspack } from '../../lib/rspackRun';
23
+ import { runCommand } from '../../lib/runCommand';
24
+ import { logTimeEnd, logTimeStart } from '../../lib/timing';
25
+ import { bundleViews, getViewsDistDir } from '../../lib/views';
26
+ const getImageContextDir = (root, appName) => path.join(root, 'dist', 'qpq', 'docker-image', appName);
27
+ // The consumer root package.json, stripped to what the image's npm install
28
+ // needs: runtime dependencies (+ overrides). Workspaces/scripts/devDeps are
29
+ // host-only concerns — the workspace packages themselves are bundled into the
30
+ // server bundle from source.
31
+ //
32
+ // quidproquo deps declared as file: refs (a consumer living beside the qpq
33
+ // monorepo) point outside the image context, where npm install would leave
34
+ // dangling symlinks — rewrite them to the vendored copies inside the context.
35
+ const writeImagePackageJson = (root, contextDir) => {
36
+ const rootPackageJson = JSON.parse(fs.readFileSync(path.join(root, 'package.json'), 'utf8'));
37
+ const dependencies = { ...(rootPackageJson.dependencies ?? {}) };
38
+ for (const [name, version] of Object.entries(dependencies)) {
39
+ if (name.startsWith('quidproquo') && version.startsWith('file:')) {
40
+ dependencies[name] = `file:./vendor/${name}`;
41
+ }
42
+ }
43
+ const imagePackageJson = {
44
+ name: `${rootPackageJson.name}-qpq-docker`,
45
+ version: rootPackageJson.version ?? '0.0.0',
46
+ private: true,
47
+ dependencies,
48
+ overrides: rootPackageJson.overrides,
49
+ };
50
+ fs.writeFileSync(path.join(contextDir, 'package.json'), JSON.stringify(imagePackageJson, null, 2) + '\n');
51
+ };
52
+ // Copy the locally-built quidproquo packages (which may be npm-linked
53
+ // checkouts newer than the registry) into vendor/ so the image runs the same
54
+ // qpq code the bundle was built against. Follows the node_modules symlinks;
55
+ // lib/config only — no node_modules, no src.
56
+ const vendorQuidproquoPackages = (root, contextDir) => {
57
+ const nodeModules = path.join(root, 'node_modules');
58
+ const vendorDir = path.join(contextDir, 'vendor');
59
+ let vendored = 0;
60
+ for (const name of fs.readdirSync(nodeModules)) {
61
+ if (!name.startsWith('quidproquo'))
62
+ continue;
63
+ const packageDir = fs.realpathSync(path.join(nodeModules, name));
64
+ const targetDir = path.join(vendorDir, name);
65
+ fs.mkdirSync(targetDir, { recursive: true });
66
+ fs.copyFileSync(path.join(packageDir, 'package.json'), path.join(targetDir, 'package.json'));
67
+ for (const sub of ['lib', 'config']) {
68
+ const subDir = path.join(packageDir, sub);
69
+ if (fs.existsSync(subDir)) {
70
+ fs.cpSync(subDir, path.join(targetDir, sub), { recursive: true, dereference: true });
71
+ }
72
+ }
73
+ vendored += 1;
74
+ }
75
+ return vendored;
76
+ };
77
+ export const dockerGo = async (appName, plan) => {
78
+ if (plan.kind === 'cancelled') {
79
+ return;
80
+ }
81
+ if (plan.kind === 'account' || plan.kind === 'bootstrap') {
82
+ console.log(`Nothing to do — the docker platform has no ${plan.kind} stacks.`);
83
+ return;
84
+ }
85
+ const root = getRoot();
86
+ const imageTag = `qpq-${appName}:${process.env.ENVIRONMENT}`;
87
+ // The dev server hosts every service of the app, so per-service/stack
88
+ // selections don't apply — the image is always the whole app.
89
+ console.log(`\n\nBuilding docker image [${imageTag}] — the whole app deploys as one image\n\n`);
90
+ logTimeStart('totalTime');
91
+ await runAppHook(appName, 'predeploy');
92
+ // Workspace packages resolve through their built dist/ (package.json main),
93
+ // so bundles would ship stale code unless every lib is tsc'd first.
94
+ console.log('Building workspace packages');
95
+ await runCommand('npm', ['run', 'build', '--workspaces', '--if-present']);
96
+ // ---- Server bundle: the dev server + every service, one main.js ----
97
+ console.log('Bundling server (dev server + all services)');
98
+ const qpqConfigs = getAppServiceQpqConfigs(root, appName);
99
+ const entry = writeDevServerEntry(root, appName);
100
+ await runRspack(getDevServerRspackConfig({ root, entry, qpqConfigs }));
101
+ // ---- Views: production builds with same-origin federation remotes ----
102
+ process.env.QPQ_VIEWS_REMOTE_BASE = '/views';
103
+ const viewServices = getServiceNamesWithViews(appName);
104
+ for (const serviceName of viewServices) {
105
+ console.log(`Bundling views: [${serviceName}]`);
106
+ await bundleViews(appName, serviceName);
107
+ }
108
+ delete process.env.QPQ_VIEWS_REMOTE_BASE;
109
+ // ---- Assemble the image context ----
110
+ console.log('Assembling image context');
111
+ const contextDir = getImageContextDir(root, appName);
112
+ fs.rmSync(contextDir, { recursive: true, force: true });
113
+ fs.mkdirSync(contextDir, { recursive: true });
114
+ fs.copyFileSync(path.join(getOwnPackageRoot(), 'docker', 'dev-server', 'Dockerfile'), path.join(contextDir, 'Dockerfile'));
115
+ writeImagePackageJson(root, contextDir);
116
+ const vendored = vendorQuidproquoPackages(root, contextDir);
117
+ console.log(`Vendored ${vendored} quidproquo packages`);
118
+ fs.cpSync(path.join(root, 'dist', 'qpq', 'dev-server'), path.join(contextDir, 'server'), { recursive: true });
119
+ // Web root mirrors the AWS buckets: shell at website/, every views build
120
+ // (shell included) under views/<svc>/.
121
+ for (const serviceName of viewServices) {
122
+ const viewsDist = getViewsDistDir(appName, serviceName);
123
+ fs.cpSync(viewsDist, path.join(contextDir, 'web', 'views', serviceName), { recursive: true });
124
+ if (serviceName === 'shell') {
125
+ fs.cpSync(viewsDist, path.join(contextDir, 'web', 'website'), { recursive: true });
126
+ }
127
+ }
128
+ // ---- Build the image ----
129
+ console.log('Building docker image');
130
+ await runCommand('docker', ['build', '-t', imageTag, contextDir]);
131
+ logTimeEnd('totalTime');
132
+ console.log(`
133
+ Done. Run it with:
134
+
135
+ docker run --rm -p 80:8080 -p 8080:8080 -p 8888:8888 -p 3001:3001 \\
136
+ -v qpq-${appName}-data:/app/.qpq-runtime \\
137
+ ${imageTag}
138
+
139
+ Then open http://localhost
140
+ (80 serves the shell; 8080 stays mapped because the app's url resolvers call localhost:8080 for apis)
141
+ `);
142
+ };
143
+ //# sourceMappingURL=go.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"go.js","sourceRoot":"","sources":["../../../../src/platforms/docker/go.ts"],"names":[],"mappings":"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","sourcesContent":["// Docker platform deploy (`qpq go` with platform 'docker') — proof-of-concept\n// self-hosting: bakes the QPQ dev server (a full local platform emulation)\n// plus every service of the app and its pre-built views into one docker image.\n//\n// 1. Build workspace packages, then the dev-server bundle (all services).\n// 2. Build every views microfrontend with a same-origin module-federation\n// remote base (/views/<svc>), mirroring the AWS website/views layout.\n// 3. Assemble an image context under dist/qpq/docker-image/<app>/ — server\n// bundle, web root, a workspaces-stripped package.json for runtime deps,\n// and the locally-built quidproquo packages as a vendor overlay.\n// 4. docker build, then print the run command.\n//\n// Not production-grade (single process, sqlite, in-memory queues) — it's the\n// whole product on one box with one command.\nimport { getAppServiceQpqConfigs, getDevServerRspackConfig } from 'quidproquo-deploy-rspack';\n\nimport fs from 'fs';\nimport path from 'path';\n\nimport { DeployPlan } from '../../lib/deployPrompts';\nimport { writeDevServerEntry } from '../../lib/devServerEntry';\nimport { getRoot, getServiceNamesWithViews } from '../../lib/discovery';\nimport { runAppHook } from '../../lib/hooks';\nimport { getOwnPackageRoot } from '../../lib/packageRoot';\nimport { runRspack } from '../../lib/rspackRun';\nimport { runCommand } from '../../lib/runCommand';\nimport { logTimeEnd, logTimeStart } from '../../lib/timing';\nimport { bundleViews, getViewsDistDir } from '../../lib/views';\n\nconst getImageContextDir = (root: string, appName: string): string => path.join(root, 'dist', 'qpq', 'docker-image', appName);\n\n// The consumer root package.json, stripped to what the image's npm install\n// needs: runtime dependencies (+ overrides). Workspaces/scripts/devDeps are\n// host-only concerns — the workspace packages themselves are bundled into the\n// server bundle from source.\n//\n// quidproquo deps declared as file: refs (a consumer living beside the qpq\n// monorepo) point outside the image context, where npm install would leave\n// dangling symlinks — rewrite them to the vendored copies inside the context.\nconst writeImagePackageJson = (root: string, contextDir: string): void => {\n const rootPackageJson = JSON.parse(fs.readFileSync(path.join(root, 'package.json'), 'utf8'));\n\n const dependencies: Record<string, string> = { ...(rootPackageJson.dependencies ?? {}) };\n for (const [name, version] of Object.entries(dependencies)) {\n if (name.startsWith('quidproquo') && version.startsWith('file:')) {\n dependencies[name] = `file:./vendor/${name}`;\n }\n }\n\n const imagePackageJson = {\n name: `${rootPackageJson.name}-qpq-docker`,\n version: rootPackageJson.version ?? '0.0.0',\n private: true,\n dependencies,\n overrides: rootPackageJson.overrides,\n };\n\n fs.writeFileSync(path.join(contextDir, 'package.json'), JSON.stringify(imagePackageJson, null, 2) + '\\n');\n};\n\n// Copy the locally-built quidproquo packages (which may be npm-linked\n// checkouts newer than the registry) into vendor/ so the image runs the same\n// qpq code the bundle was built against. Follows the node_modules symlinks;\n// lib/config only — no node_modules, no src.\nconst vendorQuidproquoPackages = (root: string, contextDir: string): number => {\n const nodeModules = path.join(root, 'node_modules');\n const vendorDir = path.join(contextDir, 'vendor');\n let vendored = 0;\n\n for (const name of fs.readdirSync(nodeModules)) {\n if (!name.startsWith('quidproquo')) continue;\n\n const packageDir = fs.realpathSync(path.join(nodeModules, name));\n const targetDir = path.join(vendorDir, name);\n fs.mkdirSync(targetDir, { recursive: true });\n\n fs.copyFileSync(path.join(packageDir, 'package.json'), path.join(targetDir, 'package.json'));\n for (const sub of ['lib', 'config']) {\n const subDir = path.join(packageDir, sub);\n if (fs.existsSync(subDir)) {\n fs.cpSync(subDir, path.join(targetDir, sub), { recursive: true, dereference: true });\n }\n }\n vendored += 1;\n }\n\n return vendored;\n};\n\nexport const dockerGo = async (appName: string, plan: DeployPlan): Promise<void> => {\n if (plan.kind === 'cancelled') {\n return;\n }\n\n if (plan.kind === 'account' || plan.kind === 'bootstrap') {\n console.log(`Nothing to do — the docker platform has no ${plan.kind} stacks.`);\n return;\n }\n\n const root = getRoot();\n const imageTag = `qpq-${appName}:${process.env.ENVIRONMENT}`;\n\n // The dev server hosts every service of the app, so per-service/stack\n // selections don't apply — the image is always the whole app.\n console.log(`\\n\\nBuilding docker image [${imageTag}] — the whole app deploys as one image\\n\\n`);\n\n logTimeStart('totalTime');\n\n await runAppHook(appName, 'predeploy');\n\n // Workspace packages resolve through their built dist/ (package.json main),\n // so bundles would ship stale code unless every lib is tsc'd first.\n console.log('Building workspace packages');\n await runCommand('npm', ['run', 'build', '--workspaces', '--if-present']);\n\n // ---- Server bundle: the dev server + every service, one main.js ----\n console.log('Bundling server (dev server + all services)');\n const qpqConfigs = getAppServiceQpqConfigs(root, appName);\n const entry = writeDevServerEntry(root, appName);\n await runRspack(getDevServerRspackConfig({ root, entry, qpqConfigs }));\n\n // ---- Views: production builds with same-origin federation remotes ----\n process.env.QPQ_VIEWS_REMOTE_BASE = '/views';\n const viewServices = getServiceNamesWithViews(appName);\n for (const serviceName of viewServices) {\n console.log(`Bundling views: [${serviceName}]`);\n await bundleViews(appName, serviceName);\n }\n delete process.env.QPQ_VIEWS_REMOTE_BASE;\n\n // ---- Assemble the image context ----\n console.log('Assembling image context');\n const contextDir = getImageContextDir(root, appName);\n fs.rmSync(contextDir, { recursive: true, force: true });\n fs.mkdirSync(contextDir, { recursive: true });\n\n fs.copyFileSync(path.join(getOwnPackageRoot(), 'docker', 'dev-server', 'Dockerfile'), path.join(contextDir, 'Dockerfile'));\n writeImagePackageJson(root, contextDir);\n\n const vendored = vendorQuidproquoPackages(root, contextDir);\n console.log(`Vendored ${vendored} quidproquo packages`);\n\n fs.cpSync(path.join(root, 'dist', 'qpq', 'dev-server'), path.join(contextDir, 'server'), { recursive: true });\n\n // Web root mirrors the AWS buckets: shell at website/, every views build\n // (shell included) under views/<svc>/.\n for (const serviceName of viewServices) {\n const viewsDist = getViewsDistDir(appName, serviceName);\n fs.cpSync(viewsDist, path.join(contextDir, 'web', 'views', serviceName), { recursive: true });\n if (serviceName === 'shell') {\n fs.cpSync(viewsDist, path.join(contextDir, 'web', 'website'), { recursive: true });\n }\n }\n\n // ---- Build the image ----\n console.log('Building docker image');\n await runCommand('docker', ['build', '-t', imageTag, contextDir]);\n\n logTimeEnd('totalTime');\n\n console.log(`\nDone. Run it with:\n\n docker run --rm -p 80:8080 -p 8080:8080 -p 8888:8888 -p 3001:3001 \\\\\n -v qpq-${appName}-data:/app/.qpq-runtime \\\\\n ${imageTag}\n\nThen open http://localhost\n(80 serves the shell; 8080 stays mapped because the app's url resolvers call localhost:8080 for apis)\n`);\n};\n"]}
@@ -0,0 +1,2 @@
1
+ import { QpqPlatformDriver } from '../types';
2
+ export declare const dockerPlatformDriver: QpqPlatformDriver;
@@ -0,0 +1,15 @@
1
+ import { dockerGo } from './go';
2
+ const publishNotSupported = async () => {
3
+ console.error('The docker platform has no federated code store — story code is baked into the image. Rebuild with qpq go instead.');
4
+ process.exit(1);
5
+ };
6
+ export const dockerPlatformDriver = {
7
+ // The docker platform needs no deploy identity — everything runs in-image.
8
+ primeDeployIdentity: () => [],
9
+ go: dockerGo,
10
+ publish: publishNotSupported,
11
+ publishBuild: publishNotSupported,
12
+ publishUpload: publishNotSupported,
13
+ publishDeploy: publishNotSupported,
14
+ };
15
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/platforms/docker/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,MAAM,CAAC;AAEhC,MAAM,mBAAmB,GAAG,KAAK,IAAmB,EAAE;IACpD,OAAO,CAAC,KAAK,CAAC,oHAAoH,CAAC,CAAC;IACpI,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,oBAAoB,GAAsB;IACrD,2EAA2E;IAC3E,mBAAmB,EAAE,GAAG,EAAE,CAAC,EAAE;IAE7B,EAAE,EAAE,QAAQ;IAEZ,OAAO,EAAE,mBAAmB;IAC5B,YAAY,EAAE,mBAAmB;IACjC,aAAa,EAAE,mBAAmB;IAClC,aAAa,EAAE,mBAAmB;CACnC,CAAC","sourcesContent":["import { QpqPlatformDriver } from '../types';\nimport { dockerGo } from './go';\n\nconst publishNotSupported = async (): Promise<void> => {\n console.error('The docker platform has no federated code store — story code is baked into the image. Rebuild with qpq go instead.');\n process.exit(1);\n};\n\nexport const dockerPlatformDriver: QpqPlatformDriver = {\n // The docker platform needs no deploy identity — everything runs in-image.\n primeDeployIdentity: () => [],\n\n go: dockerGo,\n\n publish: publishNotSupported,\n publishBuild: publishNotSupported,\n publishUpload: publishNotSupported,\n publishDeploy: publishNotSupported,\n};\n"]}
@@ -0,0 +1,4 @@
1
+ import { QpqPlatformDriver } from './types';
2
+ export declare const findPlatformDriver: (platform: string) => QpqPlatformDriver | undefined;
3
+ export declare const getPlatformDriver: (platform: string) => QpqPlatformDriver;
4
+ export * from './types';
@@ -0,0 +1,20 @@
1
+ import { awsPlatformDriver } from './aws';
2
+ import { dockerPlatformDriver } from './docker';
3
+ import { QpqDeployPlatform } from './types';
4
+ const platformDrivers = {
5
+ [QpqDeployPlatform.aws]: awsPlatformDriver,
6
+ [QpqDeployPlatform.docker]: dockerPlatformDriver,
7
+ };
8
+ // Lenient lookup for best-effort paths (local dev priming) — undefined when
9
+ // the platform isn't known, never exits.
10
+ export const findPlatformDriver = (platform) => platformDrivers[platform];
11
+ export const getPlatformDriver = (platform) => {
12
+ const driver = findPlatformDriver(platform);
13
+ if (!driver) {
14
+ console.error(`Unknown deploy platform '${platform}'. Supported platforms: ${Object.keys(platformDrivers).join(', ')}`);
15
+ process.exit(1);
16
+ }
17
+ return driver;
18
+ };
19
+ export * from './types';
20
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/platforms/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,OAAO,CAAC;AAC1C,OAAO,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AAChD,OAAO,EAAE,iBAAiB,EAAqB,MAAM,SAAS,CAAC;AAE/D,MAAM,eAAe,GAAsC;IACzD,CAAC,iBAAiB,CAAC,GAAG,CAAC,EAAE,iBAAiB;IAC1C,CAAC,iBAAiB,CAAC,MAAM,CAAC,EAAE,oBAAoB;CACjD,CAAC;AAEF,4EAA4E;AAC5E,yCAAyC;AACzC,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,QAAgB,EAAiC,EAAE,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC;AAEjH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,QAAgB,EAAqB,EAAE;IACvE,MAAM,MAAM,GAAG,kBAAkB,CAAC,QAAQ,CAAC,CAAC;IAE5C,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,CAAC,KAAK,CAAC,4BAA4B,QAAQ,2BAA2B,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACxH,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC,CAAC;AAEF,cAAc,SAAS,CAAC","sourcesContent":["import { awsPlatformDriver } from './aws';\nimport { dockerPlatformDriver } from './docker';\nimport { QpqDeployPlatform, QpqPlatformDriver } from './types';\n\nconst platformDrivers: Record<string, QpqPlatformDriver> = {\n [QpqDeployPlatform.aws]: awsPlatformDriver,\n [QpqDeployPlatform.docker]: dockerPlatformDriver,\n};\n\n// Lenient lookup for best-effort paths (local dev priming) — undefined when\n// the platform isn't known, never exits.\nexport const findPlatformDriver = (platform: string): QpqPlatformDriver | undefined => platformDrivers[platform];\n\nexport const getPlatformDriver = (platform: string): QpqPlatformDriver => {\n const driver = findPlatformDriver(platform);\n\n if (!driver) {\n console.error(`Unknown deploy platform '${platform}'. Supported platforms: ${Object.keys(platformDrivers).join(', ')}`);\n process.exit(1);\n }\n\n return driver;\n};\n\nexport * from './types';\n"]}
@@ -0,0 +1,16 @@
1
+ import { QpqAppDeployEnvironment } from 'quidproquo-deploy-awscdk';
2
+ import { DeployPlan, TeardownPlan } from '../lib/deployPrompts';
3
+ export declare enum QpqDeployPlatform {
4
+ aws = "aws",
5
+ docker = "docker"
6
+ }
7
+ export interface QpqPlatformDriver {
8
+ primeDeployIdentity: (target: QpqAppDeployEnvironment | undefined) => string[];
9
+ go: (appName: string, plan: DeployPlan) => Promise<void>;
10
+ goDocker?: (appName: string, plan: DeployPlan) => Promise<void>;
11
+ teardown?: (appName: string, plan: TeardownPlan) => Promise<void>;
12
+ publish: (appName: string, serviceNames: string[]) => Promise<void>;
13
+ publishBuild: (appName: string, serviceNames: string[]) => Promise<void>;
14
+ publishUpload: (appName: string, serviceNames: string[]) => Promise<void>;
15
+ publishDeploy: (appName: string, serviceNames: string[]) => Promise<void>;
16
+ }
@@ -0,0 +1,6 @@
1
+ export var QpqDeployPlatform;
2
+ (function (QpqDeployPlatform) {
3
+ QpqDeployPlatform["aws"] = "aws";
4
+ QpqDeployPlatform["docker"] = "docker";
5
+ })(QpqDeployPlatform || (QpqDeployPlatform = {}));
6
+ //# sourceMappingURL=types.js.map