vite-plugin-cogs-sdk
Version:
A Vite plugin to easily setup your project to be a COGS plugin or custom content
143 lines (142 loc) • 4.77 kB
JavaScript
// src/index.ts
import { existsSync } from "fs";
import { cp, mkdir, readFile, rm, writeFile } from "fs/promises";
import { basename, join, resolve } from "path";
var PLUGIN_NAME = "cogs-sdk";
var devModeIndexHtmlContent = (serverUrl) => {
const serverUrlNoTrailingSlash = serverUrl.endsWith("/") ? serverUrl.slice(0, -1) : serverUrl;
return `<html>
<head>
<title>Redirecting...</title>
<script>
document.addEventListener('DOMContentLoaded', () => {
const parsedUrl = new URL(document.location.href);
const pathParams = new URLSearchParams(parsedUrl.searchParams);
document.location.href = \`${serverUrlNoTrailingSlash}\${parsedUrl.pathname}?\${pathParams.toString()}\`;
});
</script>
</head>
<body></body>
</html>`;
};
var INDEX_HTML_POLYFILL = ` <!-- COGS SDK Polyfill for global -->
<script>
if (global === undefined) {
var global = window;
}
if (module === undefined) {
var module = {};
}
</script>
</head>`;
var cogsSdkPlugin = (options = {}) => {
let config;
let serverUrl;
let manifestFilename, manifestFilePath;
const basePath = process.cwd();
if (options.manifestFilePath) {
manifestFilename = basename(options.manifestFilePath);
manifestFilePath = resolve(basePath, options.manifestFilePath);
} else {
manifestFilename = "cogs-plugin-manifest.js";
manifestFilePath = join(basePath, "src", manifestFilename);
}
if (!existsSync(manifestFilePath)) {
throw new Error(`COGS Manifest file not found at ${manifestFilePath}`);
}
const generateDevModeOutput = async () => {
const outDirPath = join(basePath, config.build.outDir);
await rm(outDirPath, { force: true, recursive: true });
await mkdir(outDirPath);
await cp(manifestFilePath, join(outDirPath, manifestFilename));
const publicPath = join(basePath, "public");
if (existsSync(publicPath)) {
await cp(publicPath, outDirPath, { recursive: true });
}
const indexHtmlContent = devModeIndexHtmlContent(serverUrl);
await writeFile(join(outDirPath, "index.html"), indexHtmlContent);
};
return {
name: PLUGIN_NAME,
/**
* Make sure the server is exposed to all the network so it "just works" in dev mode
*/
config() {
if (options.noServerExpose) {
return {};
} else {
return { server: { host: "0.0.0.0" } };
}
},
/**
* Store the resolved config so we can access it elsewhere in the plugin code
*/
configResolved(resolvedConfig) {
config = resolvedConfig;
},
/**
* When the server is configured we add a listener to get the real port value. This is because it might not match the one in the config if
* that one was not available
*/
configureServer(server) {
server.httpServer?.on("listening", () => {
setImmediate(() => {
if (server.resolvedUrls?.network && server.resolvedUrls.network.length > 0) {
serverUrl = server.resolvedUrls.network[0];
} else if (server.resolvedUrls?.local && server.resolvedUrls.local.length > 0) {
serverUrl = server.resolvedUrls.local[0];
} else {
const address = server.httpServer?.address();
if (address && typeof address === "object") {
serverUrl = `http://localhost:${address.port}/`;
}
}
generateDevModeOutput();
});
});
},
/**
* When the build starts we detect if we're in "serve" mode (dev mode) and start a dev build output
*/
async buildStart() {
if (config.command === "serve") {
serverUrl = `http://localhost:${config.server.port}/`;
this.addWatchFile(manifestFilePath);
await generateDevModeOutput();
}
},
/**
* When the manifest file changes in dev mode, we need to rebuild the output.
* This is only used in build mode.
*/
async watchChange(path) {
if (path === manifestFilePath) {
await generateDevModeOutput();
}
},
/**
* We tell Vite to include the manifest file in the build output as an asset.
* This is only called in "build" mode when we're bundling for production
*/
async generateBundle() {
const source = await readFile(manifestFilePath);
this.emitFile({
fileName: manifestFilename,
source,
type: "asset"
});
},
/**
* We need to add a polyfill for `global` and `module` in the HTML file for the COGS SDK to correctly load
* It is used in both build and serve mode
*/
transformIndexHtml(html) {
return html.replace(/<\/head>/, INDEX_HTML_POLYFILL);
}
};
};
var index_default = cogsSdkPlugin;
export {
cogsSdkPlugin,
index_default as default
};