1616 * 为此,插件提供了一种基于 memory 的数据共享机制。
1717 */
1818
19- import { deepClone , deepEqual , isFunction } from '@pengzhanbo/utils'
19+ import { createHash } from 'node:crypto'
20+ import { deepClone , isFunction } from '@pengzhanbo/utils'
2021
2122/**
2223 * Mock data cache
@@ -55,11 +56,11 @@ class CacheImpl<T = any> {
5556 value : T
5657
5758 /**
58- * Initial value backup , used to detect if initial data has changed
59+ * Initial value hash , used to detect if initial data has changed
5960 *
60- * 初始化数据的备份 ,用于判断传入的初始化数据是否发生变更
61+ * 初始化数据的哈希值 ,用于判断传入的初始化数据是否发生变更
6162 */
62- #initialValue: T
63+ #hash: string
6364
6465 /**
6566 * Last update timestamp
@@ -68,17 +69,26 @@ class CacheImpl<T = any> {
6869 */
6970 #lastUpdate: number
7071
72+ /**
73+ * Whether to persist data on HMR
74+ *
75+ * 热更新时是否保持数据
76+ */
77+ #persistOnHMR: boolean
78+
7179 /**
7280 * Constructor
7381 *
7482 * 构造函数
7583 *
7684 * @param value - Initial value / 初始值
85+ * @param persistOnHMR - Whether to persist data on HMR / 热更新时是否保持数据
7786 */
78- constructor ( value : T ) {
87+ constructor ( value : T , persistOnHMR ?: boolean ) {
7988 this . value = value
80- this . #initialValue = deepClone ( value )
89+ this . #hash = getHash ( value )
8190 this . #lastUpdate = Date . now ( )
91+ this . #persistOnHMR = persistOnHMR ?? false
8292 }
8393
8494 /**
@@ -89,6 +99,12 @@ class CacheImpl<T = any> {
8999 * @param value - New value / 新值
90100 */
91101 hotUpdate ( value : T ) {
102+ // If persistOnHMR is enabled, skip the update to preserve the current cached value.
103+ // 如果启用了 persistOnHMR ,跳过更新以保留当前缓存值
104+ if ( this . #persistOnHMR) {
105+ return
106+ }
107+
92108 // Used for cases where repeated compilation generates random data via `mockjs` or `faker-js`,
93109 // which may cause inconsistency in interface data across different mock files.
94110 // Since compilation and loading time is necessarily much shorter than user modification intervals,
@@ -103,12 +119,43 @@ class CacheImpl<T = any> {
103119 // reinitialize to the newly compiled data.
104120 // 文件变更重新编译加载后,当两个初始化的数据不相等时,
105121 // 重新初始化为新的编译后的数据
106- if ( ! deepEqual ( value , this . #initialValue) ) {
107- this . value = value
108- this . #initialValue = deepClone ( value )
122+ const hash = getHash ( value )
123+ if ( this . #hash !== hash ) {
124+ this . value = deepClone ( value )
125+ this . #hash = hash
109126 this . #lastUpdate = Date . now ( )
110127 }
111128 }
129+
130+ /**
131+ * Set persistOnHMR
132+ *
133+ * 设置 persistOnHMR
134+ *
135+ * @param persistOnHMR - Whether to persist data on HMR / 热更新时是否保持数据
136+ */
137+ setPersistOnHMR ( persistOnHMR : boolean ) {
138+ // Once set to false, cannot be changed to true by subsequent calls
139+ // 设置为 false 后,不能被后续调用改为 true
140+ if ( ! this . #persistOnHMR)
141+ this . #persistOnHMR = persistOnHMR
142+ }
143+ }
144+
145+ /**
146+ * Options for defineMockData
147+ *
148+ * defineMockData 的选项
149+ */
150+ export interface DefineMockDataOptions {
151+ /**
152+ * Whether to persist the data value on HMR (Hot Module Replacement).
153+ *
154+ * 热更新时是否保持数据值
155+ *
156+ * @default false
157+ */
158+ persistOnHMR ?: boolean
112159}
113160
114161/**
@@ -152,15 +199,20 @@ export type MockData<T = any> = readonly [
152199 * @template T - Type of mock data / Mock 数据的类型
153200 * @param key - Unique key for mock data / Mock 数据的唯一键
154201 * @param initialData - Initial data value / 初始数据值
202+ * @param options - Options / 选项
155203 * @returns MockData object with getter, setter, and value property / 带有 getter、setter 和 value 属性的 MockData 对象
156204 */
157205export function defineMockData < T = any > (
158206 key : string ,
159207 initialData : T ,
208+ options ?: DefineMockDataOptions ,
160209) : MockData < T > {
161210 let cache = mockDataCache . get ( key ) as CacheImpl < T > | undefined
162211 if ( ! cache ) {
163- const newCache = new CacheImpl ( initialData )
212+ const newCache = new CacheImpl < T > (
213+ initialData ,
214+ options ?. persistOnHMR ,
215+ )
164216 const existing = mockDataCache . get ( key )
165217 if ( existing ) {
166218 cache = existing as CacheImpl < T >
@@ -170,6 +222,11 @@ export function defineMockData<T = any>(
170222 cache = newCache
171223 }
172224 }
225+ else {
226+ // If cache already exists, update persistOnHMR if not already set
227+ // 如果缓存已存在,且 persistOnHMR 尚未设置,则更新
228+ cache . setPersistOnHMR ( options ?. persistOnHMR ?? false )
229+ }
173230
174231 cache . hotUpdate ( initialData )
175232
@@ -200,3 +257,7 @@ export function defineMockData<T = any>(
200257
201258 return res
202259}
260+
261+ function getHash ( data : any ) : string {
262+ return createHash ( 'sha256' ) . update ( JSON . stringify ( data ) ) . digest ( 'hex' )
263+ }
0 commit comments