All files / src/node-resolve/package utils.ts

30.95% Statements 13/42
0% Branches 0/14
0% Functions 0/15
32.5% Lines 13/40

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102  1x   1x           1x                                             1x                     1x                   1x             1x             1x       1x                     1x   1x           1x           1x          
/* eslint-disable no-await-in-loop */
import path from "path";
import { IsomorphicRollupFs } from "../../fs-iface";
import { fileExists } from "../fs";
 
function isModuleDir(current: string, moduleDirs: readonly string[]) {
  return moduleDirs.some((dir) => current.endsWith(dir));
}
 
export async function findPackageJson(
  base: string,
  moduleDirs: readonly string[],
  fs: IsomorphicRollupFs,
) {
  const { root } = path.parse(base);
  let current = base;
 
  while (current !== root && !isModuleDir(current, moduleDirs)) {
    const pkgJsonPath = path.join(current, "package.json");
    if (await fileExists(pkgJsonPath, fs)) {
      const pkgJsonString = (await fs.readFile(pkgJsonPath, "utf8")) as string;
      return {
        pkgJson: JSON.parse(pkgJsonString),
        pkgPath: current,
        pkgJsonPath,
      };
    }
    current = path.resolve(current, "..");
  }
  return null;
}
 
export function isUrl(str: string) {
  try {
    return !!new URL(str);
  } catch (_) {
    return false;
  }
}
 
/**
 * Conditions is an export object where all keys are conditions like 'node' (aka do not with '.')
 */
export function isConditions(exports: any) {
  return (
    typeof exports === "object" &&
    Object.keys(exports).every((k) => !k.startsWith("."))
  );
}
 
/**
 * Mappings is an export object where all keys start with '.
 */
export function isMappings(exports: any) {
  return typeof exports === "object" && !isConditions(exports);
}
 
/**
 * Check for mixed exports, which are exports where some keys start with '.' and some do not
 */
export function isMixedExports(exports: Record<string, any>) {
  const keys = Object.keys(exports);
  return (
    keys.some((k) => k.startsWith(".")) && keys.some((k) => !k.startsWith("."))
  );
}
 
export function createBaseErrorMsg(importSpecifier: string, importer: string) {
  return `Could not resolve import "${importSpecifier}" in ${importer}`;
}
 
export function createErrorMsg(
  context: any,
  reason?: string,
  isImports?: boolean,
) {
  const { importSpecifier, importer, pkgJsonPath } = context;
  const base = createBaseErrorMsg(importSpecifier, importer);
  const field = isImports ? "imports" : "exports";
  return `${base} using ${field} defined in ${pkgJsonPath}.${reason ? ` ${reason}` : ""}`;
}
 
export class ResolveError extends Error {}
 
export class InvalidConfigurationError extends ResolveError {
  constructor(context: any, reason?: string) {
    super(createErrorMsg(context, `Invalid "exports" field. ${reason}`));
  }
}
 
export class InvalidModuleSpecifierError extends ResolveError {
  constructor(context: any, isImports?: boolean, reason?: string) {
    super(createErrorMsg(context, reason, isImports));
  }
}
 
export class InvalidPackageTargetError extends ResolveError {
  constructor(context: any, reason?: string) {
    super(createErrorMsg(context, reason));
  }
}