mybase 1.2.2 → 1.2.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/mybase.js.map +1 -0
- package/package.json +16 -1
- package/ts/funcs/Geoip2Paths.js.map +1 -0
- package/ts/funcs/MaxRuntimeHours.js.map +1 -0
- package/ts/funcs/asJSON.js.map +1 -0
- package/ts/funcs/deepCopy.js.map +1 -0
- package/ts/funcs/ensureFolder.js.map +1 -0
- package/ts/funcs/fileCacheIsValid.js.map +1 -0
- package/ts/funcs/getMysql1.js.map +1 -0
- package/ts/funcs/getMysql2.js.map +1 -0
- package/ts/funcs/getWeekNumber.js.map +1 -0
- package/ts/funcs/hash_sha512.js.map +1 -0
- package/ts/funcs/initMysql2Pool.js.map +1 -0
- package/ts/funcs/int2ip.js.map +1 -0
- package/ts/funcs/ip2int.js.map +1 -0
- package/ts/funcs/isLANIp.js.map +1 -0
- package/ts/funcs/isLocal.js.map +1 -0
- package/ts/funcs/isLoopbackIP.js.map +1 -0
- package/ts/funcs/knexConnection.js.map +1 -0
- package/ts/funcs/promiseTimeout.js.map +1 -0
- package/ts/funcs/randomIP.js.map +1 -0
- package/ts/funcs/randomIP6.js.map +1 -0
- package/ts/funcs/randomString.js.map +1 -0
- package/ts/funcs/randomTCPPort.js.map +1 -0
- package/ts/funcs/randomUTFString.js.map +1 -0
- package/ts/funcs/utcnow.js.map +1 -0
- package/ts/funcs/validEmail.js.map +1 -0
- package/ts/funcs/validIp.js.map +1 -0
- package/ts/funcs/vaultFill.js.map +1 -0
- package/ts/funcs/vaultRead.js.map +1 -0
- package/ts/funcs/wait.js.map +1 -0
- package/ts/global.js.map +1 -0
- package/ts/index.js.map +1 -0
- package/ts/models/DateIterator.js.map +1 -0
- package/ts/models/IPAddress.js.map +1 -0
- package/ts/models/Interfaces.js.map +1 -0
- package/ts/models/OTPGenerator.js.map +1 -0
- package/ts/models/Timespan.js.map +1 -0
- package/ts/models/Unixtime.js.map +1 -0
- package/ts/types.js.map +1 -0
- package/jest/isLANIp.test.js +0 -36
- package/jest/isLoopbackIP.test.js +0 -31
- package/jest.config.js +0 -13
- package/mybase.test.ts +0 -647
- package/mybase.ts +0 -397
- package/ts/funcs/Geoip2Paths.test.ts +0 -11
- package/ts/funcs/Geoip2Paths.ts +0 -28
- package/ts/funcs/MaxRuntimeHours.ts +0 -7
- package/ts/funcs/asJSON.test.js +0 -72
- package/ts/funcs/asJSON.ts +0 -9
- package/ts/funcs/deepCopy.test.ts +0 -108
- package/ts/funcs/deepCopy.ts +0 -34
- package/ts/funcs/ensureFolder.test.ts +0 -79
- package/ts/funcs/ensureFolder.ts +0 -21
- package/ts/funcs/fileCacheIsValid.ts +0 -13
- package/ts/funcs/getMysql1.ts +0 -41
- package/ts/funcs/getMysql2.ts +0 -42
- package/ts/funcs/getWeekNumber.test.ts +0 -9
- package/ts/funcs/getWeekNumber.ts +0 -31
- package/ts/funcs/hash_sha512.ts +0 -6
- package/ts/funcs/initMysql2Pool.ts +0 -11
- package/ts/funcs/int2ip.test.js +0 -33
- package/ts/funcs/int2ip.ts +0 -9
- package/ts/funcs/ip2int.test.js +0 -30
- package/ts/funcs/ip2int.ts +0 -10
- package/ts/funcs/isLANIp.test.ts +0 -58
- package/ts/funcs/isLANIp.ts +0 -34
- package/ts/funcs/isLocal.test.ts +0 -16
- package/ts/funcs/isLocal.ts +0 -5
- package/ts/funcs/isLoopbackIP.test.ts +0 -72
- package/ts/funcs/isLoopbackIP.ts +0 -30
- package/ts/funcs/knexConnection.ts +0 -42
- package/ts/funcs/promiseTimeout.test.js +0 -104
- package/ts/funcs/promiseTimeout.ts +0 -19
- package/ts/funcs/randomIP.test.ts +0 -16
- package/ts/funcs/randomIP.ts +0 -10
- package/ts/funcs/randomIP6.test.js +0 -18
- package/ts/funcs/randomIP6.ts +0 -12
- package/ts/funcs/randomString.test.ts +0 -15
- package/ts/funcs/randomString.ts +0 -5
- package/ts/funcs/randomTCPPort.test.ts +0 -62
- package/ts/funcs/randomTCPPort.ts +0 -58
- package/ts/funcs/randomUTFString.test.ts +0 -44
- package/ts/funcs/randomUTFString.ts +0 -33
- package/ts/funcs/utcnow.ts +0 -5
- package/ts/funcs/validEmail.test.js +0 -31
- package/ts/funcs/validEmail.ts +0 -11
- package/ts/funcs/validIp.test.ts +0 -33
- package/ts/funcs/validIp.ts +0 -5
- package/ts/funcs/vaultFill.ts +0 -89
- package/ts/funcs/vaultRead.ts +0 -50
- package/ts/funcs/wait.ts +0 -7
- package/ts/global.ts +0 -10
- package/ts/index.test.ts +0 -7
- package/ts/index.ts +0 -39
- package/ts/models/DateIterator.test.ts +0 -149
- package/ts/models/DateIterator.ts +0 -80
- package/ts/models/IPAddress.test.ts +0 -393
- package/ts/models/IPAddress.ts +0 -272
- package/ts/models/Interfaces.ts +0 -58
- package/ts/models/OTPGenerator.test.ts +0 -42
- package/ts/models/OTPGenerator.ts +0 -43
- package/ts/models/Timespan.ts +0 -80
- package/ts/models/Unixtime.test.ts +0 -168
- package/ts/models/Unixtime.ts +0 -208
- package/ts/types.ts +0 -42
- package/tsconfig.jest.json +0 -11
- package/tsconfig.json +0 -37
- package/types/third-party.d.ts +0 -21
package/mybase.ts
DELETED
|
@@ -1,397 +0,0 @@
|
|
|
1
|
-
/// <reference path="./ip6addr.d.ts" />
|
|
2
|
-
//#region imports
|
|
3
|
-
import ipRangeCheck from 'ip-range-check'
|
|
4
|
-
import aesjs from 'aes-js'
|
|
5
|
-
import createDebug from 'debug'
|
|
6
|
-
import os from 'os'
|
|
7
|
-
import fs from 'fs'
|
|
8
|
-
import path from 'path'
|
|
9
|
-
import net from 'net'
|
|
10
|
-
import chalk from 'chalk'
|
|
11
|
-
import validURLFn from '@7c/validurl'
|
|
12
|
-
import { sha512 } from 'js-sha512'
|
|
13
|
-
import * as ip6 from 'ip6'
|
|
14
|
-
import { Reader as MaxmindReader } from '@maxmind/geoip2-node'
|
|
15
|
-
import type { MysqlConfig, MysqlConnection, MysqlConnector, SqlQueryable } from './ts/types'
|
|
16
|
-
import { randomString } from './ts/funcs/randomString'
|
|
17
|
-
//#endregion
|
|
18
|
-
|
|
19
|
-
//#region re-export from ts/funcs
|
|
20
|
-
export { randomString }
|
|
21
|
-
export { wait } from './ts/funcs/wait'
|
|
22
|
-
export { utcnow } from './ts/funcs/utcnow'
|
|
23
|
-
export { isLocal } from './ts/funcs/isLocal'
|
|
24
|
-
export { validEmail } from './ts/funcs/validEmail'
|
|
25
|
-
export { asJSON } from './ts/funcs/asJSON'
|
|
26
|
-
export { promiseTimeout } from './ts/funcs/promiseTimeout'
|
|
27
|
-
export { randomIP } from './ts/funcs/randomIP'
|
|
28
|
-
export { MaxRuntimeHours } from './ts/funcs/MaxRuntimeHours'
|
|
29
|
-
export { Geoip2Paths } from './ts/funcs/Geoip2Paths'
|
|
30
|
-
export { vaultRead } from './ts/funcs/vaultRead'
|
|
31
|
-
export { vaultFill } from './ts/funcs/vaultFill'
|
|
32
|
-
export { hash_sha512 } from './ts/funcs/hash_sha512'
|
|
33
|
-
export { isLoopbackIP } from './ts/funcs/isLoopbackIP'
|
|
34
|
-
export { isLANIp } from './ts/funcs/isLANIp'
|
|
35
|
-
//#endregion
|
|
36
|
-
|
|
37
|
-
const debug = createDebug('mybase')
|
|
38
|
-
|
|
39
|
-
//#region Date.prototype extension
|
|
40
|
-
declare global {
|
|
41
|
-
interface Date {
|
|
42
|
-
yyyymmdd(): string
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
Date.prototype.yyyymmdd = function yyyymmdd(this: Date) {
|
|
47
|
-
const mm = this.getMonth() + 1
|
|
48
|
-
const dd = this.getDate()
|
|
49
|
-
return [this.getFullYear(), (mm > 9 ? '' : '0') + mm, (dd > 9 ? '' : '0') + dd].join('')
|
|
50
|
-
}
|
|
51
|
-
//#endregion
|
|
52
|
-
|
|
53
|
-
export function validHPassword(hpassword: string): boolean {
|
|
54
|
-
return !!(hpassword && hpassword.length === 128 && hpassword.search(/^[a-f0-9]+$/) === 0)
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
export function randomHPassword(length = 10): string {
|
|
58
|
-
const plain = randomString(length)
|
|
59
|
-
return sha512(plain)
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
export function arrayRandomItem<T>(arry: unknown, defaultValue: T | false = false): T | false {
|
|
63
|
-
if (Array.isArray(arry)) return arry[Math.floor(Math.random() * arry.length)] as T
|
|
64
|
-
return defaultValue
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
export function validIp(str: unknown): boolean {
|
|
68
|
-
console.log(`WARNING: validIp is deprecated, use validIpNative or IPAddress model`)
|
|
69
|
-
if (str && typeof str === 'string') {
|
|
70
|
-
const splitted = str.match(/^([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+)$/)
|
|
71
|
-
if (splitted) {
|
|
72
|
-
for (const octet of splitted) {
|
|
73
|
-
if (parseInt(octet, 10) >= 0 && parseInt(octet, 10) <= 255) continue
|
|
74
|
-
return false
|
|
75
|
-
}
|
|
76
|
-
return true
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
return false
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
export function validIpNative(str: string): boolean {
|
|
83
|
-
return net.isIP(str) !== 0
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
export function isURL(url: unknown): URL | false {
|
|
87
|
-
if (typeof url === 'string') {
|
|
88
|
-
try {
|
|
89
|
-
return new URL(url)
|
|
90
|
-
} catch {
|
|
91
|
-
/* ignore */
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
return false
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
export function validTime(t: unknown): number | false {
|
|
98
|
-
const valid = !!(t && parseInt(String(t), 10) > 0 && String(t).length === 10)
|
|
99
|
-
if (!valid) return false
|
|
100
|
-
return parseInt(String(t), 10)
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
export function validURL(host: unknown): boolean {
|
|
104
|
-
return validURLFn(host)
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
export function isObject(a: unknown): boolean {
|
|
108
|
-
return !!a && (a as object).constructor === Object
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
export async function getMysql(mysqlClass: MysqlConnector, config: MysqlConfig, keep_pinging = true): Promise<MysqlConnection> {
|
|
112
|
-
const mysql_client = mysqlClass.createConnection({
|
|
113
|
-
host: config.host,
|
|
114
|
-
port: config.port ? config.port : 3306,
|
|
115
|
-
user: config.login,
|
|
116
|
-
password: config.password,
|
|
117
|
-
database: config.db,
|
|
118
|
-
})
|
|
119
|
-
await new Promise<void>((resolve, reject) => {
|
|
120
|
-
mysql_client.connect((err) => {
|
|
121
|
-
if (err) {
|
|
122
|
-
debug(`mysql connection has failed to ${config.host}@${config.db}`, err)
|
|
123
|
-
reject(err)
|
|
124
|
-
return
|
|
125
|
-
}
|
|
126
|
-
debug(`mysql connection has been established to ${config.host}@${config.db}`)
|
|
127
|
-
if (keep_pinging) {
|
|
128
|
-
setInterval(() => {
|
|
129
|
-
mysql_client.ping((errPing?: NodeJS.ErrnoException | Error | null) => {
|
|
130
|
-
if (errPing && 'code' in errPing) return console.log(`could not ping mysql ${config.host}@${config.db}`, errPing.code)
|
|
131
|
-
debug(chalk.bold(`mysql ${config.host}@${config.db} is pinging properly`))
|
|
132
|
-
})
|
|
133
|
-
}, 30000)
|
|
134
|
-
}
|
|
135
|
-
resolve()
|
|
136
|
-
})
|
|
137
|
-
})
|
|
138
|
-
return mysql_client
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
export async function maxmindOpen(geoipFile: string) {
|
|
142
|
-
debug(`maxmindOpen ${geoipFile}`)
|
|
143
|
-
try {
|
|
144
|
-
const reader = await MaxmindReader.open(geoipFile, { watchForUpdates: true })
|
|
145
|
-
debug(`${geoipFile} is opened successfully`)
|
|
146
|
-
return reader
|
|
147
|
-
} catch (err) {
|
|
148
|
-
debug(`maxmindOpen Error at ${geoipFile}`, err)
|
|
149
|
-
throw err
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
export function randomBase32(length = 10): string {
|
|
154
|
-
const charSet = 'abcdefghijklmnopqrstuvwxyz234567'
|
|
155
|
-
let text = ''
|
|
156
|
-
for (let i = 0; i < length; i++) text += charSet.charAt(Math.floor(Math.random() * charSet.length))
|
|
157
|
-
return text
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
export function validAuthcode(authcode: string): boolean {
|
|
161
|
-
const alphabetOnly = 'abcdefghijklmnopqrstuvwxyz'
|
|
162
|
-
if (!authcode || authcode.length !== 12) return false
|
|
163
|
-
const ac = authcode.toLowerCase()
|
|
164
|
-
if (ac.charAt(3) !== '-') return false
|
|
165
|
-
if (ac.charAt(9) !== '-') return false
|
|
166
|
-
let checksum = 0
|
|
167
|
-
const body = ac.substring(1)
|
|
168
|
-
for (let i = 0; i < body.length; i++) {
|
|
169
|
-
const c = body.charAt(i)
|
|
170
|
-
if (c === '-') continue
|
|
171
|
-
checksum += c.charCodeAt(0)
|
|
172
|
-
}
|
|
173
|
-
const checksumChar = alphabetOnly.charAt(checksum % alphabetOnly.length)
|
|
174
|
-
if (checksumChar !== ac.charAt(0)) return false
|
|
175
|
-
return true
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
export function randomAuthcode(): string {
|
|
179
|
-
const length = 9
|
|
180
|
-
const charSet = 'abcdefghijklmnopqrstuvwxyz234567'
|
|
181
|
-
const alphabetOnly = 'abcdefghijklmnopqrstuvwxyz'
|
|
182
|
-
let checksum = 0
|
|
183
|
-
let text = ''
|
|
184
|
-
for (let i = 0; i < length; i++) {
|
|
185
|
-
if (i === 2 || i === 7) text += '-'
|
|
186
|
-
const c = charSet.charAt(Math.floor(Math.random() * charSet.length))
|
|
187
|
-
checksum += c.charCodeAt(0)
|
|
188
|
-
text += c
|
|
189
|
-
}
|
|
190
|
-
text = alphabetOnly.charAt(checksum % alphabetOnly.length) + text
|
|
191
|
-
return text
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
export function array_shuffle<T>(a: T[]): T[] {
|
|
195
|
-
let j: number
|
|
196
|
-
let x: T
|
|
197
|
-
for (let i = a.length - 1; i > 0; i--) {
|
|
198
|
-
j = Math.floor(Math.random() * (i + 1))
|
|
199
|
-
x = a[i]
|
|
200
|
-
a[i] = a[j]
|
|
201
|
-
a[j] = x
|
|
202
|
-
}
|
|
203
|
-
return a
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
export function object_shuffle<T extends Record<string, unknown>>(object: T): T {
|
|
207
|
-
const keys = array_shuffle(Object.keys(object))
|
|
208
|
-
const ret: Record<string, unknown> = {}
|
|
209
|
-
for (const k of keys) ret[k] = object[k]
|
|
210
|
-
return ret as T
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
export async function canReadAndWrite(targetPath: string, _create = false): Promise<boolean> {
|
|
214
|
-
await new Promise<void>((resolve, reject) => {
|
|
215
|
-
fs.stat(targetPath, (err) => {
|
|
216
|
-
if (err) {
|
|
217
|
-
if (err.code === 'ENOENT') {
|
|
218
|
-
fs.mkdirSync(targetPath)
|
|
219
|
-
} else {
|
|
220
|
-
reject(err)
|
|
221
|
-
return
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
fs.access(targetPath, fs.constants.W_OK | fs.constants.R_OK, (errAcc) => {
|
|
225
|
-
if (errAcc) return reject(errAcc)
|
|
226
|
-
debug(`canReadAndWrite ${targetPath}`)
|
|
227
|
-
resolve()
|
|
228
|
-
})
|
|
229
|
-
})
|
|
230
|
-
})
|
|
231
|
-
return true
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
export function softexit(message: string | false = false, seconds = 60, exitcode = 1): void {
|
|
235
|
-
if (message) console.log(message)
|
|
236
|
-
console.log(`Softexit: will stop in ${seconds} seconds..`)
|
|
237
|
-
setTimeout(() => {
|
|
238
|
-
process.exit(exitcode)
|
|
239
|
-
}, seconds * 1000)
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
export function validHostname(value: unknown): boolean {
|
|
243
|
-
if (typeof value !== 'string') return false
|
|
244
|
-
let v = value
|
|
245
|
-
const validHostnameChars = /^[a-zA-Z0-9-.]{1,253}\.?$/g
|
|
246
|
-
if (!validHostnameChars.test(v)) return false
|
|
247
|
-
if (v.endsWith('.')) v = v.slice(0, v.length - 1)
|
|
248
|
-
if (v.length > 253) return false
|
|
249
|
-
const labels = v.split('.')
|
|
250
|
-
return labels.every((label) => {
|
|
251
|
-
const validLabelChars = /^([a-zA-Z0-9-]+)$/g
|
|
252
|
-
return validLabelChars.test(label) && label.length < 64 && !label.startsWith('-') && !label.endsWith('-')
|
|
253
|
-
})
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
export function validHostname2(domainName: unknown): boolean {
|
|
257
|
-
const domainNameRegex =
|
|
258
|
-
/^(?:[a-z0-9](?:[a-z0-9_\-]{0,61}[a-z0-9])?\.){0,126}(?:[a-z0-9](?:[a-z0-9\-]{0,61}[a-z0-9]))\.?$/i
|
|
259
|
-
if (!domainName || typeof domainName !== 'string') return false
|
|
260
|
-
if (net.isIPv4(domainName) || net.isIPv6(domainName.replace(/[\[\]]/g, ''))) return true
|
|
261
|
-
let dn = domainName.replace(/\.$/, '')
|
|
262
|
-
if (dn.length < 2) return false
|
|
263
|
-
if (dn.length > 255) return false
|
|
264
|
-
if (dn.search(/\./) < 0 && dn.search(/^[0-9]+$/) === 0) return false
|
|
265
|
-
return domainNameRegex.test(dn)
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
export function removeDoubleSlashes(url: unknown): string | false {
|
|
269
|
-
if (typeof url === 'string') return url.replace(/([^:]\/)\/+/g, '$1')
|
|
270
|
-
return false
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
export function getTemp(filename: string | false = false): string {
|
|
274
|
-
const tempDirectorySymbol = Symbol.for('__RESOLVED_TEMP_DIRECTORY__')
|
|
275
|
-
const g = globalThis as typeof globalThis & { [k: symbol]: string | undefined }
|
|
276
|
-
if (!g[tempDirectorySymbol]) {
|
|
277
|
-
Object.defineProperty(g, tempDirectorySymbol, {
|
|
278
|
-
value: fs.realpathSync(os.tmpdir()),
|
|
279
|
-
})
|
|
280
|
-
}
|
|
281
|
-
let tmp = g[tempDirectorySymbol] as string
|
|
282
|
-
if (filename) tmp = path.join(tmp, filename)
|
|
283
|
-
return tmp
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
export async function sqlQuery(sqlHandle: SqlQueryable, query: string, values: unknown[] = []): Promise<unknown> {
|
|
287
|
-
return await new Promise((resolve, reject) => {
|
|
288
|
-
sqlHandle.query(query, values, (err, res) => {
|
|
289
|
-
if (err) return reject(err)
|
|
290
|
-
resolve(res)
|
|
291
|
-
})
|
|
292
|
-
})
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
export function isMochaRunning(): boolean {
|
|
296
|
-
const context = globalThis as typeof globalThis & Record<string, unknown>
|
|
297
|
-
return ['afterEach', 'after', 'beforeEach', 'before', 'describe', 'it'].every((functionName) => {
|
|
298
|
-
return context[functionName] instanceof Function
|
|
299
|
-
})
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
export function validUUID4(uuid: string): boolean {
|
|
303
|
-
return /^[0-9A-F]{8}-[0-9A-F]{4}-[4][0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i.test(uuid)
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
export async function portCheck_tcp(port: number, opts: { timeout?: number; host?: string } = {}): Promise<boolean> {
|
|
307
|
-
const { timeout = 1000, host = '127.0.0.1' } = opts
|
|
308
|
-
const promise = new Promise<void>((resolve, reject) => {
|
|
309
|
-
const socket = new net.Socket()
|
|
310
|
-
const onError = (err: unknown) => {
|
|
311
|
-
debug(`onError`, err)
|
|
312
|
-
socket.destroy()
|
|
313
|
-
reject()
|
|
314
|
-
}
|
|
315
|
-
socket.setTimeout(timeout)
|
|
316
|
-
socket.once('error', onError)
|
|
317
|
-
socket.once('timeout', onError)
|
|
318
|
-
socket.connect(port, host, () => {
|
|
319
|
-
debug(`socket.connect ${host}:${port}`)
|
|
320
|
-
socket.end()
|
|
321
|
-
resolve()
|
|
322
|
-
})
|
|
323
|
-
})
|
|
324
|
-
try {
|
|
325
|
-
await promise
|
|
326
|
-
return true
|
|
327
|
-
} catch (e) {
|
|
328
|
-
console.log(e)
|
|
329
|
-
return false
|
|
330
|
-
}
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
export function ensureProperty<T>(target: Record<string, unknown>, propsString: string, defaultValue: T | false = false, debugWalk = false): unknown {
|
|
334
|
-
function iterate(o: Record<string, unknown>, parts: string[]): unknown {
|
|
335
|
-
if (debugWalk) console.log(parts)
|
|
336
|
-
const pname = parts.shift()
|
|
337
|
-
if (pname === undefined) return defaultValue
|
|
338
|
-
if (debugWalk) console.log(`iterate`, o, pname)
|
|
339
|
-
if (Object.prototype.hasOwnProperty.call(o, pname) && typeof o[pname] === 'object' && o[pname] !== null && parts.length > 0) {
|
|
340
|
-
return iterate(o[pname] as Record<string, unknown>, parts)
|
|
341
|
-
}
|
|
342
|
-
if (debugWalk) console.log(`--`, o, pname, o[pname], parts)
|
|
343
|
-
if (Object.prototype.hasOwnProperty.call(o, pname) && parts.length === 0) return o[pname]
|
|
344
|
-
if (debugWalk) console.log(`+++`)
|
|
345
|
-
return defaultValue
|
|
346
|
-
}
|
|
347
|
-
const parts = propsString.split('.')
|
|
348
|
-
return iterate(target, parts)
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
export function int2ip(ipInt: number): string {
|
|
352
|
-
return `${ipInt >>> 24}.${(ipInt >> 16) & 255}.${(ipInt >> 8) & 255}.${ipInt & 255}`
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
export function ip2int(ip: string): number {
|
|
356
|
-
return (
|
|
357
|
-
ip.split('.').reduce((ipInt, octet) => (ipInt << 8) + parseInt(octet, 10), 0) >>> 0
|
|
358
|
-
)
|
|
359
|
-
}
|
|
360
|
-
|
|
361
|
-
export function encryptAES_CBC_NOIV(plainString: string, encryptionKey: string): string | false {
|
|
362
|
-
try {
|
|
363
|
-
const key = aesjs.utils.utf8.toBytes(encryptionKey)
|
|
364
|
-
const textBytes = aesjs.utils.utf8.toBytes(plainString)
|
|
365
|
-
const aesCbc = new aesjs.ModeOfOperation.cbc(key)
|
|
366
|
-
const encryptedBytes = aesCbc.encrypt(aesjs.padding.pkcs7.pad(textBytes, 16))
|
|
367
|
-
return aesjs.utils.hex.fromBytes(encryptedBytes)
|
|
368
|
-
} catch {
|
|
369
|
-
return false
|
|
370
|
-
}
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
export function decryptAES_CBC_NOIV(encryptedHex: string, encryptionKey: string): string | false {
|
|
374
|
-
try {
|
|
375
|
-
const key = aesjs.utils.utf8.toBytes(encryptionKey)
|
|
376
|
-
const encryptedBytes = aesjs.utils.hex.toBytes(encryptedHex)
|
|
377
|
-
const aesCbc = new aesjs.ModeOfOperation.cbc(key)
|
|
378
|
-
const decryptedBytes = aesjs.padding.pkcs7.strip(aesCbc.decrypt(encryptedBytes))
|
|
379
|
-
return aesjs.utils.utf8.fromBytes(decryptedBytes)
|
|
380
|
-
} catch {
|
|
381
|
-
return false
|
|
382
|
-
}
|
|
383
|
-
}
|
|
384
|
-
|
|
385
|
-
export function isReservedLANIP(address: string): boolean {
|
|
386
|
-
const reservedLANIPRanges = [
|
|
387
|
-
'127.0.0.0/8',
|
|
388
|
-
'10.0.0.0/8',
|
|
389
|
-
'172.16.0.0/12',
|
|
390
|
-
'192.168.0.0/16',
|
|
391
|
-
'100.64.0.0/10',
|
|
392
|
-
'fd00::/8',
|
|
393
|
-
]
|
|
394
|
-
const normalizedAddress = net.isIPv6(address) ? ip6.normalize(address) : address
|
|
395
|
-
return ipRangeCheck(normalizedAddress, reservedLANIPRanges)
|
|
396
|
-
}
|
|
397
|
-
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { Geoip2Paths } from './Geoip2Paths'
|
|
2
|
-
import * as fs from 'fs'
|
|
3
|
-
|
|
4
|
-
describe('Geoip2Paths', () => {
|
|
5
|
-
it('should return a valid path', () => {
|
|
6
|
-
const paths = Geoip2Paths()
|
|
7
|
-
expect(paths).toHaveProperty('country')
|
|
8
|
-
expect(typeof paths.country).toBe('string')
|
|
9
|
-
expect(fs.existsSync(paths.country as string)).toBe(true)
|
|
10
|
-
})
|
|
11
|
-
})
|
package/ts/funcs/Geoip2Paths.ts
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import fs from 'fs'
|
|
2
|
-
import path from 'path'
|
|
3
|
-
|
|
4
|
-
export type Geoip2Paths = {
|
|
5
|
-
country:string|false,
|
|
6
|
-
city:string|false,
|
|
7
|
-
isp:string|false,
|
|
8
|
-
ct:string|false,
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
export function Geoip2Paths() :Geoip2Paths {
|
|
13
|
-
function firstExisting(paths:Array<string>) : string|false {
|
|
14
|
-
if (Array.isArray(paths))
|
|
15
|
-
for(let fpath of paths)
|
|
16
|
-
if (fs.existsSync(fpath)) return fpath
|
|
17
|
-
return false
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
const pkgRoot = path.join(__dirname, '..', '..')
|
|
21
|
-
const mainPath = require?.main?.path
|
|
22
|
-
return {
|
|
23
|
-
country:firstExisting(['/opt/geoip2/GeoIP2-Country.mmdb','/usr/local/var/GeoIP/GeoIP2-Country.mmdb','/var/lib/GeoIP/GeoIP2-Country.mmdb','/usr/share/GeoIP/GeoIP2-Country.mmdb',path.join(pkgRoot, 'assets/GeoIP2-Country.mmdb'),path.join(mainPath || pkgRoot, 'assets/GeoIP2-Country.mmdb')]),
|
|
24
|
-
city:firstExisting(['/opt/geoip2/GeoIP2-City.mmdb','/usr/local/var/GeoIP/GeoIP2-City.mmdb','/var/lib/GeoIP/GeoIP2-City.mmdb','/usr/share/GeoIP/GeoIP2-City.mmdb',path.join(pkgRoot, 'assets/GeoIP2-City.mmdb'),path.join(mainPath || pkgRoot, 'assets/GeoIP2-City.mmdb')]),
|
|
25
|
-
isp:firstExisting(['/opt/geoip2/GeoIP2-ISP.mmdb','/usr/local/var/GeoIP/GeoIP2-ISP.mmdb','/var/lib/GeoIP/GeoIP2-ISP.mmdb','/usr/share/GeoIP/GeoIP2-ISP.mmdb',path.join(pkgRoot, 'assets/GeoIP2-ISP.mmdb'),path.join(mainPath || pkgRoot, 'assets/GeoIP2-ISP.mmdb')]),
|
|
26
|
-
ct:firstExisting(['/opt/geoip2/GeoIP2-Connection-Type.mmdb','/usr/local/var/GeoIP/GeoIP2-Connection-Type.mmdb','/var/lib/GeoIP/GeoIP2-Connection-Type.mmdb','/usr/share/GeoIP/GeoIP2-Connection-Type.mmdb',path.join(pkgRoot, 'assets/GeoIP2-Connection-Type.mmdb'),path.join(mainPath || pkgRoot, 'assets/GeoIP2-Connection-Type.mmdb')]),
|
|
27
|
-
}
|
|
28
|
-
}
|
package/ts/funcs/asJSON.test.js
DELETED
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
const { asJSON } = require('./asJSON')
|
|
2
|
-
|
|
3
|
-
describe('asJSON', () => {
|
|
4
|
-
// Returns parsed JSON object when valid JSON string is passed as input.
|
|
5
|
-
it('should return parsed JSON object when valid JSON string is passed as input', () => {
|
|
6
|
-
const inputString = '{"name": "John", "age": 30}';
|
|
7
|
-
const expectedOutput = { name: "John", age: 30 };
|
|
8
|
-
const result = asJSON(inputString);
|
|
9
|
-
expect(result).toEqual(expectedOutput);
|
|
10
|
-
});
|
|
11
|
-
|
|
12
|
-
// Returns false when empty string is passed as input.
|
|
13
|
-
it('should return false when empty string is passed as input', () => {
|
|
14
|
-
const inputString = "";
|
|
15
|
-
const expectedOutput = false;
|
|
16
|
-
const result = asJSON(inputString);
|
|
17
|
-
expect(result).toEqual(expectedOutput);
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
// Returns false when non-string input is passed.
|
|
21
|
-
it('should return false when non-string input is passed', () => {
|
|
22
|
-
const inputString = 123;
|
|
23
|
-
const expectedOutput = false;
|
|
24
|
-
const result = asJSON(inputString);
|
|
25
|
-
expect(result).toEqual(expectedOutput);
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
// Returns false when null is passed as input.
|
|
29
|
-
it('should return false when null is passed as input', () => {
|
|
30
|
-
const inputString = null;
|
|
31
|
-
const expectedOutput = false;
|
|
32
|
-
const result = asJSON(inputString);
|
|
33
|
-
expect(result).toEqual(expectedOutput);
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
// Returns false when undefined is passed as input.
|
|
37
|
-
it('should return false when undefined is passed as input', () => {
|
|
38
|
-
const inputString = undefined;
|
|
39
|
-
const expectedOutput = false;
|
|
40
|
-
const result = asJSON(inputString);
|
|
41
|
-
expect(result).toEqual(expectedOutput);
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
// Returns false when NaN is passed as input.
|
|
45
|
-
it('should return false when NaN is passed as input', () => {
|
|
46
|
-
const inputString = NaN;
|
|
47
|
-
const expectedOutput = false;
|
|
48
|
-
const result = asJSON(inputString);
|
|
49
|
-
expect(result).toEqual(expectedOutput);
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
// Returns false when invalid JSON string is passed as input.
|
|
53
|
-
it('should return false when invalid JSON string is passed as input', () => {
|
|
54
|
-
const inputString = 'invalid json';
|
|
55
|
-
const result = asJSON(inputString);
|
|
56
|
-
expect(result).toBe(false);
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
// Returns false when Infinity is passed as input.
|
|
60
|
-
it('should return false when Infinity is passed as input', () => {
|
|
61
|
-
const inputString = 'Infinity';
|
|
62
|
-
const result = asJSON(inputString);
|
|
63
|
-
expect(result).toBe(false);
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
// Returns false when input string contains a single quote.
|
|
67
|
-
it('should return false when input string contains a single quote', () => {
|
|
68
|
-
const inputString = "{'name': 'John'}";
|
|
69
|
-
const result = asJSON(inputString);
|
|
70
|
-
expect(result).toBe(false);
|
|
71
|
-
});
|
|
72
|
-
});
|
package/ts/funcs/asJSON.ts
DELETED
|
@@ -1,108 +0,0 @@
|
|
|
1
|
-
import { Unixtime } from "../models/Unixtime";
|
|
2
|
-
import { deepCopy } from "./deepCopy"
|
|
3
|
-
|
|
4
|
-
describe('deepCopy', () => {
|
|
5
|
-
it('deep-copies plain objects', () => {
|
|
6
|
-
const src = { a: 1, b: { c: 2 } };
|
|
7
|
-
const copy = deepCopy(src) as typeof src;
|
|
8
|
-
|
|
9
|
-
expect(copy).toEqual(src);
|
|
10
|
-
expect(copy).not.toBe(src);
|
|
11
|
-
|
|
12
|
-
copy.b.c = 3;
|
|
13
|
-
expect(src.b.c).toBe(2); // original stays intact
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
it('Date objects are copied as Date objects', () => {
|
|
18
|
-
const src = { date: new Date() }
|
|
19
|
-
const copy = deepCopy(src) as typeof src
|
|
20
|
-
expect(copy.date).toBeInstanceOf(Date)
|
|
21
|
-
expect(copy.date).not.toBe(src.date)
|
|
22
|
-
})
|
|
23
|
-
|
|
24
|
-
it('deep-copies arrays', () => {
|
|
25
|
-
const src = [1, [2, 3]];
|
|
26
|
-
const copy = deepCopy(src) as typeof src;
|
|
27
|
-
|
|
28
|
-
expect(copy).toEqual(src);
|
|
29
|
-
//@ts-ignore
|
|
30
|
-
copy[1][0] = 99;
|
|
31
|
-
//@ts-ignore
|
|
32
|
-
expect(src[1][0]).toBe(2);
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
it('returns primitives unchanged', () => {
|
|
36
|
-
expect(deepCopy(42 as any)).toBe(42);
|
|
37
|
-
expect(deepCopy('hello' as any)).toBe('hello');
|
|
38
|
-
expect(deepCopy(null as any)).toBeNull();
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
it('should handle circular references', () => {
|
|
42
|
-
const obj: any = { a: 1 };
|
|
43
|
-
obj.self = obj;
|
|
44
|
-
const copy = deepCopy(obj);
|
|
45
|
-
expect(copy).toEqual({ a: 1, self: copy });
|
|
46
|
-
expect(copy.self).toBe(copy);
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
it('should preserve prototype chain', () => {
|
|
50
|
-
class MyClass { x = 1; }
|
|
51
|
-
const obj = new MyClass();
|
|
52
|
-
const copy = deepCopy(obj);
|
|
53
|
-
expect(copy).toBeInstanceOf(MyClass);
|
|
54
|
-
expect(copy.x).toBe(1);
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
it('changing Date at src should not change copy', () => {
|
|
58
|
-
const src = { a: new Date("2024-05-05"), b: { c: 2 } };
|
|
59
|
-
const copy = deepCopy(src) as typeof src;
|
|
60
|
-
expect(copy).toEqual(src);
|
|
61
|
-
expect(copy).not.toBe(src);
|
|
62
|
-
src.a.setFullYear(2025)
|
|
63
|
-
expect(src.a.getFullYear()).toBe(2025)
|
|
64
|
-
expect(copy.a.getFullYear()).toBe(2024)
|
|
65
|
-
})
|
|
66
|
-
|
|
67
|
-
it('changing src integer should not change copy', () => {
|
|
68
|
-
const src = { a: 1, b: { c: 2 } };
|
|
69
|
-
const copy = deepCopy(src) as typeof src;
|
|
70
|
-
expect(copy).toEqual(src);
|
|
71
|
-
expect(copy).not.toBe(src);
|
|
72
|
-
src.a = 2
|
|
73
|
-
expect(src.a).toBe(2)
|
|
74
|
-
expect(copy.a).toBe(1)
|
|
75
|
-
})
|
|
76
|
-
|
|
77
|
-
it('changing src string should not change copy', () => {
|
|
78
|
-
const src = { a: "hello", b: { c: 2 } };
|
|
79
|
-
const copy = deepCopy(src) as typeof src;
|
|
80
|
-
expect(copy).toEqual(src);
|
|
81
|
-
expect(copy).not.toBe(src);
|
|
82
|
-
src.a = "world"
|
|
83
|
-
expect(src.a).toBe("world")
|
|
84
|
-
expect(copy.a).toBe("hello")
|
|
85
|
-
})
|
|
86
|
-
|
|
87
|
-
it('changing src boolean should not change copy', () => {
|
|
88
|
-
const src = { a: true, b: { c: 2 } };
|
|
89
|
-
const copy = deepCopy(src) as typeof src;
|
|
90
|
-
expect(copy).toEqual(src);
|
|
91
|
-
expect(copy).not.toBe(src);
|
|
92
|
-
src.a = false
|
|
93
|
-
expect(src.a).toBe(false)
|
|
94
|
-
expect(copy.a).toBe(true)
|
|
95
|
-
|
|
96
|
-
})
|
|
97
|
-
|
|
98
|
-
it('changing src Unixtime should not change copy', () => {
|
|
99
|
-
const src = { a: new Unixtime("2024-05-02"), b: { c: 2 } };
|
|
100
|
-
const copy = deepCopy(src) as typeof src;
|
|
101
|
-
expect(copy).toEqual(src);
|
|
102
|
-
expect(copy).not.toBe(src);
|
|
103
|
-
src.a.addYears(-1)
|
|
104
|
-
expect(src.a.toDate().getFullYear()).toBe(2023)
|
|
105
|
-
expect(copy.a.toDate().getFullYear()).toBe(2024)
|
|
106
|
-
})
|
|
107
|
-
|
|
108
|
-
});
|
package/ts/funcs/deepCopy.ts
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
export function deepCopy<T>(obj: T, visited = new WeakMap()): T {
|
|
2
|
-
// Handle null and non-objects
|
|
3
|
-
if (obj === null || typeof obj !== 'object') {
|
|
4
|
-
return obj;
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
// Handle circular references
|
|
8
|
-
if (visited.has(obj)) {
|
|
9
|
-
return visited.get(obj);
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
// Handle Date
|
|
13
|
-
if (obj instanceof Date) {
|
|
14
|
-
return new Date(obj.getTime()) as any;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
// Handle Array
|
|
18
|
-
if (Array.isArray(obj)) {
|
|
19
|
-
const copy: any[] = [];
|
|
20
|
-
visited.set(obj, copy);
|
|
21
|
-
obj.forEach((item, i) => {
|
|
22
|
-
copy[i] = deepCopy(item, visited);
|
|
23
|
-
});
|
|
24
|
-
return copy as T;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
// Handle Object
|
|
28
|
-
const copy = Object.create(Object.getPrototypeOf(obj));
|
|
29
|
-
visited.set(obj, copy);
|
|
30
|
-
for (const key of Object.keys(obj)) {
|
|
31
|
-
copy[key] = deepCopy((obj as any)[key], visited);
|
|
32
|
-
}
|
|
33
|
-
return copy;
|
|
34
|
-
}
|