@builtbyecho/public-api-finder 0.5.5 → 0.5.6

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 (2) hide show
  1. package/package.json +1 -1
  2. package/src/cli.js +50 -3
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@builtbyecho/public-api-finder",
3
- "version": "0.5.5",
3
+ "version": "0.5.6",
4
4
  "description": "Find free/public APIs for agents and prototypes.",
5
5
  "type": "module",
6
6
  "bin": {
package/src/cli.js CHANGED
@@ -9,10 +9,11 @@ const SOURCES = {
9
9
  publicApiLists: 'https://public-api-lists.github.io/public-api-lists/api/all.json',
10
10
  publicApisReadme: 'https://raw.githubusercontent.com/public-apis/public-apis/master/README.md',
11
11
  apisGuru: 'https://api.apis.guru/v2/list.json',
12
+ apiMegaList: 'https://raw.githubusercontent.com/cporter202/API-mega-list/main/README.md',
12
13
  };
13
14
  const CACHE_PATH = process.env.PUBLIC_API_FINDER_CACHE || join(homedir(), '.cache', 'public-api-finder', 'all.json');
14
15
  const CACHE_TTL_MS = 24 * 60 * 60 * 1000;
15
- const DATA_VERSION = 14;
16
+ const DATA_VERSION = 15;
16
17
 
17
18
  const ENRICHMENT_FIELDS = [
18
19
  'tags',
@@ -683,7 +684,7 @@ Usage:
683
684
 
684
685
  Options:
685
686
  --category <name> Filter by category substring
686
- --source <name> Filter by source: public-api-lists, public-apis, apis-guru, curated
687
+ --source <name> Filter by source: public-api-lists, public-apis, apis-guru, api-mega-list, curated
687
688
  --no-auth Only APIs with Auth = No
688
689
  --https Only HTTPS APIs
689
690
  --cors <value> Filter by CORS: Yes, No, Unknown
@@ -835,6 +836,10 @@ function intentPenalty(entry, queryText) {
835
836
  if (/\b(favicon|website preview|open graph|link preview|screenshot)\b/.test(queryText) && !/\b(microlink|urlbox|favicon|website metadata|open graph|link preview|screenshot)\b/.test(text)) penalty += 120;
836
837
  }
837
838
 
839
+ if (/\b(school district|school boundary|district boundary)\b/.test(queryText) && /\b(linkedin|jobs scraper|lead|sales|recruiting)\b/.test(text)) {
840
+ penalty += 95;
841
+ }
842
+
838
843
  if (!cat.includes('cryptocurrency') && /\b(wallet address|identicon|avatar|profile picture)\b/.test(queryText) && /\b(avatar|identicon|profile picture)\b/.test(text)) {
839
844
  penalty -= 20;
840
845
  }
@@ -926,6 +931,42 @@ function parsePublicApisReadme(readme) {
926
931
  return entries;
927
932
  }
928
933
 
934
+
935
+ function parseApiMegaList(readme) {
936
+ const entries = [];
937
+ let category = '';
938
+ for (const raw of readme.split('\n')) {
939
+ const heading = raw.match(/^##\s+(.+?)\s*$/) || raw.match(/^###\s+(.+?)\s*$/);
940
+ if (heading) {
941
+ const text = heading[1].replace(/[#*_`]/g, '').trim();
942
+ if (text && !/table of contents|repository stats|star this|join my|contributing|license/i.test(text)) category = normalizeCategory(text.replace(/^\d+\.\s*/, ''));
943
+ continue;
944
+ }
945
+ if (!raw.startsWith('| [')) continue;
946
+ const cells = raw.split('|').slice(1, -1).map(c => c.trim());
947
+ if (cells.length < 2) continue;
948
+ if (/^-+$/.test(cells[0]) || /^api name$/i.test(cells[0])) continue;
949
+ const link = cells[0].match(/\[([^\]]+)\]\(([^)]+)\)/);
950
+ if (!link) continue;
951
+ const name = link[1].replace(/<[^>]+>/g, '').trim();
952
+ const url = link[2].trim();
953
+ const description = cleanDescription(cells[1] || `${name} API`);
954
+ if (!name || !/^https?:\/\//i.test(url)) continue;
955
+ entries.push({
956
+ name,
957
+ url,
958
+ description,
959
+ auth: 'Unknown',
960
+ https: /^https:/i.test(url),
961
+ cors: 'Unknown',
962
+ category: category || 'Unknown',
963
+ source: 'api-mega-list',
964
+ sourceWeight: 1,
965
+ });
966
+ }
967
+ return entries;
968
+ }
969
+
929
970
  function parseApisGuru(data) {
930
971
  const entries = [];
931
972
  for (const [providerName, item] of Object.entries(data || {})) {
@@ -950,10 +991,11 @@ function parseApisGuru(data) {
950
991
  }
951
992
 
952
993
  async function buildData() {
953
- const [pal, publicApisReadme, guru] = await Promise.allSettled([
994
+ const [pal, publicApisReadme, guru, megaList] = await Promise.allSettled([
954
995
  fetchJson(SOURCES.publicApiLists),
955
996
  fetchText(SOURCES.publicApisReadme),
956
997
  fetchJson(SOURCES.apisGuru),
998
+ fetchText(SOURCES.apiMegaList),
957
999
  ]);
958
1000
  const entries = [];
959
1001
  const sourceStatus = {};
@@ -971,6 +1013,11 @@ async function buildData() {
971
1013
  sourceStatus['apis-guru'] = rows.length;
972
1014
  entries.push(...rows);
973
1015
  } else sourceStatus['apis-guru'] = `error: ${guru.reason.message}`;
1016
+ if (megaList.status === 'fulfilled') {
1017
+ const rows = parseApiMegaList(megaList.value);
1018
+ sourceStatus['api-mega-list'] = rows.length;
1019
+ entries.push(...rows);
1020
+ } else sourceStatus['api-mega-list'] = `error: ${megaList.reason.message}`;
974
1021
  sourceStatus.curated = ENRICHED_CURATED_APIS.length;
975
1022
  entries.push(...ENRICHED_CURATED_APIS);
976
1023
  const deduped = dedupe(entries).map(enrichApiMetadata);