@scpxl/nodejs-framework 1.0.17 → 1.0.19

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.
Files changed (192) hide show
  1. package/README.md +29 -0
  2. package/dist/api-requester/api-requester.d.ts +27 -6
  3. package/dist/api-requester/api-requester.d.ts.map +1 -1
  4. package/dist/api-requester/api-requester.js +188 -26
  5. package/dist/api-requester/api-requester.js.map +2 -2
  6. package/dist/api-requester/index.d.ts +1 -0
  7. package/dist/api-requester/index.d.ts.map +1 -1
  8. package/dist/api-requester/index.js.map +1 -1
  9. package/dist/application/base-application.d.ts +15 -22
  10. package/dist/application/base-application.d.ts.map +1 -1
  11. package/dist/application/base-application.js +145 -111
  12. package/dist/application/base-application.js.map +2 -2
  13. package/dist/application/command-application.d.ts.map +1 -1
  14. package/dist/application/command-application.js +3 -4
  15. package/dist/application/command-application.js.map +2 -2
  16. package/dist/application/web-application.d.ts.map +1 -1
  17. package/dist/application/web-application.js +9 -2
  18. package/dist/application/web-application.js.map +2 -2
  19. package/dist/cache/manager.d.ts +87 -6
  20. package/dist/cache/manager.d.ts.map +1 -1
  21. package/dist/cache/manager.js +77 -30
  22. package/dist/cache/manager.js.map +2 -2
  23. package/dist/cluster/cluster-manager.d.ts.map +1 -1
  24. package/dist/cluster/cluster-manager.js +5 -8
  25. package/dist/cluster/cluster-manager.js.map +2 -2
  26. package/dist/config/env.d.ts +11 -0
  27. package/dist/config/env.d.ts.map +1 -0
  28. package/dist/config/env.js +103 -0
  29. package/dist/config/env.js.map +7 -0
  30. package/dist/config/index.d.ts +3 -0
  31. package/dist/config/index.d.ts.map +1 -0
  32. package/dist/config/index.js +3 -0
  33. package/dist/config/index.js.map +7 -0
  34. package/dist/config/schema.d.ts +408 -0
  35. package/dist/config/schema.d.ts.map +1 -0
  36. package/dist/config/schema.js +218 -0
  37. package/dist/config/schema.js.map +7 -0
  38. package/dist/database/dynamic-entity.d.ts.map +1 -1
  39. package/dist/database/dynamic-entity.js +6 -2
  40. package/dist/database/dynamic-entity.js.map +2 -2
  41. package/dist/database/instance.d.ts.map +1 -1
  42. package/dist/database/instance.js +0 -8
  43. package/dist/database/instance.js.map +2 -2
  44. package/dist/database/manager.d.ts.map +1 -1
  45. package/dist/database/manager.js +71 -9
  46. package/dist/database/manager.js.map +2 -2
  47. package/dist/error/error-reporter.d.ts +96 -0
  48. package/dist/error/error-reporter.d.ts.map +1 -0
  49. package/dist/error/error-reporter.js +228 -0
  50. package/dist/error/error-reporter.js.map +7 -0
  51. package/dist/error/error.interface.d.ts +126 -0
  52. package/dist/error/error.interface.d.ts.map +1 -0
  53. package/dist/error/error.interface.js +45 -0
  54. package/dist/error/error.interface.js.map +7 -0
  55. package/dist/error/framework-errors.d.ts +113 -0
  56. package/dist/error/framework-errors.d.ts.map +1 -0
  57. package/dist/error/framework-errors.js +176 -0
  58. package/dist/error/framework-errors.js.map +7 -0
  59. package/dist/error/index.d.ts +6 -0
  60. package/dist/error/index.d.ts.map +1 -0
  61. package/dist/error/index.js +34 -0
  62. package/dist/error/index.js.map +7 -0
  63. package/dist/event/manager.d.ts.map +1 -1
  64. package/dist/event/manager.js +2 -9
  65. package/dist/event/manager.js.map +2 -2
  66. package/dist/index.d.ts +5 -1
  67. package/dist/index.d.ts.map +1 -1
  68. package/dist/index.js +5 -1
  69. package/dist/index.js.map +2 -2
  70. package/dist/lifecycle/exit.d.ts +2 -1
  71. package/dist/lifecycle/exit.d.ts.map +1 -1
  72. package/dist/lifecycle/exit.js +6 -0
  73. package/dist/lifecycle/exit.js.map +2 -2
  74. package/dist/lifecycle/index.d.ts +7 -0
  75. package/dist/lifecycle/index.d.ts.map +1 -0
  76. package/dist/lifecycle/index.js +12 -0
  77. package/dist/lifecycle/index.js.map +7 -0
  78. package/dist/lifecycle/lifecycle-manager.d.ts +55 -2
  79. package/dist/lifecycle/lifecycle-manager.d.ts.map +1 -1
  80. package/dist/lifecycle/lifecycle-manager.js +233 -7
  81. package/dist/lifecycle/lifecycle-manager.js.map +3 -3
  82. package/dist/lifecycle/shutdown-controller.d.ts +15 -0
  83. package/dist/lifecycle/shutdown-controller.d.ts.map +1 -0
  84. package/dist/lifecycle/shutdown-controller.js +38 -0
  85. package/dist/lifecycle/shutdown-controller.js.map +7 -0
  86. package/dist/lifecycle/types.d.ts +28 -0
  87. package/dist/lifecycle/types.d.ts.map +1 -0
  88. package/dist/lifecycle/types.js +13 -0
  89. package/dist/lifecycle/types.js.map +7 -0
  90. package/dist/logger/logger.d.ts +2 -1
  91. package/dist/logger/logger.d.ts.map +1 -1
  92. package/dist/logger/logger.js +35 -11
  93. package/dist/logger/logger.js.map +2 -2
  94. package/dist/performance/cache-performance.d.ts +6 -0
  95. package/dist/performance/cache-performance.d.ts.map +1 -1
  96. package/dist/performance/cache-performance.js +16 -0
  97. package/dist/performance/cache-performance.js.map +2 -2
  98. package/dist/performance/index.d.ts +1 -0
  99. package/dist/performance/index.d.ts.map +1 -1
  100. package/dist/performance/index.js +1 -0
  101. package/dist/performance/index.js.map +2 -2
  102. package/dist/performance/performance-monitor.d.ts.map +1 -1
  103. package/dist/performance/performance-monitor.js +47 -18
  104. package/dist/performance/performance-monitor.js.map +2 -2
  105. package/dist/performance/performance-monitor.plugin.d.ts +24 -0
  106. package/dist/performance/performance-monitor.plugin.d.ts.map +1 -0
  107. package/dist/performance/performance-monitor.plugin.js +89 -0
  108. package/dist/performance/performance-monitor.plugin.js.map +7 -0
  109. package/dist/performance/webserver-performance.js +1 -1
  110. package/dist/performance/webserver-performance.js.map +2 -2
  111. package/dist/queue/manager.d.ts.map +1 -1
  112. package/dist/queue/manager.js +3 -10
  113. package/dist/queue/manager.js.map +2 -2
  114. package/dist/queue/worker.d.ts.map +1 -1
  115. package/dist/queue/worker.js +2 -2
  116. package/dist/queue/worker.js.map +2 -2
  117. package/dist/redis/manager.d.ts.map +1 -1
  118. package/dist/redis/manager.js +228 -33
  119. package/dist/redis/manager.js.map +2 -2
  120. package/dist/request-context/index.d.ts +3 -0
  121. package/dist/request-context/index.d.ts.map +1 -0
  122. package/dist/request-context/index.js +25 -0
  123. package/dist/request-context/index.js.map +7 -0
  124. package/dist/request-context/request-context.d.ts +108 -0
  125. package/dist/request-context/request-context.d.ts.map +1 -0
  126. package/dist/request-context/request-context.interface.d.ts +46 -0
  127. package/dist/request-context/request-context.interface.d.ts.map +1 -0
  128. package/dist/request-context/request-context.interface.js +1 -0
  129. package/dist/request-context/request-context.interface.js.map +7 -0
  130. package/dist/request-context/request-context.js +79 -0
  131. package/dist/request-context/request-context.js.map +7 -0
  132. package/dist/services/aws/s3.js +4 -6
  133. package/dist/services/aws/s3.js.map +2 -2
  134. package/dist/util/file.d.ts +13 -0
  135. package/dist/util/file.d.ts.map +1 -1
  136. package/dist/util/file.js +46 -9
  137. package/dist/util/file.js.map +2 -2
  138. package/dist/util/helper.d.ts +16 -1
  139. package/dist/util/helper.d.ts.map +1 -1
  140. package/dist/util/helper.js +19 -43
  141. package/dist/util/helper.js.map +2 -2
  142. package/dist/util/index.d.ts +1 -0
  143. package/dist/util/index.d.ts.map +1 -1
  144. package/dist/util/index.js +18 -16
  145. package/dist/util/index.js.map +2 -2
  146. package/dist/util/loader.d.ts.map +1 -1
  147. package/dist/util/loader.js +13 -2
  148. package/dist/util/loader.js.map +2 -2
  149. package/dist/util/os.d.ts.map +1 -1
  150. package/dist/util/os.js +8 -14
  151. package/dist/util/os.js.map +2 -2
  152. package/dist/util/time.d.ts +8 -2
  153. package/dist/util/time.d.ts.map +1 -1
  154. package/dist/util/time.js +12 -7
  155. package/dist/util/time.js.map +2 -2
  156. package/dist/util/timing.d.ts +36 -0
  157. package/dist/util/timing.d.ts.map +1 -0
  158. package/dist/util/timing.interface.d.ts +47 -0
  159. package/dist/util/timing.interface.d.ts.map +1 -0
  160. package/dist/util/timing.interface.js +1 -0
  161. package/dist/util/timing.interface.js.map +7 -0
  162. package/dist/util/timing.js +98 -0
  163. package/dist/util/timing.js.map +7 -0
  164. package/dist/util/url.js +1 -1
  165. package/dist/util/url.js.map +2 -2
  166. package/dist/webserver/controller/base.d.ts +3 -1
  167. package/dist/webserver/controller/base.d.ts.map +1 -1
  168. package/dist/webserver/controller/base.interface.d.ts +2 -0
  169. package/dist/webserver/controller/base.interface.d.ts.map +1 -1
  170. package/dist/webserver/controller/base.js +4 -1
  171. package/dist/webserver/controller/base.js.map +2 -2
  172. package/dist/webserver/controller/health.d.ts +8 -1
  173. package/dist/webserver/controller/health.d.ts.map +1 -1
  174. package/dist/webserver/controller/health.js +36 -22
  175. package/dist/webserver/controller/health.js.map +2 -2
  176. package/dist/webserver/webserver.d.ts +16 -2
  177. package/dist/webserver/webserver.d.ts.map +1 -1
  178. package/dist/webserver/webserver.interface.d.ts +37 -0
  179. package/dist/webserver/webserver.interface.d.ts.map +1 -1
  180. package/dist/webserver/webserver.interface.js.map +2 -2
  181. package/dist/webserver/webserver.js +117 -20
  182. package/dist/webserver/webserver.js.map +2 -2
  183. package/dist/websocket/controllers/server/system.d.ts.map +1 -1
  184. package/dist/websocket/controllers/server/system.js.map +2 -2
  185. package/dist/websocket/websocket-base.d.ts.map +1 -1
  186. package/dist/websocket/websocket-base.js +2 -3
  187. package/dist/websocket/websocket-base.js.map +2 -2
  188. package/dist/websocket/websocket-server.d.ts +1 -1
  189. package/dist/websocket/websocket-server.d.ts.map +1 -1
  190. package/dist/websocket/websocket-server.js +7 -31
  191. package/dist/websocket/websocket-server.js.map +2 -2
  192. package/package.json +51 -10
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/util/file.ts"],
4
- "sourcesContent": ["import * as fs from 'fs';\nimport * as path from 'path';\nimport * as https from 'https';\nimport { pipeline } from 'stream';\nimport { promisify } from 'node:util';\nimport ffmpeg from 'fluent-ffmpeg';\n\nconst pipelineAsync = promisify(pipeline);\n\nasync function convertFile({\n inputFilePath,\n outputFilePath,\n format,\n}: {\n inputFilePath: string;\n outputFilePath: string;\n format: string;\n}): Promise<void> {\n return new Promise((resolve, reject) => {\n console.log(`Starting conversion: ${inputFilePath} -> ${outputFilePath} (format: ${format})`);\n\n const command = ffmpeg(inputFilePath)\n .output(outputFilePath)\n .outputFormat(format === 'jpg' ? 'mjpeg' : format) // Using 'mjpeg' for jpg\n .on('progress', (progress: any) => {\n console.log(`Processing: ${Math.round(progress.percent)}% done`);\n })\n .on('end', () => {\n console.log('Conversion finished successfully');\n resolve();\n })\n .on('error', (err: Error) => {\n console.error('Error during conversion:', err);\n reject(err);\n });\n\n // Start processing\n command.run();\n });\n}\n\n/**\n * Copy a file or directory synchronously\n *\n * @param src The source path\n * @param dest The destination path\n */\nfunction copySync(src: string, dest: string): void {\n const stats = fs.statSync(src);\n\n if (stats.isDirectory()) {\n // Create destination directory if it doesn't exist\n if (!fs.existsSync(dest)) {\n fs.mkdirSync(dest);\n }\n\n // Read directory contents\n const entries = fs.readdirSync(src);\n\n // Copy each file/folder\n for (const entry of entries) {\n const srcPath = path.join(src, entry);\n const destPath = path.join(dest, entry);\n\n // Recursively copy directory or file\n copySync(srcPath, destPath);\n }\n } else {\n // Copy file\n fs.copyFileSync(src, dest);\n }\n}\n\n/**\n * Download file from URL\n *\n * @param url The URL to download the file from\n * @param destinationPath The path to save the downloaded file\n */\nasync function downloadFile({ url, destinationPath }: { url: string; destinationPath: string }): Promise<void> {\n return new Promise((resolve, reject) => {\n const file = fs.createWriteStream(destinationPath);\n\n https\n .get(url, response => {\n // Check if response status is OK (200\u2013299)\n if (response.statusCode && response.statusCode >= 200 && response.statusCode < 300) {\n pipelineAsync(response, file)\n .then(() => resolve())\n .catch(err => {\n fs.unlink(destinationPath, () => reject(err)); // Clean up partially written file on error\n });\n } else {\n fs.unlink(destinationPath, () => {\n reject(new Error(`Failed to download file, status code: ${response.statusCode}`));\n });\n }\n })\n .on('error', err => {\n fs.unlink(destinationPath, () => reject(err)); // Handle request errors\n });\n\n // Handle file stream errors\n file.on('error', err => {\n fs.unlink(destinationPath, () => reject(err));\n });\n });\n}\n\n/**\n * Format file size.\n *\n * @param bytes The file size in bytes\n */\nfunction formatFileSize({ bytes }: { bytes: number }): string {\n const sizes = ['bytes', 'kB', 'MB', 'GB', 'TB'];\n if (bytes === 0) return '0 bytes';\n\n const i = Math.floor(Math.log(bytes) / Math.log(1024));\n const fileSize = (bytes / Math.pow(1024, i)).toFixed(1);\n\n return `${fileSize} ${sizes[i]}`;\n}\n\n/**\n * Remove a file or directory synchronously\n *\n * @param target The path to the file or directory to remove\n */\nfunction removeSync(target: string): void {\n if (fs.existsSync(target)) {\n const stats = fs.statSync(target);\n\n if (stats.isDirectory()) {\n // Read the directory contents\n const entries = fs.readdirSync(target);\n\n // Recursively remove directory contents\n for (const entry of entries) {\n const entryPath = path.join(target, entry);\n removeSync(entryPath); // Recursively remove each file/folder\n }\n\n // Remove the directory itself\n fs.rmdirSync(target);\n } else {\n // Remove the file\n fs.unlinkSync(target);\n }\n } else {\n console.warn(`Path ${target} does not exist.`);\n }\n}\n\nexport default {\n convertFile,\n copySync,\n downloadFile,\n formatFileSize,\n removeSync,\n};\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import * as fs from 'fs';\nimport { access, mkdir } from 'fs/promises';\nimport * as path from 'path';\nimport * as https from 'https';\nimport { pipeline } from 'stream';\nimport { promisify } from 'node:util';\nimport ffmpeg from 'fluent-ffmpeg';\n\nconst pipelineAsync = promisify(pipeline);\n\n/**\n * Check if a file or directory exists asynchronously\n * @param pathToCheck - Path to check\n * @returns Promise<boolean> - true if exists, false otherwise\n */\nasync function pathExists(pathToCheck: string): Promise<boolean> {\n try {\n await access(pathToCheck);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Ensure directory exists, create if it doesn't\n * @param dirPath - Directory path to ensure\n */\nasync function ensureDir(dirPath: string): Promise<void> {\n try {\n await access(dirPath);\n } catch {\n await mkdir(dirPath, { recursive: true });\n }\n}\n\nasync function convertFile({\n inputFilePath,\n outputFilePath,\n format,\n}: {\n inputFilePath: string;\n outputFilePath: string;\n format: string;\n}): Promise<void> {\n return new Promise((resolve, reject) => {\n console.log(`Starting conversion: ${inputFilePath} -> ${outputFilePath} (format: ${format})`);\n\n const command = ffmpeg(inputFilePath)\n .output(outputFilePath)\n .outputFormat(format === 'jpg' ? 'mjpeg' : format) // Using 'mjpeg' for jpg\n .on('progress', (progress: any) => {\n console.log(`Processing: ${Math.round(progress.percent)}% done`);\n })\n .on('end', () => {\n console.log('Conversion finished successfully');\n resolve();\n })\n .on('error', (err: Error) => {\n console.error('Error during conversion:', err);\n reject(err);\n });\n\n // Start processing\n command.run();\n });\n}\n\n/**\n * Copy a file or directory synchronously\n *\n * @param src The source path\n * @param dest The destination path\n */\nfunction copySync(src: string, dest: string): void {\n const stats = fs.statSync(src);\n\n if (stats.isDirectory()) {\n // Create destination directory if it doesn't exist\n if (!fs.existsSync(dest)) {\n fs.mkdirSync(dest);\n }\n\n // Read directory contents\n for (const entry of fs.readdirSync(src)) {\n const srcPath = path.join(src, entry);\n const destPath = path.join(dest, entry);\n copySync(srcPath, destPath);\n }\n } else {\n // Copy file\n fs.copyFileSync(src, dest);\n }\n}\n\n/**\n * Download file from URL\n *\n * @param url The URL to download the file from\n * @param destinationPath The path to save the downloaded file\n */\nasync function downloadFile({ url, destinationPath }: { url: string; destinationPath: string }): Promise<void> {\n return new Promise((resolve, reject) => {\n const file = fs.createWriteStream(destinationPath);\n\n https\n .get(url, response => {\n // Check if response status is OK (200\u2013299)\n if (response.statusCode && response.statusCode >= 200 && response.statusCode < 300) {\n pipelineAsync(response, file)\n .then(() => resolve())\n .catch(err => {\n fs.unlink(destinationPath, () => reject(err)); // Clean up partially written file on error\n });\n } else {\n fs.unlink(destinationPath, () => {\n reject(new Error(`Failed to download file, status code: ${response.statusCode}`));\n });\n }\n })\n .on('error', err => {\n fs.unlink(destinationPath, () => reject(err)); // Handle request errors\n });\n\n // Handle file stream errors\n file.on('error', err => {\n fs.unlink(destinationPath, () => reject(err));\n });\n });\n}\n\n/**\n * Format file size.\n *\n * @param bytes The file size in bytes\n */\nfunction formatFileSize({ bytes }: { bytes: number }): string {\n if (bytes === 0) return '0 bytes';\n const units = ['bytes', 'kB', 'MB', 'GB', 'TB'] as const;\n let idx = Math.floor(Math.log(bytes) / Math.log(1024));\n if (idx < 0) idx = 0;\n if (idx >= units.length) idx = units.length - 1;\n const fileSize = (bytes / Math.pow(1024, idx)).toFixed(1);\n let unit: string;\n switch (idx) {\n case 0:\n unit = 'bytes';\n break;\n case 1:\n unit = 'kB';\n break;\n case 2:\n unit = 'MB';\n break;\n case 3:\n unit = 'GB';\n break;\n default:\n unit = 'TB';\n }\n return `${fileSize} ${unit}`;\n}\n\n/**\n * Remove a file or directory synchronously\n *\n * @param target The path to the file or directory to remove\n */\nfunction removeSync(target: string): void {\n if (fs.existsSync(target)) {\n const stats = fs.statSync(target);\n\n if (stats.isDirectory()) {\n // Read the directory contents\n for (const entry of fs.readdirSync(target)) {\n const entryPath = path.join(target, entry);\n removeSync(entryPath);\n }\n\n // Remove the directory itself\n fs.rmdirSync(target);\n } else {\n // Remove the file\n fs.unlinkSync(target);\n }\n } else {\n console.warn(`Path ${target} does not exist.`);\n }\n}\n\nexport default {\n convertFile,\n copySync,\n downloadFile,\n formatFileSize,\n removeSync,\n pathExists,\n ensureDir,\n};\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1,5 +1,20 @@
1
1
  /**
2
- * Deep merge two objects safely, preventing prototype pollution.
2
+ * Deep merge objects with defaults, preventing prototype pollution.
3
+ *
4
+ * This is a secure wrapper around lodash.defaultsdeep that:
5
+ * - Sanitizes sources to remove dangerous keys (__proto__, constructor, prototype)
6
+ * - Delegates to battle-tested lodash.defaultsdeep for merge logic
7
+ * - Maintains backward compatibility with existing usage
8
+ *
9
+ * @param target - The target object to merge into
10
+ * @param sources - Source objects providing default values
11
+ * @returns The merged target object (mutated)
12
+ *
13
+ * @example
14
+ * const userConfig = { host: 'localhost' };
15
+ * const defaults = { host: '0.0.0.0', port: 3001 };
16
+ * const merged = defaultsDeep(userConfig, defaults);
17
+ * // merged = { host: 'localhost', port: 3001 }
3
18
  */
4
19
  declare function defaultsDeep(target: any, ...sources: any[]): any;
5
20
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"helper.d.ts","sourceRoot":"","sources":["../../src/util/helper.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,iBAAS,YAAY,CAAC,MAAM,EAAE,GAAG,EAAE,GAAG,OAAO,EAAE,GAAG,EAAE,GAAG,GAAG,CA2CzD;AAED;;GAEG;AACH,iBAAS,QAAQ,CAAC,IAAI,EAAE,GAAG,GAAG,OAAO,CAEpC;AAED,KAAK,SAAS,GAAG;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;CAAE,CAAC;AAExC;;;;;;GAMG;AACH,iBAAS,kBAAkB,CAAC,GAAG,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,GAAG,GAAG,CAS7D;AAED;;;;;;GAMG;AACH,iBAAS,iBAAiB,CAAC,GAAG,EAAE,SAAS,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,GAAG,EAAE,CAEhE;AAED,iBAAS,sBAAsB,IAAI,MAAM,CAExC;;;;;;;;AAED,wBAME"}
1
+ {"version":3,"file":"helper.d.ts","sourceRoot":"","sources":["../../src/util/helper.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;GAiBG;AACH,iBAAS,YAAY,CAAC,MAAM,EAAE,GAAG,EAAE,GAAG,OAAO,EAAE,GAAG,EAAE,GAAG,GAAG,CAczD;AAED;;GAEG;AACH,iBAAS,QAAQ,CAAC,IAAI,EAAE,GAAG,GAAG,OAAO,CAEpC;AAED,KAAK,SAAS,GAAG;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;CAAE,CAAC;AAExC;;;;;;GAMG;AACH,iBAAS,kBAAkB,CAAC,GAAG,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,GAAG,GAAG,CAW7D;AAED;;;;;;GAMG;AACH,iBAAS,iBAAiB,CAAC,GAAG,EAAE,SAAS,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,GAAG,EAAE,CAEhE;AAED,iBAAS,sBAAsB,IAAI,MAAM,CAExC;;;;;;;;AAED,wBAME"}
@@ -1,42 +1,16 @@
1
1
  var __defProp = Object.defineProperty;
2
2
  var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
3
+ import lodashDefaultsDeep from "lodash.defaultsdeep";
3
4
  function defaultsDeep(target, ...sources) {
4
- if (!sources.length) return target;
5
- const source = sources.shift();
6
- if (isObject(target) && isObject(source)) {
7
- for (const key in source) {
8
- if (key === "__proto__" || key === "constructor" || key === "prototype") {
9
- continue;
10
- }
11
- if (!Object.prototype.hasOwnProperty.call(source, key)) {
12
- continue;
13
- }
14
- const sourceValue = Reflect.get(source, key);
15
- if (isObject(sourceValue)) {
16
- if (!Reflect.get(target, key)) {
17
- Reflect.set(target, key, {});
18
- }
19
- defaultsDeep(Reflect.get(target, key), sourceValue);
20
- } else if (Array.isArray(sourceValue) && Array.isArray(Reflect.get(target, key))) {
21
- const sourceArray = sourceValue;
22
- const targetArray = Reflect.get(target, key);
23
- for (let i = 0; i < sourceArray.length; i++) {
24
- if (sourceArray[i] === void 0 && targetArray[i] !== void 0) {
25
- continue;
26
- }
27
- if (isObject(sourceArray[i])) {
28
- if (typeof targetArray[i] !== "object") targetArray[i] = {};
29
- defaultsDeep(targetArray[i], sourceArray[i]);
30
- } else {
31
- targetArray[i] = sourceArray[i];
32
- }
33
- }
34
- } else if (!Object.prototype.hasOwnProperty.call(target, key)) {
35
- Reflect.set(target, key, sourceValue);
36
- }
37
- }
38
- }
39
- return defaultsDeep(target, ...sources);
5
+ const sanitizedSources = sources.map((source) => {
6
+ if (!isObject(source)) return source;
7
+ const sanitized = { ...source };
8
+ delete sanitized["__proto__"];
9
+ delete sanitized["constructor"];
10
+ delete sanitized["prototype"];
11
+ return sanitized;
12
+ });
13
+ return lodashDefaultsDeep(target, ...sanitizedSources);
40
14
  }
41
15
  __name(defaultsDeep, "defaultsDeep");
42
16
  function isObject(item) {
@@ -44,12 +18,14 @@ function isObject(item) {
44
18
  }
45
19
  __name(isObject, "isObject");
46
20
  function getValueFromObject(obj, path) {
47
- return path.split(".").reduce((acc, part) => {
48
- if (part === "__proto__" || part === "constructor" || part === "prototype") {
49
- return void 0;
50
- }
51
- return acc && Object.prototype.hasOwnProperty.call(acc, part) ? Reflect.get(acc, part) : void 0;
52
- }, obj);
21
+ const parts = path.split(".");
22
+ let current = obj;
23
+ for (const part of parts) {
24
+ if (part === "__proto__" || part === "constructor" || part === "prototype") return void 0;
25
+ if (!current || !Object.prototype.hasOwnProperty.call(current, part)) return void 0;
26
+ current = current[part];
27
+ }
28
+ return current;
53
29
  }
54
30
  __name(getValueFromObject, "getValueFromObject");
55
31
  function getValueFromArray(arr, path) {
@@ -57,7 +33,7 @@ function getValueFromArray(arr, path) {
57
33
  }
58
34
  __name(getValueFromArray, "getValueFromArray");
59
35
  function getScriptFileExtension() {
60
- return process.env.NODE_ENV === "local" ? "ts" : "js";
36
+ return process.env.NODE_ENV === "development" ? "ts" : "js";
61
37
  }
62
38
  __name(getScriptFileExtension, "getScriptFileExtension");
63
39
  var helper_default = {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/util/helper.ts"],
4
- "sourcesContent": ["/**\n * Deep merge two objects safely, preventing prototype pollution.\n */\nfunction defaultsDeep(target: any, ...sources: any[]): any {\n if (!sources.length) return target;\n const source = sources.shift();\n\n if (isObject(target) && isObject(source)) {\n for (const key in source) {\n // Skip prototype pollution attempts\n if (key === '__proto__' || key === 'constructor' || key === 'prototype') {\n continue;\n }\n\n // Only process own properties to prevent prototype chain access\n if (!Object.prototype.hasOwnProperty.call(source, key)) {\n continue;\n }\n\n const sourceValue = Reflect.get(source, key);\n if (isObject(sourceValue)) {\n if (!Reflect.get(target, key)) {\n Reflect.set(target, key, {});\n }\n defaultsDeep(Reflect.get(target, key), sourceValue);\n } else if (Array.isArray(sourceValue) && Array.isArray(Reflect.get(target, key))) {\n const sourceArray = sourceValue;\n const targetArray = Reflect.get(target, key);\n for (let i = 0; i < sourceArray.length; i++) {\n if (sourceArray[i] === undefined && targetArray[i] !== undefined) {\n continue;\n }\n if (isObject(sourceArray[i])) {\n if (typeof targetArray[i] !== 'object') targetArray[i] = {};\n defaultsDeep(targetArray[i], sourceArray[i]);\n } else {\n targetArray[i] = sourceArray[i];\n }\n }\n } else if (!Object.prototype.hasOwnProperty.call(target, key)) {\n Reflect.set(target, key, sourceValue);\n }\n }\n }\n\n return defaultsDeep(target, ...sources);\n}\n\n/**\n * Check if a value is an object.\n */\nfunction isObject(item: any): boolean {\n return item && typeof item === 'object' && !Array.isArray(item);\n}\n\ntype AnyObject = { [key: string]: any };\n\n/**\n * Retrieves the value from an object using a dotted key path safely.\n *\n * @param obj - The object to retrieve the value from.\n * @param path - The dotted key path (e.g., 'user.email').\n * @returns The value at the specified key path or undefined if not found.\n */\nfunction getValueFromObject(obj: AnyObject, path: string): any {\n return path.split('.').reduce((acc, part) => {\n // Skip prototype pollution attempts\n if (part === '__proto__' || part === 'constructor' || part === 'prototype') {\n return undefined;\n }\n // Only access own properties\n return acc && Object.prototype.hasOwnProperty.call(acc, part) ? Reflect.get(acc, part) : undefined;\n }, obj);\n}\n\n/**\n * Retrieves the value from an array of objects using a dotted key path.\n *\n * @param arr - The array of objects.\n * @param path - The dotted key path (e.g., 'user.email').\n * @returns An array of values at the specified key path from each object.\n */\nfunction getValueFromArray(arr: AnyObject[], path: string): any[] {\n return arr.map(obj => getValueFromObject(obj, path));\n}\n\nfunction getScriptFileExtension(): string {\n return process.env.NODE_ENV === 'local' ? 'ts' : 'js';\n}\n\nexport default {\n defaultsDeep,\n isObject,\n getValueFromArray,\n getValueFromObject,\n getScriptFileExtension,\n};\n"],
5
- "mappings": ";;AAGA,SAAS,aAAa,WAAgB,SAAqB;AACzD,MAAI,CAAC,QAAQ,OAAQ,QAAO;AAC5B,QAAM,SAAS,QAAQ,MAAM;AAE7B,MAAI,SAAS,MAAM,KAAK,SAAS,MAAM,GAAG;AACxC,eAAW,OAAO,QAAQ;AAExB,UAAI,QAAQ,eAAe,QAAQ,iBAAiB,QAAQ,aAAa;AACvE;AAAA,MACF;AAGA,UAAI,CAAC,OAAO,UAAU,eAAe,KAAK,QAAQ,GAAG,GAAG;AACtD;AAAA,MACF;AAEA,YAAM,cAAc,QAAQ,IAAI,QAAQ,GAAG;AAC3C,UAAI,SAAS,WAAW,GAAG;AACzB,YAAI,CAAC,QAAQ,IAAI,QAAQ,GAAG,GAAG;AAC7B,kBAAQ,IAAI,QAAQ,KAAK,CAAC,CAAC;AAAA,QAC7B;AACA,qBAAa,QAAQ,IAAI,QAAQ,GAAG,GAAG,WAAW;AAAA,MACpD,WAAW,MAAM,QAAQ,WAAW,KAAK,MAAM,QAAQ,QAAQ,IAAI,QAAQ,GAAG,CAAC,GAAG;AAChF,cAAM,cAAc;AACpB,cAAM,cAAc,QAAQ,IAAI,QAAQ,GAAG;AAC3C,iBAAS,IAAI,GAAG,IAAI,YAAY,QAAQ,KAAK;AAC3C,cAAI,YAAY,CAAC,MAAM,UAAa,YAAY,CAAC,MAAM,QAAW;AAChE;AAAA,UACF;AACA,cAAI,SAAS,YAAY,CAAC,CAAC,GAAG;AAC5B,gBAAI,OAAO,YAAY,CAAC,MAAM,SAAU,aAAY,CAAC,IAAI,CAAC;AAC1D,yBAAa,YAAY,CAAC,GAAG,YAAY,CAAC,CAAC;AAAA,UAC7C,OAAO;AACL,wBAAY,CAAC,IAAI,YAAY,CAAC;AAAA,UAChC;AAAA,QACF;AAAA,MACF,WAAW,CAAC,OAAO,UAAU,eAAe,KAAK,QAAQ,GAAG,GAAG;AAC7D,gBAAQ,IAAI,QAAQ,KAAK,WAAW;AAAA,MACtC;AAAA,IACF;AAAA,EACF;AAEA,SAAO,aAAa,QAAQ,GAAG,OAAO;AACxC;AA3CS;AAgDT,SAAS,SAAS,MAAoB;AACpC,SAAO,QAAQ,OAAO,SAAS,YAAY,CAAC,MAAM,QAAQ,IAAI;AAChE;AAFS;AAaT,SAAS,mBAAmB,KAAgB,MAAmB;AAC7D,SAAO,KAAK,MAAM,GAAG,EAAE,OAAO,CAAC,KAAK,SAAS;AAE3C,QAAI,SAAS,eAAe,SAAS,iBAAiB,SAAS,aAAa;AAC1E,aAAO;AAAA,IACT;AAEA,WAAO,OAAO,OAAO,UAAU,eAAe,KAAK,KAAK,IAAI,IAAI,QAAQ,IAAI,KAAK,IAAI,IAAI;AAAA,EAC3F,GAAG,GAAG;AACR;AATS;AAkBT,SAAS,kBAAkB,KAAkB,MAAqB;AAChE,SAAO,IAAI,IAAI,SAAO,mBAAmB,KAAK,IAAI,CAAC;AACrD;AAFS;AAIT,SAAS,yBAAiC;AACxC,SAAO,QAAQ,IAAI,aAAa,UAAU,OAAO;AACnD;AAFS;AAIT,IAAO,iBAAQ;AAAA,EACb;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;",
4
+ "sourcesContent": ["import lodashDefaultsDeep from 'lodash.defaultsdeep';\n\n/**\n * Deep merge objects with defaults, preventing prototype pollution.\n *\n * This is a secure wrapper around lodash.defaultsdeep that:\n * - Sanitizes sources to remove dangerous keys (__proto__, constructor, prototype)\n * - Delegates to battle-tested lodash.defaultsdeep for merge logic\n * - Maintains backward compatibility with existing usage\n *\n * @param target - The target object to merge into\n * @param sources - Source objects providing default values\n * @returns The merged target object (mutated)\n *\n * @example\n * const userConfig = { host: 'localhost' };\n * const defaults = { host: '0.0.0.0', port: 3001 };\n * const merged = defaultsDeep(userConfig, defaults);\n * // merged = { host: 'localhost', port: 3001 }\n */\nfunction defaultsDeep(target: any, ...sources: any[]): any {\n // Sanitize sources to prevent prototype pollution\n const sanitizedSources = sources.map(source => {\n if (!isObject(source)) return source;\n\n const sanitized = { ...source };\n delete sanitized['__proto__'];\n delete sanitized['constructor'];\n delete sanitized['prototype'];\n return sanitized;\n });\n\n // Delegate to lodash.defaultsdeep with sanitized sources\n return lodashDefaultsDeep(target, ...sanitizedSources);\n}\n\n/**\n * Check if a value is an object.\n */\nfunction isObject(item: any): boolean {\n return item && typeof item === 'object' && !Array.isArray(item);\n}\n\ntype AnyObject = { [key: string]: any };\n\n/**\n * Retrieves the value from an object using a dotted key path safely.\n *\n * @param obj - The object to retrieve the value from.\n * @param path - The dotted key path (e.g., 'user.email').\n * @returns The value at the specified key path or undefined if not found.\n */\nfunction getValueFromObject(obj: AnyObject, path: string): any {\n const parts = path.split('.');\n let current: any = obj;\n for (const part of parts) {\n if (part === '__proto__' || part === 'constructor' || part === 'prototype') return undefined;\n if (!current || !Object.prototype.hasOwnProperty.call(current, part)) return undefined;\n // Access guarded by ownProperty check and blocked prototype keys\n // eslint-disable-next-line security/detect-object-injection\n current = (current as Record<string, any>)[part];\n }\n return current;\n}\n\n/**\n * Retrieves the value from an array of objects using a dotted key path.\n *\n * @param arr - The array of objects.\n * @param path - The dotted key path (e.g., 'user.email').\n * @returns An array of values at the specified key path from each object.\n */\nfunction getValueFromArray(arr: AnyObject[], path: string): any[] {\n return arr.map(obj => getValueFromObject(obj, path));\n}\n\nfunction getScriptFileExtension(): string {\n return process.env.NODE_ENV === 'development' ? 'ts' : 'js';\n}\n\nexport default {\n defaultsDeep,\n isObject,\n getValueFromArray,\n getValueFromObject,\n getScriptFileExtension,\n};\n"],
5
+ "mappings": ";;AAAA,OAAO,wBAAwB;AAoB/B,SAAS,aAAa,WAAgB,SAAqB;AAEzD,QAAM,mBAAmB,QAAQ,IAAI,YAAU;AAC7C,QAAI,CAAC,SAAS,MAAM,EAAG,QAAO;AAE9B,UAAM,YAAY,EAAE,GAAG,OAAO;AAC9B,WAAO,UAAU,WAAW;AAC5B,WAAO,UAAU,aAAa;AAC9B,WAAO,UAAU,WAAW;AAC5B,WAAO;AAAA,EACT,CAAC;AAGD,SAAO,mBAAmB,QAAQ,GAAG,gBAAgB;AACvD;AAdS;AAmBT,SAAS,SAAS,MAAoB;AACpC,SAAO,QAAQ,OAAO,SAAS,YAAY,CAAC,MAAM,QAAQ,IAAI;AAChE;AAFS;AAaT,SAAS,mBAAmB,KAAgB,MAAmB;AAC7D,QAAM,QAAQ,KAAK,MAAM,GAAG;AAC5B,MAAI,UAAe;AACnB,aAAW,QAAQ,OAAO;AACxB,QAAI,SAAS,eAAe,SAAS,iBAAiB,SAAS,YAAa,QAAO;AACnF,QAAI,CAAC,WAAW,CAAC,OAAO,UAAU,eAAe,KAAK,SAAS,IAAI,EAAG,QAAO;AAG7E,cAAW,QAAgC,IAAI;AAAA,EACjD;AACA,SAAO;AACT;AAXS;AAoBT,SAAS,kBAAkB,KAAkB,MAAqB;AAChE,SAAO,IAAI,IAAI,SAAO,mBAAmB,KAAK,IAAI,CAAC;AACrD;AAFS;AAIT,SAAS,yBAAiC;AACxC,SAAO,QAAQ,IAAI,aAAa,gBAAgB,OAAO;AACzD;AAFS;AAIT,IAAO,iBAAQ;AAAA,EACb;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;",
6
6
  "names": []
7
7
  }
@@ -1,4 +1,5 @@
1
1
  export { default as Time } from './time.js';
2
+ export { default as Timing } from './timing.js';
2
3
  export { default as File } from './file.js';
3
4
  export { default as Helper } from './helper.js';
4
5
  export { default as Image } from './image.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/util/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,WAAW,CAAC;AAC5C,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,WAAW,CAAC;AAC5C,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,OAAO,IAAI,KAAK,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,OAAO,IAAI,GAAG,EAAE,MAAM,UAAU,CAAC;AAC1C,OAAO,EAAE,OAAO,IAAI,EAAE,EAAE,MAAM,SAAS,CAAC;AACxC,OAAO,EAAE,OAAO,IAAI,GAAG,EAAE,MAAM,UAAU,CAAC;AAC1C,OAAO,EAAE,OAAO,IAAI,GAAG,EAAE,MAAM,UAAU,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/util/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,WAAW,CAAC;AAC5C,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,WAAW,CAAC;AAC5C,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,OAAO,IAAI,KAAK,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,OAAO,IAAI,GAAG,EAAE,MAAM,UAAU,CAAC;AAC1C,OAAO,EAAE,OAAO,IAAI,EAAE,EAAE,MAAM,SAAS,CAAC;AACxC,OAAO,EAAE,OAAO,IAAI,GAAG,EAAE,MAAM,UAAU,CAAC;AAC1C,OAAO,EAAE,OAAO,IAAI,GAAG,EAAE,MAAM,UAAU,CAAC"}
@@ -1,21 +1,23 @@
1
1
  import { default as default2 } from "./time.js";
2
- import { default as default3 } from "./file.js";
3
- import { default as default4 } from "./helper.js";
4
- import { default as default5 } from "./image.js";
5
- import { default as default6 } from "./loader.js";
6
- import { default as default7 } from "./num.js";
7
- import { default as default8 } from "./os.js";
8
- import { default as default9 } from "./str.js";
9
- import { default as default10 } from "./url.js";
2
+ import { default as default3 } from "./timing.js";
3
+ import { default as default4 } from "./file.js";
4
+ import { default as default5 } from "./helper.js";
5
+ import { default as default6 } from "./image.js";
6
+ import { default as default7 } from "./loader.js";
7
+ import { default as default8 } from "./num.js";
8
+ import { default as default9 } from "./os.js";
9
+ import { default as default10 } from "./str.js";
10
+ import { default as default11 } from "./url.js";
10
11
  export {
11
- default3 as File,
12
- default4 as Helper,
13
- default5 as Image,
14
- default6 as Loader,
15
- default7 as Num,
16
- default8 as OS,
17
- default9 as Str,
12
+ default4 as File,
13
+ default5 as Helper,
14
+ default6 as Image,
15
+ default7 as Loader,
16
+ default8 as Num,
17
+ default9 as OS,
18
+ default10 as Str,
18
19
  default2 as Time,
19
- default10 as URL
20
+ default3 as Timing,
21
+ default11 as URL
20
22
  };
21
23
  //# sourceMappingURL=index.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/util/index.ts"],
4
- "sourcesContent": ["export { default as Time } from './time.js';\nexport { default as File } from './file.js';\nexport { default as Helper } from './helper.js';\nexport { default as Image } from './image.js';\nexport { default as Loader } from './loader.js';\nexport { default as Num } from './num.js';\nexport { default as OS } from './os.js';\nexport { default as Str } from './str.js';\nexport { default as URL } from './url.js';\n"],
5
- "mappings": "AAAA,SAAoB,WAAXA,gBAAuB;AAChC,SAAoB,WAAXA,gBAAuB;AAChC,SAAoB,WAAXA,gBAAyB;AAClC,SAAoB,WAAXA,gBAAwB;AACjC,SAAoB,WAAXA,gBAAyB;AAClC,SAAoB,WAAXA,gBAAsB;AAC/B,SAAoB,WAAXA,gBAAqB;AAC9B,SAAoB,WAAXA,gBAAsB;AAC/B,SAAoB,WAAXA,iBAAsB;",
4
+ "sourcesContent": ["export { default as Time } from './time.js';\nexport { default as Timing } from './timing.js';\nexport { default as File } from './file.js';\nexport { default as Helper } from './helper.js';\nexport { default as Image } from './image.js';\nexport { default as Loader } from './loader.js';\nexport { default as Num } from './num.js';\nexport { default as OS } from './os.js';\nexport { default as Str } from './str.js';\nexport { default as URL } from './url.js';\n"],
5
+ "mappings": "AAAA,SAAoB,WAAXA,gBAAuB;AAChC,SAAoB,WAAXA,gBAAyB;AAClC,SAAoB,WAAXA,gBAAuB;AAChC,SAAoB,WAAXA,gBAAyB;AAClC,SAAoB,WAAXA,gBAAwB;AACjC,SAAoB,WAAXA,gBAAyB;AAClC,SAAoB,WAAXA,gBAAsB;AAC/B,SAAoB,WAAXA,gBAAqB;AAC9B,SAAoB,WAAXA,iBAAsB;AAC/B,SAAoB,WAAXA,iBAAsB;",
6
6
  "names": ["default"]
7
7
  }
@@ -1 +1 @@
1
- {"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/util/loader.ts"],"names":[],"mappings":";yDAWG;QACD,SAAS,EAAE,MAAM,CAAC;QAClB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;KACvB,KAAG,OAAO,CAAC;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;KAAE,CAAC;2DAwDhC;QACD,iBAAiB,EAAE,MAAM,CAAC;QAC1B,UAAU,EAAE,MAAM,CAAC;KACpB,KAAG,OAAO,CAAC,GAAG,CAAC;4BAkCa,IAAI;yBAKP;QAAE,aAAa,EAAE,MAAM,CAAC;QAAC,cAAc,EAAE,MAAM,CAAA;KAAE;;AAO3E,wBAKE"}
1
+ {"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/util/loader.ts"],"names":[],"mappings":";yDAoBG;QACD,SAAS,EAAE,MAAM,CAAC;QAClB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;KACvB,KAAG,OAAO,CAAC;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;KAAE,CAAC;2DAwDhC;QACD,iBAAiB,EAAE,MAAM,CAAC;QAC1B,UAAU,EAAE,MAAM,CAAC;KACpB,KAAG,OAAO,CAAC,GAAG,CAAC;4BAkCa,IAAI;yBAKP;QAAE,aAAa,EAAE,MAAM,CAAC;QAAC,cAAc,EAAE,MAAM,CAAA;KAAE;;AAO3E,wBAKE"}
@@ -2,9 +2,20 @@ var __defProp = Object.defineProperty;
2
2
  var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
3
3
  import fs from "fs";
4
4
  import path from "path";
5
+ import { LRUCache } from "lru-cache";
5
6
  import { Helper } from "./index.js";
6
- const moduleCache = /* @__PURE__ */ new Map();
7
- const entityCache = /* @__PURE__ */ new Map();
7
+ const moduleCache = new LRUCache({
8
+ max: 100,
9
+ // Max 100 directories cached
10
+ ttl: 1e3 * 60 * 10
11
+ // 10 minutes
12
+ });
13
+ const entityCache = new LRUCache({
14
+ max: 500,
15
+ // Max 500 entities cached (accessed more frequently than modules)
16
+ ttl: 1e3 * 60 * 10
17
+ // 10 minutes
18
+ });
8
19
  const loadModulesInDirectory = /* @__PURE__ */ __name(async ({
9
20
  directory,
10
21
  extensions
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/util/loader.ts"],
4
- "sourcesContent": ["import fs from 'fs';\nimport path from 'path';\nimport { Helper } from './index.js';\n\n// Cache for loaded modules to avoid repeated imports\nconst moduleCache = new Map<string, { [key: string]: any }>();\nconst entityCache = new Map<string, any>();\n\nconst loadModulesInDirectory = async ({\n directory,\n extensions,\n}: {\n directory: string;\n extensions?: string[];\n}): Promise<{ [key: string]: any }> => {\n // Create cache key based on directory and extensions\n const cacheKey = `${directory}:${extensions?.join(',') ?? 'all'}`;\n\n // Check cache first\n if (moduleCache.has(cacheKey)) {\n const cachedModule = moduleCache.get(cacheKey);\n if (cachedModule) {\n return cachedModule;\n }\n }\n\n const loadedModules: { [key: string]: any } = {};\n\n // Use readdir with withFileTypes option to avoid separate stat calls\n const dirents = await fs.promises.readdir(directory, { withFileTypes: true });\n\n for (const dirent of dirents) {\n // Skip directories without needing stat call\n if (dirent.isDirectory()) {\n continue;\n }\n\n const file = dirent.name;\n const ext = path.extname(file);\n const isDeclarationFile = file.endsWith('.d.ts');\n\n // Skip files that are not in the specified extensions or are .d.ts files\n if ((extensions && extensions.length > 0 && !extensions.includes(ext)) || isDeclarationFile) {\n continue;\n }\n\n const moduleName = path.basename(file, ext);\n const filePath = path.join(directory, file);\n\n try {\n const importedModule = await import(filePath);\n\n // Use safe property assignment to prevent prototype pollution\n if (moduleName !== '__proto__' && moduleName !== 'constructor' && moduleName !== 'prototype') {\n Reflect.set(loadedModules, moduleName, importedModule.default);\n }\n } catch (error) {\n console.error(`Failed to import module ${filePath}:`, error);\n }\n }\n\n // Cache the results for future use\n moduleCache.set(cacheKey, loadedModules);\n\n return loadedModules;\n};\n\nconst loadEntityModule = async ({\n entitiesDirectory,\n entityName,\n}: {\n entitiesDirectory: string;\n entityName: string;\n}): Promise<any> => {\n // Create cache key based on directory and entity name\n const cacheKey = `${entitiesDirectory}:${entityName}`;\n\n // Check cache first\n if (entityCache.has(cacheKey)) {\n return entityCache.get(cacheKey);\n }\n\n // Define entity module path\n const entityModulePath = path.join(entitiesDirectory, `${entityName}.${Helper.getScriptFileExtension()}`);\n\n // Import entity module\n const entityModule = await import(entityModulePath);\n\n // Safe property access to prevent prototype pollution\n if (entityName === '__proto__' || entityName === 'constructor' || entityName === 'prototype') {\n throw new Error(`Invalid entity name (Entity: ${entityName})`);\n }\n\n if (!entityModule || !Object.prototype.hasOwnProperty.call(entityModule, entityName)) {\n throw new Error(`Entity not found (Entity: ${entityName})`);\n }\n\n // Get entity class\n const EntityClass = Reflect.get(entityModule, entityName);\n\n // Cache the entity for future use\n entityCache.set(cacheKey, EntityClass);\n\n return EntityClass;\n};\n\n// Cache management functions for development/testing\nconst clearModuleCache = (): void => {\n moduleCache.clear();\n entityCache.clear();\n};\n\nconst getCacheStats = (): { modulesCached: number; entitiesCached: number } => {\n return {\n modulesCached: moduleCache.size,\n entitiesCached: entityCache.size,\n };\n};\n\nexport default {\n loadModulesInDirectory,\n loadEntityModule,\n clearModuleCache,\n getCacheStats,\n};\n"],
5
- "mappings": ";;AAAA,OAAO,QAAQ;AACf,OAAO,UAAU;AACjB,SAAS,cAAc;AAGvB,MAAM,cAAc,oBAAI,IAAoC;AAC5D,MAAM,cAAc,oBAAI,IAAiB;AAEzC,MAAM,yBAAyB,8BAAO;AAAA,EACpC;AAAA,EACA;AACF,MAGuC;AAErC,QAAM,WAAW,GAAG,SAAS,IAAI,YAAY,KAAK,GAAG,KAAK,KAAK;AAG/D,MAAI,YAAY,IAAI,QAAQ,GAAG;AAC7B,UAAM,eAAe,YAAY,IAAI,QAAQ;AAC7C,QAAI,cAAc;AAChB,aAAO;AAAA,IACT;AAAA,EACF;AAEA,QAAM,gBAAwC,CAAC;AAG/C,QAAM,UAAU,MAAM,GAAG,SAAS,QAAQ,WAAW,EAAE,eAAe,KAAK,CAAC;AAE5E,aAAW,UAAU,SAAS;AAE5B,QAAI,OAAO,YAAY,GAAG;AACxB;AAAA,IACF;AAEA,UAAM,OAAO,OAAO;AACpB,UAAM,MAAM,KAAK,QAAQ,IAAI;AAC7B,UAAM,oBAAoB,KAAK,SAAS,OAAO;AAG/C,QAAK,cAAc,WAAW,SAAS,KAAK,CAAC,WAAW,SAAS,GAAG,KAAM,mBAAmB;AAC3F;AAAA,IACF;AAEA,UAAM,aAAa,KAAK,SAAS,MAAM,GAAG;AAC1C,UAAM,WAAW,KAAK,KAAK,WAAW,IAAI;AAE1C,QAAI;AACF,YAAM,iBAAiB,MAAM,OAAO;AAGpC,UAAI,eAAe,eAAe,eAAe,iBAAiB,eAAe,aAAa;AAC5F,gBAAQ,IAAI,eAAe,YAAY,eAAe,OAAO;AAAA,MAC/D;AAAA,IACF,SAAS,OAAO;AACd,cAAQ,MAAM,2BAA2B,QAAQ,KAAK,KAAK;AAAA,IAC7D;AAAA,EACF;AAGA,cAAY,IAAI,UAAU,aAAa;AAEvC,SAAO;AACT,GAzD+B;AA2D/B,MAAM,mBAAmB,8BAAO;AAAA,EAC9B;AAAA,EACA;AACF,MAGoB;AAElB,QAAM,WAAW,GAAG,iBAAiB,IAAI,UAAU;AAGnD,MAAI,YAAY,IAAI,QAAQ,GAAG;AAC7B,WAAO,YAAY,IAAI,QAAQ;AAAA,EACjC;AAGA,QAAM,mBAAmB,KAAK,KAAK,mBAAmB,GAAG,UAAU,IAAI,OAAO,uBAAuB,CAAC,EAAE;AAGxG,QAAM,eAAe,MAAM,OAAO;AAGlC,MAAI,eAAe,eAAe,eAAe,iBAAiB,eAAe,aAAa;AAC5F,UAAM,IAAI,MAAM,gCAAgC,UAAU,GAAG;AAAA,EAC/D;AAEA,MAAI,CAAC,gBAAgB,CAAC,OAAO,UAAU,eAAe,KAAK,cAAc,UAAU,GAAG;AACpF,UAAM,IAAI,MAAM,6BAA6B,UAAU,GAAG;AAAA,EAC5D;AAGA,QAAM,cAAc,QAAQ,IAAI,cAAc,UAAU;AAGxD,cAAY,IAAI,UAAU,WAAW;AAErC,SAAO;AACT,GArCyB;AAwCzB,MAAM,mBAAmB,6BAAY;AACnC,cAAY,MAAM;AAClB,cAAY,MAAM;AACpB,GAHyB;AAKzB,MAAM,gBAAgB,6BAAyD;AAC7E,SAAO;AAAA,IACL,eAAe,YAAY;AAAA,IAC3B,gBAAgB,YAAY;AAAA,EAC9B;AACF,GALsB;AAOtB,IAAO,iBAAQ;AAAA,EACb;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;",
4
+ "sourcesContent": ["import fs from 'fs';\nimport path from 'path';\nimport { LRUCache } from 'lru-cache';\nimport { Helper } from './index.js';\n\n// Cache for loaded modules to avoid repeated imports\n// Using LRU cache to prevent unbounded memory growth in long-running processes\nconst moduleCache = new LRUCache<string, { [key: string]: any }>({\n max: 100, // Max 100 directories cached\n ttl: 1000 * 60 * 10, // 10 minutes\n});\n\nconst entityCache = new LRUCache<string, any>({\n max: 500, // Max 500 entities cached (accessed more frequently than modules)\n ttl: 1000 * 60 * 10, // 10 minutes\n});\n\nconst loadModulesInDirectory = async ({\n directory,\n extensions,\n}: {\n directory: string;\n extensions?: string[];\n}): Promise<{ [key: string]: any }> => {\n // Create cache key based on directory and extensions\n const cacheKey = `${directory}:${extensions?.join(',') ?? 'all'}`;\n\n // Check cache first\n if (moduleCache.has(cacheKey)) {\n const cachedModule = moduleCache.get(cacheKey);\n if (cachedModule) {\n return cachedModule;\n }\n }\n\n const loadedModules: { [key: string]: any } = {};\n\n // Use readdir with withFileTypes option to avoid separate stat calls\n const dirents = await fs.promises.readdir(directory, { withFileTypes: true });\n\n for (const dirent of dirents) {\n // Skip directories without needing stat call\n if (dirent.isDirectory()) {\n continue;\n }\n\n const file = dirent.name;\n const ext = path.extname(file);\n const isDeclarationFile = file.endsWith('.d.ts');\n\n // Skip files that are not in the specified extensions or are .d.ts files\n if ((extensions && extensions.length > 0 && !extensions.includes(ext)) || isDeclarationFile) {\n continue;\n }\n\n const moduleName = path.basename(file, ext);\n const filePath = path.join(directory, file);\n\n try {\n const importedModule = await import(filePath);\n\n // Use safe property assignment to prevent prototype pollution\n if (moduleName !== '__proto__' && moduleName !== 'constructor' && moduleName !== 'prototype') {\n Reflect.set(loadedModules, moduleName, importedModule.default);\n }\n } catch (error) {\n console.error(`Failed to import module ${filePath}:`, error);\n }\n }\n\n // Cache the results for future use\n moduleCache.set(cacheKey, loadedModules);\n\n return loadedModules;\n};\n\nconst loadEntityModule = async ({\n entitiesDirectory,\n entityName,\n}: {\n entitiesDirectory: string;\n entityName: string;\n}): Promise<any> => {\n // Create cache key based on directory and entity name\n const cacheKey = `${entitiesDirectory}:${entityName}`;\n\n // Check cache first\n if (entityCache.has(cacheKey)) {\n return entityCache.get(cacheKey);\n }\n\n // Define entity module path\n const entityModulePath = path.join(entitiesDirectory, `${entityName}.${Helper.getScriptFileExtension()}`);\n\n // Import entity module\n const entityModule = await import(entityModulePath);\n\n // Safe property access to prevent prototype pollution\n if (entityName === '__proto__' || entityName === 'constructor' || entityName === 'prototype') {\n throw new Error(`Invalid entity name (Entity: ${entityName})`);\n }\n\n if (!entityModule || !Object.prototype.hasOwnProperty.call(entityModule, entityName)) {\n throw new Error(`Entity not found (Entity: ${entityName})`);\n }\n\n // Get entity class\n const EntityClass = Reflect.get(entityModule, entityName);\n\n // Cache the entity for future use\n entityCache.set(cacheKey, EntityClass);\n\n return EntityClass;\n};\n\n// Cache management functions for development/testing\nconst clearModuleCache = (): void => {\n moduleCache.clear();\n entityCache.clear();\n};\n\nconst getCacheStats = (): { modulesCached: number; entitiesCached: number } => {\n return {\n modulesCached: moduleCache.size,\n entitiesCached: entityCache.size,\n };\n};\n\nexport default {\n loadModulesInDirectory,\n loadEntityModule,\n clearModuleCache,\n getCacheStats,\n};\n"],
5
+ "mappings": ";;AAAA,OAAO,QAAQ;AACf,OAAO,UAAU;AACjB,SAAS,gBAAgB;AACzB,SAAS,cAAc;AAIvB,MAAM,cAAc,IAAI,SAAyC;AAAA,EAC/D,KAAK;AAAA;AAAA,EACL,KAAK,MAAO,KAAK;AAAA;AACnB,CAAC;AAED,MAAM,cAAc,IAAI,SAAsB;AAAA,EAC5C,KAAK;AAAA;AAAA,EACL,KAAK,MAAO,KAAK;AAAA;AACnB,CAAC;AAED,MAAM,yBAAyB,8BAAO;AAAA,EACpC;AAAA,EACA;AACF,MAGuC;AAErC,QAAM,WAAW,GAAG,SAAS,IAAI,YAAY,KAAK,GAAG,KAAK,KAAK;AAG/D,MAAI,YAAY,IAAI,QAAQ,GAAG;AAC7B,UAAM,eAAe,YAAY,IAAI,QAAQ;AAC7C,QAAI,cAAc;AAChB,aAAO;AAAA,IACT;AAAA,EACF;AAEA,QAAM,gBAAwC,CAAC;AAG/C,QAAM,UAAU,MAAM,GAAG,SAAS,QAAQ,WAAW,EAAE,eAAe,KAAK,CAAC;AAE5E,aAAW,UAAU,SAAS;AAE5B,QAAI,OAAO,YAAY,GAAG;AACxB;AAAA,IACF;AAEA,UAAM,OAAO,OAAO;AACpB,UAAM,MAAM,KAAK,QAAQ,IAAI;AAC7B,UAAM,oBAAoB,KAAK,SAAS,OAAO;AAG/C,QAAK,cAAc,WAAW,SAAS,KAAK,CAAC,WAAW,SAAS,GAAG,KAAM,mBAAmB;AAC3F;AAAA,IACF;AAEA,UAAM,aAAa,KAAK,SAAS,MAAM,GAAG;AAC1C,UAAM,WAAW,KAAK,KAAK,WAAW,IAAI;AAE1C,QAAI;AACF,YAAM,iBAAiB,MAAM,OAAO;AAGpC,UAAI,eAAe,eAAe,eAAe,iBAAiB,eAAe,aAAa;AAC5F,gBAAQ,IAAI,eAAe,YAAY,eAAe,OAAO;AAAA,MAC/D;AAAA,IACF,SAAS,OAAO;AACd,cAAQ,MAAM,2BAA2B,QAAQ,KAAK,KAAK;AAAA,IAC7D;AAAA,EACF;AAGA,cAAY,IAAI,UAAU,aAAa;AAEvC,SAAO;AACT,GAzD+B;AA2D/B,MAAM,mBAAmB,8BAAO;AAAA,EAC9B;AAAA,EACA;AACF,MAGoB;AAElB,QAAM,WAAW,GAAG,iBAAiB,IAAI,UAAU;AAGnD,MAAI,YAAY,IAAI,QAAQ,GAAG;AAC7B,WAAO,YAAY,IAAI,QAAQ;AAAA,EACjC;AAGA,QAAM,mBAAmB,KAAK,KAAK,mBAAmB,GAAG,UAAU,IAAI,OAAO,uBAAuB,CAAC,EAAE;AAGxG,QAAM,eAAe,MAAM,OAAO;AAGlC,MAAI,eAAe,eAAe,eAAe,iBAAiB,eAAe,aAAa;AAC5F,UAAM,IAAI,MAAM,gCAAgC,UAAU,GAAG;AAAA,EAC/D;AAEA,MAAI,CAAC,gBAAgB,CAAC,OAAO,UAAU,eAAe,KAAK,cAAc,UAAU,GAAG;AACpF,UAAM,IAAI,MAAM,6BAA6B,UAAU,GAAG;AAAA,EAC5D;AAGA,QAAM,cAAc,QAAQ,IAAI,cAAc,UAAU;AAGxD,cAAY,IAAI,UAAU,WAAW;AAErC,SAAO;AACT,GArCyB;AAwCzB,MAAM,mBAAmB,6BAAY;AACnC,cAAY,MAAM;AAClB,cAAY,MAAM;AACpB,GAHyB;AAKzB,MAAM,gBAAgB,6BAAyD;AAC7E,SAAO;AAAA,IACL,eAAe,YAAY;AAAA,IAC3B,gBAAgB,YAAY;AAAA,EAC9B;AACF,GALsB;AAOtB,IAAO,iBAAQ;AAAA,EACb;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;",
6
6
  "names": []
7
7
  }
@@ -1 +1 @@
1
- {"version":3,"file":"os.d.ts","sourceRoot":"","sources":["../../src/util/os.ts"],"names":[],"mappings":"AAGA,iBAAS,mBAAmB,IAAI,MAAM,CA0BrC;;;;AAED,wBAEE"}
1
+ {"version":3,"file":"os.d.ts","sourceRoot":"","sources":["../../src/util/os.ts"],"names":[],"mappings":"AAGA,iBAAS,mBAAmB,IAAI,MAAM,CAarC;;;;AAED,wBAEE"}
package/dist/util/os.js CHANGED
@@ -3,24 +3,18 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
3
3
  import os from "os";
4
4
  import crypto from "crypto";
5
5
  function getUniqueComputerId() {
6
- const networkInterfaces = os.networkInterfaces();
6
+ const interfaces = Object.values(os.networkInterfaces()).filter(Boolean);
7
7
  let macAddress = "";
8
- for (const key in networkInterfaces) {
9
- const networkInterface = networkInterfaces[key];
10
- if (networkInterface) {
11
- for (const interfaceDetails of networkInterface) {
12
- if (interfaceDetails.mac) {
13
- macAddress = interfaceDetails.mac;
14
- break;
15
- }
8
+ for (const ifaceList of interfaces) {
9
+ for (const details of ifaceList) {
10
+ if (details.mac) {
11
+ macAddress = details.mac;
12
+ break;
16
13
  }
17
14
  }
18
- if (macAddress) {
19
- break;
20
- }
15
+ if (macAddress) break;
21
16
  }
22
- const uniqueComputerId = crypto.createHash("sha256").update(macAddress).digest("hex");
23
- return uniqueComputerId;
17
+ return crypto.createHash("sha256").update(macAddress).digest("hex");
24
18
  }
25
19
  __name(getUniqueComputerId, "getUniqueComputerId");
26
20
  var os_default = {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/util/os.ts"],
4
- "sourcesContent": ["import os from 'os';\nimport crypto from 'crypto';\n\nfunction getUniqueComputerId(): string {\n const networkInterfaces = os.networkInterfaces();\n\n let macAddress = '';\n\n for (const key in networkInterfaces) {\n const networkInterface = networkInterfaces[key];\n\n if (networkInterface) {\n for (const interfaceDetails of networkInterface) {\n if (interfaceDetails.mac) {\n macAddress = interfaceDetails.mac;\n\n break;\n }\n }\n }\n\n if (macAddress) {\n break;\n }\n }\n\n const uniqueComputerId = crypto.createHash('sha256').update(macAddress).digest('hex');\n\n return uniqueComputerId;\n}\n\nexport default {\n getUniqueComputerId,\n};\n"],
5
- "mappings": ";;AAAA,OAAO,QAAQ;AACf,OAAO,YAAY;AAEnB,SAAS,sBAA8B;AACrC,QAAM,oBAAoB,GAAG,kBAAkB;AAE/C,MAAI,aAAa;AAEjB,aAAW,OAAO,mBAAmB;AACnC,UAAM,mBAAmB,kBAAkB,GAAG;AAE9C,QAAI,kBAAkB;AACpB,iBAAW,oBAAoB,kBAAkB;AAC/C,YAAI,iBAAiB,KAAK;AACxB,uBAAa,iBAAiB;AAE9B;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,QAAI,YAAY;AACd;AAAA,IACF;AAAA,EACF;AAEA,QAAM,mBAAmB,OAAO,WAAW,QAAQ,EAAE,OAAO,UAAU,EAAE,OAAO,KAAK;AAEpF,SAAO;AACT;AA1BS;AA4BT,IAAO,aAAQ;AAAA,EACb;AACF;",
4
+ "sourcesContent": ["import os from 'os';\nimport crypto from 'crypto';\n\nfunction getUniqueComputerId(): string {\n const interfaces = Object.values(os.networkInterfaces()).filter(Boolean) as os.NetworkInterfaceInfo[][];\n let macAddress = '';\n for (const ifaceList of interfaces) {\n for (const details of ifaceList) {\n if (details.mac) {\n macAddress = details.mac;\n break;\n }\n }\n if (macAddress) break;\n }\n return crypto.createHash('sha256').update(macAddress).digest('hex');\n}\n\nexport default {\n getUniqueComputerId,\n};\n"],
5
+ "mappings": ";;AAAA,OAAO,QAAQ;AACf,OAAO,YAAY;AAEnB,SAAS,sBAA8B;AACrC,QAAM,aAAa,OAAO,OAAO,GAAG,kBAAkB,CAAC,EAAE,OAAO,OAAO;AACvE,MAAI,aAAa;AACjB,aAAW,aAAa,YAAY;AAClC,eAAW,WAAW,WAAW;AAC/B,UAAI,QAAQ,KAAK;AACf,qBAAa,QAAQ;AACrB;AAAA,MACF;AAAA,IACF;AACA,QAAI,WAAY;AAAA,EAClB;AACA,SAAO,OAAO,WAAW,QAAQ,EAAE,OAAO,UAAU,EAAE,OAAO,KAAK;AACpE;AAbS;AAeT,IAAO,aAAQ;AAAA,EACb;AACF;",
6
6
  "names": []
7
7
  }
@@ -1,13 +1,19 @@
1
1
  import type { FormatRelativeTimeOptions, FormatTimeOptions } from './time.interface.js';
2
+ import Timing from './timing.js';
2
3
  declare const _default: {
3
- calculateElapsedTime: ({ startTime }: {
4
- startTime: [number, number];
4
+ calculateElapsedTimeMs: ({ startTime }: {
5
+ startTime: number;
5
6
  }) => number;
6
7
  formatTime: ({ time, format, numDecimals, showUnit }: FormatTimeOptions) => string;
7
8
  formatRelativeTime: ({ date, baseDate, includeSeconds, }: FormatRelativeTimeOptions) => string;
8
9
  sleep: ({ seconds }: {
9
10
  seconds: number;
10
11
  }) => Promise<void>;
12
+ now: typeof Timing.now;
13
+ start: typeof Timing.start;
14
+ measure: typeof Timing.measure;
15
+ measureSync: typeof Timing.measureSync;
16
+ duration: typeof Timing.duration;
11
17
  };
12
18
  export default _default;
13
19
  //# sourceMappingURL=time.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"time.d.ts","sourceRoot":"","sources":["../../src/util/time.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,yBAAyB,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;;0CAK3C;QAAE,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KAAE,KAAG,MAAM;0DAUJ,iBAAiB,KAAG,MAAM;8DA4CxG,yBAAyB,KAAG,MAAM;yBAbT;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,KAAG,OAAO,CAAC,IAAI,CAAC;;AA6D/D,wBAKE"}
1
+ {"version":3,"file":"time.d.ts","sourceRoot":"","sources":["../../src/util/time.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,yBAAyB,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxF,OAAO,MAAM,MAAM,aAAa,CAAC;;4CAMc;QAAE,SAAS,EAAE,MAAM,CAAA;KAAE,KAAG,MAAM;0DAOI,iBAAiB,KAAG,MAAM;8DA4CxG,yBAAyB,KAAG,MAAM;yBAbT;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,KAAG,OAAO,CAAC,IAAI,CAAC;;;;;;;AA6D/D,wBAWE"}
package/dist/util/time.js CHANGED
@@ -1,10 +1,9 @@
1
1
  var __defProp = Object.defineProperty;
2
2
  var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
3
- const calculateElapsedTime = /* @__PURE__ */ __name(({ startTime }) => {
4
- const endTime = process.hrtime(startTime);
5
- const elapsedTime = (endTime[0] * 1e9 + endTime[1]) / 1e6;
6
- return elapsedTime;
7
- }, "calculateElapsedTime");
3
+ import Timing from "./timing.js";
4
+ const calculateElapsedTimeMs = /* @__PURE__ */ __name(({ startTime }) => {
5
+ return performance.now() - startTime;
6
+ }, "calculateElapsedTimeMs");
8
7
  const formatTime = /* @__PURE__ */ __name(({ time, format = "auto", numDecimals = 0, showUnit = true }) => {
9
8
  let formattedTime;
10
9
  let formattedTimeText;
@@ -79,10 +78,16 @@ const formatRelativeTime = /* @__PURE__ */ __name(({
79
78
  return `${value} ${unit} ago`;
80
79
  }, "formatRelativeTime");
81
80
  var time_default = {
82
- calculateElapsedTime,
81
+ calculateElapsedTimeMs,
83
82
  formatTime,
84
83
  formatRelativeTime,
85
- sleep
84
+ sleep,
85
+ // Modern timing utilities
86
+ now: Timing.now,
87
+ start: Timing.start,
88
+ measure: Timing.measure,
89
+ measureSync: Timing.measureSync,
90
+ duration: Timing.duration
86
91
  };
87
92
  export {
88
93
  time_default as default
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/util/time.ts"],
4
- "sourcesContent": ["import type { FormatRelativeTimeOptions, FormatTimeOptions } from './time.interface.js';\n\n/**\n * Calculate elapsed time in milliseconds.\n */\nconst calculateElapsedTime = ({ startTime }: { startTime: [number, number] }): number => {\n const endTime = process.hrtime(startTime);\n const elapsedTime = (endTime[0] * 1e9 + endTime[1]) / 1e6;\n\n return elapsedTime;\n};\n\n/**\n * Format time.\n */\nconst formatTime = ({ time, format = 'auto', numDecimals = 0, showUnit = true }: FormatTimeOptions): string => {\n let formattedTime: number;\n let formattedTimeText: string;\n\n if (format === 's' || (format === 'auto' && time < 60000)) {\n formattedTime = time / 1000;\n formattedTimeText = formattedTime.toFixed(numDecimals);\n format = 's'; // Ensure the unit is correctly displayed\n } else if (format === 'hh:mm:ss' || (format === 'auto' && time >= 60000)) {\n const totalSeconds = Math.floor(time / 1000);\n const hours = Math.floor(totalSeconds / 3600);\n const minutes = Math.floor((totalSeconds % 3600) / 60);\n const seconds = totalSeconds % 60;\n\n formattedTimeText = `${String(hours).padStart(2, '0')}:${String(minutes).padStart(2, '0')}:${String(seconds).padStart(2, '0')}`;\n\n return formattedTimeText; // No need to append unit for 'hh:mm:ss'\n } else {\n formattedTime = time;\n formattedTimeText = formattedTime.toFixed(numDecimals);\n format = 'ms'; // Ensure the unit is correctly displayed\n }\n\n const unit = format === 'ms' || format === 's' ? format : '';\n\n return showUnit ? `${formattedTimeText}${unit}` : formattedTimeText;\n};\n\n/**\n * Sleep for a specified number of seconds.\n */\nconst sleep = ({ seconds }: { seconds: number }): Promise<void> => {\n return new Promise(resolve => {\n setTimeout(resolve, seconds * 1000);\n });\n};\n\n/**\n * Format a date as relative time (e.g., \"in 3 minutes\", \"2 hours ago\").\n */\nconst formatRelativeTime = ({\n date,\n baseDate = new Date(),\n includeSeconds = false,\n}: FormatRelativeTimeOptions): string => {\n const diffInMs = date.getTime() - baseDate.getTime();\n const diffInSeconds = Math.abs(Math.floor(diffInMs / 1000));\n const isFuture = diffInMs > 0;\n\n // Time units in seconds\n const minute = 60;\n const hour = minute * 60;\n const day = hour * 24;\n const week = day * 7;\n const month = day * 30; // Approximate\n const year = day * 365; // Approximate\n\n let value: number;\n let unit: string;\n\n if (diffInSeconds < minute) {\n if (!includeSeconds && diffInSeconds < 60) {\n return 'just now';\n }\n value = diffInSeconds;\n unit = value === 1 ? 'second' : 'seconds';\n } else if (diffInSeconds < hour) {\n value = Math.floor(diffInSeconds / minute);\n unit = value === 1 ? 'minute' : 'minutes';\n } else if (diffInSeconds < day) {\n value = Math.floor(diffInSeconds / hour);\n unit = value === 1 ? 'hour' : 'hours';\n } else if (diffInSeconds < week) {\n value = Math.floor(diffInSeconds / day);\n unit = value === 1 ? 'day' : 'days';\n } else if (diffInSeconds < month) {\n value = Math.floor(diffInSeconds / week);\n unit = value === 1 ? 'week' : 'weeks';\n } else if (diffInSeconds < year) {\n value = Math.floor(diffInSeconds / month);\n unit = value === 1 ? 'month' : 'months';\n } else {\n value = Math.floor(diffInSeconds / year);\n unit = value === 1 ? 'year' : 'years';\n }\n\n if (isFuture) {\n return `in ${value} ${unit}`;\n }\n return `${value} ${unit} ago`;\n};\n\nexport default {\n calculateElapsedTime,\n formatTime,\n formatRelativeTime,\n sleep,\n};\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import type { FormatRelativeTimeOptions, FormatTimeOptions } from './time.interface.js';\nimport Timing from './timing.js';\n\n/**\n * Calculate elapsed time in milliseconds using performance.now().\n * More accurate and simpler than hrtime-based timing.\n */\nconst calculateElapsedTimeMs = ({ startTime }: { startTime: number }): number => {\n return performance.now() - startTime;\n};\n\n/**\n * Format time.\n */\nconst formatTime = ({ time, format = 'auto', numDecimals = 0, showUnit = true }: FormatTimeOptions): string => {\n let formattedTime: number;\n let formattedTimeText: string;\n\n if (format === 's' || (format === 'auto' && time < 60000)) {\n formattedTime = time / 1000;\n formattedTimeText = formattedTime.toFixed(numDecimals);\n format = 's'; // Ensure the unit is correctly displayed\n } else if (format === 'hh:mm:ss' || (format === 'auto' && time >= 60000)) {\n const totalSeconds = Math.floor(time / 1000);\n const hours = Math.floor(totalSeconds / 3600);\n const minutes = Math.floor((totalSeconds % 3600) / 60);\n const seconds = totalSeconds % 60;\n\n formattedTimeText = `${String(hours).padStart(2, '0')}:${String(minutes).padStart(2, '0')}:${String(seconds).padStart(2, '0')}`;\n\n return formattedTimeText; // No need to append unit for 'hh:mm:ss'\n } else {\n formattedTime = time;\n formattedTimeText = formattedTime.toFixed(numDecimals);\n format = 'ms'; // Ensure the unit is correctly displayed\n }\n\n const unit = format === 'ms' || format === 's' ? format : '';\n\n return showUnit ? `${formattedTimeText}${unit}` : formattedTimeText;\n};\n\n/**\n * Sleep for a specified number of seconds.\n */\nconst sleep = ({ seconds }: { seconds: number }): Promise<void> => {\n return new Promise(resolve => {\n setTimeout(resolve, seconds * 1000);\n });\n};\n\n/**\n * Format a date as relative time (e.g., \"in 3 minutes\", \"2 hours ago\").\n */\nconst formatRelativeTime = ({\n date,\n baseDate = new Date(),\n includeSeconds = false,\n}: FormatRelativeTimeOptions): string => {\n const diffInMs = date.getTime() - baseDate.getTime();\n const diffInSeconds = Math.abs(Math.floor(diffInMs / 1000));\n const isFuture = diffInMs > 0;\n\n // Time units in seconds\n const minute = 60;\n const hour = minute * 60;\n const day = hour * 24;\n const week = day * 7;\n const month = day * 30; // Approximate\n const year = day * 365; // Approximate\n\n let value: number;\n let unit: string;\n\n if (diffInSeconds < minute) {\n if (!includeSeconds && diffInSeconds < 60) {\n return 'just now';\n }\n value = diffInSeconds;\n unit = value === 1 ? 'second' : 'seconds';\n } else if (diffInSeconds < hour) {\n value = Math.floor(diffInSeconds / minute);\n unit = value === 1 ? 'minute' : 'minutes';\n } else if (diffInSeconds < day) {\n value = Math.floor(diffInSeconds / hour);\n unit = value === 1 ? 'hour' : 'hours';\n } else if (diffInSeconds < week) {\n value = Math.floor(diffInSeconds / day);\n unit = value === 1 ? 'day' : 'days';\n } else if (diffInSeconds < month) {\n value = Math.floor(diffInSeconds / week);\n unit = value === 1 ? 'week' : 'weeks';\n } else if (diffInSeconds < year) {\n value = Math.floor(diffInSeconds / month);\n unit = value === 1 ? 'month' : 'months';\n } else {\n value = Math.floor(diffInSeconds / year);\n unit = value === 1 ? 'year' : 'years';\n }\n\n if (isFuture) {\n return `in ${value} ${unit}`;\n }\n return `${value} ${unit} ago`;\n};\n\nexport default {\n calculateElapsedTimeMs,\n formatTime,\n formatRelativeTime,\n sleep,\n // Modern timing utilities\n now: Timing.now,\n start: Timing.start,\n measure: Timing.measure,\n measureSync: Timing.measureSync,\n duration: Timing.duration,\n};\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -0,0 +1,36 @@
1
+ import type { MeasureOptions, Timer, TimingResult } from './timing.interface.js';
2
+ /**
3
+ * Modern high-resolution timing utility using performance.now()
4
+ *
5
+ * Provides simple APIs for measuring function execution time and manual timing.
6
+ * All durations are returned in milliseconds with decimal precision.
7
+ */
8
+ declare class Timing {
9
+ /**
10
+ * Get current high-resolution timestamp in milliseconds.
11
+ * Uses performance.now() which provides sub-millisecond precision.
12
+ */
13
+ static now(): number;
14
+ /**
15
+ * Start a timer and return a Timer instance.
16
+ * Call timer.stop() to get elapsed time in milliseconds.
17
+ */
18
+ static start(): Timer;
19
+ /**
20
+ * Measure the execution time of a function (async or sync).
21
+ * Returns both the function result and timing information.
22
+ */
23
+ static measure<T>(fn: () => T | Promise<T>, options?: MeasureOptions): Promise<TimingResult<T>>;
24
+ /**
25
+ * Measure the execution time of a synchronous function.
26
+ * Returns both the function result and timing information.
27
+ */
28
+ static measureSync<T>(fn: () => T, options?: MeasureOptions): TimingResult<T>;
29
+ /**
30
+ * Calculate duration between two timestamps in milliseconds.
31
+ * Both timestamps should be from performance.now().
32
+ */
33
+ static duration(startTime: number, endTime: number): number;
34
+ }
35
+ export default Timing;
36
+ //# sourceMappingURL=timing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"timing.d.ts","sourceRoot":"","sources":["../../src/util/timing.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAqBjF;;;;;GAKG;AACH,cAAM,MAAM;IACV;;;OAGG;IACH,MAAM,CAAC,GAAG,IAAI,MAAM;IAIpB;;;OAGG;IACH,MAAM,CAAC,KAAK,IAAI,KAAK;IAIrB;;;OAGG;WACU,OAAO,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,GAAE,cAAmB,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAwBzG;;;OAGG;IACH,MAAM,CAAC,WAAW,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,OAAO,GAAE,cAAmB,GAAG,YAAY,CAAC,CAAC,CAAC;IAwBjF;;;OAGG;IACH,MAAM,CAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM;CAG5D;AAED,eAAe,MAAM,CAAC"}
@@ -0,0 +1,47 @@
1
+ export interface Timer {
2
+ /**
3
+ * Stop the timer and return elapsed time in milliseconds with decimal precision.
4
+ */
5
+ stop(): number;
6
+ /**
7
+ * Get elapsed time since timer start without stopping the timer.
8
+ */
9
+ elapsed(): number;
10
+ /**
11
+ * The start timestamp in milliseconds (performance.now() format).
12
+ */
13
+ readonly startTime: number;
14
+ }
15
+ export interface TimingResult<T = any> {
16
+ /**
17
+ * Duration in milliseconds with decimal precision.
18
+ */
19
+ duration: number;
20
+ /**
21
+ * The result returned by the measured function.
22
+ */
23
+ result: T;
24
+ /**
25
+ * Start timestamp in milliseconds (performance.now() format).
26
+ */
27
+ startTime: number;
28
+ /**
29
+ * End timestamp in milliseconds (performance.now() format).
30
+ */
31
+ endTime: number;
32
+ }
33
+ export interface MeasureOptions {
34
+ /**
35
+ * Optional name for the measurement (useful for logging/debugging).
36
+ */
37
+ name?: string;
38
+ /**
39
+ * Whether to log the timing result automatically.
40
+ */
41
+ log?: boolean;
42
+ /**
43
+ * Custom logger function to use if log is true.
44
+ */
45
+ logger?: (message: string, duration: number) => void;
46
+ }
47
+ //# sourceMappingURL=timing.interface.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"timing.interface.d.ts","sourceRoot":"","sources":["../../src/util/timing.interface.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,KAAK;IACpB;;OAEG;IACH,IAAI,IAAI,MAAM,CAAC;IAEf;;OAEG;IACH,OAAO,IAAI,MAAM,CAAC;IAElB;;OAEG;IACH,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,YAAY,CAAC,CAAC,GAAG,GAAG;IACnC;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;IAEjB;;OAEG;IACH,MAAM,EAAE,CAAC,CAAC;IAEV;;OAEG;IACH,SAAS,EAAE,MAAM,CAAC;IAElB;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,cAAc;IAC7B;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd;;OAEG;IACH,GAAG,CAAC,EAAE,OAAO,CAAC;IAEd;;OAEG;IACH,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;CACtD"}
@@ -0,0 +1 @@
1
+ //# sourceMappingURL=timing.interface.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": [],
4
+ "sourcesContent": [],
5
+ "mappings": "",
6
+ "names": []
7
+ }