@vetta-org/plugin-vite 0.0.4 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/build-warning-filter.d.ts +8 -0
- package/dist/build-warning-filter.d.ts.map +1 -0
- package/dist/build-warning-filter.js +26 -0
- package/dist/build-warning-filter.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +83 -0
- package/dist/cli.js.map +1 -0
- package/dist/dev-events.d.ts +23 -0
- package/dist/dev-events.d.ts.map +1 -0
- package/dist/dev-events.js +9 -0
- package/dist/dev-events.js.map +1 -0
- package/dist/dev-server.d.ts +9 -0
- package/dist/dev-server.d.ts.map +1 -0
- package/dist/dev-server.js +239 -0
- package/dist/dev-server.js.map +1 -0
- package/dist/dev-vite-plugins.d.ts +5 -0
- package/dist/dev-vite-plugins.d.ts.map +1 -0
- package/dist/dev-vite-plugins.js +144 -0
- package/dist/dev-vite-plugins.js.map +1 -0
- package/dist/host-theme.d.ts +5 -0
- package/dist/host-theme.d.ts.map +1 -0
- package/dist/host-theme.js +42 -0
- package/dist/host-theme.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +97 -4
- package/dist/index.js.map +1 -1
- package/dist/pack.d.ts +4 -0
- package/dist/pack.d.ts.map +1 -1
- package/dist/pack.js +68 -87
- package/dist/pack.js.map +1 -1
- package/dist/permission-contract.d.ts +13 -0
- package/dist/permission-contract.d.ts.map +1 -0
- package/dist/permission-contract.js +94 -0
- package/dist/permission-contract.js.map +1 -0
- package/dist/request-query.d.ts +8 -0
- package/dist/request-query.d.ts.map +1 -0
- package/dist/request-query.js +19 -0
- package/dist/request-query.js.map +1 -0
- package/dist/style-scope.d.ts +8 -0
- package/dist/style-scope.d.ts.map +1 -1
- package/dist/style-scope.js +102 -3
- package/dist/style-scope.js.map +1 -1
- package/package.json +13 -3
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Plugin, Rollup } from "vite";
|
|
2
|
+
export declare function isIgnorableThirdPartyClientDirective(warning: Rollup.RollupLog): boolean;
|
|
3
|
+
/**
|
|
4
|
+
* `use client` is React Server Components metadata. Plugin remotes are browser-only,
|
|
5
|
+
* so Rollup intentionally discards the directive without changing runtime behavior.
|
|
6
|
+
*/
|
|
7
|
+
export declare function createPluginBuildWarningFilter(): Plugin;
|
|
8
|
+
//# sourceMappingURL=build-warning-filter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build-warning-filter.d.ts","sourceRoot":"","sources":["../src/build-warning-filter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAK3C,wBAAgB,oCAAoC,CAAC,OAAO,EAAE,MAAM,CAAC,SAAS,GAAG,OAAO,CAQvF;AAED;;;GAGG;AACH,wBAAgB,8BAA8B,IAAI,MAAM,CASvD","sourcesContent":["import type { Plugin, Rollup } from \"vite\";\n\nconst MODULE_LEVEL_DIRECTIVE_WARNING = \"MODULE_LEVEL_DIRECTIVE\";\nconst THIRD_PARTY_MODULE_PATH = /(?:^|\\/)node_modules\\//u;\n\nexport function isIgnorableThirdPartyClientDirective(warning: Rollup.RollupLog): boolean {\n\tif (warning.code !== MODULE_LEVEL_DIRECTIVE_WARNING || !warning.id) return false;\n\tconst normalizedId = warning.id.replaceAll(\"\\\\\", \"/\");\n\treturn (\n\t\tTHIRD_PARTY_MODULE_PATH.test(normalizedId) &&\n\t\twarning.message.includes(\"Module level directives cause errors when bundled\") &&\n\t\twarning.message.includes('\"use client\"')\n\t);\n}\n\n/**\n * `use client` is React Server Components metadata. Plugin remotes are browser-only,\n * so Rollup intentionally discards the directive without changing runtime behavior.\n */\nexport function createPluginBuildWarningFilter(): Plugin {\n\treturn {\n\t\tname: \"vetta-plugin-build-warning-filter\",\n\t\tapply: \"build\",\n\t\tonLog(level, log) {\n\t\t\tif (level === \"warn\" && isIgnorableThirdPartyClientDirective(log)) return false;\n\t\t\treturn null;\n\t\t},\n\t};\n}\n"]}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
const MODULE_LEVEL_DIRECTIVE_WARNING = "MODULE_LEVEL_DIRECTIVE";
|
|
2
|
+
const THIRD_PARTY_MODULE_PATH = /(?:^|\/)node_modules\//u;
|
|
3
|
+
export function isIgnorableThirdPartyClientDirective(warning) {
|
|
4
|
+
if (warning.code !== MODULE_LEVEL_DIRECTIVE_WARNING || !warning.id)
|
|
5
|
+
return false;
|
|
6
|
+
const normalizedId = warning.id.replaceAll("\\", "/");
|
|
7
|
+
return (THIRD_PARTY_MODULE_PATH.test(normalizedId) &&
|
|
8
|
+
warning.message.includes("Module level directives cause errors when bundled") &&
|
|
9
|
+
warning.message.includes('"use client"'));
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* `use client` is React Server Components metadata. Plugin remotes are browser-only,
|
|
13
|
+
* so Rollup intentionally discards the directive without changing runtime behavior.
|
|
14
|
+
*/
|
|
15
|
+
export function createPluginBuildWarningFilter() {
|
|
16
|
+
return {
|
|
17
|
+
name: "vetta-plugin-build-warning-filter",
|
|
18
|
+
apply: "build",
|
|
19
|
+
onLog(level, log) {
|
|
20
|
+
if (level === "warn" && isIgnorableThirdPartyClientDirective(log))
|
|
21
|
+
return false;
|
|
22
|
+
return null;
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=build-warning-filter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build-warning-filter.js","sourceRoot":"","sources":["../src/build-warning-filter.ts"],"names":[],"mappings":"AAEA,MAAM,8BAA8B,GAAG,wBAAwB,CAAC;AAChE,MAAM,uBAAuB,GAAG,yBAAyB,CAAC;AAE1D,MAAM,UAAU,oCAAoC,CAAC,OAAyB,EAAW;IACxF,IAAI,OAAO,CAAC,IAAI,KAAK,8BAA8B,IAAI,CAAC,OAAO,CAAC,EAAE;QAAE,OAAO,KAAK,CAAC;IACjF,MAAM,YAAY,GAAG,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IACtD,OAAO,CACN,uBAAuB,CAAC,IAAI,CAAC,YAAY,CAAC;QAC1C,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,mDAAmD,CAAC;QAC7E,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC,CACxC,CAAC;AAAA,CACF;AAED;;;GAGG;AACH,MAAM,UAAU,8BAA8B,GAAW;IACxD,OAAO;QACN,IAAI,EAAE,mCAAmC;QACzC,KAAK,EAAE,OAAO;QACd,KAAK,CAAC,KAAK,EAAE,GAAG,EAAE;YACjB,IAAI,KAAK,KAAK,MAAM,IAAI,oCAAoC,CAAC,GAAG,CAAC;gBAAE,OAAO,KAAK,CAAC;YAChF,OAAO,IAAI,CAAC;QAAA,CACZ;KACD,CAAC;AAAA,CACF","sourcesContent":["import type { Plugin, Rollup } from \"vite\";\n\nconst MODULE_LEVEL_DIRECTIVE_WARNING = \"MODULE_LEVEL_DIRECTIVE\";\nconst THIRD_PARTY_MODULE_PATH = /(?:^|\\/)node_modules\\//u;\n\nexport function isIgnorableThirdPartyClientDirective(warning: Rollup.RollupLog): boolean {\n\tif (warning.code !== MODULE_LEVEL_DIRECTIVE_WARNING || !warning.id) return false;\n\tconst normalizedId = warning.id.replaceAll(\"\\\\\", \"/\");\n\treturn (\n\t\tTHIRD_PARTY_MODULE_PATH.test(normalizedId) &&\n\t\twarning.message.includes(\"Module level directives cause errors when bundled\") &&\n\t\twarning.message.includes('\"use client\"')\n\t);\n}\n\n/**\n * `use client` is React Server Components metadata. Plugin remotes are browser-only,\n * so Rollup intentionally discards the directive without changing runtime behavior.\n */\nexport function createPluginBuildWarningFilter(): Plugin {\n\treturn {\n\t\tname: \"vetta-plugin-build-warning-filter\",\n\t\tapply: \"build\",\n\t\tonLog(level, log) {\n\t\t\tif (level === \"warn\" && isIgnorableThirdPartyClientDirective(log)) return false;\n\t\t\treturn null;\n\t\t},\n\t};\n}\n"]}
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"","sourcesContent":["#!/usr/bin/env node\n\nimport { readFile } from \"node:fs/promises\";\nimport { resolve } from \"node:path\";\nimport { parsePluginManifest } from \"@vetta-org/plugin-sdk/manifest\";\nimport { startVettaPluginDevServer } from \"./dev-server.js\";\nimport { createVettaPluginPackage } from \"./pack.js\";\n\ntype CliCommand = \"dev\" | \"pack\" | \"validate\";\n\ninterface CliOptions {\n\tcommand: CliCommand;\n\trootDir: string;\n}\n\nfunction parseCliOptions(argv: string[]): CliOptions {\n\tconst command = argv[0];\n\tif (command !== \"dev\" && command !== \"pack\" && command !== \"validate\") {\n\t\tthrow new Error(\"Usage: vetta-plugin <dev|validate|pack> [--root <plugin-directory>]\");\n\t}\n\tlet rootDir = process.cwd();\n\tfor (let index = 1; index < argv.length; index += 1) {\n\t\tconst argument = argv[index];\n\t\tif (argument !== \"--root\" || !argv[index + 1]) {\n\t\t\tthrow new Error(`Unknown or incomplete option: ${argument}`);\n\t\t}\n\t\trootDir = resolve(argv[index + 1]);\n\t\tindex += 1;\n\t}\n\treturn { command, rootDir };\n}\n\nfunction writeEvent(event: object): void {\n\tprocess.stdout.write(`${JSON.stringify(event)}\\n`);\n}\n\nasync function runDevServer(rootDir: string): Promise<void> {\n\tconst devServer = await startVettaPluginDevServer(rootDir, writeEvent);\n\tawait new Promise<void>((resolvePromise) => {\n\t\tlet closing = false;\n\t\tconst close = () => {\n\t\t\tif (closing) return;\n\t\t\tclosing = true;\n\t\t\tvoid devServer.close().finally(resolvePromise);\n\t\t};\n\t\tprocess.once(\"SIGINT\", close);\n\t\tprocess.once(\"SIGTERM\", close);\n\t});\n}\n\nasync function validateManifest(rootDir: string): Promise<void> {\n\tconst manifestPath = resolve(rootDir, \"plugin.json\");\n\tconst raw: unknown = JSON.parse(await readFile(manifestPath, \"utf8\"));\n\tconst manifest = parsePluginManifest(raw);\n\tprocess.stdout.write(\n\t\t`${JSON.stringify({\n\t\t\tok: true,\n\t\t\tid: manifest.id,\n\t\t\tversion: manifest.version,\n\t\t\tpluginApiVersion: manifest.pluginApiVersion,\n\t\t})}\\n`,\n\t);\n}\n\nasync function packPlugin(rootDir: string): Promise<void> {\n\tconst raw: unknown = JSON.parse(await readFile(resolve(rootDir, \"plugin.json\"), \"utf8\"));\n\tconst manifest = parsePluginManifest(raw);\n\tconst result = await createVettaPluginPackage({ rootDir });\n\tprocess.stdout.write(\n\t\t`${JSON.stringify({\n\t\t\tok: true,\n\t\t\tid: manifest.id,\n\t\t\tversion: manifest.version,\n\t\t\tzipPath: result.outputPath,\n\t\t\tfiles: result.files.map((file) => file.archivePath),\n\t\t})}\\n`,\n\t);\n}\n\nasync function main(): Promise<void> {\n\ttry {\n\t\tconst options = parseCliOptions(process.argv.slice(2));\n\t\tif (options.command === \"dev\") {\n\t\t\tawait runDevServer(options.rootDir);\n\t\t\treturn;\n\t\t}\n\t\tif (options.command === \"validate\") {\n\t\t\tawait validateManifest(options.rootDir);\n\t\t\treturn;\n\t\t}\n\t\tawait packPlugin(options.rootDir);\n\t} catch (error) {\n\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\tprocess.stderr.write(`${JSON.stringify({ ok: false, error: message })}\\n`);\n\t\tprocess.exitCode = 1;\n\t}\n}\n\nvoid main();\n"]}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { readFile } from "node:fs/promises";
|
|
3
|
+
import { resolve } from "node:path";
|
|
4
|
+
import { parsePluginManifest } from "@vetta-org/plugin-sdk/manifest";
|
|
5
|
+
import { startVettaPluginDevServer } from "./dev-server.js";
|
|
6
|
+
import { createVettaPluginPackage } from "./pack.js";
|
|
7
|
+
function parseCliOptions(argv) {
|
|
8
|
+
const command = argv[0];
|
|
9
|
+
if (command !== "dev" && command !== "pack" && command !== "validate") {
|
|
10
|
+
throw new Error("Usage: vetta-plugin <dev|validate|pack> [--root <plugin-directory>]");
|
|
11
|
+
}
|
|
12
|
+
let rootDir = process.cwd();
|
|
13
|
+
for (let index = 1; index < argv.length; index += 1) {
|
|
14
|
+
const argument = argv[index];
|
|
15
|
+
if (argument !== "--root" || !argv[index + 1]) {
|
|
16
|
+
throw new Error(`Unknown or incomplete option: ${argument}`);
|
|
17
|
+
}
|
|
18
|
+
rootDir = resolve(argv[index + 1]);
|
|
19
|
+
index += 1;
|
|
20
|
+
}
|
|
21
|
+
return { command, rootDir };
|
|
22
|
+
}
|
|
23
|
+
function writeEvent(event) {
|
|
24
|
+
process.stdout.write(`${JSON.stringify(event)}\n`);
|
|
25
|
+
}
|
|
26
|
+
async function runDevServer(rootDir) {
|
|
27
|
+
const devServer = await startVettaPluginDevServer(rootDir, writeEvent);
|
|
28
|
+
await new Promise((resolvePromise) => {
|
|
29
|
+
let closing = false;
|
|
30
|
+
const close = () => {
|
|
31
|
+
if (closing)
|
|
32
|
+
return;
|
|
33
|
+
closing = true;
|
|
34
|
+
void devServer.close().finally(resolvePromise);
|
|
35
|
+
};
|
|
36
|
+
process.once("SIGINT", close);
|
|
37
|
+
process.once("SIGTERM", close);
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
async function validateManifest(rootDir) {
|
|
41
|
+
const manifestPath = resolve(rootDir, "plugin.json");
|
|
42
|
+
const raw = JSON.parse(await readFile(manifestPath, "utf8"));
|
|
43
|
+
const manifest = parsePluginManifest(raw);
|
|
44
|
+
process.stdout.write(`${JSON.stringify({
|
|
45
|
+
ok: true,
|
|
46
|
+
id: manifest.id,
|
|
47
|
+
version: manifest.version,
|
|
48
|
+
pluginApiVersion: manifest.pluginApiVersion,
|
|
49
|
+
})}\n`);
|
|
50
|
+
}
|
|
51
|
+
async function packPlugin(rootDir) {
|
|
52
|
+
const raw = JSON.parse(await readFile(resolve(rootDir, "plugin.json"), "utf8"));
|
|
53
|
+
const manifest = parsePluginManifest(raw);
|
|
54
|
+
const result = await createVettaPluginPackage({ rootDir });
|
|
55
|
+
process.stdout.write(`${JSON.stringify({
|
|
56
|
+
ok: true,
|
|
57
|
+
id: manifest.id,
|
|
58
|
+
version: manifest.version,
|
|
59
|
+
zipPath: result.outputPath,
|
|
60
|
+
files: result.files.map((file) => file.archivePath),
|
|
61
|
+
})}\n`);
|
|
62
|
+
}
|
|
63
|
+
async function main() {
|
|
64
|
+
try {
|
|
65
|
+
const options = parseCliOptions(process.argv.slice(2));
|
|
66
|
+
if (options.command === "dev") {
|
|
67
|
+
await runDevServer(options.rootDir);
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
if (options.command === "validate") {
|
|
71
|
+
await validateManifest(options.rootDir);
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
await packPlugin(options.rootDir);
|
|
75
|
+
}
|
|
76
|
+
catch (error) {
|
|
77
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
78
|
+
process.stderr.write(`${JSON.stringify({ ok: false, error: message })}\n`);
|
|
79
|
+
process.exitCode = 1;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
void main();
|
|
83
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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","sourcesContent":["#!/usr/bin/env node\n\nimport { readFile } from \"node:fs/promises\";\nimport { resolve } from \"node:path\";\nimport { parsePluginManifest } from \"@vetta-org/plugin-sdk/manifest\";\nimport { startVettaPluginDevServer } from \"./dev-server.js\";\nimport { createVettaPluginPackage } from \"./pack.js\";\n\ntype CliCommand = \"dev\" | \"pack\" | \"validate\";\n\ninterface CliOptions {\n\tcommand: CliCommand;\n\trootDir: string;\n}\n\nfunction parseCliOptions(argv: string[]): CliOptions {\n\tconst command = argv[0];\n\tif (command !== \"dev\" && command !== \"pack\" && command !== \"validate\") {\n\t\tthrow new Error(\"Usage: vetta-plugin <dev|validate|pack> [--root <plugin-directory>]\");\n\t}\n\tlet rootDir = process.cwd();\n\tfor (let index = 1; index < argv.length; index += 1) {\n\t\tconst argument = argv[index];\n\t\tif (argument !== \"--root\" || !argv[index + 1]) {\n\t\t\tthrow new Error(`Unknown or incomplete option: ${argument}`);\n\t\t}\n\t\trootDir = resolve(argv[index + 1]);\n\t\tindex += 1;\n\t}\n\treturn { command, rootDir };\n}\n\nfunction writeEvent(event: object): void {\n\tprocess.stdout.write(`${JSON.stringify(event)}\\n`);\n}\n\nasync function runDevServer(rootDir: string): Promise<void> {\n\tconst devServer = await startVettaPluginDevServer(rootDir, writeEvent);\n\tawait new Promise<void>((resolvePromise) => {\n\t\tlet closing = false;\n\t\tconst close = () => {\n\t\t\tif (closing) return;\n\t\t\tclosing = true;\n\t\t\tvoid devServer.close().finally(resolvePromise);\n\t\t};\n\t\tprocess.once(\"SIGINT\", close);\n\t\tprocess.once(\"SIGTERM\", close);\n\t});\n}\n\nasync function validateManifest(rootDir: string): Promise<void> {\n\tconst manifestPath = resolve(rootDir, \"plugin.json\");\n\tconst raw: unknown = JSON.parse(await readFile(manifestPath, \"utf8\"));\n\tconst manifest = parsePluginManifest(raw);\n\tprocess.stdout.write(\n\t\t`${JSON.stringify({\n\t\t\tok: true,\n\t\t\tid: manifest.id,\n\t\t\tversion: manifest.version,\n\t\t\tpluginApiVersion: manifest.pluginApiVersion,\n\t\t})}\\n`,\n\t);\n}\n\nasync function packPlugin(rootDir: string): Promise<void> {\n\tconst raw: unknown = JSON.parse(await readFile(resolve(rootDir, \"plugin.json\"), \"utf8\"));\n\tconst manifest = parsePluginManifest(raw);\n\tconst result = await createVettaPluginPackage({ rootDir });\n\tprocess.stdout.write(\n\t\t`${JSON.stringify({\n\t\t\tok: true,\n\t\t\tid: manifest.id,\n\t\t\tversion: manifest.version,\n\t\t\tzipPath: result.outputPath,\n\t\t\tfiles: result.files.map((file) => file.archivePath),\n\t\t})}\\n`,\n\t);\n}\n\nasync function main(): Promise<void> {\n\ttry {\n\t\tconst options = parseCliOptions(process.argv.slice(2));\n\t\tif (options.command === \"dev\") {\n\t\t\tawait runDevServer(options.rootDir);\n\t\t\treturn;\n\t\t}\n\t\tif (options.command === \"validate\") {\n\t\t\tawait validateManifest(options.rootDir);\n\t\t\treturn;\n\t\t}\n\t\tawait packPlugin(options.rootDir);\n\t} catch (error) {\n\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\tprocess.stderr.write(`${JSON.stringify({ ok: false, error: message })}\\n`);\n\t\tprocess.exitCode = 1;\n\t}\n}\n\nvoid main();\n"]}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export declare const VETTA_PLUGIN_DEV_PROTOCOL_VERSION = 1;
|
|
2
|
+
export type VettaPluginDevEvent = {
|
|
3
|
+
type: "ready";
|
|
4
|
+
protocolVersion: typeof VETTA_PLUGIN_DEV_PROTOCOL_VERSION;
|
|
5
|
+
pluginId: string;
|
|
6
|
+
entryUrl: string;
|
|
7
|
+
origin: string;
|
|
8
|
+
} | {
|
|
9
|
+
type: "update";
|
|
10
|
+
pluginId: string;
|
|
11
|
+
reason: "entry" | "full-reload" | "resource";
|
|
12
|
+
path?: string;
|
|
13
|
+
triggeredBy?: string;
|
|
14
|
+
} | {
|
|
15
|
+
type: "error";
|
|
16
|
+
pluginId?: string;
|
|
17
|
+
message: string;
|
|
18
|
+
};
|
|
19
|
+
type VettaPluginDevEventListener = (event: VettaPluginDevEvent) => void;
|
|
20
|
+
export declare function setVettaPluginDevEventListener(nextListener: VettaPluginDevEventListener | undefined): void;
|
|
21
|
+
export declare function emitVettaPluginDevEvent(event: VettaPluginDevEvent): void;
|
|
22
|
+
export {};
|
|
23
|
+
//# sourceMappingURL=dev-events.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dev-events.d.ts","sourceRoot":"","sources":["../src/dev-events.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,iCAAiC,IAAI,CAAC;AAEnD,MAAM,MAAM,mBAAmB,GAC5B;IACA,IAAI,EAAE,OAAO,CAAC;IACd,eAAe,EAAE,OAAO,iCAAiC,CAAC;IAC1D,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;CACf,GACA;IACA,IAAI,EAAE,QAAQ,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,OAAO,GAAG,aAAa,GAAG,UAAU,CAAC;IAC7C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;CACrB,GACA;IACA,IAAI,EAAE,OAAO,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CAChB,CAAC;AAEJ,KAAK,2BAA2B,GAAG,CAAC,KAAK,EAAE,mBAAmB,KAAK,IAAI,CAAC;AAIxE,wBAAgB,8BAA8B,CAAC,YAAY,EAAE,2BAA2B,GAAG,SAAS,GAAG,IAAI,CAE1G;AAED,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,mBAAmB,GAAG,IAAI,CAExE","sourcesContent":["export const VETTA_PLUGIN_DEV_PROTOCOL_VERSION = 1;\n\nexport type VettaPluginDevEvent =\n\t| {\n\t\t\ttype: \"ready\";\n\t\t\tprotocolVersion: typeof VETTA_PLUGIN_DEV_PROTOCOL_VERSION;\n\t\t\tpluginId: string;\n\t\t\tentryUrl: string;\n\t\t\torigin: string;\n\t\t}\n\t| {\n\t\t\ttype: \"update\";\n\t\t\tpluginId: string;\n\t\t\treason: \"entry\" | \"full-reload\" | \"resource\";\n\t\t\tpath?: string;\n\t\t\ttriggeredBy?: string;\n\t\t}\n\t| {\n\t\t\ttype: \"error\";\n\t\t\tpluginId?: string;\n\t\t\tmessage: string;\n\t\t};\n\ntype VettaPluginDevEventListener = (event: VettaPluginDevEvent) => void;\n\nlet listener: VettaPluginDevEventListener | undefined;\n\nexport function setVettaPluginDevEventListener(nextListener: VettaPluginDevEventListener | undefined): void {\n\tlistener = nextListener;\n}\n\nexport function emitVettaPluginDevEvent(event: VettaPluginDevEvent): void {\n\tlistener?.(event);\n}\n"]}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export const VETTA_PLUGIN_DEV_PROTOCOL_VERSION = 1;
|
|
2
|
+
let listener;
|
|
3
|
+
export function setVettaPluginDevEventListener(nextListener) {
|
|
4
|
+
listener = nextListener;
|
|
5
|
+
}
|
|
6
|
+
export function emitVettaPluginDevEvent(event) {
|
|
7
|
+
listener?.(event);
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=dev-events.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dev-events.js","sourceRoot":"","sources":["../src/dev-events.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,iCAAiC,GAAG,CAAC,CAAC;AAyBnD,IAAI,QAAiD,CAAC;AAEtD,MAAM,UAAU,8BAA8B,CAAC,YAAqD,EAAQ;IAC3G,QAAQ,GAAG,YAAY,CAAC;AAAA,CACxB;AAED,MAAM,UAAU,uBAAuB,CAAC,KAA0B,EAAQ;IACzE,QAAQ,EAAE,CAAC,KAAK,CAAC,CAAC;AAAA,CAClB","sourcesContent":["export const VETTA_PLUGIN_DEV_PROTOCOL_VERSION = 1;\n\nexport type VettaPluginDevEvent =\n\t| {\n\t\t\ttype: \"ready\";\n\t\t\tprotocolVersion: typeof VETTA_PLUGIN_DEV_PROTOCOL_VERSION;\n\t\t\tpluginId: string;\n\t\t\tentryUrl: string;\n\t\t\torigin: string;\n\t\t}\n\t| {\n\t\t\ttype: \"update\";\n\t\t\tpluginId: string;\n\t\t\treason: \"entry\" | \"full-reload\" | \"resource\";\n\t\t\tpath?: string;\n\t\t\ttriggeredBy?: string;\n\t\t}\n\t| {\n\t\t\ttype: \"error\";\n\t\t\tpluginId?: string;\n\t\t\tmessage: string;\n\t\t};\n\ntype VettaPluginDevEventListener = (event: VettaPluginDevEvent) => void;\n\nlet listener: VettaPluginDevEventListener | undefined;\n\nexport function setVettaPluginDevEventListener(nextListener: VettaPluginDevEventListener | undefined): void {\n\tlistener = nextListener;\n}\n\nexport function emitVettaPluginDevEvent(event: VettaPluginDevEvent): void {\n\tlistener?.(event);\n}\n"]}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type VettaPluginDevEvent } from "./dev-events.js";
|
|
2
|
+
export interface VettaPluginDevServer {
|
|
3
|
+
pluginId: string;
|
|
4
|
+
entryUrl: string;
|
|
5
|
+
origin: string;
|
|
6
|
+
close(): Promise<void>;
|
|
7
|
+
}
|
|
8
|
+
export declare function startVettaPluginDevServer(rootDir: string, onEvent: (event: VettaPluginDevEvent) => void): Promise<VettaPluginDevServer>;
|
|
9
|
+
//# sourceMappingURL=dev-server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dev-server.d.ts","sourceRoot":"","sources":["../src/dev-server.ts"],"names":[],"mappings":"AAYA,OAAO,EAGN,KAAK,mBAAmB,EAExB,MAAM,iBAAiB,CAAC;AAGzB,MAAM,WAAW,oBAAoB;IACpC,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACvB;AA8HD,wBAAsB,yBAAyB,CAC9C,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,CAAC,KAAK,EAAE,mBAAmB,KAAK,IAAI,GAC3C,OAAO,CAAC,oBAAoB,CAAC,CAoG/B","sourcesContent":["import { existsSync } from \"node:fs\";\nimport { readFile, stat } from \"node:fs/promises\";\nimport { createServer as createNetServer } from \"node:net\";\nimport { dirname, isAbsolute, relative, resolve } from \"node:path\";\nimport {\n\tlistPluginManifestResources,\n\tparsePluginManifest,\n\ttype PluginManifest,\n} from \"@vetta-org/plugin-sdk/manifest\";\nimport { watch } from \"chokidar\";\nimport { createServer, isCSSRequest, type ViteDevServer } from \"vite\";\nimport { VETTA_PLUGIN_DEV_ENTRY_ID } from \"./dev-vite-plugins.js\";\nimport {\n\temitVettaPluginDevEvent,\n\tsetVettaPluginDevEventListener,\n\ttype VettaPluginDevEvent,\n\tVETTA_PLUGIN_DEV_PROTOCOL_VERSION,\n} from \"./dev-events.js\";\nimport { hasOpaqueResourceQuery } from \"./request-query.js\";\n\nexport interface VettaPluginDevServer {\n\tpluginId: string;\n\tentryUrl: string;\n\torigin: string;\n\tclose(): Promise<void>;\n}\n\nfunction debugDevServer(message: string): void {\n\tif (process.env.VETTA_PLUGIN_DEV_DEBUG === \"1\") {\n\t\tprocess.stderr.write(`[vetta-plugin dev] ${message}\\n`);\n\t}\n}\n\nasync function readManifest(rootDir: string): Promise<PluginManifest> {\n\tconst manifestPath = resolve(rootDir, \"plugin.json\");\n\tconst raw: unknown = JSON.parse(await readFile(manifestPath, \"utf8\"));\n\treturn parsePluginManifest(raw);\n}\n\nfunction isInsidePath(candidate: string, root: string): boolean {\n\tconst pathFromRoot = relative(root, candidate);\n\treturn pathFromRoot === \"\" || (!pathFromRoot.startsWith(\"..\") && !isAbsolute(pathFromRoot));\n}\n\nfunction isPluginProjectModule(candidate: string, rootDir: string): boolean {\n\tif (!isInsidePath(candidate, rootDir)) return false;\n\tconst pathFromRoot = relative(rootDir, candidate);\n\treturn pathFromRoot.split(/[\\\\/]/u, 1)[0] !== \"node_modules\";\n}\n\nasync function collectWatchedResourceRoots(rootDir: string, manifest: PluginManifest): Promise<string[]> {\n\tconst resources = listPluginManifestResources(manifest).filter(\n\t\t(resource) => resource.field !== \"entry\" && resource.field !== \"styles\",\n\t);\n\tconst paths = [resolve(rootDir, \"plugin.json\"), resolve(rootDir, \"locales\")];\n\tfor (const resource of resources) {\n\t\tconst resourcePath = resolve(rootDir, resource.path);\n\t\tif (resource.kind === \"file\") {\n\t\t\tpaths.push(resourcePath);\n\t\t\tcontinue;\n\t\t}\n\t\ttry {\n\t\t\tconst resourceStat = await stat(resourcePath);\n\t\t\tpaths.push(resourceStat.isDirectory() ? resourcePath : dirname(resourcePath));\n\t\t} catch {\n\t\t\tpaths.push(resourcePath);\n\t\t}\n\t}\n\treturn paths;\n}\n\nasync function findAvailablePort(): Promise<number> {\n\treturn new Promise<number>((resolvePromise, reject) => {\n\t\tconst probe = createNetServer();\n\t\tprobe.once(\"error\", reject);\n\t\tprobe.listen(0, \"127.0.0.1\", () => {\n\t\t\tconst address = probe.address();\n\t\t\tif (address === null || typeof address === \"string\") {\n\t\t\t\tprobe.close();\n\t\t\t\treject(new Error(\"Could not allocate a plugin dev server port\"));\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tprobe.close((error) => {\n\t\t\t\tif (error) reject(error);\n\t\t\t\telse resolvePromise(address.port);\n\t\t\t});\n\t\t});\n\t});\n}\n\nfunction resolveServerOrigin(server: ViteDevServer): string {\n\tconst localUrl = server.resolvedUrls?.local[0];\n\tif (!localUrl) throw new Error(\"Vite dev server did not expose a local URL\");\n\treturn localUrl.endsWith(\"/\") ? localUrl.slice(0, -1) : localUrl;\n}\n\nfunction resolveViteConfigFile(rootDir: string): string | undefined {\n\tfor (const fileName of [\"vite.config.ts\", \"vite.config.mts\", \"vite.config.js\", \"vite.config.mjs\"]) {\n\t\tconst configPath = resolve(rootDir, fileName);\n\t\tif (existsSync(configPath)) return configPath;\n\t}\n\treturn undefined;\n}\n\nfunction assertDevPluginsConfigured(server: ViteDevServer): void {\n\tif (!server.config.plugins.some((plugin) => plugin.name === \"vetta-plugin-dev-runtime\")) {\n\t\tthrow new Error(\"Vite config must include vettaPluginFederation() to enable the plugin development runtime\");\n\t}\n}\n\nasync function assertDevEntryAvailable(entryUrl: string): Promise<void> {\n\tconst response = await fetch(entryUrl);\n\tif (!response.ok) {\n\t\tthrow new Error(`Plugin dev entry is unavailable: ${entryUrl} returned HTTP ${response.status}`);\n\t}\n\tawait response.body?.cancel();\n}\n\nasync function assertDevModuleGraphAvailable(server: ViteDevServer, rootDir: string): Promise<void> {\n\tconst environment = server.environments.client;\n\tconst pendingUrls = [VETTA_PLUGIN_DEV_ENTRY_ID];\n\tconst transformedUrls = new Set<string>();\n\twhile (pendingUrls.length > 0) {\n\t\tconst moduleUrl = pendingUrls.pop();\n\t\tif (moduleUrl === undefined || transformedUrls.has(moduleUrl)) continue;\n\t\ttransformedUrls.add(moduleUrl);\n\t\tdebugDevServer(`transforming ${moduleUrl}`);\n\t\ttry {\n\t\t\tconst result = await environment.transformRequest(moduleUrl);\n\t\t\tif (result === null) throw new Error(\"Vite returned no transform result\");\n\t\t} catch (error) {\n\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\tthrow new Error(`Plugin development module failed to transform (${moduleUrl}): ${message}`);\n\t\t}\n\t\tif (hasOpaqueResourceQuery(moduleUrl)) continue;\n\t\tconst module = await environment.moduleGraph.getModuleByUrl(moduleUrl);\n\t\tif (!module) throw new Error(`Plugin development module is missing from the Vite graph: ${moduleUrl}`);\n\t\t// A CSS transform already resolves its @imports and produces the browser\n\t\t// update module. Plugin processors such as Tailwind may attach scanned\n\t\t// source files to importedModules even though the browser never imports\n\t\t// them, so they must not become independent JavaScript probes.\n\t\tif (isCSSRequest(moduleUrl)) continue;\n\t\tfor (const importedModule of module.importedModules) {\n\t\t\tif (importedModule.file && isPluginProjectModule(importedModule.file, rootDir)) {\n\t\t\t\tpendingUrls.push(importedModule.url);\n\t\t\t}\n\t\t}\n\t}\n\tdebugDevServer(`transformed ${transformedUrls.size} plugin modules`);\n}\n\nexport async function startVettaPluginDevServer(\n\trootDir: string,\n\tonEvent: (event: VettaPluginDevEvent) => void,\n): Promise<VettaPluginDevServer> {\n\tprocess.env.VETTA_PLUGIN_DEV_SERVER = \"1\";\n\tsetVettaPluginDevEventListener(onEvent);\n\n\tlet manifest = await readManifest(rootDir);\n\tlet watchedResourceRoots = await collectWatchedResourceRoots(rootDir, manifest);\n\tconst port = await findAvailablePort();\n\tconst server = await createServer({\n\t\troot: rootDir,\n\t\tconfigFile: resolveViteConfigFile(rootDir),\n\t\tlogLevel: \"silent\",\n\t\tserver: {\n\t\t\thost: \"127.0.0.1\",\n\t\t\tport,\n\t\t\tstrictPort: true,\n\t\t\tcors: true,\n\t\t\thmr: { overlay: false },\n\t\t},\n\t});\n\tdebugDevServer(\"vite server created\");\n\tlet refreshTimer: ReturnType<typeof setTimeout> | undefined;\n\tconst resourceWatcher = watch(watchedResourceRoots, { ignoreInitial: true });\n\tresourceWatcher.on(\"error\", (error) => {\n\t\temitVettaPluginDevEvent({\n\t\t\ttype: \"error\",\n\t\t\tpluginId: manifest.id,\n\t\t\tmessage: error instanceof Error ? error.message : String(error),\n\t\t});\n\t});\n\tresourceWatcher.on(\"all\", (_event, changedPath) => {\n\t\tconst absolutePath = resolve(changedPath);\n\t\tif (!watchedResourceRoots.some((watchedPath) => isInsidePath(absolutePath, watchedPath))) return;\n\t\tif (refreshTimer) clearTimeout(refreshTimer);\n\t\trefreshTimer = setTimeout(() => {\n\t\t\tvoid (async () => {\n\t\t\t\ttry {\n\t\t\t\t\tif (absolutePath === resolve(rootDir, \"plugin.json\")) {\n\t\t\t\t\t\tmanifest = await readManifest(rootDir);\n\t\t\t\t\t\tconst nextWatchedResourceRoots = await collectWatchedResourceRoots(rootDir, manifest);\n\t\t\t\t\t\tconst removedRoots = watchedResourceRoots.filter((path) => !nextWatchedResourceRoots.includes(path));\n\t\t\t\t\t\tif (removedRoots.length > 0) await resourceWatcher.unwatch(removedRoots);\n\t\t\t\t\t\tresourceWatcher.add(nextWatchedResourceRoots);\n\t\t\t\t\t\twatchedResourceRoots = nextWatchedResourceRoots;\n\t\t\t\t\t}\n\t\t\t\t\temitVettaPluginDevEvent({\n\t\t\t\t\t\ttype: \"update\",\n\t\t\t\t\t\tpluginId: manifest.id,\n\t\t\t\t\t\treason: \"resource\",\n\t\t\t\t\t\tpath: relative(rootDir, absolutePath).replaceAll(\"\\\\\", \"/\"),\n\t\t\t\t\t});\n\t\t\t\t} catch (error) {\n\t\t\t\t\temitVettaPluginDevEvent({\n\t\t\t\t\t\ttype: \"error\",\n\t\t\t\t\t\tpluginId: manifest.id,\n\t\t\t\t\t\tmessage: error instanceof Error ? error.message : String(error),\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t})();\n\t\t}, 80);\n\t});\n\n\tlet origin: string;\n\tlet entryUrl: string;\n\ttry {\n\t\tassertDevPluginsConfigured(server);\n\t\tdebugDevServer(\"starting vite listener\");\n\t\tawait server.listen();\n\t\tdebugDevServer(\"vite listener ready\");\n\t\torigin = resolveServerOrigin(server);\n\t\tentryUrl = `${origin}/mf-manifest.json`;\n\t\tdebugDevServer(`probing ${entryUrl}`);\n\t\tawait assertDevEntryAvailable(entryUrl);\n\t\tdebugDevServer(\"probing plugin module graph\");\n\t\tawait assertDevModuleGraphAvailable(server, rootDir);\n\t\tdebugDevServer(\"plugin entry ready\");\n\t} catch (error) {\n\t\tif (refreshTimer) clearTimeout(refreshTimer);\n\t\tsetVettaPluginDevEventListener(undefined);\n\t\tawait Promise.all([resourceWatcher.close(), server.close()]);\n\t\tthrow error;\n\t}\n\tconst readyEvent: VettaPluginDevEvent = {\n\t\ttype: \"ready\",\n\t\tprotocolVersion: VETTA_PLUGIN_DEV_PROTOCOL_VERSION,\n\t\tpluginId: manifest.id,\n\t\tentryUrl,\n\t\torigin,\n\t};\n\tonEvent(readyEvent);\n\n\treturn {\n\t\tpluginId: manifest.id,\n\t\tentryUrl,\n\t\torigin,\n\t\tasync close() {\n\t\t\tif (refreshTimer) clearTimeout(refreshTimer);\n\t\t\tsetVettaPluginDevEventListener(undefined);\n\t\t\tawait Promise.all([resourceWatcher.close(), server.close()]);\n\t\t},\n\t};\n}\n"]}
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { readFile, stat } from "node:fs/promises";
|
|
3
|
+
import { createServer as createNetServer } from "node:net";
|
|
4
|
+
import { dirname, isAbsolute, relative, resolve } from "node:path";
|
|
5
|
+
import { listPluginManifestResources, parsePluginManifest, } from "@vetta-org/plugin-sdk/manifest";
|
|
6
|
+
import { watch } from "chokidar";
|
|
7
|
+
import { createServer, isCSSRequest } from "vite";
|
|
8
|
+
import { VETTA_PLUGIN_DEV_ENTRY_ID } from "./dev-vite-plugins.js";
|
|
9
|
+
import { emitVettaPluginDevEvent, setVettaPluginDevEventListener, VETTA_PLUGIN_DEV_PROTOCOL_VERSION, } from "./dev-events.js";
|
|
10
|
+
import { hasOpaqueResourceQuery } from "./request-query.js";
|
|
11
|
+
function debugDevServer(message) {
|
|
12
|
+
if (process.env.VETTA_PLUGIN_DEV_DEBUG === "1") {
|
|
13
|
+
process.stderr.write(`[vetta-plugin dev] ${message}\n`);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
async function readManifest(rootDir) {
|
|
17
|
+
const manifestPath = resolve(rootDir, "plugin.json");
|
|
18
|
+
const raw = JSON.parse(await readFile(manifestPath, "utf8"));
|
|
19
|
+
return parsePluginManifest(raw);
|
|
20
|
+
}
|
|
21
|
+
function isInsidePath(candidate, root) {
|
|
22
|
+
const pathFromRoot = relative(root, candidate);
|
|
23
|
+
return pathFromRoot === "" || (!pathFromRoot.startsWith("..") && !isAbsolute(pathFromRoot));
|
|
24
|
+
}
|
|
25
|
+
function isPluginProjectModule(candidate, rootDir) {
|
|
26
|
+
if (!isInsidePath(candidate, rootDir))
|
|
27
|
+
return false;
|
|
28
|
+
const pathFromRoot = relative(rootDir, candidate);
|
|
29
|
+
return pathFromRoot.split(/[\\/]/u, 1)[0] !== "node_modules";
|
|
30
|
+
}
|
|
31
|
+
async function collectWatchedResourceRoots(rootDir, manifest) {
|
|
32
|
+
const resources = listPluginManifestResources(manifest).filter((resource) => resource.field !== "entry" && resource.field !== "styles");
|
|
33
|
+
const paths = [resolve(rootDir, "plugin.json"), resolve(rootDir, "locales")];
|
|
34
|
+
for (const resource of resources) {
|
|
35
|
+
const resourcePath = resolve(rootDir, resource.path);
|
|
36
|
+
if (resource.kind === "file") {
|
|
37
|
+
paths.push(resourcePath);
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
try {
|
|
41
|
+
const resourceStat = await stat(resourcePath);
|
|
42
|
+
paths.push(resourceStat.isDirectory() ? resourcePath : dirname(resourcePath));
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
paths.push(resourcePath);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return paths;
|
|
49
|
+
}
|
|
50
|
+
async function findAvailablePort() {
|
|
51
|
+
return new Promise((resolvePromise, reject) => {
|
|
52
|
+
const probe = createNetServer();
|
|
53
|
+
probe.once("error", reject);
|
|
54
|
+
probe.listen(0, "127.0.0.1", () => {
|
|
55
|
+
const address = probe.address();
|
|
56
|
+
if (address === null || typeof address === "string") {
|
|
57
|
+
probe.close();
|
|
58
|
+
reject(new Error("Could not allocate a plugin dev server port"));
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
probe.close((error) => {
|
|
62
|
+
if (error)
|
|
63
|
+
reject(error);
|
|
64
|
+
else
|
|
65
|
+
resolvePromise(address.port);
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
function resolveServerOrigin(server) {
|
|
71
|
+
const localUrl = server.resolvedUrls?.local[0];
|
|
72
|
+
if (!localUrl)
|
|
73
|
+
throw new Error("Vite dev server did not expose a local URL");
|
|
74
|
+
return localUrl.endsWith("/") ? localUrl.slice(0, -1) : localUrl;
|
|
75
|
+
}
|
|
76
|
+
function resolveViteConfigFile(rootDir) {
|
|
77
|
+
for (const fileName of ["vite.config.ts", "vite.config.mts", "vite.config.js", "vite.config.mjs"]) {
|
|
78
|
+
const configPath = resolve(rootDir, fileName);
|
|
79
|
+
if (existsSync(configPath))
|
|
80
|
+
return configPath;
|
|
81
|
+
}
|
|
82
|
+
return undefined;
|
|
83
|
+
}
|
|
84
|
+
function assertDevPluginsConfigured(server) {
|
|
85
|
+
if (!server.config.plugins.some((plugin) => plugin.name === "vetta-plugin-dev-runtime")) {
|
|
86
|
+
throw new Error("Vite config must include vettaPluginFederation() to enable the plugin development runtime");
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
async function assertDevEntryAvailable(entryUrl) {
|
|
90
|
+
const response = await fetch(entryUrl);
|
|
91
|
+
if (!response.ok) {
|
|
92
|
+
throw new Error(`Plugin dev entry is unavailable: ${entryUrl} returned HTTP ${response.status}`);
|
|
93
|
+
}
|
|
94
|
+
await response.body?.cancel();
|
|
95
|
+
}
|
|
96
|
+
async function assertDevModuleGraphAvailable(server, rootDir) {
|
|
97
|
+
const environment = server.environments.client;
|
|
98
|
+
const pendingUrls = [VETTA_PLUGIN_DEV_ENTRY_ID];
|
|
99
|
+
const transformedUrls = new Set();
|
|
100
|
+
while (pendingUrls.length > 0) {
|
|
101
|
+
const moduleUrl = pendingUrls.pop();
|
|
102
|
+
if (moduleUrl === undefined || transformedUrls.has(moduleUrl))
|
|
103
|
+
continue;
|
|
104
|
+
transformedUrls.add(moduleUrl);
|
|
105
|
+
debugDevServer(`transforming ${moduleUrl}`);
|
|
106
|
+
try {
|
|
107
|
+
const result = await environment.transformRequest(moduleUrl);
|
|
108
|
+
if (result === null)
|
|
109
|
+
throw new Error("Vite returned no transform result");
|
|
110
|
+
}
|
|
111
|
+
catch (error) {
|
|
112
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
113
|
+
throw new Error(`Plugin development module failed to transform (${moduleUrl}): ${message}`);
|
|
114
|
+
}
|
|
115
|
+
if (hasOpaqueResourceQuery(moduleUrl))
|
|
116
|
+
continue;
|
|
117
|
+
const module = await environment.moduleGraph.getModuleByUrl(moduleUrl);
|
|
118
|
+
if (!module)
|
|
119
|
+
throw new Error(`Plugin development module is missing from the Vite graph: ${moduleUrl}`);
|
|
120
|
+
// A CSS transform already resolves its @imports and produces the browser
|
|
121
|
+
// update module. Plugin processors such as Tailwind may attach scanned
|
|
122
|
+
// source files to importedModules even though the browser never imports
|
|
123
|
+
// them, so they must not become independent JavaScript probes.
|
|
124
|
+
if (isCSSRequest(moduleUrl))
|
|
125
|
+
continue;
|
|
126
|
+
for (const importedModule of module.importedModules) {
|
|
127
|
+
if (importedModule.file && isPluginProjectModule(importedModule.file, rootDir)) {
|
|
128
|
+
pendingUrls.push(importedModule.url);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
debugDevServer(`transformed ${transformedUrls.size} plugin modules`);
|
|
133
|
+
}
|
|
134
|
+
export async function startVettaPluginDevServer(rootDir, onEvent) {
|
|
135
|
+
process.env.VETTA_PLUGIN_DEV_SERVER = "1";
|
|
136
|
+
setVettaPluginDevEventListener(onEvent);
|
|
137
|
+
let manifest = await readManifest(rootDir);
|
|
138
|
+
let watchedResourceRoots = await collectWatchedResourceRoots(rootDir, manifest);
|
|
139
|
+
const port = await findAvailablePort();
|
|
140
|
+
const server = await createServer({
|
|
141
|
+
root: rootDir,
|
|
142
|
+
configFile: resolveViteConfigFile(rootDir),
|
|
143
|
+
logLevel: "silent",
|
|
144
|
+
server: {
|
|
145
|
+
host: "127.0.0.1",
|
|
146
|
+
port,
|
|
147
|
+
strictPort: true,
|
|
148
|
+
cors: true,
|
|
149
|
+
hmr: { overlay: false },
|
|
150
|
+
},
|
|
151
|
+
});
|
|
152
|
+
debugDevServer("vite server created");
|
|
153
|
+
let refreshTimer;
|
|
154
|
+
const resourceWatcher = watch(watchedResourceRoots, { ignoreInitial: true });
|
|
155
|
+
resourceWatcher.on("error", (error) => {
|
|
156
|
+
emitVettaPluginDevEvent({
|
|
157
|
+
type: "error",
|
|
158
|
+
pluginId: manifest.id,
|
|
159
|
+
message: error instanceof Error ? error.message : String(error),
|
|
160
|
+
});
|
|
161
|
+
});
|
|
162
|
+
resourceWatcher.on("all", (_event, changedPath) => {
|
|
163
|
+
const absolutePath = resolve(changedPath);
|
|
164
|
+
if (!watchedResourceRoots.some((watchedPath) => isInsidePath(absolutePath, watchedPath)))
|
|
165
|
+
return;
|
|
166
|
+
if (refreshTimer)
|
|
167
|
+
clearTimeout(refreshTimer);
|
|
168
|
+
refreshTimer = setTimeout(() => {
|
|
169
|
+
void (async () => {
|
|
170
|
+
try {
|
|
171
|
+
if (absolutePath === resolve(rootDir, "plugin.json")) {
|
|
172
|
+
manifest = await readManifest(rootDir);
|
|
173
|
+
const nextWatchedResourceRoots = await collectWatchedResourceRoots(rootDir, manifest);
|
|
174
|
+
const removedRoots = watchedResourceRoots.filter((path) => !nextWatchedResourceRoots.includes(path));
|
|
175
|
+
if (removedRoots.length > 0)
|
|
176
|
+
await resourceWatcher.unwatch(removedRoots);
|
|
177
|
+
resourceWatcher.add(nextWatchedResourceRoots);
|
|
178
|
+
watchedResourceRoots = nextWatchedResourceRoots;
|
|
179
|
+
}
|
|
180
|
+
emitVettaPluginDevEvent({
|
|
181
|
+
type: "update",
|
|
182
|
+
pluginId: manifest.id,
|
|
183
|
+
reason: "resource",
|
|
184
|
+
path: relative(rootDir, absolutePath).replaceAll("\\", "/"),
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
catch (error) {
|
|
188
|
+
emitVettaPluginDevEvent({
|
|
189
|
+
type: "error",
|
|
190
|
+
pluginId: manifest.id,
|
|
191
|
+
message: error instanceof Error ? error.message : String(error),
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
})();
|
|
195
|
+
}, 80);
|
|
196
|
+
});
|
|
197
|
+
let origin;
|
|
198
|
+
let entryUrl;
|
|
199
|
+
try {
|
|
200
|
+
assertDevPluginsConfigured(server);
|
|
201
|
+
debugDevServer("starting vite listener");
|
|
202
|
+
await server.listen();
|
|
203
|
+
debugDevServer("vite listener ready");
|
|
204
|
+
origin = resolveServerOrigin(server);
|
|
205
|
+
entryUrl = `${origin}/mf-manifest.json`;
|
|
206
|
+
debugDevServer(`probing ${entryUrl}`);
|
|
207
|
+
await assertDevEntryAvailable(entryUrl);
|
|
208
|
+
debugDevServer("probing plugin module graph");
|
|
209
|
+
await assertDevModuleGraphAvailable(server, rootDir);
|
|
210
|
+
debugDevServer("plugin entry ready");
|
|
211
|
+
}
|
|
212
|
+
catch (error) {
|
|
213
|
+
if (refreshTimer)
|
|
214
|
+
clearTimeout(refreshTimer);
|
|
215
|
+
setVettaPluginDevEventListener(undefined);
|
|
216
|
+
await Promise.all([resourceWatcher.close(), server.close()]);
|
|
217
|
+
throw error;
|
|
218
|
+
}
|
|
219
|
+
const readyEvent = {
|
|
220
|
+
type: "ready",
|
|
221
|
+
protocolVersion: VETTA_PLUGIN_DEV_PROTOCOL_VERSION,
|
|
222
|
+
pluginId: manifest.id,
|
|
223
|
+
entryUrl,
|
|
224
|
+
origin,
|
|
225
|
+
};
|
|
226
|
+
onEvent(readyEvent);
|
|
227
|
+
return {
|
|
228
|
+
pluginId: manifest.id,
|
|
229
|
+
entryUrl,
|
|
230
|
+
origin,
|
|
231
|
+
async close() {
|
|
232
|
+
if (refreshTimer)
|
|
233
|
+
clearTimeout(refreshTimer);
|
|
234
|
+
setVettaPluginDevEventListener(undefined);
|
|
235
|
+
await Promise.all([resourceWatcher.close(), server.close()]);
|
|
236
|
+
},
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
//# sourceMappingURL=dev-server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dev-server.js","sourceRoot":"","sources":["../src/dev-server.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync } from \"node:fs\";\nimport { readFile, stat } from \"node:fs/promises\";\nimport { createServer as createNetServer } from \"node:net\";\nimport { dirname, isAbsolute, relative, resolve } from \"node:path\";\nimport {\n\tlistPluginManifestResources,\n\tparsePluginManifest,\n\ttype PluginManifest,\n} from \"@vetta-org/plugin-sdk/manifest\";\nimport { watch } from \"chokidar\";\nimport { createServer, isCSSRequest, type ViteDevServer } from \"vite\";\nimport { VETTA_PLUGIN_DEV_ENTRY_ID } from \"./dev-vite-plugins.js\";\nimport {\n\temitVettaPluginDevEvent,\n\tsetVettaPluginDevEventListener,\n\ttype VettaPluginDevEvent,\n\tVETTA_PLUGIN_DEV_PROTOCOL_VERSION,\n} from \"./dev-events.js\";\nimport { hasOpaqueResourceQuery } from \"./request-query.js\";\n\nexport interface VettaPluginDevServer {\n\tpluginId: string;\n\tentryUrl: string;\n\torigin: string;\n\tclose(): Promise<void>;\n}\n\nfunction debugDevServer(message: string): void {\n\tif (process.env.VETTA_PLUGIN_DEV_DEBUG === \"1\") {\n\t\tprocess.stderr.write(`[vetta-plugin dev] ${message}\\n`);\n\t}\n}\n\nasync function readManifest(rootDir: string): Promise<PluginManifest> {\n\tconst manifestPath = resolve(rootDir, \"plugin.json\");\n\tconst raw: unknown = JSON.parse(await readFile(manifestPath, \"utf8\"));\n\treturn parsePluginManifest(raw);\n}\n\nfunction isInsidePath(candidate: string, root: string): boolean {\n\tconst pathFromRoot = relative(root, candidate);\n\treturn pathFromRoot === \"\" || (!pathFromRoot.startsWith(\"..\") && !isAbsolute(pathFromRoot));\n}\n\nfunction isPluginProjectModule(candidate: string, rootDir: string): boolean {\n\tif (!isInsidePath(candidate, rootDir)) return false;\n\tconst pathFromRoot = relative(rootDir, candidate);\n\treturn pathFromRoot.split(/[\\\\/]/u, 1)[0] !== \"node_modules\";\n}\n\nasync function collectWatchedResourceRoots(rootDir: string, manifest: PluginManifest): Promise<string[]> {\n\tconst resources = listPluginManifestResources(manifest).filter(\n\t\t(resource) => resource.field !== \"entry\" && resource.field !== \"styles\",\n\t);\n\tconst paths = [resolve(rootDir, \"plugin.json\"), resolve(rootDir, \"locales\")];\n\tfor (const resource of resources) {\n\t\tconst resourcePath = resolve(rootDir, resource.path);\n\t\tif (resource.kind === \"file\") {\n\t\t\tpaths.push(resourcePath);\n\t\t\tcontinue;\n\t\t}\n\t\ttry {\n\t\t\tconst resourceStat = await stat(resourcePath);\n\t\t\tpaths.push(resourceStat.isDirectory() ? resourcePath : dirname(resourcePath));\n\t\t} catch {\n\t\t\tpaths.push(resourcePath);\n\t\t}\n\t}\n\treturn paths;\n}\n\nasync function findAvailablePort(): Promise<number> {\n\treturn new Promise<number>((resolvePromise, reject) => {\n\t\tconst probe = createNetServer();\n\t\tprobe.once(\"error\", reject);\n\t\tprobe.listen(0, \"127.0.0.1\", () => {\n\t\t\tconst address = probe.address();\n\t\t\tif (address === null || typeof address === \"string\") {\n\t\t\t\tprobe.close();\n\t\t\t\treject(new Error(\"Could not allocate a plugin dev server port\"));\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tprobe.close((error) => {\n\t\t\t\tif (error) reject(error);\n\t\t\t\telse resolvePromise(address.port);\n\t\t\t});\n\t\t});\n\t});\n}\n\nfunction resolveServerOrigin(server: ViteDevServer): string {\n\tconst localUrl = server.resolvedUrls?.local[0];\n\tif (!localUrl) throw new Error(\"Vite dev server did not expose a local URL\");\n\treturn localUrl.endsWith(\"/\") ? localUrl.slice(0, -1) : localUrl;\n}\n\nfunction resolveViteConfigFile(rootDir: string): string | undefined {\n\tfor (const fileName of [\"vite.config.ts\", \"vite.config.mts\", \"vite.config.js\", \"vite.config.mjs\"]) {\n\t\tconst configPath = resolve(rootDir, fileName);\n\t\tif (existsSync(configPath)) return configPath;\n\t}\n\treturn undefined;\n}\n\nfunction assertDevPluginsConfigured(server: ViteDevServer): void {\n\tif (!server.config.plugins.some((plugin) => plugin.name === \"vetta-plugin-dev-runtime\")) {\n\t\tthrow new Error(\"Vite config must include vettaPluginFederation() to enable the plugin development runtime\");\n\t}\n}\n\nasync function assertDevEntryAvailable(entryUrl: string): Promise<void> {\n\tconst response = await fetch(entryUrl);\n\tif (!response.ok) {\n\t\tthrow new Error(`Plugin dev entry is unavailable: ${entryUrl} returned HTTP ${response.status}`);\n\t}\n\tawait response.body?.cancel();\n}\n\nasync function assertDevModuleGraphAvailable(server: ViteDevServer, rootDir: string): Promise<void> {\n\tconst environment = server.environments.client;\n\tconst pendingUrls = [VETTA_PLUGIN_DEV_ENTRY_ID];\n\tconst transformedUrls = new Set<string>();\n\twhile (pendingUrls.length > 0) {\n\t\tconst moduleUrl = pendingUrls.pop();\n\t\tif (moduleUrl === undefined || transformedUrls.has(moduleUrl)) continue;\n\t\ttransformedUrls.add(moduleUrl);\n\t\tdebugDevServer(`transforming ${moduleUrl}`);\n\t\ttry {\n\t\t\tconst result = await environment.transformRequest(moduleUrl);\n\t\t\tif (result === null) throw new Error(\"Vite returned no transform result\");\n\t\t} catch (error) {\n\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\tthrow new Error(`Plugin development module failed to transform (${moduleUrl}): ${message}`);\n\t\t}\n\t\tif (hasOpaqueResourceQuery(moduleUrl)) continue;\n\t\tconst module = await environment.moduleGraph.getModuleByUrl(moduleUrl);\n\t\tif (!module) throw new Error(`Plugin development module is missing from the Vite graph: ${moduleUrl}`);\n\t\t// A CSS transform already resolves its @imports and produces the browser\n\t\t// update module. Plugin processors such as Tailwind may attach scanned\n\t\t// source files to importedModules even though the browser never imports\n\t\t// them, so they must not become independent JavaScript probes.\n\t\tif (isCSSRequest(moduleUrl)) continue;\n\t\tfor (const importedModule of module.importedModules) {\n\t\t\tif (importedModule.file && isPluginProjectModule(importedModule.file, rootDir)) {\n\t\t\t\tpendingUrls.push(importedModule.url);\n\t\t\t}\n\t\t}\n\t}\n\tdebugDevServer(`transformed ${transformedUrls.size} plugin modules`);\n}\n\nexport async function startVettaPluginDevServer(\n\trootDir: string,\n\tonEvent: (event: VettaPluginDevEvent) => void,\n): Promise<VettaPluginDevServer> {\n\tprocess.env.VETTA_PLUGIN_DEV_SERVER = \"1\";\n\tsetVettaPluginDevEventListener(onEvent);\n\n\tlet manifest = await readManifest(rootDir);\n\tlet watchedResourceRoots = await collectWatchedResourceRoots(rootDir, manifest);\n\tconst port = await findAvailablePort();\n\tconst server = await createServer({\n\t\troot: rootDir,\n\t\tconfigFile: resolveViteConfigFile(rootDir),\n\t\tlogLevel: \"silent\",\n\t\tserver: {\n\t\t\thost: \"127.0.0.1\",\n\t\t\tport,\n\t\t\tstrictPort: true,\n\t\t\tcors: true,\n\t\t\thmr: { overlay: false },\n\t\t},\n\t});\n\tdebugDevServer(\"vite server created\");\n\tlet refreshTimer: ReturnType<typeof setTimeout> | undefined;\n\tconst resourceWatcher = watch(watchedResourceRoots, { ignoreInitial: true });\n\tresourceWatcher.on(\"error\", (error) => {\n\t\temitVettaPluginDevEvent({\n\t\t\ttype: \"error\",\n\t\t\tpluginId: manifest.id,\n\t\t\tmessage: error instanceof Error ? error.message : String(error),\n\t\t});\n\t});\n\tresourceWatcher.on(\"all\", (_event, changedPath) => {\n\t\tconst absolutePath = resolve(changedPath);\n\t\tif (!watchedResourceRoots.some((watchedPath) => isInsidePath(absolutePath, watchedPath))) return;\n\t\tif (refreshTimer) clearTimeout(refreshTimer);\n\t\trefreshTimer = setTimeout(() => {\n\t\t\tvoid (async () => {\n\t\t\t\ttry {\n\t\t\t\t\tif (absolutePath === resolve(rootDir, \"plugin.json\")) {\n\t\t\t\t\t\tmanifest = await readManifest(rootDir);\n\t\t\t\t\t\tconst nextWatchedResourceRoots = await collectWatchedResourceRoots(rootDir, manifest);\n\t\t\t\t\t\tconst removedRoots = watchedResourceRoots.filter((path) => !nextWatchedResourceRoots.includes(path));\n\t\t\t\t\t\tif (removedRoots.length > 0) await resourceWatcher.unwatch(removedRoots);\n\t\t\t\t\t\tresourceWatcher.add(nextWatchedResourceRoots);\n\t\t\t\t\t\twatchedResourceRoots = nextWatchedResourceRoots;\n\t\t\t\t\t}\n\t\t\t\t\temitVettaPluginDevEvent({\n\t\t\t\t\t\ttype: \"update\",\n\t\t\t\t\t\tpluginId: manifest.id,\n\t\t\t\t\t\treason: \"resource\",\n\t\t\t\t\t\tpath: relative(rootDir, absolutePath).replaceAll(\"\\\\\", \"/\"),\n\t\t\t\t\t});\n\t\t\t\t} catch (error) {\n\t\t\t\t\temitVettaPluginDevEvent({\n\t\t\t\t\t\ttype: \"error\",\n\t\t\t\t\t\tpluginId: manifest.id,\n\t\t\t\t\t\tmessage: error instanceof Error ? error.message : String(error),\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t})();\n\t\t}, 80);\n\t});\n\n\tlet origin: string;\n\tlet entryUrl: string;\n\ttry {\n\t\tassertDevPluginsConfigured(server);\n\t\tdebugDevServer(\"starting vite listener\");\n\t\tawait server.listen();\n\t\tdebugDevServer(\"vite listener ready\");\n\t\torigin = resolveServerOrigin(server);\n\t\tentryUrl = `${origin}/mf-manifest.json`;\n\t\tdebugDevServer(`probing ${entryUrl}`);\n\t\tawait assertDevEntryAvailable(entryUrl);\n\t\tdebugDevServer(\"probing plugin module graph\");\n\t\tawait assertDevModuleGraphAvailable(server, rootDir);\n\t\tdebugDevServer(\"plugin entry ready\");\n\t} catch (error) {\n\t\tif (refreshTimer) clearTimeout(refreshTimer);\n\t\tsetVettaPluginDevEventListener(undefined);\n\t\tawait Promise.all([resourceWatcher.close(), server.close()]);\n\t\tthrow error;\n\t}\n\tconst readyEvent: VettaPluginDevEvent = {\n\t\ttype: \"ready\",\n\t\tprotocolVersion: VETTA_PLUGIN_DEV_PROTOCOL_VERSION,\n\t\tpluginId: manifest.id,\n\t\tentryUrl,\n\t\torigin,\n\t};\n\tonEvent(readyEvent);\n\n\treturn {\n\t\tpluginId: manifest.id,\n\t\tentryUrl,\n\t\torigin,\n\t\tasync close() {\n\t\t\tif (refreshTimer) clearTimeout(refreshTimer);\n\t\t\tsetVettaPluginDevEventListener(undefined);\n\t\t\tawait Promise.all([resourceWatcher.close(), server.close()]);\n\t\t},\n\t};\n}\n"]}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { PluginOption } from "vite";
|
|
2
|
+
export declare const VETTA_PLUGIN_DEV_ENTRY_ID = "virtual:vetta-plugin-dev-entry";
|
|
3
|
+
export declare function isVettaPluginDevServer(): boolean;
|
|
4
|
+
export declare function createVettaPluginDevPlugins(entry: string): PluginOption[];
|
|
5
|
+
//# sourceMappingURL=dev-vite-plugins.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dev-vite-plugins.d.ts","sourceRoot":"","sources":["../src/dev-vite-plugins.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAsB,YAAY,EAAkB,MAAM,MAAM,CAAC;AAG7E,eAAO,MAAM,yBAAyB,mCAAmC,CAAC;AAK1E,wBAAgB,sBAAsB,IAAI,OAAO,CAEhD;AAyID,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,MAAM,GAAG,YAAY,EAAE,CAEzE","sourcesContent":["import react from \"@vitejs/plugin-react\";\nimport { readFileSync } from \"node:fs\";\nimport { relative, resolve } from \"node:path\";\nimport { parsePluginManifest } from \"@vetta-org/plugin-sdk/manifest\";\nimport type { HMRPayload, Plugin, PluginOption, ResolvedConfig } from \"vite\";\nimport { emitVettaPluginDevEvent } from \"./dev-events.js\";\n\nexport const VETTA_PLUGIN_DEV_ENTRY_ID = \"virtual:vetta-plugin-dev-entry\";\n\nconst RESOLVED_DEV_ENTRY_ID = `\\0${VETTA_PLUGIN_DEV_ENTRY_ID}`;\nconst DEV_PREAMBLE_PATH = \"/@vetta-plugin-dev-preamble\";\n\nexport function isVettaPluginDevServer(): boolean {\n\treturn process.env.VETTA_PLUGIN_DEV_SERVER === \"1\";\n}\n\nfunction readPluginId(config: ResolvedConfig): string {\n\tconst raw: unknown = JSON.parse(readFileSync(resolve(config.root, \"plugin.json\"), \"utf8\"));\n\treturn parsePluginManifest(raw).id;\n}\n\nfunction createDevEntryPlugin(entry: string): Plugin {\n\tlet pluginId = \"\";\n\tlet entryUrl = \"\";\n\treturn {\n\t\tname: \"vetta-plugin-dev-entry\",\n\t\tapply: \"serve\",\n\t\tconfigResolved(config) {\n\t\t\tpluginId = readPluginId(config);\n\t\t\tentryUrl = `/${relative(config.root, resolve(config.root, entry)).replaceAll(\"\\\\\", \"/\")}`;\n\t\t},\n\t\tresolveId(id) {\n\t\t\treturn id === VETTA_PLUGIN_DEV_ENTRY_ID ? RESOLVED_DEV_ENTRY_ID : undefined;\n\t\t},\n\t\tload(id) {\n\t\t\tif (id !== RESOLVED_DEV_ENTRY_ID) return;\n\t\t\treturn `\nimport * as pluginModule from ${JSON.stringify(entryUrl)};\n\nconst moduleStore = globalThis.__VETTA_PLUGIN_DEV_MODULES__ ??= new Map();\nmoduleStore.set(${JSON.stringify(pluginId)}, pluginModule);\n\nexport * from ${JSON.stringify(entryUrl)};\nexport default pluginModule.default;\n\nif (import.meta.hot) {\n import.meta.hot.accept(${JSON.stringify(entryUrl)}, (nextModule) => {\n if (!nextModule) return;\n moduleStore.set(${JSON.stringify(pluginId)}, nextModule);\n import.meta.hot.send(\"vetta:plugin-lifecycle-reload\", {\n pluginId: ${JSON.stringify(pluginId)},\n reason: \"entry\",\n\t path: ${JSON.stringify(entryUrl)},\n });\n });\n import.meta.hot.on(\"vetta:plugin-full-reload\", async (reload) => {\n const nextModule = await import(${JSON.stringify(`${entryUrl}?vetta-reload=`)} + Date.now());\n moduleStore.set(${JSON.stringify(pluginId)}, nextModule);\n import.meta.hot.send(\"vetta:plugin-lifecycle-reload\", {\n pluginId: ${JSON.stringify(pluginId)},\n reason: \"full-reload\",\n\t path: reload?.path,\n\t triggeredBy: reload?.triggeredBy,\n });\n });\n}\n`;\n\t\t},\n\t};\n}\n\nfunction createDevRuntimePlugin(): Plugin {\n\tlet pluginId = \"\";\n\treturn {\n\t\tname: \"vetta-plugin-dev-runtime\",\n\t\tapply: \"serve\",\n\t\tconfigResolved(config) {\n\t\t\tpluginId = readPluginId(config);\n\t\t},\n\t\tconfigureServer(server) {\n\t\t\tserver.middlewares.use((request, response, next) => {\n\t\t\t\tif (request.url?.split(\"?\", 1)[0] !== DEV_PREAMBLE_PATH) {\n\t\t\t\t\tnext();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tresponse.statusCode = 200;\n\t\t\t\tresponse.setHeader(\"Content-Type\", \"text/javascript\");\n\t\t\t\tresponse.end(`\nimport RefreshRuntime from \"/@react-refresh\";\nRefreshRuntime.injectIntoGlobalHook(window);\nwindow.$RefreshReg$ = () => {};\nwindow.$RefreshSig$ = () => (type) => type;\nwindow.__vite_plugin_react_preamble_installed__ = true;\n`);\n\t\t\t});\n\n\t\t\tserver.ws.on(\"vetta:plugin-lifecycle-reload\", (data) => {\n\t\t\t\tconst reason =\n\t\t\t\t\ttypeof data === \"object\" && data !== null && \"reason\" in data && data.reason === \"full-reload\"\n\t\t\t\t\t\t? \"full-reload\"\n\t\t\t\t\t\t: \"entry\";\n\t\t\t\tconst path = readOptionalString(data, \"path\");\n\t\t\t\tconst triggeredBy = readOptionalString(data, \"triggeredBy\");\n\t\t\t\temitVettaPluginDevEvent({\n\t\t\t\t\ttype: \"update\",\n\t\t\t\t\tpluginId,\n\t\t\t\t\treason,\n\t\t\t\t\t...(path ? { path } : {}),\n\t\t\t\t\t...(triggeredBy ? { triggeredBy } : {}),\n\t\t\t\t});\n\t\t\t});\n\n\t\t\tconst send = server.ws.send.bind(server.ws);\n\t\t\tserver.ws.send = ((payloadOrEvent: unknown, data?: unknown) => {\n\t\t\t\tif (typeof payloadOrEvent === \"object\" && payloadOrEvent !== null && \"type\" in payloadOrEvent) {\n\t\t\t\t\tif (payloadOrEvent.type === \"full-reload\") {\n\t\t\t\t\t\tsend({\n\t\t\t\t\t\t\ttype: \"custom\",\n\t\t\t\t\t\t\tevent: \"vetta:plugin-full-reload\",\n\t\t\t\t\t\t\tdata: {\n\t\t\t\t\t\t\t\tpath: readOptionalString(payloadOrEvent, \"path\"),\n\t\t\t\t\t\t\t\ttriggeredBy: readOptionalString(payloadOrEvent, \"triggeredBy\"),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t});\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tif (payloadOrEvent.type === \"error\" && \"err\" in payloadOrEvent) {\n\t\t\t\t\t\tconst error = payloadOrEvent.err;\n\t\t\t\t\t\tconst message =\n\t\t\t\t\t\t\ttypeof error === \"object\" && error !== null && \"message\" in error\n\t\t\t\t\t\t\t\t? String(error.message)\n\t\t\t\t\t\t\t\t: String(error);\n\t\t\t\t\t\temitVettaPluginDevEvent({ type: \"error\", pluginId, message });\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (typeof payloadOrEvent === \"string\") {\n\t\t\t\t\tsend(payloadOrEvent, data);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tsend(payloadOrEvent as HMRPayload);\n\t\t\t}) as typeof server.ws.send;\n\t\t},\n\t};\n}\n\nfunction readOptionalString(value: unknown, key: string): string | undefined {\n\tif (typeof value !== \"object\" || value === null || !(key in value)) return undefined;\n\tconst candidate = (value as Record<string, unknown>)[key];\n\treturn typeof candidate === \"string\" && candidate.length > 0 ? candidate : undefined;\n}\n\nexport function createVettaPluginDevPlugins(entry: string): PluginOption[] {\n\treturn [react(), createDevEntryPlugin(entry), createDevRuntimePlugin()];\n}\n"]}
|