mybase 1.1.51 → 1.2.2
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/ip6addr.d.ts +10 -1
- package/jest.config.js +8 -1
- package/mybase.d.ts +57 -0
- package/mybase.js +401 -684
- package/mybase.test.ts +647 -0
- package/mybase.ts +397 -0
- package/package.json +3 -2
- package/ts/funcs/Geoip2Paths.js +7 -5
- package/ts/funcs/Geoip2Paths.ts +6 -4
- package/ts/funcs/asJSON.d.ts +1 -1
- package/ts/funcs/asJSON.js +6 -4
- package/ts/funcs/asJSON.ts +8 -5
- package/ts/funcs/hash_sha512.d.ts +1 -1
- package/ts/funcs/hash_sha512.js +4 -4
- package/ts/funcs/hash_sha512.ts +3 -4
- package/ts/funcs/isLANIp.d.ts +2 -3
- package/ts/funcs/isLANIp.js +14 -15
- package/ts/funcs/isLANIp.test.ts +7 -8
- package/ts/funcs/isLANIp.ts +25 -28
- package/ts/funcs/isLoopbackIP.d.ts +2 -3
- package/ts/funcs/isLoopbackIP.js +15 -16
- package/ts/funcs/isLoopbackIP.test.ts +7 -7
- package/ts/funcs/isLoopbackIP.ts +21 -23
- package/ts/funcs/validEmail.d.ts +1 -1
- package/ts/funcs/validEmail.js +0 -3
- package/ts/funcs/validEmail.ts +1 -3
- package/ts/funcs/vaultFill.js +1 -1
- package/ts/funcs/vaultFill.ts +1 -1
- package/ts/funcs/vaultRead.js +9 -3
- package/ts/funcs/vaultRead.ts +8 -3
- package/ts/index.d.ts +1 -0
- package/ts/index.js +1 -0
- package/ts/index.ts +1 -1
- package/ts/models/DateIterator.d.ts +33 -0
- package/ts/models/DateIterator.js +76 -0
- package/ts/models/DateIterator.test.ts +149 -0
- package/ts/models/DateIterator.ts +80 -0
- package/ts/models/IPAddress.d.ts +13 -13
- package/ts/models/IPAddress.ts +4 -4
- package/ts/models/OTPGenerator.test.ts +1 -1
- package/ts/types.d.ts +35 -0
- package/ts/types.js +1 -0
- package/ts/types.ts +42 -1
- package/tsconfig.jest.json +11 -0
- package/tsconfig.json +2 -1
- package/types/third-party.d.ts +21 -0
package/mybase.ts
ADDED
|
@@ -0,0 +1,397 @@
|
|
|
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
|
+
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mybase",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.2",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "mybase.js",
|
|
6
6
|
"scripts": {
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"@7c/node-ip6addr": "https://github.com/7c/node-ip6addr.git",
|
|
13
13
|
"@7c/validurl": "0.0.3",
|
|
14
|
+
"@maxmind/geoip2-node": "^5.0.0",
|
|
14
15
|
"@types/debug": "^4.1.12",
|
|
15
16
|
"@types/ip6addr": "^0.2.6",
|
|
16
17
|
"@types/mysql": "^2.15.25",
|
|
@@ -26,7 +27,7 @@
|
|
|
26
27
|
"knex": "^3.1.0",
|
|
27
28
|
"mysql": "^2.18.1",
|
|
28
29
|
"mysql2": "^3.9.1",
|
|
29
|
-
"node-vault": "^0.
|
|
30
|
+
"node-vault": "^0.12.0",
|
|
30
31
|
"psl": "^1.9.0",
|
|
31
32
|
"punycode": "^2.1.1",
|
|
32
33
|
"validator": "^13.7.0"
|
package/ts/funcs/Geoip2Paths.js
CHANGED
|
@@ -7,7 +7,7 @@ exports.Geoip2Paths = Geoip2Paths;
|
|
|
7
7
|
const fs_1 = __importDefault(require("fs"));
|
|
8
8
|
const path_1 = __importDefault(require("path"));
|
|
9
9
|
function Geoip2Paths() {
|
|
10
|
-
var _a
|
|
10
|
+
var _a;
|
|
11
11
|
function firstExisting(paths) {
|
|
12
12
|
if (Array.isArray(paths))
|
|
13
13
|
for (let fpath of paths)
|
|
@@ -15,11 +15,13 @@ function Geoip2Paths() {
|
|
|
15
15
|
return fpath;
|
|
16
16
|
return false;
|
|
17
17
|
}
|
|
18
|
+
const pkgRoot = path_1.default.join(__dirname, '..', '..');
|
|
19
|
+
const mainPath = (_a = require === null || require === void 0 ? void 0 : require.main) === null || _a === void 0 ? void 0 : _a.path;
|
|
18
20
|
return {
|
|
19
|
-
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_1.default.join(
|
|
20
|
-
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_1.default.join(
|
|
21
|
-
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_1.default.join(
|
|
22
|
-
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_1.default.join(
|
|
21
|
+
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_1.default.join(pkgRoot, 'assets/GeoIP2-Country.mmdb'), path_1.default.join(mainPath || pkgRoot, 'assets/GeoIP2-Country.mmdb')]),
|
|
22
|
+
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_1.default.join(pkgRoot, 'assets/GeoIP2-City.mmdb'), path_1.default.join(mainPath || pkgRoot, 'assets/GeoIP2-City.mmdb')]),
|
|
23
|
+
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_1.default.join(pkgRoot, 'assets/GeoIP2-ISP.mmdb'), path_1.default.join(mainPath || pkgRoot, 'assets/GeoIP2-ISP.mmdb')]),
|
|
24
|
+
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_1.default.join(pkgRoot, 'assets/GeoIP2-Connection-Type.mmdb'), path_1.default.join(mainPath || pkgRoot, 'assets/GeoIP2-Connection-Type.mmdb')]),
|
|
23
25
|
};
|
|
24
26
|
}
|
|
25
27
|
//# sourceMappingURL=Geoip2Paths.js.map
|
package/ts/funcs/Geoip2Paths.ts
CHANGED
|
@@ -17,10 +17,12 @@ export function Geoip2Paths() :Geoip2Paths {
|
|
|
17
17
|
return false
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
+
const pkgRoot = path.join(__dirname, '..', '..')
|
|
21
|
+
const mainPath = require?.main?.path
|
|
20
22
|
return {
|
|
21
|
-
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(
|
|
22
|
-
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(
|
|
23
|
-
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(
|
|
24
|
-
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(
|
|
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')]),
|
|
25
27
|
}
|
|
26
28
|
}
|
package/ts/funcs/asJSON.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare function asJSON(
|
|
1
|
+
export declare function asJSON(str: unknown): unknown | false;
|
package/ts/funcs/asJSON.js
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.asJSON = asJSON;
|
|
4
|
-
function asJSON(
|
|
5
|
-
if (!
|
|
4
|
+
function asJSON(str) {
|
|
5
|
+
if (!str || typeof str !== 'string')
|
|
6
6
|
return false;
|
|
7
7
|
try {
|
|
8
|
-
return JSON.parse(
|
|
8
|
+
return JSON.parse(str);
|
|
9
|
+
}
|
|
10
|
+
catch (_a) {
|
|
11
|
+
/* ignore */
|
|
9
12
|
}
|
|
10
|
-
catch (_) { }
|
|
11
13
|
return false;
|
|
12
14
|
}
|
|
13
15
|
//# sourceMappingURL=asJSON.js.map
|
package/ts/funcs/asJSON.ts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
export function asJSON(str: unknown): unknown | false {
|
|
2
|
+
if (!str || typeof str !== 'string') return false
|
|
3
|
+
try {
|
|
4
|
+
return JSON.parse(str)
|
|
5
|
+
} catch {
|
|
6
|
+
/* ignore */
|
|
7
|
+
}
|
|
8
|
+
return false
|
|
6
9
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare function hash_sha512(
|
|
1
|
+
export declare function hash_sha512(plain: unknown): string | false;
|
package/ts/funcs/hash_sha512.js
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.hash_sha512 = hash_sha512;
|
|
4
4
|
const js_sha512_1 = require("js-sha512");
|
|
5
|
-
function hash_sha512(
|
|
6
|
-
if (typeof
|
|
7
|
-
return (0, js_sha512_1.sha512)(
|
|
8
|
-
return
|
|
5
|
+
function hash_sha512(plain) {
|
|
6
|
+
if (typeof plain === 'string')
|
|
7
|
+
return (0, js_sha512_1.sha512)(plain);
|
|
8
|
+
return false;
|
|
9
9
|
}
|
|
10
10
|
//# sourceMappingURL=hash_sha512.js.map
|
package/ts/funcs/hash_sha512.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { sha512 } from 'js-sha512'
|
|
2
2
|
|
|
3
|
-
export function hash_sha512(
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
return ""
|
|
3
|
+
export function hash_sha512(plain: unknown): string | false {
|
|
4
|
+
if (typeof plain === 'string') return sha512(plain)
|
|
5
|
+
return false
|
|
7
6
|
}
|
package/ts/funcs/isLANIp.d.ts
CHANGED
|
@@ -1,3 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
export declare
|
|
3
|
-
export declare function isLANIp(ip: string): boolean;
|
|
1
|
+
export declare const private_network_cidrs: import("@7c/node-ip6addr").CIDR[];
|
|
2
|
+
export declare function isLANIp(ip: string): boolean | null;
|
package/ts/funcs/isLANIp.js
CHANGED
|
@@ -14,34 +14,33 @@ exports.private_network_cidrs = [
|
|
|
14
14
|
node_ip6addr_1.default.createCIDR('fd00::/8'), // Reserved by IETF for future use, but not currently in active use.
|
|
15
15
|
node_ip6addr_1.default.createCIDR('fc00::/8'), // The range currently in use for local communications within a site or organization.
|
|
16
16
|
];
|
|
17
|
-
function
|
|
18
|
-
ip = normalizeIp(ip);
|
|
17
|
+
function normalizeIp(ip) {
|
|
19
18
|
if (net_1.default.isIP(ip) === 0)
|
|
20
19
|
return false;
|
|
20
|
+
if (net_1.default.isIPv6(ip))
|
|
21
|
+
return ip.toLowerCase().replace(/^::ffff:/, '');
|
|
22
|
+
return ip;
|
|
23
|
+
}
|
|
24
|
+
function isLANIp(ip) {
|
|
25
|
+
const n = normalizeIp(ip);
|
|
26
|
+
if (n === false || net_1.default.isIP(n) === 0)
|
|
27
|
+
return false;
|
|
21
28
|
try {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
for (let cidr of exports.private_network_cidrs) {
|
|
29
|
+
const ipVersion = net_1.default.isIPv4(n) ? 'ipv4' : 'ipv6';
|
|
30
|
+
for (const cidr of exports.private_network_cidrs) {
|
|
25
31
|
if (!cidr)
|
|
26
32
|
continue;
|
|
27
|
-
|
|
33
|
+
const first = cidr.first();
|
|
28
34
|
if (first.kind() !== ipVersion)
|
|
29
35
|
continue;
|
|
30
|
-
if (cidr.contains(
|
|
36
|
+
if (cidr.contains(n))
|
|
31
37
|
return true;
|
|
32
38
|
}
|
|
39
|
+
return null;
|
|
33
40
|
}
|
|
34
41
|
catch (err) {
|
|
35
42
|
console.log(err);
|
|
36
43
|
}
|
|
37
44
|
return false;
|
|
38
45
|
}
|
|
39
|
-
function normalizeIp(ip) {
|
|
40
|
-
// also support ipv6
|
|
41
|
-
if (net_1.default.isIP(ip) === 0)
|
|
42
|
-
return '';
|
|
43
|
-
if (net_1.default.isIPv6(ip))
|
|
44
|
-
return ip.toLowerCase().replace(/^::ffff:/, '');
|
|
45
|
-
return ip;
|
|
46
|
-
}
|
|
47
46
|
//# sourceMappingURL=isLANIp.js.map
|
package/ts/funcs/isLANIp.test.ts
CHANGED
|
@@ -9,10 +9,9 @@ describe('isLANIp', () => {
|
|
|
9
9
|
// Add more test cases for LAN IP addresses
|
|
10
10
|
});
|
|
11
11
|
|
|
12
|
-
it('should return
|
|
13
|
-
expect(isLANIp('8.8.8.8')).
|
|
14
|
-
expect(isLANIp('2001:0db8:85a3:0000:0000:8a2e:0370:7334')).
|
|
15
|
-
// Add more test cases for non-LAN IP addresses
|
|
12
|
+
it('should return null for non-LAN IP addresses', () => {
|
|
13
|
+
expect(isLANIp('8.8.8.8')).toBeNull();
|
|
14
|
+
expect(isLANIp('2001:0db8:85a3:0000:0000:8a2e:0370:7334')).toBeNull();
|
|
16
15
|
});
|
|
17
16
|
|
|
18
17
|
it('should return false for invalid IP addresses', () => {
|
|
@@ -34,12 +33,12 @@ test('should return true for private IPv6', () => {
|
|
|
34
33
|
|
|
35
34
|
test('should return null for public IPv4', () => {
|
|
36
35
|
const ip = '8.8.8.8';
|
|
37
|
-
expect(isLANIp(ip)).
|
|
36
|
+
expect(isLANIp(ip)).toBeNull();
|
|
38
37
|
});
|
|
39
38
|
|
|
40
|
-
test('should return
|
|
39
|
+
test('should return null for public IPv6', () => {
|
|
41
40
|
const ip = '2001:4860:4860::8888';
|
|
42
|
-
expect(isLANIp(ip)).
|
|
41
|
+
expect(isLANIp(ip)).toBeNull();
|
|
43
42
|
});
|
|
44
43
|
|
|
45
44
|
test('should return false for invalid IP', () => {
|
|
@@ -54,6 +53,6 @@ test('should return false for invalid IP', () => {
|
|
|
54
53
|
|
|
55
54
|
test('should return null for non private IPv6', () => {
|
|
56
55
|
const ip = '::2';
|
|
57
|
-
expect(isLANIp(ip)).
|
|
56
|
+
expect(isLANIp(ip)).toBeNull();
|
|
58
57
|
});
|
|
59
58
|
});
|