@uniformdev/redirect 19.27.0 → 19.29.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +3 -0
- package/dist/index.esm.js +101 -42
- package/dist/index.js +101 -42
- package/dist/index.mjs +101 -42
- package/package.json +3 -3
package/dist/index.d.ts
CHANGED
|
@@ -98,6 +98,8 @@ declare class RedirectClient extends ApiClient<RedirectClientOptions> {
|
|
|
98
98
|
static processUrlBestMatch: (url: string, trie: PathTrie<DirectionAwareRedirectDefinition>, options?: RedirectOptions) => Promise<RedirectResult | undefined>;
|
|
99
99
|
processUrlBestMatch: (url: string, options?: RedirectOptions) => Promise<RedirectResult | undefined>;
|
|
100
100
|
processUrlAllMatches: (url: string, options?: RedirectOptions) => Promise<RedirectResult[]>;
|
|
101
|
+
private static assembling;
|
|
102
|
+
private static assemblingPromise;
|
|
101
103
|
private assembleTrie;
|
|
102
104
|
private static processHops;
|
|
103
105
|
private static processHop;
|
|
@@ -391,6 +393,7 @@ type RedirectClientGetRedirect = Pick<RedirectClientGetRequest, 'id' | 'projectM
|
|
|
391
393
|
type RedirectClientGetRedirects = Pick<RedirectClientGetRequest, 'ids' | 'limit' | 'offset' | 'orderBy' | 'search'>;
|
|
392
394
|
|
|
393
395
|
declare class WithMemoryCache extends RedirectClientCache<RedirectClientCacheOptions> {
|
|
396
|
+
private static refresher?;
|
|
394
397
|
constructor(options: RedirectClientCacheOptions);
|
|
395
398
|
private static trieCache;
|
|
396
399
|
get(key: string): Promise<PathTrie<DirectionAwareRedirectDefinition>> | undefined;
|
package/dist/index.esm.js
CHANGED
|
@@ -1,5 +1,43 @@
|
|
|
1
1
|
import "./chunk-FFYIGW52.mjs";
|
|
2
2
|
|
|
3
|
+
// src/cache/data/refresher.ts
|
|
4
|
+
var Refresher = class {
|
|
5
|
+
/**
|
|
6
|
+
* Create new refresher
|
|
7
|
+
* @param refreshRate - How often the refresher will refresh. Cannot be less than 20000 ms or 20 seconds
|
|
8
|
+
* @param refreshDuration - How many times it should refresh before sleeps until something accesses the cache. Cannot be more than 5
|
|
9
|
+
* @param refresh - Refresh method to run at the refresh rate intervals
|
|
10
|
+
*/
|
|
11
|
+
constructor({ refreshRate, refreshDuration, refresh }) {
|
|
12
|
+
this.refreshCounter = 0;
|
|
13
|
+
this.finalRate = refreshRate >= 2e4 ? refreshRate : 2e4;
|
|
14
|
+
this.finalDuration = refreshDuration <= 5 ? refreshDuration : 5;
|
|
15
|
+
this.refreshCounter = 1;
|
|
16
|
+
this.refresh = refresh;
|
|
17
|
+
this.start();
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Start async updating process again, will run for the same duration as the original. refreshRate * refreshDuration milliseconds
|
|
21
|
+
*/
|
|
22
|
+
kick() {
|
|
23
|
+
if (this.refreshCounter === 0) {
|
|
24
|
+
this.start();
|
|
25
|
+
}
|
|
26
|
+
this.refreshCounter = 1;
|
|
27
|
+
}
|
|
28
|
+
start() {
|
|
29
|
+
this.interval = setTimeout(async () => {
|
|
30
|
+
if (this.refreshCounter > this.finalDuration) {
|
|
31
|
+
this.refreshCounter = 0;
|
|
32
|
+
} else {
|
|
33
|
+
await this.refresh();
|
|
34
|
+
this.refreshCounter++;
|
|
35
|
+
this.start();
|
|
36
|
+
}
|
|
37
|
+
}, this.finalRate);
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
|
|
3
41
|
// src/cache/redirectClientCache.ts
|
|
4
42
|
var RedirectClientCache = class {
|
|
5
43
|
constructor(options) {
|
|
@@ -11,11 +49,19 @@ var RedirectClientCache = class {
|
|
|
11
49
|
var _WithMemoryCache = class extends RedirectClientCache {
|
|
12
50
|
constructor(options) {
|
|
13
51
|
super(options);
|
|
52
|
+
if (options.refreshRate && !_WithMemoryCache.refresher) {
|
|
53
|
+
_WithMemoryCache.refresher = new Refresher({
|
|
54
|
+
refreshRate: options.refreshRate,
|
|
55
|
+
refreshDuration: 5,
|
|
56
|
+
refresh: this.refresh
|
|
57
|
+
});
|
|
58
|
+
}
|
|
14
59
|
}
|
|
15
60
|
/* Get data from the cache and debounce pausing refresh */
|
|
16
61
|
get(key) {
|
|
17
|
-
var _a, _b;
|
|
18
|
-
|
|
62
|
+
var _a, _b, _c;
|
|
63
|
+
(_a = _WithMemoryCache.refresher) == null ? void 0 : _a.kick();
|
|
64
|
+
return (_c = (_b = _WithMemoryCache.trieCache[key]) == null ? void 0 : _b.data) != null ? _c : void 0;
|
|
19
65
|
}
|
|
20
66
|
/* Set new data to the cache and reset the refresh method */
|
|
21
67
|
set(key, data, refresh) {
|
|
@@ -39,13 +85,15 @@ var _WithMemoryCache = class extends RedirectClientCache {
|
|
|
39
85
|
}
|
|
40
86
|
refresh() {
|
|
41
87
|
var _a, _b;
|
|
88
|
+
const caches = [];
|
|
42
89
|
for (const key in _WithMemoryCache.trieCache) {
|
|
43
90
|
const p = (_b = (_a = _WithMemoryCache.trieCache[key]) == null ? void 0 : _a.refresh) == null ? void 0 : _b.call(_a);
|
|
44
91
|
if (p) {
|
|
45
92
|
_WithMemoryCache.trieCache[key] = { ..._WithMemoryCache.trieCache[key], data: p };
|
|
93
|
+
caches.push(p.then());
|
|
46
94
|
}
|
|
47
95
|
}
|
|
48
|
-
return Promise.all(
|
|
96
|
+
return Promise.all(caches);
|
|
49
97
|
}
|
|
50
98
|
};
|
|
51
99
|
var WithMemoryCache = _WithMemoryCache;
|
|
@@ -130,7 +178,7 @@ var PathTrie = class {
|
|
|
130
178
|
}
|
|
131
179
|
return result;
|
|
132
180
|
};
|
|
133
|
-
const scanWildcards = () => {
|
|
181
|
+
const scanWildcards = (i) => {
|
|
134
182
|
let wildcard = void 0;
|
|
135
183
|
while ((!wildcard || wildcard.active) && wildcards.length) {
|
|
136
184
|
wildcard = wildcards.pop();
|
|
@@ -140,6 +188,11 @@ var PathTrie = class {
|
|
|
140
188
|
wildcard.active = true;
|
|
141
189
|
cur = wildcard == null ? void 0 : wildcard.startTrie;
|
|
142
190
|
wildcards.push(wildcard);
|
|
191
|
+
if (i === segments.length - 1 && wildcards.length && wildcards[wildcards.length - 1].active && wildcards[wildcards.length - 1].startTrie[dataProp]) {
|
|
192
|
+
wildcards[wildcards.length - 1].startTrie[dataProp].forEach(
|
|
193
|
+
(d) => ret.push({ data: d, variables: getVariables() })
|
|
194
|
+
);
|
|
195
|
+
}
|
|
143
196
|
return wildcard == null ? void 0 : wildcard.start;
|
|
144
197
|
};
|
|
145
198
|
for (let i = 0; i < segments.length; i++) {
|
|
@@ -168,21 +221,22 @@ var PathTrie = class {
|
|
|
168
221
|
if (i === segments.length - 1) {
|
|
169
222
|
if (cur[dataProp]) {
|
|
170
223
|
cur[dataProp].forEach((d) => ret.push({ data: d, variables: getVariables() }));
|
|
224
|
+
} else {
|
|
225
|
+
const more = scanWildcards(i);
|
|
226
|
+
if (typeof more === "undefined" || ret.length > 0 && bestMatch)
|
|
227
|
+
return [...ret, ...splats];
|
|
228
|
+
i = more;
|
|
171
229
|
}
|
|
172
230
|
}
|
|
173
|
-
} else
|
|
174
|
-
const more = scanWildcards();
|
|
175
|
-
if (typeof more === "undefined")
|
|
231
|
+
} else {
|
|
232
|
+
const more = scanWildcards(i);
|
|
233
|
+
if (typeof more === "undefined" || ret.length > 0 && bestMatch)
|
|
176
234
|
return [...ret, ...splats];
|
|
177
235
|
i = more;
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
}
|
|
183
|
-
} else {
|
|
184
|
-
const more = scanWildcards();
|
|
185
|
-
if (typeof more === "undefined")
|
|
236
|
+
}
|
|
237
|
+
if (i === segments.length - 1 && wildcards.length !== 0) {
|
|
238
|
+
const more = scanWildcards(i);
|
|
239
|
+
if (typeof more === "undefined" || ret.length > 0 && bestMatch)
|
|
186
240
|
return [...ret, ...splats];
|
|
187
241
|
i = more;
|
|
188
242
|
}
|
|
@@ -342,22 +396,29 @@ var _RedirectClient = class extends ApiClient {
|
|
|
342
396
|
}
|
|
343
397
|
}
|
|
344
398
|
async assembleTrie() {
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
399
|
+
if (!_RedirectClient.assembling) {
|
|
400
|
+
_RedirectClient.assembling = true;
|
|
401
|
+
_RedirectClient.assemblingPromise = (async () => {
|
|
402
|
+
const trie = new PathTrie();
|
|
403
|
+
for await (const redirect of this.getAllRedirects()) {
|
|
404
|
+
const source = processUrl(redirect.redirect.sourceUrl);
|
|
405
|
+
const target = processUrl(redirect.redirect.targetUrl);
|
|
406
|
+
trie.insert(source.path, {
|
|
407
|
+
redirect: redirect.redirect,
|
|
408
|
+
metadata: redirect.metadata,
|
|
409
|
+
reverse: false
|
|
410
|
+
});
|
|
411
|
+
trie.insert(target.path, {
|
|
412
|
+
redirect: redirect.redirect,
|
|
413
|
+
metadata: redirect.metadata,
|
|
414
|
+
reverse: true
|
|
415
|
+
});
|
|
416
|
+
}
|
|
417
|
+
_RedirectClient.assembling = false;
|
|
418
|
+
return trie;
|
|
419
|
+
})();
|
|
359
420
|
}
|
|
360
|
-
return
|
|
421
|
+
return await _RedirectClient.assemblingPromise;
|
|
361
422
|
}
|
|
362
423
|
static processHops(url, trie, bestMatch, options) {
|
|
363
424
|
var _a;
|
|
@@ -429,20 +490,14 @@ var _RedirectClient = class extends ApiClient {
|
|
|
429
490
|
* @param options - Different options available to the redirect engine
|
|
430
491
|
*/
|
|
431
492
|
static processDefinitionToResults(processedUrl, definition, variables, options) {
|
|
432
|
-
var _a, _b, _c, _d, _e;
|
|
433
493
|
const resultUrl = (options == null ? void 0 : options.reverse) ? definition.redirect.sourceUrl : definition.redirect.targetUrl;
|
|
434
494
|
const processedResult = processUrl(resultUrl);
|
|
435
495
|
const redirect = definition == null ? void 0 : definition.redirect;
|
|
436
496
|
if (redirect.sourceMustMatchDomain && processedUrl.domain !== processedResult.domain)
|
|
437
497
|
return void 0;
|
|
438
|
-
const
|
|
439
|
-
const domain = redirect.targetPreserveIncomingDomain ? processedUrl.domain : (_d = (_c = processedResult.domain) != null ? _c : processedUrl.domain) != null ? _d : "";
|
|
440
|
-
const queryString = redirect.sourceRetainQuerystring && processedResult.query ? (_e = processedResult.query) != null ? _e : "" : definition.redirect.sourceRetainQuerystring ? processedUrl.query : "";
|
|
441
|
-
const finalUrl = `${protocol}${domain}${processedResult.port}${processedResult.path}${queryString}`;
|
|
498
|
+
const finalUrl = _RedirectClient.getTargetVariableExpandedUrl(processedUrl.url, redirect);
|
|
442
499
|
return {
|
|
443
|
-
url:
|
|
444
|
-
return cur.replace(o.key, o.value);
|
|
445
|
-
}, finalUrl),
|
|
500
|
+
url: finalUrl,
|
|
446
501
|
definition,
|
|
447
502
|
label: (options == null ? void 0 : options.label) ? variables.reduce((cur, o) => {
|
|
448
503
|
return cur.replace(o.key, `<em>${o.value}</em>`);
|
|
@@ -477,7 +532,7 @@ var _RedirectClient = class extends ApiClient {
|
|
|
477
532
|
}
|
|
478
533
|
const protocol = redirectDefinition.targetPreserveIncomingProtocol ? processedUrl.protocol : processedTarget.protocol;
|
|
479
534
|
const domain = redirectDefinition.targetPreserveIncomingDomain ? processedUrl.domain : processedTarget.domain;
|
|
480
|
-
const port = processedTarget.port;
|
|
535
|
+
const port = redirectDefinition.targetPreserveIncomingDomain ? processedUrl.port : processedTarget.port;
|
|
481
536
|
const query = redirectDefinition.sourceRetainQuerystring && redirectDefinition.targetMergeQuerystring ? this.mergeQueryStrings(processedUrl.query, processedTarget.query) : !redirectDefinition.targetMergeQuerystring && redirectDefinition.sourceRetainQuerystring ? processedUrl.query : processedTarget.query;
|
|
482
537
|
const fragment = redirectDefinition.sourceRetainQuerystring && redirectDefinition.targetMergeQuerystring ? this.mergeQueryStrings(processedUrl.fragment, processedTarget.fragment) : !redirectDefinition.targetMergeQuerystring && redirectDefinition.sourceRetainQuerystring ? processedUrl.fragment : processedTarget.fragment;
|
|
483
538
|
return `${protocol}${domain}${port}${finalUrlPath}${query}${fragment}`;
|
|
@@ -499,15 +554,15 @@ var _RedirectClient = class extends ApiClient {
|
|
|
499
554
|
return (fragment ? "#" : "?") + merged;
|
|
500
555
|
return "";
|
|
501
556
|
}
|
|
502
|
-
static getSourceVariables(path, source, isVariable = (pathSegment) => pathSegment.startsWith(":")) {
|
|
557
|
+
static getSourceVariables(path, source, isVariable = (pathSegment, isLast) => pathSegment.startsWith(":") || pathSegment === "*" && isLast) {
|
|
503
558
|
const variables = {};
|
|
504
559
|
const pathSegments = path.split("/");
|
|
505
560
|
const sourceSegments = source.split("/");
|
|
506
|
-
if (pathSegments.length !== sourceSegments.length) {
|
|
561
|
+
if (pathSegments.length !== sourceSegments.length && !source.endsWith("/*")) {
|
|
507
562
|
throw new Error("Path and source have different numbers of path segments, must be the same");
|
|
508
563
|
}
|
|
509
564
|
sourceSegments.forEach((sourceSegment, i) => {
|
|
510
|
-
if (isVariable(sourceSegment)) {
|
|
565
|
+
if (isVariable(sourceSegment, i === sourceSegments.length - 1)) {
|
|
511
566
|
variables[sourceSegment] = pathSegments[i];
|
|
512
567
|
}
|
|
513
568
|
});
|
|
@@ -519,6 +574,10 @@ RedirectClient.processUrlBestMatch = async (url, trie, options) => {
|
|
|
519
574
|
var _a;
|
|
520
575
|
return (_a = _RedirectClient.processHops(url, trie, true, options)) == null ? void 0 : _a[0];
|
|
521
576
|
};
|
|
577
|
+
RedirectClient.assembling = false;
|
|
578
|
+
RedirectClient.assemblingPromise = new Promise(
|
|
579
|
+
() => new PathTrie()
|
|
580
|
+
);
|
|
522
581
|
var UncachedRedirectClient = class extends RedirectClient {
|
|
523
582
|
constructor(options) {
|
|
524
583
|
super({ ...options, bypassCache: true });
|
package/dist/index.js
CHANGED
|
@@ -326,6 +326,44 @@ __export(src_exports, {
|
|
|
326
326
|
});
|
|
327
327
|
module.exports = __toCommonJS(src_exports);
|
|
328
328
|
|
|
329
|
+
// src/cache/data/refresher.ts
|
|
330
|
+
var Refresher = class {
|
|
331
|
+
/**
|
|
332
|
+
* Create new refresher
|
|
333
|
+
* @param refreshRate - How often the refresher will refresh. Cannot be less than 20000 ms or 20 seconds
|
|
334
|
+
* @param refreshDuration - How many times it should refresh before sleeps until something accesses the cache. Cannot be more than 5
|
|
335
|
+
* @param refresh - Refresh method to run at the refresh rate intervals
|
|
336
|
+
*/
|
|
337
|
+
constructor({ refreshRate, refreshDuration, refresh }) {
|
|
338
|
+
this.refreshCounter = 0;
|
|
339
|
+
this.finalRate = refreshRate >= 2e4 ? refreshRate : 2e4;
|
|
340
|
+
this.finalDuration = refreshDuration <= 5 ? refreshDuration : 5;
|
|
341
|
+
this.refreshCounter = 1;
|
|
342
|
+
this.refresh = refresh;
|
|
343
|
+
this.start();
|
|
344
|
+
}
|
|
345
|
+
/**
|
|
346
|
+
* Start async updating process again, will run for the same duration as the original. refreshRate * refreshDuration milliseconds
|
|
347
|
+
*/
|
|
348
|
+
kick() {
|
|
349
|
+
if (this.refreshCounter === 0) {
|
|
350
|
+
this.start();
|
|
351
|
+
}
|
|
352
|
+
this.refreshCounter = 1;
|
|
353
|
+
}
|
|
354
|
+
start() {
|
|
355
|
+
this.interval = setTimeout(async () => {
|
|
356
|
+
if (this.refreshCounter > this.finalDuration) {
|
|
357
|
+
this.refreshCounter = 0;
|
|
358
|
+
} else {
|
|
359
|
+
await this.refresh();
|
|
360
|
+
this.refreshCounter++;
|
|
361
|
+
this.start();
|
|
362
|
+
}
|
|
363
|
+
}, this.finalRate);
|
|
364
|
+
}
|
|
365
|
+
};
|
|
366
|
+
|
|
329
367
|
// src/cache/redirectClientCache.ts
|
|
330
368
|
var RedirectClientCache = class {
|
|
331
369
|
constructor(options) {
|
|
@@ -337,11 +375,19 @@ var RedirectClientCache = class {
|
|
|
337
375
|
var _WithMemoryCache = class extends RedirectClientCache {
|
|
338
376
|
constructor(options) {
|
|
339
377
|
super(options);
|
|
378
|
+
if (options.refreshRate && !_WithMemoryCache.refresher) {
|
|
379
|
+
_WithMemoryCache.refresher = new Refresher({
|
|
380
|
+
refreshRate: options.refreshRate,
|
|
381
|
+
refreshDuration: 5,
|
|
382
|
+
refresh: this.refresh
|
|
383
|
+
});
|
|
384
|
+
}
|
|
340
385
|
}
|
|
341
386
|
/* Get data from the cache and debounce pausing refresh */
|
|
342
387
|
get(key) {
|
|
343
|
-
var _a, _b;
|
|
344
|
-
|
|
388
|
+
var _a, _b, _c;
|
|
389
|
+
(_a = _WithMemoryCache.refresher) == null ? void 0 : _a.kick();
|
|
390
|
+
return (_c = (_b = _WithMemoryCache.trieCache[key]) == null ? void 0 : _b.data) != null ? _c : void 0;
|
|
345
391
|
}
|
|
346
392
|
/* Set new data to the cache and reset the refresh method */
|
|
347
393
|
set(key, data, refresh) {
|
|
@@ -365,13 +411,15 @@ var _WithMemoryCache = class extends RedirectClientCache {
|
|
|
365
411
|
}
|
|
366
412
|
refresh() {
|
|
367
413
|
var _a, _b;
|
|
414
|
+
const caches = [];
|
|
368
415
|
for (const key in _WithMemoryCache.trieCache) {
|
|
369
416
|
const p = (_b = (_a = _WithMemoryCache.trieCache[key]) == null ? void 0 : _a.refresh) == null ? void 0 : _b.call(_a);
|
|
370
417
|
if (p) {
|
|
371
418
|
_WithMemoryCache.trieCache[key] = { ..._WithMemoryCache.trieCache[key], data: p };
|
|
419
|
+
caches.push(p.then());
|
|
372
420
|
}
|
|
373
421
|
}
|
|
374
|
-
return Promise.all(
|
|
422
|
+
return Promise.all(caches);
|
|
375
423
|
}
|
|
376
424
|
};
|
|
377
425
|
var WithMemoryCache = _WithMemoryCache;
|
|
@@ -456,7 +504,7 @@ var PathTrie = class {
|
|
|
456
504
|
}
|
|
457
505
|
return result;
|
|
458
506
|
};
|
|
459
|
-
const scanWildcards = () => {
|
|
507
|
+
const scanWildcards = (i) => {
|
|
460
508
|
let wildcard = void 0;
|
|
461
509
|
while ((!wildcard || wildcard.active) && wildcards.length) {
|
|
462
510
|
wildcard = wildcards.pop();
|
|
@@ -466,6 +514,11 @@ var PathTrie = class {
|
|
|
466
514
|
wildcard.active = true;
|
|
467
515
|
cur = wildcard == null ? void 0 : wildcard.startTrie;
|
|
468
516
|
wildcards.push(wildcard);
|
|
517
|
+
if (i === segments.length - 1 && wildcards.length && wildcards[wildcards.length - 1].active && wildcards[wildcards.length - 1].startTrie[dataProp]) {
|
|
518
|
+
wildcards[wildcards.length - 1].startTrie[dataProp].forEach(
|
|
519
|
+
(d) => ret.push({ data: d, variables: getVariables() })
|
|
520
|
+
);
|
|
521
|
+
}
|
|
469
522
|
return wildcard == null ? void 0 : wildcard.start;
|
|
470
523
|
};
|
|
471
524
|
for (let i = 0; i < segments.length; i++) {
|
|
@@ -494,21 +547,22 @@ var PathTrie = class {
|
|
|
494
547
|
if (i === segments.length - 1) {
|
|
495
548
|
if (cur[dataProp]) {
|
|
496
549
|
cur[dataProp].forEach((d) => ret.push({ data: d, variables: getVariables() }));
|
|
550
|
+
} else {
|
|
551
|
+
const more = scanWildcards(i);
|
|
552
|
+
if (typeof more === "undefined" || ret.length > 0 && bestMatch)
|
|
553
|
+
return [...ret, ...splats];
|
|
554
|
+
i = more;
|
|
497
555
|
}
|
|
498
556
|
}
|
|
499
|
-
} else
|
|
500
|
-
const more = scanWildcards();
|
|
501
|
-
if (typeof more === "undefined")
|
|
557
|
+
} else {
|
|
558
|
+
const more = scanWildcards(i);
|
|
559
|
+
if (typeof more === "undefined" || ret.length > 0 && bestMatch)
|
|
502
560
|
return [...ret, ...splats];
|
|
503
561
|
i = more;
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
}
|
|
509
|
-
} else {
|
|
510
|
-
const more = scanWildcards();
|
|
511
|
-
if (typeof more === "undefined")
|
|
562
|
+
}
|
|
563
|
+
if (i === segments.length - 1 && wildcards.length !== 0) {
|
|
564
|
+
const more = scanWildcards(i);
|
|
565
|
+
if (typeof more === "undefined" || ret.length > 0 && bestMatch)
|
|
512
566
|
return [...ret, ...splats];
|
|
513
567
|
i = more;
|
|
514
568
|
}
|
|
@@ -668,22 +722,29 @@ var _RedirectClient = class extends import_api.ApiClient {
|
|
|
668
722
|
}
|
|
669
723
|
}
|
|
670
724
|
async assembleTrie() {
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
725
|
+
if (!_RedirectClient.assembling) {
|
|
726
|
+
_RedirectClient.assembling = true;
|
|
727
|
+
_RedirectClient.assemblingPromise = (async () => {
|
|
728
|
+
const trie = new PathTrie();
|
|
729
|
+
for await (const redirect of this.getAllRedirects()) {
|
|
730
|
+
const source = processUrl(redirect.redirect.sourceUrl);
|
|
731
|
+
const target = processUrl(redirect.redirect.targetUrl);
|
|
732
|
+
trie.insert(source.path, {
|
|
733
|
+
redirect: redirect.redirect,
|
|
734
|
+
metadata: redirect.metadata,
|
|
735
|
+
reverse: false
|
|
736
|
+
});
|
|
737
|
+
trie.insert(target.path, {
|
|
738
|
+
redirect: redirect.redirect,
|
|
739
|
+
metadata: redirect.metadata,
|
|
740
|
+
reverse: true
|
|
741
|
+
});
|
|
742
|
+
}
|
|
743
|
+
_RedirectClient.assembling = false;
|
|
744
|
+
return trie;
|
|
745
|
+
})();
|
|
685
746
|
}
|
|
686
|
-
return
|
|
747
|
+
return await _RedirectClient.assemblingPromise;
|
|
687
748
|
}
|
|
688
749
|
static processHops(url, trie, bestMatch, options) {
|
|
689
750
|
var _a;
|
|
@@ -755,20 +816,14 @@ var _RedirectClient = class extends import_api.ApiClient {
|
|
|
755
816
|
* @param options - Different options available to the redirect engine
|
|
756
817
|
*/
|
|
757
818
|
static processDefinitionToResults(processedUrl, definition, variables, options) {
|
|
758
|
-
var _a, _b, _c, _d, _e;
|
|
759
819
|
const resultUrl = (options == null ? void 0 : options.reverse) ? definition.redirect.sourceUrl : definition.redirect.targetUrl;
|
|
760
820
|
const processedResult = processUrl(resultUrl);
|
|
761
821
|
const redirect = definition == null ? void 0 : definition.redirect;
|
|
762
822
|
if (redirect.sourceMustMatchDomain && processedUrl.domain !== processedResult.domain)
|
|
763
823
|
return void 0;
|
|
764
|
-
const
|
|
765
|
-
const domain = redirect.targetPreserveIncomingDomain ? processedUrl.domain : (_d = (_c = processedResult.domain) != null ? _c : processedUrl.domain) != null ? _d : "";
|
|
766
|
-
const queryString = redirect.sourceRetainQuerystring && processedResult.query ? (_e = processedResult.query) != null ? _e : "" : definition.redirect.sourceRetainQuerystring ? processedUrl.query : "";
|
|
767
|
-
const finalUrl = `${protocol}${domain}${processedResult.port}${processedResult.path}${queryString}`;
|
|
824
|
+
const finalUrl = _RedirectClient.getTargetVariableExpandedUrl(processedUrl.url, redirect);
|
|
768
825
|
return {
|
|
769
|
-
url:
|
|
770
|
-
return cur.replace(o.key, o.value);
|
|
771
|
-
}, finalUrl),
|
|
826
|
+
url: finalUrl,
|
|
772
827
|
definition,
|
|
773
828
|
label: (options == null ? void 0 : options.label) ? variables.reduce((cur, o) => {
|
|
774
829
|
return cur.replace(o.key, `<em>${o.value}</em>`);
|
|
@@ -803,7 +858,7 @@ var _RedirectClient = class extends import_api.ApiClient {
|
|
|
803
858
|
}
|
|
804
859
|
const protocol = redirectDefinition.targetPreserveIncomingProtocol ? processedUrl.protocol : processedTarget.protocol;
|
|
805
860
|
const domain = redirectDefinition.targetPreserveIncomingDomain ? processedUrl.domain : processedTarget.domain;
|
|
806
|
-
const port = processedTarget.port;
|
|
861
|
+
const port = redirectDefinition.targetPreserveIncomingDomain ? processedUrl.port : processedTarget.port;
|
|
807
862
|
const query = redirectDefinition.sourceRetainQuerystring && redirectDefinition.targetMergeQuerystring ? this.mergeQueryStrings(processedUrl.query, processedTarget.query) : !redirectDefinition.targetMergeQuerystring && redirectDefinition.sourceRetainQuerystring ? processedUrl.query : processedTarget.query;
|
|
808
863
|
const fragment = redirectDefinition.sourceRetainQuerystring && redirectDefinition.targetMergeQuerystring ? this.mergeQueryStrings(processedUrl.fragment, processedTarget.fragment) : !redirectDefinition.targetMergeQuerystring && redirectDefinition.sourceRetainQuerystring ? processedUrl.fragment : processedTarget.fragment;
|
|
809
864
|
return `${protocol}${domain}${port}${finalUrlPath}${query}${fragment}`;
|
|
@@ -825,15 +880,15 @@ var _RedirectClient = class extends import_api.ApiClient {
|
|
|
825
880
|
return (fragment ? "#" : "?") + merged;
|
|
826
881
|
return "";
|
|
827
882
|
}
|
|
828
|
-
static getSourceVariables(path, source, isVariable = (pathSegment) => pathSegment.startsWith(":")) {
|
|
883
|
+
static getSourceVariables(path, source, isVariable = (pathSegment, isLast) => pathSegment.startsWith(":") || pathSegment === "*" && isLast) {
|
|
829
884
|
const variables = {};
|
|
830
885
|
const pathSegments = path.split("/");
|
|
831
886
|
const sourceSegments = source.split("/");
|
|
832
|
-
if (pathSegments.length !== sourceSegments.length) {
|
|
887
|
+
if (pathSegments.length !== sourceSegments.length && !source.endsWith("/*")) {
|
|
833
888
|
throw new Error("Path and source have different numbers of path segments, must be the same");
|
|
834
889
|
}
|
|
835
890
|
sourceSegments.forEach((sourceSegment, i) => {
|
|
836
|
-
if (isVariable(sourceSegment)) {
|
|
891
|
+
if (isVariable(sourceSegment, i === sourceSegments.length - 1)) {
|
|
837
892
|
variables[sourceSegment] = pathSegments[i];
|
|
838
893
|
}
|
|
839
894
|
});
|
|
@@ -845,6 +900,10 @@ RedirectClient.processUrlBestMatch = async (url, trie, options) => {
|
|
|
845
900
|
var _a;
|
|
846
901
|
return (_a = _RedirectClient.processHops(url, trie, true, options)) == null ? void 0 : _a[0];
|
|
847
902
|
};
|
|
903
|
+
RedirectClient.assembling = false;
|
|
904
|
+
RedirectClient.assemblingPromise = new Promise(
|
|
905
|
+
() => new PathTrie()
|
|
906
|
+
);
|
|
848
907
|
var UncachedRedirectClient = class extends RedirectClient {
|
|
849
908
|
constructor(options) {
|
|
850
909
|
super({ ...options, bypassCache: true });
|
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,43 @@
|
|
|
1
1
|
import "./chunk-FFYIGW52.mjs";
|
|
2
2
|
|
|
3
|
+
// src/cache/data/refresher.ts
|
|
4
|
+
var Refresher = class {
|
|
5
|
+
/**
|
|
6
|
+
* Create new refresher
|
|
7
|
+
* @param refreshRate - How often the refresher will refresh. Cannot be less than 20000 ms or 20 seconds
|
|
8
|
+
* @param refreshDuration - How many times it should refresh before sleeps until something accesses the cache. Cannot be more than 5
|
|
9
|
+
* @param refresh - Refresh method to run at the refresh rate intervals
|
|
10
|
+
*/
|
|
11
|
+
constructor({ refreshRate, refreshDuration, refresh }) {
|
|
12
|
+
this.refreshCounter = 0;
|
|
13
|
+
this.finalRate = refreshRate >= 2e4 ? refreshRate : 2e4;
|
|
14
|
+
this.finalDuration = refreshDuration <= 5 ? refreshDuration : 5;
|
|
15
|
+
this.refreshCounter = 1;
|
|
16
|
+
this.refresh = refresh;
|
|
17
|
+
this.start();
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Start async updating process again, will run for the same duration as the original. refreshRate * refreshDuration milliseconds
|
|
21
|
+
*/
|
|
22
|
+
kick() {
|
|
23
|
+
if (this.refreshCounter === 0) {
|
|
24
|
+
this.start();
|
|
25
|
+
}
|
|
26
|
+
this.refreshCounter = 1;
|
|
27
|
+
}
|
|
28
|
+
start() {
|
|
29
|
+
this.interval = setTimeout(async () => {
|
|
30
|
+
if (this.refreshCounter > this.finalDuration) {
|
|
31
|
+
this.refreshCounter = 0;
|
|
32
|
+
} else {
|
|
33
|
+
await this.refresh();
|
|
34
|
+
this.refreshCounter++;
|
|
35
|
+
this.start();
|
|
36
|
+
}
|
|
37
|
+
}, this.finalRate);
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
|
|
3
41
|
// src/cache/redirectClientCache.ts
|
|
4
42
|
var RedirectClientCache = class {
|
|
5
43
|
constructor(options) {
|
|
@@ -11,11 +49,19 @@ var RedirectClientCache = class {
|
|
|
11
49
|
var _WithMemoryCache = class extends RedirectClientCache {
|
|
12
50
|
constructor(options) {
|
|
13
51
|
super(options);
|
|
52
|
+
if (options.refreshRate && !_WithMemoryCache.refresher) {
|
|
53
|
+
_WithMemoryCache.refresher = new Refresher({
|
|
54
|
+
refreshRate: options.refreshRate,
|
|
55
|
+
refreshDuration: 5,
|
|
56
|
+
refresh: this.refresh
|
|
57
|
+
});
|
|
58
|
+
}
|
|
14
59
|
}
|
|
15
60
|
/* Get data from the cache and debounce pausing refresh */
|
|
16
61
|
get(key) {
|
|
17
|
-
var _a, _b;
|
|
18
|
-
|
|
62
|
+
var _a, _b, _c;
|
|
63
|
+
(_a = _WithMemoryCache.refresher) == null ? void 0 : _a.kick();
|
|
64
|
+
return (_c = (_b = _WithMemoryCache.trieCache[key]) == null ? void 0 : _b.data) != null ? _c : void 0;
|
|
19
65
|
}
|
|
20
66
|
/* Set new data to the cache and reset the refresh method */
|
|
21
67
|
set(key, data, refresh) {
|
|
@@ -39,13 +85,15 @@ var _WithMemoryCache = class extends RedirectClientCache {
|
|
|
39
85
|
}
|
|
40
86
|
refresh() {
|
|
41
87
|
var _a, _b;
|
|
88
|
+
const caches = [];
|
|
42
89
|
for (const key in _WithMemoryCache.trieCache) {
|
|
43
90
|
const p = (_b = (_a = _WithMemoryCache.trieCache[key]) == null ? void 0 : _a.refresh) == null ? void 0 : _b.call(_a);
|
|
44
91
|
if (p) {
|
|
45
92
|
_WithMemoryCache.trieCache[key] = { ..._WithMemoryCache.trieCache[key], data: p };
|
|
93
|
+
caches.push(p.then());
|
|
46
94
|
}
|
|
47
95
|
}
|
|
48
|
-
return Promise.all(
|
|
96
|
+
return Promise.all(caches);
|
|
49
97
|
}
|
|
50
98
|
};
|
|
51
99
|
var WithMemoryCache = _WithMemoryCache;
|
|
@@ -130,7 +178,7 @@ var PathTrie = class {
|
|
|
130
178
|
}
|
|
131
179
|
return result;
|
|
132
180
|
};
|
|
133
|
-
const scanWildcards = () => {
|
|
181
|
+
const scanWildcards = (i) => {
|
|
134
182
|
let wildcard = void 0;
|
|
135
183
|
while ((!wildcard || wildcard.active) && wildcards.length) {
|
|
136
184
|
wildcard = wildcards.pop();
|
|
@@ -140,6 +188,11 @@ var PathTrie = class {
|
|
|
140
188
|
wildcard.active = true;
|
|
141
189
|
cur = wildcard == null ? void 0 : wildcard.startTrie;
|
|
142
190
|
wildcards.push(wildcard);
|
|
191
|
+
if (i === segments.length - 1 && wildcards.length && wildcards[wildcards.length - 1].active && wildcards[wildcards.length - 1].startTrie[dataProp]) {
|
|
192
|
+
wildcards[wildcards.length - 1].startTrie[dataProp].forEach(
|
|
193
|
+
(d) => ret.push({ data: d, variables: getVariables() })
|
|
194
|
+
);
|
|
195
|
+
}
|
|
143
196
|
return wildcard == null ? void 0 : wildcard.start;
|
|
144
197
|
};
|
|
145
198
|
for (let i = 0; i < segments.length; i++) {
|
|
@@ -168,21 +221,22 @@ var PathTrie = class {
|
|
|
168
221
|
if (i === segments.length - 1) {
|
|
169
222
|
if (cur[dataProp]) {
|
|
170
223
|
cur[dataProp].forEach((d) => ret.push({ data: d, variables: getVariables() }));
|
|
224
|
+
} else {
|
|
225
|
+
const more = scanWildcards(i);
|
|
226
|
+
if (typeof more === "undefined" || ret.length > 0 && bestMatch)
|
|
227
|
+
return [...ret, ...splats];
|
|
228
|
+
i = more;
|
|
171
229
|
}
|
|
172
230
|
}
|
|
173
|
-
} else
|
|
174
|
-
const more = scanWildcards();
|
|
175
|
-
if (typeof more === "undefined")
|
|
231
|
+
} else {
|
|
232
|
+
const more = scanWildcards(i);
|
|
233
|
+
if (typeof more === "undefined" || ret.length > 0 && bestMatch)
|
|
176
234
|
return [...ret, ...splats];
|
|
177
235
|
i = more;
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
}
|
|
183
|
-
} else {
|
|
184
|
-
const more = scanWildcards();
|
|
185
|
-
if (typeof more === "undefined")
|
|
236
|
+
}
|
|
237
|
+
if (i === segments.length - 1 && wildcards.length !== 0) {
|
|
238
|
+
const more = scanWildcards(i);
|
|
239
|
+
if (typeof more === "undefined" || ret.length > 0 && bestMatch)
|
|
186
240
|
return [...ret, ...splats];
|
|
187
241
|
i = more;
|
|
188
242
|
}
|
|
@@ -342,22 +396,29 @@ var _RedirectClient = class extends ApiClient {
|
|
|
342
396
|
}
|
|
343
397
|
}
|
|
344
398
|
async assembleTrie() {
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
399
|
+
if (!_RedirectClient.assembling) {
|
|
400
|
+
_RedirectClient.assembling = true;
|
|
401
|
+
_RedirectClient.assemblingPromise = (async () => {
|
|
402
|
+
const trie = new PathTrie();
|
|
403
|
+
for await (const redirect of this.getAllRedirects()) {
|
|
404
|
+
const source = processUrl(redirect.redirect.sourceUrl);
|
|
405
|
+
const target = processUrl(redirect.redirect.targetUrl);
|
|
406
|
+
trie.insert(source.path, {
|
|
407
|
+
redirect: redirect.redirect,
|
|
408
|
+
metadata: redirect.metadata,
|
|
409
|
+
reverse: false
|
|
410
|
+
});
|
|
411
|
+
trie.insert(target.path, {
|
|
412
|
+
redirect: redirect.redirect,
|
|
413
|
+
metadata: redirect.metadata,
|
|
414
|
+
reverse: true
|
|
415
|
+
});
|
|
416
|
+
}
|
|
417
|
+
_RedirectClient.assembling = false;
|
|
418
|
+
return trie;
|
|
419
|
+
})();
|
|
359
420
|
}
|
|
360
|
-
return
|
|
421
|
+
return await _RedirectClient.assemblingPromise;
|
|
361
422
|
}
|
|
362
423
|
static processHops(url, trie, bestMatch, options) {
|
|
363
424
|
var _a;
|
|
@@ -429,20 +490,14 @@ var _RedirectClient = class extends ApiClient {
|
|
|
429
490
|
* @param options - Different options available to the redirect engine
|
|
430
491
|
*/
|
|
431
492
|
static processDefinitionToResults(processedUrl, definition, variables, options) {
|
|
432
|
-
var _a, _b, _c, _d, _e;
|
|
433
493
|
const resultUrl = (options == null ? void 0 : options.reverse) ? definition.redirect.sourceUrl : definition.redirect.targetUrl;
|
|
434
494
|
const processedResult = processUrl(resultUrl);
|
|
435
495
|
const redirect = definition == null ? void 0 : definition.redirect;
|
|
436
496
|
if (redirect.sourceMustMatchDomain && processedUrl.domain !== processedResult.domain)
|
|
437
497
|
return void 0;
|
|
438
|
-
const
|
|
439
|
-
const domain = redirect.targetPreserveIncomingDomain ? processedUrl.domain : (_d = (_c = processedResult.domain) != null ? _c : processedUrl.domain) != null ? _d : "";
|
|
440
|
-
const queryString = redirect.sourceRetainQuerystring && processedResult.query ? (_e = processedResult.query) != null ? _e : "" : definition.redirect.sourceRetainQuerystring ? processedUrl.query : "";
|
|
441
|
-
const finalUrl = `${protocol}${domain}${processedResult.port}${processedResult.path}${queryString}`;
|
|
498
|
+
const finalUrl = _RedirectClient.getTargetVariableExpandedUrl(processedUrl.url, redirect);
|
|
442
499
|
return {
|
|
443
|
-
url:
|
|
444
|
-
return cur.replace(o.key, o.value);
|
|
445
|
-
}, finalUrl),
|
|
500
|
+
url: finalUrl,
|
|
446
501
|
definition,
|
|
447
502
|
label: (options == null ? void 0 : options.label) ? variables.reduce((cur, o) => {
|
|
448
503
|
return cur.replace(o.key, `<em>${o.value}</em>`);
|
|
@@ -477,7 +532,7 @@ var _RedirectClient = class extends ApiClient {
|
|
|
477
532
|
}
|
|
478
533
|
const protocol = redirectDefinition.targetPreserveIncomingProtocol ? processedUrl.protocol : processedTarget.protocol;
|
|
479
534
|
const domain = redirectDefinition.targetPreserveIncomingDomain ? processedUrl.domain : processedTarget.domain;
|
|
480
|
-
const port = processedTarget.port;
|
|
535
|
+
const port = redirectDefinition.targetPreserveIncomingDomain ? processedUrl.port : processedTarget.port;
|
|
481
536
|
const query = redirectDefinition.sourceRetainQuerystring && redirectDefinition.targetMergeQuerystring ? this.mergeQueryStrings(processedUrl.query, processedTarget.query) : !redirectDefinition.targetMergeQuerystring && redirectDefinition.sourceRetainQuerystring ? processedUrl.query : processedTarget.query;
|
|
482
537
|
const fragment = redirectDefinition.sourceRetainQuerystring && redirectDefinition.targetMergeQuerystring ? this.mergeQueryStrings(processedUrl.fragment, processedTarget.fragment) : !redirectDefinition.targetMergeQuerystring && redirectDefinition.sourceRetainQuerystring ? processedUrl.fragment : processedTarget.fragment;
|
|
483
538
|
return `${protocol}${domain}${port}${finalUrlPath}${query}${fragment}`;
|
|
@@ -499,15 +554,15 @@ var _RedirectClient = class extends ApiClient {
|
|
|
499
554
|
return (fragment ? "#" : "?") + merged;
|
|
500
555
|
return "";
|
|
501
556
|
}
|
|
502
|
-
static getSourceVariables(path, source, isVariable = (pathSegment) => pathSegment.startsWith(":")) {
|
|
557
|
+
static getSourceVariables(path, source, isVariable = (pathSegment, isLast) => pathSegment.startsWith(":") || pathSegment === "*" && isLast) {
|
|
503
558
|
const variables = {};
|
|
504
559
|
const pathSegments = path.split("/");
|
|
505
560
|
const sourceSegments = source.split("/");
|
|
506
|
-
if (pathSegments.length !== sourceSegments.length) {
|
|
561
|
+
if (pathSegments.length !== sourceSegments.length && !source.endsWith("/*")) {
|
|
507
562
|
throw new Error("Path and source have different numbers of path segments, must be the same");
|
|
508
563
|
}
|
|
509
564
|
sourceSegments.forEach((sourceSegment, i) => {
|
|
510
|
-
if (isVariable(sourceSegment)) {
|
|
565
|
+
if (isVariable(sourceSegment, i === sourceSegments.length - 1)) {
|
|
511
566
|
variables[sourceSegment] = pathSegments[i];
|
|
512
567
|
}
|
|
513
568
|
});
|
|
@@ -519,6 +574,10 @@ RedirectClient.processUrlBestMatch = async (url, trie, options) => {
|
|
|
519
574
|
var _a;
|
|
520
575
|
return (_a = _RedirectClient.processHops(url, trie, true, options)) == null ? void 0 : _a[0];
|
|
521
576
|
};
|
|
577
|
+
RedirectClient.assembling = false;
|
|
578
|
+
RedirectClient.assemblingPromise = new Promise(
|
|
579
|
+
() => new PathTrie()
|
|
580
|
+
);
|
|
522
581
|
var UncachedRedirectClient = class extends RedirectClient {
|
|
523
582
|
constructor(options) {
|
|
524
583
|
super({ ...options, bypassCache: true });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@uniformdev/redirect",
|
|
3
|
-
"version": "19.
|
|
3
|
+
"version": "19.29.0",
|
|
4
4
|
"description": "Uniform redirect client",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE.txt",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -32,12 +32,12 @@
|
|
|
32
32
|
"/dist"
|
|
33
33
|
],
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@uniformdev/context": "19.
|
|
35
|
+
"@uniformdev/context": "19.29.0",
|
|
36
36
|
"p-limit": "^3.1.0",
|
|
37
37
|
"rfdc": "^1.3.0"
|
|
38
38
|
},
|
|
39
39
|
"publishConfig": {
|
|
40
40
|
"access": "public"
|
|
41
41
|
},
|
|
42
|
-
"gitHead": "
|
|
42
|
+
"gitHead": "f8e9d5f6283fb3d72ba095c0e307907dc591ce4a"
|
|
43
43
|
}
|