From dc5533bb1e7f9ce68c0de71bbdc67f17613f2e2e Mon Sep 17 00:00:00 2001 From: Spencer Date: Mon, 10 Sep 2018 12:01:48 -0700 Subject: [PATCH] [ui/url] TypeScript-ify (#22849) Looking to use `absoluteToParsedUrl()` in TypeScript and it would be nice if it was TypeScript as well. --- src/core/public/utils/modify_url.test.ts | 4 +- src/core/public/utils/modify_url.ts | 17 +-- ...arsed_url.js => absolute_to_parsed_url.ts} | 14 ++- ...h_and_id.js => extract_app_path_and_id.ts} | 6 +- ...ana_parsed_url.js => kibana_parsed_url.ts} | 116 +++++++++++------- .../url/{prepend_path.js => prepend_path.ts} | 4 +- ...to_absolute.js => relative_to_absolute.ts} | 2 +- 7 files changed, 94 insertions(+), 69 deletions(-) rename src/ui/public/url/{absolute_to_parsed_url.js => absolute_to_parsed_url.ts} (87%) rename src/ui/public/url/{extract_app_path_and_id.js => extract_app_path_and_id.ts} (94%) rename src/ui/public/url/{kibana_parsed_url.js => kibana_parsed_url.ts} (59%) rename src/ui/public/url/{prepend_path.js => prepend_path.ts} (94%) rename src/ui/public/url/{relative_to_absolute.js => relative_to_absolute.ts} (96%) diff --git a/src/core/public/utils/modify_url.test.ts b/src/core/public/utils/modify_url.test.ts index d1b7081093c285..3b8091b7c3074c 100644 --- a/src/core/public/utils/modify_url.test.ts +++ b/src/core/public/utils/modify_url.test.ts @@ -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/'); @@ -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/'); }); diff --git a/src/core/public/utils/modify_url.ts b/src/core/public/utils/modify_url.ts index 15a5532226c60a..a441c7eed6a38e 100644 --- a/src/core/public/utils/modify_url.ts +++ b/src/core/public/utils/modify_url.ts @@ -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 @@ -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 | void) { const parsed = parseUrl(url, true); // copy over the most specific version of each @@ -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, diff --git a/src/ui/public/url/absolute_to_parsed_url.js b/src/ui/public/url/absolute_to_parsed_url.ts similarity index 87% rename from src/ui/public/url/absolute_to_parsed_url.js rename to src/ui/public/url/absolute_to_parsed_url.ts index ccbe35803ea036..cd2781c56eefe7 100644 --- a/src/ui/public/url/absolute_to_parsed_url.js +++ b/src/ui/public/url/absolute_to_parsed_url.ts @@ -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'; /** * @@ -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, + }); } diff --git a/src/ui/public/url/extract_app_path_and_id.js b/src/ui/public/url/extract_app_path_and_id.ts similarity index 94% rename from src/ui/public/url/extract_app_path_and_id.js rename to src/ui/public/url/extract_app_path_and_id.ts index 84ecd2296f00fe..44bba272e0873a 100644 --- a/src/ui/public/url/extract_app_path_and_id.js +++ b/src/ui/public/url/extract_app_path_and_id.ts @@ -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) : ''; diff --git a/src/ui/public/url/kibana_parsed_url.js b/src/ui/public/url/kibana_parsed_url.ts similarity index 59% rename from src/ui/public/url/kibana_parsed_url.js rename to src/ui/public/url/kibana_parsed_url.ts index ef84440ef7af8e..d05768ceb2c376 100644 --- a/src/ui/public/url/kibana_parsed_url.js +++ b/src/ui/public/url/kibana_parsed_url.ts @@ -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¶ms - * basePath is "/basePath" - * appId is "appId" - * appPath is "/an/appPath?with=query¶ms" - * - * 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¶ms + * + * - basePath is "/basePath" + * - appId is "appId" + * - appPath is "/an/appPath?with=query¶ms" + * + * 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; @@ -73,7 +97,7 @@ export class KibanaParsedUrl { this.protocol = hostOrProtocolSpecified ? protocol : window.location.protocol; } - getGlobalState() { + public getGlobalState() { if (!this.appPath) { return ''; } @@ -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; diff --git a/src/ui/public/url/prepend_path.js b/src/ui/public/url/prepend_path.ts similarity index 94% rename from src/ui/public/url/prepend_path.js rename to src/ui/public/url/prepend_path.ts index 343e2e05b0fcc0..b8a77d5c23beeb 100644 --- a/src/ui/public/url/prepend_path.js +++ b/src/ui/public/url/prepend_path.ts @@ -17,8 +17,8 @@ * under the License. */ -import { parse, format } from 'url'; import { isString } from 'lodash'; +import { format, parse } from 'url'; /** * @@ -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; } diff --git a/src/ui/public/url/relative_to_absolute.js b/src/ui/public/url/relative_to_absolute.ts similarity index 96% rename from src/ui/public/url/relative_to_absolute.js rename to src/ui/public/url/relative_to_absolute.ts index 14aed9d12eebec..7d0737d145a1b2 100644 --- a/src/ui/public/url/relative_to_absolute.js +++ b/src/ui/public/url/relative_to_absolute.ts @@ -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);