lopata 0.4.1 → 0.4.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lopata",
3
- "version": "0.4.1",
3
+ "version": "0.4.2",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -52,6 +52,8 @@ export function devServerPlugin(options: DevServerPluginOptions): Plugin {
52
52
  let currentModule: Record<string, unknown> | null = null
53
53
  // Serializes module reload — prevents concurrent wireClassRefs calls
54
54
  let reloadLock: Promise<void> | null = null
55
+ // Flag set on file change; next request will clear runner cache
56
+ let needsReload = false
55
57
 
56
58
  return {
57
59
  name: 'lopata:dev-server',
@@ -133,7 +135,7 @@ export function devServerPlugin(options: DevServerPluginOptions): Plugin {
133
135
  config,
134
136
  gracePeriodMs: 0,
135
137
  get active() {
136
- return currentModule ? { workerModule: currentModule, env } : null
138
+ return currentModule ? { workerModule: currentModule, env, registry } : null
137
139
  },
138
140
  list() {
139
141
  return []
@@ -165,7 +167,24 @@ export function devServerPlugin(options: DevServerPluginOptions): Plugin {
165
167
  apiMod.setWorkerRegistry(workerRegistry)
166
168
  }
167
169
 
168
- // 5. Set up WebSocket trace streaming on httpServer
170
+ // 5. Track SSR-relevant file changes.
171
+ // Vite's built-in HMR flow invalidates the module graph and sends
172
+ // full-reload events to the runner. However, the runner's async HMR
173
+ // handler can race with incoming requests. We set a flag here and
174
+ // clear the runner's evaluated module cache on the next request,
175
+ // ensuring a clean re-evaluation from the freshly-invalidated module graph.
176
+ server.watcher.on('change', (file) => {
177
+ const ssrEnv = server.environments[options.envName]
178
+ if (!ssrEnv) return
179
+ const normalizedFile = file.replace(/\\/g, '/')
180
+ const mods = ssrEnv.moduleGraph.getModulesByFile(normalizedFile)
181
+ if (mods && mods.size > 0) {
182
+ needsReload = true
183
+ currentModule = null
184
+ }
185
+ })
186
+
187
+ // 6. Set up WebSocket trace streaming on httpServer
169
188
  setupTraceWebSocket(server)
170
189
 
171
190
  // 6. Return middleware callback (post-middleware — runs after framework plugins)
@@ -225,6 +244,19 @@ export function devServerPlugin(options: DevServerPluginOptions): Plugin {
225
244
  // Wait for any in-progress reload before importing
226
245
  if (reloadLock) await reloadLock
227
246
 
247
+ // Clear runner's evaluated module cache when files changed.
248
+ // The module graph is already invalidated by Vite's onFileChange,
249
+ // but the runner caches evaluated modules independently.
250
+ // Using .clear() (like the Cloudflare plugin) wipes all three
251
+ // maps (idToModuleMap, fileToModulesMap, urlToIdModuleMap),
252
+ // forcing a full re-evaluation from the fresh module graph.
253
+ if (needsReload) {
254
+ needsReload = false
255
+ const runner = (ssrEnv as { runner: { evaluatedModules: { clear(): void } } }).runner
256
+ runner.evaluatedModules.clear()
257
+ console.log('[lopata:vite] Cleared runner module cache (file change detected)')
258
+ }
259
+
228
260
  const workerModule = await (ssrEnv as any).runner.import(entrypoint) as Record<string, unknown>
229
261
 
230
262
  // Re-wire class refs when module changes (HMR invalidation)