@cordy/electro-cli 1.2.7 → 1.2.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.mjs +316 -52
- package/package.json +4 -4
package/dist/index.mjs
CHANGED
|
@@ -8,6 +8,7 @@ import { build, createLogger, createServer, mergeConfig, version } from "vite";
|
|
|
8
8
|
import { existsSync } from "node:fs";
|
|
9
9
|
import { tmpdir } from "node:os";
|
|
10
10
|
import { spawn } from "node:child_process";
|
|
11
|
+
import { setTimeout as setTimeout$1 } from "node:timers/promises";
|
|
11
12
|
|
|
12
13
|
//#region ../../node_modules/.bun/cac@6.7.14/node_modules/cac/dist/index.mjs
|
|
13
14
|
function toArr(any) {
|
|
@@ -490,7 +491,7 @@ const cac = (name = "") => new CAC(name);
|
|
|
490
491
|
|
|
491
492
|
//#endregion
|
|
492
493
|
//#region package.json
|
|
493
|
-
var version$1 = "1.2.
|
|
494
|
+
var version$1 = "1.2.10";
|
|
494
495
|
|
|
495
496
|
//#endregion
|
|
496
497
|
//#region src/dev/logger.ts
|
|
@@ -752,7 +753,7 @@ function validateMergedNodeConfig(config, scope) {
|
|
|
752
753
|
const output = rolldownOpts.output;
|
|
753
754
|
if (output && typeof output === "object" && !Array.isArray(output)) {
|
|
754
755
|
const fmt = output.format;
|
|
755
|
-
if (fmt && fmt !== "es") throw new Error(`[electro] ${scope}: invalid output format "${fmt}". Electro
|
|
756
|
+
if (fmt && fmt !== "es" && fmt !== "cjs") throw new Error(`[electro] ${scope}: invalid output format "${fmt}". Electro supports "es" and "cjs" for Node scopes. Update build.rolldownOptions.output.format in your config.`);
|
|
756
757
|
}
|
|
757
758
|
}
|
|
758
759
|
if (config.ssr === false || config.build?.ssr === false) throw new Error(`[electro] ${scope}: SSR cannot be disabled in Node scopes. SSR mode is required for correct Node.js module resolution.`);
|
|
@@ -766,11 +767,6 @@ function enforceMergedNodeConfig(config, _scope) {
|
|
|
766
767
|
const build = config.build;
|
|
767
768
|
if (!build) return;
|
|
768
769
|
if (build.target !== "esnext") build.target = "esnext";
|
|
769
|
-
const rolldownOpts = build.rolldownOptions;
|
|
770
|
-
if (rolldownOpts) {
|
|
771
|
-
const output = rolldownOpts.output;
|
|
772
|
-
if (output && output.format !== "es") output.format = "es";
|
|
773
|
-
}
|
|
774
770
|
if (!build.ssr) build.ssr = true;
|
|
775
771
|
}
|
|
776
772
|
/** Validate that installed Vite version is within the supported range. */
|
|
@@ -805,15 +801,101 @@ async function loadConfig(configPath) {
|
|
|
805
801
|
/**
|
|
806
802
|
* Resolve externals for Node scope builds (main/preload).
|
|
807
803
|
*
|
|
808
|
-
*
|
|
809
|
-
*
|
|
804
|
+
* Auto-externalizes: electron, Node builtins (bare + node: prefixed),
|
|
805
|
+
* package.json dependencies + optionalDependencies, and deep imports (pkg/subpath).
|
|
810
806
|
*/
|
|
811
|
-
function resolveExternals() {
|
|
812
|
-
|
|
807
|
+
async function resolveExternals(root) {
|
|
808
|
+
const pkgPath = resolve(root, "package.json");
|
|
809
|
+
const pkg = JSON.parse(await readFile(pkgPath, "utf-8"));
|
|
810
|
+
const deps = new Set([
|
|
813
811
|
"electron",
|
|
814
|
-
|
|
815
|
-
...
|
|
816
|
-
];
|
|
812
|
+
...Object.keys(pkg.dependencies ?? {}),
|
|
813
|
+
...Object.keys(pkg.optionalDependencies ?? {})
|
|
814
|
+
]);
|
|
815
|
+
deps.delete("@cordy/electro");
|
|
816
|
+
const builtins = builtinModules.flatMap((m) => [m, `node:${m}`]);
|
|
817
|
+
const depsArray = [...deps];
|
|
818
|
+
const cjsInteropDeps = (await Promise.all(depsArray.map(async (dep) => ({
|
|
819
|
+
dep,
|
|
820
|
+
isCommonJs: await isLikelyCommonJsDependency(root, dep)
|
|
821
|
+
})))).filter((entry) => entry.isCommonJs).map((entry) => entry.dep);
|
|
822
|
+
const deepPattern = depsArray.length > 0 ? new RegExp(`^(${depsArray.map(escapeRegExp).join("|")})/.+`) : null;
|
|
823
|
+
return {
|
|
824
|
+
externals: deepPattern ? [
|
|
825
|
+
...depsArray,
|
|
826
|
+
...builtins,
|
|
827
|
+
deepPattern
|
|
828
|
+
] : [...depsArray, ...builtins],
|
|
829
|
+
cjsInteropDeps
|
|
830
|
+
};
|
|
831
|
+
}
|
|
832
|
+
function escapeRegExp(str) {
|
|
833
|
+
return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
834
|
+
}
|
|
835
|
+
async function isLikelyCommonJsDependency(root, dep) {
|
|
836
|
+
if (dep === "electron" || dep.startsWith("node:")) return false;
|
|
837
|
+
const depPkgPath = resolve(root, "node_modules", dep, "package.json");
|
|
838
|
+
try {
|
|
839
|
+
return !isLikelyEsmPackage(JSON.parse(await readFile(depPkgPath, "utf-8")));
|
|
840
|
+
} catch {
|
|
841
|
+
return false;
|
|
842
|
+
}
|
|
843
|
+
}
|
|
844
|
+
function isLikelyEsmPackage(pkg) {
|
|
845
|
+
if (pkg.type === "module") return true;
|
|
846
|
+
if (typeof pkg.module === "string") return true;
|
|
847
|
+
if (typeof pkg.main === "string" && pkg.main.endsWith(".mjs")) return true;
|
|
848
|
+
if (typeof pkg.exports === "string" && pkg.exports.endsWith(".mjs")) return true;
|
|
849
|
+
if (hasImportCondition(pkg.exports)) return true;
|
|
850
|
+
return false;
|
|
851
|
+
}
|
|
852
|
+
function hasImportCondition(value) {
|
|
853
|
+
if (!value || typeof value !== "object") return false;
|
|
854
|
+
if (Array.isArray(value)) return value.some(hasImportCondition);
|
|
855
|
+
const record = value;
|
|
856
|
+
if ("import" in record) return true;
|
|
857
|
+
for (const nested of Object.values(record)) if (hasImportCondition(nested)) return true;
|
|
858
|
+
return false;
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
//#endregion
|
|
862
|
+
//#region src/dev/node-format.ts
|
|
863
|
+
/**
|
|
864
|
+
* Mirrors Node package behavior:
|
|
865
|
+
* - package.json "type": "module" => ESM output
|
|
866
|
+
* - otherwise => CJS output
|
|
867
|
+
*/
|
|
868
|
+
async function resolveNodeOutputFormat(root) {
|
|
869
|
+
const pkgPath = resolve(root, "package.json");
|
|
870
|
+
try {
|
|
871
|
+
const raw = await readFile(pkgPath, "utf-8");
|
|
872
|
+
return JSON.parse(raw).type === "module" ? "es" : "cjs";
|
|
873
|
+
} catch {
|
|
874
|
+
return "cjs";
|
|
875
|
+
}
|
|
876
|
+
}
|
|
877
|
+
const MAIN_ENTRY_CANDIDATES = [
|
|
878
|
+
"index.mjs",
|
|
879
|
+
"index.cjs",
|
|
880
|
+
"index.js"
|
|
881
|
+
];
|
|
882
|
+
/**
|
|
883
|
+
* Find built main entry regardless of selected output format.
|
|
884
|
+
*/
|
|
885
|
+
async function resolveMainEntryPath(mainOutDir) {
|
|
886
|
+
for (const candidate of MAIN_ENTRY_CANDIDATES) {
|
|
887
|
+
const fullPath = resolve(mainOutDir, candidate);
|
|
888
|
+
if (await pathExists(fullPath)) return fullPath;
|
|
889
|
+
}
|
|
890
|
+
throw new Error(`Main entry not found in ${mainOutDir}. Expected one of: ${MAIN_ENTRY_CANDIDATES.join(", ")}`);
|
|
891
|
+
}
|
|
892
|
+
async function pathExists(filePath) {
|
|
893
|
+
try {
|
|
894
|
+
await access(filePath);
|
|
895
|
+
return true;
|
|
896
|
+
} catch {
|
|
897
|
+
return false;
|
|
898
|
+
}
|
|
817
899
|
}
|
|
818
900
|
|
|
819
901
|
//#endregion
|
|
@@ -1829,30 +1911,117 @@ var MagicString = class MagicString {
|
|
|
1829
1911
|
};
|
|
1830
1912
|
|
|
1831
1913
|
//#endregion
|
|
1832
|
-
//#region src/plugins/
|
|
1914
|
+
//#region src/plugins/cjs-external-interop.ts
|
|
1915
|
+
const STATIC_IMPORT_RE = /(?<=\s|^|;)import\s*([\s"']*(?<imports>[\p{L}\p{M}\w\t\n\r $*,/{}@.]+)from\s*)?["']\s*(?<specifier>(?<="\s*)[^"]*[^\s"](?=\s*")|(?<='\s*)[^']*[^\s'](?=\s*'))\s*["'][\s;]*/gmu;
|
|
1916
|
+
const IDENT_RE = /^[A-Za-z_$][\w$]*$/;
|
|
1833
1917
|
/**
|
|
1834
|
-
*
|
|
1835
|
-
*
|
|
1836
|
-
* When bundling CJS dependencies into ESM format, the output may contain
|
|
1837
|
-
* references to `__filename`, `__dirname`, or `require()` which don't exist
|
|
1838
|
-
* in ES modules. This plugin detects those references and injects shims.
|
|
1918
|
+
* Rewrites named imports from external CommonJS deps to runtime-safe accessors.
|
|
1839
1919
|
*
|
|
1840
|
-
*
|
|
1920
|
+
* Example:
|
|
1921
|
+
* import { autoUpdater } from "electron-updater"
|
|
1922
|
+
* becomes
|
|
1923
|
+
* import * as __cjs_ext_0__ from "electron-updater"
|
|
1924
|
+
* const autoUpdater = __cjs_ext_0__.autoUpdater ?? __cjs_ext_0__.default?.autoUpdater
|
|
1841
1925
|
*/
|
|
1842
|
-
|
|
1843
|
-
|
|
1926
|
+
function cjsExternalInteropPlugin(cjsDeps) {
|
|
1927
|
+
if (cjsDeps.length === 0) return {
|
|
1928
|
+
name: "electro:cjs-external-interop",
|
|
1929
|
+
apply: "build"
|
|
1930
|
+
};
|
|
1931
|
+
const cjsDepSet = new Set(cjsDeps);
|
|
1932
|
+
return {
|
|
1933
|
+
name: "electro:cjs-external-interop",
|
|
1934
|
+
apply: "build",
|
|
1935
|
+
enforce: "post",
|
|
1936
|
+
renderChunk(code, _chunk, { format, sourcemap }) {
|
|
1937
|
+
if (format !== "es") return null;
|
|
1938
|
+
let s = null;
|
|
1939
|
+
let counter = 0;
|
|
1940
|
+
for (const match of code.matchAll(STATIC_IMPORT_RE)) {
|
|
1941
|
+
const statement = match[0];
|
|
1942
|
+
const start = match.index ?? 0;
|
|
1943
|
+
const specifier = match.groups?.specifier?.trim();
|
|
1944
|
+
const importsClause = match.groups?.imports?.trim();
|
|
1945
|
+
if (!specifier || !importsClause) continue;
|
|
1946
|
+
if (!isCjsExternalSpecifier(specifier, cjsDepSet)) continue;
|
|
1947
|
+
const parsed = parseImportClause(importsClause);
|
|
1948
|
+
if (!parsed) continue;
|
|
1949
|
+
const ns = `__cjs_ext_${counter++}__`;
|
|
1950
|
+
const lines = [`import * as ${ns} from ${JSON.stringify(specifier)};`];
|
|
1951
|
+
if (parsed.defaultImport) lines.push(`const ${parsed.defaultImport} = ${ns}.default ?? ${ns};`);
|
|
1952
|
+
for (const { imported, local } of parsed.named) lines.push(`const ${local} = ${ns}.${imported} ?? ${ns}.default?.${imported};`);
|
|
1953
|
+
s ??= new MagicString(code);
|
|
1954
|
+
s.overwrite(start, start + statement.length, lines.join("\n"));
|
|
1955
|
+
}
|
|
1956
|
+
if (!s) return null;
|
|
1957
|
+
return {
|
|
1958
|
+
code: s.toString(),
|
|
1959
|
+
map: sourcemap ? s.generateMap({ hires: "boundary" }) : null
|
|
1960
|
+
};
|
|
1961
|
+
}
|
|
1962
|
+
};
|
|
1963
|
+
}
|
|
1964
|
+
function isCjsExternalSpecifier(specifier, cjsDepSet) {
|
|
1965
|
+
if (specifier.startsWith(".") || specifier.startsWith("/") || specifier.startsWith("\0") || specifier.startsWith("node:")) return false;
|
|
1966
|
+
if (cjsDepSet.has(specifier)) return true;
|
|
1967
|
+
for (const dep of cjsDepSet) if (specifier.startsWith(`${dep}/`)) return true;
|
|
1968
|
+
return false;
|
|
1969
|
+
}
|
|
1970
|
+
function parseImportClause(clause) {
|
|
1971
|
+
const braceStart = clause.indexOf("{");
|
|
1972
|
+
const braceEnd = clause.lastIndexOf("}");
|
|
1973
|
+
if (braceStart < 0 || braceEnd < braceStart) return null;
|
|
1974
|
+
const defaultPart = clause.slice(0, braceStart).trim().replace(/,$/, "").trim();
|
|
1975
|
+
if (defaultPart.startsWith("*")) return null;
|
|
1976
|
+
let defaultImport;
|
|
1977
|
+
if (defaultPart.length > 0) {
|
|
1978
|
+
const normalized = defaultPart.replace(/^type\s+/, "").trim();
|
|
1979
|
+
if (!IDENT_RE.test(normalized)) return null;
|
|
1980
|
+
defaultImport = normalized;
|
|
1981
|
+
}
|
|
1982
|
+
const namedPart = clause.slice(braceStart + 1, braceEnd).trim();
|
|
1983
|
+
if (namedPart.length === 0) return null;
|
|
1984
|
+
const named = [];
|
|
1985
|
+
for (const raw of namedPart.split(",")) {
|
|
1986
|
+
const token = raw.trim();
|
|
1987
|
+
if (token.length === 0) continue;
|
|
1988
|
+
const normalized = token.replace(/^type\s+/, "").trim();
|
|
1989
|
+
const match = /^([A-Za-z_$][\w$]*)(?:\s+as\s+([A-Za-z_$][\w$]*))?$/.exec(normalized);
|
|
1990
|
+
if (!match) return null;
|
|
1991
|
+
named.push({
|
|
1992
|
+
imported: match[1],
|
|
1993
|
+
local: match[2] ?? match[1]
|
|
1994
|
+
});
|
|
1995
|
+
}
|
|
1996
|
+
if (named.length === 0) return null;
|
|
1997
|
+
return {
|
|
1998
|
+
defaultImport,
|
|
1999
|
+
named
|
|
2000
|
+
};
|
|
2001
|
+
}
|
|
2002
|
+
|
|
2003
|
+
//#endregion
|
|
2004
|
+
//#region src/plugins/esm-shim.ts
|
|
2005
|
+
const CJSYNTAX_RE = /__filename|__dirname|require\(|require\.resolve\(/;
|
|
2006
|
+
const CJS_SHIM = `
|
|
1844
2007
|
// -- CommonJS Shims --
|
|
1845
|
-
import
|
|
1846
|
-
|
|
1847
|
-
|
|
2008
|
+
import __cjs_url__ from "node:url";
|
|
2009
|
+
import __cjs_path__ from "node:path";
|
|
2010
|
+
import __cjs_mod__ from "node:module";
|
|
2011
|
+
const __filename = __cjs_url__.fileURLToPath(import.meta.url);
|
|
2012
|
+
const __dirname = __cjs_path__.dirname(__filename);
|
|
1848
2013
|
const require = __cjs_mod__.createRequire(import.meta.url);
|
|
1849
2014
|
`;
|
|
1850
|
-
const
|
|
2015
|
+
const ESM_STATIC_IMPORT_RE = /(?<=\s|^|;)import\s*([\s"']*(?<imports>[\p{L}\p{M}\w\t\n\r $*,/{}@.]+)from\s*)?["']\s*(?<specifier>(?<="\s*)[^"]*[^\s"](?=\s*")|(?<='\s*)[^']*[^\s'](?=\s*'))\s*["'][\s;]*/gmu;
|
|
1851
2016
|
function findStaticImports(code) {
|
|
1852
2017
|
const matches = [];
|
|
1853
|
-
for (const match of code.matchAll(
|
|
2018
|
+
for (const match of code.matchAll(ESM_STATIC_IMPORT_RE)) matches.push({ end: (match.index || 0) + match[0].length });
|
|
1854
2019
|
return matches;
|
|
1855
2020
|
}
|
|
2021
|
+
/**
|
|
2022
|
+
* Inject CommonJS shims into ESM output when bundled code contains
|
|
2023
|
+
* require/__dirname/__filename references.
|
|
2024
|
+
*/
|
|
1856
2025
|
function esmShimPlugin() {
|
|
1857
2026
|
return {
|
|
1858
2027
|
name: "electro:esm-shim",
|
|
@@ -1860,11 +2029,11 @@ function esmShimPlugin() {
|
|
|
1860
2029
|
enforce: "post",
|
|
1861
2030
|
renderChunk(code, _chunk, { format, sourcemap }) {
|
|
1862
2031
|
if (format !== "es") return null;
|
|
1863
|
-
if (code.includes(
|
|
1864
|
-
const
|
|
1865
|
-
const indexToAppend =
|
|
2032
|
+
if (code.includes(CJS_SHIM) || !CJSYNTAX_RE.test(code)) return null;
|
|
2033
|
+
const lastImport = findStaticImports(code).pop();
|
|
2034
|
+
const indexToAppend = lastImport ? lastImport.end : 0;
|
|
1866
2035
|
const s = new MagicString(code);
|
|
1867
|
-
s.appendRight(indexToAppend,
|
|
2036
|
+
s.appendRight(indexToAppend, CJS_SHIM);
|
|
1868
2037
|
return {
|
|
1869
2038
|
code: s.toString(),
|
|
1870
2039
|
map: sourcemap ? s.generateMap({ hires: "boundary" }) : null
|
|
@@ -1873,6 +2042,26 @@ function esmShimPlugin() {
|
|
|
1873
2042
|
};
|
|
1874
2043
|
}
|
|
1875
2044
|
|
|
2045
|
+
//#endregion
|
|
2046
|
+
//#region src/plugins/import-meta.ts
|
|
2047
|
+
/**
|
|
2048
|
+
* Rewrites import.meta.* expressions for CommonJS output format.
|
|
2049
|
+
*/
|
|
2050
|
+
function importMetaPlugin() {
|
|
2051
|
+
return {
|
|
2052
|
+
name: "electro:import-meta",
|
|
2053
|
+
apply: "build",
|
|
2054
|
+
enforce: "pre",
|
|
2055
|
+
resolveImportMeta(property, { format }) {
|
|
2056
|
+
if (format !== "cjs") return null;
|
|
2057
|
+
if (property === "url") return `require("node:url").pathToFileURL(__filename).href`;
|
|
2058
|
+
if (property === "filename") return `__filename`;
|
|
2059
|
+
if (property === "dirname") return `__dirname`;
|
|
2060
|
+
return null;
|
|
2061
|
+
}
|
|
2062
|
+
};
|
|
2063
|
+
}
|
|
2064
|
+
|
|
1876
2065
|
//#endregion
|
|
1877
2066
|
//#region src/dev/vite-node-config.ts
|
|
1878
2067
|
function resolveSourcemap$1(mode) {
|
|
@@ -1882,16 +2071,24 @@ function resolveSourcemap$1(mode) {
|
|
|
1882
2071
|
return true;
|
|
1883
2072
|
}
|
|
1884
2073
|
function createNodeConfig(opts) {
|
|
2074
|
+
const format = opts.format ?? "es";
|
|
2075
|
+
const moduleCondition = format === "cjs" ? "require" : "import";
|
|
1885
2076
|
const resolveConditions = opts.scope === "preload" ? [
|
|
1886
2077
|
"node",
|
|
1887
|
-
|
|
2078
|
+
moduleCondition,
|
|
1888
2079
|
"default"
|
|
1889
|
-
] : ["node",
|
|
2080
|
+
] : ["node", moduleCondition];
|
|
1890
2081
|
const envPrefix = opts.scope === "main" ? ["MAIN_VITE_", "VITE_"] : ["PRELOAD_VITE_", "VITE_"];
|
|
2082
|
+
const entryExt = format === "cjs" ? "cjs" : "mjs";
|
|
1891
2083
|
const config = {
|
|
1892
2084
|
configFile: false,
|
|
1893
2085
|
root: opts.root,
|
|
1894
|
-
plugins: [
|
|
2086
|
+
plugins: [
|
|
2087
|
+
importMetaPlugin(),
|
|
2088
|
+
...opts.plugins ?? [],
|
|
2089
|
+
cjsExternalInteropPlugin(opts.cjsInteropDeps ?? []),
|
|
2090
|
+
esmShimPlugin()
|
|
2091
|
+
],
|
|
1895
2092
|
customLogger: opts.customLogger,
|
|
1896
2093
|
envPrefix,
|
|
1897
2094
|
define: {
|
|
@@ -1905,8 +2102,8 @@ function createNodeConfig(opts) {
|
|
|
1905
2102
|
emptyOutDir: true,
|
|
1906
2103
|
rolldownOptions: {
|
|
1907
2104
|
output: {
|
|
1908
|
-
format
|
|
1909
|
-
entryFileNames:
|
|
2105
|
+
format,
|
|
2106
|
+
entryFileNames: `index.${entryExt}`
|
|
1910
2107
|
},
|
|
1911
2108
|
external: opts.externals
|
|
1912
2109
|
},
|
|
@@ -1919,7 +2116,7 @@ function createNodeConfig(opts) {
|
|
|
1919
2116
|
},
|
|
1920
2117
|
ssr: {
|
|
1921
2118
|
target: "node",
|
|
1922
|
-
noExternal:
|
|
2119
|
+
noExternal: ["@cordy/electro"]
|
|
1923
2120
|
},
|
|
1924
2121
|
resolve: { conditions: resolveConditions },
|
|
1925
2122
|
logLevel: opts.logLevel ?? "warn",
|
|
@@ -2689,6 +2886,7 @@ async function build$1(options) {
|
|
|
2689
2886
|
const root = loaded.root;
|
|
2690
2887
|
const outDir = resolve(root, options.outDir);
|
|
2691
2888
|
const codegenDir = resolve(root, ".electro");
|
|
2889
|
+
const nodeFormat = await resolveNodeOutputFormat(root);
|
|
2692
2890
|
const views = config.views ?? [];
|
|
2693
2891
|
const rendererViews = views.filter((v) => v.entry);
|
|
2694
2892
|
const srcDir = resolve(root, "src");
|
|
@@ -2725,7 +2923,9 @@ async function build$1(options) {
|
|
|
2725
2923
|
stepFail("codegen", err instanceof Error ? err.message : String(err));
|
|
2726
2924
|
process.exit(1);
|
|
2727
2925
|
}
|
|
2728
|
-
const
|
|
2926
|
+
const resolvedExternals = await resolveExternals(root);
|
|
2927
|
+
const externals = resolvedExternals.externals;
|
|
2928
|
+
const cjsInteropDeps = resolvedExternals.cjsInteropDeps;
|
|
2729
2929
|
const logger = createBuildLogger();
|
|
2730
2930
|
try {
|
|
2731
2931
|
buildScope("main");
|
|
@@ -2736,7 +2936,9 @@ async function build$1(options) {
|
|
|
2736
2936
|
externals,
|
|
2737
2937
|
sourcemap: options.sourcemap,
|
|
2738
2938
|
logger,
|
|
2739
|
-
bytecode: options.bytecode
|
|
2939
|
+
bytecode: options.bytecode,
|
|
2940
|
+
format: nodeFormat,
|
|
2941
|
+
cjsInteropDeps
|
|
2740
2942
|
});
|
|
2741
2943
|
} catch (err) {
|
|
2742
2944
|
stepFail("main", err instanceof Error ? err.message : String(err));
|
|
@@ -2752,7 +2954,9 @@ async function build$1(options) {
|
|
|
2752
2954
|
externals,
|
|
2753
2955
|
sourcemap: options.sourcemap,
|
|
2754
2956
|
logger,
|
|
2755
|
-
bytecode: options.bytecode
|
|
2957
|
+
bytecode: options.bytecode,
|
|
2958
|
+
format: nodeFormat,
|
|
2959
|
+
cjsInteropDeps
|
|
2756
2960
|
});
|
|
2757
2961
|
} catch (err) {
|
|
2758
2962
|
stepFail("preload", err instanceof Error ? err.message : String(err));
|
|
@@ -2804,6 +3008,8 @@ async function buildMain(args) {
|
|
|
2804
3008
|
sourcemap: args.sourcemap,
|
|
2805
3009
|
customLogger: args.logger,
|
|
2806
3010
|
logLevel: "info",
|
|
3011
|
+
format: args.format,
|
|
3012
|
+
cjsInteropDeps: args.cjsInteropDeps,
|
|
2807
3013
|
define: { __ELECTRO_VIEW_REGISTRY__: JSON.stringify(viewRegistry) }
|
|
2808
3014
|
}));
|
|
2809
3015
|
}
|
|
@@ -2829,7 +3035,9 @@ async function buildPreload(args) {
|
|
|
2829
3035
|
plugins: preloadPlugins,
|
|
2830
3036
|
sourcemap: args.sourcemap,
|
|
2831
3037
|
customLogger: args.logger,
|
|
2832
|
-
logLevel: "info"
|
|
3038
|
+
logLevel: "info",
|
|
3039
|
+
format: args.format,
|
|
3040
|
+
cjsInteropDeps: args.cjsInteropDeps
|
|
2833
3041
|
});
|
|
2834
3042
|
if (Object.keys(input).length > 1) {
|
|
2835
3043
|
const subBuildConfig = createNodeConfig({
|
|
@@ -2846,7 +3054,9 @@ async function buildPreload(args) {
|
|
|
2846
3054
|
],
|
|
2847
3055
|
sourcemap: args.sourcemap,
|
|
2848
3056
|
customLogger: args.logger,
|
|
2849
|
-
logLevel: "info"
|
|
3057
|
+
logLevel: "info",
|
|
3058
|
+
format: args.format,
|
|
3059
|
+
cjsInteropDeps: args.cjsInteropDeps
|
|
2850
3060
|
});
|
|
2851
3061
|
baseConfig.plugins.push(isolateEntriesPlugin(subBuildConfig));
|
|
2852
3062
|
}
|
|
@@ -2891,6 +3101,8 @@ async function flattenRendererOutput(rendererDir, views, root) {
|
|
|
2891
3101
|
//#region src/dev/dev-server.ts
|
|
2892
3102
|
const MAIN_RESTART_DEBOUNCE_MS = 80;
|
|
2893
3103
|
const CONFIG_DEBOUNCE_MS = 300;
|
|
3104
|
+
const MAIN_ENTRY_WAIT_TIMEOUT_MS = 1e4;
|
|
3105
|
+
const MAIN_ENTRY_WAIT_INTERVAL_MS = 50;
|
|
2894
3106
|
var DevServer = class {
|
|
2895
3107
|
rendererServer = null;
|
|
2896
3108
|
electronProcess = null;
|
|
@@ -2909,6 +3121,9 @@ var DevServer = class {
|
|
|
2909
3121
|
mainWatch = null;
|
|
2910
3122
|
preloadWatch = null;
|
|
2911
3123
|
outputDir = "";
|
|
3124
|
+
nodeFormat = "es";
|
|
3125
|
+
mainInitialBuildPromise = null;
|
|
3126
|
+
resolveMainInitialBuild = null;
|
|
2912
3127
|
logLevel;
|
|
2913
3128
|
clearScreen;
|
|
2914
3129
|
rendererOnly;
|
|
@@ -2936,6 +3151,7 @@ var DevServer = class {
|
|
|
2936
3151
|
this.config = loaded.config;
|
|
2937
3152
|
this.root = loaded.root;
|
|
2938
3153
|
this.outputDir = this.outDirOverride ? resolve(this.root, this.outDirOverride) : resolve(this.root, ".electro");
|
|
3154
|
+
this.nodeFormat = await resolveNodeOutputFormat(this.root);
|
|
2939
3155
|
this.configPaths.add(loaded.configPath);
|
|
2940
3156
|
for (const view of this.config.views ?? []) this.configPaths.add(view.__source);
|
|
2941
3157
|
const views = this.config.views ?? [];
|
|
@@ -2976,11 +3192,13 @@ var DevServer = class {
|
|
|
2976
3192
|
this.attachConfigWatcher();
|
|
2977
3193
|
return;
|
|
2978
3194
|
}
|
|
2979
|
-
const
|
|
3195
|
+
const resolvedExternals = await resolveExternals(this.root);
|
|
3196
|
+
const externals = resolvedExternals.externals;
|
|
3197
|
+
const cjsInteropDeps = resolvedExternals.cjsInteropDeps;
|
|
2980
3198
|
if (views.length > 0) {
|
|
2981
3199
|
const preloadTimer = startTimer();
|
|
2982
3200
|
try {
|
|
2983
|
-
await this.buildPreload(externals);
|
|
3201
|
+
await this.buildPreload(externals, cjsInteropDeps);
|
|
2984
3202
|
step("preload", preloadTimer());
|
|
2985
3203
|
} catch (err) {
|
|
2986
3204
|
stepFail("preload", err instanceof Error ? err.message : String(err));
|
|
@@ -2989,7 +3207,7 @@ var DevServer = class {
|
|
|
2989
3207
|
}
|
|
2990
3208
|
const mainBuildTimer = startTimer();
|
|
2991
3209
|
try {
|
|
2992
|
-
await this.buildMain(externals);
|
|
3210
|
+
await this.buildMain(externals, cjsInteropDeps);
|
|
2993
3211
|
step("main", mainBuildTimer());
|
|
2994
3212
|
} catch (err) {
|
|
2995
3213
|
stepFail("main", err instanceof Error ? err.message : String(err));
|
|
@@ -2997,6 +3215,7 @@ var DevServer = class {
|
|
|
2997
3215
|
}
|
|
2998
3216
|
const electronTimer = startTimer();
|
|
2999
3217
|
try {
|
|
3218
|
+
await this.waitForMainInitialBuild();
|
|
3000
3219
|
await this.attachElectronProcess();
|
|
3001
3220
|
step("electron", electronTimer());
|
|
3002
3221
|
} catch (err) {
|
|
@@ -3025,6 +3244,8 @@ var DevServer = class {
|
|
|
3025
3244
|
this.mainWatch = null;
|
|
3026
3245
|
this.preloadWatch?.close();
|
|
3027
3246
|
this.preloadWatch = null;
|
|
3247
|
+
this.resolveMainInitialBuild = null;
|
|
3248
|
+
this.mainInitialBuildPromise = null;
|
|
3028
3249
|
if (this.mainRestartFlushTimer) {
|
|
3029
3250
|
clearTimeout(this.mainRestartFlushTimer);
|
|
3030
3251
|
this.mainRestartFlushTimer = null;
|
|
@@ -3073,7 +3294,7 @@ var DevServer = class {
|
|
|
3073
3294
|
const addr = this.rendererServer.httpServer?.address();
|
|
3074
3295
|
this.rendererUrl = `http://localhost:${typeof addr === "object" && addr ? addr.port : 5173}`;
|
|
3075
3296
|
}
|
|
3076
|
-
async buildPreload(externals) {
|
|
3297
|
+
async buildPreload(externals, cjsInteropDeps) {
|
|
3077
3298
|
const views = (this.config.views ?? []).filter((v) => v.entry);
|
|
3078
3299
|
const preloadOutDir = resolve(this.outputDir, "preload");
|
|
3079
3300
|
const input = {};
|
|
@@ -3093,7 +3314,9 @@ var DevServer = class {
|
|
|
3093
3314
|
],
|
|
3094
3315
|
logLevel: this.logLevel,
|
|
3095
3316
|
clearScreen: this.clearScreen,
|
|
3096
|
-
sourcemap: this.sourcemap
|
|
3317
|
+
sourcemap: this.sourcemap,
|
|
3318
|
+
format: this.nodeFormat,
|
|
3319
|
+
cjsInteropDeps
|
|
3097
3320
|
});
|
|
3098
3321
|
if (Object.keys(input).length > 1) {
|
|
3099
3322
|
const subBuildConfig = createNodeConfig({
|
|
@@ -3110,7 +3333,9 @@ var DevServer = class {
|
|
|
3110
3333
|
],
|
|
3111
3334
|
logLevel: this.logLevel,
|
|
3112
3335
|
clearScreen: this.clearScreen,
|
|
3113
|
-
sourcemap: this.sourcemap
|
|
3336
|
+
sourcemap: this.sourcemap,
|
|
3337
|
+
format: this.nodeFormat,
|
|
3338
|
+
cjsInteropDeps
|
|
3114
3339
|
});
|
|
3115
3340
|
baseConfig.plugins.push(isolateEntriesPlugin(subBuildConfig));
|
|
3116
3341
|
}
|
|
@@ -3136,9 +3361,15 @@ var DevServer = class {
|
|
|
3136
3361
|
});
|
|
3137
3362
|
this.preloadWatch = await build(baseConfig);
|
|
3138
3363
|
}
|
|
3139
|
-
async buildMain(externals) {
|
|
3364
|
+
async buildMain(externals, cjsInteropDeps) {
|
|
3140
3365
|
const runtimeEntry = this.config.runtime.entry;
|
|
3141
3366
|
const entry = resolve(dirname(this.config.runtime.__source), runtimeEntry);
|
|
3367
|
+
this.mainInitialBuildPromise = new Promise((resolve) => {
|
|
3368
|
+
this.resolveMainInitialBuild = () => {
|
|
3369
|
+
resolve();
|
|
3370
|
+
this.resolveMainInitialBuild = null;
|
|
3371
|
+
};
|
|
3372
|
+
});
|
|
3142
3373
|
const viewRegistry = (this.config.views ?? []).map((v) => ({
|
|
3143
3374
|
id: v.name,
|
|
3144
3375
|
hasRenderer: !!v.entry,
|
|
@@ -3161,6 +3392,8 @@ var DevServer = class {
|
|
|
3161
3392
|
clearScreen: this.clearScreen,
|
|
3162
3393
|
userViteConfig: this.config.runtime.vite,
|
|
3163
3394
|
sourcemap: this.sourcemap,
|
|
3395
|
+
format: this.nodeFormat,
|
|
3396
|
+
cjsInteropDeps,
|
|
3164
3397
|
define: { __ELECTRO_VIEW_REGISTRY__: JSON.stringify(viewRegistry) }
|
|
3165
3398
|
});
|
|
3166
3399
|
const self = this;
|
|
@@ -3176,6 +3409,7 @@ var DevServer = class {
|
|
|
3176
3409
|
if (firstBuild) {
|
|
3177
3410
|
firstBuild = false;
|
|
3178
3411
|
changedFile = null;
|
|
3412
|
+
self.resolveMainInitialBuild?.();
|
|
3179
3413
|
return;
|
|
3180
3414
|
}
|
|
3181
3415
|
const currentChanged = changedFile;
|
|
@@ -3191,8 +3425,21 @@ var DevServer = class {
|
|
|
3191
3425
|
});
|
|
3192
3426
|
this.mainWatch = await build(mainConfig);
|
|
3193
3427
|
}
|
|
3428
|
+
/**
|
|
3429
|
+
* Primary startup synchronization for dev mode:
|
|
3430
|
+
* wait until the initial main watch build has completed.
|
|
3431
|
+
*/
|
|
3432
|
+
async waitForMainInitialBuild() {
|
|
3433
|
+
if (!this.mainInitialBuildPromise) return;
|
|
3434
|
+
const timeout = setTimeout$1(MAIN_ENTRY_WAIT_TIMEOUT_MS).then(() => {
|
|
3435
|
+
throw new Error(`Main initial build did not finish in ${MAIN_ENTRY_WAIT_TIMEOUT_MS}ms.`);
|
|
3436
|
+
});
|
|
3437
|
+
const promise = this.mainInitialBuildPromise;
|
|
3438
|
+
this.mainInitialBuildPromise = null;
|
|
3439
|
+
await Promise.race([promise, timeout]);
|
|
3440
|
+
}
|
|
3194
3441
|
async attachElectronProcess() {
|
|
3195
|
-
const mainEntry =
|
|
3442
|
+
const mainEntry = await this.waitForMainEntry();
|
|
3196
3443
|
const env = { ELECTRO_DEV: "true" };
|
|
3197
3444
|
if (this.rendererServer) {
|
|
3198
3445
|
const addr = this.rendererServer.httpServer?.address();
|
|
@@ -3221,6 +3468,23 @@ var DevServer = class {
|
|
|
3221
3468
|
});
|
|
3222
3469
|
}
|
|
3223
3470
|
/**
|
|
3471
|
+
* In watch mode, Vite can return the watcher before the first output file
|
|
3472
|
+
* is written. Wait for the built main entry to appear before spawning Electron.
|
|
3473
|
+
*/
|
|
3474
|
+
async waitForMainEntry() {
|
|
3475
|
+
const mainOutDir = resolve(this.outputDir, "main");
|
|
3476
|
+
const deadline = Date.now() + MAIN_ENTRY_WAIT_TIMEOUT_MS;
|
|
3477
|
+
let lastError;
|
|
3478
|
+
while (Date.now() < deadline) try {
|
|
3479
|
+
return await resolveMainEntryPath(mainOutDir);
|
|
3480
|
+
} catch (err) {
|
|
3481
|
+
lastError = err;
|
|
3482
|
+
await setTimeout$1(MAIN_ENTRY_WAIT_INTERVAL_MS);
|
|
3483
|
+
}
|
|
3484
|
+
const detail = lastError instanceof Error ? ` Last error: ${lastError.message}` : "";
|
|
3485
|
+
throw new Error(`Main entry was not generated in time (${MAIN_ENTRY_WAIT_TIMEOUT_MS}ms). Checked in: ${mainOutDir}.${detail}`);
|
|
3486
|
+
}
|
|
3487
|
+
/**
|
|
3224
3488
|
* Restart Electron — handles queued restarts if another rebuild
|
|
3225
3489
|
* arrives while restart is in flight.
|
|
3226
3490
|
*/
|
|
@@ -3374,7 +3638,7 @@ async function preview(options) {
|
|
|
3374
3638
|
if (!options.skipBuild) await build$1(options);
|
|
3375
3639
|
else note("Skipped build (--skip-build)");
|
|
3376
3640
|
const root = process.cwd();
|
|
3377
|
-
const mainEntry = resolve(resolve(root, options.outDir), "main
|
|
3641
|
+
const mainEntry = await resolveMainEntryPath(resolve(resolve(root, options.outDir), "main"));
|
|
3378
3642
|
const launchTimer = startTimer();
|
|
3379
3643
|
try {
|
|
3380
3644
|
const proc = await launchElectron({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cordy/electro-cli",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.10",
|
|
4
4
|
"description": "CLI for @cordy/electro — dev server, build, and code generation commands",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -47,15 +47,15 @@
|
|
|
47
47
|
"prepublishOnly": "bun run build"
|
|
48
48
|
},
|
|
49
49
|
"peerDependencies": {
|
|
50
|
-
"@cordy/electro": "1.2.
|
|
50
|
+
"@cordy/electro": "1.2.8",
|
|
51
51
|
"electron": ">=40.4.1",
|
|
52
52
|
"vite": ">=8.0.0"
|
|
53
53
|
},
|
|
54
54
|
"dependencies": {
|
|
55
|
-
"@cordy/electro-generator": "1.2.
|
|
55
|
+
"@cordy/electro-generator": "1.2.8"
|
|
56
56
|
},
|
|
57
57
|
"devDependencies": {
|
|
58
|
-
"@cordy/electro": "1.2.
|
|
58
|
+
"@cordy/electro": "1.2.9",
|
|
59
59
|
"@types/node": "^25.2.3",
|
|
60
60
|
"cac": "^6.7.14",
|
|
61
61
|
"electron": "^40.4.1",
|