From 1702635156ef8f59af3aa7d6c53db08aa71f9ef1 Mon Sep 17 00:00:00 2001 From: Marvin Hagemeister Date: Tue, 16 Sep 2025 16:38:42 +0200 Subject: [PATCH 1/3] wip --- deno.json | 1 + deno.lock | 28 +++++++++++++++++++ .../demo/routes/tests/supabase_pg.tsx | 7 +++++ packages/plugin-vite/src/plugins/deno.ts | 12 ++++++++ 4 files changed, 48 insertions(+) create mode 100644 packages/plugin-vite/demo/routes/tests/supabase_pg.tsx diff --git a/deno.json b/deno.json index 7af8d6be3e3..4f7de09cad0 100644 --- a/deno.json +++ b/deno.json @@ -47,6 +47,7 @@ "@std/dotenv": "jsr:@std/dotenv@^0.225.5", "@std/http": "jsr:@std/http@^1.0.15", "@std/uuid": "jsr:@std/uuid@^1.0.7", + "@supabase/postgrest-js": "npm:@supabase/postgrest-js@^1.21.4", "@types/node": "npm:@types/node@^24.3.0", "docsearch": "https://esm.sh/@docsearch/js@3.5.2?target=es2020", "esbuild": "npm:esbuild@0.25.7", diff --git a/deno.lock b/deno.lock index 67c9beaee17..315095c3152 100644 --- a/deno.lock +++ b/deno.lock @@ -68,6 +68,7 @@ "npm:@preact/signals@^2.2.1": "2.3.1_preact@10.27.2", "npm:@prefresh/vite@^2.4.8": "2.4.10_preact@10.27.2_vite@7.1.5__@types+node@24.3.3__picomatch@4.0.3_@types+node@24.3.3", "npm:@radix-ui/themes@^3.2.1": "3.2.1_react@19.1.1_react-dom@19.1.1__react@19.1.1", + "npm:@supabase/postgrest-js@^1.21.4": "1.21.4", "npm:@tailwindcss/postcss@^4.1.10": "4.1.13", "npm:@tailwindcss/vite@^4.1.12": "4.1.13_vite@7.1.5__@types+node@24.3.3__picomatch@4.0.3_@types+node@24.3.3", "npm:@types/babel__core@^7.20.5": "7.20.5", @@ -101,6 +102,7 @@ "npm:ts-morph@26": "26.0.0", "npm:vite-plugin-inspect@^11.3.2": "11.3.3_vite@7.1.5__@types+node@24.3.3__picomatch@4.0.3_@types+node@24.3.3", "npm:vite@*": "7.1.5_@types+node@24.3.3_picomatch@4.0.3", + "npm:vite@7.1.5": "7.1.5_@types+node@24.3.3_picomatch@4.0.3", "npm:vite@^7.1.4": "7.1.5_@types+node@24.3.3_picomatch@4.0.3", "npm:vite@^7.1.5": "7.1.5_@types+node@24.3.3_picomatch@4.0.3" }, @@ -1617,6 +1619,18 @@ "os": ["win32"], "cpu": ["x64"] }, + "@supabase/node-fetch@2.6.15": { + "integrity": "sha512-1ibVeYUacxWYi9i0cf5efil6adJ9WRyZBLivgjs+AUpewx1F3xPi7gLgaASI2SmIQxPoCEjAsLAzKPgMJVgOUQ==", + "dependencies": [ + "whatwg-url" + ] + }, + "@supabase/postgrest-js@1.21.4": { + "integrity": "sha512-TxZCIjxk6/dP9abAi89VQbWWMBbybpGWyvmIzTd79OeravM13OjR/YEYeyUOPcM1C3QyvXkvPZhUfItvmhY1IQ==", + "dependencies": [ + "@supabase/node-fetch" + ] + }, "@tailwindcss/node@4.1.13": { "integrity": "sha512-eq3ouolC1oEFOAvOMOBAmfCIqZBJuvWvvYWh5h5iOYfe1HFC6+GZ6EIL0JdM3/niGRJmnrOc+8gl9/HGUaaptw==", "dependencies": [ @@ -3355,6 +3369,9 @@ "totalist@3.0.1": { "integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==" }, + "tr46@0.0.3": { + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, "ts-interface-checker@0.1.13": { "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==" }, @@ -3462,6 +3479,16 @@ ], "bin": true }, + "webidl-conversions@3.0.1": { + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "whatwg-url@5.0.0": { + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dependencies": [ + "tr46", + "webidl-conversions" + ] + }, "which@2.0.2": { "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dependencies": [ @@ -3619,6 +3646,7 @@ "jsr:@std/uuid@^1.0.7", "npm:@opentelemetry/api@^1.9.0", "npm:@preact/signals@^2.2.1", + "npm:@supabase/postgrest-js@^1.21.4", "npm:@tailwindcss/postcss@^4.1.10", "npm:@types/node@^24.3.0", "npm:esbuild-wasm@0.25.7", diff --git a/packages/plugin-vite/demo/routes/tests/supabase_pg.tsx b/packages/plugin-vite/demo/routes/tests/supabase_pg.tsx new file mode 100644 index 00000000000..110ec8ea718 --- /dev/null +++ b/packages/plugin-vite/demo/routes/tests/supabase_pg.tsx @@ -0,0 +1,7 @@ +import * as supabase from "@supabase/postgrest-js"; + +export default function Page() { + // deno-lint-ignore no-console + console.log(supabase); + return

supabase

; +} diff --git a/packages/plugin-vite/src/plugins/deno.ts b/packages/plugin-vite/src/plugins/deno.ts index d1c9d217b44..759c620ea53 100644 --- a/packages/plugin-vite/src/plugins/deno.ts +++ b/packages/plugin-vite/src/plugins/deno.ts @@ -40,6 +40,14 @@ export function deno(): Plugin { ssrLoader = await new Workspace({ platform: "node", cachedOnly: true, + nodeConditions: [ + "deno", + "node", + "import", + "module", + "default", + "require", + ], }).createLoader(); browserLoader = await new Workspace({ platform: "browser", @@ -116,6 +124,10 @@ export function deno(): Plugin { ResolutionMode.Import, ); + if (original.includes("supabas")) { + console.log({ original, id, resolved }); + } + if (resolved.startsWith("node:")) { return { id: resolved, From f75548b29fc4479a38ed4c68c02bd6473712937e Mon Sep 17 00:00:00 2001 From: Marvin Hagemeister Date: Fri, 19 Sep 2025 14:36:03 +0200 Subject: [PATCH 2/3] fix(vite): cover more commonjs cases --- packages/plugin-vite/src/plugins/deno.ts | 10 +- .../src/plugins/patches/code_eval.ts | 26 ---- .../src/plugins/patches/commonjs.ts | 74 ++++++------ .../src/plugins/patches/commonjs_test.ts | 111 +++++++++++++++--- 4 files changed, 143 insertions(+), 78 deletions(-) diff --git a/packages/plugin-vite/src/plugins/deno.ts b/packages/plugin-vite/src/plugins/deno.ts index 759c620ea53..1d76b8d8132 100644 --- a/packages/plugin-vite/src/plugins/deno.ts +++ b/packages/plugin-vite/src/plugins/deno.ts @@ -53,6 +53,12 @@ export function deno(): Plugin { platform: "browser", preserveJsx: true, cachedOnly: true, + nodeConditions: [ + "import", + "module", + "browser", + "default", + ], }) .createLoader(); }, @@ -124,10 +130,6 @@ export function deno(): Plugin { ResolutionMode.Import, ); - if (original.includes("supabas")) { - console.log({ original, id, resolved }); - } - if (resolved.startsWith("node:")) { return { id: resolved, diff --git a/packages/plugin-vite/src/plugins/patches/code_eval.ts b/packages/plugin-vite/src/plugins/patches/code_eval.ts index 445e3451880..1197a76e62d 100644 --- a/packages/plugin-vite/src/plugins/patches/code_eval.ts +++ b/packages/plugin-vite/src/plugins/patches/code_eval.ts @@ -34,32 +34,6 @@ export function codeEvalPlugin( } }, }, - CallExpression: { - enter(path) { - if ( - t.isMemberExpression(path.node.callee) && - t.isIdentifier(path.node.callee.object) && - t.isIdentifier(path.node.callee.property) && - path.node.callee.object.name === "Object" && - path.node.callee.property.name === "defineProperty" && - path.node.arguments.length >= 2 - ) { - const args = path.node.arguments; - - if ( - t.isIdentifier(args[0]) && args[0].name === "exports" || - t.isMemberExpression(args[0]) && - t.isIdentifier(args[0].object) && - t.isIdentifier(args[0].property) && - args[0].object.name === "module" && - args[0].property.name === "exports" && - t.isStringLiteral(args[1]) && args[1].value === "native" - ) { - path.remove(); - } - } - }, - }, }, }; }; diff --git a/packages/plugin-vite/src/plugins/patches/commonjs.ts b/packages/plugin-vite/src/plugins/patches/commonjs.ts index cc36f976260..981f6f5e203 100644 --- a/packages/plugin-vite/src/plugins/patches/commonjs.ts +++ b/packages/plugin-vite/src/plugins/patches/commonjs.ts @@ -74,6 +74,7 @@ export function cjsPlugin( const exported = state.get(EXPORTED); const exportedNs = state.get(EXPORTED_NAMESPACES); const needsRequireImport = state.get(NEEDS_REQUIRE_IMPORT); + const hasEsModule = state.get(HAS_ES_MODULE); if (needsRequireImport) { // Inject: @@ -223,7 +224,7 @@ export function cjsPlugin( ); } - if (exportNamed.size > 0 || exportedNs.size > 0) { + if (exportNamed.size > 0 || exportedNs.size > 0 || hasEsModule) { const id = path.scope.generateUidIdentifier("__default"); path.pushContainer( @@ -288,8 +289,24 @@ export function cjsPlugin( ); } - if (body.length === 0 && state.get(HAS_ES_MODULE)) { + if (body.length === 0 && hasEsModule) { path.pushContainer("body", t.exportNamedDeclaration(null)); + } else if (hasEsModule) { + path.pushContainer( + "body", + t.exportNamedDeclaration( + t.variableDeclaration( + "var", + [t.variableDeclarator( + t.identifier("__esModule"), + t.memberExpression( + t.identifier("exports"), + t.identifier("__esModule"), + ), + )], + ), + ), + ); } }, }, @@ -299,7 +316,6 @@ export function cjsPlugin( if (isObjEsModuleFlag(t, path.node)) { state.set(HAS_ES_MODULE, true); - path.remove(); return; } @@ -343,23 +359,31 @@ export function cjsPlugin( path.parentPath?.get("id").isIdentifier() || path.parentPath?.isCallExpression() ) { - path.replaceWith( - t.logicalExpression( - "??", - t.memberExpression( - t.cloneNode(id, true), - t.identifier("__require"), - ), + if ( + path.parentPath?.isCallExpression() && + t.isIdentifier(path.parentPath.node.callee) && + path.parentPath.node.callee.name === "__importDefault" + ) { + path.replaceWith(t.cloneNode(id, true)); + } else { + path.replaceWith( t.logicalExpression( "??", t.memberExpression( t.cloneNode(id, true), - t.identifier("default"), + t.identifier("__require"), + ), + t.logicalExpression( + "??", + t.memberExpression( + t.cloneNode(id, true), + t.identifier("default"), + ), + t.cloneNode(id, true), ), - t.cloneNode(id, true), ), - ), - ); + ); + } return; } @@ -406,19 +430,14 @@ export function cjsPlugin( if (state.get(IS_ESM)) return; // Check: Object.defineProperty(module.exports) "__esModule" ...) // Check: Object.defineProperty(exports) "__esModule" ...) + // Check: a({}, "__esModule", ...) if ( t.isCallExpression(path.node.expression) && - t.isMemberExpression(path.node.expression.callee) && - t.isIdentifier(path.node.expression.callee.object) && - t.isIdentifier(path.node.expression.callee.property) && - path.node.expression.callee.object.name === "Object" && - path.node.expression.callee.property.name === "defineProperty" && - path.node.expression.arguments.length >= 2 && + path.node.expression.arguments.length === 3 && t.isStringLiteral(path.node.expression.arguments[1]) && path.node.expression.arguments[1].value === "__esModule" ) { state.set(HAS_ES_MODULE, true); - path.remove(); return; } @@ -565,7 +584,6 @@ export function cjsPlugin( if (isEsModuleFlag(t, expr.node)) { state.set(HAS_ES_MODULE, true); - path.remove(); } else if (left.isMemberExpression()) { if (isModuleExports(t, left.node)) { exported.add("default"); @@ -594,7 +612,6 @@ export function cjsPlugin( } else if (expr.isCallExpression()) { if (isObjEsModuleFlag(t, expr.node)) { state.set(HAS_ES_MODULE, true); - path.remove(); } } }, @@ -687,16 +704,7 @@ function isObjEsModuleFlag( t: typeof types, node: types.CallExpression, ): boolean { - return t.isMemberExpression(node.callee) && - t.isIdentifier(node.callee.object) && - node.callee.object.name === "Object" && - t.isIdentifier(node.callee.property) && - node.callee.property.name === "defineProperty" && - node.arguments.length === 3 && - (t.isMemberExpression(node.arguments[0]) && - isModuleExports(t, node.arguments[0]) || - t.isIdentifier(node.arguments[0]) && - node.arguments[0].name === "exports") && + return node.arguments.length === 3 && t.isStringLiteral(node.arguments[1]) && node.arguments[1].value === "__esModule" && t.isObjectExpression(node.arguments[2]); diff --git a/packages/plugin-vite/src/plugins/patches/commonjs_test.ts b/packages/plugin-vite/src/plugins/patches/commonjs_test.ts index 6f5226432f1..663254f4761 100644 --- a/packages/plugin-vite/src/plugins/patches/commonjs_test.ts +++ b/packages/plugin-vite/src/plugins/patches/commonjs_test.ts @@ -31,6 +31,7 @@ const DEFAULT_EXPORT_END = `export default _default; export var __require = exports;`; const IMPORT_REQUIRE = `import { createRequire } from "node:module"; const require = createRequire(import.meta.url);`; +const EXPORT_ES_MODULE = `export var __esModule = exports.__esModule;`; Deno.test("commonjs - module.exports default", () => { runTest({ @@ -58,13 +59,15 @@ Deno.test("commonjs - exports with default + named", () => { exports.default = 'x'; exports.foo = 'foo';`, expected: `${INIT} +exports.__esModule = true; exports.default = 'x'; exports.foo = 'foo'; var _foo = exports.foo; export { _foo as foo }; ${DEFAULT_EXPORT} _default.foo = _foo; -${DEFAULT_EXPORT_END}`, +${DEFAULT_EXPORT_END} +${EXPORT_ES_MODULE}`, }); }); @@ -74,13 +77,15 @@ Deno.test("commonjs - module.exports with default + named", () => { module.exports.default = 'x'; module.exports.foo = 'foo';`, expected: `${INIT} +module.exports.__esModule = true; module.exports.default = 'x'; module.exports.foo = 'foo'; var _foo = exports.foo; export { _foo as foo }; ${DEFAULT_EXPORT} _default.foo = _foo; -${DEFAULT_EXPORT_END}`, +${DEFAULT_EXPORT_END} +${EXPORT_ES_MODULE}`, }); }); @@ -91,13 +96,17 @@ exports.foo = 'bar'; const foo = 'also bar'; `, expected: `${INIT} +Object.defineProperty(exports, '__esModule', { + value: true +}); exports.foo = 'bar'; const foo = 'also bar'; var _foo = exports.foo; export { _foo as foo }; ${DEFAULT_EXPORT} _default.foo = _foo; -${DEFAULT_EXPORT_END}`, +${DEFAULT_EXPORT_END} +${EXPORT_ES_MODULE}`, }); }); @@ -108,20 +117,30 @@ exports.default = 'foo'; exports.foo = 'bar'; `, expected: `${INIT} +Object.defineProperty(exports, '__esModule', { + value: true +}); exports.default = 'foo'; exports.foo = 'bar'; var _foo = exports.foo; export { _foo as foo }; ${DEFAULT_EXPORT} _default.foo = _foo; -${DEFAULT_EXPORT_END}`, +${DEFAULT_EXPORT_END} +${EXPORT_ES_MODULE}`, }); }); Deno.test("commonjs - esModule flag only", () => { runTest({ input: `Object.defineProperty(exports, "__esModule", { value: true });`, - expected: `export {};`, + expected: `Object.defineProperty(exports, "__esModule", { + value: true +}); +const _default = exports.default ?? exports; +export default _default; +export var __require = exports; +${EXPORT_ES_MODULE}`, }); }); @@ -129,14 +148,26 @@ Deno.test("commonjs - esModule flag only #2", () => { runTest({ input: `Object.defineProperty(module.exports, "__esModule", { value: true });`, - expected: `export {};`, + expected: `Object.defineProperty(module.exports, "__esModule", { + value: true +}); +const _default = exports.default ?? exports; +export default _default; +export var __require = exports; +${EXPORT_ES_MODULE}`, }); }); Deno.test("commonjs - esModule flag only minified #3", () => { runTest({ input: `Object.defineProperty(exports, '__esModule', { value: !0 });`, - expected: `export {};`, + expected: `Object.defineProperty(exports, '__esModule', { + value: !0 +}); +const _default = exports.default ?? exports; +export default _default; +export var __require = exports; +${EXPORT_ES_MODULE}`, }); }); @@ -147,6 +178,9 @@ exports.foo = 'bar'; exports.bar = 'foo'; `, expected: `${INIT} +Object.defineProperty(exports, '__esModule', { + value: true +}); exports.foo = 'bar'; exports.bar = 'foo'; var _foo = exports.foo; @@ -155,7 +189,8 @@ export { _foo as foo, _bar as bar }; ${DEFAULT_EXPORT} _default.foo = _foo; _default.bar = _bar; -${DEFAULT_EXPORT_END}`, +${DEFAULT_EXPORT_END} +${EXPORT_ES_MODULE}`, }); }); @@ -228,13 +263,17 @@ Deno.test("commonjs - duplicate exports", () => { exports.trace = void 0; exports.trace = 'foo'`, expected: `${INIT} +Object.defineProperty(exports, "__esModule", { + value: true +}); exports.trace = void 0; exports.trace = 'foo'; var _trace = exports.trace; export { _trace as trace }; ${DEFAULT_EXPORT} _default.trace = _trace; -${DEFAULT_EXPORT_END}`, +${DEFAULT_EXPORT_END} +${EXPORT_ES_MODULE}`, }); }); @@ -244,12 +283,16 @@ Deno.test("commonjs - cleared exports", () => { exports.foo = exports.bar = void 0; exports.foo = 'foo'`, expected: `${INIT} +Object.defineProperty(exports, "__esModule", { + value: true +}); exports.foo = 'foo'; var _foo = exports.foo; export { _foo as foo }; ${DEFAULT_EXPORT} _default.foo = _foo; -${DEFAULT_EXPORT_END}`, +${DEFAULT_EXPORT_END} +${EXPORT_ES_MODULE}`, }); }); @@ -291,13 +334,17 @@ Deno.test("commonjs - define exports #3", () => { exports._globalThis = void 0; exports._globalThis = typeof globalThis === 'object' ? globalThis : global;`, expected: `${INIT} +Object.defineProperty(exports, "__esModule", { + value: true +}); exports._globalThis = void 0; exports._globalThis = typeof globalThis === 'object' ? globalThis : global; var _globalThis = exports._globalThis; export { _globalThis }; ${DEFAULT_EXPORT} _default._globalThis = _globalThis; -${DEFAULT_EXPORT_END}`, +${DEFAULT_EXPORT_END} +${EXPORT_ES_MODULE}`, }); }); @@ -307,13 +354,17 @@ Deno.test("commonjs - named function", () => { function foo() {}; exports.foo = foo;`, expected: `${INIT} +Object.defineProperty(exports, "__esModule", { + value: true +}); function foo() {} exports.foo = foo; var _foo = exports.foo; export { _foo as foo }; ${DEFAULT_EXPORT} _default.foo = _foo; -${DEFAULT_EXPORT_END}`, +${DEFAULT_EXPORT_END} +${EXPORT_ES_MODULE}`, }); }); @@ -363,6 +414,9 @@ var DiagLogLevel; DiagLogLevel[DiagLogLevel["ALL"] = 9999] = "ALL"; })(DiagLogLevel = exports.DiagLogLevel || (exports.DiagLogLevel = {}));`, expected: `${INIT} +Object.defineProperty(exports, "__esModule", { + value: true +}); exports.DiagLogLevel = void 0; var DiagLogLevel; (function (DiagLogLevel) { @@ -372,7 +426,8 @@ var _DiagLogLevel = exports.DiagLogLevel; export { _DiagLogLevel as DiagLogLevel }; ${DEFAULT_EXPORT} _default.DiagLogLevel = _DiagLogLevel; -${DEFAULT_EXPORT_END}`, +${DEFAULT_EXPORT_END} +${EXPORT_ES_MODULE}`, }); }); @@ -397,6 +452,9 @@ Deno.test("commonjs - export default object", () => { module.exports = { foo: 'bar' }; `, expected: `${INIT} +Object.defineProperty(exports, '__esModule', { + value: true +}); module.exports = { foo: 'bar' }; @@ -404,7 +462,8 @@ var _foo = exports.foo; export { _foo as foo }; ${DEFAULT_EXPORT} _default.foo = _foo; -${DEFAULT_EXPORT_END}`, +${DEFAULT_EXPORT_END} +${EXPORT_ES_MODULE}`, }); }); @@ -457,10 +516,14 @@ var __createBinding = this && this.__createBinding || (Object.create ? function var __exportStar = this && this.__exportStar || function (m, exports) { for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); }; +Object.defineProperty(exports, "__esModule", { + value: true +}); export * from "./node"; ${DEFAULT_EXPORT} Object.assign(_default, _ns); -${DEFAULT_EXPORT_END}`, +${DEFAULT_EXPORT_END} +${EXPORT_ES_MODULE}`, }); }); @@ -621,3 +684,21 @@ export default module.exports; export var create = module.exports.create;`, }); }); + +Deno.test("commonjs - minified __esModule", () => { + runTest({ + filename: "foo.js", + input: ` +const m = module.exports; +const a = Object.defineProperty; +a(m, "__esModule", { value: !0 });`, + expected: `const m = module.exports; +const a = Object.defineProperty; +a(m, "__esModule", { + value: !0 +}); +${DEFAULT_EXPORT} +${DEFAULT_EXPORT_END} +export var __esModule = exports.__esModule;`, + }); +}); From 2d7c2cc850495a3f8094654ff96d4a8f2341217a Mon Sep 17 00:00:00 2001 From: Marvin Hagemeister Date: Fri, 19 Sep 2025 18:28:35 +0200 Subject: [PATCH 3/3] more --- deno.json | 1 + deno.lock | 42 ++++++++ .../plugin-vite/demo/routes/tests/redis.tsx | 7 ++ packages/plugin-vite/src/plugins/deno.ts | 17 +--- .../src/plugins/patches/commonjs.ts | 95 +++++++++++++++++-- .../src/plugins/patches/commonjs_test.ts | 23 ++++- packages/plugin-vite/tests/dev_server_test.ts | 22 +++++ 7 files changed, 180 insertions(+), 27 deletions(-) create mode 100644 packages/plugin-vite/demo/routes/tests/redis.tsx diff --git a/deno.json b/deno.json index 4f7de09cad0..bae8fa257a9 100644 --- a/deno.json +++ b/deno.json @@ -77,6 +77,7 @@ "@std/testing": "jsr:@std/testing@^1.0.12", "@tailwindcss/postcss": "npm:@tailwindcss/postcss@^4.1.10", + "redis": "npm:redis@^5.8.2", "rollup": "npm:rollup@^4.50.0", "tailwindcss": "npm:tailwindcss@^4.1.10", "postcss": "npm:postcss@8.5.6", diff --git a/deno.lock b/deno.lock index 315095c3152..ea888810b63 100644 --- a/deno.lock +++ b/deno.lock @@ -95,6 +95,7 @@ "npm:preact@^10.26.9": "10.27.2", "npm:preact@^10.27.0": "10.27.2", "npm:prismjs@^1.29.0": "1.30.0", + "npm:redis@^5.8.2": "5.8.2_@redis+client@5.8.2", "npm:rollup-plugin-visualizer@^6.0.3": "6.0.3_rollup@4.50.1", "npm:rollup@^4.50.0": "4.50.1", "npm:tailwindcss@^3.4.17": "3.4.17_postcss@8.5.6", @@ -1507,6 +1508,36 @@ "react-remove-scroll-bar" ] }, + "@redis/bloom@5.8.2_@redis+client@5.8.2": { + "integrity": "sha512-855DR0ChetZLarblio5eM0yLwxA9Dqq50t8StXKp5bAtLT0G+rZ+eRzzqxl37sPqQKjUudSYypz55o6nNhbz0A==", + "dependencies": [ + "@redis/client" + ] + }, + "@redis/client@5.8.2": { + "integrity": "sha512-WtMScno3+eBpTac1Uav2zugXEoXqaU23YznwvFgkPwBQVwEHTDgOG7uEAObtZ/Nyn8SmAMbqkEubJaMOvnqdsQ==", + "dependencies": [ + "cluster-key-slot" + ] + }, + "@redis/json@5.8.2_@redis+client@5.8.2": { + "integrity": "sha512-uxpVfas3I0LccBX9rIfDgJ0dBrUa3+0Gc8sEwmQQH0vHi7C1Rx1Qn8Nv1QWz5bohoeIXMICFZRcyDONvum2l/w==", + "dependencies": [ + "@redis/client" + ] + }, + "@redis/search@5.8.2_@redis+client@5.8.2": { + "integrity": "sha512-cNv7HlgayavCBXqPXgaS97DRPVWFznuzsAmmuemi2TMCx5scwLiP50TeZvUS06h/MG96YNPe6A0Zt57yayfxwA==", + "dependencies": [ + "@redis/client" + ] + }, + "@redis/time-series@5.8.2_@redis+client@5.8.2": { + "integrity": "sha512-g2NlHM07fK8H4k+613NBsk3y70R2JIM2dPMSkhIjl2Z17SYvaYKdusz85d7VYOrZBWtDrHV/WD2E3vGu+zni8A==", + "dependencies": [ + "@redis/client" + ] + }, "@rollup/pluginutils@4.2.1": { "integrity": "sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==", "dependencies": [ @@ -3120,6 +3151,16 @@ "redis-errors" ] }, + "redis@5.8.2_@redis+client@5.8.2": { + "integrity": "sha512-31vunZj07++Y1vcFGcnNWEf5jPoTkGARgfWI4+Tk55vdwHxhAvug8VEtW7Cx+/h47NuJTEg/JL77zAwC6E0OeA==", + "dependencies": [ + "@redis/bloom", + "@redis/client", + "@redis/json", + "@redis/search", + "@redis/time-series" + ] + }, "require-directory@2.1.1": { "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==" }, @@ -3660,6 +3701,7 @@ "npm:preact-render-to-string@^6.5.11", "npm:preact@^10.27.0", "npm:prismjs@^1.29.0", + "npm:redis@^5.8.2", "npm:rollup@^4.50.0", "npm:tailwindcss@^4.1.10", "npm:ts-morph@26", diff --git a/packages/plugin-vite/demo/routes/tests/redis.tsx b/packages/plugin-vite/demo/routes/tests/redis.tsx new file mode 100644 index 00000000000..fc73d99291b --- /dev/null +++ b/packages/plugin-vite/demo/routes/tests/redis.tsx @@ -0,0 +1,7 @@ +import * as redis from "redis"; + +export default function Page() { + // deno-lint-ignore no-console + console.log(redis); + return

redis

; +} diff --git a/packages/plugin-vite/src/plugins/deno.ts b/packages/plugin-vite/src/plugins/deno.ts index 1d76b8d8132..1f2e9988ee7 100644 --- a/packages/plugin-vite/src/plugins/deno.ts +++ b/packages/plugin-vite/src/plugins/deno.ts @@ -40,25 +40,11 @@ export function deno(): Plugin { ssrLoader = await new Workspace({ platform: "node", cachedOnly: true, - nodeConditions: [ - "deno", - "node", - "import", - "module", - "default", - "require", - ], }).createLoader(); browserLoader = await new Workspace({ platform: "browser", preserveJsx: true, cachedOnly: true, - nodeConditions: [ - "import", - "module", - "browser", - "default", - ], }) .createLoader(); }, @@ -67,7 +53,8 @@ export function deno(): Plugin { }, async resolveId(id, importer, options) { if (BUILTINS.has(id)) { - if (!id.startsWith("node:") && BUILTINS.has(`node:${id}`)) { + // `node:` prefix is not included in builtins list. + if (!id.startsWith("node:")) { id = `node:${id}`; } return { diff --git a/packages/plugin-vite/src/plugins/patches/commonjs.ts b/packages/plugin-vite/src/plugins/patches/commonjs.ts index 981f6f5e203..40f1991227e 100644 --- a/packages/plugin-vite/src/plugins/patches/commonjs.ts +++ b/packages/plugin-vite/src/plugins/patches/commonjs.ts @@ -1,4 +1,7 @@ import type { NodePath, PluginObj, types } from "@babel/core"; +import { builtinModules } from "node:module"; + +const BUILTINS = new Set(builtinModules); export function cjsPlugin( { types: t }: { types: typeof types }, @@ -261,15 +264,60 @@ export function cjsPlugin( for (let i = 0; i < mappedNs.length; i++) { const mapped = mappedNs[i]; + + const key = path.scope.generateUid("k"); path.pushContainer( "body", - t.expressionStatement( - t.callExpression( - t.memberExpression( - t.identifier("Object"), - t.identifier("assign"), + t.forInStatement( + t.variableDeclaration("var", [ + t.variableDeclarator(t.identifier(key)), + ]), + t.identifier(mapped), + t.ifStatement( + t.logicalExpression( + "&&", + t.logicalExpression( + "&&", + t.binaryExpression( + "!==", + t.identifier(key), + t.stringLiteral("default"), + ), + t.binaryExpression( + "!==", + t.identifier(key), + t.stringLiteral("__esModule"), + ), + ), + t.callExpression( + t.memberExpression( + t.memberExpression( + t.memberExpression( + t.identifier("Object"), + t.identifier("prototype"), + ), + t.identifier("hasOwnProperty"), + ), + t.identifier("call"), + ), + [t.identifier(mapped), t.identifier(key)], + ), + ), + t.expressionStatement( + t.assignmentExpression( + "=", + t.memberExpression( + t.cloneNode(id, true), + t.identifier(key), + true, + ), + t.memberExpression( + t.identifier(mapped), + t.identifier(key), + true, + ), + ), ), - [t.cloneNode(id, true), t.identifier(mapped)], ), ), ); @@ -329,7 +377,8 @@ export function cjsPlugin( const mods = state.get(REQUIRE_CALLS) ?? []; state.set(REQUIRE_CALLS, mods); - if (t.isStringLiteral(path.node.arguments[0])) { + const source = path.node.arguments[0]; + if (t.isStringLiteral(source)) { // Check if we can hoist it or if we need to keep it. let canImport = true; let parent: NodePath | null = path.parentPath; @@ -359,12 +408,40 @@ export function cjsPlugin( path.parentPath?.get("id").isIdentifier() || path.parentPath?.isCallExpression() ) { - if ( + // Vite json processing always adds a default property. + if (source.value.endsWith(".json")) { + path.replaceWith( + t.logicalExpression( + "??", + t.memberExpression( + t.cloneNode(id, true), + t.identifier("default"), + ), + t.cloneNode(id, true), + ), + ); + } else if ( path.parentPath?.isCallExpression() && t.isIdentifier(path.parentPath.node.callee) && path.parentPath.node.callee.name === "__importDefault" ) { - path.replaceWith(t.cloneNode(id, true)); + if ( + BUILTINS.has(source.value) || + source.value.startsWith("node:") + ? BUILTINS.has(source.value.slice("node:".length)) + : BUILTINS.has(`node:${source.value}`) + ) { + path.replaceWith(t.logicalExpression( + "??", + t.memberExpression( + t.cloneNode(id, true), + t.identifier("default"), + ), + t.cloneNode(id, true), + )); + } else { + path.replaceWith(t.cloneNode(id, true)); + } } else { path.replaceWith( t.logicalExpression( diff --git a/packages/plugin-vite/src/plugins/patches/commonjs_test.ts b/packages/plugin-vite/src/plugins/patches/commonjs_test.ts index 663254f4761..1f4e55444b9 100644 --- a/packages/plugin-vite/src/plugins/patches/commonjs_test.ts +++ b/packages/plugin-vite/src/plugins/patches/commonjs_test.ts @@ -375,7 +375,7 @@ Deno.test("commonjs - detect esbuild shims", () => { import * as _ns from "./globalThis"; export * from "./globalThis"; ${DEFAULT_EXPORT} -Object.assign(_default, _ns); +for (var _k in _ns) if (_k !== "default" && _k !== "__esModule" && Object.prototype.hasOwnProperty.call(_ns, _k)) _default[_k] = _ns[_k]; ${DEFAULT_EXPORT_END}`, }); }); @@ -521,7 +521,7 @@ Object.defineProperty(exports, "__esModule", { }); export * from "./node"; ${DEFAULT_EXPORT} -Object.assign(_default, _ns); +for (var _k in _ns) if (_k !== "default" && _k !== "__esModule" && Object.prototype.hasOwnProperty.call(_ns, _k)) _default[_k] = _ns[_k]; ${DEFAULT_EXPORT_END} ${EXPORT_ES_MODULE}`, }); @@ -639,7 +639,7 @@ ${DEFAULT_EXPORT_END}`, }); }); -Deno.test("commonjs - re-export", () => { +Deno.test("commonjs - re-export #2", () => { runTest({ input: `module.exports = require("foo");`, expected: `${INIT} @@ -702,3 +702,20 @@ ${DEFAULT_EXPORT_END} export var __esModule = exports.__esModule;`, }); }); + +Deno.test("commonjs - esbuild __importDefault", () => { + runTest({ + input: + `var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +const node_events_1 = __importDefault(require("node:events"));`, + expected: `import * as _mod from "node:events"; +var __importDefault = this && this.__importDefault || function (mod) { + return mod && mod.__esModule ? mod : { + "default": mod + }; +}; +const node_events_1 = __importDefault(_mod.default ?? _mod);`, + }); +}); diff --git a/packages/plugin-vite/tests/dev_server_test.ts b/packages/plugin-vite/tests/dev_server_test.ts index 1a0ae9cafbd..877778b9225 100644 --- a/packages/plugin-vite/tests/dev_server_test.ts +++ b/packages/plugin-vite/tests/dev_server_test.ts @@ -420,6 +420,28 @@ Deno.test({ sanitizeResources: false, }); +Deno.test({ + name: "vite dev - redis", + fn: async () => { + const res = await fetch(`${demoServer.address()}/tests/redis`); + const text = await res.text(); + expect(text).toContain("

redis

"); + }, + sanitizeOps: false, + sanitizeResources: false, +}); + +Deno.test({ + name: "vite dev - @supabase/postgres-js", + fn: async () => { + const res = await fetch(`${demoServer.address()}/tests/supabase_pg`); + const text = await res.text(); + expect(text).toContain("

supabase

"); + }, + sanitizeOps: false, + sanitizeResources: false, +}); + Deno.test({ name: "vite dev - radix", fn: async () => {