Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ A Visual Studio Code extension for FastAPI application development. Available on

This extension enhances the FastAPI development experience in Visual Studio Code by providing:

### Endpoint Explorer
### Path Operation Explorer

The Endpoint Explorer provides a hierarchical tree view of all FastAPI routes in your application. You can expand routers to see their associated endpoints, and click on any route to jump directly to its definition in the code. You can also jump to router definitions by right-clicking on a router node.
The Path Operation Explorer provides a hierarchical tree view of all FastAPI routes in your application. You can expand routers to see their associated path operations, and click on any route to jump directly to its definition in the code. You can also jump to router definitions by right-clicking on a router node.

![Endpoint Explorer GIF](media/walkthrough/endpoints.gif)
![Path Operation Explorer GIF](media/walkthrough/path-operations.gif)

### Search for routes

Expand Down
4 changes: 2 additions & 2 deletions TELEMETRY.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ This disables only the FastAPI extension's telemetry while leaving other telemet

We collect anonymous usage metrics to improve the extension. We do **not** collect:
- File paths or file contents
- Route paths or endpoint names
- Route paths or path operation names
- Any code from your project
- IP addresses (geo-IP is disabled)

Expand All @@ -42,7 +42,7 @@ We collect anonymous usage metrics to improve the extension. We do **not** colle
| Extension deactivated | Session duration (time from activation to deactivation) | Helps us understand how long users keep VS Code open with the extension active |
| Activation failed | Error category (e.g., "parse_error", "wasm_load_error"), failure stage | Helps us debug issues users encounter |
| Entrypoint detected | Detection duration, method used (config/pyproject/heuristic), success/failure, routes and routers count | Helps us understand which detection methods work best |
| Tree view visible | _(none)_ | Know if users see the endpoint explorer |
| Tree view visible | _(none)_ | Know if users see the path operation explorer |
| Search executed | Number of results, whether user selected a result | Helps us understand search usage |
| CodeLens provided | Number of test calls found, number matched to routes | Helps us understand CodeLens effectiveness |
| Routes navigated | Count of navigations (cumulative) | Helps us understand feature usage depth |
Expand Down
56 changes: 28 additions & 28 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@
],
"commands": [
{
"command": "fastapi-vscode.refreshEndpoints",
"title": "Refresh Endpoints",
"command": "fastapi-vscode.refreshPathOperations",
"title": "Refresh Path Operations",
"category": "FastAPI",
"icon": "$(refresh)"
},
Expand All @@ -52,8 +52,8 @@
"icon": "$(fold)"
},
{
"command": "fastapi-vscode.copyEndpointPath",
"title": "Copy Endpoint Path",
"command": "fastapi-vscode.copyPathOperationPath",
"title": "Copy Path to Path Operation",
"category": "FastAPI"
},
{
Expand All @@ -67,8 +67,8 @@
"category": "FastAPI"
},
{
"command": "fastapi-vscode.searchEndpoints",
"title": "Search Endpoints...",
"command": "fastapi-vscode.searchPathOperations",
"title": "Search Path Operations...",
"category": "FastAPI",
"icon": "$(search)"
},
Expand Down Expand Up @@ -105,15 +105,15 @@
],
"keybindings": [
{
"command": "fastapi-vscode.searchEndpoints",
"command": "fastapi-vscode.searchPathOperations",
"key": "ctrl+shift+e",
"mac": "cmd+shift+e"
}
],
"menus": {
"commandPalette": [
{
"command": "fastapi-vscode.copyEndpointPath",
"command": "fastapi-vscode.copyPathOperationPath",
"when": "false"
},
{
Expand Down Expand Up @@ -147,25 +147,25 @@
],
"view/title": [
{
"command": "fastapi-vscode.refreshEndpoints",
"when": "view == endpoint-explorer",
"command": "fastapi-vscode.refreshPathOperations",
"when": "view == path-operation-explorer",
"group": "navigation@1"
},
{
"command": "fastapi-vscode.toggleRouters",
"when": "view == endpoint-explorer",
"when": "view == path-operation-explorer",
"group": "navigation@2"
}
],
"view/item/context": [
{
"command": "fastapi-vscode.copyEndpointPath",
"when": "view == endpoint-explorer && viewItem == route",
"command": "fastapi-vscode.copyPathOperationPath",
"when": "view == path-operation-explorer && viewItem == route",
"group": "navigation"
},
{
"command": "fastapi-vscode.goToRouter",
"when": "view == endpoint-explorer && viewItem == router",
"when": "view == path-operation-explorer && viewItem == router",
"group": "navigation"
}
]
Expand All @@ -189,8 +189,8 @@
"views": {
"fastapi": [
{
"id": "endpoint-explorer",
"name": "Endpoint Explorer",
"id": "path-operation-explorer",
"name": "Path Operation Explorer",
"icon": "media/icons/logo-outline.svg"
}
],
Expand All @@ -205,7 +205,7 @@
},
"viewsWelcome": [
{
"view": "endpoint-explorer",
"view": "path-operation-explorer",
"contents": "No FastAPI apps found in this workspace.\n\n[Configure Entry Point](command:workbench.action.openSettings?[\"fastapi.entryPoint\"])\n\n[Open Getting Started](command:workbench.action.openWalkthrough?{\"category\":\"FastAPILabs.fastapi-vscode#fastapi-getting-started\"})"
}
],
Expand All @@ -217,27 +217,27 @@
"icon": "media/icons/logo-teal.svg",
"steps": [
{
"id": "view-endpoints",
"title": "View Your API Endpoints",
"description": "Open the Endpoint Explorer in the Activity Bar (⚡) to see all routes in your FastAPI application.\n[Open Endpoint Explorer](command:endpoint-explorer.focus)",
"id": "view-path-operations",
"title": "View Your Path Operations",
"description": "Open the Path Operation Explorer in the Activity Bar (⚡) to see all routes in your FastAPI application.\n[Open Path Operation Explorer](command:path-operation-explorer.focus)",
"media": {
"image": "media/walkthrough/endpoints.gif",
"altText": "Endpoint Explorer showing FastAPI routes organized by router"
"image": "media/walkthrough/path-operations.gif",
"altText": "Path Operation Explorer showing FastAPI routes organized by router"
},
"completionEvents": [
"onView:endpoint-explorer"
"onView:path-operation-explorer"
]
},
{
"id": "search-endpoints",
"title": "Quickly Find Endpoints",
"description": "Instantly filter and navigate to any endpoint in your application.\n[Search Endpoints](command:fastapi-vscode.searchEndpoints)",
"id": "search-path-operations",
"title": "Quickly Find Path Operations",
"description": "Instantly filter and navigate to any path operation in your application.\n[Search Path Operations](command:fastapi-vscode.searchPathOperations)",
"media": {
"image": "media/walkthrough/search.gif",
"altText": "Search endpoints quick pick showing filtered results"
"altText": "Search path operations quick pick showing filtered results"
},
"completionEvents": [
"onCommand:fastapi-vscode.searchEndpoints"
"onCommand:fastapi-vscode.searchPathOperations"
]
},
{
Expand Down
2 changes: 1 addition & 1 deletion src/core/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* Public API for FastAPI endpoint discovery.
* Public API for FastAPI path operation discovery.
* This module can be used independently of VSCode.
*/

Expand Down
34 changes: 17 additions & 17 deletions src/core/pathUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,25 +89,25 @@ export function countSegments(path: string): number {
}

/**
* Checks if a test path matches an endpoint path pattern.
* Checks if a test path matches a path operation path pattern.
* Both paths may contain dynamic segments like {item_id} or {settings.API_V1_STR}
* which match any segment.
*
* Leading dynamic prefixes (like {settings.API_V1_STR}) and query strings are stripped
* before comparison.
*
* Examples:
* pathMatchesEndpoint("/items/123", "/items/{item_id}") -> true
* pathMatchesEndpoint("/items/123/details", "/items/{item_id}") -> false
* pathMatchesEndpoint("/users/abc/posts/456", "/users/{user_id}/posts/{post_id}") -> true
* pathMatchesEndpoint("/items/", "/items/{item_id}") -> false
* pathMatchesEndpoint("{settings.API}/apps/{id}", "/apps/{app_id}") -> true
* pathMatchesEndpoint("{BASE}/users/{id}", "/users/{user_id}") -> true
* pathMatchesEndpoint("/teams/?owner=true", "/teams") -> true (query string stripped)
* pathMatchesPathOperation("/items/123", "/items/{item_id}") -> true
* pathMatchesPathOperation("/items/123/details", "/items/{item_id}") -> false
* pathMatchesPathOperation("/users/abc/posts/456", "/users/{user_id}/posts/{post_id}") -> true
* pathMatchesPathOperation("/items/", "/items/{item_id}") -> false
* pathMatchesPathOperation("{settings.API}/apps/{id}", "/apps/{app_id}") -> true
* pathMatchesPathOperation("{BASE}/users/{id}", "/users/{user_id}") -> true
* pathMatchesPathOperation("/teams/?owner=true", "/teams") -> true (query string stripped)
*/
export function pathMatchesEndpoint(
export function pathMatchesPathOperation(
testPath: string,
endpointPath: string,
pathOperationPath: string,
): boolean {
// Strip query string from test path (e.g., "/teams/?owner=true" -> "/teams/")
const testPathWithoutQuery = testPath.split("?")[0]
Expand All @@ -116,26 +116,26 @@ export function pathMatchesEndpoint(
const testSegments = stripLeadingDynamicSegments(testPathWithoutQuery)
.split("/")
.filter(Boolean)
const endpointSegments = stripLeadingDynamicSegments(endpointPath)
const pathOperationSegments = stripLeadingDynamicSegments(pathOperationPath)
.split("/")
.filter(Boolean)

// Segment counts must match
if (testSegments.length !== endpointSegments.length) {
if (testSegments.length !== pathOperationSegments.length) {
return false
}

// Compare each segment positionally
return testSegments.every((testSeg, i) => {
const endpointSeg = endpointSegments[i]
const pathOperationSeg = pathOperationSegments[i]
// Dynamic segments (e.g., {id}, {app.id}) match any value
const testIsDynamic = testSeg.startsWith("{") && testSeg.endsWith("}")
const endpointIsDynamic =
endpointSeg.startsWith("{") && endpointSeg.endsWith("}")
if (testIsDynamic || endpointIsDynamic) {
const pathOperationIsDynamic =
pathOperationSeg.startsWith("{") && pathOperationSeg.endsWith("}")
if (testIsDynamic || pathOperationIsDynamic) {
return true
}
return testSeg === endpointSeg
return testSeg === pathOperationSeg
})
}

Expand Down
2 changes: 1 addition & 1 deletion src/core/types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* Public API types for FastAPI endpoint discovery.
* Public API types for FastAPI path operation discovery.
*/

export type HTTPMethod =
Expand Down
Loading
Loading