mirror of
https://github.com/webadderallorg/Recordly.git
synced 2026-09-24 06:46:09 +00:00
fix(electron): force main bundle cjs output
This commit is contained in:
@@ -0,0 +1,46 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import {
|
||||
findElectronMainCjsEsmSyntax,
|
||||
normalizeElectronMainCjsSource,
|
||||
} from "../scripts/normalize-electron-main-cjs.mjs";
|
||||
|
||||
describe("Electron main CJS normalizer", () => {
|
||||
it("converts Rollup named export blocks to CommonJS assignments", () => {
|
||||
const source = [
|
||||
'const MAIN_DIST = "dist-electron";',
|
||||
'const RENDERER_DIST = "dist";',
|
||||
"const VITE_DEV_SERVER_URL = process.env.VITE_DEV_SERVER_URL;",
|
||||
"export {",
|
||||
" MAIN_DIST,",
|
||||
" RENDERER_DIST,",
|
||||
" VITE_DEV_SERVER_URL",
|
||||
"};",
|
||||
].join("\n");
|
||||
|
||||
const result = normalizeElectronMainCjsSource(source);
|
||||
|
||||
expect(result.changed).toBe(true);
|
||||
expect(result.source).toContain("exports.MAIN_DIST = MAIN_DIST;");
|
||||
expect(result.source).toContain("exports.RENDERER_DIST = RENDERER_DIST;");
|
||||
expect(result.source).toContain("exports.VITE_DEV_SERVER_URL = VITE_DEV_SERVER_URL;");
|
||||
expect(findElectronMainCjsEsmSyntax(result.source)).toEqual([]);
|
||||
});
|
||||
|
||||
it("converts single-line aliased named exports to CommonJS assignments", () => {
|
||||
const source = "export { VITE_DEV_SERVER_URL as devServerUrl };";
|
||||
|
||||
const result = normalizeElectronMainCjsSource(source);
|
||||
|
||||
expect(result.changed).toBe(true);
|
||||
expect(result.source).toBe("exports.devServerUrl = VITE_DEV_SERVER_URL;");
|
||||
expect(findElectronMainCjsEsmSyntax(result.source)).toEqual([]);
|
||||
});
|
||||
|
||||
it("reports unsupported ESM export syntax that cannot be normalized safely", () => {
|
||||
const source = "export default MAIN_DIST;";
|
||||
|
||||
expect(findElectronMainCjsEsmSyntax(source)).toEqual([
|
||||
{ line: 1, text: "export default MAIN_DIST;" },
|
||||
]);
|
||||
});
|
||||
});
|
||||
@@ -49,6 +49,49 @@ function convertImportLine(line) {
|
||||
return null;
|
||||
}
|
||||
|
||||
function convertNamedExports(namedSpec, indent = "") {
|
||||
const statements = [];
|
||||
for (const rawSpecifier of namedSpec.split(",")) {
|
||||
const specifier = rawSpecifier.trim();
|
||||
if (!specifier) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const aliasMatch = specifier.match(
|
||||
/^([A-Za-z_$][A-Za-z0-9_$]*)\s+as\s+([A-Za-z_$][A-Za-z0-9_$]*)$/,
|
||||
);
|
||||
const localName = aliasMatch ? aliasMatch[1] : specifier;
|
||||
const exportName = aliasMatch ? aliasMatch[2] : specifier;
|
||||
if (
|
||||
!/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(localName) ||
|
||||
!/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(exportName)
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
statements.push(`${indent}exports.${exportName} = ${localName};`);
|
||||
}
|
||||
|
||||
return statements;
|
||||
}
|
||||
|
||||
function convertExportLine(line) {
|
||||
const singleLineMatch = line.match(
|
||||
/^([ \t]*)export\s*\{\s*([^}]*)\s*\}\s*;?[ \t]*$/,
|
||||
);
|
||||
if (singleLineMatch) {
|
||||
const [, indent, namedSpec] = singleLineMatch;
|
||||
return convertNamedExports(namedSpec, indent);
|
||||
}
|
||||
|
||||
const blockStartMatch = line.match(/^([ \t]*)export\s*\{\s*$/);
|
||||
if (blockStartMatch) {
|
||||
return { indent: blockStartMatch[1], specifiers: [] };
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function updateLexicalState(line, state) {
|
||||
let mode = state.mode;
|
||||
let escaped = false;
|
||||
@@ -296,8 +339,29 @@ export function normalizeElectronMainCjsSource(source) {
|
||||
const lines = source.split(/\r?\n/);
|
||||
const normalizedLines = [];
|
||||
let state = { mode: null };
|
||||
let exportBlock = null;
|
||||
|
||||
for (const line of lines) {
|
||||
if (exportBlock) {
|
||||
if (/^[ \t]*\}\s*;?[ \t]*$/.test(line)) {
|
||||
const statements = convertNamedExports(
|
||||
exportBlock.specifiers.join(","),
|
||||
exportBlock.indent,
|
||||
);
|
||||
if (statements === null) {
|
||||
normalizedLines.push(`export {\n${exportBlock.specifiers.join("\n")}\n};`);
|
||||
} else {
|
||||
normalizedLines.push(...statements);
|
||||
changed = true;
|
||||
}
|
||||
exportBlock = null;
|
||||
continue;
|
||||
}
|
||||
|
||||
exportBlock.specifiers.push(line.trim().replace(/,$/, ""));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (state.mode === null) {
|
||||
const converted = convertImportLine(line);
|
||||
if (converted !== null) {
|
||||
@@ -305,6 +369,17 @@ export function normalizeElectronMainCjsSource(source) {
|
||||
changed = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
const convertedExport = convertExportLine(line);
|
||||
if (convertedExport !== null) {
|
||||
if (Array.isArray(convertedExport)) {
|
||||
normalizedLines.push(...convertedExport);
|
||||
changed = true;
|
||||
} else {
|
||||
exportBlock = convertedExport;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
const normalized = replaceImportMetaUrlInCode(line, state);
|
||||
@@ -348,6 +423,13 @@ export function findElectronMainCjsEsmSyntax(source) {
|
||||
});
|
||||
continue;
|
||||
}
|
||||
if (/^[ \t]*export\b/.test(line)) {
|
||||
matches.push({
|
||||
line: index + 1,
|
||||
text: line.trim(),
|
||||
});
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
state = updateLexicalState(line, state);
|
||||
|
||||
+34
-2
@@ -4,6 +4,36 @@ import react from "@vitejs/plugin-react";
|
||||
import { defineConfig, type Plugin } from "vite";
|
||||
import electron from "vite-plugin-electron/simple";
|
||||
|
||||
function electronMainCjsOutputPlugin(): Plugin {
|
||||
return {
|
||||
name: "recordly-electron-main-cjs-output",
|
||||
enforce: "post",
|
||||
config(config) {
|
||||
// Vite mergeConfig concatenates lib.formats with the plugin's ESM default.
|
||||
config.build ??= {};
|
||||
const build = config.build;
|
||||
const lib = build.lib;
|
||||
if (lib && typeof lib === "object") {
|
||||
lib.formats = ["cjs"];
|
||||
lib.fileName = (_format, entryName) => `${entryName}.cjs`;
|
||||
}
|
||||
|
||||
build.rollupOptions ??= {};
|
||||
const rollupOptions = build.rollupOptions;
|
||||
const cjsOutput = {
|
||||
format: "cjs" as const,
|
||||
inlineDynamicImports: true,
|
||||
entryFileNames: "[name].cjs",
|
||||
chunkFileNames: "[name]-[hash].cjs",
|
||||
};
|
||||
|
||||
rollupOptions.output = Array.isArray(rollupOptions.output)
|
||||
? rollupOptions.output.map((output) => ({ ...output, ...cjsOutput }))
|
||||
: { ...(rollupOptions.output ?? {}), ...cjsOutput };
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function electronMainCjsGuardPlugin(): Plugin {
|
||||
return {
|
||||
name: "recordly-electron-main-cjs-guard",
|
||||
@@ -37,17 +67,19 @@ export default defineConfig({
|
||||
lib: {
|
||||
entry: "electron/main.ts",
|
||||
formats: ["cjs"],
|
||||
fileName: (_format, entryName) => `${entryName}.cjs`,
|
||||
},
|
||||
rollupOptions: {
|
||||
external: ["ffmpeg-static", "uiohook-napi"],
|
||||
output: {
|
||||
format: "cjs",
|
||||
inlineDynamicImports: true,
|
||||
entryFileNames: "[name].cjs",
|
||||
chunkFileNames: "[name].cjs",
|
||||
chunkFileNames: "[name]-[hash].cjs",
|
||||
},
|
||||
},
|
||||
},
|
||||
plugins: [electronMainCjsGuardPlugin()],
|
||||
plugins: [electronMainCjsOutputPlugin(), electronMainCjsGuardPlugin()],
|
||||
},
|
||||
},
|
||||
preload: {
|
||||
|
||||
Reference in New Issue
Block a user