@@ -0,0 +1,85 @@
|
||||
import * as Refreshable from "effect-fc-next/Refreshable"
|
||||
|
||||
export interface HotContext {
|
||||
readonly data: Record<string, unknown>
|
||||
accept(): void
|
||||
invalidate(message?: string): void
|
||||
}
|
||||
|
||||
interface RefreshData {
|
||||
readonly cells: Map<string, Refreshable.Cell<any>>
|
||||
ids?: readonly string[]
|
||||
}
|
||||
|
||||
const hotDataKey = "__effectFcRefresh"
|
||||
|
||||
const getRefreshData = (hot: HotContext): RefreshData => {
|
||||
const data = hot.data as Record<string, unknown>
|
||||
const current = data[hotDataKey] as RefreshData | undefined
|
||||
if (current)
|
||||
return current
|
||||
|
||||
const refreshData: RefreshData = {
|
||||
cells: new Map(),
|
||||
}
|
||||
data[hotDataKey] = refreshData
|
||||
return refreshData
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers an Effect View descriptor in a Vite HMR data cell.
|
||||
*
|
||||
* This API is injected by `@effect-view/vite`; applications should not need to
|
||||
* call it directly.
|
||||
*/
|
||||
export const register = <A extends object>(
|
||||
component: A,
|
||||
hot: HotContext | undefined,
|
||||
id: string,
|
||||
signature: string,
|
||||
forceReset = false,
|
||||
): A => {
|
||||
if (!hot)
|
||||
return component
|
||||
|
||||
const refreshData = getRefreshData(hot)
|
||||
const previous = refreshData.cells.get(id)
|
||||
if (!previous) {
|
||||
const cell = Refreshable.makeCell(component, signature, forceReset)
|
||||
refreshData.cells.set(id, cell)
|
||||
return Refreshable.attach(component, cell)
|
||||
}
|
||||
|
||||
previous.update(component, signature, forceReset)
|
||||
return Refreshable.attach(component, previous)
|
||||
}
|
||||
|
||||
const sameIds = (
|
||||
self: readonly string[],
|
||||
that: readonly string[],
|
||||
): boolean => self.length === that.length
|
||||
&& self.every((id, index) => id === that[index])
|
||||
|
||||
/**
|
||||
* Accepts an instrumented module when its Effect View definition set is
|
||||
* unchanged. Renames and removals invalidate upward so a stale cell cannot
|
||||
* remain mounted indefinitely.
|
||||
*/
|
||||
export const accept = (
|
||||
hot: HotContext | undefined,
|
||||
ids: readonly string[],
|
||||
): void => {
|
||||
if (!hot)
|
||||
return
|
||||
|
||||
const refreshData = getRefreshData(hot)
|
||||
const previousIds = refreshData.ids
|
||||
refreshData.ids = ids
|
||||
|
||||
if (previousIds && !sameIds(previousIds, ids)) {
|
||||
hot.invalidate("[effect-view] Effect View exports changed")
|
||||
return
|
||||
}
|
||||
|
||||
hot.accept()
|
||||
}
|
||||
Reference in New Issue
Block a user