UNPKG

@pact-toolbox/unplugin

Version:
224 lines (222 loc) 7.52 kB
import { PLUGIN_NAME, createPactToolboxNetwork, prettyPrintError } from "./utils-caVmxe1_.js"; import { ParsingError, createPactToJSTransformer } from "./pactToJS-p3Xxm_Ew.js"; import { getNetworkConfig, getSerializableNetworkConfig, isLocalNetwork, resolveConfig } from "@pact-toolbox/config"; import { PactToolboxClient } from "@pact-toolbox/runtime"; import { spinner, writeFile } from "@pact-toolbox/utils"; import { createUnplugin } from "unplugin"; import path from "node:path"; //#region src/plugin/factory.ts /** * Factory function to create the Vite plugin. * @param options Plugin options including transformation hooks. * @returns An instance of the Unplugin. */ const unpluginFactory = (options = {}) => { const { startNetwork = true } = options; const cache = /* @__PURE__ */ new Map(); const toolboxConfigPromise = resolveConfig(); let resolvedConfig; let networkConfig; let client = options.client; let network = null; let isTest = process.env.NODE_ENV === "test"; let isServe = false; const deploySpinner = spinner({ indicator: "dots" }); const transformPactToJS = createPactToJSTransformer(); /** * Asynchronous function to handle server configuration. */ const configureServer = async () => { try { resolvedConfig = await toolboxConfigPromise; networkConfig = getNetworkConfig(resolvedConfig); client = new PactToolboxClient(resolvedConfig); if (startNetwork) { const { network: networkInstance, client: networkClient } = await createPactToolboxNetwork({ isServe, isTest, client, networkConfig }, resolvedConfig, options); network = networkInstance; client = networkClient; } } catch (error) { console.error("Error during server configuration:", error); } }; /** * Asynchronous function to handle configuration resolution. * @param config Vite resolved configuration. */ const onConfig = async (config, { command }) => { try { resolvedConfig = await toolboxConfigPromise; isTest = command === "test" || isTest; isServe = command === "serve"; if (!isTest) { const serializableNetworkConfig = getSerializableNetworkConfig(resolvedConfig); config.define = config.define || {}; config.define["globalThis.__PACT_TOOLBOX_NETWORK_CONFIG__"] = JSON.stringify(serializableNetworkConfig); } } catch (error) { console.error("Error during config resolution:", error); } }; /** * Asynchronous function to handle file transformation. * @param src Source code of the `.pact` file. * @param id File identifier (path). * @returns Transformed code and source map. */ const transformFile = async (src, id) => { if (!id.endsWith(".pact")) return null; const cached = cache.get(id); const shouldTransform = !cached || cached.src !== src; const cleanName = path.basename(id); if (!shouldTransform) return { code: cached.code, map: null }; try { const { code, types, modules } = transformPactToJS(src); const isDeployed = modules.length > 0 ? (await Promise.all(modules.map((m) => client?.isContractDeployed(m.path)))).every(Boolean) : false; cache.set(id, { code, types, src, isDeployed }); if (isLocalNetwork(networkConfig) && network) deployContract(id, src, isDeployed).catch((error) => { prettyPrintError(`Failed to deploy contract ${cleanName}`, error); }); return { code, map: null }; } catch (error) { if (error instanceof ParsingError) { console.error(`Parsing error in ${id}:`); error.errors.forEach((err) => { console.error(` Line ${err.line}, Column ${err.column}: ${err.message}`); }); return null; } console.error(`Unexpected error during transformation of ${id}:`, error); throw error; } }; /** * Asynchronous function to handle contract deployment. * @param id File identifier (path). * @param src Source code of the `.pact` file. * @param isDeployed Flag indicating if the contract is already deployed. */ const deployContract = async (id, src, isDeployed) => { if (!client) { console.error("PactToolboxClient is not initialized."); return; } deploySpinner.start(`Deploying contract ${path.basename(id)}...`); return Promise.all([writeFile(`${id}.d.ts`, cache.get(id).types), client.deployCode(src, { build: { upgrade: isDeployed, init: !isDeployed } }).then(() => { const cached = cache.get(id); if (cached) { cached.isDeployed = true; cache.set(id, cached); } deploySpinner.stop(`Contract ${path.basename(id)} deployed successfully.`); })]); }; /** * Asynchronous function to handle Rspack integration. * @param compiler Rspack compiler instance. */ const configureRspack = async (compiler) => { try { const { DefinePlugin } = await import("@rspack/core"); resolvedConfig = await toolboxConfigPromise; const serializableNetworkConfig = getSerializableNetworkConfig(resolvedConfig); const definePlugin = new DefinePlugin({ "globalThis.__PACT_TOOLBOX_NETWORK_CONFIG__": JSON.stringify(serializableNetworkConfig) }); if (!client) client = new PactToolboxClient(resolvedConfig); if (!networkConfig) networkConfig = getNetworkConfig(resolvedConfig); definePlugin.apply(compiler); if (compiler.options.mode === "development") { const { network: networkInstance, client: networkClient } = await createPactToolboxNetwork({ isServe: true, isTest: false, client, networkConfig }, resolvedConfig, options); network = networkInstance; client = networkClient; } compiler.hooks.shutdown.tap(PLUGIN_NAME, async () => { const shutdownSpinner = spinner({ indicator: "timer" }); if (network) try { shutdownSpinner.start("Shutting down network..."); await Promise.race([network.stop(), new Promise((resolve) => setTimeout(resolve, 1e4))]); } finally { shutdownSpinner.stop("Network stopped!"); } }); } catch (error) { console.error("Error during Rspack configuration:", error); } }; /** * Sets up Esbuild options for the plugin. * @param build Esbuild build instance. */ const setupEsbuild = async (build) => { try { const serializableNetworkConfig = getSerializableNetworkConfig(await toolboxConfigPromise); build.initialOptions.define = { ...build.initialOptions.define, "globalThis.__PACT_TOOLBOX_NETWORK_CONFIG__": JSON.stringify(serializableNetworkConfig) }; } catch (error) { console.error("Error during Esbuild setup:", error); } }; /** * Main plugin object created by Unplugin. */ return { name: PLUGIN_NAME, enforce: "post", transformInclude(id) { return id.endsWith(".pact"); }, transform: transformFile, configureServer, vite: { config: onConfig, closeBundle: async (error) => { const shutdownSpinner = spinner({ indicator: "timer" }); if (error) console.error("Error during Vite bundle:", error); if (network) try { shutdownSpinner.start("Shutting down network..."); await Promise.race([network.stop(), new Promise((resolve) => setTimeout(resolve, 1e4))]); } finally { shutdownSpinner.stop("Network stopped!"); } } }, esbuild: { setup: setupEsbuild }, rspack: configureRspack }; }; /** * Create and export the Unplugin instance with default options. */ const unplugin = /* @__PURE__ */ createUnplugin(unpluginFactory); /** * Default export of the plugin. */ var factory_default = unplugin; //#endregion export { factory_default, unplugin, unpluginFactory }; //# sourceMappingURL=factory-BrSZXBjz.js.map