Home Manual Reference Source Test Repository

src/alias.js

/**
 * The registered path aliases.
 * @type {Map}
 */
const ALIASES = new Map([
  ['@app', '@root/lib'],
  ['@npm', '@root/node_modules'],
  ['@runtime', '@root/var'],
  ['@webroot', '@root/web']
]);

setAlias('@core', __dirname);
setAlias('@root', process.cwd());

/**
 * Translates a path alias into an actual path.
 *
 * The translation is done according to the following procedure:
 * - If the given alias does not start with `@`, it is returned back without change.
 * - Otherwise, look for the registered alias that matches the beginning part of the given alias. If it exists, replace the matching part of the given alias with the corresponding registered path.
 * - Throw an error or return an empty string, depending on the `throwError` parameter.
 *
 * @param {string} alias The alias to be translated.
 * @param {boolean} [throwError] Value indicating whether to throw an error if the given alias is invalid.
 * @return {string} The path corresponding to the alias, or an empty string if the root alias is not previously registered.
 * @throws {TypeError} The path alias is invalid while `throwError` is `true`.
 */
export function getAlias(alias, throwError = true) {
  if (typeof alias != 'string' || !alias.startsWith('@')) return alias;

  let parts = alias.split('/');
  let name = parts.shift();
  if (!ALIASES.has(name)) {
    if (throwError) throw new TypeError(`Invalid path alias: ${alias}`);
    return '';
  }

  parts.unshift(ALIASES.get(name));
  return getAlias(parts.join('/'));
}

/**
 * Registers a path alias.
 *
 * It must start with the character `@` so that it can be easily differentiated from non-alias paths.
 * Alias defined without leading `@` will be prefixed with `@` character.
 * Any trailing `/` and `\` characters in the given path will be trimmed.
 *
 * @param {string} name The alias name (e.g. `"@alias"`).
 * @param {string} path The path corresponding to the alias. This can be: a directory or a file path, a URL or a path alias.
 * @throws {TypeError} The specified name is empty.
 */
export function setAlias(name, path) {
  if (typeof name != 'string' || !name.length) throw new TypeError('The specified name is empty.');
  if (!name.startsWith('@')) name = `@${name}`;

  if (typeof path != 'string' || !path.length) ALIASES.delete(name);
  else ALIASES.set(name, path.replace(/\\/g, '/').replace(/\/+$/, ''));
}