apigrip 0.6.1 → 0.6.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/cli/index.js +62 -37
- package/package.json +1 -1
package/cli/index.js
CHANGED
|
@@ -14,6 +14,43 @@ if (compIdx !== -1) {
|
|
|
14
14
|
const cmdsWithMethod = ['send', 'curl', 'show', 'last'];
|
|
15
15
|
let handled = false;
|
|
16
16
|
|
|
17
|
+
// Extract --project <name> or --spec <path> from args to resolve the right project
|
|
18
|
+
function getArgValue(flag) {
|
|
19
|
+
const idx = args.indexOf(flag);
|
|
20
|
+
return (idx !== -1 && idx + 1 < args.length) ? args[idx + 1] : null;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// Resolve project dir from --project name, --spec path, or cwd
|
|
24
|
+
async function resolveProjectDir() {
|
|
25
|
+
const { loadProjects, findProjectForDir } = await import('../core/projects-store.js');
|
|
26
|
+
const projectName = getArgValue('--project');
|
|
27
|
+
const specFlag = getArgValue('--spec');
|
|
28
|
+
if (specFlag) {
|
|
29
|
+
const { dirname } = await import('node:path');
|
|
30
|
+
return getArgValue('--project')
|
|
31
|
+
? loadProjects().find(p => p.name === projectName)?.path || process.cwd()
|
|
32
|
+
: dirname(specFlag);
|
|
33
|
+
}
|
|
34
|
+
if (projectName) {
|
|
35
|
+
const match = loadProjects().find(p => p.name === projectName);
|
|
36
|
+
if (match) return match.path;
|
|
37
|
+
}
|
|
38
|
+
const cwdMatch = findProjectForDir(process.cwd());
|
|
39
|
+
return cwdMatch ? cwdMatch.path : process.cwd();
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Discover and parse spec, returning endpoints
|
|
43
|
+
async function resolveEndpoints() {
|
|
44
|
+
const { discoverSpec } = await import('../core/spec-discovery.js');
|
|
45
|
+
const { parseSpec, extractEndpoints } = await import('../core/spec-parser.js');
|
|
46
|
+
const projectDir = await resolveProjectDir();
|
|
47
|
+
const specFlag = getArgValue('--spec');
|
|
48
|
+
const specPath = specFlag || (await discoverSpec(projectDir))?.specPath;
|
|
49
|
+
if (!specPath) return [];
|
|
50
|
+
const spec = await parseSpec(specPath);
|
|
51
|
+
return extractEndpoints(spec);
|
|
52
|
+
}
|
|
53
|
+
|
|
17
54
|
try {
|
|
18
55
|
// --project <TAB> → bookmarked project names
|
|
19
56
|
if (prevArg === '--project') {
|
|
@@ -25,55 +62,43 @@ if (compIdx !== -1) {
|
|
|
25
62
|
|
|
26
63
|
// -e / --env <TAB> → environment names
|
|
27
64
|
if (!handled && (prevArg === '--env' || prevArg === '-e')) {
|
|
28
|
-
const {
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
const envData = loadEnvironments(match.path);
|
|
33
|
-
Object.keys(envData.environments || {}).forEach(n => console.log(n));
|
|
34
|
-
}
|
|
65
|
+
const { loadEnvironments } = await import('../core/env-resolver.js');
|
|
66
|
+
const projectDir = await resolveProjectDir();
|
|
67
|
+
const envData = loadEnvironments(projectDir);
|
|
68
|
+
Object.keys(envData.environments || {}).forEach(n => console.log(n));
|
|
35
69
|
handled = true;
|
|
36
70
|
}
|
|
37
71
|
|
|
38
72
|
// --tag <TAB> → tag names from spec
|
|
39
73
|
if (!handled && prevArg === '--tag') {
|
|
40
|
-
const
|
|
41
|
-
const
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
const result = match ? await discoverSpec(match.path) : await discoverSpec(process.cwd());
|
|
45
|
-
const specPath = result?.specPath || result;
|
|
46
|
-
if (specPath) {
|
|
47
|
-
const spec = await parseSpec(specPath);
|
|
48
|
-
const endpoints = extractEndpoints(spec);
|
|
49
|
-
const tags = new Set();
|
|
50
|
-
endpoints.forEach(e => (e.tags || []).forEach(t => tags.add(t)));
|
|
51
|
-
tags.forEach(t => console.log(t));
|
|
52
|
-
}
|
|
74
|
+
const endpoints = await resolveEndpoints();
|
|
75
|
+
const tags = new Set();
|
|
76
|
+
endpoints.forEach(e => (e.tags || []).forEach(t => tags.add(t)));
|
|
77
|
+
tags.forEach(t => console.log(t));
|
|
53
78
|
handled = true;
|
|
54
79
|
}
|
|
55
80
|
|
|
56
81
|
// Commands with <method> <path>: complete methods, then endpoint paths
|
|
82
|
+
// Use pattern matching (not positional counting) to handle interspersed options
|
|
57
83
|
if (!handled && cmdsWithMethod.includes(cmd)) {
|
|
58
|
-
const
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
const
|
|
64
|
-
const
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
if (
|
|
70
|
-
const
|
|
71
|
-
const
|
|
72
|
-
const
|
|
73
|
-
const filtered = method ? endpoints.filter(e => e.method === method) : endpoints;
|
|
84
|
+
const currentWord = args[args.length - 1] || '';
|
|
85
|
+
// If user is typing an option flag, let yargs handle it
|
|
86
|
+
if (!currentWord.startsWith('-')) {
|
|
87
|
+
// Look at all args except the current word being completed
|
|
88
|
+
const prior = args.slice(2, -1);
|
|
89
|
+
const methodArg = prior.find(a => METHODS.includes(a.toUpperCase()));
|
|
90
|
+
const pathArg = prior.find(a => a.startsWith('/'));
|
|
91
|
+
|
|
92
|
+
if (!methodArg) {
|
|
93
|
+
METHODS.forEach(m => console.log(m));
|
|
94
|
+
handled = true;
|
|
95
|
+
} else if (!pathArg) {
|
|
96
|
+
const endpoints = await resolveEndpoints();
|
|
97
|
+
const method = methodArg.toUpperCase();
|
|
98
|
+
const filtered = endpoints.filter(e => e.method === method);
|
|
74
99
|
filtered.forEach(e => console.log(e.path));
|
|
100
|
+
handled = true;
|
|
75
101
|
}
|
|
76
|
-
handled = true;
|
|
77
102
|
}
|
|
78
103
|
}
|
|
79
104
|
} catch {
|