aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/utils.js
blob: 446402ccf98d6f457294229d1db60d573e63b1ac (plain) (blame)
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
const path = require('path');

exports.PscError = class PscError extends Error {
  constructor(message, modules) {
    super(message);
    this.modules = modules;
    this.isPscError = true;
  }

  static get name() {
    return 'PscError';
  }
};

const repeat = (value, times) =>
  times <= 0 ? [] : [value, ...repeat(value, times - 1)];
const diffPursModuleNames = (from, target, parts) => {
  if (!from.length) return parts.concat(target);
  if (!target.length) return parts.concat(repeat('..', from.length));
  const [head_from, ...tail_from] = from;
  const [head_target, ...tail_target] = target;
  return head_from === head_target
    ? diffPursModuleNames(tail_from, tail_target, parts)
    : parts.concat(repeat('..', from.length), target);
};

const normalizeRewriteRuleDest = ({ dest, moduleName }) =>
  typeof dest === 'function' ? dest(moduleName) : dest;
const rewrite = ({ rules, moduleName }) => {
  const moduleNameParts = moduleName.split('.')
  for (const [rule, dest] of Object.entries(rules)) {
    const ruleParts = rule.split('.');
    const matched = ruleParts.every((part, i) =>
      part === '*' || part === moduleNameParts[i]);
    if (!matched) continue;
    const rest = moduleNameParts.slice(ruleParts.length);
    const base = normalizeRewriteRuleDest({ dest, moduleName });
    return `${path.join(base, ...rest)}.purs`;
  }
};

exports.resolvePursModule = ({ baseModulePath, baseModuleName, rewriteRules, targetModuleName }) => {
  const rewrittenModulePath = rewrite({ rules: rewriteRules, moduleName: targetModuleName });
  if (rewrittenModulePath) return rewrittenModulePath;
  const parts = diffPursModuleNames(
    baseModuleName.split('.'),
    targetModuleName.split('.'),
    []);
  return parts.length
    ? path.resolve(baseModulePath,
      `${path.join(...parts)}.purs`)
    : baseModulePath;
};

exports.resolveForeignModule = pursModulePath =>
  path.join(path.dirname(pursModulePath),
    path.basename(pursModulePath, path.extname(pursModulePath)) + '.js');