All files index.js

100% Statements 47/47
100% Branches 10/10
100% Functions 5/5
100% Lines 44/44
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 103 104 105 106 107 108 109 110          1x 1x 1x 1x                     1x   1x               1x 16x 16x     1x 8x 8x 7x 7x     1x     1x 9x 9x     1x 7x 7x 7x 7x 7x   7x       1x     15x   15x   6x   6x         6x   6x         6x   6x   3x   3x   3x   3x     6x   6x   3x   3x   3x   3x          
import { dirname, join, relative, resolve } from "path";
import debugConstructor from "debug";
import { execFileSync, spawn } from "child_process";
import { StringLiteral } from "babel-types";
 
const debug = debugConstructor("babel-plugin-bucklescript");
const globalPath = process.cwd();
const compileDir = "lib";
const fileRegex = /\.(re|ml)$/;
 
let bsb;
 
/* istanbul ignore next */
try {
  bsb = require.resolve("bs-platform/bin/bsb.exe");
} catch (_) {
  bsb = "bsb";
}
 
debug("Spawning bsb watch process");
 
const watcher = spawn(bsb, ["-w"], { stdio: ["ignore", "pipe", "pipe"] });
 
/* istanbul ignore next */
process.on("exit", () => {
  debug("Terminating bsb watch process");
  watcher.kill();
});
 
export const isBuckleScriptFile = path => {
  debug(`Checking if the file is a bs file: " ${path}"`);
  return fileRegex.test(path);
};
 
export const traverseExpression = (t, arg) => {
  debug("Traversing the AST expression");
  if (t.isStringLiteral(arg)) {
    debug("AST expression is a string");
    return arg;
  }
 
  return null;
};
 
export const getModuleType = state => {
  debug("Checking configured module type");
  return state.opts.module || "js";
};
 
export const getNewPath = (path, state) => {
  debug("Generating new path");
  const sourcePath = dirname(state.file.opts.filenameRelative);
  const requirePath = resolve(sourcePath, path);
  const rootPath = requirePath.replace(globalPath, "");
  const newPath = join(globalPath, compileDir, getModuleType(state), rootPath);
 
  return newPath.replace(fileRegex, ".js");
};
 
export default ({ types: t }) => {
  return {
    visitor: {
      CallExpression(path, state) {
        debug("Evaluating call expression");
 
        if (path.node.callee.name !== "require") return;
 
        debug("Call expression is a require call");
 
        const args = path.node.arguments;
 
        /* istanbul ignore next */
        if (!args.length) return;
 
        debug("Call expression has at least one argument");
 
        const firstArg = traverseExpression(t, args[0]);
 
        /* istanbul ignore next */
        if (!firstArg) return;
 
        debug("Call expression has a valid first argument");
 
        if (!isBuckleScriptFile(firstArg.value)) return;
 
        debug("Path is a bucklescript file");
 
        const newPath = getNewPath(firstArg.value, state);
 
        debug(`Setting new path: "${newPath}"`);
 
        path.node.arguments = [t.stringLiteral(newPath)];
      },
      ImportDeclaration(path, state) {
        debug("Evaluating import declaration");
 
        if (!isBuckleScriptFile(path.node.source.value)) return;
 
        debug("Path is a bucklescript file");
 
        const newPath = getNewPath(path.node.source.value, state);
 
        debug(`Setting new path: "${newPath}"`);
 
        path.node.source.value = t.stringLiteral(newPath);
      }
    }
  };
};