kirbyup 3.3.0 → 3.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/bin/kirbyup.mjs +1 -1
- package/dist/client/config.d.ts +4 -4
- package/dist/client/config.js +7 -0
- package/dist/client/plugin.d.ts +7 -12
- package/dist/client/plugin.js +14 -0
- package/dist/node/cli-start.js +42 -0
- package/dist/node/cli.d.ts +1 -2
- package/dist/node/cli.js +8 -0
- package/dist/node/config.js +22 -0
- package/dist/node/errors.js +18 -0
- package/dist/node/index.d.ts +6 -5
- package/dist/node/index.js +175 -0
- package/dist/node/plugins/build-cleanup.js +21 -0
- package/dist/node/plugins/glob-import.js +35 -0
- package/dist/node/plugins/hmr.js +57 -0
- package/dist/node/plugins/utils.js +113 -0
- package/dist/node/types.d.ts +44 -0
- package/dist/node/utils.js +26 -0
- package/dist/package.js +6 -0
- package/package.json +30 -29
- package/dist/client/config.d.mts +0 -6
- package/dist/client/config.mjs +0 -5
- package/dist/client/plugin.d.mts +0 -12
- package/dist/client/plugin.mjs +0 -24
- package/dist/node/cli.d.mts +0 -2
- package/dist/node/cli.mjs +0 -58
- package/dist/node/index.d.mts +0 -7
- package/dist/node/index.mjs +0 -25
- package/dist/shared/kirbyup.BtejYnwg.mjs +0 -928
- package/dist/shared/kirbyup.DNMktHWN.d.mts +0 -43
- package/dist/shared/kirbyup.DNMktHWN.d.ts +0 -43
package/README.md
CHANGED
package/bin/kirbyup.mjs
CHANGED
package/dist/client/config.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import 'vite';
|
|
1
|
+
import { UserConfig } from "../node/types.js";
|
|
3
2
|
|
|
3
|
+
//#region src/client/config.d.ts
|
|
4
4
|
declare function defineConfig(config: UserConfig): UserConfig;
|
|
5
|
-
|
|
6
|
-
export { defineConfig };
|
|
5
|
+
//#endregion
|
|
6
|
+
export { defineConfig };
|
package/dist/client/plugin.d.ts
CHANGED
|
@@ -1,12 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
*/
|
|
9
|
-
import(glob: string): Record<string, any>;
|
|
10
|
-
}>;
|
|
11
|
-
|
|
12
|
-
export { kirbyup };
|
|
1
|
+
//#region src/client/plugin.d.ts
|
|
2
|
+
interface KirbyupUtilities {
|
|
3
|
+
import: (glob: string) => Record<string, any>;
|
|
4
|
+
}
|
|
5
|
+
declare const kirbyup: Readonly<KirbyupUtilities>;
|
|
6
|
+
//#endregion
|
|
7
|
+
export { KirbyupUtilities, kirbyup };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
//#region src/client/plugin.ts
|
|
2
|
+
const kirbyup = Object.freeze({ import(glob) {
|
|
3
|
+
const modules = glob;
|
|
4
|
+
return Object.entries(modules).reduce((accumulator, [path, component]) => {
|
|
5
|
+
accumulator[getComponentName(path)] = component.default;
|
|
6
|
+
return accumulator;
|
|
7
|
+
}, {});
|
|
8
|
+
} });
|
|
9
|
+
function getComponentName(path) {
|
|
10
|
+
return path.substring(path.lastIndexOf("/") + 1, path.lastIndexOf(".")).toLowerCase();
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
//#endregion
|
|
14
|
+
export { kirbyup };
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { name, version } from "../package.js";
|
|
2
|
+
import { build, serve } from "./index.js";
|
|
3
|
+
import { cac } from "cac";
|
|
4
|
+
|
|
5
|
+
//#region src/node/cli-start.ts
|
|
6
|
+
async function startCli(cwd = process.cwd(), argv = process.argv) {
|
|
7
|
+
const cli = cac(name);
|
|
8
|
+
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) => {
|
|
9
|
+
process.env.NODE_ENV ||= options.watch ? "development" : "production";
|
|
10
|
+
await build({
|
|
11
|
+
cwd,
|
|
12
|
+
entry: file,
|
|
13
|
+
...options
|
|
14
|
+
});
|
|
15
|
+
});
|
|
16
|
+
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) => {
|
|
17
|
+
process.env.NODE_ENV ||= "development";
|
|
18
|
+
const server = await serve({
|
|
19
|
+
cwd,
|
|
20
|
+
entry: file,
|
|
21
|
+
...options
|
|
22
|
+
});
|
|
23
|
+
const exitProcess = async () => {
|
|
24
|
+
try {
|
|
25
|
+
await server.close();
|
|
26
|
+
} finally {
|
|
27
|
+
process.exit();
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
process.once("SIGINT", exitProcess);
|
|
31
|
+
});
|
|
32
|
+
cli.help((s) => s.map((msg) => ({
|
|
33
|
+
...msg,
|
|
34
|
+
body: msg.body.replace(" (default: \0)", "")
|
|
35
|
+
})));
|
|
36
|
+
cli.version(version);
|
|
37
|
+
cli.parse(argv, { run: false });
|
|
38
|
+
await cli.runMatchedCommand();
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
//#endregion
|
|
42
|
+
export { startCli };
|
package/dist/node/cli.d.ts
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
|
|
2
|
-
export { };
|
|
1
|
+
export {};
|
package/dist/node/cli.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { loadConfig } from "c12";
|
|
2
|
+
import postcssrc from "postcss-load-config";
|
|
3
|
+
|
|
4
|
+
//#region src/node/config.ts
|
|
5
|
+
function loadConfig$1(cwd = process.cwd()) {
|
|
6
|
+
return loadConfig({
|
|
7
|
+
cwd,
|
|
8
|
+
name: "kirbyup",
|
|
9
|
+
rcFile: false,
|
|
10
|
+
packageJson: false
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
async function resolvePostCSSConfig(cwd) {
|
|
14
|
+
try {
|
|
15
|
+
return await postcssrc(void 0, void 0, { stopDir: cwd });
|
|
16
|
+
} catch (error) {
|
|
17
|
+
if (!error.message.includes("No PostCSS Config found")) throw error;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
//#endregion
|
|
22
|
+
export { loadConfig$1 as loadConfig, resolvePostCSSConfig };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { consola } from "consola";
|
|
2
|
+
|
|
3
|
+
//#region src/node/errors.ts
|
|
4
|
+
var PrettyError = class extends Error {
|
|
5
|
+
constructor(message) {
|
|
6
|
+
super(message);
|
|
7
|
+
this.name = this.constructor.name;
|
|
8
|
+
if (typeof Error.captureStackTrace === "function") Error.captureStackTrace(this, this.constructor);
|
|
9
|
+
else this.stack = new Error(message).stack;
|
|
10
|
+
}
|
|
11
|
+
};
|
|
12
|
+
function handleError(error) {
|
|
13
|
+
consola.error(error.message);
|
|
14
|
+
process.exitCode = 1;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
//#endregion
|
|
18
|
+
export { PrettyError, handleError };
|
package/dist/node/index.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
1
|
+
import { BuildOptions, ServeOptions } from "./types.js";
|
|
2
|
+
import { ViteDevServer } from "vite";
|
|
3
3
|
|
|
4
|
+
//#region src/node/index.d.ts
|
|
4
5
|
declare function build(options: BuildOptions): Promise<void>;
|
|
5
|
-
declare function serve(options: ServeOptions): Promise<
|
|
6
|
-
|
|
7
|
-
export { build, serve };
|
|
6
|
+
declare function serve(options: ServeOptions): Promise<ViteDevServer>;
|
|
7
|
+
//#endregion
|
|
8
|
+
export { build, serve };
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import { name, version } from "../package.js";
|
|
2
|
+
import { loadConfig, resolvePostCSSConfig } from "./config.js";
|
|
3
|
+
import { PrettyError, handleError } from "./errors.js";
|
|
4
|
+
import kirbyupBuildCleanupPlugin from "./plugins/build-cleanup.js";
|
|
5
|
+
import kirbyupGlobImportPlugin from "./plugins/glob-import.js";
|
|
6
|
+
import kirbyupHmrPlugin from "./plugins/hmr.js";
|
|
7
|
+
import { printFileInfo, toArray } from "./utils.js";
|
|
8
|
+
import * as fs from "node:fs";
|
|
9
|
+
import * as fsp from "node:fs/promises";
|
|
10
|
+
import vuePlugin from "@vitejs/plugin-vue2";
|
|
11
|
+
import vueJsxPlugin from "@vitejs/plugin-vue2-jsx";
|
|
12
|
+
import { consola } from "consola";
|
|
13
|
+
import { colors } from "consola/utils";
|
|
14
|
+
import { basename, dirname, resolve } from "pathe";
|
|
15
|
+
import { debounce } from "perfect-debounce";
|
|
16
|
+
import externalGlobals from "rollup-plugin-external-globals";
|
|
17
|
+
import { build as build$1, createLogger, createServer, mergeConfig } from "vite";
|
|
18
|
+
import fullReloadPlugin from "vite-plugin-full-reload";
|
|
19
|
+
import * as vueCompilerSfc from "vue/compiler-sfc";
|
|
20
|
+
|
|
21
|
+
//#region src/node/index.ts
|
|
22
|
+
let resolvedKirbyupConfig;
|
|
23
|
+
let resolvedPostCssConfig;
|
|
24
|
+
const logLevel = "warn";
|
|
25
|
+
const logger = createLogger(logLevel);
|
|
26
|
+
const loggerWarn = logger.warn;
|
|
27
|
+
logger.warn = (msg, options) => {
|
|
28
|
+
if (msg.includes("(!) build.outDir")) return;
|
|
29
|
+
loggerWarn(msg, options);
|
|
30
|
+
};
|
|
31
|
+
function getViteConfig(command, options) {
|
|
32
|
+
const aliasDir = resolve(options.cwd, dirname(options.entry));
|
|
33
|
+
const { alias = {}, vite, extendViteConfig } = resolvedKirbyupConfig;
|
|
34
|
+
const userConfig = vite ?? extendViteConfig ?? {};
|
|
35
|
+
const sharedConfig = {
|
|
36
|
+
resolve: { alias: {
|
|
37
|
+
"~/": `${aliasDir}/`,
|
|
38
|
+
"@/": `${aliasDir}/`,
|
|
39
|
+
...alias
|
|
40
|
+
} },
|
|
41
|
+
plugins: [
|
|
42
|
+
vuePlugin({ compiler: vueCompilerSfc }),
|
|
43
|
+
vueJsxPlugin(),
|
|
44
|
+
kirbyupGlobImportPlugin(),
|
|
45
|
+
{
|
|
46
|
+
...externalGlobals({ vue: "Vue" }),
|
|
47
|
+
enforce: "post"
|
|
48
|
+
}
|
|
49
|
+
],
|
|
50
|
+
build: { copyPublicDir: false },
|
|
51
|
+
...resolvedPostCssConfig && { css: { postcss: resolvedPostCssConfig } },
|
|
52
|
+
envDir: options.cwd,
|
|
53
|
+
envPrefix: ["VITE_", "KIRBYUP_"],
|
|
54
|
+
customLogger: logger,
|
|
55
|
+
logLevel
|
|
56
|
+
};
|
|
57
|
+
if (command === "serve") {
|
|
58
|
+
const { port, watch } = options;
|
|
59
|
+
const serveConfig = mergeConfig(sharedConfig, {
|
|
60
|
+
plugins: [kirbyupHmrPlugin(options), watch && fullReloadPlugin(watch)].filter(Boolean),
|
|
61
|
+
build: { rollupOptions: { input: resolve(options.cwd, options.entry) } },
|
|
62
|
+
server: {
|
|
63
|
+
port,
|
|
64
|
+
strictPort: true,
|
|
65
|
+
origin: `http://localhost:${port}`
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
return mergeConfig(serveConfig, userConfig);
|
|
69
|
+
}
|
|
70
|
+
const mode = options.watch ? "development" : "production";
|
|
71
|
+
const buildConfig = mergeConfig(sharedConfig, {
|
|
72
|
+
mode,
|
|
73
|
+
plugins: [kirbyupBuildCleanupPlugin(options)],
|
|
74
|
+
build: {
|
|
75
|
+
lib: {
|
|
76
|
+
entry: resolve(options.cwd, options.entry),
|
|
77
|
+
formats: ["iife"],
|
|
78
|
+
name: "kirbyupExport",
|
|
79
|
+
fileName: () => "index.js"
|
|
80
|
+
},
|
|
81
|
+
minify: mode === "production",
|
|
82
|
+
outDir: options.outDir,
|
|
83
|
+
emptyOutDir: false,
|
|
84
|
+
rollupOptions: { output: { assetFileNames: "index.[ext]" } }
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
return mergeConfig(buildConfig, userConfig);
|
|
88
|
+
}
|
|
89
|
+
async function generate(options) {
|
|
90
|
+
const config = getViteConfig("build", options);
|
|
91
|
+
let result;
|
|
92
|
+
try {
|
|
93
|
+
result = await build$1(config);
|
|
94
|
+
} catch (error) {
|
|
95
|
+
consola.error("Build failed");
|
|
96
|
+
if (config.mode === "production") throw error;
|
|
97
|
+
}
|
|
98
|
+
if (result && !options.watch) {
|
|
99
|
+
const { output } = toArray(result)[0];
|
|
100
|
+
let maxLength = 0;
|
|
101
|
+
for (const chunkFile in output) {
|
|
102
|
+
const fileNameLength = output[chunkFile].fileName.length;
|
|
103
|
+
if (fileNameLength > maxLength) maxLength = fileNameLength;
|
|
104
|
+
}
|
|
105
|
+
for (const { fileName, type, code } of output) {
|
|
106
|
+
const content = code || await fsp.readFile(resolve(options.outDir, fileName), "utf8");
|
|
107
|
+
await printFileInfo({
|
|
108
|
+
root: options.cwd,
|
|
109
|
+
outDir: options.outDir,
|
|
110
|
+
filePath: fileName,
|
|
111
|
+
content,
|
|
112
|
+
type,
|
|
113
|
+
maxLength
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
return result;
|
|
118
|
+
}
|
|
119
|
+
async function build(options) {
|
|
120
|
+
assertEntryExists(options);
|
|
121
|
+
const { cwd } = options;
|
|
122
|
+
const { config, configFile } = await loadConfig(cwd);
|
|
123
|
+
resolvedKirbyupConfig = config ?? {};
|
|
124
|
+
resolvedPostCssConfig = await resolvePostCSSConfig(cwd);
|
|
125
|
+
consola.log(colors.green(`${name} v${version}`));
|
|
126
|
+
consola.start(`Building ${colors.cyan(options.entry)}`);
|
|
127
|
+
if (options.watch) consola.info("Running in watch mode");
|
|
128
|
+
const debouncedBuild = debounce(async () => {
|
|
129
|
+
generate(options).catch(handleError);
|
|
130
|
+
}, 100);
|
|
131
|
+
const startWatcher = async () => {
|
|
132
|
+
if (!options.watch) return;
|
|
133
|
+
const { watch } = await import("chokidar");
|
|
134
|
+
const ignored = ["**/{.git,node_modules}/**", "index.{css,js}"];
|
|
135
|
+
const watchPaths = typeof options.watch === "boolean" ? dirname(options.entry) : Array.isArray(options.watch) ? options.watch.filter((path) => typeof path === "string") : options.watch;
|
|
136
|
+
consola.info(`Watching for changes in ${toArray(watchPaths).map((i) => colors.cyan(i)).join(", ")}`);
|
|
137
|
+
const watcher = watch(watchPaths, {
|
|
138
|
+
ignoreInitial: true,
|
|
139
|
+
ignorePermissionErrors: true,
|
|
140
|
+
ignored,
|
|
141
|
+
cwd
|
|
142
|
+
});
|
|
143
|
+
if (configFile) watcher.add(configFile);
|
|
144
|
+
watcher.on("all", async (type, file) => {
|
|
145
|
+
const absolutePath = resolve(cwd, file);
|
|
146
|
+
if (configFile === absolutePath) {
|
|
147
|
+
resolvedKirbyupConfig = (await loadConfig(cwd)).config ?? {};
|
|
148
|
+
consola.info(`${colors.cyan(basename(file))} changed, setting new config`);
|
|
149
|
+
} else consola.log(`${colors.green(type)} ${colors.white(colors.dim(file))}`);
|
|
150
|
+
debouncedBuild();
|
|
151
|
+
});
|
|
152
|
+
};
|
|
153
|
+
await generate(options);
|
|
154
|
+
consola.success("Build successful");
|
|
155
|
+
startWatcher();
|
|
156
|
+
}
|
|
157
|
+
async function serve(options) {
|
|
158
|
+
assertEntryExists(options);
|
|
159
|
+
const { cwd } = options;
|
|
160
|
+
const { config } = await loadConfig(cwd);
|
|
161
|
+
resolvedKirbyupConfig = config ?? {};
|
|
162
|
+
resolvedPostCssConfig = await resolvePostCSSConfig(cwd);
|
|
163
|
+
consola.log(colors.green(`${name} v${version}`));
|
|
164
|
+
consola.info("Starting development server...");
|
|
165
|
+
const server = await createServer(getViteConfig("serve", options));
|
|
166
|
+
await server.listen();
|
|
167
|
+
consola.success(`Server is listening on :${server.config.server.port}`);
|
|
168
|
+
return server;
|
|
169
|
+
}
|
|
170
|
+
function assertEntryExists(options) {
|
|
171
|
+
if (!fs.existsSync(resolve(options.cwd, options.entry))) throw new PrettyError(`Cannot find "${options.entry}"`);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
//#endregion
|
|
175
|
+
export { build, serve };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import * as fs from "node:fs";
|
|
2
|
+
import { resolve } from "pathe";
|
|
3
|
+
|
|
4
|
+
//#region src/node/plugins/build-cleanup.ts
|
|
5
|
+
function kirbyupBuildCleanupPlugin(options) {
|
|
6
|
+
let config;
|
|
7
|
+
let devIndexPath;
|
|
8
|
+
return {
|
|
9
|
+
name: "kirbyup:build-cleanup",
|
|
10
|
+
configResolved(resolvedConfig) {
|
|
11
|
+
config = resolvedConfig;
|
|
12
|
+
devIndexPath = resolve(config.root, options.outDir, "index.dev.mjs");
|
|
13
|
+
},
|
|
14
|
+
writeBundle() {
|
|
15
|
+
if (fs.existsSync(devIndexPath)) fs.unlinkSync(devIndexPath);
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
//#endregion
|
|
21
|
+
export { kirbyupBuildCleanupPlugin as default };
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { multilineCommentsRE, singlelineCommentsRE } from "./utils.js";
|
|
2
|
+
import MagicString from "magic-string";
|
|
3
|
+
|
|
4
|
+
//#region src/node/plugins/glob-import.ts
|
|
5
|
+
/**
|
|
6
|
+
* Transforms `kirbyup.import(<path>)` to `kirbyup.import(import.meta.glob(<path>, { eager: true }))`
|
|
7
|
+
*/
|
|
8
|
+
function kirbyupGlobImportPlugin() {
|
|
9
|
+
let config;
|
|
10
|
+
return {
|
|
11
|
+
name: "kirbyup:glob-import",
|
|
12
|
+
configResolved(resolvedConfig) {
|
|
13
|
+
config = resolvedConfig;
|
|
14
|
+
},
|
|
15
|
+
async transform(code) {
|
|
16
|
+
if (!code.includes("kirbyup.import")) return;
|
|
17
|
+
const kirbyupImportRE = /\bkirbyup\.import\s*\(\s*('[^']+'|"[^"]+"|`[^`]+`)\s*\)/g;
|
|
18
|
+
const noCommentsCode = code.replace(multilineCommentsRE, (m) => " ".repeat(m.length)).replace(singlelineCommentsRE, (m) => " ".repeat(m.length));
|
|
19
|
+
let s;
|
|
20
|
+
let match;
|
|
21
|
+
while (match = kirbyupImportRE.exec(noCommentsCode)) {
|
|
22
|
+
const { 0: exp, 1: rawPath, index } = match;
|
|
23
|
+
if (!s) s = new MagicString(code);
|
|
24
|
+
s.overwrite(index, index + exp.length, `kirbyup.import(import.meta.glob(${rawPath}, { eager: true }))`);
|
|
25
|
+
}
|
|
26
|
+
if (s) return {
|
|
27
|
+
code: s.toString(),
|
|
28
|
+
map: config.build.sourcemap ? s.generateMap({ hires: true }) : void 0
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
//#endregion
|
|
35
|
+
export { kirbyupGlobImportPlugin as default };
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { __INJECTED_HMR_CODE__, isHmrRuntimeId } from "./utils.js";
|
|
2
|
+
import * as fs from "node:fs";
|
|
3
|
+
import * as fsp from "node:fs/promises";
|
|
4
|
+
import { resolve } from "pathe";
|
|
5
|
+
import { detectPackageManager } from "nypm";
|
|
6
|
+
|
|
7
|
+
//#region src/node/plugins/hmr.ts
|
|
8
|
+
function kirbyupHmrPlugin(options) {
|
|
9
|
+
let config;
|
|
10
|
+
let entry;
|
|
11
|
+
let devIndexPath;
|
|
12
|
+
return {
|
|
13
|
+
name: "kirbyup:hmr",
|
|
14
|
+
apply: "serve",
|
|
15
|
+
configResolved(resolvedConfig) {
|
|
16
|
+
config = resolvedConfig;
|
|
17
|
+
entry = resolve(config.root, options.entry);
|
|
18
|
+
devIndexPath = resolve(config.root, options.outDir || "", "index.dev.mjs");
|
|
19
|
+
},
|
|
20
|
+
transform(code, id) {
|
|
21
|
+
if (isHmrRuntimeId(id)) return code.replace(/^.*=\s*record\.Ctor\.super\.extend\(options\)/m, "$_applyKirbyModifications(record.Ctor.options, options) // injected by kirbyup\n$&") + __INJECTED_HMR_CODE__;
|
|
22
|
+
},
|
|
23
|
+
configureServer(server) {
|
|
24
|
+
if (!server.httpServer) return;
|
|
25
|
+
server.httpServer.once("listening", async () => {
|
|
26
|
+
const entryPath = entry.replace(`${config.root}/`, "");
|
|
27
|
+
const { address, family, port } = server.httpServer.address();
|
|
28
|
+
const baseUrl = `http://${family === "IPv6" ? `[${address}]` : address}:${port}${config.base}`;
|
|
29
|
+
const entryUrl = new URL(entryPath, baseUrl).href;
|
|
30
|
+
const pm = await detectPackageManager(config.root);
|
|
31
|
+
await fsp.writeFile(devIndexPath, getViteProxyModule(entryUrl, pm));
|
|
32
|
+
});
|
|
33
|
+
},
|
|
34
|
+
closeBundle() {
|
|
35
|
+
if (fs.existsSync(devIndexPath)) fs.unlinkSync(devIndexPath);
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Proxy the JS file to "forward" the plugin script loaded by Kirby to the Vite server
|
|
41
|
+
*/
|
|
42
|
+
function getViteProxyModule(entryUrl, packageManager) {
|
|
43
|
+
const pm = packageManager?.name || "npm";
|
|
44
|
+
return `
|
|
45
|
+
try {
|
|
46
|
+
await import("${entryUrl}");
|
|
47
|
+
} catch (err) {
|
|
48
|
+
console.error(
|
|
49
|
+
"[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."
|
|
50
|
+
);
|
|
51
|
+
throw err;
|
|
52
|
+
}
|
|
53
|
+
`.trimStart();
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
//#endregion
|
|
57
|
+
export { kirbyupHmrPlugin as default };
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
//#region src/node/plugins/utils.ts
|
|
2
|
+
const multilineCommentsRE = /\/\*(.|[\r\n])*?\*\//g;
|
|
3
|
+
const singlelineCommentsRE = /\/\/.*/g;
|
|
4
|
+
const HMR_RUNTIME_ID = "\0plugin-vue2:hmr-runtime";
|
|
5
|
+
const JSX_HMR_RUNTIME_ID = "plugin-vue2-jsx:hmr-runtime";
|
|
6
|
+
function isHmrRuntimeId(id) {
|
|
7
|
+
return id === HMR_RUNTIME_ID || id === JSX_HMR_RUNTIME_ID;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* This code is injected into the HMR runtime of plugin-vue2(-jsx).
|
|
11
|
+
*
|
|
12
|
+
* All `.vue` components register themselves once with the HMR runtime, so their exported
|
|
13
|
+
* component definitions can be stored in a map, alongside the rendered component instances
|
|
14
|
+
* that are based off this definition. When a module is updated, the runtime applies all
|
|
15
|
+
* changes from the updated module to the stored definition, then re-renders the instances.
|
|
16
|
+
*
|
|
17
|
+
* ```js
|
|
18
|
+
* {
|
|
19
|
+
* [id]: { options: ComponentDefinition, instances: [...] }
|
|
20
|
+
* }
|
|
21
|
+
* ```
|
|
22
|
+
*
|
|
23
|
+
* However, in some cases (sections and blocks) Kirby does not actually register the
|
|
24
|
+
* object that is exported from a `.vue` file (and stored as definition) as component,
|
|
25
|
+
* instead it creates a new object and merges the definition from the `.vue` file in:
|
|
26
|
+
* https://github.com/getkirby/kirby/blob/main/panel/public/js/plugins.js#L22-L25
|
|
27
|
+
* After changes, the runtime updates the definition and re-renders the instances, but since
|
|
28
|
+
* they are derived from the object created by Kirby, not the stored definition, nothing happens.
|
|
29
|
+
* To fix that, we wrap `rerender()` and `reload()` so that before applying the updates, we first check
|
|
30
|
+
* if the updated definition belongs to a component added by a Kirby plugin. To do so, we can check
|
|
31
|
+
* whether the `__file` (added by plugin-vue2) or `__hmrId` (added by plugin-vue2-jsx) properties of the
|
|
32
|
+
* updated module and the plugin component match. If so, we look up the component definition that is
|
|
33
|
+
* _actually_ used by component instances rendered on the page (`window.panel.app.$options.components`)
|
|
34
|
+
* and if it differs from the one stored in the HMR runtime's map, we updates the map's reference.
|
|
35
|
+
*
|
|
36
|
+
* We also check the component name and add a `$_isSection` flag if it's `k-something-section`, because
|
|
37
|
+
* section components are hard to detect and need special treatment in `$_applyKirbyModifications`.
|
|
38
|
+
*
|
|
39
|
+
* `$_applyKirbyModifications`:
|
|
40
|
+
*
|
|
41
|
+
* Kirby modifies component definitions before registering components.
|
|
42
|
+
* This includes adding the section mixin to section components,
|
|
43
|
+
* giving templates priority over render functions if both exist
|
|
44
|
+
* and resolving component names in `extends` to their definition object:
|
|
45
|
+
* https://github.com/getkirby/kirby/blob/2965c3124e3b141072a2d46c798a327dda710060/panel/src/panel/plugins.js
|
|
46
|
+
* When a module is reloaded, Vue receives a fresh component definition that is
|
|
47
|
+
* missing these modifications. We need to re-apply them, else the runtime will
|
|
48
|
+
* prune them when patching the stored definition to match the newer one.
|
|
49
|
+
*
|
|
50
|
+
* The call to `$_applyKirbyModifications()` is injected into `__VUE_HMR_RUNTIME__.reload()`
|
|
51
|
+
* at the appropriate position using a RegExp in the Vite plugin's transform method.
|
|
52
|
+
*/
|
|
53
|
+
const __INJECTED_HMR_CODE__ = `
|
|
54
|
+
/** - injected by kirbyup - */
|
|
55
|
+
for (const methodName of ['rerender', 'reload']) {
|
|
56
|
+
const original = __VUE_HMR_RUNTIME__[methodName]
|
|
57
|
+
|
|
58
|
+
__VUE_HMR_RUNTIME__[methodName] = function (id, updatedDef) {
|
|
59
|
+
const key = updatedDef?.__file ? '__file' : updatedDef?.__hmrId ? '__hmrId' : null
|
|
60
|
+
|
|
61
|
+
if (key) {
|
|
62
|
+
const pluginComponents = window.panel.plugins.components
|
|
63
|
+
// const usedComponentDefs = window.panel.app.$options.components
|
|
64
|
+
const usedComponentDefs = window.panel.app._vnode.componentInstance.$options.components // #33
|
|
65
|
+
|
|
66
|
+
for (const componentName in pluginComponents) {
|
|
67
|
+
if (updatedDef[key] === pluginComponents[componentName][key]) {
|
|
68
|
+
const usedDefinition = usedComponentDefs[componentName].options
|
|
69
|
+
|
|
70
|
+
if (map[id].options !== usedDefinition)
|
|
71
|
+
map[id].options = usedDefinition
|
|
72
|
+
|
|
73
|
+
if (typeof map[id].options.$_isSection !== 'boolean')
|
|
74
|
+
map[id].options.$_isSection = /^k-.*-section$/.test(componentName)
|
|
75
|
+
|
|
76
|
+
break
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return original.apply(this, arguments)
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function $_applyKirbyModifications(activeDef, newDef) {
|
|
86
|
+
const usedComponentDefs = window.panel.app.$options.components
|
|
87
|
+
|
|
88
|
+
if (newDef.template)
|
|
89
|
+
newDef.render = null
|
|
90
|
+
|
|
91
|
+
if (activeDef.$_isSection)
|
|
92
|
+
newDef.$_isSection = true
|
|
93
|
+
if (newDef.$_isSection && !newDef.mixins?.[0]?.methods?.load)
|
|
94
|
+
newDef.mixins = [activeDef.mixins[0], ...(newDef.mixins || [])]
|
|
95
|
+
|
|
96
|
+
if (typeof newDef.extends === 'string') {
|
|
97
|
+
if (newDef.extends === activeDef.extends?.options?.name) {
|
|
98
|
+
newDef.extends = activeDef.extends
|
|
99
|
+
}
|
|
100
|
+
else if (usedComponentDefs[newDef.extends]) {
|
|
101
|
+
newDef.extends = usedComponentDefs[newDef.extends].extend({
|
|
102
|
+
options: newDef,
|
|
103
|
+
components: { ...usedComponentDefs, ...(newDef.components || {}) },
|
|
104
|
+
})
|
|
105
|
+
}
|
|
106
|
+
else { newDef.extends = null }
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
/** -- */
|
|
110
|
+
`;
|
|
111
|
+
|
|
112
|
+
//#endregion
|
|
113
|
+
export { __INJECTED_HMR_CODE__, isHmrRuntimeId, multilineCommentsRE, singlelineCommentsRE };
|
|
@@ -0,0 +1,44 @@
|
|
|
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
|
+
* @deprecated Use `vite` instead.
|
|
40
|
+
*/
|
|
41
|
+
extendViteConfig?: InlineConfig;
|
|
42
|
+
}
|
|
43
|
+
//#endregion
|
|
44
|
+
export { BuildOptions, ServeOptions, UserConfig };
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { consola } from "consola";
|
|
2
|
+
import { colors } from "consola/utils";
|
|
3
|
+
import { normalize, relative, resolve } from "pathe";
|
|
4
|
+
import { Buffer } from "node:buffer";
|
|
5
|
+
import { promisify } from "node:util";
|
|
6
|
+
import { gzip } from "node:zlib";
|
|
7
|
+
|
|
8
|
+
//#region src/node/utils.ts
|
|
9
|
+
const compress = promisify(gzip);
|
|
10
|
+
function toArray(array) {
|
|
11
|
+
array ??= [];
|
|
12
|
+
return Array.isArray(array) ? array : [array];
|
|
13
|
+
}
|
|
14
|
+
async function getCompressedSize(code) {
|
|
15
|
+
return ` / gzip: ${((await compress(typeof code === "string" ? code : Buffer.from(code))).length / 1024).toFixed(2)} KiB`;
|
|
16
|
+
}
|
|
17
|
+
async function printFileInfo({ root, outDir, filePath, content, type, maxLength }) {
|
|
18
|
+
const prettyOutDir = `${normalize(relative(root, resolve(root, outDir)))}/`;
|
|
19
|
+
const kibs = content.length / 1024;
|
|
20
|
+
const compressedSize = await getCompressedSize(content);
|
|
21
|
+
const writeColor = type === "chunk" ? colors.cyan : colors.magenta;
|
|
22
|
+
consola.log(colors.white(colors.dim(prettyOutDir)) + writeColor(filePath.padEnd(maxLength + 2)) + colors.dim(`${kibs.toFixed(2)} kB${compressedSize}`));
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
//#endregion
|
|
26
|
+
export { printFileInfo, toArray };
|