@mereb/shared-packages 0.0.10 → 0.0.14

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.
@@ -1,6 +1,7 @@
1
1
  import { type RedisClientType } from '@redis/client';
2
2
  export interface RedisOptions {
3
3
  url: string;
4
+ connectTimeoutMs?: number;
4
5
  }
5
6
  export declare function getRedisClient(options: RedisOptions): Promise<RedisClientType>;
6
7
  export declare function disconnectRedis(): Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"redis.d.ts","sourceRoot":"","sources":["../../src/cache/redis.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,KAAK,eAAe,EAAE,MAAM,eAAe,CAAC;AAOnE,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC;CACb;AAED,wBAAsB,cAAc,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,eAAe,CAAC,CASpF;AAED,wBAAsB,eAAe,kBAKpC"}
1
+ {"version":3,"file":"redis.d.ts","sourceRoot":"","sources":["../../src/cache/redis.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,KAAK,eAAe,EAAE,MAAM,eAAe,CAAC;AAQnE,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAiCD,wBAAsB,cAAc,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,eAAe,CAAC,CAepF;AAED,wBAAsB,eAAe,kBAKpC"}
@@ -8,14 +8,52 @@ exports.disconnectRedis = disconnectRedis;
8
8
  const client_1 = require("@redis/client");
9
9
  const pino_1 = __importDefault(require("pino"));
10
10
  const logger = (0, pino_1.default)({ name: 'redis' });
11
+ const DEFAULT_CONNECT_TIMEOUT_MS = 5_000;
11
12
  let client;
13
+ function withTimeout(promise, timeoutMs) {
14
+ return new Promise((resolve, reject) => {
15
+ const timer = setTimeout(() => {
16
+ reject(new Error(`Timed out connecting to Redis after ${timeoutMs}ms`));
17
+ }, timeoutMs);
18
+ promise
19
+ .then((value) => {
20
+ clearTimeout(timer);
21
+ resolve(value);
22
+ })
23
+ .catch((error) => {
24
+ clearTimeout(timer);
25
+ reject(error);
26
+ });
27
+ });
28
+ }
29
+ async function connectClient(instance, timeoutMs) {
30
+ try {
31
+ await withTimeout(instance.connect(), timeoutMs);
32
+ }
33
+ catch (error) {
34
+ try {
35
+ await instance.disconnect();
36
+ }
37
+ catch {
38
+ // ignore disconnect errors during cleanup
39
+ }
40
+ throw error;
41
+ }
42
+ }
12
43
  async function getRedisClient(options) {
13
44
  if (!client) {
45
+ const timeoutMs = options.connectTimeoutMs ?? DEFAULT_CONNECT_TIMEOUT_MS;
14
46
  client = (0, client_1.createClient)({ url: options.url });
15
47
  client.on('error', (err) => {
16
48
  logger.error({ err }, 'Redis connection error');
17
49
  });
18
- await client.connect();
50
+ try {
51
+ await connectClient(client, timeoutMs);
52
+ }
53
+ catch (error) {
54
+ client = undefined;
55
+ throw error;
56
+ }
19
57
  }
20
58
  return client;
21
59
  }
@@ -2,9 +2,30 @@ export interface EnvConfigOptions<T extends string> {
2
2
  defaults?: Partial<Record<T, string>>;
3
3
  required?: T[];
4
4
  }
5
+ export type EnvSpec<K extends string = string> = {
6
+ key: K;
7
+ type: 'string';
8
+ fallback?: string;
9
+ } | {
10
+ key: K;
11
+ type: 'number';
12
+ fallback?: number;
13
+ } | {
14
+ key: K;
15
+ type: 'boolean';
16
+ fallback?: boolean;
17
+ };
18
+ type EnvResult<Specs extends EnvSpec[]> = {
19
+ [S in Specs[number] as S['key']]: S['type'] extends 'string' ? string : S['type'] extends 'number' ? number : boolean;
20
+ };
5
21
  export declare function loadEnv(path?: string): void;
22
+ export declare function loadThenGetEnvs<const Specs extends EnvSpec[]>(options: {
23
+ path?: string;
24
+ envs: Specs;
25
+ }): EnvResult<Specs>;
6
26
  export declare function getEnv<T extends string>(key: T, fallback?: string): string;
7
27
  export declare function mustGetEnv<T extends string>(keys: T[]): Record<T, string>;
8
28
  export declare function getBooleanEnv(key: string, fallback?: boolean): boolean;
9
29
  export declare function getNumberEnv(key: string, fallback?: number): number;
30
+ export {};
10
31
  //# sourceMappingURL=env.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../../src/config/env.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,gBAAgB,CAAC,CAAC,SAAS,MAAM;IAChD,QAAQ,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;IACtC,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAC;CAChB;AAED,wBAAgB,OAAO,CAAC,IAAI,CAAC,EAAE,MAAM,QAKpC;AAED,wBAAgB,MAAM,CAAC,CAAC,SAAS,MAAM,EAAE,GAAG,EAAE,CAAC,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAM1E;AAED,wBAAgB,UAAU,CAAC,CAAC,SAAS,MAAM,EAAE,IAAI,EAAE,CAAC,EAAE,GAAG,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,CASzE;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,UAAQ,GAAG,OAAO,CAMpE;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAanE"}
1
+ {"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../../src/config/env.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,gBAAgB,CAAC,CAAC,SAAS,MAAM;IAChD,QAAQ,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;IACtC,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAC;CAChB;AAED,MAAM,MAAM,OAAO,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,IACzC;IAAE,GAAG,EAAE,CAAC,CAAC;IAAC,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GAC7C;IAAE,GAAG,EAAE,CAAC,CAAC;IAAC,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GAC7C;IAAE,GAAG,EAAE,CAAC,CAAC;IAAC,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC;AAEpD,KAAK,SAAS,CAAC,KAAK,SAAS,OAAO,EAAE,IAAI;KACvC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,SAAS,QAAQ,GACxD,MAAM,GACN,CAAC,CAAC,MAAM,CAAC,SAAS,QAAQ,GACxB,MAAM,GACN,OAAO;CACd,CAAC;AAEF,wBAAgB,OAAO,CAAC,IAAI,CAAC,EAAE,MAAM,QAKpC;AAED,wBAAgB,eAAe,CAAC,KAAK,CAAC,KAAK,SAAS,OAAO,EAAE,EAC3D,OAAO,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,KAAK,CAAA;CAAE,GACtC,SAAS,CAAC,KAAK,CAAC,CAiClB;AAED,wBAAgB,MAAM,CAAC,CAAC,SAAS,MAAM,EAAE,GAAG,EAAE,CAAC,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAM1E;AAED,wBAAgB,UAAU,CAAC,CAAC,SAAS,MAAM,EAAE,IAAI,EAAE,CAAC,EAAE,GAAG,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,CASzE;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,UAAQ,GAAG,OAAO,CAMpE;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAanE"}
@@ -4,6 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.loadEnv = loadEnv;
7
+ exports.loadThenGetEnvs = loadThenGetEnvs;
7
8
  exports.getEnv = getEnv;
8
9
  exports.mustGetEnv = mustGetEnv;
9
10
  exports.getBooleanEnv = getBooleanEnv;
@@ -16,6 +17,28 @@ function loadEnv(path) {
16
17
  loaded = true;
17
18
  }
18
19
  }
20
+ function loadThenGetEnvs(options) {
21
+ loadEnv(options.path);
22
+ const envs = {};
23
+ for (const spec of options.envs) {
24
+ switch (spec.type) {
25
+ case 'string':
26
+ envs[spec.key] = getEnv(spec.key, spec.fallback);
27
+ break;
28
+ case 'number':
29
+ envs[spec.key] = getNumberEnv(spec.key, spec.fallback);
30
+ break;
31
+ case 'boolean':
32
+ envs[spec.key] = getBooleanEnv(spec.key, spec.fallback ?? false);
33
+ break;
34
+ default: {
35
+ const _exhaustive = spec;
36
+ throw new Error(`Unsupported env type ${spec.type}`);
37
+ }
38
+ }
39
+ }
40
+ return envs;
41
+ }
19
42
  function getEnv(key, fallback) {
20
43
  const value = process.env[key] ?? fallback;
21
44
  if (value === undefined) {
@@ -50,7 +73,7 @@ function getNumberEnv(key, fallback) {
50
73
  }
51
74
  const numeric = Number(value);
52
75
  if (Number.isNaN(numeric)) {
53
- throw new Error(`Environment variable ${key} must be a number`);
76
+ throw new TypeError(`Environment variable ${key} must be a number`);
54
77
  }
55
78
  return numeric;
56
79
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mereb/shared-packages",
3
- "version": "0.0.10",
3
+ "version": "0.0.14",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "files": [
@@ -40,12 +40,14 @@
40
40
  "@types/node": "^20.12.7",
41
41
  "eslint": "^8.57.0",
42
42
  "rimraf": "^5.0.5",
43
- "typescript": "^5.4.5"
43
+ "typescript": "^5.4.5",
44
+ "vitest": "^1.6.0"
44
45
  },
45
46
  "scripts": {
46
47
  "build": "tsc -b",
47
48
  "clean": "rimraf dist",
48
49
  "lint": "eslint \"src/**/*.{ts,tsx}\"",
50
+ "test": "vitest run",
49
51
  "typecheck": "tsc --noEmit",
50
52
  "version:bump": "node ./scripts/bump-version.mjs"
51
53
  }