All files / src ODataHelper.ts

100% Statements 55/55
100% Branches 51/51
100% Functions 11/11
100% Lines 52/52
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129                          1x 1x   1x   34x 68x 3x     68x 34x                       1x   63x 27x     36x 2x   34x   36x 36x 36x 36x   36x   36x 198x 198x 198x 198x 200x   198x 107x       107x               1x 44x 1x   43x 2x     41x 41x 41x     41x 16x   25x   41x             1x 106x             1x 45x             1x 407x 823x 3x   823x 245x   823x     407x    
/**
 * @module ODataHelper
 * @preferred
 *
 * @description Helper methods for OData Operations
 */ /** */
 
// TODO: ezeket vhova kivezetni
import { SnConfigModel } from './Config/snconfigmodel';
import { IContent } from './Content';
import { IODataParams, ODataFieldParameter } from './ODataApi';
import { Content } from './SN';
 
const ODATA_PARAMS = ['select', 'expand', 'orderby', 'top', 'skip', 'filter', 'format', 'inlinecount'];
export const DATA_ROOT = 'OData.svc';
 
export const combineODataFieldParameters: <T extends IContent>(...params: ODataFieldParameter<T>[]) => ODataFieldParameter<Content<T>>
    = <T extends IContent>(...params: ODataFieldParameter<T>[]) => {
        params.forEach((param) => {
            if (typeof param === 'string') {
                param = [param];
            }
        });
        params = params.filter((param) => param && param.length > 0);
        return [...new Set([].concat.apply([], params))] as ODataFieldParameter<T>;
    };
 
/**
 * Method to build proper parameter string to OData requests based on the given option Object.
 *
 * Checks whether a given parameter is standard OData param or not and based on this information this params get the '$' sign.
 *
 * If there's no select param given, or it is empty 'Id' is the default, so only this field will be on the content in the JSON result. To get all the field values, without selection, set it to 'all', but please avoid this if it's possible.
 * @param {IODataOptions} options Represents an ODataOptions obejct based through the IODataOptions interface. Holds the possible url parameters as properties.
 * @returns {string} String with the url params in the correct format e.g. '$select=DisplayName,Index'&$top=2&metadata=no'.
 */
export const buildUrlParamString: <T extends IContent = IContent>(config: SnConfigModel, options?: IODataParams<T>) => string =
    <T extends IContent>(config: SnConfigModel, options?: IODataParams<T>): string => {
        if (!options) {
            return '';
        }
 
        if (config.RequiredSelect === 'all' || config.DefaultSelect === 'all' || options.select === 'all') {
            options.select = undefined;
        } else {
            options.select = combineODataFieldParameters<any>(config.RequiredSelect, options.select || config.DefaultSelect) as any;
        }
        options.metadata = options.metadata || config.DefaultMetadata;
        options.inlinecount = options.inlinecount || config.DefaultInlineCount;
        options.expand = options.expand || config.DefaultExpand as any;
        options.top = options.top || config.DefaultTop;
 
        const segments: { name: string, value: string }[] = [];
        // tslint:disable-next-line:forin
        for (const key in options) {
            const name = ODATA_PARAMS.indexOf(key) > -1 ? `$${key}` : key;
            const plainValue = (options as any)[key];
            let parsedValue = plainValue;
            if (plainValue instanceof Array && plainValue.length && plainValue.length > 0) {
                parsedValue = plainValue.map((v) => v.join && v.join(' ') || v).join(',');
            }
            if (name && parsedValue && parsedValue.length) {
                segments.push({ name, value: parsedValue });
            }
        }
 
        return segments.map((s) => `${s.name}=${s.value}`).join('&');
    };
 
/**
 * Method that gets the URL that refers to a single item in the Sense/Net Content Repository
 * @param path {string} Path that you want to format.
 * @returns {string} Path in entity format e.g. /workspaces('project') from /workspaces/project
 */
export const getContentURLbyPath: (path: string) => string = (path: string): string => {
    if (typeof path === 'undefined' || path.indexOf('/') < 0 || path.length <= 1) {
        throw new Error('This is not a valid path.');
    }
    if (isItemPath(path)) {
        return path;
    }
 
    const lastSlashPosition = path.lastIndexOf('/');
    const name = path.substring(lastSlashPosition + 1);
    const parentPath = path.substring(0, lastSlashPosition);
 
    let url;
    if (name.indexOf('Root') > -1) {
        url = `${parentPath}/('${name}')`;
    } else {
        url = `${parentPath}('${name}')`;
    }
    return url;
};
/**
 * Method that gets the URL that refers to a single item in the Sense/Net Content Repository by its Id
 * @param id {number} Id of the Content.
 * @returns {string} e.g. /content(123)
 */
export const getContentUrlbyId: (id: number) => string = (id: number) => {
    return `/content(${id})`;
};
/**
 * Method that tells if a path is an item path.
 * @param path {string} Path that you want to test.
 * @returns {boolean} Returns if the given path is a path of a Content or not.
 */
export const isItemPath: (path: string) => boolean = (path) => {
    return path.indexOf("('") >= 0 && path.indexOf("')") === path.length - 2;
};
 
/**
 * Method that allows to join paths without multiple or missing slashes
 * @param args The list of the paths to join
 */
export const joinPaths = (...args: string[]) => {
    const trimSlashes = (path: string) => {
        if (path.endsWith('/')) {
            path = path.substring(0, path.length - 1);
        }
        if (path.startsWith('/')) {
            path = path.substring(1, path.length);
        }
        return path;
    };
 
    return args.map(trimSlashes).join('/');
};