tempest-react-sdk 0.34.0 → 0.36.0

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 (259) hide show
  1. package/README.md +72 -68
  2. package/dist/audio/audio-output.cjs +2 -0
  3. package/dist/audio/audio-output.cjs.map +1 -0
  4. package/dist/audio/audio-output.js +17 -0
  5. package/dist/audio/audio-output.js.map +1 -0
  6. package/dist/audio/audio-player.cjs +1 -1
  7. package/dist/audio/audio-player.cjs.map +1 -1
  8. package/dist/audio/audio-player.js +21 -20
  9. package/dist/audio/audio-player.js.map +1 -1
  10. package/dist/audio/audio-recorder.cjs +2 -0
  11. package/dist/audio/audio-recorder.cjs.map +1 -0
  12. package/dist/audio/audio-recorder.js +30 -0
  13. package/dist/audio/audio-recorder.js.map +1 -0
  14. package/dist/audio/duration.cjs +2 -0
  15. package/dist/audio/duration.cjs.map +1 -0
  16. package/dist/audio/duration.js +10 -0
  17. package/dist/audio/duration.js.map +1 -0
  18. package/dist/audio/level-meter.cjs +2 -0
  19. package/dist/audio/level-meter.cjs.map +1 -0
  20. package/dist/audio/level-meter.js +34 -0
  21. package/dist/audio/level-meter.js.map +1 -0
  22. package/dist/audio/media-access.cjs +2 -0
  23. package/dist/audio/media-access.cjs.map +1 -0
  24. package/dist/audio/media-access.js +51 -0
  25. package/dist/audio/media-access.js.map +1 -0
  26. package/dist/audio/use-audio-recorder.cjs +2 -0
  27. package/dist/audio/use-audio-recorder.cjs.map +1 -0
  28. package/dist/audio/use-audio-recorder.js +94 -0
  29. package/dist/audio/use-audio-recorder.js.map +1 -0
  30. package/dist/audio/use-audio.cjs.map +1 -1
  31. package/dist/audio/use-audio.js.map +1 -1
  32. package/dist/audio/use-microphone.cjs +2 -0
  33. package/dist/audio/use-microphone.cjs.map +1 -0
  34. package/dist/audio/use-microphone.js +54 -0
  35. package/dist/audio/use-microphone.js.map +1 -0
  36. package/dist/audio/wav.cjs +2 -0
  37. package/dist/audio/wav.cjs.map +1 -0
  38. package/dist/audio/wav.js +49 -0
  39. package/dist/audio/wav.js.map +1 -0
  40. package/dist/auth/passkey.cjs +2 -0
  41. package/dist/auth/passkey.cjs.map +1 -0
  42. package/dist/auth/passkey.js +171 -0
  43. package/dist/auth/passkey.js.map +1 -0
  44. package/dist/auth/use-passkey.cjs +2 -0
  45. package/dist/auth/use-passkey.cjs.map +1 -0
  46. package/dist/auth/use-passkey.js +120 -0
  47. package/dist/auth/use-passkey.js.map +1 -0
  48. package/dist/br/PixQRCode.cjs +2 -0
  49. package/dist/br/PixQRCode.cjs.map +1 -0
  50. package/dist/br/PixQRCode.js +70 -0
  51. package/dist/br/PixQRCode.js.map +1 -0
  52. package/dist/br/PixQRCode.module.cjs +2 -0
  53. package/dist/br/PixQRCode.module.cjs.map +1 -0
  54. package/dist/br/PixQRCode.module.js +15 -0
  55. package/dist/br/PixQRCode.module.js.map +1 -0
  56. package/dist/br/boleto.cjs +2 -0
  57. package/dist/br/boleto.cjs.map +1 -0
  58. package/dist/br/boleto.js +225 -0
  59. package/dist/br/boleto.js.map +1 -0
  60. package/dist/br/holidays.cjs +2 -0
  61. package/dist/br/holidays.cjs.map +1 -0
  62. package/dist/br/holidays.js +148 -0
  63. package/dist/br/holidays.js.map +1 -0
  64. package/dist/br/nfe.cjs +2 -0
  65. package/dist/br/nfe.cjs.map +1 -0
  66. package/dist/br/nfe.js +104 -0
  67. package/dist/br/nfe.js.map +1 -0
  68. package/dist/br/pix.cjs +2 -0
  69. package/dist/br/pix.cjs.map +1 -0
  70. package/dist/br/pix.js +148 -0
  71. package/dist/br/pix.js.map +1 -0
  72. package/dist/br.cjs +1 -1
  73. package/dist/br.cjs.map +1 -1
  74. package/dist/br.d.ts +878 -0
  75. package/dist/br.js +7 -2
  76. package/dist/br.js.map +1 -1
  77. package/dist/capture/barcode.cjs +2 -0
  78. package/dist/capture/barcode.cjs.map +1 -0
  79. package/dist/capture/barcode.js +59 -0
  80. package/dist/capture/barcode.js.map +1 -0
  81. package/dist/capture/media-recorder.cjs +2 -0
  82. package/dist/capture/media-recorder.cjs.map +1 -0
  83. package/dist/capture/media-recorder.js +64 -0
  84. package/dist/capture/media-recorder.js.map +1 -0
  85. package/dist/capture/use-barcode-scanner.cjs +2 -0
  86. package/dist/capture/use-barcode-scanner.cjs.map +1 -0
  87. package/dist/capture/use-barcode-scanner.js +86 -0
  88. package/dist/capture/use-barcode-scanner.js.map +1 -0
  89. package/dist/capture/use-screen-capture.cjs +2 -0
  90. package/dist/capture/use-screen-capture.cjs.map +1 -0
  91. package/dist/capture/use-screen-capture.js +79 -0
  92. package/dist/capture/use-screen-capture.js.map +1 -0
  93. package/dist/capture/use-speech-recognition.cjs +2 -0
  94. package/dist/capture/use-speech-recognition.cjs.map +1 -0
  95. package/dist/capture/use-speech-recognition.js +118 -0
  96. package/dist/capture/use-speech-recognition.js.map +1 -0
  97. package/dist/capture/use-torch.cjs +2 -0
  98. package/dist/capture/use-torch.cjs.map +1 -0
  99. package/dist/capture/use-torch.js +33 -0
  100. package/dist/capture/use-torch.js.map +1 -0
  101. package/dist/capture/use-video-recorder.cjs +2 -0
  102. package/dist/capture/use-video-recorder.cjs.map +1 -0
  103. package/dist/capture/use-video-recorder.js +90 -0
  104. package/dist/capture/use-video-recorder.js.map +1 -0
  105. package/dist/capture/video-recorder.cjs +2 -0
  106. package/dist/capture/video-recorder.cjs.map +1 -0
  107. package/dist/capture/video-recorder.js +31 -0
  108. package/dist/capture/video-recorder.js.map +1 -0
  109. package/dist/components/AIChat/AIChat.cjs +1 -1
  110. package/dist/components/AIChat/AIChat.cjs.map +1 -1
  111. package/dist/components/AIChat/AIChat.js +93 -97
  112. package/dist/components/AIChat/AIChat.js.map +1 -1
  113. package/dist/components/AIChat/AIChatComposer.cjs +1 -1
  114. package/dist/components/AIChat/AIChatComposer.cjs.map +1 -1
  115. package/dist/components/AIChat/AIChatComposer.js +2 -1
  116. package/dist/components/AIChat/AIChatComposer.js.map +1 -1
  117. package/dist/components/AIChat/AIChatTurn.cjs +2 -2
  118. package/dist/components/AIChat/AIChatTurn.js +6 -6
  119. package/dist/components/AIChat/AIChatTurn.js.map +1 -1
  120. package/dist/components/Alert/Alert.module.cjs.map +1 -1
  121. package/dist/components/Alert/Alert.module.js.map +1 -1
  122. package/dist/components/AudioPlayer/AudioPlayer.cjs +2 -0
  123. package/dist/components/AudioPlayer/AudioPlayer.cjs.map +1 -0
  124. package/dist/components/AudioPlayer/AudioPlayer.js +123 -0
  125. package/dist/components/AudioPlayer/AudioPlayer.js.map +1 -0
  126. package/dist/components/AudioPlayer/AudioPlayer.module.cjs +2 -0
  127. package/dist/components/AudioPlayer/AudioPlayer.module.cjs.map +1 -0
  128. package/dist/components/AudioPlayer/AudioPlayer.module.js +12 -0
  129. package/dist/components/AudioPlayer/AudioPlayer.module.js.map +1 -0
  130. package/dist/components/AudioRecorder/AudioRecorder.cjs +2 -0
  131. package/dist/components/AudioRecorder/AudioRecorder.cjs.map +1 -0
  132. package/dist/components/AudioRecorder/AudioRecorder.js +179 -0
  133. package/dist/components/AudioRecorder/AudioRecorder.js.map +1 -0
  134. package/dist/components/AudioRecorder/AudioRecorder.module.cjs +2 -0
  135. package/dist/components/AudioRecorder/AudioRecorder.module.cjs.map +1 -0
  136. package/dist/components/AudioRecorder/AudioRecorder.module.js +19 -0
  137. package/dist/components/AudioRecorder/AudioRecorder.module.js.map +1 -0
  138. package/dist/components/Badge/Badge.module.cjs.map +1 -1
  139. package/dist/components/Badge/Badge.module.js.map +1 -1
  140. package/dist/components/BarcodeScanner/BarcodeScanner.cjs +2 -0
  141. package/dist/components/BarcodeScanner/BarcodeScanner.cjs.map +1 -0
  142. package/dist/components/BarcodeScanner/BarcodeScanner.js +123 -0
  143. package/dist/components/BarcodeScanner/BarcodeScanner.js.map +1 -0
  144. package/dist/components/BarcodeScanner/BarcodeScanner.module.cjs +2 -0
  145. package/dist/components/BarcodeScanner/BarcodeScanner.module.cjs.map +1 -0
  146. package/dist/components/BarcodeScanner/BarcodeScanner.module.js +22 -0
  147. package/dist/components/BarcodeScanner/BarcodeScanner.module.js.map +1 -0
  148. package/dist/components/BottomNavigation/BottomNavigation.module.cjs.map +1 -1
  149. package/dist/components/BottomNavigation/BottomNavigation.module.js.map +1 -1
  150. package/dist/components/Button/Button.module.cjs.map +1 -1
  151. package/dist/components/Button/Button.module.js.map +1 -1
  152. package/dist/components/Combobox/Combobox.module.cjs.map +1 -1
  153. package/dist/components/Combobox/Combobox.module.js.map +1 -1
  154. package/dist/components/DataTable/DataTable.cjs +1 -1
  155. package/dist/components/DataTable/DataTable.cjs.map +1 -1
  156. package/dist/components/DataTable/DataTable.js +203 -66
  157. package/dist/components/DataTable/DataTable.js.map +1 -1
  158. package/dist/components/DataTable/DataTable.module.cjs +1 -1
  159. package/dist/components/DataTable/DataTable.module.cjs.map +1 -1
  160. package/dist/components/DataTable/DataTable.module.js +9 -3
  161. package/dist/components/DataTable/DataTable.module.js.map +1 -1
  162. package/dist/components/DataTable/EditableCell.cjs +2 -0
  163. package/dist/components/DataTable/EditableCell.cjs.map +1 -0
  164. package/dist/components/DataTable/EditableCell.js +77 -0
  165. package/dist/components/DataTable/EditableCell.js.map +1 -0
  166. package/dist/components/DataTable/edit-labels.cjs +2 -0
  167. package/dist/components/DataTable/edit-labels.cjs.map +1 -0
  168. package/dist/components/DataTable/edit-labels.js +11 -0
  169. package/dist/components/DataTable/edit-labels.js.map +1 -0
  170. package/dist/components/DateRangePicker/DateRangePicker.module.cjs.map +1 -1
  171. package/dist/components/DateRangePicker/DateRangePicker.module.js.map +1 -1
  172. package/dist/components/MultiSelect/MultiSelect.module.cjs.map +1 -1
  173. package/dist/components/MultiSelect/MultiSelect.module.js.map +1 -1
  174. package/dist/components/NavigationRail/NavigationRail.module.cjs.map +1 -1
  175. package/dist/components/NavigationRail/NavigationRail.module.js.map +1 -1
  176. package/dist/components/SyncStatusBadge/SyncStatusBadge.cjs +1 -1
  177. package/dist/components/SyncStatusBadge/SyncStatusBadge.cjs.map +1 -1
  178. package/dist/components/SyncStatusBadge/SyncStatusBadge.js +33 -32
  179. package/dist/components/SyncStatusBadge/SyncStatusBadge.js.map +1 -1
  180. package/dist/components/Toast/ToastProvider.cjs +1 -1
  181. package/dist/components/Toast/ToastProvider.cjs.map +1 -1
  182. package/dist/components/Toast/ToastProvider.js +1 -2
  183. package/dist/components/Toast/ToastProvider.js.map +1 -1
  184. package/dist/hooks/use-announce.cjs +2 -0
  185. package/dist/hooks/use-announce.cjs.map +1 -0
  186. package/dist/hooks/use-announce.js +50 -0
  187. package/dist/hooks/use-announce.js.map +1 -0
  188. package/dist/hooks/use-media-devices.cjs +2 -0
  189. package/dist/hooks/use-media-devices.cjs.map +1 -0
  190. package/dist/hooks/use-media-devices.js +46 -0
  191. package/dist/hooks/use-media-devices.js.map +1 -0
  192. package/dist/hooks/use-media-permission.cjs +2 -0
  193. package/dist/hooks/use-media-permission.cjs.map +1 -0
  194. package/dist/hooks/use-media-permission.js +33 -0
  195. package/dist/hooks/use-media-permission.js.map +1 -0
  196. package/dist/http/resumable-upload.cjs +2 -0
  197. package/dist/http/resumable-upload.cjs.map +1 -0
  198. package/dist/http/resumable-upload.js +249 -0
  199. package/dist/http/resumable-upload.js.map +1 -0
  200. package/dist/perf/cache-size.cjs +2 -0
  201. package/dist/perf/cache-size.cjs.map +1 -0
  202. package/dist/perf/cache-size.js +16 -0
  203. package/dist/perf/cache-size.js.map +1 -0
  204. package/dist/perf/device.cjs +2 -0
  205. package/dist/perf/device.cjs.map +1 -0
  206. package/dist/perf/device.js +22 -0
  207. package/dist/perf/device.js.map +1 -0
  208. package/dist/perf/format.cjs +2 -0
  209. package/dist/perf/format.cjs.map +1 -0
  210. package/dist/perf/format.js +8 -0
  211. package/dist/perf/format.js.map +1 -0
  212. package/dist/perf/profiler.cjs +2 -0
  213. package/dist/perf/profiler.cjs.map +1 -0
  214. package/dist/perf/profiler.js +46 -0
  215. package/dist/perf/profiler.js.map +1 -0
  216. package/dist/styles.css +1 -1
  217. package/dist/tempest-react-sdk.cjs +1 -1
  218. package/dist/tempest-react-sdk.d.ts +2705 -38
  219. package/dist/tempest-react-sdk.js +268 -240
  220. package/dist/vision/core/timing.cjs +2 -0
  221. package/dist/vision/core/timing.cjs.map +1 -0
  222. package/dist/vision/core/timing.js +24 -0
  223. package/dist/vision/core/timing.js.map +1 -0
  224. package/dist/vision/index.cjs +1 -1
  225. package/dist/vision/index.cjs.map +1 -1
  226. package/dist/vision/index.js +16 -15
  227. package/dist/vision/index.js.map +1 -1
  228. package/dist/vision/postprocess/detection.cjs +1 -1
  229. package/dist/vision/postprocess/detection.cjs.map +1 -1
  230. package/dist/vision/postprocess/detection.js +2 -2
  231. package/dist/vision/postprocess/detection.js.map +1 -1
  232. package/dist/vision/postprocess/segmentation.cjs +1 -1
  233. package/dist/vision/postprocess/segmentation.cjs.map +1 -1
  234. package/dist/vision/postprocess/segmentation.js +1 -1
  235. package/dist/vision/postprocess/segmentation.js.map +1 -1
  236. package/dist/vision/results.cjs +1 -1
  237. package/dist/vision/results.cjs.map +1 -1
  238. package/dist/vision/results.js +18 -13
  239. package/dist/vision/results.js.map +1 -1
  240. package/dist/vision/tasks/classifier.cjs +1 -1
  241. package/dist/vision/tasks/classifier.cjs.map +1 -1
  242. package/dist/vision/tasks/classifier.js +46 -39
  243. package/dist/vision/tasks/classifier.js.map +1 -1
  244. package/dist/vision/tasks/detector.cjs +1 -1
  245. package/dist/vision/tasks/detector.cjs.map +1 -1
  246. package/dist/vision/tasks/detector.js +40 -33
  247. package/dist/vision/tasks/detector.js.map +1 -1
  248. package/dist/vision/tasks/segmenter.cjs +1 -1
  249. package/dist/vision/tasks/segmenter.cjs.map +1 -1
  250. package/dist/vision/tasks/segmenter.js +35 -28
  251. package/dist/vision/tasks/segmenter.js.map +1 -1
  252. package/dist/vision/use-camera-stream.cjs +1 -1
  253. package/dist/vision/use-camera-stream.cjs.map +1 -1
  254. package/dist/vision/use-camera-stream.js +40 -57
  255. package/dist/vision/use-camera-stream.js.map +1 -1
  256. package/dist/vision.cjs +1 -1
  257. package/dist/vision.d.ts +93 -13
  258. package/dist/vision.js +21 -20
  259. package/package.json +1 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PixQRCode.cjs","names":[],"sources":["../../src/br/PixQRCode.tsx"],"sourcesContent":["import type { HTMLAttributes } from \"react\";\nimport { useMemo } from \"react\";\n\nimport { CopyButton } from \"@/components/CopyButton\";\nimport { QRCode } from \"@/components/QRCode\";\nimport type { QRErrorCorrection } from \"@/components/QRCode\";\nimport { cn } from \"@/utils/cn\";\n\nimport { PixError, pixPayload } from \"./pix\";\nimport type { PixInput } from \"./pix\";\nimport styles from \"./PixQRCode.module.css\";\n\n/** Strings the component renders, so an app can translate them. */\nexport interface PixQRCodeLabels {\n /** Accessible name of the symbol. */\n qr: string;\n /** Copy button, idle. */\n copy: string;\n /** Copy button, just clicked. */\n copied: string;\n}\n\nconst DEFAULT_LABELS: PixQRCodeLabels = {\n qr: \"QR code do Pix\",\n copy: \"Copiar código\",\n copied: \"Copiado\",\n};\n\nexport interface PixQRCodeProps extends Omit<HTMLAttributes<HTMLDivElement>, \"children\"> {\n /**\n * Build the payload from its parts. Mutually exclusive with {@link payload}.\n */\n pix?: PixInput;\n /**\n * A payload your PSP already produced, used verbatim.\n *\n * Prefer this for a dynamic charge: the PSP signed that string, and rebuilding\n * it here from parsed parts would only add a way to get it wrong.\n */\n payload?: string;\n /** Rendered side of the symbol in px, quiet zone included. Default `192`. */\n size?: number;\n /**\n * Error-correction level. Default `\"M\"`.\n *\n * A printed QR that will be photographed at an angle scans better at `\"Q\"` or\n * `\"H\"`; the cost is a denser symbol, so raise the size with it.\n */\n level?: QRErrorCorrection;\n /** Render the copia-e-cola line and its copy button. Default `true`. */\n showCopy?: boolean;\n /** Amount caption, e.g. `\"R$ 25,50\"`. Rendered above the symbol when set. */\n amountLabel?: string;\n /** Payee caption. Rendered under the amount when set. */\n payeeLabel?: string;\n labels?: Partial<PixQRCodeLabels>;\n /** Called after the payload reaches the clipboard. */\n onCopied?: () => void;\n}\n\n/**\n * A Pix QR code with the copia-e-cola string next to it.\n *\n * The two affordances belong together: a QR is unusable on the device that is\n * *showing* it, which is exactly where a mobile checkout puts it, so every real\n * Pix screen ends up needing the copyable string as well. Rendering only the\n * symbol is the single most common mistake in a Pix flow.\n *\n * Everything is computed locally — {@link pixPayload} builds the string and the\n * SDK's own encoder draws the symbol — so the key, the amount and the txid never\n * leave the page. A QR-image service would receive all three.\n *\n * @throws {PixError} When neither `pix` nor `payload` is given, when both are, or\n * when `pix` fails validation. A bad key is a programming or data error rather\n * than a state to render, so it surfaces; wrap the screen in `ErrorBoundary` when\n * the values come from user input.\n *\n * @example\n * <PixQRCode\n * pix={{\n * key: \"loja@tempest.dev\",\n * merchantName: \"Loja Tempest\",\n * merchantCity: \"São Paulo\",\n * amount: 25.5,\n * txid: \"PEDIDO123\",\n * }}\n * amountLabel=\"R$ 25,50\"\n * payeeLabel=\"Loja Tempest\"\n * />\n *\n * @example\n * <PixQRCode payload={charge.brcode} level=\"Q\" size={220} />\n */\nexport function PixQRCode({\n pix,\n payload,\n size = 192,\n level = \"M\",\n showCopy = true,\n amountLabel,\n payeeLabel,\n labels,\n onCopied,\n className,\n ...rest\n}: PixQRCodeProps) {\n const value = useMemo(() => {\n if (payload !== undefined && pix !== undefined) {\n throw new PixError(\"Pass either `pix` or `payload` to PixQRCode, not both.\");\n }\n if (payload !== undefined) return payload.trim();\n if (pix !== undefined) return pixPayload(pix);\n throw new PixError(\"PixQRCode needs either `pix` or `payload`.\");\n }, [pix, payload]);\n\n const text = { ...DEFAULT_LABELS, ...labels };\n\n return (\n <div className={cn(styles.pix, className)} {...rest}>\n {amountLabel !== undefined && <span className={styles.amount}>{amountLabel}</span>}\n {payeeLabel !== undefined && <span className={styles.payee}>{payeeLabel}</span>}\n <div className={styles.symbol}>\n <QRCode value={value} size={size} level={level} label={text.qr} margin={2} />\n </div>\n {showCopy && (\n <div className={styles.copy}>\n <code className={styles.payload} data-testid=\"pix-payload\">\n {value}\n </code>\n <CopyButton value={value} onCopied={onCopied}>\n <span className={styles.copyIdle}>{text.copy}</span>\n <span className={styles.copyDone}>{text.copied}</span>\n </CopyButton>\n </div>\n )}\n </div>\n );\n}\n"],"mappings":"sPAsBA,IAAM,EAAkC,CACpC,GAAI,iBACJ,KAAM,gBACN,OAAQ,SACZ,EAmEA,SAAgB,EAAU,CACtB,MACA,UACA,OAAO,IACP,QAAQ,IACR,WAAW,GACX,cACA,aACA,SACA,WACA,YACA,GAAG,GACY,CACf,IAAM,GAAA,EAAA,EAAA,QAAA,KAAsB,CACxB,GAAI,IAAY,IAAA,IAAa,IAAQ,IAAA,GACjC,MAAM,IAAI,EAAA,SAAS,wDAAwD,EAE/E,GAAI,IAAY,IAAA,GAAW,OAAO,EAAQ,KAAK,EAC/C,GAAI,IAAQ,IAAA,GAAW,OAAO,EAAA,WAAW,CAAG,EAC5C,MAAM,IAAI,EAAA,SAAS,4CAA4C,CACnE,EAAG,CAAC,EAAK,CAAO,CAAC,EAEX,EAAO,CAAE,GAAG,EAAgB,GAAG,CAAO,EAE5C,OACI,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAW,EAAA,GAAG,EAAA,QAAO,IAAK,CAAS,EAAG,GAAI,WAA/C,CACK,IAAgB,IAAA,KAAa,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAA,QAAO,gBAAS,CAAkB,CAAA,EAChF,IAAe,IAAA,KAAa,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAA,QAAO,eAAQ,CAAiB,CAAA,GAC9E,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAW,EAAA,QAAO,iBACnB,EAAA,EAAA,IAAA,CAAC,EAAA,OAAD,CAAe,QAAa,OAAa,QAAO,MAAO,EAAK,GAAI,OAAQ,CAAI,CAAA,CAC3E,CAAA,EACJ,IACG,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAW,EAAA,QAAO,cAAvB,EACI,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAA,QAAO,QAAS,cAAY,uBACxC,CACC,CAAA,GACN,EAAA,EAAA,KAAA,CAAC,EAAA,WAAD,CAAmB,QAAiB,oBAApC,EACI,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAA,QAAO,kBAAW,EAAK,IAAW,CAAA,GACnD,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAA,QAAO,kBAAW,EAAK,MAAa,CAAA,CAC7C,GACX,GAER,GAEb"}
@@ -0,0 +1,70 @@
1
+ import { cn as e } from "../utils/cn.js";
2
+ import { QRCode as t } from "../components/QRCode/QRCode.js";
3
+ import { CopyButton as n } from "../components/CopyButton/CopyButton.js";
4
+ import { PixError as r, pixPayload as i } from "./pix.js";
5
+ import a from "./PixQRCode.module.js";
6
+ import { useMemo as o } from "react";
7
+ import { jsx as s, jsxs as c } from "react/jsx-runtime";
8
+ //#region src/br/PixQRCode.tsx
9
+ var l = {
10
+ qr: "QR code do Pix",
11
+ copy: "Copiar código",
12
+ copied: "Copiado"
13
+ };
14
+ function u({ pix: u, payload: d, size: f = 192, level: p = "M", showCopy: m = !0, amountLabel: h, payeeLabel: g, labels: _, onCopied: v, className: y, ...b }) {
15
+ let x = o(() => {
16
+ if (d !== void 0 && u !== void 0) throw new r("Pass either `pix` or `payload` to PixQRCode, not both.");
17
+ if (d !== void 0) return d.trim();
18
+ if (u !== void 0) return i(u);
19
+ throw new r("PixQRCode needs either `pix` or `payload`.");
20
+ }, [u, d]), S = {
21
+ ...l,
22
+ ..._
23
+ };
24
+ return /* @__PURE__ */ c("div", {
25
+ className: e(a.pix, y),
26
+ ...b,
27
+ children: [
28
+ h !== void 0 && /* @__PURE__ */ s("span", {
29
+ className: a.amount,
30
+ children: h
31
+ }),
32
+ g !== void 0 && /* @__PURE__ */ s("span", {
33
+ className: a.payee,
34
+ children: g
35
+ }),
36
+ /* @__PURE__ */ s("div", {
37
+ className: a.symbol,
38
+ children: /* @__PURE__ */ s(t, {
39
+ value: x,
40
+ size: f,
41
+ level: p,
42
+ label: S.qr,
43
+ margin: 2
44
+ })
45
+ }),
46
+ m && /* @__PURE__ */ c("div", {
47
+ className: a.copy,
48
+ children: [/* @__PURE__ */ s("code", {
49
+ className: a.payload,
50
+ "data-testid": "pix-payload",
51
+ children: x
52
+ }), /* @__PURE__ */ c(n, {
53
+ value: x,
54
+ onCopied: v,
55
+ children: [/* @__PURE__ */ s("span", {
56
+ className: a.copyIdle,
57
+ children: S.copy
58
+ }), /* @__PURE__ */ s("span", {
59
+ className: a.copyDone,
60
+ children: S.copied
61
+ })]
62
+ })]
63
+ })
64
+ ]
65
+ });
66
+ }
67
+ //#endregion
68
+ export { u as PixQRCode };
69
+
70
+ //# sourceMappingURL=PixQRCode.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PixQRCode.js","names":[],"sources":["../../src/br/PixQRCode.tsx"],"sourcesContent":["import type { HTMLAttributes } from \"react\";\nimport { useMemo } from \"react\";\n\nimport { CopyButton } from \"@/components/CopyButton\";\nimport { QRCode } from \"@/components/QRCode\";\nimport type { QRErrorCorrection } from \"@/components/QRCode\";\nimport { cn } from \"@/utils/cn\";\n\nimport { PixError, pixPayload } from \"./pix\";\nimport type { PixInput } from \"./pix\";\nimport styles from \"./PixQRCode.module.css\";\n\n/** Strings the component renders, so an app can translate them. */\nexport interface PixQRCodeLabels {\n /** Accessible name of the symbol. */\n qr: string;\n /** Copy button, idle. */\n copy: string;\n /** Copy button, just clicked. */\n copied: string;\n}\n\nconst DEFAULT_LABELS: PixQRCodeLabels = {\n qr: \"QR code do Pix\",\n copy: \"Copiar código\",\n copied: \"Copiado\",\n};\n\nexport interface PixQRCodeProps extends Omit<HTMLAttributes<HTMLDivElement>, \"children\"> {\n /**\n * Build the payload from its parts. Mutually exclusive with {@link payload}.\n */\n pix?: PixInput;\n /**\n * A payload your PSP already produced, used verbatim.\n *\n * Prefer this for a dynamic charge: the PSP signed that string, and rebuilding\n * it here from parsed parts would only add a way to get it wrong.\n */\n payload?: string;\n /** Rendered side of the symbol in px, quiet zone included. Default `192`. */\n size?: number;\n /**\n * Error-correction level. Default `\"M\"`.\n *\n * A printed QR that will be photographed at an angle scans better at `\"Q\"` or\n * `\"H\"`; the cost is a denser symbol, so raise the size with it.\n */\n level?: QRErrorCorrection;\n /** Render the copia-e-cola line and its copy button. Default `true`. */\n showCopy?: boolean;\n /** Amount caption, e.g. `\"R$ 25,50\"`. Rendered above the symbol when set. */\n amountLabel?: string;\n /** Payee caption. Rendered under the amount when set. */\n payeeLabel?: string;\n labels?: Partial<PixQRCodeLabels>;\n /** Called after the payload reaches the clipboard. */\n onCopied?: () => void;\n}\n\n/**\n * A Pix QR code with the copia-e-cola string next to it.\n *\n * The two affordances belong together: a QR is unusable on the device that is\n * *showing* it, which is exactly where a mobile checkout puts it, so every real\n * Pix screen ends up needing the copyable string as well. Rendering only the\n * symbol is the single most common mistake in a Pix flow.\n *\n * Everything is computed locally — {@link pixPayload} builds the string and the\n * SDK's own encoder draws the symbol — so the key, the amount and the txid never\n * leave the page. A QR-image service would receive all three.\n *\n * @throws {PixError} When neither `pix` nor `payload` is given, when both are, or\n * when `pix` fails validation. A bad key is a programming or data error rather\n * than a state to render, so it surfaces; wrap the screen in `ErrorBoundary` when\n * the values come from user input.\n *\n * @example\n * <PixQRCode\n * pix={{\n * key: \"loja@tempest.dev\",\n * merchantName: \"Loja Tempest\",\n * merchantCity: \"São Paulo\",\n * amount: 25.5,\n * txid: \"PEDIDO123\",\n * }}\n * amountLabel=\"R$ 25,50\"\n * payeeLabel=\"Loja Tempest\"\n * />\n *\n * @example\n * <PixQRCode payload={charge.brcode} level=\"Q\" size={220} />\n */\nexport function PixQRCode({\n pix,\n payload,\n size = 192,\n level = \"M\",\n showCopy = true,\n amountLabel,\n payeeLabel,\n labels,\n onCopied,\n className,\n ...rest\n}: PixQRCodeProps) {\n const value = useMemo(() => {\n if (payload !== undefined && pix !== undefined) {\n throw new PixError(\"Pass either `pix` or `payload` to PixQRCode, not both.\");\n }\n if (payload !== undefined) return payload.trim();\n if (pix !== undefined) return pixPayload(pix);\n throw new PixError(\"PixQRCode needs either `pix` or `payload`.\");\n }, [pix, payload]);\n\n const text = { ...DEFAULT_LABELS, ...labels };\n\n return (\n <div className={cn(styles.pix, className)} {...rest}>\n {amountLabel !== undefined && <span className={styles.amount}>{amountLabel}</span>}\n {payeeLabel !== undefined && <span className={styles.payee}>{payeeLabel}</span>}\n <div className={styles.symbol}>\n <QRCode value={value} size={size} level={level} label={text.qr} margin={2} />\n </div>\n {showCopy && (\n <div className={styles.copy}>\n <code className={styles.payload} data-testid=\"pix-payload\">\n {value}\n </code>\n <CopyButton value={value} onCopied={onCopied}>\n <span className={styles.copyIdle}>{text.copy}</span>\n <span className={styles.copyDone}>{text.copied}</span>\n </CopyButton>\n </div>\n )}\n </div>\n );\n}\n"],"mappings":";;;;;;;;AAsBA,IAAM,IAAkC;CACpC,IAAI;CACJ,MAAM;CACN,QAAQ;AACZ;AAmEA,SAAgB,EAAU,EACtB,QACA,YACA,UAAO,KACP,WAAQ,KACR,cAAW,IACX,gBACA,eACA,WACA,aACA,cACA,GAAG,KACY;CACf,IAAM,IAAQ,QAAc;EACxB,IAAI,MAAY,KAAA,KAAa,MAAQ,KAAA,GACjC,MAAM,IAAI,EAAS,wDAAwD;EAE/E,IAAI,MAAY,KAAA,GAAW,OAAO,EAAQ,KAAK;EAC/C,IAAI,MAAQ,KAAA,GAAW,OAAO,EAAW,CAAG;EAC5C,MAAM,IAAI,EAAS,4CAA4C;CACnE,GAAG,CAAC,GAAK,CAAO,CAAC,GAEX,IAAO;EAAE,GAAG;EAAgB,GAAG;CAAO;CAE5C,OACI,kBAAC,OAAD;EAAK,WAAW,EAAG,EAAO,KAAK,CAAS;EAAG,GAAI;YAA/C;GACK,MAAgB,KAAA,KAAa,kBAAC,QAAD;IAAM,WAAW,EAAO;cAAS;GAAkB,CAAA;GAChF,MAAe,KAAA,KAAa,kBAAC,QAAD;IAAM,WAAW,EAAO;cAAQ;GAAiB,CAAA;GAC9E,kBAAC,OAAD;IAAK,WAAW,EAAO;cACnB,kBAAC,GAAD;KAAe;KAAa;KAAa;KAAO,OAAO,EAAK;KAAI,QAAQ;IAAI,CAAA;GAC3E,CAAA;GACJ,KACG,kBAAC,OAAD;IAAK,WAAW,EAAO;cAAvB,CACI,kBAAC,QAAD;KAAM,WAAW,EAAO;KAAS,eAAY;eACxC;IACC,CAAA,GACN,kBAAC,GAAD;KAAmB;KAAiB;eAApC,CACI,kBAAC,QAAD;MAAM,WAAW,EAAO;gBAAW,EAAK;KAAW,CAAA,GACnD,kBAAC,QAAD;MAAM,WAAW,EAAO;gBAAW,EAAK;KAAa,CAAA,CAC7C;MACX;;EAER;;AAEb"}
@@ -0,0 +1,2 @@
1
+ var e=`tempest_pix_sx91C`,t=`tempest_symbol_tVr1U`,n=`tempest_copy_tKHV5`,r=`tempest_payload_4V3pI`,i=`tempest_copyDone_jmjJa`,a=`tempest_copyIdle_iwRqW`,o=`tempest_amount_jr-Bf`,s=`tempest_payee_-VHXL`,c={pix:e,symbol:t,copy:n,payload:r,copyDone:i,copyIdle:a,amount:o,payee:s};exports.amount=o,exports.copy=n,exports.copyDone=i,exports.copyIdle=a,exports.default=c,exports.payee=s,exports.payload=r,exports.pix=e,exports.symbol=t;
2
+ //# sourceMappingURL=PixQRCode.module.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PixQRCode.module.cjs","names":[],"sources":["../../src/br/PixQRCode.module.css"],"sourcesContent":[".pix {\n display: inline-flex;\n flex-direction: column;\n align-items: center;\n gap: var(--tempest-space-3);\n font-family: var(--tempest-font-sans);\n}\n\n.symbol {\n /* The QR stays black on white in both themes — see the note on `QRCode`. A\n white plate under it keeps the quiet zone intact on a dark page. */\n padding: var(--tempest-space-2);\n background: #ffffff;\n border-radius: var(--tempest-radius-md);\n border: 1px solid var(--tempest-border);\n}\n\n.copy {\n display: flex;\n align-items: center;\n gap: var(--tempest-space-2);\n width: 100%;\n max-width: 320px;\n}\n\n.payload {\n flex: 1 1 auto;\n min-width: 0;\n overflow: hidden;\n padding: var(--tempest-space-1) var(--tempest-space-2);\n background: var(--tempest-surface-2);\n border: 1px solid var(--tempest-border);\n border-radius: var(--tempest-radius-sm);\n color: var(--tempest-text-muted);\n font-family: var(--tempest-font-mono);\n font-size: var(--tempest-text-xs);\n line-height: var(--tempest-leading-snug);\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n/* The copy button renders both labels and CSS picks one, because `CopyButton`\n keeps the copied flag in `data-copied` and renders its children unchanged in\n both states. Swapping the text node also keeps the button's accessible name in\n sync, which an `aria-label` would not. */\n.copyDone {\n display: none;\n}\n\n.copy button[data-copied] .copyIdle {\n display: none;\n}\n\n.copy button[data-copied] .copyDone {\n display: inline;\n}\n\n.amount {\n color: var(--tempest-text);\n font-size: var(--tempest-text-lg);\n font-weight: var(--tempest-weight-semibold);\n}\n\n.payee {\n color: var(--tempest-text-muted);\n font-size: var(--tempest-text-sm);\n text-align: center;\n}\n"],"mappings":""}
@@ -0,0 +1,15 @@
1
+ //#region src/br/PixQRCode.module.css
2
+ var e = "tempest_pix_sx91C", t = "tempest_symbol_tVr1U", n = "tempest_copy_tKHV5", r = "tempest_payload_4V3pI", i = "tempest_copyDone_jmjJa", a = "tempest_copyIdle_iwRqW", o = "tempest_amount_jr-Bf", s = "tempest_payee_-VHXL", c = {
3
+ pix: e,
4
+ symbol: t,
5
+ copy: n,
6
+ payload: r,
7
+ copyDone: i,
8
+ copyIdle: a,
9
+ amount: o,
10
+ payee: s
11
+ };
12
+ //#endregion
13
+ export { o as amount, n as copy, i as copyDone, a as copyIdle, c as default, s as payee, r as payload, e as pix, t as symbol };
14
+
15
+ //# sourceMappingURL=PixQRCode.module.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PixQRCode.module.js","names":[],"sources":["../../src/br/PixQRCode.module.css"],"sourcesContent":[".pix {\n display: inline-flex;\n flex-direction: column;\n align-items: center;\n gap: var(--tempest-space-3);\n font-family: var(--tempest-font-sans);\n}\n\n.symbol {\n /* The QR stays black on white in both themes — see the note on `QRCode`. A\n white plate under it keeps the quiet zone intact on a dark page. */\n padding: var(--tempest-space-2);\n background: #ffffff;\n border-radius: var(--tempest-radius-md);\n border: 1px solid var(--tempest-border);\n}\n\n.copy {\n display: flex;\n align-items: center;\n gap: var(--tempest-space-2);\n width: 100%;\n max-width: 320px;\n}\n\n.payload {\n flex: 1 1 auto;\n min-width: 0;\n overflow: hidden;\n padding: var(--tempest-space-1) var(--tempest-space-2);\n background: var(--tempest-surface-2);\n border: 1px solid var(--tempest-border);\n border-radius: var(--tempest-radius-sm);\n color: var(--tempest-text-muted);\n font-family: var(--tempest-font-mono);\n font-size: var(--tempest-text-xs);\n line-height: var(--tempest-leading-snug);\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n/* The copy button renders both labels and CSS picks one, because `CopyButton`\n keeps the copied flag in `data-copied` and renders its children unchanged in\n both states. Swapping the text node also keeps the button's accessible name in\n sync, which an `aria-label` would not. */\n.copyDone {\n display: none;\n}\n\n.copy button[data-copied] .copyIdle {\n display: none;\n}\n\n.copy button[data-copied] .copyDone {\n display: inline;\n}\n\n.amount {\n color: var(--tempest-text);\n font-size: var(--tempest-text-lg);\n font-weight: var(--tempest-weight-semibold);\n}\n\n.payee {\n color: var(--tempest-text-muted);\n font-size: var(--tempest-text-sm);\n text-align: center;\n}\n"],"mappings":""}
@@ -0,0 +1,2 @@
1
+ var e=class extends Error{constructor(e){super(e),this.name=`BoletoError`}},t=Date.UTC(1997,9,7),n=Date.UTC(2022,4,29),r=864e5,i=1e3,a=9999,o=[2,1],s=2,c={1:`Prefeituras`,2:`Saneamento`,3:`Energia elétrica e gás`,4:`Telecomunicações`,5:`Órgãos governamentais`,6:`Carnes e assemelhados ou empresas identificadas por CNPJ`,7:`Multas de trânsito`,9:`Uso exclusivo do banco`},l=6;function u(e){return e.replace(/\D/g,``)}function d(t){if(!/^\d+$/.test(t))throw new e(`mod10Dac needs digits, got ${JSON.stringify(t)}.`);let n=0;for(let e=0;e<t.length;e+=1){let r=t.length-1-e,i=Number(t[e])*o[r%o.length];n+=i>9?i-9:i}let r=n%10;return r===0?0:10-r}function f(e){let t=0;for(let n=0;n<e.length;n+=1){let r=e.length-1-n;t+=Number(e[n])*(s+r%8)}return t}function p(t){if(!/^\d+$/.test(t))throw new e(`mod11DacCobranca needs digits, got ${JSON.stringify(t)}.`);let n=f(t)%11;return n===0||n===1||n===10?1:11-n}function m(t){if(!/^\d+$/.test(t))throw new e(`mod11DacArrecadacao needs digits, got ${JSON.stringify(t)}.`);let n=f(t)%11;return n===0||n===1?0:11-n}function h(e){let t=u(e);return t.length===47?`banco`:t.length===48?`arrecadacao`:t.length===44?t.startsWith(`8`)?`arrecadacao`:`banco`:null}function g(e,t){let n=new Date(e+t*r);return new Date(n.getUTCFullYear(),n.getUTCMonth(),n.getUTCDate())}function _(e,r={}){if(e===0)return null;let{epoch:a=`auto`,reference:o=new Date}=r;if(a===`legacy`)return{date:g(t,e),epoch:`legacy`};if(a===`current`)return{date:g(n,e),epoch:`current`};let s=g(t,e);if(e<i)return{date:s,epoch:`legacy`};let c=g(n,e),l=o.getTime();return Math.abs(c.getTime()-l)<=Math.abs(s.getTime()-l)?{date:c,epoch:`current`}:{date:s,epoch:`legacy`}}function v(o,s=`current`){let c=s===`legacy`?t:n,l=Date.UTC(o.getFullYear(),o.getMonth(),o.getDate()),u=Math.round((l-c)/r);if(u<i||u>a)throw new e(`${o.toISOString().slice(0,10)} is fator ${u} under the "${s}" epoch, outside the ${i}-${a} the field holds.`);return u}function y(e){let t=e.slice(0,8),n=Number(t.slice(0,4)),r=Number(t.slice(4,6)),i=Number(t.slice(6,8));if(n<1997||n>2099||r<1||r>12||i<1||i>31)return null;let a=new Date(n,r-1,i);return a.getMonth()===r-1&&a.getDate()===i?a:null}function b(e){let t=e.slice(19),n=e.slice(0,4)+t.slice(0,5),r=t.slice(5,15),i=t.slice(15,25);return n+d(n)+r+d(r)+i+d(i)+e.slice(4,5)+e.slice(5,19)}function x(e){let t=S(e)===11?m:d,n=``;for(let r=0;r<44;r+=11){let i=e.slice(r,r+11);n+=i+t(i)}return n}function S(e){return e[2]===`8`||e[2]===`9`?11:10}function C(e,t){let n=Number(e.slice(5,9)),r=_(n,t),i=e.slice(3,4);return{kind:`banco`,codigoBarras:e,linhaDigitavel:b(e),banco:e.slice(0,3),moeda:i,moedaLabel:i===`9`?`Real`:null,dv:e.slice(4,5),fatorVencimento:n,vencimento:r?.date??null,vencimentoEpoch:r?.epoch??null,valor:Number(e.slice(9,19))/100,campoLivre:e.slice(19)}}function w(e){let t=Number(e[1]),n=Number(e[2]),r=t===l,i=r?e.slice(23):e.slice(19),a=e.slice(4,15),o=n===6||n===8;return{kind:`arrecadacao`,codigoBarras:e,linhaDigitavel:x(e),segmento:t,segmentoLabel:c[t]??null,identificacaoValor:n,dvModulo:S(e),dv:e.slice(3,4),valor:o?Number(a)/100:null,valorRaw:a,empresa:r?e.slice(15,23):e.slice(15,19),empresaIsCnpj:r,campoLivre:i,vencimentoCampoLivre:y(i)}}function T(t){if(t.startsWith(`8`)){let n=t.slice(0,3)+t.slice(4),r=S(t)===11?m(n):d(n);if(String(r)!==t[3])throw new e(`Arrecadação check digit is ${t[3]}, recomputed ${r} (módulo ${S(t)}).`);return}let n=p(t.slice(0,4)+t.slice(5));if(String(n)!==t[4])throw new e(`Barcode check digit is ${t[4]}, recomputed ${n}.`)}function E(t){if(!`6789`.includes(t[2]))throw new e(`Position 3 of an arrecadação barcode must be 6, 7, 8 or 9 (identificação do valor), got ${t[2]}.`)}function D(t,n={}){let r=u(t);if(r.length!==44)throw new e(`A barcode has 44 digits, got ${r.length}. A 47- or 48-digit string is a typed line — use parseLinhaDigitavel.`);return r.startsWith(`8`)?(E(r),T(r),w(r)):(T(r),C(r,n))}function O(t,n={}){let r=u(t);if(r.length===47)return D(k(r),n);if(r.length===48)return D(A(r),n);throw new e(`A typed line has 47 digits (bank) or 48 (arrecadação), got ${r.length}. A 44-digit string is a barcode — use parseCodigoBarras.`)}function k(t){return[[t.slice(0,9),t.slice(9,10)],[t.slice(10,20),t.slice(20,21)],[t.slice(21,31),t.slice(31,32)]].forEach(([t,n],r)=>{let i=d(t);if(String(i)!==n)throw new e(`Field ${r+1} check digit is ${n}, recomputed ${i} (módulo 10).`)}),t.slice(0,4)+t.slice(32,33)+t.slice(33,47)+t.slice(4,9)+t.slice(10,20)+t.slice(21,31)}function A(t){let n=[0,12,24,36].map(e=>({body:t.slice(e,e+11),dv:t.slice(e+11,e+12)})),r=n.map(e=>e.body).join(``);if(!r.startsWith(`8`))throw new e(`A 48-digit typed line is an arrecadação slip and must start with 8, got ${r[0]}.`);E(r);let i=S(r)===11?m:d;return n.forEach((t,n)=>{let a=i(t.body);if(String(a)!==t.dv)throw new e(`Block ${n+1} check digit is ${t.dv}, recomputed ${a} (módulo ${S(r)}).`)}),r}function j(e){return O(e).codigoBarras}function M(e){return D(e).linhaDigitavel}function N(e){try{let t=u(e);return t.length===44?D(t):O(t),!0}catch{return!1}}function P(e){let t=u(e);return t.length===47?[`${t.slice(0,5)}.${t.slice(5,10)}`,`${t.slice(10,15)}.${t.slice(15,21)}`,`${t.slice(21,26)}.${t.slice(26,32)}`,t.slice(32,33),t.slice(33)].join(` `):t.length===48?[0,12,24,36].map(e=>t.slice(e,e+12)).join(` `):e}exports.BoletoError=e,exports.boletoDueDate=_,exports.boletoKind=h,exports.codigoBarrasToLinhaDigitavel=M,exports.fatorVencimento=v,exports.formatLinhaDigitavel=P,exports.linhaDigitavelToCodigoBarras=j,exports.mod10Dac=d,exports.mod11DacArrecadacao=m,exports.mod11DacCobranca=p,exports.parseCodigoBarras=D,exports.parseLinhaDigitavel=O,exports.validateBoleto=N;
2
+ //# sourceMappingURL=boleto.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"boleto.cjs","names":[],"sources":["../../src/br/boleto.ts"],"sourcesContent":["/**\n * A boleto string could not be read, or failed a check digit.\n *\n * Its own class so a scanner screen can tell \"this is not a boleto\" apart from a\n * bug, and so the message can be shown to the operator as-is.\n */\nexport class BoletoError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"BoletoError\";\n }\n}\n\n/**\n * The two incompatible layouts that share the 44-digit barcode.\n *\n * `\"banco\"` is the cobrança boleto every bank issues; `\"arrecadacao\"` is the\n * concessionária/tributo slip, which starts with `8` and lays out its 44 digits\n * completely differently — same length, different meaning for every field.\n */\nexport type BoletoKind = \"banco\" | \"arrecadacao\";\n\n/** Which base date the fator de vencimento counts from. See {@link boletoDueDate}. */\nexport type BoletoEpoch = \"auto\" | \"legacy\" | \"current\";\n\n/** Options shared by every parser here. */\nexport interface BoletoOptions {\n /** Fator de vencimento epoch. Default `\"auto\"`. */\n epoch?: BoletoEpoch;\n /** Date `\"auto\"` measures proximity against. Default `new Date()`. */\n reference?: Date;\n}\n\n/** A cobrança boleto — the kind a bank issues against an invoice. */\nexport interface BoletoBanco {\n kind: \"banco\";\n /** 44 digits. */\n codigoBarras: string;\n /** 47 digits. */\n linhaDigitavel: string;\n /** 3-digit bank code in the clearing house, e.g. `\"341\"`. */\n banco: string;\n /** 1 digit. `\"9\"` is BRL; nothing else is in use. */\n moeda: string;\n /** `\"Real\"` for `\"9\"`, `null` for anything else. */\n moedaLabel: string | null;\n /** The general check digit, position 5 of the barcode. */\n dv: string;\n /** Raw 4-digit field. `0` means the boleto carries no due date. */\n fatorVencimento: number;\n /** Due date, or `null` when the fator is `0`. */\n vencimento: Date | null;\n /** Which epoch {@link vencimento} was resolved under. `null` when there is none. */\n vencimentoEpoch: Exclude<BoletoEpoch, \"auto\"> | null;\n /** Reais. `0` when the issuer left the amount for the payer to fill in. */\n valor: number;\n /** 25 digits the issuing bank defines. Not interpretable without its manual. */\n campoLivre: string;\n}\n\n/** An arrecadação/convênio slip — utilities, taxes, traffic fines. */\nexport interface BoletoArrecadacao {\n kind: \"arrecadacao\";\n /** 44 digits, always starting with `8`. */\n codigoBarras: string;\n /** 48 digits, in four blocks of twelve. */\n linhaDigitavel: string;\n /** Position 2. See {@link segmentoLabel}. */\n segmento: number;\n /** Human label, or `null` for a value the layout does not define. */\n segmentoLabel: string | null;\n /** Position 3: `6`/`8` mean real money, `7`/`9` mean a reference quantity. */\n identificacaoValor: number;\n /** Which modulo position 3 selects for the general check digit. */\n dvModulo: 10 | 11;\n /** The general check digit, position 4. */\n dv: string;\n /** Reais, or `null` when position 3 says the field is a reference, not money. */\n valor: number | null;\n /** The raw 11-digit value field, useful when {@link valor} is `null`. */\n valorRaw: string;\n /**\n * Positions 16-19 — the 4-digit code FEBRABAN assigns the company — or, on\n * segmento 6, positions 16-23, which are the first eight CNPJ digits.\n */\n empresa: string;\n /** `true` when {@link empresa} is a CNPJ prefix rather than a FEBRABAN code. */\n empresaIsCnpj: boolean;\n /** 25 digits, or 21 when the CNPJ took four of them. Issuer-defined. */\n campoLivre: string;\n /**\n * Due date read from the first eight digits of the campo livre.\n *\n * The layout says a due date, **if present**, must sit there as `AAAAMMDD` —\n * but the field is optional and nothing marks its presence, so a campo livre\n * that merely looks like a date lands here too. Treat it as a hint for a UI,\n * never as the date a payment settles against.\n */\n vencimentoCampoLivre: Date | null;\n}\n\n/** What the two parsers return. Narrow on `kind`. */\nexport type Boleto = BoletoBanco | BoletoArrecadacao;\n\n/** Base date of the fator de vencimento as FEBRABAN defined it in 1997. */\nconst LEGACY_EPOCH_UTC = Date.UTC(1997, 9, 7);\n\n/**\n * Base date the fator de vencimento restarted from.\n *\n * FEBRABAN communication FB-009/2023: the 4-digit field hit its ceiling of 9999\n * on 2025-02-21 (1997-10-07 + 9999 days), so from 2025-02-22 the counter restarts\n * at 1000 against a new base of 2022-05-29 (2022-05-29 + 1000 days = 2025-02-22).\n */\nconst CURRENT_EPOCH_UTC = Date.UTC(2022, 4, 29);\n\nconst MS_PER_DAY = 86_400_000;\n\n/** First fator FEBRABAN ever put in circulation, in either epoch. */\nconst FATOR_MIN = 1000;\n\n/** Last fator the 4-digit field can hold. */\nconst FATOR_MAX = 9999;\n\nconst MOD10_WEIGHTS = [2, 1] as const;\nconst MOD11_WEIGHT_FIRST = 2;\nconst MOD11_WEIGHT_LAST = 9;\n\nconst SEGMENTO_LABELS: Record<number, string> = {\n 1: \"Prefeituras\",\n 2: \"Saneamento\",\n 3: \"Energia elétrica e gás\",\n 4: \"Telecomunicações\",\n 5: \"Órgãos governamentais\",\n 6: \"Carnes e assemelhados ou empresas identificadas por CNPJ\",\n 7: \"Multas de trânsito\",\n 9: \"Uso exclusivo do banco\",\n};\n\n/** Segmento whose company identifier is a CNPJ prefix instead of a FEBRABAN code. */\nconst SEGMENTO_CNPJ = 6;\n\n/** Digits of a value that may carry the usual dots, spaces and dashes. */\nfunction digits(value: string): string {\n return value.replace(/\\D/g, \"\");\n}\n\n/**\n * DAC módulo 10, FEBRABAN flavour.\n *\n * Multipliers cycle `2, 1, 2, 1, …` from right to left; the **digits** of each\n * product are summed individually (so `6 × 2 = 12` contributes `1 + 2`); the DAC\n * is `10 - (sum mod 10)`, and `0` when that remainder is `0`.\n *\n * Ported from \"Layout Padrão de Arrecadação/Recebimento com Utilização do Código\n * de Barras\", FEBRABAN version 07 (effective 2023-03-01), section 07 — whose own\n * worked example gives `01230067896 → 3`.\n *\n * @param value - Digits only.\n * @returns The check digit, 0-9.\n * @throws {BoletoError} When `value` is empty or holds a non-digit.\n */\nexport function mod10Dac(value: string): number {\n if (!/^\\d+$/.test(value))\n throw new BoletoError(`mod10Dac needs digits, got ${JSON.stringify(value)}.`);\n let sum = 0;\n for (let index = 0; index < value.length; index += 1) {\n const fromRight = value.length - 1 - index;\n const product = Number(value[index]) * MOD10_WEIGHTS[fromRight % MOD10_WEIGHTS.length]!;\n sum += product > 9 ? product - 9 : product;\n }\n const remainder = sum % 10;\n return remainder === 0 ? 0 : 10 - remainder;\n}\n\n/** Sum of `digit × weight` with weights cycling 2…9 from the right. */\nfunction mod11Sum(value: string): number {\n const span = MOD11_WEIGHT_LAST - MOD11_WEIGHT_FIRST + 1;\n let sum = 0;\n for (let index = 0; index < value.length; index += 1) {\n const fromRight = value.length - 1 - index;\n sum += Number(value[index]) * (MOD11_WEIGHT_FIRST + (fromRight % span));\n }\n return sum;\n}\n\n/**\n * DAC módulo 11 for a **cobrança** barcode — position 5 of a bank boleto.\n *\n * Weights cycle `2…9` from right to left, the products are summed whole, and the\n * DAC is `11 - (sum mod 11)`. A remainder of `0`, `1` or `10` would put `11`, `10`\n * or `1` in a one-digit field, and FEBRABAN resolves all three to **`1`**.\n *\n * That last rule is where cobrança and arrecadação disagree — see\n * {@link mod11DacArrecadacao}, which resolves the same remainders to `0`. Using\n * one flavour on the other layout produces a check digit that is wrong exactly\n * 3 times in 11, which is why they are separate functions here.\n *\n * @param value - The 43 digits of the barcode with position 5 removed.\n * @returns The check digit, 1-9.\n * @throws {BoletoError} When `value` is empty or holds a non-digit.\n */\nexport function mod11DacCobranca(value: string): number {\n if (!/^\\d+$/.test(value)) {\n throw new BoletoError(`mod11DacCobranca needs digits, got ${JSON.stringify(value)}.`);\n }\n const remainder = mod11Sum(value) % 11;\n return remainder === 0 || remainder === 1 || remainder === 10 ? 1 : 11 - remainder;\n}\n\n/**\n * DAC módulo 11 for an **arrecadação** barcode — position 4 of a `8…` slip.\n *\n * Same weights and same subtraction as {@link mod11DacCobranca}, but a remainder\n * of `0` or `1` resolves to **`0`**.\n *\n * Ported from the FEBRABAN version 07 layout, section 10, and pinned by that\n * document's own worked example: the 43-digit sequence\n * `8220000215048200974123220154098290108605940` sums to 705, `705 mod 11 = 1`,\n * and the barcode the spec prints carries `0` in position 4.\n *\n * @param value - The 43 digits of the barcode with position 4 removed.\n * @returns The check digit, 0 or 2-9.\n * @throws {BoletoError} When `value` is empty or holds a non-digit.\n */\nexport function mod11DacArrecadacao(value: string): number {\n if (!/^\\d+$/.test(value)) {\n throw new BoletoError(`mod11DacArrecadacao needs digits, got ${JSON.stringify(value)}.`);\n }\n const remainder = mod11Sum(value) % 11;\n return remainder === 0 || remainder === 1 ? 0 : 11 - remainder;\n}\n\n/**\n * Which layout a string is in, without throwing.\n *\n * @param value - A barcode or typed line, masked or not.\n * @returns The layout, or `null` when the length is not 44, 47 or 48.\n */\nexport function boletoKind(value: string): BoletoKind | null {\n const raw = digits(value);\n if (raw.length === 47) return \"banco\";\n if (raw.length === 48) return \"arrecadacao\";\n if (raw.length === 44) return raw.startsWith(\"8\") ? \"arrecadacao\" : \"banco\";\n return null;\n}\n\n/** Local midnight of the calendar day `days` after a UTC epoch. */\nfunction dayAfter(epochUtcMs: number, days: number): Date {\n const utc = new Date(epochUtcMs + days * MS_PER_DAY);\n return new Date(utc.getUTCFullYear(), utc.getUTCMonth(), utc.getUTCDate());\n}\n\n/**\n * Resolve a fator de vencimento to a calendar date.\n *\n * The field is four digits of days since a base date, and it has had **two** base\n * dates: 1997-10-07 until the counter saturated at 9999 on 2025-02-21, then\n * 2022-05-29 from 2025-02-22, when FEBRABAN restarted it at 1000.\n *\n * !!! danger \"The two epochs are genuinely ambiguous\"\n * Every fator from 1000 to 9999 has a reading under each base — 1997-10-07\n * gives a date in `2000-07-03 … 2025-02-21`, 2022-05-29 gives one in\n * `2025-02-22 … 2049-10-14`. Nothing in the barcode says which. `\"auto\"`\n * picks whichever lands nearer `reference`, which is right for the case that\n * matters (a slip being paid now) and wrong for an archive sweep. Pass\n * `\"legacy\"` or `\"current\"` when you know.\n *\n * @param fator - The raw 4-digit field as a number. `0` means \"no due date\".\n * @param options - Epoch selection. Default `\"auto\"` against `new Date()`.\n * @returns Local midnight of the due date, or `null` when `fator` is `0`.\n *\n * @example\n * boletoDueDate(1000, { epoch: \"legacy\" }); // 2000-07-03\n * boletoDueDate(1000, { epoch: \"current\" }); // 2025-02-22\n */\nexport function boletoDueDate(\n fator: number,\n options: BoletoOptions = {},\n): { date: Date; epoch: Exclude<BoletoEpoch, \"auto\"> } | null {\n if (fator === 0) return null;\n const { epoch = \"auto\", reference = new Date() } = options;\n\n if (epoch === \"legacy\") return { date: dayAfter(LEGACY_EPOCH_UTC, fator), epoch: \"legacy\" };\n if (epoch === \"current\") return { date: dayAfter(CURRENT_EPOCH_UTC, fator), epoch: \"current\" };\n\n const legacy = dayAfter(LEGACY_EPOCH_UTC, fator);\n if (fator < FATOR_MIN) return { date: legacy, epoch: \"legacy\" };\n const current = dayAfter(CURRENT_EPOCH_UTC, fator);\n const at = reference.getTime();\n return Math.abs(current.getTime() - at) <= Math.abs(legacy.getTime() - at)\n ? { date: current, epoch: \"current\" }\n : { date: legacy, epoch: \"legacy\" };\n}\n\n/**\n * Invert {@link boletoDueDate}: the fator that encodes a due date.\n *\n * @param date - The due date. Only its local calendar day is used.\n * @param epoch - Base date to count from. Default `\"current\"`, the epoch in force\n * since 2025-02-22 and therefore the one a boleto issued today must use.\n * @returns The 4-digit fator.\n * @throws {BoletoError} When the date falls outside the 1000-9999 window of that\n * epoch, because no fator can represent it.\n *\n * @example\n * fatorVencimento(new Date(2025, 1, 22)); // 1000\n */\nexport function fatorVencimento(\n date: Date,\n epoch: Exclude<BoletoEpoch, \"auto\"> = \"current\",\n): number {\n const base = epoch === \"legacy\" ? LEGACY_EPOCH_UTC : CURRENT_EPOCH_UTC;\n const target = Date.UTC(date.getFullYear(), date.getMonth(), date.getDate());\n const fator = Math.round((target - base) / MS_PER_DAY);\n if (fator < FATOR_MIN || fator > FATOR_MAX) {\n throw new BoletoError(\n `${date.toISOString().slice(0, 10)} is fator ${fator} under the \"${epoch}\" epoch, ` +\n `outside the ${FATOR_MIN}-${FATOR_MAX} the field holds.`,\n );\n }\n return fator;\n}\n\n/**\n * `AAAAMMDD` at the head of an arrecadação campo livre, when it reads as a date.\n *\n * The caller only ever passes a slice of a validated barcode, so the head is\n * always eight digits; what is not guaranteed is that those digits are a date, and\n * `20260231` has to come back `null` rather than roll into March.\n */\nfunction campoLivreDate(campoLivre: string): Date | null {\n const head = campoLivre.slice(0, 8);\n const year = Number(head.slice(0, 4));\n const month = Number(head.slice(4, 6));\n const day = Number(head.slice(6, 8));\n if (year < 1997 || year > 2099 || month < 1 || month > 12 || day < 1 || day > 31) return null;\n const date = new Date(year, month - 1, day);\n return date.getMonth() === month - 1 && date.getDate() === day ? date : null;\n}\n\n/** Assemble the 47-digit typed line from a validated 44-digit bank barcode. */\nfunction bancoLinha(barcode: string): string {\n const campoLivre = barcode.slice(19);\n const field1 = barcode.slice(0, 4) + campoLivre.slice(0, 5);\n const field2 = campoLivre.slice(5, 15);\n const field3 = campoLivre.slice(15, 25);\n return (\n field1 +\n mod10Dac(field1) +\n field2 +\n mod10Dac(field2) +\n field3 +\n mod10Dac(field3) +\n barcode.slice(4, 5) +\n barcode.slice(5, 19)\n );\n}\n\n/** Assemble the 48-digit typed line from a validated 44-digit arrecadação barcode. */\nfunction arrecadacaoLinha(barcode: string): string {\n const dac = mod11Selector(barcode) === 11 ? mod11DacArrecadacao : mod10Dac;\n let line = \"\";\n for (let start = 0; start < 44; start += 11) {\n const block = barcode.slice(start, start + 11);\n line += block + dac(block);\n }\n return line;\n}\n\n/** Which modulo position 3 of an arrecadação barcode selects. */\nfunction mod11Selector(barcode: string): 10 | 11 {\n return barcode[2] === \"8\" || barcode[2] === \"9\" ? 11 : 10;\n}\n\n/** Read a 44-digit bank barcode, whose general DV has already been checked. */\nfunction readBanco(barcode: string, options: BoletoOptions): BoletoBanco {\n const fator = Number(barcode.slice(5, 9));\n const due = boletoDueDate(fator, options);\n const moeda = barcode.slice(3, 4);\n return {\n kind: \"banco\",\n codigoBarras: barcode,\n linhaDigitavel: bancoLinha(barcode),\n banco: barcode.slice(0, 3),\n moeda,\n moedaLabel: moeda === \"9\" ? \"Real\" : null,\n dv: barcode.slice(4, 5),\n fatorVencimento: fator,\n vencimento: due?.date ?? null,\n vencimentoEpoch: due?.epoch ?? null,\n valor: Number(barcode.slice(9, 19)) / 100,\n campoLivre: barcode.slice(19),\n };\n}\n\n/** Read a 44-digit arrecadação barcode, whose general DV has already been checked. */\nfunction readArrecadacao(barcode: string): BoletoArrecadacao {\n const segmento = Number(barcode[1]);\n const identificacaoValor = Number(barcode[2]);\n const empresaIsCnpj = segmento === SEGMENTO_CNPJ;\n const campoLivre = empresaIsCnpj ? barcode.slice(23) : barcode.slice(19);\n const valorRaw = barcode.slice(4, 15);\n const isMoney = identificacaoValor === 6 || identificacaoValor === 8;\n return {\n kind: \"arrecadacao\",\n codigoBarras: barcode,\n linhaDigitavel: arrecadacaoLinha(barcode),\n segmento,\n segmentoLabel: SEGMENTO_LABELS[segmento] ?? null,\n identificacaoValor,\n dvModulo: mod11Selector(barcode),\n dv: barcode.slice(3, 4),\n valor: isMoney ? Number(valorRaw) / 100 : null,\n valorRaw,\n empresa: empresaIsCnpj ? barcode.slice(15, 23) : barcode.slice(15, 19),\n empresaIsCnpj,\n campoLivre,\n vencimentoCampoLivre: campoLivreDate(campoLivre),\n };\n}\n\n/** Recompute and compare the general check digit of a 44-digit barcode. */\nfunction assertBarcodeDv(barcode: string): void {\n if (barcode.startsWith(\"8\")) {\n const body = barcode.slice(0, 3) + barcode.slice(4);\n const dac = mod11Selector(barcode) === 11 ? mod11DacArrecadacao(body) : mod10Dac(body);\n if (String(dac) !== barcode[3]) {\n throw new BoletoError(\n `Arrecadação check digit is ${barcode[3]}, recomputed ${dac} (módulo ${mod11Selector(barcode)}).`,\n );\n }\n return;\n }\n const dac = mod11DacCobranca(barcode.slice(0, 4) + barcode.slice(5));\n if (String(dac) !== barcode[4]) {\n throw new BoletoError(`Barcode check digit is ${barcode[4]}, recomputed ${dac}.`);\n }\n}\n\n/** Reject an arrecadação barcode whose position 3 is not one of 6, 7, 8, 9. */\nfunction assertIdentificacaoValor(barcode: string): void {\n if (!\"6789\".includes(barcode[2]!)) {\n throw new BoletoError(\n `Position 3 of an arrecadação barcode must be 6, 7, 8 or 9 (identificação do valor), got ${barcode[2]}.`,\n );\n }\n}\n\n/**\n * Read a 44-digit barcode — either layout — into its fields.\n *\n * The first digit picks the layout: `8` is an arrecadação/convênio slip, anything\n * else is a cobrança boleto. They are **not** variants of one format; every field\n * moves. Narrow the result on `kind` before touching it.\n *\n * @param value - 44 digits. Spaces and punctuation are ignored.\n * @param options - Fator de vencimento epoch. See {@link boletoDueDate}.\n * @returns The parsed boleto, with the matching typed line filled in.\n * @throws {BoletoError} On a length other than 44, on a general check digit that\n * does not recompute, or on an arrecadação slip whose position 3 is out of spec.\n *\n * @example\n * const boleto = parseCodigoBarras(scanned);\n * if (boleto.kind === \"banco\") console.log(boleto.valor, boleto.vencimento);\n */\nexport function parseCodigoBarras(value: string, options: BoletoOptions = {}): Boleto {\n const barcode = digits(value);\n if (barcode.length !== 44) {\n throw new BoletoError(\n `A barcode has 44 digits, got ${barcode.length}. ` +\n \"A 47- or 48-digit string is a typed line — use parseLinhaDigitavel.\",\n );\n }\n if (barcode.startsWith(\"8\")) {\n assertIdentificacaoValor(barcode);\n assertBarcodeDv(barcode);\n return readArrecadacao(barcode);\n }\n assertBarcodeDv(barcode);\n return readBanco(barcode, options);\n}\n\n/**\n * Read a typed line — 47 digits for a bank boleto, 48 for an arrecadação slip.\n *\n * Both layouts interleave check digits with the data, so the function rebuilds the\n * 44-digit barcode as it goes and every DV is verified: the three (bank) or four\n * (arrecadação) block digits, plus the general one.\n *\n * @param value - 47 or 48 digits. The usual `.`, ` ` and `-` are ignored.\n * @param options - Fator de vencimento epoch. See {@link boletoDueDate}.\n * @returns The parsed boleto, with the barcode filled in.\n * @throws {BoletoError} On a length other than 47 or 48, or on any check digit\n * that does not recompute.\n *\n * @example\n * const boleto = parseLinhaDigitavel(\"34191.09008 64592.181109 00000.463074 1 84410000002000\");\n */\nexport function parseLinhaDigitavel(value: string, options: BoletoOptions = {}): Boleto {\n const line = digits(value);\n if (line.length === 47) return parseCodigoBarras(bancoBarcode(line), options);\n if (line.length === 48) return parseCodigoBarras(arrecadacaoBarcode(line), options);\n throw new BoletoError(\n `A typed line has 47 digits (bank) or 48 (arrecadação), got ${line.length}. ` +\n \"A 44-digit string is a barcode — use parseCodigoBarras.\",\n );\n}\n\n/** Verify the three field DVs of a 47-digit line and rebuild the barcode. */\nfunction bancoBarcode(line: string): string {\n const fields: [string, string][] = [\n [line.slice(0, 9), line.slice(9, 10)],\n [line.slice(10, 20), line.slice(20, 21)],\n [line.slice(21, 31), line.slice(31, 32)],\n ];\n fields.forEach(([body, dv], index) => {\n const dac = mod10Dac(body);\n if (String(dac) !== dv) {\n throw new BoletoError(\n `Field ${index + 1} check digit is ${dv}, recomputed ${dac} (módulo 10).`,\n );\n }\n });\n return (\n line.slice(0, 4) +\n line.slice(32, 33) +\n line.slice(33, 47) +\n line.slice(4, 9) +\n line.slice(10, 20) +\n line.slice(21, 31)\n );\n}\n\n/** Verify the four block DVs of a 48-digit line and rebuild the barcode. */\nfunction arrecadacaoBarcode(line: string): string {\n const blocks = [0, 12, 24, 36].map((start) => ({\n body: line.slice(start, start + 11),\n dv: line.slice(start + 11, start + 12),\n }));\n const barcode = blocks.map((block) => block.body).join(\"\");\n if (!barcode.startsWith(\"8\")) {\n throw new BoletoError(\n `A 48-digit typed line is an arrecadação slip and must start with 8, got ${barcode[0]}.`,\n );\n }\n assertIdentificacaoValor(barcode);\n const dac = mod11Selector(barcode) === 11 ? mod11DacArrecadacao : mod10Dac;\n blocks.forEach((block, index) => {\n const expected = dac(block.body);\n if (String(expected) !== block.dv) {\n throw new BoletoError(\n `Block ${index + 1} check digit is ${block.dv}, recomputed ${expected} ` +\n `(módulo ${mod11Selector(barcode)}).`,\n );\n }\n });\n return barcode;\n}\n\n/**\n * Convert a typed line to its 44-digit barcode.\n *\n * @param value - 47 or 48 digits.\n * @returns The 44-digit barcode.\n * @throws {BoletoError} On a bad length or a check digit that does not recompute.\n */\nexport function linhaDigitavelToCodigoBarras(value: string): string {\n return parseLinhaDigitavel(value).codigoBarras;\n}\n\n/**\n * Convert a 44-digit barcode to its typed line — 47 digits, or 48 for `8…`.\n *\n * @param value - 44 digits.\n * @returns The typed line, check digits included.\n * @throws {BoletoError} On a bad length or a general check digit that does not\n * recompute.\n */\nexport function codigoBarrasToLinhaDigitavel(value: string): string {\n return parseCodigoBarras(value).linhaDigitavel;\n}\n\n/**\n * Whether a boleto string is internally consistent.\n *\n * Checks every digit the layout can check — the block DVs of a typed line and the\n * general DV in both representations. It says nothing about whether the boleto\n * exists, is registered, or is still payable: only a bank can answer that. What it\n * *does* catch is the common failure, a mistyped or truncated line.\n *\n * @param value - A barcode (44) or typed line (47/48), masked or not.\n * @returns `true` when everything recomputes.\n *\n * @example\n * if (!validateBoleto(input)) setError(\"Confira a linha digitável.\");\n */\nexport function validateBoleto(value: string): boolean {\n try {\n const raw = digits(value);\n if (raw.length === 44) parseCodigoBarras(raw);\n else parseLinhaDigitavel(raw);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Group a typed line the way it is printed, so a human can read it back.\n *\n * 47 digits become `AAABC.CCCCD EEEEE.EEEEEF GGGGG.GGGGGH I JJJJKKKKKKKKKK`;\n * 48 digits become four blocks of twelve. Anything else is returned untouched —\n * this is a display helper, not a validator.\n *\n * @param value - A typed line, masked or not.\n * @returns The grouped string.\n *\n * @example\n * formatLinhaDigitavel(\"34191090086459218110900000463074184410000002000\");\n * // \"34191.09008 64592.181109 00000.463074 1 84410000002000\"\n */\nexport function formatLinhaDigitavel(value: string): string {\n const line = digits(value);\n if (line.length === 47) {\n return [\n `${line.slice(0, 5)}.${line.slice(5, 10)}`,\n `${line.slice(10, 15)}.${line.slice(15, 21)}`,\n `${line.slice(21, 26)}.${line.slice(26, 32)}`,\n line.slice(32, 33),\n line.slice(33),\n ].join(\" \");\n }\n if (line.length === 48) {\n return [0, 12, 24, 36].map((start) => line.slice(start, start + 12)).join(\" \");\n }\n return value;\n}\n"],"mappings":"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"}
@@ -0,0 +1,225 @@
1
+ //#region src/br/boleto.ts
2
+ var e = class extends Error {
3
+ constructor(e) {
4
+ super(e), this.name = "BoletoError";
5
+ }
6
+ }, t = Date.UTC(1997, 9, 7), n = Date.UTC(2022, 4, 29), r = 864e5, i = 1e3, a = 9999, o = [2, 1], s = 2, c = {
7
+ 1: "Prefeituras",
8
+ 2: "Saneamento",
9
+ 3: "Energia elétrica e gás",
10
+ 4: "Telecomunicações",
11
+ 5: "Órgãos governamentais",
12
+ 6: "Carnes e assemelhados ou empresas identificadas por CNPJ",
13
+ 7: "Multas de trânsito",
14
+ 9: "Uso exclusivo do banco"
15
+ }, l = 6;
16
+ function u(e) {
17
+ return e.replace(/\D/g, "");
18
+ }
19
+ function d(t) {
20
+ if (!/^\d+$/.test(t)) throw new e(`mod10Dac needs digits, got ${JSON.stringify(t)}.`);
21
+ let n = 0;
22
+ for (let e = 0; e < t.length; e += 1) {
23
+ let r = t.length - 1 - e, i = Number(t[e]) * o[r % o.length];
24
+ n += i > 9 ? i - 9 : i;
25
+ }
26
+ let r = n % 10;
27
+ return r === 0 ? 0 : 10 - r;
28
+ }
29
+ function f(e) {
30
+ let t = 0;
31
+ for (let n = 0; n < e.length; n += 1) {
32
+ let r = e.length - 1 - n;
33
+ t += Number(e[n]) * (s + r % 8);
34
+ }
35
+ return t;
36
+ }
37
+ function p(t) {
38
+ if (!/^\d+$/.test(t)) throw new e(`mod11DacCobranca needs digits, got ${JSON.stringify(t)}.`);
39
+ let n = f(t) % 11;
40
+ return n === 0 || n === 1 || n === 10 ? 1 : 11 - n;
41
+ }
42
+ function m(t) {
43
+ if (!/^\d+$/.test(t)) throw new e(`mod11DacArrecadacao needs digits, got ${JSON.stringify(t)}.`);
44
+ let n = f(t) % 11;
45
+ return n === 0 || n === 1 ? 0 : 11 - n;
46
+ }
47
+ function h(e) {
48
+ let t = u(e);
49
+ return t.length === 47 ? "banco" : t.length === 48 ? "arrecadacao" : t.length === 44 ? t.startsWith("8") ? "arrecadacao" : "banco" : null;
50
+ }
51
+ function g(e, t) {
52
+ let n = new Date(e + t * r);
53
+ return new Date(n.getUTCFullYear(), n.getUTCMonth(), n.getUTCDate());
54
+ }
55
+ function _(e, r = {}) {
56
+ if (e === 0) return null;
57
+ let { epoch: a = "auto", reference: o = /* @__PURE__ */ new Date() } = r;
58
+ if (a === "legacy") return {
59
+ date: g(t, e),
60
+ epoch: "legacy"
61
+ };
62
+ if (a === "current") return {
63
+ date: g(n, e),
64
+ epoch: "current"
65
+ };
66
+ let s = g(t, e);
67
+ if (e < i) return {
68
+ date: s,
69
+ epoch: "legacy"
70
+ };
71
+ let c = g(n, e), l = o.getTime();
72
+ return Math.abs(c.getTime() - l) <= Math.abs(s.getTime() - l) ? {
73
+ date: c,
74
+ epoch: "current"
75
+ } : {
76
+ date: s,
77
+ epoch: "legacy"
78
+ };
79
+ }
80
+ function v(o, s = "current") {
81
+ let c = s === "legacy" ? t : n, l = Date.UTC(o.getFullYear(), o.getMonth(), o.getDate()), u = Math.round((l - c) / r);
82
+ if (u < i || u > a) throw new e(`${o.toISOString().slice(0, 10)} is fator ${u} under the "${s}" epoch, outside the ${i}-${a} the field holds.`);
83
+ return u;
84
+ }
85
+ function y(e) {
86
+ let t = e.slice(0, 8), n = Number(t.slice(0, 4)), r = Number(t.slice(4, 6)), i = Number(t.slice(6, 8));
87
+ if (n < 1997 || n > 2099 || r < 1 || r > 12 || i < 1 || i > 31) return null;
88
+ let a = new Date(n, r - 1, i);
89
+ return a.getMonth() === r - 1 && a.getDate() === i ? a : null;
90
+ }
91
+ function b(e) {
92
+ let t = e.slice(19), n = e.slice(0, 4) + t.slice(0, 5), r = t.slice(5, 15), i = t.slice(15, 25);
93
+ return n + d(n) + r + d(r) + i + d(i) + e.slice(4, 5) + e.slice(5, 19);
94
+ }
95
+ function x(e) {
96
+ let t = S(e) === 11 ? m : d, n = "";
97
+ for (let r = 0; r < 44; r += 11) {
98
+ let i = e.slice(r, r + 11);
99
+ n += i + t(i);
100
+ }
101
+ return n;
102
+ }
103
+ function S(e) {
104
+ return e[2] === "8" || e[2] === "9" ? 11 : 10;
105
+ }
106
+ function C(e, t) {
107
+ let n = Number(e.slice(5, 9)), r = _(n, t), i = e.slice(3, 4);
108
+ return {
109
+ kind: "banco",
110
+ codigoBarras: e,
111
+ linhaDigitavel: b(e),
112
+ banco: e.slice(0, 3),
113
+ moeda: i,
114
+ moedaLabel: i === "9" ? "Real" : null,
115
+ dv: e.slice(4, 5),
116
+ fatorVencimento: n,
117
+ vencimento: r?.date ?? null,
118
+ vencimentoEpoch: r?.epoch ?? null,
119
+ valor: Number(e.slice(9, 19)) / 100,
120
+ campoLivre: e.slice(19)
121
+ };
122
+ }
123
+ function w(e) {
124
+ let t = Number(e[1]), n = Number(e[2]), r = t === l, i = r ? e.slice(23) : e.slice(19), a = e.slice(4, 15), o = n === 6 || n === 8;
125
+ return {
126
+ kind: "arrecadacao",
127
+ codigoBarras: e,
128
+ linhaDigitavel: x(e),
129
+ segmento: t,
130
+ segmentoLabel: c[t] ?? null,
131
+ identificacaoValor: n,
132
+ dvModulo: S(e),
133
+ dv: e.slice(3, 4),
134
+ valor: o ? Number(a) / 100 : null,
135
+ valorRaw: a,
136
+ empresa: r ? e.slice(15, 23) : e.slice(15, 19),
137
+ empresaIsCnpj: r,
138
+ campoLivre: i,
139
+ vencimentoCampoLivre: y(i)
140
+ };
141
+ }
142
+ function T(t) {
143
+ if (t.startsWith("8")) {
144
+ let n = t.slice(0, 3) + t.slice(4), r = S(t) === 11 ? m(n) : d(n);
145
+ if (String(r) !== t[3]) throw new e(`Arrecadação check digit is ${t[3]}, recomputed ${r} (módulo ${S(t)}).`);
146
+ return;
147
+ }
148
+ let n = p(t.slice(0, 4) + t.slice(5));
149
+ if (String(n) !== t[4]) throw new e(`Barcode check digit is ${t[4]}, recomputed ${n}.`);
150
+ }
151
+ function E(t) {
152
+ if (!"6789".includes(t[2])) throw new e(`Position 3 of an arrecadação barcode must be 6, 7, 8 or 9 (identificação do valor), got ${t[2]}.`);
153
+ }
154
+ function D(t, n = {}) {
155
+ let r = u(t);
156
+ if (r.length !== 44) throw new e(`A barcode has 44 digits, got ${r.length}. A 47- or 48-digit string is a typed line — use parseLinhaDigitavel.`);
157
+ return r.startsWith("8") ? (E(r), T(r), w(r)) : (T(r), C(r, n));
158
+ }
159
+ function O(t, n = {}) {
160
+ let r = u(t);
161
+ if (r.length === 47) return D(k(r), n);
162
+ if (r.length === 48) return D(A(r), n);
163
+ throw new e(`A typed line has 47 digits (bank) or 48 (arrecadação), got ${r.length}. A 44-digit string is a barcode — use parseCodigoBarras.`);
164
+ }
165
+ function k(t) {
166
+ return [
167
+ [t.slice(0, 9), t.slice(9, 10)],
168
+ [t.slice(10, 20), t.slice(20, 21)],
169
+ [t.slice(21, 31), t.slice(31, 32)]
170
+ ].forEach(([t, n], r) => {
171
+ let i = d(t);
172
+ if (String(i) !== n) throw new e(`Field ${r + 1} check digit is ${n}, recomputed ${i} (módulo 10).`);
173
+ }), t.slice(0, 4) + t.slice(32, 33) + t.slice(33, 47) + t.slice(4, 9) + t.slice(10, 20) + t.slice(21, 31);
174
+ }
175
+ function A(t) {
176
+ let n = [
177
+ 0,
178
+ 12,
179
+ 24,
180
+ 36
181
+ ].map((e) => ({
182
+ body: t.slice(e, e + 11),
183
+ dv: t.slice(e + 11, e + 12)
184
+ })), r = n.map((e) => e.body).join("");
185
+ if (!r.startsWith("8")) throw new e(`A 48-digit typed line is an arrecadação slip and must start with 8, got ${r[0]}.`);
186
+ E(r);
187
+ let i = S(r) === 11 ? m : d;
188
+ return n.forEach((t, n) => {
189
+ let a = i(t.body);
190
+ if (String(a) !== t.dv) throw new e(`Block ${n + 1} check digit is ${t.dv}, recomputed ${a} (módulo ${S(r)}).`);
191
+ }), r;
192
+ }
193
+ function j(e) {
194
+ return O(e).codigoBarras;
195
+ }
196
+ function M(e) {
197
+ return D(e).linhaDigitavel;
198
+ }
199
+ function N(e) {
200
+ try {
201
+ let t = u(e);
202
+ return t.length === 44 ? D(t) : O(t), !0;
203
+ } catch {
204
+ return !1;
205
+ }
206
+ }
207
+ function P(e) {
208
+ let t = u(e);
209
+ return t.length === 47 ? [
210
+ `${t.slice(0, 5)}.${t.slice(5, 10)}`,
211
+ `${t.slice(10, 15)}.${t.slice(15, 21)}`,
212
+ `${t.slice(21, 26)}.${t.slice(26, 32)}`,
213
+ t.slice(32, 33),
214
+ t.slice(33)
215
+ ].join(" ") : t.length === 48 ? [
216
+ 0,
217
+ 12,
218
+ 24,
219
+ 36
220
+ ].map((e) => t.slice(e, e + 12)).join(" ") : e;
221
+ }
222
+ //#endregion
223
+ export { e as BoletoError, _ as boletoDueDate, h as boletoKind, M as codigoBarrasToLinhaDigitavel, v as fatorVencimento, P as formatLinhaDigitavel, j as linhaDigitavelToCodigoBarras, d as mod10Dac, m as mod11DacArrecadacao, p as mod11DacCobranca, D as parseCodigoBarras, O as parseLinhaDigitavel, N as validateBoleto };
224
+
225
+ //# sourceMappingURL=boleto.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"boleto.js","names":[],"sources":["../../src/br/boleto.ts"],"sourcesContent":["/**\n * A boleto string could not be read, or failed a check digit.\n *\n * Its own class so a scanner screen can tell \"this is not a boleto\" apart from a\n * bug, and so the message can be shown to the operator as-is.\n */\nexport class BoletoError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"BoletoError\";\n }\n}\n\n/**\n * The two incompatible layouts that share the 44-digit barcode.\n *\n * `\"banco\"` is the cobrança boleto every bank issues; `\"arrecadacao\"` is the\n * concessionária/tributo slip, which starts with `8` and lays out its 44 digits\n * completely differently — same length, different meaning for every field.\n */\nexport type BoletoKind = \"banco\" | \"arrecadacao\";\n\n/** Which base date the fator de vencimento counts from. See {@link boletoDueDate}. */\nexport type BoletoEpoch = \"auto\" | \"legacy\" | \"current\";\n\n/** Options shared by every parser here. */\nexport interface BoletoOptions {\n /** Fator de vencimento epoch. Default `\"auto\"`. */\n epoch?: BoletoEpoch;\n /** Date `\"auto\"` measures proximity against. Default `new Date()`. */\n reference?: Date;\n}\n\n/** A cobrança boleto — the kind a bank issues against an invoice. */\nexport interface BoletoBanco {\n kind: \"banco\";\n /** 44 digits. */\n codigoBarras: string;\n /** 47 digits. */\n linhaDigitavel: string;\n /** 3-digit bank code in the clearing house, e.g. `\"341\"`. */\n banco: string;\n /** 1 digit. `\"9\"` is BRL; nothing else is in use. */\n moeda: string;\n /** `\"Real\"` for `\"9\"`, `null` for anything else. */\n moedaLabel: string | null;\n /** The general check digit, position 5 of the barcode. */\n dv: string;\n /** Raw 4-digit field. `0` means the boleto carries no due date. */\n fatorVencimento: number;\n /** Due date, or `null` when the fator is `0`. */\n vencimento: Date | null;\n /** Which epoch {@link vencimento} was resolved under. `null` when there is none. */\n vencimentoEpoch: Exclude<BoletoEpoch, \"auto\"> | null;\n /** Reais. `0` when the issuer left the amount for the payer to fill in. */\n valor: number;\n /** 25 digits the issuing bank defines. Not interpretable without its manual. */\n campoLivre: string;\n}\n\n/** An arrecadação/convênio slip — utilities, taxes, traffic fines. */\nexport interface BoletoArrecadacao {\n kind: \"arrecadacao\";\n /** 44 digits, always starting with `8`. */\n codigoBarras: string;\n /** 48 digits, in four blocks of twelve. */\n linhaDigitavel: string;\n /** Position 2. See {@link segmentoLabel}. */\n segmento: number;\n /** Human label, or `null` for a value the layout does not define. */\n segmentoLabel: string | null;\n /** Position 3: `6`/`8` mean real money, `7`/`9` mean a reference quantity. */\n identificacaoValor: number;\n /** Which modulo position 3 selects for the general check digit. */\n dvModulo: 10 | 11;\n /** The general check digit, position 4. */\n dv: string;\n /** Reais, or `null` when position 3 says the field is a reference, not money. */\n valor: number | null;\n /** The raw 11-digit value field, useful when {@link valor} is `null`. */\n valorRaw: string;\n /**\n * Positions 16-19 — the 4-digit code FEBRABAN assigns the company — or, on\n * segmento 6, positions 16-23, which are the first eight CNPJ digits.\n */\n empresa: string;\n /** `true` when {@link empresa} is a CNPJ prefix rather than a FEBRABAN code. */\n empresaIsCnpj: boolean;\n /** 25 digits, or 21 when the CNPJ took four of them. Issuer-defined. */\n campoLivre: string;\n /**\n * Due date read from the first eight digits of the campo livre.\n *\n * The layout says a due date, **if present**, must sit there as `AAAAMMDD` —\n * but the field is optional and nothing marks its presence, so a campo livre\n * that merely looks like a date lands here too. Treat it as a hint for a UI,\n * never as the date a payment settles against.\n */\n vencimentoCampoLivre: Date | null;\n}\n\n/** What the two parsers return. Narrow on `kind`. */\nexport type Boleto = BoletoBanco | BoletoArrecadacao;\n\n/** Base date of the fator de vencimento as FEBRABAN defined it in 1997. */\nconst LEGACY_EPOCH_UTC = Date.UTC(1997, 9, 7);\n\n/**\n * Base date the fator de vencimento restarted from.\n *\n * FEBRABAN communication FB-009/2023: the 4-digit field hit its ceiling of 9999\n * on 2025-02-21 (1997-10-07 + 9999 days), so from 2025-02-22 the counter restarts\n * at 1000 against a new base of 2022-05-29 (2022-05-29 + 1000 days = 2025-02-22).\n */\nconst CURRENT_EPOCH_UTC = Date.UTC(2022, 4, 29);\n\nconst MS_PER_DAY = 86_400_000;\n\n/** First fator FEBRABAN ever put in circulation, in either epoch. */\nconst FATOR_MIN = 1000;\n\n/** Last fator the 4-digit field can hold. */\nconst FATOR_MAX = 9999;\n\nconst MOD10_WEIGHTS = [2, 1] as const;\nconst MOD11_WEIGHT_FIRST = 2;\nconst MOD11_WEIGHT_LAST = 9;\n\nconst SEGMENTO_LABELS: Record<number, string> = {\n 1: \"Prefeituras\",\n 2: \"Saneamento\",\n 3: \"Energia elétrica e gás\",\n 4: \"Telecomunicações\",\n 5: \"Órgãos governamentais\",\n 6: \"Carnes e assemelhados ou empresas identificadas por CNPJ\",\n 7: \"Multas de trânsito\",\n 9: \"Uso exclusivo do banco\",\n};\n\n/** Segmento whose company identifier is a CNPJ prefix instead of a FEBRABAN code. */\nconst SEGMENTO_CNPJ = 6;\n\n/** Digits of a value that may carry the usual dots, spaces and dashes. */\nfunction digits(value: string): string {\n return value.replace(/\\D/g, \"\");\n}\n\n/**\n * DAC módulo 10, FEBRABAN flavour.\n *\n * Multipliers cycle `2, 1, 2, 1, …` from right to left; the **digits** of each\n * product are summed individually (so `6 × 2 = 12` contributes `1 + 2`); the DAC\n * is `10 - (sum mod 10)`, and `0` when that remainder is `0`.\n *\n * Ported from \"Layout Padrão de Arrecadação/Recebimento com Utilização do Código\n * de Barras\", FEBRABAN version 07 (effective 2023-03-01), section 07 — whose own\n * worked example gives `01230067896 → 3`.\n *\n * @param value - Digits only.\n * @returns The check digit, 0-9.\n * @throws {BoletoError} When `value` is empty or holds a non-digit.\n */\nexport function mod10Dac(value: string): number {\n if (!/^\\d+$/.test(value))\n throw new BoletoError(`mod10Dac needs digits, got ${JSON.stringify(value)}.`);\n let sum = 0;\n for (let index = 0; index < value.length; index += 1) {\n const fromRight = value.length - 1 - index;\n const product = Number(value[index]) * MOD10_WEIGHTS[fromRight % MOD10_WEIGHTS.length]!;\n sum += product > 9 ? product - 9 : product;\n }\n const remainder = sum % 10;\n return remainder === 0 ? 0 : 10 - remainder;\n}\n\n/** Sum of `digit × weight` with weights cycling 2…9 from the right. */\nfunction mod11Sum(value: string): number {\n const span = MOD11_WEIGHT_LAST - MOD11_WEIGHT_FIRST + 1;\n let sum = 0;\n for (let index = 0; index < value.length; index += 1) {\n const fromRight = value.length - 1 - index;\n sum += Number(value[index]) * (MOD11_WEIGHT_FIRST + (fromRight % span));\n }\n return sum;\n}\n\n/**\n * DAC módulo 11 for a **cobrança** barcode — position 5 of a bank boleto.\n *\n * Weights cycle `2…9` from right to left, the products are summed whole, and the\n * DAC is `11 - (sum mod 11)`. A remainder of `0`, `1` or `10` would put `11`, `10`\n * or `1` in a one-digit field, and FEBRABAN resolves all three to **`1`**.\n *\n * That last rule is where cobrança and arrecadação disagree — see\n * {@link mod11DacArrecadacao}, which resolves the same remainders to `0`. Using\n * one flavour on the other layout produces a check digit that is wrong exactly\n * 3 times in 11, which is why they are separate functions here.\n *\n * @param value - The 43 digits of the barcode with position 5 removed.\n * @returns The check digit, 1-9.\n * @throws {BoletoError} When `value` is empty or holds a non-digit.\n */\nexport function mod11DacCobranca(value: string): number {\n if (!/^\\d+$/.test(value)) {\n throw new BoletoError(`mod11DacCobranca needs digits, got ${JSON.stringify(value)}.`);\n }\n const remainder = mod11Sum(value) % 11;\n return remainder === 0 || remainder === 1 || remainder === 10 ? 1 : 11 - remainder;\n}\n\n/**\n * DAC módulo 11 for an **arrecadação** barcode — position 4 of a `8…` slip.\n *\n * Same weights and same subtraction as {@link mod11DacCobranca}, but a remainder\n * of `0` or `1` resolves to **`0`**.\n *\n * Ported from the FEBRABAN version 07 layout, section 10, and pinned by that\n * document's own worked example: the 43-digit sequence\n * `8220000215048200974123220154098290108605940` sums to 705, `705 mod 11 = 1`,\n * and the barcode the spec prints carries `0` in position 4.\n *\n * @param value - The 43 digits of the barcode with position 4 removed.\n * @returns The check digit, 0 or 2-9.\n * @throws {BoletoError} When `value` is empty or holds a non-digit.\n */\nexport function mod11DacArrecadacao(value: string): number {\n if (!/^\\d+$/.test(value)) {\n throw new BoletoError(`mod11DacArrecadacao needs digits, got ${JSON.stringify(value)}.`);\n }\n const remainder = mod11Sum(value) % 11;\n return remainder === 0 || remainder === 1 ? 0 : 11 - remainder;\n}\n\n/**\n * Which layout a string is in, without throwing.\n *\n * @param value - A barcode or typed line, masked or not.\n * @returns The layout, or `null` when the length is not 44, 47 or 48.\n */\nexport function boletoKind(value: string): BoletoKind | null {\n const raw = digits(value);\n if (raw.length === 47) return \"banco\";\n if (raw.length === 48) return \"arrecadacao\";\n if (raw.length === 44) return raw.startsWith(\"8\") ? \"arrecadacao\" : \"banco\";\n return null;\n}\n\n/** Local midnight of the calendar day `days` after a UTC epoch. */\nfunction dayAfter(epochUtcMs: number, days: number): Date {\n const utc = new Date(epochUtcMs + days * MS_PER_DAY);\n return new Date(utc.getUTCFullYear(), utc.getUTCMonth(), utc.getUTCDate());\n}\n\n/**\n * Resolve a fator de vencimento to a calendar date.\n *\n * The field is four digits of days since a base date, and it has had **two** base\n * dates: 1997-10-07 until the counter saturated at 9999 on 2025-02-21, then\n * 2022-05-29 from 2025-02-22, when FEBRABAN restarted it at 1000.\n *\n * !!! danger \"The two epochs are genuinely ambiguous\"\n * Every fator from 1000 to 9999 has a reading under each base — 1997-10-07\n * gives a date in `2000-07-03 … 2025-02-21`, 2022-05-29 gives one in\n * `2025-02-22 … 2049-10-14`. Nothing in the barcode says which. `\"auto\"`\n * picks whichever lands nearer `reference`, which is right for the case that\n * matters (a slip being paid now) and wrong for an archive sweep. Pass\n * `\"legacy\"` or `\"current\"` when you know.\n *\n * @param fator - The raw 4-digit field as a number. `0` means \"no due date\".\n * @param options - Epoch selection. Default `\"auto\"` against `new Date()`.\n * @returns Local midnight of the due date, or `null` when `fator` is `0`.\n *\n * @example\n * boletoDueDate(1000, { epoch: \"legacy\" }); // 2000-07-03\n * boletoDueDate(1000, { epoch: \"current\" }); // 2025-02-22\n */\nexport function boletoDueDate(\n fator: number,\n options: BoletoOptions = {},\n): { date: Date; epoch: Exclude<BoletoEpoch, \"auto\"> } | null {\n if (fator === 0) return null;\n const { epoch = \"auto\", reference = new Date() } = options;\n\n if (epoch === \"legacy\") return { date: dayAfter(LEGACY_EPOCH_UTC, fator), epoch: \"legacy\" };\n if (epoch === \"current\") return { date: dayAfter(CURRENT_EPOCH_UTC, fator), epoch: \"current\" };\n\n const legacy = dayAfter(LEGACY_EPOCH_UTC, fator);\n if (fator < FATOR_MIN) return { date: legacy, epoch: \"legacy\" };\n const current = dayAfter(CURRENT_EPOCH_UTC, fator);\n const at = reference.getTime();\n return Math.abs(current.getTime() - at) <= Math.abs(legacy.getTime() - at)\n ? { date: current, epoch: \"current\" }\n : { date: legacy, epoch: \"legacy\" };\n}\n\n/**\n * Invert {@link boletoDueDate}: the fator that encodes a due date.\n *\n * @param date - The due date. Only its local calendar day is used.\n * @param epoch - Base date to count from. Default `\"current\"`, the epoch in force\n * since 2025-02-22 and therefore the one a boleto issued today must use.\n * @returns The 4-digit fator.\n * @throws {BoletoError} When the date falls outside the 1000-9999 window of that\n * epoch, because no fator can represent it.\n *\n * @example\n * fatorVencimento(new Date(2025, 1, 22)); // 1000\n */\nexport function fatorVencimento(\n date: Date,\n epoch: Exclude<BoletoEpoch, \"auto\"> = \"current\",\n): number {\n const base = epoch === \"legacy\" ? LEGACY_EPOCH_UTC : CURRENT_EPOCH_UTC;\n const target = Date.UTC(date.getFullYear(), date.getMonth(), date.getDate());\n const fator = Math.round((target - base) / MS_PER_DAY);\n if (fator < FATOR_MIN || fator > FATOR_MAX) {\n throw new BoletoError(\n `${date.toISOString().slice(0, 10)} is fator ${fator} under the \"${epoch}\" epoch, ` +\n `outside the ${FATOR_MIN}-${FATOR_MAX} the field holds.`,\n );\n }\n return fator;\n}\n\n/**\n * `AAAAMMDD` at the head of an arrecadação campo livre, when it reads as a date.\n *\n * The caller only ever passes a slice of a validated barcode, so the head is\n * always eight digits; what is not guaranteed is that those digits are a date, and\n * `20260231` has to come back `null` rather than roll into March.\n */\nfunction campoLivreDate(campoLivre: string): Date | null {\n const head = campoLivre.slice(0, 8);\n const year = Number(head.slice(0, 4));\n const month = Number(head.slice(4, 6));\n const day = Number(head.slice(6, 8));\n if (year < 1997 || year > 2099 || month < 1 || month > 12 || day < 1 || day > 31) return null;\n const date = new Date(year, month - 1, day);\n return date.getMonth() === month - 1 && date.getDate() === day ? date : null;\n}\n\n/** Assemble the 47-digit typed line from a validated 44-digit bank barcode. */\nfunction bancoLinha(barcode: string): string {\n const campoLivre = barcode.slice(19);\n const field1 = barcode.slice(0, 4) + campoLivre.slice(0, 5);\n const field2 = campoLivre.slice(5, 15);\n const field3 = campoLivre.slice(15, 25);\n return (\n field1 +\n mod10Dac(field1) +\n field2 +\n mod10Dac(field2) +\n field3 +\n mod10Dac(field3) +\n barcode.slice(4, 5) +\n barcode.slice(5, 19)\n );\n}\n\n/** Assemble the 48-digit typed line from a validated 44-digit arrecadação barcode. */\nfunction arrecadacaoLinha(barcode: string): string {\n const dac = mod11Selector(barcode) === 11 ? mod11DacArrecadacao : mod10Dac;\n let line = \"\";\n for (let start = 0; start < 44; start += 11) {\n const block = barcode.slice(start, start + 11);\n line += block + dac(block);\n }\n return line;\n}\n\n/** Which modulo position 3 of an arrecadação barcode selects. */\nfunction mod11Selector(barcode: string): 10 | 11 {\n return barcode[2] === \"8\" || barcode[2] === \"9\" ? 11 : 10;\n}\n\n/** Read a 44-digit bank barcode, whose general DV has already been checked. */\nfunction readBanco(barcode: string, options: BoletoOptions): BoletoBanco {\n const fator = Number(barcode.slice(5, 9));\n const due = boletoDueDate(fator, options);\n const moeda = barcode.slice(3, 4);\n return {\n kind: \"banco\",\n codigoBarras: barcode,\n linhaDigitavel: bancoLinha(barcode),\n banco: barcode.slice(0, 3),\n moeda,\n moedaLabel: moeda === \"9\" ? \"Real\" : null,\n dv: barcode.slice(4, 5),\n fatorVencimento: fator,\n vencimento: due?.date ?? null,\n vencimentoEpoch: due?.epoch ?? null,\n valor: Number(barcode.slice(9, 19)) / 100,\n campoLivre: barcode.slice(19),\n };\n}\n\n/** Read a 44-digit arrecadação barcode, whose general DV has already been checked. */\nfunction readArrecadacao(barcode: string): BoletoArrecadacao {\n const segmento = Number(barcode[1]);\n const identificacaoValor = Number(barcode[2]);\n const empresaIsCnpj = segmento === SEGMENTO_CNPJ;\n const campoLivre = empresaIsCnpj ? barcode.slice(23) : barcode.slice(19);\n const valorRaw = barcode.slice(4, 15);\n const isMoney = identificacaoValor === 6 || identificacaoValor === 8;\n return {\n kind: \"arrecadacao\",\n codigoBarras: barcode,\n linhaDigitavel: arrecadacaoLinha(barcode),\n segmento,\n segmentoLabel: SEGMENTO_LABELS[segmento] ?? null,\n identificacaoValor,\n dvModulo: mod11Selector(barcode),\n dv: barcode.slice(3, 4),\n valor: isMoney ? Number(valorRaw) / 100 : null,\n valorRaw,\n empresa: empresaIsCnpj ? barcode.slice(15, 23) : barcode.slice(15, 19),\n empresaIsCnpj,\n campoLivre,\n vencimentoCampoLivre: campoLivreDate(campoLivre),\n };\n}\n\n/** Recompute and compare the general check digit of a 44-digit barcode. */\nfunction assertBarcodeDv(barcode: string): void {\n if (barcode.startsWith(\"8\")) {\n const body = barcode.slice(0, 3) + barcode.slice(4);\n const dac = mod11Selector(barcode) === 11 ? mod11DacArrecadacao(body) : mod10Dac(body);\n if (String(dac) !== barcode[3]) {\n throw new BoletoError(\n `Arrecadação check digit is ${barcode[3]}, recomputed ${dac} (módulo ${mod11Selector(barcode)}).`,\n );\n }\n return;\n }\n const dac = mod11DacCobranca(barcode.slice(0, 4) + barcode.slice(5));\n if (String(dac) !== barcode[4]) {\n throw new BoletoError(`Barcode check digit is ${barcode[4]}, recomputed ${dac}.`);\n }\n}\n\n/** Reject an arrecadação barcode whose position 3 is not one of 6, 7, 8, 9. */\nfunction assertIdentificacaoValor(barcode: string): void {\n if (!\"6789\".includes(barcode[2]!)) {\n throw new BoletoError(\n `Position 3 of an arrecadação barcode must be 6, 7, 8 or 9 (identificação do valor), got ${barcode[2]}.`,\n );\n }\n}\n\n/**\n * Read a 44-digit barcode — either layout — into its fields.\n *\n * The first digit picks the layout: `8` is an arrecadação/convênio slip, anything\n * else is a cobrança boleto. They are **not** variants of one format; every field\n * moves. Narrow the result on `kind` before touching it.\n *\n * @param value - 44 digits. Spaces and punctuation are ignored.\n * @param options - Fator de vencimento epoch. See {@link boletoDueDate}.\n * @returns The parsed boleto, with the matching typed line filled in.\n * @throws {BoletoError} On a length other than 44, on a general check digit that\n * does not recompute, or on an arrecadação slip whose position 3 is out of spec.\n *\n * @example\n * const boleto = parseCodigoBarras(scanned);\n * if (boleto.kind === \"banco\") console.log(boleto.valor, boleto.vencimento);\n */\nexport function parseCodigoBarras(value: string, options: BoletoOptions = {}): Boleto {\n const barcode = digits(value);\n if (barcode.length !== 44) {\n throw new BoletoError(\n `A barcode has 44 digits, got ${barcode.length}. ` +\n \"A 47- or 48-digit string is a typed line — use parseLinhaDigitavel.\",\n );\n }\n if (barcode.startsWith(\"8\")) {\n assertIdentificacaoValor(barcode);\n assertBarcodeDv(barcode);\n return readArrecadacao(barcode);\n }\n assertBarcodeDv(barcode);\n return readBanco(barcode, options);\n}\n\n/**\n * Read a typed line — 47 digits for a bank boleto, 48 for an arrecadação slip.\n *\n * Both layouts interleave check digits with the data, so the function rebuilds the\n * 44-digit barcode as it goes and every DV is verified: the three (bank) or four\n * (arrecadação) block digits, plus the general one.\n *\n * @param value - 47 or 48 digits. The usual `.`, ` ` and `-` are ignored.\n * @param options - Fator de vencimento epoch. See {@link boletoDueDate}.\n * @returns The parsed boleto, with the barcode filled in.\n * @throws {BoletoError} On a length other than 47 or 48, or on any check digit\n * that does not recompute.\n *\n * @example\n * const boleto = parseLinhaDigitavel(\"34191.09008 64592.181109 00000.463074 1 84410000002000\");\n */\nexport function parseLinhaDigitavel(value: string, options: BoletoOptions = {}): Boleto {\n const line = digits(value);\n if (line.length === 47) return parseCodigoBarras(bancoBarcode(line), options);\n if (line.length === 48) return parseCodigoBarras(arrecadacaoBarcode(line), options);\n throw new BoletoError(\n `A typed line has 47 digits (bank) or 48 (arrecadação), got ${line.length}. ` +\n \"A 44-digit string is a barcode — use parseCodigoBarras.\",\n );\n}\n\n/** Verify the three field DVs of a 47-digit line and rebuild the barcode. */\nfunction bancoBarcode(line: string): string {\n const fields: [string, string][] = [\n [line.slice(0, 9), line.slice(9, 10)],\n [line.slice(10, 20), line.slice(20, 21)],\n [line.slice(21, 31), line.slice(31, 32)],\n ];\n fields.forEach(([body, dv], index) => {\n const dac = mod10Dac(body);\n if (String(dac) !== dv) {\n throw new BoletoError(\n `Field ${index + 1} check digit is ${dv}, recomputed ${dac} (módulo 10).`,\n );\n }\n });\n return (\n line.slice(0, 4) +\n line.slice(32, 33) +\n line.slice(33, 47) +\n line.slice(4, 9) +\n line.slice(10, 20) +\n line.slice(21, 31)\n );\n}\n\n/** Verify the four block DVs of a 48-digit line and rebuild the barcode. */\nfunction arrecadacaoBarcode(line: string): string {\n const blocks = [0, 12, 24, 36].map((start) => ({\n body: line.slice(start, start + 11),\n dv: line.slice(start + 11, start + 12),\n }));\n const barcode = blocks.map((block) => block.body).join(\"\");\n if (!barcode.startsWith(\"8\")) {\n throw new BoletoError(\n `A 48-digit typed line is an arrecadação slip and must start with 8, got ${barcode[0]}.`,\n );\n }\n assertIdentificacaoValor(barcode);\n const dac = mod11Selector(barcode) === 11 ? mod11DacArrecadacao : mod10Dac;\n blocks.forEach((block, index) => {\n const expected = dac(block.body);\n if (String(expected) !== block.dv) {\n throw new BoletoError(\n `Block ${index + 1} check digit is ${block.dv}, recomputed ${expected} ` +\n `(módulo ${mod11Selector(barcode)}).`,\n );\n }\n });\n return barcode;\n}\n\n/**\n * Convert a typed line to its 44-digit barcode.\n *\n * @param value - 47 or 48 digits.\n * @returns The 44-digit barcode.\n * @throws {BoletoError} On a bad length or a check digit that does not recompute.\n */\nexport function linhaDigitavelToCodigoBarras(value: string): string {\n return parseLinhaDigitavel(value).codigoBarras;\n}\n\n/**\n * Convert a 44-digit barcode to its typed line — 47 digits, or 48 for `8…`.\n *\n * @param value - 44 digits.\n * @returns The typed line, check digits included.\n * @throws {BoletoError} On a bad length or a general check digit that does not\n * recompute.\n */\nexport function codigoBarrasToLinhaDigitavel(value: string): string {\n return parseCodigoBarras(value).linhaDigitavel;\n}\n\n/**\n * Whether a boleto string is internally consistent.\n *\n * Checks every digit the layout can check — the block DVs of a typed line and the\n * general DV in both representations. It says nothing about whether the boleto\n * exists, is registered, or is still payable: only a bank can answer that. What it\n * *does* catch is the common failure, a mistyped or truncated line.\n *\n * @param value - A barcode (44) or typed line (47/48), masked or not.\n * @returns `true` when everything recomputes.\n *\n * @example\n * if (!validateBoleto(input)) setError(\"Confira a linha digitável.\");\n */\nexport function validateBoleto(value: string): boolean {\n try {\n const raw = digits(value);\n if (raw.length === 44) parseCodigoBarras(raw);\n else parseLinhaDigitavel(raw);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Group a typed line the way it is printed, so a human can read it back.\n *\n * 47 digits become `AAABC.CCCCD EEEEE.EEEEEF GGGGG.GGGGGH I JJJJKKKKKKKKKK`;\n * 48 digits become four blocks of twelve. Anything else is returned untouched —\n * this is a display helper, not a validator.\n *\n * @param value - A typed line, masked or not.\n * @returns The grouped string.\n *\n * @example\n * formatLinhaDigitavel(\"34191090086459218110900000463074184410000002000\");\n * // \"34191.09008 64592.181109 00000.463074 1 84410000002000\"\n */\nexport function formatLinhaDigitavel(value: string): string {\n const line = digits(value);\n if (line.length === 47) {\n return [\n `${line.slice(0, 5)}.${line.slice(5, 10)}`,\n `${line.slice(10, 15)}.${line.slice(15, 21)}`,\n `${line.slice(21, 26)}.${line.slice(26, 32)}`,\n line.slice(32, 33),\n line.slice(33),\n ].join(\" \");\n }\n if (line.length === 48) {\n return [0, 12, 24, 36].map((start) => line.slice(start, start + 12)).join(\" \");\n }\n return value;\n}\n"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ var e=[{month:1,day:1,name:`Confraternização Universal`,kind:`national`},{month:4,day:21,name:`Tiradentes`,kind:`national`},{month:5,day:1,name:`Dia do Trabalho`,kind:`national`},{month:9,day:7,name:`Independência do Brasil`,kind:`national`},{month:10,day:12,name:`Nossa Senhora Aparecida`,kind:`national`},{month:11,day:2,name:`Finados`,kind:`national`},{month:11,day:15,name:`Proclamação da República`,kind:`national`},{month:11,day:20,name:`Dia Nacional de Zumbi e da Consciência Negra`,kind:`national`,since:2024},{month:12,day:25,name:`Natal`,kind:`national`}],t=[{offset:-48,name:`Carnaval (segunda-feira)`,kind:`banking`},{offset:-47,name:`Carnaval (terça-feira)`,kind:`banking`},{offset:-2,name:`Sexta-feira da Paixão`,kind:`banking`},{offset:60,name:`Corpus Christi`,kind:`banking`}],n=[`national`,`banking`],r=[0,6],i=864e5,a=400;function o(e,t,n){return`${String(e).padStart(4,`0`)}-${String(t).padStart(2,`0`)}-${String(n).padStart(2,`0`)}`}function s(e){if(typeof e==`string`){let t=/^(\d{4})-(\d{2})-(\d{2})$/.exec(e.trim());if(t===null)throw RangeError(`Expected a YYYY-MM-DD date, got ${JSON.stringify(e)}.`);return new Date(Number(t[1]),Number(t[2])-1,Number(t[3]))}if(Number.isNaN(e.getTime()))throw RangeError(`Received an Invalid Date.`);return new Date(e.getFullYear(),e.getMonth(),e.getDate())}function c(e){let t=s(e);return o(t.getFullYear(),t.getMonth()+1,t.getDate())}function l(e){let t=e%19,n=Math.floor(e/100),r=e%100,i=Math.floor(n/4),a=n%4,o=Math.floor((n+8)/25),s=Math.floor((n-o+1)/3),c=(19*t+n-i-s+15)%30,l=Math.floor(r/4),u=r%4,d=(32+2*a+2*l-c-u)%7,f=Math.floor((t+11*c+22*d)/451),p=Math.floor((c+d-7*f+114)/31),m=(c+d-7*f+114)%31+1;return new Date(e,p-1,m)}function u(n){let r=e.filter(e=>e.since===void 0||n>=e.since).map(e=>({date:o(n,e.month,e.day),name:e.name,kind:e.kind,movable:!1})),a=l(n);for(let e of t){let t=new Date(a.getTime()+e.offset*i);r.push({date:o(t.getFullYear(),t.getMonth()+1,t.getDate()),name:e.name,kind:e.kind,movable:!0})}return r.sort((e,t)=>e.date.localeCompare(t.date))}function d(e,t){let r=t.kinds??n,i=new Set(u(e).filter(e=>r.includes(e.kind)).map(e=>e.date));for(let e of t.extra??[])i.add(c(e));return i}function f(e,t={}){let n=c(e);return d(Number(n.slice(0,4)),t).has(n)}function p(e,t={}){let n=s(e);return!(t.weekend??r).includes(n.getDay())&&!f(n,t)}function m(e,t={}){let n=s(e);for(let e=0;e<a;e+=1)if(n.setDate(n.getDate()+1),p(n,t))return n;throw RangeError(`No business day within ${a} days of ${c(e)} — check \`weekend\` and \`extra\`.`)}function h(e,t,n={}){let r=s(e),i=t<0?-1:1;for(let o=0;o<Math.abs(t);o+=1){let t=!1;for(let e=0;e<a&&!t;e+=1)r.setDate(r.getDate()+i),t=p(r,n);if(!t)throw RangeError(`No business day within ${a} days while walking from ${c(e)} — check \`weekend\` and \`extra\`.`)}return r}exports.addBusinessDays=h,exports.easterSunday=l,exports.holidaysFor=u,exports.isBusinessDay=p,exports.isHoliday=f,exports.nextBusinessDay=m;
2
+ //# sourceMappingURL=holidays.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"holidays.cjs","names":[],"sources":["../../src/br/holidays.ts"],"sourcesContent":["/**\n * How binding a non-working day is.\n *\n * - `\"national\"` — a feriado nacional in federal law. Nobody works, and a\n * deadline that lands here moves.\n * - `\"banking\"` — not a statutory holiday, but a day the national financial\n * system does not operate: Carnaval (Monday and Tuesday), Sexta-feira da\n * Paixão and Corpus Christi. Bank branches are shut and compensation does not\n * run, so a boleto or a TED dated here settles later — but an employer may\n * legally require work, which is why the two kinds are separate.\n */\nexport type HolidayKind = \"national\" | \"banking\";\n\n/** One non-working day in a given year. */\nexport interface Holiday {\n /** `YYYY-MM-DD` in the local calendar. */\n date: string;\n /** Portuguese name, as the law or the Bacen calendar spells it. */\n name: string;\n kind: HolidayKind;\n /** `true` when the date is derived from Easter rather than fixed. */\n movable: boolean;\n}\n\n/** Anything these helpers accept as a day. */\nexport type DateInput = Date | string;\n\n/** Options shared by the calendar helpers. */\nexport interface BusinessDayOptions {\n /**\n * Which kinds count as non-working. Default `[\"national\", \"banking\"]`, i.e.\n * the Bacen calendar — the right default for anything money moves through.\n * Pass `[\"national\"]` for a labour-law calendar.\n */\n kinds?: readonly HolidayKind[];\n /**\n * Extra non-working days, as `YYYY-MM-DD` or `Date`. This is where state and\n * municipal holidays go: they are **not** in the built-in table and never will\n * be — there are 5 570 municipalities, each free to declare its own.\n */\n extra?: readonly DateInput[];\n /**\n * Days of the week that are not worked, `0` = Sunday. Default `[0, 6]`.\n */\n weekend?: readonly number[];\n}\n\n/** Fixed-date national holidays, with the year each became one. */\nconst FIXED_HOLIDAYS: readonly {\n month: number;\n day: number;\n name: string;\n kind: HolidayKind;\n since?: number;\n}[] = [\n { month: 1, day: 1, name: \"Confraternização Universal\", kind: \"national\" },\n { month: 4, day: 21, name: \"Tiradentes\", kind: \"national\" },\n { month: 5, day: 1, name: \"Dia do Trabalho\", kind: \"national\" },\n { month: 9, day: 7, name: \"Independência do Brasil\", kind: \"national\" },\n { month: 10, day: 12, name: \"Nossa Senhora Aparecida\", kind: \"national\" },\n { month: 11, day: 2, name: \"Finados\", kind: \"national\" },\n { month: 11, day: 15, name: \"Proclamação da República\", kind: \"national\" },\n {\n month: 11,\n day: 20,\n name: \"Dia Nacional de Zumbi e da Consciência Negra\",\n kind: \"national\",\n since: 2024,\n },\n { month: 12, day: 25, name: \"Natal\", kind: \"national\" },\n];\n\n/** Easter-relative holidays, as a day offset from Easter Sunday. */\nconst MOVABLE_HOLIDAYS: readonly { offset: number; name: string; kind: HolidayKind }[] = [\n { offset: -48, name: \"Carnaval (segunda-feira)\", kind: \"banking\" },\n { offset: -47, name: \"Carnaval (terça-feira)\", kind: \"banking\" },\n { offset: -2, name: \"Sexta-feira da Paixão\", kind: \"banking\" },\n { offset: 60, name: \"Corpus Christi\", kind: \"banking\" },\n];\n\nconst DEFAULT_KINDS: readonly HolidayKind[] = [\"national\", \"banking\"];\nconst DEFAULT_WEEKEND: readonly number[] = [0, 6];\nconst MS_PER_DAY = 86_400_000;\n\n/**\n * How far a walk may go before it is treated as a bug rather than a long holiday.\n *\n * A real calendar never has more than a handful of consecutive non-working days,\n * so hitting this means `extra` or `weekend` marked every day off, and looping\n * forever is worse than an error.\n */\nconst MAX_WALK_DAYS = 400;\n\n/** `YYYY-MM-DD` from a local-calendar date. */\nfunction toIso(year: number, month: number, day: number): string {\n return `${String(year).padStart(4, \"0\")}-${String(month).padStart(2, \"0\")}-${String(day).padStart(2, \"0\")}`;\n}\n\n/**\n * Local midnight for any accepted input.\n *\n * Everything here works on local calendar components, never on UTC: `new Date(y,\n * m, d)` and `getFullYear()/getMonth()/getDate()`. Going through `toISOString()`\n * would shift the day for every viewer east of Greenwich, and \"is today a\n * holiday\" is a question about the viewer's calendar.\n *\n * @throws {RangeError} When a string is not `YYYY-MM-DD` or a `Date` is invalid.\n */\nfunction toLocalDate(input: DateInput): Date {\n if (typeof input === \"string\") {\n const match = /^(\\d{4})-(\\d{2})-(\\d{2})$/.exec(input.trim());\n if (match === null) {\n throw new RangeError(`Expected a YYYY-MM-DD date, got ${JSON.stringify(input)}.`);\n }\n return new Date(Number(match[1]), Number(match[2]) - 1, Number(match[3]));\n }\n if (Number.isNaN(input.getTime())) throw new RangeError(\"Received an Invalid Date.\");\n return new Date(input.getFullYear(), input.getMonth(), input.getDate());\n}\n\n/** `YYYY-MM-DD` for any accepted input. */\nfunction isoOf(input: DateInput): string {\n const date = toLocalDate(input);\n return toIso(date.getFullYear(), date.getMonth() + 1, date.getDate());\n}\n\n/**\n * Easter Sunday in the Gregorian calendar.\n *\n * The anonymous Gregorian computus (Meeus/Jones/Butcher): pure integer\n * arithmetic over the year, no tables and no dependency. It is exact for every\n * Gregorian year, which is why the four movable Brazilian holidays are derived\n * from it rather than listed.\n *\n * @param year - Gregorian year.\n * @returns Local midnight of Easter Sunday.\n *\n * @example\n * easterSunday(2026); // 2026-04-05\n */\nexport function easterSunday(year: number): Date {\n const a = year % 19;\n const b = Math.floor(year / 100);\n const c = year % 100;\n const d = Math.floor(b / 4);\n const e = b % 4;\n const f = Math.floor((b + 8) / 25);\n const g = Math.floor((b - f + 1) / 3);\n const h = (19 * a + b - d - g + 15) % 30;\n const i = Math.floor(c / 4);\n const k = c % 4;\n const l = (32 + 2 * e + 2 * i - h - k) % 7;\n const m = Math.floor((a + 11 * h + 22 * l) / 451);\n const month = Math.floor((h + l - 7 * m + 114) / 31);\n const day = ((h + l - 7 * m + 114) % 31) + 1;\n return new Date(year, month - 1, day);\n}\n\n/**\n * Every national non-working day in a year, ordered by date.\n *\n * **What is here:** the nine feriados nacionais in federal law (Lei 662/1949 as\n * amended by Lei 10.607/2002, Lei 6.802/1980 for 12 October, and Lei 14.759/2023\n * for 20 November, which is why that one only appears from 2024), plus the four\n * movable days the national financial system observes.\n *\n * **What is deliberately not here**, and will not be:\n *\n * - **State and municipal holidays.** A data magna varies by state and each of the\n * 5 570 municipalities may declare its own, including up to four religious\n * days. No table can be both complete and current; pass them through\n * `options.extra`.\n * - **Ponto facultativo.** A federal decree that lets public servants off is not a\n * holiday and binds nobody else, so it changes no deadline.\n * - **Pre-2002 history.** The table encodes the law as it stands today. Asking for\n * 1998 returns today's set shifted to 1998, not what was in force then.\n *\n * Carnaval, Sexta-feira da Paixão and Corpus Christi are the interesting case:\n * none of them is a feriado nacional in federal law, yet CMN Resolução 4.880/2020\n * closes the banks on all four days, so a payment cannot settle. They are returned\n * with `kind: \"banking\"` — counted by default, and excluded by passing\n * `kinds: [\"national\"]`.\n *\n * @param year - Gregorian year.\n * @returns The holidays of that year, ascending by date.\n *\n * @example\n * holidaysFor(2026).filter((holiday) => holiday.kind === \"national\").length; // 9\n */\nexport function holidaysFor(year: number): Holiday[] {\n const holidays: Holiday[] = FIXED_HOLIDAYS.filter(\n (entry) => entry.since === undefined || year >= entry.since,\n ).map((entry) => ({\n date: toIso(year, entry.month, entry.day),\n name: entry.name,\n kind: entry.kind,\n movable: false,\n }));\n\n const easter = easterSunday(year);\n for (const entry of MOVABLE_HOLIDAYS) {\n const date = new Date(easter.getTime() + entry.offset * MS_PER_DAY);\n holidays.push({\n date: toIso(date.getFullYear(), date.getMonth() + 1, date.getDate()),\n name: entry.name,\n kind: entry.kind,\n movable: true,\n });\n }\n\n return holidays.sort((left, right) => left.date.localeCompare(right.date));\n}\n\n/** The set of `YYYY-MM-DD` strings that count as off for a given year. */\nfunction offDays(year: number, options: BusinessDayOptions): Set<string> {\n const kinds = options.kinds ?? DEFAULT_KINDS;\n const days = new Set(\n holidaysFor(year)\n .filter((holiday) => kinds.includes(holiday.kind))\n .map((holiday) => holiday.date),\n );\n for (const entry of options.extra ?? []) days.add(isoOf(entry));\n return days;\n}\n\n/**\n * Whether a date is a national holiday.\n *\n * @param date - `YYYY-MM-DD` or a `Date`. Only the local calendar day matters.\n * @param options - See {@link BusinessDayOptions}. `weekend` is ignored here — a\n * Sunday is not a holiday, it is a Sunday.\n * @returns `true` when the day is in the table (or in `extra`).\n * @throws {RangeError} On a malformed string or an Invalid Date.\n *\n * @example\n * isHoliday(\"2026-11-20\"); // true\n * isHoliday(\"2026-02-17\"); // true — Carnaval\n * isHoliday(\"2026-02-17\", { kinds: [\"national\"] }); // false\n */\nexport function isHoliday(date: DateInput, options: BusinessDayOptions = {}): boolean {\n const iso = isoOf(date);\n return offDays(Number(iso.slice(0, 4)), options).has(iso);\n}\n\n/**\n * Whether a date is a working day: not a weekend, not a holiday.\n *\n * @param date - `YYYY-MM-DD` or a `Date`.\n * @param options - See {@link BusinessDayOptions}.\n * @returns `true` when work happens on that day.\n * @throws {RangeError} On a malformed string or an Invalid Date.\n *\n * @example\n * isBusinessDay(\"2026-04-03\"); // false — Sexta-feira da Paixão\n */\nexport function isBusinessDay(date: DateInput, options: BusinessDayOptions = {}): boolean {\n const local = toLocalDate(date);\n const weekend = options.weekend ?? DEFAULT_WEEKEND;\n if (weekend.includes(local.getDay())) return false;\n return !isHoliday(local, options);\n}\n\n/**\n * The first working day strictly after a date.\n *\n * Strictly after: calling it on a Wednesday returns Thursday, never the same\n * Wednesday. That is what a \"prazo de D+1\" means, and it makes the function safe\n * to call in a loop.\n *\n * @param date - `YYYY-MM-DD` or a `Date`.\n * @param options - See {@link BusinessDayOptions}.\n * @returns Local midnight of the next working day.\n * @throws {RangeError} On a malformed input, or when `options` marked so many days\n * off that no working day exists within {@link MAX_WALK_DAYS}.\n *\n * @example\n * nextBusinessDay(\"2026-12-24\"); // 2026-12-28 — the 25th is Natal, then a weekend\n */\nexport function nextBusinessDay(date: DateInput, options: BusinessDayOptions = {}): Date {\n const cursor = toLocalDate(date);\n for (let step = 0; step < MAX_WALK_DAYS; step += 1) {\n cursor.setDate(cursor.getDate() + 1);\n if (isBusinessDay(cursor, options)) return cursor;\n }\n throw new RangeError(\n `No business day within ${MAX_WALK_DAYS} days of ${isoOf(date)} — check \\`weekend\\` and \\`extra\\`.`,\n );\n}\n\n/**\n * Move a date by a number of working days.\n *\n * `n` days forward means `n` calls to {@link nextBusinessDay}; a negative `n`\n * walks backwards the same way. `n === 0` returns the day unchanged **even when it\n * is not a working day** — snapping silently would hide the case a caller most\n * needs to see.\n *\n * @param date - `YYYY-MM-DD` or a `Date`.\n * @param days - Working days to add. May be negative.\n * @param options - See {@link BusinessDayOptions}.\n * @returns Local midnight of the resulting day.\n * @throws {RangeError} On a malformed input, or on a calendar with no working days.\n *\n * @example\n * addBusinessDays(\"2026-04-01\", 2); // 2026-04-06 — skips Good Friday and the weekend\n */\nexport function addBusinessDays(\n date: DateInput,\n days: number,\n options: BusinessDayOptions = {},\n): Date {\n const cursor = toLocalDate(date);\n const direction = days < 0 ? -1 : 1;\n for (let moved = 0; moved < Math.abs(days); moved += 1) {\n let landed = false;\n for (let step = 0; step < MAX_WALK_DAYS && !landed; step += 1) {\n cursor.setDate(cursor.getDate() + direction);\n landed = isBusinessDay(cursor, options);\n }\n if (!landed) {\n throw new RangeError(\n `No business day within ${MAX_WALK_DAYS} days while walking from ${isoOf(date)} — ` +\n \"check `weekend` and `extra`.\",\n );\n }\n }\n return cursor;\n}\n"],"mappings":"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"}