apiforge-analyzer 1.3.7 → 1.3.8
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 +66 -2
- package/dist/cjs/cli.js +762 -0
- package/dist/cjs/detect.js +48 -0
- package/dist/cjs/frameworks/python-introspect.js +555 -0
- package/dist/cjs/frameworks/python.js +209 -0
- package/dist/cjs/index.js +16 -1
- package/dist/esm/cli.js +764 -2
- package/dist/esm/detect.js +47 -1
- package/dist/esm/frameworks/python-introspect.js +552 -0
- package/dist/esm/frameworks/python.js +171 -0
- package/dist/esm/index.js +15 -1
- package/dist/types/detect.d.ts +12 -1
- package/dist/types/frameworks/python-introspect.d.ts +18 -0
- package/dist/types/frameworks/python.d.ts +52 -0
- package/dist/types/index.d.ts +11 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# apiforge-analyzer
|
|
2
2
|
|
|
3
|
-
CLI and library for auto-generating API documentation from live Express, Fastify, NestJS, Next.js, Vite, and React Router apps.
|
|
3
|
+
CLI and library for auto-generating API documentation from live Express, Fastify, NestJS, Next.js, Vite, and React Router apps — and Python FastAPI, Flask, and Django apps.
|
|
4
4
|
|
|
5
5
|
Routes are extracted at runtime by walking the framework's internal route stack — no static analysis, no decorators, no changes to your production code.
|
|
6
6
|
|
|
@@ -260,6 +260,64 @@ await analyzeReactRouter({
|
|
|
260
260
|
})
|
|
261
261
|
```
|
|
262
262
|
|
|
263
|
+
### Python — FastAPI, Flask, Django / DRF
|
|
264
|
+
|
|
265
|
+
Run `npx apiforge` from the Python project root (Node ≥ 18 is still needed to run the CLI).
|
|
266
|
+
The project is recognised from `manage.py` or from `fastapi` / `flask` / `django` in
|
|
267
|
+
`requirements.txt`, `pyproject.toml`, `Pipfile`, `setup.py`, or `setup.cfg`.
|
|
268
|
+
|
|
269
|
+
It works like the Node flow. The CLI:
|
|
270
|
+
|
|
271
|
+
1. Finds the file to patch: the module that creates the app (`main.py`, the Flask `create_app` module), or
|
|
272
|
+
Django's `manage.py`.
|
|
273
|
+
2. Checks that the framework is installed. If it isn't, it offers to create `.venv` and `pip install` the
|
|
274
|
+
project's dependencies from `requirements.txt`, `setup.py`/`pyproject.toml` (`pip install -e .`), or a
|
|
275
|
+
bare `pyproject.toml` dependency list. This is the `npm install` step, done for you.
|
|
276
|
+
3. Asks which command starts your server, like the npm-script picker:
|
|
277
|
+
- FastAPI: `fastapi dev`, `fastapi run`, `uvicorn main:app`, `python main.py`
|
|
278
|
+
- Flask: `flask --app app run`, `python app.py`
|
|
279
|
+
- Django: `manage.py runserver --noreload`, `manage.py runserver`
|
|
280
|
+
|
|
281
|
+
You can also type your own. All of these use the project's venv Python.
|
|
282
|
+
4. Adds a temporary snippet to that file and runs the command. The snippet reads the routes as soon as
|
|
283
|
+
the app is loaded, before the server binds its port.
|
|
284
|
+
5. If the server crashes with `No module named 'x'`, offers to install the package and retry. Only packages
|
|
285
|
+
the project declares (including extras such as `[test]`) or well-known import≠pip names (`jose` →
|
|
286
|
+
`python-jose`) are offered.
|
|
287
|
+
6. Stops the server and uploads the routes. At the end it asks "Remove APIForge code changes?", like the
|
|
288
|
+
Node flow. Ctrl+C removes the snippet immediately.
|
|
289
|
+
|
|
290
|
+
The snippet holds no API key and does nothing unless the CLI runs it: it needs an `APIFORGE_INTROSPECT`
|
|
291
|
+
environment variable that only the CLI sets. It writes routes to a temp file outside the project, and the
|
|
292
|
+
CLI uploads them. If you keep the snippet, it does nothing on its own, and the next run replaces it.
|
|
293
|
+
Because your own start command runs, the server needs what it normally needs, such as env vars like a
|
|
294
|
+
database URL. If it fails, the CLI shows the last lines of its output, where Python prints the actual error.
|
|
295
|
+
|
|
296
|
+
The routes are read from the framework's live route table:
|
|
297
|
+
|
|
298
|
+
| Framework | Source of truth |
|
|
299
|
+
|---|---|
|
|
300
|
+
| FastAPI | `app.openapi()`, which gives real Pydantic types for params, bodies, and responses. It also picks up dependency names, `HTTPException` codes raised in handlers, and `app.mount()` sub-apps. |
|
|
301
|
+
| Flask | `app.url_map` plus each view's source: `request.args`, `request.get_json()`, `abort()`, decorators. Blueprints and `MethodView` are supported. |
|
|
302
|
+
| Django | The root URLconf resolver, including `path()`/`re_path()`, class-based views, DRF ViewSets/routers, `@api_view`, serializers, and `permission_classes`. Admin and DRF login URLs are skipped. |
|
|
303
|
+
|
|
304
|
+
The suggested commands use `APIFORGE_PYTHON`, else the active virtualenv, else `.venv/`, `venv/` or `env/`
|
|
305
|
+
in the project, else the system `python`. That interpreter must have the app's dependencies installed.
|
|
306
|
+
|
|
307
|
+
Programmatic use from Node doesn't inject anything or start a server. It imports the app with that same
|
|
308
|
+
interpreter and reads the route table directly:
|
|
309
|
+
|
|
310
|
+
```ts
|
|
311
|
+
import { analyze } from 'apiforge-analyzer'
|
|
312
|
+
|
|
313
|
+
await analyze(null, {
|
|
314
|
+
projectName: 'My API',
|
|
315
|
+
framework: 'fastapi', // or 'flask' / 'django' — auto-detected when omitted
|
|
316
|
+
pythonApp: 'main:app', // Flask factory: 'app:create_app' + pythonFactory: true
|
|
317
|
+
// djangoSettings: 'mysite.settings', // Django: defaults to the one manage.py sets
|
|
318
|
+
})
|
|
319
|
+
```
|
|
320
|
+
|
|
263
321
|
## Options
|
|
264
322
|
|
|
265
323
|
```ts
|
|
@@ -288,12 +346,18 @@ interface AnalyzerOptions {
|
|
|
288
346
|
errorCatalogPath?: string
|
|
289
347
|
envelopes?: Record<string, { wrapper: string; dataField: string; excluded?: string[] } | { bare: true }>
|
|
290
348
|
annotationsPath?: string
|
|
349
|
+
|
|
350
|
+
// Python only — see "Python" above
|
|
351
|
+
pythonApp?: string // app import path, e.g. 'main:app' (auto-detected when omitted)
|
|
352
|
+
pythonFactory?: boolean // call pythonApp as a factory (Flask create_app)
|
|
353
|
+
pythonPath?: string // interpreter (default: APIFORGE_PYTHON / active venv / project venv)
|
|
354
|
+
djangoSettings?: string // e.g. 'mysite.settings' (default: read from manage.py)
|
|
291
355
|
}
|
|
292
356
|
```
|
|
293
357
|
|
|
294
358
|
`analyze()` throws instead of resolving to `[]` when the detected or forced framework has no
|
|
295
359
|
analyzer (currently: anything other than `express`, `fastify`, `nestjs`, `nextjs-pages`,
|
|
296
|
-
`nextjs-app`, `vite`, `react-router`). Every other early-exit (no API key, debounced, zero
|
|
360
|
+
`nextjs-app`, `vite`, `react-router`, `fastapi`, `flask`, `django`). Every other early-exit (no API key, debounced, zero
|
|
297
361
|
routes found, `NODE_ENV=production`) still resolves to `[]` — only "this framework cannot be
|
|
298
362
|
analyzed" is a thrown error, so a caller can tell the two apart. `detectFramework()` also
|
|
299
363
|
exposes this directly: `detectFramework(app).supported` is `false` for a framework it can
|