@qpqjs/cli 0.3.0 → 0.5.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 +27 -23
- package/lib/commonjs/commands/goDevApi.js.map +1 -1
- package/lib/commonjs/commands/goDevWeb.js +14 -9
- 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/Output.d.ts +12 -0
- package/lib/commonjs/lib/Output.js +3 -0
- package/lib/commonjs/lib/Output.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/createOutput.d.ts +2 -0
- package/lib/commonjs/lib/createOutput.js +39 -0
- package/lib/commonjs/lib/createOutput.js.map +1 -0
- 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/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.d.ts +1 -0
- package/lib/commonjs/lib/qpqConfigs.js +11 -6
- 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 +17 -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 +17 -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 +24 -21
- package/lib/esm/commands/goDevApi.js.map +1 -1
- package/lib/esm/commands/goDevWeb.js +13 -9
- 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/Output.d.ts +12 -0
- package/lib/esm/lib/Output.js +2 -0
- package/lib/esm/lib/Output.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/createOutput.d.ts +2 -0
- package/lib/esm/lib/createOutput.js +35 -0
- package/lib/esm/lib/createOutput.js.map +1 -0
- 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/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.d.ts +1 -0
- package/lib/esm/lib/qpqConfigs.js +9 -5
- 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 +18 -26
- 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 +20 -32
- 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
|
@@ -1,26 +1,27 @@
|
|
|
1
|
-
// Docker platform deploy (`qpq go` with platform 'docker')
|
|
1
|
+
// Docker platform deploy (`qpq go` with platform 'docker'), proof-of-concept
|
|
2
2
|
// self-hosting: bakes the QPQ dev server (a full local platform emulation)
|
|
3
3
|
// plus every service of the app and its pre-built views into one docker image.
|
|
4
4
|
//
|
|
5
5
|
// 1. Build workspace packages, then the dev-server bundle (all services).
|
|
6
6
|
// 2. Build every views microfrontend with a same-origin module-federation
|
|
7
7
|
// remote base (/<views subdomain>/<svc>), mirroring the AWS layout.
|
|
8
|
-
// 3. Assemble an image context under dist/qpq/docker-image/<app
|
|
8
|
+
// 3. Assemble an image context under dist/qpq/docker-image/<app>/, server
|
|
9
9
|
// bundle, web root (every web entry, placed by its port or its domain),
|
|
10
10
|
// a workspaces-stripped package.json for runtime deps, and the
|
|
11
11
|
// locally-built quidproquo packages as a vendor overlay.
|
|
12
12
|
// 4. docker build (buildx with a push when the deployment names a registry or
|
|
13
13
|
// a target platform), write a docker-compose.yml, print how to run it.
|
|
14
14
|
//
|
|
15
|
-
// Not production-grade (single process, sqlite KVS, in-memory queues)
|
|
15
|
+
// Not production-grade (single process, sqlite KVS, in-memory queues):
|
|
16
16
|
// it's the whole product on one box with one command.
|
|
17
17
|
import { getQpqAppDeployment } from '@qpqjs/config-aws';
|
|
18
|
-
import { isQpqPackageName, QpqDeployEnvVar } from '@qpqjs/core';
|
|
18
|
+
import { getDevServerDistPath, getDockerImageContextPath, isQpqPackageName, QpqDeployEnvVar } from '@qpqjs/core';
|
|
19
19
|
import { getAppServiceQpqConfigs, getDevServerRspackConfig, listInstalledQpqPackageNames, runRspack } from '@qpqjs/deploy-rspack';
|
|
20
20
|
import { getWebEntryDir, getWebEntryPlacements } from '@qpqjs/dev-server';
|
|
21
21
|
import { FEDERATED_VIEWS_SUBDOMAIN } from '@qpqjs/webserver';
|
|
22
22
|
import fs from 'fs';
|
|
23
23
|
import path from 'path';
|
|
24
|
+
import { createOutput } from '../../lib/createOutput';
|
|
24
25
|
import { writeDevServerEntry, writeUserScriptChildEntry } from '../../lib/devServerEntry';
|
|
25
26
|
import { readDevServerPorts } from '../../lib/devServerPorts';
|
|
26
27
|
import { getRoot, getServiceNamesWithViews } from '../../lib/discovery';
|
|
@@ -37,7 +38,8 @@ import { getDockerPlatformSettings } from './getDockerPlatformSettings';
|
|
|
37
38
|
import { getImageName } from './getImageName';
|
|
38
39
|
import { resolvePortMappings } from './resolvePortMappings';
|
|
39
40
|
import { writeComposeFile } from './writeComposeFile';
|
|
40
|
-
const
|
|
41
|
+
const out = createOutput('docker');
|
|
42
|
+
const getImageContextDir = (root, appName) => getDockerImageContextPath(root, appName);
|
|
41
43
|
// Every web entry's files go where the runtime looks for them. The federated views entry
|
|
42
44
|
// is assembled from every service's views build (one folder per service, as on AWS);
|
|
43
45
|
// anything else is its own buildPath. A missing build fails here rather than serving an
|
|
@@ -84,12 +86,12 @@ const writeDockerfile = (contextDir, containerPorts) => {
|
|
|
84
86
|
};
|
|
85
87
|
// The consumer root package.json, stripped to what the image's npm install
|
|
86
88
|
// needs: runtime dependencies (+ overrides). Workspaces/scripts/devDeps are
|
|
87
|
-
// host-only concerns
|
|
89
|
+
// host-only concerns, the workspace packages themselves are bundled into the
|
|
88
90
|
// server bundle from source.
|
|
89
91
|
//
|
|
90
92
|
// quidproquo deps declared as file: refs (a consumer living beside the qpq
|
|
91
93
|
// monorepo) point outside the image context, where npm install would leave
|
|
92
|
-
// dangling symlinks
|
|
94
|
+
// dangling symlinks, rewrite them to the vendored copies inside the context.
|
|
93
95
|
const writeImagePackageJson = (root, contextDir) => {
|
|
94
96
|
const rootPackageJson = JSON.parse(fs.readFileSync(path.join(root, 'package.json'), 'utf8'));
|
|
95
97
|
const dependencies = { ...(rootPackageJson.dependencies ?? {}) };
|
|
@@ -110,7 +112,7 @@ const writeImagePackageJson = (root, contextDir) => {
|
|
|
110
112
|
// Copy the locally-built quidproquo packages (which may be npm-linked
|
|
111
113
|
// checkouts newer than the registry) into vendor/ so the image runs the same
|
|
112
114
|
// qpq code the bundle was built against. Follows the node_modules symlinks;
|
|
113
|
-
// lib/config only
|
|
115
|
+
// lib/config only, no node_modules, no src.
|
|
114
116
|
const vendorQuidproquoPackages = (root, contextDir) => {
|
|
115
117
|
const nodeModules = path.join(root, 'node_modules');
|
|
116
118
|
const vendorDir = path.join(contextDir, 'vendor');
|
|
@@ -135,7 +137,7 @@ export const dockerGo = async (appName, plan) => {
|
|
|
135
137
|
return;
|
|
136
138
|
}
|
|
137
139
|
if (plan.kind === 'account' || plan.kind === 'bootstrap') {
|
|
138
|
-
|
|
140
|
+
out.log(`Nothing to do — the docker platform has no ${plan.kind} stacks.`);
|
|
139
141
|
return;
|
|
140
142
|
}
|
|
141
143
|
const root = getRoot();
|
|
@@ -146,16 +148,16 @@ export const dockerGo = async (appName, plan) => {
|
|
|
146
148
|
const containerName = `qpq-${applicationName}`;
|
|
147
149
|
const volumeName = `${containerName}-data`;
|
|
148
150
|
// The dev server hosts every service of the app, so per-service/stack
|
|
149
|
-
// selections don't apply
|
|
150
|
-
|
|
151
|
+
// selections don't apply, the image is always the whole app.
|
|
152
|
+
out.log(`\n\nBuilding docker image [${imageName}] — the whole app deploys as one image\n\n`);
|
|
151
153
|
logTimeStart('totalTime');
|
|
152
154
|
await runAppHook(appName, 'predeploy');
|
|
153
155
|
// Workspace packages resolve through their built dist/ (package.json main),
|
|
154
156
|
// so bundles would ship stale code unless every lib is tsc'd first.
|
|
155
|
-
|
|
157
|
+
out.log('Building workspace packages');
|
|
156
158
|
assertNoFailures('Workspace build', await runHookForAppPackages('build', appName, getDefaultHookJobs()));
|
|
157
159
|
// ---- Server bundle: the dev server + every service, one main.js ----
|
|
158
|
-
|
|
160
|
+
out.log('Bundling server (dev server + all services)');
|
|
159
161
|
const qpqConfigs = getAppServiceQpqConfigs(root, appName);
|
|
160
162
|
// Resolved before anything slow runs, so a bad port or domain fails the build up front.
|
|
161
163
|
const devServerPorts = readDevServerPorts(appName);
|
|
@@ -176,21 +178,21 @@ export const dockerGo = async (appName, plan) => {
|
|
|
176
178
|
process.env.QPQ_VIEWS_REMOTE_BASE = `/${FEDERATED_VIEWS_SUBDOMAIN}`;
|
|
177
179
|
const viewServices = getServiceNamesWithViews(appName);
|
|
178
180
|
for (const serviceName of viewServices) {
|
|
179
|
-
|
|
181
|
+
out.log(`Bundling views: [${serviceName}]`);
|
|
180
182
|
await bundleViews(appName, serviceName);
|
|
181
183
|
}
|
|
182
184
|
delete process.env.QPQ_VIEWS_REMOTE_BASE;
|
|
183
185
|
clearWebAddressingEnv();
|
|
184
186
|
// ---- Assemble the image context ----
|
|
185
|
-
|
|
187
|
+
out.log('Assembling image context');
|
|
186
188
|
const contextDir = getImageContextDir(root, appName);
|
|
187
189
|
fs.rmSync(contextDir, { recursive: true, force: true });
|
|
188
190
|
fs.mkdirSync(contextDir, { recursive: true });
|
|
189
191
|
writeDockerfile(contextDir, containerPorts);
|
|
190
192
|
writeImagePackageJson(root, contextDir);
|
|
191
193
|
const vendored = vendorQuidproquoPackages(root, contextDir);
|
|
192
|
-
|
|
193
|
-
fs.cpSync(
|
|
194
|
+
out.log(`Vendored ${vendored} quidproquo packages`);
|
|
195
|
+
fs.cpSync(getDevServerDistPath(root), path.join(contextDir, 'server'), { recursive: true });
|
|
194
196
|
for (const entry of [...webEntryRoutes, ...webEntryHosts]) {
|
|
195
197
|
copyWebEntryContent(appName, contextDir, entry, viewServices);
|
|
196
198
|
}
|
|
@@ -206,7 +208,7 @@ export const dockerGo = async (appName, plan) => {
|
|
|
206
208
|
publicFileStoragePort: mapHostPort(devServerPorts.fileStorage),
|
|
207
209
|
});
|
|
208
210
|
// ---- Build the image ----
|
|
209
|
-
|
|
211
|
+
out.log(`Building docker image${dockerSettings.arch ? ` for ${dockerSettings.arch}` : ''}${dockerSettings.registry ? `, pushing to ${dockerSettings.registry}` : ''}`);
|
|
210
212
|
await buildImage(imageName, contextDir, dockerSettings);
|
|
211
213
|
logTimeEnd('totalTime');
|
|
212
214
|
const hostUrl = (containerPort) => {
|
|
@@ -222,7 +224,7 @@ export const dockerGo = async (appName, plan) => {
|
|
|
222
224
|
const onHost = dockerSettings.registry
|
|
223
225
|
? `On the host (Unraid: Compose Manager, or any docker host), copy the compose file there and run:`
|
|
224
226
|
: `Run it here:`;
|
|
225
|
-
|
|
227
|
+
out.log(`
|
|
226
228
|
Done. The image is ${where}.
|
|
227
229
|
|
|
228
230
|
${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 { createOutput } from '../../lib/createOutput';\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 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"]}
|
|
@@ -1,17 +1,18 @@
|
|
|
1
|
+
import { CliError } from '../../lib/CliError';
|
|
2
|
+
import { createOutput } from '../../lib/createOutput';
|
|
1
3
|
import { BUILD_ONLY_FLAG, FROM_BUILD_FLAG } from '../../lib/goDockerMode';
|
|
2
4
|
import { getDockerPlatformSettings } from './getDockerPlatformSettings';
|
|
3
5
|
import { dockerGo } from './go';
|
|
6
|
+
const out = createOutput('docker');
|
|
4
7
|
const publishNotSupported = async () => {
|
|
5
|
-
|
|
6
|
-
process.exit(1);
|
|
8
|
+
throw new CliError('The docker platform has no federated code store: story code is baked into the image. Rebuild with qpq go instead.');
|
|
7
9
|
};
|
|
8
10
|
// A docker platform's deploy already is the containerised one, so `qpq go:docker`
|
|
9
11
|
// (what a scaffolded app's `npm run deploy` runs) is the same build. The image is
|
|
10
12
|
// the deploy, so there is no saved build to split across two runs.
|
|
11
13
|
const dockerGoDocker = async (appName, plan, mode) => {
|
|
12
14
|
if (mode !== 'full') {
|
|
13
|
-
|
|
14
|
-
process.exit(1);
|
|
15
|
+
throw new CliError(`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.`);
|
|
15
16
|
}
|
|
16
17
|
await dockerGo(appName, plan);
|
|
17
18
|
};
|
|
@@ -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,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAEtD,OAAO,EAAE,eAAe,EAAE,eAAe,EAAgB,MAAM,wBAAwB,CAAC;AAExF,OAAO,EAAE,yBAAyB,EAAE,MAAM,6BAA6B,CAAC;AACxE,OAAO,EAAE,QAAQ,EAAE,MAAM,MAAM,CAAC;AAEhC,MAAM,GAAG,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC;AAEnC,MAAM,mBAAmB,GAAG,KAAK,IAAmB,EAAE;IACpD,MAAM,IAAI,QAAQ,CAAC,mHAAmH,CAAC,CAAC;AAC1I,CAAC,CAAC;AAEF,kFAAkF;AAClF,kFAAkF;AAClF,mEAAmE;AACnE,MAAM,cAAc,GAAG,KAAK,EAAE,OAAe,EAAE,IAAgB,EAAE,IAAkB,EAAiB,EAAE;IACpG,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;QACpB,MAAM,IAAI,QAAQ,CAChB,uDAAuD,eAAe,QAAQ,eAAe,gDAAgD,CAC9I,CAAC;IACJ,CAAC;IAED,MAAM,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;AAChC,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,oBAAoB,GAAsB;IACrD,2FAA2F;IAC3F,oFAAoF;IACpF,iBAAiB,EAAE,CAAC,cAAc,EAAE,UAAU,EAAE,EAAE;QAChD,yBAAyB,CAAC,cAAc,EAAE,UAAU,CAAC,CAAC;IACxD,CAAC;IAED,EAAE,EAAE,QAAQ;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 { createOutput } from '../../lib/createOutput';\nimport { DeployPlan } from '../../lib/deployPrompts';\nimport { BUILD_ONLY_FLAG, FROM_BUILD_FLAG, GoDockerMode } from '../../lib/goDockerMode';\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"]}
|
|
@@ -14,10 +14,11 @@ export const parseMounts = (value) => value
|
|
|
14
14
|
if (!match) {
|
|
15
15
|
throw new Error(`Mount '${item}' must be host:container with both absolute, optionally ending :ro, e.g. /mnt/user/media:/media`);
|
|
16
16
|
}
|
|
17
|
-
const
|
|
17
|
+
const [, host = '', containerPath = '', mode] = match;
|
|
18
|
+
const container = trimTrailingSlashes(containerPath);
|
|
18
19
|
if (container === IMAGE_ROOT || container.startsWith(`${IMAGE_ROOT}/`) || container === '/') {
|
|
19
20
|
throw new Error(`Mount '${item}' would cover the image's own files: mount it somewhere other than / or ${IMAGE_ROOT}`);
|
|
20
21
|
}
|
|
21
|
-
return { host: trimTrailingSlashes(
|
|
22
|
+
return { host: trimTrailingSlashes(host), container, readOnly: mode === 'ro' };
|
|
22
23
|
});
|
|
23
24
|
//# 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;AAC/F,MAAM,CAAC,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;AAC/F,MAAM,CAAC,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","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"]}
|
|
@@ -1,6 +1,9 @@
|
|
|
1
|
+
import { CliError } from '../lib/CliError';
|
|
2
|
+
import { createOutput } from '../lib/createOutput';
|
|
1
3
|
import { awsPlatformDriver } from './aws';
|
|
2
4
|
import { dockerPlatformDriver } from './docker';
|
|
3
5
|
import { QpqDeployPlatform } from './types';
|
|
6
|
+
const out = createOutput('platform');
|
|
4
7
|
const platformDrivers = {
|
|
5
8
|
[QpqDeployPlatform.aws]: awsPlatformDriver,
|
|
6
9
|
[QpqDeployPlatform.docker]: dockerPlatformDriver,
|
|
@@ -8,8 +11,7 @@ const platformDrivers = {
|
|
|
8
11
|
export const getPlatformDriver = (platform) => {
|
|
9
12
|
const driver = platformDrivers[platform];
|
|
10
13
|
if (!driver) {
|
|
11
|
-
|
|
12
|
-
process.exit(1);
|
|
14
|
+
throw new CliError(`Unknown deploy platform '${platform}'. Supported platforms: ${Object.keys(platformDrivers).join(', ')}`);
|
|
13
15
|
}
|
|
14
16
|
return driver;
|
|
15
17
|
};
|
|
@@ -1 +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,MAAM,CAAC,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,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAC3C,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,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,GAAG,GAAG,YAAY,CAAC,UAAU,CAAC,CAAC;AAErC,MAAM,eAAe,GAAsC;IACzD,CAAC,iBAAiB,CAAC,GAAG,CAAC,EAAE,iBAAiB;IAC1C,CAAC,iBAAiB,CAAC,MAAM,CAAC,EAAE,oBAAoB;CACjD,CAAC;AAEF,MAAM,CAAC,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,QAAQ,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;AAEF,cAAc,SAAS,CAAC","sourcesContent":["import { CliError } from '../lib/CliError';\nimport { createOutput } from '../lib/createOutput';\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,MAAM,CAAN,IAAY,iBAGX;AAHD,WAAY,iBAAiB;IAC3B,gCAAW,CAAA;IACX,sCAAiB,CAAA;AACnB,CAAC,EAHW,iBAAiB,KAAjB,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,MAAM,CAAN,IAAY,iBAGX;AAHD,WAAY,iBAAiB;IAC3B,gCAAW,CAAA;IACX,sCAAiB,CAAA;AACnB,CAAC,EAHW,iBAAiB,KAAjB,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"]}
|
package/package.json
CHANGED
|
@@ -1,10 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@qpqjs/cli",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "The qpq CLI
|
|
3
|
+
"version": "0.5.0",
|
|
4
|
+
"description": "The qpq CLI: build, dev and deploy orchestration for quidproquo apps.",
|
|
5
5
|
"main": "./lib/commonjs/index.js",
|
|
6
6
|
"module": "./lib/esm/index.js",
|
|
7
7
|
"types": "./lib/commonjs/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./lib/commonjs/index.d.ts",
|
|
11
|
+
"module": "./lib/esm/index.js",
|
|
12
|
+
"default": "./lib/commonjs/index.js"
|
|
13
|
+
},
|
|
14
|
+
"./package.json": "./package.json"
|
|
15
|
+
},
|
|
8
16
|
"sideEffects": false,
|
|
9
17
|
"files": [
|
|
10
18
|
"lib/**/*",
|
|
@@ -24,11 +32,13 @@
|
|
|
24
32
|
"lint": "npx eslint .",
|
|
25
33
|
"lint:fix": "npx eslint . --fix",
|
|
26
34
|
"format": "prettier --write \"**/*.{js,jsx,ts,tsx,json,css,scss,md}\"",
|
|
27
|
-
"build:bin-perms": "node -e \"require('fs').chmodSync('lib/commonjs/bin/qpq.js', 0o755)\""
|
|
35
|
+
"build:bin-perms": "node -e \"require('fs').chmodSync('lib/commonjs/bin/qpq.js', 0o755)\"",
|
|
36
|
+
"test:watch": "vitest"
|
|
28
37
|
},
|
|
29
38
|
"repository": {
|
|
30
39
|
"type": "git",
|
|
31
|
-
"url": "git+https://github.com/qpqjs/quidproquo.git"
|
|
40
|
+
"url": "git+https://github.com/qpqjs/quidproquo.git",
|
|
41
|
+
"directory": "packages/cli"
|
|
32
42
|
},
|
|
33
43
|
"keywords": [],
|
|
34
44
|
"author": "",
|
|
@@ -45,30 +55,33 @@
|
|
|
45
55
|
"@aws-sdk/client-s3": "^3.1093.0",
|
|
46
56
|
"@aws-sdk/client-sts": "^3.1093.0",
|
|
47
57
|
"@inquirer/prompts": "^8.5.2",
|
|
58
|
+
"@qpqjs/actionprocessor-aws": "0.5.0",
|
|
59
|
+
"@qpqjs/actionprocessor-node": "0.5.0",
|
|
60
|
+
"@qpqjs/config-aws": "0.5.0",
|
|
61
|
+
"@qpqjs/core": "0.5.0",
|
|
62
|
+
"@qpqjs/deploy-aws": "0.5.0",
|
|
63
|
+
"@qpqjs/deploy-rspack": "0.5.0",
|
|
64
|
+
"@qpqjs/dev-server": "0.5.0",
|
|
65
|
+
"@qpqjs/user-script": "0.5.0",
|
|
66
|
+
"@qpqjs/webserver": "0.5.0",
|
|
48
67
|
"@rspack/dev-server": "^2.1.0",
|
|
49
|
-
"aws-cdk": "^2.
|
|
68
|
+
"aws-cdk": "^2.1146.1",
|
|
50
69
|
"madge": "^8.0.0",
|
|
51
|
-
"quidproquo": "0.3.0",
|
|
52
|
-
"@qpqjs/actionprocessor-aws": "0.3.0",
|
|
53
|
-
"@qpqjs/config-aws": "0.3.0",
|
|
54
|
-
"@qpqjs/core": "0.3.0",
|
|
55
|
-
"@qpqjs/deploy-aws": "0.3.0",
|
|
56
|
-
"@qpqjs/deploy-rspack": "0.3.0",
|
|
57
|
-
"@qpqjs/user-script": "0.3.0",
|
|
58
|
-
"@qpqjs/dev-server": "0.3.0",
|
|
59
|
-
"@qpqjs/webserver": "0.3.0",
|
|
60
70
|
"ts-node": "^10.9.1",
|
|
61
71
|
"typescript": "^5.8.2"
|
|
62
72
|
},
|
|
63
73
|
"devDependencies": {
|
|
64
74
|
"@rspack/core": "^2.1.2",
|
|
65
75
|
"@types/node": "^22.13.13",
|
|
66
|
-
"@qpqjs/tsconfig": "0.
|
|
76
|
+
"@qpqjs/tsconfig": "0.5.0"
|
|
67
77
|
},
|
|
68
78
|
"bin": {
|
|
69
79
|
"qpq": "./lib/commonjs/bin/qpq.js"
|
|
70
80
|
},
|
|
71
81
|
"peerDependencies": {
|
|
72
82
|
"@rspack/core": "^2.0.0"
|
|
83
|
+
},
|
|
84
|
+
"engines": {
|
|
85
|
+
"node": ">=24"
|
|
73
86
|
}
|
|
74
87
|
}
|
|
@@ -6,7 +6,7 @@ A quidproquo user script. It builds to one JavaScript file that a quidproquo ser
|
|
|
6
6
|
|
|
7
7
|
- The entry is `src/main.ts`. Split the code across other files and folders as you like; the build folds them in.
|
|
8
8
|
- Every export of `src/main.ts` must be a function. A generator export runs as a story: it yields quidproquo actions and its return value is what the caller gets. A plain function export returns its value.
|
|
9
|
-
- Scripts run in a sandbox. The actions available are the pure ones (`askDateNow`, `
|
|
9
|
+
- Scripts run in a sandbox. The actions available are the pure ones (`askDateNow`, `askGuidNew`, logging, random numbers) and `askNetworkRequest` for calling out over HTTP; a story that yields a file, store or other resource action fails at that point. The service that hosts scripts may offer its own module to import instead (see `defineUserScriptModule`).
|
|
10
10
|
- Import from `@qpqjs/core`. npm packages you add to `package.json` are bundled into the output. Node builtins such as `fs` are refused at build time.
|
|
11
11
|
|
|
12
12
|
## Build
|