apigrip 0.2.3 → 0.3.0

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
@@ -9,8 +9,19 @@ The spec file on disk is the only source of truth. It is never imported, copied,
9
9
  ## Quick start
10
10
 
11
11
  ```bash
12
- npm install
13
- npm start -- --project /path/to/your/api
12
+ # Install globally
13
+ npm install -g apigrip
14
+
15
+ # Bookmark a project and start the UI
16
+ apigrip projects add /path/to/your/api
17
+ apigrip serve
18
+ ```
19
+
20
+ Or run from inside a project directory (auto-detects the spec):
21
+
22
+ ```bash
23
+ cd /path/to/your/api
24
+ apigrip serve
14
25
  ```
15
26
 
16
27
  Open `http://127.0.0.1:3000` in your browser.
@@ -24,7 +35,7 @@ Open `http://127.0.0.1:3000` in your browser.
24
35
 
25
36
  - Browse endpoints from any OpenAPI 2.0, 3.0.x, or 3.1.x spec
26
37
  - Send requests via curl subprocess with full `curl -v` level detail
27
- - Live reload on spec changes, git branch switches, and `$ref` dependency updates
38
+ - Live reload on spec changes, git branch switches, and `$ref` dependency updates (web UI and MCP)
28
39
  - Parameter persistence across restarts (auto-saved per project, per endpoint)
29
40
  - Named environments with `{{ variable }}` syntax resolved at send time
30
41
  - Git status bar showing branch, commit, and dirty/clean state
@@ -37,8 +48,9 @@ Open `http://127.0.0.1:3000` in your browser.
37
48
 
38
49
  ```bash
39
50
  # Start the web UI
40
- apigrip serve # default port 3000
51
+ apigrip serve # loads last bookmarked project
41
52
  apigrip serve --port 8080 --open # custom port, open browser
53
+ apigrip serve --project /path/to/api # explicit project
42
54
 
43
55
  # Send requests from the terminal
44
56
  apigrip send GET /users # basic request
@@ -95,6 +107,8 @@ CLI commands auto-detect the project from the current working directory:
95
107
  3. If cwd contains an OpenAPI spec file, use it directly
96
108
  4. Otherwise, error
97
109
 
110
+ The `serve` command has additional fallbacks: if cwd is a git repo with a spec, it uses that. Otherwise it loads the first bookmarked project. Opening a project in the web UI automatically bookmarks it.
111
+
98
112
  ## Web UI
99
113
 
100
114
  Two-panel layout: request on the left, response on the right.
@@ -103,7 +117,7 @@ Two-panel layout: request on the left, response on the right.
103
117
 
104
118
  **Right panel** -- status badge, timing, response body (pretty-printed), headers, verbose `curl -v` output, copyable curl command.
105
119
 
106
- **Keyboard shortcuts**: `Ctrl+P` (command palette), `Ctrl+O` (open project), `Ctrl+E` (environment editor), `Ctrl+Enter` (send request).
120
+ **Keyboard shortcuts**: `Ctrl+P` (command palette), `Ctrl+O` (open project), `Ctrl+E` (environment editor), `Ctrl+Enter` (send request), `Ctrl+Shift+L` (toggle theme).
107
121
 
108
122
  ## Environments
109
123
 
@@ -183,6 +197,8 @@ Expose the spec to AI coding assistants via the Model Context Protocol:
183
197
 
184
198
  **Resources:** `spec://parsed`, `project://info`
185
199
 
200
+ The MCP server watches the spec file and auto-reloads when it changes, so tools always return current data.
201
+
186
202
  ## Project structure
187
203
 
188
204
  ```
@@ -233,7 +249,7 @@ Config is stored at `$XDG_CONFIG_HOME/apigrip/` (or `~/.config/apigrip/`). Proje
233
249
  npm test
234
250
  ```
235
251
 
236
- Runs 282 tests across 17 test files using Node's built-in test runner (`node --test`). The test suite uses the tool's own OpenAPI spec as a fixture (self-referential testing).
252
+ Runs 741 tests using Node's built-in test runner (`node --test`). The test suite uses the tool's own OpenAPI spec as a fixture (self-referential testing).
237
253
 
238
254
  ## License
239
255
 
@@ -2,6 +2,7 @@ import { parseSpec } from '../../core/spec-parser.js';
2
2
  import { createMcpServer } from '../../mcp/server.js';
3
3
  import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
4
4
  import { resolveProjectContext } from '../resolve-project.js';
5
+ import chokidar from 'chokidar';
5
6
 
6
7
  export async function mcpCommand(argv) {
7
8
  const { projectDir, specPath } = await resolveProjectContext(argv);
@@ -19,7 +20,28 @@ export async function mcpCommand(argv) {
19
20
  process.exit(2);
20
21
  }
21
22
 
22
- const server = await createMcpServer({ projectDir, specPath, spec });
23
+ const state = { projectDir, specPath, spec };
24
+ const server = await createMcpServer(state);
25
+
26
+ // Watch spec file for changes and auto-reload
27
+ const watcher = chokidar.watch(specPath, {
28
+ ignoreInitial: true,
29
+ awaitWriteFinish: { stabilityThreshold: 50, pollInterval: 10 },
30
+ });
31
+
32
+ let reloadTimer = null;
33
+ watcher.on('change', () => {
34
+ if (reloadTimer) clearTimeout(reloadTimer);
35
+ reloadTimer = setTimeout(async () => {
36
+ try {
37
+ state.spec = await parseSpec(specPath);
38
+ console.error(`[apigrip] Spec reloaded`);
39
+ } catch (err) {
40
+ console.error(`[apigrip] Spec reload error: ${err.message}`);
41
+ }
42
+ }, 100);
43
+ });
44
+
23
45
  const transport = new StdioServerTransport();
24
46
  await server.connect(transport);
25
47
  }
@@ -2,6 +2,8 @@ import fs from 'node:fs';
2
2
  import path from 'node:path';
3
3
  import { parseSpec } from '../../core/spec-parser.js';
4
4
  import { createServer } from '../../server/index.js';
5
+ import { createSpecWatcher } from '../../server/spec-watcher.js';
6
+ import { broadcast } from '../../server/routes/events.js';
5
7
  import { findProjectForDir, loadProjects } from '../../core/projects-store.js';
6
8
  import { discoverSpec } from '../../core/spec-discovery.js';
7
9
 
@@ -81,7 +83,12 @@ export async function serveCommand(argv) {
81
83
  console.warn(' Use --no-browse to disable directory listing and project switching.');
82
84
  }
83
85
 
84
- const { app } = createServer({ projectDir, specPath, spec, noBrowse });
86
+ const { app, state } = createServer({ projectDir, specPath, spec, noBrowse });
87
+
88
+ // Start file watcher for live reload
89
+ if (specPath) {
90
+ createSpecWatcher(state, broadcast).catch(() => {});
91
+ }
85
92
 
86
93
  const server = app.listen(port, host, () => {
87
94
  console.log(`Server listening on http://${host}:${port}`);