@knsdev330/node-utils 1.0.1
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/LICENSE +21 -0
- package/README.md +85 -0
- package/dist/Cookies.d.ts +33 -0
- package/dist/Cookies.d.ts.map +1 -0
- package/dist/Cookies.js +54 -0
- package/dist/Cookies.js.map +1 -0
- package/dist/EApiCodes.d.ts +2 -0
- package/dist/EApiCodes.d.ts.map +1 -0
- package/dist/EApiCodes.js +2 -0
- package/dist/EApiCodes.js.map +1 -0
- package/dist/ErrorClasses.d.ts +78 -0
- package/dist/ErrorClasses.d.ts.map +1 -0
- package/dist/ErrorClasses.js +118 -0
- package/dist/ErrorClasses.js.map +1 -0
- package/dist/FBUtils.d.ts +22 -0
- package/dist/FBUtils.d.ts.map +1 -0
- package/dist/FBUtils.js +68 -0
- package/dist/FBUtils.js.map +1 -0
- package/dist/GoogleUtils.d.ts +43 -0
- package/dist/GoogleUtils.d.ts.map +1 -0
- package/dist/GoogleUtils.js +80 -0
- package/dist/GoogleUtils.js.map +1 -0
- package/dist/HMACUtils.d.ts +39 -0
- package/dist/HMACUtils.d.ts.map +1 -0
- package/dist/HMACUtils.js +61 -0
- package/dist/HMACUtils.js.map +1 -0
- package/dist/HttpCodes.d.ts +26 -0
- package/dist/HttpCodes.d.ts.map +1 -0
- package/dist/HttpCodes.js +25 -0
- package/dist/HttpCodes.js.map +1 -0
- package/dist/IDUtils.d.ts +28 -0
- package/dist/IDUtils.d.ts.map +1 -0
- package/dist/IDUtils.js +47 -0
- package/dist/IDUtils.js.map +1 -0
- package/dist/JwtUtils.d.ts +79 -0
- package/dist/JwtUtils.d.ts.map +1 -0
- package/dist/JwtUtils.js +94 -0
- package/dist/JwtUtils.js.map +1 -0
- package/dist/Nums.d.ts +101 -0
- package/dist/Nums.d.ts.map +1 -0
- package/dist/Nums.js +141 -0
- package/dist/Nums.js.map +1 -0
- package/dist/PasswordUtils.d.ts +58 -0
- package/dist/PasswordUtils.d.ts.map +1 -0
- package/dist/PasswordUtils.js +82 -0
- package/dist/PasswordUtils.js.map +1 -0
- package/dist/Rand.d.ts +44 -0
- package/dist/Rand.d.ts.map +1 -0
- package/dist/Rand.js +72 -0
- package/dist/Rand.js.map +1 -0
- package/dist/TurnstileValidator.d.ts +57 -0
- package/dist/TurnstileValidator.d.ts.map +1 -0
- package/dist/TurnstileValidator.js +99 -0
- package/dist/TurnstileValidator.js.map +1 -0
- package/dist/bnUtils.d.ts +15 -0
- package/dist/bnUtils.d.ts.map +1 -0
- package/dist/bnUtils.js +67 -0
- package/dist/bnUtils.js.map +1 -0
- package/dist/getEnvv.d.ts +21 -0
- package/dist/getEnvv.d.ts.map +1 -0
- package/dist/getEnvv.js +68 -0
- package/dist/getEnvv.js.map +1 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +17 -0
- package/dist/index.js.map +1 -0
- package/dist/tryCatch.d.ts +23 -0
- package/dist/tryCatch.d.ts.map +1 -0
- package/dist/tryCatch.js +29 -0
- package/dist/tryCatch.js.map +1 -0
- package/dist/types.d.ts +8 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/validators.d.ts +7 -0
- package/dist/validators.d.ts.map +1 -0
- package/dist/validators.js +11 -0
- package/dist/validators.js.map +1 -0
- package/package.json +80 -0
package/dist/Nums.js
ADDED
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Clamp a number to an inclusive range.
|
|
3
|
+
* @param value - Input number.
|
|
4
|
+
* @param min - Inclusive lower bound.
|
|
5
|
+
* @param max - Inclusive upper bound.
|
|
6
|
+
* @returns `value` constrained to `[min, max]`.
|
|
7
|
+
*/
|
|
8
|
+
export const clamp = (value, min, max) => Math.min(Math.max(value, min), max);
|
|
9
|
+
/**
|
|
10
|
+
* Check whether a number falls within an inclusive range.
|
|
11
|
+
* @param value - Number to test.
|
|
12
|
+
* @param min - Inclusive lower bound.
|
|
13
|
+
* @param max - Inclusive upper bound.
|
|
14
|
+
* @returns `true` when `min <= value <= max`; otherwise `false`.
|
|
15
|
+
*/
|
|
16
|
+
export const isBetween = (value, min, max) => value >= min && value <= max;
|
|
17
|
+
/**
|
|
18
|
+
* Round a number to a fixed number of decimal places.
|
|
19
|
+
* @param value - Number to round.
|
|
20
|
+
* @param decimals - Decimal places to keep.
|
|
21
|
+
* @returns Rounded number.
|
|
22
|
+
*/
|
|
23
|
+
export const roundTo = (value, decimals) => {
|
|
24
|
+
const factor = 10 ** decimals;
|
|
25
|
+
return Math.round(value * factor) / factor;
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* Round a number down to a fixed number of decimal places.
|
|
29
|
+
* @param value - Number to floor.
|
|
30
|
+
* @param decimals - Decimal places to keep.
|
|
31
|
+
* @returns Floored number.
|
|
32
|
+
*/
|
|
33
|
+
export const floorTo = (value, decimals) => {
|
|
34
|
+
const factor = 10 ** decimals;
|
|
35
|
+
return Math.floor(value * factor) / factor;
|
|
36
|
+
};
|
|
37
|
+
/**
|
|
38
|
+
* Round a number up to a fixed number of decimal places.
|
|
39
|
+
* @param value - Number to ceil.
|
|
40
|
+
* @param decimals - Decimal places to keep.
|
|
41
|
+
* @returns Ceiled number.
|
|
42
|
+
*/
|
|
43
|
+
export const ceilTo = (value, decimals) => {
|
|
44
|
+
const factor = 10 ** decimals;
|
|
45
|
+
return Math.ceil(value * factor) / factor;
|
|
46
|
+
};
|
|
47
|
+
/**
|
|
48
|
+
* Parse a value into an integer safely.
|
|
49
|
+
* @param value - Value to parse.
|
|
50
|
+
* @param radix - Numeric base for parsing string inputs.
|
|
51
|
+
* @returns Parsed integer, or `null` for `null`/`undefined`/`NaN`.
|
|
52
|
+
*/
|
|
53
|
+
export const parseIntSafe = (value, radix = 10) => {
|
|
54
|
+
if (value === null || value === undefined)
|
|
55
|
+
return null;
|
|
56
|
+
const n = typeof value === 'number' ? value : parseInt(String(value), radix);
|
|
57
|
+
return Number.isNaN(n) ? null : n;
|
|
58
|
+
};
|
|
59
|
+
/**
|
|
60
|
+
* Parse a value into a floating-point number safely.
|
|
61
|
+
* @param value - Value to parse.
|
|
62
|
+
* @returns Parsed number, or `null` for `null`/`undefined`/`NaN`.
|
|
63
|
+
*/
|
|
64
|
+
export const parseFloatSafe = (value) => {
|
|
65
|
+
if (value === null || value === undefined)
|
|
66
|
+
return null;
|
|
67
|
+
const n = typeof value === 'number' ? value : parseFloat(String(value));
|
|
68
|
+
return Number.isNaN(n) ? null : n;
|
|
69
|
+
};
|
|
70
|
+
/**
|
|
71
|
+
* Type guard for finite numbers.
|
|
72
|
+
* @param value - Unknown input.
|
|
73
|
+
* @returns `true` when `value` is a finite `number`.
|
|
74
|
+
*/
|
|
75
|
+
export const isFiniteNumber = (value) => typeof value === 'number' && Number.isFinite(value);
|
|
76
|
+
/**
|
|
77
|
+
* Type guard for integer numbers.
|
|
78
|
+
* @param value - Unknown input.
|
|
79
|
+
* @returns `true` when `value` is an integer `number`.
|
|
80
|
+
*/
|
|
81
|
+
export const isInteger = (value) => typeof value === 'number' && Number.isInteger(value);
|
|
82
|
+
/**
|
|
83
|
+
* Format a number using `Intl.NumberFormat`.
|
|
84
|
+
* @param value - Number to format.
|
|
85
|
+
* @param locale - BCP47 locale string.
|
|
86
|
+
* @param options - Number format options.
|
|
87
|
+
* @returns Formatted number string.
|
|
88
|
+
*/
|
|
89
|
+
export const formatNumber = (value, locale = 'en', options) => new Intl.NumberFormat(locale, {
|
|
90
|
+
minimumFractionDigits: 0,
|
|
91
|
+
maximumFractionDigits: 2,
|
|
92
|
+
...options,
|
|
93
|
+
}).format(value);
|
|
94
|
+
/**
|
|
95
|
+
* Format a number with group separators.
|
|
96
|
+
* @param value - Number to format.
|
|
97
|
+
* @param locale - BCP47 locale string. (default: 'en')
|
|
98
|
+
* @param decimals - Optional fixed fraction digits.
|
|
99
|
+
* @returns Formatted string with commas/grouping.
|
|
100
|
+
*/
|
|
101
|
+
export const formatWithCommas = (value, locale = 'en', decimals) => {
|
|
102
|
+
const opts = {};
|
|
103
|
+
if (decimals !== undefined) {
|
|
104
|
+
opts.minimumFractionDigits = decimals;
|
|
105
|
+
opts.maximumFractionDigits = decimals;
|
|
106
|
+
}
|
|
107
|
+
return new Intl.NumberFormat(locale, opts).format(value);
|
|
108
|
+
};
|
|
109
|
+
/**
|
|
110
|
+
* Calculate percentage of `part` out of `total`.
|
|
111
|
+
* @param part - Numerator.
|
|
112
|
+
* @param total - Denominator.
|
|
113
|
+
* @param decimals - Decimal places in the result.
|
|
114
|
+
* @returns Percentage value. Returns `0` if `total` is `0`.
|
|
115
|
+
*/
|
|
116
|
+
export const percentage = (part, total, decimals = 0) => {
|
|
117
|
+
if (total === 0)
|
|
118
|
+
return 0;
|
|
119
|
+
return roundTo((part / total) * 100, decimals);
|
|
120
|
+
};
|
|
121
|
+
/**
|
|
122
|
+
* Convert unknown input to a finite number with fallback.
|
|
123
|
+
* @param value - Value to convert.
|
|
124
|
+
* @param fallback - Value used when conversion is not finite.
|
|
125
|
+
* @returns Finite number from input, or `fallback`.
|
|
126
|
+
*/
|
|
127
|
+
export const toNumber = (value, fallback) => {
|
|
128
|
+
const n = typeof value === 'number' ? value : parseFloat(String(value));
|
|
129
|
+
return Number.isFinite(n) ? n : fallback;
|
|
130
|
+
};
|
|
131
|
+
/**
|
|
132
|
+
* Convert unknown input to an integer with fallback.
|
|
133
|
+
* @param value - Value to convert.
|
|
134
|
+
* @param fallback - Value used when conversion is not an integer.
|
|
135
|
+
* @returns Integer from input, or `fallback`.
|
|
136
|
+
*/
|
|
137
|
+
export const toInt = (value, fallback) => {
|
|
138
|
+
const n = typeof value === 'number' ? value : parseInt(String(value), 10);
|
|
139
|
+
return Number.isInteger(n) ? n : fallback;
|
|
140
|
+
};
|
|
141
|
+
//# sourceMappingURL=Nums.js.map
|
package/dist/Nums.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Nums.js","sourceRoot":"","sources":["../src/Nums.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
declare class passwordUtils {
|
|
2
|
+
/**
|
|
3
|
+
* Hash a password with bcrypt and return result as success/error object.
|
|
4
|
+
* @param password - Plain-text password.
|
|
5
|
+
* @param saltRounds - BCrypt salt rounds.
|
|
6
|
+
* @returns Success object with hash, or failure object with error.
|
|
7
|
+
*/
|
|
8
|
+
readonly hashPassword: (password: string, saltRounds?: number) => Promise<{
|
|
9
|
+
success: true;
|
|
10
|
+
hashedPassword: string;
|
|
11
|
+
} | {
|
|
12
|
+
success: false;
|
|
13
|
+
error: Error;
|
|
14
|
+
}>;
|
|
15
|
+
/**
|
|
16
|
+
* Hash a password with bcrypt and throw on failure.
|
|
17
|
+
* @param password - Plain-text password.
|
|
18
|
+
* @param saltRounds - BCrypt salt rounds.
|
|
19
|
+
* @returns Hashed password string.
|
|
20
|
+
* @throws {InternalServerError} If hashing fails.
|
|
21
|
+
*/
|
|
22
|
+
readonly hashPasswordOrThrow: (password: string, saltRounds?: number) => Promise<string>;
|
|
23
|
+
/**
|
|
24
|
+
* Compare plain-text password with bcrypt hash.
|
|
25
|
+
* @param password - Plain-text password.
|
|
26
|
+
* @param hashedPassword - BCrypt hash.
|
|
27
|
+
* @returns `true`/`false` comparison result, or `false` if comparison throws.
|
|
28
|
+
*/
|
|
29
|
+
readonly comparePassword: (password: string, hashedPassword: string) => Promise<boolean | null>;
|
|
30
|
+
/**
|
|
31
|
+
* Compare plain-text password with bcrypt hash and throw on failure.
|
|
32
|
+
* @param password - Plain-text password.
|
|
33
|
+
* @param hashedPassword - BCrypt hash.
|
|
34
|
+
* @returns `true` when password matches hash, otherwise `false`.
|
|
35
|
+
* @throws {InternalServerError} If comparison fails unexpectedly.
|
|
36
|
+
*/
|
|
37
|
+
readonly comparePasswordOrThrow: (password: string, hashedPassword: string) => Promise<boolean>;
|
|
38
|
+
/**
|
|
39
|
+
* Validate password length boundaries.
|
|
40
|
+
* @param password - Plain-text password.
|
|
41
|
+
* @param minLength - Inclusive minimum length.
|
|
42
|
+
* @param maxLength - Inclusive maximum length.
|
|
43
|
+
* @returns `true` when password length is within bounds.
|
|
44
|
+
*/
|
|
45
|
+
readonly validateStrength: (password: string, minLength: number, maxLength: number) => boolean;
|
|
46
|
+
/**
|
|
47
|
+
* Check whether a string appears to be a bcrypt hash.
|
|
48
|
+
* @param value - Input string.
|
|
49
|
+
* @returns `true` when input matches bcrypt hash pattern.
|
|
50
|
+
*/
|
|
51
|
+
readonly isBcryptHash: (value: string) => boolean;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Singleton instance of password utilities.
|
|
55
|
+
*/
|
|
56
|
+
export declare const PasswordUtils: passwordUtils;
|
|
57
|
+
export {};
|
|
58
|
+
//# sourceMappingURL=PasswordUtils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PasswordUtils.d.ts","sourceRoot":"","sources":["../src/PasswordUtils.ts"],"names":[],"mappings":"AAKA,cAAM,aAAa;IAClB;;;;;OAKG;IACH,QAAQ,CAAC,YAAY,GACpB,UAAU,MAAM,EAChB,mBAAgC,KAC9B,OAAO,CAAC;QAAE,OAAO,EAAE,IAAI,CAAC;QAAC,cAAc,EAAE,MAAM,CAAA;KAAE,GAAG;QAAE,OAAO,EAAE,KAAK,CAAC;QAAC,KAAK,EAAE,KAAK,CAAA;KAAE,CAAC,CAOtF;IAEF;;;;;;OAMG;IACH,QAAQ,CAAC,mBAAmB,GAC3B,UAAU,MAAM,EAChB,mBAAgC,KAC9B,OAAO,CAAC,MAAM,CAAC,CAOhB;IAEF;;;;;OAKG;IACH,QAAQ,CAAC,eAAe,GACvB,UAAU,MAAM,EAChB,gBAAgB,MAAM,KACpB,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAOxB;IAEF;;;;;;OAMG;IACH,QAAQ,CAAC,sBAAsB,GAC9B,UAAU,MAAM,EAChB,gBAAgB,MAAM,KACpB,OAAO,CAAC,OAAO,CAAC,CAOjB;IAEF;;;;;;OAMG;IACH,QAAQ,CAAC,gBAAgB,GAAI,UAAU,MAAM,EAAE,WAAW,MAAM,EAAE,WAAW,MAAM,KAAG,OAAO,CAC/B;IAE9D;;;;OAIG;IACH,QAAQ,CAAC,YAAY,GAAI,OAAO,MAAM,KAAG,OAAO,CACI;CACpD;AAED;;GAEG;AACH,eAAO,MAAM,aAAa,eAAsB,CAAC"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import bcrypt from "bcrypt";
|
|
2
|
+
import { InternalServerError } from "./ErrorClasses.js";
|
|
3
|
+
const DEFAULT_SALT_ROUNDS = 10;
|
|
4
|
+
class passwordUtils {
|
|
5
|
+
/**
|
|
6
|
+
* Hash a password with bcrypt and return result as success/error object.
|
|
7
|
+
* @param password - Plain-text password.
|
|
8
|
+
* @param saltRounds - BCrypt salt rounds.
|
|
9
|
+
* @returns Success object with hash, or failure object with error.
|
|
10
|
+
*/
|
|
11
|
+
hashPassword = async (password, saltRounds = DEFAULT_SALT_ROUNDS) => {
|
|
12
|
+
try {
|
|
13
|
+
return { success: true, hashedPassword: await bcrypt.hash(password, saltRounds) };
|
|
14
|
+
}
|
|
15
|
+
catch (error) {
|
|
16
|
+
return { success: false, error: error };
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* Hash a password with bcrypt and throw on failure.
|
|
21
|
+
* @param password - Plain-text password.
|
|
22
|
+
* @param saltRounds - BCrypt salt rounds.
|
|
23
|
+
* @returns Hashed password string.
|
|
24
|
+
* @throws {InternalServerError} If hashing fails.
|
|
25
|
+
*/
|
|
26
|
+
hashPasswordOrThrow = async (password, saltRounds = DEFAULT_SALT_ROUNDS) => {
|
|
27
|
+
try {
|
|
28
|
+
return await bcrypt.hash(password, saltRounds);
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
throw new InternalServerError();
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* Compare plain-text password with bcrypt hash.
|
|
36
|
+
* @param password - Plain-text password.
|
|
37
|
+
* @param hashedPassword - BCrypt hash.
|
|
38
|
+
* @returns `true`/`false` comparison result, or `false` if comparison throws.
|
|
39
|
+
*/
|
|
40
|
+
comparePassword = async (password, hashedPassword) => {
|
|
41
|
+
try {
|
|
42
|
+
return await bcrypt.compare(password, hashedPassword);
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
/**
|
|
49
|
+
* Compare plain-text password with bcrypt hash and throw on failure.
|
|
50
|
+
* @param password - Plain-text password.
|
|
51
|
+
* @param hashedPassword - BCrypt hash.
|
|
52
|
+
* @returns `true` when password matches hash, otherwise `false`.
|
|
53
|
+
* @throws {InternalServerError} If comparison fails unexpectedly.
|
|
54
|
+
*/
|
|
55
|
+
comparePasswordOrThrow = async (password, hashedPassword) => {
|
|
56
|
+
try {
|
|
57
|
+
return await bcrypt.compare(password, hashedPassword);
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
throw new InternalServerError();
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
/**
|
|
64
|
+
* Validate password length boundaries.
|
|
65
|
+
* @param password - Plain-text password.
|
|
66
|
+
* @param minLength - Inclusive minimum length.
|
|
67
|
+
* @param maxLength - Inclusive maximum length.
|
|
68
|
+
* @returns `true` when password length is within bounds.
|
|
69
|
+
*/
|
|
70
|
+
validateStrength = (password, minLength, maxLength) => password.length >= minLength && password.length <= maxLength;
|
|
71
|
+
/**
|
|
72
|
+
* Check whether a string appears to be a bcrypt hash.
|
|
73
|
+
* @param value - Input string.
|
|
74
|
+
* @returns `true` when input matches bcrypt hash pattern.
|
|
75
|
+
*/
|
|
76
|
+
isBcryptHash = (value) => /^\$2[aby]\$\d{2}\$[./A-Za-z0-9]{53}$/.test(value);
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Singleton instance of password utilities.
|
|
80
|
+
*/
|
|
81
|
+
export const PasswordUtils = new passwordUtils();
|
|
82
|
+
//# sourceMappingURL=PasswordUtils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PasswordUtils.js","sourceRoot":"","sources":["../src/PasswordUtils.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAExD,MAAM,mBAAmB,GAAG,EAAE,CAAC;AAE/B,MAAM,aAAa;IAClB;;;;;OAKG;IACM,YAAY,GAAG,KAAK,EAC5B,QAAgB,EAChB,UAAU,GAAG,mBAAmB,EACwD,EAAE;QAC1F,IAAI,CAAC;YACJ,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,cAAc,EAAE,MAAM,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,UAAU,CAAC,EAAE,CAAC;QACnF,CAAC;QACD,OAAO,KAAK,EAAE,CAAC;YACd,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAc,EAAE,CAAC;QAClD,CAAC;IACF,CAAC,CAAC;IAEF;;;;;;OAMG;IACM,mBAAmB,GAAG,KAAK,EACnC,QAAgB,EAChB,UAAU,GAAG,mBAAmB,EACd,EAAE;QACpB,IAAI,CAAC;YACJ,OAAO,MAAM,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;QAChD,CAAC;QACD,MAAM,CAAC;YACN,MAAM,IAAI,mBAAmB,EAAE,CAAC;QACjC,CAAC;IACF,CAAC,CAAC;IAEF;;;;;OAKG;IACM,eAAe,GAAG,KAAK,EAC/B,QAAgB,EAChB,cAAsB,EACI,EAAE;QAC5B,IAAI,CAAC;YACJ,OAAO,MAAM,MAAM,CAAC,OAAO,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC;QACvD,CAAC;QACD,MAAM,CAAC;YACN,OAAO,KAAK,CAAC;QACd,CAAC;IACF,CAAC,CAAC;IAEF;;;;;;OAMG;IACM,sBAAsB,GAAG,KAAK,EACtC,QAAgB,EAChB,cAAsB,EACH,EAAE;QACrB,IAAI,CAAC;YACJ,OAAO,MAAM,MAAM,CAAC,OAAO,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC;QACvD,CAAC;QACD,MAAM,CAAC;YACN,MAAM,IAAI,mBAAmB,EAAE,CAAC;QACjC,CAAC;IACF,CAAC,CAAC;IAEF;;;;;;OAMG;IACM,gBAAgB,GAAG,CAAC,QAAgB,EAAE,SAAiB,EAAE,SAAiB,EAAW,EAAE,CAC/F,QAAQ,CAAC,MAAM,IAAI,SAAS,IAAI,QAAQ,CAAC,MAAM,IAAI,SAAS,CAAC;IAE9D;;;;OAIG;IACM,YAAY,GAAG,CAAC,KAAa,EAAW,EAAE,CAClD,sCAAsC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;CACpD;AAED;;GAEG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,IAAI,aAAa,EAAE,CAAC"}
|
package/dist/Rand.d.ts
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pseudo-random integer between `min` and `max` (inclusive) using `Math.random()`.
|
|
3
|
+
* @param min - Inclusive lower bound.
|
|
4
|
+
* @param max - Inclusive upper bound.
|
|
5
|
+
* @returns A pseudo-random integer `n` such that `min <= n <= max`.
|
|
6
|
+
*/
|
|
7
|
+
export declare const srandInt: (min: number, max: number) => number;
|
|
8
|
+
/**
|
|
9
|
+
* Crypto-random integer between `min` and `max` (inclusive).
|
|
10
|
+
* @param min - Inclusive lower bound. Must be a safe integer.
|
|
11
|
+
* @param max - Inclusive upper bound. Must be a safe integer.
|
|
12
|
+
* @returns A crypto-random integer `n` such that `min <= n <= max`.
|
|
13
|
+
* @throws {TypeError} If `min` or `max` are not safe integers.
|
|
14
|
+
* @throws {RangeError} If `max < min`.
|
|
15
|
+
*/
|
|
16
|
+
export declare const randInt: (min: number, max: number) => number;
|
|
17
|
+
/**
|
|
18
|
+
* Pseudo-random float between `min` and `max`.
|
|
19
|
+
* Note: uses `Math.random()`, so the result is effectively in `[min, max)` (with `max` excluded).
|
|
20
|
+
* @param min - Inclusive lower bound.
|
|
21
|
+
* @param max - Upper bound (effectively exclusive).
|
|
22
|
+
* @returns A pseudo-random number `x` such that `min <= x < max`.
|
|
23
|
+
*/
|
|
24
|
+
export declare const srandFloat: (min: number, max: number) => number;
|
|
25
|
+
/**
|
|
26
|
+
* Crypto-random float between `min` and `max` (inclusive).
|
|
27
|
+
* @param min - Inclusive lower bound.
|
|
28
|
+
* @param max - Inclusive upper bound.
|
|
29
|
+
* @returns A crypto-random number `x` such that `min <= x <= max` (subject to normal floating-point rounding).
|
|
30
|
+
*/
|
|
31
|
+
export declare const randFloat: (min: number, max: number) => number;
|
|
32
|
+
/**
|
|
33
|
+
* Generates a crypto-random RFC4122 v4 UUID.
|
|
34
|
+
* @returns A UUID string (e.g. `xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx`).
|
|
35
|
+
*/
|
|
36
|
+
export declare const randUuid: () => string;
|
|
37
|
+
/**
|
|
38
|
+
* Crypto-random Base58 string.
|
|
39
|
+
* Uses `randInt(0, max)` with an inclusive `max` contract.
|
|
40
|
+
* @param length - Number of characters to generate.
|
|
41
|
+
* @returns A Base58 string of length `length` (or `""` if `length <= 0`).
|
|
42
|
+
*/
|
|
43
|
+
export declare const randStr: (length: number) => string;
|
|
44
|
+
//# sourceMappingURL=Rand.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Rand.d.ts","sourceRoot":"","sources":["../src/Rand.ts"],"names":[],"mappings":"AAIA;;;;;GAKG;AACH,eAAO,MAAM,QAAQ,GAAI,KAAK,MAAM,EAAE,KAAK,MAAM,WACC,CAAC;AAEnD;;;;;;;GAOG;AACH,eAAO,MAAM,OAAO,GAAI,KAAK,MAAM,EAAE,KAAK,MAAM,WAW/C,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,UAAU,GAAI,KAAK,MAAM,EAAE,KAAK,MAAM,WAAsC,CAAC;AAE1F;;;;;GAKG;AACH,eAAO,MAAM,SAAS,GAAI,KAAK,MAAM,EAAE,KAAK,MAAM,WAUjD,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,QAAQ,QAAO,MAAsB,CAAC;AAEnD;;;;;GAKG;AACH,eAAO,MAAM,OAAO,GAAI,QAAQ,MAAM,WAOrC,CAAA"}
|
package/dist/Rand.js
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { randomUUID, randomInt as cryptoRandomInt } from "crypto";
|
|
2
|
+
const BASE58_CHARS = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';
|
|
3
|
+
/**
|
|
4
|
+
* Pseudo-random integer between `min` and `max` (inclusive) using `Math.random()`.
|
|
5
|
+
* @param min - Inclusive lower bound.
|
|
6
|
+
* @param max - Inclusive upper bound.
|
|
7
|
+
* @returns A pseudo-random integer `n` such that `min <= n <= max`.
|
|
8
|
+
*/
|
|
9
|
+
export const srandInt = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min;
|
|
10
|
+
/**
|
|
11
|
+
* Crypto-random integer between `min` and `max` (inclusive).
|
|
12
|
+
* @param min - Inclusive lower bound. Must be a safe integer.
|
|
13
|
+
* @param max - Inclusive upper bound. Must be a safe integer.
|
|
14
|
+
* @returns A crypto-random integer `n` such that `min <= n <= max`.
|
|
15
|
+
* @throws {TypeError} If `min` or `max` are not safe integers.
|
|
16
|
+
* @throws {RangeError} If `max < min`.
|
|
17
|
+
*/
|
|
18
|
+
export const randInt = (min, max) => {
|
|
19
|
+
// Node's `crypto.randomInt` uses an exclusive upper bound.
|
|
20
|
+
// We keep the previous inclusive `max` contract.
|
|
21
|
+
if (!Number.isSafeInteger(min) || !Number.isSafeInteger(max)) {
|
|
22
|
+
throw new TypeError("randInt(min, max) requires safe integers");
|
|
23
|
+
}
|
|
24
|
+
if (max < min) {
|
|
25
|
+
throw new RangeError("randInt(min, max): max must be >= min");
|
|
26
|
+
}
|
|
27
|
+
return cryptoRandomInt(min, max + 1);
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Pseudo-random float between `min` and `max`.
|
|
31
|
+
* Note: uses `Math.random()`, so the result is effectively in `[min, max)` (with `max` excluded).
|
|
32
|
+
* @param min - Inclusive lower bound.
|
|
33
|
+
* @param max - Upper bound (effectively exclusive).
|
|
34
|
+
* @returns A pseudo-random number `x` such that `min <= x < max`.
|
|
35
|
+
*/
|
|
36
|
+
export const srandFloat = (min, max) => Math.random() * (max - min) + min;
|
|
37
|
+
/**
|
|
38
|
+
* Crypto-random float between `min` and `max` (inclusive).
|
|
39
|
+
* @param min - Inclusive lower bound.
|
|
40
|
+
* @param max - Inclusive upper bound.
|
|
41
|
+
* @returns A crypto-random number `x` such that `min <= x <= max` (subject to normal floating-point rounding).
|
|
42
|
+
*/
|
|
43
|
+
export const randFloat = (min, max) => {
|
|
44
|
+
const range = max - min;
|
|
45
|
+
if (range === 0)
|
|
46
|
+
return min;
|
|
47
|
+
// Uniform value in [0, 1] using 48 random bits (inclusive upper endpoint).
|
|
48
|
+
// `crypto.randomInt(min, max)` treats `max` as exclusive.
|
|
49
|
+
const maxInclusiveInt = 2 ** 48 - 2;
|
|
50
|
+
const uInt = cryptoRandomInt(0, maxInclusiveInt + 1); // -> [0, maxInclusiveInt]
|
|
51
|
+
const u = uInt / maxInclusiveInt; // -> [0, 1]
|
|
52
|
+
return min + u * range;
|
|
53
|
+
};
|
|
54
|
+
/**
|
|
55
|
+
* Generates a crypto-random RFC4122 v4 UUID.
|
|
56
|
+
* @returns A UUID string (e.g. `xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx`).
|
|
57
|
+
*/
|
|
58
|
+
export const randUuid = () => randomUUID();
|
|
59
|
+
/**
|
|
60
|
+
* Crypto-random Base58 string.
|
|
61
|
+
* Uses `randInt(0, max)` with an inclusive `max` contract.
|
|
62
|
+
* @param length - Number of characters to generate.
|
|
63
|
+
* @returns A Base58 string of length `length` (or `""` if `length <= 0`).
|
|
64
|
+
*/
|
|
65
|
+
export const randStr = (length) => {
|
|
66
|
+
let result = '';
|
|
67
|
+
for (let i = 0; i < length; i++) {
|
|
68
|
+
result += BASE58_CHARS[randInt(0, BASE58_CHARS.length - 1)];
|
|
69
|
+
}
|
|
70
|
+
return result;
|
|
71
|
+
};
|
|
72
|
+
//# sourceMappingURL=Rand.js.map
|
package/dist/Rand.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Rand.js","sourceRoot":"","sources":["../src/Rand.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,IAAI,eAAe,EAAE,MAAM,QAAQ,CAAC;AAElE,MAAM,YAAY,GAAG,4DAA4D,CAAC;AAElF;;;;;GAKG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,GAAW,EAAE,GAAW,EAAE,EAAE,CACpD,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC;AAEnD;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,GAAW,EAAE,GAAW,EAAE,EAAE;IACnD,2DAA2D;IAC3D,iDAAiD;IACjD,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,GAAG,CAAC,EAAE,CAAC;QAC9D,MAAM,IAAI,SAAS,CAAC,0CAA0C,CAAC,CAAC;IACjE,CAAC;IACD,IAAI,GAAG,GAAG,GAAG,EAAE,CAAC;QACf,MAAM,IAAI,UAAU,CAAC,uCAAuC,CAAC,CAAC;IAC/D,CAAC;IAED,OAAO,eAAe,CAAC,GAAG,EAAE,GAAG,GAAG,CAAC,CAAC,CAAC;AACtC,CAAC,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,GAAW,EAAE,GAAW,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG,GAAG,CAAC,GAAG,GAAG,CAAC;AAE1F;;;;;GAKG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,GAAW,EAAE,GAAW,EAAE,EAAE;IACrD,MAAM,KAAK,GAAG,GAAG,GAAG,GAAG,CAAC;IACxB,IAAI,KAAK,KAAK,CAAC;QAAE,OAAO,GAAG,CAAC;IAE5B,2EAA2E;IAC3E,0DAA0D;IAC1D,MAAM,eAAe,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IACpC,MAAM,IAAI,GAAG,eAAe,CAAC,CAAC,EAAE,eAAe,GAAG,CAAC,CAAC,CAAC,CAAC,0BAA0B;IAChF,MAAM,CAAC,GAAG,IAAI,GAAG,eAAe,CAAC,CAAC,YAAY;IAC9C,OAAO,GAAG,GAAG,CAAC,GAAG,KAAK,CAAC;AACxB,CAAC,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,GAAW,EAAE,CAAC,UAAU,EAAE,CAAC;AAEnD;;;;;GAKG;AACH,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,MAAc,EAAE,EAAE;IACzC,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACjC,MAAM,IAAI,YAAY,CAAC,OAAO,CAAC,CAAC,EAAE,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;IAC7D,CAAC;IAED,OAAO,MAAM,CAAC;AACf,CAAC,CAAA"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type { TAppEnvs } from "./types.js";
|
|
2
|
+
type customErrCodes = "invalid-token-format" | "token-too-long" | "action-mismatch" | "hostname-mismatch" | "validation-timeout" | "internal-error";
|
|
3
|
+
type TurnstileValidationError = {
|
|
4
|
+
'success': false;
|
|
5
|
+
'error-codes': (customErrCodes | 'missing-input-secret' | 'invalid-input-secret' | 'missing-input-response' | 'invalid-input-response' | 'bad-request' | 'timeout-or-duplicate' | 'internal-error')[];
|
|
6
|
+
};
|
|
7
|
+
type TurnstileValidationSuccess = {
|
|
8
|
+
'success': true;
|
|
9
|
+
'challenge_ts': string;
|
|
10
|
+
'hostname': string;
|
|
11
|
+
'error-codes': [];
|
|
12
|
+
'action': string;
|
|
13
|
+
'cdata': unknown;
|
|
14
|
+
'metadata': {
|
|
15
|
+
'ephemeral_id': string;
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
type TurnstileValidationResult = [null, TurnstileValidationError] | [TurnstileValidationSuccess, null];
|
|
19
|
+
declare class turnstileValidator {
|
|
20
|
+
/**
|
|
21
|
+
* Validate a Cloudflare Turnstile token.
|
|
22
|
+
* @param secretKey - Turnstile secret key.
|
|
23
|
+
* @param token - Token submitted by the client.
|
|
24
|
+
* @param remoteip - Optional client IP.
|
|
25
|
+
* @param options - Optional expected action/hostname and idempotency key.
|
|
26
|
+
* @param timeout - Request timeout in milliseconds.
|
|
27
|
+
* @param _appEnv - Reserved for callers (e.g. future logging policy); unused.
|
|
28
|
+
* @returns Tuple of `[successResult, null]` or `[null, errorResult]`.
|
|
29
|
+
*/
|
|
30
|
+
readonly validate: (secretKey: string, token: string, remoteip: string | null | undefined, options: {
|
|
31
|
+
expectedAction?: string;
|
|
32
|
+
expectedHostname?: string;
|
|
33
|
+
idempotencyKey?: string;
|
|
34
|
+
} | undefined, timeout: number | undefined, _appEnv: TAppEnvs) => Promise<TurnstileValidationResult>;
|
|
35
|
+
/**
|
|
36
|
+
* Validate Turnstile token and throw on failure.
|
|
37
|
+
* @param secretKey - Turnstile secret key.
|
|
38
|
+
* @param token - Token submitted by the client.
|
|
39
|
+
* @param remoteip - Optional client IP.
|
|
40
|
+
* @param options - Optional expected action/hostname and idempotency key.
|
|
41
|
+
* @param timeout - Request timeout in milliseconds.
|
|
42
|
+
* @param APP_ENV - Reserved; forwarded to `validate` for API stability.
|
|
43
|
+
* @returns Successful Turnstile verification payload.
|
|
44
|
+
* @throws {BadRequest} When token validation fails.
|
|
45
|
+
*/
|
|
46
|
+
readonly validateOrThrow: (secretKey: string, token: string, remoteip: string | null | undefined, options: {
|
|
47
|
+
expectedAction?: string;
|
|
48
|
+
expectedHostname?: string;
|
|
49
|
+
idempotencyKey?: string;
|
|
50
|
+
} | undefined, timeout: number | undefined, APP_ENV: TAppEnvs) => Promise<TurnstileValidationSuccess>;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Singleton instance of Turnstile validation utilities.
|
|
54
|
+
*/
|
|
55
|
+
export declare const TurnstileValidator: turnstileValidator;
|
|
56
|
+
export {};
|
|
57
|
+
//# sourceMappingURL=TurnstileValidator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TurnstileValidator.d.ts","sourceRoot":"","sources":["../src/TurnstileValidator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAG3C,KAAK,cAAc,GAAG,sBAAsB,GAC3C,gBAAgB,GAChB,iBAAiB,GACjB,mBAAmB,GACnB,oBAAoB,GACpB,gBAAgB,CAAC;AAElB,KAAK,wBAAwB,GAAG;IAC/B,SAAS,EAAE,KAAK,CAAC;IACjB,aAAa,EAAE,CACd,cAAc,GACd,sBAAsB,GACtB,sBAAsB,GACtB,wBAAwB,GACxB,wBAAwB,GACxB,aAAa,GACb,sBAAsB,GACtB,gBAAgB,CAChB,EAAE,CAAC;CACJ,CAAC;AAEF,KAAK,0BAA0B,GAAG;IACjC,SAAS,EAAE,IAAI,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,EAAE,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE;QACX,cAAc,EAAE,MAAM,CAAC;KACvB,CAAC;CACF,CAAA;AAED,KAAK,yBAAyB,GAAG,CAAC,IAAI,EAAE,wBAAwB,CAAC,GAAG,CAAC,0BAA0B,EAAE,IAAI,CAAC,CAAC;AAGvG,cAAM,kBAAkB;IACvB;;;;;;;;;OASG;IACH,QAAQ,CAAC,QAAQ,GAChB,WAAW,MAAM,EACjB,OAAO,MAAM,EACb,UAAU,MAAM,GAAG,IAAI,GAAG,SAAS,EACnC,SAAS;QAAE,cAAc,CAAC,EAAE,MAAM,CAAC;QAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;QAAC,cAAc,CAAC,EAAE,MAAM,CAAA;KAAE,YAAK,EAC7F,2BAAe,EACf,SAAS,QAAQ,KACf,OAAO,CAAC,yBAAyB,CAAC,CAmFpC;IAED;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,eAAe,GACvB,WAAW,MAAM,EACjB,OAAO,MAAM,EACb,UAAU,MAAM,GAAG,IAAI,GAAG,SAAS,EACnC,SAAS;QAAE,cAAc,CAAC,EAAE,MAAM,CAAC;QAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;QAAC,cAAc,CAAC,EAAE,MAAM,CAAA;KAAE,YAAK,EAC7F,2BAAe,EACf,SAAS,QAAQ,KACf,OAAO,CAAC,0BAA0B,CAAC,CAMrC;CACD;AAED;;GAEG;AACH,eAAO,MAAM,kBAAkB,oBAA2B,CAAC"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { BadRequest } from "./ErrorClasses.js";
|
|
2
|
+
class turnstileValidator {
|
|
3
|
+
/**
|
|
4
|
+
* Validate a Cloudflare Turnstile token.
|
|
5
|
+
* @param secretKey - Turnstile secret key.
|
|
6
|
+
* @param token - Token submitted by the client.
|
|
7
|
+
* @param remoteip - Optional client IP.
|
|
8
|
+
* @param options - Optional expected action/hostname and idempotency key.
|
|
9
|
+
* @param timeout - Request timeout in milliseconds.
|
|
10
|
+
* @param _appEnv - Reserved for callers (e.g. future logging policy); unused.
|
|
11
|
+
* @returns Tuple of `[successResult, null]` or `[null, errorResult]`.
|
|
12
|
+
*/
|
|
13
|
+
validate = async (secretKey, token, remoteip, options = {}, timeout = 10000, _appEnv) => {
|
|
14
|
+
// Input validation
|
|
15
|
+
if (!token || typeof token !== "string") {
|
|
16
|
+
return [null, { success: false, 'error-codes': ["invalid-token-format"] }];
|
|
17
|
+
}
|
|
18
|
+
if (token.length > 2048) {
|
|
19
|
+
return [null, { success: false, 'error-codes': ["token-too-long"] }];
|
|
20
|
+
}
|
|
21
|
+
// Prepare request
|
|
22
|
+
const controller = new AbortController();
|
|
23
|
+
const timeoutId = setTimeout(() => controller.abort(), timeout);
|
|
24
|
+
try {
|
|
25
|
+
const formData = new FormData();
|
|
26
|
+
formData.append("secret", secretKey);
|
|
27
|
+
formData.append("response", token);
|
|
28
|
+
if (remoteip) {
|
|
29
|
+
formData.append("remoteip", remoteip);
|
|
30
|
+
}
|
|
31
|
+
if (options.idempotencyKey) {
|
|
32
|
+
formData.append("idempotency_key", options.idempotencyKey);
|
|
33
|
+
}
|
|
34
|
+
const response = await fetch("https://challenges.cloudflare.com/turnstile/v0/siteverify", {
|
|
35
|
+
method: "POST",
|
|
36
|
+
body: formData,
|
|
37
|
+
signal: controller.signal,
|
|
38
|
+
});
|
|
39
|
+
if (!response.ok) {
|
|
40
|
+
return [null, { success: false, 'error-codes': ["internal-error"] }];
|
|
41
|
+
}
|
|
42
|
+
let result;
|
|
43
|
+
try {
|
|
44
|
+
result = await response.json();
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
return [null, { success: false, 'error-codes': ["internal-error"] }];
|
|
48
|
+
}
|
|
49
|
+
if (typeof result !== "object" || result === null || !("success" in result)) {
|
|
50
|
+
return [null, { success: false, 'error-codes': ["internal-error"] }];
|
|
51
|
+
}
|
|
52
|
+
// Additional validation
|
|
53
|
+
if (result.success) {
|
|
54
|
+
if (options.expectedAction &&
|
|
55
|
+
result.action !== options.expectedAction) {
|
|
56
|
+
return [null, { success: false, 'error-codes': ["action-mismatch"] }];
|
|
57
|
+
}
|
|
58
|
+
if (options.expectedHostname &&
|
|
59
|
+
result.hostname !== options.expectedHostname) {
|
|
60
|
+
return [null, { success: false, 'error-codes': ["hostname-mismatch"] }];
|
|
61
|
+
}
|
|
62
|
+
return [result, null];
|
|
63
|
+
}
|
|
64
|
+
return [null, result];
|
|
65
|
+
}
|
|
66
|
+
catch (error) {
|
|
67
|
+
if (error instanceof Error && error.name === "AbortError") {
|
|
68
|
+
return [null, { success: false, 'error-codes': ["validation-timeout"] }];
|
|
69
|
+
}
|
|
70
|
+
return [null, { success: false, 'error-codes': ["internal-error"] }];
|
|
71
|
+
}
|
|
72
|
+
finally {
|
|
73
|
+
clearTimeout(timeoutId);
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
/**
|
|
77
|
+
* Validate Turnstile token and throw on failure.
|
|
78
|
+
* @param secretKey - Turnstile secret key.
|
|
79
|
+
* @param token - Token submitted by the client.
|
|
80
|
+
* @param remoteip - Optional client IP.
|
|
81
|
+
* @param options - Optional expected action/hostname and idempotency key.
|
|
82
|
+
* @param timeout - Request timeout in milliseconds.
|
|
83
|
+
* @param APP_ENV - Reserved; forwarded to `validate` for API stability.
|
|
84
|
+
* @returns Successful Turnstile verification payload.
|
|
85
|
+
* @throws {BadRequest} When token validation fails.
|
|
86
|
+
*/
|
|
87
|
+
validateOrThrow = async (secretKey, token, remoteip, options = {}, timeout = 10000, APP_ENV) => {
|
|
88
|
+
const [result, error] = await this.validate(secretKey, token, remoteip, options, timeout, APP_ENV);
|
|
89
|
+
if (error) {
|
|
90
|
+
throw new BadRequest('CAPTCHA__VALIDATION_FAILED');
|
|
91
|
+
}
|
|
92
|
+
return result;
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Singleton instance of Turnstile validation utilities.
|
|
97
|
+
*/
|
|
98
|
+
export const TurnstileValidator = new turnstileValidator();
|
|
99
|
+
//# sourceMappingURL=TurnstileValidator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TurnstileValidator.js","sourceRoot":"","sources":["../src/TurnstileValidator.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAsC/C,MAAM,kBAAkB;IACvB;;;;;;;;;OASG;IACM,QAAQ,GAAG,KAAK,EACxB,SAAiB,EACjB,KAAa,EACb,QAAmC,EACnC,UAA2F,EAAE,EAC7F,OAAO,GAAG,KAAK,EACf,OAAiB,EACoB,EAAE;QAEvC,mBAAmB;QACnB,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;YACzC,OAAO,CAAC,IAAI,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,CAAC,sBAAsB,CAAC,EAAE,CAAC,CAAC;QAC5E,CAAC;QAED,IAAI,KAAK,CAAC,MAAM,GAAG,IAAI,EAAE,CAAC;YACzB,OAAO,CAAC,IAAI,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,CAAC,gBAAgB,CAAC,EAAE,CAAC,CAAC;QACtE,CAAC;QAED,kBAAkB;QAClB,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;QACzC,MAAM,SAAS,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,OAAO,CAAC,CAAC;QAEhE,IAAI,CAAC;YACJ,MAAM,QAAQ,GAAG,IAAI,QAAQ,EAAE,CAAC;YAChC,QAAQ,CAAC,MAAM,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;YACrC,QAAQ,CAAC,MAAM,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;YAEnC,IAAI,QAAQ,EAAE,CAAC;gBACd,QAAQ,CAAC,MAAM,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;YACvC,CAAC;YAED,IAAI,OAAO,CAAC,cAAc,EAAE,CAAC;gBAC5B,QAAQ,CAAC,MAAM,CAAC,iBAAiB,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC;YAC5D,CAAC;YAED,MAAM,QAAQ,GAAG,MAAM,KAAK,CAC3B,2DAA2D,EAC3D;gBACC,MAAM,EAAE,MAAM;gBACd,IAAI,EAAE,QAAQ;gBACd,MAAM,EAAE,UAAU,CAAC,MAAM;aACzB,CACD,CAAC;YAEF,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;gBAClB,OAAO,CAAC,IAAI,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,CAAC,gBAAgB,CAAC,EAAE,CAAC,CAAC;YACtE,CAAC;YAED,IAAI,MAA6D,CAAC;YAClE,IAAI,CAAC;gBACJ,MAAM,GAAG,MAAM,QAAQ,CAAC,IAAI,EAA2D,CAAC;YACzF,CAAC;YACD,MAAM,CAAC;gBACN,OAAO,CAAC,IAAI,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,CAAC,gBAAgB,CAAC,EAAE,CAAC,CAAC;YACtE,CAAC;YAED,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI,IAAI,CAAC,CAAC,SAAS,IAAI,MAAM,CAAC,EAAE,CAAC;gBAC7E,OAAO,CAAC,IAAI,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,CAAC,gBAAgB,CAAC,EAAE,CAAC,CAAC;YACtE,CAAC;YAED,wBAAwB;YACxB,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;gBACpB,IACC,OAAO,CAAC,cAAc;oBACtB,MAAM,CAAC,MAAM,KAAK,OAAO,CAAC,cAAc,EACvC,CAAC;oBACF,OAAO,CAAC,IAAI,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,CAAC,iBAAiB,CAAC,EAAE,CAAC,CAAC;gBACvE,CAAC;gBAED,IACC,OAAO,CAAC,gBAAgB;oBACxB,MAAM,CAAC,QAAQ,KAAK,OAAO,CAAC,gBAAgB,EAC3C,CAAC;oBACF,OAAO,CAAC,IAAI,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,CAAC,mBAAmB,CAAC,EAAE,CAAC,CAAC;gBACzE,CAAC;gBAED,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;YACvB,CAAC;YAED,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACvB,CAAC;QACD,OAAO,KAAK,EAAE,CAAC;YACd,IAAI,KAAK,YAAY,KAAK,IAAI,KAAK,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;gBAC3D,OAAO,CAAC,IAAI,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,CAAC,oBAAoB,CAAC,EAAE,CAAC,CAAC;YAC1E,CAAC;YACD,OAAO,CAAC,IAAI,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,CAAC,gBAAgB,CAAC,EAAE,CAAC,CAAC;QACtE,CAAC;gBACO,CAAC;YACR,YAAY,CAAC,SAAS,CAAC,CAAC;QACzB,CAAC;IACF,CAAC,CAAA;IAED;;;;;;;;;;OAUG;IACM,eAAe,GAAG,KAAK,EAC/B,SAAiB,EACjB,KAAa,EACb,QAAmC,EACnC,UAA2F,EAAE,EAC7F,OAAO,GAAG,KAAK,EACf,OAAiB,EACqB,EAAE;QACxC,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;QACnG,IAAI,KAAK,EAAE,CAAC;YACX,MAAM,IAAI,UAAU,CAAC,4BAA4B,CAAC,CAAC;QACpD,CAAC;QACD,OAAO,MAAM,CAAC;IACf,CAAC,CAAA;CACD;AAED;;GAEG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,IAAI,kBAAkB,EAAE,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { TMonths, TMonthsShorts } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Convert ASCII digits in the input to Bengali digits.
|
|
4
|
+
* Non-digit characters are preserved as-is.
|
|
5
|
+
* @param num - A number or string to convert.
|
|
6
|
+
* @returns A string where `0-9` are replaced by their Bengali equivalents.
|
|
7
|
+
*/
|
|
8
|
+
export declare const bnNum: (num: number | string) => string;
|
|
9
|
+
/**
|
|
10
|
+
* Convert a lowercase English month (full/short) or month number to the Bengali month name.
|
|
11
|
+
* @param month - Month as a number (`1-12`), lowercase full English month name, or lowercase short English month name.
|
|
12
|
+
* @returns The Bengali month name string for known inputs; otherwise returns the original `month` value.
|
|
13
|
+
*/
|
|
14
|
+
export declare const monthToBn: (month: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | TMonths | TMonthsShorts) => string;
|
|
15
|
+
//# sourceMappingURL=bnUtils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bnUtils.d.ts","sourceRoot":"","sources":["../src/bnUtils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEzD;;;;;GAKG;AACH,eAAO,MAAM,KAAK,GAAI,KAAK,MAAM,GAAG,MAAM,KAAG,MAiB5C,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,SAAS,GACrB,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,OAAO,GAAG,aAAa,KAC/E,MAcF,CAAC"}
|