unplugin-essor 0.0.17-beta.6 → 0.0.17
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/dist/astro.cjs +3 -3
- package/dist/astro.js +1 -1
- package/dist/{chunk-KXK55FFZ.cjs → chunk-ASRB37BB.cjs} +82 -49
- package/dist/chunk-ASRB37BB.cjs.map +1 -0
- package/dist/{chunk-KWEBR2TV.js → chunk-REX4A3LQ.js} +82 -49
- package/dist/chunk-REX4A3LQ.js.map +1 -0
- package/dist/esbuild.cjs +2 -2
- package/dist/esbuild.js +1 -1
- package/dist/farm.cjs +2 -2
- package/dist/farm.js +1 -1
- package/dist/index.cjs +4 -4
- package/dist/index.js +1 -1
- package/dist/rolldown.cjs +2 -2
- package/dist/rolldown.js +1 -1
- package/dist/rollup.cjs +2 -2
- package/dist/rollup.js +1 -1
- package/dist/rspack.cjs +2 -2
- package/dist/rspack.js +1 -1
- package/dist/types.d.cts +59 -2
- package/dist/types.d.ts +59 -2
- package/dist/vite.cjs +2 -2
- package/dist/vite.js +1 -1
- package/dist/webpack.cjs +2 -2
- package/dist/webpack.js +1 -1
- package/package.json +14 -10
- package/dist/chunk-KWEBR2TV.js.map +0 -1
- package/dist/chunk-KXK55FFZ.cjs.map +0 -1
package/dist/astro.cjs
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkASRB37BB_cjs = require('./chunk-ASRB37BB.cjs');
|
|
4
4
|
|
|
5
5
|
// src/astro.ts
|
|
6
6
|
var astro_default = (options) => ({
|
|
7
7
|
name: "unplugin-starter",
|
|
8
8
|
hooks: {
|
|
9
9
|
// eslint-disable-next-line require-await
|
|
10
|
-
"astro:config:setup": (astro) =>
|
|
10
|
+
"astro:config:setup": (astro) => chunkASRB37BB_cjs.__async(null, null, function* () {
|
|
11
11
|
var _a;
|
|
12
12
|
(_a = astro.config.vite).plugins || (_a.plugins = []);
|
|
13
|
-
astro.config.vite.plugins.push(
|
|
13
|
+
astro.config.vite.plugins.push(chunkASRB37BB_cjs.index_default.vite(options));
|
|
14
14
|
})
|
|
15
15
|
}
|
|
16
16
|
});
|
package/dist/astro.js
CHANGED
|
@@ -47,6 +47,18 @@ var __spreadValues = (a, b) => {
|
|
|
47
47
|
return a;
|
|
48
48
|
};
|
|
49
49
|
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
50
|
+
var __objRest = (source, exclude) => {
|
|
51
|
+
var target = {};
|
|
52
|
+
for (var prop in source)
|
|
53
|
+
if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
|
|
54
|
+
target[prop] = source[prop];
|
|
55
|
+
if (source != null && __getOwnPropSymbols)
|
|
56
|
+
for (var prop of __getOwnPropSymbols(source)) {
|
|
57
|
+
if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
|
|
58
|
+
target[prop] = source[prop];
|
|
59
|
+
}
|
|
60
|
+
return target;
|
|
61
|
+
};
|
|
50
62
|
var __async = (__this, __arguments, generator) => {
|
|
51
63
|
return new Promise((resolve, reject) => {
|
|
52
64
|
var fulfilled = (value) => {
|
|
@@ -69,7 +81,7 @@ var __async = (__this, __arguments, generator) => {
|
|
|
69
81
|
};
|
|
70
82
|
|
|
71
83
|
// raw-loader:/home/runner/work/essor/essor/packages/unplugin/src/hmr-runtime.js?raw
|
|
72
|
-
var hmr_runtime_default = "/**\n * Essor HMR Runtime - Registry-based Hot Module Replacement\n *\n * This runtime enables precise component-level HMR updates without full page reloads:\n *\n * 1. **Registry Tracking**: Each component id points to its latest implementation\n * 2. **Signature Tracking**: Components are tracked by code signatures (from babel plugin)\n * 3. **Precise Updates**: Only components with changed signatures are updated\n * 4. **Instance Reloading**: Live component instances remount when their implementation changes\n * 5. **Bundler Agnostic**: Works with Vite, Webpack, Rspack, and other bundlers\n */\nimport { createComponent, onDestroy } from 'essor';\n\nconst isFunction = (value) => typeof value === 'function';\nconst ESSOR_HMR = 'essor-hmr';\n/**\n * Global component registry for HMR tracking\n *\n * Maps hmrId -> ComponentInfo where:\n * - hmrId: Unique identifier for component (fileHash:componentName)\n * - component: Current component function\n * - signature: Hash of component code (changes when code changes)\n * - instances: Set of active component instances\n * - updated: True after HMR applies a newer implementation\n */\nconst componentRegistry = new Map();\n\nfunction cleanupInstance(hmrId, info, component) {\n info.instances.delete(component);\n\n if (info.instances.size === 0 && !info.updated && componentRegistry.get(hmrId) === info) {\n componentRegistry.delete(hmrId);\n }\n}\n\n/**\n * Utility function to handle invalidate or reload\n * @param hot - Hot module API object\n */\nfunction invalidateOrReload(hot) {\n if (isFunction(hot?.invalidate)) {\n hot.invalidate();\n } else if (typeof location !== 'undefined') {\n location.reload();\n }\n}\n\n/**\n * Create HMR-enabled component wrapper\n *\n * This function wraps a component to enable HMR:\n * 1. Creates or retrieves component registry entry\n * 2. Creates the component from the latest registered implementation\n * 3. Tracks the instance until destroy()\n * 4. applyUpdate() remounts tracked instances when the implementation changes\n *\n * @param componentFn - Component function with __hmrId and __signature\n * @param props - Component props\n * @returns Component instance that responds to HMR updates\n */\nexport function createHMRComponent(componentFn, props) {\n const { __hmrId: hmrId, __signature: signature } = componentFn;\n\n if (!hmrId) {\n // If no hmrId, create normal component\n return createComponent(componentFn, props);\n }\n\n let info = componentRegistry.get(hmrId);\n\n if (!info) {\n info = {\n component: componentFn,\n signature,\n instances: new Set(),\n updated: false,\n };\n componentRegistry.set(hmrId, info);\n } else if (info.instances.size === 0 && !info.updated) {\n info.signature = signature;\n info.component = componentFn;\n }\n\n let component;\n let disposed = false;\n let isForceUpdating = false;\n const cleanupHMR = () => {\n if (isForceUpdating) return;\n if (disposed) return;\n disposed = true;\n cleanupInstance(hmrId, info, component);\n };\n\n // Use a stable boundary function so destroy cleanup is registered only\n // after the component is mounted inside a real Essor scope. This also lets\n // stale closures render the latest implementation after a hot update.\n function HMRBoundary(nextProps) {\n onDestroy(cleanupHMR);\n return info.component.call(this, nextProps);\n }\n\n component = createComponent(HMRBoundary, props);\n info.instances.add(component);\n\n const originalForceUpdate = component.forceUpdate;\n if (isFunction(originalForceUpdate)) {\n component.forceUpdate = function (...args) {\n isForceUpdating = true;\n try {\n return originalForceUpdate.apply(this, args);\n } finally {\n isForceUpdating = false;\n }\n };\n }\n\n // Integrate with component lifecycle - cleanup only when the component is\n // actually unmounted, not during forceUpdate's destroy/remount cycle.\n const originalDestroy = component.destroy;\n component.destroy = function (...args) {\n try {\n if (isFunction(originalDestroy)) {\n return originalDestroy.apply(this, args);\n }\n } finally {\n if (!isForceUpdating) {\n cleanupHMR();\n }\n }\n };\n\n return component;\n}\n\n/**\n * Determine if a component needs to be updated\n *\n * A component should update if:\n * 1. Function instance changed (indicates module was re-executed)\n * 2. Signature changed (indicates component code was modified)\n *\n * @param oldInfo - Existing component registry info\n * @param newComponentFn - New component function from updated module\n * @param newSignature - New signature hash from updated module\n * @returns true if component should update\n */\nfunction shouldUpdate(oldInfo, newComponentFn, newSignature) {\n if (!oldInfo) return true;\n\n // Check function instance (handles constant updates via module re-execution)\n if (oldInfo.component !== newComponentFn) {\n return true;\n }\n\n // Check compile-time signature (handles component code changes)\n return oldInfo.signature !== newSignature;\n}\n\n/**\n * Check if a value is an HMR-enabled component\n *\n * @param value - Value to check\n * @returns true if value is a function with __hmrId property\n */\nfunction isHMRComponent(value) {\n return value && isFunction(value) && value.__hmrId;\n}\n\n/**\n * Apply HMR updates to components\n *\n * Iterates through the new component registry and force-updates live\n * component instances whose implementation changed.\n *\n * @param registry - Array of components from updated module\n * @returns true if reload needed (errors occurred), false otherwise\n */\nexport function applyUpdate(registry) {\n if (!Array.isArray(registry) || registry.length === 0) {\n return false;\n }\n\n let needsReload = false;\n\n for (const entry of registry) {\n if (!isHMRComponent(entry)) {\n continue;\n }\n\n const { __hmrId: hmrId, __signature: signature } = entry;\n const id = hmrId;\n const info = componentRegistry.get(hmrId);\n\n if (!info) {\n componentRegistry.set(hmrId, {\n component: entry,\n signature,\n instances: new Set(),\n updated: true,\n });\n continue;\n }\n\n // Use shouldUpdate to determine if update is needed\n if (!shouldUpdate(info, entry, signature)) {\n continue;\n }\n\n info.signature = signature;\n info.component = entry;\n info.updated = true;\n\n for (const component of [...info.instances]) {\n try {\n component.forceUpdate();\n } catch (error) {\n console.error(`[Essor HMR] Failed to update ${id}:`, error);\n cleanupInstance(hmrId, info, component);\n needsReload = true;\n }\n }\n }\n\n return needsReload;\n}\n\n/**\n * Common handler for HMR updates across bundlers\n * @param hot - Hot module API\n * @param newModule - Updated module\n * @returns true if handled successfully\n */\nfunction handleHMRUpdate(hot, newModule) {\n if (!newModule) {\n invalidateOrReload(hot);\n return false;\n }\n\n // Extract HMR components from new module\n const newRegistry = extractHMRComponents(newModule);\n if (newRegistry.length === 0) {\n return true;\n }\n\n const needsReload = applyUpdate(newRegistry);\n if (needsReload) {\n invalidateOrReload(hot);\n }\n return true;\n}\n\n/**\n * Setup HMR for Vite bundler\n *\n * Vite provides import.meta.hot.accept() callback that receives the new module\n */\nfunction setupViteHMR(hot, registry) {\n hot.data ??= {};\n const isUpdate = !!hot.data[ESSOR_HMR];\n hot.data[ESSOR_HMR] = registry;\n\n if (isUpdate) {\n const needsReload = applyUpdate(registry);\n if (needsReload) {\n invalidateOrReload(hot);\n }\n }\n}\n\n/**\n * Setup HMR for Webpack/Rspack bundlers\n *\n * Webpack-style HMR uses module.hot.accept() and hot.data for state persistence\n */\nfunction setupWebpackHMR(hot, registry) {\n if (isFunction(hot.accept)) {\n hot.accept();\n }\n\n // Apply update if previous data exists from last hot reload\n if (hot.data?.[ESSOR_HMR]) {\n const needsReload = applyUpdate(registry);\n if (needsReload) {\n invalidateOrReload(hot);\n }\n }\n\n // Save current registry for next update\n if (isFunction(hot.dispose)) {\n hot.dispose((data) => {\n data[ESSOR_HMR] = registry;\n });\n }\n}\n\n/**\n * Setup HMR for other bundlers (fallback)\n *\n * Attempts to work with any bundler that provides a basic hot module API\n */\nfunction setupStandardHMR(hot, registry) {\n // Try accept callback mode first (more efficient)\n if (isFunction(hot.accept)) {\n try {\n hot.accept((newModule) => handleHMRUpdate(hot, newModule));\n } catch {\n // Some bundlers don't support accept with callback\n // Fall back to simple accept (for Webpack-style pattern)\n try {\n hot.accept();\n } catch (error_) {\n console.warn('[Essor HMR] Failed to setup hot.accept:', error_);\n }\n }\n }\n\n // Setup dispose handler for state persistence\n if (isFunction(hot.dispose)) {\n hot.dispose((data) => {\n data.__$registry$__ = registry;\n data.__essor_timestamp__ = Date.now();\n });\n }\n\n // Apply update if previous data exists (for Webpack-style HMR)\n if (hot.data?.__$registry$__) {\n const needsReload = applyUpdate(registry);\n if (needsReload) {\n invalidateOrReload(hot);\n }\n }\n}\n\n/**\n * Extract HMR components from a module\n *\n * Looks for __$registry$__ array first (generated by babel plugin),\n * then falls back to scanning all exports for HMR components\n *\n * @param module - Module object to scan\n * @returns Array of HMR component functions\n */\nfunction extractHMRComponents(module) {\n if (!module) return [];\n\n // Prefer __$registry$__\n if (Array.isArray(module.__$registry$__)) {\n return module.__$registry$__;\n }\n\n // Otherwise search in exports\n const components = [];\n for (const key of Object.keys(module)) {\n const value = module[key];\n if (isHMRComponent(value)) {\n components.push(value);\n }\n }\n return components;\n}\n\n/**\n * Main HMR entry point\n *\n * Called from transformed modules to set up HMR based on bundler type\n *\n * @param bundlerType - Type of bundler (vite, webpack5, rspack, etc.)\n * @param hot - Hot module API object (import.meta.hot or module.hot)\n * @param registry - Array of components from current module\n * @returns true if HMR setup succeeded, false otherwise\n */\nexport function hmrAccept(bundlerType, hot, registry) {\n if (!hot || !registry) {\n return false;\n }\n\n switch (bundlerType) {\n case 'vite':\n setupViteHMR(hot, registry);\n break;\n case 'webpack':\n case 'webpack5':\n case 'rspack':\n setupWebpackHMR(hot, registry);\n break;\n default:\n // Use standard HMR setup\n setupStandardHMR(hot, registry);\n break;\n }\n\n return true;\n}\n\n/**\n * Cleanup all instances of a component (utility function)\n *\n * @param hmrId - Component HMR ID\n * @returns Number of instances cleaned up\n */\nexport function unregisterAllInstances(hmrId) {\n const info = componentRegistry.get(hmrId);\n if (!info) return 0;\n\n let count = 0;\n for (const item of [...info.instances]) {\n try {\n cleanupInstance(hmrId, info, item);\n } catch (error) {\n console.error(`[Essor HMR] Failed to unregister component instance:`, error);\n }\n count++;\n }\n\n return count;\n}\n\n/**\n * Get registry information for debugging\n *\n * @returns Object mapping hmrId to component info (signature, instance count)\n */\nexport function getRegistryInfo() {\n const info = {};\n for (const [id, data] of componentRegistry) {\n info[id] = {\n signature: data.signature,\n instanceCount: data.instances.size,\n };\n }\n return info;\n}\n";
|
|
84
|
+
var hmr_runtime_default = "/**\n * Essor HMR Runtime - Registry-based Hot Module Replacement\n *\n * This runtime enables precise component-level HMR updates without full page reloads:\n *\n * 1. **Registry Tracking**: Each component id points to its latest implementation\n * 2. **Signature Tracking**: Components are tracked by code signatures (from babel plugin)\n * 3. **Precise Updates**: Only components with changed signatures are updated\n * 4. **Instance Reloading**: Live component instances remount when their implementation changes\n * 5. **Bundler Agnostic**: Works with Vite, Webpack, Rspack, and other bundlers\n */\nimport { createComponent, onDestroy } from 'essor';\n\nconst isFunction = (value) => typeof value === 'function';\nconst ESSOR_HMR = 'essor-hmr';\n/**\n * Global component registry for HMR tracking\n *\n * Maps hmrId -> ComponentInfo where:\n * - hmrId: Unique identifier for component (fileHash:componentName)\n * - component: Current component function\n * - signature: Hash of component code (changes when code changes)\n * - instances: Set of active component instances\n * - updated: True after HMR applies a newer implementation\n */\nconst componentRegistry = new Map();\n\nfunction cleanupInstance(hmrId, info, component) {\n info.instances.delete(component);\n\n if (info.instances.size === 0 && !info.updated && componentRegistry.get(hmrId) === info) {\n componentRegistry.delete(hmrId);\n }\n}\n\n/**\n * Utility function to handle invalidate or reload\n * @param hot - Hot module API object\n */\nfunction invalidateOrReload(hot) {\n if (isFunction(hot?.invalidate)) {\n hot.invalidate();\n } else if (typeof location !== 'undefined') {\n location.reload();\n }\n}\n\n/**\n * Create HMR-enabled component wrapper\n *\n * This function wraps a component to enable HMR:\n * 1. Creates or retrieves component registry entry\n * 2. Creates the component from the latest registered implementation\n * 3. Tracks the instance until destroy()\n * 4. applyUpdate() remounts tracked instances when the implementation changes\n *\n * @param componentFn - Component function with __hmrId and __signature\n * @param props - Component props\n * @returns Component instance that responds to HMR updates\n */\nexport function createHMRComponent(componentFn, props) {\n const { __hmrId: hmrId, __signature: signature } = componentFn;\n\n if (!hmrId) {\n // If no hmrId, create normal component\n return createComponent(componentFn, props);\n }\n\n let info = componentRegistry.get(hmrId);\n\n if (!info) {\n info = {\n component: componentFn,\n signature,\n instances: new Set(),\n updated: false,\n };\n componentRegistry.set(hmrId, info);\n } else if (info.instances.size === 0 && !info.updated) {\n info.signature = signature;\n info.component = componentFn;\n }\n\n let component;\n let disposed = false;\n let isForceUpdating = false;\n const cleanupHMR = () => {\n if (isForceUpdating) return;\n if (disposed) return;\n disposed = true;\n cleanupInstance(hmrId, info, component);\n };\n\n // Use a stable boundary function so destroy cleanup is registered only\n // after the component is mounted inside a real Essor scope. This also lets\n // stale closures render the latest implementation after a hot update.\n function HMRBoundary(nextProps) {\n onDestroy(cleanupHMR);\n return info.component.call(this, nextProps);\n }\n\n component = createComponent(HMRBoundary, props);\n info.instances.add(component);\n\n const originalForceUpdate = component.forceUpdate;\n if (isFunction(originalForceUpdate)) {\n component.forceUpdate = function (...args) {\n isForceUpdating = true;\n try {\n return originalForceUpdate.apply(this, args);\n } finally {\n isForceUpdating = false;\n }\n };\n }\n\n // Integrate with component lifecycle - cleanup only when the component is\n // actually unmounted, not during forceUpdate's destroy/remount cycle.\n const originalDestroy = component.destroy;\n component.destroy = function (...args) {\n try {\n if (isFunction(originalDestroy)) {\n return originalDestroy.apply(this, args);\n }\n } finally {\n if (!isForceUpdating) {\n cleanupHMR();\n }\n }\n };\n\n return component;\n}\n\n/**\n * Determine if a component needs to be updated\n *\n * A component should update if:\n * 1. Function instance changed (indicates module was re-executed)\n * 2. Signature changed (indicates component code was modified)\n *\n * @param oldInfo - Existing component registry info\n * @param newComponentFn - New component function from updated module\n * @param newSignature - New signature hash from updated module\n * @returns true if component should update\n */\nfunction shouldUpdate(oldInfo, newComponentFn, newSignature) {\n if (!oldInfo) return true;\n\n // Check function instance (handles constant updates via module re-execution)\n if (oldInfo.component !== newComponentFn) {\n return true;\n }\n\n // Check compile-time signature (handles component code changes)\n return oldInfo.signature !== newSignature;\n}\n\n/**\n * Check if a value is an HMR-enabled component\n *\n * @param value - Value to check\n * @returns true if value is a function with __hmrId property\n */\nfunction isHMRComponent(value) {\n return value && isFunction(value) && value.__hmrId;\n}\n\nfunction emitHmrEvent(detail) {\n if (typeof CustomEvent !== 'undefined' && typeof dispatchEvent !== 'undefined') {\n dispatchEvent(new CustomEvent('essor:hmr-update', { detail }));\n }\n}\n\n/**\n * Apply HMR updates to components\n *\n * Iterates through the new component registry and force-updates live\n * component instances whose implementation changed.\n *\n * @param registry - Array of components from updated module\n * @returns true if reload needed (errors occurred), false otherwise\n */\nexport function applyUpdate(registry) {\n if (!Array.isArray(registry) || registry.length === 0) {\n return false;\n }\n\n let needsReload = false;\n const updatedIds = [];\n\n for (const entry of registry) {\n if (!isHMRComponent(entry)) {\n continue;\n }\n\n const { __hmrId: hmrId, __signature: signature } = entry;\n const info = componentRegistry.get(hmrId);\n\n if (!info) {\n componentRegistry.set(hmrId, {\n component: entry,\n signature,\n instances: new Set(),\n updated: true,\n });\n continue;\n }\n\n // Use shouldUpdate to determine if update is needed\n if (!shouldUpdate(info, entry, signature)) {\n continue;\n }\n\n info.signature = signature;\n info.component = entry;\n info.updated = true;\n updatedIds.push(hmrId);\n\n for (const component of [...info.instances]) {\n try {\n component.forceUpdate();\n } catch (error) {\n console.error(`[Essor HMR] Failed to update ${hmrId}:`, error);\n cleanupInstance(hmrId, info, component);\n needsReload = true;\n }\n }\n }\n\n if (updatedIds.length > 0) {\n emitHmrEvent({ updatedIds });\n }\n\n return needsReload;\n}\n\n/**\n * Setup HMR for Vite bundler\n *\n * Vite provides import.meta.hot.accept() callback that receives the new module\n */\nfunction setupViteHMR(hot, registry) {\n hot.data ??= {};\n const isUpdate = !!hot.data[ESSOR_HMR];\n hot.data[ESSOR_HMR] = registry;\n\n if (isUpdate) {\n if (applyUpdate(registry)) invalidateOrReload(hot);\n }\n}\n\n/**\n * Setup HMR for Webpack/Rspack bundlers\n *\n * Webpack-style HMR uses module.hot.accept() and hot.data for state persistence\n */\nfunction setupWebpackHMR(hot, registry) {\n if (isFunction(hot.accept)) {\n hot.accept();\n }\n\n if (hot.data?.[ESSOR_HMR]) {\n if (applyUpdate(registry)) invalidateOrReload(hot);\n }\n\n if (isFunction(hot.dispose)) {\n hot.dispose((data) => {\n data[ESSOR_HMR] = registry;\n });\n }\n}\n\n/**\n * Setup HMR for other bundlers (fallback)\n *\n * Attempts to work with any bundler that provides a basic hot module API\n */\nfunction setupStandardHMR(hot, registry) {\n // Try accept with a callback that receives the new module.\n if (isFunction(hot.accept)) {\n try {\n hot.accept((newModule) => {\n if (!newModule) {\n invalidateOrReload(hot);\n return;\n }\n const newRegistry = extractHMRComponents(newModule);\n if (newRegistry.length === 0) return;\n if (applyUpdate(newRegistry)) invalidateOrReload(hot);\n });\n } catch {\n // Some bundlers don't support accept with callback \u2014 fall back to simple accept.\n try {\n hot.accept();\n } catch (error_) {\n console.warn('[Essor HMR] Failed to setup hot.accept:', error_);\n }\n }\n }\n\n // Setup dispose handler for state persistence\n if (isFunction(hot.dispose)) {\n hot.dispose((data) => {\n data[ESSOR_HMR] = registry;\n });\n }\n\n // Apply update if previous data exists\n if (hot.data?.[ESSOR_HMR]) {\n if (applyUpdate(registry)) invalidateOrReload(hot);\n }\n}\n\n/**\n * Extract HMR components from a module\n *\n * Looks for __$registry$__ array first (generated by babel plugin),\n * then falls back to scanning all exports for HMR components\n *\n * @param module - Module object to scan\n * @returns Array of HMR component functions\n */\nfunction extractHMRComponents(module) {\n if (!module) return [];\n\n // Prefer __$registry$__\n if (Array.isArray(module.__$registry$__)) {\n return module.__$registry$__;\n }\n\n // Otherwise search in exports\n const components = [];\n for (const key of Object.keys(module)) {\n const value = module[key];\n if (isHMRComponent(value)) {\n components.push(value);\n }\n }\n return components;\n}\n\n/**\n * Main HMR entry point\n *\n * Called from transformed modules to set up HMR based on bundler type\n *\n * @param bundlerType - Type of bundler (vite, webpack5, rspack, etc.)\n * @param hot - Hot module API object (import.meta.hot or module.hot)\n * @param registry - Array of components from current module\n * @returns true if HMR setup succeeded, false otherwise\n */\nexport function hmrAccept(bundlerType, hot, registry) {\n if (!hot || !registry) {\n return false;\n }\n\n switch (bundlerType) {\n case 'vite':\n setupViteHMR(hot, registry);\n break;\n case 'webpack':\n case 'webpack5':\n case 'rspack':\n setupWebpackHMR(hot, registry);\n break;\n default:\n // Use standard HMR setup\n setupStandardHMR(hot, registry);\n break;\n }\n\n return true;\n}\n";
|
|
73
85
|
|
|
74
86
|
// src/index.ts
|
|
75
87
|
var VIRTUAL_MODULE_ID = "virtual:essor-hmr";
|
|
@@ -80,12 +92,27 @@ var DEFAULT_OPTIONS = {
|
|
|
80
92
|
props: true,
|
|
81
93
|
hmr: true,
|
|
82
94
|
enableFor: false,
|
|
83
|
-
omitClosingTags: true
|
|
95
|
+
omitClosingTags: true,
|
|
96
|
+
delegateEvents: true
|
|
97
|
+
};
|
|
98
|
+
var LEGACY_MODE_ALIASES = {
|
|
99
|
+
ssg: "server",
|
|
100
|
+
ssr: "hydrate"
|
|
84
101
|
};
|
|
102
|
+
function normalizeMode(mode) {
|
|
103
|
+
if (mode) {
|
|
104
|
+
return LEGACY_MODE_ALIASES[mode] || mode;
|
|
105
|
+
}
|
|
106
|
+
return "client";
|
|
107
|
+
}
|
|
85
108
|
var FILE_EXTENSION_REGEX = /\.[cm]?[jt]sx?$/i;
|
|
86
|
-
var
|
|
109
|
+
var SKIP_DIRECTORIES_REGEX = /[\\/](?:node_modules|dist|public)[\\/]/;
|
|
87
110
|
var HMR_DISPOSE_PREFIX = "import.meta.hot?.dispose(";
|
|
88
111
|
var HMR_DISPOSE_SUFFIX = ");";
|
|
112
|
+
var HMR_IMPORTS = {
|
|
113
|
+
createHMRComponent: `import { createHMRComponent as __$createHMRComponent$__ } from "${VIRTUAL_MODULE_ID}";`,
|
|
114
|
+
hmrAccept: `import { hmrAccept as __$hmrAccept$__ } from "${VIRTUAL_MODULE_ID}";`
|
|
115
|
+
};
|
|
89
116
|
function detectBundler(meta) {
|
|
90
117
|
if (meta == null ? void 0 : meta.framework) {
|
|
91
118
|
switch (meta.framework) {
|
|
@@ -109,6 +136,9 @@ function detectBundler(meta) {
|
|
|
109
136
|
return "standard";
|
|
110
137
|
}
|
|
111
138
|
function extractHMRDisposeHandlers(code) {
|
|
139
|
+
if (!code.includes(HMR_DISPOSE_PREFIX)) {
|
|
140
|
+
return { code, disposeHandlers: [] };
|
|
141
|
+
}
|
|
112
142
|
const lines = code.split("\n");
|
|
113
143
|
const disposeHandlers = [];
|
|
114
144
|
const cleanedLines = lines.filter((line) => {
|
|
@@ -124,42 +154,37 @@ function extractHMRDisposeHandlers(code) {
|
|
|
124
154
|
disposeHandlers
|
|
125
155
|
};
|
|
126
156
|
}
|
|
157
|
+
function getHotExpression(bundlerType) {
|
|
158
|
+
if (bundlerType === "webpack5" || bundlerType === "rspack") {
|
|
159
|
+
return "import.meta.webpackHot";
|
|
160
|
+
}
|
|
161
|
+
return "import.meta.hot";
|
|
162
|
+
}
|
|
127
163
|
function generateHMRCode(bundlerType, disposeHandlers = []) {
|
|
128
|
-
const
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
" import.meta.hot.accept();",
|
|
137
|
-
' __$hmrAccept$__("vite", import.meta.hot, __$registry$__);',
|
|
138
|
-
"}"
|
|
139
|
-
].join("\n") : [
|
|
140
|
-
"if (import.meta.hot) {",
|
|
141
|
-
...disposeLines,
|
|
142
|
-
` __$hmrAccept$__("${bundlerType}", import.meta.hot, __$registry$__);`,
|
|
143
|
-
"}"
|
|
144
|
-
].join("\n");
|
|
145
|
-
return {
|
|
146
|
-
imports,
|
|
147
|
-
register
|
|
148
|
-
};
|
|
164
|
+
const hot = getHotExpression(bundlerType);
|
|
165
|
+
const disposeLines = disposeHandlers.map((handler) => ` ${hot}.dispose(${handler});`);
|
|
166
|
+
const lines = [`if (${hot}) {`, ...disposeLines];
|
|
167
|
+
if (bundlerType === "vite") {
|
|
168
|
+
lines.push(` ${hot}.accept();`);
|
|
169
|
+
}
|
|
170
|
+
lines.push(` __$hmrAccept$__("${bundlerType}", ${hot}, __$registry$__);`, "}");
|
|
171
|
+
return { imports: HMR_IMPORTS, register: lines.join("\n") };
|
|
149
172
|
}
|
|
150
173
|
var unpluginFactory = (options = {}, meta) => {
|
|
174
|
+
var _a;
|
|
151
175
|
const filter = vite.createFilter(options.include, options.exclude);
|
|
152
176
|
const bundlerType = detectBundler(meta);
|
|
153
177
|
let isProd = process.env.NODE_ENV === "production";
|
|
154
178
|
const finalOptions = __spreadProps(__spreadValues(__spreadValues({}, DEFAULT_OPTIONS), options), {
|
|
179
|
+
mode: normalizeMode((_a = options.mode) != null ? _a : DEFAULT_OPTIONS.mode),
|
|
155
180
|
bundler: bundlerType
|
|
156
181
|
});
|
|
157
182
|
return {
|
|
158
183
|
name: "unplugin-essor",
|
|
159
184
|
/**
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
185
|
+
* Vite-specific config to preserve JSX so the babel plugin can handle it.
|
|
186
|
+
|
|
187
|
+
*/
|
|
163
188
|
vite: {
|
|
164
189
|
config() {
|
|
165
190
|
const ctx = this;
|
|
@@ -196,8 +221,8 @@ var unpluginFactory = (options = {}, meta) => {
|
|
|
196
221
|
},
|
|
197
222
|
rolldown: {
|
|
198
223
|
options(opts) {
|
|
199
|
-
var
|
|
200
|
-
(
|
|
224
|
+
var _a2;
|
|
225
|
+
(_a2 = opts.transform) != null ? _a2 : opts.transform = {
|
|
201
226
|
jsx: "preserve"
|
|
202
227
|
};
|
|
203
228
|
}
|
|
@@ -205,14 +230,21 @@ var unpluginFactory = (options = {}, meta) => {
|
|
|
205
230
|
/**
|
|
206
231
|
* Transform code with Babel plugin
|
|
207
232
|
*/
|
|
208
|
-
transform(code, id) {
|
|
209
|
-
|
|
233
|
+
transform(code, id, options2) {
|
|
234
|
+
var _b, _c;
|
|
235
|
+
if (SKIP_DIRECTORIES_REGEX.test(id) || !FILE_EXTENSION_REGEX.test(id) || !filter(id)) {
|
|
210
236
|
return;
|
|
211
237
|
}
|
|
212
238
|
if (!filter(id) || !FILE_EXTENSION_REGEX.test(id)) {
|
|
213
|
-
return
|
|
239
|
+
return;
|
|
214
240
|
}
|
|
215
|
-
const
|
|
241
|
+
const isSsr = finalOptions.mode === "server" || (options2 == null ? void 0 : options2.ssr) === true;
|
|
242
|
+
const _a2 = finalOptions, { symbol, include, exclude } = _a2, babelPassOptions = __objRest(_a2, ["symbol", "include", "exclude"]);
|
|
243
|
+
const babelOptions = __spreadProps(__spreadValues({}, babelPassOptions), {
|
|
244
|
+
signalPrefix: (_c = (_b = finalOptions.signalPrefix) != null ? _b : symbol) != null ? _c : "$",
|
|
245
|
+
mode: isSsr ? "server" : finalOptions.mode,
|
|
246
|
+
hmr: !isSsr && !isProd && finalOptions.hmr
|
|
247
|
+
});
|
|
216
248
|
let result;
|
|
217
249
|
try {
|
|
218
250
|
result = babel__namespace.transformSync(code, {
|
|
@@ -228,23 +260,24 @@ var unpluginFactory = (options = {}, meta) => {
|
|
|
228
260
|
if (!(result == null ? void 0 : result.code)) {
|
|
229
261
|
return code;
|
|
230
262
|
}
|
|
231
|
-
let finalCode
|
|
263
|
+
let finalCode;
|
|
232
264
|
if (babelOptions.hmr) {
|
|
233
|
-
const
|
|
234
|
-
const
|
|
235
|
-
const
|
|
236
|
-
if (
|
|
237
|
-
finalCode =
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
265
|
+
const { code: strippedCode, disposeHandlers } = extractHMRDisposeHandlers(result.code);
|
|
266
|
+
const hasComponents = strippedCode.includes("__$createHMRComponent$__");
|
|
267
|
+
const hasRegistry = strippedCode.includes("__$registry$__");
|
|
268
|
+
if (!hasComponents && !hasRegistry && disposeHandlers.length === 0) {
|
|
269
|
+
finalCode = result.code;
|
|
270
|
+
} else {
|
|
271
|
+
const hmrCode = generateHMRCode(bundlerType, disposeHandlers);
|
|
272
|
+
const parts = [];
|
|
273
|
+
if (hasRegistry) parts.push(hmrCode.imports.hmrAccept);
|
|
274
|
+
if (hasComponents) parts.push(hmrCode.imports.createHMRComponent);
|
|
275
|
+
parts.push(strippedCode);
|
|
276
|
+
if (hasRegistry) parts.push(hmrCode.register);
|
|
277
|
+
finalCode = parts.join("\n");
|
|
245
278
|
}
|
|
246
279
|
} else {
|
|
247
|
-
finalCode
|
|
280
|
+
finalCode = result.code;
|
|
248
281
|
}
|
|
249
282
|
return {
|
|
250
283
|
code: finalCode,
|
|
@@ -260,5 +293,5 @@ exports.__async = __async;
|
|
|
260
293
|
exports.index_default = index_default;
|
|
261
294
|
exports.unplugin = unplugin;
|
|
262
295
|
exports.unpluginFactory = unpluginFactory;
|
|
263
|
-
//# sourceMappingURL=chunk-
|
|
264
|
-
//# sourceMappingURL=chunk-
|
|
296
|
+
//# sourceMappingURL=chunk-ASRB37BB.cjs.map
|
|
297
|
+
//# sourceMappingURL=chunk-ASRB37BB.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["raw-loader:/home/runner/work/essor/essor/packages/unplugin/src/hmr-runtime.js?raw","../src/index.ts"],"names":["createFilter","_a","options","babel","essorBabelPlugin"],"mappings":"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","file":"chunk-ASRB37BB.cjs","sourcesContent":["/**\n * Essor HMR Runtime - Registry-based Hot Module Replacement\n *\n * This runtime enables precise component-level HMR updates without full page reloads:\n *\n * 1. **Registry Tracking**: Each component id points to its latest implementation\n * 2. **Signature Tracking**: Components are tracked by code signatures (from babel plugin)\n * 3. **Precise Updates**: Only components with changed signatures are updated\n * 4. **Instance Reloading**: Live component instances remount when their implementation changes\n * 5. **Bundler Agnostic**: Works with Vite, Webpack, Rspack, and other bundlers\n */\nimport { createComponent, onDestroy } from 'essor';\n\nconst isFunction = (value) => typeof value === 'function';\nconst ESSOR_HMR = 'essor-hmr';\n/**\n * Global component registry for HMR tracking\n *\n * Maps hmrId -> ComponentInfo where:\n * - hmrId: Unique identifier for component (fileHash:componentName)\n * - component: Current component function\n * - signature: Hash of component code (changes when code changes)\n * - instances: Set of active component instances\n * - updated: True after HMR applies a newer implementation\n */\nconst componentRegistry = new Map();\n\nfunction cleanupInstance(hmrId, info, component) {\n info.instances.delete(component);\n\n if (info.instances.size === 0 && !info.updated && componentRegistry.get(hmrId) === info) {\n componentRegistry.delete(hmrId);\n }\n}\n\n/**\n * Utility function to handle invalidate or reload\n * @param hot - Hot module API object\n */\nfunction invalidateOrReload(hot) {\n if (isFunction(hot?.invalidate)) {\n hot.invalidate();\n } else if (typeof location !== 'undefined') {\n location.reload();\n }\n}\n\n/**\n * Create HMR-enabled component wrapper\n *\n * This function wraps a component to enable HMR:\n * 1. Creates or retrieves component registry entry\n * 2. Creates the component from the latest registered implementation\n * 3. Tracks the instance until destroy()\n * 4. applyUpdate() remounts tracked instances when the implementation changes\n *\n * @param componentFn - Component function with __hmrId and __signature\n * @param props - Component props\n * @returns Component instance that responds to HMR updates\n */\nexport function createHMRComponent(componentFn, props) {\n const { __hmrId: hmrId, __signature: signature } = componentFn;\n\n if (!hmrId) {\n // If no hmrId, create normal component\n return createComponent(componentFn, props);\n }\n\n let info = componentRegistry.get(hmrId);\n\n if (!info) {\n info = {\n component: componentFn,\n signature,\n instances: new Set(),\n updated: false,\n };\n componentRegistry.set(hmrId, info);\n } else if (info.instances.size === 0 && !info.updated) {\n info.signature = signature;\n info.component = componentFn;\n }\n\n let component;\n let disposed = false;\n let isForceUpdating = false;\n const cleanupHMR = () => {\n if (isForceUpdating) return;\n if (disposed) return;\n disposed = true;\n cleanupInstance(hmrId, info, component);\n };\n\n // Use a stable boundary function so destroy cleanup is registered only\n // after the component is mounted inside a real Essor scope. This also lets\n // stale closures render the latest implementation after a hot update.\n function HMRBoundary(nextProps) {\n onDestroy(cleanupHMR);\n return info.component.call(this, nextProps);\n }\n\n component = createComponent(HMRBoundary, props);\n info.instances.add(component);\n\n const originalForceUpdate = component.forceUpdate;\n if (isFunction(originalForceUpdate)) {\n component.forceUpdate = function (...args) {\n isForceUpdating = true;\n try {\n return originalForceUpdate.apply(this, args);\n } finally {\n isForceUpdating = false;\n }\n };\n }\n\n // Integrate with component lifecycle - cleanup only when the component is\n // actually unmounted, not during forceUpdate's destroy/remount cycle.\n const originalDestroy = component.destroy;\n component.destroy = function (...args) {\n try {\n if (isFunction(originalDestroy)) {\n return originalDestroy.apply(this, args);\n }\n } finally {\n if (!isForceUpdating) {\n cleanupHMR();\n }\n }\n };\n\n return component;\n}\n\n/**\n * Determine if a component needs to be updated\n *\n * A component should update if:\n * 1. Function instance changed (indicates module was re-executed)\n * 2. Signature changed (indicates component code was modified)\n *\n * @param oldInfo - Existing component registry info\n * @param newComponentFn - New component function from updated module\n * @param newSignature - New signature hash from updated module\n * @returns true if component should update\n */\nfunction shouldUpdate(oldInfo, newComponentFn, newSignature) {\n if (!oldInfo) return true;\n\n // Check function instance (handles constant updates via module re-execution)\n if (oldInfo.component !== newComponentFn) {\n return true;\n }\n\n // Check compile-time signature (handles component code changes)\n return oldInfo.signature !== newSignature;\n}\n\n/**\n * Check if a value is an HMR-enabled component\n *\n * @param value - Value to check\n * @returns true if value is a function with __hmrId property\n */\nfunction isHMRComponent(value) {\n return value && isFunction(value) && value.__hmrId;\n}\n\nfunction emitHmrEvent(detail) {\n if (typeof CustomEvent !== 'undefined' && typeof dispatchEvent !== 'undefined') {\n dispatchEvent(new CustomEvent('essor:hmr-update', { detail }));\n }\n}\n\n/**\n * Apply HMR updates to components\n *\n * Iterates through the new component registry and force-updates live\n * component instances whose implementation changed.\n *\n * @param registry - Array of components from updated module\n * @returns true if reload needed (errors occurred), false otherwise\n */\nexport function applyUpdate(registry) {\n if (!Array.isArray(registry) || registry.length === 0) {\n return false;\n }\n\n let needsReload = false;\n const updatedIds = [];\n\n for (const entry of registry) {\n if (!isHMRComponent(entry)) {\n continue;\n }\n\n const { __hmrId: hmrId, __signature: signature } = entry;\n const info = componentRegistry.get(hmrId);\n\n if (!info) {\n componentRegistry.set(hmrId, {\n component: entry,\n signature,\n instances: new Set(),\n updated: true,\n });\n continue;\n }\n\n // Use shouldUpdate to determine if update is needed\n if (!shouldUpdate(info, entry, signature)) {\n continue;\n }\n\n info.signature = signature;\n info.component = entry;\n info.updated = true;\n updatedIds.push(hmrId);\n\n for (const component of [...info.instances]) {\n try {\n component.forceUpdate();\n } catch (error) {\n console.error(`[Essor HMR] Failed to update ${hmrId}:`, error);\n cleanupInstance(hmrId, info, component);\n needsReload = true;\n }\n }\n }\n\n if (updatedIds.length > 0) {\n emitHmrEvent({ updatedIds });\n }\n\n return needsReload;\n}\n\n/**\n * Setup HMR for Vite bundler\n *\n * Vite provides import.meta.hot.accept() callback that receives the new module\n */\nfunction setupViteHMR(hot, registry) {\n hot.data ??= {};\n const isUpdate = !!hot.data[ESSOR_HMR];\n hot.data[ESSOR_HMR] = registry;\n\n if (isUpdate) {\n if (applyUpdate(registry)) invalidateOrReload(hot);\n }\n}\n\n/**\n * Setup HMR for Webpack/Rspack bundlers\n *\n * Webpack-style HMR uses module.hot.accept() and hot.data for state persistence\n */\nfunction setupWebpackHMR(hot, registry) {\n if (isFunction(hot.accept)) {\n hot.accept();\n }\n\n if (hot.data?.[ESSOR_HMR]) {\n if (applyUpdate(registry)) invalidateOrReload(hot);\n }\n\n if (isFunction(hot.dispose)) {\n hot.dispose((data) => {\n data[ESSOR_HMR] = registry;\n });\n }\n}\n\n/**\n * Setup HMR for other bundlers (fallback)\n *\n * Attempts to work with any bundler that provides a basic hot module API\n */\nfunction setupStandardHMR(hot, registry) {\n // Try accept with a callback that receives the new module.\n if (isFunction(hot.accept)) {\n try {\n hot.accept((newModule) => {\n if (!newModule) {\n invalidateOrReload(hot);\n return;\n }\n const newRegistry = extractHMRComponents(newModule);\n if (newRegistry.length === 0) return;\n if (applyUpdate(newRegistry)) invalidateOrReload(hot);\n });\n } catch {\n // Some bundlers don't support accept with callback — fall back to simple accept.\n try {\n hot.accept();\n } catch (error_) {\n console.warn('[Essor HMR] Failed to setup hot.accept:', error_);\n }\n }\n }\n\n // Setup dispose handler for state persistence\n if (isFunction(hot.dispose)) {\n hot.dispose((data) => {\n data[ESSOR_HMR] = registry;\n });\n }\n\n // Apply update if previous data exists\n if (hot.data?.[ESSOR_HMR]) {\n if (applyUpdate(registry)) invalidateOrReload(hot);\n }\n}\n\n/**\n * Extract HMR components from a module\n *\n * Looks for __$registry$__ array first (generated by babel plugin),\n * then falls back to scanning all exports for HMR components\n *\n * @param module - Module object to scan\n * @returns Array of HMR component functions\n */\nfunction extractHMRComponents(module) {\n if (!module) return [];\n\n // Prefer __$registry$__\n if (Array.isArray(module.__$registry$__)) {\n return module.__$registry$__;\n }\n\n // Otherwise search in exports\n const components = [];\n for (const key of Object.keys(module)) {\n const value = module[key];\n if (isHMRComponent(value)) {\n components.push(value);\n }\n }\n return components;\n}\n\n/**\n * Main HMR entry point\n *\n * Called from transformed modules to set up HMR based on bundler type\n *\n * @param bundlerType - Type of bundler (vite, webpack5, rspack, etc.)\n * @param hot - Hot module API object (import.meta.hot or module.hot)\n * @param registry - Array of components from current module\n * @returns true if HMR setup succeeded, false otherwise\n */\nexport function hmrAccept(bundlerType, hot, registry) {\n if (!hot || !registry) {\n return false;\n }\n\n switch (bundlerType) {\n case 'vite':\n setupViteHMR(hot, registry);\n break;\n case 'webpack':\n case 'webpack5':\n case 'rspack':\n setupWebpackHMR(hot, registry);\n break;\n default:\n // Use standard HMR setup\n setupStandardHMR(hot, registry);\n break;\n }\n\n return true;\n}\n","import { createUnplugin } from 'unplugin';\nimport * as babel from '@babel/core';\nimport essorBabelPlugin from 'babel-plugin-essor';\nimport { createFilter } from 'vite';\n// @ts-ignore - resolved by esbuild raw plugin at build time\nimport hmrRuntimeCode from './hmr-runtime.js?raw';\nimport type { UnpluginContextMeta, UnpluginFactory } from 'unplugin';\nimport type { LegacyRenderMode, Options, RenderMode } from './types';\n\n/**\n * Virtual module ID for HMR runtime\n * Injected as an import in transformed files that have HMR components\n */\nconst VIRTUAL_MODULE_ID = 'virtual:essor-hmr';\nconst RESOLVED_VIRTUAL_MODULE_ID = '\\0virtual:essor-hmr';\n\n/**\n * Default plugin options\n */\nconst DEFAULT_OPTIONS = {\n symbol: '$' as const,\n mode: 'client' as RenderMode,\n props: true,\n hmr: true,\n enableFor: false,\n omitClosingTags: true,\n delegateEvents: true,\n};\n\n/**\n * Maps the deprecated `ssg` / `ssr` mode aliases onto the canonical render\n * modes understood by `babel-plugin-essor`:\n * - `ssg` → `server` (emit static HTML strings via `renderToString`)\n * - `ssr` → `hydrate` (emit hydration-ready client output)\n *\n * Retained only for backwards compatibility; the aliases will be removed in a\n * future major release (see {@link LegacyRenderMode}). Use the canonical\n * `client` | `server` | `hydrate` names instead.\n */\nconst LEGACY_MODE_ALIASES: Record<string, RenderMode> = {\n ssg: 'server',\n ssr: 'hydrate',\n};\n\n/**\n * Normalizes a user-supplied `mode` to a canonical {@link RenderMode}. Accepts\n * the canonical names verbatim and translates the deprecated `ssg` / `ssr`\n * aliases so the rest of the plugin and the Babel plugin only ever see\n * `client` | `server` | `hydrate`.\n */\nfunction normalizeMode(mode: RenderMode | LegacyRenderMode | undefined): RenderMode {\n if (mode) {\n return LEGACY_MODE_ALIASES[mode] || (mode as RenderMode);\n }\n return 'client';\n}\n\n/**\n * Performance: Pre-compiled regex and constants\n */\nconst FILE_EXTENSION_REGEX = /\\.[cm]?[jt]sx?$/i;\nconst SKIP_DIRECTORIES_REGEX = /[\\\\/](?:node_modules|dist|public)[\\\\/]/;\nconst HMR_DISPOSE_PREFIX = 'import.meta.hot?.dispose(';\nconst HMR_DISPOSE_SUFFIX = ');';\n\nconst HMR_IMPORTS = {\n createHMRComponent: `import { createHMRComponent as __$createHMRComponent$__ } from \"${VIRTUAL_MODULE_ID}\";`,\n hmrAccept: `import { hmrAccept as __$hmrAccept$__ } from \"${VIRTUAL_MODULE_ID}\";`,\n} as const;\n\ntype BundlerType = 'vite' | 'webpack5' | 'rspack' | 'rollup' | 'esbuild' | 'standard';\n\n/**\n * Detect bundler type from unplugin meta or environment variables\n *\n * This is important for HMR because different bundlers have different\n * HMR APIs (import.meta.hot.accept, module.hot.accept, etc.)\n */\nfunction detectBundler(meta: UnpluginContextMeta): BundlerType {\n // First, try to detect from unplugin meta\n if (meta?.framework) {\n switch (meta.framework) {\n case 'vite':\n return 'vite';\n case 'webpack':\n return 'webpack5';\n case 'rspack':\n return 'rspack';\n case 'rollup':\n return 'rollup';\n case 'esbuild':\n return 'esbuild';\n }\n }\n\n // Defensive fallback: unplugin always provides meta.framework, but in edge\n // cases (custom wrappers, test harnesses) these env vars act as a safety net.\n if (typeof process !== 'undefined' && process.env) {\n if (process.env.VITE || process.env.VITEST) return 'vite';\n if (process.env.WEBPACK_VERSION) return 'webpack5';\n if (process.env.RSPACK) return 'rspack';\n }\n\n return 'standard';\n}\n\n/**\n * Extract mount cleanup handlers emitted by the Babel HMR pass.\n *\n * @param code - Transformed module code.\n * @returns Module code without inline disposal calls and the extracted handlers.\n */\nfunction extractHMRDisposeHandlers(code: string) {\n if (!code.includes(HMR_DISPOSE_PREFIX)) {\n return { code, disposeHandlers: [] };\n }\n const lines = code.split('\\n');\n const disposeHandlers: string[] = [];\n const cleanedLines = lines.filter((line) => {\n const trimmed = line.trim();\n if (!trimmed.startsWith(HMR_DISPOSE_PREFIX) || !trimmed.endsWith(HMR_DISPOSE_SUFFIX)) {\n return true;\n }\n\n disposeHandlers.push(trimmed.slice(HMR_DISPOSE_PREFIX.length, -HMR_DISPOSE_SUFFIX.length));\n return false;\n });\n\n return {\n code: cleanedLines.join('\\n'),\n disposeHandlers,\n };\n}\n\n/**\n * Returns the correct hot-module-replacement global expression for a bundler.\n *\n * - Vite: `import.meta.hot`\n * - webpack / rspack: `import.meta.webpackHot` (webpack-compatible HMR protocol)\n * - others: `import.meta.hot` (no real HMR; guard is always falsy — safe)\n */\nfunction getHotExpression(bundlerType: BundlerType): string {\n if (bundlerType === 'webpack5' || bundlerType === 'rspack') {\n return 'import.meta.webpackHot';\n }\n return 'import.meta.hot';\n}\n\nfunction generateHMRCode(bundlerType: BundlerType, disposeHandlers: string[] = []) {\n const hot = getHotExpression(bundlerType);\n const disposeLines = disposeHandlers.map((handler) => ` ${hot}.dispose(${handler});`);\n\n // Build the HMR registration block. Vite needs an explicit `accept()` call;\n // webpack/rspack handle acceptance inside `__$hmrAccept$__`.\n const lines = [`if (${hot}) {`, ...disposeLines];\n if (bundlerType === 'vite') {\n lines.push(` ${hot}.accept();`);\n }\n lines.push(` __$hmrAccept$__(\"${bundlerType}\", ${hot}, __$registry$__);`, '}');\n\n return { imports: HMR_IMPORTS, register: lines.join('\\n') };\n}\n\nexport const unpluginFactory: UnpluginFactory<Options | undefined> = (\n options: Options = {},\n meta,\n) => {\n // Create file filter based on include/exclude patterns\n const filter = createFilter(options.include, options.exclude);\n\n // Detect bundler type for HMR\n const bundlerType = detectBundler(meta);\n\n // NODE_ENV is set by most bundlers; fallback treats unknown env as dev (HMR on)\n let isProd = process.env.NODE_ENV === 'production';\n\n // Merge user options with defaults (hmr excluded — computed dynamically in\n // transform). `mode` is normalized to a canonical RenderMode so the Babel\n // plugin only ever receives `client` | `server` | `hydrate`.\n const finalOptions = {\n ...DEFAULT_OPTIONS,\n ...options,\n mode: normalizeMode(options.mode ?? DEFAULT_OPTIONS.mode),\n bundler: bundlerType,\n };\n\n return {\n name: 'unplugin-essor',\n /**\n * Vite-specific config to preserve JSX so the babel plugin can handle it.\n\n */\n vite: {\n config(this: unknown) {\n // Inside a vite hook, `this` is the rollup plugin context. On Vite 8 /\n // rolldown-vite it exposes `meta.rolldownVersion`.\n const ctx = this as { meta?: Record<string, unknown> } | undefined;\n const isRolldownVite = !!ctx?.meta && 'rolldownVersion' in ctx.meta;\n const key = (isRolldownVite ? 'oxc' : 'esbuild') as 'esbuild';\n return {\n [key]: { jsx: 'preserve' },\n };\n },\n configResolved(config: { command: string }) {\n // Vite's command is more reliable than NODE_ENV for detecting dev vs build\n isProd = config.command === 'build';\n },\n },\n\n /**\n * Resolve virtual HMR runtime module\n */\n resolveId(id: string) {\n if (id === VIRTUAL_MODULE_ID) {\n return RESOLVED_VIRTUAL_MODULE_ID;\n }\n return null;\n },\n\n /**\n * Load virtual HMR runtime module\n */\n load(id: string) {\n if (id === RESOLVED_VIRTUAL_MODULE_ID) {\n return {\n code: hmrRuntimeCode,\n map: null,\n };\n }\n return null;\n },\n rolldown: {\n options(opts) {\n opts.transform ??= {\n jsx: 'preserve',\n };\n },\n },\n /**\n * Transform code with Babel plugin\n */\n transform(code, id, options?: { ssr?: boolean }) {\n // Skip node_modules, dist, public and non-JS/TS files\n if (SKIP_DIRECTORIES_REGEX.test(id) || !FILE_EXTENSION_REGEX.test(id) || !filter(id)) {\n return;\n }\n // Only transform JS/TS files\n if (!filter(id) || !FILE_EXTENSION_REGEX.test(id)) {\n return;\n }\n const isSsr = finalOptions.mode === 'server' || options?.ssr === true;\n\n // Extract unplugin-only options before passing to Babel\n const { symbol, include, exclude, ...babelPassOptions } = finalOptions;\n\n const babelOptions = {\n ...babelPassOptions,\n signalPrefix: finalOptions.signalPrefix ?? symbol ?? '$',\n mode: isSsr ? 'server' : finalOptions.mode,\n hmr: !isSsr && !isProd && finalOptions.hmr,\n };\n\n // Transform with Babel (with error handling)\n let result;\n try {\n result = babel.transformSync(code, {\n filename: id,\n sourceMaps: true,\n sourceType: 'module',\n plugins: [[essorBabelPlugin, babelOptions]],\n });\n } catch (error) {\n console.error(`[unplugin-essor] Transform failed for ${id}:`, error);\n return null;\n }\n\n if (!result?.code) {\n return code;\n }\n\n let finalCode: string;\n\n if (babelOptions.hmr) {\n const { code: strippedCode, disposeHandlers } = extractHMRDisposeHandlers(result.code);\n const hasComponents = strippedCode.includes('__$createHMRComponent$__');\n const hasRegistry = strippedCode.includes('__$registry$__');\n\n if (!hasComponents && !hasRegistry && disposeHandlers.length === 0) {\n finalCode = result.code;\n } else {\n const hmrCode = generateHMRCode(bundlerType, disposeHandlers);\n const parts: string[] = [];\n if (hasRegistry) parts.push(hmrCode.imports.hmrAccept);\n if (hasComponents) parts.push(hmrCode.imports.createHMRComponent);\n parts.push(strippedCode);\n if (hasRegistry) parts.push(hmrCode.register);\n\n finalCode = parts.join('\\n');\n }\n } else {\n finalCode = result.code;\n }\n\n return {\n code: finalCode,\n map: result.map,\n };\n },\n };\n};\n\nexport const unplugin = /* #__PURE__ */ createUnplugin(unpluginFactory);\n\nexport default unplugin;\n"]}
|
|
@@ -22,6 +22,18 @@ var __spreadValues = (a, b) => {
|
|
|
22
22
|
return a;
|
|
23
23
|
};
|
|
24
24
|
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
25
|
+
var __objRest = (source, exclude) => {
|
|
26
|
+
var target = {};
|
|
27
|
+
for (var prop in source)
|
|
28
|
+
if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
|
|
29
|
+
target[prop] = source[prop];
|
|
30
|
+
if (source != null && __getOwnPropSymbols)
|
|
31
|
+
for (var prop of __getOwnPropSymbols(source)) {
|
|
32
|
+
if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
|
|
33
|
+
target[prop] = source[prop];
|
|
34
|
+
}
|
|
35
|
+
return target;
|
|
36
|
+
};
|
|
25
37
|
var __async = (__this, __arguments, generator) => {
|
|
26
38
|
return new Promise((resolve, reject) => {
|
|
27
39
|
var fulfilled = (value) => {
|
|
@@ -44,7 +56,7 @@ var __async = (__this, __arguments, generator) => {
|
|
|
44
56
|
};
|
|
45
57
|
|
|
46
58
|
// raw-loader:/home/runner/work/essor/essor/packages/unplugin/src/hmr-runtime.js?raw
|
|
47
|
-
var hmr_runtime_default = "/**\n * Essor HMR Runtime - Registry-based Hot Module Replacement\n *\n * This runtime enables precise component-level HMR updates without full page reloads:\n *\n * 1. **Registry Tracking**: Each component id points to its latest implementation\n * 2. **Signature Tracking**: Components are tracked by code signatures (from babel plugin)\n * 3. **Precise Updates**: Only components with changed signatures are updated\n * 4. **Instance Reloading**: Live component instances remount when their implementation changes\n * 5. **Bundler Agnostic**: Works with Vite, Webpack, Rspack, and other bundlers\n */\nimport { createComponent, onDestroy } from 'essor';\n\nconst isFunction = (value) => typeof value === 'function';\nconst ESSOR_HMR = 'essor-hmr';\n/**\n * Global component registry for HMR tracking\n *\n * Maps hmrId -> ComponentInfo where:\n * - hmrId: Unique identifier for component (fileHash:componentName)\n * - component: Current component function\n * - signature: Hash of component code (changes when code changes)\n * - instances: Set of active component instances\n * - updated: True after HMR applies a newer implementation\n */\nconst componentRegistry = new Map();\n\nfunction cleanupInstance(hmrId, info, component) {\n info.instances.delete(component);\n\n if (info.instances.size === 0 && !info.updated && componentRegistry.get(hmrId) === info) {\n componentRegistry.delete(hmrId);\n }\n}\n\n/**\n * Utility function to handle invalidate or reload\n * @param hot - Hot module API object\n */\nfunction invalidateOrReload(hot) {\n if (isFunction(hot?.invalidate)) {\n hot.invalidate();\n } else if (typeof location !== 'undefined') {\n location.reload();\n }\n}\n\n/**\n * Create HMR-enabled component wrapper\n *\n * This function wraps a component to enable HMR:\n * 1. Creates or retrieves component registry entry\n * 2. Creates the component from the latest registered implementation\n * 3. Tracks the instance until destroy()\n * 4. applyUpdate() remounts tracked instances when the implementation changes\n *\n * @param componentFn - Component function with __hmrId and __signature\n * @param props - Component props\n * @returns Component instance that responds to HMR updates\n */\nexport function createHMRComponent(componentFn, props) {\n const { __hmrId: hmrId, __signature: signature } = componentFn;\n\n if (!hmrId) {\n // If no hmrId, create normal component\n return createComponent(componentFn, props);\n }\n\n let info = componentRegistry.get(hmrId);\n\n if (!info) {\n info = {\n component: componentFn,\n signature,\n instances: new Set(),\n updated: false,\n };\n componentRegistry.set(hmrId, info);\n } else if (info.instances.size === 0 && !info.updated) {\n info.signature = signature;\n info.component = componentFn;\n }\n\n let component;\n let disposed = false;\n let isForceUpdating = false;\n const cleanupHMR = () => {\n if (isForceUpdating) return;\n if (disposed) return;\n disposed = true;\n cleanupInstance(hmrId, info, component);\n };\n\n // Use a stable boundary function so destroy cleanup is registered only\n // after the component is mounted inside a real Essor scope. This also lets\n // stale closures render the latest implementation after a hot update.\n function HMRBoundary(nextProps) {\n onDestroy(cleanupHMR);\n return info.component.call(this, nextProps);\n }\n\n component = createComponent(HMRBoundary, props);\n info.instances.add(component);\n\n const originalForceUpdate = component.forceUpdate;\n if (isFunction(originalForceUpdate)) {\n component.forceUpdate = function (...args) {\n isForceUpdating = true;\n try {\n return originalForceUpdate.apply(this, args);\n } finally {\n isForceUpdating = false;\n }\n };\n }\n\n // Integrate with component lifecycle - cleanup only when the component is\n // actually unmounted, not during forceUpdate's destroy/remount cycle.\n const originalDestroy = component.destroy;\n component.destroy = function (...args) {\n try {\n if (isFunction(originalDestroy)) {\n return originalDestroy.apply(this, args);\n }\n } finally {\n if (!isForceUpdating) {\n cleanupHMR();\n }\n }\n };\n\n return component;\n}\n\n/**\n * Determine if a component needs to be updated\n *\n * A component should update if:\n * 1. Function instance changed (indicates module was re-executed)\n * 2. Signature changed (indicates component code was modified)\n *\n * @param oldInfo - Existing component registry info\n * @param newComponentFn - New component function from updated module\n * @param newSignature - New signature hash from updated module\n * @returns true if component should update\n */\nfunction shouldUpdate(oldInfo, newComponentFn, newSignature) {\n if (!oldInfo) return true;\n\n // Check function instance (handles constant updates via module re-execution)\n if (oldInfo.component !== newComponentFn) {\n return true;\n }\n\n // Check compile-time signature (handles component code changes)\n return oldInfo.signature !== newSignature;\n}\n\n/**\n * Check if a value is an HMR-enabled component\n *\n * @param value - Value to check\n * @returns true if value is a function with __hmrId property\n */\nfunction isHMRComponent(value) {\n return value && isFunction(value) && value.__hmrId;\n}\n\n/**\n * Apply HMR updates to components\n *\n * Iterates through the new component registry and force-updates live\n * component instances whose implementation changed.\n *\n * @param registry - Array of components from updated module\n * @returns true if reload needed (errors occurred), false otherwise\n */\nexport function applyUpdate(registry) {\n if (!Array.isArray(registry) || registry.length === 0) {\n return false;\n }\n\n let needsReload = false;\n\n for (const entry of registry) {\n if (!isHMRComponent(entry)) {\n continue;\n }\n\n const { __hmrId: hmrId, __signature: signature } = entry;\n const id = hmrId;\n const info = componentRegistry.get(hmrId);\n\n if (!info) {\n componentRegistry.set(hmrId, {\n component: entry,\n signature,\n instances: new Set(),\n updated: true,\n });\n continue;\n }\n\n // Use shouldUpdate to determine if update is needed\n if (!shouldUpdate(info, entry, signature)) {\n continue;\n }\n\n info.signature = signature;\n info.component = entry;\n info.updated = true;\n\n for (const component of [...info.instances]) {\n try {\n component.forceUpdate();\n } catch (error) {\n console.error(`[Essor HMR] Failed to update ${id}:`, error);\n cleanupInstance(hmrId, info, component);\n needsReload = true;\n }\n }\n }\n\n return needsReload;\n}\n\n/**\n * Common handler for HMR updates across bundlers\n * @param hot - Hot module API\n * @param newModule - Updated module\n * @returns true if handled successfully\n */\nfunction handleHMRUpdate(hot, newModule) {\n if (!newModule) {\n invalidateOrReload(hot);\n return false;\n }\n\n // Extract HMR components from new module\n const newRegistry = extractHMRComponents(newModule);\n if (newRegistry.length === 0) {\n return true;\n }\n\n const needsReload = applyUpdate(newRegistry);\n if (needsReload) {\n invalidateOrReload(hot);\n }\n return true;\n}\n\n/**\n * Setup HMR for Vite bundler\n *\n * Vite provides import.meta.hot.accept() callback that receives the new module\n */\nfunction setupViteHMR(hot, registry) {\n hot.data ??= {};\n const isUpdate = !!hot.data[ESSOR_HMR];\n hot.data[ESSOR_HMR] = registry;\n\n if (isUpdate) {\n const needsReload = applyUpdate(registry);\n if (needsReload) {\n invalidateOrReload(hot);\n }\n }\n}\n\n/**\n * Setup HMR for Webpack/Rspack bundlers\n *\n * Webpack-style HMR uses module.hot.accept() and hot.data for state persistence\n */\nfunction setupWebpackHMR(hot, registry) {\n if (isFunction(hot.accept)) {\n hot.accept();\n }\n\n // Apply update if previous data exists from last hot reload\n if (hot.data?.[ESSOR_HMR]) {\n const needsReload = applyUpdate(registry);\n if (needsReload) {\n invalidateOrReload(hot);\n }\n }\n\n // Save current registry for next update\n if (isFunction(hot.dispose)) {\n hot.dispose((data) => {\n data[ESSOR_HMR] = registry;\n });\n }\n}\n\n/**\n * Setup HMR for other bundlers (fallback)\n *\n * Attempts to work with any bundler that provides a basic hot module API\n */\nfunction setupStandardHMR(hot, registry) {\n // Try accept callback mode first (more efficient)\n if (isFunction(hot.accept)) {\n try {\n hot.accept((newModule) => handleHMRUpdate(hot, newModule));\n } catch {\n // Some bundlers don't support accept with callback\n // Fall back to simple accept (for Webpack-style pattern)\n try {\n hot.accept();\n } catch (error_) {\n console.warn('[Essor HMR] Failed to setup hot.accept:', error_);\n }\n }\n }\n\n // Setup dispose handler for state persistence\n if (isFunction(hot.dispose)) {\n hot.dispose((data) => {\n data.__$registry$__ = registry;\n data.__essor_timestamp__ = Date.now();\n });\n }\n\n // Apply update if previous data exists (for Webpack-style HMR)\n if (hot.data?.__$registry$__) {\n const needsReload = applyUpdate(registry);\n if (needsReload) {\n invalidateOrReload(hot);\n }\n }\n}\n\n/**\n * Extract HMR components from a module\n *\n * Looks for __$registry$__ array first (generated by babel plugin),\n * then falls back to scanning all exports for HMR components\n *\n * @param module - Module object to scan\n * @returns Array of HMR component functions\n */\nfunction extractHMRComponents(module) {\n if (!module) return [];\n\n // Prefer __$registry$__\n if (Array.isArray(module.__$registry$__)) {\n return module.__$registry$__;\n }\n\n // Otherwise search in exports\n const components = [];\n for (const key of Object.keys(module)) {\n const value = module[key];\n if (isHMRComponent(value)) {\n components.push(value);\n }\n }\n return components;\n}\n\n/**\n * Main HMR entry point\n *\n * Called from transformed modules to set up HMR based on bundler type\n *\n * @param bundlerType - Type of bundler (vite, webpack5, rspack, etc.)\n * @param hot - Hot module API object (import.meta.hot or module.hot)\n * @param registry - Array of components from current module\n * @returns true if HMR setup succeeded, false otherwise\n */\nexport function hmrAccept(bundlerType, hot, registry) {\n if (!hot || !registry) {\n return false;\n }\n\n switch (bundlerType) {\n case 'vite':\n setupViteHMR(hot, registry);\n break;\n case 'webpack':\n case 'webpack5':\n case 'rspack':\n setupWebpackHMR(hot, registry);\n break;\n default:\n // Use standard HMR setup\n setupStandardHMR(hot, registry);\n break;\n }\n\n return true;\n}\n\n/**\n * Cleanup all instances of a component (utility function)\n *\n * @param hmrId - Component HMR ID\n * @returns Number of instances cleaned up\n */\nexport function unregisterAllInstances(hmrId) {\n const info = componentRegistry.get(hmrId);\n if (!info) return 0;\n\n let count = 0;\n for (const item of [...info.instances]) {\n try {\n cleanupInstance(hmrId, info, item);\n } catch (error) {\n console.error(`[Essor HMR] Failed to unregister component instance:`, error);\n }\n count++;\n }\n\n return count;\n}\n\n/**\n * Get registry information for debugging\n *\n * @returns Object mapping hmrId to component info (signature, instance count)\n */\nexport function getRegistryInfo() {\n const info = {};\n for (const [id, data] of componentRegistry) {\n info[id] = {\n signature: data.signature,\n instanceCount: data.instances.size,\n };\n }\n return info;\n}\n";
|
|
59
|
+
var hmr_runtime_default = "/**\n * Essor HMR Runtime - Registry-based Hot Module Replacement\n *\n * This runtime enables precise component-level HMR updates without full page reloads:\n *\n * 1. **Registry Tracking**: Each component id points to its latest implementation\n * 2. **Signature Tracking**: Components are tracked by code signatures (from babel plugin)\n * 3. **Precise Updates**: Only components with changed signatures are updated\n * 4. **Instance Reloading**: Live component instances remount when their implementation changes\n * 5. **Bundler Agnostic**: Works with Vite, Webpack, Rspack, and other bundlers\n */\nimport { createComponent, onDestroy } from 'essor';\n\nconst isFunction = (value) => typeof value === 'function';\nconst ESSOR_HMR = 'essor-hmr';\n/**\n * Global component registry for HMR tracking\n *\n * Maps hmrId -> ComponentInfo where:\n * - hmrId: Unique identifier for component (fileHash:componentName)\n * - component: Current component function\n * - signature: Hash of component code (changes when code changes)\n * - instances: Set of active component instances\n * - updated: True after HMR applies a newer implementation\n */\nconst componentRegistry = new Map();\n\nfunction cleanupInstance(hmrId, info, component) {\n info.instances.delete(component);\n\n if (info.instances.size === 0 && !info.updated && componentRegistry.get(hmrId) === info) {\n componentRegistry.delete(hmrId);\n }\n}\n\n/**\n * Utility function to handle invalidate or reload\n * @param hot - Hot module API object\n */\nfunction invalidateOrReload(hot) {\n if (isFunction(hot?.invalidate)) {\n hot.invalidate();\n } else if (typeof location !== 'undefined') {\n location.reload();\n }\n}\n\n/**\n * Create HMR-enabled component wrapper\n *\n * This function wraps a component to enable HMR:\n * 1. Creates or retrieves component registry entry\n * 2. Creates the component from the latest registered implementation\n * 3. Tracks the instance until destroy()\n * 4. applyUpdate() remounts tracked instances when the implementation changes\n *\n * @param componentFn - Component function with __hmrId and __signature\n * @param props - Component props\n * @returns Component instance that responds to HMR updates\n */\nexport function createHMRComponent(componentFn, props) {\n const { __hmrId: hmrId, __signature: signature } = componentFn;\n\n if (!hmrId) {\n // If no hmrId, create normal component\n return createComponent(componentFn, props);\n }\n\n let info = componentRegistry.get(hmrId);\n\n if (!info) {\n info = {\n component: componentFn,\n signature,\n instances: new Set(),\n updated: false,\n };\n componentRegistry.set(hmrId, info);\n } else if (info.instances.size === 0 && !info.updated) {\n info.signature = signature;\n info.component = componentFn;\n }\n\n let component;\n let disposed = false;\n let isForceUpdating = false;\n const cleanupHMR = () => {\n if (isForceUpdating) return;\n if (disposed) return;\n disposed = true;\n cleanupInstance(hmrId, info, component);\n };\n\n // Use a stable boundary function so destroy cleanup is registered only\n // after the component is mounted inside a real Essor scope. This also lets\n // stale closures render the latest implementation after a hot update.\n function HMRBoundary(nextProps) {\n onDestroy(cleanupHMR);\n return info.component.call(this, nextProps);\n }\n\n component = createComponent(HMRBoundary, props);\n info.instances.add(component);\n\n const originalForceUpdate = component.forceUpdate;\n if (isFunction(originalForceUpdate)) {\n component.forceUpdate = function (...args) {\n isForceUpdating = true;\n try {\n return originalForceUpdate.apply(this, args);\n } finally {\n isForceUpdating = false;\n }\n };\n }\n\n // Integrate with component lifecycle - cleanup only when the component is\n // actually unmounted, not during forceUpdate's destroy/remount cycle.\n const originalDestroy = component.destroy;\n component.destroy = function (...args) {\n try {\n if (isFunction(originalDestroy)) {\n return originalDestroy.apply(this, args);\n }\n } finally {\n if (!isForceUpdating) {\n cleanupHMR();\n }\n }\n };\n\n return component;\n}\n\n/**\n * Determine if a component needs to be updated\n *\n * A component should update if:\n * 1. Function instance changed (indicates module was re-executed)\n * 2. Signature changed (indicates component code was modified)\n *\n * @param oldInfo - Existing component registry info\n * @param newComponentFn - New component function from updated module\n * @param newSignature - New signature hash from updated module\n * @returns true if component should update\n */\nfunction shouldUpdate(oldInfo, newComponentFn, newSignature) {\n if (!oldInfo) return true;\n\n // Check function instance (handles constant updates via module re-execution)\n if (oldInfo.component !== newComponentFn) {\n return true;\n }\n\n // Check compile-time signature (handles component code changes)\n return oldInfo.signature !== newSignature;\n}\n\n/**\n * Check if a value is an HMR-enabled component\n *\n * @param value - Value to check\n * @returns true if value is a function with __hmrId property\n */\nfunction isHMRComponent(value) {\n return value && isFunction(value) && value.__hmrId;\n}\n\nfunction emitHmrEvent(detail) {\n if (typeof CustomEvent !== 'undefined' && typeof dispatchEvent !== 'undefined') {\n dispatchEvent(new CustomEvent('essor:hmr-update', { detail }));\n }\n}\n\n/**\n * Apply HMR updates to components\n *\n * Iterates through the new component registry and force-updates live\n * component instances whose implementation changed.\n *\n * @param registry - Array of components from updated module\n * @returns true if reload needed (errors occurred), false otherwise\n */\nexport function applyUpdate(registry) {\n if (!Array.isArray(registry) || registry.length === 0) {\n return false;\n }\n\n let needsReload = false;\n const updatedIds = [];\n\n for (const entry of registry) {\n if (!isHMRComponent(entry)) {\n continue;\n }\n\n const { __hmrId: hmrId, __signature: signature } = entry;\n const info = componentRegistry.get(hmrId);\n\n if (!info) {\n componentRegistry.set(hmrId, {\n component: entry,\n signature,\n instances: new Set(),\n updated: true,\n });\n continue;\n }\n\n // Use shouldUpdate to determine if update is needed\n if (!shouldUpdate(info, entry, signature)) {\n continue;\n }\n\n info.signature = signature;\n info.component = entry;\n info.updated = true;\n updatedIds.push(hmrId);\n\n for (const component of [...info.instances]) {\n try {\n component.forceUpdate();\n } catch (error) {\n console.error(`[Essor HMR] Failed to update ${hmrId}:`, error);\n cleanupInstance(hmrId, info, component);\n needsReload = true;\n }\n }\n }\n\n if (updatedIds.length > 0) {\n emitHmrEvent({ updatedIds });\n }\n\n return needsReload;\n}\n\n/**\n * Setup HMR for Vite bundler\n *\n * Vite provides import.meta.hot.accept() callback that receives the new module\n */\nfunction setupViteHMR(hot, registry) {\n hot.data ??= {};\n const isUpdate = !!hot.data[ESSOR_HMR];\n hot.data[ESSOR_HMR] = registry;\n\n if (isUpdate) {\n if (applyUpdate(registry)) invalidateOrReload(hot);\n }\n}\n\n/**\n * Setup HMR for Webpack/Rspack bundlers\n *\n * Webpack-style HMR uses module.hot.accept() and hot.data for state persistence\n */\nfunction setupWebpackHMR(hot, registry) {\n if (isFunction(hot.accept)) {\n hot.accept();\n }\n\n if (hot.data?.[ESSOR_HMR]) {\n if (applyUpdate(registry)) invalidateOrReload(hot);\n }\n\n if (isFunction(hot.dispose)) {\n hot.dispose((data) => {\n data[ESSOR_HMR] = registry;\n });\n }\n}\n\n/**\n * Setup HMR for other bundlers (fallback)\n *\n * Attempts to work with any bundler that provides a basic hot module API\n */\nfunction setupStandardHMR(hot, registry) {\n // Try accept with a callback that receives the new module.\n if (isFunction(hot.accept)) {\n try {\n hot.accept((newModule) => {\n if (!newModule) {\n invalidateOrReload(hot);\n return;\n }\n const newRegistry = extractHMRComponents(newModule);\n if (newRegistry.length === 0) return;\n if (applyUpdate(newRegistry)) invalidateOrReload(hot);\n });\n } catch {\n // Some bundlers don't support accept with callback \u2014 fall back to simple accept.\n try {\n hot.accept();\n } catch (error_) {\n console.warn('[Essor HMR] Failed to setup hot.accept:', error_);\n }\n }\n }\n\n // Setup dispose handler for state persistence\n if (isFunction(hot.dispose)) {\n hot.dispose((data) => {\n data[ESSOR_HMR] = registry;\n });\n }\n\n // Apply update if previous data exists\n if (hot.data?.[ESSOR_HMR]) {\n if (applyUpdate(registry)) invalidateOrReload(hot);\n }\n}\n\n/**\n * Extract HMR components from a module\n *\n * Looks for __$registry$__ array first (generated by babel plugin),\n * then falls back to scanning all exports for HMR components\n *\n * @param module - Module object to scan\n * @returns Array of HMR component functions\n */\nfunction extractHMRComponents(module) {\n if (!module) return [];\n\n // Prefer __$registry$__\n if (Array.isArray(module.__$registry$__)) {\n return module.__$registry$__;\n }\n\n // Otherwise search in exports\n const components = [];\n for (const key of Object.keys(module)) {\n const value = module[key];\n if (isHMRComponent(value)) {\n components.push(value);\n }\n }\n return components;\n}\n\n/**\n * Main HMR entry point\n *\n * Called from transformed modules to set up HMR based on bundler type\n *\n * @param bundlerType - Type of bundler (vite, webpack5, rspack, etc.)\n * @param hot - Hot module API object (import.meta.hot or module.hot)\n * @param registry - Array of components from current module\n * @returns true if HMR setup succeeded, false otherwise\n */\nexport function hmrAccept(bundlerType, hot, registry) {\n if (!hot || !registry) {\n return false;\n }\n\n switch (bundlerType) {\n case 'vite':\n setupViteHMR(hot, registry);\n break;\n case 'webpack':\n case 'webpack5':\n case 'rspack':\n setupWebpackHMR(hot, registry);\n break;\n default:\n // Use standard HMR setup\n setupStandardHMR(hot, registry);\n break;\n }\n\n return true;\n}\n";
|
|
48
60
|
|
|
49
61
|
// src/index.ts
|
|
50
62
|
var VIRTUAL_MODULE_ID = "virtual:essor-hmr";
|
|
@@ -55,12 +67,27 @@ var DEFAULT_OPTIONS = {
|
|
|
55
67
|
props: true,
|
|
56
68
|
hmr: true,
|
|
57
69
|
enableFor: false,
|
|
58
|
-
omitClosingTags: true
|
|
70
|
+
omitClosingTags: true,
|
|
71
|
+
delegateEvents: true
|
|
72
|
+
};
|
|
73
|
+
var LEGACY_MODE_ALIASES = {
|
|
74
|
+
ssg: "server",
|
|
75
|
+
ssr: "hydrate"
|
|
59
76
|
};
|
|
77
|
+
function normalizeMode(mode) {
|
|
78
|
+
if (mode) {
|
|
79
|
+
return LEGACY_MODE_ALIASES[mode] || mode;
|
|
80
|
+
}
|
|
81
|
+
return "client";
|
|
82
|
+
}
|
|
60
83
|
var FILE_EXTENSION_REGEX = /\.[cm]?[jt]sx?$/i;
|
|
61
|
-
var
|
|
84
|
+
var SKIP_DIRECTORIES_REGEX = /[\\/](?:node_modules|dist|public)[\\/]/;
|
|
62
85
|
var HMR_DISPOSE_PREFIX = "import.meta.hot?.dispose(";
|
|
63
86
|
var HMR_DISPOSE_SUFFIX = ");";
|
|
87
|
+
var HMR_IMPORTS = {
|
|
88
|
+
createHMRComponent: `import { createHMRComponent as __$createHMRComponent$__ } from "${VIRTUAL_MODULE_ID}";`,
|
|
89
|
+
hmrAccept: `import { hmrAccept as __$hmrAccept$__ } from "${VIRTUAL_MODULE_ID}";`
|
|
90
|
+
};
|
|
64
91
|
function detectBundler(meta) {
|
|
65
92
|
if (meta == null ? void 0 : meta.framework) {
|
|
66
93
|
switch (meta.framework) {
|
|
@@ -84,6 +111,9 @@ function detectBundler(meta) {
|
|
|
84
111
|
return "standard";
|
|
85
112
|
}
|
|
86
113
|
function extractHMRDisposeHandlers(code) {
|
|
114
|
+
if (!code.includes(HMR_DISPOSE_PREFIX)) {
|
|
115
|
+
return { code, disposeHandlers: [] };
|
|
116
|
+
}
|
|
87
117
|
const lines = code.split("\n");
|
|
88
118
|
const disposeHandlers = [];
|
|
89
119
|
const cleanedLines = lines.filter((line) => {
|
|
@@ -99,42 +129,37 @@ function extractHMRDisposeHandlers(code) {
|
|
|
99
129
|
disposeHandlers
|
|
100
130
|
};
|
|
101
131
|
}
|
|
132
|
+
function getHotExpression(bundlerType) {
|
|
133
|
+
if (bundlerType === "webpack5" || bundlerType === "rspack") {
|
|
134
|
+
return "import.meta.webpackHot";
|
|
135
|
+
}
|
|
136
|
+
return "import.meta.hot";
|
|
137
|
+
}
|
|
102
138
|
function generateHMRCode(bundlerType, disposeHandlers = []) {
|
|
103
|
-
const
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
" import.meta.hot.accept();",
|
|
112
|
-
' __$hmrAccept$__("vite", import.meta.hot, __$registry$__);',
|
|
113
|
-
"}"
|
|
114
|
-
].join("\n") : [
|
|
115
|
-
"if (import.meta.hot) {",
|
|
116
|
-
...disposeLines,
|
|
117
|
-
` __$hmrAccept$__("${bundlerType}", import.meta.hot, __$registry$__);`,
|
|
118
|
-
"}"
|
|
119
|
-
].join("\n");
|
|
120
|
-
return {
|
|
121
|
-
imports,
|
|
122
|
-
register
|
|
123
|
-
};
|
|
139
|
+
const hot = getHotExpression(bundlerType);
|
|
140
|
+
const disposeLines = disposeHandlers.map((handler) => ` ${hot}.dispose(${handler});`);
|
|
141
|
+
const lines = [`if (${hot}) {`, ...disposeLines];
|
|
142
|
+
if (bundlerType === "vite") {
|
|
143
|
+
lines.push(` ${hot}.accept();`);
|
|
144
|
+
}
|
|
145
|
+
lines.push(` __$hmrAccept$__("${bundlerType}", ${hot}, __$registry$__);`, "}");
|
|
146
|
+
return { imports: HMR_IMPORTS, register: lines.join("\n") };
|
|
124
147
|
}
|
|
125
148
|
var unpluginFactory = (options = {}, meta) => {
|
|
149
|
+
var _a;
|
|
126
150
|
const filter = createFilter(options.include, options.exclude);
|
|
127
151
|
const bundlerType = detectBundler(meta);
|
|
128
152
|
let isProd = process.env.NODE_ENV === "production";
|
|
129
153
|
const finalOptions = __spreadProps(__spreadValues(__spreadValues({}, DEFAULT_OPTIONS), options), {
|
|
154
|
+
mode: normalizeMode((_a = options.mode) != null ? _a : DEFAULT_OPTIONS.mode),
|
|
130
155
|
bundler: bundlerType
|
|
131
156
|
});
|
|
132
157
|
return {
|
|
133
158
|
name: "unplugin-essor",
|
|
134
159
|
/**
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
160
|
+
* Vite-specific config to preserve JSX so the babel plugin can handle it.
|
|
161
|
+
|
|
162
|
+
*/
|
|
138
163
|
vite: {
|
|
139
164
|
config() {
|
|
140
165
|
const ctx = this;
|
|
@@ -171,8 +196,8 @@ var unpluginFactory = (options = {}, meta) => {
|
|
|
171
196
|
},
|
|
172
197
|
rolldown: {
|
|
173
198
|
options(opts) {
|
|
174
|
-
var
|
|
175
|
-
(
|
|
199
|
+
var _a2;
|
|
200
|
+
(_a2 = opts.transform) != null ? _a2 : opts.transform = {
|
|
176
201
|
jsx: "preserve"
|
|
177
202
|
};
|
|
178
203
|
}
|
|
@@ -180,14 +205,21 @@ var unpluginFactory = (options = {}, meta) => {
|
|
|
180
205
|
/**
|
|
181
206
|
* Transform code with Babel plugin
|
|
182
207
|
*/
|
|
183
|
-
transform(code, id) {
|
|
184
|
-
|
|
208
|
+
transform(code, id, options2) {
|
|
209
|
+
var _b, _c;
|
|
210
|
+
if (SKIP_DIRECTORIES_REGEX.test(id) || !FILE_EXTENSION_REGEX.test(id) || !filter(id)) {
|
|
185
211
|
return;
|
|
186
212
|
}
|
|
187
213
|
if (!filter(id) || !FILE_EXTENSION_REGEX.test(id)) {
|
|
188
|
-
return
|
|
214
|
+
return;
|
|
189
215
|
}
|
|
190
|
-
const
|
|
216
|
+
const isSsr = finalOptions.mode === "server" || (options2 == null ? void 0 : options2.ssr) === true;
|
|
217
|
+
const _a2 = finalOptions, { symbol, include, exclude } = _a2, babelPassOptions = __objRest(_a2, ["symbol", "include", "exclude"]);
|
|
218
|
+
const babelOptions = __spreadProps(__spreadValues({}, babelPassOptions), {
|
|
219
|
+
signalPrefix: (_c = (_b = finalOptions.signalPrefix) != null ? _b : symbol) != null ? _c : "$",
|
|
220
|
+
mode: isSsr ? "server" : finalOptions.mode,
|
|
221
|
+
hmr: !isSsr && !isProd && finalOptions.hmr
|
|
222
|
+
});
|
|
191
223
|
let result;
|
|
192
224
|
try {
|
|
193
225
|
result = babel.transformSync(code, {
|
|
@@ -203,23 +235,24 @@ var unpluginFactory = (options = {}, meta) => {
|
|
|
203
235
|
if (!(result == null ? void 0 : result.code)) {
|
|
204
236
|
return code;
|
|
205
237
|
}
|
|
206
|
-
let finalCode
|
|
238
|
+
let finalCode;
|
|
207
239
|
if (babelOptions.hmr) {
|
|
208
|
-
const
|
|
209
|
-
const
|
|
210
|
-
const
|
|
211
|
-
if (
|
|
212
|
-
finalCode =
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
240
|
+
const { code: strippedCode, disposeHandlers } = extractHMRDisposeHandlers(result.code);
|
|
241
|
+
const hasComponents = strippedCode.includes("__$createHMRComponent$__");
|
|
242
|
+
const hasRegistry = strippedCode.includes("__$registry$__");
|
|
243
|
+
if (!hasComponents && !hasRegistry && disposeHandlers.length === 0) {
|
|
244
|
+
finalCode = result.code;
|
|
245
|
+
} else {
|
|
246
|
+
const hmrCode = generateHMRCode(bundlerType, disposeHandlers);
|
|
247
|
+
const parts = [];
|
|
248
|
+
if (hasRegistry) parts.push(hmrCode.imports.hmrAccept);
|
|
249
|
+
if (hasComponents) parts.push(hmrCode.imports.createHMRComponent);
|
|
250
|
+
parts.push(strippedCode);
|
|
251
|
+
if (hasRegistry) parts.push(hmrCode.register);
|
|
252
|
+
finalCode = parts.join("\n");
|
|
220
253
|
}
|
|
221
254
|
} else {
|
|
222
|
-
finalCode
|
|
255
|
+
finalCode = result.code;
|
|
223
256
|
}
|
|
224
257
|
return {
|
|
225
258
|
code: finalCode,
|
|
@@ -232,5 +265,5 @@ var unplugin = /* @__PURE__ */ createUnplugin(unpluginFactory);
|
|
|
232
265
|
var index_default = unplugin;
|
|
233
266
|
|
|
234
267
|
export { __async, index_default, unplugin, unpluginFactory };
|
|
235
|
-
//# sourceMappingURL=chunk-
|
|
236
|
-
//# sourceMappingURL=chunk-
|
|
268
|
+
//# sourceMappingURL=chunk-REX4A3LQ.js.map
|
|
269
|
+
//# sourceMappingURL=chunk-REX4A3LQ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["raw-loader:/home/runner/work/essor/essor/packages/unplugin/src/hmr-runtime.js?raw","../src/index.ts"],"names":["_a","options"],"mappings":"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","file":"chunk-REX4A3LQ.js","sourcesContent":["/**\n * Essor HMR Runtime - Registry-based Hot Module Replacement\n *\n * This runtime enables precise component-level HMR updates without full page reloads:\n *\n * 1. **Registry Tracking**: Each component id points to its latest implementation\n * 2. **Signature Tracking**: Components are tracked by code signatures (from babel plugin)\n * 3. **Precise Updates**: Only components with changed signatures are updated\n * 4. **Instance Reloading**: Live component instances remount when their implementation changes\n * 5. **Bundler Agnostic**: Works with Vite, Webpack, Rspack, and other bundlers\n */\nimport { createComponent, onDestroy } from 'essor';\n\nconst isFunction = (value) => typeof value === 'function';\nconst ESSOR_HMR = 'essor-hmr';\n/**\n * Global component registry for HMR tracking\n *\n * Maps hmrId -> ComponentInfo where:\n * - hmrId: Unique identifier for component (fileHash:componentName)\n * - component: Current component function\n * - signature: Hash of component code (changes when code changes)\n * - instances: Set of active component instances\n * - updated: True after HMR applies a newer implementation\n */\nconst componentRegistry = new Map();\n\nfunction cleanupInstance(hmrId, info, component) {\n info.instances.delete(component);\n\n if (info.instances.size === 0 && !info.updated && componentRegistry.get(hmrId) === info) {\n componentRegistry.delete(hmrId);\n }\n}\n\n/**\n * Utility function to handle invalidate or reload\n * @param hot - Hot module API object\n */\nfunction invalidateOrReload(hot) {\n if (isFunction(hot?.invalidate)) {\n hot.invalidate();\n } else if (typeof location !== 'undefined') {\n location.reload();\n }\n}\n\n/**\n * Create HMR-enabled component wrapper\n *\n * This function wraps a component to enable HMR:\n * 1. Creates or retrieves component registry entry\n * 2. Creates the component from the latest registered implementation\n * 3. Tracks the instance until destroy()\n * 4. applyUpdate() remounts tracked instances when the implementation changes\n *\n * @param componentFn - Component function with __hmrId and __signature\n * @param props - Component props\n * @returns Component instance that responds to HMR updates\n */\nexport function createHMRComponent(componentFn, props) {\n const { __hmrId: hmrId, __signature: signature } = componentFn;\n\n if (!hmrId) {\n // If no hmrId, create normal component\n return createComponent(componentFn, props);\n }\n\n let info = componentRegistry.get(hmrId);\n\n if (!info) {\n info = {\n component: componentFn,\n signature,\n instances: new Set(),\n updated: false,\n };\n componentRegistry.set(hmrId, info);\n } else if (info.instances.size === 0 && !info.updated) {\n info.signature = signature;\n info.component = componentFn;\n }\n\n let component;\n let disposed = false;\n let isForceUpdating = false;\n const cleanupHMR = () => {\n if (isForceUpdating) return;\n if (disposed) return;\n disposed = true;\n cleanupInstance(hmrId, info, component);\n };\n\n // Use a stable boundary function so destroy cleanup is registered only\n // after the component is mounted inside a real Essor scope. This also lets\n // stale closures render the latest implementation after a hot update.\n function HMRBoundary(nextProps) {\n onDestroy(cleanupHMR);\n return info.component.call(this, nextProps);\n }\n\n component = createComponent(HMRBoundary, props);\n info.instances.add(component);\n\n const originalForceUpdate = component.forceUpdate;\n if (isFunction(originalForceUpdate)) {\n component.forceUpdate = function (...args) {\n isForceUpdating = true;\n try {\n return originalForceUpdate.apply(this, args);\n } finally {\n isForceUpdating = false;\n }\n };\n }\n\n // Integrate with component lifecycle - cleanup only when the component is\n // actually unmounted, not during forceUpdate's destroy/remount cycle.\n const originalDestroy = component.destroy;\n component.destroy = function (...args) {\n try {\n if (isFunction(originalDestroy)) {\n return originalDestroy.apply(this, args);\n }\n } finally {\n if (!isForceUpdating) {\n cleanupHMR();\n }\n }\n };\n\n return component;\n}\n\n/**\n * Determine if a component needs to be updated\n *\n * A component should update if:\n * 1. Function instance changed (indicates module was re-executed)\n * 2. Signature changed (indicates component code was modified)\n *\n * @param oldInfo - Existing component registry info\n * @param newComponentFn - New component function from updated module\n * @param newSignature - New signature hash from updated module\n * @returns true if component should update\n */\nfunction shouldUpdate(oldInfo, newComponentFn, newSignature) {\n if (!oldInfo) return true;\n\n // Check function instance (handles constant updates via module re-execution)\n if (oldInfo.component !== newComponentFn) {\n return true;\n }\n\n // Check compile-time signature (handles component code changes)\n return oldInfo.signature !== newSignature;\n}\n\n/**\n * Check if a value is an HMR-enabled component\n *\n * @param value - Value to check\n * @returns true if value is a function with __hmrId property\n */\nfunction isHMRComponent(value) {\n return value && isFunction(value) && value.__hmrId;\n}\n\nfunction emitHmrEvent(detail) {\n if (typeof CustomEvent !== 'undefined' && typeof dispatchEvent !== 'undefined') {\n dispatchEvent(new CustomEvent('essor:hmr-update', { detail }));\n }\n}\n\n/**\n * Apply HMR updates to components\n *\n * Iterates through the new component registry and force-updates live\n * component instances whose implementation changed.\n *\n * @param registry - Array of components from updated module\n * @returns true if reload needed (errors occurred), false otherwise\n */\nexport function applyUpdate(registry) {\n if (!Array.isArray(registry) || registry.length === 0) {\n return false;\n }\n\n let needsReload = false;\n const updatedIds = [];\n\n for (const entry of registry) {\n if (!isHMRComponent(entry)) {\n continue;\n }\n\n const { __hmrId: hmrId, __signature: signature } = entry;\n const info = componentRegistry.get(hmrId);\n\n if (!info) {\n componentRegistry.set(hmrId, {\n component: entry,\n signature,\n instances: new Set(),\n updated: true,\n });\n continue;\n }\n\n // Use shouldUpdate to determine if update is needed\n if (!shouldUpdate(info, entry, signature)) {\n continue;\n }\n\n info.signature = signature;\n info.component = entry;\n info.updated = true;\n updatedIds.push(hmrId);\n\n for (const component of [...info.instances]) {\n try {\n component.forceUpdate();\n } catch (error) {\n console.error(`[Essor HMR] Failed to update ${hmrId}:`, error);\n cleanupInstance(hmrId, info, component);\n needsReload = true;\n }\n }\n }\n\n if (updatedIds.length > 0) {\n emitHmrEvent({ updatedIds });\n }\n\n return needsReload;\n}\n\n/**\n * Setup HMR for Vite bundler\n *\n * Vite provides import.meta.hot.accept() callback that receives the new module\n */\nfunction setupViteHMR(hot, registry) {\n hot.data ??= {};\n const isUpdate = !!hot.data[ESSOR_HMR];\n hot.data[ESSOR_HMR] = registry;\n\n if (isUpdate) {\n if (applyUpdate(registry)) invalidateOrReload(hot);\n }\n}\n\n/**\n * Setup HMR for Webpack/Rspack bundlers\n *\n * Webpack-style HMR uses module.hot.accept() and hot.data for state persistence\n */\nfunction setupWebpackHMR(hot, registry) {\n if (isFunction(hot.accept)) {\n hot.accept();\n }\n\n if (hot.data?.[ESSOR_HMR]) {\n if (applyUpdate(registry)) invalidateOrReload(hot);\n }\n\n if (isFunction(hot.dispose)) {\n hot.dispose((data) => {\n data[ESSOR_HMR] = registry;\n });\n }\n}\n\n/**\n * Setup HMR for other bundlers (fallback)\n *\n * Attempts to work with any bundler that provides a basic hot module API\n */\nfunction setupStandardHMR(hot, registry) {\n // Try accept with a callback that receives the new module.\n if (isFunction(hot.accept)) {\n try {\n hot.accept((newModule) => {\n if (!newModule) {\n invalidateOrReload(hot);\n return;\n }\n const newRegistry = extractHMRComponents(newModule);\n if (newRegistry.length === 0) return;\n if (applyUpdate(newRegistry)) invalidateOrReload(hot);\n });\n } catch {\n // Some bundlers don't support accept with callback — fall back to simple accept.\n try {\n hot.accept();\n } catch (error_) {\n console.warn('[Essor HMR] Failed to setup hot.accept:', error_);\n }\n }\n }\n\n // Setup dispose handler for state persistence\n if (isFunction(hot.dispose)) {\n hot.dispose((data) => {\n data[ESSOR_HMR] = registry;\n });\n }\n\n // Apply update if previous data exists\n if (hot.data?.[ESSOR_HMR]) {\n if (applyUpdate(registry)) invalidateOrReload(hot);\n }\n}\n\n/**\n * Extract HMR components from a module\n *\n * Looks for __$registry$__ array first (generated by babel plugin),\n * then falls back to scanning all exports for HMR components\n *\n * @param module - Module object to scan\n * @returns Array of HMR component functions\n */\nfunction extractHMRComponents(module) {\n if (!module) return [];\n\n // Prefer __$registry$__\n if (Array.isArray(module.__$registry$__)) {\n return module.__$registry$__;\n }\n\n // Otherwise search in exports\n const components = [];\n for (const key of Object.keys(module)) {\n const value = module[key];\n if (isHMRComponent(value)) {\n components.push(value);\n }\n }\n return components;\n}\n\n/**\n * Main HMR entry point\n *\n * Called from transformed modules to set up HMR based on bundler type\n *\n * @param bundlerType - Type of bundler (vite, webpack5, rspack, etc.)\n * @param hot - Hot module API object (import.meta.hot or module.hot)\n * @param registry - Array of components from current module\n * @returns true if HMR setup succeeded, false otherwise\n */\nexport function hmrAccept(bundlerType, hot, registry) {\n if (!hot || !registry) {\n return false;\n }\n\n switch (bundlerType) {\n case 'vite':\n setupViteHMR(hot, registry);\n break;\n case 'webpack':\n case 'webpack5':\n case 'rspack':\n setupWebpackHMR(hot, registry);\n break;\n default:\n // Use standard HMR setup\n setupStandardHMR(hot, registry);\n break;\n }\n\n return true;\n}\n","import { createUnplugin } from 'unplugin';\nimport * as babel from '@babel/core';\nimport essorBabelPlugin from 'babel-plugin-essor';\nimport { createFilter } from 'vite';\n// @ts-ignore - resolved by esbuild raw plugin at build time\nimport hmrRuntimeCode from './hmr-runtime.js?raw';\nimport type { UnpluginContextMeta, UnpluginFactory } from 'unplugin';\nimport type { LegacyRenderMode, Options, RenderMode } from './types';\n\n/**\n * Virtual module ID for HMR runtime\n * Injected as an import in transformed files that have HMR components\n */\nconst VIRTUAL_MODULE_ID = 'virtual:essor-hmr';\nconst RESOLVED_VIRTUAL_MODULE_ID = '\\0virtual:essor-hmr';\n\n/**\n * Default plugin options\n */\nconst DEFAULT_OPTIONS = {\n symbol: '$' as const,\n mode: 'client' as RenderMode,\n props: true,\n hmr: true,\n enableFor: false,\n omitClosingTags: true,\n delegateEvents: true,\n};\n\n/**\n * Maps the deprecated `ssg` / `ssr` mode aliases onto the canonical render\n * modes understood by `babel-plugin-essor`:\n * - `ssg` → `server` (emit static HTML strings via `renderToString`)\n * - `ssr` → `hydrate` (emit hydration-ready client output)\n *\n * Retained only for backwards compatibility; the aliases will be removed in a\n * future major release (see {@link LegacyRenderMode}). Use the canonical\n * `client` | `server` | `hydrate` names instead.\n */\nconst LEGACY_MODE_ALIASES: Record<string, RenderMode> = {\n ssg: 'server',\n ssr: 'hydrate',\n};\n\n/**\n * Normalizes a user-supplied `mode` to a canonical {@link RenderMode}. Accepts\n * the canonical names verbatim and translates the deprecated `ssg` / `ssr`\n * aliases so the rest of the plugin and the Babel plugin only ever see\n * `client` | `server` | `hydrate`.\n */\nfunction normalizeMode(mode: RenderMode | LegacyRenderMode | undefined): RenderMode {\n if (mode) {\n return LEGACY_MODE_ALIASES[mode] || (mode as RenderMode);\n }\n return 'client';\n}\n\n/**\n * Performance: Pre-compiled regex and constants\n */\nconst FILE_EXTENSION_REGEX = /\\.[cm]?[jt]sx?$/i;\nconst SKIP_DIRECTORIES_REGEX = /[\\\\/](?:node_modules|dist|public)[\\\\/]/;\nconst HMR_DISPOSE_PREFIX = 'import.meta.hot?.dispose(';\nconst HMR_DISPOSE_SUFFIX = ');';\n\nconst HMR_IMPORTS = {\n createHMRComponent: `import { createHMRComponent as __$createHMRComponent$__ } from \"${VIRTUAL_MODULE_ID}\";`,\n hmrAccept: `import { hmrAccept as __$hmrAccept$__ } from \"${VIRTUAL_MODULE_ID}\";`,\n} as const;\n\ntype BundlerType = 'vite' | 'webpack5' | 'rspack' | 'rollup' | 'esbuild' | 'standard';\n\n/**\n * Detect bundler type from unplugin meta or environment variables\n *\n * This is important for HMR because different bundlers have different\n * HMR APIs (import.meta.hot.accept, module.hot.accept, etc.)\n */\nfunction detectBundler(meta: UnpluginContextMeta): BundlerType {\n // First, try to detect from unplugin meta\n if (meta?.framework) {\n switch (meta.framework) {\n case 'vite':\n return 'vite';\n case 'webpack':\n return 'webpack5';\n case 'rspack':\n return 'rspack';\n case 'rollup':\n return 'rollup';\n case 'esbuild':\n return 'esbuild';\n }\n }\n\n // Defensive fallback: unplugin always provides meta.framework, but in edge\n // cases (custom wrappers, test harnesses) these env vars act as a safety net.\n if (typeof process !== 'undefined' && process.env) {\n if (process.env.VITE || process.env.VITEST) return 'vite';\n if (process.env.WEBPACK_VERSION) return 'webpack5';\n if (process.env.RSPACK) return 'rspack';\n }\n\n return 'standard';\n}\n\n/**\n * Extract mount cleanup handlers emitted by the Babel HMR pass.\n *\n * @param code - Transformed module code.\n * @returns Module code without inline disposal calls and the extracted handlers.\n */\nfunction extractHMRDisposeHandlers(code: string) {\n if (!code.includes(HMR_DISPOSE_PREFIX)) {\n return { code, disposeHandlers: [] };\n }\n const lines = code.split('\\n');\n const disposeHandlers: string[] = [];\n const cleanedLines = lines.filter((line) => {\n const trimmed = line.trim();\n if (!trimmed.startsWith(HMR_DISPOSE_PREFIX) || !trimmed.endsWith(HMR_DISPOSE_SUFFIX)) {\n return true;\n }\n\n disposeHandlers.push(trimmed.slice(HMR_DISPOSE_PREFIX.length, -HMR_DISPOSE_SUFFIX.length));\n return false;\n });\n\n return {\n code: cleanedLines.join('\\n'),\n disposeHandlers,\n };\n}\n\n/**\n * Returns the correct hot-module-replacement global expression for a bundler.\n *\n * - Vite: `import.meta.hot`\n * - webpack / rspack: `import.meta.webpackHot` (webpack-compatible HMR protocol)\n * - others: `import.meta.hot` (no real HMR; guard is always falsy — safe)\n */\nfunction getHotExpression(bundlerType: BundlerType): string {\n if (bundlerType === 'webpack5' || bundlerType === 'rspack') {\n return 'import.meta.webpackHot';\n }\n return 'import.meta.hot';\n}\n\nfunction generateHMRCode(bundlerType: BundlerType, disposeHandlers: string[] = []) {\n const hot = getHotExpression(bundlerType);\n const disposeLines = disposeHandlers.map((handler) => ` ${hot}.dispose(${handler});`);\n\n // Build the HMR registration block. Vite needs an explicit `accept()` call;\n // webpack/rspack handle acceptance inside `__$hmrAccept$__`.\n const lines = [`if (${hot}) {`, ...disposeLines];\n if (bundlerType === 'vite') {\n lines.push(` ${hot}.accept();`);\n }\n lines.push(` __$hmrAccept$__(\"${bundlerType}\", ${hot}, __$registry$__);`, '}');\n\n return { imports: HMR_IMPORTS, register: lines.join('\\n') };\n}\n\nexport const unpluginFactory: UnpluginFactory<Options | undefined> = (\n options: Options = {},\n meta,\n) => {\n // Create file filter based on include/exclude patterns\n const filter = createFilter(options.include, options.exclude);\n\n // Detect bundler type for HMR\n const bundlerType = detectBundler(meta);\n\n // NODE_ENV is set by most bundlers; fallback treats unknown env as dev (HMR on)\n let isProd = process.env.NODE_ENV === 'production';\n\n // Merge user options with defaults (hmr excluded — computed dynamically in\n // transform). `mode` is normalized to a canonical RenderMode so the Babel\n // plugin only ever receives `client` | `server` | `hydrate`.\n const finalOptions = {\n ...DEFAULT_OPTIONS,\n ...options,\n mode: normalizeMode(options.mode ?? DEFAULT_OPTIONS.mode),\n bundler: bundlerType,\n };\n\n return {\n name: 'unplugin-essor',\n /**\n * Vite-specific config to preserve JSX so the babel plugin can handle it.\n\n */\n vite: {\n config(this: unknown) {\n // Inside a vite hook, `this` is the rollup plugin context. On Vite 8 /\n // rolldown-vite it exposes `meta.rolldownVersion`.\n const ctx = this as { meta?: Record<string, unknown> } | undefined;\n const isRolldownVite = !!ctx?.meta && 'rolldownVersion' in ctx.meta;\n const key = (isRolldownVite ? 'oxc' : 'esbuild') as 'esbuild';\n return {\n [key]: { jsx: 'preserve' },\n };\n },\n configResolved(config: { command: string }) {\n // Vite's command is more reliable than NODE_ENV for detecting dev vs build\n isProd = config.command === 'build';\n },\n },\n\n /**\n * Resolve virtual HMR runtime module\n */\n resolveId(id: string) {\n if (id === VIRTUAL_MODULE_ID) {\n return RESOLVED_VIRTUAL_MODULE_ID;\n }\n return null;\n },\n\n /**\n * Load virtual HMR runtime module\n */\n load(id: string) {\n if (id === RESOLVED_VIRTUAL_MODULE_ID) {\n return {\n code: hmrRuntimeCode,\n map: null,\n };\n }\n return null;\n },\n rolldown: {\n options(opts) {\n opts.transform ??= {\n jsx: 'preserve',\n };\n },\n },\n /**\n * Transform code with Babel plugin\n */\n transform(code, id, options?: { ssr?: boolean }) {\n // Skip node_modules, dist, public and non-JS/TS files\n if (SKIP_DIRECTORIES_REGEX.test(id) || !FILE_EXTENSION_REGEX.test(id) || !filter(id)) {\n return;\n }\n // Only transform JS/TS files\n if (!filter(id) || !FILE_EXTENSION_REGEX.test(id)) {\n return;\n }\n const isSsr = finalOptions.mode === 'server' || options?.ssr === true;\n\n // Extract unplugin-only options before passing to Babel\n const { symbol, include, exclude, ...babelPassOptions } = finalOptions;\n\n const babelOptions = {\n ...babelPassOptions,\n signalPrefix: finalOptions.signalPrefix ?? symbol ?? '$',\n mode: isSsr ? 'server' : finalOptions.mode,\n hmr: !isSsr && !isProd && finalOptions.hmr,\n };\n\n // Transform with Babel (with error handling)\n let result;\n try {\n result = babel.transformSync(code, {\n filename: id,\n sourceMaps: true,\n sourceType: 'module',\n plugins: [[essorBabelPlugin, babelOptions]],\n });\n } catch (error) {\n console.error(`[unplugin-essor] Transform failed for ${id}:`, error);\n return null;\n }\n\n if (!result?.code) {\n return code;\n }\n\n let finalCode: string;\n\n if (babelOptions.hmr) {\n const { code: strippedCode, disposeHandlers } = extractHMRDisposeHandlers(result.code);\n const hasComponents = strippedCode.includes('__$createHMRComponent$__');\n const hasRegistry = strippedCode.includes('__$registry$__');\n\n if (!hasComponents && !hasRegistry && disposeHandlers.length === 0) {\n finalCode = result.code;\n } else {\n const hmrCode = generateHMRCode(bundlerType, disposeHandlers);\n const parts: string[] = [];\n if (hasRegistry) parts.push(hmrCode.imports.hmrAccept);\n if (hasComponents) parts.push(hmrCode.imports.createHMRComponent);\n parts.push(strippedCode);\n if (hasRegistry) parts.push(hmrCode.register);\n\n finalCode = parts.join('\\n');\n }\n } else {\n finalCode = result.code;\n }\n\n return {\n code: finalCode,\n map: result.map,\n };\n },\n };\n};\n\nexport const unplugin = /* #__PURE__ */ createUnplugin(unpluginFactory);\n\nexport default unplugin;\n"]}
|
package/dist/esbuild.cjs
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkASRB37BB_cjs = require('./chunk-ASRB37BB.cjs');
|
|
4
4
|
var unplugin = require('unplugin');
|
|
5
5
|
|
|
6
|
-
var esbuild_default = unplugin.createEsbuildPlugin(
|
|
6
|
+
var esbuild_default = unplugin.createEsbuildPlugin(chunkASRB37BB_cjs.unpluginFactory);
|
|
7
7
|
|
|
8
8
|
module.exports = esbuild_default;
|
|
9
9
|
//# sourceMappingURL=esbuild.cjs.map
|
package/dist/esbuild.js
CHANGED
package/dist/farm.cjs
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkASRB37BB_cjs = require('./chunk-ASRB37BB.cjs');
|
|
4
4
|
var unplugin = require('unplugin');
|
|
5
5
|
|
|
6
|
-
var farm_default = unplugin.createFarmPlugin(
|
|
6
|
+
var farm_default = unplugin.createFarmPlugin(chunkASRB37BB_cjs.unpluginFactory);
|
|
7
7
|
|
|
8
8
|
module.exports = farm_default;
|
|
9
9
|
//# sourceMappingURL=farm.cjs.map
|
package/dist/farm.js
CHANGED
package/dist/index.cjs
CHANGED
|
@@ -2,21 +2,21 @@
|
|
|
2
2
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
|
-
var
|
|
5
|
+
var chunkASRB37BB_cjs = require('./chunk-ASRB37BB.cjs');
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
Object.defineProperty(exports, "default", {
|
|
10
10
|
enumerable: true,
|
|
11
|
-
get: function () { return
|
|
11
|
+
get: function () { return chunkASRB37BB_cjs.index_default; }
|
|
12
12
|
});
|
|
13
13
|
Object.defineProperty(exports, "unplugin", {
|
|
14
14
|
enumerable: true,
|
|
15
|
-
get: function () { return
|
|
15
|
+
get: function () { return chunkASRB37BB_cjs.unplugin; }
|
|
16
16
|
});
|
|
17
17
|
Object.defineProperty(exports, "unpluginFactory", {
|
|
18
18
|
enumerable: true,
|
|
19
|
-
get: function () { return
|
|
19
|
+
get: function () { return chunkASRB37BB_cjs.unpluginFactory; }
|
|
20
20
|
});
|
|
21
21
|
//# sourceMappingURL=index.cjs.map
|
|
22
22
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.js
CHANGED
package/dist/rolldown.cjs
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkASRB37BB_cjs = require('./chunk-ASRB37BB.cjs');
|
|
4
4
|
var unplugin = require('unplugin');
|
|
5
5
|
|
|
6
|
-
var rolldown_default = unplugin.createRolldownPlugin(
|
|
6
|
+
var rolldown_default = unplugin.createRolldownPlugin(chunkASRB37BB_cjs.unpluginFactory);
|
|
7
7
|
|
|
8
8
|
module.exports = rolldown_default;
|
|
9
9
|
//# sourceMappingURL=rolldown.cjs.map
|
package/dist/rolldown.js
CHANGED
package/dist/rollup.cjs
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkASRB37BB_cjs = require('./chunk-ASRB37BB.cjs');
|
|
4
4
|
var unplugin = require('unplugin');
|
|
5
5
|
|
|
6
|
-
var rollup_default = unplugin.createRollupPlugin(
|
|
6
|
+
var rollup_default = unplugin.createRollupPlugin(chunkASRB37BB_cjs.unpluginFactory);
|
|
7
7
|
|
|
8
8
|
module.exports = rollup_default;
|
|
9
9
|
//# sourceMappingURL=rollup.cjs.map
|
package/dist/rollup.js
CHANGED
package/dist/rspack.cjs
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkASRB37BB_cjs = require('./chunk-ASRB37BB.cjs');
|
|
4
4
|
var unplugin = require('unplugin');
|
|
5
5
|
|
|
6
|
-
var rspack_default = unplugin.createRspackPlugin(
|
|
6
|
+
var rspack_default = unplugin.createRspackPlugin(chunkASRB37BB_cjs.unpluginFactory);
|
|
7
7
|
|
|
8
8
|
module.exports = rspack_default;
|
|
9
9
|
//# sourceMappingURL=rspack.cjs.map
|
package/dist/rspack.js
CHANGED
package/dist/types.d.cts
CHANGED
|
@@ -1,13 +1,70 @@
|
|
|
1
1
|
import { FilterPattern } from 'vite';
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Canonical render modes, kept in sync with `babel-plugin-essor`'s
|
|
5
|
+
* `RENDER_MODE` enum (`client` | `server` | `hydrate`).
|
|
6
|
+
*/
|
|
7
|
+
type RenderMode = 'client' | 'server' | 'hydrate';
|
|
8
|
+
/**
|
|
9
|
+
* Legacy render-mode aliases retained for backwards compatibility.
|
|
10
|
+
*
|
|
11
|
+
* @deprecated Use the canonical {@link RenderMode} names instead — `ssg` maps
|
|
12
|
+
* to `server` and `ssr` maps to `hydrate`. These aliases will be removed in a future major.
|
|
13
|
+
*/
|
|
14
|
+
type LegacyRenderMode = 'ssg' | 'ssr';
|
|
3
15
|
interface Options {
|
|
16
|
+
/**
|
|
17
|
+
* Minimatch patterns to include for transformation.
|
|
18
|
+
*/
|
|
4
19
|
include?: FilterPattern;
|
|
20
|
+
/**
|
|
21
|
+
* Minimatch patterns to exclude from transformation.
|
|
22
|
+
*/
|
|
5
23
|
exclude?: FilterPattern;
|
|
6
|
-
|
|
24
|
+
/**
|
|
25
|
+
* Render target used by the compiler. Accepts the canonical
|
|
26
|
+
* {@link RenderMode} names (`client` | `server` | `hydrate`).
|
|
27
|
+
*
|
|
28
|
+
* The legacy `ssg` / `ssr` aliases are still accepted but deprecated; `ssg`
|
|
29
|
+
* resolves to `server` and `ssr` resolves to `hydrate`.
|
|
30
|
+
*/
|
|
31
|
+
mode?: RenderMode | LegacyRenderMode;
|
|
32
|
+
/**
|
|
33
|
+
* Whether to transform component props preprocessing.
|
|
34
|
+
* @default true
|
|
35
|
+
*/
|
|
7
36
|
props?: boolean;
|
|
37
|
+
/**
|
|
38
|
+
* Prefix symbol used to identify reactive variables.
|
|
39
|
+
* @deprecated Use `signalPrefix` instead.
|
|
40
|
+
* @default '$'
|
|
41
|
+
*/
|
|
8
42
|
symbol?: '$';
|
|
43
|
+
/**
|
|
44
|
+
* Custom signal prefix identifier (e.g. '$').
|
|
45
|
+
* @default '$'
|
|
46
|
+
*/
|
|
47
|
+
signalPrefix?: string;
|
|
48
|
+
/**
|
|
49
|
+
* Whether to enable hot module replacement.
|
|
50
|
+
* @default true
|
|
51
|
+
*/
|
|
9
52
|
hmr?: boolean;
|
|
53
|
+
/**
|
|
54
|
+
* Whether to omit closing tags from native DOM templates using Solid's omitLastClosingTag behavior.
|
|
55
|
+
* @default true
|
|
56
|
+
*/
|
|
10
57
|
omitClosingTags?: boolean;
|
|
58
|
+
/**
|
|
59
|
+
* Whether to enable legacy For compiler optimization.
|
|
60
|
+
* @default false
|
|
61
|
+
*/
|
|
62
|
+
enableFor?: boolean;
|
|
63
|
+
/**
|
|
64
|
+
* Forces event delegation on or off globally.
|
|
65
|
+
* @default true
|
|
66
|
+
*/
|
|
67
|
+
delegateEvents?: boolean;
|
|
11
68
|
}
|
|
12
69
|
|
|
13
|
-
export type { Options };
|
|
70
|
+
export type { LegacyRenderMode, Options, RenderMode };
|
package/dist/types.d.ts
CHANGED
|
@@ -1,13 +1,70 @@
|
|
|
1
1
|
import { FilterPattern } from 'vite';
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Canonical render modes, kept in sync with `babel-plugin-essor`'s
|
|
5
|
+
* `RENDER_MODE` enum (`client` | `server` | `hydrate`).
|
|
6
|
+
*/
|
|
7
|
+
type RenderMode = 'client' | 'server' | 'hydrate';
|
|
8
|
+
/**
|
|
9
|
+
* Legacy render-mode aliases retained for backwards compatibility.
|
|
10
|
+
*
|
|
11
|
+
* @deprecated Use the canonical {@link RenderMode} names instead — `ssg` maps
|
|
12
|
+
* to `server` and `ssr` maps to `hydrate`. These aliases will be removed in a future major.
|
|
13
|
+
*/
|
|
14
|
+
type LegacyRenderMode = 'ssg' | 'ssr';
|
|
3
15
|
interface Options {
|
|
16
|
+
/**
|
|
17
|
+
* Minimatch patterns to include for transformation.
|
|
18
|
+
*/
|
|
4
19
|
include?: FilterPattern;
|
|
20
|
+
/**
|
|
21
|
+
* Minimatch patterns to exclude from transformation.
|
|
22
|
+
*/
|
|
5
23
|
exclude?: FilterPattern;
|
|
6
|
-
|
|
24
|
+
/**
|
|
25
|
+
* Render target used by the compiler. Accepts the canonical
|
|
26
|
+
* {@link RenderMode} names (`client` | `server` | `hydrate`).
|
|
27
|
+
*
|
|
28
|
+
* The legacy `ssg` / `ssr` aliases are still accepted but deprecated; `ssg`
|
|
29
|
+
* resolves to `server` and `ssr` resolves to `hydrate`.
|
|
30
|
+
*/
|
|
31
|
+
mode?: RenderMode | LegacyRenderMode;
|
|
32
|
+
/**
|
|
33
|
+
* Whether to transform component props preprocessing.
|
|
34
|
+
* @default true
|
|
35
|
+
*/
|
|
7
36
|
props?: boolean;
|
|
37
|
+
/**
|
|
38
|
+
* Prefix symbol used to identify reactive variables.
|
|
39
|
+
* @deprecated Use `signalPrefix` instead.
|
|
40
|
+
* @default '$'
|
|
41
|
+
*/
|
|
8
42
|
symbol?: '$';
|
|
43
|
+
/**
|
|
44
|
+
* Custom signal prefix identifier (e.g. '$').
|
|
45
|
+
* @default '$'
|
|
46
|
+
*/
|
|
47
|
+
signalPrefix?: string;
|
|
48
|
+
/**
|
|
49
|
+
* Whether to enable hot module replacement.
|
|
50
|
+
* @default true
|
|
51
|
+
*/
|
|
9
52
|
hmr?: boolean;
|
|
53
|
+
/**
|
|
54
|
+
* Whether to omit closing tags from native DOM templates using Solid's omitLastClosingTag behavior.
|
|
55
|
+
* @default true
|
|
56
|
+
*/
|
|
10
57
|
omitClosingTags?: boolean;
|
|
58
|
+
/**
|
|
59
|
+
* Whether to enable legacy For compiler optimization.
|
|
60
|
+
* @default false
|
|
61
|
+
*/
|
|
62
|
+
enableFor?: boolean;
|
|
63
|
+
/**
|
|
64
|
+
* Forces event delegation on or off globally.
|
|
65
|
+
* @default true
|
|
66
|
+
*/
|
|
67
|
+
delegateEvents?: boolean;
|
|
11
68
|
}
|
|
12
69
|
|
|
13
|
-
export type { Options };
|
|
70
|
+
export type { LegacyRenderMode, Options, RenderMode };
|
package/dist/vite.cjs
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkASRB37BB_cjs = require('./chunk-ASRB37BB.cjs');
|
|
4
4
|
var unplugin = require('unplugin');
|
|
5
5
|
|
|
6
|
-
var vite_default = unplugin.createVitePlugin(
|
|
6
|
+
var vite_default = unplugin.createVitePlugin(chunkASRB37BB_cjs.unpluginFactory);
|
|
7
7
|
|
|
8
8
|
module.exports = vite_default;
|
|
9
9
|
//# sourceMappingURL=vite.cjs.map
|
package/dist/vite.js
CHANGED
package/dist/webpack.cjs
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkASRB37BB_cjs = require('./chunk-ASRB37BB.cjs');
|
|
4
4
|
var unplugin = require('unplugin');
|
|
5
5
|
|
|
6
|
-
var webpack_default = unplugin.createWebpackPlugin(
|
|
6
|
+
var webpack_default = unplugin.createWebpackPlugin(chunkASRB37BB_cjs.unpluginFactory);
|
|
7
7
|
|
|
8
8
|
module.exports = webpack_default;
|
|
9
9
|
//# sourceMappingURL=webpack.cjs.map
|
package/dist/webpack.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "unplugin-essor",
|
|
3
|
-
"version": "0.0.17
|
|
3
|
+
"version": "0.0.17",
|
|
4
4
|
"description": "",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"keywords": [
|
|
@@ -113,19 +113,23 @@
|
|
|
113
113
|
}
|
|
114
114
|
},
|
|
115
115
|
"dependencies": {
|
|
116
|
-
"@babel/core": "^
|
|
117
|
-
"unplugin": "2.
|
|
118
|
-
"
|
|
116
|
+
"@babel/core": "^8.0.1",
|
|
117
|
+
"unplugin": "^3.2.0",
|
|
118
|
+
"@estjs/shared": "0.0.17",
|
|
119
|
+
"babel-plugin-essor": "0.0.17"
|
|
119
120
|
},
|
|
120
121
|
"devDependencies": {
|
|
121
|
-
"@rspack/cli": "^2.0.
|
|
122
|
-
"@rspack/core": "^2.0.
|
|
123
|
-
"@types/node": "^
|
|
124
|
-
"rollup": "^4.
|
|
122
|
+
"@rspack/cli": "^2.0.8",
|
|
123
|
+
"@rspack/core": "^2.0.8",
|
|
124
|
+
"@types/node": "^26.0.0",
|
|
125
|
+
"rollup": "^4.62.2",
|
|
125
126
|
"tsup": "^8.5.1",
|
|
126
127
|
"typescript": "^6.0.3",
|
|
127
|
-
"vite": "^8.0.
|
|
128
|
-
"essor": "0.0.17
|
|
128
|
+
"vite": "^8.0.16",
|
|
129
|
+
"essor": "0.0.17"
|
|
130
|
+
},
|
|
131
|
+
"engines": {
|
|
132
|
+
"node": "^22.18.0 || >=24.11.0"
|
|
129
133
|
},
|
|
130
134
|
"scripts": {
|
|
131
135
|
"build": "tsup",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["raw-loader:/home/runner/work/essor/essor/packages/unplugin/src/hmr-runtime.js?raw","../src/index.ts"],"names":[],"mappings":"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","file":"chunk-KWEBR2TV.js","sourcesContent":["/**\n * Essor HMR Runtime - Registry-based Hot Module Replacement\n *\n * This runtime enables precise component-level HMR updates without full page reloads:\n *\n * 1. **Registry Tracking**: Each component id points to its latest implementation\n * 2. **Signature Tracking**: Components are tracked by code signatures (from babel plugin)\n * 3. **Precise Updates**: Only components with changed signatures are updated\n * 4. **Instance Reloading**: Live component instances remount when their implementation changes\n * 5. **Bundler Agnostic**: Works with Vite, Webpack, Rspack, and other bundlers\n */\nimport { createComponent, onDestroy } from 'essor';\n\nconst isFunction = (value) => typeof value === 'function';\nconst ESSOR_HMR = 'essor-hmr';\n/**\n * Global component registry for HMR tracking\n *\n * Maps hmrId -> ComponentInfo where:\n * - hmrId: Unique identifier for component (fileHash:componentName)\n * - component: Current component function\n * - signature: Hash of component code (changes when code changes)\n * - instances: Set of active component instances\n * - updated: True after HMR applies a newer implementation\n */\nconst componentRegistry = new Map();\n\nfunction cleanupInstance(hmrId, info, component) {\n info.instances.delete(component);\n\n if (info.instances.size === 0 && !info.updated && componentRegistry.get(hmrId) === info) {\n componentRegistry.delete(hmrId);\n }\n}\n\n/**\n * Utility function to handle invalidate or reload\n * @param hot - Hot module API object\n */\nfunction invalidateOrReload(hot) {\n if (isFunction(hot?.invalidate)) {\n hot.invalidate();\n } else if (typeof location !== 'undefined') {\n location.reload();\n }\n}\n\n/**\n * Create HMR-enabled component wrapper\n *\n * This function wraps a component to enable HMR:\n * 1. Creates or retrieves component registry entry\n * 2. Creates the component from the latest registered implementation\n * 3. Tracks the instance until destroy()\n * 4. applyUpdate() remounts tracked instances when the implementation changes\n *\n * @param componentFn - Component function with __hmrId and __signature\n * @param props - Component props\n * @returns Component instance that responds to HMR updates\n */\nexport function createHMRComponent(componentFn, props) {\n const { __hmrId: hmrId, __signature: signature } = componentFn;\n\n if (!hmrId) {\n // If no hmrId, create normal component\n return createComponent(componentFn, props);\n }\n\n let info = componentRegistry.get(hmrId);\n\n if (!info) {\n info = {\n component: componentFn,\n signature,\n instances: new Set(),\n updated: false,\n };\n componentRegistry.set(hmrId, info);\n } else if (info.instances.size === 0 && !info.updated) {\n info.signature = signature;\n info.component = componentFn;\n }\n\n let component;\n let disposed = false;\n let isForceUpdating = false;\n const cleanupHMR = () => {\n if (isForceUpdating) return;\n if (disposed) return;\n disposed = true;\n cleanupInstance(hmrId, info, component);\n };\n\n // Use a stable boundary function so destroy cleanup is registered only\n // after the component is mounted inside a real Essor scope. This also lets\n // stale closures render the latest implementation after a hot update.\n function HMRBoundary(nextProps) {\n onDestroy(cleanupHMR);\n return info.component.call(this, nextProps);\n }\n\n component = createComponent(HMRBoundary, props);\n info.instances.add(component);\n\n const originalForceUpdate = component.forceUpdate;\n if (isFunction(originalForceUpdate)) {\n component.forceUpdate = function (...args) {\n isForceUpdating = true;\n try {\n return originalForceUpdate.apply(this, args);\n } finally {\n isForceUpdating = false;\n }\n };\n }\n\n // Integrate with component lifecycle - cleanup only when the component is\n // actually unmounted, not during forceUpdate's destroy/remount cycle.\n const originalDestroy = component.destroy;\n component.destroy = function (...args) {\n try {\n if (isFunction(originalDestroy)) {\n return originalDestroy.apply(this, args);\n }\n } finally {\n if (!isForceUpdating) {\n cleanupHMR();\n }\n }\n };\n\n return component;\n}\n\n/**\n * Determine if a component needs to be updated\n *\n * A component should update if:\n * 1. Function instance changed (indicates module was re-executed)\n * 2. Signature changed (indicates component code was modified)\n *\n * @param oldInfo - Existing component registry info\n * @param newComponentFn - New component function from updated module\n * @param newSignature - New signature hash from updated module\n * @returns true if component should update\n */\nfunction shouldUpdate(oldInfo, newComponentFn, newSignature) {\n if (!oldInfo) return true;\n\n // Check function instance (handles constant updates via module re-execution)\n if (oldInfo.component !== newComponentFn) {\n return true;\n }\n\n // Check compile-time signature (handles component code changes)\n return oldInfo.signature !== newSignature;\n}\n\n/**\n * Check if a value is an HMR-enabled component\n *\n * @param value - Value to check\n * @returns true if value is a function with __hmrId property\n */\nfunction isHMRComponent(value) {\n return value && isFunction(value) && value.__hmrId;\n}\n\n/**\n * Apply HMR updates to components\n *\n * Iterates through the new component registry and force-updates live\n * component instances whose implementation changed.\n *\n * @param registry - Array of components from updated module\n * @returns true if reload needed (errors occurred), false otherwise\n */\nexport function applyUpdate(registry) {\n if (!Array.isArray(registry) || registry.length === 0) {\n return false;\n }\n\n let needsReload = false;\n\n for (const entry of registry) {\n if (!isHMRComponent(entry)) {\n continue;\n }\n\n const { __hmrId: hmrId, __signature: signature } = entry;\n const id = hmrId;\n const info = componentRegistry.get(hmrId);\n\n if (!info) {\n componentRegistry.set(hmrId, {\n component: entry,\n signature,\n instances: new Set(),\n updated: true,\n });\n continue;\n }\n\n // Use shouldUpdate to determine if update is needed\n if (!shouldUpdate(info, entry, signature)) {\n continue;\n }\n\n info.signature = signature;\n info.component = entry;\n info.updated = true;\n\n for (const component of [...info.instances]) {\n try {\n component.forceUpdate();\n } catch (error) {\n console.error(`[Essor HMR] Failed to update ${id}:`, error);\n cleanupInstance(hmrId, info, component);\n needsReload = true;\n }\n }\n }\n\n return needsReload;\n}\n\n/**\n * Common handler for HMR updates across bundlers\n * @param hot - Hot module API\n * @param newModule - Updated module\n * @returns true if handled successfully\n */\nfunction handleHMRUpdate(hot, newModule) {\n if (!newModule) {\n invalidateOrReload(hot);\n return false;\n }\n\n // Extract HMR components from new module\n const newRegistry = extractHMRComponents(newModule);\n if (newRegistry.length === 0) {\n return true;\n }\n\n const needsReload = applyUpdate(newRegistry);\n if (needsReload) {\n invalidateOrReload(hot);\n }\n return true;\n}\n\n/**\n * Setup HMR for Vite bundler\n *\n * Vite provides import.meta.hot.accept() callback that receives the new module\n */\nfunction setupViteHMR(hot, registry) {\n hot.data ??= {};\n const isUpdate = !!hot.data[ESSOR_HMR];\n hot.data[ESSOR_HMR] = registry;\n\n if (isUpdate) {\n const needsReload = applyUpdate(registry);\n if (needsReload) {\n invalidateOrReload(hot);\n }\n }\n}\n\n/**\n * Setup HMR for Webpack/Rspack bundlers\n *\n * Webpack-style HMR uses module.hot.accept() and hot.data for state persistence\n */\nfunction setupWebpackHMR(hot, registry) {\n if (isFunction(hot.accept)) {\n hot.accept();\n }\n\n // Apply update if previous data exists from last hot reload\n if (hot.data?.[ESSOR_HMR]) {\n const needsReload = applyUpdate(registry);\n if (needsReload) {\n invalidateOrReload(hot);\n }\n }\n\n // Save current registry for next update\n if (isFunction(hot.dispose)) {\n hot.dispose((data) => {\n data[ESSOR_HMR] = registry;\n });\n }\n}\n\n/**\n * Setup HMR for other bundlers (fallback)\n *\n * Attempts to work with any bundler that provides a basic hot module API\n */\nfunction setupStandardHMR(hot, registry) {\n // Try accept callback mode first (more efficient)\n if (isFunction(hot.accept)) {\n try {\n hot.accept((newModule) => handleHMRUpdate(hot, newModule));\n } catch {\n // Some bundlers don't support accept with callback\n // Fall back to simple accept (for Webpack-style pattern)\n try {\n hot.accept();\n } catch (error_) {\n console.warn('[Essor HMR] Failed to setup hot.accept:', error_);\n }\n }\n }\n\n // Setup dispose handler for state persistence\n if (isFunction(hot.dispose)) {\n hot.dispose((data) => {\n data.__$registry$__ = registry;\n data.__essor_timestamp__ = Date.now();\n });\n }\n\n // Apply update if previous data exists (for Webpack-style HMR)\n if (hot.data?.__$registry$__) {\n const needsReload = applyUpdate(registry);\n if (needsReload) {\n invalidateOrReload(hot);\n }\n }\n}\n\n/**\n * Extract HMR components from a module\n *\n * Looks for __$registry$__ array first (generated by babel plugin),\n * then falls back to scanning all exports for HMR components\n *\n * @param module - Module object to scan\n * @returns Array of HMR component functions\n */\nfunction extractHMRComponents(module) {\n if (!module) return [];\n\n // Prefer __$registry$__\n if (Array.isArray(module.__$registry$__)) {\n return module.__$registry$__;\n }\n\n // Otherwise search in exports\n const components = [];\n for (const key of Object.keys(module)) {\n const value = module[key];\n if (isHMRComponent(value)) {\n components.push(value);\n }\n }\n return components;\n}\n\n/**\n * Main HMR entry point\n *\n * Called from transformed modules to set up HMR based on bundler type\n *\n * @param bundlerType - Type of bundler (vite, webpack5, rspack, etc.)\n * @param hot - Hot module API object (import.meta.hot or module.hot)\n * @param registry - Array of components from current module\n * @returns true if HMR setup succeeded, false otherwise\n */\nexport function hmrAccept(bundlerType, hot, registry) {\n if (!hot || !registry) {\n return false;\n }\n\n switch (bundlerType) {\n case 'vite':\n setupViteHMR(hot, registry);\n break;\n case 'webpack':\n case 'webpack5':\n case 'rspack':\n setupWebpackHMR(hot, registry);\n break;\n default:\n // Use standard HMR setup\n setupStandardHMR(hot, registry);\n break;\n }\n\n return true;\n}\n\n/**\n * Cleanup all instances of a component (utility function)\n *\n * @param hmrId - Component HMR ID\n * @returns Number of instances cleaned up\n */\nexport function unregisterAllInstances(hmrId) {\n const info = componentRegistry.get(hmrId);\n if (!info) return 0;\n\n let count = 0;\n for (const item of [...info.instances]) {\n try {\n cleanupInstance(hmrId, info, item);\n } catch (error) {\n console.error(`[Essor HMR] Failed to unregister component instance:`, error);\n }\n count++;\n }\n\n return count;\n}\n\n/**\n * Get registry information for debugging\n *\n * @returns Object mapping hmrId to component info (signature, instance count)\n */\nexport function getRegistryInfo() {\n const info = {};\n for (const [id, data] of componentRegistry) {\n info[id] = {\n signature: data.signature,\n instanceCount: data.instances.size,\n };\n }\n return info;\n}\n","import { createUnplugin } from 'unplugin';\nimport * as babel from '@babel/core';\nimport essorBabelPlugin from 'babel-plugin-essor';\nimport { createFilter } from 'vite';\n// @ts-ignore - resolved by esbuild raw plugin at build time\nimport hmrRuntimeCode from './hmr-runtime.js?raw';\nimport type { UnpluginContextMeta, UnpluginFactory } from 'unplugin';\nimport type { Options } from './types';\n\n/**\n * Virtual module ID for HMR runtime\n * Injected as an import in transformed files that have HMR components\n */\nconst VIRTUAL_MODULE_ID = 'virtual:essor-hmr';\nconst RESOLVED_VIRTUAL_MODULE_ID = '\\0virtual:essor-hmr';\n\n/**\n * Default plugin options\n */\nconst DEFAULT_OPTIONS = {\n symbol: '$',\n mode: 'client',\n props: true,\n hmr: true,\n enableFor: false,\n omitClosingTags: true,\n};\n\n/**\n * Performance: Pre-compiled regex and constants\n */\nconst FILE_EXTENSION_REGEX = /\\.[cm]?[jt]sx?$/i;\nconst SKIP_DIRECTORIES = ['node_modules', 'dist', 'public'];\nconst HMR_DISPOSE_PREFIX = 'import.meta.hot?.dispose(';\nconst HMR_DISPOSE_SUFFIX = ');';\n\ntype BundlerType = 'vite' | 'webpack5' | 'rspack' | 'rollup' | 'esbuild' | 'standard';\n\n/**\n * Detect bundler type from unplugin meta or environment variables\n *\n * This is important for HMR because different bundlers have different\n * HMR APIs (import.meta.hot.accept, module.hot.accept, etc.)\n */\nfunction detectBundler(meta: UnpluginContextMeta): BundlerType {\n // First, try to detect from unplugin meta\n if (meta?.framework) {\n switch (meta.framework) {\n case 'vite':\n return 'vite';\n case 'webpack':\n return 'webpack5';\n case 'rspack':\n return 'rspack';\n case 'rollup':\n return 'rollup';\n case 'esbuild':\n return 'esbuild';\n }\n }\n\n // Fallback: detect from environment variables\n if (typeof process !== 'undefined' && process.env) {\n if (process.env.VITE || process.env.VITEST) return 'vite';\n if (process.env.WEBPACK_VERSION) return 'webpack5';\n if (process.env.RSPACK) return 'rspack';\n }\n\n // Default to standard if detection fails\n return 'standard';\n}\n\n/**\n * Extract mount cleanup handlers emitted by the Babel HMR pass.\n *\n * @param code - Transformed module code.\n * @returns Module code without inline disposal calls and the extracted handlers.\n */\nfunction extractHMRDisposeHandlers(code: string) {\n const lines = code.split('\\n');\n const disposeHandlers: string[] = [];\n const cleanedLines = lines.filter((line) => {\n const trimmed = line.trim();\n if (!trimmed.startsWith(HMR_DISPOSE_PREFIX) || !trimmed.endsWith(HMR_DISPOSE_SUFFIX)) {\n return true;\n }\n\n disposeHandlers.push(trimmed.slice(HMR_DISPOSE_PREFIX.length, -HMR_DISPOSE_SUFFIX.length));\n return false;\n });\n\n return {\n code: cleanedLines.join('\\n'),\n disposeHandlers,\n };\n}\n\nfunction generateHMRCode(bundlerType: BundlerType, disposeHandlers: string[] = []) {\n // Import HMR utilities from virtual module\n const imports = {\n createHMRComponent: `import { createHMRComponent as __$createHMRComponent$__ } from \"${VIRTUAL_MODULE_ID}\";`,\n hmrAccept: `import { hmrAccept as __$hmrAccept$__ } from \"${VIRTUAL_MODULE_ID}\";`,\n };\n const disposeLines = disposeHandlers.map((handler) => ` import.meta.hot.dispose(${handler});`);\n\n const register =\n bundlerType === 'vite'\n ? [\n 'if (import.meta.hot) {',\n ...disposeLines,\n ' import.meta.hot.accept();',\n ' __$hmrAccept$__(\"vite\", import.meta.hot, __$registry$__);',\n '}',\n ].join('\\n')\n : [\n 'if (import.meta.hot) {',\n ...disposeLines,\n ` __$hmrAccept$__(\"${bundlerType}\", import.meta.hot, __$registry$__);`,\n '}',\n ].join('\\n');\n\n return {\n imports,\n register,\n };\n}\n\nexport const unpluginFactory: UnpluginFactory<Options | undefined> = (\n options: Options = {},\n meta,\n) => {\n // Create file filter based on include/exclude patterns\n const filter = createFilter(options.include, options.exclude);\n\n // Detect bundler type for HMR\n const bundlerType = detectBundler(meta);\n\n // NODE_ENV is set by most bundlers; fallback treats unknown env as dev (HMR on)\n let isProd = process.env.NODE_ENV === 'production';\n\n // Merge user options with defaults (hmr excluded — computed dynamically in transform)\n const finalOptions = {\n ...DEFAULT_OPTIONS,\n ...options,\n bundler: bundlerType,\n };\n\n return {\n name: 'unplugin-essor',\n /**\n * Vite-specific config to preserve JSX so the babel plugin can handle it.\n \n */\n vite: {\n config(this: unknown) {\n // Inside a vite hook, `this` is the rollup plugin context. On Vite 8 /\n // rolldown-vite it exposes `meta.rolldownVersion`.\n const ctx = this as { meta?: Record<string, unknown> } | undefined;\n const isRolldownVite = !!ctx?.meta && 'rolldownVersion' in ctx.meta;\n const key = (isRolldownVite ? 'oxc' : 'esbuild') as 'esbuild';\n return {\n [key]: { jsx: 'preserve' },\n };\n },\n configResolved(config: { command: string }) {\n // Vite's command is more reliable than NODE_ENV for detecting dev vs build\n isProd = config.command === 'build';\n },\n },\n\n /**\n * Resolve virtual HMR runtime module\n */\n resolveId(id: string) {\n if (id === VIRTUAL_MODULE_ID) {\n return RESOLVED_VIRTUAL_MODULE_ID;\n }\n return null;\n },\n\n /**\n * Load virtual HMR runtime module\n */\n load(id: string) {\n if (id === RESOLVED_VIRTUAL_MODULE_ID) {\n return {\n code: hmrRuntimeCode,\n map: null,\n };\n }\n return null;\n },\n rolldown: {\n options(opts) {\n opts.transform ??= {\n jsx: 'preserve',\n };\n },\n },\n /**\n * Transform code with Babel plugin\n */\n transform(code, id) {\n // Skip node_modules, dist, and public directories\n if (SKIP_DIRECTORIES.some((p) => id.includes(p))) {\n return;\n }\n\n // Only transform JS/TS files\n if (!filter(id) || !FILE_EXTENSION_REGEX.test(id)) {\n return null;\n }\n\n // options.hmr explicit value wins; otherwise enable only in dev\n const babelOptions = { ...finalOptions, hmr: !isProd && finalOptions.hmr };\n\n // Transform with Babel (with error handling)\n let result;\n try {\n result = babel.transformSync(code, {\n filename: id,\n sourceMaps: true,\n sourceType: 'module',\n plugins: [[essorBabelPlugin, babelOptions]],\n });\n } catch (error) {\n console.error(`[unplugin-essor] Transform failed for ${id}:`, error);\n return null;\n }\n\n if (!result?.code) {\n return code;\n }\n\n let finalCode = '';\n\n // Inject HMR code if enabled and components are present\n if (babelOptions.hmr) {\n const hmrResult = extractHMRDisposeHandlers(result.code);\n const hmrCode = generateHMRCode(bundlerType, hmrResult.disposeHandlers);\n const transformedCode = hmrResult.code;\n\n if (transformedCode.includes('__$createHMRComponent$__')) {\n finalCode = `${hmrCode.imports.createHMRComponent}\\n${finalCode}`;\n }\n finalCode += transformedCode;\n if (transformedCode.includes('__$registry$__')) {\n finalCode = `${hmrCode.imports.hmrAccept}\\n${finalCode}\\n${hmrCode.register}`;\n }\n } else {\n finalCode += result.code;\n }\n\n return {\n code: finalCode,\n map: result.map,\n };\n },\n };\n};\n\nexport const unplugin = /* #__PURE__ */ createUnplugin(unpluginFactory);\n\nexport default unplugin;\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["raw-loader:/home/runner/work/essor/essor/packages/unplugin/src/hmr-runtime.js?raw","../src/index.ts"],"names":["createFilter","babel","essorBabelPlugin"],"mappings":"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","file":"chunk-KXK55FFZ.cjs","sourcesContent":["/**\n * Essor HMR Runtime - Registry-based Hot Module Replacement\n *\n * This runtime enables precise component-level HMR updates without full page reloads:\n *\n * 1. **Registry Tracking**: Each component id points to its latest implementation\n * 2. **Signature Tracking**: Components are tracked by code signatures (from babel plugin)\n * 3. **Precise Updates**: Only components with changed signatures are updated\n * 4. **Instance Reloading**: Live component instances remount when their implementation changes\n * 5. **Bundler Agnostic**: Works with Vite, Webpack, Rspack, and other bundlers\n */\nimport { createComponent, onDestroy } from 'essor';\n\nconst isFunction = (value) => typeof value === 'function';\nconst ESSOR_HMR = 'essor-hmr';\n/**\n * Global component registry for HMR tracking\n *\n * Maps hmrId -> ComponentInfo where:\n * - hmrId: Unique identifier for component (fileHash:componentName)\n * - component: Current component function\n * - signature: Hash of component code (changes when code changes)\n * - instances: Set of active component instances\n * - updated: True after HMR applies a newer implementation\n */\nconst componentRegistry = new Map();\n\nfunction cleanupInstance(hmrId, info, component) {\n info.instances.delete(component);\n\n if (info.instances.size === 0 && !info.updated && componentRegistry.get(hmrId) === info) {\n componentRegistry.delete(hmrId);\n }\n}\n\n/**\n * Utility function to handle invalidate or reload\n * @param hot - Hot module API object\n */\nfunction invalidateOrReload(hot) {\n if (isFunction(hot?.invalidate)) {\n hot.invalidate();\n } else if (typeof location !== 'undefined') {\n location.reload();\n }\n}\n\n/**\n * Create HMR-enabled component wrapper\n *\n * This function wraps a component to enable HMR:\n * 1. Creates or retrieves component registry entry\n * 2. Creates the component from the latest registered implementation\n * 3. Tracks the instance until destroy()\n * 4. applyUpdate() remounts tracked instances when the implementation changes\n *\n * @param componentFn - Component function with __hmrId and __signature\n * @param props - Component props\n * @returns Component instance that responds to HMR updates\n */\nexport function createHMRComponent(componentFn, props) {\n const { __hmrId: hmrId, __signature: signature } = componentFn;\n\n if (!hmrId) {\n // If no hmrId, create normal component\n return createComponent(componentFn, props);\n }\n\n let info = componentRegistry.get(hmrId);\n\n if (!info) {\n info = {\n component: componentFn,\n signature,\n instances: new Set(),\n updated: false,\n };\n componentRegistry.set(hmrId, info);\n } else if (info.instances.size === 0 && !info.updated) {\n info.signature = signature;\n info.component = componentFn;\n }\n\n let component;\n let disposed = false;\n let isForceUpdating = false;\n const cleanupHMR = () => {\n if (isForceUpdating) return;\n if (disposed) return;\n disposed = true;\n cleanupInstance(hmrId, info, component);\n };\n\n // Use a stable boundary function so destroy cleanup is registered only\n // after the component is mounted inside a real Essor scope. This also lets\n // stale closures render the latest implementation after a hot update.\n function HMRBoundary(nextProps) {\n onDestroy(cleanupHMR);\n return info.component.call(this, nextProps);\n }\n\n component = createComponent(HMRBoundary, props);\n info.instances.add(component);\n\n const originalForceUpdate = component.forceUpdate;\n if (isFunction(originalForceUpdate)) {\n component.forceUpdate = function (...args) {\n isForceUpdating = true;\n try {\n return originalForceUpdate.apply(this, args);\n } finally {\n isForceUpdating = false;\n }\n };\n }\n\n // Integrate with component lifecycle - cleanup only when the component is\n // actually unmounted, not during forceUpdate's destroy/remount cycle.\n const originalDestroy = component.destroy;\n component.destroy = function (...args) {\n try {\n if (isFunction(originalDestroy)) {\n return originalDestroy.apply(this, args);\n }\n } finally {\n if (!isForceUpdating) {\n cleanupHMR();\n }\n }\n };\n\n return component;\n}\n\n/**\n * Determine if a component needs to be updated\n *\n * A component should update if:\n * 1. Function instance changed (indicates module was re-executed)\n * 2. Signature changed (indicates component code was modified)\n *\n * @param oldInfo - Existing component registry info\n * @param newComponentFn - New component function from updated module\n * @param newSignature - New signature hash from updated module\n * @returns true if component should update\n */\nfunction shouldUpdate(oldInfo, newComponentFn, newSignature) {\n if (!oldInfo) return true;\n\n // Check function instance (handles constant updates via module re-execution)\n if (oldInfo.component !== newComponentFn) {\n return true;\n }\n\n // Check compile-time signature (handles component code changes)\n return oldInfo.signature !== newSignature;\n}\n\n/**\n * Check if a value is an HMR-enabled component\n *\n * @param value - Value to check\n * @returns true if value is a function with __hmrId property\n */\nfunction isHMRComponent(value) {\n return value && isFunction(value) && value.__hmrId;\n}\n\n/**\n * Apply HMR updates to components\n *\n * Iterates through the new component registry and force-updates live\n * component instances whose implementation changed.\n *\n * @param registry - Array of components from updated module\n * @returns true if reload needed (errors occurred), false otherwise\n */\nexport function applyUpdate(registry) {\n if (!Array.isArray(registry) || registry.length === 0) {\n return false;\n }\n\n let needsReload = false;\n\n for (const entry of registry) {\n if (!isHMRComponent(entry)) {\n continue;\n }\n\n const { __hmrId: hmrId, __signature: signature } = entry;\n const id = hmrId;\n const info = componentRegistry.get(hmrId);\n\n if (!info) {\n componentRegistry.set(hmrId, {\n component: entry,\n signature,\n instances: new Set(),\n updated: true,\n });\n continue;\n }\n\n // Use shouldUpdate to determine if update is needed\n if (!shouldUpdate(info, entry, signature)) {\n continue;\n }\n\n info.signature = signature;\n info.component = entry;\n info.updated = true;\n\n for (const component of [...info.instances]) {\n try {\n component.forceUpdate();\n } catch (error) {\n console.error(`[Essor HMR] Failed to update ${id}:`, error);\n cleanupInstance(hmrId, info, component);\n needsReload = true;\n }\n }\n }\n\n return needsReload;\n}\n\n/**\n * Common handler for HMR updates across bundlers\n * @param hot - Hot module API\n * @param newModule - Updated module\n * @returns true if handled successfully\n */\nfunction handleHMRUpdate(hot, newModule) {\n if (!newModule) {\n invalidateOrReload(hot);\n return false;\n }\n\n // Extract HMR components from new module\n const newRegistry = extractHMRComponents(newModule);\n if (newRegistry.length === 0) {\n return true;\n }\n\n const needsReload = applyUpdate(newRegistry);\n if (needsReload) {\n invalidateOrReload(hot);\n }\n return true;\n}\n\n/**\n * Setup HMR for Vite bundler\n *\n * Vite provides import.meta.hot.accept() callback that receives the new module\n */\nfunction setupViteHMR(hot, registry) {\n hot.data ??= {};\n const isUpdate = !!hot.data[ESSOR_HMR];\n hot.data[ESSOR_HMR] = registry;\n\n if (isUpdate) {\n const needsReload = applyUpdate(registry);\n if (needsReload) {\n invalidateOrReload(hot);\n }\n }\n}\n\n/**\n * Setup HMR for Webpack/Rspack bundlers\n *\n * Webpack-style HMR uses module.hot.accept() and hot.data for state persistence\n */\nfunction setupWebpackHMR(hot, registry) {\n if (isFunction(hot.accept)) {\n hot.accept();\n }\n\n // Apply update if previous data exists from last hot reload\n if (hot.data?.[ESSOR_HMR]) {\n const needsReload = applyUpdate(registry);\n if (needsReload) {\n invalidateOrReload(hot);\n }\n }\n\n // Save current registry for next update\n if (isFunction(hot.dispose)) {\n hot.dispose((data) => {\n data[ESSOR_HMR] = registry;\n });\n }\n}\n\n/**\n * Setup HMR for other bundlers (fallback)\n *\n * Attempts to work with any bundler that provides a basic hot module API\n */\nfunction setupStandardHMR(hot, registry) {\n // Try accept callback mode first (more efficient)\n if (isFunction(hot.accept)) {\n try {\n hot.accept((newModule) => handleHMRUpdate(hot, newModule));\n } catch {\n // Some bundlers don't support accept with callback\n // Fall back to simple accept (for Webpack-style pattern)\n try {\n hot.accept();\n } catch (error_) {\n console.warn('[Essor HMR] Failed to setup hot.accept:', error_);\n }\n }\n }\n\n // Setup dispose handler for state persistence\n if (isFunction(hot.dispose)) {\n hot.dispose((data) => {\n data.__$registry$__ = registry;\n data.__essor_timestamp__ = Date.now();\n });\n }\n\n // Apply update if previous data exists (for Webpack-style HMR)\n if (hot.data?.__$registry$__) {\n const needsReload = applyUpdate(registry);\n if (needsReload) {\n invalidateOrReload(hot);\n }\n }\n}\n\n/**\n * Extract HMR components from a module\n *\n * Looks for __$registry$__ array first (generated by babel plugin),\n * then falls back to scanning all exports for HMR components\n *\n * @param module - Module object to scan\n * @returns Array of HMR component functions\n */\nfunction extractHMRComponents(module) {\n if (!module) return [];\n\n // Prefer __$registry$__\n if (Array.isArray(module.__$registry$__)) {\n return module.__$registry$__;\n }\n\n // Otherwise search in exports\n const components = [];\n for (const key of Object.keys(module)) {\n const value = module[key];\n if (isHMRComponent(value)) {\n components.push(value);\n }\n }\n return components;\n}\n\n/**\n * Main HMR entry point\n *\n * Called from transformed modules to set up HMR based on bundler type\n *\n * @param bundlerType - Type of bundler (vite, webpack5, rspack, etc.)\n * @param hot - Hot module API object (import.meta.hot or module.hot)\n * @param registry - Array of components from current module\n * @returns true if HMR setup succeeded, false otherwise\n */\nexport function hmrAccept(bundlerType, hot, registry) {\n if (!hot || !registry) {\n return false;\n }\n\n switch (bundlerType) {\n case 'vite':\n setupViteHMR(hot, registry);\n break;\n case 'webpack':\n case 'webpack5':\n case 'rspack':\n setupWebpackHMR(hot, registry);\n break;\n default:\n // Use standard HMR setup\n setupStandardHMR(hot, registry);\n break;\n }\n\n return true;\n}\n\n/**\n * Cleanup all instances of a component (utility function)\n *\n * @param hmrId - Component HMR ID\n * @returns Number of instances cleaned up\n */\nexport function unregisterAllInstances(hmrId) {\n const info = componentRegistry.get(hmrId);\n if (!info) return 0;\n\n let count = 0;\n for (const item of [...info.instances]) {\n try {\n cleanupInstance(hmrId, info, item);\n } catch (error) {\n console.error(`[Essor HMR] Failed to unregister component instance:`, error);\n }\n count++;\n }\n\n return count;\n}\n\n/**\n * Get registry information for debugging\n *\n * @returns Object mapping hmrId to component info (signature, instance count)\n */\nexport function getRegistryInfo() {\n const info = {};\n for (const [id, data] of componentRegistry) {\n info[id] = {\n signature: data.signature,\n instanceCount: data.instances.size,\n };\n }\n return info;\n}\n","import { createUnplugin } from 'unplugin';\nimport * as babel from '@babel/core';\nimport essorBabelPlugin from 'babel-plugin-essor';\nimport { createFilter } from 'vite';\n// @ts-ignore - resolved by esbuild raw plugin at build time\nimport hmrRuntimeCode from './hmr-runtime.js?raw';\nimport type { UnpluginContextMeta, UnpluginFactory } from 'unplugin';\nimport type { Options } from './types';\n\n/**\n * Virtual module ID for HMR runtime\n * Injected as an import in transformed files that have HMR components\n */\nconst VIRTUAL_MODULE_ID = 'virtual:essor-hmr';\nconst RESOLVED_VIRTUAL_MODULE_ID = '\\0virtual:essor-hmr';\n\n/**\n * Default plugin options\n */\nconst DEFAULT_OPTIONS = {\n symbol: '$',\n mode: 'client',\n props: true,\n hmr: true,\n enableFor: false,\n omitClosingTags: true,\n};\n\n/**\n * Performance: Pre-compiled regex and constants\n */\nconst FILE_EXTENSION_REGEX = /\\.[cm]?[jt]sx?$/i;\nconst SKIP_DIRECTORIES = ['node_modules', 'dist', 'public'];\nconst HMR_DISPOSE_PREFIX = 'import.meta.hot?.dispose(';\nconst HMR_DISPOSE_SUFFIX = ');';\n\ntype BundlerType = 'vite' | 'webpack5' | 'rspack' | 'rollup' | 'esbuild' | 'standard';\n\n/**\n * Detect bundler type from unplugin meta or environment variables\n *\n * This is important for HMR because different bundlers have different\n * HMR APIs (import.meta.hot.accept, module.hot.accept, etc.)\n */\nfunction detectBundler(meta: UnpluginContextMeta): BundlerType {\n // First, try to detect from unplugin meta\n if (meta?.framework) {\n switch (meta.framework) {\n case 'vite':\n return 'vite';\n case 'webpack':\n return 'webpack5';\n case 'rspack':\n return 'rspack';\n case 'rollup':\n return 'rollup';\n case 'esbuild':\n return 'esbuild';\n }\n }\n\n // Fallback: detect from environment variables\n if (typeof process !== 'undefined' && process.env) {\n if (process.env.VITE || process.env.VITEST) return 'vite';\n if (process.env.WEBPACK_VERSION) return 'webpack5';\n if (process.env.RSPACK) return 'rspack';\n }\n\n // Default to standard if detection fails\n return 'standard';\n}\n\n/**\n * Extract mount cleanup handlers emitted by the Babel HMR pass.\n *\n * @param code - Transformed module code.\n * @returns Module code without inline disposal calls and the extracted handlers.\n */\nfunction extractHMRDisposeHandlers(code: string) {\n const lines = code.split('\\n');\n const disposeHandlers: string[] = [];\n const cleanedLines = lines.filter((line) => {\n const trimmed = line.trim();\n if (!trimmed.startsWith(HMR_DISPOSE_PREFIX) || !trimmed.endsWith(HMR_DISPOSE_SUFFIX)) {\n return true;\n }\n\n disposeHandlers.push(trimmed.slice(HMR_DISPOSE_PREFIX.length, -HMR_DISPOSE_SUFFIX.length));\n return false;\n });\n\n return {\n code: cleanedLines.join('\\n'),\n disposeHandlers,\n };\n}\n\nfunction generateHMRCode(bundlerType: BundlerType, disposeHandlers: string[] = []) {\n // Import HMR utilities from virtual module\n const imports = {\n createHMRComponent: `import { createHMRComponent as __$createHMRComponent$__ } from \"${VIRTUAL_MODULE_ID}\";`,\n hmrAccept: `import { hmrAccept as __$hmrAccept$__ } from \"${VIRTUAL_MODULE_ID}\";`,\n };\n const disposeLines = disposeHandlers.map((handler) => ` import.meta.hot.dispose(${handler});`);\n\n const register =\n bundlerType === 'vite'\n ? [\n 'if (import.meta.hot) {',\n ...disposeLines,\n ' import.meta.hot.accept();',\n ' __$hmrAccept$__(\"vite\", import.meta.hot, __$registry$__);',\n '}',\n ].join('\\n')\n : [\n 'if (import.meta.hot) {',\n ...disposeLines,\n ` __$hmrAccept$__(\"${bundlerType}\", import.meta.hot, __$registry$__);`,\n '}',\n ].join('\\n');\n\n return {\n imports,\n register,\n };\n}\n\nexport const unpluginFactory: UnpluginFactory<Options | undefined> = (\n options: Options = {},\n meta,\n) => {\n // Create file filter based on include/exclude patterns\n const filter = createFilter(options.include, options.exclude);\n\n // Detect bundler type for HMR\n const bundlerType = detectBundler(meta);\n\n // NODE_ENV is set by most bundlers; fallback treats unknown env as dev (HMR on)\n let isProd = process.env.NODE_ENV === 'production';\n\n // Merge user options with defaults (hmr excluded — computed dynamically in transform)\n const finalOptions = {\n ...DEFAULT_OPTIONS,\n ...options,\n bundler: bundlerType,\n };\n\n return {\n name: 'unplugin-essor',\n /**\n * Vite-specific config to preserve JSX so the babel plugin can handle it.\n \n */\n vite: {\n config(this: unknown) {\n // Inside a vite hook, `this` is the rollup plugin context. On Vite 8 /\n // rolldown-vite it exposes `meta.rolldownVersion`.\n const ctx = this as { meta?: Record<string, unknown> } | undefined;\n const isRolldownVite = !!ctx?.meta && 'rolldownVersion' in ctx.meta;\n const key = (isRolldownVite ? 'oxc' : 'esbuild') as 'esbuild';\n return {\n [key]: { jsx: 'preserve' },\n };\n },\n configResolved(config: { command: string }) {\n // Vite's command is more reliable than NODE_ENV for detecting dev vs build\n isProd = config.command === 'build';\n },\n },\n\n /**\n * Resolve virtual HMR runtime module\n */\n resolveId(id: string) {\n if (id === VIRTUAL_MODULE_ID) {\n return RESOLVED_VIRTUAL_MODULE_ID;\n }\n return null;\n },\n\n /**\n * Load virtual HMR runtime module\n */\n load(id: string) {\n if (id === RESOLVED_VIRTUAL_MODULE_ID) {\n return {\n code: hmrRuntimeCode,\n map: null,\n };\n }\n return null;\n },\n rolldown: {\n options(opts) {\n opts.transform ??= {\n jsx: 'preserve',\n };\n },\n },\n /**\n * Transform code with Babel plugin\n */\n transform(code, id) {\n // Skip node_modules, dist, and public directories\n if (SKIP_DIRECTORIES.some((p) => id.includes(p))) {\n return;\n }\n\n // Only transform JS/TS files\n if (!filter(id) || !FILE_EXTENSION_REGEX.test(id)) {\n return null;\n }\n\n // options.hmr explicit value wins; otherwise enable only in dev\n const babelOptions = { ...finalOptions, hmr: !isProd && finalOptions.hmr };\n\n // Transform with Babel (with error handling)\n let result;\n try {\n result = babel.transformSync(code, {\n filename: id,\n sourceMaps: true,\n sourceType: 'module',\n plugins: [[essorBabelPlugin, babelOptions]],\n });\n } catch (error) {\n console.error(`[unplugin-essor] Transform failed for ${id}:`, error);\n return null;\n }\n\n if (!result?.code) {\n return code;\n }\n\n let finalCode = '';\n\n // Inject HMR code if enabled and components are present\n if (babelOptions.hmr) {\n const hmrResult = extractHMRDisposeHandlers(result.code);\n const hmrCode = generateHMRCode(bundlerType, hmrResult.disposeHandlers);\n const transformedCode = hmrResult.code;\n\n if (transformedCode.includes('__$createHMRComponent$__')) {\n finalCode = `${hmrCode.imports.createHMRComponent}\\n${finalCode}`;\n }\n finalCode += transformedCode;\n if (transformedCode.includes('__$registry$__')) {\n finalCode = `${hmrCode.imports.hmrAccept}\\n${finalCode}\\n${hmrCode.register}`;\n }\n } else {\n finalCode += result.code;\n }\n\n return {\n code: finalCode,\n map: result.map,\n };\n },\n };\n};\n\nexport const unplugin = /* #__PURE__ */ createUnplugin(unpluginFactory);\n\nexport default unplugin;\n"]}
|