2018-02-21 09:46:04 -08:00
|
|
|
import { assert } from '@ember/debug';
|
2018-07-17 16:15:53 -07:00
|
|
|
import { DatasetPlatform, Fabric, isDatasetFabric } from 'wherehows-web/constants';
|
2018-02-21 09:46:04 -08:00
|
|
|
|
2018-03-14 14:45:14 -07:00
|
|
|
/**
|
|
|
|
* Path segment in a urn. common btw WH and LI formats
|
|
|
|
* @type {RegExp}
|
|
|
|
*/
|
2018-08-20 14:18:49 -07:00
|
|
|
const urnPath = /[\w.$\-\/{}+()\s\*]+/;
|
2017-04-28 22:02:46 -07:00
|
|
|
/**
|
2017-05-01 11:33:40 -07:00
|
|
|
* Matches a url string with a `urn` query. urn query with letters or underscore segment of any length greater
|
2017-05-01 22:58:16 -07:00
|
|
|
* than 1 followed by colon and 3 forward slashes and a segment containing letters, {, }, _ or /, or none
|
2017-04-28 22:02:46 -07:00
|
|
|
* The value following the urn key is retained
|
|
|
|
* @type {RegExp}
|
|
|
|
*/
|
2018-03-14 14:45:14 -07:00
|
|
|
const datasetUrnRegexWH = new RegExp(`([a-z_-]+):\/{3}(${urnPath.source})`, 'i');
|
2018-02-14 20:47:26 -08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Matches a urn string that follows the pattern captures, the comma delimited platform, segment and fabric
|
|
|
|
* e.g urn:li:dataset:(urn:li:dataPlatform:PLATFORM,SEGMENT,FABRIC)
|
|
|
|
* @type {RegExp}
|
|
|
|
*/
|
2018-07-11 10:09:42 -07:00
|
|
|
const datasetUrnRegexLI = new RegExp(`urn:li:dataset:\\(urn:li:dataPlatform:([\\w-]+),(${urnPath.source})?,(\\w+)\\)`);
|
2017-05-15 12:45:28 -07:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Matches urn's that occur in flow urls
|
|
|
|
* @type {RegExp}
|
|
|
|
*/
|
2017-09-20 14:25:27 -07:00
|
|
|
const specialFlowUrnRegex = /(?:\?urn=)([a-z0-9_\-/{}\s]+)/i;
|
|
|
|
|
2018-02-14 20:47:26 -08:00
|
|
|
/**
|
|
|
|
* Checks if a string matches the datasetUrnRegexWH
|
|
|
|
* @param {string} candidateUrn
|
|
|
|
* @returns {boolean}
|
|
|
|
*/
|
|
|
|
const isWhUrn = (candidateUrn: string): boolean => datasetUrnRegexWH.test(String(candidateUrn));
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Checks if a string matches the datasetUrnRegexLI
|
|
|
|
* @param {string} candidateUrn
|
|
|
|
* @returns {boolean}
|
|
|
|
*/
|
|
|
|
const isLiUrn = (candidateUrn: string): boolean => datasetUrnRegexLI.test(String(candidateUrn));
|
|
|
|
|
2018-05-02 09:45:26 -07:00
|
|
|
/**
|
|
|
|
* Checks that a string matches the expected valuePatternRegex
|
|
|
|
* @param {string} candidate the supplied pattern string
|
|
|
|
* @return {boolean}
|
|
|
|
*/
|
|
|
|
const isValidCustomValuePattern = (candidate: string): boolean => !!candidate; // TODO:
|
|
|
|
|
2017-04-28 13:44:31 -07:00
|
|
|
/**
|
|
|
|
* Asserts that a provided string matches the urn pattern above
|
2017-10-19 18:17:16 -07:00
|
|
|
* @param {string} candidateUrn the string to test on
|
2017-04-28 13:44:31 -07:00
|
|
|
*/
|
2018-02-14 20:47:26 -08:00
|
|
|
const isUrn = (candidateUrn: string) => isLiUrn(candidateUrn) || isWhUrn(candidateUrn);
|
2017-04-28 13:44:31 -07:00
|
|
|
|
2017-10-19 18:17:16 -07:00
|
|
|
/**
|
|
|
|
* Extracts the platform string from the candidate urn string
|
|
|
|
* @param {string} candidateUrn the urn string with leading platform identifier
|
|
|
|
* @returns {string | void}
|
|
|
|
*/
|
|
|
|
const getPlatformFromUrn = (candidateUrn: string) => {
|
2018-02-14 20:47:26 -08:00
|
|
|
const matches = datasetUrnRegexWH.exec(candidateUrn);
|
|
|
|
|
2017-10-19 18:17:16 -07:00
|
|
|
if (matches) {
|
|
|
|
const [, platform] = matches;
|
|
|
|
return platform.toUpperCase();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2018-07-18 14:57:04 -07:00
|
|
|
/**
|
|
|
|
* Extracts the constituent parts of a datasystem / dataset urn
|
|
|
|
* @param {string} urn
|
|
|
|
* @return {({platform: DatasetPlatform | void; prefix: string | void; fabric: Fabric | void})}
|
|
|
|
*/
|
|
|
|
const getUrnParts = (
|
|
|
|
urn: string
|
|
|
|
): { platform: DatasetPlatform | void; prefix: string | void; fabric: Fabric | void } => {
|
|
|
|
const match = datasetUrnRegexLI.exec(urn);
|
|
|
|
const urnParts = {
|
|
|
|
platform: void 0,
|
|
|
|
prefix: void 0,
|
|
|
|
fabric: void 0
|
|
|
|
};
|
|
|
|
|
|
|
|
if (match) {
|
|
|
|
let [, platform, prefix, fabric] = match;
|
|
|
|
fabric = String(fabric).toUpperCase();
|
|
|
|
|
|
|
|
return {
|
|
|
|
...urnParts,
|
|
|
|
platform: <DatasetPlatform>platform,
|
|
|
|
prefix,
|
|
|
|
fabric: isDatasetFabric(fabric) ? fabric : void 0
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
return urnParts;
|
|
|
|
};
|
|
|
|
|
2018-02-21 09:46:04 -08:00
|
|
|
/**
|
|
|
|
* Converts a WH URN format to a LI URN format
|
|
|
|
* @param {string} whUrn
|
|
|
|
* @return {string}
|
|
|
|
*/
|
|
|
|
const convertWhUrnToLiUrn = (whUrn: string): string => {
|
|
|
|
assert(`Expected ${whUrn} to be in the WH urn format`, isWhUrn(whUrn));
|
|
|
|
const [, platform, path] = datasetUrnRegexWH.exec(whUrn)!;
|
|
|
|
|
2018-03-08 10:21:01 -08:00
|
|
|
return buildLiUrn(<DatasetPlatform>platform, path);
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Takes a dataset platform, path, and fabric to produce an liUrn
|
|
|
|
* @param {DatasetPlatform} platform
|
|
|
|
* @param {string} path
|
|
|
|
* @param {Fabric} [fabric=Fabric.Prod]
|
|
|
|
* @return {string}
|
|
|
|
*/
|
2018-07-18 13:01:26 -07:00
|
|
|
const buildLiUrn = (platform: DatasetPlatform, path: string = '', fabric: Fabric = Fabric.Prod): string => {
|
2018-03-08 10:21:01 -08:00
|
|
|
const formattedPath = convertWhDatasetPathToLiPath(platform, path);
|
|
|
|
return `urn:li:dataset:(urn:li:dataPlatform:${platform},${formattedPath},${fabric})`;
|
2018-02-21 09:46:04 -08:00
|
|
|
};
|
|
|
|
|
2018-02-21 18:10:29 -08:00
|
|
|
/**
|
|
|
|
* Converts a path from WH urn format, replace forward slash with periods in non DatasetPlatform.HDFS cases,
|
|
|
|
* add leading forward slash if platform is DatasetPlatform.HDFS
|
|
|
|
* @param {DatasetPlatform} platform
|
|
|
|
* @param {string} path
|
|
|
|
* @return {string}
|
|
|
|
*/
|
2018-03-08 10:21:01 -08:00
|
|
|
const convertWhDatasetPathToLiPath = (platform: DatasetPlatform, path: string): string => {
|
|
|
|
if (String(platform).toLowerCase() === DatasetPlatform.HDFS) {
|
|
|
|
return path.charAt(0) === '/' ? path : `/${path}`;
|
|
|
|
}
|
|
|
|
|
|
|
|
return path.replace(/\//g, '.');
|
|
|
|
};
|
2018-02-21 18:10:29 -08:00
|
|
|
|
2018-02-21 09:46:04 -08:00
|
|
|
/**
|
|
|
|
* Cached RegExp object for a global search of /
|
|
|
|
* @type {RegExp}
|
|
|
|
*/
|
|
|
|
const encodedSlashRegExp = new RegExp(encodeURIComponent('/'), 'g');
|
|
|
|
/**
|
|
|
|
* Replaces any occurrence of / with the encoded equivalent
|
|
|
|
* @param {string} urn
|
|
|
|
* @return {string}
|
|
|
|
*/
|
|
|
|
const encodeForwardSlash = (urn: string): string => urn.replace(/\//g, encodeURIComponent('/'));
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Replaces encoded slashes with /
|
|
|
|
* @param {string} urn
|
|
|
|
* @return {string}
|
|
|
|
*/
|
|
|
|
const decodeForwardSlash = (urn: string): string => urn.replace(encodedSlashRegExp, decodeURIComponent('/'));
|
|
|
|
|
2018-04-23 12:08:49 -07:00
|
|
|
/**
|
|
|
|
* Stores the encoded URL for the asterisk/wildcard symbol since encodeURIComponent doesn't catch these
|
|
|
|
* as a reserved symbol
|
|
|
|
* @type {string}
|
|
|
|
*/
|
|
|
|
const encodedWildcard = '%2A';
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Cached RegExp object for a global search of /
|
|
|
|
* @type {RegExp}
|
|
|
|
*/
|
|
|
|
const encodedWildcardRegExp = new RegExp(encodedWildcard, 'g');
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Replaces any occurence of * with the encoded equivalent
|
|
|
|
* @param {string} urn
|
|
|
|
* @return {string}
|
|
|
|
*/
|
|
|
|
const encodeWildcard = (urn: string): string => urn.replace(/\*/g, encodedWildcard);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Replaces encoded slashes with /
|
|
|
|
* @param {string} urn
|
|
|
|
* @return {string}
|
|
|
|
*/
|
|
|
|
const decodeWildcard = (urn: string): string => urn.replace(encodedWildcardRegExp, decodeURIComponent('*'));
|
|
|
|
|
2018-02-21 09:46:04 -08:00
|
|
|
/**
|
|
|
|
* Replaces occurrences of / with the encoded counterpart in a urn string
|
|
|
|
* @param {string} urn
|
|
|
|
* @return {string}
|
|
|
|
*/
|
|
|
|
const encodeUrn = (urn: string): string => encodeForwardSlash(urn);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Replaces encoded occurrences of / with the string /
|
|
|
|
* @param {string} urn
|
|
|
|
* @return {string}
|
|
|
|
*/
|
|
|
|
const decodeUrn = (urn: string): string => decodeForwardSlash(urn);
|
|
|
|
|
2017-10-19 18:17:16 -07:00
|
|
|
export default isUrn;
|
|
|
|
|
2018-02-21 09:46:04 -08:00
|
|
|
export {
|
|
|
|
datasetUrnRegexWH,
|
|
|
|
datasetUrnRegexLI,
|
2018-05-02 09:45:26 -07:00
|
|
|
isValidCustomValuePattern,
|
2018-02-21 09:46:04 -08:00
|
|
|
isWhUrn,
|
|
|
|
isLiUrn,
|
2018-03-08 10:21:01 -08:00
|
|
|
buildLiUrn,
|
2018-02-21 09:46:04 -08:00
|
|
|
specialFlowUrnRegex,
|
|
|
|
getPlatformFromUrn,
|
2018-07-18 14:57:04 -07:00
|
|
|
getUrnParts,
|
2018-02-21 09:46:04 -08:00
|
|
|
convertWhUrnToLiUrn,
|
2018-02-21 19:20:20 -08:00
|
|
|
convertWhDatasetPathToLiPath,
|
2018-02-21 11:06:21 -08:00
|
|
|
encodeForwardSlash,
|
2018-04-23 12:08:49 -07:00
|
|
|
encodeWildcard,
|
|
|
|
decodeWildcard,
|
2018-02-21 09:46:04 -08:00
|
|
|
encodeUrn,
|
|
|
|
decodeUrn
|
|
|
|
};
|