@qpqjs/cli 0.4.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/runCli.js +2 -2
- package/lib/commonjs/cli/runCli.js.map +1 -1
- package/lib/commonjs/commands/checkCircular.js +2 -2
- package/lib/commonjs/commands/checkCircular.js.map +1 -1
- package/lib/commonjs/commands/goDev.js +2 -2
- package/lib/commonjs/commands/goDev.js.map +1 -1
- package/lib/commonjs/commands/goDevApi.js +6 -5
- package/lib/commonjs/commands/goDevApi.js.map +1 -1
- package/lib/commonjs/commands/goDevWeb.js +3 -3
- package/lib/commonjs/commands/goDevWeb.js.map +1 -1
- package/lib/commonjs/commands/goDocker.js +2 -2
- package/lib/commonjs/commands/goDocker.js.map +1 -1
- package/lib/commonjs/commands/hooks.js +2 -2
- package/lib/commonjs/commands/hooks.js.map +1 -1
- package/lib/commonjs/commands/migrate.js +2 -2
- package/lib/commonjs/commands/migrate.js.map +1 -1
- package/lib/commonjs/commands/prep.js +2 -2
- package/lib/commonjs/commands/prep.js.map +1 -1
- package/lib/commonjs/commands/scriptBuild.js +2 -2
- package/lib/commonjs/commands/scriptBuild.js.map +1 -1
- package/lib/commonjs/commands/scriptBuilderLayer.js +2 -2
- package/lib/commonjs/commands/scriptBuilderLayer.js.map +1 -1
- package/lib/commonjs/commands/scriptNew.js +2 -2
- package/lib/commonjs/commands/scriptNew.js.map +1 -1
- package/lib/commonjs/commands/setup.js +2 -2
- package/lib/commonjs/commands/setup.js.map +1 -1
- package/lib/commonjs/commands/synth.js +2 -2
- package/lib/commonjs/commands/synth.js.map +1 -1
- package/lib/commonjs/lib/{out.d.ts → Output.d.ts} +2 -1
- package/lib/commonjs/lib/Output.js +3 -0
- package/lib/commonjs/lib/Output.js.map +1 -0
- package/lib/commonjs/lib/clearResourcesPlan.js +2 -2
- package/lib/commonjs/lib/clearResourcesPlan.js.map +1 -1
- package/lib/commonjs/lib/createOutput.d.ts +2 -0
- package/lib/commonjs/lib/{out.js → createOutput.js} +13 -4
- package/lib/commonjs/lib/createOutput.js.map +1 -0
- package/lib/commonjs/lib/deployPrompts.js +3 -3
- package/lib/commonjs/lib/deployPrompts.js.map +1 -1
- package/lib/commonjs/lib/hooks.js +2 -2
- package/lib/commonjs/lib/hooks.js.map +1 -1
- package/lib/commonjs/lib/killChildWithEscalation.js +2 -2
- package/lib/commonjs/lib/killChildWithEscalation.js.map +1 -1
- package/lib/commonjs/lib/killStaleListeners.js +3 -3
- package/lib/commonjs/lib/killStaleListeners.js.map +1 -1
- package/lib/commonjs/lib/prompts.js +2 -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 +9 -4
- package/lib/commonjs/lib/qpqConfigs.js.map +1 -1
- package/lib/commonjs/lib/requireDriverCapability.js +2 -2
- package/lib/commonjs/lib/requireDriverCapability.js.map +1 -1
- package/lib/commonjs/lib/resolveAppSelection.js +3 -3
- package/lib/commonjs/lib/resolveAppSelection.js.map +1 -1
- package/lib/commonjs/lib/resolveDeployment.js +3 -3
- package/lib/commonjs/lib/resolveDeployment.js.map +1 -1
- package/lib/commonjs/lib/runCommand.js +2 -2
- package/lib/commonjs/lib/runCommand.js.map +1 -1
- package/lib/commonjs/lib/runTasks.js +2 -2
- package/lib/commonjs/lib/runTasks.js.map +1 -1
- package/lib/commonjs/lib/timing.js +2 -2
- package/lib/commonjs/lib/timing.js.map +1 -1
- package/lib/commonjs/lib/typeWatcher.js +3 -3
- package/lib/commonjs/lib/typeWatcher.js.map +1 -1
- package/lib/commonjs/lib/userScriptBuilderLayer.js +1 -1
- package/lib/commonjs/lib/userScriptBuilderLayer.js.map +1 -1
- package/lib/commonjs/platforms/aws/awsCredentials.js +2 -2
- package/lib/commonjs/platforms/aws/awsCredentials.js.map +1 -1
- package/lib/commonjs/platforms/aws/clearResources.js +4 -3
- package/lib/commonjs/platforms/aws/clearResources.js.map +1 -1
- package/lib/commonjs/platforms/aws/go.js +2 -2
- package/lib/commonjs/platforms/aws/go.js.map +1 -1
- package/lib/commonjs/platforms/aws/goDocker.js +2 -2
- package/lib/commonjs/platforms/aws/goDocker.js.map +1 -1
- package/lib/commonjs/platforms/aws/publish.js +2 -2
- package/lib/commonjs/platforms/aws/publish.js.map +1 -1
- package/lib/commonjs/platforms/aws/remote.js +2 -2
- package/lib/commonjs/platforms/aws/remote.js.map +1 -1
- package/lib/commonjs/platforms/aws/setup/buildGithubDeployRoleStep.js +2 -2
- package/lib/commonjs/platforms/aws/setup/buildGithubDeployRoleStep.js.map +1 -1
- package/lib/commonjs/platforms/aws/stacks.js +4 -8
- package/lib/commonjs/platforms/aws/stacks.js.map +1 -1
- package/lib/commonjs/platforms/aws/teardown.js +2 -2
- package/lib/commonjs/platforms/aws/teardown.js.map +1 -1
- package/lib/commonjs/platforms/aws/viewsSync.js +2 -2
- package/lib/commonjs/platforms/aws/viewsSync.js.map +1 -1
- package/lib/commonjs/platforms/docker/go.js +2 -2
- package/lib/commonjs/platforms/docker/go.js.map +1 -1
- package/lib/commonjs/platforms/docker/index.js +2 -2
- package/lib/commonjs/platforms/docker/index.js.map +1 -1
- package/lib/commonjs/platforms/index.js +2 -2
- package/lib/commonjs/platforms/index.js.map +1 -1
- package/lib/esm/cli/runCli.js +1 -1
- package/lib/esm/cli/runCli.js.map +1 -1
- package/lib/esm/commands/checkCircular.js +1 -1
- package/lib/esm/commands/checkCircular.js.map +1 -1
- package/lib/esm/commands/goDev.js +1 -1
- package/lib/esm/commands/goDev.js.map +1 -1
- package/lib/esm/commands/goDevApi.js +4 -4
- package/lib/esm/commands/goDevApi.js.map +1 -1
- package/lib/esm/commands/goDevWeb.js +2 -2
- package/lib/esm/commands/goDevWeb.js.map +1 -1
- package/lib/esm/commands/goDocker.js +1 -1
- package/lib/esm/commands/goDocker.js.map +1 -1
- package/lib/esm/commands/hooks.js +1 -1
- package/lib/esm/commands/hooks.js.map +1 -1
- package/lib/esm/commands/migrate.js +1 -1
- package/lib/esm/commands/migrate.js.map +1 -1
- package/lib/esm/commands/prep.js +1 -1
- package/lib/esm/commands/prep.js.map +1 -1
- package/lib/esm/commands/scriptBuild.js +1 -1
- package/lib/esm/commands/scriptBuild.js.map +1 -1
- package/lib/esm/commands/scriptBuilderLayer.js +1 -1
- package/lib/esm/commands/scriptBuilderLayer.js.map +1 -1
- package/lib/esm/commands/scriptNew.js +1 -1
- package/lib/esm/commands/scriptNew.js.map +1 -1
- package/lib/esm/commands/setup.js +1 -1
- package/lib/esm/commands/setup.js.map +1 -1
- package/lib/esm/commands/synth.js +1 -1
- package/lib/esm/commands/synth.js.map +1 -1
- package/lib/esm/lib/{out.d.ts → Output.d.ts} +2 -1
- package/lib/esm/lib/Output.js +2 -0
- package/lib/esm/lib/Output.js.map +1 -0
- package/lib/esm/lib/clearResourcesPlan.js +1 -1
- package/lib/esm/lib/clearResourcesPlan.js.map +1 -1
- package/lib/esm/lib/createOutput.d.ts +2 -0
- package/lib/esm/lib/{out.js → createOutput.js} +13 -4
- package/lib/esm/lib/createOutput.js.map +1 -0
- package/lib/esm/lib/deployPrompts.js +2 -2
- package/lib/esm/lib/deployPrompts.js.map +1 -1
- package/lib/esm/lib/hooks.js +1 -1
- package/lib/esm/lib/hooks.js.map +1 -1
- package/lib/esm/lib/killChildWithEscalation.js +1 -1
- package/lib/esm/lib/killChildWithEscalation.js.map +1 -1
- package/lib/esm/lib/killStaleListeners.js +2 -2
- package/lib/esm/lib/killStaleListeners.js.map +1 -1
- package/lib/esm/lib/prompts.js +1 -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 +7 -3
- package/lib/esm/lib/qpqConfigs.js.map +1 -1
- package/lib/esm/lib/requireDriverCapability.js +1 -1
- package/lib/esm/lib/requireDriverCapability.js.map +1 -1
- package/lib/esm/lib/resolveAppSelection.js +2 -2
- package/lib/esm/lib/resolveAppSelection.js.map +1 -1
- package/lib/esm/lib/resolveDeployment.js +2 -2
- package/lib/esm/lib/resolveDeployment.js.map +1 -1
- package/lib/esm/lib/runCommand.js +1 -1
- package/lib/esm/lib/runCommand.js.map +1 -1
- package/lib/esm/lib/runTasks.js +1 -1
- package/lib/esm/lib/runTasks.js.map +1 -1
- package/lib/esm/lib/timing.js +1 -1
- package/lib/esm/lib/timing.js.map +1 -1
- package/lib/esm/lib/typeWatcher.js +2 -2
- package/lib/esm/lib/typeWatcher.js.map +1 -1
- package/lib/esm/lib/userScriptBuilderLayer.js +1 -1
- package/lib/esm/lib/userScriptBuilderLayer.js.map +1 -1
- package/lib/esm/platforms/aws/awsCredentials.js +1 -1
- package/lib/esm/platforms/aws/awsCredentials.js.map +1 -1
- package/lib/esm/platforms/aws/clearResources.js +3 -2
- package/lib/esm/platforms/aws/clearResources.js.map +1 -1
- package/lib/esm/platforms/aws/go.js +1 -1
- package/lib/esm/platforms/aws/go.js.map +1 -1
- package/lib/esm/platforms/aws/goDocker.js +1 -1
- package/lib/esm/platforms/aws/goDocker.js.map +1 -1
- package/lib/esm/platforms/aws/publish.js +1 -1
- package/lib/esm/platforms/aws/publish.js.map +1 -1
- package/lib/esm/platforms/aws/remote.js +1 -1
- package/lib/esm/platforms/aws/remote.js.map +1 -1
- package/lib/esm/platforms/aws/setup/buildGithubDeployRoleStep.js +1 -1
- package/lib/esm/platforms/aws/setup/buildGithubDeployRoleStep.js.map +1 -1
- package/lib/esm/platforms/aws/stacks.js +5 -9
- package/lib/esm/platforms/aws/stacks.js.map +1 -1
- package/lib/esm/platforms/aws/teardown.js +1 -1
- package/lib/esm/platforms/aws/teardown.js.map +1 -1
- package/lib/esm/platforms/aws/viewsSync.js +1 -1
- package/lib/esm/platforms/aws/viewsSync.js.map +1 -1
- package/lib/esm/platforms/docker/go.js +1 -1
- package/lib/esm/platforms/docker/go.js.map +1 -1
- package/lib/esm/platforms/docker/index.js +1 -1
- package/lib/esm/platforms/docker/index.js.map +1 -1
- package/lib/esm/platforms/index.js +1 -1
- package/lib/esm/platforms/index.js.map +1 -1
- package/package.json +11 -11
- package/lib/commonjs/lib/out.js.map +0 -1
- package/lib/esm/lib/out.js.map +0 -1
package/lib/esm/commands/prep.js
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
// path aliases for cross-view federated imports). Run after adding/removing a
|
|
3
3
|
// `// federated.export` marker.
|
|
4
4
|
import { writeFederatedTsconfigForApp } from '@qpqjs/deploy-rspack';
|
|
5
|
+
import { createOutput } from '../lib/createOutput';
|
|
5
6
|
import { getAvailableApps, getRoot } from '../lib/discovery';
|
|
6
|
-
import { createOutput } from '../lib/out';
|
|
7
7
|
import { resolveAppSelection } from '../lib/resolveAppSelection';
|
|
8
8
|
const out = createOutput('prep');
|
|
9
9
|
export const prepCommand = async (argv) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prep.js","sourceRoot":"","sources":["../../../src/commands/prep.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,8EAA8E;AAC9E,gCAAgC;AAChC,OAAO,EAAE,4BAA4B,EAAE,MAAM,sBAAsB,CAAC;AAEpE,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"prep.js","sourceRoot":"","sources":["../../../src/commands/prep.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,8EAA8E;AAC9E,gCAAgC;AAChC,OAAO,EAAE,4BAA4B,EAAE,MAAM,sBAAsB,CAAC;AAEpE,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,gBAAgB,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAC7D,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAEjE,MAAM,GAAG,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC;AAEjC,MAAM,CAAC,MAAM,WAAW,GAAG,KAAK,EAAE,IAAc,EAAiB,EAAE;IACjE,MAAM,SAAS,GAAG,MAAM,mBAAmB,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;IACtE,MAAM,QAAQ,GAAG,SAAS,KAAK,KAAK,CAAC,CAAC,CAAC,gBAAgB,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IAExE,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,MAAM,WAAW,GAAG,4BAA4B,CAAC,OAAO,EAAE,EAAE,OAAO,CAAC,CAAC;QACrE,GAAG,CAAC,GAAG,CAAC,eAAe,WAAW,8BAA8B,OAAO,0BAA0B,CAAC,CAAC;IACrG,CAAC;AACH,CAAC,CAAC","sourcesContent":["// `qpq prep`, regenerates apps/<app>/tsconfig.federated.json (the TypeScript\n// path aliases for cross-view federated imports). Run after adding/removing a\n// `// federated.export` marker.\nimport { writeFederatedTsconfigForApp } from '@qpqjs/deploy-rspack';\n\nimport { createOutput } from '../lib/createOutput';\nimport { getAvailableApps, getRoot } from '../lib/discovery';\nimport { resolveAppSelection } from '../lib/resolveAppSelection';\n\nconst out = createOutput('prep');\n\nexport const prepCommand = async (argv: string[]): Promise<void> => {\n const selection = await resolveAppSelection({ argv, allowAll: true });\n const appNames = selection === 'all' ? getAvailableApps() : [selection];\n\n for (const appName of appNames) {\n const exposeCount = writeFederatedTsconfigForApp(getRoot(), appName);\n out.log(`prep: wrote ${exposeCount} federated aliases to apps/${appName}/tsconfig.federated.json`);\n }\n};\n"]}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
import { buildUserScript, checkUserScriptOutput, UserScriptBuildError } from '@qpqjs/user-script';
|
|
5
5
|
import path from 'path';
|
|
6
6
|
import { getArgValue, getPositionalArgs, hasArgFlag } from '../lib/args';
|
|
7
|
-
import { createOutput } from '../lib/
|
|
7
|
+
import { createOutput } from '../lib/createOutput';
|
|
8
8
|
const out = createOutput('script:build');
|
|
9
9
|
export const scriptBuildCommand = async (argv) => {
|
|
10
10
|
const [projectDir] = getPositionalArgs(argv, ['--out']);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scriptBuild.js","sourceRoot":"","sources":["../../../src/commands/scriptBuild.ts"],"names":[],"mappings":"AAAA,sFAAsF;AACtF,mFAAmF;AACnF,oEAAoE;AACpE,OAAO,EAAE,eAAe,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAElG,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzE,OAAO,EAAE,YAAY,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"scriptBuild.js","sourceRoot":"","sources":["../../../src/commands/scriptBuild.ts"],"names":[],"mappings":"AAAA,sFAAsF;AACtF,mFAAmF;AACnF,oEAAoE;AACpE,OAAO,EAAE,eAAe,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAElG,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzE,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAEnD,MAAM,GAAG,GAAG,YAAY,CAAC,cAAc,CAAC,CAAC;AAEzC,MAAM,CAAC,MAAM,kBAAkB,GAAG,KAAK,EAAE,IAAc,EAAiB,EAAE;IACxE,MAAM,CAAC,UAAU,CAAC,GAAG,iBAAiB,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;IACxD,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,GAAG,CAAC,KAAK,CAAC,4DAA4D,CAAC,CAAC;QACxE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,MAAM,GAAG,WAAW,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;IAE3E,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,EAAE,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,UAAU,CAAC,IAAI,EAAE,cAAc,CAAC,EAAE,CAAC,CAAC;QAC1G,yFAAyF;QACzF,MAAM,OAAO,GAAG,qBAAqB,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QACxD,GAAG,CAAC,GAAG,CAAC,uBAAuB,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC;QACnD,GAAG,CAAC,GAAG,CAAC,cAAc,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC9C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,oBAAoB,EAAE,CAAC;YAC1C,GAAG,CAAC,KAAK,CAAC,iBAAiB,KAAK,CAAC,IAAI,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;YAC3D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QACD,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC,CAAC","sourcesContent":["// `qpq script:build <dir> [--out <dir>] [--source-map]`, bundle a user-script project\n// into one main.js that askUserScriptExecute can load from a drive. `--source-map`\n// embeds the map in main.js; no separate .map file is ever written.\nimport { buildUserScript, checkUserScriptOutput, UserScriptBuildError } from '@qpqjs/user-script';\n\nimport path from 'path';\n\nimport { getArgValue, getPositionalArgs, hasArgFlag } from '../lib/args';\nimport { createOutput } from '../lib/createOutput';\n\nconst out = createOutput('script:build');\n\nexport const scriptBuildCommand = async (argv: string[]): Promise<void> => {\n const [projectDir] = getPositionalArgs(argv, ['--out']);\n if (!projectDir) {\n out.error('Usage: qpq script:build <dir> [--out <dir>] [--source-map]');\n process.exit(1);\n }\n\n const outDir = getArgValue(argv, '--out') ?? path.join(projectDir, 'dist');\n\n try {\n const result = await buildUserScript({ projectDir, outDir, sourceMap: hasArgFlag(argv, '--source-map') });\n // A developer's own build is checked in this process; a platform build asks the sandbox.\n const exports = checkUserScriptOutput(result.entryPath);\n out.log(`script:build: wrote ${result.entryPath}`);\n out.log(` exports: ${exports.join(', ')}`);\n } catch (error) {\n if (error instanceof UserScriptBuildError) {\n out.error(`script:build: ${error.code}: ${error.message}`);\n process.exit(1);\n }\n throw error;\n }\n};\n"]}
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
import { JavascriptRuntimeArchitecture } from '@qpqjs/core';
|
|
8
8
|
import { getUserScriptBuilderLayerDir } from '@qpqjs/user-script';
|
|
9
9
|
import { getArgValue } from '../lib/args';
|
|
10
|
-
import { createOutput } from '../lib/
|
|
10
|
+
import { createOutput } from '../lib/createOutput';
|
|
11
11
|
import { buildUserScriptBuilderLayer } from '../lib/userScriptBuilderLayer';
|
|
12
12
|
const out = createOutput('script:builder-layer');
|
|
13
13
|
const ARCH_FLAG = '--arch';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scriptBuilderLayer.js","sourceRoot":"","sources":["../../../src/commands/scriptBuilderLayer.ts"],"names":[],"mappings":"AAAA,wFAAwF;AACxF,wFAAwF;AACxF,yFAAyF;AACzF,wFAAwF;AACxF,yFAAyF;AACzF,uDAAuD;AACvD,OAAO,EAAE,6BAA6B,EAAE,MAAM,aAAa,CAAC;AAC5D,OAAO,EAAE,4BAA4B,EAAE,MAAM,oBAAoB,CAAC;AAElE,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,YAAY,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"scriptBuilderLayer.js","sourceRoot":"","sources":["../../../src/commands/scriptBuilderLayer.ts"],"names":[],"mappings":"AAAA,wFAAwF;AACxF,wFAAwF;AACxF,yFAAyF;AACzF,wFAAwF;AACxF,yFAAyF;AACzF,uDAAuD;AACvD,OAAO,EAAE,6BAA6B,EAAE,MAAM,aAAa,CAAC;AAC5D,OAAO,EAAE,4BAA4B,EAAE,MAAM,oBAAoB,CAAC;AAElE,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,2BAA2B,EAAE,MAAM,+BAA+B,CAAC;AAE5E,MAAM,GAAG,GAAG,YAAY,CAAC,sBAAsB,CAAC,CAAC;AAEjD,MAAM,SAAS,GAAG,QAAQ,CAAC;AAC3B,MAAM,oBAAoB,GAAG,6BAA6B,CAAC,KAAK,CAAC;AAEjE,0DAA0D;AAC1D,sFAAsF;AACtF,yEAAyE;AACzE,MAAM,gBAAgB,GAAG,GAAW,EAAE,CAAC,OAAO,CAAC,2BAA2B,CAAC,CAAC,OAAiB,CAAC;AAE9F,MAAM,iBAAiB,GAAG,CAAC,IAAc,EAAiC,EAAE;IAC1E,MAAM,SAAS,GAAG,WAAW,CAAC,IAAI,EAAE,SAAS,CAAC,IAAI,oBAAoB,CAAC;IACvE,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,6BAA6B,CAAC,CAAC;IAC3D,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,SAA0C,CAAC,EAAE,CAAC;QAChE,GAAG,CAAC,KAAK,CAAC,iCAAiC,SAAS,KAAK,SAAS,sBAAsB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC5G,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IACD,OAAO,SAA0C,CAAC;AACpD,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,yBAAyB,GAAG,KAAK,EAAE,IAAc,EAAiB,EAAE;IAC/E,MAAM,YAAY,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;IAC7C,MAAM,aAAa,GAAG,gBAAgB,EAAE,CAAC;IACzC,MAAM,MAAM,GAAG,4BAA4B,EAAE,CAAC;IAE9C,GAAG,CAAC,GAAG,CAAC,iDAAiD,aAAa,cAAc,YAAY,SAAS,MAAM,EAAE,CAAC,CAAC;IACnH,MAAM,OAAO,GAAG,2BAA2B,CAAC,EAAE,MAAM,EAAE,YAAY,EAAE,aAAa,EAAE,CAAC,CAAC;IACrF,GAAG,CAAC,GAAG,CAAC,+BAA+B,OAAO,EAAE,CAAC,CAAC;AACpD,CAAC,CAAC","sourcesContent":["// `qpq script:builder-layer [--arch arm64|x86_64]`, produce the lambda layer that gives\n// a service rspack, for services that registered defineUserScriptBuilder. The directory\n// is the one getUserScriptBuilderApiLayer points at, so nothing is told a path. Run from\n// the app's qpq:predeploy hook, which go:docker fires before the workspace is built, so\n// this command deliberately loads no service config (that would import unbuilt packages)\n// and takes the lambda architecture as a flag instead.\nimport { JavascriptRuntimeArchitecture } from '@qpqjs/core';\nimport { getUserScriptBuilderLayerDir } from '@qpqjs/user-script';\n\nimport { getArgValue } from '../lib/args';\nimport { createOutput } from '../lib/createOutput';\nimport { buildUserScriptBuilderLayer } from '../lib/userScriptBuilderLayer';\n\nconst out = createOutput('script:builder-layer');\n\nconst ARCH_FLAG = '--arch';\nconst DEFAULT_ARCHITECTURE = JavascriptRuntimeArchitecture.Arm64;\n\n/* eslint-disable @typescript-eslint/no-require-imports */\n// The rspack the CLI itself resolves is the one the dev server builds with; the layer\n// pins the same version so a script builds identically on both runtimes.\nconst getRspackVersion = (): string => require('@rspack/core/package.json').version as string;\n\nconst parseArchitecture = (argv: string[]): JavascriptRuntimeArchitecture => {\n const requested = getArgValue(argv, ARCH_FLAG) ?? DEFAULT_ARCHITECTURE;\n const known = Object.values(JavascriptRuntimeArchitecture);\n if (!known.includes(requested as JavascriptRuntimeArchitecture)) {\n out.error(`script:builder-layer: unknown ${ARCH_FLAG} [${requested}]; expected one of ${known.join(', ')}`);\n process.exit(1);\n }\n return requested as JavascriptRuntimeArchitecture;\n};\n\nexport const scriptBuilderLayerCommand = async (argv: string[]): Promise<void> => {\n const architecture = parseArchitecture(argv);\n const rspackVersion = getRspackVersion();\n const outDir = getUserScriptBuilderLayerDir();\n\n out.log(`script:builder-layer: installing @rspack/core@${rspackVersion} for linux ${architecture} into ${outDir}`);\n const nodeDir = buildUserScriptBuilderLayer({ outDir, architecture, rspackVersion });\n out.log(`script:builder-layer: wrote ${nodeDir}`);\n};\n"]}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// directory. See templates/user-script/README.md for what a script is.
|
|
3
3
|
import path from 'path';
|
|
4
4
|
import { getPositionalArgs } from '../lib/args';
|
|
5
|
-
import { createOutput } from '../lib/
|
|
5
|
+
import { createOutput } from '../lib/createOutput';
|
|
6
6
|
import { createUserScriptProject } from '../lib/userScriptTemplate';
|
|
7
7
|
const out = createOutput('script:new');
|
|
8
8
|
export const scriptNewCommand = async (argv) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scriptNew.js","sourceRoot":"","sources":["../../../src/commands/scriptNew.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,uEAAuE;AACvE,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"scriptNew.js","sourceRoot":"","sources":["../../../src/commands/scriptNew.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,uEAAuE;AACvE,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AAEpE,MAAM,GAAG,GAAG,YAAY,CAAC,YAAY,CAAC,CAAC;AAEvC,MAAM,CAAC,MAAM,gBAAgB,GAAG,KAAK,EAAE,IAAc,EAAiB,EAAE;IACtE,MAAM,CAAC,SAAS,CAAC,GAAG,iBAAiB,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IAChD,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,GAAG,CAAC,KAAK,CAAC,6BAA6B,CAAC,CAAC;QACzC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,OAAO,GAAG,uBAAuB,CAAC,SAAS,CAAC,CAAC;IAEnD,GAAG,CAAC,GAAG,CAAC,qBAAqB,OAAO,CAAC,MAAM,aAAa,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;IACnF,KAAK,MAAM,IAAI,IAAI,OAAO,EAAE,CAAC;QAC3B,GAAG,CAAC,GAAG,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC;IACvB,CAAC;IACD,GAAG,CAAC,GAAG,CAAC,YAAY,SAAS,mBAAmB,CAAC,CAAC;AACpD,CAAC,CAAC","sourcesContent":["// `qpq script:new <dir>`, write the user-script template project into a new\n// directory. See templates/user-script/README.md for what a script is.\nimport path from 'path';\n\nimport { getPositionalArgs } from '../lib/args';\nimport { createOutput } from '../lib/createOutput';\nimport { createUserScriptProject } from '../lib/userScriptTemplate';\n\nconst out = createOutput('script:new');\n\nexport const scriptNewCommand = async (argv: string[]): Promise<void> => {\n const [targetDir] = getPositionalArgs(argv, []);\n if (!targetDir) {\n out.error('Usage: qpq script:new <dir>');\n process.exit(1);\n }\n\n const written = createUserScriptProject(targetDir);\n\n out.log(`script:new: wrote ${written.length} files to ${path.resolve(targetDir)}`);\n for (const file of written) {\n out.log(` ${file}`);\n }\n out.log(`Next: cd ${targetDir} && npm run build`);\n};\n"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { getArgValue } from '../lib/args';
|
|
2
|
-
import { createOutput } from '../lib/
|
|
2
|
+
import { createOutput } from '../lib/createOutput';
|
|
3
3
|
import { promptCheckbox } from '../lib/prompts';
|
|
4
4
|
import { resolveCommandContext } from '../lib/resolveCommandContext';
|
|
5
5
|
const out = createOutput('setup');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"setup.js","sourceRoot":"","sources":["../../../src/commands/setup.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,YAAY,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"setup.js","sourceRoot":"","sources":["../../../src/commands/setup.ts"],"names":[],"mappings":"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","sourcesContent":["// `qpq setup`, takes a cloud environment from empty to deployed, in order, with\n// every step checked first so the menu shows what is already in place and a\n// rerun on a half-set-up account is safe. The platform (from the deployment's\n// entry in deploy.config.json) contributes the steps.\n// --check print each step's status and exit, run nothing\n// --yes run every step without the menu\n// --only a,b run only the named step ids (no menu)\nimport { Nullable } from '@qpqjs/core';\n\nimport { getArgValue } from '../lib/args';\nimport { createOutput } from '../lib/createOutput';\nimport { promptCheckbox } from '../lib/prompts';\nimport { resolveCommandContext } from '../lib/resolveCommandContext';\nimport { SetupCheckResult, SetupStep } from '../lib/setupStep';\n\nconst out = createOutput('setup');\n\ntype CheckedStep = { step: SetupStep; result: Nullable<SetupCheckResult> };\n\nconst statusLabel = (result: Nullable<SetupCheckResult>): string => (result === null ? '?' : result.done ? 'done' : 'todo');\n\nconst printChecklist = (checked: CheckedStep[]): void => {\n for (const { step, result } of checked) {\n const detail = result?.detail ? ` ${result.detail}` : '';\n out.log(` [${statusLabel(result).padEnd(4)}] ${step.name}${detail}`);\n }\n};\n\nconst checkAll = async (steps: SetupStep[]): Promise<CheckedStep[]> => {\n const checked: CheckedStep[] = [];\n for (const step of steps) {\n try {\n checked.push({ step, result: await step.check() });\n } catch (error) {\n checked.push({ step, result: { done: false, detail: `check failed: ${error instanceof Error ? error.message : String(error)}` } });\n }\n }\n return checked;\n};\n\n// Steps not yet done are preselected; done ones can still be picked to rerun.\nconst chooseSteps = async (checked: CheckedStep[]): Promise<SetupStep[]> => {\n const chosen = await promptCheckbox(\n 'Setup steps to run (space toggles, enter runs in order)',\n checked.map(({ step, result }) => ({\n name: `[${statusLabel(result).padEnd(4)}] ${step.name}`,\n value: step,\n checked: !result?.done,\n description: result?.detail,\n })),\n );\n\n // Always run in checklist order, whatever order they were ticked in.\n return checked.map(({ step }) => step).filter((step) => chosen.includes(step));\n};\n\nconst selectFromArgs = (steps: SetupStep[], argv: string[]): Nullable<SetupStep[]> => {\n if (argv.includes('--yes')) {\n return steps;\n }\n\n const only = getArgValue(argv, '--only');\n if (!only) {\n return null;\n }\n\n const ids = only.split(',').map((id) => id.trim());\n const unknown = ids.filter((id) => !steps.some((step) => step.id === id));\n if (unknown.length > 0) {\n out.error(`Unknown setup step id(s): ${unknown.join(', ')}. Known: ${steps.map((step) => step.id).join(', ')}`);\n process.exit(1);\n }\n\n return steps.filter((step) => ids.includes(step.id));\n};\n\nexport const setupCommand = async (argv: string[]): Promise<void> => {\n const { appName, deploymentName, deployment, driver } = await resolveCommandContext(argv);\n\n // Nothing to set up is a normal outcome here, not a refused command.\n if (!driver.setupSteps) {\n out.log(`The '${deployment.platform}' platform has nothing to set up for deployment '${deploymentName}'.`);\n return;\n }\n\n const steps = await driver.setupSteps(appName, deploymentName);\n\n out.log(`\\nSetup for app '${appName}', deployment '${deploymentName}' (${deployment.platform})\\n`);\n const checked = await checkAll(steps);\n printChecklist(checked);\n out.log('');\n\n if (argv.includes('--check')) {\n return;\n }\n\n const toRun = selectFromArgs(steps, argv) ?? (await chooseSteps(checked));\n if (toRun.length === 0) {\n out.log('Nothing selected.');\n return;\n }\n\n for (const step of toRun) {\n out.log(`\\n== ${step.name}\\n`);\n await step.run();\n }\n\n out.log('\\nSetup complete. Final state:\\n');\n printChecklist(await checkAll(steps));\n out.log(`\\nNext: deploy the services with npx qpq go:docker all all --app ${appName} --deployment ${deploymentName}`);\n};\n"]}
|
|
@@ -8,8 +8,8 @@ import { getInfrastructureConfigPath, qpqCoreUtils, QpqDeployEnvVar } from '@qpq
|
|
|
8
8
|
import fs from 'fs';
|
|
9
9
|
import path from 'path';
|
|
10
10
|
import { getPositionalArgs } from '../lib/args';
|
|
11
|
+
import { createOutput } from '../lib/createOutput';
|
|
11
12
|
import { getAvailableApps, getRoot, getServiceNamesWithSubdir } from '../lib/discovery';
|
|
12
|
-
import { createOutput } from '../lib/out';
|
|
13
13
|
import { loadServiceQpqConfig } from '../lib/qpqConfigs';
|
|
14
14
|
import { getRequestedAppName, resolveAppSelection } from '../lib/resolveAppSelection';
|
|
15
15
|
import { resolveDeployment } from '../lib/resolveDeployment';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"synth.js","sourceRoot":"","sources":["../../../src/commands/synth.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAC1E,uDAAuD;AACvD,EAAE;AACF,yEAAyE;AACzE,2EAA2E;AAC3E,6EAA6E;AAC7E,OAAO,EAAE,2BAA2B,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEzF,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,
|
|
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,4 +1,5 @@
|
|
|
1
1
|
type Print = (...parts: unknown[]) => void;
|
|
2
|
+
/** The prefixed console every cli command prints through. */
|
|
2
3
|
export type Output = {
|
|
3
4
|
log: Print;
|
|
4
5
|
info: Print;
|
|
@@ -6,6 +7,6 @@ export type Output = {
|
|
|
6
7
|
error: Print;
|
|
7
8
|
time: (label: string) => void;
|
|
8
9
|
timeEnd: (label: string) => void;
|
|
10
|
+
rewriteLineAbove: (linesUp: number, text: string) => void;
|
|
9
11
|
};
|
|
10
|
-
export declare const createOutput: (area: string) => Output;
|
|
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"]}
|
|
@@ -6,11 +6,11 @@
|
|
|
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
11
|
import { getDeployTargetLabel } from './getDeployTargetLabel';
|
|
11
12
|
import { promptCheckbox, promptSelect, promptTypedConfirmation } from './prompts';
|
|
12
13
|
import { loadServiceQpqConfig } from './qpqConfigs';
|
|
13
|
-
import { createOutput } from './out';
|
|
14
14
|
const out = createOutput('clear-resources-plan');
|
|
15
15
|
// Every owned data resource across the app's services, in service order.
|
|
16
16
|
const getClearableResources = (appName) => {
|
|
@@ -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,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,uBAAuB,EAAE,MAAM,WAAW,CAAC;AAClF,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;
|
|
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,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,uBAAuB,EAAE,MAAM,WAAW,CAAC;AAClF,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAEpD,MAAM,GAAG,GAAG,YAAY,CAAC,sBAAsB,CAAC,CAAC;AAiBjD,yEAAyE;AACzE,MAAM,qBAAqB,GAAG,CAAC,OAAe,EAAuB,EAAE;IACrE,MAAM,SAAS,GAAwB,EAAE,CAAC;IAE1C,KAAK,MAAM,OAAO,IAAI,eAAe,CAAC,OAAO,CAAC,EAAE,CAAC;QAC/C,MAAM,SAAS,GAAG,oBAAoB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAEzD,KAAK,MAAM,KAAK,IAAI,YAAY,CAAC,2BAA2B,CAAC,SAAS,CAAC,EAAE,CAAC;YACxE,SAAS,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,cAAc,EAAE,YAAY,EAAE,KAAK,CAAC,YAAY,EAAE,CAAC,CAAC;QACtF,CAAC;QAED,KAAK,MAAM,KAAK,IAAI,YAAY,CAAC,4BAA4B,CAAC,SAAS,CAAC,EAAE,CAAC;YACzE,SAAS,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,eAAe,EAAE,YAAY,EAAE,KAAK,CAAC,iBAAiB,EAAE,CAAC,CAAC;QAC5F,CAAC;IACH,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC,CAAC;AAEF,MAAM,UAAU,GAAG,yDAAyD,CAAC;AAC7E,MAAM,WAAW,GAAG,8CAA8C,CAAC;AAEnE,kEAAkE;AAClE,MAAM,aAAa,GAAG,KAAK,EAAE,SAA8B,EAAgC,EAAE;IAC3F,MAAM,QAAQ,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IAE7E,MAAM,QAAQ,GAAG,CAAC,OAAe,EAAE,EAAE,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,OAAO,KAAK,OAAO,CAAC,CAAC,MAAM,CAAC;IAE1G,MAAM,MAAM,GAAG,MAAM,cAAc,CACjC,gEAAgE,EAChE,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,GAAG,OAAO,KAAK,QAAQ,CAAC,OAAO,CAAC,aAAa,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC,CACrG,CAAC;IAEF,OAAO,SAAS,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;AAC3E,CAAC,CAAC;AAEF,iDAAiD;AACjD,MAAM,cAAc,GAAG,CAAC,SAA8B,EAAgC,EAAE,CACtF,cAAc,CACZ,6DAA6D,EAC7D,SAAS,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;IAC3B,IAAI,EAAE,GAAG,QAAQ,CAAC,OAAO,MAAM,QAAQ,CAAC,YAAY,KAAK,QAAQ,CAAC,IAAI,KAAK,cAAc,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,GAAG;IACjH,KAAK,EAAE,QAAQ;CAChB,CAAC,CAAC,CACJ,CAAC;AAEJ,MAAM,CAAC,MAAM,wBAAwB,GAAG,KAAK,EAAE,OAAe,EAA+B,EAAE;IAC7F,MAAM,UAAU,GAAG,oBAAoB,EAAE,CAAC;IAE1C,MAAM,SAAS,GAAG,qBAAqB,CAAC,OAAO,CAAC,CAAC;IAEjD,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC3B,GAAG,CAAC,GAAG,CAAC,0DAA0D,CAAC,CAAC;QACpE,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC;IAC/B,CAAC;IAED,MAAM,IAAI,GAAG,MAAM,YAAY,CAAC,0CAA0C,EAAE,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC,CAAC;IAEvG,MAAM,SAAS,GAAG,IAAI,KAAK,UAAU,CAAC,CAAC,CAAC,MAAM,aAAa,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,MAAM,cAAc,CAAC,SAAS,CAAC,CAAC;IAEzG,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC3B,GAAG,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC;QACtC,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC;IAC/B,CAAC;IAED,GAAG,CAAC,GAAG,CAAC,mDAAmD,SAAS,CAAC,MAAM,oBAAoB,UAAU,IAAI,CAAC,CAAC;IAC/G,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;QACjC,GAAG,CAAC,GAAG,CAAC,KAAK,QAAQ,CAAC,OAAO,MAAM,QAAQ,CAAC,YAAY,KAAK,QAAQ,CAAC,IAAI,KAAK,cAAc,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,GAAG,CAAC,CAAC;IACzH,CAAC;IAED,IAAI,CAAC,CAAC,MAAM,uBAAuB,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC;QACjD,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC;IAC/B,CAAC;IAED,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC;AACnD,CAAC,CAAC","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"]}
|
|
@@ -2,14 +2,20 @@
|
|
|
2
2
|
// commands reads as one program. This is the only place the cli touches the console.
|
|
3
3
|
export const createOutput = (area) => {
|
|
4
4
|
const prefix = `[qpq:${area}]`;
|
|
5
|
-
//
|
|
6
|
-
//
|
|
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
|
|
7
13
|
// looked up per call, not captured, so a test can spy on it after this module loads.
|
|
8
14
|
const withPrefix = (method) => {
|
|
9
15
|
return (...parts) => {
|
|
10
16
|
const [first, ...rest] = parts;
|
|
11
17
|
if (typeof first === 'string') {
|
|
12
|
-
return console[method](
|
|
18
|
+
return console[method](prefixLines(first), ...rest);
|
|
13
19
|
}
|
|
14
20
|
return console[method](prefix, ...parts);
|
|
15
21
|
};
|
|
@@ -21,6 +27,9 @@ export const createOutput = (area) => {
|
|
|
21
27
|
error: withPrefix('error'),
|
|
22
28
|
time: (label) => console.time(`${prefix} ${label}`),
|
|
23
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
|
+
},
|
|
24
33
|
};
|
|
25
34
|
};
|
|
26
|
-
//# sourceMappingURL=
|
|
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,9 +1,9 @@
|
|
|
1
1
|
import { getPositionalArgs } from './args';
|
|
2
|
+
import { CliError } from './CliError';
|
|
3
|
+
import { createOutput } from './createOutput';
|
|
2
4
|
import { getServiceNames } from './discovery';
|
|
3
5
|
import { getDeployTargetLabel } from './getDeployTargetLabel';
|
|
4
6
|
import { promptSelect, promptTypedConfirmation, promptYesNo } from './prompts';
|
|
5
|
-
import { CliError } from './CliError';
|
|
6
|
-
import { createOutput } from './out';
|
|
7
7
|
const out = createOutput('deploy-prompts');
|
|
8
8
|
const STACK_TYPES = ['all', 'inf', 'api', 'web', 'views'];
|
|
9
9
|
// Non-interactive deploy plan from positional args: `qpq go <services> [stacks]`.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"deployPrompts.js","sourceRoot":"","sources":["../../../src/lib/deployPrompts.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,iBAAiB,EAAE,MAAM,QAAQ,CAAC;AAC3C,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,uBAAuB,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAC/E,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAErC,MAAM,GAAG,GAAG,YAAY,CAAC,gBAAgB,CAAC,CAAC;AAI3C,MAAM,WAAW,GAAgB,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;AAgBvE,kFAAkF;AAClF,yFAAyF;AACzF,yEAAyE;AACzE,gFAAgF;AAChF,+EAA+E;AAC/E,gFAAgF;AAChF,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,OAAe,EAAE,IAAc,EAAwB,EAAE;IAC/F,MAAM,CAAC,WAAW,EAAE,SAAS,CAAC,GAAG,iBAAiB,CAAC,IAAI,EAAE,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC,CAAC;IAEpF,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;QAC9B,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC;IACtC,CAAC;IACD,IAAI,WAAW,KAAK,QAAQ,EAAE,CAAC;QAC7B,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC;IAC7D,CAAC;IACD,IAAI,WAAW,KAAK,WAAW,EAAE,CAAC;QAChC,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,aAAa,EAAE,KAAK,EAAE,CAAC;IAC9D,CAAC;IAED,MAAM,WAAW,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC;IAC7C,MAAM,QAAQ,GACZ,WAAW,KAAK,KAAK;QACnB,CAAC,CAAC,WAAW;QACb,CAAC,CAAC,WAAW;aACR,KAAK,CAAC,GAAG,CAAC;aACV,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;aACpB,MAAM,CAAC,OAAO,CAAC,CAAC;IAEzB,MAAM,eAAe,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,WAAW,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;IACrF,IAAI,eAAe,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC/B,MAAM,IAAI,QAAQ,CAAC,uBAAuB,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,qBAAqB,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACrH,CAAC;IAED,MAAM,MAAM,GAAG,CAAC,SAAS,IAAI,KAAK,CAAc,CAAC;IACjD,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;QAClC,MAAM,IAAI,QAAQ,CAAC,mBAAmB,SAAS,oBAAoB,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC/F,CAAC;IAED,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC;AACjF,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,gBAAgB,GAAG,KAAK,EAAE,OAAe,EAAuB,EAAE;IAC7E,MAAM,UAAU,GAAG,oBAAoB,EAAE,CAAC;IAE1C,IAAI,CAAC,CAAC,MAAM,WAAW,CAAC,kBAAkB,UAAU,GAAG,CAAC,CAAC,EAAE,CAAC;QAC1D,GAAG,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QACpB,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC;IAC/B,CAAC;IAED,IAAI,QAAQ,GAAa,EAAE,CAAC;IAE5B,GAAG,CAAC;QACF,MAAM,WAAW,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC;QAE7C,uEAAuE;QACvE,MAAM,OAAO,GAAG,SAAS,CAAC;QAC1B,MAAM,WAAW,GAAG,aAAa,CAAC;QAClC,MAAM,aAAa,GAAG,YAAY,CAAC;QACnC,MAAM,gBAAgB,GAAG,2BAA2B,CAAC;QAErD,MAAM,OAAO,GAAG,MAAM,YAAY,CAAC,2BAA2B,EAAE,CAAC,OAAO,EAAE,GAAG,WAAW,EAAE,WAAW,EAAE,aAAa,EAAE,gBAAgB,CAAC,CAAC,CAAC;QAEzI,IAAI,OAAO,KAAK,OAAO,EAAE,CAAC;YACxB,QAAQ,GAAG,WAAW,CAAC;YACvB,MAAM;QACR,CAAC;QACD,IAAI,OAAO,KAAK,WAAW,EAAE,CAAC;YAC5B,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC;QACtC,CAAC;QACD,IAAI,OAAO,KAAK,aAAa,EAAE,CAAC;YAC9B,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC;QAC7D,CAAC;QACD,IAAI,OAAO,KAAK,gBAAgB,EAAE,CAAC;YACjC,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,aAAa,EAAE,KAAK,EAAE,CAAC;QAC9D,CAAC;QAED,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACzB,CAAC,QAAQ,MAAM,WAAW,CAAC,wCAAwC,CAAC,EAAE;IAEtE,QAAQ,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC;IAElC,MAAM,MAAM,GAAG,CAAC,MAAM,YAAY,CAAC,kBAAkB,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC,CAAc,CAAC;IAE5G,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;AACzD,CAAC,CAAC;AAOF,4EAA4E;AAC5E,2EAA2E;AAC3E,4EAA4E;AAC5E,MAAM,CAAC,MAAM,kBAAkB,GAAG,KAAK,EAAE,OAAe,EAAyB,EAAE;IACjF,MAAM,UAAU,GAAG,oBAAoB,EAAE,CAAC;IAE1C,IAAI,QAAQ,GAAa,EAAE,CAAC;IAE5B,GAAG,CAAC;QACF,MAAM,WAAW,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC;QAC7C,MAAM,OAAO,GAAG,SAAS,CAAC;QAE1B,MAAM,OAAO,GAAG,MAAM,YAAY,CAAC,8BAA8B,EAAE,CAAC,OAAO,EAAE,GAAG,WAAW,CAAC,CAAC,CAAC;QAE9F,IAAI,OAAO,KAAK,OAAO,EAAE,CAAC;YACxB,QAAQ,GAAG,WAAW,CAAC;YACvB,MAAM;QACR,CAAC;QAED,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACzB,CAAC,QAAQ,MAAM,WAAW,CAAC,2CAA2C,CAAC,EAAE;IAEzE,QAAQ,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC;IAElC,GAAG,CAAC,GAAG,CAAC,oFAAoF,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACnH,IAAI,CAAC,CAAC,MAAM,uBAAuB,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC;QACjD,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC;IAC/B,CAAC;IAED,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC;AACjD,CAAC,CAAC","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 { getServiceNames } from './discovery';\nimport { getDeployTargetLabel } from './getDeployTargetLabel';\nimport { promptSelect, promptTypedConfirmation, promptYesNo } from './prompts';\nimport { CliError } from './CliError';\nimport { createOutput } from './out';\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
|
+
{"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"]}
|
package/lib/esm/lib/hooks.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import fs from 'fs';
|
|
2
2
|
import path from 'path';
|
|
3
|
+
import { createOutput } from './createOutput';
|
|
3
4
|
import { getAppDirectory, getAppsDirectory, getAvailableApps, getRoot } from './discovery';
|
|
4
5
|
import { nextPrefixColor, runCommand, runCommandPrefixed } from './runCommand';
|
|
5
6
|
import { runDependencyTasks } from './runTasks';
|
|
6
|
-
import { createOutput } from './out';
|
|
7
7
|
const out = createOutput('hooks');
|
|
8
8
|
// App lifecycle hooks: apps/<app>/package.json scripts named `qpq:<hook>`
|
|
9
9
|
// (e.g. qpq:postinstall, qpq:prebuild). The CLI invokes them when present;
|
package/lib/esm/lib/hooks.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hooks.js","sourceRoot":"","sources":["../../../src/lib/hooks.ts"],"names":[],"mappings":"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","sourcesContent":["import fs from 'fs';\nimport path from 'path';\n\nimport { getAppDirectory, getAppsDirectory, getAvailableApps, getRoot } from './discovery';\nimport { nextPrefixColor, runCommand, runCommandPrefixed } from './runCommand';\nimport { runDependencyTasks, TaskFailure } from './runTasks';\nimport { createOutput } from './out';\n\nconst out = createOutput('hooks');\n\ntype HookPackageJson = {\n name?: string;\n scripts?: Record<string, string>;\n workspaces?: string[];\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n peerDependencies?: Record<string, string>;\n};\n\n// A directory whose package.json can carry qpq:<hook> scripts: either an app\n// (apps/<app>/package.json, which need not be an npm workspace) or any package\n// matched by the consumer root's `workspaces` globs.\ntype HookPackage = {\n dir: string;\n label: string; // app name or package name, for display\n pkg: HookPackageJson;\n};\n\n// App lifecycle hooks: apps/<app>/package.json scripts named `qpq:<hook>`\n// (e.g. qpq:postinstall, qpq:prebuild). The CLI invokes them when present;\n// apps without the hook are skipped silently.\nexport const runAppHook = async (appName: string, hook: string): Promise<boolean> => {\n const packageJsonPath = path.join(getAppDirectory(appName), 'package.json');\n if (!fs.existsSync(packageJsonPath)) {\n return false;\n }\n\n const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));\n const scriptName = `qpq:${hook}`;\n if (!packageJson.scripts?.[scriptName]) {\n return false;\n }\n\n out.log(`Running ${scriptName} for [${appName}]`);\n await runCommand('npm', ['run', scriptName], { cwd: getAppDirectory(appName) });\n return true;\n};\n\nconst isDirectory = (candidate: string): boolean => fs.existsSync(candidate) && fs.statSync(candidate).isDirectory();\n\nconst listSubdirectories = (dir: string): string[] => {\n if (!isDirectory(dir)) {\n return [];\n }\n return fs\n .readdirSync(dir)\n .map((name) => path.join(dir, name))\n .filter(isDirectory);\n};\n\n// Expand one `workspaces` glob. Only literal segments and bare `*` are\n// supported, which covers the patterns qpq repos use (e.g.\n// \"apps/*/services/*/models\"); anything fancier (\"**\", braces) matches nothing.\nconst expandWorkspacePattern = (root: string, pattern: string): string[] => {\n let dirs = [root];\n for (const segment of pattern.split('/')) {\n if (segment === '*') {\n dirs = dirs.flatMap(listSubdirectories);\n } else {\n dirs = dirs.map((dir) => path.join(dir, segment)).filter(isDirectory);\n }\n }\n return dirs;\n};\n\nconst readPackageJson = (dir: string): HookPackageJson | undefined => {\n const packageJsonPath = path.join(dir, 'package.json');\n if (!fs.existsSync(packageJsonPath)) {\n return undefined;\n }\n return JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8')) as HookPackageJson;\n};\n\n// Every directory that can carry hooks: app dirs plus all workspace packages,\n// deduped (an app dir could itself be a workspace).\nconst getHookPackages = (): HookPackage[] => {\n const root = getRoot();\n const rootPkg = readPackageJson(root);\n\n const appDirs = getAvailableApps().map((appName) => ({ dir: getAppDirectory(appName), fallbackLabel: appName }));\n const workspaceDirs = (rootPkg?.workspaces ?? [])\n .flatMap((pattern) => expandWorkspacePattern(root, pattern))\n .map((dir) => ({ dir, fallbackLabel: path.relative(root, dir) }));\n\n const packages: HookPackage[] = [];\n const seen = new Set<string>();\n for (const { dir, fallbackLabel } of [...appDirs, ...workspaceDirs]) {\n const resolved = path.resolve(dir);\n if (seen.has(resolved)) {\n continue;\n }\n seen.add(resolved);\n\n const pkg = readPackageJson(dir);\n if (pkg) {\n packages.push({ dir, label: pkg.name ?? fallbackLabel, pkg });\n }\n }\n\n return packages;\n};\n\n// The script a hook resolves to in one package: `qpq:<hook>` when defined,\n// otherwise the plain `<hook>` script. Empty-string scripts count as absent.\nconst resolveHookScript = (pkg: HookPackageJson, hook: string): string | undefined => {\n if (pkg.scripts?.[`qpq:${hook}`]) {\n return `qpq:${hook}`;\n }\n if (pkg.scripts?.[hook]) {\n return hook;\n }\n return undefined;\n};\n\nconst getDeclaredDependencyNames = (pkg: HookPackageJson): string[] =>\n Object.keys({ ...pkg.dependencies, ...pkg.devDependencies, ...pkg.peerDependencies });\n\n// True for a package inside apps/<some other app>/. Packages outside apps/\n// are shared, so they never count as another app's.\nconst isOtherAppPackage = (dir: string, appName: string): boolean => {\n const relative = path.relative(getAppsDirectory(), path.resolve(dir));\n if (relative === '' || relative.startsWith('..') || path.isAbsolute(relative)) {\n return false;\n }\n return relative.split(path.sep)[0] !== appName;\n};\n\n// The app's own packages and the shared ones, plus every package they depend\n// on wherever it lives, so a cross-app dependency still gets built.\nconst getAppHookPackages = (appName: string): HookPackage[] => {\n const allPackages = getHookPackages();\n const byName = new Map<string, HookPackage>();\n for (const hookPackage of allPackages) {\n if (hookPackage.pkg.name) {\n byName.set(hookPackage.pkg.name, hookPackage);\n }\n }\n\n const selected = new Set(allPackages.filter((hookPackage) => !isOtherAppPackage(hookPackage.dir, appName)));\n const pending = [...selected];\n for (let current = pending.pop(); current; current = pending.pop()) {\n for (const depName of getDeclaredDependencyNames(current.pkg)) {\n const dep = byName.get(depName);\n if (dep && !selected.has(dep)) {\n selected.add(dep);\n pending.push(dep);\n }\n }\n }\n\n return allPackages.filter((hookPackage) => selected.has(hookPackage));\n};\n\n// Run the hook's script in each of `candidates` that defines it (qpq:<hook>\n// preferred over a plain <hook> script), in dependency order (declared deps\n// resolved by package name), with up to `jobs` running concurrently. Packages\n// whose dependencies aren't part of this run don't wait on them.\nconst runHookForPackages = async (candidates: HookPackage[], hook: string, jobs: number): Promise<TaskFailure[]> => {\n const hookPackages = candidates\n .map((candidate) => ({ ...candidate, scriptName: resolveHookScript(candidate.pkg, hook) }))\n .filter((candidate): candidate is HookPackage & { scriptName: string } => candidate.scriptName !== undefined);\n\n if (hookPackages.length === 0) {\n out.log(`No app or workspace package defines a \"qpq:${hook}\" or \"${hook}\" script, nothing to run.`);\n return [];\n }\n\n // Dependency edges only count between packages that are part of this run:\n // a dep that doesn't define the hook has nothing to wait for.\n const runSetNames = new Set(hookPackages.map((hookPackage) => hookPackage.pkg.name).filter(Boolean));\n\n const tasks = hookPackages.map((hookPackage) => ({\n id: hookPackage.pkg.name ?? hookPackage.dir,\n label: hookPackage.label,\n deps: getDeclaredDependencyNames(hookPackage.pkg).filter((name) => runSetNames.has(name) && name !== hookPackage.pkg.name),\n run: () => runCommandPrefixed(hookPackage.label, 'npm', ['run', hookPackage.scriptName], { cwd: hookPackage.dir, color: nextPrefixColor() }),\n }));\n\n out.log(`Running ${hook} hooks in ${tasks.length} package(s) (${jobs} jobs, dependency ordered)`);\n return runDependencyTasks(tasks, jobs);\n};\n\n/** Runs a hook in every app and workspace package that defines it. Returns the failures; callers decide fatality. */\nexport const runHookForAllPackages = (hook: string, jobs: number): Promise<TaskFailure[]> => runHookForPackages(getHookPackages(), hook, jobs);\n\n/**\n * Runs a hook in one app's packages, the shared packages outside apps/, and anything those depend on.\n * Other apps' packages are skipped. Returns the failures; callers decide fatality.\n */\nexport const runHookForAppPackages = (hook: string, appName: string, jobs: number): Promise<TaskFailure[]> =>\n runHookForPackages(getAppHookPackages(appName), hook, jobs);\n"]}
|
|
1
|
+
{"version":3,"file":"hooks.js","sourceRoot":"","sources":["../../../src/lib/hooks.ts"],"names":[],"mappings":"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","sourcesContent":["import fs from 'fs';\nimport path from 'path';\n\nimport { createOutput } from './createOutput';\nimport { getAppDirectory, getAppsDirectory, getAvailableApps, getRoot } from './discovery';\nimport { nextPrefixColor, runCommand, runCommandPrefixed } from './runCommand';\nimport { runDependencyTasks, TaskFailure } from './runTasks';\n\nconst out = createOutput('hooks');\n\ntype HookPackageJson = {\n name?: string;\n scripts?: Record<string, string>;\n workspaces?: string[];\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n peerDependencies?: Record<string, string>;\n};\n\n// A directory whose package.json can carry qpq:<hook> scripts: either an app\n// (apps/<app>/package.json, which need not be an npm workspace) or any package\n// matched by the consumer root's `workspaces` globs.\ntype HookPackage = {\n dir: string;\n label: string; // app name or package name, for display\n pkg: HookPackageJson;\n};\n\n// App lifecycle hooks: apps/<app>/package.json scripts named `qpq:<hook>`\n// (e.g. qpq:postinstall, qpq:prebuild). The CLI invokes them when present;\n// apps without the hook are skipped silently.\nexport const runAppHook = async (appName: string, hook: string): Promise<boolean> => {\n const packageJsonPath = path.join(getAppDirectory(appName), 'package.json');\n if (!fs.existsSync(packageJsonPath)) {\n return false;\n }\n\n const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));\n const scriptName = `qpq:${hook}`;\n if (!packageJson.scripts?.[scriptName]) {\n return false;\n }\n\n out.log(`Running ${scriptName} for [${appName}]`);\n await runCommand('npm', ['run', scriptName], { cwd: getAppDirectory(appName) });\n return true;\n};\n\nconst isDirectory = (candidate: string): boolean => fs.existsSync(candidate) && fs.statSync(candidate).isDirectory();\n\nconst listSubdirectories = (dir: string): string[] => {\n if (!isDirectory(dir)) {\n return [];\n }\n return fs\n .readdirSync(dir)\n .map((name) => path.join(dir, name))\n .filter(isDirectory);\n};\n\n// Expand one `workspaces` glob. Only literal segments and bare `*` are\n// supported, which covers the patterns qpq repos use (e.g.\n// \"apps/*/services/*/models\"); anything fancier (\"**\", braces) matches nothing.\nconst expandWorkspacePattern = (root: string, pattern: string): string[] => {\n let dirs = [root];\n for (const segment of pattern.split('/')) {\n if (segment === '*') {\n dirs = dirs.flatMap(listSubdirectories);\n } else {\n dirs = dirs.map((dir) => path.join(dir, segment)).filter(isDirectory);\n }\n }\n return dirs;\n};\n\nconst readPackageJson = (dir: string): HookPackageJson | undefined => {\n const packageJsonPath = path.join(dir, 'package.json');\n if (!fs.existsSync(packageJsonPath)) {\n return undefined;\n }\n return JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8')) as HookPackageJson;\n};\n\n// Every directory that can carry hooks: app dirs plus all workspace packages,\n// deduped (an app dir could itself be a workspace).\nconst getHookPackages = (): HookPackage[] => {\n const root = getRoot();\n const rootPkg = readPackageJson(root);\n\n const appDirs = getAvailableApps().map((appName) => ({ dir: getAppDirectory(appName), fallbackLabel: appName }));\n const workspaceDirs = (rootPkg?.workspaces ?? [])\n .flatMap((pattern) => expandWorkspacePattern(root, pattern))\n .map((dir) => ({ dir, fallbackLabel: path.relative(root, dir) }));\n\n const packages: HookPackage[] = [];\n const seen = new Set<string>();\n for (const { dir, fallbackLabel } of [...appDirs, ...workspaceDirs]) {\n const resolved = path.resolve(dir);\n if (seen.has(resolved)) {\n continue;\n }\n seen.add(resolved);\n\n const pkg = readPackageJson(dir);\n if (pkg) {\n packages.push({ dir, label: pkg.name ?? fallbackLabel, pkg });\n }\n }\n\n return packages;\n};\n\n// The script a hook resolves to in one package: `qpq:<hook>` when defined,\n// otherwise the plain `<hook>` script. Empty-string scripts count as absent.\nconst resolveHookScript = (pkg: HookPackageJson, hook: string): string | undefined => {\n if (pkg.scripts?.[`qpq:${hook}`]) {\n return `qpq:${hook}`;\n }\n if (pkg.scripts?.[hook]) {\n return hook;\n }\n return undefined;\n};\n\nconst getDeclaredDependencyNames = (pkg: HookPackageJson): string[] =>\n Object.keys({ ...pkg.dependencies, ...pkg.devDependencies, ...pkg.peerDependencies });\n\n// True for a package inside apps/<some other app>/. Packages outside apps/\n// are shared, so they never count as another app's.\nconst isOtherAppPackage = (dir: string, appName: string): boolean => {\n const relative = path.relative(getAppsDirectory(), path.resolve(dir));\n if (relative === '' || relative.startsWith('..') || path.isAbsolute(relative)) {\n return false;\n }\n return relative.split(path.sep)[0] !== appName;\n};\n\n// The app's own packages and the shared ones, plus every package they depend\n// on wherever it lives, so a cross-app dependency still gets built.\nconst getAppHookPackages = (appName: string): HookPackage[] => {\n const allPackages = getHookPackages();\n const byName = new Map<string, HookPackage>();\n for (const hookPackage of allPackages) {\n if (hookPackage.pkg.name) {\n byName.set(hookPackage.pkg.name, hookPackage);\n }\n }\n\n const selected = new Set(allPackages.filter((hookPackage) => !isOtherAppPackage(hookPackage.dir, appName)));\n const pending = [...selected];\n for (let current = pending.pop(); current; current = pending.pop()) {\n for (const depName of getDeclaredDependencyNames(current.pkg)) {\n const dep = byName.get(depName);\n if (dep && !selected.has(dep)) {\n selected.add(dep);\n pending.push(dep);\n }\n }\n }\n\n return allPackages.filter((hookPackage) => selected.has(hookPackage));\n};\n\n// Run the hook's script in each of `candidates` that defines it (qpq:<hook>\n// preferred over a plain <hook> script), in dependency order (declared deps\n// resolved by package name), with up to `jobs` running concurrently. Packages\n// whose dependencies aren't part of this run don't wait on them.\nconst runHookForPackages = async (candidates: HookPackage[], hook: string, jobs: number): Promise<TaskFailure[]> => {\n const hookPackages = candidates\n .map((candidate) => ({ ...candidate, scriptName: resolveHookScript(candidate.pkg, hook) }))\n .filter((candidate): candidate is HookPackage & { scriptName: string } => candidate.scriptName !== undefined);\n\n if (hookPackages.length === 0) {\n out.log(`No app or workspace package defines a \"qpq:${hook}\" or \"${hook}\" script, nothing to run.`);\n return [];\n }\n\n // Dependency edges only count between packages that are part of this run:\n // a dep that doesn't define the hook has nothing to wait for.\n const runSetNames = new Set(hookPackages.map((hookPackage) => hookPackage.pkg.name).filter(Boolean));\n\n const tasks = hookPackages.map((hookPackage) => ({\n id: hookPackage.pkg.name ?? hookPackage.dir,\n label: hookPackage.label,\n deps: getDeclaredDependencyNames(hookPackage.pkg).filter((name) => runSetNames.has(name) && name !== hookPackage.pkg.name),\n run: () => runCommandPrefixed(hookPackage.label, 'npm', ['run', hookPackage.scriptName], { cwd: hookPackage.dir, color: nextPrefixColor() }),\n }));\n\n out.log(`Running ${hook} hooks in ${tasks.length} package(s) (${jobs} jobs, dependency ordered)`);\n return runDependencyTasks(tasks, jobs);\n};\n\n/** Runs a hook in every app and workspace package that defines it. Returns the failures; callers decide fatality. */\nexport const runHookForAllPackages = (hook: string, jobs: number): Promise<TaskFailure[]> => runHookForPackages(getHookPackages(), hook, jobs);\n\n/**\n * Runs a hook in one app's packages, the shared packages outside apps/, and anything those depend on.\n * Other apps' packages are skipped. Returns the failures; callers decide fatality.\n */\nexport const runHookForAppPackages = (hook: string, appName: string, jobs: number): Promise<TaskFailure[]> =>\n runHookForPackages(getAppHookPackages(appName), hook, jobs);\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createOutput } from './
|
|
1
|
+
import { createOutput } from './createOutput';
|
|
2
2
|
const out = createOutput('kill-child-with-escalation');
|
|
3
3
|
// Above the dev server's 5s worst-case shutdown budget, below docker's 10s
|
|
4
4
|
// default stop grace, so a container stop still exits cleanly rather than
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"killChildWithEscalation.js","sourceRoot":"","sources":["../../../src/lib/killChildWithEscalation.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"killChildWithEscalation.js","sourceRoot":"","sources":["../../../src/lib/killChildWithEscalation.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE9C,MAAM,GAAG,GAAG,YAAY,CAAC,4BAA4B,CAAC,CAAC;AAEvD,2EAA2E;AAC3E,0EAA0E;AAC1E,4CAA4C;AAC5C,MAAM,qBAAqB,GAAG,IAAI,CAAC;AAEnC;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,KAAmB,EAAE,OAAO,GAAG,qBAAqB,EAAiB,EAAE;IAC7G,IAAI,KAAK,CAAC,QAAQ,KAAK,IAAI,IAAI,KAAK,CAAC,UAAU,KAAK,IAAI,EAAE,CAAC;QACzD,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;IAC3B,CAAC;IAED,OAAO,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;QACnC,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;YAC5B,GAAG,CAAC,IAAI,CAAC,kCAAkC,OAAO,uBAAuB,CAAC,CAAC;YAC3E,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACxB,CAAC,EAAE,OAAO,CAAC,CAAC;QAEZ,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE;YACtB,YAAY,CAAC,KAAK,CAAC,CAAC;YACpB,OAAO,EAAE,CAAC;QACZ,CAAC,CAAC,CAAC;QAEH,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IACxB,CAAC,CAAC,CAAC;AACL,CAAC,CAAC","sourcesContent":["// Stopping the dev server child, with a hard backstop.\n//\n// The dev server now runs an ordered shutdown on SIGTERM (drain in-flight\n// work, then checkpoint the stores) instead of dying instantly. That is the\n// point - it is what stops a save-triggered restart eating a queue message\n// mid-story - but it means a bare `child.kill()` followed by waiting for exit\n// can now wait forever if a teardown wedges. Without escalation this would\n// trade a data-loss bug for a hung-restart bug, and the next launch would find\n// its ports still held.\nimport { ChildProcess } from 'child_process';\n\nimport { createOutput } from './createOutput';\n\nconst out = createOutput('kill-child-with-escalation');\n\n// Above the dev server's 5s worst-case shutdown budget, below docker's 10s\n// default stop grace, so a container stop still exits cleanly rather than\n// being SIGKILLed by docker mid-escalation.\nconst DEFAULT_KILL_GRACE_MS = 6000;\n\n/**\n * SIGTERM the child, resolve once it has actually exited, and SIGKILL it if it\n * has not gone within the grace window.\n *\n * Resolves rather than rejects on escalation: the caller's next move is the\n * same either way (start the replacement), and a rejection would only give\n * every call site a catch to write.\n */\nexport const killChildWithEscalation = (child: ChildProcess, graceMs = DEFAULT_KILL_GRACE_MS): Promise<void> => {\n if (child.exitCode !== null || child.signalCode !== null) {\n return Promise.resolve();\n }\n\n return new Promise<void>((resolve) => {\n const timer = setTimeout(() => {\n out.warn(`Dev server did not exit within ${graceMs}ms — sending SIGKILL.`);\n child.kill('SIGKILL');\n }, graceMs);\n\n child.once('exit', () => {\n clearTimeout(timer);\n resolve();\n });\n\n child.kill('SIGTERM');\n });\n};\n"]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { runCommandCaptureSync, sleepSync } from './runCommand';
|
|
2
1
|
import fs from 'fs';
|
|
3
2
|
import path from 'path';
|
|
4
|
-
import { createOutput } from './
|
|
3
|
+
import { createOutput } from './createOutput';
|
|
4
|
+
import { runCommandCaptureSync, sleepSync } from './runCommand';
|
|
5
5
|
const out = createOutput('kill-stale-listeners');
|
|
6
6
|
// Matches any invocation of the qpq CLI itself, regardless of how it was
|
|
7
7
|
// launched: `node node_modules/.bin/qpq ...` (the npm-script shim, which has
|