UNPKG

9.17 kBJavaScriptView Raw
1import { OperationType } from "./constants";
2const trimLeftSlashes = new RegExp("^[/]+");
3const trimRightSlashes = new RegExp("[/]+$");
4const illegalResourceIdCharacters = new RegExp("[/\\\\?#]");
5const illegalItemResourceIdCharacters = new RegExp("[/\\\\#]");
6/** @hidden */
7export function jsonStringifyAndEscapeNonASCII(arg) {
8 // TODO: better way for this? Not sure.
9 // escapes non-ASCII characters as \uXXXX
10 return JSON.stringify(arg).replace(/[\u007F-\uFFFF]/g, (m) => {
11 return "\\u" + ("0000" + m.charCodeAt(0).toString(16)).slice(-4);
12 });
13}
14/**
15 * @hidden
16 */
17export function parseLink(resourcePath) {
18 if (resourcePath.length === 0) {
19 /* for DatabaseAccount case, both type and objectBody will be undefined. */
20 return {
21 type: undefined,
22 objectBody: undefined,
23 };
24 }
25 if (resourcePath[resourcePath.length - 1] !== "/") {
26 resourcePath = resourcePath + "/";
27 }
28 if (resourcePath[0] !== "/") {
29 resourcePath = "/" + resourcePath;
30 }
31 /*
32 The path will be in the form of /[resourceType]/[resourceId]/ ....
33 /[resourceType]//[resourceType]/[resourceId]/ .... /[resourceType]/[resourceId]/
34 or /[resourceType]/[resourceId]/ .... /[resourceType]/[resourceId]/[resourceType]/[resourceId]/ ....
35 /[resourceType]/[resourceId]/
36 The result of split will be in the form of
37 [[[resourceType], [resourceId] ... ,[resourceType], [resourceId], ""]
38 In the first case, to extract the resourceId it will the element before last ( at length -2 )
39 and the type will be before it ( at length -3 )
40 In the second case, to extract the resource type it will the element before last ( at length -2 )
41 */
42 const pathParts = resourcePath.split("/");
43 let id;
44 let type;
45 if (pathParts.length % 2 === 0) {
46 // request in form /[resourceType]/[resourceId]/ .... /[resourceType]/[resourceId].
47 id = pathParts[pathParts.length - 2];
48 type = pathParts[pathParts.length - 3];
49 }
50 else {
51 // request in form /[resourceType]/[resourceId]/ .... /[resourceType]/.
52 id = pathParts[pathParts.length - 3];
53 type = pathParts[pathParts.length - 2];
54 }
55 const result = {
56 type,
57 objectBody: {
58 id,
59 self: resourcePath,
60 },
61 };
62 return result;
63}
64/**
65 * @hidden
66 */
67export function isReadRequest(operationType) {
68 return operationType === OperationType.Read || operationType === OperationType.Query;
69}
70/**
71 * @hidden
72 */
73export function sleep(time) {
74 return new Promise((resolve) => {
75 setTimeout(() => {
76 resolve();
77 }, time);
78 });
79}
80/**
81 * @hidden
82 */
83export function getContainerLink(link) {
84 return link.split("/").slice(0, 4).join("/");
85}
86/**
87 * @hidden
88 */
89export function trimSlashes(source) {
90 return source.replace(trimLeftSlashes, "").replace(trimRightSlashes, "");
91}
92/**
93 * @hidden
94 */
95export function getHexaDigit() {
96 return Math.floor(Math.random() * 16).toString(16);
97}
98/**
99 * @hidden
100 */
101export function parsePath(path) {
102 const pathParts = [];
103 let currentIndex = 0;
104 const throwError = () => {
105 throw new Error("Path " + path + " is invalid at index " + currentIndex);
106 };
107 const getEscapedToken = () => {
108 const quote = path[currentIndex];
109 let newIndex = ++currentIndex;
110 for (;;) {
111 newIndex = path.indexOf(quote, newIndex);
112 if (newIndex === -1) {
113 throwError();
114 }
115 if (path[newIndex - 1] !== "\\") {
116 break;
117 }
118 ++newIndex;
119 }
120 const token = path.substr(currentIndex, newIndex - currentIndex);
121 currentIndex = newIndex + 1;
122 return token;
123 };
124 const getToken = () => {
125 const newIndex = path.indexOf("/", currentIndex);
126 let token = null;
127 if (newIndex === -1) {
128 token = path.substr(currentIndex);
129 currentIndex = path.length;
130 }
131 else {
132 token = path.substr(currentIndex, newIndex - currentIndex);
133 currentIndex = newIndex;
134 }
135 token = token.trim();
136 return token;
137 };
138 while (currentIndex < path.length) {
139 if (path[currentIndex] !== "/") {
140 throwError();
141 }
142 if (++currentIndex === path.length) {
143 break;
144 }
145 if (path[currentIndex] === '"' || path[currentIndex] === "'") {
146 pathParts.push(getEscapedToken());
147 }
148 else {
149 pathParts.push(getToken());
150 }
151 }
152 return pathParts;
153}
154/**
155 * @hidden
156 */
157export function isResourceValid(resource, err) {
158 // TODO: fix strictness issues so that caller contexts respects the types of the functions
159 if (resource.id) {
160 if (typeof resource.id !== "string") {
161 err.message = "Id must be a string.";
162 return false;
163 }
164 if (resource.id.indexOf("/") !== -1 ||
165 resource.id.indexOf("\\") !== -1 ||
166 resource.id.indexOf("?") !== -1 ||
167 resource.id.indexOf("#") !== -1) {
168 err.message = "Id contains illegal chars.";
169 return false;
170 }
171 if (resource.id[resource.id.length - 1] === " ") {
172 err.message = "Id ends with a space.";
173 return false;
174 }
175 }
176 return true;
177}
178/**
179 * @hidden
180 */
181export function isItemResourceValid(resource, err) {
182 // TODO: fix strictness issues so that caller contexts respects the types of the functions
183 if (resource.id) {
184 if (typeof resource.id !== "string") {
185 err.message = "Id must be a string.";
186 return false;
187 }
188 if (resource.id.indexOf("/") !== -1 ||
189 resource.id.indexOf("\\") !== -1 ||
190 resource.id.indexOf("#") !== -1) {
191 err.message = "Id contains illegal chars.";
192 return false;
193 }
194 }
195 return true;
196}
197/** @hidden */
198export function getIdFromLink(resourceLink) {
199 resourceLink = trimSlashes(resourceLink);
200 return resourceLink;
201}
202/** @hidden */
203export function getPathFromLink(resourceLink, resourceType) {
204 resourceLink = trimSlashes(resourceLink);
205 if (resourceType) {
206 return "/" + encodeURI(resourceLink) + "/" + resourceType;
207 }
208 else {
209 return "/" + encodeURI(resourceLink);
210 }
211}
212/**
213 * @hidden
214 */
215export function isStringNullOrEmpty(inputString) {
216 // checks whether string is null, undefined, empty or only contains space
217 return !inputString || /^\s*$/.test(inputString);
218}
219/**
220 * @hidden
221 */
222export function trimSlashFromLeftAndRight(inputString) {
223 if (typeof inputString !== "string") {
224 throw new Error("invalid input: input is not string");
225 }
226 return inputString.replace(trimLeftSlashes, "").replace(trimRightSlashes, "");
227}
228/**
229 * @hidden
230 */
231export function validateResourceId(resourceId) {
232 // if resourceId is not a string or is empty throw an error
233 if (typeof resourceId !== "string" || isStringNullOrEmpty(resourceId)) {
234 throw new Error("Resource ID must be a string and cannot be undefined, null or empty");
235 }
236 // if resource id contains illegal characters throw an error
237 if (illegalResourceIdCharacters.test(resourceId)) {
238 throw new Error("Illegal characters ['/', '\\', '#', '?'] cannot be used in Resource ID");
239 }
240 return true;
241}
242/**
243 * @hidden
244 */
245export function validateItemResourceId(resourceId) {
246 // if resourceId is not a string or is empty throw an error
247 if (typeof resourceId !== "string" || isStringNullOrEmpty(resourceId)) {
248 throw new Error("Resource ID must be a string and cannot be undefined, null or empty");
249 }
250 // if resource id contains illegal characters throw an error
251 if (illegalItemResourceIdCharacters.test(resourceId)) {
252 throw new Error("Illegal characters ['/', '\\', '#'] cannot be used in Resource ID");
253 }
254 return true;
255}
256/**
257 * @hidden
258 */
259export function getResourceIdFromPath(resourcePath) {
260 if (!resourcePath || typeof resourcePath !== "string") {
261 return null;
262 }
263 const trimmedPath = trimSlashFromLeftAndRight(resourcePath);
264 const pathSegments = trimmedPath.split("/");
265 // number of segments of a path must always be even
266 if (pathSegments.length % 2 !== 0) {
267 return null;
268 }
269 return pathSegments[pathSegments.length - 1];
270}
271/**
272 * @hidden
273 */
274export function parseConnectionString(connectionString) {
275 const keyValueStrings = connectionString.split(";");
276 const { AccountEndpoint, AccountKey } = keyValueStrings.reduce((connectionObject, keyValueString) => {
277 const [key, ...value] = keyValueString.split("=");
278 connectionObject[key] = value.join("=");
279 return connectionObject;
280 }, {});
281 if (!AccountEndpoint || !AccountKey) {
282 throw new Error("Could not parse the provided connection string");
283 }
284 return {
285 endpoint: AccountEndpoint,
286 key: AccountKey,
287 };
288}
289//# sourceMappingURL=helper.js.map
\No newline at end of file