@qpqjs/cli 0.0.0-stage → 0.2.1
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/README.md +92 -2
- package/docker/cdk-deployer/Dockerfile +13 -0
- package/docker/dev-server/Dockerfile +47 -0
- package/lib/commonjs/bin/qpq.d.ts +2 -0
- package/lib/commonjs/bin/qpq.js +6 -0
- package/lib/commonjs/bin/qpq.js.map +1 -0
- package/lib/commonjs/bin/qpqCdkApp.d.ts +1 -0
- package/lib/commonjs/bin/qpqCdkApp.js +8 -0
- package/lib/commonjs/bin/qpqCdkApp.js.map +1 -0
- package/lib/commonjs/cli/commandMenu.d.ts +2 -0
- package/lib/commonjs/cli/commandMenu.js +81 -0
- package/lib/commonjs/cli/commandMenu.js.map +1 -0
- package/lib/commonjs/cli/commandRegistry.d.ts +10 -0
- package/lib/commonjs/cli/commandRegistry.js +177 -0
- package/lib/commonjs/cli/commandRegistry.js.map +1 -0
- package/lib/commonjs/cli/index.d.ts +1 -0
- package/lib/commonjs/cli/index.js +18 -0
- package/lib/commonjs/cli/index.js.map +1 -0
- package/lib/commonjs/cli/runCli.d.ts +1 -0
- package/lib/commonjs/cli/runCli.js +86 -0
- package/lib/commonjs/cli/runCli.js.map +1 -0
- package/lib/commonjs/commands/checkCircular.d.ts +1 -0
- package/lib/commonjs/commands/checkCircular.js +70 -0
- package/lib/commonjs/commands/checkCircular.js.map +1 -0
- package/lib/commonjs/commands/clearResources.d.ts +1 -0
- package/lib/commonjs/commands/clearResources.js +36 -0
- package/lib/commonjs/commands/clearResources.js.map +1 -0
- package/lib/commonjs/commands/go.d.ts +1 -0
- package/lib/commonjs/commands/go.js +30 -0
- package/lib/commonjs/commands/go.js.map +1 -0
- package/lib/commonjs/commands/goDev.d.ts +1 -0
- package/lib/commonjs/commands/goDev.js +46 -0
- package/lib/commonjs/commands/goDev.js.map +1 -0
- package/lib/commonjs/commands/goDevApi.d.ts +1 -0
- package/lib/commonjs/commands/goDevApi.js +158 -0
- package/lib/commonjs/commands/goDevApi.js.map +1 -0
- package/lib/commonjs/commands/goDevWeb.d.ts +4 -0
- package/lib/commonjs/commands/goDevWeb.js +144 -0
- package/lib/commonjs/commands/goDevWeb.js.map +1 -0
- package/lib/commonjs/commands/goDocker.d.ts +1 -0
- package/lib/commonjs/commands/goDocker.js +43 -0
- package/lib/commonjs/commands/goDocker.js.map +1 -0
- package/lib/commonjs/commands/hooks.d.ts +1 -0
- package/lib/commonjs/commands/hooks.js +39 -0
- package/lib/commonjs/commands/hooks.js.map +1 -0
- package/lib/commonjs/commands/migrate.d.ts +1 -0
- package/lib/commonjs/commands/migrate.js +70 -0
- package/lib/commonjs/commands/migrate.js.map +1 -0
- package/lib/commonjs/commands/prep.d.ts +1 -0
- package/lib/commonjs/commands/prep.js +28 -0
- package/lib/commonjs/commands/prep.js.map +1 -0
- package/lib/commonjs/commands/publish.d.ts +4 -0
- package/lib/commonjs/commands/publish.js +54 -0
- package/lib/commonjs/commands/publish.js.map +1 -0
- package/lib/commonjs/commands/scriptBuild.d.ts +1 -0
- package/lib/commonjs/commands/scriptBuild.js +46 -0
- package/lib/commonjs/commands/scriptBuild.js.map +1 -0
- package/lib/commonjs/commands/scriptBuilderLayer.d.ts +1 -0
- package/lib/commonjs/commands/scriptBuilderLayer.js +48 -0
- package/lib/commonjs/commands/scriptBuilderLayer.js.map +1 -0
- package/lib/commonjs/commands/scriptNew.d.ts +1 -0
- package/lib/commonjs/commands/scriptNew.js +35 -0
- package/lib/commonjs/commands/scriptNew.js.map +1 -0
- package/lib/commonjs/commands/setup.d.ts +1 -0
- package/lib/commonjs/commands/setup.js +102 -0
- package/lib/commonjs/commands/setup.js.map +1 -0
- package/lib/commonjs/commands/synth.d.ts +1 -0
- package/lib/commonjs/commands/synth.js +89 -0
- package/lib/commonjs/commands/synth.js.map +1 -0
- package/lib/commonjs/commands/teardown.d.ts +1 -0
- package/lib/commonjs/commands/teardown.js +33 -0
- package/lib/commonjs/commands/teardown.js.map +1 -0
- package/lib/commonjs/index.d.ts +1 -0
- package/lib/commonjs/index.js +18 -0
- package/lib/commonjs/index.js.map +1 -0
- package/lib/commonjs/lib/args.d.ts +3 -0
- package/lib/commonjs/lib/args.js +31 -0
- package/lib/commonjs/lib/args.js.map +1 -0
- package/lib/commonjs/lib/circularImports.d.ts +3 -0
- package/lib/commonjs/lib/circularImports.js +79 -0
- package/lib/commonjs/lib/circularImports.js.map +1 -0
- package/lib/commonjs/lib/clearResourcesPlan.d.ts +15 -0
- package/lib/commonjs/lib/clearResourcesPlan.js +79 -0
- package/lib/commonjs/lib/clearResourcesPlan.js.map +1 -0
- package/lib/commonjs/lib/deployPrompts.d.ts +26 -0
- package/lib/commonjs/lib/deployPrompts.js +118 -0
- package/lib/commonjs/lib/deployPrompts.js.map +1 -0
- package/lib/commonjs/lib/devServerEntry.d.ts +22 -0
- package/lib/commonjs/lib/devServerEntry.js +135 -0
- package/lib/commonjs/lib/devServerEntry.js.map +1 -0
- package/lib/commonjs/lib/devServerPorts.d.ts +13 -0
- package/lib/commonjs/lib/devServerPorts.js +36 -0
- package/lib/commonjs/lib/devServerPorts.js.map +1 -0
- package/lib/commonjs/lib/discovery.d.ts +10 -0
- package/lib/commonjs/lib/discovery.js +56 -0
- package/lib/commonjs/lib/discovery.js.map +1 -0
- package/lib/commonjs/lib/getDefaultHookJobs.d.ts +2 -0
- package/lib/commonjs/lib/getDefaultHookJobs.js +11 -0
- package/lib/commonjs/lib/getDefaultHookJobs.js.map +1 -0
- package/lib/commonjs/lib/getDeployTargetLabel.d.ts +2 -0
- package/lib/commonjs/lib/getDeployTargetLabel.js +12 -0
- package/lib/commonjs/lib/getDeployTargetLabel.js.map +1 -0
- package/lib/commonjs/lib/goDockerMode.d.ts +6 -0
- package/lib/commonjs/lib/goDockerMode.js +23 -0
- package/lib/commonjs/lib/goDockerMode.js.map +1 -0
- package/lib/commonjs/lib/hooks.d.ts +9 -0
- package/lib/commonjs/lib/hooks.js +178 -0
- package/lib/commonjs/lib/hooks.js.map +1 -0
- package/lib/commonjs/lib/keepOtherDevServersFlag.d.ts +1 -0
- package/lib/commonjs/lib/keepOtherDevServersFlag.js +11 -0
- package/lib/commonjs/lib/keepOtherDevServersFlag.js.map +1 -0
- package/lib/commonjs/lib/killChildWithEscalation.d.ts +10 -0
- package/lib/commonjs/lib/killChildWithEscalation.js +33 -0
- package/lib/commonjs/lib/killChildWithEscalation.js.map +1 -0
- package/lib/commonjs/lib/killStaleListeners.d.ts +17 -0
- package/lib/commonjs/lib/killStaleListeners.js +220 -0
- package/lib/commonjs/lib/killStaleListeners.js.map +1 -0
- package/lib/commonjs/lib/packageRoot.d.ts +1 -0
- package/lib/commonjs/lib/packageRoot.js +21 -0
- package/lib/commonjs/lib/packageRoot.js.map +1 -0
- package/lib/commonjs/lib/prompts.d.ts +15 -0
- package/lib/commonjs/lib/prompts.js +78 -0
- package/lib/commonjs/lib/prompts.js.map +1 -0
- package/lib/commonjs/lib/qpqConfigs.d.ts +4 -0
- package/lib/commonjs/lib/qpqConfigs.js +27 -0
- package/lib/commonjs/lib/qpqConfigs.js.map +1 -0
- package/lib/commonjs/lib/resolveAppSelection.d.ts +6 -0
- package/lib/commonjs/lib/resolveAppSelection.js +58 -0
- package/lib/commonjs/lib/resolveAppSelection.js.map +1 -0
- package/lib/commonjs/lib/resolveDeployment.d.ts +14 -0
- package/lib/commonjs/lib/resolveDeployment.js +58 -0
- package/lib/commonjs/lib/resolveDeployment.js.map +1 -0
- package/lib/commonjs/lib/runCommand.d.ts +14 -0
- package/lib/commonjs/lib/runCommand.js +103 -0
- package/lib/commonjs/lib/runCommand.js.map +1 -0
- package/lib/commonjs/lib/runTasks.d.ts +15 -0
- package/lib/commonjs/lib/runTasks.js +123 -0
- package/lib/commonjs/lib/runTasks.js.map +1 -0
- package/lib/commonjs/lib/setupStep.d.ts +16 -0
- package/lib/commonjs/lib/setupStep.js +3 -0
- package/lib/commonjs/lib/setupStep.js.map +1 -0
- package/lib/commonjs/lib/timing.d.ts +2 -0
- package/lib/commonjs/lib/timing.js +11 -0
- package/lib/commonjs/lib/timing.js.map +1 -0
- package/lib/commonjs/lib/typeWatcher.d.ts +2 -0
- package/lib/commonjs/lib/typeWatcher.js +59 -0
- package/lib/commonjs/lib/typeWatcher.js.map +1 -0
- package/lib/commonjs/lib/userScriptBuilderLayer.d.ts +23 -0
- package/lib/commonjs/lib/userScriptBuilderLayer.js +74 -0
- package/lib/commonjs/lib/userScriptBuilderLayer.js.map +1 -0
- package/lib/commonjs/lib/userScriptTemplate.d.ts +6 -0
- package/lib/commonjs/lib/userScriptTemplate.js +47 -0
- package/lib/commonjs/lib/userScriptTemplate.js.map +1 -0
- package/lib/commonjs/lib/views.d.ts +2 -0
- package/lib/commonjs/lib/views.js +31 -0
- package/lib/commonjs/lib/views.js.map +1 -0
- package/lib/commonjs/lib/webAddressingEnv.d.ts +7 -0
- package/lib/commonjs/lib/webAddressingEnv.js +16 -0
- package/lib/commonjs/lib/webAddressingEnv.js.map +1 -0
- package/lib/commonjs/platforms/aws/awsCredentials.d.ts +1 -0
- package/lib/commonjs/platforms/aws/awsCredentials.js +28 -0
- package/lib/commonjs/platforms/aws/awsCredentials.js.map +1 -0
- package/lib/commonjs/platforms/aws/cdkApp.d.ts +3 -0
- package/lib/commonjs/platforms/aws/cdkApp.js +31 -0
- package/lib/commonjs/platforms/aws/cdkApp.js.map +1 -0
- package/lib/commonjs/platforms/aws/clearResources.d.ts +2 -0
- package/lib/commonjs/platforms/aws/clearResources.js +167 -0
- package/lib/commonjs/platforms/aws/clearResources.js.map +1 -0
- package/lib/commonjs/platforms/aws/go.d.ts +2 -0
- package/lib/commonjs/platforms/aws/go.js +131 -0
- package/lib/commonjs/platforms/aws/go.js.map +1 -0
- package/lib/commonjs/platforms/aws/goDocker.d.ts +3 -0
- package/lib/commonjs/platforms/aws/goDocker.js +457 -0
- package/lib/commonjs/platforms/aws/goDocker.js.map +1 -0
- package/lib/commonjs/platforms/aws/goDockerManifest.d.ts +44 -0
- package/lib/commonjs/platforms/aws/goDockerManifest.js +38 -0
- package/lib/commonjs/platforms/aws/goDockerManifest.js.map +1 -0
- package/lib/commonjs/platforms/aws/index.d.ts +2 -0
- package/lib/commonjs/platforms/aws/index.js +23 -0
- package/lib/commonjs/platforms/aws/index.js.map +1 -0
- package/lib/commonjs/platforms/aws/prepareDeployment.d.ts +3 -0
- package/lib/commonjs/platforms/aws/prepareDeployment.js +10 -0
- package/lib/commonjs/platforms/aws/prepareDeployment.js.map +1 -0
- package/lib/commonjs/platforms/aws/publish.d.ts +4 -0
- package/lib/commonjs/platforms/aws/publish.js +66 -0
- package/lib/commonjs/platforms/aws/publish.js.map +1 -0
- package/lib/commonjs/platforms/aws/remote.d.ts +11 -0
- package/lib/commonjs/platforms/aws/remote.js +105 -0
- package/lib/commonjs/platforms/aws/remote.js.map +1 -0
- package/lib/commonjs/platforms/aws/setup/awsSetupContext.d.ts +12 -0
- package/lib/commonjs/platforms/aws/setup/awsSetupContext.js +20 -0
- package/lib/commonjs/platforms/aws/setup/awsSetupContext.js.map +1 -0
- package/lib/commonjs/platforms/aws/setup/awsSetupSteps.d.ts +8 -0
- package/lib/commonjs/platforms/aws/setup/awsSetupSteps.js +44 -0
- package/lib/commonjs/platforms/aws/setup/awsSetupSteps.js.map +1 -0
- package/lib/commonjs/platforms/aws/setup/buildBucketNamesStep.d.ts +4 -0
- package/lib/commonjs/platforms/aws/setup/buildBucketNamesStep.js +77 -0
- package/lib/commonjs/platforms/aws/setup/buildBucketNamesStep.js.map +1 -0
- package/lib/commonjs/platforms/aws/setup/buildCdkBootstrapSteps.d.ts +5 -0
- package/lib/commonjs/platforms/aws/setup/buildCdkBootstrapSteps.js +38 -0
- package/lib/commonjs/platforms/aws/setup/buildCdkBootstrapSteps.js.map +1 -0
- package/lib/commonjs/platforms/aws/setup/buildGithubDeployRoleStep.d.ts +4 -0
- package/lib/commonjs/platforms/aws/setup/buildGithubDeployRoleStep.js +55 -0
- package/lib/commonjs/platforms/aws/setup/buildGithubDeployRoleStep.js.map +1 -0
- package/lib/commonjs/platforms/aws/setup/buildGithubOidcProviderStep.d.ts +4 -0
- package/lib/commonjs/platforms/aws/setup/buildGithubOidcProviderStep.js +54 -0
- package/lib/commonjs/platforms/aws/setup/buildGithubOidcProviderStep.js.map +1 -0
- package/lib/commonjs/platforms/aws/setup/buildHostedZonesStep.d.ts +4 -0
- package/lib/commonjs/platforms/aws/setup/buildHostedZonesStep.js +63 -0
- package/lib/commonjs/platforms/aws/setup/buildHostedZonesStep.js.map +1 -0
- package/lib/commonjs/platforms/aws/setup/buildIamCapabilityStep.d.ts +4 -0
- package/lib/commonjs/platforms/aws/setup/buildIamCapabilityStep.js +48 -0
- package/lib/commonjs/platforms/aws/setup/buildIamCapabilityStep.js.map +1 -0
- package/lib/commonjs/platforms/aws/setup/buildIdentityStep.d.ts +4 -0
- package/lib/commonjs/platforms/aws/setup/buildIdentityStep.js +39 -0
- package/lib/commonjs/platforms/aws/setup/buildIdentityStep.js.map +1 -0
- package/lib/commonjs/platforms/aws/setup/buildStackSteps.d.ts +5 -0
- package/lib/commonjs/platforms/aws/setup/buildStackSteps.js +32 -0
- package/lib/commonjs/platforms/aws/setup/buildStackSteps.js.map +1 -0
- package/lib/commonjs/platforms/aws/setup/describeStackStatus.d.ts +4 -0
- package/lib/commonjs/platforms/aws/setup/describeStackStatus.js +32 -0
- package/lib/commonjs/platforms/aws/setup/describeStackStatus.js.map +1 -0
- package/lib/commonjs/platforms/aws/setup/index.d.ts +1 -0
- package/lib/commonjs/platforms/aws/setup/index.js +18 -0
- package/lib/commonjs/platforms/aws/setup/index.js.map +1 -0
- package/lib/commonjs/platforms/aws/stacks.d.ts +7 -0
- package/lib/commonjs/platforms/aws/stacks.js +94 -0
- package/lib/commonjs/platforms/aws/stacks.js.map +1 -0
- package/lib/commonjs/platforms/aws/teardown.d.ts +2 -0
- package/lib/commonjs/platforms/aws/teardown.js +59 -0
- package/lib/commonjs/platforms/aws/teardown.js.map +1 -0
- package/lib/commonjs/platforms/aws/viewsSync.d.ts +3 -0
- package/lib/commonjs/platforms/aws/viewsSync.js +77 -0
- package/lib/commonjs/platforms/aws/viewsSync.js.map +1 -0
- package/lib/commonjs/platforms/docker/QpqDockerPlatformSettings.d.ts +10 -0
- package/lib/commonjs/platforms/docker/QpqDockerPlatformSettings.js +3 -0
- package/lib/commonjs/platforms/docker/QpqDockerPlatformSettings.js.map +1 -0
- package/lib/commonjs/platforms/docker/getContainerPorts.d.ts +4 -0
- package/lib/commonjs/platforms/docker/getContainerPorts.js +12 -0
- package/lib/commonjs/platforms/docker/getContainerPorts.js.map +1 -0
- package/lib/commonjs/platforms/docker/getDefaultPortMappings.d.ts +3 -0
- package/lib/commonjs/platforms/docker/getDefaultPortMappings.js +10 -0
- package/lib/commonjs/platforms/docker/getDefaultPortMappings.js.map +1 -0
- package/lib/commonjs/platforms/docker/getDockerPlatformSettings.d.ts +14 -0
- package/lib/commonjs/platforms/docker/getDockerPlatformSettings.js +39 -0
- package/lib/commonjs/platforms/docker/getDockerPlatformSettings.js.map +1 -0
- package/lib/commonjs/platforms/docker/getImageName.d.ts +6 -0
- package/lib/commonjs/platforms/docker/getImageName.js +10 -0
- package/lib/commonjs/platforms/docker/getImageName.js.map +1 -0
- package/lib/commonjs/platforms/docker/go.d.ts +2 -0
- package/lib/commonjs/platforms/docker/go.js +261 -0
- package/lib/commonjs/platforms/docker/go.js.map +1 -0
- package/lib/commonjs/platforms/docker/index.d.ts +2 -0
- package/lib/commonjs/platforms/docker/index.js +43 -0
- package/lib/commonjs/platforms/docker/index.js.map +1 -0
- package/lib/commonjs/platforms/docker/parseMounts.d.ts +7 -0
- package/lib/commonjs/platforms/docker/parseMounts.js +27 -0
- package/lib/commonjs/platforms/docker/parseMounts.js.map +1 -0
- package/lib/commonjs/platforms/docker/parsePortMappings.d.ts +8 -0
- package/lib/commonjs/platforms/docker/parsePortMappings.js +26 -0
- package/lib/commonjs/platforms/docker/parsePortMappings.js.map +1 -0
- package/lib/commonjs/platforms/docker/resolvePortMappings.d.ts +8 -0
- package/lib/commonjs/platforms/docker/resolvePortMappings.js +23 -0
- package/lib/commonjs/platforms/docker/resolvePortMappings.js.map +1 -0
- package/lib/commonjs/platforms/docker/writeComposeFile.d.ts +20 -0
- package/lib/commonjs/platforms/docker/writeComposeFile.js +44 -0
- package/lib/commonjs/platforms/docker/writeComposeFile.js.map +1 -0
- package/lib/commonjs/platforms/index.d.ts +3 -0
- package/lib/commonjs/platforms/index.js +35 -0
- package/lib/commonjs/platforms/index.js.map +1 -0
- package/lib/commonjs/platforms/types.d.ts +21 -0
- package/lib/commonjs/platforms/types.js +9 -0
- package/lib/commonjs/platforms/types.js.map +1 -0
- package/lib/esm/bin/qpq.d.ts +2 -0
- package/lib/esm/bin/qpq.js +4 -0
- package/lib/esm/bin/qpq.js.map +1 -0
- package/lib/esm/bin/qpqCdkApp.d.ts +1 -0
- package/lib/esm/bin/qpqCdkApp.js +6 -0
- package/lib/esm/bin/qpqCdkApp.js.map +1 -0
- package/lib/esm/cli/commandMenu.d.ts +2 -0
- package/lib/esm/cli/commandMenu.js +67 -0
- package/lib/esm/cli/commandMenu.js.map +1 -0
- package/lib/esm/cli/commandRegistry.d.ts +10 -0
- package/lib/esm/cli/commandRegistry.js +161 -0
- package/lib/esm/cli/commandRegistry.js.map +1 -0
- package/lib/esm/cli/index.d.ts +1 -0
- package/lib/esm/cli/index.js +2 -0
- package/lib/esm/cli/index.js.map +1 -0
- package/lib/esm/cli/runCli.d.ts +1 -0
- package/lib/esm/cli/runCli.js +73 -0
- package/lib/esm/cli/runCli.js.map +1 -0
- package/lib/esm/commands/checkCircular.d.ts +1 -0
- package/lib/esm/commands/checkCircular.js +55 -0
- package/lib/esm/commands/checkCircular.js.map +1 -0
- package/lib/esm/commands/clearResources.d.ts +1 -0
- package/lib/esm/commands/clearResources.js +23 -0
- package/lib/esm/commands/clearResources.js.map +1 -0
- package/lib/esm/commands/go.d.ts +1 -0
- package/lib/esm/commands/go.js +16 -0
- package/lib/esm/commands/go.js.map +1 -0
- package/lib/esm/commands/goDev.d.ts +1 -0
- package/lib/esm/commands/goDev.js +33 -0
- package/lib/esm/commands/goDev.js.map +1 -0
- package/lib/esm/commands/goDevApi.d.ts +1 -0
- package/lib/esm/commands/goDevApi.js +142 -0
- package/lib/esm/commands/goDevApi.js.map +1 -0
- package/lib/esm/commands/goDevWeb.d.ts +4 -0
- package/lib/esm/commands/goDevWeb.js +129 -0
- package/lib/esm/commands/goDevWeb.js.map +1 -0
- package/lib/esm/commands/goDocker.d.ts +1 -0
- package/lib/esm/commands/goDocker.js +29 -0
- package/lib/esm/commands/goDocker.js.map +1 -0
- package/lib/esm/commands/hooks.d.ts +1 -0
- package/lib/esm/commands/hooks.js +26 -0
- package/lib/esm/commands/hooks.js.map +1 -0
- package/lib/esm/commands/migrate.d.ts +1 -0
- package/lib/esm/commands/migrate.js +57 -0
- package/lib/esm/commands/migrate.js.map +1 -0
- package/lib/esm/commands/prep.d.ts +1 -0
- package/lib/esm/commands/prep.js +15 -0
- package/lib/esm/commands/prep.js.map +1 -0
- package/lib/esm/commands/publish.d.ts +4 -0
- package/lib/esm/commands/publish.js +38 -0
- package/lib/esm/commands/publish.js.map +1 -0
- package/lib/esm/commands/scriptBuild.d.ts +1 -0
- package/lib/esm/commands/scriptBuild.js +29 -0
- package/lib/esm/commands/scriptBuild.js.map +1 -0
- package/lib/esm/commands/scriptBuilderLayer.d.ts +1 -0
- package/lib/esm/commands/scriptBuilderLayer.js +34 -0
- package/lib/esm/commands/scriptBuilderLayer.js.map +1 -0
- package/lib/esm/commands/scriptNew.d.ts +1 -0
- package/lib/esm/commands/scriptNew.js +19 -0
- package/lib/esm/commands/scriptNew.js.map +1 -0
- package/lib/esm/commands/setup.d.ts +1 -0
- package/lib/esm/commands/setup.js +88 -0
- package/lib/esm/commands/setup.js.map +1 -0
- package/lib/esm/commands/synth.d.ts +1 -0
- package/lib/esm/commands/synth.js +73 -0
- package/lib/esm/commands/synth.js.map +1 -0
- package/lib/esm/commands/teardown.d.ts +1 -0
- package/lib/esm/commands/teardown.js +20 -0
- package/lib/esm/commands/teardown.js.map +1 -0
- package/lib/esm/index.d.ts +1 -0
- package/lib/esm/index.js +2 -0
- package/lib/esm/index.js.map +1 -0
- package/lib/esm/lib/args.d.ts +3 -0
- package/lib/esm/lib/args.js +25 -0
- package/lib/esm/lib/args.js.map +1 -0
- package/lib/esm/lib/circularImports.d.ts +3 -0
- package/lib/esm/lib/circularImports.js +61 -0
- package/lib/esm/lib/circularImports.js.map +1 -0
- package/lib/esm/lib/clearResourcesPlan.d.ts +15 -0
- package/lib/esm/lib/clearResourcesPlan.js +65 -0
- package/lib/esm/lib/clearResourcesPlan.js.map +1 -0
- package/lib/esm/lib/deployPrompts.d.ts +26 -0
- package/lib/esm/lib/deployPrompts.js +103 -0
- package/lib/esm/lib/deployPrompts.js.map +1 -0
- package/lib/esm/lib/devServerEntry.d.ts +22 -0
- package/lib/esm/lib/devServerEntry.js +127 -0
- package/lib/esm/lib/devServerEntry.js.map +1 -0
- package/lib/esm/lib/devServerPorts.d.ts +13 -0
- package/lib/esm/lib/devServerPorts.js +27 -0
- package/lib/esm/lib/devServerPorts.js.map +1 -0
- package/lib/esm/lib/discovery.d.ts +10 -0
- package/lib/esm/lib/discovery.js +40 -0
- package/lib/esm/lib/discovery.js.map +1 -0
- package/lib/esm/lib/getDefaultHookJobs.d.ts +2 -0
- package/lib/esm/lib/getDefaultHookJobs.js +4 -0
- package/lib/esm/lib/getDefaultHookJobs.js.map +1 -0
- package/lib/esm/lib/getDeployTargetLabel.d.ts +2 -0
- package/lib/esm/lib/getDeployTargetLabel.js +8 -0
- package/lib/esm/lib/getDeployTargetLabel.js.map +1 -0
- package/lib/esm/lib/goDockerMode.d.ts +6 -0
- package/lib/esm/lib/goDockerMode.js +19 -0
- package/lib/esm/lib/goDockerMode.js.map +1 -0
- package/lib/esm/lib/hooks.d.ts +9 -0
- package/lib/esm/lib/hooks.js +154 -0
- package/lib/esm/lib/hooks.js.map +1 -0
- package/lib/esm/lib/keepOtherDevServersFlag.d.ts +1 -0
- package/lib/esm/lib/keepOtherDevServersFlag.js +8 -0
- package/lib/esm/lib/keepOtherDevServersFlag.js.map +1 -0
- package/lib/esm/lib/killChildWithEscalation.d.ts +10 -0
- package/lib/esm/lib/killChildWithEscalation.js +29 -0
- package/lib/esm/lib/killChildWithEscalation.js.map +1 -0
- package/lib/esm/lib/killStaleListeners.d.ts +17 -0
- package/lib/esm/lib/killStaleListeners.js +210 -0
- package/lib/esm/lib/killStaleListeners.js.map +1 -0
- package/lib/esm/lib/packageRoot.d.ts +1 -0
- package/lib/esm/lib/packageRoot.js +14 -0
- package/lib/esm/lib/packageRoot.js.map +1 -0
- package/lib/esm/lib/prompts.d.ts +15 -0
- package/lib/esm/lib/prompts.js +28 -0
- package/lib/esm/lib/prompts.js.map +1 -0
- package/lib/esm/lib/qpqConfigs.d.ts +4 -0
- package/lib/esm/lib/qpqConfigs.js +21 -0
- package/lib/esm/lib/qpqConfigs.js.map +1 -0
- package/lib/esm/lib/resolveAppSelection.d.ts +6 -0
- package/lib/esm/lib/resolveAppSelection.js +45 -0
- package/lib/esm/lib/resolveAppSelection.js.map +1 -0
- package/lib/esm/lib/resolveDeployment.d.ts +14 -0
- package/lib/esm/lib/resolveDeployment.js +45 -0
- package/lib/esm/lib/resolveDeployment.js.map +1 -0
- package/lib/esm/lib/runCommand.d.ts +14 -0
- package/lib/esm/lib/runCommand.js +92 -0
- package/lib/esm/lib/runCommand.js.map +1 -0
- package/lib/esm/lib/runTasks.d.ts +15 -0
- package/lib/esm/lib/runTasks.js +108 -0
- package/lib/esm/lib/runTasks.js.map +1 -0
- package/lib/esm/lib/setupStep.d.ts +16 -0
- package/lib/esm/lib/setupStep.js +2 -0
- package/lib/esm/lib/setupStep.js.map +1 -0
- package/lib/esm/lib/timing.d.ts +2 -0
- package/lib/esm/lib/timing.js +6 -0
- package/lib/esm/lib/timing.js.map +1 -0
- package/lib/esm/lib/typeWatcher.d.ts +2 -0
- package/lib/esm/lib/typeWatcher.js +51 -0
- package/lib/esm/lib/typeWatcher.js.map +1 -0
- package/lib/esm/lib/userScriptBuilderLayer.d.ts +23 -0
- package/lib/esm/lib/userScriptBuilderLayer.js +65 -0
- package/lib/esm/lib/userScriptBuilderLayer.js.map +1 -0
- package/lib/esm/lib/userScriptTemplate.d.ts +6 -0
- package/lib/esm/lib/userScriptTemplate.js +39 -0
- package/lib/esm/lib/userScriptTemplate.js.map +1 -0
- package/lib/esm/lib/views.d.ts +2 -0
- package/lib/esm/lib/views.js +14 -0
- package/lib/esm/lib/views.js.map +1 -0
- package/lib/esm/lib/webAddressingEnv.d.ts +7 -0
- package/lib/esm/lib/webAddressingEnv.js +11 -0
- package/lib/esm/lib/webAddressingEnv.js.map +1 -0
- package/lib/esm/platforms/aws/awsCredentials.d.ts +1 -0
- package/lib/esm/platforms/aws/awsCredentials.js +15 -0
- package/lib/esm/platforms/aws/awsCredentials.js.map +1 -0
- package/lib/esm/platforms/aws/cdkApp.d.ts +3 -0
- package/lib/esm/platforms/aws/cdkApp.js +22 -0
- package/lib/esm/platforms/aws/cdkApp.js.map +1 -0
- package/lib/esm/platforms/aws/clearResources.d.ts +2 -0
- package/lib/esm/platforms/aws/clearResources.js +151 -0
- package/lib/esm/platforms/aws/clearResources.js.map +1 -0
- package/lib/esm/platforms/aws/go.d.ts +2 -0
- package/lib/esm/platforms/aws/go.js +115 -0
- package/lib/esm/platforms/aws/go.js.map +1 -0
- package/lib/esm/platforms/aws/goDocker.d.ts +3 -0
- package/lib/esm/platforms/aws/goDocker.js +441 -0
- package/lib/esm/platforms/aws/goDocker.js.map +1 -0
- package/lib/esm/platforms/aws/goDockerManifest.d.ts +44 -0
- package/lib/esm/platforms/aws/goDockerManifest.js +26 -0
- package/lib/esm/platforms/aws/goDockerManifest.js.map +1 -0
- package/lib/esm/platforms/aws/index.d.ts +2 -0
- package/lib/esm/platforms/aws/index.js +20 -0
- package/lib/esm/platforms/aws/index.js.map +1 -0
- package/lib/esm/platforms/aws/prepareDeployment.d.ts +3 -0
- package/lib/esm/platforms/aws/prepareDeployment.js +6 -0
- package/lib/esm/platforms/aws/prepareDeployment.js.map +1 -0
- package/lib/esm/platforms/aws/publish.d.ts +4 -0
- package/lib/esm/platforms/aws/publish.js +50 -0
- package/lib/esm/platforms/aws/publish.js.map +1 -0
- package/lib/esm/platforms/aws/remote.d.ts +11 -0
- package/lib/esm/platforms/aws/remote.js +89 -0
- package/lib/esm/platforms/aws/remote.js.map +1 -0
- package/lib/esm/platforms/aws/setup/awsSetupContext.d.ts +12 -0
- package/lib/esm/platforms/aws/setup/awsSetupContext.js +16 -0
- package/lib/esm/platforms/aws/setup/awsSetupContext.js.map +1 -0
- package/lib/esm/platforms/aws/setup/awsSetupSteps.d.ts +8 -0
- package/lib/esm/platforms/aws/setup/awsSetupSteps.js +31 -0
- package/lib/esm/platforms/aws/setup/awsSetupSteps.js.map +1 -0
- package/lib/esm/platforms/aws/setup/buildBucketNamesStep.d.ts +4 -0
- package/lib/esm/platforms/aws/setup/buildBucketNamesStep.js +62 -0
- package/lib/esm/platforms/aws/setup/buildBucketNamesStep.js.map +1 -0
- package/lib/esm/platforms/aws/setup/buildCdkBootstrapSteps.d.ts +5 -0
- package/lib/esm/platforms/aws/setup/buildCdkBootstrapSteps.js +24 -0
- package/lib/esm/platforms/aws/setup/buildCdkBootstrapSteps.js.map +1 -0
- package/lib/esm/platforms/aws/setup/buildGithubDeployRoleStep.d.ts +4 -0
- package/lib/esm/platforms/aws/setup/buildGithubDeployRoleStep.js +40 -0
- package/lib/esm/platforms/aws/setup/buildGithubDeployRoleStep.js.map +1 -0
- package/lib/esm/platforms/aws/setup/buildGithubOidcProviderStep.d.ts +4 -0
- package/lib/esm/platforms/aws/setup/buildGithubOidcProviderStep.js +40 -0
- package/lib/esm/platforms/aws/setup/buildGithubOidcProviderStep.js.map +1 -0
- package/lib/esm/platforms/aws/setup/buildHostedZonesStep.d.ts +4 -0
- package/lib/esm/platforms/aws/setup/buildHostedZonesStep.js +49 -0
- package/lib/esm/platforms/aws/setup/buildHostedZonesStep.js.map +1 -0
- package/lib/esm/platforms/aws/setup/buildIamCapabilityStep.d.ts +4 -0
- package/lib/esm/platforms/aws/setup/buildIamCapabilityStep.js +34 -0
- package/lib/esm/platforms/aws/setup/buildIamCapabilityStep.js.map +1 -0
- package/lib/esm/platforms/aws/setup/buildIdentityStep.d.ts +4 -0
- package/lib/esm/platforms/aws/setup/buildIdentityStep.js +26 -0
- package/lib/esm/platforms/aws/setup/buildIdentityStep.js.map +1 -0
- package/lib/esm/platforms/aws/setup/buildStackSteps.d.ts +5 -0
- package/lib/esm/platforms/aws/setup/buildStackSteps.js +17 -0
- package/lib/esm/platforms/aws/setup/buildStackSteps.js.map +1 -0
- package/lib/esm/platforms/aws/setup/describeStackStatus.d.ts +4 -0
- package/lib/esm/platforms/aws/setup/describeStackStatus.js +17 -0
- package/lib/esm/platforms/aws/setup/describeStackStatus.js.map +1 -0
- package/lib/esm/platforms/aws/setup/index.d.ts +1 -0
- package/lib/esm/platforms/aws/setup/index.js +2 -0
- package/lib/esm/platforms/aws/setup/index.js.map +1 -0
- package/lib/esm/platforms/aws/stacks.d.ts +7 -0
- package/lib/esm/platforms/aws/stacks.js +72 -0
- package/lib/esm/platforms/aws/stacks.js.map +1 -0
- package/lib/esm/platforms/aws/teardown.d.ts +2 -0
- package/lib/esm/platforms/aws/teardown.js +46 -0
- package/lib/esm/platforms/aws/teardown.js.map +1 -0
- package/lib/esm/platforms/aws/viewsSync.d.ts +3 -0
- package/lib/esm/platforms/aws/viewsSync.js +60 -0
- package/lib/esm/platforms/aws/viewsSync.js.map +1 -0
- package/lib/esm/platforms/docker/QpqDockerPlatformSettings.d.ts +10 -0
- package/lib/esm/platforms/docker/QpqDockerPlatformSettings.js +2 -0
- package/lib/esm/platforms/docker/QpqDockerPlatformSettings.js.map +1 -0
- package/lib/esm/platforms/docker/getContainerPorts.d.ts +4 -0
- package/lib/esm/platforms/docker/getContainerPorts.js +8 -0
- package/lib/esm/platforms/docker/getContainerPorts.js.map +1 -0
- package/lib/esm/platforms/docker/getDefaultPortMappings.d.ts +3 -0
- package/lib/esm/platforms/docker/getDefaultPortMappings.js +6 -0
- package/lib/esm/platforms/docker/getDefaultPortMappings.js.map +1 -0
- package/lib/esm/platforms/docker/getDockerPlatformSettings.d.ts +14 -0
- package/lib/esm/platforms/docker/getDockerPlatformSettings.js +34 -0
- package/lib/esm/platforms/docker/getDockerPlatformSettings.js.map +1 -0
- package/lib/esm/platforms/docker/getImageName.d.ts +6 -0
- package/lib/esm/platforms/docker/getImageName.js +6 -0
- package/lib/esm/platforms/docker/getImageName.js.map +1 -0
- package/lib/esm/platforms/docker/go.d.ts +2 -0
- package/lib/esm/platforms/docker/go.js +242 -0
- package/lib/esm/platforms/docker/go.js.map +1 -0
- package/lib/esm/platforms/docker/index.d.ts +2 -0
- package/lib/esm/platforms/docker/index.js +31 -0
- package/lib/esm/platforms/docker/index.js.map +1 -0
- package/lib/esm/platforms/docker/parseMounts.d.ts +7 -0
- package/lib/esm/platforms/docker/parseMounts.js +23 -0
- package/lib/esm/platforms/docker/parseMounts.js.map +1 -0
- package/lib/esm/platforms/docker/parsePortMappings.d.ts +8 -0
- package/lib/esm/platforms/docker/parsePortMappings.js +21 -0
- package/lib/esm/platforms/docker/parsePortMappings.js.map +1 -0
- package/lib/esm/platforms/docker/resolvePortMappings.d.ts +8 -0
- package/lib/esm/platforms/docker/resolvePortMappings.js +18 -0
- package/lib/esm/platforms/docker/resolvePortMappings.js.map +1 -0
- package/lib/esm/platforms/docker/writeComposeFile.d.ts +20 -0
- package/lib/esm/platforms/docker/writeComposeFile.js +37 -0
- package/lib/esm/platforms/docker/writeComposeFile.js.map +1 -0
- package/lib/esm/platforms/index.d.ts +3 -0
- package/lib/esm/platforms/index.js +17 -0
- package/lib/esm/platforms/index.js.map +1 -0
- package/lib/esm/platforms/types.d.ts +21 -0
- package/lib/esm/platforms/types.js +6 -0
- package/lib/esm/platforms/types.js.map +1 -0
- package/package.json +71 -3
- package/templates/user-script/README.md +28 -0
- package/templates/user-script/gitignore +2 -0
- package/templates/user-script/package.json +16 -0
- package/templates/user-script/src/main.ts +15 -0
- package/templates/user-script/tsconfig.json +12 -0
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { ParsedDockerPlatformSettings } from './getDockerPlatformSettings';
|
|
2
|
+
/**
|
|
3
|
+
* `[<registry>/]qpq-<application>:<tag>`. Named by the deployment's application, not the app
|
|
4
|
+
* folder, so two products built from one codebase get separate images and data volumes.
|
|
5
|
+
*/
|
|
6
|
+
export declare const getImageName: (applicationName: string, settings: ParsedDockerPlatformSettings) => string;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `[<registry>/]qpq-<application>:<tag>`. Named by the deployment's application, not the app
|
|
3
|
+
* folder, so two products built from one codebase get separate images and data volumes.
|
|
4
|
+
*/
|
|
5
|
+
export const getImageName = (applicationName, settings) => `${settings.registry ? `${settings.registry}/` : ''}qpq-${applicationName}:${settings.tag}`;
|
|
6
|
+
//# sourceMappingURL=getImageName.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getImageName.js","sourceRoot":"","sources":["../../../../src/platforms/docker/getImageName.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,eAAuB,EAAE,QAAsC,EAAU,EAAE,CACtG,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC,EAAE,OAAO,eAAe,IAAI,QAAQ,CAAC,GAAG,EAAE,CAAC","sourcesContent":["import { ParsedDockerPlatformSettings } from './getDockerPlatformSettings';\n\n/**\n * `[<registry>/]qpq-<application>:<tag>`. Named by the deployment's application, not the app\n * folder, so two products built from one codebase get separate images and data volumes.\n */\nexport const getImageName = (applicationName: string, settings: ParsedDockerPlatformSettings): string =>\n `${settings.registry ? `${settings.registry}/` : ''}qpq-${applicationName}:${settings.tag}`;\n"]}
|
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
// Docker platform deploy (`qpq go` with platform 'docker') — proof-of-concept
|
|
2
|
+
// self-hosting: bakes the QPQ dev server (a full local platform emulation)
|
|
3
|
+
// plus every service of the app and its pre-built views into one docker image.
|
|
4
|
+
//
|
|
5
|
+
// 1. Build workspace packages, then the dev-server bundle (all services).
|
|
6
|
+
// 2. Build every views microfrontend with a same-origin module-federation
|
|
7
|
+
// remote base (/<views subdomain>/<svc>), mirroring the AWS layout.
|
|
8
|
+
// 3. Assemble an image context under dist/qpq/docker-image/<app>/ — server
|
|
9
|
+
// bundle, web root (every web entry, placed by its port or its domain),
|
|
10
|
+
// a workspaces-stripped package.json for runtime deps, and the
|
|
11
|
+
// locally-built quidproquo packages as a vendor overlay.
|
|
12
|
+
// 4. docker build (buildx with a push when the deployment names a registry or
|
|
13
|
+
// a target platform), write a docker-compose.yml, print how to run it.
|
|
14
|
+
//
|
|
15
|
+
// Not production-grade (single process, sqlite KVS, in-memory queues) —
|
|
16
|
+
// it's the whole product on one box with one command.
|
|
17
|
+
import { getQpqAppDeployment } from '@qpqjs/config-aws';
|
|
18
|
+
import { isQpqPackageName, QpqDeployEnvVar } from '@qpqjs/core';
|
|
19
|
+
import { getAppServiceQpqConfigs, getDevServerRspackConfig, listInstalledQpqPackageNames, runRspack } from '@qpqjs/deploy-rspack';
|
|
20
|
+
import { getWebEntryDir, getWebEntryPlacements } from '@qpqjs/dev-server';
|
|
21
|
+
import { FEDERATED_VIEWS_SUBDOMAIN } from '@qpqjs/webserver';
|
|
22
|
+
import fs from 'fs';
|
|
23
|
+
import path from 'path';
|
|
24
|
+
import { writeDevServerEntry, writeUserScriptChildEntry } from '../../lib/devServerEntry';
|
|
25
|
+
import { readDevServerPorts } from '../../lib/devServerPorts';
|
|
26
|
+
import { getRoot, getServiceNamesWithViews } from '../../lib/discovery';
|
|
27
|
+
import { getDefaultHookJobs } from '../../lib/getDefaultHookJobs';
|
|
28
|
+
import { runAppHook, runHookForAppPackages } from '../../lib/hooks';
|
|
29
|
+
import { getOwnPackageRoot } from '../../lib/packageRoot';
|
|
30
|
+
import { runCommand } from '../../lib/runCommand';
|
|
31
|
+
import { assertNoFailures } from '../../lib/runTasks';
|
|
32
|
+
import { logTimeEnd, logTimeStart } from '../../lib/timing';
|
|
33
|
+
import { bundleViews, getViewsDistDir } from '../../lib/views';
|
|
34
|
+
import { clearWebAddressingEnv, setWebAddressingEnv } from '../../lib/webAddressingEnv';
|
|
35
|
+
import { getContainerPorts } from './getContainerPorts';
|
|
36
|
+
import { getDockerPlatformSettings } from './getDockerPlatformSettings';
|
|
37
|
+
import { getImageName } from './getImageName';
|
|
38
|
+
import { resolvePortMappings } from './resolvePortMappings';
|
|
39
|
+
import { writeComposeFile } from './writeComposeFile';
|
|
40
|
+
const getImageContextDir = (root, appName) => path.join(root, 'dist', 'qpq', 'docker-image', appName);
|
|
41
|
+
// Every web entry's files go where the runtime looks for them. The federated views entry
|
|
42
|
+
// is assembled from every service's views build (one folder per service, as on AWS);
|
|
43
|
+
// anything else is its own buildPath. A missing build fails here rather than serving an
|
|
44
|
+
// empty site later.
|
|
45
|
+
const copyWebEntryContent = (appName, contextDir, entry, viewServices) => {
|
|
46
|
+
const label = `${entry.service}/${entry.entryName}`;
|
|
47
|
+
const targetDir = getWebEntryDir(path.join(contextDir, 'web'), entry);
|
|
48
|
+
if (entry.webEntry.domain.subDomainName === FEDERATED_VIEWS_SUBDOMAIN) {
|
|
49
|
+
for (const serviceName of viewServices) {
|
|
50
|
+
fs.cpSync(getViewsDistDir(appName, serviceName), path.join(targetDir, serviceName), { recursive: true });
|
|
51
|
+
}
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
// A standalone host entry serves its own service's views build, as on AWS.
|
|
55
|
+
if (entry.webEntry.storageDrive.syncServiceViews) {
|
|
56
|
+
fs.cpSync(getViewsDistDir(appName, entry.service), targetDir, { recursive: true });
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
if (!entry.webEntry.buildPath) {
|
|
60
|
+
throw new Error(`Web entry ${label} has no buildPath, so there is nothing to serve`);
|
|
61
|
+
}
|
|
62
|
+
const buildDir = path.resolve(entry.configRoot, entry.webEntry.buildPath);
|
|
63
|
+
if (!fs.existsSync(path.join(buildDir, entry.webEntry.indexRoot))) {
|
|
64
|
+
throw new Error(`Web entry ${label} has no ${entry.webEntry.indexRoot} under ${buildDir}; build it before qpq go`);
|
|
65
|
+
}
|
|
66
|
+
fs.cpSync(buildDir, targetDir, { recursive: true });
|
|
67
|
+
};
|
|
68
|
+
// Plain `docker build` into the local store unless the deployment asks for a registry or a
|
|
69
|
+
// target platform, which need buildx: `--push` sends a cross-platform image straight to the
|
|
70
|
+
// registry, `--load` keeps a same-machine one local.
|
|
71
|
+
const buildImage = async (imageName, contextDir, settings) => {
|
|
72
|
+
if (!settings.registry && !settings.arch) {
|
|
73
|
+
await runCommand('docker', ['build', '-t', imageName, contextDir]);
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
const platformArgs = settings.arch ? ['--platform', settings.arch] : [];
|
|
77
|
+
await runCommand('docker', ['buildx', 'build', ...platformArgs, '-t', imageName, settings.registry ? '--push' : '--load', contextDir]);
|
|
78
|
+
};
|
|
79
|
+
// The Dockerfile is shared; only its EXPOSE line depends on the app.
|
|
80
|
+
const writeDockerfile = (contextDir, containerPorts) => {
|
|
81
|
+
const template = fs.readFileSync(path.join(getOwnPackageRoot(), 'docker', 'dev-server', 'Dockerfile'), 'utf8');
|
|
82
|
+
const dockerfile = template.replace(/^EXPOSE .*$/m, `EXPOSE ${containerPorts.join(' ')}`);
|
|
83
|
+
fs.writeFileSync(path.join(contextDir, 'Dockerfile'), dockerfile);
|
|
84
|
+
};
|
|
85
|
+
// The consumer root package.json, stripped to what the image's npm install
|
|
86
|
+
// needs: runtime dependencies (+ overrides). Workspaces/scripts/devDeps are
|
|
87
|
+
// host-only concerns — the workspace packages themselves are bundled into the
|
|
88
|
+
// server bundle from source.
|
|
89
|
+
//
|
|
90
|
+
// quidproquo deps declared as file: refs (a consumer living beside the qpq
|
|
91
|
+
// monorepo) point outside the image context, where npm install would leave
|
|
92
|
+
// dangling symlinks — rewrite them to the vendored copies inside the context.
|
|
93
|
+
const writeImagePackageJson = (root, contextDir) => {
|
|
94
|
+
const rootPackageJson = JSON.parse(fs.readFileSync(path.join(root, 'package.json'), 'utf8'));
|
|
95
|
+
const dependencies = { ...(rootPackageJson.dependencies ?? {}) };
|
|
96
|
+
for (const [name, version] of Object.entries(dependencies)) {
|
|
97
|
+
if (isQpqPackageName(name) && version.startsWith('file:')) {
|
|
98
|
+
dependencies[name] = `file:./vendor/${name}`;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
const imagePackageJson = {
|
|
102
|
+
name: `${rootPackageJson.name}-qpq-docker`,
|
|
103
|
+
version: rootPackageJson.version ?? '0.0.0',
|
|
104
|
+
private: true,
|
|
105
|
+
dependencies,
|
|
106
|
+
overrides: rootPackageJson.overrides,
|
|
107
|
+
};
|
|
108
|
+
fs.writeFileSync(path.join(contextDir, 'package.json'), JSON.stringify(imagePackageJson, null, 2) + '\n');
|
|
109
|
+
};
|
|
110
|
+
// Copy the locally-built quidproquo packages (which may be npm-linked
|
|
111
|
+
// checkouts newer than the registry) into vendor/ so the image runs the same
|
|
112
|
+
// qpq code the bundle was built against. Follows the node_modules symlinks;
|
|
113
|
+
// lib/config only — no node_modules, no src.
|
|
114
|
+
const vendorQuidproquoPackages = (root, contextDir) => {
|
|
115
|
+
const nodeModules = path.join(root, 'node_modules');
|
|
116
|
+
const vendorDir = path.join(contextDir, 'vendor');
|
|
117
|
+
let vendored = 0;
|
|
118
|
+
for (const name of listInstalledQpqPackageNames(nodeModules)) {
|
|
119
|
+
const packageDir = fs.realpathSync(path.join(nodeModules, name));
|
|
120
|
+
const targetDir = path.join(vendorDir, name);
|
|
121
|
+
fs.mkdirSync(targetDir, { recursive: true });
|
|
122
|
+
fs.copyFileSync(path.join(packageDir, 'package.json'), path.join(targetDir, 'package.json'));
|
|
123
|
+
for (const sub of ['lib', 'config']) {
|
|
124
|
+
const subDir = path.join(packageDir, sub);
|
|
125
|
+
if (fs.existsSync(subDir)) {
|
|
126
|
+
fs.cpSync(subDir, path.join(targetDir, sub), { recursive: true, dereference: true });
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
vendored += 1;
|
|
130
|
+
}
|
|
131
|
+
return vendored;
|
|
132
|
+
};
|
|
133
|
+
export const dockerGo = async (appName, plan) => {
|
|
134
|
+
if (plan.kind === 'cancelled') {
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
if (plan.kind === 'account' || plan.kind === 'bootstrap') {
|
|
138
|
+
console.log(`Nothing to do — the docker platform has no ${plan.kind} stacks.`);
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
const root = getRoot();
|
|
142
|
+
const deploymentName = process.env[QpqDeployEnvVar.deployName];
|
|
143
|
+
const dockerSettings = getDockerPlatformSettings(deploymentName, getQpqAppDeployment(root, appName, deploymentName));
|
|
144
|
+
const applicationName = process.env[QpqDeployEnvVar.applicationName];
|
|
145
|
+
const imageName = getImageName(applicationName, dockerSettings);
|
|
146
|
+
const containerName = `qpq-${applicationName}`;
|
|
147
|
+
const volumeName = `${containerName}-data`;
|
|
148
|
+
// The dev server hosts every service of the app, so per-service/stack
|
|
149
|
+
// selections don't apply — the image is always the whole app.
|
|
150
|
+
console.log(`\n\nBuilding docker image [${imageName}] — the whole app deploys as one image\n\n`);
|
|
151
|
+
logTimeStart('totalTime');
|
|
152
|
+
await runAppHook(appName, 'predeploy');
|
|
153
|
+
// Workspace packages resolve through their built dist/ (package.json main),
|
|
154
|
+
// so bundles would ship stale code unless every lib is tsc'd first.
|
|
155
|
+
console.log('Building workspace packages');
|
|
156
|
+
assertNoFailures('Workspace build', await runHookForAppPackages('build', appName, getDefaultHookJobs()));
|
|
157
|
+
// ---- Server bundle: the dev server + every service, one main.js ----
|
|
158
|
+
console.log('Bundling server (dev server + all services)');
|
|
159
|
+
const qpqConfigs = getAppServiceQpqConfigs(root, appName);
|
|
160
|
+
// Resolved before anything slow runs, so a bad port or domain fails the build up front.
|
|
161
|
+
const devServerPorts = readDevServerPorts(appName);
|
|
162
|
+
const { hosts: webEntryHosts, routes: webEntryRoutes } = getWebEntryPlacements(qpqConfigs, Object.values(devServerPorts));
|
|
163
|
+
const containerPorts = getContainerPorts(devServerPorts, webEntryHosts);
|
|
164
|
+
const portMappings = resolvePortMappings(deploymentName, dockerSettings, devServerPorts.api, containerPorts);
|
|
165
|
+
const mapHostPort = (containerPort) => portMappings.find((mapping) => mapping.container === containerPort)?.host ?? containerPort;
|
|
166
|
+
// Nothing deploys into the container, so the image runs its own pending migrations on start.
|
|
167
|
+
const entry = writeDevServerEntry(root, appName, 'migrate-then-serve');
|
|
168
|
+
const userScriptChildEntry = writeUserScriptChildEntry(root);
|
|
169
|
+
// The image installs its own node_modules next to the bundle, so externals
|
|
170
|
+
// must stay bare; host-resolved absolute paths do not exist in the container.
|
|
171
|
+
await runRspack(getDevServerRspackConfig({ root, entry, userScriptChildEntry, qpqConfigs, portableExternals: true }));
|
|
172
|
+
// ---- Views: production builds with same-origin federation remotes ----
|
|
173
|
+
// The browser reaches everything on the page's own host, on the HOST side of the port
|
|
174
|
+
// mappings; an unmapped port stays as is (nothing outside the container can reach it anyway).
|
|
175
|
+
setWebAddressingEnv(qpqConfigs, { api: devServerPorts.api, webSocket: devServerPorts.webSocket, mapHostPort });
|
|
176
|
+
process.env.QPQ_VIEWS_REMOTE_BASE = `/${FEDERATED_VIEWS_SUBDOMAIN}`;
|
|
177
|
+
const viewServices = getServiceNamesWithViews(appName);
|
|
178
|
+
for (const serviceName of viewServices) {
|
|
179
|
+
console.log(`Bundling views: [${serviceName}]`);
|
|
180
|
+
await bundleViews(appName, serviceName);
|
|
181
|
+
}
|
|
182
|
+
delete process.env.QPQ_VIEWS_REMOTE_BASE;
|
|
183
|
+
clearWebAddressingEnv();
|
|
184
|
+
// ---- Assemble the image context ----
|
|
185
|
+
console.log('Assembling image context');
|
|
186
|
+
const contextDir = getImageContextDir(root, appName);
|
|
187
|
+
fs.rmSync(contextDir, { recursive: true, force: true });
|
|
188
|
+
fs.mkdirSync(contextDir, { recursive: true });
|
|
189
|
+
writeDockerfile(contextDir, containerPorts);
|
|
190
|
+
writeImagePackageJson(root, contextDir);
|
|
191
|
+
const vendored = vendorQuidproquoPackages(root, contextDir);
|
|
192
|
+
console.log(`Vendored ${vendored} quidproquo packages`);
|
|
193
|
+
fs.cpSync(path.join(root, 'dist', 'qpq', 'dev-server'), path.join(contextDir, 'server'), { recursive: true });
|
|
194
|
+
for (const entry of [...webEntryRoutes, ...webEntryHosts]) {
|
|
195
|
+
copyWebEntryContent(appName, contextDir, entry, viewServices);
|
|
196
|
+
}
|
|
197
|
+
const composePath = writeComposeFile({
|
|
198
|
+
contextDir,
|
|
199
|
+
imageName,
|
|
200
|
+
serviceName: containerName,
|
|
201
|
+
volumeName,
|
|
202
|
+
portMappings,
|
|
203
|
+
dataPath: dockerSettings.dataPath ?? null,
|
|
204
|
+
mounts: dockerSettings.mounts ?? [],
|
|
205
|
+
publicHost: dockerSettings.publicHost ?? null,
|
|
206
|
+
publicFileStoragePort: mapHostPort(devServerPorts.fileStorage),
|
|
207
|
+
});
|
|
208
|
+
// ---- Build the image ----
|
|
209
|
+
console.log(`Building docker image${dockerSettings.arch ? ` for ${dockerSettings.arch}` : ''}${dockerSettings.registry ? `, pushing to ${dockerSettings.registry}` : ''}`);
|
|
210
|
+
await buildImage(imageName, contextDir, dockerSettings);
|
|
211
|
+
logTimeEnd('totalTime');
|
|
212
|
+
const hostUrl = (containerPort) => {
|
|
213
|
+
const hostPort = portMappings.find((mapping) => mapping.container === containerPort)?.host;
|
|
214
|
+
return hostPort === undefined ? `(container port ${containerPort} is not mapped)` : `http://localhost${hostPort === 80 ? '' : `:${hostPort}`}`;
|
|
215
|
+
};
|
|
216
|
+
const siteUrl = hostUrl(devServerPorts.api);
|
|
217
|
+
const entryLines = [
|
|
218
|
+
...webEntryRoutes.map((route) => ` ${route.service}/${route.entryName}: ${siteUrl}${route.path === '/' ? '' : route.path}`),
|
|
219
|
+
...webEntryHosts.map((host) => ` ${host.service}/${host.entryName}: ${hostUrl(host.port)}`),
|
|
220
|
+
].join('\n');
|
|
221
|
+
const where = dockerSettings.registry ? `pushed to [${imageName}]` : `[${imageName}] in the local docker store`;
|
|
222
|
+
const onHost = dockerSettings.registry
|
|
223
|
+
? `On the host (Unraid: Compose Manager, or any docker host), copy the compose file there and run:`
|
|
224
|
+
: `Run it here:`;
|
|
225
|
+
console.log(`
|
|
226
|
+
Done. The image is ${where}.
|
|
227
|
+
|
|
228
|
+
${onHost}
|
|
229
|
+
|
|
230
|
+
docker compose -f ${composePath} up -d
|
|
231
|
+
|
|
232
|
+
Then open ${siteUrl} (replace localhost with the host's address)
|
|
233
|
+
${entryLines ? `\nWeb entries:\n${entryLines}\n` : ''}
|
|
234
|
+
Ports come from the deployment's platformSettings.portMappings (${portMappings.map((m) => `${m.host}:${m.container}`).join(', ')})
|
|
235
|
+
and are baked into the frontend, so a host must map the same ones. App state lives in ${dockerSettings.dataPath ?? `the ${volumeName} volume`}.${dockerSettings.mounts?.length
|
|
236
|
+
? `\nAlso mounted: ${dockerSettings.mounts.map((mount) => `${mount.host} at ${mount.container}${mount.readOnly ? ' (read-only)' : ''}`).join(', ')}.`
|
|
237
|
+
: ''}${dockerSettings.publicHost
|
|
238
|
+
? ''
|
|
239
|
+
: `\nSecure file urls point at localhost; set platformSettings.publicHost to the address browsers use for this host.`}
|
|
240
|
+
`);
|
|
241
|
+
};
|
|
242
|
+
//# sourceMappingURL=go.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"go.js","sourceRoot":"","sources":["../../../../src/platforms/docker/go.ts"],"names":[],"mappings":"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","sourcesContent":["// Docker platform deploy (`qpq go` with platform 'docker') — proof-of-concept\n// self-hosting: bakes the QPQ dev server (a full local platform emulation)\n// plus every service of the app and its pre-built views into one docker image.\n//\n// 1. Build workspace packages, then the dev-server bundle (all services).\n// 2. Build every views microfrontend with a same-origin module-federation\n// remote base (/<views 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"]}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { BUILD_ONLY_FLAG, FROM_BUILD_FLAG } from '../../lib/goDockerMode';
|
|
2
|
+
import { getDockerPlatformSettings } from './getDockerPlatformSettings';
|
|
3
|
+
import { dockerGo } from './go';
|
|
4
|
+
const publishNotSupported = async () => {
|
|
5
|
+
console.error('The docker platform has no federated code store — story code is baked into the image. Rebuild with qpq go instead.');
|
|
6
|
+
process.exit(1);
|
|
7
|
+
};
|
|
8
|
+
// A docker platform's deploy already is the containerised one, so `qpq go:docker`
|
|
9
|
+
// (what a scaffolded app's `npm run deploy` runs) is the same build. The image is
|
|
10
|
+
// the deploy, so there is no saved build to split across two runs.
|
|
11
|
+
const dockerGoDocker = async (appName, plan, mode) => {
|
|
12
|
+
if (mode !== 'full') {
|
|
13
|
+
console.error(`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.`);
|
|
14
|
+
process.exit(1);
|
|
15
|
+
}
|
|
16
|
+
await dockerGo(appName, plan);
|
|
17
|
+
};
|
|
18
|
+
export const dockerPlatformDriver = {
|
|
19
|
+
// No identity to prime. Mappings are only parsed here; which container ports exist depends
|
|
20
|
+
// on the app's config, which is not loaded yet, so that check happens in the build.
|
|
21
|
+
prepareDeployment: (deploymentName, deployment) => {
|
|
22
|
+
getDockerPlatformSettings(deploymentName, deployment);
|
|
23
|
+
},
|
|
24
|
+
go: dockerGo,
|
|
25
|
+
goDocker: dockerGoDocker,
|
|
26
|
+
publish: publishNotSupported,
|
|
27
|
+
publishBuild: publishNotSupported,
|
|
28
|
+
publishUpload: publishNotSupported,
|
|
29
|
+
publishDeploy: publishNotSupported,
|
|
30
|
+
};
|
|
31
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/platforms/docker/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,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,mBAAmB,GAAG,KAAK,IAAmB,EAAE;IACpD,OAAO,CAAC,KAAK,CAAC,oHAAoH,CAAC,CAAC;IACpI,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC;AAEF,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,OAAO,CAAC,KAAK,CACX,uDAAuD,eAAe,QAAQ,eAAe,gDAAgD,CAC9I,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,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 { 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 publishNotSupported = async (): Promise<void> => {\n console.error('The docker platform has no federated code store — story code is baked into the image. Rebuild with qpq go instead.');\n process.exit(1);\n};\n\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 console.error(\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 process.exit(1);\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"]}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// host:container, both absolute, optionally ending :ro or :rw.
|
|
2
|
+
const MOUNT_PATTERN = /^(\/[^:]*):(\/[^:]*?)(?::(ro|rw))?$/;
|
|
3
|
+
// The image's own files live under /app (including the state directory), so a mount there would
|
|
4
|
+
// hide them.
|
|
5
|
+
const IMAGE_ROOT = '/app';
|
|
6
|
+
const trimTrailingSlashes = (folder) => folder.replace(/\/+$/, '') || '/';
|
|
7
|
+
/** Parses "host:container[:ro], ..." into mounts, throwing naming the first malformed item. */
|
|
8
|
+
export const parseMounts = (value) => value
|
|
9
|
+
.split(',')
|
|
10
|
+
.map((item) => item.trim())
|
|
11
|
+
.filter(Boolean)
|
|
12
|
+
.map((item) => {
|
|
13
|
+
const match = MOUNT_PATTERN.exec(item);
|
|
14
|
+
if (!match) {
|
|
15
|
+
throw new Error(`Mount '${item}' must be host:container with both absolute, optionally ending :ro, e.g. /mnt/user/media:/media`);
|
|
16
|
+
}
|
|
17
|
+
const container = trimTrailingSlashes(match[2]);
|
|
18
|
+
if (container === IMAGE_ROOT || container.startsWith(`${IMAGE_ROOT}/`) || container === '/') {
|
|
19
|
+
throw new Error(`Mount '${item}' would cover the image's own files: mount it somewhere other than / or ${IMAGE_ROOT}`);
|
|
20
|
+
}
|
|
21
|
+
return { host: trimTrailingSlashes(match[1]), container, readOnly: match[3] === 'ro' };
|
|
22
|
+
});
|
|
23
|
+
//# sourceMappingURL=parseMounts.js.map
|
|
@@ -0,0 +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,SAAS,GAAG,mBAAmB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAChD,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,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;AACzF,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 container = trimTrailingSlashes(match[2]);\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(match[1]), container, readOnly: match[3] === 'ro' };\n });\n"]}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export type PortMapping = {
|
|
2
|
+
host: number;
|
|
3
|
+
container: number;
|
|
4
|
+
};
|
|
5
|
+
/** Parses "host:container, ..." into pairs, throwing naming the first malformed item. */
|
|
6
|
+
export declare const parsePortMappings: (value: string) => PortMapping[];
|
|
7
|
+
/** Throws when a mapping targets a port the image does not listen on. */
|
|
8
|
+
export declare const assertContainerPorts: (mappings: PortMapping[], containerPorts: number[]) => void;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
const PAIR_PATTERN = /^(\d{1,5}):(\d{1,5})$/;
|
|
2
|
+
/** Parses "host:container, ..." into pairs, throwing naming the first malformed item. */
|
|
3
|
+
export const parsePortMappings = (value) => value
|
|
4
|
+
.split(',')
|
|
5
|
+
.map((item) => item.trim())
|
|
6
|
+
.filter(Boolean)
|
|
7
|
+
.map((item) => {
|
|
8
|
+
const match = PAIR_PATTERN.exec(item);
|
|
9
|
+
if (!match) {
|
|
10
|
+
throw new Error(`Port mapping '${item}' must be host:container, e.g. 80:8080`);
|
|
11
|
+
}
|
|
12
|
+
return { host: Number(match[1]), container: Number(match[2]) };
|
|
13
|
+
});
|
|
14
|
+
/** Throws when a mapping targets a port the image does not listen on. */
|
|
15
|
+
export const assertContainerPorts = (mappings, containerPorts) => {
|
|
16
|
+
const unknown = mappings.filter((mapping) => !containerPorts.includes(mapping.container));
|
|
17
|
+
if (unknown.length > 0) {
|
|
18
|
+
throw new Error(`Port mapping(s) ${unknown.map((m) => `'${m.host}:${m.container}'`).join(', ')} target ports the image does not listen on (${containerPorts.join(', ')})`);
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
//# sourceMappingURL=parsePortMappings.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parsePortMappings.js","sourceRoot":"","sources":["../../../../src/platforms/docker/parsePortMappings.ts"],"names":[],"mappings":"AAKA,MAAM,YAAY,GAAG,uBAAuB,CAAC;AAE7C,yFAAyF;AACzF,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,KAAa,EAAiB,EAAE,CAChE,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,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACtC,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CAAC,iBAAiB,IAAI,wCAAwC,CAAC,CAAC;IACjF,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AACjE,CAAC,CAAC,CAAC;AAEP,yEAAyE;AACzE,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,QAAuB,EAAE,cAAwB,EAAQ,EAAE;IAC9F,MAAM,OAAO,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,cAAc,CAAC,QAAQ,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC;IAC1F,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CACb,mBAAmB,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,+CAA+C,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAC1J,CAAC;IACJ,CAAC;AACH,CAAC,CAAC","sourcesContent":["export type PortMapping = {\n host: number;\n container: number;\n};\n\nconst PAIR_PATTERN = /^(\\d{1,5}):(\\d{1,5})$/;\n\n/** Parses \"host:container, ...\" into pairs, throwing naming the first malformed item. */\nexport const parsePortMappings = (value: string): PortMapping[] =>\n value\n .split(',')\n .map((item) => item.trim())\n .filter(Boolean)\n .map((item) => {\n const match = PAIR_PATTERN.exec(item);\n if (!match) {\n throw new Error(`Port mapping '${item}' must be host:container, e.g. 80:8080`);\n }\n return { host: Number(match[1]), container: Number(match[2]) };\n });\n\n/** Throws when a mapping targets a port the image does not listen on. */\nexport const assertContainerPorts = (mappings: PortMapping[], containerPorts: number[]): void => {\n const unknown = mappings.filter((mapping) => !containerPorts.includes(mapping.container));\n if (unknown.length > 0) {\n throw new Error(\n `Port mapping(s) ${unknown.map((m) => `'${m.host}:${m.container}'`).join(', ')} target ports the image does not listen on (${containerPorts.join(', ')})`,\n );\n }\n};\n"]}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { ParsedDockerPlatformSettings } from './getDockerPlatformSettings';
|
|
2
|
+
import { PortMapping } from './parsePortMappings';
|
|
3
|
+
/**
|
|
4
|
+
* The host:container pairs to run the image with: the deployment's own, or one per container
|
|
5
|
+
* port plus 80 for the site. Throws, naming the deployment, when a mapping targets a port the
|
|
6
|
+
* image does not listen on.
|
|
7
|
+
*/
|
|
8
|
+
export declare const resolvePortMappings: (deploymentName: string, settings: ParsedDockerPlatformSettings, apiPort: number, containerPorts: number[]) => PortMapping[];
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { getDefaultPortMappings } from './getDefaultPortMappings';
|
|
2
|
+
import { assertContainerPorts } from './parsePortMappings';
|
|
3
|
+
/**
|
|
4
|
+
* The host:container pairs to run the image with: the deployment's own, or one per container
|
|
5
|
+
* port plus 80 for the site. Throws, naming the deployment, when a mapping targets a port the
|
|
6
|
+
* image does not listen on.
|
|
7
|
+
*/
|
|
8
|
+
export const resolvePortMappings = (deploymentName, settings, apiPort, containerPorts) => {
|
|
9
|
+
const portMappings = settings.portMappings ?? getDefaultPortMappings(apiPort, containerPorts);
|
|
10
|
+
try {
|
|
11
|
+
assertContainerPorts(portMappings, containerPorts);
|
|
12
|
+
}
|
|
13
|
+
catch (error) {
|
|
14
|
+
throw new Error(`Invalid docker deployment '${deploymentName}': ${error instanceof Error ? error.message : String(error)}`);
|
|
15
|
+
}
|
|
16
|
+
return portMappings;
|
|
17
|
+
};
|
|
18
|
+
//# sourceMappingURL=resolvePortMappings.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolvePortMappings.js","sourceRoot":"","sources":["../../../../src/platforms/docker/resolvePortMappings.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAElE,OAAO,EAAE,oBAAoB,EAAe,MAAM,qBAAqB,CAAC;AAExE;;;;GAIG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,CACjC,cAAsB,EACtB,QAAsC,EACtC,OAAe,EACf,cAAwB,EACT,EAAE;IACjB,MAAM,YAAY,GAAG,QAAQ,CAAC,YAAY,IAAI,sBAAsB,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC;IAC9F,IAAI,CAAC;QACH,oBAAoB,CAAC,YAAY,EAAE,cAAc,CAAC,CAAC;IACrD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,8BAA8B,cAAc,MAAM,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAC9H,CAAC;IACD,OAAO,YAAY,CAAC;AACtB,CAAC,CAAC","sourcesContent":["import { getDefaultPortMappings } from './getDefaultPortMappings';\nimport { ParsedDockerPlatformSettings } from './getDockerPlatformSettings';\nimport { assertContainerPorts, PortMapping } from './parsePortMappings';\n\n/**\n * The host:container pairs to run the image with: the deployment's own, or one per container\n * port plus 80 for the site. Throws, naming the deployment, when a mapping targets a port the\n * image does not listen on.\n */\nexport const resolvePortMappings = (\n deploymentName: string,\n settings: ParsedDockerPlatformSettings,\n apiPort: number,\n containerPorts: number[],\n): PortMapping[] => {\n const portMappings = settings.portMappings ?? getDefaultPortMappings(apiPort, containerPorts);\n try {\n assertContainerPorts(portMappings, containerPorts);\n } catch (error) {\n throw new Error(`Invalid docker deployment '${deploymentName}': ${error instanceof Error ? error.message : String(error)}`);\n }\n return portMappings;\n};\n"]}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Nullable } from '@qpqjs/core';
|
|
2
|
+
import { Mount } from './parseMounts';
|
|
3
|
+
import { PortMapping } from './parsePortMappings';
|
|
4
|
+
export type ComposeFileOptions = {
|
|
5
|
+
contextDir: string;
|
|
6
|
+
imageName: string;
|
|
7
|
+
serviceName: string;
|
|
8
|
+
volumeName: string;
|
|
9
|
+
portMappings: PortMapping[];
|
|
10
|
+
dataPath: Nullable<string>;
|
|
11
|
+
mounts: Mount[];
|
|
12
|
+
publicHost: Nullable<string>;
|
|
13
|
+
publicFileStoragePort: number;
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* A docker-compose.yml for running the image on any docker host: the image, the port mappings
|
|
17
|
+
* the frontend was built for, the public host, where the app's state lives, and any other host
|
|
18
|
+
* folders mounted into it. Returns its path.
|
|
19
|
+
*/
|
|
20
|
+
export declare const writeComposeFile: ({ contextDir, imageName, serviceName, volumeName, portMappings, dataPath, mounts, publicHost, publicFileStoragePort, }: ComposeFileOptions) => string;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { DEV_SERVER_PUBLIC_FILE_STORAGE_PORT_ENV, DEV_SERVER_PUBLIC_HOST_ENV } from '../../lib/devServerEntry';
|
|
4
|
+
/**
|
|
5
|
+
* A docker-compose.yml for running the image on any docker host: the image, the port mappings
|
|
6
|
+
* the frontend was built for, the public host, where the app's state lives, and any other host
|
|
7
|
+
* folders mounted into it. Returns its path.
|
|
8
|
+
*/
|
|
9
|
+
export const writeComposeFile = ({ contextDir, imageName, serviceName, volumeName, portMappings, dataPath, mounts, publicHost, publicFileStoragePort, }) => {
|
|
10
|
+
const ports = portMappings.map((mapping) => ` - "${mapping.host}:${mapping.container}"`).join('\n');
|
|
11
|
+
const environmentLines = [
|
|
12
|
+
...(publicHost ? [`${DEV_SERVER_PUBLIC_HOST_ENV}=${publicHost}`] : []),
|
|
13
|
+
`${DEV_SERVER_PUBLIC_FILE_STORAGE_PORT_ENV}=${publicFileStoragePort}`,
|
|
14
|
+
];
|
|
15
|
+
const environment = ` environment:\n${environmentLines.map((line) => ` - ${line}`).join('\n')}\n`;
|
|
16
|
+
// All app state (key-value stores, file storage) is this one directory.
|
|
17
|
+
const stateSource = dataPath ?? volumeName;
|
|
18
|
+
const namedVolume = dataPath ? '' : `\nvolumes:\n ${volumeName}:\n`;
|
|
19
|
+
// Quoted (a JSON string is a valid YAML one), since host folders can hold spaces.
|
|
20
|
+
const mountLines = mounts.map((mount) => `\n - ${JSON.stringify(`${mount.host}:${mount.container}${mount.readOnly ? ':ro' : ''}`)}`).join('');
|
|
21
|
+
const compose = `# Generated by qpq go from deploy.config.json. Host ports are baked into the frontend, so
|
|
22
|
+
# change them there and rebuild rather than here.
|
|
23
|
+
services:
|
|
24
|
+
${serviceName}:
|
|
25
|
+
image: ${imageName}
|
|
26
|
+
container_name: ${serviceName}
|
|
27
|
+
restart: unless-stopped
|
|
28
|
+
${environment} ports:
|
|
29
|
+
${ports}
|
|
30
|
+
volumes:
|
|
31
|
+
- ${stateSource}:/app/.qpq-runtime${mountLines}
|
|
32
|
+
${namedVolume}`;
|
|
33
|
+
const composePath = path.join(contextDir, 'docker-compose.yml');
|
|
34
|
+
fs.writeFileSync(composePath, compose);
|
|
35
|
+
return composePath;
|
|
36
|
+
};
|
|
37
|
+
//# sourceMappingURL=writeComposeFile.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"writeComposeFile.js","sourceRoot":"","sources":["../../../../src/platforms/docker/writeComposeFile.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,OAAO,EAAE,uCAAuC,EAAE,0BAA0B,EAAE,MAAM,0BAA0B,CAAC;AAoB/G;;;;GAIG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,EAC/B,UAAU,EACV,SAAS,EACT,WAAW,EACX,UAAU,EACV,YAAY,EACZ,QAAQ,EACR,MAAM,EACN,UAAU,EACV,qBAAqB,GACF,EAAU,EAAE;IAC/B,MAAM,KAAK,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,YAAY,OAAO,CAAC,IAAI,IAAI,OAAO,CAAC,SAAS,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAEzG,MAAM,gBAAgB,GAAG;QACvB,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,GAAG,0BAA0B,IAAI,UAAU,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACtE,GAAG,uCAAuC,IAAI,qBAAqB,EAAE;KACtE,CAAC;IACF,MAAM,WAAW,GAAG,qBAAqB,gBAAgB,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;IAE1G,wEAAwE;IACxE,MAAM,WAAW,GAAG,QAAQ,IAAI,UAAU,CAAC;IAC3C,MAAM,WAAW,GAAG,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,iBAAiB,UAAU,KAAK,CAAC;IACrE,kFAAkF;IAClF,MAAM,UAAU,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,aAAa,IAAI,CAAC,SAAS,CAAC,GAAG,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,SAAS,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAEnJ,MAAM,OAAO,GAAG;;;IAGd,WAAW;aACF,SAAS;sBACA,WAAW;;EAE/B,WAAW;EACX,KAAK;;UAEG,WAAW,qBAAqB,UAAU;EAClD,WAAW,EAAE,CAAC;IAEd,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,oBAAoB,CAAC,CAAC;IAChE,EAAE,CAAC,aAAa,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;IACvC,OAAO,WAAW,CAAC;AACrB,CAAC,CAAC","sourcesContent":["import { Nullable } from '@qpqjs/core';\n\nimport fs from 'fs';\nimport path from 'path';\n\nimport { DEV_SERVER_PUBLIC_FILE_STORAGE_PORT_ENV, DEV_SERVER_PUBLIC_HOST_ENV } from '../../lib/devServerEntry';\nimport { Mount } from './parseMounts';\nimport { PortMapping } from './parsePortMappings';\n\nexport type ComposeFileOptions = {\n contextDir: string;\n imageName: string;\n serviceName: string;\n volumeName: string;\n portMappings: PortMapping[];\n // Host directory for the app's state; null keeps it in the named volume.\n dataPath: Nullable<string>;\n // Host folders the app reads or writes beyond its state.\n mounts: Mount[];\n // The address browsers use for the host; null leaves secure file urls on localhost.\n publicHost: Nullable<string>;\n // Host-side port of the file storage listener, for the secure urls it hands out.\n publicFileStoragePort: number;\n};\n\n/**\n * A docker-compose.yml for running the image on any docker host: the image, the port mappings\n * the frontend was built for, the public host, where the app's state lives, and any other host\n * folders mounted into it. Returns its path.\n */\nexport const writeComposeFile = ({\n contextDir,\n imageName,\n serviceName,\n volumeName,\n portMappings,\n dataPath,\n mounts,\n publicHost,\n publicFileStoragePort,\n}: ComposeFileOptions): string => {\n const ports = portMappings.map((mapping) => ` - \"${mapping.host}:${mapping.container}\"`).join('\\n');\n\n const environmentLines = [\n ...(publicHost ? [`${DEV_SERVER_PUBLIC_HOST_ENV}=${publicHost}`] : []),\n `${DEV_SERVER_PUBLIC_FILE_STORAGE_PORT_ENV}=${publicFileStoragePort}`,\n ];\n const environment = ` environment:\\n${environmentLines.map((line) => ` - ${line}`).join('\\n')}\\n`;\n\n // All app state (key-value stores, file storage) is this one directory.\n const stateSource = dataPath ?? volumeName;\n const namedVolume = dataPath ? '' : `\\nvolumes:\\n ${volumeName}:\\n`;\n // Quoted (a JSON string is a valid YAML one), since host folders can hold spaces.\n const mountLines = mounts.map((mount) => `\\n - ${JSON.stringify(`${mount.host}:${mount.container}${mount.readOnly ? ':ro' : ''}`)}`).join('');\n\n const compose = `# Generated by qpq go from deploy.config.json. Host ports are baked into the frontend, so\n# change them there and rebuild rather than here.\nservices:\n ${serviceName}:\n image: ${imageName}\n container_name: ${serviceName}\n restart: unless-stopped\n${environment} ports:\n${ports}\n volumes:\n - ${stateSource}:/app/.qpq-runtime${mountLines}\n${namedVolume}`;\n\n const composePath = path.join(contextDir, 'docker-compose.yml');\n fs.writeFileSync(composePath, compose);\n return composePath;\n};\n"]}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { awsPlatformDriver } from './aws';
|
|
2
|
+
import { dockerPlatformDriver } from './docker';
|
|
3
|
+
import { QpqDeployPlatform } from './types';
|
|
4
|
+
const platformDrivers = {
|
|
5
|
+
[QpqDeployPlatform.aws]: awsPlatformDriver,
|
|
6
|
+
[QpqDeployPlatform.docker]: dockerPlatformDriver,
|
|
7
|
+
};
|
|
8
|
+
export const getPlatformDriver = (platform) => {
|
|
9
|
+
const driver = platformDrivers[platform];
|
|
10
|
+
if (!driver) {
|
|
11
|
+
console.error(`Unknown deploy platform '${platform}'. Supported platforms: ${Object.keys(platformDrivers).join(', ')}`);
|
|
12
|
+
process.exit(1);
|
|
13
|
+
}
|
|
14
|
+
return driver;
|
|
15
|
+
};
|
|
16
|
+
export * from './types';
|
|
17
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/platforms/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,OAAO,CAAC;AAC1C,OAAO,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AAChD,OAAO,EAAE,iBAAiB,EAAqB,MAAM,SAAS,CAAC;AAE/D,MAAM,eAAe,GAAsC;IACzD,CAAC,iBAAiB,CAAC,GAAG,CAAC,EAAE,iBAAiB;IAC1C,CAAC,iBAAiB,CAAC,MAAM,CAAC,EAAE,oBAAoB;CACjD,CAAC;AAEF,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,OAAO,CAAC,KAAK,CAAC,4BAA4B,QAAQ,2BAA2B,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACxH,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC,CAAC;AAEF,cAAc,SAAS,CAAC","sourcesContent":["import { awsPlatformDriver } from './aws';\nimport { dockerPlatformDriver } from './docker';\nimport { QpqDeployPlatform, QpqPlatformDriver } from './types';\n\nconst platformDrivers: Record<string, QpqPlatformDriver> = {\n [QpqDeployPlatform.aws]: awsPlatformDriver,\n [QpqDeployPlatform.docker]: dockerPlatformDriver,\n};\n\nexport const getPlatformDriver = (platform: string): QpqPlatformDriver => {\n const driver = platformDrivers[platform];\n\n if (!driver) {\n console.error(`Unknown deploy platform '${platform}'. Supported platforms: ${Object.keys(platformDrivers).join(', ')}`);\n process.exit(1);\n }\n\n return driver;\n};\n\nexport * from './types';\n"]}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { QpqAppDeployment } from '@qpqjs/core';
|
|
2
|
+
import { ClearResourcesPlan } from '../lib/clearResourcesPlan';
|
|
3
|
+
import { DeployPlan, TeardownPlan } from '../lib/deployPrompts';
|
|
4
|
+
import { GoDockerMode } from '../lib/goDockerMode';
|
|
5
|
+
import { SetupStep } from '../lib/setupStep';
|
|
6
|
+
export declare enum QpqDeployPlatform {
|
|
7
|
+
aws = "aws",
|
|
8
|
+
docker = "docker"
|
|
9
|
+
}
|
|
10
|
+
export interface QpqPlatformDriver {
|
|
11
|
+
prepareDeployment: (deploymentName: string, deployment: QpqAppDeployment) => void;
|
|
12
|
+
go: (appName: string, plan: DeployPlan) => Promise<void>;
|
|
13
|
+
goDocker?: (appName: string, plan: DeployPlan, mode: GoDockerMode) => Promise<void>;
|
|
14
|
+
teardown?: (appName: string, plan: TeardownPlan) => Promise<void>;
|
|
15
|
+
clearResources?: (appName: string, plan: ClearResourcesPlan) => Promise<void>;
|
|
16
|
+
setupSteps?: (appName: string, deploymentName: string) => Promise<SetupStep[]>;
|
|
17
|
+
publish: (appName: string, serviceNames: string[]) => Promise<void>;
|
|
18
|
+
publishBuild: (appName: string, serviceNames: string[]) => Promise<void>;
|
|
19
|
+
publishUpload: (appName: string, serviceNames: string[]) => Promise<void>;
|
|
20
|
+
publishDeploy: (appName: string, serviceNames: string[]) => Promise<void>;
|
|
21
|
+
}
|