jd-intel 0.3.0 → 0.3.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jd-intel",
3
- "version": "0.3.0",
3
+ "version": "0.3.1",
4
4
  "description": "Fetch and normalize job descriptions across every major ATS (Greenhouse, Lever, Ashby) — for your AI assistant, no copy-paste.",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
@@ -13,5 +13,6 @@
13
13
  {"slug": "billogram", "name": "Billogram", "sector": "fintech / billing"},
14
14
  {"slug": "detectify", "name": "Detectify", "sector": "security"},
15
15
  {"slug": "storytel", "name": "Storytel", "sector": "audiobooks"},
16
- {"slug": "oneflow", "name": "Oneflow", "sector": "contract management"}
16
+ {"slug": "oneflow", "name": "Oneflow", "sector": "contract management"},
17
+ {"slug": "crunchbase", "name": "Crunchbase", "sector": "company data"}
17
18
  ]
@@ -23,14 +23,36 @@ import { normalize, stripHtml } from '../normalizer.js';
23
23
  * @param {string} slug - TeamTailor career-site slug (e.g., 'tibber')
24
24
  * @returns {Promise<Array>} Normalized job objects
25
25
  */
26
- export async function fetchTeamtailor(slug) {
27
- const url = `https://${slug}.teamtailor.com/jobs.rss`;
28
- const resp = await fetch(url, { redirect: 'follow' });
26
+ // Most sites are {slug}.teamtailor.com, but some sit on a regional
27
+ // segment, e.g. crunchbase.na.teamtailor.com. '' is the base host.
28
+ const TT_REGIONS = ['', 'na', 'eu'];
29
29
 
30
- if (!resp.ok) {
31
- if (resp.status === 404) return []; // No TeamTailor site for this slug
32
- throw new Error(`TeamTailor RSS error for ${slug}: ${resp.status}`);
30
+ /**
31
+ * Resolve which TeamTailor host actually serves this slug's feed.
32
+ * Returns the first 200 Response, throws on a non-404 error, or
33
+ * returns null if no region has a feed.
34
+ */
35
+ async function resolveFeed(slug, method = 'GET') {
36
+ for (const region of TT_REGIONS) {
37
+ const host = region
38
+ ? `${slug}.${region}.teamtailor.com`
39
+ : `${slug}.teamtailor.com`;
40
+ const resp = await fetch(`https://${host}/jobs.rss`, {
41
+ method,
42
+ redirect: 'follow',
43
+ });
44
+ if (resp.ok) return resp;
45
+ if (resp.status !== 404) {
46
+ throw new Error(`TeamTailor RSS error for ${slug}: ${resp.status}`);
47
+ }
48
+ // 404 on this host — try the next region.
33
49
  }
50
+ return null;
51
+ }
52
+
53
+ export async function fetchTeamtailor(slug) {
54
+ const resp = await resolveFeed(slug, 'GET');
55
+ if (!resp) return []; // No TeamTailor site in any known region
34
56
 
35
57
  const xml = await resp.text();
36
58
 
@@ -105,11 +127,7 @@ function decodeEntities(s) {
105
127
  */
106
128
  export async function hasTeamtailor(slug) {
107
129
  try {
108
- const resp = await fetch(`https://${slug}.teamtailor.com/jobs.rss`, {
109
- method: 'HEAD',
110
- redirect: 'follow',
111
- });
112
- return resp.ok;
130
+ return (await resolveFeed(slug, 'HEAD')) !== null;
113
131
  } catch {
114
132
  return false;
115
133
  }