kirbyup 4.0.0-alpha.3 → 4.0.0-alpha.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/node/cli.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { a as version, i as name, n as serve, r as handleError, t as build } from "../node-DxNmVk8V.mjs";
1
+ import { a as version, i as name, n as serve, r as handleError, t as build } from "../node-GoJ-fFA1.mjs";
2
2
  import { cac } from "cac";
3
3
 
4
4
  //#region src/node/cli-start.ts
@@ -1,3 +1,3 @@
1
- import { n as serve, t as build } from "../node-DxNmVk8V.mjs";
1
+ import { n as serve, t as build } from "../node-GoJ-fFA1.mjs";
2
2
 
3
3
  export { build, serve };
@@ -18,7 +18,7 @@ import { gzip } from "node:zlib";
18
18
 
19
19
  //#region package.json
20
20
  var name = "kirbyup";
21
- var version = "4.0.0-alpha.3";
21
+ var version = "4.0.0-alpha.4";
22
22
 
23
23
  //#endregion
24
24
  //#region src/node/config.ts
@@ -72,109 +72,149 @@ function kirbyupBuildCleanupPlugin(options) {
72
72
 
73
73
  //#endregion
74
74
  //#region src/node/plugins/utils.ts
75
- const HMR_RUNTIME_ID = "\0plugin-vue2:hmr-runtime";
76
- const JSX_HMR_RUNTIME_ID = "plugin-vue2-jsx:hmr-runtime";
77
- function isHmrRuntimeId(id) {
78
- return id === HMR_RUNTIME_ID || id === JSX_HMR_RUNTIME_ID;
79
- }
80
75
  /**
81
- * This code is injected into the HMR runtime of plugin-vue2(-jsx).
76
+ * This code is injected into Vue 3 components to wrap the global HMR runtime.
82
77
  *
83
- * All `.vue` components register themselves once with the HMR runtime, so their exported
84
- * component definitions can be stored in a map, alongside the rendered component instances
85
- * that are based off this definition. When a module is updated, the runtime applies all
86
- * changes from the updated module to the stored definition, then re-renders the instances.
78
+ * All `.vue` components register themselves with the HMR runtime (`__VUE_HMR_RUNTIME__`),
79
+ * which stores their component definitions in a map. When a module is updated, the runtime
80
+ * applies changes to the stored definition and re-renders component instances.
87
81
  *
82
+ * In Vue 3, the HMR map structure is:
88
83
  * ```js
89
84
  * {
90
- * [id]: { options: ComponentDefinition, instances: [...] }
85
+ * [id]: { initialDef: ComponentDefinition, instances: Set<ComponentInstance> }
91
86
  * }
92
87
  * ```
93
88
  *
94
- * However, in some cases (sections and blocks) Kirby does not actually register the
95
- * object that is exported from a `.vue` file (and stored as definition) as component,
96
- * instead it creates a new object and merges the definition from the `.vue` file in:
97
- * https://github.com/getkirby/kirby/blob/main/panel/public/js/plugins.js#L22-L25
98
- * After changes, the runtime updates the definition and re-renders the instances, but since
99
- * they are derived from the object created by Kirby, not the stored definition, nothing happens.
100
- * To fix that, we wrap `rerender()` and `reload()` so that before applying the updates, we first check
101
- * if the updated definition belongs to a component added by a Kirby plugin. To do so, we can check
102
- * whether the `__file` (added by plugin-vue2) or `__hmrId` (added by plugin-vue2-jsx) properties of the
103
- * updated module and the plugin component match. If so, we look up the component definition that is
104
- * _actually_ used by component instances rendered on the page (`window.panel.app.$options.components`)
105
- * and if it differs from the one stored in the HMR runtime's map, we updates the map's reference.
89
+ * However, Kirby does not register the exact object exported from a `.vue` file.
90
+ * Instead, it creates a new object and merges the definition in:
91
+ * https://github.com/getkirby/kirby/blob/main/panel/public/js/plugins.js
92
+ *
93
+ * After HMR changes, the runtime updates the stored definition and re-renders instances,
94
+ * but since they are derived from Kirby's modified object (not the stored definition),
95
+ * updates may not apply correctly.
96
+ *
97
+ * To fix this, we wrap `__VUE_HMR_RUNTIME__.rerender()` and `__VUE_HMR_RUNTIME__.reload()`:
98
+ *
99
+ * 1. **Before updates**, we check if the component belongs to a Kirby plugin by matching
100
+ * the `__hmrId` or `__file` properties against registered plugin components.
101
+ *
102
+ * 2. **If matched**, we look up the actual component definition used by Kirby
103
+ * (`window.panel.app.config.globalProperties.$root.$options.components`)
104
+ * and update the HMR map's reference to point to it.
105
+ *
106
+ * 3. **For section components** (detected by `k-*-section` name pattern), we add a
107
+ * `$_isSection` flag for special treatment in `$_applyKirbyModifications()`.
106
108
  *
107
- * We also check the component name and add a `$_isSection` flag if it's `k-something-section`, because
108
- * section components are hard to detect and need special treatment in `$_applyKirbyModifications`.
109
+ * `$_applyKirbyModifications()`:
109
110
  *
110
- * `$_applyKirbyModifications`:
111
+ * Kirby modifies component definitions before registration:
112
+ * - Adds the section mixin to section components
113
+ * - Gives templates priority over render functions
114
+ * - Resolves component names in `extends` to their definition objects
111
115
  *
112
- * Kirby modifies component definitions before registering components.
113
- * This includes adding the section mixin to section components,
114
- * giving templates priority over render functions if both exist
115
- * and resolving component names in `extends` to their definition object:
116
- * https://github.com/getkirby/kirby/blob/2965c3124e3b141072a2d46c798a327dda710060/panel/src/panel/plugins.js
117
- * When a module is reloaded, Vue receives a fresh component definition that is
118
- * missing these modifications. We need to re-apply them, else the runtime will
119
- * prune them when patching the stored definition to match the newer one.
116
+ * When a module hot reloads, Vue 3 receives a fresh component definition missing
117
+ * these modifications. We re-apply them to ensure the runtime doesn't prune them
118
+ * when patching the stored definition with the updated one.
120
119
  *
121
- * The call to `$_applyKirbyModifications()` is injected into `__VUE_HMR_RUNTIME__.reload()`
122
- * at the appropriate position using a RegExp in the Vite plugin's transform method.
120
+ * This code uses a singleton pattern (`__KIRBYUP_HMR_WRAPPED__`) to ensure the
121
+ * wrapper is installed only once, even though it's injected into every component.
123
122
  */
124
- const __INJECTED_HMR_CODE__ = `
125
- /** - injected by kirbyup - */
126
- for (const methodName of ['rerender', 'reload']) {
127
- const original = __VUE_HMR_RUNTIME__[methodName]
123
+ const __HMR_INJECTION_CODE__ = `
124
+ /** - injected by kirbyup for Vue 3 HMR - */
125
+ if (typeof __VUE_HMR_RUNTIME__ !== 'undefined' && !window.__KIRBYUP_HMR_WRAPPED__) {
126
+ window.__KIRBYUP_HMR_WRAPPED__ = true;
128
127
 
129
- __VUE_HMR_RUNTIME__[methodName] = function (id, updatedDef) {
130
- const key = updatedDef?.__file ? '__file' : updatedDef?.__hmrId ? '__hmrId' : null
128
+ const originalRerender = __VUE_HMR_RUNTIME__.rerender;
129
+ const originalReload = __VUE_HMR_RUNTIME__.reload;
130
+
131
+ __VUE_HMR_RUNTIME__.rerender = function(id, newRender) {
132
+ $_syncKirbyComponent(id);
133
+ return originalRerender.call(this, id, newRender);
134
+ };
135
+
136
+ __VUE_HMR_RUNTIME__.reload = function(id, newComp) {
137
+ const record = $_getHmrRecord(id);
138
+ if (record) {
139
+ $_syncKirbyComponent(id, record.initialDef);
140
+ $_applyKirbyModifications(record.initialDef, newComp);
141
+ }
142
+ return originalReload.call(this, id, newComp);
143
+ };
144
+
145
+ function $_getHmrRecord(id) {
146
+ // Vue 3's HMR map is not exposed, so we maintain our own parallel map
147
+ // by wrapping \`createRecord\` to track component definitions
148
+ if (!window.__KIRBYUP_MAP__) {
149
+ window.__KIRBYUP_MAP__ = new Map();
150
+ const originalCreate = __VUE_HMR_RUNTIME__.createRecord;
151
+ __VUE_HMR_RUNTIME__.createRecord = function(id, initialDef) {
152
+ window.__KIRBYUP_MAP__.set(id, { initialDef });
153
+ return originalCreate.call(this, id, initialDef);
154
+ };
155
+ }
156
+ return window.__KIRBYUP_MAP__.get(id);
157
+ }
131
158
 
132
- if (key) {
133
- const pluginComponents = window.panel.plugins.components
134
- // const usedComponentDefs = window.panel.app.$options.components
135
- const usedComponentDefs = window.panel.app._vnode.componentInstance.$options.components // #33
159
+ function $_syncKirbyComponent(id, activeDef) {
160
+ const pluginComponents = window.panel?.plugins?.components;
161
+ const usedComponentDefs = window.panel?.app?.config?.globalProperties?.$root?.$options?.components;
136
162
 
137
- for (const componentName in pluginComponents) {
138
- if (updatedDef[key] === pluginComponents[componentName][key]) {
139
- const usedDefinition = usedComponentDefs[componentName].options
163
+ if (!pluginComponents || !usedComponentDefs) return;
140
164
 
141
- if (map[id].options !== usedDefinition)
142
- map[id].options = usedDefinition
165
+ const record = $_getHmrRecord(id);
166
+ if (!record) return;
143
167
 
144
- if (typeof map[id].options.$_isSection !== 'boolean')
145
- map[id].options.$_isSection = /^k-.*-section$/.test(componentName)
168
+ for (const componentName in pluginComponents) {
169
+ const pluginComp = pluginComponents[componentName];
146
170
 
147
- break
171
+ if (pluginComp.__hmrId === id || pluginComp.__file === record.initialDef?.__file) {
172
+ const usedDef = usedComponentDefs[componentName];
173
+
174
+ if (usedDef && record.initialDef !== usedDef) {
175
+ record.initialDef = usedDef;
176
+ }
177
+
178
+ if (activeDef && typeof activeDef.$_isSection !== 'boolean') {
179
+ activeDef.$_isSection = /^k-.*-section$/.test(componentName);
148
180
  }
181
+
182
+ break;
149
183
  }
150
184
  }
151
-
152
- return original.apply(this, arguments)
153
185
  }
154
- }
155
186
 
156
- function $_applyKirbyModifications(activeDef, newDef) {
157
- const usedComponentDefs = window.panel.app.$options.components
187
+ function $_applyKirbyModifications(activeDef, newDef) {
188
+ const usedComponentDefs = window.panel?.app?.config?.globalProperties?.$root?.$options?.components;
158
189
 
159
- if (newDef.template)
160
- newDef.render = null
190
+ if (!usedComponentDefs) return;
161
191
 
162
- if (activeDef.$_isSection)
163
- newDef.$_isSection = true
164
- if (newDef.$_isSection && !newDef.mixins?.[0]?.methods?.load)
165
- newDef.mixins = [activeDef.mixins[0], ...(newDef.mixins || [])]
192
+ // Give templates priority over render functions
193
+ if (newDef.template) {
194
+ newDef.render = null;
195
+ }
166
196
 
167
- if (typeof newDef.extends === 'string') {
168
- if (newDef.extends === activeDef.extends?.options?.name) {
169
- newDef.extends = activeDef.extends
197
+ // Re-apply section mixin for section components
198
+ if (activeDef.$_isSection) {
199
+ newDef.$_isSection = true;
200
+ if (!newDef.mixins?.[0]?.methods?.load) {
201
+ const sectionMixin = activeDef.mixins?.[0];
202
+ if (sectionMixin) {
203
+ newDef.mixins = [sectionMixin, ...(newDef.mixins || [])];
204
+ }
205
+ }
170
206
  }
171
- else if (usedComponentDefs[newDef.extends]) {
172
- newDef.extends = usedComponentDefs[newDef.extends].extend({
173
- options: newDef,
174
- components: { ...usedComponentDefs, ...(newDef.components || {}) },
175
- })
207
+
208
+ // Resolve component name in extends to definition object
209
+ if (typeof newDef.extends === 'string') {
210
+ if (newDef.extends === activeDef.extends?.name) {
211
+ newDef.extends = activeDef.extends;
212
+ } else if (usedComponentDefs[newDef.extends]) {
213
+ newDef.extends = usedComponentDefs[newDef.extends];
214
+ } else {
215
+ newDef.extends = null;
216
+ }
176
217
  }
177
- else { newDef.extends = null }
178
218
  }
179
219
  }
180
220
  /** -- */
@@ -195,7 +235,14 @@ function kirbyupHmrPlugin(options) {
195
235
  devIndexPath = resolve(config.root, options.outDir || "", "index.dev.mjs");
196
236
  },
197
237
  transform(code, id) {
198
- if (isHmrRuntimeId(id)) return code.replace(/^.*=\s*record\.Ctor\.super\.extend\(options\)/m, "$_applyKirbyModifications(record.Ctor.options, options) // injected by kirbyup\n$&") + __INJECTED_HMR_CODE__;
238
+ if (!id.endsWith(".vue")) return;
239
+ if (!code.includes("__VUE_HMR_RUNTIME__.createRecord")) return;
240
+ const injectionPoint = code.indexOf("import.meta.hot.accept");
241
+ if (injectionPoint === -1) return;
242
+ return {
243
+ code: `${code.slice(0, injectionPoint) + __HMR_INJECTION_CODE__}\n${code.slice(injectionPoint)}`,
244
+ map: null
245
+ };
199
246
  },
200
247
  configureServer(server) {
201
248
  if (!server.httpServer) return;
@@ -389,7 +436,7 @@ function getViteConfig(command, options) {
389
436
  const mode = options.watch ? "development" : "production";
390
437
  return mergeConfig(mergeConfig(sharedConfig, {
391
438
  mode,
392
- plugins: [kirbyupBuildCleanupPlugin(options)],
439
+ plugins: [kirbyupBuildCleanupPlugin(options), options.watch && kirbyupRunningMarkerPlugin({ outDir: options.outDir })].filter(Boolean),
393
440
  build: {
394
441
  lib: {
395
442
  entry: resolve(options.cwd, options.entry),
@@ -412,8 +459,8 @@ async function generate(options) {
412
459
  try {
413
460
  result = await build(config);
414
461
  } catch (error) {
415
- consola.error("Build failed");
416
462
  if (config.mode === "production") throw error;
463
+ else consola.error(error);
417
464
  }
418
465
  if (result && !options.watch) {
419
466
  const { output } = toArray(result)[0];
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "kirbyup",
3
3
  "type": "module",
4
- "version": "4.0.0-alpha.3",
4
+ "version": "4.0.0-alpha.4",
5
5
  "packageManager": "pnpm@10.25.0",
6
6
  "description": "Zero-config bundler for Kirby Panel plugins",
7
7
  "author": {
@@ -84,7 +84,6 @@
84
84
  "perfect-debounce": "^2.0.0",
85
85
  "postcss": "^8.5.6",
86
86
  "postcss-load-config": "^6.0.1",
87
- "rollup-plugin-external-globals": "^0.13.0",
88
87
  "sass": "^1.95.1",
89
88
  "vite": "^7.2.7",
90
89
  "vite-plugin-full-reload": "^1.2.0",