Skip to content

Commit 75e2a18

Browse files
committed
Fix for augmentations
1 parent 077924a commit 75e2a18

File tree

4 files changed

+123
-9
lines changed

4 files changed

+123
-9
lines changed

src/vite/plugin.tsx

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -115,31 +115,32 @@ export const reactRouterDevTools: (args?: ReactRouterViteConfig) => Plugin[] = (
115115
return injectRdtClient(code, config, pluginImports, id)
116116
},
117117
},
118+
118119
{
119-
name: "react-router-devtools-inject-context",
120+
name: "react-router-devtools-data-function-augment",
120121
apply(config) {
121-
return shouldInject(config.mode, includeDevtools)
122+
return shouldInject(config.mode, includeServer)
122123
},
123124
transform(code, id) {
124125
const routeId = isTransformable(id)
125126
if (!routeId) {
126127
return
127128
}
128-
const finalCode = injectContext(code, routeId, id)
129+
const finalCode = augmentDataFetchingFunctions(code, routeId, id)
129130
return finalCode
130131
},
131132
},
132133
{
133-
name: "react-router-devtools-data-function-augment",
134+
name: "react-router-devtools-inject-context",
134135
apply(config) {
135-
return shouldInject(config.mode, includeServer)
136+
return shouldInject(config.mode, includeDevtools)
136137
},
137138
transform(code, id) {
138139
const routeId = isTransformable(id)
139140
if (!routeId) {
140141
return
141142
}
142-
const finalCode = augmentDataFetchingFunctions(code, routeId, id)
143+
const finalCode = injectContext(code, routeId, id)
143144
return finalCode
144145
},
145146
},

src/vite/utils/data-functions-augment.test.ts

Lines changed: 77 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,9 @@ describe("transform", () => {
7474
)
7575
const expected = removeWhitespace(`
7676
import { withLoaderWrapper as _withLoaderWrapper } from "react-router-devtools/server";
77-
export { loader as _loader } from "./loader.js";
77+
import { loader as _loader } from "./loader.js";
7878
export const loader = _withLoaderWrapper(_loader, "test");
79+
export {} from "./loader.js";
7980
`)
8081
expect(removeWhitespace(result.code)).toStrictEqual(expected)
8182
})
@@ -240,6 +241,24 @@ describe("transform", () => {
240241
`)
241242
expect(removeWhitespace(result.code)).toStrictEqual(expected)
242243
})
244+
245+
it("should transform the client action export when it's re-exported from another file", () => {
246+
const result = augmentDataFetchingFunctions(
247+
`
248+
export { clientLoader } from "./clientLoader.js";
249+
`,
250+
"test",
251+
"/file/path"
252+
)
253+
const expected = removeWhitespace(`
254+
import { withClientLoaderWrapper as _withClientLoaderWrapper } from "react-router-devtools/client";
255+
import { clientLoader as _clientLoader } from "./clientLoader.js";
256+
export const clientLoader = _withClientLoaderWrapper(_clientLoader, "test");
257+
export {} from "./clientLoader.js";
258+
`)
259+
expect(removeWhitespace(result.code)).toStrictEqual(expected)
260+
})
261+
243262
it("should wrap the clientLoader export when it's exported via export { clientLoader } and declared within the file", () => {
244263
const result = augmentDataFetchingFunctions(
245264
`
@@ -338,8 +357,9 @@ describe("transform", () => {
338357
)
339358
const expected = removeWhitespace(`
340359
import { withActionWrapper as _withActionWrapper } from "react-router-devtools/server";
341-
export { action as _action } from "./action.js";
360+
import { action as _action } from "./action.js";
342361
export const action = _withActionWrapper(_action, "test");
362+
export {} from "./action.js";
343363
`)
344364
expect(removeWhitespace(result.code)).toStrictEqual(expected)
345365
})
@@ -467,6 +487,23 @@ describe("transform", () => {
467487
expect(removeWhitespace(result.code)).toStrictEqual(expected)
468488
})
469489

490+
it("should transform the client action export when it's re-exported from another file", () => {
491+
const result = augmentDataFetchingFunctions(
492+
`
493+
export { clientAction } from "./clientAction.js";
494+
`,
495+
"test",
496+
"/file/path"
497+
)
498+
const expected = removeWhitespace(`
499+
import { withClientActionWrapper as _withClientActionWrapper } from "react-router-devtools/client";
500+
import { clientAction as _clientAction } from "./clientAction.js";
501+
export const clientAction = _withClientActionWrapper(_clientAction, "test");
502+
export {} from "./clientAction.js";
503+
`)
504+
expect(removeWhitespace(result.code)).toStrictEqual(expected)
505+
})
506+
470507
it("should transform the client action export when it's imported from another file and exported", () => {
471508
const result = augmentDataFetchingFunctions(
472509
`
@@ -512,3 +549,41 @@ describe("transform", () => {
512549
})
513550
})
514551
})
552+
553+
it("should transform the re-exports when it's re-exported from another file with multiple re-exports", () => {
554+
const result = augmentDataFetchingFunctions(
555+
`
556+
export { action, loader, default } from "./action.js";
557+
`,
558+
"test",
559+
"/file/path"
560+
)
561+
const expected = removeWhitespace(`
562+
import { withActionWrapper as _withActionWrapper, withLoaderWrapper as _withLoaderWrapper } from "react-router-devtools/server";
563+
import { action as _action } from "./action.js";
564+
import { loader as _loader } from "./action.js";
565+
export const action = _withActionWrapper(_action, "test");
566+
export const loader = _withLoaderWrapper(_loader, "test");
567+
export { default } from "./action.js";
568+
`)
569+
expect(removeWhitespace(result.code)).toStrictEqual(expected)
570+
})
571+
572+
it("should transform the re-exports when it's re-exported from another file with multiple re-exports", () => {
573+
const result = augmentDataFetchingFunctions(
574+
`
575+
export { action, loader, default, blah } from "./action.js";
576+
`,
577+
"test",
578+
"/file/path"
579+
)
580+
const expected = removeWhitespace(`
581+
import { withActionWrapper as _withActionWrapper, withLoaderWrapper as _withLoaderWrapper } from "react-router-devtools/server";
582+
import { action as _action } from "./action.js";
583+
import { loader as _loader } from "./action.js";
584+
export const action = _withActionWrapper(_action, "test");
585+
export const loader = _withLoaderWrapper(_loader, "test");
586+
export { default, blah } from "./action.js";
587+
`)
588+
expect(removeWhitespace(result.code)).toStrictEqual(expected)
589+
})

src/vite/utils/data-functions-augment.ts

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ const transform = (ast: ParseResult<Babel.File>, routeId: string) => {
3232
return str.charAt(0).toUpperCase() + str.slice(1)
3333
}
3434
const transformations: Array<() => void> = []
35+
36+
const importDeclarations: Babel.ImportDeclaration[] = []
3537
trav(ast, {
3638
ExportDeclaration(path) {
3739
if (path.isExportNamedDeclaration()) {
@@ -91,7 +93,39 @@ const transform = (ast: ParseResult<Babel.File>, routeId: string) => {
9193
? getClientHocId(path, `with${uppercaseFirstLetter(name)}Wrapper`)
9294
: getServerHocId(path, `with${uppercaseFirstLetter(name)}Wrapper`)
9395
const binding = path.scope.getBinding(name)
94-
if (binding?.path.isFunctionDeclaration()) {
96+
97+
if (path.node.source) {
98+
// Special condition: export { loader, action } from "./path"
99+
const source = path.node.source.value
100+
101+
importDeclarations.push(
102+
t.importDeclaration(
103+
[t.importSpecifier(t.identifier(`_${name}`), t.identifier(name))],
104+
t.stringLiteral(source)
105+
)
106+
)
107+
transformations.push(() => {
108+
path.insertBefore(
109+
t.exportNamedDeclaration(
110+
t.variableDeclaration("const", [
111+
t.variableDeclarator(
112+
t.identifier(name),
113+
t.callExpression(uid, [t.identifier(`_${name}`), t.stringLiteral(routeId)])
114+
),
115+
])
116+
)
117+
)
118+
})
119+
120+
// Remove the specifier from the exports and add a manual export
121+
transformations.push(() => {
122+
const remainingSpecifiers = path.node.specifiers.filter(
123+
(exportSpecifier) => !(t.isIdentifier(exportSpecifier.exported) && exportSpecifier.exported.name === name)
124+
)
125+
126+
path.replaceWith(t.exportNamedDeclaration(null, remainingSpecifiers, path.node.source))
127+
})
128+
} else if (binding?.path.isFunctionDeclaration()) {
95129
// Replace the function declaration with a wrapped version
96130
binding.path.replaceWith(
97131
t.variableDeclaration("const", [
@@ -138,6 +172,9 @@ const transform = (ast: ParseResult<Babel.File>, routeId: string) => {
138172
for (const transformation of transformations) {
139173
transformation()
140174
}
175+
if (importDeclarations.length > 0) {
176+
ast.program.body.unshift(...importDeclarations)
177+
}
141178
if (serverHocs.length > 0) {
142179
ast.program.body.unshift(
143180
t.importDeclaration(
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { loader, default }from "./_index";

0 commit comments

Comments
 (0)