quidproquo-cli 0.1.6 → 0.1.8
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/docker/dev-server/Dockerfile +7 -9
- package/lib/commonjs/cli/commandMenu.d.ts +2 -0
- package/lib/commonjs/cli/commandMenu.js +81 -0
- package/lib/commonjs/cli/commandMenu.js.map +1 -0
- package/lib/commonjs/cli/commandRegistry.d.ts +10 -0
- package/lib/commonjs/cli/commandRegistry.js +131 -0
- package/lib/commonjs/cli/commandRegistry.js.map +1 -0
- package/lib/commonjs/cli/runCli.js +49 -49
- package/lib/commonjs/cli/runCli.js.map +1 -1
- package/lib/commonjs/commands/clearResources.d.ts +1 -0
- package/lib/commonjs/commands/clearResources.js +36 -0
- package/lib/commonjs/commands/clearResources.js.map +1 -0
- package/lib/commonjs/commands/go.js +3 -1
- package/lib/commonjs/commands/go.js.map +1 -1
- package/lib/commonjs/commands/goDev.js +23 -122
- package/lib/commonjs/commands/goDev.js.map +1 -1
- package/lib/commonjs/commands/goDevApi.d.ts +1 -0
- package/lib/commonjs/commands/goDevApi.js +110 -0
- package/lib/commonjs/commands/goDevApi.js.map +1 -0
- package/lib/commonjs/commands/goDevWeb.d.ts +4 -1
- package/lib/commonjs/commands/goDevWeb.js +4 -2
- package/lib/commonjs/commands/goDevWeb.js.map +1 -1
- package/lib/commonjs/commands/goDocker.js +3 -1
- package/lib/commonjs/commands/goDocker.js.map +1 -1
- package/lib/commonjs/commands/hooks.js +23 -5
- package/lib/commonjs/commands/hooks.js.map +1 -1
- package/lib/commonjs/lib/clearResourcesPlan.d.ts +15 -0
- package/lib/commonjs/lib/clearResourcesPlan.js +80 -0
- package/lib/commonjs/lib/clearResourcesPlan.js.map +1 -0
- package/lib/commonjs/lib/deployPrompts.d.ts +1 -0
- package/lib/commonjs/lib/deployPrompts.js +40 -2
- package/lib/commonjs/lib/deployPrompts.js.map +1 -1
- package/lib/commonjs/lib/devServerEntry.js +3 -0
- package/lib/commonjs/lib/devServerEntry.js.map +1 -1
- package/lib/commonjs/lib/hooks.d.ts +2 -1
- package/lib/commonjs/lib/hooks.js +100 -5
- package/lib/commonjs/lib/hooks.js.map +1 -1
- package/lib/commonjs/lib/killStaleListeners.d.ts +3 -0
- package/lib/commonjs/lib/killStaleListeners.js +170 -0
- package/lib/commonjs/lib/killStaleListeners.js.map +1 -0
- package/lib/commonjs/lib/prompts.d.ts +10 -0
- package/lib/commonjs/lib/prompts.js +15 -1
- 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 -1
- package/lib/commonjs/lib/qpqConfigs.js.map +1 -1
- package/lib/commonjs/lib/resolveAppSelection.js +1 -1
- package/lib/commonjs/lib/resolveAppSelection.js.map +1 -1
- package/lib/commonjs/lib/runTasks.d.ts +5 -0
- package/lib/commonjs/lib/runTasks.js +82 -1
- package/lib/commonjs/lib/runTasks.js.map +1 -1
- package/lib/commonjs/lib/typeWatcher.d.ts +2 -0
- package/lib/commonjs/lib/typeWatcher.js +59 -0
- package/lib/commonjs/lib/typeWatcher.js.map +1 -0
- package/lib/commonjs/platforms/aws/cdkApp.js +5 -1
- package/lib/commonjs/platforms/aws/cdkApp.js.map +1 -1
- package/lib/commonjs/platforms/aws/clearResources.d.ts +2 -0
- package/lib/commonjs/platforms/aws/clearResources.js +167 -0
- package/lib/commonjs/platforms/aws/clearResources.js.map +1 -0
- package/lib/commonjs/platforms/aws/go.js +15 -1
- package/lib/commonjs/platforms/aws/go.js.map +1 -1
- package/lib/commonjs/platforms/aws/goDocker.js +76 -8
- package/lib/commonjs/platforms/aws/goDocker.js.map +1 -1
- package/lib/commonjs/platforms/aws/index.js +2 -0
- package/lib/commonjs/platforms/aws/index.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/types.d.ts +2 -0
- package/lib/commonjs/platforms/types.js.map +1 -1
- package/lib/esm/cli/commandMenu.d.ts +2 -0
- package/lib/esm/cli/commandMenu.js +67 -0
- package/lib/esm/cli/commandMenu.js.map +1 -0
- package/lib/esm/cli/commandRegistry.d.ts +10 -0
- package/lib/esm/cli/commandRegistry.js +115 -0
- package/lib/esm/cli/commandRegistry.js.map +1 -0
- package/lib/esm/cli/runCli.js +49 -49
- package/lib/esm/cli/runCli.js.map +1 -1
- package/lib/esm/commands/clearResources.d.ts +1 -0
- package/lib/esm/commands/clearResources.js +23 -0
- package/lib/esm/commands/clearResources.js.map +1 -0
- package/lib/esm/commands/go.js +3 -2
- package/lib/esm/commands/go.js.map +1 -1
- package/lib/esm/commands/goDev.js +24 -120
- package/lib/esm/commands/goDev.js.map +1 -1
- package/lib/esm/commands/goDevApi.d.ts +1 -0
- package/lib/esm/commands/goDevApi.js +94 -0
- package/lib/esm/commands/goDevApi.js.map +1 -0
- package/lib/esm/commands/goDevWeb.d.ts +4 -1
- package/lib/esm/commands/goDevWeb.js +4 -2
- package/lib/esm/commands/goDevWeb.js.map +1 -1
- package/lib/esm/commands/goDocker.js +3 -2
- package/lib/esm/commands/goDocker.js.map +1 -1
- package/lib/esm/commands/hooks.js +21 -6
- package/lib/esm/commands/hooks.js.map +1 -1
- package/lib/esm/lib/clearResourcesPlan.d.ts +15 -0
- package/lib/esm/lib/clearResourcesPlan.js +66 -0
- package/lib/esm/lib/clearResourcesPlan.js.map +1 -0
- package/lib/esm/lib/deployPrompts.d.ts +1 -0
- package/lib/esm/lib/deployPrompts.js +38 -1
- package/lib/esm/lib/deployPrompts.js.map +1 -1
- package/lib/esm/lib/devServerEntry.js +3 -0
- package/lib/esm/lib/devServerEntry.js.map +1 -1
- package/lib/esm/lib/hooks.d.ts +2 -1
- package/lib/esm/lib/hooks.js +97 -5
- package/lib/esm/lib/hooks.js.map +1 -1
- package/lib/esm/lib/killStaleListeners.d.ts +3 -0
- package/lib/esm/lib/killStaleListeners.js +161 -0
- package/lib/esm/lib/killStaleListeners.js.map +1 -0
- package/lib/esm/lib/prompts.d.ts +10 -0
- package/lib/esm/lib/prompts.js +12 -0
- 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 -0
- package/lib/esm/lib/qpqConfigs.js.map +1 -1
- package/lib/esm/lib/resolveAppSelection.js +1 -1
- package/lib/esm/lib/resolveAppSelection.js.map +1 -1
- package/lib/esm/lib/runTasks.d.ts +5 -0
- package/lib/esm/lib/runTasks.js +80 -0
- package/lib/esm/lib/runTasks.js.map +1 -1
- package/lib/esm/lib/typeWatcher.d.ts +2 -0
- package/lib/esm/lib/typeWatcher.js +51 -0
- package/lib/esm/lib/typeWatcher.js.map +1 -0
- package/lib/esm/platforms/aws/cdkApp.js +5 -1
- package/lib/esm/platforms/aws/cdkApp.js.map +1 -1
- package/lib/esm/platforms/aws/clearResources.d.ts +2 -0
- package/lib/esm/platforms/aws/clearResources.js +151 -0
- package/lib/esm/platforms/aws/clearResources.js.map +1 -0
- package/lib/esm/platforms/aws/go.js +16 -2
- package/lib/esm/platforms/aws/go.js.map +1 -1
- package/lib/esm/platforms/aws/goDocker.js +77 -9
- package/lib/esm/platforms/aws/goDocker.js.map +1 -1
- package/lib/esm/platforms/aws/index.js +2 -0
- package/lib/esm/platforms/aws/index.js.map +1 -1
- package/lib/esm/platforms/docker/go.js +2 -2
- package/lib/esm/platforms/docker/go.js.map +1 -1
- package/lib/esm/platforms/types.d.ts +2 -0
- package/lib/esm/platforms/types.js.map +1 -1
- package/package.json +12 -10
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"qpqConfigs.js","sourceRoot":"","sources":["../../../src/lib/qpqConfigs.ts"],"names":[],"mappings":";;;AAAA,qDAA+D;AAC/D,uEAAwE;AAExE,2CAAuD;AAEvD,wEAAwE;AACxE,2EAA2E;AAC3E,uBAAuB;AAChB,MAAM,oBAAoB,GAAG,CAAC,OAAe,EAAE,OAAe,EAAa,EAAE,CAAC,IAAA,uDAA4B,EAAC,IAAA,mBAAO,GAAE,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;AAAlI,QAAA,oBAAoB,wBAA8G;AAExI,MAAM,YAAY,GAAG,CAAC,OAAe,EAAU,EAAE;IACtD,MAAM,QAAQ,GAAG,IAAA,2BAAe,EAAC,OAAO,CAAC,CAAC;IAC1C,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,6BAA6B,OAAO,EAAE,CAAC,CAAC;IACnF,OAAO,8BAAY,CAAC,kBAAkB,CAAC,IAAA,4BAAoB,EAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACrF,CAAC,CAAC;AAJW,QAAA,YAAY,gBAIvB","sourcesContent":["import { type QPQConfig, qpqCoreUtils } from 'quidproquo-core';\nimport { getWorkspaceServiceQpqConfig } from 'quidproquo-deploy-awscdk';\n\nimport { getRoot, getServiceNames } from './discovery';\n\n// Loads a service's live infrastructure.ts (qpq runs with ts-node hooks\n// registered, so requiring TS works and `@scope/*` imports resolve through\n// workspace symlinks).\nexport const loadServiceQpqConfig = (appName: string, service: string): QPQConfig => getWorkspaceServiceQpqConfig(getRoot(), appName, service);\n\nexport const getAppPrefix = (appName: string): string => {\n const services = getServiceNames(appName);\n if (services.length === 0) throw new Error(`No services found for app ${appName}`);\n return qpqCoreUtils.getApplicationName(loadServiceQpqConfig(appName, services[0]));\n};\n"]}
|
|
1
|
+
{"version":3,"file":"qpqConfigs.js","sourceRoot":"","sources":["../../../src/lib/qpqConfigs.ts"],"names":[],"mappings":";;;AAAA,qDAA+D;AAC/D,uEAAwE;AAExE,2CAAuD;AAEvD,wEAAwE;AACxE,2EAA2E;AAC3E,uBAAuB;AAChB,MAAM,oBAAoB,GAAG,CAAC,OAAe,EAAE,OAAe,EAAa,EAAE,CAAC,IAAA,uDAA4B,EAAC,IAAA,mBAAO,GAAE,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;AAAlI,QAAA,oBAAoB,wBAA8G;AAExI,MAAM,YAAY,GAAG,CAAC,OAAe,EAAU,EAAE;IACtD,MAAM,QAAQ,GAAG,IAAA,2BAAe,EAAC,OAAO,CAAC,CAAC;IAC1C,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,6BAA6B,OAAO,EAAE,CAAC,CAAC;IACnF,OAAO,8BAAY,CAAC,kBAAkB,CAAC,IAAA,4BAAoB,EAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACrF,CAAC,CAAC;AAJW,QAAA,YAAY,gBAIvB;AAEF,+EAA+E;AAC/E,gFAAgF;AAChF,6EAA6E;AAC7E,8EAA8E;AAC9E,8EAA8E;AAC9E,4DAA4D;AACrD,MAAM,6BAA6B,GAAG,CAAC,OAAe,EAAE,YAAsB,EAAY,EAAE,CACjG,YAAY,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC,8BAAY,CAAC,uBAAuB,CAAC,IAAA,4BAAoB,EAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;AADtG,QAAA,6BAA6B,iCACyE","sourcesContent":["import { type QPQConfig, qpqCoreUtils } from 'quidproquo-core';\nimport { getWorkspaceServiceQpqConfig } from 'quidproquo-deploy-awscdk';\n\nimport { getRoot, getServiceNames } from './discovery';\n\n// Loads a service's live infrastructure.ts (qpq runs with ts-node hooks\n// registered, so requiring TS works and `@scope/*` imports resolve through\n// workspace symlinks).\nexport const loadServiceQpqConfig = (appName: string, service: string): QPQConfig => getWorkspaceServiceQpqConfig(getRoot(), appName, service);\n\nexport const getAppPrefix = (appName: string): string => {\n const services = getServiceNames(appName);\n if (services.length === 0) throw new Error(`No services found for app ${appName}`);\n return qpqCoreUtils.getApplicationName(loadServiceQpqConfig(appName, services[0]));\n};\n\n// The subset of the given services that opt into module-federation publishing,\n// i.e. declare defineFederatedModuleStore(...). Federation is a config setting,\n// not a directory convention (unlike views/ backends), so detecting it means\n// loading each service's config — which is why this lives here and not in the\n// directory-only discovery module. Used by the deploy drivers to decide which\n// backends to publish federated remotes for after a deploy.\nexport const getServiceNamesWithFederation = (appName: string, serviceNames: string[]): string[] =>\n serviceNames.filter((service) => !!qpqCoreUtils.getFederatedModuleStore(loadServiceQpqConfig(appName, service)));\n"]}
|
|
@@ -11,7 +11,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
exports.resolveAppSelection = void 0;
|
|
13
13
|
// One app-selection contract for every app-facing command (prep / synth / go /
|
|
14
|
-
// go:dev / go:dev:web / publish). Resolution order:
|
|
14
|
+
// go:dev / go:dev:api / go:dev:web / publish). Resolution order:
|
|
15
15
|
// 1. --app <name> / --app=<name> on argv
|
|
16
16
|
// 2. npm_config_app (npm run x --app foo, no --)
|
|
17
17
|
// 3. an env var the command already honours (QPQ_DEV_APP / DEPLOY_APP_NAME)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolveAppSelection.js","sourceRoot":"","sources":["../../../src/lib/resolveAppSelection.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,+EAA+E;AAC/E,
|
|
1
|
+
{"version":3,"file":"resolveAppSelection.js","sourceRoot":"","sources":["../../../src/lib/resolveAppSelection.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,+EAA+E;AAC/E,iEAAiE;AACjE,2CAA2C;AAC3C,+EAA+E;AAC/E,kFAAkF;AAClF,kDAAkD;AAClD,qCAAqC;AACrC,6DAA6D;AAC7D,6EAA6E;AAC7E,+EAA+E;AAC/E,+CAA+C;AAC/C,iCAAqC;AACrC,2CAA+C;AAC/C,uCAAyC;AAUzC,MAAM,eAAe,GAAG,CAAC,SAA6B,EAAE,aAAuB,EAAS,EAAE;IACxF,IAAI,SAAS;QAAE,OAAO,CAAC,KAAK,CAAC,gBAAgB,SAAS,IAAI,CAAC,CAAC;IAC5D,OAAO,CAAC,KAAK,CAAC,eAAe,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACzD,OAAO,CAAC,KAAK,CAAC,wDAAwD,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAC5F,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC;AAEK,MAAM,mBAAmB,GAAG,CAAO,OAA0B,EAAmB,EAAE;IACvF,MAAM,aAAa,GAAG,IAAA,4BAAgB,GAAE,CAAC;IACzC,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC/B,OAAO,CAAC,KAAK,CAAC,4BAA4B,CAAC,CAAC;QAC5C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,SAAS,GACb,IAAA,kBAAW,EAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IAEjI,IAAI,SAAS,EAAE,CAAC;QACd,IAAI,OAAO,CAAC,QAAQ,IAAI,SAAS,KAAK,KAAK;YAAE,OAAO,KAAK,CAAC;QAC1D,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,SAAS,CAAC;YAAE,eAAe,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC;QAClF,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC/B,OAAO,CAAC,GAAG,CAAC,cAAc,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAC9C,OAAO,aAAa,CAAC,CAAC,CAAC,CAAC;IAC1B,CAAC;IAED,IAAI,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QACxB,OAAO,IAAA,sBAAY,EAAC,YAAY,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,GAAG,aAAa,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC;IAClG,CAAC;IAED,OAAO,eAAe,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC;AACnD,CAAC,CAAA,CAAC;AA1BW,QAAA,mBAAmB,uBA0B9B","sourcesContent":["// One app-selection contract for every app-facing command (prep / synth / go /\n// go:dev / go:dev:api / go:dev:web / publish). Resolution order:\n// 1. --app <name> / --app=<name> on argv\n// 2. npm_config_app (npm run x --app foo, no --)\n// 3. an env var the command already honours (QPQ_DEV_APP / DEPLOY_APP_NAME)\n// 4. exactly one app under apps/ -> auto-select\n// 5. interactive prompt (TTY only)\n// 6. otherwise: print the valid app list and exit non-zero\n// An unknown name (from any source) also prints the list and exits non-zero.\n// Commands that can meaningfully run for every app may pass allowAll to accept\n// `--app all` (returned as the literal 'all').\nimport { getArgValue } from './args';\nimport { getAvailableApps } from './discovery';\nimport { promptSelect } from './prompts';\n\nexport type ResolveAppOptions = {\n argv: string[];\n // Env var this command historically honours (e.g. QPQ_DEV_APP, DEPLOY_APP_NAME).\n envVar?: string;\n // Accept `--app all` and return 'all'.\n allowAll?: boolean;\n};\n\nconst exitWithAppList = (requested: string | undefined, availableApps: string[]): never => {\n if (requested) console.error(`Unknown app '${requested}'.`);\n console.error(`Valid apps: ${availableApps.join(', ')}`);\n console.error(`Pass one with --app <name> (e.g. qpq <command> --app ${availableApps[0]}).`);\n process.exit(1);\n};\n\nexport const resolveAppSelection = async (options: ResolveAppOptions): Promise<string> => {\n const availableApps = getAvailableApps();\n if (availableApps.length === 0) {\n console.error('No apps found under apps/.');\n process.exit(1);\n }\n\n const requested =\n getArgValue(options.argv, '--app') || process.env.npm_config_app || (options.envVar ? process.env[options.envVar] : undefined);\n\n if (requested) {\n if (options.allowAll && requested === 'all') return 'all';\n if (!availableApps.includes(requested)) exitWithAppList(requested, availableApps);\n return requested;\n }\n\n if (availableApps.length === 1) {\n console.log(`Using app: ${availableApps[0]}`);\n return availableApps[0];\n }\n\n if (process.stdin.isTTY) {\n return promptSelect('Select app', options.allowAll ? [...availableApps, 'all'] : availableApps);\n }\n\n return exitWithAppList(undefined, availableApps);\n};\n"]}
|
|
@@ -7,4 +7,9 @@ export type TaskFailure = {
|
|
|
7
7
|
error: Error;
|
|
8
8
|
};
|
|
9
9
|
export declare const runTasks: (tasks: Task[], limit: number) => Promise<TaskFailure[]>;
|
|
10
|
+
export type DependencyTask = Task & {
|
|
11
|
+
id: string;
|
|
12
|
+
deps: string[];
|
|
13
|
+
};
|
|
14
|
+
export declare const runDependencyTasks: (tasks: DependencyTask[], limit: number) => Promise<TaskFailure[]>;
|
|
10
15
|
export declare const assertNoFailures: (phaseName: string, failures: TaskFailure[]) => void;
|
|
@@ -9,7 +9,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
9
9
|
});
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.assertNoFailures = exports.runTasks = void 0;
|
|
12
|
+
exports.assertNoFailures = exports.runDependencyTasks = exports.runTasks = void 0;
|
|
13
13
|
// Run tasks with at most `limit` in flight; never rejects — failures come back
|
|
14
14
|
// labelled so a whole wave can finish before we report what broke.
|
|
15
15
|
const runTasks = (tasks, limit) => __awaiter(void 0, void 0, void 0, function* () {
|
|
@@ -31,6 +31,87 @@ const runTasks = (tasks, limit) => __awaiter(void 0, void 0, void 0, function* (
|
|
|
31
31
|
return failures;
|
|
32
32
|
});
|
|
33
33
|
exports.runTasks = runTasks;
|
|
34
|
+
// Run tasks with at most `limit` in flight, but a task only starts once every
|
|
35
|
+
// task in its `deps` has succeeded. A failure doesn't stop unrelated tasks;
|
|
36
|
+
// dependents of the failed task are skipped (logged, not returned as failures,
|
|
37
|
+
// the root cause already is). Never rejects. Tasks left unstartable by a
|
|
38
|
+
// dependency cycle come back as failures.
|
|
39
|
+
const runDependencyTasks = (tasks, limit) => __awaiter(void 0, void 0, void 0, function* () {
|
|
40
|
+
const failures = [];
|
|
41
|
+
const succeeded = new Set();
|
|
42
|
+
const failed = new Set();
|
|
43
|
+
const started = new Set();
|
|
44
|
+
const pipelines = [];
|
|
45
|
+
let slots = Math.max(1, limit);
|
|
46
|
+
const waiting = [];
|
|
47
|
+
const acquire = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
48
|
+
if (slots > 0) {
|
|
49
|
+
slots -= 1;
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
yield new Promise((resolve) => waiting.push(resolve));
|
|
53
|
+
});
|
|
54
|
+
const release = () => {
|
|
55
|
+
const next = waiting.shift();
|
|
56
|
+
if (next) {
|
|
57
|
+
next();
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
slots += 1;
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
const runOne = (task) => __awaiter(void 0, void 0, void 0, function* () {
|
|
64
|
+
yield acquire();
|
|
65
|
+
try {
|
|
66
|
+
yield task.run();
|
|
67
|
+
succeeded.add(task.id);
|
|
68
|
+
}
|
|
69
|
+
catch (error) {
|
|
70
|
+
failed.add(task.id);
|
|
71
|
+
failures.push({ label: task.label, error: error });
|
|
72
|
+
}
|
|
73
|
+
finally {
|
|
74
|
+
release();
|
|
75
|
+
}
|
|
76
|
+
launchReady();
|
|
77
|
+
});
|
|
78
|
+
// Repeatedly sweep until stable: launching one task or cascading one skip can
|
|
79
|
+
// unblock (or block) tasks earlier in the list.
|
|
80
|
+
const launchReady = () => {
|
|
81
|
+
let changed = true;
|
|
82
|
+
while (changed) {
|
|
83
|
+
changed = false;
|
|
84
|
+
for (const task of tasks) {
|
|
85
|
+
if (started.has(task.id))
|
|
86
|
+
continue;
|
|
87
|
+
if (task.deps.some((dep) => failed.has(dep))) {
|
|
88
|
+
started.add(task.id);
|
|
89
|
+
failed.add(task.id); // cascade so transitive dependents skip too
|
|
90
|
+
console.log(`Skipping ${task.label} (a dependency failed)`);
|
|
91
|
+
changed = true;
|
|
92
|
+
}
|
|
93
|
+
else if (task.deps.every((dep) => succeeded.has(dep))) {
|
|
94
|
+
started.add(task.id);
|
|
95
|
+
pipelines.push(runOne(task));
|
|
96
|
+
changed = true;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
launchReady();
|
|
102
|
+
// runOne re-invokes launchReady as tasks finish, pushing newly unblocked
|
|
103
|
+
// pipelines while earlier ones are being awaited; drain until it stays empty.
|
|
104
|
+
while (pipelines.length > 0) {
|
|
105
|
+
yield Promise.all(pipelines.splice(0, pipelines.length));
|
|
106
|
+
}
|
|
107
|
+
for (const task of tasks) {
|
|
108
|
+
if (!started.has(task.id)) {
|
|
109
|
+
failures.push({ label: task.label, error: new Error('unstartable: dependency cycle') });
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
return failures;
|
|
113
|
+
});
|
|
114
|
+
exports.runDependencyTasks = runDependencyTasks;
|
|
34
115
|
const assertNoFailures = (phaseName, failures) => {
|
|
35
116
|
if (failures.length === 0)
|
|
36
117
|
return;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runTasks.js","sourceRoot":"","sources":["../../../src/lib/runTasks.ts"],"names":[],"mappings":";;;;;;;;;;;;AAGA,+EAA+E;AAC/E,mEAAmE;AAC5D,MAAM,QAAQ,GAAG,CAAO,KAAa,EAAE,KAAa,EAA0B,EAAE;IACrF,MAAM,QAAQ,GAAkB,EAAE,CAAC;IACnC,IAAI,SAAS,GAAG,CAAC,CAAC;IAElB,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;IAC/D,MAAM,OAAO,CAAC,GAAG,CACf,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,WAAW,EAAE,EAAE,GAAS,EAAE;QAC7C,OAAO,SAAS,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC;YAChC,MAAM,IAAI,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC;YAC9B,SAAS,IAAI,CAAC,CAAC;YACf,IAAI,CAAC;gBACH,MAAM,IAAI,CAAC,GAAG,EAAE,CAAC;YACnB,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,QAAQ,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,KAAK,EAAE,KAAc,EAAE,CAAC,CAAC;YAC9D,CAAC;QACH,CAAC;IACH,CAAC,CAAA,CAAC,CACH,CAAC;IAEF,OAAO,QAAQ,CAAC;AAClB,CAAC,CAAA,CAAC;AApBW,QAAA,QAAQ,YAoBnB;AAEK,MAAM,gBAAgB,GAAG,CAAC,SAAiB,EAAE,QAAuB,EAAQ,EAAE;IACnF,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO;IAClC,OAAO,CAAC,KAAK,CAAC,KAAK,SAAS,cAAc,CAAC,CAAC;IAC5C,QAAQ,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,OAAO,CAAC,KAAK,KAAK,OAAO,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;IAC7F,MAAM,IAAI,KAAK,CAAC,GAAG,SAAS,KAAK,QAAQ,CAAC,MAAM,iBAAiB,CAAC,CAAC;AACrE,CAAC,CAAC;AALW,QAAA,gBAAgB,oBAK3B","sourcesContent":["export type Task = { label: string; run: () => Promise<void> };\nexport type TaskFailure = { label: string; error: Error };\n\n// Run tasks with at most `limit` in flight; never rejects — failures come back\n// labelled so a whole wave can finish before we report what broke.\nexport const runTasks = async (tasks: Task[], limit: number): Promise<TaskFailure[]> => {\n const failures: TaskFailure[] = [];\n let nextIndex = 0;\n\n const workerCount = Math.max(1, Math.min(limit, tasks.length));\n await Promise.all(\n Array.from({ length: workerCount }, async () => {\n while (nextIndex < tasks.length) {\n const task = tasks[nextIndex];\n nextIndex += 1;\n try {\n await task.run();\n } catch (error) {\n failures.push({ label: task.label, error: error as Error });\n }\n }\n }),\n );\n\n return failures;\n};\n\nexport const assertNoFailures = (phaseName: string, failures: TaskFailure[]): void => {\n if (failures.length === 0) return;\n console.error(`\\n${phaseName} failed for:`);\n failures.forEach((failure) => console.error(` ${failure.label}: ${failure.error.message}`));\n throw new Error(`${phaseName}: ${failures.length} task(s) failed`);\n};\n"]}
|
|
1
|
+
{"version":3,"file":"runTasks.js","sourceRoot":"","sources":["../../../src/lib/runTasks.ts"],"names":[],"mappings":"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","sourcesContent":["export type Task = { label: string; run: () => Promise<void> };\nexport type TaskFailure = { label: string; error: Error };\n\n// Run tasks with at most `limit` in flight; never rejects — failures come back\n// labelled so a whole wave can finish before we report what broke.\nexport const runTasks = async (tasks: Task[], limit: number): Promise<TaskFailure[]> => {\n const failures: TaskFailure[] = [];\n let nextIndex = 0;\n\n const workerCount = Math.max(1, Math.min(limit, tasks.length));\n await Promise.all(\n Array.from({ length: workerCount }, async () => {\n while (nextIndex < tasks.length) {\n const task = tasks[nextIndex];\n nextIndex += 1;\n try {\n await task.run();\n } catch (error) {\n failures.push({ label: task.label, error: error as Error });\n }\n }\n }),\n );\n\n return failures;\n};\n\nexport type DependencyTask = Task & {\n // Unique id other tasks reference in `deps` (e.g. a package name).\n id: string;\n // Ids of tasks that must succeed before this one starts. Ids not present in\n // the task list should be filtered out by the caller.\n deps: string[];\n};\n\n// Run tasks with at most `limit` in flight, but a task only starts once every\n// task in its `deps` has succeeded. A failure doesn't stop unrelated tasks;\n// dependents of the failed task are skipped (logged, not returned as failures,\n// the root cause already is). Never rejects. Tasks left unstartable by a\n// dependency cycle come back as failures.\nexport const runDependencyTasks = async (tasks: DependencyTask[], limit: number): Promise<TaskFailure[]> => {\n const failures: TaskFailure[] = [];\n const succeeded = new Set<string>();\n const failed = new Set<string>();\n const started = new Set<string>();\n const pipelines: Array<Promise<void>> = [];\n\n let slots = Math.max(1, limit);\n const waiting: Array<() => void> = [];\n\n const acquire = async (): Promise<void> => {\n if (slots > 0) {\n slots -= 1;\n return;\n }\n await new Promise<void>((resolve) => waiting.push(resolve));\n };\n\n const release = (): void => {\n const next = waiting.shift();\n if (next) {\n next();\n } else {\n slots += 1;\n }\n };\n\n const runOne = async (task: DependencyTask): Promise<void> => {\n await acquire();\n try {\n await task.run();\n succeeded.add(task.id);\n } catch (error) {\n failed.add(task.id);\n failures.push({ label: task.label, error: error as Error });\n } finally {\n release();\n }\n launchReady();\n };\n\n // Repeatedly sweep until stable: launching one task or cascading one skip can\n // unblock (or block) tasks earlier in the list.\n const launchReady = (): void => {\n let changed = true;\n while (changed) {\n changed = false;\n for (const task of tasks) {\n if (started.has(task.id)) continue;\n if (task.deps.some((dep) => failed.has(dep))) {\n started.add(task.id);\n failed.add(task.id); // cascade so transitive dependents skip too\n console.log(`Skipping ${task.label} (a dependency failed)`);\n changed = true;\n } else if (task.deps.every((dep) => succeeded.has(dep))) {\n started.add(task.id);\n pipelines.push(runOne(task));\n changed = true;\n }\n }\n }\n };\n\n launchReady();\n // runOne re-invokes launchReady as tasks finish, pushing newly unblocked\n // pipelines while earlier ones are being awaited; drain until it stays empty.\n while (pipelines.length > 0) {\n await Promise.all(pipelines.splice(0, pipelines.length));\n }\n\n for (const task of tasks) {\n if (!started.has(task.id)) {\n failures.push({ label: task.label, error: new Error('unstartable: dependency cycle') });\n }\n }\n\n return failures;\n};\n\nexport const assertNoFailures = (phaseName: string, failures: TaskFailure[]): void => {\n if (failures.length === 0) return;\n console.error(`\\n${phaseName} failed for:`);\n failures.forEach((failure) => console.error(` ${failure.label}: ${failure.error.message}`));\n throw new Error(`${phaseName}: ${failures.length} task(s) failed`);\n};\n"]}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.startTypeWatcher = void 0;
|
|
7
|
+
// Keeps workspace packages' declaration output (dist/*.d.ts) fresh while
|
|
8
|
+
// `qpq go:dev` runs. The rspack dev builds bundle workspace source directly,
|
|
9
|
+
// so this watcher only feeds the editor and validate-ts, which resolve
|
|
10
|
+
// cross-package types through each package's built declarations.
|
|
11
|
+
//
|
|
12
|
+
// One `tsc -b --watch` over every workspace package that ships types; routine
|
|
13
|
+
// watch chatter is dropped so only real compile errors reach the shared
|
|
14
|
+
// terminal. Opt out with `--no-types`.
|
|
15
|
+
const quidproquo_deploy_rspack_1 = require("quidproquo-deploy-rspack");
|
|
16
|
+
const child_process_1 = require("child_process");
|
|
17
|
+
const fs_1 = __importDefault(require("fs"));
|
|
18
|
+
const path_1 = __importDefault(require("path"));
|
|
19
|
+
// Routine tsc watch status lines; everything else is worth showing.
|
|
20
|
+
const routineTscPatterns = [/Starting compilation in watch mode/, /File change detected/, /Found 0 errors/];
|
|
21
|
+
const isRoutineTscLine = (line) => routineTscPatterns.some((pattern) => pattern.test(line));
|
|
22
|
+
// Forwards non-routine tsc output line by line under a [types] prefix.
|
|
23
|
+
const forwardTscOutput = (chunk) => {
|
|
24
|
+
for (const line of chunk.toString().split('\n')) {
|
|
25
|
+
if (line.trim().length === 0 || isRoutineTscLine(line)) {
|
|
26
|
+
continue;
|
|
27
|
+
}
|
|
28
|
+
console.log(`[types] ${line}`);
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
// A workspace package wants declaration watching when it has a tsconfig and
|
|
32
|
+
// publishes types from its build output. Packages bundled by rspack (views,
|
|
33
|
+
// service handlers) don't ship types and are skipped.
|
|
34
|
+
const isTypedWorkspacePackage = (dir) => {
|
|
35
|
+
if (!fs_1.default.existsSync(path_1.default.join(dir, 'tsconfig.json'))) {
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
const packageJson = JSON.parse(fs_1.default.readFileSync(path_1.default.join(dir, 'package.json'), 'utf-8'));
|
|
39
|
+
return !!(packageJson.types || packageJson.typings);
|
|
40
|
+
};
|
|
41
|
+
const startTypeWatcher = (root) => {
|
|
42
|
+
var _a, _b;
|
|
43
|
+
const projectDirs = (0, quidproquo_deploy_rspack_1.getWorkspacePackageDirs)(root).filter(isTypedWorkspacePackage);
|
|
44
|
+
if (projectDirs.length === 0) {
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
const relativeDirs = projectDirs.map((dir) => path_1.default.relative(root, dir));
|
|
48
|
+
const child = (0, child_process_1.spawn)('npx', ['tsc', '-b', ...relativeDirs, '--watch', '--preserveWatchOutput', '--pretty'], {
|
|
49
|
+
cwd: root,
|
|
50
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
51
|
+
shell: process.platform === 'win32',
|
|
52
|
+
});
|
|
53
|
+
(_a = child.stdout) === null || _a === void 0 ? void 0 : _a.on('data', forwardTscOutput);
|
|
54
|
+
(_b = child.stderr) === null || _b === void 0 ? void 0 : _b.on('data', forwardTscOutput);
|
|
55
|
+
console.log(`Type watcher: tsc -b --watch over ${relativeDirs.length} workspace packages (disable with --no-types).`);
|
|
56
|
+
return child;
|
|
57
|
+
};
|
|
58
|
+
exports.startTypeWatcher = startTypeWatcher;
|
|
59
|
+
//# sourceMappingURL=typeWatcher.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"typeWatcher.js","sourceRoot":"","sources":["../../../src/lib/typeWatcher.ts"],"names":[],"mappings":";;;;;;AAAA,yEAAyE;AACzE,6EAA6E;AAC7E,uEAAuE;AACvE,iEAAiE;AACjE,EAAE;AACF,8EAA8E;AAC9E,wEAAwE;AACxE,uCAAuC;AACvC,uEAAmE;AAEnE,iDAAoD;AACpD,4CAAoB;AACpB,gDAAwB;AAExB,oEAAoE;AACpE,MAAM,kBAAkB,GAAG,CAAC,oCAAoC,EAAE,sBAAsB,EAAE,gBAAgB,CAAC,CAAC;AAE5G,MAAM,gBAAgB,GAAG,CAAC,IAAY,EAAW,EAAE,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;AAE7G,uEAAuE;AACvE,MAAM,gBAAgB,GAAG,CAAC,KAAa,EAAQ,EAAE;IAC/C,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QAChD,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,IAAI,gBAAgB,CAAC,IAAI,CAAC,EAAE,CAAC;YACvD,SAAS;QACX,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC;IACjC,CAAC;AACH,CAAC,CAAC;AAEF,4EAA4E;AAC5E,4EAA4E;AAC5E,sDAAsD;AACtD,MAAM,uBAAuB,GAAG,CAAC,GAAW,EAAW,EAAE;IACvD,IAAI,CAAC,YAAE,CAAC,UAAU,CAAC,cAAI,CAAC,IAAI,CAAC,GAAG,EAAE,eAAe,CAAC,CAAC,EAAE,CAAC;QACpD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,YAAE,CAAC,YAAY,CAAC,cAAI,CAAC,IAAI,CAAC,GAAG,EAAE,cAAc,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;IACzF,OAAO,CAAC,CAAC,CAAC,WAAW,CAAC,KAAK,IAAI,WAAW,CAAC,OAAO,CAAC,CAAC;AACtD,CAAC,CAAC;AAEK,MAAM,gBAAgB,GAAG,CAAC,IAAY,EAAuB,EAAE;;IACpE,MAAM,WAAW,GAAG,IAAA,kDAAuB,EAAC,IAAI,CAAC,CAAC,MAAM,CAAC,uBAAuB,CAAC,CAAC;IAClF,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC7B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,YAAY,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,cAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC;IACxE,MAAM,KAAK,GAAG,IAAA,qBAAK,EAAC,KAAK,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,YAAY,EAAE,SAAS,EAAE,uBAAuB,EAAE,UAAU,CAAC,EAAE;QACzG,GAAG,EAAE,IAAI;QACT,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC;QACjC,KAAK,EAAE,OAAO,CAAC,QAAQ,KAAK,OAAO;KACpC,CAAC,CAAC;IAEH,MAAA,KAAK,CAAC,MAAM,0CAAE,EAAE,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;IAC3C,MAAA,KAAK,CAAC,MAAM,0CAAE,EAAE,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;IAE3C,OAAO,CAAC,GAAG,CAAC,qCAAqC,YAAY,CAAC,MAAM,gDAAgD,CAAC,CAAC;IAEtH,OAAO,KAAK,CAAC;AACf,CAAC,CAAC;AAnBW,QAAA,gBAAgB,oBAmB3B","sourcesContent":["// Keeps workspace packages' declaration output (dist/*.d.ts) fresh while\n// `qpq go:dev` runs. The rspack dev builds bundle workspace source directly,\n// so this watcher only feeds the editor and validate-ts, which resolve\n// cross-package types through each package's built declarations.\n//\n// One `tsc -b --watch` over every workspace package that ships types; routine\n// watch chatter is dropped so only real compile errors reach the shared\n// terminal. Opt out with `--no-types`.\nimport { getWorkspacePackageDirs } from 'quidproquo-deploy-rspack';\n\nimport { ChildProcess, spawn } from 'child_process';\nimport fs from 'fs';\nimport path from 'path';\n\n// Routine tsc watch status lines; everything else is worth showing.\nconst routineTscPatterns = [/Starting compilation in watch mode/, /File change detected/, /Found 0 errors/];\n\nconst isRoutineTscLine = (line: string): boolean => routineTscPatterns.some((pattern) => pattern.test(line));\n\n// Forwards non-routine tsc output line by line under a [types] prefix.\nconst forwardTscOutput = (chunk: Buffer): void => {\n for (const line of chunk.toString().split('\\n')) {\n if (line.trim().length === 0 || isRoutineTscLine(line)) {\n continue;\n }\n console.log(`[types] ${line}`);\n }\n};\n\n// A workspace package wants declaration watching when it has a tsconfig and\n// publishes types from its build output. Packages bundled by rspack (views,\n// service handlers) don't ship types and are skipped.\nconst isTypedWorkspacePackage = (dir: string): boolean => {\n if (!fs.existsSync(path.join(dir, 'tsconfig.json'))) {\n return false;\n }\n\n const packageJson = JSON.parse(fs.readFileSync(path.join(dir, 'package.json'), 'utf-8'));\n return !!(packageJson.types || packageJson.typings);\n};\n\nexport const startTypeWatcher = (root: string): ChildProcess | null => {\n const projectDirs = getWorkspacePackageDirs(root).filter(isTypedWorkspacePackage);\n if (projectDirs.length === 0) {\n return null;\n }\n\n const relativeDirs = projectDirs.map((dir) => path.relative(root, dir));\n const child = spawn('npx', ['tsc', '-b', ...relativeDirs, '--watch', '--preserveWatchOutput', '--pretty'], {\n cwd: root,\n stdio: ['ignore', 'pipe', 'pipe'],\n shell: process.platform === 'win32',\n });\n\n child.stdout?.on('data', forwardTscOutput);\n child.stderr?.on('data', forwardTscOutput);\n\n console.log(`Type watcher: tsc -b --watch over ${relativeDirs.length} workspace packages (disable with --no-types).`);\n\n return child;\n};\n"]}
|
|
@@ -9,8 +9,12 @@ const packageRoot_1 = require("../../lib/packageRoot");
|
|
|
9
9
|
// The CDK app command (`cdk ... --app "<this>"`): quidproquo-deploy-awscdk's
|
|
10
10
|
// generic workspace app under ts-node hooks, with DEPLOY_* in the env.
|
|
11
11
|
const getCdkAppCommand = () => {
|
|
12
|
+
// Resolve ts-node from this package, not the workspace cwd — under npm link
|
|
13
|
+
// the CLI's dependencies are never hoisted into the workspace's node_modules,
|
|
14
|
+
// so a bare `-r ts-node/...` preload fails there.
|
|
15
|
+
const tsNodeRegister = require.resolve('ts-node/register/transpile-only');
|
|
12
16
|
const cdkAppScript = path_1.default.join((0, packageRoot_1.getOwnPackageRoot)(), 'lib', 'commonjs', 'bin', 'qpqCdkApp.js');
|
|
13
|
-
return `node -r
|
|
17
|
+
return `node -r "${tsNodeRegister}" "${cdkAppScript}"`;
|
|
14
18
|
};
|
|
15
19
|
exports.getCdkAppCommand = getCdkAppCommand;
|
|
16
20
|
// The docker build context for the go:docker deployer image.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cdkApp.js","sourceRoot":"","sources":["../../../../src/platforms/aws/cdkApp.ts"],"names":[],"mappings":";;;;;;AAAA,gDAAwB;AAExB,uDAA0D;AAE1D,6EAA6E;AAC7E,uEAAuE;AAChE,MAAM,gBAAgB,GAAG,GAAW,EAAE;IAC3C,MAAM,YAAY,GAAG,cAAI,CAAC,IAAI,CAAC,IAAA,+BAAiB,GAAE,EAAE,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,cAAc,CAAC,CAAC;IAC9F,OAAO,
|
|
1
|
+
{"version":3,"file":"cdkApp.js","sourceRoot":"","sources":["../../../../src/platforms/aws/cdkApp.ts"],"names":[],"mappings":";;;;;;AAAA,gDAAwB;AAExB,uDAA0D;AAE1D,6EAA6E;AAC7E,uEAAuE;AAChE,MAAM,gBAAgB,GAAG,GAAW,EAAE;IAC3C,4EAA4E;IAC5E,8EAA8E;IAC9E,kDAAkD;IAClD,MAAM,cAAc,GAAG,OAAO,CAAC,OAAO,CAAC,iCAAiC,CAAC,CAAC;IAC1E,MAAM,YAAY,GAAG,cAAI,CAAC,IAAI,CAAC,IAAA,+BAAiB,GAAE,EAAE,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,cAAc,CAAC,CAAC;IAC9F,OAAO,YAAY,cAAc,MAAM,YAAY,GAAG,CAAC;AACzD,CAAC,CAAC;AAPW,QAAA,gBAAgB,oBAO3B;AAEF,6DAA6D;AACtD,MAAM,YAAY,GAAG,GAAW,EAAE,CAAC,cAAI,CAAC,IAAI,CAAC,IAAA,+BAAiB,GAAE,EAAE,QAAQ,EAAE,cAAc,CAAC,CAAC;AAAtF,QAAA,YAAY,gBAA0E","sourcesContent":["import path from 'path';\n\nimport { getOwnPackageRoot } from '../../lib/packageRoot';\n\n// The CDK app command (`cdk ... --app \"<this>\"`): quidproquo-deploy-awscdk's\n// generic workspace app under ts-node hooks, with DEPLOY_* in the env.\nexport const getCdkAppCommand = (): string => {\n // Resolve ts-node from this package, not the workspace cwd — under npm link\n // the CLI's dependencies are never hoisted into the workspace's node_modules,\n // so a bare `-r ts-node/...` preload fails there.\n const tsNodeRegister = require.resolve('ts-node/register/transpile-only');\n const cdkAppScript = path.join(getOwnPackageRoot(), 'lib', 'commonjs', 'bin', 'qpqCdkApp.js');\n return `node -r \"${tsNodeRegister}\" \"${cdkAppScript}\"`;\n};\n\n// The docker build context for the go:docker deployer image.\nexport const getDockerDir = (): string => path.join(getOwnPackageRoot(), 'docker', 'cdk-deployer');\n"]}
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.awsClearResources = void 0;
|
|
13
|
+
// AWS implementation of `qpq clear-resources`: empty (never delete) the
|
|
14
|
+
// selected data resources. Storage drives are S3 buckets - emptied including
|
|
15
|
+
// every object version and delete marker, so versioned buckets come out clean
|
|
16
|
+
// too. Key value stores are DynamoDB tables - truncated by scanning keys only
|
|
17
|
+
// and batch-deleting. The stacks and the resources themselves are untouched,
|
|
18
|
+
// so this is the "reset my data" counterpart to `qpq teardown`.
|
|
19
|
+
//
|
|
20
|
+
// Runtime names are resolved from each service's live qpq config with the
|
|
21
|
+
// same naming utils the deployed runtime uses, so what gets emptied is
|
|
22
|
+
// exactly what the app reads and writes.
|
|
23
|
+
const quidproquo_actionprocessor_awslambda_1 = require("quidproquo-actionprocessor-awslambda");
|
|
24
|
+
const quidproquo_config_aws_1 = require("quidproquo-config-aws");
|
|
25
|
+
const quidproquo_core_1 = require("quidproquo-core");
|
|
26
|
+
const client_dynamodb_1 = require("@aws-sdk/client-dynamodb");
|
|
27
|
+
const client_s3_1 = require("@aws-sdk/client-s3");
|
|
28
|
+
const qpqConfigs_1 = require("../../lib/qpqConfigs");
|
|
29
|
+
const awsCredentials_1 = require("./awsCredentials");
|
|
30
|
+
// Same resolution as the runtime's resolveStorageDriveBucketName (not exported
|
|
31
|
+
// from the actionprocessor package root): honour the cross-module owner and
|
|
32
|
+
// its resourceNameOverride.
|
|
33
|
+
const resolveBucketName = (drive, qpqConfig) => {
|
|
34
|
+
var _a, _b;
|
|
35
|
+
const storageDriveConfig = quidproquo_core_1.qpqCoreUtils.getStorageDriveByName(drive, qpqConfig);
|
|
36
|
+
if (!storageDriveConfig) {
|
|
37
|
+
throw new Error(`Could not find storage drive config for [${drive}]`);
|
|
38
|
+
}
|
|
39
|
+
return quidproquo_actionprocessor_awslambda_1.awsNamingUtils.getConfigRuntimeResourceNameFromConfigWithServiceOverride(((_a = storageDriveConfig.owner) === null || _a === void 0 ? void 0 : _a.resourceNameOverride) || drive, qpqConfig, (_b = storageDriveConfig.owner) === null || _b === void 0 ? void 0 : _b.module);
|
|
40
|
+
};
|
|
41
|
+
// Log a progress heartbeat roughly every this-many removals, so a large
|
|
42
|
+
// resource visibly ticks along instead of looking hung.
|
|
43
|
+
const PROGRESS_EVERY = 2000;
|
|
44
|
+
// Empty a bucket including all versions + delete markers. Returns the number
|
|
45
|
+
// of objects/versions removed.
|
|
46
|
+
const emptyBucket = (bucketName, region) => __awaiter(void 0, void 0, void 0, function* () {
|
|
47
|
+
var _a, _b;
|
|
48
|
+
const s3 = new client_s3_1.S3Client({ region });
|
|
49
|
+
let removed = 0;
|
|
50
|
+
let lastReported = 0;
|
|
51
|
+
let keyMarker;
|
|
52
|
+
let versionIdMarker;
|
|
53
|
+
do {
|
|
54
|
+
const page = yield s3.send(new client_s3_1.ListObjectVersionsCommand({ Bucket: bucketName, KeyMarker: keyMarker, VersionIdMarker: versionIdMarker }));
|
|
55
|
+
const objects = [...((_a = page.Versions) !== null && _a !== void 0 ? _a : []), ...((_b = page.DeleteMarkers) !== null && _b !== void 0 ? _b : [])].map((v) => ({
|
|
56
|
+
Key: v.Key,
|
|
57
|
+
VersionId: v.VersionId,
|
|
58
|
+
}));
|
|
59
|
+
if (objects.length > 0) {
|
|
60
|
+
yield s3.send(new client_s3_1.DeleteObjectsCommand({ Bucket: bucketName, Delete: { Objects: objects, Quiet: true } }));
|
|
61
|
+
removed += objects.length;
|
|
62
|
+
}
|
|
63
|
+
if (removed - lastReported >= PROGRESS_EVERY) {
|
|
64
|
+
console.log(` ... ${removed} objects/versions so far`);
|
|
65
|
+
lastReported = removed;
|
|
66
|
+
}
|
|
67
|
+
keyMarker = page.IsTruncated ? page.NextKeyMarker : undefined;
|
|
68
|
+
versionIdMarker = page.IsTruncated ? page.NextVersionIdMarker : undefined;
|
|
69
|
+
} while (keyMarker || versionIdMarker);
|
|
70
|
+
return removed;
|
|
71
|
+
});
|
|
72
|
+
// Truncate a table: scan key attributes only, batch-delete 25 at a time,
|
|
73
|
+
// retrying unprocessed items. Returns the number of items removed.
|
|
74
|
+
const truncateTable = (tableName, region) => __awaiter(void 0, void 0, void 0, function* () {
|
|
75
|
+
var _a, _b, _c, _d, _e;
|
|
76
|
+
const dynamo = new client_dynamodb_1.DynamoDBClient({ region });
|
|
77
|
+
const described = yield dynamo.send(new client_dynamodb_1.DescribeTableCommand({ TableName: tableName }));
|
|
78
|
+
const keyAttributes = ((_b = (_a = described.Table) === null || _a === void 0 ? void 0 : _a.KeySchema) !== null && _b !== void 0 ? _b : []).map((k) => k.AttributeName);
|
|
79
|
+
// Alias every key attribute - a raw name could collide with a reserved word.
|
|
80
|
+
const projection = keyAttributes.map((_, i) => `#k${i}`).join(', ');
|
|
81
|
+
const attributeNames = Object.fromEntries(keyAttributes.map((attribute, i) => [`#k${i}`, attribute]));
|
|
82
|
+
let removed = 0;
|
|
83
|
+
let lastReported = 0;
|
|
84
|
+
let exclusiveStartKey;
|
|
85
|
+
do {
|
|
86
|
+
const page = yield dynamo.send(new client_dynamodb_1.ScanCommand({
|
|
87
|
+
TableName: tableName,
|
|
88
|
+
ProjectionExpression: projection,
|
|
89
|
+
ExpressionAttributeNames: attributeNames,
|
|
90
|
+
ExclusiveStartKey: exclusiveStartKey,
|
|
91
|
+
}));
|
|
92
|
+
const items = (_c = page.Items) !== null && _c !== void 0 ? _c : [];
|
|
93
|
+
for (let i = 0; i < items.length; i += 25) {
|
|
94
|
+
let requests = items.slice(i, i + 25).map((item) => ({ DeleteRequest: { Key: item } }));
|
|
95
|
+
while (requests.length > 0) {
|
|
96
|
+
const result = yield dynamo.send(new client_dynamodb_1.BatchWriteItemCommand({ RequestItems: { [tableName]: requests } }));
|
|
97
|
+
removed += requests.length;
|
|
98
|
+
const unprocessed = (_e = (_d = result.UnprocessedItems) === null || _d === void 0 ? void 0 : _d[tableName]) !== null && _e !== void 0 ? _e : [];
|
|
99
|
+
removed -= unprocessed.length;
|
|
100
|
+
requests = unprocessed;
|
|
101
|
+
if (requests.length > 0) {
|
|
102
|
+
// Throttled - back off briefly before retrying the leftovers.
|
|
103
|
+
yield new Promise((resolve) => setTimeout(resolve, 250));
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
if (removed - lastReported >= PROGRESS_EVERY) {
|
|
108
|
+
console.log(` ... ${removed} items so far`);
|
|
109
|
+
lastReported = removed;
|
|
110
|
+
}
|
|
111
|
+
exclusiveStartKey = page.LastEvaluatedKey;
|
|
112
|
+
} while (exclusiveStartKey);
|
|
113
|
+
return removed;
|
|
114
|
+
});
|
|
115
|
+
const clearResource = (appName, resource) => __awaiter(void 0, void 0, void 0, function* () {
|
|
116
|
+
const qpqConfig = (0, qpqConfigs_1.loadServiceQpqConfig)(appName, resource.service);
|
|
117
|
+
const region = quidproquo_config_aws_1.qpqConfigAwsUtils.getApplicationModuleDeployRegion(qpqConfig);
|
|
118
|
+
if (resource.kind === 'storageDrive') {
|
|
119
|
+
const bucketName = resolveBucketName(resource.resourceName, qpqConfig);
|
|
120
|
+
console.log(` emptying s3://${bucketName} ...`);
|
|
121
|
+
try {
|
|
122
|
+
const removed = yield emptyBucket(bucketName, region);
|
|
123
|
+
console.log(` emptied s3://${bucketName} (${removed} objects/versions)`);
|
|
124
|
+
}
|
|
125
|
+
catch (error) {
|
|
126
|
+
if (error instanceof client_s3_1.NoSuchBucket) {
|
|
127
|
+
console.log(` skipped s3://${bucketName} (bucket does not exist - not deployed?)`);
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
throw error;
|
|
131
|
+
}
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
// 'kvs' matches the resourceType every runtime KVS action processor passes,
|
|
135
|
+
// giving the deployed '-qpqkvs' table name suffix.
|
|
136
|
+
const tableName = quidproquo_actionprocessor_awslambda_1.awsNamingUtils.getKvsDynamoTableNameFromConfig(resource.resourceName, qpqConfig, 'kvs');
|
|
137
|
+
console.log(` truncating ${tableName} ...`);
|
|
138
|
+
try {
|
|
139
|
+
const removed = yield truncateTable(tableName, region);
|
|
140
|
+
console.log(` truncated ${tableName} (${removed} items)`);
|
|
141
|
+
}
|
|
142
|
+
catch (error) {
|
|
143
|
+
if (error instanceof client_dynamodb_1.ResourceNotFoundException) {
|
|
144
|
+
console.log(` skipped ${tableName} (table does not exist - not deployed?)`);
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
throw error;
|
|
148
|
+
}
|
|
149
|
+
});
|
|
150
|
+
const awsClearResources = (appName, plan) => __awaiter(void 0, void 0, void 0, function* () {
|
|
151
|
+
if (plan.kind === 'cancelled') {
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
if ((yield (0, awsCredentials_1.isAwsCredentialsValid)()) === false) {
|
|
155
|
+
console.log('Credentials are expired or invalid.');
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
console.log('\nEmptying resources:');
|
|
159
|
+
// Sequential on purpose: predictable output, and no burst of parallel scans
|
|
160
|
+
// against provisioned-throughput tables.
|
|
161
|
+
for (const resource of plan.resources) {
|
|
162
|
+
yield clearResource(appName, resource);
|
|
163
|
+
}
|
|
164
|
+
console.log('Done.');
|
|
165
|
+
});
|
|
166
|
+
exports.awsClearResources = awsClearResources;
|
|
167
|
+
//# sourceMappingURL=clearResources.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clearResources.js","sourceRoot":"","sources":["../../../../src/platforms/aws/clearResources.ts"],"names":[],"mappings":"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","sourcesContent":["// AWS implementation of `qpq clear-resources`: empty (never delete) the\n// selected data resources. Storage drives are S3 buckets - emptied including\n// every object version and delete marker, so versioned buckets come out clean\n// too. Key value stores are DynamoDB tables - truncated by scanning keys only\n// and batch-deleting. The stacks and the resources themselves are untouched,\n// so this is the \"reset my data\" counterpart to `qpq teardown`.\n//\n// Runtime names are resolved from each service's live qpq config with the\n// same naming utils the deployed runtime uses, so what gets emptied is\n// exactly what the app reads and writes.\nimport { awsNamingUtils } from 'quidproquo-actionprocessor-awslambda';\nimport { qpqConfigAwsUtils } from 'quidproquo-config-aws';\nimport { QPQConfig, qpqCoreUtils } from 'quidproquo-core';\n\nimport {\n BatchWriteItemCommand,\n DescribeTableCommand,\n DynamoDBClient,\n ResourceNotFoundException,\n ScanCommand,\n WriteRequest,\n} from '@aws-sdk/client-dynamodb';\nimport { DeleteObjectsCommand, ListObjectVersionsCommand, NoSuchBucket, ObjectIdentifier, S3Client } from '@aws-sdk/client-s3';\n\nimport { ClearableResource, ClearResourcesPlan } from '../../lib/clearResourcesPlan';\nimport { loadServiceQpqConfig } from '../../lib/qpqConfigs';\nimport { isAwsCredentialsValid } from './awsCredentials';\n\n// Same resolution as the runtime's resolveStorageDriveBucketName (not exported\n// from the actionprocessor package root): honour the cross-module owner and\n// its resourceNameOverride.\nconst resolveBucketName = (drive: string, qpqConfig: QPQConfig): string => {\n const storageDriveConfig = qpqCoreUtils.getStorageDriveByName(drive, qpqConfig);\n\n if (!storageDriveConfig) {\n throw new Error(`Could not find storage drive config for [${drive}]`);\n }\n\n return awsNamingUtils.getConfigRuntimeResourceNameFromConfigWithServiceOverride(\n storageDriveConfig.owner?.resourceNameOverride || drive,\n qpqConfig,\n storageDriveConfig.owner?.module,\n );\n};\n\n// Log a progress heartbeat roughly every this-many removals, so a large\n// resource visibly ticks along instead of looking hung.\nconst PROGRESS_EVERY = 2000;\n\n// Empty a bucket including all versions + delete markers. Returns the number\n// of objects/versions removed.\nconst emptyBucket = async (bucketName: string, region: string): Promise<number> => {\n const s3 = new S3Client({ region });\n let removed = 0;\n let lastReported = 0;\n let keyMarker: string | undefined;\n let versionIdMarker: string | undefined;\n\n do {\n const page = await s3.send(new ListObjectVersionsCommand({ Bucket: bucketName, KeyMarker: keyMarker, VersionIdMarker: versionIdMarker }));\n\n const objects: ObjectIdentifier[] = [...(page.Versions ?? []), ...(page.DeleteMarkers ?? [])].map((v) => ({\n Key: v.Key!,\n VersionId: v.VersionId,\n }));\n\n if (objects.length > 0) {\n await s3.send(new DeleteObjectsCommand({ Bucket: bucketName, Delete: { Objects: objects, Quiet: true } }));\n removed += objects.length;\n }\n\n if (removed - lastReported >= PROGRESS_EVERY) {\n console.log(` ... ${removed} objects/versions so far`);\n lastReported = removed;\n }\n\n keyMarker = page.IsTruncated ? page.NextKeyMarker : undefined;\n versionIdMarker = page.IsTruncated ? page.NextVersionIdMarker : undefined;\n } while (keyMarker || versionIdMarker);\n\n return removed;\n};\n\n// Truncate a table: scan key attributes only, batch-delete 25 at a time,\n// retrying unprocessed items. Returns the number of items removed.\nconst truncateTable = async (tableName: string, region: string): Promise<number> => {\n const dynamo = new DynamoDBClient({ region });\n\n const described = await dynamo.send(new DescribeTableCommand({ TableName: tableName }));\n const keyAttributes = (described.Table?.KeySchema ?? []).map((k) => k.AttributeName!);\n\n // Alias every key attribute - a raw name could collide with a reserved word.\n const projection = keyAttributes.map((_, i) => `#k${i}`).join(', ');\n const attributeNames = Object.fromEntries(keyAttributes.map((attribute, i) => [`#k${i}`, attribute]));\n\n let removed = 0;\n let lastReported = 0;\n let exclusiveStartKey: Record<string, any> | undefined;\n\n do {\n const page = await dynamo.send(\n new ScanCommand({\n TableName: tableName,\n ProjectionExpression: projection,\n ExpressionAttributeNames: attributeNames,\n ExclusiveStartKey: exclusiveStartKey,\n }),\n );\n\n const items = page.Items ?? [];\n\n for (let i = 0; i < items.length; i += 25) {\n let requests: WriteRequest[] = items.slice(i, i + 25).map((item) => ({ DeleteRequest: { Key: item } }));\n\n while (requests.length > 0) {\n const result = await dynamo.send(new BatchWriteItemCommand({ RequestItems: { [tableName]: requests } }));\n removed += requests.length;\n\n const unprocessed = result.UnprocessedItems?.[tableName] ?? [];\n removed -= unprocessed.length;\n requests = unprocessed;\n\n if (requests.length > 0) {\n // Throttled - back off briefly before retrying the leftovers.\n await new Promise((resolve) => setTimeout(resolve, 250));\n }\n }\n }\n\n if (removed - lastReported >= PROGRESS_EVERY) {\n console.log(` ... ${removed} items so far`);\n lastReported = removed;\n }\n\n exclusiveStartKey = page.LastEvaluatedKey;\n } while (exclusiveStartKey);\n\n return removed;\n};\n\nconst clearResource = async (appName: string, resource: ClearableResource): Promise<void> => {\n const qpqConfig = loadServiceQpqConfig(appName, resource.service);\n const region = qpqConfigAwsUtils.getApplicationModuleDeployRegion(qpqConfig);\n\n if (resource.kind === 'storageDrive') {\n const bucketName = resolveBucketName(resource.resourceName, qpqConfig);\n console.log(` emptying s3://${bucketName} ...`);\n try {\n const removed = await emptyBucket(bucketName, region);\n console.log(` emptied s3://${bucketName} (${removed} objects/versions)`);\n } catch (error) {\n if (error instanceof NoSuchBucket) {\n console.log(` skipped s3://${bucketName} (bucket does not exist - not deployed?)`);\n return;\n }\n throw error;\n }\n return;\n }\n\n // 'kvs' matches the resourceType every runtime KVS action processor passes,\n // giving the deployed '-qpqkvs' table name suffix.\n const tableName = awsNamingUtils.getKvsDynamoTableNameFromConfig(resource.resourceName, qpqConfig, 'kvs');\n console.log(` truncating ${tableName} ...`);\n try {\n const removed = await truncateTable(tableName, region);\n console.log(` truncated ${tableName} (${removed} items)`);\n } catch (error) {\n if (error instanceof ResourceNotFoundException) {\n console.log(` skipped ${tableName} (table does not exist - not deployed?)`);\n return;\n }\n throw error;\n }\n};\n\nexport const awsClearResources = async (appName: string, plan: ClearResourcesPlan): Promise<void> => {\n if (plan.kind === 'cancelled') {\n return;\n }\n\n if ((await isAwsCredentialsValid()) === false) {\n console.log('Credentials are expired or invalid.');\n return;\n }\n\n console.log('\\nEmptying resources:');\n\n // Sequential on purpose: predictable output, and no burst of parallel scans\n // against provisioned-throughput tables.\n for (const resource of plan.resources) {\n await clearResource(appName, resource);\n }\n\n console.log('Done.');\n};\n"]}
|
|
@@ -16,7 +16,10 @@ exports.awsGo = void 0;
|
|
|
16
16
|
// AWS sequential deploy (`qpq go`). Per service it: synths the QPQ config,
|
|
17
17
|
// rspack-bundles the backend (programmatic — no per-service rspack.config.ts),
|
|
18
18
|
// deploys the inf/api/web CDK stacks (cdk runs the generic workspace app via
|
|
19
|
-
// --app), bundles views (rspack, production) and syncs them to S3.
|
|
19
|
+
// --app), bundles views (rspack, production) and syncs them to S3. Finally, any
|
|
20
|
+
// service that opts into module federation has its federated remote published
|
|
21
|
+
// (built + uploaded + manifest flipped), so a deploy that ships new backend
|
|
22
|
+
// code also republishes the code the lambdas federate.
|
|
20
23
|
const quidproquo_deploy_awscdk_1 = require("quidproquo-deploy-awscdk");
|
|
21
24
|
const quidproquo_deploy_rspack_1 = require("quidproquo-deploy-rspack");
|
|
22
25
|
const path_1 = __importDefault(require("path"));
|
|
@@ -29,6 +32,7 @@ const runCommand_1 = require("../../lib/runCommand");
|
|
|
29
32
|
const timing_1 = require("../../lib/timing");
|
|
30
33
|
const views_1 = require("../../lib/views");
|
|
31
34
|
const awsCredentials_1 = require("./awsCredentials");
|
|
35
|
+
const publish_1 = require("./publish");
|
|
32
36
|
const stacks_1 = require("./stacks");
|
|
33
37
|
const viewsSync_1 = require("./viewsSync");
|
|
34
38
|
const buildAndDeploy = (serviceName, needsSynth, needsBuildApi, needsInfStack, needsApiStack, needsWebStack, needsViewStack, appName) => __awaiter(void 0, void 0, void 0, function* () {
|
|
@@ -110,6 +114,16 @@ const awsGo = (appName, plan) => __awaiter(void 0, void 0, void 0, function* ()
|
|
|
110
114
|
return buildAndDeploy(service, phase === 0, phase === 1 && shouldBuildApi, phase === 2 && (allStacks || stacks === 'inf'), phase === 3 && (allStacks || stacks === 'api'), phase === 4 && (allStacks || stacks === 'web'), phase === 5 && (allStacks || stacks === 'views'), appName);
|
|
111
115
|
}), Promise.resolve());
|
|
112
116
|
}
|
|
117
|
+
// Publishing federated remotes only matters once the new backend code is
|
|
118
|
+
// live, so it's gated on the api stack having been (re)deployed. Services
|
|
119
|
+
// without defineFederatedModuleStore(...) are skipped.
|
|
120
|
+
if (allStacks || stacks === 'api') {
|
|
121
|
+
const federatedServices = (0, qpqConfigs_1.getServiceNamesWithFederation)(appName, services);
|
|
122
|
+
if (federatedServices.length > 0) {
|
|
123
|
+
console.log('\n\nPublishing federated backends\n');
|
|
124
|
+
yield (0, publish_1.awsPublish)(appName, federatedServices);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
113
127
|
(0, timing_1.logTimeEnd)('totalTime');
|
|
114
128
|
});
|
|
115
129
|
exports.awsGo = awsGo;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"go.js","sourceRoot":"","sources":["../../../../src/platforms/aws/go.ts"],"names":[],"mappings":"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","sourcesContent":["// AWS sequential deploy (`qpq go`). Per service it: synths the QPQ config,\n// rspack-bundles the backend (programmatic — no per-service rspack.config.ts),\n// deploys the inf/api/web CDK stacks (cdk runs the generic workspace app via\n// --app), bundles views (rspack, production) and syncs them to S3.\nimport { qpqDeployAwsCdkUtils } from 'quidproquo-deploy-awscdk';\nimport { getServiceRspackConfig } from 'quidproquo-deploy-rspack';\n\nimport path from 'path';\n\nimport { synthCommand } from '../../commands/synth';\nimport { DeployPlan } from '../../lib/deployPrompts';\nimport { getServiceDirectory, getServiceNamesWithViews } from '../../lib/discovery';\nimport { runAppHook } from '../../lib/hooks';\nimport { loadServiceQpqConfig } from '../../lib/qpqConfigs';\nimport { runRspack } from '../../lib/rspackRun';\nimport { runCommand } from '../../lib/runCommand';\nimport { logTimeEnd, logTimeStart } from '../../lib/timing';\nimport { bundleViews } from '../../lib/views';\nimport { isAwsCredentialsValid } from './awsCredentials';\nimport { deployAccountStack, deployBootstrapStack, deployDomainStack, deployServiceStack } from './stacks';\nimport { syncViewsToS3 } from './viewsSync';\n\nconst buildAndDeploy = async (\n serviceName: string,\n needsSynth: boolean,\n needsBuildApi: boolean,\n needsInfStack: boolean,\n needsApiStack: boolean,\n needsWebStack: boolean,\n needsViewStack: boolean,\n appName: string,\n): Promise<void> => {\n if (needsSynth) {\n console.log('Synth QPQ Configs');\n await synthCommand([serviceName, '--app', appName]);\n }\n\n const qpqConfigForService = loadServiceQpqConfig(appName, serviceName);\n\n if (needsBuildApi) {\n console.log('Building Api: ', serviceName);\n await runRspack(getServiceRspackConfig(qpqConfigForService, path.join(getServiceDirectory(appName, serviceName), 'service')));\n }\n\n if (needsInfStack) {\n console.log('Deploy Inf: ', serviceName);\n await deployServiceStack(serviceName, qpqDeployAwsCdkUtils.getInfStackName(qpqConfigForService), appName);\n }\n\n if (needsApiStack) {\n console.log('Deploy Api: ', serviceName);\n await deployServiceStack(serviceName, qpqDeployAwsCdkUtils.getApiStackName(qpqConfigForService), appName);\n }\n\n if (needsWebStack) {\n console.log('Deploy Web: ', serviceName);\n await deployServiceStack(serviceName, qpqDeployAwsCdkUtils.getWebStackName(qpqConfigForService), appName);\n }\n\n if (needsViewStack && getServiceNamesWithViews(appName).includes(serviceName)) {\n console.log('Building Views: ', serviceName);\n await bundleViews(appName, serviceName);\n await syncViewsToS3(appName, serviceName);\n }\n};\n\nexport const awsGo = async (appName: string, plan: DeployPlan): Promise<void> => {\n if (plan.kind === 'cancelled') {\n return;\n }\n\n logTimeStart('totalTime');\n\n if (plan.kind === 'account') {\n await deployAccountStack(plan.appName);\n logTimeEnd('totalTime');\n return;\n }\n\n if (plan.kind === 'bootstrap') {\n // Actor bootstraps deploy into a shared account — leave the account-level\n // guardrails stack alone (deploy it explicitly via the 'account' option).\n if (process.env.ACTOR_NAME) {\n console.log('Skipping account stack for actor deploy');\n } else {\n await deployAccountStack(plan.appName);\n }\n if (plan.includeDomain) {\n await deployDomainStack(plan.appName);\n }\n await deployBootstrapStack(plan.appName);\n logTimeEnd('totalTime');\n return;\n }\n\n const { services, stacks } = plan;\n const shouldBuildApi = stacks !== 'views';\n\n console.log('\\n\\nRunning automated deploy\\n\\n');\n console.log('Executing for services');\n console.log(services.join(', '));\n\n if ((await isAwsCredentialsValid()) === false) {\n console.log('Credentials are expired or invalid.');\n return;\n }\n\n const allStacks = stacks === 'all';\n\n await runAppHook(appName, 'predeploy');\n\n // Workspace packages resolve through their built dist/ (package.json main),\n // so bundles would ship stale code unless every lib is tsc'd first.\n console.log('Building workspace packages');\n await runCommand('npm', ['run', 'build', '--workspaces', '--if-present']);\n\n // Views uploads resolve bucket names from the shell service's config.\n if (allStacks || stacks === 'views') {\n await synthCommand(['shell', '--app', appName]);\n }\n\n for (let phase = 0; phase <= 5; phase += 1) {\n await services.reduce(async (cur, service) => {\n await cur;\n return buildAndDeploy(\n service,\n phase === 0,\n phase === 1 && shouldBuildApi,\n phase === 2 && (allStacks || stacks === 'inf'),\n phase === 3 && (allStacks || stacks === 'api'),\n phase === 4 && (allStacks || stacks === 'web'),\n phase === 5 && (allStacks || stacks === 'views'),\n appName,\n );\n }, Promise.resolve());\n }\n\n logTimeEnd('totalTime');\n};\n"]}
|
|
1
|
+
{"version":3,"file":"go.js","sourceRoot":"","sources":["../../../../src/platforms/aws/go.ts"],"names":[],"mappings":"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","sourcesContent":["// AWS sequential deploy (`qpq go`). Per service it: synths the QPQ config,\n// rspack-bundles the backend (programmatic — no per-service rspack.config.ts),\n// deploys the inf/api/web CDK stacks (cdk runs the generic workspace app via\n// --app), bundles views (rspack, production) and syncs them to S3. Finally, any\n// service that opts into module federation has its federated remote published\n// (built + uploaded + manifest flipped), so a deploy that ships new backend\n// code also republishes the code the lambdas federate.\nimport { qpqDeployAwsCdkUtils } from 'quidproquo-deploy-awscdk';\nimport { getServiceRspackConfig } from 'quidproquo-deploy-rspack';\n\nimport path from 'path';\n\nimport { synthCommand } from '../../commands/synth';\nimport { DeployPlan } from '../../lib/deployPrompts';\nimport { getServiceDirectory, getServiceNamesWithViews } from '../../lib/discovery';\nimport { runAppHook } from '../../lib/hooks';\nimport { getServiceNamesWithFederation, loadServiceQpqConfig } from '../../lib/qpqConfigs';\nimport { runRspack } from '../../lib/rspackRun';\nimport { runCommand } from '../../lib/runCommand';\nimport { logTimeEnd, logTimeStart } from '../../lib/timing';\nimport { bundleViews } from '../../lib/views';\nimport { isAwsCredentialsValid } from './awsCredentials';\nimport { awsPublish } from './publish';\nimport { deployAccountStack, deployBootstrapStack, deployDomainStack, deployServiceStack } from './stacks';\nimport { syncViewsToS3 } from './viewsSync';\n\nconst buildAndDeploy = async (\n serviceName: string,\n needsSynth: boolean,\n needsBuildApi: boolean,\n needsInfStack: boolean,\n needsApiStack: boolean,\n needsWebStack: boolean,\n needsViewStack: boolean,\n appName: string,\n): Promise<void> => {\n if (needsSynth) {\n console.log('Synth QPQ Configs');\n await synthCommand([serviceName, '--app', appName]);\n }\n\n const qpqConfigForService = loadServiceQpqConfig(appName, serviceName);\n\n if (needsBuildApi) {\n console.log('Building Api: ', serviceName);\n await runRspack(getServiceRspackConfig(qpqConfigForService, path.join(getServiceDirectory(appName, serviceName), 'service')));\n }\n\n if (needsInfStack) {\n console.log('Deploy Inf: ', serviceName);\n await deployServiceStack(serviceName, qpqDeployAwsCdkUtils.getInfStackName(qpqConfigForService), appName);\n }\n\n if (needsApiStack) {\n console.log('Deploy Api: ', serviceName);\n await deployServiceStack(serviceName, qpqDeployAwsCdkUtils.getApiStackName(qpqConfigForService), appName);\n }\n\n if (needsWebStack) {\n console.log('Deploy Web: ', serviceName);\n await deployServiceStack(serviceName, qpqDeployAwsCdkUtils.getWebStackName(qpqConfigForService), appName);\n }\n\n if (needsViewStack && getServiceNamesWithViews(appName).includes(serviceName)) {\n console.log('Building Views: ', serviceName);\n await bundleViews(appName, serviceName);\n await syncViewsToS3(appName, serviceName);\n }\n};\n\nexport const awsGo = async (appName: string, plan: DeployPlan): Promise<void> => {\n if (plan.kind === 'cancelled') {\n return;\n }\n\n logTimeStart('totalTime');\n\n if (plan.kind === 'account') {\n await deployAccountStack(plan.appName);\n logTimeEnd('totalTime');\n return;\n }\n\n if (plan.kind === 'bootstrap') {\n // Actor bootstraps deploy into a shared account — leave the account-level\n // guardrails stack alone (deploy it explicitly via the 'account' option).\n if (process.env.ACTOR_NAME) {\n console.log('Skipping account stack for actor deploy');\n } else {\n await deployAccountStack(plan.appName);\n }\n if (plan.includeDomain) {\n await deployDomainStack(plan.appName);\n }\n await deployBootstrapStack(plan.appName);\n logTimeEnd('totalTime');\n return;\n }\n\n const { services, stacks } = plan;\n const shouldBuildApi = stacks !== 'views';\n\n console.log('\\n\\nRunning automated deploy\\n\\n');\n console.log('Executing for services');\n console.log(services.join(', '));\n\n if ((await isAwsCredentialsValid()) === false) {\n console.log('Credentials are expired or invalid.');\n return;\n }\n\n const allStacks = stacks === 'all';\n\n await runAppHook(appName, 'predeploy');\n\n // Workspace packages resolve through their built dist/ (package.json main),\n // so bundles would ship stale code unless every lib is tsc'd first.\n console.log('Building workspace packages');\n await runCommand('npm', ['run', 'build', '--workspaces', '--if-present']);\n\n // Views uploads resolve bucket names from the shell service's config.\n if (allStacks || stacks === 'views') {\n await synthCommand(['shell', '--app', appName]);\n }\n\n for (let phase = 0; phase <= 5; phase += 1) {\n await services.reduce(async (cur, service) => {\n await cur;\n return buildAndDeploy(\n service,\n phase === 0,\n phase === 1 && shouldBuildApi,\n phase === 2 && (allStacks || stacks === 'inf'),\n phase === 3 && (allStacks || stacks === 'api'),\n phase === 4 && (allStacks || stacks === 'web'),\n phase === 5 && (allStacks || stacks === 'views'),\n appName,\n );\n }, Promise.resolve());\n }\n\n // Publishing federated remotes only matters once the new backend code is\n // live, so it's gated on the api stack having been (re)deployed. Services\n // without defineFederatedModuleStore(...) are skipped.\n if (allStacks || stacks === 'api') {\n const federatedServices = getServiceNamesWithFederation(appName, services);\n if (federatedServices.length > 0) {\n console.log('\\n\\nPublishing federated backends\\n');\n await awsPublish(appName, federatedServices);\n }\n }\n\n logTimeEnd('totalTime');\n};\n"]}
|