@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.
- package/lib/commonjs/cli/commandMenu.js +5 -4
- package/lib/commonjs/cli/commandMenu.js.map +1 -1
- package/lib/commonjs/cli/runCli.js +15 -7
- package/lib/commonjs/cli/runCli.js.map +1 -1
- package/lib/commonjs/commands/checkCircular.js +15 -7
- package/lib/commonjs/commands/checkCircular.js.map +1 -1
- package/lib/commonjs/commands/clearResources.js +8 -14
- package/lib/commonjs/commands/clearResources.js.map +1 -1
- package/lib/commonjs/commands/go.js +3 -7
- package/lib/commonjs/commands/go.js.map +1 -1
- package/lib/commonjs/commands/goDev.js +4 -2
- package/lib/commonjs/commands/goDev.js.map +1 -1
- package/lib/commonjs/commands/goDevApi.js +23 -20
- package/lib/commonjs/commands/goDevApi.js.map +1 -1
- package/lib/commonjs/commands/goDevWeb.js +13 -8
- package/lib/commonjs/commands/goDevWeb.js.map +1 -1
- package/lib/commonjs/commands/goDocker.js +10 -13
- package/lib/commonjs/commands/goDocker.js.map +1 -1
- package/lib/commonjs/commands/hooks.js +4 -2
- package/lib/commonjs/commands/hooks.js.map +1 -1
- package/lib/commonjs/commands/migrate.js +11 -9
- package/lib/commonjs/commands/migrate.js.map +1 -1
- package/lib/commonjs/commands/prep.js +4 -2
- package/lib/commonjs/commands/prep.js.map +1 -1
- package/lib/commonjs/commands/publish.js +4 -7
- package/lib/commonjs/commands/publish.js.map +1 -1
- package/lib/commonjs/commands/scriptBuild.js +7 -5
- package/lib/commonjs/commands/scriptBuild.js.map +1 -1
- package/lib/commonjs/commands/scriptBuilderLayer.js +6 -4
- package/lib/commonjs/commands/scriptBuilderLayer.js.map +1 -1
- package/lib/commonjs/commands/scriptNew.js +7 -5
- package/lib/commonjs/commands/scriptNew.js.map +1 -1
- package/lib/commonjs/commands/setup.js +14 -22
- package/lib/commonjs/commands/setup.js.map +1 -1
- package/lib/commonjs/commands/synth.js +16 -20
- package/lib/commonjs/commands/synth.js.map +1 -1
- package/lib/commonjs/commands/teardown.js +8 -14
- package/lib/commonjs/commands/teardown.js.map +1 -1
- package/lib/commonjs/lib/CliError.d.ts +4 -0
- package/lib/commonjs/lib/CliError.js +14 -0
- package/lib/commonjs/lib/CliError.js.map +1 -0
- package/lib/commonjs/lib/circularImports.d.ts +0 -1
- package/lib/commonjs/lib/circularImports.js +5 -6
- package/lib/commonjs/lib/circularImports.js.map +1 -1
- package/lib/commonjs/lib/clearResourcesPlan.d.ts +0 -1
- package/lib/commonjs/lib/clearResourcesPlan.js +12 -13
- package/lib/commonjs/lib/clearResourcesPlan.js.map +1 -1
- package/lib/commonjs/lib/deployPrompts.d.ts +2 -1
- package/lib/commonjs/lib/deployPrompts.js +16 -16
- package/lib/commonjs/lib/deployPrompts.js.map +1 -1
- package/lib/commonjs/lib/devServerEntry.js +5 -4
- package/lib/commonjs/lib/devServerEntry.js.map +1 -1
- package/lib/commonjs/lib/devServerPorts.js +2 -4
- package/lib/commonjs/lib/devServerPorts.js.map +1 -1
- package/lib/commonjs/lib/discovery.d.ts +0 -2
- package/lib/commonjs/lib/discovery.js +11 -44
- package/lib/commonjs/lib/discovery.js.map +1 -1
- package/lib/commonjs/lib/hooks.js +5 -3
- package/lib/commonjs/lib/hooks.js.map +1 -1
- package/lib/commonjs/lib/killChildWithEscalation.js +3 -1
- package/lib/commonjs/lib/killChildWithEscalation.js.map +1 -1
- package/lib/commonjs/lib/killStaleListeners.js +24 -37
- package/lib/commonjs/lib/killStaleListeners.js.map +1 -1
- package/lib/commonjs/lib/out.d.ts +11 -0
- package/lib/commonjs/lib/out.js +30 -0
- package/lib/commonjs/lib/out.js.map +1 -0
- package/lib/commonjs/lib/prompts.d.ts +1 -0
- package/lib/commonjs/lib/prompts.js +15 -2
- package/lib/commonjs/lib/prompts.js.map +1 -1
- package/lib/commonjs/lib/qpqConfigs.js +4 -4
- package/lib/commonjs/lib/qpqConfigs.js.map +1 -1
- package/lib/commonjs/lib/requireDriverCapability.d.ts +7 -0
- package/lib/commonjs/lib/requireDriverCapability.js +17 -0
- package/lib/commonjs/lib/requireDriverCapability.js.map +1 -0
- package/lib/commonjs/lib/resolveAppSelection.d.ts +1 -0
- package/lib/commonjs/lib/resolveAppSelection.js +19 -12
- package/lib/commonjs/lib/resolveAppSelection.js.map +1 -1
- package/lib/commonjs/lib/resolveCommandContext.d.ts +12 -0
- package/lib/commonjs/lib/resolveCommandContext.js +26 -0
- package/lib/commonjs/lib/resolveCommandContext.js.map +1 -0
- package/lib/commonjs/lib/resolveDeployment.d.ts +0 -1
- package/lib/commonjs/lib/resolveDeployment.js +15 -10
- package/lib/commonjs/lib/resolveDeployment.js.map +1 -1
- package/lib/commonjs/lib/runCommand.d.ts +20 -0
- package/lib/commonjs/lib/runCommand.js +64 -34
- package/lib/commonjs/lib/runCommand.js.map +1 -1
- package/lib/commonjs/lib/runTasks.js +8 -4
- package/lib/commonjs/lib/runTasks.js.map +1 -1
- package/lib/commonjs/lib/timing.js +5 -3
- package/lib/commonjs/lib/timing.js.map +1 -1
- package/lib/commonjs/lib/typeWatcher.d.ts +2 -1
- package/lib/commonjs/lib/typeWatcher.js +6 -13
- package/lib/commonjs/lib/typeWatcher.js.map +1 -1
- package/lib/commonjs/lib/userScriptBuilderLayer.d.ts +0 -2
- package/lib/commonjs/lib/userScriptBuilderLayer.js +7 -8
- package/lib/commonjs/lib/userScriptBuilderLayer.js.map +1 -1
- package/lib/commonjs/lib/views.js +3 -2
- package/lib/commonjs/lib/views.js.map +1 -1
- package/lib/commonjs/lib/webAddressingEnv.d.ts +0 -2
- package/lib/commonjs/lib/webAddressingEnv.js +4 -4
- package/lib/commonjs/lib/webAddressingEnv.js.map +1 -1
- package/lib/commonjs/platforms/aws/awsCredentials.js +3 -1
- package/lib/commonjs/platforms/aws/awsCredentials.js.map +1 -1
- package/lib/commonjs/platforms/aws/cdkApp.js +1 -1
- package/lib/commonjs/platforms/aws/cdkApp.js.map +1 -1
- package/lib/commonjs/platforms/aws/clearResources.js +16 -26
- package/lib/commonjs/platforms/aws/clearResources.js.map +1 -1
- package/lib/commonjs/platforms/aws/getDeployEnv.d.ts +1 -0
- package/lib/commonjs/platforms/aws/getDeployEnv.js +12 -0
- package/lib/commonjs/platforms/aws/getDeployEnv.js.map +1 -0
- package/lib/commonjs/platforms/aws/go.js +17 -15
- package/lib/commonjs/platforms/aws/go.js.map +1 -1
- package/lib/commonjs/platforms/aws/goDocker.js +29 -26
- package/lib/commonjs/platforms/aws/goDocker.js.map +1 -1
- package/lib/commonjs/platforms/aws/goDockerManifest.js +6 -1
- package/lib/commonjs/platforms/aws/goDockerManifest.js.map +1 -1
- package/lib/commonjs/platforms/aws/publish.js +13 -11
- package/lib/commonjs/platforms/aws/publish.js.map +1 -1
- package/lib/commonjs/platforms/aws/remote.js +8 -7
- package/lib/commonjs/platforms/aws/remote.js.map +1 -1
- package/lib/commonjs/platforms/aws/setup/buildBucketNamesStep.js +4 -4
- package/lib/commonjs/platforms/aws/setup/buildBucketNamesStep.js.map +1 -1
- package/lib/commonjs/platforms/aws/setup/buildGithubDeployRoleStep.js +4 -3
- package/lib/commonjs/platforms/aws/setup/buildGithubDeployRoleStep.js.map +1 -1
- package/lib/commonjs/platforms/aws/stacks.d.ts +0 -1
- package/lib/commonjs/platforms/aws/stacks.js +21 -33
- package/lib/commonjs/platforms/aws/stacks.js.map +1 -1
- package/lib/commonjs/platforms/aws/teardown.js +9 -7
- package/lib/commonjs/platforms/aws/teardown.js.map +1 -1
- package/lib/commonjs/platforms/aws/viewsSync.js +23 -11
- package/lib/commonjs/platforms/aws/viewsSync.js.map +1 -1
- package/lib/commonjs/platforms/docker/go.js +20 -18
- package/lib/commonjs/platforms/docker/go.js.map +1 -1
- package/lib/commonjs/platforms/docker/index.js +5 -4
- package/lib/commonjs/platforms/docker/index.js.map +1 -1
- package/lib/commonjs/platforms/docker/parseMounts.js +3 -2
- package/lib/commonjs/platforms/docker/parseMounts.js.map +1 -1
- package/lib/commonjs/platforms/index.js +4 -2
- package/lib/commonjs/platforms/index.js.map +1 -1
- package/lib/commonjs/platforms/types.d.ts +2 -2
- package/lib/commonjs/platforms/types.js.map +1 -1
- package/lib/esm/cli/commandMenu.js +5 -4
- package/lib/esm/cli/commandMenu.js.map +1 -1
- package/lib/esm/cli/runCli.js +15 -7
- package/lib/esm/cli/runCli.js.map +1 -1
- package/lib/esm/commands/checkCircular.js +15 -7
- package/lib/esm/commands/checkCircular.js.map +1 -1
- package/lib/esm/commands/clearResources.js +8 -14
- package/lib/esm/commands/clearResources.js.map +1 -1
- package/lib/esm/commands/go.js +3 -7
- package/lib/esm/commands/go.js.map +1 -1
- package/lib/esm/commands/goDev.js +4 -2
- package/lib/esm/commands/goDev.js.map +1 -1
- package/lib/esm/commands/goDevApi.js +21 -18
- package/lib/esm/commands/goDevApi.js.map +1 -1
- package/lib/esm/commands/goDevWeb.js +12 -8
- package/lib/esm/commands/goDevWeb.js.map +1 -1
- package/lib/esm/commands/goDocker.js +10 -13
- package/lib/esm/commands/goDocker.js.map +1 -1
- package/lib/esm/commands/hooks.js +4 -2
- package/lib/esm/commands/hooks.js.map +1 -1
- package/lib/esm/commands/migrate.js +9 -7
- package/lib/esm/commands/migrate.js.map +1 -1
- package/lib/esm/commands/prep.js +4 -2
- package/lib/esm/commands/prep.js.map +1 -1
- package/lib/esm/commands/publish.js +4 -7
- package/lib/esm/commands/publish.js.map +1 -1
- package/lib/esm/commands/scriptBuild.js +7 -5
- package/lib/esm/commands/scriptBuild.js.map +1 -1
- package/lib/esm/commands/scriptBuilderLayer.js +6 -4
- package/lib/esm/commands/scriptBuilderLayer.js.map +1 -1
- package/lib/esm/commands/scriptNew.js +7 -5
- package/lib/esm/commands/scriptNew.js.map +1 -1
- package/lib/esm/commands/setup.js +14 -22
- package/lib/esm/commands/setup.js.map +1 -1
- package/lib/esm/commands/synth.js +18 -22
- package/lib/esm/commands/synth.js.map +1 -1
- package/lib/esm/commands/teardown.js +8 -14
- package/lib/esm/commands/teardown.js.map +1 -1
- package/lib/esm/lib/CliError.d.ts +4 -0
- package/lib/esm/lib/CliError.js +11 -0
- package/lib/esm/lib/CliError.js.map +1 -0
- package/lib/esm/lib/circularImports.d.ts +0 -1
- package/lib/esm/lib/circularImports.js +4 -4
- package/lib/esm/lib/circularImports.js.map +1 -1
- package/lib/esm/lib/clearResourcesPlan.d.ts +0 -1
- package/lib/esm/lib/clearResourcesPlan.js +12 -12
- package/lib/esm/lib/clearResourcesPlan.js.map +1 -1
- package/lib/esm/lib/deployPrompts.d.ts +2 -1
- package/lib/esm/lib/deployPrompts.js +17 -17
- package/lib/esm/lib/deployPrompts.js.map +1 -1
- package/lib/esm/lib/devServerEntry.js +5 -4
- package/lib/esm/lib/devServerEntry.js.map +1 -1
- package/lib/esm/lib/devServerPorts.js +2 -3
- package/lib/esm/lib/devServerPorts.js.map +1 -1
- package/lib/esm/lib/discovery.d.ts +0 -2
- package/lib/esm/lib/discovery.js +10 -38
- package/lib/esm/lib/discovery.js.map +1 -1
- package/lib/esm/lib/hooks.js +5 -3
- package/lib/esm/lib/hooks.js.map +1 -1
- package/lib/esm/lib/killChildWithEscalation.js +3 -1
- package/lib/esm/lib/killChildWithEscalation.js.map +1 -1
- package/lib/esm/lib/killStaleListeners.js +24 -37
- package/lib/esm/lib/killStaleListeners.js.map +1 -1
- package/lib/esm/lib/out.d.ts +11 -0
- package/lib/esm/lib/out.js +26 -0
- package/lib/esm/lib/out.js.map +1 -0
- package/lib/esm/lib/prompts.d.ts +1 -0
- package/lib/esm/lib/prompts.js +13 -1
- package/lib/esm/lib/prompts.js.map +1 -1
- package/lib/esm/lib/qpqConfigs.js +4 -4
- package/lib/esm/lib/qpqConfigs.js.map +1 -1
- package/lib/esm/lib/requireDriverCapability.d.ts +7 -0
- package/lib/esm/lib/requireDriverCapability.js +13 -0
- package/lib/esm/lib/requireDriverCapability.js.map +1 -0
- package/lib/esm/lib/resolveAppSelection.d.ts +1 -0
- package/lib/esm/lib/resolveAppSelection.js +17 -11
- package/lib/esm/lib/resolveAppSelection.js.map +1 -1
- package/lib/esm/lib/resolveCommandContext.d.ts +12 -0
- package/lib/esm/lib/resolveCommandContext.js +12 -0
- package/lib/esm/lib/resolveCommandContext.js.map +1 -0
- package/lib/esm/lib/resolveDeployment.d.ts +0 -1
- package/lib/esm/lib/resolveDeployment.js +13 -8
- package/lib/esm/lib/resolveDeployment.js.map +1 -1
- package/lib/esm/lib/runCommand.d.ts +20 -0
- package/lib/esm/lib/runCommand.js +52 -31
- package/lib/esm/lib/runCommand.js.map +1 -1
- package/lib/esm/lib/runTasks.js +8 -4
- package/lib/esm/lib/runTasks.js.map +1 -1
- package/lib/esm/lib/timing.js +5 -3
- package/lib/esm/lib/timing.js.map +1 -1
- package/lib/esm/lib/typeWatcher.d.ts +2 -1
- package/lib/esm/lib/typeWatcher.js +6 -13
- package/lib/esm/lib/typeWatcher.js.map +1 -1
- package/lib/esm/lib/userScriptBuilderLayer.d.ts +0 -2
- package/lib/esm/lib/userScriptBuilderLayer.js +5 -5
- package/lib/esm/lib/userScriptBuilderLayer.js.map +1 -1
- package/lib/esm/lib/views.js +3 -2
- package/lib/esm/lib/views.js.map +1 -1
- package/lib/esm/lib/webAddressingEnv.d.ts +0 -2
- package/lib/esm/lib/webAddressingEnv.js +1 -1
- package/lib/esm/lib/webAddressingEnv.js.map +1 -1
- package/lib/esm/platforms/aws/awsCredentials.js +3 -1
- package/lib/esm/platforms/aws/awsCredentials.js.map +1 -1
- package/lib/esm/platforms/aws/cdkApp.js +1 -1
- package/lib/esm/platforms/aws/cdkApp.js.map +1 -1
- package/lib/esm/platforms/aws/clearResources.js +16 -25
- package/lib/esm/platforms/aws/clearResources.js.map +1 -1
- package/lib/esm/platforms/aws/getDeployEnv.d.ts +1 -0
- package/lib/esm/platforms/aws/getDeployEnv.js +8 -0
- package/lib/esm/platforms/aws/getDeployEnv.js.map +1 -0
- package/lib/esm/platforms/aws/go.js +17 -15
- package/lib/esm/platforms/aws/go.js.map +1 -1
- package/lib/esm/platforms/aws/goDocker.js +29 -26
- package/lib/esm/platforms/aws/goDocker.js.map +1 -1
- package/lib/esm/platforms/aws/goDockerManifest.js +6 -1
- package/lib/esm/platforms/aws/goDockerManifest.js.map +1 -1
- package/lib/esm/platforms/aws/publish.js +13 -11
- package/lib/esm/platforms/aws/publish.js.map +1 -1
- package/lib/esm/platforms/aws/remote.js +9 -7
- package/lib/esm/platforms/aws/remote.js.map +1 -1
- package/lib/esm/platforms/aws/setup/buildBucketNamesStep.js +2 -2
- package/lib/esm/platforms/aws/setup/buildBucketNamesStep.js.map +1 -1
- package/lib/esm/platforms/aws/setup/buildGithubDeployRoleStep.js +4 -3
- package/lib/esm/platforms/aws/setup/buildGithubDeployRoleStep.js.map +1 -1
- package/lib/esm/platforms/aws/stacks.d.ts +0 -1
- package/lib/esm/platforms/aws/stacks.js +22 -30
- package/lib/esm/platforms/aws/stacks.js.map +1 -1
- package/lib/esm/platforms/aws/teardown.js +9 -7
- package/lib/esm/platforms/aws/teardown.js.map +1 -1
- package/lib/esm/platforms/aws/viewsSync.js +22 -10
- package/lib/esm/platforms/aws/viewsSync.js.map +1 -1
- package/lib/esm/platforms/docker/go.js +21 -19
- package/lib/esm/platforms/docker/go.js.map +1 -1
- package/lib/esm/platforms/docker/index.js +5 -4
- package/lib/esm/platforms/docker/index.js.map +1 -1
- package/lib/esm/platforms/docker/parseMounts.js +3 -2
- package/lib/esm/platforms/docker/parseMounts.js.map +1 -1
- package/lib/esm/platforms/index.js +4 -2
- package/lib/esm/platforms/index.js.map +1 -1
- package/lib/esm/platforms/types.d.ts +2 -2
- package/lib/esm/platforms/types.js.map +1 -1
- package/package.json +28 -15
- package/templates/user-script/README.md +1 -1
|
@@ -13,21 +13,21 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
13
13
|
};
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
15
|
exports.dockerGo = void 0;
|
|
16
|
-
// Docker platform deploy (`qpq go` with platform 'docker')
|
|
16
|
+
// Docker platform deploy (`qpq go` with platform 'docker'), proof-of-concept
|
|
17
17
|
// self-hosting: bakes the QPQ dev server (a full local platform emulation)
|
|
18
18
|
// plus every service of the app and its pre-built views into one docker image.
|
|
19
19
|
//
|
|
20
20
|
// 1. Build workspace packages, then the dev-server bundle (all services).
|
|
21
21
|
// 2. Build every views microfrontend with a same-origin module-federation
|
|
22
22
|
// remote base (/<views subdomain>/<svc>), mirroring the AWS layout.
|
|
23
|
-
// 3. Assemble an image context under dist/qpq/docker-image/<app
|
|
23
|
+
// 3. Assemble an image context under dist/qpq/docker-image/<app>/, server
|
|
24
24
|
// bundle, web root (every web entry, placed by its port or its domain),
|
|
25
25
|
// a workspaces-stripped package.json for runtime deps, and the
|
|
26
26
|
// locally-built quidproquo packages as a vendor overlay.
|
|
27
27
|
// 4. docker build (buildx with a push when the deployment names a registry or
|
|
28
28
|
// a target platform), write a docker-compose.yml, print how to run it.
|
|
29
29
|
//
|
|
30
|
-
// Not production-grade (single process, sqlite KVS, in-memory queues)
|
|
30
|
+
// Not production-grade (single process, sqlite KVS, in-memory queues):
|
|
31
31
|
// it's the whole product on one box with one command.
|
|
32
32
|
const config_aws_1 = require("@qpqjs/config-aws");
|
|
33
33
|
const core_1 = require("@qpqjs/core");
|
|
@@ -41,6 +41,7 @@ const devServerPorts_1 = require("../../lib/devServerPorts");
|
|
|
41
41
|
const discovery_1 = require("../../lib/discovery");
|
|
42
42
|
const getDefaultHookJobs_1 = require("../../lib/getDefaultHookJobs");
|
|
43
43
|
const hooks_1 = require("../../lib/hooks");
|
|
44
|
+
const out_1 = require("../../lib/out");
|
|
44
45
|
const packageRoot_1 = require("../../lib/packageRoot");
|
|
45
46
|
const runCommand_1 = require("../../lib/runCommand");
|
|
46
47
|
const runTasks_1 = require("../../lib/runTasks");
|
|
@@ -52,7 +53,8 @@ const getDockerPlatformSettings_1 = require("./getDockerPlatformSettings");
|
|
|
52
53
|
const getImageName_1 = require("./getImageName");
|
|
53
54
|
const resolvePortMappings_1 = require("./resolvePortMappings");
|
|
54
55
|
const writeComposeFile_1 = require("./writeComposeFile");
|
|
55
|
-
const
|
|
56
|
+
const out = (0, out_1.createOutput)('docker');
|
|
57
|
+
const getImageContextDir = (root, appName) => (0, core_1.getDockerImageContextPath)(root, appName);
|
|
56
58
|
// Every web entry's files go where the runtime looks for them. The federated views entry
|
|
57
59
|
// is assembled from every service's views build (one folder per service, as on AWS);
|
|
58
60
|
// anything else is its own buildPath. A missing build fails here rather than serving an
|
|
@@ -99,12 +101,12 @@ const writeDockerfile = (contextDir, containerPorts) => {
|
|
|
99
101
|
};
|
|
100
102
|
// The consumer root package.json, stripped to what the image's npm install
|
|
101
103
|
// needs: runtime dependencies (+ overrides). Workspaces/scripts/devDeps are
|
|
102
|
-
// host-only concerns
|
|
104
|
+
// host-only concerns, the workspace packages themselves are bundled into the
|
|
103
105
|
// server bundle from source.
|
|
104
106
|
//
|
|
105
107
|
// quidproquo deps declared as file: refs (a consumer living beside the qpq
|
|
106
108
|
// monorepo) point outside the image context, where npm install would leave
|
|
107
|
-
// dangling symlinks
|
|
109
|
+
// dangling symlinks, rewrite them to the vendored copies inside the context.
|
|
108
110
|
const writeImagePackageJson = (root, contextDir) => {
|
|
109
111
|
var _a, _b;
|
|
110
112
|
const rootPackageJson = JSON.parse(fs_1.default.readFileSync(path_1.default.join(root, 'package.json'), 'utf8'));
|
|
@@ -126,7 +128,7 @@ const writeImagePackageJson = (root, contextDir) => {
|
|
|
126
128
|
// Copy the locally-built quidproquo packages (which may be npm-linked
|
|
127
129
|
// checkouts newer than the registry) into vendor/ so the image runs the same
|
|
128
130
|
// qpq code the bundle was built against. Follows the node_modules symlinks;
|
|
129
|
-
// lib/config only
|
|
131
|
+
// lib/config only, no node_modules, no src.
|
|
130
132
|
const vendorQuidproquoPackages = (root, contextDir) => {
|
|
131
133
|
const nodeModules = path_1.default.join(root, 'node_modules');
|
|
132
134
|
const vendorDir = path_1.default.join(contextDir, 'vendor');
|
|
@@ -152,7 +154,7 @@ const dockerGo = (appName, plan) => __awaiter(void 0, void 0, void 0, function*
|
|
|
152
154
|
return;
|
|
153
155
|
}
|
|
154
156
|
if (plan.kind === 'account' || plan.kind === 'bootstrap') {
|
|
155
|
-
|
|
157
|
+
out.log(`Nothing to do — the docker platform has no ${plan.kind} stacks.`);
|
|
156
158
|
return;
|
|
157
159
|
}
|
|
158
160
|
const root = (0, discovery_1.getRoot)();
|
|
@@ -163,16 +165,16 @@ const dockerGo = (appName, plan) => __awaiter(void 0, void 0, void 0, function*
|
|
|
163
165
|
const containerName = `qpq-${applicationName}`;
|
|
164
166
|
const volumeName = `${containerName}-data`;
|
|
165
167
|
// The dev server hosts every service of the app, so per-service/stack
|
|
166
|
-
// selections don't apply
|
|
167
|
-
|
|
168
|
+
// selections don't apply, the image is always the whole app.
|
|
169
|
+
out.log(`\n\nBuilding docker image [${imageName}] — the whole app deploys as one image\n\n`);
|
|
168
170
|
(0, timing_1.logTimeStart)('totalTime');
|
|
169
171
|
yield (0, hooks_1.runAppHook)(appName, 'predeploy');
|
|
170
172
|
// Workspace packages resolve through their built dist/ (package.json main),
|
|
171
173
|
// so bundles would ship stale code unless every lib is tsc'd first.
|
|
172
|
-
|
|
174
|
+
out.log('Building workspace packages');
|
|
173
175
|
(0, runTasks_1.assertNoFailures)('Workspace build', yield (0, hooks_1.runHookForAppPackages)('build', appName, (0, getDefaultHookJobs_1.getDefaultHookJobs)()));
|
|
174
176
|
// ---- Server bundle: the dev server + every service, one main.js ----
|
|
175
|
-
|
|
177
|
+
out.log('Bundling server (dev server + all services)');
|
|
176
178
|
const qpqConfigs = (0, deploy_rspack_1.getAppServiceQpqConfigs)(root, appName);
|
|
177
179
|
// Resolved before anything slow runs, so a bad port or domain fails the build up front.
|
|
178
180
|
const devServerPorts = (0, devServerPorts_1.readDevServerPorts)(appName);
|
|
@@ -193,21 +195,21 @@ const dockerGo = (appName, plan) => __awaiter(void 0, void 0, void 0, function*
|
|
|
193
195
|
process.env.QPQ_VIEWS_REMOTE_BASE = `/${webserver_1.FEDERATED_VIEWS_SUBDOMAIN}`;
|
|
194
196
|
const viewServices = (0, discovery_1.getServiceNamesWithViews)(appName);
|
|
195
197
|
for (const serviceName of viewServices) {
|
|
196
|
-
|
|
198
|
+
out.log(`Bundling views: [${serviceName}]`);
|
|
197
199
|
yield (0, views_1.bundleViews)(appName, serviceName);
|
|
198
200
|
}
|
|
199
201
|
delete process.env.QPQ_VIEWS_REMOTE_BASE;
|
|
200
202
|
(0, webAddressingEnv_1.clearWebAddressingEnv)();
|
|
201
203
|
// ---- Assemble the image context ----
|
|
202
|
-
|
|
204
|
+
out.log('Assembling image context');
|
|
203
205
|
const contextDir = getImageContextDir(root, appName);
|
|
204
206
|
fs_1.default.rmSync(contextDir, { recursive: true, force: true });
|
|
205
207
|
fs_1.default.mkdirSync(contextDir, { recursive: true });
|
|
206
208
|
writeDockerfile(contextDir, containerPorts);
|
|
207
209
|
writeImagePackageJson(root, contextDir);
|
|
208
210
|
const vendored = vendorQuidproquoPackages(root, contextDir);
|
|
209
|
-
|
|
210
|
-
fs_1.default.cpSync(
|
|
211
|
+
out.log(`Vendored ${vendored} quidproquo packages`);
|
|
212
|
+
fs_1.default.cpSync((0, core_1.getDevServerDistPath)(root), path_1.default.join(contextDir, 'server'), { recursive: true });
|
|
211
213
|
for (const entry of [...webEntryRoutes, ...webEntryHosts]) {
|
|
212
214
|
copyWebEntryContent(appName, contextDir, entry, viewServices);
|
|
213
215
|
}
|
|
@@ -223,7 +225,7 @@ const dockerGo = (appName, plan) => __awaiter(void 0, void 0, void 0, function*
|
|
|
223
225
|
publicFileStoragePort: mapHostPort(devServerPorts.fileStorage),
|
|
224
226
|
});
|
|
225
227
|
// ---- Build the image ----
|
|
226
|
-
|
|
228
|
+
out.log(`Building docker image${dockerSettings.arch ? ` for ${dockerSettings.arch}` : ''}${dockerSettings.registry ? `, pushing to ${dockerSettings.registry}` : ''}`);
|
|
227
229
|
yield buildImage(imageName, contextDir, dockerSettings);
|
|
228
230
|
(0, timing_1.logTimeEnd)('totalTime');
|
|
229
231
|
const hostUrl = (containerPort) => {
|
|
@@ -240,7 +242,7 @@ const dockerGo = (appName, plan) => __awaiter(void 0, void 0, void 0, function*
|
|
|
240
242
|
const onHost = dockerSettings.registry
|
|
241
243
|
? `On the host (Unraid: Compose Manager, or any docker host), copy the compose file there and run:`
|
|
242
244
|
: `Run it here:`;
|
|
243
|
-
|
|
245
|
+
out.log(`
|
|
244
246
|
Done. The image is ${where}.
|
|
245
247
|
|
|
246
248
|
${onHost}
|
|
@@ -1 +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 subdomain>/<svc>), mirroring the AWS layout.\n// 3. Assemble an image context under dist/qpq/docker-image/<app>/ — server\n// bundle, web root (every web entry, placed by its port or its domain),\n// a workspaces-stripped package.json for runtime deps, and the\n// locally-built quidproquo packages as a vendor overlay.\n// 4. docker build (buildx with a push when the deployment names a registry or\n// a target platform), write a docker-compose.yml, print how to run it.\n//\n// Not production-grade (single process, sqlite KVS, in-memory queues) —\n// it's the whole product on one box with one command.\nimport { getQpqAppDeployment } from '@qpqjs/config-aws';\nimport { isQpqPackageName, QpqDeployEnvVar } from '@qpqjs/core';\nimport { getAppServiceQpqConfigs, getDevServerRspackConfig, listInstalledQpqPackageNames, runRspack } from '@qpqjs/deploy-rspack';\nimport { getWebEntryDir, getWebEntryPlacements, WebEntryHost, WebEntryRoute } from '@qpqjs/dev-server';\nimport { FEDERATED_VIEWS_SUBDOMAIN } from '@qpqjs/webserver';\n\nimport fs from 'fs';\nimport path from 'path';\n\nimport { DeployPlan } from '../../lib/deployPrompts';\nimport { writeDevServerEntry, writeUserScriptChildEntry } from '../../lib/devServerEntry';\nimport { readDevServerPorts } from '../../lib/devServerPorts';\nimport { getRoot, getServiceNamesWithViews } from '../../lib/discovery';\nimport { getDefaultHookJobs } from '../../lib/getDefaultHookJobs';\nimport { runAppHook, runHookForAppPackages } from '../../lib/hooks';\nimport { getOwnPackageRoot } from '../../lib/packageRoot';\nimport { runCommand } from '../../lib/runCommand';\nimport { assertNoFailures } from '../../lib/runTasks';\nimport { logTimeEnd, logTimeStart } from '../../lib/timing';\nimport { bundleViews, getViewsDistDir } from '../../lib/views';\nimport { clearWebAddressingEnv, setWebAddressingEnv } from '../../lib/webAddressingEnv';\nimport { getContainerPorts } from './getContainerPorts';\nimport { getDockerPlatformSettings, ParsedDockerPlatformSettings } from './getDockerPlatformSettings';\nimport { getImageName } from './getImageName';\nimport { resolvePortMappings } from './resolvePortMappings';\nimport { writeComposeFile } from './writeComposeFile';\n\nconst getImageContextDir = (root: string, appName: string): string => path.join(root, 'dist', 'qpq', 'docker-image', appName);\n\n// Every web entry's files go where the runtime looks for them. The federated views entry\n// is assembled from every service's views build (one folder per service, as on AWS);\n// anything else is its own buildPath. A missing build fails here rather than serving an\n// empty site later.\nconst copyWebEntryContent = (appName: string, contextDir: string, entry: WebEntryHost | WebEntryRoute, viewServices: string[]): void => {\n const label = `${entry.service}/${entry.entryName}`;\n const targetDir = getWebEntryDir(path.join(contextDir, 'web'), entry);\n\n if (entry.webEntry.domain.subDomainName === FEDERATED_VIEWS_SUBDOMAIN) {\n for (const serviceName of viewServices) {\n fs.cpSync(getViewsDistDir(appName, serviceName), path.join(targetDir, serviceName), { recursive: true });\n }\n return;\n }\n\n // A standalone host entry serves its own service's views build, as on AWS.\n if (entry.webEntry.storageDrive.syncServiceViews) {\n fs.cpSync(getViewsDistDir(appName, entry.service), targetDir, { recursive: true });\n return;\n }\n\n if (!entry.webEntry.buildPath) {\n throw new Error(`Web entry ${label} has no buildPath, so there is nothing to serve`);\n }\n const buildDir = path.resolve(entry.configRoot, entry.webEntry.buildPath);\n if (!fs.existsSync(path.join(buildDir, entry.webEntry.indexRoot))) {\n throw new Error(`Web entry ${label} has no ${entry.webEntry.indexRoot} under ${buildDir}; build it before qpq go`);\n }\n fs.cpSync(buildDir, targetDir, { recursive: true });\n};\n\n// Plain `docker build` into the local store unless the deployment asks for a registry or a\n// target platform, which need buildx: `--push` sends a cross-platform image straight to the\n// registry, `--load` keeps a same-machine one local.\nconst buildImage = async (imageName: string, contextDir: string, settings: ParsedDockerPlatformSettings): Promise<void> => {\n if (!settings.registry && !settings.arch) {\n await runCommand('docker', ['build', '-t', imageName, contextDir]);\n return;\n }\n\n const platformArgs = settings.arch ? ['--platform', settings.arch] : [];\n await runCommand('docker', ['buildx', 'build', ...platformArgs, '-t', imageName, settings.registry ? '--push' : '--load', contextDir]);\n};\n\n// The Dockerfile is shared; only its EXPOSE line depends on the app.\nconst writeDockerfile = (contextDir: string, containerPorts: number[]): void => {\n const template = fs.readFileSync(path.join(getOwnPackageRoot(), 'docker', 'dev-server', 'Dockerfile'), 'utf8');\n const dockerfile = template.replace(/^EXPOSE .*$/m, `EXPOSE ${containerPorts.join(' ')}`);\n fs.writeFileSync(path.join(contextDir, 'Dockerfile'), dockerfile);\n};\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 (isQpqPackageName(name) && 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 listInstalledQpqPackageNames(nodeModules)) {\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 deploymentName = process.env[QpqDeployEnvVar.deployName]!;\n const dockerSettings = getDockerPlatformSettings(deploymentName, getQpqAppDeployment(root, appName, deploymentName));\n\n const applicationName = process.env[QpqDeployEnvVar.applicationName]!;\n const imageName = getImageName(applicationName, dockerSettings);\n const containerName = `qpq-${applicationName}`;\n const volumeName = `${containerName}-data`;\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 [${imageName}] — 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 assertNoFailures('Workspace build', await runHookForAppPackages('build', appName, getDefaultHookJobs()));\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\n // Resolved before anything slow runs, so a bad port or domain fails the build up front.\n const devServerPorts = readDevServerPorts(appName);\n const { hosts: webEntryHosts, routes: webEntryRoutes } = getWebEntryPlacements(qpqConfigs, Object.values(devServerPorts));\n const containerPorts = getContainerPorts(devServerPorts, webEntryHosts);\n const portMappings = resolvePortMappings(deploymentName, dockerSettings, devServerPorts.api, containerPorts);\n const mapHostPort = (containerPort: number): number => portMappings.find((mapping) => mapping.container === containerPort)?.host ?? containerPort;\n\n // Nothing deploys into the container, so the image runs its own pending migrations on start.\n const entry = writeDevServerEntry(root, appName, 'migrate-then-serve');\n const userScriptChildEntry = writeUserScriptChildEntry(root);\n // The image installs its own node_modules next to the bundle, so externals\n // must stay bare; host-resolved absolute paths do not exist in the container.\n await runRspack(getDevServerRspackConfig({ root, entry, userScriptChildEntry, qpqConfigs, portableExternals: true }));\n\n // ---- Views: production builds with same-origin federation remotes ----\n // The browser reaches everything on the page's own host, on the HOST side of the port\n // mappings; an unmapped port stays as is (nothing outside the container can reach it anyway).\n setWebAddressingEnv(qpqConfigs, { api: devServerPorts.api, webSocket: devServerPorts.webSocket, mapHostPort });\n process.env.QPQ_VIEWS_REMOTE_BASE = `/${FEDERATED_VIEWS_SUBDOMAIN}`;\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 clearWebAddressingEnv();\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 writeDockerfile(contextDir, containerPorts);\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 for (const entry of [...webEntryRoutes, ...webEntryHosts]) {\n copyWebEntryContent(appName, contextDir, entry, viewServices);\n }\n\n const composePath = writeComposeFile({\n contextDir,\n imageName,\n serviceName: containerName,\n volumeName,\n portMappings,\n dataPath: dockerSettings.dataPath ?? null,\n mounts: dockerSettings.mounts ?? [],\n publicHost: dockerSettings.publicHost ?? null,\n publicFileStoragePort: mapHostPort(devServerPorts.fileStorage),\n });\n\n // ---- Build the image ----\n console.log(\n `Building docker image${dockerSettings.arch ? ` for ${dockerSettings.arch}` : ''}${dockerSettings.registry ? `, pushing to ${dockerSettings.registry}` : ''}`,\n );\n await buildImage(imageName, contextDir, dockerSettings);\n\n logTimeEnd('totalTime');\n\n const hostUrl = (containerPort: number): string => {\n const hostPort = portMappings.find((mapping) => mapping.container === containerPort)?.host;\n return hostPort === undefined ? `(container port ${containerPort} is not mapped)` : `http://localhost${hostPort === 80 ? '' : `:${hostPort}`}`;\n };\n const siteUrl = hostUrl(devServerPorts.api);\n const entryLines = [\n ...webEntryRoutes.map((route) => ` ${route.service}/${route.entryName}: ${siteUrl}${route.path === '/' ? '' : route.path}`),\n ...webEntryHosts.map((host) => ` ${host.service}/${host.entryName}: ${hostUrl(host.port)}`),\n ].join('\\n');\n const where = dockerSettings.registry ? `pushed to [${imageName}]` : `[${imageName}] in the local docker store`;\n const onHost = dockerSettings.registry\n ? `On the host (Unraid: Compose Manager, or any docker host), copy the compose file there and run:`\n : `Run it here:`;\n console.log(`\nDone. The image is ${where}.\n\n${onHost}\n\n docker compose -f ${composePath} up -d\n\nThen open ${siteUrl} (replace localhost with the host's address)\n${entryLines ? `\\nWeb entries:\\n${entryLines}\\n` : ''}\nPorts come from the deployment's platformSettings.portMappings (${portMappings.map((m) => `${m.host}:${m.container}`).join(', ')})\nand are baked into the frontend, so a host must map the same ones. App state lives in ${dockerSettings.dataPath ?? `the ${volumeName} volume`}.${\n dockerSettings.mounts?.length\n ? `\\nAlso mounted: ${dockerSettings.mounts.map((mount) => `${mount.host} at ${mount.container}${mount.readOnly ? ' (read-only)' : ''}`).join(', ')}.`\n : ''\n }${\n dockerSettings.publicHost\n ? ''\n : `\\nSecure file urls point at localhost; set platformSettings.publicHost to the address browsers use for this host.`\n }\n`);\n};\n"]}
|
|
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 subdomain>/<svc>), mirroring the AWS layout.\n// 3. Assemble an image context under dist/qpq/docker-image/<app>/, server\n// bundle, web root (every web entry, placed by its port or its domain),\n// a workspaces-stripped package.json for runtime deps, and the\n// locally-built quidproquo packages as a vendor overlay.\n// 4. docker build (buildx with a push when the deployment names a registry or\n// a target platform), write a docker-compose.yml, print how to run it.\n//\n// Not production-grade (single process, sqlite KVS, in-memory queues):\n// it's the whole product on one box with one command.\nimport { getQpqAppDeployment } from '@qpqjs/config-aws';\nimport { getDevServerDistPath, getDockerImageContextPath, isQpqPackageName, QpqDeployEnvVar } from '@qpqjs/core';\nimport { getAppServiceQpqConfigs, getDevServerRspackConfig, listInstalledQpqPackageNames, runRspack } from '@qpqjs/deploy-rspack';\nimport { getWebEntryDir, getWebEntryPlacements, WebEntryHost, WebEntryRoute } from '@qpqjs/dev-server';\nimport { FEDERATED_VIEWS_SUBDOMAIN } from '@qpqjs/webserver';\n\nimport fs from 'fs';\nimport path from 'path';\n\nimport { DeployPlan } from '../../lib/deployPrompts';\nimport { writeDevServerEntry, writeUserScriptChildEntry } from '../../lib/devServerEntry';\nimport { readDevServerPorts } from '../../lib/devServerPorts';\nimport { getRoot, getServiceNamesWithViews } from '../../lib/discovery';\nimport { getDefaultHookJobs } from '../../lib/getDefaultHookJobs';\nimport { runAppHook, runHookForAppPackages } from '../../lib/hooks';\nimport { createOutput } from '../../lib/out';\nimport { getOwnPackageRoot } from '../../lib/packageRoot';\nimport { runCommand } from '../../lib/runCommand';\nimport { assertNoFailures } from '../../lib/runTasks';\nimport { logTimeEnd, logTimeStart } from '../../lib/timing';\nimport { bundleViews, getViewsDistDir } from '../../lib/views';\nimport { clearWebAddressingEnv, setWebAddressingEnv } from '../../lib/webAddressingEnv';\nimport { getContainerPorts } from './getContainerPorts';\nimport { getDockerPlatformSettings, ParsedDockerPlatformSettings } from './getDockerPlatformSettings';\nimport { getImageName } from './getImageName';\nimport { resolvePortMappings } from './resolvePortMappings';\nimport { writeComposeFile } from './writeComposeFile';\n\nconst out = createOutput('docker');\n\nconst getImageContextDir = (root: string, appName: string): string => getDockerImageContextPath(root, appName);\n\n// Every web entry's files go where the runtime looks for them. The federated views entry\n// is assembled from every service's views build (one folder per service, as on AWS);\n// anything else is its own buildPath. A missing build fails here rather than serving an\n// empty site later.\nconst copyWebEntryContent = (appName: string, contextDir: string, entry: WebEntryHost | WebEntryRoute, viewServices: string[]): void => {\n const label = `${entry.service}/${entry.entryName}`;\n const targetDir = getWebEntryDir(path.join(contextDir, 'web'), entry);\n\n if (entry.webEntry.domain.subDomainName === FEDERATED_VIEWS_SUBDOMAIN) {\n for (const serviceName of viewServices) {\n fs.cpSync(getViewsDistDir(appName, serviceName), path.join(targetDir, serviceName), { recursive: true });\n }\n return;\n }\n\n // A standalone host entry serves its own service's views build, as on AWS.\n if (entry.webEntry.storageDrive.syncServiceViews) {\n fs.cpSync(getViewsDistDir(appName, entry.service), targetDir, { recursive: true });\n return;\n }\n\n if (!entry.webEntry.buildPath) {\n throw new Error(`Web entry ${label} has no buildPath, so there is nothing to serve`);\n }\n const buildDir = path.resolve(entry.configRoot, entry.webEntry.buildPath);\n if (!fs.existsSync(path.join(buildDir, entry.webEntry.indexRoot))) {\n throw new Error(`Web entry ${label} has no ${entry.webEntry.indexRoot} under ${buildDir}; build it before qpq go`);\n }\n fs.cpSync(buildDir, targetDir, { recursive: true });\n};\n\n// Plain `docker build` into the local store unless the deployment asks for a registry or a\n// target platform, which need buildx: `--push` sends a cross-platform image straight to the\n// registry, `--load` keeps a same-machine one local.\nconst buildImage = async (imageName: string, contextDir: string, settings: ParsedDockerPlatformSettings): Promise<void> => {\n if (!settings.registry && !settings.arch) {\n await runCommand('docker', ['build', '-t', imageName, contextDir]);\n return;\n }\n\n const platformArgs = settings.arch ? ['--platform', settings.arch] : [];\n await runCommand('docker', ['buildx', 'build', ...platformArgs, '-t', imageName, settings.registry ? '--push' : '--load', contextDir]);\n};\n\n// The Dockerfile is shared; only its EXPOSE line depends on the app.\nconst writeDockerfile = (contextDir: string, containerPorts: number[]): void => {\n const template = fs.readFileSync(path.join(getOwnPackageRoot(), 'docker', 'dev-server', 'Dockerfile'), 'utf8');\n const dockerfile = template.replace(/^EXPOSE .*$/m, `EXPOSE ${containerPorts.join(' ')}`);\n fs.writeFileSync(path.join(contextDir, 'Dockerfile'), dockerfile);\n};\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 (isQpqPackageName(name) && 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 listInstalledQpqPackageNames(nodeModules)) {\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 out.log(`Nothing to do — the docker platform has no ${plan.kind} stacks.`);\n return;\n }\n\n const root = getRoot();\n const deploymentName = process.env[QpqDeployEnvVar.deployName]!;\n const dockerSettings = getDockerPlatformSettings(deploymentName, getQpqAppDeployment(root, appName, deploymentName));\n\n const applicationName = process.env[QpqDeployEnvVar.applicationName]!;\n const imageName = getImageName(applicationName, dockerSettings);\n const containerName = `qpq-${applicationName}`;\n const volumeName = `${containerName}-data`;\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 out.log(`\\n\\nBuilding docker image [${imageName}] — 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 out.log('Building workspace packages');\n assertNoFailures('Workspace build', await runHookForAppPackages('build', appName, getDefaultHookJobs()));\n\n // ---- Server bundle: the dev server + every service, one main.js ----\n out.log('Bundling server (dev server + all services)');\n const qpqConfigs = getAppServiceQpqConfigs(root, appName);\n\n // Resolved before anything slow runs, so a bad port or domain fails the build up front.\n const devServerPorts = readDevServerPorts(appName);\n const { hosts: webEntryHosts, routes: webEntryRoutes } = getWebEntryPlacements(qpqConfigs, Object.values(devServerPorts));\n const containerPorts = getContainerPorts(devServerPorts, webEntryHosts);\n const portMappings = resolvePortMappings(deploymentName, dockerSettings, devServerPorts.api, containerPorts);\n const mapHostPort = (containerPort: number): number => portMappings.find((mapping) => mapping.container === containerPort)?.host ?? containerPort;\n\n // Nothing deploys into the container, so the image runs its own pending migrations on start.\n const entry = writeDevServerEntry(root, appName, 'migrate-then-serve');\n const userScriptChildEntry = writeUserScriptChildEntry(root);\n // The image installs its own node_modules next to the bundle, so externals\n // must stay bare; host-resolved absolute paths do not exist in the container.\n await runRspack(getDevServerRspackConfig({ root, entry, userScriptChildEntry, qpqConfigs, portableExternals: true }));\n\n // ---- Views: production builds with same-origin federation remotes ----\n // The browser reaches everything on the page's own host, on the HOST side of the port\n // mappings; an unmapped port stays as is (nothing outside the container can reach it anyway).\n setWebAddressingEnv(qpqConfigs, { api: devServerPorts.api, webSocket: devServerPorts.webSocket, mapHostPort });\n process.env.QPQ_VIEWS_REMOTE_BASE = `/${FEDERATED_VIEWS_SUBDOMAIN}`;\n const viewServices = getServiceNamesWithViews(appName);\n for (const serviceName of viewServices) {\n out.log(`Bundling views: [${serviceName}]`);\n await bundleViews(appName, serviceName);\n }\n delete process.env.QPQ_VIEWS_REMOTE_BASE;\n clearWebAddressingEnv();\n\n // ---- Assemble the image context ----\n out.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 writeDockerfile(contextDir, containerPorts);\n writeImagePackageJson(root, contextDir);\n\n const vendored = vendorQuidproquoPackages(root, contextDir);\n out.log(`Vendored ${vendored} quidproquo packages`);\n\n fs.cpSync(getDevServerDistPath(root), path.join(contextDir, 'server'), { recursive: true });\n\n for (const entry of [...webEntryRoutes, ...webEntryHosts]) {\n copyWebEntryContent(appName, contextDir, entry, viewServices);\n }\n\n const composePath = writeComposeFile({\n contextDir,\n imageName,\n serviceName: containerName,\n volumeName,\n portMappings,\n dataPath: dockerSettings.dataPath ?? null,\n mounts: dockerSettings.mounts ?? [],\n publicHost: dockerSettings.publicHost ?? null,\n publicFileStoragePort: mapHostPort(devServerPorts.fileStorage),\n });\n\n // ---- Build the image ----\n out.log(\n `Building docker image${dockerSettings.arch ? ` for ${dockerSettings.arch}` : ''}${dockerSettings.registry ? `, pushing to ${dockerSettings.registry}` : ''}`,\n );\n await buildImage(imageName, contextDir, dockerSettings);\n\n logTimeEnd('totalTime');\n\n const hostUrl = (containerPort: number): string => {\n const hostPort = portMappings.find((mapping) => mapping.container === containerPort)?.host;\n return hostPort === undefined ? `(container port ${containerPort} is not mapped)` : `http://localhost${hostPort === 80 ? '' : `:${hostPort}`}`;\n };\n const siteUrl = hostUrl(devServerPorts.api);\n const entryLines = [\n ...webEntryRoutes.map((route) => ` ${route.service}/${route.entryName}: ${siteUrl}${route.path === '/' ? '' : route.path}`),\n ...webEntryHosts.map((host) => ` ${host.service}/${host.entryName}: ${hostUrl(host.port)}`),\n ].join('\\n');\n const where = dockerSettings.registry ? `pushed to [${imageName}]` : `[${imageName}] in the local docker store`;\n const onHost = dockerSettings.registry\n ? `On the host (Unraid: Compose Manager, or any docker host), copy the compose file there and run:`\n : `Run it here:`;\n out.log(`\nDone. The image is ${where}.\n\n${onHost}\n\n docker compose -f ${composePath} up -d\n\nThen open ${siteUrl} (replace localhost with the host's address)\n${entryLines ? `\\nWeb entries:\\n${entryLines}\\n` : ''}\nPorts come from the deployment's platformSettings.portMappings (${portMappings.map((m) => `${m.host}:${m.container}`).join(', ')})\nand are baked into the frontend, so a host must map the same ones. App state lives in ${dockerSettings.dataPath ?? `the ${volumeName} volume`}.${\n dockerSettings.mounts?.length\n ? `\\nAlso mounted: ${dockerSettings.mounts.map((mount) => `${mount.host} at ${mount.container}${mount.readOnly ? ' (read-only)' : ''}`).join(', ')}.`\n : ''\n }${\n dockerSettings.publicHost\n ? ''\n : `\\nSecure file urls point at localhost; set platformSettings.publicHost to the address browsers use for this host.`\n }\n`);\n};\n"]}
|
|
@@ -10,20 +10,21 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
exports.dockerPlatformDriver = void 0;
|
|
13
|
+
const CliError_1 = require("../../lib/CliError");
|
|
13
14
|
const goDockerMode_1 = require("../../lib/goDockerMode");
|
|
15
|
+
const out_1 = require("../../lib/out");
|
|
14
16
|
const getDockerPlatformSettings_1 = require("./getDockerPlatformSettings");
|
|
15
17
|
const go_1 = require("./go");
|
|
18
|
+
const out = (0, out_1.createOutput)('docker');
|
|
16
19
|
const publishNotSupported = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
17
|
-
|
|
18
|
-
process.exit(1);
|
|
20
|
+
throw new CliError_1.CliError('The docker platform has no federated code store: story code is baked into the image. Rebuild with qpq go instead.');
|
|
19
21
|
});
|
|
20
22
|
// A docker platform's deploy already is the containerised one, so `qpq go:docker`
|
|
21
23
|
// (what a scaffolded app's `npm run deploy` runs) is the same build. The image is
|
|
22
24
|
// the deploy, so there is no saved build to split across two runs.
|
|
23
25
|
const dockerGoDocker = (appName, plan, mode) => __awaiter(void 0, void 0, void 0, function* () {
|
|
24
26
|
if (mode !== 'full') {
|
|
25
|
-
|
|
26
|
-
process.exit(1);
|
|
27
|
+
throw new CliError_1.CliError(`The docker platform builds and deploys in one step; ${goDockerMode_1.BUILD_ONLY_FLAG} and ${goDockerMode_1.FROM_BUILD_FLAG} do not apply. Run qpq go:docker without them.`);
|
|
27
28
|
}
|
|
28
29
|
yield (0, go_1.dockerGo)(appName, plan);
|
|
29
30
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/platforms/docker/index.ts"],"names":[],"mappings":";;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/platforms/docker/index.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,iDAA8C;AAE9C,yDAAwF;AACxF,uCAA6C;AAE7C,2EAAwE;AACxE,6BAAgC;AAEhC,MAAM,GAAG,GAAG,IAAA,kBAAY,EAAC,QAAQ,CAAC,CAAC;AAEnC,MAAM,mBAAmB,GAAG,GAAwB,EAAE;IACpD,MAAM,IAAI,mBAAQ,CAAC,mHAAmH,CAAC,CAAC;AAC1I,CAAC,CAAA,CAAC;AAEF,kFAAkF;AAClF,kFAAkF;AAClF,mEAAmE;AACnE,MAAM,cAAc,GAAG,CAAO,OAAe,EAAE,IAAgB,EAAE,IAAkB,EAAiB,EAAE;IACpG,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;QACpB,MAAM,IAAI,mBAAQ,CAChB,uDAAuD,8BAAe,QAAQ,8BAAe,gDAAgD,CAC9I,CAAC;IACJ,CAAC;IAED,MAAM,IAAA,aAAQ,EAAC,OAAO,EAAE,IAAI,CAAC,CAAC;AAChC,CAAC,CAAA,CAAC;AAEW,QAAA,oBAAoB,GAAsB;IACrD,2FAA2F;IAC3F,oFAAoF;IACpF,iBAAiB,EAAE,CAAC,cAAc,EAAE,UAAU,EAAE,EAAE;QAChD,IAAA,qDAAyB,EAAC,cAAc,EAAE,UAAU,CAAC,CAAC;IACxD,CAAC;IAED,EAAE,EAAE,aAAQ;IACZ,QAAQ,EAAE,cAAc;IAExB,OAAO,EAAE,mBAAmB;IAC5B,YAAY,EAAE,mBAAmB;IACjC,aAAa,EAAE,mBAAmB;IAClC,aAAa,EAAE,mBAAmB;CACnC,CAAC","sourcesContent":["import { CliError } from '../../lib/CliError';\nimport { DeployPlan } from '../../lib/deployPrompts';\nimport { BUILD_ONLY_FLAG, FROM_BUILD_FLAG, GoDockerMode } from '../../lib/goDockerMode';\nimport { createOutput } from '../../lib/out';\nimport { QpqPlatformDriver } from '../types';\nimport { getDockerPlatformSettings } from './getDockerPlatformSettings';\nimport { dockerGo } from './go';\n\nconst out = createOutput('docker');\n\nconst publishNotSupported = async (): Promise<void> => {\n throw new CliError('The docker platform has no federated code store: story code is baked into the image. Rebuild with qpq go instead.');\n};\n\n// A docker platform's deploy already is the containerised one, so `qpq go:docker`\n// (what a scaffolded app's `npm run deploy` runs) is the same build. The image is\n// the deploy, so there is no saved build to split across two runs.\nconst dockerGoDocker = async (appName: string, plan: DeployPlan, mode: GoDockerMode): Promise<void> => {\n if (mode !== 'full') {\n throw new CliError(\n `The docker platform builds and deploys in one step; ${BUILD_ONLY_FLAG} and ${FROM_BUILD_FLAG} do not apply. Run qpq go:docker without them.`,\n );\n }\n\n await dockerGo(appName, plan);\n};\n\nexport const dockerPlatformDriver: QpqPlatformDriver = {\n // No identity to prime. Mappings are only parsed here; which container ports exist depends\n // on the app's config, which is not loaded yet, so that check happens in the build.\n prepareDeployment: (deploymentName, deployment) => {\n getDockerPlatformSettings(deploymentName, deployment);\n },\n\n go: dockerGo,\n goDocker: dockerGoDocker,\n\n publish: publishNotSupported,\n publishBuild: publishNotSupported,\n publishUpload: publishNotSupported,\n publishDeploy: publishNotSupported,\n};\n"]}
|
|
@@ -17,11 +17,12 @@ const parseMounts = (value) => value
|
|
|
17
17
|
if (!match) {
|
|
18
18
|
throw new Error(`Mount '${item}' must be host:container with both absolute, optionally ending :ro, e.g. /mnt/user/media:/media`);
|
|
19
19
|
}
|
|
20
|
-
const
|
|
20
|
+
const [, host = '', containerPath = '', mode] = match;
|
|
21
|
+
const container = trimTrailingSlashes(containerPath);
|
|
21
22
|
if (container === IMAGE_ROOT || container.startsWith(`${IMAGE_ROOT}/`) || container === '/') {
|
|
22
23
|
throw new Error(`Mount '${item}' would cover the image's own files: mount it somewhere other than / or ${IMAGE_ROOT}`);
|
|
23
24
|
}
|
|
24
|
-
return { host: trimTrailingSlashes(
|
|
25
|
+
return { host: trimTrailingSlashes(host), container, readOnly: mode === 'ro' };
|
|
25
26
|
});
|
|
26
27
|
exports.parseMounts = parseMounts;
|
|
27
28
|
//# sourceMappingURL=parseMounts.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parseMounts.js","sourceRoot":"","sources":["../../../../src/platforms/docker/parseMounts.ts"],"names":[],"mappings":";;;AAQA,+DAA+D;AAC/D,MAAM,aAAa,GAAG,qCAAqC,CAAC;AAE5D,gGAAgG;AAChG,aAAa;AACb,MAAM,UAAU,GAAG,MAAM,CAAC;AAE1B,MAAM,mBAAmB,GAAG,CAAC,MAAc,EAAU,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,GAAG,CAAC;AAE1F,+FAA+F;AACxF,MAAM,WAAW,GAAG,CAAC,KAAa,EAAW,EAAE,CACpD,KAAK;KACF,KAAK,CAAC,GAAG,CAAC;KACV,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;KAC1B,MAAM,CAAC,OAAO,CAAC;KACf,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;IACZ,MAAM,KAAK,GAAG,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACvC,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CAAC,UAAU,IAAI,iGAAiG,CAAC,CAAC;IACnI,CAAC;IAED,MAAM,
|
|
1
|
+
{"version":3,"file":"parseMounts.js","sourceRoot":"","sources":["../../../../src/platforms/docker/parseMounts.ts"],"names":[],"mappings":";;;AAQA,+DAA+D;AAC/D,MAAM,aAAa,GAAG,qCAAqC,CAAC;AAE5D,gGAAgG;AAChG,aAAa;AACb,MAAM,UAAU,GAAG,MAAM,CAAC;AAE1B,MAAM,mBAAmB,GAAG,CAAC,MAAc,EAAU,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,GAAG,CAAC;AAE1F,+FAA+F;AACxF,MAAM,WAAW,GAAG,CAAC,KAAa,EAAW,EAAE,CACpD,KAAK;KACF,KAAK,CAAC,GAAG,CAAC;KACV,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;KAC1B,MAAM,CAAC,OAAO,CAAC;KACf,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;IACZ,MAAM,KAAK,GAAG,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACvC,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CAAC,UAAU,IAAI,iGAAiG,CAAC,CAAC;IACnI,CAAC;IAED,MAAM,CAAC,EAAE,IAAI,GAAG,EAAE,EAAE,aAAa,GAAG,EAAE,EAAE,IAAI,CAAC,GAAG,KAAK,CAAC;IACtD,MAAM,SAAS,GAAG,mBAAmB,CAAC,aAAa,CAAC,CAAC;IACrD,IAAI,SAAS,KAAK,UAAU,IAAI,SAAS,CAAC,UAAU,CAAC,GAAG,UAAU,GAAG,CAAC,IAAI,SAAS,KAAK,GAAG,EAAE,CAAC;QAC5F,MAAM,IAAI,KAAK,CAAC,UAAU,IAAI,2EAA2E,UAAU,EAAE,CAAC,CAAC;IACzH,CAAC;IAED,OAAO,EAAE,IAAI,EAAE,mBAAmB,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE,IAAI,KAAK,IAAI,EAAE,CAAC;AACjF,CAAC,CAAC,CAAC;AAlBM,QAAA,WAAW,eAkBjB","sourcesContent":["export type Mount = {\n // Absolute folder on the docker host, e.g. /mnt/user/media/downloads.\n host: string;\n // Where it appears inside the container.\n container: string;\n readOnly: boolean;\n};\n\n// host:container, both absolute, optionally ending :ro or :rw.\nconst MOUNT_PATTERN = /^(\\/[^:]*):(\\/[^:]*?)(?::(ro|rw))?$/;\n\n// The image's own files live under /app (including the state directory), so a mount there would\n// hide them.\nconst IMAGE_ROOT = '/app';\n\nconst trimTrailingSlashes = (folder: string): string => folder.replace(/\\/+$/, '') || '/';\n\n/** Parses \"host:container[:ro], ...\" into mounts, throwing naming the first malformed item. */\nexport const parseMounts = (value: string): Mount[] =>\n value\n .split(',')\n .map((item) => item.trim())\n .filter(Boolean)\n .map((item) => {\n const match = MOUNT_PATTERN.exec(item);\n if (!match) {\n throw new Error(`Mount '${item}' must be host:container with both absolute, optionally ending :ro, e.g. /mnt/user/media:/media`);\n }\n\n const [, host = '', containerPath = '', mode] = match;\n const container = trimTrailingSlashes(containerPath);\n if (container === IMAGE_ROOT || container.startsWith(`${IMAGE_ROOT}/`) || container === '/') {\n throw new Error(`Mount '${item}' would cover the image's own files: mount it somewhere other than / or ${IMAGE_ROOT}`);\n }\n\n return { host: trimTrailingSlashes(host), container, readOnly: mode === 'ro' };\n });\n"]}
|
|
@@ -15,9 +15,12 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
17
|
exports.getPlatformDriver = void 0;
|
|
18
|
+
const CliError_1 = require("../lib/CliError");
|
|
19
|
+
const out_1 = require("../lib/out");
|
|
18
20
|
const aws_1 = require("./aws");
|
|
19
21
|
const docker_1 = require("./docker");
|
|
20
22
|
const types_1 = require("./types");
|
|
23
|
+
const out = (0, out_1.createOutput)('platform');
|
|
21
24
|
const platformDrivers = {
|
|
22
25
|
[types_1.QpqDeployPlatform.aws]: aws_1.awsPlatformDriver,
|
|
23
26
|
[types_1.QpqDeployPlatform.docker]: docker_1.dockerPlatformDriver,
|
|
@@ -25,8 +28,7 @@ const platformDrivers = {
|
|
|
25
28
|
const getPlatformDriver = (platform) => {
|
|
26
29
|
const driver = platformDrivers[platform];
|
|
27
30
|
if (!driver) {
|
|
28
|
-
|
|
29
|
-
process.exit(1);
|
|
31
|
+
throw new CliError_1.CliError(`Unknown deploy platform '${platform}'. Supported platforms: ${Object.keys(platformDrivers).join(', ')}`);
|
|
30
32
|
}
|
|
31
33
|
return driver;
|
|
32
34
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/platforms/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,+BAA0C;AAC1C,qCAAgD;AAChD,mCAA+D;AAE/D,MAAM,eAAe,GAAsC;IACzD,CAAC,yBAAiB,CAAC,GAAG,CAAC,EAAE,uBAAiB;IAC1C,CAAC,yBAAiB,CAAC,MAAM,CAAC,EAAE,6BAAoB;CACjD,CAAC;AAEK,MAAM,iBAAiB,GAAG,CAAC,QAAgB,EAAqB,EAAE;IACvE,MAAM,MAAM,GAAG,eAAe,CAAC,QAAQ,CAAC,CAAC;IAEzC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/platforms/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,8CAA2C;AAC3C,oCAA0C;AAC1C,+BAA0C;AAC1C,qCAAgD;AAChD,mCAA+D;AAE/D,MAAM,GAAG,GAAG,IAAA,kBAAY,EAAC,UAAU,CAAC,CAAC;AAErC,MAAM,eAAe,GAAsC;IACzD,CAAC,yBAAiB,CAAC,GAAG,CAAC,EAAE,uBAAiB;IAC1C,CAAC,yBAAiB,CAAC,MAAM,CAAC,EAAE,6BAAoB;CACjD,CAAC;AAEK,MAAM,iBAAiB,GAAG,CAAC,QAAgB,EAAqB,EAAE;IACvE,MAAM,MAAM,GAAG,eAAe,CAAC,QAAQ,CAAC,CAAC;IAEzC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,mBAAQ,CAAC,4BAA4B,QAAQ,2BAA2B,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC/H,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC,CAAC;AARW,QAAA,iBAAiB,qBAQ5B;AAEF,0CAAwB","sourcesContent":["import { CliError } from '../lib/CliError';\nimport { createOutput } from '../lib/out';\nimport { awsPlatformDriver } from './aws';\nimport { dockerPlatformDriver } from './docker';\nimport { QpqDeployPlatform, QpqPlatformDriver } from './types';\n\nconst out = createOutput('platform');\n\nconst platformDrivers: Record<string, QpqPlatformDriver> = {\n [QpqDeployPlatform.aws]: awsPlatformDriver,\n [QpqDeployPlatform.docker]: dockerPlatformDriver,\n};\n\nexport const getPlatformDriver = (platform: string): QpqPlatformDriver => {\n const driver = platformDrivers[platform];\n\n if (!driver) {\n throw new CliError(`Unknown deploy platform '${platform}'. Supported platforms: ${Object.keys(platformDrivers).join(', ')}`);\n }\n\n return driver;\n};\n\nexport * from './types';\n"]}
|
|
@@ -7,7 +7,7 @@ export declare enum QpqDeployPlatform {
|
|
|
7
7
|
aws = "aws",
|
|
8
8
|
docker = "docker"
|
|
9
9
|
}
|
|
10
|
-
export
|
|
10
|
+
export type QpqPlatformDriver = {
|
|
11
11
|
prepareDeployment: (deploymentName: string, deployment: QpqAppDeployment) => void;
|
|
12
12
|
go: (appName: string, plan: DeployPlan) => Promise<void>;
|
|
13
13
|
goDocker?: (appName: string, plan: DeployPlan, mode: GoDockerMode) => Promise<void>;
|
|
@@ -18,4 +18,4 @@ export interface QpqPlatformDriver {
|
|
|
18
18
|
publishBuild: (appName: string, serviceNames: string[]) => Promise<void>;
|
|
19
19
|
publishUpload: (appName: string, serviceNames: string[]) => Promise<void>;
|
|
20
20
|
publishDeploy: (appName: string, serviceNames: string[]) => Promise<void>;
|
|
21
|
-
}
|
|
21
|
+
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/platforms/types.ts"],"names":[],"mappings":";;;AAOA,IAAY,iBAGX;AAHD,WAAY,iBAAiB;IAC3B,gCAAW,CAAA;IACX,sCAAiB,CAAA;AACnB,CAAC,EAHW,iBAAiB,iCAAjB,iBAAiB,QAG5B","sourcesContent":["import { QpqAppDeployment } from '@qpqjs/core';\n\nimport { ClearResourcesPlan } from '../lib/clearResourcesPlan';\nimport { DeployPlan, TeardownPlan } from '../lib/deployPrompts';\nimport { GoDockerMode } from '../lib/goDockerMode';\nimport { SetupStep } from '../lib/setupStep';\n\nexport enum QpqDeployPlatform {\n aws = 'aws',\n docker = 'docker',\n}\n\n// A deploy platform driver
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/platforms/types.ts"],"names":[],"mappings":";;;AAOA,IAAY,iBAGX;AAHD,WAAY,iBAAiB;IAC3B,gCAAW,CAAA;IACX,sCAAiB,CAAA;AACnB,CAAC,EAHW,iBAAiB,iCAAjB,iBAAiB,QAG5B","sourcesContent":["import { QpqAppDeployment } from '@qpqjs/core';\n\nimport { ClearResourcesPlan } from '../lib/clearResourcesPlan';\nimport { DeployPlan, TeardownPlan } from '../lib/deployPrompts';\nimport { GoDockerMode } from '../lib/goDockerMode';\nimport { SetupStep } from '../lib/setupStep';\n\nexport enum QpqDeployPlatform {\n aws = 'aws',\n docker = 'docker',\n}\n\n// A deploy platform driver, everything that happens after \"what to deploy\"\n// has been decided. `qpq go` resolves the app + deployment, prompts the plan,\n// then hands off here; the platform comes from the deployment's entry in\n// apps/<app>/deploy.config.json, so an app can move platforms with a config\n// change instead of a different command.\nexport type QpqPlatformDriver = {\n // Check the deployment's platformSettings and prime the platform's identity\n // env vars from them. Throws when the entry is incomplete. Runs before any\n // infrastructure.ts is required, since service configs read those vars at load.\n prepareDeployment: (deploymentName: string, deployment: QpqAppDeployment) => void;\n\n // Sequential deploy (`qpq go`).\n go: (appName: string, plan: DeployPlan) => Promise<void>;\n\n // Parallel containerized deploy (`qpq go:docker`), optional; drivers that\n // have no docker strategy simply omit it. The mode splits the run into a\n // build half and a deploy half (`--build-only` / `--from-build`); a driver\n // whose build and deploy cannot be separated refuses anything but 'full'.\n goDocker?: (appName: string, plan: DeployPlan, mode: GoDockerMode) => Promise<void>;\n\n // Destroy the web/api/inf stacks for selected services (`qpq teardown`):\n // optional; drivers with no teardown strategy simply omit it.\n teardown?: (appName: string, plan: TeardownPlan) => Promise<void>;\n\n // Empty the stored data of selected resources without touching the stacks\n // (`qpq clear-resources`), optional; drivers with no strategy omit it.\n clearResources?: (appName: string, plan: ClearResourcesPlan) => Promise<void>;\n\n // The ordered checklist that takes an empty cloud environment to a deployed\n // one (`qpq setup`), optional; drivers with nothing to set up omit it.\n setupSteps?: (appName: string, deploymentName: string) => Promise<SetupStep[]>;\n\n // Federated remote publishing (`qpq publish[:build|:upload|:deploy]`).\n publish: (appName: string, serviceNames: string[]) => Promise<void>;\n publishBuild: (appName: string, serviceNames: string[]) => Promise<void>;\n publishUpload: (appName: string, serviceNames: string[]) => Promise<void>;\n publishDeploy: (appName: string, serviceNames: string[]) => Promise<void>;\n};\n"]}
|
|
@@ -5,9 +5,9 @@
|
|
|
5
5
|
// continues until the user picks a runnable leaf. Rows are deliberately left
|
|
6
6
|
// unstyled so inquirer's active-item highlight colours the whole row.
|
|
7
7
|
import { promptSelectDetailed } from '../lib/prompts';
|
|
8
|
-
const lastSegment = (name) => name.split(':').slice(-1)[0];
|
|
8
|
+
const lastSegment = (name) => name.split(':').slice(-1)[0] ?? name;
|
|
9
9
|
// The first path segment of `name` below `prefix` ('' means the tree root).
|
|
10
|
-
const childSegment = (name, prefix) => name.slice(prefix ? prefix.length + 1 : 0).split(':')[0];
|
|
10
|
+
const childSegment = (name, prefix) => name.slice(prefix ? prefix.length + 1 : 0).split(':')[0] ?? '';
|
|
11
11
|
const runRow = (command) => ({
|
|
12
12
|
label: `qpq ${command.name}`,
|
|
13
13
|
summary: command.summary,
|
|
@@ -22,8 +22,9 @@ const buildRows = (commands, prefix) => {
|
|
|
22
22
|
for (const segment of segments) {
|
|
23
23
|
const segmentPrefix = prefix ? `${prefix}:${segment}` : segment;
|
|
24
24
|
const subtree = deeper.filter((command) => command.name === segmentPrefix || command.name.startsWith(`${segmentPrefix}:`));
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
const [only] = subtree;
|
|
26
|
+
if (subtree.length === 1 && only && only.name === segmentPrefix) {
|
|
27
|
+
leafRows.push(runRow(only));
|
|
27
28
|
}
|
|
28
29
|
else {
|
|
29
30
|
// A group's summary is its own runnable command's summary when it has
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"commandMenu.js","sourceRoot":"","sources":["../../../src/cli/commandMenu.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,yEAAyE;AACzE,2EAA2E;AAC3E,6EAA6E;AAC7E,6EAA6E;AAC7E,sEAAsE;AACtE,OAAO,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAOtD,MAAM,WAAW,GAAG,CAAC,IAAY,EAAU,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"commandMenu.js","sourceRoot":"","sources":["../../../src/cli/commandMenu.ts"],"names":[],"mappings":"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","sourcesContent":["// Interactive drill-down for a bare `qpq`: the colon-separated command names\n// form a tree (go, go:dev, go:dev:api, ...). Each menu level renders its\n// options as the full command line they resolve to (`qpq go:dev:api`) with\n// the command's summary alongside, groups shown as `qpq go:??`, and drilling\n// continues until the user picks a runnable leaf. Rows are deliberately left\n// unstyled so inquirer's active-item highlight colours the whole row.\nimport { promptSelectDetailed } from '../lib/prompts';\nimport { CliCommand } from './commandRegistry';\n\ntype MenuChoice = { kind: 'run'; command: CliCommand } | { kind: 'drill'; prefix: string } | { kind: 'back' };\n\ntype MenuRow = { label: string; summary?: string; value: MenuChoice };\n\nconst lastSegment = (name: string): string => name.split(':').slice(-1)[0] ?? name;\n\n// The first path segment of `name` below `prefix` ('' means the tree root).\nconst childSegment = (name: string, prefix: string): string => name.slice(prefix ? prefix.length + 1 : 0).split(':')[0] ?? '';\n\nconst runRow = (command: CliCommand): MenuRow => ({\n label: `qpq ${command.name}`,\n summary: command.summary,\n value: { kind: 'run', command },\n});\n\nconst buildRows = (commands: CliCommand[], prefix: string): MenuRow[] => {\n const exact = prefix ? commands.find((command) => command.name === prefix) : undefined;\n const deeper = commands.filter((command) => command.name !== prefix && (!prefix || command.name.startsWith(`${prefix}:`)));\n const segments = [...new Set(deeper.map((command) => childSegment(command.name, prefix)))];\n\n const groupRows: MenuRow[] = [];\n const leafRows: MenuRow[] = [];\n\n for (const segment of segments) {\n const segmentPrefix = prefix ? `${prefix}:${segment}` : segment;\n const subtree = deeper.filter((command) => command.name === segmentPrefix || command.name.startsWith(`${segmentPrefix}:`));\n\n const [only] = subtree;\n if (subtree.length === 1 && only && only.name === segmentPrefix) {\n leafRows.push(runRow(only));\n } else {\n // A group's summary is its own runnable command's summary when it has\n // one, otherwise a listing of what's inside.\n const groupSummary = subtree.find((command) => command.name === segmentPrefix)?.summary;\n groupRows.push({\n label: `qpq ${segmentPrefix}:??`,\n summary: groupSummary ?? subtree.map((command) => lastSegment(command.name)).join(', '),\n value: { kind: 'drill', prefix: segmentPrefix },\n });\n }\n }\n\n // The current prefix's own command (run what this menu is named after)\n // leads, then groups, then the remaining runnable commands.\n const rows = [...(exact ? [runRow(exact)] : []), ...groupRows, ...leafRows];\n\n if (prefix) {\n rows.push({ label: '(back)', value: { kind: 'back' } });\n }\n\n return rows;\n};\n\n// Align the rows into two columns: the command line, then its summary.\nconst toChoices = (rows: MenuRow[]): { name: string; value: MenuChoice; short?: string }[] => {\n const columnWidth = Math.max(...rows.map((row) => row.label.length)) + 2;\n\n return rows.map((row) => ({\n name: row.summary ? `${row.label.padEnd(columnWidth)}${row.summary}` : row.label,\n value: row.value,\n short: row.label,\n }));\n};\n\n// Walk the menu until a runnable command is picked.\nexport const promptCommandFromMenu = async (commands: CliCommand[]): Promise<CliCommand> => {\n let prefix = '';\n\n for (;;) {\n const picked = await promptSelectDetailed<MenuChoice>('Run:', toChoices(buildRows(commands, prefix)));\n\n if (picked.kind === 'run') {\n return picked.command;\n }\n\n prefix = picked.kind === 'drill' ? picked.prefix : prefix.split(':').slice(0, -1).join(':');\n }\n};\n"]}
|
package/lib/esm/cli/runCli.js
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
|
+
import { CliError } from '../lib/CliError';
|
|
2
|
+
import { createOutput } from '../lib/out';
|
|
1
3
|
import { promptCommandFromMenu } from './commandMenu';
|
|
2
4
|
import { buildUsage, cliCommands } from './commandRegistry';
|
|
3
|
-
|
|
5
|
+
const out = createOutput('cli');
|
|
6
|
+
// Service infrastructure.ts files (and app config fragments) are TypeScript, so
|
|
4
7
|
// register ts-node's transpile-only require hook so the CLI can require them
|
|
5
8
|
// directly, using the consumer root's tsconfig.json ts-node settings.
|
|
6
9
|
//
|
|
7
10
|
// CONTRACT: JavaScript apps (create-qpq-app --language javascript) also lean
|
|
8
|
-
// on this hook
|
|
11
|
+
// on this hook, their tsconfig.json ts-node block sets allowJs (so their
|
|
9
12
|
// ESM-syntax infrastructure.js compiles at require time) and scope/scopeDir
|
|
10
13
|
// (so the hook never touches quidproquo libs outside the app). Any
|
|
11
14
|
// replacement for ts-node here must honour those consumer tsconfig options.
|
|
@@ -34,7 +37,7 @@ const resolveCommandInteractively = async () => {
|
|
|
34
37
|
export const runCli = async (argv) => {
|
|
35
38
|
const [commandName, ...argvRest] = argv;
|
|
36
39
|
if (commandName === 'help' || commandName === '--help') {
|
|
37
|
-
|
|
40
|
+
out.log(buildUsage());
|
|
38
41
|
return;
|
|
39
42
|
}
|
|
40
43
|
let command;
|
|
@@ -42,7 +45,7 @@ export const runCli = async (argv) => {
|
|
|
42
45
|
if (!commandName) {
|
|
43
46
|
// Only prompt on a real terminal; piped/CI invocations get the usage text.
|
|
44
47
|
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
|
45
|
-
|
|
48
|
+
out.log(buildUsage());
|
|
46
49
|
return;
|
|
47
50
|
}
|
|
48
51
|
const resolved = await resolveCommandInteractively();
|
|
@@ -55,8 +58,8 @@ export const runCli = async (argv) => {
|
|
|
55
58
|
command = cliCommands.find((c) => c.name === commandName);
|
|
56
59
|
commandArgv = argvRest;
|
|
57
60
|
if (!command) {
|
|
58
|
-
|
|
59
|
-
|
|
61
|
+
out.error(`Unknown command: ${commandName}`);
|
|
62
|
+
out.log(buildUsage());
|
|
60
63
|
process.exitCode = 1;
|
|
61
64
|
return;
|
|
62
65
|
}
|
|
@@ -66,7 +69,12 @@ export const runCli = async (argv) => {
|
|
|
66
69
|
await command.run(commandArgv);
|
|
67
70
|
}
|
|
68
71
|
catch (error) {
|
|
69
|
-
|
|
72
|
+
if (error instanceof CliError) {
|
|
73
|
+
out.error(error.message);
|
|
74
|
+
process.exitCode = error.exitCode;
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
out.error(`qpq ${command.name} failed:`, error);
|
|
70
78
|
process.exitCode = 1;
|
|
71
79
|
}
|
|
72
80
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runCli.js","sourceRoot":"","sources":["../../../src/cli/runCli.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"runCli.js","sourceRoot":"","sources":["../../../src/cli/runCli.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAC3C,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AACtD,OAAO,EAAE,UAAU,EAAc,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAExE,MAAM,GAAG,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC;AAEhC,gFAAgF;AAChF,6EAA6E;AAC7E,sEAAsE;AACtE,EAAE;AACF,6EAA6E;AAC7E,yEAAyE;AACzE,4EAA4E;AAC5E,mEAAmE;AACnE,4EAA4E;AAC5E,MAAM,cAAc,GAAG,GAAS,EAAE;IAChC,iEAAiE;IACjE,OAAO,CAAC,SAAS,CAAC,CAAC,QAAQ,CAAC,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;AACvD,CAAC,CAAC;AAEF,wEAAwE;AACxE,iCAAiC;AACjC,MAAM,YAAY,GAAG,CAAC,KAAc,EAAW,EAAE,CAAC,KAAK,YAAY,KAAK,IAAI,KAAK,CAAC,IAAI,KAAK,iBAAiB,CAAC;AAE7G,0EAA0E;AAC1E,4EAA4E;AAC5E,MAAM,2BAA2B,GAAG,KAAK,IAAuE,EAAE;IAChH,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,qBAAqB,CAAC,WAAW,CAAC,CAAC;QACzD,MAAM,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,MAAM,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAEzE,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC;IAClC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC;YACxB,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,MAAM,GAAG,KAAK,EAAE,IAAc,EAAiB,EAAE;IAC5D,MAAM,CAAC,WAAW,EAAE,GAAG,QAAQ,CAAC,GAAG,IAAI,CAAC;IAExC,IAAI,WAAW,KAAK,MAAM,IAAI,WAAW,KAAK,QAAQ,EAAE,CAAC;QACvD,GAAG,CAAC,GAAG,CAAC,UAAU,EAAE,CAAC,CAAC;QACtB,OAAO;IACT,CAAC;IAED,IAAI,OAA+B,CAAC;IACpC,IAAI,WAAW,GAAa,EAAE,CAAC;IAE/B,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,2EAA2E;QAC3E,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;YAClD,GAAG,CAAC,GAAG,CAAC,UAAU,EAAE,CAAC,CAAC;YACtB,OAAO;QACT,CAAC;QAED,MAAM,QAAQ,GAAG,MAAM,2BAA2B,EAAE,CAAC;QAErD,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,OAAO;QACT,CAAC;QAED,CAAC,EAAE,OAAO,EAAE,WAAW,EAAE,GAAG,QAAQ,CAAC,CAAC;IACxC,CAAC;SAAM,CAAC;QACN,OAAO,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,WAAW,CAAC,CAAC;QAC1D,WAAW,GAAG,QAAQ,CAAC;QAEvB,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,GAAG,CAAC,KAAK,CAAC,oBAAoB,WAAW,EAAE,CAAC,CAAC;YAC7C,GAAG,CAAC,GAAG,CAAC,UAAU,EAAE,CAAC,CAAC;YACtB,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;YACrB,OAAO;QACT,CAAC;IACH,CAAC;IAED,cAAc,EAAE,CAAC;IAEjB,IAAI,CAAC;QACH,MAAM,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IACjC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,QAAQ,EAAE,CAAC;YAC9B,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YACzB,OAAO,CAAC,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC;YAClC,OAAO;QACT,CAAC;QAED,GAAG,CAAC,KAAK,CAAC,OAAO,OAAO,CAAC,IAAI,UAAU,EAAE,KAAK,CAAC,CAAC;QAChD,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;IACvB,CAAC;AACH,CAAC,CAAC","sourcesContent":["import { Nullable } from '@qpqjs/core';\n\nimport { CliError } from '../lib/CliError';\nimport { createOutput } from '../lib/out';\nimport { promptCommandFromMenu } from './commandMenu';\nimport { buildUsage, CliCommand, cliCommands } from './commandRegistry';\n\nconst out = createOutput('cli');\n\n// Service infrastructure.ts files (and app config fragments) are TypeScript, so\n// register ts-node's transpile-only require hook so the CLI can require them\n// directly, using the consumer root's tsconfig.json ts-node settings.\n//\n// CONTRACT: JavaScript apps (create-qpq-app --language javascript) also lean\n// on this hook, their tsconfig.json ts-node block sets allowJs (so their\n// ESM-syntax infrastructure.js compiles at require time) and scope/scopeDir\n// (so the hook never touches quidproquo libs outside the app). Any\n// replacement for ts-node here must honour those consumer tsconfig options.\nconst registerTsNode = (): void => {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n require('ts-node').register({ transpileOnly: true });\n};\n\n// Inquirer throws ExitPromptError on ctrl-c; treat that as a quiet exit\n// rather than a command failure.\nconst isPromptExit = (error: unknown): boolean => error instanceof Error && error.name === 'ExitPromptError';\n\n// Bare `qpq` on a terminal: drill through the command menu, gathering any\n// arguments the picked command needs. Returns null when the user bails out.\nconst resolveCommandInteractively = async (): Promise<Nullable<{ command: CliCommand; commandArgv: string[] }>> => {\n try {\n const command = await promptCommandFromMenu(cliCommands);\n const commandArgv = command.promptArgs ? await command.promptArgs() : [];\n\n return { command, commandArgv };\n } catch (error) {\n if (isPromptExit(error)) {\n return null;\n }\n\n throw error;\n }\n};\n\nexport const runCli = async (argv: string[]): Promise<void> => {\n const [commandName, ...argvRest] = argv;\n\n if (commandName === 'help' || commandName === '--help') {\n out.log(buildUsage());\n return;\n }\n\n let command: CliCommand | undefined;\n let commandArgv: string[] = [];\n\n if (!commandName) {\n // Only prompt on a real terminal; piped/CI invocations get the usage text.\n if (!process.stdin.isTTY || !process.stdout.isTTY) {\n out.log(buildUsage());\n return;\n }\n\n const resolved = await resolveCommandInteractively();\n\n if (!resolved) {\n return;\n }\n\n ({ command, commandArgv } = resolved);\n } else {\n command = cliCommands.find((c) => c.name === commandName);\n commandArgv = argvRest;\n\n if (!command) {\n out.error(`Unknown command: ${commandName}`);\n out.log(buildUsage());\n process.exitCode = 1;\n return;\n }\n }\n\n registerTsNode();\n\n try {\n await command.run(commandArgv);\n } catch (error) {\n if (error instanceof CliError) {\n out.error(error.message);\n process.exitCode = error.exitCode;\n return;\n }\n\n out.error(`qpq ${command.name} failed:`, error);\n process.exitCode = 1;\n }\n};\n"]}
|