@nmakarov/cli-toolkit 0.55.0 → 0.59.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/dist/index.js CHANGED
@@ -1081,6 +1081,10 @@ var Args = class _Args {
1081
1081
  this.parseArgs(args);
1082
1082
  this.env = this.get("env")?.toLowerCase() || "local";
1083
1083
  this.loadDotEnv();
1084
+ const envAfterDotEnv = this.get("env")?.toLowerCase();
1085
+ if (envAfterDotEnv) {
1086
+ this.env = envAfterDotEnv;
1087
+ }
1084
1088
  this.loadConfigFiles();
1085
1089
  this.checkConflicts();
1086
1090
  if (context && typeof context.registerCleanup === "function") {
@@ -3541,6 +3545,12 @@ var Db = class _Db {
3541
3545
  }
3542
3546
  if (!dbConnectionString) {
3543
3547
  if (!dbName) {
3548
+ const env = context?.args?.env;
3549
+ if (env && String(env).toLowerCase() !== "local") {
3550
+ throw new ParamError(
3551
+ `Db: dbName not set for env="${env}" (set --dbName or DB_NAME_${String(env).toUpperCase()})`
3552
+ );
3553
+ }
3544
3554
  dbName = "local";
3545
3555
  }
3546
3556
  const paramName = `dbConnectionString${capitalizeFirstLetter(dbName)}`;
@@ -5269,6 +5279,8 @@ function servicePaths(service) {
5269
5279
  current: join2(root, "current"),
5270
5280
  sharedEnv: join2(root, "shared", ".env"),
5271
5281
  ecosystem: join2(root, "shared", "ecosystem.config.cjs"),
5282
+ /** Preloaded by pm2 `node_args --require` so ENV survives flaky restarts. */
5283
+ ensureEnv: join2(root, "shared", "ensure-env.cjs"),
5272
5284
  deployLog: join2(root, "logs", "deploy.log"),
5273
5285
  lockHashFile: join2(root, "shared", ".package-lock.sha256")
5274
5286
  };
@@ -5658,7 +5670,10 @@ async function reloadPm2(paths, options = {}) {
5658
5670
  logger.info(`pm2 ${appName}: reloading (old pid=${oldPid})`);
5659
5671
  }
5660
5672
  }
5661
- await runShell(`pm2 startOrReload "${paths.ecosystem}" --update-env`, { logger });
5673
+ await runShell(
5674
+ `ENV=production NODE_ENV=production pm2 startOrReload "${paths.ecosystem}" --update-env`,
5675
+ { logger }
5676
+ );
5662
5677
  logger.info("pm2 reloaded");
5663
5678
  if (appName) {
5664
5679
  const proc = await waitPm2(
@@ -5707,7 +5722,10 @@ async function startPm2(paths, options = {}) {
5707
5722
  logger.info(`[dryRun] would pm2 start ${paths.ecosystem} --update-env`);
5708
5723
  return;
5709
5724
  }
5710
- await runShell(`pm2 start "${paths.ecosystem}" --update-env`, { logger });
5725
+ await runShell(
5726
+ `ENV=production NODE_ENV=production pm2 start "${paths.ecosystem}" --update-env`,
5727
+ { logger }
5728
+ );
5711
5729
  logger.info("pm2 started");
5712
5730
  if (appName) {
5713
5731
  const proc = await waitPm2(
@@ -5959,12 +5977,24 @@ function resolvePm2Args(pm2) {
5959
5977
  if (/(?:^|\s)--stopAllowance=/.test(base)) return base;
5960
5978
  return `${base}${base ? " " : ""}--stopAllowance=${Math.floor(stopSec)}`.trim();
5961
5979
  }
5980
+ function buildEnsureEnvScript() {
5981
+ return `/**
5982
+ * Written by cli-toolkit deploy (init-structure). Do not hand-edit.
5983
+ * Preloaded via pm2 node_args --require. Always set (do not only fill when unset):
5984
+ * \`pm2 startOrReload --update-env\` can inject a non-production ENV from the
5985
+ * deploy shell / prior dump, and a conditional assign would leave it in place.
5986
+ */
5987
+ process.env.ENV = "production";
5988
+ process.env.NODE_ENV = "production";
5989
+ `;
5990
+ }
5962
5991
  function buildEcosystemConfig(service, paths) {
5963
5992
  const { pm2 } = service;
5964
5993
  const outLog = join9(paths.logs, `${pm2.appName}.out.log`);
5965
5994
  const errLog = join9(paths.logs, `${pm2.appName}.err.log`);
5966
5995
  const killTimeoutMs = resolveKillTimeoutMs(pm2);
5967
5996
  const args = resolvePm2Args(pm2);
5997
+ const ensureEnv = paths.ensureEnv;
5968
5998
  return `/**
5969
5999
  * pm2 ecosystem for ${service.name} \u2014 written by cli-toolkit deploy from the
5970
6000
  * service manifest (init/deploy). Do not hand-edit; change pm2.* in the
@@ -5977,6 +6007,8 @@ module.exports = {
5977
6007
  script: "${pm2.script}",
5978
6008
  cwd: "${paths.current}",
5979
6009
  args: ${JSON.stringify(args)},
6010
+ // Absolute --require so ENV is set before Args constructs (see shared/ensure-env.cjs).
6011
+ node_args: ${JSON.stringify(`--require ${ensureEnv}`)},
5980
6012
  instances: 1,
5981
6013
  exec_mode: "fork",
5982
6014
  autorestart: true,
@@ -6018,9 +6050,17 @@ async function initServiceStructure(service, options = {}) {
6018
6050
  created.push(dir);
6019
6051
  }
6020
6052
  const ecosystemExisted = await pathExists4(paths.ecosystem);
6053
+ const ensureEnvExisted = await pathExists4(paths.ensureEnv);
6021
6054
  if (!dryRun) {
6055
+ await writeFile5(paths.ensureEnv, buildEnsureEnvScript(), { mode: 420 });
6022
6056
  await writeFile5(paths.ecosystem, buildEcosystemConfig(service, paths), { mode: 420 });
6023
6057
  }
6058
+ if (ensureEnvExisted) {
6059
+ logger.info(`synced ${paths.ensureEnv}`);
6060
+ } else {
6061
+ created.push(paths.ensureEnv);
6062
+ logger.info(`seeded ${paths.ensureEnv}`);
6063
+ }
6024
6064
  if (ecosystemExisted) {
6025
6065
  logger.info(`synced ${paths.ecosystem} from manifest`);
6026
6066
  } else {