@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 +1 @@
|
|
|
1
|
-
{"version":3,"file":"synth.js","sourceRoot":"","sources":["../../../src/commands/synth.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"synth.js","sourceRoot":"","sources":["../../../src/commands/synth.ts"],"names":[],"mappings":"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","sourcesContent":["// `qpq synth [service]`, synthesizes each backend service's QPQ config to\n// dist/apps/<app>/infrastructure/<module>-config.json.\n//\n// Runs with ts-node hooks registered (see runCli), which transpiles each\n// service's infrastructure.ts on require. Cross-package `@scope/*` imports\n// resolve through the workspace node_modules symlinks to already-built dist.\nimport { getInfrastructureConfigPath, qpqCoreUtils, QpqDeployEnvVar } from '@qpqjs/core';\n\nimport fs from 'fs';\nimport path from 'path';\n\nimport { getPositionalArgs } from '../lib/args';\nimport { createOutput } from '../lib/createOutput';\nimport { getAvailableApps, getRoot, getServiceNamesWithSubdir } from '../lib/discovery';\nimport { loadServiceQpqConfig } from '../lib/qpqConfigs';\nimport { getRequestedAppName, resolveAppSelection } from '../lib/resolveAppSelection';\nimport { resolveDeployment } from '../lib/resolveDeployment';\n\nconst out = createOutput('synth');\n\nconst processConfig = (folderName: string, appName: string): void => {\n out.log(`Processing infrastructure: [${folderName}] for app [${appName}]`);\n const qpqConfig = loadServiceQpqConfig(appName, folderName);\n const moduleName = qpqCoreUtils.getApplicationModuleName(qpqConfig);\n\n const directoryPath = getInfrastructureConfigPath(getRoot(), appName);\n fs.mkdirSync(directoryPath, { recursive: true });\n fs.writeFileSync(path.join(directoryPath, `${moduleName}-config.json`), JSON.stringify(qpqConfig, null, 2));\n out.log(` -> ${appName}/infrastructure/${moduleName}-config.json`);\n};\n\nexport const synthCommand = async (argv: string[]): Promise<void> => {\n const [specifiedServiceName] = getPositionalArgs(argv, ['--app', '--deployment']);\n\n let appNames: string[];\n if (specifiedServiceName && !getRequestedAppName(argv, QpqDeployEnvVar.deployAppName)) {\n // A bare service name is unambiguous, synth it in whichever app owns it.\n const appWithService = getAvailableApps().find((appName) => getServiceNamesWithSubdir(appName, 'service').includes(specifiedServiceName));\n if (!appWithService) {\n out.error(`Service '${specifiedServiceName}' not found in any app`);\n process.exit(1);\n }\n appNames = [appWithService];\n } else {\n const selection = await resolveAppSelection({ argv, envVar: QpqDeployEnvVar.deployAppName, allowAll: true });\n appNames = selection === 'all' ? getAvailableApps() : [selection];\n }\n\n out.log(`QPQ synthesizing apps: ${appNames.join(', ')}`);\n\n for (const appName of appNames) {\n // Service configs read the deployment env vars at require time, so the\n // deployment is resolved (and primed) before any infrastructure.ts loads.\n await resolveDeployment(argv, appName);\n\n // Validate a specified service against the app's discovered services before it\n // reaches loadServiceQpqConfig -> require, exactly as the bare-service-name branch\n // above does: an unchecked typo hits a cryptic module-resolution error and a `../`\n // value normalizes into an arbitrary require target.\n const appServices = getServiceNamesWithSubdir(appName, 'service');\n if (specifiedServiceName && !appServices.includes(specifiedServiceName)) {\n out.error(`Service '${specifiedServiceName}' not found in app '${appName}'`);\n process.exitCode = 1;\n continue;\n }\n\n const serviceNames = specifiedServiceName ? [specifiedServiceName] : appServices;\n\n for (const folderName of serviceNames) {\n try {\n processConfig(folderName, appName);\n } catch (error) {\n out.error(`Failed to process ${folderName} in ${appName}:`, error);\n process.exitCode = 1;\n }\n }\n }\n};\n"]}
|
|
@@ -1,20 +1,14 @@
|
|
|
1
|
-
// `qpq teardown
|
|
1
|
+
// `qpq teardown`, interactive destroy, the counterpart of `qpq go`. Resolves
|
|
2
2
|
// the app + deployment the same way, asks which services to tear down (with
|
|
3
|
-
// a typed confirmation
|
|
3
|
+
// a typed confirmation, this deletes stored data), then hands off to the
|
|
4
4
|
// platform driver to destroy the web, api and inf stacks in that order.
|
|
5
5
|
import { promptTeardownPlan } from '../lib/deployPrompts';
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import { getPlatformDriver } from '../platforms';
|
|
6
|
+
import { requireDriverCapability } from '../lib/requireDriverCapability';
|
|
7
|
+
import { resolveCommandContext } from '../lib/resolveCommandContext';
|
|
9
8
|
export const teardownCommand = async (argv) => {
|
|
10
|
-
const
|
|
11
|
-
const
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
console.error(`The '${deployment.platform}' platform has no teardown strategy.`);
|
|
15
|
-
process.exit(1);
|
|
16
|
-
}
|
|
17
|
-
const plan = await promptTeardownPlan(appName);
|
|
18
|
-
await driver.teardown(appName, plan);
|
|
9
|
+
const context = await resolveCommandContext(argv);
|
|
10
|
+
const teardown = requireDriverCapability(context, 'teardown');
|
|
11
|
+
const plan = await promptTeardownPlan(context.appName);
|
|
12
|
+
await teardown(context.appName, plan);
|
|
19
13
|
};
|
|
20
14
|
//# sourceMappingURL=teardown.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"teardown.js","sourceRoot":"","sources":["../../../src/commands/teardown.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"teardown.js","sourceRoot":"","sources":["../../../src/commands/teardown.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,4EAA4E;AAC5E,yEAAyE;AACzE,wEAAwE;AACxE,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,uBAAuB,EAAE,MAAM,gCAAgC,CAAC;AACzE,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AAErE,MAAM,CAAC,MAAM,eAAe,GAAG,KAAK,EAAE,IAAc,EAAiB,EAAE;IACrE,MAAM,OAAO,GAAG,MAAM,qBAAqB,CAAC,IAAI,CAAC,CAAC;IAClD,MAAM,QAAQ,GAAG,uBAAuB,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;IAE9D,MAAM,IAAI,GAAG,MAAM,kBAAkB,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IAEvD,MAAM,QAAQ,CAAC,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;AACxC,CAAC,CAAC","sourcesContent":["// `qpq teardown`, interactive destroy, the counterpart of `qpq go`. Resolves\n// the app + deployment the same way, asks which services to tear down (with\n// a typed confirmation, this deletes stored data), then hands off to the\n// platform driver to destroy the web, api and inf stacks in that order.\nimport { promptTeardownPlan } from '../lib/deployPrompts';\nimport { requireDriverCapability } from '../lib/requireDriverCapability';\nimport { resolveCommandContext } from '../lib/resolveCommandContext';\n\nexport const teardownCommand = async (argv: string[]): Promise<void> => {\n const context = await resolveCommandContext(argv);\n const teardown = requireDriverCapability(context, 'teardown');\n\n const plan = await promptTeardownPlan(context.appName);\n\n await teardown(context.appName, plan);\n};\n"]}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// A failure the command layer turns into an exit code and one line of output. Library code
|
|
2
|
+
// throws this instead of printing and exiting itself, so it stays usable from anywhere.
|
|
3
|
+
export class CliError extends Error {
|
|
4
|
+
exitCode;
|
|
5
|
+
constructor(message, exitCode = 1) {
|
|
6
|
+
super(message);
|
|
7
|
+
this.name = 'CliError';
|
|
8
|
+
this.exitCode = exitCode;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=CliError.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CliError.js","sourceRoot":"","sources":["../../../src/lib/CliError.ts"],"names":[],"mappings":"AAAA,2FAA2F;AAC3F,wFAAwF;AACxF,MAAM,OAAO,QAAS,SAAQ,KAAK;IACxB,QAAQ,CAAS;IAE1B,YAAY,OAAe,EAAE,WAAmB,CAAC;QAC/C,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,UAAU,CAAC;QACvB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC3B,CAAC;CACF","sourcesContent":["// A failure the command layer turns into an exit code and one line of output. Library code\n// throws this instead of printing and exiting itself, so it stays usable from anywhere.\nexport class CliError extends Error {\n readonly exitCode: number;\n\n constructor(message: string, exitCode: number = 1) {\n super(message);\n this.name = 'CliError';\n this.exitCode = exitCode;\n }\n}\n"]}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
type Print = (...parts: unknown[]) => void;
|
|
2
|
+
/** The prefixed console every cli command prints through. */
|
|
3
|
+
export type Output = {
|
|
4
|
+
log: Print;
|
|
5
|
+
info: Print;
|
|
6
|
+
warn: Print;
|
|
7
|
+
error: Print;
|
|
8
|
+
time: (label: string) => void;
|
|
9
|
+
timeEnd: (label: string) => void;
|
|
10
|
+
rewriteLineAbove: (linesUp: number, text: string) => void;
|
|
11
|
+
};
|
|
12
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Output.js","sourceRoot":"","sources":["../../../src/lib/Output.ts"],"names":[],"mappings":"","sourcesContent":["type Print = (...parts: unknown[]) => void;\n\n/** The prefixed console every cli command prints through. */\nexport type Output = {\n log: Print;\n info: Print;\n warn: Print;\n error: Print;\n // A named stopwatch, printed on end.\n time: (label: string) => void;\n timeEnd: (label: string) => void;\n // Rewrites a line printed `linesUp` rows above the cursor in place (a status chip appended to a row that is\n // already on screen), prefixed like every other line. Terminal only: the caller falls back to a plain line otherwise.\n rewriteLineAbove: (linesUp: number, text: string) => void;\n};\n"]}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
// flows like `npm run validate-ts` with no bundling.
|
|
6
6
|
//
|
|
7
7
|
// Scope: each workspace's src, relative imports. Cross-package cycles are
|
|
8
|
-
// already impossible
|
|
8
|
+
// already impossible, TypeScript project references refuse to build them, so
|
|
9
9
|
// every runtime-relevant cycle lives inside one package's src. Type-only
|
|
10
10
|
// imports are skipped (skipTypeImports): tsc erases them, so they never create
|
|
11
11
|
// a runtime cycle.
|
|
@@ -14,7 +14,7 @@ import path from 'path';
|
|
|
14
14
|
// madge ships no type definitions; declare the narrow slice we use.
|
|
15
15
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
16
16
|
const madge = require('madge');
|
|
17
|
-
// Expand npm workspace globs (plain path segments and `*` segments only
|
|
17
|
+
// Expand npm workspace globs (plain path segments and `*` segments only, the
|
|
18
18
|
// only forms npm workspaces use in practice) into existing directories.
|
|
19
19
|
const expandWorkspaceGlob = (root, pattern) => {
|
|
20
20
|
let candidates = [root];
|
|
@@ -33,7 +33,7 @@ const expandWorkspaceGlob = (root, pattern) => {
|
|
|
33
33
|
}
|
|
34
34
|
return candidates.filter((dir) => fs.existsSync(dir) && fs.statSync(dir).isDirectory());
|
|
35
35
|
};
|
|
36
|
-
|
|
36
|
+
const getWorkspaceDirectories = (root) => {
|
|
37
37
|
const packageJson = JSON.parse(fs.readFileSync(path.join(root, 'package.json'), 'utf8'));
|
|
38
38
|
const patterns = packageJson.workspaces ?? [];
|
|
39
39
|
return patterns.flatMap((pattern) => expandWorkspaceGlob(root, pattern));
|
|
@@ -44,7 +44,7 @@ export const findWorkspaceImportCycles = async (root) => {
|
|
|
44
44
|
.filter((dir) => fs.existsSync(dir));
|
|
45
45
|
// Excludes: node_modules and built output (dist/lib), declaration files
|
|
46
46
|
// (type-only, can't cycle at runtime), and anything madge resolves to outside
|
|
47
|
-
// the repo root (linked framework packages
|
|
47
|
+
// the repo root (linked framework packages, their cycles surface through the
|
|
48
48
|
// rspack CircularCheckRspackPlugin instead, this command owns the consumer
|
|
49
49
|
// repo). Out-of-root paths start with '..' because baseDir is the repo root.
|
|
50
50
|
const result = await madge(sourceDirs, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"circularImports.js","sourceRoot":"","sources":["../../../src/lib/circularImports.ts"],"names":[],"mappings":"AAAA,sEAAsE;AACtE,+EAA+E;AAC/E,4EAA4E;AAC5E,8EAA8E;AAC9E,qDAAqD;AACrD,EAAE;AACF,0EAA0E;AAC1E
|
|
1
|
+
{"version":3,"file":"circularImports.js","sourceRoot":"","sources":["../../../src/lib/circularImports.ts"],"names":[],"mappings":"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","sourcesContent":["// Source-level circular import detection over the consumer repo's npm\n// workspaces, powered by madge (AST-based dependency graph + cycle detection).\n// Complements the rspack CircularCheckRspackPlugin (which needs a bundle to\n// run): this scans TypeScript sources directly, so it can run inside tsc-only\n// flows like `npm run validate-ts` with no bundling.\n//\n// Scope: each workspace's src, relative imports. Cross-package cycles are\n// already impossible, TypeScript project references refuse to build them, so\n// every runtime-relevant cycle lives inside one package's src. Type-only\n// imports are skipped (skipTypeImports): tsc erases them, so they never create\n// a runtime cycle.\nimport fs from 'fs';\nimport path from 'path';\n\n// madge ships no type definitions; declare the narrow slice we use.\n// eslint-disable-next-line @typescript-eslint/no-require-imports\nconst madge = require('madge') as (paths: string[], config: object) => Promise<{ circular(): string[][] }>;\n\nexport type ImportCycle = string[];\n\n// Expand npm workspace globs (plain path segments and `*` segments only, the\n// only forms npm workspaces use in practice) into existing directories.\nconst expandWorkspaceGlob = (root: string, pattern: string): string[] => {\n let candidates = [root];\n\n for (const segment of pattern.split('/')) {\n if (segment === '*') {\n candidates = candidates.flatMap((dir) =>\n fs.existsSync(dir)\n ? fs\n .readdirSync(dir, { withFileTypes: true })\n .filter((entry) => entry.isDirectory())\n .map((entry) => path.join(dir, entry.name))\n : [],\n );\n } else {\n candidates = candidates.map((dir) => path.join(dir, segment));\n }\n }\n\n return candidates.filter((dir) => fs.existsSync(dir) && fs.statSync(dir).isDirectory());\n};\n\nconst getWorkspaceDirectories = (root: string): string[] => {\n const packageJson = JSON.parse(fs.readFileSync(path.join(root, 'package.json'), 'utf8'));\n const patterns: string[] = packageJson.workspaces ?? [];\n return patterns.flatMap((pattern) => expandWorkspaceGlob(root, pattern));\n};\n\nexport const findWorkspaceImportCycles = async (root: string): Promise<ImportCycle[]> => {\n const sourceDirs = getWorkspaceDirectories(root)\n .map((dir) => path.join(dir, 'src'))\n .filter((dir) => fs.existsSync(dir));\n\n // Excludes: node_modules and built output (dist/lib), declaration files\n // (type-only, can't cycle at runtime), and anything madge resolves to outside\n // the repo root (linked framework packages, their cycles surface through the\n // rspack CircularCheckRspackPlugin instead, this command owns the consumer\n // repo). Out-of-root paths start with '..' because baseDir is the repo root.\n const result = await madge(sourceDirs, {\n baseDir: root,\n fileExtensions: ['ts', 'tsx'],\n excludeRegExp: [/node_modules/, /(^|\\/)(dist|lib)\\//, /\\.d\\.ts$/, /^\\.\\./],\n detectiveOptions: {\n ts: { skipTypeImports: true },\n tsx: { skipTypeImports: true },\n },\n });\n\n return result.circular();\n};\n"]}
|
|
@@ -11,5 +11,4 @@ export type ClearResourcesPlan = {
|
|
|
11
11
|
appName: string;
|
|
12
12
|
resources: ClearableResource[];
|
|
13
13
|
};
|
|
14
|
-
export declare const getClearableResources: (appName: string) => ClearableResource[];
|
|
15
14
|
export declare const promptClearResourcesPlan: (appName: string) => Promise<ClearResourcesPlan>;
|
|
@@ -6,19 +6,21 @@
|
|
|
6
6
|
// table every service declares against one owner) appears exactly once, on
|
|
7
7
|
// the service that owns it.
|
|
8
8
|
import { qpqCoreUtils } from '@qpqjs/core';
|
|
9
|
+
import { createOutput } from './createOutput';
|
|
9
10
|
import { getServiceNames } from './discovery';
|
|
10
|
-
import { promptCheckbox, promptSelect, promptText } from './prompts';
|
|
11
|
-
import { loadServiceQpqConfig } from './qpqConfigs';
|
|
12
11
|
import { getDeployTargetLabel } from './getDeployTargetLabel';
|
|
12
|
+
import { promptCheckbox, promptSelect, promptTypedConfirmation } from './prompts';
|
|
13
|
+
import { loadServiceQpqConfig } from './qpqConfigs';
|
|
14
|
+
const out = createOutput('clear-resources-plan');
|
|
13
15
|
// Every owned data resource across the app's services, in service order.
|
|
14
|
-
|
|
16
|
+
const getClearableResources = (appName) => {
|
|
15
17
|
const resources = [];
|
|
16
18
|
for (const service of getServiceNames(appName)) {
|
|
17
19
|
const qpqConfig = loadServiceQpqConfig(appName, service);
|
|
18
|
-
for (const drive of qpqCoreUtils.
|
|
20
|
+
for (const drive of qpqCoreUtils.getOwnedStorageDriveConfigs(qpqConfig)) {
|
|
19
21
|
resources.push({ service, kind: 'storageDrive', resourceName: drive.storageDrive });
|
|
20
22
|
}
|
|
21
|
-
for (const store of qpqCoreUtils.
|
|
23
|
+
for (const store of qpqCoreUtils.getOwnedKeyValueStoreConfigs(qpqConfig)) {
|
|
22
24
|
resources.push({ service, kind: 'keyValueStore', resourceName: store.keyValueStoreName });
|
|
23
25
|
}
|
|
24
26
|
}
|
|
@@ -42,22 +44,20 @@ export const promptClearResourcesPlan = async (appName) => {
|
|
|
42
44
|
const deployInfo = getDeployTargetLabel();
|
|
43
45
|
const clearable = getClearableResources(appName);
|
|
44
46
|
if (clearable.length === 0) {
|
|
45
|
-
|
|
47
|
+
out.log('No storage drives or key value stores found in this app.');
|
|
46
48
|
return { kind: 'cancelled' };
|
|
47
49
|
}
|
|
48
50
|
const mode = await promptSelect('How do you want to select what to empty?', [BY_SERVICE, BY_RESOURCE]);
|
|
49
51
|
const resources = mode === BY_SERVICE ? await pickByService(clearable) : await pickByResource(clearable);
|
|
50
52
|
if (resources.length === 0) {
|
|
51
|
-
|
|
53
|
+
out.log('Nothing selected. Exiting!');
|
|
52
54
|
return { kind: 'cancelled' };
|
|
53
55
|
}
|
|
54
|
-
|
|
56
|
+
out.log(`\nThis will EMPTY (delete all stored data from) ${resources.length} resource(s) in [${deployInfo}]:`);
|
|
55
57
|
for (const resource of resources) {
|
|
56
|
-
|
|
58
|
+
out.log(` ${resource.service} — ${resource.resourceName} (${resource.kind === 'storageDrive' ? 'bucket' : 'table'})`);
|
|
57
59
|
}
|
|
58
|
-
|
|
59
|
-
if (confirmation !== deployInfo) {
|
|
60
|
-
console.log('Confirmation did not match. Exiting!');
|
|
60
|
+
if (!(await promptTypedConfirmation(deployInfo))) {
|
|
61
61
|
return { kind: 'cancelled' };
|
|
62
62
|
}
|
|
63
63
|
return { kind: 'resources', appName, resources };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"clearResourcesPlan.js","sourceRoot":"","sources":["../../../src/lib/clearResourcesPlan.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,8EAA8E;AAC9E,yEAAyE;AACzE,yEAAyE;AACzE,6EAA6E;AAC7E,2EAA2E;AAC3E,4BAA4B;AAC5B,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,
|
|
1
|
+
{"version":3,"file":"clearResourcesPlan.js","sourceRoot":"","sources":["../../../src/lib/clearResourcesPlan.ts"],"names":[],"mappings":"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","sourcesContent":["// The question flow for `qpq clear-resources`: enumerate every service's OWNED\n// data resources (storage drives -> buckets, key value stores -> tables) from\n// its live qpq config, multi-select which to empty, then type the deploy\n// target back to confirm - emptying deletes stored data, so a y/n prompt\n// isn't enough friction. Owned-only so a cross-module ref (e.g. a membership\n// table every service declares against one owner) appears exactly once, on\n// the service that owns it.\nimport { qpqCoreUtils } from '@qpqjs/core';\n\nimport { createOutput } from './createOutput';\nimport { getServiceNames } from './discovery';\nimport { getDeployTargetLabel } from './getDeployTargetLabel';\nimport { promptCheckbox, promptSelect, promptTypedConfirmation } from './prompts';\nimport { loadServiceQpqConfig } from './qpqConfigs';\n\nconst out = createOutput('clear-resources-plan');\n\nexport type ClearableResourceKind = 'storageDrive' | 'keyValueStore';\n\nexport type ClearableResource = {\n service: string;\n kind: ClearableResourceKind;\n // The config-level resource name (e.g. 'templateTestAssets', 'userTenantLinks');\n // the platform driver resolves it to the concrete runtime name (bucket/table).\n resourceName: string;\n};\n\nexport type ClearResourcesPlan =\n | { kind: 'cancelled' }\n // Empty (not destroy) the selected resources' stored data.\n | { kind: 'resources'; appName: string; resources: ClearableResource[] };\n\n// Every owned data resource across the app's services, in service order.\nconst getClearableResources = (appName: string): ClearableResource[] => {\n const resources: ClearableResource[] = [];\n\n for (const service of getServiceNames(appName)) {\n const qpqConfig = loadServiceQpqConfig(appName, service);\n\n for (const drive of qpqCoreUtils.getOwnedStorageDriveConfigs(qpqConfig)) {\n resources.push({ service, kind: 'storageDrive', resourceName: drive.storageDrive });\n }\n\n for (const store of qpqCoreUtils.getOwnedKeyValueStoreConfigs(qpqConfig)) {\n resources.push({ service, kind: 'keyValueStore', resourceName: store.keyValueStoreName });\n }\n }\n\n return resources;\n};\n\nconst BY_SERVICE = 'By service — empty everything the selected services own';\nconst BY_RESOURCE = 'By resource — pick individual buckets/tables';\n\n// Service mode: pick services, take every resource each one owns.\nconst pickByService = async (clearable: ClearableResource[]): Promise<ClearableResource[]> => {\n const services = [...new Set(clearable.map((resource) => resource.service))];\n\n const countFor = (service: string) => clearable.filter((resource) => resource.service === service).length;\n\n const picked = await promptCheckbox(\n 'Select services to EMPTY (every bucket/table the service owns)',\n services.map((service) => ({ name: `${service} (${countFor(service)} resources)`, value: service })),\n );\n\n return clearable.filter((resource) => picked.includes(resource.service));\n};\n\n// Resource mode: pick individual buckets/tables.\nconst pickByResource = (clearable: ClearableResource[]): Promise<ClearableResource[]> =>\n promptCheckbox(\n 'Select resources to EMPTY (all stored data will be deleted)',\n clearable.map((resource) => ({\n name: `${resource.service} — ${resource.resourceName} (${resource.kind === 'storageDrive' ? 'bucket' : 'table'})`,\n value: resource,\n })),\n );\n\nexport const promptClearResourcesPlan = async (appName: string): Promise<ClearResourcesPlan> => {\n const deployInfo = getDeployTargetLabel();\n\n const clearable = getClearableResources(appName);\n\n if (clearable.length === 0) {\n out.log('No storage drives or key value stores found in this app.');\n return { kind: 'cancelled' };\n }\n\n const mode = await promptSelect('How do you want to select what to empty?', [BY_SERVICE, BY_RESOURCE]);\n\n const resources = mode === BY_SERVICE ? await pickByService(clearable) : await pickByResource(clearable);\n\n if (resources.length === 0) {\n out.log('Nothing selected. Exiting!');\n return { kind: 'cancelled' };\n }\n\n out.log(`\\nThis will EMPTY (delete all stored data from) ${resources.length} resource(s) in [${deployInfo}]:`);\n for (const resource of resources) {\n out.log(` ${resource.service} — ${resource.resourceName} (${resource.kind === 'storageDrive' ? 'bucket' : 'table'})`);\n }\n\n if (!(await promptTypedConfirmation(deployInfo))) {\n return { kind: 'cancelled' };\n }\n\n return { kind: 'resources', appName, resources };\n};\n"]}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
// Every line the cli prints carries `[qpq:<area>]`, so output from the concurrent and nested
|
|
2
|
+
// commands reads as one program. This is the only place the cli touches the console.
|
|
3
|
+
export const createOutput = (area) => {
|
|
4
|
+
const prefix = `[qpq:${area}]`;
|
|
5
|
+
// Every line of a leading string gets the prefix, and a blank line stays blank, so a message with leading or
|
|
6
|
+
// embedded newlines reads as prefixed lines rather than a lone prefix followed by bare text.
|
|
7
|
+
const prefixLines = (text) => text
|
|
8
|
+
.split('\n')
|
|
9
|
+
.map((line) => (line === '' ? '' : `${prefix} ${line}`))
|
|
10
|
+
.join('\n');
|
|
11
|
+
// A leading string is prefixed line by line; anything else (an error, an object) is printed
|
|
12
|
+
// after the prefix as its own argument so the console keeps formatting it. The console method is
|
|
13
|
+
// looked up per call, not captured, so a test can spy on it after this module loads.
|
|
14
|
+
const withPrefix = (method) => {
|
|
15
|
+
return (...parts) => {
|
|
16
|
+
const [first, ...rest] = parts;
|
|
17
|
+
if (typeof first === 'string') {
|
|
18
|
+
return console[method](prefixLines(first), ...rest);
|
|
19
|
+
}
|
|
20
|
+
return console[method](prefix, ...parts);
|
|
21
|
+
};
|
|
22
|
+
};
|
|
23
|
+
return {
|
|
24
|
+
log: withPrefix('log'),
|
|
25
|
+
info: withPrefix('info'),
|
|
26
|
+
warn: withPrefix('warn'),
|
|
27
|
+
error: withPrefix('error'),
|
|
28
|
+
time: (label) => console.time(`${prefix} ${label}`),
|
|
29
|
+
timeEnd: (label) => console.timeEnd(`${prefix} ${label}`),
|
|
30
|
+
rewriteLineAbove: (linesUp, text) => {
|
|
31
|
+
process.stdout.write(`\x1b[${linesUp}F\x1b[2K${prefixLines(text)}\x1b[${linesUp}E`);
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
};
|
|
35
|
+
//# sourceMappingURL=createOutput.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createOutput.js","sourceRoot":"","sources":["../../../src/lib/createOutput.ts"],"names":[],"mappings":"AAEA,6FAA6F;AAC7F,qFAAqF;AACrF,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,IAAY,EAAU,EAAE;IACnD,MAAM,MAAM,GAAG,QAAQ,IAAI,GAAG,CAAC;IAE/B,6GAA6G;IAC7G,6FAA6F;IAC7F,MAAM,WAAW,GAAG,CAAC,IAAY,EAAU,EAAE,CAC3C,IAAI;SACD,KAAK,CAAC,IAAI,CAAC;SACX,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI,IAAI,EAAE,CAAC,CAAC;SACvD,IAAI,CAAC,IAAI,CAAC,CAAC;IAEhB,4FAA4F;IAC5F,iGAAiG;IACjG,qFAAqF;IACrF,MAAM,UAAU,GAAG,CAAC,MAAyC,EAAyB,EAAE;QACtF,OAAO,CAAC,GAAG,KAAK,EAAE,EAAE;YAClB,MAAM,CAAC,KAAK,EAAE,GAAG,IAAI,CAAC,GAAG,KAAK,CAAC;YAE/B,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;gBAC9B,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC,WAAW,CAAC,KAAK,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC;YACtD,CAAC;YAED,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,GAAG,KAAK,CAAC,CAAC;QAC3C,CAAC,CAAC;IACJ,CAAC,CAAC;IAEF,OAAO;QACL,GAAG,EAAE,UAAU,CAAC,KAAK,CAAC;QACtB,IAAI,EAAE,UAAU,CAAC,MAAM,CAAC;QACxB,IAAI,EAAE,UAAU,CAAC,MAAM,CAAC;QACxB,KAAK,EAAE,UAAU,CAAC,OAAO,CAAC;QAC1B,IAAI,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,MAAM,IAAI,KAAK,EAAE,CAAC;QACnD,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,MAAM,IAAI,KAAK,EAAE,CAAC;QACzD,gBAAgB,EAAE,CAAC,OAAO,EAAE,IAAI,EAAE,EAAE;YAClC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,OAAO,WAAW,WAAW,CAAC,IAAI,CAAC,QAAQ,OAAO,GAAG,CAAC,CAAC;QACtF,CAAC;KACF,CAAC;AACJ,CAAC,CAAC","sourcesContent":["import { Output } from './Output';\n\n// Every line the cli prints carries `[qpq:<area>]`, so output from the concurrent and nested\n// commands reads as one program. This is the only place the cli touches the console.\nexport const createOutput = (area: string): Output => {\n const prefix = `[qpq:${area}]`;\n\n // Every line of a leading string gets the prefix, and a blank line stays blank, so a message with leading or\n // embedded newlines reads as prefixed lines rather than a lone prefix followed by bare text.\n const prefixLines = (text: string): string =>\n text\n .split('\\n')\n .map((line) => (line === '' ? '' : `${prefix} ${line}`))\n .join('\\n');\n\n // A leading string is prefixed line by line; anything else (an error, an object) is printed\n // after the prefix as its own argument so the console keeps formatting it. The console method is\n // looked up per call, not captured, so a test can spy on it after this module loads.\n const withPrefix = (method: 'log' | 'info' | 'warn' | 'error'): Output[typeof method] => {\n return (...parts) => {\n const [first, ...rest] = parts;\n\n if (typeof first === 'string') {\n return console[method](prefixLines(first), ...rest);\n }\n\n return console[method](prefix, ...parts);\n };\n };\n\n return {\n log: withPrefix('log'),\n info: withPrefix('info'),\n warn: withPrefix('warn'),\n error: withPrefix('error'),\n time: (label) => console.time(`${prefix} ${label}`),\n timeEnd: (label) => console.timeEnd(`${prefix} ${label}`),\n rewriteLineAbove: (linesUp, text) => {\n process.stdout.write(`\\x1b[${linesUp}F\\x1b[2K${prefixLines(text)}\\x1b[${linesUp}E`);\n },\n };\n};\n"]}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Nullable } from '@qpqjs/core';
|
|
1
2
|
export type StackType = 'all' | 'inf' | 'api' | 'web' | 'views';
|
|
2
3
|
export type DeployPlan = {
|
|
3
4
|
kind: 'cancelled';
|
|
@@ -14,7 +15,7 @@ export type DeployPlan = {
|
|
|
14
15
|
services: string[];
|
|
15
16
|
stacks: StackType;
|
|
16
17
|
};
|
|
17
|
-
export declare const buildDeployPlanFromArgs: (appName: string, argv: string[]) => DeployPlan
|
|
18
|
+
export declare const buildDeployPlanFromArgs: (appName: string, argv: string[]) => Nullable<DeployPlan>;
|
|
18
19
|
export declare const promptDeployPlan: (appName: string) => Promise<DeployPlan>;
|
|
19
20
|
export type TeardownPlan = {
|
|
20
21
|
kind: 'cancelled';
|
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
// The interactive question flow shared by `qpq go` (sequential AWS deploy) and
|
|
2
|
-
// a future dockerized variant: pick an app, confirm the target, pick services
|
|
3
|
-
// (or domain/bootstrap), pick stacks. buildDeployPlanFromArgs is the
|
|
4
|
-
// non-interactive shortcut (`qpq go all all`) that skips every prompt.
|
|
5
1
|
import { getPositionalArgs } from './args';
|
|
6
|
-
import {
|
|
2
|
+
import { CliError } from './CliError';
|
|
3
|
+
import { createOutput } from './createOutput';
|
|
7
4
|
import { getServiceNames } from './discovery';
|
|
8
|
-
import {
|
|
5
|
+
import { getDeployTargetLabel } from './getDeployTargetLabel';
|
|
6
|
+
import { promptSelect, promptTypedConfirmation, promptYesNo } from './prompts';
|
|
7
|
+
const out = createOutput('deploy-prompts');
|
|
9
8
|
const STACK_TYPES = ['all', 'inf', 'api', 'web', 'views'];
|
|
10
9
|
// Non-interactive deploy plan from positional args: `qpq go <services> [stacks]`.
|
|
11
10
|
// services: 'all' | comma-separated service names | 'account' | 'domain' | 'bootstrap'
|
|
@@ -28,23 +27,26 @@ export const buildDeployPlanFromArgs = (appName, argv) => {
|
|
|
28
27
|
return { kind: 'bootstrap', appName, includeDomain: false };
|
|
29
28
|
}
|
|
30
29
|
const allServices = getServiceNames(appName);
|
|
31
|
-
const services = servicesArg === 'all'
|
|
30
|
+
const services = servicesArg === 'all'
|
|
31
|
+
? allServices
|
|
32
|
+
: servicesArg
|
|
33
|
+
.split(',')
|
|
34
|
+
.map((s) => s.trim())
|
|
35
|
+
.filter(Boolean);
|
|
32
36
|
const unknownServices = services.filter((service) => !allServices.includes(service));
|
|
33
37
|
if (unknownServices.length > 0) {
|
|
34
|
-
|
|
35
|
-
process.exit(1);
|
|
38
|
+
throw new CliError(`Unknown service(s): ${unknownServices.join(', ')}. Valid services: ${allServices.join(', ')}`);
|
|
36
39
|
}
|
|
37
40
|
const stacks = (stacksArg ?? 'all');
|
|
38
41
|
if (!STACK_TYPES.includes(stacks)) {
|
|
39
|
-
|
|
40
|
-
process.exit(1);
|
|
42
|
+
throw new CliError(`Unknown stacks '${stacksArg}'. Valid stacks: ${STACK_TYPES.join(', ')}`);
|
|
41
43
|
}
|
|
42
44
|
return { kind: 'services', appName, services: [...new Set(services)], stacks };
|
|
43
45
|
};
|
|
44
46
|
export const promptDeployPlan = async (appName) => {
|
|
45
47
|
const deployInfo = getDeployTargetLabel();
|
|
46
48
|
if (!(await promptYesNo(`Deploying to: [${deployInfo}]`))) {
|
|
47
|
-
|
|
49
|
+
out.log('Exiting!');
|
|
48
50
|
return { kind: 'cancelled' };
|
|
49
51
|
}
|
|
50
52
|
let services = [];
|
|
@@ -76,7 +78,7 @@ export const promptDeployPlan = async (appName) => {
|
|
|
76
78
|
return { kind: 'services', appName, services, stacks };
|
|
77
79
|
};
|
|
78
80
|
// The question flow for `qpq teardown`: pick services, then type the deploy
|
|
79
|
-
// target back to confirm
|
|
81
|
+
// target back to confirm, destroying inf stacks takes user data (key value
|
|
80
82
|
// stores, user directories) with it, so a y/n prompt isn't enough friction.
|
|
81
83
|
export const promptTeardownPlan = async (appName) => {
|
|
82
84
|
const deployInfo = getDeployTargetLabel();
|
|
@@ -92,10 +94,8 @@ export const promptTeardownPlan = async (appName) => {
|
|
|
92
94
|
services.push(service);
|
|
93
95
|
} while (await promptYesNo('Do you want to tear down another service?'));
|
|
94
96
|
services = [...new Set(services)];
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
if (confirmation !== deployInfo) {
|
|
98
|
-
console.log('Confirmation did not match. Exiting!');
|
|
97
|
+
out.log(`\nThis will DESTROY the web, api and inf stacks (including all stored data) for: ${services.join(', ')}`);
|
|
98
|
+
if (!(await promptTypedConfirmation(deployInfo))) {
|
|
99
99
|
return { kind: 'cancelled' };
|
|
100
100
|
}
|
|
101
101
|
return { kind: 'services', appName, services };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"deployPrompts.js","sourceRoot":"","sources":["../../../src/lib/deployPrompts.ts"],"names":[],"mappings":"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","sourcesContent":["// The interactive question flow shared by `qpq go` (sequential AWS deploy) and\n// a future dockerized variant: pick an app, confirm the target, pick services\n// (or domain/bootstrap), pick stacks. buildDeployPlanFromArgs is the\n// non-interactive shortcut (`qpq go all all`) that skips every prompt.\nimport { getPositionalArgs } from './args';\nimport { getDeployTargetLabel } from './getDeployTargetLabel';\nimport { getServiceNames } from './discovery';\nimport { promptSelect, promptText, promptYesNo } from './prompts';\n\nexport type StackType = 'all' | 'inf' | 'api' | 'web' | 'views';\n\nconst STACK_TYPES: StackType[] = ['all', 'inf', 'api', 'web', 'views'];\n\nexport type DeployPlan =\n | { kind: 'cancelled' }\n // Deploy only the account-level guardrails stack (one per AWS account).\n | { kind: 'account'; appName: string }\n // Deploy the bootstrap stack (and optionally the domain stack first).\n | { kind: 'bootstrap'; appName: string; includeDomain: boolean }\n // Deploy the selected stacks for the selected services.\n | {\n kind: 'services';\n appName: string;\n services: string[];\n stacks: StackType;\n };\n\n// Non-interactive deploy plan from positional args: `qpq go <services> [stacks]`.\n// services: 'all' | comma-separated service names | 'account' | 'domain' | 'bootstrap'\n// stacks: all | inf | api | web | views (defaults to 'all')\n// Returns null when no positional services token is given, so callers fall back\n// to the interactive promptDeployPlan. Passing args is an explicit opt-in to a\n// prompt-free deploy, so the \"Deploying to: [env]\" confirmation is skipped too.\nexport const buildDeployPlanFromArgs = (appName: string, argv: string[]): DeployPlan | null => {\n const [servicesArg, stacksArg] = getPositionalArgs(argv, ['--app', '--deployment']);\n\n if (!servicesArg) {\n return null;\n }\n\n if (servicesArg === 'account') {\n return { kind: 'account', appName };\n }\n if (servicesArg === 'domain') {\n return { kind: 'bootstrap', appName, includeDomain: true };\n }\n if (servicesArg === 'bootstrap') {\n return { kind: 'bootstrap', appName, includeDomain: false };\n }\n\n const allServices = getServiceNames(appName);\n const services = servicesArg === 'all' ? allServices : servicesArg.split(',').map((s) => s.trim()).filter(Boolean);\n\n const unknownServices = services.filter((service) => !allServices.includes(service));\n if (unknownServices.length > 0) {\n console.error(`Unknown service(s): ${unknownServices.join(', ')}. Valid services: ${allServices.join(', ')}`);\n process.exit(1);\n }\n\n const stacks = (stacksArg ?? 'all') as StackType;\n if (!STACK_TYPES.includes(stacks)) {\n console.error(`Unknown stacks '${stacksArg}'. Valid stacks: ${STACK_TYPES.join(', ')}`);\n process.exit(1);\n }\n\n return { kind: 'services', appName, services: [...new Set(services)], stacks };\n};\n\nexport const promptDeployPlan = async (appName: string): Promise<DeployPlan> => {\n const deployInfo = getDeployTargetLabel();\n\n if (!(await promptYesNo(`Deploying to: [${deployInfo}]`))) {\n console.log('Exiting!');\n return { kind: 'cancelled' };\n }\n\n let services: string[] = [];\n\n do {\n const allServices = getServiceNames(appName);\n\n // Bracketed so the meta options can't be mistaken for actual services.\n const allText = '[ all ]';\n const accountText = '[ account ]';\n const domainEnvText = '[ domain ]';\n const bootstrapEnvText = '[ bootstrap environment ]';\n\n const service = await promptSelect('Select services to deploy', [allText, ...allServices, accountText, domainEnvText, bootstrapEnvText]);\n\n if (service === allText) {\n services = allServices;\n break;\n }\n if (service === accountText) {\n return { kind: 'account', appName };\n }\n if (service === domainEnvText) {\n return { kind: 'bootstrap', appName, includeDomain: true };\n }\n if (service === bootstrapEnvText) {\n return { kind: 'bootstrap', appName, includeDomain: false };\n }\n\n services.push(service);\n } while (await promptYesNo('Do you want to deploy another service?'));\n\n services = [...new Set(services)];\n\n const stacks = (await promptSelect('Stacks to deploy', ['all', 'inf', 'api', 'web', 'views'])) as StackType;\n\n return { kind: 'services', appName, services, stacks };\n};\n\nexport type TeardownPlan =\n | { kind: 'cancelled' }\n // Destroy the web, api and inf stacks for the selected services.\n | { kind: 'services'; appName: string; services: string[] };\n\n// The question flow for `qpq teardown`: pick services, then type the deploy\n// target back to confirm — destroying inf stacks takes user data (key value\n// stores, user directories) with it, so a y/n prompt isn't enough friction.\nexport const promptTeardownPlan = async (appName: string): Promise<TeardownPlan> => {\n const deployInfo = getDeployTargetLabel();\n\n let services: string[] = [];\n\n do {\n const allServices = getServiceNames(appName);\n const allText = '[ all ]';\n\n const service = await promptSelect('Select services to tear down', [allText, ...allServices]);\n\n if (service === allText) {\n services = allServices;\n break;\n }\n\n services.push(service);\n } while (await promptYesNo('Do you want to tear down another service?'));\n\n services = [...new Set(services)];\n\n console.log(`\\nThis will DESTROY the web, api and inf stacks (including all stored data) for: ${services.join(', ')}`);\n const confirmation = await promptText(`Type '${deployInfo}' to confirm`);\n\n if (confirmation !== deployInfo) {\n console.log('Confirmation did not match. Exiting!');\n return { kind: 'cancelled' };\n }\n\n return { kind: 'services', appName, services };\n};\n"]}
|
|
1
|
+
{"version":3,"file":"deployPrompts.js","sourceRoot":"","sources":["../../../src/lib/deployPrompts.ts"],"names":[],"mappings":"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","sourcesContent":["// The interactive question flow shared by `qpq go` (sequential AWS deploy) and\n// a future dockerized variant: pick an app, confirm the target, pick services\n// (or domain/bootstrap), pick stacks. buildDeployPlanFromArgs is the\n// non-interactive shortcut (`qpq go all all`) that skips every prompt.\nimport { Nullable } from '@qpqjs/core';\n\nimport { getPositionalArgs } from './args';\nimport { CliError } from './CliError';\nimport { createOutput } from './createOutput';\nimport { getServiceNames } from './discovery';\nimport { getDeployTargetLabel } from './getDeployTargetLabel';\nimport { promptSelect, promptTypedConfirmation, promptYesNo } from './prompts';\n\nconst out = createOutput('deploy-prompts');\n\nexport type StackType = 'all' | 'inf' | 'api' | 'web' | 'views';\n\nconst STACK_TYPES: StackType[] = ['all', 'inf', 'api', 'web', 'views'];\n\nexport type DeployPlan =\n | { kind: 'cancelled' }\n // Deploy only the account-level guardrails stack (one per AWS account).\n | { kind: 'account'; appName: string }\n // Deploy the bootstrap stack (and optionally the domain stack first).\n | { kind: 'bootstrap'; appName: string; includeDomain: boolean }\n // Deploy the selected stacks for the selected services.\n | {\n kind: 'services';\n appName: string;\n services: string[];\n stacks: StackType;\n };\n\n// Non-interactive deploy plan from positional args: `qpq go <services> [stacks]`.\n// services: 'all' | comma-separated service names | 'account' | 'domain' | 'bootstrap'\n// stacks: all | inf | api | web | views (defaults to 'all')\n// Returns null when no positional services token is given, so callers fall back\n// to the interactive promptDeployPlan. Passing args is an explicit opt-in to a\n// prompt-free deploy, so the \"Deploying to: [env]\" confirmation is skipped too.\nexport const buildDeployPlanFromArgs = (appName: string, argv: string[]): Nullable<DeployPlan> => {\n const [servicesArg, stacksArg] = getPositionalArgs(argv, ['--app', '--deployment']);\n\n if (!servicesArg) {\n return null;\n }\n\n if (servicesArg === 'account') {\n return { kind: 'account', appName };\n }\n if (servicesArg === 'domain') {\n return { kind: 'bootstrap', appName, includeDomain: true };\n }\n if (servicesArg === 'bootstrap') {\n return { kind: 'bootstrap', appName, includeDomain: false };\n }\n\n const allServices = getServiceNames(appName);\n const services =\n servicesArg === 'all'\n ? allServices\n : servicesArg\n .split(',')\n .map((s) => s.trim())\n .filter(Boolean);\n\n const unknownServices = services.filter((service) => !allServices.includes(service));\n if (unknownServices.length > 0) {\n throw new CliError(`Unknown service(s): ${unknownServices.join(', ')}. Valid services: ${allServices.join(', ')}`);\n }\n\n const stacks = (stacksArg ?? 'all') as StackType;\n if (!STACK_TYPES.includes(stacks)) {\n throw new CliError(`Unknown stacks '${stacksArg}'. Valid stacks: ${STACK_TYPES.join(', ')}`);\n }\n\n return { kind: 'services', appName, services: [...new Set(services)], stacks };\n};\n\nexport const promptDeployPlan = async (appName: string): Promise<DeployPlan> => {\n const deployInfo = getDeployTargetLabel();\n\n if (!(await promptYesNo(`Deploying to: [${deployInfo}]`))) {\n out.log('Exiting!');\n return { kind: 'cancelled' };\n }\n\n let services: string[] = [];\n\n do {\n const allServices = getServiceNames(appName);\n\n // Bracketed so the meta options can't be mistaken for actual services.\n const allText = '[ all ]';\n const accountText = '[ account ]';\n const domainEnvText = '[ domain ]';\n const bootstrapEnvText = '[ bootstrap environment ]';\n\n const service = await promptSelect('Select services to deploy', [allText, ...allServices, accountText, domainEnvText, bootstrapEnvText]);\n\n if (service === allText) {\n services = allServices;\n break;\n }\n if (service === accountText) {\n return { kind: 'account', appName };\n }\n if (service === domainEnvText) {\n return { kind: 'bootstrap', appName, includeDomain: true };\n }\n if (service === bootstrapEnvText) {\n return { kind: 'bootstrap', appName, includeDomain: false };\n }\n\n services.push(service);\n } while (await promptYesNo('Do you want to deploy another service?'));\n\n services = [...new Set(services)];\n\n const stacks = (await promptSelect('Stacks to deploy', ['all', 'inf', 'api', 'web', 'views'])) as StackType;\n\n return { kind: 'services', appName, services, stacks };\n};\n\nexport type TeardownPlan =\n | { kind: 'cancelled' }\n // Destroy the web, api and inf stacks for the selected services.\n | { kind: 'services'; appName: string; services: string[] };\n\n// The question flow for `qpq teardown`: pick services, then type the deploy\n// target back to confirm, destroying inf stacks takes user data (key value\n// stores, user directories) with it, so a y/n prompt isn't enough friction.\nexport const promptTeardownPlan = async (appName: string): Promise<TeardownPlan> => {\n const deployInfo = getDeployTargetLabel();\n\n let services: string[] = [];\n\n do {\n const allServices = getServiceNames(appName);\n const allText = '[ all ]';\n\n const service = await promptSelect('Select services to tear down', [allText, ...allServices]);\n\n if (service === allText) {\n services = allServices;\n break;\n }\n\n services.push(service);\n } while (await promptYesNo('Do you want to tear down another service?'));\n\n services = [...new Set(services)];\n\n out.log(`\\nThis will DESTROY the web, api and inf stacks (including all stored data) for: ${services.join(', ')}`);\n if (!(await promptTypedConfirmation(deployInfo))) {\n return { kind: 'cancelled' };\n }\n\n return { kind: 'services', appName, services };\n};\n"]}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import { getDevServerDistPath } from '@qpqjs/core';
|
|
2
|
+
import { USER_SCRIPT_CHILD_BUNDLE_NAME } from '@qpqjs/deploy-rspack';
|
|
1
3
|
import fs from 'fs';
|
|
2
4
|
import path from 'path';
|
|
3
|
-
import { USER_SCRIPT_CHILD_BUNDLE_NAME } from '@qpqjs/deploy-rspack';
|
|
4
5
|
import { DEFAULT_DEV_SERVER_PORTS, getDevServerConfigPath } from './devServerPorts';
|
|
5
6
|
/** Env vars the docker image sets so the running server knows how the outside world reaches it. */
|
|
6
7
|
export const DEV_SERVER_PUBLIC_HOST_ENV = 'QPQ_PUBLIC_HOST';
|
|
@@ -43,7 +44,7 @@ const getRunCall = (mode) => {
|
|
|
43
44
|
* shares one bundle shape, so a local migration run rehearses exactly the deployed path.
|
|
44
45
|
*/
|
|
45
46
|
export const writeDevServerEntry = (root, appName, mode = 'serve') => {
|
|
46
|
-
const entryDir =
|
|
47
|
+
const entryDir = getDevServerDistPath(root);
|
|
47
48
|
const entryPath = path.join(entryDir, ENTRY_FILE_NAMES[mode]);
|
|
48
49
|
const overridesPath = getDevServerConfigPath(appName);
|
|
49
50
|
const overridesImport = fs.existsSync(overridesPath)
|
|
@@ -98,11 +99,11 @@ ${getRunCall(mode)}
|
|
|
98
99
|
* serves that one call with the service's config and module loader, then exits.
|
|
99
100
|
*/
|
|
100
101
|
export const writeUserScriptChildEntry = (root) => {
|
|
101
|
-
const entryDir =
|
|
102
|
+
const entryDir = getDevServerDistPath(root);
|
|
102
103
|
const entryPath = path.join(entryDir, USER_SCRIPT_CHILD_ENTRY_FILE_NAME);
|
|
103
104
|
fs.mkdirSync(entryDir, { recursive: true });
|
|
104
105
|
fs.writeFileSync(entryPath, `// GENERATED by qpq — do not edit.
|
|
105
|
-
import { qpqCoreUtils } from '@qpqjs/core';
|
|
106
|
+
import { getDevServerDistPath, qpqCoreUtils } from '@qpqjs/core';
|
|
106
107
|
import { runUserScriptChildMain } from '@qpqjs/actionprocessor-node';
|
|
107
108
|
import {
|
|
108
109
|
qpqConfigs,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"devServerEntry.js","sourceRoot":"","sources":["../../../src/lib/devServerEntry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"devServerEntry.js","sourceRoot":"","sources":["../../../src/lib/devServerEntry.ts"],"names":[],"mappings":"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","sourcesContent":["import { getDevServerDistPath } from '@qpqjs/core';\nimport { USER_SCRIPT_CHILD_BUNDLE_NAME } from '@qpqjs/deploy-rspack';\n\nimport fs from 'fs';\nimport path from 'path';\n\nimport { DEFAULT_DEV_SERVER_PORTS, getDevServerConfigPath } from './devServerPorts';\n\n/**\n * What the generated bootstrap does: serve forever, run pending migrations once and exit, or\n * both in turn (the docker image, where nothing else ever deploys and so nothing else would\n * run the migrations).\n */\nexport type DevServerEntryMode = 'serve' | 'migrate' | 'migrate-then-serve';\n\n/** Env vars the docker image sets so the running server knows how the outside world reaches it. */\nexport const DEV_SERVER_PUBLIC_HOST_ENV = 'QPQ_PUBLIC_HOST';\nexport const DEV_SERVER_PUBLIC_FILE_STORAGE_PORT_ENV = 'QPQ_PUBLIC_FILE_STORAGE_PORT';\n\nconst USER_SCRIPT_CHILD_ENTRY_FILE_NAME = 'user-script-child.entry.ts';\n\nconst ENTRY_FILE_NAMES: Record<DevServerEntryMode, string> = {\n serve: 'entry.ts',\n migrate: 'migrate.entry.ts',\n 'migrate-then-serve': 'entry.ts',\n};\n\nconst reportMigrations = `(ran) => {\n const total = Object.values(ran).reduce((sum, keys) => sum + keys.length, 0);\n for (const [service, keys] of Object.entries(ran)) {\n for (const key of keys) {\n console.log(\\` [\\${service}] \\${key}\\`);\n }\n }\n console.log(total === 0 ? 'No pending migrations.' : \\`Ran \\${total} migration(s).\\`);\n }`;\n\nconst getRunCall = (mode: DevServerEntryMode): string => {\n if (mode === 'serve') {\n return 'startDevServer(devServerConfig, devServerConfigOverrides);';\n }\n\n const afterMigrations = mode === 'migrate' ? 'process.exit(0);' : 'return startDevServer(devServerConfig, devServerConfigOverrides);';\n\n return `runMigrations(devServerConfig, devServerConfigOverrides)\n .then(${reportMigrations})\n .then(() => {\n ${afterMigrations}\n })\n .catch((error) => {\n console.error('Migration failed:', error);\n // Non-zero so CI, shell chains and a container restart policy actually notice.\n process.exit(1);\n });`;\n};\n\n/**\n * Writes the dev-server bootstrap for an app and returns its path. Generated per build so it\n * can import the optional app-owned overrides file (apps/<app>/devServer.config.ts) and the\n * `quidproquo-dynamic-loader` virtual module QpqPlugin injects at bundle time. Every mode\n * shares one bundle shape, so a local migration run rehearses exactly the deployed path.\n */\nexport const writeDevServerEntry = (root: string, appName: string, mode: DevServerEntryMode = 'serve'): string => {\n const entryDir = getDevServerDistPath(root);\n const entryPath = path.join(entryDir, ENTRY_FILE_NAMES[mode]);\n\n const overridesPath = getDevServerConfigPath(appName);\n const overridesImport = fs.existsSync(overridesPath)\n ? `import devServerConfigOverrides from ${JSON.stringify(overridesPath.replace(/\\.ts$/, ''))};`\n : 'const devServerConfigOverrides = {};';\n\n const imports = mode === 'serve' ? 'startDevServer' : mode === 'migrate' ? 'runMigrations' : 'runMigrations, startDevServer';\n\n fs.mkdirSync(entryDir, { recursive: true });\n fs.writeFileSync(\n entryPath,\n `// GENERATED by qpq — do not edit.\nimport { ${imports} } from '@qpqjs/dev-server';\nimport path from 'path';\nimport {\n qpqConfigs,\n qpqDynamicModuleLoaderForService,\n // @ts-ignore - Special build-time virtual module\n} from 'quidproquo-dynamic-loader';\n\n${overridesImport}\n\n// Ports are defaults here; the app's devServer.config.ts \\`ports\\` win when the server resolves its config.\nconst devServerConfig = {\n serverDomain: 'localhost',\n serverPort: ${DEFAULT_DEV_SERVER_PORTS.api},\n webSocketPort: ${DEFAULT_DEV_SERVER_PORTS.webSocket},\n // Scoped per app so running the dev server for two apps out of the same\n // repo root doesn't share kvs/file-storage/config state.\n runtimePath: ${JSON.stringify(path.join('.qpq-runtime', appName))},\n fileStorageConfig: {\n // Secure file urls are absolute, so a container has to be told the address browsers use.\n secureUrlHost: process.env.${DEV_SERVER_PUBLIC_HOST_ENV} || 'localhost',\n secureUrlPort: ${DEFAULT_DEV_SERVER_PORTS.fileStorage},\n secureUrlPublicPort: Number(process.env.${DEV_SERVER_PUBLIC_FILE_STORAGE_PORT_ENV}) || undefined,\n // No fixed secret: the server mints a random one per process, so a secure url token\n // (which names a filesystem path) cannot be forged by anyone who has read this file.\n },\n qpqConfigs,\n dynamicModuleLoader: qpqDynamicModuleLoaderForService,\n // The user-script child bundle is built beside this one (see writeUserScriptChildEntry).\n userScriptChildModulePath: path.join(path.dirname(process.argv[1]), ${JSON.stringify(`${USER_SCRIPT_CHILD_BUNDLE_NAME}.js`)}),\n // QPQ_WEB_ROOT (set in the docker platform image) turns on static web serving.\n webRoot: process.env.QPQ_WEB_ROOT,\n logServiceName: 'admin',\n delay: { default: 0 },\n};\n\n${getRunCall(mode)}\n`,\n );\n\n return entryPath;\n};\n\n/**\n * Writes the dev server's user-script child entry and returns its path. The server forks the\n * bundle this becomes once per script call, with the service name as its argument; the child\n * serves that one call with the service's config and module loader, then exits.\n */\nexport const writeUserScriptChildEntry = (root: string): string => {\n const entryDir = getDevServerDistPath(root);\n const entryPath = path.join(entryDir, USER_SCRIPT_CHILD_ENTRY_FILE_NAME);\n\n fs.mkdirSync(entryDir, { recursive: true });\n fs.writeFileSync(\n entryPath,\n `// GENERATED by qpq — do not edit.\nimport { getDevServerDistPath, qpqCoreUtils } from '@qpqjs/core';\nimport { runUserScriptChildMain } from '@qpqjs/actionprocessor-node';\nimport {\n qpqConfigs,\n qpqDynamicModuleLoaderForService,\n // @ts-ignore - Special build-time virtual module\n} from 'quidproquo-dynamic-loader';\n\nexport const main = (): void => {\n const serviceName = process.argv[2];\n const qpqConfig = qpqConfigs.find((config) => qpqCoreUtils.getApplicationModuleName(config) === serviceName);\n if (!qpqConfig) {\n throw new Error(\\`User script child: no service named [\\${serviceName}]\\`);\n }\n\n runUserScriptChildMain(qpqConfig, (runtime) => qpqDynamicModuleLoaderForService(serviceName, runtime));\n};\n\nmain();\n`,\n );\n\n return entryPath;\n};\n"]}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { requireModuleDefault } from '@qpqjs/deploy-aws';
|
|
1
2
|
import fs from 'fs';
|
|
2
3
|
import path from 'path';
|
|
3
4
|
import { getAppDirectory } from './discovery';
|
|
@@ -19,9 +20,7 @@ export const readDevServerPorts = (appName) => {
|
|
|
19
20
|
if (!fs.existsSync(configPath)) {
|
|
20
21
|
return DEFAULT_DEV_SERVER_PORTS;
|
|
21
22
|
}
|
|
22
|
-
|
|
23
|
-
const loaded = require(configPath.replace(/\.ts$/, ''));
|
|
24
|
-
const overrides = (loaded.default ?? loaded);
|
|
23
|
+
const overrides = requireModuleDefault(configPath.replace(/\.ts$/, ''));
|
|
25
24
|
return { ...DEFAULT_DEV_SERVER_PORTS, ...overrides.ports };
|
|
26
25
|
};
|
|
27
26
|
//# sourceMappingURL=devServerPorts.js.map
|