@tmlmobilidade/go-interfaces-cachedb 20260717.1316.58

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.
@@ -0,0 +1,2 @@
1
+ export * from './interface.js';
2
+ export * from './keys.js';
package/dist/index.js ADDED
@@ -0,0 +1,2 @@
1
+ export * from './interface.js';
2
+ export * from './keys.js';
@@ -0,0 +1,60 @@
1
+ import { type RedisClientType } from '@tmlmobilidade/go-clients-redis';
2
+ import { type cacheDbKey } from './keys.js';
3
+ declare class CacheDbClass {
4
+ private static _instance;
5
+ private client;
6
+ /**
7
+ * Returns the singleton instance of the subclass.
8
+ */
9
+ static getInstance(): Promise<CacheDbClass>;
10
+ /**
11
+ * Deletes all keys from the cache that are not allowed by {@link isAllowedHubcacheDbKey}.
12
+ * This method is useful for maintaining a clean state free of stale
13
+ * or irrelevant cache entries that consume storage and memory resources.
14
+ * @returns A promise that resolves when the cleaning process is complete.
15
+ * @throws Will throw an error if the cleaning process fails.
16
+ */
17
+ clean(): Promise<void>;
18
+ /**
19
+ * Deletes a cache entry by its key.
20
+ * @param key The key of the cache entry to delete.
21
+ * @returns A promise that resolves when the deletion process is complete.
22
+ * @throws Will throw an error if the deletion process fails.
23
+ */
24
+ delete(key: cacheDbKey): Promise<void>;
25
+ /**
26
+ * Deletes multiple cache entries.
27
+ * @param keys The list of keys to delete.
28
+ */
29
+ deleteMany(keys: string[]): Promise<void>;
30
+ /**
31
+ * Retrieves a cache entry by its key.
32
+ * @param key The key of the cache entry to retrieve.
33
+ * @returns A promise that resolves with the cache entry value,
34
+ * or `null` if not found.
35
+ * @throws Will throw an error if the retrieval process fails.
36
+ */
37
+ get(key: cacheDbKey): Promise<null | string>;
38
+ /**
39
+ * Scans cache keys by pattern.
40
+ * @param pattern The redis pattern to match.
41
+ * @returns A promise resolving with all matching keys.
42
+ */
43
+ scan(pattern: string): Promise<string[]>;
44
+ /**
45
+ * Saves a cache entry with an optional time-to-live (TTL).
46
+ * @param key The key of the cache entry to save.
47
+ * @param value The value of the cache entry to save. Must be a string.
48
+ * @param ttl Optional time-to-live (TTL) in seconds. Omit when not needed.
49
+ */
50
+ set(key: cacheDbKey, value: string, ttl?: number): Promise<void>;
51
+ protected connectToClient(): Promise<RedisClientType>;
52
+ /**
53
+ * Initializes the Redis client.
54
+ * @throws Will throw an error if the client initialization fails.
55
+ * @returns A promise that resolves when the initialization process is complete.
56
+ */
57
+ protected init(): Promise<void>;
58
+ }
59
+ export declare const cacheDb: CacheDbClass;
60
+ export {};
@@ -0,0 +1,121 @@
1
+ /* * */
2
+ import { RedisDatabaseClient } from '@tmlmobilidade/go-clients-redis';
3
+ import { asyncSingletonProxy } from '@tmlmobilidade/utils';
4
+ /* * */
5
+ class CacheDbClass {
6
+ //
7
+ static _instance = null;
8
+ client;
9
+ /**
10
+ * Returns the singleton instance of the subclass.
11
+ */
12
+ static async getInstance() {
13
+ // If no instance exists, create one and store the promise.
14
+ // This ensures that if multiple calls to getInstance() happen concurrently,
15
+ // they will all await the same initialization process.
16
+ if (!this._instance) {
17
+ this._instance = (async () => {
18
+ const instance = new CacheDbClass();
19
+ // This behaves like the constructor,
20
+ // but allows for async initialization.
21
+ await instance.init();
22
+ return instance;
23
+ })();
24
+ }
25
+ // Await the instance if it's still initializing,
26
+ // or return it immediately if ready.
27
+ return await this._instance;
28
+ }
29
+ /**
30
+ * Deletes all keys from the cache that are not allowed by {@link isAllowedHubcacheDbKey}.
31
+ * This method is useful for maintaining a clean state free of stale
32
+ * or irrelevant cache entries that consume storage and memory resources.
33
+ * @returns A promise that resolves when the cleaning process is complete.
34
+ * @throws Will throw an error if the cleaning process fails.
35
+ */
36
+ async clean() {
37
+ const allKeys = await this.client.keys('*');
38
+ const keysToDelete = allKeys.filter(key => key);
39
+ if (keysToDelete.length)
40
+ await this.client.del(keysToDelete);
41
+ }
42
+ /**
43
+ * Deletes a cache entry by its key.
44
+ * @param key The key of the cache entry to delete.
45
+ * @returns A promise that resolves when the deletion process is complete.
46
+ * @throws Will throw an error if the deletion process fails.
47
+ */
48
+ async delete(key) {
49
+ await this.client.del(key);
50
+ }
51
+ /**
52
+ * Deletes multiple cache entries.
53
+ * @param keys The list of keys to delete.
54
+ */
55
+ async deleteMany(keys) {
56
+ if (!keys.length)
57
+ return;
58
+ await this.client.del(keys);
59
+ }
60
+ /**
61
+ * Retrieves a cache entry by its key.
62
+ * @param key The key of the cache entry to retrieve.
63
+ * @returns A promise that resolves with the cache entry value,
64
+ * or `null` if not found.
65
+ * @throws Will throw an error if the retrieval process fails.
66
+ */
67
+ async get(key) {
68
+ const result = await this.client.get(key);
69
+ if (typeof result !== 'string')
70
+ return null;
71
+ return result;
72
+ }
73
+ /**
74
+ * Scans cache keys by pattern.
75
+ * @param pattern The redis pattern to match.
76
+ * @returns A promise resolving with all matching keys.
77
+ */
78
+ async scan(pattern) {
79
+ const foundKeys = new Set();
80
+ for await (const scanResult of this.client.scanIterator({ MATCH: pattern, TYPE: 'string' })) {
81
+ // Scan result is an array of keys because Redis just goes over all keys
82
+ // in the database without any specific order or pagination and returns
83
+ // only the ones that match the requested pattern.
84
+ scanResult.forEach(key => foundKeys.add(key));
85
+ }
86
+ return Array.from(foundKeys);
87
+ }
88
+ /**
89
+ * Saves a cache entry with an optional time-to-live (TTL).
90
+ * @param key The key of the cache entry to save.
91
+ * @param value The value of the cache entry to save. Must be a string.
92
+ * @param ttl Optional time-to-live (TTL) in seconds. Omit when not needed.
93
+ */
94
+ async set(key, value, ttl) {
95
+ // Validate value type before setting cache
96
+ if (typeof value !== 'string')
97
+ throw new Error(`[cacheDb] Value must be a string. Got "${typeof value}" for key "${key}".`);
98
+ // Set cache with optional TTL
99
+ if (ttl)
100
+ await this.client.set(key, value, { expiration: { type: 'EX', value: ttl } });
101
+ else
102
+ await this.client.set(key, value);
103
+ }
104
+ connectToClient() {
105
+ return RedisDatabaseClient.getClient({ prefix: 'CACHEDB' });
106
+ }
107
+ /**
108
+ * Initializes the Redis client.
109
+ * @throws Will throw an error if the client initialization fails.
110
+ * @returns A promise that resolves when the initialization process is complete.
111
+ */
112
+ async init() {
113
+ // Skip if already initialized
114
+ if (this.client)
115
+ return;
116
+ // Connect to the Redis client
117
+ this.client = await this.connectToClient();
118
+ }
119
+ }
120
+ /* * */
121
+ export const cacheDb = asyncSingletonProxy(CacheDbClass);
package/dist/keys.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ export declare const cacheDbKeyValues: readonly ["hub:v1:navegante:app-enabled", "hub:v1:alerts:published:json", "hub:v1:alerts:published:json:cm", "hub:v1:alerts:published:gtfs", "hub:v1:alerts:published:gtfs:cm", "hub:v1:alerts:published:rss", "hub:v1:alerts:published:rss:cm", "hub:v1:plans:approved:json", "hub:v1:realtime:vehicles:metadata:json", "hub:v1:realtime:vehicles:positions:json", "hub:v1:realtime:vehicles:positions:gtfs", "hub:v1:realtime:eta:json", "hub:v1:realtime:eta:gtfs", "hub:v1:network:dates", "hub:v1:network:periods", "hub:v1:network:stops", "hub:v1:network:legacy-stops-map", "hub:v1:network:lines", "hub:v1:network:routes", "hub:v1:network:plans", "hub:v1:metrics:demand:by-agency:by-operational-date:json", "hub:v1:network:vehicles:protobuf", `hub:v1:network:patterns:${string}`, `hub:v1:network:shapes:${string}`];
2
+ export type cacheDbKey = typeof cacheDbKeyValues[number];
package/dist/keys.js ADDED
@@ -0,0 +1,28 @@
1
+ /* * */
2
+ const dynamicKey = () => 'use-for-dynamic-key';
3
+ export const cacheDbKeyValues = [
4
+ 'hub:v1:navegante:app-enabled',
5
+ 'hub:v1:alerts:published:json',
6
+ 'hub:v1:alerts:published:json:cm',
7
+ 'hub:v1:alerts:published:gtfs',
8
+ 'hub:v1:alerts:published:gtfs:cm',
9
+ 'hub:v1:alerts:published:rss',
10
+ 'hub:v1:alerts:published:rss:cm',
11
+ 'hub:v1:plans:approved:json',
12
+ 'hub:v1:realtime:vehicles:metadata:json',
13
+ 'hub:v1:realtime:vehicles:positions:json',
14
+ 'hub:v1:realtime:vehicles:positions:gtfs',
15
+ 'hub:v1:realtime:eta:json',
16
+ 'hub:v1:realtime:eta:gtfs',
17
+ 'hub:v1:network:dates',
18
+ 'hub:v1:network:periods',
19
+ 'hub:v1:network:stops',
20
+ 'hub:v1:network:legacy-stops-map',
21
+ 'hub:v1:network:lines',
22
+ 'hub:v1:network:routes',
23
+ 'hub:v1:network:plans',
24
+ 'hub:v1:metrics:demand:by-agency:by-operational-date:json',
25
+ 'hub:v1:network:vehicles:protobuf',
26
+ `hub:v1:network:patterns:${dynamicKey()}`,
27
+ `hub:v1:network:shapes:${dynamicKey()}`,
28
+ ];
package/package.json ADDED
@@ -0,0 +1,53 @@
1
+ {
2
+ "name": "@tmlmobilidade/go-interfaces-cachedb",
3
+ "version": "20260717.1316.58",
4
+ "author": {
5
+ "email": "iso@tmlmobilidade.pt",
6
+ "name": "TML-ISO"
7
+ },
8
+ "license": "AGPL-3.0-or-later",
9
+ "homepage": "https://go.tmlmobilidade.pt",
10
+ "bugs": {
11
+ "url": "https://github.com/tmlmobilidade/go/issues"
12
+ },
13
+ "repository": {
14
+ "type": "git",
15
+ "url": "git+https://github.com/tmlmobilidade/go.git"
16
+ },
17
+ "keywords": [
18
+ "public transit",
19
+ "tml",
20
+ "transportes metropolitanos de lisboa",
21
+ "go"
22
+ ],
23
+ "publishConfig": {
24
+ "access": "public"
25
+ },
26
+ "type": "module",
27
+ "files": [
28
+ "dist"
29
+ ],
30
+ "main": "./dist/index.js",
31
+ "types": "./dist/index.d.ts",
32
+ "scripts": {
33
+ "build": "tsc && resolve-tspaths",
34
+ "lint": "eslint ./src/ && tsc --noEmit",
35
+ "lint:fix": "eslint ./src/ --fix",
36
+ "watch": "tsc-watch --onSuccess 'resolve-tspaths'"
37
+ },
38
+ "dependencies": {
39
+ "@tmlmobilidade/go-clients-redis": "*",
40
+ "@tmlmobilidade/logger": "*",
41
+ "@tmlmobilidade/utils": "*",
42
+ "luxon": "3.7.2",
43
+ "zod": "3.25.76"
44
+ },
45
+ "devDependencies": {
46
+ "@tmlmobilidade/tsconfig": "*",
47
+ "@types/luxon": "3.7.2",
48
+ "@types/node": "26.1.1",
49
+ "resolve-tspaths": "0.8.23",
50
+ "tsc-watch": "7.2.1",
51
+ "typescript": "6.0.3"
52
+ }
53
+ }