1 | import { diffChars } from 'diff';
|
2 | import * as _ from 'lodash';
|
3 | import { Log, Level } from 'ng2-logger/browser';
|
4 | import { Helpers } from './helpers';
|
5 | const log = Log.create('ng2-rest params', Level.__NOTHING);
|
6 |
|
7 | export function isValid(pattern) {
|
8 | return (new RegExp('\/:[a-zA-Z]*', 'g')).test(pattern.replace('://', ''));
|
9 | }
|
10 | export function check(url, pattern) {
|
11 | if (!Helpers.checkValidUrl(url)) {
|
12 | console.error(`[ng2-rest] Incorrect url: ${url}`);
|
13 | return false;
|
14 | }
|
15 | if (url.charAt(url.length - 1) === '/')
|
16 | url = url.slice(0, url.length - 2);
|
17 | if (pattern.charAt(pattern.length - 1) === '/')
|
18 | pattern = pattern.slice(0, url.length - 2);
|
19 | pattern = pattern.replace(/\//g, '\/');
|
20 | pattern = pattern.replace(new RegExp('\/:[a-zA-Z]*', 'g'), '.+');
|
21 | let reg = new RegExp(pattern, 'g');
|
22 | return reg.test(url);
|
23 | }
|
24 | export function getModels(pattern) {
|
25 | let m = pattern.match(new RegExp('[a-z-A-Z]*\/:', 'g'));
|
26 | return m.map(p => p.replace('/:', ''));
|
27 | }
|
28 | export function getRestPramsNames(pattern) {
|
29 | if (pattern.charAt(pattern.length - 1) !== '/')
|
30 | pattern = `${pattern}/`;
|
31 | let m = pattern.match(new RegExp(':[a-zA-Z]*\/', 'g'));
|
32 | let res = m.map(p => p.replace(':', '').replace('/', ''));
|
33 | return res.filter(p => p.trim() !== '');
|
34 | }
|
35 | export function containsModels(url, models) {
|
36 | if (url.charAt(0) !== '/')
|
37 | url = '/' + url;
|
38 |
|
39 | let res = models.filter(m => {
|
40 | let word = '/' + m;
|
41 | log.d('word', word);
|
42 | let iii = url.indexOf(word);
|
43 | log.d('iii', iii);
|
44 | if (iii + word.length < url.length && url.charAt(iii + word.length) !== '/') {
|
45 | return false;
|
46 | }
|
47 | if (iii !== -1) {
|
48 | url = url.replace(new RegExp('\/' + m, 'g'), '');
|
49 | return true;
|
50 | }
|
51 | return false;
|
52 | }).length;
|
53 | log.d('containsModels', res);
|
54 | return res === models.length;
|
55 | }
|
56 | export function stars(n) {
|
57 | let res = '';
|
58 | for (let i = 0; i < n; i++)
|
59 | res += '*';
|
60 | return res;
|
61 | }
|
62 | export function getRestParams(url, pattern) {
|
63 | let res = {};
|
64 | let models = getRestPramsNames(pattern);
|
65 | log.d('models', models);
|
66 | models.forEach(m => {
|
67 | pattern = pattern.replace(`:${m}`, stars(m.length));
|
68 | });
|
69 | let currentModel = undefined;
|
70 | diffChars(pattern, url).forEach(d => {
|
71 | log.d('d', d);
|
72 | if (d.added) {
|
73 | if (!isNaN(Number(d.value)))
|
74 | res[currentModel] = Number(d.value);
|
75 | else if (d.value.trim() === 'true')
|
76 | res[currentModel] = true;
|
77 | else if (d.value.trim() === 'false')
|
78 | res[currentModel] = false;
|
79 | else
|
80 | res[currentModel] = decodeURIComponent(d.value);
|
81 | currentModel = undefined;
|
82 | }
|
83 | let m = d.value.replace(':', "");
|
84 | log.d('model m', m);
|
85 | if (d.removed) {
|
86 | currentModel = models.shift();
|
87 | }
|
88 | });
|
89 | return res;
|
90 | }
|
91 | export const regexisPath = /[^\..]+(\.[^\..]+)+/g;
|
92 |
|
93 |
|
94 |
|
95 | function cutUrlModel(params, models, output) {
|
96 | if (models.length === 0)
|
97 | return output.join('\/');
|
98 | let m = models.pop();
|
99 | let param = m.match(/:[a-zA-Z0-9\.]+/)[0].replace(':', '');
|
100 | const paramIsPath = regexisPath.test(param);
|
101 | log.i('cut param', param);
|
102 | let model = m.match(/[a-zA-Z0-9]+\//)[0].replace('\/', '');
|
103 | if (params === undefined ||
|
104 | (paramIsPath ? _.get(params, param) === undefined : params[param] === undefined) ||
|
105 | param === 'undefined') {
|
106 | output.length = 0;
|
107 | output.unshift(model);
|
108 | return cutUrlModel(params, models, output);
|
109 | }
|
110 | else {
|
111 | if (paramIsPath) {
|
112 | log.i('param is path', param);
|
113 | let mrep = m.replace(new RegExp(`:${param}`, 'g'), `${_.get(params, param)}`);
|
114 | output.unshift(mrep);
|
115 | return cutUrlModel(params, models, output);
|
116 | }
|
117 | else {
|
118 | log.i('param is normal', param);
|
119 | let mrep = m.replace(new RegExp(`:${param}`, 'g'), `${params[param]}`);
|
120 | output.unshift(mrep);
|
121 | return cutUrlModel(params, models, output);
|
122 | }
|
123 | }
|
124 | }
|
125 | export function interpolateParamsToUrl(params, url) {
|
126 | const regexInt = /\[\[([^\..]+\.[^\..]+)+\]\]/g;
|
127 | url = url.split('/').map(p => {
|
128 |
|
129 | let isParam = p.startsWith(':');
|
130 | if (isParam) {
|
131 | let part = p.slice(1);
|
132 |
|
133 | if (regexInt.test(part)) {
|
134 |
|
135 | part = part.replace('[[', '');
|
136 | part = part.replace(']]', '');
|
137 | }
|
138 | return `:${part}`;
|
139 | }
|
140 | return p;
|
141 | }).join('/');
|
142 |
|
143 |
|
144 | let slash = {
|
145 | start: url.charAt(0) === '\/',
|
146 | end: url.charAt(url.length - 1) === '\/'
|
147 | };
|
148 | let morePramsOnEnd = url.match(/(\/:[a-zA-Z0-9\.]+){2,10}/g);
|
149 | if (morePramsOnEnd && (Array.isArray(morePramsOnEnd) && morePramsOnEnd.length === 1)) {
|
150 |
|
151 | let m = morePramsOnEnd[0];
|
152 | let match = m.match(/\/:[a-zA-Z0-9\.]+/g);
|
153 |
|
154 | match.forEach(e => {
|
155 | let c = e.replace('\/:', '');
|
156 |
|
157 | if (regexisPath.test(c)) {
|
158 | url = url.replace(e, `/${_.get(params, c)}`);
|
159 | }
|
160 | else {
|
161 | url = url.replace(e, `/${params[c]}`);
|
162 | }
|
163 |
|
164 | });
|
165 | return url;
|
166 | }
|
167 | let nestedParams = url.match(/[a-zA-Z0-9]+\/:[a-zA-Z0-9\.]+/g);
|
168 | if (!nestedParams || (Array.isArray(nestedParams) && nestedParams.length === 0))
|
169 | return url;
|
170 |
|
171 | if (!slash.end)
|
172 | url = `${url}/`;
|
173 | let addUndefinedForAlone = (!/:[a-zA-Z0-9\.]+\/$/g.test(url) && /[a-zA-Z0-9]+\/$/g.test(url));
|
174 | let replace = (nestedParams.length > 1 ? nestedParams.join('\/') : nestedParams[0]) +
|
175 | (addUndefinedForAlone ? '\/' + url.match(/[a-zA-Z0-9]+\/$/g)[0] : '\/');
|
176 | let beginHref = url.replace(replace, '');
|
177 | if (addUndefinedForAlone) {
|
178 | url = url.replace(/\/$/g, '/:undefined');
|
179 | nestedParams = url.match(/[a-zA-Z0-9]+\/:[a-zA-Z0-9\.]+/g);
|
180 | url = cutUrlModel(params, nestedParams, []);
|
181 | }
|
182 | else {
|
183 | url = cutUrlModel(params, nestedParams, []);
|
184 | }
|
185 | url = beginHref + url;
|
186 | if (url.charAt(url.length - 1) !== '/' && slash.end)
|
187 | url = `${url}/`;
|
188 | if (url.charAt(0) !== '\/' && slash.start)
|
189 | url = `/${url}`;
|
190 | return url;
|
191 | }
|
192 |
|
193 |
|
194 |
|
195 | export function decodeUrl(url) {
|
196 | let regex = /[?&]([^=#]+)=([^&#]*)/g, params = {}, match;
|
197 | while (match = regex.exec(url)) {
|
198 | params[decodeURIComponent(match[1])] = decodeURIComponent(match[2]);
|
199 | }
|
200 | let paramsObject = params;
|
201 | for (let p in paramsObject) {
|
202 | if (paramsObject[p] === undefined) {
|
203 | delete paramsObject[p];
|
204 | continue;
|
205 | }
|
206 | if (paramsObject.hasOwnProperty(p)) {
|
207 |
|
208 | let n = Number(params[p]);
|
209 | if (!isNaN(n)) {
|
210 | params[p] = n;
|
211 | continue;
|
212 | }
|
213 | if (typeof params[p] === 'string') {
|
214 |
|
215 | let json;
|
216 | try {
|
217 | json = JSON.parse(params[p]);
|
218 | }
|
219 | catch (error) { }
|
220 | if (json !== undefined) {
|
221 | params[p] = json;
|
222 | continue;
|
223 | }
|
224 |
|
225 |
|
226 |
|
227 |
|
228 |
|
229 |
|
230 | }
|
231 | }
|
232 | }
|
233 | return params;
|
234 | }
|
235 |
|
236 |
|
237 |
|
238 |
|
239 |
|
240 |
|
241 |
|
242 | export function getParamsUrl(params, doNotSerialize = false) {
|
243 | let urlparts = [];
|
244 | if (!params)
|
245 | return '';
|
246 | if (!(params instanceof Array))
|
247 | return '';
|
248 | if (params.length === 0)
|
249 | return '';
|
250 | params.forEach(urlparam => {
|
251 | if (JSON.stringify(urlparam) !== '{}') {
|
252 | let parameters = [];
|
253 | let paramObject = urlparam;
|
254 | for (let p in paramObject) {
|
255 | if (paramObject[p] === undefined)
|
256 | delete paramObject[p];
|
257 | if (paramObject.hasOwnProperty(p) && typeof p === 'string' && p !== 'regex' && !(paramObject[p] instanceof RegExp)) {
|
258 | if (p.length > 0 && p[0] === '/') {
|
259 | let newName = p.slice(1, p.length - 1);
|
260 | urlparam[newName] = urlparam[p];
|
261 | urlparam[p] = undefined;
|
262 | p = newName;
|
263 | }
|
264 | if (p.length > 0 && p[p.length - 1] === '/') {
|
265 | let newName = p.slice(0, p.length - 2);
|
266 | urlparam[newName] = urlparam[p];
|
267 | urlparam[p] = undefined;
|
268 | p = newName;
|
269 | }
|
270 | let v = urlparam[p];
|
271 | if (v instanceof Object) {
|
272 | urlparam[p] = JSON.stringify(urlparam[p]);
|
273 | }
|
274 | urlparam[p] = doNotSerialize ? urlparam[p] : encodeURIComponent(urlparam[p]);
|
275 | if (urlparam.regex !== undefined && urlparam.regex instanceof RegExp) {
|
276 | if (!urlparam.regex.test(urlparam[p])) {
|
277 | console.warn(`Data: ${urlparam[p]} incostistent with regex ${urlparam.regex.source}`);
|
278 | }
|
279 | }
|
280 | parameters.push(`${p}=${urlparam[p]}`);
|
281 | }
|
282 | }
|
283 | urlparts.push(parameters.join('&'));
|
284 | }
|
285 | });
|
286 | let join = urlparts.join().trim();
|
287 | if (join.trim() === '')
|
288 | return '';
|
289 | return `?${urlparts.join('&')}`;
|
290 | }
|
291 | function transform(o) {
|
292 | if (typeof o === 'object') {
|
293 | return encodeURIComponent(JSON.stringify(o));
|
294 | }
|
295 | return o;
|
296 | }
|
297 | export function prepareUrlOldWay(params) {
|
298 | if (!params)
|
299 | return this.endpoint;
|
300 | if (typeof params === 'object') {
|
301 | params = transform(params);
|
302 | }
|
303 | return this.endpoint + '/' + params;
|
304 | }
|
305 |
|
\ | No newline at end of file |