import fs from "fs";
import path from "path";
import { createRequire } from "module";
import { fileURLToPath } from "url";
//#region src/shared/runtimeManifest.ts
var MANIFEST_FILE = "plugin-dev-manifest.json";
/**
* Корень npm-пакета продукта по URL собранного entry (`vite/index.js`, `vite/pluginDev/index.js`, …).
* @param dirnameStepsToPackageRoot сколько раз подняться из `path.dirname(entryUrl)` до корня пакета
*   (для `…/vite/index.js` → 1, для `…/vite/pluginDev/index.js` → 2).
*/
function hostProductPackageRootFromBundledEntry(bundledEntryImportMetaUrl, dirnameStepsToPackageRoot) {
	let dir = path.dirname(fileURLToPath(bundledEntryImportMetaUrl));
	for (let i = 0; i < dirnameStepsToPackageRoot; i++) dir = path.join(dir, "..");
	return path.resolve(dir);
}
function readJson(filePath) {
	return JSON.parse(fs.readFileSync(filePath, "utf-8"));
}
function tryResolveFromPackage(_require, request) {
	try {
		return _require.resolve(request);
	} catch {
		return null;
	}
}
/**
* Проверяет совместимость `schemaVersion` манифеста с поддерживаемым диапазоном.
*
* - Отсутствие поля → legacy v0 (старые main packages до введения versioning).
*   Возвращает `0`, чтобы caller мог при желании логировать deprecation.
* - Integer > 0 в пределах [1, MAX_SUPPORTED_MANIFEST_SCHEMA_VERSION] → OK.
* - Выше или невалидный тип → throw с подсказкой обновить PluginDev.
*/
function assertManifestSchemaVersion(manifest, pluginName, runtimePackage) {
	const raw = manifest.schemaVersion;
	if (raw === void 0) return 0;
	if (typeof raw !== "number" || !Number.isInteger(raw) || raw < 0) throw new Error([`[${pluginName}] ${MANIFEST_FILE} has invalid schemaVersion (expected non-negative integer, got ${JSON.stringify(raw)}).`, `This usually means a malformed install of ${runtimePackage}. Try removing node_modules and reinstalling.`].join("\n"));
	if (raw > 1) throw new Error([
		`[${pluginName}] ${MANIFEST_FILE} schemaVersion=${raw} is newer than this PluginDev can read (max 1).`,
		`The installed ${runtimePackage} ships a newer runtime contract.`,
		`Upgrade your @scope/<main>/{vite,webpack}/pluginDev import to a matching version`,
		`or downgrade ${runtimePackage} to a version compatible with this PluginDev.`
	].join("\n"));
	return raw;
}
function readRuntimeManifest(runtimePackage, pluginName, bundledEntryImportMetaUrl, dirnameStepsToPackageRoot) {
	const _require = createRequire(path.resolve(process.cwd(), "package.json"));
	const hostRoot = hostProductPackageRootFromBundledEntry(bundledEntryImportMetaUrl, dirnameStepsToPackageRoot);
	const embeddedRuntimePkgJson = path.join(hostRoot, "runtime", "package.json");
	const packageJsonPath = fs.existsSync(embeddedRuntimePkgJson) ? embeddedRuntimePkgJson : _require.resolve(`${runtimePackage}/package.json`);
	const packageDir = path.dirname(packageJsonPath);
	const manifestPath = tryResolveFromPackage(_require, `${runtimePackage}/plugin-dev-manifest.json`) || path.join(packageDir, "plugin-dev-manifest.json");
	if (fs.existsSync(manifestPath)) {
		const manifest = readJson(manifestPath);
		assertManifestSchemaVersion(manifest, pluginName, runtimePackage);
		console.log(`[${pluginName}] runtime manifest at ${manifestPath}`);
		return manifest;
	}
	const runtimePkg = readJson(packageJsonPath);
	if (!runtimePkg.runtimeModules || typeof runtimePkg.runtimeModules !== "object") throw new Error(`No "${MANIFEST_FILE}" and no legacy runtime metadata in ${runtimePackage}/package.json`);
	console.warn(`[${pluginName}] ${MANIFEST_FILE} not found, falling back to legacy package.json metadata`);
	return {
		runtimeModules: runtimePkg.runtimeModules,
		runtimeExports: runtimePkg.runtimeExports || {},
		runtimeCoreModules: Array.isArray(runtimePkg.runtimeCoreModules) ? runtimePkg.runtimeCoreModules : [],
		runtimeCoreExport: runtimePkg.runtimeCoreExport || "Core"
	};
}
function createRuntimeEntryList(runtimeManifest) {
	const runtimeModules = runtimeManifest.runtimeModules || {};
	const runtimeExports = runtimeManifest.runtimeExports || {};
	const runtimeCoreModules = Array.isArray(runtimeManifest.runtimeCoreModules) ? runtimeManifest.runtimeCoreModules : [];
	return {
		runtimeModules,
		runtimeExports,
		runtimeCoreModules,
		runtimeCoreExport: runtimeManifest.runtimeCoreExport || "Core",
		runtimeEntries: Object.entries(runtimeModules).map(([runtimeSubpath, originalName]) => ({
			runtimeSubpath,
			originalName,
			exportName: runtimeExports[runtimeSubpath]
		})),
		runtimeCoreModuleSet: new Set(runtimeCoreModules)
	};
}
//#endregion
//#region src/shared/pluginDevOptions.ts
/**
* Normalizes shared `pluginDev` options for Vite and Webpack adapters.
*/
function resolvePluginDevOptions(options) {
	let o = {};
	if (options && options !== true) o = options;
	const externals = o.externals === "global" ? "globals" : o.externals;
	const defaultAlias = externals === void 0 || externals === "esm" || externals === false;
	return {
		externals: externals !== void 0 ? externals : "esm",
		alias: o.alias !== void 0 ? o.alias : defaultAlias,
		allowedDeepRuntimeImports: new Set(o.allowedDeepRuntimeImports ?? [])
	};
}
//#endregion
//#region src/shared/branding.ts
/**
* Чтение `process.env.REACT_APP_*` — как в основном приложении.
* На этапе сборки `build.ts` подставляет в `define` итоговые строки (см. `bundlerDefines()`).
*/
var BUNDLER_DEFAULT_PACKAGE_NAME = "useblocks";
var BUNDLER_DEFAULT_APP_NAME = "useblocks";
var BUNDLER_RUNTIME_PACKAGE = "useblocks/runtime";
var BUNDLER_NAMESPACE = `__${BUNDLER_DEFAULT_APP_NAME}__`;
//#endregion
//#region src/shared/runtimeCorePackage.ts
function getRuntimeCorePackageName(mainPackageName) {
	const normalized = String(mainPackageName || "").replace(/\/+$/, "");
	if (!normalized) throw new Error("[runtime-core] mainPackageName is empty");
	return `${normalized}/runtime-core`;
}
//#endregion
//#region src/shared/uiKitPaths.ts
/** Main package import for ui-kit bytes: `@scope/app/ui-kit` (not under `/runtime/`). */
function getMainPackageUiKitSubpath(mainPackage = BUNDLER_DEFAULT_PACKAGE_NAME) {
	const normalized = String(mainPackage || "").replace(/\/+$/, "");
	if (!normalized) throw new Error("[ui-kit-paths] mainPackage is empty");
	return `${normalized}/ui-kit`;
}
function isUiKitManifestEntry(exportName) {
	return exportName === "UiKit";
}
//#endregion
//#region src/shared/externalsResolver.ts
function buildRuntimeExternalEntries(runtimeEntries, runtimeCoreModuleSet, runtimePackage, runtimeCorePackage, mainPackage) {
	return runtimeEntries.map(({ runtimeSubpath, originalName, exportName }) => ({
		originalName,
		runtimeRequest: runtimeCoreModuleSet.has(originalName) ? runtimeCorePackage : isUiKitManifestEntry(exportName) ? getMainPackageUiKitSubpath(mainPackage) : `${runtimePackage}/${runtimeSubpath}`,
		exportName,
		isCore: runtimeCoreModuleSet.has(originalName)
	}));
}
function isNestedRuntimeRequest(request, runtimeRequest) {
	return request === runtimeRequest || request.startsWith(`${runtimeRequest}/`) || request.startsWith(`${runtimeRequest}.`);
}
function getCoreExternalWebpackValue(type, namespace, coreExport, runtimeCorePackage) {
	switch (type) {
		case "esm": return runtimeCorePackage;
		case "globals": return `var ${namespace}.modules.${coreExport}`;
		case "async-globals": return [`promise ${namespace}.modules`, coreExport];
		default: throw new Error(`Unexpected WebpackExternalsType: ${String(type)}`);
	}
}
/**
* Resolve a webpack external value for one manifest-derived runtime entry (`buildRuntimeExternalEntries`).
*
* For **core singleton** modules (`entry.isCore`), nested requests under `runtimeRequest` (`pkg/sub`, `pkg/sub.js`)
* are externalized too. Under `globals` / `async-globals`, nested paths still resolve to **one**
* host global: `namespace.modules.${runtimeCoreExport}` (deep imports are not surfaced separately — matches current contract).
*/
function getWebpackRuntimeExternalValue(type, entry, request, runtimeCoreExport, opts) {
	const { runtimeCompatCoreRequest, runtimeCorePackage, namespace } = opts;
	if (entry.isCore) {
		if (request === entry.originalName) return type === "esm" ? entry.runtimeRequest : getCoreExternalWebpackValue(type, namespace, runtimeCoreExport, opts.runtimeCorePackage);
		if (isNestedRuntimeRequest(request, entry.runtimeRequest)) return type === "esm" ? request : getCoreExternalWebpackValue(type, namespace, runtimeCoreExport, opts.runtimeCorePackage);
		return;
	}
	switch (type) {
		case "esm":
			if (request === entry.originalName) return entry.runtimeRequest;
			if (isNestedRuntimeRequest(request, entry.runtimeRequest)) return request;
			return;
		case "globals":
			if (!entry.exportName) return;
			if (request === entry.originalName || isNestedRuntimeRequest(request, entry.runtimeRequest)) return `var ${namespace}.modules.${entry.exportName}`;
			return;
		case "async-globals":
			if (!entry.exportName) return;
			if (request === entry.originalName || isNestedRuntimeRequest(request, entry.runtimeRequest)) return [`promise ${namespace}.modules`, entry.exportName];
			return;
		default: return;
	}
}
//#endregion
//#region src/shared/webpackPluginDevAliasKey.ts
/**
* Webpack `resolve.alias` key for a bare package from plugin-dev manifest: exact specifier only.
* Suffix `$` prevents prefix match (e.g. `@ant-design/icons` must not match `@ant-design/icons/es/...`).
*/
function webpackPluginDevExactBareAliasKey(originalName) {
	return `${originalName}$`;
}
//#endregion
//#region src/shared/runtimeDeepImportGuard.ts
/**
* Singleton-safe deep-import guard for runtime packages.
*
* Background: runtime packages (`react`, `antd`, `@ant-design/icons`, …) are delivered
* to plugins via published subpaths `<main>/runtime/<name>/`. If a plugin imports an
* unpublished deep path (e.g. `antd/es/locale/zh_CN`), the plugin's bundler will
* resolve it from the plugin's own `node_modules` — yielding a **second copy** of the
* package inside the plugin bundle. For singleton-sensitive libraries (React,
* `@ant-design/cssinjs`, our DI) this silently splits the graph and breaks the host
* contract at runtime.
*
* Policy:
*   1. Default — **throw** with a diagnostic listing the registered subpaths.
*   2. Escape-hatch — `allowedDeepRuntimeImports` (exact strings only). A matching
*      request is allowed but emits a one-shot warn, signalling that the plugin
*      consciously ships its own copy of that subpath.
*
* Pure: no side effects on input, returns a plain decision the caller renders into
* the bundler's native error/warn channel.
*
* @module runtimeDeepImportGuard
*/
/**
* Корень bare-package для проверки запрещённых deep-импортов runtime пакетов.
* - `react` → `react`
* - `@ant-design/icons` → `@ant-design/icons`
* - `antd/es/locale/zh_CN` → `antd`
*/
function getRuntimePackageRoot(spec) {
	if (spec.startsWith("@")) return spec.split("/").slice(0, 2).join("/");
	return spec.split("/")[0];
}
/** Strip branded runtime root prefix so `@scope/runtime/antd/es/…` is checked as bare `antd/es/…`. */
function stripRuntimePackagePrefix(request, runtimePackage) {
	const prefix = `${runtimePackage}/`;
	if (!request.startsWith(prefix)) return null;
	return request.slice(prefix.length);
}
/** Bare + runtime-prefixed forms (deduped) for guard evaluation. */
function resolveDeepImportGuardRequests(request, runtimePackage) {
	const seen = /* @__PURE__ */ new Set();
	const out = [];
	const push = (value) => {
		if (!seen.has(value)) {
			seen.add(value);
			out.push(value);
		}
	};
	push(request);
	if (runtimePackage) {
		const bare = stripRuntimePackagePrefix(request, runtimePackage);
		if (bare) push(bare);
	}
	return out;
}
function hasKey(set, key) {
	if (set instanceof Set) return set.has(key);
	return Object.prototype.hasOwnProperty.call(set, key);
}
/** Strip runtime entry index file suffix (`react/index.js` → `react`). */
var RUNTIME_INDEX_SUFFIX_RE = /\/index(?:\.(?:js|mjs|cjs))?$/;
function normalizeRegisteredRuntimeSubpath(request) {
	return request.replace(RUNTIME_INDEX_SUFFIX_RE, "");
}
function normalizeDeepImportRequestId(request) {
	return request.replace(/\\/g, "/");
}
function evaluateSingleDeepImportRequest(request, input) {
	const normalizedRequestId = normalizeDeepImportRequestId(request);
	const { knownRuntimeModules, runtimePackageRoots, runtimeRootKnownSubpaths, allowedDeepRuntimeImports, pluginName, optInExample } = input;
	for (const root of runtimePackageRoots) {
		if (!normalizedRequestId.startsWith(`${root}/`)) continue;
		if (hasKey(knownRuntimeModules, normalizedRequestId)) return { action: "pass-through" };
		const normalizedSubpath = normalizeRegisteredRuntimeSubpath(normalizedRequestId);
		if (normalizedSubpath !== normalizedRequestId && hasKey(knownRuntimeModules, normalizedSubpath)) return { action: "pass-through" };
		if (allowedDeepRuntimeImports.has(normalizedRequestId)) return {
			action: "allow-with-warn",
			matchedRoot: root,
			warnMessage: [`[${pluginName}] allowed deep runtime import "${normalizedRequestId}" — singleton invariant is relaxed.`, `The plugin will bundle its own copy of "${root}" subpath; ensure this is intentional.`].join(" ")
		};
		const known = Array.from(runtimeRootKnownSubpaths.get(root) ?? []).sort();
		return {
			action: "block",
			matchedRoot: root,
			errorMessage: [
				`[${pluginName}] Deep import "${normalizedRequestId}" of runtime package "${root}" is not allowed.`,
				`Runtime packages must be imported as bare specifiers or via known runtime subpaths.`,
				known.length > 0 ? `Available subpaths: ${known.join(", ")}` : "",
				`If you need this deep path, either:`,
				`  • add a runtime entry to runtime-contract.ts on the host side, or`,
				`  • ${optInExample(request)} — at the cost of a second copy.`
			].filter(Boolean).join("\n")
		};
	}
	return { action: "pass-through" };
}
function evaluateDeepImportRequest(input) {
	const { request, runtimePackage, ...rest } = input;
	for (const candidate of resolveDeepImportGuardRequests(request, runtimePackage)) {
		const decision = evaluateSingleDeepImportRequest(candidate, rest);
		if (decision.action !== "pass-through") return decision;
	}
	return { action: "pass-through" };
}
//#endregion
//#region src/shared/runtimeJsxPolicy.ts
/** Branded runtime subpath; published artifact re-exports production jsx-runtime (see build-runtime patch). */
function resolveRuntimeJsxDevRuntimeFacade(runtimePackage) {
	return `${runtimePackage}/react/jsx-dev-runtime`;
}
/** Webpack exact-match alias keys for JSX runtime entry points (PluginDev alias mode). */
function buildRuntimeJsxWebpackAliasEntries(runtimePackage) {
	return {
		"react/jsx-runtime$": `${runtimePackage}/react/jsx-runtime`,
		"react/jsx-dev-runtime$": resolveRuntimeJsxDevRuntimeFacade(runtimePackage)
	};
}
//#endregion
//#region src/shared/pluginBundleSanityCheck.ts
/**
* Build-time defensive check для bundle плагина.
*
* После сборки плагина (Vite generateBundle / Webpack afterEmit) проверяет,
* что в его JS-чанках НЕТ bare-импортов рантайм-пакетов (react, react-dom,
* antd, @ant-design/icons, …). Все они должны идти через
* `<main>/runtime/<pkg>` (singleton) или `<main>/ui-kit` / `<main>/runtime-core`.
*
* Симптом-кейс: integrator грузит plugin в release-host Vite, который видит
* `import "react"` в chunk'е плагина и независимо prebundle'ит его → второй
* React → `Invalid hook call`. См. `reactDuplicateDetector.ts` (runtime-side
* проверка) и `RUNTIME_DELIVERY_CR.md` §12.
*
* Pure: возвращает решение, caller рендерит warn / throw в нужный канал.
*
* @module pluginBundleSanityCheck
*/
/**
* Bare-имена, которые НЕ должны попадать в bundle плагина как external.
* Источник истины — пакеты `runtime-bundle` в runtime-contract. Жёстко
* перечислены, чтобы host plugin/PluginDev не читали контракт runtime'ом
* (контракт замораживается в branding на этапе сборки bundler-plugins).
*/
var SINGLETON_BARE_NAMES = [
	"react",
	"react-dom",
	"react-dom/client",
	"react/jsx-runtime",
	"react/jsx-dev-runtime",
	"antd",
	"@ant-design/icons"
];
/**
* Регекспы для поиска bare-импорта `from "X"` / `from 'X'` / `import "X"` / `import('X')`.
* Точно совпадает с bare-id (не подцеплять `<main>/runtime/react`).
*/
function buildBareImportPattern(bare) {
	const escaped = bare.replace(/[.*+?^${}()|[\]\\/]/g, "\\$&");
	return new RegExp(String.raw`(?:from|import)\s*\(?\s*["']` + escaped + String.raw`["']\s*\)?`);
}
var BARE_PATTERNS = new Map(SINGLETON_BARE_NAMES.map((bare) => [bare, buildBareImportPattern(bare)]));
var LEGACY_CORE_DI_EXTERNAL_PATTERNS = [
	/\.modules\.Core\b/,
	/modules\["Core"\]/,
	/modules\.Core\b/,
	/\["promise\s+__[\w]+__\.modules",\s*"Core"\]/
];
function checkPluginBundleSanity(input) {
	const violations = [];
	const uiKitPattern = input.uiKitPackage ? buildBareImportPattern(input.uiKitPackage) : null;
	const uiKitName = input.uiKitPackage ?? "";
	for (const [chunkFileName, source] of input.chunks) {
		for (const [bare, pattern] of BARE_PATTERNS) if (pattern.test(source)) violations.push({
			chunkFileName,
			bare
		});
		if (uiKitPattern && uiKitPattern.test(source)) violations.push({
			chunkFileName,
			bare: uiKitName
		});
		for (const legacyPattern of LEGACY_CORE_DI_EXTERNAL_PATTERNS) if (legacyPattern.test(source)) {
			violations.push({
				chunkFileName,
				bare: "legacy-modules.Core-external"
			});
			break;
		}
	}
	if (violations.length === 0) return { status: "clean" };
	return {
		status: "violations",
		violations,
		warnMessage: renderViolationsWarn(input.pluginName, input.mainPackage, violations)
	};
}
function renderViolationsWarn(pluginName, mainPackage, violations) {
	const byBare = /* @__PURE__ */ new Map();
	for (const v of violations) {
		if (!byBare.has(v.bare)) byBare.set(v.bare, []);
		byBare.get(v.bare).push(v.chunkFileName);
	}
	const lines = [];
	lines.push(`[${pluginName}] Plugin bundle contains BARE runtime imports (singleton invariant broken).`, `These imports will be resolved by the integrator's Vite as a SEPARATE React/antd copy,`, `causing "Invalid hook call" when the plugin meets host singletons.`, ``, `Bare imports found:`);
	for (const [bare, chunks] of byBare) {
		lines.push(`  • "${bare}"`);
		for (const c of chunks.slice(0, 5)) lines.push(`      in ${c}`);
		if (chunks.length > 5) lines.push(`      …and ${chunks.length - 5} more chunk(s)`);
	}
	lines.push(``, `Likely root cause: PluginDev externals/alias did not catch these imports.`, `Each bare id should resolve through main subpath:`, `   "react"             → "${mainPackage}/runtime/react"`, `   "react-dom"         → "${mainPackage}/runtime/react-dom"`, `   "react/jsx-runtime" → "${mainPackage}/runtime/react/jsx-runtime"`, `   "antd"              → "${mainPackage}/runtime/antd"`, `   "@<scope>/ui-kit"   → "${mainPackage}/ui-kit"`, ``, `Check that PluginDev() is added to plugin's vite/webpack config with externals: 'esm' (or 'globals').`);
	return lines.join("\n");
}
//#endregion
//#region src/webpack/pluginDev/index.ts
var PLUGIN_NAME = `${BUNDLER_DEFAULT_APP_NAME}-pluginDev-webpack`;
var RUNTIME_CORE_PACKAGE = getRuntimeCorePackageName(BUNDLER_DEFAULT_PACKAGE_NAME);
var RUNTIME_COMPAT_CORE_REQUEST = `${BUNDLER_RUNTIME_PACKAGE}/core`;
var PLUGIN_DEV_WEBPACK_ENTRY_URL = import.meta.url;
var STRICT_ENV_FLAG = "BUNDLER_RUNTIME_STRICT";
function isPluginDevStrictMode(envSource = process.env) {
	const raw = envSource[STRICT_ENV_FLAG];
	return raw === "1" || raw === "true";
}
function printModeHints(opts) {
	if (opts.externals === "globals") console.warn(`[${PLUGIN_NAME}] globals mode is intended for the browser/script target. Make sure the host loads runtime globals before the plugin bundle.`);
	if (opts.externals === "async-globals") console.warn(`[${PLUGIN_NAME}] async-globals is an advanced Webpack compatibility target. Prefer the npm package target unless the host explicitly requires async globals.`);
	if (opts.alias && (opts.externals === "globals" || opts.externals === "async-globals")) console.warn(`[${PLUGIN_NAME}] alias=true with ${opts.externals} is an advanced setup and is usually unnecessary.`);
}
function createRuntimeExternalResolver(type, runtimeExternalEntries, runtimeCoreExport, runtimeModules, runtimePackageRoots, runtimeRootKnownSubpaths, allowedDeepRuntimeImports) {
	return function runtimeExternalResolver(data, callback) {
		const request = data.request;
		if (!request) {
			callback();
			return;
		}
		if (request === RUNTIME_COMPAT_CORE_REQUEST || request.startsWith(`${RUNTIME_COMPAT_CORE_REQUEST}/`) || request.startsWith(`${RUNTIME_COMPAT_CORE_REQUEST}.`) || request === RUNTIME_CORE_PACKAGE || request.startsWith(`${RUNTIME_CORE_PACKAGE}/`) || request.startsWith(`${RUNTIME_CORE_PACKAGE}.`)) {
			callback(null, type === "esm" ? request.replace(RUNTIME_COMPAT_CORE_REQUEST, RUNTIME_CORE_PACKAGE) : getCoreExternalWebpackValue(type, BUNDLER_NAMESPACE, runtimeCoreExport, RUNTIME_CORE_PACKAGE));
			return;
		}
		const resolverOpts = {
			runtimeCompatCoreRequest: RUNTIME_COMPAT_CORE_REQUEST,
			runtimeCorePackage: RUNTIME_CORE_PACKAGE,
			namespace: BUNDLER_NAMESPACE
		};
		for (const entry of runtimeExternalEntries) {
			const mapped = getWebpackRuntimeExternalValue(type, entry, request, runtimeCoreExport, resolverOpts);
			if (mapped !== void 0) {
				callback(null, mapped);
				return;
			}
		}
		/**
		* Deep-импорт неизвестного subpath runtime-пакета приводит к second instance.
		* Лучше упасть на сборке плагина с понятной диагностикой, чем silently
		* расщепить singleton-граф (см. EXTENSIONS_API / RUNTIME_DELIVERY).
		*/
		const guard = evaluateDeepImportRequest({
			request,
			runtimePackage: BUNDLER_RUNTIME_PACKAGE,
			knownRuntimeModules: runtimeModules,
			runtimePackageRoots,
			runtimeRootKnownSubpaths,
			allowedDeepRuntimeImports,
			pluginName: PLUGIN_NAME,
			optInExample: (req) => `opt in via new PluginDev({ allowedDeepRuntimeImports: ['${req}'] })`
		});
		if (guard.action === "allow-with-warn") {
			console.warn(guard.warnMessage);
			callback();
			return;
		}
		if (guard.action === "block") {
			callback(new Error(guard.errorMessage));
			return;
		}
		callback();
	};
}
var PluginDev = class {
	constructor(options) {
		this._opts = resolvePluginDevOptions(options);
	}
	apply(compiler) {
		const opts = this._opts;
		let runtimeModules;
		let runtimeCoreModules;
		let runtimeCoreExport;
		let runtimeEntries;
		let runtimeCoreModuleSet;
		let runtimeExports;
		try {
			({runtimeModules, runtimeCoreModules, runtimeCoreExport, runtimeEntries, runtimeCoreModuleSet, runtimeExports} = createRuntimeEntryList(readRuntimeManifest(BUNDLER_RUNTIME_PACKAGE, PLUGIN_NAME, PLUGIN_DEV_WEBPACK_ENTRY_URL, 2)));
		} catch (e) {
			const msg = e instanceof Error ? e.message : String(e);
			throw new Error(`[${PLUGIN_NAME}] ${BUNDLER_RUNTIME_PACKAGE} not found.\nMake sure it is installed: npm install ${BUNDLER_RUNTIME_PACKAGE}\n` + msg);
		}
		const allOriginalNames = runtimeEntries.map(({ originalName }) => originalName);
		/**
		* Корни bare-package'ов рантайма (react, react-dom, antd, @ant-design/icons, …).
		* Используются, чтобы запретить deep-импорты вида `antd/es/locale/zh_CN`,
		* которые приведут к расщеплению singleton-графа (antd в host + antd в плагине).
		*/
		const runtimePackageRoots = /* @__PURE__ */ new Set();
		const runtimeRootKnownSubpaths = /* @__PURE__ */ new Map();
		for (const entry of runtimeEntries) {
			if (isUiKitManifestEntry(entry.exportName)) continue;
			const root = getRuntimePackageRoot(entry.originalName);
			runtimePackageRoots.add(root);
			if (!runtimeRootKnownSubpaths.has(root)) runtimeRootKnownSubpaths.set(root, /* @__PURE__ */ new Set());
			runtimeRootKnownSubpaths.get(root).add(entry.originalName);
		}
		console.log(`[${PLUGIN_NAME}] externals: ${opts.externals || "disabled"}, alias: ${opts.alias}`);
		printModeHints(opts);
		if (opts.alias || runtimeCoreModules.length > 0) {
			if (!compiler.options.resolve) compiler.options.resolve = {};
			if (!compiler.options.resolve.alias) compiler.options.resolve.alias = {};
			const alias = compiler.options.resolve.alias;
			if (opts.alias) Object.assign(alias, buildRuntimeJsxWebpackAliasEntries(BUNDLER_RUNTIME_PACKAGE));
			for (const { originalName, exportName } of runtimeEntries) {
				if (!opts.alias && !runtimeCoreModuleSet.has(originalName)) continue;
				const replacement = runtimeCoreModuleSet.has(originalName) ? RUNTIME_CORE_PACKAGE : isUiKitManifestEntry(exportName) ? getMainPackageUiKitSubpath(BUNDLER_DEFAULT_PACKAGE_NAME) : `${BUNDLER_RUNTIME_PACKAGE}/${originalName}`;
				alias[webpackPluginDevExactBareAliasKey(originalName)] = replacement;
			}
			console.log(`[${PLUGIN_NAME}] ${allOriginalNames.length} resolve aliases`);
		}
		if (opts.alias) {
			const guardInput = {
				knownRuntimeModules: runtimeModules,
				runtimePackageRoots,
				runtimeRootKnownSubpaths,
				allowedDeepRuntimeImports: opts.allowedDeepRuntimeImports,
				pluginName: PLUGIN_NAME,
				runtimePackage: BUNDLER_RUNTIME_PACKAGE,
				optInExample: (req) => `opt in via new PluginDev({ allowedDeepRuntimeImports: ['${req}'] })`
			};
			compiler.hooks.normalModuleFactory.tap(PLUGIN_NAME, (nmf) => {
				nmf.hooks.beforeResolve.tap(PLUGIN_NAME, (resolveData) => {
					const request = resolveData?.request;
					if (!request) return;
					const guard = evaluateDeepImportRequest({
						request,
						...guardInput
					});
					if (guard.action === "allow-with-warn") {
						console.warn(guard.warnMessage);
						return;
					}
					if (guard.action === "block") throw new Error(guard.errorMessage);
				});
			});
		}
		if (!opts.externals) return;
		const externals = {};
		const type = opts.externals;
		const runtimeExternalEntries = buildRuntimeExternalEntries(runtimeEntries, runtimeCoreModuleSet, BUNDLER_RUNTIME_PACKAGE, RUNTIME_CORE_PACKAGE, BUNDLER_DEFAULT_PACKAGE_NAME);
		if (runtimeCoreModules.length > 0) switch (type) {
			case "esm":
				externals[RUNTIME_CORE_PACKAGE] = RUNTIME_CORE_PACKAGE;
				externals[RUNTIME_COMPAT_CORE_REQUEST] = RUNTIME_CORE_PACKAGE;
				break;
			case "globals":
				externals[RUNTIME_CORE_PACKAGE] = `var ${BUNDLER_NAMESPACE}.modules.${runtimeCoreExport}`;
				externals[RUNTIME_COMPAT_CORE_REQUEST] = `var ${BUNDLER_NAMESPACE}.modules.${runtimeCoreExport}`;
				break;
			case "async-globals":
				externals[RUNTIME_CORE_PACKAGE] = [`promise ${BUNDLER_NAMESPACE}.modules`, runtimeCoreExport];
				externals[RUNTIME_COMPAT_CORE_REQUEST] = [`promise ${BUNDLER_NAMESPACE}.modules`, runtimeCoreExport];
				break;
		}
		for (const { originalName, runtimeRequest, exportName, isCore } of runtimeExternalEntries) {
			if (isCore) continue;
			switch (type) {
				case "esm":
					externals[originalName] = runtimeRequest;
					externals[runtimeRequest] = runtimeRequest;
					break;
				case "globals":
					if (exportName) {
						externals[originalName] = `var ${BUNDLER_NAMESPACE}.modules.${exportName}`;
						externals[runtimeRequest] = `var ${BUNDLER_NAMESPACE}.modules.${exportName}`;
					}
					break;
				case "async-globals":
					if (exportName) {
						externals[originalName] = [`promise ${BUNDLER_NAMESPACE}.modules`, exportName];
						externals[runtimeRequest] = [`promise ${BUNDLER_NAMESPACE}.modules`, exportName];
					}
					break;
			}
		}
		const resolver = createRuntimeExternalResolver(type, runtimeExternalEntries, runtimeCoreExport, runtimeModules, runtimePackageRoots, runtimeRootKnownSubpaths, opts.allowedDeepRuntimeImports);
		const existing = compiler.options.externals;
		if (typeof existing === "object" && !Array.isArray(existing) && !(existing instanceof RegExp)) compiler.options.externals = [resolver, {
			...existing,
			...externals
		}];
		else if (Array.isArray(existing)) compiler.options.externals = [
			resolver,
			...existing,
			externals
		];
		else compiler.options.externals = [resolver, externals];
		console.log(`[${PLUGIN_NAME}] ${Object.keys(externals).length} ${type} externals`);
		/**
		* Build-time defensive: после emit'а scan'ит JS-assets на bare-импорты
		* (`react`, `react-dom`, `antd`, …). Все они должны быть external'ены
		* в `<main>/runtime/<pkg>` — иначе integrator получит второй React'a.
		* См. `pluginBundleSanityCheck` и `RUNTIME_DELIVERY_CR.md` §12.
		*/
		compiler.hooks.afterEmit.tap(PLUGIN_NAME, (compilation) => {
			if (!(compilation.outputOptions.path || compiler.outputPath)) return;
			const chunks = /* @__PURE__ */ new Map();
			for (const [fileName, source] of Object.entries(compilation.assets)) {
				if (!/\.(?:js|mjs|cjs)$/.test(fileName)) continue;
				try {
					const code = source.source?.();
					if (code == null) continue;
					chunks.set(fileName, typeof code === "string" ? code : code.toString("utf-8"));
				} catch {}
			}
			if (chunks.size === 0) return;
			const sanity = checkPluginBundleSanity({
				chunks,
				mainPackage: BUNDLER_DEFAULT_PACKAGE_NAME,
				pluginName: PLUGIN_NAME
			});
			if (sanity.status === "violations" && sanity.warnMessage) {
				if (isPluginDevStrictMode()) {
					compilation.errors.push(new Error(sanity.warnMessage));
					return;
				}
				compilation.warnings.push(new Error(sanity.warnMessage));
			}
		});
	}
};
//#endregion
export { PluginDev as default };
