jest.resolver.cjs2.1 KBView on GitHub /**
* Custom jest resolver that mirrors the tsconfig.json "@/*" path aliases.
*
* tsconfig.json defines:
* "@/*": ["./", "./modules/cedar-os/src/*", "./modules/cedar-os/src/cedar-os-components/*",
* "../server/src/*"]
*
* Jest's moduleNameMapper only supports a single replacement per pattern, so it can't
* replicate this multi-path fallback. This resolver does it by trying each candidate
* in order and returning the first one that exists.
*
* The `../server/src/*` candidate is deliberately NOT mirrored here. It exists purely so
* tsc can resolve the server's own `@/` imports while it type-checks server sources pulled
* in via `@zero/server/*`. At runtime a mail test has no business loading backend modules
* into jsdom, so leaving it out keeps an accidental `@/services/...` from silently resolving
* to server code instead of failing loudly.
*/
const path = require('path');
const fs = require('fs');
const ROOT = path.resolve(__dirname);
/** Candidate suffixes that @/* expands to, in tsconfig priority order */
const AT_SLASH_ROOTS = [
ROOT,
path.join(ROOT, 'modules/cedar-os/src'),
path.join(ROOT, 'modules/cedar-os/src/cedar-os-components'),
];
/** Extensions to try when resolving without an explicit extension */
const EXTENSIONS = ['.ts', '.tsx', '.js', '.jsx', '/index.ts', '/index.tsx', '/index.js'];
function tryResolveWithExtensions(base) {
// If the path already has a known extension, check it directly
if (/\.(ts|tsx|js|jsx)$/.test(base)) {
if (fs.existsSync(base)) return base;
return null;
}
for (const ext of EXTENSIONS) {
const candidate = base + ext;
if (fs.existsSync(candidate)) return candidate;
}
return null;
}
module.exports = (request, options) => {
// Only intercept @/* imports that the default resolver would fail on
if (request.startsWith('@/')) {
const suffix = request.slice(2); // strip '@/'
for (const root of AT_SLASH_ROOTS) {
const resolved = tryResolveWithExtensions(path.join(root, suffix));
if (resolved) return resolved;
}
}
// Fall back to jest's built-in resolver for everything else
return options.defaultResolver(request, options);
};