public-api-finder 0.2.1 → 0.2.2

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 CHANGED
@@ -11,10 +11,10 @@ Powered by multiple sources:
11
11
  ## Quick start
12
12
 
13
13
  ```bash
14
- npx public-api-finder "weather forecast" --no-auth --https
15
- npx public-api-finder "crypto prices" --category Cryptocurrency --limit 5
16
- npx public-api-finder "jobs" --json
17
- npx public-api-finder "payments" --openapi
14
+ npx --package public-api-finder public-api-finder "weather forecast" --no-auth --https
15
+ npx --package public-api-finder public-api-finder "crypto prices" --category Cryptocurrency --limit 5
16
+ npx --package public-api-finder public-api-finder "jobs" --json
17
+ npx --package public-api-finder public-api-finder "payments" --openapi
18
18
  ```
19
19
 
20
20
  ## Why
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "public-api-finder",
3
- "version": "0.2.1",
3
+ "version": "0.2.2",
4
4
  "description": "Find free/public APIs for agents and prototypes.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -10,10 +10,10 @@ Use this skill when a task needs a public API candidate. The CLI searches multip
10
10
  ## Quick command
11
11
 
12
12
  ```bash
13
- npx public-api-finder "weather forecast" --no-auth --https
14
- npx public-api-finder "crypto prices" --category Cryptocurrency --limit 5
15
- npx public-api-finder "jobs" --json
16
- npx public-api-finder "payments" --openapi
13
+ npx --package public-api-finder public-api-finder "weather forecast" --no-auth --https
14
+ npx --package public-api-finder public-api-finder "crypto prices" --category Cryptocurrency --limit 5
15
+ npx --package public-api-finder public-api-finder "jobs" --json
16
+ npx --package public-api-finder public-api-finder "payments" --openapi
17
17
  ```
18
18
 
19
19
  If npm is unavailable, use the bundled fallback script:
package/src/cli.js CHANGED
@@ -11,6 +11,54 @@ const SOURCES = {
11
11
  const CACHE_PATH = process.env.PUBLIC_API_FINDER_CACHE || join(homedir(), '.cache', 'public-api-finder', 'all.json');
12
12
  const CACHE_TTL_MS = 24 * 60 * 60 * 1000;
13
13
 
14
+ const DOMAIN_PROFILES = {
15
+ crypto: {
16
+ triggers: ['crypto', 'cryptocurrency', 'cryptocurrencies', 'bitcoin', 'ethereum', 'blockchain', 'defi', 'token', 'tokens', 'coin', 'coins', 'wallet'],
17
+ categories: ['cryptocurrency', 'currency exchange', 'finance', 'financial'],
18
+ categoryWeights: { cryptocurrency: 16, 'currency exchange': 5, finance: 3, financial: 3 },
19
+ boostTerms: ['crypto', 'cryptocurrency', 'bitcoin', 'ethereum', 'blockchain', 'defi', 'token', 'coin', 'exchange', 'price', 'market'],
20
+ weakTerms: ['price', 'prices'],
21
+ },
22
+ finance: {
23
+ triggers: ['stock', 'stocks', 'equity', 'equities', 'market', 'trading', 'ticker', 'tickers', 'quote', 'quotes', 'etf', 'forex', 'portfolio'],
24
+ categories: ['finance', 'financial', 'currency exchange'],
25
+ categoryWeights: { finance: 14, financial: 14, 'currency exchange': 5 },
26
+ boostTerms: ['stock', 'stocks', 'equity', 'market', 'trading', 'ticker', 'quote', 'quotes', 'forex', 'portfolio'],
27
+ weakTerms: ['quote', 'quotes', 'price', 'prices', 'market'],
28
+ },
29
+ };
30
+
31
+ function detectDomains(queryTokens) {
32
+ return Object.entries(DOMAIN_PROFILES)
33
+ .filter(([, profile]) => profile.triggers.some(t => queryTokens.has(t)))
34
+ .map(([name]) => name);
35
+ }
36
+
37
+ function domainAdjustment(entry, queryTokens) {
38
+ const domains = detectDomains(queryTokens);
39
+ if (!domains.length) return 0;
40
+ const cat = String(entry.category || '').toLowerCase();
41
+ const text = `${entry.name || ''} ${entry.description || ''} ${entry.provider || ''}`.toLowerCase();
42
+ let adjustment = 0;
43
+ for (const domain of domains) {
44
+ const profile = DOMAIN_PROFILES[domain];
45
+ let categoryBoost = 0;
46
+ for (const [category, weight] of Object.entries(profile.categoryWeights || {})) {
47
+ if (cat.includes(category)) categoryBoost = Math.max(categoryBoost, weight);
48
+ }
49
+ const categoryHit = categoryBoost > 0;
50
+ const textHit = profile.boostTerms.some(t => text.includes(t));
51
+ if (categoryHit) adjustment += categoryBoost;
52
+ else if (textHit) adjustment += 3;
53
+ else adjustment -= 10;
54
+ for (const weak of profile.weakTerms) {
55
+ if (queryTokens.has(weak) && text.includes(weak) && !categoryHit && !textHit) adjustment -= 4;
56
+ }
57
+ }
58
+ return adjustment;
59
+ }
60
+
61
+
14
62
  function usage() {
15
63
  console.log(`public-api-finder — multi-source public API discovery for agents
16
64
 
@@ -84,7 +132,7 @@ function score(entry, queryTokens) {
84
132
  if (entry.sources?.length > 1) base += 2;
85
133
  if (entry.auth === 'No') base += 1;
86
134
  if (entry.https) base += 1;
87
- return base;
135
+ return base + domainAdjustment(entry, queryTokens);
88
136
  }
89
137
 
90
138
  async function cacheIsFresh() {
@@ -279,6 +327,7 @@ function filterEntries(entries, args) {
279
327
  const matched = q.size ? textScore(e, q) : 1;
280
328
  if (q.size && matched === 0) return [];
281
329
  const s = q.size ? score(e, q) : 1;
330
+ if (q.size && s <= 0) return [];
282
331
  return [{ ...e, score: s + (e.sourceWeight || 0) }];
283
332
  }).sort((a, b) => b.score - a.score || String(a.category).localeCompare(String(b.category)) || String(a.name).localeCompare(String(b.name))).slice(0, args.limit);
284
333
  }