namirasoft-core 1.5.3 → 1.5.5
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/CacheService.d.ts +2 -2
- package/dist/CacheService.js +16 -6
- package/dist/CacheService.js.map +1 -1
- package/dist/NamingConvention.js +1 -1
- package/dist/NamingConvention.js.map +1 -1
- package/package.json +25 -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 +89 -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 -303
- 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,90 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
{
|
|
13
|
-
private name: string;
|
|
14
|
-
|
|
15
|
-
private
|
|
16
|
-
private
|
|
17
|
-
private
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
let
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
1
|
+
import { IStorage } from "./IStorage";
|
|
2
|
+
|
|
3
|
+
interface CacheStorage<DataType>
|
|
4
|
+
{
|
|
5
|
+
version?: string;
|
|
6
|
+
expires_at: Date;
|
|
7
|
+
data: DataType;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export class CacheService<DataType>
|
|
11
|
+
{
|
|
12
|
+
private static pending: { [name: string]: Promise<any> } = {};
|
|
13
|
+
private static fetcherSources: { [name: string]: string } = {};
|
|
14
|
+
|
|
15
|
+
private name: string;
|
|
16
|
+
private storage: IStorage;
|
|
17
|
+
private duration_minutes: number;
|
|
18
|
+
private getVersion: () => Promise<string>;
|
|
19
|
+
private getFromSource: () => Promise<DataType>;
|
|
20
|
+
public onExpired?: () => void;
|
|
21
|
+
constructor(name: string, storage: IStorage, duration_minutes: number, getVersion: () => Promise<string>, getFromSource: () => Promise<DataType>)
|
|
22
|
+
{
|
|
23
|
+
let source = getFromSource.toString();
|
|
24
|
+
let existing = CacheService.fetcherSources[name];
|
|
25
|
+
if (existing !== undefined && existing !== source)
|
|
26
|
+
throw new Error(`CacheService: name "${name}" was already registered with a different getFromSource. The name is a global dedup key — instances that share a name must share the same fetcher.`);
|
|
27
|
+
CacheService.fetcherSources[name] = source;
|
|
28
|
+
|
|
29
|
+
this.name = name;
|
|
30
|
+
this.storage = storage;
|
|
31
|
+
this.duration_minutes = duration_minutes;
|
|
32
|
+
this.getVersion = getVersion;
|
|
33
|
+
this.getFromSource = getFromSource;
|
|
34
|
+
}
|
|
35
|
+
async get(): Promise<DataType>
|
|
36
|
+
{
|
|
37
|
+
if (this.name in CacheService.pending)
|
|
38
|
+
return CacheService.pending[this.name] as Promise<DataType>;
|
|
39
|
+
|
|
40
|
+
let promise = (async (): Promise<DataType> =>
|
|
41
|
+
{
|
|
42
|
+
let version = await this.getVersion();
|
|
43
|
+
let value = this.storage.get(this.name, "");
|
|
44
|
+
if (value)
|
|
45
|
+
{
|
|
46
|
+
let cache = JSON.parse(value) as CacheStorage<DataType>;
|
|
47
|
+
if (cache.version == version)
|
|
48
|
+
if (new Date(cache.expires_at) > new Date())
|
|
49
|
+
if (cache.data != null)
|
|
50
|
+
return cache.data;
|
|
51
|
+
}
|
|
52
|
+
let ans = await this.getFromSource();
|
|
53
|
+
await this.set(ans, version);
|
|
54
|
+
return ans;
|
|
55
|
+
})().finally(() =>
|
|
56
|
+
{
|
|
57
|
+
delete CacheService.pending[this.name];
|
|
58
|
+
}) as Promise<DataType>;
|
|
59
|
+
|
|
60
|
+
CacheService.pending[this.name] = promise;
|
|
61
|
+
return promise;
|
|
62
|
+
}
|
|
63
|
+
async set(data: DataType, version?: string)
|
|
64
|
+
{
|
|
65
|
+
delete CacheService.pending[this.name];
|
|
66
|
+
|
|
67
|
+
if (!version)
|
|
68
|
+
version = await this.getVersion();
|
|
69
|
+
let expires_at = new Date();
|
|
70
|
+
expires_at.setMinutes(expires_at.getMinutes() + this.duration_minutes);
|
|
71
|
+
let value = JSON.stringify({ data, version, expires_at });
|
|
72
|
+
this.storage.set(this.name, value);
|
|
73
|
+
|
|
74
|
+
if (this.onExpired)
|
|
75
|
+
{
|
|
76
|
+
let sleep = expires_at.getTime() - new Date().getTime();
|
|
77
|
+
if (sleep <= 0)
|
|
78
|
+
sleep = 5 * 1000;
|
|
79
|
+
setTimeout(() =>
|
|
80
|
+
{
|
|
81
|
+
this.onExpired?.();
|
|
82
|
+
}, sleep);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
del()
|
|
86
|
+
{
|
|
87
|
+
delete CacheService.pending[this.name];
|
|
88
|
+
this.storage.del(this.name);
|
|
89
|
+
}
|
|
77
90
|
}
|