tempest-react-sdk 0.35.0 → 0.37.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.
- package/README.md +72 -70
- package/dist/audio/audio-output.cjs +2 -0
- package/dist/audio/audio-output.cjs.map +1 -0
- package/dist/audio/audio-output.js +17 -0
- package/dist/audio/audio-output.js.map +1 -0
- package/dist/audio/audio-player.cjs +1 -1
- package/dist/audio/audio-player.cjs.map +1 -1
- package/dist/audio/audio-player.js +21 -20
- package/dist/audio/audio-player.js.map +1 -1
- package/dist/audio/audio-recorder.cjs +2 -0
- package/dist/audio/audio-recorder.cjs.map +1 -0
- package/dist/audio/audio-recorder.js +30 -0
- package/dist/audio/audio-recorder.js.map +1 -0
- package/dist/audio/duration.cjs +2 -0
- package/dist/audio/duration.cjs.map +1 -0
- package/dist/audio/duration.js +10 -0
- package/dist/audio/duration.js.map +1 -0
- package/dist/audio/level-meter.cjs +2 -0
- package/dist/audio/level-meter.cjs.map +1 -0
- package/dist/audio/level-meter.js +34 -0
- package/dist/audio/level-meter.js.map +1 -0
- package/dist/audio/media-access.cjs +2 -0
- package/dist/audio/media-access.cjs.map +1 -0
- package/dist/audio/media-access.js +51 -0
- package/dist/audio/media-access.js.map +1 -0
- package/dist/audio/use-audio-recorder.cjs +2 -0
- package/dist/audio/use-audio-recorder.cjs.map +1 -0
- package/dist/audio/use-audio-recorder.js +94 -0
- package/dist/audio/use-audio-recorder.js.map +1 -0
- package/dist/audio/use-audio.cjs.map +1 -1
- package/dist/audio/use-audio.js.map +1 -1
- package/dist/audio/use-microphone.cjs +2 -0
- package/dist/audio/use-microphone.cjs.map +1 -0
- package/dist/audio/use-microphone.js +54 -0
- package/dist/audio/use-microphone.js.map +1 -0
- package/dist/audio/wav.cjs +2 -0
- package/dist/audio/wav.cjs.map +1 -0
- package/dist/audio/wav.js +49 -0
- package/dist/audio/wav.js.map +1 -0
- package/dist/auth/passkey.cjs +2 -0
- package/dist/auth/passkey.cjs.map +1 -0
- package/dist/auth/passkey.js +171 -0
- package/dist/auth/passkey.js.map +1 -0
- package/dist/auth/use-passkey.cjs +2 -0
- package/dist/auth/use-passkey.cjs.map +1 -0
- package/dist/auth/use-passkey.js +120 -0
- package/dist/auth/use-passkey.js.map +1 -0
- package/dist/br/PixQRCode.cjs +2 -0
- package/dist/br/PixQRCode.cjs.map +1 -0
- package/dist/br/PixQRCode.js +70 -0
- package/dist/br/PixQRCode.js.map +1 -0
- package/dist/br/PixQRCode.module.cjs +2 -0
- package/dist/br/PixQRCode.module.cjs.map +1 -0
- package/dist/br/PixQRCode.module.js +15 -0
- package/dist/br/PixQRCode.module.js.map +1 -0
- package/dist/br/boleto.cjs +2 -0
- package/dist/br/boleto.cjs.map +1 -0
- package/dist/br/boleto.js +225 -0
- package/dist/br/boleto.js.map +1 -0
- package/dist/br/holidays.cjs +2 -0
- package/dist/br/holidays.cjs.map +1 -0
- package/dist/br/holidays.js +148 -0
- package/dist/br/holidays.js.map +1 -0
- package/dist/br/nfe.cjs +2 -0
- package/dist/br/nfe.cjs.map +1 -0
- package/dist/br/nfe.js +104 -0
- package/dist/br/nfe.js.map +1 -0
- package/dist/br/pix.cjs +2 -0
- package/dist/br/pix.cjs.map +1 -0
- package/dist/br/pix.js +148 -0
- package/dist/br/pix.js.map +1 -0
- package/dist/br.cjs +1 -1
- package/dist/br.cjs.map +1 -1
- package/dist/br.d.ts +878 -0
- package/dist/br.js +7 -2
- package/dist/br.js.map +1 -1
- package/dist/capture/barcode.cjs +2 -0
- package/dist/capture/barcode.cjs.map +1 -0
- package/dist/capture/barcode.js +59 -0
- package/dist/capture/barcode.js.map +1 -0
- package/dist/capture/media-recorder.cjs +2 -0
- package/dist/capture/media-recorder.cjs.map +1 -0
- package/dist/capture/media-recorder.js +64 -0
- package/dist/capture/media-recorder.js.map +1 -0
- package/dist/capture/use-barcode-scanner.cjs +2 -0
- package/dist/capture/use-barcode-scanner.cjs.map +1 -0
- package/dist/capture/use-barcode-scanner.js +86 -0
- package/dist/capture/use-barcode-scanner.js.map +1 -0
- package/dist/capture/use-screen-capture.cjs +2 -0
- package/dist/capture/use-screen-capture.cjs.map +1 -0
- package/dist/capture/use-screen-capture.js +79 -0
- package/dist/capture/use-screen-capture.js.map +1 -0
- package/dist/capture/use-speech-recognition.cjs +2 -0
- package/dist/capture/use-speech-recognition.cjs.map +1 -0
- package/dist/capture/use-speech-recognition.js +118 -0
- package/dist/capture/use-speech-recognition.js.map +1 -0
- package/dist/capture/use-torch.cjs +2 -0
- package/dist/capture/use-torch.cjs.map +1 -0
- package/dist/capture/use-torch.js +33 -0
- package/dist/capture/use-torch.js.map +1 -0
- package/dist/capture/use-video-recorder.cjs +2 -0
- package/dist/capture/use-video-recorder.cjs.map +1 -0
- package/dist/capture/use-video-recorder.js +90 -0
- package/dist/capture/use-video-recorder.js.map +1 -0
- package/dist/capture/video-recorder.cjs +2 -0
- package/dist/capture/video-recorder.cjs.map +1 -0
- package/dist/capture/video-recorder.js +31 -0
- package/dist/capture/video-recorder.js.map +1 -0
- package/dist/components/AIChat/AIChat.cjs +1 -1
- package/dist/components/AIChat/AIChat.cjs.map +1 -1
- package/dist/components/AIChat/AIChat.js +93 -97
- package/dist/components/AIChat/AIChat.js.map +1 -1
- package/dist/components/AIChat/AIChatComposer.cjs +1 -1
- package/dist/components/AIChat/AIChatComposer.cjs.map +1 -1
- package/dist/components/AIChat/AIChatComposer.js +2 -1
- package/dist/components/AIChat/AIChatComposer.js.map +1 -1
- package/dist/components/AIChat/AIChatTurn.cjs +2 -2
- package/dist/components/AIChat/AIChatTurn.js +6 -6
- package/dist/components/AIChat/AIChatTurn.js.map +1 -1
- package/dist/components/Alert/Alert.module.cjs.map +1 -1
- package/dist/components/Alert/Alert.module.js.map +1 -1
- package/dist/components/AudioPlayer/AudioPlayer.cjs +2 -0
- package/dist/components/AudioPlayer/AudioPlayer.cjs.map +1 -0
- package/dist/components/AudioPlayer/AudioPlayer.js +123 -0
- package/dist/components/AudioPlayer/AudioPlayer.js.map +1 -0
- package/dist/components/AudioPlayer/AudioPlayer.module.cjs +2 -0
- package/dist/components/AudioPlayer/AudioPlayer.module.cjs.map +1 -0
- package/dist/components/AudioPlayer/AudioPlayer.module.js +12 -0
- package/dist/components/AudioPlayer/AudioPlayer.module.js.map +1 -0
- package/dist/components/AudioRecorder/AudioRecorder.cjs +2 -0
- package/dist/components/AudioRecorder/AudioRecorder.cjs.map +1 -0
- package/dist/components/AudioRecorder/AudioRecorder.js +179 -0
- package/dist/components/AudioRecorder/AudioRecorder.js.map +1 -0
- package/dist/components/AudioRecorder/AudioRecorder.module.cjs +2 -0
- package/dist/components/AudioRecorder/AudioRecorder.module.cjs.map +1 -0
- package/dist/components/AudioRecorder/AudioRecorder.module.js +19 -0
- package/dist/components/AudioRecorder/AudioRecorder.module.js.map +1 -0
- package/dist/components/Badge/Badge.module.cjs.map +1 -1
- package/dist/components/Badge/Badge.module.js.map +1 -1
- package/dist/components/BarcodeScanner/BarcodeScanner.cjs +2 -0
- package/dist/components/BarcodeScanner/BarcodeScanner.cjs.map +1 -0
- package/dist/components/BarcodeScanner/BarcodeScanner.js +123 -0
- package/dist/components/BarcodeScanner/BarcodeScanner.js.map +1 -0
- package/dist/components/BarcodeScanner/BarcodeScanner.module.cjs +2 -0
- package/dist/components/BarcodeScanner/BarcodeScanner.module.cjs.map +1 -0
- package/dist/components/BarcodeScanner/BarcodeScanner.module.js +22 -0
- package/dist/components/BarcodeScanner/BarcodeScanner.module.js.map +1 -0
- package/dist/components/BottomNavigation/BottomNavigation.module.cjs.map +1 -1
- package/dist/components/BottomNavigation/BottomNavigation.module.js.map +1 -1
- package/dist/components/Button/Button.module.cjs.map +1 -1
- package/dist/components/Button/Button.module.js.map +1 -1
- package/dist/components/Combobox/Combobox.module.cjs.map +1 -1
- package/dist/components/Combobox/Combobox.module.js.map +1 -1
- package/dist/components/DataTable/DataTable.cjs +1 -1
- package/dist/components/DataTable/DataTable.cjs.map +1 -1
- package/dist/components/DataTable/DataTable.js +203 -66
- package/dist/components/DataTable/DataTable.js.map +1 -1
- package/dist/components/DataTable/DataTable.module.cjs +1 -1
- package/dist/components/DataTable/DataTable.module.cjs.map +1 -1
- package/dist/components/DataTable/DataTable.module.js +9 -3
- package/dist/components/DataTable/DataTable.module.js.map +1 -1
- package/dist/components/DataTable/EditableCell.cjs +2 -0
- package/dist/components/DataTable/EditableCell.cjs.map +1 -0
- package/dist/components/DataTable/EditableCell.js +77 -0
- package/dist/components/DataTable/EditableCell.js.map +1 -0
- package/dist/components/DataTable/edit-labels.cjs +2 -0
- package/dist/components/DataTable/edit-labels.cjs.map +1 -0
- package/dist/components/DataTable/edit-labels.js +11 -0
- package/dist/components/DataTable/edit-labels.js.map +1 -0
- package/dist/components/DateRangePicker/DateRangePicker.module.cjs.map +1 -1
- package/dist/components/DateRangePicker/DateRangePicker.module.js.map +1 -1
- package/dist/components/MultiSelect/MultiSelect.module.cjs.map +1 -1
- package/dist/components/MultiSelect/MultiSelect.module.js.map +1 -1
- package/dist/components/NavigationRail/NavigationRail.module.cjs.map +1 -1
- package/dist/components/NavigationRail/NavigationRail.module.js.map +1 -1
- package/dist/components/SyncStatusBadge/SyncStatusBadge.cjs +1 -1
- package/dist/components/SyncStatusBadge/SyncStatusBadge.cjs.map +1 -1
- package/dist/components/SyncStatusBadge/SyncStatusBadge.js +33 -32
- package/dist/components/SyncStatusBadge/SyncStatusBadge.js.map +1 -1
- package/dist/components/Toast/ToastProvider.cjs +1 -1
- package/dist/components/Toast/ToastProvider.cjs.map +1 -1
- package/dist/components/Toast/ToastProvider.js +1 -2
- package/dist/components/Toast/ToastProvider.js.map +1 -1
- package/dist/hooks/use-announce.cjs +2 -0
- package/dist/hooks/use-announce.cjs.map +1 -0
- package/dist/hooks/use-announce.js +50 -0
- package/dist/hooks/use-announce.js.map +1 -0
- package/dist/hooks/use-media-devices.cjs +2 -0
- package/dist/hooks/use-media-devices.cjs.map +1 -0
- package/dist/hooks/use-media-devices.js +46 -0
- package/dist/hooks/use-media-devices.js.map +1 -0
- package/dist/hooks/use-media-permission.cjs +2 -0
- package/dist/hooks/use-media-permission.cjs.map +1 -0
- package/dist/hooks/use-media-permission.js +33 -0
- package/dist/hooks/use-media-permission.js.map +1 -0
- package/dist/http/resumable-upload.cjs +2 -0
- package/dist/http/resumable-upload.cjs.map +1 -0
- package/dist/http/resumable-upload.js +249 -0
- package/dist/http/resumable-upload.js.map +1 -0
- package/dist/styles.css +1 -1
- package/dist/tempest-react-sdk.cjs +1 -1
- package/dist/tempest-react-sdk.d.ts +2485 -29
- package/dist/tempest-react-sdk.js +268 -244
- package/dist/vision/core/graph.cjs +2 -0
- package/dist/vision/core/graph.cjs.map +1 -0
- package/dist/vision/core/graph.js +17 -0
- package/dist/vision/core/graph.js.map +1 -0
- package/dist/vision/core/session.cjs +1 -1
- package/dist/vision/core/session.cjs.map +1 -1
- package/dist/vision/core/session.js +19 -9
- package/dist/vision/core/session.js.map +1 -1
- package/dist/vision/index.cjs +1 -1
- package/dist/vision/index.cjs.map +1 -1
- package/dist/vision/index.js +14 -13
- package/dist/vision/index.js.map +1 -1
- package/dist/vision/tasks/classifier.cjs +1 -1
- package/dist/vision/tasks/classifier.cjs.map +1 -1
- package/dist/vision/tasks/classifier.js +33 -25
- package/dist/vision/tasks/classifier.js.map +1 -1
- package/dist/vision/tasks/detector.cjs +1 -1
- package/dist/vision/tasks/detector.cjs.map +1 -1
- package/dist/vision/tasks/detector.js +28 -20
- package/dist/vision/tasks/detector.js.map +1 -1
- package/dist/vision/tasks/segmenter.cjs +1 -1
- package/dist/vision/tasks/segmenter.cjs.map +1 -1
- package/dist/vision/tasks/segmenter.js +23 -15
- package/dist/vision/tasks/segmenter.js.map +1 -1
- package/dist/vision/use-camera-stream.cjs +1 -1
- package/dist/vision/use-camera-stream.cjs.map +1 -1
- package/dist/vision/use-camera-stream.js +40 -57
- package/dist/vision/use-camera-stream.js.map +1 -1
- package/dist/vision.cjs +1 -1
- package/dist/vision.d.ts +149 -8
- package/dist/vision.js +22 -21
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-passkey.js","names":[],"sources":["../../src/auth/use-passkey.ts"],"sourcesContent":["import { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\n\nimport { useStableCallback } from \"../hooks/use-stable-callback\";\nimport {\n classifyPasskeyError,\n createPasskeyClient,\n type PasskeyAuthenticationJSON,\n type PasskeyClient,\n type PasskeyCreationOptionsJSON,\n type PasskeyError,\n type PasskeyRegistrationJSON,\n type PasskeyRequestOptionsJSON,\n} from \"./passkey\";\n\n/**\n * Where a passkey ceremony is.\n *\n * `\"prompting\"` and `\"verifying\"` are split because they need different copy:\n * while prompting, the browser sheet is up and the user must touch a sensor;\n * while verifying, your backend is checking the signature and the user should\n * just wait.\n */\nexport type PasskeyStatus = \"idle\" | \"prompting\" | \"verifying\" | \"success\" | \"error\";\n\n/** Capability probes shared by both passkey hooks. */\nexport interface PasskeyCapabilities {\n /** WebAuthn exists in this browser. Known synchronously. */\n supported: boolean;\n /**\n * This device has a built-in authenticator. `null` until the async probe\n * settles — render nothing passkey-related while it is `null`.\n */\n platformAvailable: boolean | null;\n /** Autofill-driven sign-in is available. `null` until the probe settles. */\n conditionalAvailable: boolean | null;\n}\n\nlet sharedClient: PasskeyClient | undefined;\n\n/**\n * Lazily built default client, shared by every hook that was not given one.\n *\n * Lazy rather than a module-level constant so that importing the hooks never runs\n * a call the bundler cannot prove side-effect-free — that alone would pin the\n * module into every consumer's bundle.\n */\nfunction defaultClient(): PasskeyClient {\n sharedClient ??= createPasskeyClient();\n return sharedClient;\n}\n\n/**\n * Probe what this device can do, once per mount.\n *\n * @param client - Client whose probes to call.\n * @returns The three capability answers, two of them async.\n */\nexport function usePasskeyCapabilities(client?: PasskeyClient): PasskeyCapabilities {\n const resolved = useMemo(() => client ?? defaultClient(), [client]);\n const [supported] = useState<boolean>(() => resolved.isSupported());\n const [platformAvailable, setPlatformAvailable] = useState<boolean | null>(null);\n const [conditionalAvailable, setConditionalAvailable] = useState<boolean | null>(null);\n\n useEffect(() => {\n let cancelled = false;\n void resolved.isPlatformAuthenticatorAvailable().then((value) => {\n if (!cancelled) setPlatformAvailable(value);\n });\n void resolved.isConditionalMediationAvailable().then((value) => {\n if (!cancelled) setConditionalAvailable(value);\n });\n return () => {\n cancelled = true;\n };\n }, [resolved]);\n\n return { supported, platformAvailable, conditionalAvailable };\n}\n\n/** Options for {@link usePasskeyRegistration}. */\nexport interface UsePasskeyRegistrationOptions<TResult> {\n /** Fetch server options — your `POST /webauthn/register/begin`. */\n getOptions: () => Promise<PasskeyCreationOptionsJSON>;\n /** Send the credential to be verified — your `POST /webauthn/register/finish`. */\n verify: (credential: PasskeyRegistrationJSON) => Promise<TResult>;\n /** Client to use. Defaults to a shared `createPasskeyClient()`. */\n client?: PasskeyClient;\n /** Called with whatever `verify` resolved to. */\n onSuccess?: (result: TResult) => void;\n /** Called with the classified failure. */\n onError?: (error: PasskeyError) => void;\n}\n\n/** Value returned by {@link usePasskeyRegistration}. */\nexport interface UsePasskeyRegistrationResult<TResult> extends PasskeyCapabilities {\n /** Run the ceremony. Resolves `null` on failure — read `error` for the reason. */\n register: () => Promise<TResult | null>;\n /** Current phase. */\n status: PasskeyStatus;\n /** Last failure, cleared when a new attempt starts. */\n error: PasskeyError | null;\n /** Whatever `verify` resolved to, on success. */\n data: TResult | null;\n /** Close the browser sheet from your own UI. */\n cancel: () => void;\n /** Back to `\"idle\"`, clearing `error` and `data`. */\n reset: () => void;\n}\n\n/**\n * Register a passkey: fetch options, run `navigator.credentials.create`, hand the\n * credential to your backend.\n *\n * `register()` **resolves** rather than rejects on failure, because every failure\n * here is already state the UI has to render (`error.kind`, `status`). Forcing a\n * `try/catch` around a button handler that also has to set state would only\n * duplicate what the hook holds.\n *\n * @param options - Transport callbacks plus optional client and listeners.\n * @returns Ceremony state, the `register` action, and the capability probes.\n *\n * @example\n * const passkey = usePasskeyRegistration({\n * getOptions: () => api.post(\"/webauthn/register/begin\"),\n * verify: (credential) => api.post(\"/webauthn/register/finish\", { body: credential }),\n * });\n *\n * if (passkey.platformAvailable === false) return null;\n * return (\n * <button onClick={() => void passkey.register()} disabled={passkey.status === \"prompting\"}>\n * Criar passkey\n * </button>\n * );\n */\nexport function usePasskeyRegistration<TResult = unknown>(\n options: UsePasskeyRegistrationOptions<TResult>,\n): UsePasskeyRegistrationResult<TResult> {\n const client = useMemo(() => options.client ?? defaultClient(), [options.client]);\n const capabilities = usePasskeyCapabilities(client);\n const [status, setStatus] = useState<PasskeyStatus>(\"idle\");\n const [error, setError] = useState<PasskeyError | null>(null);\n const [data, setData] = useState<TResult | null>(null);\n const controller = useRef<AbortController | null>(null);\n\n const getOptions = useStableCallback(options.getOptions);\n const verify = useStableCallback(options.verify);\n const onSuccess = useStableCallback((result: TResult) => options.onSuccess?.(result));\n const onError = useStableCallback((failure: PasskeyError) => options.onError?.(failure));\n\n const register = useCallback(async (): Promise<TResult | null> => {\n setStatus(\"prompting\");\n setError(null);\n const abort = new AbortController();\n controller.current = abort;\n try {\n const serverOptions = await getOptions();\n const credential = await client.register(serverOptions, { signal: abort.signal });\n setStatus(\"verifying\");\n const result = await verify(credential);\n setData(result);\n setStatus(\"success\");\n onSuccess(result);\n return result;\n } catch (thrown) {\n const failure = classifyPasskeyError(thrown, \"register\");\n setError(failure);\n setStatus(\"error\");\n onError(failure);\n return null;\n } finally {\n controller.current = null;\n }\n }, [client, getOptions, verify, onSuccess, onError]);\n\n const cancel = useCallback((): void => {\n controller.current?.abort();\n }, []);\n\n const reset = useCallback((): void => {\n setStatus(\"idle\");\n setError(null);\n setData(null);\n }, []);\n\n return { ...capabilities, register, status, error, data, cancel, reset };\n}\n\n/** Options for {@link usePasskeySignIn}. */\nexport interface UsePasskeySignInOptions<TResult> {\n /** Fetch server options — your `POST /webauthn/signin/begin`. */\n getOptions: () => Promise<PasskeyRequestOptionsJSON>;\n /** Send the assertion to be verified — your `POST /webauthn/signin/finish`. */\n verify: (assertion: PasskeyAuthenticationJSON) => Promise<TResult>;\n /** Client to use. Defaults to a shared `createPasskeyClient()`. */\n client?: PasskeyClient;\n /**\n * Arm the autofill flow on mount (`mediation: \"conditional\"`).\n *\n * The request stays pending, invisibly, until the user picks a passkey from\n * the browser's autofill list — so the field it should appear on needs\n * `autocomplete=\"username webauthn\"`. Only one conditional request may be live\n * per page, and it is aborted on unmount.\n */\n conditional?: boolean;\n /** Called with whatever `verify` resolved to. */\n onSuccess?: (result: TResult) => void;\n /** Called with the classified failure. */\n onError?: (error: PasskeyError) => void;\n}\n\n/** Value returned by {@link usePasskeySignIn}. */\nexport interface UsePasskeySignInResult<TResult> extends PasskeyCapabilities {\n /** Run the modal ceremony. Resolves `null` on failure. */\n signIn: () => Promise<TResult | null>;\n /** Current phase. */\n status: PasskeyStatus;\n /** Last failure, cleared when a new attempt starts. */\n error: PasskeyError | null;\n /** Whatever `verify` resolved to, on success. */\n data: TResult | null;\n /** True while an armed conditional (autofill) request is waiting. */\n conditionalPending: boolean;\n /** Close the browser sheet from your own UI. */\n cancel: () => void;\n /** Back to `\"idle\"`, clearing `error` and `data`. */\n reset: () => void;\n}\n\n/**\n * Sign in with a passkey, with or without the autofill flow.\n *\n * Two ways in, and a good login page wires both. `signIn()` is the explicit\n * button. `conditional: true` arms the pleasant one: the browser lists the user's\n * passkeys inside the username field itself, so signing in is one tap and no\n * password was ever typed. The field must carry\n * `autocomplete=\"username webauthn\"` or the list never appears — the hook cannot\n * do that part for you.\n *\n * A conditional request that is aborted (unmount, or the user typing a password\n * instead) is **not** surfaced as an error: nothing failed, the user chose\n * another door.\n *\n * @param options - Transport callbacks, `conditional`, optional client and listeners.\n * @returns Ceremony state, the `signIn` action, and the capability probes.\n *\n * @example\n * const passkey = usePasskeySignIn({\n * conditional: true,\n * getOptions: () => api.post(\"/webauthn/signin/begin\"),\n * verify: (assertion) => api.post(\"/webauthn/signin/finish\", { body: assertion }),\n * onSuccess: (session) => auth.setToken(session.access_token),\n * });\n *\n * <input name=\"email\" autoComplete=\"username webauthn\" />\n * <button onClick={() => void passkey.signIn()}>Entrar com passkey</button>\n */\nexport function usePasskeySignIn<TResult = unknown>(\n options: UsePasskeySignInOptions<TResult>,\n): UsePasskeySignInResult<TResult> {\n const client = useMemo(() => options.client ?? defaultClient(), [options.client]);\n const capabilities = usePasskeyCapabilities(client);\n const [status, setStatus] = useState<PasskeyStatus>(\"idle\");\n const [error, setError] = useState<PasskeyError | null>(null);\n const [data, setData] = useState<TResult | null>(null);\n const [conditionalPending, setConditionalPending] = useState(false);\n const controller = useRef<AbortController | null>(null);\n const conditional = options.conditional ?? false;\n\n const getOptions = useStableCallback(options.getOptions);\n const verify = useStableCallback(options.verify);\n const onSuccess = useStableCallback((result: TResult) => options.onSuccess?.(result));\n const onError = useStableCallback((failure: PasskeyError) => options.onError?.(failure));\n\n const run = useCallback(\n async (\n mediation: \"optional\" | \"conditional\",\n abort: AbortController = new AbortController(),\n ): Promise<TResult | null> => {\n controller.current = abort;\n if (mediation === \"optional\") {\n setStatus(\"prompting\");\n setError(null);\n }\n try {\n const serverOptions = await getOptions();\n const assertion = await client.authenticate(serverOptions, {\n mediation,\n signal: abort.signal,\n });\n setStatus(\"verifying\");\n const result = await verify(assertion);\n setData(result);\n setStatus(\"success\");\n onSuccess(result);\n return result;\n } catch (thrown) {\n const failure = classifyPasskeyError(thrown, \"authenticate\");\n if (failure.kind === \"aborted\" && mediation === \"conditional\") return null;\n setError(failure);\n setStatus(\"error\");\n onError(failure);\n return null;\n } finally {\n controller.current = null;\n }\n },\n [client, getOptions, verify, onSuccess, onError],\n );\n\n const signIn = useCallback(() => run(\"optional\"), [run]);\n\n useEffect(() => {\n if (!conditional) return;\n let cancelled = false;\n let abort: AbortController | null = null;\n\n async function arm(): Promise<void> {\n if (!(await client.isConditionalMediationAvailable())) return;\n if (cancelled) return;\n setConditionalPending(true);\n abort = new AbortController();\n await run(\"conditional\", abort);\n if (!cancelled) setConditionalPending(false);\n }\n\n void arm();\n\n return () => {\n cancelled = true;\n abort?.abort();\n };\n }, [conditional, client, run]);\n\n const cancel = useCallback((): void => {\n controller.current?.abort();\n }, []);\n\n const reset = useCallback((): void => {\n setStatus(\"idle\");\n setError(null);\n setData(null);\n }, []);\n\n return {\n ...capabilities,\n signIn,\n status,\n error,\n data,\n conditionalPending,\n cancel,\n reset,\n };\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const e=require("../utils/cn.cjs"),t=require("../components/QRCode/QRCode.cjs"),n=require("../components/CopyButton/CopyButton.cjs"),r=require("./pix.cjs"),i=require("./PixQRCode.module.cjs");let a=require("react"),o=require("react/jsx-runtime");var s={qr:`QR code do Pix`,copy:`Copiar código`,copied:`Copiado`};function c({pix:c,payload:l,size:u=192,level:d=`M`,showCopy:f=!0,amountLabel:p,payeeLabel:m,labels:h,onCopied:g,className:_,...v}){let y=(0,a.useMemo)(()=>{if(l!==void 0&&c!==void 0)throw new r.PixError("Pass either `pix` or `payload` to PixQRCode, not both.");if(l!==void 0)return l.trim();if(c!==void 0)return r.pixPayload(c);throw new r.PixError("PixQRCode needs either `pix` or `payload`.")},[c,l]),b={...s,...h};return(0,o.jsxs)(`div`,{className:e.cn(i.default.pix,_),...v,children:[p!==void 0&&(0,o.jsx)(`span`,{className:i.default.amount,children:p}),m!==void 0&&(0,o.jsx)(`span`,{className:i.default.payee,children:m}),(0,o.jsx)(`div`,{className:i.default.symbol,children:(0,o.jsx)(t.QRCode,{value:y,size:u,level:d,label:b.qr,margin:2})}),f&&(0,o.jsxs)(`div`,{className:i.default.copy,children:[(0,o.jsx)(`code`,{className:i.default.payload,"data-testid":`pix-payload`,children:y}),(0,o.jsxs)(n.CopyButton,{value:y,onCopied:g,children:[(0,o.jsx)(`span`,{className:i.default.copyIdle,children:b.copy}),(0,o.jsx)(`span`,{className:i.default.copyDone,children:b.copied})]})]})]})}exports.PixQRCode=c;
|
|
2
|
+
//# sourceMappingURL=PixQRCode.cjs.map
|
|
@@ -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":"AAMA,IAAa,EAAb,cAAiC,KAAM,CACnC,YAAY,EAAiB,CACzB,MAAM,CAAO,EACb,KAAK,KAAO,aAChB,CACJ,EA8FM,EAAmB,KAAK,IAAI,KAAM,EAAG,CAAC,EAStC,EAAoB,KAAK,IAAI,KAAM,EAAG,EAAE,EAExC,EAAa,MAGb,EAAY,IAGZ,EAAY,KAEZ,EAAgB,CAAC,EAAG,CAAC,EACrB,EAAqB,EAGrB,EAA0C,CAC5C,EAAG,cACH,EAAG,aACH,EAAG,yBACH,EAAG,mBACH,EAAG,wBACH,EAAG,2DACH,EAAG,qBACH,EAAG,wBACP,EAGM,EAAgB,EAGtB,SAAS,EAAO,EAAuB,CACnC,OAAO,EAAM,QAAQ,MAAO,EAAE,CAClC,CAiBA,SAAgB,EAAS,EAAuB,CAC5C,GAAI,CAAC,QAAQ,KAAK,CAAK,EACnB,MAAM,IAAI,EAAY,8BAA8B,KAAK,UAAU,CAAK,EAAE,EAAE,EAChF,IAAI,EAAM,EACV,IAAK,IAAI,EAAQ,EAAG,EAAQ,EAAM,OAAQ,GAAS,EAAG,CAClD,IAAM,EAAY,EAAM,OAAS,EAAI,EAC/B,EAAU,OAAO,EAAM,EAAM,EAAI,EAAc,EAAY,EAAc,QAC/E,GAAO,EAAU,EAAI,EAAU,EAAI,CACvC,CACA,IAAM,EAAY,EAAM,GACxB,OAAO,IAAc,EAAI,EAAI,GAAK,CACtC,CAGA,SAAS,EAAS,EAAuB,CACrC,IACI,EAAM,EACV,IAAK,IAAI,EAAQ,EAAG,EAAQ,EAAM,OAAQ,GAAS,EAAG,CAClD,IAAM,EAAY,EAAM,OAAS,EAAI,EACrC,GAAO,OAAO,EAAM,EAAM,GAAK,EAAsB,EAAY,EACrE,CACA,OAAO,CACX,CAkBA,SAAgB,EAAiB,EAAuB,CACpD,GAAI,CAAC,QAAQ,KAAK,CAAK,EACnB,MAAM,IAAI,EAAY,sCAAsC,KAAK,UAAU,CAAK,EAAE,EAAE,EAExF,IAAM,EAAY,EAAS,CAAK,EAAI,GACpC,OAAO,IAAc,GAAK,IAAc,GAAK,IAAc,GAAK,EAAI,GAAK,CAC7E,CAiBA,SAAgB,EAAoB,EAAuB,CACvD,GAAI,CAAC,QAAQ,KAAK,CAAK,EACnB,MAAM,IAAI,EAAY,yCAAyC,KAAK,UAAU,CAAK,EAAE,EAAE,EAE3F,IAAM,EAAY,EAAS,CAAK,EAAI,GACpC,OAAO,IAAc,GAAK,IAAc,EAAI,EAAI,GAAK,CACzD,CAQA,SAAgB,EAAW,EAAkC,CACzD,IAAM,EAAM,EAAO,CAAK,EAIxB,OAHI,EAAI,SAAW,GAAW,QAC1B,EAAI,SAAW,GAAW,cAC1B,EAAI,SAAW,GAAW,EAAI,WAAW,GAAG,EAAI,cAAgB,QAC7D,IACX,CAGA,SAAS,EAAS,EAAoB,EAAoB,CACtD,IAAM,EAAM,IAAI,KAAK,EAAa,EAAO,CAAU,EACnD,OAAO,IAAI,KAAK,EAAI,eAAe,EAAG,EAAI,YAAY,EAAG,EAAI,WAAW,CAAC,CAC7E,CAyBA,SAAgB,EACZ,EACA,EAAyB,CAAC,EACgC,CAC1D,GAAI,IAAU,EAAG,OAAO,KACxB,GAAM,CAAE,QAAQ,OAAQ,YAAY,IAAI,MAAW,EAEnD,GAAI,IAAU,SAAU,MAAO,CAAE,KAAM,EAAS,EAAkB,CAAK,EAAG,MAAO,QAAS,EAC1F,GAAI,IAAU,UAAW,MAAO,CAAE,KAAM,EAAS,EAAmB,CAAK,EAAG,MAAO,SAAU,EAE7F,IAAM,EAAS,EAAS,EAAkB,CAAK,EAC/C,GAAI,EAAQ,EAAW,MAAO,CAAE,KAAM,EAAQ,MAAO,QAAS,EAC9D,IAAM,EAAU,EAAS,EAAmB,CAAK,EAC3C,EAAK,EAAU,QAAQ,EAC7B,OAAO,KAAK,IAAI,EAAQ,QAAQ,EAAI,CAAE,GAAK,KAAK,IAAI,EAAO,QAAQ,EAAI,CAAE,EACnE,CAAE,KAAM,EAAS,MAAO,SAAU,EAClC,CAAE,KAAM,EAAQ,MAAO,QAAS,CAC1C,CAeA,SAAgB,EACZ,EACA,EAAsC,UAChC,CACN,IAAM,EAAO,IAAU,SAAW,EAAmB,EAC/C,EAAS,KAAK,IAAI,EAAK,YAAY,EAAG,EAAK,SAAS,EAAG,EAAK,QAAQ,CAAC,EACrE,EAAQ,KAAK,OAAO,EAAS,GAAQ,CAAU,EACrD,GAAI,EAAQ,GAAa,EAAQ,EAC7B,MAAM,IAAI,EACN,GAAG,EAAK,YAAY,CAAC,CAAC,MAAM,EAAG,EAAE,EAAE,YAAY,EAAM,cAAc,EAAM,uBACtD,EAAU,GAAG,EAAU,kBAC9C,EAEJ,OAAO,CACX,CASA,SAAS,EAAe,EAAiC,CACrD,IAAM,EAAO,EAAW,MAAM,EAAG,CAAC,EAC5B,EAAO,OAAO,EAAK,MAAM,EAAG,CAAC,CAAC,EAC9B,EAAQ,OAAO,EAAK,MAAM,EAAG,CAAC,CAAC,EAC/B,EAAM,OAAO,EAAK,MAAM,EAAG,CAAC,CAAC,EACnC,GAAI,EAAO,MAAQ,EAAO,MAAQ,EAAQ,GAAK,EAAQ,IAAM,EAAM,GAAK,EAAM,GAAI,OAAO,KACzF,IAAM,EAAO,IAAI,KAAK,EAAM,EAAQ,EAAG,CAAG,EAC1C,OAAO,EAAK,SAAS,IAAM,EAAQ,GAAK,EAAK,QAAQ,IAAM,EAAM,EAAO,IAC5E,CAGA,SAAS,EAAW,EAAyB,CACzC,IAAM,EAAa,EAAQ,MAAM,EAAE,EAC7B,EAAS,EAAQ,MAAM,EAAG,CAAC,EAAI,EAAW,MAAM,EAAG,CAAC,EACpD,EAAS,EAAW,MAAM,EAAG,EAAE,EAC/B,EAAS,EAAW,MAAM,GAAI,EAAE,EACtC,OACI,EACA,EAAS,CAAM,EACf,EACA,EAAS,CAAM,EACf,EACA,EAAS,CAAM,EACf,EAAQ,MAAM,EAAG,CAAC,EAClB,EAAQ,MAAM,EAAG,EAAE,CAE3B,CAGA,SAAS,EAAiB,EAAyB,CAC/C,IAAM,EAAM,EAAc,CAAO,IAAM,GAAK,EAAsB,EAC9D,EAAO,GACX,IAAK,IAAI,EAAQ,EAAG,EAAQ,GAAI,GAAS,GAAI,CACzC,IAAM,EAAQ,EAAQ,MAAM,EAAO,EAAQ,EAAE,EAC7C,GAAQ,EAAQ,EAAI,CAAK,CAC7B,CACA,OAAO,CACX,CAGA,SAAS,EAAc,EAA0B,CAC7C,OAAO,EAAQ,KAAO,KAAO,EAAQ,KAAO,IAAM,GAAK,EAC3D,CAGA,SAAS,EAAU,EAAiB,EAAqC,CACrE,IAAM,EAAQ,OAAO,EAAQ,MAAM,EAAG,CAAC,CAAC,EAClC,EAAM,EAAc,EAAO,CAAO,EAClC,EAAQ,EAAQ,MAAM,EAAG,CAAC,EAChC,MAAO,CACH,KAAM,QACN,aAAc,EACd,eAAgB,EAAW,CAAO,EAClC,MAAO,EAAQ,MAAM,EAAG,CAAC,EACzB,QACA,WAAY,IAAU,IAAM,OAAS,KACrC,GAAI,EAAQ,MAAM,EAAG,CAAC,EACtB,gBAAiB,EACjB,WAAY,GAAK,MAAQ,KACzB,gBAAiB,GAAK,OAAS,KAC/B,MAAO,OAAO,EAAQ,MAAM,EAAG,EAAE,CAAC,EAAI,IACtC,WAAY,EAAQ,MAAM,EAAE,CAChC,CACJ,CAGA,SAAS,EAAgB,EAAoC,CACzD,IAAM,EAAW,OAAO,EAAQ,EAAE,EAC5B,EAAqB,OAAO,EAAQ,EAAE,EACtC,EAAgB,IAAa,EAC7B,EAAa,EAAgB,EAAQ,MAAM,EAAE,EAAI,EAAQ,MAAM,EAAE,EACjE,EAAW,EAAQ,MAAM,EAAG,EAAE,EAC9B,EAAU,IAAuB,GAAK,IAAuB,EACnE,MAAO,CACH,KAAM,cACN,aAAc,EACd,eAAgB,EAAiB,CAAO,EACxC,WACA,cAAe,EAAgB,IAAa,KAC5C,qBACA,SAAU,EAAc,CAAO,EAC/B,GAAI,EAAQ,MAAM,EAAG,CAAC,EACtB,MAAO,EAAU,OAAO,CAAQ,EAAI,IAAM,KAC1C,WACA,QAAS,EAAgB,EAAQ,MAAM,GAAI,EAAE,EAAI,EAAQ,MAAM,GAAI,EAAE,EACrE,gBACA,aACA,qBAAsB,EAAe,CAAU,CACnD,CACJ,CAGA,SAAS,EAAgB,EAAuB,CAC5C,GAAI,EAAQ,WAAW,GAAG,EAAG,CACzB,IAAM,EAAO,EAAQ,MAAM,EAAG,CAAC,EAAI,EAAQ,MAAM,CAAC,EAC5C,EAAM,EAAc,CAAO,IAAM,GAAK,EAAoB,CAAI,EAAI,EAAS,CAAI,EACrF,GAAI,OAAO,CAAG,IAAM,EAAQ,GACxB,MAAM,IAAI,EACN,8BAA8B,EAAQ,GAAG,eAAe,EAAI,WAAW,EAAc,CAAO,EAAE,GAClG,EAEJ,MACJ,CACA,IAAM,EAAM,EAAiB,EAAQ,MAAM,EAAG,CAAC,EAAI,EAAQ,MAAM,CAAC,CAAC,EACnE,GAAI,OAAO,CAAG,IAAM,EAAQ,GACxB,MAAM,IAAI,EAAY,0BAA0B,EAAQ,GAAG,eAAe,EAAI,EAAE,CAExF,CAGA,SAAS,EAAyB,EAAuB,CACrD,GAAI,CAAC,OAAO,SAAS,EAAQ,EAAG,EAC5B,MAAM,IAAI,EACN,2FAA2F,EAAQ,GAAG,EAC1G,CAER,CAmBA,SAAgB,EAAkB,EAAe,EAAyB,CAAC,EAAW,CAClF,IAAM,EAAU,EAAO,CAAK,EAC5B,GAAI,EAAQ,SAAW,GACnB,MAAM,IAAI,EACN,gCAAgC,EAAQ,OAAO,sEAEnD,EAQJ,OANI,EAAQ,WAAW,GAAG,GACtB,EAAyB,CAAO,EAChC,EAAgB,CAAO,EAChB,EAAgB,CAAO,IAElC,EAAgB,CAAO,EAChB,EAAU,EAAS,CAAO,EACrC,CAkBA,SAAgB,EAAoB,EAAe,EAAyB,CAAC,EAAW,CACpF,IAAM,EAAO,EAAO,CAAK,EACzB,GAAI,EAAK,SAAW,GAAI,OAAO,EAAkB,EAAa,CAAI,EAAG,CAAO,EAC5E,GAAI,EAAK,SAAW,GAAI,OAAO,EAAkB,EAAmB,CAAI,EAAG,CAAO,EAClF,MAAM,IAAI,EACN,8DAA8D,EAAK,OAAO,0DAE9E,CACJ,CAGA,SAAS,EAAa,EAAsB,CAcxC,MARA,CAJI,CAAC,EAAK,MAAM,EAAG,CAAC,EAAG,EAAK,MAAM,EAAG,EAAE,CAAC,EACpC,CAAC,EAAK,MAAM,GAAI,EAAE,EAAG,EAAK,MAAM,GAAI,EAAE,CAAC,EACvC,CAAC,EAAK,MAAM,GAAI,EAAE,EAAG,EAAK,MAAM,GAAI,EAAE,CAAC,CAE3C,CAAA,CAAO,SAAS,CAAC,EAAM,GAAK,IAAU,CAClC,IAAM,EAAM,EAAS,CAAI,EACzB,GAAI,OAAO,CAAG,IAAM,EAChB,MAAM,IAAI,EACN,SAAS,EAAQ,EAAE,kBAAkB,EAAG,eAAe,EAAI,cAC/D,CAER,CAAC,EAEG,EAAK,MAAM,EAAG,CAAC,EACf,EAAK,MAAM,GAAI,EAAE,EACjB,EAAK,MAAM,GAAI,EAAE,EACjB,EAAK,MAAM,EAAG,CAAC,EACf,EAAK,MAAM,GAAI,EAAE,EACjB,EAAK,MAAM,GAAI,EAAE,CAEzB,CAGA,SAAS,EAAmB,EAAsB,CAC9C,IAAM,EAAS,CAAC,EAAG,GAAI,GAAI,EAAE,CAAC,CAAC,IAAK,IAAW,CAC3C,KAAM,EAAK,MAAM,EAAO,EAAQ,EAAE,EAClC,GAAI,EAAK,MAAM,EAAQ,GAAI,EAAQ,EAAE,CACzC,EAAE,EACI,EAAU,EAAO,IAAK,GAAU,EAAM,IAAI,CAAC,CAAC,KAAK,EAAE,EACzD,GAAI,CAAC,EAAQ,WAAW,GAAG,EACvB,MAAM,IAAI,EACN,2EAA2E,EAAQ,GAAG,EAC1F,EAEJ,EAAyB,CAAO,EAChC,IAAM,EAAM,EAAc,CAAO,IAAM,GAAK,EAAsB,EAUlE,OATA,EAAO,SAAS,EAAO,IAAU,CAC7B,IAAM,EAAW,EAAI,EAAM,IAAI,EAC/B,GAAI,OAAO,CAAQ,IAAM,EAAM,GAC3B,MAAM,IAAI,EACN,SAAS,EAAQ,EAAE,kBAAkB,EAAM,GAAG,eAAe,EAAS,WACvD,EAAc,CAAO,EAAE,GAC1C,CAER,CAAC,EACM,CACX,CASA,SAAgB,EAA6B,EAAuB,CAChE,OAAO,EAAoB,CAAK,CAAC,CAAC,YACtC,CAUA,SAAgB,EAA6B,EAAuB,CAChE,OAAO,EAAkB,CAAK,CAAC,CAAC,cACpC,CAgBA,SAAgB,EAAe,EAAwB,CACnD,GAAI,CACA,IAAM,EAAM,EAAO,CAAK,EAGxB,OAFI,EAAI,SAAW,GAAI,EAAkB,CAAG,EACvC,EAAoB,CAAG,EACrB,EACX,MAAQ,CACJ,MAAO,EACX,CACJ,CAgBA,SAAgB,EAAqB,EAAuB,CACxD,IAAM,EAAO,EAAO,CAAK,EAazB,OAZI,EAAK,SAAW,GACT,CACH,GAAG,EAAK,MAAM,EAAG,CAAC,EAAE,GAAG,EAAK,MAAM,EAAG,EAAE,IACvC,GAAG,EAAK,MAAM,GAAI,EAAE,EAAE,GAAG,EAAK,MAAM,GAAI,EAAE,IAC1C,GAAG,EAAK,MAAM,GAAI,EAAE,EAAE,GAAG,EAAK,MAAM,GAAI,EAAE,IAC1C,EAAK,MAAM,GAAI,EAAE,EACjB,EAAK,MAAM,EAAE,CACjB,CAAC,CAAC,KAAK,GAAG,EAEV,EAAK,SAAW,GACT,CAAC,EAAG,GAAI,GAAI,EAAE,CAAC,CAAC,IAAK,GAAU,EAAK,MAAM,EAAO,EAAQ,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,EAE1E,CACX"}
|
|
@@ -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
|