kirbyup
Version:
Zero-config bundler for Kirby Panel plugins
929 lines (890 loc) • 28.4 kB
JavaScript
import * as fs from 'node:fs';
import { existsSync } from 'node:fs';
import * as fsp from 'node:fs/promises';
import { readFile } from 'node:fs/promises';
import vuePlugin from '@vitejs/plugin-vue2';
import vueJsxPlugin from '@vitejs/plugin-vue2-jsx';
import { consola } from 'consola';
import { colors } from 'consola/utils';
import { resolve, join, normalize, relative, dirname, basename } from 'pathe';
import { debounce } from 'perfect-debounce';
import externalGlobals from 'rollup-plugin-external-globals';
import { createLogger, createServer, build as build$1, mergeConfig } from 'vite';
import fullReloadPlugin from 'vite-plugin-full-reload';
import * as vueCompilerSfc from 'vue/compiler-sfc';
import { loadConfig as loadConfig$1 } from 'c12';
import postcssrc from 'postcss-load-config';
import MagicString from 'magic-string';
import { createRequire } from 'node:module';
import 'child_process';
import 'path';
import 'process';
import 'stream';
import 'readline';
import { Buffer as Buffer$1 } from 'node:buffer';
import { promisify } from 'node:util';
import { gzip } from 'node:zlib';
const name = "kirbyup";
const version = "3.3.0";
function loadConfig(cwd = process.cwd()) {
return loadConfig$1({
cwd,
name: "kirbyup",
rcFile: false,
packageJson: false
});
}
async function resolvePostCSSConfig(cwd) {
try {
return await postcssrc(void 0, void 0, { stopDir: cwd });
} catch (error) {
if (!error.message.includes("No PostCSS Config found"))
throw error;
}
}
class PrettyError extends Error {
constructor(message) {
super(message);
this.name = this.constructor.name;
if (typeof Error.captureStackTrace === "function")
Error.captureStackTrace(this, this.constructor);
else
this.stack = new Error(message).stack;
}
}
function handleError(error) {
consola.error(error.message);
process.exitCode = 1;
}
function kirbyupBuildCleanupPlugin(options) {
let config;
let devIndexPath;
return {
name: "kirbyup:build-cleanup",
configResolved(resolvedConfig) {
config = resolvedConfig;
devIndexPath = resolve(config.root, options.outDir, "index.dev.mjs");
},
writeBundle() {
if (fs.existsSync(devIndexPath))
fs.unlinkSync(devIndexPath);
}
};
}
const multilineCommentsRE = /\/\*(.|[\r\n])*?\*\//g;
const singlelineCommentsRE = /\/\/.*/g;
const HMR_RUNTIME_ID = "\0plugin-vue2:hmr-runtime";
const JSX_HMR_RUNTIME_ID = "plugin-vue2-jsx:hmr-runtime";
function isHmrRuntimeId(id) {
return id === HMR_RUNTIME_ID || id === JSX_HMR_RUNTIME_ID;
}
const __INJECTED_HMR_CODE__ = `
/** - injected by kirbyup - */
for (const methodName of ['rerender', 'reload']) {
const original = __VUE_HMR_RUNTIME__[methodName]
__VUE_HMR_RUNTIME__[methodName] = function (id, updatedDef) {
const key = updatedDef?.__file ? '__file' : updatedDef?.__hmrId ? '__hmrId' : null
if (key) {
const pluginComponents = window.panel.plugins.components
// const usedComponentDefs = window.panel.app.$options.components
const usedComponentDefs = window.panel.app._vnode.componentInstance.$options.components // #33
for (const componentName in pluginComponents) {
if (updatedDef[key] === pluginComponents[componentName][key]) {
const usedDefinition = usedComponentDefs[componentName].options
if (map[id].options !== usedDefinition)
map[id].options = usedDefinition
if (typeof map[id].options.$_isSection !== 'boolean')
map[id].options.$_isSection = /^k-.*-section$/.test(componentName)
break
}
}
}
return original.apply(this, arguments)
}
}
function $_applyKirbyModifications(activeDef, newDef) {
const usedComponentDefs = window.panel.app.$options.components
if (newDef.template)
newDef.render = null
if (activeDef.$_isSection)
newDef.$_isSection = true
if (newDef.$_isSection && !newDef.mixins?.[0]?.methods?.load)
newDef.mixins = [activeDef.mixins[0], ...(newDef.mixins || [])]
if (typeof newDef.extends === 'string') {
if (newDef.extends === activeDef.extends?.options?.name) {
newDef.extends = activeDef.extends
}
else if (usedComponentDefs[newDef.extends]) {
newDef.extends = usedComponentDefs[newDef.extends].extend({
options: newDef,
components: { ...usedComponentDefs, ...(newDef.components || {}) },
})
}
else { newDef.extends = null }
}
}
/** -- */
`;
function kirbyupGlobImportPlugin() {
let config;
return {
name: "kirbyup:glob-import",
configResolved(resolvedConfig) {
config = resolvedConfig;
},
async transform(code) {
if (!code.includes("kirbyup.import"))
return;
const kirbyupImportRE = /\bkirbyup\.import\s*\(\s*('[^']+'|"[^"]+"|`[^`]+`)\s*\)/g;
const noCommentsCode = code.replace(multilineCommentsRE, (m) => " ".repeat(m.length)).replace(singlelineCommentsRE, (m) => " ".repeat(m.length));
let s;
let match;
while (match = kirbyupImportRE.exec(noCommentsCode)) {
const { 0: exp, 1: rawPath, index } = match;
if (!s)
s = new MagicString(code);
s.overwrite(
index,
index + exp.length,
`kirbyup.import(import.meta.glob(${rawPath}, { eager: true }))`
);
}
if (s) {
return {
code: s.toString(),
map: config.build.sourcemap ? s.generateMap({ hires: true }) : void 0
};
}
}
};
}
const require = createRequire(import.meta.url);
var St = Object.create;
var $ = Object.defineProperty;
var kt = Object.getOwnPropertyDescriptor;
var Tt = Object.getOwnPropertyNames;
var At = Object.getPrototypeOf, Rt = Object.prototype.hasOwnProperty;
var h = /* @__PURE__ */ ((t) => typeof require < "u" ? require : typeof Proxy < "u" ? new Proxy(t, {
get: (e, n) => (typeof require < "u" ? require : e)[n]
}) : t)(function(t) {
if (typeof require < "u") return require.apply(this, arguments);
throw Error('Dynamic require of "' + t + '" is not supported');
});
var l = (t, e) => () => (e || t((e = { exports: {} }).exports, e), e.exports);
var $t = (t, e, n, r) => {
if (e && typeof e == "object" || typeof e == "function")
for (let s of Tt(e))
!Rt.call(t, s) && s !== n && $(t, s, { get: () => e[s], enumerable: !(r = kt(e, s)) || r.enumerable });
return t;
};
var Nt = (t, e, n) => (n = t != null ? St(At(t)) : {}, $t(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
$(n, "default", { value: t, enumerable: true }) ,
t
));
// node_modules/isexe/windows.js
var W = l((Se, H) => {
H.exports = z;
z.sync = Wt;
var j = h("fs");
function Ht(t, e) {
var n = e.pathExt !== void 0 ? e.pathExt : process.env.PATHEXT;
if (!n || (n = n.split(";"), n.indexOf("") !== -1))
return true;
for (var r = 0; r < n.length; r++) {
var s = n[r].toLowerCase();
if (s && t.substr(-s.length).toLowerCase() === s)
return true;
}
return false;
}
function F(t, e, n) {
return !t.isSymbolicLink() && !t.isFile() ? false : Ht(e, n);
}
function z(t, e, n) {
j.stat(t, function(r, s) {
n(r, r ? false : F(s, t, e));
});
}
function Wt(t, e) {
return F(j.statSync(t), t, e);
}
});
// node_modules/isexe/mode.js
var X = l((ke, B) => {
B.exports = K;
K.sync = Dt;
var D = h("fs");
function K(t, e, n) {
D.stat(t, function(r, s) {
n(r, r ? false : M(s, e));
});
}
function Dt(t, e) {
return M(D.statSync(t), e);
}
function M(t, e) {
return t.isFile() && Kt(t, e);
}
function Kt(t, e) {
var n = t.mode, r = t.uid, s = t.gid, o = e.uid !== void 0 ? e.uid : process.getuid && process.getuid(), i = e.gid !== void 0 ? e.gid : process.getgid && process.getgid(), a = parseInt("100", 8), c = parseInt("010", 8), u = parseInt("001", 8), f = a | c, p = n & u || n & c && s === i || n & a && r === o || n & f && o === 0;
return p;
}
});
// node_modules/isexe/index.js
var U = l((Ae, G) => {
h("fs"); var v;
process.platform === "win32" || global.TESTING_WINDOWS ? v = W() : v = X();
G.exports = y;
y.sync = Mt;
function y(t, e, n) {
if (typeof e == "function" && (n = e, e = {}), !n) {
if (typeof Promise != "function")
throw new TypeError("callback not provided");
return new Promise(function(r, s) {
y(t, e || {}, function(o, i) {
o ? s(o) : r(i);
});
});
}
v(t, e || {}, function(r, s) {
r && (r.code === "EACCES" || e && e.ignoreErrors) && (r = null, s = false), n(r, s);
});
}
function Mt(t, e) {
try {
return v.sync(t, e || {});
} catch (n) {
if (e && e.ignoreErrors || n.code === "EACCES")
return false;
throw n;
}
}
});
// node_modules/which/which.js
var et = l((Re, tt) => {
var g = process.platform === "win32" || process.env.OSTYPE === "cygwin" || process.env.OSTYPE === "msys", Y = h("path"), Bt = g ? ";" : ":", V = U(), J = (t) => Object.assign(new Error(`not found: ${t}`), { code: "ENOENT" }), Q = (t, e) => {
let n = e.colon || Bt, r = t.match(/\//) || g && t.match(/\\/) ? [""] : [
// windows always checks the cwd first
...g ? [process.cwd()] : [],
...(e.path || process.env.PATH || /* istanbul ignore next: very unusual */
"").split(n)
], s = g ? e.pathExt || process.env.PATHEXT || ".EXE;.CMD;.BAT;.COM" : "", o = g ? s.split(n) : [""];
return g && t.indexOf(".") !== -1 && o[0] !== "" && o.unshift(""), {
pathEnv: r,
pathExt: o,
pathExtExe: s
};
}, Z = (t, e, n) => {
typeof e == "function" && (n = e, e = {}), e || (e = {});
let { pathEnv: r, pathExt: s, pathExtExe: o } = Q(t, e), i = [], a = (u) => new Promise((f, p) => {
if (u === r.length)
return e.all && i.length ? f(i) : p(J(t));
let d = r[u], w = /^".*"$/.test(d) ? d.slice(1, -1) : d, m = Y.join(w, t), b = !w && /^\.[\\\/]/.test(t) ? t.slice(0, 2) + m : m;
f(c(b, u, 0));
}), c = (u, f, p) => new Promise((d, w) => {
if (p === s.length)
return d(a(f + 1));
let m = s[p];
V(u + m, { pathExt: o }, (b, Ot) => {
if (!b && Ot)
if (e.all)
i.push(u + m);
else
return d(u + m);
return d(c(u, f, p + 1));
});
});
return n ? a(0).then((u) => n(null, u), n) : a(0);
}, Xt = (t, e) => {
e = e || {};
let { pathEnv: n, pathExt: r, pathExtExe: s } = Q(t, e), o = [];
for (let i = 0; i < n.length; i++) {
let a = n[i], c = /^".*"$/.test(a) ? a.slice(1, -1) : a, u = Y.join(c, t), f = !c && /^\.[\\\/]/.test(t) ? t.slice(0, 2) + u : u;
for (let p = 0; p < r.length; p++) {
let d = f + r[p];
try {
if (V.sync(d, { pathExt: s }))
if (e.all)
o.push(d);
else
return d;
} catch {
}
}
}
if (e.all && o.length)
return o;
if (e.nothrow)
return null;
throw J(t);
};
tt.exports = Z;
Z.sync = Xt;
});
// node_modules/path-key/index.js
var rt = l(($e, _) => {
var nt = (t = {}) => {
let e = t.env || process.env;
return (t.platform || process.platform) !== "win32" ? "PATH" : Object.keys(e).reverse().find((r) => r.toUpperCase() === "PATH") || "Path";
};
_.exports = nt;
_.exports.default = nt;
});
// node_modules/cross-spawn/lib/util/resolveCommand.js
var ct = l((Ne, it) => {
var st = h("path"), Gt = et(), Ut = rt();
function ot(t, e) {
let n = t.options.env || process.env, r = process.cwd(), s = t.options.cwd != null, o = s && process.chdir !== void 0 && !process.chdir.disabled;
if (o)
try {
process.chdir(t.options.cwd);
} catch {
}
let i;
try {
i = Gt.sync(t.command, {
path: n[Ut({ env: n })],
pathExt: e ? st.delimiter : void 0
});
} catch {
} finally {
o && process.chdir(r);
}
return i && (i = st.resolve(s ? t.options.cwd : "", i)), i;
}
function Yt(t) {
return ot(t) || ot(t, true);
}
it.exports = Yt;
});
// node_modules/cross-spawn/lib/util/escape.js
var ut = l((qe, P) => {
var C = /([()\][%!^"`<>&|;, *?])/g;
function Vt(t) {
return t = t.replace(C, "^$1"), t;
}
function Jt(t, e) {
return t = `${t}`, t = t.replace(/(\\*)"/g, '$1$1\\"'), t = t.replace(/(\\*)$/, "$1$1"), t = `"${t}"`, t = t.replace(C, "^$1"), e && (t = t.replace(C, "^$1")), t;
}
P.exports.command = Vt;
P.exports.argument = Jt;
});
// node_modules/shebang-regex/index.js
var lt = l((Ie, at) => {
at.exports = /^#!(.*)/;
});
// node_modules/shebang-command/index.js
var dt = l((Le, pt) => {
var Qt = lt();
pt.exports = (t = "") => {
let e = t.match(Qt);
if (!e)
return null;
let [n, r] = e[0].replace(/#! ?/, "").split(" "), s = n.split("/").pop();
return s === "env" ? r : r ? `${s} ${r}` : s;
};
});
// node_modules/cross-spawn/lib/util/readShebang.js
var ht = l((je, ft) => {
var O = h("fs"), Zt = dt();
function te(t) {
let n = Buffer.alloc(150), r;
try {
r = O.openSync(t, "r"), O.readSync(r, n, 0, 150, 0), O.closeSync(r);
} catch {
}
return Zt(n.toString());
}
ft.exports = te;
});
// node_modules/cross-spawn/lib/parse.js
var wt = l((Fe, Et) => {
var ee = h("path"), mt = ct(), gt = ut(), ne = ht(), re = process.platform === "win32", se = /\.(?:com|exe)$/i, oe = /node_modules[\\/].bin[\\/][^\\/]+\.cmd$/i;
function ie(t) {
t.file = mt(t);
let e = t.file && ne(t.file);
return e ? (t.args.unshift(t.file), t.command = e, mt(t)) : t.file;
}
function ce(t) {
if (!re)
return t;
let e = ie(t), n = !se.test(e);
if (t.options.forceShell || n) {
let r = oe.test(e);
t.command = ee.normalize(t.command), t.command = gt.command(t.command), t.args = t.args.map((o) => gt.argument(o, r));
let s = [t.command].concat(t.args).join(" ");
t.args = ["/d", "/s", "/c", `"${s}"`], t.command = process.env.comspec || "cmd.exe", t.options.windowsVerbatimArguments = true;
}
return t;
}
function ue(t, e, n) {
e && !Array.isArray(e) && (n = e, e = null), e = e ? e.slice(0) : [], n = Object.assign({}, n);
let r = {
command: t,
args: e,
options: n,
file: void 0,
original: {
command: t,
args: e
}
};
return n.shell ? r : ce(r);
}
Et.exports = ue;
});
// node_modules/cross-spawn/lib/enoent.js
var bt = l((ze, vt) => {
var S = process.platform === "win32";
function k(t, e) {
return Object.assign(new Error(`${e} ${t.command} ENOENT`), {
code: "ENOENT",
errno: "ENOENT",
syscall: `${e} ${t.command}`,
path: t.command,
spawnargs: t.args
});
}
function ae(t, e) {
if (!S)
return;
let n = t.emit;
t.emit = function(r, s) {
if (r === "exit") {
let o = xt(s, e);
if (o)
return n.call(t, "error", o);
}
return n.apply(t, arguments);
};
}
function xt(t, e) {
return S && t === 1 && !e.file ? k(e.original, "spawn") : null;
}
function le(t, e) {
return S && t === 1 && !e.file ? k(e.original, "spawnSync") : null;
}
vt.exports = {
hookChildProcess: ae,
verifyENOENT: xt,
verifyENOENTSync: le,
notFoundError: k
};
});
// node_modules/cross-spawn/index.js
var Ct = l((He, E) => {
var yt = h("child_process"), T = wt(), A = bt();
function _t(t, e, n) {
let r = T(t, e, n), s = yt.spawn(r.command, r.args, r.options);
return A.hookChildProcess(s, r), s;
}
function pe(t, e, n) {
let r = T(t, e, n), s = yt.spawnSync(r.command, r.args, r.options);
return s.error = s.error || A.verifyENOENTSync(s.status, r), s;
}
E.exports = _t;
E.exports.spawn = _t;
E.exports.sync = pe;
E.exports._parse = T;
E.exports._enoent = A;
});
// src/main.ts
Nt(Ct());
async function findup(cwd, match, options = {}) {
const segments = normalize(cwd).split("/");
while (segments.length > 0) {
const path = segments.join("/") || "/";
const result = await match(path);
if (result || !options.includeParentDirs) {
return result;
}
segments.pop();
}
}
function parsePackageManagerField(packageManager) {
const [name, _version] = (packageManager || "").split("@");
const [version, buildMeta] = _version?.split("+") || [];
if (name && name !== "-" && /^(@[a-z0-9-~][a-z0-9-._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/.test(name)) {
return { name, version, buildMeta };
}
const sanitized = name.replace(/\W+/g, "");
const warnings = [
`Abnormal characters found in \`packageManager\` field, sanitizing from \`${name}\` to \`${sanitized}\``
];
return {
name: sanitized,
version,
buildMeta,
warnings
};
}
const packageManagers = [
{
name: "npm",
command: "npm",
lockFile: "package-lock.json"
},
{
name: "pnpm",
command: "pnpm",
lockFile: "pnpm-lock.yaml",
files: ["pnpm-workspace.yaml"]
},
{
name: "bun",
command: "bun",
lockFile: ["bun.lockb", "bun.lock"]
},
{
name: "yarn",
command: "yarn",
lockFile: "yarn.lock",
files: [".yarnrc.yml"]
},
{
name: "deno",
command: "deno",
lockFile: "deno.lock",
files: ["deno.json"]
}
];
async function detectPackageManager(cwd, options = {}) {
const detected = await findup(
resolve(cwd || "."),
async (path) => {
if (!options.ignorePackageJSON) {
const packageJSONPath = join(path, "package.json");
if (existsSync(packageJSONPath)) {
const packageJSON = JSON.parse(
await readFile(packageJSONPath, "utf8")
);
if (packageJSON?.packageManager) {
const {
name,
version = "0.0.0",
buildMeta,
warnings
} = parsePackageManagerField(packageJSON.packageManager);
if (name) {
const majorVersion = version.split(".")[0];
const packageManager = packageManagers.find(
(pm) => pm.name === name && pm.majorVersion === majorVersion
) || packageManagers.find((pm) => pm.name === name);
return {
name,
command: name,
version,
majorVersion,
buildMeta,
warnings,
files: packageManager?.files,
lockFile: packageManager?.lockFile
};
}
}
}
const denoJSONPath = join(path, "deno.json");
if (existsSync(denoJSONPath)) {
return packageManagers.find((pm) => pm.name === "deno");
}
}
if (!options.ignoreLockFile) {
for (const packageManager of packageManagers) {
const detectionsFiles = [
packageManager.lockFile,
packageManager.files
].flat().filter(Boolean);
if (detectionsFiles.some((file) => existsSync(resolve(path, file)))) {
return {
...packageManager
};
}
}
}
},
{
includeParentDirs: options.includeParentDirs ?? true
}
);
if (!detected && !options.ignoreArgv) {
const scriptArg = process.argv[1];
if (scriptArg) {
for (const packageManager of packageManagers) {
const re = new RegExp(`[/\\\\]\\.?${packageManager.command}`);
if (re.test(scriptArg)) {
return packageManager;
}
}
}
}
return detected;
}
function kirbyupHmrPlugin(options) {
let config;
let entry;
let devIndexPath;
return {
name: "kirbyup:hmr",
apply: "serve",
configResolved(resolvedConfig) {
config = resolvedConfig;
entry = resolve(config.root, options.entry);
devIndexPath = resolve(config.root, options.outDir || "", "index.dev.mjs");
},
transform(code, id) {
if (isHmrRuntimeId(id)) {
return code.replace(
// https://github.com/vitejs/vite-plugin-vue2/blob/8de73ea6b8a1df4c14308da2885db195dacc2b14/src/utils/hmrRuntime.ts#L173
/^.*=\s*record\.Ctor\.super\.extend\(options\)/m,
"$_applyKirbyModifications(record.Ctor.options, options) // injected by kirbyup\n$&"
) + __INJECTED_HMR_CODE__;
}
},
configureServer(server) {
if (!server.httpServer)
return;
server.httpServer.once("listening", async () => {
const entryPath = entry.replace(`${config.root}/`, "");
const { address, family, port } = server.httpServer.address();
const hostname = family === "IPv6" ? `[${address}]` : address;
const baseUrl = `http://${hostname}:${port}${config.base}`;
const entryUrl = new URL(entryPath, baseUrl).href;
const pm = await detectPackageManager(config.root);
await fsp.writeFile(devIndexPath, getViteProxyModule(entryUrl, pm));
});
},
closeBundle() {
if (fs.existsSync(devIndexPath))
fs.unlinkSync(devIndexPath);
}
};
}
function getViteProxyModule(entryUrl, packageManager) {
const pm = packageManager?.name || "npm";
return `
try {
await import("${entryUrl}");
} catch (err) {
console.error(
"[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."
);
throw err;
}
`.trimStart();
}
function toArray(array) {
array ??= [];
return Array.isArray(array) ? array : [array];
}
const compress = promisify(gzip);
async function getCompressedSize(code) {
const size = (await compress(typeof code === "string" ? code : Buffer$1.from(code))).length / 1024;
return ` / gzip: ${size.toFixed(2)} KiB`;
}
async function printFileInfo(root, outDir, filePath, content, type, maxLength) {
const prettyOutDir = `${normalize(relative(root, resolve(root, outDir)))}/`;
const kibs = content.length / 1024;
const compressedSize = await getCompressedSize(content);
const writeColor = type === "chunk" ? colors.cyan : colors.magenta;
consola.log(
colors.white(colors.dim(prettyOutDir)) + writeColor(filePath.padEnd(maxLength + 2)) + colors.dim(`${kibs.toFixed(2)} kB${compressedSize}`)
);
}
let resolvedKirbyupConfig;
let resolvedPostCssConfig;
const logLevel = "warn";
const logger = createLogger(logLevel);
const loggerWarn = logger.warn;
logger.warn = (msg, options) => {
if (msg.includes("(!) build.outDir"))
return;
loggerWarn(msg, options);
};
function getViteConfig(command, options) {
const aliasDir = resolve(options.cwd, dirname(options.entry));
const { alias = {}, vite, extendViteConfig } = resolvedKirbyupConfig;
const userConfig = vite ?? extendViteConfig ?? {};
const sharedConfig = {
resolve: {
alias: {
"~/": `${aliasDir}/`,
"@/": `${aliasDir}/`,
...alias
}
},
plugins: [
// Explicitly pass the compiler, since the plugin's resolving of the compiler
// looks in the current directory and breaks `npx kirbyup`
vuePlugin({ compiler: vueCompilerSfc }),
vueJsxPlugin(),
kirbyupGlobImportPlugin(),
{ ...externalGlobals({ vue: "Vue" }), enforce: "post" }
],
build: {
copyPublicDir: false
},
...resolvedPostCssConfig && {
css: {
postcss: resolvedPostCssConfig
}
},
envDir: options.cwd,
envPrefix: ["VITE_", "KIRBYUP_"],
customLogger: logger,
logLevel
};
if (command === "serve") {
const { port, watch } = options;
const serveConfig = mergeConfig(sharedConfig, {
plugins: [
kirbyupHmrPlugin(options),
watch && fullReloadPlugin(watch)
].filter(Boolean),
// Input needs to be specified so dependency pre-bundling works
build: {
rollupOptions: {
input: resolve(options.cwd, options.entry)
}
},
// Specify origin so asset URLs include Vite server host
server: {
port,
strictPort: true,
origin: `http://localhost:${port}`
}
});
return mergeConfig(serveConfig, userConfig);
}
const mode = options.watch ? "development" : "production";
const buildConfig = mergeConfig(sharedConfig, {
mode,
plugins: [kirbyupBuildCleanupPlugin(options)],
build: {
lib: {
entry: resolve(options.cwd, options.entry),
formats: ["iife"],
name: "kirbyupExport",
fileName: () => "index.js"
},
minify: mode === "production",
outDir: options.outDir,
emptyOutDir: false,
rollupOptions: {
output: {
assetFileNames: "index.[ext]"
}
}
}
});
return mergeConfig(buildConfig, userConfig);
}
async function generate(options) {
const config = getViteConfig("build", options);
let result;
try {
result = await build$1(config);
} catch (error) {
consola.error("Build failed");
if (config.mode === "production")
throw error;
}
if (result && !options.watch) {
const { output } = toArray(result)[0];
let longest = 0;
for (const file in output) {
const l = output[file].fileName.length;
if (l > longest)
longest = l;
}
for (const { fileName, type, code } of output) {
await printFileInfo(
options.cwd,
options.outDir,
fileName,
code ?? await fsp.readFile(resolve(options.outDir, fileName), "utf8"),
type,
longest
);
}
}
return result;
}
async function build(options) {
assertEntryExists(options);
const { cwd } = options;
const { config, configFile } = await loadConfig(cwd);
resolvedKirbyupConfig = config ?? {};
resolvedPostCssConfig = await resolvePostCSSConfig(cwd);
{
consola.log(colors.green(`${name} v${version}`));
consola.start(`Building ${colors.cyan(options.entry)}`);
}
if (options.watch)
consola.info("Running in watch mode");
const debouncedBuild = debounce(async () => {
generate(options).catch(handleError);
}, 100);
const startWatcher = async () => {
if (!options.watch)
return;
const { watch } = await import('chokidar');
const ignored = [
"**/{.git,node_modules}/**",
// Always ignore dist files
"index.{css,js}"
];
const watchPaths = typeof options.watch === "boolean" ? dirname(options.entry) : Array.isArray(options.watch) ? options.watch.filter(
(path) => typeof path === "string"
) : options.watch;
consola.info(
`Watching for changes in ${toArray(watchPaths).map((i) => colors.cyan(i)).join(", ")}`
);
const watcher = watch(watchPaths, {
ignoreInitial: true,
ignorePermissionErrors: true,
ignored,
cwd
});
if (configFile)
watcher.add(configFile);
watcher.on("all", async (type, file) => {
const absolutePath = resolve(cwd, file);
if (configFile === absolutePath) {
resolvedKirbyupConfig = (await loadConfig(cwd)).config ?? {};
consola.info(
`${colors.cyan(basename(file))} changed, setting new config`
);
} else {
consola.log(`${colors.green(type)} ${colors.white(colors.dim(file))}`);
}
debouncedBuild();
});
};
await generate(options);
consola.success("Build successful");
startWatcher();
}
async function serve(options) {
assertEntryExists(options);
const { cwd } = options;
const { config } = await loadConfig(cwd);
resolvedKirbyupConfig = config ?? {};
resolvedPostCssConfig = await resolvePostCSSConfig(cwd);
{
consola.log(colors.green(`${name} v${version}`));
consola.info("Starting development server...");
}
const server = await createServer(getViteConfig("serve", options));
await server.listen();
consola.success(`Server is listening on :${server.config.server.port}`);
return server;
}
function assertEntryExists(options) {
if (!fs.existsSync(resolve(options.cwd, options.entry)))
throw new PrettyError(`Cannot find "${options.entry}"`);
}
export { build as b, handleError as h, name as n, serve as s, version as v };