function getSource(loader, name, callback) {
  let componentName = name;
  let component = loader.components[name];
  if (!component) {
    // Try an alias
    const keys = Object.keys(loader.components);
    for (let i = 0; i < keys.length; i += 1) {
      const key = keys[i];
      if (key.split('/')[1] === name) {
        component = loader.components[key];
        componentName = key;
        break;
      }
    }
    if (!component) {
      callback(new Error(`Component ${componentName} not installed`));
      return;
    }
  }

  const nameParts = componentName.split('/');
  if (nameParts.length === 1) {
    nameParts[1] = nameParts[0];
    nameParts[0] = '';
  }

  /**
   * @param {Error|null} err
   * @param {Object} [src]
   */
  const finalize = (err, src) => {
    if (err) {
      callback(err);
      return;
    }
    if (!loader.specsForComponents) {
      callback(err, src);
      return;
    }
    if (!loader.specsForComponents[componentName]) {
      callback(err, src);
      return;
    }
    const specPath = loader.specsForComponents[componentName];
    fs.readFile(path.resolve(loader.baseDir, specPath), 'utf-8', (fsErr, specs) => {
      if (fsErr) {
        // Ignore spec reading errors
        callback(err, src);
        return;
      }
      callback(err, {
        ...src,
        tests: specs,
      });
    });
  };

  if (loader.isGraph(component)) {
    if (typeof component === 'object') {
      const comp = /** @type import("fbp-graph").Graph */ (component);
      if (typeof comp.toJSON === 'function') {
        finalize(null, {
          name: nameParts[1],
          library: nameParts[0],
          code: JSON.stringify(comp.toJSON()),
          language: 'json',
        });
        return;
      }
      finalize(new Error(`Can't provide source for ${componentName}. Not a file`));
      return;
    }
    if (typeof component === 'string') {
      fbpGraph.graph.loadFile(component, (err, graph) => {
        if (err) {
          finalize(err);
          return;
        }
        if (!graph) {
          finalize(new Error('Unable to load graph'));
          return;
        }
        finalize(null, {
          name: nameParts[1],
          library: nameParts[0],
          code: JSON.stringify(graph.toJSON()),
          language: 'json',
        });
      });
      return;
    }
  }

  if (loader.sourcesForComponents && loader.sourcesForComponents[componentName]) {
    finalize(null, {
      name: nameParts[1],
      library: nameParts[0],
      code: loader.sourcesForComponents[componentName].source,
      language: loader.sourcesForComponents[componentName].language,
    });
    return;
  }

  if (typeof component === 'string') {
    const componentFile = component;
    fs.readFile(componentFile, 'utf-8', (err, code) => {
      if (err) {
        finalize(err);
        return;
      }
      finalize(null, {
        name: nameParts[1],
        library: nameParts[0],
        language: utils.guessLanguageFromFilename(componentFile),
        code,
      });
    });
    return;
  }
  finalize(new Error(`Can't provide source for ${componentName}. Not a file`));
}
@param {import("../ComponentLoader").ComponentLoader} loader
@param {string} name
@param {SourceCallback} callback
@returns {void}