@bf6mods/cli 1.0.2 → 1.1.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 +6 -1
- package/dist/cli/index.js +217 -25
- package/dist/cli/index.js.map +1 -1
- package/dist/resources/maps/spatial/MP_Abbasid-ModBuilderCustom0.spatial.json +218 -0
- package/dist/resources/maps/spatial/MP_Aftermath-ModBuilderCustom0.spatial.json +194 -0
- package/dist/resources/maps/spatial/MP_Battery-ModBuilderCustom0.spatial.json +249 -0
- package/dist/resources/maps/spatial/MP_Capstone-ModBuilderCustom0.spatial.json +189 -0
- package/dist/resources/maps/spatial/MP_Dumbo-ModBuilderCustom0.spatial.json +222 -0
- package/dist/resources/maps/spatial/MP_FireStorm-ModBuilderCustom0.spatial.json +197 -0
- package/dist/resources/maps/spatial/MP_Limestone-ModBuilderCustom0.spatial.json +226 -0
- package/dist/resources/maps/spatial/MP_Outskirts-ModBuilderCustom0.spatial.json +190 -0
- package/dist/resources/maps/spatial/MP_Tungsten-ModBuilderCustom0.spatial.json +206 -0
- package/dist/resources/prepare/types/config.ts +144 -145
- package/dist/resources/templates/All/package.json +2 -2
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -29,8 +29,9 @@ Just run `npm run build` in your project dir, open [portal.battlefield.com](http
|
|
|
29
29
|
- Use multiple different files, instead of just one large TypeScript file!
|
|
30
30
|
- Use a programatic interface for defining your gamemode.
|
|
31
31
|
- Extensive documentation
|
|
32
|
-
- Extended standard library
|
|
32
|
+
- Extended standard library (still in progress)
|
|
33
33
|
- Hot reload
|
|
34
|
+
- Automatic string injection
|
|
34
35
|
|
|
35
36
|
## Structure
|
|
36
37
|
|
|
@@ -70,3 +71,7 @@ export default defineBf6Config({
|
|
|
70
71
|
## @bf6mods/sdk
|
|
71
72
|
|
|
72
73
|
This is a seperate library that exports the `PortalSdk`'s `mod` and `modlib`. Additionally it exports some stdlib helper functions and classes to help accelerate development.
|
|
74
|
+
|
|
75
|
+
## Join the discord with fellow modders!
|
|
76
|
+
|
|
77
|
+
You can join the discord by clicking this [link](https://discord.gg/2gJ9fheYYK)!
|
package/dist/cli/index.js
CHANGED
|
@@ -6,7 +6,7 @@ import { Command } from "commander";
|
|
|
6
6
|
// package.json
|
|
7
7
|
var package_default = {
|
|
8
8
|
name: "@bf6mods/cli",
|
|
9
|
-
version: "1.0.
|
|
9
|
+
version: "1.0.2",
|
|
10
10
|
description: "CLI and library for bundling BF6 mods",
|
|
11
11
|
license: "MIT",
|
|
12
12
|
type: "module",
|
|
@@ -28,8 +28,12 @@ var package_default = {
|
|
|
28
28
|
files: [
|
|
29
29
|
"dist/"
|
|
30
30
|
],
|
|
31
|
+
repository: {
|
|
32
|
+
type: "git",
|
|
33
|
+
url: "git+https://github.com/bf6mods/bf6mods.git"
|
|
34
|
+
},
|
|
31
35
|
dependencies: {
|
|
32
|
-
"@bf6mods/sdk": "1.0.
|
|
36
|
+
"@bf6mods/sdk": "1.0.3",
|
|
33
37
|
"@clack/prompts": "^0.11.0",
|
|
34
38
|
chokidar: "^4.0.3",
|
|
35
39
|
colors: "^1.4.0",
|
|
@@ -43,15 +47,17 @@ var package_default = {
|
|
|
43
47
|
access: "public"
|
|
44
48
|
},
|
|
45
49
|
devDependencies: {
|
|
50
|
+
"@oxc-project/types": "^0.95.0",
|
|
46
51
|
"@types/stringify-object": "^4.0.5",
|
|
47
52
|
"cross-env": "^10.1.0",
|
|
48
53
|
tsx: "^4.20.6"
|
|
49
54
|
}
|
|
50
55
|
};
|
|
51
56
|
|
|
52
|
-
// src/cli/build.ts
|
|
57
|
+
// src/cli/build/index.ts
|
|
53
58
|
import fs from "fs";
|
|
54
59
|
import path from "path";
|
|
60
|
+
import { fileURLToPath } from "url";
|
|
55
61
|
import {
|
|
56
62
|
AttachmentType
|
|
57
63
|
} from "@bf6mods/sdk";
|
|
@@ -72,7 +78,156 @@ var MapId = /* @__PURE__ */ ((MapId2) => {
|
|
|
72
78
|
return MapId2;
|
|
73
79
|
})(MapId || {});
|
|
74
80
|
|
|
75
|
-
// src/cli/build.ts
|
|
81
|
+
// src/cli/build/generated-strings.ts
|
|
82
|
+
function extractBf6Strings(bf6Strings, generateFromLiterals) {
|
|
83
|
+
return {
|
|
84
|
+
name: "extract-bf6-strings",
|
|
85
|
+
generateBundle(_options, bundle) {
|
|
86
|
+
if (!generateFromLiterals) return;
|
|
87
|
+
let id = 0;
|
|
88
|
+
const existingStrings = new Set(Object.values(bf6Strings));
|
|
89
|
+
for (const [_file, output] of Object.entries(bundle)) {
|
|
90
|
+
let walk2 = function(node) {
|
|
91
|
+
if (node.type === "Literal") {
|
|
92
|
+
if (typeof node.value !== "string" || node.value === "" || node.value === "----uniquename----")
|
|
93
|
+
return;
|
|
94
|
+
if (!(node.value in bf6Strings) && !existingStrings.has(node.value)) {
|
|
95
|
+
existingStrings.add(node.value);
|
|
96
|
+
bf6Strings[`__auto__${id++}`] = node.value;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
for (const value of Object.values(node)) {
|
|
100
|
+
if (!value) continue;
|
|
101
|
+
if (Array.isArray(value)) {
|
|
102
|
+
for (const v of value) {
|
|
103
|
+
if (v && typeof v === "object" && "type" in v) walk2(v);
|
|
104
|
+
}
|
|
105
|
+
} else if (typeof value === "object" && "type" in value) {
|
|
106
|
+
walk2(value);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
var walk = walk2;
|
|
111
|
+
if (output.type !== "chunk") continue;
|
|
112
|
+
const code = output.code;
|
|
113
|
+
const program2 = this.parse(code, {
|
|
114
|
+
lang: "ts",
|
|
115
|
+
astType: "js",
|
|
116
|
+
range: true
|
|
117
|
+
});
|
|
118
|
+
for (const item of program2.body) {
|
|
119
|
+
walk2(item);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
},
|
|
123
|
+
moduleParsed(moduleInfo) {
|
|
124
|
+
if (moduleInfo.code && moduleInfo.exports.includes("bf6Strings")) {
|
|
125
|
+
const code = moduleInfo.code;
|
|
126
|
+
const getSnippet = (start, end, linesBefore = 2, linesAfter = 2) => {
|
|
127
|
+
const lines = code.split(/\r?\n/);
|
|
128
|
+
const startLine = Math.max(
|
|
129
|
+
0,
|
|
130
|
+
code.slice(0, start).split(/\r?\n/).length - 1 - linesBefore
|
|
131
|
+
);
|
|
132
|
+
const endLine = Math.min(
|
|
133
|
+
lines.length,
|
|
134
|
+
code.slice(0, end).split(/\r?\n/).length - 1 + linesAfter
|
|
135
|
+
);
|
|
136
|
+
return lines.slice(startLine, endLine).map((line, i) => {
|
|
137
|
+
const actualLine = startLine + i + 1;
|
|
138
|
+
return `${actualLine.toString().padStart(3)} | ${line}`;
|
|
139
|
+
}).join("\n");
|
|
140
|
+
};
|
|
141
|
+
const program2 = this.parse(code, {
|
|
142
|
+
lang: "ts",
|
|
143
|
+
astType: "js",
|
|
144
|
+
range: true
|
|
145
|
+
});
|
|
146
|
+
const extractObjectLiteral = (declaration) => {
|
|
147
|
+
if (declaration.init?.type !== "ObjectExpression") {
|
|
148
|
+
const snippet = getSnippet(...declaration.range ?? [0, 0]);
|
|
149
|
+
this.error(
|
|
150
|
+
`\u274C Invalid bf6Strings export: expected an object literal.
|
|
151
|
+
|
|
152
|
+
${snippet}`
|
|
153
|
+
);
|
|
154
|
+
}
|
|
155
|
+
for (const property of declaration.init.properties) {
|
|
156
|
+
if (property.type !== "Property") {
|
|
157
|
+
const snippet = getSnippet(...property.range ?? [0, 0]);
|
|
158
|
+
this.error(
|
|
159
|
+
`\u274C Invalid bf6Strings property: expected a key/value pair.
|
|
160
|
+
Found type: ${property.type}
|
|
161
|
+
|
|
162
|
+
${snippet}`
|
|
163
|
+
);
|
|
164
|
+
}
|
|
165
|
+
let key = void 0;
|
|
166
|
+
if (property.key.type === "Literal") {
|
|
167
|
+
key = property.key.value;
|
|
168
|
+
} else if (property.key.type === "Identifier") {
|
|
169
|
+
key = property.key.name;
|
|
170
|
+
} else {
|
|
171
|
+
const snippet = getSnippet(...property.range ?? [0, 0]);
|
|
172
|
+
this.error(
|
|
173
|
+
`\u274C Invalid bf6Strings key: expected a string literal or identifier.
|
|
174
|
+
Found type: ${property.key.type}
|
|
175
|
+
|
|
176
|
+
${snippet}`
|
|
177
|
+
);
|
|
178
|
+
continue;
|
|
179
|
+
}
|
|
180
|
+
if (property.value.type !== "Literal") {
|
|
181
|
+
const snippet = getSnippet(...property.range ?? [0, 0]);
|
|
182
|
+
this.error(
|
|
183
|
+
`\u274C Invalid bf6Strings value: expected a string literal.
|
|
184
|
+
Found type: ${property.value.type}
|
|
185
|
+
|
|
186
|
+
${snippet}`
|
|
187
|
+
);
|
|
188
|
+
}
|
|
189
|
+
const value = property.value.value;
|
|
190
|
+
if (typeof key !== "string" && typeof key !== "number" && typeof key !== "bigint" && typeof key !== "boolean") {
|
|
191
|
+
const snippet = getSnippet(...property.range ?? [0, 0]);
|
|
192
|
+
this.error(
|
|
193
|
+
`\u274C bf6Strings key must be a string, found: ${typeof key}
|
|
194
|
+
|
|
195
|
+
${snippet}`
|
|
196
|
+
);
|
|
197
|
+
}
|
|
198
|
+
if (typeof value !== "string" && typeof value !== "number" && typeof value !== "bigint" && typeof value !== "boolean") {
|
|
199
|
+
const snippet = getSnippet(...property.range ?? [0, 0]);
|
|
200
|
+
this.error(
|
|
201
|
+
`\u274C bf6Strings value must be a string, found: ${typeof value}
|
|
202
|
+
|
|
203
|
+
${snippet}`
|
|
204
|
+
);
|
|
205
|
+
}
|
|
206
|
+
bf6Strings[`${key}`] = `${value}`;
|
|
207
|
+
}
|
|
208
|
+
};
|
|
209
|
+
for (const item of program2.body) {
|
|
210
|
+
if (item.type === "VariableDeclaration") {
|
|
211
|
+
for (const declaration of item.declarations) {
|
|
212
|
+
if (declaration.type === "VariableDeclarator" && declaration.id.type === "Identifier" && declaration.id.name === "bf6Strings") {
|
|
213
|
+
extractObjectLiteral(declaration);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
if (item.type === "ExportNamedDeclaration" && item.declaration?.type === "VariableDeclaration") {
|
|
218
|
+
for (const declaration of item.declaration.declarations) {
|
|
219
|
+
if (declaration.type === "VariableDeclarator" && declaration.id.type === "Identifier" && declaration.id.name === "bf6Strings") {
|
|
220
|
+
extractObjectLiteral(declaration);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// src/cli/build/index.ts
|
|
76
231
|
async function getBf6Config(rootDir) {
|
|
77
232
|
globalThis.defineBf6Config = (c) => c;
|
|
78
233
|
globalThis.MapId = MapId;
|
|
@@ -90,39 +245,43 @@ async function build() {
|
|
|
90
245
|
fs.rmSync(outDir, { recursive: true, force: true });
|
|
91
246
|
fs.mkdirSync(outDir, { recursive: true });
|
|
92
247
|
const minifyJson = typeof config.minify === "boolean" ? config.minify : config.minify?.json ?? false;
|
|
248
|
+
const generatedStrings = {};
|
|
93
249
|
let tsAttachment;
|
|
94
250
|
if (config.entrypoint) {
|
|
95
251
|
const entryAbs = path.resolve(workingDir, config.entrypoint);
|
|
96
252
|
const compiled = await buildEntrypoint(
|
|
97
253
|
entryAbs,
|
|
98
|
-
|
|
99
|
-
|
|
254
|
+
generatedStrings,
|
|
255
|
+
config.generateStrings ?? true
|
|
100
256
|
);
|
|
101
257
|
tsAttachment = createTsAttachment(entryAbs, compiled);
|
|
102
258
|
}
|
|
103
259
|
const { attachments, mapRotation } = await collectAttachments(
|
|
104
260
|
config,
|
|
105
261
|
workingDir,
|
|
106
|
-
tsAttachment
|
|
262
|
+
tsAttachment,
|
|
263
|
+
generatedStrings
|
|
107
264
|
);
|
|
108
265
|
await writeModJson(config, outDir, attachments, mapRotation, minifyJson);
|
|
109
266
|
console.log(`\u2714 Built mod: ${config.name}`);
|
|
110
267
|
}
|
|
111
|
-
async function buildEntrypoint(entry,
|
|
268
|
+
async function buildEntrypoint(entry, bf6Strings, generateStringsFromLiterals) {
|
|
112
269
|
const bundle = await rolldown({
|
|
113
|
-
input: entry
|
|
270
|
+
input: entry,
|
|
271
|
+
plugins: [extractBf6Strings(bf6Strings, generateStringsFromLiterals)],
|
|
272
|
+
logLevel: "debug"
|
|
114
273
|
});
|
|
115
274
|
const result = await bundle.generate({
|
|
116
275
|
format: "esm",
|
|
117
276
|
inlineDynamicImports: true
|
|
118
277
|
});
|
|
119
278
|
const code = result.output[0].code;
|
|
120
|
-
if (emit) {
|
|
121
|
-
await fs.promises.writeFile(path.resolve(outDir, "index.js"), code);
|
|
122
|
-
}
|
|
123
279
|
return code;
|
|
124
280
|
}
|
|
125
|
-
|
|
281
|
+
var __filename = fileURLToPath(import.meta.url);
|
|
282
|
+
var __dirname = path.dirname(__filename);
|
|
283
|
+
var spatialsDir = path.resolve(__dirname, "../resources/maps/spatial");
|
|
284
|
+
async function collectAttachments(config, workingDir, tsAttachment, generatedStrings) {
|
|
126
285
|
const attachments = [];
|
|
127
286
|
const mapRotation = [];
|
|
128
287
|
if (tsAttachment) attachments.push(tsAttachment);
|
|
@@ -130,11 +289,20 @@ async function collectAttachments(config, workingDir, tsAttachment) {
|
|
|
130
289
|
const strPath = path.resolve(workingDir, config.strings);
|
|
131
290
|
if (!fs.existsSync(strPath)) throw new Error("Cannot find strings file");
|
|
132
291
|
const raw = await fs.promises.readFile(strPath, "utf8");
|
|
133
|
-
|
|
292
|
+
const attachment = createStringsAttachment(strPath, raw, generatedStrings);
|
|
293
|
+
attachments.push(attachment);
|
|
134
294
|
}
|
|
135
295
|
if (config.scenes) {
|
|
136
296
|
let mapIdx = 0;
|
|
137
|
-
for (const
|
|
297
|
+
for (const map of config.scenes) {
|
|
298
|
+
let mapId;
|
|
299
|
+
let scene;
|
|
300
|
+
if (Array.isArray(map)) {
|
|
301
|
+
[mapId, scene] = map;
|
|
302
|
+
} else {
|
|
303
|
+
mapId = map;
|
|
304
|
+
scene = path.resolve(spatialsDir, `${mapId}.spatial.json`);
|
|
305
|
+
}
|
|
138
306
|
const scenePath = path.resolve(workingDir, scene);
|
|
139
307
|
if (!fs.existsSync(scenePath))
|
|
140
308
|
throw new Error(`Cannot find spatial data file: ${scene}`);
|
|
@@ -160,6 +328,19 @@ async function writeModJson(config, outDir, attachments, mapRotation, minify) {
|
|
|
160
328
|
};
|
|
161
329
|
const jsonOutput = minify ? JSON.stringify(finalJson) : JSON.stringify(finalJson, null, 2);
|
|
162
330
|
await fs.promises.writeFile(path.resolve(outDir, "mod.json"), jsonOutput);
|
|
331
|
+
if (config.outputArtifacts && finalJson?.attachments) {
|
|
332
|
+
for (const attachment of finalJson.attachments) {
|
|
333
|
+
const attachmentsDir = path.resolve(outDir, "attachments");
|
|
334
|
+
if (!fs.existsSync(attachmentsDir))
|
|
335
|
+
fs.mkdirSync(attachmentsDir, {
|
|
336
|
+
recursive: true
|
|
337
|
+
});
|
|
338
|
+
await fs.promises.writeFile(
|
|
339
|
+
path.resolve(outDir, "attachments", attachment.filename),
|
|
340
|
+
atob(attachment.attachmentData.original)
|
|
341
|
+
);
|
|
342
|
+
}
|
|
343
|
+
}
|
|
163
344
|
}
|
|
164
345
|
function createTsAttachment(filePath, compiled) {
|
|
165
346
|
return {
|
|
@@ -173,7 +354,18 @@ function createTsAttachment(filePath, compiled) {
|
|
|
173
354
|
errors: []
|
|
174
355
|
};
|
|
175
356
|
}
|
|
176
|
-
function createStringsAttachment(filePath, raw) {
|
|
357
|
+
function createStringsAttachment(filePath, raw, generatedStrings) {
|
|
358
|
+
let result = raw;
|
|
359
|
+
if (generatedStrings) {
|
|
360
|
+
result = JSON.stringify(
|
|
361
|
+
{
|
|
362
|
+
...generatedStrings,
|
|
363
|
+
...JSON.parse(raw)
|
|
364
|
+
},
|
|
365
|
+
null,
|
|
366
|
+
4
|
|
367
|
+
);
|
|
368
|
+
}
|
|
177
369
|
return {
|
|
178
370
|
id: crypto.randomUUID(),
|
|
179
371
|
version: "1.0",
|
|
@@ -181,7 +373,7 @@ function createStringsAttachment(filePath, raw) {
|
|
|
181
373
|
isProcessable: true,
|
|
182
374
|
processingStatus: 2,
|
|
183
375
|
attachmentType: AttachmentType.Strings,
|
|
184
|
-
attachmentData: { original: toBase64(
|
|
376
|
+
attachmentData: { original: toBase64(result), compiled: "" },
|
|
185
377
|
errors: []
|
|
186
378
|
};
|
|
187
379
|
}
|
|
@@ -293,11 +485,11 @@ import stringifyObject from "stringify-object";
|
|
|
293
485
|
import child_process from "child_process";
|
|
294
486
|
import fs3 from "fs";
|
|
295
487
|
import path3 from "path";
|
|
296
|
-
import { fileURLToPath } from "url";
|
|
488
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
297
489
|
import * as prompts from "@clack/prompts";
|
|
298
|
-
var
|
|
299
|
-
var
|
|
300
|
-
var templatesDir = path3.resolve(
|
|
490
|
+
var __filename2 = fileURLToPath2(import.meta.url);
|
|
491
|
+
var __dirname2 = path3.dirname(__filename2);
|
|
492
|
+
var templatesDir = path3.resolve(__dirname2, "../resources/templates");
|
|
301
493
|
function renameFilesRecursively(dir, modName) {
|
|
302
494
|
const entries = fs3.readdirSync(dir, { withFileTypes: true });
|
|
303
495
|
for (const entry of entries) {
|
|
@@ -540,7 +732,7 @@ function stringifyWithRaw(value, options = {}) {
|
|
|
540
732
|
// src/cli/prepare.ts
|
|
541
733
|
import fs5 from "fs";
|
|
542
734
|
import path5 from "path";
|
|
543
|
-
import { fileURLToPath as
|
|
735
|
+
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
544
736
|
import colors3 from "colors";
|
|
545
737
|
import { genExport, genInlineTypeImport } from "knitwork";
|
|
546
738
|
|
|
@@ -580,11 +772,11 @@ var printToConsole = (message) => {
|
|
|
580
772
|
// src/cli/prepare.ts
|
|
581
773
|
async function prepare() {
|
|
582
774
|
try {
|
|
583
|
-
const
|
|
584
|
-
const
|
|
775
|
+
const __filename3 = fileURLToPath3(import.meta.url);
|
|
776
|
+
const __dirname3 = path5.dirname(__filename3);
|
|
585
777
|
const _workingDir = path5.resolve(".");
|
|
586
778
|
const buildDir = path5.resolve(".bf6");
|
|
587
|
-
const resources = path5.resolve(
|
|
779
|
+
const resources = path5.resolve(__dirname3, "../resources/prepare");
|
|
588
780
|
fs5.cpSync(
|
|
589
781
|
path5.resolve(resources, "tsconfig.json"),
|
|
590
782
|
path5.resolve(buildDir, "tsconfig.json")
|
package/dist/cli/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/cli/index.ts","../../package.json","../../src/cli/build.ts","../../src/resources/prepare/types/config.ts","../../src/cli/dev.ts","../../src/cli/import.ts","../../src/cli/init.ts","../../src/cli/prepare.ts","../../src/cli/utils.ts","../../../../node_modules/ansi-regex/index.js","../../../../node_modules/strip-ansi/index.js"],"sourcesContent":["#!/usr/bin/env node\r\nimport { Command } from \"commander\";\r\nimport pkg from \"../../package.json\" with { type: \"json\" };\r\nimport { build } from \"./build.js\";\r\nimport { dev } from \"./dev.ts\";\r\nimport { importFile } from \"./import.ts\";\r\nimport { init, installDependencies } from \"./init.js\";\r\nimport { prepare } from \"./prepare.js\";\r\n\r\nconst program = new Command();\r\n\r\nprogram\r\n\t.name(Object.keys(pkg.bin)[0])\r\n\t.description(pkg.description)\r\n\t.version(pkg.version);\r\n\r\nprogram\r\n\t.command(\"init\")\r\n\t.argument(\"[directory]\")\r\n\t.description(\"Create a new bf6 mod\")\r\n\t.action(async (directory) => {\r\n\t\tawait init(directory);\r\n\t});\r\n\r\nprogram\r\n\t.command(\"build\")\r\n\t.description(\"build the bf6 mod\")\r\n\t.action(async () => {\r\n\t\tawait build();\r\n\t});\r\n\r\nprogram\r\n\t.command(\"prepare\")\r\n\t.description(\"prepare the types for bf6 mod\")\r\n\t.action(async () => {\r\n\t\tawait prepare();\r\n\t});\r\n\r\nprogram\r\n\t.command(\"dev\")\r\n\t.description(\"watch the changes in src, and recompile as needed\")\r\n\t.action(async () => {\r\n\t\tawait dev();\r\n\t});\r\n\r\nprogram\r\n\t.command(\"import\")\r\n\t.argument(\"<input>\")\r\n\t.argument(\"<output>\")\r\n\t.description(\"decompiles the json config of a mod into a new project\")\r\n\t.action(async (input, output) => {\r\n\t\tawait importFile(input as string, output as string);\r\n\t\tinstallDependencies(output);\r\n\t});\r\n\r\nprogram.exitOverride((_err) => {\r\n\tif (process.env.EXIT_CODE === \"none\") process.exit(0);\r\n});\r\n\r\nprogram.parse();\r\n","{\r\n\t\"name\": \"@bf6mods/cli\",\r\n\t\"version\": \"1.0.1\",\r\n\t\"description\": \"CLI and library for bundling BF6 mods\",\r\n\t\"license\": \"MIT\",\r\n\t\"type\": \"module\",\r\n\t\"bin\": {\r\n\t\t\"bf6mods\": \"./dist/cli/index.js\"\r\n\t},\r\n\t\"main\": \"./dist/index.js\",\r\n\t\"types\": \"./dist/index.d.ts\",\r\n\t\"scripts\": {\r\n\t\t\"build\": \"tsup\",\r\n\t\t\"start\": \"cross-env EXIT_CODE=none tsx ./src/cli/index.ts\"\r\n\t},\r\n\t\"exports\": {\r\n\t\t\".\": {\r\n\t\t\t\"types\": \"./dist/index.d.ts\",\r\n\t\t\t\"import\": \"./dist/index.js\"\r\n\t\t}\r\n\t},\r\n\t\"files\": [\r\n\t\t\"dist/\"\r\n\t],\r\n\t\"dependencies\": {\r\n\t\t\"@bf6mods/sdk\": \"1.0.1\",\r\n\t\t\"@clack/prompts\": \"^0.11.0\",\r\n\t\t\"chokidar\": \"^4.0.3\",\r\n\t\t\"colors\": \"^1.4.0\",\r\n\t\t\"commander\": \"^14.0.1\",\r\n\t\t\"jiti\": \"^2.6.1\",\r\n\t\t\"knitwork\": \"^1.2.0\",\r\n\t\t\"rolldown\": \"^1.0.0-beta.43\",\r\n\t\t\"stringify-object\": \"^6.0.0\"\r\n\t},\r\n\t\"publishConfig\": {\r\n\t\t\"access\": \"public\"\r\n\t},\r\n\t\"devDependencies\": {\r\n\t\t\"@types/stringify-object\": \"^4.0.5\",\r\n\t\t\"cross-env\": \"^10.1.0\",\r\n\t\t\"tsx\": \"^4.20.6\"\r\n\t}\r\n}\r\n","import fs from \"node:fs\";\r\nimport path from \"node:path\";\r\nimport {\r\n\ttype Attachment,\r\n\tAttachmentType,\r\n\ttype ConfigType,\r\n\ttype MapType,\r\n} from \"@bf6mods/sdk\";\r\nimport { createJiti } from \"jiti\";\r\nimport { rolldown } from \"rolldown\";\r\nimport {\r\n\ttype Bf6Config,\r\n\tMapId as MapIdEnum,\r\n} from \"../resources/prepare/types/config.ts\";\r\n\r\ndeclare global {\r\n\tvar defineBf6Config: ((config: Bf6Config) => Bf6Config) | undefined;\r\n\tvar MapId: typeof MapIdEnum | undefined;\r\n}\r\n\r\n/**\r\n * Dynamically imports and validates bf6.config.ts\r\n */\r\nexport async function getBf6Config(rootDir: string): Promise<Bf6Config> {\r\n\tglobalThis.defineBf6Config = (c) => c;\r\n\tglobalThis.MapId = MapIdEnum;\r\n\tconst jiti = createJiti(rootDir, { interopDefault: true });\r\n\tconst result = await jiti.import(\"./bf6.config\", { default: true });\r\n\tdelete globalThis.defineBf6Config;\r\n\tdelete globalThis.MapId;\r\n\treturn result as Bf6Config;\r\n}\r\n\r\n/**\r\n * Builds the entire mod project once (for production or single run).\r\n */\r\nexport async function build() {\r\n\tconst workingDir = path.resolve(\".\");\r\n\tconst config = await getBf6Config(workingDir);\r\n\r\n\tconst outDir = path.resolve(workingDir, config.outDir);\r\n\tif (fs.existsSync(outDir))\r\n\t\tfs.rmSync(outDir, { recursive: true, force: true });\r\n\tfs.mkdirSync(outDir, { recursive: true });\r\n\r\n\tconst minifyJson =\r\n\t\ttypeof config.minify === \"boolean\"\r\n\t\t\t? config.minify\r\n\t\t\t: (config.minify?.json ?? false);\r\n\r\n\tlet tsAttachment: Attachment | undefined;\r\n\tif (config.entrypoint) {\r\n\t\tconst entryAbs = path.resolve(workingDir, config.entrypoint);\r\n\t\tconst compiled = await buildEntrypoint(\r\n\t\t\tentryAbs,\r\n\t\t\toutDir,\r\n\t\t\t!!config.outputArtifacts,\r\n\t\t);\r\n\t\ttsAttachment = createTsAttachment(entryAbs, compiled);\r\n\t}\r\n\r\n\tconst { attachments, mapRotation } = await collectAttachments(\r\n\t\tconfig,\r\n\t\tworkingDir,\r\n\t\ttsAttachment,\r\n\t);\r\n\r\n\tawait writeModJson(config, outDir, attachments, mapRotation, minifyJson);\r\n\tconsole.log(`✔ Built mod: ${config.name}`);\r\n}\r\n\r\n/**\r\n * Compiles the TypeScript entrypoint using rolldown and returns the compiled code.\r\n */\r\nexport async function buildEntrypoint(\r\n\tentry: string,\r\n\toutDir: string,\r\n\temit: boolean,\r\n): Promise<string> {\r\n\tconst bundle = await rolldown({\r\n\t\tinput: entry,\r\n\t});\r\n\tconst result = await bundle.generate({\r\n\t\tformat: \"esm\",\r\n\t\tinlineDynamicImports: true,\r\n\t});\r\n\tconst code = result.output[0].code;\r\n\tif (emit) {\r\n\t\tawait fs.promises.writeFile(path.resolve(outDir, \"index.js\"), code);\r\n\t}\r\n\treturn code;\r\n}\r\n\r\n/**\r\n * Collects all attachments (TS, scenes, strings) and returns them + mapRotation.\r\n */\r\nexport async function collectAttachments(\r\n\tconfig: Bf6Config,\r\n\tworkingDir: string,\r\n\ttsAttachment?: Attachment,\r\n) {\r\n\tconst attachments: Attachment[] = [];\r\n\tconst mapRotation: MapType[] = [];\r\n\r\n\tif (tsAttachment) attachments.push(tsAttachment);\r\n\r\n\t// Strings\r\n\tif (config.strings) {\r\n\t\tconst strPath = path.resolve(workingDir, config.strings);\r\n\t\tif (!fs.existsSync(strPath)) throw new Error(\"Cannot find strings file\");\r\n\t\tconst raw = await fs.promises.readFile(strPath, \"utf8\");\r\n\t\tattachments.push(createStringsAttachment(strPath, raw));\r\n\t}\r\n\r\n\t// Scenes\r\n\tif (config.scenes) {\r\n\t\tlet mapIdx = 0;\r\n\t\tfor (const [mapId, scene] of config.scenes) {\r\n\t\t\tconst scenePath = path.resolve(workingDir, scene);\r\n\t\t\tif (!fs.existsSync(scenePath))\r\n\t\t\t\tthrow new Error(`Cannot find spatial data file: ${scene}`);\r\n\t\t\tconst raw = await fs.promises.readFile(scenePath, \"utf8\");\r\n\t\t\tconst spatial = createSpatialAttachment(scenePath, raw, mapIdx++);\r\n\t\t\tattachments.push(spatial);\r\n\t\t\tmapRotation.push({ id: mapId, spatialAttachment: spatial });\r\n\t\t}\r\n\t}\r\n\r\n\treturn { attachments, mapRotation };\r\n}\r\n\r\n/**\r\n * Writes the mod.json output to disk.\r\n */\r\nexport async function writeModJson(\r\n\tconfig: Bf6Config,\r\n\toutDir: string,\r\n\tattachments: ConfigType[\"attachments\"],\r\n\tmapRotation: MapType[],\r\n\tminify: boolean,\r\n) {\r\n\tconst baseGame = config.game;\r\n\tconst finalJson: ConfigType = {\r\n\t\tname: config.name,\r\n\t\tdescription: config.description,\r\n\t\tgameMode: \"ModBuilderCustom\",\r\n\t\tmutators: baseGame.mutators ?? {},\r\n\t\tassetRestrictions: baseGame.assetRestrictions ?? {},\r\n\t\tteamComposition: baseGame.teamComposition ?? [],\r\n\t\tmapRotation,\r\n\t\tattachments,\r\n\t};\r\n\r\n\tconst jsonOutput = minify\r\n\t\t? JSON.stringify(finalJson)\r\n\t\t: JSON.stringify(finalJson, null, 2);\r\n\tawait fs.promises.writeFile(path.resolve(outDir, \"mod.json\"), jsonOutput);\r\n}\r\n\r\nexport function createTsAttachment(\r\n\tfilePath: string,\r\n\tcompiled: string,\r\n): Attachment {\r\n\treturn {\r\n\t\tid: crypto.randomUUID(),\r\n\t\tversion: \"1.0\",\r\n\t\tfilename: `${path.parse(filePath).name}.js`,\r\n\t\tisProcessable: true,\r\n\t\tprocessingStatus: 2,\r\n\t\tattachmentType: AttachmentType.TypeScript,\r\n\t\tattachmentData: { original: toBase64(compiled), compiled: \"\" },\r\n\t\terrors: [],\r\n\t};\r\n}\r\n\r\nexport function createStringsAttachment(\r\n\tfilePath: string,\r\n\traw: string,\r\n): Attachment {\r\n\treturn {\r\n\t\tid: crypto.randomUUID(),\r\n\t\tversion: \"1.0\",\r\n\t\tfilename: path.basename(filePath),\r\n\t\tisProcessable: true,\r\n\t\tprocessingStatus: 2,\r\n\t\tattachmentType: AttachmentType.Strings,\r\n\t\tattachmentData: { original: toBase64(raw), compiled: \"\" },\r\n\t\terrors: [],\r\n\t};\r\n}\r\n\r\nexport function createSpatialAttachment(\r\n\tfilePath: string,\r\n\traw: string,\r\n\tmapIdx: number,\r\n): MapType[\"spatialAttachment\"] {\r\n\treturn {\r\n\t\tid: crypto.randomUUID(),\r\n\t\tversion: \"1.0\",\r\n\t\tfilename: path.basename(filePath),\r\n\t\tisProcessable: true,\r\n\t\tprocessingStatus: 2,\r\n\t\tattachmentType: AttachmentType.SpatialData,\r\n\t\tattachmentData: { original: toBase64(raw), compiled: \"\" },\r\n\t\tmetadata: `mapIdx=${mapIdx}`,\r\n\t\terrors: [],\r\n\t};\r\n}\r\n\r\nexport function toBase64(input: string | Buffer): string {\r\n\treturn Buffer.isBuffer(input)\r\n\t\t? input.toString(\"base64\")\r\n\t\t: Buffer.from(input, \"utf8\").toString(\"base64\");\r\n}\r\n","import type { ConfigType } from \"@bf6mods/sdk\";\r\n\r\nexport enum MapId {\r\n\tFireStorm = \"MP_FireStorm-ModBuilderCustom0\",\r\n\tSiegeOfCairo = \"MP_Abbasid-ModBuilderCustom0\",\r\n\tEmpireState = \"MP_Aftermath-ModBuilderCustom0\",\r\n\tIberianOffensive = \"MP_Battery-ModBuilderCustom0\",\r\n\tLiberationPeak = \"MP_Capstone-ModBuilderCustom0\",\r\n\tManhattanBridge = \"MP_Dumbo-ModBuilderCustom0\",\r\n\tSaintsQuarter = \"MP_Limestone-ModBuilderCustom0\",\r\n\tNewSobekCity = \"MP_Outskirts-ModBuilderCustom0\",\r\n\tMirakValley = \"MP_Tungsten-ModBuilderCustom0\",\r\n}\r\n\r\n/**\r\n * Represents the root configuration for a Battlefield 6 mod project.\r\n *\r\n * This file combines both build-level settings (like entrypoints and output directories)\r\n * and in-game configuration data (such as mutators and asset restrictions)\r\n * under the `game` key.\r\n *\r\n * Use {@link defineBf6Config} to define and validate this structure\r\n * in your `bf6.config.ts` file.\r\n */\r\nexport type Bf6Config = {\r\n\t/**\r\n\t * The human-readable name of the mod.\r\n\t *\r\n\t * Typically matches the project name used in the BF6 mod editor or\r\n\t * the display name shown in the in-game mod browser.\r\n\t */\r\n\tname: string;\r\n\r\n\t/**\r\n\t * A short description of the mod’s purpose or content.\r\n\t * Used for display and metadata purposes.\r\n\t */\r\n\tdescription: string;\r\n\r\n\t/**\r\n\t * The output directory where compiled or bundled files are written.\r\n\t * Usually something like `\"dist\"` or `\"build\"`.\r\n\t */\r\n\toutDir: string;\r\n\r\n\t/**\r\n\t * Whether or not to output the built files like the entrypoint typescript file\r\n\t */\r\n\toutputArtifacts?: boolean;\r\n\r\n\t/**\r\n\t * The main entrypoint for your mod’s TypeScript source file.\r\n\t *\r\n\t * This is typically something like `\"src/index.ts\"` or `\"src/main.ts\"`.\r\n\t */\r\n\tentrypoint?: string;\r\n\r\n\t/**\r\n\t * One or more scene file paths (.json) that the mod includes.\r\n\t * Can be a single string or an array of paths.\r\n\t * Can be a directory if single string provided\r\n\t */\r\n\tscenes?: [MapId, string][];\r\n\r\n\t/**\r\n\t * Path to a JSON file or other source that defines localized strings\r\n\t * used by the mod (optional).\r\n\t */\r\n\tstrings?: string;\r\n\r\n\t/**\r\n\t * Generate strings automatically\r\n\t */\r\n\tgenerateStrings?: boolean;\r\n\r\n\t/**\r\n\t * Controls whether build output should be minified.\r\n\t *\r\n\t * Can be a boolean (to toggle all minification),\r\n\t * or an object specifying independent settings for JS and JSON files.\r\n\t *\r\n\t * @example\r\n\t * ```ts\r\n\t * minify: true\r\n\t * // or\r\n\t * minify: { js: true, json: false }\r\n\t * ```\r\n\t */\r\n\tminify?:\r\n\t\t| {\r\n\t\t\t\t/** Whether to minify JavaScript output. */\r\n\t\t\t\tjs?: boolean;\r\n\t\t\t\t/** Whether to minify JSON output. */\r\n\t\t\t\tjson?: boolean;\r\n\t\t }\r\n\t\t/** Enables or disables all minification. */\r\n\t\t| boolean;\r\n\r\n\t/**\r\n\t * The underlying in-game configuration derived from `ConfigType`\r\n\t * in the BF6 SDK. Includes gameplay-level details like mutators,\r\n\t * asset restrictions, and team compositions.\r\n\t *\r\n\t * The following properties are **excluded**:\r\n\t * - `attachments`\r\n\t * - `workspace`\r\n\t * - `mapRotation`\r\n\t * - `name`\r\n\t * - `description`\r\n\t *\r\n\t * since those are either redundant or handled elsewhere.\r\n\t */\r\n\tgame: Omit<\r\n\t\tConfigType,\r\n\t\t\"attachments\" | \"workspace\" | \"mapRotation\" | \"name\" | \"description\"\r\n\t>;\r\n};\r\n\r\n/**\r\n * Defines and validates a Battlefield 6 mod configuration object.\r\n *\r\n * This helper ensures your config is properly typed and can be\r\n * statically analyzed by TypeScript.\r\n *\r\n * @example\r\n * ```ts\r\n * export default defineBf6Config({\r\n * name: \"My Custom Mod\",\r\n * description: \"Adds custom rules\",\r\n * outDir: \"dist\",\r\n * entrypoint: \"src/main.ts\",\r\n * game: {\r\n * mutators: [],\r\n * assetRestrictions: {},\r\n * teamComposition: [],\r\n * },\r\n * });\r\n * ```\r\n *\r\n * @param bf6Config The configuration object to validate and return.\r\n * @returns The validated Battlefield 6 configuration object.\r\n */\r\nexport function defineBf6Config(bf6Config: Bf6Config): Bf6Config {\r\n\treturn bf6Config;\r\n}\r\n","import fs from \"node:fs\";\r\nimport { glob } from \"node:fs/promises\";\r\nimport path from \"node:path\";\r\nimport chokidar, { type FSWatcher } from \"chokidar\";\r\nimport colors from \"colors\";\r\nimport { build, getBf6Config } from \"./build.ts\";\r\n\r\nexport async function dev() {\r\n\tconst workingDir = path.resolve(\".\");\r\n\tlet config = await getBf6Config(workingDir);\r\n\tconst outDir = path.resolve(workingDir, config.outDir);\r\n\tif (!fs.existsSync(outDir)) fs.mkdirSync(outDir, { recursive: true });\r\n\r\n\tconsole.log(colors.cyan(`▶ Starting dev for ${config.name}`));\r\n\r\n\tlet watcher: FSWatcher | undefined;\r\n\r\n\tasync function rebuild(trigger: string) {\r\n\t\tconsole.log(\r\n\t\t\tcolors.yellow(\r\n\t\t\t\t`↻ Change detected in ${path.basename(trigger)}, rebuilding...`,\r\n\t\t\t),\r\n\t\t);\r\n\t\tconst start = performance.now();\r\n\t\ttry {\r\n\t\t\tawait build();\r\n\t\t\tconst end = performance.now();\r\n\t\t\tconst duration = ((end - start) / 1000).toFixed(2);\r\n\t\t\tconsole.log(colors.green(`✔ Updated mod.json (${duration}s)`));\r\n\t\t} catch (err) {\r\n\t\t\tconsole.error(colors.red(`✖ Rebuild failed: ${(err as Error).message}`));\r\n\t\t}\r\n\t}\r\n\r\n\tasync function collectWatchTargets(): Promise<string[]> {\r\n\t\tconst targets: string[] = [];\r\n\r\n\t\tif (config.entrypoint)\r\n\t\t\ttargets.push(path.resolve(workingDir, config.entrypoint));\r\n\t\tif (config.scenes) {\r\n\t\t\tfor (const [, scene] of config.scenes) {\r\n\t\t\t\ttargets.push(path.resolve(workingDir, scene));\r\n\t\t\t}\r\n\t\t}\r\n\t\tif (config.strings) targets.push(path.resolve(workingDir, config.strings));\r\n\r\n\t\tconst srcDir = path.resolve(workingDir, \"src\");\r\n\t\tfor await (const entry of glob(`${srcDir}/**/*`)) targets.push(entry);\r\n\r\n\t\tfor await (const entry of glob(\"bf6.config.*\")) targets.push(entry);\r\n\r\n\t\treturn targets;\r\n\t}\r\n\r\n\tasync function setupWatcher() {\r\n\t\tif (watcher) {\r\n\t\t\tawait watcher.close();\r\n\t\t\tconsole.log(colors.grey(\"♻ Reloading watcher due to config change...\"));\r\n\t\t}\r\n\r\n\t\tconst watchTargets = await collectWatchTargets();\r\n\r\n\t\twatcher = chokidar.watch(watchTargets, {\r\n\t\t\tpersistent: true,\r\n\t\t\tignoreInitial: true,\r\n\t\t\tawaitWriteFinish: true,\r\n\t\t\tignored: [path.resolve(outDir), `${path.resolve(outDir)}/**`],\r\n\t\t});\r\n\r\n\t\twatcher.on(\"change\", async (file) => {\r\n\t\t\tif (file.includes(\"bf6.config.\")) {\r\n\t\t\t\tconsole.log(\r\n\t\t\t\t\tcolors.magenta(\r\n\t\t\t\t\t\t\"⚙ Config changed — reloading and rebuilding watcher...\",\r\n\t\t\t\t\t),\r\n\t\t\t\t);\r\n\t\t\t\ttry {\r\n\t\t\t\t\tconfig = await getBf6Config(workingDir);\r\n\t\t\t\t\tawait setupWatcher();\r\n\t\t\t\t} catch (err) {\r\n\t\t\t\t\tconsole.error(\r\n\t\t\t\t\t\tcolors.red(`✖ Failed to reload config: ${(err as Error).message}`),\r\n\t\t\t\t\t);\r\n\t\t\t\t}\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\r\n\t\t\tawait rebuild(file);\r\n\t\t});\r\n\r\n\t\twatcher.on(\"add\", async (file) => await rebuild(file));\r\n\r\n\t\tawait rebuild(\"initial\");\r\n\t}\r\n\r\n\tawait setupWatcher();\r\n}\r\n","import fs from \"node:fs\";\r\nimport path from \"node:path\";\r\nimport { AttachmentType, type ConfigType } from \"@bf6mods/sdk\";\r\nimport stringifyObject from \"stringify-object\";\r\nimport { MapId as MapIdEnum } from \"../resources/prepare/types/config.ts\";\r\nimport { startProject } from \"./init.ts\";\r\n\r\nasync function writeFileSafe(filePath: string, data: string | Buffer) {\r\n\tconst dir = path.dirname(filePath);\r\n\tawait fs.promises.mkdir(dir, { recursive: true });\r\n\tawait fs.promises.writeFile(filePath, data);\r\n}\r\n\r\nfunction getMapKeyByValue(value: string): keyof typeof MapIdEnum | undefined {\r\n\treturn Object.keys(MapIdEnum).find(\r\n\t\t(k) => MapIdEnum[k as keyof typeof MapIdEnum] === value,\r\n\t) as keyof typeof MapIdEnum | undefined;\r\n}\r\n\r\nexport async function importFile(input: string, output: string, name?: string) {\r\n\tconst workingDir = path.resolve(\".\");\r\n\tconst entrypoint = path.resolve(workingDir, input);\r\n\tconst outDir = path.resolve(workingDir, output);\r\n\r\n\tif (!fs.existsSync(entrypoint)) throw new Error(\"Cannot find strings file\");\r\n\r\n\tconst config = JSON.parse(\r\n\t\tawait fs.promises.readFile(entrypoint, { encoding: \"utf8\" }),\r\n\t) as ConfigType;\r\n\r\n\tif (!fs.existsSync(outDir))\r\n\t\tawait fs.promises.mkdir(outDir, { recursive: true });\r\n\r\n\tawait startProject(outDir, \"None\", name ?? config.name);\r\n\r\n\tlet typescriptFile: string | undefined;\r\n\tlet stringsFile: string | undefined;\r\n\tconst scenes: [string, string][] = [];\r\n\tconst promises: Promise<unknown>[] = [];\r\n\r\n\tif (config.attachments) {\r\n\t\tfor (const attachment of config.attachments) {\r\n\t\t\tif (attachment.attachmentType === AttachmentType.TypeScript)\r\n\t\t\t\ttypescriptFile = attachment.filename;\r\n\r\n\t\t\tif (attachment.attachmentType === AttachmentType.Strings)\r\n\t\t\t\tstringsFile = attachment.filename;\r\n\r\n\t\t\tif (attachment.attachmentType === AttachmentType.SpatialData) {\r\n\t\t\t\t// We'll just use the data attached to mapRotation instead\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\r\n\t\t\tpromises.push(\r\n\t\t\t\twriteFileSafe(\r\n\t\t\t\t\tpath.resolve(outDir, \"src\", attachment.filename),\r\n\t\t\t\t\tatob(attachment.attachmentData.original),\r\n\t\t\t\t),\r\n\t\t\t);\r\n\t\t}\r\n\t}\r\n\r\n\t// Extract spatial scenes from mapRotation instead of guessing\r\n\tif (config.mapRotation?.length) {\r\n\t\tfor (const map of config.mapRotation) {\r\n\t\t\tpromises.push(\r\n\t\t\t\twriteFileSafe(\r\n\t\t\t\t\tpath.resolve(outDir, \"src\", \"scenes\", map.spatialAttachment.filename),\r\n\t\t\t\t\tatob(map.spatialAttachment.attachmentData.original),\r\n\t\t\t\t),\r\n\t\t\t);\r\n\r\n\t\t\tscenes.push([map.id, `src/scenes/${map.spatialAttachment.filename}`]);\r\n\t\t}\r\n\t}\r\n\r\n\t// build the new bf6.config.ts structure\r\n\tconst bf6Config = {\r\n\t\tname: name ?? config.name,\r\n\t\tdescription: config.description,\r\n\t\toutDir: \"dist\",\r\n\t\tentrypoint: typescriptFile ? `src/${typescriptFile}` : undefined,\r\n\t\tscenes: scenes\r\n\t\t\t? scenes.map(([id, path]) => [\r\n\t\t\t\t\t`MapId.${getMapKeyByValue(id) ?? id}`,\r\n\t\t\t\t\tpath,\r\n\t\t\t\t])\r\n\t\t\t: undefined,\r\n\t\tstrings: stringsFile ? `src/${stringsFile}` : undefined,\r\n\t\tgame: {\r\n\t\t\tmutators: config.mutators,\r\n\t\t\tassetRestrictions: config.assetRestrictions,\r\n\t\t\tgameMode: config.gameMode,\r\n\t\t\tteamComposition: config.teamComposition,\r\n\t\t},\r\n\t};\r\n\r\n\tconst bf6ConfigContent = `export default defineBf6Config(${stringifyWithRaw(\r\n\t\tbf6Config,\r\n\t)});\\n`;\r\n\r\n\tpromises.push(\r\n\t\twriteFileSafe(path.resolve(outDir, \"bf6.config.ts\"), bf6ConfigContent),\r\n\t);\r\n\r\n\tawait Promise.all(promises);\r\n}\r\n\r\nfunction stringifyWithRaw(value: unknown, options = {}) {\r\n\treturn stringifyObject(value, {\r\n\t\tindent: \" \", // 4 spaces\r\n\t\tsingleQuotes: true,\r\n\t\ttransform: (_obj, _prop, originalResult) => {\r\n\t\t\t// Remove quotes from MapId.* expressions\r\n\t\t\tif (/^['\"]MapId\\.[A-Za-z0-9_]+['\"]$/.test(originalResult)) {\r\n\t\t\t\treturn originalResult.slice(1, -1); // remove surrounding quotes\r\n\t\t\t}\r\n\t\t\treturn originalResult;\r\n\t\t},\r\n\t\t...options,\r\n\t});\r\n}\r\n","import child_process from \"node:child_process\";\r\nimport fs from \"node:fs\";\r\nimport path from \"node:path\";\r\nimport { fileURLToPath } from \"node:url\";\r\nimport * as prompts from \"@clack/prompts\";\r\nimport { importFile } from \"./import.ts\";\r\n\r\nconst __filename = fileURLToPath(import.meta.url);\r\nconst __dirname = path.dirname(__filename);\r\n\r\nconst templatesDir = path.resolve(__dirname, \"../resources/templates\");\r\n\r\nfunction renameFilesRecursively(dir: string, modName: string) {\r\n\tconst entries = fs.readdirSync(dir, { withFileTypes: true });\r\n\tfor (const entry of entries) {\r\n\t\tconst oldPath = path.join(dir, entry.name);\r\n\t\tlet newPath = oldPath;\r\n\r\n\t\t// Rename file or folder if it includes {name}\r\n\t\tif (entry.name.includes(\"{name}\")) {\r\n\t\t\tconst newName = entry.name.replace(\"{name}\", modName);\r\n\t\t\tnewPath = path.join(dir, newName);\r\n\t\t\tfs.renameSync(oldPath, newPath);\r\n\t\t}\r\n\r\n\t\t// If it's a bf6.config.ts, replace the {bf6ConfigName} placeholder\r\n\t\tif (entry.name === \"bf6.config.ts\") {\r\n\t\t\tlet content = fs.readFileSync(newPath, \"utf-8\");\r\n\t\t\tcontent = content.replace(/{bf6ConfigName}/g, modName);\r\n\t\t\tfs.writeFileSync(newPath, content, \"utf-8\");\r\n\t\t}\r\n\r\n\t\t// If it's a package.json, rewrite the \"name\" field\r\n\t\tif (entry.name === \"package.json\") {\r\n\t\t\tconst pkg = JSON.parse(fs.readFileSync(newPath, \"utf-8\"));\r\n\t\t\tpkg.name = modName;\r\n\t\t\tfs.writeFileSync(newPath, JSON.stringify(pkg, null, 2));\r\n\t\t}\r\n\r\n\t\t// Recurse into directories (using the new name if renamed)\r\n\t\tif (fs.statSync(newPath).isDirectory()) {\r\n\t\t\trenameFilesRecursively(newPath, modName);\r\n\t\t}\r\n\t}\r\n}\r\n\r\nexport const templates = [\r\n\t\"Basic\",\r\n\t\"AcePursuit\",\r\n\t\"BombSquad\",\r\n\t\"Exfil\",\r\n\t\"Vertigo\",\r\n] as const;\r\n\r\nexport async function startProject(\r\n\tdestination: string,\r\n\ttemplate: (typeof templates)[number] | \"None\",\r\n\tname?: string,\r\n) {\r\n\tif ([\"AcePursuit\", \"BombSquad\", \"Exfil\", \"Vertigo\"].includes(template)) {\r\n\t\tconst importPath = path.resolve(templatesDir, `${template}.json`);\r\n\t\tawait importFile(importPath, destination, name);\r\n\t} else if (template === \"None\") {\r\n\t\t// Do nothing if none\r\n\t} else {\r\n\t\t// Handles the Basic and any other template provided\r\n\t\tconst templateDir = path.resolve(templatesDir, template);\r\n\t\tfs.cpSync(templateDir, destination, { recursive: true });\r\n\t}\r\n\r\n\tfs.cpSync(path.resolve(templatesDir, \"All\"), destination, {\r\n\t\trecursive: true,\r\n\t});\r\n\r\n\tif (name) renameFilesRecursively(destination, name);\r\n}\r\n\r\nexport function installDependencies(projectDir: string) {\r\n\ttry {\r\n\t\tchild_process.execSync(`npm install`, {\r\n\t\t\tstdio: \"inherit\",\r\n\t\t\tcwd: projectDir,\r\n\t\t});\r\n\t\treturn true;\r\n\t} catch (_err) {\r\n\t\treturn false;\r\n\t}\r\n}\r\n\r\nconst _defaultTargetDir = \"bf6-mod\";\r\nconst cancel = () => prompts.cancel(\"Operation cancelled\");\r\n\r\nfunction isEmpty(path: string) {\r\n\tconst files = fs.readdirSync(path);\r\n\treturn files.length === 0 || (files.length === 1 && files[0] === \".git\");\r\n}\r\n\r\nfunction emptyDir(dir: string) {\r\n\tif (!fs.existsSync(dir)) {\r\n\t\treturn;\r\n\t}\r\n\tfor (const file of fs.readdirSync(dir)) {\r\n\t\tif (file === \".git\") {\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\tfs.rmSync(path.resolve(dir, file), { recursive: true, force: true });\r\n\t}\r\n}\r\n\r\nexport async function init(argTargetDir?: string) {\r\n\tprompts.intro(\"Initialize Bf6 Mod\");\r\n\r\n\tconst path = argTargetDir\r\n\t\t? argTargetDir\r\n\t\t: await prompts.text({\r\n\t\t\t\tmessage: \"Where should we create your project?\",\r\n\t\t\t\tplaceholder: \"./ace-pursuit\",\r\n\t\t\t\tvalidate: (value) => {\r\n\t\t\t\t\tif (!value) return \"Please enter a path.\";\r\n\t\t\t\t\tif (value[0] !== \".\") return \"Please enter a relative path.\";\r\n\t\t\t\t},\r\n\t\t\t});\r\n\tif (prompts.isCancel(path)) return cancel();\r\n\r\n\tlet name = await prompts.text({\r\n\t\tmessage: \"What is the name of your mod?\",\r\n\t\tplaceholder: \"Ace Pursuit\",\r\n\t\tvalidate: (value) => {\r\n\t\t\tif (!value.trim()) return \"Please enter a name.\";\r\n\t\t},\r\n\t});\r\n\tif (prompts.isCancel(name)) return cancel();\r\n\tname = name.trim();\r\n\r\n\tif (fs.existsSync(path) && !isEmpty(path)) {\r\n\t\tlet overwrite: \"yes\" | \"no\" | \"ignore\" | undefined;\r\n\t\tconst res = await prompts.select({\r\n\t\t\tmessage:\r\n\t\t\t\t(path === \".\" ? \"Current directory\" : `Target directory \"${path}\"`) +\r\n\t\t\t\t` is not empty. Please choose how to proceed:`,\r\n\t\t\toptions: [\r\n\t\t\t\t{\r\n\t\t\t\t\tlabel: \"Cancel operation\",\r\n\t\t\t\t\tvalue: \"no\",\r\n\t\t\t\t},\r\n\t\t\t\t{\r\n\t\t\t\t\tlabel: \"Remove existing files and continue\",\r\n\t\t\t\t\tvalue: \"yes\",\r\n\t\t\t\t},\r\n\t\t\t\t{\r\n\t\t\t\t\tlabel: \"Ignore files and continue\",\r\n\t\t\t\t\tvalue: \"ignore\",\r\n\t\t\t\t},\r\n\t\t\t],\r\n\t\t});\r\n\t\tif (prompts.isCancel(res)) return cancel();\r\n\t\toverwrite = res;\r\n\r\n\t\tswitch (overwrite) {\r\n\t\t\tcase \"yes\":\r\n\t\t\t\temptyDir(path);\r\n\t\t\t\tbreak;\r\n\t\t\tcase \"no\":\r\n\t\t\t\tcancel();\r\n\t\t\t\treturn;\r\n\t\t}\r\n\t}\r\n\r\n\tconst template = await prompts.select({\r\n\t\tmessage: \"Select a template:\",\r\n\t\toptions: templates.map((template) => {\r\n\t\t\treturn {\r\n\t\t\t\tlabel: template,\r\n\t\t\t\tvalue: template,\r\n\t\t\t};\r\n\t\t}),\r\n\t});\r\n\tif (prompts.isCancel(template)) return cancel();\r\n\r\n\tawait startProject(path, template, name);\r\n\r\n\tconst s = prompts.spinner();\r\n\ts.start(\"Installing via npm\");\r\n\tconst installed = installDependencies(path);\r\n\tif (installed) s.stop(\"Installed via npm\");\r\n\telse s.stop(\"Failed to install via npm\", 1);\r\n\r\n\tconst nextSteps = `cd ${path}\\nnpm run build`;\r\n\r\n\tprompts.note(nextSteps, \"Next steps.\");\r\n}\r\n","import fs from \"node:fs\";\r\nimport path from \"node:path\";\r\nimport { fileURLToPath } from \"node:url\";\r\nimport colors from \"colors\";\r\nimport { genExport, genInlineTypeImport } from \"knitwork\";\r\nimport { printToConsole } from \"./utils.js\";\r\n\r\nexport async function prepare() {\r\n\ttry {\r\n\t\tconst __filename = fileURLToPath(import.meta.url);\r\n\t\tconst __dirname = path.dirname(__filename);\r\n\r\n\t\tconst _workingDir = path.resolve(\".\");\r\n\t\tconst buildDir = path.resolve(\".bf6\");\r\n\r\n\t\tconst resources = path.resolve(__dirname, \"../resources/prepare\");\r\n\r\n\t\tfs.cpSync(\r\n\t\t\tpath.resolve(resources, \"tsconfig.json\"),\r\n\t\t\tpath.resolve(buildDir, \"tsconfig.json\"),\r\n\t\t);\r\n\t\tfs.cpSync(\r\n\t\t\tpath.resolve(resources, \"bf6.d.ts\"),\r\n\t\t\tpath.resolve(buildDir, \"bf6.d.ts\"),\r\n\t\t);\r\n\t\tfs.cpSync(\r\n\t\t\tpath.resolve(resources, \"types\", \"config.ts\"),\r\n\t\t\tpath.resolve(buildDir, \"types\", \"config.ts\"),\r\n\t\t);\r\n\r\n\t\tconst ConfigFileExports = genExport(\"./types/config.ts\", [\r\n\t\t\t\"defineBf6Config\",\r\n\t\t]);\r\n\t\tfs.writeFileSync(\r\n\t\t\tpath.resolve(buildDir, \"imports.d.ts\"),\r\n\t\t\t`${ConfigFileExports}\\n`,\r\n\t\t);\r\n\r\n\t\tconst augmentations: Record<string, string> = {\r\n\t\t\tdefineBf6Config: genInlineTypeImport(\r\n\t\t\t\t\"./types/config.ts\",\r\n\t\t\t\t`defineBf6Config`,\r\n\t\t\t),\r\n\t\t\tMapId: genInlineTypeImport(\"./types/config.ts\", `MapId`),\r\n\t\t};\r\n\r\n\t\tconst args = genNamespaceAugmentation(\"global\", augmentations);\r\n\t\tfs.writeFileSync(\r\n\t\t\tpath.resolve(buildDir, \"globals.d.ts\"),\r\n\t\t\t`export {}\\n\\n${args}\\n`,\r\n\t\t);\r\n\r\n\t\tprintToConsole(`${colors.green(\"✔\")} Types generated in .bf6`);\r\n\t} catch (error) {\r\n\t\tconsole.error(error);\r\n\t\tprintToConsole(`${colors.red(\"✗\")} Types failed to generate in .bf6`);\r\n\t}\r\n}\r\n\r\nconst genNamespaceAugmentation = (\r\n\tname: string,\r\n\tcontents: Record<string, string>,\r\n) => {\r\n\tif (!contents || Object.keys(contents).length === 0)\r\n\t\treturn `declare ${name} {}`;\r\n\tconst decls = Object.entries(contents)\r\n\t\t.map(([k, v]) => `\\tconst ${k}: ${v};`)\r\n\t\t.join(\"\\n\");\r\n\treturn `declare ${name} {\\n${decls}\\n}`;\r\n};\r\n","import colors from \"colors\";\r\nimport stripAnsi from \"strip-ansi\";\r\n\r\n/**\r\n * Safely prints a message with a right-aligned timestamp.\r\n */\r\nexport const printToConsole = (message: string) => {\r\n\tconst now = new Date();\r\n\tconst formattedTime = colors.grey(now.toLocaleTimeString());\r\n\tconst terminalWidth = process.stdout.columns || 80;\r\n\r\n\tconst timeLength = stripAnsi(formattedTime).length;\r\n\tconst messageLength = stripAnsi(message).length;\r\n\tconst available = terminalWidth - (messageLength + timeLength);\r\n\r\n\tconst spacing = available > 1 ? \" \".repeat(available) : \" \";\r\n\r\n\tconsole.log(`${message}${spacing}${formattedTime}`);\r\n};\r\n","export default function ansiRegex({onlyFirst = false} = {}) {\n\t// Valid string terminator sequences are BEL, ESC\\, and 0x9c\n\tconst ST = '(?:\\\\u0007|\\\\u001B\\\\u005C|\\\\u009C)';\n\n\t// OSC sequences only: ESC ] ... ST (non-greedy until the first ST)\n\tconst osc = `(?:\\\\u001B\\\\][\\\\s\\\\S]*?${ST})`;\n\n\t// CSI and related: ESC/C1, optional intermediates, optional params (supports ; and :) then final byte\n\tconst csi = '[\\\\u001B\\\\u009B][[\\\\]()#;?]*(?:\\\\d{1,4}(?:[;:]\\\\d{0,4})*)?[\\\\dA-PR-TZcf-nq-uy=><~]';\n\n\tconst pattern = `${osc}|${csi}`;\n\n\treturn new RegExp(pattern, onlyFirst ? undefined : 'g');\n}\n","import ansiRegex from 'ansi-regex';\n\nconst regex = ansiRegex();\n\nexport default function stripAnsi(string) {\n\tif (typeof string !== 'string') {\n\t\tthrow new TypeError(`Expected a \\`string\\`, got \\`${typeof string}\\``);\n\t}\n\n\t// Even though the regex is global, we don't need to reset the `.lastIndex`\n\t// because unlike `.exec()` and `.test()`, `.replace()` does it automatically\n\t// and doing it manually has a performance penalty.\n\treturn string.replace(regex, '');\n}\n"],"mappings":"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","names":["MapId","fs","path","path","fs","fs","path","AttachmentType","fs","path","path","fs","cancel","path","fs","template","path","fs","AttachmentType","fs","path","fileURLToPath","colors","colors","colors","__filename","fileURLToPath","__dirname","path","fs","colors"]}
|
|
1
|
+
{"version":3,"sources":["../../src/cli/index.ts","../../package.json","../../src/cli/build/index.ts","../../src/resources/prepare/types/config.ts","../../src/cli/build/generated-strings.ts","../../src/cli/dev.ts","../../src/cli/import.ts","../../src/cli/init.ts","../../src/cli/prepare.ts","../../src/cli/utils.ts","../../../../node_modules/ansi-regex/index.js","../../../../node_modules/strip-ansi/index.js"],"sourcesContent":["#!/usr/bin/env node\nimport { Command } from \"commander\";\nimport pkg from \"../../package.json\" with { type: \"json\" };\nimport { build } from \"./build/index.ts\";\nimport { dev } from \"./dev.ts\";\nimport { importFile } from \"./import.ts\";\nimport { init, installDependencies } from \"./init.js\";\nimport { prepare } from \"./prepare.js\";\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.description(\"Create a new bf6 mod\")\n\t.action(async (directory) => {\n\t\tawait init(directory);\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.description(\"decompiles the json config of a mod into a new project\")\n\t.action(async (input, output) => {\n\t\tawait importFile(input as string, output as string);\n\t\tinstallDependencies(output);\n\t});\n\nprogram.exitOverride((_err) => {\n\tif (process.env.EXIT_CODE === \"none\") process.exit(0);\n});\n\nprogram.parse();\n","{\n\t\"name\": \"@bf6mods/cli\",\n\t\"version\": \"1.0.2\",\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\": \"tsup\",\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/sdk\": \"1.0.3\",\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\"jiti\": \"^2.6.1\",\n\t\t\"knitwork\": \"^1.2.0\",\n\t\t\"rolldown\": \"^1.0.0-beta.43\",\n\t\t\"stringify-object\": \"^6.0.0\"\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\"tsx\": \"^4.20.6\"\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 { createJiti } from \"jiti\";\nimport { type Plugin, rolldown } from \"rolldown\";\nimport {\n\ttype Bf6Config,\n\tMapId as MapIdEnum,\n} from \"../../resources/prepare/types/config.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(rootDir: string): Promise<Bf6Config> {\n\tglobalThis.defineBf6Config = (c) => c;\n\tglobalThis.MapId = MapIdEnum;\n\tconst jiti = createJiti(rootDir, { interopDefault: true });\n\tconst result = await jiti.import(\"./bf6.config\", { default: true });\n\tdelete globalThis.defineBf6Config;\n\tdelete globalThis.MapId;\n\treturn result as Bf6Config;\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\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\tconsole.log(`✔ Built mod: ${config.name}`);\n}\n\nexport function helloPlugin(message = \"hello-plugin ran ✅\"): Plugin {\n\treturn {\n\t\tname: \"hello-plugin\",\n\n\t\t// Fires once when the build starts\n\t\tbuildStart() {\n\t\t\t// Prefer the bundler's logger so it shows up in Rolldown's output\n\t\t\t// (Rolldown forwards plugin warnings to the console.)\n\t\t\ttry {\n\t\t\t\t// Rollup-style API: this.warn(...) is widely supported\n\t\t\t\tthis.warn({ code: \"HELLO_PLUGIN\", message });\n\t\t\t} catch {\n\t\t\t\t// Fallback if the context logger isn't available\n\t\t\t\t// (e.g., if API changes or running programmatically)\n\t\t\t\tconsole.log(`[hello-plugin] ${message}`);\n\t\t\t}\n\t\t},\n\n\t\t// Also log at bundle time to show multiple hook points\n\t\tgenerateBundle() {\n\t\t\ttry {\n\t\t\t\tthis.warn({\n\t\t\t\t\tcode: \"HELLO_PLUGIN\",\n\t\t\t\t\tmessage: `${message} (generateBundle)`,\n\t\t\t\t});\n\t\t\t} catch {\n\t\t\t\tconsole.log(`[hello-plugin] ${message} (generateBundle)`);\n\t\t\t}\n\t\t},\n\t};\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});\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) {\n\t\tconst strPath = path.resolve(workingDir, config.strings);\n\t\tif (!fs.existsSync(strPath)) throw new Error(\"Cannot find strings file\");\n\t\tconst raw = await fs.promises.readFile(strPath, \"utf8\");\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 type { ConfigType } from \"@bf6mods/sdk\";\n\nexport enum MapId {\n\tFireStorm = \"MP_FireStorm-ModBuilderCustom0\",\n\tSiegeOfCairo = \"MP_Abbasid-ModBuilderCustom0\",\n\tEmpireState = \"MP_Aftermath-ModBuilderCustom0\",\n\tIberianOffensive = \"MP_Battery-ModBuilderCustom0\",\n\tLiberationPeak = \"MP_Capstone-ModBuilderCustom0\",\n\tManhattanBridge = \"MP_Dumbo-ModBuilderCustom0\",\n\tSaintsQuarter = \"MP_Limestone-ModBuilderCustom0\",\n\tNewSobekCity = \"MP_Outskirts-ModBuilderCustom0\",\n\tMirakValley = \"MP_Tungsten-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 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 type { Node, ObjectProperty, VariableDeclarator } from \"@oxc-project/types\";\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\t\tconst snippet = getSnippet(...(declaration.range ?? [0, 0]));\n\t\t\t\t\t\t\tthis.error(\n\t\t\t\t\t\t\t\t`❌ Invalid bf6Strings export: expected an object literal.\\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\tfor (const property of declaration.init.properties) {\n\t\t\t\t\t\t\tif (property.type !== \"Property\") {\n\t\t\t\t\t\t\t\tconst snippet = getSnippet(...(property.range ?? [0, 0]));\n\t\t\t\t\t\t\t\tthis.error(\n\t\t\t\t\t\t\t\t\t`❌ Invalid bf6Strings property: expected a key/value pair.\\nFound type: ${property.type}\\n\\n${snippet}`,\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tlet key: string | number | bigint | boolean | RegExp | null | undefined = undefined;\n\t\t\t\t\t\t\tif (property.key.type === \"Literal\") {\n\t\t\t\t\t\t\t\tkey = property.key.value;\n\t\t\t\t\t\t\t} else if (property.key.type === \"Identifier\") {\n\t\t\t\t\t\t\t\tkey = property.key.name;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tconst snippet = getSnippet(...(property.range ?? [0, 0]));\n\t\t\t\t\t\t\t\tthis.error(\n\t\t\t\t\t\t\t\t\t`❌ 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\t);\n\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif (property.value.type !== \"Literal\") {\n\t\t\t\t\t\t\t\tconst snippet = getSnippet(...(property.range ?? [0, 0]));\n\t\t\t\t\t\t\t\tthis.error(\n\t\t\t\t\t\t\t\t\t`❌ Invalid bf6Strings value: expected a string literal.\\nFound type: ${property.value.type}\\n\\n${snippet}`,\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tconst value = property.value.value;\n\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\ttypeof key !== \"string\" &&\n\t\t\t\t\t\t\t\ttypeof key !== \"number\" &&\n\t\t\t\t\t\t\t\ttypeof key !== \"bigint\" &&\n\t\t\t\t\t\t\t\ttypeof key !== \"boolean\"\n\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\tconst snippet = getSnippet(...(property.range ?? [0, 0]));\n\t\t\t\t\t\t\t\tthis.error(\n\t\t\t\t\t\t\t\t\t`❌ bf6Strings key must be a string, found: ${typeof key}\\n\\n${snippet}`,\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\ttypeof value !== \"string\" &&\n\t\t\t\t\t\t\t\ttypeof value !== \"number\" &&\n\t\t\t\t\t\t\t\ttypeof value !== \"bigint\" &&\n\t\t\t\t\t\t\t\ttypeof value !== \"boolean\"\n\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\tconst snippet = getSnippet(...(property.range ?? [0, 0]));\n\t\t\t\t\t\t\t\tthis.error(\n\t\t\t\t\t\t\t\t\t`❌ bf6Strings value must be a string, found: ${typeof value}\\n\\n${snippet}`,\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tbf6Strings[`${key}`] = `${value}`;\n\t\t\t\t\t\t}\n\t\t\t\t}\n\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 (item.type === \"ExportNamedDeclaration\" && item.declaration?.type === \"VariableDeclaration\") {\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 { glob } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport chokidar, { type FSWatcher } from \"chokidar\";\nimport colors from \"colors\";\nimport { build, getBf6Config } from \"./build/index.ts\";\n\nexport async function dev() {\n\tconst workingDir = path.resolve(\".\");\n\tlet config = await getBf6Config(workingDir);\n\tconst outDir = path.resolve(workingDir, config.outDir);\n\tif (!fs.existsSync(outDir)) fs.mkdirSync(outDir, { recursive: true });\n\n\tconsole.log(colors.cyan(`▶ Starting dev for ${config.name}`));\n\n\tlet watcher: FSWatcher | undefined;\n\n\tasync function rebuild(trigger: string) {\n\t\tconsole.log(\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 end = performance.now();\n\t\t\tconst duration = ((end - start) / 1000).toFixed(2);\n\t\t\tconsole.log(colors.green(`✔ Updated mod.json (${duration}s)`));\n\t\t} catch (err) {\n\t\t\tconsole.error(colors.red(`✖ Rebuild failed: ${(err as Error).message}`));\n\t\t}\n\t}\n\n\tasync function collectWatchTargets(): 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\t\t}\n\t\t}\n\t\tif (config.strings) targets.push(path.resolve(workingDir, config.strings));\n\n\t\tconst srcDir = path.resolve(workingDir, \"src\");\n\t\tfor await (const entry of glob(`${srcDir}/**/*`)) targets.push(entry);\n\n\t\tfor await (const entry of glob(\"bf6.config.*\")) targets.push(entry);\n\n\t\treturn targets;\n\t}\n\n\tasync function setupWatcher() {\n\t\tif (watcher) {\n\t\t\tawait watcher.close();\n\t\t\tconsole.log(colors.grey(\"♻ Reloading watcher due to config change...\"));\n\t\t}\n\n\t\tconst watchTargets = await collectWatchTargets();\n\n\t\twatcher = chokidar.watch(watchTargets, {\n\t\t\tpersistent: true,\n\t\t\tignoreInitial: true,\n\t\t\tawaitWriteFinish: true,\n\t\t\tignored: [path.resolve(outDir), `${path.resolve(outDir)}/**`],\n\t\t});\n\n\t\twatcher.on(\"change\", async (file) => {\n\t\t\tif (file.includes(\"bf6.config.\")) {\n\t\t\t\tconsole.log(\n\t\t\t\t\tcolors.magenta(\n\t\t\t\t\t\t\"⚙ Config changed — reloading and rebuilding watcher...\",\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t\ttry {\n\t\t\t\t\tconfig = await getBf6Config(workingDir);\n\t\t\t\t\tawait setupWatcher();\n\t\t\t\t} catch (err) {\n\t\t\t\t\tconsole.error(\n\t\t\t\t\t\tcolors.red(`✖ Failed to reload config: ${(err as Error).message}`),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tawait rebuild(file);\n\t\t});\n\n\t\twatcher.on(\"add\", async (file) => await rebuild(file));\n\n\t\tawait rebuild(\"initial\");\n\t}\n\n\tawait setupWatcher();\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { AttachmentType, type ConfigType } from \"@bf6mods/sdk\";\nimport stringifyObject from \"stringify-object\";\nimport { MapId as MapIdEnum } from \"../resources/prepare/types/config.ts\";\nimport { startProject } from \"./init.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(input: string, output: string, name?: string) {\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\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\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\tfor (const attachment of config.attachments) {\n\t\t\tif (attachment.attachmentType === AttachmentType.TypeScript)\n\t\t\t\ttypescriptFile = attachment.filename;\n\n\t\t\tif (attachment.attachmentType === AttachmentType.Strings)\n\t\t\t\tstringsFile = attachment.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\", attachment.filename),\n\t\t\t\t\tatob(attachment.attachmentData.original),\n\t\t\t\t),\n\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\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\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 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 { 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\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\"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\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(argTargetDir?: string) {\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 = await prompts.text({\n\t\tmessage: \"What is the name of your mod?\",\n\t\tplaceholder: \"Ace Pursuit\",\n\t\tvalidate: (value) => {\n\t\t\tif (!value.trim()) return \"Please enter a name.\";\n\t\t},\n\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\tconst res = await prompts.select({\n\t\t\tmessage:\n\t\t\t\t(path === \".\" ? \"Current directory\" : `Target directory \"${path}\"`) +\n\t\t\t\t` is not empty. Please choose how to proceed:`,\n\t\t\toptions: [\n\t\t\t\t{\n\t\t\t\t\tlabel: \"Cancel operation\",\n\t\t\t\t\tvalue: \"no\",\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tlabel: \"Remove existing files and continue\",\n\t\t\t\t\tvalue: \"yes\",\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tlabel: \"Ignore files and continue\",\n\t\t\t\t\tvalue: \"ignore\",\n\t\t\t\t},\n\t\t\t],\n\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 = await prompts.select({\n\t\tmessage: \"Select a template:\",\n\t\toptions: templates.map((template) => {\n\t\t\treturn {\n\t\t\t\tlabel: template,\n\t\t\t\tvalue: template,\n\t\t\t};\n\t\t}),\n\t});\n\tif (prompts.isCancel(template)) return cancel();\n\n\tawait startProject(path, template, name);\n\n\tconst s = prompts.spinner();\n\ts.start(\"Installing via npm\");\n\tconst installed = installDependencies(path);\n\tif (installed) s.stop(\"Installed via npm\");\n\telse s.stop(\"Failed to install via npm\", 1);\n\n\tconst nextSteps = `cd ${path}\\nnpm run build`;\n\n\tprompts.note(nextSteps, \"Next steps.\");\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(\"✔\")} Types generated in .bf6`);\n\t} catch (error) {\n\t\tconsole.error(error);\n\t\tprintToConsole(`${colors.red(\"✗\")} Types failed to generate in .bf6`);\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","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) => {\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\tconsole.log(`${message}${spacing}${formattedTime}`);\n};\n","export default function ansiRegex({onlyFirst = false} = {}) {\n\t// Valid string terminator sequences are BEL, ESC\\, and 0x9c\n\tconst ST = '(?:\\\\u0007|\\\\u001B\\\\u005C|\\\\u009C)';\n\n\t// OSC sequences only: ESC ] ... ST (non-greedy until the first ST)\n\tconst osc = `(?:\\\\u001B\\\\][\\\\s\\\\S]*?${ST})`;\n\n\t// CSI and related: ESC/C1, optional intermediates, optional params (supports ; and :) then final byte\n\tconst csi = '[\\\\u001B\\\\u009B][[\\\\]()#;?]*(?:\\\\d{1,4}(?:[;:]\\\\d{0,4})*)?[\\\\dA-PR-TZcf-nq-uy=><~]';\n\n\tconst pattern = `${osc}|${csi}`;\n\n\treturn new RegExp(pattern, onlyFirst ? undefined : 'g');\n}\n","import ansiRegex from 'ansi-regex';\n\nconst regex = ansiRegex();\n\nexport default function stripAnsi(string) {\n\tif (typeof string !== 'string') {\n\t\tthrow new TypeError(`Expected a \\`string\\`, got \\`${typeof string}\\``);\n\t}\n\n\t// Even though the regex is global, we don't need to reset the `.lastIndex`\n\t// because unlike `.exec()` and `.test()`, `.replace()` does it automatically\n\t// and doing it manually has a performance penalty.\n\treturn string.replace(regex, '');\n}\n"],"mappings":"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","names":["MapId","walk","program","fs","path","path","fs","fs","path","AttachmentType","fs","path","fileURLToPath","__filename","fileURLToPath","__dirname","path","fs","cancel","path","fs","template","path","fs","AttachmentType","fs","path","fileURLToPath","colors","colors","colors","__filename","fileURLToPath","__dirname","path","fs","colors"]}
|