constructor(options = {}) {
    super();

    if (!(this instanceof AssetGraph)) {
      return new AssetGraph(options);
    }

    this.isAssetGraph = true;

    Object.assign(this, options);

    // this.root might be undefined, in which case urlTools.urlOrFsPathToUrl will use process.cwd()
    this.root = normalizeUrl(urlTools.urlOrFsPathToUrl(this.root, true)); // ensureTrailingSlash

    this._assets = new Set();
    this.idIndex = {};
    this._urlIndex = {};

    this.teepee = new Teepee({
      retry: ['selfRedirect', '5xx'],
      headers: {
        'User-Agent': `AssetGraph v${
          require('../package.json').version
        } (https://www.npmjs.com/package/assetgraph)`,
      },
    });
    // Clumsily opt out of teepee's expansion of {...} placeholders in urls.
    // We don't want that in assetgraph, and the regexp that teepee uses breaks for certain inputs: https://github.com/assetgraph/assetgraph/issues/1144
    this.teepee.expandUrl = function (url) {
      return url;
    };
  }
Create a new AssetGraph instance.

Options:

 - `root` (optional) The root URL of the graph, either as a fully
          qualified `file:` or `http:` url or file system
          path. Defaults to the current directory,
          ie. `file://<process.cwd()>/`. The purpose of the root
          option is to allow resolution of root-relative urls
          (eg. `<a href="/foo.html">`) from `file:` locations.

Examples:

    new AssetGraph()
        // => root: "file:///current/working/dir/"

    new AssetGraph({root: '/absolute/fs/path'});
        // => root: "file:///absolute/fs/path/"

    new AssetGraph({root: 'relative/path'})
        // => root: "file:///current/working/dir/relative/path/"

@constructor
@param {Object} options
@param {String} [options.root] AssetGraph root, allowing root relative URL resolution
@param {String} [options.canonicalRoot] Canonical URL root of deployed graph. Matching relations will be treated as root relative