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/BaseUUID.ts
CHANGED
|
@@ -1,77 +1,77 @@
|
|
|
1
|
-
import { NIL, v4, v5 } from "uuid";
|
|
2
|
-
|
|
3
|
-
export class BaseUUID
|
|
4
|
-
{
|
|
5
|
-
public static SIZE = 20;
|
|
6
|
-
static isValid(id: any): boolean
|
|
7
|
-
{
|
|
8
|
-
let value = (id ?? "") + "";
|
|
9
|
-
if (value.length != BaseUUID.SIZE)
|
|
10
|
-
return false;
|
|
11
|
-
let parts = id.split("@")[0].split("-");
|
|
12
|
-
if (parts.length < 2)
|
|
13
|
-
return false;
|
|
14
|
-
return /^[a-z][a-z][a-z]$/.test(parts[0]);
|
|
15
|
-
}
|
|
16
|
-
static isValidShort(id: string, short: string): boolean
|
|
17
|
-
{
|
|
18
|
-
if (BaseUUID.isValid(id))
|
|
19
|
-
return BaseUUID.getShort(id) === short;
|
|
20
|
-
return false;
|
|
21
|
-
}
|
|
22
|
-
static getShort(id: string)
|
|
23
|
-
{
|
|
24
|
-
let parts = (id ?? "").split("@")[0].split("-");
|
|
25
|
-
let ans = [];
|
|
26
|
-
for (let index = 0; index < parts.length - 1; index++)
|
|
27
|
-
{
|
|
28
|
-
const part = parts[index];
|
|
29
|
-
if (/^[a-z][a-z][a-z]$/.test(part))
|
|
30
|
-
ans.push(part);
|
|
31
|
-
else
|
|
32
|
-
break;
|
|
33
|
-
}
|
|
34
|
-
return ans.join("-");
|
|
35
|
-
}
|
|
36
|
-
short: string;
|
|
37
|
-
lenght: number
|
|
38
|
-
constructor(short: string, lenght?: number)
|
|
39
|
-
{
|
|
40
|
-
this.short = short;
|
|
41
|
-
this.lenght = lenght ?? BaseUUID.SIZE;
|
|
42
|
-
}
|
|
43
|
-
static uuid(lenght?: number, seed?: string): string
|
|
44
|
-
{
|
|
45
|
-
if (!lenght)
|
|
46
|
-
lenght = BaseUUID.SIZE;
|
|
47
|
-
let value = null;
|
|
48
|
-
if (seed)
|
|
49
|
-
{
|
|
50
|
-
value = v5(seed, NIL);
|
|
51
|
-
}
|
|
52
|
-
else
|
|
53
|
-
value = v4();
|
|
54
|
-
let ans = value.replace(/-/g, '');
|
|
55
|
-
while (ans.length < lenght)
|
|
56
|
-
ans += this.uuid(BaseUUID.SIZE, seed);
|
|
57
|
-
ans = ans.substring(0, lenght);
|
|
58
|
-
return ans;
|
|
59
|
-
}
|
|
60
|
-
static isChild(id: string): boolean
|
|
61
|
-
{
|
|
62
|
-
let index = id.indexOf("@")
|
|
63
|
-
return index != -1;
|
|
64
|
-
}
|
|
65
|
-
static changeToChild(owner_id: string, name: string): string
|
|
66
|
-
{
|
|
67
|
-
let index = owner_id.indexOf("@")
|
|
68
|
-
if (index != -1)
|
|
69
|
-
return owner_id.substring(0, index + 1) + name.substring(0, BaseUUID.SIZE - index - 1).padStart(BaseUUID.SIZE - index - 1, '-');
|
|
70
|
-
return "";
|
|
71
|
-
}
|
|
72
|
-
new(seed?: string, lenght?: number)
|
|
73
|
-
{
|
|
74
|
-
let ans = this.short + "-" + BaseUUID.uuid(BaseUUID.SIZE, seed);
|
|
75
|
-
return ans.substring(0, lenght ?? this.lenght);
|
|
76
|
-
}
|
|
1
|
+
import { NIL, v4, v5 } from "uuid";
|
|
2
|
+
|
|
3
|
+
export class BaseUUID
|
|
4
|
+
{
|
|
5
|
+
public static SIZE = 20;
|
|
6
|
+
static isValid(id: any): boolean
|
|
7
|
+
{
|
|
8
|
+
let value = (id ?? "") + "";
|
|
9
|
+
if (value.length != BaseUUID.SIZE)
|
|
10
|
+
return false;
|
|
11
|
+
let parts = id.split("@")[0].split("-");
|
|
12
|
+
if (parts.length < 2)
|
|
13
|
+
return false;
|
|
14
|
+
return /^[a-z][a-z][a-z]$/.test(parts[0]);
|
|
15
|
+
}
|
|
16
|
+
static isValidShort(id: string, short: string): boolean
|
|
17
|
+
{
|
|
18
|
+
if (BaseUUID.isValid(id))
|
|
19
|
+
return BaseUUID.getShort(id) === short;
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
static getShort(id: string)
|
|
23
|
+
{
|
|
24
|
+
let parts = (id ?? "").split("@")[0].split("-");
|
|
25
|
+
let ans = [];
|
|
26
|
+
for (let index = 0; index < parts.length - 1; index++)
|
|
27
|
+
{
|
|
28
|
+
const part = parts[index];
|
|
29
|
+
if (/^[a-z][a-z][a-z]$/.test(part))
|
|
30
|
+
ans.push(part);
|
|
31
|
+
else
|
|
32
|
+
break;
|
|
33
|
+
}
|
|
34
|
+
return ans.join("-");
|
|
35
|
+
}
|
|
36
|
+
short: string;
|
|
37
|
+
lenght: number
|
|
38
|
+
constructor(short: string, lenght?: number)
|
|
39
|
+
{
|
|
40
|
+
this.short = short;
|
|
41
|
+
this.lenght = lenght ?? BaseUUID.SIZE;
|
|
42
|
+
}
|
|
43
|
+
static uuid(lenght?: number, seed?: string): string
|
|
44
|
+
{
|
|
45
|
+
if (!lenght)
|
|
46
|
+
lenght = BaseUUID.SIZE;
|
|
47
|
+
let value = null;
|
|
48
|
+
if (seed)
|
|
49
|
+
{
|
|
50
|
+
value = v5(seed, NIL);
|
|
51
|
+
}
|
|
52
|
+
else
|
|
53
|
+
value = v4();
|
|
54
|
+
let ans = value.replace(/-/g, '');
|
|
55
|
+
while (ans.length < lenght)
|
|
56
|
+
ans += this.uuid(BaseUUID.SIZE, seed);
|
|
57
|
+
ans = ans.substring(0, lenght);
|
|
58
|
+
return ans;
|
|
59
|
+
}
|
|
60
|
+
static isChild(id: string): boolean
|
|
61
|
+
{
|
|
62
|
+
let index = id.indexOf("@")
|
|
63
|
+
return index != -1;
|
|
64
|
+
}
|
|
65
|
+
static changeToChild(owner_id: string, name: string): string
|
|
66
|
+
{
|
|
67
|
+
let index = owner_id.indexOf("@")
|
|
68
|
+
if (index != -1)
|
|
69
|
+
return owner_id.substring(0, index + 1) + name.substring(0, BaseUUID.SIZE - index - 1).padStart(BaseUUID.SIZE - index - 1, '-');
|
|
70
|
+
return "";
|
|
71
|
+
}
|
|
72
|
+
new(seed?: string, lenght?: number)
|
|
73
|
+
{
|
|
74
|
+
let ans = this.short + "-" + BaseUUID.uuid(BaseUUID.SIZE, seed);
|
|
75
|
+
return ans.substring(0, lenght ?? this.lenght);
|
|
76
|
+
}
|
|
77
77
|
};
|
package/src/ByteOperation.ts
CHANGED
|
@@ -1,58 +1,58 @@
|
|
|
1
|
-
export enum ByteUnit
|
|
2
|
-
{
|
|
3
|
-
B = "B",
|
|
4
|
-
KB = "KB",
|
|
5
|
-
MB = "MB",
|
|
6
|
-
GB = "GB",
|
|
7
|
-
TB = "TB",
|
|
8
|
-
PB = "PB",
|
|
9
|
-
};
|
|
10
|
-
|
|
11
|
-
const SIGN_TO_NUMBER: Record<ByteUnit, number> = {
|
|
12
|
-
[ByteUnit.B]: 0,
|
|
13
|
-
[ByteUnit.KB]: 1,
|
|
14
|
-
[ByteUnit.MB]: 2,
|
|
15
|
-
[ByteUnit.GB]: 3,
|
|
16
|
-
[ByteUnit.TB]: 4,
|
|
17
|
-
[ByteUnit.PB]: 5,
|
|
18
|
-
};
|
|
19
|
-
const NUMBER_TO_SIGN: Record<number, ByteUnit> = {
|
|
20
|
-
0: ByteUnit.B,
|
|
21
|
-
1: ByteUnit.KB,
|
|
22
|
-
2: ByteUnit.MB,
|
|
23
|
-
3: ByteUnit.GB,
|
|
24
|
-
4: ByteUnit.TB,
|
|
25
|
-
5: ByteUnit.PB,
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
export class ByteOperation
|
|
29
|
-
{
|
|
30
|
-
static format(value: number, unit: ByteUnit)
|
|
31
|
-
{
|
|
32
|
-
let KILO = 1024;
|
|
33
|
-
let bytes = this.convert(value, unit, ByteUnit.B);
|
|
34
|
-
if (!bytes || bytes < 1) return "0B";
|
|
35
|
-
|
|
36
|
-
let index = 0;
|
|
37
|
-
while (bytes >= KILO && NUMBER_TO_SIGN[index] != null)
|
|
38
|
-
{
|
|
39
|
-
bytes /= KILO;
|
|
40
|
-
index++;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
function formatNumber(value: number): string
|
|
44
|
-
{
|
|
45
|
-
if (value != Math.round(value))
|
|
46
|
-
{
|
|
47
|
-
if (value < 1) return value.toFixed(2);
|
|
48
|
-
if (value < 100) return value.toFixed(1);
|
|
49
|
-
}
|
|
50
|
-
return value.toFixed(0);
|
|
51
|
-
}
|
|
52
|
-
return `${formatNumber(bytes)}${NUMBER_TO_SIGN[index]}`;
|
|
53
|
-
}
|
|
54
|
-
static convert(value: number, from: ByteUnit, to: ByteUnit)
|
|
55
|
-
{
|
|
56
|
-
return value * (2 ** (10 * (SIGN_TO_NUMBER[from] - SIGN_TO_NUMBER[to])));
|
|
57
|
-
}
|
|
1
|
+
export enum ByteUnit
|
|
2
|
+
{
|
|
3
|
+
B = "B",
|
|
4
|
+
KB = "KB",
|
|
5
|
+
MB = "MB",
|
|
6
|
+
GB = "GB",
|
|
7
|
+
TB = "TB",
|
|
8
|
+
PB = "PB",
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
const SIGN_TO_NUMBER: Record<ByteUnit, number> = {
|
|
12
|
+
[ByteUnit.B]: 0,
|
|
13
|
+
[ByteUnit.KB]: 1,
|
|
14
|
+
[ByteUnit.MB]: 2,
|
|
15
|
+
[ByteUnit.GB]: 3,
|
|
16
|
+
[ByteUnit.TB]: 4,
|
|
17
|
+
[ByteUnit.PB]: 5,
|
|
18
|
+
};
|
|
19
|
+
const NUMBER_TO_SIGN: Record<number, ByteUnit> = {
|
|
20
|
+
0: ByteUnit.B,
|
|
21
|
+
1: ByteUnit.KB,
|
|
22
|
+
2: ByteUnit.MB,
|
|
23
|
+
3: ByteUnit.GB,
|
|
24
|
+
4: ByteUnit.TB,
|
|
25
|
+
5: ByteUnit.PB,
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export class ByteOperation
|
|
29
|
+
{
|
|
30
|
+
static format(value: number, unit: ByteUnit)
|
|
31
|
+
{
|
|
32
|
+
let KILO = 1024;
|
|
33
|
+
let bytes = this.convert(value, unit, ByteUnit.B);
|
|
34
|
+
if (!bytes || bytes < 1) return "0B";
|
|
35
|
+
|
|
36
|
+
let index = 0;
|
|
37
|
+
while (bytes >= KILO && NUMBER_TO_SIGN[index] != null)
|
|
38
|
+
{
|
|
39
|
+
bytes /= KILO;
|
|
40
|
+
index++;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function formatNumber(value: number): string
|
|
44
|
+
{
|
|
45
|
+
if (value != Math.round(value))
|
|
46
|
+
{
|
|
47
|
+
if (value < 1) return value.toFixed(2);
|
|
48
|
+
if (value < 100) return value.toFixed(1);
|
|
49
|
+
}
|
|
50
|
+
return value.toFixed(0);
|
|
51
|
+
}
|
|
52
|
+
return `${formatNumber(bytes)}${NUMBER_TO_SIGN[index]}`;
|
|
53
|
+
}
|
|
54
|
+
static convert(value: number, from: ByteUnit, to: ByteUnit)
|
|
55
|
+
{
|
|
56
|
+
return value * (2 ** (10 * (SIGN_TO_NUMBER[from] - SIGN_TO_NUMBER[to])));
|
|
57
|
+
}
|
|
58
58
|
}
|
package/src/CacheService.ts
CHANGED
|
@@ -1,77 +1,77 @@
|
|
|
1
|
-
import { Mutex } from "async-mutex";
|
|
2
|
-
import { IStorage } from "./IStorage";
|
|
3
|
-
|
|
4
|
-
interface CacheStorage<DataType>
|
|
5
|
-
{
|
|
6
|
-
version?: string;
|
|
7
|
-
expires_at: Date;
|
|
8
|
-
data: DataType;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export class CacheService<DataType>
|
|
12
|
-
{
|
|
13
|
-
private name: string;
|
|
14
|
-
private storage: IStorage;
|
|
15
|
-
private duration_minutes: number;
|
|
16
|
-
private getVersion: () => Promise<string>;
|
|
17
|
-
private getFromSource: () => Promise<DataType>;
|
|
18
|
-
public onExpired?: () => void;
|
|
19
|
-
public runGetOn?: Mutex;
|
|
20
|
-
constructor(name: string, storage: IStorage, duration_minutes: number, getVersion: () => Promise<string>, getFromSource: () => Promise<DataType>)
|
|
21
|
-
{
|
|
22
|
-
this.name = name;
|
|
23
|
-
this.storage = storage;
|
|
24
|
-
this.duration_minutes = duration_minutes;
|
|
25
|
-
this.getVersion = getVersion;
|
|
26
|
-
this.getFromSource = getFromSource;
|
|
27
|
-
}
|
|
28
|
-
async get(): Promise<DataType>
|
|
29
|
-
{
|
|
30
|
-
let innerGet = async () =>
|
|
31
|
-
{
|
|
32
|
-
let version = await this.getVersion();
|
|
33
|
-
let value = this.storage.get(this.name, "");
|
|
34
|
-
if (value)
|
|
35
|
-
{
|
|
36
|
-
let cache = JSON.parse(value) as CacheStorage<DataType>;
|
|
37
|
-
if (cache.version == version)
|
|
38
|
-
if (new Date(cache.expires_at) > new Date())
|
|
39
|
-
if (cache.data != null)
|
|
40
|
-
return cache.data;
|
|
41
|
-
}
|
|
42
|
-
let ans = await this.getFromSource();
|
|
43
|
-
await this.set(ans, version);
|
|
44
|
-
return ans;
|
|
45
|
-
};
|
|
46
|
-
if (this.runGetOn)
|
|
47
|
-
return await this.runGetOn.runExclusive(async () =>
|
|
48
|
-
{
|
|
49
|
-
return await innerGet();
|
|
50
|
-
});
|
|
51
|
-
return await innerGet();
|
|
52
|
-
}
|
|
53
|
-
async set(data: DataType, version?: string)
|
|
54
|
-
{
|
|
55
|
-
if (!version)
|
|
56
|
-
version = await this.getVersion();
|
|
57
|
-
let expires_at = new Date();
|
|
58
|
-
expires_at.setMinutes(expires_at.getMinutes() + this.duration_minutes);
|
|
59
|
-
let value = JSON.stringify({ data, version, expires_at });
|
|
60
|
-
this.storage.set(this.name, value);
|
|
61
|
-
|
|
62
|
-
if (this.onExpired)
|
|
63
|
-
{
|
|
64
|
-
let sleep = expires_at.getTime() - new Date().getTime();
|
|
65
|
-
if (sleep <= 0)
|
|
66
|
-
sleep = 5 * 1000;
|
|
67
|
-
setTimeout(() =>
|
|
68
|
-
{
|
|
69
|
-
this.onExpired?.();
|
|
70
|
-
}, sleep);
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
del()
|
|
74
|
-
{
|
|
75
|
-
this.storage.del(this.name);
|
|
76
|
-
}
|
|
1
|
+
import { Mutex } from "async-mutex";
|
|
2
|
+
import { IStorage } from "./IStorage";
|
|
3
|
+
|
|
4
|
+
interface CacheStorage<DataType>
|
|
5
|
+
{
|
|
6
|
+
version?: string;
|
|
7
|
+
expires_at: Date;
|
|
8
|
+
data: DataType;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export class CacheService<DataType>
|
|
12
|
+
{
|
|
13
|
+
private name: string;
|
|
14
|
+
private storage: IStorage;
|
|
15
|
+
private duration_minutes: number;
|
|
16
|
+
private getVersion: () => Promise<string>;
|
|
17
|
+
private getFromSource: () => Promise<DataType>;
|
|
18
|
+
public onExpired?: () => void;
|
|
19
|
+
public runGetOn?: Mutex;
|
|
20
|
+
constructor(name: string, storage: IStorage, duration_minutes: number, getVersion: () => Promise<string>, getFromSource: () => Promise<DataType>)
|
|
21
|
+
{
|
|
22
|
+
this.name = name;
|
|
23
|
+
this.storage = storage;
|
|
24
|
+
this.duration_minutes = duration_minutes;
|
|
25
|
+
this.getVersion = getVersion;
|
|
26
|
+
this.getFromSource = getFromSource;
|
|
27
|
+
}
|
|
28
|
+
async get(): Promise<DataType>
|
|
29
|
+
{
|
|
30
|
+
let innerGet = async () =>
|
|
31
|
+
{
|
|
32
|
+
let version = await this.getVersion();
|
|
33
|
+
let value = this.storage.get(this.name, "");
|
|
34
|
+
if (value)
|
|
35
|
+
{
|
|
36
|
+
let cache = JSON.parse(value) as CacheStorage<DataType>;
|
|
37
|
+
if (cache.version == version)
|
|
38
|
+
if (new Date(cache.expires_at) > new Date())
|
|
39
|
+
if (cache.data != null)
|
|
40
|
+
return cache.data;
|
|
41
|
+
}
|
|
42
|
+
let ans = await this.getFromSource();
|
|
43
|
+
await this.set(ans, version);
|
|
44
|
+
return ans;
|
|
45
|
+
};
|
|
46
|
+
if (this.runGetOn)
|
|
47
|
+
return await this.runGetOn.runExclusive(async () =>
|
|
48
|
+
{
|
|
49
|
+
return await innerGet();
|
|
50
|
+
});
|
|
51
|
+
return await innerGet();
|
|
52
|
+
}
|
|
53
|
+
async set(data: DataType, version?: string)
|
|
54
|
+
{
|
|
55
|
+
if (!version)
|
|
56
|
+
version = await this.getVersion();
|
|
57
|
+
let expires_at = new Date();
|
|
58
|
+
expires_at.setMinutes(expires_at.getMinutes() + this.duration_minutes);
|
|
59
|
+
let value = JSON.stringify({ data, version, expires_at });
|
|
60
|
+
this.storage.set(this.name, value);
|
|
61
|
+
|
|
62
|
+
if (this.onExpired)
|
|
63
|
+
{
|
|
64
|
+
let sleep = expires_at.getTime() - new Date().getTime();
|
|
65
|
+
if (sleep <= 0)
|
|
66
|
+
sleep = 5 * 1000;
|
|
67
|
+
setTimeout(() =>
|
|
68
|
+
{
|
|
69
|
+
this.onExpired?.();
|
|
70
|
+
}, sleep);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
del()
|
|
74
|
+
{
|
|
75
|
+
this.storage.del(this.name);
|
|
76
|
+
}
|
|
77
77
|
}
|