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.
Files changed (2) hide show
  1. package/cli/index.js +62 -37
  2. 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 { findProjectForDir } = await import('../core/projects-store.js');
29
- const match = findProjectForDir(process.cwd());
30
- if (match) {
31
- const { loadEnvironments } = await import('../core/env-resolver.js');
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 { findProjectForDir } = await import('../core/projects-store.js');
41
- const { discoverSpec } = await import('../core/spec-discovery.js');
42
- const { parseSpec, extractEndpoints } = await import('../core/spec-parser.js');
43
- const match = findProjectForDir(process.cwd());
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 positionals = args.slice(2).filter(a => !a.startsWith('-'));
59
- if (positionals.length <= 1) {
60
- METHODS.forEach(m => console.log(m));
61
- handled = true;
62
- } else if (positionals.length === 2) {
63
- const { findProjectForDir } = await import('../core/projects-store.js');
64
- const { discoverSpec } = await import('../core/spec-discovery.js');
65
- const { parseSpec, extractEndpoints } = await import('../core/spec-parser.js');
66
- const match = findProjectForDir(process.cwd());
67
- const result = match ? await discoverSpec(match.path) : await discoverSpec(process.cwd());
68
- const specPath = result?.specPath || result;
69
- if (specPath) {
70
- const spec = await parseSpec(specPath);
71
- const endpoints = extractEndpoints(spec);
72
- const method = positionals[0]?.toUpperCase();
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 {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "apigrip",
3
- "version": "0.6.1",
3
+ "version": "0.6.2",
4
4
  "description": "A spec-first, read-only OpenAPI client for developers",
5
5
  "type": "module",
6
6
  "main": "./lib/index.cjs",