@ztimson/utils 0.27.9 → 0.27.11
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/cache.d.ts +11 -52
- package/dist/index.cjs +182 -107
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +182 -107
- package/dist/index.mjs.map +1 -1
- package/dist/path-events.d.ts +37 -10
- package/package.json +1 -1
package/dist/cache.d.ts
CHANGED
|
@@ -38,6 +38,7 @@ export declare class Cache<K extends string | number | symbol, T> {
|
|
|
38
38
|
*/
|
|
39
39
|
constructor(key?: keyof T | undefined, options?: CacheOptions);
|
|
40
40
|
private getKey;
|
|
41
|
+
/** Save item to storage */
|
|
41
42
|
private save;
|
|
42
43
|
private clearTimer;
|
|
43
44
|
private touchLRU;
|
|
@@ -48,72 +49,30 @@ export declare class Cache<K extends string | number | symbol, T> {
|
|
|
48
49
|
all(expired?: boolean): CachedValue<T>[];
|
|
49
50
|
/**
|
|
50
51
|
* Add a new item to the cache. Like set, but finds key automatically
|
|
51
|
-
* @param {T} value Item to add to cache
|
|
52
|
-
* @param {number | undefined} ttl Override default expiry
|
|
53
|
-
* @return {this}
|
|
54
52
|
*/
|
|
55
53
|
add(value: T, ttl?: any): this;
|
|
56
54
|
/**
|
|
57
55
|
* Add several rows to the cache
|
|
58
|
-
* @param {T[]} rows Several items that will be cached using the default key
|
|
59
|
-
* @param complete Mark cache as complete & reliable, defaults to true
|
|
60
|
-
* @return {this}
|
|
61
56
|
*/
|
|
62
57
|
addAll(rows: T[], complete?: boolean): this;
|
|
63
|
-
/**
|
|
64
|
-
* Remove all keys from cache
|
|
65
|
-
*/
|
|
58
|
+
/** Remove all keys */
|
|
66
59
|
clear(): this;
|
|
67
|
-
/**
|
|
68
|
-
* Delete an item from the cache
|
|
69
|
-
* @param {K} key Item's primary key
|
|
70
|
-
*/
|
|
60
|
+
/** Delete a cached item */
|
|
71
61
|
delete(key: K): this;
|
|
72
|
-
/**
|
|
73
|
-
* Return cache as an array of key-value pairs
|
|
74
|
-
* @return {[K, T][]} Key-value pairs array
|
|
75
|
-
*/
|
|
62
|
+
/** Return entries as array */
|
|
76
63
|
entries(expired?: boolean): [K, CachedValue<T>][];
|
|
77
|
-
/**
|
|
78
|
-
* Manually expire a cached item
|
|
79
|
-
* @param {K} key Key to expire
|
|
80
|
-
*/
|
|
64
|
+
/** Manually expire a cached item */
|
|
81
65
|
expire(key: K): this;
|
|
82
|
-
/**
|
|
83
|
-
* Find the first cached item to match a filter
|
|
84
|
-
* @param {Partial<T>} filter Partial item to match
|
|
85
|
-
* @param {Boolean} expired Include expired items, defaults to false
|
|
86
|
-
* @returns {T | undefined} Cached item or undefined if nothing matched
|
|
87
|
-
*/
|
|
66
|
+
/** Find first matching item */
|
|
88
67
|
find(filter: Partial<T>, expired?: boolean): T | undefined;
|
|
89
|
-
/**
|
|
90
|
-
* Get item from the cache
|
|
91
|
-
* @param {K} key Key to lookup
|
|
92
|
-
* @param expired Include expired items
|
|
93
|
-
* @return {T} Cached item
|
|
94
|
-
*/
|
|
68
|
+
/** Get cached item by key */
|
|
95
69
|
get(key: K, expired?: boolean): CachedValue<T> | null;
|
|
96
|
-
/**
|
|
97
|
-
* Get a list of cached keys
|
|
98
|
-
* @return {K[]} Array of keys
|
|
99
|
-
*/
|
|
70
|
+
/** Return list of keys */
|
|
100
71
|
keys(expired?: boolean): K[];
|
|
101
|
-
/**
|
|
102
|
-
* Get map of cached items
|
|
103
|
-
* @return {Record<K, T>}
|
|
104
|
-
*/
|
|
72
|
+
/** Return map of key → item */
|
|
105
73
|
map(expired?: boolean): Record<K, CachedValue<T>>;
|
|
106
|
-
/**
|
|
107
|
-
* Add an item to the cache manually specifying the key
|
|
108
|
-
* @param {K} key Key item will be cached under
|
|
109
|
-
* @param {T} value Item to cache
|
|
110
|
-
* @param {number | undefined} ttl Override default expiry in seconds
|
|
111
|
-
* @return {this}
|
|
112
|
-
*/
|
|
74
|
+
/** Add item manually specifying the key */
|
|
113
75
|
set(key: K, value: T, ttl?: number | undefined): this;
|
|
114
|
-
/**
|
|
115
|
-
* Get all cached items
|
|
116
|
-
* @return {T[]} Array of items
|
|
117
|
-
*/
|
|
76
|
+
/** Get all cached items */
|
|
118
77
|
values: (expired?: boolean) => CachedValue<T>[];
|
|
119
78
|
}
|
package/dist/index.cjs
CHANGED
|
@@ -186,6 +186,9 @@ ${opts.message || this.desc}`;
|
|
|
186
186
|
return obj;
|
|
187
187
|
}
|
|
188
188
|
function deepCopy(value) {
|
|
189
|
+
if (value == null) return value;
|
|
190
|
+
const t = typeof value;
|
|
191
|
+
if (t === "string" || t === "number" || t === "boolean" || t === "function") return value;
|
|
189
192
|
try {
|
|
190
193
|
return structuredClone(value);
|
|
191
194
|
} catch {
|
|
@@ -467,10 +470,7 @@ ${opts.message || this.desc}`;
|
|
|
467
470
|
__publicField(this, "complete", false);
|
|
468
471
|
/** Await initial loading */
|
|
469
472
|
__publicField(this, "loading", new Promise((r) => this._loading = r));
|
|
470
|
-
/**
|
|
471
|
-
* Get all cached items
|
|
472
|
-
* @return {T[]} Array of items
|
|
473
|
-
*/
|
|
473
|
+
/** Get all cached items */
|
|
474
474
|
__publicField(this, "values", this.all);
|
|
475
475
|
var _a, _b, _c, _d;
|
|
476
476
|
this.key = key;
|
|
@@ -518,6 +518,7 @@ ${opts.message || this.desc}`;
|
|
|
518
518
|
if (value[this.key] === void 0) throw new Error(`${this.key.toString()} Doesn't exist on ${JSON.stringify(value, null, 2)}`);
|
|
519
519
|
return value[this.key];
|
|
520
520
|
}
|
|
521
|
+
/** Save item to storage */
|
|
521
522
|
save(key) {
|
|
522
523
|
var _a, _b;
|
|
523
524
|
const persists = this.options.persistentStorage;
|
|
@@ -571,9 +572,6 @@ ${opts.message || this.desc}`;
|
|
|
571
572
|
}
|
|
572
573
|
/**
|
|
573
574
|
* Add a new item to the cache. Like set, but finds key automatically
|
|
574
|
-
* @param {T} value Item to add to cache
|
|
575
|
-
* @param {number | undefined} ttl Override default expiry
|
|
576
|
-
* @return {this}
|
|
577
575
|
*/
|
|
578
576
|
add(value, ttl = this.ttl) {
|
|
579
577
|
const key = this.getKey(value);
|
|
@@ -582,9 +580,6 @@ ${opts.message || this.desc}`;
|
|
|
582
580
|
}
|
|
583
581
|
/**
|
|
584
582
|
* Add several rows to the cache
|
|
585
|
-
* @param {T[]} rows Several items that will be cached using the default key
|
|
586
|
-
* @param complete Mark cache as complete & reliable, defaults to true
|
|
587
|
-
* @return {this}
|
|
588
583
|
*/
|
|
589
584
|
addAll(rows, complete = true) {
|
|
590
585
|
this.clear();
|
|
@@ -592,9 +587,7 @@ ${opts.message || this.desc}`;
|
|
|
592
587
|
this.complete = complete;
|
|
593
588
|
return this;
|
|
594
589
|
}
|
|
595
|
-
/**
|
|
596
|
-
* Remove all keys from cache
|
|
597
|
-
*/
|
|
590
|
+
/** Remove all keys */
|
|
598
591
|
clear() {
|
|
599
592
|
this.complete = false;
|
|
600
593
|
for (const [k, t] of this.timers) clearTimeout(t);
|
|
@@ -604,10 +597,7 @@ ${opts.message || this.desc}`;
|
|
|
604
597
|
this.save();
|
|
605
598
|
return this;
|
|
606
599
|
}
|
|
607
|
-
/**
|
|
608
|
-
* Delete an item from the cache
|
|
609
|
-
* @param {K} key Item's primary key
|
|
610
|
-
*/
|
|
600
|
+
/** Delete a cached item */
|
|
611
601
|
delete(key) {
|
|
612
602
|
this.clearTimer(key);
|
|
613
603
|
const idx = this.lruOrder.indexOf(key);
|
|
@@ -616,10 +606,7 @@ ${opts.message || this.desc}`;
|
|
|
616
606
|
this.save(key);
|
|
617
607
|
return this;
|
|
618
608
|
}
|
|
619
|
-
/**
|
|
620
|
-
* Return cache as an array of key-value pairs
|
|
621
|
-
* @return {[K, T][]} Key-value pairs array
|
|
622
|
-
*/
|
|
609
|
+
/** Return entries as array */
|
|
623
610
|
entries(expired) {
|
|
624
611
|
const out = [];
|
|
625
612
|
for (const [k, v] of this.store.entries()) {
|
|
@@ -628,10 +615,7 @@ ${opts.message || this.desc}`;
|
|
|
628
615
|
}
|
|
629
616
|
return out;
|
|
630
617
|
}
|
|
631
|
-
/**
|
|
632
|
-
* Manually expire a cached item
|
|
633
|
-
* @param {K} key Key to expire
|
|
634
|
-
*/
|
|
618
|
+
/** Manually expire a cached item */
|
|
635
619
|
expire(key) {
|
|
636
620
|
this.complete = false;
|
|
637
621
|
if (this.options.expiryPolicy == "keep") {
|
|
@@ -644,12 +628,7 @@ ${opts.message || this.desc}`;
|
|
|
644
628
|
} else this.delete(key);
|
|
645
629
|
return this;
|
|
646
630
|
}
|
|
647
|
-
/**
|
|
648
|
-
* Find the first cached item to match a filter
|
|
649
|
-
* @param {Partial<T>} filter Partial item to match
|
|
650
|
-
* @param {Boolean} expired Include expired items, defaults to false
|
|
651
|
-
* @returns {T | undefined} Cached item or undefined if nothing matched
|
|
652
|
-
*/
|
|
631
|
+
/** Find first matching item */
|
|
653
632
|
find(filter, expired) {
|
|
654
633
|
for (const v of this.store.values()) {
|
|
655
634
|
const row = v;
|
|
@@ -657,24 +636,16 @@ ${opts.message || this.desc}`;
|
|
|
657
636
|
}
|
|
658
637
|
return void 0;
|
|
659
638
|
}
|
|
660
|
-
/**
|
|
661
|
-
* Get item from the cache
|
|
662
|
-
* @param {K} key Key to lookup
|
|
663
|
-
* @param expired Include expired items
|
|
664
|
-
* @return {T} Cached item
|
|
665
|
-
*/
|
|
639
|
+
/** Get cached item by key */
|
|
666
640
|
get(key, expired) {
|
|
667
641
|
const raw = this.store.get(key);
|
|
668
642
|
if (raw == null) return null;
|
|
669
|
-
const cached = deepCopy(raw);
|
|
670
643
|
this.touchLRU(key);
|
|
671
|
-
|
|
644
|
+
const isExpired = raw == null ? void 0 : raw._expired;
|
|
645
|
+
if (expired || !isExpired) return deepCopy(raw);
|
|
672
646
|
return null;
|
|
673
647
|
}
|
|
674
|
-
/**
|
|
675
|
-
* Get a list of cached keys
|
|
676
|
-
* @return {K[]} Array of keys
|
|
677
|
-
*/
|
|
648
|
+
/** Return list of keys */
|
|
678
649
|
keys(expired) {
|
|
679
650
|
const out = [];
|
|
680
651
|
for (const [k, v] of this.store.entries()) {
|
|
@@ -683,10 +654,7 @@ ${opts.message || this.desc}`;
|
|
|
683
654
|
}
|
|
684
655
|
return out;
|
|
685
656
|
}
|
|
686
|
-
/**
|
|
687
|
-
* Get map of cached items
|
|
688
|
-
* @return {Record<K, T>}
|
|
689
|
-
*/
|
|
657
|
+
/** Return map of key → item */
|
|
690
658
|
map(expired) {
|
|
691
659
|
const copy = {};
|
|
692
660
|
for (const [k, v] of this.store.entries()) {
|
|
@@ -695,13 +663,7 @@ ${opts.message || this.desc}`;
|
|
|
695
663
|
}
|
|
696
664
|
return copy;
|
|
697
665
|
}
|
|
698
|
-
/**
|
|
699
|
-
* Add an item to the cache manually specifying the key
|
|
700
|
-
* @param {K} key Key item will be cached under
|
|
701
|
-
* @param {T} value Item to cache
|
|
702
|
-
* @param {number | undefined} ttl Override default expiry in seconds
|
|
703
|
-
* @return {this}
|
|
704
|
-
*/
|
|
666
|
+
/** Add item manually specifying the key */
|
|
705
667
|
set(key, value, ttl = this.options.ttl) {
|
|
706
668
|
if (this.options.expiryPolicy == "keep") delete value._expired;
|
|
707
669
|
this.clearTimer(key);
|
|
@@ -712,7 +674,7 @@ ${opts.message || this.desc}`;
|
|
|
712
674
|
const t = setTimeout(() => {
|
|
713
675
|
this.expire(key);
|
|
714
676
|
this.save(key);
|
|
715
|
-
},
|
|
677
|
+
}, ttl * 1e3);
|
|
716
678
|
this.timers.set(key, t);
|
|
717
679
|
}
|
|
718
680
|
return this;
|
|
@@ -1957,10 +1919,12 @@ ${opts.message || this.desc}`;
|
|
|
1957
1919
|
__publicField(this, "fullPath");
|
|
1958
1920
|
/** Path including the name, excluding the module */
|
|
1959
1921
|
__publicField(this, "path");
|
|
1960
|
-
/** Last
|
|
1922
|
+
/** Last segment of path */
|
|
1961
1923
|
__publicField(this, "name");
|
|
1962
1924
|
/** List of methods */
|
|
1963
1925
|
__publicField(this, "methods");
|
|
1926
|
+
/** Whether this path contains glob patterns */
|
|
1927
|
+
__publicField(this, "hasGlob");
|
|
1964
1928
|
if (typeof e == "object") {
|
|
1965
1929
|
Object.assign(this, e);
|
|
1966
1930
|
return;
|
|
@@ -1969,17 +1933,34 @@ ${opts.message || this.desc}`;
|
|
|
1969
1933
|
Object.assign(this, _PathEvent.pathEventCache.get(e));
|
|
1970
1934
|
return;
|
|
1971
1935
|
}
|
|
1972
|
-
let [p,
|
|
1973
|
-
if (!method) method =
|
|
1974
|
-
if (p
|
|
1975
|
-
|
|
1976
|
-
|
|
1936
|
+
let [p, method] = e.replaceAll(/\/{2,}/g, "/").split(":");
|
|
1937
|
+
if (!method) method = "*";
|
|
1938
|
+
if (p === "" || p === void 0) {
|
|
1939
|
+
this.module = "";
|
|
1940
|
+
this.path = "";
|
|
1941
|
+
this.fullPath = "";
|
|
1942
|
+
this.name = "";
|
|
1943
|
+
this.methods = new ASet(["n"]);
|
|
1944
|
+
this.hasGlob = false;
|
|
1945
|
+
_PathEvent.pathEventCache.set(e, this);
|
|
1946
|
+
return;
|
|
1947
|
+
}
|
|
1948
|
+
if (p === "*") {
|
|
1949
|
+
this.module = "";
|
|
1950
|
+
this.path = "";
|
|
1951
|
+
this.fullPath = "**";
|
|
1952
|
+
this.name = "";
|
|
1953
|
+
this.methods = new ASet(["*"]);
|
|
1954
|
+
this.hasGlob = true;
|
|
1955
|
+
_PathEvent.pathEventCache.set(e, this);
|
|
1956
|
+
return;
|
|
1977
1957
|
}
|
|
1978
1958
|
let temp = p.split("/").filter((p2) => !!p2);
|
|
1979
1959
|
this.module = temp.splice(0, 1)[0] || "";
|
|
1980
1960
|
this.path = temp.join("/");
|
|
1981
1961
|
this.fullPath = `${this.module}${this.module && this.path ? "/" : ""}${this.path}`;
|
|
1982
1962
|
this.name = temp.pop() || "";
|
|
1963
|
+
this.hasGlob = this.fullPath.includes("*");
|
|
1983
1964
|
this.methods = new ASet(method.split(""));
|
|
1984
1965
|
_PathEvent.pathEventCache.set(e, this);
|
|
1985
1966
|
}
|
|
@@ -2004,6 +1985,13 @@ ${opts.message || this.desc}`;
|
|
|
2004
1985
|
set create(v) {
|
|
2005
1986
|
v ? this.methods.delete("n").delete("*").add("c") : this.methods.delete("c");
|
|
2006
1987
|
}
|
|
1988
|
+
/** Execute method specified */
|
|
1989
|
+
get execute() {
|
|
1990
|
+
return !this.methods.has("n") && (this.methods.has("*") || this.methods.has("x"));
|
|
1991
|
+
}
|
|
1992
|
+
set execute(v) {
|
|
1993
|
+
v ? this.methods.delete("n").delete("*").add("x") : this.methods.delete("x");
|
|
1994
|
+
}
|
|
2007
1995
|
/** Read method specified */
|
|
2008
1996
|
get read() {
|
|
2009
1997
|
return !this.methods.has("n") && (this.methods.has("*") || this.methods.has("r"));
|
|
@@ -2029,6 +2017,64 @@ ${opts.message || this.desc}`;
|
|
|
2029
2017
|
static clearCache() {
|
|
2030
2018
|
_PathEvent.pathEventCache.clear();
|
|
2031
2019
|
}
|
|
2020
|
+
/** Clear the permission cache */
|
|
2021
|
+
static clearPermissionCache() {
|
|
2022
|
+
_PathEvent.permissionCache.clear();
|
|
2023
|
+
}
|
|
2024
|
+
/**
|
|
2025
|
+
* Score a path for specificity ranking (lower = more specific = higher priority)
|
|
2026
|
+
* @private
|
|
2027
|
+
*/
|
|
2028
|
+
static scoreSpecificity(path) {
|
|
2029
|
+
if (path === "**" || path === "") return Number.MAX_SAFE_INTEGER;
|
|
2030
|
+
const segments = path.split("/").filter((p) => !!p);
|
|
2031
|
+
let score = -segments.length;
|
|
2032
|
+
segments.forEach((seg) => {
|
|
2033
|
+
if (seg === "**") score += 0.5;
|
|
2034
|
+
else if (seg === "*") score += 0.25;
|
|
2035
|
+
});
|
|
2036
|
+
return score;
|
|
2037
|
+
}
|
|
2038
|
+
/**
|
|
2039
|
+
* Check if a path matches a glob pattern
|
|
2040
|
+
* @private
|
|
2041
|
+
*/
|
|
2042
|
+
static pathMatchesGlob(path, pattern) {
|
|
2043
|
+
if (pattern === path) return true;
|
|
2044
|
+
const pathParts = path.split("/").filter((p) => !!p);
|
|
2045
|
+
const patternParts = pattern.split("/").filter((p) => !!p);
|
|
2046
|
+
let pathIdx = 0;
|
|
2047
|
+
let patternIdx = 0;
|
|
2048
|
+
while (patternIdx < patternParts.length && pathIdx < pathParts.length) {
|
|
2049
|
+
const patternPart = patternParts[patternIdx];
|
|
2050
|
+
if (patternPart === "**") {
|
|
2051
|
+
if (patternIdx === patternParts.length - 1) {
|
|
2052
|
+
return true;
|
|
2053
|
+
}
|
|
2054
|
+
patternParts[patternIdx + 1];
|
|
2055
|
+
while (pathIdx < pathParts.length) {
|
|
2056
|
+
if (_PathEvent.pathMatchesGlob(pathParts.slice(pathIdx).join("/"), patternParts.slice(patternIdx + 1).join("/"))) {
|
|
2057
|
+
return true;
|
|
2058
|
+
}
|
|
2059
|
+
pathIdx++;
|
|
2060
|
+
}
|
|
2061
|
+
return false;
|
|
2062
|
+
} else if (patternPart === "*") {
|
|
2063
|
+
pathIdx++;
|
|
2064
|
+
patternIdx++;
|
|
2065
|
+
} else {
|
|
2066
|
+
if (patternPart !== pathParts[pathIdx]) {
|
|
2067
|
+
return false;
|
|
2068
|
+
}
|
|
2069
|
+
pathIdx++;
|
|
2070
|
+
patternIdx++;
|
|
2071
|
+
}
|
|
2072
|
+
}
|
|
2073
|
+
if (patternIdx < patternParts.length) {
|
|
2074
|
+
return patternParts.slice(patternIdx).every((p) => p === "**");
|
|
2075
|
+
}
|
|
2076
|
+
return pathIdx === pathParts.length;
|
|
2077
|
+
}
|
|
2032
2078
|
/**
|
|
2033
2079
|
* Combine multiple events into one parsed object. Longest path takes precedent, but all subsequent methods are
|
|
2034
2080
|
* combined until a "none" is reached
|
|
@@ -2037,38 +2083,58 @@ ${opts.message || this.desc}`;
|
|
|
2037
2083
|
* @return {PathEvent} Final combined permission
|
|
2038
2084
|
*/
|
|
2039
2085
|
static combine(...paths) {
|
|
2040
|
-
|
|
2041
|
-
const
|
|
2042
|
-
const
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
if (
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2086
|
+
const parsed = paths.map((p) => p instanceof _PathEvent ? p : new _PathEvent(p));
|
|
2087
|
+
const sorted = parsed.toSorted((p1, p2) => {
|
|
2088
|
+
const score1 = _PathEvent.scoreSpecificity(p1.fullPath);
|
|
2089
|
+
const score2 = _PathEvent.scoreSpecificity(p2.fullPath);
|
|
2090
|
+
return score1 - score2;
|
|
2091
|
+
});
|
|
2092
|
+
let result = null;
|
|
2093
|
+
for (const p of sorted) {
|
|
2094
|
+
if (!result) {
|
|
2095
|
+
result = p;
|
|
2096
|
+
} else {
|
|
2097
|
+
if (result.fullPath.startsWith(p.fullPath)) {
|
|
2098
|
+
if (p.none) {
|
|
2099
|
+
break;
|
|
2100
|
+
}
|
|
2101
|
+
result.methods = new ASet([...result.methods, ...p.methods]);
|
|
2102
|
+
}
|
|
2103
|
+
}
|
|
2104
|
+
}
|
|
2105
|
+
return result || new _PathEvent("");
|
|
2053
2106
|
}
|
|
2054
2107
|
/**
|
|
2055
2108
|
* Filter a set of paths based on the target
|
|
2056
2109
|
*
|
|
2057
2110
|
* @param {string | PathEvent | (string | PathEvent)[]} target Array of events that will filtered
|
|
2058
|
-
* @param filter {...PathEvent} Must
|
|
2059
|
-
* @return {
|
|
2111
|
+
* @param filter {...PathEvent} Must contain one of
|
|
2112
|
+
* @return {PathEvent[]} Filtered results
|
|
2060
2113
|
*/
|
|
2061
2114
|
static filter(target, ...filter) {
|
|
2062
2115
|
const parsedTarget = makeArray(target).map((pe) => pe instanceof _PathEvent ? pe : new _PathEvent(pe));
|
|
2063
2116
|
const parsedFilter = makeArray(filter).map((pe) => pe instanceof _PathEvent ? pe : new _PathEvent(pe));
|
|
2064
|
-
return parsedTarget.filter((t) =>
|
|
2065
|
-
const
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2117
|
+
return parsedTarget.filter((t) => {
|
|
2118
|
+
const combined = _PathEvent.combine(t);
|
|
2119
|
+
return !!parsedFilter.find((r) => _PathEvent.matches(r, combined));
|
|
2120
|
+
});
|
|
2121
|
+
}
|
|
2122
|
+
/**
|
|
2123
|
+
* Check if a filter pattern matches a target path
|
|
2124
|
+
* @private
|
|
2125
|
+
*/
|
|
2126
|
+
static matches(pattern, target) {
|
|
2127
|
+
if (pattern.fullPath === "" || target.fullPath === "") return false;
|
|
2128
|
+
if (pattern.fullPath === "*" || target.fullPath === "*") return pattern.methods.has("*") || target.methods.has("*") || pattern.methods.intersection(target.methods).length > 0;
|
|
2129
|
+
const methodsMatch = pattern.all || target.all || pattern.methods.intersection(target.methods).length > 0;
|
|
2130
|
+
if (!methodsMatch) return false;
|
|
2131
|
+
if (!pattern.hasGlob && !target.hasGlob) {
|
|
2132
|
+
return pattern.fullPath === target.fullPath;
|
|
2133
|
+
}
|
|
2134
|
+
if (pattern.hasGlob) {
|
|
2135
|
+
return this.pathMatchesGlob(target.fullPath, pattern.fullPath);
|
|
2136
|
+
}
|
|
2137
|
+
return this.pathMatchesGlob(pattern.fullPath, target.fullPath);
|
|
2072
2138
|
}
|
|
2073
2139
|
/**
|
|
2074
2140
|
* Squash 2 sets of paths & return true if any overlap is found
|
|
@@ -2080,21 +2146,15 @@ ${opts.message || this.desc}`;
|
|
|
2080
2146
|
static has(target, ...has) {
|
|
2081
2147
|
const parsedTarget = makeArray(target).map((pe) => pe instanceof _PathEvent ? pe : new _PathEvent(pe));
|
|
2082
2148
|
const parsedRequired = makeArray(has).map((pe) => pe instanceof _PathEvent ? pe : new _PathEvent(pe));
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
const p1 = r.fullPath.includes("*") ? r.fullPath.slice(0, r.fullPath.indexOf("*")) : r.fullPath;
|
|
2086
|
-
const p2 = t.fullPath.includes("*") ? t.fullPath.slice(0, t.fullPath.indexOf("*")) : t.fullPath;
|
|
2087
|
-
const scope = p1.startsWith(p2);
|
|
2088
|
-
const methods = r.all || t.all || r.methods.intersection(t.methods).length;
|
|
2089
|
-
return (wildcard || scope) && methods;
|
|
2090
|
-
}));
|
|
2149
|
+
const effectiveTarget = parsedTarget.length === 1 ? parsedTarget[0] : _PathEvent.combine(...parsedTarget);
|
|
2150
|
+
return !!parsedRequired.find((r) => _PathEvent.matches(r, effectiveTarget));
|
|
2091
2151
|
}
|
|
2092
2152
|
/**
|
|
2093
2153
|
* Squash 2 sets of paths & return true if the target has all paths
|
|
2094
2154
|
*
|
|
2095
2155
|
* @param {string | PathEvent | (string | PathEvent)[]} target Array of Events as strings or pre-parsed
|
|
2096
2156
|
* @param has Target must have all these paths
|
|
2097
|
-
* @return {boolean} Whether
|
|
2157
|
+
* @return {boolean} Whether all are present
|
|
2098
2158
|
*/
|
|
2099
2159
|
static hasAll(target, ...has) {
|
|
2100
2160
|
return has.filter((h) => _PathEvent.has(target, h)).length == has.length;
|
|
@@ -2102,7 +2162,7 @@ ${opts.message || this.desc}`;
|
|
|
2102
2162
|
/**
|
|
2103
2163
|
* Same as `has` but raises an error if there is no overlap
|
|
2104
2164
|
*
|
|
2105
|
-
* @param {string | string[]} target Array of Events as strings or pre-parsed
|
|
2165
|
+
* @param {string | PathEvent | (string | PathEvent)[]} target Array of Events as strings or pre-parsed
|
|
2106
2166
|
* @param has Target must have at least one of these path
|
|
2107
2167
|
*/
|
|
2108
2168
|
static hasFatal(target, ...has) {
|
|
@@ -2111,7 +2171,7 @@ ${opts.message || this.desc}`;
|
|
|
2111
2171
|
/**
|
|
2112
2172
|
* Same as `hasAll` but raises an error if the target is missing any paths
|
|
2113
2173
|
*
|
|
2114
|
-
* @param {string | string[]} target Array of Events as strings or pre-parsed
|
|
2174
|
+
* @param {string | PathEvent | (string | PathEvent)[]} target Array of Events as strings or pre-parsed
|
|
2115
2175
|
* @param has Target must have all these paths
|
|
2116
2176
|
*/
|
|
2117
2177
|
static hasAllFatal(target, ...has) {
|
|
@@ -2143,7 +2203,7 @@ ${opts.message || this.desc}`;
|
|
|
2143
2203
|
* Squash 2 sets of paths & return true if the target has all paths
|
|
2144
2204
|
*
|
|
2145
2205
|
* @param has Target must have all these paths
|
|
2146
|
-
* @return {boolean} Whether
|
|
2206
|
+
* @return {boolean} Whether all are present
|
|
2147
2207
|
*/
|
|
2148
2208
|
hasAll(...has) {
|
|
2149
2209
|
return _PathEvent.hasAll(this, ...has);
|
|
@@ -2168,7 +2228,7 @@ ${opts.message || this.desc}`;
|
|
|
2168
2228
|
* Filter a set of paths based on this event
|
|
2169
2229
|
*
|
|
2170
2230
|
* @param {string | PathEvent | (string | PathEvent)[]} target Array of events that will filtered
|
|
2171
|
-
* @return {
|
|
2231
|
+
* @return {PathEvent[]} Filtered results
|
|
2172
2232
|
*/
|
|
2173
2233
|
filter(target) {
|
|
2174
2234
|
return _PathEvent.filter(target, this);
|
|
@@ -2184,6 +2244,10 @@ ${opts.message || this.desc}`;
|
|
|
2184
2244
|
};
|
|
2185
2245
|
/** Internal cache for PathEvent instances to avoid redundant parsing */
|
|
2186
2246
|
__publicField(_PathEvent, "pathEventCache", /* @__PURE__ */ new Map());
|
|
2247
|
+
/** Cache for compiled permissions (path + required permissions → result) */
|
|
2248
|
+
__publicField(_PathEvent, "permissionCache", /* @__PURE__ */ new Map());
|
|
2249
|
+
/** Max size for permission cache before LRU eviction */
|
|
2250
|
+
__publicField(_PathEvent, "MAX_PERMISSION_CACHE_SIZE", 1e3);
|
|
2187
2251
|
let PathEvent = _PathEvent;
|
|
2188
2252
|
class PathEventEmitter {
|
|
2189
2253
|
constructor(prefix = "") {
|
|
@@ -2192,16 +2256,27 @@ ${opts.message || this.desc}`;
|
|
|
2192
2256
|
}
|
|
2193
2257
|
emit(event, ...args) {
|
|
2194
2258
|
const parsed = event instanceof PathEvent ? event : new PathEvent(`${this.prefix}/${event}`);
|
|
2195
|
-
this.listeners.filter((l) => PathEvent.has(l[0], parsed)).forEach(
|
|
2259
|
+
this.listeners.filter((l) => PathEvent.has(l[0], parsed)).forEach((l) => l[1](parsed, ...args));
|
|
2196
2260
|
}
|
|
2197
2261
|
off(listener) {
|
|
2198
2262
|
this.listeners = this.listeners.filter((l) => l[1] != listener);
|
|
2199
2263
|
}
|
|
2200
2264
|
on(event, listener) {
|
|
2201
2265
|
makeArray(event).forEach((e) => {
|
|
2202
|
-
|
|
2266
|
+
let fullEvent;
|
|
2267
|
+
if (typeof e === "string") {
|
|
2268
|
+
if (e[0] === ":" && this.prefix) {
|
|
2269
|
+
fullEvent = `${this.prefix}${e}`;
|
|
2270
|
+
} else if (this.prefix) {
|
|
2271
|
+
fullEvent = `${this.prefix}/${e}`;
|
|
2272
|
+
} else {
|
|
2273
|
+
fullEvent = e;
|
|
2274
|
+
}
|
|
2275
|
+
} else {
|
|
2276
|
+
fullEvent = e instanceof PathEvent ? PathEvent.toString(e.fullPath, e.methods) : e;
|
|
2277
|
+
}
|
|
2203
2278
|
this.listeners.push([
|
|
2204
|
-
|
|
2279
|
+
new PathEvent(fullEvent),
|
|
2205
2280
|
listener
|
|
2206
2281
|
]);
|
|
2207
2282
|
});
|
|
@@ -2217,7 +2292,7 @@ ${opts.message || this.desc}`;
|
|
|
2217
2292
|
});
|
|
2218
2293
|
}
|
|
2219
2294
|
relayEvents(emitter) {
|
|
2220
|
-
emitter.on("
|
|
2295
|
+
emitter.on("**", (event, ...args) => this.emit(event, ...args));
|
|
2221
2296
|
}
|
|
2222
2297
|
}
|
|
2223
2298
|
function search(rows, search2, regex, transform = (r) => r) {
|
|
@@ -2426,7 +2501,7 @@ ${opts.message || this.desc}`;
|
|
|
2426
2501
|
}
|
|
2427
2502
|
}
|
|
2428
2503
|
memoryStorage.MemoryStorage = MemoryStorage;
|
|
2429
|
-
(function(
|
|
2504
|
+
(function(exports$1) {
|
|
2430
2505
|
var __createBinding = commonjsGlobal && commonjsGlobal.__createBinding || (Object.create ? function(o, m, k, k2) {
|
|
2431
2506
|
if (k2 === void 0) k2 = k;
|
|
2432
2507
|
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
@@ -2440,12 +2515,12 @@ ${opts.message || this.desc}`;
|
|
|
2440
2515
|
if (k2 === void 0) k2 = k;
|
|
2441
2516
|
o[k2] = m[k];
|
|
2442
2517
|
});
|
|
2443
|
-
var __exportStar = commonjsGlobal && commonjsGlobal.__exportStar || function(m,
|
|
2444
|
-
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(
|
|
2518
|
+
var __exportStar = commonjsGlobal && commonjsGlobal.__exportStar || function(m, exports$12) {
|
|
2519
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports$12, p)) __createBinding(exports$12, m, p);
|
|
2445
2520
|
};
|
|
2446
|
-
Object.defineProperty(
|
|
2447
|
-
__exportStar(persist$1,
|
|
2448
|
-
__exportStar(memoryStorage,
|
|
2521
|
+
Object.defineProperty(exports$1, "__esModule", { value: true });
|
|
2522
|
+
__exportStar(persist$1, exports$1);
|
|
2523
|
+
__exportStar(memoryStorage, exports$1);
|
|
2449
2524
|
})(dist);
|
|
2450
2525
|
exports2.ASet = ASet;
|
|
2451
2526
|
exports2.ArgParser = ArgParser;
|