@addfox/core 0.1.1-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":["../../src/config/defineConfig.ts","../../src/constants.ts","../../src/entry/html.ts","../../src/entry/discoverer.ts","../../src/entry/manifestParser.ts","../../src/entry/resolver.ts","../../src/manifest/loader.ts","../../src/config/loader.ts","../../src/manifest/builder.ts","../../src/reloadManager.ts","../../src/version.ts","../../src/frameworkDetect.ts"],"sourcesContent":["import type { AddfoxUserConfig } from \"../types.ts\";\r\n\r\nexport function defineConfig(config: AddfoxUserConfig): AddfoxUserConfig {\r\n return config;\r\n}\r\n","/**\r\n * Framework-level constants shared by config, discover, manifest, cli, etc.\r\n * Some behaviour can be overridden via AddfoxUserConfig or env vars.\r\n */\r\n\r\n/** Supported config file names (priority order) */\r\nexport const CONFIG_FILES = [\"addfox.config.ts\", \"addfox.config.js\", \"addfox.config.mjs\"] as const;\r\n\r\n/** Entry script extensions (.js preferred when both exist) */\r\nexport const SCRIPT_EXTS = [\".js\", \".jsx\", \".ts\", \".tsx\"] as const;\r\n\r\n/** Reserved entry names (not user-renamable): popup, options, sidepanel, offscreen, sandbox, newtab, bookmarks, history, background, devtools, content */\r\nexport const RESERVED_ENTRY_NAMES = [\r\n \"popup\",\r\n \"options\",\r\n \"sidepanel\",\r\n \"offscreen\",\r\n \"sandbox\",\r\n \"newtab\",\r\n \"bookmarks\",\r\n \"history\",\r\n \"background\",\r\n \"devtools\",\r\n \"content\",\r\n] as const;\r\n\r\n/** Entry names that require HTML (popup, options, sidepanel, devtools, offscreen, sandbox, newtab, bookmarks, history) */\r\nexport const HTML_ENTRY_NAMES = [\r\n \"popup\",\r\n \"options\",\r\n \"sidepanel\",\r\n \"devtools\",\r\n \"offscreen\",\r\n \"sandbox\",\r\n \"newtab\",\r\n \"bookmarks\",\r\n \"history\",\r\n] as const;\r\n\r\n/** Script-only entry names (background, content) */\r\nexport const SCRIPT_ONLY_ENTRY_NAMES = [\"background\", \"content\"] as const;\r\n\r\n/**\r\n * Entry names that participate in HMR reload manager (WS-only reload).\r\n * Same set as SCRIPT_ONLY_ENTRY_NAMES; single source of truth for pipeline and plugin-hmr.\r\n */\r\nexport const RELOAD_MANAGER_ENTRY_NAMES = new Set<string>(SCRIPT_ONLY_ENTRY_NAMES);\r\n\r\n/** Parent dir for build output (path is outputRoot/outDir; avoids root dist being scanned by Tailwind v4 etc.) */\r\nexport const ADDFOX_OUTPUT_ROOT = \".addfox\";\r\n\r\n/** Default output dir name under outputRoot (user can override via outDir) */\r\nexport const DEFAULT_OUT_DIR = \"extension\";\r\n\r\n/** Default app directory (relative to project root) */\r\nexport const DEFAULT_APP_DIR = \"app\";\r\n\r\n/** Default env prefixes exposed to extension runtime (only public vars) */\r\nexport const DEFAULT_ENV_PREFIXES = [\"ADDFOX_PUBLIC_\"] as const;\r\n\r\n/** Dev mode HMR WebSocket port */\r\nexport const HMR_WS_PORT = 23333;\r\n\r\n/** Default build target browser (manifest target) */\r\nexport const DEFAULT_BROWSER = \"chromium\" as const;\r\n\r\n/** Supported build targets for -t/--target and manifest selection */\r\nexport const SUPPORTED_BROWSERS = [\"chromium\", \"firefox\"] as const;\r\n\r\nexport type BrowserTarget = (typeof SUPPORTED_BROWSERS)[number];\r\n\r\n/** Browser-specific output subdirectory prefix */\r\nexport const BROWSER_OUTPUT_PREFIX = \"extension\" as const;\r\n\r\n/**\r\n * Get browser-specific output subdirectory name.\r\n * Returns \"extension-chromium\" or \"extension-firefox\" based on browser target.\r\n */\r\nexport function getBrowserOutputDir(browser: BrowserTarget): string {\r\n return `${BROWSER_OUTPUT_PREFIX}-${browser}`;\r\n}\r\n\r\n/** Supported browsers for CLI --browser and config.browserPath paths */\r\nexport const SUPPORTED_LAUNCH_TARGETS = [\r\n \"chrome\",\r\n \"chromium\",\r\n \"edge\",\r\n \"brave\",\r\n \"vivaldi\",\r\n \"opera\",\r\n \"santa\",\r\n \"arc\",\r\n \"yandex\",\r\n \"browseros\",\r\n \"custom\",\r\n \"firefox\",\r\n] as const;\r\n\r\nexport type LaunchTarget = (typeof SUPPORTED_LAUNCH_TARGETS)[number];\r\n\r\n/** CLI commands */\r\nexport const CLI_COMMANDS = [\"dev\", \"build\", \"test\"] as const;\r\n\r\nexport type CliCommand = (typeof CLI_COMMANDS)[number];\r\n\r\n/** Rstest config file names (resolution order per https://rstest.rs/guide/basic/configure-rstest) */\r\nexport const RSTEST_CONFIG_FILES = [\r\n \"rstest.config.cts\",\r\n \"rstest.config.mts\",\r\n \"rstest.config.cjs\",\r\n \"rstest.config.js\",\r\n \"rstest.config.ts\",\r\n \"rstest.config.mjs\",\r\n] as const;\r\n\r\n/** Manifest subdir under appDir (second lookup: appDir/manifest/) */\r\nexport const MANIFEST_DIR = \"manifest\";\r\n\r\n/** Manifest file names auto-read under appDir (base shared; chromium/firefox override) */\r\nexport const MANIFEST_FILE_NAMES = {\r\n base: \"manifest.json\",\r\n chromium: \"manifest.chromium.json\",\r\n firefox: \"manifest.firefox.json\",\r\n} as const;\r\n\r\n/** Output paths per entry in manifest (relative to outDir); key is placeholder [addfox.xxx] name */\r\nexport const MANIFEST_ENTRY_PATHS = {\r\n background: \"background/index.js\",\r\n content: \"content/index.js\",\r\n popup: \"popup/index.html\",\r\n options: \"options/index.html\",\r\n sidepanel: \"sidepanel/index.html\",\r\n devtools: \"devtools/index.html\",\r\n offscreen: \"offscreen/index.html\",\r\n sandbox: \"sandbox/index.html\",\r\n newtab: \"newtab/index.html\",\r\n bookmarks: \"bookmarks/index.html\",\r\n history: \"history/index.html\",\r\n} as const;\r\n\r\n/** Placeholder [addfox.xxx] key; must match MANIFEST_ENTRY_PATHS keys */\r\nexport type EntryKey = keyof typeof MANIFEST_ENTRY_PATHS;\r\n\r\n/** Runtime list of entry keys (for placeholder replacement iteration) */\r\nexport const MANIFEST_ENTRY_KEYS: readonly EntryKey[] = Object.keys(\r\n MANIFEST_ENTRY_PATHS\r\n) as EntryKey[];\r\n\r\n/** Chromium-family only (excludes firefox); used for HMR etc. */\r\nexport type ChromiumLaunchTarget = Exclude<LaunchTarget, \"firefox\">;\r\n","import { resolve, dirname } from \"path\";\r\nimport { readFileSync, existsSync } from \"fs\";\r\nimport type { ScriptInjectPosition } from \"../types.ts\";\r\n\r\nexport type { ScriptInjectPosition };\r\n\r\nexport interface AddfoxEntryScriptResult {\r\n /** Resolved src attribute value (relative path) */\r\n src: string;\r\n /** Where the script tag sits: head or body */\r\n inject: ScriptInjectPosition;\r\n /** HTML content with the data-addfox-entry script tag removed */\r\n strippedHtml: string;\r\n}\r\n\r\n/** True if src is a relative path (no leading / or \\, no protocol). */\r\nexport function isScriptSrcRelative(src: string): boolean {\r\n const t = src.trim();\r\n if (t.startsWith(\"/\") || t.startsWith(\"\\\\\")) return false;\r\n if (/^[a-z][a-z0-9+.-]*:\\/\\//i.test(t)) return false;\r\n return true;\r\n}\r\n\r\nconst ENTRY_SCRIPT_REGEX =\r\n /<script\\b[^>]*data-addfox-entry[^>]*>[\\s\\S]*?<\\/script>/gi;\r\nconst HEAD_CLOSE_REGEX = /<\\/head\\s*>/i;\r\n\r\n/** Matches a single script tag with src attribute (for fallback). */\r\nconst SCRIPT_WITH_SRC_REGEX =\r\n /<script\\b[^>]*\\ssrc\\s*=\\s*[\"']([^\"']+)[\"'][^>]*>[\\s\\S]*?<\\/script>/gi;\r\n\r\n/**\r\n * Finds the first <script src=\"...\"> in HTML (head or body) with protocol-less src.\r\n * Returns { src, fullTag, tagStartIndex } or undefined.\r\n */\r\nfunction findFirstScriptWithRelativeSrc(html: string): { src: string; fullTag: string; tagStartIndex: number } | undefined {\r\n const reg = new RegExp(SCRIPT_WITH_SRC_REGEX.source, \"gi\");\r\n let match: RegExpExecArray | null;\r\n while ((match = reg.exec(html)) !== null) {\r\n const src = match[1];\r\n if (!isScriptSrcRelative(src)) continue;\r\n return { src, fullTag: match[0], tagStartIndex: match.index };\r\n }\r\n return undefined;\r\n}\r\n\r\n/**\r\n * Parses HTML at htmlPath for the entry script.\r\n * Entry is either: (1) script with data-addfox-entry and protocol-less src, or\r\n * (2) if none found, the first script in HTML (head or body) with protocol-less src.\r\n * Returns src, inject position (head vs body), and HTML with that script tag removed.\r\n * If no such tag is found or it has no valid src, returns undefined.\r\n */\r\nexport function parseAddfoxEntryFromHtml(\r\n htmlPath: string\r\n): AddfoxEntryScriptResult | undefined {\r\n const raw = readFileSync(htmlPath, \"utf-8\");\r\n\r\n const reg = new RegExp(ENTRY_SCRIPT_REGEX.source, \"gi\");\r\n const match = reg.exec(raw);\r\n if (match) {\r\n const tag = match[0];\r\n const tagStartIndex = match.index;\r\n const srcMatch = tag.match(/src\\s*=\\s*[\"']([^\"']+)[\"']/i);\r\n if (srcMatch?.[1] && isScriptSrcRelative(srcMatch[1])) {\r\n const src = srcMatch[1];\r\n const headCloseMatch = raw.match(HEAD_CLOSE_REGEX);\r\n const headCloseIndex = headCloseMatch?.index ?? -1;\r\n const inject: ScriptInjectPosition =\r\n headCloseIndex >= 0 && tagStartIndex < headCloseIndex ? \"head\" : \"body\";\r\n const strippedHtml = raw.replace(ENTRY_SCRIPT_REGEX, \"\").trimEnd();\r\n return { src, inject, strippedHtml };\r\n }\r\n }\r\n\r\n const fallback = findFirstScriptWithRelativeSrc(raw);\r\n if (!fallback) return undefined;\r\n const headCloseMatch = raw.match(HEAD_CLOSE_REGEX);\r\n const headCloseIndex = headCloseMatch?.index ?? -1;\r\n const inject: ScriptInjectPosition =\r\n headCloseIndex >= 0 && fallback.tagStartIndex < headCloseIndex ? \"head\" : \"body\";\r\n const strippedHtml = raw.replace(fallback.fullTag, \"\").trimEnd();\r\n return {\r\n src: fallback.src,\r\n inject,\r\n strippedHtml,\r\n };\r\n}\r\n\r\n/**\r\n * If html has data-addfox-entry and its script src resolves to the same path as scriptPath,\r\n * returns the inject position so the entry can use stripped template and html.inject.\r\n */\r\nexport function getScriptInjectIfMatches(\r\n htmlPath: string,\r\n scriptPath: string\r\n): ScriptInjectPosition | undefined {\r\n try {\r\n const parsed = parseAddfoxEntryFromHtml(htmlPath);\r\n if (!parsed) return undefined;\r\n const resolvedFromHtml = resolve(dirname(htmlPath), parsed.src);\r\n return resolvedFromHtml === scriptPath ? parsed.inject : undefined;\r\n } catch {\r\n return undefined;\r\n }\r\n}\r\n\r\n/**\r\n * Resolve script path from HTML that has data-addfox-entry with src.\r\n * - src must be relative; throws if absolute.\r\n * - Resolved file must exist; throws if not found.\r\n * Use this when the entry is driven by HTML so invalid config fails fast.\r\n */\r\nexport function resolveScriptFromHtmlStrict(htmlPath: string): {\r\n scriptPath: string;\r\n inject: ScriptInjectPosition;\r\n} {\r\n const parsed = parseAddfoxEntryFromHtml(htmlPath);\r\n if (!parsed) {\r\n throw new Error(\r\n \"data-addfox-entry script must have a src attribute (relative path)\"\r\n );\r\n }\r\n if (!isScriptSrcRelative(parsed.src)) {\r\n throw new Error(\r\n `data-addfox-entry src must be relative, got: ${JSON.stringify(parsed.src)}`\r\n );\r\n }\r\n const scriptPath = resolve(dirname(htmlPath), parsed.src);\r\n if (!existsSync(scriptPath)) {\r\n throw new Error(`Entry script not found: ${scriptPath}`);\r\n }\r\n return { scriptPath, inject: parsed.inject };\r\n}\r\n","/**\r\n * Entry discovery - finds extension entry points\r\n */\r\n\r\nimport { resolve } from \"path\";\r\nimport { existsSync, readdirSync } from \"fs\";\r\nimport type { EntryInfo } from \"../types.ts\";\r\nimport { SCRIPT_EXTS, HTML_ENTRY_NAMES, SCRIPT_ONLY_ENTRY_NAMES } from \"../constants.ts\";\r\nimport {\r\n getScriptInjectIfMatches,\r\n parseAddfoxEntryFromHtml,\r\n resolveScriptFromHtmlStrict,\r\n} from \"./html.ts\";\r\nimport { AddfoxError, ADDFOX_ERROR_CODES } from \"@addfox/common\";\r\n\r\ninterface DirContents {\r\n files: Set<string>;\r\n dirs: Set<string>;\r\n}\r\n\r\ninterface DiscoveryOptions {\r\n scriptExts: readonly string[];\r\n scriptOnlyNames: readonly string[];\r\n htmlEntryNames: readonly string[];\r\n}\r\n\r\ninterface HtmlResolution {\r\n scriptPath: string;\r\n inject: EntryInfo[\"scriptInject\"];\r\n}\r\n\r\nfunction readDirContents(dir: string): DirContents | null {\r\n try {\r\n const entries = readdirSync(dir, { withFileTypes: true });\r\n return {\r\n files: new Set(entries.filter(e => e.isFile()).map(e => e.name)),\r\n dirs: new Set(entries.filter(e => e.isDirectory()).map(e => e.name)),\r\n };\r\n } catch {\r\n return null;\r\n }\r\n}\r\n\r\nfunction findScriptInDir(dir: string, scriptExts: readonly string[]): string | undefined {\r\n const contents = readDirContents(dir);\r\n if (!contents) return undefined;\r\n \r\n for (const ext of scriptExts) {\r\n if (contents.files.has(`index${ext}`)) return resolve(dir, `index${ext}`);\r\n }\r\n return undefined;\r\n}\r\n\r\nfunction findScriptInDirFromContents(\r\n dirPath: string,\r\n contents: DirContents | null,\r\n scriptExts: readonly string[]\r\n): string | undefined {\r\n if (!contents) return findScriptInDir(dirPath, scriptExts);\r\n \r\n for (const ext of scriptExts) {\r\n if (contents.files.has(`index${ext}`)) return resolve(dirPath, `index${ext}`);\r\n }\r\n return undefined;\r\n}\r\n\r\nfunction findNamedScript(\r\n baseDir: string,\r\n name: string,\r\n scriptExts: readonly string[],\r\n baseContents: DirContents | null\r\n): string | undefined {\r\n if (baseContents) {\r\n for (const ext of scriptExts) {\r\n if (baseContents.files.has(`${name}${ext}`)) return resolve(baseDir, `${name}${ext}`);\r\n }\r\n return undefined;\r\n }\r\n \r\n for (const ext of scriptExts) {\r\n const p = resolve(baseDir, `${name}${ext}`);\r\n if (existsSync(p)) return p;\r\n }\r\n return undefined;\r\n}\r\n\r\nfunction findNamedHtml(\r\n baseDir: string,\r\n name: string,\r\n baseContents: DirContents | null\r\n): string | undefined {\r\n if (baseContents) {\r\n return baseContents.files.has(`${name}.html`) ? resolve(baseDir, `${name}.html`) : undefined;\r\n }\r\n const p = resolve(baseDir, `${name}.html`);\r\n return existsSync(p) ? p : undefined;\r\n}\r\n\r\nfunction isValidScriptExt(pathStr: string, scriptExts: readonly string[]): boolean {\r\n const lower = pathStr.trim().toLowerCase();\r\n return scriptExts.some(ext => lower.endsWith(ext));\r\n}\r\n\r\nfunction resolveScriptFromHtmlWithInjectStrict(\r\n htmlPath: string,\r\n scriptExts: readonly string[]\r\n): HtmlResolution {\r\n const resolved = resolveScriptFromHtmlStrict(htmlPath);\r\n if (!isValidScriptExt(resolved.scriptPath, scriptExts)) {\r\n throw new AddfoxError({\r\n code: ADDFOX_ERROR_CODES.ENTRY_SCRIPT_FROM_HTML,\r\n message: \"Invalid data-addfox-entry script in HTML\",\r\n details: `HTML: ${htmlPath}. Resolved path is not a supported script: ${resolved.scriptPath}`,\r\n hint: \"data-addfox-entry script must have a relative src and the file must exist\",\r\n });\r\n }\r\n return resolved;\r\n}\r\n\r\nfunction tryResolveEntryFromHtml(\r\n htmlPath: string,\r\n scriptExts: readonly string[]\r\n): HtmlResolution | undefined {\r\n try {\r\n const parsed = parseAddfoxEntryFromHtml(htmlPath);\r\n if (!parsed) return undefined;\r\n return resolveScriptFromHtmlWithInjectStrict(htmlPath, scriptExts);\r\n } catch (e) {\r\n throw new AddfoxError({\r\n code: ADDFOX_ERROR_CODES.ENTRY_SCRIPT_FROM_HTML,\r\n message: \"Invalid data-addfox-entry script in HTML\",\r\n details: `HTML: ${htmlPath}. ${e instanceof Error ? e.message : String(e)}`,\r\n hint: \"data-addfox-entry script must have a relative src and the file must exist\",\r\n });\r\n }\r\n}\r\n\r\nfunction buildHtmlEntryInfo(\r\n name: string,\r\n htmlPath: string,\r\n conventionalScriptPath: string | undefined,\r\n scriptExts: readonly string[]\r\n): EntryInfo | null {\r\n const fromHtml = tryResolveEntryFromHtml(htmlPath, scriptExts);\r\n \r\n if (fromHtml) {\r\n return {\r\n name,\r\n scriptPath: fromHtml.scriptPath,\r\n htmlPath,\r\n html: true,\r\n scriptInject: fromHtml.inject,\r\n outputFollowsScriptPath: true,\r\n };\r\n }\r\n \r\n if (!conventionalScriptPath) return null;\r\n \r\n return {\r\n name,\r\n scriptPath: conventionalScriptPath,\r\n htmlPath,\r\n html: true,\r\n scriptInject: getScriptInjectIfMatches(htmlPath, conventionalScriptPath),\r\n };\r\n}\r\n\r\nfunction discoverScriptOnlyEntry(\r\n baseDir: string,\r\n name: string,\r\n contents: DirContents | null,\r\n options: DiscoveryOptions\r\n): EntryInfo | null {\r\n const singleScript = findNamedScript(baseDir, name, options.scriptExts, contents);\r\n if (singleScript) return { name, scriptPath: singleScript, html: false };\r\n\r\n if (!contents?.dirs.has(name)) return null;\r\n \r\n const scriptPath = findScriptInDir(resolve(baseDir, name), options.scriptExts);\r\n return scriptPath ? { name, scriptPath, html: false } : null;\r\n}\r\n\r\nfunction discoverHtmlEntryFromFlat(\r\n baseDir: string,\r\n name: string,\r\n contents: DirContents | null,\r\n options: DiscoveryOptions\r\n): EntryInfo | null {\r\n const singleScript = findNamedScript(baseDir, name, options.scriptExts, contents);\r\n const singleHtml = findNamedHtml(baseDir, name, contents);\r\n\r\n if (singleScript && singleHtml) {\r\n return buildHtmlEntryInfo(name, singleHtml, singleScript, options.scriptExts);\r\n }\r\n \r\n if (singleHtml) {\r\n const conventional = findNamedScript(baseDir, name, options.scriptExts, contents);\r\n return buildHtmlEntryInfo(name, singleHtml, conventional, options.scriptExts);\r\n }\r\n \r\n return null;\r\n}\r\n\r\nfunction discoverHtmlEntryFromDir(\r\n baseDir: string,\r\n name: string,\r\n contents: DirContents | null,\r\n options: DiscoveryOptions\r\n): EntryInfo | null {\r\n if (!contents?.dirs.has(name)) return null;\r\n\r\n const dirPath = resolve(baseDir, name);\r\n const subContents = readDirContents(dirPath);\r\n const htmlPath = subContents?.files.has(\"index.html\")\r\n ? resolve(dirPath, \"index.html\")\r\n : undefined;\r\n const scriptPath = findScriptInDirFromContents(dirPath, subContents, options.scriptExts);\r\n\r\n if (scriptPath && htmlPath) {\r\n return buildHtmlEntryInfo(name, htmlPath, scriptPath, options.scriptExts);\r\n }\r\n \r\n if (scriptPath) {\r\n return {\r\n name,\r\n scriptPath,\r\n htmlPath,\r\n html: true,\r\n scriptInject: htmlPath ? getScriptInjectIfMatches(htmlPath, scriptPath) : undefined,\r\n };\r\n }\r\n \r\n if (!htmlPath) return null;\r\n \r\n return buildHtmlEntryInfo(name, htmlPath, undefined, options.scriptExts);\r\n}\r\n\r\nfunction discoverHtmlEntry(\r\n baseDir: string,\r\n name: string,\r\n contents: DirContents | null,\r\n options: DiscoveryOptions\r\n): EntryInfo | null {\r\n return (\r\n discoverHtmlEntryFromFlat(baseDir, name, contents, options) ??\r\n discoverHtmlEntryFromDir(baseDir, name, contents, options)\r\n );\r\n}\r\n\r\nfunction discoverEntriesInternal(baseDir: string, options: DiscoveryOptions): EntryInfo[] {\r\n const contents = readDirContents(baseDir);\r\n const entries: EntryInfo[] = [];\r\n\r\n for (const name of options.scriptOnlyNames) {\r\n const entry = discoverScriptOnlyEntry(baseDir, name, contents, options);\r\n if (entry) entries.push(entry);\r\n }\r\n\r\n for (const name of options.htmlEntryNames) {\r\n const entry = discoverHtmlEntry(baseDir, name, contents, options);\r\n if (entry) entries.push(entry);\r\n }\r\n\r\n return entries;\r\n}\r\n\r\nexport interface EntryDiscovererOptions {\r\n scriptExts?: readonly string[];\r\n scriptOnlyNames?: readonly string[];\r\n htmlEntryNames?: readonly string[];\r\n}\r\n\r\nfunction createOptions(options: EntryDiscovererOptions = {}): DiscoveryOptions {\r\n return {\r\n scriptExts: options.scriptExts ?? SCRIPT_EXTS,\r\n scriptOnlyNames: options.scriptOnlyNames ?? SCRIPT_ONLY_ENTRY_NAMES,\r\n htmlEntryNames: options.htmlEntryNames ?? HTML_ENTRY_NAMES,\r\n };\r\n}\r\n\r\nexport function discoverEntries(baseDir: string, options?: EntryDiscovererOptions): EntryInfo[] {\r\n return discoverEntriesInternal(baseDir, createOptions(options));\r\n}\r\n\r\nexport function getHtmlEntryNames(options?: Pick<EntryDiscovererOptions, 'htmlEntryNames'>): string[] {\r\n return [...(options?.htmlEntryNames ?? HTML_ENTRY_NAMES)];\r\n}\r\n\r\nexport function getScriptOnlyEntryNames(options?: Pick<EntryDiscovererOptions, 'scriptOnlyNames'>): string[] {\r\n return [...(options?.scriptOnlyNames ?? SCRIPT_ONLY_ENTRY_NAMES)];\r\n}\r\n\r\nexport function getAllEntryNames(options?: EntryDiscovererOptions): string[] {\r\n return [...getHtmlEntryNames(options), ...getScriptOnlyEntryNames(options)];\r\n}\r\n\r\n","/**\r\n * Manifest entry parser - extracts entry paths from manifest.json\r\n * Allows users to specify source file paths directly in manifest fields\r\n */\r\n\r\nimport type { ManifestRecord, EntryConfigValue } from \"../types.ts\";\r\nimport type { BrowserTarget } from \"../constants.ts\";\r\nimport { MANIFEST_ENTRY_PATHS, MANIFEST_ENTRY_KEYS } from \"../constants.ts\";\r\n\r\ntype EntryKey = keyof typeof MANIFEST_ENTRY_PATHS;\r\n\r\ninterface ExtractedEntry {\r\n name: string;\r\n value: EntryConfigValue;\r\n /** Original manifest field path, used for later replacement */\r\n manifestPath: string;\r\n}\r\n\r\ninterface ParsedEntryFromManifest {\r\n entries: Record<string, EntryConfigValue>;\r\n /** Maps manifest field paths to entry names for replacement */\r\n replacementMap: Map<string, string>;\r\n}\r\n\r\n/** Whether the path is a source file path (not a build output path) */\r\nfunction isSourceFilePath(path: string): boolean {\r\n const lower = path.trim().toLowerCase();\r\n return /\\.(ts|tsx|js|jsx)$/.test(lower) && !lower.includes(\"/dist/\") && !lower.includes(\"\\\\dist\\\\\");\r\n}\r\n\r\n/** Extract entry name from path */\r\nfunction inferEntryNameFromPath(path: string): string | null {\r\n const cleanPath = path.replace(/^\\.\\/|^\\//, \"\");\r\n const firstSegment = cleanPath.split(/[\\/\\\\]/)[0];\r\n \r\n if (MANIFEST_ENTRY_KEYS.includes(firstSegment as EntryKey)) {\r\n return firstSegment;\r\n }\r\n return null;\r\n}\r\n\r\n/** Extract service_worker path */\r\nfunction extractServiceWorker(\r\n manifest: ManifestRecord,\r\n browser: BrowserTarget\r\n): ExtractedEntry | null {\r\n const bg = manifest.background as Record<string, unknown> | undefined;\r\n if (!bg) return null;\r\n\r\n // MV3: service_worker\r\n const serviceWorker = bg.service_worker;\r\n if (typeof serviceWorker === \"string\" && isSourceFilePath(serviceWorker)) {\r\n const entryName = inferEntryNameFromPath(serviceWorker) ?? \"background\";\r\n return {\r\n name: entryName,\r\n value: serviceWorker.replace(/^\\.\\//, \"\"),\r\n manifestPath: \"background.service_worker\",\r\n };\r\n }\r\n\r\n // MV2: scripts array\r\n const scripts = bg.scripts;\r\n if (Array.isArray(scripts) && scripts.length > 0) {\r\n const firstScript = scripts[0];\r\n if (typeof firstScript === \"string\" && isSourceFilePath(firstScript)) {\r\n const entryName = inferEntryNameFromPath(firstScript) ?? \"background\";\r\n return {\r\n name: entryName,\r\n value: firstScript.replace(/^\\.\\//, \"\"),\r\n manifestPath: \"background.scripts[0]\",\r\n };\r\n }\r\n }\r\n\r\n // MV2: page\r\n const page = bg.page;\r\n if (typeof page === \"string\" && isSourceFilePath(page)) {\r\n const entryName = inferEntryNameFromPath(page) ?? \"background\";\r\n return {\r\n name: entryName,\r\n value: page.replace(/^\\.\\//, \"\"),\r\n manifestPath: \"background.page\",\r\n };\r\n }\r\n\r\n return null;\r\n}\r\n\r\n/** Extract action.default_popup or browser_action.default_popup path */\r\nfunction extractPopup(\r\n manifest: ManifestRecord,\r\n browser: BrowserTarget\r\n): ExtractedEntry | null {\r\n const mv = manifest.manifest_version === 2 ? 2 : 3;\r\n \r\n let popupPath: string | undefined;\r\n let manifestPath: string | undefined;\r\n\r\n if (mv === 3) {\r\n const action = manifest.action as Record<string, unknown> | undefined;\r\n const defaultPopup = action?.default_popup;\r\n if (typeof defaultPopup === \"string\") {\r\n popupPath = defaultPopup;\r\n manifestPath = \"action.default_popup\";\r\n }\r\n } else {\r\n const browserAction = manifest.browser_action as Record<string, unknown> | undefined;\r\n const defaultPopup = browserAction?.default_popup;\r\n if (typeof defaultPopup === \"string\") {\r\n popupPath = defaultPopup;\r\n manifestPath = \"browser_action.default_popup\";\r\n }\r\n }\r\n\r\n if (popupPath && isSourceFilePath(popupPath)) {\r\n const entryName = inferEntryNameFromPath(popupPath) ?? \"popup\";\r\n return {\r\n name: entryName,\r\n value: popupPath.replace(/^\\.\\//, \"\"),\r\n manifestPath: manifestPath!,\r\n };\r\n }\r\n\r\n return null;\r\n}\r\n\r\n/** Extract options_page or options_ui.page path */\r\nfunction extractOptions(manifest: ManifestRecord): ExtractedEntry | null {\r\n const mv = manifest.manifest_version === 2 ? 2 : 3;\r\n \r\n let optionsPath: string | undefined;\r\n let manifestPath: string | undefined;\r\n\r\n if (mv === 3) {\r\n const optionsUi = manifest.options_ui as Record<string, unknown> | undefined;\r\n const page = optionsUi?.page;\r\n if (typeof page === \"string\") {\r\n optionsPath = page;\r\n manifestPath = \"options_ui.page\";\r\n }\r\n } else {\r\n const optionsPage = manifest.options_page;\r\n if (typeof optionsPage === \"string\") {\r\n optionsPath = optionsPage;\r\n manifestPath = \"options_page\";\r\n }\r\n }\r\n\r\n if (optionsPath && isSourceFilePath(optionsPath)) {\r\n const entryName = inferEntryNameFromPath(optionsPath) ?? \"options\";\r\n return {\r\n name: entryName,\r\n value: optionsPath.replace(/^\\.\\//, \"\"),\r\n manifestPath: manifestPath!,\r\n };\r\n }\r\n\r\n return null;\r\n}\r\n\r\n/** Extract devtools_page path */\r\nfunction extractDevtools(manifest: ManifestRecord): ExtractedEntry | null {\r\n const devtoolsPage = manifest.devtools_page;\r\n if (typeof devtoolsPage === \"string\" && isSourceFilePath(devtoolsPage)) {\r\n const entryName = inferEntryNameFromPath(devtoolsPage) ?? \"devtools\";\r\n return {\r\n name: entryName,\r\n value: devtoolsPage.replace(/^\\.\\//, \"\"),\r\n manifestPath: \"devtools_page\",\r\n };\r\n }\r\n return null;\r\n}\r\n\r\n/** Extract side_panel.default_path */\r\nfunction extractSidepanel(manifest: ManifestRecord): ExtractedEntry | null {\r\n const sidePanel = manifest.side_panel as Record<string, unknown> | undefined;\r\n const defaultPath = sidePanel?.default_path;\r\n \r\n if (typeof defaultPath === \"string\" && isSourceFilePath(defaultPath)) {\r\n const entryName = inferEntryNameFromPath(defaultPath) ?? \"sidepanel\";\r\n return {\r\n name: entryName,\r\n value: defaultPath.replace(/^\\.\\//, \"\"),\r\n manifestPath: \"side_panel.default_path\",\r\n };\r\n }\r\n return null;\r\n}\r\n\r\n/** Extract sandbox.pages path */\r\nfunction extractSandbox(manifest: ManifestRecord): ExtractedEntry | null {\r\n const sandbox = manifest.sandbox as Record<string, unknown> | undefined;\r\n const pages = sandbox?.pages;\r\n \r\n if (Array.isArray(pages) && pages.length > 0) {\r\n const firstPage = pages[0];\r\n if (typeof firstPage === \"string\" && isSourceFilePath(firstPage)) {\r\n const entryName = inferEntryNameFromPath(firstPage) ?? \"sandbox\";\r\n return {\r\n name: entryName,\r\n value: firstPage.replace(/^\\.\\//, \"\"),\r\n manifestPath: \"sandbox.pages[0]\",\r\n };\r\n }\r\n }\r\n return null;\r\n}\r\n\r\n/** Extract chrome_url_overrides paths */\r\nfunction extractOverrides(manifest: ManifestRecord): ExtractedEntry[] {\r\n const entries: ExtractedEntry[] = [];\r\n const overrides = manifest.chrome_url_overrides as Record<string, unknown> | undefined;\r\n \r\n if (!overrides) return entries;\r\n\r\n const overrideKeys = [\"newtab\", \"bookmarks\", \"history\"] as const;\r\n \r\n for (const key of overrideKeys) {\r\n const path = overrides[key];\r\n if (typeof path === \"string\" && isSourceFilePath(path)) {\r\n const entryName = inferEntryNameFromPath(path) ?? key;\r\n entries.push({\r\n name: entryName,\r\n value: path.replace(/^\\.\\//, \"\"),\r\n manifestPath: `chrome_url_overrides.${key}`,\r\n });\r\n }\r\n }\r\n \r\n return entries;\r\n}\r\n\r\n/** Extract source file paths from content_scripts */\r\nfunction extractContentScripts(manifest: ManifestRecord): ExtractedEntry | null {\r\n const contentScripts = manifest.content_scripts;\r\n if (!Array.isArray(contentScripts) || contentScripts.length === 0) {\r\n return null;\r\n }\r\n\r\n /** Find first content script that includes a source file path */\r\n for (let i = 0; i < contentScripts.length; i++) {\r\n const cs = contentScripts[i] as Record<string, unknown>;\r\n const js = cs.js;\r\n \r\n if (Array.isArray(js) && js.length > 0) {\r\n for (let j = 0; j < js.length; j++) {\r\n const path = js[j];\r\n if (typeof path === \"string\" && isSourceFilePath(path)) {\r\n const entryName = inferEntryNameFromPath(path) ?? \"content\";\r\n return {\r\n name: entryName,\r\n value: path.replace(/^\\.\\//, \"\"),\r\n manifestPath: `content_scripts[${i}].js[${j}]`,\r\n };\r\n }\r\n }\r\n }\r\n }\r\n\r\n return null;\r\n}\r\n\r\n/**\r\n * Extract all entry config from manifest.\r\n * Only extracts fields that specify source file paths (.ts/.tsx/.js/.jsx).\r\n */\r\nexport function extractEntriesFromManifest(\r\n manifest: ManifestRecord,\r\n browser: BrowserTarget\r\n): ParsedEntryFromManifest {\r\n const entries: Record<string, EntryConfigValue> = {};\r\n const replacementMap = new Map<string, string>();\r\n\r\n const extractors = [\r\n () => extractServiceWorker(manifest, browser),\r\n () => extractPopup(manifest, browser),\r\n () => extractOptions(manifest),\r\n () => extractDevtools(manifest),\r\n () => extractSidepanel(manifest),\r\n () => extractSandbox(manifest),\r\n () => extractContentScripts(manifest),\r\n () => extractOverrides(manifest),\r\n ];\r\n\r\n for (const extractor of extractors) {\r\n const result = extractor();\r\n if (result) {\r\n if (Array.isArray(result)) {\r\n for (const entry of result) {\r\n entries[entry.name] = entry.value;\r\n replacementMap.set(entry.manifestPath, entry.name);\r\n }\r\n } else {\r\n entries[result.name] = result.value;\r\n replacementMap.set(result.manifestPath, result.name);\r\n }\r\n }\r\n }\r\n\r\n return { entries, replacementMap };\r\n}\r\n\r\n/**\r\n * Check whether the manifest contains any source file paths.\r\n */\r\nexport function hasManifestSourcePaths(manifest: ManifestRecord): boolean {\r\n const tempBrowser: BrowserTarget = \"chromium\";\r\n const { entries } = extractEntriesFromManifest(manifest, tempBrowser);\r\n return Object.keys(entries).length > 0;\r\n}\r\n\r\nexport type { ParsedEntryFromManifest, ExtractedEntry };\r\n","/**\r\n * Entry resolution - resolves entry configuration\r\n * Priority: 1. config.entry > 2. manifest entries > 3. auto-discovery\r\n */\r\n\r\nimport { resolve, dirname, basename } from \"path\";\r\nimport { existsSync } from \"fs\";\r\nimport type { AddfoxUserConfig, EntryInfo, EntryConfigValue, ManifestRecord } from \"../types.ts\";\r\nimport { HTML_ENTRY_NAMES, SCRIPT_EXTS } from \"../constants.ts\";\r\nimport type { BrowserTarget } from \"../constants.ts\";\r\nimport { discoverEntries, type EntryDiscovererOptions } from \"./discoverer.ts\";\r\nimport {\r\n getScriptInjectIfMatches,\r\n parseAddfoxEntryFromHtml,\r\n resolveScriptFromHtmlStrict,\r\n} from \"./html.ts\";\r\nimport { AddfoxError, ADDFOX_ERROR_CODES } from \"@addfox/common\";\r\nimport { extractEntriesFromManifest, type ParsedEntryFromManifest } from \"./manifestParser.ts\";\r\n\r\n// ============================================================================\r\n// Types\r\n// ============================================================================\r\n\r\nexport interface EntryResolverOptions {\r\n entryDiscovererOptions?: EntryDiscovererOptions;\r\n /** Target browser for manifest entry extraction */\r\n browser?: BrowserTarget;\r\n}\r\n\r\nexport interface EntryResolutionResult {\r\n entries: EntryInfo[];\r\n /** Map of manifest field paths to entry names for output path replacement */\r\n manifestReplacementMap?: Map<string, string>;\r\n}\r\n\r\n// ============================================================================\r\n// Utilities\r\n// ============================================================================\r\n\r\nconst HTML_ENTRY_SET = new Set(HTML_ENTRY_NAMES);\r\n\r\nfunction isHtmlPath(pathStr: string): boolean {\r\n return pathStr.trim().toLowerCase().endsWith(\".html\");\r\n}\r\n\r\nfunction isScriptPath(pathStr: string): boolean {\r\n const lower = pathStr.trim().toLowerCase();\r\n return SCRIPT_EXTS.some(ext => lower.endsWith(ext));\r\n}\r\n\r\nfunction findScriptInDir(dir: string): string | undefined {\r\n for (const ext of SCRIPT_EXTS) {\r\n const p = resolve(dir, `index${ext}`);\r\n if (existsSync(p)) return p;\r\n }\r\n return undefined;\r\n}\r\n\r\nfunction findScriptForHtmlDir(dir: string, htmlFilename: string): string | undefined {\r\n const stem = basename(htmlFilename, \".html\");\r\n for (const ext of SCRIPT_EXTS) {\r\n const p = resolve(dir, `${stem}${ext}`);\r\n if (existsSync(p)) return p;\r\n }\r\n return findScriptInDir(dir);\r\n}\r\n\r\nfunction isEntryConfigObject(value: EntryConfigValue): value is { src: string; html?: boolean | string } {\r\n return typeof value === \"object\" && value !== null && \"src\" in value;\r\n}\r\n\r\nfunction resolveHtmlPath(baseDir: string, htmlValue: string | undefined): string | undefined {\r\n if (!htmlValue) return undefined;\r\n const resolved = resolve(baseDir, htmlValue);\r\n if (!isHtmlPath(resolved)) return undefined;\r\n return existsSync(resolved) ? resolved : undefined;\r\n}\r\n\r\nfunction resolveHtmlFlag(\r\n entryName: string,\r\n htmlValue: boolean | string | undefined,\r\n hasTemplate: boolean\r\n): boolean {\r\n if (htmlValue === false) return false;\r\n if (htmlValue === true) return true;\r\n if (typeof htmlValue === \"string\") return hasTemplate;\r\n return isHtmlEntryName(entryName);\r\n}\r\n\r\nfunction isHtmlEntryName(entryName: string): boolean {\r\n return HTML_ENTRY_SET.has(entryName as (typeof HTML_ENTRY_NAMES)[number]);\r\n}\r\n\r\nfunction enrichEntryWithScriptInject(entry: EntryInfo): EntryInfo {\r\n if (!entry.htmlPath || !entry.scriptPath) return entry;\r\n const scriptInject = getScriptInjectIfMatches(entry.htmlPath, entry.scriptPath);\r\n return scriptInject ? { ...entry, scriptInject } : entry;\r\n}\r\n\r\nfunction inferHtmlPathForReservedName(entryName: string, scriptPath: string): string | undefined {\r\n if (!HTML_ENTRY_SET.has(entryName as (typeof HTML_ENTRY_NAMES)[number])) return undefined;\r\n const dir = dirname(scriptPath);\r\n const htmlPath = resolve(dir, \"index.html\");\r\n return existsSync(htmlPath) ? htmlPath : undefined;\r\n}\r\n\r\n// ============================================================================\r\n// Entry Resolution\r\n// ============================================================================\r\n\r\nfunction resolveEntryFromObject(\r\n baseDir: string,\r\n name: string,\r\n value: { src: string; html?: boolean | string }\r\n): EntryInfo | null {\r\n const scriptPath = resolve(baseDir, value.src);\r\n if (!existsSync(scriptPath) || !isScriptPath(scriptPath)) return null;\r\n \r\n const htmlPath = resolveHtmlPath(baseDir, typeof value.html === \"string\" ? value.html : undefined);\r\n if (typeof value.html === \"string\" && !htmlPath) return null;\r\n \r\n const inferredHtml = htmlPath ?? inferHtmlPathForReservedName(name, scriptPath);\r\n const html = resolveHtmlFlag(name, value.html, Boolean(htmlPath));\r\n \r\n return enrichEntryWithScriptInject({ name, scriptPath, htmlPath: inferredHtml, html });\r\n}\r\n\r\nfunction resolveEntryFromHtml(\r\n baseDir: string,\r\n name: string,\r\n pathStr: string\r\n): EntryInfo | null {\r\n const htmlPath = resolve(baseDir, pathStr);\r\n const dir = dirname(htmlPath);\r\n \r\n let parsed: ReturnType<typeof parseAddfoxEntryFromHtml>;\r\n try {\r\n parsed = parseAddfoxEntryFromHtml(htmlPath);\r\n } catch {\r\n parsed = undefined;\r\n }\r\n \r\n let scriptPath: string | undefined;\r\n if (parsed) {\r\n try {\r\n scriptPath = resolveScriptFromHtmlStrict(htmlPath).scriptPath;\r\n } catch (e) {\r\n throw new AddfoxError({\r\n code: ADDFOX_ERROR_CODES.ENTRY_SCRIPT_FROM_HTML,\r\n message: \"Invalid data-addfox-entry script in HTML\",\r\n details: `HTML: ${htmlPath}. ${e instanceof Error ? e.message : String(e)}`,\r\n hint: \"data-addfox-entry script must have a relative src and the file must exist\",\r\n });\r\n }\r\n } else {\r\n scriptPath = findScriptForHtmlDir(dir, basename(htmlPath));\r\n }\r\n \r\n if (!scriptPath) return null;\r\n \r\n return enrichEntryWithScriptInject({\r\n name,\r\n scriptPath,\r\n htmlPath,\r\n html: true,\r\n outputFollowsScriptPath: Boolean(parsed),\r\n });\r\n}\r\n\r\nfunction resolveEntryFromScript(\r\n baseDir: string,\r\n name: string,\r\n pathStr: string\r\n): EntryInfo | null {\r\n const scriptPath = resolve(baseDir, pathStr);\r\n if (!existsSync(scriptPath)) return null;\r\n \r\n const htmlPath = inferHtmlPathForReservedName(name, scriptPath);\r\n const html = isHtmlEntryName(name);\r\n \r\n return enrichEntryWithScriptInject({ name, scriptPath, htmlPath, html });\r\n}\r\n\r\nfunction resolveSingleEntry(\r\n baseDir: string,\r\n name: string,\r\n value: EntryConfigValue\r\n): EntryInfo | null {\r\n if (isEntryConfigObject(value)) {\r\n return resolveEntryFromObject(baseDir, name, value);\r\n }\r\n \r\n const resolved = resolve(baseDir, value);\r\n if (!existsSync(resolved)) return null;\r\n \r\n if (isHtmlPath(value)) {\r\n return resolveEntryFromHtml(baseDir, name, value);\r\n }\r\n \r\n if (isScriptPath(value)) {\r\n return resolveEntryFromScript(baseDir, name, value);\r\n }\r\n \r\n return null;\r\n}\r\n\r\n// ============================================================================\r\n// Public API\r\n// ============================================================================\r\n\r\n/**\r\n * Resolve entries with priority:\r\n * 1. config.entry (highest priority)\r\n * 2. manifest entries (if config.entry doesn't specify)\r\n * 3. auto-discovery (lowest priority)\r\n */\r\nexport function resolveEntries(\r\n config: Pick<AddfoxUserConfig, \"entry\" | \"appDir\">,\r\n _root: string,\r\n baseDir: string,\r\n manifest?: ManifestRecord,\r\n options?: EntryResolverOptions\r\n): EntryResolutionResult {\r\n const browser = options?.browser ?? \"chromium\";\r\n \r\n // Step 1: Start with auto-discovered entries (lowest priority)\r\n const defaultEntries = discoverEntries(baseDir, options?.entryDiscovererOptions);\r\n const entryMap = new Map<string, EntryInfo>(defaultEntries.map(e => [e.name, e]));\r\n \r\n // Track manifest replacement map for output path replacement\r\n let manifestReplacementMap: Map<string, string> | undefined;\r\n \r\n // Step 2: Apply manifest entries (middle priority) - only if no config.entry\r\n const entryConfig = config.entry;\r\n const hasExplicitEntryConfig = entryConfig && Object.keys(entryConfig).length > 0;\r\n \r\n if (manifest && !hasExplicitEntryConfig) {\r\n const manifestResult = extractEntriesFromManifest(manifest, browser);\r\n manifestReplacementMap = manifestResult.replacementMap;\r\n \r\n for (const [name, pathStr] of Object.entries(manifestResult.entries)) {\r\n // Only apply if entry not already resolved from config.entry\r\n const resolved = resolveSingleEntry(baseDir, name, pathStr);\r\n if (resolved) {\r\n entryMap.set(name, resolved);\r\n }\r\n }\r\n }\r\n \r\n // Step 3: Apply config.entry (highest priority) - always overrides\r\n if (hasExplicitEntryConfig) {\r\n for (const [name, pathStr] of Object.entries(entryConfig)) {\r\n const resolved = resolveSingleEntry(baseDir, name, pathStr);\r\n if (resolved) entryMap.set(name, resolved);\r\n else entryMap.delete(name);\r\n }\r\n }\r\n \r\n return {\r\n entries: Array.from(entryMap.values()),\r\n manifestReplacementMap,\r\n };\r\n}\r\n\r\n/**\r\n * Legacy API - returns just the entries array for backward compatibility\r\n */\r\nexport function resolveEntriesLegacy(\r\n config: Pick<AddfoxUserConfig, \"entry\" | \"appDir\">,\r\n _root: string,\r\n baseDir: string,\r\n options?: EntryResolverOptions\r\n): EntryInfo[] {\r\n return resolveEntries(config, _root, baseDir, undefined, options).entries;\r\n}\r\n\r\nexport { extractEntriesFromManifest, type ParsedEntryFromManifest };\r\n","import { resolve } from \"path\";\r\nimport { readFileSync, existsSync } from \"fs\";\r\nimport type {\r\n ManifestConfig,\r\n ManifestRecord,\r\n ChromiumFirefoxManifest,\r\n ManifestPathConfig,\r\n} from \"../types.ts\";\r\nimport type { BrowserTarget } from \"../constants.ts\";\r\nimport { MANIFEST_DIR, MANIFEST_FILE_NAMES } from \"../constants.ts\";\r\n\r\n/** Target for manifest validation: use browser-specific rules (e.g. Firefox MV3 allows background.scripts). */\r\nexport type ManifestValidationTarget = Extract<BrowserTarget, \"chromium\" | \"firefox\">;\r\n\r\n/**\r\n * Manifest loader: reads manifest from appDir or resolves manifest object/path config from addfox.config.\r\n */\r\nexport class ManifestLoader {\r\n private readManifestJson(filePath: string): ManifestRecord | null {\r\n if (!existsSync(filePath)) return null;\r\n try {\r\n const raw = readFileSync(filePath, \"utf-8\");\r\n const data = JSON.parse(raw);\r\n return typeof data === \"object\" && data !== null ? (data as ManifestRecord) : null;\r\n } catch {\r\n return null;\r\n }\r\n }\r\n\r\n private isManifestPathConfig(\r\n m: ManifestConfig | ManifestPathConfig | undefined\r\n ): m is ManifestPathConfig {\r\n if (!m || typeof m !== \"object\") return false;\r\n const c = m as Record<string, unknown>;\r\n return (\r\n (typeof c.chromium === \"string\" || typeof c.firefox === \"string\") &&\r\n !(\"manifest_version\" in c) &&\r\n !(\"name\" in c && \"version\" in c)\r\n );\r\n }\r\n\r\n private isChromiumFirefoxObject(m: ManifestConfig): m is ChromiumFirefoxManifest {\r\n return isChromiumFirefoxObjectValue(m);\r\n }\r\n\r\n private deepMerge(base: ManifestRecord, override: ManifestRecord): ManifestRecord {\r\n const out: ManifestRecord = { ...base };\r\n for (const key of Object.keys(override)) {\r\n const b = base[key];\r\n const o = override[key];\r\n if (\r\n o !== null &&\r\n typeof o === \"object\" &&\r\n !Array.isArray(o) &&\r\n b !== null &&\r\n typeof b === \"object\" &&\r\n !Array.isArray(b)\r\n ) {\r\n out[key] = this.deepMerge(b as ManifestRecord, o as ManifestRecord);\r\n } else {\r\n out[key] = o;\r\n }\r\n }\r\n return out;\r\n }\r\n\r\n private loadFromDir(dir: string): {\r\n base: ManifestRecord | null;\r\n chromium: ManifestRecord | null;\r\n firefox: ManifestRecord | null;\r\n } {\r\n const basePath = resolve(dir, MANIFEST_FILE_NAMES.base);\r\n const chromPath = resolve(dir, MANIFEST_FILE_NAMES.chromium);\r\n const firefoxPath = resolve(dir, MANIFEST_FILE_NAMES.firefox);\r\n return {\r\n base: this.readManifestJson(basePath),\r\n chromium: this.readManifestJson(chromPath),\r\n firefox: this.readManifestJson(firefoxPath),\r\n };\r\n }\r\n\r\n private hasAnyManifest(files: {\r\n base: ManifestRecord | null;\r\n chromium: ManifestRecord | null;\r\n firefox: ManifestRecord | null;\r\n }): boolean {\r\n return files.base !== null || files.chromium !== null || files.firefox !== null;\r\n }\r\n\r\n private buildConfigFromFiles(files: {\r\n base: ManifestRecord | null;\r\n chromium: ManifestRecord | null;\r\n firefox: ManifestRecord | null;\r\n }): ChromiumFirefoxManifest | null {\r\n const base = files.base ?? files.chromium ?? files.firefox ?? null;\r\n if (!base) return null;\r\n const chromium = files.chromium ? this.deepMerge(base, files.chromium) : base;\r\n const firefox = files.firefox ? this.deepMerge(base, files.firefox) : base;\r\n return { chromium, firefox };\r\n }\r\n\r\n /**\r\n * Resolve user manifest (object / path / unset) into unified ManifestConfig (object form).\r\n * Priority: addfox.config manifest > files directly in appDir > files in appDir/manifest/.\r\n */\r\n resolve(\r\n input: ManifestConfig | ManifestPathConfig | undefined,\r\n root: string,\r\n appDir: string\r\n ): ManifestConfig | null {\r\n if (input === undefined || input === null) {\r\n const manifestSubdir = resolve(appDir, MANIFEST_DIR);\r\n const baseInApp = resolve(appDir, MANIFEST_FILE_NAMES.base);\r\n const baseInSub = resolve(manifestSubdir, MANIFEST_FILE_NAMES.base);\r\n const dir =\r\n existsSync(baseInApp)\r\n ? appDir\r\n : existsSync(baseInSub)\r\n ? manifestSubdir\r\n : null;\r\n if (dir !== null) {\r\n const files = this.loadFromDir(dir);\r\n if (this.hasAnyManifest(files)) {\r\n return validateAndReturn(this.buildConfigFromFiles(files));\r\n }\r\n }\r\n return null;\r\n }\r\n\r\n if (this.isManifestPathConfig(input)) {\r\n const result: ChromiumFirefoxManifest = {};\r\n if (input.chromium) {\r\n const obj = this.readManifestJson(resolve(appDir, input.chromium));\r\n if (obj) result.chromium = obj;\r\n }\r\n if (input.firefox) {\r\n const obj = this.readManifestJson(resolve(appDir, input.firefox));\r\n if (obj) result.firefox = obj;\r\n }\r\n const chrom = result.chromium ?? result.firefox;\r\n const ff = result.firefox ?? result.chromium;\r\n if (!chrom && !ff) return null;\r\n return validateAndReturn({ chromium: chrom ?? {}, firefox: ff ?? {} });\r\n }\r\n\r\n if (this.isChromiumFirefoxObject(input)) return validateAndReturn(input);\r\n return validateAndReturn(input);\r\n }\r\n}\r\n\r\nconst defaultLoader = new ManifestLoader();\r\n\r\n/**\r\n * Resolve user manifest (object / path / unset) into unified ManifestConfig (object form).\r\n * Path config is relative to appDir; when unset, reads manifest.json / manifest.chromium.json / manifest.firefox.json from appDir.\r\n */\r\nexport function resolveManifestInput(\r\n input: ManifestConfig | ManifestPathConfig | undefined,\r\n root: string,\r\n appDir: string\r\n): ManifestConfig | null {\r\n return defaultLoader.resolve(input, root, appDir);\r\n}\r\n\r\nfunction validateAndReturn(config: ManifestConfig | null): ManifestConfig | null {\r\n if (!config) return null;\r\n validateManifestSchema(config);\r\n return config;\r\n}\r\n\r\nfunction validateManifestSchema(config: ManifestConfig): void {\r\n if (isChromiumFirefoxObjectValue(config)) {\r\n if (config.chromium) validateManifestRecord(config.chromium, \"chromium\");\r\n if (config.firefox) validateManifestRecord(config.firefox, \"firefox\");\r\n return;\r\n }\r\n validateManifestRecord(config);\r\n}\r\n\r\nfunction isChromiumFirefoxObjectValue(m: ManifestConfig): m is ChromiumFirefoxManifest {\r\n return typeof m === \"object\" && m !== null && (\"chromium\" in m || \"firefox\" in m);\r\n}\r\n\r\nfunction validateManifestRecord(\r\n manifest: ManifestRecord,\r\n target?: ManifestValidationTarget\r\n): void {\r\n const mv = getManifestVersion(manifest);\r\n if (mv == null) throw new Error(\"manifest_version must be 2 or 3\");\r\n const errors =\r\n mv === 2 ? validateMv2(manifest) : validateMv3(manifest, target);\r\n if (errors.length > 0) throw new Error(errors.join(\"; \"));\r\n}\r\n\r\nfunction getManifestVersion(manifest: ManifestRecord): 2 | 3 | null {\r\n const mv = manifest.manifest_version;\r\n if (mv === 2 || mv === 3) return mv;\r\n return null;\r\n}\r\n\r\nfunction validateMv2(manifest: ManifestRecord): string[] {\r\n const errors: string[] = [];\r\n if (manifest.action != null) {\r\n errors.push(`MV2 does not support \"action\"; use \"browser_action\" or \"page_action\"`);\r\n }\r\n if (manifest.host_permissions != null) {\r\n errors.push(`MV2 does not support \"host_permissions\"; use \"permissions\"`);\r\n }\r\n errors.push(...validateBackgroundMv2(manifest.background));\r\n errors.push(...validatePermissionsList(manifest.permissions, \"permissions\"));\r\n return errors;\r\n}\r\n\r\nfunction validateMv3(\r\n manifest: ManifestRecord,\r\n target?: ManifestValidationTarget\r\n): string[] {\r\n const errors: string[] = [];\r\n if (manifest.browser_action != null || manifest.page_action != null) {\r\n errors.push(`MV3 does not support \"browser_action\" or \"page_action\"; use \"action\"`);\r\n }\r\n const bgErrors =\r\n target === \"firefox\"\r\n ? validateBackgroundMv3Firefox(manifest.background)\r\n : validateBackgroundMv3Chrome(manifest.background);\r\n errors.push(...bgErrors);\r\n errors.push(...validatePermissionsList(manifest.permissions, \"permissions\"));\r\n errors.push(...validatePermissionsList(manifest.host_permissions, \"host_permissions\"));\r\n errors.push(...validateAction(manifest.action));\r\n return errors;\r\n}\r\n\r\nfunction validateBackgroundMv2(background: unknown): string[] {\r\n const errors: string[] = [];\r\n if (!background) return errors;\r\n if (typeof background !== \"object\") {\r\n errors.push(`MV2 \"background\" must be an object`);\r\n return errors;\r\n }\r\n const bg = background as { service_worker?: unknown; scripts?: unknown; page?: unknown };\r\n if (bg.service_worker != null) {\r\n errors.push(`MV2 \"background.service_worker\" is not allowed`);\r\n }\r\n if (bg.scripts != null && !isStringArray(bg.scripts)) {\r\n errors.push(`MV2 \"background.scripts\" must be string[]`);\r\n }\r\n if (bg.page != null && typeof bg.page !== \"string\") {\r\n errors.push(`MV2 \"background.page\" must be a string`);\r\n }\r\n return errors;\r\n}\r\n\r\n/** Chrome MV3: only background.service_worker (string); scripts/page not supported. */\r\nfunction validateBackgroundMv3Chrome(background: unknown): string[] {\r\n const errors: string[] = [];\r\n if (!background) return errors;\r\n if (typeof background !== \"object\") {\r\n errors.push(`MV3 (Chrome) \"background\" must be an object`);\r\n return errors;\r\n }\r\n const bg = background as { service_worker?: unknown; scripts?: unknown; page?: unknown };\r\n if (bg.scripts != null) {\r\n errors.push(`MV3 (Chrome) \"background.scripts\" is not allowed; use \"service_worker\"`);\r\n }\r\n if (bg.page != null) {\r\n errors.push(`MV3 (Chrome) \"background.page\" is not allowed; use \"service_worker\"`);\r\n }\r\n if (bg.service_worker != null && typeof bg.service_worker !== \"string\") {\r\n errors.push(`MV3 (Chrome) \"background.service_worker\" must be a string`);\r\n }\r\n return errors;\r\n}\r\n\r\n/** Firefox MV3: background.scripts (string[]) or background.page (string); service_worker not supported by Firefox but allowed for cross-browser manifests. */\r\nfunction validateBackgroundMv3Firefox(background: unknown): string[] {\r\n const errors: string[] = [];\r\n if (!background) return errors;\r\n if (typeof background !== \"object\") {\r\n errors.push(`MV3 (Firefox) \"background\" must be an object`);\r\n return errors;\r\n }\r\n const bg = background as { service_worker?: unknown; scripts?: unknown; page?: unknown };\r\n const hasScripts = bg.scripts != null;\r\n const hasPage = bg.page != null;\r\n const hasServiceWorker = bg.service_worker != null;\r\n if (!hasScripts && !hasPage && !hasServiceWorker) {\r\n return errors;\r\n }\r\n if (hasScripts && !isStringArray(bg.scripts)) {\r\n errors.push(`MV3 (Firefox) \"background.scripts\" must be string[]`);\r\n }\r\n if (hasPage && typeof bg.page !== \"string\") {\r\n errors.push(`MV3 (Firefox) \"background.page\" must be a string`);\r\n }\r\n if (hasServiceWorker && typeof bg.service_worker !== \"string\") {\r\n errors.push(`MV3 (Firefox) \"background.service_worker\" must be a string when present`);\r\n }\r\n if (hasPage && hasScripts) {\r\n errors.push(`MV3 (Firefox) \"background\" cannot have both \"page\" and \"scripts\"`);\r\n }\r\n return errors;\r\n}\r\n\r\nfunction validateAction(action: unknown): string[] {\r\n if (action == null) return [];\r\n if (typeof action !== \"object\") return [`\"action\" must be an object`];\r\n const act = action as { default_popup?: unknown };\r\n if (act.default_popup != null && typeof act.default_popup !== \"string\") {\r\n return [`\"action.default_popup\" must be a string`];\r\n }\r\n return [];\r\n}\r\n\r\nfunction validatePermissionsList(value: unknown, key: string): string[] {\r\n if (value == null) return [];\r\n return isStringArray(value) ? [] : [`\"${key}\" must be string[]`];\r\n}\r\n\r\nfunction isStringArray(value: unknown): value is string[] {\r\n return Array.isArray(value) && value.every((item) => typeof item === \"string\");\r\n}\r\n","/**\r\n * Config loading - resolves addfox configuration\r\n */\r\n\r\nimport { createRequire } from \"module\";\r\nimport { resolve } from \"path\";\r\nimport { existsSync, statSync } from \"fs\";\r\nimport type { AddfoxUserConfig, AddfoxResolvedConfig, EntryInfo, ManifestRecord } from \"../types.ts\";\r\nimport {\r\n CONFIG_FILES,\r\n DEFAULT_OUT_DIR,\r\n DEFAULT_APP_DIR,\r\n DEFAULT_ENV_PREFIXES,\r\n ADDFOX_OUTPUT_ROOT,\r\n RSTEST_CONFIG_FILES,\r\n} from \"../constants.ts\";\r\nimport { AddfoxError, ADDFOX_ERROR_CODES } from \"@addfox/common\";\r\nimport { discoverEntries, type EntryDiscovererOptions } from \"../entry/discoverer.ts\";\r\nimport { resolveEntries, type EntryResolverOptions } from \"../entry/resolver.ts\";\r\nimport { resolveManifestInput } from \"../manifest/loader.ts\";\r\nimport { logDoneTimed, logEntriesTable } from \"@addfox/common\";\r\n\r\nexport interface ConfigResolutionResult {\r\n config: AddfoxResolvedConfig;\r\n baseEntries: EntryInfo[];\r\n entries: EntryInfo[];\r\n}\r\n\r\nexport interface ConfigLoaderOptions {\r\n configFiles?: readonly string[];\r\n entryDiscovererOptions?: EntryDiscovererOptions;\r\n entryResolverOptions?: EntryResolverOptions;\r\n}\r\n\r\nconst require = createRequire(\r\n typeof __filename !== \"undefined\" ? __filename : import.meta.url\r\n);\r\n\r\nfunction loadWithJiti(root: string, configPath: string): unknown {\r\n const isConfigRestart = process.env.ADDFOX_CONFIG_RESTART === \"1\";\r\n const jitiOptions: Record<string, unknown> = { esmResolve: true };\r\n \r\n if (isConfigRestart) {\r\n jitiOptions.moduleCache = false;\r\n jitiOptions.requireCache = false;\r\n }\r\n \r\n const jitiFn = require(\"jiti\")(root, jitiOptions) as (path: string) => unknown;\r\n return jitiFn(configPath);\r\n}\r\n\r\nfunction loadNativeJs(configPath: string): unknown {\r\n const mod = require(configPath) as { default?: unknown } | undefined;\r\n return mod?.default ?? mod;\r\n}\r\n\r\nfunction unwrapConfig(mod: unknown): AddfoxUserConfig {\r\n if (mod == null) return {} as AddfoxUserConfig;\r\n \r\n if (typeof mod === \"object\" && \"default\" in mod && mod.default !== undefined) {\r\n return (mod.default ?? {}) as AddfoxUserConfig;\r\n }\r\n \r\n return (mod ?? {}) as AddfoxUserConfig;\r\n}\r\n\r\nfunction loadConfigModule(root: string, configPath: string, file: string): AddfoxUserConfig {\r\n const isNativeJs = file.endsWith(\".js\") || file.endsWith(\".mjs\");\r\n \r\n if (isNativeJs) {\r\n try {\r\n return unwrapConfig(loadNativeJs(configPath));\r\n } catch {\r\n // Fall back to jiti for ESM .js or other edge cases\r\n }\r\n }\r\n \r\n return unwrapConfig(loadWithJiti(root, configPath));\r\n}\r\n\r\nfunction findConfigFile(root: string, configFiles: readonly string[]): string | null {\r\n for (const file of configFiles) {\r\n const p = resolve(root, file);\r\n if (existsSync(p)) return p;\r\n }\r\n return null;\r\n}\r\n\r\nfunction loadConfigAtPath(root: string, configPath: string, file: string): AddfoxUserConfig {\r\n try {\r\n return loadConfigModule(root, configPath, file);\r\n } catch (e) {\r\n const message = e instanceof Error ? e.message : String(e);\r\n throw new AddfoxError({\r\n code: ADDFOX_ERROR_CODES.CONFIG_LOAD_FAILED,\r\n message: \"Failed to load config file\",\r\n details: `File: ${configPath}, error: ${message}`,\r\n hint: \"Check addfox.config syntax and dependencies\",\r\n cause: e instanceof Error ? e : undefined,\r\n });\r\n }\r\n}\r\n\r\nexport function loadConfigFile(\r\n root: string,\r\n configFiles: readonly string[] = CONFIG_FILES\r\n): AddfoxUserConfig | null {\r\n for (const file of configFiles) {\r\n const p = resolve(root, file);\r\n if (!existsSync(p)) continue;\r\n return loadConfigAtPath(root, p, file);\r\n }\r\n return null;\r\n}\r\n\r\nexport function getResolvedConfigFilePath(\r\n root: string,\r\n configFiles: readonly string[] = CONFIG_FILES\r\n): string | null {\r\n return findConfigFile(root, configFiles);\r\n}\r\n\r\nfunction resolveAppDir(root: string, userConfig: AddfoxUserConfig): string {\r\n return resolve(root, userConfig.appDir ?? DEFAULT_APP_DIR);\r\n}\r\n\r\nfunction validateAppDir(appDir: string, entryDisabled: boolean): void {\r\n if (entryDisabled) return;\r\n if (!existsSync(appDir) || !statSync(appDir).isDirectory()) {\r\n throw new AddfoxError({\r\n code: ADDFOX_ERROR_CODES.APP_DIR_MISSING,\r\n message: \"App directory not found\",\r\n details: `Missing appDir: ${appDir}`,\r\n hint: \"Create the directory or set appDir to an existing folder (default is app/)\",\r\n });\r\n }\r\n}\r\n\r\nfunction createResolvedConfig(\r\n userConfig: AddfoxUserConfig,\r\n root: string,\r\n appDir: string,\r\n manifest: NonNullable<AddfoxResolvedConfig[\"manifest\"]>\r\n): AddfoxResolvedConfig {\r\n return {\r\n ...userConfig,\r\n manifest,\r\n appDir,\r\n outDir: userConfig.outDir ?? DEFAULT_OUT_DIR,\r\n envPrefix: userConfig.envPrefix ?? [...DEFAULT_ENV_PREFIXES],\r\n outputRoot: ADDFOX_OUTPUT_ROOT,\r\n root,\r\n };\r\n}\r\n\r\nfunction discoverAndResolveEntries(\r\n userConfig: AddfoxUserConfig,\r\n root: string,\r\n appDir: string,\r\n manifest: ManifestRecord | null,\r\n entryDiscovererOptions?: EntryDiscovererOptions,\r\n entryResolverOptions?: EntryResolverOptions\r\n): { baseEntries: EntryInfo[]; entries: EntryInfo[] } {\r\n const baseEntries = discoverEntries(appDir, entryDiscovererOptions);\r\n const result = resolveEntries(userConfig, root, appDir, manifest ?? undefined, entryResolverOptions);\r\n return { baseEntries, entries: result.entries };\r\n}\r\n\r\nexport function resolveAddfoxConfig(\r\n root: string,\r\n options: ConfigLoaderOptions = {}\r\n): ConfigResolutionResult {\r\n const t0 = performance.now();\r\n \r\n // Load config file\r\n const userConfig = loadConfigFile(root, options.configFiles);\r\n if (!userConfig) {\r\n throw new AddfoxError({\r\n code: ADDFOX_ERROR_CODES.CONFIG_NOT_FOUND,\r\n message: \"Addfox config file not found\",\r\n details: `No addfox.config.ts, addfox.config.js or addfox.config.mjs found under ${root}`,\r\n hint: \"Run the command from project root or create addfox.config.ts / addfox.config.js\",\r\n });\r\n }\r\n \r\n // Resolve paths\r\n const appDir = resolveAppDir(root, userConfig);\r\n const entryDisabled = userConfig.entry === false;\r\n \r\n // Validate\r\n validateAppDir(appDir, entryDisabled);\r\n \r\n // Resolve manifest\r\n const manifest = resolveManifestInput(userConfig.manifest, root, appDir);\r\n if (!manifest) {\r\n throw new AddfoxError({\r\n code: ADDFOX_ERROR_CODES.MANIFEST_MISSING,\r\n message: \"Manifest config or file not found\",\r\n details:\r\n \"Configure manifest in addfox.config, or place manifest.json / manifest.chromium.json / manifest.firefox.json under appDir or appDir/manifest\",\r\n hint:\r\n \"Option 1: manifest: { name, version, ... } in addfox.config; Option 2: manifest.json under appDir or appDir/manifest; Option 3: manifest: { chromium: 'path/to/manifest.json' } (path relative to appDir)\",\r\n });\r\n }\r\n \r\n // Create resolved config\r\n const config = createResolvedConfig(userConfig, root, appDir, manifest);\r\n \r\n // Discover and resolve entries\r\n // Extract the actual manifest record for the target browser (default to chromium)\r\n const manifestForEntry = typeof manifest === \"object\" && manifest !== null\r\n ? ((manifest as { chromium?: ManifestRecord; firefox?: ManifestRecord }).chromium ?? \r\n (manifest as { chromium?: ManifestRecord; firefox?: ManifestRecord }).firefox ?? \r\n manifest as ManifestRecord)\r\n : null;\r\n \r\n const { baseEntries, entries } = entryDisabled\r\n ? { baseEntries: [], entries: [] }\r\n : discoverAndResolveEntries(\r\n userConfig,\r\n root,\r\n appDir,\r\n manifestForEntry,\r\n options.entryDiscovererOptions,\r\n options.entryResolverOptions\r\n );\r\n \r\n if (!entryDisabled && entries.length === 0) {\r\n throw new AddfoxError({\r\n code: ADDFOX_ERROR_CODES.NO_ENTRIES,\r\n message: \"No entries discovered\",\r\n details: `No background, content, popup, options or sidepanel entry found under ${appDir}`,\r\n hint: \"At least one such directory with index.ts / index.js etc. is required\",\r\n });\r\n }\r\n \r\n // Log results\r\n logDoneTimed(\"Parse config\", Math.round(performance.now() - t0));\r\n logEntriesTable(entries, { root });\r\n \r\n return { config, baseEntries, entries };\r\n}\r\n\r\nexport function clearConfigCache(configFilePath: string): void {\r\n try {\r\n delete require.cache[configFilePath];\r\n } catch {\r\n // ignore\r\n }\r\n \r\n for (const key of Object.keys(require.cache)) {\r\n const mod = require.cache[key] as { filename?: string } | undefined;\r\n if (mod?.filename === configFilePath) {\r\n try {\r\n delete require.cache[key];\r\n } catch {\r\n // ignore\r\n }\r\n }\r\n }\r\n}\r\n\r\nexport function getResolvedRstestConfigFilePath(root: string): string | null {\r\n for (const file of RSTEST_CONFIG_FILES) {\r\n const p = resolve(root, file);\r\n if (existsSync(p)) return p;\r\n }\r\n return null;\r\n}\r\n","/**\r\n * Manifest builder - builds extension manifest for target browsers\r\n */\r\n\r\nimport type { ManifestConfig, ManifestRecord, ChromiumFirefoxManifest, EntryInfo } from \"../types.ts\";\r\nimport { basename, extname } from \"path\";\r\nimport { MANIFEST_ENTRY_PATHS, MANIFEST_ENTRY_KEYS, SCRIPT_ONLY_ENTRY_NAMES } from \"../constants.ts\";\r\nimport type { BrowserTarget } from \"../constants.ts\";\r\n\r\n/** Content script build output */\r\nexport interface ContentScriptOutput {\r\n js: string[];\r\n css: string[];\r\n autoFillCssInManifest?: boolean;\r\n}\r\n\r\ntype FillAction = (out: ManifestRecord, path: string) => void;\r\n\r\ntype ManifestPickerResult = { manifest: ManifestRecord; warnMessage?: string };\r\n\r\nconst ADDFOX_PLACEHOLDER_REGEX = /\\[addfox\\.([a-z]+)\\]/g;\r\nconst CONTENT_PLACEHOLDER = \"[addfox.content]\";\r\nconst CONTENT_PLACEHOLDER_LEGACY = \"[addfox.content]\";\r\nconst SCRIPT_KEYS_SET = new Set<string>(SCRIPT_ONLY_ENTRY_NAMES);\r\n\r\n/** Check if a path looks like a source file (not a build output) */\r\nfunction isSourceFilePath(path: string): boolean {\r\n const lower = path.trim().toLowerCase();\r\n return /\\.(ts|tsx|js|jsx)$/.test(lower);\r\n}\r\n\r\nfunction isChromiumFirefoxManifest(m: ManifestConfig): m is ChromiumFirefoxManifest {\r\n return typeof m === \"object\" && m !== null && (\"chromium\" in m || \"firefox\" in m);\r\n}\r\n\r\nfunction isEntryFieldEmpty(value: unknown): boolean {\r\n if (value === undefined || value === null) return true;\r\n if (typeof value === \"string\") return value.trim() === \"\";\r\n if (Array.isArray(value)) return value.length === 0;\r\n return false;\r\n}\r\n\r\nfunction hasNonEmptyStringArray(value: unknown): value is string[] {\r\n return Array.isArray(value) && value.length > 0;\r\n}\r\n\r\nfunction isManifestRecord(value: unknown): value is ManifestRecord {\r\n return value !== null && typeof value === \"object\" && !Array.isArray(value);\r\n}\r\n\r\nexport function getManifestRecordForTarget(config: ManifestConfig, target: BrowserTarget): ManifestRecord {\r\n return pickManifestForTarget(config, target).manifest;\r\n}\r\n\r\nfunction pickManifestForTarget(config: ManifestConfig, target: BrowserTarget): ManifestPickerResult {\r\n if (!isChromiumFirefoxManifest(config)) {\r\n return { manifest: config };\r\n }\r\n\r\n const hasChromium = config.chromium != null && typeof config.chromium === \"object\";\r\n const hasFirefox = config.firefox != null && typeof config.firefox === \"object\";\r\n\r\n // Both browsers defined\r\n if (hasChromium && hasFirefox) {\r\n const match = config[target];\r\n if (match != null && typeof match === \"object\") {\r\n return { manifest: match as ManifestRecord };\r\n }\r\n const fallback = (target === \"firefox\" ? config.chromium : config.firefox)!;\r\n return {\r\n manifest: fallback,\r\n warnMessage: `Build target is ${target} but manifest.${target} is missing; using ${target === \"firefox\" ? \"chromium\" : \"firefox\"} manifest.`,\r\n };\r\n }\r\n\r\n // Only Chromium\r\n if (hasChromium) {\r\n return {\r\n manifest: config.chromium!,\r\n warnMessage: target === \"firefox\" \r\n ? \"Build target is firefox but manifest only has chromium; using chromium manifest.\"\r\n : undefined,\r\n };\r\n }\r\n\r\n // Only Firefox\r\n if (hasFirefox) {\r\n return {\r\n manifest: config.firefox!,\r\n warnMessage: target === \"chromium\"\r\n ? \"Build target is chromium but manifest only has firefox; using firefox manifest.\"\r\n : undefined,\r\n };\r\n }\r\n\r\n // Fallback\r\n return {\r\n manifest: (config.chromium ?? config.firefox) ?? {},\r\n warnMessage: \"Manifest has no chromium or firefox object; using fallback.\",\r\n };\r\n}\r\n\r\nfunction buildScriptOutputPath(entry: EntryInfo): string {\r\n const scriptStem = basename(entry.scriptPath, extname(entry.scriptPath));\r\n return scriptStem === entry.name ? `${entry.name}.js` : `${entry.name}/index.js`;\r\n}\r\n\r\nfunction buildHtmlOutputPath(entry: EntryInfo, fallback: string): string {\r\n if (!entry.htmlPath) return fallback;\r\n const htmlFile = basename(entry.htmlPath).toLowerCase();\r\n return htmlFile === `${entry.name}.html` ? `${entry.name}.html` : fallback;\r\n}\r\n\r\nfunction buildPlaceholderMap(entries: EntryInfo[]): Record<string, string> {\r\n const map: Record<string, string> = {};\r\n for (const key of MANIFEST_ENTRY_KEYS) {\r\n const entry = entries.find((e) => e.name === key);\r\n if (!entry) continue;\r\n map[key] = SCRIPT_KEYS_SET.has(key)\r\n ? buildScriptOutputPath(entry)\r\n : buildHtmlOutputPath(entry, MANIFEST_ENTRY_PATHS[key]);\r\n }\r\n return map;\r\n}\r\n\r\n/**\r\n * Build a map from source file paths to output paths\r\n * This is used to replace source paths in manifest with build output paths\r\n */\r\nfunction buildSourceToOutputMap(entries: EntryInfo[]): Map<string, string> {\r\n const map = new Map<string, string>();\r\n const placeholderMap = buildPlaceholderMap(entries);\r\n \r\n for (const key of MANIFEST_ENTRY_KEYS) {\r\n const entry = entries.find((e) => e.name === key);\r\n if (!entry) continue;\r\n \r\n // Map the source path to the output path\r\n const sourcePath = entry.scriptPath;\r\n const outputPath = placeholderMap[key];\r\n \r\n if (sourcePath && outputPath) {\r\n // Store both full path and relative path variants\r\n map.set(sourcePath, outputPath);\r\n \r\n // Also store just the basename for matching\r\n const basename = sourcePath.split(/[\\\\/]/).pop();\r\n if (basename) {\r\n map.set(basename, outputPath);\r\n map.set(`./${basename}`, outputPath);\r\n }\r\n \r\n // Store the entry directory relative path\r\n const entryDir = key;\r\n const entryIndexPath = `${entryDir}/${basename}`;\r\n map.set(entryIndexPath, outputPath);\r\n map.set(`./${entryIndexPath}`, outputPath);\r\n }\r\n }\r\n \r\n return map;\r\n}\r\n\r\nfunction shouldUseServiceWorker(mv: 2 | 3, browser: BrowserTarget): boolean {\r\n return mv === 3 && browser === \"chromium\";\r\n}\r\n\r\nfunction isChromiumOnlyAutofillKey(key: string): boolean {\r\n return key === \"sidepanel\" || key === \"newtab\" || key === \"bookmarks\" || key === \"history\";\r\n}\r\n\r\nconst fillers: Record<string, (mv: 2 | 3, browser: BrowserTarget) => FillAction> = {\r\n background: (mv, browser) => (out, path) => {\r\n const bg = (out.background as Record<string, unknown>) ?? {};\r\n if (shouldUseServiceWorker(mv, browser)) {\r\n if (isEntryFieldEmpty((bg as { service_worker?: string }).service_worker)) {\r\n out.background = { ...bg, service_worker: path };\r\n }\r\n } else {\r\n const scripts = (bg as { scripts?: string[] }).scripts;\r\n if (!Array.isArray(scripts) || scripts.length === 0) {\r\n out.background = { ...bg, scripts: [path] };\r\n }\r\n }\r\n },\r\n\r\n popup: (mv) => (out, path) => {\r\n if (mv === 3) {\r\n const action = (out.action as Record<string, unknown>) ?? {};\r\n if (isEntryFieldEmpty((action as { default_popup?: string }).default_popup)) {\r\n out.action = { ...action, default_popup: path };\r\n }\r\n } else {\r\n const ba = (out.browser_action as Record<string, unknown>) ?? {};\r\n if (isEntryFieldEmpty((ba as { default_popup?: string }).default_popup)) {\r\n out.browser_action = { ...ba, default_popup: path };\r\n }\r\n }\r\n },\r\n\r\n options: (mv) => (out, path) => {\r\n if (mv === 3) {\r\n const opt = (out.options_ui as Record<string, unknown>) ?? {};\r\n if (isEntryFieldEmpty((opt as { page?: string }).page)) {\r\n out.options_ui = { ...opt, page: path };\r\n }\r\n } else if (isEntryFieldEmpty((out as { options_page?: string }).options_page)) {\r\n (out as Record<string, unknown>).options_page = path;\r\n }\r\n },\r\n\r\n devtools: () => (out, path) => {\r\n if (isEntryFieldEmpty((out as { devtools_page?: string }).devtools_page)) {\r\n (out as Record<string, unknown>).devtools_page = path;\r\n }\r\n },\r\n\r\n sandbox: () => (out, path) => {\r\n const sandbox = out.sandbox;\r\n if (sandbox === null || typeof sandbox !== \"object\" || Array.isArray(sandbox)) {\r\n out.sandbox = { pages: [path] };\r\n return;\r\n }\r\n const pages = (sandbox as { pages?: unknown }).pages;\r\n if (!Array.isArray(pages) || pages.length === 0) {\r\n out.sandbox = { ...sandbox, pages: [path] };\r\n }\r\n },\r\n\r\n content: () => (out, path) => {\r\n const cs = out.content_scripts;\r\n if (!Array.isArray(cs) || cs.length === 0) {\r\n out.content_scripts = [\r\n { matches: [\"<all_urls>\"], js: [path], run_at: \"document_idle\" },\r\n ] as ManifestRecord[\"content_scripts\"];\r\n }\r\n },\r\n\r\n newtab: () => (out, path) => {\r\n const overrides = (out.chrome_url_overrides as Record<string, unknown>) ?? {};\r\n if (isEntryFieldEmpty(overrides.newtab)) {\r\n out.chrome_url_overrides = { ...overrides, newtab: path };\r\n }\r\n },\r\n\r\n bookmarks: () => (out, path) => {\r\n const overrides = (out.chrome_url_overrides as Record<string, unknown>) ?? {};\r\n if (isEntryFieldEmpty(overrides.bookmarks)) {\r\n out.chrome_url_overrides = { ...overrides, bookmarks: path };\r\n }\r\n ensurePermission(out, \"bookmarks\");\r\n },\r\n\r\n history: () => (out, path) => {\r\n const overrides = (out.chrome_url_overrides as Record<string, unknown>) ?? {};\r\n if (isEntryFieldEmpty(overrides.history)) {\r\n out.chrome_url_overrides = { ...overrides, history: path };\r\n }\r\n ensurePermission(out, \"history\");\r\n },\r\n\r\n sidepanel: () => (out, path) => {\r\n const sp = (out.side_panel as Record<string, unknown>) ?? {};\r\n if (isEntryFieldEmpty((sp as { default_path?: string }).default_path)) {\r\n out.side_panel = { ...sp, default_path: path };\r\n }\r\n },\r\n};\r\n\r\nfunction ensurePermission(out: ManifestRecord, permission: string): void {\r\n const current = out.permissions;\r\n if (!Array.isArray(current)) {\r\n out.permissions = [permission];\r\n return;\r\n }\r\n if (!current.includes(permission)) {\r\n out.permissions = [...current, permission];\r\n }\r\n}\r\n\r\nfunction buildAutoFillers(mv: 2 | 3, browser: BrowserTarget): Record<string, FillAction> {\r\n const result: Record<string, FillAction> = {};\r\n for (const [key, factory] of Object.entries(fillers)) {\r\n if (key === \"sidepanel\" && mv !== 3) continue;\r\n if (browser === \"firefox\" && isChromiumOnlyAutofillKey(key)) continue;\r\n result[key] = factory(mv, browser);\r\n }\r\n return result;\r\n}\r\n\r\nfunction needsSidePanelPermission(\r\n out: ManifestRecord,\r\n placeholderMap: Record<string, string>,\r\n browser: BrowserTarget\r\n): boolean {\r\n if (browser !== \"chromium\") return false;\r\n if (placeholderMap.sidepanel != null) return true;\r\n const sp = out.side_panel;\r\n if (sp == null || typeof sp !== \"object\" || Array.isArray(sp)) return false;\r\n const path = (sp as { default_path?: string }).default_path;\r\n return typeof path === \"string\" && path.trim() !== \"\";\r\n}\r\n\r\nfunction autoFillEntryFields(\r\n manifest: ManifestRecord,\r\n placeholderMap: Record<string, string>,\r\n browser: BrowserTarget\r\n): ManifestRecord {\r\n const mv = manifest.manifest_version === 2 ? 2 : 3;\r\n const out: ManifestRecord = { ...manifest };\r\n const autoFillers = buildAutoFillers(mv, browser);\r\n\r\n for (const [key, path] of Object.entries(placeholderMap)) {\r\n autoFillers[key]?.(out, path);\r\n }\r\n\r\n if (mv === 3 && needsSidePanelPermission(out, placeholderMap, browser)) {\r\n ensurePermission(out, \"sidePanel\");\r\n }\r\n\r\n return out;\r\n}\r\n\r\nfunction replacePlaceholderInString(str: string, placeholderMap: Record<string, string>): string {\r\n return str.replace(ADDFOX_PLACEHOLDER_REGEX, (_, key: string) =>\r\n key in placeholderMap ? placeholderMap[key] : `[addfox.${key}]`\r\n );\r\n}\r\n\r\nfunction replacePlaceholdersInValue(value: unknown, placeholderMap: Record<string, string>): unknown {\r\n if (typeof value === \"string\") {\r\n return replacePlaceholderInString(value, placeholderMap);\r\n }\r\n if (Array.isArray(value)) {\r\n return value.map((item) => replacePlaceholdersInValue(item, placeholderMap));\r\n }\r\n if (value !== null && typeof value === \"object\") {\r\n const out: ManifestRecord = {};\r\n for (const [k, v] of Object.entries(value)) {\r\n out[k] = replacePlaceholdersInValue(v, placeholderMap);\r\n }\r\n return out;\r\n }\r\n return value;\r\n}\r\n\r\n/**\r\n * Replace source file paths in manifest with build output paths\r\n * This handles the case where users specify source paths like \"./background.ts\" in manifest\r\n */\r\nfunction replaceSourcePathsWithOutput(\r\n value: unknown,\r\n sourceToOutputMap: Map<string, string>\r\n): unknown {\r\n if (typeof value === \"string\") {\r\n // Check if this is a source file path that needs replacement\r\n if (isSourceFilePath(value)) {\r\n // Try exact match\r\n const outputPath = sourceToOutputMap.get(value);\r\n if (outputPath) return outputPath;\r\n \r\n // Try matching basename\r\n const basename = value.split(/[\\\\/]/).pop();\r\n if (basename) {\r\n const fromBasename = sourceToOutputMap.get(basename);\r\n if (fromBasename) return fromBasename;\r\n \r\n const fromDotSlash = sourceToOutputMap.get(`./${basename}`);\r\n if (fromDotSlash) return fromDotSlash;\r\n }\r\n }\r\n return value;\r\n }\r\n \r\n if (Array.isArray(value)) {\r\n return value.map((item) => replaceSourcePathsWithOutput(item, sourceToOutputMap));\r\n }\r\n \r\n if (value !== null && typeof value === \"object\") {\r\n const out: ManifestRecord = {};\r\n for (const [k, v] of Object.entries(value)) {\r\n out[k] = replaceSourcePathsWithOutput(v, sourceToOutputMap);\r\n }\r\n return out;\r\n }\r\n \r\n return value;\r\n}\r\n\r\nfunction resolveContentScriptsPlaceholders(\r\n manifest: ManifestRecord,\r\n placeholderMap: Record<string, string>,\r\n contentScriptOutput?: ContentScriptOutput\r\n): ManifestRecord {\r\n const contentScripts = manifest.content_scripts;\r\n if (!Array.isArray(contentScripts)) return manifest;\r\n\r\n const defaultContentJs = placeholderMap.content ? [placeholderMap.content] : [];\r\n const shouldAutoFillCss = contentScriptOutput?.autoFillCssInManifest !== false;\r\n\r\n const resolved = contentScripts.map((item: unknown) => {\r\n if (item === null || typeof item !== \"object\" || Array.isArray(item)) return item;\r\n \r\n const obj = item as Record<string, unknown>;\r\n const out: Record<string, unknown> = { ...obj };\r\n\r\n // Resolve JS placeholders\r\n if (Array.isArray(obj.js)) {\r\n const jsReplacement = contentScriptOutput?.js ?? defaultContentJs;\r\n out.js = (obj.js as unknown[]).flatMap((el) =>\r\n (el === CONTENT_PLACEHOLDER || el === CONTENT_PLACEHOLDER_LEGACY) ? jsReplacement : [el]\r\n );\r\n }\r\n\r\n // Resolve CSS placeholders\r\n if (Array.isArray(obj.css)) {\r\n const cssReplacement = contentScriptOutput?.css ?? [];\r\n const resolvedCss = (obj.css as unknown[]).flatMap((el) =>\r\n (el === CONTENT_PLACEHOLDER || el === CONTENT_PLACEHOLDER_LEGACY) ? cssReplacement : [el]\r\n );\r\n if (resolvedCss.length > 0) out.css = resolvedCss;\r\n else delete out.css;\r\n }\r\n\r\n // Inject default JS if needed\r\n const hadJs = hasNonEmptyStringArray(out.js);\r\n const hadCss = hasNonEmptyStringArray(out.css);\r\n if (!hadJs && !hadCss && placeholderMap.content) {\r\n out.js = contentScriptOutput?.js ?? defaultContentJs;\r\n }\r\n\r\n // Auto-fill CSS\r\n const hasJs = hasNonEmptyStringArray(out.js);\r\n const isContentItem = hasJs &&\r\n placeholderMap.content != null &&\r\n (out.js as string[]).includes(placeholderMap.content);\r\n \r\n if (shouldAutoFillCss && isContentItem && contentScriptOutput?.css?.length && !hasNonEmptyStringArray(out.css)) {\r\n out.css = contentScriptOutput.css;\r\n }\r\n\r\n return out;\r\n });\r\n\r\n return { ...manifest, content_scripts: resolved };\r\n}\r\n\r\n/**\r\n * Replace source file paths in content_scripts with output paths\r\n */\r\nfunction replaceContentScriptSourcePaths(\r\n manifest: ManifestRecord,\r\n sourceToOutputMap: Map<string, string>\r\n): ManifestRecord {\r\n const contentScripts = manifest.content_scripts;\r\n if (!Array.isArray(contentScripts)) return manifest;\r\n\r\n const resolved = contentScripts.map((item: unknown) => {\r\n if (item === null || typeof item !== \"object\" || Array.isArray(item)) return item;\r\n \r\n const obj = item as Record<string, unknown>;\r\n const out: Record<string, unknown> = { ...obj };\r\n\r\n // Replace source paths in js array\r\n if (Array.isArray(obj.js)) {\r\n out.js = (obj.js as string[]).map((path) => {\r\n if (typeof path === \"string\" && isSourceFilePath(path)) {\r\n const outputPath = sourceToOutputMap.get(path);\r\n if (outputPath) return outputPath;\r\n \r\n // Try basename match\r\n const basename = path.split(/[\\\\/]/).pop();\r\n if (basename) {\r\n const fromBasename = sourceToOutputMap.get(basename);\r\n if (fromBasename) return fromBasename;\r\n }\r\n }\r\n return path;\r\n });\r\n }\r\n\r\n return out;\r\n });\r\n\r\n return { ...manifest, content_scripts: resolved };\r\n}\r\n\r\nfunction buildManifest(\r\n manifest: ManifestRecord,\r\n entries: EntryInfo[],\r\n browser: BrowserTarget,\r\n contentScriptOutput?: ContentScriptOutput\r\n): ManifestRecord {\r\n const placeholderMap = buildPlaceholderMap(entries);\r\n const sourceToOutputMap = buildSourceToOutputMap(entries);\r\n \r\n const pipeline = [\r\n // Step 1: Auto-fill empty entry fields\r\n (m: ManifestRecord) => autoFillEntryFields(m, placeholderMap, browser),\r\n // Step 2: Replace [addfox.xxx] placeholders\r\n (m: ManifestRecord) => resolveContentScriptsPlaceholders(m, placeholderMap, contentScriptOutput),\r\n // Step 3: Replace source file paths with output paths\r\n (m: ManifestRecord) => replaceSourcePathsWithOutput(m, sourceToOutputMap) as ManifestRecord,\r\n // Step 4: Handle content_scripts source path replacement specifically\r\n (m: ManifestRecord) => replaceContentScriptSourcePaths(m, sourceToOutputMap),\r\n // Step 5: Legacy placeholder replacement (for backward compatibility)\r\n (m: ManifestRecord) => replacePlaceholdersInValue(m, placeholderMap) as ManifestRecord,\r\n ];\r\n\r\n const result = pipeline.reduce((acc, fn) => fn(acc) as ManifestRecord, { ...manifest });\r\n \r\n return isManifestRecord(result) ? result : manifest;\r\n}\r\n\r\nexport function buildForBrowser(\r\n config: ManifestConfig,\r\n entries: EntryInfo[],\r\n browser: BrowserTarget,\r\n onWarn?: (message: string) => void,\r\n contentScriptOutput?: ContentScriptOutput\r\n): ManifestRecord {\r\n const { manifest, warnMessage } = pickManifestForTarget(config, browser);\r\n if (warnMessage) onWarn?.(warnMessage);\r\n return buildManifest(manifest, entries, browser, contentScriptOutput);\r\n}\r\n\r\nexport function resolveManifestChromium(\r\n config: ManifestConfig,\r\n entries: EntryInfo[]\r\n): ManifestRecord {\r\n return buildForBrowser(config, entries, \"chromium\");\r\n}\r\n\r\nexport function resolveManifestFirefox(\r\n config: ManifestConfig,\r\n entries: EntryInfo[]\r\n): ManifestRecord {\r\n return buildForBrowser(config, entries, \"firefox\");\r\n}\r\n\r\nexport function resolveManifestForTarget(\r\n config: ManifestConfig,\r\n entries: EntryInfo[],\r\n target: BrowserTarget,\r\n onWarn?: (message: string) => void,\r\n contentScriptOutput?: ContentScriptOutput\r\n): ManifestRecord {\r\n return buildForBrowser(config, entries, target, onWarn, contentScriptOutput);\r\n}\r\n","/**\r\n * Reload manager helpers: map entries to ReloadManagerEntry for HMR plugin.\r\n */\r\n\r\nimport { resolve } from \"path\";\r\nimport type { EntryInfo, ReloadManagerEntry } from \"./types.js\";\r\nimport { RELOAD_MANAGER_ENTRY_NAMES } from \"./constants.js\";\r\n\r\n/**\r\n * Build reloadManagerEntries from pipeline entries (filter + resolve path).\r\n * Used by CLI when building HMR plugin options.\r\n */\r\nexport function toReloadManagerEntries(\r\n entries: EntryInfo[],\r\n root: string\r\n): ReloadManagerEntry[] {\r\n return entries\r\n .filter((e) => RELOAD_MANAGER_ENTRY_NAMES.has(e.name))\r\n .map((e) => ({ name: e.name, path: resolve(root, e.scriptPath) }));\r\n}\r\n","import { createRequire } from \"node:module\";\r\nimport { existsSync } from \"node:fs\";\r\nimport { resolve, dirname } from \"node:path\";\r\nimport { fileURLToPath } from \"node:url\";\r\n\r\nconst require = createRequire(import.meta.url);\r\n\r\n/**\r\n * Find package.json by checking multiple possible locations.\r\n * - From dist/esm: ../../package.json\r\n * - From src: ../package.json\r\n */\r\nfunction findPackageJson(): { version?: string } {\r\n const __dirname = dirname(fileURLToPath(import.meta.url));\r\n \r\n // Try dist/esm location first\r\n const distPath = resolve(__dirname, \"../../package.json\");\r\n if (existsSync(distPath)) {\r\n return require(distPath);\r\n }\r\n \r\n // Try src location (for tests)\r\n const srcPath = resolve(__dirname, \"../package.json\");\r\n if (existsSync(srcPath)) {\r\n return require(srcPath);\r\n }\r\n \r\n // Fallback\r\n return {};\r\n}\r\n\r\nconst pkg = findPackageJson();\r\n\r\n/**\r\n * Current addfox (core) version, e.g. for extension error reports.\r\n */\r\nexport function getAddfoxVersion(): string {\r\n return pkg?.version ?? \"0.0.0\";\r\n}\r\n","/**\r\n * Detect front-end framework from project package.json (dependencies / devDependencies).\r\n * Used for debug error output; falls back to Vanilla when none detected.\r\n */\r\n\r\nimport { existsSync, readFileSync } from \"node:fs\";\r\nimport { join } from \"node:path\";\r\n\r\nexport type FrontendFramework =\r\n | \"Vanilla\"\r\n | \"React\"\r\n | \"Vue\"\r\n | \"Preact\"\r\n | \"Svelte\"\r\n | \"Solid\";\r\n\r\nconst FRAMEWORK_KEYS: { pkg: string; name: FrontendFramework }[] = [\r\n { pkg: \"solid-js\", name: \"Solid\" },\r\n { pkg: \"svelte\", name: \"Svelte\" },\r\n { pkg: \"vue\", name: \"Vue\" },\r\n { pkg: \"preact\", name: \"Preact\" },\r\n { pkg: \"react\", name: \"React\" },\r\n];\r\n\r\nfunction readPackageJson(root: string): Record<string, unknown> | null {\r\n const path = join(root, \"package.json\");\r\n if (!existsSync(path)) return null;\r\n try {\r\n const raw = readFileSync(path, \"utf-8\");\r\n return JSON.parse(raw) as Record<string, unknown>;\r\n } catch {\r\n return null;\r\n }\r\n}\r\n\r\nfunction hasDep(pkg: Record<string, unknown>, key: string): boolean {\r\n const deps = pkg.dependencies as Record<string, string> | undefined;\r\n const devDeps = pkg.devDependencies as Record<string, string> | undefined;\r\n if (deps && typeof deps[key] === \"string\") return true;\r\n if (devDeps && typeof devDeps[key] === \"string\") return true;\r\n return false;\r\n}\r\n\r\n/**\r\n * Detect front-end framework from project root package.json.\r\n * Checks dependencies/devDependencies for solid-js, svelte, vue, preact, react (first match wins).\r\n * Returns \"Vanilla\" when root is empty, package.json missing, or no framework detected.\r\n */\r\nexport function detectFrontendFramework(root: string): FrontendFramework {\r\n if (!root || typeof root !== \"string\") return \"Vanilla\";\r\n const pkg = readPackageJson(root);\r\n if (!pkg) return \"Vanilla\";\r\n for (const { pkg: key, name } of FRAMEWORK_KEYS) {\r\n if (hasDep(pkg, key)) return name;\r\n }\r\n return \"Vanilla\";\r\n}\r\n"],"names":["defineConfig","config","CONFIG_FILES","SCRIPT_EXTS","RESERVED_ENTRY_NAMES","HTML_ENTRY_NAMES","SCRIPT_ONLY_ENTRY_NAMES","RELOAD_MANAGER_ENTRY_NAMES","Set","ADDFOX_OUTPUT_ROOT","DEFAULT_OUT_DIR","DEFAULT_ENV_PREFIXES","DEFAULT_BROWSER","SUPPORTED_BROWSERS","BROWSER_OUTPUT_PREFIX","getBrowserOutputDir","browser","SUPPORTED_LAUNCH_TARGETS","CLI_COMMANDS","RSTEST_CONFIG_FILES","MANIFEST_DIR","MANIFEST_FILE_NAMES","MANIFEST_ENTRY_PATHS","MANIFEST_ENTRY_KEYS","Object","isScriptSrcRelative","src","t","ENTRY_SCRIPT_REGEX","HEAD_CLOSE_REGEX","SCRIPT_WITH_SRC_REGEX","findFirstScriptWithRelativeSrc","html","reg","RegExp","match","parseAddfoxEntryFromHtml","htmlPath","raw","readFileSync","tag","tagStartIndex","srcMatch","headCloseMatch","headCloseIndex","inject","strippedHtml","fallback","getScriptInjectIfMatches","scriptPath","parsed","resolvedFromHtml","resolve","dirname","undefined","resolveScriptFromHtmlStrict","Error","JSON","existsSync","readDirContents","dir","entries","readdirSync","e","findScriptInDir","scriptExts","contents","ext","findScriptInDirFromContents","dirPath","findNamedScript","baseDir","name","baseContents","p","findNamedHtml","isValidScriptExt","pathStr","lower","resolveScriptFromHtmlWithInjectStrict","resolved","AddfoxError","ADDFOX_ERROR_CODES","tryResolveEntryFromHtml","String","buildHtmlEntryInfo","conventionalScriptPath","fromHtml","discoverScriptOnlyEntry","options","singleScript","discoverHtmlEntryFromFlat","singleHtml","conventional","discoverHtmlEntryFromDir","subContents","discoverHtmlEntry","discoverEntriesInternal","entry","createOptions","discoverEntries","getHtmlEntryNames","getScriptOnlyEntryNames","getAllEntryNames","isSourceFilePath","path","inferEntryNameFromPath","cleanPath","firstSegment","extractServiceWorker","manifest","bg","serviceWorker","entryName","scripts","Array","firstScript","page","extractPopup","mv","popupPath","manifestPath","action","defaultPopup","browserAction","extractOptions","optionsPath","optionsUi","optionsPage","extractDevtools","devtoolsPage","extractSidepanel","sidePanel","defaultPath","extractSandbox","sandbox","pages","firstPage","extractOverrides","overrides","overrideKeys","key","extractContentScripts","contentScripts","i","cs","js","j","extractEntriesFromManifest","replacementMap","Map","extractors","extractor","result","HTML_ENTRY_SET","isHtmlPath","isScriptPath","findScriptForHtmlDir","htmlFilename","stem","basename","isEntryConfigObject","value","resolveHtmlPath","htmlValue","resolveHtmlFlag","hasTemplate","isHtmlEntryName","enrichEntryWithScriptInject","scriptInject","inferHtmlPathForReservedName","resolveEntryFromObject","inferredHtml","Boolean","resolveEntryFromHtml","resolveEntryFromScript","resolveSingleEntry","resolveEntries","_root","defaultEntries","entryMap","manifestReplacementMap","entryConfig","hasExplicitEntryConfig","manifestResult","ManifestLoader","filePath","data","m","c","isChromiumFirefoxObjectValue","base","override","out","b","o","basePath","chromPath","firefoxPath","files","chromium","firefox","input","root","appDir","manifestSubdir","baseInApp","baseInSub","validateAndReturn","obj","chrom","ff","defaultLoader","resolveManifestInput","validateManifestSchema","validateManifestRecord","target","getManifestVersion","errors","validateMv2","validateMv3","validateBackgroundMv2","validatePermissionsList","bgErrors","validateBackgroundMv3Firefox","validateBackgroundMv3Chrome","validateAction","background","isStringArray","hasScripts","hasPage","hasServiceWorker","act","item","require","createRequire","__filename","loadWithJiti","configPath","isConfigRestart","process","jitiOptions","jitiFn","loadNativeJs","mod","unwrapConfig","loadConfigModule","file","isNativeJs","findConfigFile","configFiles","loadConfigAtPath","message","loadConfigFile","getResolvedConfigFilePath","resolveAppDir","userConfig","DEFAULT_APP_DIR","validateAppDir","entryDisabled","statSync","createResolvedConfig","discoverAndResolveEntries","entryDiscovererOptions","entryResolverOptions","baseEntries","resolveAddfoxConfig","t0","performance","manifestForEntry","logDoneTimed","Math","logEntriesTable","clearConfigCache","configFilePath","getResolvedRstestConfigFilePath","ADDFOX_PLACEHOLDER_REGEX","CONTENT_PLACEHOLDER","CONTENT_PLACEHOLDER_LEGACY","SCRIPT_KEYS_SET","isChromiumFirefoxManifest","isEntryFieldEmpty","hasNonEmptyStringArray","isManifestRecord","getManifestRecordForTarget","pickManifestForTarget","hasChromium","hasFirefox","buildScriptOutputPath","scriptStem","extname","buildHtmlOutputPath","htmlFile","buildPlaceholderMap","map","buildSourceToOutputMap","placeholderMap","sourcePath","outputPath","entryDir","entryIndexPath","shouldUseServiceWorker","isChromiumOnlyAutofillKey","fillers","ba","opt","ensurePermission","sp","permission","current","buildAutoFillers","factory","needsSidePanelPermission","autoFillEntryFields","autoFillers","replacePlaceholderInString","str","_","replacePlaceholdersInValue","k","v","replaceSourcePathsWithOutput","sourceToOutputMap","fromBasename","fromDotSlash","resolveContentScriptsPlaceholders","contentScriptOutput","defaultContentJs","shouldAutoFillCss","jsReplacement","el","cssReplacement","resolvedCss","hadJs","hadCss","hasJs","isContentItem","replaceContentScriptSourcePaths","buildManifest","pipeline","acc","fn","buildForBrowser","onWarn","warnMessage","resolveManifestChromium","resolveManifestFirefox","resolveManifestForTarget","toReloadManagerEntries","findPackageJson","__dirname","fileURLToPath","distPath","srcPath","pkg","getAddfoxVersion","FRAMEWORK_KEYS","readPackageJson","join","hasDep","deps","devDeps","detectFrontendFramework"],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Manifest builder - builds extension manifest for target browsers
3
+ */
4
+ import type { ManifestConfig, ManifestRecord, EntryInfo } from "../types.ts";
5
+ import type { BrowserTarget } from "../constants.ts";
6
+ /** Content script build output */
7
+ export interface ContentScriptOutput {
8
+ js: string[];
9
+ css: string[];
10
+ autoFillCssInManifest?: boolean;
11
+ }
12
+ export declare function getManifestRecordForTarget(config: ManifestConfig, target: BrowserTarget): ManifestRecord;
13
+ export declare function buildForBrowser(config: ManifestConfig, entries: EntryInfo[], browser: BrowserTarget, onWarn?: (message: string) => void, contentScriptOutput?: ContentScriptOutput): ManifestRecord;
14
+ export declare function resolveManifestChromium(config: ManifestConfig, entries: EntryInfo[]): ManifestRecord;
15
+ export declare function resolveManifestFirefox(config: ManifestConfig, entries: EntryInfo[]): ManifestRecord;
16
+ export declare function resolveManifestForTarget(config: ManifestConfig, entries: EntryInfo[], target: BrowserTarget, onWarn?: (message: string) => void, contentScriptOutput?: ContentScriptOutput): ManifestRecord;
@@ -0,0 +1,9 @@
1
+ /**
2
+ * @addfox/core/manifest
3
+ *
4
+ * Manifest loading and building
5
+ */
6
+ export { buildForBrowser, resolveManifestChromium, resolveManifestFirefox, resolveManifestForTarget, getManifestRecordForTarget, } from "./builder.ts";
7
+ export type { ContentScriptOutput } from "./builder.ts";
8
+ export { resolveManifestInput, ManifestLoader, } from "./loader.ts";
9
+ export type { ManifestValidationTarget } from "./loader.ts";
@@ -0,0 +1,26 @@
1
+ import type { ManifestConfig, ManifestPathConfig } from "../types.ts";
2
+ import type { BrowserTarget } from "../constants.ts";
3
+ /** Target for manifest validation: use browser-specific rules (e.g. Firefox MV3 allows background.scripts). */
4
+ export type ManifestValidationTarget = Extract<BrowserTarget, "chromium" | "firefox">;
5
+ /**
6
+ * Manifest loader: reads manifest from appDir or resolves manifest object/path config from addfox.config.
7
+ */
8
+ export declare class ManifestLoader {
9
+ private readManifestJson;
10
+ private isManifestPathConfig;
11
+ private isChromiumFirefoxObject;
12
+ private deepMerge;
13
+ private loadFromDir;
14
+ private hasAnyManifest;
15
+ private buildConfigFromFiles;
16
+ /**
17
+ * Resolve user manifest (object / path / unset) into unified ManifestConfig (object form).
18
+ * Priority: addfox.config manifest > files directly in appDir > files in appDir/manifest/.
19
+ */
20
+ resolve(input: ManifestConfig | ManifestPathConfig | undefined, root: string, appDir: string): ManifestConfig | null;
21
+ }
22
+ /**
23
+ * Resolve user manifest (object / path / unset) into unified ManifestConfig (object form).
24
+ * Path config is relative to appDir; when unset, reads manifest.json / manifest.chromium.json / manifest.firefox.json from appDir.
25
+ */
26
+ export declare function resolveManifestInput(input: ManifestConfig | ManifestPathConfig | undefined, root: string, appDir: string): ManifestConfig | null;
@@ -0,0 +1,18 @@
1
+ import type { HookManager } from '@addfox/common';
2
+ import type { PipelineContext } from './types.js';
3
+ /**
4
+ * Pipeline - orchestrates build flow with hook points
5
+ * Uses external HookManager for hook storage/execution
6
+ */
7
+ export declare class Pipeline {
8
+ private hooks;
9
+ constructor(hooks: HookManager<Record<string, PipelineContext>>);
10
+ /**
11
+ * Execute the full pipeline flow
12
+ */
13
+ execute(root: string, argv: string[]): Promise<PipelineContext>;
14
+ /**
15
+ * Run before/after hooks for a stage
16
+ */
17
+ private runStage;
18
+ }
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Pipeline system for Addfox build process
3
+ */
4
+ export { Pipeline } from './Pipeline.js';
5
+ export type { PipelineContext, PipelineStage, PipelineHook } from './types.js';
@@ -0,0 +1 @@
1
+ export { Pipeline } from "../434.js";
@@ -0,0 +1,26 @@
1
+ import type { RsbuildConfig } from '@rsbuild/core';
2
+ import type { BrowserTarget, CliCommand } from '../constants.js';
3
+ import type { AddfoxResolvedConfig, EntryInfo } from '../types.js';
4
+ /**
5
+ * Pipeline context passed through all stages
6
+ */
7
+ export interface PipelineContext {
8
+ root: string;
9
+ command: CliCommand;
10
+ browser: BrowserTarget;
11
+ cache?: boolean;
12
+ report?: boolean | Record<string, unknown>;
13
+ config: AddfoxResolvedConfig;
14
+ baseEntries: EntryInfo[];
15
+ entries: EntryInfo[];
16
+ rsbuild: RsbuildConfig;
17
+ isDev: boolean;
18
+ distPath: string;
19
+ argv?: string[];
20
+ }
21
+ /**
22
+ * Pipeline stage names
23
+ */
24
+ export type PipelineStage = 'init' | 'options' | 'parse' | 'load' | 'resolve' | 'prepare' | 'build' | 'complete';
25
+ /** Hook function type for pipeline */
26
+ export type PipelineHook = (ctx: PipelineContext) => void | Promise<void>;
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Reload manager helpers: map entries to ReloadManagerEntry for HMR plugin.
3
+ */
4
+ import type { EntryInfo, ReloadManagerEntry } from "./types.js";
5
+ /**
6
+ * Build reloadManagerEntries from pipeline entries (filter + resolve path).
7
+ * Used by CLI when building HMR plugin options.
8
+ */
9
+ export declare function toReloadManagerEntries(entries: EntryInfo[], root: string): ReloadManagerEntry[];