UNPKG

every-plugin

Version:
197 lines (195 loc) 8.19 kB
import { __require } from "../../_virtual/_rolldown/runtime.mjs"; import { setupPluginMiddleware } from "./dev-server-middleware.mjs"; import { buildSharedDependencies } from "./module-federation.mjs"; import { getPluginInfo, loadDevConfig } from "./utils.mjs"; import fs from "node:fs"; import path from "node:path"; import crypto from "node:crypto"; import { ModuleFederationPlugin } from "@module-federation/enhanced/rspack"; //#region src/build/rspack/plugin.ts var EmitPluginManifest = class { name = "EmitPluginManifest"; constructor(options = {}) { this.options = options; } apply(compiler) { compiler.hooks.thisCompilation.tap(this.name, (compilation) => { const webpack = compiler.webpack; const rawSource = webpack?.sources?.RawSource; const stage = webpack?.Compilation?.PROCESS_ASSETS_STAGE_ADDITIONS ?? 1e3; compilation.hooks.processAssets.tapPromise({ name: this.name, stage }, async () => { const context = compiler.options.context || process.cwd(); const pluginInfo = getPluginInfo(context); const contractFileName = this.options.contractFileName ?? "contract.d.ts"; const manifestFileName = this.options.manifestFileName ?? "plugin.manifest.json"; const sourceContractPath = path.join(context, "types", contractFileName); let contractTypes; const tryReadFile = async (filePath) => { if (!fs.existsSync(filePath)) return null; if (!fs.statSync(filePath).isFile()) return null; try { return await fs.promises.readFile(filePath, "utf8"); } catch { return null; } }; contractTypes = await tryReadFile(sourceContractPath) ?? ""; if (!contractTypes) { const packageDir = context.split("/").pop(); const nestedPath = path.join(context, "types", packageDir ?? "", "src", contractFileName); contractTypes = await tryReadFile(nestedPath) ?? ""; if (!contractTypes) { console.warn(`[EmitPluginManifest] Contract file not found at ${sourceContractPath} or ${nestedPath}. Skipping manifest generation.`); return; } } const contractSha256 = crypto.createHash("sha256").update(contractTypes).digest("hex"); const manifest = { schemaVersion: 1, kind: "every-plugin/manifest", plugin: { name: pluginInfo.name, version: pluginInfo.version }, runtime: { remoteEntry: "./remoteEntry.js" }, contract: { kind: "orpc", types: { path: `./types/${contractFileName}`, exportName: "contract", typeName: "ContractType", sha256: contractSha256 } } }; const additionalExportsEntries = []; if (this.options.additionalExports?.length) { for (const additional of this.options.additionalExports) { const sourcePath = path.join(context, "types", additional.srcPath); const content = await tryReadFile(sourcePath); if (!content) { console.warn(`[EmitPluginManifest] Additional export file not found at ${sourcePath}. Skipping.`); continue; } const sha256 = crypto.createHash("sha256").update(content).digest("hex"); const distPath = `./types/${additional.srcPath}`; additionalExportsEntries.push({ path: distPath, exports: additional.exportNames, sha256 }); if (rawSource) compilation.emitAsset(`types/${additional.srcPath}`, new rawSource(content)); } if (additionalExportsEntries.length > 0) manifest.additionalExports = additionalExportsEntries; } if (rawSource) { compilation.emitAsset(manifestFileName, new rawSource(`${JSON.stringify(manifest, null, 2)}\n`)); compilation.emitAsset(`types/${contractFileName}`, new rawSource(`${contractTypes}`)); } }); }); } }; var EveryPluginDevServer = class { name = "EveryPluginDevServer"; constructor(options = {}) { this.options = options; } apply(compiler) { const pluginInfo = getPluginInfo(compiler.options.context || process.cwd()); const devConfig = loadDevConfig(this.options.devConfigPath || "./plugin.dev.ts"); const port = Number(process.env.PORT) || this.options.port || devConfig?.port || 3999; this.configureDefaults(compiler, pluginInfo); if (!compiler.options.devServer) compiler.options.devServer = {}; this.configureDevServer(compiler, pluginInfo, devConfig, port); new ModuleFederationPlugin({ name: pluginInfo.normalizedName, filename: "remoteEntry.js", dts: this.options.dts !== false, manifest: {}, runtimePlugins: [__require.resolve("@module-federation/node/runtimePlugin")], library: { type: "commonjs-module" }, exposes: { "./plugin": "./src/index.ts" }, shared: buildSharedDependencies(pluginInfo), shareStrategy: "version-first" }).apply(compiler); if (this.options.dts === false) compiler.options.plugins = (compiler.options.plugins ?? []).filter((p) => !p || typeof p !== "object" || p.name !== "MFDevPlugin" && p.name !== "ModuleFederationDtsPlugin"); } configureDefaults(compiler, pluginInfo) { const context = compiler.options.context || process.cwd(); if (!compiler.options.output) compiler.options.output = {}; compiler.options.output.uniqueName = pluginInfo.normalizedName; compiler.options.output.publicPath = "auto"; compiler.options.output.path = path.resolve(context, "dist"); compiler.options.output.clean = true; compiler.options.output.library = { type: "commonjs-module" }; if (!compiler.options.target) compiler.options.target = "async-node"; if (!compiler.options.mode) compiler.options.mode = process.env.NODE_ENV === "development" ? "development" : "production"; if (compiler.options.devtool === void 0) compiler.options.devtool = "source-map"; if (!compiler.options.infrastructureLogging) compiler.options.infrastructureLogging = { level: "warn" }; this.ensureTypeScriptLoader(compiler); if (!compiler.options.resolve) compiler.options.resolve = {}; compiler.options.resolve.extensions = [ "...", ".tsx", ".ts" ]; compiler.options.resolve.conditionNames = [ "webpack", "import", "module", "require", "node", "default" ]; if (compiler.options.resolve.byDependency) for (const depType of Object.keys(compiler.options.resolve.byDependency)) { const depConfig = compiler.options.resolve.byDependency[depType]; if (depConfig?.conditionNames) depConfig.conditionNames = depConfig.conditionNames.filter((c) => c !== "development"); } compiler.options.resolve.fallback = { ...compiler.options.resolve.fallback, bufferutil: false, "utf-8-validate": false }; } ensureTypeScriptLoader(compiler) { if (!compiler.options.module) compiler.options.module = { rules: [] }; if (!compiler.options.module.rules) compiler.options.module.rules = []; if (!compiler.options.module.rules.some((rule) => typeof rule === "object" && rule !== null && "test" in rule && rule.test instanceof RegExp && rule.test.test(".ts"))) compiler.options.module.rules.push({ test: /\.tsx?$/, use: "builtin:swc-loader", exclude: /node_modules/ }); } configureDevServer(compiler, pluginInfo, devConfig, port) { if (!compiler.options.devServer) return; const context = compiler.options.context || process.cwd(); const originalSetup = compiler.options.devServer.setupMiddlewares; compiler.options.devServer.port = port; compiler.options.devServer.static = path.join(context, "dist"); compiler.options.devServer.hot = true; compiler.options.devServer.devMiddleware = { writeToDisk: true }; compiler.options.devServer.headers = { "Access-Control-Allow-Origin": "*", "Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, PATCH, OPTIONS", "Access-Control-Allow-Headers": "X-Requested-With, content-type, Authorization" }; compiler.options.devServer.client = { logging: "warn", overlay: { warnings: false, errors: true } }; compiler.options.devServer.setupMiddlewares = (middlewares, devServer) => { setupPluginMiddleware(devServer, pluginInfo, devConfig, port); return originalSetup ? originalSetup(middlewares, devServer) : middlewares; }; } }; //#endregion export { EmitPluginManifest, EveryPluginDevServer }; //# sourceMappingURL=plugin.mjs.map