@patroltech/agent-capabilities 0.0.0-stage → 0.2.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 (443) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +171 -2
  3. package/dist/actions/alerts.d.ts +3 -0
  4. package/dist/actions/alerts.d.ts.map +1 -0
  5. package/dist/actions/alerts.js +90 -0
  6. package/dist/actions/alerts.js.map +1 -0
  7. package/dist/actions/batch-policy.d.ts +67 -0
  8. package/dist/actions/batch-policy.d.ts.map +1 -0
  9. package/dist/actions/batch-policy.js +73 -0
  10. package/dist/actions/batch-policy.js.map +1 -0
  11. package/dist/actions/checkpoint-archive.d.ts +3 -0
  12. package/dist/actions/checkpoint-archive.d.ts.map +1 -0
  13. package/dist/actions/checkpoint-archive.js +173 -0
  14. package/dist/actions/checkpoint-archive.js.map +1 -0
  15. package/dist/actions/checkpoint-geo.d.ts +4 -0
  16. package/dist/actions/checkpoint-geo.d.ts.map +1 -0
  17. package/dist/actions/checkpoint-geo.js +286 -0
  18. package/dist/actions/checkpoint-geo.js.map +1 -0
  19. package/dist/actions/checkpoints.d.ts +10 -0
  20. package/dist/actions/checkpoints.d.ts.map +1 -0
  21. package/dist/actions/checkpoints.js +222 -0
  22. package/dist/actions/checkpoints.js.map +1 -0
  23. package/dist/actions/guard.d.ts +13 -0
  24. package/dist/actions/guard.d.ts.map +1 -0
  25. package/dist/actions/guard.js +30 -0
  26. package/dist/actions/guard.js.map +1 -0
  27. package/dist/actions/incidents.d.ts +3 -0
  28. package/dist/actions/incidents.d.ts.map +1 -0
  29. package/dist/actions/incidents.js +260 -0
  30. package/dist/actions/incidents.js.map +1 -0
  31. package/dist/actions/index.d.ts +20 -0
  32. package/dist/actions/index.d.ts.map +1 -0
  33. package/dist/actions/index.js +60 -0
  34. package/dist/actions/index.js.map +1 -0
  35. package/dist/actions/locations.d.ts +4 -0
  36. package/dist/actions/locations.d.ts.map +1 -0
  37. package/dist/actions/locations.js +202 -0
  38. package/dist/actions/locations.js.map +1 -0
  39. package/dist/actions/names.d.ts +27 -0
  40. package/dist/actions/names.d.ts.map +1 -0
  41. package/dist/actions/names.js +48 -0
  42. package/dist/actions/names.js.map +1 -0
  43. package/dist/actions/patrollers.d.ts +6 -0
  44. package/dist/actions/patrollers.d.ts.map +1 -0
  45. package/dist/actions/patrollers.js +172 -0
  46. package/dist/actions/patrollers.js.map +1 -0
  47. package/dist/actions/route-schedules.d.ts +4 -0
  48. package/dist/actions/route-schedules.d.ts.map +1 -0
  49. package/dist/actions/route-schedules.js +110 -0
  50. package/dist/actions/route-schedules.js.map +1 -0
  51. package/dist/actions/routes.d.ts +5 -0
  52. package/dist/actions/routes.d.ts.map +1 -0
  53. package/dist/actions/routes.js +348 -0
  54. package/dist/actions/routes.js.map +1 -0
  55. package/dist/actions/support/antifraud-rules.d.ts +53 -0
  56. package/dist/actions/support/antifraud-rules.d.ts.map +1 -0
  57. package/dist/actions/support/antifraud-rules.js +121 -0
  58. package/dist/actions/support/antifraud-rules.js.map +1 -0
  59. package/dist/actions/support/elegir-ubicacion.d.ts +31 -0
  60. package/dist/actions/support/elegir-ubicacion.d.ts.map +1 -0
  61. package/dist/actions/support/elegir-ubicacion.js +42 -0
  62. package/dist/actions/support/elegir-ubicacion.js.map +1 -0
  63. package/dist/actions/support/next-step.d.ts +26 -0
  64. package/dist/actions/support/next-step.d.ts.map +1 -0
  65. package/dist/actions/support/next-step.js +55 -0
  66. package/dist/actions/support/next-step.js.map +1 -0
  67. package/dist/actions/support/route-impact.d.ts +25 -0
  68. package/dist/actions/support/route-impact.d.ts.map +1 -0
  69. package/dist/actions/support/route-impact.js +76 -0
  70. package/dist/actions/support/route-impact.js.map +1 -0
  71. package/dist/actions/support/route-lookup.d.ts +27 -0
  72. package/dist/actions/support/route-lookup.d.ts.map +1 -0
  73. package/dist/actions/support/route-lookup.js +44 -0
  74. package/dist/actions/support/route-lookup.js.map +1 -0
  75. package/dist/actions/support/schedule.d.ts +38 -0
  76. package/dist/actions/support/schedule.d.ts.map +1 -0
  77. package/dist/actions/support/schedule.js +62 -0
  78. package/dist/actions/support/schedule.js.map +1 -0
  79. package/dist/actions/support/shared.d.ts +112 -0
  80. package/dist/actions/support/shared.d.ts.map +1 -0
  81. package/dist/actions/support/shared.js +171 -0
  82. package/dist/actions/support/shared.js.map +1 -0
  83. package/dist/actions/support/texts.d.ts +47 -0
  84. package/dist/actions/support/texts.d.ts.map +1 -0
  85. package/dist/actions/support/texts.js +134 -0
  86. package/dist/actions/support/texts.js.map +1 -0
  87. package/dist/actions/support/turno.d.ts +16 -0
  88. package/dist/actions/support/turno.d.ts.map +1 -0
  89. package/dist/actions/support/turno.js +35 -0
  90. package/dist/actions/support/turno.js.map +1 -0
  91. package/dist/actions/support/user-access.d.ts +72 -0
  92. package/dist/actions/support/user-access.d.ts.map +1 -0
  93. package/dist/actions/support/user-access.js +194 -0
  94. package/dist/actions/support/user-access.js.map +1 -0
  95. package/dist/actions/types.d.ts +130 -0
  96. package/dist/actions/types.d.ts.map +1 -0
  97. package/dist/actions/types.js +20 -0
  98. package/dist/actions/types.js.map +1 -0
  99. package/dist/actions/user-roles.d.ts +4 -0
  100. package/dist/actions/user-roles.d.ts.map +1 -0
  101. package/dist/actions/user-roles.js +195 -0
  102. package/dist/actions/user-roles.js.map +1 -0
  103. package/dist/actions/users.d.ts +3 -0
  104. package/dist/actions/users.d.ts.map +1 -0
  105. package/dist/actions/users.js +146 -0
  106. package/dist/actions/users.js.map +1 -0
  107. package/dist/catalog/buildCatalog.d.ts +19 -0
  108. package/dist/catalog/buildCatalog.d.ts.map +1 -0
  109. package/dist/catalog/buildCatalog.js +38 -0
  110. package/dist/catalog/buildCatalog.js.map +1 -0
  111. package/dist/catalog/english.d.ts +17 -0
  112. package/dist/catalog/english.d.ts.map +1 -0
  113. package/dist/catalog/english.js +392 -0
  114. package/dist/catalog/english.js.map +1 -0
  115. package/dist/catalog/entries.d.ts +6 -0
  116. package/dist/catalog/entries.d.ts.map +1 -0
  117. package/dist/catalog/entries.js +610 -0
  118. package/dist/catalog/entries.js.map +1 -0
  119. package/dist/catalog/types.d.ts +61 -0
  120. package/dist/catalog/types.d.ts.map +1 -0
  121. package/dist/catalog/types.js +2 -0
  122. package/dist/catalog/types.js.map +1 -0
  123. package/dist/context.d.ts +37 -0
  124. package/dist/context.d.ts.map +1 -0
  125. package/dist/context.js +11 -0
  126. package/dist/context.js.map +1 -0
  127. package/dist/deps.d.ts +23 -0
  128. package/dist/deps.d.ts.map +1 -0
  129. package/dist/deps.js +12 -0
  130. package/dist/deps.js.map +1 -0
  131. package/dist/domain/access-logs-csv.d.ts +25 -0
  132. package/dist/domain/access-logs-csv.d.ts.map +1 -0
  133. package/dist/domain/access-logs-csv.js +36 -0
  134. package/dist/domain/access-logs-csv.js.map +1 -0
  135. package/dist/domain/backend-errors.d.ts +54 -0
  136. package/dist/domain/backend-errors.d.ts.map +1 -0
  137. package/dist/domain/backend-errors.js +364 -0
  138. package/dist/domain/backend-errors.js.map +1 -0
  139. package/dist/domain/country.d.ts +9 -0
  140. package/dist/domain/country.d.ts.map +1 -0
  141. package/dist/domain/country.js +13 -0
  142. package/dist/domain/country.js.map +1 -0
  143. package/dist/domain/date-range.d.ts +33 -0
  144. package/dist/domain/date-range.d.ts.map +1 -0
  145. package/dist/domain/date-range.js +110 -0
  146. package/dist/domain/date-range.js.map +1 -0
  147. package/dist/domain/geo.d.ts +14 -0
  148. package/dist/domain/geo.d.ts.map +1 -0
  149. package/dist/domain/geo.js +22 -0
  150. package/dist/domain/geo.js.map +1 -0
  151. package/dist/domain/guard-app-message.d.ts +15 -0
  152. package/dist/domain/guard-app-message.d.ts.map +1 -0
  153. package/dist/domain/guard-app-message.js +39 -0
  154. package/dist/domain/guard-app-message.js.map +1 -0
  155. package/dist/domain/incident-priority.d.ts +25 -0
  156. package/dist/domain/incident-priority.d.ts.map +1 -0
  157. package/dist/domain/incident-priority.js +15 -0
  158. package/dist/domain/incident-priority.js.map +1 -0
  159. package/dist/domain/incident-status.d.ts +29 -0
  160. package/dist/domain/incident-status.d.ts.map +1 -0
  161. package/dist/domain/incident-status.js +44 -0
  162. package/dist/domain/incident-status.js.map +1 -0
  163. package/dist/domain/language.d.ts +39 -0
  164. package/dist/domain/language.d.ts.map +1 -0
  165. package/dist/domain/language.js +112 -0
  166. package/dist/domain/language.js.map +1 -0
  167. package/dist/domain/money.d.ts +3 -0
  168. package/dist/domain/money.d.ts.map +1 -0
  169. package/dist/domain/money.js +12 -0
  170. package/dist/domain/money.js.map +1 -0
  171. package/dist/domain/puesta-en-marcha.d.ts +47 -0
  172. package/dist/domain/puesta-en-marcha.d.ts.map +1 -0
  173. package/dist/domain/puesta-en-marcha.js +22 -0
  174. package/dist/domain/puesta-en-marcha.js.map +1 -0
  175. package/dist/domain/qr-image.d.ts +25 -0
  176. package/dist/domain/qr-image.d.ts.map +1 -0
  177. package/dist/domain/qr-image.js +28 -0
  178. package/dist/domain/qr-image.js.map +1 -0
  179. package/dist/domain/resolve-by-name.d.ts +32 -0
  180. package/dist/domain/resolve-by-name.d.ts.map +1 -0
  181. package/dist/domain/resolve-by-name.js +40 -0
  182. package/dist/domain/resolve-by-name.js.map +1 -0
  183. package/dist/domain/route-checkpoints.d.ts +31 -0
  184. package/dist/domain/route-checkpoints.d.ts.map +1 -0
  185. package/dist/domain/route-checkpoints.js +27 -0
  186. package/dist/domain/route-checkpoints.js.map +1 -0
  187. package/dist/domain/route-schedule.d.ts +88 -0
  188. package/dist/domain/route-schedule.d.ts.map +1 -0
  189. package/dist/domain/route-schedule.js +203 -0
  190. package/dist/domain/route-schedule.js.map +1 -0
  191. package/dist/domain/scan-explanation.d.ts +25 -0
  192. package/dist/domain/scan-explanation.d.ts.map +1 -0
  193. package/dist/domain/scan-explanation.js +99 -0
  194. package/dist/domain/scan-explanation.js.map +1 -0
  195. package/dist/domain/scans-csv.d.ts +37 -0
  196. package/dist/domain/scans-csv.d.ts.map +1 -0
  197. package/dist/domain/scans-csv.js +67 -0
  198. package/dist/domain/scans-csv.js.map +1 -0
  199. package/dist/domain/timezone.d.ts +61 -0
  200. package/dist/domain/timezone.d.ts.map +1 -0
  201. package/dist/domain/timezone.js +113 -0
  202. package/dist/domain/timezone.js.map +1 -0
  203. package/dist/domain/tool-result.d.ts +55 -0
  204. package/dist/domain/tool-result.d.ts.map +1 -0
  205. package/dist/domain/tool-result.js +47 -0
  206. package/dist/domain/tool-result.js.map +1 -0
  207. package/dist/domain/urls.d.ts +33 -0
  208. package/dist/domain/urls.d.ts.map +1 -0
  209. package/dist/domain/urls.js +20 -0
  210. package/dist/domain/urls.js.map +1 -0
  211. package/dist/gateway/PatrolTechGateway.d.ts +195 -0
  212. package/dist/gateway/PatrolTechGateway.d.ts.map +1 -0
  213. package/dist/gateway/PatrolTechGateway.js +2 -0
  214. package/dist/gateway/PatrolTechGateway.js.map +1 -0
  215. package/dist/gateway/index.d.ts +4 -0
  216. package/dist/gateway/index.d.ts.map +1 -0
  217. package/dist/gateway/index.js +4 -0
  218. package/dist/gateway/index.js.map +1 -0
  219. package/dist/gateway/sdk/SdkPatrolTechGateway.d.ts +145 -0
  220. package/dist/gateway/sdk/SdkPatrolTechGateway.d.ts.map +1 -0
  221. package/dist/gateway/sdk/SdkPatrolTechGateway.js +101 -0
  222. package/dist/gateway/sdk/SdkPatrolTechGateway.js.map +1 -0
  223. package/dist/gateway/sdk/access.d.ts +8 -0
  224. package/dist/gateway/sdk/access.d.ts.map +1 -0
  225. package/dist/gateway/sdk/access.js +39 -0
  226. package/dist/gateway/sdk/access.js.map +1 -0
  227. package/dist/gateway/sdk/billing.d.ts +7 -0
  228. package/dist/gateway/sdk/billing.d.ts.map +1 -0
  229. package/dist/gateway/sdk/billing.js +92 -0
  230. package/dist/gateway/sdk/billing.js.map +1 -0
  231. package/dist/gateway/sdk/checkpoint-mappers.d.ts +23 -0
  232. package/dist/gateway/sdk/checkpoint-mappers.d.ts.map +1 -0
  233. package/dist/gateway/sdk/checkpoint-mappers.js +59 -0
  234. package/dist/gateway/sdk/checkpoint-mappers.js.map +1 -0
  235. package/dist/gateway/sdk/checkpoints.d.ts +33 -0
  236. package/dist/gateway/sdk/checkpoints.d.ts.map +1 -0
  237. package/dist/gateway/sdk/checkpoints.js +163 -0
  238. package/dist/gateway/sdk/checkpoints.js.map +1 -0
  239. package/dist/gateway/sdk/errors.d.ts +10 -0
  240. package/dist/gateway/sdk/errors.d.ts.map +1 -0
  241. package/dist/gateway/sdk/errors.js +46 -0
  242. package/dist/gateway/sdk/errors.js.map +1 -0
  243. package/dist/gateway/sdk/incidents.d.ts +18 -0
  244. package/dist/gateway/sdk/incidents.d.ts.map +1 -0
  245. package/dist/gateway/sdk/incidents.js +98 -0
  246. package/dist/gateway/sdk/incidents.js.map +1 -0
  247. package/dist/gateway/sdk/index.d.ts +4 -0
  248. package/dist/gateway/sdk/index.d.ts.map +1 -0
  249. package/dist/gateway/sdk/index.js +4 -0
  250. package/dist/gateway/sdk/index.js.map +1 -0
  251. package/dist/gateway/sdk/list.d.ts +15 -0
  252. package/dist/gateway/sdk/list.d.ts.map +1 -0
  253. package/dist/gateway/sdk/list.js +12 -0
  254. package/dist/gateway/sdk/list.js.map +1 -0
  255. package/dist/gateway/sdk/locations.d.ts +24 -0
  256. package/dist/gateway/sdk/locations.d.ts.map +1 -0
  257. package/dist/gateway/sdk/locations.js +44 -0
  258. package/dist/gateway/sdk/locations.js.map +1 -0
  259. package/dist/gateway/sdk/patrollers.d.ts +26 -0
  260. package/dist/gateway/sdk/patrollers.d.ts.map +1 -0
  261. package/dist/gateway/sdk/patrollers.js +132 -0
  262. package/dist/gateway/sdk/patrollers.js.map +1 -0
  263. package/dist/gateway/sdk/rounds.d.ts +15 -0
  264. package/dist/gateway/sdk/rounds.d.ts.map +1 -0
  265. package/dist/gateway/sdk/rounds.js +142 -0
  266. package/dist/gateway/sdk/rounds.js.map +1 -0
  267. package/dist/gateway/sdk/routes.d.ts +18 -0
  268. package/dist/gateway/sdk/routes.d.ts.map +1 -0
  269. package/dist/gateway/sdk/routes.js +74 -0
  270. package/dist/gateway/sdk/routes.js.map +1 -0
  271. package/dist/gateway/sdk/scans.d.ts +4 -0
  272. package/dist/gateway/sdk/scans.d.ts.map +1 -0
  273. package/dist/gateway/sdk/scans.js +72 -0
  274. package/dist/gateway/sdk/scans.js.map +1 -0
  275. package/dist/gateway/sdk/transport.d.ts +77 -0
  276. package/dist/gateway/sdk/transport.d.ts.map +1 -0
  277. package/dist/gateway/sdk/transport.js +81 -0
  278. package/dist/gateway/sdk/transport.js.map +1 -0
  279. package/dist/gateway/sdk/users.d.ts +15 -0
  280. package/dist/gateway/sdk/users.d.ts.map +1 -0
  281. package/dist/gateway/sdk/users.js +49 -0
  282. package/dist/gateway/sdk/users.js.map +1 -0
  283. package/dist/gateway/types/access.d.ts +32 -0
  284. package/dist/gateway/types/access.d.ts.map +1 -0
  285. package/dist/gateway/types/access.js +2 -0
  286. package/dist/gateway/types/access.js.map +1 -0
  287. package/dist/gateway/types/billing.d.ts +60 -0
  288. package/dist/gateway/types/billing.d.ts.map +1 -0
  289. package/dist/gateway/types/billing.js +2 -0
  290. package/dist/gateway/types/billing.js.map +1 -0
  291. package/dist/gateway/types/checkpoints.d.ts +84 -0
  292. package/dist/gateway/types/checkpoints.d.ts.map +1 -0
  293. package/dist/gateway/types/checkpoints.js +2 -0
  294. package/dist/gateway/types/checkpoints.js.map +1 -0
  295. package/dist/gateway/types/common.d.ts +13 -0
  296. package/dist/gateway/types/common.d.ts.map +1 -0
  297. package/dist/gateway/types/common.js +2 -0
  298. package/dist/gateway/types/common.js.map +1 -0
  299. package/dist/gateway/types/incidents.d.ts +53 -0
  300. package/dist/gateway/types/incidents.d.ts.map +1 -0
  301. package/dist/gateway/types/incidents.js +2 -0
  302. package/dist/gateway/types/incidents.js.map +1 -0
  303. package/dist/gateway/types/index.d.ts +12 -0
  304. package/dist/gateway/types/index.d.ts.map +1 -0
  305. package/dist/gateway/types/index.js +12 -0
  306. package/dist/gateway/types/index.js.map +1 -0
  307. package/dist/gateway/types/locations.d.ts +7 -0
  308. package/dist/gateway/types/locations.d.ts.map +1 -0
  309. package/dist/gateway/types/locations.js +2 -0
  310. package/dist/gateway/types/locations.js.map +1 -0
  311. package/dist/gateway/types/patrollers.d.ts +68 -0
  312. package/dist/gateway/types/patrollers.d.ts.map +1 -0
  313. package/dist/gateway/types/patrollers.js +15 -0
  314. package/dist/gateway/types/patrollers.js.map +1 -0
  315. package/dist/gateway/types/rounds.d.ts +89 -0
  316. package/dist/gateway/types/rounds.d.ts.map +1 -0
  317. package/dist/gateway/types/rounds.js +2 -0
  318. package/dist/gateway/types/rounds.js.map +1 -0
  319. package/dist/gateway/types/routes.d.ts +48 -0
  320. package/dist/gateway/types/routes.d.ts.map +1 -0
  321. package/dist/gateway/types/routes.js +2 -0
  322. package/dist/gateway/types/routes.js.map +1 -0
  323. package/dist/gateway/types/scans.d.ts +44 -0
  324. package/dist/gateway/types/scans.d.ts.map +1 -0
  325. package/dist/gateway/types/scans.js +2 -0
  326. package/dist/gateway/types/scans.js.map +1 -0
  327. package/dist/gateway/types/users.d.ts +32 -0
  328. package/dist/gateway/types/users.d.ts.map +1 -0
  329. package/dist/gateway/types/users.js +2 -0
  330. package/dist/gateway/types/users.js.map +1 -0
  331. package/dist/index.d.ts +32 -0
  332. package/dist/index.d.ts.map +1 -0
  333. package/dist/index.js +40 -0
  334. package/dist/index.js.map +1 -0
  335. package/dist/ports/FileSink.d.ts +20 -0
  336. package/dist/ports/FileSink.d.ts.map +1 -0
  337. package/dist/ports/FileSink.js +2 -0
  338. package/dist/ports/FileSink.js.map +1 -0
  339. package/dist/ports/Logger.d.ts +16 -0
  340. package/dist/ports/Logger.d.ts.map +1 -0
  341. package/dist/ports/Logger.js +7 -0
  342. package/dist/ports/Logger.js.map +1 -0
  343. package/dist/ports/PendingActionStore.d.ts +84 -0
  344. package/dist/ports/PendingActionStore.d.ts.map +1 -0
  345. package/dist/ports/PendingActionStore.js +16 -0
  346. package/dist/ports/PendingActionStore.js.map +1 -0
  347. package/dist/reads/access.d.ts +4 -0
  348. package/dist/reads/access.d.ts.map +1 -0
  349. package/dist/reads/access.js +129 -0
  350. package/dist/reads/access.js.map +1 -0
  351. package/dist/reads/checkpoints.d.ts +4 -0
  352. package/dist/reads/checkpoints.d.ts.map +1 -0
  353. package/dist/reads/checkpoints.js +152 -0
  354. package/dist/reads/checkpoints.js.map +1 -0
  355. package/dist/reads/files.d.ts +9 -0
  356. package/dist/reads/files.d.ts.map +1 -0
  357. package/dist/reads/files.js +222 -0
  358. package/dist/reads/files.js.map +1 -0
  359. package/dist/reads/incidents.d.ts +4 -0
  360. package/dist/reads/incidents.d.ts.map +1 -0
  361. package/dist/reads/incidents.js +159 -0
  362. package/dist/reads/incidents.js.map +1 -0
  363. package/dist/reads/index.d.ts +11 -0
  364. package/dist/reads/index.d.ts.map +1 -0
  365. package/dist/reads/index.js +51 -0
  366. package/dist/reads/index.js.map +1 -0
  367. package/dist/reads/onboarding.d.ts +4 -0
  368. package/dist/reads/onboarding.d.ts.map +1 -0
  369. package/dist/reads/onboarding.js +41 -0
  370. package/dist/reads/onboarding.js.map +1 -0
  371. package/dist/reads/organization.d.ts +26 -0
  372. package/dist/reads/organization.d.ts.map +1 -0
  373. package/dist/reads/organization.js +45 -0
  374. package/dist/reads/organization.js.map +1 -0
  375. package/dist/reads/patrollers.d.ts +11 -0
  376. package/dist/reads/patrollers.d.ts.map +1 -0
  377. package/dist/reads/patrollers.js +172 -0
  378. package/dist/reads/patrollers.js.map +1 -0
  379. package/dist/reads/plan.d.ts +4 -0
  380. package/dist/reads/plan.d.ts.map +1 -0
  381. package/dist/reads/plan.js +195 -0
  382. package/dist/reads/plan.js.map +1 -0
  383. package/dist/reads/rounds.d.ts +4 -0
  384. package/dist/reads/rounds.d.ts.map +1 -0
  385. package/dist/reads/rounds.js +160 -0
  386. package/dist/reads/rounds.js.map +1 -0
  387. package/dist/reads/routes.d.ts +4 -0
  388. package/dist/reads/routes.d.ts.map +1 -0
  389. package/dist/reads/routes.js +34 -0
  390. package/dist/reads/routes.js.map +1 -0
  391. package/dist/reads/support/access-locations.d.ts +22 -0
  392. package/dist/reads/support/access-locations.d.ts.map +1 -0
  393. package/dist/reads/support/access-locations.js +55 -0
  394. package/dist/reads/support/access-locations.js.map +1 -0
  395. package/dist/reads/support/excel.d.ts +10 -0
  396. package/dist/reads/support/excel.d.ts.map +1 -0
  397. package/dist/reads/support/excel.js +35 -0
  398. package/dist/reads/support/excel.js.map +1 -0
  399. package/dist/reads/support/params.d.ts +50 -0
  400. package/dist/reads/support/params.d.ts.map +1 -0
  401. package/dist/reads/support/params.js +73 -0
  402. package/dist/reads/support/params.js.map +1 -0
  403. package/dist/reads/support/resolve.d.ts +17 -0
  404. package/dist/reads/support/resolve.d.ts.map +1 -0
  405. package/dist/reads/support/resolve.js +33 -0
  406. package/dist/reads/support/resolve.js.map +1 -0
  407. package/dist/reads/support/results.d.ts +22 -0
  408. package/dist/reads/support/results.d.ts.map +1 -0
  409. package/dist/reads/support/results.js +41 -0
  410. package/dist/reads/support/results.js.map +1 -0
  411. package/dist/reads/support/roles.d.ts +13 -0
  412. package/dist/reads/support/roles.d.ts.map +1 -0
  413. package/dist/reads/support/roles.js +27 -0
  414. package/dist/reads/support/roles.js.map +1 -0
  415. package/dist/reads/support/scans.d.ts +31 -0
  416. package/dist/reads/support/scans.d.ts.map +1 -0
  417. package/dist/reads/support/scans.js +66 -0
  418. package/dist/reads/support/scans.js.map +1 -0
  419. package/dist/reads/types.d.ts +48 -0
  420. package/dist/reads/types.d.ts.map +1 -0
  421. package/dist/reads/types.js +5 -0
  422. package/dist/reads/types.js.map +1 -0
  423. package/dist/reads/users.d.ts +4 -0
  424. package/dist/reads/users.d.ts.map +1 -0
  425. package/dist/reads/users.js +57 -0
  426. package/dist/reads/users.js.map +1 -0
  427. package/dist/testing/FakePatrolTechGateway.d.ts +212 -0
  428. package/dist/testing/FakePatrolTechGateway.d.ts.map +1 -0
  429. package/dist/testing/FakePatrolTechGateway.js +712 -0
  430. package/dist/testing/FakePatrolTechGateway.js.map +1 -0
  431. package/dist/testing/RecordingFileSink.d.ts +12 -0
  432. package/dist/testing/RecordingFileSink.d.ts.map +1 -0
  433. package/dist/testing/RecordingFileSink.js +12 -0
  434. package/dist/testing/RecordingFileSink.js.map +1 -0
  435. package/dist/testing/index.d.ts +4 -0
  436. package/dist/testing/index.d.ts.map +1 -0
  437. package/dist/testing/index.js +4 -0
  438. package/dist/testing/index.js.map +1 -0
  439. package/dist/testing/reads.d.ts +34 -0
  440. package/dist/testing/reads.d.ts.map +1 -0
  441. package/dist/testing/reads.js +39 -0
  442. package/dist/testing/reads.js.map +1 -0
  443. package/package.json +76 -4
@@ -0,0 +1,364 @@
1
+ import { resolveUrls } from './urls.js';
2
+ /**
3
+ * Respuesta no-2xx del backend de PatrolTech, con su cuerpo para poder
4
+ * distinguir el motivo (`code`). La lanza `SdkPatrolTechClient`; el mensaje es el
5
+ * de siempre, así que quien solo mira `err.message` no nota la diferencia.
6
+ */
7
+ export class PatrolTechApiError extends Error {
8
+ status;
9
+ path;
10
+ body;
11
+ constructor(status, path, body) {
12
+ super(`PatrolTech API error ${status} en ${path}`);
13
+ this.status = status;
14
+ this.path = path;
15
+ this.body = body;
16
+ this.name = 'PatrolTechApiError';
17
+ }
18
+ }
19
+ /**
20
+ * Textos al cliente por idioma. `m` es el mensaje del backend (si trae uno) y `precio` el del extra.
21
+ * `dashboard` y `license` son el panel y su página Licencia a los que se deriva al cliente.
22
+ */
23
+ const textsFor = ({ dashboard, license }) => ({
24
+ es: {
25
+ sinCambios: 'No se ha hecho ningún cambio.',
26
+ session_expired: 'Tu sesión con el panel ha caducado y no he podido hacerlo.',
27
+ session_expired_tail: 'Vuelve a pedírmelo.',
28
+ forbidden: 'Tu usuario no tiene permiso para hacer esto en esa organización o ubicación.',
29
+ forbidden_tail: 'Puede hacerlo un administrador de tu cuenta.',
30
+ plan_limit: (m) => m ?? 'Has alcanzado el límite de tu plan.',
31
+ plan_limit_tail: `Puedes ampliar el plan en Licencia: ${license}`,
32
+ plan_limit_users_tail: `Puedes invitarla como Viewer (solo ver), que no ocupa plaza de gestor, o ampliar el plan en Licencia: ${license}`,
33
+ extra_checkpoint: (precio) => `Este checkpoint supera los incluidos en tu plan y añadiría un cargo extra${precio ? ` de ${precio}` : ''}.`,
34
+ extra_checkpoint_tail: `Si quieres añadirlo, créalo desde el panel, donde confirmarás el cargo: ${dashboard}`,
35
+ code_taken: 'Ese código ya lo usa otro checkpoint de tu organización.',
36
+ code_taken_tail: 'Elige otro código o deja que se genere uno automáticamente.',
37
+ checkpoint_archived: 'Ese checkpoint está archivado y un checkpoint archivado no se puede usar en rutas.',
38
+ checkpoint_archived_tail: 'Si vuelve a estar en servicio, desarchívalo primero.',
39
+ checkpoint_other_location: 'Ese checkpoint no es de la ubicación de la ruta: una ruta solo lleva checkpoints de su ubicación.',
40
+ route_without_checkpoints: 'Esa ruta no tiene checkpoints y una ruta sin checkpoints no se puede activar.',
41
+ route_without_checkpoints_tail: 'Añádele checkpoints primero y luego actívala.',
42
+ policies_pending: `Antes de hacer cambios tienes que aceptar las políticas vigentes: entra en el panel (${dashboard}) y acéptalas.`,
43
+ account_suspended: (motivo) => {
44
+ const porque = motivo === 'over_plan_limit'
45
+ ? ' porque usa más puntos de control de los que incluye el plan gratuito'
46
+ : motivo === 'unpaid'
47
+ ? ' por un pago pendiente'
48
+ : '';
49
+ return `La cuenta de esa organización está suspendida${porque}.`;
50
+ },
51
+ account_suspended_unpaid: `Un administrador puede reactivarla pagando o actualizando el método de pago en Licencia: ${license}.`,
52
+ account_suspended_over_plan_limit: `Un administrador puede reactivarla eligiendo un plan en Licencia: ${license}, o escríbeme por aquí si prefieres seguir en el plan gratuito.`,
53
+ account_suspended_manual: 'Si crees que es un error, cuéntamelo y lo reviso con el equipo.',
54
+ invalid_data: (m) => `El panel no ha aceptado los datos${m ? `: ${conPunto(m)}` : '.'}`,
55
+ not_found: 'Eso ya no existe en el panel: quizá se borró desde allí.',
56
+ unavailable: 'No he podido completarlo porque el panel no responde ahora mismo.',
57
+ unavailable_tail: 'Inténtalo de nuevo en unos minutos.',
58
+ locale: 'es-ES',
59
+ alAno: 'al año',
60
+ alMes: 'al mes',
61
+ },
62
+ en: {
63
+ sinCambios: 'No changes have been made.',
64
+ session_expired: 'Your dashboard session has expired and I could not do it.',
65
+ session_expired_tail: 'Please ask me again.',
66
+ forbidden: "Your user doesn't have permission to do this in that organization or location.",
67
+ forbidden_tail: 'An administrator of your account can do it.',
68
+ // El mensaje del backend va en español: en inglés se usa el genérico.
69
+ plan_limit: () => "You've reached your plan's limit.",
70
+ plan_limit_tail: `You can upgrade your plan in License: ${license}`,
71
+ plan_limit_users_tail: `You can invite them as a Viewer (view only), which doesn't use a manager seat, or upgrade your plan in License: ${license}`,
72
+ extra_checkpoint: (precio) => `This checkpoint goes beyond the ones included in your plan and would add an extra charge${precio ? ` of ${precio}` : ''}.`,
73
+ extra_checkpoint_tail: `If you want to add it, create it from the dashboard, where you'll confirm the charge: ${dashboard}`,
74
+ code_taken: 'That code is already used by another checkpoint in your organization.',
75
+ code_taken_tail: 'Choose another code or let one be generated automatically.',
76
+ checkpoint_archived: 'That checkpoint is archived, and an archived checkpoint cannot be used in routes.',
77
+ checkpoint_archived_tail: 'If it is back in service, unarchive it first.',
78
+ checkpoint_other_location: "That checkpoint isn't in the route's location: a route only takes checkpoints of its own location.",
79
+ route_without_checkpoints: "That route has no checkpoints, and a route without checkpoints can't be activated.",
80
+ route_without_checkpoints_tail: 'Add checkpoints to it first, then activate it.',
81
+ policies_pending: `Before making changes you need to accept the current policies: log in to the dashboard (${dashboard}) and accept them.`,
82
+ account_suspended: (motivo) => {
83
+ const porque = motivo === 'over_plan_limit'
84
+ ? ' because it uses more checkpoints than the free plan includes'
85
+ : motivo === 'unpaid'
86
+ ? ' because of a pending payment'
87
+ : '';
88
+ return `That organization's account is suspended${porque}.`;
89
+ },
90
+ account_suspended_unpaid: `An administrator can reactivate it by paying or updating the payment method in License: ${license}.`,
91
+ account_suspended_over_plan_limit: `An administrator can reactivate it by choosing a plan in License: ${license}, or write to me here if you prefer to stay on the free plan.`,
92
+ account_suspended_manual: 'If you think this is a mistake, tell me and I will review it with the team.',
93
+ invalid_data: (m) => `The dashboard didn't accept the data${m ? `: ${conPunto(m)}` : '.'}`,
94
+ not_found: 'That no longer exists in the dashboard: it may have been deleted there.',
95
+ unavailable: "I couldn't complete it because the dashboard isn't responding right now.",
96
+ unavailable_tail: 'Please try again in a few minutes.',
97
+ locale: 'en-GB',
98
+ alAno: 'per year',
99
+ alMes: 'per month',
100
+ },
101
+ fr: {
102
+ sinCambios: "Aucune modification n'a été effectuée.",
103
+ session_expired: "Votre session sur le tableau de bord a expiré et je n'ai pas pu le faire.",
104
+ session_expired_tail: 'Demandez-le-moi à nouveau.',
105
+ forbidden: "Votre utilisateur n'a pas l'autorisation de faire cela dans cette organisation ou ce site.",
106
+ forbidden_tail: 'Un administrateur de votre compte peut le faire.',
107
+ // Igual que en inglés: el mensaje del backend va en español y se usa el genérico.
108
+ plan_limit: () => 'Vous avez atteint la limite de votre forfait.',
109
+ plan_limit_tail: `Vous pouvez changer de forfait dans Licence : ${license}`,
110
+ plan_limit_users_tail: `Vous pouvez inviter cette personne en tant que Viewer (lecture seule), qui n'occupe pas de place de gestionnaire, ou changer de forfait dans Licence : ${license}`,
111
+ extra_checkpoint: (precio) => `Ce checkpoint dépasse ceux inclus dans votre forfait et ajouterait un supplément${precio ? ` de ${precio}` : ''}.`,
112
+ extra_checkpoint_tail: `Si vous voulez l'ajouter, créez-le depuis le tableau de bord, où vous confirmerez le supplément : ${dashboard}`,
113
+ code_taken: 'Ce code est déjà utilisé par un autre checkpoint de votre organisation.',
114
+ code_taken_tail: 'Choisissez un autre code ou laissez-en générer un automatiquement.',
115
+ checkpoint_archived: 'Ce checkpoint est archivé, et un checkpoint archivé ne peut pas être utilisé dans un parcours.',
116
+ checkpoint_archived_tail: "S'il est de nouveau en service, désarchivez-le d'abord.",
117
+ checkpoint_other_location: "Ce checkpoint n'est pas sur le site du parcours : un parcours ne prend que les checkpoints de son site.",
118
+ route_without_checkpoints: "Ce parcours n'a pas de checkpoints, et un parcours sans checkpoints ne peut pas être activé.",
119
+ route_without_checkpoints_tail: "Ajoutez-y d'abord des checkpoints, puis activez-le.",
120
+ policies_pending: `Avant de faire des modifications, vous devez accepter les politiques en vigueur : connectez-vous au tableau de bord (${dashboard}) et acceptez-les.`,
121
+ account_suspended: (motivo) => {
122
+ const porque = motivo === 'over_plan_limit'
123
+ ? " car elle utilise plus de checkpoints que n'en inclut le forfait gratuit"
124
+ : motivo === 'unpaid'
125
+ ? " en raison d'un paiement en attente"
126
+ : '';
127
+ return `Le compte de cette organisation est suspendu${porque}.`;
128
+ },
129
+ account_suspended_unpaid: `Un administrateur peut le réactiver en payant ou en mettant à jour le moyen de paiement dans Licence : ${license}.`,
130
+ account_suspended_over_plan_limit: `Un administrateur peut le réactiver en choisissant un forfait dans Licence : ${license}, ou écrivez-moi ici si vous préférez rester sur le forfait gratuit.`,
131
+ account_suspended_manual: "Si vous pensez qu'il s'agit d'une erreur, dites-le-moi et je vérifierai avec l'équipe.",
132
+ invalid_data: (m) => `Le tableau de bord n'a pas accepté les données${m ? ` : ${conPunto(m)}` : '.'}`,
133
+ not_found: "Cela n'existe plus dans le tableau de bord : il a peut-être été supprimé depuis là.",
134
+ unavailable: "Je n'ai pas pu le faire car le tableau de bord ne répond pas pour le moment.",
135
+ unavailable_tail: 'Réessayez dans quelques minutes.',
136
+ locale: 'fr-FR',
137
+ alAno: 'par an',
138
+ alMes: 'par mois',
139
+ },
140
+ });
141
+ /** Recurso del 402 (`LimitExceededResponse.resource` del backend) en cada idioma. */
142
+ const RECURSO = {
143
+ es: { checkpoints: 'checkpoints', locations: 'ubicaciones', users: 'gestores (Editor o Admin)' },
144
+ en: { checkpoints: 'checkpoints', locations: 'locations', users: 'managers (Editor or Admin)' },
145
+ fr: {
146
+ checkpoints: 'checkpoints',
147
+ locations: 'sites',
148
+ users: 'gestionnaires (Editor ou Admin)',
149
+ },
150
+ };
151
+ /**
152
+ * Los textos que cambian con `upsell: false` (MCP): los límites con sus números,
153
+ * sin nombres de plan, sin «mejorar el plan» y sin enlaces a Licencia. El mensaje
154
+ * del 402 del backend no se repite (nombra el plan).
155
+ */
156
+ const neutralTextsFor = (dashboard) => ({
157
+ es: {
158
+ plan_limit: (l) => l
159
+ ? `Se ha alcanzado el límite de ${l.recurso} de la organización: ${l.limite}${l.enUso !== undefined ? ` (${l.enUso} en uso)` : ''}.`
160
+ : 'Se ha alcanzado un límite de uso de la organización.',
161
+ plan_limit_users_tail: 'Puedes invitarla como Viewer (solo ver), que no ocupa plaza de gestor.',
162
+ extra_checkpoint: (precio) => `Este checkpoint supera los incluidos en la organización y añadiría un cargo extra${precio ? ` de ${precio}` : ''}.`,
163
+ account_suspended: (motivo) => {
164
+ const porque = motivo === 'over_plan_limit'
165
+ ? ' porque usa más puntos de control de los incluidos'
166
+ : motivo === 'unpaid'
167
+ ? ' por un pago pendiente'
168
+ : '';
169
+ return `La cuenta de esa organización está suspendida${porque}.`;
170
+ },
171
+ account_suspended_tail: `Un administrador puede reactivarla desde el panel: ${dashboard}.`,
172
+ },
173
+ en: {
174
+ plan_limit: (l) => l
175
+ ? `The organization has reached its ${l.recurso} limit: ${l.limite}${l.enUso !== undefined ? ` (${l.enUso} in use)` : ''}.`
176
+ : 'The organization has reached a usage limit.',
177
+ plan_limit_users_tail: "You can invite them as a Viewer (view only), which doesn't use a manager seat.",
178
+ extra_checkpoint: (precio) => `This checkpoint goes beyond the ones included for the organization and would add an extra charge${precio ? ` of ${precio}` : ''}.`,
179
+ account_suspended: (motivo) => {
180
+ const porque = motivo === 'over_plan_limit'
181
+ ? ' because it uses more checkpoints than are included'
182
+ : motivo === 'unpaid'
183
+ ? ' because of a pending payment'
184
+ : '';
185
+ return `That organization's account is suspended${porque}.`;
186
+ },
187
+ account_suspended_tail: `An administrator can reactivate it from the dashboard: ${dashboard}.`,
188
+ },
189
+ fr: {
190
+ plan_limit: (l) => l
191
+ ? `L'organisation a atteint sa limite de ${l.recurso} : ${l.limite}${l.enUso !== undefined ? ` (${l.enUso} utilisés)` : ''}.`
192
+ : "L'organisation a atteint une limite d'utilisation.",
193
+ plan_limit_users_tail: "Vous pouvez inviter cette personne en tant que Viewer (lecture seule), qui n'occupe pas de place de gestionnaire.",
194
+ extra_checkpoint: (precio) => `Ce checkpoint dépasse ceux inclus pour l'organisation et ajouterait un supplément${precio ? ` de ${precio}` : ''}.`,
195
+ account_suspended: (motivo) => {
196
+ const porque = motivo === 'over_plan_limit'
197
+ ? ' car elle utilise plus de checkpoints que ceux inclus'
198
+ : motivo === 'unpaid'
199
+ ? " en raison d'un paiement en attente"
200
+ : '';
201
+ return `Le compte de cette organisation est suspendu${porque}.`;
202
+ },
203
+ account_suspended_tail: `Un administrateur peut le réactiver depuis le tableau de bord : ${dashboard}.`,
204
+ },
205
+ });
206
+ function limiteDel402(body, idioma) {
207
+ const limite = field(body, 'limit');
208
+ if (typeof limite !== 'number')
209
+ return undefined;
210
+ const enUso = field(body, 'currentUsage');
211
+ const resource = text(field(body, 'resource')) ?? 'checkpoints';
212
+ return {
213
+ limite,
214
+ enUso: typeof enUso === 'number' ? enUso : undefined,
215
+ recurso: RECURSO[idioma][resource] ?? RECURSO[idioma].checkpoints,
216
+ };
217
+ }
218
+ /**
219
+ * Traduce un fallo al llamar al backend a lo que se le dice al cliente, en su
220
+ * idioma (`es`, `en` o `fr`, ver `fixedTextLanguage`). Acepta cualquier cosa
221
+ * capturada: lo que no es un `PatrolTechApiError` (timeout, red) es `unavailable`.
222
+ * `opts.urls` son los enlaces a los que se deriva al cliente (por defecto, los de producción) y
223
+ * `opts.upsell: false` quita el plan y la Licencia de los límites (402, 409 de extra, 423) y
224
+ * `opts.operation: 'read'` quita «No se ha hecho ningún cambio» (una lectura nunca cambia nada).
225
+ *
226
+ * Forma del cuerpo de error del backend: los errores con `apiErrorBody` llevan
227
+ * `code` y `message` en primer nivel (402 de límite, 409 de extra y de código);
228
+ * el resto pasa por el envelope global, que deja `message` arriba (o «Error» si
229
+ * no había) y mete el cuerpo original en `meta` (401 `TOKEN_EXPIRED`, 451 de
230
+ * políticas, 400 `VALIDATION_ERROR` con su `error.message`).
231
+ */
232
+ export function translateBackendError(err, idioma = 'es', opts = {}) {
233
+ const urls = resolveUrls(opts.urls);
234
+ const t = textsFor(urls)[idioma];
235
+ const neutral = opts.upsell === false ? neutralTextsFor(urls.dashboard)[idioma] : undefined;
236
+ // En una lectura no hay cambios que negar: la frase sobra (y despista).
237
+ const sinCambios = opts.operation === 'read' ? '' : t.sinCambios;
238
+ const say = (kind, ...parts) => ({
239
+ kind,
240
+ mensajeCliente: parts.filter((part) => part.length > 0).join(' '),
241
+ });
242
+ const unavailable = () => say('unavailable', t.unavailable, sinCambios, t.unavailable_tail);
243
+ if (!(err instanceof PatrolTechApiError))
244
+ return unavailable();
245
+ const { status } = err;
246
+ const { code, message, reason } = readErrorBody(err.body);
247
+ if (status === 401)
248
+ return say('session_expired', t.session_expired, sinCambios, t.session_expired_tail);
249
+ if (status === 403)
250
+ return say('forbidden', t.forbidden, sinCambios, t.forbidden_tail);
251
+ if (status === 402) {
252
+ // Sin asientos de gestor (invitar a un Editor o Admin): un Viewer no ocupa plaza.
253
+ const deGestores = code === 'USER_LIMIT_REACHED';
254
+ if (neutral) {
255
+ const limite = neutral.plan_limit(limiteDel402(err.body, idioma));
256
+ const tail = deGestores ? [neutral.plan_limit_users_tail] : [];
257
+ return say('plan_limit', limite, sinCambios, ...tail);
258
+ }
259
+ const tail = deGestores ? t.plan_limit_users_tail : t.plan_limit_tail;
260
+ return say('plan_limit', t.plan_limit(message), sinCambios, tail);
261
+ }
262
+ if (status === 409 && code === 'EXTRA_CHECKPOINT_CONFIRMATION_REQUIRED') {
263
+ // Nunca se confirma el cobro desde el bot (`confirmExtraBilling`): se deriva al panel.
264
+ const precio = extraPrice(err.body, t);
265
+ return say('extra_checkpoint', neutral ? neutral.extra_checkpoint(precio) : t.extra_checkpoint(precio), sinCambios, t.extra_checkpoint_tail);
266
+ }
267
+ if (status === 409 && code === 'VERIFICATION_CODE_TAKEN')
268
+ return say('code_taken', t.code_taken, sinCambios, t.code_taken_tail);
269
+ // Rutas: el checkpoint se archivó o no es del sitio entre proponer y confirmar (el mensaje del backend va en inglés).
270
+ if (status === 400 && code === 'CHECKPOINT_ARCHIVED') {
271
+ return say('checkpoint_archived', t.checkpoint_archived, sinCambios, t.checkpoint_archived_tail);
272
+ }
273
+ if (status === 400 && code === 'CHECKPOINT_NOT_IN_ROUTE_LOCATION') {
274
+ return say('checkpoint_other_location', t.checkpoint_other_location, sinCambios);
275
+ }
276
+ // Activar una ruta sin checkpoints (se ha vaciado entre proponer y confirmar, o la crea vacía otro camino).
277
+ if (status === 400 && code === 'ROUTE_HAS_NO_CHECKPOINTS') {
278
+ return say('route_without_checkpoints', t.route_without_checkpoints, sinCambios, t.route_without_checkpoints_tail);
279
+ }
280
+ if (status === 423 && code === 'ORGANIZATION_SUSPENDED') {
281
+ if (neutral) {
282
+ const conPago = reason === 'unpaid' || reason === 'over_plan_limit';
283
+ const tail = conPago ? neutral.account_suspended_tail : t.account_suspended_manual;
284
+ return say('account_suspended', neutral.account_suspended(reason), sinCambios, tail);
285
+ }
286
+ const tail = reason === 'unpaid'
287
+ ? t.account_suspended_unpaid
288
+ : reason === 'over_plan_limit'
289
+ ? t.account_suspended_over_plan_limit
290
+ : t.account_suspended_manual;
291
+ return say('account_suspended', t.account_suspended(reason), sinCambios, tail);
292
+ }
293
+ if (status === 451)
294
+ return say('policies_pending', t.policies_pending, sinCambios);
295
+ // 404: se borró (desde el panel o en otra conversación) entre proponer y confirmar.
296
+ if (status === 404)
297
+ return say('not_found', t.not_found, sinCambios);
298
+ // El mensaje del backend solo se repite en español y si se entiende: en inglés y francés (va en
299
+ // español o es técnico) y los internos («unique_user_role_scope already exists») van con el genérico.
300
+ const legible = idioma === 'es' && message && !MENSAJE_TECNICO_RE.test(message) ? message : undefined;
301
+ if (status >= 400 && status < 500)
302
+ return say('invalid_data', t.invalid_data(legible), sinCambios);
303
+ return unavailable();
304
+ }
305
+ /**
306
+ * `translateBackendError` para quien EJECUTA una acción confirmada en un canal
307
+ * sin upsell (el MCP): el rechazo del backend en el idioma del cliente, con los
308
+ * límites en números y sin nombres de plan ni enlaces a Licencia.
309
+ */
310
+ export function translateActionError(err, language, urls) {
311
+ return translateBackendError(err, language, { urls, upsell: false });
312
+ }
313
+ /** Mensajes del backend que no son para el cliente: restricciones de la BD, validación genérica, inglés técnico. */
314
+ const MENSAJE_TECNICO_RE = /already exists|validation failed|constraint|violat|sequelize|duplicate key|not found|\w+_\w+/i;
315
+ /** El mensaje del backend termina en punto para que no se pegue con «No se ha hecho ningún cambio.». */
316
+ function conPunto(m) {
317
+ return /[.!?…]$/.test(m) ? m : `${m}.`;
318
+ }
319
+ function field(obj, key) {
320
+ return obj && typeof obj === 'object' ? obj[key] : undefined;
321
+ }
322
+ function text(v) {
323
+ return typeof v === 'string' && v.trim().length > 0 ? v.trim() : undefined;
324
+ }
325
+ function readErrorBody(body) {
326
+ const meta = field(body, 'meta');
327
+ // El 423 de suspensión lleva `code` y `reason` dentro de `data`.
328
+ const data = field(body, 'data');
329
+ const code = text(field(body, 'code')) ??
330
+ text(field(data, 'code')) ??
331
+ text(field(meta, 'code')) ??
332
+ text(field(field(meta, 'error'), 'code'));
333
+ const reason = text(field(data, 'reason'));
334
+ // «Error» es lo que pone el envelope cuando el cuerpo original no traía mensaje.
335
+ const top = text(field(body, 'message'));
336
+ const message = (top !== 'Error' ? top : undefined) ?? text(field(field(meta, 'error'), 'message'));
337
+ return { code, message, reason };
338
+ }
339
+ /** El `code` con el que el backend explica un rechazo, esté donde esté en el cuerpo. */
340
+ export function backendErrorCode(err) {
341
+ return readErrorBody(err.body).code;
342
+ }
343
+ /** `extraPrice` del 409: importe en céntimos, moneda e intervalo en que se cobra. */
344
+ function extraPrice(body, t) {
345
+ const p = field(body, 'extraPrice');
346
+ const amount = field(p, 'amount');
347
+ const currency = text(field(p, 'currency'));
348
+ const interval = field(p, 'interval');
349
+ if (typeof amount !== 'number' || !currency)
350
+ return undefined;
351
+ const importe = new Intl.NumberFormat(t.locale, { style: 'currency', currency }).format(amount / 100);
352
+ return `${importe} ${interval === 'year' ? t.alAno : t.alMes}`;
353
+ }
354
+ /**
355
+ * ¿El backend rechazó porque la App (Incidencias, Control de Acceso) no está
356
+ * activa en la organización? `requireFeature` responde 403 «Feature '<key>' is
357
+ * not enabled for this organization»: no es falta de permiso del usuario.
358
+ */
359
+ export function isFeatureDisabled(err) {
360
+ return (err instanceof PatrolTechApiError &&
361
+ err.status === 403 &&
362
+ /is not enabled/i.test(readErrorBody(err.body).message ?? ''));
363
+ }
364
+ //# sourceMappingURL=backend-errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backend-errors.js","sourceRoot":"","sources":["../../src/domain/backend-errors.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAA+C,MAAM,WAAW,CAAC;AAErF;;;;GAIG;AACH,MAAM,OAAO,kBAAmB,SAAQ,KAAK;IAEhC;IACA;IACA;IAHX,YACW,MAAc,EACd,IAAY,EACZ,IAAa;QAEtB,KAAK,CAAC,wBAAwB,MAAM,OAAO,IAAI,EAAE,CAAC,CAAC;QAJ1C,WAAM,GAAN,MAAM,CAAQ;QACd,SAAI,GAAJ,IAAI,CAAQ;QACZ,SAAI,GAAJ,IAAI,CAAS;QAGtB,IAAI,CAAC,IAAI,GAAG,oBAAoB,CAAC;IACnC,CAAC;CACF;AAuBD;;;GAGG;AACH,MAAM,QAAQ,GAAG,CAAC,EAAE,SAAS,EAAE,OAAO,EAAkB,EAAE,EAAE,CAC1D,CAAC;IACC,EAAE,EAAE;QACF,UAAU,EAAE,+BAA+B;QAC3C,eAAe,EAAE,4DAA4D;QAC7E,oBAAoB,EAAE,qBAAqB;QAC3C,SAAS,EAAE,8EAA8E;QACzF,cAAc,EAAE,8CAA8C;QAC9D,UAAU,EAAE,CAAC,CAAU,EAAE,EAAE,CAAC,CAAC,IAAI,qCAAqC;QACtE,eAAe,EAAE,uCAAuC,OAAO,EAAE;QACjE,qBAAqB,EAAE,yGAAyG,OAAO,EAAE;QACzI,gBAAgB,EAAE,CAAC,MAAe,EAAE,EAAE,CACpC,4EAA4E,MAAM,CAAC,CAAC,CAAC,OAAO,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG;QAC9G,qBAAqB,EAAE,2EAA2E,SAAS,EAAE;QAC7G,UAAU,EAAE,0DAA0D;QACtE,eAAe,EAAE,6DAA6D;QAC9E,mBAAmB,EACjB,oFAAoF;QACtF,wBAAwB,EAAE,sDAAsD;QAChF,yBAAyB,EACvB,mGAAmG;QACrG,yBAAyB,EACvB,+EAA+E;QACjF,8BAA8B,EAAE,+CAA+C;QAC/E,gBAAgB,EAAE,wFAAwF,SAAS,gBAAgB;QACnI,iBAAiB,EAAE,CAAC,MAAe,EAAE,EAAE;YACrC,MAAM,MAAM,GACV,MAAM,KAAK,iBAAiB;gBAC1B,CAAC,CAAC,uEAAuE;gBACzE,CAAC,CAAC,MAAM,KAAK,QAAQ;oBACnB,CAAC,CAAC,wBAAwB;oBAC1B,CAAC,CAAC,EAAE,CAAC;YACX,OAAO,gDAAgD,MAAM,GAAG,CAAC;QACnE,CAAC;QACD,wBAAwB,EAAE,4FAA4F,OAAO,GAAG;QAChI,iCAAiC,EAAE,qEAAqE,OAAO,iEAAiE;QAChL,wBAAwB,EAAE,iEAAiE;QAC3F,YAAY,EAAE,CAAC,CAAU,EAAE,EAAE,CAC3B,oCAAoC,CAAC,CAAC,CAAC,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,EAAE;QACpE,SAAS,EAAE,0DAA0D;QACrE,WAAW,EAAE,mEAAmE;QAChF,gBAAgB,EAAE,qCAAqC;QACvD,MAAM,EAAE,OAAO;QACf,KAAK,EAAE,QAAQ;QACf,KAAK,EAAE,QAAQ;KAChB;IACD,EAAE,EAAE;QACF,UAAU,EAAE,4BAA4B;QACxC,eAAe,EAAE,2DAA2D;QAC5E,oBAAoB,EAAE,sBAAsB;QAC5C,SAAS,EAAE,gFAAgF;QAC3F,cAAc,EAAE,6CAA6C;QAC7D,sEAAsE;QACtE,UAAU,EAAE,GAAG,EAAE,CAAC,mCAAmC;QACrD,eAAe,EAAE,yCAAyC,OAAO,EAAE;QACnE,qBAAqB,EAAE,mHAAmH,OAAO,EAAE;QACnJ,gBAAgB,EAAE,CAAC,MAAe,EAAE,EAAE,CACpC,2FAA2F,MAAM,CAAC,CAAC,CAAC,OAAO,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG;QAC7H,qBAAqB,EAAE,yFAAyF,SAAS,EAAE;QAC3H,UAAU,EAAE,uEAAuE;QACnF,eAAe,EAAE,4DAA4D;QAC7E,mBAAmB,EACjB,mFAAmF;QACrF,wBAAwB,EAAE,+CAA+C;QACzE,yBAAyB,EACvB,oGAAoG;QACtG,yBAAyB,EACvB,oFAAoF;QACtF,8BAA8B,EAAE,gDAAgD;QAChF,gBAAgB,EAAE,2FAA2F,SAAS,oBAAoB;QAC1I,iBAAiB,EAAE,CAAC,MAAe,EAAE,EAAE;YACrC,MAAM,MAAM,GACV,MAAM,KAAK,iBAAiB;gBAC1B,CAAC,CAAC,+DAA+D;gBACjE,CAAC,CAAC,MAAM,KAAK,QAAQ;oBACnB,CAAC,CAAC,+BAA+B;oBACjC,CAAC,CAAC,EAAE,CAAC;YACX,OAAO,2CAA2C,MAAM,GAAG,CAAC;QAC9D,CAAC;QACD,wBAAwB,EAAE,2FAA2F,OAAO,GAAG;QAC/H,iCAAiC,EAAE,qEAAqE,OAAO,+DAA+D;QAC9K,wBAAwB,EACtB,6EAA6E;QAC/E,YAAY,EAAE,CAAC,CAAU,EAAE,EAAE,CAC3B,uCAAuC,CAAC,CAAC,CAAC,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,EAAE;QACvE,SAAS,EAAE,yEAAyE;QACpF,WAAW,EAAE,0EAA0E;QACvF,gBAAgB,EAAE,oCAAoC;QACtD,MAAM,EAAE,OAAO;QACf,KAAK,EAAE,UAAU;QACjB,KAAK,EAAE,WAAW;KACnB;IACD,EAAE,EAAE;QACF,UAAU,EAAE,wCAAwC;QACpD,eAAe,EAAE,2EAA2E;QAC5F,oBAAoB,EAAE,4BAA4B;QAClD,SAAS,EACP,4FAA4F;QAC9F,cAAc,EAAE,kDAAkD;QAClE,kFAAkF;QAClF,UAAU,EAAE,GAAG,EAAE,CAAC,+CAA+C;QACjE,eAAe,EAAE,iDAAiD,OAAO,EAAE;QAC3E,qBAAqB,EAAE,0JAA0J,OAAO,EAAE;QAC1L,gBAAgB,EAAE,CAAC,MAAe,EAAE,EAAE,CACpC,mFAAmF,MAAM,CAAC,CAAC,CAAC,OAAO,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG;QACrH,qBAAqB,EAAE,qGAAqG,SAAS,EAAE;QACvI,UAAU,EAAE,yEAAyE;QACrF,eAAe,EAAE,oEAAoE;QACrF,mBAAmB,EACjB,gGAAgG;QAClG,wBAAwB,EAAE,yDAAyD;QACnF,yBAAyB,EACvB,yGAAyG;QAC3G,yBAAyB,EACvB,8FAA8F;QAChG,8BAA8B,EAAE,qDAAqD;QACrF,gBAAgB,EAAE,wHAAwH,SAAS,oBAAoB;QACvK,iBAAiB,EAAE,CAAC,MAAe,EAAE,EAAE;YACrC,MAAM,MAAM,GACV,MAAM,KAAK,iBAAiB;gBAC1B,CAAC,CAAC,0EAA0E;gBAC5E,CAAC,CAAC,MAAM,KAAK,QAAQ;oBACnB,CAAC,CAAC,qCAAqC;oBACvC,CAAC,CAAC,EAAE,CAAC;YACX,OAAO,+CAA+C,MAAM,GAAG,CAAC;QAClE,CAAC;QACD,wBAAwB,EAAE,0GAA0G,OAAO,GAAG;QAC9I,iCAAiC,EAAE,gFAAgF,OAAO,sEAAsE;QAChM,wBAAwB,EACtB,wFAAwF;QAC1F,YAAY,EAAE,CAAC,CAAU,EAAE,EAAE,CAC3B,iDAAiD,CAAC,CAAC,CAAC,CAAC,MAAM,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,EAAE;QAClF,SAAS,EACP,qFAAqF;QACvF,WAAW,EAAE,8EAA8E;QAC3F,gBAAgB,EAAE,kCAAkC;QACpD,MAAM,EAAE,OAAO;QACf,KAAK,EAAE,QAAQ;QACf,KAAK,EAAE,UAAU;KAClB;CACF,CAAuD,CAAC;AAE3D,qFAAqF;AACrF,MAAM,OAAO,GAAsD;IACjE,EAAE,EAAE,EAAE,WAAW,EAAE,aAAa,EAAE,SAAS,EAAE,aAAa,EAAE,KAAK,EAAE,2BAA2B,EAAE;IAChG,EAAE,EAAE,EAAE,WAAW,EAAE,aAAa,EAAE,SAAS,EAAE,WAAW,EAAE,KAAK,EAAE,4BAA4B,EAAE;IAC/F,EAAE,EAAE;QACF,WAAW,EAAE,aAAa;QAC1B,SAAS,EAAE,OAAO;QAClB,KAAK,EAAE,iCAAiC;KACzC;CACF,CAAC;AASF;;;;GAIG;AACH,MAAM,eAAe,GAAG,CAAC,SAAiB,EAAE,EAAE,CAC5C,CAAC;IACC,EAAE,EAAE;QACF,UAAU,EAAE,CAAC,CAAU,EAAE,EAAE,CACzB,CAAC;YACC,CAAC,CAAC,gCAAgC,CAAC,CAAC,OAAO,wBAAwB,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,UAAU,CAAC,CAAC,CAAC,EAAE,GAAG;YACpI,CAAC,CAAC,sDAAsD;QAC5D,qBAAqB,EACnB,wEAAwE;QAC1E,gBAAgB,EAAE,CAAC,MAAe,EAAE,EAAE,CACpC,oFAAoF,MAAM,CAAC,CAAC,CAAC,OAAO,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG;QACtH,iBAAiB,EAAE,CAAC,MAAe,EAAE,EAAE;YACrC,MAAM,MAAM,GACV,MAAM,KAAK,iBAAiB;gBAC1B,CAAC,CAAC,oDAAoD;gBACtD,CAAC,CAAC,MAAM,KAAK,QAAQ;oBACnB,CAAC,CAAC,wBAAwB;oBAC1B,CAAC,CAAC,EAAE,CAAC;YACX,OAAO,gDAAgD,MAAM,GAAG,CAAC;QACnE,CAAC;QACD,sBAAsB,EAAE,sDAAsD,SAAS,GAAG;KAC3F;IACD,EAAE,EAAE;QACF,UAAU,EAAE,CAAC,CAAU,EAAE,EAAE,CACzB,CAAC;YACC,CAAC,CAAC,oCAAoC,CAAC,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,UAAU,CAAC,CAAC,CAAC,EAAE,GAAG;YAC3H,CAAC,CAAC,6CAA6C;QACnD,qBAAqB,EACnB,gFAAgF;QAClF,gBAAgB,EAAE,CAAC,MAAe,EAAE,EAAE,CACpC,mGAAmG,MAAM,CAAC,CAAC,CAAC,OAAO,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG;QACrI,iBAAiB,EAAE,CAAC,MAAe,EAAE,EAAE;YACrC,MAAM,MAAM,GACV,MAAM,KAAK,iBAAiB;gBAC1B,CAAC,CAAC,qDAAqD;gBACvD,CAAC,CAAC,MAAM,KAAK,QAAQ;oBACnB,CAAC,CAAC,+BAA+B;oBACjC,CAAC,CAAC,EAAE,CAAC;YACX,OAAO,2CAA2C,MAAM,GAAG,CAAC;QAC9D,CAAC;QACD,sBAAsB,EAAE,0DAA0D,SAAS,GAAG;KAC/F;IACD,EAAE,EAAE;QACF,UAAU,EAAE,CAAC,CAAU,EAAE,EAAE,CACzB,CAAC;YACC,CAAC,CAAC,yCAAyC,CAAC,CAAC,OAAO,MAAM,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,YAAY,CAAC,CAAC,CAAC,EAAE,GAAG;YAC7H,CAAC,CAAC,oDAAoD;QAC1D,qBAAqB,EACnB,mHAAmH;QACrH,gBAAgB,EAAE,CAAC,MAAe,EAAE,EAAE,CACpC,oFAAoF,MAAM,CAAC,CAAC,CAAC,OAAO,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG;QACtH,iBAAiB,EAAE,CAAC,MAAe,EAAE,EAAE;YACrC,MAAM,MAAM,GACV,MAAM,KAAK,iBAAiB;gBAC1B,CAAC,CAAC,uDAAuD;gBACzD,CAAC,CAAC,MAAM,KAAK,QAAQ;oBACnB,CAAC,CAAC,qCAAqC;oBACvC,CAAC,CAAC,EAAE,CAAC;YACX,OAAO,+CAA+C,MAAM,GAAG,CAAC;QAClE,CAAC;QACD,sBAAsB,EAAE,mEAAmE,SAAS,GAAG;KACxG;CACF,CAAuD,CAAC;AAE3D,SAAS,YAAY,CAAC,IAAa,EAAE,MAAyB;IAC5D,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACpC,IAAI,OAAO,MAAM,KAAK,QAAQ;QAAE,OAAO,SAAS,CAAC;IACjD,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC;IAC1C,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC,IAAI,aAAa,CAAC;IAChE,OAAO;QACL,MAAM;QACN,KAAK,EAAE,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS;QACpD,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC,WAAW;KAClE,CAAC;AACJ,CAAC;AAQD;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,qBAAqB,CACnC,GAAY,EACZ,SAA4B,IAAI,EAChC,OAA8B,EAAE;IAEhC,MAAM,IAAI,GAAG,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACpC,MAAM,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC;IACjC,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,KAAK,KAAK,CAAC,CAAC,CAAC,eAAe,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAC5F,wEAAwE;IACxE,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,KAAK,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC;IACjE,MAAM,GAAG,GAAG,CAAC,IAAsB,EAAE,GAAG,KAAe,EAAkB,EAAE,CAAC,CAAC;QAC3E,IAAI;QACJ,cAAc,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;KAClE,CAAC,CAAC;IACH,MAAM,WAAW,GAAG,GAAG,EAAE,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC,CAAC,WAAW,EAAE,UAAU,EAAE,CAAC,CAAC,gBAAgB,CAAC,CAAC;IAC5F,IAAI,CAAC,CAAC,GAAG,YAAY,kBAAkB,CAAC;QAAE,OAAO,WAAW,EAAE,CAAC;IAC/D,MAAM,EAAE,MAAM,EAAE,GAAG,GAAG,CAAC;IACvB,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAE1D,IAAI,MAAM,KAAK,GAAG;QAChB,OAAO,GAAG,CAAC,iBAAiB,EAAE,CAAC,CAAC,eAAe,EAAE,UAAU,EAAE,CAAC,CAAC,oBAAoB,CAAC,CAAC;IACvF,IAAI,MAAM,KAAK,GAAG;QAAE,OAAO,GAAG,CAAC,WAAW,EAAE,CAAC,CAAC,SAAS,EAAE,UAAU,EAAE,CAAC,CAAC,cAAc,CAAC,CAAC;IACvF,IAAI,MAAM,KAAK,GAAG,EAAE,CAAC;QACnB,kFAAkF;QAClF,MAAM,UAAU,GAAG,IAAI,KAAK,oBAAoB,CAAC;QACjD,IAAI,OAAO,EAAE,CAAC;YACZ,MAAM,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;YAClE,MAAM,IAAI,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YAC/D,OAAO,GAAG,CAAC,YAAY,EAAE,MAAM,EAAE,UAAU,EAAE,GAAG,IAAI,CAAC,CAAC;QACxD,CAAC;QACD,MAAM,IAAI,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC;QACtE,OAAO,GAAG,CAAC,YAAY,EAAE,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,UAAU,EAAE,IAAI,CAAC,CAAC;IACpE,CAAC;IACD,IAAI,MAAM,KAAK,GAAG,IAAI,IAAI,KAAK,wCAAwC,EAAE,CAAC;QACxE,uFAAuF;QACvF,MAAM,MAAM,GAAG,UAAU,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;QACvC,OAAO,GAAG,CACR,kBAAkB,EAClB,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,gBAAgB,CAAC,MAAM,CAAC,EACvE,UAAU,EACV,CAAC,CAAC,qBAAqB,CACxB,CAAC;IACJ,CAAC;IACD,IAAI,MAAM,KAAK,GAAG,IAAI,IAAI,KAAK,yBAAyB;QACtD,OAAO,GAAG,CAAC,YAAY,EAAE,CAAC,CAAC,UAAU,EAAE,UAAU,EAAE,CAAC,CAAC,eAAe,CAAC,CAAC;IACxE,sHAAsH;IACtH,IAAI,MAAM,KAAK,GAAG,IAAI,IAAI,KAAK,qBAAqB,EAAE,CAAC;QACrD,OAAO,GAAG,CACR,qBAAqB,EACrB,CAAC,CAAC,mBAAmB,EACrB,UAAU,EACV,CAAC,CAAC,wBAAwB,CAC3B,CAAC;IACJ,CAAC;IACD,IAAI,MAAM,KAAK,GAAG,IAAI,IAAI,KAAK,kCAAkC,EAAE,CAAC;QAClE,OAAO,GAAG,CAAC,2BAA2B,EAAE,CAAC,CAAC,yBAAyB,EAAE,UAAU,CAAC,CAAC;IACnF,CAAC;IACD,4GAA4G;IAC5G,IAAI,MAAM,KAAK,GAAG,IAAI,IAAI,KAAK,0BAA0B,EAAE,CAAC;QAC1D,OAAO,GAAG,CACR,2BAA2B,EAC3B,CAAC,CAAC,yBAAyB,EAC3B,UAAU,EACV,CAAC,CAAC,8BAA8B,CACjC,CAAC;IACJ,CAAC;IACD,IAAI,MAAM,KAAK,GAAG,IAAI,IAAI,KAAK,wBAAwB,EAAE,CAAC;QACxD,IAAI,OAAO,EAAE,CAAC;YACZ,MAAM,OAAO,GAAG,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,iBAAiB,CAAC;YACpE,MAAM,IAAI,GAAG,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,sBAAsB,CAAC,CAAC,CAAC,CAAC,CAAC,wBAAwB,CAAC;YACnF,OAAO,GAAG,CAAC,mBAAmB,EAAE,OAAO,CAAC,iBAAiB,CAAC,MAAM,CAAC,EAAE,UAAU,EAAE,IAAI,CAAC,CAAC;QACvF,CAAC;QACD,MAAM,IAAI,GACR,MAAM,KAAK,QAAQ;YACjB,CAAC,CAAC,CAAC,CAAC,wBAAwB;YAC5B,CAAC,CAAC,MAAM,KAAK,iBAAiB;gBAC5B,CAAC,CAAC,CAAC,CAAC,iCAAiC;gBACrC,CAAC,CAAC,CAAC,CAAC,wBAAwB,CAAC;QACnC,OAAO,GAAG,CAAC,mBAAmB,EAAE,CAAC,CAAC,iBAAiB,CAAC,MAAM,CAAC,EAAE,UAAU,EAAE,IAAI,CAAC,CAAC;IACjF,CAAC;IACD,IAAI,MAAM,KAAK,GAAG;QAAE,OAAO,GAAG,CAAC,kBAAkB,EAAE,CAAC,CAAC,gBAAgB,EAAE,UAAU,CAAC,CAAC;IACnF,oFAAoF;IACpF,IAAI,MAAM,KAAK,GAAG;QAAE,OAAO,GAAG,CAAC,WAAW,EAAE,CAAC,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;IACrE,gGAAgG;IAChG,sGAAsG;IACtG,MAAM,OAAO,GACX,MAAM,KAAK,IAAI,IAAI,OAAO,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;IACxF,IAAI,MAAM,IAAI,GAAG,IAAI,MAAM,GAAG,GAAG;QAC/B,OAAO,GAAG,CAAC,cAAc,EAAE,CAAC,CAAC,YAAY,CAAC,OAAO,CAAC,EAAE,UAAU,CAAC,CAAC;IAClE,OAAO,WAAW,EAAE,CAAC;AACvB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,oBAAoB,CAClC,GAAY,EACZ,QAA2B,EAC3B,IAA8B;IAE9B,OAAO,qBAAqB,CAAC,GAAG,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;AACvE,CAAC;AAED,oHAAoH;AACpH,MAAM,kBAAkB,GACtB,+FAA+F,CAAC;AAElG,wGAAwG;AACxG,SAAS,QAAQ,CAAC,CAAS;IACzB,OAAO,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC;AACzC,CAAC;AAED,SAAS,KAAK,CAAC,GAAY,EAAE,GAAW;IACtC,OAAO,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAE,GAA+B,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AAC5F,CAAC;AAED,SAAS,IAAI,CAAC,CAAU;IACtB,OAAO,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;AAC7E,CAAC;AAED,SAAS,aAAa,CAAC,IAAa;IAClC,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACjC,iEAAiE;IACjE,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACjC,MAAM,IAAI,GACR,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACzB,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACzB,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACzB,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;IAC5C,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC;IAC3C,iFAAiF;IACjF,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC;IACzC,MAAM,OAAO,GACX,CAAC,GAAG,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC;IACtF,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;AACnC,CAAC;AAED,wFAAwF;AACxF,MAAM,UAAU,gBAAgB,CAAC,GAAuB;IACtD,OAAO,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC;AACtC,CAAC;AAED,qFAAqF;AACrF,SAAS,UAAU,CACjB,IAAa,EACb,CAAmD;IAEnD,MAAM,CAAC,GAAG,KAAK,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;IACpC,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;IAClC,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC;IAC5C,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC;IACtC,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,CAAC,QAAQ;QAAE,OAAO,SAAS,CAAC;IAC9D,MAAM,OAAO,GAAG,IAAI,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,CAAC,CAAC,MAAM,CACrF,MAAM,GAAG,GAAG,CACb,CAAC;IACF,OAAO,GAAG,OAAO,IAAI,QAAQ,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC;AACjE,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAAC,GAAY;IAC5C,OAAO,CACL,GAAG,YAAY,kBAAkB;QACjC,GAAG,CAAC,MAAM,KAAK,GAAG;QAClB,iBAAiB,CAAC,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,OAAO,IAAI,EAAE,CAAC,CAC9D,CAAC;AACJ,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * País ISO-2 que da el cliente (o el modelo en su nombre), validado; null si no es un código real.
3
+ * Las capacidades no deciden la moneda: solo le pasan al backend el país, como el selector de
4
+ * planes del panel. (El país por el teléfono lo deduce el consumidor y llega en el contexto.)
5
+ */
6
+ export declare function normalizeCountry(input: string | null | undefined): string | null;
7
+ /** Lo que hay que hacer cuando falta el país: preguntárselo al cliente. */
8
+ export declare const FALTA_PAIS = "Falta el pa\u00EDs del cliente, que el sistema necesita para darle los precios y cobrarle en su moneda. Preg\u00FAntale en qu\u00E9 pa\u00EDs est\u00E1 su empresa (una sola pregunta) y vuelve a llamar a esta herramienta con `pais` = su c\u00F3digo ISO-2 (p. ej. MX, ES, AR). No supongas el pa\u00EDs.";
9
+ //# sourceMappingURL=country.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"country.d.ts","sourceRoot":"","sources":["../../src/domain/country.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAGhF;AAED,2EAA2E;AAC3E,eAAO,MAAM,UAAU,iTACsP,CAAC"}
@@ -0,0 +1,13 @@
1
+ const REGIONES = new Intl.DisplayNames(['en'], { type: 'region', fallback: 'none' });
2
+ /**
3
+ * País ISO-2 que da el cliente (o el modelo en su nombre), validado; null si no es un código real.
4
+ * Las capacidades no deciden la moneda: solo le pasan al backend el país, como el selector de
5
+ * planes del panel. (El país por el teléfono lo deduce el consumidor y llega en el contexto.)
6
+ */
7
+ export function normalizeCountry(input) {
8
+ const code = input?.trim().toUpperCase();
9
+ return code && /^[A-Z]{2}$/.test(code) && REGIONES.of(code) ? code : null;
10
+ }
11
+ /** Lo que hay que hacer cuando falta el país: preguntárselo al cliente. */
12
+ export const FALTA_PAIS = 'Falta el país del cliente, que el sistema necesita para darle los precios y cobrarle en su moneda. Pregúntale en qué país está su empresa (una sola pregunta) y vuelve a llamar a esta herramienta con `pais` = su código ISO-2 (p. ej. MX, ES, AR). No supongas el país.';
13
+ //# sourceMappingURL=country.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"country.js","sourceRoot":"","sources":["../../src/domain/country.ts"],"names":[],"mappings":"AAAA,MAAM,QAAQ,GAAG,IAAI,IAAI,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC;AAErF;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAgC;IAC/D,MAAM,IAAI,GAAG,KAAK,EAAE,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACzC,OAAO,IAAI,IAAI,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,QAAQ,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;AAC5E,CAAC;AAED,2EAA2E;AAC3E,MAAM,CAAC,MAAM,UAAU,GACrB,2QAA2Q,CAAC"}
@@ -0,0 +1,33 @@
1
+ export type Periodo = 'hoy' | 'ayer' | 'ultimos_7_dias' | 'ultimos_30_dias' | 'todos';
2
+ export interface DateRange {
3
+ dateFrom?: string;
4
+ dateTo?: string;
5
+ limit: number;
6
+ /** Avisos para el modelo (p. ej. un `desde` que no era una fecha y se ignoró). */
7
+ avisos?: string[];
8
+ }
9
+ /**
10
+ * Valida 'YYYY-MM-DD' y devuelve sus partes, o `null` si no es una fecha real.
11
+ *
12
+ * Antes construía una `Date` y `desde: 'ayer'` acababa en `Invalid Date` →
13
+ * `.toISOString()` lanzaba → el turno entero caía en el fallback con un escalado
14
+ * espurio. Ahora el parámetro malo se ignora y se avisa al modelo.
15
+ */
16
+ export declare function parseLocalDate(ymd: string): {
17
+ y: number;
18
+ m: number;
19
+ d: number;
20
+ } | null;
21
+ /**
22
+ * Resuelve el periodo o rango de fechas pedido por el usuario a un `dateFrom`/
23
+ * `dateTo` en ISO (para filtrar en la API) y el `limit` a pedir.
24
+ *
25
+ * Los límites de día se calculan en el calendario del CLIENTE (`tz`, la que sale
26
+ * de su prefijo telefónico), no en la hora del servidor: "los escaneos del 16"
27
+ * para un cliente de México empezaban a las 16:00 del día 15.
28
+ *
29
+ * Nunca lanza: un `desde`/`hasta` que no sea una fecha real se ignora y se
30
+ * devuelve el motivo en `avisos` para que el modelo pueda decirlo o reintentar.
31
+ */
32
+ export declare function resolveDateRange(periodo?: Periodo, desde?: string, hasta?: string, now?: Date, tz?: string): DateRange;
33
+ //# sourceMappingURL=date-range.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"date-range.d.ts","sourceRoot":"","sources":["../../src/domain/date-range.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,OAAO,GAAG,KAAK,GAAG,MAAM,GAAG,gBAAgB,GAAG,iBAAiB,GAAG,OAAO,CAAC;AAEtF,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,kFAAkF;IAClF,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB;AAOD;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAatF;AA0BD;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,CAAC,EAAE,OAAO,EACjB,KAAK,CAAC,EAAE,MAAM,EACd,KAAK,CAAC,EAAE,MAAM,EACd,GAAG,GAAE,IAAiB,EACtB,EAAE,GAAE,MAAyB,GAC5B,SAAS,CAiEX"}
@@ -0,0 +1,110 @@
1
+ import { DEFAULT_TIMEZONE, localToUtc, zonedParts } from './timezone.js';
2
+ const RECENT_LIMIT = 10;
3
+ const RANGE_LIMIT = 100;
4
+ const YMD_RE = /^(\d{4})-(\d{2})-(\d{2})$/;
5
+ /**
6
+ * Valida 'YYYY-MM-DD' y devuelve sus partes, o `null` si no es una fecha real.
7
+ *
8
+ * Antes construía una `Date` y `desde: 'ayer'` acababa en `Invalid Date` →
9
+ * `.toISOString()` lanzaba → el turno entero caía en el fallback con un escalado
10
+ * espurio. Ahora el parámetro malo se ignora y se avisa al modelo.
11
+ */
12
+ export function parseLocalDate(ymd) {
13
+ const match = YMD_RE.exec(ymd.trim());
14
+ if (!match)
15
+ return null;
16
+ const [, yStr, mStr, dStr] = match;
17
+ const y = Number(yStr);
18
+ const m = Number(mStr);
19
+ const d = Number(dStr);
20
+ if (m < 1 || m > 12 || d < 1 || d > 31)
21
+ return null;
22
+ // Rechaza días que no existen en ese mes (31 de febrero, 30 de febrero…).
23
+ const probe = new Date(Date.UTC(y, m - 1, d));
24
+ if (probe.getUTCFullYear() !== y || probe.getUTCMonth() !== m - 1 || probe.getUTCDate() !== d)
25
+ return null;
26
+ return { y, m, d };
27
+ }
28
+ function ymdToString({ y, m, d }) {
29
+ return `${String(y).padStart(4, '0')}-${String(m).padStart(2, '0')}-${String(d).padStart(2, '0')}`;
30
+ }
31
+ /** Día natural desplazado `days` días (aritmética de calendario, no de instantes). */
32
+ function shiftDays(ymd, days) {
33
+ const shifted = new Date(Date.UTC(ymd.y, ymd.m - 1, ymd.d + days));
34
+ return { y: shifted.getUTCFullYear(), m: shifted.getUTCMonth() + 1, d: shifted.getUTCDate() };
35
+ }
36
+ /** Instante UTC de las 00:00 del día natural `ymd` en la zona `tz`. */
37
+ function startOfDay(ymd, tz) {
38
+ return localToUtc(`${ymdToString(ymd)}T00:00`, tz).toISOString();
39
+ }
40
+ /** Día natural del cliente (en `tz`) correspondiente al instante `now`. */
41
+ function todayIn(now, tz) {
42
+ const parts = zonedParts(now, tz);
43
+ return { y: parts.y, m: parts.m, d: parts.d };
44
+ }
45
+ /**
46
+ * Resuelve el periodo o rango de fechas pedido por el usuario a un `dateFrom`/
47
+ * `dateTo` en ISO (para filtrar en la API) y el `limit` a pedir.
48
+ *
49
+ * Los límites de día se calculan en el calendario del CLIENTE (`tz`, la que sale
50
+ * de su prefijo telefónico), no en la hora del servidor: "los escaneos del 16"
51
+ * para un cliente de México empezaban a las 16:00 del día 15.
52
+ *
53
+ * Nunca lanza: un `desde`/`hasta` que no sea una fecha real se ignora y se
54
+ * devuelve el motivo en `avisos` para que el modelo pueda decirlo o reintentar.
55
+ */
56
+ export function resolveDateRange(periodo, desde, hasta, now = new Date(), tz = DEFAULT_TIMEZONE) {
57
+ const avisos = [];
58
+ let desdeYmd = desde ? parseLocalDate(desde) : null;
59
+ if (desde && !desdeYmd)
60
+ avisos.push(`El parámetro «desde» («${desde}») no es una fecha YYYY-MM-DD válida: se ha ignorado.`);
61
+ let hastaYmd = hasta ? parseLocalDate(hasta) : null;
62
+ if (hasta && !hastaYmd)
63
+ avisos.push(`El parámetro «hasta» («${hasta}») no es una fecha YYYY-MM-DD válida: se ha ignorado.`);
64
+ // Rango invertido: pedirlo a la API devolvería SIEMPRE cero resultados y el
65
+ // modelo lo leería como "no hubo actividad". Se descarta el rango y se dice.
66
+ if (desdeYmd && hastaYmd && ymdToString(desdeYmd) > ymdToString(hastaYmd)) {
67
+ avisos.push(`El rango está invertido («desde» ${ymdToString(desdeYmd)} es posterior a «hasta» ${ymdToString(hastaYmd)}): no se ha filtrado por fecha. Corrige las fechas y vuelve a intentarlo.`);
68
+ desdeYmd = null;
69
+ hastaYmd = null;
70
+ }
71
+ const withAvisos = (range) => avisos.length > 0 ? { ...range, avisos } : range;
72
+ if (desdeYmd || hastaYmd) {
73
+ return withAvisos({
74
+ ...(desdeYmd ? { dateFrom: startOfDay(desdeYmd, tz) } : {}),
75
+ ...(hastaYmd ? { dateTo: startOfDay(shiftDays(hastaYmd, 1), tz) } : {}),
76
+ limit: RANGE_LIMIT,
77
+ });
78
+ }
79
+ const today = todayIn(now, tz);
80
+ switch (periodo) {
81
+ case 'hoy':
82
+ return withAvisos({
83
+ dateFrom: startOfDay(today, tz),
84
+ dateTo: now.toISOString(),
85
+ limit: RANGE_LIMIT,
86
+ });
87
+ case 'ayer':
88
+ return withAvisos({
89
+ dateFrom: startOfDay(shiftDays(today, -1), tz),
90
+ dateTo: startOfDay(today, tz),
91
+ limit: RANGE_LIMIT,
92
+ });
93
+ case 'ultimos_7_dias':
94
+ return withAvisos({
95
+ dateFrom: startOfDay(shiftDays(today, -7), tz),
96
+ dateTo: now.toISOString(),
97
+ limit: RANGE_LIMIT,
98
+ });
99
+ case 'ultimos_30_dias':
100
+ return withAvisos({
101
+ dateFrom: startOfDay(shiftDays(today, -30), tz),
102
+ dateTo: now.toISOString(),
103
+ limit: RANGE_LIMIT,
104
+ });
105
+ case 'todos':
106
+ default:
107
+ return withAvisos({ limit: RECENT_LIMIT });
108
+ }
109
+ }
110
+ //# sourceMappingURL=date-range.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"date-range.js","sourceRoot":"","sources":["../../src/domain/date-range.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAYzE,MAAM,YAAY,GAAG,EAAE,CAAC;AACxB,MAAM,WAAW,GAAG,GAAG,CAAC;AAExB,MAAM,MAAM,GAAG,2BAA2B,CAAC;AAE3C;;;;;;GAMG;AACH,MAAM,UAAU,cAAc,CAAC,GAAW;IACxC,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;IACtC,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IACxB,MAAM,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,GAAG,KAAK,CAAC;IACnC,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;IACvB,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;IACvB,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;IACvB,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE;QAAE,OAAO,IAAI,CAAC;IACpD,0EAA0E;IAC1E,MAAM,KAAK,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAC9C,IAAI,KAAK,CAAC,cAAc,EAAE,KAAK,CAAC,IAAI,KAAK,CAAC,WAAW,EAAE,KAAK,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,UAAU,EAAE,KAAK,CAAC;QAC3F,OAAO,IAAI,CAAC;IACd,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;AACrB,CAAC;AAED,SAAS,WAAW,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAuC;IACnE,OAAO,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC;AACrG,CAAC;AAED,sFAAsF;AACtF,SAAS,SAAS,CAChB,GAAwC,EACxC,IAAY;IAEZ,MAAM,OAAO,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC;IACnE,OAAO,EAAE,CAAC,EAAE,OAAO,CAAC,cAAc,EAAE,EAAE,CAAC,EAAE,OAAO,CAAC,WAAW,EAAE,GAAG,CAAC,EAAE,CAAC,EAAE,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC;AAChG,CAAC;AAED,uEAAuE;AACvE,SAAS,UAAU,CAAC,GAAwC,EAAE,EAAU;IACtE,OAAO,UAAU,CAAC,GAAG,WAAW,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;AACnE,CAAC;AAED,2EAA2E;AAC3E,SAAS,OAAO,CAAC,GAAS,EAAE,EAAU;IACpC,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IAClC,OAAO,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,CAAC;AAChD,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,gBAAgB,CAC9B,OAAiB,EACjB,KAAc,EACd,KAAc,EACd,MAAY,IAAI,IAAI,EAAE,EACtB,KAAa,gBAAgB;IAE7B,MAAM,MAAM,GAAa,EAAE,CAAC;IAE5B,IAAI,QAAQ,GAAG,KAAK,CAAC,CAAC,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACpD,IAAI,KAAK,IAAI,CAAC,QAAQ;QACpB,MAAM,CAAC,IAAI,CACT,0BAA0B,KAAK,uDAAuD,CACvF,CAAC;IACJ,IAAI,QAAQ,GAAG,KAAK,CAAC,CAAC,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACpD,IAAI,KAAK,IAAI,CAAC,QAAQ;QACpB,MAAM,CAAC,IAAI,CACT,0BAA0B,KAAK,uDAAuD,CACvF,CAAC;IAEJ,4EAA4E;IAC5E,6EAA6E;IAC7E,IAAI,QAAQ,IAAI,QAAQ,IAAI,WAAW,CAAC,QAAQ,CAAC,GAAG,WAAW,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC1E,MAAM,CAAC,IAAI,CACT,oCAAoC,WAAW,CAAC,QAAQ,CAAC,2BAA2B,WAAW,CAAC,QAAQ,CAAC,2EAA2E,CACrL,CAAC;QACF,QAAQ,GAAG,IAAI,CAAC;QAChB,QAAQ,GAAG,IAAI,CAAC;IAClB,CAAC;IAED,MAAM,UAAU,GAAG,CAAC,KAAgB,EAAa,EAAE,CACjD,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC;IAEnD,IAAI,QAAQ,IAAI,QAAQ,EAAE,CAAC;QACzB,OAAO,UAAU,CAAC;YAChB,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,UAAU,CAAC,QAAQ,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC3D,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,UAAU,CAAC,SAAS,CAAC,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACvE,KAAK,EAAE,WAAW;SACnB,CAAC,CAAC;IACL,CAAC;IAED,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IAC/B,QAAQ,OAAO,EAAE,CAAC;QAChB,KAAK,KAAK;YACR,OAAO,UAAU,CAAC;gBAChB,QAAQ,EAAE,UAAU,CAAC,KAAK,EAAE,EAAE,CAAC;gBAC/B,MAAM,EAAE,GAAG,CAAC,WAAW,EAAE;gBACzB,KAAK,EAAE,WAAW;aACnB,CAAC,CAAC;QACL,KAAK,MAAM;YACT,OAAO,UAAU,CAAC;gBAChB,QAAQ,EAAE,UAAU,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;gBAC9C,MAAM,EAAE,UAAU,CAAC,KAAK,EAAE,EAAE,CAAC;gBAC7B,KAAK,EAAE,WAAW;aACnB,CAAC,CAAC;QACL,KAAK,gBAAgB;YACnB,OAAO,UAAU,CAAC;gBAChB,QAAQ,EAAE,UAAU,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;gBAC9C,MAAM,EAAE,GAAG,CAAC,WAAW,EAAE;gBACzB,KAAK,EAAE,WAAW;aACnB,CAAC,CAAC;QACL,KAAK,iBAAiB;YACpB,OAAO,UAAU,CAAC;gBAChB,QAAQ,EAAE,UAAU,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC/C,MAAM,EAAE,GAAG,CAAC,WAAW,EAAE;gBACzB,KAAK,EAAE,WAAW;aACnB,CAAC,CAAC;QACL,KAAK,OAAO,CAAC;QACb;YACE,OAAO,UAAU,CAAC,EAAE,KAAK,EAAE,YAAY,EAAE,CAAC,CAAC;IAC/C,CAAC;AACH,CAAC"}
@@ -0,0 +1,14 @@
1
+ import type { FixedTextLanguage } from './language.js';
2
+ /** Distancia en metros entre dos puntos (haversine, la misma fórmula que el antifraude del backend). */
3
+ export declare function distanciaMetros(a: {
4
+ lat: number;
5
+ lng: number;
6
+ }, b: {
7
+ lat: number;
8
+ lng: number;
9
+ }): number;
10
+ /** «56 m» o «3,3 km» (coma decimal en es y fr). */
11
+ export declare function formatoDistancia(metros: number, idioma: FixedTextLanguage): string;
12
+ /** Enlace de Google Maps a unas coordenadas. */
13
+ export declare function enlaceMapa(lat: number, lng: number): string;
14
+ //# sourceMappingURL=geo.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"geo.d.ts","sourceRoot":"","sources":["../../src/domain/geo.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAKvD,wGAAwG;AACxG,wBAAgB,eAAe,CAC7B,CAAC,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,EAC/B,CAAC,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAC9B,MAAM,CAMR;AAED,mDAAmD;AACnD,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,iBAAiB,GAAG,MAAM,CAKlF;AAED,gDAAgD;AAChD,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAE3D"}
@@ -0,0 +1,22 @@
1
+ const RADIO_TIERRA_M = 6_371_000;
2
+ const rad = (g) => (g * Math.PI) / 180;
3
+ /** Distancia en metros entre dos puntos (haversine, la misma fórmula que el antifraude del backend). */
4
+ export function distanciaMetros(a, b) {
5
+ const dLat = rad(b.lat - a.lat);
6
+ const dLng = rad(b.lng - a.lng);
7
+ const h = Math.sin(dLat / 2) ** 2 + Math.cos(rad(a.lat)) * Math.cos(rad(b.lat)) * Math.sin(dLng / 2) ** 2;
8
+ return 2 * RADIO_TIERRA_M * Math.asin(Math.min(1, Math.sqrt(h)));
9
+ }
10
+ /** «56 m» o «3,3 km» (coma decimal en es y fr). */
11
+ export function formatoDistancia(metros, idioma) {
12
+ // Lo que redondea a 1000 m ya va en km (antes salía «1000 m»).
13
+ if (metros < 999.5)
14
+ return `${Math.round(metros)} m`;
15
+ const km = (metros / 1000).toFixed(metros < 100_000 ? 1 : 0);
16
+ return `${idioma === 'en' ? km : km.replace('.', ',')} km`;
17
+ }
18
+ /** Enlace de Google Maps a unas coordenadas. */
19
+ export function enlaceMapa(lat, lng) {
20
+ return `https://www.google.com/maps?q=${lat},${lng}`;
21
+ }
22
+ //# sourceMappingURL=geo.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"geo.js","sourceRoot":"","sources":["../../src/domain/geo.ts"],"names":[],"mappings":"AAEA,MAAM,cAAc,GAAG,SAAS,CAAC;AACjC,MAAM,GAAG,GAAG,CAAC,CAAS,EAAU,EAAE,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC;AAEvD,wGAAwG;AACxG,MAAM,UAAU,eAAe,CAC7B,CAA+B,EAC/B,CAA+B;IAE/B,MAAM,IAAI,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;IAChC,MAAM,IAAI,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;IAChC,MAAM,CAAC,GACL,IAAI,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC;IAClG,OAAO,CAAC,GAAG,cAAc,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACnE,CAAC;AAED,mDAAmD;AACnD,MAAM,UAAU,gBAAgB,CAAC,MAAc,EAAE,MAAyB;IACxE,+DAA+D;IAC/D,IAAI,MAAM,GAAG,KAAK;QAAE,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC;IACrD,MAAM,EAAE,GAAG,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC7D,OAAO,GAAG,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,KAAK,CAAC;AAC7D,CAAC;AAED,gDAAgD;AAChD,MAAM,UAAU,UAAU,CAAC,GAAW,EAAE,GAAW;IACjD,OAAO,iCAAiC,GAAG,IAAI,GAAG,EAAE,CAAC;AACvD,CAAC"}