/**
 * ESM/CJS-dual-mode helpers for the lazy `nodeRequire` pattern.
 *
 * Background
 * ----------
 * Several services in this codebase use the canonical `nodeRequire` pattern
 * (commit `070cd3e5` — `fix(esm): anchor createRequire to process.argv[1]`)
 * to lazily load modules without forcing every test that transitively imports
 * them to mock the dependency. The pattern looks like:
 *
 *     const nodeRequire: NodeRequire =
 *       typeof require === 'function'
 *         ? require
 *         : createRequire(pathToFileURL(process.argv[1] || process.cwd()).href);
 *
 * That pattern works **only** for npm-package targets (e.g.
 * `nodeRequire('better-sqlite3')`) — Node's resolver walks UP from the anchor
 * (`process.argv[1]`) to find `node_modules`, so the anchor's exact location
 * does not matter for package resolution.
 *
 * It silently breaks for **relative project paths** like
 * `nodeRequire('../v3/request.service.js')`. In production ESM, the relative
 * spec is resolved against `process.argv[1]` (the entry script) — NOT against
 * the calling module — so the require fails with `Cannot find module …`. In
 * tests (ts-jest CJS transpile) the per-module `require` parameter is used
 * instead, so the relative spec resolves correctly against the calling file
 * and the bug stays hidden.
 *
 * Symptom that motivated this helper: `core/get-my-active-work` returned 500
 * with "Cannot find module '../v3/request.service.js'" because
 * `ActiveWorkBriefingService.getInstance()` called
 * `nodeRequire('../v3/request.service.js')` from
 * `services/agent/active-work-briefing.service.js` while `nodeRequire` was
 * anchored to `dist/backend/backend/src/index.js`.
 *
 * What this helper does
 * ---------------------
 * `resolveProjectModulePath(testRelativePath, prodPathFromEntryDir)` returns:
 *
 * 1. In test mode (`typeof require === 'function'` — ts-jest CJS) — the
 *    `testRelativePath` unchanged, so the per-module CJS require resolves it
 *    relative to the calling file (its existing, working behavior).
 * 2. In production ESM — an absolute path computed by joining
 *    `path.dirname(process.argv[1])` with `prodPathFromEntryDir`.
 *    Absolute paths are accepted by `nodeRequire` regardless of anchor.
 *
 * Why this is two-arg rather than one
 * -----------------------------------
 * We considered single-arg variants:
 *   • `import.meta.url` — triggers TS1343 under ts-jest's CJS target. Even with
 *     `// @ts-expect-error`, ts-jest's transpile may still fail at parse.
 *   • `new Function('return import.meta.url')()` — was tried (PR #323) and is
 *     forbidden — `new Function` evaluates in non-module scope where
 *     `import.meta` is a SyntaxError. Crashed production at startup.
 *   • `eval('import.meta.url')` — works at runtime via direct-eval scope
 *     inheritance, but trips ESLint `no-eval` and is fragile across engines.
 *   • Stack-trace introspection — gross and slow.
 *
 * Asking the caller to spell out **two** equivalent paths (one usable from the
 * caller's perspective, one usable from the entry script's perspective) is
 * verbose but unambiguous, parse-clean under both TS targets, and free of any
 * runtime tricks.
 *
 * Usage
 * -----
 *     // Caller is at `backend/src/services/agent/active-work-briefing.service.ts`
 *     // Target is at `backend/src/services/v3/request.service.ts`
 *     // Entry script (process.argv[1]) is `dist/backend/backend/src/index.js`
 *     // → from the caller's perspective: `../v3/request.service.js`
 *     // → from the entry-script-dir's perspective: `services/v3/request.service.js`
 *
 *     const spec = resolveProjectModulePath(
 *       '../v3/request.service.js',
 *       'services/v3/request.service.js',
 *     );
 *     const { RequestService } = nodeRequire(spec);
 *
 * Test guard
 * ----------
 * `esm-require.utils.test.ts` exercises both branches and locks the contract
 * (test branch ↔ untouched relative path; prod branch ↔ absolute path joined
 * to `process.argv[1]`'s dirname).
 *
 * @module utils/esm-require.utils
 */
import path from 'path';
/**
 * Resolves a project-relative require spec to a string safe to pass to
 * `nodeRequire` in both ts-jest CJS test mode and production ESM mode.
 *
 * @param testRelativePath - The require spec written from the calling file's
 *   perspective. Used verbatim in test mode (ts-jest CJS) where each module
 *   gets its own `require` and relative resolution Just Works. Example:
 *   `'../v3/request.service.js'`.
 * @param prodPathFromEntryDir - The require spec rewritten as a path under
 *   `path.dirname(process.argv[1])`. Used in production ESM where
 *   `nodeRequire` is anchored to the entry script. Example:
 *   `'services/v3/request.service.js'` (under `dist/backend/backend/src/`).
 * @returns A string suitable for `nodeRequire(...)`.
 *
 * @example
 * ```typescript
 * const { RequestService } = nodeRequire(
 *   resolveProjectModulePath(
 *     '../v3/request.service.js',
 *     'services/v3/request.service.js',
 *   ),
 * );
 * ```
 */
export function resolveProjectModulePath(testRelativePath, prodPathFromEntryDir) {
    // The same `typeof require` probe the canonical `nodeRequire` pattern uses.
    // Under ts-jest's CJS transpile, the per-module `require` parameter is
    // defined and is the correct anchor for relative resolution. Under
    // production ESM, `require` is undefined globally and we must hand
    // `nodeRequire` an absolute path.
    if (typeof require === 'function') {
        return testRelativePath;
    }
    const entryScript = process.argv[1] || process.cwd();
    const entryDir = path.dirname(entryScript);
    return path.join(entryDir, prodPathFromEntryDir);
}
//# sourceMappingURL=esm-require.utils.js.map