Skip to content
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
- Fixed Express route mapping for aliased Router imports that follow block comment banners, thanks @rohitjavvadi.
- Fixed Laravel route mapping to include array-style `Route::group` prefixes, thanks @rohitjavvadi.
- Fixed Fastify route-object mapping to emit static method arrays while ignoring dynamic entries, thanks @rohitjavvadi.
- Fixed Fastify plugin callback route mapping for typed parameters and plugin aliases, thanks @rohitjavvadi.
- Fixed Bun package-manager detection to recognize the text `bun.lock` lockfile, thanks @austinm911.

## 0.3.0 - 2026-05-18
Expand Down
143 changes: 143 additions & 0 deletions src/mapper.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2408,12 +2408,131 @@ describe("mapFeatures", () => {
root,
"src/fastify-plugin.ts",
[
"import fastifyPlugin from 'fastify-plugin';",
"import fp from 'fastify-plugin';",
"import cjsPlugin = require('fastify-plugin');",
"import { FastifyInstance } from 'fastify';",
"import type { FastifyInstance as FastifyApp } from 'fastify';",
"",
"export async function routes(fastify: FastifyInstance) {",
" fastify.get('/plugin-users', listPluginUsers);",
"}",
"export async function appRoutes(app: FastifyInstance) {",
" app.get('/plugin-app-users', listPluginAppUsers);",
"}",
"export async function typedReturnRoutes(app: FastifyInstance): Promise<void> {",
" app.get('/plugin-typed-return-users', listPluginTypedReturnUsers);",
"}",
"export async function typedObjectReturnRoutes(app: FastifyInstance): Promise<{ ok: true }> {",
" app.get('/plugin-typed-object-return-users', listPluginTypedObjectReturnUsers);",
"}",
"export async function aliasedTypeRoutes(app: FastifyApp) {",
" app.get('/plugin-aliased-type-users', listPluginAliasedTypeUsers);",
"}",
"const app = createHttpServer();",
"app.get('/not-plugin-app-typed', ignoredApp);",
"export const serverRoutes = fastifyPlugin(async function routes(server) {",
" server.get('/plugin-server-users', listPluginServerUsers);",
"});",
"export const serverReturnRoutes = fastifyPlugin(function routes(server): Promise<void> {",
" server.get('/plugin-server-return-users', listPluginServerReturnUsers);",
"});",
"export const arrowRoutes = fastifyPlugin(async (app) => {",
" app.get('/plugin-arrow-users', listPluginArrowUsers);",
"});",
"export const bareArrowRoutes = fastifyPlugin(async bareApp => {",
" bareApp.get('/plugin-bare-arrow-users', listPluginBareArrowUsers);",
"});",
"export const instanceRoutes = fp(async (instance, options) => {",
" instance.get('/plugin-instance-users', listPluginInstanceUsers);",
" options.get('/not-plugin-options', ignoredOptions);",
"});",
"export const commentRoutes = fp(async (instance) => {",
" // }",
" instance.get('/plugin-comment-users', listPluginCommentUsers);",
"});",
"export const commentedArgumentRoutes = fp( /* routes */ async (commentedApp) => {",
" commentedApp.get('/plugin-commented-argument-users', listPluginCommentedArgumentUsers);",
"});",
"export const aliasedRoutes = fp(async (app) => {",
" app.get('/plugin-aliased-users', listPluginAliasedUsers);",
"});",
"type PluginOptions = { prefix: string };",
"export const genericRoutes = fastifyPlugin<PluginOptions>(async (server) => {",
" server.get('/plugin-generic-users', listPluginGenericUsers);",
"});",
"export const importEqualsRoutes = cjsPlugin(async (server) => {",
" server.get('/plugin-import-equals-users', listPluginImportEqualsUsers);",
"});",
"const defaultPlugin = require('fastify-plugin').default;",
"export const defaultRequireRoutes = defaultPlugin(async (app) => {",
" app.get('/plugin-default-require-users', listPluginDefaultRequireUsers);",
"});",
"export const typedArrowRoutes = async (server: FastifyInstance): Promise<void> => {",
" server.get('/plugin-typed-arrow-users', listPluginTypedArrowUsers);",
"};",
"const server = createHttpServer();",
"server.get('/not-plugin-server', ignoredServer);",
'export async function inlineRoutes(inlineApp: import("fastify").FastifyInstance) {',
' inlineApp.get("/plugin-inline-users", listPluginInlineUsers);',
"}",
'export const inlineArrowRoutes = async (inlineServer: import("fastify").FastifyInstance): Promise<void> => {',
' inlineServer.get("/plugin-inline-arrow-users", listPluginInlineArrowUsers);',
"};",
"function listPluginUsers() {}",
"function listPluginAppUsers() {}",
"function listPluginTypedReturnUsers() {}",
"function listPluginTypedObjectReturnUsers() {}",
"function listPluginAliasedTypeUsers() {}",
"function listPluginServerUsers() {}",
"function listPluginServerReturnUsers() {}",
"function listPluginArrowUsers() {}",
"function listPluginBareArrowUsers() {}",
"function listPluginInstanceUsers() {}",
"function listPluginCommentUsers() {}",
"function listPluginCommentedArgumentUsers() {}",
"function listPluginAliasedUsers() {}",
"function listPluginGenericUsers() {}",
"function listPluginImportEqualsUsers() {}",
"function listPluginDefaultRequireUsers() {}",
"function listPluginTypedArrowUsers() {}",
"function listPluginInlineUsers() {}",
"function listPluginInlineArrowUsers() {}",
"function createHttpServer() { return { get() {} }; }",
"function ignoredApp() {}",
"function ignoredServer() {}",
"function ignoredOptions() {}",
"",
].join("\n"),
);
await writeFixture(
root,
"src/fastify-multiline-import.ts",
[
"import {",
" FastifyInstance,",
"} from 'fastify';",
"",
"export async function multilineRoutes(app: FastifyInstance) {",
" app.get('/plugin-multiline-users', listPluginMultilineUsers);",
"}",
"function listPluginMultilineUsers() {}",
"",
].join("\n"),
);
await writeFixture(
root,
"src/not-fastify-plugin.ts",
[
'import { FastifyInstance } from "./types"',
'import Fastify from "fastify"',
"export async function genericAppRoutes(app) {",
' app.get("/not-plugin-app", ignored);',
"}",
"export async function shadowInstanceRoutes(instance: FastifyInstance) {",
' instance.get("/shadow-fastify-instance", ignored);',
"}",
"function ignored() {}",
"",
].join("\n"),
);
Expand Down Expand Up @@ -2585,6 +2704,25 @@ describe("mapFeatures", () => {
"Fastify route GET /route-status",
"Fastify route POST /webhook/github",
"Fastify route GET /plugin-users",
"Fastify route GET /plugin-app-users",
"Fastify route GET /plugin-typed-return-users",
"Fastify route GET /plugin-typed-object-return-users",
"Fastify route GET /plugin-aliased-type-users",
"Fastify route GET /plugin-server-users",
"Fastify route GET /plugin-server-return-users",
"Fastify route GET /plugin-arrow-users",
"Fastify route GET /plugin-bare-arrow-users",
"Fastify route GET /plugin-instance-users",
"Fastify route GET /plugin-comment-users",
"Fastify route GET /plugin-commented-argument-users",
"Fastify route GET /plugin-aliased-users",
"Fastify route GET /plugin-generic-users",
"Fastify route GET /plugin-import-equals-users",
"Fastify route GET /plugin-default-require-users",
"Fastify route GET /plugin-typed-arrow-users",
"Fastify route GET /plugin-inline-users",
"Fastify route GET /plugin-inline-arrow-users",
"Fastify route GET /plugin-multiline-users",
"Hono route GET /api/items",
"Hono route DELETE /sessions/:id",
]),
Expand All @@ -2607,6 +2745,11 @@ describe("mapFeatures", () => {
expect(titles).not.toContain("Express route GET /assigned-not-router");
expect(titles).not.toContain("Express route GET /dynamic/");
expect(titles).not.toContain("Fastify route GET /dynamic/");
expect(titles).not.toContain("Fastify route GET /not-plugin-app");
expect(titles).not.toContain("Fastify route GET /not-plugin-app-typed");
expect(titles).not.toContain("Fastify route GET /not-plugin-server");
expect(titles).not.toContain("Fastify route GET /not-plugin-options");
expect(titles).not.toContain("Fastify route GET /shadow-fastify-instance");
expect(titles).not.toContain("Fastify route GET /concat-");
expect(titles).not.toContain("Express route DELETE /reports");
expect(admin?.source).toBe("express-route");
Expand Down
Loading