fix(gateway): anchor dotenv discovery to module (#1138)

This commit is contained in:
shaggy (mosaic-dev box)
2026-08-09 22:21:17 -05:00
parent b82a51da80
commit 884d527cc8
2 changed files with 418 additions and 49 deletions
+74 -8
View File
@@ -1,14 +1,80 @@
import { config } from 'dotenv';
import { existsSync } from 'node:fs';
import { homedir } from 'node:os';
import { join, resolve } from 'node:path';
import { dirname, join, resolve } from 'node:path';
import { fileURLToPath } from 'node:url';
import { detectFromEnv, loadConfig } from '@mosaicstack/config';
// Load .env from daemon config dir (global install / daemon mode).
// It takes precedence over file-based local-dev configuration.
type TierSource =
| 'process environment'
| 'daemon .env'
| 'monorepo-root .env'
| 'gateway-local .env'
| 'default';
type BootSource = TierSource | 'mosaic.config.json';
const here = dirname(fileURLToPath(import.meta.url));
const daemonEnv = join(homedir(), '.config', 'mosaic', 'gateway', '.env');
if (existsSync(daemonEnv)) config({ path: daemonEnv });
const monorepoRootEnv = resolve(here, '../../..', '.env');
const gatewayLocalEnv = resolve(here, '..', '.env');
// Load .env from monorepo root (cwd is apps/gateway when run via pnpm filter),
// then fill any remaining values from apps/gateway/.env when present.
config({ path: resolve(process.cwd(), '../../.env') });
config();
const inheritedTier = process.env['MOSAIC_STORAGE_TIER'];
let tierSource: TierSource = inheritedTier === undefined ? 'default' : 'process environment';
const inheritedDatabaseUrl = process.env['DATABASE_URL'];
let databaseUrlSource: TierSource =
inheritedDatabaseUrl === undefined ? 'default' : 'process environment';
function loadAnchoredDotenv(
path: string,
sourceLabel: Exclude<TierSource, 'process environment' | 'default'>,
): void {
if (!existsSync(path)) {
return;
}
const beforeTier = process.env['MOSAIC_STORAGE_TIER'];
const beforeDatabaseUrl = process.env['DATABASE_URL'];
config({ path, quiet: true });
if (
beforeTier === undefined &&
process.env['MOSAIC_STORAGE_TIER'] !== undefined &&
tierSource === 'default'
) {
tierSource = sourceLabel;
}
if (
beforeDatabaseUrl === undefined &&
process.env['DATABASE_URL'] !== undefined &&
databaseUrlSource === 'default'
) {
databaseUrlSource = sourceLabel;
}
}
// Load .env from daemon config dir (global install / daemon mode) first.
// It takes precedence over file-based local-dev configuration.
loadAnchoredDotenv(daemonEnv, 'daemon .env');
// Load .env from the anchored monorepo root, then fill any remaining values
// from apps/gateway/.env when present.
loadAnchoredDotenv(monorepoRootEnv, 'monorepo-root .env');
loadAnchoredDotenv(gatewayLocalEnv, 'gateway-local .env');
const envOnlyTier = detectFromEnv().tier;
const resolvedTier = loadConfig().tier;
let source: BootSource;
if (resolvedTier !== envOnlyTier) {
source = 'mosaic.config.json';
} else if (tierSource !== 'default') {
source = tierSource;
} else if (envOnlyTier === 'standalone' && databaseUrlSource !== 'default') {
source = databaseUrlSource;
} else {
source = 'default';
}
console.info(`[gateway env] storage tier=${resolvedTier} source=${source}`);