@foldkit/vite-plugin 0.3.1 → 0.4.0

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.
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EAAE,MAAM,EAAkC,MAAM,MAAM,CAAA;AAGlE,6CAA6C;AAC7C,MAAM,MAAM,oBAAoB,GAAG,QAAQ,CAAC;IAC1C;;;;;OAKG;IACH,eAAe,CAAC,EAAE,MAAM,CAAA;CACzB,CAAC,CAAA;AAqBF,eAAO,MAAM,OAAO,GAAI,UAAS,oBAAyB,KAAG,MAO5D,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AA+BA,OAAO,KAAK,EAAE,MAAM,EAAkC,MAAM,MAAM,CAAA;AAGlE,6CAA6C;AAC7C,MAAM,MAAM,oBAAoB,GAAG,QAAQ,CAAC;IAC1C;;;;;OAKG;IACH,eAAe,CAAC,EAAE,MAAM,CAAA;CACzB,CAAC,CAAA;AAofF,eAAO,MAAM,OAAO,GAAI,UAAS,oBAAyB,KAAG,MAgC5D,CAAA"}
package/dist/index.js CHANGED
@@ -1,174 +1,268 @@
1
- import { Array, Effect, Either, HashMap, HashSet, Match, Option, Ref, Schema as S, pipe, } from 'effect';
1
+ import { Array, Console, Data, Effect, Exit, Fiber, HashMap, HashSet, Match as M, Option, Queue, Ref, Schema as S, Stream, pipe, } from 'effect';
2
2
  import { EventFrame, RequestFrame, ResponseFrame, ResponseRuntimes, } from 'foldkit/devtools-protocol';
3
+ import { PreserveModelMessage, RequestModelMessage, RestoreModelMessage, } from 'foldkit/hmr-protocol';
3
4
  import { WebSocketServer } from 'ws';
4
- let preservedModel = undefined;
5
- let isHmrReload = false;
6
- const connectedRuntimesRef = Ref.unsafeMake(HashMap.empty());
7
- const mcpClientsRef = Ref.unsafeMake(HashSet.empty());
8
- const clientConnectionsRef = Ref.unsafeMake(HashMap.empty());
9
- const trackedClientsRef = Ref.unsafeMake(HashSet.empty());
10
- let viteServer = null;
11
- let mcpWebSocketServer = null;
12
- export const foldkit = (options = {}) => {
13
- return {
14
- name: 'foldkit-hmr',
15
- apply: 'serve',
16
- configureServer: server => configureServer(server, options),
17
- handleHotUpdate,
5
+ // NOTE: Vite's dep optimizer scans the consumer's source for `effect`
6
+ // imports and pre-bundles only those exports into a single `effect.js`
7
+ // blob. It does not follow imports through workspace/node_modules
8
+ // packages, so any `effect` namespace foldkit's compiled dist references
9
+ // that the consumer does not mention by name is missing from the blob
10
+ // and crashes at runtime in dev. The list below covers every top-level
11
+ // namespace foldkit imports from bare `'effect'`. Over-inclusion is
12
+ // harmless; under-inclusion is the bug. Kept in sync with foldkit's
13
+ // source by `scripts/check-effect-prebundle.ts` (runs in `pnpm check`).
14
+ const FORCE_INCLUDED_EFFECT_NAMESPACES = [
15
+ 'effect/Array',
16
+ 'effect/Cause',
17
+ 'effect/Clock',
18
+ 'effect/Context',
19
+ 'effect/Data',
20
+ 'effect/DateTime',
21
+ 'effect/Duration',
22
+ 'effect/Effect',
23
+ 'effect/Equal',
24
+ 'effect/Equivalence',
25
+ 'effect/Exit',
26
+ 'effect/Fiber',
27
+ 'effect/Function',
28
+ 'effect/Hash',
29
+ 'effect/HashMap',
30
+ 'effect/HashSet',
31
+ 'effect/Layer',
32
+ 'effect/Match',
33
+ 'effect/Number',
34
+ 'effect/Option',
35
+ 'effect/Order',
36
+ 'effect/Predicate',
37
+ 'effect/PubSub',
38
+ 'effect/Queue',
39
+ 'effect/Record',
40
+ 'effect/Ref',
41
+ 'effect/Result',
42
+ 'effect/Scheduler',
43
+ 'effect/Schema',
44
+ 'effect/SchemaIssue',
45
+ 'effect/SchemaTransformation',
46
+ 'effect/Stream',
47
+ 'effect/String',
48
+ 'effect/Struct',
49
+ 'effect/SubscriptionRef',
50
+ 'effect/Types',
51
+ ];
52
+ const Event = Data.taggedEnum();
53
+ const makeState = Effect.gen(function* () {
54
+ const preservedModels = yield* Ref.make(HashMap.empty());
55
+ const connectedRuntimes = yield* Ref.make(HashMap.empty());
56
+ const mcpClients = yield* Ref.make(HashSet.empty());
57
+ const clientConnections = yield* Ref.make(HashMap.empty());
58
+ const trackedClients = yield* Ref.make(HashSet.empty());
59
+ const state = {
60
+ preservedModels,
61
+ connectedRuntimes,
62
+ mcpClients,
63
+ clientConnections,
64
+ trackedClients,
18
65
  };
19
- };
20
- const configureServer = (server, options) => {
21
- viteServer = server;
22
- server.ws.on('foldkit:preserve-model', model => {
23
- preservedModel = model;
66
+ return state;
67
+ });
68
+ const encodeResponseFrameJson = S.encodeUnknownSync(S.fromJsonString(ResponseFrame));
69
+ // HANDLERS
70
+ const handlePreserveModelReceived = (state, payload) => Exit.match(S.decodeUnknownExit(PreserveModelMessage)(payload), {
71
+ onFailure: error => Console.warn('[foldkit:hmr] failed to decode preserve-model payload', error),
72
+ onSuccess: ({ id, model }) => {
73
+ const entry = { model, isHmrReload: false };
74
+ return Ref.update(state.preservedModels, HashMap.set(id, entry));
75
+ },
76
+ });
77
+ const handleRequestModelReceived = (server, state, payload) => Exit.match(S.decodeUnknownExit(RequestModelMessage)(payload), {
78
+ onFailure: error => Console.warn('[foldkit:hmr] failed to decode request-model payload', error),
79
+ onSuccess: ({ id }) => Effect.gen(function* () {
80
+ const current = yield* Ref.get(state.preservedModels);
81
+ const sendRestore = (model) => Effect.sync(() => server.ws.send('foldkit:restore-model', S.encodeUnknownSync(RestoreModelMessage)(RestoreModelMessage.make({ id, model }))));
82
+ yield* Option.match(HashMap.get(current, id), {
83
+ onNone: () => sendRestore(undefined),
84
+ onSome: entry => {
85
+ if (entry.isHmrReload) {
86
+ const served = { ...entry, isHmrReload: false };
87
+ return Ref.update(state.preservedModels, HashMap.set(id, served)).pipe(Effect.flatMap(() => sendRestore(entry.model)));
88
+ }
89
+ return Ref.update(state.preservedModels, HashMap.remove(id)).pipe(Effect.flatMap(() => sendRestore(undefined)));
90
+ },
91
+ });
92
+ }),
93
+ });
94
+ const handleHotUpdateFired = (state) => Ref.update(state.preservedModels, current => HashMap.map(current, entry => ({ ...entry, isHmrReload: true })));
95
+ const handleBrowserEventFrameReceived = (state, data, client) => Exit.match(S.decodeUnknownExit(EventFrame)(data), {
96
+ onFailure: error => Console.warn('[foldkit:devTools] failed to decode browser event frame', error),
97
+ onSuccess: frame => M.value(frame.event).pipe(M.tagsExhaustive({
98
+ EventConnected: event => handleConnectedEvent(state, event, client),
99
+ EventDisconnected: event => handleDisconnectedEvent(state, event),
100
+ })),
101
+ });
102
+ const handleConnectedEvent = (state, event, client) => Effect.gen(function* () {
103
+ yield* Ref.update(state.connectedRuntimes, HashMap.set(event.runtime.connectionId, event.runtime));
104
+ yield* Ref.update(state.clientConnections, currentMap => {
105
+ const existing = HashMap.get(currentMap, client).pipe(Option.getOrElse(() => HashSet.empty()));
106
+ return HashMap.set(currentMap, client, HashSet.add(existing, event.runtime.connectionId));
24
107
  });
25
- server.ws.on('foldkit:request-model', () => {
26
- server.ws.send('foldkit:restore-model', isHmrReload ? preservedModel : undefined);
27
- if (!isHmrReload) {
28
- preservedModel = undefined;
29
- }
30
- isHmrReload = false;
108
+ yield* Console.log(`[foldkit:devTools] runtime connected: ${event.runtime.connectionId} (${event.runtime.title})`);
109
+ });
110
+ const handleDisconnectedEvent = (state, event) => Effect.gen(function* () {
111
+ yield* Ref.update(state.connectedRuntimes, HashMap.remove(event.connectionId));
112
+ yield* Console.log(`[foldkit:devTools] runtime disconnected: ${event.connectionId}`);
113
+ });
114
+ const pruneRuntime = (state, connectionId) => Effect.gen(function* () {
115
+ yield* Ref.update(state.connectedRuntimes, HashMap.remove(connectionId));
116
+ yield* Console.log(`[foldkit:devTools] runtime pruned (socket close): ${connectionId}`);
117
+ });
118
+ const pruneRuntimesForClient = (state, connectionIds) => Effect.forEach(Array.fromIterable(connectionIds), connectionId => pruneRuntime(state, connectionId), { discard: true });
119
+ const handleViteClientClosed = (state, client) => Effect.gen(function* () {
120
+ const connections = yield* Ref.get(state.clientConnections);
121
+ yield* Option.match(HashMap.get(connections, client), {
122
+ onNone: () => Effect.void,
123
+ onSome: connectionIds => pruneRuntimesForClient(state, connectionIds),
31
124
  });
32
- server.ws.on('foldkit:devTools:event', (data, client) => {
33
- ensureClientTracked(client);
34
- handleBrowserEventFrame(data, client);
125
+ yield* Ref.update(state.clientConnections, HashMap.remove(client));
126
+ yield* Ref.update(state.trackedClients, HashSet.remove(client));
127
+ });
128
+ const handleBrowserResponseFrameReceived = (state, data) => Exit.match(S.decodeUnknownExit(ResponseFrame)(data), {
129
+ onFailure: error => Console.warn('[foldkit:devTools] failed to decode browser response frame', error),
130
+ onSuccess: frame => broadcastResponseToMcpClients(state, frame),
131
+ });
132
+ const broadcastResponseToMcpClients = (state, frame) => Effect.gen(function* () {
133
+ const clients = yield* Ref.get(state.mcpClients);
134
+ const payload = encodeResponseFrameJson(frame);
135
+ yield* Effect.sync(() => {
136
+ for (const client of clients) {
137
+ if (client.readyState === client.OPEN) {
138
+ client.send(payload);
139
+ }
140
+ }
35
141
  });
36
- server.ws.on('foldkit:devTools:response', (data) => {
37
- handleBrowserResponseFrame(data);
142
+ });
143
+ const handleMcpClientConnected = (state, client) => Effect.gen(function* () {
144
+ yield* Ref.update(state.mcpClients, HashSet.add(client));
145
+ const total = HashSet.size(yield* Ref.get(state.mcpClients));
146
+ yield* Console.log(`[foldkit:devTools] MCP client connected (${total} total)`);
147
+ });
148
+ const handleMcpClientDisconnected = (state, client) => Effect.gen(function* () {
149
+ yield* Ref.update(state.mcpClients, HashSet.remove(client));
150
+ const remaining = HashSet.size(yield* Ref.get(state.mcpClients));
151
+ yield* Console.log(`[foldkit:devTools] MCP client disconnected (${remaining} remaining)`);
152
+ });
153
+ const handleMcpRequestReceived = (server, state, client, raw) => Exit.match(S.decodeUnknownExit(S.fromJsonString(RequestFrame))(raw), {
154
+ onFailure: error => Console.warn('[foldkit:devTools] failed to decode MCP request frame', error),
155
+ onSuccess: frame => M.value(frame.request).pipe(M.tag('RequestListRuntimes', () => replyListRuntimes(state, client, frame.id)), M.orElse(() => forwardRequestToBrowsers(server, frame))),
156
+ });
157
+ const replyListRuntimes = (state, client, requestId) => Effect.gen(function* () {
158
+ const runtimes = pipe(yield* Ref.get(state.connectedRuntimes), HashMap.values, Array.fromIterable);
159
+ const responseFrame = {
160
+ id: requestId,
161
+ response: ResponseRuntimes({ runtimes }),
162
+ };
163
+ yield* Effect.sync(() => {
164
+ if (client.readyState === client.OPEN) {
165
+ client.send(encodeResponseFrameJson(responseFrame));
166
+ }
38
167
  });
39
- if (options.devToolsMcpPort !== undefined) {
40
- startMcpWebSocketServer(options.devToolsMcpPort);
41
- server.httpServer?.on('close', stopMcpWebSocketServer);
168
+ });
169
+ const forwardRequestToBrowsers = (server, frame) => Effect.sync(() => server.ws.send('foldkit:devTools:request', S.encodeUnknownSync(RequestFrame)(frame)));
170
+ // EVENT DISPATCH
171
+ const dispatchEvent = (server, state, event) => M.value(event).pipe(M.tagsExhaustive({
172
+ PreserveModelReceived: ({ payload }) => handlePreserveModelReceived(state, payload),
173
+ RequestModelReceived: ({ payload }) => handleRequestModelReceived(server, state, payload),
174
+ BrowserEventFrameReceived: ({ data, client }) => handleBrowserEventFrameReceived(state, data, client),
175
+ BrowserResponseFrameReceived: ({ data }) => handleBrowserResponseFrameReceived(state, data),
176
+ ViteClientClosed: ({ client }) => handleViteClientClosed(state, client),
177
+ HotUpdateFired: () => handleHotUpdateFired(state),
178
+ McpClientConnected: ({ client }) => handleMcpClientConnected(state, client),
179
+ McpClientDisconnected: ({ client }) => handleMcpClientDisconnected(state, client),
180
+ McpRequestReceived: ({ client, raw }) => handleMcpRequestReceived(server, state, client, raw),
181
+ }));
182
+ // VITE WS BRIDGE
183
+ const ensureClientTracked = (state, client, enqueue) => Effect.gen(function* () {
184
+ const tracked = yield* Ref.get(state.trackedClients);
185
+ if (HashSet.has(tracked, client)) {
186
+ return;
42
187
  }
43
- };
44
- const startMcpWebSocketServer = (port) => {
188
+ yield* Ref.update(state.trackedClients, HashSet.add(client));
189
+ yield* Effect.sync(() => client.socket.on('close', () => enqueue(Event.ViteClientClosed({ client }))));
190
+ });
191
+ const registerViteWsHandlers = (server, state, enqueue) => Effect.sync(() => {
192
+ server.ws.on('foldkit:preserve-model', payload => enqueue(Event.PreserveModelReceived({ payload })));
193
+ server.ws.on('foldkit:request-model', payload => enqueue(Event.RequestModelReceived({ payload })));
194
+ server.ws.on('foldkit:devTools:event', (data, client) => {
195
+ Effect.runFork(ensureClientTracked(state, client, enqueue));
196
+ enqueue(Event.BrowserEventFrameReceived({ data, client }));
197
+ });
198
+ server.ws.on('foldkit:devTools:response', (data) => enqueue(Event.BrowserResponseFrameReceived({ data })));
199
+ });
200
+ // MCP RELAY
201
+ const startMcpRelay = (port, enqueue) => Effect.acquireRelease(Effect.sync(() => {
45
202
  const wss = new WebSocketServer({ port });
46
- mcpWebSocketServer = wss;
47
203
  wss.on('error', error => {
48
- console.error(`[foldkit:devTools] MCP relay failed to start on port ${port}; continuing without the relay`, error);
49
- mcpWebSocketServer = null;
204
+ if ('code' in error && error.code === 'EADDRINUSE') {
205
+ console.error(`\n[foldkit:devTools] Port ${port} is already in use, so the DevTools MCP relay could not start.\n` +
206
+ `[foldkit:devTools] This usually means another Foldkit project is already running and bound to this port.\n` +
207
+ `[foldkit:devTools] Until the port is freed, agents will not be able to connect to this app via the Foldkit DevTools MCP server.\n` +
208
+ `[foldkit:devTools] Stop the other project, or set a different \`devToolsMcpPort\` in this project's vite config.\n`);
209
+ }
210
+ else {
211
+ console.error(`[foldkit:devTools] MCP relay failed to start on port ${port}; continuing without the relay`, error);
212
+ }
50
213
  });
51
214
  wss.on('connection', client => {
52
- Effect.runSync(Ref.update(mcpClientsRef, HashSet.add(client)));
53
- const total = HashSet.size(Effect.runSync(Ref.get(mcpClientsRef)));
54
- console.log(`[foldkit:devTools] MCP client connected (${total} total)`);
55
- client.on('message', raw => {
56
- handleMcpMessage(client, raw.toString());
57
- });
58
- client.on('close', () => {
59
- Effect.runSync(Ref.update(mcpClientsRef, HashSet.remove(client)));
60
- const remaining = HashSet.size(Effect.runSync(Ref.get(mcpClientsRef)));
61
- console.log(`[foldkit:devTools] MCP client disconnected (${remaining} remaining)`);
62
- });
215
+ enqueue(Event.McpClientConnected({ client }));
216
+ client.on('message', raw => enqueue(Event.McpRequestReceived({ client, raw: raw.toString() })));
217
+ client.on('close', () => enqueue(Event.McpClientDisconnected({ client })));
63
218
  client.on('error', error => {
64
219
  console.error('[foldkit:devTools] MCP client error', error);
65
220
  });
66
221
  });
67
- console.log(`[foldkit:devTools] MCP relay listening on ws://localhost:${port}`);
68
- };
69
- const stopMcpWebSocketServer = () => {
70
- const clients = Effect.runSync(Ref.get(mcpClientsRef));
71
- HashSet.forEach(clients, client => {
72
- client.close();
222
+ wss.on('listening', () => {
223
+ console.log(`[foldkit:devTools] MCP relay listening on ws://localhost:${port}`);
73
224
  });
74
- Effect.runSync(Ref.set(mcpClientsRef, HashSet.empty()));
75
- mcpWebSocketServer?.close();
76
- mcpWebSocketServer = null;
225
+ return wss;
226
+ }), wss => Effect.sync(() => {
227
+ wss.close();
77
228
  console.log('[foldkit:devTools] MCP relay stopped');
78
- };
79
- const handleBrowserEventFrame = (data, client) => {
80
- const decoded = S.decodeUnknownEither(EventFrame)(data);
81
- Either.match(decoded, {
82
- onLeft: error => {
83
- console.warn('[foldkit:devTools] failed to decode browser event frame', error);
84
- },
85
- onRight: frame => Match.value(frame.event).pipe(Match.tagsExhaustive({
86
- EventConnected: event => handleConnectedEvent(event, client),
87
- EventDisconnected: handleDisconnectedEvent,
88
- })),
89
- });
90
- };
91
- const ensureClientTracked = (client) => {
92
- const tracked = Effect.runSync(Ref.get(trackedClientsRef));
93
- if (HashSet.has(tracked, client)) {
94
- return;
229
+ }));
230
+ // PROGRAM
231
+ const main = (server, events, options) => Effect.gen(function* () {
232
+ const state = yield* makeState;
233
+ const enqueue = (event) => {
234
+ Queue.offerUnsafe(events, event);
235
+ };
236
+ yield* registerViteWsHandlers(server, state, enqueue);
237
+ if (options.devToolsMcpPort !== undefined) {
238
+ yield* startMcpRelay(options.devToolsMcpPort, enqueue);
95
239
  }
96
- Effect.runSync(Ref.update(trackedClientsRef, HashSet.add(client)));
97
- client.socket.on('close', () => handleClientClose(client));
98
- };
99
- const handleClientClose = (client) => {
100
- pipe(Effect.runSync(Ref.get(clientConnectionsRef)), HashMap.get(client), Option.match({
101
- onNone: () => { },
102
- onSome: connectionIds => HashSet.forEach(connectionIds, connectionId => {
103
- Effect.runSync(Ref.update(connectedRuntimesRef, HashMap.remove(connectionId)));
104
- console.log(`[foldkit:devTools] runtime pruned (socket close): ${connectionId}`);
240
+ yield* Stream.fromQueue(events).pipe(Stream.runForEach(event => dispatchEvent(server, state, event)));
241
+ });
242
+ // PLUGIN ENTRY
243
+ export const foldkit = (options = {}) => {
244
+ const events = Effect.runSync(Queue.unbounded());
245
+ return {
246
+ name: 'foldkit-hmr',
247
+ apply: 'serve',
248
+ config: () => ({
249
+ optimizeDeps: {
250
+ include: [...FORCE_INCLUDED_EFFECT_NAMESPACES],
251
+ },
105
252
  }),
106
- }));
107
- Effect.runSync(Ref.update(clientConnectionsRef, HashMap.remove(client)));
108
- Effect.runSync(Ref.update(trackedClientsRef, HashSet.remove(client)));
109
- };
110
- const handleBrowserResponseFrame = (data) => {
111
- const decoded = S.decodeUnknownEither(ResponseFrame)(data);
112
- Either.match(decoded, {
113
- onLeft: error => {
114
- console.warn('[foldkit:devTools] failed to decode browser response frame', error);
253
+ configureServer: server => {
254
+ const fiber = Effect.runFork(Effect.scoped(main(server, events, options)));
255
+ server.httpServer?.on('close', () => {
256
+ Effect.runFork(Fiber.interrupt(fiber));
257
+ });
115
258
  },
116
- onRight: forwardResponseToMcpClients,
117
- });
118
- };
119
- const handleConnectedEvent = (event, client) => {
120
- Effect.runSync(Ref.update(connectedRuntimesRef, HashMap.set(event.runtime.connectionId, event.runtime)));
121
- Effect.runSync(Ref.update(clientConnectionsRef, currentMap => {
122
- const existing = pipe(HashMap.get(currentMap, client), Option.getOrElse(() => HashSet.empty()));
123
- return HashMap.set(currentMap, client, HashSet.add(existing, event.runtime.connectionId));
124
- }));
125
- console.log(`[foldkit:devTools] runtime connected: ${event.runtime.connectionId} (${event.runtime.title})`);
126
- };
127
- const handleDisconnectedEvent = (event) => {
128
- Effect.runSync(Ref.update(connectedRuntimesRef, HashMap.remove(event.connectionId)));
129
- console.log(`[foldkit:devTools] runtime disconnected: ${event.connectionId}`);
130
- };
131
- const broadcastToMcpClients = (payload) => {
132
- const clients = Effect.runSync(Ref.get(mcpClientsRef));
133
- HashSet.forEach(clients, client => {
134
- if (client.readyState === client.OPEN) {
135
- client.send(payload);
136
- }
137
- });
138
- };
139
- const forwardResponseToMcpClients = (responseFrame) => {
140
- broadcastToMcpClients(JSON.stringify(responseFrame));
141
- };
142
- const handleMcpMessage = (client, raw) => {
143
- const decoded = S.decodeUnknownEither(S.parseJson(RequestFrame))(raw);
144
- Either.match(decoded, {
145
- onLeft: error => {
146
- console.warn('[foldkit:devTools] failed to decode MCP request frame', error);
259
+ handleHotUpdate: ({ server, modules, }) => {
260
+ if (modules.length === 0) {
261
+ return;
262
+ }
263
+ server.ws.send({ type: 'full-reload' });
264
+ Queue.offerUnsafe(events, Event.HotUpdateFired());
265
+ return [];
147
266
  },
148
- onRight: frame => Match.value(frame.request).pipe(Match.tag('RequestListRuntimes', () => replyListRuntimes(client, frame.id)), Match.orElse(() => forwardRequestToBrowsers(frame))),
149
- });
150
- };
151
- const replyListRuntimes = (client, requestId) => {
152
- const runtimes = pipe(Effect.runSync(Ref.get(connectedRuntimesRef)), HashMap.values, Array.fromIterable);
153
- const responseFrame = {
154
- id: requestId,
155
- response: ResponseRuntimes({ runtimes }),
156
267
  };
157
- if (client.readyState === client.OPEN) {
158
- client.send(JSON.stringify(responseFrame));
159
- }
160
- };
161
- const forwardRequestToBrowsers = (frame) => {
162
- if (viteServer === null) {
163
- return;
164
- }
165
- viteServer.ws.send('foldkit:devTools:request', frame);
166
- };
167
- const handleHotUpdate = ({ server, modules, }) => {
168
- if (modules.length === 0) {
169
- return;
170
- }
171
- isHmrReload = true;
172
- server.ws.send({ type: 'full-reload' });
173
- return [];
174
268
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@foldkit/vite-plugin",
3
- "version": "0.3.1",
3
+ "version": "0.4.0",
4
4
  "description": "Vite plugin for Foldkit hot module reloading with state preservation",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -16,7 +16,7 @@
16
16
  "dist"
17
17
  ],
18
18
  "peerDependencies": {
19
- "effect": "^3.18.2",
19
+ "effect": "4.0.0-beta.59",
20
20
  "foldkit": "^0",
21
21
  "vite": "^7.0.0"
22
22
  },
@@ -25,10 +25,10 @@
25
25
  },
26
26
  "devDependencies": {
27
27
  "@types/ws": "^8.5.13",
28
- "effect": "^3.19.19",
28
+ "effect": "4.0.0-beta.59",
29
29
  "typescript": "^6.0.2",
30
30
  "vite": "^7.3.1",
31
- "foldkit": "0.76.1"
31
+ "foldkit": "0.82.0"
32
32
  },
33
33
  "keywords": [
34
34
  "vite",