Skip to content

Commit

Permalink
[ui/url] TypeScript-ify (#22849) (#22896)
Browse files Browse the repository at this point in the history
Looking to use `absoluteToParsedUrl()` in TypeScript and it would be nice if it was TypeScript as well.
  • Loading branch information
Spencer authored Sep 11, 2018
1 parent 704667f commit 9b03dd6
Show file tree
Hide file tree
Showing 7 changed files with 94 additions and 69 deletions.
4 changes: 2 additions & 2 deletions src/core/public/utils/modify_url.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ it('supports returning a new url spec', () => {
it('supports modifying the passed object', () => {
expect(
modifyUrl('http://localhost', parsed => {
parsed.port = 9999;
parsed.port = '9999';
parsed.auth = 'foo:bar';
})
).toBe('http://foo:bar@localhost:9999/');
Expand All @@ -43,7 +43,7 @@ it('supports changing pathname', () => {
it('supports changing port', () => {
expect(
modifyUrl('http://localhost:5601', parsed => {
parsed.port = parsed.port! + 1;
parsed.port = String(Number(parsed.port) + 1);
})
).toBe('http://localhost:5602/');
});
Expand Down
17 changes: 3 additions & 14 deletions src/core/public/utils/modify_url.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,23 +24,12 @@ interface UrlParts {
slashes?: boolean;
auth?: string;
hostname?: string;
port?: number;
port?: string;
pathname?: string;
query: { [key: string]: string | string[] | undefined };
hash?: string;
}

interface UrlFormatParts {
protocol?: string;
slashes?: boolean;
auth?: string;
hostname?: string;
port?: string | number;
pathname?: string;
query?: { [key: string]: string | string[] | undefined };
hash?: string;
}

/**
* Takes a URL and a function that takes the meaningful parts
* of the URL as a key-value object, modifies some or all of
Expand Down Expand Up @@ -69,7 +58,7 @@ interface UrlFormatParts {
* @param url the url to parse
* @param block a function that will modify the parsed url, or return a new one
*/
export function modifyUrl(url: string, block: (parts: UrlParts) => UrlFormatParts | void) {
export function modifyUrl(url: string, block: (parts: UrlParts) => Partial<UrlParts> | void) {
const parsed = parseUrl(url, true);

// copy over the most specific version of each
Expand All @@ -83,7 +72,7 @@ export function modifyUrl(url: string, block: (parts: UrlParts) => UrlFormatPart
slashes: parsed.slashes,
auth: parsed.auth,
hostname: parsed.hostname,
port: parsed.port ? Number(parsed.port) : undefined,
port: parsed.port,
pathname: parsed.pathname,
query: parsed.query || {},
hash: parsed.hash,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,10 @@
* under the License.
*/

import { parse } from 'url';

import { extractAppPathAndId } from './extract_app_path_and_id';
import { KibanaParsedUrl } from './kibana_parsed_url';
import { parse } from 'url';

/**
*
Expand All @@ -29,8 +30,15 @@ import { parse } from 'url';
* "/gra".
* @return {KibanaParsedUrl}
*/
export function absoluteToParsedUrl(absoluteUrl, basePath = '') {
export function absoluteToParsedUrl(absoluteUrl: string, basePath = '') {
const { appPath, appId } = extractAppPathAndId(absoluteUrl, basePath);
const { hostname, port, protocol } = parse(absoluteUrl);
return new KibanaParsedUrl({ basePath, appId, appPath, hostname, port, protocol });
return new KibanaParsedUrl({
basePath,
appId: appId!,
appPath,
hostname,
port,
protocol,
});
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,15 @@ import { parse } from 'url';
* @param {string} url - a relative or absolute url which contains an appPath, an appId, and optionally, a basePath.
* @param {string} basePath - optional base path, if given should start with "/".
*/
export function extractAppPathAndId(url, basePath = '') {
export function extractAppPathAndId(url: string, basePath = '') {
const parsedUrl = parse(url);
if (!parsedUrl.path) {
return { };
return {};
}
const pathWithoutBase = parsedUrl.path.slice(basePath.length);

if (!pathWithoutBase.startsWith('/app/')) {
return { };
return {};
}

const appPath = parsedUrl.hash && parsedUrl.hash.length > 0 ? parsedUrl.hash.slice(1) : '';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,48 +19,72 @@

import { parse } from 'url';

import { prependPath } from './prepend_path';
import { modifyUrl } from '../../../core/public/utils';
import { prependPath } from './prepend_path';

/**
* Represents the pieces that make up a url in Kibana, offering some helpful functionality for
* translating those pieces into absolute or relative urls. A Kibana url with a basePath looks like this:
* http://localhost:5601/basePath/app/appId#/an/appPath?with=query&params
* basePath is "/basePath"
* appId is "appId"
* appPath is "/an/appPath?with=query&params"
*
* Almost all urls in Kibana should have this structure, including the "/app" portion in front of the appId
* (one exception is the login link).
*/
export class KibanaParsedUrl {
interface Options {
/**
* @param {Object} options
* @property {string} options.basePath - An optional base path for kibana. If supplied, should start with a "/".
* e.g. in https://localhost:5601/gra/app/kibana#/visualize/edit/viz_id the basePath is
* "/gra".
* @property {string} options.appId - the app id.
* An optional base path for kibana. If supplied, should start with a "/".
* e.g. in https://localhost:5601/gra/app/kibana#/visualize/edit/viz_id the
* basePath is "/gra"
*/
basePath?: string;

/**
* The app id.
* e.g. in https://localhost:5601/gra/app/kibana#/visualize/edit/viz_id the app id is "kibana".
* @property {string} options.appPath - the path for a page in the the app. Should start with a "/". Don't include the hash sign. Can
*/
appId: string;

/**
* The path for a page in the the app. Should start with a "/". Don't include the hash sign. Can
* include all query parameters.
* e.g. in https://localhost:5601/gra/app/kibana#/visualize/edit/viz_id?g=state the appPath is
* "/visualize/edit/viz_id?g=state"
* @property {string} options.hostname - Optional hostname. Uses current window location's hostname if no host or
* protocol information is supplied.
* @property {string} options.port - Optional port. Uses current window location's port if no host or protocol
* information is supplied.
* @property {string} options.protocol - Optional protocol. Uses current window location's protocol if no host or
* protocol information is supplied.
*/
constructor(options) {
const {
appId,
basePath = '',
appPath = '',
hostname,
protocol,
port
} = options;
appPath?: string;

/**
* Optional hostname. Uses current window location's hostname if hostname, port,
* and protocol are undefined.
*/
hostname?: string;

/**
* Optional port. Uses current window location's port if hostname, port,
* and protocol are undefined.
*/
port?: string;

/**
* Optional protocol. Uses current window location's protocol if hostname, port,
* and protocol are undefined.
*/
protocol?: string;
}

/**
* Represents the pieces that make up a url in Kibana, offering some helpful functionality
* for translating those pieces into absolute or relative urls. A Kibana url with a basePath
* looks like this: http://localhost:5601/basePath/app/appId#/an/appPath?with=query&params
*
* - basePath is "/basePath"
* - appId is "appId"
* - appPath is "/an/appPath?with=query&params"
*
* Almost all urls in Kibana should have this structure, including the "/app" portion in front of the appId
* (one exception is the login link).
*/
export class KibanaParsedUrl {
public appId: string;
public appPath: string;
public basePath: string;
public hostname?: string;
public protocol?: string;
public port?: string;

constructor(options: Options) {
const { appId, basePath = '', appPath = '', hostname, protocol, port } = options;

// We'll use window defaults
const hostOrProtocolSpecified = hostname || protocol || port;
Expand All @@ -73,7 +97,7 @@ export class KibanaParsedUrl {
this.protocol = hostOrProtocolSpecified ? protocol : window.location.protocol;
}

getGlobalState() {
public getGlobalState() {
if (!this.appPath) {
return '';
}
Expand All @@ -82,35 +106,39 @@ export class KibanaParsedUrl {
return query._g || '';
}

setGlobalState(newGlobalState) {
if (!this.appPath) { return; }
public setGlobalState(newGlobalState: string) {
if (!this.appPath) {
return;
}

this.appPath = modifyUrl(this.appPath, parsed => {
parsed.query._g = newGlobalState;
});
}

addQueryParameter(name, val) {
this.appPath = modifyUrl(this.appPath, parsed => { parsed.query[name] = val; });
public addQueryParameter(name: string, val: string) {
this.appPath = modifyUrl(this.appPath, parsed => {
parsed.query[name] = val;
});
}

getHashedAppPath() {
public getHashedAppPath() {
return `#${this.appPath}`;
}

getAppBasePath() {
public getAppBasePath() {
return `/${this.appId}`;
}

getAppRootPath() {
public getAppRootPath() {
return `/app${this.getAppBasePath()}${this.getHashedAppPath()}`;
}

getRootRelativePath() {
public getRootRelativePath() {
return prependPath(this.getAppRootPath(), this.basePath);
}

getAbsoluteUrl() {
public getAbsoluteUrl() {
return modifyUrl(this.getRootRelativePath(), parsed => {
parsed.protocol = this.protocol;
parsed.port = this.port;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@
* under the License.
*/

import { parse, format } from 'url';
import { isString } from 'lodash';
import { format, parse } from 'url';

/**
*
Expand All @@ -28,7 +28,7 @@ import { isString } from 'lodash';
* the relative path isn't in the right format (e.g. doesn't start with a "/") the relativePath is returned
* unchanged.
*/
export function prependPath(relativePath, newPath = '') {
export function prependPath(relativePath: string, newPath = '') {
if (!relativePath || !isString(relativePath)) {
return relativePath;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
* starts with a "/", for example "/account/cart", you would get back "http://www.mysite.com/account/cart".
* @return {string} the relative url transformed into an absolute url
*/
export function relativeToAbsolute(url) {
export function relativeToAbsolute(url: string) {
// convert all link urls to absolute urls
const a = document.createElement('a');
a.setAttribute('href', url);
Expand Down

0 comments on commit 9b03dd6

Please sign in to comment.