255 lines
9.4 KiB
TypeScript
255 lines
9.4 KiB
TypeScript
import { existsSync } from "node:fs";
|
|
import { createRequire } from "node:module";
|
|
import { dirname, join } from "node:path";
|
|
import { fileURLToPath, URL } from "node:url";
|
|
import { defineConfig, type Plugin } from "vite";
|
|
import react from "@vitejs/plugin-react";
|
|
|
|
const require = createRequire(import.meta.url);
|
|
const webuiRoot = dirname(fileURLToPath(import.meta.url));
|
|
const installedModulesVirtualId = "virtual:govoplan-installed-modules";
|
|
const resolvedInstalledModulesVirtualId = `\0${installedModulesVirtualId}`;
|
|
const installedModuleVirtualPrefix = "virtual:govoplan-installed-module/";
|
|
const resolvedInstalledModuleVirtualPrefix = `\0${installedModuleVirtualPrefix}`;
|
|
|
|
const defaultWebModulePackages = [
|
|
"@govoplan/access-webui",
|
|
"@govoplan/admin-webui",
|
|
"@govoplan/addresses-webui",
|
|
"@govoplan/audit-webui",
|
|
"@govoplan/calendar-webui",
|
|
"@govoplan/campaign-webui",
|
|
"@govoplan/dataflow-webui",
|
|
"@govoplan/datasources-webui",
|
|
"@govoplan/dashboard-webui",
|
|
"@govoplan/docs-webui",
|
|
"@govoplan/files-webui",
|
|
"@govoplan/idm-webui",
|
|
"@govoplan/mail-webui",
|
|
"@govoplan/notifications-webui",
|
|
"@govoplan/organizations-webui",
|
|
"@govoplan/ops-webui",
|
|
"@govoplan/policy-webui",
|
|
"@govoplan/postbox-webui",
|
|
"@govoplan/risk-compliance-webui",
|
|
"@govoplan/scheduling-webui",
|
|
"@govoplan/search-webui",
|
|
"@govoplan/views-webui",
|
|
"@govoplan/workflow-webui"
|
|
];
|
|
|
|
function configuredWebModulePackages(): string[] {
|
|
const configured = process.env.GOVOPLAN_WEBUI_MODULE_PACKAGES;
|
|
if (configured === undefined) return defaultWebModulePackages;
|
|
return configured.split(",").map((specifier) => specifier.trim()).filter(Boolean);
|
|
}
|
|
|
|
function packageDirectory(specifier: string): string {
|
|
const parts = specifier.startsWith("@") ? specifier.split("/") : [specifier];
|
|
return join(webuiRoot, "node_modules", ...parts);
|
|
}
|
|
|
|
function packageInstalled(specifier: string): boolean {
|
|
if (existsSync(join(packageDirectory(specifier), "package.json"))) return true;
|
|
try {
|
|
require.resolve(specifier);
|
|
return true;
|
|
} catch {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
function availableWebModuleSpecifiers(): string[] {
|
|
return configuredWebModulePackages().filter(packageInstalled);
|
|
}
|
|
|
|
function deferredVendorChunk(id: string): string | undefined {
|
|
const normalized = id.replaceAll("\\", "/");
|
|
if (!normalized.includes("/node_modules/")) return undefined;
|
|
if (
|
|
normalized.includes("/@tiptap/core/")
|
|
|| normalized.includes("/@tiptap/react/")
|
|
) {
|
|
return "rich-text-core";
|
|
}
|
|
if (normalized.includes("/@tiptap/")) {
|
|
return "rich-text-extensions";
|
|
}
|
|
if (
|
|
normalized.includes("/prosemirror-")
|
|
|| normalized.includes("/linkifyjs/")
|
|
|| normalized.includes("/orderedmap/")
|
|
|| normalized.includes("/rope-sequence/")
|
|
) {
|
|
return "rich-text-engine";
|
|
}
|
|
if (normalized.includes("/bpmn-js-properties-panel/")) {
|
|
return "bpmn-properties-provider";
|
|
}
|
|
if (normalized.includes("/@bpmn-io/properties-panel/")) {
|
|
return "bpmn-properties-ui";
|
|
}
|
|
if (normalized.includes("/@codemirror/view/")) {
|
|
return "bpmn-expression-view";
|
|
}
|
|
if (normalized.includes("/@codemirror/state/")) {
|
|
return "bpmn-expression-state";
|
|
}
|
|
if (normalized.includes("/@codemirror/language/")) {
|
|
return "bpmn-expression-language";
|
|
}
|
|
if (normalized.includes("/@codemirror/")) {
|
|
return "bpmn-expression-tools";
|
|
}
|
|
if (normalized.includes("/@lezer/")) {
|
|
return "bpmn-expression-parser";
|
|
}
|
|
if (
|
|
normalized.includes("/@bpmn-io/feel-editor/")
|
|
|| normalized.includes("/@bpmn-io/feelers-editor/")
|
|
) {
|
|
return "bpmn-expression-editors";
|
|
}
|
|
if (normalized.includes("/focus-trap/")) {
|
|
return "bpmn-properties-focus";
|
|
}
|
|
if (normalized.includes("/bpmn-js/")) return "bpmn-modeler";
|
|
if (normalized.includes("/diagram-js/")) return "bpmn-diagram-engine";
|
|
if (
|
|
normalized.includes("/bpmn-moddle/")
|
|
|| normalized.includes("/moddle/")
|
|
|| normalized.includes("/moddle-xml/")
|
|
|| normalized.includes("/saxen/")
|
|
) {
|
|
return "bpmn-xml";
|
|
}
|
|
return undefined;
|
|
}
|
|
|
|
function govoplanInstalledModulesPlugin(): Plugin {
|
|
const specifierByModuleVirtualId = new Map(
|
|
availableWebModuleSpecifiers().map((specifier) => [
|
|
`${installedModuleVirtualPrefix}${encodeURIComponent(specifier)}`,
|
|
specifier
|
|
])
|
|
);
|
|
|
|
return {
|
|
name: "govoplan-installed-modules",
|
|
resolveId(id: string) {
|
|
if (id === installedModulesVirtualId) return resolvedInstalledModulesVirtualId;
|
|
if (specifierByModuleVirtualId.has(id)) return `\0${id}`;
|
|
return null;
|
|
},
|
|
load(id: string) {
|
|
if (id === resolvedInstalledModulesVirtualId) {
|
|
const loaders = [...specifierByModuleVirtualId].map(([virtualId, specifier]) => (
|
|
`{ packageName: ${JSON.stringify(specifier)}, load: () => import(${JSON.stringify(virtualId)}) }`
|
|
));
|
|
return [
|
|
`export const installedWebModuleLoaders = [${loaders.join(", ")}];`,
|
|
"export default installedWebModuleLoaders;"
|
|
].join("\n");
|
|
}
|
|
if (!id.startsWith(resolvedInstalledModuleVirtualPrefix)) return null;
|
|
const publicVirtualId = id.slice(1);
|
|
const specifier = specifierByModuleVirtualId.get(publicVirtualId);
|
|
if (!specifier) return null;
|
|
const moduleEntry = join(packageDirectory(specifier), "src", "module.ts");
|
|
if (!existsSync(moduleEntry)) {
|
|
throw new Error(`${specifier} does not expose src/module.ts`);
|
|
}
|
|
// Import the contribution descriptor directly. Package root barrels may
|
|
// intentionally re-export pages and would otherwise defeat route splitting.
|
|
return `export { default } from ${JSON.stringify(moduleEntry)};`;
|
|
}
|
|
};
|
|
}
|
|
|
|
export default defineConfig({
|
|
plugins: [govoplanInstalledModulesPlugin(), react()],
|
|
optimizeDeps: {
|
|
exclude: availableWebModuleSpecifiers(),
|
|
// Dataflow is discovered through the virtual module registry, so Vite's
|
|
// initial scan cannot see this CommonJS-backed transitive dependency.
|
|
include: ["@xyflow/react"]
|
|
},
|
|
build: {
|
|
manifest: true,
|
|
rollupOptions: {
|
|
output: {
|
|
manualChunks: deferredVendorChunk,
|
|
// Keep dependencies of deferred BPMN packages in their lazy graph. The
|
|
// legacy Rollup behavior merged those dependencies into manual chunks
|
|
// and hoisted the properties-panel runtime into the application entry.
|
|
onlyExplicitManualChunks: true
|
|
}
|
|
},
|
|
chunkSizeWarningLimit: 500
|
|
},
|
|
resolve: {
|
|
preserveSymlinks: false,
|
|
dedupe: [
|
|
"@tiptap/core",
|
|
"@tiptap/pm",
|
|
"@tiptap/react",
|
|
"@xyflow/react",
|
|
"@bpmn-io/properties-panel",
|
|
"bpmn-js",
|
|
"bpmn-js-properties-panel",
|
|
"bpmn-moddle",
|
|
"lucide-react",
|
|
"react",
|
|
"react-dom",
|
|
"react-router",
|
|
"read-excel-file"
|
|
],
|
|
alias: [
|
|
{ find: "@govoplan/core-webui/app", replacement: fileURLToPath(new URL("./src/app.ts", import.meta.url)) },
|
|
{ find: "@govoplan/core-webui/definition-graph", replacement: fileURLToPath(new URL("./src/definitionGraph.ts", import.meta.url)) },
|
|
{ find: "@govoplan/core-webui/wysiwyg", replacement: fileURLToPath(new URL("./src/wysiwyg.ts", import.meta.url)) },
|
|
{ find: "@govoplan/core-webui", replacement: fileURLToPath(new URL("./src/index.ts", import.meta.url)) }
|
|
]
|
|
},
|
|
server: {
|
|
fs: {
|
|
allow: [
|
|
fileURLToPath(new URL('.', import.meta.url)),
|
|
fileURLToPath(new URL('../../govoplan-access/webui', import.meta.url)),
|
|
fileURLToPath(new URL('../../govoplan-admin/webui', import.meta.url)),
|
|
fileURLToPath(new URL('../../govoplan-addresses/webui', import.meta.url)),
|
|
fileURLToPath(new URL('../../govoplan-audit/webui', import.meta.url)),
|
|
fileURLToPath(new URL('../../govoplan-calendar/webui', import.meta.url)),
|
|
fileURLToPath(new URL('../../govoplan-dataflow/webui', import.meta.url)),
|
|
fileURLToPath(new URL('../../govoplan-datasources/webui', import.meta.url)),
|
|
fileURLToPath(new URL('../../govoplan-dashboard/webui', import.meta.url)),
|
|
fileURLToPath(new URL('../../govoplan-docs/webui', import.meta.url)),
|
|
fileURLToPath(new URL('../../govoplan-files/webui', import.meta.url)),
|
|
fileURLToPath(new URL('../../govoplan-idm/webui', import.meta.url)),
|
|
fileURLToPath(new URL('../../govoplan-mail/webui', import.meta.url)),
|
|
fileURLToPath(new URL('../../govoplan-notifications/webui', import.meta.url)),
|
|
fileURLToPath(new URL('../../govoplan-organizations/webui', import.meta.url)),
|
|
fileURLToPath(new URL('../../govoplan-campaign/webui', import.meta.url)),
|
|
fileURLToPath(new URL('../../govoplan-ops/webui', import.meta.url)),
|
|
fileURLToPath(new URL('../../govoplan-policy/webui', import.meta.url)),
|
|
fileURLToPath(new URL('../../govoplan-postbox/webui', import.meta.url)),
|
|
fileURLToPath(new URL('../../govoplan-risk-compliance/webui', import.meta.url)),
|
|
fileURLToPath(new URL('../../govoplan-scheduling/webui', import.meta.url)),
|
|
fileURLToPath(new URL('../../govoplan-search/webui', import.meta.url)),
|
|
fileURLToPath(new URL('../../govoplan-views/webui', import.meta.url)),
|
|
fileURLToPath(new URL('../../govoplan-workflow/webui', import.meta.url))
|
|
]
|
|
},
|
|
proxy: {
|
|
"/api": {
|
|
target: process.env.VITE_API_PROXY_TARGET || "http://127.0.0.1:8000",
|
|
changeOrigin: true
|
|
},
|
|
"/health": {
|
|
target: process.env.VITE_API_PROXY_TARGET || "http://127.0.0.1:8000",
|
|
changeOrigin: true
|
|
}
|
|
}
|
|
}
|
|
});
|