Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -722,6 +722,99 @@ describe("transform", () => {
})
})

describe("aliased import transforms", () => {
it("should transform aliased loader import where local name is loader", () => {
const result = augmentDataFetchingFunctions(
`
import { myLoader as loader } from "./loaders";
export { loader };
`,
"test",
"/file/path"
)
const expected = removeWhitespace(`
import { withLoaderWrapper as _withLoaderWrapper } from "react-router-devtools/server";
import { myLoader as _loader } from "./loaders";
export const loader = _withLoaderWrapper(_loader, "test");
`)
expect(removeWhitespace(result.code)).toStrictEqual(expected)
})

it("should transform aliased action import where local name is action", () => {
const result = augmentDataFetchingFunctions(
`
import { myLoaderAction as action } from "./actions";
export { action };
`,
"test",
"/file/path"
)
const expected = removeWhitespace(`
import { withActionWrapper as _withActionWrapper } from "react-router-devtools/server";
import { myLoaderAction as _action } from "./actions";
export const action = _withActionWrapper(_action, "test");
`)
expect(removeWhitespace(result.code)).toStrictEqual(expected)
})

it("should transform aliased clientLoader import where local name is clientLoader", () => {
const result = augmentDataFetchingFunctions(
`
import { myLoaderClientLoader as clientLoader } from "./loaders";
export { clientLoader };
`,
"test",
"/file/path"
)
const expected = removeWhitespace(`
import { withClientLoaderWrapper as _withClientLoaderWrapper } from "react-router-devtools/client";
import { myLoaderClientLoader as _clientLoader } from "./loaders";
export const clientLoader = _withClientLoaderWrapper(_clientLoader, "test");
`)
expect(removeWhitespace(result.code)).toStrictEqual(expected)
})

it("should transform aliased clientAction import where local name is clientAction", () => {
const result = augmentDataFetchingFunctions(
`
import { myLoaderClientAction as clientAction } from "./actions";
export { clientAction };
`,
"test",
"/file/path"
)
const expected = removeWhitespace(`
import { withClientActionWrapper as _withClientActionWrapper } from "react-router-devtools/client";
import { myLoaderClientAction as _clientAction } from "./actions";
export const clientAction = _withClientActionWrapper(_clientAction, "test");
`)
expect(removeWhitespace(result.code)).toStrictEqual(expected)
})

it("should transform aliased loader import and update usages in code", () => {
const result = augmentDataFetchingFunctions(
`
import { myLoader as loader } from "./loaders";
const test = () => {
return loader();
}
export { loader };
`,
"test",
"/file/path"
)
const expected = removeWhitespace(`
import { withLoaderWrapper as _withLoaderWrapper } from "react-router-devtools/server";
import { myLoader as _loader } from "./loaders";
const test = () => {
return _loader();
};
export const loader = _withLoaderWrapper(_loader, "test");
`)
expect(removeWhitespace(result.code)).toStrictEqual(expected)
})
})

it("should transform the re-exports when it's re-exported from another file with multiple re-exports", () => {
const result = augmentDataFetchingFunctions(
`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,17 @@ const transform = (ast: ParseResult<Babel.File>, routeId: string) => {
if (!t.isImportSpecifier(specifier) || !t.isIdentifier(specifier.imported)) {
continue
}
const name = specifier.imported.name
const importedName = specifier.imported.name
const localName = specifier.local.name
// Handle aliased imports where local name is a target export
// e.g., import { myLoader as loader }
if (ALL_EXPORTS.includes(localName) && !ALL_EXPORTS.includes(importedName)) {
const uniqueName = path.scope.generateUidIdentifier(localName)
imports.push([localName, uniqueName])
path.scope.rename(localName, uniqueName.name)
continue
}
const name = importedName
if (!ALL_EXPORTS.includes(name)) {
continue
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -622,6 +622,99 @@ describe("transform", () => {
})
})

describe("aliased import transforms", () => {
it("should transform aliased loader import where local name is loader", () => {
const result = injectContext(
`
import { myLoader as loader } from "./loaders";
export { loader };
`,
"test",
"/file/path"
)
const expected = removeWhitespace(`
import { withLoaderContextWrapper as _withLoaderContextWrapper } from "react-router-devtools/context";
import { myLoader as _loader } from "./loaders";
export const loader = _withLoaderContextWrapper(_loader, "test");
`)
expect(removeWhitespace(result.code)).toStrictEqual(expected)
})

it("should transform aliased action import where local name is action", () => {
const result = injectContext(
`
import { myLoaderAction as action } from "./actions";
export { action };
`,
"test",
"/file/path"
)
const expected = removeWhitespace(`
import { withActionContextWrapper as _withActionContextWrapper } from "react-router-devtools/context";
import { myLoaderAction as _action } from "./actions";
export const action = _withActionContextWrapper(_action, "test");
`)
expect(removeWhitespace(result.code)).toStrictEqual(expected)
})

it("should transform aliased clientLoader import where local name is clientLoader", () => {
const result = injectContext(
`
import { myLoaderClientLoader as clientLoader } from "./loaders";
export { clientLoader };
`,
"test",
"/file/path"
)
const expected = removeWhitespace(`
import { withClientLoaderContextWrapper as _withClientLoaderContextWrapper } from "react-router-devtools/context";
import { myLoaderClientLoader as _clientLoader } from "./loaders";
export const clientLoader = _withClientLoaderContextWrapper(_clientLoader, "test");
`)
expect(removeWhitespace(result.code)).toStrictEqual(expected)
})

it("should transform aliased clientAction import where local name is clientAction", () => {
const result = injectContext(
`
import { myLoaderClientAction as clientAction } from "./actions";
export { clientAction };
`,
"test",
"/file/path"
)
const expected = removeWhitespace(`
import { withClientActionContextWrapper as _withClientActionContextWrapper } from "react-router-devtools/context";
import { myLoaderClientAction as _clientAction } from "./actions";
export const clientAction = _withClientActionContextWrapper(_clientAction, "test");
`)
expect(removeWhitespace(result.code)).toStrictEqual(expected)
})

it("should transform aliased loader import and update usages in code", () => {
const result = injectContext(
`
import { myLoader as loader } from "./loaders";
const test = () => {
return loader();
}
export { loader };
`,
"test",
"/file/path"
)
const expected = removeWhitespace(`
import { withLoaderContextWrapper as _withLoaderContextWrapper } from "react-router-devtools/context";
import { myLoader as _loader } from "./loaders";
const test = () => {
return _loader();
};
export const loader = _withLoaderContextWrapper(_loader, "test");
`)
expect(removeWhitespace(result.code)).toStrictEqual(expected)
})
})

it("should transform the re-exports when it's re-exported from another file with multiple re-exports", () => {
const result = injectContext(
`
Expand Down
12 changes: 11 additions & 1 deletion packages/react-router-devtools/src/vite/utils/inject-context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,17 @@ const transform = (ast: ParseResult<Babel.File>, routeId: string) => {
if (!t.isImportSpecifier(specifier) || !t.isIdentifier(specifier.imported)) {
continue
}
const name = specifier.imported.name
const importedName = specifier.imported.name
const localName = specifier.local.name
// Handle aliased imports where local name is a target export
// e.g., import { myLoader as loader }
if (ALL_EXPORTS.includes(localName) && !ALL_EXPORTS.includes(importedName)) {
const uniqueName = path.scope.generateUidIdentifier(localName)
imports.push([localName, uniqueName])
path.scope.rename(localName, uniqueName.name)
continue
}
const name = importedName
if (!ALL_EXPORTS.includes(name)) {
continue
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -630,4 +630,71 @@ describe("middleware augmentation", () => {
expect(result.code).toContain('"authMiddleware"')
})
})

describe("aliased import transforms", () => {
it("should transform aliased middleware import where local name is middleware", () => {
const result = augmentMiddlewareFunctions(
`
import { authMiddleware as middleware } from "./middlewares";
export { middleware };
`,
"test",
"/file/path"
)
// Should skip transformation for re-exported imported middleware
// The aliased import handler renames it but since it's imported and re-exported, it skips
expect(result.code).toContain("authMiddleware")
})

it("should transform aliased clientMiddleware import where local name is clientMiddleware", () => {
const result = augmentMiddlewareFunctions(
`
import { clientAuthMiddleware as clientMiddleware } from "./middlewares";
export { clientMiddleware };
`,
"test",
"/file/path"
)
// Should skip transformation for re-exported imported middleware
expect(result.code).toContain("clientAuthMiddleware")
})

it("should handle aliased middleware import used in array", () => {
const result = augmentMiddlewareFunctions(
`
import { someAuthFn as authMiddleware } from "./auth";
export const middleware = [authMiddleware];
`,
"test",
"/file/path"
)
const expected = removeWhitespace(`
import { withMiddlewareWrapperSingle as _withMiddlewareWrapperSingle } from "react-router-devtools/server";
import { someAuthFn as authMiddleware } from "./auth";
export const middleware = [
_withMiddlewareWrapperSingle(authMiddleware, "test", 0, "authMiddleware")
];
`)
expect(removeWhitespace(result.code)).toStrictEqual(expected)
})

it("should handle aliased clientMiddleware import used in array", () => {
const result = augmentMiddlewareFunctions(
`
import { someClientAuthFn as clientAuthMiddleware } from "./auth";
export const clientMiddleware = [clientAuthMiddleware];
`,
"test",
"/file/path"
)
const expected = removeWhitespace(`
import { withClientMiddlewareWrapperSingle as _withClientMiddlewareWrapperSingle } from "react-router-devtools/client";
import { someClientAuthFn as clientAuthMiddleware } from "./auth";
export const clientMiddleware = [
_withClientMiddlewareWrapperSingle(clientAuthMiddleware, "test", 0, "clientAuthMiddleware")
];
`)
expect(removeWhitespace(result.code)).toStrictEqual(expected)
})
})
})
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,17 @@ const transform = (ast: ParseResult<Babel.File>, routeId: string) => {
if (!t.isImportSpecifier(specifier) || !t.isIdentifier(specifier.imported)) {
continue
}
const name = specifier.imported.name
const importedName = specifier.imported.name
const localName = specifier.local.name
// Handle aliased imports where local name is a target export
// e.g., import { someMiddleware as middleware }
if (ALL_MIDDLEWARE_EXPORTS.includes(localName) && !ALL_MIDDLEWARE_EXPORTS.includes(importedName)) {
const uniqueName = path.scope.generateUidIdentifier(localName)
imports.push([localName, uniqueName])
path.scope.rename(localName, uniqueName.name)
continue
}
const name = importedName
if (!ALL_MIDDLEWARE_EXPORTS.includes(name)) {
continue
}
Expand Down