fix: break remaining shared/mod.js barrel imports in report generation chain (#1588)
PR #1527 fixed metrics.ts but missed several other paths that still reach shared/mod.js → ui.js → @gsd/pi-tui during report generation via native dynamic import() (which bypasses jiti alias resolution). Remaining chains fixed: - preferences.ts, preferences-validation.ts, export.ts, forensics.ts, migrate/parsers.ts: import from shared/format-utils.js directly - state.ts, visualizer-data.ts, files.ts: import from milestone-ids.js instead of guided-flow.js (which pulls in shared/mod.js) - files.ts: import checkExistingEnvKeys from new env-utils.ts instead of get-secrets-from-user.ts (which imports @gsd/pi-tui) New file: env-utils.ts extracts the pure checkExistingEnvKeys function. Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
e35ad9d194
commit
21a9ab2bcf
10 changed files with 45 additions and 33 deletions
31
src/resources/extensions/env-utils.ts
Normal file
31
src/resources/extensions/env-utils.ts
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
// GSD Extension — Environment variable utilities
|
||||
// Copyright (c) 2026 Jeremy McSpadden <jeremy@fluxlabs.net>
|
||||
//
|
||||
// Pure utility for checking existing env keys in .env files and process.env.
|
||||
// Extracted from get-secrets-from-user.ts to avoid pulling in @gsd/pi-tui
|
||||
// when only env-checking is needed (e.g. from files.ts during report generation).
|
||||
|
||||
import { readFile } from "node:fs/promises";
|
||||
|
||||
/**
|
||||
* Check which keys already exist in a .env file or process.env.
|
||||
* Returns the subset of `keys` that are already set.
|
||||
*/
|
||||
export async function checkExistingEnvKeys(keys: string[], envFilePath: string): Promise<string[]> {
|
||||
let fileContent = "";
|
||||
try {
|
||||
fileContent = await readFile(envFilePath, "utf8");
|
||||
} catch {
|
||||
// ENOENT or other read error — proceed with empty content
|
||||
}
|
||||
|
||||
const existing: string[] = [];
|
||||
for (const key of keys) {
|
||||
const escaped = key.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
||||
const regex = new RegExp(`^${escaped}\\s*=`, "m");
|
||||
if (regex.test(fileContent) || key in process.env) {
|
||||
existing.push(key);
|
||||
}
|
||||
}
|
||||
return existing;
|
||||
}
|
||||
|
|
@ -67,30 +67,11 @@ async function writeEnvKey(filePath: string, key: string, value: string): Promis
|
|||
|
||||
// ─── Exported utilities ───────────────────────────────────────────────────────
|
||||
|
||||
/**
|
||||
* Check which keys already exist in the .env file or process.env.
|
||||
* Returns the subset of `keys` that are already set.
|
||||
* Handles ENOENT gracefully (still checks process.env).
|
||||
* Empty-string values count as existing.
|
||||
*/
|
||||
export async function checkExistingEnvKeys(keys: string[], envFilePath: string): Promise<string[]> {
|
||||
let fileContent = "";
|
||||
try {
|
||||
fileContent = await readFile(envFilePath, "utf8");
|
||||
} catch {
|
||||
// ENOENT or other read error — proceed with empty content
|
||||
}
|
||||
|
||||
const existing: string[] = [];
|
||||
for (const key of keys) {
|
||||
const escaped = key.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
||||
const regex = new RegExp(`^${escaped}\\s*=`, "m");
|
||||
if (regex.test(fileContent) || key in process.env) {
|
||||
existing.push(key);
|
||||
}
|
||||
}
|
||||
return existing;
|
||||
}
|
||||
// Re-export from env-utils.ts so existing consumers still work.
|
||||
// The implementation lives in env-utils.ts to avoid pulling @gsd/pi-tui
|
||||
// into modules that only need env-checking (e.g. files.ts during reports).
|
||||
import { checkExistingEnvKeys } from "./env-utils.js";
|
||||
export { checkExistingEnvKeys };
|
||||
|
||||
/**
|
||||
* Detect the write destination based on project files in basePath.
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import {
|
|||
} from "./metrics.js";
|
||||
import type { UnitMetrics } from "./metrics.js";
|
||||
import { gsdRoot } from "./paths.js";
|
||||
import { formatDuration, fileLink } from "../shared/mod.js";
|
||||
import { formatDuration, fileLink } from "../shared/format-utils.js";
|
||||
import { getErrorMessage } from "./error-utils.js";
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import { promises as fs } from 'node:fs';
|
|||
import { resolve } from 'node:path';
|
||||
import { atomicWriteAsync } from './atomic-write.js';
|
||||
import { resolveMilestoneFile, relMilestoneFile, resolveGsdRootFile } from './paths.js';
|
||||
import { milestoneIdSort, findMilestoneIds } from './guided-flow.js';
|
||||
import { milestoneIdSort, findMilestoneIds } from './milestone-ids.js';
|
||||
|
||||
import type {
|
||||
Roadmap, BoundaryMapEntry,
|
||||
|
|
@ -20,7 +20,7 @@ import type {
|
|||
ManifestStatus,
|
||||
} from './types.js';
|
||||
|
||||
import { checkExistingEnvKeys } from '../get-secrets-from-user.js';
|
||||
import { checkExistingEnvKeys } from '../env-utils.js';
|
||||
import { parseRoadmapSlices } from './roadmap-slices.js';
|
||||
import { nativeParseRoadmap, nativeExtractSection, nativeParsePlanFile, nativeParseSummaryFile, NATIVE_UNAVAILABLE } from './native-parser-bridge.js';
|
||||
import { debugTime, debugCount } from './debug-logger.js';
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ import { deriveState } from "./state.js";
|
|||
import { isAutoActive } from "./auto.js";
|
||||
import { loadPrompt } from "./prompt-loader.js";
|
||||
import { gsdRoot } from "./paths.js";
|
||||
import { formatDuration } from "../shared/mod.js";
|
||||
import { formatDuration } from "../shared/format-utils.js";
|
||||
import { getAutoWorktreePath } from "./auto-worktree.js";
|
||||
|
||||
// ─── Types ────────────────────────────────────────────────────────────────────
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
// Zero Pi dependencies — uses only exported helpers from files.ts.
|
||||
|
||||
import { splitFrontmatter, parseFrontmatterMap, extractBoldField } from '../files.js';
|
||||
import { normalizeStringArray } from '../../shared/mod.js';
|
||||
import { normalizeStringArray } from '../../shared/format-utils.js';
|
||||
|
||||
import type {
|
||||
PlanningRoadmap,
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import type { GitPreferences } from "./git-service.js";
|
|||
import type { PostUnitHookConfig, PreDispatchHookConfig, TokenProfile, PhaseSkipPreferences } from "./types.js";
|
||||
import type { DynamicRoutingConfig } from "./model-router.js";
|
||||
import { VALID_BRANCH_NAME } from "./git-service.js";
|
||||
import { normalizeStringArray } from "../shared/mod.js";
|
||||
import { normalizeStringArray } from "../shared/format-utils.js";
|
||||
|
||||
import {
|
||||
KNOWN_PREFERENCE_KEYS,
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ import { gsdRoot } from "./paths.js";
|
|||
import { parse as parseYaml } from "yaml";
|
||||
import type { PostUnitHookConfig, PreDispatchHookConfig, TokenProfile } from "./types.js";
|
||||
import type { DynamicRoutingConfig } from "./model-router.js";
|
||||
import { normalizeStringArray } from "../shared/mod.js";
|
||||
import { normalizeStringArray } from "../shared/format-utils.js";
|
||||
import { resolveProfileDefaults as _resolveProfileDefaults } from "./preferences-models.js";
|
||||
|
||||
import {
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ import {
|
|||
gsdRoot,
|
||||
} from './paths.js';
|
||||
|
||||
import { milestoneIdSort, findMilestoneIds } from './guided-flow.js';
|
||||
import { milestoneIdSort, findMilestoneIds } from './milestone-ids.js';
|
||||
import { nativeBatchParseGsdFiles, type BatchParsedFile } from './native-parser-bridge.js';
|
||||
|
||||
import { join, resolve } from 'path';
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
import { existsSync, readFileSync, statSync } from 'node:fs';
|
||||
import { deriveState } from './state.js';
|
||||
import { parseRoadmap, parsePlan, parseSummary, loadFile } from './files.js';
|
||||
import { findMilestoneIds } from './guided-flow.js';
|
||||
import { findMilestoneIds } from './milestone-ids.js';
|
||||
import { resolveMilestoneFile, resolveSliceFile, resolveGsdRootFile } from './paths.js';
|
||||
import {
|
||||
getLedger,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue