Re: [whatwg/url] Consider adding a constructor to make a URL from parts (#354)

I've been thinking a bit, and I think it would make sense to go from broad (href), to more specific (hostname). That way every time you add a more specific key, it will override what you specified earlier. A naive implementation would be this: 


```js
const { URL, URLSearchParams } = require('url');
function createURL(
  {
    hash,
    host,
    hostname,
    href,
    origin,
    password,
    pathname,
    port,
    protocol,
    search,
    searchParams,
    username,
  } = {}
) {
  const defaultHref =
    href !== undefined
      ? href
      : protocol !== undefined &&
        (host !== undefined || origin !== undefined || hostname !== undefined)
        ? `${protocol}//${host || origin || hostname}`
        : undefined;

  const url = new URL(defaultHref);

  // everything
  if (href !== undefined) {
    url.href = href;
  }

  // hostname : port
  if (host !== undefined) {
    url.host = host;
  }
  // protocol // hostname : port
  if (origin !== undefined) {
    url.origin = origin;
  }
  if (hostname !== undefined) {
    url.hostname = hostname;
  }

  // only visible in href
  if (password !== undefined) {
    url.password = password;
  }
  if (username !== undefined) {
    url.username = username;
  }

  if (port !== undefined) {
    url.port = port;
  }
  if (pathname !== undefined) {
    url.pathname = pathname;
  }

  // includes :
  if (protocol !== undefined) {
    url.protocol = protocol;
  }

  // includes #
  if (hash !== undefined) {
    url.hash = hash;
  }
  // let's say searchParams overrides search
  // includes ?
  if (search !== undefined) {
    url.search = search;
  }
  if (searchParams !== undefined) {
    // this overrides
    url.search = searchParams;
  }
  return url;
}
```

You can then use it like this: 

```
const url = createURL({
  href: 'ftp://google.com',
  protocol: 'https:',
  origin: 'github.com',
  host: 'morespecific.com:20',
  hostname: 'mostspecific.fr',
  pathname: '/whatwg/url/search',
  hash: '#haha',
  port: 800,
  search: '?not-specific-enough',
  searchParams: new URLSearchParams({
    utf8: '✓',
    q: 'test',
    type: undefined,
    cool: ['turbo', 'aaaa'],
    q: JSON.stringify({
      overkill: 'true',
      cool: 'no',
    }),
  }),
  username: 'anon',
  password: 'hunter12',
});
```

This would return 

```jsURL {
  href: 'https://anon:hunter12@mostspecific.fr:800/whatwg/url/search?utf8=%E2%9C%93&q=%7B%22overkill%22%3A%22true%22%2C%22cool%22%3A%22no%22%7D&type=undefined&cool=turbo%2Caaaa#haha',
  origin: 'https://mostspecific.fr:800',
  protocol: 'https:',
  username: 'anon',
  password: 'hunter12',
  host: 'mostspecific.fr:800',
  hostname: 'mostspecific.fr',
  port: '800',
  pathname: '/whatwg/url/search',
  search: '?utf8=%E2%9C%93&q=%7B%22overkill%22%3A%22true%22%2C%22cool%22%3A%22no%22%7D&type=undefined&cool=turbo%2Caaaa',
  searchParams: URLSearchParams {
  'utf8' => '✓',
  'q' => '{"overkill":"true","cool":"no"}',
  'type' => 'undefined',
  'cool' => 'turbo,aaaa' },
  hash: '#haha' }
```

It will throw when none of the minimal `defaultHref` items are available. In order that is: 

1. no href
2. no protocol and no host
2. no protocol and no origin
2. no protocol and no hostname

This will (now) throw an error with `undefined` not being a correct URL, but that can be replaced with an error with what you entered. 

Am I on the right track?

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/whatwg/url/issues/354#issuecomment-347264401

Received on Monday, 27 November 2017 17:46:56 UTC