hibp 0.0.0-dev.9896b89a

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. package/API.md +508 -0
  2. package/CHANGELOG.md +7 -0
  3. package/LICENSE.txt +22 -0
  4. package/MIGRATION.md +227 -0
  5. package/README.md +255 -0
  6. package/dist/browser/hibp.module.js +2 -0
  7. package/dist/browser/hibp.module.js.map +1 -0
  8. package/dist/browser/hibp.umd.js +2 -0
  9. package/dist/browser/hibp.umd.js.map +1 -0
  10. package/dist/cjs/api/haveibeenpwned/fetchFromApi.js +107 -0
  11. package/dist/cjs/api/haveibeenpwned/fetchFromApi.js.map +1 -0
  12. package/dist/cjs/api/haveibeenpwned/index.js +6 -0
  13. package/dist/cjs/api/haveibeenpwned/index.js.map +1 -0
  14. package/dist/cjs/api/haveibeenpwned/responses.js +79 -0
  15. package/dist/cjs/api/haveibeenpwned/responses.js.map +1 -0
  16. package/dist/cjs/api/pwnedpasswords/fetchFromApi.js +44 -0
  17. package/dist/cjs/api/pwnedpasswords/fetchFromApi.js.map +1 -0
  18. package/dist/cjs/api/pwnedpasswords/index.js +5 -0
  19. package/dist/cjs/api/pwnedpasswords/index.js.map +1 -0
  20. package/dist/cjs/api/pwnedpasswords/responses.js +20 -0
  21. package/dist/cjs/api/pwnedpasswords/responses.js.map +1 -0
  22. package/dist/cjs/breach.js +55 -0
  23. package/dist/cjs/breach.js.map +1 -0
  24. package/dist/cjs/breachedAccount.js +101 -0
  25. package/dist/cjs/breachedAccount.js.map +1 -0
  26. package/dist/cjs/breaches.js +55 -0
  27. package/dist/cjs/breaches.js.map +1 -0
  28. package/dist/cjs/dataClasses.js +34 -0
  29. package/dist/cjs/dataClasses.js.map +1 -0
  30. package/dist/cjs/hibp.js +21 -0
  31. package/dist/cjs/hibp.js.map +1 -0
  32. package/dist/cjs/package.json.js +7 -0
  33. package/dist/cjs/package.json.js.map +1 -0
  34. package/dist/cjs/pasteAccount.js +59 -0
  35. package/dist/cjs/pasteAccount.js.map +1 -0
  36. package/dist/cjs/pwnedPassword.js +45 -0
  37. package/dist/cjs/pwnedPassword.js.map +1 -0
  38. package/dist/cjs/pwnedPasswordRange.js +63 -0
  39. package/dist/cjs/pwnedPasswordRange.js.map +1 -0
  40. package/dist/cjs/search.js +97 -0
  41. package/dist/cjs/search.js.map +1 -0
  42. package/dist/esm/api/haveibeenpwned/fetchFromApi.mjs +104 -0
  43. package/dist/esm/api/haveibeenpwned/fetchFromApi.mjs.map +1 -0
  44. package/dist/esm/api/haveibeenpwned/index.mjs +2 -0
  45. package/dist/esm/api/haveibeenpwned/index.mjs.map +1 -0
  46. package/dist/esm/api/haveibeenpwned/responses.mjs +71 -0
  47. package/dist/esm/api/haveibeenpwned/responses.mjs.map +1 -0
  48. package/dist/esm/api/pwnedpasswords/fetchFromApi.mjs +42 -0
  49. package/dist/esm/api/pwnedpasswords/fetchFromApi.mjs.map +1 -0
  50. package/dist/esm/api/pwnedpasswords/index.mjs +2 -0
  51. package/dist/esm/api/pwnedpasswords/index.mjs.map +1 -0
  52. package/dist/esm/api/pwnedpasswords/responses.mjs +17 -0
  53. package/dist/esm/api/pwnedpasswords/responses.mjs.map +1 -0
  54. package/dist/esm/breach.mjs +53 -0
  55. package/dist/esm/breach.mjs.map +1 -0
  56. package/dist/esm/breachedAccount.mjs +99 -0
  57. package/dist/esm/breachedAccount.mjs.map +1 -0
  58. package/dist/esm/breaches.mjs +53 -0
  59. package/dist/esm/breaches.mjs.map +1 -0
  60. package/dist/esm/dataClasses.mjs +32 -0
  61. package/dist/esm/dataClasses.mjs.map +1 -0
  62. package/dist/esm/hibp.mjs +10 -0
  63. package/dist/esm/hibp.mjs.map +1 -0
  64. package/dist/esm/package.json.mjs +4 -0
  65. package/dist/esm/package.json.mjs.map +1 -0
  66. package/dist/esm/pasteAccount.mjs +57 -0
  67. package/dist/esm/pasteAccount.mjs.map +1 -0
  68. package/dist/esm/pwnedPassword.mjs +43 -0
  69. package/dist/esm/pwnedPassword.mjs.map +1 -0
  70. package/dist/esm/pwnedPasswordRange.mjs +61 -0
  71. package/dist/esm/pwnedPasswordRange.mjs.map +1 -0
  72. package/dist/esm/search.mjs +95 -0
  73. package/dist/esm/search.mjs.map +1 -0
  74. package/dist/hibp.d.ts +502 -0
  75. package/example/runkit.js +16 -0
  76. package/package.json +139 -0
package/MIGRATION.md ADDED
@@ -0,0 +1,227 @@
1
+ ## Migration Notes
2
+
3
+ #### 10.0.1 → 11.0.0
4
+
5
+ - `pwnedPasswordRange` now returns an object mapping the matching suffix to a
6
+ count representing the number of occurrences, rather than an array of objects
7
+ each containing a matching suffix and its count. Code dependent on parsing the
8
+ response text will need updated to deal with the new data format:
9
+ ```js
10
+ {
11
+ "003D68EB55068C33ACE09247EE4C639306B": 3,
12
+ "012C192B2F16F82EA0EB9EF18D9D539B0DD": 1,
13
+ ...
14
+ }
15
+ ```
16
+
17
+ #### 9.0.3 → 10.0.0
18
+
19
+ - The production/minified versions of the browser build targets have been
20
+ renamed:
21
+
22
+ - ESM for Browsers (`<script type="module">`)
23
+ - `dist/browser/hibp.esm.min.js` → `dist/browser/hibp.module.js`
24
+ - UMD
25
+ - `dist/browser/hibp.umd.min.js` → `dist/browser/hibp.umd.js`
26
+
27
+ - The development/non-minified versions of the UMD and ESM for browsers build
28
+ targets have been removed. If you were using them, please update your imports
29
+ to use the production/minified versions (see above).
30
+
31
+ - The internal directory structure of the source code is now being preserved in
32
+ the CJS and ESM for bundlers build outputs (`dist/cjs` and `dist/esm`). If you
33
+ were deep importing anything you probably shouldn't have been (:wink:), you
34
+ may need to update your imports.
35
+
36
+ - Support for Node.js version 10.x has been dropped. You must upgrade your
37
+ Node.js environment to at least v12.16.0.
38
+
39
+ #### 8.0.1 → 9.0.0
40
+
41
+ - Output files for all build targets have been consolidated under the `dist`
42
+ directory. This should be transparent if you followed the documentation, but
43
+ the changes are as follows:
44
+
45
+ - CommonJS
46
+ - `lib/hibp.js` → `dist/cjs/hibp.js`
47
+ - ECMAScript Modules
48
+ - `es/hibp.js` → `dist/esm/hibp.js`
49
+ - ECMAScript Modules for Browsers (development)
50
+ - `dist/hibp.mjs` → `dist/browser/hibp.esm.js`
51
+ - ECMAScript Modules for Browsers (production)
52
+ - `dist/hibp.min.mjs` → `dist/browser/hibp.esm.min.js`
53
+ - UMD (development)
54
+ - `dist/hibp.js` → `dist/browser/hibp.umd.js`
55
+ - UMD (production)
56
+ - `dist/hibp.min.js` → `dist/browser/hibp.umd.min.js`
57
+ - TypeScript Declarations
58
+ - `types/hibp.d.ts` → `dist/hibp.d.ts`
59
+
60
+ - Support for Node.js version 8.x has been dropped. You must upgrade your
61
+ Node.js environment to at least v10.
62
+
63
+ #### 7.5.2 → 8.0.0
64
+
65
+ - The `breachedAccount`, `pasteAccount`, and `search` modules now have an
66
+ `apiKey` option, which is required by v3 of the `haveibeenpwned.com` API
67
+ (unless you are proxying your requests through a server that inserts an API
68
+ key on your behalf via the `baseUrl` option). You can purchase an API key from
69
+ Troy at [https://haveibeenpwned.com/API/Key][get-key]. See [Troy's blog
70
+ post][api-key-blog-post] for rationale and a full explanation.
71
+ - The default value of the `truncate` option in the `breachedAccount` and
72
+ `search` modules has been changed from `false` to `true` per Troy's
73
+ recommendation. If you do not specify a value of `false` explicitly, each
74
+ `Breach` result will only contain the breach name (no metadata).
75
+ - The default value of the `includeUnverified` option in the `breachedAccount`
76
+ module has been changed from `false` to `true` per Troy's recommendation.
77
+ Although there are not many unverified breaches in the system, it's possible
78
+ you will get more breaches back than you did previously. You may explicitly
79
+ disable this by specifying a value of `false` for this option.
80
+ - Support for Node.js version 6.x has been dropped. You must upgrade your
81
+ Node.js environment to at least v8.9.0.
82
+
83
+ #### 6.0.0 → 7.0.0
84
+
85
+ - `pwnedPassword` now uses the more secure hash range API rather than submitting
86
+ plain text passwords over the wire. The [new remote
87
+ API][pwnedpasswordsbyrange] no longer makes a distinction between passwords
88
+ that are hashses vs. plain text, so `pwnedPassword` no longer takes an options
89
+ object as the `isAHash` option has been removed.
90
+
91
+ - `pwnedPassword` now resolves with a number representing the number of times
92
+ the given password was exposed in a breach. Code using truthy checks should
93
+ continue to function as before (when it returned a boolean), but explicit
94
+ checks will need updated.
95
+
96
+ - `pwnedPasswordRange` now returns an array of objects containing the matching
97
+ suffix and a count representing the number of occurrences, rather than a plain
98
+ text blob of all the data directly from the remote API response. Code
99
+ dependent on parsing the response text will need updated to deal with the new
100
+ data format:
101
+ ```js
102
+ [
103
+ { suffix: "003D68EB55068C33ACE09247EE4C639306B", count: 3 },
104
+ { suffix: "012C192B2F16F82EA0EB9EF18D9D539B0DD", count: 1 },
105
+ ...
106
+ ]
107
+ ```
108
+
109
+ #### 5.3.0 → 6.0.0
110
+
111
+ - Support for Node.js versions less than 6.x has been dropped. If you are
112
+ leveraging this library in such an environment, you should restrict the
113
+ version in your dependencies to `^5.3.0`.
114
+
115
+ #### 4.4.0 → 5.0.0
116
+
117
+ - The biggest breaking change in `5.0.0` is the removal of the `default` export.
118
+ `hibp` is designed as a collection of modules to be imported explicitly as
119
+ needed and exporting a `default`-named object containing all the modules is
120
+ arguably an anti-pattern. Instead, an anonymous object of all the named
121
+ modules is exported, providing better dead code elimination support in order
122
+ to produce smaller bundles when importing from `hibp`. The quickest upgrade
123
+ path (providing invocation syntax equivalence to prior versions) is to change
124
+ your import statement to import all the modules into a local `hibp` namespace,
125
+ but the recommended upgrade path is to import exactly which modules you need
126
+ and update your calls to remove the preceding `hibp` references.
127
+
128
+ ```javascript
129
+ // 4.x
130
+ import hibp from 'hibp';
131
+ hibp.breachedAccount(/* ... */).then(/* ... */);
132
+
133
+ // 5.x (upgrade option 1, one-liner quick fix)
134
+ import * as hibp from 'hibp';
135
+ hibp.breachedAccount(/* ... */).then(/* ... */);
136
+
137
+ // 5.x (upgrade option 2, more explicit but requires more code changes)
138
+ import { breachedAccount } from 'hibp';
139
+ breachedAccount(/* ... */).then(/* ... */);
140
+ ```
141
+
142
+ - The `browser` entry point field has been removed from `package.json` as
143
+ webpack was using it by default when omitting the `target` option or
144
+ explicitly using `target: 'web'` (see issue #8 for details). No `<script>` tag
145
+ changes should be necessary, but if you were otherwise relying on the
146
+ `browser` field to resolve to the UMD build, you will need to update your
147
+ configuration accordingly. Also worth noting here is the fact that the non-UMD
148
+ builds have been updated to target browsers (see issue #9), so bundling them
149
+ instead of the UMD build when targeting browsers should remain fully
150
+ compatible while producing smaller bundles.
151
+
152
+ - The `index.js` file has been removed entirely. It's sole purpose was to
153
+ provide a separate entry point for the CJS/ESM (non-UMD) builds to include the
154
+ `source-map-support` module to enable source map support in Node for debugging
155
+ purposes. Source maps are still generated at build time and included in the
156
+ package, so debugging is still possible but the responsibility of enabling
157
+ support for source maps is now on the consumer. If you were importing
158
+ `index.js` explicitly rather than relying on the entry point fields in
159
+ `package.json`, you will need to replace that with `hibp.js`.
160
+
161
+ #### 3.0.0 → 4.0.0
162
+
163
+ - Support for Node.js versions less than 4.x has been dropped. It will probably
164
+ still work (at least for the foreseeable future), but I'm not going out of my
165
+ way to make sure. If you are leveraging this library in such an environment,
166
+ you should restrict the version in your dependencies to `^3.0.0`.
167
+
168
+ #### 2.2.0 → 3.0.0
169
+
170
+ - The browser (UMD) build output has moved from the `lib` directory to the
171
+ `dist` directory to separate it from the server-side output. A development
172
+ (non-minified) version is also now included, which was omitted in the past as
173
+ it would have had the same file name in the same directory as the server-side
174
+ output.
175
+
176
+ #### 1.0.8 → 2.0.0
177
+
178
+ - All API methods which previously resolved to `undefined` (upon receiving a
179
+ `404 Not Found` response from the remote endpoint) now resolve to `null`
180
+ instead. This may or may not be a breaking change, depending on how strictly
181
+ you're handling the "no data found" return value. Loose truthy/falsey checks
182
+ like `if (breachData) { ... }` will be fine, but strict equality checks like
183
+ `if (breachData === undefined) { ... }` will break.
184
+
185
+ **_N.B._** _This is a philosophical change based on various sources regarding
186
+ the difference between null and undefined in JavaScript. In the case where a
187
+ query responds with no data, it is an expected absence of value, as that is
188
+ how the remote API is documented to respond when there are no relevant objects
189
+ to return._
190
+
191
+ [Ryan Morr](http://goo.gl/TGTS96):
192
+
193
+ > To distinguish between the two, you may want to think of undefined as
194
+ > representing an unexpected absence of value and null as representing an
195
+ > expected absence of value."
196
+
197
+ [MDN](https://goo.gl/n85RSe):
198
+
199
+ > In APIs, null is often retrieved in place where an object can be expected
200
+ > but no object is relevant.
201
+
202
+ - All API methods that previously took optional, positional parameters like
203
+ `domain` and `truncateResults` now take an options object instead. For
204
+ example:
205
+
206
+ 1.0.8 (old):
207
+
208
+ ```javascript
209
+ hibp.breachedAccount(account, 'adobe.com', true).then(/* ... */);
210
+ ```
211
+
212
+ 2.0.0 (new):
213
+
214
+ ```javascript
215
+ hibp
216
+ .breachedAccount(account, { domain: 'adobe.com', truncate: true })
217
+ .then(/* ... */);
218
+ ```
219
+
220
+ This change was made to make the API more expressive and reduce ambiguity. See
221
+ the API documentation (or JSDoc comments) for details.
222
+
223
+ [pwnedpasswordsbyrange]:
224
+ https://haveibeenpwned.com/API/v2#SearchingPwnedPasswordsByRange
225
+ [api-key-blog-post]:
226
+ https://www.troyhunt.com/authentication-and-the-have-i-been-pwned-api/
227
+ [get-key]: https://haveibeenpwned.com/API/Key
package/README.md ADDED
@@ -0,0 +1,255 @@
1
+ <a href="https://wkovacs64.github.io/hibp">
2
+ <img
3
+ alt="logo"
4
+ title="logo"
5
+ src="https://wkovacs64.github.io/hibp/logo.png"
6
+ align="right"
7
+ width="85"
8
+ />
9
+ </a>
10
+
11
+ # hibp
12
+
13
+ _A Promise-based client for [Troy Hunt][troy]'s [Have I been
14
+ pwned?][haveibeenpwned] service._
15
+
16
+ [![npm Version][npm-image]][npm-url] [![Build Status][ci-image]][ci-url]
17
+ [![Code Coverage][coverage-image]][coverage-url]
18
+ [![All Contributors](https://img.shields.io/badge/all_contributors-7-orange.svg?style=flat-square)](#contributors-)
19
+
20
+ ## Installation
21
+
22
+ In Node.js:
23
+
24
+ ```shell
25
+ npm install hibp
26
+ ```
27
+
28
+ In [Deno][deno] (via [Skypack][skypack]):
29
+
30
+ ```ts
31
+ // Replace x.y.z with the desired hibp version ↓ ↓ ↓
32
+ import * as hibp from 'https://cdn.skypack.dev/hibp@x.y.z?dts';
33
+ ```
34
+
35
+ See the [browser](#using-in-the-browser) section below for information on how to
36
+ use it in the browser.
37
+
38
+ ## Features (🔑 = [requires][api-key-blog-post] an [API key][get-api-key])
39
+
40
+ - Get a single breach event
41
+ - Get all breaches for an account 🔑
42
+ - Get all breach events in the system
43
+ - Get all data classes
44
+ - Get all pastes for an account 🔑
45
+ - [Securely][search-by-range] check a password to see if it has been exposed in
46
+ a data breach
47
+ - Check a SHA-1 prefix to see if it has been exposed in a data breach
48
+ - Search for an account in both breaches and pastes at the same time 🔑
49
+ - All queries return a Promise
50
+ - Available server-side (Node.js) and client-side (browser)
51
+ - Written in TypeScript, so all modules come fully typed
52
+
53
+ ## Usage
54
+
55
+ ##### ECMAScript module syntax:
56
+
57
+ ```javascript
58
+ // import individual modules as needed
59
+ import { dataClasses, search } from 'hibp';
60
+ // or, import all modules into a local namespace
61
+ import * as hibp from 'hibp';
62
+ ```
63
+
64
+ ##### CommonJS module syntax:
65
+
66
+ ```javascript
67
+ // require individual modules as needed
68
+ const { dataClasses, search } = require('hibp');
69
+ // or, require all modules into a local namespace
70
+ const hibp = require('hibp');
71
+ ```
72
+
73
+ The following modules are available:
74
+
75
+ - [breach](API.md#breach)
76
+ - [breachedAccount](API.md#breachedaccount)
77
+ - [breaches](API.md#breaches)
78
+ - [dataClasses](API.md#dataclasses)
79
+ - [pasteAccount](API.md#pasteaccount)
80
+ - [pwnedPassword](API.md#pwnedpassword)
81
+ - [pwnedPasswordRange](API.md#pwnedpasswordrange)
82
+ - [search](API.md#search)
83
+
84
+ Please see the [API reference](API.md) for more detailed usage information and
85
+ examples.
86
+
87
+ #### Quick-Start Example
88
+
89
+ ```javascript
90
+ import { search } from 'hibp';
91
+
92
+ search('someAccountOrEmail', { apiKey: 'my-api-key' })
93
+ .then((data) => {
94
+ if (data.breaches || data.pastes) {
95
+ // Bummer...
96
+ console.log(data);
97
+ } else {
98
+ // Phew! We're clear.
99
+ console.log('Good news — no pwnage found!');
100
+ }
101
+ })
102
+ .catch((err) => {
103
+ // Something went wrong.
104
+ console.log(err.message);
105
+ });
106
+ ```
107
+
108
+ #### Rate Limiting
109
+
110
+ The haveibeenpwned.com API [rate limits][haveibeenpwned-rate-limiting] requests
111
+ to prevent abuse. In the event you get rate limited, the module will throw a
112
+ custom `RateLimitError` which will include a `retryAfterSeconds` property so you
113
+ know when you can try the call again (as a `number`, unless the remote API did
114
+ not provide one, in which case it will be `undefined` - but that _should_ never
115
+ happen).
116
+
117
+ #### Using in the browser
118
+
119
+ **Prerequisite:** This module requires a Promise implementation to exist in the
120
+ global namespace prior to being loaded. Therefore, to facilitate usage in
121
+ [browsers without native Promise support][caniuse-promise], you are responsible
122
+ for providing a polyfill. I recommend [es6-promise][es6-promise].
123
+
124
+ You have several options for using this library in a browser environment:
125
+
126
+ 1. Bundled
127
+
128
+ The most efficient and recommended method is to bundle it with client-side
129
+ code using a module bundler like [webpack][webpack]. If your build process
130
+ honors the `module` field in `package.json`, you can import the ECMAScript
131
+ module as described [above](#usage). Otherwise, the `main` field resolves to
132
+ the CommonJS module version.
133
+
134
+ 1. UMD
135
+
136
+ There is also a Universal Module Definition (UMD) build provided for usage in
137
+ the browser. When using this build, an `hibp` object will be added to the
138
+ browser's `window` object.
139
+
140
+ The recommended way to include the UMD build (when using a `<script>` tag) is
141
+ to use the [unpkg][unpkg] CDN, specifying the exact version you want. If you
142
+ don't specify a version, the `latest` tag will be used, which could be
143
+ dangerous if/when there are breaking changes made to the API. See
144
+ [unpkg][unpkg] for details and advanced version specification, but generally
145
+ you will want to do the following (replacing `x.y.z` with the version you
146
+ want):
147
+
148
+ ```html
149
+ <script src="https://unpkg.com/hibp@x.y.z"></script>
150
+ ```
151
+
152
+ 1. ESM for Browsers
153
+
154
+ Modern browsers now [support][caniuse-esm] importing ECMAScript modules via
155
+ `<script type="module">` tags. Like the UMD option above, this build is also
156
+ available the [unpkg][unpkg] CDN (and the same versioning rules apply), but
157
+ you must specify the full path (including the file extension). For example:
158
+
159
+ ```html
160
+ <script type="module">
161
+ // Replace x.y.z with the desired hibp version ↓ ↓ ↓
162
+ import { dataClasses } from 'https://unpkg.com/hibp@x.y.z/dist/browser/hibp.module.js';
163
+
164
+ const logDataClasses = async () => {
165
+ console.table(await dataClasses());
166
+ };
167
+
168
+ logDataClasses();
169
+ </script>
170
+ ```
171
+
172
+ For more information on ESM in the browser, check out [Using JS modules in
173
+ the browser][js-modules].
174
+
175
+ ## Try It Out
176
+
177
+ [Test hibp in your browser with RunKit.][runkit]
178
+
179
+ ## Projects Using hibp
180
+
181
+ - [pwned][pwned] - a command-line tool for querying the '[Have I been
182
+ pwned?][haveibeenpwned]' service
183
+ - [Password Lense][pwl] - a static web application to reveal character types in
184
+ a password
185
+ - [Hasura Backend Plus](https://nhost.github.io/hasura-backend-plus/) -
186
+ Authentication & Storage for Hasura
187
+ - [Staart API](https://staart.js.org/api/) - a Node.js backend starter for SaaS
188
+ startups
189
+ - [BanManager-WebUI](https://github.com/BanManagement/BanManager-WebUI) - Web
190
+ interface for BanManager
191
+
192
+ Send me a [PR][pulls] or an email and I'll add yours to the list!
193
+
194
+ ## License
195
+
196
+ This module is distributed under the [MIT License][license].
197
+
198
+ [npm-image]: https://img.shields.io/npm/v/hibp.svg?style=flat-square
199
+ [npm-url]: https://www.npmjs.com/package/hibp
200
+ [ci-image]:
201
+ https://img.shields.io/github/actions/workflow/status/wKovacs64/hibp/ci.yml?logo=github&style=flat-square
202
+ [ci-url]: https://github.com/wKovacs64/hibp/actions?query=workflow%3Aci
203
+ [coverage-image]:
204
+ https://img.shields.io/codecov/c/github/wKovacs64/hibp/main.svg?style=flat-square
205
+ [coverage-url]: https://codecov.io/gh/wKovacs64/hibp/branch/main
206
+ [deno]: https://deno.land/
207
+ [skypack]: https://www.skypack.dev/
208
+ [troy]: https://www.troyhunt.com
209
+ [haveibeenpwned]: https://haveibeenpwned.com
210
+ [haveibeenpwned-rate-limiting]: https://haveibeenpwned.com/API/v3#RateLimiting
211
+ [search-by-range]:
212
+ https://haveibeenpwned.com/API/v2#SearchingPwnedPasswordsByRange
213
+ [api-key-blog-post]:
214
+ https://www.troyhunt.com/authentication-and-the-have-i-been-pwned-api/
215
+ [get-api-key]: https://haveibeenpwned.com/API/Key
216
+ [unpkg]: https://unpkg.com
217
+ [caniuse-esm]: https://caniuse.com/#feat=es6-module
218
+ [js-modules]: https://v8.dev/features/modules#browser
219
+ [webpack]: https://webpack.js.org
220
+ [caniuse-promise]: https://caniuse.com/#search=promise
221
+ [es6-promise]: https://github.com/stefanpenner/es6-promise
222
+ [runkit]: https://runkit.com/npm/hibp
223
+ [pwned]: https://github.com/wKovacs64/pwned
224
+ [pulls]: https://github.com/wKovacs64/hibp/pulls
225
+ [pwl]: https://pwl.netlify.com/
226
+ [license]: https://github.com/wKovacs64/hibp/tree/main/LICENSE.txt
227
+
228
+ ## Contributors ✨
229
+
230
+ Thanks goes to these wonderful people
231
+ ([emoji key](https://allcontributors.org/docs/en/emoji-key)):
232
+
233
+ <!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
234
+ <!-- prettier-ignore-start -->
235
+ <!-- markdownlint-disable -->
236
+ <table>
237
+ <tr>
238
+ <td align="center"><a href="https://github.com/wKovacs64"><img src="https://avatars.githubusercontent.com/u/1288694?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Justin Hall</b></sub></a><br /><a href="https://github.com/wKovacs64/hibp/commits?author=wKovacs64" title="Code">💻</a> <a href="https://github.com/wKovacs64/hibp/commits?author=wKovacs64" title="Documentation">📖</a> <a href="#infra-wKovacs64" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a> <a href="#maintenance-wKovacs64" title="Maintenance">🚧</a> <a href="https://github.com/wKovacs64/hibp/pulls?q=is%3Apr+reviewed-by%3AwKovacs64" title="Reviewed Pull Requests">👀</a> <a href="https://github.com/wKovacs64/hibp/commits?author=wKovacs64" title="Tests">⚠️</a></td>
239
+ <td align="center"><a href="https://www.troyhunt.com"><img src="https://avatars.githubusercontent.com/u/273244?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Troy Hunt</b></sub></a><br /><a href="#data-troyhunt" title="Data">🔣</a></td>
240
+ <td align="center"><a href="https://jellekralt.com"><img src="https://avatars.githubusercontent.com/u/214558?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Jelle Kralt</b></sub></a><br /><a href="https://github.com/wKovacs64/hibp/commits?author=jellekralt" title="Code">💻</a></td>
241
+ <td align="center"><a href="https://github.com/timaschew"><img src="https://avatars.githubusercontent.com/u/110870?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Anton W</b></sub></a><br /><a href="https://github.com/wKovacs64/hibp/issues?q=author%3Atimaschew" title="Bug reports">🐛</a></td>
242
+ <td align="center"><a href="https://github.com/danieladams456"><img src="https://avatars.githubusercontent.com/u/3953840?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Daniel Adams</b></sub></a><br /><a href="https://github.com/wKovacs64/hibp/commits?author=danieladams456" title="Code">💻</a></td>
243
+ <td align="center"><a href="https://twitter.com/d0gb3r7"><img src="https://avatars.githubusercontent.com/u/454308?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Markus Dolic</b></sub></a><br /><a href="https://github.com/wKovacs64/hibp/issues?q=author%3Ayelworc" title="Bug reports">🐛</a></td>
244
+ <td align="center"><a href="https://github.com/textbook/about"><img src="https://avatars.githubusercontent.com/u/785939?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Jonathan Sharpe</b></sub></a><br /><a href="https://github.com/wKovacs64/hibp/commits?author=textbook" title="Code">💻</a></td>
245
+ </tr>
246
+ </table>
247
+
248
+ <!-- markdownlint-restore -->
249
+ <!-- prettier-ignore-end -->
250
+
251
+ <!-- ALL-CONTRIBUTORS-LIST:END -->
252
+
253
+ This project follows the
254
+ [all-contributors](https://github.com/all-contributors/all-contributors)
255
+ specification. Contributions of any kind welcome!
@@ -0,0 +1,2 @@
1
+ var t=globalThis.fetch;new Map;const e=400,n="Bad request — the account does not comply with an acceptable format.",r=401,s=403,o="Forbidden - access denied.",i=404,u=(new Map([["retry-after","2"]]),429);class h extends Error{retryAfterSeconds;constructor(t,e,n){super(e,n),this.name=this.constructor.name,this.retryAfterSeconds="string"==typeof t?Number.parseInt(t,10):void 0}}function a(a,{apiKey:c,baseUrl:f="https://haveibeenpwned.com/api/v3",userAgent:l}={}){const p={};c&&(p["HIBP-API-Key"]=c),l&&(p["User-Agent"]=l),l||"undefined"!=typeof navigator||(p["User-Agent"]="hibp 0.0.0-dev.9896b89a");const d={headers:p},g=`${f.replace(/\/$/g,"")}${a}`;return t(g,d).then((t=>{if(t.ok)return t.json();switch(t.status){case e:throw Error(n);case r:return t.json().then((t=>{throw Error(t.message)}));case s:{const e=t.headers.get("cf-ray");if(e)throw Error(function(t){return`Request blocked, contact haveibeenpwned.com if this continues (Ray ID: ${t})`}(e));throw Error(o)}case i:return null;case u:return t.json().then((e=>{const n=t.headers.get("retry-after");throw new h(n,e.message)}));default:throw Error(t.statusText)}}))}function c(t,e={}){return a("/breach/"+encodeURIComponent(t),e)}function f(t,e={includeUnverified:!0,truncate:!0}){const n=`/breachedaccount/${encodeURIComponent(t)}?`,r=[];return e.domain&&r.push("domain="+encodeURIComponent(e.domain)),!1===e.includeUnverified&&r.push("includeUnverified=false"),!1===e.truncate&&r.push("truncateResponse=false"),a(`${n}${r.join("&")}`,{apiKey:e.apiKey,baseUrl:e.baseUrl,userAgent:e.userAgent})}function l(t={}){const e=[];return t.domain&&e.push("domain="+encodeURIComponent(t.domain)),a("/breaches?"+e.join("&"),{baseUrl:t.baseUrl,userAgent:t.userAgent})}function p(t={}){return a("/dataclasses",t)}function d(t,e={}){return a("/pasteaccount/"+encodeURIComponent(t),{apiKey:e.apiKey,baseUrl:e.baseUrl,userAgent:e.userAgent})}const g="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";function A(t,e,n,r){let s,o,i;const u=e||[0],h=(n=n||0)>>>3,a=-1===r?3:0;for(s=0;t.length>s;s+=1)i=s+h,o=i>>>2,o>=u.length&&u.push(0),u[o]|=t[s]<<8*(a+r*(i%4));return{value:u,binLen:8*t.length+n}}function m(t,e,n){switch(e){case"UTF8":case"UTF16BE":case"UTF16LE":break;default:throw Error("encoding must be UTF8, UTF16BE, or UTF16LE")}switch(t){case"HEX":return function(t,e,r){return function(t,e,n,r){let s,o,i,u;if(0!=t.length%2)throw Error("String of HEX type must be in byte increments");const h=e||[0],a=(n=n||0)>>>3,c=-1===r?3:0;for(s=0;t.length>s;s+=2){if(o=parseInt(t.substr(s,2),16),isNaN(o))throw Error("String of HEX type contains invalid characters");for(u=(s>>>1)+a,i=u>>>2;i>=h.length;)h.push(0);h[i]|=o<<8*(c+r*(u%4))}return{value:h,binLen:4*t.length+n}}(t,e,r,n)};case"TEXT":return function(t,r,s){return function(t,e,n,r,s){let o,i,u,h,a,c,f,l,p=0;const d=n||[0],g=(r=r||0)>>>3;if("UTF8"===e)for(f=-1===s?3:0,u=0;t.length>u;u+=1)for(o=t.charCodeAt(u),i=[],128>o?i.push(o):2048>o?(i.push(192|o>>>6),i.push(128|63&o)):55296>o||o>=57344?i.push(224|o>>>12,128|o>>>6&63,128|63&o):(u+=1,o=65536+((1023&o)<<10|1023&t.charCodeAt(u)),i.push(240|o>>>18,128|o>>>12&63,128|o>>>6&63,128|63&o)),h=0;i.length>h;h+=1){for(c=p+g,a=c>>>2;a>=d.length;)d.push(0);d[a]|=i[h]<<8*(f+s*(c%4)),p+=1}else for(f=-1===s?2:0,l="UTF16LE"===e&&1!==s||"UTF16LE"!==e&&1===s,u=0;t.length>u;u+=1){for(o=t.charCodeAt(u),!0===l&&(h=255&o,o=h<<8|o>>>8),c=p+g,a=c>>>2;a>=d.length;)d.push(0);d[a]|=o<<8*(f+s*(c%4)),p+=2}return{value:d,binLen:8*p+r}}(t,e,r,s,n)};case"B64":return function(t,e,r){return function(t,e,n,r){let s,o,i,u,h,a,c,f=0;const l=e||[0],p=(n=n||0)>>>3,d=-1===r?3:0,A=t.indexOf("=");if(-1===t.search(/^[a-zA-Z0-9=+/]+$/))throw Error("Invalid character in base-64 string");if(t=t.replace(/=/g,""),-1!==A&&t.length>A)throw Error("Invalid '=' found in base-64 string");for(o=0;t.length>o;o+=4){for(h=t.substr(o,4),u=0,i=0;h.length>i;i+=1)s=g.indexOf(h.charAt(i)),u|=s<<18-6*i;for(i=0;h.length-1>i;i+=1){for(c=f+p,a=c>>>2;a>=l.length;)l.push(0);l[a]|=(u>>>16-8*i&255)<<8*(d+r*(c%4)),f+=1}}return{value:l,binLen:8*f+n}}(t,e,r,n)};case"BYTES":return function(t,e,r){return function(t,e,n,r){let s,o,i,u;const h=e||[0],a=(n=n||0)>>>3,c=-1===r?3:0;for(o=0;t.length>o;o+=1)s=t.charCodeAt(o),u=o+a,i=u>>>2,i>=h.length&&h.push(0),h[i]|=s<<8*(c+r*(u%4));return{value:h,binLen:8*t.length+n}}(t,e,r,n)};case"ARRAYBUFFER":try{new ArrayBuffer(0)}catch(t){throw Error("ARRAYBUFFER not supported by this environment")}return function(t,e,r){return function(t,e,n,r){return A(new Uint8Array(t),e,n,r)}(t,e,r,n)};case"UINT8ARRAY":try{new Uint8Array(0)}catch(t){throw Error("UINT8ARRAY not supported by this environment")}return function(t,e,r){return A(t,e,r,n)};default:throw Error("format must be HEX, TEXT, B64, BYTES, ARRAYBUFFER, or UINT8ARRAY")}}function U(t,e,n,r){switch(t){case"HEX":return function(t){return function(t,e,n,r){const s="0123456789abcdef";let o,i,u="";const h=e/8,a=-1===n?3:0;for(o=0;h>o;o+=1)i=t[o>>>2]>>>8*(a+n*(o%4)),u+=s.charAt(i>>>4&15)+s.charAt(15&i);return r.outputUpper?u.toUpperCase():u}(t,e,n,r)};case"B64":return function(t){return function(t,e,n,r){let s,o,i,u,h,a="";const c=e/8,f=-1===n?3:0;for(s=0;c>s;s+=3)for(u=c>s+1?t[s+1>>>2]:0,h=c>s+2?t[s+2>>>2]:0,i=(t[s>>>2]>>>8*(f+n*(s%4))&255)<<16|(u>>>8*(f+n*((s+1)%4))&255)<<8|h>>>8*(f+n*((s+2)%4))&255,o=0;4>o;o+=1)a+=8*s+6*o>e?r.b64Pad:g.charAt(i>>>6*(3-o)&63);return a}(t,e,n,r)};case"BYTES":return function(t){return function(t,e,n){let r,s,o="";const i=e/8,u=-1===n?3:0;for(r=0;i>r;r+=1)s=t[r>>>2]>>>8*(u+n*(r%4))&255,o+=String.fromCharCode(s);return o}(t,e,n)};case"ARRAYBUFFER":try{new ArrayBuffer(0)}catch(t){throw Error("ARRAYBUFFER not supported by this environment")}return function(t){return function(t,e,n){let r;const s=e/8,o=new ArrayBuffer(s),i=new Uint8Array(o),u=-1===n?3:0;for(r=0;s>r;r+=1)i[r]=t[r>>>2]>>>8*(u+n*(r%4))&255;return o}(t,e,n)};case"UINT8ARRAY":try{new Uint8Array(0)}catch(t){throw Error("UINT8ARRAY not supported by this environment")}return function(t){return function(t,e,n){let r;const s=e/8,o=-1===n?3:0,i=new Uint8Array(s);for(r=0;s>r;r+=1)i[r]=t[r>>>2]>>>8*(o+n*(r%4))&255;return i}(t,e,n)};default:throw Error("format must be HEX, B64, BYTES, ARRAYBUFFER, or UINT8ARRAY")}}function E(t){const e={outputUpper:!1,b64Pad:"=",outputLen:-1},n=t||{},r="Output length must be a multiple of 8";if(e.outputUpper=n.outputUpper||!1,n.b64Pad&&(e.b64Pad=n.b64Pad),n.outputLen){if(n.outputLen%8!=0)throw Error(r);e.outputLen=n.outputLen}else if(n.shakeLen){if(n.shakeLen%8!=0)throw Error(r);e.outputLen=n.shakeLen}if("boolean"!=typeof e.outputUpper)throw Error("Invalid outputUpper formatting option");if("string"!=typeof e.b64Pad)throw Error("Invalid b64Pad formatting option");return e}function b(t,e){return t<<e|t>>>32-e}function w(t,e,n){return t^e^n}function R(t,e,n){return t&e^t&n^e&n}function y(t,e){const n=(65535&t)+(65535&e);return(65535&(t>>>16)+(e>>>16)+(n>>>16))<<16|65535&n}function v(t,e,n,r,s){const o=(65535&t)+(65535&e)+(65535&n)+(65535&r)+(65535&s);return(65535&(t>>>16)+(e>>>16)+(n>>>16)+(r>>>16)+(s>>>16)+(o>>>16))<<16|65535&o}function T(t){return[1732584193,4023233417,2562383102,271733878,3285377520]}function C(t,e){let n,r,s,o,i,u,h;const a=[];for(n=e[0],r=e[1],s=e[2],o=e[3],i=e[4],h=0;80>h;h+=1)a[h]=16>h?t[h]:b(a[h-3]^a[h-8]^a[h-14]^a[h-16],1),u=20>h?v(b(n,5),(c=r)&s^~c&o,i,1518500249,a[h]):40>h?v(b(n,5),w(r,s,o),i,1859775393,a[h]):60>h?v(b(n,5),R(r,s,o),i,2400959708,a[h]):v(b(n,5),w(r,s,o),i,3395469782,a[h]),i=o,o=s,s=b(r,30),r=n,n=u;var c;return e[0]=y(n,e[0]),e[1]=y(r,e[1]),e[2]=y(s,e[2]),e[3]=y(o,e[3]),e[4]=y(i,e[4]),e}function B(t,e,n,r){let s;const o=15+(e+65>>>9<<4),i=e+n;for(;o>=t.length;)t.push(0);for(t[e>>>5]|=128<<24-e%32,t[o]=4294967295&i,t[o-1]=i/4294967296|0,s=0;t.length>s;s+=16)r=C(t.slice(s,s+16),r);return r}class F extends class{constructor(t,e,n){const r=n||{};if(this.t=e,this.i=r.encoding||"UTF8",this.numRounds=r.numRounds||1,isNaN(this.numRounds)||this.numRounds!==parseInt(this.numRounds,10)||1>this.numRounds)throw Error("numRounds must a integer >= 1");this.o=t,this.h=[],this.u=0,this.l=!1,this.A=0,this.p=!1,this.R=[],this.U=[]}update(t){let e,n=0;const r=this.T>>>5,s=this.F(t,this.h,this.u),o=s.binLen,i=s.value,u=o>>>5;for(e=0;u>e;e+=r)o>=n+this.T&&(this.m=this.g(i.slice(e,e+r),this.m),n+=this.T);return this.A+=n,this.h=i.slice(n>>>5),this.u=o%this.T,this.l=!0,this}getHash(t,e){let n,r,s=this.B;const o=E(e);if(this.v){if(-1===o.outputLen)throw Error("Output length must be specified in options");s=o.outputLen}const i=U(t,s,this.Y,o);if(this.p&&this.H)return i(this.H(o));for(r=this.C(this.h.slice(),this.u,this.A,this.I(this.m),s),n=1;this.numRounds>n;n+=1)this.v&&s%32!=0&&(r[r.length-1]&=16777215>>>24-s%32),r=this.C(r,s,0,this.L(this.o),s);return i(r)}setHMACKey(t,e,n){if(!this.M)throw Error("Variant does not support HMAC");if(this.l)throw Error("Cannot set MAC key after calling update");const r=m(e,(n||{}).encoding||"UTF8",this.Y);this.N(r(t))}N(t){const e=this.T>>>3,n=e/4-1;let r;if(1!==this.numRounds)throw Error("Cannot set numRounds with MAC");if(this.p)throw Error("MAC key already set");for(t.binLen/8>e&&(t.value=this.C(t.value,t.binLen,0,this.L(this.o),this.B));n>=t.value.length;)t.value.push(0);for(r=0;n>=r;r+=1)this.R[r]=909522486^t.value[r],this.U[r]=1549556828^t.value[r];this.m=this.g(this.R,this.m),this.A=this.T,this.p=!0}getHMAC(t,e){const n=E(e);return U(t,this.B,this.Y,n)(this.S())}S(){let t;if(!this.p)throw Error("Cannot call getHMAC without first setting MAC key");const e=this.C(this.h.slice(),this.u,this.A,this.I(this.m),this.B);return t=this.g(this.U,this.L(this.o)),t=this.C(e,this.B,this.T,t,this.B),t}}{constructor(t,e,n){if("SHA-1"!==t)throw Error("Chosen SHA variant is not supported");super(t,e,n);const r=n||{};this.M=!0,this.H=this.S,this.Y=-1,this.F=m(this.t,this.i,this.Y),this.g=C,this.I=function(t){return t.slice()},this.L=T,this.C=B,this.m=[1732584193,4023233417,2562383102,271733878,3285377520],this.T=512,this.B=160,this.v=!1,r.hmacKey&&this.N(function(t,e,n,r){const s="hmacKey must include a value and format";if(!e)throw Error(s);if(void 0===e.value||!e.format)throw Error(s);return m(e.format,e.encoding||"UTF8",n)(e.value)}(0,r.hmacKey,this.Y))}}const L=400;function I(e,n={}){return function(e,{baseUrl:n="https://api.pwnedpasswords.com",userAgent:r}={}){const s=Object.assign({},r?{headers:{"User-Agent":r}}:{}),o=`${n.replace(/\/$/g,"")}${e}`;return t(o,s).then((t=>{if(t.ok)return t.text();if(t.status===L)return t.text().then((t=>{throw Error(t)}));throw Error(t.statusText)}))}("/range/"+encodeURIComponent(e),n).then((t=>t.split("\n").filter(Boolean))).then((t=>t.reduce(((t,e)=>{const[n,r]=e.split(":");return t[n]=parseInt(r,10),t}),{})))}function Y(t,e={}){const n=new F("SHA-1","TEXT");n.update(t);const r=n.getHash("HEX",{outputUpper:!0}),s=r.slice(0,5),o=r.slice(5);return I(s,e).then((t=>t[o]||0))}function H(t,e={truncate:!0}){const{apiKey:n,baseUrl:r,userAgent:s}=e;return Promise.all([f(t,e),/^.+@.+$/.test(t)?d(t,{apiKey:n,baseUrl:r,userAgent:s}):null]).then((t=>({breaches:t[0],pastes:t[1]})))}export{h as RateLimitError,c as breach,f as breachedAccount,l as breaches,p as dataClasses,d as pasteAccount,Y as pwnedPassword,I as pwnedPasswordRange,H as search};
2
+ //# sourceMappingURL=hibp.module.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hibp.module.js","sources":["../../node_modules/@remix-run/web-fetch/src/lib.js","../../src/api/haveibeenpwned/responses.ts","../../src/api/haveibeenpwned/fetchFromApi.ts","../../src/breach.ts","../../src/breachedAccount.ts","../../src/breaches.ts","../../src/dataClasses.ts","../../src/pasteAccount.ts","../../node_modules/jssha/dist/sha1.mjs","../../src/api/pwnedpasswords/responses.ts","../../src/pwnedPasswordRange.ts","../../src/api/pwnedpasswords/fetchFromApi.ts","../../src/pwnedPassword.ts","../../src/search.ts"],"sourcesContent":["\n\n// On the web we just export native fetch implementation\nexport { ReadableStream, Blob, FormData } from './package.js';\nexport const { Headers, Request, Response } = globalThis;\nexport default globalThis.fetch\n\n","/**\n * Known potential responses from the remote API.\n *\n * Unfortunately, the API does not send a decent human-readable message back\n * with each response, but they are documented on the website:\n * https://haveibeenpwned.com/api/v3#ResponseCodes\n *\n * These objects simply provide a mapping between the HTTP response status code\n * and the corresponding human-readable message so we can throw a more\n * descriptive error for the consumer. (They are also leveraged in our tests.)\n */\n\nimport type { ResponseBody } from './types';\n\n/** @internal */\nexport interface HaveIBeenPwnedApiResponse {\n headers: Map<string, string>;\n status: number;\n statusText?: string;\n body?: ResponseBody;\n}\n\nconst emptyHeaders = new Map<string, string>();\n\n/** @internal */\nexport const OK: HaveIBeenPwnedApiResponse = {\n headers: emptyHeaders,\n status: 200,\n};\n\n/** @internal */\nexport const BAD_REQUEST: HaveIBeenPwnedApiResponse = {\n headers: emptyHeaders,\n status: 400,\n statusText:\n 'Bad request — the account does not comply with an acceptable format.',\n};\n\n/**\n * This response has unique behavior. For some reason, the API includes an\n * object in the response body for this one, containing a human-readable\n * message. Manually populating the message here purely for use in tests.\n *\n * @internal\n */\nexport const UNAUTHORIZED: HaveIBeenPwnedApiResponse = {\n headers: emptyHeaders,\n status: 401,\n body: {\n statusCode: 401,\n message: 'Access denied due to missing hibp-api-key.',\n },\n};\n\n/** @internal */\nexport const FORBIDDEN: HaveIBeenPwnedApiResponse = {\n headers: emptyHeaders,\n status: 403,\n statusText: 'Forbidden - access denied.',\n};\n\n/** @internal */\nexport const BLOCKED: HaveIBeenPwnedApiResponse = {\n headers: new Map([['cf-ray', 'someRayId']]),\n status: 403,\n};\n\n/** @internal */\nexport const NOT_FOUND: HaveIBeenPwnedApiResponse = {\n headers: emptyHeaders,\n status: 404,\n};\n\n/**\n * This response has unique behavior. For some reason, the API includes an\n * object in the response body for this one, containing a human-readable\n * message. Manually populating the message here purely for use in tests.\n *\n * @internal\n */\nexport const TOO_MANY_REQUESTS: HaveIBeenPwnedApiResponse = {\n headers: new Map([['retry-after', '2']]),\n status: 429,\n body: {\n statusCode: 429,\n message: 'Rate limit is exceeded. Try again in 2 seconds.',\n },\n};\n","import fetch from '@remix-run/web-fetch';\nimport { name, version } from '../../../package.json';\nimport {\n BAD_REQUEST,\n UNAUTHORIZED,\n FORBIDDEN,\n NOT_FOUND,\n TOO_MANY_REQUESTS,\n} from './responses';\nimport type { ApiData, ErrorData } from './types';\n\n/**\n * Custom error thrown when the haveibeenpwned.com API responds with 429 Too\n * Many Requests. See the `retryAfterSeconds` property for the number of seconds\n * to wait before attempting the request again.\n *\n * @see https://haveibeenpwned.com/API/v3#RateLimiting\n */\nexport class RateLimitError extends Error {\n /**\n * The number of seconds to wait before attempting the request again. May be\n * `undefined` if the API does not provide a `retry-after` header, but this\n * should never happen.\n */\n public retryAfterSeconds: number | undefined;\n\n constructor(\n retryAfter: ReturnType<Headers['get']>,\n message: string | undefined,\n options?: ErrorOptions,\n ) {\n super(message, options);\n this.name = this.constructor.name;\n this.retryAfterSeconds =\n typeof retryAfter === 'string'\n ? Number.parseInt(retryAfter, 10) /* c8 ignore start */\n : undefined;\n }\n}\n/* c8 ignore stop */\n\nfunction blockedWithRayId(rayId: string) {\n return `Request blocked, contact haveibeenpwned.com if this continues (Ray ID: ${rayId})`;\n}\n\n/**\n * Fetches data from the supplied API endpoint.\n *\n * HTTP status code 200 returns an Object (data found).\n * HTTP status code 404 returns null (no data found).\n * HTTP status code 400 throws an Error (bad request).\n * HTTP status code 401 throws an Error (unauthorized).\n * HTTP status code 403 throws an Error (forbidden).\n * HTTP status code 429 throws an Error (too many requests).\n *\n * @internal\n * @private\n * @param {string} endpoint the API endpoint to query\n * @param {object} [options] a configuration object\n * @param {string} [options.apiKey] an API key from\n * https://haveibeenpwned.com/API/Key\n * @param {string} [options.baseUrl] a custom base URL for the\n * haveibeenpwned.com API endpoints (default:\n * `https://haveibeenpwned.com/api/v3`)\n * @param {string} [options.userAgent] a custom string to send as the User-Agent\n * field in the request headers (default: `hibp <version>`)\n * @returns {Promise<ApiData>} a Promise which resolves to the data resulting\n * from the query (or null for 404 Not Found responses), or rejects with an\n * Error\n */\nexport function fetchFromApi(\n endpoint: string,\n {\n apiKey,\n baseUrl = 'https://haveibeenpwned.com/api/v3',\n userAgent,\n }: { apiKey?: string; baseUrl?: string; userAgent?: string } = {},\n): Promise<ApiData> {\n const headers: Record<string, string> = {};\n\n if (apiKey) {\n headers['HIBP-API-Key'] = apiKey;\n }\n\n if (userAgent) {\n headers['User-Agent'] = userAgent;\n }\n\n // Provide a default User-Agent when running outside the browser\n if (!userAgent && typeof navigator === 'undefined') {\n headers['User-Agent'] = `${name} ${version}`;\n }\n\n const config = { headers };\n const url = `${baseUrl.replace(/\\/$/g, '')}${endpoint}`;\n\n return fetch(url, config).then((res) => {\n if (res.ok) return res.json() as Promise<ApiData>;\n\n switch (res.status) {\n case BAD_REQUEST.status:\n throw new Error(BAD_REQUEST.statusText);\n case UNAUTHORIZED.status:\n return res.json().then((body: ErrorData) => {\n throw new Error(body.message);\n });\n case FORBIDDEN.status: {\n const rayId = res.headers.get('cf-ray');\n if (rayId) {\n throw new Error(blockedWithRayId(rayId));\n }\n throw new Error(FORBIDDEN.statusText);\n }\n case NOT_FOUND.status:\n return null;\n case TOO_MANY_REQUESTS.status:\n return res.json().then((body: ErrorData) => {\n const retryAfter = res.headers.get('retry-after');\n throw new RateLimitError(retryAfter, body.message);\n });\n default:\n throw new Error(res.statusText);\n }\n });\n}\n","import type { Breach } from './api/haveibeenpwned/types';\nimport { fetchFromApi } from './api/haveibeenpwned';\n\n/**\n * An object representing a breach.\n *\n * @typedef {object} Breach\n * @property {string} Name\n * @property {string} Title\n * @property {string} Domain\n * @property {string} BreachDate\n * @property {string} AddedDate\n * @property {string} ModifiedDate\n * @property {number} PwnCount\n * @property {string} Description\n * @property {string} LogoPath\n * @property {string[]} DataClasses\n * @property {boolean} IsVerified\n * @property {boolean} IsFabricated\n * @property {boolean} IsSensitive\n * @property {boolean} IsRetired\n * @property {boolean} IsSpamList\n */\n\n/**\n * Fetches data for a specific breach event.\n *\n * @param {string} breachName the name of a breach in the system\n * @param {object} [options] a configuration object\n * @param {string} [options.baseUrl] a custom base URL for the\n * haveibeenpwned.com API endpoints (default:\n * `https://haveibeenpwned.com/api/v3`)\n * @param {string} [options.userAgent] a custom string to send as the User-Agent\n * field in the request headers (default: `hibp <version>`)\n * @returns {(Promise<Breach>|Promise<null>)} a Promise which resolves to an\n * object representing a breach (or null if no breach was found), or rejects\n * with an Error\n * @example\n * breach('Adobe')\n * .then(data => {\n * if (data) {\n * // ...\n * } else {\n * // ...\n * }\n * })\n * .catch(err => {\n * // ...\n * });\n */\nexport function breach(\n breachName: string,\n options: { baseUrl?: string; userAgent?: string } = {},\n): Promise<Breach | null> {\n return fetchFromApi(\n `/breach/${encodeURIComponent(breachName)}`,\n options,\n ) as Promise<Breach | null>;\n}\n","import type { Breach } from './api/haveibeenpwned/types';\nimport { fetchFromApi } from './api/haveibeenpwned';\n\n/**\n * Fetches breach data for a specific account.\n *\n * ***Warning (July 18, 2019):***\n *\n * `haveibeenpwned.com` now requires an API key from\n * https://haveibeenpwned.com/API/Key for the `breachedaccount` endpoint. The\n * `apiKey` option here is not explicitly required, but direct requests made\n * without it (that is, without specifying a `baseUrl` to a proxy that inserts a\n * valid API key on your behalf) will fail.\n *\n * @param {string} account a username or email address\n * @param {object} [options] a configuration object\n * @param {string} [options.apiKey] an API key from\n * https://haveibeenpwned.com/API/Key (default: undefined)\n * @param {string} [options.domain] a domain by which to filter the results\n * (default: all domains)\n * @param {boolean} [options.includeUnverified] include \"unverified\" breaches in\n * the results (default: true)\n * @param {boolean} [options.truncate] truncate the results to only include\n * the name of each breach (default: true)\n * @param {string} [options.baseUrl] a custom base URL for the\n * haveibeenpwned.com API endpoints (default:\n * `https://haveibeenpwned.com/api/v3`)\n * @param {string} [options.userAgent] a custom string to send as the User-Agent\n * field in the request headers (default: `hibp <version>`)\n * @returns {(Promise<Breach[]> | Promise<null>)} a Promise which resolves to an\n * array of breach objects (or null if no breaches were found), or rejects with\n * an Error\n * @example\n * breachedAccount('foo', { apiKey: 'my-api-key' })\n * .then(data => {\n * if (data) {\n * // ...\n * } else {\n * // ...\n * }\n * })\n * .catch(err => {\n * // ...\n * });\n * @example\n * breachedAccount('bar', {\n * includeUnverified: false,\n * baseUrl: 'https://my-hibp-proxy:8080',\n * })\n * .then(data => {\n * if (data) {\n * // ...\n * } else {\n * // ...\n * }\n * })\n * .catch(err => {\n * // ...\n * });\n * @example\n * breachedAccount('baz', {\n * apiKey: 'my-api-key',\n * domain: 'adobe.com',\n * truncate: false,\n * userAgent: 'my-app 1.0'\n * })\n * .then(data => {\n * if (data) {\n * // ...\n * } else {\n * // ...\n * }\n * })\n * .catch(err => {\n * // ...\n * });\n */\nexport function breachedAccount(\n account: string,\n options: {\n apiKey?: string;\n domain?: string;\n includeUnverified?: boolean;\n truncate?: boolean;\n baseUrl?: string;\n userAgent?: string;\n } = {\n includeUnverified: true,\n truncate: true,\n },\n): Promise<Breach[] | null> {\n const endpoint = `/breachedaccount/${encodeURIComponent(account)}?`;\n const params: Array<string> = [];\n if (options.domain) {\n params.push(`domain=${encodeURIComponent(options.domain)}`);\n }\n if (options.includeUnverified === false) {\n params.push('includeUnverified=false');\n }\n if (options.truncate === false) {\n params.push('truncateResponse=false');\n }\n return fetchFromApi(`${endpoint}${params.join('&')}`, {\n apiKey: options.apiKey,\n baseUrl: options.baseUrl,\n userAgent: options.userAgent,\n }) as Promise<Breach[] | null>;\n}\n","import type { Breach } from './api/haveibeenpwned/types';\nimport { fetchFromApi } from './api/haveibeenpwned';\n\n/**\n * Fetches all breach events in the system.\n *\n * @param {object} [options] a configuration object\n * @param {string} [options.domain] a domain by which to filter the results\n * (default: all domains)\n * @param {string} [options.baseUrl] a custom base URL for the\n * haveibeenpwned.com API endpoints (default:\n * `https://haveibeenpwned.com/api/v3`)\n * @param {string} [options.userAgent] a custom string to send as the User-Agent\n * field in the request headers (default: `hibp <version>`)\n * @returns {Promise<Breach[]>} a Promise which resolves to an array of breach\n * objects (an empty array if no breaches were found), or rejects with an Error\n * @example\n * breaches()\n * .then(data => {\n * if (data) {\n * // ...\n * } else {\n * // ...\n * }\n * })\n * .catch(err => {\n * // ...\n * });\n * @example\n * breaches({ domain: 'adobe.com' })\n * .then(data => {\n * if (data) {\n * // ...\n * } else {\n * // ...\n * }\n * })\n * .catch(err => {\n * // ...\n * });\n */\nexport function breaches(\n options: {\n domain?: string;\n baseUrl?: string;\n userAgent?: string;\n } = {},\n): Promise<Breach[]> {\n const endpoint = '/breaches?';\n const params: Array<string> = [];\n if (options.domain) {\n params.push(`domain=${encodeURIComponent(options.domain)}`);\n }\n return fetchFromApi(`${endpoint}${params.join('&')}`, {\n baseUrl: options.baseUrl,\n userAgent: options.userAgent,\n }) as Promise<Breach[]>;\n}\n","import { fetchFromApi } from './api/haveibeenpwned';\n\n/**\n * Fetches all data classes in the system.\n *\n * @param {object} [options] a configuration object\n * @param {string} [options.baseUrl] a custom base URL for the\n * haveibeenpwned.com API endpoints (default:\n * `https://haveibeenpwned.com/api/v3`)\n * @param {string} [options.userAgent] a custom string to send as the User-Agent\n * field in the request headers (default: `hibp <version>`)\n * @returns {(Promise<string[]> | Promise<null>)} a Promise which resolves to an\n * array of strings (or null if no data classes were found), or rejects with an\n * Error\n * @example\n * dataClasses()\n * .then(data => {\n * if (data) {\n * // ...\n * } else {\n * // ...\n * }\n * })\n * .catch(err => {\n * // ...\n * });\n */\nexport function dataClasses(\n options: { baseUrl?: string; userAgent?: string } = {},\n): Promise<string[] | null> {\n return fetchFromApi('/dataclasses', options) as Promise<string[] | null>;\n}\n","import type { Paste } from './api/haveibeenpwned/types';\nimport { fetchFromApi } from './api/haveibeenpwned';\n\n/**\n * An object representing a paste.\n *\n * @typedef {object} Paste\n * @property {string} Id\n * @property {string} Source\n * @property {string} Title\n * @property {string} Date\n * @property {number} EmailCount\n */\n\n/**\n * Fetches paste data for a specific account (email address).\n *\n * ***Warning (July 18, 2019):***\n *\n * `haveibeenpwned.com` now requires an API key from\n * https://haveibeenpwned.com/API/Key for the `pasteaccount` endpoint. The\n * `apiKey` option here is not explicitly required, but direct requests made\n * without it (that is, without specifying a `baseUrl` to a proxy that inserts a\n * valid API key on your behalf) will fail.\n *\n * @param {string} email the email address to query\n * @param {object} [options] a configuration object\n * @param {string} [options.apiKey] an API key from\n * https://haveibeenpwned.com/API/Key\n * @param {string} [options.baseUrl] a custom base URL for the\n * haveibeenpwned.com API endpoints (default:\n * `https://haveibeenpwned.com/api/v3`)\n * @param {string} [options.userAgent] a custom string to send as the User-Agent\n * field in the request headers (default: `hibp <version>`)\n * @returns {(Promise<Paste[]> | Promise<null>)} a Promise which resolves to an\n * array of paste objects (or null if no pastes were found), or rejects with an\n * Error\n * @example\n * pasteAccount('foo@bar.com', { apiKey: 'my-api-key' })\n * .then(data => {\n * if (data) {\n * // ...\n * } else {\n * // ...\n * }\n * })\n * .catch(err => {\n * // ...\n * });\n */\nexport function pasteAccount(\n email: string,\n options: { apiKey?: string; baseUrl?: string; userAgent?: string } = {},\n): Promise<Paste[] | null> {\n return fetchFromApi(`/pasteaccount/${encodeURIComponent(email)}`, {\n apiKey: options.apiKey,\n baseUrl: options.baseUrl,\n userAgent: options.userAgent,\n }) as Promise<Paste[] | null>;\n}\n","/**\n * A JavaScript implementation of the SHA family of hashes - defined in FIPS PUB 180-4, FIPS PUB 202,\n * and SP 800-185 - as well as the corresponding HMAC implementation as defined in FIPS PUB 198-1.\n *\n * Copyright 2008-2022 Brian Turek, 1998-2009 Paul Johnston & Contributors\n * Distributed under the BSD License\n * See http://caligatio.github.com/jsSHA/ for more information\n */\nconst t=\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";function r(t,r,n,i){let e,s,o;const h=r||[0],u=(n=n||0)>>>3,f=-1===i?3:0;for(e=0;e<t.length;e+=1)o=e+u,s=o>>>2,h.length<=s&&h.push(0),h[s]|=t[e]<<8*(f+i*(o%4));return{value:h,binLen:8*t.length+n}}function n(n,i,e){switch(i){case\"UTF8\":case\"UTF16BE\":case\"UTF16LE\":break;default:throw new Error(\"encoding must be UTF8, UTF16BE, or UTF16LE\")}switch(n){case\"HEX\":return function(t,r,n){return function(t,r,n,i){let e,s,o,h;if(0!=t.length%2)throw new Error(\"String of HEX type must be in byte increments\");const u=r||[0],f=(n=n||0)>>>3,c=-1===i?3:0;for(e=0;e<t.length;e+=2){if(s=parseInt(t.substr(e,2),16),isNaN(s))throw new Error(\"String of HEX type contains invalid characters\");for(h=(e>>>1)+f,o=h>>>2;u.length<=o;)u.push(0);u[o]|=s<<8*(c+i*(h%4))}return{value:u,binLen:4*t.length+n}}(t,r,n,e)};case\"TEXT\":return function(t,r,n){return function(t,r,n,i,e){let s,o,h,u,f,c,a,w,E=0;const l=n||[0],A=(i=i||0)>>>3;if(\"UTF8\"===r)for(a=-1===e?3:0,h=0;h<t.length;h+=1)for(s=t.charCodeAt(h),o=[],128>s?o.push(s):2048>s?(o.push(192|s>>>6),o.push(128|63&s)):55296>s||57344<=s?o.push(224|s>>>12,128|s>>>6&63,128|63&s):(h+=1,s=65536+((1023&s)<<10|1023&t.charCodeAt(h)),o.push(240|s>>>18,128|s>>>12&63,128|s>>>6&63,128|63&s)),u=0;u<o.length;u+=1){for(c=E+A,f=c>>>2;l.length<=f;)l.push(0);l[f]|=o[u]<<8*(a+e*(c%4)),E+=1}else for(a=-1===e?2:0,w=\"UTF16LE\"===r&&1!==e||\"UTF16LE\"!==r&&1===e,h=0;h<t.length;h+=1){for(s=t.charCodeAt(h),!0===w&&(u=255&s,s=u<<8|s>>>8),c=E+A,f=c>>>2;l.length<=f;)l.push(0);l[f]|=s<<8*(a+e*(c%4)),E+=2}return{value:l,binLen:8*E+i}}(t,i,r,n,e)};case\"B64\":return function(r,n,i){return function(r,n,i,e){let s,o,h,u,f,c,a,w=0;const E=n||[0],l=(i=i||0)>>>3,A=-1===e?3:0,p=r.indexOf(\"=\");if(-1===r.search(/^[a-zA-Z0-9=+/]+$/))throw new Error(\"Invalid character in base-64 string\");if(r=r.replace(/=/g,\"\"),-1!==p&&p<r.length)throw new Error(\"Invalid '=' found in base-64 string\");for(o=0;o<r.length;o+=4){for(f=r.substr(o,4),u=0,h=0;h<f.length;h+=1)s=t.indexOf(f.charAt(h)),u|=s<<18-6*h;for(h=0;h<f.length-1;h+=1){for(a=w+l,c=a>>>2;E.length<=c;)E.push(0);E[c]|=(u>>>16-8*h&255)<<8*(A+e*(a%4)),w+=1}}return{value:E,binLen:8*w+i}}(r,n,i,e)};case\"BYTES\":return function(t,r,n){return function(t,r,n,i){let e,s,o,h;const u=r||[0],f=(n=n||0)>>>3,c=-1===i?3:0;for(s=0;s<t.length;s+=1)e=t.charCodeAt(s),h=s+f,o=h>>>2,u.length<=o&&u.push(0),u[o]|=e<<8*(c+i*(h%4));return{value:u,binLen:8*t.length+n}}(t,r,n,e)};case\"ARRAYBUFFER\":try{new ArrayBuffer(0)}catch(t){throw new Error(\"ARRAYBUFFER not supported by this environment\")}return function(t,n,i){return function(t,n,i,e){return r(new Uint8Array(t),n,i,e)}(t,n,i,e)};case\"UINT8ARRAY\":try{new Uint8Array(0)}catch(t){throw new Error(\"UINT8ARRAY not supported by this environment\")}return function(t,n,i){return r(t,n,i,e)};default:throw new Error(\"format must be HEX, TEXT, B64, BYTES, ARRAYBUFFER, or UINT8ARRAY\")}}function i(r,n,i,e){switch(r){case\"HEX\":return function(t){return function(t,r,n,i){const e=\"0123456789abcdef\";let s,o,h=\"\";const u=r/8,f=-1===n?3:0;for(s=0;s<u;s+=1)o=t[s>>>2]>>>8*(f+n*(s%4)),h+=e.charAt(o>>>4&15)+e.charAt(15&o);return i.outputUpper?h.toUpperCase():h}(t,n,i,e)};case\"B64\":return function(r){return function(r,n,i,e){let s,o,h,u,f,c=\"\";const a=n/8,w=-1===i?3:0;for(s=0;s<a;s+=3)for(u=s+1<a?r[s+1>>>2]:0,f=s+2<a?r[s+2>>>2]:0,h=(r[s>>>2]>>>8*(w+i*(s%4))&255)<<16|(u>>>8*(w+i*((s+1)%4))&255)<<8|f>>>8*(w+i*((s+2)%4))&255,o=0;o<4;o+=1)c+=8*s+6*o<=n?t.charAt(h>>>6*(3-o)&63):e.b64Pad;return c}(r,n,i,e)};case\"BYTES\":return function(t){return function(t,r,n){let i,e,s=\"\";const o=r/8,h=-1===n?3:0;for(i=0;i<o;i+=1)e=t[i>>>2]>>>8*(h+n*(i%4))&255,s+=String.fromCharCode(e);return s}(t,n,i)};case\"ARRAYBUFFER\":try{new ArrayBuffer(0)}catch(t){throw new Error(\"ARRAYBUFFER not supported by this environment\")}return function(t){return function(t,r,n){let i;const e=r/8,s=new ArrayBuffer(e),o=new Uint8Array(s),h=-1===n?3:0;for(i=0;i<e;i+=1)o[i]=t[i>>>2]>>>8*(h+n*(i%4))&255;return s}(t,n,i)};case\"UINT8ARRAY\":try{new Uint8Array(0)}catch(t){throw new Error(\"UINT8ARRAY not supported by this environment\")}return function(t){return function(t,r,n){let i;const e=r/8,s=-1===n?3:0,o=new Uint8Array(e);for(i=0;i<e;i+=1)o[i]=t[i>>>2]>>>8*(s+n*(i%4))&255;return o}(t,n,i)};default:throw new Error(\"format must be HEX, B64, BYTES, ARRAYBUFFER, or UINT8ARRAY\")}}function e(t){const r={outputUpper:!1,b64Pad:\"=\",outputLen:-1},n=t||{},i=\"Output length must be a multiple of 8\";if(r.outputUpper=n.outputUpper||!1,n.b64Pad&&(r.b64Pad=n.b64Pad),n.outputLen){if(n.outputLen%8!=0)throw new Error(i);r.outputLen=n.outputLen}else if(n.shakeLen){if(n.shakeLen%8!=0)throw new Error(i);r.outputLen=n.shakeLen}if(\"boolean\"!=typeof r.outputUpper)throw new Error(\"Invalid outputUpper formatting option\");if(\"string\"!=typeof r.b64Pad)throw new Error(\"Invalid b64Pad formatting option\");return r}function s(t,r){return t<<r|t>>>32-r}function o(t,r,n){return t^r^n}function h(t,r,n){return t&r^t&n^r&n}function u(t,r){const n=(65535&t)+(65535&r);return(65535&(t>>>16)+(r>>>16)+(n>>>16))<<16|65535&n}function f(t,r,n,i,e){const s=(65535&t)+(65535&r)+(65535&n)+(65535&i)+(65535&e);return(65535&(t>>>16)+(r>>>16)+(n>>>16)+(i>>>16)+(e>>>16)+(s>>>16))<<16|65535&s}function c(t){return[1732584193,4023233417,2562383102,271733878,3285377520]}function a(t,r){let n,i,e,c,a,w,E;const l=[];for(n=r[0],i=r[1],e=r[2],c=r[3],a=r[4],E=0;E<80;E+=1)l[E]=E<16?t[E]:s(l[E-3]^l[E-8]^l[E-14]^l[E-16],1),w=E<20?f(s(n,5),(A=i)&e^~A&c,a,1518500249,l[E]):E<40?f(s(n,5),o(i,e,c),a,1859775393,l[E]):E<60?f(s(n,5),h(i,e,c),a,2400959708,l[E]):f(s(n,5),o(i,e,c),a,3395469782,l[E]),a=c,c=e,e=s(i,30),i=n,n=w;var A;return r[0]=u(n,r[0]),r[1]=u(i,r[1]),r[2]=u(e,r[2]),r[3]=u(c,r[3]),r[4]=u(a,r[4]),r}function w(t,r,n,i){let e;const s=15+(r+65>>>9<<4),o=r+n;for(;t.length<=s;)t.push(0);for(t[r>>>5]|=128<<24-r%32,t[s]=4294967295&o,t[s-1]=o/4294967296|0,e=0;e<t.length;e+=16)i=a(t.slice(e,e+16),i);return i}class E extends class{constructor(t,r,n){const i=n||{};if(this.t=r,this.i=i.encoding||\"UTF8\",this.numRounds=i.numRounds||1,isNaN(this.numRounds)||this.numRounds!==parseInt(this.numRounds,10)||1>this.numRounds)throw new Error(\"numRounds must a integer >= 1\");this.o=t,this.h=[],this.u=0,this.l=!1,this.A=0,this.p=!1,this.R=[],this.U=[]}update(t){let r,n=0;const i=this.T>>>5,e=this.F(t,this.h,this.u),s=e.binLen,o=e.value,h=s>>>5;for(r=0;r<h;r+=i)n+this.T<=s&&(this.m=this.g(o.slice(r,r+i),this.m),n+=this.T);return this.A+=n,this.h=o.slice(n>>>5),this.u=s%this.T,this.l=!0,this}getHash(t,r){let n,s,o=this.B;const h=e(r);if(this.v){if(-1===h.outputLen)throw new Error(\"Output length must be specified in options\");o=h.outputLen}const u=i(t,o,this.Y,h);if(this.p&&this.H)return u(this.H(h));for(s=this.C(this.h.slice(),this.u,this.A,this.I(this.m),o),n=1;n<this.numRounds;n+=1)this.v&&o%32!=0&&(s[s.length-1]&=16777215>>>24-o%32),s=this.C(s,o,0,this.L(this.o),o);return u(s)}setHMACKey(t,r,i){if(!this.M)throw new Error(\"Variant does not support HMAC\");if(this.l)throw new Error(\"Cannot set MAC key after calling update\");const e=n(r,(i||{}).encoding||\"UTF8\",this.Y);this.N(e(t))}N(t){const r=this.T>>>3,n=r/4-1;let i;if(1!==this.numRounds)throw new Error(\"Cannot set numRounds with MAC\");if(this.p)throw new Error(\"MAC key already set\");for(r<t.binLen/8&&(t.value=this.C(t.value,t.binLen,0,this.L(this.o),this.B));t.value.length<=n;)t.value.push(0);for(i=0;i<=n;i+=1)this.R[i]=909522486^t.value[i],this.U[i]=1549556828^t.value[i];this.m=this.g(this.R,this.m),this.A=this.T,this.p=!0}getHMAC(t,r){const n=e(r);return i(t,this.B,this.Y,n)(this.S())}S(){let t;if(!this.p)throw new Error(\"Cannot call getHMAC without first setting MAC key\");const r=this.C(this.h.slice(),this.u,this.A,this.I(this.m),this.B);return t=this.g(this.U,this.L(this.o)),t=this.C(r,this.B,this.T,t,this.B),t}}{constructor(t,r,i){if(\"SHA-1\"!==t)throw new Error(\"Chosen SHA variant is not supported\");super(t,r,i);const e=i||{};this.M=!0,this.H=this.S,this.Y=-1,this.F=n(this.t,this.i,this.Y),this.g=a,this.I=function(t){return t.slice()},this.L=c,this.C=w,this.m=[1732584193,4023233417,2562383102,271733878,3285377520],this.T=512,this.B=160,this.v=!1,e.hmacKey&&this.N(function(t,r,i,e){const s=t+\" must include a value and format\";if(!r){if(!e)throw new Error(s);return e}if(void 0===r.value||!r.format)throw new Error(s);return n(r.format,r.encoding||\"UTF8\",i)(r.value)}(\"hmacKey\",e.hmacKey,this.Y))}}export{E as default};\n","/**\n * Known potential responses from the remote API.\n *\n * https://haveibeenpwned.com/api/v3#PwnedPasswords\n *\n */\n\n/** @internal */\nexport interface PwnedPasswordsApiResponse {\n status: number;\n body?: string;\n}\n\n/** @internal */\nexport const OK: PwnedPasswordsApiResponse = {\n status: 200,\n};\n\n/** @internal */\nexport const BAD_REQUEST: PwnedPasswordsApiResponse = {\n status: 400,\n body: 'The hash prefix was not in a valid format',\n};\n","import { fetchFromApi } from './api/pwnedpasswords';\n\nexport interface PwnedPasswordSuffixes {\n [suffix: string]: number;\n}\n\n/**\n * An object mapping an exposed password hash suffix (corresponding to a given\n * hash prefix) to how many times it occurred in the Pwned Passwords repository.\n *\n * @typedef {Object.<string, number>} PwnedPasswordSuffixes\n */\n\n/**\n * Fetches the SHA-1 hash suffixes for the given 5-character SHA-1 hash prefix.\n *\n * When a password hash with the same first 5 characters is found in the Pwned\n * Passwords repository, the API will respond with an HTTP 200 and include the\n * suffix of every hash beginning with the specified prefix, followed by a count\n * of how many times it appears in the data set. This function parses the\n * response and returns a more structured format.\n *\n * @param {string} prefix the first 5 characters of a SHA-1 password hash (case\n * insensitive)\n * @param {object} [options] a configuration object\n * @param {string} [options.baseUrl] a custom base URL for the\n * pwnedpasswords.com API endpoints (default: `https://api.pwnedpasswords.com`)\n * @param {string} [options.userAgent] a custom string to send as the User-Agent\n * field in the request headers (default: `hibp <version>`)\n * @returns {Promise<PwnedPasswordSuffixes>} a Promise which resolves to an\n * object mapping the `suffix` that when matched with the prefix composes the\n * complete hash, to the `count` of how many times it appears in the breached\n * password data set, or rejects with an Error\n *\n * @example\n * pwnedPasswordRange('5BAA6')\n * .then(results => {\n * // results will have the following shape:\n * // {\n * // \"003D68EB55068C33ACE09247EE4C639306B\": 3,\n * // \"012C192B2F16F82EA0EB9EF18D9D539B0DD\": 1,\n * // ...\n * // }\n * })\n * @example\n * const suffix = '1E4C9B93F3F0682250B6CF8331B7EE68FD8';\n * pwnedPasswordRange('5BAA6')\n * .then(results => (results[suffix] || 0))\n * .catch(err => {\n * // ...\n * });\n * @see https://haveibeenpwned.com/api/v3#SearchingPwnedPasswordsByRange\n */\nexport function pwnedPasswordRange(\n prefix: string,\n options: { baseUrl?: string; userAgent?: string } = {},\n): Promise<PwnedPasswordSuffixes> {\n return (\n fetchFromApi(`/range/${encodeURIComponent(prefix)}`, options)\n // create array from lines of text in response body\n .then((data) => data.split('\\n').filter(Boolean))\n // convert into an object mapping suffix to count for each line\n .then((results) =>\n results.reduce<PwnedPasswordSuffixes>((acc, row) => {\n const [suffix, countString] = row.split(':');\n acc[suffix] = parseInt(countString, 10);\n return acc;\n }, {}),\n )\n );\n}\n","import fetch from '@remix-run/web-fetch';\nimport { BAD_REQUEST } from './responses';\n\n/**\n * Fetches data from the supplied API endpoint.\n *\n * HTTP status code 200 returns plain text (data found).\n * HTTP status code 400 throws an Error (bad request).\n *\n * @internal\n * @private\n * @param {string} endpoint the API endpoint to query\n * @param {object} [options] a configuration object\n * @param {string} [options.baseUrl] a custom base URL for the\n * pwnedpasswords.com API endpoints (default: `https://api.pwnedpasswords.com`)\n * @param {string} [options.userAgent] a custom string to send as the User-Agent\n * field in the request headers (default: `hibp <version>`)\n * @returns {Promise<string>} a Promise which resolves to the data resulting\n * from the query, or rejects with an Error\n */\nexport function fetchFromApi(\n endpoint: string,\n {\n baseUrl = 'https://api.pwnedpasswords.com',\n userAgent,\n }: { baseUrl?: string; userAgent?: string } = {},\n): Promise<string> {\n const config = Object.assign(\n {},\n userAgent\n ? {\n headers: {\n 'User-Agent': userAgent,\n },\n }\n : {},\n );\n\n const url = `${baseUrl.replace(/\\/$/g, '')}${endpoint}`;\n\n return fetch(url, config).then((res) => {\n if (res.ok) return res.text();\n\n if (res.status === BAD_REQUEST.status) {\n return res.text().then((text) => {\n throw new Error(text);\n });\n }\n\n throw new Error(res.statusText);\n });\n}\n","import JSSHA from 'jssha/dist/sha1';\nimport { pwnedPasswordRange } from './pwnedPasswordRange';\n\n/**\n * Fetches the number of times the the given password has been exposed in a\n * breach (0 indicating no exposure). The password is given in plain text, but\n * only the first 5 characters of its SHA-1 hash will be submitted to the API.\n *\n * @param {string} password a password in plain text\n * @param {object} [options] a configuration object\n * @param {string} [options.baseUrl] a custom base URL for the\n * pwnedpasswords.com API endpoints (default: `https://api.pwnedpasswords.com`)\n * @param {string} [options.userAgent] a custom string to send as the User-Agent\n * field in the request headers (default: `hibp <version>`)\n * @returns {Promise<number>} a Promise which resolves to the number of times\n * the password has been exposed in a breach, or rejects with an Error\n * @example\n * pwnedPassword('f00b4r')\n * .then(numPwns => {\n * // truthy check or numeric condition\n * if (numPwns) {\n * // ...\n * } else {\n * // ...\n * }\n * })\n * .catch(err => {\n * // ...\n * });\n * @see https://haveibeenpwned.com/api/v3#PwnedPasswords\n */\nexport function pwnedPassword(\n password: string,\n options: { baseUrl?: string; userAgent?: string } = {},\n): Promise<number> {\n const sha1 = new JSSHA('SHA-1', 'TEXT');\n sha1.update(password);\n const hash = sha1.getHash('HEX', { outputUpper: true });\n const prefix = hash.slice(0, 5);\n const suffix = hash.slice(5);\n\n return pwnedPasswordRange(prefix, options).then(\n (range) => range[suffix] || 0,\n );\n}\n","import type { Breach, Paste } from './api/haveibeenpwned/types';\nimport { breachedAccount } from './breachedAccount';\nimport { pasteAccount } from './pasteAccount';\n\nexport interface SearchResults {\n breaches: Breach[] | null;\n pastes: Paste[] | null;\n}\n\n/**\n * An object representing search results.\n *\n * @typedef {object} SearchResults\n * @property {(Breach[] | null)} breaches\n * @property {(Paste[] | null)} pastes\n */\n\n/**\n * Fetches all breaches and all pastes associated with the provided account\n * (email address or username). Note that the remote API does not support\n * querying pastes by username (only email addresses), so in the event the\n * provided account is not a valid email address, only breach data is queried\n * and the \"pastes\" field of the resulting object will always be null. This is\n * exactly how searching via the current web interface behaves, which this\n * convenience method is designed to mimic.\n *\n * ***Warning (July 18, 2019):***\n *\n * `haveibeenpwned.com` now requires an API key from\n * https://haveibeenpwned.com/API/Key for the `breachedaccount` and\n * `pasteaccount` endpoints. The `apiKey` option here is not explicitly\n * required, but direct requests made without it (that is, without specifying a\n * `baseUrl` to a proxy that inserts a valid API key on your behalf) will fail.\n *\n * @param {string} account an email address or username\n * @param {object} [breachOptions] a configuration object pertaining to breach\n * queries\n * @param {string} [breachOptions.apiKey] an API key from\n * https://haveibeenpwned.com/API/Key\n * @param {string} [breachOptions.domain] a domain by which to filter the\n * results (default: all domains)\n * @param {boolean} [breachOptions.truncate] truncate the results to only\n * include the name of each breach (default: true)\n * @param {string} [breachOptions.baseUrl] a custom base URL for the\n * haveibeenpwned.com API endpoints (default:\n * `https://haveibeenpwned.com/api/v3`)\n * @param {string} [breachOptions.userAgent] a custom string to send as the\n * User-Agent field in the request headers (default: `hibp <version>`)\n * @returns {Promise<SearchResults>} a Promise which resolves to an object\n * containing a \"breaches\" key (which can be null or an array of breach objects)\n * and a \"pastes\" key (which can be null or an array of paste objects), or\n * rejects with an Error\n * @example\n * search('foo', { apiKey: 'my-api-key' })\n * .then(data => {\n * if (data.breaches || data.pastes) {\n * // ...\n * } else {\n * // ...\n * }\n * })\n * .catch(err => {\n * // ...\n * });\n * @example\n * search('nobody@nowhere.com', { apiKey: 'my-api-key', truncate: false })\n * .then(data => {\n * if (data.breaches || data.pastes) {\n * // ...\n * } else {\n * // ...\n * }\n * })\n * .catch(err => {\n * // ...\n * });\n *\n * @see https://haveibeenpwned.com/\n */\nexport function search(\n account: string,\n breachOptions: {\n apiKey?: string;\n domain?: string;\n truncate?: boolean;\n baseUrl?: string;\n userAgent?: string;\n } = {\n truncate: true,\n },\n): Promise<SearchResults> {\n const { apiKey, baseUrl, userAgent } = breachOptions;\n\n return Promise.all([\n breachedAccount(account, breachOptions),\n // This email regex is garbage but it seems to be what the API uses:\n /^.+@.+$/.test(account)\n ? pasteAccount(account, { apiKey, baseUrl, userAgent })\n : null,\n ]).then(\n // Avoid array destructuring here to prevent need for Babel helpers\n (promises) => ({\n breaches: promises[0],\n pastes: promises[1],\n }),\n );\n}\n"],"names":["fetch","globalThis","Map","BAD_REQUEST","UNAUTHORIZED","FORBIDDEN","NOT_FOUND","TOO_MANY_REQUESTS","RateLimitError","Error","retryAfterSeconds","constructor","retryAfter","message","options","super","this","name","Number","parseInt","undefined","fetchFromApi","endpoint","apiKey","baseUrl","userAgent","headers","navigator","config","url","replace","then","res","ok","json","status","body","rayId","get","blockedWithRayId","statusText","breach","breachName","encodeURIComponent","breachedAccount","account","includeUnverified","truncate","params","domain","push","join","breaches","dataClasses","pasteAccount","email","t","r","n","i","e","s","o","h","u","f","length","value","binLen","c","substr","isNaN","a","w","E","l","A","charCodeAt","p","indexOf","search","charAt","ArrayBuffer","Uint8Array","outputUpper","toUpperCase","b64Pad","String","fromCharCode","outputLen","shakeLen","slice","encoding","numRounds","R","U","update","T","F","m","g","getHash","B","v","Y","H","C","I","L","setHMACKey","M","N","getHMAC","S","hmacKey","format","pwnedPasswordRange","prefix","Object","assign","text","data","split","filter","Boolean","results","reduce","acc","row","suffix","countString","pwnedPassword","password","sha1","JSSHA","hash","range","breachOptions","Promise","all","test","promises","pastes"],"mappings":"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"}