@willbooster/wb 15.2.1 → 15.3.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/bin/dotenv.js CHANGED
@@ -83,17 +83,30 @@ function validateStandardWbEnv(value, fixTarget) {
83
83
 
84
84
  // Mirrors src/commands/dotenv.ts (readAndApplyEnvironmentVariables) for this startup fast path.
85
85
  function readAndApplyEnvironmentVariables(cwd) {
86
+ // The mode is FORCED only when WB_ENV is explicitly exported; it drives the forced-mode override
87
+ // below and the validation at the end.
86
88
  const mode = process.env.WB_ENV;
87
- // Mode-specific sources drive the forced-mode override below.
89
+ // Two selectors, both defaulting to development like wb's main loader (`WB_ENV || NODE_ENV ||
90
+ // 'development'`) so a repo keeping dev-only secrets in `[profiles.development.secrets]` loads them
91
+ // when WB_ENV is unset instead of only the base table:
92
+ // - envCascade picks the `.env.<envCascade>` files. It must NOT consult FNOX_PROFILE — that is a
93
+ // fnox-only selector, and letting it redirect a legacy `.env`-only project's cascade would load
94
+ // the wrong files.
95
+ // - fnoxCascade picks the fnox `--profile` and gates the WB_ENV check below. It additionally honors
96
+ // an explicit FNOX_PROFILE, because fnox honors it and `wb dotenv` without WB_ENV is documented
97
+ // to as well.
98
+ const envCascade = mode || process.env.NODE_ENV || 'development';
99
+ const fnoxCascade = mode || process.env.FNOX_PROFILE || process.env.NODE_ENV || 'development';
100
+ // Mode-specific sources drive the forced-mode override below (only meaningful when the mode is forced).
88
101
  const modeVars = mode
89
102
  ? { ...readEnvFile(path.join(cwd, `.env.${mode}`)), ...readEnvFile(path.join(cwd, `.env.${mode}.local`)) }
90
103
  : {};
91
- // Mirror the shared cascade's precedence: .env.<mode>.local > .env.local > .env.<mode> > .env.
104
+ // Mirror the shared cascade's precedence: .env.<c>.local > .env.local > .env.<c> > .env (c = envCascade).
92
105
  const dotenvVars = {
93
106
  ...readEnvFile(path.join(cwd, '.env')),
94
- ...(mode ? readEnvFile(path.join(cwd, `.env.${mode}`)) : {}),
107
+ ...readEnvFile(path.join(cwd, `.env.${envCascade}`)),
95
108
  ...readEnvFile(path.join(cwd, '.env.local')),
96
- ...(mode ? readEnvFile(path.join(cwd, `.env.${mode}.local`)) : {}),
109
+ ...readEnvFile(path.join(cwd, `.env.${envCascade}.local`)),
97
110
  };
98
111
  // WB_ENV in process.env means the mode is explicitly forced, so values from the mode's own
99
112
  // sources (.env.<mode>[.local] and the fnox profile) win over variables inherited from the
@@ -101,7 +114,7 @@ function readAndApplyEnvironmentVariables(cwd) {
101
114
  // (see https://github.com/WillBooster/shared/issues/930).
102
115
  const modeFileOverridesProcessEnv = !!mode && !isCI(process.env.CI);
103
116
  // fnox.toml is the committed, encrypted equivalent of .env files; local .env files still win over it.
104
- const fnoxVars = readFnoxEnvironmentVariables(cwd, mode, dotenvVars, modeFileOverridesProcessEnv);
117
+ const fnoxVars = readFnoxEnvironmentVariables(cwd, fnoxCascade, dotenvVars, modeFileOverridesProcessEnv);
105
118
  const parsed = { ...fnoxVars, ...dotenvVars };
106
119
  // Expand ${...} references against exported variables whose FILE value loses to the shell
107
120
  // (mirroring readEnvironmentVariables' effective-value semantics): a reference must resolve to
@@ -139,18 +152,26 @@ function readAndApplyEnvironmentVariables(cwd) {
139
152
  // child will see.
140
153
  validateStandardWbEnv(mode, 'the exported variable');
141
154
  validateStandardWbEnv(process.env.WB_ENV, 'the env source or the exported variable');
142
- // The exported mode selected the cascade, so a mode file silently replacing it with a DIFFERENT
143
- // valid mode (e.g. `.env.production` containing `WB_ENV=development`) must be rejected as well.
155
+ // The selected environment is what an env source silently resolving WB_ENV to a DIFFERENT value must
156
+ // agree with, else the child runs labeled one environment while carrying another's secrets. The
157
+ // expectation is `fnoxCascade` only when a fnox config participates (its profile provides WB_ENV in a
158
+ // compliant repo); in a legacy `.env`-only project FNOX_PROFILE is irrelevant, so the expectation is
159
+ // `envCascade`. This covers both a forced `.env.production` containing `WB_ENV=development` and the
160
+ // default-development path (`.env.development`, read even when WB_ENV is unset, containing
161
+ // `WB_ENV=production`), comparing against the selected cascade rather than just the forced `mode`.
162
+ // Only a STANDARD cascade is enforced (mirroring Project.completeAndValidateWbEnv): a custom suffix
163
+ // such as `NODE_ENV=qa` legitimately selects `.env.qa` while WB_ENV stays a standard mode.
164
+ const expectedCascade = hasProjectFnoxConfig(cwd) ? fnoxCascade : envCascade;
144
165
  if (
145
- mode &&
146
166
  process.env.WB_ENV &&
147
- process.env.WB_ENV !== mode &&
167
+ ['development', 'test', 'staging', 'production'].includes(expectedCascade) &&
168
+ process.env.WB_ENV !== expectedCascade &&
148
169
  process.env.WB_SKIP_ENV_CHECK !== '1' &&
149
170
  process.env.WB_SKIP_ENV_CHECK !== 'true'
150
171
  ) {
151
172
  console.error(
152
- `WB_ENV resolves to "${process.env.WB_ENV}" although the "${mode}" environment was selected. ` +
153
- `Fix the WB_ENV defined in the mode's env sources, or set WB_SKIP_ENV_CHECK=1 to skip this check.`
173
+ `WB_ENV resolves to "${process.env.WB_ENV}" although the "${expectedCascade}" environment was selected. ` +
174
+ `Fix the WB_ENV defined in the env sources, or set WB_SKIP_ENV_CHECK=1 to skip this check.`
154
175
  );
155
176
  process.exit(1);
156
177
  }
@@ -197,8 +218,8 @@ function runFnoxExport(cwd, cascade, options) {
197
218
  if (options.ignoreProfileEnvVar) {
198
219
  // Without `--profile`, fnox falls back to FNOX_PROFILE; the base-adjudication export must
199
220
  // read the BASE secrets, so the inherited profile selection is cleared for it — and only for
200
- // it: a profile-less PRIMARY export (e.g. `wb dotenv` without WB_ENV) keeps honoring
201
- // FNOX_PROFILE.
221
+ // it. A PRIMARY export still honors FNOX_PROFILE: it either stays profile-less (fnox reads the
222
+ // variable) or folds it into the `--profile` it passes (see wb dotenv's cascade).
202
223
  delete env.FNOX_PROFILE;
203
224
  }
204
225
  const result = childProcess.spawnSync('fnox', args, {