kirbyup 4.0.0-alpha.4 → 4.0.0-alpha.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -3
- package/dist/client/config.d.mts +1 -1
- package/dist/client/config.mjs +1 -2
- package/dist/client/plugin.mjs +11 -5
- package/dist/node/cli.mjs +2 -5
- package/dist/node/index.d.mts +1 -1
- package/dist/node/index.mjs +2 -3
- package/dist/node-Do_IAs2E.mjs +422 -0
- package/dist/{types-CFhX3iS8.d.mts → types-0NUTyTUQ.d.mts} +0 -1
- package/package.json +24 -22
- package/dist/node-GoJ-fFA1.mjs +0 -538
package/README.md
CHANGED
|
@@ -2,8 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
# kirbyup
|
|
4
4
|
|
|
5
|
-
[](https://www.npmjs.com/package/kirbyup)
|
|
6
|
-
|
|
7
5
|
The official bundler for Kirby Panel plugins with zero-config usage and built-in HMR.
|
|
8
6
|
|
|
9
7
|
- [✨ Release Notes](https://github.com/johannschopplich/kirbyup/releases)
|
|
@@ -35,7 +33,7 @@ npm i -D kirbyup
|
|
|
35
33
|
> [!TIP]
|
|
36
34
|
> [📖 Read the documentation](https://kirbyup.getkirby.com) or skip starting from scratch and pick one of the following starters:
|
|
37
35
|
> - [`eslint`](./examples/eslint)
|
|
38
|
-
> - [`
|
|
36
|
+
> - [`unocss`](./examples/unocss)
|
|
39
37
|
|
|
40
38
|
Having installed kirbyup, you can add the following scripts as shortcuts to the commands you will use most often:
|
|
41
39
|
|
package/dist/client/config.d.mts
CHANGED
package/dist/client/config.mjs
CHANGED
package/dist/client/plugin.mjs
CHANGED
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
//#region src/client/plugin.ts
|
|
2
|
-
const kirbyup = Object.freeze({
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
const kirbyup = Object.freeze({
|
|
3
|
+
/**
|
|
4
|
+
* Auto-import Kirby Panel components, transformed by
|
|
5
|
+
* kirbyup's glob-import plugin for Vite.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* kirbyup.import('./components/blocks/*.vue')
|
|
9
|
+
*/
|
|
10
|
+
import(glob) {
|
|
11
|
+
return Object.entries(glob).reduce((accumulator, [path, component]) => {
|
|
5
12
|
accumulator[getComponentName(path)] = component.default;
|
|
6
13
|
return accumulator;
|
|
7
14
|
}, {});
|
|
@@ -9,6 +16,5 @@ const kirbyup = Object.freeze({ import(glob) {
|
|
|
9
16
|
function getComponentName(path) {
|
|
10
17
|
return path.substring(path.lastIndexOf("/") + 1, path.lastIndexOf(".")).toLowerCase();
|
|
11
18
|
}
|
|
12
|
-
|
|
13
19
|
//#endregion
|
|
14
|
-
export { kirbyup };
|
|
20
|
+
export { kirbyup };
|
package/dist/node/cli.mjs
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { a as version, i as name, n as serve, r as handleError, t as build } from "../node-
|
|
1
|
+
import { a as version, i as name, n as serve, r as handleError, t as build } from "../node-Do_IAs2E.mjs";
|
|
2
2
|
import { cac } from "cac";
|
|
3
|
-
|
|
4
3
|
//#region src/node/cli-start.ts
|
|
5
4
|
async function startCli(cwd = process.cwd(), argv = process.argv) {
|
|
6
5
|
const cli = cac(name);
|
|
@@ -36,10 +35,8 @@ async function startCli(cwd = process.cwd(), argv = process.argv) {
|
|
|
36
35
|
cli.parse(argv, { run: false });
|
|
37
36
|
await cli.runMatchedCommand();
|
|
38
37
|
}
|
|
39
|
-
|
|
40
38
|
//#endregion
|
|
41
39
|
//#region src/node/cli.ts
|
|
42
40
|
startCli().catch(handleError);
|
|
43
|
-
|
|
44
41
|
//#endregion
|
|
45
|
-
export {
|
|
42
|
+
export {};
|
package/dist/node/index.d.mts
CHANGED
package/dist/node/index.mjs
CHANGED
|
@@ -1,3 +1,2 @@
|
|
|
1
|
-
import { n as serve, t as build } from "../node-
|
|
2
|
-
|
|
3
|
-
export { build, serve };
|
|
1
|
+
import { n as serve, t as build } from "../node-Do_IAs2E.mjs";
|
|
2
|
+
export { build, serve };
|
|
@@ -0,0 +1,422 @@
|
|
|
1
|
+
import * as fs from "node:fs";
|
|
2
|
+
import * as fsp from "node:fs/promises";
|
|
3
|
+
import vuePlugin from "@vitejs/plugin-vue";
|
|
4
|
+
import vueJsxPlugin from "@vitejs/plugin-vue-jsx";
|
|
5
|
+
import { consola } from "consola";
|
|
6
|
+
import { colors } from "consola/utils";
|
|
7
|
+
import { basename, dirname, normalize, relative, resolve } from "pathe";
|
|
8
|
+
import { debounce } from "perfect-debounce";
|
|
9
|
+
import { build, createLogger, createServer, mergeConfig, normalizePath } from "vite";
|
|
10
|
+
import fullReloadPlugin from "vite-plugin-full-reload";
|
|
11
|
+
import * as vueCompilerSfc from "vue/compiler-sfc";
|
|
12
|
+
import { loadConfig } from "c12";
|
|
13
|
+
import postcssrc from "postcss-load-config";
|
|
14
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
15
|
+
import { detectPackageManager } from "nypm";
|
|
16
|
+
import { isIP } from "node:net";
|
|
17
|
+
import { Buffer } from "node:buffer";
|
|
18
|
+
import { promisify } from "node:util";
|
|
19
|
+
import { gzip } from "node:zlib";
|
|
20
|
+
//#region package.json
|
|
21
|
+
var name = "kirbyup";
|
|
22
|
+
var version = "4.0.0-alpha.6";
|
|
23
|
+
//#endregion
|
|
24
|
+
//#region src/node/config.ts
|
|
25
|
+
function loadConfig$1(cwd = process.cwd()) {
|
|
26
|
+
return loadConfig({
|
|
27
|
+
cwd,
|
|
28
|
+
name: "kirbyup",
|
|
29
|
+
rcFile: false,
|
|
30
|
+
packageJson: false
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
async function resolvePostCSSConfig(cwd) {
|
|
34
|
+
try {
|
|
35
|
+
return await postcssrc(void 0, void 0, { stopDir: cwd });
|
|
36
|
+
} catch (error) {
|
|
37
|
+
if (!error.message.includes("No PostCSS Config found")) throw error;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
//#endregion
|
|
41
|
+
//#region src/node/errors.ts
|
|
42
|
+
var PrettyError = class extends Error {
|
|
43
|
+
constructor(message) {
|
|
44
|
+
super(message);
|
|
45
|
+
this.name = this.constructor.name;
|
|
46
|
+
if (typeof Error.captureStackTrace === "function") Error.captureStackTrace(this, this.constructor);
|
|
47
|
+
else this.stack = new Error(message).stack;
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
function handleError(error) {
|
|
51
|
+
consola.error(error.message);
|
|
52
|
+
process.exitCode = 1;
|
|
53
|
+
}
|
|
54
|
+
//#endregion
|
|
55
|
+
//#region src/node/plugins/build-cleanup.ts
|
|
56
|
+
function kirbyupBuildCleanupPlugin(options) {
|
|
57
|
+
let config;
|
|
58
|
+
let devIndexPath;
|
|
59
|
+
return {
|
|
60
|
+
name: "kirbyup:build-cleanup",
|
|
61
|
+
configResolved(resolvedConfig) {
|
|
62
|
+
config = resolvedConfig;
|
|
63
|
+
devIndexPath = resolve(config.root, options.outDir, "index.dev.js");
|
|
64
|
+
},
|
|
65
|
+
writeBundle() {
|
|
66
|
+
if (options.watch) return;
|
|
67
|
+
if (fs.existsSync(devIndexPath)) fs.unlinkSync(devIndexPath);
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
//#endregion
|
|
72
|
+
//#region src/node/utils/server.ts
|
|
73
|
+
function resolveOriginFromServerOptions(serverOptions, port, fallbackHostname) {
|
|
74
|
+
const protocol = serverOptions?.https && (typeof serverOptions.https === "boolean" || Object.keys(serverOptions.https).length > 0) ? "https" : "http";
|
|
75
|
+
const configuredHost = normalizeHost(serverOptions?.host);
|
|
76
|
+
return `${protocol}://${formatHostname(configuredHost || fallbackHostname || "localhost")}${(configuredHost ? hostIncludesPort(configuredHost) : false) || !needsExplicitPort(protocol, port) ? "" : `:${port}`}`;
|
|
77
|
+
}
|
|
78
|
+
function ensureTrailingSlash(url) {
|
|
79
|
+
return url.endsWith("/") ? url : `${url}/`;
|
|
80
|
+
}
|
|
81
|
+
function normalizeHost(host) {
|
|
82
|
+
if (host === false || host === void 0) return;
|
|
83
|
+
if (host === true) return "0.0.0.0";
|
|
84
|
+
return host;
|
|
85
|
+
}
|
|
86
|
+
function formatHostname(host) {
|
|
87
|
+
if (!host) return "localhost";
|
|
88
|
+
if (host.startsWith("[") && host.endsWith("]")) return host;
|
|
89
|
+
return isIP(host) === 6 ? `[${host}]` : host;
|
|
90
|
+
}
|
|
91
|
+
function hostIncludesPort(host) {
|
|
92
|
+
if (host.startsWith("[")) {
|
|
93
|
+
const closingIndex = host.indexOf("]");
|
|
94
|
+
return closingIndex > -1 && host.slice(closingIndex + 1).startsWith(":");
|
|
95
|
+
}
|
|
96
|
+
if (isIP(host) === 6) return false;
|
|
97
|
+
return host.includes(":");
|
|
98
|
+
}
|
|
99
|
+
function needsExplicitPort(protocol, port) {
|
|
100
|
+
if (protocol === "http") return port !== 80;
|
|
101
|
+
return port !== 443;
|
|
102
|
+
}
|
|
103
|
+
//#endregion
|
|
104
|
+
//#region src/node/plugins/runtime/hmr-shim.js?raw
|
|
105
|
+
var hmr_shim_default = "/* eslint-disable no-undef */\nimport 'vue'\n\nif (typeof __VUE_HMR_RUNTIME__ !== 'undefined') {\n const originalReload = __VUE_HMR_RUNTIME__.reload\n\n __VUE_HMR_RUNTIME__.reload = function (id, newComp) {\n const plugins = window.panel && window.panel.plugins\n const app = window.panel && window.panel.app\n\n if (\n plugins\n && app\n && plugins.components\n && typeof plugins.resolveComponentExtension === 'function'\n && typeof plugins.resolveComponentRender === 'function'\n && typeof plugins.resolveComponentMixins === 'function'\n ) {\n for (const name in plugins.components) {\n const pluginComp = plugins.components[name]\n if (\n pluginComp.__hmrId === id\n || (newComp.__file && pluginComp.__file === newComp.__file)\n ) {\n plugins.resolveComponentExtension(app, name, newComp)\n plugins.resolveComponentRender(newComp)\n plugins.resolveComponentMixins(newComp)\n break\n }\n }\n }\n\n return originalReload.call(this, id, newComp)\n }\n}\nelse {\n console.warn(\n '[kirbyup] Vue HMR runtime not detected; component changes will fall back to full page reload. The Kirby Panel may be loading a production build of Vue.',\n )\n}\n";
|
|
106
|
+
//#endregion
|
|
107
|
+
//#region src/node/plugins/runtime/vue-stub.js?raw
|
|
108
|
+
var vue_stub_default = "const __kirbyupVueImportMapEl = typeof document !== 'undefined'\n ? document.querySelector('script[type=\"importmap\"]')\n : null\nconst __kirbyupVueImports = __kirbyupVueImportMapEl\n ? (() => {\n try {\n return JSON.parse(__kirbyupVueImportMapEl.textContent || '{}').imports || {}\n }\n // eslint-disable-next-line unused-imports/no-unused-vars\n catch (_) {\n return {}\n }\n })()\n : {}\nconst __kirbyupVueUrl = __kirbyupVueImports.vue\nif (!__kirbyupVueUrl) {\n throw new Error(\n '[kirbyup] No \"vue\" entry found in the page <script type=\"importmap\">. Ensure Kirby\\'s Panel is loaded with v6 import maps enabled.',\n )\n}\n// eslint-disable-next-line no-unused-vars, antfu/no-top-level-await\nconst __kirbyupVueModule = await import(/* @vite-ignore */ __kirbyupVueUrl)\n";
|
|
109
|
+
//#endregion
|
|
110
|
+
//#region src/node/plugins/utils.ts
|
|
111
|
+
/**
|
|
112
|
+
* Vue's `reload` does `Object.assign(record.initialDef, newComp)`, which would
|
|
113
|
+
* overwrite Kirby's in-place mutations on the stored definition. The shim
|
|
114
|
+
* re-runs Kirby's plugin helpers on `newComp` first; see
|
|
115
|
+
* https://github.com/getkirby/kirby/blob/v6/develop/panel/src/panel/plugins.ts
|
|
116
|
+
* ("expose helper functions for kirbyup"). `rerender` is not wrapped: in Vue 3
|
|
117
|
+
* it only swaps a render function, leaving Kirby's mutations untouched.
|
|
118
|
+
*/
|
|
119
|
+
const __HMR_SHIM_CODE__ = hmr_shim_default;
|
|
120
|
+
/**
|
|
121
|
+
* Extract public named exports from a Rollup-style ESM bundle. Vue's
|
|
122
|
+
* `dist/vue.esm-browser.js` ships a single trailing `export { ... }` block
|
|
123
|
+
* with a few `internalName as publicName` aliases.
|
|
124
|
+
*
|
|
125
|
+
* Only the last block is read; `as`-aliased entries yield the public name.
|
|
126
|
+
*/
|
|
127
|
+
function extractEsmNamedExports(source) {
|
|
128
|
+
const blockMatches = [...source.matchAll(/export\s*\{([^}]*)\}/g)];
|
|
129
|
+
if (blockMatches.length === 0) return [];
|
|
130
|
+
return blockMatches.at(-1)[1].split(",").map((entry) => entry.trim()).filter(Boolean).map((entry) => {
|
|
131
|
+
const aliasMatch = entry.match(/^\S+\s+as\s+(\S+)$/);
|
|
132
|
+
return aliasMatch ? aliasMatch[1] : entry;
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Reads Kirby's panel-vue URL at runtime from the page's
|
|
137
|
+
* `<script type="importmap">` and dynamic-imports it; the browser's module
|
|
138
|
+
* map dedups by URL, so plugin SFCs share Kirby's Vue instance (and
|
|
139
|
+
* `__VUE_HMR_RUNTIME__`). Top-level await lets consumers keep using ordinary
|
|
140
|
+
* `import { ... } from 'vue'` syntax.
|
|
141
|
+
*/
|
|
142
|
+
function buildVueStubCode(namedExports) {
|
|
143
|
+
if (namedExports.length === 0) return vue_stub_default;
|
|
144
|
+
return vue_stub_default + `\nexport const {\n${namedExports.map((name) => ` ${name},`).join("\n")}\n} = __kirbyupVueModule\n`;
|
|
145
|
+
}
|
|
146
|
+
//#endregion
|
|
147
|
+
//#region src/node/plugins/hmr.ts
|
|
148
|
+
const SHIM_ID = "\0kirbyup:hmr-shim";
|
|
149
|
+
const SHIM_PUBLIC_ID = SHIM_ID.slice(1);
|
|
150
|
+
const VUE_STUB_ID = "\0kirbyup:vue-stub";
|
|
151
|
+
const VUE_STUB_PUBLIC_ID = VUE_STUB_ID.slice(1);
|
|
152
|
+
const VUE_NOT_FOUND_STUB = `throw new Error('[kirbyup] Cannot resolve "vue/dist/vue.esm-browser.js" from the plugin project. Make sure "vue" is installed as a dependency.')\n`;
|
|
153
|
+
function kirbyupHmrPlugin(options) {
|
|
154
|
+
let config;
|
|
155
|
+
let entry;
|
|
156
|
+
let entryId;
|
|
157
|
+
let devIndexPath;
|
|
158
|
+
let vueStubCode;
|
|
159
|
+
return {
|
|
160
|
+
name: "kirbyup:hmr",
|
|
161
|
+
apply: "serve",
|
|
162
|
+
enforce: "pre",
|
|
163
|
+
config() {
|
|
164
|
+
return {
|
|
165
|
+
optimizeDeps: { exclude: ["vue"] },
|
|
166
|
+
resolve: { alias: [{
|
|
167
|
+
find: /^vue$/,
|
|
168
|
+
replacement: VUE_STUB_ID
|
|
169
|
+
}] }
|
|
170
|
+
};
|
|
171
|
+
},
|
|
172
|
+
configResolved(resolvedConfig) {
|
|
173
|
+
config = resolvedConfig;
|
|
174
|
+
entry = resolve(config.root, options.entry);
|
|
175
|
+
entryId = normalizePath(entry);
|
|
176
|
+
devIndexPath = resolve(config.root, options.outDir ?? "", "index.dev.js");
|
|
177
|
+
try {
|
|
178
|
+
const vueUrl = import.meta.resolve("vue/dist/vue.esm-browser.js", pathToFileURL(`${config.root}/_`).href);
|
|
179
|
+
const namedExports = extractEsmNamedExports(fs.readFileSync(fileURLToPath(vueUrl), "utf8"));
|
|
180
|
+
vueStubCode = namedExports.length > 0 ? buildVueStubCode(namedExports) : void 0;
|
|
181
|
+
} catch {
|
|
182
|
+
vueStubCode = void 0;
|
|
183
|
+
}
|
|
184
|
+
},
|
|
185
|
+
resolveId(source) {
|
|
186
|
+
if (source === SHIM_ID || source === SHIM_PUBLIC_ID) return SHIM_ID;
|
|
187
|
+
if (source === VUE_STUB_ID || source === VUE_STUB_PUBLIC_ID) return VUE_STUB_ID;
|
|
188
|
+
},
|
|
189
|
+
load(id) {
|
|
190
|
+
if (id === SHIM_ID) return {
|
|
191
|
+
code: __HMR_SHIM_CODE__,
|
|
192
|
+
map: null,
|
|
193
|
+
moduleType: "js"
|
|
194
|
+
};
|
|
195
|
+
if (id === VUE_STUB_ID) return {
|
|
196
|
+
code: vueStubCode ?? VUE_NOT_FOUND_STUB,
|
|
197
|
+
map: null,
|
|
198
|
+
moduleType: "js"
|
|
199
|
+
};
|
|
200
|
+
},
|
|
201
|
+
transform(code, id) {
|
|
202
|
+
if (normalizePath(id.split("?")[0]) !== entryId) return;
|
|
203
|
+
if (code.includes(SHIM_PUBLIC_ID)) return;
|
|
204
|
+
return {
|
|
205
|
+
code: `import ${JSON.stringify(SHIM_ID)}\n${code}`,
|
|
206
|
+
map: null
|
|
207
|
+
};
|
|
208
|
+
},
|
|
209
|
+
configureServer(server) {
|
|
210
|
+
if (!server.httpServer) return;
|
|
211
|
+
server.httpServer.once("listening", async () => {
|
|
212
|
+
const entryPath = entry.replace(`${config.root}/`, "");
|
|
213
|
+
const baseUrl = getDevBaseUrl(server, config);
|
|
214
|
+
const entryUrl = new URL(entryPath, baseUrl).href;
|
|
215
|
+
const pm = await detectPackageManager(config.root);
|
|
216
|
+
await fsp.writeFile(devIndexPath, getViteProxyModule(entryUrl, pm));
|
|
217
|
+
});
|
|
218
|
+
},
|
|
219
|
+
async closeBundle() {
|
|
220
|
+
await fsp.rm(devIndexPath, { force: true });
|
|
221
|
+
}
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
function getViteProxyModule(entryUrl, packageManager) {
|
|
225
|
+
const pm = packageManager?.name || "npm";
|
|
226
|
+
return `
|
|
227
|
+
try {
|
|
228
|
+
await import("${entryUrl}");
|
|
229
|
+
} catch (error) {
|
|
230
|
+
console.error(
|
|
231
|
+
"[kirbyup] Couldn't connect to the development server at ${entryUrl}. Run \`${pm} run serve\` to start Vite or build the plugin with \`${pm} run build\` so Kirby uses the production version."
|
|
232
|
+
);
|
|
233
|
+
throw error;
|
|
234
|
+
}
|
|
235
|
+
`.trimStart();
|
|
236
|
+
}
|
|
237
|
+
function getDevBaseUrl(server, config) {
|
|
238
|
+
const { address, port } = server.httpServer.address();
|
|
239
|
+
const normalizedOrigin = ensureTrailingSlash(config.server?.origin ?? server.resolvedUrls?.local?.[0] ?? server.resolvedUrls?.network?.[0] ?? resolveOriginFromServerOptions(config.server, port, address));
|
|
240
|
+
const base = config.base ?? "/";
|
|
241
|
+
return new URL(base, normalizedOrigin).href;
|
|
242
|
+
}
|
|
243
|
+
//#endregion
|
|
244
|
+
//#region src/node/utils.ts
|
|
245
|
+
const compress = promisify(gzip);
|
|
246
|
+
function toArray(array) {
|
|
247
|
+
array ??= [];
|
|
248
|
+
return Array.isArray(array) ? array : [array];
|
|
249
|
+
}
|
|
250
|
+
async function getCompressedSize(code) {
|
|
251
|
+
return ` / gzip: ${((await compress(typeof code === "string" ? code : Buffer.from(code))).length / 1024).toFixed(2)} KiB`;
|
|
252
|
+
}
|
|
253
|
+
async function printFileInfo({ root, outDir, filePath, content, type, maxLength }) {
|
|
254
|
+
const prettyOutDir = `${normalize(relative(root, resolve(root, outDir)))}/`;
|
|
255
|
+
const kibs = content.length / 1024;
|
|
256
|
+
const compressedSize = await getCompressedSize(content);
|
|
257
|
+
const writeColor = type === "chunk" ? colors.cyan : colors.magenta;
|
|
258
|
+
consola.log(colors.white(colors.dim(prettyOutDir)) + writeColor(filePath.padEnd(maxLength + 2)) + colors.dim(`${kibs.toFixed(2)} kB${compressedSize}`));
|
|
259
|
+
}
|
|
260
|
+
//#endregion
|
|
261
|
+
//#region src/node/index.ts
|
|
262
|
+
const DEV_OUTPUT_FILENAME = "index.dev.js";
|
|
263
|
+
let resolvedKirbyupConfig;
|
|
264
|
+
let resolvedPostCssConfig;
|
|
265
|
+
const logLevel = "warn";
|
|
266
|
+
const logger = createLogger(logLevel);
|
|
267
|
+
const loggerWarn = logger.warn;
|
|
268
|
+
logger.warn = (msg, options) => {
|
|
269
|
+
if (msg.includes("(!) build.outDir")) return;
|
|
270
|
+
loggerWarn(msg, options);
|
|
271
|
+
};
|
|
272
|
+
function getViteConfig(command, options) {
|
|
273
|
+
const aliasDir = resolve(options.cwd, dirname(options.entry));
|
|
274
|
+
const { alias = {}, vite } = resolvedKirbyupConfig;
|
|
275
|
+
const userConfig = vite ?? {};
|
|
276
|
+
const sharedConfig = {
|
|
277
|
+
resolve: { alias: {
|
|
278
|
+
"~/": `${aliasDir}/`,
|
|
279
|
+
"@/": `${aliasDir}/`,
|
|
280
|
+
...alias
|
|
281
|
+
} },
|
|
282
|
+
plugins: [vuePlugin({ compiler: vueCompilerSfc }), vueJsxPlugin()],
|
|
283
|
+
build: { copyPublicDir: false },
|
|
284
|
+
...resolvedPostCssConfig && { css: { postcss: resolvedPostCssConfig } },
|
|
285
|
+
envDir: options.cwd,
|
|
286
|
+
envPrefix: ["VITE_", "KIRBYUP_"],
|
|
287
|
+
customLogger: logger,
|
|
288
|
+
logLevel
|
|
289
|
+
};
|
|
290
|
+
if (command === "serve") {
|
|
291
|
+
const { port, watch } = options;
|
|
292
|
+
const inferredOrigin = userConfig.server?.origin ?? resolveOriginFromServerOptions(userConfig.server, port, "localhost");
|
|
293
|
+
return mergeConfig(mergeConfig(sharedConfig, {
|
|
294
|
+
plugins: [kirbyupHmrPlugin(options), watch && fullReloadPlugin(watch)].filter(Boolean),
|
|
295
|
+
build: { rollupOptions: { input: resolve(options.cwd, options.entry) } },
|
|
296
|
+
server: {
|
|
297
|
+
port,
|
|
298
|
+
strictPort: true,
|
|
299
|
+
origin: inferredOrigin,
|
|
300
|
+
cors: true
|
|
301
|
+
}
|
|
302
|
+
}), userConfig);
|
|
303
|
+
}
|
|
304
|
+
const mode = options.watch ? "development" : "production";
|
|
305
|
+
return mergeConfig(mergeConfig(sharedConfig, {
|
|
306
|
+
mode,
|
|
307
|
+
plugins: [kirbyupBuildCleanupPlugin(options)],
|
|
308
|
+
build: {
|
|
309
|
+
lib: {
|
|
310
|
+
entry: resolve(options.cwd, options.entry),
|
|
311
|
+
formats: ["es"],
|
|
312
|
+
fileName: () => options.watch ? DEV_OUTPUT_FILENAME : "index.js"
|
|
313
|
+
},
|
|
314
|
+
minify: mode === "production",
|
|
315
|
+
outDir: options.outDir,
|
|
316
|
+
emptyOutDir: false,
|
|
317
|
+
rollupOptions: {
|
|
318
|
+
external: ["vue"],
|
|
319
|
+
output: { assetFileNames: "index.[ext]" }
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
}), userConfig);
|
|
323
|
+
}
|
|
324
|
+
async function generate(options) {
|
|
325
|
+
const config = getViteConfig("build", options);
|
|
326
|
+
let result;
|
|
327
|
+
try {
|
|
328
|
+
result = await build(config);
|
|
329
|
+
} catch (error) {
|
|
330
|
+
if (config.mode === "production") throw error;
|
|
331
|
+
else consola.error(error);
|
|
332
|
+
}
|
|
333
|
+
if (result && !options.watch) {
|
|
334
|
+
const { output } = toArray(result)[0];
|
|
335
|
+
let maxLength = 0;
|
|
336
|
+
for (const chunkFile in output) {
|
|
337
|
+
const fileNameLength = output[chunkFile].fileName.length;
|
|
338
|
+
if (fileNameLength > maxLength) maxLength = fileNameLength;
|
|
339
|
+
}
|
|
340
|
+
for (const { fileName, type, code } of output) {
|
|
341
|
+
const content = code || await fsp.readFile(resolve(options.outDir, fileName), "utf8");
|
|
342
|
+
await printFileInfo({
|
|
343
|
+
root: options.cwd,
|
|
344
|
+
outDir: options.outDir,
|
|
345
|
+
filePath: fileName,
|
|
346
|
+
content,
|
|
347
|
+
type,
|
|
348
|
+
maxLength
|
|
349
|
+
});
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
return result;
|
|
353
|
+
}
|
|
354
|
+
async function build$1(options) {
|
|
355
|
+
assertEntryExists(options);
|
|
356
|
+
const { cwd } = options;
|
|
357
|
+
const { config, configFile } = await loadConfig$1(cwd);
|
|
358
|
+
resolvedKirbyupConfig = config ?? {};
|
|
359
|
+
resolvedPostCssConfig = await resolvePostCSSConfig(cwd);
|
|
360
|
+
consola.log(colors.green(`${name} v${version}`));
|
|
361
|
+
consola.start(`Building ${colors.cyan(options.entry)}`);
|
|
362
|
+
if (options.watch) consola.info("Running in watch mode");
|
|
363
|
+
await generate(options);
|
|
364
|
+
consola.success("Build successful");
|
|
365
|
+
if (!options.watch) return;
|
|
366
|
+
const { watch } = await import("chokidar");
|
|
367
|
+
const debouncedBuild = debounce(async () => {
|
|
368
|
+
generate(options).catch(handleError);
|
|
369
|
+
}, 100);
|
|
370
|
+
const ignored = [
|
|
371
|
+
"**/{.git,node_modules}/**",
|
|
372
|
+
"index.{css,js}",
|
|
373
|
+
DEV_OUTPUT_FILENAME
|
|
374
|
+
];
|
|
375
|
+
const watchPaths = typeof options.watch === "boolean" ? dirname(options.entry) : Array.isArray(options.watch) ? options.watch.filter((path) => typeof path === "string") : options.watch;
|
|
376
|
+
consola.info(`Watching for changes in ${toArray(watchPaths).map((i) => colors.cyan(i)).join(", ")}`);
|
|
377
|
+
const watcher = watch(watchPaths, {
|
|
378
|
+
ignoreInitial: true,
|
|
379
|
+
ignorePermissionErrors: true,
|
|
380
|
+
ignored,
|
|
381
|
+
cwd
|
|
382
|
+
});
|
|
383
|
+
const devOutputPath = resolve(options.outDir, DEV_OUTPUT_FILENAME);
|
|
384
|
+
const cleanup = async () => {
|
|
385
|
+
await watcher.close().catch(() => {});
|
|
386
|
+
await fsp.rm(devOutputPath, { force: true }).catch(() => {});
|
|
387
|
+
};
|
|
388
|
+
process.once("exit", () => {
|
|
389
|
+
try {
|
|
390
|
+
fs.rmSync(devOutputPath, { force: true });
|
|
391
|
+
} catch {}
|
|
392
|
+
});
|
|
393
|
+
const onShutdown = () => void cleanup().finally(() => process.exit(0));
|
|
394
|
+
process.once("SIGINT", onShutdown);
|
|
395
|
+
process.once("SIGTERM", onShutdown);
|
|
396
|
+
if (configFile) watcher.add(configFile);
|
|
397
|
+
watcher.on("all", async (type, file) => {
|
|
398
|
+
if (configFile === resolve(cwd, file)) {
|
|
399
|
+
resolvedKirbyupConfig = (await loadConfig$1(cwd)).config ?? {};
|
|
400
|
+
consola.info(`${colors.cyan(basename(file))} changed, setting new config`);
|
|
401
|
+
} else consola.log(`${colors.green(type)} ${colors.white(colors.dim(file))}`);
|
|
402
|
+
debouncedBuild();
|
|
403
|
+
});
|
|
404
|
+
}
|
|
405
|
+
async function serve(options) {
|
|
406
|
+
assertEntryExists(options);
|
|
407
|
+
const { cwd } = options;
|
|
408
|
+
const { config } = await loadConfig$1(cwd);
|
|
409
|
+
resolvedKirbyupConfig = config ?? {};
|
|
410
|
+
resolvedPostCssConfig = await resolvePostCSSConfig(cwd);
|
|
411
|
+
consola.log(colors.green(`${name} v${version}`));
|
|
412
|
+
consola.info("Starting development server…");
|
|
413
|
+
const server = await createServer(getViteConfig("serve", options));
|
|
414
|
+
await server.listen();
|
|
415
|
+
consola.success(`Server is listening on :${server.config.server.port}`);
|
|
416
|
+
return server;
|
|
417
|
+
}
|
|
418
|
+
function assertEntryExists(options) {
|
|
419
|
+
if (!fs.existsSync(resolve(options.cwd, options.entry))) throw new PrettyError(`Cannot find "${options.entry}"`);
|
|
420
|
+
}
|
|
421
|
+
//#endregion
|
|
422
|
+
export { version as a, name as i, serve as n, handleError as r, build$1 as t };
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kirbyup",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "4.0.0-alpha.
|
|
5
|
-
"packageManager": "pnpm@10.
|
|
4
|
+
"version": "4.0.0-alpha.6",
|
|
5
|
+
"packageManager": "pnpm@10.33.3",
|
|
6
6
|
"description": "Zero-config bundler for Kirby Panel plugins",
|
|
7
7
|
"author": {
|
|
8
8
|
"name": "Johann Schopplich",
|
|
@@ -57,7 +57,7 @@
|
|
|
57
57
|
"dist"
|
|
58
58
|
],
|
|
59
59
|
"engines": {
|
|
60
|
-
"node": ">=
|
|
60
|
+
"node": ">=24"
|
|
61
61
|
},
|
|
62
62
|
"scripts": {
|
|
63
63
|
"build": "tsdown",
|
|
@@ -71,32 +71,34 @@
|
|
|
71
71
|
"test:types": "tsc --noEmit"
|
|
72
72
|
},
|
|
73
73
|
"dependencies": {
|
|
74
|
-
"@vitejs/plugin-vue": "^6.0.
|
|
75
|
-
"@vitejs/plugin-vue-jsx": "^5.1.
|
|
76
|
-
"@vue/compiler-sfc": "^3.5.
|
|
77
|
-
"c12": "^
|
|
78
|
-
"cac": "^
|
|
74
|
+
"@vitejs/plugin-vue": "^6.0.6",
|
|
75
|
+
"@vitejs/plugin-vue-jsx": "^5.1.5",
|
|
76
|
+
"@vue/compiler-sfc": "^3.5.34",
|
|
77
|
+
"c12": "^4.0.0-beta.4",
|
|
78
|
+
"cac": "^7.0.0",
|
|
79
79
|
"chokidar": "^5.0.0",
|
|
80
80
|
"consola": "^3.4.2",
|
|
81
81
|
"magic-string": "^0.30.21",
|
|
82
|
-
"nypm": "^0.6.
|
|
82
|
+
"nypm": "^0.6.6",
|
|
83
83
|
"pathe": "^2.0.3",
|
|
84
|
-
"perfect-debounce": "^2.
|
|
85
|
-
"postcss": "^8.5.
|
|
84
|
+
"perfect-debounce": "^2.1.0",
|
|
85
|
+
"postcss": "^8.5.14",
|
|
86
86
|
"postcss-load-config": "^6.0.1",
|
|
87
|
-
"sass": "^1.
|
|
88
|
-
"vite": "^
|
|
87
|
+
"sass": "^1.99.0",
|
|
88
|
+
"vite": "^8.0.10",
|
|
89
89
|
"vite-plugin-full-reload": "^1.2.0",
|
|
90
|
-
"vue": "^3.5.
|
|
90
|
+
"vue": "^3.5.34"
|
|
91
91
|
},
|
|
92
92
|
"devDependencies": {
|
|
93
|
-
"@antfu/eslint-config": "^
|
|
94
|
-
"@types/node": "^24.
|
|
95
|
-
"bumpp": "^
|
|
96
|
-
"eslint": "^
|
|
97
|
-
"
|
|
98
|
-
"
|
|
99
|
-
"
|
|
100
|
-
"
|
|
93
|
+
"@antfu/eslint-config": "^8.2.0",
|
|
94
|
+
"@types/node": "^24.12.2",
|
|
95
|
+
"bumpp": "^11.0.1",
|
|
96
|
+
"eslint": "^10.3.0",
|
|
97
|
+
"eslint-flat-config-utils": "^3.2.0",
|
|
98
|
+
"tinyglobby": "^0.2.16",
|
|
99
|
+
"tsdown": "^0.21.10",
|
|
100
|
+
"typescript": "^6.0.3",
|
|
101
|
+
"unplugin-raw": "^0.7.0",
|
|
102
|
+
"vitest": "^4.1.5"
|
|
101
103
|
}
|
|
102
104
|
}
|
package/dist/node-GoJ-fFA1.mjs
DELETED
|
@@ -1,538 +0,0 @@
|
|
|
1
|
-
import * as fs from "node:fs";
|
|
2
|
-
import * as fsp from "node:fs/promises";
|
|
3
|
-
import vuePlugin from "@vitejs/plugin-vue";
|
|
4
|
-
import vueJsxPlugin from "@vitejs/plugin-vue-jsx";
|
|
5
|
-
import { consola } from "consola";
|
|
6
|
-
import { colors } from "consola/utils";
|
|
7
|
-
import { basename, dirname, normalize, relative, resolve } from "pathe";
|
|
8
|
-
import { debounce } from "perfect-debounce";
|
|
9
|
-
import { build, createLogger, mergeConfig } from "vite";
|
|
10
|
-
import fullReloadPlugin from "vite-plugin-full-reload";
|
|
11
|
-
import * as vueCompilerSfc from "vue/compiler-sfc";
|
|
12
|
-
import { loadConfig } from "c12";
|
|
13
|
-
import postcssrc from "postcss-load-config";
|
|
14
|
-
import { detectPackageManager } from "nypm";
|
|
15
|
-
import { Buffer } from "node:buffer";
|
|
16
|
-
import { promisify } from "node:util";
|
|
17
|
-
import { gzip } from "node:zlib";
|
|
18
|
-
|
|
19
|
-
//#region package.json
|
|
20
|
-
var name = "kirbyup";
|
|
21
|
-
var version = "4.0.0-alpha.4";
|
|
22
|
-
|
|
23
|
-
//#endregion
|
|
24
|
-
//#region src/node/config.ts
|
|
25
|
-
function loadConfig$1(cwd = process.cwd()) {
|
|
26
|
-
return loadConfig({
|
|
27
|
-
cwd,
|
|
28
|
-
name: "kirbyup",
|
|
29
|
-
rcFile: false,
|
|
30
|
-
packageJson: false
|
|
31
|
-
});
|
|
32
|
-
}
|
|
33
|
-
async function resolvePostCSSConfig(cwd) {
|
|
34
|
-
try {
|
|
35
|
-
return await postcssrc(void 0, void 0, { stopDir: cwd });
|
|
36
|
-
} catch (error) {
|
|
37
|
-
if (!error.message.includes("No PostCSS Config found")) throw error;
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
//#endregion
|
|
42
|
-
//#region src/node/errors.ts
|
|
43
|
-
var PrettyError = class extends Error {
|
|
44
|
-
constructor(message) {
|
|
45
|
-
super(message);
|
|
46
|
-
this.name = this.constructor.name;
|
|
47
|
-
if (typeof Error.captureStackTrace === "function") Error.captureStackTrace(this, this.constructor);
|
|
48
|
-
else this.stack = new Error(message).stack;
|
|
49
|
-
}
|
|
50
|
-
};
|
|
51
|
-
function handleError(error) {
|
|
52
|
-
consola.error(error.message);
|
|
53
|
-
process.exitCode = 1;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
//#endregion
|
|
57
|
-
//#region src/node/plugins/build-cleanup.ts
|
|
58
|
-
function kirbyupBuildCleanupPlugin(options) {
|
|
59
|
-
let config;
|
|
60
|
-
let devIndexPath;
|
|
61
|
-
return {
|
|
62
|
-
name: "kirbyup:build-cleanup",
|
|
63
|
-
configResolved(resolvedConfig) {
|
|
64
|
-
config = resolvedConfig;
|
|
65
|
-
devIndexPath = resolve(config.root, options.outDir, "index.dev.mjs");
|
|
66
|
-
},
|
|
67
|
-
writeBundle() {
|
|
68
|
-
if (fs.existsSync(devIndexPath)) fs.unlinkSync(devIndexPath);
|
|
69
|
-
}
|
|
70
|
-
};
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
//#endregion
|
|
74
|
-
//#region src/node/plugins/utils.ts
|
|
75
|
-
/**
|
|
76
|
-
* This code is injected into Vue 3 components to wrap the global HMR runtime.
|
|
77
|
-
*
|
|
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.
|
|
81
|
-
*
|
|
82
|
-
* In Vue 3, the HMR map structure is:
|
|
83
|
-
* ```js
|
|
84
|
-
* {
|
|
85
|
-
* [id]: { initialDef: ComponentDefinition, instances: Set<ComponentInstance> }
|
|
86
|
-
* }
|
|
87
|
-
* ```
|
|
88
|
-
*
|
|
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()`.
|
|
108
|
-
*
|
|
109
|
-
* `$_applyKirbyModifications()`:
|
|
110
|
-
*
|
|
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
|
|
115
|
-
*
|
|
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.
|
|
119
|
-
*
|
|
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.
|
|
122
|
-
*/
|
|
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;
|
|
127
|
-
|
|
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
|
-
}
|
|
158
|
-
|
|
159
|
-
function $_syncKirbyComponent(id, activeDef) {
|
|
160
|
-
const pluginComponents = window.panel?.plugins?.components;
|
|
161
|
-
const usedComponentDefs = window.panel?.app?.config?.globalProperties?.$root?.$options?.components;
|
|
162
|
-
|
|
163
|
-
if (!pluginComponents || !usedComponentDefs) return;
|
|
164
|
-
|
|
165
|
-
const record = $_getHmrRecord(id);
|
|
166
|
-
if (!record) return;
|
|
167
|
-
|
|
168
|
-
for (const componentName in pluginComponents) {
|
|
169
|
-
const pluginComp = pluginComponents[componentName];
|
|
170
|
-
|
|
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);
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
break;
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
function $_applyKirbyModifications(activeDef, newDef) {
|
|
188
|
-
const usedComponentDefs = window.panel?.app?.config?.globalProperties?.$root?.$options?.components;
|
|
189
|
-
|
|
190
|
-
if (!usedComponentDefs) return;
|
|
191
|
-
|
|
192
|
-
// Give templates priority over render functions
|
|
193
|
-
if (newDef.template) {
|
|
194
|
-
newDef.render = null;
|
|
195
|
-
}
|
|
196
|
-
|
|
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
|
-
}
|
|
206
|
-
}
|
|
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
|
-
}
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
/** -- */
|
|
221
|
-
`;
|
|
222
|
-
|
|
223
|
-
//#endregion
|
|
224
|
-
//#region src/node/plugins/hmr.ts
|
|
225
|
-
function kirbyupHmrPlugin(options) {
|
|
226
|
-
let config;
|
|
227
|
-
let entry;
|
|
228
|
-
let devIndexPath;
|
|
229
|
-
return {
|
|
230
|
-
name: "kirbyup:hmr",
|
|
231
|
-
apply: "serve",
|
|
232
|
-
configResolved(resolvedConfig) {
|
|
233
|
-
config = resolvedConfig;
|
|
234
|
-
entry = resolve(config.root, options.entry);
|
|
235
|
-
devIndexPath = resolve(config.root, options.outDir || "", "index.dev.mjs");
|
|
236
|
-
},
|
|
237
|
-
transform(code, id) {
|
|
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
|
-
};
|
|
246
|
-
},
|
|
247
|
-
configureServer(server) {
|
|
248
|
-
if (!server.httpServer) return;
|
|
249
|
-
server.httpServer.once("listening", async () => {
|
|
250
|
-
const entryPath = entry.replace(`${config.root}/`, "");
|
|
251
|
-
const { address, family, port } = server.httpServer.address();
|
|
252
|
-
const baseUrl = `http://${family === "IPv6" ? `[${address}]` : address}:${port}${config.base}`;
|
|
253
|
-
const entryUrl = new URL(entryPath, baseUrl).href;
|
|
254
|
-
const pm = await detectPackageManager(config.root);
|
|
255
|
-
await fsp.writeFile(devIndexPath, getViteProxyModule(entryUrl, pm));
|
|
256
|
-
});
|
|
257
|
-
},
|
|
258
|
-
closeBundle() {
|
|
259
|
-
if (fs.existsSync(devIndexPath)) fs.unlinkSync(devIndexPath);
|
|
260
|
-
}
|
|
261
|
-
};
|
|
262
|
-
}
|
|
263
|
-
/**
|
|
264
|
-
* Proxy the JS file to "forward" the plugin script loaded by Kirby to the Vite server
|
|
265
|
-
*/
|
|
266
|
-
function getViteProxyModule(entryUrl, packageManager) {
|
|
267
|
-
const pm = packageManager?.name || "npm";
|
|
268
|
-
return `
|
|
269
|
-
try {
|
|
270
|
-
await import("${entryUrl}");
|
|
271
|
-
} catch (err) {
|
|
272
|
-
console.error(
|
|
273
|
-
"[kirbyup] Couldn't connect to the development server. Run \`${pm} run serve\` to start Vite or build the plugin with \`${pm} run build\` so Kirby uses the production version."
|
|
274
|
-
);
|
|
275
|
-
throw err;
|
|
276
|
-
}
|
|
277
|
-
`.trimStart();
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
//#endregion
|
|
281
|
-
//#region src/node/plugins/vite-running.ts
|
|
282
|
-
const VITE_RUNNING_FILENAME = ".vite-running";
|
|
283
|
-
function kirbyupRunningMarkerPlugin(options = {}) {
|
|
284
|
-
let config;
|
|
285
|
-
let pluginDir;
|
|
286
|
-
let markerPath;
|
|
287
|
-
let exitCleanupRegistered = false;
|
|
288
|
-
const ensureMarker = async () => {
|
|
289
|
-
if (markerPath) return;
|
|
290
|
-
try {
|
|
291
|
-
const resolvedPath = await ensureViteRunningMarker(pluginDir);
|
|
292
|
-
if (resolvedPath) markerPath = resolvedPath;
|
|
293
|
-
} catch (error) {
|
|
294
|
-
config.logger.warn(`[kirbyup] Failed to write ${VITE_RUNNING_FILENAME}: ${error.message}`);
|
|
295
|
-
}
|
|
296
|
-
};
|
|
297
|
-
const cleanupMarker = async () => {
|
|
298
|
-
if (!markerPath) return;
|
|
299
|
-
try {
|
|
300
|
-
await removeViteRunningMarker(markerPath);
|
|
301
|
-
} catch (error) {
|
|
302
|
-
config.logger.warn(`[kirbyup] Failed to remove ${VITE_RUNNING_FILENAME}: ${error.message}`);
|
|
303
|
-
} finally {
|
|
304
|
-
markerPath = void 0;
|
|
305
|
-
}
|
|
306
|
-
};
|
|
307
|
-
const registerProcessCleanup = () => {
|
|
308
|
-
if (exitCleanupRegistered) return;
|
|
309
|
-
exitCleanupRegistered = true;
|
|
310
|
-
process.once("exit", () => {
|
|
311
|
-
if (markerPath && fs.existsSync(markerPath)) try {
|
|
312
|
-
fs.rmSync(markerPath, { force: true });
|
|
313
|
-
} catch {}
|
|
314
|
-
});
|
|
315
|
-
};
|
|
316
|
-
return {
|
|
317
|
-
name: "kirbyup:vite-running",
|
|
318
|
-
configResolved(resolved) {
|
|
319
|
-
config = resolved;
|
|
320
|
-
pluginDir = resolve(resolved.root, options.outDir || "");
|
|
321
|
-
registerProcessCleanup();
|
|
322
|
-
},
|
|
323
|
-
configureServer(server) {
|
|
324
|
-
server.httpServer?.once("listening", () => ensureMarker());
|
|
325
|
-
server.httpServer?.once("close", () => cleanupMarker());
|
|
326
|
-
},
|
|
327
|
-
buildStart() {
|
|
328
|
-
if (config.command !== "build" || !config.build.watch) return;
|
|
329
|
-
ensureMarker();
|
|
330
|
-
}
|
|
331
|
-
};
|
|
332
|
-
}
|
|
333
|
-
/**
|
|
334
|
-
* Creates the `.vite-running` marker file if the directory is inside `site/plugins/`.
|
|
335
|
-
* Returns `undefined` if the directory is not a Kirby plugin directory.
|
|
336
|
-
*/
|
|
337
|
-
async function ensureViteRunningMarker(targetDir) {
|
|
338
|
-
if (!isInsideKirbyPlugins(targetDir)) return;
|
|
339
|
-
const markerPath = resolve(targetDir, VITE_RUNNING_FILENAME);
|
|
340
|
-
await fsp.writeFile(markerPath, "", "utf8");
|
|
341
|
-
return markerPath;
|
|
342
|
-
}
|
|
343
|
-
/**
|
|
344
|
-
* Removes the `.vite-running` marker file.
|
|
345
|
-
*/
|
|
346
|
-
async function removeViteRunningMarker(markerPath) {
|
|
347
|
-
if (!markerPath) return;
|
|
348
|
-
await fsp.rm(markerPath, { force: true });
|
|
349
|
-
}
|
|
350
|
-
/**
|
|
351
|
-
* Checks if a directory is inside a Kirby plugin directory (`site/plugins/*`).
|
|
352
|
-
* This is used to determine whether to create the `.vite-running` marker file,
|
|
353
|
-
* which Kirby 6+ uses to detect development mode and load the development
|
|
354
|
-
* build of Vue instead of the production build.
|
|
355
|
-
*/
|
|
356
|
-
function isInsideKirbyPlugins(targetDir) {
|
|
357
|
-
const initialDir = normalize(targetDir);
|
|
358
|
-
let currentDir = initialDir;
|
|
359
|
-
while (true) {
|
|
360
|
-
const parentDir = dirname(currentDir);
|
|
361
|
-
if (currentDir !== initialDir && isPathSegmentEqual(basename(currentDir), "plugins") && isPathSegmentEqual(basename(parentDir), "site")) return true;
|
|
362
|
-
if (currentDir === parentDir) return false;
|
|
363
|
-
currentDir = parentDir;
|
|
364
|
-
}
|
|
365
|
-
}
|
|
366
|
-
/**
|
|
367
|
-
* Performs case-insensitive comparison of path segments.
|
|
368
|
-
*/
|
|
369
|
-
function isPathSegmentEqual(segment, expected) {
|
|
370
|
-
return segment.toLowerCase() === expected;
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
//#endregion
|
|
374
|
-
//#region src/node/utils.ts
|
|
375
|
-
const compress = promisify(gzip);
|
|
376
|
-
function toArray(array) {
|
|
377
|
-
array ??= [];
|
|
378
|
-
return Array.isArray(array) ? array : [array];
|
|
379
|
-
}
|
|
380
|
-
async function getCompressedSize(code) {
|
|
381
|
-
return ` / gzip: ${((await compress(typeof code === "string" ? code : Buffer.from(code))).length / 1024).toFixed(2)} KiB`;
|
|
382
|
-
}
|
|
383
|
-
async function printFileInfo({ root, outDir, filePath, content, type, maxLength }) {
|
|
384
|
-
const prettyOutDir = `${normalize(relative(root, resolve(root, outDir)))}/`;
|
|
385
|
-
const kibs = content.length / 1024;
|
|
386
|
-
const compressedSize = await getCompressedSize(content);
|
|
387
|
-
const writeColor = type === "chunk" ? colors.cyan : colors.magenta;
|
|
388
|
-
consola.log(colors.white(colors.dim(prettyOutDir)) + writeColor(filePath.padEnd(maxLength + 2)) + colors.dim(`${kibs.toFixed(2)} kB${compressedSize}`));
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
//#endregion
|
|
392
|
-
//#region src/node/index.ts
|
|
393
|
-
let resolvedKirbyupConfig;
|
|
394
|
-
let resolvedPostCssConfig;
|
|
395
|
-
const logLevel = "warn";
|
|
396
|
-
const logger = createLogger(logLevel);
|
|
397
|
-
const loggerWarn = logger.warn;
|
|
398
|
-
logger.warn = (msg, options) => {
|
|
399
|
-
if (msg.includes("(!) build.outDir")) return;
|
|
400
|
-
loggerWarn(msg, options);
|
|
401
|
-
};
|
|
402
|
-
function getViteConfig(command, options) {
|
|
403
|
-
const aliasDir = resolve(options.cwd, dirname(options.entry));
|
|
404
|
-
const { alias = {}, vite } = resolvedKirbyupConfig;
|
|
405
|
-
const userConfig = vite ?? {};
|
|
406
|
-
const sharedConfig = {
|
|
407
|
-
resolve: { alias: {
|
|
408
|
-
"~/": `${aliasDir}/`,
|
|
409
|
-
"@/": `${aliasDir}/`,
|
|
410
|
-
...alias
|
|
411
|
-
} },
|
|
412
|
-
plugins: [vuePlugin({ compiler: vueCompilerSfc }), vueJsxPlugin()],
|
|
413
|
-
build: { copyPublicDir: false },
|
|
414
|
-
...resolvedPostCssConfig && { css: { postcss: resolvedPostCssConfig } },
|
|
415
|
-
envDir: options.cwd,
|
|
416
|
-
envPrefix: ["VITE_", "KIRBYUP_"],
|
|
417
|
-
customLogger: logger,
|
|
418
|
-
logLevel
|
|
419
|
-
};
|
|
420
|
-
if (command === "serve") {
|
|
421
|
-
const { port, watch } = options;
|
|
422
|
-
return mergeConfig(mergeConfig(sharedConfig, {
|
|
423
|
-
plugins: [
|
|
424
|
-
kirbyupHmrPlugin(options),
|
|
425
|
-
kirbyupRunningMarkerPlugin({ outDir: options.outDir }),
|
|
426
|
-
watch && fullReloadPlugin(watch)
|
|
427
|
-
].filter(Boolean),
|
|
428
|
-
build: { rollupOptions: { input: resolve(options.cwd, options.entry) } },
|
|
429
|
-
server: {
|
|
430
|
-
port,
|
|
431
|
-
strictPort: true,
|
|
432
|
-
origin: `http://localhost:${port}`
|
|
433
|
-
}
|
|
434
|
-
}), userConfig);
|
|
435
|
-
}
|
|
436
|
-
const mode = options.watch ? "development" : "production";
|
|
437
|
-
return mergeConfig(mergeConfig(sharedConfig, {
|
|
438
|
-
mode,
|
|
439
|
-
plugins: [kirbyupBuildCleanupPlugin(options), options.watch && kirbyupRunningMarkerPlugin({ outDir: options.outDir })].filter(Boolean),
|
|
440
|
-
build: {
|
|
441
|
-
lib: {
|
|
442
|
-
entry: resolve(options.cwd, options.entry),
|
|
443
|
-
formats: ["es"],
|
|
444
|
-
fileName: () => "index.js"
|
|
445
|
-
},
|
|
446
|
-
minify: mode === "production",
|
|
447
|
-
outDir: options.outDir,
|
|
448
|
-
emptyOutDir: false,
|
|
449
|
-
rollupOptions: {
|
|
450
|
-
external: ["vue"],
|
|
451
|
-
output: { assetFileNames: "index.[ext]" }
|
|
452
|
-
}
|
|
453
|
-
}
|
|
454
|
-
}), userConfig);
|
|
455
|
-
}
|
|
456
|
-
async function generate(options) {
|
|
457
|
-
const config = getViteConfig("build", options);
|
|
458
|
-
let result;
|
|
459
|
-
try {
|
|
460
|
-
result = await build(config);
|
|
461
|
-
} catch (error) {
|
|
462
|
-
if (config.mode === "production") throw error;
|
|
463
|
-
else consola.error(error);
|
|
464
|
-
}
|
|
465
|
-
if (result && !options.watch) {
|
|
466
|
-
const { output } = toArray(result)[0];
|
|
467
|
-
let maxLength = 0;
|
|
468
|
-
for (const chunkFile in output) {
|
|
469
|
-
const fileNameLength = output[chunkFile].fileName.length;
|
|
470
|
-
if (fileNameLength > maxLength) maxLength = fileNameLength;
|
|
471
|
-
}
|
|
472
|
-
for (const { fileName, type, code } of output) {
|
|
473
|
-
const content = code || await fsp.readFile(resolve(options.outDir, fileName), "utf8");
|
|
474
|
-
await printFileInfo({
|
|
475
|
-
root: options.cwd,
|
|
476
|
-
outDir: options.outDir,
|
|
477
|
-
filePath: fileName,
|
|
478
|
-
content,
|
|
479
|
-
type,
|
|
480
|
-
maxLength
|
|
481
|
-
});
|
|
482
|
-
}
|
|
483
|
-
}
|
|
484
|
-
return result;
|
|
485
|
-
}
|
|
486
|
-
async function build$1(options) {
|
|
487
|
-
assertEntryExists(options);
|
|
488
|
-
const { cwd } = options;
|
|
489
|
-
const { config, configFile } = await loadConfig$1(cwd);
|
|
490
|
-
resolvedKirbyupConfig = config ?? {};
|
|
491
|
-
resolvedPostCssConfig = await resolvePostCSSConfig(cwd);
|
|
492
|
-
consola.log(colors.green(`${name} v${version}`));
|
|
493
|
-
consola.start(`Building ${colors.cyan(options.entry)}`);
|
|
494
|
-
if (options.watch) consola.info("Running in watch mode");
|
|
495
|
-
const debouncedBuild = debounce(async () => {
|
|
496
|
-
generate(options).catch(handleError);
|
|
497
|
-
}, 100);
|
|
498
|
-
const startWatcher = async () => {
|
|
499
|
-
if (!options.watch) return;
|
|
500
|
-
const { watch } = await import("chokidar");
|
|
501
|
-
const ignored = ["**/{.git,node_modules}/**", "index.{css,js,mjs}"];
|
|
502
|
-
const watchPaths = typeof options.watch === "boolean" ? dirname(options.entry) : Array.isArray(options.watch) ? options.watch.filter((path) => typeof path === "string") : options.watch;
|
|
503
|
-
consola.info(`Watching for changes in ${toArray(watchPaths).map((i) => colors.cyan(i)).join(", ")}`);
|
|
504
|
-
const watcher = watch(watchPaths, {
|
|
505
|
-
ignoreInitial: true,
|
|
506
|
-
ignorePermissionErrors: true,
|
|
507
|
-
ignored,
|
|
508
|
-
cwd
|
|
509
|
-
});
|
|
510
|
-
if (configFile) watcher.add(configFile);
|
|
511
|
-
watcher.on("all", async (type, file) => {
|
|
512
|
-
if (configFile === resolve(cwd, file)) {
|
|
513
|
-
resolvedKirbyupConfig = (await loadConfig$1(cwd)).config ?? {};
|
|
514
|
-
consola.info(`${colors.cyan(basename(file))} changed, setting new config`);
|
|
515
|
-
} else consola.log(`${colors.green(type)} ${colors.white(colors.dim(file))}`);
|
|
516
|
-
debouncedBuild();
|
|
517
|
-
});
|
|
518
|
-
};
|
|
519
|
-
await generate(options);
|
|
520
|
-
consola.success("Build successful");
|
|
521
|
-
startWatcher();
|
|
522
|
-
}
|
|
523
|
-
async function serve(options) {
|
|
524
|
-
assertEntryExists(options);
|
|
525
|
-
const { cwd } = options;
|
|
526
|
-
const { config } = await loadConfig$1(cwd);
|
|
527
|
-
resolvedKirbyupConfig = config ?? {};
|
|
528
|
-
resolvedPostCssConfig = await resolvePostCSSConfig(cwd);
|
|
529
|
-
consola.log(colors.green(`${name} v${version}`));
|
|
530
|
-
consola.info(`Development server unavailable. Use watch mode for now: ${colors.cyan(`kirbyup build ${options.entry} --watch`)}`);
|
|
531
|
-
throw new PrettyError("HMR is not yet implemented for Kirby 6 plugins. Please use watch mode instead.");
|
|
532
|
-
}
|
|
533
|
-
function assertEntryExists(options) {
|
|
534
|
-
if (!fs.existsSync(resolve(options.cwd, options.entry))) throw new PrettyError(`Cannot find "${options.entry}"`);
|
|
535
|
-
}
|
|
536
|
-
|
|
537
|
-
//#endregion
|
|
538
|
-
export { version as a, name as i, serve as n, handleError as r, build$1 as t };
|