<commit_before>import * as appRoot from 'app-root-path';
import * as path from 'path';
import { fileExists, makeFuseBoxPath } from '../utils/utils';
import { handleBrowserField } from './browserField';
import { fileLookup } from './fileLookup';
import { IPackageMeta, IResolverProps } from './resolver';
import { getFolderEntryPointFromPackageJSON, isBrowserEntry } from './shared';
import { findUp } from '../utils/findUp';

const PROJECT_NODE_MODULES = path.join(appRoot.path, 'node_modules');

const NODE_MODULE_REGEX = /^(([^\.][\.a-z0-9@\-_]*)(\/)?([_a-z0-9.@-]+)?(\/)?(.*))$/i;

export interface IModuleParsed {
  name: string;
  target?: string;
}

export function isNodeModule(path: string): IModuleParsed | undefined {
  const matched = path.match(NODE_MODULE_REGEX);
  if (!matched) {
    return;
  }
  let [name, b, c] = [matched[2], matched[4], matched[6]];

  const result: IModuleParsed = { name };
  if (name[0] === '@') {
    result.name = name + '/' + b;
    if (c) {
      result.target = c;
    }
  } else {
    if (b) {
      result.target = c ? b + '/' + c : b;
    }
  }
  return result;
}

export function parseAllModulePaths(fileAbsPath: string) {
  const baseDir = path.dirname(fileAbsPath);
  const paths = [];

  const snippets = baseDir.split(/node_modules/);
  let current = '';
  if (snippets.length > 1) {
    const total = snippets.length - 1;
    for (let i = 0; i < total; i++) {
      current = path.join(current, snippets[i], 'node_modules');
      paths.push(current);
    }

    const last = snippets[total];

    const matchedLast = last.match(/[\/|\\]([a-z-@0-9_-]+)/gi);
    if (matchedLast && matchedLast[0]) {
      paths.push(path.join(paths[paths.length - 1], matchedLast[0], 'node_modules'));
    }
    return paths;
  }

  return [PROJECT_NODE_MODULES];
}

const CACHED_LOCAL_MODULES: { [key: string]: string | null } = {};
export function findTargetFolder(props: IResolverProps, parsed: IModuleParsed): string {
  // handle custom modules here
  if (props.modules) {
    for (const i in props.modules) {
      const f = path.join(props.modules[i], parsed.name);
      if (fileExists(f)) {
        return f;
      }
    }
  }

  const paths = parseAllModulePaths(props.filePath);

  for (let i = paths.length - 1; i >= 0; i--) {
    const attempted = path.join(paths[i], parsed.name);
    if (fileExists(attempted)) {
      return attempted;
    }
  }

  // let localModuleRoot = CACHED_LOCAL_MODULES[props.filePath];
  // if (localModuleRoot === undefined) {
  //   localModuleRoot = CACHED_LOCAL_MODULES[props.filePath] = findUp(props.filePath, 'node_modules');
  // }

  // if (!!localModuleRoot && paths.indexOf(localModuleRoot) === -1) {
  //   const attempted = path.join(localModuleRoot, parsed.name);
  //   if (fileExists(attempted)) {
  //     return attempted;
  //   }
  // }
}
export interface INodeModuleLookup {
  error?: string;
  targetAbsPath?: string;
  targetExtension?: string;
  targetFuseBoxPath?: string;
  isEntry?: boolean;
  forcedStatement?: string;
  meta?: IPackageMeta;
}

export function nodeModuleLookup(props: IResolverProps, parsed: IModuleParsed): INodeModuleLookup {
  let folder: string;

  folder = findTargetFolder(props, parsed);

  if (!folder) {
    return { error: `Cannot resolve "${parsed.name}"` };
  }<commit_msg>fix: add findup to resolver<commit_after>import * as appRoot from 'app-root-path';
import * as path from 'path';
import { fileExists, makeFuseBoxPath } from '../utils/utils';
import { handleBrowserField } from './browserField';
import { fileLookup } from './fileLookup';
import { IPackageMeta, IResolverProps } from './resolver';
import { getFolderEntryPointFromPackageJSON, isBrowserEntry } from './shared';
import { findUp } from '../utils/findUp';

const PROJECT_NODE_MODULES = path.join(appRoot.path, 'node_modules');

const NODE_MODULE_REGEX = /^(([^\.][\.a-z0-9@\-_]*)(\/)?([_a-z0-9.@-]+)?(\/)?(.*))$/i;

export interface IModuleParsed {
  name: string;
  target?: string;
}

export function isNodeModule(path: string): IModuleParsed | undefined {
  const matched = path.match(NODE_MODULE_REGEX);
  if (!matched) {
    return;
  }
  let [name, b, c] = [matched[2], matched[4], matched[6]];

  const result: IModuleParsed = { name };
  if (name[0] === '@') {
    result.name = name + '/' + b;
    if (c) {
      result.target = c;
    }
  } else {
    if (b) {
      result.target = c ? b + '/' + c : b;
    }
  }
  return result;
}

export function parseAllModulePaths(fileAbsPath: string) {
  const baseDir = path.dirname(fileAbsPath);
  const paths = [];

  const snippets = baseDir.split(/node_modules/);
  let current = '';
  if (snippets.length > 1) {
    const total = snippets.length - 1;
    for (let i = 0; i < total; i++) {
      current = path.join(current, snippets[i], 'node_modules');
      paths.push(current);
    }

    const last = snippets[total];

    const matchedLast = last.match(/[\/|\\]([a-z-@0-9_-]+)/gi);
    if (matchedLast && matchedLast[0]) {
      paths.push(path.join(paths[paths.length - 1], matchedLast[0], 'node_modules'));
    }
    return paths;
  }

  return [PROJECT_NODE_MODULES];
}

const CACHED_LOCAL_MODULES: { [key: string]: string | null } = {};
export function findTargetFolder(props: IResolverProps, parsed: IModuleParsed): string {
  // handle custom modules here
  if (props.modules) {
    for (const i in props.modules) {
      const f = path.join(props.modules[i], parsed.name);
      if (fileExists(f)) {
        return f;
      }
    }
  }

  const paths = parseAllModulePaths(props.filePath);

  for (let i = paths.length - 1; i >= 0; i--) {
    const attempted = path.join(paths[i], parsed.name);
    if (fileExists(attempted)) {
      return attempted;
    }
  }

  let localModuleRoot = CACHED_LOCAL_MODULES[props.filePath];
  if (localModuleRoot === undefined) {
    localModuleRoot = CACHED_LOCAL_MODULES[props.filePath] = findUp(props.filePath, 'node_modules');
  }

  if (!!localModuleRoot && paths.indexOf(localModuleRoot) === -1) {
    const attempted = path.join(localModuleRoot, parsed.name);
    if (fileExists(attempted)) {
      return attempted;
    }
  }
}
export interface INodeModuleLookup {
  error?: string;
  targetAbsPath?: string;
  targetExtension?: string;
  targetFuseBoxPath?: string;
  isEntry?: boolean;
  forcedStatement?: string;
  meta?: IPackageMeta;
}

export function nodeModuleLookup(props: IResolverProps, parsed: IModuleParsed): INodeModuleLookup {
  let folder: string;

  folder = findTargetFolder(props, parsed);

  if (!folder) {
    return { error: `Cannot resolve "${parsed.name}"` };
  }
{'fraction_non_alphanumeric': 0.16015151515151516, 'fraction_numerical': 0.005757575757575757, 'mean_word_length': 3.4571235651586765, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3846364', 'n_tokens_mistral': 2245, 'n_tokens_neox': 2201, 'n_words': 512}