node-server-engine 1.7.3 → 1.8.0
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/entities/Localizator/Localizator.js +2 -2
- package/dist/entities/Localizator/Localizator.js.map +1 -1
- package/dist/entities/Redis/Redis.d.ts +10 -2
- package/dist/entities/Redis/Redis.js +104 -9
- package/dist/entities/Redis/Redis.js.map +1 -1
- package/dist/entities/Redis/Redis.types.d.ts +6 -0
- package/dist/entities/Redis/Redis.types.js.map +1 -1
- package/dist/entities/Redis/index.d.ts +1 -1
- package/dist/entities/Redis/index.js +22 -1
- package/dist/entities/Redis/index.js.map +1 -1
- package/dist/utils/report/output.d.ts +10 -0
- package/dist/utils/report/output.js +18 -3
- package/dist/utils/report/output.js.map +1 -1
- package/package.json +5 -4
|
@@ -20,7 +20,7 @@ let interval;
|
|
|
20
20
|
/** Service handling contextual localization */
|
|
21
21
|
const Localizator = exports.Localizator = {
|
|
22
22
|
async init() {
|
|
23
|
-
(0, _checkEnvironment.
|
|
23
|
+
(0, _checkEnvironment.assertEnvironment)({
|
|
24
24
|
LOCALES_BUCKET: _envAssert.envAssert.isString()
|
|
25
25
|
});
|
|
26
26
|
await Localizator.synchronize();
|
|
@@ -122,7 +122,7 @@ const Localizator = exports.Localizator = {
|
|
|
122
122
|
},
|
|
123
123
|
/** Cleanup the instance */
|
|
124
124
|
shutdown() {
|
|
125
|
-
if (interval)
|
|
125
|
+
if (interval) clearInterval(interval);
|
|
126
126
|
}
|
|
127
127
|
};
|
|
128
128
|
//# sourceMappingURL=Localizator.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Localizator.js","names":["_guessNamingConvention","require","_EngineError","_LifecycleController","_Storage","_checkEnvironment","_envAssert","_report","namespace","REFRESH_FREQUENCY","localeData","scripts","interval","Localizator","exports","init","
|
|
1
|
+
{"version":3,"file":"Localizator.js","names":["_guessNamingConvention","require","_EngineError","_LifecycleController","_Storage","_checkEnvironment","_envAssert","_report","namespace","REFRESH_FREQUENCY","localeData","scripts","interval","Localizator","exports","init","assertEnvironment","LOCALES_BUCKET","envAssert","isString","synchronize","setInterval","catch","error","reportError","LifecycleController","register","getLocaleFile","file","reportDebug","message","data","bucket","process","env","Storage","get","stringified","toString","result","JSON","parse","fetchedLocaleData","fetchedScripts","Promise","all","buildRangeRegex","script","i","Object","keys","ranges","rangeRegex","RegExp","join","guessNamingConvention","firstName","lastName","locale","EngineError","name","getDisplayNames","convention","reduce","type","safeType","replace","trim","getLocaleData","isValidLocale","undefined","shutdown","clearInterval"],"sources":["../../../src/entities/Localizator/Localizator.ts"],"sourcesContent":["import { guessNamingConvention } from './guessNamingConvention';\nimport {\n LocalizatorLocalizationData,\n LocalizatorLocalizationDataElement,\n LocalizatorScripts,\n LocalizatorNamingConventions\n} from './Localizator.types';\nimport { EngineError } from 'entities/EngineError';\nimport { LifecycleController } from 'entities/LifecycleController';\nimport { Storage } from 'entities/Storage';\nimport { assertEnvironment } from 'utils/checkEnvironment';\nimport { envAssert } from 'utils/envAssert';\nimport { reportError, reportDebug } from 'utils/report';\n\nconst namespace = 'engine:localizator';\n\nconst REFRESH_FREQUENCY = 10 * 60 * 1000;\n\nlet localeData: undefined | LocalizatorLocalizationData;\nlet scripts: undefined | LocalizatorScripts;\nlet interval: NodeJS.Timeout | string | number | undefined;\n\n/** Service handling contextual localization */\nexport const Localizator = {\n async init(): Promise<void> {\n assertEnvironment({ LOCALES_BUCKET: envAssert.isString() });\n await Localizator.synchronize();\n // Keep synchronizing\n interval = setInterval(() => {\n Localizator.synchronize().catch((error) => {\n reportError(error);\n });\n }, REFRESH_FREQUENCY);\n LifecycleController.register(Localizator);\n },\n\n /**\n * Fetch a JSON file from the locales bucket\n */\n async getLocaleFile<T>(file: string): Promise<T> {\n reportDebug({\n namespace,\n message: `Starting download of localization file [${file}]`,\n data: { bucket: process.env.LOCALES_BUCKET, file }\n });\n const { data } = await Storage.get(\n process.env.LOCALES_BUCKET as string,\n file\n );\n const stringified = data.toString('utf-8');\n const result = JSON.parse(stringified) as T;\n reportDebug({\n namespace,\n message: `Fetched localization file [${file}]`,\n data: { bucket: process.env.LOCALES_BUCKET, file, result }\n });\n return result;\n },\n\n /**\n * Synchronizes the localeData and scripts files\n * Should be called only once on startup\n */\n async synchronize(): Promise<void> {\n reportDebug({ namespace, message: `Starting synchronizing` });\n const [fetchedLocaleData, fetchedScripts] = await Promise.all([\n Localizator.getLocaleFile<LocalizatorLocalizationData>('localeData.json'),\n Localizator.getLocaleFile<LocalizatorScripts>('scripts.json')\n ]);\n localeData = fetchedLocaleData;\n scripts = Localizator.buildRangeRegex(fetchedScripts);\n reportDebug({ namespace, message: `Finished synchronizing` });\n },\n\n /** Transform unicode ranges in scripts data to regex */\n buildRangeRegex(script: LocalizatorScripts): LocalizatorScripts {\n for (const i of Object.keys(script)) {\n const ranges = script[i].ranges;\n if (ranges) {\n script[i].rangeRegex = new RegExp(`[${ranges.join('')}]`, 'u');\n }\n }\n return script;\n },\n\n /** Guess the naming convention to use for a given name and locale */\n guessNamingConvention(\n firstName: string,\n lastName: string,\n locale: string\n ): LocalizatorNamingConventions {\n if (!scripts || !localeData)\n throw new EngineError({ message: 'Localizator is not initialized' });\n const name = firstName + lastName; // merge two names if possible\n return guessNamingConvention(scripts, localeData, name, locale);\n },\n\n /**\n * Calculate the different display names for a user\n */\n getDisplayNames(\n firstName: string,\n lastName: string,\n locale: string\n ): LocalizatorNamingConventions {\n const convention = Localizator.guessNamingConvention(\n firstName,\n lastName,\n locale\n );\n return Object.keys(convention).reduce((convention, type) => {\n const safeType = type as keyof LocalizatorNamingConventions;\n convention[safeType] = convention[safeType]\n .replace('{firstName}', firstName)\n .replace('{lastName}', lastName ?? '')\n .trim();\n return convention;\n }, convention);\n },\n\n /** Get the localization data for a locale */\n getLocaleData(locale: string): LocalizatorLocalizationDataElement {\n if (!localeData)\n throw new EngineError({ message: 'Localizator is not initialized' });\n return localeData[locale];\n },\n\n /** Check if a locale exists */\n isValidLocale(locale: string): boolean {\n if (!localeData)\n throw new EngineError({ message: 'Localizator is not initialized' });\n return localeData[locale] !== undefined;\n },\n\n /** Cleanup the instance */\n shutdown(): void {\n if (interval) clearInterval(interval);\n }\n};\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -1,12 +1,20 @@
|
|
|
1
1
|
import { Redis as RedisClient } from 'ioredis';
|
|
2
2
|
import { RedisCreateOptions } from './Redis.types';
|
|
3
3
|
export declare let redisClient: undefined | RedisClient;
|
|
4
|
+
/**
|
|
5
|
+
* Factory function to create a new Redis instance (exported for testing)
|
|
6
|
+
*/
|
|
7
|
+
export declare function createRedisInstance(config: any): RedisClient;
|
|
4
8
|
/**
|
|
5
9
|
* We use a proxy to extend the Redis behavior and allow initialization of the client only when needed while keeping the same interface
|
|
6
10
|
*/
|
|
7
11
|
export declare const Redis: never;
|
|
8
12
|
/**
|
|
9
|
-
*
|
|
13
|
+
* Get the underlying Redis client (for advanced use cases)
|
|
14
|
+
*/
|
|
15
|
+
export declare function getClient(): RedisClient | undefined;
|
|
16
|
+
/**
|
|
17
|
+
* On init create client and connect
|
|
10
18
|
*/
|
|
11
19
|
export declare function init(): void;
|
|
12
20
|
/**
|
|
@@ -14,6 +22,6 @@ export declare function init(): void;
|
|
|
14
22
|
*/
|
|
15
23
|
export declare function shutdown(): Promise<void>;
|
|
16
24
|
/**
|
|
17
|
-
* Create Redis client
|
|
25
|
+
* Create Redis client with enhanced configuration
|
|
18
26
|
*/
|
|
19
27
|
export declare function createRedisClient(options?: RedisCreateOptions): RedisClient;
|
|
@@ -5,6 +5,8 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.Redis = void 0;
|
|
7
7
|
exports.createRedisClient = createRedisClient;
|
|
8
|
+
exports.createRedisInstance = createRedisInstance;
|
|
9
|
+
exports.getClient = getClient;
|
|
8
10
|
exports.init = init;
|
|
9
11
|
exports.redisClient = void 0;
|
|
10
12
|
exports.shutdown = shutdown;
|
|
@@ -12,8 +14,16 @@ var _ioredis = require("ioredis");
|
|
|
12
14
|
var _Redis = require("./Redis.validate");
|
|
13
15
|
var _EngineError = require("../EngineError");
|
|
14
16
|
var _LifecycleController = require("../LifecycleController");
|
|
17
|
+
var _report = require("../../utils/report");
|
|
15
18
|
let redisClient = exports.redisClient = void 0;
|
|
16
19
|
|
|
20
|
+
/**
|
|
21
|
+
* Factory function to create a new Redis instance (exported for testing)
|
|
22
|
+
*/
|
|
23
|
+
function createRedisInstance(config) {
|
|
24
|
+
return new _ioredis.Redis(config);
|
|
25
|
+
}
|
|
26
|
+
|
|
17
27
|
/**
|
|
18
28
|
* We use a proxy to extend the Redis behavior and allow initialization of the client only when needed while keeping the same interface
|
|
19
29
|
*/
|
|
@@ -25,6 +35,7 @@ const Redis = exports.Redis = new Proxy(
|
|
|
25
35
|
get: function (target, property) {
|
|
26
36
|
if (property === 'init') return init;
|
|
27
37
|
if (property === 'shutdown') return shutdown;
|
|
38
|
+
if (property === 'getClient') return getClient;
|
|
28
39
|
// Create the redis client if it does not exist
|
|
29
40
|
if (!redisClient) throw new _EngineError.EngineError({
|
|
30
41
|
message: 'Redis client was not initialized'
|
|
@@ -37,12 +48,59 @@ const Redis = exports.Redis = new Proxy(
|
|
|
37
48
|
});
|
|
38
49
|
|
|
39
50
|
/**
|
|
40
|
-
*
|
|
51
|
+
* Get the underlying Redis client (for advanced use cases)
|
|
52
|
+
*/
|
|
53
|
+
function getClient() {
|
|
54
|
+
return redisClient;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* On init create client and connect
|
|
41
59
|
*/
|
|
42
60
|
function init() {
|
|
43
61
|
// Ignore if already initialized
|
|
44
|
-
if (redisClient)
|
|
62
|
+
if (redisClient) {
|
|
63
|
+
(0, _report.reportDebug)({
|
|
64
|
+
namespace: 'engine:redis',
|
|
65
|
+
message: 'Redis client already initialized'
|
|
66
|
+
});
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
45
69
|
exports.redisClient = redisClient = createRedisClient();
|
|
70
|
+
|
|
71
|
+
// Setup event listeners
|
|
72
|
+
redisClient.on('connect', () => {
|
|
73
|
+
(0, _report.reportDebug)({
|
|
74
|
+
namespace: 'engine:redis',
|
|
75
|
+
message: 'Redis client connecting'
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
redisClient.on('ready', () => {
|
|
79
|
+
(0, _report.reportDebug)({
|
|
80
|
+
namespace: 'engine:redis',
|
|
81
|
+
message: 'Redis client ready'
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
redisClient.on('error', err => {
|
|
85
|
+
(0, _report.reportError)(new _EngineError.EngineError({
|
|
86
|
+
message: 'Redis client error',
|
|
87
|
+
data: {
|
|
88
|
+
error: err.message
|
|
89
|
+
}
|
|
90
|
+
}));
|
|
91
|
+
});
|
|
92
|
+
redisClient.on('close', () => {
|
|
93
|
+
(0, _report.reportDebug)({
|
|
94
|
+
namespace: 'engine:redis',
|
|
95
|
+
message: 'Redis connection closed'
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
redisClient.on('reconnecting', () => {
|
|
99
|
+
(0, _report.reportDebug)({
|
|
100
|
+
namespace: 'engine:redis',
|
|
101
|
+
message: 'Redis client reconnecting'
|
|
102
|
+
});
|
|
103
|
+
});
|
|
46
104
|
_LifecycleController.LifecycleController.register(Redis);
|
|
47
105
|
}
|
|
48
106
|
|
|
@@ -50,26 +108,63 @@ function init() {
|
|
|
50
108
|
* On shutdown close connection and clear client
|
|
51
109
|
*/
|
|
52
110
|
async function shutdown() {
|
|
53
|
-
if (redisClient)
|
|
111
|
+
if (redisClient) {
|
|
112
|
+
try {
|
|
113
|
+
await redisClient.quit();
|
|
114
|
+
(0, _report.reportDebug)({
|
|
115
|
+
namespace: 'engine:redis',
|
|
116
|
+
message: 'Redis client disconnected'
|
|
117
|
+
});
|
|
118
|
+
} catch (error) {
|
|
119
|
+
(0, _report.reportError)(new _EngineError.EngineError({
|
|
120
|
+
message: 'Error during Redis shutdown',
|
|
121
|
+
data: {
|
|
122
|
+
error: error.message
|
|
123
|
+
}
|
|
124
|
+
}));
|
|
125
|
+
}
|
|
126
|
+
}
|
|
54
127
|
exports.redisClient = redisClient = undefined;
|
|
55
128
|
}
|
|
56
129
|
|
|
57
130
|
/**
|
|
58
|
-
* Create Redis client
|
|
131
|
+
* Create Redis client with enhanced configuration
|
|
59
132
|
*/
|
|
60
133
|
function createRedisClient(options = {}) {
|
|
61
134
|
// Check that environment variables are correctly set
|
|
62
135
|
(0, _Redis.validateRedisEnvironment)(options);
|
|
63
|
-
|
|
136
|
+
|
|
137
|
+
// Throw an error if there is no host
|
|
64
138
|
if (!process.env.REDIS_HOST) throw new _EngineError.EngineError({
|
|
65
139
|
message: 'Host required to initialize Redis connection'
|
|
66
140
|
});
|
|
67
|
-
|
|
68
|
-
port: process.env.REDIS_PORT ? parseInt(process.env.REDIS_PORT) :
|
|
141
|
+
const config = {
|
|
142
|
+
port: process.env.REDIS_PORT ? parseInt(process.env.REDIS_PORT) : 6379,
|
|
69
143
|
host: process.env.REDIS_HOST,
|
|
70
144
|
username: process.env.REDIS_USERNAME,
|
|
71
145
|
password: process.env.REDIS_PASSWORD,
|
|
72
|
-
db: 0
|
|
73
|
-
|
|
146
|
+
db: options.db ?? 0,
|
|
147
|
+
retryStrategy: times => {
|
|
148
|
+
const delay = Math.min(times * 50, 2000);
|
|
149
|
+
return delay;
|
|
150
|
+
},
|
|
151
|
+
reconnectOnError: err => {
|
|
152
|
+
const targetErrors = ['READONLY', 'ECONNRESET', 'ETIMEDOUT'];
|
|
153
|
+
return targetErrors.some(targetError => err.message.includes(targetError));
|
|
154
|
+
},
|
|
155
|
+
maxRetriesPerRequest: 3,
|
|
156
|
+
enableReadyCheck: options.enableReadyCheck ?? true,
|
|
157
|
+
lazyConnect: options.lazyConnect ?? process.env.NODE_ENV === 'test',
|
|
158
|
+
...options.redis
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
// Add TLS configuration if TLS_CA is provided
|
|
162
|
+
if (process.env.TLS_CA) {
|
|
163
|
+
config.tls = {
|
|
164
|
+
ca: process.env.TLS_CA,
|
|
165
|
+
rejectUnauthorized: process.env.NODE_ENV === 'production'
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
return createRedisInstance(config);
|
|
74
169
|
}
|
|
75
170
|
//# sourceMappingURL=Redis.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Redis.js","names":["_ioredis","require","_Redis","_EngineError","_LifecycleController","redisClient","exports","Redis","Proxy","get","target","property","init","shutdown","EngineError","message","createRedisClient","LifecycleController","register","quit","undefined","options","validateRedisEnvironment","process","env","REDIS_HOST","
|
|
1
|
+
{"version":3,"file":"Redis.js","names":["_ioredis","require","_Redis","_EngineError","_LifecycleController","_report","redisClient","exports","createRedisInstance","config","RedisClient","Redis","Proxy","get","target","property","init","shutdown","getClient","EngineError","message","reportDebug","namespace","createRedisClient","on","err","reportError","data","error","LifecycleController","register","quit","undefined","options","validateRedisEnvironment","process","env","REDIS_HOST","port","REDIS_PORT","parseInt","host","username","REDIS_USERNAME","password","REDIS_PASSWORD","db","retryStrategy","times","delay","Math","min","reconnectOnError","targetErrors","some","targetError","includes","maxRetriesPerRequest","enableReadyCheck","lazyConnect","NODE_ENV","redis","TLS_CA","tls","ca","rejectUnauthorized"],"sources":["../../../src/entities/Redis/Redis.ts"],"sourcesContent":["import { Redis as RedisClient } from 'ioredis';\nimport { RedisInterface, RedisCreateOptions } from './Redis.types';\nimport { validateRedisEnvironment } from './Redis.validate';\nimport { EngineError } from 'entities/EngineError';\nimport { LifecycleController } from 'entities/LifecycleController';\nimport { reportDebug, reportError } from 'utils/report';\n\nexport let redisClient: undefined | RedisClient;\n\n/**\n * Factory function to create a new Redis instance (exported for testing)\n */\nexport function createRedisInstance(config: any): RedisClient {\n return new RedisClient(config);\n}\n\n/**\n * We use a proxy to extend the Redis behavior and allow initialization of the client only when needed while keeping the same interface\n */\nexport const Redis = new Proxy<RedisInterface>(\n // Due to how we do the proxying, we are forced to ignore ts-errors, we could never create an object that respects the interface properly\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n {},\n {\n get: function (target, property): unknown {\n if (property === 'init') return init;\n if (property === 'shutdown') return shutdown;\n if (property === 'getClient') return getClient;\n // Create the redis client if it does not exist\n if (!redisClient)\n throw new EngineError({ message: 'Redis client was not initialized' });\n // Call the function on the redis client\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n return redisClient[property] as unknown;\n }\n }\n);\n\n/**\n * Get the underlying Redis client (for advanced use cases)\n */\nexport function getClient(): RedisClient | undefined {\n return redisClient;\n}\n\n/**\n * On init create client and connect\n */\nexport function init(): void {\n // Ignore if already initialized\n if (redisClient) {\n reportDebug({\n namespace: 'engine:redis',\n message: 'Redis client already initialized'\n });\n return;\n }\n \n redisClient = createRedisClient();\n \n // Setup event listeners\n redisClient.on('connect', () => {\n reportDebug({\n namespace: 'engine:redis',\n message: 'Redis client connecting'\n });\n });\n \n redisClient.on('ready', () => {\n reportDebug({\n namespace: 'engine:redis',\n message: 'Redis client ready'\n });\n });\n \n redisClient.on('error', (err) => {\n reportError(new EngineError({\n message: 'Redis client error',\n data: { error: err.message }\n }));\n });\n \n redisClient.on('close', () => {\n reportDebug({\n namespace: 'engine:redis',\n message: 'Redis connection closed'\n });\n });\n \n redisClient.on('reconnecting', () => {\n reportDebug({\n namespace: 'engine:redis',\n message: 'Redis client reconnecting'\n });\n });\n \n LifecycleController.register(Redis);\n}\n\n/**\n * On shutdown close connection and clear client\n */\nexport async function shutdown(): Promise<void> {\n if (redisClient) {\n try {\n await redisClient.quit();\n reportDebug({\n namespace: 'engine:redis',\n message: 'Redis client disconnected'\n });\n } catch (error) {\n reportError(new EngineError({\n message: 'Error during Redis shutdown',\n data: { error: (error as Error).message }\n }));\n }\n }\n redisClient = undefined;\n}\n\n/**\n * Create Redis client with enhanced configuration\n */\nexport function createRedisClient(\n options: RedisCreateOptions = {}\n): RedisClient {\n // Check that environment variables are correctly set\n validateRedisEnvironment(options);\n \n // Throw an error if there is no host\n if (!process.env.REDIS_HOST)\n throw new EngineError({\n message: 'Host required to initialize Redis connection'\n });\n\n const config: any = {\n port: process.env.REDIS_PORT ? parseInt(process.env.REDIS_PORT) : 6379,\n host: process.env.REDIS_HOST,\n username: process.env.REDIS_USERNAME,\n password: process.env.REDIS_PASSWORD,\n db: options.db ?? 0,\n retryStrategy: (times: number) => {\n const delay = Math.min(times * 50, 2000);\n return delay;\n },\n reconnectOnError: (err: Error) => {\n const targetErrors = ['READONLY', 'ECONNRESET', 'ETIMEDOUT'];\n return targetErrors.some(targetError => err.message.includes(targetError));\n },\n maxRetriesPerRequest: 3,\n enableReadyCheck: options.enableReadyCheck ?? true,\n lazyConnect: options.lazyConnect ?? (process.env.NODE_ENV === 'test'),\n ...options.redis\n };\n\n // Add TLS configuration if TLS_CA is provided\n if (process.env.TLS_CA) {\n config.tls = {\n ca: process.env.TLS_CA,\n rejectUnauthorized: process.env.NODE_ENV === 'production'\n };\n }\n\n return createRedisInstance(config);\n}\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -4,6 +4,8 @@ export type RedisInterface = IoRedis & Cluster & {
|
|
|
4
4
|
init: () => void;
|
|
5
5
|
/** Stop the redis service */
|
|
6
6
|
shutdown: () => Promise<void>;
|
|
7
|
+
/** Get the underlying Redis client */
|
|
8
|
+
getClient: () => IoRedis | undefined;
|
|
7
9
|
};
|
|
8
10
|
/** Options to initialize a Redis client */
|
|
9
11
|
export interface RedisCreateOptions {
|
|
@@ -13,4 +15,8 @@ export interface RedisCreateOptions {
|
|
|
13
15
|
enableReadyCheck?: boolean;
|
|
14
16
|
/** Cluster mode read operation settings, can make reads on masters, slaves, or both */
|
|
15
17
|
scaleReads?: string;
|
|
18
|
+
/** Database index to use (default: 0) */
|
|
19
|
+
db?: number;
|
|
20
|
+
/** Lazy connect - don't connect until first command (default: false) */
|
|
21
|
+
lazyConnect?: boolean;
|
|
16
22
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Redis.types.js","names":[],"sources":["../../../src/entities/Redis/Redis.types.ts"],"sourcesContent":["import { Redis as IoRedis, Cluster, RedisOptions } from 'ioredis';\n\nexport type RedisInterface = IoRedis &\n Cluster & {\n /** Start the redis service */\n init: () => void;\n /** Stop the redis service */\n shutdown: () => Promise<void>;\n };\n\n/** Options to initialize a Redis client */\nexport interface RedisCreateOptions {\n /** Redis client settings */\n redis?: RedisOptions;\n /** Should the client perform readiness check when establishing the connection */\n enableReadyCheck?: boolean;\n /** Cluster mode read operation settings, can make reads on masters, slaves, or both */\n scaleReads?: string;\n}\n"],"mappings":"","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"Redis.types.js","names":[],"sources":["../../../src/entities/Redis/Redis.types.ts"],"sourcesContent":["import { Redis as IoRedis, Cluster, RedisOptions } from 'ioredis';\n\nexport type RedisInterface = IoRedis &\n Cluster & {\n /** Start the redis service */\n init: () => void;\n /** Stop the redis service */\n shutdown: () => Promise<void>;\n /** Get the underlying Redis client */\n getClient: () => IoRedis | undefined;\n };\n\n/** Options to initialize a Redis client */\nexport interface RedisCreateOptions {\n /** Redis client settings */\n redis?: RedisOptions;\n /** Should the client perform readiness check when establishing the connection */\n enableReadyCheck?: boolean;\n /** Cluster mode read operation settings, can make reads on masters, slaves, or both */\n scaleReads?: string;\n /** Database index to use (default: 0) */\n db?: number;\n /** Lazy connect - don't connect until first command (default: false) */\n lazyConnect?: boolean;\n}\n"],"mappings":"","ignoreList":[]}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { Redis, createRedisClient } from './Redis';
|
|
1
|
+
export { Redis, createRedisClient, getClient, init, shutdown } from './Redis';
|
|
2
2
|
export * from './Redis.types';
|
|
@@ -5,7 +5,10 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
var _exportNames = {
|
|
7
7
|
Redis: true,
|
|
8
|
-
createRedisClient: true
|
|
8
|
+
createRedisClient: true,
|
|
9
|
+
getClient: true,
|
|
10
|
+
init: true,
|
|
11
|
+
shutdown: true
|
|
9
12
|
};
|
|
10
13
|
Object.defineProperty(exports, "Redis", {
|
|
11
14
|
enumerable: true,
|
|
@@ -19,6 +22,24 @@ Object.defineProperty(exports, "createRedisClient", {
|
|
|
19
22
|
return _Redis.createRedisClient;
|
|
20
23
|
}
|
|
21
24
|
});
|
|
25
|
+
Object.defineProperty(exports, "getClient", {
|
|
26
|
+
enumerable: true,
|
|
27
|
+
get: function () {
|
|
28
|
+
return _Redis.getClient;
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
Object.defineProperty(exports, "init", {
|
|
32
|
+
enumerable: true,
|
|
33
|
+
get: function () {
|
|
34
|
+
return _Redis.init;
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
Object.defineProperty(exports, "shutdown", {
|
|
38
|
+
enumerable: true,
|
|
39
|
+
get: function () {
|
|
40
|
+
return _Redis.shutdown;
|
|
41
|
+
}
|
|
42
|
+
});
|
|
22
43
|
var _Redis = require("./Redis");
|
|
23
44
|
var _Redis2 = require("./Redis.types");
|
|
24
45
|
Object.keys(_Redis2).forEach(function (key) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["_Redis","require","_Redis2","Object","keys","forEach","key","prototype","hasOwnProperty","call","_exportNames","exports","defineProperty","enumerable","get"],"sources":["../../../src/entities/Redis/index.ts"],"sourcesContent":["export { Redis, createRedisClient } from './Redis';\nexport * from './Redis.types';\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","names":["_Redis","require","_Redis2","Object","keys","forEach","key","prototype","hasOwnProperty","call","_exportNames","exports","defineProperty","enumerable","get"],"sources":["../../../src/entities/Redis/index.ts"],"sourcesContent":["export { Redis, createRedisClient, getClient, init, shutdown } from './Redis';\nexport * from './Redis.types';\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,IAAAA,MAAA,GAAAC,OAAA;AACA,IAAAC,OAAA,GAAAD,OAAA;AAAAE,MAAA,CAAAC,IAAA,CAAAF,OAAA,EAAAG,OAAA,WAAAC,GAAA;EAAA,IAAAA,GAAA,kBAAAA,GAAA;EAAA,IAAAH,MAAA,CAAAI,SAAA,CAAAC,cAAA,CAAAC,IAAA,CAAAC,YAAA,EAAAJ,GAAA;EAAA,IAAAA,GAAA,IAAAK,OAAA,IAAAA,OAAA,CAAAL,GAAA,MAAAJ,OAAA,CAAAI,GAAA;EAAAH,MAAA,CAAAS,cAAA,CAAAD,OAAA,EAAAL,GAAA;IAAAO,UAAA;IAAAC,GAAA,WAAAA,CAAA;MAAA,OAAAZ,OAAA,CAAAI,GAAA;IAAA;EAAA;AAAA","ignoreList":[]}
|
|
@@ -1,4 +1,14 @@
|
|
|
1
1
|
import { LogEntry, FullLogEntry } from './output.types';
|
|
2
|
+
import { LogSeverity } from '../../const';
|
|
2
3
|
export declare const INSTANCE_ID: `${string}-${string}-${string}-${string}-${string}`;
|
|
4
|
+
/**
|
|
5
|
+
* Format timestamp as HH:MM:SS
|
|
6
|
+
*/
|
|
7
|
+
export declare function formatTime(date?: Date): string;
|
|
8
|
+
/**
|
|
9
|
+
* Format log entry for human-readable local development output
|
|
10
|
+
*/
|
|
11
|
+
export declare function formatLocalLog(severity: LogSeverity | string, message: string): void;
|
|
12
|
+
export declare function formatLocalLog(entry: FullLogEntry): string;
|
|
3
13
|
/** Add metadata to the log entry and print it */
|
|
4
14
|
export declare function output(data: LogEntry): FullLogEntry;
|
|
@@ -5,6 +5,8 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
value: true
|
|
6
6
|
});
|
|
7
7
|
exports.INSTANCE_ID = void 0;
|
|
8
|
+
exports.formatLocalLog = formatLocalLog;
|
|
9
|
+
exports.formatTime = formatTime;
|
|
8
10
|
exports.output = output;
|
|
9
11
|
var _crypto = require("crypto");
|
|
10
12
|
var _callsite = _interopRequireDefault(require("callsite"));
|
|
@@ -51,15 +53,28 @@ function getSeverityColor(severity) {
|
|
|
51
53
|
/**
|
|
52
54
|
* Format timestamp as HH:MM:SS
|
|
53
55
|
*/
|
|
54
|
-
function formatTime() {
|
|
55
|
-
const now = new Date();
|
|
56
|
+
function formatTime(date) {
|
|
57
|
+
const now = date || new Date();
|
|
56
58
|
return now.toTimeString().split(' ')[0];
|
|
57
59
|
}
|
|
58
60
|
|
|
59
61
|
/**
|
|
60
62
|
* Format log entry for human-readable local development output
|
|
61
63
|
*/
|
|
62
|
-
|
|
64
|
+
|
|
65
|
+
function formatLocalLog(severityOrEntry, message) {
|
|
66
|
+
// Handle overloaded signature for testing
|
|
67
|
+
if (typeof severityOrEntry === 'string' && message !== undefined) {
|
|
68
|
+
const time = formatTime();
|
|
69
|
+
const severityColor = getSeverityColor(severityOrEntry);
|
|
70
|
+
const useColors = process.env.NODE_ENV !== 'production';
|
|
71
|
+
let output = useColors ? `${colors.gray}[${time}]${colors.reset} ${severityColor}${severityOrEntry.padEnd(8)}${colors.reset} ${message}` : `[${time}] ${severityOrEntry.padEnd(8)} ${message}`;
|
|
72
|
+
console.log(output);
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Original function implementation
|
|
77
|
+
const entry = severityOrEntry;
|
|
63
78
|
const time = formatTime();
|
|
64
79
|
const severity = entry.severity || 'INFO';
|
|
65
80
|
const severityColor = getSeverityColor(severity);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"output.js","names":["_crypto","require","_callsite","_interopRequireDefault","_jsonStringifySafe","_const","INSTANCE_ID","exports","randomUUID","colors","reset","bright","dim","red","green","yellow","blue","magenta","cyan","white","gray","getSeverityColor","severity","LogSeverity","DEBUG","INFO","WARNING","ERROR","CRITICAL","formatTime","now","Date","toTimeString","split","formatLocalLog","entry","time","severityColor","showDetailedLogs","process","env","DETAILED_LOGS","parts","push","padEnd","message","output","join","errorType","errorCode","statusCode","errorParts","statusColor","length","context","httpRequest","req","method","url","stack_trace","data","Object","keys","JSON","stringify","fileName","lineNumber","isLocalDevelopment","LOG_FORMAT","NODE_ENV","KUBERNETES_POD_NAME","CLOUD_RUN_JOB","call","callsite","fullEntry","getLineNumber","getFileName","replace","serviceContext","service","CHART","HOSTNAME","version","BUILD_ID","environment","instance","SILENCE_REPORT","console","dir","depth","formattedLog","error","log"],"sources":["../../../src/utils/report/output.ts"],"sourcesContent":["import { randomUUID } from 'crypto';\nimport callsite from 'callsite';\nimport stringify from 'json-stringify-safe';\nimport { LogEntry, FullLogEntry } from './output.types';\nimport { LogSeverity } from 'const';\n\n// NOTE: Server instance id (helpful for distributed logs)\nexport const INSTANCE_ID = randomUUID();\n\n// ANSI color codes for terminal output\nconst colors = {\n reset: '\\x1b[0m',\n bright: '\\x1b[1m',\n dim: '\\x1b[2m',\n red: '\\x1b[31m',\n green: '\\x1b[32m',\n yellow: '\\x1b[33m',\n blue: '\\x1b[34m',\n magenta: '\\x1b[35m',\n cyan: '\\x1b[36m',\n white: '\\x1b[37m',\n gray: '\\x1b[90m'\n};\n\n/**\n * Get color for log severity level\n */\nfunction getSeverityColor(severity?: string): string {\n switch (severity) {\n case LogSeverity.DEBUG:\n return colors.cyan;\n case LogSeverity.INFO:\n return colors.green;\n case LogSeverity.WARNING:\n return colors.yellow;\n case LogSeverity.ERROR:\n return colors.red;\n case LogSeverity.CRITICAL:\n return `${colors.bright}${colors.red}`;\n default:\n return colors.white;\n }\n}\n\n/**\n * Format timestamp as HH:MM:SS\n */\nfunction formatTime(): string {\n const now = new Date();\n return now.toTimeString().split(' ')[0];\n}\n\n/**\n * Format log entry for human-readable local development output\n */\nfunction formatLocalLog(entry: FullLogEntry): string {\n const time = formatTime();\n const severity = entry.severity || 'INFO';\n const severityColor = getSeverityColor(severity);\n const showDetailedLogs = process.env.DETAILED_LOGS === 'true';\n \n const parts: string[] = [];\n \n // Timestamp and severity\n parts.push(\n `${colors.gray}[${time}]${colors.reset} ${severityColor}${severity.padEnd(8)}${colors.reset}`\n );\n \n // Message\n if (entry.message) {\n parts.push(`${entry.message}`);\n }\n \n let output = parts.join(' ');\n \n // Error details (compact format)\n if (entry.errorType || entry.errorCode || entry.statusCode) {\n const errorParts: string[] = [];\n if (entry.errorCode) errorParts.push(`${colors.red}${entry.errorCode}${colors.reset}`);\n if (entry.statusCode) {\n const statusColor = entry.statusCode >= 500 ? colors.red : entry.statusCode >= 400 ? colors.yellow : colors.green;\n errorParts.push(`${statusColor}${entry.statusCode}${colors.reset}`);\n }\n if (errorParts.length > 0) {\n output += ` ${colors.dim}[${errorParts.join(' ')}]${colors.reset}`;\n }\n }\n \n // HTTP request context (compact)\n if (entry.context?.httpRequest) {\n const req = entry.context.httpRequest;\n output += ` ${colors.dim}${req.method} ${req.url}${colors.reset}`;\n }\n \n // Stack trace (only in detailed mode)\n if (showDetailedLogs && entry.stack_trace) {\n output += `\\n${colors.gray}Stack Trace:${colors.reset}\\n${colors.dim}${entry.stack_trace}${colors.reset}`;\n }\n \n // Additional data (only in detailed mode or if no message)\n if (showDetailedLogs && entry.data && Object.keys(entry.data).length > 0) {\n output += `\\n${colors.cyan}Data:${colors.reset}\\n${colors.dim}${JSON.stringify(entry.data, null, 2)}${colors.reset}`;\n }\n \n // File location (only in detailed mode)\n if (showDetailedLogs && entry.fileName) {\n output += `\\n ${colors.dim}${entry.fileName}:${entry.lineNumber || '?'}${colors.reset}`;\n }\n \n return output;\n}\n\n/**\n * Check if running in local development environment\n */\nfunction isLocalDevelopment(): boolean {\n // Allow forcing local format via environment variable\n if (process.env.LOG_FORMAT === 'local') return true;\n if (process.env.LOG_FORMAT === 'json') return false;\n \n return (\n process.env.NODE_ENV === 'development' ||\n process.env.NODE_ENV === 'dev' ||\n (!process.env.NODE_ENV && !process.env.KUBERNETES_POD_NAME && !process.env.CLOUD_RUN_JOB)\n );\n}\n\n/** Add metadata to the log entry and print it */\nexport function output(data: LogEntry): FullLogEntry {\n // Gather useful information about where the logger was called from\n const call = callsite()[2];\n\n // Append additional metadata to the log entry\n const fullEntry: FullLogEntry = {\n ...data,\n lineNumber: call.getLineNumber(),\n fileName: call\n .getFileName()\n .replace(/.*node_modules\\//, '')\n .replace(/.*src\\//, 'src/'),\n serviceContext: {\n service: process.env.CHART ?? process.env.HOSTNAME,\n version: process.env.BUILD_ID,\n environment: process.env.NODE_ENV,\n instance: process.env.KUBERNETES_POD_NAME ?? INSTANCE_ID\n }\n };\n\n // Ignore when silenced\n if (process.env.SILENCE_REPORT) return fullEntry;\n\n if (process.env.NODE_ENV === 'test') {\n // In test mode pretty print with full depth\n console.dir(fullEntry, { depth: 5 });\n } else if (isLocalDevelopment()) {\n // Local development: use formatted, colorized output\n const formattedLog = formatLocalLog(fullEntry);\n if (data.severity === LogSeverity.ERROR || data.severity === LogSeverity.CRITICAL || (data.statusCode && data.statusCode >= 500)) {\n console.error(formattedLog);\n } else {\n console.log(formattedLog);\n }\n } else {\n // Production/GCP: use JSON format for structured logging\n const entry = stringify(fullEntry);\n if (data.statusCode && data.statusCode >= 500) {\n console.error(entry);\n } else {\n console.log(entry);\n }\n }\n \n return fullEntry;\n}\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"output.js","names":["_crypto","require","_callsite","_interopRequireDefault","_jsonStringifySafe","_const","INSTANCE_ID","exports","randomUUID","colors","reset","bright","dim","red","green","yellow","blue","magenta","cyan","white","gray","getSeverityColor","severity","LogSeverity","DEBUG","INFO","WARNING","ERROR","CRITICAL","formatTime","date","now","Date","toTimeString","split","formatLocalLog","severityOrEntry","message","undefined","time","severityColor","useColors","process","env","NODE_ENV","output","padEnd","console","log","entry","showDetailedLogs","DETAILED_LOGS","parts","push","join","errorType","errorCode","statusCode","errorParts","statusColor","length","context","httpRequest","req","method","url","stack_trace","data","Object","keys","JSON","stringify","fileName","lineNumber","isLocalDevelopment","LOG_FORMAT","KUBERNETES_POD_NAME","CLOUD_RUN_JOB","call","callsite","fullEntry","getLineNumber","getFileName","replace","serviceContext","service","CHART","HOSTNAME","version","BUILD_ID","environment","instance","SILENCE_REPORT","dir","depth","formattedLog","error"],"sources":["../../../src/utils/report/output.ts"],"sourcesContent":["import { randomUUID } from 'crypto';\nimport callsite from 'callsite';\nimport stringify from 'json-stringify-safe';\nimport { LogEntry, FullLogEntry } from './output.types';\nimport { LogSeverity } from 'const';\n\n// NOTE: Server instance id (helpful for distributed logs)\nexport const INSTANCE_ID = randomUUID();\n\n// ANSI color codes for terminal output\nconst colors = {\n reset: '\\x1b[0m',\n bright: '\\x1b[1m',\n dim: '\\x1b[2m',\n red: '\\x1b[31m',\n green: '\\x1b[32m',\n yellow: '\\x1b[33m',\n blue: '\\x1b[34m',\n magenta: '\\x1b[35m',\n cyan: '\\x1b[36m',\n white: '\\x1b[37m',\n gray: '\\x1b[90m'\n};\n\n/**\n * Get color for log severity level\n */\nfunction getSeverityColor(severity?: string): string {\n switch (severity) {\n case LogSeverity.DEBUG:\n return colors.cyan;\n case LogSeverity.INFO:\n return colors.green;\n case LogSeverity.WARNING:\n return colors.yellow;\n case LogSeverity.ERROR:\n return colors.red;\n case LogSeverity.CRITICAL:\n return `${colors.bright}${colors.red}`;\n default:\n return colors.white;\n }\n}\n\n/**\n * Format timestamp as HH:MM:SS\n */\nexport function formatTime(date?: Date): string {\n const now = date || new Date();\n return now.toTimeString().split(' ')[0];\n}\n\n/**\n * Format log entry for human-readable local development output\n */\nexport function formatLocalLog(severity: LogSeverity | string, message: string): void;\nexport function formatLocalLog(entry: FullLogEntry): string;\nexport function formatLocalLog(severityOrEntry: LogSeverity | string | FullLogEntry, message?: string): string | void {\n // Handle overloaded signature for testing\n if (typeof severityOrEntry === 'string' && message !== undefined) {\n const time = formatTime();\n const severityColor = getSeverityColor(severityOrEntry);\n const useColors = process.env.NODE_ENV !== 'production';\n \n let output = useColors \n ? `${colors.gray}[${time}]${colors.reset} ${severityColor}${severityOrEntry.padEnd(8)}${colors.reset} ${message}`\n : `[${time}] ${severityOrEntry.padEnd(8)} ${message}`;\n \n console.log(output);\n return;\n }\n \n // Original function implementation\n const entry = severityOrEntry as FullLogEntry;\n const time = formatTime();\n const severity = entry.severity || 'INFO';\n const severityColor = getSeverityColor(severity);\n const showDetailedLogs = process.env.DETAILED_LOGS === 'true';\n \n const parts: string[] = [];\n \n // Timestamp and severity\n parts.push(\n `${colors.gray}[${time}]${colors.reset} ${severityColor}${severity.padEnd(8)}${colors.reset}`\n );\n \n // Message\n if (entry.message) {\n parts.push(`${entry.message}`);\n }\n \n let output = parts.join(' ');\n \n // Error details (compact format)\n if (entry.errorType || entry.errorCode || entry.statusCode) {\n const errorParts: string[] = [];\n if (entry.errorCode) errorParts.push(`${colors.red}${entry.errorCode}${colors.reset}`);\n if (entry.statusCode) {\n const statusColor = entry.statusCode >= 500 ? colors.red : entry.statusCode >= 400 ? colors.yellow : colors.green;\n errorParts.push(`${statusColor}${entry.statusCode}${colors.reset}`);\n }\n if (errorParts.length > 0) {\n output += ` ${colors.dim}[${errorParts.join(' ')}]${colors.reset}`;\n }\n }\n \n // HTTP request context (compact)\n if (entry.context?.httpRequest) {\n const req = entry.context.httpRequest;\n output += ` ${colors.dim}${req.method} ${req.url}${colors.reset}`;\n }\n \n // Stack trace (only in detailed mode)\n if (showDetailedLogs && entry.stack_trace) {\n output += `\\n${colors.gray}Stack Trace:${colors.reset}\\n${colors.dim}${entry.stack_trace}${colors.reset}`;\n }\n \n // Additional data (only in detailed mode or if no message)\n if (showDetailedLogs && entry.data && Object.keys(entry.data).length > 0) {\n output += `\\n${colors.cyan}Data:${colors.reset}\\n${colors.dim}${JSON.stringify(entry.data, null, 2)}${colors.reset}`;\n }\n \n // File location (only in detailed mode)\n if (showDetailedLogs && entry.fileName) {\n output += `\\n ${colors.dim}${entry.fileName}:${entry.lineNumber || '?'}${colors.reset}`;\n }\n \n return output;\n}\n\n/**\n * Check if running in local development environment\n */\nfunction isLocalDevelopment(): boolean {\n // Allow forcing local format via environment variable\n if (process.env.LOG_FORMAT === 'local') return true;\n if (process.env.LOG_FORMAT === 'json') return false;\n \n return (\n process.env.NODE_ENV === 'development' ||\n process.env.NODE_ENV === 'dev' ||\n (!process.env.NODE_ENV && !process.env.KUBERNETES_POD_NAME && !process.env.CLOUD_RUN_JOB)\n );\n}\n\n/** Add metadata to the log entry and print it */\nexport function output(data: LogEntry): FullLogEntry {\n // Gather useful information about where the logger was called from\n const call = callsite()[2];\n\n // Append additional metadata to the log entry\n const fullEntry: FullLogEntry = {\n ...data,\n lineNumber: call.getLineNumber(),\n fileName: call\n .getFileName()\n .replace(/.*node_modules\\//, '')\n .replace(/.*src\\//, 'src/'),\n serviceContext: {\n service: process.env.CHART ?? process.env.HOSTNAME,\n version: process.env.BUILD_ID,\n environment: process.env.NODE_ENV,\n instance: process.env.KUBERNETES_POD_NAME ?? INSTANCE_ID\n }\n };\n\n // Ignore when silenced\n if (process.env.SILENCE_REPORT) return fullEntry;\n\n if (process.env.NODE_ENV === 'test') {\n // In test mode pretty print with full depth\n console.dir(fullEntry, { depth: 5 });\n } else if (isLocalDevelopment()) {\n // Local development: use formatted, colorized output\n const formattedLog = formatLocalLog(fullEntry);\n if (data.severity === LogSeverity.ERROR || data.severity === LogSeverity.CRITICAL || (data.statusCode && data.statusCode >= 500)) {\n console.error(formattedLog);\n } else {\n console.log(formattedLog);\n }\n } else {\n // Production/GCP: use JSON format for structured logging\n const entry = stringify(fullEntry);\n if (data.statusCode && data.statusCode >= 500) {\n console.error(entry);\n } else {\n console.log(entry);\n }\n }\n \n return fullEntry;\n}\n"],"mappings":"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","ignoreList":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "node-server-engine",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.8.0",
|
|
4
4
|
"description": "Framework used to develop backend services. This package ships with a lot of features to standardize the creation of services, letting you focus on the business logic.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -11,8 +11,9 @@
|
|
|
11
11
|
"lint:fix": "eslint ./src --fix",
|
|
12
12
|
"prepublish": "npm run build",
|
|
13
13
|
"prepublishOnly": "npm run build",
|
|
14
|
-
"test": "cross-env NODE_ENV=test TS_NODE_PROJECT=tsconfig.test.json
|
|
15
|
-
"test:
|
|
14
|
+
"test": "cross-env NODE_ENV=test TS_NODE_PROJECT=tsconfig.test.json mocha --require ts-node/register --require tsconfig-paths/register --reporter spec --timeout 10000 --exit test/hooks.ts 'src/**/*.test.ts'",
|
|
15
|
+
"test:coverage": "cross-env NODE_ENV=test TS_NODE_PROJECT=tsconfig.test.json nyc --reporter=text --no-clean mocha --require ts-node/register --require tsconfig-paths/register --reporter spec test/hooks.ts 'src/**/*.test.ts'",
|
|
16
|
+
"test:file": "cross-env NODE_ENV=test TS_NODE_PROJECT=tsconfig.test.json mocha --require ts-node/register --require tsconfig-paths/register --reporter spec --exit test/hooks.ts",
|
|
16
17
|
"coverage": "nyc report --report-dir=./.test-coverage --reporter=html --reporter=text",
|
|
17
18
|
"coverage:ci": "nyc report --reporter=text-summary",
|
|
18
19
|
"test:ci": "npm run test -- --reporter spec",
|
|
@@ -61,7 +62,7 @@
|
|
|
61
62
|
"filesize-parser": "^1.5.1",
|
|
62
63
|
"fs-extra": "^11.3.0",
|
|
63
64
|
"glob": "^11.0.0",
|
|
64
|
-
"ioredis": "^5.
|
|
65
|
+
"ioredis": "^5.8.2",
|
|
65
66
|
"json-stringify-safe": "^5.0.1",
|
|
66
67
|
"jsonwebtoken": "^9.0.2",
|
|
67
68
|
"mime-types": "^2.1.35",
|