Skip to content

Commit bf2edeb

Browse files
refactoring; removing duplicate code
1 parent 5e6cfd7 commit bf2edeb

File tree

2 files changed

+41
-14
lines changed

2 files changed

+41
-14
lines changed

src/helpers/Regex.ts

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ export const UUID_REGEX = new RegExp(UUID, "i");
66
export const EXTRACT_UUID_REGEX = new RegExp("^{?(" + UUID + ")}?$", "i");
77
export const EXTRACT_UUID_FROM_URL_REGEX = new RegExp("(" + UUID + ")\\)$", "i");
88
//global here is fine because the state is reset inside string.replace function
9-
export const REMOVE_BRACKETS_FROM_GUID_REGEX = new RegExp(`{(${UUID})}`, "g");
9+
export const REMOVE_BRACKETS_FROM_UUID_REGEX = new RegExp(`{(${UUID})}`, "g");
1010
export const ENTITY_UUID_REGEX = new RegExp(`\\/(\\w+)\\((${UUID})`, "i");
1111

1212
export function isUuid(value: string): boolean {
@@ -26,14 +26,21 @@ export function extractUuidFromUrl(url?: string): string | null {
2626
}
2727

2828
export function removeCurlyBracketsFromUuid(value: string): string {
29-
return value.replace(REMOVE_BRACKETS_FROM_GUID_REGEX, (_match, p1) => p1);
29+
return value.replace(REMOVE_BRACKETS_FROM_UUID_REGEX, (_match, p1) => p1);
3030
}
3131

32+
const QUOTATION_MARK_REGEX = /(["'].*?["'])/;
33+
34+
/**
35+
* Safely removes curly brackets from guids in a URL
36+
* @param url URL to remove curly brackets from
37+
* @returns URL with guid without curly brackets
38+
*/
3239
export function safelyRemoveCurlyBracketsFromUrl(url: string): string {
3340
//todo: in future I will need to replace this with a negative lookbehind and lookahead
3441

3542
// Split the filter string by quotation marks
36-
const parts = url.split(/(["'].*?["'])/);
43+
const parts = url.split(QUOTATION_MARK_REGEX);
3744
return parts
3845
.map((part, index) => {
3946
// Only process parts that are not within quotes
@@ -90,9 +97,25 @@ function sanitizeCookie(cookie: string): string {
9097
return cookie.replace(SPECIAL_CHARACTER_REGEX, (char) => characterMap[char]);
9198
}
9299

100+
const LEADING_SLASH_REGEX = /^\//;
101+
export function removeLeadingSlash(value: string): string {
102+
return value.replace(LEADING_SLASH_REGEX, "");
103+
}
104+
105+
const UNICODE_SYMBOLS_REGEX = /[\u007F-\uFFFF]/g;
106+
export function escapeUnicodeSymbols(value: string): string {
107+
return value.replace(UNICODE_SYMBOLS_REGEX, (chr: string) => `\\u${("0000" + chr.charCodeAt(0).toString(16)).slice(-4)}`);
108+
}
109+
110+
const DOUBLE_QUOTE_REGEX = /"/g;
111+
export function removeDoubleQuotes(value: string): string {
112+
return value.replace(DOUBLE_QUOTE_REGEX, "");
113+
}
114+
93115
export const BATCH_RESPONSE_HEADERS_REGEX = /^([^()<>@,;:\\"\/[\]?={} \t]+)\s?:\s?(.*)/;
94116
export const HTTP_STATUS_REGEX = /HTTP\/?\s*[\d.]*\s+(\d{3})\s+([\w\s]*)$/m;
95117
export const CONTENT_TYPE_PLAIN_REGEX = /Content-Type: text\/plain/i;
96118
export const ODATA_ENTITYID_REGEX = /OData-EntityId.+/i;
97119
export const TEXT_REGEX = /\w+$/g;
98120
export const LINE_ENDING_REGEX = /\r?\n/;
121+
export const SEARCH_FOR_ENTITY_NAME_REGEX = /(\w+)(\([\d\w-]+\))$/;

src/utils/Request.ts

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,14 @@ import { Utility } from "./Utility";
44
import { Config, HeaderCollection } from "../dynamics-web-api";
55
import { ErrorHelper } from "../helpers/ErrorHelper";
66
import { InternalConfig } from "./Config";
7-
import { safelyRemoveCurlyBracketsFromUrl } from "../helpers/Regex";
7+
import {
8+
removeCurlyBracketsFromUuid,
9+
removeLeadingSlash,
10+
escapeUnicodeSymbols,
11+
safelyRemoveCurlyBracketsFromUrl,
12+
SEARCH_FOR_ENTITY_NAME_REGEX,
13+
removeDoubleQuotes,
14+
} from "../helpers/Regex";
815

916
export let entityNames: Record<string, string | null> | null = null;
1017

@@ -339,9 +346,9 @@ export const composePreferHeader = (request: InternalRequest, config: Config): s
339346
if (trimmedItem === "return=representation") {
340347
returnRepresentation = true;
341348
} else if (trimmedItem.includes("odata.include-annotations=")) {
342-
includeAnnotations = trimmedItem.replace("odata.include-annotations=", "").replace(/"/g, "");
349+
includeAnnotations = removeDoubleQuotes(trimmedItem.replace("odata.include-annotations=", ""));
343350
} else if (trimmedItem.startsWith("odata.maxpagesize=")) {
344-
maxPageSize = Number(trimmedItem.replace("odata.maxpagesize=", "").replace(/"/g, "")) || 0;
351+
maxPageSize = Number(removeDoubleQuotes(trimmedItem.replace("odata.maxpagesize=", ""))) || 0;
345352
} else if (trimmedItem.includes("odata.track-changes")) {
346353
trackChanges = true;
347354
} else if (trimmedItem.includes("odata.continue-on-error")) {
@@ -491,15 +498,12 @@ export const processData = (data: any, config: InternalConfig): string | Uint8Ar
491498

492499
if (data instanceof Uint8Array || data instanceof Uint16Array || data instanceof Uint32Array) return data;
493500

494-
const replaceGuidBrackets = (value: string): string => value.replace(/(.+)\(\{([\w\d-]+)\}\)/g, "$1($2)");
495-
496501
const replaceEntityNameWithCollectionName = (value: string): string => {
497-
const regularExpression = /([\w_]+)(\([\d\w-]+\))$/;
498-
const valueParts = regularExpression.exec(value);
502+
const valueParts = SEARCH_FOR_ENTITY_NAME_REGEX.exec(value);
499503
if (valueParts && valueParts.length > 2) {
500504
const collectionName = findCollectionName(valueParts[1]);
501505
if (!Utility.isNull(collectionName)) {
502-
return value.replace(regularExpression, `${collectionName}$2`);
506+
return value.replace(SEARCH_FOR_ENTITY_NAME_REGEX, `${collectionName}$2`);
503507
}
504508
}
505509
return value;
@@ -512,7 +516,7 @@ export const processData = (data: any, config: InternalConfig): string | Uint8Ar
512516
value = `/${value}`;
513517
}
514518
} else {
515-
value = `${config.dataApi.url}${value.replace(/^\//, "")}`;
519+
value = `${config.dataApi.url}${removeLeadingSlash(value)}`;
516520
}
517521
}
518522
return value;
@@ -521,7 +525,7 @@ export const processData = (data: any, config: InternalConfig): string | Uint8Ar
521525
const stringifiedData = JSON.stringify(data, (key, value) => {
522526
if (key.endsWith("@odata.bind") || key.endsWith("@odata.id")) {
523527
if (typeof value === "string" && !value.startsWith("$")) {
524-
value = replaceGuidBrackets(value);
528+
value = removeCurlyBracketsFromUuid(value);
525529
if (config.useEntityNames) {
526530
value = replaceEntityNameWithCollectionName(value);
527531
}
@@ -533,7 +537,7 @@ export const processData = (data: any, config: InternalConfig): string | Uint8Ar
533537
return value;
534538
});
535539

536-
return stringifiedData.replace(/[\u007F-\uFFFF]/g, (chr: string) => `\\u${("0000" + chr.charCodeAt(0).toString(16)).slice(-4)}`);
540+
return escapeUnicodeSymbols(stringifiedData);
537541
};
538542

539543
export const setStandardHeaders = (headers: HeaderCollection = {}): HeaderCollection => {

0 commit comments

Comments
 (0)