emilsoftware-utilities 2.0.0-dev.23 → 2.0.0-dev.25

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 (261) hide show
  1. package/README.MD +147 -0
  2. package/dist/ContractGenerator.d.ts +4 -3
  3. package/dist/ContractGenerator.js +15 -5
  4. package/dist/ContractGenerator.js.map +1 -1
  5. package/dist/DailyFileTransport.d.ts +8 -2
  6. package/dist/DailyFileTransport.js +9 -2
  7. package/dist/DailyFileTransport.js.map +1 -1
  8. package/dist/DatabaseUpdater.js +8 -3
  9. package/dist/DatabaseUpdater.js.map +1 -1
  10. package/dist/ExecutionTimeLogger.d.ts +2 -2
  11. package/dist/ExecutionTimeLogger.js +3 -2
  12. package/dist/ExecutionTimeLogger.js.map +1 -1
  13. package/dist/Logger.d.ts +22 -9
  14. package/dist/Logger.js +131 -54
  15. package/dist/Logger.js.map +1 -1
  16. package/dist/Orm.d.ts +26 -6
  17. package/dist/Orm.js +144 -40
  18. package/dist/Orm.js.map +1 -1
  19. package/dist/Utilities.d.ts +12 -7
  20. package/dist/Utilities.js +57 -22
  21. package/dist/Utilities.js.map +1 -1
  22. package/dist/accessi-module/AccessiModule.d.ts +9 -0
  23. package/dist/accessi-module/AccessiModule.js +12 -4
  24. package/dist/accessi-module/AccessiModule.js.map +1 -1
  25. package/dist/accessi-module/Console/console.css +529 -281
  26. package/dist/accessi-module/Console/console.js +2081 -85
  27. package/dist/accessi-module/Console/console.js.map +1 -1
  28. package/dist/accessi-module/Console/generated/accessiApi.d.ts +167 -1
  29. package/dist/accessi-module/Console/generated/accessiApi.js +156 -2
  30. package/dist/accessi-module/Console/generated/accessiApi.js.map +1 -1
  31. package/dist/accessi-module/Console/generated/model/abilitazioneMenu.d.ts +20 -8
  32. package/dist/accessi-module/Console/generated/model/abilitazioneMenu.js.map +1 -1
  33. package/dist/accessi-module/Console/generated/model/createFilterTypeRequest.d.ts +23 -0
  34. package/dist/accessi-module/Console/generated/model/createFilterTypeRequest.js +3 -0
  35. package/dist/accessi-module/Console/generated/model/createFilterTypeRequest.js.map +1 -0
  36. package/dist/accessi-module/Console/generated/model/createFilterTypeRequestFlgEnabled.d.ts +14 -0
  37. package/dist/accessi-module/Console/generated/model/createFilterTypeRequestFlgEnabled.js +15 -0
  38. package/dist/accessi-module/Console/generated/model/createFilterTypeRequestFlgEnabled.js.map +1 -0
  39. package/dist/accessi-module/Console/generated/model/createMenuGroupRequest.d.ts +27 -0
  40. package/dist/accessi-module/Console/generated/model/createMenuGroupRequest.js +9 -0
  41. package/dist/accessi-module/Console/generated/model/createMenuGroupRequest.js.map +1 -0
  42. package/dist/accessi-module/Console/generated/model/createMenuRequest.d.ts +52 -0
  43. package/dist/accessi-module/Console/generated/model/createMenuRequest.js +9 -0
  44. package/dist/accessi-module/Console/generated/model/createMenuRequest.js.map +1 -0
  45. package/dist/accessi-module/Console/generated/model/createMenuTypeRequest.d.ts +18 -0
  46. package/dist/accessi-module/Console/generated/model/createMenuTypeRequest.js +9 -0
  47. package/dist/accessi-module/Console/generated/model/createMenuTypeRequest.js.map +1 -0
  48. package/dist/accessi-module/Console/generated/model/createServiceTokenRequest.d.ts +16 -0
  49. package/dist/accessi-module/Console/generated/model/createServiceTokenRequest.js +9 -0
  50. package/dist/accessi-module/Console/generated/model/createServiceTokenRequest.js.map +1 -0
  51. package/dist/accessi-module/Console/generated/model/createServiceTokenResponse.d.ts +14 -0
  52. package/dist/accessi-module/Console/generated/model/createServiceTokenResponse.js +3 -0
  53. package/dist/accessi-module/Console/generated/model/createServiceTokenResponse.js.map +1 -0
  54. package/dist/accessi-module/Console/generated/model/getMenuTypesResponse.d.ts +14 -0
  55. package/dist/accessi-module/Console/generated/model/getMenuTypesResponse.js +3 -0
  56. package/dist/accessi-module/Console/generated/model/getMenuTypesResponse.js.map +1 -0
  57. package/dist/accessi-module/Console/generated/model/getServiceTokensParams.d.ts +12 -0
  58. package/dist/accessi-module/Console/generated/model/getServiceTokensParams.js +9 -0
  59. package/dist/accessi-module/Console/generated/model/getServiceTokensParams.js.map +1 -0
  60. package/dist/accessi-module/Console/generated/model/getServiceTokensResponse.d.ts +14 -0
  61. package/dist/accessi-module/Console/generated/model/getServiceTokensResponse.js +3 -0
  62. package/dist/accessi-module/Console/generated/model/getServiceTokensResponse.js.map +1 -0
  63. package/dist/accessi-module/Console/generated/model/getUsersParams.d.ts +8 -0
  64. package/dist/accessi-module/Console/generated/model/getUsersParams.js.map +1 -1
  65. package/dist/accessi-module/Console/generated/model/index.d.ts +18 -0
  66. package/dist/accessi-module/Console/generated/model/index.js +18 -0
  67. package/dist/accessi-module/Console/generated/model/index.js.map +1 -1
  68. package/dist/accessi-module/Console/generated/model/issuedServiceTokenDto.d.ts +30 -0
  69. package/dist/accessi-module/Console/generated/model/issuedServiceTokenDto.js +9 -0
  70. package/dist/accessi-module/Console/generated/model/issuedServiceTokenDto.js.map +1 -0
  71. package/dist/accessi-module/Console/generated/model/menuTypeEntity.d.ts +12 -0
  72. package/dist/accessi-module/Console/generated/model/menuTypeEntity.js +9 -0
  73. package/dist/accessi-module/Console/generated/model/menuTypeEntity.js.map +1 -0
  74. package/dist/accessi-module/Console/generated/model/serviceTokenDto.d.ts +28 -0
  75. package/dist/accessi-module/Console/generated/model/serviceTokenDto.js +9 -0
  76. package/dist/accessi-module/Console/generated/model/serviceTokenDto.js.map +1 -0
  77. package/dist/accessi-module/Console/generated/model/updateFilterTypeRequest.d.ts +21 -0
  78. package/dist/accessi-module/Console/generated/model/updateFilterTypeRequest.js +3 -0
  79. package/dist/accessi-module/Console/generated/model/updateFilterTypeRequest.js.map +1 -0
  80. package/dist/accessi-module/Console/generated/model/updateFilterTypeRequestFlgEnabled.d.ts +14 -0
  81. package/dist/accessi-module/Console/generated/model/updateFilterTypeRequestFlgEnabled.js +15 -0
  82. package/dist/accessi-module/Console/generated/model/updateFilterTypeRequestFlgEnabled.js.map +1 -0
  83. package/dist/accessi-module/Console/generated/model/updateMenuGroupRequest.d.ts +22 -0
  84. package/dist/accessi-module/Console/generated/model/updateMenuGroupRequest.js +9 -0
  85. package/dist/accessi-module/Console/generated/model/updateMenuGroupRequest.js.map +1 -0
  86. package/dist/accessi-module/Console/generated/model/updateMenuRequest.d.ts +47 -0
  87. package/dist/accessi-module/Console/generated/model/updateMenuRequest.js +9 -0
  88. package/dist/accessi-module/Console/generated/model/updateMenuRequest.js.map +1 -0
  89. package/dist/accessi-module/Console/generated/model/updateMenuTypeRequest.d.ts +13 -0
  90. package/dist/accessi-module/Console/generated/model/updateMenuTypeRequest.js +9 -0
  91. package/dist/accessi-module/Console/generated/model/updateMenuTypeRequest.js.map +1 -0
  92. package/dist/accessi-module/Console/help.d.ts +13 -0
  93. package/dist/accessi-module/Console/help.js +348 -0
  94. package/dist/accessi-module/Console/help.js.map +1 -0
  95. package/dist/accessi-module/Console/index.html +89 -21
  96. package/dist/accessi-module/Console/wiki.d.ts +52 -0
  97. package/dist/accessi-module/Console/wiki.js +689 -0
  98. package/dist/accessi-module/Console/wiki.js.map +1 -0
  99. package/dist/accessi-module/Controllers/AccessiConsoleController.d.ts +8 -1
  100. package/dist/accessi-module/Controllers/AccessiConsoleController.js +52 -15
  101. package/dist/accessi-module/Controllers/AccessiConsoleController.js.map +1 -1
  102. package/dist/accessi-module/Controllers/ConfiguratorController.d.ts +1 -3
  103. package/dist/accessi-module/Controllers/ConfiguratorController.js +6 -8
  104. package/dist/accessi-module/Controllers/ConfiguratorController.js.map +1 -1
  105. package/dist/accessi-module/Controllers/EmailController.d.ts +1 -1
  106. package/dist/accessi-module/Controllers/EmailController.js +1 -1
  107. package/dist/accessi-module/Controllers/EmailController.js.map +1 -1
  108. package/dist/accessi-module/Controllers/FiltriController.d.ts +5 -4
  109. package/dist/accessi-module/Controllers/FiltriController.js +92 -4
  110. package/dist/accessi-module/Controllers/FiltriController.js.map +1 -1
  111. package/dist/accessi-module/Controllers/PermissionController.d.ts +11 -0
  112. package/dist/accessi-module/Controllers/PermissionController.js +273 -8
  113. package/dist/accessi-module/Controllers/PermissionController.js.map +1 -1
  114. package/dist/accessi-module/Controllers/ServiceTokenController.d.ts +23 -0
  115. package/dist/accessi-module/Controllers/ServiceTokenController.js +176 -0
  116. package/dist/accessi-module/Controllers/ServiceTokenController.js.map +1 -0
  117. package/dist/accessi-module/Controllers/UserController.d.ts +2 -2
  118. package/dist/accessi-module/Controllers/UserController.js +25 -9
  119. package/dist/accessi-module/Controllers/UserController.js.map +1 -1
  120. package/dist/accessi-module/Dtos/Abilitazione.js.map +1 -1
  121. package/dist/accessi-module/Dtos/AbilitazioneMenu.js +16 -8
  122. package/dist/accessi-module/Dtos/AbilitazioneMenu.js.map +1 -1
  123. package/dist/accessi-module/Dtos/AssignPermissionsToUserRequest.js.map +1 -1
  124. package/dist/accessi-module/Dtos/AssignRolesToUserRequest.js.map +1 -1
  125. package/dist/accessi-module/Dtos/AuthenticatedUserPayloadDto.js.map +1 -1
  126. package/dist/accessi-module/Dtos/BaseResponse.js.map +1 -1
  127. package/dist/accessi-module/Dtos/CatalogDtos.d.ts +66 -0
  128. package/dist/accessi-module/Dtos/CatalogDtos.js +336 -0
  129. package/dist/accessi-module/Dtos/CatalogDtos.js.map +1 -0
  130. package/dist/accessi-module/Dtos/ConfirmResetPasswordRequest.js.map +1 -1
  131. package/dist/accessi-module/Dtos/FiltriUtente.js.map +1 -1
  132. package/dist/accessi-module/Dtos/GetGroupsWithMenusResponse.js.map +1 -1
  133. package/dist/accessi-module/Dtos/GetMenusResponse.js +1 -1
  134. package/dist/accessi-module/Dtos/GetMenusResponse.js.map +1 -1
  135. package/dist/accessi-module/Dtos/GetRolesResponse.js.map +1 -1
  136. package/dist/accessi-module/Dtos/GetUserByTokenRequest.js.map +1 -1
  137. package/dist/accessi-module/Dtos/GetUserByTokenResponse.js.map +1 -1
  138. package/dist/accessi-module/Dtos/GetUsersResponse.d.ts +1 -1
  139. package/dist/accessi-module/Dtos/GetUsersResponse.js.map +1 -1
  140. package/dist/accessi-module/Dtos/LoginRequest.js.map +1 -1
  141. package/dist/accessi-module/Dtos/LoginResponse.d.ts +1 -1
  142. package/dist/accessi-module/Dtos/LoginResponse.js +1 -1
  143. package/dist/accessi-module/Dtos/LoginResponse.js.map +1 -1
  144. package/dist/accessi-module/Dtos/MenuItem.js +1 -0
  145. package/dist/accessi-module/Dtos/Permission.js.map +1 -1
  146. package/dist/accessi-module/Dtos/RegisterRequest.js +2 -1
  147. package/dist/accessi-module/Dtos/RegisterRequest.js.map +1 -1
  148. package/dist/accessi-module/Dtos/RegisterResponse.js.map +1 -1
  149. package/dist/accessi-module/Dtos/Role.js.map +1 -1
  150. package/dist/accessi-module/Dtos/RuoliMenu.js.map +1 -1
  151. package/dist/accessi-module/Dtos/SendResetPasswordEmailRequest.js.map +1 -1
  152. package/dist/accessi-module/Dtos/ServiceToken.d.ts +34 -0
  153. package/dist/accessi-module/Dtos/ServiceToken.js +128 -0
  154. package/dist/accessi-module/Dtos/ServiceToken.js.map +1 -0
  155. package/dist/accessi-module/Dtos/SetStatoRegistrazione.js.map +1 -1
  156. package/dist/accessi-module/Dtos/TipoFiltro.js.map +1 -1
  157. package/dist/accessi-module/Dtos/TokenResult.js.map +1 -1
  158. package/dist/accessi-module/Dtos/TwoFactorDtos.js.map +1 -1
  159. package/dist/accessi-module/Dtos/UpdateEnabledStatusRequest.js.map +1 -1
  160. package/dist/accessi-module/Dtos/UserDto.js +4 -2
  161. package/dist/accessi-module/Dtos/UserDto.js.map +1 -1
  162. package/dist/accessi-module/Dtos/UserGrantsDto.js.map +1 -1
  163. package/dist/accessi-module/Dtos/UserGrantsResponse.js.map +1 -1
  164. package/dist/accessi-module/Dtos/index.d.ts +2 -0
  165. package/dist/accessi-module/Dtos/index.js +2 -0
  166. package/dist/accessi-module/Dtos/index.js.map +1 -1
  167. package/dist/accessi-module/Services/AuthService/AuthService.d.ts +2 -2
  168. package/dist/accessi-module/Services/AuthService/AuthService.js +36 -36
  169. package/dist/accessi-module/Services/AuthService/AuthService.js.map +1 -1
  170. package/dist/accessi-module/Services/EmailService/EmailService.d.ts +2 -1
  171. package/dist/accessi-module/Services/EmailService/EmailService.js +9 -6
  172. package/dist/accessi-module/Services/EmailService/EmailService.js.map +1 -1
  173. package/dist/accessi-module/Services/FiltriService/FiltriService.d.ts +10 -3
  174. package/dist/accessi-module/Services/FiltriService/FiltriService.js +64 -6
  175. package/dist/accessi-module/Services/FiltriService/FiltriService.js.map +1 -1
  176. package/dist/accessi-module/Services/PermissionService/PermissionService.d.ts +44 -1
  177. package/dist/accessi-module/Services/PermissionService/PermissionService.js +418 -110
  178. package/dist/accessi-module/Services/PermissionService/PermissionService.js.map +1 -1
  179. package/dist/accessi-module/Services/ServiceTokenService/ServiceTokenService.d.ts +75 -0
  180. package/dist/accessi-module/Services/ServiceTokenService/ServiceTokenService.js +265 -0
  181. package/dist/accessi-module/Services/ServiceTokenService/ServiceTokenService.js.map +1 -0
  182. package/dist/accessi-module/Services/TwoFactorService/TwoFactorService.js +23 -27
  183. package/dist/accessi-module/Services/TwoFactorService/TwoFactorService.js.map +1 -1
  184. package/dist/accessi-module/Services/UserService/UserService.d.ts +10 -3
  185. package/dist/accessi-module/Services/UserService/UserService.js +170 -84
  186. package/dist/accessi-module/Services/UserService/UserService.js.map +1 -1
  187. package/dist/accessi-module/database-updates/AccessiDatabaseUpdater.d.ts +9 -0
  188. package/dist/accessi-module/database-updates/AccessiDatabaseUpdater.js +76 -28
  189. package/dist/accessi-module/database-updates/AccessiDatabaseUpdater.js.map +1 -1
  190. package/dist/accessi-module/database-updates/accessiSchema.d.ts +1 -1
  191. package/dist/accessi-module/database-updates/accessiSchema.js +9 -1
  192. package/dist/accessi-module/database-updates/accessiSchema.js.map +1 -1
  193. package/dist/accessi-module/database-updates/optionalColumns.d.ts +2 -0
  194. package/dist/accessi-module/database-updates/optionalColumns.js +33 -1
  195. package/dist/accessi-module/database-updates/optionalColumns.js.map +1 -1
  196. package/dist/accessi-module/database-updates/runAccessiDbUpdate.js +7 -2
  197. package/dist/accessi-module/database-updates/runAccessiDbUpdate.js.map +1 -1
  198. package/dist/accessi-module/federated-auth/FederatedAuthController.d.ts +1 -0
  199. package/dist/accessi-module/federated-auth/FederatedAuthController.js +26 -0
  200. package/dist/accessi-module/federated-auth/FederatedAuthController.js.map +1 -1
  201. package/dist/accessi-module/federated-auth/FederatedAuthService.d.ts +6 -0
  202. package/dist/accessi-module/federated-auth/FederatedAuthService.js +28 -1
  203. package/dist/accessi-module/federated-auth/FederatedAuthService.js.map +1 -1
  204. package/dist/accessi-module/index.d.ts +4 -1
  205. package/dist/accessi-module/index.js +8 -2
  206. package/dist/accessi-module/index.js.map +1 -1
  207. package/dist/accessi-module/jwt/jwt.strategy.js +8 -5
  208. package/dist/accessi-module/jwt/jwt.strategy.js.map +1 -1
  209. package/dist/accessi-module/middleware/accessiRequirements.d.ts +1 -1
  210. package/dist/accessi-module/middleware/accessiRequirements.js.map +1 -1
  211. package/dist/accessi-module/middleware/authenticateGen.js +11 -7
  212. package/dist/accessi-module/middleware/authenticateGen.js.map +1 -1
  213. package/dist/accessi-module/security/accessControl.js +8 -3
  214. package/dist/accessi-module/security/accessControl.js.map +1 -1
  215. package/dist/accessi-module/security/authenticatedToken.d.ts +1 -1
  216. package/dist/accessi-module/security/authenticatedToken.js +2 -1
  217. package/dist/accessi-module/security/authenticatedToken.js.map +1 -1
  218. package/dist/accessi-module/security/passwordResetToken.d.ts +9 -3
  219. package/dist/accessi-module/security/passwordResetToken.js +9 -5
  220. package/dist/accessi-module/security/passwordResetToken.js.map +1 -1
  221. package/dist/accessi-module/security/publicAuthRateLimit.d.ts +1 -1
  222. package/dist/accessi-module/security/publicAuthRateLimit.js +28 -8
  223. package/dist/accessi-module/security/publicAuthRateLimit.js.map +1 -1
  224. package/dist/accessi-module/security/serviceTokenGuard.d.ts +25 -0
  225. package/dist/accessi-module/security/serviceTokenGuard.js +85 -0
  226. package/dist/accessi-module/security/serviceTokenGuard.js.map +1 -0
  227. package/dist/accessi-module/security/serviceTokenRateLimit.d.ts +8 -0
  228. package/dist/accessi-module/security/serviceTokenRateLimit.js +49 -0
  229. package/dist/accessi-module/security/serviceTokenRateLimit.js.map +1 -0
  230. package/dist/allegati-module/AllegatiModule.d.ts +11 -0
  231. package/dist/allegati-module/AllegatiModule.js +11 -1
  232. package/dist/allegati-module/AllegatiModule.js.map +1 -1
  233. package/dist/allegati-module/Controllers/AllegatiController.d.ts +2 -1
  234. package/dist/allegati-module/Controllers/AllegatiController.js +23 -15
  235. package/dist/allegati-module/Controllers/AllegatiController.js.map +1 -1
  236. package/dist/allegati-module/Dtos/AllegatoDto.js.map +1 -1
  237. package/dist/allegati-module/Dtos/BaseResponse.js.map +1 -1
  238. package/dist/allegati-module/Dtos/UploadSingleFileRequest.js.map +1 -1
  239. package/dist/allegati-module/Dtos/responses/DownloadAllegatoResponseDto.js.map +1 -1
  240. package/dist/allegati-module/Dtos/responses/GetListResponse.js.map +1 -1
  241. package/dist/allegati-module/Dtos/responses/UploadAllegatoResponseDto.js.map +1 -1
  242. package/dist/allegati-module/Services/AllegatiService/AllegatiService.d.ts +10 -3
  243. package/dist/allegati-module/Services/AllegatiService/AllegatiService.js +101 -52
  244. package/dist/allegati-module/Services/AllegatiService/AllegatiService.js.map +1 -1
  245. package/dist/allegati-module/security/allegatiAuthorizationGuard.d.ts +14 -0
  246. package/dist/allegati-module/security/allegatiAuthorizationGuard.js +70 -0
  247. package/dist/allegati-module/security/allegatiAuthorizationGuard.js.map +1 -0
  248. package/dist/autobind.d.ts +10 -3
  249. package/dist/autobind.js +24 -9
  250. package/dist/autobind.js.map +1 -1
  251. package/dist/emilsoftware-utilities-2.0.0-dev.25.tgz +0 -0
  252. package/dist/firebird-compat.d.ts +13 -0
  253. package/dist/firebird-compat.js +3 -2
  254. package/dist/firebird-compat.js.map +1 -1
  255. package/dist/scripts/generateAccessiWiki.d.ts +1 -0
  256. package/dist/scripts/generateAccessiWiki.js +131 -0
  257. package/dist/scripts/generateAccessiWiki.js.map +1 -0
  258. package/dist/swagger/SwaggerConfig.js +6 -3
  259. package/dist/swagger/SwaggerConfig.js.map +1 -1
  260. package/package.json +19 -8
  261. package/dist/emilsoftware-utilities-2.0.0-dev.23.tgz +0 -0
package/README.MD CHANGED
@@ -1,3 +1,14 @@
1
+ # Emilsoftware Utilities
2
+
3
+ Documentazione completa del modulo Accessi, generata da `src/accessi-module/Console/wiki.ts` (stessa fonte della Wiki nella console):
4
+
5
+ - **[WIKI.md](WIKI.md)** — guida completa con indice, esempi corretti e antipattern.
6
+ - **[WIKI.ai.md](WIKI.ai.md)** — versione compatta da fornire a un'IA che costruisce il backend.
7
+
8
+ Rigenera entrambi con `npm run generate:accessi-wiki` (incluso in `npm run build`).
9
+
10
+ ---
11
+
1
12
  Convenzioni per i Commit Message
2
13
 
3
14
  1. feat:
@@ -36,3 +47,139 @@ git push origin main
36
47
  ## Accessi
37
48
 
38
49
  La documentazione operativa del modulo accessi si trova in [src/accessi-module/README.md](src/accessi-module/README.md).
50
+
51
+ ## Test e qualita
52
+
53
+ | Comando | Descrizione |
54
+ | --- | --- |
55
+ | `npm run typecheck` | Typecheck TypeScript in modalita `strict` (piu flag di igiene) |
56
+ | `npm run lint` | Lint dependency-free (no `any`, no `@ts-ignore`, no `console.*` fuori dal logger) |
57
+ | `npm test` | Typecheck + lint + test unitari |
58
+ | `npm run test:unit` | Solo test unitari (`node --test`) |
59
+ | `npm run test:coverage` | Test unitari con report e **soglie minime** di copertura |
60
+ | `npm run test:integration` | Integration test su Firebird reale (default: porta 3055) |
61
+ | `npm run test:integration:fb5` / `:fb3` / `:fb25` | Integration test su Firebird 5 / 3 / 2.5 |
62
+ | `npm run test:accessi-console` | Test end-to-end della console (richiede un browser Chromium e la build) |
63
+
64
+ ### Integration test su Firebird reale
65
+
66
+ Avvia i database di test (Firebird 5 sulla 3055, Firebird 3 sulla 3056, Firebird 2.5 sulla 3057) e lancia la suite:
67
+
68
+ ```bash
69
+ docker compose -f docker-compose.test.yml up -d
70
+ npm run test:integration:fb5
71
+ npm run test:integration:fb3
72
+ npm run test:integration:fb25
73
+ docker compose -f docker-compose.test.yml down -v
74
+ ```
75
+
76
+ Firebird 2.5 usa l'immagine `jacobalberty/firebird:v2.5.9-ss` (l'immagine ufficiale non copre la 2.5) con `Legacy_Auth` e wire crypt disabilitato: lo script `test:integration:fb25` imposta da solo plugin e wireCrypt.
77
+
78
+ Il database viene creato dal test stesso (`attachOrCreate`) e lo schema costruito dal migrator
79
+ della libreria (`AccessiDatabaseUpdater`), quindi gli integration test validano anche migrazione e
80
+ compatibilita dello schema. Senza un Firebird raggiungibile i test vengono marcati come `skip`; con
81
+ `ACCESSI_TEST_REQUIRE_DB=1` falliscono invece di essere saltati (usato dalla CI).
82
+
83
+ Variabili: `ACCESSI_TEST_DB_HOST`, `ACCESSI_TEST_DB_PORT`, `ACCESSI_TEST_DB_DATABASE`,
84
+ `ACCESSI_TEST_DB_USER`, `ACCESSI_TEST_DB_PASSWORD`, `ACCESSI_TEST_DB_WIRE_CRYPT`,
85
+ `ACCESSI_TEST_DB_AUTH_PLUGIN`.
86
+
87
+ I container usano le porte host **3055** e **3056** per non entrare in conflitto con un Firebird
88
+ locale spesso in ascolto sulla 3050. Per cambiare porta/percorso, modifica i mapping in
89
+ `docker-compose.test.yml` e passa `ACCESSI_TEST_DB_PORT` / `ACCESSI_TEST_DB_DATABASE`.
90
+
91
+ La CI (`.github/workflows/ci.yml`) esegue typecheck, test con coverage e build, piu un job di
92
+ integration test in matrice su Firebird 5 e 3. Il workflow di release (`publish.yml`) esegue
93
+ typecheck e test prima di build e pubblicazione.
94
+
95
+ ## Service token (macchina-a-macchina)
96
+
97
+ Credenziali di servizio per chiamate tecniche, **non legate a un utente** e senza login giornaliero.
98
+ Sostituiscono l'uso di un `secret` nel body: si inviano con `Authorization: Bearer <token>`.
99
+
100
+ - Formato: `st_<id>.<segreto>`. Il segreto e mostrato **una sola volta** alla creazione/rotazione.
101
+ - Storage: tabella `ACCESSI_SERVICE_TOKEN` (schema Accessi, migrazione automatica `1.7.0`). Il segreto e salvato solo come hash SHA-256 e confrontato a tempo costante.
102
+ - Metadati e audit: descrizione, scope, creazione/scadenza, ultimo utilizzo con **IP** (`lastUsedIp`), revoca con **autore** (`revokedBy`).
103
+ - Rate limit anti-abuso per IP sulla verifica (HTTP 429).
104
+ - API amministrative (solo superutente): `POST /api/accessi/service-token`, `GET /api/accessi/service-token` (`includeRevoked=true`), `DELETE /api/accessi/service-token/:tokenId`, `POST /api/accessi/service-token/:tokenId/rotate`.
105
+ - Console: sezione **Token di servizio** (crea, ruota, revoca; copia il token una sola volta).
106
+ - Utilizzo lato consumer: guard `ServiceTokenGuard` con `@RequireServiceTokenScopes('ia')`; il token verificato e disponibile con `getAccessiServiceToken(req)`.
107
+ - Opzione: `serviceTokens: { enabled?: boolean; defaultTtlDays?: number }` in `AccessiOptions`.
108
+
109
+ ```ts
110
+ import { Module } from '@nestjs/common';
111
+ import { ServiceTokenGuard, RequireServiceTokenScopes } from 'emilsoftware-utilities';
112
+
113
+ @UseGuards(ServiceTokenGuard)
114
+ @RequireServiceTokenScopes('ia')
115
+ @Controller('ia')
116
+ export class IaController {}
117
+ ```
118
+
119
+ ## Hardening e opzioni
120
+
121
+ - I log delle query **non includono i valori dei parametri** (segreti, credenziali, PII). Per riattivare esplicitamente i valori: `logQueryParameters: true` nelle `databaseOptions`.
122
+ - Pool di connessioni **attivo di default** (`poolSize` default `5`); `poolSize: 0` disabilita e torna a una connessione per query. Gli script di breve durata devono chiamare `await Orm.closePools()` prima di uscire.
123
+ - I JWT sono verificati con algoritmo fissato a `HS256` ed e obbligatoria una scadenza (`expiresIn`) valida.
124
+ - **Chiavi JWT separate per scopo** (`access`, `reset`, `2fa`), derivate dal segreto configurato; il claim `typ: 'access'` e **obbligatorio** per gli access token.
125
+ - La backdoor mock `admin`/`demo` non e mai attiva quando `NODE_ENV=production`.
126
+ - Gli allegati sono **protetti di default**: senza `allegatiOptions.authorize` le richieste rispondono 403. Per la migrazione da versioni precedenti impostare `requireAuthorization: false` (sconsigliato in produzione).
127
+ - Upload allegati: limite di 1 file / 90 MB applicato da Multer e validazione dei magic byte oltre al mimetype dichiarato.
128
+
129
+ ## Integrazione
130
+
131
+ | Scenario | API |
132
+ | --- | --- |
133
+ | Backend Express esistente | `await initializeAccessiModule(app, accessiOptions)` monta le rotte `/api/accessi` su un host Nest isolato |
134
+ | Applicazione NestJS | importa `AccessiModule.forRoot(accessiOptions)` (e/o `AllegatiModule.forRoot(allegatiOptions)`) |
135
+ | Accessi + Allegati insieme | `EmilsoftwareModule.forRoot({ accessiOptions, allegatiOptions })` |
136
+
137
+ Tutta la configurazione e riservata al backend: segreti JWT/SMTP/DB non devono mai raggiungere il browser.
138
+
139
+ ## Riferimento `AccessiOptions`
140
+
141
+ | Campo | Tipo | Note |
142
+ | --- | --- | --- |
143
+ | `databaseOptions` | `Options` | Connessione Firebird (`DatabaseUtilities.createOption`). Supporta `logQueryParameters`, `poolSize`, `wireCrypt`, `pluginName`. |
144
+ | `confirmationEmailUrl` / `confirmationEmailReturnUrl` | `string` | URL per le email di reset. |
145
+ | `customResetPage` / `confirmationEmailPrefix` | `string?` | Pagina di reset personalizzata. |
146
+ | `encryptionKey` | `string` | Solo compatibilita/migrazione password legacy cifrate. |
147
+ | `mockDemoUser` | `boolean` | Utenti fittizi `admin`/`demo`; **mai** attivi in produzione. |
148
+ | `passwordExpiration` / `passwordExpirationDays` | `boolean?` / `number?` | Scadenza password (default 90 giorni). |
149
+ | `legacyPasswordMigrationOnStartup` | `boolean?` | Migrazione password legacy al bootstrap (default `true`). |
150
+ | `autoUpdateDatabase` | `boolean?` | Riconcilia lo schema al bootstrap (default `true`); con `false` verifica in sola lettura. |
151
+ | `jwtOptions` | `{ secret: string; expiresIn: string }` | HS256 con scadenza obbligatoria. |
152
+ | `emailOptions` | `EmailOptions` | SMTP per reset e codici 2FA. |
153
+ | `publicAuthRateLimit` | `PublicAuthRateLimitOptions?` | Limiti degli endpoint pubblici (default attivi). |
154
+ | `publicRegistration` | `{ enabled?: boolean }?` | Registrazione pubblica opt-in. |
155
+ | `federatedAuthentication` | `{ enabled?; allowSelfRegistration? }?` | SSO provider-agnostico. |
156
+ | `extensionFieldsOptions` | `ExtensionFieldsOptions[]?` | Campi applicativi estesi. |
157
+ | `serviceTokens` | `{ enabled?: boolean; defaultTtlDays?: number }?` | Token macchina-a-macchina (default abilitati). |
158
+
159
+ ## Riferimento `AllegatiOptions`
160
+
161
+ | Campo | Tipo | Note |
162
+ | --- | --- | --- |
163
+ | `databaseOptions` | `Options` | Connessione Firebird. |
164
+ | `authorize` | `(req) => boolean \| Promise<boolean>?` | Controllo di autorizzazione applicato a ogni richiesta; `false` → 403. |
165
+ | `requireAuthorization` | `boolean?` | **Default `true`**: senza `authorize` le richieste sono rifiutate con 403 (secure by default). `false` ripristina il comportamento storico (endpoint aperti) durante la migrazione. |
166
+
167
+ ## Contratto risposte ed errori
168
+
169
+ - Successo generico: `RestUtilities.sendOKMessage` → `{ severity, status, statusCode, message }`.
170
+ - Payload: `RestUtilities.sendBaseResponse` → `{ Status: { errorCode, errorDescription }, Result, Message }`.
171
+ - Errore: `{ severity: 'error', status, statusCode, code, message, error, details? }`, con `code` stabile (es. `ACCESSI_UNAUTHORIZED`, `ACCESSI_INVALID_CREDENTIALS`, `PASSWORD_EXPIRED`, `ACCESSI_DATABASE_SCHEMA_OUTDATED`, `ACCESSI_SERVICE_TOKEN_RATE_LIMITED`). Lo status deriva dalla `HttpException` (validazione → 400); errori di schema DB → 503. SQL, stack e dati sensibili non vengono mai esposti.
172
+
173
+ ## Migrazioni e schema
174
+
175
+ - Lo schema Accessi e versionato in `accessiSchema.ts` (`ACCESSI_SCHEMA_VERSION`) e riconciliato in modo **idempotente e ripartibile** da `AccessiDatabaseUpdater` (nessun DDL distruttivo, FK/indici/trigger verificati, sequence avanzate solo in avanti).
176
+ - La versione viene aggiornata **solo dopo** `assertCompatible`; su errore la migrazione si puo rieseguire.
177
+ - Firebird non rende utilizzabili gli oggetti creati nella stessa transazione, quindi il DDL non e racchiuso in un'unica transazione: la robustezza e data da idempotenza + verifica finale.
178
+ - Con `autoUpdateDatabase: false` la libreria verifica lo schema in sola lettura e blocca l'avvio se incompatibile (`AccessiDatabaseUpdater.inspectSchema`).
179
+
180
+ ## Osservabilita
181
+
182
+ - `Logger` strutturato (console colorata + file JSON giornaliero), condiviso per directory.
183
+ - Livello minimo configurabile per istanza (`new Logger(tag, { level: 'info' })`) o globalmente con la variabile `LOG_LEVEL` (default `database` = tutto).
184
+ - Redazione automatica dei campi sensibili (`password`, `token`, `secret`, ...) e serializzazione degli `Error` con stack.
185
+ - I log delle query non contengono i valori dei parametri (salvo `logQueryParameters: true`).
@@ -1,3 +1,4 @@
1
+ import { Styles, UserOptions } from "jspdf-autotable";
1
2
  export interface IPartiContratto {
2
3
  fornitore: {
3
4
  denominazione: string;
@@ -25,8 +26,8 @@ export type DynamicElement = {
25
26
  config: {
26
27
  head: string[];
27
28
  body: string[][];
28
- options?: any;
29
- styles?: any;
29
+ options?: UserOptions;
30
+ styles?: Partial<Styles>;
30
31
  };
31
32
  };
32
33
  interface DocumentConfig {
@@ -100,7 +101,7 @@ export declare class DocumentGenerator {
100
101
  private curX;
101
102
  private curY;
102
103
  private configLoaded;
103
- constructor(configPath?: string);
104
+ constructor(configPath?: string | undefined);
104
105
  setConfig(config: DocumentConfig): void;
105
106
  private applyTemplate;
106
107
  private applyPartiPlaceholders;
@@ -43,7 +43,11 @@ class DocumentGenerator {
43
43
  return template.replace(/\$(\w+)\$/g, (match, key) => dynamicFields[key] !== undefined ? dynamicFields[key] : match);
44
44
  }
45
45
  applyPartiPlaceholders(text, parti) {
46
- return text.replace(/\$(fornitore|cliente):(\w+)\$/g, (match, party, field) => (parti[party] && parti[party][field]) ? parti[party][field] : match);
46
+ return text.replace(/\$(fornitore|cliente):(\w+)\$/g, (match, party, field) => {
47
+ const partyData = parti[party];
48
+ const value = partyData === null || partyData === void 0 ? void 0 : partyData[field];
49
+ return value !== null && value !== void 0 ? value : match;
50
+ });
47
51
  }
48
52
  loadConfig() {
49
53
  return __awaiter(this, void 0, void 0, function* () {
@@ -68,8 +72,9 @@ class DocumentGenerator {
68
72
  this.curY = margins.alto;
69
73
  }
70
74
  extractPlaceholder(text) {
75
+ var _a;
71
76
  const match = text.match(/^\$(\w+)\$$/);
72
- return match ? match[1] : null;
77
+ return match ? ((_a = match[1]) !== null && _a !== void 0 ? _a : null) : null;
73
78
  }
74
79
  installFont(fontPath, fontName) {
75
80
  return __awaiter(this, void 0, void 0, function* () {
@@ -108,8 +113,8 @@ class DocumentGenerator {
108
113
  });
109
114
  }
110
115
  // Writes a single line with inline bold processing.
111
- writeLineWithInlineBold(line_1, x_1, y_1, normalFont_1, fontSize_1, color_1, maxWidth_1) {
112
- return __awaiter(this, arguments, void 0, function* (line, x, y, normalFont, fontSize, color, maxWidth, lineSpacingFactor = 1.15) {
116
+ writeLineWithInlineBold(line_1, x_1, y_1, normalFont_1, fontSize_1, color_1, _maxWidth_1) {
117
+ return __awaiter(this, arguments, void 0, function* (line, x, y, normalFont, fontSize, color, _maxWidth, lineSpacingFactor = 1.15) {
113
118
  let currentX = x;
114
119
  // Split the line by bold segments. The regex keeps the markers.
115
120
  const segments = line.split(/(\*\*.*?\*\*)/);
@@ -310,7 +315,12 @@ class DocumentGenerator {
310
315
  this.curY += this.config.staccoriga;
311
316
  }
312
317
  const tipOutput = params.tipOutput || 'd';
313
- const fileName = `Documento_${params.parti.cliente.denominazione}.pdf`;
318
+ // Sanitizza il nome: evita path traversal e caratteri non validi nel filesystem.
319
+ const safeDenominazione = params.parti.cliente.denominazione
320
+ .replace(/[\\/:*?"<>|\u0000-\u001f]/g, '_')
321
+ .replace(/\.+$/, '')
322
+ .trim() || 'cliente';
323
+ const fileName = `Documento_${safeDenominazione}.pdf`;
314
324
  if (tipOutput === 'd') {
315
325
  const pdfBuffer = this.doc.output('arraybuffer');
316
326
  yield fs_1.promises.writeFile(fileName, Buffer.from(pdfBuffer));
@@ -1 +1 @@
1
- {"version":3,"file":"ContractGenerator.js","sourceRoot":"","sources":["../src/ContractGenerator.ts"],"names":[],"mappings":"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","sourcesContent":["import { jsPDF } from \"jspdf\";\nimport autotable from \"jspdf-autotable\";\nimport { promises as fs } from 'fs';\nimport path from 'path';\n\nexport interface IPartiContratto {\n fornitore: { denominazione: string; codiceFiscale: string; indirizzoCompleto: string; };\n cliente: { denominazione: string; codiceFiscale: string; indirizzoCompleto: string; };\n}\n\nexport interface DocumentParams {\n parti: IPartiContratto;\n tipOutput?: 'f' | 'd' | 'u';\n dynamicFields?: { [key: string]: string };\n dynamicElements?: { [placeholder: string]: DynamicElement };\n}\n\nexport type DynamicElement = {\n type: 'table';\n config: {\n head: string[];\n body: string[][];\n options?: any;\n styles?: any;\n };\n};\n\ninterface DocumentConfig {\n fontTitolo: { nome: string; dimensione: number; colore: string; installPath?: string; };\n fontSottotitolo: { nome: string; dimensione: number; colore: string; installPath?: string; };\n fontTesto: { nome: string; dimensione: number; colore: string; installPath?: string; };\n fontBold: { nome: string; dimensione: number; colore: string; installPath?: string; };\n margini: { sx: number; dx: number; alto: number; basso: number; };\n staccoriga: number;\n rientro: number;\n testi: {\n titolo: string;\n premessa: string;\n Punti: Array<{ titolo: string; Sottopunti: Array<{ titolo: string; contenuto: string; }>; }>;\n versione: string;\n };\n immagini: Array<{ path: string; posizione: [number, number]; dimensioni: [number, number]; coeffDim?: number; }>;\n box: { backgrund: string; raggio: number; };\n tableStyle?: { lineColor?: string; lineWidth?: number; font?: string; fontSize?: number; cellPadding?: number; fillColor?: string; };\n}\n\nasync function loadImageAsBase64(imagePath: string): Promise<string> {\n const absolutePath = path.resolve(imagePath);\n const buffer = await fs.readFile(absolutePath);\n const ext = path.extname(imagePath).slice(1).toLowerCase();\n const base64 = buffer.toString('base64');\n return `data:image/${ext};base64,${base64}`;\n}\n\nexport class DocumentGenerator {\n private config!: DocumentConfig;\n private doc!: jsPDF;\n private curX: number = 0;\n private curY: number = 0;\n private configLoaded: boolean = false;\n\n constructor(private configPath?: string) { }\n\n public setConfig(config: DocumentConfig) {\n this.config = config;\n this.configLoaded = true;\n }\n\n private applyTemplate(template: string, dynamicFields?: { [key: string]: string }): string {\n if (!dynamicFields) return template;\n return template.replace(/\\$(\\w+)\\$/g, (match, key) =>\n dynamicFields[key] !== undefined ? dynamicFields[key] : match\n );\n }\n\n private applyPartiPlaceholders(text: string, parti: IPartiContratto): string {\n return text.replace(/\\$(fornitore|cliente):(\\w+)\\$/g, (match, party, field) =>\n (parti[party] && (parti[party] as any)[field]) ? (parti[party] as any)[field] : match\n );\n }\n\n private async loadConfig(): Promise<void> {\n if (this.configLoaded) return;\n if (!this.configPath) throw new Error(\"No configuration provided.\");\n try {\n const data = await fs.readFile(this.configPath, 'utf8');\n this.config = JSON.parse(data) as DocumentConfig;\n this.configLoaded = true;\n } catch (error) {\n throw new Error(`Error reading configuration file: ${error}`);\n }\n }\n\n private initDoc(): void {\n this.doc = new jsPDF();\n const margins = this.config.margini;\n this.curX = margins.sx;\n this.curY = margins.alto;\n }\n\n private extractPlaceholder(text: string): string | null {\n const match = text.match(/^\\$(\\w+)\\$$/);\n return match ? match[1] : null;\n }\n\n private async installFont(fontPath: string, fontName: string): Promise<void> {\n const absolutePath = path.resolve(fontPath);\n const buffer = await fs.readFile(absolutePath);\n const base64Font = buffer.toString('base64');\n //console.log(`Installing font ${fontName} from ${absolutePath}`);\n this.doc.addFileToVFS(`${fontName}.ttf`, base64Font);\n this.doc.addFont(`${fontName}.ttf`, fontName, 'normal');\n this.doc.setFont(fontName);\n }\n\n // Writes wrapped text, handling inline bold segments.\n private async writeWrappedTextCore(\n fontName: string,\n fontSize: number,\n color: string,\n text: string,\n x: number,\n y: number,\n maxWidth: number,\n lineSpacingFactor: number = 1.15\n ): Promise<number> {\n this.doc.setFont(fontName);\n this.doc.setFontSize(fontSize);\n this.doc.setTextColor(color);\n const lines = this.doc.splitTextToSize(text, maxWidth);\n const lineHeight = (fontSize * lineSpacingFactor / 72) * 25.4;\n for (const line of lines) {\n if (y + lineHeight > (this.doc.internal.pageSize.getHeight() - this.config.margini.basso)) {\n this.doc.addPage();\n y = this.config.margini.alto;\n }\n // If the line contains inline bold markers, process them.\n if (line.includes(\"**\")) {\n y = await this.writeLineWithInlineBold(line, x, y, fontName, fontSize, color, maxWidth, lineSpacingFactor);\n } else {\n this.doc.text(line, x, y);\n y += lineHeight;\n }\n }\n return y;\n }\n\n // Writes a single line with inline bold processing.\n private async writeLineWithInlineBold(\n line: string,\n x: number,\n y: number,\n normalFont: string,\n fontSize: number,\n color: string,\n maxWidth: number,\n lineSpacingFactor: number = 1.15\n ): Promise<number> {\n let currentX = x;\n // Split the line by bold segments. The regex keeps the markers.\n const segments = line.split(/(\\*\\*.*?\\*\\*)/);\n const lineHeight = (fontSize * lineSpacingFactor / 72) * 25.4;\n for (const seg of segments) {\n let segText = seg;\n let useBold = false;\n if (seg.startsWith(\"**\") && seg.endsWith(\"**\")) {\n useBold = true;\n segText = seg.substring(2, seg.length - 2);\n }\n if (useBold) {\n this.doc.setFont(this.config.fontBold.nome);\n } else {\n this.doc.setFont(normalFont);\n }\n this.doc.setFontSize(fontSize);\n this.doc.setTextColor(color);\n const segWidth = this.doc.getTextWidth(segText);\n // Write segment\n this.doc.text(segText, currentX, y);\n currentX += segWidth;\n }\n return y + lineHeight;\n }\n\n private async writeWrappedTextWithFont(\n fontConf: { nome: string; dimensione: number; colore: string; installPath?: string },\n text: string,\n x: number,\n y: number,\n maxWidth: number,\n lineSpacingFactor: number = 1.15\n ): Promise<void> {\n const fontList = this.doc.getFontList();\n if (!fontList[fontConf.nome]) {\n if (fontConf.installPath) await this.installFont(fontConf.installPath, fontConf.nome);\n else throw new Error(\"Font not present and no installPath provided\");\n } else {\n this.doc.setFont(fontConf.nome);\n }\n this.curY = await this.writeWrappedTextCore(fontConf.nome, fontConf.dimensione, fontConf.colore, text, x, y, maxWidth, lineSpacingFactor);\n }\n\n public async writeBoxedText(\n text: string,\n fontConf: { nome: string; dimensione: number; colore: string; installPath?: string },\n padding: number = 5,\n borderRadius: number = 5,\n borderWidth: number = 1,\n boxColor?: string\n ): Promise<void> {\n const fontList = this.doc.getFontList();\n if (!fontList[fontConf.nome]) {\n if (fontConf.installPath) await this.installFont(fontConf.installPath, fontConf.nome);\n else throw new Error(\"Font not present and no installPath provided\");\n } else {\n this.doc.setFont(fontConf.nome);\n }\n this.doc.setFontSize(fontConf.dimensione);\n this.doc.setTextColor(fontConf.colore);\n const pageWidth = this.doc.internal.pageSize.getWidth();\n const maxTextWidth = pageWidth - this.config.margini.sx - this.config.margini.dx - 2 * padding;\n const lines = this.doc.splitTextToSize(text, maxTextWidth);\n const lineHeight = (fontConf.dimensione * 1.15 / 72) * 25.4;\n const textHeight = lines.length * lineHeight;\n const boxX = this.curX;\n const boxY = this.curY;\n const boxWidth = maxTextWidth + 2 * padding;\n const boxHeight = textHeight + 2 * padding;\n if (boxColor) {\n this.doc.setFillColor(boxColor);\n this.doc.roundedRect(boxX, boxY, boxWidth, boxHeight, borderRadius, borderRadius, \"F\");\n }\n this.doc.setLineWidth(borderWidth);\n this.doc.roundedRect(boxX, boxY, boxWidth, boxHeight, borderRadius, borderRadius);\n const textX = boxX + padding;\n let textY = boxY + padding + lineHeight;\n for (const line of lines) {\n if (line.includes(\"**\")) {\n textY = await this.writeLineWithInlineBold(line, textX, textY, fontConf.nome, fontConf.dimensione, fontConf.colore, maxTextWidth, 1.15);\n } else {\n this.doc.text(line, textX, textY);\n textY += lineHeight;\n }\n }\n this.curY = boxY + boxHeight + this.config.staccoriga;\n }\n\n\n // Checks if text is wrapped in '^' markers for boxed text.\n private isBoxedText(text: string): boolean {\n return text.startsWith('^') && text.endsWith('^');\n }\n\n // Removes '^' markers.\n private stripBoxMarkers(text: string): string {\n return text.substring(1, text.length - 1);\n }\n\n // Checks if text is entirely wrapped in '**' markers (not inline).\n // (This function is kept for backward compatibility.)\n private isBoldText(text: string): boolean {\n return text.startsWith('**') && text.endsWith('**');\n }\n\n // Removes '**' markers.\n private stripBoldMarkers(text: string): string {\n return text.substring(2, text.length - 2);\n }\n\n // Inserts images using the current cursor position.\n private async insertLogo(): Promise<void> {\n if (this.config.immagini && this.config.immagini.length > 0) {\n const startX = this.curX;\n for (const imgConf of this.config.immagini) {\n const format = imgConf.path.split('.').pop()?.toUpperCase() || 'PNG';\n const base64Image = await loadImageAsBase64(imgConf.path);\n const startY = this.curY;\n if (startY + imgConf.dimensioni[1] > (this.doc.internal.pageSize.getHeight() - this.config.margini.basso)) {\n this.doc.addPage();\n this.curY = this.config.margini.alto;\n }\n this.doc.addImage(base64Image, format, startX, this.curY, imgConf.dimensioni[0], imgConf.dimensioni[1]);\n //console.log(`Image inserted at X: ${startX}, Y: ${this.curY}`);\n this.curY = this.curY + imgConf.dimensioni[1] + this.config.staccoriga;\n }\n }\n }\n\n // Generates the PDF document by processing images, dynamic fields, tables, and text.\n // Supports inline bold formatting and boxed text.\n public async generateDocument(params: DocumentParams): Promise<string | ArrayBuffer> {\n await this.loadConfig();\n this.initDoc();\n await this.insertLogo();\n const dynamicFields = params.dynamicFields || {};\n const dynamicElements = params.dynamicElements || {};\n const pageWidth = this.doc.internal.pageSize.getWidth();\n const maxWidth = pageWidth - (this.config.margini.sx + this.config.margini.dx);\n let titolo = this.applyTemplate(this.config.testi.titolo, dynamicFields);\n titolo = this.applyPartiPlaceholders(titolo, params.parti);\n await this.writeWrappedTextWithFont(this.config.fontTitolo, titolo, this.curX, this.curY, maxWidth);\n this.curY += this.config.staccoriga;\n let premessa = this.applyTemplate(this.config.testi.premessa, dynamicFields);\n premessa = this.applyPartiPlaceholders(premessa, params.parti);\n await this.writeWrappedTextWithFont(this.config.fontTesto, premessa, this.curX, this.curY, maxWidth);\n this.curY += this.config.staccoriga;\n for (const punto of this.config.testi.Punti) {\n let puntoTitolo = this.applyTemplate(punto.titolo, dynamicFields);\n puntoTitolo = this.applyPartiPlaceholders(puntoTitolo, params.parti);\n await this.writeWrappedTextWithFont(this.config.fontTitolo, puntoTitolo, this.curX, this.curY, maxWidth);\n this.curY += this.config.staccoriga;\n for (const sub of punto.Sottopunti) {\n const placeholder = this.extractPlaceholder(sub.titolo);\n if (placeholder && dynamicElements[placeholder] && dynamicElements[placeholder].type === 'table' && dynamicElements[placeholder].config) {\n const tableConfig = dynamicElements[placeholder].config!;\n const defaultTableOptions = this.config.tableStyle || {};\n autotable(this.doc, {\n startY: this.curY,\n head: [tableConfig.head],\n body: tableConfig.body,\n ...defaultTableOptions,\n ...tableConfig.options,\n ...tableConfig.styles\n });\n this.curY = (this.doc as any).lastAutoTable.finalY + this.config.staccoriga;\n } else {\n if (sub.titolo) {\n let titleText = this.applyTemplate(sub.titolo, dynamicFields);\n titleText = this.applyPartiPlaceholders(titleText, params.parti);\n if (this.isBoxedText(titleText)) {\n const boxText = this.stripBoxMarkers(titleText);\n await this.writeBoxedText(boxText, this.config.fontSottotitolo);\n } else if (this.isBoldText(titleText)) {\n const boldText = this.stripBoldMarkers(titleText);\n\n await this.writeWrappedTextWithFont({ ...this.config.fontSottotitolo, nome: this.config.fontSottotitolo.nome },\n boldText, this.curX + this.config.rientro, this.curY, maxWidth - this.config.rientro);\n } else {\n await this.writeWrappedTextWithFont(this.config.fontSottotitolo, titleText, this.curX + this.config.rientro, this.curY, maxWidth - this.config.rientro);\n }\n this.curY += this.config.staccoriga;\n }\n }\n const contentPlaceholder = this.extractPlaceholder(sub.contenuto);\n if (contentPlaceholder && dynamicElements[contentPlaceholder] && dynamicElements[contentPlaceholder].type === 'table' && dynamicElements[contentPlaceholder].config) {\n const tableConfig = dynamicElements[contentPlaceholder].config!;\n const defaultTableOptions = this.config.tableStyle || {};\n autotable(this.doc, {\n startY: this.curY,\n head: [tableConfig.head],\n body: tableConfig.body,\n ...defaultTableOptions,\n ...tableConfig.options,\n ...tableConfig.styles\n });\n this.curY = (this.doc as any).lastAutoTable.finalY + this.config.staccoriga;\n } else if (sub.contenuto) {\n let contenuto = this.applyTemplate(sub.contenuto, dynamicFields);\n contenuto = this.applyPartiPlaceholders(contenuto, params.parti);\n if (this.isBoxedText(contenuto)) {\n const boxText = this.stripBoxMarkers(contenuto);\n await this.writeBoxedText(boxText, this.config.fontTesto);\n } else if (this.isBoldText(contenuto)) {\n const boldText = this.stripBoldMarkers(contenuto);\n await this.writeWrappedTextWithFont({ ...this.config.fontTesto, nome: this.config.fontTesto.nome },\n boldText, this.curX + this.config.rientro, this.curY, maxWidth - this.config.rientro);\n } else {\n await this.writeWrappedTextWithFont(this.config.fontTesto, contenuto, this.curX + this.config.rientro, this.curY, maxWidth - this.config.rientro);\n }\n this.curY += this.config.staccoriga;\n }\n }\n this.curY += this.config.staccoriga;\n }\n const tipOutput = params.tipOutput || 'd';\n const fileName = `Documento_${params.parti.cliente.denominazione}.pdf`;\n if (tipOutput === 'd') {\n const pdfBuffer = this.doc.output('arraybuffer');\n await fs.writeFile(fileName, Buffer.from(pdfBuffer));\n return fileName;\n } else if (tipOutput === 'u') {\n return this.doc.output('arraybuffer');\n } else {\n return this.doc.output('arraybuffer');\n }\n }\n}"]}
1
+ {"version":3,"file":"ContractGenerator.js","sourceRoot":"","sources":["../src/ContractGenerator.ts"],"names":[],"mappings":"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","sourcesContent":["import { jsPDF } from \"jspdf\";\nimport autotable, { Styles, UserOptions } from \"jspdf-autotable\";\nimport { promises as fs } from 'fs';\nimport path from 'path';\n\nexport interface IPartiContratto {\n fornitore: { denominazione: string; codiceFiscale: string; indirizzoCompleto: string; };\n cliente: { denominazione: string; codiceFiscale: string; indirizzoCompleto: string; };\n}\n\nexport interface DocumentParams {\n parti: IPartiContratto;\n tipOutput?: 'f' | 'd' | 'u';\n dynamicFields?: { [key: string]: string };\n dynamicElements?: { [placeholder: string]: DynamicElement };\n}\n\nexport type DynamicElement = {\n type: 'table';\n config: {\n head: string[];\n body: string[][];\n options?: UserOptions;\n styles?: Partial<Styles>;\n };\n};\n\ninterface DocumentConfig {\n fontTitolo: { nome: string; dimensione: number; colore: string; installPath?: string; };\n fontSottotitolo: { nome: string; dimensione: number; colore: string; installPath?: string; };\n fontTesto: { nome: string; dimensione: number; colore: string; installPath?: string; };\n fontBold: { nome: string; dimensione: number; colore: string; installPath?: string; };\n margini: { sx: number; dx: number; alto: number; basso: number; };\n staccoriga: number;\n rientro: number;\n testi: {\n titolo: string;\n premessa: string;\n Punti: Array<{ titolo: string; Sottopunti: Array<{ titolo: string; contenuto: string; }>; }>;\n versione: string;\n };\n immagini: Array<{ path: string; posizione: [number, number]; dimensioni: [number, number]; coeffDim?: number; }>;\n box: { backgrund: string; raggio: number; };\n tableStyle?: { lineColor?: string; lineWidth?: number; font?: string; fontSize?: number; cellPadding?: number; fillColor?: string; };\n}\n\nasync function loadImageAsBase64(imagePath: string): Promise<string> {\n const absolutePath = path.resolve(imagePath);\n const buffer = await fs.readFile(absolutePath);\n const ext = path.extname(imagePath).slice(1).toLowerCase();\n const base64 = buffer.toString('base64');\n return `data:image/${ext};base64,${base64}`;\n}\n\nexport class DocumentGenerator {\n private config!: DocumentConfig;\n private doc!: jsPDF;\n private curX: number = 0;\n private curY: number = 0;\n private configLoaded: boolean = false;\n\n constructor(private configPath?: string) { }\n\n public setConfig(config: DocumentConfig) {\n this.config = config;\n this.configLoaded = true;\n }\n\n private applyTemplate(template: string, dynamicFields?: { [key: string]: string }): string {\n if (!dynamicFields) return template;\n return template.replace(/\\$(\\w+)\\$/g, (match, key) =>\n dynamicFields[key] !== undefined ? dynamicFields[key] : match\n );\n }\n\n private applyPartiPlaceholders(text: string, parti: IPartiContratto): string {\n return text.replace(/\\$(fornitore|cliente):(\\w+)\\$/g, (match: string, party: string, field: string) => {\n const partyData = (parti as unknown as Record<string, Record<string, string> | undefined>)[party];\n const value = partyData?.[field];\n return value ?? match;\n });\n }\n\n private async loadConfig(): Promise<void> {\n if (this.configLoaded) return;\n if (!this.configPath) throw new Error(\"No configuration provided.\");\n try {\n const data = await fs.readFile(this.configPath, 'utf8');\n this.config = JSON.parse(data) as DocumentConfig;\n this.configLoaded = true;\n } catch (error) {\n throw new Error(`Error reading configuration file: ${error}`);\n }\n }\n\n private initDoc(): void {\n this.doc = new jsPDF();\n const margins = this.config.margini;\n this.curX = margins.sx;\n this.curY = margins.alto;\n }\n\n private extractPlaceholder(text: string): string | null {\n const match = text.match(/^\\$(\\w+)\\$$/);\n return match ? (match[1] ?? null) : null;\n }\n\n private async installFont(fontPath: string, fontName: string): Promise<void> {\n const absolutePath = path.resolve(fontPath);\n const buffer = await fs.readFile(absolutePath);\n const base64Font = buffer.toString('base64');\n //console.log(`Installing font ${fontName} from ${absolutePath}`);\n this.doc.addFileToVFS(`${fontName}.ttf`, base64Font);\n this.doc.addFont(`${fontName}.ttf`, fontName, 'normal');\n this.doc.setFont(fontName);\n }\n\n // Writes wrapped text, handling inline bold segments.\n private async writeWrappedTextCore(\n fontName: string,\n fontSize: number,\n color: string,\n text: string,\n x: number,\n y: number,\n maxWidth: number,\n lineSpacingFactor: number = 1.15\n ): Promise<number> {\n this.doc.setFont(fontName);\n this.doc.setFontSize(fontSize);\n this.doc.setTextColor(color);\n const lines = this.doc.splitTextToSize(text, maxWidth);\n const lineHeight = (fontSize * lineSpacingFactor / 72) * 25.4;\n for (const line of lines) {\n if (y + lineHeight > (this.doc.internal.pageSize.getHeight() - this.config.margini.basso)) {\n this.doc.addPage();\n y = this.config.margini.alto;\n }\n // If the line contains inline bold markers, process them.\n if (line.includes(\"**\")) {\n y = await this.writeLineWithInlineBold(line, x, y, fontName, fontSize, color, maxWidth, lineSpacingFactor);\n } else {\n this.doc.text(line, x, y);\n y += lineHeight;\n }\n }\n return y;\n }\n\n // Writes a single line with inline bold processing.\n private async writeLineWithInlineBold(\n line: string,\n x: number,\n y: number,\n normalFont: string,\n fontSize: number,\n color: string,\n _maxWidth: number,\n lineSpacingFactor: number = 1.15\n ): Promise<number> {\n let currentX = x;\n // Split the line by bold segments. The regex keeps the markers.\n const segments = line.split(/(\\*\\*.*?\\*\\*)/);\n const lineHeight = (fontSize * lineSpacingFactor / 72) * 25.4;\n for (const seg of segments) {\n let segText = seg;\n let useBold = false;\n if (seg.startsWith(\"**\") && seg.endsWith(\"**\")) {\n useBold = true;\n segText = seg.substring(2, seg.length - 2);\n }\n if (useBold) {\n this.doc.setFont(this.config.fontBold.nome);\n } else {\n this.doc.setFont(normalFont);\n }\n this.doc.setFontSize(fontSize);\n this.doc.setTextColor(color);\n const segWidth = this.doc.getTextWidth(segText);\n // Write segment\n this.doc.text(segText, currentX, y);\n currentX += segWidth;\n }\n return y + lineHeight;\n }\n\n private async writeWrappedTextWithFont(\n fontConf: { nome: string; dimensione: number; colore: string; installPath?: string },\n text: string,\n x: number,\n y: number,\n maxWidth: number,\n lineSpacingFactor: number = 1.15\n ): Promise<void> {\n const fontList = this.doc.getFontList();\n if (!fontList[fontConf.nome]) {\n if (fontConf.installPath) await this.installFont(fontConf.installPath, fontConf.nome);\n else throw new Error(\"Font not present and no installPath provided\");\n } else {\n this.doc.setFont(fontConf.nome);\n }\n this.curY = await this.writeWrappedTextCore(fontConf.nome, fontConf.dimensione, fontConf.colore, text, x, y, maxWidth, lineSpacingFactor);\n }\n\n public async writeBoxedText(\n text: string,\n fontConf: { nome: string; dimensione: number; colore: string; installPath?: string },\n padding: number = 5,\n borderRadius: number = 5,\n borderWidth: number = 1,\n boxColor?: string\n ): Promise<void> {\n const fontList = this.doc.getFontList();\n if (!fontList[fontConf.nome]) {\n if (fontConf.installPath) await this.installFont(fontConf.installPath, fontConf.nome);\n else throw new Error(\"Font not present and no installPath provided\");\n } else {\n this.doc.setFont(fontConf.nome);\n }\n this.doc.setFontSize(fontConf.dimensione);\n this.doc.setTextColor(fontConf.colore);\n const pageWidth = this.doc.internal.pageSize.getWidth();\n const maxTextWidth = pageWidth - this.config.margini.sx - this.config.margini.dx - 2 * padding;\n const lines = this.doc.splitTextToSize(text, maxTextWidth);\n const lineHeight = (fontConf.dimensione * 1.15 / 72) * 25.4;\n const textHeight = lines.length * lineHeight;\n const boxX = this.curX;\n const boxY = this.curY;\n const boxWidth = maxTextWidth + 2 * padding;\n const boxHeight = textHeight + 2 * padding;\n if (boxColor) {\n this.doc.setFillColor(boxColor);\n this.doc.roundedRect(boxX, boxY, boxWidth, boxHeight, borderRadius, borderRadius, \"F\");\n }\n this.doc.setLineWidth(borderWidth);\n this.doc.roundedRect(boxX, boxY, boxWidth, boxHeight, borderRadius, borderRadius);\n const textX = boxX + padding;\n let textY = boxY + padding + lineHeight;\n for (const line of lines) {\n if (line.includes(\"**\")) {\n textY = await this.writeLineWithInlineBold(line, textX, textY, fontConf.nome, fontConf.dimensione, fontConf.colore, maxTextWidth, 1.15);\n } else {\n this.doc.text(line, textX, textY);\n textY += lineHeight;\n }\n }\n this.curY = boxY + boxHeight + this.config.staccoriga;\n }\n\n\n // Checks if text is wrapped in '^' markers for boxed text.\n private isBoxedText(text: string): boolean {\n return text.startsWith('^') && text.endsWith('^');\n }\n\n // Removes '^' markers.\n private stripBoxMarkers(text: string): string {\n return text.substring(1, text.length - 1);\n }\n\n // Checks if text is entirely wrapped in '**' markers (not inline).\n // (This function is kept for backward compatibility.)\n private isBoldText(text: string): boolean {\n return text.startsWith('**') && text.endsWith('**');\n }\n\n // Removes '**' markers.\n private stripBoldMarkers(text: string): string {\n return text.substring(2, text.length - 2);\n }\n\n // Inserts images using the current cursor position.\n private async insertLogo(): Promise<void> {\n if (this.config.immagini && this.config.immagini.length > 0) {\n const startX = this.curX;\n for (const imgConf of this.config.immagini) {\n const format = imgConf.path.split('.').pop()?.toUpperCase() || 'PNG';\n const base64Image = await loadImageAsBase64(imgConf.path);\n const startY = this.curY;\n if (startY + imgConf.dimensioni[1] > (this.doc.internal.pageSize.getHeight() - this.config.margini.basso)) {\n this.doc.addPage();\n this.curY = this.config.margini.alto;\n }\n this.doc.addImage(base64Image, format, startX, this.curY, imgConf.dimensioni[0], imgConf.dimensioni[1]);\n //console.log(`Image inserted at X: ${startX}, Y: ${this.curY}`);\n this.curY = this.curY + imgConf.dimensioni[1] + this.config.staccoriga;\n }\n }\n }\n\n // Generates the PDF document by processing images, dynamic fields, tables, and text.\n // Supports inline bold formatting and boxed text.\n public async generateDocument(params: DocumentParams): Promise<string | ArrayBuffer> {\n await this.loadConfig();\n this.initDoc();\n await this.insertLogo();\n const dynamicFields = params.dynamicFields || {};\n const dynamicElements = params.dynamicElements || {};\n const pageWidth = this.doc.internal.pageSize.getWidth();\n const maxWidth = pageWidth - (this.config.margini.sx + this.config.margini.dx);\n let titolo = this.applyTemplate(this.config.testi.titolo, dynamicFields);\n titolo = this.applyPartiPlaceholders(titolo, params.parti);\n await this.writeWrappedTextWithFont(this.config.fontTitolo, titolo, this.curX, this.curY, maxWidth);\n this.curY += this.config.staccoriga;\n let premessa = this.applyTemplate(this.config.testi.premessa, dynamicFields);\n premessa = this.applyPartiPlaceholders(premessa, params.parti);\n await this.writeWrappedTextWithFont(this.config.fontTesto, premessa, this.curX, this.curY, maxWidth);\n this.curY += this.config.staccoriga;\n for (const punto of this.config.testi.Punti) {\n let puntoTitolo = this.applyTemplate(punto.titolo, dynamicFields);\n puntoTitolo = this.applyPartiPlaceholders(puntoTitolo, params.parti);\n await this.writeWrappedTextWithFont(this.config.fontTitolo, puntoTitolo, this.curX, this.curY, maxWidth);\n this.curY += this.config.staccoriga;\n for (const sub of punto.Sottopunti) {\n const placeholder = this.extractPlaceholder(sub.titolo);\n if (placeholder && dynamicElements[placeholder] && dynamicElements[placeholder].type === 'table' && dynamicElements[placeholder].config) {\n const tableConfig = dynamicElements[placeholder].config!;\n const defaultTableOptions = this.config.tableStyle || {};\n autotable(this.doc, {\n startY: this.curY,\n head: [tableConfig.head],\n body: tableConfig.body,\n ...defaultTableOptions,\n ...tableConfig.options,\n ...tableConfig.styles\n });\n this.curY = ((this.doc as unknown) as { lastAutoTable: { finalY: number } }).lastAutoTable.finalY + this.config.staccoriga;\n } else {\n if (sub.titolo) {\n let titleText = this.applyTemplate(sub.titolo, dynamicFields);\n titleText = this.applyPartiPlaceholders(titleText, params.parti);\n if (this.isBoxedText(titleText)) {\n const boxText = this.stripBoxMarkers(titleText);\n await this.writeBoxedText(boxText, this.config.fontSottotitolo);\n } else if (this.isBoldText(titleText)) {\n const boldText = this.stripBoldMarkers(titleText);\n\n await this.writeWrappedTextWithFont({ ...this.config.fontSottotitolo, nome: this.config.fontSottotitolo.nome },\n boldText, this.curX + this.config.rientro, this.curY, maxWidth - this.config.rientro);\n } else {\n await this.writeWrappedTextWithFont(this.config.fontSottotitolo, titleText, this.curX + this.config.rientro, this.curY, maxWidth - this.config.rientro);\n }\n this.curY += this.config.staccoriga;\n }\n }\n const contentPlaceholder = this.extractPlaceholder(sub.contenuto);\n if (contentPlaceholder && dynamicElements[contentPlaceholder] && dynamicElements[contentPlaceholder].type === 'table' && dynamicElements[contentPlaceholder].config) {\n const tableConfig = dynamicElements[contentPlaceholder].config!;\n const defaultTableOptions = this.config.tableStyle || {};\n autotable(this.doc, {\n startY: this.curY,\n head: [tableConfig.head],\n body: tableConfig.body,\n ...defaultTableOptions,\n ...tableConfig.options,\n ...tableConfig.styles\n });\n this.curY = ((this.doc as unknown) as { lastAutoTable: { finalY: number } }).lastAutoTable.finalY + this.config.staccoriga;\n } else if (sub.contenuto) {\n let contenuto = this.applyTemplate(sub.contenuto, dynamicFields);\n contenuto = this.applyPartiPlaceholders(contenuto, params.parti);\n if (this.isBoxedText(contenuto)) {\n const boxText = this.stripBoxMarkers(contenuto);\n await this.writeBoxedText(boxText, this.config.fontTesto);\n } else if (this.isBoldText(contenuto)) {\n const boldText = this.stripBoldMarkers(contenuto);\n await this.writeWrappedTextWithFont({ ...this.config.fontTesto, nome: this.config.fontTesto.nome },\n boldText, this.curX + this.config.rientro, this.curY, maxWidth - this.config.rientro);\n } else {\n await this.writeWrappedTextWithFont(this.config.fontTesto, contenuto, this.curX + this.config.rientro, this.curY, maxWidth - this.config.rientro);\n }\n this.curY += this.config.staccoriga;\n }\n }\n this.curY += this.config.staccoriga;\n }\n const tipOutput = params.tipOutput || 'd';\n // Sanitizza il nome: evita path traversal e caratteri non validi nel filesystem.\n const safeDenominazione = params.parti.cliente.denominazione\n .replace(/[\\\\/:*?\"<>|\\u0000-\\u001f]/g, '_')\n .replace(/\\.+$/, '')\n .trim() || 'cliente';\n const fileName = `Documento_${safeDenominazione}.pdf`;\n if (tipOutput === 'd') {\n const pdfBuffer = this.doc.output('arraybuffer');\n await fs.writeFile(fileName, Buffer.from(pdfBuffer));\n return fileName;\n } else if (tipOutput === 'u') {\n return this.doc.output('arraybuffer');\n } else {\n return this.doc.output('arraybuffer');\n }\n }\n}\n"]}
@@ -1,4 +1,9 @@
1
1
  import Transport from 'winston-transport';
2
+ type LogInfo = {
3
+ time?: Date;
4
+ [key: string]: unknown;
5
+ [key: symbol]: unknown;
6
+ };
2
7
  /** One append-only JSON-lines file per local calendar day, including idle days. */
3
8
  export declare class DailyFileTransport extends Transport {
4
9
  private readonly directory;
@@ -7,9 +12,10 @@ export declare class DailyFileTransport extends Transport {
7
12
  private filename;
8
13
  private touchToday;
9
14
  private scheduleMidnight;
10
- log(info: any, callback: (error?: Error | null) => void): void;
15
+ log(info: LogInfo, callback: (error?: Error | null) => void): void;
11
16
  close(): void;
12
17
  logv(chunks: {
13
- chunk: any;
18
+ chunk: LogInfo;
14
19
  }[], callback: (error?: Error | null) => void): void;
15
20
  }
21
+ export {};
@@ -32,7 +32,10 @@ class DailyFileTransport extends winston_transport_1.default {
32
32
  this.touchToday();
33
33
  }
34
34
  catch (error) {
35
- this.emit('error', error);
35
+ // `emit('error')` senza listener farebbe crashare il processo: emetti solo se osservato.
36
+ if (this.listenerCount('error') > 0) {
37
+ this.emit('error', error);
38
+ }
36
39
  }
37
40
  finally {
38
41
  this.scheduleMidnight();
@@ -58,7 +61,11 @@ class DailyFileTransport extends winston_transport_1.default {
58
61
  const next = (error) => {
59
62
  if (error || index === chunks.length)
60
63
  return callback(error);
61
- this.log(chunks[index++].chunk, next);
64
+ const chunk = chunks[index];
65
+ index += 1;
66
+ if (!chunk)
67
+ return callback(error);
68
+ this.log(chunk.chunk, next);
62
69
  };
63
70
  next();
64
71
  }
@@ -1 +1 @@
1
- {"version":3,"file":"DailyFileTransport.js","sourceRoot":"","sources":["../src/DailyFileTransport.ts"],"names":[],"mappings":"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","sourcesContent":["import Transport from 'winston-transport';\nimport { appendFile, appendFileSync, mkdirSync } from 'fs';\nimport { join } from 'path';\n\n/** One append-only JSON-lines file per local calendar day, including idle days. */\nexport class DailyFileTransport extends Transport {\n private timer?: NodeJS.Timeout;\n\n constructor(private readonly directory: string) {\n super();\n mkdirSync(directory, { recursive: true });\n this.touchToday();\n this.scheduleMidnight();\n }\n\n private filename(date: Date): string {\n const month = String(date.getMonth() + 1).padStart(2, '0');\n const day = String(date.getDate()).padStart(2, '0');\n return join(this.directory, `${date.getFullYear()}-${month}-${day}.json`);\n }\n\n private touchToday(): void {\n appendFileSync(this.filename(new Date()), '', { flag: 'a' });\n }\n\n private scheduleMidnight(): void {\n const now = new Date();\n const midnight = new Date(now.getFullYear(), now.getMonth(), now.getDate() + 1);\n this.timer = setTimeout(() => {\n try {\n this.touchToday();\n } catch (error) {\n this.emit('error', error);\n } finally {\n this.scheduleMidnight();\n }\n }, Math.max(1, midnight.getTime() - now.getTime()));\n this.timer.unref();\n }\n\n log(info: any, callback: (error?: Error | null) => void): void {\n // Capture the event's day even when the transport is draining a backlog.\n const date = info.time instanceof Date ? info.time : new Date();\n appendFile(this.filename(date), `${info[Symbol.for('message')]}\\n`, { flag: 'a' }, (error) => {\n if (!error) this.emit('logged', info);\n callback(error);\n });\n }\n\n close(): void {\n if (this.timer) clearTimeout(this.timer);\n }\n\n logv(chunks: { chunk: any }[], callback: (error?: Error | null) => void): void {\n let index = 0;\n const next = (error?: Error | null) => {\n if (error || index === chunks.length) return callback(error);\n this.log(chunks[index++].chunk, next);\n };\n next();\n }\n}\n"]}
1
+ {"version":3,"file":"DailyFileTransport.js","sourceRoot":"","sources":["../src/DailyFileTransport.ts"],"names":[],"mappings":"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","sourcesContent":["import Transport from 'winston-transport';\nimport { appendFile, appendFileSync, mkdirSync } from 'fs';\nimport { join } from 'path';\n\ntype LogInfo = {\n time?: Date;\n [key: string]: unknown;\n [key: symbol]: unknown;\n};\n\n/** One append-only JSON-lines file per local calendar day, including idle days. */\nexport class DailyFileTransport extends Transport {\n private timer?: NodeJS.Timeout;\n\n constructor(private readonly directory: string) {\n super();\n mkdirSync(directory, { recursive: true });\n this.touchToday();\n this.scheduleMidnight();\n }\n\n private filename(date: Date): string {\n const month = String(date.getMonth() + 1).padStart(2, '0');\n const day = String(date.getDate()).padStart(2, '0');\n return join(this.directory, `${date.getFullYear()}-${month}-${day}.json`);\n }\n\n private touchToday(): void {\n appendFileSync(this.filename(new Date()), '', { flag: 'a' });\n }\n\n private scheduleMidnight(): void {\n const now = new Date();\n const midnight = new Date(now.getFullYear(), now.getMonth(), now.getDate() + 1);\n this.timer = setTimeout(() => {\n try {\n this.touchToday();\n } catch (error) {\n // `emit('error')` senza listener farebbe crashare il processo: emetti solo se osservato.\n if (this.listenerCount('error') > 0) {\n this.emit('error', error);\n }\n } finally {\n this.scheduleMidnight();\n }\n }, Math.max(1, midnight.getTime() - now.getTime()));\n this.timer.unref();\n }\n\n override log(info: LogInfo, callback: (error?: Error | null) => void): void {\n // Capture the event's day even when the transport is draining a backlog.\n const date = info.time instanceof Date ? info.time : new Date();\n appendFile(this.filename(date), `${info[Symbol.for('message')]}\\n`, { flag: 'a' }, (error) => {\n if (!error) this.emit('logged', info);\n callback(error);\n });\n }\n\n override close(): void {\n if (this.timer) clearTimeout(this.timer);\n }\n\n override logv(chunks: { chunk: LogInfo }[], callback: (error?: Error | null) => void): void {\n let index = 0;\n const next = (error?: Error | null) => {\n if (error || index === chunks.length) return callback(error);\n const chunk = chunks[index];\n index += 1;\n if (!chunk) return callback(error);\n this.log(chunk.chunk, next);\n };\n next();\n }\n}\n"]}
@@ -117,6 +117,7 @@ class DatabaseUpdater {
117
117
  */
118
118
  static getDatabaseVersion(options) {
119
119
  return __awaiter(this, void 0, void 0, function* () {
120
+ var _a;
120
121
  try {
121
122
  if (!(yield this.tableExists(options, "PARAMETRI"))) {
122
123
  return null;
@@ -129,7 +130,11 @@ class DatabaseUpdater {
129
130
  this.versionParameterKeys[1],
130
131
  this.versionParameterKeys[0],
131
132
  ]));
132
- return parameters.length > 0 ? parameters[0].DESPAR : null;
133
+ if (parameters.length === 0) {
134
+ return null;
135
+ }
136
+ const rawVersion = (_a = parameters[0]) === null || _a === void 0 ? void 0 : _a.DESPAR;
137
+ return typeof rawVersion === "string" ? rawVersion : rawVersion == null ? null : String(rawVersion);
133
138
  }
134
139
  catch (error) {
135
140
  this.logger.error(`Error getting database version:`, error);
@@ -144,7 +149,7 @@ class DatabaseUpdater {
144
149
  */
145
150
  static setDatabaseVersion(options, version) {
146
151
  return __awaiter(this, void 0, void 0, function* () {
147
- var _a, _b, _c;
152
+ var _a;
148
153
  try {
149
154
  if (!(yield this.tableExists(options, "PARAMETRI"))) {
150
155
  yield this.createParametersTable(options);
@@ -157,7 +162,7 @@ class DatabaseUpdater {
157
162
  for (const row of existingRows) {
158
163
  yield Orm_1.Orm.execute(options, "UPDATE PARAMETRI SET DESPAR = ? WHERE CODPAR = ?", [
159
164
  version,
160
- (_c = (_b = (_a = row.CODPAR) === null || _a === void 0 ? void 0 : _a.trim) === null || _b === void 0 ? void 0 : _b.call(_a)) !== null && _c !== void 0 ? _c : row.CODPAR,
165
+ String((_a = row.CODPAR) !== null && _a !== void 0 ? _a : "").trim(),
161
166
  ]);
162
167
  }
163
168
  }
@@ -1 +1 @@
1
- {"version":3,"file":"DatabaseUpdater.js","sourceRoot":"","sources":["../src/DatabaseUpdater.ts"],"names":[],"mappings":"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","sourcesContent":["import { Orm } from \"./Orm\";\nimport { Logger } from \"./Logger\";\nimport { Options } from \"node-firebird\";\n\nexport abstract class DatabaseUpdater {\n //#region Fields and Options\n protected static options: Options;\n protected static logger: Logger = new Logger(DatabaseUpdater.name);\n protected static readonly versionParameterKeys = [\"VersioneDB\", \"DBVERSION\"];\n //#endregion\n\n //#region Utility Methods\n /**\n * Checks if a table exists.\n * @param options Database connection options.\n * @param table Table name.\n * @returns True if the table exists, false otherwise.\n */\n protected static async tableExists(\n options: Options,\n table: string\n ): Promise<boolean> {\n\n try {\n const query = `\n SELECT 1\n FROM RDB$RELATIONS\n WHERE RDB$RELATION_NAME = ?\n AND COALESCE(RDB$SYSTEM_FLAG, 0) = 0`;\n const result = await Orm.query(options, query, [table.toUpperCase()]);\n return result.length > 0;\n } catch (error: any) {\n this.logger.error(`Error checking table ${table}:`, error);\n throw error;\n }\n }\n\n /**\n * Checks if a column exists in a specific table.\n * @param options Database connection options.\n * @param table Table name.\n * @param column Column name.\n * @returns True if the column exists, false otherwise.\n */\n protected static async columnExists(\n options: Options,\n table: string,\n column: string\n ): Promise<boolean> {\n\n try {\n const query = `\n SELECT 1 \n FROM RDB$RELATION_FIELDS \n WHERE RDB$RELATION_NAME = ? \n AND RDB$FIELD_NAME = ?`;\n const result = await Orm.query(options, query, [\n table.toUpperCase(),\n column.toUpperCase(),\n ]);\n return result.length > 0;\n } catch (error: any) {\n this.logger.error(`Error checking column ${column} on table ${table}:`, error);\n throw error;\n }\n }\n\n /**\n * Checks if a generator/sequence exists.\n * @param options Database connection options.\n * @param generator Generator name.\n * @returns True if the generator exists, false otherwise.\n */\n protected static async generatorExists(\n options: Options,\n generator: string\n ): Promise<boolean> {\n\n try {\n const query = `\n SELECT 1\n FROM RDB$GENERATORS\n WHERE RDB$GENERATOR_NAME = ?`;\n const result = await Orm.query(options, query, [generator.toUpperCase()]);\n return result.length > 0;\n } catch (error: any) {\n this.logger.error(`Error checking generator ${generator}:`, error);\n throw error;\n }\n }\n\n /**\n * Checks if a trigger exists.\n * @param options Database connection options.\n * @param trigger Trigger name.\n * @returns True if the trigger exists, false otherwise.\n */\n protected static async triggerExists(\n options: Options,\n trigger: string\n ): Promise<boolean> {\n\n try {\n const query = `\n SELECT 1\n FROM RDB$TRIGGERS\n WHERE RDB$TRIGGER_NAME = ?\n AND COALESCE(RDB$SYSTEM_FLAG, 0) = 0`;\n const result = await Orm.query(options, query, [trigger.toUpperCase()]);\n return result.length > 0;\n } catch (error: any) {\n this.logger.error(`Error checking trigger ${trigger}:`, error);\n throw error;\n }\n }\n\n /**\n * Retrieves the current database version from the PARAMETRI table.\n * @param options Database connection options.\n * @returns The current database version or null if not found.\n */\n protected static async getDatabaseVersion(options: Options): Promise<string | null> {\n\n try {\n if (!(await this.tableExists(options, \"PARAMETRI\"))) {\n return null;\n }\n\n const parameters = (await Orm.query(\n options,\n `SELECT CODPAR, DESPAR\n FROM PARAMETRI\n WHERE CODPAR IN (?, ?)\n ORDER BY CASE WHEN CODPAR = ? THEN 0 ELSE 1 END`,\n [\n this.versionParameterKeys[0],\n this.versionParameterKeys[1],\n this.versionParameterKeys[0],\n ]\n )) as any[];\n\n return parameters.length > 0 ? parameters[0].DESPAR : null;\n } catch (error: any) {\n this.logger.error(`Error getting database version:`, error);\n throw error;\n }\n }\n\n /**\n * Updates the database version in the PARAMETRI table.\n * @param options Database connection options.\n * @param version The new database version.\n */\n protected static async setDatabaseVersion(\n options: Options,\n version: string\n ): Promise<void> {\n\n try {\n if (!(await this.tableExists(options, \"PARAMETRI\"))) {\n await this.createParametersTable(options);\n }\n\n const existingRows = (await Orm.query(\n options,\n \"SELECT CODPAR FROM PARAMETRI WHERE CODPAR IN (?, ?)\",\n [this.versionParameterKeys[0], this.versionParameterKeys[1]]\n )) as any[];\n\n if (existingRows.length === 0) {\n await Orm.execute(\n options,\n \"INSERT INTO PARAMETRI (CODPAR, DESPAR, NOTE, GRUPPO) VALUES (?, ?, ?, ?)\",\n [this.versionParameterKeys[0], version, \"versione\", null]\n );\n return;\n }\n\n for (const row of existingRows) {\n await Orm.execute(options, \"UPDATE PARAMETRI SET DESPAR = ? WHERE CODPAR = ?\", [\n version,\n row.CODPAR?.trim?.() ?? row.CODPAR,\n ]);\n }\n } catch (error: any) {\n this.logger.error(`Error setting database version:`, error);\n throw error;\n }\n }\n //#endregion\n\n //#region Initialization Methods\n /**\n * Ensures the PARAMETRI table exists and initializes it if necessary.\n * @param options Database connection options.\n */\n protected static async createParametersTable(options: Options): Promise<void> {\n try {\n const tableAlreadyExists = await this.tableExists(options, \"PARAMETRI\");\n if (!tableAlreadyExists) {\n const createTableQuery = `\n CREATE TABLE PARAMETRI (\n CODPAR VARCHAR(15) NOT NULL,\n DESPAR VARCHAR(255),\n NOTE BLOB SUB_TYPE 1 SEGMENT SIZE 80,\n GRUPPO VARCHAR(20)\n );`;\n\n await Orm.query(options, createTableQuery);\n\n await Orm.query(\n options,\n \"ALTER TABLE PARAMETRI ADD CONSTRAINT PK_PARAMETRI PRIMARY KEY (CODPAR);\"\n );\n }\n\n const versioneDb = await this.getDatabaseVersion(options);\n if (versioneDb !== null && versioneDb !== undefined) {\n return;\n }\n\n await Orm.execute(\n options,\n \"INSERT INTO PARAMETRI (CODPAR, DESPAR, NOTE, GRUPPO) VALUES (?,?,?,?)\",\n [this.versionParameterKeys[0], \"0.0a\", \"versione\", null]\n );\n } catch (error: any) {\n this.logger.error(\"Error creating table PARAMETRI:\", error);\n throw error;\n }\n\n\n }\n //#endregion\n}\n"]}
1
+ {"version":3,"file":"DatabaseUpdater.js","sourceRoot":"","sources":["../src/DatabaseUpdater.ts"],"names":[],"mappings":"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","sourcesContent":["import { Orm } from \"./Orm\";\nimport { Logger } from \"./Logger\";\nimport { Options } from \"node-firebird\";\n\nexport abstract class DatabaseUpdater {\n //#region Fields and Options\n protected static options: Options;\n protected static logger: Logger = new Logger(DatabaseUpdater.name);\n protected static readonly versionParameterKeys = [\"VersioneDB\", \"DBVERSION\"];\n //#endregion\n\n //#region Utility Methods\n /**\n * Checks if a table exists.\n * @param options Database connection options.\n * @param table Table name.\n * @returns True if the table exists, false otherwise.\n */\n protected static async tableExists(\n options: Options,\n table: string\n ): Promise<boolean> {\n\n try {\n const query = `\n SELECT 1\n FROM RDB$RELATIONS\n WHERE RDB$RELATION_NAME = ?\n AND COALESCE(RDB$SYSTEM_FLAG, 0) = 0`;\n const result = await Orm.query(options, query, [table.toUpperCase()]);\n return result.length > 0;\n } catch (error) {\n this.logger.error(`Error checking table ${table}:`, error);\n throw error;\n }\n }\n\n /**\n * Checks if a column exists in a specific table.\n * @param options Database connection options.\n * @param table Table name.\n * @param column Column name.\n * @returns True if the column exists, false otherwise.\n */\n protected static async columnExists(\n options: Options,\n table: string,\n column: string\n ): Promise<boolean> {\n\n try {\n const query = `\n SELECT 1 \n FROM RDB$RELATION_FIELDS \n WHERE RDB$RELATION_NAME = ? \n AND RDB$FIELD_NAME = ?`;\n const result = await Orm.query(options, query, [\n table.toUpperCase(),\n column.toUpperCase(),\n ]);\n return result.length > 0;\n } catch (error) {\n this.logger.error(`Error checking column ${column} on table ${table}:`, error);\n throw error;\n }\n }\n\n /**\n * Checks if a generator/sequence exists.\n * @param options Database connection options.\n * @param generator Generator name.\n * @returns True if the generator exists, false otherwise.\n */\n protected static async generatorExists(\n options: Options,\n generator: string\n ): Promise<boolean> {\n\n try {\n const query = `\n SELECT 1\n FROM RDB$GENERATORS\n WHERE RDB$GENERATOR_NAME = ?`;\n const result = await Orm.query(options, query, [generator.toUpperCase()]);\n return result.length > 0;\n } catch (error) {\n this.logger.error(`Error checking generator ${generator}:`, error);\n throw error;\n }\n }\n\n /**\n * Checks if a trigger exists.\n * @param options Database connection options.\n * @param trigger Trigger name.\n * @returns True if the trigger exists, false otherwise.\n */\n protected static async triggerExists(\n options: Options,\n trigger: string\n ): Promise<boolean> {\n\n try {\n const query = `\n SELECT 1\n FROM RDB$TRIGGERS\n WHERE RDB$TRIGGER_NAME = ?\n AND COALESCE(RDB$SYSTEM_FLAG, 0) = 0`;\n const result = await Orm.query(options, query, [trigger.toUpperCase()]);\n return result.length > 0;\n } catch (error) {\n this.logger.error(`Error checking trigger ${trigger}:`, error);\n throw error;\n }\n }\n\n /**\n * Retrieves the current database version from the PARAMETRI table.\n * @param options Database connection options.\n * @returns The current database version or null if not found.\n */\n protected static async getDatabaseVersion(options: Options): Promise<string | null> {\n\n try {\n if (!(await this.tableExists(options, \"PARAMETRI\"))) {\n return null;\n }\n\n const parameters = (await Orm.query(\n options,\n `SELECT CODPAR, DESPAR\n FROM PARAMETRI\n WHERE CODPAR IN (?, ?)\n ORDER BY CASE WHEN CODPAR = ? THEN 0 ELSE 1 END`,\n [\n this.versionParameterKeys[0],\n this.versionParameterKeys[1],\n this.versionParameterKeys[0],\n ]\n ));\n\n if (parameters.length === 0) {\n return null;\n }\n\n const rawVersion = parameters[0]?.DESPAR;\n return typeof rawVersion === \"string\" ? rawVersion : rawVersion == null ? null : String(rawVersion);\n } catch (error) {\n this.logger.error(`Error getting database version:`, error);\n throw error;\n }\n }\n\n /**\n * Updates the database version in the PARAMETRI table.\n * @param options Database connection options.\n * @param version The new database version.\n */\n protected static async setDatabaseVersion(\n options: Options,\n version: string\n ): Promise<void> {\n\n try {\n if (!(await this.tableExists(options, \"PARAMETRI\"))) {\n await this.createParametersTable(options);\n }\n\n const existingRows = (await Orm.query(\n options,\n \"SELECT CODPAR FROM PARAMETRI WHERE CODPAR IN (?, ?)\",\n [this.versionParameterKeys[0], this.versionParameterKeys[1]]\n ));\n\n if (existingRows.length === 0) {\n await Orm.execute(\n options,\n \"INSERT INTO PARAMETRI (CODPAR, DESPAR, NOTE, GRUPPO) VALUES (?, ?, ?, ?)\",\n [this.versionParameterKeys[0], version, \"versione\", null]\n );\n return;\n }\n\n for (const row of existingRows) {\n await Orm.execute(options, \"UPDATE PARAMETRI SET DESPAR = ? WHERE CODPAR = ?\", [\n version,\n String(row.CODPAR ?? \"\").trim(),\n ]);\n }\n } catch (error) {\n this.logger.error(`Error setting database version:`, error);\n throw error;\n }\n }\n //#endregion\n\n //#region Initialization Methods\n /**\n * Ensures the PARAMETRI table exists and initializes it if necessary.\n * @param options Database connection options.\n */\n protected static async createParametersTable(options: Options): Promise<void> {\n try {\n const tableAlreadyExists = await this.tableExists(options, \"PARAMETRI\");\n if (!tableAlreadyExists) {\n const createTableQuery = `\n CREATE TABLE PARAMETRI (\n CODPAR VARCHAR(15) NOT NULL,\n DESPAR VARCHAR(255),\n NOTE BLOB SUB_TYPE 1 SEGMENT SIZE 80,\n GRUPPO VARCHAR(20)\n );`;\n\n await Orm.query(options, createTableQuery);\n\n await Orm.query(\n options,\n \"ALTER TABLE PARAMETRI ADD CONSTRAINT PK_PARAMETRI PRIMARY KEY (CODPAR);\"\n );\n }\n\n const versioneDb = await this.getDatabaseVersion(options);\n if (versioneDb !== null && versioneDb !== undefined) {\n return;\n }\n\n await Orm.execute(\n options,\n \"INSERT INTO PARAMETRI (CODPAR, DESPAR, NOTE, GRUPPO) VALUES (?,?,?,?)\",\n [this.versionParameterKeys[0], \"0.0a\", \"versione\", null]\n );\n } catch (error) {\n this.logger.error(\"Error creating table PARAMETRI:\", error);\n throw error;\n }\n\n\n }\n //#endregion\n}\n"]}
@@ -4,7 +4,7 @@ export declare class ExecutionTimeLogger {
4
4
  * @param target The target object.
5
5
  * @param propertyKey The name of the method.
6
6
  * @param descriptor The property descriptor of the method.
7
- * @description use ExecutionTimeLogger.apply on any method
7
+ * @description use ExecutionTimeLogger.apply on a method
8
8
  */
9
- static apply(target: any, propertyKey: string, descriptor: PropertyDescriptor): PropertyDescriptor;
9
+ static apply(target: object, propertyKey: string, descriptor: PropertyDescriptor): PropertyDescriptor;
10
10
  }
@@ -17,7 +17,7 @@ class ExecutionTimeLogger {
17
17
  * @param target The target object.
18
18
  * @param propertyKey The name of the method.
19
19
  * @param descriptor The property descriptor of the method.
20
- * @description use ExecutionTimeLogger.apply on any method
20
+ * @description use ExecutionTimeLogger.apply on a method
21
21
  */
22
22
  static apply(target, propertyKey, descriptor) {
23
23
  const originalMethod = descriptor.value;
@@ -38,7 +38,8 @@ class ExecutionTimeLogger {
38
38
  return result;
39
39
  }
40
40
  catch (error) {
41
- logger.error(`[${className}] ${propertyKey} method threw an error: ${error.message}`);
41
+ const message = error instanceof Error ? error.message : String(error);
42
+ logger.error(`[${className}] ${propertyKey} method threw an error: ${message}`);
42
43
  throw error;
43
44
  }
44
45
  });
@@ -1 +1 @@
1
- {"version":3,"file":"ExecutionTimeLogger.js","sourceRoot":"","sources":["../src/ExecutionTimeLogger.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,yBAA4B;AAE5B,MAAa,mBAAmB;IAC5B;;;;;;OAMG;IACH,MAAM,CAAC,KAAK,CAAC,MAAW,EAAE,WAAmB,EAAE,UAA8B;QACzE,MAAM,cAAc,GAAG,UAAU,CAAC,KAAK,CAAC;QAExC,IAAI,OAAO,cAAc,KAAK,UAAU,EAAE,CAAC;YACvC,MAAM,IAAI,SAAS,CAAC,4DAA4D,OAAO,cAAc,EAAE,CAAC,CAAC;QAC7G,CAAC;QAED,MAAM,SAAS,GAAG,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC;QAC1C,MAAM,MAAM,GAAG,IAAI,SAAM,CAAC,SAAS,CAAC,CAAC;QACrC,UAAU,CAAC,KAAK,GAAG,UAAgB,GAAG,IAAW;;gBAC7C,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;gBAC/B,MAAM,CAAC,IAAI,CAAC,IAAI,SAAS,KAAK,WAAW,iCAAiC,CAAC,CAAC;gBAE5E,IAAI,CAAC;oBACD,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;oBACtD,MAAM,GAAG,GAAG,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;oBAClC,MAAM,sBAAsB,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC;oBAC5D,MAAM,CAAC,IAAI,CAAC,IAAI,SAAS,KAAK,WAAW,gBAAgB,sBAAsB,CAAC,OAAO,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC;oBAC5G,OAAO,MAAM,CAAC;gBAClB,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACb,MAAM,CAAC,KAAK,CAAC,IAAI,SAAS,KAAK,WAAW,2BAA2B,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;oBACtF,MAAM,KAAK,CAAC;gBAChB,CAAC;YACL,CAAC;SAAA,CAAC;QAEF,OAAO,UAAU,CAAC;IACtB,CAAC;CACJ;AAnCD,kDAmCC","sourcesContent":["import { Logger } from \"./\";\n\nexport class ExecutionTimeLogger {\n /**\n * Wraps a method to log its execution time and errors.\n * @param target The target object.\n * @param propertyKey The name of the method.\n * @param descriptor The property descriptor of the method.\n * @description use ExecutionTimeLogger.apply on any method\n */\n static apply(target: any, propertyKey: string, descriptor: PropertyDescriptor) {\n const originalMethod = descriptor.value;\n\n if (typeof originalMethod !== \"function\") {\n throw new TypeError(`ExecutionTimeLogger can only be applied to methods, not: ${typeof originalMethod}`);\n }\n\n const className = target.constructor.name;\n const logger = new Logger(className);\n descriptor.value = async function (...args: any[]) {\n const start = process.hrtime();\n logger.info(`[${className}] ${propertyKey} method execution started . . .`);\n \n try {\n const result = await originalMethod.apply(this, args);\n const end = process.hrtime(start);\n const durationInMilliseconds = end[0] * 1000 + end[1] / 1e6;\n logger.info(`[${className}] ${propertyKey} method took ${durationInMilliseconds.toFixed(2)} ms to execute`);\n return result;\n } catch (error) {\n logger.error(`[${className}] ${propertyKey} method threw an error: ${error.message}`);\n throw error;\n }\n };\n\n return descriptor;\n }\n}\n"]}
1
+ {"version":3,"file":"ExecutionTimeLogger.js","sourceRoot":"","sources":["../src/ExecutionTimeLogger.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,yBAA4B;AAE5B,MAAa,mBAAmB;IAC5B;;;;;;OAMG;IACH,MAAM,CAAC,KAAK,CAAC,MAAc,EAAE,WAAmB,EAAE,UAA8B;QAC5E,MAAM,cAAc,GAAG,UAAU,CAAC,KAAK,CAAC;QAExC,IAAI,OAAO,cAAc,KAAK,UAAU,EAAE,CAAC;YACvC,MAAM,IAAI,SAAS,CAAC,4DAA4D,OAAO,cAAc,EAAE,CAAC,CAAC;QAC7G,CAAC;QAED,MAAM,SAAS,GAAI,MAA4C,CAAC,WAAW,CAAC,IAAI,CAAC;QACjF,MAAM,MAAM,GAAG,IAAI,SAAM,CAAC,SAAS,CAAC,CAAC;QACrC,UAAU,CAAC,KAAK,GAAG,UAAgB,GAAG,IAAe;;gBACjD,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;gBAC/B,MAAM,CAAC,IAAI,CAAC,IAAI,SAAS,KAAK,WAAW,iCAAiC,CAAC,CAAC;gBAE5E,IAAI,CAAC;oBACD,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;oBACtD,MAAM,GAAG,GAAG,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;oBAClC,MAAM,sBAAsB,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC;oBAC5D,MAAM,CAAC,IAAI,CAAC,IAAI,SAAS,KAAK,WAAW,gBAAgB,sBAAsB,CAAC,OAAO,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC;oBAC5G,OAAO,MAAM,CAAC;gBAClB,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACb,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;oBACvE,MAAM,CAAC,KAAK,CAAC,IAAI,SAAS,KAAK,WAAW,2BAA2B,OAAO,EAAE,CAAC,CAAC;oBAChF,MAAM,KAAK,CAAC;gBAChB,CAAC;YACL,CAAC;SAAA,CAAC;QAEF,OAAO,UAAU,CAAC;IACtB,CAAC;CACJ;AApCD,kDAoCC","sourcesContent":["import { Logger } from \"./\";\n\nexport class ExecutionTimeLogger {\n /**\n * Wraps a method to log its execution time and errors.\n * @param target The target object.\n * @param propertyKey The name of the method.\n * @param descriptor The property descriptor of the method.\n * @description use ExecutionTimeLogger.apply on a method\n */\n static apply(target: object, propertyKey: string, descriptor: PropertyDescriptor) {\n const originalMethod = descriptor.value;\n\n if (typeof originalMethod !== \"function\") {\n throw new TypeError(`ExecutionTimeLogger can only be applied to methods, not: ${typeof originalMethod}`);\n }\n\n const className = (target as { constructor: { name: string } }).constructor.name;\n const logger = new Logger(className);\n descriptor.value = async function (...args: unknown[]) {\n const start = process.hrtime();\n logger.info(`[${className}] ${propertyKey} method execution started . . .`);\n \n try {\n const result = await originalMethod.apply(this, args);\n const end = process.hrtime(start);\n const durationInMilliseconds = end[0] * 1000 + end[1] / 1e6;\n logger.info(`[${className}] ${propertyKey} method took ${durationInMilliseconds.toFixed(2)} ms to execute`);\n return result;\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n logger.error(`[${className}] ${propertyKey} method threw an error: ${message}`);\n throw error;\n }\n };\n\n return descriptor;\n }\n}\n"]}