@cripty2001/utils 0.0.230 → 0.0.232

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/dist/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { Whispr } from "@cripty2001/whispr";
2
+ import type { TSchema } from "@sinclair/typebox";
2
3
  export type JSONEncodable = number | string | boolean | JSONEncodable[] | null | {
3
4
  [key: string]: JSONEncodable;
4
5
  };
@@ -11,6 +12,13 @@ export type ExactlyOne<T> = {
11
12
  [K in keyof T]: Pick<T, K> & Partial<Record<Exclude<keyof T, K>, never>>;
12
13
  }[keyof T];
13
14
  export type AllRequired<T> = T extends ExactlyOne<infer U> ? ExactlyOne<Required<U>> : never;
15
+ /**
16
+ * Generate a random number between 0 and `maxExclusive - 1`.
17
+ * @param maxExclusive The maximum exclusive value to generate
18
+ * @returns A random number between 0 and `maxExclusive - 1`
19
+ * @throws If `maxExclusive` is less than 1 or greater than 2^32
20
+ */
21
+ export declare function randomBelow(maxExclusive: number): number;
14
22
  /**
15
23
  * Generate a random string from the given alphabeth.
16
24
  * @param _alphabeth The alphabeth to draw characters from
@@ -74,15 +82,51 @@ export declare function parseQuery(query: string | Record<string, any> | URLSear
74
82
  * @param min The minimum allowed number
75
83
  * @param max The maximum allowed number
76
84
  * @returns The generated random int
85
+ * @throws If `max - min + 1` is greater than 2^32
77
86
  */
78
87
  export declare function randBetween(min: number, max: number): number;
88
+ export declare class GetenvHandledError extends Error {
89
+ constructor(message: string);
90
+ }
79
91
  /**
80
- * Get an environment variable, throwing if it is not defined and no default value is provided.
92
+ * Get an environment variable, convert it using the given converter function.
93
+ * If the environment variable is not defined, the default value is used.
94
+ * If the conversion throws an error, the conversion is aborted and an error is thrown. The default value is not used in this case.
95
+ *
81
96
  * @param key The environment variable key
82
97
  * @param defaultValue The default value to use if the environment variable is not defined
83
- * @returns The environment variable value, or the default value if provided
98
+ * @param converter The function to use to convert the environment variable value to the desired type. If the converter throws a GetenvHandledError, that message is surfaced to the user. Otherwise, a generic error message is thrown.
99
+ *
100
+ * @returns The converted environment variable value, or the default value if provided
101
+ *
102
+ * @throws If the environment variable is not defined and no default value is provided
103
+ * @throws If the conversion throws an error
104
+ */
105
+ export declare function getEnv<R>(key: string, defaultValue?: R, converter?: (string: string) => R): R;
106
+ /**
107
+ * @see getEnv, returning a string.
108
+ *
109
+ * @param allowEmpty Whether to allow empty strings
110
+ */
111
+ export declare function getEnvString(key: string, allowEmpty?: boolean, defaultValue?: string): string;
112
+ /**
113
+ * @see getEnv, with the additional constraint that the environment variable must be a valid integer.
114
+ *
115
+ * @param constraints The constraints (min and max) to apply to the environment variable value
116
+ *
117
+ * Note: the default value is not used instead of an invalid integer. An invalid integer therefore throws an error.
118
+ */
119
+ export declare function getEnvInt(key: string, constraints?: {
120
+ min?: number;
121
+ max?: number;
122
+ }, defaultValue?: number): number;
123
+ /**
124
+ * @see getEnv, with the additional constraint that the environment variable must be a valid JSON object.
125
+ * Note: the default value is not used instead of an invalid JSON object. An invalid JSON object therefore throws an error.
126
+ *
127
+ * @param schema The schema to use to validate the environment variable value
84
128
  */
85
- export declare function getEnv(key: string, defaultValue?: string): string;
129
+ export declare function getEnvJson<T>(key: string, defaultValue?: T, schema?: TSchema): T;
86
130
  export declare const CURRENT_TS_MS: () => Whispr<number>;
87
131
  export declare function getClock(rate: number): Whispr<number>;
88
132
  export declare function timediff2HumanReadable(diffMs: number): string;
package/dist/index.js CHANGED
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.CURRENT_TS_MS = void 0;
3
+ exports.CURRENT_TS_MS = exports.GetenvHandledError = void 0;
4
+ exports.randomBelow = randomBelow;
4
5
  exports.getRandom = getRandom;
5
6
  exports.getRandomId = getRandomId;
6
7
  exports.getRandomOtp = getRandomOtp;
@@ -15,12 +16,39 @@ exports.stableLog = stableLog;
15
16
  exports.parseQuery = parseQuery;
16
17
  exports.randBetween = randBetween;
17
18
  exports.getEnv = getEnv;
19
+ exports.getEnvString = getEnvString;
20
+ exports.getEnvInt = getEnvInt;
21
+ exports.getEnvJson = getEnvJson;
18
22
  exports.getClock = getClock;
19
23
  exports.timediff2HumanReadable = timediff2HumanReadable;
20
24
  exports.fn2promise = fn2promise;
21
25
  exports.safeApply = safeApply;
22
26
  const whispr_1 = require("@cripty2001/whispr");
23
27
  const lodash_1 = require("lodash");
28
+ const U32_LIMIT = 0x1_0000_0000;
29
+ function randomU32() {
30
+ const buf = new Uint32Array(1);
31
+ globalThis.crypto.getRandomValues(buf);
32
+ return buf[0];
33
+ }
34
+ /**
35
+ * Generate a random number between 0 and `maxExclusive - 1`.
36
+ * @param maxExclusive The maximum exclusive value to generate
37
+ * @returns A random number between 0 and `maxExclusive - 1`
38
+ * @throws If `maxExclusive` is less than 1 or greater than 2^32
39
+ */
40
+ function randomBelow(maxExclusive) {
41
+ const n = Math.floor(maxExclusive);
42
+ if (n < 1)
43
+ throw new RangeError(`randomBelow span must be at least 1: ${n}`);
44
+ if (n > U32_LIMIT)
45
+ throw new RangeError(`randomBelow span exceeds 2^32: ${n}`);
46
+ const threshold = U32_LIMIT - (U32_LIMIT % n);
47
+ let x = randomU32();
48
+ while (x >= threshold)
49
+ x = randomU32();
50
+ return x % n;
51
+ }
24
52
  /**
25
53
  * Generate a random string from the given alphabeth.
26
54
  * @param _alphabeth The alphabeth to draw characters from
@@ -31,7 +59,7 @@ function getRandom(_alphabeth, length) {
31
59
  const alphabeth = _alphabeth.split("");
32
60
  const toReturn = [];
33
61
  while (toReturn.length < length) {
34
- toReturn.push(alphabeth[Math.floor(Math.random() * alphabeth.length)]);
62
+ toReturn.push(alphabeth[randomBelow(alphabeth.length)]);
35
63
  }
36
64
  return toReturn.join("");
37
65
  }
@@ -189,21 +217,97 @@ function parseQuery(query, fields) {
189
217
  * @param min The minimum allowed number
190
218
  * @param max The maximum allowed number
191
219
  * @returns The generated random int
220
+ * @throws If `max - min + 1` is greater than 2^32
192
221
  */
193
222
  function randBetween(min, max) {
194
- return Math.floor(Math.random() * (max - min + 1)) + min;
223
+ const span = max - min + 1;
224
+ if (span <= 1)
225
+ return min;
226
+ return min + randomBelow(span);
195
227
  }
228
+ class GetenvHandledError extends Error {
229
+ constructor(message) {
230
+ super(message);
231
+ }
232
+ }
233
+ exports.GetenvHandledError = GetenvHandledError;
196
234
  /**
197
- * Get an environment variable, throwing if it is not defined and no default value is provided.
235
+ * Get an environment variable, convert it using the given converter function.
236
+ * If the environment variable is not defined, the default value is used.
237
+ * If the conversion throws an error, the conversion is aborted and an error is thrown. The default value is not used in this case.
238
+ *
198
239
  * @param key The environment variable key
199
240
  * @param defaultValue The default value to use if the environment variable is not defined
200
- * @returns The environment variable value, or the default value if provided
241
+ * @param converter The function to use to convert the environment variable value to the desired type. If the converter throws a GetenvHandledError, that message is surfaced to the user. Otherwise, a generic error message is thrown.
242
+ *
243
+ * @returns The converted environment variable value, or the default value if provided
244
+ *
245
+ * @throws If the environment variable is not defined and no default value is provided
246
+ * @throws If the conversion throws an error
247
+ */
248
+ function getEnv(key, defaultValue, converter = (s) => s) {
249
+ const value = process.env[key];
250
+ if (value === undefined) {
251
+ if (defaultValue === undefined)
252
+ throw new Error(`Environment variable ${key} is not defined and no default value was provided.`);
253
+ else
254
+ return defaultValue;
255
+ }
256
+ const converted = (() => {
257
+ try {
258
+ return converter(value);
259
+ }
260
+ catch (e) {
261
+ const message = e instanceof GetenvHandledError ? `(${e.message})` : "";
262
+ throw new Error(`Environment variable ${key} cannot be converted to the desired type.${message}`);
263
+ }
264
+ })();
265
+ return converted;
266
+ }
267
+ /**
268
+ * @see getEnv, returning a string.
269
+ *
270
+ * @param allowEmpty Whether to allow empty strings
271
+ */
272
+ function getEnvString(key, allowEmpty = false, defaultValue) {
273
+ return getEnv(key, defaultValue, (s) => {
274
+ if (s === "" && !allowEmpty)
275
+ throw new GetenvHandledError(`Empty string.`);
276
+ return s;
277
+ });
278
+ }
279
+ /**
280
+ * @see getEnv, with the additional constraint that the environment variable must be a valid integer.
281
+ *
282
+ * @param constraints The constraints (min and max) to apply to the environment variable value
283
+ *
284
+ * Note: the default value is not used instead of an invalid integer. An invalid integer therefore throws an error.
285
+ */
286
+ function getEnvInt(key, constraints = {}, defaultValue) {
287
+ return getEnv(key, defaultValue, (s) => {
288
+ const parsed = parseInt(s);
289
+ if (isNaN(parsed))
290
+ throw new GetenvHandledError(`Invalid integer.`);
291
+ const MIN = constraints.min ?? Number.MIN_SAFE_INTEGER;
292
+ if (parsed < MIN)
293
+ throw new GetenvHandledError(`Less than minimum: ${MIN}.`);
294
+ const MAX = constraints.max ?? Number.MAX_SAFE_INTEGER;
295
+ if (parsed > MAX)
296
+ throw new GetenvHandledError(`Greater than maximum: ${MAX}.`);
297
+ return parsed;
298
+ });
299
+ }
300
+ /**
301
+ * @see getEnv, with the additional constraint that the environment variable must be a valid JSON object.
302
+ * Note: the default value is not used instead of an invalid JSON object. An invalid JSON object therefore throws an error.
303
+ *
304
+ * @param schema The schema to use to validate the environment variable value
201
305
  */
202
- function getEnv(key, defaultValue) {
203
- const value = process.env[key] ?? defaultValue;
204
- if (value === undefined)
205
- throw new Error(`Environment variable ${key} is not defined and no default value was provided.`);
206
- return value;
306
+ function getEnvJson(key, defaultValue, schema) {
307
+ const value = getEnv(key, defaultValue, (s) => JSON.parse(s));
308
+ return schema ?
309
+ schema.parse(value) :
310
+ value;
207
311
  }
208
312
  const [currentTsMs, setCurrentTsMs] = whispr_1.Whispr.create(Date.now());
209
313
  let currentTsMsInterval = null;
@@ -1,4 +1,4 @@
1
1
  export type LoggerReactDisplayProps = {
2
2
  zIndex?: number;
3
3
  };
4
- export declare function LoggerReactDisplay({ zIndex }: LoggerReactDisplayProps): import("react/jsx-runtime").JSX.Element | null;
4
+ export declare function LoggerReactDisplay({ zIndex }: LoggerReactDisplayProps): import("react").JSX.Element | null;
@@ -4,4 +4,4 @@ export type ButtonProps = {
4
4
  className?: string;
5
5
  onError?: (error: unknown) => void;
6
6
  };
7
- export default function Button({ onClick, children, className, onError }: ButtonProps): import("react/jsx-runtime").JSX.Element;
7
+ export default function Button({ onClick, children, className, onError }: ButtonProps): import("react").JSX.Element;
@@ -2,4 +2,4 @@ export type CopiableProps = {
2
2
  value: string;
3
3
  className?: string;
4
4
  };
5
- export default function Copiable({ value, className }: CopiableProps): import("react/jsx-runtime").JSX.Element;
5
+ export default function Copiable({ value, className }: CopiableProps): import("react").JSX.Element;
@@ -24,4 +24,4 @@ export type FormComponentProps<T extends Record<string, string>> = {
24
24
  button: string;
25
25
  };
26
26
  };
27
- export default function FormComponent<T extends Record<string, string>>(props: FormComponentProps<T>): import("react/jsx-runtime").JSX.Element;
27
+ export default function FormComponent<T extends Record<string, string>>(props: FormComponentProps<T>): import("react").JSX.Element;
@@ -23,4 +23,4 @@ export type InputComponentProps<V extends InputComponentPropsVariants> = {
23
23
  validate?: (value: string) => void;
24
24
  variants: V;
25
25
  };
26
- export default function InputComponent<Variants extends InputComponentPropsVariants>(props: InputComponentProps<Variants>): import("react/jsx-runtime").JSX.Element;
26
+ export default function InputComponent<Variants extends InputComponentPropsVariants>(props: InputComponentProps<Variants>): import("react").JSX.Element;
@@ -7,4 +7,4 @@ export type LoaderProps<T> = {
7
7
  }) => React.ReactNode;
8
8
  loader?: React.ReactNode;
9
9
  };
10
- export default function Loader<T>(props: LoaderProps<T>): import("react/jsx-runtime").JSX.Element;
10
+ export default function Loader<T>(props: LoaderProps<T>): React.JSX.Element;
@@ -10,4 +10,4 @@ export type ModalComponentProps = {
10
10
  animate?: boolean;
11
11
  panelClassName?: string;
12
12
  };
13
- export default function ModalComponent({ children, open, setOpen, animate, panelClassName, }: ModalComponentProps): import("react/jsx-runtime").JSX.Element | null;
13
+ export default function ModalComponent({ children, open, setOpen, animate, panelClassName, }: ModalComponentProps): import("react").JSX.Element | null;
@@ -2,4 +2,4 @@ export type TableProps = {
2
2
  value: (string | React.ReactNode)[][];
3
3
  headers: string[];
4
4
  };
5
- export default function Table({ value, headers }: TableProps): import("react/jsx-runtime").JSX.Element;
5
+ export default function Table({ value, headers }: TableProps): import("react").JSX.Element;
@@ -4,4 +4,4 @@ export type TextButtonProps = Omit<ButtonProps, 'children'> & {
4
4
  title: string;
5
5
  icon?: React.ReactElement<LucideIcon>;
6
6
  };
7
- export default function TextButton({ title, onClick, className, icon }: TextButtonProps): import("react/jsx-runtime").JSX.Element;
7
+ export default function TextButton({ title, onClick, className, icon }: TextButtonProps): import("react").JSX.Element;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cripty2001/utils",
3
- "version": "0.0.230",
3
+ "version": "0.0.232",
4
4
  "description": "Internal Set of utils. If you need them use them, otherwise go to the next package ;)",
5
5
  "homepage": "https://github.com/cripty2001/utils#readme",
6
6
  "bugs": {
@@ -12,6 +12,9 @@
12
12
  },
13
13
  "license": "MIT",
14
14
  "author": "Fabio Mauri <cripty2001@outlook.com>",
15
+ "engines": {
16
+ "node": ">=22"
17
+ },
15
18
  "main": "./dist/index.js",
16
19
  "types": "./dist/index.d.ts",
17
20
  "scripts": {
@@ -27,6 +30,7 @@
27
30
  ],
28
31
  "dependencies": {
29
32
  "@cripty2001/whispr": "^0.4.1",
33
+ "@sinclair/typebox": "^0.34.41",
30
34
  "cors": "^2.8.6",
31
35
  "lodash": "^4.17.21"
32
36
  },
@@ -34,20 +38,16 @@
34
38
  "@types/cors": "^2.8.19",
35
39
  "@types/express": "^5.0.5",
36
40
  "@types/lodash": "^4.17.21",
37
- "@types/mjml": "^4.7.4",
38
- "@types/node": "^24.9.1",
41
+ "@types/node": "^24.13.3",
39
42
  "@types/react": "^19",
40
43
  "react": "^19",
41
- "typescript": "^5.9.3"
44
+ "typescript": "^7.0.2"
42
45
  },
43
46
  "peerDependencies": {
44
47
  "@msgpack/msgpack": "^3.1.2",
45
- "@sinclair/typebox": "^0.34.41",
46
48
  "dotenv": "^17.2.3",
47
49
  "express": "^5.2.1",
48
- "handlebars": "^4.7.8",
49
50
  "lucide-react": ">=0.552.0",
50
- "mjml": "^4.17.1",
51
51
  "react": "^19"
52
52
  },
53
53
  "peerDependenciesMeta": {
@@ -101,11 +101,6 @@
101
101
  "types": "./dist/Appserver/client.d.ts",
102
102
  "require": "./dist/Appserver/client.js"
103
103
  },
104
- "./mail-template": {
105
- "import": "./dist/MailTemplate/index.js",
106
- "types": "./dist/MailTemplate/index.d.ts",
107
- "require": "./dist/MailTemplate/index.js"
108
- },
109
104
  "./react": {
110
105
  "import": "./dist/react/index.js",
111
106
  "types": "./dist/react/index.d.ts",