ember-vite-hmr 2.1.3 → 2.1.4
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/README.md
CHANGED
|
@@ -13,6 +13,26 @@ this tries to keep the state of properties in components and controller
|
|
|
13
13
|
|
|
14
14
|
it cannot hot reload local properties that turn out to be helpers/modifiers/components.
|
|
15
15
|
|
|
16
|
+
### HMR Lifecycle Hook
|
|
17
|
+
|
|
18
|
+
Components and services can implement a `_hmrAccepted` method to perform custom logic during hot module replacement:
|
|
19
|
+
|
|
20
|
+
```js
|
|
21
|
+
export default class MyComponent extends Component {
|
|
22
|
+
_hmrAccepted(oldInstance) {
|
|
23
|
+
// Custom state migration logic
|
|
24
|
+
// oldInstance contains the previous component instance
|
|
25
|
+
console.log('HMR accepted, migrating from:', oldInstance);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
This hook is called after automatic state synchronization but before the old instance is destroyed, allowing you to:
|
|
31
|
+
- Perform custom state migrations
|
|
32
|
+
- Clean up resources
|
|
33
|
+
- Log HMR events
|
|
34
|
+
- Handle complex state transitions
|
|
35
|
+
|
|
16
36
|
## Installation
|
|
17
37
|
|
|
18
38
|
```
|
|
@@ -44,6 +44,7 @@ function getState(component, skip) {
|
|
|
44
44
|
function syncState(instance) {
|
|
45
45
|
const args = instance.args;
|
|
46
46
|
if (args.__hot__) {
|
|
47
|
+
const oldInstance = args.__hot__.oldInstance;
|
|
47
48
|
const state = instance.__get_hot_state__?.() || args.__hot__.getState?.();
|
|
48
49
|
for (const k in state) {
|
|
49
50
|
if (instance[k] instanceof Service) {
|
|
@@ -51,7 +52,13 @@ function syncState(instance) {
|
|
|
51
52
|
}
|
|
52
53
|
instance[k] = state[k];
|
|
53
54
|
}
|
|
55
|
+
|
|
56
|
+
// Call _hmrAccepted hook if defined
|
|
57
|
+
if (typeof instance._hmrAccepted === 'function') {
|
|
58
|
+
instance._hmrAccepted(oldInstance);
|
|
59
|
+
}
|
|
54
60
|
args.__hot__.getState = () => getState(instance, ['args']);
|
|
61
|
+
args.__hot__.oldInstance = instance;
|
|
55
62
|
}
|
|
56
63
|
}
|
|
57
64
|
function initialize() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"setup-hmr-manager.js","sources":["../../src/instance-initializers/setup-hmr-manager.ts"],"sourcesContent":["import Route from '@ember/routing/route';\nimport Service from '@ember/service';\nimport Component from '@glimmer/component';\nimport { getInternalComponentManager } from '@glimmer/manager';\n\ninterface HotComponent extends Component<{ __hot__?: unknown }> {\n __get_hot_state__?: () => Record<string, unknown>;\n [key: string]: unknown;\n}\n\ntype Mutable<T> = {\n -readonly [P in keyof T]: unknown;\n};\n\nfunction findPropertyDescriptor(\n component: HotComponent | Record<string, unknown>,\n key: string,\n) {\n let proto = component;\n while (proto) {\n const desc = Object.getOwnPropertyDescriptor(proto, key);\n if (desc) return desc;\n proto = Object.getPrototypeOf(proto);\n }\n}\n\nfunction getState(component: HotComponent, skip: string[]) {\n const state: Record<string, unknown> = {};\n if (!component) {\n return state;\n }\n for (const key in component) {\n if (skip.includes(key)) continue;\n const entry = findPropertyDescriptor(component, key);\n const value = component[key as keyof Component];\n \n // Skip Service instances - they should not be synced\n if (value instanceof Service) {\n continue;\n }\n \n // Skip Function properties - they should not be synced\n if (typeof value === 'function') {\n continue;\n }\n \n if (entry) {\n if (\n entry.writable &&\n !Object.prototype.toString.call(entry.value).includes('Function')\n ) {\n state[key] = component[key as keyof Component];\n }\n if (entry.set) {\n state[key] = component[key as keyof Component];\n }\n }\n }\n return state;\n}\n\nfunction syncState(instance: Mutable<HotComponent>) {\n const args = instance.args as { __hot__?: { getState?: () => Record<string, unknown
|
|
1
|
+
{"version":3,"file":"setup-hmr-manager.js","sources":["../../src/instance-initializers/setup-hmr-manager.ts"],"sourcesContent":["import Route from '@ember/routing/route';\nimport Service from '@ember/service';\nimport Component from '@glimmer/component';\nimport { getInternalComponentManager } from '@glimmer/manager';\n\ninterface HotComponent extends Component<{ __hot__?: unknown }> {\n __get_hot_state__?: () => Record<string, unknown>;\n _hmrAccepted?: (oldInstance?: HotComponent) => void;\n [key: string]: unknown;\n}\n\ntype Mutable<T> = {\n -readonly [P in keyof T]: unknown;\n};\n\nfunction findPropertyDescriptor(\n component: HotComponent | Record<string, unknown>,\n key: string,\n) {\n let proto = component;\n while (proto) {\n const desc = Object.getOwnPropertyDescriptor(proto, key);\n if (desc) return desc;\n proto = Object.getPrototypeOf(proto);\n }\n}\n\nfunction getState(component: HotComponent, skip: string[]) {\n const state: Record<string, unknown> = {};\n if (!component) {\n return state;\n }\n for (const key in component) {\n if (skip.includes(key)) continue;\n const entry = findPropertyDescriptor(component, key);\n const value = component[key as keyof Component];\n \n // Skip Service instances - they should not be synced\n if (value instanceof Service) {\n continue;\n }\n \n // Skip Function properties - they should not be synced\n if (typeof value === 'function') {\n continue;\n }\n \n if (entry) {\n if (\n entry.writable &&\n !Object.prototype.toString.call(entry.value).includes('Function')\n ) {\n state[key] = component[key as keyof Component];\n }\n if (entry.set) {\n state[key] = component[key as keyof Component];\n }\n }\n }\n return state;\n}\n\nfunction syncState(instance: Mutable<HotComponent>) {\n const args = instance.args as { __hot__?: { getState?: () => Record<string, unknown>; oldInstance?: HotComponent } };\n if (args.__hot__) {\n const oldInstance = args.__hot__.oldInstance;\n const state =\n (instance.__get_hot_state__ as (() => Record<string, unknown>) | undefined)?.() || args.__hot__.getState?.();\n for (const k in state) {\n if (instance[k as keyof HotComponent] instanceof Service) {\n continue;\n }\n instance[k as keyof HotComponent] = state[k];\n }\n \n // Call _hmrAccepted hook if defined\n if (typeof instance._hmrAccepted === 'function') {\n instance._hmrAccepted(oldInstance);\n }\n \n args.__hot__.getState = () => getState(instance as HotComponent, ['args']);\n args.__hot__.oldInstance = instance as HotComponent;\n }\n}\n\nexport function initialize() {\n const ComponentManager = getInternalComponentManager(Component);\n const proto = Object.getPrototypeOf(ComponentManager);\n const create = proto.create;\n proto.create = function (...args: unknown[]) {\n const instance = create.call(this, ...args);\n setTimeout(() => syncState(instance.component));\n return instance;\n };\n\n const setupController = Route.prototype.setupController;\n\n const StateCache: Record<string, unknown> = {};\n\n Route.prototype.setupController = function (...args: Parameters<typeof setupController>) {\n const controller = args[0] as unknown as Record<string, unknown>;\n const r = setupController.call(this, ...args);\n const fullRouteName = this.fullRouteName;\n const state = StateCache[fullRouteName] as { router?: Record<string, unknown>; controller?: Record<string, unknown> } || {};\n const skip = ['_qpDelegate', 'target', 'queryParams'];\n const routerState = getState(state.router as HotComponent, skip);\n const controllerState = getState(state.controller as HotComponent, skip);\n for (const k in routerState) {\n (this as unknown as Record<string, unknown>)[k] = routerState[k];\n }\n for (const k in controllerState) {\n (controller as Record<string, unknown>)[k] = controllerState[k];\n }\n StateCache[fullRouteName] = {\n route: this,\n controller,\n };\n return r;\n };\n}\n\nexport default {\n initialize,\n};\n"],"names":["findPropertyDescriptor","component","key","proto","desc","Object","getOwnPropertyDescriptor","getPrototypeOf","getState","skip","state","includes","entry","value","Service","writable","prototype","toString","call","set","syncState","instance","args","__hot__","oldInstance","__get_hot_state__","k","_hmrAccepted","initialize","ComponentManager","getInternalComponentManager","Component","create","setTimeout","setupController","Route","StateCache","controller","r","fullRouteName","routerState","router","controllerState","route"],"mappings":"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"}
|
package/dist/lib/babel-plugin.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ember-vite-hmr",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.4",
|
|
4
4
|
"keywords": [
|
|
5
5
|
"ember-addon"
|
|
6
6
|
],
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"prepack": "pnpm build || echo 'its okay'"
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"@babel/core": "^7.
|
|
42
|
+
"@babel/core": "^7.29.0",
|
|
43
43
|
"@babel/plugin-transform-typescript": "^7.28.6",
|
|
44
44
|
"@babel/traverse": "^7.29.0",
|
|
45
45
|
"@babel/types": "^7.28.5",
|
|
@@ -110,7 +110,7 @@
|
|
|
110
110
|
"thread-loader": "^4.0.2",
|
|
111
111
|
"typescript": "^5.9.3",
|
|
112
112
|
"vite": "^7.2.6",
|
|
113
|
-
"vitest": "^4.1.
|
|
113
|
+
"vitest": "^4.1.4"
|
|
114
114
|
},
|
|
115
115
|
"peerDependencies": {
|
|
116
116
|
"@embroider/compat": "*",
|