node-server-engine 1.7.3 → 1.7.4

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.
@@ -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.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) clearTimeout(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","checkEnvironment","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","clearTimeout"],"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 { checkEnvironment } 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 checkEnvironment({ 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) clearTimeout(interval);\n }\n};\n"],"mappings":"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","ignoreList":[]}
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,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
- function formatLocalLog(entry) {
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.7.3",
3
+ "version": "1.7.4",
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 nyc --reporter=text --no-clean mocha --require ts-node/register --require tsconfig-paths/register --reporter spec test/hooks.ts 'src/**/*.test.ts'",
15
- "test:file": "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",
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",