@bf6mods/cli 1.6.0 → 1.7.0
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.
- package/README.md +9 -51
- package/dist/cli/index.js +215 -20
- package/dist/cli/index.js.map +1 -1
- package/dist/{puppeteer-u5zMrFnK.js → puppeteer-BzRJX4NM.js} +72 -48
- package/dist/puppeteer-BzRJX4NM.js.map +1 -0
- package/dist/resources/prepare/types/config.ts +17 -0
- package/dist/resources/templates/All/README.md +22 -0
- package/dist/resources/templates/All/placeholder.jpg +0 -0
- package/dist/resources/templates/Basic/bf6.config.ts +1 -0
- package/dist/resources/templates/Complete/bf6.config.ts +1 -0
- package/package.json +2 -1
- package/dist/puppeteer-u5zMrFnK.js.map +0 -1
- package/dist/resources/templates/BombSquad.json +0 -1
package/dist/cli/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["program","key:\n\t\t\t\t\t\t\t| string\n\t\t\t\t\t\t\t| number\n\t\t\t\t\t\t\t| bigint\n\t\t\t\t\t\t\t| boolean\n\t\t\t\t\t\t\t| RegExp\n\t\t\t\t\t\t\t| null\n\t\t\t\t\t\t\t| undefined","MapIdEnum","tsAttachment: Attachment | undefined","__filename","__dirname","attachments: Attachment[]","mapRotation: MapType[]","mapId: MapIdEnum","scene: string","finalJson: ConfigType","puppeteer: PuppeteerImport","id: string | undefined","owned","watcher: FSWatcher | undefined","timer: NodeJS.Timeout | undefined","targets: string[]","config","logger: Bf6Logger | undefined","bf6CliPackageJson.version","bf6SdkPackageJson.version","path","overwrite: \"yes\" | \"no\" | \"ignore\" | undefined","template","MapIdEnum","typescriptFile: string | undefined","stringsFile: string | undefined","scenes: [string, string][]","promises: Promise<unknown>[]","ext: string","path","__filename","__dirname","pkg.bin","pkg.description","pkg.version"],"sources":["../../package.json","../../src/resources/prepare/types/config.ts","../../src/cli/utils.ts","../../src/cli/build/generated-strings.ts","../../src/cli/build/index.ts","../../src/cli/deploy/authenticate.ts","../../src/cli/deploy/index.ts","../../src/cli/log.ts","../../src/cli/dev.ts","../../../sdk/package.json","../../src/cli/init.ts","../../src/cli/import.ts","../../src/cli/prepare.ts","../../src/cli/index.ts"],"sourcesContent":["{\n\t\"name\": \"@bf6mods/cli\",\n\t\"version\": \"1.6.0\",\n\t\"description\": \"CLI and library for bundling BF6 mods\",\n\t\"license\": \"MIT\",\n\t\"type\": \"module\",\n\t\"bin\": {\n\t\t\"bf6mods\": \"./dist/cli/index.js\"\n\t},\n\t\"main\": \"./dist/index.js\",\n\t\"types\": \"./dist/index.d.ts\",\n\t\"scripts\": {\n\t\t\"build\": \"tsdown\",\n\t\t\"start\": \"cross-env EXIT_CODE=none tsx ./src/cli/index.ts\"\n\t},\n\t\"exports\": {\n\t\t\".\": {\n\t\t\t\"types\": \"./dist/index.d.ts\",\n\t\t\t\"import\": \"./dist/index.js\"\n\t\t}\n\t},\n\t\"files\": [\n\t\t\"dist/\"\n\t],\n\t\"repository\": {\n\t\t\"type\": \"git\",\n\t\t\"url\": \"git+https://github.com/bf6mods/bf6mods.git\"\n\t},\n\t\"dependencies\": {\n\t\t\"@bf6mods/portal\": \"*\",\n\t\t\"@bf6mods/sdk\": \"*\",\n\t\t\"@clack/prompts\": \"^0.11.0\",\n\t\t\"chokidar\": \"^4.0.3\",\n\t\t\"colors\": \"^1.4.0\",\n\t\t\"commander\": \"^14.0.1\",\n\t\t\"import-global\": \"^1.1.1\",\n\t\t\"jiti\": \"^2.6.1\",\n\t\t\"keytar\": \"^7.9.0\",\n\t\t\"knitwork\": \"^1.2.0\",\n\t\t\"rolldown\": \"^1.0.0-beta.44\",\n\t\t\"stringify-object\": \"^6.0.0\",\n\t\t\"strip-ansi\": \"^7.1.2\"\n\t},\n\t\"publishConfig\": {\n\t\t\"access\": \"public\"\n\t},\n\t\"devDependencies\": {\n\t\t\"@oxc-project/types\": \"^0.95.0\",\n\t\t\"@types/stringify-object\": \"^4.0.5\",\n\t\t\"cross-env\": \"^10.1.0\",\n\t\t\"execa\": \"^9.6.0\",\n\t\t\"puppeteer\": \"^24.27.0\",\n\t\t\"tsx\": \"^4.20.6\"\n\t}\n}\n","import type { ConfigType } from \"@bf6mods/sdk\";\n\nexport enum MapId {\n\tSiegeOfCairo = \"MP_Abbasid-ModBuilderCustom0\",\n\tEmpireState = \"MP_Aftermath-ModBuilderCustom0\",\n\tBlackwellFields = \"MP_Badlands-ModBuilderCustom0\",\n\tIberianOffensive = \"MP_Battery-ModBuilderCustom0\",\n\tLiberationPeak = \"MP_Capstone-ModBuilderCustom0\",\n\tManhattanBridge = \"MP_Dumbo-ModBuilderCustom0\",\n\tEastwoord = \"MP_Eastwood-ModBuilderCustom0\",\n\tFireStorm = \"MP_FireStorm-ModBuilderCustom0\",\n\tSaintsQuarter = \"MP_Limestone-ModBuilderCustom0\",\n\tNewSobekCity = \"MP_Outskirts-ModBuilderCustom0\",\n\tMirakValley = \"MP_Tungsten-ModBuilderCustom0\",\n\tGolfCourse = \"MP_Granite_ClubHouse_Portal-ModBuilderCustom0\",\n\tDefenseNexus = \"MP_Granite_TechCampus_Portal-ModBuilderCustom0\",\n\tPortalSandbox = \"MP_Portal_Sand-ModBuilderCustom0\",\n\tMarina = \"MP_Granite_Marina_Portal-ModBuilderCustom0\",\n\tDowntown = \"MP_Granite_MainStreet_Portal-ModBuilderCustom0\",\n\tArea22B = \"MP_Granite_MilitaryRnD_Portal-ModBuilderCustom0\",\n\tRedlineStorage = \"MP_Granite_MilitaryStorage_Portal-ModBuilderCustom0\",\n}\n\n/**\n * Represents the root configuration for a Battlefield 6 mod project.\n *\n * This file combines both build-level settings (like entrypoints and output directories)\n * and in-game configuration data (such as mutators and asset restrictions)\n * under the `game` key.\n *\n * Use {@link defineBf6Config} to define and validate this structure\n * in your `bf6.config.ts` file.\n */\nexport type Bf6Config = {\n\t/**\n\t * The unique identifier of your mod experience.\n\t *\n\t * You can find this ID in the URL when editing your experience:\n\t * [https://portal.battlefield.com/bf6/experience/settings/mode?id=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx](https://portal.battlefield.com/bf6/experience/settings/mode?id=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)\n\t *\n\t * This ID is referenced when deploying your mod using:\n\t * npx \\@bf6mods/cli deploy\n\t */\n\tid?: string;\n\n\t/**\n\t * The human-readable name of the mod.\n\t *\n\t * Typically matches the project name used in the BF6 mod editor or\n\t * the display name shown in the in-game mod browser.\n\t */\n\tname: string;\n\n\t/**\n\t * A short description of the mod’s purpose or content.\n\t * Used for display and metadata purposes.\n\t */\n\tdescription: string;\n\n\t/**\n\t * The output directory where compiled or bundled files are written.\n\t * Usually something like `\"dist\"` or `\"build\"`.\n\t */\n\toutDir: string;\n\n\t/**\n\t * Whether or not to output the built files like the entrypoint typescript file\n\t */\n\toutputArtifacts?: boolean;\n\n\t/**\n\t * The main entrypoint for your mod’s TypeScript source file.\n\t *\n\t * This is typically something like `\"src/index.ts\"` or `\"src/main.ts\"`.\n\t */\n\tentrypoint?: string;\n\n\t/**\n\t * One or more scene file paths (.json) that the mod includes.\n\t * If no file path is provided, it loads in the default spatial data.\n\t */\n\tscenes?: ([MapId, string] | MapId)[];\n\n\t/**\n\t * Path to a JSON file or other source that defines localized strings\n\t * used by the mod (optional).\n\t */\n\tstrings?: string;\n\n\t/**\n\t * Generate strings automatically, by default this is enabled\n\t */\n\tgenerateStrings?: boolean;\n\n\t/**\n\t * Controls whether build output should be minified.\n\t *\n\t * Can be a boolean (to toggle all minification),\n\t * or an object specifying independent settings for JS and JSON files.\n\t *\n\t * @example\n\t * ```ts\n\t * minify: true\n\t * // or\n\t * minify: { js: true, json: false }\n\t * ```\n\t */\n\tminify?:\n\t\t| {\n\t\t\t\t/** Whether to minify JavaScript output. */\n\t\t\t\tjs?: boolean;\n\t\t\t\t/** Whether to minify JSON output. */\n\t\t\t\tjson?: boolean;\n\t\t }\n\t\t/** Enables or disables all minification. */\n\t\t| boolean;\n\n\t/**\n\t * The underlying in-game configuration derived from `ConfigType`\n\t * in the BF6 SDK. Includes gameplay-level details like mutators,\n\t * asset restrictions, and team compositions.\n\t *\n\t * The following properties are **excluded**:\n\t * - `attachments`\n\t * - `workspace`\n\t * - `mapRotation`\n\t * - `name`\n\t * - `description`\n\t *\n\t * since those are either redundant or handled elsewhere.\n\t */\n\tgame: Omit<\n\t\tConfigType,\n\t\t\"attachments\" | \"workspace\" | \"mapRotation\" | \"name\" | \"description\"\n\t>;\n};\n\n/**\n * Defines and validates a Battlefield 6 mod configuration object.\n *\n * This helper ensures your config is properly typed and can be\n * statically analyzed by TypeScript.\n *\n * @example\n * ```ts\n * export default defineBf6Config({\n * name: \"My Custom Mod\",\n * description: \"Adds custom rules\",\n * outDir: \"dist\",\n * entrypoint: \"src/main.ts\",\n * game: {\n * mutators: [],\n * assetRestrictions: {},\n * teamComposition: [],\n * },\n * });\n * ```\n *\n * @param bf6Config The configuration object to validate and return.\n * @returns The validated Battlefield 6 configuration object.\n */\nexport function defineBf6Config(bf6Config: Bf6Config): Bf6Config {\n\treturn bf6Config;\n}\n","import colors from \"colors\";\nimport stripAnsi from \"strip-ansi\";\n\n/**\n * Safely prints a message with a right-aligned timestamp.\n */\nexport const printToConsole = (message: string, error: boolean = false) => {\n\tconst now = new Date();\n\tconst formattedTime = colors.grey(now.toLocaleTimeString());\n\tconst terminalWidth = process.stdout.columns || 80;\n\n\tconst timeLength = stripAnsi(formattedTime).length;\n\tconst messageLength = stripAnsi(message).length;\n\tconst available = terminalWidth - (messageLength + timeLength);\n\n\tconst spacing = available > 1 ? \" \".repeat(available) : \" \";\n\n\tif (error) console.error(`${message}${spacing}${formattedTime}`);\n\telse console.log(`${message}${spacing}${formattedTime}`);\n};\n\nexport const readableList = (initialValues: readonly string[]) => {\n\tconst values = initialValues.map((v) => `\"${v}\"`);\n\tif (values.length > 1)\n\t\treturn `${values.slice(0, -1).join(\", \")} or ${values.slice(-1)}`;\n\treturn values[0];\n};\n","import type { Node, VariableDeclarator } from \"@oxc-project/types\";\nimport colors from \"colors\";\nimport type { Plugin } from \"rolldown\";\n\nexport function extractBf6Strings(\n\tbf6Strings: Record<string, string>,\n\tgenerateFromLiterals: boolean,\n): Plugin {\n\treturn {\n\t\tname: \"extract-bf6-strings\",\n\t\tgenerateBundle(_options, bundle) {\n\t\t\tif (!generateFromLiterals) return;\n\n\t\t\tlet id = 0;\n\t\t\tconst existingStrings = new Set(Object.values(bf6Strings));\n\n\t\t\tfor (const [_file, output] of Object.entries(bundle)) {\n\t\t\t\tif (output.type !== \"chunk\") continue;\n\t\t\t\tconst code = output.code;\n\n\t\t\t\t// Parse the code with rolldown’s parser\n\t\t\t\tconst program = this.parse(code, {\n\t\t\t\t\tlang: \"ts\",\n\t\t\t\t\tastType: \"js\",\n\t\t\t\t\trange: true,\n\t\t\t\t});\n\n\t\t\t\t// Visit every node recursively to collect string literals\n\t\t\t\tfunction walk(node: Node) {\n\t\t\t\t\tif (node.type === \"Literal\") {\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\ttypeof node.value !== \"string\" ||\n\t\t\t\t\t\t\tnode.value === \"\" ||\n\t\t\t\t\t\t\tnode.value === \"----uniquename----\"\n\t\t\t\t\t\t)\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t!(node.value in bf6Strings) &&\n\t\t\t\t\t\t\t!existingStrings.has(node.value)\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\texistingStrings.add(node.value);\n\t\t\t\t\t\t\tbf6Strings[`__auto__${id++}`] = node.value;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tfor (const value of Object.values(node)) {\n\t\t\t\t\t\tif (!value) continue;\n\t\t\t\t\t\tif (Array.isArray(value)) {\n\t\t\t\t\t\t\tfor (const v of value) {\n\t\t\t\t\t\t\t\tif (v && typeof v === \"object\" && \"type\" in v) walk(v as Node);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else if (typeof value === \"object\" && \"type\" in value) {\n\t\t\t\t\t\t\twalk(value as Node);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tfor (const item of program.body) {\n\t\t\t\t\twalk(item);\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tmoduleParsed(moduleInfo) {\n\t\t\tif (moduleInfo.code && moduleInfo.exports.includes(\"bf6Strings\")) {\n\t\t\t\tconst code = moduleInfo.code;\n\t\t\t\tconst getSnippet = (\n\t\t\t\t\tstart: number,\n\t\t\t\t\tend: number,\n\t\t\t\t\tlinesBefore = 2,\n\t\t\t\t\tlinesAfter = 2,\n\t\t\t\t) => {\n\t\t\t\t\tconst lines = code.split(/\\r?\\n/);\n\t\t\t\t\tconst startLine = Math.max(\n\t\t\t\t\t\t0,\n\t\t\t\t\t\tcode.slice(0, start).split(/\\r?\\n/).length - 1 - linesBefore,\n\t\t\t\t\t);\n\t\t\t\t\tconst endLine = Math.min(\n\t\t\t\t\t\tlines.length,\n\t\t\t\t\t\tcode.slice(0, end).split(/\\r?\\n/).length - 1 + linesAfter,\n\t\t\t\t\t);\n\t\t\t\t\treturn lines\n\t\t\t\t\t\t.slice(startLine, endLine)\n\t\t\t\t\t\t.map((line, i) => {\n\t\t\t\t\t\t\tconst actualLine = startLine + i + 1;\n\t\t\t\t\t\t\treturn `${actualLine.toString().padStart(3)} | ${line}`;\n\t\t\t\t\t\t})\n\t\t\t\t\t\t.join(\"\\n\");\n\t\t\t\t};\n\n\t\t\t\tconst program = this.parse(code, {\n\t\t\t\t\tlang: \"ts\",\n\t\t\t\t\tastType: \"js\",\n\t\t\t\t\trange: true,\n\t\t\t\t});\n\n\t\t\t\tconst extractObjectLiteral = (declaration: VariableDeclarator) => {\n\t\t\t\t\tif (declaration.init?.type !== \"ObjectExpression\") {\n\t\t\t\t\t\tconst snippet = getSnippet(...(declaration.range ?? [0, 0]));\n\t\t\t\t\t\tthis.error(\n\t\t\t\t\t\t\t`${colors.red.bold(\"✗\")} Invalid bf6Strings export: expected an object literal.\\n\\n${snippet}`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\n\t\t\t\t\tfor (const property of declaration.init.properties) {\n\t\t\t\t\t\tif (property.type !== \"Property\") {\n\t\t\t\t\t\t\tconst snippet = getSnippet(...(property.range ?? [0, 0]));\n\t\t\t\t\t\t\tthis.error(\n\t\t\t\t\t\t\t\t`${colors.red.bold(\"✗\")} Invalid bf6Strings property: expected a key/value pair.\\nFound type: ${property.type}\\n\\n${snippet}`,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tlet key:\n\t\t\t\t\t\t\t| string\n\t\t\t\t\t\t\t| number\n\t\t\t\t\t\t\t| bigint\n\t\t\t\t\t\t\t| boolean\n\t\t\t\t\t\t\t| RegExp\n\t\t\t\t\t\t\t| null\n\t\t\t\t\t\t\t| undefined;\n\t\t\t\t\t\tif (property.key.type === \"Literal\") {\n\t\t\t\t\t\t\tkey = property.key.value;\n\t\t\t\t\t\t} else if (property.key.type === \"Identifier\") {\n\t\t\t\t\t\t\tkey = property.key.name;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tconst snippet = getSnippet(...(property.range ?? [0, 0]));\n\t\t\t\t\t\t\tthis.error(\n\t\t\t\t\t\t\t\t`${colors.red.bold(\"✗\")} Invalid bf6Strings key: expected a string literal or identifier.\\nFound type: ${property.key.type}\\n\\n${snippet}`,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (property.value.type !== \"Literal\") {\n\t\t\t\t\t\t\tconst snippet = getSnippet(...(property.range ?? [0, 0]));\n\t\t\t\t\t\t\tthis.error(\n\t\t\t\t\t\t\t\t`${colors.red.bold(\"✗\")} Invalid bf6Strings value: expected a string literal.\\nFound type: ${property.value.type}\\n\\n${snippet}`,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst value = property.value.value;\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\ttypeof key !== \"string\" &&\n\t\t\t\t\t\t\ttypeof key !== \"number\" &&\n\t\t\t\t\t\t\ttypeof key !== \"bigint\" &&\n\t\t\t\t\t\t\ttypeof key !== \"boolean\"\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\tconst snippet = getSnippet(...(property.range ?? [0, 0]));\n\t\t\t\t\t\t\tthis.error(\n\t\t\t\t\t\t\t\t`${colors.red.bold(\"✗\")} bf6Strings key must be a string, found: ${typeof key}\\n\\n${snippet}`,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\ttypeof value !== \"string\" &&\n\t\t\t\t\t\t\ttypeof value !== \"number\" &&\n\t\t\t\t\t\t\ttypeof value !== \"bigint\" &&\n\t\t\t\t\t\t\ttypeof value !== \"boolean\"\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\tconst snippet = getSnippet(...(property.range ?? [0, 0]));\n\t\t\t\t\t\t\tthis.error(\n\t\t\t\t\t\t\t\t`${colors.red.bold(\"✗\")} bf6Strings value must be a string, found: ${typeof value}\\n\\n${snippet}`,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tbf6Strings[`${key}`] = `${value}`;\n\t\t\t\t\t}\n\t\t\t\t};\n\n\t\t\t\tfor (const item of program.body) {\n\t\t\t\t\t// Case 1: plain variable `var bf6Strings = {...}`\n\t\t\t\t\tif (item.type === \"VariableDeclaration\") {\n\t\t\t\t\t\tfor (const declaration of item.declarations) {\n\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\tdeclaration.type === \"VariableDeclarator\" &&\n\t\t\t\t\t\t\t\tdeclaration.id.type === \"Identifier\" &&\n\t\t\t\t\t\t\t\tdeclaration.id.name === \"bf6Strings\"\n\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\textractObjectLiteral(declaration);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Case 2: exported variable `export const bf6Strings = {...}`\n\t\t\t\t\tif (\n\t\t\t\t\t\titem.type === \"ExportNamedDeclaration\" &&\n\t\t\t\t\t\titem.declaration?.type === \"VariableDeclaration\"\n\t\t\t\t\t) {\n\t\t\t\t\t\tfor (const declaration of item.declaration.declarations) {\n\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\tdeclaration.type === \"VariableDeclarator\" &&\n\t\t\t\t\t\t\t\tdeclaration.id.type === \"Identifier\" &&\n\t\t\t\t\t\t\t\tdeclaration.id.name === \"bf6Strings\"\n\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\textractObjectLiteral(declaration);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t};\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport {\n\ttype Attachment,\n\tAttachmentType,\n\ttype ConfigType,\n\ttype MapType,\n} from \"@bf6mods/sdk\";\nimport colors from \"colors\";\nimport { createJiti } from \"jiti\";\nimport { rolldown } from \"rolldown\";\nimport {\n\ttype Bf6Config,\n\tMapId as MapIdEnum,\n} from \"../../resources/prepare/types/config.ts\";\nimport { printToConsole } from \"../utils.ts\";\nimport { extractBf6Strings } from \"./generated-strings.ts\";\n\ndeclare global {\n\tvar defineBf6Config: ((config: Bf6Config) => Bf6Config) | undefined;\n\tvar MapId: typeof MapIdEnum | undefined;\n}\n\n/**\n * Dynamically imports and validates bf6.config.ts\n */\nexport async function getBf6Config(\n\trootDir: string,\n): Promise<Bf6Config | undefined> {\n\ttry {\n\t\tglobalThis.defineBf6Config = (c) => c;\n\t\tglobalThis.MapId = MapIdEnum;\n\t\tconst jiti = createJiti(rootDir, { interopDefault: true });\n\t\tconst result = await jiti.import(\"./bf6.config\", { default: true });\n\t\tdelete globalThis.defineBf6Config;\n\t\tdelete globalThis.MapId;\n\t\treturn result as Bf6Config;\n\t} catch (_error) {\n\t\treturn;\n\t}\n}\n\n/**\n * Builds the entire mod project once (for production or single run).\n */\nexport async function build() {\n\tconst workingDir = path.resolve(\".\");\n\tconst config = await getBf6Config(workingDir);\n\tif (!config) throw new Error(\"Cannot find bf6.config.ts!\");\n\n\tconst outDir = path.resolve(workingDir, config.outDir);\n\tif (fs.existsSync(outDir))\n\t\tfs.rmSync(outDir, { recursive: true, force: true });\n\tfs.mkdirSync(outDir, { recursive: true });\n\n\tconst minifyJson =\n\t\ttypeof config.minify === \"boolean\"\n\t\t\t? config.minify\n\t\t\t: (config.minify?.json ?? false);\n\n\tconst generatedStrings = {};\n\tlet tsAttachment: Attachment | undefined;\n\tif (config.entrypoint) {\n\t\tconst entryAbs = path.resolve(workingDir, config.entrypoint);\n\t\tconst compiled = await buildEntrypoint(\n\t\t\tentryAbs,\n\t\t\tgeneratedStrings,\n\t\t\tconfig.generateStrings ?? true,\n\t\t);\n\t\ttsAttachment = createTsAttachment(entryAbs, compiled);\n\t}\n\n\tconst { attachments, mapRotation } = await collectAttachments(\n\t\tconfig,\n\t\tworkingDir,\n\t\ttsAttachment,\n\t\tgeneratedStrings,\n\t);\n\n\tawait writeModJson(config, outDir, attachments, mapRotation, minifyJson);\n\tprintToConsole(`${colors.green.bold(\"✓\")} Built mod: ${config.name}`);\n}\n\n/**\n * Compiles the TypeScript entrypoint using rolldown and returns the compiled code.\n */\nexport async function buildEntrypoint(\n\tentry: string,\n\tbf6Strings: Record<string, string>,\n\tgenerateStringsFromLiterals: boolean,\n): Promise<string> {\n\tconst bundle = await rolldown({\n\t\tinput: entry,\n\t\tplugins: [extractBf6Strings(bf6Strings, generateStringsFromLiterals)],\n\t\tlogLevel: \"debug\",\n\t\tresolve: {\n\t\t\talias: {\n\t\t\t\tmodlib: \"@bf6mods/sdk\",\n\t\t\t},\n\t\t},\n\t});\n\tconst result = await bundle.generate({\n\t\tformat: \"esm\",\n\t\tinlineDynamicImports: true,\n\t});\n\n\tconst code = result.output[0].code;\n\treturn code;\n}\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\nconst spatialsDir = path.resolve(__dirname, \"../resources/maps/spatial\");\n/**\n * Collects all attachments (TS, scenes, strings) and returns them + mapRotation.\n */\nexport async function collectAttachments(\n\tconfig: Bf6Config,\n\tworkingDir: string,\n\ttsAttachment: Attachment | undefined,\n\tgeneratedStrings: Record<string, number | string> | undefined,\n) {\n\tconst attachments: Attachment[] = [];\n\tconst mapRotation: MapType[] = [];\n\n\tif (tsAttachment) attachments.push(tsAttachment);\n\n\t// Strings\n\tif (config.strings || Object.keys(generatedStrings ?? {}).length > 0) {\n\t\tconst strPath = path.resolve(workingDir, config.strings ?? \"strings.json\");\n\t\tlet raw = \"{}\";\n\t\tif (fs.existsSync(strPath)) {\n\t\t\traw = await fs.promises.readFile(strPath, \"utf8\");\n\t\t} else {\n\t\t\t// Create a placeholder for clarity (optional)\n\t\t\tprintToConsole(\n\t\t\t\tcolors.yellow(\n\t\t\t\t\t`⚠️ No strings.json found, generating from literals only.`,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\n\t\tconst attachment = createStringsAttachment(strPath, raw, generatedStrings);\n\t\tattachments.push(attachment);\n\t}\n\n\t// Scenes\n\tif (config.scenes) {\n\t\tlet mapIdx = 0;\n\t\tfor (const map of config.scenes) {\n\t\t\tlet mapId: MapIdEnum;\n\t\t\tlet scene: string;\n\t\t\tif (Array.isArray(map)) {\n\t\t\t\t[mapId, scene] = map;\n\t\t\t} else {\n\t\t\t\tmapId = map;\n\t\t\t\tscene = path.resolve(spatialsDir, `${mapId}.spatial.json`);\n\t\t\t}\n\n\t\t\tconst scenePath = path.resolve(workingDir, scene);\n\t\t\tif (!fs.existsSync(scenePath))\n\t\t\t\tthrow new Error(`Cannot find spatial data file: ${scene}`);\n\t\t\tconst raw = await fs.promises.readFile(scenePath, \"utf8\");\n\t\t\tconst spatial = createSpatialAttachment(scenePath, raw, mapIdx++);\n\t\t\tattachments.push(spatial);\n\t\t\tmapRotation.push({ id: mapId, spatialAttachment: spatial });\n\t\t}\n\t}\n\n\treturn { attachments, mapRotation };\n}\n\n/**\n * Writes the mod.json output to disk.\n */\nexport async function writeModJson(\n\tconfig: Bf6Config,\n\toutDir: string,\n\tattachments: ConfigType[\"attachments\"],\n\tmapRotation: MapType[],\n\tminify: boolean,\n) {\n\tconst baseGame = config.game;\n\tconst finalJson: ConfigType = {\n\t\tname: config.name,\n\t\tdescription: config.description,\n\t\tgameMode: \"ModBuilderCustom\",\n\t\tmutators: baseGame.mutators ?? {},\n\t\tassetRestrictions: baseGame.assetRestrictions ?? {},\n\t\tteamComposition: baseGame.teamComposition ?? [],\n\t\tmapRotation,\n\t\tattachments,\n\t};\n\n\tconst jsonOutput = minify\n\t\t? JSON.stringify(finalJson)\n\t\t: JSON.stringify(finalJson, null, 2);\n\tawait fs.promises.writeFile(path.resolve(outDir, \"mod.json\"), jsonOutput);\n\n\tif (config.outputArtifacts && finalJson?.attachments) {\n\t\tfor (const attachment of finalJson.attachments) {\n\t\t\tconst attachmentsDir = path.resolve(outDir, \"attachments\");\n\t\t\tif (!fs.existsSync(attachmentsDir))\n\t\t\t\tfs.mkdirSync(attachmentsDir, {\n\t\t\t\t\trecursive: true,\n\t\t\t\t});\n\t\t\tawait fs.promises.writeFile(\n\t\t\t\tpath.resolve(outDir, \"attachments\", attachment.filename),\n\t\t\t\tatob(attachment.attachmentData.original),\n\t\t\t);\n\t\t}\n\t}\n}\n\nexport function createTsAttachment(\n\tfilePath: string,\n\tcompiled: string,\n): Attachment {\n\treturn {\n\t\tid: crypto.randomUUID(),\n\t\tversion: \"1.0\",\n\t\tfilename: `${path.parse(filePath).name}.js`,\n\t\tisProcessable: true,\n\t\tprocessingStatus: 2,\n\t\tattachmentType: AttachmentType.TypeScript,\n\t\tattachmentData: { original: toBase64(compiled), compiled: \"\" },\n\t\terrors: [],\n\t};\n}\n\nexport function createStringsAttachment(\n\tfilePath: string,\n\traw: string,\n\tgeneratedStrings?: Record<string, number | string> | undefined,\n): Attachment {\n\tlet result = raw;\n\tif (generatedStrings) {\n\t\tresult = JSON.stringify(\n\t\t\t{\n\t\t\t\t...generatedStrings,\n\t\t\t\t...JSON.parse(raw),\n\t\t\t},\n\t\t\tnull,\n\t\t\t4,\n\t\t);\n\t}\n\n\treturn {\n\t\tid: crypto.randomUUID(),\n\t\tversion: \"1.0\",\n\t\tfilename: path.basename(filePath),\n\t\tisProcessable: true,\n\t\tprocessingStatus: 2,\n\t\tattachmentType: AttachmentType.Strings,\n\t\tattachmentData: { original: toBase64(result), compiled: \"\" },\n\t\terrors: [],\n\t};\n}\n\nexport function createSpatialAttachment(\n\tfilePath: string,\n\traw: string,\n\tmapIdx: number,\n): MapType[\"spatialAttachment\"] {\n\treturn {\n\t\tid: crypto.randomUUID(),\n\t\tversion: \"1.0\",\n\t\tfilename: path.basename(filePath),\n\t\tisProcessable: true,\n\t\tprocessingStatus: 2,\n\t\tattachmentType: AttachmentType.SpatialData,\n\t\tattachmentData: { original: toBase64(raw), compiled: \"\" },\n\t\tmetadata: `mapIdx=${mapIdx}`,\n\t\terrors: [],\n\t};\n}\n\nexport function toBase64(input: string | Buffer): string {\n\treturn Buffer.isBuffer(input)\n\t\t? input.toString(\"base64\")\n\t\t: Buffer.from(input, \"utf8\").toString(\"base64\");\n}\n","import os from \"node:os\";\nimport path from \"node:path\";\nimport colors from \"colors\";\nimport keytar from \"keytar\";\nimport { printToConsole } from \"../utils.ts\";\nimport { clients } from \"./index.ts\";\n\nexport type PuppeteerImport = typeof import(\"puppeteer\");\n\nexport async function getSessionIdFromCookies() {\n\tlet puppeteer: PuppeteerImport;\n\ttry {\n\t\tpuppeteer = (await import(\"puppeteer\")) as unknown as PuppeteerImport;\n\t} catch (_error) {\n\t\tprintToConsole(`${colors.red.bold(\"✗\")} Puppeteer could not be loaded.`);\n\t\tconsole.error(\n\t\t\t\"It looks like Puppeteer is not installed in this environment.\",\n\t\t);\n\t\tconsole.error(\n\t\t\t`${colors.green.bold(\"✓\")} Fix: install Puppeteer locally in the CLI package:`,\n\t\t);\n\t\tconsole.error(\"\t npm i -g puppeteer\");\n\t\tconsole.error(\"\\nIf you prefer not to install a browser automation tool,\");\n\t\tconsole.error(\n\t\t\t\"you can instead provide an auth code using the --auth-code option:\",\n\t\t);\n\t\tconsole.error(\"\t bf6mods deploy <input> --auth-code=<code>\\n\");\n\t\tprocess.exit(0);\n\t}\n\n\tconst profileDir = path.join(os.homedir(), \".bf6mods-browser\");\n\n\tconst browser = await puppeteer.launch({\n\t\theadless: false,\n\t\tdefaultViewport: null,\n\t\tuserDataDir: profileDir,\n\t});\n\tconst page = await browser.newPage();\n\tawait page.goto(\"https://portal.battlefield.com/bf6/experiences\");\n\tconsole.log(\"Please log in to Battlefield Portal if needed...\");\n\n\t// Poll for bf6sessionId cookie\n\tawait page.waitForFunction(\n\t\t() => {\n\t\t\treturn document.cookie.includes(\"bf6sessionId\");\n\t\t},\n\t\t{ timeout: 0 },\n\t); // no timeout, wait as long as needed\n\n\tconsole.log(`${colors.green.bold(\"✓\")} Login detected!`);\n\n\tconst cookies = await page.cookies();\n\tawait browser.close();\n\n\treturn cookies.find((cookie) => cookie.name === \"bf6sessionId\")?.value;\n}\n\nexport async function tryAuthenticateWithSessionId(sessionId: string) {\n\tawait clients.authenticate({\n\t\tsessionId,\n\t});\n\n\ttry {\n\t\tawait clients.play.getProgressionTypes({});\n\t} catch (error) {\n\t\tif (!(error instanceof Error)) return false;\n\t\tif (error.message === \"[unauthenticated]\") return false;\n\t}\n\n\treturn true;\n}\n\nexport async function authenticate(sessionIdParam?: string) {\n\tprintToConsole(`🔑 Attempting authentication…`);\n\n\tif (sessionIdParam) {\n\t\tif (await tryAuthenticateWithSessionId(sessionIdParam)) {\n\t\t\tawait keytar.setPassword(\"bf6mods\", \"sessionId\", sessionIdParam);\n\t\t\treturn true;\n\t\t}\n\t\tprintToConsole(\n\t\t\t`${colors.red(\"✗\")} Provided sessionId is invalid, ignoring…`,\n\t\t);\n\t}\n\n\tconst storedSessionId = await keytar.getPassword(\"bf6mods\", \"sessionId\");\n\tif (storedSessionId) {\n\t\tif (await tryAuthenticateWithSessionId(storedSessionId)) {\n\t\t\treturn true;\n\t\t}\n\t\tprintToConsole(`${colors.yellow(\"⚠\")} Stored sessionId expired, removing…`);\n\t\tawait keytar.deletePassword(\"bf6mods\", \"sessionId\");\n\t}\n\n\tprintToConsole(`🌐 Launching browser to authenticate…`);\n\tconst cookieSessionId = await getSessionIdFromCookies();\n\n\tif (!cookieSessionId) {\n\t\tprintToConsole(\n\t\t\t`${colors.red(\"✗\")} Failed to retrieve Battlefield session, exiting.`,\n\t\t\ttrue,\n\t\t);\n\t\treturn false;\n\t}\n\n\tif (await tryAuthenticateWithSessionId(cookieSessionId)) {\n\t\tawait keytar.setPassword(\"bf6mods\", \"sessionId\", cookieSessionId);\n\t\treturn true;\n\t}\n\n\tprintToConsole(\n\t\t`${colors.red(\"✗\")} Authentication failed. Session may have expired immediately.`,\n\t\ttrue,\n\t);\n\n\treturn false;\n}\n\ntype PlayClient = typeof clients.play;\nexport async function alwaysAuthenticatedRequest<K extends keyof PlayClient>(\n\tmethod: K,\n\trequest: Parameters<PlayClient[K]>[0],\n\tsessionId: string | undefined,\n\toptions?: Parameters<PlayClient[K]>[1],\n): Promise<Awaited<ReturnType<PlayClient[K]>>> {\n\tconst fn = clients.play[method] as (\n\t\treq: Parameters<PlayClient[K]>[0],\n\t\topts?: Parameters<PlayClient[K]>[1],\n\t) => ReturnType<PlayClient[K]>;\n\n\ttry {\n\t\treturn await fn(request, options);\n\t} catch (error) {\n\t\tif (error instanceof Error && error.message === \"[unauthenticated]\") {\n\t\t\tprintToConsole(\"🔄 Session expired. Re-authenticating…\");\n\t\t\tconst success = await authenticate(sessionId);\n\t\t\tif (!success) throw error;\n\t\t\treturn await fn(request, options);\n\t\t}\n\t\tthrow error;\n\t}\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { Clients, Generated_pb } from \"@bf6mods/portal\";\nimport type { ConfigType } from \"@bf6mods/sdk\";\nimport colors from \"colors\";\nimport { getBf6Config } from \"../build/index.ts\";\nimport { printToConsole } from \"../utils.ts\";\nimport { alwaysAuthenticatedRequest } from \"./authenticate.ts\";\n\nexport const clients = new Clients();\n\nexport async function deploy({\n\tinput,\n\tsessionIdParam,\n\tmodId,\n}: {\n\tinput?: string;\n\tsessionIdParam?: string;\n\tpublish?: boolean;\n\tmodId?: string;\n}) {\n\tprintToConsole(\"To be implemented in a future release\");\n\tprocess.exit(0);\n\tconst rootDir = path.resolve(\".\");\n\tif (!input) input = path.resolve(rootDir, \"dist\", \"mod.json\");\n\tprintToConsole(`🚀 Starting deploy for ${colors.cyan(input)}…`);\n\tif (!fs.existsSync(input))\n\t\treturn printToConsole(\n\t\t\t`${colors.red.bold(\"✗\")} File ${colors.cyan(input)} does not exist!`,\n\t\t\ttrue,\n\t\t);\n\tconst mod = JSON.parse(\n\t\tfs.readFileSync(input, { encoding: \"utf-8\" }),\n\t) as ConfigType;\n\n\tconst blueprints = await alwaysAuthenticatedRequest(\n\t\t\"getScheduledBlueprints\",\n\t\t{},\n\t\tsessionIdParam,\n\t);\n\tconsole.log(\"blueprints\", blueprints.blueprintIds);\n\n\tconst _blueprint = await alwaysAuthenticatedRequest(\n\t\t\"getBlueprintsById\",\n\t\t{\n\t\t\tblueprintIds: blueprints.blueprintIds,\n\t\t},\n\t\tsessionIdParam,\n\t);\n\n\tconst config = await getBf6Config(rootDir);\n\n\tlet id: string | undefined = modId;\n\tif (!config)\n\t\tprintToConsole(\n\t\t\t`Cannot find bf6mods config in dir ${rootDir}, proceeding without it.`,\n\t\t);\n\telse if (config?.id) id = config.id;\n\telse {\n\t\tprintToConsole(\n\t\t\t`No id specified in bf6.config.ts! Defaulting to experience with same name!`,\n\t\t);\n\t}\n\n\tif (!id) {\n\t\tconst owned = await alwaysAuthenticatedRequest(\n\t\t\t\"getOwnedPlayElementsV2\",\n\t\t\t{\n\t\t\t\tincludeDenied: true,\n\t\t\t\tpublishStates: [\n\t\t\t\t\tGenerated_pb.PublishStateType.Draft,\n\t\t\t\t\tGenerated_pb.PublishStateType.Published,\n\t\t\t\t\tGenerated_pb.PublishStateType.Error,\n\t\t\t\t],\n\t\t\t},\n\t\t\tsessionIdParam,\n\t\t);\n\t\tconsole.log(\n\t\t\t\"owned:\",\n\t\t\towned.playElements.map((owned) => owned.playElement),\n\t\t);\n\t\tconst found = owned.playElements.find(\n\t\t\t(element) => element?.playElement?.name === mod.name,\n\t\t);\n\t\tif (found?.playElement?.id) id = found.playElement.id;\n\t}\n\n\tif (!id) {\n\t\tprintToConsole(\n\t\t\t`${colors.red.bold(\"✗\")} Cannot find an id for your mod to deploy with! Please specify the id explicitly with \\`--id\\` or by having a mod with the same name!`,\n\t\t);\n\t\tprocess.exit(0);\n\t}\n\n\tconst playElementResponse = await alwaysAuthenticatedRequest(\n\t\t\"getPlayElement\",\n\t\t{\n\t\t\tid,\n\t\t\tincludeDenied: true,\n\t\t},\n\t\tsessionIdParam,\n\t);\n\n\tif (\n\t\t!playElementResponse.playElement ||\n\t\t!playElementResponse.playElementDesign ||\n\t\t!playElementResponse.progressionMode\n\t)\n\t\tthrow new Error(\n\t\t\t\"Cannot find essential attribute in mod, please report to GitHub!\",\n\t\t);\n\n\tif (!mod.mapRotation) throw new Error(\"You must specify at least one map!\");\n\n\tconsole.log(\"playElementResponse:\", playElementResponse);\n\n\t// buildSaveExperiencePayload(mod, blueprint.blueprints[0], playElementResponse as Required<typeof playElementResponse>)\n\n\t// console.log('tags', blueprint.blueprints[0].availableProgressionModeTags?.tags)\n\n\t// clients.play.updatePlayElement({\n\t// \tname: mod.name,\n\t// \tdescription: mod.description,\n\t// \tmapRotation: {\n\t// \t\tmaps: mod.mapRotation?.map((map) => {\n\t// \t\t\tconst mapData = blueprint.blueprints[0].availableGameData?.maps.find(\n\t// \t\t\t\t(availableMap) =>\n\t// \t\t\t\t\t`${availableMap.levelName}-${availableMap.levelName}` === map.id,\n\t// \t\t\t);\n\t// \t\t\tif (!mapData)\n\t// \t\t\t\tthrow new Error(\n\t// \t\t\t\t\t`Unable to deploy, due to map not being found. Please create a GitHub issue.${blueprint.blueprints}`,\n\t// \t\t\t\t);\n\t// \t\t\treturn {\n\t// \t\t\t\tlevelName: mapData.levelName,\n\t// \t\t\t\tlevelLocation: mapData.levelLocation,\n\t// \t\t\t\trounds: 1,\n\t// \t\t\t\tallowedSpectators: mapData.allowedSpectators,\n\t// \t\t\t\tmutators: [], // unknown as to what this does\n\t// \t\t\t\tteamComposition: {\n\t// \t\t\t\t\tteams: mod.teamComposition?.map((team) => ({\n\t// \t\t\t\t\t\tteamId: team[0],\n\t// \t\t\t\t\t\tcapacity: team[1]?.aiCapacity ?? 0 + team[1].humanCapacity,\n\t// \t\t\t\t\t})),\n\t// \t\t\t\t\tinternalTeams: mod.teamComposition?.map((team) => ({\n\t// \t\t\t\t\t\tteamId: team[0],\n\t// \t\t\t\t\t\tcapacity: 0,\n\t// \t\t\t\t\t\tcapacityTyppe: 0,\n\t// \t\t\t\t\t})),\n\t// \t\t\t\t},\n\t// \t\t\t} as Omit<Generated_pb.MapEntry, \"$typeName\">;\n\t// \t\t}),\n\t// \t\tattributes: {\n\t// \t\t\trotationBehavior: Generated_pb.RotationBehavior.LOOP,\n\t// \t\t},\n\t// \t},\n\t// })\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport chokidar, { type FSWatcher } from \"chokidar\";\nimport colors from \"colors\";\nimport { printToConsole } from \"./utils.ts\";\n\nexport class Bf6Logger {\n\tprivate static instance: Bf6Logger | undefined;\n\n\tprivate watchTarget: string;\n\tprivate watcher?: FSWatcher;\n\tprivate lastSize: number;\n\n\tconstructor(input?: string) {\n\t\tif (Bf6Logger.instance) {\n\t\t\tprintToConsole(\n\t\t\t\tcolors.yellow(\"⚠ Existing logger found — closing it first...\"),\n\t\t\t);\n\t\t\tBf6Logger.instance.stop();\n\t\t}\n\n\t\tif (input) this.watchTarget = path.resolve(input);\n\t\telse if (process.env.LOCALAPPDATA)\n\t\t\tthis.watchTarget = path.resolve(\n\t\t\t\tprocess.env.LOCALAPPDATA,\n\t\t\t\t\"temp\",\n\t\t\t\t\"Battlefieldâ„¢ 6\",\n\t\t\t\t\"PortalLog.txt\",\n\t\t\t);\n\t\telse\n\t\t\tthrow new Error(\n\t\t\t\t`${colors.red.bold(\"✗\")} Env variable LOCALAPPDATA not defined, and input file to watch was not provided!`,\n\t\t\t);\n\n\t\tif (!fs.existsSync(this.watchTarget))\n\t\t\tthrow new Error(\n\t\t\t\t`${colors.red.bold(\"✗\")} Cannot find file '${this.watchTarget}' to watch for changes`,\n\t\t\t);\n\n\t\tthis.lastSize = fs.statSync(this.watchTarget).size;\n\t\tBf6Logger.instance = this;\n\t}\n\n\tasync start() {\n\t\tprintToConsole(\n\t\t\tcolors.cyan(\n\t\t\t\t`👀 Watching Battlefield logs at: ${colors.yellow(this.watchTarget)}`,\n\t\t\t),\n\t\t);\n\n\t\tthis.watcher = chokidar.watch(this.watchTarget, {\n\t\t\tpersistent: true,\n\t\t\tignoreInitial: true,\n\t\t});\n\n\t\tthis.watcher.on(\"change\", this.handleChange.bind(this));\n\t}\n\n\tasync stop() {\n\t\tif (this.watcher) {\n\t\t\tthis.watcher.close();\n\t\t\tthis.watcher = undefined;\n\t\t\tprintToConsole(\n\t\t\t\tcolors.yellow(\n\t\t\t\t\t`${colors.red.bold(\"✗\")} Stopped watching: ${colors.gray(this.watchTarget)}`,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t\tBf6Logger.instance = undefined;\n\t}\n\n\tprivate handleChange(file: string, stats?: fs.Stats) {\n\t\tif (!stats) return;\n\t\tif (stats.size > this.lastSize) {\n\t\t\tconst newBytes = stats.size - this.lastSize;\n\t\t\tconst fd = fs.openSync(file, \"r\");\n\t\t\tconst buffer = Buffer.alloc(newBytes);\n\t\t\tfs.readSync(fd, buffer, 0, newBytes, this.lastSize);\n\t\t\tfs.closeSync(fd);\n\n\t\t\tconst newContent = buffer\n\t\t\t\t.toString(\"utf8\")\n\t\t\t\t.split(\"QuickJS: \")\n\t\t\t\t.filter((debug) => debug.trim() !== \"\")\n\t\t\t\t.map((debug) => debug.trim())\n\t\t\t\t.map((debug) => {\n\t\t\t\t\tif (debug.startsWith(\"console.log: \")) {\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\ttype: \"console.log\",\n\t\t\t\t\t\t\ttext: debug.replace(\"console.log: \", \"\"),\n\t\t\t\t\t\t};\n\t\t\t\t\t} else if (debug.startsWith(\"Exception:\")) {\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\ttype: \"exception\",\n\t\t\t\t\t\t\ttext: debug.replace(\"Exception:\", \"\"),\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\n\t\t\t\t\treturn {\n\t\t\t\t\t\ttype: \"unknown\",\n\t\t\t\t\t\ttext: debug,\n\t\t\t\t\t};\n\t\t\t\t});\n\n\t\t\tfor (const content of newContent) {\n\t\t\t\tif (content.type === \"console.log\")\n\t\t\t\t\tprintToConsole(colors.gray(content.text));\n\t\t\t\telse if (content.type === \"exception\")\n\t\t\t\t\tprintToConsole(colors.red(content.text), true);\n\t\t\t\telse printToConsole(colors.bold(content.text));\n\t\t\t}\n\t\t}\n\t\tthis.lastSize = stats.size;\n\t}\n}\n","import fs from \"node:fs\";\nimport { glob } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport chokidar, { type FSWatcher } from \"chokidar\";\nimport colors from \"colors\";\nimport type { Bf6Config } from \"../resources/prepare/types/config.ts\";\nimport { build, getBf6Config } from \"./build/index.ts\";\nimport { Bf6Logger } from \"./log.ts\";\nimport { printToConsole } from \"./utils.ts\";\n\nexport async function dev() {\n\tconst workingDir = path.resolve(\".\");\n\tconst config = await getBf6Config(workingDir);\n\tif (!config) throw new Error(\"Cannot find bf6.config.ts!\");\n\tconst outDir = path.resolve(workingDir, config.outDir);\n\tfs.mkdirSync(outDir, { recursive: true });\n\n\tprintToConsole(colors.cyan(`▶ Starting dev for ${config.name}`));\n\n\tlet watcher: FSWatcher | undefined;\n\n\t// biome-ignore lint/suspicious/noExplicitAny: doesn't really matter in this case\n\tfunction debounce<T extends (...args: any[]) => void>(fn: T, delay: number) {\n\t\tlet timer: NodeJS.Timeout | undefined;\n\t\treturn (...args: Parameters<T>) => {\n\t\t\tif (timer) clearTimeout(timer);\n\t\t\ttimer = setTimeout(() => fn(...args), delay);\n\t\t};\n\t}\n\n\tconst rebuild = async (trigger: string) => {\n\t\tprintToConsole(\n\t\t\tcolors.yellow(\n\t\t\t\t`↻ Change detected in ${path.basename(trigger)}, rebuilding...`,\n\t\t\t),\n\t\t);\n\t\tconst start = performance.now();\n\t\ttry {\n\t\t\tawait build();\n\t\t\tconst duration = ((performance.now() - start) / 1000).toFixed(2);\n\t\t\tprintToConsole(\n\t\t\t\t`${colors.green.bold(\"✓\")} Updated mod.json (${duration}s)`,\n\t\t\t);\n\t\t} catch (err) {\n\t\t\tprintToConsole(\n\t\t\t\tcolors.red(\n\t\t\t\t\t`${colors.red.bold(\"✗\")} Rebuild failed: ${(err as Error).message}`,\n\t\t\t\t),\n\t\t\t\ttrue,\n\t\t\t);\n\t\t}\n\t};\n\n\tconst debouncedRebuild = debounce(rebuild, 200);\n\n\tasync function collectWatchTargets(config: Bf6Config): Promise<string[]> {\n\t\tconst targets: string[] = [];\n\n\t\tif (config.entrypoint)\n\t\t\ttargets.push(path.resolve(workingDir, config.entrypoint));\n\t\tif (config.scenes)\n\t\t\tfor (const [, scene] of config.scenes)\n\t\t\t\ttargets.push(path.resolve(workingDir, scene));\n\t\tif (config.strings) targets.push(path.resolve(workingDir, config.strings));\n\t\tfor await (const entry of glob(\"bf6.config.*\")) targets.push(entry);\n\t\tfor await (const entry of glob(\"src/**/*\")) targets.push(entry);\n\n\t\treturn targets;\n\t}\n\n\tasync function setupWatcher(config: Bf6Config) {\n\t\tif (watcher) {\n\t\t\tawait watcher.close();\n\t\t\tprintToConsole(\n\t\t\t\tcolors.grey(\"♻ Reloading watcher due to config change...\"),\n\t\t\t);\n\t\t\tawait new Promise((r) => setTimeout(r, 10));\n\t\t}\n\n\t\tconst watchTargets = await collectWatchTargets(config);\n\t\tprintToConsole(colors.cyan(`👀 Watching ${watchTargets.length} files...`));\n\n\t\twatcher = chokidar.watch(watchTargets, {\n\t\t\tpersistent: true,\n\t\t\tignoreInitial: true,\n\t\t\tawaitWriteFinish: { stabilityThreshold: 250, pollInterval: 100 },\n\t\t\tignored: [outDir, `${outDir}/**`, \"node_modules/**\", \".git/**\"],\n\t\t});\n\n\t\twatcher.on(\"error\", (err) => {\n\t\t\tprintToConsole(\n\t\t\t\tcolors.red(`⚠ Watcher error: ${(err as Error).message}`),\n\t\t\t\ttrue,\n\t\t\t);\n\t\t\tsetTimeout(setupWatcher, 1000);\n\t\t});\n\n\t\twatcher.on(\"change\", async (file) => {\n\t\t\tif (file.includes(\"bf6.config.\")) {\n\t\t\t\tprintToConsole(\n\t\t\t\t\tcolors.magenta(\"⚙ Config changed — reloading watcher...\"),\n\t\t\t\t);\n\t\t\t\tconst newConfig = await getBf6Config(workingDir);\n\t\t\t\tif (!newConfig) throw new Error(\"Cannot find bf6.config.ts!\");\n\t\t\t\tawait setupWatcher(newConfig);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tdebouncedRebuild(file);\n\t\t});\n\n\t\twatcher.on(\"add\", debouncedRebuild);\n\t\tawait rebuild(\"initial\");\n\t}\n\n\tprocess.on(\"SIGINT\", async () => {\n\t\tprintToConsole(colors.red(`\\n${colors.red.bold(\"✗\")} Exiting dev mode...`));\n\t\tawait watcher?.close();\n\t\tprocess.exit(0);\n\t});\n\n\tawait setupWatcher(config);\n\n\tlet logger: Bf6Logger | undefined;\n\ttry {\n\t\tlogger = new Bf6Logger();\n\t\tlogger.start();\n\t} catch (error) {\n\t\tprintToConsole(\n\t\t\tcolors.grey(\n\t\t\t\t\"Failed to start logging for the following reason (building will still work)\",\n\t\t\t),\n\t\t\ttrue,\n\t\t);\n\t\tprintToConsole((error as Error).message, true);\n\t}\n}\n","{\n\t\"name\": \"@bf6mods/sdk\",\n\t\"version\": \"1.6.0\",\n\t\"description\": \"TypeScript definitions for the BF6 modding API\",\n\t\"type\": \"module\",\n\t\"license\": \"MIT\",\n\t\"exports\": {\n\t\t\".\": {\n\t\t\t\"types\": \"./dist/index.d.ts\",\n\t\t\t\"import\": \"./dist/index.js\"\n\t\t},\n\t\t\"./std\": {\n\t\t\t\"types\": \"./dist/std/index.d.ts\",\n\t\t\t\"import\": \"./dist/std/index.js\"\n\t\t}\n\t},\n\t\"repository\": {\n\t\t\"type\": \"git\",\n\t\t\"url\": \"git+https://github.com/bf6mods/bf6mods.git\"\n\t},\n\t\"files\": [\n\t\t\"dist/\"\n\t],\n\t\"scripts\": {\n\t\t\"build\": \"tsdown\"\n\t},\n\t\"keywords\": [\n\t\t\"bf6\",\n\t\t\"mods\",\n\t\t\"typescript\",\n\t\t\"definitions\",\n\t\t\"api\"\n\t],\n\t\"publishConfig\": {\n\t\t\"access\": \"public\"\n\t}\n}\n","import child_process from \"node:child_process\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport * as prompts from \"@clack/prompts\";\nimport bf6SdkPackageJson from \"../../../sdk/package.json\" with { type: \"json\" };\nimport bf6CliPackageJson from \"../../package.json\" with { type: \"json\" };\nimport { importFile } from \"./import.ts\";\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\n\nconst templatesDir = path.resolve(__dirname, \"../resources/templates\");\n\nfunction renameFilesRecursively(dir: string, modName: string) {\n\tconst entries = fs.readdirSync(dir, { withFileTypes: true });\n\tfor (const entry of entries) {\n\t\tconst oldPath = path.join(dir, entry.name);\n\t\tlet newPath = oldPath;\n\n\t\t// Rename file or folder if it includes {name}\n\t\tif (entry.name.includes(\"{name}\")) {\n\t\t\tconst newName = entry.name.replace(\"{name}\", modName);\n\t\t\tnewPath = path.join(dir, newName);\n\t\t\tfs.renameSync(oldPath, newPath);\n\t\t}\n\n\t\t// If it's a bf6.config.ts, replace the {bf6ConfigName} placeholder\n\t\tif (entry.name === \"bf6.config.ts\") {\n\t\t\tlet content = fs.readFileSync(newPath, \"utf-8\");\n\t\t\tcontent = content.replace(/{bf6ConfigName}/g, modName);\n\t\t\tfs.writeFileSync(newPath, content, \"utf-8\");\n\t\t}\n\n\t\t// If it's a package.json, rewrite the \"name\" field\n\t\tif (entry.name === \"package.json\") {\n\t\t\tconst pkg = JSON.parse(fs.readFileSync(newPath, \"utf-8\"));\n\t\t\tpkg.name = modName;\n\t\t\tif (!pkg.devDependencies) pkg.devDependencies = {};\n\t\t\tpkg.devDependencies[\"@bf6mods/cli\"] = `^${bf6CliPackageJson.version}`;\n\t\t\tpkg.devDependencies[\"@bf6mods/sdk\"] = `^${bf6SdkPackageJson.version}`;\n\t\t\tfs.writeFileSync(newPath, JSON.stringify(pkg, null, 2));\n\t\t}\n\n\t\t// Recurse into directories (using the new name if renamed)\n\t\tif (fs.statSync(newPath).isDirectory()) {\n\t\t\trenameFilesRecursively(newPath, modName);\n\t\t}\n\t}\n}\n\nexport const templates = [\n\t\"Basic\",\n\t\"Complete\",\n\t\"AcePursuit\",\n\t\"BombSquad\",\n\t\"Exfil\",\n\t\"Vertigo\",\n] as const;\n\nexport async function startProject(\n\tdestination: string,\n\ttemplate: (typeof templates)[number] | \"None\",\n\tname?: string,\n) {\n\tif ([\"AcePursuit\", \"BombSquad\", \"Exfil\", \"Vertigo\"].includes(template)) {\n\t\tconst importPath = path.resolve(templatesDir, `${template}.json`);\n\t\tawait importFile(importPath, destination, name);\n\t} else if (template === \"None\") {\n\t\t// Do nothing if none\n\t} else {\n\t\t// Handles the Basic and any other template provided\n\t\tconst templateDir = path.resolve(templatesDir, template);\n\t\tfs.cpSync(templateDir, destination, { recursive: true });\n\t}\n\n\tfs.cpSync(path.resolve(templatesDir, \"All\"), destination, {\n\t\trecursive: true,\n\t});\n\n\tconst gitignorePath = path.join(destination, \"_gitignore\");\n\tconst dotGitignorePath = path.join(destination, \".gitignore\");\n\tif (fs.existsSync(gitignorePath)) {\n\t\tfs.renameSync(gitignorePath, dotGitignorePath);\n\t}\n\n\tif (name) renameFilesRecursively(destination, name);\n}\n\nexport function installDependencies(projectDir: string) {\n\ttry {\n\t\tchild_process.execSync(`npm install`, {\n\t\t\tstdio: \"inherit\",\n\t\t\tcwd: projectDir,\n\t\t});\n\t\treturn true;\n\t} catch (_err) {\n\t\treturn false;\n\t}\n}\n\nconst _defaultTargetDir = \"bf6-mod\";\nconst cancel = () => prompts.cancel(\"Operation cancelled\");\n\nfunction isEmpty(path: string) {\n\tconst files = fs.readdirSync(path);\n\treturn files.length === 0 || (files.length === 1 && files[0] === \".git\");\n}\n\nfunction emptyDir(dir: string) {\n\tif (!fs.existsSync(dir)) {\n\t\treturn;\n\t}\n\tfor (const file of fs.readdirSync(dir)) {\n\t\tif (file === \".git\") {\n\t\t\tcontinue;\n\t\t}\n\t\tfs.rmSync(path.resolve(dir, file), { recursive: true, force: true });\n\t}\n}\n\nexport async function init(\n\targTargetDir?: string,\n\toptions?: {\n\t\tname?: string;\n\t\ttemplate?: (typeof templates)[number];\n\t\tonExists?: \"overwrite\" | \"cancel\" | \"ignore\";\n\t\tinstallDependencies?: boolean;\n\t},\n) {\n\tprompts.intro(\"Initialize Bf6 Mod\");\n\n\tconst path = argTargetDir\n\t\t? argTargetDir\n\t\t: await prompts.text({\n\t\t\t\tmessage: \"Where should we create your project?\",\n\t\t\t\tplaceholder: \"./ace-pursuit\",\n\t\t\t\tvalidate: (value) => {\n\t\t\t\t\tif (!value) return \"Please enter a path.\";\n\t\t\t\t\tif (value[0] !== \".\") return \"Please enter a relative path.\";\n\t\t\t\t},\n\t\t\t});\n\tif (prompts.isCancel(path)) return cancel();\n\n\tlet name = options?.name\n\t\t? options.name\n\t\t: await prompts.text({\n\t\t\t\tmessage: \"What is the name of your mod?\",\n\t\t\t\tplaceholder: \"Ace Pursuit\",\n\t\t\t\tvalidate: (value) => {\n\t\t\t\t\tif (!value.trim()) return \"Please enter a name.\";\n\t\t\t\t},\n\t\t\t});\n\tif (prompts.isCancel(name)) return cancel();\n\tname = name.trim();\n\n\tif (fs.existsSync(path) && !isEmpty(path)) {\n\t\tlet overwrite: \"yes\" | \"no\" | \"ignore\" | undefined;\n\t\tif (options?.onExists) {\n\t\t\tswitch (options.onExists) {\n\t\t\t\tcase \"overwrite\":\n\t\t\t\t\toverwrite = \"yes\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"cancel\":\n\t\t\t\t\toverwrite = \"no\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"ignore\":\n\t\t\t\t\toverwrite = \"ignore\";\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tconst res = overwrite\n\t\t\t? overwrite\n\t\t\t: await prompts.select({\n\t\t\t\t\tmessage:\n\t\t\t\t\t\t(path === \".\"\n\t\t\t\t\t\t\t? \"Current directory\"\n\t\t\t\t\t\t\t: `Target directory \"${path}\"`) +\n\t\t\t\t\t\t` is not empty. Please choose how to proceed:`,\n\t\t\t\t\toptions: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tlabel: \"Cancel operation\",\n\t\t\t\t\t\t\tvalue: \"no\",\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tlabel: \"Remove existing files and continue\",\n\t\t\t\t\t\t\tvalue: \"yes\",\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tlabel: \"Ignore files and continue\",\n\t\t\t\t\t\t\tvalue: \"ignore\",\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t});\n\t\tif (prompts.isCancel(res)) return cancel();\n\t\toverwrite = res;\n\n\t\tswitch (overwrite) {\n\t\t\tcase \"yes\":\n\t\t\t\temptyDir(path);\n\t\t\t\tbreak;\n\t\t\tcase \"no\":\n\t\t\t\tcancel();\n\t\t\t\treturn;\n\t\t}\n\t}\n\n\tconst template = options?.template\n\t\t? options.template\n\t\t: await prompts.select({\n\t\t\t\tmessage: \"Select a template:\",\n\t\t\t\toptions: templates.map((template) => {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tlabel: template,\n\t\t\t\t\t\tvalue: template,\n\t\t\t\t\t};\n\t\t\t\t}),\n\t\t\t});\n\tif (prompts.isCancel(template)) return cancel();\n\n\tawait startProject(path, template, name);\n\n\tif (options?.installDependencies) {\n\t\tconst s = prompts.spinner();\n\t\ts.start(\"Installing via npm\");\n\t\tconst installed = installDependencies(path);\n\t\tif (installed) s.stop(\"Installed via npm\");\n\t\telse s.stop(\"Failed to install via npm\", 1);\n\n\t\tconst nextSteps = `cd ${path}\\nnpm run build`;\n\n\t\tprompts.note(nextSteps, \"Next steps.\");\n\t} else {\n\t\tconst nextSteps = `cd ${path}\\nnpm i\\nnpm run build`;\n\n\t\tprompts.note(nextSteps, \"Next steps.\");\n\t}\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { AttachmentType, type ConfigType } from \"@bf6mods/sdk\";\nimport colors from \"colors\";\nimport stringifyObject from \"stringify-object\";\nimport { MapId as MapIdEnum } from \"../resources/prepare/types/config.ts\";\nimport { startProject } from \"./init.ts\";\nimport { printToConsole } from \"./utils.ts\";\n\nasync function writeFileSafe(filePath: string, data: string | Buffer) {\n\tconst dir = path.dirname(filePath);\n\tawait fs.promises.mkdir(dir, { recursive: true });\n\tawait fs.promises.writeFile(filePath, data);\n}\n\nfunction getMapKeyByValue(value: string): keyof typeof MapIdEnum | undefined {\n\treturn Object.keys(MapIdEnum).find(\n\t\t(k) => MapIdEnum[k as keyof typeof MapIdEnum] === value,\n\t) as keyof typeof MapIdEnum | undefined;\n}\n\nexport async function importFile(\n\tinput: string,\n\toutput: string,\n\tname?: string,\n\tlogging = false,\n) {\n\tconst start = performance.now();\n\tconst workingDir = path.resolve(\".\");\n\tconst entrypoint = path.resolve(workingDir, input);\n\tconst outDir = path.resolve(workingDir, output);\n\n\tif (!fs.existsSync(entrypoint)) throw new Error(\"Cannot find strings file\");\n\n\tif (logging)\n\t\tprintToConsole(colors.cyan(`📦 Importing config from: ${entrypoint}`));\n\n\tconst config = JSON.parse(\n\t\tawait fs.promises.readFile(entrypoint, { encoding: \"utf8\" }),\n\t) as ConfigType;\n\n\tif (!fs.existsSync(outDir)) {\n\t\tawait fs.promises.mkdir(outDir, { recursive: true });\n\t\tif (logging)\n\t\t\tprintToConsole(colors.cyan(`📁 Created output directory: ${outDir}`));\n\t}\n\n\tawait startProject(outDir, \"None\", name ?? config.name);\n\n\tlet typescriptFile: string | undefined;\n\tlet stringsFile: string | undefined;\n\tconst scenes: [string, string][] = [];\n\tconst promises: Promise<unknown>[] = [];\n\n\tif (config.attachments) {\n\t\tlet unamedAttachmentIndex = 0;\n\t\tfor (const attachment of config.attachments) {\n\t\t\tlet filename = attachment.filename?.trim();\n\t\t\tif (!filename) {\n\t\t\t\tunamedAttachmentIndex++;\n\n\t\t\t\tlet ext: string = \"\";\n\t\t\t\tif (attachment.attachmentType === AttachmentType.TypeScript)\n\t\t\t\t\text = \".ts\";\n\t\t\t\telse if (attachment.attachmentType === AttachmentType.Strings)\n\t\t\t\t\text = \".strings.json\";\n\t\t\t\telse if (attachment.attachmentType === AttachmentType.SpatialData)\n\t\t\t\t\text = \".spatial.json\";\n\n\t\t\t\tif (unamedAttachmentIndex > 1)\n\t\t\t\t\tfilename = `attachment_${unamedAttachmentIndex}${ext}`;\n\t\t\t\telse filename = `attachment${ext}`;\n\t\t\t}\n\n\t\t\tif (attachment.attachmentType === AttachmentType.TypeScript)\n\t\t\t\ttypescriptFile = filename;\n\n\t\t\tif (attachment.attachmentType === AttachmentType.Strings)\n\t\t\t\tstringsFile = filename;\n\n\t\t\tif (attachment.attachmentType === AttachmentType.SpatialData) {\n\t\t\t\t// We'll just use the data attached to mapRotation instead\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tpromises.push(\n\t\t\t\twriteFileSafe(\n\t\t\t\t\tpath.resolve(outDir, \"src\", filename),\n\t\t\t\t\tatob(attachment.attachmentData.original),\n\t\t\t\t),\n\t\t\t);\n\n\t\t\tif (logging)\n\t\t\t\tprintToConsole(\n\t\t\t\t\t`${colors.green(\"✓\")} Wrote attachment: ${colors.yellow(filename)}`,\n\t\t\t\t);\n\t\t}\n\t}\n\n\t// Extract spatial scenes from mapRotation instead of guessing\n\tif (config.mapRotation?.length) {\n\t\tfor (const map of config.mapRotation) {\n\t\t\tpromises.push(\n\t\t\t\twriteFileSafe(\n\t\t\t\t\tpath.resolve(outDir, \"src\", \"scenes\", map.spatialAttachment.filename),\n\t\t\t\t\tatob(map.spatialAttachment.attachmentData.original),\n\t\t\t\t),\n\t\t\t);\n\n\t\t\tscenes.push([map.id, `src/scenes/${map.spatialAttachment.filename}`]);\n\n\t\t\tif (logging)\n\t\t\t\tprintToConsole(\n\t\t\t\t\t`${colors.green(\"✓\")} Added scene: ${colors.yellow(map.id)}`,\n\t\t\t\t);\n\t\t}\n\t}\n\n\t// build the new bf6.config.ts structure\n\tconst bf6Config = {\n\t\tname: name ?? config.name,\n\t\tdescription: config.description,\n\t\toutDir: \"dist\",\n\t\tentrypoint: typescriptFile ? `src/${typescriptFile}` : undefined,\n\t\tscenes: scenes\n\t\t\t? scenes.map(([id, path]) => [\n\t\t\t\t\t`MapId.${getMapKeyByValue(id) ?? id}`,\n\t\t\t\t\tpath,\n\t\t\t\t])\n\t\t\t: undefined,\n\t\tstrings: stringsFile ? `src/${stringsFile}` : undefined,\n\t\tgame: {\n\t\t\tmutators: config.mutators,\n\t\t\tassetRestrictions: config.assetRestrictions,\n\t\t\tgameMode: config.gameMode,\n\t\t\tteamComposition: config.teamComposition,\n\t\t},\n\t};\n\n\tconst bf6ConfigContent = `export default defineBf6Config(${stringifyWithRaw(\n\t\tbf6Config,\n\t)});\\n`;\n\n\tpromises.push(\n\t\twriteFileSafe(path.resolve(outDir, \"bf6.config.ts\"), bf6ConfigContent),\n\t);\n\n\tawait Promise.all(promises);\n\n\tconst duration = ((performance.now() - start) / 1000).toFixed(2);\n\tif (logging)\n\t\tprintToConsole(\n\t\t\t`${colors.green.bold(\"✓\")} Import complete (${duration}s) → ${colors.yellow(outDir)}`,\n\t\t);\n}\n\nfunction stringifyWithRaw(value: unknown, options = {}) {\n\treturn stringifyObject(value, {\n\t\tindent: \" \", // 4 spaces\n\t\tsingleQuotes: true,\n\t\ttransform: (_obj, _prop, originalResult) => {\n\t\t\t// Remove quotes from MapId.* expressions\n\t\t\tif (/^['\"]MapId\\.[A-Za-z0-9_]+['\"]$/.test(originalResult)) {\n\t\t\t\treturn originalResult.slice(1, -1); // remove surrounding quotes\n\t\t\t}\n\t\t\treturn originalResult;\n\t\t},\n\t\t...options,\n\t});\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport colors from \"colors\";\nimport { genExport, genInlineTypeImport } from \"knitwork\";\nimport { printToConsole } from \"./utils.js\";\n\nexport async function prepare() {\n\ttry {\n\t\tconst __filename = fileURLToPath(import.meta.url);\n\t\tconst __dirname = path.dirname(__filename);\n\n\t\tconst _workingDir = path.resolve(\".\");\n\t\tconst buildDir = path.resolve(\".bf6\");\n\n\t\tconst resources = path.resolve(__dirname, \"../resources/prepare\");\n\n\t\tfs.cpSync(\n\t\t\tpath.resolve(resources, \"tsconfig.json\"),\n\t\t\tpath.resolve(buildDir, \"tsconfig.json\"),\n\t\t);\n\t\tfs.cpSync(\n\t\t\tpath.resolve(resources, \"bf6.d.ts\"),\n\t\t\tpath.resolve(buildDir, \"bf6.d.ts\"),\n\t\t);\n\t\tfs.cpSync(\n\t\t\tpath.resolve(resources, \"types\", \"config.ts\"),\n\t\t\tpath.resolve(buildDir, \"types\", \"config.ts\"),\n\t\t);\n\n\t\tconst ConfigFileExports = genExport(\"./types/config.ts\", [\n\t\t\t\"defineBf6Config\",\n\t\t]);\n\t\tfs.writeFileSync(\n\t\t\tpath.resolve(buildDir, \"imports.d.ts\"),\n\t\t\t`${ConfigFileExports}\\n`,\n\t\t);\n\n\t\tconst augmentations: Record<string, string> = {\n\t\t\tdefineBf6Config: genInlineTypeImport(\n\t\t\t\t\"./types/config.ts\",\n\t\t\t\t`defineBf6Config`,\n\t\t\t),\n\t\t\tMapId: genInlineTypeImport(\"./types/config.ts\", `MapId`),\n\t\t};\n\n\t\tconst args = genNamespaceAugmentation(\"global\", augmentations);\n\t\tfs.writeFileSync(\n\t\t\tpath.resolve(buildDir, \"globals.d.ts\"),\n\t\t\t`export {}\\n\\n${args}\\n`,\n\t\t);\n\n\t\tprintToConsole(`${colors.green.bold(\"✓\")} Types generated in .bf6`);\n\t} catch (error) {\n\t\tconsole.error(error);\n\t\tprintToConsole(\n\t\t\t`${colors.red.bold(\"✗\")} Types failed to generate in .bf6`,\n\t\t\ttrue,\n\t\t);\n\t}\n}\n\nconst genNamespaceAugmentation = (\n\tname: string,\n\tcontents: Record<string, string>,\n) => {\n\tif (!contents || Object.keys(contents).length === 0)\n\t\treturn `declare ${name} {}`;\n\tconst decls = Object.entries(contents)\n\t\t.map(([k, v]) => `\\tconst ${k}: ${v};`)\n\t\t.join(\"\\n\");\n\treturn `declare ${name} {\\n${decls}\\n}`;\n};\n","#!/usr/bin/env node\nimport colors from \"colors\";\nimport { Command } from \"commander\";\nimport pkg from \"../../package.json\" with { type: \"json\" };\nimport { build } from \"./build/index.ts\";\nimport { deploy } from \"./deploy/index.ts\";\nimport { dev } from \"./dev.ts\";\nimport { importFile } from \"./import.ts\";\nimport { init, installDependencies, templates } from \"./init.js\";\nimport { Bf6Logger } from \"./log.ts\";\nimport { prepare } from \"./prepare.js\";\nimport { printToConsole, readableList } from \"./utils.ts\";\n\nconst program = new Command();\n\nprogram\n\t.name(Object.keys(pkg.bin)[0])\n\t.description(pkg.description)\n\t.version(pkg.version);\n\nprogram\n\t.command(\"init\")\n\t.argument(\"[directory]\")\n\t.option(\"--name <name>\", \"The name of your mod\")\n\t.option(\"--template <template>\", \"The template to use\")\n\t.option(\n\t\t\"--on-exists <action>\",\n\t\t`Either \"overwrite\", \"cancel\", or \"ignore\" as to what to do if files exist in the directory`,\n\t)\n\t.option(\"--no-install-dependencies\", `Prevents install of dependencies`)\n\t.description(\"Create a new bf6 mod\")\n\t.action(async (directory, options) => {\n\t\tconst { name, template, onExists, installDependencies } = options;\n\t\tif (\n\t\t\tonExists !== undefined &&\n\t\t\t![\"overwrite\", \"cancel\", \"ignore\"].includes(onExists)\n\t\t) {\n\t\t\tprintToConsole(\n\t\t\t\t`${colors.red.bold(\"✗\")} Invalid value for --on-exists: \"${onExists}\". Expected one of \"overwrite\", \"cancel\", or \"ignore\".`,\n\t\t\t\ttrue,\n\t\t\t);\n\t\t\tprocess.exit(1);\n\t\t}\n\t\tif (template !== undefined && !templates.includes(template)) {\n\t\t\tprintToConsole(\n\t\t\t\t`${colors.red.bold(\"✗\")} Invalid value for --template: \"${template}\". Expected one of ${readableList(templates)}.`,\n\t\t\t\ttrue,\n\t\t\t);\n\t\t\tprocess.exit(1);\n\t\t}\n\n\t\tawait init(directory, {\n\t\t\tname,\n\t\t\ttemplate,\n\t\t\tonExists,\n\t\t\tinstallDependencies,\n\t\t});\n\t});\n\nprogram\n\t.command(\"build\")\n\t.description(\"build the bf6 mod\")\n\t.action(async () => {\n\t\tawait build();\n\t});\n\nprogram\n\t.command(\"prepare\")\n\t.description(\"prepare the types for bf6 mod\")\n\t.action(async () => {\n\t\tawait prepare();\n\t});\n\nprogram\n\t.command(\"dev\")\n\t.description(\"watch the changes in src, and recompile as needed\")\n\t.action(async () => {\n\t\tawait dev();\n\t});\n\nprogram\n\t.command(\"import\")\n\t.argument(\"<input>\")\n\t.argument(\"<output>\")\n\t.option(\"--no-install-dependencies\", `Prevents install of dependencies`)\n\t.description(\"decompiles the json config of a mod into a new project\")\n\t.action(async (input, output, options: { installDependencies: boolean }) => {\n\t\tawait importFile(input as string, output as string, undefined, true);\n\t\tif (options?.installDependencies) installDependencies(output);\n\t});\n\nprogram\n\t.command(\"log\")\n\t.argument(\"[input]\")\n\t.description(\"logs the output from a locally running server\")\n\t.action(async (input) => {\n\t\tconst logger = new Bf6Logger(input);\n\t\tlogger.start();\n\t});\n\nprogram\n\t.command(\"deploy\")\n\t.argument(\"[input]\")\n\t.option(\n\t\t\"--session-id <session id>\",\n\t\t`The session id to use when deploying, should be web-xxxx`,\n\t)\n\t.option(\"--publish\", `Whether to publish your mod`)\n\t.option(\"--id <id>\", `The id of your mod`)\n\t.description(\n\t\t\"deploys your mod for you, if unauthenticated, it requests reauthentication\",\n\t)\n\t.action(async (input, options) => {\n\t\tawait deploy({\n\t\t\tinput,\n\t\t\tsessionIdParam: options?.sessionId,\n\t\t\tpublish: options?.publish,\n\t\t\tmodId: options?.id,\n\t\t});\n\t});\n\nprogram.exitOverride((_err) => {\n\tif (process.env.EXIT_CODE === \"none\") process.exit(0);\n});\n\nif (!process.argv.slice(2).length) {\n\tprogram.outputHelp();\n\tprocess.exit(0);\n}\n\nprogram.parse();\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["program","edits: { pos: number; insert: string }[]","program","key:\n\t\t\t\t\t\t\t| string\n\t\t\t\t\t\t\t| number\n\t\t\t\t\t\t\t| bigint\n\t\t\t\t\t\t\t| boolean\n\t\t\t\t\t\t\t| RegExp\n\t\t\t\t\t\t\t| null\n\t\t\t\t\t\t\t| undefined","errors: string[]","buffer: Buffer","MapIdEnum","tsAttachment: Attachment | undefined","__filename","__dirname","attachments: Attachment[]","mapRotation: MapType[]","mapId: MapIdEnum","scene: string","finalJson: ConfigType","puppeteer: PuppeteerImport","id: string | undefined","owned","thumbnailPath: string | undefined","thumbnailExt: string | undefined","watcher: FSWatcher | undefined","timer: NodeJS.Timeout | undefined","targets: string[]","config","logger: Bf6Logger | undefined","bf6CliPackageJson.version","bf6SdkPackageJson.version","path","overwrite: \"yes\" | \"no\" | \"ignore\" | undefined","template","MapIdEnum","typescriptFile: string | undefined","stringsFile: string | undefined","scenes: [string, string][]","promises: Promise<unknown>[]","ext: string","path","__filename","__dirname","pkg.bin","pkg.description","pkg.version"],"sources":["../../package.json","../../src/resources/prepare/types/config.ts","../../src/cli/utils.ts","../../src/cli/build/any-params.ts","../../src/cli/build/generated-strings.ts","../../src/cli/build/thumbnail.ts","../../src/cli/build/index.ts","../../src/cli/deploy/authenticate.ts","../../src/cli/deploy/index.ts","../../src/cli/log.ts","../../src/cli/dev.ts","../../../sdk/package.json","../../src/cli/init.ts","../../src/cli/import.ts","../../src/cli/prepare.ts","../../src/cli/index.ts"],"sourcesContent":["{\n\t\"name\": \"@bf6mods/cli\",\n\t\"version\": \"1.7.0\",\n\t\"description\": \"CLI and library for bundling BF6 mods\",\n\t\"license\": \"MIT\",\n\t\"type\": \"module\",\n\t\"bin\": {\n\t\t\"bf6mods\": \"./dist/cli/index.js\"\n\t},\n\t\"main\": \"./dist/index.js\",\n\t\"types\": \"./dist/index.d.ts\",\n\t\"scripts\": {\n\t\t\"build\": \"tsdown\",\n\t\t\"start\": \"cross-env EXIT_CODE=none tsx ./src/cli/index.ts\"\n\t},\n\t\"exports\": {\n\t\t\".\": {\n\t\t\t\"types\": \"./dist/index.d.ts\",\n\t\t\t\"import\": \"./dist/index.js\"\n\t\t}\n\t},\n\t\"files\": [\n\t\t\"dist/\"\n\t],\n\t\"repository\": {\n\t\t\"type\": \"git\",\n\t\t\"url\": \"git+https://github.com/bf6mods/bf6mods.git\"\n\t},\n\t\"dependencies\": {\n\t\t\"@bf6mods/portal\": \"*\",\n\t\t\"@bf6mods/sdk\": \"*\",\n\t\t\"@clack/prompts\": \"^0.11.0\",\n\t\t\"chokidar\": \"^4.0.3\",\n\t\t\"colors\": \"^1.4.0\",\n\t\t\"commander\": \"^14.0.1\",\n\t\t\"import-global\": \"^1.1.1\",\n\t\t\"jiti\": \"^2.6.1\",\n\t\t\"keytar\": \"^7.9.0\",\n\t\t\"knitwork\": \"^1.2.0\",\n\t\t\"rolldown\": \"^1.0.0-beta.44\",\n\t\t\"sharp\": \"^0.34.5\",\n\t\t\"stringify-object\": \"^6.0.0\",\n\t\t\"strip-ansi\": \"^7.1.2\"\n\t},\n\t\"publishConfig\": {\n\t\t\"access\": \"public\"\n\t},\n\t\"devDependencies\": {\n\t\t\"@oxc-project/types\": \"^0.95.0\",\n\t\t\"@types/stringify-object\": \"^4.0.5\",\n\t\t\"cross-env\": \"^10.1.0\",\n\t\t\"execa\": \"^9.6.0\",\n\t\t\"puppeteer\": \"^24.27.0\",\n\t\t\"tsx\": \"^4.20.6\"\n\t}\n}\n","import type { ConfigType } from \"@bf6mods/sdk\";\n\nexport enum MapId {\n\tSiegeOfCairo = \"MP_Abbasid-ModBuilderCustom0\",\n\tEmpireState = \"MP_Aftermath-ModBuilderCustom0\",\n\tBlackwellFields = \"MP_Badlands-ModBuilderCustom0\",\n\tIberianOffensive = \"MP_Battery-ModBuilderCustom0\",\n\tLiberationPeak = \"MP_Capstone-ModBuilderCustom0\",\n\tManhattanBridge = \"MP_Dumbo-ModBuilderCustom0\",\n\tEastwoord = \"MP_Eastwood-ModBuilderCustom0\",\n\tFireStorm = \"MP_FireStorm-ModBuilderCustom0\",\n\tSaintsQuarter = \"MP_Limestone-ModBuilderCustom0\",\n\tNewSobekCity = \"MP_Outskirts-ModBuilderCustom0\",\n\tMirakValley = \"MP_Tungsten-ModBuilderCustom0\",\n\tGolfCourse = \"MP_Granite_ClubHouse_Portal-ModBuilderCustom0\",\n\tDefenseNexus = \"MP_Granite_TechCampus_Portal-ModBuilderCustom0\",\n\tPortalSandbox = \"MP_Portal_Sand-ModBuilderCustom0\",\n\tMarina = \"MP_Granite_Marina_Portal-ModBuilderCustom0\",\n\tDowntown = \"MP_Granite_MainStreet_Portal-ModBuilderCustom0\",\n\tArea22B = \"MP_Granite_MilitaryRnD_Portal-ModBuilderCustom0\",\n\tRedlineStorage = \"MP_Granite_MilitaryStorage_Portal-ModBuilderCustom0\",\n}\n\n/**\n * Represents the root configuration for a Battlefield 6 mod project.\n *\n * This file combines both build-level settings (like entrypoints and output directories)\n * and in-game configuration data (such as mutators and asset restrictions)\n * under the `game` key.\n *\n * Use {@link defineBf6Config} to define and validate this structure\n * in your `bf6.config.ts` file.\n */\nexport type Bf6Config = {\n\t/**\n\t * The unique identifier of your mod experience.\n\t *\n\t * You can find this ID in the URL when editing your experience:\n\t * [https://portal.battlefield.com/bf6/experience/settings/mode?id=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx](https://portal.battlefield.com/bf6/experience/settings/mode?id=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)\n\t *\n\t * This ID is referenced when deploying your mod using:\n\t * npx \\@bf6mods/cli deploy\n\t */\n\tid?: string;\n\n\t/**\n\t * The human-readable name of the mod.\n\t *\n\t * Typically matches the project name used in the BF6 mod editor or\n\t * the display name shown in the in-game mod browser.\n\t */\n\tname: string;\n\n\t/**\n\t * A short description of the mod’s purpose or content.\n\t * Used for display and metadata purposes.\n\t */\n\tdescription: string;\n\n\t/**\n\t * The output directory where compiled or bundled files are written.\n\t * Usually something like `\"dist\"` or `\"build\"`.\n\t */\n\toutDir: string;\n\n\t/**\n\t * Whether or not to output the built files like the entrypoint typescript file\n\t */\n\toutputArtifacts?: boolean;\n\n\t/**\n\t * The main entrypoint for your mod’s TypeScript source file.\n\t *\n\t * This is typically something like `\"src/index.ts\"` or `\"src/main.ts\"`.\n\t */\n\tentrypoint?: string;\n\n\t/**\n\t * One or more scene file paths (.json) that the mod includes.\n\t * If no file path is provided, it loads in the default spatial data.\n\t */\n\tscenes?: ([MapId, string] | MapId)[];\n\n\t/**\n\t * Path to a JSON file or other source that defines localized strings\n\t * used by the mod (optional).\n\t */\n\tstrings?: string;\n\n\t/**\n\t * Generate strings automatically, by default this is enabled\n\t */\n\tgenerateStrings?: boolean;\n\n\t/**\n\t * Path to a thumbnail image for the mod.\n\t *\n\t * The image must meet BF6 Portal requirements:\n\t * - Max file size: 78KB\n\t * - Dimensions: 352x248 pixels\n\t * - Format: JPEG or PNG\n\t *\n\t * @example\n\t * ```ts\n\t * thumbnail: \"assets/thumbnail.png\"\n\t * // or\n\t * thumbnail: \"thumbnail.jpg\"\n\t * ```\n\t */\n\tthumbnail?: string;\n\n\t/**\n\t * Controls whether build output should be minified.\n\t *\n\t * Can be a boolean (to toggle all minification),\n\t * or an object specifying independent settings for JS and JSON files.\n\t *\n\t * @example\n\t * ```ts\n\t * minify: true\n\t * // or\n\t * minify: { js: true, json: false }\n\t * ```\n\t */\n\tminify?:\n\t\t| {\n\t\t\t\t/** Whether to minify JavaScript output. */\n\t\t\t\tjs?: boolean;\n\t\t\t\t/** Whether to minify JSON output. */\n\t\t\t\tjson?: boolean;\n\t\t }\n\t\t/** Enables or disables all minification. */\n\t\t| boolean;\n\n\t/**\n\t * The underlying in-game configuration derived from `ConfigType`\n\t * in the BF6 SDK. Includes gameplay-level details like mutators,\n\t * asset restrictions, and team compositions.\n\t *\n\t * The following properties are **excluded**:\n\t * - `attachments`\n\t * - `workspace`\n\t * - `mapRotation`\n\t * - `name`\n\t * - `description`\n\t *\n\t * since those are either redundant or handled elsewhere.\n\t */\n\tgame: Omit<\n\t\tConfigType,\n\t\t\"attachments\" | \"workspace\" | \"mapRotation\" | \"name\" | \"description\"\n\t>;\n};\n\n/**\n * Defines and validates a Battlefield 6 mod configuration object.\n *\n * This helper ensures your config is properly typed and can be\n * statically analyzed by TypeScript.\n *\n * @example\n * ```ts\n * export default defineBf6Config({\n * name: \"My Custom Mod\",\n * description: \"Adds custom rules\",\n * outDir: \"dist\",\n * entrypoint: \"src/main.ts\",\n * game: {\n * mutators: [],\n * assetRestrictions: {},\n * teamComposition: [],\n * },\n * });\n * ```\n *\n * @param bf6Config The configuration object to validate and return.\n * @returns The validated Battlefield 6 configuration object.\n */\nexport function defineBf6Config(bf6Config: Bf6Config): Bf6Config {\n\treturn bf6Config;\n}\n","import colors from \"colors\";\nimport stripAnsi from \"strip-ansi\";\n\n/**\n * Safely prints a message with a right-aligned timestamp.\n */\nexport const printToConsole = (message: string, error: boolean = false) => {\n\tconst now = new Date();\n\tconst formattedTime = colors.grey(now.toLocaleTimeString());\n\tconst terminalWidth = process.stdout.columns || 80;\n\n\tconst timeLength = stripAnsi(formattedTime).length;\n\tconst messageLength = stripAnsi(message).length;\n\tconst available = terminalWidth - (messageLength + timeLength);\n\n\tconst spacing = available > 1 ? \" \".repeat(available) : \" \";\n\n\tif (error) console.error(`${message}${spacing}${formattedTime}`);\n\telse console.log(`${message}${spacing}${formattedTime}`);\n};\n\nexport const readableList = (initialValues: readonly string[]) => {\n\tconst values = initialValues.map((v) => `\"${v}\"`);\n\tif (values.length > 1)\n\t\treturn `${values.slice(0, -1).join(\", \")} or ${values.slice(-1)}`;\n\treturn values[0];\n};\n","import type { Node } from \"@oxc-project/types\";\nimport type { Plugin } from \"rolldown\";\n\nexport function addAnyToParams(): Plugin {\n\treturn {\n\t\tname: \"add-any-to-params\",\n\t\tgenerateBundle(_options, bundle) {\n\t\t\tfor (const [_file, output] of Object.entries(bundle)) {\n\t\t\t\tif (output.type !== \"chunk\") continue;\n\n\t\t\t\tconst program = this.parse(output.code, {\n\t\t\t\t\tlang: \"js\",\n\t\t\t\t\tastType: \"js\",\n\t\t\t\t\trange: true,\n\t\t\t\t});\n\n\t\t\t\tconst edits: { pos: number; insert: string }[] = [];\n\n\t\t\t\tfunction walk(node: Node) {\n\t\t\t\t\tif (!node || typeof node !== \"object\") return;\n\n\t\t\t\t\t// Arrow/function params are just Identifiers or Patterns in JS AST\n\t\t\t\t\tif (\n\t\t\t\t\t\tnode.type === \"FunctionDeclaration\" ||\n\t\t\t\t\t\tnode.type === \"FunctionExpression\" ||\n\t\t\t\t\t\tnode.type === \"ArrowFunctionExpression\"\n\t\t\t\t\t) {\n\t\t\t\t\t\tfor (const param of node.params) {\n\t\t\t\t\t\t\tif (param.type === \"Identifier\" && param.range) {\n\t\t\t\t\t\t\t\tedits.push({ pos: param.range[1], insert: \": any\" });\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\tparam.type === \"AssignmentPattern\" &&\n\t\t\t\t\t\t\t\tparam.left?.type === \"Identifier\" &&\n\t\t\t\t\t\t\t\tparam.left.range\n\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\tedits.push({ pos: param.left.range[1], insert: \": any\" });\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\tparam.type === \"RestElement\" &&\n\t\t\t\t\t\t\t\tparam.argument?.type === \"Identifier\" &&\n\t\t\t\t\t\t\t\tparam.argument.range\n\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\tedits.push({ pos: param.argument.range[1], insert: \": any\" });\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t// Add ObjectPattern / ArrayPattern handling if needed\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tfor (const val of Object.values(node)) {\n\t\t\t\t\t\tif (Array.isArray(val)) val.forEach(walk);\n\t\t\t\t\t\telse if (val && typeof val === \"object\" && \"type\" in val) walk(val);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tfor (const item of program.body) walk(item);\n\n\t\t\t\tedits.sort((a, b) => b.pos - a.pos);\n\t\t\t\tlet result = output.code;\n\t\t\t\tfor (const edit of edits) {\n\t\t\t\t\tresult =\n\t\t\t\t\t\tresult.slice(0, edit.pos) + edit.insert + result.slice(edit.pos);\n\t\t\t\t}\n\n\t\t\t\toutput.code = result;\n\t\t\t}\n\t\t},\n\t};\n}\n","import type { Node, VariableDeclarator } from \"@oxc-project/types\";\nimport colors from \"colors\";\nimport type { Plugin } from \"rolldown\";\n\nexport function extractBf6Strings(\n\tbf6Strings: Record<string, string>,\n\tgenerateFromLiterals: boolean,\n): Plugin {\n\treturn {\n\t\tname: \"extract-bf6-strings\",\n\t\tgenerateBundle(_options, bundle) {\n\t\t\tif (!generateFromLiterals) return;\n\n\t\t\tlet id = 0;\n\t\t\tconst existingStrings = new Set(Object.values(bf6Strings));\n\n\t\t\tfor (const [_file, output] of Object.entries(bundle)) {\n\t\t\t\tif (output.type !== \"chunk\") continue;\n\t\t\t\tconst code = output.code;\n\n\t\t\t\t// Parse the code with rolldown’s parser\n\t\t\t\tconst program = this.parse(code, {\n\t\t\t\t\tlang: \"ts\",\n\t\t\t\t\tastType: \"js\",\n\t\t\t\t\trange: true,\n\t\t\t\t});\n\n\t\t\t\t// Visit every node recursively to collect string literals\n\t\t\t\tfunction walk(node: Node) {\n\t\t\t\t\tif (node.type === \"Literal\") {\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\ttypeof node.value !== \"string\" ||\n\t\t\t\t\t\t\tnode.value === \"\" ||\n\t\t\t\t\t\t\tnode.value === \"----uniquename----\"\n\t\t\t\t\t\t)\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t!(node.value in bf6Strings) &&\n\t\t\t\t\t\t\t!existingStrings.has(node.value)\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\texistingStrings.add(node.value);\n\t\t\t\t\t\t\tbf6Strings[`__auto__${id++}`] = node.value;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tfor (const value of Object.values(node)) {\n\t\t\t\t\t\tif (!value) continue;\n\t\t\t\t\t\tif (Array.isArray(value)) {\n\t\t\t\t\t\t\tfor (const v of value) {\n\t\t\t\t\t\t\t\tif (v && typeof v === \"object\" && \"type\" in v) walk(v as Node);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else if (typeof value === \"object\" && \"type\" in value) {\n\t\t\t\t\t\t\twalk(value as Node);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tfor (const item of program.body) {\n\t\t\t\t\twalk(item);\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tmoduleParsed(moduleInfo) {\n\t\t\tif (moduleInfo.code && moduleInfo.exports.includes(\"bf6Strings\")) {\n\t\t\t\tconst code = moduleInfo.code;\n\t\t\t\tconst getSnippet = (\n\t\t\t\t\tstart: number,\n\t\t\t\t\tend: number,\n\t\t\t\t\tlinesBefore = 2,\n\t\t\t\t\tlinesAfter = 2,\n\t\t\t\t) => {\n\t\t\t\t\tconst lines = code.split(/\\r?\\n/);\n\t\t\t\t\tconst startLine = Math.max(\n\t\t\t\t\t\t0,\n\t\t\t\t\t\tcode.slice(0, start).split(/\\r?\\n/).length - 1 - linesBefore,\n\t\t\t\t\t);\n\t\t\t\t\tconst endLine = Math.min(\n\t\t\t\t\t\tlines.length,\n\t\t\t\t\t\tcode.slice(0, end).split(/\\r?\\n/).length - 1 + linesAfter,\n\t\t\t\t\t);\n\t\t\t\t\treturn lines\n\t\t\t\t\t\t.slice(startLine, endLine)\n\t\t\t\t\t\t.map((line, i) => {\n\t\t\t\t\t\t\tconst actualLine = startLine + i + 1;\n\t\t\t\t\t\t\treturn `${actualLine.toString().padStart(3)} | ${line}`;\n\t\t\t\t\t\t})\n\t\t\t\t\t\t.join(\"\\n\");\n\t\t\t\t};\n\n\t\t\t\tconst program = this.parse(code, {\n\t\t\t\t\tlang: \"ts\",\n\t\t\t\t\tastType: \"js\",\n\t\t\t\t\trange: true,\n\t\t\t\t});\n\n\t\t\t\tconst extractObjectLiteral = (declaration: VariableDeclarator) => {\n\t\t\t\t\tif (declaration.init?.type !== \"ObjectExpression\") {\n\t\t\t\t\t\tconst snippet = getSnippet(...(declaration.range ?? [0, 0]));\n\t\t\t\t\t\tthis.error(\n\t\t\t\t\t\t\t`${colors.red.bold(\"✗\")} Invalid bf6Strings export: expected an object literal.\\n\\n${snippet}`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\n\t\t\t\t\tfor (const property of declaration.init.properties) {\n\t\t\t\t\t\tif (property.type !== \"Property\") {\n\t\t\t\t\t\t\tconst snippet = getSnippet(...(property.range ?? [0, 0]));\n\t\t\t\t\t\t\tthis.error(\n\t\t\t\t\t\t\t\t`${colors.red.bold(\"✗\")} Invalid bf6Strings property: expected a key/value pair.\\nFound type: ${property.type}\\n\\n${snippet}`,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tlet key:\n\t\t\t\t\t\t\t| string\n\t\t\t\t\t\t\t| number\n\t\t\t\t\t\t\t| bigint\n\t\t\t\t\t\t\t| boolean\n\t\t\t\t\t\t\t| RegExp\n\t\t\t\t\t\t\t| null\n\t\t\t\t\t\t\t| undefined;\n\t\t\t\t\t\tif (property.key.type === \"Literal\") {\n\t\t\t\t\t\t\tkey = property.key.value;\n\t\t\t\t\t\t} else if (property.key.type === \"Identifier\") {\n\t\t\t\t\t\t\tkey = property.key.name;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tconst snippet = getSnippet(...(property.range ?? [0, 0]));\n\t\t\t\t\t\t\tthis.error(\n\t\t\t\t\t\t\t\t`${colors.red.bold(\"✗\")} Invalid bf6Strings key: expected a string literal or identifier.\\nFound type: ${property.key.type}\\n\\n${snippet}`,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (property.value.type !== \"Literal\") {\n\t\t\t\t\t\t\tconst snippet = getSnippet(...(property.range ?? [0, 0]));\n\t\t\t\t\t\t\tthis.error(\n\t\t\t\t\t\t\t\t`${colors.red.bold(\"✗\")} Invalid bf6Strings value: expected a string literal.\\nFound type: ${property.value.type}\\n\\n${snippet}`,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst value = property.value.value;\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\ttypeof key !== \"string\" &&\n\t\t\t\t\t\t\ttypeof key !== \"number\" &&\n\t\t\t\t\t\t\ttypeof key !== \"bigint\" &&\n\t\t\t\t\t\t\ttypeof key !== \"boolean\"\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\tconst snippet = getSnippet(...(property.range ?? [0, 0]));\n\t\t\t\t\t\t\tthis.error(\n\t\t\t\t\t\t\t\t`${colors.red.bold(\"✗\")} bf6Strings key must be a string, found: ${typeof key}\\n\\n${snippet}`,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\ttypeof value !== \"string\" &&\n\t\t\t\t\t\t\ttypeof value !== \"number\" &&\n\t\t\t\t\t\t\ttypeof value !== \"bigint\" &&\n\t\t\t\t\t\t\ttypeof value !== \"boolean\"\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\tconst snippet = getSnippet(...(property.range ?? [0, 0]));\n\t\t\t\t\t\t\tthis.error(\n\t\t\t\t\t\t\t\t`${colors.red.bold(\"✗\")} bf6Strings value must be a string, found: ${typeof value}\\n\\n${snippet}`,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tbf6Strings[`${key}`] = `${value}`;\n\t\t\t\t\t}\n\t\t\t\t};\n\n\t\t\t\tfor (const item of program.body) {\n\t\t\t\t\t// Case 1: plain variable `var bf6Strings = {...}`\n\t\t\t\t\tif (item.type === \"VariableDeclaration\") {\n\t\t\t\t\t\tfor (const declaration of item.declarations) {\n\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\tdeclaration.type === \"VariableDeclarator\" &&\n\t\t\t\t\t\t\t\tdeclaration.id.type === \"Identifier\" &&\n\t\t\t\t\t\t\t\tdeclaration.id.name === \"bf6Strings\"\n\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\textractObjectLiteral(declaration);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Case 2: exported variable `export const bf6Strings = {...}`\n\t\t\t\t\tif (\n\t\t\t\t\t\titem.type === \"ExportNamedDeclaration\" &&\n\t\t\t\t\t\titem.declaration?.type === \"VariableDeclaration\"\n\t\t\t\t\t) {\n\t\t\t\t\t\tfor (const declaration of item.declaration.declarations) {\n\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\tdeclaration.type === \"VariableDeclarator\" &&\n\t\t\t\t\t\t\t\tdeclaration.id.type === \"Identifier\" &&\n\t\t\t\t\t\t\t\tdeclaration.id.name === \"bf6Strings\"\n\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\textractObjectLiteral(declaration);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t};\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport colors from \"colors\";\nimport sharp from \"sharp\";\nimport { printToConsole } from \"../utils.ts\";\n\n/**\n * BF6 Portal thumbnail requirements:\n * - Max file size: 78KB\n * - Dimensions: 352x248 pixels\n * - Format: JPEG or PNG\n */\nexport const THUMBNAIL_REQUIREMENTS = {\n\tmaxSizeBytes: 78 * 1024, // 78KB\n\twidth: 352,\n\theight: 248,\n\tsupportedFormats: [\".jpg\", \".jpeg\", \".png\"],\n} as const;\n\n/**\n * Validates that an image buffer meets BF6 Portal requirements\n */\nexport function validateThumbnail(\n\tbuffer: Buffer,\n\tfilename: string,\n): { valid: boolean; errors: string[] } {\n\tconst errors: string[] = [];\n\n\t// Check file size\n\tif (buffer.length > THUMBNAIL_REQUIREMENTS.maxSizeBytes) {\n\t\terrors.push(\n\t\t\t`File size is ${(buffer.length / 1024).toFixed(2)}KB, must be less than 78KB`,\n\t\t);\n\t}\n\n\t// Check file format\n\tconst ext = path.extname(filename).toLowerCase();\n\tif (\n\t\t!THUMBNAIL_REQUIREMENTS.supportedFormats.includes(\n\t\t\text as (typeof THUMBNAIL_REQUIREMENTS.supportedFormats)[number],\n\t\t)\n\t) {\n\t\terrors.push(\n\t\t\t`File format ${ext} is not supported. Must be ${THUMBNAIL_REQUIREMENTS.supportedFormats.join(\" or \")}`,\n\t\t);\n\t}\n\n\t// Check image dimensions using basic image header parsing\n\tconst dimensions = getImageDimensions(buffer, ext);\n\tif (dimensions) {\n\t\tif (\n\t\t\tdimensions.width !== THUMBNAIL_REQUIREMENTS.width ||\n\t\t\tdimensions.height !== THUMBNAIL_REQUIREMENTS.height\n\t\t) {\n\t\t\terrors.push(\n\t\t\t\t`Image dimensions are ${dimensions.width}x${dimensions.height}, must be ${THUMBNAIL_REQUIREMENTS.width}x${THUMBNAIL_REQUIREMENTS.height}`,\n\t\t\t);\n\t\t}\n\t}\n\n\treturn { valid: errors.length === 0, errors };\n}\n\n/**\n * Gets image dimensions from buffer by reading image headers\n */\nfunction getImageDimensions(\n\tbuffer: Buffer,\n\text: string,\n): { width: number; height: number } | null {\n\ttry {\n\t\tif (ext === \".png\") {\n\t\t\t// PNG: Read IHDR chunk (bytes 16-23 contain width and height)\n\t\t\tif (buffer.length >= 24 && buffer.toString(\"ascii\", 1, 4) === \"PNG\") {\n\t\t\t\tconst width = buffer.readUInt32BE(16);\n\t\t\t\tconst height = buffer.readUInt32BE(20);\n\t\t\t\treturn { width, height };\n\t\t\t}\n\t\t} else if (ext === \".jpg\" || ext === \".jpeg\") {\n\t\t\t// JPEG: Parse SOF (Start of Frame) marker\n\t\t\tlet offset = 2; // Skip initial 0xFFD8\n\t\t\twhile (offset < buffer.length) {\n\t\t\t\t// Find marker\n\t\t\t\tif (buffer[offset] !== 0xff) break;\n\t\t\t\tconst marker = buffer[offset + 1];\n\t\t\t\toffset += 2;\n\n\t\t\t\t// SOF markers (0xC0-0xCF except 0xC4, 0xC8, 0xCC)\n\t\t\t\tif (\n\t\t\t\t\tmarker >= 0xc0 &&\n\t\t\t\t\tmarker <= 0xcf &&\n\t\t\t\t\tmarker !== 0xc4 &&\n\t\t\t\t\tmarker !== 0xc8 &&\n\t\t\t\t\tmarker !== 0xcc\n\t\t\t\t) {\n\t\t\t\t\t// Height is at offset+3, width at offset+5 (both 2 bytes, big-endian)\n\t\t\t\t\tconst height = buffer.readUInt16BE(offset + 3);\n\t\t\t\t\tconst width = buffer.readUInt16BE(offset + 5);\n\t\t\t\t\treturn { width, height };\n\t\t\t\t}\n\n\t\t\t\t// Skip segment\n\t\t\t\tconst segmentLength = buffer.readUInt16BE(offset);\n\t\t\t\toffset += segmentLength;\n\t\t\t}\n\t\t}\n\t} catch (_error) {\n\t\t// Failed to parse dimensions\n\t}\n\treturn null;\n}\n\n/**\n * Processes a thumbnail file for BF6 Portal\n * Saves the resized thumbnail to the output directory\n */\nexport async function processThumbnail(\n\tthumbnailPath: string,\n\tworkingDir: string,\n\toutDir: string,\n): Promise<boolean> {\n\tconst fullPath = path.resolve(workingDir, thumbnailPath);\n\n\tif (!fs.existsSync(fullPath)) {\n\t\tprintToConsole(\n\t\t\tcolors.yellow(`⚠️ Thumbnail file not found: ${thumbnailPath}`),\n\t\t);\n\t\treturn false;\n\t}\n\n\tlet buffer: Buffer = await fs.promises.readFile(fullPath);\n\tconst filename = path.basename(fullPath);\n\tconst ext = path.extname(fullPath);\n\n\t// Validate thumbnail\n\tconst validation = validateThumbnail(buffer, filename);\n\tif (!validation.valid) {\n\t\tprintToConsole(\n\t\t\tcolors.yellow(\n\t\t\t\t`⚠️ Thumbnail doesn't meet requirements, attempting to resize and optimize...`,\n\t\t\t),\n\t\t);\n\n\t\t// Attempt to resize and optimize\n\t\ttry {\n\t\t\tbuffer = Buffer.from(await resizeThumbnail(buffer, fullPath));\n\t\t\tprintToConsole(\n\t\t\t\tcolors.green(\n\t\t\t\t\t`✓ Thumbnail resized and optimized: ${filename} (${(buffer.length / 1024).toFixed(2)}KB)`,\n\t\t\t\t),\n\t\t\t);\n\t\t} catch (error) {\n\t\t\tprintToConsole(\n\t\t\t\tcolors.red(\n\t\t\t\t\t`✗ Failed to resize thumbnail: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n\t\t\t\t),\n\t\t\t);\n\t\t\tprintToConsole(\n\t\t\t\tcolors.yellow(\n\t\t\t\t\t`\\nThumbnail requirements:\\n - Size: max 78KB\\n - Dimensions: 352x248 pixels\\n - Format: JPEG or PNG`,\n\t\t\t\t),\n\t\t\t);\n\t\t\treturn false;\n\t\t}\n\t} else {\n\t\tprintToConsole(\n\t\t\t`${colors.green.bold(\"✓\")} Thumbnail validated: ${filename} (${(buffer.length / 1024).toFixed(2)}KB)`,\n\t\t);\n\t}\n\n\t// Save to output directory with standardized name\n\tconst outputPath = path.resolve(outDir, `thumbnail${ext}`);\n\tawait fs.promises.writeFile(outputPath, buffer);\n\tprintToConsole(\n\t\tcolors.green(\n\t\t\t`✓ Thumbnail saved to: ${path.relative(workingDir, outputPath)}`,\n\t\t),\n\t);\n\n\treturn true;\n}\n\n/**\n * Resizes and optimizes an image to meet BF6 Portal thumbnail requirements\n */\nexport async function resizeThumbnail(\n\tbuffer: Buffer,\n\toriginalPath: string,\n): Promise<Buffer> {\n\tconst ext = path.extname(originalPath).toLowerCase();\n\tconst isJpeg = ext === \".jpg\" || ext === \".jpeg\";\n\n\t// Start with target dimensions\n\tlet result = await sharp(buffer)\n\t\t.resize(THUMBNAIL_REQUIREMENTS.width, THUMBNAIL_REQUIREMENTS.height, {\n\t\t\tfit: \"cover\",\n\t\t\tposition: \"center\",\n\t\t})\n\t\t.toBuffer();\n\n\t// If it's a JPEG or we need to convert to JPEG for size optimization\n\tif (isJpeg || result.length > THUMBNAIL_REQUIREMENTS.maxSizeBytes) {\n\t\t// Try with progressive quality reduction\n\t\tfor (let quality = 90; quality >= 60; quality -= 10) {\n\t\t\tresult = await sharp(buffer)\n\t\t\t\t.resize(THUMBNAIL_REQUIREMENTS.width, THUMBNAIL_REQUIREMENTS.height, {\n\t\t\t\t\tfit: \"cover\",\n\t\t\t\t\tposition: \"center\",\n\t\t\t\t})\n\t\t\t\t.jpeg({ quality, progressive: true })\n\t\t\t\t.toBuffer();\n\n\t\t\tif (result.length <= THUMBNAIL_REQUIREMENTS.maxSizeBytes) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t} else {\n\t\t// For PNG, try optimization\n\t\tresult = await sharp(buffer)\n\t\t\t.resize(THUMBNAIL_REQUIREMENTS.width, THUMBNAIL_REQUIREMENTS.height, {\n\t\t\t\tfit: \"cover\",\n\t\t\t\tposition: \"center\",\n\t\t\t})\n\t\t\t.png({ compressionLevel: 9, quality: 90 })\n\t\t\t.toBuffer();\n\t}\n\n\t// Final check\n\tif (result.length > THUMBNAIL_REQUIREMENTS.maxSizeBytes) {\n\t\tthrow new Error(\n\t\t\t`Unable to compress image below 78KB (current: ${(result.length / 1024).toFixed(2)}KB). Try using a simpler image or pre-compressing it.`,\n\t\t);\n\t}\n\n\treturn result;\n}\n\n/**\n * Helper to create a data URL from base64 thumbnail data\n */\nexport function createThumbnailDataUrl(\n\tbase64: string,\n\tformat: \"png\" | \"jpeg\",\n): string {\n\tconst mimeType = format === \"png\" ? \"image/png\" : \"image/jpeg\";\n\treturn `data:${mimeType};base64,${base64}`;\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport {\n\ttype Attachment,\n\tAttachmentType,\n\ttype ConfigType,\n\ttype MapType,\n} from \"@bf6mods/sdk\";\nimport colors from \"colors\";\nimport { createJiti } from \"jiti\";\nimport { rolldown } from \"rolldown\";\nimport {\n\ttype Bf6Config,\n\tMapId as MapIdEnum,\n} from \"../../resources/prepare/types/config.ts\";\nimport { printToConsole } from \"../utils.ts\";\nimport { addAnyToParams } from \"./any-params.ts\";\nimport { extractBf6Strings } from \"./generated-strings.ts\";\nimport { processThumbnail } from \"./thumbnail.ts\";\n\ndeclare global {\n\tvar defineBf6Config: ((config: Bf6Config) => Bf6Config) | undefined;\n\tvar MapId: typeof MapIdEnum | undefined;\n}\n\n/**\n * Dynamically imports and validates bf6.config.ts\n */\nexport async function getBf6Config(\n\trootDir: string,\n): Promise<Bf6Config | undefined> {\n\ttry {\n\t\tglobalThis.defineBf6Config = (c) => c;\n\t\tglobalThis.MapId = MapIdEnum;\n\t\tconst jiti = createJiti(rootDir, { interopDefault: true });\n\t\tconst result = await jiti.import(\"./bf6.config\", { default: true });\n\t\tdelete globalThis.defineBf6Config;\n\t\tdelete globalThis.MapId;\n\t\treturn result as Bf6Config;\n\t} catch (_error) {\n\t\treturn;\n\t}\n}\n\n/**\n * Builds the entire mod project once (for production or single run).\n */\nexport async function build() {\n\tconst workingDir = path.resolve(\".\");\n\tconst config = await getBf6Config(workingDir);\n\tif (!config) throw new Error(\"Cannot find bf6.config.ts!\");\n\n\tconst outDir = path.resolve(workingDir, config.outDir);\n\tif (fs.existsSync(outDir))\n\t\tfs.rmSync(outDir, { recursive: true, force: true });\n\tfs.mkdirSync(outDir, { recursive: true });\n\n\tconst minifyJson =\n\t\ttypeof config.minify === \"boolean\"\n\t\t\t? config.minify\n\t\t\t: (config.minify?.json ?? false);\n\n\tconst generatedStrings = {};\n\tlet tsAttachment: Attachment | undefined;\n\tif (config.entrypoint) {\n\t\tconst entryAbs = path.resolve(workingDir, config.entrypoint);\n\t\tconst compiled = await buildEntrypoint(\n\t\t\tentryAbs,\n\t\t\tgeneratedStrings,\n\t\t\tconfig.generateStrings ?? true,\n\t\t);\n\t\ttsAttachment = createTsAttachment(entryAbs, compiled);\n\t}\n\n\tconst { attachments, mapRotation } = await collectAttachments(\n\t\tconfig,\n\t\tworkingDir,\n\t\ttsAttachment,\n\t\tgeneratedStrings,\n\t);\n\n\t// Process thumbnail if provided (saves to outDir)\n\tif (config.thumbnail) {\n\t\tawait processThumbnail(config.thumbnail, workingDir, outDir);\n\t}\n\n\tawait writeModJson(config, outDir, attachments, mapRotation, minifyJson);\n\tprintToConsole(`${colors.green.bold(\"✓\")} Built mod: ${config.name}`);\n}\n\n/**\n * Compiles the TypeScript entrypoint using rolldown and returns the compiled code.\n */\nexport async function buildEntrypoint(\n\tentry: string,\n\tbf6Strings: Record<string, string>,\n\tgenerateStringsFromLiterals: boolean,\n): Promise<string> {\n\tconst bundle = await rolldown({\n\t\tinput: entry,\n\t\tplugins: [\n\t\t\textractBf6Strings(bf6Strings, generateStringsFromLiterals),\n\t\t\taddAnyToParams(),\n\t\t],\n\t\tlogLevel: \"debug\",\n\t\tresolve: {\n\t\t\talias: {\n\t\t\t\tmodlib: \"@bf6mods/sdk\",\n\t\t\t},\n\t\t},\n\t});\n\tconst result = await bundle.generate({\n\t\tformat: \"esm\",\n\t\tinlineDynamicImports: true,\n\t});\n\n\treturn result.output[0].code;\n}\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\nconst spatialsDir = path.resolve(__dirname, \"../resources/maps/spatial\");\n/**\n * Collects all attachments (TS, scenes, strings) and returns them + mapRotation.\n */\nexport async function collectAttachments(\n\tconfig: Bf6Config,\n\tworkingDir: string,\n\ttsAttachment: Attachment | undefined,\n\tgeneratedStrings: Record<string, number | string> | undefined,\n) {\n\tconst attachments: Attachment[] = [];\n\tconst mapRotation: MapType[] = [];\n\n\tif (tsAttachment) attachments.push(tsAttachment);\n\n\t// Strings\n\tif (config.strings || Object.keys(generatedStrings ?? {}).length > 0) {\n\t\tconst strPath = path.resolve(workingDir, config.strings ?? \"strings.json\");\n\t\tlet raw = \"{}\";\n\t\tif (fs.existsSync(strPath)) {\n\t\t\traw = await fs.promises.readFile(strPath, \"utf8\");\n\t\t} else {\n\t\t\t// Create a placeholder for clarity (optional)\n\t\t\tprintToConsole(\n\t\t\t\tcolors.yellow(\n\t\t\t\t\t`⚠️ No strings.json found, generating from literals only.`,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\n\t\tconst attachment = createStringsAttachment(strPath, raw, generatedStrings);\n\t\tattachments.push(attachment);\n\t}\n\n\t// Scenes\n\tif (config.scenes) {\n\t\tlet mapIdx = 0;\n\t\tfor (const map of config.scenes) {\n\t\t\tlet mapId: MapIdEnum;\n\t\t\tlet scene: string;\n\t\t\tif (Array.isArray(map)) {\n\t\t\t\t[mapId, scene] = map;\n\t\t\t} else {\n\t\t\t\tmapId = map;\n\t\t\t\tscene = path.resolve(spatialsDir, `${mapId}.spatial.json`);\n\t\t\t}\n\n\t\t\tconst scenePath = path.resolve(workingDir, scene);\n\t\t\tif (!fs.existsSync(scenePath))\n\t\t\t\tthrow new Error(`Cannot find spatial data file: ${scene}`);\n\t\t\tconst raw = await fs.promises.readFile(scenePath, \"utf8\");\n\t\t\tconst spatial = createSpatialAttachment(scenePath, raw, mapIdx++);\n\t\t\tattachments.push(spatial);\n\t\t\tmapRotation.push({ id: mapId, spatialAttachment: spatial });\n\t\t}\n\t}\n\n\treturn { attachments, mapRotation };\n}\n\n/**\n * Writes the mod.json output to disk.\n */\nexport async function writeModJson(\n\tconfig: Bf6Config,\n\toutDir: string,\n\tattachments: ConfigType[\"attachments\"],\n\tmapRotation: MapType[],\n\tminify: boolean,\n) {\n\tconst baseGame = config.game;\n\tconst finalJson: ConfigType = {\n\t\tname: config.name,\n\t\tdescription: config.description,\n\t\tgameMode: \"ModBuilderCustom\",\n\t\tmutators: baseGame.mutators ?? {},\n\t\tassetRestrictions: baseGame.assetRestrictions ?? {},\n\t\tteamComposition: baseGame.teamComposition ?? [],\n\t\tmapRotation,\n\t\tattachments,\n\t};\n\n\tconst jsonOutput = minify\n\t\t? JSON.stringify(finalJson)\n\t\t: JSON.stringify(finalJson, null, 2);\n\tawait fs.promises.writeFile(path.resolve(outDir, \"mod.json\"), jsonOutput);\n\n\tif (config.outputArtifacts && finalJson?.attachments) {\n\t\tfor (const attachment of finalJson.attachments) {\n\t\t\tconst attachmentsDir = path.resolve(outDir, \"attachments\");\n\t\t\tif (!fs.existsSync(attachmentsDir))\n\t\t\t\tfs.mkdirSync(attachmentsDir, {\n\t\t\t\t\trecursive: true,\n\t\t\t\t});\n\t\t\tawait fs.promises.writeFile(\n\t\t\t\tpath.resolve(outDir, \"attachments\", attachment.filename),\n\t\t\t\tatob(attachment.attachmentData.original),\n\t\t\t);\n\t\t}\n\t}\n}\n\nexport function createTsAttachment(\n\tfilePath: string,\n\tcompiled: string,\n): Attachment {\n\treturn {\n\t\tid: crypto.randomUUID(),\n\t\tversion: \"1.0\",\n\t\tfilename: `${path.parse(filePath).name}.ts`,\n\t\tisProcessable: true,\n\t\tprocessingStatus: 2,\n\t\tattachmentType: AttachmentType.TypeScript,\n\t\tattachmentData: { original: toBase64(compiled), compiled: \"\" },\n\t\terrors: [],\n\t};\n}\n\nexport function createStringsAttachment(\n\tfilePath: string,\n\traw: string,\n\tgeneratedStrings?: Record<string, number | string> | undefined,\n): Attachment {\n\tlet result = raw;\n\tif (generatedStrings) {\n\t\tresult = JSON.stringify(\n\t\t\t{\n\t\t\t\t...generatedStrings,\n\t\t\t\t...JSON.parse(raw),\n\t\t\t},\n\t\t\tnull,\n\t\t\t4,\n\t\t);\n\t}\n\n\treturn {\n\t\tid: crypto.randomUUID(),\n\t\tversion: \"1.0\",\n\t\tfilename: path.basename(filePath),\n\t\tisProcessable: true,\n\t\tprocessingStatus: 2,\n\t\tattachmentType: AttachmentType.Strings,\n\t\tattachmentData: { original: toBase64(result), compiled: \"\" },\n\t\terrors: [],\n\t};\n}\n\nexport function createSpatialAttachment(\n\tfilePath: string,\n\traw: string,\n\tmapIdx: number,\n): MapType[\"spatialAttachment\"] {\n\treturn {\n\t\tid: crypto.randomUUID(),\n\t\tversion: \"1.0\",\n\t\tfilename: path.basename(filePath),\n\t\tisProcessable: true,\n\t\tprocessingStatus: 2,\n\t\tattachmentType: AttachmentType.SpatialData,\n\t\tattachmentData: { original: toBase64(raw), compiled: \"\" },\n\t\tmetadata: `mapIdx=${mapIdx}`,\n\t\terrors: [],\n\t};\n}\n\nexport function toBase64(input: string | Buffer): string {\n\treturn Buffer.isBuffer(input)\n\t\t? input.toString(\"base64\")\n\t\t: Buffer.from(input, \"utf8\").toString(\"base64\");\n}\n","import os from \"node:os\";\nimport path from \"node:path\";\nimport colors from \"colors\";\nimport keytar from \"keytar\";\nimport { printToConsole } from \"../utils.ts\";\nimport { clients } from \"./index.ts\";\n\nexport type PuppeteerImport = typeof import(\"puppeteer\");\n\nexport async function getSessionIdFromCookies() {\n\tlet puppeteer: PuppeteerImport;\n\ttry {\n\t\tpuppeteer = (await import(\"puppeteer\")) as unknown as PuppeteerImport;\n\t} catch (_error) {\n\t\tprintToConsole(`${colors.red.bold(\"✗\")} Puppeteer could not be loaded.`);\n\t\tconsole.error(\n\t\t\t\"It looks like Puppeteer is not installed in this environment.\",\n\t\t);\n\t\tconsole.error(\n\t\t\t`${colors.green.bold(\"✓\")} Fix: install Puppeteer locally in the CLI package:`,\n\t\t);\n\t\tconsole.error(\"\t npm i -g puppeteer\");\n\t\tconsole.error(\"\\nIf you prefer not to install a browser automation tool,\");\n\t\tconsole.error(\n\t\t\t\"you can instead provide an auth code using the --auth-code option:\",\n\t\t);\n\t\tconsole.error(\"\t bf6mods deploy <input> --auth-code=<code>\\n\");\n\t\tprocess.exit(0);\n\t}\n\n\tconst profileDir = path.join(os.homedir(), \".bf6mods-browser\");\n\n\tconst browser = await puppeteer.launch({\n\t\theadless: false,\n\t\tdefaultViewport: null,\n\t\tuserDataDir: profileDir,\n\t});\n\tconst page = await browser.newPage();\n\tawait page.goto(\"https://portal.battlefield.com/bf6/experiences\");\n\tconsole.log(\"Please log in to Battlefield Portal if needed...\");\n\n\t// Poll for bf6sessionId cookie\n\tawait page.waitForFunction(\n\t\t() => {\n\t\t\treturn document.cookie.includes(\"bf6sessionId\");\n\t\t},\n\t\t{ timeout: 0 },\n\t); // no timeout, wait as long as needed\n\n\tconsole.log(`${colors.green.bold(\"✓\")} Login detected!`);\n\n\tconst cookies = await browser.cookies();\n\tawait browser.close();\n\n\treturn cookies.find((cookie) => cookie.name === \"bf6sessionId\")?.value;\n}\n\nexport async function tryAuthenticateWithSessionId(sessionId: string) {\n\tawait clients.authenticate({\n\t\tsessionId,\n\t});\n\n\ttry {\n\t\tawait clients.play.getProgressionTypes({});\n\t} catch (error) {\n\t\tif (!(error instanceof Error)) return false;\n\t\tif (error.message === \"[unauthenticated]\") return false;\n\t}\n\n\treturn true;\n}\n\nexport async function authenticate(sessionIdParam?: string) {\n\tprintToConsole(`🔑 Attempting authentication…`);\n\n\tif (sessionIdParam) {\n\t\tif (await tryAuthenticateWithSessionId(sessionIdParam)) {\n\t\t\tawait keytar.setPassword(\"bf6mods\", \"sessionId\", sessionIdParam);\n\t\t\treturn true;\n\t\t}\n\t\tprintToConsole(\n\t\t\t`${colors.red(\"✗\")} Provided sessionId is invalid, ignoring…`,\n\t\t);\n\t}\n\n\tconst storedSessionId = await keytar.getPassword(\"bf6mods\", \"sessionId\");\n\tif (storedSessionId) {\n\t\tif (await tryAuthenticateWithSessionId(storedSessionId)) {\n\t\t\treturn true;\n\t\t}\n\t\tprintToConsole(`${colors.yellow(\"⚠\")} Stored sessionId expired, removing…`);\n\t\tawait keytar.deletePassword(\"bf6mods\", \"sessionId\");\n\t}\n\n\tprintToConsole(`🌐 Launching browser to authenticate…`);\n\tconst cookieSessionId = await getSessionIdFromCookies();\n\n\tif (!cookieSessionId) {\n\t\tprintToConsole(\n\t\t\t`${colors.red(\"✗\")} Failed to retrieve Battlefield session, exiting.`,\n\t\t\ttrue,\n\t\t);\n\t\treturn false;\n\t}\n\n\tif (await tryAuthenticateWithSessionId(cookieSessionId)) {\n\t\tawait keytar.setPassword(\"bf6mods\", \"sessionId\", cookieSessionId);\n\t\treturn true;\n\t}\n\n\tprintToConsole(\n\t\t`${colors.red(\"✗\")} Authentication failed. Session may have expired immediately.`,\n\t\ttrue,\n\t);\n\n\treturn false;\n}\n\nexport async function alwaysAuthenticatedRequest<T>(\n\tmethod: () => Promise<T> | T,\n\tsessionId: string | undefined,\n): Promise<T> {\n\ttry {\n\t\treturn await method();\n\t} catch (error) {\n\t\tif (error instanceof Error && error.message === \"[unauthenticated]\") {\n\t\t\tprintToConsole(\"🔄 Session expired. Re-authenticating…\");\n\t\t\tconst success = await authenticate(sessionId);\n\t\t\tif (!success) throw error;\n\t\t\treturn await method();\n\t\t}\n\t\tthrow error;\n\t}\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { Clients, Generated_pb } from \"@bf6mods/portal\";\nimport type { ConfigType } from \"@bf6mods/sdk\";\nimport colors from \"colors\";\nimport { getBf6Config } from \"../build/index.ts\";\nimport { printToConsole } from \"../utils.ts\";\nimport { alwaysAuthenticatedRequest } from \"./authenticate.ts\";\n\nexport const clients = new Clients();\n\nexport async function deploy({\n\tinput,\n\tsessionIdParam,\n\tmodId,\n}: {\n\tinput?: string;\n\tsessionIdParam?: string;\n\tpublish?: boolean;\n\tmodId?: string;\n}) {\n\tconst rootDir = path.resolve(\".\");\n\tif (!input) input = path.resolve(rootDir, \"dist\", \"mod.json\");\n\tprintToConsole(`🚀 Starting deploy for ${colors.cyan(input)}…`);\n\tif (!fs.existsSync(input))\n\t\treturn printToConsole(\n\t\t\t`${colors.red.bold(\"✗\")} File ${colors.cyan(input)} does not exist!`,\n\t\t\ttrue,\n\t\t);\n\tconst mod = JSON.parse(\n\t\tfs.readFileSync(input, { encoding: \"utf-8\" }),\n\t) as ConfigType;\n\n\tconst blueprints = await alwaysAuthenticatedRequest(\n\t\t() => clients.play.getScheduledBlueprints({}),\n\t\tsessionIdParam,\n\t);\n\tconsole.log(\"blueprints\", blueprints.blueprintIds);\n\n\tconst _blueprint = await alwaysAuthenticatedRequest(\n\t\t() =>\n\t\t\tclients.play.getBlueprintsById({\n\t\t\t\tblueprintIds: blueprints.blueprintIds,\n\t\t\t}),\n\t\tsessionIdParam,\n\t);\n\n\tconst config = await getBf6Config(rootDir);\n\n\tlet id: string | undefined = modId;\n\tif (!config)\n\t\tprintToConsole(\n\t\t\t`Cannot find bf6mods config in dir ${rootDir}, proceeding without it.`,\n\t\t);\n\telse if (config?.id) id = config.id;\n\telse {\n\t\tprintToConsole(\n\t\t\t`No id specified in bf6.config.ts! Defaulting to experience with same name!`,\n\t\t);\n\t}\n\n\tif (!id) {\n\t\tconst owned = await alwaysAuthenticatedRequest(\n\t\t\t() =>\n\t\t\t\tclients.play.getOwnedPlayElementsV2({\n\t\t\t\t\tincludeDenied: true,\n\t\t\t\t\tpublishStates: [\n\t\t\t\t\t\tGenerated_pb.PublishStateType.Draft,\n\t\t\t\t\t\tGenerated_pb.PublishStateType.Published,\n\t\t\t\t\t\tGenerated_pb.PublishStateType.Error,\n\t\t\t\t\t],\n\t\t\t\t}),\n\t\t\tsessionIdParam,\n\t\t);\n\t\tconsole.log(\n\t\t\t\"owned:\",\n\t\t\towned.playElements.map((owned) => owned.playElement),\n\t\t);\n\t\tconst found = owned.playElements.find(\n\t\t\t(element) => element?.playElement?.name === mod.name,\n\t\t);\n\t\tif (found?.playElement?.id) id = found.playElement.id;\n\t}\n\n\tif (!id) {\n\t\tprintToConsole(\n\t\t\t`${colors.red.bold(\"✗\")} Cannot find an id for your mod to deploy with! Please specify the id explicitly with \\`--id\\` or by having a mod with the same name!`,\n\t\t);\n\t\tprocess.exit(0);\n\t}\n\n\tconst playElementResponse = await alwaysAuthenticatedRequest(\n\t\t() =>\n\t\t\tclients.play.getPlayElement({\n\t\t\t\tid,\n\t\t\t\tincludeDenied: true,\n\t\t\t}),\n\t\tsessionIdParam,\n\t);\n\n\tif (\n\t\t!playElementResponse.playElement ||\n\t\t!playElementResponse.playElementDesign ||\n\t\t!playElementResponse.progressionMode\n\t)\n\t\tthrow new Error(\n\t\t\t\"Cannot find essential attribute in mod, please report to GitHub!\",\n\t\t);\n\n\tif (!mod.mapRotation) throw new Error(\"You must specify at least one map!\");\n\n\tconsole.log(\"playElementResponse:\", playElementResponse);\n\n\tconst thumbnailExtensions = [\".jpg\", \".jpeg\", \".png\"];\n\tlet thumbnailPath: string | undefined;\n\tlet thumbnailExt: string | undefined;\n\n\tfor (const ext of thumbnailExtensions) {\n\t\tconst testPath = path.resolve(rootDir, \"dist\", `thumbnail${ext}`);\n\t\tif (fs.existsSync(testPath)) {\n\t\t\tthumbnailPath = testPath;\n\t\t\tthumbnailExt = ext;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tif (thumbnailPath && thumbnailExt) {\n\t\ttry {\n\t\t\tprintToConsole(colors.blue(\"📸 Uploading thumbnail...\"));\n\t\t\tconst thumbnailBuffer = await fs.promises.readFile(thumbnailPath);\n\n\t\t\tconst mimeType = thumbnailExt === \".png\" ? \"image/png\" : \"image/jpeg\";\n\n\t\t\tconst uploadResponse = await alwaysAuthenticatedRequest(\n\t\t\t\t() =>\n\t\t\t\t\tclients.play.uploadExperienceThumbnail({\n\t\t\t\t\t\timage: thumbnailBuffer,\n\t\t\t\t\t\tmimeType,\n\t\t\t\t\t}),\n\t\t\t\tsessionIdParam,\n\t\t\t);\n\t\t\tprintToConsole(\n\t\t\t\tcolors.green(\n\t\t\t\t\t`✓ Thumbnail uploaded successfully: ${uploadResponse.assetId}`,\n\t\t\t\t),\n\t\t\t);\n\t\t\tprintToConsole(colors.dim(` URL: ${uploadResponse.url}`));\n\t\t} catch (error) {\n\t\t\tprintToConsole(\n\t\t\t\tcolors.yellow(\n\t\t\t\t\t`⚠ Failed to upload thumbnail: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n\t\t\t\t),\n\t\t\t);\n\t\t\tprintToConsole(colors.dim(\" Continuing deployment without thumbnail\"));\n\t\t}\n\t} else {\n\t\tprintToConsole(\n\t\t\tcolors.dim(\" No thumbnail found in dist folder, skipping upload\"),\n\t\t);\n\t}\n\n\t// buildSaveExperiencePayload(mod, blueprint.blueprints[0], playElementResponse as Required<typeof playElementResponse>)\n\n\t// console.log('tags', blueprint.blueprints[0].availableProgressionModeTags?.tags)\n\n\t// clients.play.updatePlayElement({\n\t// \tname: mod.name,\n\t// \tdescription: mod.description,\n\t// \tmapRotation: {\n\t// \t\tmaps: mod.mapRotation?.map((map) => {\n\t// \t\t\tconst mapData = blueprint.blueprints[0].availableGameData?.maps.find(\n\t// \t\t\t\t(availableMap) =>\n\t// \t\t\t\t\t`${availableMap.levelName}-${availableMap.levelName}` === map.id,\n\t// \t\t\t);\n\t// \t\t\tif (!mapData)\n\t// \t\t\t\tthrow new Error(\n\t// \t\t\t\t\t`Unable to deploy, due to map not being found. Please create a GitHub issue.${blueprint.blueprints}`,\n\t// \t\t\t\t);\n\t// \t\t\treturn {\n\t// \t\t\t\tlevelName: mapData.levelName,\n\t// \t\t\t\tlevelLocation: mapData.levelLocation,\n\t// \t\t\t\trounds: 1,\n\t// \t\t\t\tallowedSpectators: mapData.allowedSpectators,\n\t// \t\t\t\tmutators: [], // unknown as to what this does\n\t// \t\t\t\tteamComposition: {\n\t// \t\t\t\t\tteams: mod.teamComposition?.map((team) => ({\n\t// \t\t\t\t\t\tteamId: team[0],\n\t// \t\t\t\t\t\tcapacity: team[1]?.aiCapacity ?? 0 + team[1].humanCapacity,\n\t// \t\t\t\t\t})),\n\t// \t\t\t\t\tinternalTeams: mod.teamComposition?.map((team) => ({\n\t// \t\t\t\t\t\tteamId: team[0],\n\t// \t\t\t\t\t\tcapacity: 0,\n\t// \t\t\t\t\t\tcapacityTyppe: 0,\n\t// \t\t\t\t\t})),\n\t// \t\t\t\t},\n\t// \t\t\t} as Omit<Generated_pb.MapEntry, \"$typeName\">;\n\t// \t\t}),\n\t// \t\tattributes: {\n\t// \t\t\trotationBehavior: Generated_pb.RotationBehavior.LOOP,\n\t// \t\t},\n\t// \t},\n\t// })\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport chokidar, { type FSWatcher } from \"chokidar\";\nimport colors from \"colors\";\nimport { printToConsole } from \"./utils.ts\";\n\nexport class Bf6Logger {\n\tprivate static instance: Bf6Logger | undefined;\n\n\tprivate watchTarget: string;\n\tprivate watcher?: FSWatcher;\n\tprivate lastSize: number;\n\n\tconstructor(input?: string) {\n\t\tif (Bf6Logger.instance) {\n\t\t\tprintToConsole(\n\t\t\t\tcolors.yellow(\"⚠ Existing logger found — closing it first...\"),\n\t\t\t);\n\t\t\tBf6Logger.instance.stop();\n\t\t}\n\n\t\tif (input) this.watchTarget = path.resolve(input);\n\t\telse if (process.env.LOCALAPPDATA)\n\t\t\tthis.watchTarget = path.resolve(\n\t\t\t\tprocess.env.LOCALAPPDATA,\n\t\t\t\t\"temp\",\n\t\t\t\t\"Battlefieldâ„¢ 6\",\n\t\t\t\t\"PortalLog.txt\",\n\t\t\t);\n\t\telse\n\t\t\tthrow new Error(\n\t\t\t\t`${colors.red.bold(\"✗\")} Env variable LOCALAPPDATA not defined, and input file to watch was not provided!`,\n\t\t\t);\n\n\t\tif (!fs.existsSync(this.watchTarget))\n\t\t\tthrow new Error(\n\t\t\t\t`${colors.red.bold(\"✗\")} Cannot find file '${this.watchTarget}' to watch for changes`,\n\t\t\t);\n\n\t\tthis.lastSize = fs.statSync(this.watchTarget).size;\n\t\tBf6Logger.instance = this;\n\t}\n\n\tasync start() {\n\t\tprintToConsole(\n\t\t\tcolors.cyan(\n\t\t\t\t`👀 Watching Battlefield logs at: ${colors.yellow(this.watchTarget)}`,\n\t\t\t),\n\t\t);\n\n\t\tthis.watcher = chokidar.watch(this.watchTarget, {\n\t\t\tpersistent: true,\n\t\t\tignoreInitial: true,\n\t\t});\n\n\t\tthis.watcher.on(\"change\", this.handleChange.bind(this));\n\t}\n\n\tasync stop() {\n\t\tif (this.watcher) {\n\t\t\tthis.watcher.close();\n\t\t\tthis.watcher = undefined;\n\t\t\tprintToConsole(\n\t\t\t\tcolors.yellow(\n\t\t\t\t\t`${colors.red.bold(\"✗\")} Stopped watching: ${colors.gray(this.watchTarget)}`,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t\tBf6Logger.instance = undefined;\n\t}\n\n\tprivate handleChange(file: string, stats?: fs.Stats) {\n\t\tif (!stats) return;\n\t\tif (stats.size > this.lastSize) {\n\t\t\tconst newBytes = stats.size - this.lastSize;\n\t\t\tconst fd = fs.openSync(file, \"r\");\n\t\t\tconst buffer = Buffer.alloc(newBytes);\n\t\t\tfs.readSync(fd, buffer, 0, newBytes, this.lastSize);\n\t\t\tfs.closeSync(fd);\n\n\t\t\tconst newContent = buffer\n\t\t\t\t.toString(\"utf8\")\n\t\t\t\t.split(\"QuickJS: \")\n\t\t\t\t.filter((debug) => debug.trim() !== \"\")\n\t\t\t\t.map((debug) => debug.trim())\n\t\t\t\t.map((debug) => {\n\t\t\t\t\tif (debug.startsWith(\"console.log: \")) {\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\ttype: \"console.log\",\n\t\t\t\t\t\t\ttext: debug.replace(\"console.log: \", \"\"),\n\t\t\t\t\t\t};\n\t\t\t\t\t} else if (debug.startsWith(\"Exception:\")) {\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\ttype: \"exception\",\n\t\t\t\t\t\t\ttext: debug.replace(\"Exception:\", \"\"),\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\n\t\t\t\t\treturn {\n\t\t\t\t\t\ttype: \"unknown\",\n\t\t\t\t\t\ttext: debug,\n\t\t\t\t\t};\n\t\t\t\t});\n\n\t\t\tfor (const content of newContent) {\n\t\t\t\tif (content.type === \"console.log\")\n\t\t\t\t\tprintToConsole(colors.gray(content.text));\n\t\t\t\telse if (content.type === \"exception\")\n\t\t\t\t\tprintToConsole(colors.red(content.text), true);\n\t\t\t\telse printToConsole(colors.bold(content.text));\n\t\t\t}\n\t\t}\n\t\tthis.lastSize = stats.size;\n\t}\n}\n","import fs from \"node:fs\";\nimport { glob } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport chokidar, { type FSWatcher } from \"chokidar\";\nimport colors from \"colors\";\nimport type { Bf6Config } from \"../resources/prepare/types/config.ts\";\nimport { build, getBf6Config } from \"./build/index.ts\";\nimport { Bf6Logger } from \"./log.ts\";\nimport { printToConsole } from \"./utils.ts\";\n\nexport async function dev() {\n\tconst workingDir = path.resolve(\".\");\n\tconst config = await getBf6Config(workingDir);\n\tif (!config) throw new Error(\"Cannot find bf6.config.ts!\");\n\tconst outDir = path.resolve(workingDir, config.outDir);\n\tfs.mkdirSync(outDir, { recursive: true });\n\n\tprintToConsole(colors.cyan(`▶ Starting dev for ${config.name}`));\n\n\tlet watcher: FSWatcher | undefined;\n\n\t// biome-ignore lint/suspicious/noExplicitAny: doesn't really matter in this case\n\tfunction debounce<T extends (...args: any[]) => void>(fn: T, delay: number) {\n\t\tlet timer: NodeJS.Timeout | undefined;\n\t\treturn (...args: Parameters<T>) => {\n\t\t\tif (timer) clearTimeout(timer);\n\t\t\ttimer = setTimeout(() => fn(...args), delay);\n\t\t};\n\t}\n\n\tconst rebuild = async (trigger: string) => {\n\t\tprintToConsole(\n\t\t\tcolors.yellow(\n\t\t\t\t`↻ Change detected in ${path.basename(trigger)}, rebuilding...`,\n\t\t\t),\n\t\t);\n\t\tconst start = performance.now();\n\t\ttry {\n\t\t\tawait build();\n\t\t\tconst duration = ((performance.now() - start) / 1000).toFixed(2);\n\t\t\tprintToConsole(\n\t\t\t\t`${colors.green.bold(\"✓\")} Updated mod.json (${duration}s)`,\n\t\t\t);\n\t\t} catch (err) {\n\t\t\tprintToConsole(\n\t\t\t\tcolors.red(\n\t\t\t\t\t`${colors.red.bold(\"✗\")} Rebuild failed: ${(err as Error).message}`,\n\t\t\t\t),\n\t\t\t\ttrue,\n\t\t\t);\n\t\t}\n\t};\n\n\tconst debouncedRebuild = debounce(rebuild, 200);\n\n\tasync function collectWatchTargets(config: Bf6Config): Promise<string[]> {\n\t\tconst targets: string[] = [];\n\n\t\tif (config.entrypoint)\n\t\t\ttargets.push(path.resolve(workingDir, config.entrypoint));\n\t\tif (config.scenes)\n\t\t\tfor (const [, scene] of config.scenes)\n\t\t\t\ttargets.push(path.resolve(workingDir, scene));\n\t\tif (config.strings) targets.push(path.resolve(workingDir, config.strings));\n\t\tfor await (const entry of glob(\"bf6.config.*\")) targets.push(entry);\n\t\tfor await (const entry of glob(\"src/**/*\")) targets.push(entry);\n\n\t\treturn targets;\n\t}\n\n\tasync function setupWatcher(config: Bf6Config) {\n\t\tif (watcher) {\n\t\t\tawait watcher.close();\n\t\t\tprintToConsole(\n\t\t\t\tcolors.grey(\"♻ Reloading watcher due to config change...\"),\n\t\t\t);\n\t\t\tawait new Promise((r) => setTimeout(r, 10));\n\t\t}\n\n\t\tconst watchTargets = await collectWatchTargets(config);\n\t\tprintToConsole(colors.cyan(`👀 Watching ${watchTargets.length} files...`));\n\n\t\twatcher = chokidar.watch(watchTargets, {\n\t\t\tpersistent: true,\n\t\t\tignoreInitial: true,\n\t\t\tawaitWriteFinish: { stabilityThreshold: 250, pollInterval: 100 },\n\t\t\tignored: [outDir, `${outDir}/**`, \"node_modules/**\", \".git/**\"],\n\t\t});\n\n\t\twatcher.on(\"error\", (err) => {\n\t\t\tprintToConsole(\n\t\t\t\tcolors.red(`⚠ Watcher error: ${(err as Error).message}`),\n\t\t\t\ttrue,\n\t\t\t);\n\t\t\tsetTimeout(setupWatcher, 1000);\n\t\t});\n\n\t\twatcher.on(\"change\", async (file) => {\n\t\t\tif (file.includes(\"bf6.config.\")) {\n\t\t\t\tprintToConsole(\n\t\t\t\t\tcolors.magenta(\"⚙ Config changed — reloading watcher...\"),\n\t\t\t\t);\n\t\t\t\tconst newConfig = await getBf6Config(workingDir);\n\t\t\t\tif (!newConfig) throw new Error(\"Cannot find bf6.config.ts!\");\n\t\t\t\tawait setupWatcher(newConfig);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tdebouncedRebuild(file);\n\t\t});\n\n\t\twatcher.on(\"add\", debouncedRebuild);\n\t\tawait rebuild(\"initial\");\n\t}\n\n\tprocess.on(\"SIGINT\", async () => {\n\t\tprintToConsole(colors.red(`\\n${colors.red.bold(\"✗\")} Exiting dev mode...`));\n\t\tawait watcher?.close();\n\t\tprocess.exit(0);\n\t});\n\n\tawait setupWatcher(config);\n\n\tlet logger: Bf6Logger | undefined;\n\ttry {\n\t\tlogger = new Bf6Logger();\n\t\tlogger.start();\n\t} catch (error) {\n\t\tprintToConsole(\n\t\t\tcolors.grey(\n\t\t\t\t\"Failed to start logging for the following reason (building will still work)\",\n\t\t\t),\n\t\t\ttrue,\n\t\t);\n\t\tprintToConsole((error as Error).message, true);\n\t}\n}\n","{\n\t\"name\": \"@bf6mods/sdk\",\n\t\"version\": \"1.7.0\",\n\t\"description\": \"TypeScript definitions for the BF6 modding API\",\n\t\"type\": \"module\",\n\t\"license\": \"MIT\",\n\t\"exports\": {\n\t\t\".\": {\n\t\t\t\"types\": \"./dist/index.d.ts\",\n\t\t\t\"import\": \"./dist/index.js\"\n\t\t},\n\t\t\"./std\": {\n\t\t\t\"types\": \"./dist/std/index.d.ts\",\n\t\t\t\"import\": \"./dist/std/index.js\"\n\t\t}\n\t},\n\t\"repository\": {\n\t\t\"type\": \"git\",\n\t\t\"url\": \"git+https://github.com/bf6mods/bf6mods.git\"\n\t},\n\t\"files\": [\n\t\t\"dist/\"\n\t],\n\t\"scripts\": {\n\t\t\"build\": \"tsdown\"\n\t},\n\t\"keywords\": [\n\t\t\"bf6\",\n\t\t\"mods\",\n\t\t\"typescript\",\n\t\t\"definitions\",\n\t\t\"api\"\n\t],\n\t\"publishConfig\": {\n\t\t\"access\": \"public\"\n\t}\n}\n","import child_process from \"node:child_process\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport * as prompts from \"@clack/prompts\";\nimport bf6SdkPackageJson from \"../../../sdk/package.json\" with { type: \"json\" };\nimport bf6CliPackageJson from \"../../package.json\" with { type: \"json\" };\nimport { importFile } from \"./import.ts\";\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\n\nconst templatesDir = path.resolve(__dirname, \"../resources/templates\");\n\nfunction renameFilesRecursively(dir: string, modName: string) {\n\tconst entries = fs.readdirSync(dir, { withFileTypes: true });\n\tfor (const entry of entries) {\n\t\tconst oldPath = path.join(dir, entry.name);\n\t\tlet newPath = oldPath;\n\n\t\t// Rename file or folder if it includes {name}\n\t\tif (entry.name.includes(\"{name}\")) {\n\t\t\tconst newName = entry.name.replace(\"{name}\", modName);\n\t\t\tnewPath = path.join(dir, newName);\n\t\t\tfs.renameSync(oldPath, newPath);\n\t\t}\n\n\t\t// If it's a bf6.config.ts, replace the {bf6ConfigName} placeholder\n\t\tif (entry.name === \"bf6.config.ts\") {\n\t\t\tlet content = fs.readFileSync(newPath, \"utf-8\");\n\t\t\tcontent = content.replace(/{bf6ConfigName}/g, modName);\n\t\t\tfs.writeFileSync(newPath, content, \"utf-8\");\n\t\t}\n\n\t\t// If it's a package.json, rewrite the \"name\" field\n\t\tif (entry.name === \"package.json\") {\n\t\t\tconst pkg = JSON.parse(fs.readFileSync(newPath, \"utf-8\"));\n\t\t\tpkg.name = modName;\n\t\t\tif (!pkg.devDependencies) pkg.devDependencies = {};\n\t\t\tpkg.devDependencies[\"@bf6mods/cli\"] = `^${bf6CliPackageJson.version}`;\n\t\t\tpkg.devDependencies[\"@bf6mods/sdk\"] = `^${bf6SdkPackageJson.version}`;\n\t\t\tfs.writeFileSync(newPath, JSON.stringify(pkg, null, 2));\n\t\t}\n\n\t\t// Recurse into directories (using the new name if renamed)\n\t\tif (fs.statSync(newPath).isDirectory()) {\n\t\t\trenameFilesRecursively(newPath, modName);\n\t\t}\n\t}\n}\n\nexport const templates = [\n\t\"Basic\",\n\t\"Complete\",\n\t\"AcePursuit\",\n\t\"Exfil\",\n\t\"Vertigo\",\n] as const;\n\nexport async function startProject(\n\tdestination: string,\n\ttemplate: (typeof templates)[number] | \"None\",\n\tname?: string,\n) {\n\tif ([\"AcePursuit\", \"Exfil\", \"Vertigo\"].includes(template)) {\n\t\tconst importPath = path.resolve(templatesDir, `${template}.json`);\n\t\tawait importFile(importPath, destination, name);\n\t} else if (template === \"None\") {\n\t\t// Do nothing if none\n\t} else {\n\t\t// Handles the Basic and any other template provided\n\t\tconst templateDir = path.resolve(templatesDir, template);\n\t\tfs.cpSync(templateDir, destination, { recursive: true });\n\t}\n\n\tfs.cpSync(path.resolve(templatesDir, \"All\"), destination, {\n\t\trecursive: true,\n\t});\n\n\tconst gitignorePath = path.join(destination, \"_gitignore\");\n\tconst dotGitignorePath = path.join(destination, \".gitignore\");\n\tif (fs.existsSync(gitignorePath)) {\n\t\tfs.renameSync(gitignorePath, dotGitignorePath);\n\t}\n\n\tif (name) renameFilesRecursively(destination, name);\n}\n\nexport function installDependencies(projectDir: string) {\n\ttry {\n\t\tchild_process.execSync(`npm install`, {\n\t\t\tstdio: \"inherit\",\n\t\t\tcwd: projectDir,\n\t\t});\n\t\treturn true;\n\t} catch (_err) {\n\t\treturn false;\n\t}\n}\n\nconst _defaultTargetDir = \"bf6-mod\";\nconst cancel = () => prompts.cancel(\"Operation cancelled\");\n\nfunction isEmpty(path: string) {\n\tconst files = fs.readdirSync(path);\n\treturn files.length === 0 || (files.length === 1 && files[0] === \".git\");\n}\n\nfunction emptyDir(dir: string) {\n\tif (!fs.existsSync(dir)) {\n\t\treturn;\n\t}\n\tfor (const file of fs.readdirSync(dir)) {\n\t\tif (file === \".git\") {\n\t\t\tcontinue;\n\t\t}\n\t\tfs.rmSync(path.resolve(dir, file), { recursive: true, force: true });\n\t}\n}\n\nexport async function init(\n\targTargetDir?: string,\n\toptions?: {\n\t\tname?: string;\n\t\ttemplate?: (typeof templates)[number];\n\t\tonExists?: \"overwrite\" | \"cancel\" | \"ignore\";\n\t\tinstallDependencies?: boolean;\n\t},\n) {\n\tprompts.intro(\"Initialize Bf6 Mod\");\n\n\tconst path = argTargetDir\n\t\t? argTargetDir\n\t\t: await prompts.text({\n\t\t\t\tmessage: \"Where should we create your project?\",\n\t\t\t\tplaceholder: \"./ace-pursuit\",\n\t\t\t\tvalidate: (value) => {\n\t\t\t\t\tif (!value) return \"Please enter a path.\";\n\t\t\t\t\tif (value[0] !== \".\") return \"Please enter a relative path.\";\n\t\t\t\t},\n\t\t\t});\n\tif (prompts.isCancel(path)) return cancel();\n\n\tlet name = options?.name\n\t\t? options.name\n\t\t: await prompts.text({\n\t\t\t\tmessage: \"What is the name of your mod?\",\n\t\t\t\tplaceholder: \"Ace Pursuit\",\n\t\t\t\tvalidate: (value) => {\n\t\t\t\t\tif (!value.trim()) return \"Please enter a name.\";\n\t\t\t\t},\n\t\t\t});\n\tif (prompts.isCancel(name)) return cancel();\n\tname = name.trim();\n\n\tif (fs.existsSync(path) && !isEmpty(path)) {\n\t\tlet overwrite: \"yes\" | \"no\" | \"ignore\" | undefined;\n\t\tif (options?.onExists) {\n\t\t\tswitch (options.onExists) {\n\t\t\t\tcase \"overwrite\":\n\t\t\t\t\toverwrite = \"yes\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"cancel\":\n\t\t\t\t\toverwrite = \"no\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"ignore\":\n\t\t\t\t\toverwrite = \"ignore\";\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tconst res = overwrite\n\t\t\t? overwrite\n\t\t\t: await prompts.select({\n\t\t\t\t\tmessage:\n\t\t\t\t\t\t(path === \".\"\n\t\t\t\t\t\t\t? \"Current directory\"\n\t\t\t\t\t\t\t: `Target directory \"${path}\"`) +\n\t\t\t\t\t\t` is not empty. Please choose how to proceed:`,\n\t\t\t\t\toptions: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tlabel: \"Cancel operation\",\n\t\t\t\t\t\t\tvalue: \"no\",\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tlabel: \"Remove existing files and continue\",\n\t\t\t\t\t\t\tvalue: \"yes\",\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tlabel: \"Ignore files and continue\",\n\t\t\t\t\t\t\tvalue: \"ignore\",\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t});\n\t\tif (prompts.isCancel(res)) return cancel();\n\t\toverwrite = res;\n\n\t\tswitch (overwrite) {\n\t\t\tcase \"yes\":\n\t\t\t\temptyDir(path);\n\t\t\t\tbreak;\n\t\t\tcase \"no\":\n\t\t\t\tcancel();\n\t\t\t\treturn;\n\t\t}\n\t}\n\n\tconst template = options?.template\n\t\t? options.template\n\t\t: await prompts.select({\n\t\t\t\tmessage: \"Select a template:\",\n\t\t\t\toptions: templates.map((template) => {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tlabel: template,\n\t\t\t\t\t\tvalue: template,\n\t\t\t\t\t};\n\t\t\t\t}),\n\t\t\t});\n\tif (prompts.isCancel(template)) return cancel();\n\n\tawait startProject(path, template, name);\n\n\tif (options?.installDependencies) {\n\t\tconst s = prompts.spinner();\n\t\ts.start(\"Installing via npm\");\n\t\tconst installed = installDependencies(path);\n\t\tif (installed) s.stop(\"Installed via npm\");\n\t\telse s.stop(\"Failed to install via npm\", 1);\n\n\t\tconst nextSteps = `cd ${path}\\nnpm run build`;\n\n\t\tprompts.note(nextSteps, \"Next steps.\");\n\t} else {\n\t\tconst nextSteps = `cd ${path}\\nnpm i\\nnpm run build`;\n\n\t\tprompts.note(nextSteps, \"Next steps.\");\n\t}\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { AttachmentType, type ConfigType } from \"@bf6mods/sdk\";\nimport colors from \"colors\";\nimport stringifyObject from \"stringify-object\";\nimport { MapId as MapIdEnum } from \"../resources/prepare/types/config.ts\";\nimport { startProject } from \"./init.ts\";\nimport { printToConsole } from \"./utils.ts\";\n\nasync function writeFileSafe(filePath: string, data: string | Buffer) {\n\tconst dir = path.dirname(filePath);\n\tawait fs.promises.mkdir(dir, { recursive: true });\n\tawait fs.promises.writeFile(filePath, data);\n}\n\nfunction getMapKeyByValue(value: string): keyof typeof MapIdEnum | undefined {\n\treturn Object.keys(MapIdEnum).find(\n\t\t(k) => MapIdEnum[k as keyof typeof MapIdEnum] === value,\n\t) as keyof typeof MapIdEnum | undefined;\n}\n\nexport async function importFile(\n\tinput: string,\n\toutput: string,\n\tname?: string,\n\tlogging = false,\n) {\n\tconst start = performance.now();\n\tconst workingDir = path.resolve(\".\");\n\tconst entrypoint = path.resolve(workingDir, input);\n\tconst outDir = path.resolve(workingDir, output);\n\n\tif (!fs.existsSync(entrypoint)) throw new Error(\"Cannot find strings file\");\n\n\tif (logging)\n\t\tprintToConsole(colors.cyan(`📦 Importing config from: ${entrypoint}`));\n\n\tconst config = JSON.parse(\n\t\tawait fs.promises.readFile(entrypoint, { encoding: \"utf8\" }),\n\t) as ConfigType;\n\n\tif (!fs.existsSync(outDir)) {\n\t\tawait fs.promises.mkdir(outDir, { recursive: true });\n\t\tif (logging)\n\t\t\tprintToConsole(colors.cyan(`📁 Created output directory: ${outDir}`));\n\t}\n\n\tawait startProject(outDir, \"None\", name ?? config.name);\n\n\tlet typescriptFile: string | undefined;\n\tlet stringsFile: string | undefined;\n\tconst scenes: [string, string][] = [];\n\tconst promises: Promise<unknown>[] = [];\n\n\tif (config.attachments) {\n\t\tlet unamedAttachmentIndex = 0;\n\t\tfor (const attachment of config.attachments) {\n\t\t\tlet filename = attachment.filename?.trim();\n\t\t\tif (!filename) {\n\t\t\t\tunamedAttachmentIndex++;\n\n\t\t\t\tlet ext: string = \"\";\n\t\t\t\tif (attachment.attachmentType === AttachmentType.TypeScript)\n\t\t\t\t\text = \".ts\";\n\t\t\t\telse if (attachment.attachmentType === AttachmentType.Strings)\n\t\t\t\t\text = \".strings.json\";\n\t\t\t\telse if (attachment.attachmentType === AttachmentType.SpatialData)\n\t\t\t\t\text = \".spatial.json\";\n\n\t\t\t\tif (unamedAttachmentIndex > 1)\n\t\t\t\t\tfilename = `attachment_${unamedAttachmentIndex}${ext}`;\n\t\t\t\telse filename = `attachment${ext}`;\n\t\t\t}\n\n\t\t\tif (attachment.attachmentType === AttachmentType.TypeScript)\n\t\t\t\ttypescriptFile = filename;\n\n\t\t\tif (attachment.attachmentType === AttachmentType.Strings)\n\t\t\t\tstringsFile = filename;\n\n\t\t\tif (attachment.attachmentType === AttachmentType.SpatialData) {\n\t\t\t\t// We'll just use the data attached to mapRotation instead\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tpromises.push(\n\t\t\t\twriteFileSafe(\n\t\t\t\t\tpath.resolve(outDir, \"src\", filename),\n\t\t\t\t\tatob(attachment.attachmentData.original),\n\t\t\t\t),\n\t\t\t);\n\n\t\t\tif (logging)\n\t\t\t\tprintToConsole(\n\t\t\t\t\t`${colors.green(\"✓\")} Wrote attachment: ${colors.yellow(filename)}`,\n\t\t\t\t);\n\t\t}\n\t}\n\n\t// Extract spatial scenes from mapRotation instead of guessing\n\tif (config.mapRotation?.length) {\n\t\tfor (const map of config.mapRotation) {\n\t\t\tpromises.push(\n\t\t\t\twriteFileSafe(\n\t\t\t\t\tpath.resolve(outDir, \"src\", \"scenes\", map.spatialAttachment.filename),\n\t\t\t\t\tatob(map.spatialAttachment.attachmentData.original),\n\t\t\t\t),\n\t\t\t);\n\n\t\t\tscenes.push([map.id, `src/scenes/${map.spatialAttachment.filename}`]);\n\n\t\t\tif (logging)\n\t\t\t\tprintToConsole(\n\t\t\t\t\t`${colors.green(\"✓\")} Added scene: ${colors.yellow(map.id)}`,\n\t\t\t\t);\n\t\t}\n\t}\n\n\t// build the new bf6.config.ts structure\n\tconst bf6Config = {\n\t\tname: name ?? config.name,\n\t\tdescription: config.description,\n\t\toutDir: \"dist\",\n\t\tentrypoint: typescriptFile ? `src/${typescriptFile}` : undefined,\n\t\tscenes: scenes\n\t\t\t? scenes.map(([id, path]) => [\n\t\t\t\t\t`MapId.${getMapKeyByValue(id) ?? id}`,\n\t\t\t\t\tpath,\n\t\t\t\t])\n\t\t\t: undefined,\n\t\tstrings: stringsFile ? `src/${stringsFile}` : undefined,\n\t\tgame: {\n\t\t\tmutators: config.mutators,\n\t\t\tassetRestrictions: config.assetRestrictions,\n\t\t\tgameMode: config.gameMode,\n\t\t\tteamComposition: config.teamComposition,\n\t\t},\n\t};\n\n\tconst bf6ConfigContent = `export default defineBf6Config(${stringifyWithRaw(\n\t\tbf6Config,\n\t)});\\n`;\n\n\tpromises.push(\n\t\twriteFileSafe(path.resolve(outDir, \"bf6.config.ts\"), bf6ConfigContent),\n\t);\n\n\tawait Promise.all(promises);\n\n\tconst duration = ((performance.now() - start) / 1000).toFixed(2);\n\tif (logging)\n\t\tprintToConsole(\n\t\t\t`${colors.green.bold(\"✓\")} Import complete (${duration}s) → ${colors.yellow(outDir)}`,\n\t\t);\n}\n\nfunction stringifyWithRaw(value: unknown, options = {}) {\n\treturn stringifyObject(value, {\n\t\tindent: \" \", // 4 spaces\n\t\tsingleQuotes: true,\n\t\ttransform: (_obj, _prop, originalResult) => {\n\t\t\t// Remove quotes from MapId.* expressions\n\t\t\tif (/^['\"]MapId\\.[A-Za-z0-9_]+['\"]$/.test(originalResult)) {\n\t\t\t\treturn originalResult.slice(1, -1); // remove surrounding quotes\n\t\t\t}\n\t\t\treturn originalResult;\n\t\t},\n\t\t...options,\n\t});\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport colors from \"colors\";\nimport { genExport, genInlineTypeImport } from \"knitwork\";\nimport { printToConsole } from \"./utils.js\";\n\nexport async function prepare() {\n\ttry {\n\t\tconst __filename = fileURLToPath(import.meta.url);\n\t\tconst __dirname = path.dirname(__filename);\n\n\t\tconst _workingDir = path.resolve(\".\");\n\t\tconst buildDir = path.resolve(\".bf6\");\n\n\t\tconst resources = path.resolve(__dirname, \"../resources/prepare\");\n\n\t\tfs.cpSync(\n\t\t\tpath.resolve(resources, \"tsconfig.json\"),\n\t\t\tpath.resolve(buildDir, \"tsconfig.json\"),\n\t\t);\n\t\tfs.cpSync(\n\t\t\tpath.resolve(resources, \"bf6.d.ts\"),\n\t\t\tpath.resolve(buildDir, \"bf6.d.ts\"),\n\t\t);\n\t\tfs.cpSync(\n\t\t\tpath.resolve(resources, \"types\", \"config.ts\"),\n\t\t\tpath.resolve(buildDir, \"types\", \"config.ts\"),\n\t\t);\n\n\t\tconst ConfigFileExports = genExport(\"./types/config.ts\", [\n\t\t\t\"defineBf6Config\",\n\t\t]);\n\t\tfs.writeFileSync(\n\t\t\tpath.resolve(buildDir, \"imports.d.ts\"),\n\t\t\t`${ConfigFileExports}\\n`,\n\t\t);\n\n\t\tconst augmentations: Record<string, string> = {\n\t\t\tdefineBf6Config: genInlineTypeImport(\n\t\t\t\t\"./types/config.ts\",\n\t\t\t\t`defineBf6Config`,\n\t\t\t),\n\t\t\tMapId: genInlineTypeImport(\"./types/config.ts\", `MapId`),\n\t\t};\n\n\t\tconst args = genNamespaceAugmentation(\"global\", augmentations);\n\t\tfs.writeFileSync(\n\t\t\tpath.resolve(buildDir, \"globals.d.ts\"),\n\t\t\t`export {}\\n\\n${args}\\n`,\n\t\t);\n\n\t\tprintToConsole(`${colors.green.bold(\"✓\")} Types generated in .bf6`);\n\t} catch (error) {\n\t\tconsole.error(error);\n\t\tprintToConsole(\n\t\t\t`${colors.red.bold(\"✗\")} Types failed to generate in .bf6`,\n\t\t\ttrue,\n\t\t);\n\t}\n}\n\nconst genNamespaceAugmentation = (\n\tname: string,\n\tcontents: Record<string, string>,\n) => {\n\tif (!contents || Object.keys(contents).length === 0)\n\t\treturn `declare ${name} {}`;\n\tconst decls = Object.entries(contents)\n\t\t.map(([k, v]) => `\\tconst ${k}: ${v};`)\n\t\t.join(\"\\n\");\n\treturn `declare ${name} {\\n${decls}\\n}`;\n};\n","#!/usr/bin/env node\nimport colors from \"colors\";\nimport { Command } from \"commander\";\nimport pkg from \"../../package.json\" with { type: \"json\" };\nimport { build } from \"./build/index.ts\";\nimport { deploy } from \"./deploy/index.ts\";\nimport { dev } from \"./dev.ts\";\nimport { importFile } from \"./import.ts\";\nimport { init, installDependencies, templates } from \"./init.js\";\nimport { Bf6Logger } from \"./log.ts\";\nimport { prepare } from \"./prepare.js\";\nimport { printToConsole, readableList } from \"./utils.ts\";\n\nconst program = new Command();\n\nprogram\n\t.name(Object.keys(pkg.bin)[0])\n\t.description(pkg.description)\n\t.version(pkg.version);\n\nprogram\n\t.command(\"init\")\n\t.argument(\"[directory]\")\n\t.option(\"--name <name>\", \"The name of your mod\")\n\t.option(\"--template <template>\", \"The template to use\")\n\t.option(\n\t\t\"--on-exists <action>\",\n\t\t`Either \"overwrite\", \"cancel\", or \"ignore\" as to what to do if files exist in the directory`,\n\t)\n\t.option(\"--no-install-dependencies\", `Prevents install of dependencies`)\n\t.description(\"Create a new bf6 mod\")\n\t.action(async (directory, options) => {\n\t\tconst { name, template, onExists, installDependencies } = options;\n\t\tif (\n\t\t\tonExists !== undefined &&\n\t\t\t![\"overwrite\", \"cancel\", \"ignore\"].includes(onExists)\n\t\t) {\n\t\t\tprintToConsole(\n\t\t\t\t`${colors.red.bold(\"✗\")} Invalid value for --on-exists: \"${onExists}\". Expected one of \"overwrite\", \"cancel\", or \"ignore\".`,\n\t\t\t\ttrue,\n\t\t\t);\n\t\t\tprocess.exit(1);\n\t\t}\n\t\tif (template !== undefined && !templates.includes(template)) {\n\t\t\tprintToConsole(\n\t\t\t\t`${colors.red.bold(\"✗\")} Invalid value for --template: \"${template}\". Expected one of ${readableList(templates)}.`,\n\t\t\t\ttrue,\n\t\t\t);\n\t\t\tprocess.exit(1);\n\t\t}\n\n\t\tawait init(directory, {\n\t\t\tname,\n\t\t\ttemplate,\n\t\t\tonExists,\n\t\t\tinstallDependencies,\n\t\t});\n\t});\n\nprogram\n\t.command(\"build\")\n\t.description(\"build the bf6 mod\")\n\t.action(async () => {\n\t\tawait build();\n\t});\n\nprogram\n\t.command(\"prepare\")\n\t.description(\"prepare the types for bf6 mod\")\n\t.action(async () => {\n\t\tawait prepare();\n\t});\n\nprogram\n\t.command(\"dev\")\n\t.description(\"watch the changes in src, and recompile as needed\")\n\t.action(async () => {\n\t\tawait dev();\n\t});\n\nprogram\n\t.command(\"import\")\n\t.argument(\"<input>\")\n\t.argument(\"<output>\")\n\t.option(\"--no-install-dependencies\", `Prevents install of dependencies`)\n\t.description(\"decompiles the json config of a mod into a new project\")\n\t.action(async (input, output, options: { installDependencies: boolean }) => {\n\t\tawait importFile(input as string, output as string, undefined, true);\n\t\tif (options?.installDependencies) installDependencies(output);\n\t});\n\nprogram\n\t.command(\"log\")\n\t.argument(\"[input]\")\n\t.description(\"logs the output from a locally running server\")\n\t.action(async (input) => {\n\t\tconst logger = new Bf6Logger(input);\n\t\tlogger.start();\n\t});\n\nprogram\n\t.command(\"deploy\")\n\t.argument(\"[input]\")\n\t.option(\n\t\t\"--session-id <session id>\",\n\t\t`The session id to use when deploying, should be web-xxxx`,\n\t)\n\t.option(\"--publish\", `Whether to publish your mod`)\n\t.option(\"--id <id>\", `The id of your mod`)\n\t.description(\n\t\t\"deploys your mod for you, if unauthenticated, it requests reauthentication\",\n\t)\n\t.action(async (input, options) => {\n\t\tawait deploy({\n\t\t\tinput,\n\t\t\tsessionIdParam: options?.sessionId,\n\t\t\tpublish: options?.publish,\n\t\t\tmodId: options?.id,\n\t\t});\n\t});\n\nprogram.exitOverride((_err) => {\n\tif (process.env.EXIT_CODE === \"none\") process.exit(0);\n});\n\nif (!process.argv.slice(2).length) {\n\tprogram.outputHelp();\n\tprocess.exit(0);\n}\n\nprogram.parse();\n"],"mappings":"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"}
|