function asComponent(func, options) {
  let hasCallback = false;
  /** @type {Array<FuncParam>} */
  const params = getParams(func).filter((p) => {
    if (p.param !== 'callback') { return true; }
    hasCallback = true;
    return false;
  });

  const c = new Component(options);
  params.forEach((p) => {
    /** @type {PortOptions} */
    const portOptions = { required: true };
    if (typeof p.default !== 'undefined') {
      portOptions.default = p.default;
      portOptions.required = false;
    }
    c.inPorts.add(p.param, portOptions);
    c.forwardBrackets[p.param] = ['out', 'error'];
  });
  if (!params.length) {
    c.inPorts.add('in',
      { datatype: 'bang' });
  }

  c.outPorts.add('out');
  c.outPorts.add('error');
  c.process((input, output) => {
    let values;
    if (params.length) {
      for (let i = 0; i < params.length; i += 1) {
        const p = params[i];
        if (!input.hasData(p.param)) { return; }
      }
      values = params.map((p) => input.getData(p.param));
    } else {
      if (!input.hasData('in')) { return; }
      input.getData('in');
      values = [];
    }

    if (hasCallback) {
      // Handle Node.js style async functions
      /**
       * @param {Error|null} err
       * @param {any} [res]
       */
      const cb = (err, res) => {
        if (err) {
          output.done(err);
          return;
        }
        output.sendDone(res);
      };
      values.push(cb);
      func(...values);
      return;
    }

    const res = func(...values);
    if (res && (typeof res === 'object') && (typeof res.then === 'function')) {
      // Result is a Promise, resolve and handle
      const resPromise = /** @type {Promise<any>} */ (res);
      resPromise.then(
        (val) => output.sendDone(val),
        (err) => output.done(err),
      );
      return;
    }
    output.sendDone(res);
  });
  return c;
}
@param {Function} func
@param {Object} options
@returns {Component}