@jmlq/auth 0.0.1-alpha.1

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 (332) hide show
  1. package/README.md +306 -0
  2. package/dist/examples/bcrypt-password-hasher.example.d.ts +3 -0
  3. package/dist/examples/bcrypt-password-hasher.example.js +78 -0
  4. package/dist/examples/entity-object.example.d.ts +39 -0
  5. package/dist/examples/entity-object.example.js +411 -0
  6. package/dist/examples/factory-auth-service-example.d.ts +3 -0
  7. package/dist/examples/factory-auth-service-example.js +84 -0
  8. package/dist/examples/index.example.d.ts +12 -0
  9. package/dist/examples/index.example.js +171 -0
  10. package/dist/examples/jwt-algoritm.example.d.ts +47 -0
  11. package/dist/examples/jwt-algoritm.example.js +447 -0
  12. package/dist/examples/jwt-token-generator.example.d.ts +6 -0
  13. package/dist/examples/jwt-token-generator.example.js +49 -0
  14. package/dist/examples/jwt-verifier.example.d.ts +3 -0
  15. package/dist/examples/jwt-verifier.example.js +80 -0
  16. package/dist/examples/password-policy.example.d.ts +7 -0
  17. package/dist/examples/password-policy.example.js +57 -0
  18. package/dist/examples/service-jwt-token.example.d.ts +3 -0
  19. package/dist/examples/service-jwt-token.example.js +154 -0
  20. package/dist/examples/service-token-session.example.d.ts +3 -0
  21. package/dist/examples/service-token-session.example.js +139 -0
  22. package/dist/examples/use-case-login-with-password.example.d.ts +6 -0
  23. package/dist/examples/use-case-login-with-password.example.js +105 -0
  24. package/dist/examples/use-case-logout.example.d.ts +7 -0
  25. package/dist/examples/use-case-logout.example.js +134 -0
  26. package/dist/examples/use-case-refresh-token.example.d.ts +11 -0
  27. package/dist/examples/use-case-refresh-token.example.js +164 -0
  28. package/dist/examples/use-case-register-user.example.d.ts +9 -0
  29. package/dist/examples/use-case-register-user.example.js +110 -0
  30. package/dist/index.d.ts +1 -0
  31. package/dist/index.js +17 -0
  32. package/dist/src/application/dtos/index.d.ts +4 -0
  33. package/dist/src/application/dtos/index.js +20 -0
  34. package/dist/src/application/dtos/login.dto.d.ts +9 -0
  35. package/dist/src/application/dtos/login.dto.js +2 -0
  36. package/dist/src/application/dtos/logout.dto.d.ts +7 -0
  37. package/dist/src/application/dtos/logout.dto.js +2 -0
  38. package/dist/src/application/dtos/refresh-token.dto.d.ts +7 -0
  39. package/dist/src/application/dtos/refresh-token.dto.js +2 -0
  40. package/dist/src/application/dtos/register-user.dto.d.ts +16 -0
  41. package/dist/src/application/dtos/register-user.dto.js +2 -0
  42. package/dist/src/application/factories/auth-service.factory.d.ts +5 -0
  43. package/dist/src/application/factories/auth-service.factory.js +51 -0
  44. package/dist/src/application/factories/index.d.ts +1 -0
  45. package/dist/src/application/factories/index.js +17 -0
  46. package/dist/src/application/index.d.ts +3 -0
  47. package/dist/src/application/index.js +19 -0
  48. package/dist/src/application/use-cases/index.d.ts +4 -0
  49. package/dist/src/application/use-cases/index.js +20 -0
  50. package/dist/src/application/use-cases/login-with-password.use-case.d.ts +9 -0
  51. package/dist/src/application/use-cases/login-with-password.use-case.js +36 -0
  52. package/dist/src/application/use-cases/logout.use-case.d.ts +7 -0
  53. package/dist/src/application/use-cases/logout.use-case.js +22 -0
  54. package/dist/src/application/use-cases/refresh-token.use-case.d.ts +7 -0
  55. package/dist/src/application/use-cases/refresh-token.use-case.js +23 -0
  56. package/dist/src/application/use-cases/register-user.use-case.d.ts +10 -0
  57. package/dist/src/application/use-cases/register-user.use-case.js +37 -0
  58. package/dist/src/domain/entities/credential.entity.d.ts +78 -0
  59. package/dist/src/domain/entities/credential.entity.js +92 -0
  60. package/dist/src/domain/entities/index.d.ts +2 -0
  61. package/dist/src/domain/entities/index.js +18 -0
  62. package/dist/src/domain/entities/user.entity.d.ts +97 -0
  63. package/dist/src/domain/entities/user.entity.js +116 -0
  64. package/dist/src/domain/errors/auth-domain-error.d.ts +82 -0
  65. package/dist/src/domain/errors/auth-domain-error.js +112 -0
  66. package/dist/src/domain/errors/auth.errors.d.ts +56 -0
  67. package/dist/src/domain/errors/auth.errors.js +76 -0
  68. package/dist/src/domain/errors/identity.errors.d.ts +34 -0
  69. package/dist/src/domain/errors/identity.errors.js +82 -0
  70. package/dist/src/domain/errors/index.d.ts +2 -0
  71. package/dist/src/domain/errors/index.js +18 -0
  72. package/dist/src/domain/index.d.ts +6 -0
  73. package/dist/src/domain/index.js +22 -0
  74. package/dist/src/domain/object-values/email.d.ts +37 -0
  75. package/dist/src/domain/object-values/email.js +56 -0
  76. package/dist/src/domain/object-values/hashed-password.d.ts +28 -0
  77. package/dist/src/domain/object-values/hashed-password.js +73 -0
  78. package/dist/src/domain/object-values/id.d.ts +8 -0
  79. package/dist/src/domain/object-values/id.js +28 -0
  80. package/dist/src/domain/object-values/index.d.ts +5 -0
  81. package/dist/src/domain/object-values/index.js +13 -0
  82. package/dist/src/domain/object-values/permission.d.ts +15 -0
  83. package/dist/src/domain/object-values/permission.js +57 -0
  84. package/dist/src/domain/object-values/role.d.ts +25 -0
  85. package/dist/src/domain/object-values/role.js +108 -0
  86. package/dist/src/domain/ports/auth/password-hasher.d.ts +7 -0
  87. package/dist/src/domain/ports/auth/password-hasher.js +2 -0
  88. package/dist/src/domain/ports/auth/password-policy-config.port.d.ts +0 -0
  89. package/dist/src/domain/ports/auth/password-policy-config.port.js +10 -0
  90. package/dist/src/domain/ports/auth/password-policy.port.d.ts +10 -0
  91. package/dist/src/domain/ports/auth/password-policy.port.js +2 -0
  92. package/dist/src/domain/ports/config/auth-config.port.d.ts +19 -0
  93. package/dist/src/domain/ports/config/auth-config.port.js +3 -0
  94. package/dist/src/domain/ports/index.d.ts +9 -0
  95. package/dist/src/domain/ports/index.js +25 -0
  96. package/dist/src/domain/ports/jwt/factory/signature-strategy-factory.port.d.ts +14 -0
  97. package/dist/src/domain/ports/jwt/factory/signature-strategy-factory.port.js +2 -0
  98. package/dist/src/domain/ports/jwt/payload/jwt-payload.port.d.ts +12 -0
  99. package/dist/src/domain/ports/jwt/payload/jwt-payload.port.js +2 -0
  100. package/dist/src/domain/ports/jwt/signature-strategy-factory.port.d.ts +14 -0
  101. package/dist/src/domain/ports/jwt/signature-strategy-factory.port.js +2 -0
  102. package/dist/src/domain/ports/jwt/signature-strategy.d.ts +30 -0
  103. package/dist/src/domain/ports/jwt/signature-strategy.js +4 -0
  104. package/dist/src/domain/ports/jwt/signature-strategy.port.d.ts +31 -0
  105. package/dist/src/domain/ports/jwt/signature-strategy.port.js +4 -0
  106. package/dist/src/domain/ports/jwt/strategy/signature-strategy.port.d.ts +31 -0
  107. package/dist/src/domain/ports/jwt/strategy/signature-strategy.port.js +4 -0
  108. package/dist/src/domain/ports/repository/credential.repository.d.ts +10 -0
  109. package/dist/src/domain/ports/repository/credential.repository.js +2 -0
  110. package/dist/src/domain/ports/repository/index.d.ts +2 -0
  111. package/dist/src/domain/ports/repository/index.js +18 -0
  112. package/dist/src/domain/ports/repository/user.repository.d.ts +13 -0
  113. package/dist/src/domain/ports/repository/user.repository.js +2 -0
  114. package/dist/src/domain/ports/token/token-session.port.d.ts +7 -0
  115. package/dist/src/domain/ports/token/token-session.port.js +2 -0
  116. package/dist/src/domain/ports/token/token.service.port.d.ts +9 -0
  117. package/dist/src/domain/ports/token/token.service.port.js +2 -0
  118. package/dist/src/domain/props/create-payload-props.port.d.ts +0 -0
  119. package/dist/src/domain/props/create-payload-props.port.js +8 -0
  120. package/dist/src/domain/props/entities/credential.props.d.ts +8 -0
  121. package/dist/src/domain/props/entities/credential.props.js +2 -0
  122. package/dist/src/domain/props/entities/index.d.ts +2 -0
  123. package/dist/src/domain/props/entities/index.js +18 -0
  124. package/dist/src/domain/props/entities/user.props.d.ts +10 -0
  125. package/dist/src/domain/props/entities/user.props.js +2 -0
  126. package/dist/src/domain/props/index.d.ts +2 -0
  127. package/dist/src/domain/props/index.js +18 -0
  128. package/dist/src/domain/props/jwt/create-payload.props.d.ts +9 -0
  129. package/dist/src/domain/props/jwt/create-payload.props.js +2 -0
  130. package/dist/src/domain/props/jwt/generate-access-token.props.d.ts +8 -0
  131. package/dist/src/domain/props/jwt/generate-access-token.props.js +2 -0
  132. package/dist/src/domain/props/jwt/generate-refresh-token.props.d.ts +8 -0
  133. package/dist/src/domain/props/jwt/generate-refresh-token.props.js +2 -0
  134. package/dist/src/domain/props/jwt/generate-token.props.d.ts +10 -0
  135. package/dist/src/domain/props/jwt/generate-token.props.js +2 -0
  136. package/dist/src/domain/props/jwt/index.d.ts +5 -0
  137. package/dist/src/domain/props/jwt/index.js +21 -0
  138. package/dist/src/domain/props/jwt/jwt-subject.d.ts +7 -0
  139. package/dist/src/domain/props/jwt/jwt-subject.js +2 -0
  140. package/dist/src/domain/props/jwt/jwt-user.d.ts +7 -0
  141. package/dist/src/domain/props/jwt/jwt-user.js +2 -0
  142. package/dist/src/domain/props/services/generate-access-token.props.d.ts +8 -0
  143. package/dist/src/domain/props/services/generate-access-token.props.js +2 -0
  144. package/dist/src/domain/props/services/generate-refresh-token.props.d.ts +8 -0
  145. package/dist/src/domain/props/services/generate-refresh-token.props.js +2 -0
  146. package/dist/src/domain/props/services/index.d.ts +2 -0
  147. package/dist/src/domain/props/services/index.js +18 -0
  148. package/dist/src/domain/services/index.d.ts +1 -0
  149. package/dist/src/domain/services/index.js +17 -0
  150. package/dist/src/domain/services/password-policy.service.d.ts +8 -0
  151. package/dist/src/domain/services/password-policy.service.js +29 -0
  152. package/dist/src/domain/services/token.service.port.d.ts +9 -0
  153. package/dist/src/domain/services/token.service.port.js +2 -0
  154. package/dist/src/index.d.ts +78 -0
  155. package/dist/src/index.js +94 -0
  156. package/dist/src/infrastructure/index.d.ts +5 -0
  157. package/dist/src/infrastructure/index.js +21 -0
  158. package/dist/src/infrastructure/jwt/factory/index.d.ts +1 -0
  159. package/dist/src/infrastructure/jwt/factory/index.js +17 -0
  160. package/dist/src/infrastructure/jwt/factory/signature-strategy.factory.d.ts +21 -0
  161. package/dist/src/infrastructure/jwt/factory/signature-strategy.factory.js +61 -0
  162. package/dist/src/infrastructure/jwt/index.d.ts +3 -0
  163. package/dist/src/infrastructure/jwt/index.js +19 -0
  164. package/dist/src/infrastructure/jwt/signature-strategy.factory.d.ts +21 -0
  165. package/dist/src/infrastructure/jwt/signature-strategy.factory.js +61 -0
  166. package/dist/src/infrastructure/jwt/strategies/ecdsa-signature-strategy.d.ts +47 -0
  167. package/dist/src/infrastructure/jwt/strategies/ecdsa-signature-strategy.js +124 -0
  168. package/dist/src/infrastructure/jwt/strategies/ecdsa-signature.strategy.d.ts +47 -0
  169. package/dist/src/infrastructure/jwt/strategies/ecdsa-signature.strategy.js +124 -0
  170. package/dist/src/infrastructure/jwt/strategies/hmac-signature-strategy.d.ts +54 -0
  171. package/dist/src/infrastructure/jwt/strategies/hmac-signature-strategy.js +129 -0
  172. package/dist/src/infrastructure/jwt/strategies/hmac-signature.strategy.d.ts +54 -0
  173. package/dist/src/infrastructure/jwt/strategies/hmac-signature.strategy.js +129 -0
  174. package/dist/src/infrastructure/jwt/strategies/index.d.ts +3 -0
  175. package/dist/src/infrastructure/jwt/strategies/index.js +19 -0
  176. package/dist/src/infrastructure/jwt/strategies/rsa-signature-strategy.d.ts +47 -0
  177. package/dist/src/infrastructure/jwt/strategies/rsa-signature-strategy.js +124 -0
  178. package/dist/src/infrastructure/jwt/strategies/rsa-signature.strategy.d.ts +47 -0
  179. package/dist/src/infrastructure/jwt/strategies/rsa-signature.strategy.js +124 -0
  180. package/dist/src/infrastructure/jwt/token/actions/jwt-token-generator.d.ts +57 -0
  181. package/dist/src/infrastructure/jwt/token/actions/jwt-token-generator.js +123 -0
  182. package/dist/src/infrastructure/jwt/token/actions/jwt-token-verifier.d.ts +59 -0
  183. package/dist/src/infrastructure/jwt/token/actions/jwt-token-verifier.js +100 -0
  184. package/dist/src/infrastructure/jwt/token/index.d.ts +5 -0
  185. package/dist/src/infrastructure/jwt/token/index.js +21 -0
  186. package/dist/src/infrastructure/jwt/token/jwt-signer.d.ts +33 -0
  187. package/dist/src/infrastructure/jwt/token/jwt-signer.js +46 -0
  188. package/dist/src/infrastructure/jwt/token/jwt-token-parser.d.ts +29 -0
  189. package/dist/src/infrastructure/jwt/token/jwt-token-parser.js +57 -0
  190. package/dist/src/infrastructure/jwt/token/jwt-token-validator.d.ts +32 -0
  191. package/dist/src/infrastructure/jwt/token/jwt-token-validator.js +77 -0
  192. package/dist/src/infrastructure/jwt/token/tools/jwt-signer.d.ts +33 -0
  193. package/dist/src/infrastructure/jwt/token/tools/jwt-signer.js +46 -0
  194. package/dist/src/infrastructure/jwt/token/tools/jwt-token-parser.d.ts +30 -0
  195. package/dist/src/infrastructure/jwt/token/tools/jwt-token-parser.js +57 -0
  196. package/dist/src/infrastructure/jwt/token/tools/jwt-token-validator.d.ts +32 -0
  197. package/dist/src/infrastructure/jwt/token/tools/jwt-token-validator.js +77 -0
  198. package/dist/src/infrastructure/repositories/index.d.ts +1 -0
  199. package/dist/src/infrastructure/repositories/index.js +17 -0
  200. package/dist/src/infrastructure/repositories/test/in-memory-credential.repository.d.ts +12 -0
  201. package/dist/src/infrastructure/repositories/test/in-memory-credential.repository.js +68 -0
  202. package/dist/src/infrastructure/repositories/test/in-memory-token-session.repository.d.ts +67 -0
  203. package/dist/src/infrastructure/repositories/test/in-memory-token-session.repository.js +128 -0
  204. package/dist/src/infrastructure/repositories/test/in-memory-user.repository.d.ts +11 -0
  205. package/dist/src/infrastructure/repositories/test/in-memory-user.repository.js +49 -0
  206. package/dist/src/infrastructure/repositories/test/index.d.ts +2 -0
  207. package/dist/src/infrastructure/repositories/test/index.js +18 -0
  208. package/dist/src/infrastructure/security/bcrypt-password-hasher.d.ts +6 -0
  209. package/dist/src/infrastructure/security/bcrypt-password-hasher.js +19 -0
  210. package/dist/src/infrastructure/security/index.d.ts +1 -0
  211. package/dist/src/infrastructure/security/index.js +17 -0
  212. package/dist/src/infrastructure/services/default-token-session.service.d.ts +18 -0
  213. package/dist/src/infrastructure/services/default-token-session.service.js +88 -0
  214. package/dist/src/infrastructure/services/index.d.ts +2 -0
  215. package/dist/src/infrastructure/services/index.js +18 -0
  216. package/dist/src/infrastructure/services/jwt-token.service.d.ts +15 -0
  217. package/dist/src/infrastructure/services/jwt-token.service.js +44 -0
  218. package/dist/src/infrastructure/services/simple-jwt-token.service.d.ts +15 -0
  219. package/dist/src/infrastructure/services/simple-jwt-token.service.js +46 -0
  220. package/dist/src/infrastructure/services/token-session.service.d.ts +24 -0
  221. package/dist/src/infrastructure/services/token-session.service.js +131 -0
  222. package/dist/src/infrastructure/types/auth-service-container.d.ts +14 -0
  223. package/dist/src/infrastructure/types/auth-service-container.js +2 -0
  224. package/dist/src/infrastructure/types/index.d.ts +1 -0
  225. package/dist/src/infrastructure/types/index.js +17 -0
  226. package/dist/src/shared/constants/index.d.ts +1 -0
  227. package/dist/src/shared/constants/index.js +17 -0
  228. package/dist/src/shared/constants/jwt-algorithms.d.ts +17 -0
  229. package/dist/src/shared/constants/jwt-algorithms.js +23 -0
  230. package/dist/src/shared/encoders/base64-url-encoder.d.ts +29 -0
  231. package/dist/src/shared/encoders/base64-url-encoder.js +45 -0
  232. package/dist/src/shared/encoders/index.d.ts +1 -0
  233. package/dist/src/shared/encoders/index.js +17 -0
  234. package/dist/src/shared/index.d.ts +4 -0
  235. package/dist/src/shared/index.js +20 -0
  236. package/dist/src/shared/types/index.d.ts +1 -0
  237. package/dist/src/shared/types/index.js +17 -0
  238. package/dist/src/shared/types/jwt.d.ts +25 -0
  239. package/dist/src/shared/types/jwt.js +2 -0
  240. package/dist/src/shared/types/jwt.types.d.ts +39 -0
  241. package/dist/src/shared/types/jwt.types.js +2 -0
  242. package/dist/src/shared/utils/index.d.ts +1 -0
  243. package/dist/src/shared/utils/index.js +17 -0
  244. package/dist/src/shared/utils/time-parser.d.ts +28 -0
  245. package/dist/src/shared/utils/time-parser.js +76 -0
  246. package/dist/tests/application/factory/auth-service-factory.spec.d.ts +1 -0
  247. package/dist/tests/application/factory/auth-service-factory.spec.js +97 -0
  248. package/dist/tests/application/use-cases/login-with-password.integration.spec.d.ts +1 -0
  249. package/dist/tests/application/use-cases/login-with-password.integration.spec.js +140 -0
  250. package/dist/tests/application/use-cases/logout-use-case.spec.d.ts +1 -0
  251. package/dist/tests/application/use-cases/logout-use-case.spec.js +40 -0
  252. package/dist/tests/application/use-cases/refresh-token-use-case.spec.d.ts +1 -0
  253. package/dist/tests/application/use-cases/refresh-token-use-case.spec.js +116 -0
  254. package/dist/tests/application/use-cases/register-user.usecase.spec.d.ts +1 -0
  255. package/dist/tests/application/use-cases/register-user.usecase.spec.js +151 -0
  256. package/dist/tests/domain/entities/credential.spec.d.ts +1 -0
  257. package/dist/tests/domain/entities/credential.spec.js +93 -0
  258. package/dist/tests/domain/entities/user.spec.d.ts +1 -0
  259. package/dist/tests/domain/entities/user.spec.js +93 -0
  260. package/dist/tests/domain/object-values/email.spec.d.ts +1 -0
  261. package/dist/tests/domain/object-values/email.spec.js +77 -0
  262. package/dist/tests/domain/object-values/hashed-password.spec.d.ts +1 -0
  263. package/dist/tests/domain/object-values/hashed-password.spec.js +54 -0
  264. package/dist/tests/domain/object-values/id.spec.d.ts +1 -0
  265. package/dist/tests/domain/object-values/id.spec.js +48 -0
  266. package/dist/tests/domain/object-values/permission.spec.d.ts +1 -0
  267. package/dist/tests/domain/object-values/permission.spec.js +75 -0
  268. package/dist/tests/domain/object-values/role.spec.d.ts +1 -0
  269. package/dist/tests/domain/object-values/role.spec.js +139 -0
  270. package/dist/tests/domain/services/default-password-policy.spec.d.ts +1 -0
  271. package/dist/tests/domain/services/default-password-policy.spec.js +69 -0
  272. package/dist/tests/doman/entities/credential.spec.d.ts +1 -0
  273. package/dist/tests/doman/entities/credential.spec.js +93 -0
  274. package/dist/tests/doman/entities/user.spec.d.ts +1 -0
  275. package/dist/tests/doman/entities/user.spec.js +93 -0
  276. package/dist/tests/doman/object-values/email.spec.d.ts +1 -0
  277. package/dist/tests/doman/object-values/email.spec.js +77 -0
  278. package/dist/tests/doman/object-values/hashed-password.spec.d.ts +1 -0
  279. package/dist/tests/doman/object-values/hashed-password.spec.js +54 -0
  280. package/dist/tests/doman/object-values/id.spec.d.ts +1 -0
  281. package/dist/tests/doman/object-values/id.spec.js +48 -0
  282. package/dist/tests/doman/object-values/permission.spec.d.ts +1 -0
  283. package/dist/tests/doman/object-values/permission.spec.js +75 -0
  284. package/dist/tests/doman/object-values/role.spec.d.ts +1 -0
  285. package/dist/tests/doman/object-values/role.spec.js +139 -0
  286. package/dist/tests/helpers/make-jwt-subject.d.ts +7 -0
  287. package/dist/tests/helpers/make-jwt-subject.js +16 -0
  288. package/dist/tests/helpers/make-jwt-user.d.ts +7 -0
  289. package/dist/tests/helpers/make-jwt-user.js +16 -0
  290. package/dist/tests/helpers/make-user.d.ts +2 -0
  291. package/dist/tests/helpers/make-user.js +15 -0
  292. package/dist/tests/infrastructure/jwt/signature-strategy-factory.spec.d.ts +1 -0
  293. package/dist/tests/infrastructure/jwt/signature-strategy-factory.spec.js +127 -0
  294. package/dist/tests/infrastructure/jwt/strategies/ecdsa-signature-strategy.spec.d.ts +1 -0
  295. package/dist/tests/infrastructure/jwt/strategies/ecdsa-signature-strategy.spec.js +157 -0
  296. package/dist/tests/infrastructure/jwt/strategies/hmac-signature-strategy.spec.d.ts +1 -0
  297. package/dist/tests/infrastructure/jwt/strategies/hmac-signature-strategy.spec.js +150 -0
  298. package/dist/tests/infrastructure/jwt/strategies/rsa-signature-strategy..spec.d.ts +1 -0
  299. package/dist/tests/infrastructure/jwt/strategies/rsa-signature-strategy..spec.js +156 -0
  300. package/dist/tests/infrastructure/jwt/token/actions/jwt-token-generator.spec.d.ts +1 -0
  301. package/dist/tests/infrastructure/jwt/token/actions/jwt-token-generator.spec.js +179 -0
  302. package/dist/tests/infrastructure/jwt/token/actions/jwt-token-verifier.spec.d.ts +1 -0
  303. package/dist/tests/infrastructure/jwt/token/actions/jwt-token-verifier.spec.js +142 -0
  304. package/dist/tests/infrastructure/jwt/token/jwt-signer.spec.d.ts +1 -0
  305. package/dist/tests/infrastructure/jwt/token/jwt-signer.spec.js +125 -0
  306. package/dist/tests/infrastructure/jwt/token/jwt-token-parser.spec.d.ts +1 -0
  307. package/dist/tests/infrastructure/jwt/token/jwt-token-parser.spec.js +116 -0
  308. package/dist/tests/infrastructure/jwt/token/jwt-token-validator.spec.d.ts +1 -0
  309. package/dist/tests/infrastructure/jwt/token/jwt-token-validator.spec.js +88 -0
  310. package/dist/tests/infrastructure/jwt/token/tools/jwt-signer.spec.d.ts +1 -0
  311. package/dist/tests/infrastructure/jwt/token/tools/jwt-signer.spec.js +126 -0
  312. package/dist/tests/infrastructure/jwt/token/tools/jwt-token-parser.spec.d.ts +1 -0
  313. package/dist/tests/infrastructure/jwt/token/tools/jwt-token-parser.spec.js +116 -0
  314. package/dist/tests/infrastructure/jwt/token/tools/jwt-token-validator.spec.d.ts +1 -0
  315. package/dist/tests/infrastructure/jwt/token/tools/jwt-token-validator.spec.js +88 -0
  316. package/dist/tests/infrastructure/security/security/bcrypt-password-hasher.spec.d.ts +1 -0
  317. package/dist/tests/infrastructure/security/security/bcrypt-password-hasher.spec.js +37 -0
  318. package/dist/tests/infrastructure/services/jwt-token-service.spec.d.ts +1 -0
  319. package/dist/tests/infrastructure/services/jwt-token-service.spec.js +145 -0
  320. package/dist/tests/infrastructure/services/token-session.service.spec.d.ts +1 -0
  321. package/dist/tests/infrastructure/services/token-session.service.spec.js +269 -0
  322. package/dist/tests/shared/constants/jwt-algorithms.spec.d.ts +1 -0
  323. package/dist/tests/shared/constants/jwt-algorithms.spec.js +27 -0
  324. package/dist/tests/shared/encoders/base64-url-encoder.spec.d.ts +1 -0
  325. package/dist/tests/shared/encoders/base64-url-encoder.spec.js +70 -0
  326. package/dist/tests/shared/utils/time-parser.spec.d.ts +1 -0
  327. package/dist/tests/shared/utils/time-parser.spec.js +80 -0
  328. package/dist/utils/index.d.ts +1 -0
  329. package/dist/utils/index.js +17 -0
  330. package/dist/utils/time-parser.d.ts +28 -0
  331. package/dist/utils/time-parser.js +76 -0
  332. package/package.json +48 -0
@@ -0,0 +1,145 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const jwt_token_service_1 = require("../../../src/infrastructure/services/jwt-token.service");
4
+ describe("JwtTokenService", () => {
5
+ let config;
6
+ let jwtGenerator;
7
+ let jwtVerifier;
8
+ let jwtValidator;
9
+ let service;
10
+ beforeEach(() => {
11
+ // ⚠️ Rellena/ajusta según tu definición real de IAuthConfig["info"]
12
+ config = {
13
+ accessTokenSecret: "access-secret",
14
+ refreshTokenSecret: "refresh-secret",
15
+ accessTokenExpirationMs: 15 * 60 * 1000,
16
+ refreshTokenExpirationMs: 7 * 24 * 60 * 60 * 1000,
17
+ issuer: "test-issuer",
18
+ audience: "test-audience",
19
+ appName: "test-app",
20
+ };
21
+ jwtGenerator = {
22
+ generateAccessToken: jest.fn(),
23
+ generateRefreshToken: jest.fn(),
24
+ };
25
+ jwtVerifier = {
26
+ verifyAccessToken: jest.fn(),
27
+ verifyRefreshToken: jest.fn(),
28
+ getTokenExpiration: jest.fn(),
29
+ };
30
+ jwtValidator = {
31
+ validateTokenInput: jest.fn(),
32
+ };
33
+ service = new jwt_token_service_1.JwtTokenService(config, jwtGenerator, jwtVerifier, jwtValidator);
34
+ });
35
+ describe("generateAccessToken", () => {
36
+ it("debería delegar en JwtTokenGenerator.generateAccessToken y retornar el token", async () => {
37
+ const props = {
38
+ userId: "user-123",
39
+ };
40
+ const expectedToken = "access.token.value";
41
+ jwtGenerator.generateAccessToken.mockResolvedValue(expectedToken);
42
+ const result = await service.generateAccessToken(props);
43
+ expect(jwtGenerator.generateAccessToken).toHaveBeenCalledTimes(1);
44
+ expect(jwtGenerator.generateAccessToken).toHaveBeenCalledWith(props);
45
+ expect(result).toBe(expectedToken);
46
+ });
47
+ });
48
+ describe("generateRefreshToken", () => {
49
+ it("debería delegar en JwtTokenGenerator.generateRefreshToken y retornar el token", async () => {
50
+ const props = {
51
+ userId: "user-123",
52
+ };
53
+ const expectedToken = "refresh.token.value";
54
+ jwtGenerator.generateRefreshToken.mockResolvedValue(expectedToken);
55
+ const result = await service.generateRefreshToken(props);
56
+ expect(jwtGenerator.generateRefreshToken).toHaveBeenCalledTimes(1);
57
+ expect(jwtGenerator.generateRefreshToken).toHaveBeenCalledWith(props);
58
+ expect(result).toBe(expectedToken);
59
+ });
60
+ });
61
+ describe("verifyAccessToken", () => {
62
+ it("debería validar el token y delegar en JwtTokenVerifier.verifyAccessToken", async () => {
63
+ const token = "access.token.value";
64
+ const payload = {
65
+ sub: "user-123",
66
+ roles: [
67
+ {
68
+ role: "user",
69
+ },
70
+ ],
71
+ customClaims: {},
72
+ jti: "unique-jwt-id",
73
+ iss: "test-issuer",
74
+ aud: "test-audience",
75
+ iat: Date.now() / 1000,
76
+ exp: (Date.now() + 1000) / 1000,
77
+ };
78
+ jwtVerifier.verifyAccessToken.mockResolvedValue(payload);
79
+ const result = await service.verifyAccessToken(token);
80
+ // Primero se valida la entrada
81
+ expect(jwtValidator.validateTokenInput).toHaveBeenCalledTimes(1);
82
+ expect(jwtValidator.validateTokenInput).toHaveBeenCalledWith(token);
83
+ // Luego se delega al verificador con el token y la config
84
+ expect(jwtVerifier.verifyAccessToken).toHaveBeenCalledTimes(1);
85
+ expect(jwtVerifier.verifyAccessToken).toHaveBeenCalledWith(token, config);
86
+ expect(result).toBe(payload);
87
+ });
88
+ it("debería propagar el error si validateTokenInput lanza una excepción", async () => {
89
+ const token = "invalid.token";
90
+ jwtValidator.validateTokenInput.mockImplementation(() => {
91
+ throw new Error("Invalid token format");
92
+ });
93
+ await expect(service.verifyAccessToken(token)).rejects.toThrow("Invalid token format");
94
+ // Si falla la validación, no debería llamar al verificador
95
+ expect(jwtVerifier.verifyAccessToken).not.toHaveBeenCalled();
96
+ });
97
+ });
98
+ describe("verifyRefreshToken", () => {
99
+ it("debería validar el token y delegar en JwtTokenVerifier.verifyRefreshToken", async () => {
100
+ const token = "refresh.token.value";
101
+ const payload = {
102
+ sub: "user-123",
103
+ roles: [
104
+ {
105
+ role: "user",
106
+ },
107
+ ],
108
+ customClaims: {},
109
+ jti: "unique-jwt-id",
110
+ iss: "test-issuer",
111
+ aud: "test-audience",
112
+ iat: Date.now() / 1000,
113
+ exp: (Date.now() + 1000) / 1000,
114
+ };
115
+ jwtVerifier.verifyRefreshToken.mockResolvedValue(payload);
116
+ const result = await service.verifyRefreshToken(token);
117
+ expect(jwtValidator.validateTokenInput).toHaveBeenCalledTimes(1);
118
+ expect(jwtValidator.validateTokenInput).toHaveBeenCalledWith(token);
119
+ expect(jwtVerifier.verifyRefreshToken).toHaveBeenCalledTimes(1);
120
+ expect(jwtVerifier.verifyRefreshToken).toHaveBeenCalledWith(token, config);
121
+ expect(result).toBe(payload);
122
+ });
123
+ });
124
+ describe("getTokenExpiration", () => {
125
+ it("debería validar el token y delegar en JwtTokenVerifier.getTokenExpiration", async () => {
126
+ const token = "any.token.value";
127
+ const expectedDate = new Date(Date.now() + 10000);
128
+ jwtVerifier.getTokenExpiration.mockResolvedValue(expectedDate);
129
+ const result = await service.getTokenExpiration(token);
130
+ expect(jwtValidator.validateTokenInput).toHaveBeenCalledTimes(1);
131
+ expect(jwtValidator.validateTokenInput).toHaveBeenCalledWith(token);
132
+ expect(jwtVerifier.getTokenExpiration).toHaveBeenCalledTimes(1);
133
+ expect(jwtVerifier.getTokenExpiration).toHaveBeenCalledWith(token);
134
+ expect(result).toBe(expectedDate);
135
+ });
136
+ it("debería propagar el error si validateTokenInput lanza una excepción", async () => {
137
+ const token = "invalid.token";
138
+ jwtValidator.validateTokenInput.mockImplementation(() => {
139
+ throw new Error("Invalid token");
140
+ });
141
+ await expect(service.getTokenExpiration(token)).rejects.toThrow("Invalid token");
142
+ expect(jwtVerifier.getTokenExpiration).not.toHaveBeenCalled();
143
+ });
144
+ });
145
+ });
@@ -0,0 +1,269 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const domain_1 = require("../../../src/domain");
4
+ const token_session_service_1 = require("../../../src/infrastructure/services/token-session.service");
5
+ const shared_1 = require("../../../src/shared");
6
+ describe("TokenSessionService", () => {
7
+ let tokenService;
8
+ let userRepository;
9
+ let credentialRepository;
10
+ const accessTokenExpiration = "15m";
11
+ const refreshTokenExpiration = "7d";
12
+ const accessSecret = "access-secret";
13
+ const refreshSecret = "refresh-secret";
14
+ const algorithm = "HS256";
15
+ const makeService = () => new token_session_service_1.TokenSessionService(tokenService, userRepository, credentialRepository, algorithm, accessTokenExpiration, refreshTokenExpiration, accessSecret, refreshSecret);
16
+ beforeEach(() => {
17
+ tokenService = {
18
+ generateAccessToken: jest.fn(),
19
+ generateRefreshToken: jest.fn(),
20
+ verifyAccessToken: jest.fn(),
21
+ verifyRefreshToken: jest.fn(),
22
+ getTokenExpiration: jest.fn(),
23
+ };
24
+ userRepository = {
25
+ findById: jest.fn(),
26
+ };
27
+ credentialRepository = {
28
+ save: jest.fn(),
29
+ findByUserId: jest.fn(),
30
+ findByRefreshToken: jest.fn(),
31
+ update: jest.fn(),
32
+ delete: jest.fn(),
33
+ deleteByRefreshToken: jest.fn(),
34
+ };
35
+ jest.restoreAllMocks();
36
+ });
37
+ // ────────────────────────────────────────────────
38
+ // Constructor
39
+ // ────────────────────────────────────────────────
40
+ it("debería lanzar JwtSecretError si faltan los secretos", () => {
41
+ expect(() => new token_session_service_1.TokenSessionService(tokenService, userRepository, credentialRepository, algorithm, accessTokenExpiration, refreshTokenExpiration, undefined, // accessTokenSecret
42
+ undefined // refreshTokenSecret
43
+ )).toThrow(domain_1.JwtSecretError);
44
+ });
45
+ it("debería lanzar error si la configuración de expiración es inválida", () => {
46
+ const spy = jest
47
+ .spyOn(shared_1.TimeParser, "parseToMilliseconds")
48
+ .mockImplementation(() => {
49
+ throw new Error("Formato inválido");
50
+ });
51
+ expect(() => new token_session_service_1.TokenSessionService(tokenService, userRepository, credentialRepository, algorithm, "invalid", // access
52
+ "invalid", // refresh
53
+ accessSecret, refreshSecret)).toThrow("Invalid token expiration configuration");
54
+ spy.mockRestore();
55
+ });
56
+ // ────────────────────────────────────────────────
57
+ // createSession
58
+ // ────────────────────────────────────────────────
59
+ describe("createSession", () => {
60
+ it("debería generar access y refresh tokens, guardar la credencial y retornarla", async () => {
61
+ const service = makeService();
62
+ const mockUserId = "user-123";
63
+ const mockEmail = "user@example.com";
64
+ const mockRolesPublic = [{ role: "user" }];
65
+ const user = {
66
+ id: { toString: () => mockUserId },
67
+ email: { toString: () => mockEmail },
68
+ roles: [
69
+ {
70
+ getValuePublic: () => mockRolesPublic[0],
71
+ },
72
+ ],
73
+ };
74
+ tokenService.generateAccessToken.mockResolvedValue("access-token");
75
+ tokenService.generateRefreshToken.mockResolvedValue("refresh-token");
76
+ const result = await service.createSession(user);
77
+ // Debe generar tokens con los datos del usuario
78
+ expect(tokenService.generateAccessToken).toHaveBeenCalledTimes(1);
79
+ expect(tokenService.generateAccessToken).toHaveBeenCalledWith(expect.objectContaining({
80
+ user: {
81
+ id: mockUserId,
82
+ email: mockEmail,
83
+ roles: mockRolesPublic,
84
+ },
85
+ expiresIn: accessTokenExpiration,
86
+ }));
87
+ expect(tokenService.generateRefreshToken).toHaveBeenCalledTimes(1);
88
+ expect(tokenService.generateRefreshToken).toHaveBeenCalledWith(expect.objectContaining({
89
+ user: {
90
+ id: mockUserId,
91
+ email: mockEmail,
92
+ roles: mockRolesPublic,
93
+ },
94
+ expiresIn: refreshTokenExpiration,
95
+ }));
96
+ // Debe guardar la credencial
97
+ expect(credentialRepository.save).toHaveBeenCalledTimes(1);
98
+ const savedCredential = credentialRepository.save.mock
99
+ .calls[0][0];
100
+ // La credencial retornada debe ser la misma que se guardó
101
+ expect(result).toBe(savedCredential);
102
+ expect(savedCredential).toBeInstanceOf(domain_1.Credential);
103
+ });
104
+ });
105
+ // ────────────────────────────────────────────────
106
+ // refreshSession
107
+ // ────────────────────────────────────────────────
108
+ describe("refreshSession", () => {
109
+ const refreshToken = "refresh-token";
110
+ it("debería lanzar InvalidOrExpiredRefreshTokenError si no existe credencial para el refresh token", async () => {
111
+ const service = makeService();
112
+ credentialRepository.findByRefreshToken.mockResolvedValue(null);
113
+ await expect(service.refreshSession(refreshToken)).rejects.toThrow(domain_1.InvalidOrExpiredRefreshTokenError);
114
+ expect(credentialRepository.findByRefreshToken).toHaveBeenCalledWith(refreshToken);
115
+ });
116
+ it("debería lanzar InvalidOrExpiredRefreshTokenError si verifyRefreshToken falla", async () => {
117
+ const service = makeService();
118
+ credentialRepository.findByRefreshToken.mockResolvedValue({});
119
+ tokenService.verifyRefreshToken.mockRejectedValue(new Error("expired"));
120
+ await expect(service.refreshSession(refreshToken)).rejects.toThrow(domain_1.InvalidOrExpiredRefreshTokenError);
121
+ });
122
+ it("debería lanzar UserNotFoundError si el usuario no existe", async () => {
123
+ const service = makeService();
124
+ credentialRepository.findByRefreshToken.mockResolvedValue({});
125
+ const payload = {
126
+ sub: "user-123",
127
+ iss: "test",
128
+ aud: "test",
129
+ iat: Date.now() / 1000,
130
+ exp: (Date.now() + 1000) / 1000,
131
+ roles: [],
132
+ customClaims: {},
133
+ jti: "id",
134
+ };
135
+ tokenService.verifyRefreshToken.mockResolvedValue(payload);
136
+ userRepository.findById.mockResolvedValue(null);
137
+ await expect(service.refreshSession(refreshToken)).rejects.toThrow(domain_1.UserNotFoundError);
138
+ expect(userRepository.findById).toHaveBeenCalledWith(expect.any(domain_1.Id) // se instancia con payload.sub
139
+ );
140
+ });
141
+ it("debería lanzar UserDisabledError si el usuario está deshabilitado", async () => {
142
+ const service = makeService();
143
+ credentialRepository.findByRefreshToken.mockResolvedValue({});
144
+ const payload = {
145
+ sub: "user-123",
146
+ iss: "test",
147
+ aud: "test",
148
+ iat: Date.now() / 1000,
149
+ exp: (Date.now() + 1000) / 1000,
150
+ roles: [],
151
+ customClaims: {},
152
+ jti: "id",
153
+ };
154
+ tokenService.verifyRefreshToken.mockResolvedValue(payload);
155
+ const user = {
156
+ canLogin: jest.fn().mockReturnValue(false),
157
+ };
158
+ userRepository.findById.mockResolvedValue(user);
159
+ await expect(service.refreshSession(refreshToken)).rejects.toThrow(domain_1.UserDisabledError);
160
+ });
161
+ it("debería crear una nueva sesión, eliminar la credencial anterior y retornar la nueva", async () => {
162
+ const service = makeService();
163
+ // Existe una credencial asociada al refresh token
164
+ credentialRepository.findByRefreshToken.mockResolvedValue({});
165
+ const payload = {
166
+ sub: "user-123",
167
+ iss: "test",
168
+ aud: "test",
169
+ iat: Date.now() / 1000,
170
+ exp: (Date.now() + 1000) / 1000,
171
+ roles: [],
172
+ customClaims: {},
173
+ jti: "id",
174
+ };
175
+ tokenService.verifyRefreshToken.mockResolvedValue(payload);
176
+ const user = {
177
+ id: { toString: () => "user-123" },
178
+ email: { toString: () => "user@example.com" },
179
+ roles: [
180
+ {
181
+ getValuePublic: () => ({ role: "user" }),
182
+ },
183
+ ],
184
+ canLogin: jest.fn().mockReturnValue(true),
185
+ };
186
+ userRepository.findById.mockResolvedValue(user);
187
+ tokenService.generateAccessToken.mockResolvedValue("new-access");
188
+ tokenService.generateRefreshToken.mockResolvedValue("new-refresh");
189
+ const result = await service.refreshSession(refreshToken);
190
+ // Debe haber creado y guardado una nueva credencial
191
+ expect(credentialRepository.save).toHaveBeenCalledTimes(1);
192
+ const savedCredential = credentialRepository.save.mock
193
+ .calls[0][0];
194
+ expect(result).toBe(savedCredential);
195
+ expect(savedCredential).toBeInstanceOf(domain_1.Credential);
196
+ // Debe eliminar la credencial vieja asociada al refresh token
197
+ expect(credentialRepository.deleteByRefreshToken).toHaveBeenCalledWith(refreshToken);
198
+ });
199
+ });
200
+ // ────────────────────────────────────────────────
201
+ // validateSession
202
+ // ────────────────────────────────────────────────
203
+ describe("validateSession", () => {
204
+ it("debería retornar el usuario cuando el token es válido y el usuario puede iniciar sesión", async () => {
205
+ const service = makeService();
206
+ const payload = {
207
+ sub: "user-123",
208
+ iss: "test",
209
+ aud: "test",
210
+ iat: Date.now() / 1000,
211
+ exp: (Date.now() + 1000) / 1000,
212
+ roles: [],
213
+ customClaims: {},
214
+ jti: "id",
215
+ };
216
+ tokenService.verifyAccessToken.mockResolvedValue(payload);
217
+ const user = {
218
+ canLogin: jest.fn().mockReturnValue(true),
219
+ };
220
+ userRepository.findById.mockResolvedValue(user);
221
+ const result = await service.validateSession("access-token");
222
+ expect(tokenService.verifyAccessToken).toHaveBeenCalledWith("access-token");
223
+ expect(userRepository.findById).toHaveBeenCalledWith(expect.any(domain_1.Id));
224
+ expect(result).toBe(user);
225
+ });
226
+ it("debería retornar null si verifyAccessToken lanza error", async () => {
227
+ const service = makeService();
228
+ tokenService.verifyAccessToken.mockRejectedValue(new Error("invalid"));
229
+ const result = await service.validateSession("invalid-token");
230
+ expect(result).toBeNull();
231
+ });
232
+ it("debería retornar null si el usuario no existe o no puede iniciar sesión", async () => {
233
+ const service = makeService();
234
+ const payload = {
235
+ sub: "user-123",
236
+ iss: "test",
237
+ aud: "test",
238
+ iat: Date.now() / 1000,
239
+ exp: (Date.now() + 1000) / 1000,
240
+ roles: [],
241
+ customClaims: {},
242
+ jti: "id",
243
+ };
244
+ tokenService.verifyAccessToken.mockResolvedValue(payload);
245
+ // Caso usuario no existe
246
+ userRepository.findById.mockResolvedValueOnce(null);
247
+ const result1 = await service.validateSession("access-token");
248
+ expect(result1).toBeNull();
249
+ // Caso usuario existe pero no puede iniciar sesión
250
+ const user = {
251
+ canLogin: jest.fn().mockReturnValue(false),
252
+ };
253
+ userRepository.findById.mockResolvedValueOnce(user);
254
+ const result2 = await service.validateSession("access-token");
255
+ expect(result2).toBeNull();
256
+ });
257
+ });
258
+ // ────────────────────────────────────────────────
259
+ // revokeSession
260
+ // ────────────────────────────────────────────────
261
+ describe("revokeSession", () => {
262
+ it("debería eliminar la credencial asociada al refresh token", async () => {
263
+ const service = makeService();
264
+ const refreshToken = "refresh-token";
265
+ await service.revokeSession(refreshToken);
266
+ expect(credentialRepository.deleteByRefreshToken).toHaveBeenCalledWith(refreshToken);
267
+ });
268
+ });
269
+ });
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const shared_1 = require("src/shared");
4
+ describe("algorithms constant", () => {
5
+ it("define las tres categorías principales", () => {
6
+ expect(Object.keys(shared_1.algorithms)).toEqual(["hmac", "rsa", "ecdsa"]);
7
+ });
8
+ it("cada categoría contiene tres algoritmos esperados", () => {
9
+ expect(Object.keys(shared_1.algorithms.hmac)).toEqual(["HS256", "HS384", "HS512"]);
10
+ expect(Object.keys(shared_1.algorithms.rsa)).toEqual(["RS256", "RS384", "RS512"]);
11
+ expect(Object.keys(shared_1.algorithms.ecdsa)).toEqual(["ES256", "ES384", "ES512"]);
12
+ });
13
+ it("los valores coinciden exactamente con sus claves (autodescriptivos)", () => {
14
+ for (const [family, algos] of Object.entries(shared_1.algorithms)) {
15
+ for (const [key, value] of Object.entries(algos)) {
16
+ expect(value).toBe(key);
17
+ }
18
+ }
19
+ });
20
+ it("no debe contener valores nulos o indefinidos", () => {
21
+ for (const family of Object.values(shared_1.algorithms)) {
22
+ for (const value of Object.values(family)) {
23
+ expect(value).toBeTruthy();
24
+ }
25
+ }
26
+ });
27
+ });
@@ -0,0 +1,70 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const shared_1 = require("../../../src/shared");
4
+ describe("Base64UrlEncoder", () => {
5
+ const enc = new shared_1.Base64UrlEncoder();
6
+ describe("encode", () => {
7
+ it.each([
8
+ ["", ""],
9
+ ["f", "Zg"],
10
+ ["fo", "Zm8"],
11
+ ["foo", "Zm9v"],
12
+ ["foob", "Zm9vYg"],
13
+ ["fooba", "Zm9vYmE"],
14
+ ["foobar", "Zm9vYmFy"],
15
+ ["hello", "aGVsbG8"],
16
+ ["mañana", "bWHDsWFuYQ"], // UTF-8
17
+ ["🔥", "8J-UpQ"], // incluye '-'
18
+ ["😺", "8J-Yug"], // incluye '-'
19
+ ["00?", "MDA_"], // incluye '_'
20
+ ])('encode("%s") → "%s"', (plain, expected) => {
21
+ expect(enc.encode(plain)).toBe(expected);
22
+ });
23
+ it("no contiene +, / ni = (URL-safe y sin padding)", () => {
24
+ const out = enc.encode("texto con símbolos: ~✓🔥/+/=");
25
+ expect(out).not.toMatch(/[+/=]/);
26
+ });
27
+ });
28
+ describe("decode", () => {
29
+ it.each([
30
+ ["", ""],
31
+ ["Zg", "f"], // sin padding (==)
32
+ ["Zm8", "fo"], // sin padding (=)
33
+ ["Zm9v", "foo"], // sin padding
34
+ ["Zm9vYg", "foob"],
35
+ ["Zm9vYmE", "fooba"],
36
+ ["Zm9vYmFy", "foobar"],
37
+ ["aGVsbG8", "hello"],
38
+ ["bWHDsWFuYQ", "mañana"], // UTF-8
39
+ ["8J-UpQ", "🔥"], // con '-'
40
+ ["MDA_", "00?"], // con '_'
41
+ ])('decode("%s") → "%s"', (b64url, expected) => {
42
+ expect(enc.decode(b64url)).toBe(expected);
43
+ });
44
+ it("acepta también Base64 “estándar” con padding", () => {
45
+ // Aunque la clase es URL-safe, su decode soporta base64 estándar.
46
+ expect(enc.decode("aGVsbG8=")).toBe("hello");
47
+ expect(enc.decode("Zm8=")).toBe("fo");
48
+ expect(enc.decode("Zg==")).toBe("f");
49
+ });
50
+ it("reconstituye padding correcto cuando falta", () => {
51
+ // length % 4 === 2 → agrega "=="
52
+ expect(enc.decode("Zg")).toBe("f");
53
+ // length % 4 === 3 → agrega "="
54
+ expect(enc.decode("Zm8")).toBe("fo");
55
+ });
56
+ });
57
+ describe("round-trip", () => {
58
+ it.each([
59
+ "",
60
+ "hola",
61
+ "The quick brown fox jumps over the lazy dog.",
62
+ "mañana será otro día",
63
+ "🔥😺 ~ ✓ / + _",
64
+ ])('decode(encode(x)) === x para "%s"', (plain) => {
65
+ const encoded = enc.encode(plain);
66
+ const decoded = enc.decode(encoded);
67
+ expect(decoded).toBe(plain);
68
+ });
69
+ });
70
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,80 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ // tests/shared/TimeParser.spec.ts
4
+ const time_parser_1 = require("../../../src/shared/utils/time-parser");
5
+ describe("TimeParser", () => {
6
+ describe("parseToMilliseconds", () => {
7
+ it.each([
8
+ ["30s", 30000],
9
+ ["1m", 60000],
10
+ ["15m", 900000],
11
+ ["1h", 3600000],
12
+ ["2h", 7200000],
13
+ ["1d", 86400000],
14
+ ["3d", 259200000],
15
+ ])("convierte %s a %d ms", (input, expected) => {
16
+ expect(time_parser_1.TimeParser.parseToMilliseconds(input)).toBe(expected);
17
+ });
18
+ it("ignora espacios y mayúsculas/minúsculas", () => {
19
+ expect(time_parser_1.TimeParser.parseToMilliseconds(" 2H ")).toBe(7200000);
20
+ expect(time_parser_1.TimeParser.parseToMilliseconds(" 45S")).toBe(45000);
21
+ });
22
+ it("lanza si no es string o es falsy", () => {
23
+ expect(() => time_parser_1.TimeParser.parseToMilliseconds("")).toThrow(/must be a string/i);
24
+ // Solo espacios
25
+ expect(() => time_parser_1.TimeParser.parseToMilliseconds(" ")).toThrow(/invalid time format/i);
26
+ });
27
+ it("lanza si el formato no coincide con número+unidad", () => {
28
+ for (const bad of ["15", "m15", "1 h", "1w", "1mh", "-5m"]) {
29
+ expect(() => time_parser_1.TimeParser.parseToMilliseconds(bad)).toThrow(/invalid time format/i);
30
+ }
31
+ });
32
+ it("lanza si el valor es 0 (o no positivo)", () => {
33
+ expect(() => time_parser_1.TimeParser.parseToMilliseconds("0m")).toThrow(/invalid time value/i);
34
+ expect(() => time_parser_1.TimeParser.parseToMilliseconds("000s")).toThrow(/invalid time value/i);
35
+ });
36
+ it("acepta ceros a la izquierda válidos (01h -> 1h)", () => {
37
+ expect(time_parser_1.TimeParser.parseToMilliseconds("01h")).toBe(3600000);
38
+ });
39
+ });
40
+ describe("isValidTimeString", () => {
41
+ it.each(["30s", "1m", "2h", "7d", " 2H "])("devuelve true para %s", (input) => {
42
+ expect(time_parser_1.TimeParser.isValidTimeString(input)).toBe(true);
43
+ });
44
+ it.each(["", " ", "1", "m15", "1 h", "1w", "0m", "-5m"])("devuelve false para %s", (input) => {
45
+ expect(time_parser_1.TimeParser.isValidTimeString(input)).toBe(false);
46
+ });
47
+ });
48
+ describe("getSupportedUnits", () => {
49
+ it("devuelve las unidades soportadas en orden estable", () => {
50
+ const units = time_parser_1.TimeParser.getSupportedUnits();
51
+ expect(units).toEqual(["s", "m", "h", "d"]);
52
+ expect(new Set(units)).toEqual(new Set(["s", "m", "h", "d"]));
53
+ });
54
+ });
55
+ describe("formatMilliseconds", () => {
56
+ it.each([
57
+ [1000, "1s"],
58
+ [3000, "3s"],
59
+ [60000, "1m"],
60
+ [120000, "2m"],
61
+ [180000, "3m"],
62
+ [3600000, "1h"],
63
+ [7200000, "2h"],
64
+ [86400000, "1d"],
65
+ [172800000, "2d"],
66
+ ])("formatea %d como %s", (ms, expected) => {
67
+ expect(time_parser_1.TimeParser.formatMilliseconds(ms)).toBe(expected);
68
+ });
69
+ it("elige la unidad más grande divisible exactamente (90_000 -> 90s, no 1.5m)", () => {
70
+ expect(time_parser_1.TimeParser.formatMilliseconds(90000)).toBe("90s");
71
+ });
72
+ it('cuando no es divisible exacto por 1000, devuelve "Xms"', () => {
73
+ expect(time_parser_1.TimeParser.formatMilliseconds(1501)).toBe("1501ms");
74
+ expect(time_parser_1.TimeParser.formatMilliseconds(65001)).toBe("65001ms");
75
+ });
76
+ it('0ms retorna "0ms"', () => {
77
+ expect(time_parser_1.TimeParser.formatMilliseconds(0)).toBe("0ms");
78
+ });
79
+ });
80
+ });
@@ -0,0 +1 @@
1
+ export * from "./time-parser";
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./time-parser"), exports);
@@ -0,0 +1,28 @@
1
+ export declare class TimeParser {
2
+ private static readonly TIME_UNITS;
3
+ private static readonly TIME_PATTERN;
4
+ /**
5
+ * Convierte una cadena de tiempo (ej: "15m", "1h", "7d") a milisegundos
6
+ * @param timeString - Cadena de tiempo en formato número + unidad
7
+ * @returns Tiempo en milisegundos
8
+ * @throws Error si el formato es inválido
9
+ */
10
+ static parseToMilliseconds(timeString: string): number;
11
+ /**
12
+ * Valida si una cadena de tiempo tiene el formato correcto
13
+ * @param timeString - Cadena de tiempo a validar
14
+ * @returns true si es válida, false en caso contrario
15
+ */
16
+ static isValidTimeString(timeString: string): boolean;
17
+ /**
18
+ * Obtiene las unidades de tiempo soportadas
19
+ * @returns Array con las unidades soportadas
20
+ */
21
+ static getSupportedUnits(): string[];
22
+ /**
23
+ * Convierte milisegundos a formato legible
24
+ * @param milliseconds - Tiempo en milisegundos
25
+ * @returns Cadena de tiempo legible
26
+ */
27
+ static formatMilliseconds(milliseconds: number): string;
28
+ }