@ls-apis/cli 0.0.1 → 0.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/data/apis.json +22 -12
- package/package.json +1 -1
- package/dist/packages/cli/src/categories.js +0 -13
- package/dist/packages/cli/src/colors.js +0 -19
- package/dist/packages/cli/src/config.js +0 -36
- package/dist/packages/cli/src/formatter.js +0 -73
- package/dist/packages/cli/src/index.js +0 -178
- package/dist/packages/cli/src/providers.js +0 -21
- package/dist/packages/cli/src/qa.js +0 -14
- package/dist/packages/cli/src/search.js +0 -50
- package/dist/packages/cli/src/types.js +0 -1
package/data/apis.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"timestamp": "2026-05-
|
|
2
|
+
"timestamp": "2026-05-22T08:36:32.009Z",
|
|
3
3
|
"providers": [
|
|
4
4
|
{
|
|
5
5
|
"name": "apis-guru",
|
|
@@ -33973,7 +33973,7 @@
|
|
|
33973
33973
|
"cors": "unknown",
|
|
33974
33974
|
"categories": ["Jobs"],
|
|
33975
33975
|
"openapiSpec": null,
|
|
33976
|
-
"sources": ["github-public-apis"
|
|
33976
|
+
"sources": ["github-public-apis"]
|
|
33977
33977
|
},
|
|
33978
33978
|
{
|
|
33979
33979
|
"name": "Careerjet",
|
|
@@ -40745,6 +40745,16 @@
|
|
|
40745
40745
|
"openapiSpec": null,
|
|
40746
40746
|
"sources": ["publicapis-dev"]
|
|
40747
40747
|
},
|
|
40748
|
+
{
|
|
40749
|
+
"name": "PageBolt",
|
|
40750
|
+
"description": "Screenshot, PDF, video recording, OG image, and page inspection via REST API.",
|
|
40751
|
+
"link": "https://pagebolt.dev/",
|
|
40752
|
+
"auth": "apiKey",
|
|
40753
|
+
"cors": null,
|
|
40754
|
+
"categories": ["Development"],
|
|
40755
|
+
"openapiSpec": null,
|
|
40756
|
+
"sources": ["publicapis-dev"]
|
|
40757
|
+
},
|
|
40748
40758
|
{
|
|
40749
40759
|
"name": "SEO Score",
|
|
40750
40760
|
"description": "Comprehensive SEO audit with 28 checks, scoring, and prioritized recommendations.",
|
|
@@ -40905,16 +40915,6 @@
|
|
|
40905
40915
|
"openapiSpec": null,
|
|
40906
40916
|
"sources": ["publicapis-dev"]
|
|
40907
40917
|
},
|
|
40908
|
-
{
|
|
40909
|
-
"name": "Web Scraping API",
|
|
40910
|
-
"description": "Extract structured data from any public URL.",
|
|
40911
|
-
"link": "https://apyhub.com/utility/sharpapi-web-scraping-api",
|
|
40912
|
-
"auth": "apiKey",
|
|
40913
|
-
"cors": null,
|
|
40914
|
-
"categories": ["Development"],
|
|
40915
|
-
"openapiSpec": null,
|
|
40916
|
-
"sources": ["publicapis-dev"]
|
|
40917
|
-
},
|
|
40918
40918
|
{
|
|
40919
40919
|
"name": "PDFBolt",
|
|
40920
40920
|
"description": "High-quality HTML to PDF conversion with templates and AI generation.",
|
|
@@ -41965,6 +41965,16 @@
|
|
|
41965
41965
|
"openapiSpec": null,
|
|
41966
41966
|
"sources": ["publicapis-dev"]
|
|
41967
41967
|
},
|
|
41968
|
+
{
|
|
41969
|
+
"name": "Himalayas",
|
|
41970
|
+
"description": "Remote job listings with salary, timezone, and location data.",
|
|
41971
|
+
"link": "https://himalayas.app/api",
|
|
41972
|
+
"auth": null,
|
|
41973
|
+
"cors": null,
|
|
41974
|
+
"categories": ["Jobs"],
|
|
41975
|
+
"openapiSpec": null,
|
|
41976
|
+
"sources": ["publicapis-dev"]
|
|
41977
|
+
},
|
|
41968
41978
|
{
|
|
41969
41979
|
"name": "CV - Job match score API",
|
|
41970
41980
|
"description": "This API use multiple criteria to evaluate how well a candidate fits a job position.",
|
package/package.json
CHANGED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { getCategories } from './search.js';
|
|
2
|
-
import { formatList } from './formatter.js';
|
|
3
|
-
import { initColors } from './colors.js';
|
|
4
|
-
export function handleCategories(apis, argv, config) {
|
|
5
|
-
const noColor = argv.color === false;
|
|
6
|
-
initColors(noColor ?? !config.colors);
|
|
7
|
-
const categories = getCategories(apis);
|
|
8
|
-
const output = formatList(categories, 'categories', {
|
|
9
|
-
sort: argv.sort,
|
|
10
|
-
output: argv.output,
|
|
11
|
-
});
|
|
12
|
-
console.log(output);
|
|
13
|
-
}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import chalk from 'chalk';
|
|
2
|
-
let useColor = false;
|
|
3
|
-
export function initColors(noColor) {
|
|
4
|
-
if (noColor === true || process.env.NO_COLOR) {
|
|
5
|
-
useColor = false;
|
|
6
|
-
}
|
|
7
|
-
else {
|
|
8
|
-
useColor = true;
|
|
9
|
-
}
|
|
10
|
-
chalk.level = useColor ? 3 : 0;
|
|
11
|
-
}
|
|
12
|
-
export const color = {
|
|
13
|
-
bold: (text) => (useColor ? chalk.bold(text) : text),
|
|
14
|
-
dim: (text) => (useColor ? chalk.dim(text) : text),
|
|
15
|
-
cyan: (text) => (useColor ? chalk.cyan(text) : text),
|
|
16
|
-
green: (text) => (useColor ? chalk.green(text) : text),
|
|
17
|
-
yellow: (text) => (useColor ? chalk.yellow(text) : text),
|
|
18
|
-
red: (text) => (useColor ? chalk.red(text) : text),
|
|
19
|
-
};
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import { readFile, writeFile, access } from 'node:fs/promises';
|
|
2
|
-
import { homedir } from 'node:os';
|
|
3
|
-
import { join } from 'node:path';
|
|
4
|
-
export const CONFIG_PATH = join(homedir(), '.ls-apis');
|
|
5
|
-
const DEFAULTS = {
|
|
6
|
-
limit: 20,
|
|
7
|
-
descriptionMaxLength: 250,
|
|
8
|
-
colors: true,
|
|
9
|
-
};
|
|
10
|
-
export async function loadConfig() {
|
|
11
|
-
try {
|
|
12
|
-
const raw = await readFile(CONFIG_PATH, 'utf-8');
|
|
13
|
-
const parsed = JSON.parse(raw);
|
|
14
|
-
return {
|
|
15
|
-
limit: parsed.limit ?? DEFAULTS.limit,
|
|
16
|
-
descriptionMaxLength: parsed.descriptionMaxLength ?? DEFAULTS.descriptionMaxLength,
|
|
17
|
-
colors: parsed.colors ?? DEFAULTS.colors,
|
|
18
|
-
};
|
|
19
|
-
}
|
|
20
|
-
catch {
|
|
21
|
-
await ensureConfigExists();
|
|
22
|
-
return DEFAULTS;
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
async function ensureConfigExists() {
|
|
26
|
-
try {
|
|
27
|
-
await access(CONFIG_PATH);
|
|
28
|
-
}
|
|
29
|
-
catch {
|
|
30
|
-
await writeFile(CONFIG_PATH, JSON.stringify(DEFAULTS, null, 2) + '\n');
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
export async function getConfig() {
|
|
34
|
-
const config = await loadConfig();
|
|
35
|
-
return { config, filePath: CONFIG_PATH };
|
|
36
|
-
}
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
import { color } from './colors.js';
|
|
2
|
-
function truncate(text, maxLength) {
|
|
3
|
-
if (text.length <= maxLength) {
|
|
4
|
-
return text;
|
|
5
|
-
}
|
|
6
|
-
return text.slice(0, maxLength) + '...';
|
|
7
|
-
}
|
|
8
|
-
function formatText(results, total, limit, options) {
|
|
9
|
-
const maxLen = options.descriptionMaxLength ?? 250;
|
|
10
|
-
const lines = [];
|
|
11
|
-
lines.push(color.bold(`Found ${total} APIs:`));
|
|
12
|
-
for (const api of results.slice(0, limit)) {
|
|
13
|
-
lines.push(color.cyan(` ${api.name}`));
|
|
14
|
-
lines.push(` ${color.dim('Description:')} ${truncate(api.description ?? 'No description', maxLen)}`);
|
|
15
|
-
lines.push(` ${color.dim('Link:')} ${api.link}`);
|
|
16
|
-
// Test missing braces - should trigger ESLint error
|
|
17
|
-
if (api.auth !== undefined && api.auth !== null) {
|
|
18
|
-
lines.push(` ${color.dim('Auth:')} ${color.yellow(api.auth)}`);
|
|
19
|
-
}
|
|
20
|
-
if (api.categories.length > 0) {
|
|
21
|
-
lines.push(` ${color.dim('Categories:')} ${color.green(api.categories.join(', '))}`);
|
|
22
|
-
}
|
|
23
|
-
if (api.openapiSpec !== undefined && api.openapiSpec !== null) {
|
|
24
|
-
lines.push(` ${color.dim('OpenAPI Spec:')} ${api.openapiSpec}`);
|
|
25
|
-
}
|
|
26
|
-
if (api.sources.length > 0) {
|
|
27
|
-
lines.push(` ${color.dim('Sources:')} ${api.sources.join(', ')}`);
|
|
28
|
-
}
|
|
29
|
-
lines.push('');
|
|
30
|
-
}
|
|
31
|
-
if (results.length > limit) {
|
|
32
|
-
lines.push(` ${color.dim('... and ' + (results.length - limit) + ' more')}`);
|
|
33
|
-
}
|
|
34
|
-
return lines.join('\n');
|
|
35
|
-
}
|
|
36
|
-
function formatJson(results, limit) {
|
|
37
|
-
return JSON.stringify(results.slice(0, limit), null, 2);
|
|
38
|
-
}
|
|
39
|
-
export function formatResults(results, total, limit, options) {
|
|
40
|
-
if (options.output === 'json') {
|
|
41
|
-
return formatJson(results, limit);
|
|
42
|
-
}
|
|
43
|
-
return formatText(results, total, limit, options);
|
|
44
|
-
}
|
|
45
|
-
export function formatList(items, label, options) {
|
|
46
|
-
const sorted = [...items.entries()].sort((a, b) => a[0].localeCompare(b[0]));
|
|
47
|
-
if (options.sort === 'count') {
|
|
48
|
-
sorted.sort((a, b) => b[1] - a[1]);
|
|
49
|
-
}
|
|
50
|
-
if (options.output === 'json') {
|
|
51
|
-
return JSON.stringify(sorted.map(([name, count]) => ({ name, count })), null, 2);
|
|
52
|
-
}
|
|
53
|
-
const lines = [`Found ${sorted.length} ${label}:`];
|
|
54
|
-
for (const [name, count] of sorted) {
|
|
55
|
-
lines.push(` ${name.padEnd(20)} (${count} APIs)`);
|
|
56
|
-
}
|
|
57
|
-
return lines.join('\n');
|
|
58
|
-
}
|
|
59
|
-
export function formatProviders(providers, options) {
|
|
60
|
-
const sorted = [...providers].sort((a, b) => a.name.localeCompare(b.name));
|
|
61
|
-
if (options.sort === 'count') {
|
|
62
|
-
sorted.sort((a, b) => (b.count ?? 0) - (a.count ?? 0));
|
|
63
|
-
}
|
|
64
|
-
if (options.output === 'json') {
|
|
65
|
-
return JSON.stringify(sorted, null, 2);
|
|
66
|
-
}
|
|
67
|
-
const lines = [`Found ${sorted.length} providers:`];
|
|
68
|
-
for (const provider of sorted) {
|
|
69
|
-
const countStr = provider.count !== undefined ? ` (${provider.count} APIs)` : '';
|
|
70
|
-
lines.push(` ${provider.name.padEnd(20)} ${color.dim(provider.url)}${countStr}`);
|
|
71
|
-
}
|
|
72
|
-
return lines.join('\n');
|
|
73
|
-
}
|
|
@@ -1,178 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import { readFile } from 'node:fs/promises';
|
|
3
|
-
import { join, dirname } from 'node:path';
|
|
4
|
-
import { fileURLToPath } from 'node:url';
|
|
5
|
-
import yargs from 'yargs';
|
|
6
|
-
import { hideBin } from 'yargs/helpers';
|
|
7
|
-
import { initColors } from './colors.js';
|
|
8
|
-
import { loadConfig, getConfig } from './config.js';
|
|
9
|
-
import { search } from './search.js';
|
|
10
|
-
import { formatResults } from './formatter.js';
|
|
11
|
-
import { handleCategories } from './categories.js';
|
|
12
|
-
import { handleProviders } from './providers.js';
|
|
13
|
-
import { runQa } from './qa.js';
|
|
14
|
-
let version;
|
|
15
|
-
async function getVersion() {
|
|
16
|
-
if (!version) {
|
|
17
|
-
const packageJsonPath = join(dirname(fileURLToPath(import.meta.url)), '../package.json');
|
|
18
|
-
const pkg = JSON.parse(await readFile(packageJsonPath, 'utf-8'));
|
|
19
|
-
version = pkg.version;
|
|
20
|
-
}
|
|
21
|
-
return version;
|
|
22
|
-
}
|
|
23
|
-
export async function run(argv) {
|
|
24
|
-
const config = await loadConfig();
|
|
25
|
-
const ver = await getVersion();
|
|
26
|
-
const dataFile = join(dirname(fileURLToPath(import.meta.url)), '../data/apis.json');
|
|
27
|
-
const data = await readFile(dataFile, 'utf-8');
|
|
28
|
-
const { apis, providers } = JSON.parse(data);
|
|
29
|
-
let exitEarly = false;
|
|
30
|
-
const args = await yargs(argv)
|
|
31
|
-
.scriptName('ls-apis')
|
|
32
|
-
.strict()
|
|
33
|
-
.version(ver)
|
|
34
|
-
.alias('version', 'V')
|
|
35
|
-
.alias('version', 'v')
|
|
36
|
-
.usage('$0 <command> [options]')
|
|
37
|
-
.usage('$0 [options]')
|
|
38
|
-
.example('$0 -q weather', 'Search for weather APIs')
|
|
39
|
-
.example('$0 -c weather', 'Filter by weather category')
|
|
40
|
-
.example('$0 -q weather -c storage', 'Search weather in storage category')
|
|
41
|
-
.example('$0 -a oauth', 'Filter by OAuth auth')
|
|
42
|
-
.example('$0 -q weather -l 50', 'Limit results to 50')
|
|
43
|
-
.example('$0 -q weather -o json', 'Output as JSON')
|
|
44
|
-
.example('$0 -q weather -s name', 'Sort results by name')
|
|
45
|
-
.command({
|
|
46
|
-
command: 'categories',
|
|
47
|
-
describe: 'List all API categories',
|
|
48
|
-
builder: (yargs) => {
|
|
49
|
-
return yargs
|
|
50
|
-
.option('sort', {
|
|
51
|
-
alias: 's',
|
|
52
|
-
type: 'string',
|
|
53
|
-
choices: ['name', 'count'],
|
|
54
|
-
default: 'name',
|
|
55
|
-
describe: 'Sort by name or count',
|
|
56
|
-
})
|
|
57
|
-
.option('output', {
|
|
58
|
-
alias: 'o',
|
|
59
|
-
type: 'string',
|
|
60
|
-
choices: ['text', 'json'],
|
|
61
|
-
default: 'text',
|
|
62
|
-
describe: 'Output format',
|
|
63
|
-
});
|
|
64
|
-
},
|
|
65
|
-
handler: (argv) => {
|
|
66
|
-
handleCategories(apis, argv, config);
|
|
67
|
-
exitEarly = true;
|
|
68
|
-
},
|
|
69
|
-
})
|
|
70
|
-
.command({
|
|
71
|
-
command: 'providers',
|
|
72
|
-
describe: 'List all data providers',
|
|
73
|
-
builder: (yargs) => {
|
|
74
|
-
return yargs
|
|
75
|
-
.option('sort', {
|
|
76
|
-
alias: 's',
|
|
77
|
-
type: 'string',
|
|
78
|
-
choices: ['name', 'count'],
|
|
79
|
-
default: 'name',
|
|
80
|
-
describe: 'Sort by name or count',
|
|
81
|
-
})
|
|
82
|
-
.option('output', {
|
|
83
|
-
alias: 'o',
|
|
84
|
-
type: 'string',
|
|
85
|
-
choices: ['text', 'json'],
|
|
86
|
-
default: 'text',
|
|
87
|
-
describe: 'Output format',
|
|
88
|
-
});
|
|
89
|
-
},
|
|
90
|
-
handler: (argv) => {
|
|
91
|
-
handleProviders(providers, apis, argv, config);
|
|
92
|
-
exitEarly = true;
|
|
93
|
-
},
|
|
94
|
-
})
|
|
95
|
-
.command({
|
|
96
|
-
command: 'config',
|
|
97
|
-
describe: 'Show config settings',
|
|
98
|
-
handler: async () => {
|
|
99
|
-
const { config, filePath } = await getConfig();
|
|
100
|
-
console.log(`Config file: ${filePath}`);
|
|
101
|
-
console.log(JSON.stringify(config, null, 2));
|
|
102
|
-
exitEarly = true;
|
|
103
|
-
},
|
|
104
|
-
})
|
|
105
|
-
.command({
|
|
106
|
-
command: 'qa',
|
|
107
|
-
describe: 'Run QA validation on apis.json',
|
|
108
|
-
builder: (yargs) => {
|
|
109
|
-
return yargs.option('file', {
|
|
110
|
-
alias: 'f',
|
|
111
|
-
type: 'string',
|
|
112
|
-
describe: 'Custom output file path (default: qa-output/issues.json)',
|
|
113
|
-
});
|
|
114
|
-
},
|
|
115
|
-
handler: async (argv) => {
|
|
116
|
-
await runQa(config.descriptionMaxLength, argv.file);
|
|
117
|
-
exitEarly = true;
|
|
118
|
-
},
|
|
119
|
-
})
|
|
120
|
-
.option('query', {
|
|
121
|
-
alias: 'q',
|
|
122
|
-
type: 'string',
|
|
123
|
-
describe: 'Search query (filters name, description)',
|
|
124
|
-
})
|
|
125
|
-
.option('category', { alias: 'c', type: 'string', describe: 'Filter by category' })
|
|
126
|
-
.option('auth', {
|
|
127
|
-
alias: 'a',
|
|
128
|
-
type: 'string',
|
|
129
|
-
describe: 'Filter by auth (apiKey, OAuth, no)',
|
|
130
|
-
})
|
|
131
|
-
.option('limit', {
|
|
132
|
-
alias: 'l',
|
|
133
|
-
type: 'number',
|
|
134
|
-
default: config.limit,
|
|
135
|
-
describe: 'Max results to show',
|
|
136
|
-
})
|
|
137
|
-
.option('output', {
|
|
138
|
-
alias: 'o',
|
|
139
|
-
type: 'string',
|
|
140
|
-
choices: ['text', 'json'],
|
|
141
|
-
default: 'text',
|
|
142
|
-
describe: 'Output format',
|
|
143
|
-
})
|
|
144
|
-
.option('sort', {
|
|
145
|
-
alias: 's',
|
|
146
|
-
type: 'string',
|
|
147
|
-
choices: ['name', 'category', 'auth'],
|
|
148
|
-
describe: 'Sort results by field',
|
|
149
|
-
})
|
|
150
|
-
.option('no-color', { type: 'boolean', describe: 'Disable colors in output' })
|
|
151
|
-
.help()
|
|
152
|
-
.alias('help', 'h')
|
|
153
|
-
.alias('help', '?')
|
|
154
|
-
.parse();
|
|
155
|
-
if (exitEarly) {
|
|
156
|
-
return;
|
|
157
|
-
}
|
|
158
|
-
const noColor = args.color === false;
|
|
159
|
-
initColors(noColor ?? !config.colors);
|
|
160
|
-
const results = search(apis, {
|
|
161
|
-
query: args.query,
|
|
162
|
-
category: args.category,
|
|
163
|
-
auth: args.auth,
|
|
164
|
-
sort: args.sort,
|
|
165
|
-
limit: args.limit,
|
|
166
|
-
});
|
|
167
|
-
const output = formatResults(results, results.length, args.limit, {
|
|
168
|
-
output: args.output,
|
|
169
|
-
descriptionMaxLength: config.descriptionMaxLength,
|
|
170
|
-
});
|
|
171
|
-
console.log(output);
|
|
172
|
-
}
|
|
173
|
-
if (process.argv[1] && !process.argv[1].includes('vitest')) {
|
|
174
|
-
run(hideBin(process.argv)).catch((err) => {
|
|
175
|
-
console.error('Error:', err.message);
|
|
176
|
-
process.exit(1);
|
|
177
|
-
});
|
|
178
|
-
}
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import { formatProviders } from './formatter.js';
|
|
2
|
-
import { initColors } from './colors.js';
|
|
3
|
-
export function handleProviders(providers, apis, argv, config) {
|
|
4
|
-
const noColor = argv.color === false;
|
|
5
|
-
initColors(noColor ?? !config.colors);
|
|
6
|
-
const counts = new Map();
|
|
7
|
-
for (const api of apis) {
|
|
8
|
-
for (const source of api.sources) {
|
|
9
|
-
counts.set(source, (counts.get(source) ?? 0) + 1);
|
|
10
|
-
}
|
|
11
|
-
}
|
|
12
|
-
const providersWithCounts = providers.map((p) => ({
|
|
13
|
-
...p,
|
|
14
|
-
count: counts.get(p.name) ?? 0,
|
|
15
|
-
}));
|
|
16
|
-
const output = formatProviders(providersWithCounts, {
|
|
17
|
-
sort: argv.sort,
|
|
18
|
-
output: argv.output,
|
|
19
|
-
});
|
|
20
|
-
console.log(output);
|
|
21
|
-
}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { execSync } from 'node:child_process';
|
|
2
|
-
import { join, dirname } from 'node:path';
|
|
3
|
-
import { fileURLToPath } from 'node:url';
|
|
4
|
-
import { realpathSync } from 'node:fs';
|
|
5
|
-
export async function runQa(descriptionMaxLength, outputFile) {
|
|
6
|
-
const currentDir = dirname(realpathSync(fileURLToPath(import.meta.url)));
|
|
7
|
-
const projectRoot = join(currentDir, '../../..');
|
|
8
|
-
const script = join(projectRoot, 'packages/aggregator/src/qa/index.ts');
|
|
9
|
-
const args = ['npx', 'tsx', script];
|
|
10
|
-
if (outputFile) {
|
|
11
|
-
args.push('--output', outputFile);
|
|
12
|
-
}
|
|
13
|
-
execSync(args.join(' '), { cwd: projectRoot, stdio: 'inherit' });
|
|
14
|
-
}
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
export function search(apis, options) {
|
|
2
|
-
let results = apis;
|
|
3
|
-
if (options.query) {
|
|
4
|
-
const q = options.query.toLowerCase();
|
|
5
|
-
results = results.filter((api) => api.name.toLowerCase().includes(q) || api.description?.toLowerCase().includes(q));
|
|
6
|
-
}
|
|
7
|
-
if (options.category) {
|
|
8
|
-
const cat = options.category.toLowerCase();
|
|
9
|
-
results = results.filter((api) => api.categories.some((c) => c.toLowerCase().includes(cat)));
|
|
10
|
-
}
|
|
11
|
-
if (options.auth) {
|
|
12
|
-
const auth = options.auth.toLowerCase();
|
|
13
|
-
results = results.filter((api) => {
|
|
14
|
-
if (auth === 'no') {
|
|
15
|
-
return !api.auth;
|
|
16
|
-
}
|
|
17
|
-
return api.auth?.toLowerCase().includes(auth);
|
|
18
|
-
});
|
|
19
|
-
}
|
|
20
|
-
if (options.sort) {
|
|
21
|
-
results = [...results].sort((a, b) => {
|
|
22
|
-
switch (options.sort) {
|
|
23
|
-
case 'name':
|
|
24
|
-
return a.name.localeCompare(b.name);
|
|
25
|
-
case 'category': {
|
|
26
|
-
const catA = a.categories[0] ?? '';
|
|
27
|
-
const catB = b.categories[0] ?? '';
|
|
28
|
-
return catA.localeCompare(catB);
|
|
29
|
-
}
|
|
30
|
-
case 'auth': {
|
|
31
|
-
const authA = a.auth ?? '';
|
|
32
|
-
const authB = b.auth ?? '';
|
|
33
|
-
return authA.localeCompare(authB);
|
|
34
|
-
}
|
|
35
|
-
default:
|
|
36
|
-
return 0;
|
|
37
|
-
}
|
|
38
|
-
});
|
|
39
|
-
}
|
|
40
|
-
return results;
|
|
41
|
-
}
|
|
42
|
-
export function getCategories(apis) {
|
|
43
|
-
const map = new Map();
|
|
44
|
-
for (const api of apis) {
|
|
45
|
-
for (const cat of api.categories) {
|
|
46
|
-
map.set(cat, (map.get(cat) ?? 0) + 1);
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
return map;
|
|
50
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|