Unified · Split
| @@ -28,57 +28,6 @@ async function canConnect(host, probePort, timeoutMs = 1_000) { · 27 unmodified lines | |||
| 28 | 28 | ||
| 29 | const f = (p) => path.join(import.meta.dirname, "..", p); | 29 | const f = (p) => path.join(import.meta.dirname, "..", p); |
| 30 | 30 | ||
| 31 | function collectFilesRecursively(rootDir) { | ||
| 32 | const files = []; | ||
| 33 | |||
| 34 | const visit = (dir) => { | ||
| 35 | let entries = []; | ||
| 36 | try { | ||
| 37 | entries = fs.readdirSync(dir, { withFileTypes: true }); | ||
| 38 | } catch { | ||
| 39 | return; | ||
| 40 | } | ||
| 41 | |||
| 42 | for (const entry of entries) { | ||
| 43 | const fullPath = path.join(dir, entry.name); | ||
| 44 | if (entry.isDirectory()) { | ||
| 45 | visit(fullPath); | ||
| 46 | continue; | ||
| 47 | } | ||
| 48 | if (entry.isFile()) { | ||
| 49 | files.push(fullPath); | ||
| 50 | } | ||
| 51 | } | ||
| 52 | }; | ||
| 53 | |||
| 54 | visit(rootDir); | ||
| 55 | return files; | ||
| 56 | } | ||
| 57 | |||
| 58 | function getDesktopBundleFreshnessFloor() { | ||
| 59 | const sourceFiles = [ | ||
| 60 | ...collectFilesRecursively(f("src")), | ||
| 61 | f("tsdown.config.ts"), | ||
| 62 | f("tsconfig.json"), | ||
| 63 | f("package.json"), | ||
| 64 | ]; | ||
| 65 | let newestMtimeMs = 0; | ||
| 66 | |||
| 67 | for (const sourceFile of sourceFiles) { | ||
| 68 | try { | ||
| 69 | const stat = fs.statSync(sourceFile); | ||
| 70 | newestMtimeMs = Math.max(newestMtimeMs, stat.mtimeMs); | ||
| 71 | } catch { | ||
| 72 | // Best-effort: ignore transient or missing files in the readiness floor. | ||
| 73 | } | ||
| 74 | } | ||
| 75 | |||
| 76 | return { | ||
| 77 | newestMtimeMs, | ||
| 78 | sourceFileCount: sourceFiles.length, | ||
| 79 | }; | ||
| 80 | } | ||
| 81 | |||
| 82 | function inspectBundleFile(bundleFile) { | 31 | function inspectBundleFile(bundleFile) { |
| 83 | let stat = null; | 32 | let stat = null; |
| 84 | try { | 33 | try { |
| @@ -92,15 +41,6 @@ function inspectBundleFile(bundleFile) { · 7 unmodified lines | |||
| 92 | }; | 41 | }; |
| 93 | } | 42 | } |
| 94 | 43 | ||
| 95 | if (bundleFile.freshnessFloorMs > 0 && stat.mtimeMs < bundleFile.freshnessFloorMs) { | ||
| 96 | return { | ||
| 97 | ...bundleFile, | ||
| 98 | status: "outdated", | ||
| 99 | mtimeMs: stat.mtimeMs, | ||
| 100 | reason: `mtime older than source floor by ${Math.round(bundleFile.freshnessFloorMs - stat.mtimeMs)}ms`, | ||
| 101 | }; | ||
| 102 | } | ||
| 103 | |||
| 104 | return { | 44 | return { |
| 105 | ...bundleFile, | 45 | ...bundleFile, |
| 106 | status: "ready", | 46 | status: "ready", |
| @@ -121,28 +61,18 @@ function describeBundleStates(states) { · 14 unmodified lines | |||
| 121 | 61 | ||
| 122 | function waitForDesktopBundles(timeoutMs) { | 62 | function waitForDesktopBundles(timeoutMs) { |
| 123 | const startedAt = Date.now(); | 63 | const startedAt = Date.now(); |
| 124 | const desktopFloor = getDesktopBundleFreshnessFloor(); | ||
| 125 | if (desktopFloor.newestMtimeMs > 0) { | ||
| 126 | console.log( | ||
| 127 | `[dev-electron] desktop bundle freshness floor=${new Date(desktopFloor.newestMtimeMs).toISOString()} from ${desktopFloor.sourceFileCount} source files`, | ||
| 128 | ); | ||
| 129 | } | ||
| 130 | |||
| 131 | const bundleFiles = [ | 64 | const bundleFiles = [ |
| 132 | { | 65 | { |
| 133 | path: f("dist-electron/main.mjs"), | 66 | path: f("dist-electron/main.mjs"), |
| 134 | label: "desktop/main.mjs", | 67 | label: "desktop/main.mjs", |
| 135 | freshnessFloorMs: desktopFloor.newestMtimeMs, | ||
| 136 | }, | 68 | }, |
| 137 | { | 69 | { |
| 138 | path: f("dist-electron/preload.cjs"), | 70 | path: f("dist-electron/preload.cjs"), |
| 139 | label: "desktop/preload.cjs", | 71 | label: "desktop/preload.cjs", |
| 140 | freshnessFloorMs: desktopFloor.newestMtimeMs, | ||
| 141 | }, | 72 | }, |
| 142 | { | 73 | { |
| 143 | path: f("../server/dist/index.mjs"), | 74 | path: f("../server/dist/index.mjs"), |
| 144 | label: "server/index.mjs", | 75 | label: "server/index.mjs", |
| 145 | freshnessFloorMs: 0, | ||
| 146 | }, | 76 | }, |
| 147 | ]; | 77 | ]; |
| 148 | let lastProgressLogAt = 0; | 78 | let lastProgressLogAt = 0; |
| @@ -151,9 +81,8 @@ function waitForDesktopBundles(timeoutMs) { · 2 unmodified lines | |||
| 151 | const tick = () => { | 81 | const tick = () => { |
| 152 | const states = bundleFiles.map(inspectBundleFile); | 82 | const states = bundleFiles.map(inspectBundleFile); |
| 153 | const missing = states.filter((state) => state.status === "missing"); | 83 | const missing = states.filter((state) => state.status === "missing"); |
| 154 | const outdated = states.filter((state) => state.status === "outdated"); | ||
| 155 | 84 | ||
| 156 | if (missing.length === 0 && outdated.length === 0) { | 85 | if (missing.length === 0) { |
| 157 | resolve(); | 86 | resolve(); |
| 158 | return; | 87 | return; |
| 159 | } | 88 | } |
| @@ -164,9 +93,6 @@ function waitForDesktopBundles(timeoutMs) { · 4 unmodified lines | |||
| 164 | if (missing.length > 0) { | 93 | if (missing.length > 0) { |
| 165 | parts.push(`missing: ${missing.map((state) => state.label).join(", ")}`); | 94 | parts.push(`missing: ${missing.map((state) => state.label).join(", ")}`); |
| 166 | } | 95 | } |
| 167 | if (outdated.length > 0) { | ||
| 168 | parts.push(`outdated: ${outdated.map((state) => state.label).join(", ")}`); | ||
| 169 | } | ||
| 170 | reject( | 96 | reject( |
| 171 | new Error( | 97 | new Error( |
| 172 | `[dev-electron] timed out after ${timeoutMs}ms waiting for bundles (${parts.join("; ")})\n[dev-electron] bundle state: ${describeBundleStates(states)}`, | 98 | `[dev-electron] timed out after ${timeoutMs}ms waiting for bundles (${parts.join("; ")})\n[dev-electron] bundle state: ${describeBundleStates(states)}`, |
| @@ -181,9 +107,6 @@ function waitForDesktopBundles(timeoutMs) { · 8 unmodified lines | |||
| 181 | if (missing.length > 0) { | 107 | if (missing.length > 0) { |
| 182 | waitParts.push(`missing=${missing.map((state) => state.label).join(",")}`); | 108 | waitParts.push(`missing=${missing.map((state) => state.label).join(",")}`); |
| 183 | } | 109 | } |
| 184 | if (outdated.length > 0) { | ||
| 185 | waitParts.push(`outdated=${outdated.map((state) => state.label).join(",")}`); | ||
| 186 | } | ||
| 187 | console.log( | 110 | console.log( |
| 188 | `[dev-electron] still waiting for bundles after ${elapsedMs}ms (${waitParts.join("; ")})`, | 111 | `[dev-electron] still waiting for bundles after ${elapsedMs}ms (${waitParts.join("; ")})`, |
| 189 | ); | 112 | ); |