kirbyup 4.0.0-alpha.7 → 4.0.0-alpha.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -18,13 +18,13 @@ The official bundler for Kirby Panel plugins. Zero-config, built-in HMR.
18
18
 
19
19
  ## Requirements
20
20
 
21
- - **Node.js 24+**: paired with a package manager (pnpm, npm, or yarn).
22
- - **Kirby 6 or newer**: kirbyup 4.x targets the Vue 3-based Panel runtime introduced in Kirby 6. For Kirby 4 or 5 plugins, use kirbyup 3.x.
21
+ - **Node.js 24 or newer** with pnpm, npm or yarn.
22
+ - **Kirby 6 or newer.** kirbyup 4 builds for the Vue 3 Panel. Plugins for Kirby 4 and 5 stay on kirbyup 3.x, documented at the [last 3.x release](https://github.com/johannschopplich/kirbyup/tree/v3.5.0/docs). Upgrading? Read the [migration guide](https://kirbyup.getkirby.com/guide/migration).
23
23
 
24
24
  ## Setup
25
25
 
26
26
  > [!TIP]
27
- > Skip starting from scratch and pick one of the following starters:
27
+ > Skip the setup with one of the starters:
28
28
  > - [`eslint`](./examples/eslint)
29
29
  > - [`unocss`](./examples/unocss)
30
30
 
@@ -39,16 +39,16 @@ npm i -D kirbyup
39
39
  yarn add -D kirbyup
40
40
  ```
41
41
 
42
- After installation, add these scripts to your `package.json`:
42
+ Add the two scripts to `package.json`:
43
43
 
44
44
  ```json
45
45
  {
46
46
  "scripts": {
47
- "dev": "kirbyup serve src/index.js",
47
+ "dev": "kirbyup dev src/index.js",
48
48
  "build": "kirbyup src/index.js"
49
49
  },
50
50
  "devDependencies": {
51
- "kirbyup": "^4.0.0-alpha.6"
51
+ "kirbyup": "^4.0.0"
52
52
  }
53
53
  }
54
54
  ```
package/bin/kirbyup.mjs CHANGED
@@ -1,3 +1,2 @@
1
1
  #!/usr/bin/env node
2
- 'use strict'
3
- import('../dist/node/cli.mjs')
2
+ import('../dist/node/entry.mjs')
@@ -1,5 +1,4 @@
1
- import { r as UserConfig } from "../types-3hN383nZ.mjs";
2
-
1
+ import { r as UserConfig } from "../types-Dh8QpeYt.mjs";
3
2
  //#region src/client/config.d.ts
4
3
  declare function defineConfig(config: UserConfig): UserConfig;
5
4
  //#endregion
@@ -1,8 +1,7 @@
1
1
  //#region src/client/plugin.ts
2
2
  const kirbyup = Object.freeze({
3
3
  /**
4
- * Auto-import Kirby Panel components, transformed by
5
- * kirbyup's glob-import plugin for Vite.
4
+ * Auto-imports the Kirby Panel components matching a glob.
6
5
  *
7
6
  * @example
8
7
  * kirbyup.import('./components/blocks/*.vue')
@@ -0,0 +1 @@
1
+ export {}
@@ -0,0 +1,400 @@
1
+ import { a as version, c as reportFailure, i as name, l as log_exports, n as serve, o as ArgumentError, r as description, s as CliError, t as build, u as paint } from "../node-noo8EBlY.mjs";
2
+ import { parseArgs, stripVTControlCharacters } from "node:util";
3
+ import process from "node:process";
4
+ //#region node_modules/.pnpm/utilful@3.3.0_vitest@4.1.11_@types+node@26.4.0_vite@8.2.2_@types+node@26.4.0_jiti@2.7.0_sass@1.103.1_yaml@2.9.0__/node_modules/utilful/dist/cli/args.mjs
5
+ const commonArgs = { verbose: {
6
+ type: "boolean",
7
+ description: "Print the cause chain and stack trace on failure"
8
+ } };
9
+ /** Parses `argv` against a definition. An absent boolean reads as `false`, and `--no-<name>` turns one off. */
10
+ function parseArgs$1(argv, argsDef, { allowExtraPositionals = false } = {}) {
11
+ let parseResult;
12
+ try {
13
+ parseResult = parseArgs({
14
+ args: joinNegativeValues(splitShortOptionValues(argv), argsDef),
15
+ options: toNodeOptions(argsDef),
16
+ strict: true,
17
+ allowPositionals: true,
18
+ allowNegative: true
19
+ });
20
+ } catch (error) {
21
+ if (isNodeArgumentError(error)) throw new ArgumentError(error.message.split(". ")[0]);
22
+ throw error;
23
+ }
24
+ const args = { _: parseResult.positionals };
25
+ const positionalNames = [];
26
+ for (const [name, definition] of Object.entries(argsDef)) {
27
+ if (definition.type === "positional") {
28
+ positionalNames.push(name);
29
+ continue;
30
+ }
31
+ const value = parseResult.values[name];
32
+ if (definition.type === "boolean") args[name] = value ?? false;
33
+ else if (value === void 0 && definition.required === true) throw new ArgumentError(`Missing required argument: --${name}`);
34
+ else args[name] = value;
35
+ }
36
+ positionalNames.forEach((name, index) => {
37
+ const definition = argsDef[name];
38
+ const value = parseResult.positionals[index];
39
+ if (value === void 0 && definition.required === true) throw new ArgumentError(`Missing required positional argument: ${name.toUpperCase()}`);
40
+ args[name] = value;
41
+ });
42
+ if (!allowExtraPositionals && parseResult.positionals.length > positionalNames.length) throw new ArgumentError(`Unexpected argument: ${JSON.stringify(parseResult.positionals[positionalNames.length])}`);
43
+ return args;
44
+ }
45
+ function toNodeOptions(argsDef) {
46
+ const options = {};
47
+ for (const [name, definition] of Object.entries(argsDef)) {
48
+ if (definition.type === "positional") continue;
49
+ const option = { type: definition.type };
50
+ if (definition.alias !== void 0) option.short = definition.alias;
51
+ if (definition.default !== void 0) option.default = definition.default;
52
+ options[name] = option;
53
+ }
54
+ return options;
55
+ }
56
+ /**
57
+ * Splits an inline value off a short option. Node's `parseArgs` splits
58
+ * `--name=value` but leaves `-n=value` whole, so `-o=report.json` would write to
59
+ * a file named `=report.json`. Past `--` every token is an operand and stays as
60
+ * it was written.
61
+ */
62
+ function splitShortOptionValues(argv) {
63
+ const splitArguments = [];
64
+ let isTerminated = false;
65
+ for (const argument of argv) {
66
+ const match = /^(-[^-])=(.*)$/.exec(argument);
67
+ if (isTerminated || match === null) {
68
+ splitArguments.push(argument);
69
+ isTerminated ||= argument === "--";
70
+ continue;
71
+ }
72
+ splitArguments.push(match[1], match[2]);
73
+ }
74
+ return splitArguments;
75
+ }
76
+ /**
77
+ * Joins a negative number onto the value-taking option before it, as
78
+ * `--start=-3`. Node refuses `--start -3` as ambiguous, but a token that starts
79
+ * with a digit after its dash is a number wherever a value is due.
80
+ */
81
+ function joinNegativeValues(argv, argsDef) {
82
+ const optionNamesBySpelling = /* @__PURE__ */ new Map();
83
+ for (const [name, definition] of Object.entries(argsDef)) {
84
+ if (definition.type !== "string") continue;
85
+ optionNamesBySpelling.set(`--${name}`, name);
86
+ if (definition.alias !== void 0) optionNamesBySpelling.set(`-${definition.alias}`, name);
87
+ }
88
+ const joinedArguments = [];
89
+ for (let index = 0; index < argv.length; index++) {
90
+ const argument = argv[index];
91
+ const next = argv[index + 1];
92
+ const name = optionNamesBySpelling.get(argument);
93
+ if (argument === "--") {
94
+ joinedArguments.push(...argv.slice(index));
95
+ break;
96
+ }
97
+ if (name !== void 0 && next !== void 0 && /^-\d/.test(next)) {
98
+ joinedArguments.push(`--${name}=${next}`);
99
+ index++;
100
+ continue;
101
+ }
102
+ joinedArguments.push(argument);
103
+ }
104
+ return joinedArguments;
105
+ }
106
+ function isNodeArgumentError(error) {
107
+ return error instanceof Error && String(error.code).startsWith("ERR_PARSE_ARGS");
108
+ }
109
+ //#endregion
110
+ //#region node_modules/.pnpm/utilful@3.3.0_vitest@4.1.11_@types+node@26.4.0_vite@8.2.2_@types+node@26.4.0_jiti@2.7.0_sass@1.103.1_yaml@2.9.0__/node_modules/utilful/dist/cli/usage.mjs
111
+ function renderUsage(command, { parent, stream = process.stdout } = {}) {
112
+ const color = (style, text) => paint(style, text, stream);
113
+ const heading = (title) => color("bold", title);
114
+ const meta = command.meta ?? {};
115
+ const parentMeta = parent?.meta ?? {};
116
+ const commandName = [parentMeta.name, meta.name].filter((name) => name !== void 0).join(" ");
117
+ const version = meta.version ?? parentMeta.version;
118
+ const positionalLines = [];
119
+ const optionLines = [];
120
+ const commandLines = [];
121
+ const usageLine = [];
122
+ for (const [name, definition] of Object.entries(command.args ?? {})) {
123
+ const isRequired = definition.type !== "boolean" && definition.required === true;
124
+ const hasDefault = definition.type !== "positional" && definition.default !== void 0 && definition.default !== false;
125
+ const hints = [
126
+ definition.description,
127
+ isRequired ? color("gray", "(Required)") : void 0,
128
+ hasDefault ? color("gray", `(Default: ${definition.default})`) : void 0
129
+ ].filter((hint) => hint !== void 0).join(" ");
130
+ if (definition.type === "positional") {
131
+ const label = name.toUpperCase();
132
+ positionalLines.push([color("cyan", label), hints]);
133
+ usageLine.push(isRequired ? `<${label}>` : `[${label}]`);
134
+ continue;
135
+ }
136
+ const spellings = [definition.alias === void 0 ? void 0 : `-${definition.alias}`, `--${name}`].filter((spelling) => spelling !== void 0).join(", ");
137
+ const value = definition.type === "string" ? `<${definition.valueHint ?? name}>` : void 0;
138
+ optionLines.push([color("cyan", spellings) + (value === void 0 ? "" : color("dim", `=${value}`)), hints]);
139
+ if (definition.type === "boolean" && definition.default === true) optionLines.push([color("cyan", `--no-${name}`), ""]);
140
+ if (isRequired) usageLine.push(`--${name}=${value}`);
141
+ }
142
+ for (const [name, subCommand] of Object.entries(command.subCommands ?? {})) commandLines.push([color("cyan", name), subCommand.meta?.description ?? ""]);
143
+ const hasArguments = positionalLines.length > 0 || optionLines.length > 0;
144
+ if (commandLines.length > 0 && !hasArguments) usageLine.push(Object.keys(command.subCommands).join("|"));
145
+ const lines = [
146
+ color("bold", version === void 0 ? commandName : `${commandName} v${version}`),
147
+ ...meta.description === void 0 ? [] : [meta.description],
148
+ "",
149
+ `${heading("USAGE")} ${color("cyan", [
150
+ commandName,
151
+ hasArguments ? "[OPTIONS]" : void 0,
152
+ ...usageLine
153
+ ].filter((part) => part !== void 0).join(" "))}`,
154
+ ""
155
+ ];
156
+ for (const [title, rows] of [
157
+ ["ARGUMENTS", positionalLines],
158
+ ["OPTIONS", optionLines],
159
+ ["COMMANDS", commandLines]
160
+ ]) if (rows.length > 0) lines.push(heading(title), "", formatColumns(rows), "");
161
+ if (commandLines.length > 0) lines.push(`Use ${color("cyan", `${commandName} <command> --help`)} for more information about a command.`);
162
+ return lines.join("\n").trimEnd();
163
+ }
164
+ function formatColumns(rows) {
165
+ const widths = rows[0].map((_, column) => Math.max(...rows.map((row) => visibleLength(row[column]))));
166
+ return rows.map((row) => row.map((cell, column) => ` ${cell}${" ".repeat(widths[column] - visibleLength(cell))}`).join("").trimEnd()).join("\n");
167
+ }
168
+ function visibleLength(text) {
169
+ return stripVTControlCharacters(text).length;
170
+ }
171
+ //#endregion
172
+ //#region node_modules/.pnpm/utilful@3.3.0_vitest@4.1.11_@types+node@26.4.0_vite@8.2.2_@types+node@26.4.0_jiti@2.7.0_sass@1.103.1_yaml@2.9.0__/node_modules/utilful/dist/cli/command.mjs
173
+ const HELP_FLAGS = /* @__PURE__ */ new Set(["--help", "-h"]);
174
+ const VERSION_FLAGS = /* @__PURE__ */ new Set(["--version", "-v"]);
175
+ function defineCommand(command) {
176
+ return command;
177
+ }
178
+ /**
179
+ * Runs the command tree and reports whatever it throws. Help someone asked for
180
+ * is the result of the run and goes to stdout; usage that follows a wrong
181
+ * argument is diagnostics and joins its message on stderr.
182
+ */
183
+ async function runMain(command, options = {}) {
184
+ const argv = options.argv ?? process.argv.slice(2);
185
+ const beforeTerminator = argv.slice(0, argv.includes("--") ? argv.indexOf("--") : void 0);
186
+ const hasFlag = (flags) => beforeTerminator.some((argument) => flags.has(argument));
187
+ try {
188
+ if (hasFlag(HELP_FLAGS)) process.stdout.write(`${usageFor(command, argv, process.stdout)}\n`);
189
+ else if (hasFlag(VERSION_FLAGS)) process.stdout.write(`${command.meta?.version ?? ""}\n`);
190
+ else await runCommand(command, argv);
191
+ } catch (error) {
192
+ if (error instanceof ArgumentError) process.stderr.write(`${usageFor(command, argv, process.stderr)}\n\n`);
193
+ const verbose = !(error instanceof ArgumentError) && beforeTerminator.includes("--verbose");
194
+ reportFailure(error, {
195
+ ...options,
196
+ verbose
197
+ });
198
+ }
199
+ }
200
+ /** Runs like `runMain`, but without the error boundary. */
201
+ async function runCommand(command, argv) {
202
+ const { name, firstOperand, rest } = findSubCommand(command, argv);
203
+ if (name !== void 0) return runCommand(command.subCommands[name], rest);
204
+ if (command.subCommands !== void 0 && command.run === void 0) throw new ArgumentError(firstOperand === void 0 ? "Missing command" : `Unknown command: ${firstOperand}`);
205
+ const args = parseArgs$1(rest, command.args ?? {}, { allowExtraPositionals: command.allowExtraPositionals });
206
+ await command.run?.({ args });
207
+ }
208
+ function usageFor(command, argv, stream) {
209
+ const { name } = findSubCommand(command, argv);
210
+ return name === void 0 ? renderUsage(command, { stream }) : renderUsage(command.subCommands[name], {
211
+ parent: command,
212
+ stream
213
+ });
214
+ }
215
+ /**
216
+ * Finds the sub-command the first operand names, wherever it stands among the
217
+ * options. Telling an operand from the value of an option needs every
218
+ * value-taking option of every sub-command, since the command is still unknown.
219
+ */
220
+ function findSubCommand(command, argv) {
221
+ if (command.subCommands === void 0) return { rest: [...argv] };
222
+ const options = Object.assign(toNodeOptions(command.args ?? {}), ...Object.values(command.subCommands).map((subCommand) => toNodeOptions(subCommand.args ?? {})));
223
+ const { tokens } = parseArgs({
224
+ args: [...argv],
225
+ options,
226
+ strict: false,
227
+ allowPositionals: true,
228
+ tokens: true
229
+ });
230
+ const firstOperand = tokens.find((token) => token.kind === "positional" || token.kind === "option-terminator");
231
+ if (firstOperand?.kind !== "positional") return { rest: [...argv] };
232
+ if (Object.hasOwn(command.subCommands, firstOperand.value)) return {
233
+ name: firstOperand.value,
234
+ rest: argv.toSpliced(firstOperand.index, 1)
235
+ };
236
+ return {
237
+ firstOperand: firstOperand.value,
238
+ rest: [...argv]
239
+ };
240
+ }
241
+ //#endregion
242
+ //#region src/node/commands/watch-paths.ts
243
+ const GLOB_CHARACTERS = /[*?[\]{}]/;
244
+ /**
245
+ * Splits a comma-separated `--watch-path` value.
246
+ *
247
+ * `build` hands its paths to chokidar, which has expanded no globs since v4, so
248
+ * a pattern there would watch nothing at all – it is rejected rather than
249
+ * silently ignored. `serve` matches through Vite's own watcher, where globs work.
250
+ */
251
+ function resolveWatchPaths(value, { allowGlobs }) {
252
+ const paths = (value ?? "").split(",").map((path) => path.trim()).filter((path) => path !== "");
253
+ if (!allowGlobs) {
254
+ const pattern = paths.find((path) => GLOB_CHARACTERS.test(path));
255
+ if (pattern !== void 0) throw new CliError(`--watch-path takes files and folders, not patterns: ${pattern}\nName the folder instead – it is watched recursively.`);
256
+ }
257
+ return paths;
258
+ }
259
+ //#endregion
260
+ //#region src/node/commands/build.ts
261
+ const buildArgs = {
262
+ ...commonArgs,
263
+ "file": {
264
+ type: "positional",
265
+ description: "Entry file of the plugin",
266
+ required: true
267
+ },
268
+ "out-dir": {
269
+ type: "string",
270
+ alias: "d",
271
+ description: "Output directory",
272
+ valueHint: "dir"
273
+ },
274
+ "watch": {
275
+ type: "boolean",
276
+ alias: "w",
277
+ description: "Rebuild when the folder of the entry file changes"
278
+ },
279
+ "watch-path": {
280
+ type: "string",
281
+ description: "Comma-separated files and folders to watch instead",
282
+ valueHint: "paths"
283
+ }
284
+ };
285
+ const buildCommand = defineCommand({
286
+ meta: {
287
+ name: "build",
288
+ description: "Compile the Kirby Panel plugin to index.js and index.css"
289
+ },
290
+ args: buildArgs,
291
+ async run({ args }) {
292
+ const cwd = process.cwd();
293
+ const paths = resolveWatchPaths(args["watch-path"], { allowGlobs: false });
294
+ const watch = paths.length > 0 ? paths : args.watch;
295
+ process.env.NODE_ENV ||= watch === false ? "production" : "development";
296
+ await build({
297
+ cwd,
298
+ entry: args.file,
299
+ outDir: args["out-dir"] ?? cwd,
300
+ watch
301
+ });
302
+ }
303
+ });
304
+ //#endregion
305
+ //#region src/node/commands/dev.ts
306
+ const DEFAULT_PORT = 5177;
307
+ const DEFAULT_WATCH = "./**/*.php";
308
+ const devArgs = {
309
+ ...commonArgs,
310
+ "file": {
311
+ type: "positional",
312
+ description: "Entry file of the plugin",
313
+ required: true
314
+ },
315
+ "out-dir": {
316
+ type: "string",
317
+ alias: "d",
318
+ description: "Output directory",
319
+ valueHint: "dir"
320
+ },
321
+ "watch": {
322
+ type: "boolean",
323
+ alias: "w",
324
+ default: true,
325
+ description: "Reload the Panel when a watched file changes"
326
+ },
327
+ "watch-path": {
328
+ type: "string",
329
+ default: DEFAULT_WATCH,
330
+ description: "Comma-separated files, folders and globs to watch",
331
+ valueHint: "paths"
332
+ },
333
+ "port": {
334
+ type: "string",
335
+ alias: "p",
336
+ default: String(DEFAULT_PORT),
337
+ description: "Port for the development server"
338
+ }
339
+ };
340
+ async function run({ args }) {
341
+ process.env.NODE_ENV ||= "development";
342
+ const paths = resolveWatchPaths(args["watch-path"], { allowGlobs: true });
343
+ const server = await serve({
344
+ cwd: process.cwd(),
345
+ entry: args.file,
346
+ outDir: args["out-dir"] ?? process.cwd(),
347
+ watch: args.watch && paths.length > 0 ? paths : false,
348
+ port: parsePort(args.port)
349
+ });
350
+ process.once("SIGINT", async () => {
351
+ try {
352
+ await server.close();
353
+ } finally {
354
+ process.exit();
355
+ }
356
+ });
357
+ }
358
+ const devCommand = defineCommand({
359
+ meta: {
360
+ name: "dev",
361
+ description: "Start a development server with live reload"
362
+ },
363
+ args: devArgs,
364
+ run
365
+ });
366
+ const serveCommand = defineCommand({
367
+ meta: {
368
+ name: "serve",
369
+ description: "Former name of dev, kept so existing scripts keep working"
370
+ },
371
+ args: devArgs,
372
+ async run(context) {
373
+ log_exports.info("`kirbyup serve` is now `kirbyup dev`.");
374
+ await run(context);
375
+ }
376
+ });
377
+ /** The parser knows strings and booleans only, so the port arrives as a string. */
378
+ function parsePort(value) {
379
+ const port = Number(value);
380
+ if (!Number.isInteger(port) || port < 1 || port > 65535) throw new CliError(`Not a usable port: ${JSON.stringify(value)}`);
381
+ return port;
382
+ }
383
+ //#endregion
384
+ //#region src/node/entry.ts
385
+ runMain(defineCommand({
386
+ meta: {
387
+ name,
388
+ version,
389
+ description: `${description}. An entry file on its own builds it: kirbyup src/index.js`
390
+ },
391
+ args: buildArgs,
392
+ subCommands: {
393
+ build: buildCommand,
394
+ dev: devCommand,
395
+ serve: serveCommand
396
+ },
397
+ run: buildCommand.run
398
+ }));
399
+ //#endregion
400
+ export {};
@@ -1,6 +1,5 @@
1
- import { n as ServeOptions, t as BuildOptions } from "../types-3hN383nZ.mjs";
1
+ import { n as ServeOptions, t as BuildOptions } from "../types-Dh8QpeYt.mjs";
2
2
  import { ViteDevServer } from "vite";
3
-
4
3
  //#region src/node/index.d.ts
5
4
  declare function build(options: BuildOptions): Promise<void>;
6
5
  declare function serve(options: ServeOptions): Promise<ViteDevServer>;
@@ -1,2 +1,2 @@
1
- import { n as serve, t as build } from "../node-BAAmufwc.mjs";
1
+ import { n as serve, t as build } from "../node-noo8EBlY.mjs";
2
2
  export { build, serve };
@@ -1,22 +1,99 @@
1
1
  import * as fs from "node:fs";
2
2
  import * as fsp from "node:fs/promises";
3
+ import { basename, dirname, relative, resolve } from "node:path";
3
4
  import vuePlugin from "@vitejs/plugin-vue";
4
5
  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
6
  import { debounce } from "perfect-debounce";
7
+ import { styleText } from "node:util";
8
+ import process$1 from "node:process";
9
9
  import { build, createFilter, createLogger, createServer, mergeConfig, normalizePath } from "vite";
10
- import * as vueCompilerSfc from "vue/compiler-sfc";
11
10
  import { loadConfig } from "c12";
12
- import postcssrcLoad from "postcss-load-config";
11
+ import { WriteStream } from "node:tty";
13
12
  import { gzipSync } from "node:zlib";
13
+ import { Ansis } from "ansis";
14
14
  import MagicString from "magic-string";
15
15
  import { stripLiteral } from "strip-literal";
16
16
  import { isIP } from "node:net";
17
- //#region package.json
18
- var name = "kirbyup";
19
- var version = "4.0.0-alpha.7";
17
+ //#region node_modules/.pnpm/utilful@3.3.0_vitest@4.1.11_@types+node@26.4.0_vite@8.2.2_@types+node@26.4.0_jiti@2.7.0_sass@1.103.1_yaml@2.9.0__/node_modules/utilful/dist/_virtual/_rolldown/runtime.mjs
18
+ var __defProp = Object.defineProperty;
19
+ var __exportAll = (all, no_symbols) => {
20
+ let target = {};
21
+ for (var name in all) __defProp(target, name, {
22
+ get: all[name],
23
+ enumerable: true
24
+ });
25
+ if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
26
+ return target;
27
+ };
28
+ //#endregion
29
+ //#region node_modules/.pnpm/utilful@3.3.0_vitest@4.1.11_@types+node@26.4.0_vite@8.2.2_@types+node@26.4.0_jiti@2.7.0_sass@1.103.1_yaml@2.9.0__/node_modules/utilful/dist/cli/style.mjs
30
+ function paint(style, text, stream) {
31
+ return styleText(style, text, { stream });
32
+ }
33
+ //#endregion
34
+ //#region node_modules/.pnpm/utilful@3.3.0_vitest@4.1.11_@types+node@26.4.0_vite@8.2.2_@types+node@26.4.0_jiti@2.7.0_sass@1.103.1_yaml@2.9.0__/node_modules/utilful/dist/cli/log.mjs
35
+ var log_exports = /* @__PURE__ */ __exportAll({
36
+ blankLine: () => blankLine$1,
37
+ error: () => error,
38
+ info: () => info,
39
+ success: () => success,
40
+ warn: () => warn
41
+ });
42
+ function error(message) {
43
+ console.error(`${paint("red", "✖", process$1.stderr)} ${message}`);
44
+ }
45
+ function warn(message) {
46
+ console.error(`${paint("yellow", "⚠", process$1.stderr)} ${message}`);
47
+ }
48
+ function info(message) {
49
+ console.error(`${paint("cyan", "●", process$1.stderr)} ${message}`);
50
+ }
51
+ function success(message) {
52
+ console.error(`${paint("green", "✔", process$1.stderr)} ${message}`);
53
+ }
54
+ function blankLine$1() {
55
+ console.error("");
56
+ }
57
+ //#endregion
58
+ //#region node_modules/.pnpm/utilful@3.3.0_vitest@4.1.11_@types+node@26.4.0_vite@8.2.2_@types+node@26.4.0_jiti@2.7.0_sass@1.103.1_yaml@2.9.0__/node_modules/utilful/dist/cli/errors.mjs
59
+ /**
60
+ * A condition the CLI recognized and phrased for a human. Anything else
61
+ * reaching the boundary is a defect in the tool and prints its stack unasked.
62
+ */
63
+ var CliError = class extends Error {};
64
+ /** Gets usage printed alongside its message. */
65
+ var ArgumentError = class extends CliError {};
66
+ /** Reports a failure the way the boundary does, for one that outlives `run`, such as a watch rebuild. */
67
+ function reportFailure(error$1, { verbose = false, expectedErrors = [], describe } = {}) {
68
+ const sections = [error$1 instanceof Error ? describe?.(error$1) ?? error$1.message : String(error$1)];
69
+ if (verbose || !isExpected(error$1, expectedErrors)) {
70
+ const causeChain = formatCauseChain(error$1);
71
+ if (causeChain) sections.push(causeChain);
72
+ if (error$1 instanceof Error && error$1.stack) sections.push(error$1.stack);
73
+ }
74
+ error(sections.join("\n\n"));
75
+ process$1.exitCode = 1;
76
+ }
77
+ /**
78
+ * Reports whether the CLI raised this error deliberately rather than tripping
79
+ * over it. A system error such as `ENOENT` reaches the boundary as the honest
80
+ * answer to what the user asked for, so it reads as deliberate too, while an
81
+ * `ERR_*` error from a Node API is a wrong call and stays a defect.
82
+ */
83
+ function isExpected(error, expectedErrors) {
84
+ if (error instanceof CliError) return true;
85
+ if (expectedErrors.some((expectedError) => error instanceof expectedError)) return true;
86
+ return error instanceof Error && /^E[A-Z0-9]+$/.test(String(error.code));
87
+ }
88
+ function formatCauseChain(error) {
89
+ const causeLines = [];
90
+ let current = error instanceof Error ? error.cause : void 0;
91
+ while (current instanceof Error) {
92
+ causeLines.push(`Caused by: ${current.name || "Error"}: ${current.message}`);
93
+ current = current.cause;
94
+ }
95
+ return causeLines.join("\n");
96
+ }
20
97
  //#endregion
21
98
  //#region src/node/config.ts
22
99
  function loadConfig$1(cwd = process.cwd()) {
@@ -27,37 +104,91 @@ function loadConfig$1(cwd = process.cwd()) {
27
104
  packageJson: false
28
105
  });
29
106
  }
30
- async function resolvePostCSSConfig(cwd) {
31
- try {
32
- return await postcssrcLoad(void 0, void 0, { stopDir: cwd });
33
- } catch (error) {
34
- if (!error.message.includes("No PostCSS Config found")) throw error;
35
- }
36
- }
37
107
  //#endregion
38
- //#region src/node/errors.ts
39
- var PrettyError = class extends Error {
40
- constructor(message) {
41
- super(message);
42
- this.name = this.constructor.name;
43
- Error.captureStackTrace(this, this.constructor);
44
- }
45
- };
46
- function handleError(error) {
47
- consola.error(error.message);
48
- process.exitCode = 1;
108
+ //#region package.json
109
+ var name = "kirbyup";
110
+ var version = "4.0.0-alpha.9";
111
+ var description = "Zero-config bundler for Kirby Panel plugins";
112
+ //#endregion
113
+ //#region src/node/output.ts
114
+ /**
115
+ * Follows the rule `styleText` applies, so this output and utilful's `log`
116
+ * agree: a terminal or `FORCE_COLOR`, never `NO_COLOR`. On its own, ansis
117
+ * would color a pipe as soon as `COLORTERM` is set.
118
+ */
119
+ function colorLevel(stream) {
120
+ if (!stream.isTTY && process$1.env.FORCE_COLOR === void 0) return 0;
121
+ const depth = WriteStream.prototype.getColorDepth.call(stream);
122
+ return depth >= 24 ? 3 : depth >= 8 ? 2 : depth >= 4 ? 1 : 0;
123
+ }
124
+ const ansis = new Ansis(colorLevel(process$1.stderr));
125
+ const brand = ansis.hex("#f67f2f");
126
+ const badge = ansis.bgHex("#f67f2f").black;
127
+ /** U+279C. */
128
+ const ARROW = "➜";
129
+ const INDENT = " ";
130
+ function banner(action, subject) {
131
+ const status = subject === void 0 ? ansis.dim(action) : `${ansis.dim(action)} ${ansis.cyan(subject)}`;
132
+ console.error(`${badge(` ${name} `)} ${brand(`v${version}`)} ${status}`);
133
+ }
134
+ function blankLine() {
135
+ console.error("");
136
+ }
137
+ function aside(message) {
138
+ console.error(`${INDENT}${ansis.dim(message)}`);
139
+ }
140
+ function fileWritten({ root, outDir, filePath, content, type, maxLength }) {
141
+ const prettyOutDir = `${normalizePath(relative(root, outDir))}/`;
142
+ const kibs = content.length / 1024;
143
+ const compressedKibs = gzipSync(content).length / 1024;
144
+ const paint = type === "chunk" ? ansis.cyan : ansis.magenta;
145
+ console.error(`${INDENT}${ansis.green(ARROW)} ${ansis.dim(prettyOutDir)}${ansis.bold(paint(filePath.padEnd(maxLength + 2)))}${ansis.dim(`${kibs.toFixed(2)} kB`)} ${ansis.gray("·")} ${ansis.dim(`gzip ${compressedKibs.toFixed(2)} kB`)}`);
146
+ }
147
+ function serverReady({ root, url, outDir, devFilename, watchPaths, startedAt }) {
148
+ const devIndex = normalizePath(relative(root, resolve(root, outDir ?? "", devFilename)));
149
+ const labelWidth = 8;
150
+ row("Server", ansis.cyan(ansis.link(url)), labelWidth);
151
+ row("Plugin", ansis.dim(devIndex), labelWidth);
152
+ if (watchPaths.length > 0) row("Watching", ansis.dim(watchPaths.join(", ")), labelWidth);
153
+ blankLine();
154
+ aside(`ready in ${elapsed(startedAt)} – open the Panel and your changes appear as you save`);
155
+ aside(`stop with ${ansis.bold("Ctrl-C")}`);
156
+ }
157
+ function watching(paths) {
158
+ row("Watching", ansis.dim(paths.join(", ")), 8);
159
+ }
160
+ function fileChanged(event, file) {
161
+ console.error(`${INDENT}${ansis.green(ARROW)} ${ansis.bold(file)} ${ansis.dim(event)}`);
162
+ }
163
+ function fullReload(file) {
164
+ console.error(`${INDENT}${ansis.green(ARROW)} ${ansis.bold(file)} ${ansis.dim("changed, reloading the Panel")}`);
165
+ }
166
+ function configChanged(file) {
167
+ console.error(`${INDENT}${ansis.green(ARROW)} ${ansis.bold(file)} ${ansis.dim("changed, reloading the config")}`);
168
+ }
169
+ function elapsed(startedAt) {
170
+ const milliseconds = Math.round(performance.now() - startedAt);
171
+ return milliseconds < 1e3 ? `${milliseconds} ms` : `${(milliseconds / 1e3).toFixed(2)} s`;
172
+ }
173
+ function row(label, value, labelWidth) {
174
+ console.error(`${INDENT}${ansis.green(ARROW)} ${ansis.bold(`${label}:`.padEnd(labelWidth + 1))} ${value}`);
49
175
  }
50
176
  //#endregion
51
177
  //#region src/node/plugins/build-cleanup.ts
178
+ const VITE_HASH_UPDATE_MARKER_RE = /\/\*\$vite\$:\d+\*\/\s*$/;
52
179
  function kirbyupBuildCleanupPlugin(options) {
53
180
  let config;
54
181
  let devIndexPath;
55
182
  return {
56
183
  name: "kirbyup:build-cleanup",
184
+ enforce: "post",
57
185
  configResolved(resolvedConfig) {
58
186
  config = resolvedConfig;
59
187
  devIndexPath = resolve(config.root, options.outDir, "index.dev.js");
60
188
  },
189
+ generateBundle(_outputOptions, bundle) {
190
+ for (const item of Object.values(bundle)) if (item.type === "asset" && typeof item.source === "string") item.source = item.source.replace(VITE_HASH_UPDATE_MARKER_RE, "");
191
+ },
61
192
  writeBundle() {
62
193
  if (options.watch) return;
63
194
  if (fs.existsSync(devIndexPath)) fs.unlinkSync(devIndexPath);
@@ -70,41 +201,26 @@ function toArray(array) {
70
201
  array ??= [];
71
202
  return Array.isArray(array) ? array : [array];
72
203
  }
73
- async function printFileInfo({ root, outDir, filePath, content, type, maxLength }) {
74
- const prettyOutDir = `${normalize(relative(root, outDir))}/`;
75
- const kibs = content.length / 1024;
76
- const compressedKibs = gzipSync(content).length / 1024;
77
- const writeColor = type === "chunk" ? colors.cyan : colors.magenta;
78
- consola.log(colors.white(colors.dim(prettyOutDir)) + writeColor(filePath.padEnd(maxLength + 2)) + colors.dim(`${kibs.toFixed(2)} kB / gzip: ${compressedKibs.toFixed(2)} KiB`));
79
- }
80
204
  //#endregion
81
205
  //#region src/node/plugins/full-reload.ts
82
206
  /**
83
- * Triggers a full browser reload when files matching the given globs change.
84
- * Vite forces chokidar's `disableGlobbing: true` by default; this plugin
85
- * resets it so glob strings passed to `watcher.add` are expanded by chokidar.
207
+ * Triggers a full browser reload when a watched file changes. The matching is
208
+ * `createFilter`, not the watcher: Vite already watches the project root, and
209
+ * chokidar has expanded no globs since v4, so adding a pattern to it does nothing.
86
210
  */
87
211
  function kirbyupFullReloadPlugin(paths) {
88
212
  return {
89
213
  name: "kirbyup:full-reload",
90
214
  apply: "serve",
91
- config() {
92
- return { server: { watch: { disableGlobbing: false } } };
93
- },
94
- configureServer({ watcher, ws, config: { root, logger } }) {
95
- const files = toArray(paths).map((p) => resolve(root, p));
96
- const matches = createFilter(files);
97
- watcher.add(files);
215
+ configureServer({ watcher, ws, config: { root } }) {
216
+ const matches = createFilter(toArray(paths).map((path) => resolve(root, path)));
98
217
  const reload = (path) => {
99
218
  if (!matches(path)) return;
100
219
  setTimeout(() => ws.send({
101
220
  type: "full-reload",
102
221
  path: "*"
103
222
  }), 0);
104
- logger.info(`${colors.green("full reload")} ${colors.dim(relative(root, path))}`, {
105
- clear: true,
106
- timestamp: true
107
- });
223
+ fullReload(normalizePath(relative(root, path)));
108
224
  };
109
225
  watcher.on("add", reload);
110
226
  watcher.on("change", reload);
@@ -173,10 +289,10 @@ function hostIncludesPort(host) {
173
289
  }
174
290
  //#endregion
175
291
  //#region src/node/plugins/runtime/hmr-shim.js?raw
176
- 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";
292
+ 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, app } = window.panel ?? {}\n\n if (plugins?.components) {\n for (const [name, pluginComp] of Object.entries(plugins.components)) {\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(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";
177
293
  //#endregion
178
294
  //#region src/node/plugins/runtime/vue-stub.js?raw
179
- 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";
295
+ 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 the Kirby 6 Panel is loaded.',\n )\n}\n// eslint-disable-next-line no-unused-vars, antfu/no-top-level-await\nconst __kirbyupVueModule = await import(/* @vite-ignore */ __kirbyupVueUrl)\n";
180
296
  //#endregion
181
297
  //#region src/node/plugins/utils.ts
182
298
  /**
@@ -197,7 +313,11 @@ const __HMR_SHIM_CODE__ = hmr_shim_default;
197
313
  */
198
314
  function buildVueStubCode(namedExports) {
199
315
  if (namedExports.length === 0) return vue_stub_default;
200
- return vue_stub_default + `\nexport const {\n${namedExports.map((name) => ` ${name},`).join("\n")}\n} = __kirbyupVueModule\n`;
316
+ return [vue_stub_default, `
317
+ export const {
318
+ ${namedExports.map((name) => ` ${name},`).join("\n")}
319
+ } = __kirbyupVueModule
320
+ `.trimStart()].join("\n");
201
321
  }
202
322
  //#endregion
203
323
  //#region src/node/plugins/hmr.ts
@@ -212,10 +332,17 @@ function kirbyupHmrPlugin(options) {
212
332
  let entryId;
213
333
  let devIndexPath;
214
334
  let vueStubCode;
335
+ let markWritten;
336
+ let markFailed;
337
+ const devIndexWritten = new Promise((resolve, reject) => {
338
+ markWritten = resolve;
339
+ markFailed = reject;
340
+ });
215
341
  return {
216
342
  name: "kirbyup:hmr",
217
343
  apply: "serve",
218
344
  enforce: "pre",
345
+ api: { devIndexWritten },
219
346
  config() {
220
347
  return {
221
348
  optimizeDeps: { exclude: ["vue"] },
@@ -232,7 +359,7 @@ function kirbyupHmrPlugin(options) {
232
359
  devIndexPath = resolve(config.root, options.outDir ?? "", "index.dev.js");
233
360
  try {
234
361
  const vueModule = await import("vue");
235
- const namedExports = Object.keys(vueModule).filter((name) => name !== "default");
362
+ const namedExports = Object.keys(vueModule).filter((name) => name !== "default" && /^[A-Z_$][\w$]*$/i.test(name));
236
363
  vueStubCode = namedExports.length > 0 ? buildVueStubCode(namedExports) : void 0;
237
364
  } catch {
238
365
  vueStubCode = void 0;
@@ -263,16 +390,25 @@ function kirbyupHmrPlugin(options) {
263
390
  };
264
391
  },
265
392
  configureServer(server) {
266
- if (!server.httpServer) return;
393
+ if (!server.httpServer) {
394
+ markWritten();
395
+ return;
396
+ }
267
397
  server.httpServer.once("listening", async () => {
268
- const entryPath = entry.replace(`${config.root}/`, "");
269
- const baseUrl = getDevBaseUrl(server, config);
270
- const entryUrl = new URL(entryPath, baseUrl).href;
271
- const pm = detectPackageManager(config.root);
272
- await fsp.writeFile(devIndexPath, getViteProxyModule(entryUrl, pm));
398
+ try {
399
+ const entryPath = entry.replace(`${config.root}/`, "");
400
+ const baseUrl = getDevBaseUrl(server, config);
401
+ const entryUrl = new URL(entryPath, baseUrl).href;
402
+ const pm = detectPackageManager(config.root);
403
+ await fsp.writeFile(devIndexPath, getViteProxyModule(entryUrl, pm));
404
+ markWritten();
405
+ } catch (error) {
406
+ markFailed(error);
407
+ }
273
408
  });
274
409
  },
275
410
  async closeBundle() {
411
+ await devIndexWritten.catch(() => {});
276
412
  await fsp.rm(devIndexPath, { force: true });
277
413
  }
278
414
  };
@@ -283,9 +419,9 @@ try {
283
419
  await import("${entryUrl}");
284
420
  } catch (error) {
285
421
  console.error(
286
- "[kirbyup] Couldn't connect to the development server at ${entryUrl}. Run \`${packageManager} run serve\` to start Vite or build the plugin with \`${packageManager} run build\` so Kirby uses the production version."
422
+ "[kirbyup] Couldn't connect to the development server at ${entryUrl}. Run \`${packageManager} run dev\` to start Vite or build the plugin with \`${packageManager} run build\` so Kirby uses the production version.",
423
+ error
287
424
  );
288
- throw error;
289
425
  }
290
426
  `.trimStart();
291
427
  }
@@ -305,9 +441,9 @@ function detectPackageManager(cwd) {
305
441
  //#endregion
306
442
  //#region src/node/index.ts
307
443
  const DEV_OUTPUT_FILENAME = "index.dev.js";
308
- const SUPPRESSED_WARNING_PREFIX = "\n(!) build.outDir";
444
+ const SUPPRESSED_WARNING = "(!) build.outDir";
309
445
  const logLevel = "warn";
310
- function getViteConfig(command, options, { kirbyupConfig, postCssConfig, logger }) {
446
+ function getViteConfig(command, options, { kirbyupConfig, logger }) {
311
447
  const aliasDir = resolve(options.cwd, dirname(options.entry));
312
448
  const { alias = {}, vite } = kirbyupConfig;
313
449
  const userConfig = vite ?? {};
@@ -318,15 +454,11 @@ function getViteConfig(command, options, { kirbyupConfig, postCssConfig, logger
318
454
  ...alias
319
455
  } },
320
456
  plugins: [
321
- vuePlugin({ compiler: vueCompilerSfc }),
457
+ vuePlugin(),
322
458
  vueJsxPlugin(),
323
459
  kirbyupGlobImportPlugin()
324
460
  ],
325
461
  build: { copyPublicDir: false },
326
- ...postCssConfig && { css: { postcss: {
327
- ...postCssConfig.options,
328
- plugins: postCssConfig.plugins
329
- } } },
330
462
  envDir: options.cwd,
331
463
  envPrefix: ["VITE_", "KIRBYUP_"],
332
464
  customLogger: logger,
@@ -334,26 +466,29 @@ function getViteConfig(command, options, { kirbyupConfig, postCssConfig, logger
334
466
  };
335
467
  if (command === "serve") {
336
468
  const { port, watch } = options;
337
- const inferredOrigin = userConfig.server?.origin ?? resolveOriginFromServerOptions(userConfig.server, port, "localhost");
338
- return mergeConfig(mergeConfig(sharedConfig, {
469
+ const resolvedPort = userConfig.server?.port ?? port;
470
+ const inferredOrigin = userConfig.server?.origin ?? resolveOriginFromServerOptions(userConfig.server, resolvedPort, "localhost");
471
+ const serveConfig = mergeConfig(sharedConfig, {
339
472
  plugins: [kirbyupHmrPlugin(options), watch && kirbyupFullReloadPlugin(watch)].filter(Boolean),
340
473
  build: { rollupOptions: { input: resolve(options.cwd, options.entry) } },
341
474
  server: {
342
- port,
475
+ port: resolvedPort,
343
476
  strictPort: true,
344
477
  origin: inferredOrigin,
345
478
  cors: true
346
479
  }
347
- }), userConfig);
480
+ });
481
+ return mergeConfig(serveConfig, userConfig);
348
482
  }
349
483
  const mode = options.watch ? "development" : "production";
350
- return mergeConfig(mergeConfig(sharedConfig, {
484
+ const buildConfig = mergeConfig(sharedConfig, {
351
485
  mode,
352
486
  plugins: [kirbyupBuildCleanupPlugin(options)],
353
487
  build: {
354
488
  lib: {
355
489
  entry: resolve(options.cwd, options.entry),
356
- formats: ["es"],
490
+ formats: ["iife"],
491
+ name: "kirbyupPlugin",
357
492
  fileName: () => options.watch ? DEV_OUTPUT_FILENAME : "index.js"
358
493
  },
359
494
  minify: mode === "production",
@@ -361,10 +496,15 @@ function getViteConfig(command, options, { kirbyupConfig, postCssConfig, logger
361
496
  emptyOutDir: false,
362
497
  rollupOptions: {
363
498
  external: ["vue"],
364
- output: { assetFileNames: "index.[ext]" }
499
+ output: {
500
+ assetFileNames: "index.[ext]",
501
+ exports: "none",
502
+ globals: (id) => `await import(${JSON.stringify(id)})`
503
+ }
365
504
  }
366
505
  }
367
- }), userConfig);
506
+ });
507
+ return mergeConfig(buildConfig, userConfig);
368
508
  }
369
509
  async function generate(options, context) {
370
510
  const config = getViteConfig("build", options, context);
@@ -372,15 +512,16 @@ async function generate(options, context) {
372
512
  try {
373
513
  result = await build(config);
374
514
  } catch (error) {
375
- if (!options.watch) throw error;
376
- consola.error(error);
515
+ const buildError = new CliError(error instanceof Error ? error.message : String(error), { cause: error });
516
+ if (!options.watch) throw buildError;
517
+ reportFailure(buildError);
377
518
  }
378
519
  if (!result || options.watch) return;
379
- const { output } = toArray(result)[0];
380
- const maxLength = Math.max(0, ...output.map((item) => item.fileName.length));
381
- for (const item of output) {
520
+ const { output: bundle } = toArray(result)[0];
521
+ const maxLength = Math.max(0, ...bundle.map((item) => item.fileName.length));
522
+ for (const item of bundle) {
382
523
  const content = item.type === "chunk" ? item.code : await fsp.readFile(resolve(options.outDir, item.fileName), "utf8");
383
- await printFileInfo({
524
+ fileWritten({
384
525
  root: options.cwd,
385
526
  outDir: options.outDir,
386
527
  filePath: item.fileName,
@@ -394,20 +535,19 @@ async function build$1(options) {
394
535
  assertEntryExists(options);
395
536
  const { cwd } = options;
396
537
  const { config, configFile } = await loadConfig$1(cwd);
397
- const postCssConfig = await resolvePostCSSConfig(cwd);
398
538
  const context = {
399
539
  kirbyupConfig: config ?? {},
400
- postCssConfig,
401
540
  logger: createKirbyupLogger()
402
541
  };
403
- consola.log(colors.green(`${name} v${version}`));
404
- consola.start(`Building ${colors.cyan(options.entry)}`);
542
+ const startedAt = performance.now();
543
+ banner("building", options.entry);
544
+ blankLine();
405
545
  await generate(options, context);
406
- consola.success("Build successful");
546
+ aside(`built in ${elapsed(startedAt)}`);
407
547
  if (!options.watch) return;
408
548
  const { watch } = await import("chokidar");
409
549
  const debouncedBuild = debounce(() => {
410
- generate(options, context).catch(handleError);
550
+ generate(options, context).catch(reportFailure);
411
551
  }, 100);
412
552
  const ignored = [
413
553
  "**/{.git,node_modules}/**",
@@ -415,7 +555,7 @@ async function build$1(options) {
415
555
  DEV_OUTPUT_FILENAME
416
556
  ];
417
557
  const watchPaths = options.watch === true ? dirname(options.entry) : toArray(options.watch);
418
- consola.info(`Watching for changes in ${toArray(watchPaths).map((i) => colors.cyan(i)).join(", ")}`);
558
+ watching(toArray(watchPaths));
419
559
  const watcher = watch(watchPaths, {
420
560
  ignoreInitial: true,
421
561
  ignorePermissionErrors: true,
@@ -439,10 +579,11 @@ async function build$1(options) {
439
579
  process.once("SIGTERM", onShutdown);
440
580
  if (configFile) watcher.add(configFile);
441
581
  watcher.on("all", async (type, file) => {
442
- if (configFile === resolve(cwd, file)) {
582
+ const absolutePath = resolve(cwd, file);
583
+ if (configFile === absolutePath) {
443
584
  context.kirbyupConfig = (await loadConfig$1(cwd)).config ?? {};
444
- consola.info(`${colors.cyan(basename(file))} changed, setting new config`);
445
- } else consola.log(`${colors.green(type)} ${colors.white(colors.dim(file))}`);
585
+ configChanged(basename(file));
586
+ } else fileChanged(type, file);
446
587
  debouncedBuild();
447
588
  });
448
589
  }
@@ -450,17 +591,25 @@ async function serve(options) {
450
591
  assertEntryExists(options);
451
592
  const { cwd } = options;
452
593
  const { config } = await loadConfig$1(cwd);
453
- const postCssConfig = await resolvePostCSSConfig(cwd);
454
594
  const context = {
455
595
  kirbyupConfig: config ?? {},
456
- postCssConfig,
457
596
  logger: createKirbyupLogger()
458
597
  };
459
- consola.log(colors.green(`${name} v${version}`));
460
- consola.info("Starting development server…");
598
+ const startedAt = performance.now();
599
+ banner("starting the development server");
600
+ blankLine();
461
601
  const server = await createServer(getViteConfig("serve", options, context));
462
602
  await server.listen();
463
- consola.success(`Server is listening on :${server.config.server.port}`);
603
+ await (server.config.plugins.find((plugin) => plugin.name === "kirbyup:hmr")?.api)?.devIndexWritten;
604
+ const port = server.config.server.port ?? options.port;
605
+ serverReady({
606
+ root: cwd,
607
+ url: server.config.server.origin ?? resolveOriginFromServerOptions(server.config.server, port, "localhost"),
608
+ outDir: options.outDir,
609
+ devFilename: DEV_OUTPUT_FILENAME,
610
+ watchPaths: options.watch === false ? [] : toArray(options.watch),
611
+ startedAt
612
+ });
464
613
  return server;
465
614
  }
466
615
  function createKirbyupLogger() {
@@ -468,13 +617,13 @@ function createKirbyupLogger() {
468
617
  return {
469
618
  ...baseLogger,
470
619
  warn(msg, options) {
471
- if (msg.startsWith(SUPPRESSED_WARNING_PREFIX)) return;
620
+ if (msg.includes(SUPPRESSED_WARNING)) return;
472
621
  baseLogger.warn(msg, options);
473
622
  }
474
623
  };
475
624
  }
476
625
  function assertEntryExists(options) {
477
- if (!fs.existsSync(resolve(options.cwd, options.entry))) throw new PrettyError(`Cannot find "${options.entry}"`);
626
+ if (!fs.existsSync(resolve(options.cwd, options.entry))) throw new CliError(`Cannot find "${options.entry}"`);
478
627
  }
479
628
  //#endregion
480
- export { version as a, name as i, serve as n, handleError as r, build$1 as t };
629
+ export { version as a, reportFailure as c, name as i, log_exports as l, serve as n, ArgumentError as o, description as r, CliError as s, build$1 as t, paint as u };
@@ -0,0 +1,38 @@
1
+ import { AliasOptions, InlineConfig } from "vite";
2
+ //#region src/node/types.d.ts
3
+ interface BaseOptions {
4
+ cwd: string;
5
+ entry: string;
6
+ }
7
+ interface ServeOptions extends BaseOptions {
8
+ watch: false | string | string[];
9
+ port: number;
10
+ outDir?: string;
11
+ }
12
+ interface BuildOptions extends BaseOptions {
13
+ outDir: string;
14
+ watch: boolean | string | string[];
15
+ }
16
+ interface UserConfig {
17
+ /**
18
+ * Object or array of objects defining aliases that replace values in
19
+ * `import` statements. With either format, the order of the entries
20
+ * matters: the first defined rules are applied first.
21
+ */
22
+ alias?: AliasOptions;
23
+ /**
24
+ * Additional Vite configuration, merged into kirbyup's defaults – for
25
+ * example, to define global constant replacements.
26
+ *
27
+ * @example
28
+ * export default defineConfig({
29
+ * vite: {
30
+ * define: {
31
+ * __TEST__: JSON.stringify(process.env.TEST === 'true'),
32
+ * },
33
+ * })
34
+ */
35
+ vite?: InlineConfig;
36
+ }
37
+ //#endregion
38
+ export { ServeOptions as n, UserConfig as r, BuildOptions 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.7",
5
- "packageManager": "pnpm@10.33.3",
4
+ "version": "4.0.0-alpha.9",
5
+ "packageManager": "pnpm@11.25.0",
6
6
  "description": "Zero-config bundler for Kirby Panel plugins",
7
7
  "author": {
8
8
  "name": "Johann Schopplich",
@@ -39,16 +39,6 @@
39
39
  }
40
40
  },
41
41
  "types": "./dist/node/index.d.mts",
42
- "typesVersions": {
43
- "*": {
44
- "config": [
45
- "./dist/client/config.d.mts"
46
- ],
47
- "plugin": [
48
- "./dist/client/plugin.d.mts"
49
- ]
50
- }
51
- },
52
42
  "bin": {
53
43
  "kirbyup": "bin/kirbyup.mjs"
54
44
  },
@@ -61,9 +51,9 @@
61
51
  },
62
52
  "scripts": {
63
53
  "build": "tsdown",
64
- "docs:dev": "vitepress dev docs",
65
- "docs:build": "vitepress build docs",
66
- "docs:preview": "vitepress preview docs",
54
+ "docs:dev": "pnpm --filter docs run dev",
55
+ "docs:build": "pnpm --filter docs run build",
56
+ "docs:preview": "pnpm --filter docs run preview",
67
57
  "lint": "eslint .",
68
58
  "lint:fix": "eslint . --fix",
69
59
  "release": "bumpp",
@@ -71,32 +61,28 @@
71
61
  "test:types": "tsc --noEmit"
72
62
  },
73
63
  "dependencies": {
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",
64
+ "@vitejs/plugin-vue": "^6.0.8",
65
+ "@vitejs/plugin-vue-jsx": "^5.1.6",
66
+ "ansis": "^4.3.1",
67
+ "c12": "^4.0.0-beta.5",
79
68
  "chokidar": "^5.0.0",
80
- "consola": "^3.4.2",
81
- "magic-string": "^0.30.21",
82
- "pathe": "^2.0.3",
69
+ "magic-string": "^1.2.3",
83
70
  "perfect-debounce": "^2.1.0",
84
- "postcss": "^8.5.14",
85
- "postcss-load-config": "^6.0.1",
86
- "sass": "^1.99.0",
87
- "strip-literal": "^3.1.0",
88
- "vite": "^8.0.10",
89
- "vue": "^3.5.34"
71
+ "sass": "^1.103.1",
72
+ "strip-literal": "^4.0.0",
73
+ "vite": "^8.2.2",
74
+ "vue": "^3.5.42"
90
75
  },
91
76
  "devDependencies": {
92
- "@antfu/eslint-config": "^8.2.0",
93
- "@types/node": "^24.12.2",
94
- "bumpp": "^11.0.1",
95
- "eslint": "^10.3.0",
77
+ "@antfu/eslint-config": "^9.3.0",
78
+ "@types/node": "^26.4.0",
79
+ "bumpp": "^12.2.2",
80
+ "eslint": "^10.9.1",
96
81
  "eslint-flat-config-utils": "^3.2.0",
97
- "tsdown": "^0.21.10",
82
+ "tsdown": "^0.22.14",
98
83
  "typescript": "^6.0.3",
99
- "unplugin-raw": "^0.7.0",
100
- "vitest": "^4.1.5"
84
+ "unplugin-raw": "^0.8.0",
85
+ "utilful": "^3.3.0",
86
+ "vitest": "^4.1.11"
101
87
  }
102
88
  }
@@ -1 +0,0 @@
1
- export { };
package/dist/node/cli.mjs DELETED
@@ -1,42 +0,0 @@
1
- import { a as version, i as name, n as serve, r as handleError, t as build } from "../node-BAAmufwc.mjs";
2
- import { cac } from "cac";
3
- //#region src/node/cli-start.ts
4
- async function startCli(cwd = process.cwd(), argv = process.argv) {
5
- const cli = cac(name);
6
- cli.command("<file>", "Compile the Kirby Panel plugin to index.js and index.css").option("-d, --out-dir <dir>", "Output directory", { default: cwd }).option("-w, --watch [path]", "Watch for file changes. If no path is specified, the folder of the input file will be watched", { default: false }).example("kirbyup src/index.js").example("kirbyup src/index.js --out-dir ~/kirby-site/site/plugins/demo").example("kirbyup src/index.js --watch src/**/*.{js,css} --watch assets/*\n").action(async (file, options) => {
7
- process.env.NODE_ENV ||= options.watch ? "development" : "production";
8
- await build({
9
- cwd,
10
- entry: file,
11
- ...options
12
- });
13
- });
14
- cli.command("serve <file>", "Start development server with live reload").option("--no-watch", "Don't watch .php files for changes", { default: "\0" }).option("-w, --watch <path>", "Watch additional files", { default: "./**/*.php" }).option("-p, --port <number>", "Port for the development server", { default: 5177 }).option("-d, --out-dir <dir>", "Output directory").example("kirbyup serve src/index.js").example("kirbyup serve src/index.js --no-watch --port 3003").example("kirbyup serve src/index.js --watch snippets/*.php --watch templates/*.php\n").action(async (file, options) => {
15
- process.env.NODE_ENV ||= "development";
16
- const server = await serve({
17
- cwd,
18
- entry: file,
19
- ...options
20
- });
21
- const exitProcess = async () => {
22
- try {
23
- await server.close();
24
- } finally {
25
- process.exit();
26
- }
27
- };
28
- process.once("SIGINT", exitProcess);
29
- });
30
- cli.help((s) => s.map((msg) => ({
31
- ...msg,
32
- body: msg.body.replace(" (default: \0)", "")
33
- })));
34
- cli.version(version);
35
- cli.parse(argv, { run: false });
36
- await cli.runMatchedCommand();
37
- }
38
- //#endregion
39
- //#region src/node/cli.ts
40
- startCli().catch(handleError);
41
- //#endregion
42
- export {};
@@ -1,40 +0,0 @@
1
- import { AliasOptions, InlineConfig } from "vite";
2
-
3
- //#region src/node/types.d.ts
4
- interface BaseOptions {
5
- cwd: string;
6
- entry: string;
7
- }
8
- interface ServeOptions extends BaseOptions {
9
- watch: false | string | string[];
10
- port: number;
11
- outDir?: string;
12
- }
13
- interface BuildOptions extends BaseOptions {
14
- outDir: string;
15
- watch: boolean | string | string[];
16
- }
17
- interface UserConfig {
18
- /**
19
- * Specifies an object or an array of objects, which defines aliases
20
- * used to replace values in `import` statements.
21
- * With either format, the order of the entries is important,
22
- * in that the first defined rules are applied first.
23
- */
24
- alias?: AliasOptions;
25
- /**
26
- * Extends Vite's configuration. Will be merged with kirbyup's
27
- * default configuration. For example, you can define global constant replacements.
28
- *
29
- * @example
30
- * export default defineConfig({
31
- * vite: {
32
- * define: {
33
- * __TEST__: JSON.stringify(process.env.TEST === 'true'),
34
- * },
35
- * })
36
- */
37
- vite?: InlineConfig;
38
- }
39
- //#endregion
40
- export { ServeOptions as n, UserConfig as r, BuildOptions as t };