hibp 0.0.0-dev.0e634825
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/API.md +508 -0
- package/CHANGELOG.md +17 -0
- package/LICENSE.txt +22 -0
- package/MIGRATION.md +227 -0
- package/README.md +255 -0
- package/dist/browser/hibp.module.js +2 -0
- package/dist/browser/hibp.module.js.map +1 -0
- package/dist/browser/hibp.umd.js +2 -0
- package/dist/browser/hibp.umd.js.map +1 -0
- package/dist/cjs/api/haveibeenpwned/fetchFromApi.js +107 -0
- package/dist/cjs/api/haveibeenpwned/fetchFromApi.js.map +1 -0
- package/dist/cjs/api/haveibeenpwned/index.js +6 -0
- package/dist/cjs/api/haveibeenpwned/index.js.map +1 -0
- package/dist/cjs/api/haveibeenpwned/responses.js +79 -0
- package/dist/cjs/api/haveibeenpwned/responses.js.map +1 -0
- package/dist/cjs/api/pwnedpasswords/fetchFromApi.js +44 -0
- package/dist/cjs/api/pwnedpasswords/fetchFromApi.js.map +1 -0
- package/dist/cjs/api/pwnedpasswords/index.js +5 -0
- package/dist/cjs/api/pwnedpasswords/index.js.map +1 -0
- package/dist/cjs/api/pwnedpasswords/responses.js +20 -0
- package/dist/cjs/api/pwnedpasswords/responses.js.map +1 -0
- package/dist/cjs/api/web-fetch.js +14 -0
- package/dist/cjs/api/web-fetch.js.map +1 -0
- package/dist/cjs/breach.js +55 -0
- package/dist/cjs/breach.js.map +1 -0
- package/dist/cjs/breachedAccount.js +101 -0
- package/dist/cjs/breachedAccount.js.map +1 -0
- package/dist/cjs/breaches.js +55 -0
- package/dist/cjs/breaches.js.map +1 -0
- package/dist/cjs/dataClasses.js +34 -0
- package/dist/cjs/dataClasses.js.map +1 -0
- package/dist/cjs/hibp.d.ts +480 -0
- package/dist/cjs/hibp.js +21 -0
- package/dist/cjs/hibp.js.map +1 -0
- package/dist/cjs/package.json.js +7 -0
- package/dist/cjs/package.json.js.map +1 -0
- package/dist/cjs/pasteAccount.js +59 -0
- package/dist/cjs/pasteAccount.js.map +1 -0
- package/dist/cjs/pwnedPassword.js +45 -0
- package/dist/cjs/pwnedPassword.js.map +1 -0
- package/dist/cjs/pwnedPasswordRange.js +63 -0
- package/dist/cjs/pwnedPasswordRange.js.map +1 -0
- package/dist/cjs/search.js +97 -0
- package/dist/cjs/search.js.map +1 -0
- package/dist/esm/api/haveibeenpwned/fetchFromApi.mjs +104 -0
- package/dist/esm/api/haveibeenpwned/fetchFromApi.mjs.map +1 -0
- package/dist/esm/api/haveibeenpwned/index.mjs +2 -0
- package/dist/esm/api/haveibeenpwned/index.mjs.map +1 -0
- package/dist/esm/api/haveibeenpwned/responses.mjs +71 -0
- package/dist/esm/api/haveibeenpwned/responses.mjs.map +1 -0
- package/dist/esm/api/pwnedpasswords/fetchFromApi.mjs +42 -0
- package/dist/esm/api/pwnedpasswords/fetchFromApi.mjs.map +1 -0
- package/dist/esm/api/pwnedpasswords/index.mjs +2 -0
- package/dist/esm/api/pwnedpasswords/index.mjs.map +1 -0
- package/dist/esm/api/pwnedpasswords/responses.mjs +17 -0
- package/dist/esm/api/pwnedpasswords/responses.mjs.map +1 -0
- package/dist/esm/api/web-fetch.mjs +10 -0
- package/dist/esm/api/web-fetch.mjs.map +1 -0
- package/dist/esm/breach.mjs +53 -0
- package/dist/esm/breach.mjs.map +1 -0
- package/dist/esm/breachedAccount.mjs +99 -0
- package/dist/esm/breachedAccount.mjs.map +1 -0
- package/dist/esm/breaches.mjs +53 -0
- package/dist/esm/breaches.mjs.map +1 -0
- package/dist/esm/dataClasses.mjs +32 -0
- package/dist/esm/dataClasses.mjs.map +1 -0
- package/dist/esm/hibp.d.mts +480 -0
- package/dist/esm/hibp.mjs +10 -0
- package/dist/esm/hibp.mjs.map +1 -0
- package/dist/esm/package.json.mjs +4 -0
- package/dist/esm/package.json.mjs.map +1 -0
- package/dist/esm/pasteAccount.mjs +57 -0
- package/dist/esm/pasteAccount.mjs.map +1 -0
- package/dist/esm/pwnedPassword.mjs +43 -0
- package/dist/esm/pwnedPassword.mjs.map +1 -0
- package/dist/esm/pwnedPasswordRange.mjs +61 -0
- package/dist/esm/pwnedPasswordRange.mjs.map +1 -0
- package/dist/esm/search.mjs +95 -0
- package/dist/esm/search.mjs.map +1 -0
- package/example/runkit.js +16 -0
- package/package.json +138 -0
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import JSSHA from 'jssha/dist/sha1';
|
|
2
|
+
import { pwnedPasswordRange } from './pwnedPasswordRange.mjs';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Fetches the number of times the the given password has been exposed in a
|
|
6
|
+
* breach (0 indicating no exposure). The password is given in plain text, but
|
|
7
|
+
* only the first 5 characters of its SHA-1 hash will be submitted to the API.
|
|
8
|
+
*
|
|
9
|
+
* @param {string} password a password in plain text
|
|
10
|
+
* @param {object} [options] a configuration object
|
|
11
|
+
* @param {string} [options.baseUrl] a custom base URL for the
|
|
12
|
+
* pwnedpasswords.com API endpoints (default: `https://api.pwnedpasswords.com`)
|
|
13
|
+
* @param {string} [options.userAgent] a custom string to send as the User-Agent
|
|
14
|
+
* field in the request headers (default: `hibp <version>`)
|
|
15
|
+
* @returns {Promise<number>} a Promise which resolves to the number of times
|
|
16
|
+
* the password has been exposed in a breach, or rejects with an Error
|
|
17
|
+
* @example
|
|
18
|
+
* pwnedPassword('f00b4r')
|
|
19
|
+
* .then(numPwns => {
|
|
20
|
+
* // truthy check or numeric condition
|
|
21
|
+
* if (numPwns) {
|
|
22
|
+
* // ...
|
|
23
|
+
* } else {
|
|
24
|
+
* // ...
|
|
25
|
+
* }
|
|
26
|
+
* })
|
|
27
|
+
* .catch(err => {
|
|
28
|
+
* // ...
|
|
29
|
+
* });
|
|
30
|
+
* @see https://haveibeenpwned.com/api/v3#PwnedPasswords
|
|
31
|
+
*/
|
|
32
|
+
function pwnedPassword(password, options = {}) {
|
|
33
|
+
const sha1 = new JSSHA('SHA-1', 'TEXT');
|
|
34
|
+
sha1.update(password);
|
|
35
|
+
const hash = sha1.getHash('HEX', {
|
|
36
|
+
outputUpper: true
|
|
37
|
+
});
|
|
38
|
+
const prefix = hash.slice(0, 5);
|
|
39
|
+
const suffix = hash.slice(5);
|
|
40
|
+
return pwnedPasswordRange(prefix, options).then(range => range[suffix] || 0);
|
|
41
|
+
}
|
|
42
|
+
export { pwnedPassword };
|
|
43
|
+
//# sourceMappingURL=pwnedPassword.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pwnedPassword.mjs","sources":["../../src/pwnedPassword.ts"],"sourcesContent":["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"],"names":["pwnedPassword","password","options","sha1","JSSHA","update","hash","getHash","outputUpper","prefix","slice","suffix","pwnedPasswordRange","then","range"],"mappings":";;;AAGA;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2BG;SACaA,aAAaA,CAC3BC,QAAgB,EAChBC,UAAoD,EAAE,EAAA;EAEtD,MAAMC,IAAI,GAAG,IAAIC,KAAK,CAAC,OAAO,EAAE,MAAM,CAAC;EACvCD,IAAI,CAACE,MAAM,CAACJ,QAAQ,CAAC;EACrB,MAAMK,IAAI,GAAGH,IAAI,CAACI,OAAO,CAAC,KAAK,EAAE;IAAEC,WAAW,EAAE;EAAI,CAAE,CAAC;EACvD,MAAMC,MAAM,GAAGH,IAAI,CAACI,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;EAC/B,MAAMC,MAAM,GAAGL,IAAI,CAACI,KAAK,CAAC,CAAC,CAAC;EAE5B,OAAOE,kBAAkB,CAACH,MAAM,EAAEP,OAAO,CAAC,CAACW,IAAI,CAC5CC,KAAK,IAAKA,KAAK,CAACH,MAAM,CAAC,IAAI,CAAC,CAC9B;AACH;"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { fetchFromApi } from './api/pwnedpasswords/fetchFromApi.mjs';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* An object mapping an exposed password hash suffix (corresponding to a given
|
|
5
|
+
* hash prefix) to how many times it occurred in the Pwned Passwords repository.
|
|
6
|
+
*
|
|
7
|
+
* @typedef {Object.<string, number>} PwnedPasswordSuffixes
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Fetches the SHA-1 hash suffixes for the given 5-character SHA-1 hash prefix.
|
|
11
|
+
*
|
|
12
|
+
* When a password hash with the same first 5 characters is found in the Pwned
|
|
13
|
+
* Passwords repository, the API will respond with an HTTP 200 and include the
|
|
14
|
+
* suffix of every hash beginning with the specified prefix, followed by a count
|
|
15
|
+
* of how many times it appears in the data set. This function parses the
|
|
16
|
+
* response and returns a more structured format.
|
|
17
|
+
*
|
|
18
|
+
* @param {string} prefix the first 5 characters of a SHA-1 password hash (case
|
|
19
|
+
* insensitive)
|
|
20
|
+
* @param {object} [options] a configuration object
|
|
21
|
+
* @param {string} [options.baseUrl] a custom base URL for the
|
|
22
|
+
* pwnedpasswords.com API endpoints (default: `https://api.pwnedpasswords.com`)
|
|
23
|
+
* @param {string} [options.userAgent] a custom string to send as the User-Agent
|
|
24
|
+
* field in the request headers (default: `hibp <version>`)
|
|
25
|
+
* @returns {Promise<PwnedPasswordSuffixes>} a Promise which resolves to an
|
|
26
|
+
* object mapping the `suffix` that when matched with the prefix composes the
|
|
27
|
+
* complete hash, to the `count` of how many times it appears in the breached
|
|
28
|
+
* password data set, or rejects with an Error
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* pwnedPasswordRange('5BAA6')
|
|
32
|
+
* .then(results => {
|
|
33
|
+
* // results will have the following shape:
|
|
34
|
+
* // {
|
|
35
|
+
* // "003D68EB55068C33ACE09247EE4C639306B": 3,
|
|
36
|
+
* // "012C192B2F16F82EA0EB9EF18D9D539B0DD": 1,
|
|
37
|
+
* // ...
|
|
38
|
+
* // }
|
|
39
|
+
* })
|
|
40
|
+
* @example
|
|
41
|
+
* const suffix = '1E4C9B93F3F0682250B6CF8331B7EE68FD8';
|
|
42
|
+
* pwnedPasswordRange('5BAA6')
|
|
43
|
+
* .then(results => (results[suffix] || 0))
|
|
44
|
+
* .catch(err => {
|
|
45
|
+
* // ...
|
|
46
|
+
* });
|
|
47
|
+
* @see https://haveibeenpwned.com/api/v3#SearchingPwnedPasswordsByRange
|
|
48
|
+
*/
|
|
49
|
+
function pwnedPasswordRange(prefix, options = {}) {
|
|
50
|
+
return fetchFromApi(`/range/${encodeURIComponent(prefix)}`, options)
|
|
51
|
+
// create array from lines of text in response body
|
|
52
|
+
.then(data => data.split('\n').filter(Boolean))
|
|
53
|
+
// convert into an object mapping suffix to count for each line
|
|
54
|
+
.then(results => results.reduce((acc, row) => {
|
|
55
|
+
const [suffix, countString] = row.split(':');
|
|
56
|
+
acc[suffix] = parseInt(countString, 10);
|
|
57
|
+
return acc;
|
|
58
|
+
}, {}));
|
|
59
|
+
}
|
|
60
|
+
export { pwnedPasswordRange };
|
|
61
|
+
//# sourceMappingURL=pwnedPasswordRange.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pwnedPasswordRange.mjs","sources":["../../src/pwnedPasswordRange.ts"],"sourcesContent":["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"],"names":["pwnedPasswordRange","prefix","options","fetchFromApi","encodeURIComponent","then","data","split","filter","Boolean","results","reduce","acc","row","suffix","countString","parseInt"],"mappings":";;AAMA;;;;;AAKG;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAuCG;SACaA,kBAAkBA,CAChCC,MAAc,EACdC,UAAoD,EAAE,EAAA;EAEtD,OACEC,YAAY,CAAW,UAAAC,kBAAkB,CAACH,MAAM,CAAC,EAAE,EAAEC,OAAO;;GAEzDG,IAAI,CAAEC,IAAI,IAAKA,IAAI,CAACC,KAAK,CAAC,IAAI,CAAC,CAACC,MAAM,CAACC,OAAO,CAAC;;GAE/CJ,IAAI,CAAEK,OAAO,IACZA,OAAO,CAACC,MAAM,CAAwB,CAACC,GAAG,EAAEC,GAAG,KAAI;IACjD,MAAM,CAACC,MAAM,EAAEC,WAAW,CAAC,GAAGF,GAAG,CAACN,KAAK,CAAC,GAAG,CAAC;IAC5CK,GAAG,CAACE,MAAM,CAAC,GAAGE,QAAQ,CAACD,WAAW,EAAE,EAAE,CAAC;IACvC,OAAOH,GAAG;EACZ,CAAC,EAAE,CAAA,CAAE,CAAC,CACP;AAEP;"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { breachedAccount } from './breachedAccount.mjs';
|
|
2
|
+
import { pasteAccount } from './pasteAccount.mjs';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* An object representing search results.
|
|
6
|
+
*
|
|
7
|
+
* @typedef {object} SearchResults
|
|
8
|
+
* @property {(Breach[] | null)} breaches
|
|
9
|
+
* @property {(Paste[] | null)} pastes
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* Fetches all breaches and all pastes associated with the provided account
|
|
13
|
+
* (email address or username). Note that the remote API does not support
|
|
14
|
+
* querying pastes by username (only email addresses), so in the event the
|
|
15
|
+
* provided account is not a valid email address, only breach data is queried
|
|
16
|
+
* and the "pastes" field of the resulting object will always be null. This is
|
|
17
|
+
* exactly how searching via the current web interface behaves, which this
|
|
18
|
+
* convenience method is designed to mimic.
|
|
19
|
+
*
|
|
20
|
+
* ***Warning (July 18, 2019):***
|
|
21
|
+
*
|
|
22
|
+
* `haveibeenpwned.com` now requires an API key from
|
|
23
|
+
* https://haveibeenpwned.com/API/Key for the `breachedaccount` and
|
|
24
|
+
* `pasteaccount` endpoints. The `apiKey` option here is not explicitly
|
|
25
|
+
* required, but direct requests made without it (that is, without specifying a
|
|
26
|
+
* `baseUrl` to a proxy that inserts a valid API key on your behalf) will fail.
|
|
27
|
+
*
|
|
28
|
+
* @param {string} account an email address or username
|
|
29
|
+
* @param {object} [breachOptions] a configuration object pertaining to breach
|
|
30
|
+
* queries
|
|
31
|
+
* @param {string} [breachOptions.apiKey] an API key from
|
|
32
|
+
* https://haveibeenpwned.com/API/Key
|
|
33
|
+
* @param {string} [breachOptions.domain] a domain by which to filter the
|
|
34
|
+
* results (default: all domains)
|
|
35
|
+
* @param {boolean} [breachOptions.truncate] truncate the results to only
|
|
36
|
+
* include the name of each breach (default: true)
|
|
37
|
+
* @param {string} [breachOptions.baseUrl] a custom base URL for the
|
|
38
|
+
* haveibeenpwned.com API endpoints (default:
|
|
39
|
+
* `https://haveibeenpwned.com/api/v3`)
|
|
40
|
+
* @param {string} [breachOptions.userAgent] a custom string to send as the
|
|
41
|
+
* User-Agent field in the request headers (default: `hibp <version>`)
|
|
42
|
+
* @returns {Promise<SearchResults>} a Promise which resolves to an object
|
|
43
|
+
* containing a "breaches" key (which can be null or an array of breach objects)
|
|
44
|
+
* and a "pastes" key (which can be null or an array of paste objects), or
|
|
45
|
+
* rejects with an Error
|
|
46
|
+
* @example
|
|
47
|
+
* search('foo', { apiKey: 'my-api-key' })
|
|
48
|
+
* .then(data => {
|
|
49
|
+
* if (data.breaches || data.pastes) {
|
|
50
|
+
* // ...
|
|
51
|
+
* } else {
|
|
52
|
+
* // ...
|
|
53
|
+
* }
|
|
54
|
+
* })
|
|
55
|
+
* .catch(err => {
|
|
56
|
+
* // ...
|
|
57
|
+
* });
|
|
58
|
+
* @example
|
|
59
|
+
* search('nobody@nowhere.com', { apiKey: 'my-api-key', truncate: false })
|
|
60
|
+
* .then(data => {
|
|
61
|
+
* if (data.breaches || data.pastes) {
|
|
62
|
+
* // ...
|
|
63
|
+
* } else {
|
|
64
|
+
* // ...
|
|
65
|
+
* }
|
|
66
|
+
* })
|
|
67
|
+
* .catch(err => {
|
|
68
|
+
* // ...
|
|
69
|
+
* });
|
|
70
|
+
*
|
|
71
|
+
* @see https://haveibeenpwned.com/
|
|
72
|
+
*/
|
|
73
|
+
function search(account, breachOptions = {
|
|
74
|
+
truncate: true
|
|
75
|
+
}) {
|
|
76
|
+
const {
|
|
77
|
+
apiKey,
|
|
78
|
+
baseUrl,
|
|
79
|
+
userAgent
|
|
80
|
+
} = breachOptions;
|
|
81
|
+
return Promise.all([breachedAccount(account, breachOptions),
|
|
82
|
+
// This email regex is garbage but it seems to be what the API uses:
|
|
83
|
+
/^.+@.+$/.test(account) ? pasteAccount(account, {
|
|
84
|
+
apiKey,
|
|
85
|
+
baseUrl,
|
|
86
|
+
userAgent
|
|
87
|
+
}) : null]).then(
|
|
88
|
+
// Avoid array destructuring here to prevent need for Babel helpers
|
|
89
|
+
promises => ({
|
|
90
|
+
breaches: promises[0],
|
|
91
|
+
pastes: promises[1]
|
|
92
|
+
}));
|
|
93
|
+
}
|
|
94
|
+
export { search };
|
|
95
|
+
//# sourceMappingURL=search.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search.mjs","sources":["../../src/search.ts"],"sourcesContent":["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":["search","account","breachOptions","truncate","apiKey","baseUrl","userAgent","Promise","all","breachedAccount","test","pasteAccount","then","promises","breaches","pastes"],"mappings":";;;AASA;;;;;;AAMG;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6DG;AACa,SAAAA,MAAMA,CACpBC,OAAe,EACfC,aAMI,GAAA;EACFC,QAAQ,EAAE;AACX,CAAA,EAAA;EAED,MAAM;IAAEC,MAAM;IAAEC,OAAO;IAAEC;EAAS,CAAE,GAAGJ,aAAa;EAEpD,OAAOK,OAAO,CAACC,GAAG,CAAC,CACjBC,eAAe,CAACR,OAAO,EAAEC,aAAa,CAAC;;EAEvC,SAAS,CAACQ,IAAI,CAACT,OAAO,CAAC,GACnBU,YAAY,CAACV,OAAO,EAAE;IAAEG,MAAM;IAAEC,OAAO;IAAEC;EAAS,CAAE,CAAC,GACrD,IAAI,CACT,CAAC,CAACM,IAAI;;EAEJC,QAAQ,KAAM;IACbC,QAAQ,EAAED,QAAQ,CAAC,CAAC,CAAC;IACrBE,MAAM,EAAEF,QAAQ,CAAC,CAAC;EACnB,CAAA,CAAC,CACH;AACH;"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
const hibp = require('hibp');
|
|
2
|
+
|
|
3
|
+
hibp
|
|
4
|
+
.breach('Adobe')
|
|
5
|
+
.then((data) => {
|
|
6
|
+
if (data) {
|
|
7
|
+
// Breach data found
|
|
8
|
+
console.log(data);
|
|
9
|
+
} else {
|
|
10
|
+
console.log('No breach data found by that name.');
|
|
11
|
+
}
|
|
12
|
+
})
|
|
13
|
+
.catch((err) => {
|
|
14
|
+
// Something went wrong.
|
|
15
|
+
console.log(err.message);
|
|
16
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "hibp",
|
|
3
|
+
"version": "0.0.0-dev.0e634825",
|
|
4
|
+
"description": "A Promise-based client for the 'Have I been pwned?' service.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"haveibeenpwned",
|
|
7
|
+
"hibp",
|
|
8
|
+
"pwned",
|
|
9
|
+
"security",
|
|
10
|
+
"hack",
|
|
11
|
+
"dump",
|
|
12
|
+
"breach",
|
|
13
|
+
"pastes",
|
|
14
|
+
"passwords",
|
|
15
|
+
"client"
|
|
16
|
+
],
|
|
17
|
+
"author": {
|
|
18
|
+
"name": "Justin Hall",
|
|
19
|
+
"email": "justin.r.hall@gmail.com"
|
|
20
|
+
},
|
|
21
|
+
"license": "MIT",
|
|
22
|
+
"exports": {
|
|
23
|
+
".": {
|
|
24
|
+
"browser": "./dist/browser/hibp.module.js",
|
|
25
|
+
"umd": "./dist/browser/hibp.umd.js",
|
|
26
|
+
"require": "./dist/cjs/hibp.js",
|
|
27
|
+
"import": "./dist/esm/hibp.mjs"
|
|
28
|
+
},
|
|
29
|
+
"./package.json": "./package.json"
|
|
30
|
+
},
|
|
31
|
+
"main": "dist/cjs/hibp.js",
|
|
32
|
+
"module": "dist/esm/hibp.mjs",
|
|
33
|
+
"unpkg": "dist/browser/hibp.umd.js",
|
|
34
|
+
"runkitExampleFilename": "example/runkit.js",
|
|
35
|
+
"files": [
|
|
36
|
+
"dist",
|
|
37
|
+
"example",
|
|
38
|
+
"API.md",
|
|
39
|
+
"CHANGELOG.md",
|
|
40
|
+
"MIGRATION.md"
|
|
41
|
+
],
|
|
42
|
+
"sideEffects": false,
|
|
43
|
+
"scripts": {
|
|
44
|
+
"build": "run-s --silent build:bundle build:types build:docs",
|
|
45
|
+
"build:bundle": "rollup --config",
|
|
46
|
+
"build:docs": "jsdoc2md --no-cache --files src/*.ts --configure jsdoc2md.json > API.md && node scripts/fix-api-docs.js",
|
|
47
|
+
"build:types": "dts-bundle-generator --silent --umd-module-name hibp --out-file dist/cjs/hibp.d.ts src/hibp.ts && prettier --loglevel silent --write dist/cjs/hibp.d.ts && cpy dist/cjs/hibp.d.ts dist/esm --flat --rename=hibp.d.mts",
|
|
48
|
+
"changeset": "changeset",
|
|
49
|
+
"changeset:version": "changeset version && npm install --package-lock-only",
|
|
50
|
+
"changeset:publish": "changeset publish",
|
|
51
|
+
"check-types": "run-p --silent check-types:*",
|
|
52
|
+
"check-types:cypress": "tsc --project cypress",
|
|
53
|
+
"check-types:src": "tsc --noEmit",
|
|
54
|
+
"clean": "rimraf dist coverage",
|
|
55
|
+
"cy:open": "cypress open",
|
|
56
|
+
"cy:run": "cypress run",
|
|
57
|
+
"format": "prettier --cache --write .",
|
|
58
|
+
"lint": "eslint .",
|
|
59
|
+
"prebuild": "npm run --silent clean",
|
|
60
|
+
"prepare": "npm run --silent build",
|
|
61
|
+
"prepublishOnly": "run-s --silent lint check-types test test:browser:run",
|
|
62
|
+
"size": "bundlewatch --config .bundlewatch.config.js",
|
|
63
|
+
"ssat": "start-server-and-test start-test-server 3000",
|
|
64
|
+
"start-test-server": "serve --no-clipboard",
|
|
65
|
+
"test": "vitest run",
|
|
66
|
+
"test:coverage": "vitest run --coverage",
|
|
67
|
+
"test:browser:open": "run-s --silent build:bundle \"ssat cy:open\"",
|
|
68
|
+
"test:browser:run": "run-s --silent build:bundle \"ssat cy:run\"",
|
|
69
|
+
"test:watch": "vitest watch"
|
|
70
|
+
},
|
|
71
|
+
"private": false,
|
|
72
|
+
"publishConfig": {
|
|
73
|
+
"access": "public"
|
|
74
|
+
},
|
|
75
|
+
"repository": {
|
|
76
|
+
"type": "git",
|
|
77
|
+
"url": "https://github.com/wKovacs64/hibp.git"
|
|
78
|
+
},
|
|
79
|
+
"bugs": {
|
|
80
|
+
"url": "https://github.com/wKovacs64/hibp/issues"
|
|
81
|
+
},
|
|
82
|
+
"homepage": "https://wkovacs64.github.io/hibp",
|
|
83
|
+
"engines": {
|
|
84
|
+
"node": ">= 14.13.1"
|
|
85
|
+
},
|
|
86
|
+
"dependencies": {
|
|
87
|
+
"@remix-run/web-fetch": "^4.3.2",
|
|
88
|
+
"jssha": "^3.3.0"
|
|
89
|
+
},
|
|
90
|
+
"devDependencies": {
|
|
91
|
+
"@babel/core": "7.21.0",
|
|
92
|
+
"@babel/parser": "7.21.2",
|
|
93
|
+
"@babel/plugin-proposal-class-properties": "7.18.6",
|
|
94
|
+
"@babel/plugin-proposal-object-rest-spread": "7.20.7",
|
|
95
|
+
"@babel/preset-env": "7.20.2",
|
|
96
|
+
"@babel/preset-typescript": "7.21.0",
|
|
97
|
+
"@changesets/changelog-github": "0.4.8",
|
|
98
|
+
"@changesets/cli": "2.26.0",
|
|
99
|
+
"@rollup/plugin-babel": "6.0.3",
|
|
100
|
+
"@rollup/plugin-commonjs": "24.0.1",
|
|
101
|
+
"@rollup/plugin-json": "6.0.0",
|
|
102
|
+
"@rollup/plugin-node-resolve": "15.0.1",
|
|
103
|
+
"@rollup/plugin-replace": "5.0.2",
|
|
104
|
+
"@rollup/plugin-terser": "0.4.0",
|
|
105
|
+
"@rollup/plugin-typescript": "11.0.0",
|
|
106
|
+
"@types/common-tags": "1.8.1",
|
|
107
|
+
"@types/debug": "4.1.7",
|
|
108
|
+
"@types/node": "18.15.3",
|
|
109
|
+
"@types/ws": "8.5.4",
|
|
110
|
+
"@vitest/coverage-c8": "0.29.2",
|
|
111
|
+
"@wkovacs64/prettier-config": "3.0.3",
|
|
112
|
+
"babel-plugin-annotate-pure-calls": "0.4.0",
|
|
113
|
+
"bundlewatch": "0.3.3",
|
|
114
|
+
"c8": "7.13.0",
|
|
115
|
+
"codecov": "3.8.3",
|
|
116
|
+
"common-tags": "1.8.2",
|
|
117
|
+
"cpy-cli": "4.2.0",
|
|
118
|
+
"cross-env": "7.0.3",
|
|
119
|
+
"cypress": "12.7.0",
|
|
120
|
+
"dts-bundle-generator": "7.2.0",
|
|
121
|
+
"eslint": "8.36.0",
|
|
122
|
+
"eslint-plugin-cypress": "2.12.1",
|
|
123
|
+
"eslint-plugin-wkovacs64": "14.1.0",
|
|
124
|
+
"glob": "9.2.1",
|
|
125
|
+
"jsdoc-babel": "0.5.0",
|
|
126
|
+
"jsdoc-to-markdown": "8.0.0",
|
|
127
|
+
"msw": "1.1.0",
|
|
128
|
+
"npm-run-all": "4.1.5",
|
|
129
|
+
"prettier": "2.8.4",
|
|
130
|
+
"rimraf": "4.4.0",
|
|
131
|
+
"rollup": "3.19.1",
|
|
132
|
+
"serve": "14.2.0",
|
|
133
|
+
"start-server-and-test": "2.0.0",
|
|
134
|
+
"tslib": "2.5.0",
|
|
135
|
+
"typescript": "4.9.5",
|
|
136
|
+
"vitest": "0.29.2"
|
|
137
|
+
}
|
|
138
|
+
}
|