namirasoft-core 1.5.2 → 1.5.3
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/SKILL.md +223 -223
- package/dist/TimeOperation.d.ts +1 -0
- package/dist/TimeOperation.js +4 -0
- package/dist/TimeOperation.js.map +1 -1
- package/package.json +26 -26
- package/src/BaseDatabaseRow.ts +6 -6
- package/src/BaseLogger.ts +24 -24
- package/src/BaseMetaColumn.ts +17 -17
- package/src/BaseMetaDatabase.ts +30 -30
- package/src/BaseMetaTable.ts +40 -40
- package/src/BaseServer.ts +150 -150
- package/src/BaseUUID.ts +76 -76
- package/src/ByteOperation.ts +57 -57
- package/src/CacheService.ts +76 -76
- package/src/ColorOperation.ts +153 -153
- package/src/ConsoleOperation.ts +68 -68
- package/src/ConvertService.ts +123 -123
- package/src/CookieService.ts +33 -33
- package/src/Countries.ts +486 -486
- package/src/Country.ts +21 -21
- package/src/CountryOperation.ts +98 -98
- package/src/CronOperation.ts +121 -121
- package/src/EncodingOperation.ts +46 -46
- package/src/EnvService.ts +28 -28
- package/src/ErrorOperation.ts +13 -13
- package/src/FileOperation.ts +60 -60
- package/src/FilterItem.ts +117 -117
- package/src/FilterItemColumnType.ts +9 -9
- package/src/FilterItemOperator.ts +52 -52
- package/src/GeoOperation.ts +18 -18
- package/src/HTTPError.ts +8 -8
- package/src/HTTPMethod.ts +7 -7
- package/src/HashOperation.ts +24 -24
- package/src/ILogger.ts +17 -17
- package/src/IStorage.ts +5 -5
- package/src/IStorageCookie.ts +52 -52
- package/src/IStorageJsonFile.ts +45 -45
- package/src/IStorageLocal.ts +16 -16
- package/src/IStorageMemoryDedicated.ts +17 -17
- package/src/IStorageMemoryShared.ts +21 -21
- package/src/IStorageSession.ts +16 -16
- package/src/LogLevel.ts +11 -11
- package/src/NamingConvention.ts +199 -199
- package/src/ObjectService.ts +27 -27
- package/src/PackageService.ts +76 -76
- package/src/PasswordOperation.ts +12 -12
- package/src/PhoneOperation.ts +8 -8
- package/src/PriceOperation.ts +20 -20
- package/src/SearchOperation.ts +31 -31
- package/src/SetTimeouService.ts +32 -32
- package/src/SortItem.ts +88 -88
- package/src/StringOperation.ts +22 -22
- package/src/TimeOperation.ts +303 -299
- package/src/TimeUnitOperation.ts +82 -82
- package/src/URLOperation.ts +66 -66
- package/src/VersionOperation.ts +46 -46
- package/src/index.ts +52 -52
package/src/Country.ts
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
|
-
export class Country
|
|
2
|
-
{
|
|
3
|
-
continent: string = "";
|
|
4
|
-
name: string = "";
|
|
5
|
-
iso2: string = "";
|
|
6
|
-
iso3: string = "";
|
|
7
|
-
code: string = "";
|
|
8
|
-
european_union: boolean = false;
|
|
9
|
-
coeff: number;
|
|
10
|
-
other: string[] = [];
|
|
11
|
-
constructor(continent: string, name: string, iso2: string, iso3: string, code: string, european_union: boolean, coeff: number, other: string[] = [])
|
|
12
|
-
{
|
|
13
|
-
this.continent = continent;
|
|
14
|
-
this.name = name;
|
|
15
|
-
this.iso2 = iso2;
|
|
16
|
-
this.iso3 = iso3;
|
|
17
|
-
this.code = code;
|
|
18
|
-
this.european_union = european_union;
|
|
19
|
-
this.coeff = coeff;
|
|
20
|
-
this.other = other;
|
|
21
|
-
}
|
|
1
|
+
export class Country
|
|
2
|
+
{
|
|
3
|
+
continent: string = "";
|
|
4
|
+
name: string = "";
|
|
5
|
+
iso2: string = "";
|
|
6
|
+
iso3: string = "";
|
|
7
|
+
code: string = "";
|
|
8
|
+
european_union: boolean = false;
|
|
9
|
+
coeff: number;
|
|
10
|
+
other: string[] = [];
|
|
11
|
+
constructor(continent: string, name: string, iso2: string, iso3: string, code: string, european_union: boolean, coeff: number, other: string[] = [])
|
|
12
|
+
{
|
|
13
|
+
this.continent = continent;
|
|
14
|
+
this.name = name;
|
|
15
|
+
this.iso2 = iso2;
|
|
16
|
+
this.iso3 = iso3;
|
|
17
|
+
this.code = code;
|
|
18
|
+
this.european_union = european_union;
|
|
19
|
+
this.coeff = coeff;
|
|
20
|
+
this.other = other;
|
|
21
|
+
}
|
|
22
22
|
}
|
package/src/CountryOperation.ts
CHANGED
|
@@ -1,99 +1,99 @@
|
|
|
1
|
-
import { Country } from "./Country";
|
|
2
|
-
import { Countries } from "./Countries";
|
|
3
|
-
|
|
4
|
-
export class CountryOperation
|
|
5
|
-
{
|
|
6
|
-
private static simplify(input: string): string
|
|
7
|
-
{
|
|
8
|
-
if (!input)
|
|
9
|
-
input = "";
|
|
10
|
-
let arr = [" ", ".", "/", "'", "\"", "?", "!", "-", "+", "_", '\$', "@", "%", " of ", " the ", " a ", " an "];
|
|
11
|
-
arr.map(pattern => input = input.split(pattern).join(""));
|
|
12
|
-
input = input.split("é").join("e");
|
|
13
|
-
return input.trim().toLowerCase();
|
|
14
|
-
}
|
|
15
|
-
static find(input: string): Country | null
|
|
16
|
-
{
|
|
17
|
-
if (!input)
|
|
18
|
-
input = "";
|
|
19
|
-
input = this.simplify(input);
|
|
20
|
-
if (input)
|
|
21
|
-
for (let country of Countries.getAll())
|
|
22
|
-
{
|
|
23
|
-
let values = [country.iso2, country.iso3, country.name];
|
|
24
|
-
if (input.startsWith(country.code))
|
|
25
|
-
return country;
|
|
26
|
-
if (country.other)
|
|
27
|
-
for (let i = 0; i < country.other.length; i++)
|
|
28
|
-
values.push(country.other[i]);
|
|
29
|
-
for (let i = 0; i < values.length; i++)
|
|
30
|
-
if (this.simplify(values[i]) === input)
|
|
31
|
-
return country;
|
|
32
|
-
}
|
|
33
|
-
return null;
|
|
34
|
-
}
|
|
35
|
-
static findPhone(input: string): Country[]
|
|
36
|
-
{
|
|
37
|
-
if (!input)
|
|
38
|
-
input = "";
|
|
39
|
-
input = this.simplify(input);
|
|
40
|
-
let ans = [];
|
|
41
|
-
let max = 0;
|
|
42
|
-
if (input)
|
|
43
|
-
for (let country of Countries.getAll())
|
|
44
|
-
if (input.startsWith(country.code))
|
|
45
|
-
{
|
|
46
|
-
ans.push(country);
|
|
47
|
-
max = Math.max(country.code.length, max);
|
|
48
|
-
}
|
|
49
|
-
let res = [];
|
|
50
|
-
for (let i = 0; i < ans.length; i++)
|
|
51
|
-
{
|
|
52
|
-
if (ans[i].code.length == max)
|
|
53
|
-
res.push(ans[i]);
|
|
54
|
-
}
|
|
55
|
-
return res;
|
|
56
|
-
}
|
|
57
|
-
static isPhoneFromCountry(input: string, country: Country | string | null)
|
|
58
|
-
{
|
|
59
|
-
if (country instanceof String)
|
|
60
|
-
country = this.find(country as string);
|
|
61
|
-
let countries = this.findPhone(input);
|
|
62
|
-
if (country)
|
|
63
|
-
for (let i = 0; i < countries.length; i++)
|
|
64
|
-
if (this.areEqual([countries[i], country]))
|
|
65
|
-
return true;
|
|
66
|
-
return false;
|
|
67
|
-
}
|
|
68
|
-
static areEqual(countries: (Country | string)[]): boolean
|
|
69
|
-
{
|
|
70
|
-
countries = countries.map(country =>
|
|
71
|
-
{
|
|
72
|
-
let c: Country | null = null;
|
|
73
|
-
if (country instanceof Country)
|
|
74
|
-
c = country;
|
|
75
|
-
else
|
|
76
|
-
c = this.find(country as string);
|
|
77
|
-
if (c)
|
|
78
|
-
return c.name;
|
|
79
|
-
throw new Error("Couldn't find country: " + country);
|
|
80
|
-
});
|
|
81
|
-
countries = countries.filter(v => v);
|
|
82
|
-
countries = countries.filter((v, i, a) => a.indexOf(v) === i);
|
|
83
|
-
return countries.length === 1;
|
|
84
|
-
}
|
|
85
|
-
static getCoeff(code: string, amount: number, times: number = 1): number
|
|
86
|
-
{
|
|
87
|
-
if (!times)
|
|
88
|
-
times = 1;
|
|
89
|
-
let country: Country | null = this.find(code);
|
|
90
|
-
let ans: number = country?.coeff ?? 0;
|
|
91
|
-
if (isNaN(ans))
|
|
92
|
-
ans = 0.1;
|
|
93
|
-
ans += Math.min(Math.max(1 - ans, 0), 1) * (times - 1) / times;
|
|
94
|
-
ans = Math.min(Math.max(ans, 0), 1);
|
|
95
|
-
if (amount)
|
|
96
|
-
ans = amount * ans;
|
|
97
|
-
return ans;
|
|
98
|
-
}
|
|
1
|
+
import { Country } from "./Country";
|
|
2
|
+
import { Countries } from "./Countries";
|
|
3
|
+
|
|
4
|
+
export class CountryOperation
|
|
5
|
+
{
|
|
6
|
+
private static simplify(input: string): string
|
|
7
|
+
{
|
|
8
|
+
if (!input)
|
|
9
|
+
input = "";
|
|
10
|
+
let arr = [" ", ".", "/", "'", "\"", "?", "!", "-", "+", "_", '\$', "@", "%", " of ", " the ", " a ", " an "];
|
|
11
|
+
arr.map(pattern => input = input.split(pattern).join(""));
|
|
12
|
+
input = input.split("é").join("e");
|
|
13
|
+
return input.trim().toLowerCase();
|
|
14
|
+
}
|
|
15
|
+
static find(input: string): Country | null
|
|
16
|
+
{
|
|
17
|
+
if (!input)
|
|
18
|
+
input = "";
|
|
19
|
+
input = this.simplify(input);
|
|
20
|
+
if (input)
|
|
21
|
+
for (let country of Countries.getAll())
|
|
22
|
+
{
|
|
23
|
+
let values = [country.iso2, country.iso3, country.name];
|
|
24
|
+
if (input.startsWith(country.code))
|
|
25
|
+
return country;
|
|
26
|
+
if (country.other)
|
|
27
|
+
for (let i = 0; i < country.other.length; i++)
|
|
28
|
+
values.push(country.other[i]);
|
|
29
|
+
for (let i = 0; i < values.length; i++)
|
|
30
|
+
if (this.simplify(values[i]) === input)
|
|
31
|
+
return country;
|
|
32
|
+
}
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
static findPhone(input: string): Country[]
|
|
36
|
+
{
|
|
37
|
+
if (!input)
|
|
38
|
+
input = "";
|
|
39
|
+
input = this.simplify(input);
|
|
40
|
+
let ans = [];
|
|
41
|
+
let max = 0;
|
|
42
|
+
if (input)
|
|
43
|
+
for (let country of Countries.getAll())
|
|
44
|
+
if (input.startsWith(country.code))
|
|
45
|
+
{
|
|
46
|
+
ans.push(country);
|
|
47
|
+
max = Math.max(country.code.length, max);
|
|
48
|
+
}
|
|
49
|
+
let res = [];
|
|
50
|
+
for (let i = 0; i < ans.length; i++)
|
|
51
|
+
{
|
|
52
|
+
if (ans[i].code.length == max)
|
|
53
|
+
res.push(ans[i]);
|
|
54
|
+
}
|
|
55
|
+
return res;
|
|
56
|
+
}
|
|
57
|
+
static isPhoneFromCountry(input: string, country: Country | string | null)
|
|
58
|
+
{
|
|
59
|
+
if (country instanceof String)
|
|
60
|
+
country = this.find(country as string);
|
|
61
|
+
let countries = this.findPhone(input);
|
|
62
|
+
if (country)
|
|
63
|
+
for (let i = 0; i < countries.length; i++)
|
|
64
|
+
if (this.areEqual([countries[i], country]))
|
|
65
|
+
return true;
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
static areEqual(countries: (Country | string)[]): boolean
|
|
69
|
+
{
|
|
70
|
+
countries = countries.map(country =>
|
|
71
|
+
{
|
|
72
|
+
let c: Country | null = null;
|
|
73
|
+
if (country instanceof Country)
|
|
74
|
+
c = country;
|
|
75
|
+
else
|
|
76
|
+
c = this.find(country as string);
|
|
77
|
+
if (c)
|
|
78
|
+
return c.name;
|
|
79
|
+
throw new Error("Couldn't find country: " + country);
|
|
80
|
+
});
|
|
81
|
+
countries = countries.filter(v => v);
|
|
82
|
+
countries = countries.filter((v, i, a) => a.indexOf(v) === i);
|
|
83
|
+
return countries.length === 1;
|
|
84
|
+
}
|
|
85
|
+
static getCoeff(code: string, amount: number, times: number = 1): number
|
|
86
|
+
{
|
|
87
|
+
if (!times)
|
|
88
|
+
times = 1;
|
|
89
|
+
let country: Country | null = this.find(code);
|
|
90
|
+
let ans: number = country?.coeff ?? 0;
|
|
91
|
+
if (isNaN(ans))
|
|
92
|
+
ans = 0.1;
|
|
93
|
+
ans += Math.min(Math.max(1 - ans, 0), 1) * (times - 1) / times;
|
|
94
|
+
ans = Math.min(Math.max(ans, 0), 1);
|
|
95
|
+
if (amount)
|
|
96
|
+
ans = amount * ans;
|
|
97
|
+
return ans;
|
|
98
|
+
}
|
|
99
99
|
}
|
package/src/CronOperation.ts
CHANGED
|
@@ -1,122 +1,122 @@
|
|
|
1
|
-
export class CronOperation
|
|
2
|
-
{
|
|
3
|
-
static splitPatterns(pattern: string): string[]
|
|
4
|
-
{
|
|
5
|
-
return pattern.split(',').map(p => p.trim()).filter(p => p);
|
|
6
|
-
}
|
|
7
|
-
static isValid(pattern: string): boolean
|
|
8
|
-
{
|
|
9
|
-
let patterns = CronOperation.splitPatterns(pattern);
|
|
10
|
-
if (patterns.length == 0)
|
|
11
|
-
return false;
|
|
12
|
-
if (patterns.length == 1)
|
|
13
|
-
{
|
|
14
|
-
let regexes = [/\*[/\d+]/gm, /\d+[/\d+]/gm, /\d+-\d+[/\d+]/gm]
|
|
15
|
-
for (let i = 0; i < regexes.length; i++)
|
|
16
|
-
if (regexes[i].test(patterns[0]))
|
|
17
|
-
return true;
|
|
18
|
-
return false;
|
|
19
|
-
}
|
|
20
|
-
for (let i = 0; i < patterns.length; i++)
|
|
21
|
-
if (!CronOperation.isValid(patterns[i]))
|
|
22
|
-
return false;
|
|
23
|
-
return true;
|
|
24
|
-
}
|
|
25
|
-
static check(pattern: string): void
|
|
26
|
-
{
|
|
27
|
-
if (!CronOperation.isValid(pattern))
|
|
28
|
-
throw new Error("Invalid schedule/cron format. Use one of: *, */5, 8, 0-10, 2-10/3, or a comma-separated list (e.g. 0,4,5-10/2).");
|
|
29
|
-
}
|
|
30
|
-
static getNumbers(pattern: string, min: number, max: number): number[]
|
|
31
|
-
{
|
|
32
|
-
let patterns = CronOperation.splitPatterns(pattern);
|
|
33
|
-
let ans: number[] = [];
|
|
34
|
-
for (let i = 0; i < patterns.length; i++)
|
|
35
|
-
{
|
|
36
|
-
const element = patterns[i];
|
|
37
|
-
let ts = element.split('/').map(p => p.trim());
|
|
38
|
-
let step = ts.length == 1 ? 1 : parseInt(ts[1]);
|
|
39
|
-
if (element.includes("-"))
|
|
40
|
-
{
|
|
41
|
-
let ns = element.split('-').map(p => p.trim());
|
|
42
|
-
let from = parseInt(ns[0]);
|
|
43
|
-
let to = parseInt(ns[1]);
|
|
44
|
-
for (let p = from; p <= to; p += step)
|
|
45
|
-
ans.push(p);
|
|
46
|
-
}
|
|
47
|
-
else if (element.includes("*"))
|
|
48
|
-
for (let p = min; p <= max; p += step)
|
|
49
|
-
ans.push(p);
|
|
50
|
-
else
|
|
51
|
-
ans.push(parseInt(element));
|
|
52
|
-
}
|
|
53
|
-
ans = ans.sort();
|
|
54
|
-
ans.forEach(p =>
|
|
55
|
-
{
|
|
56
|
-
if (p < min)
|
|
57
|
-
throw new Error(`Number must be more than or equal to ${min}`);
|
|
58
|
-
if (p > max)
|
|
59
|
-
throw new Error(`Number must be less than or equal to ${max}`);
|
|
60
|
-
});
|
|
61
|
-
return ans;
|
|
62
|
-
}
|
|
63
|
-
static getNext(current: number, pattern: string, min: number, max?: number): { next: number, reset: boolean }
|
|
64
|
-
{
|
|
65
|
-
function getNextLoop(current: number, start: number, end: number | undefined, step: number)
|
|
66
|
-
{
|
|
67
|
-
if (current < start)
|
|
68
|
-
return start;
|
|
69
|
-
const offset = Math.ceil((current - start + 1) / step) * step;
|
|
70
|
-
const next = start + offset;
|
|
71
|
-
if (end == null)
|
|
72
|
-
return next;
|
|
73
|
-
return next > end ? start : next;
|
|
74
|
-
}
|
|
75
|
-
function forwardDistance(current: number, candidate: number, min: number, max?: number): number
|
|
76
|
-
{
|
|
77
|
-
if (max == null)
|
|
78
|
-
return candidate > current ? candidate - current : Infinity;
|
|
79
|
-
const ring = max - min + 1;
|
|
80
|
-
const curIdx = current - min;
|
|
81
|
-
const candIdx = candidate - min;
|
|
82
|
-
let dist = (candIdx - curIdx + ring) % ring;
|
|
83
|
-
if (dist === 0)
|
|
84
|
-
dist = ring;
|
|
85
|
-
return dist;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
let patterns = CronOperation.splitPatterns(pattern);
|
|
89
|
-
let ans: number | null = null;
|
|
90
|
-
let bestDist = Infinity;
|
|
91
|
-
for (let i = 0; i < patterns.length; i++)
|
|
92
|
-
{
|
|
93
|
-
const element = patterns[i];
|
|
94
|
-
let ts = element.split('/').map(p => p.trim());
|
|
95
|
-
let step = ts.length == 1 ? 1 : parseInt(ts[1]);
|
|
96
|
-
let candidate: number;
|
|
97
|
-
if (element.includes("-"))
|
|
98
|
-
{
|
|
99
|
-
let ns = element.split('-').map(p => p.trim());
|
|
100
|
-
let start = Math.max(min, parseInt(ns[0]));
|
|
101
|
-
let end = Math.min(max ?? parseInt(ns[1]), parseInt(ns[1]));
|
|
102
|
-
candidate = getNextLoop(current, start, end, step);
|
|
103
|
-
}
|
|
104
|
-
else if (element.includes("*"))
|
|
105
|
-
candidate = getNextLoop(current, min, max, step);
|
|
106
|
-
else
|
|
107
|
-
candidate = parseInt(element);
|
|
108
|
-
|
|
109
|
-
const dist = forwardDistance(current, candidate, min, max);
|
|
110
|
-
|
|
111
|
-
if (dist < bestDist)
|
|
112
|
-
{
|
|
113
|
-
bestDist = dist;
|
|
114
|
-
ans = candidate;
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
let reset = false;
|
|
118
|
-
if (ans != null)
|
|
119
|
-
reset = ans <= current;
|
|
120
|
-
return { next: ans ?? current, reset };
|
|
121
|
-
}
|
|
1
|
+
export class CronOperation
|
|
2
|
+
{
|
|
3
|
+
static splitPatterns(pattern: string): string[]
|
|
4
|
+
{
|
|
5
|
+
return pattern.split(',').map(p => p.trim()).filter(p => p);
|
|
6
|
+
}
|
|
7
|
+
static isValid(pattern: string): boolean
|
|
8
|
+
{
|
|
9
|
+
let patterns = CronOperation.splitPatterns(pattern);
|
|
10
|
+
if (patterns.length == 0)
|
|
11
|
+
return false;
|
|
12
|
+
if (patterns.length == 1)
|
|
13
|
+
{
|
|
14
|
+
let regexes = [/\*[/\d+]/gm, /\d+[/\d+]/gm, /\d+-\d+[/\d+]/gm]
|
|
15
|
+
for (let i = 0; i < regexes.length; i++)
|
|
16
|
+
if (regexes[i].test(patterns[0]))
|
|
17
|
+
return true;
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
for (let i = 0; i < patterns.length; i++)
|
|
21
|
+
if (!CronOperation.isValid(patterns[i]))
|
|
22
|
+
return false;
|
|
23
|
+
return true;
|
|
24
|
+
}
|
|
25
|
+
static check(pattern: string): void
|
|
26
|
+
{
|
|
27
|
+
if (!CronOperation.isValid(pattern))
|
|
28
|
+
throw new Error("Invalid schedule/cron format. Use one of: *, */5, 8, 0-10, 2-10/3, or a comma-separated list (e.g. 0,4,5-10/2).");
|
|
29
|
+
}
|
|
30
|
+
static getNumbers(pattern: string, min: number, max: number): number[]
|
|
31
|
+
{
|
|
32
|
+
let patterns = CronOperation.splitPatterns(pattern);
|
|
33
|
+
let ans: number[] = [];
|
|
34
|
+
for (let i = 0; i < patterns.length; i++)
|
|
35
|
+
{
|
|
36
|
+
const element = patterns[i];
|
|
37
|
+
let ts = element.split('/').map(p => p.trim());
|
|
38
|
+
let step = ts.length == 1 ? 1 : parseInt(ts[1]);
|
|
39
|
+
if (element.includes("-"))
|
|
40
|
+
{
|
|
41
|
+
let ns = element.split('-').map(p => p.trim());
|
|
42
|
+
let from = parseInt(ns[0]);
|
|
43
|
+
let to = parseInt(ns[1]);
|
|
44
|
+
for (let p = from; p <= to; p += step)
|
|
45
|
+
ans.push(p);
|
|
46
|
+
}
|
|
47
|
+
else if (element.includes("*"))
|
|
48
|
+
for (let p = min; p <= max; p += step)
|
|
49
|
+
ans.push(p);
|
|
50
|
+
else
|
|
51
|
+
ans.push(parseInt(element));
|
|
52
|
+
}
|
|
53
|
+
ans = ans.sort();
|
|
54
|
+
ans.forEach(p =>
|
|
55
|
+
{
|
|
56
|
+
if (p < min)
|
|
57
|
+
throw new Error(`Number must be more than or equal to ${min}`);
|
|
58
|
+
if (p > max)
|
|
59
|
+
throw new Error(`Number must be less than or equal to ${max}`);
|
|
60
|
+
});
|
|
61
|
+
return ans;
|
|
62
|
+
}
|
|
63
|
+
static getNext(current: number, pattern: string, min: number, max?: number): { next: number, reset: boolean }
|
|
64
|
+
{
|
|
65
|
+
function getNextLoop(current: number, start: number, end: number | undefined, step: number)
|
|
66
|
+
{
|
|
67
|
+
if (current < start)
|
|
68
|
+
return start;
|
|
69
|
+
const offset = Math.ceil((current - start + 1) / step) * step;
|
|
70
|
+
const next = start + offset;
|
|
71
|
+
if (end == null)
|
|
72
|
+
return next;
|
|
73
|
+
return next > end ? start : next;
|
|
74
|
+
}
|
|
75
|
+
function forwardDistance(current: number, candidate: number, min: number, max?: number): number
|
|
76
|
+
{
|
|
77
|
+
if (max == null)
|
|
78
|
+
return candidate > current ? candidate - current : Infinity;
|
|
79
|
+
const ring = max - min + 1;
|
|
80
|
+
const curIdx = current - min;
|
|
81
|
+
const candIdx = candidate - min;
|
|
82
|
+
let dist = (candIdx - curIdx + ring) % ring;
|
|
83
|
+
if (dist === 0)
|
|
84
|
+
dist = ring;
|
|
85
|
+
return dist;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
let patterns = CronOperation.splitPatterns(pattern);
|
|
89
|
+
let ans: number | null = null;
|
|
90
|
+
let bestDist = Infinity;
|
|
91
|
+
for (let i = 0; i < patterns.length; i++)
|
|
92
|
+
{
|
|
93
|
+
const element = patterns[i];
|
|
94
|
+
let ts = element.split('/').map(p => p.trim());
|
|
95
|
+
let step = ts.length == 1 ? 1 : parseInt(ts[1]);
|
|
96
|
+
let candidate: number;
|
|
97
|
+
if (element.includes("-"))
|
|
98
|
+
{
|
|
99
|
+
let ns = element.split('-').map(p => p.trim());
|
|
100
|
+
let start = Math.max(min, parseInt(ns[0]));
|
|
101
|
+
let end = Math.min(max ?? parseInt(ns[1]), parseInt(ns[1]));
|
|
102
|
+
candidate = getNextLoop(current, start, end, step);
|
|
103
|
+
}
|
|
104
|
+
else if (element.includes("*"))
|
|
105
|
+
candidate = getNextLoop(current, min, max, step);
|
|
106
|
+
else
|
|
107
|
+
candidate = parseInt(element);
|
|
108
|
+
|
|
109
|
+
const dist = forwardDistance(current, candidate, min, max);
|
|
110
|
+
|
|
111
|
+
if (dist < bestDist)
|
|
112
|
+
{
|
|
113
|
+
bestDist = dist;
|
|
114
|
+
ans = candidate;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
let reset = false;
|
|
118
|
+
if (ans != null)
|
|
119
|
+
reset = ans <= current;
|
|
120
|
+
return { next: ans ?? current, reset };
|
|
121
|
+
}
|
|
122
122
|
}
|
package/src/EncodingOperation.ts
CHANGED
|
@@ -1,47 +1,47 @@
|
|
|
1
|
-
export enum EncodingOperationPartType
|
|
2
|
-
{
|
|
3
|
-
Text = "text",
|
|
4
|
-
Key = "key",
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
export type EncodingOperationPart =
|
|
8
|
-
| { type: EncodingOperationPartType.Text; text: string }
|
|
9
|
-
| { type: EncodingOperationPartType.Key; key: string; value: string };
|
|
10
|
-
|
|
11
|
-
export class EncodingOperation
|
|
12
|
-
{
|
|
13
|
-
static Base64Encode(message: string): string
|
|
14
|
-
{
|
|
15
|
-
const bytes = new TextEncoder().encode(message);
|
|
16
|
-
let binary = "";
|
|
17
|
-
bytes.forEach(b => binary += String.fromCharCode(b));
|
|
18
|
-
return btoa(binary);
|
|
19
|
-
}
|
|
20
|
-
static Base64Decode(message: string): string
|
|
21
|
-
{
|
|
22
|
-
const binary = atob(message);
|
|
23
|
-
const bytes = Uint8Array.from(binary, c => c.charCodeAt(0));
|
|
24
|
-
return new TextDecoder().decode(bytes);
|
|
25
|
-
}
|
|
26
|
-
static VariableToStringEncode(key: string, value: string): string
|
|
27
|
-
{
|
|
28
|
-
return `\${${key}:${value}}`;
|
|
29
|
-
}
|
|
30
|
-
static VariableToStringDecode(key: string, text: string): EncodingOperationPart[]
|
|
31
|
-
{
|
|
32
|
-
let parts: EncodingOperationPart[] = [];
|
|
33
|
-
let regex = new RegExp(`\\\$\\{${key}:([^}]+)\\}`, "g");
|
|
34
|
-
let last = 0;
|
|
35
|
-
let match: RegExpExecArray | null;
|
|
36
|
-
while ((match = regex.exec(text)) !== null)
|
|
37
|
-
{
|
|
38
|
-
if (match.index > last)
|
|
39
|
-
parts.push({ type: EncodingOperationPartType.Text, text: text.substring(last, match.index) });
|
|
40
|
-
parts.push({ type: EncodingOperationPartType.Key, key, value: match[1] });
|
|
41
|
-
last = match.index + match[0].length;
|
|
42
|
-
}
|
|
43
|
-
if (last < text.length)
|
|
44
|
-
parts.push({ type: EncodingOperationPartType.Text, text: text.substring(last) });
|
|
45
|
-
return parts;
|
|
46
|
-
}
|
|
1
|
+
export enum EncodingOperationPartType
|
|
2
|
+
{
|
|
3
|
+
Text = "text",
|
|
4
|
+
Key = "key",
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export type EncodingOperationPart =
|
|
8
|
+
| { type: EncodingOperationPartType.Text; text: string }
|
|
9
|
+
| { type: EncodingOperationPartType.Key; key: string; value: string };
|
|
10
|
+
|
|
11
|
+
export class EncodingOperation
|
|
12
|
+
{
|
|
13
|
+
static Base64Encode(message: string): string
|
|
14
|
+
{
|
|
15
|
+
const bytes = new TextEncoder().encode(message);
|
|
16
|
+
let binary = "";
|
|
17
|
+
bytes.forEach(b => binary += String.fromCharCode(b));
|
|
18
|
+
return btoa(binary);
|
|
19
|
+
}
|
|
20
|
+
static Base64Decode(message: string): string
|
|
21
|
+
{
|
|
22
|
+
const binary = atob(message);
|
|
23
|
+
const bytes = Uint8Array.from(binary, c => c.charCodeAt(0));
|
|
24
|
+
return new TextDecoder().decode(bytes);
|
|
25
|
+
}
|
|
26
|
+
static VariableToStringEncode(key: string, value: string): string
|
|
27
|
+
{
|
|
28
|
+
return `\${${key}:${value}}`;
|
|
29
|
+
}
|
|
30
|
+
static VariableToStringDecode(key: string, text: string): EncodingOperationPart[]
|
|
31
|
+
{
|
|
32
|
+
let parts: EncodingOperationPart[] = [];
|
|
33
|
+
let regex = new RegExp(`\\\$\\{${key}:([^}]+)\\}`, "g");
|
|
34
|
+
let last = 0;
|
|
35
|
+
let match: RegExpExecArray | null;
|
|
36
|
+
while ((match = regex.exec(text)) !== null)
|
|
37
|
+
{
|
|
38
|
+
if (match.index > last)
|
|
39
|
+
parts.push({ type: EncodingOperationPartType.Text, text: text.substring(last, match.index) });
|
|
40
|
+
parts.push({ type: EncodingOperationPartType.Key, key, value: match[1] });
|
|
41
|
+
last = match.index + match[0].length;
|
|
42
|
+
}
|
|
43
|
+
if (last < text.length)
|
|
44
|
+
parts.push({ type: EncodingOperationPartType.Text, text: text.substring(last) });
|
|
45
|
+
return parts;
|
|
46
|
+
}
|
|
47
47
|
}
|
package/src/EnvService.ts
CHANGED
|
@@ -1,29 +1,29 @@
|
|
|
1
|
-
import { ConvertService } from "./ConvertService";
|
|
2
|
-
|
|
3
|
-
export class EnvService extends ConvertService
|
|
4
|
-
{
|
|
5
|
-
static isDebugMode()
|
|
6
|
-
{
|
|
7
|
-
let DEBUG = new EnvService("DEBUG", false).getBoolean(false);
|
|
8
|
-
let REACT_DEBUG = new EnvService("REACT_DEBUG", false).getBoolean(false);
|
|
9
|
-
return DEBUG || REACT_DEBUG;
|
|
10
|
-
}
|
|
11
|
-
name: string;
|
|
12
|
-
constructor(name: string, mandatory: boolean = false)
|
|
13
|
-
{
|
|
14
|
-
super(mandatory);
|
|
15
|
-
this.name = name;
|
|
16
|
-
}
|
|
17
|
-
override getNullString()
|
|
18
|
-
{
|
|
19
|
-
let ans = process.env[this.name];
|
|
20
|
-
if (ans)
|
|
21
|
-
return ans;
|
|
22
|
-
return null;
|
|
23
|
-
}
|
|
24
|
-
protected override onMandatoryError(): void
|
|
25
|
-
{
|
|
26
|
-
if (!process.env.NAMIRASOFT_MUTE)
|
|
27
|
-
throw new Error(`Env value was not provided: ${this.name}`);
|
|
28
|
-
}
|
|
1
|
+
import { ConvertService } from "./ConvertService";
|
|
2
|
+
|
|
3
|
+
export class EnvService extends ConvertService
|
|
4
|
+
{
|
|
5
|
+
static isDebugMode()
|
|
6
|
+
{
|
|
7
|
+
let DEBUG = new EnvService("DEBUG", false).getBoolean(false);
|
|
8
|
+
let REACT_DEBUG = new EnvService("REACT_DEBUG", false).getBoolean(false);
|
|
9
|
+
return DEBUG || REACT_DEBUG;
|
|
10
|
+
}
|
|
11
|
+
name: string;
|
|
12
|
+
constructor(name: string, mandatory: boolean = false)
|
|
13
|
+
{
|
|
14
|
+
super(mandatory);
|
|
15
|
+
this.name = name;
|
|
16
|
+
}
|
|
17
|
+
override getNullString()
|
|
18
|
+
{
|
|
19
|
+
let ans = process.env[this.name];
|
|
20
|
+
if (ans)
|
|
21
|
+
return ans;
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
protected override onMandatoryError(): void
|
|
25
|
+
{
|
|
26
|
+
if (!process.env.NAMIRASOFT_MUTE)
|
|
27
|
+
throw new Error(`Env value was not provided: ${this.name}`);
|
|
28
|
+
}
|
|
29
29
|
}
|
package/src/ErrorOperation.ts
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import { HTTPError } from "./HTTPError";
|
|
2
|
-
import { StringOperation } from "./StringOperation";
|
|
3
|
-
|
|
4
|
-
export class ErrorOperation
|
|
5
|
-
{
|
|
6
|
-
static throwHTTP(code: number, message: string, ...args: string[])
|
|
7
|
-
{
|
|
8
|
-
throw this.getHTTP(code, message, ...args);
|
|
9
|
-
}
|
|
10
|
-
static getHTTP(code: number, message: string, ...args: string[])
|
|
11
|
-
{
|
|
12
|
-
return new HTTPError(code, StringOperation.format(message, ...args));
|
|
13
|
-
}
|
|
1
|
+
import { HTTPError } from "./HTTPError";
|
|
2
|
+
import { StringOperation } from "./StringOperation";
|
|
3
|
+
|
|
4
|
+
export class ErrorOperation
|
|
5
|
+
{
|
|
6
|
+
static throwHTTP(code: number, message: string, ...args: string[])
|
|
7
|
+
{
|
|
8
|
+
throw this.getHTTP(code, message, ...args);
|
|
9
|
+
}
|
|
10
|
+
static getHTTP(code: number, message: string, ...args: string[])
|
|
11
|
+
{
|
|
12
|
+
return new HTTPError(code, StringOperation.format(message, ...args));
|
|
13
|
+
}
|
|
14
14
|
}
|