is-academic-email 1.0.1 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,58 @@
1
+ # is-academic-email
2
+
3
+ A lightweight Node.js utility for detecting academic email addresses and domains, powered by the [swot](https://github.com/jetbrains/swot) dataset.
4
+
5
+ ## Installation
6
+
7
+ Using npm:
8
+
9
+ ```sh
10
+ npm install is-academic-email
11
+ ```
12
+
13
+ Using pnpm:
14
+
15
+ ```sh
16
+ pnpm add is-academic-email
17
+ ```
18
+
19
+ ## Quick start
20
+
21
+ ```ts
22
+ import {
23
+ isAcademic,
24
+ isUnderTLD,
25
+ isStoplisted,
26
+ findSchoolNames,
27
+ } from 'is-academic-email';
28
+
29
+ isAcademic('jane.doe@ox.ac.uk'); // true ("ox.ac.uk" is a known academic domain)
30
+ isAcademic('user@gmail.com'); // false ("gmail.com" is not academic)
31
+
32
+ isUnderTLD('prof@university.edu.ee'); // true ("edu.ee" is a known academic TLD)
33
+ isStoplisted('https://mail.america.edu'); // true ("america.edu" is stoplisted)
34
+
35
+ findSchoolNames('alice@cs.stanford.edu'); // ["Stanford University"]
36
+ ```
37
+
38
+ ## API
39
+
40
+ ### `isAcademic(email: string): boolean`
41
+
42
+ Returns `true` if the email is valid and not stoplisted, and either under a known academic TLD or associated with a known institution.
43
+
44
+ ### `isUnderTLD(input: string): boolean`
45
+
46
+ Returns `true` if the host is under a known academic/public-suffix TLD (supports compound TLDs like `ac.uk`).
47
+
48
+ ### `isStoplisted(input: string): boolean`
49
+
50
+ Returns `true` if the host matches a known stoplisted domain (e.g., abusive domain under whitelisted TLD).
51
+
52
+ ### `findSchoolNames(input: string): string[]`
53
+
54
+ Returns institution names associated with the host (empty array if none).
55
+
56
+ ### `SWOT_METADATA`
57
+
58
+ Metadata about the dataset (e.g., version and record counts).
package/dist/index.d.ts CHANGED
@@ -1,16 +1,58 @@
1
- export type SwotDataPacked = {
2
- institutions: Record<string, string[]>;
3
- stoplist: string[];
4
- tlds: string[];
5
- };
1
+ /**
2
+ * Unpacked dataset used at runtime.
3
+ *
4
+ * @property {Map<string, string[]>} institutions Map from registered domain
5
+ * (e.g., "stanford.edu") to one or more official institution names.
6
+ * @property {Set<string>} stoplist Domains/subdomains that should not be considered academic.
7
+ * @property {Set<string>} tlds Academic/public-suffix TLDs (e.g., "edu", "ac.uk").
8
+ */
6
9
  export type SwotData = {
7
10
  institutions: Map<string, string[]>;
8
11
  stoplist: Set<string>;
9
12
  tlds: Set<string>;
10
13
  };
14
+ /**
15
+ * Check if the host is under a known academic/public-suffix TLD
16
+ * (e.g., "edu", "ac.uk").
17
+ *
18
+ * @param {string} emailOrDomain Email address, bare domain, or full URL.
19
+ * @returns {boolean} True if any domain suffix matches a known academic TLD.
20
+ * @example
21
+ * isUnderTLD('prof@university.edu'); // true (if "edu" is in TLDs)
22
+ */
11
23
  export declare function isUnderTLD(emailOrDomain: string): boolean;
24
+ /**
25
+ * Check if the host is in the stoplist
26
+ *
27
+ * @param {string} emailOrDomain Email address, bare domain, or full URL.
28
+ * @returns {boolean} True if any domain suffix is stoplisted.
29
+ * @example
30
+ * isStoplisted('user@stoplisted.edu'); // true (if "stoplisted.edu" is in stoplist)
31
+ */
12
32
  export declare function isStoplisted(emailOrDomain: string): boolean;
33
+ /**
34
+ * Get institution names associated with the host.
35
+ * Returns a new array; returns [] if none found.
36
+ *
37
+ * @param {string} emailOrDomain Email address, bare domain, or full URL.
38
+ * @returns {string[]} Institution names for the first matching suffix.
39
+ * @example
40
+ * findSchoolNames('alice@cs.stanford.edu'); // ["Stanford University"]
41
+ */
13
42
  export declare function findSchoolNames(emailOrDomain: string): string[];
43
+ /**
44
+ * Check if an email address is an academic email address.
45
+ *
46
+ * @param {string} email Email address to test.
47
+ * @returns {boolean} True if the email is valid and not stoplisted, and
48
+ * either under a known academic TLD or associated with a known institution.
49
+ * @example
50
+ * isAcademic('jane.doe@ox.ac.uk'); // true (if "ac.uk" or domain is known)
51
+ */
14
52
  export declare function isAcademic(email: string): boolean;
15
- export { SWOT_METADATA } from './swot-metadata';
16
- //# sourceMappingURL=index.d.ts.map
53
+ /**
54
+ * Metadata about the dataset (e.g., version and counts).
55
+ *
56
+ * @see ./swot-metadata.js
57
+ */
58
+ export { SWOT_METADATA } from './swot-metadata.js';
package/dist/index.js CHANGED
@@ -42,12 +42,38 @@ function checkSet(set, parts) {
42
42
  }
43
43
  return false;
44
44
  }
45
+ /**
46
+ * Check if the host is under a known academic/public-suffix TLD
47
+ * (e.g., "edu", "ac.uk").
48
+ *
49
+ * @param {string} emailOrDomain Email address, bare domain, or full URL.
50
+ * @returns {boolean} True if any domain suffix matches a known academic TLD.
51
+ * @example
52
+ * isUnderTLD('prof@university.edu'); // true (if "edu" is in TLDs)
53
+ */
45
54
  export function isUnderTLD(emailOrDomain) {
46
55
  return checkSet(DATA.tlds, domainParts(emailOrDomain));
47
56
  }
57
+ /**
58
+ * Check if the host is in the stoplist
59
+ *
60
+ * @param {string} emailOrDomain Email address, bare domain, or full URL.
61
+ * @returns {boolean} True if any domain suffix is stoplisted.
62
+ * @example
63
+ * isStoplisted('user@stoplisted.edu'); // true (if "stoplisted.edu" is in stoplist)
64
+ */
48
65
  export function isStoplisted(emailOrDomain) {
49
66
  return checkSet(DATA.stoplist, domainParts(emailOrDomain));
50
67
  }
68
+ /**
69
+ * Get institution names associated with the host.
70
+ * Returns a new array; returns [] if none found.
71
+ *
72
+ * @param {string} emailOrDomain Email address, bare domain, or full URL.
73
+ * @returns {string[]} Institution names for the first matching suffix.
74
+ * @example
75
+ * findSchoolNames('alice@cs.stanford.edu'); // ["Stanford University"]
76
+ */
51
77
  export function findSchoolNames(emailOrDomain) {
52
78
  const parts = domainParts(emailOrDomain);
53
79
  let subj = '';
@@ -59,6 +85,15 @@ export function findSchoolNames(emailOrDomain) {
59
85
  }
60
86
  return [];
61
87
  }
88
+ /**
89
+ * Check if an email address is an academic email address.
90
+ *
91
+ * @param {string} email Email address to test.
92
+ * @returns {boolean} True if the email is valid and not stoplisted, and
93
+ * either under a known academic TLD or associated with a known institution.
94
+ * @example
95
+ * isAcademic('jane.doe@ox.ac.uk'); // true (if "ac.uk" or domain is known)
96
+ */
62
97
  export function isAcademic(email) {
63
98
  const valid = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
64
99
  if (!valid)
@@ -66,5 +101,9 @@ export function isAcademic(email) {
66
101
  return (!isStoplisted(email) &&
67
102
  (isUnderTLD(email) || findSchoolNames(email).length > 0));
68
103
  }
69
- export { SWOT_METADATA } from './swot-metadata';
70
- //# sourceMappingURL=index.js.map
104
+ /**
105
+ * Metadata about the dataset (e.g., version and counts).
106
+ *
107
+ * @see ./swot-metadata.js
108
+ */
109
+ export { SWOT_METADATA } from './swot-metadata.js';
@@ -2,6 +2,5 @@ export declare const SWOT_METADATA: {
2
2
  readonly commit: "8866dac84c80b27b3918c3a15d6f8707dbf84740";
3
3
  readonly date: "2025-09-07 16:53:42 +0300";
4
4
  readonly url: "https://github.com/jetbrains/swot";
5
- readonly updatedAt: "2025-09-07T16:49:40.654Z";
5
+ readonly updatedAt: "2025-09-07T17:22:07.525Z";
6
6
  };
7
- //# sourceMappingURL=swot-metadata.d.ts.map
@@ -1,8 +1,7 @@
1
- // This file was automatically generated on 2025-09-07T16:49:43.499Z
1
+ // This file was automatically generated on 2025-09-07T17:22:10.362Z
2
2
  export const SWOT_METADATA = {
3
3
  "commit": "8866dac84c80b27b3918c3a15d6f8707dbf84740",
4
4
  "date": "2025-09-07 16:53:42 +0300",
5
5
  "url": "https://github.com/jetbrains/swot",
6
- "updatedAt": "2025-09-07T16:49:40.654Z"
6
+ "updatedAt": "2025-09-07T17:22:07.525Z"
7
7
  };
8
- //# sourceMappingURL=swot-metadata.js.map
package/package.json CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "is-academic-email",
3
- "version": "1.0.1",
3
+ "version": "1.0.3",
4
4
  "description": "Fast academic email validation using the JetBrains swot database",
5
5
  "repository": {
6
- "url": "https://github.com/amplitudesxd/is-academic-email"
6
+ "url": "git+https://github.com/amplitudesxd/is-academic-email.git"
7
7
  },
8
8
  "main": "dist/index.js",
9
9
  "module": "dist/index.js",
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAOA,MAAM,MAAM,cAAc,GAAG;IAC3B,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IACvC,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,QAAQ,GAAG;IACrB,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IACpC,QAAQ,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACtB,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CACnB,CAAC;AA4CF,wBAAgB,UAAU,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAEzD;AAED,wBAAgB,YAAY,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAE3D;AAED,wBAAgB,eAAe,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,EAAE,CAS/D;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAOjD;AAED,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC"}
package/dist/index.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAc/D,SAAS,QAAQ;IACf,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,cAAc,CAAC,CAAC;IAE5D,IAAI,MAAsB,CAAC;IAC3B,IAAI,CAAC;QACH,MAAM,UAAU,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;QAC7C,MAAM,YAAY,GAAG,oBAAoB,CAAC,UAAU,CAAC,CAAC;QACtD,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAmB,CAAC;IACvE,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,GAAG,EAAE,YAAY,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;IACxD,CAAC;IAED,OAAO;QACL,YAAY,EAAE,IAAI,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;QAC1D,QAAQ,EAAE,IAAI,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;QAC9D,IAAI,EAAE,IAAI,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;KACvD,CAAC;AACJ,CAAC;AAED,MAAM,IAAI,GAAa,QAAQ,EAAE,CAAC;AAElC,SAAS,WAAW,CAAC,aAAqB;IACxC,MAAM,GAAG,GAAG,aAAa,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC/C,MAAM,IAAI,GAAG,GAAG;SACb,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;SAC/B,OAAO,CAAC,cAAc,EAAE,EAAE,CAAC;SAC3B,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC;SACtB,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;SACb,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IACjB,IAAI,CAAC,IAAI;QAAE,OAAO,EAAE,CAAC;IACrB,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,CAAC;AACnC,CAAC;AAED,SAAS,QAAQ,CAAC,GAAgB,EAAE,KAAe;IACjD,IAAI,IAAI,GAAG,EAAE,CAAC;IACd,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;QACvC,IAAI,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC;YAAE,OAAO,IAAI,CAAC;IACjC,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,aAAqB;IAC9C,OAAO,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,WAAW,CAAC,aAAa,CAAC,CAAC,CAAC;AACzD,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,aAAqB;IAChD,OAAO,QAAQ,CAAC,IAAI,CAAC,QAAQ,EAAE,WAAW,CAAC,aAAa,CAAC,CAAC,CAAC;AAC7D,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,aAAqB;IACnD,MAAM,KAAK,GAAG,WAAW,CAAC,aAAa,CAAC,CAAC;IACzC,IAAI,IAAI,GAAG,EAAE,CAAC;IACd,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;QACvC,MAAM,KAAK,GAAG,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC1C,IAAI,KAAK,IAAI,KAAK,CAAC,MAAM;YAAE,OAAO,KAAK,CAAC,KAAK,EAAE,CAAC;IAClD,CAAC;IACD,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,KAAa;IACtC,MAAM,KAAK,GAAG,4BAA4B,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACvD,IAAI,CAAC,KAAK;QAAE,OAAO,KAAK,CAAC;IACzB,OAAO,CACL,CAAC,YAAY,CAAC,KAAK,CAAC;QACpB,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,eAAe,CAAC,KAAK,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CACzD,CAAC;AACJ,CAAC;AAED,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"swot-metadata.d.ts","sourceRoot":"","sources":["../src/swot-metadata.ts"],"names":[],"mappings":"AACA,eAAO,MAAM,aAAa;;;;;CAKhB,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"swot-metadata.js","sourceRoot":"","sources":["../src/swot-metadata.ts"],"names":[],"mappings":"AAAA,oEAAoE;AACpE,MAAM,CAAC,MAAM,aAAa,GAAG;IAC3B,QAAQ,EAAE,0CAA0C;IACpD,MAAM,EAAE,2BAA2B;IACnC,KAAK,EAAE,mCAAmC;IAC1C,WAAW,EAAE,0BAA0B;CAC/B,CAAC"}