unplugin-essor 0.0.15-beta.9 → 0.0.16-beta.1

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.
Files changed (51) hide show
  1. package/dist/astro.cjs +7 -7
  2. package/dist/astro.cjs.map +1 -1
  3. package/dist/astro.js +6 -8
  4. package/dist/astro.js.map +1 -1
  5. package/dist/chunk-A5FJKKLT.cjs +237 -0
  6. package/dist/chunk-A5FJKKLT.cjs.map +1 -0
  7. package/dist/chunk-RU3ODIHJ.js +209 -0
  8. package/dist/chunk-RU3ODIHJ.js.map +1 -0
  9. package/dist/esbuild.cjs +6 -7
  10. package/dist/esbuild.cjs.map +1 -1
  11. package/dist/esbuild.js +5 -8
  12. package/dist/esbuild.js.map +1 -1
  13. package/dist/farm.cjs +6 -7
  14. package/dist/farm.cjs.map +1 -1
  15. package/dist/farm.js +5 -8
  16. package/dist/farm.js.map +1 -1
  17. package/dist/index.cjs +16 -5
  18. package/dist/index.cjs.map +1 -1
  19. package/dist/index.js +2 -10
  20. package/dist/index.js.map +1 -1
  21. package/dist/rolldown.cjs +6 -7
  22. package/dist/rolldown.cjs.map +1 -1
  23. package/dist/rolldown.js +5 -8
  24. package/dist/rolldown.js.map +1 -1
  25. package/dist/rollup.cjs +6 -7
  26. package/dist/rollup.cjs.map +1 -1
  27. package/dist/rollup.js +5 -8
  28. package/dist/rollup.js.map +1 -1
  29. package/dist/rspack.cjs +6 -7
  30. package/dist/rspack.cjs.map +1 -1
  31. package/dist/rspack.d.cts +2 -1
  32. package/dist/rspack.d.ts +2 -1
  33. package/dist/rspack.js +5 -8
  34. package/dist/rspack.js.map +1 -1
  35. package/dist/types.cjs +4 -1
  36. package/dist/types.cjs.map +1 -1
  37. package/dist/types.js +2 -0
  38. package/dist/types.js.map +1 -1
  39. package/dist/vite.cjs +6 -7
  40. package/dist/vite.cjs.map +1 -1
  41. package/dist/vite.js +5 -8
  42. package/dist/vite.js.map +1 -1
  43. package/dist/webpack.cjs +6 -7
  44. package/dist/webpack.cjs.map +1 -1
  45. package/dist/webpack.js +5 -8
  46. package/dist/webpack.js.map +1 -1
  47. package/package.json +10 -9
  48. package/dist/chunk-KCKAO6VH.js +0 -126
  49. package/dist/chunk-KCKAO6VH.js.map +0 -1
  50. package/dist/chunk-KK7POSQ3.cjs +0 -126
  51. package/dist/chunk-KK7POSQ3.cjs.map +0 -1
package/dist/astro.cjs CHANGED
@@ -1,22 +1,22 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true});
1
+ 'use strict';
2
2
 
3
- var _chunkKK7POSQ3cjs = require('./chunk-KK7POSQ3.cjs');
3
+ var chunkA5FJKKLT_cjs = require('./chunk-A5FJKKLT.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": async (astro) => {
10
+ "astro:config:setup": (astro) => chunkA5FJKKLT_cjs.__async(null, null, function* () {
11
11
  var _a;
12
12
  (_a = astro.config.vite).plugins || (_a.plugins = []);
13
- astro.config.vite.plugins.push(_chunkKK7POSQ3cjs.index_default.vite(options));
14
- }
13
+ astro.config.vite.plugins.push(chunkA5FJKKLT_cjs.index_default.vite(options));
14
+ })
15
15
  }
16
16
  });
17
17
 
18
-
19
- exports.default = astro_default;
18
+ module.exports = astro_default;
19
+ //# sourceMappingURL=astro.cjs.map
20
20
 
21
21
  module.exports = exports.default;
22
22
  //# sourceMappingURL=astro.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["/home/runner/work/essor/essor/packages/unplugin/dist/astro.cjs","../src/astro.ts"],"names":[],"mappings":"AAAA;AACE;AACF,wDAAA;AACA;AACA;ACDA,IAAO,cAAA,EAAQ,CAAC,OAAA,EAAA,GAAA,CAA2B;AAAA,EACzC,IAAA,EAAM,kBAAA;AAAA,EACN,KAAA,EAAO;AAAA;AAAA,IAEL,oBAAA,EAAsB,MAAA,CAAO,KAAA,EAAA,GAAe;AAPhD,MAAA,IAAA,EAAA;AAQM,MAAA,CAAA,GAAA,EAAA,KAAA,CAAM,MAAA,CAAO,IAAA,CAAA,CAAK,QAAA,GAAA,CAAlB,EAAA,CAAkB,QAAA,EAAY,CAAC,CAAA,CAAA;AAC/B,MAAA,KAAA,CAAM,MAAA,CAAO,IAAA,CAAK,OAAA,CAAQ,IAAA,CAAK,+BAAA,CAAS,IAAA,CAAK,OAAO,CAAC,CAAA;AAAA,IACvD;AAAA,EACF;AACF,CAAA,CAAA;ADIA;AACE;AACF,gCAAA","file":"/home/runner/work/essor/essor/packages/unplugin/dist/astro.cjs","sourcesContent":[null,"import unplugin from '.';\nimport type { Options } from './types';\n\nexport default (options: Options): any => ({\n name: 'unplugin-starter',\n hooks: {\n // eslint-disable-next-line require-await\n 'astro:config:setup': async (astro: any) => {\n astro.config.vite.plugins ||= [];\n astro.config.vite.plugins.push(unplugin.vite(options));\n },\n },\n});\n"]}
1
+ {"version":3,"sources":["../src/astro.ts"],"names":["__async","index_default"],"mappings":";;;;;AAGA,IAAO,aAAA,GAAQ,CAAC,OAAA,MAA2B;AAAA,EACzC,IAAA,EAAM,kBAAA;AAAA,EACN,KAAA,EAAO;AAAA;AAAA,IAEL,oBAAA,EAAsB,CAAO,KAAA,KAAeA,yBAAA,CAAA,IAAA,EAAA,IAAA,EAAA,aAAA;AAPhD,MAAA,IAAA,EAAA;AAQM,MAAA,CAAA,EAAA,GAAA,KAAA,CAAM,MAAA,CAAO,IAAA,EAAK,OAAA,KAAlB,EAAA,CAAkB,UAAY,EAAC,CAAA;AAC/B,MAAA,KAAA,CAAM,OAAO,IAAA,CAAK,OAAA,CAAQ,KAAKC,+BAAA,CAAS,IAAA,CAAK,OAAO,CAAC,CAAA;AAAA,IACvD,CAAA;AAAA;AAEJ,CAAA","file":"astro.cjs","sourcesContent":["import unplugin from '.';\nimport type { Options } from './types';\n\nexport default (options: Options): any => ({\n name: 'unplugin-starter',\n hooks: {\n // eslint-disable-next-line require-await\n 'astro:config:setup': async (astro: any) => {\n astro.config.vite.plugins ||= [];\n astro.config.vite.plugins.push(unplugin.vite(options));\n },\n },\n});\n"]}
package/dist/astro.js CHANGED
@@ -1,20 +1,18 @@
1
- import {
2
- index_default
3
- } from "./chunk-KCKAO6VH.js";
1
+ import { __async, index_default } from './chunk-RU3ODIHJ.js';
4
2
 
5
3
  // src/astro.ts
6
4
  var astro_default = (options) => ({
7
5
  name: "unplugin-starter",
8
6
  hooks: {
9
7
  // eslint-disable-next-line require-await
10
- "astro:config:setup": async (astro) => {
8
+ "astro:config:setup": (astro) => __async(null, null, function* () {
11
9
  var _a;
12
10
  (_a = astro.config.vite).plugins || (_a.plugins = []);
13
11
  astro.config.vite.plugins.push(index_default.vite(options));
14
- }
12
+ })
15
13
  }
16
14
  });
17
- export {
18
- astro_default as default
19
- };
15
+
16
+ export { astro_default as default };
17
+ //# sourceMappingURL=astro.js.map
20
18
  //# sourceMappingURL=astro.js.map
package/dist/astro.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/astro.ts"],"sourcesContent":["import unplugin from '.';\nimport type { Options } from './types';\n\nexport default (options: Options): any => ({\n name: 'unplugin-starter',\n hooks: {\n // eslint-disable-next-line require-await\n 'astro:config:setup': async (astro: any) => {\n astro.config.vite.plugins ||= [];\n astro.config.vite.plugins.push(unplugin.vite(options));\n },\n },\n});\n"],"mappings":";;;;;AAGA,IAAO,gBAAQ,CAAC,aAA2B;AAAA,EACzC,MAAM;AAAA,EACN,OAAO;AAAA;AAAA,IAEL,sBAAsB,OAAO,UAAe;AAPhD;AAQM,kBAAM,OAAO,MAAK,YAAlB,GAAkB,UAAY,CAAC;AAC/B,YAAM,OAAO,KAAK,QAAQ,KAAK,cAAS,KAAK,OAAO,CAAC;AAAA,IACvD;AAAA,EACF;AACF;","names":[]}
1
+ {"version":3,"sources":["../src/astro.ts"],"names":[],"mappings":";;;AAGA,IAAO,aAAA,GAAQ,CAAC,OAAA,MAA2B;AAAA,EACzC,IAAA,EAAM,kBAAA;AAAA,EACN,KAAA,EAAO;AAAA;AAAA,IAEL,oBAAA,EAAsB,CAAO,KAAA,KAAe,OAAA,CAAA,IAAA,EAAA,IAAA,EAAA,aAAA;AAPhD,MAAA,IAAA,EAAA;AAQM,MAAA,CAAA,EAAA,GAAA,KAAA,CAAM,MAAA,CAAO,IAAA,EAAK,OAAA,KAAlB,EAAA,CAAkB,UAAY,EAAC,CAAA;AAC/B,MAAA,KAAA,CAAM,OAAO,IAAA,CAAK,OAAA,CAAQ,KAAK,aAAA,CAAS,IAAA,CAAK,OAAO,CAAC,CAAA;AAAA,IACvD,CAAA;AAAA;AAEJ,CAAA","file":"astro.js","sourcesContent":["import unplugin from '.';\nimport type { Options } from './types';\n\nexport default (options: Options): any => ({\n name: 'unplugin-starter',\n hooks: {\n // eslint-disable-next-line require-await\n 'astro:config:setup': async (astro: any) => {\n astro.config.vite.plugins ||= [];\n astro.config.vite.plugins.push(unplugin.vite(options));\n },\n },\n});\n"]}
@@ -0,0 +1,237 @@
1
+ 'use strict';
2
+
3
+ var unplugin$1 = require('unplugin');
4
+ var babel = require('@babel/core');
5
+ var essorBabelPlugin = require('babel-plugin-essor');
6
+ var vite = require('vite');
7
+
8
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
9
+
10
+ function _interopNamespace(e) {
11
+ if (e && e.__esModule) return e;
12
+ var n = Object.create(null);
13
+ if (e) {
14
+ Object.keys(e).forEach(function (k) {
15
+ if (k !== 'default') {
16
+ var d = Object.getOwnPropertyDescriptor(e, k);
17
+ Object.defineProperty(n, k, d.get ? d : {
18
+ enumerable: true,
19
+ get: function () { return e[k]; }
20
+ });
21
+ }
22
+ });
23
+ }
24
+ n.default = e;
25
+ return Object.freeze(n);
26
+ }
27
+
28
+ var babel__namespace = /*#__PURE__*/_interopNamespace(babel);
29
+ var essorBabelPlugin__default = /*#__PURE__*/_interopDefault(essorBabelPlugin);
30
+
31
+ var __defProp = Object.defineProperty;
32
+ var __defProps = Object.defineProperties;
33
+ var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
34
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
35
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
36
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
37
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
38
+ var __spreadValues = (a, b) => {
39
+ for (var prop in b || (b = {}))
40
+ if (__hasOwnProp.call(b, prop))
41
+ __defNormalProp(a, prop, b[prop]);
42
+ if (__getOwnPropSymbols)
43
+ for (var prop of __getOwnPropSymbols(b)) {
44
+ if (__propIsEnum.call(b, prop))
45
+ __defNormalProp(a, prop, b[prop]);
46
+ }
47
+ return a;
48
+ };
49
+ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
50
+ var __async = (__this, __arguments, generator) => {
51
+ return new Promise((resolve, reject) => {
52
+ var fulfilled = (value) => {
53
+ try {
54
+ step(generator.next(value));
55
+ } catch (e) {
56
+ reject(e);
57
+ }
58
+ };
59
+ var rejected = (value) => {
60
+ try {
61
+ step(generator.throw(value));
62
+ } catch (e) {
63
+ reject(e);
64
+ }
65
+ };
66
+ var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
67
+ step((generator = generator.apply(__this, __arguments)).next());
68
+ });
69
+ };
70
+
71
+ // raw-loader:/home/runner/work/essor/essor/packages/unplugin/src/hmr-runtime.js?raw
72
+ var hmr_runtime_default = "/**\n * Essor HMR Runtime - Signal-based Hot Module Replacement\n *\n * This runtime enables precise component-level HMR updates without full page reloads:\n *\n * 1. **Signal Wrapping**: Each component is wrapped in a reactive signal\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. **Effect Subscription**: Component instances subscribe to signal changes via effects\n * 5. **Bundler Agnostic**: Works with Vite, Webpack, Rspack, and other bundlers\n */\nimport { createComponent, effect, signal } from 'essor';\n\nconst isFunction = (value) => typeof value === 'function';\n/**\n * Global component registry for HMR tracking\n *\n * Maps hmrId -> ComponentInfo where:\n * - hmrId: Unique identifier for component (fileHash:componentName)\n * - componentSignal: Reactive signal holding the current component function\n * - signature: Hash of component code (changes when code changes)\n * - instances: Set of active component instances\n * - cleanups: Map of cleanup functions for each instance's effect\n */\nconst componentRegistry = new Map();\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. Wraps component function to always read from latest signal value\n * 3. Sets up reactive effect to auto-update component when signal changes\n * 4. Returns regular component instance that auto-updates on HMR\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 // First registration: create signal wrapped component\n info = {\n componentSignal: signal(componentFn),\n signature,\n instances: new Set(), // Track all instances\n cleanups: new Map(), // Store cleanup for each instance\n };\n componentRegistry.set(hmrId, info);\n }\n\n // Create Component instance\n const component = createComponent(componentFn, props);\n // Track this instance\n info.instances.add(component);\n\n // Create effect for this Component instance\n // The effect subscribes to componentSignal and updates the component\n // We read the signal value immediately to establish the dependency,\n // but only trigger updates on subsequent changes\n let initialized = false;\n const cleanup = effect(() => {\n // Read signal value to establish dependency\n const currentComponentFn = info.componentSignal.value;\n // Skip the initialization run - only update on actual changes\n if (!initialized) {\n initialized = true;\n return;\n }\n\n // Update this specific instance when signal changes\n try {\n component.component = currentComponentFn;\n component.forceUpdate();\n } catch (error) {\n console.error(`[Essor HMR] Failed to update component instance:`, error);\n }\n });\n\n // Store cleanup function for this instance\n info.cleanups.set(component, cleanup);\n\n // Integrate with component lifecycle - cleanup when component is destroyed\n // Store the original onBeforeUnmount handler if it exists\n const originalOnBeforeUnmount = component.onBeforeUnmount;\n component.onBeforeUnmount = function () {\n // Call original handler first\n if (originalOnBeforeUnmount) {\n originalOnBeforeUnmount.call(this);\n }\n // Cleanup HMR effect\n const cleanupFn = info.cleanups.get(component);\n if (cleanupFn) {\n cleanupFn();\n info.cleanups.delete(component);\n }\n // Remove from instances tracking\n info.instances.delete(component);\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 const oldFn = oldInfo.componentSignal.value;\n if (oldFn !== 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 updates signals\n * for components whose signatures have changed. This triggers\n * reactive effects in component instances, causing them to re-render.\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 const { __hmrId: hmrId, __signature: signature } = entry;\n const id = hmrId;\n const info = componentRegistry.get(hmrId);\n\n if (!info) {\n // New component, skip (will be registered on first render)\n continue;\n }\n\n // Use shouldUpdate to determine if update is needed\n if (!shouldUpdate(info, entry, signature)) {\n continue;\n }\n\n // Component changed, apply update\n try {\n info.signature = signature;\n info.componentSignal.value = entry;\n } catch (error) {\n console.error(`[Essor HMR] Failed to update ${id}:`, error);\n needsReload = true;\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) {\n hot.accept((newModule) => handleHMRUpdate(hot, newModule));\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?.__$registry$__) {\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.__$registry$__ = 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 || registry.length === 0) {\n return false;\n }\n\n switch (bundlerType) {\n case 'vite':\n setupViteHMR(hot, registry);\n break;\n case 'webpack':\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 const cleanup = info.cleanups.get(item);\n if (cleanup) {\n try {\n cleanup();\n } catch (error) {\n console.error(`[Essor HMR] Failed to cleanup effect:`, error);\n }\n }\n count++;\n }\n\n info.instances.clear();\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";
73
+
74
+ // src/index.ts
75
+ var VIRTUAL_MODULE_ID = "virtual:essor-hmr";
76
+ var RESOLVED_VIRTUAL_MODULE_ID = "\0virtual:essor-hmr";
77
+ var DEFAULT_OPTIONS = {
78
+ symbol: "$",
79
+ mode: "client",
80
+ props: true,
81
+ hmr: true,
82
+ enableFor: false
83
+ };
84
+ var FILE_EXTENSION_REGEX = /\.[cm]?[jt]sx?$/i;
85
+ var SKIP_DIRECTORIES = ["node_modules", "dist", "public"];
86
+ function detectBundler(meta) {
87
+ if (meta == null ? void 0 : meta.framework) {
88
+ switch (meta.framework) {
89
+ case "vite":
90
+ return "vite";
91
+ case "webpack":
92
+ return "webpack5";
93
+ case "rspack":
94
+ return "rspack";
95
+ case "rollup":
96
+ return "rollup";
97
+ case "esbuild":
98
+ return "esbuild";
99
+ }
100
+ }
101
+ if (typeof process !== "undefined" && process.env) {
102
+ if (process.env.VITE || process.env.VITEST) return "vite";
103
+ if (process.env.WEBPACK_VERSION) return "webpack5";
104
+ if (process.env.RSPACK) return "rspack";
105
+ }
106
+ return "standard";
107
+ }
108
+ function generateHMRCode(bundlerType) {
109
+ const imports = [
110
+ `import { createHMRComponent as __$createHMRComponent$__ } from "${VIRTUAL_MODULE_ID}";`,
111
+ `import { hmrAccept as __$hmrAccept$__ } from "${VIRTUAL_MODULE_ID}";`
112
+ ];
113
+ const register = [
114
+ "if (import.meta.hot) {",
115
+ ` __$hmrAccept$__("${bundlerType}", import.meta.hot, __$registry$__);`,
116
+ " import.meta.hot?.accept()",
117
+ "}"
118
+ ].join("\n");
119
+ return {
120
+ importsCreateHMRComponent: `${imports[0]}
121
+ `,
122
+ importHmrAccept: `${imports[1]}
123
+ `,
124
+ register
125
+ };
126
+ }
127
+ var unpluginFactory = (options = {}, meta) => {
128
+ const filter = vite.createFilter(options.include, options.exclude);
129
+ const bundlerType = detectBundler(meta);
130
+ const finalOptions = __spreadProps(__spreadValues(__spreadValues({}, DEFAULT_OPTIONS), options), {
131
+ bundler: bundlerType
132
+ // Pass bundler type to babel plugin
133
+ });
134
+ return {
135
+ name: "unplugin-essor",
136
+ /**
137
+ * Vite-specific config to preserve JSX so the babel plugin can handle it.
138
+
139
+ */
140
+ vite: {
141
+ config() {
142
+ const ctx = this;
143
+ const isRolldownVite = !!(ctx == null ? void 0 : ctx.meta) && "rolldownVersion" in ctx.meta;
144
+ const key = isRolldownVite ? "oxc" : "esbuild";
145
+ return {
146
+ [key]: { jsx: "preserve" }
147
+ };
148
+ }
149
+ },
150
+ /**
151
+ * Resolve virtual HMR runtime module
152
+ */
153
+ resolveId(id) {
154
+ if (id === VIRTUAL_MODULE_ID) {
155
+ return RESOLVED_VIRTUAL_MODULE_ID;
156
+ }
157
+ return null;
158
+ },
159
+ /**
160
+ * Load virtual HMR runtime module
161
+ */
162
+ load(id) {
163
+ if (id === RESOLVED_VIRTUAL_MODULE_ID) {
164
+ return {
165
+ code: hmr_runtime_default,
166
+ map: null
167
+ };
168
+ }
169
+ return null;
170
+ },
171
+ rolldown: {
172
+ options(opts) {
173
+ var _a;
174
+ (_a = opts.transform) != null ? _a : opts.transform = {
175
+ jsx: "preserve"
176
+ };
177
+ }
178
+ },
179
+ /**
180
+ * Transform code with Babel plugin
181
+ */
182
+ transform(code, id) {
183
+ if (SKIP_DIRECTORIES.some((p) => id.includes(p))) {
184
+ return;
185
+ }
186
+ if (!filter(id) || !FILE_EXTENSION_REGEX.test(id)) {
187
+ return null;
188
+ }
189
+ const babelOptions = __spreadValues({}, finalOptions);
190
+ let result;
191
+ try {
192
+ result = babel__namespace.transformSync(code, {
193
+ filename: id,
194
+ sourceMaps: true,
195
+ sourceType: "module",
196
+ plugins: [[essorBabelPlugin__default.default, babelOptions]]
197
+ });
198
+ } catch (error) {
199
+ console.error(`[unplugin-essor] Transform failed for ${id}:`, error);
200
+ return null;
201
+ }
202
+ if (!(result == null ? void 0 : result.code)) {
203
+ return code;
204
+ }
205
+ const hmrEnabled = babelOptions.hmr && (babelOptions.mode === "client" || babelOptions.mode === "ssr");
206
+ let finalCode = "";
207
+ if (hmrEnabled) {
208
+ const hmrCode = generateHMRCode(bundlerType);
209
+ if (result.code.includes("__$createHMRComponent$__")) {
210
+ finalCode = `${hmrCode.importsCreateHMRComponent}
211
+ ${finalCode}`;
212
+ }
213
+ finalCode += result.code;
214
+ if (result.code.includes("__$registry$__")) {
215
+ finalCode = `${hmrCode.importHmrAccept}
216
+ ${finalCode}
217
+ ${hmrCode.register}`;
218
+ }
219
+ } else {
220
+ finalCode += result.code;
221
+ }
222
+ return {
223
+ code: finalCode,
224
+ map: result.map
225
+ };
226
+ }
227
+ };
228
+ };
229
+ var unplugin = /* @__PURE__ */ unplugin$1.createUnplugin(unpluginFactory);
230
+ var index_default = unplugin;
231
+
232
+ exports.__async = __async;
233
+ exports.index_default = index_default;
234
+ exports.unplugin = unplugin;
235
+ exports.unpluginFactory = unpluginFactory;
236
+ //# sourceMappingURL=chunk-A5FJKKLT.cjs.map
237
+ //# sourceMappingURL=chunk-A5FJKKLT.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","babel","essorBabelPlugin"],"mappings":"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","file":"chunk-A5FJKKLT.cjs","sourcesContent":["/**\n * Essor HMR Runtime - Signal-based Hot Module Replacement\n *\n * This runtime enables precise component-level HMR updates without full page reloads:\n *\n * 1. **Signal Wrapping**: Each component is wrapped in a reactive signal\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. **Effect Subscription**: Component instances subscribe to signal changes via effects\n * 5. **Bundler Agnostic**: Works with Vite, Webpack, Rspack, and other bundlers\n */\nimport { createComponent, effect, signal } from 'essor';\n\nconst isFunction = (value) => typeof value === 'function';\n/**\n * Global component registry for HMR tracking\n *\n * Maps hmrId -> ComponentInfo where:\n * - hmrId: Unique identifier for component (fileHash:componentName)\n * - componentSignal: Reactive signal holding the current component function\n * - signature: Hash of component code (changes when code changes)\n * - instances: Set of active component instances\n * - cleanups: Map of cleanup functions for each instance's effect\n */\nconst componentRegistry = new Map();\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. Wraps component function to always read from latest signal value\n * 3. Sets up reactive effect to auto-update component when signal changes\n * 4. Returns regular component instance that auto-updates on HMR\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 // First registration: create signal wrapped component\n info = {\n componentSignal: signal(componentFn),\n signature,\n instances: new Set(), // Track all instances\n cleanups: new Map(), // Store cleanup for each instance\n };\n componentRegistry.set(hmrId, info);\n }\n\n // Create Component instance\n const component = createComponent(componentFn, props);\n // Track this instance\n info.instances.add(component);\n\n // Create effect for this Component instance\n // The effect subscribes to componentSignal and updates the component\n // We read the signal value immediately to establish the dependency,\n // but only trigger updates on subsequent changes\n let initialized = false;\n const cleanup = effect(() => {\n // Read signal value to establish dependency\n const currentComponentFn = info.componentSignal.value;\n // Skip the initialization run - only update on actual changes\n if (!initialized) {\n initialized = true;\n return;\n }\n\n // Update this specific instance when signal changes\n try {\n component.component = currentComponentFn;\n component.forceUpdate();\n } catch (error) {\n console.error(`[Essor HMR] Failed to update component instance:`, error);\n }\n });\n\n // Store cleanup function for this instance\n info.cleanups.set(component, cleanup);\n\n // Integrate with component lifecycle - cleanup when component is destroyed\n // Store the original onBeforeUnmount handler if it exists\n const originalOnBeforeUnmount = component.onBeforeUnmount;\n component.onBeforeUnmount = function () {\n // Call original handler first\n if (originalOnBeforeUnmount) {\n originalOnBeforeUnmount.call(this);\n }\n // Cleanup HMR effect\n const cleanupFn = info.cleanups.get(component);\n if (cleanupFn) {\n cleanupFn();\n info.cleanups.delete(component);\n }\n // Remove from instances tracking\n info.instances.delete(component);\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 const oldFn = oldInfo.componentSignal.value;\n if (oldFn !== 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 updates signals\n * for components whose signatures have changed. This triggers\n * reactive effects in component instances, causing them to re-render.\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 const { __hmrId: hmrId, __signature: signature } = entry;\n const id = hmrId;\n const info = componentRegistry.get(hmrId);\n\n if (!info) {\n // New component, skip (will be registered on first render)\n continue;\n }\n\n // Use shouldUpdate to determine if update is needed\n if (!shouldUpdate(info, entry, signature)) {\n continue;\n }\n\n // Component changed, apply update\n try {\n info.signature = signature;\n info.componentSignal.value = entry;\n } catch (error) {\n console.error(`[Essor HMR] Failed to update ${id}:`, error);\n needsReload = true;\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) {\n hot.accept((newModule) => handleHMRUpdate(hot, newModule));\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?.__$registry$__) {\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.__$registry$__ = 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 || registry.length === 0) {\n return false;\n }\n\n switch (bundlerType) {\n case 'vite':\n setupViteHMR(hot, registry);\n break;\n case 'webpack':\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 const cleanup = info.cleanups.get(item);\n if (cleanup) {\n try {\n cleanup();\n } catch (error) {\n console.error(`[Essor HMR] Failed to cleanup effect:`, error);\n }\n }\n count++;\n }\n\n info.instances.clear();\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};\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'];\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 * Generate HMR boilerplate code for a specific bundler\n *\n * @param bundlerType - The bundler type detected\n * @returns Object with imports and registration code\n */\nfunction generateHMRCode(bundlerType: BundlerType) {\n // Import HMR utilities from virtual module\n const imports = [\n `import { createHMRComponent as __$createHMRComponent$__ } from \"${VIRTUAL_MODULE_ID}\";`,\n `import { hmrAccept as __$hmrAccept$__ } from \"${VIRTUAL_MODULE_ID}\";`,\n ];\n\n // Generate HMR acceptance code\n // The registry array (__$registry$__) is generated by the babel plugin\n const register = [\n 'if (import.meta.hot) {',\n ` __$hmrAccept$__(\"${bundlerType}\", import.meta.hot, __$registry$__);`,\n ' import.meta.hot?.accept()',\n '}',\n ].join('\\n');\n\n return {\n importsCreateHMRComponent: `${imports[0]}\\n`,\n importHmrAccept: `${imports[1]}\\n`,\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 // Merge user options with defaults\n const finalOptions = {\n ...DEFAULT_OPTIONS,\n ...options,\n bundler: bundlerType, // Pass bundler type to babel plugin\n };\n\n return {\n name: 'unplugin-essor',\n\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 },\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 const babelOptions = { ...finalOptions };\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 // Determine if HMR should be enabled\n // HMR is only for client-side code with components\n const hmrEnabled =\n babelOptions.hmr && (babelOptions.mode === 'client' || babelOptions.mode === 'ssr');\n\n let finalCode = '';\n\n // Inject HMR code if enabled and components are present\n if (hmrEnabled) {\n const hmrCode = generateHMRCode(bundlerType);\n\n if (result.code.includes('__$createHMRComponent$__')) {\n finalCode = `${hmrCode.importsCreateHMRComponent}\\n${finalCode}`;\n }\n finalCode += result.code;\n if (result.code.includes('__$registry$__')) {\n finalCode = `${hmrCode.importHmrAccept}\\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"]}
@@ -0,0 +1,209 @@
1
+ import { createUnplugin } from 'unplugin';
2
+ import * as babel from '@babel/core';
3
+ import essorBabelPlugin from 'babel-plugin-essor';
4
+ import { createFilter } from 'vite';
5
+
6
+ var __defProp = Object.defineProperty;
7
+ var __defProps = Object.defineProperties;
8
+ var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
9
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
10
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
11
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
12
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
13
+ var __spreadValues = (a, b) => {
14
+ for (var prop in b || (b = {}))
15
+ if (__hasOwnProp.call(b, prop))
16
+ __defNormalProp(a, prop, b[prop]);
17
+ if (__getOwnPropSymbols)
18
+ for (var prop of __getOwnPropSymbols(b)) {
19
+ if (__propIsEnum.call(b, prop))
20
+ __defNormalProp(a, prop, b[prop]);
21
+ }
22
+ return a;
23
+ };
24
+ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
25
+ var __async = (__this, __arguments, generator) => {
26
+ return new Promise((resolve, reject) => {
27
+ var fulfilled = (value) => {
28
+ try {
29
+ step(generator.next(value));
30
+ } catch (e) {
31
+ reject(e);
32
+ }
33
+ };
34
+ var rejected = (value) => {
35
+ try {
36
+ step(generator.throw(value));
37
+ } catch (e) {
38
+ reject(e);
39
+ }
40
+ };
41
+ var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
42
+ step((generator = generator.apply(__this, __arguments)).next());
43
+ });
44
+ };
45
+
46
+ // raw-loader:/home/runner/work/essor/essor/packages/unplugin/src/hmr-runtime.js?raw
47
+ var hmr_runtime_default = "/**\n * Essor HMR Runtime - Signal-based Hot Module Replacement\n *\n * This runtime enables precise component-level HMR updates without full page reloads:\n *\n * 1. **Signal Wrapping**: Each component is wrapped in a reactive signal\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. **Effect Subscription**: Component instances subscribe to signal changes via effects\n * 5. **Bundler Agnostic**: Works with Vite, Webpack, Rspack, and other bundlers\n */\nimport { createComponent, effect, signal } from 'essor';\n\nconst isFunction = (value) => typeof value === 'function';\n/**\n * Global component registry for HMR tracking\n *\n * Maps hmrId -> ComponentInfo where:\n * - hmrId: Unique identifier for component (fileHash:componentName)\n * - componentSignal: Reactive signal holding the current component function\n * - signature: Hash of component code (changes when code changes)\n * - instances: Set of active component instances\n * - cleanups: Map of cleanup functions for each instance's effect\n */\nconst componentRegistry = new Map();\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. Wraps component function to always read from latest signal value\n * 3. Sets up reactive effect to auto-update component when signal changes\n * 4. Returns regular component instance that auto-updates on HMR\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 // First registration: create signal wrapped component\n info = {\n componentSignal: signal(componentFn),\n signature,\n instances: new Set(), // Track all instances\n cleanups: new Map(), // Store cleanup for each instance\n };\n componentRegistry.set(hmrId, info);\n }\n\n // Create Component instance\n const component = createComponent(componentFn, props);\n // Track this instance\n info.instances.add(component);\n\n // Create effect for this Component instance\n // The effect subscribes to componentSignal and updates the component\n // We read the signal value immediately to establish the dependency,\n // but only trigger updates on subsequent changes\n let initialized = false;\n const cleanup = effect(() => {\n // Read signal value to establish dependency\n const currentComponentFn = info.componentSignal.value;\n // Skip the initialization run - only update on actual changes\n if (!initialized) {\n initialized = true;\n return;\n }\n\n // Update this specific instance when signal changes\n try {\n component.component = currentComponentFn;\n component.forceUpdate();\n } catch (error) {\n console.error(`[Essor HMR] Failed to update component instance:`, error);\n }\n });\n\n // Store cleanup function for this instance\n info.cleanups.set(component, cleanup);\n\n // Integrate with component lifecycle - cleanup when component is destroyed\n // Store the original onBeforeUnmount handler if it exists\n const originalOnBeforeUnmount = component.onBeforeUnmount;\n component.onBeforeUnmount = function () {\n // Call original handler first\n if (originalOnBeforeUnmount) {\n originalOnBeforeUnmount.call(this);\n }\n // Cleanup HMR effect\n const cleanupFn = info.cleanups.get(component);\n if (cleanupFn) {\n cleanupFn();\n info.cleanups.delete(component);\n }\n // Remove from instances tracking\n info.instances.delete(component);\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 const oldFn = oldInfo.componentSignal.value;\n if (oldFn !== 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 updates signals\n * for components whose signatures have changed. This triggers\n * reactive effects in component instances, causing them to re-render.\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 const { __hmrId: hmrId, __signature: signature } = entry;\n const id = hmrId;\n const info = componentRegistry.get(hmrId);\n\n if (!info) {\n // New component, skip (will be registered on first render)\n continue;\n }\n\n // Use shouldUpdate to determine if update is needed\n if (!shouldUpdate(info, entry, signature)) {\n continue;\n }\n\n // Component changed, apply update\n try {\n info.signature = signature;\n info.componentSignal.value = entry;\n } catch (error) {\n console.error(`[Essor HMR] Failed to update ${id}:`, error);\n needsReload = true;\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) {\n hot.accept((newModule) => handleHMRUpdate(hot, newModule));\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?.__$registry$__) {\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.__$registry$__ = 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 || registry.length === 0) {\n return false;\n }\n\n switch (bundlerType) {\n case 'vite':\n setupViteHMR(hot, registry);\n break;\n case 'webpack':\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 const cleanup = info.cleanups.get(item);\n if (cleanup) {\n try {\n cleanup();\n } catch (error) {\n console.error(`[Essor HMR] Failed to cleanup effect:`, error);\n }\n }\n count++;\n }\n\n info.instances.clear();\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";
48
+
49
+ // src/index.ts
50
+ var VIRTUAL_MODULE_ID = "virtual:essor-hmr";
51
+ var RESOLVED_VIRTUAL_MODULE_ID = "\0virtual:essor-hmr";
52
+ var DEFAULT_OPTIONS = {
53
+ symbol: "$",
54
+ mode: "client",
55
+ props: true,
56
+ hmr: true,
57
+ enableFor: false
58
+ };
59
+ var FILE_EXTENSION_REGEX = /\.[cm]?[jt]sx?$/i;
60
+ var SKIP_DIRECTORIES = ["node_modules", "dist", "public"];
61
+ function detectBundler(meta) {
62
+ if (meta == null ? void 0 : meta.framework) {
63
+ switch (meta.framework) {
64
+ case "vite":
65
+ return "vite";
66
+ case "webpack":
67
+ return "webpack5";
68
+ case "rspack":
69
+ return "rspack";
70
+ case "rollup":
71
+ return "rollup";
72
+ case "esbuild":
73
+ return "esbuild";
74
+ }
75
+ }
76
+ if (typeof process !== "undefined" && process.env) {
77
+ if (process.env.VITE || process.env.VITEST) return "vite";
78
+ if (process.env.WEBPACK_VERSION) return "webpack5";
79
+ if (process.env.RSPACK) return "rspack";
80
+ }
81
+ return "standard";
82
+ }
83
+ function generateHMRCode(bundlerType) {
84
+ const imports = [
85
+ `import { createHMRComponent as __$createHMRComponent$__ } from "${VIRTUAL_MODULE_ID}";`,
86
+ `import { hmrAccept as __$hmrAccept$__ } from "${VIRTUAL_MODULE_ID}";`
87
+ ];
88
+ const register = [
89
+ "if (import.meta.hot) {",
90
+ ` __$hmrAccept$__("${bundlerType}", import.meta.hot, __$registry$__);`,
91
+ " import.meta.hot?.accept()",
92
+ "}"
93
+ ].join("\n");
94
+ return {
95
+ importsCreateHMRComponent: `${imports[0]}
96
+ `,
97
+ importHmrAccept: `${imports[1]}
98
+ `,
99
+ register
100
+ };
101
+ }
102
+ var unpluginFactory = (options = {}, meta) => {
103
+ const filter = createFilter(options.include, options.exclude);
104
+ const bundlerType = detectBundler(meta);
105
+ const finalOptions = __spreadProps(__spreadValues(__spreadValues({}, DEFAULT_OPTIONS), options), {
106
+ bundler: bundlerType
107
+ // Pass bundler type to babel plugin
108
+ });
109
+ return {
110
+ name: "unplugin-essor",
111
+ /**
112
+ * Vite-specific config to preserve JSX so the babel plugin can handle it.
113
+
114
+ */
115
+ vite: {
116
+ config() {
117
+ const ctx = this;
118
+ const isRolldownVite = !!(ctx == null ? void 0 : ctx.meta) && "rolldownVersion" in ctx.meta;
119
+ const key = isRolldownVite ? "oxc" : "esbuild";
120
+ return {
121
+ [key]: { jsx: "preserve" }
122
+ };
123
+ }
124
+ },
125
+ /**
126
+ * Resolve virtual HMR runtime module
127
+ */
128
+ resolveId(id) {
129
+ if (id === VIRTUAL_MODULE_ID) {
130
+ return RESOLVED_VIRTUAL_MODULE_ID;
131
+ }
132
+ return null;
133
+ },
134
+ /**
135
+ * Load virtual HMR runtime module
136
+ */
137
+ load(id) {
138
+ if (id === RESOLVED_VIRTUAL_MODULE_ID) {
139
+ return {
140
+ code: hmr_runtime_default,
141
+ map: null
142
+ };
143
+ }
144
+ return null;
145
+ },
146
+ rolldown: {
147
+ options(opts) {
148
+ var _a;
149
+ (_a = opts.transform) != null ? _a : opts.transform = {
150
+ jsx: "preserve"
151
+ };
152
+ }
153
+ },
154
+ /**
155
+ * Transform code with Babel plugin
156
+ */
157
+ transform(code, id) {
158
+ if (SKIP_DIRECTORIES.some((p) => id.includes(p))) {
159
+ return;
160
+ }
161
+ if (!filter(id) || !FILE_EXTENSION_REGEX.test(id)) {
162
+ return null;
163
+ }
164
+ const babelOptions = __spreadValues({}, finalOptions);
165
+ let result;
166
+ try {
167
+ result = babel.transformSync(code, {
168
+ filename: id,
169
+ sourceMaps: true,
170
+ sourceType: "module",
171
+ plugins: [[essorBabelPlugin, babelOptions]]
172
+ });
173
+ } catch (error) {
174
+ console.error(`[unplugin-essor] Transform failed for ${id}:`, error);
175
+ return null;
176
+ }
177
+ if (!(result == null ? void 0 : result.code)) {
178
+ return code;
179
+ }
180
+ const hmrEnabled = babelOptions.hmr && (babelOptions.mode === "client" || babelOptions.mode === "ssr");
181
+ let finalCode = "";
182
+ if (hmrEnabled) {
183
+ const hmrCode = generateHMRCode(bundlerType);
184
+ if (result.code.includes("__$createHMRComponent$__")) {
185
+ finalCode = `${hmrCode.importsCreateHMRComponent}
186
+ ${finalCode}`;
187
+ }
188
+ finalCode += result.code;
189
+ if (result.code.includes("__$registry$__")) {
190
+ finalCode = `${hmrCode.importHmrAccept}
191
+ ${finalCode}
192
+ ${hmrCode.register}`;
193
+ }
194
+ } else {
195
+ finalCode += result.code;
196
+ }
197
+ return {
198
+ code: finalCode,
199
+ map: result.map
200
+ };
201
+ }
202
+ };
203
+ };
204
+ var unplugin = /* @__PURE__ */ createUnplugin(unpluginFactory);
205
+ var index_default = unplugin;
206
+
207
+ export { __async, index_default, unplugin, unpluginFactory };
208
+ //# sourceMappingURL=chunk-RU3ODIHJ.js.map
209
+ //# sourceMappingURL=chunk-RU3ODIHJ.js.map