namirasoft-core 1.2.13 → 1.2.15
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/.gitlab-ci.yml +13 -13
- package/dist/EncryptionOperation.d.ts +2 -2
- package/dist/EncryptionOperation.js +21 -10
- package/dist/EncryptionOperation.js.map +1 -1
- package/dist/SignOperation.d.ts +4 -0
- package/dist/SignOperation.js +14 -0
- package/dist/SignOperation.js.map +1 -0
- package/package.json +15 -15
- package/src/BaseDatabaseRow.ts +6 -6
- package/src/BaseServer.ts +72 -72
- package/src/ConvertService.ts +98 -98
- package/src/Countries.ts +486 -486
- package/src/Country.ts +21 -21
- package/src/CountryOperation.ts +98 -98
- package/src/EncryptionOperation.ts +40 -29
- package/src/ErrorOperation.ts +13 -13
- package/src/FileOperation.ts +50 -50
- package/src/GeoOperation.ts +18 -18
- package/src/HTTPError.ts +8 -8
- package/src/HTTPMethod.ts +6 -6
- package/src/HashOperation.ts +24 -24
- package/src/IStorage.ts +5 -5
- package/src/IStorageLocal.ts +16 -16
- package/src/IStorageMemory.ts +17 -17
- package/src/ObjectService.ts +23 -23
- package/src/PackageService.ts +66 -66
- package/src/PhoneOperation.ts +8 -8
- package/src/StringOperation.ts +18 -18
- package/src/TimeOperation.ts +262 -262
- package/src/URLOperation.ts +54 -54
- package/src/VersionOperation.ts +46 -46
- package/src/index.ts +23 -23
- package/tsconfig.json +29 -29
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
|
}
|
|
@@ -1,30 +1,41 @@
|
|
|
1
|
-
import * as crypto from 'node:crypto';
|
|
2
|
-
|
|
3
|
-
export class EncryptionOperation
|
|
4
|
-
{
|
|
5
|
-
private static encrypt<T>(algorithm: string, secret: string, message: T): string
|
|
6
|
-
{
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
const
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
1
|
+
import * as crypto from 'node:crypto';
|
|
2
|
+
|
|
3
|
+
export class EncryptionOperation
|
|
4
|
+
{
|
|
5
|
+
private static encrypt<T>(algorithm: string, secret: string, message: T): string
|
|
6
|
+
{
|
|
7
|
+
if (secret.length != 32)
|
|
8
|
+
throw new Error("Secret length must be exactly 32");
|
|
9
|
+
const secretBytes = Buffer.from(secret);
|
|
10
|
+
const iv = crypto.randomBytes(16);
|
|
11
|
+
const cipher = crypto.createCipheriv(algorithm, secretBytes, iv);
|
|
12
|
+
const encrypted = Buffer.concat([cipher.update(JSON.stringify(message), 'utf8'), cipher.final()]);
|
|
13
|
+
const authTag = (cipher as any).getAuthTag();
|
|
14
|
+
const ivHex = iv.toString('hex');
|
|
15
|
+
const authTagHex = authTag.toString('hex');
|
|
16
|
+
const encryptedHex = encrypted.toString('hex');
|
|
17
|
+
return [ivHex, authTagHex, encryptedHex].join(";");
|
|
18
|
+
}
|
|
19
|
+
private static decrypt<T>(algorithm: string, secret: string, message: string): T
|
|
20
|
+
{
|
|
21
|
+
const [ivHex, authTagHex, encryptedHex] = message.split(';');
|
|
22
|
+
const iv = Buffer.from(ivHex, 'hex');
|
|
23
|
+
const authTag = Buffer.from(authTagHex, 'hex');
|
|
24
|
+
const encrypte = Buffer.from(encryptedHex, 'hex');
|
|
25
|
+
|
|
26
|
+
const decipher = crypto.createDecipheriv(algorithm, secret, iv);
|
|
27
|
+
(decipher as any).setAuthTag(authTag);
|
|
28
|
+
|
|
29
|
+
let decrypted = decipher.update(encrypte);
|
|
30
|
+
decrypted = Buffer.concat([decrypted, decipher.final()]);
|
|
31
|
+
return JSON.parse(decrypted.toString());
|
|
32
|
+
}
|
|
33
|
+
static AES256GCMEncrypt<T>(secret: string, message: T): string
|
|
34
|
+
{
|
|
35
|
+
return EncryptionOperation.encrypt("aes-256-gcm", secret, message);
|
|
36
|
+
}
|
|
37
|
+
static AES256GCMDecrypt<T>(secret: string, message: string): T
|
|
38
|
+
{
|
|
39
|
+
return EncryptionOperation.decrypt("aes-256-gcm", secret, message);
|
|
40
|
+
}
|
|
30
41
|
}
|
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
|
}
|
package/src/FileOperation.ts
CHANGED
|
@@ -1,51 +1,51 @@
|
|
|
1
|
-
let fs: any;
|
|
2
|
-
let path: any;
|
|
3
|
-
if (typeof window === 'undefined')
|
|
4
|
-
{
|
|
5
|
-
fs = require('fs');
|
|
6
|
-
path = require('path');
|
|
7
|
-
}
|
|
8
|
-
export class FileOperation
|
|
9
|
-
{
|
|
10
|
-
static findUp(fileName: string): string[]
|
|
11
|
-
{
|
|
12
|
-
let currentDir: string = __dirname;
|
|
13
|
-
const rootDir: string = process.cwd();
|
|
14
|
-
const foundFilePaths: string[] = [];
|
|
15
|
-
function searchRecursively(dir: string)
|
|
16
|
-
{
|
|
17
|
-
const files: string[] = fs.readdirSync(dir);
|
|
18
|
-
if (files.includes(fileName))
|
|
19
|
-
foundFilePaths.push(path.join(dir, fileName));
|
|
20
|
-
if (rootDir === dir)
|
|
21
|
-
return;
|
|
22
|
-
searchRecursively(path.dirname(dir));
|
|
23
|
-
}
|
|
24
|
-
searchRecursively(currentDir);
|
|
25
|
-
return foundFilePaths;
|
|
26
|
-
}
|
|
27
|
-
static async foreachFolder(base: string, handler: (base: string, sub: string, full: string) => Promise<void>, folders: boolean = true, files: boolean = true)
|
|
28
|
-
{
|
|
29
|
-
async function recursive(base: string, sub: string)
|
|
30
|
-
{
|
|
31
|
-
let files_folders = fs.readdirSync(path.join(base, sub));
|
|
32
|
-
for (let folder of files_folders)
|
|
33
|
-
{
|
|
34
|
-
let s = path.join(sub, folder)
|
|
35
|
-
let p = path.join(base, s);
|
|
36
|
-
if (fs.statSync(p).isDirectory())
|
|
37
|
-
{
|
|
38
|
-
if (folders)
|
|
39
|
-
await handler(base, sub, folder);
|
|
40
|
-
await recursive(base, s);
|
|
41
|
-
}
|
|
42
|
-
else
|
|
43
|
-
{
|
|
44
|
-
if (files)
|
|
45
|
-
await handler(base, sub, folder);
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
await recursive(base, "");
|
|
50
|
-
}
|
|
1
|
+
let fs: any;
|
|
2
|
+
let path: any;
|
|
3
|
+
if (typeof window === 'undefined')
|
|
4
|
+
{
|
|
5
|
+
fs = require('fs');
|
|
6
|
+
path = require('path');
|
|
7
|
+
}
|
|
8
|
+
export class FileOperation
|
|
9
|
+
{
|
|
10
|
+
static findUp(fileName: string): string[]
|
|
11
|
+
{
|
|
12
|
+
let currentDir: string = __dirname;
|
|
13
|
+
const rootDir: string = process.cwd();
|
|
14
|
+
const foundFilePaths: string[] = [];
|
|
15
|
+
function searchRecursively(dir: string)
|
|
16
|
+
{
|
|
17
|
+
const files: string[] = fs.readdirSync(dir);
|
|
18
|
+
if (files.includes(fileName))
|
|
19
|
+
foundFilePaths.push(path.join(dir, fileName));
|
|
20
|
+
if (rootDir === dir)
|
|
21
|
+
return;
|
|
22
|
+
searchRecursively(path.dirname(dir));
|
|
23
|
+
}
|
|
24
|
+
searchRecursively(currentDir);
|
|
25
|
+
return foundFilePaths;
|
|
26
|
+
}
|
|
27
|
+
static async foreachFolder(base: string, handler: (base: string, sub: string, full: string) => Promise<void>, folders: boolean = true, files: boolean = true)
|
|
28
|
+
{
|
|
29
|
+
async function recursive(base: string, sub: string)
|
|
30
|
+
{
|
|
31
|
+
let files_folders = fs.readdirSync(path.join(base, sub));
|
|
32
|
+
for (let folder of files_folders)
|
|
33
|
+
{
|
|
34
|
+
let s = path.join(sub, folder)
|
|
35
|
+
let p = path.join(base, s);
|
|
36
|
+
if (fs.statSync(p).isDirectory())
|
|
37
|
+
{
|
|
38
|
+
if (folders)
|
|
39
|
+
await handler(base, sub, folder);
|
|
40
|
+
await recursive(base, s);
|
|
41
|
+
}
|
|
42
|
+
else
|
|
43
|
+
{
|
|
44
|
+
if (files)
|
|
45
|
+
await handler(base, sub, folder);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
await recursive(base, "");
|
|
50
|
+
}
|
|
51
51
|
}
|
package/src/GeoOperation.ts
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
export class GeoOperation
|
|
2
|
-
{
|
|
3
|
-
static distance(lat1: number, lng1: number, lat2: number, lng2: number)
|
|
4
|
-
{
|
|
5
|
-
function degreeToRadian(degree: number)
|
|
6
|
-
{
|
|
7
|
-
return degree * Math.PI / 180;
|
|
8
|
-
}
|
|
9
|
-
let R = 6371; // km
|
|
10
|
-
let dLat = degreeToRadian(lat2 - lat1);
|
|
11
|
-
let dLng = degreeToRadian(lng2 - lng1);
|
|
12
|
-
lat1 = degreeToRadian(lat1);
|
|
13
|
-
lat2 = degreeToRadian(lat2);
|
|
14
|
-
let a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
|
|
15
|
-
Math.sin(dLng / 2) * Math.sin(dLng / 2) * Math.cos(lat1) * Math.cos(lat2);
|
|
16
|
-
let c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
|
|
17
|
-
return R * c;
|
|
18
|
-
}
|
|
1
|
+
export class GeoOperation
|
|
2
|
+
{
|
|
3
|
+
static distance(lat1: number, lng1: number, lat2: number, lng2: number)
|
|
4
|
+
{
|
|
5
|
+
function degreeToRadian(degree: number)
|
|
6
|
+
{
|
|
7
|
+
return degree * Math.PI / 180;
|
|
8
|
+
}
|
|
9
|
+
let R = 6371; // km
|
|
10
|
+
let dLat = degreeToRadian(lat2 - lat1);
|
|
11
|
+
let dLng = degreeToRadian(lng2 - lng1);
|
|
12
|
+
lat1 = degreeToRadian(lat1);
|
|
13
|
+
lat2 = degreeToRadian(lat2);
|
|
14
|
+
let a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
|
|
15
|
+
Math.sin(dLng / 2) * Math.sin(dLng / 2) * Math.cos(lat1) * Math.cos(lat2);
|
|
16
|
+
let c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
|
|
17
|
+
return R * c;
|
|
18
|
+
}
|
|
19
19
|
}
|
package/src/HTTPError.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
export class HTTPError extends Error
|
|
2
|
-
{
|
|
3
|
-
code: number;
|
|
4
|
-
constructor(code: number, message: string)
|
|
5
|
-
{
|
|
6
|
-
super(message);
|
|
7
|
-
this.code = code;
|
|
8
|
-
}
|
|
1
|
+
export class HTTPError extends Error
|
|
2
|
+
{
|
|
3
|
+
code: number;
|
|
4
|
+
constructor(code: number, message: string)
|
|
5
|
+
{
|
|
6
|
+
super(message);
|
|
7
|
+
this.code = code;
|
|
8
|
+
}
|
|
9
9
|
}
|
package/src/HTTPMethod.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
export enum HTTPMethod
|
|
2
|
-
{
|
|
3
|
-
GET,
|
|
4
|
-
POST,
|
|
5
|
-
PUT,
|
|
6
|
-
DELETE
|
|
1
|
+
export enum HTTPMethod
|
|
2
|
+
{
|
|
3
|
+
GET,
|
|
4
|
+
POST,
|
|
5
|
+
PUT,
|
|
6
|
+
DELETE
|
|
7
7
|
}
|
package/src/HashOperation.ts
CHANGED
|
@@ -1,25 +1,25 @@
|
|
|
1
|
-
import * as crypto from 'node:crypto';
|
|
2
|
-
|
|
3
|
-
export class HashOperation
|
|
4
|
-
{
|
|
5
|
-
static SHA256<T>(message: T): string
|
|
6
|
-
{
|
|
7
|
-
const hash = crypto.createHash('sha256');
|
|
8
|
-
hash.update(JSON.stringify(message));
|
|
9
|
-
return hash.digest('hex');
|
|
10
|
-
}
|
|
11
|
-
static SHA256Secret<T>(secret: string, message: T): string
|
|
12
|
-
{
|
|
13
|
-
const hash = crypto.createHmac('sha256', secret);
|
|
14
|
-
hash.update(JSON.stringify(message));
|
|
15
|
-
return hash.digest('hex');
|
|
16
|
-
}
|
|
17
|
-
static isValidSHA256(values: any, signature: string)
|
|
18
|
-
{
|
|
19
|
-
return this.SHA256(values).toLowerCase() === signature.toLowerCase();
|
|
20
|
-
}
|
|
21
|
-
static isValidSHA256Secret(secret: string, values: any, signature: string)
|
|
22
|
-
{
|
|
23
|
-
return this.SHA256Secret(secret, values).toLowerCase() === signature.toLowerCase();
|
|
24
|
-
}
|
|
1
|
+
import * as crypto from 'node:crypto';
|
|
2
|
+
|
|
3
|
+
export class HashOperation
|
|
4
|
+
{
|
|
5
|
+
static SHA256<T>(message: T): string
|
|
6
|
+
{
|
|
7
|
+
const hash = crypto.createHash('sha256');
|
|
8
|
+
hash.update(JSON.stringify(message));
|
|
9
|
+
return hash.digest('hex');
|
|
10
|
+
}
|
|
11
|
+
static SHA256Secret<T>(secret: string, message: T): string
|
|
12
|
+
{
|
|
13
|
+
const hash = crypto.createHmac('sha256', secret);
|
|
14
|
+
hash.update(JSON.stringify(message));
|
|
15
|
+
return hash.digest('hex');
|
|
16
|
+
}
|
|
17
|
+
static isValidSHA256(values: any, signature: string)
|
|
18
|
+
{
|
|
19
|
+
return this.SHA256(values).toLowerCase() === signature.toLowerCase();
|
|
20
|
+
}
|
|
21
|
+
static isValidSHA256Secret(secret: string, values: any, signature: string)
|
|
22
|
+
{
|
|
23
|
+
return this.SHA256Secret(secret, values).toLowerCase() === signature.toLowerCase();
|
|
24
|
+
}
|
|
25
25
|
}
|
package/src/IStorage.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
export abstract class IStorage
|
|
2
|
-
{
|
|
3
|
-
abstract get(name: string, defaultValue: string): string;
|
|
4
|
-
abstract set(name: string, value: string): void;
|
|
5
|
-
abstract del(name: string): void;
|
|
1
|
+
export abstract class IStorage
|
|
2
|
+
{
|
|
3
|
+
abstract get(name: string, defaultValue: string): string;
|
|
4
|
+
abstract set(name: string, value: string): void;
|
|
5
|
+
abstract del(name: string): void;
|
|
6
6
|
}
|
package/src/IStorageLocal.ts
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
import { IStorage } from "./IStorage.js";
|
|
2
|
-
|
|
3
|
-
export class IStorageLocal extends IStorage
|
|
4
|
-
{
|
|
5
|
-
override get(name: string, defaultValue: string)
|
|
6
|
-
{
|
|
7
|
-
return localStorage.getItem(name) ?? defaultValue;
|
|
8
|
-
}
|
|
9
|
-
override set(name: string, value: string)
|
|
10
|
-
{
|
|
11
|
-
localStorage.setItem(name, value);
|
|
12
|
-
}
|
|
13
|
-
override del(name: string)
|
|
14
|
-
{
|
|
15
|
-
localStorage.removeItem(name);
|
|
16
|
-
}
|
|
1
|
+
import { IStorage } from "./IStorage.js";
|
|
2
|
+
|
|
3
|
+
export class IStorageLocal extends IStorage
|
|
4
|
+
{
|
|
5
|
+
override get(name: string, defaultValue: string)
|
|
6
|
+
{
|
|
7
|
+
return localStorage.getItem(name) ?? defaultValue;
|
|
8
|
+
}
|
|
9
|
+
override set(name: string, value: string)
|
|
10
|
+
{
|
|
11
|
+
localStorage.setItem(name, value);
|
|
12
|
+
}
|
|
13
|
+
override del(name: string)
|
|
14
|
+
{
|
|
15
|
+
localStorage.removeItem(name);
|
|
16
|
+
}
|
|
17
17
|
}
|
package/src/IStorageMemory.ts
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
import { IStorage } from "./IStorage";
|
|
2
|
-
|
|
3
|
-
export class IStorageMemory extends IStorage
|
|
4
|
-
{
|
|
5
|
-
static data: { [name: string]: string } = {};
|
|
6
|
-
override get(name: string, defaultValue: string)
|
|
7
|
-
{
|
|
8
|
-
return IStorageMemory.data[name] ?? defaultValue;
|
|
9
|
-
}
|
|
10
|
-
override set(name: string, value: string)
|
|
11
|
-
{
|
|
12
|
-
IStorageMemory.data[name] = value;
|
|
13
|
-
}
|
|
14
|
-
override del(name: string)
|
|
15
|
-
{
|
|
16
|
-
delete IStorageMemory.data[name];
|
|
17
|
-
}
|
|
1
|
+
import { IStorage } from "./IStorage";
|
|
2
|
+
|
|
3
|
+
export class IStorageMemory extends IStorage
|
|
4
|
+
{
|
|
5
|
+
static data: { [name: string]: string } = {};
|
|
6
|
+
override get(name: string, defaultValue: string)
|
|
7
|
+
{
|
|
8
|
+
return IStorageMemory.data[name] ?? defaultValue;
|
|
9
|
+
}
|
|
10
|
+
override set(name: string, value: string)
|
|
11
|
+
{
|
|
12
|
+
IStorageMemory.data[name] = value;
|
|
13
|
+
}
|
|
14
|
+
override del(name: string)
|
|
15
|
+
{
|
|
16
|
+
delete IStorageMemory.data[name];
|
|
17
|
+
}
|
|
18
18
|
}
|