@seasketch/geoprocessing
Version:
Geoprocessing and reporting framework for SeaSketch 2.0
107 lines (90 loc) • 2.81 kB
text/typescript
import fs from "fs-extra";
import path from "node:path";
import { GeoprocessingJsonConfig } from "../../src/types/index.js";
import { createServer } from "vite";
import react from "@vitejs/plugin-react";
import { nodePolyfills } from "vite-plugin-node-polyfills";
if (!process.env.PROJECT_PATH) throw new Error("Missing PROJECT_PATH");
const PROJECT_PATH = process.env.PROJECT_PATH || "UNDEFINED";
const destBuildPath = path.join(PROJECT_PATH, ".build-web");
const geoprocessing: GeoprocessingJsonConfig = JSON.parse(
fs
.readFileSync(path.join(PROJECT_PATH, "project", "geoprocessing.json"))
.toString(),
);
if (
!geoprocessing.preprocessingFunctions &&
!geoprocessing.geoprocessingFunctions
) {
throw new Error("No functions found in geoprocessing.json");
}
console.log("Found report clients in geoprocessing.json:");
const reportClients = geoprocessing.clients.reduce((clientSoFar, curClient) => {
return { [curClient.name]: curClient.source, ...clientSoFar };
}, {});
for (const clientPath of Object.values(reportClients)) console.log(clientPath);
// Generate top-level ReportApp.tsx with dynamic import of report clients
const clientImportStr = geoprocessing.clients
.map(
(c) => `
reportClients["${c.name}"] = React.lazy(
() => import(/* @vite-ignore */"../${c.source}")
);
`,
)
.join("");
fs.writeFileSync(
path.join(destBuildPath, "ReportApp.tsx"),
`
import React, { Suspense, lazy } from "react";
import ReactDOM from "react-dom";
import { App } from "@seasketch/geoprocessing/client-ui";
const ReportApp = () => {
const reportClients: Record<
string,
React.LazyExoticComponent<() => React.JSX.Element>
> = {};
${clientImportStr}
return (
<Suspense fallback={<div>Loading reports...</div>}>
<App reports={reportClients} />
</Suspense>
);
};
ReactDOM.render(<ReportApp />, document.getElementById("root"));
`,
);
// Create top-level index.html that loads report client
console.log("Generating index.html");
fs.writeFileSync(
path.join(destBuildPath, "index.html"),
`
<!doctype html>
<html>
<head>
<meta charset="utf-8"/>
<title>Report App</title>
<style>
html, body {margin: 0px; background-color:#efefef;padding: 4px;padding-top: 0px;}
</style>
</head>
<body>
<div id="root"></div>
<script type="module" src="ReportApp.tsx"></script>
</body>
</html>
`,
);
const server = await createServer({
// any valid user config options, plus `mode` and `configFile`
root: destBuildPath,
plugins: [react(), nodePolyfills()],
publicDir: path.join(PROJECT_PATH, "src", "assets"),
server: {
port: 8080,
open: true,
},
});
await server.listen();
server.printUrls();
server.bindCLIShortcuts({ print: true });