ttmg-pack 0.2.8 → 0.2.9-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/constants/index.d.ts +14 -0
- package/dist/index.js +329 -90
- package/dist/index.js.map +1 -1
- package/dist/libs/buildPkgs/index.d.ts +2 -1
- package/dist/libs/buildPlugins/index.d.ts +2 -0
- package/dist/libs/debugPkgs/index.d.ts +1 -1
- package/dist/libs/makePkgs/addDepsToPackages.d.ts +17 -0
- package/dist/libs/makePkgs/collectDeps.d.ts +4 -1
- package/dist/libs/makePkgs/collectMaps.d.ts +1 -0
- package/dist/libs/makePkgs/index.d.ts +5 -0
- package/dist/libs/makePkgs/pack.d.ts +1 -1
- package/dist/typings/index.d.ts +1 -0
- package/dist/utils/cpDir.d.ts +1 -0
- package/dist/utils/getCheckConfig.d.ts +2 -0
- package/dist/utils/index.d.ts +3 -2
- package/dist/utils/overrideConfig.d.ts +1 -1
- package/dist/utils/unity/getUnityBuildConfig.d.ts +2 -0
- package/dist/utils/unity/index.d.ts +1 -0
- package/package.json +1 -1
- package/CHANGELOG.md +0 -333
- package/dist/libs/checkPkgs/checkPkgPath.d.ts +0 -1
- package/dist/libs/extractPkgs/hasAnyNodeModulesShallow.d.ts +0 -1
- package/dist/libs/extractPkgs/index.d.ts +0 -6
- package/dist/libs/makePkgs/extract/NodeModuleExtractor.d.ts +0 -39
- package/dist/libs/makePkgs/extract/hasAnyNodeModulesShallow.d.ts +0 -1
- package/dist/libs/makePkgs/extract/index.d.ts +0 -6
- package/dist/libs/makePkgs/extract.d.ts +0 -4
- package/dist/utils/NodeModuleExtractor.d.ts +0 -38
|
@@ -37,3 +37,17 @@ export declare const GAME_ENGINES: {
|
|
|
37
37
|
export declare const TTMG_TEMP_DIR = "__TTMG_TEMP__";
|
|
38
38
|
export declare const USELESS_DIRS: string[];
|
|
39
39
|
export declare const USELESS_FILES: string[];
|
|
40
|
+
export declare const GAME_PKG_SIZE_LIMIT: {
|
|
41
|
+
common: {
|
|
42
|
+
project: number;
|
|
43
|
+
main: number;
|
|
44
|
+
sub: any;
|
|
45
|
+
independent: number;
|
|
46
|
+
};
|
|
47
|
+
unity: {
|
|
48
|
+
project: number;
|
|
49
|
+
main: any;
|
|
50
|
+
sub: any;
|
|
51
|
+
independent: any;
|
|
52
|
+
};
|
|
53
|
+
};
|
package/dist/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* ==========================================
|
|
3
3
|
* @Description: ttmg pack
|
|
4
|
-
* @Version: 0.2.
|
|
4
|
+
* @Version: 0.2.9-beta.2
|
|
5
5
|
* @Author: zhanghongyang.mocha
|
|
6
|
-
* @Date: 2026-01-
|
|
6
|
+
* @Date: 2026-01-22 19:16:02
|
|
7
7
|
* ==========================================
|
|
8
8
|
*/
|
|
9
9
|
'use strict';
|
|
@@ -149,6 +149,13 @@ const PACKAGE_TYPE = {
|
|
|
149
149
|
const TTMG_TEMP_DIR = '__TTMG_TEMP__';
|
|
150
150
|
const USELESS_DIRS = ['node_modules', '__MACOSX', TTMG_TEMP_DIR];
|
|
151
151
|
const USELESS_FILES = ['.DS_Store', 'Thumbs.db'];
|
|
152
|
+
const GAME_PKG_SIZE_LIMIT = {
|
|
153
|
+
unity: {
|
|
154
|
+
project: 60 * 1024 * 1024,
|
|
155
|
+
main: null,
|
|
156
|
+
independent: null,
|
|
157
|
+
},
|
|
158
|
+
};
|
|
152
159
|
|
|
153
160
|
/**
|
|
154
161
|
* 递归统计目录下所有文件的大小,支持过滤文件夹和文件
|
|
@@ -432,59 +439,6 @@ function getGameEngine(gameEntry) {
|
|
|
432
439
|
}
|
|
433
440
|
}
|
|
434
441
|
|
|
435
|
-
function isUnityEngine(gameEntry) {
|
|
436
|
-
return getGameEngine(gameEntry) === 'unity';
|
|
437
|
-
}
|
|
438
|
-
|
|
439
|
-
function getWasmBrCodePath({ entryDir, }) {
|
|
440
|
-
if (!isUnityEngine(entryDir)) {
|
|
441
|
-
return '';
|
|
442
|
-
}
|
|
443
|
-
else {
|
|
444
|
-
/**
|
|
445
|
-
* 检查项目下存在一个名为 wasmcode 的文件夹,且文件夹下存在一个文件后缀为 .webgl.wasm.code.unityweb.wasm.br 的文件。,如果满足条件,就展示 true,否则 返回 false
|
|
446
|
-
*/
|
|
447
|
-
const wasmCodeDir = path.join(entryDir, 'wasmcode');
|
|
448
|
-
if (!fs.existsSync(wasmCodeDir)) {
|
|
449
|
-
return '';
|
|
450
|
-
}
|
|
451
|
-
const wasmBrFiles = fs.readdirSync(wasmCodeDir).filter(file => file.endsWith('.webgl.wasm.code.unityweb.wasm.br'));
|
|
452
|
-
if (wasmBrFiles.length === 0) {
|
|
453
|
-
return '';
|
|
454
|
-
}
|
|
455
|
-
else {
|
|
456
|
-
return path.relative(entryDir, path.join(wasmCodeDir, wasmBrFiles[0]));
|
|
457
|
-
}
|
|
458
|
-
}
|
|
459
|
-
}
|
|
460
|
-
|
|
461
|
-
function getWasmBrCodeMd5({ entryDir }) {
|
|
462
|
-
// originalWasmMd5
|
|
463
|
-
try {
|
|
464
|
-
const gameConfig = JSON.parse(fs.readFileSync(path.join(entryDir, 'game.json'), 'utf-8'));
|
|
465
|
-
return gameConfig.originalWasmMd5 || '';
|
|
466
|
-
}
|
|
467
|
-
catch (_a) {
|
|
468
|
-
return '';
|
|
469
|
-
}
|
|
470
|
-
}
|
|
471
|
-
|
|
472
|
-
// 面向高鹏编程 😢
|
|
473
|
-
/**
|
|
474
|
-
* 覆盖配置,根据游戏引擎类型,设置主包和独立子包的大小限制
|
|
475
|
-
* @param entryDir 游戏项目入口目录
|
|
476
|
-
* @param config 原始构建配置
|
|
477
|
-
* @returns 覆盖后的构建配置
|
|
478
|
-
*/
|
|
479
|
-
function overrideConfig(config) {
|
|
480
|
-
var _a, _b, _c;
|
|
481
|
-
const { entry: entryDir } = config;
|
|
482
|
-
const isUnity = isUnityEngine(entryDir);
|
|
483
|
-
return Object.assign(Object.assign({}, config), { build: Object.assign(Object.assign({}, config.build), { pkgSizeLimit: !isUnity ? (_a = config.build) === null || _a === void 0 ? void 0 : _a.pkgSizeLimit : 60 * 1024 * 1024, mainPkgSizeLimit: !isUnity ? (_b = config.build) === null || _b === void 0 ? void 0 : _b.mainPkgSizeLimit : null, independentSubPkgSizeLimit: !isUnity
|
|
484
|
-
? (_c = config.build) === null || _c === void 0 ? void 0 : _c.independentSubPkgSizeLimit
|
|
485
|
-
: null }) });
|
|
486
|
-
}
|
|
487
|
-
|
|
488
442
|
let initializePromise = null;
|
|
489
443
|
/**
|
|
490
444
|
* 确保一个异步函数在整个应用生命周期内只被执行一次。
|
|
@@ -605,6 +559,98 @@ async function genOpenDataContext(entryPath) {
|
|
|
605
559
|
return jsCode;
|
|
606
560
|
}
|
|
607
561
|
|
|
562
|
+
function isUnityEngine(gameEntry) {
|
|
563
|
+
return getGameEngine(gameEntry) === 'unity';
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
function getWasmBrCodePath({ entryDir, }) {
|
|
567
|
+
if (!isUnityEngine(entryDir)) {
|
|
568
|
+
return '';
|
|
569
|
+
}
|
|
570
|
+
else {
|
|
571
|
+
/**
|
|
572
|
+
* 检查项目下存在一个名为 wasmcode 的文件夹,且文件夹下存在一个文件后缀为 .webgl.wasm.code.unityweb.wasm.br 的文件。,如果满足条件,就展示 true,否则 返回 false
|
|
573
|
+
*/
|
|
574
|
+
const wasmCodeDir = path.join(entryDir, 'wasmcode');
|
|
575
|
+
if (!fs.existsSync(wasmCodeDir)) {
|
|
576
|
+
return '';
|
|
577
|
+
}
|
|
578
|
+
const wasmBrFiles = fs.readdirSync(wasmCodeDir).filter(file => file.endsWith('.webgl.wasm.code.unityweb.wasm.br'));
|
|
579
|
+
if (wasmBrFiles.length === 0) {
|
|
580
|
+
return '';
|
|
581
|
+
}
|
|
582
|
+
else {
|
|
583
|
+
return path.relative(entryDir, path.join(wasmCodeDir, wasmBrFiles[0]));
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
function getWasmBrCodeMd5({ entryDir }) {
|
|
589
|
+
// originalWasmMd5
|
|
590
|
+
try {
|
|
591
|
+
const gameConfig = JSON.parse(fs.readFileSync(path.join(entryDir, 'game.json'), 'utf-8'));
|
|
592
|
+
return gameConfig.originalWasmMd5 || '';
|
|
593
|
+
}
|
|
594
|
+
catch (_a) {
|
|
595
|
+
return '';
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
function getUnityBuildConfig() {
|
|
600
|
+
return {
|
|
601
|
+
pkgSizeLimit: GAME_PKG_SIZE_LIMIT.unity.project,
|
|
602
|
+
mainPkgSizeLimit: GAME_PKG_SIZE_LIMIT.unity.main,
|
|
603
|
+
independentSubPkgSizeLimit: GAME_PKG_SIZE_LIMIT.unity.independent,
|
|
604
|
+
};
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
function getCheckConfig(config) {
|
|
608
|
+
if (isUnityEngine(config.entry)) {
|
|
609
|
+
return getUnityBuildConfig();
|
|
610
|
+
}
|
|
611
|
+
else {
|
|
612
|
+
return {
|
|
613
|
+
pkgSizeLimit: 30 * 1024 * 1024,
|
|
614
|
+
mainPkgSizeLimit: 4 * 1024 * 1024,
|
|
615
|
+
independentSubPkgSizeLimit: 4 * 1024 * 1024,
|
|
616
|
+
};
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
function copyDirectory(src, dest) {
|
|
621
|
+
try {
|
|
622
|
+
if (!fs.existsSync(dest)) {
|
|
623
|
+
fs.mkdirSync(dest, { recursive: true });
|
|
624
|
+
}
|
|
625
|
+
const items = fs.readdirSync(src);
|
|
626
|
+
const normalizedDest = path.resolve(dest) + path.sep;
|
|
627
|
+
items.forEach(item => {
|
|
628
|
+
const srcPath = path.join(src, item);
|
|
629
|
+
const destPath = path.join(dest, item);
|
|
630
|
+
// 检查当前要处理的源路径是否就是目标路径
|
|
631
|
+
// 这可以防止将目标目录本身复制到自身中
|
|
632
|
+
if (path.resolve(srcPath) === path.resolve(dest)) {
|
|
633
|
+
return; // 跳过目标目录本身
|
|
634
|
+
}
|
|
635
|
+
// 获取文件状态
|
|
636
|
+
const stat = fs.statSync(srcPath);
|
|
637
|
+
if (stat.isFile()) {
|
|
638
|
+
// 复制文件
|
|
639
|
+
fs.copyFileSync(srcPath, destPath);
|
|
640
|
+
}
|
|
641
|
+
else if (stat.isDirectory()) {
|
|
642
|
+
const childNormalizedSrc = path.resolve(srcPath) + path.sep;
|
|
643
|
+
if (!normalizedDest.startsWith(childNormalizedSrc)) {
|
|
644
|
+
copyDirectory(srcPath, destPath);
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
});
|
|
648
|
+
}
|
|
649
|
+
catch (error) {
|
|
650
|
+
logger.error(`copyDirectory error: ${error}`);
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
|
|
608
654
|
/**
|
|
609
655
|
* 将 packageConfig packages 中 分拆的包 配置迁移到 odr_packages 中
|
|
610
656
|
*/
|
|
@@ -624,7 +670,7 @@ async function writeOdrConfig(outputDir) {
|
|
|
624
670
|
if (!odrPackages[relatedPkgName]) {
|
|
625
671
|
odrPackages[relatedPkgName] = {};
|
|
626
672
|
}
|
|
627
|
-
odrPackages[relatedPkgName] = Object.assign(Object.assign({}, odrPackages[relatedPkgName]), { root: pkgConfig.root, code_output: pkgConfig.output, code_md5: pkgConfig.md5, main: pkgConfig.main });
|
|
673
|
+
odrPackages[relatedPkgName] = Object.assign(Object.assign({}, odrPackages[relatedPkgName]), { root: pkgConfig.root, code_output: pkgConfig.output, code_md5: pkgConfig.md5, main: pkgConfig.main, dependencies: pkgConfig.dependencies, type: pkgConfig.type });
|
|
628
674
|
delete packages[pkgName];
|
|
629
675
|
}
|
|
630
676
|
if (pkgName.endsWith(ODR_ASSET_DIR_SUFFIX)) {
|
|
@@ -653,12 +699,14 @@ async function makeOdrPkgs(outputDir) {
|
|
|
653
699
|
const pkgOutput = path.join(outputDir, pkgName);
|
|
654
700
|
const codeOutput = path.join(outputDir, `${pkgName}${ODR_CODE_DIR_SUFFIX}`);
|
|
655
701
|
const assetOutput = path.join(outputDir, `${pkgName}${ODR_ASSET_DIR_SUFFIX}`);
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
702
|
+
if (packages[pkgName].type === 'game') {
|
|
703
|
+
ensureDirSync(codeOutput);
|
|
704
|
+
ensureDirSync(assetOutput);
|
|
705
|
+
fs.cpSync(pkgOutput, codeOutput, { recursive: true });
|
|
706
|
+
fs.cpSync(pkgOutput, assetOutput, { recursive: true });
|
|
707
|
+
deleteNoJsFilesSync(codeOutput);
|
|
708
|
+
deleteJsFilesSync(assetOutput);
|
|
709
|
+
}
|
|
662
710
|
/**
|
|
663
711
|
* 写入配置
|
|
664
712
|
*/
|
|
@@ -901,7 +949,8 @@ function checkGameJson(entryDir, config) {
|
|
|
901
949
|
*/
|
|
902
950
|
function checkProjectSize(entryDir, config) {
|
|
903
951
|
logger.info('start check project size');
|
|
904
|
-
const {
|
|
952
|
+
const { dev } = config;
|
|
953
|
+
const { pkgSizeLimit } = getCheckConfig(config);
|
|
905
954
|
const enableDev = dev === null || dev === void 0 ? void 0 : dev.enable;
|
|
906
955
|
const gameSize = getProjectSize({ entryDir });
|
|
907
956
|
const gameSizeMB = (gameSize / (1024 * 1024)).toFixed(2);
|
|
@@ -938,11 +987,12 @@ const defaultCheckConfig$2 = {
|
|
|
938
987
|
*/
|
|
939
988
|
function checkMainPackageSize({ entryDir, config, }) {
|
|
940
989
|
logger.info('start check main package size');
|
|
941
|
-
const {
|
|
990
|
+
const { dev } = config;
|
|
991
|
+
const { mainPkgSizeLimit } = getCheckConfig(config);
|
|
942
992
|
const mainPkgSize = getMainPkgSize({ entryDir });
|
|
943
993
|
const mainPkgSizeMB = (mainPkgSize / (1024 * 1024)).toFixed(2);
|
|
944
|
-
const limitMB = (
|
|
945
|
-
if (mainPkgSize >
|
|
994
|
+
const limitMB = (mainPkgSizeLimit / (1024 * 1024)).toFixed(2);
|
|
995
|
+
if (mainPkgSize > mainPkgSizeLimit) {
|
|
946
996
|
const errMsg = `Check main package size failed, main package size ${mainPkgSizeMB}MB, must not exceed ${limitMB}MB`;
|
|
947
997
|
logger.error(errMsg);
|
|
948
998
|
if (dev === null || dev === void 0 ? void 0 : dev.enable) {
|
|
@@ -983,10 +1033,7 @@ function checkMainPackage(entryDir, config) {
|
|
|
983
1033
|
entryDir,
|
|
984
1034
|
config,
|
|
985
1035
|
}));
|
|
986
|
-
|
|
987
|
-
* 检查主包大小是否超出限制, 仅对非unity工程生效
|
|
988
|
-
*/
|
|
989
|
-
if (!isUnityEngine(entryDir) && ((_a = config.build) === null || _a === void 0 ? void 0 : _a.mainPkgSizeLimit)) {
|
|
1036
|
+
if ((_a = getCheckConfig(config)) === null || _a === void 0 ? void 0 : _a.mainPkgSizeLimit) {
|
|
990
1037
|
checkResults.push(checkMainPackageSize({
|
|
991
1038
|
entryDir,
|
|
992
1039
|
config,
|
|
@@ -1085,7 +1132,6 @@ function checkIndependentPackages(entryDir, config) {
|
|
|
1085
1132
|
logger.info('start check independent subpackages in game.json');
|
|
1086
1133
|
const independentSubpackages = getIndependentPackagesConfig(entryDir);
|
|
1087
1134
|
independentSubpackages.forEach(sub => {
|
|
1088
|
-
var _a;
|
|
1089
1135
|
/**
|
|
1090
1136
|
* 校验 independent subpackage 配置是否为空
|
|
1091
1137
|
*/
|
|
@@ -1132,8 +1178,8 @@ function checkIndependentPackages(entryDir, config) {
|
|
|
1132
1178
|
/**
|
|
1133
1179
|
* 校验 independent subpackage 包大小,不做校验
|
|
1134
1180
|
*/
|
|
1135
|
-
const independentSubPkgSizeLimit = (
|
|
1136
|
-
if (
|
|
1181
|
+
const { independentSubPkgSizeLimit } = getCheckConfig(config);
|
|
1182
|
+
if (independentSubPkgSizeLimit) {
|
|
1137
1183
|
const checkSizeResult = checkPkgSize({
|
|
1138
1184
|
entryDir: subpackageEntryDir,
|
|
1139
1185
|
pkgName: sub.name,
|
|
@@ -1344,6 +1390,8 @@ async function setup(entryDir, outputDir) {
|
|
|
1344
1390
|
root: '',
|
|
1345
1391
|
main: 'game.js',
|
|
1346
1392
|
output: `${GAME_MAIN_PACKAGE_NAME}${STTPKG_EXT}`,
|
|
1393
|
+
type: 'game',
|
|
1394
|
+
dependencies: []
|
|
1347
1395
|
};
|
|
1348
1396
|
transformSubPackages(gameJson.subpackages).forEach(({ name, root, main, independent }) => {
|
|
1349
1397
|
// root 是目录
|
|
@@ -1354,6 +1402,8 @@ async function setup(entryDir, outputDir) {
|
|
|
1354
1402
|
main,
|
|
1355
1403
|
output: `${name}${STTPKG_EXT}`,
|
|
1356
1404
|
independent,
|
|
1405
|
+
type: 'game',
|
|
1406
|
+
dependencies: []
|
|
1357
1407
|
};
|
|
1358
1408
|
if (independent) {
|
|
1359
1409
|
fyfPackages.push({
|
|
@@ -1501,6 +1551,27 @@ function collectMaps(entryDir, packages) {
|
|
|
1501
1551
|
logger.info('基于游戏源代码收集分包中的 JS 文件完成');
|
|
1502
1552
|
return result;
|
|
1503
1553
|
}
|
|
1554
|
+
function collectPluginMaps(gameDir, entryDir, name) {
|
|
1555
|
+
logger.info('开始基于插件源代码收集分包中的 JS 文件');
|
|
1556
|
+
const result = {};
|
|
1557
|
+
let jsFiles;
|
|
1558
|
+
jsFiles = collectPkgJsFiles({
|
|
1559
|
+
entry: entryDir,
|
|
1560
|
+
root: entryDir,
|
|
1561
|
+
exts: ['.js', '.ts', '.jsx', '.tsx'],
|
|
1562
|
+
excludeDirs: [],
|
|
1563
|
+
});
|
|
1564
|
+
const list = [];
|
|
1565
|
+
jsFiles.forEach(absPath => {
|
|
1566
|
+
list.push(path.relative(gameDir, absPath).replace(/\\/g, '/'));
|
|
1567
|
+
});
|
|
1568
|
+
const packNameRoot = name;
|
|
1569
|
+
result[name] = {
|
|
1570
|
+
[`${packNameRoot}/game.pack.js`]: list,
|
|
1571
|
+
};
|
|
1572
|
+
logger.info('基于插件源代码收集分包中的 JS 文件完成');
|
|
1573
|
+
return result;
|
|
1574
|
+
}
|
|
1504
1575
|
|
|
1505
1576
|
function collectDeps(gameEntry, packages) {
|
|
1506
1577
|
// 自动扫描 game 目录下的一级文件夹作为根前缀
|
|
@@ -1553,6 +1624,7 @@ function collectDeps(gameEntry, packages) {
|
|
|
1553
1624
|
}
|
|
1554
1625
|
requireCalls.push({
|
|
1555
1626
|
file: path.relative(gameEntry, fullPath),
|
|
1627
|
+
type: 'game',
|
|
1556
1628
|
callee: node.callee.name,
|
|
1557
1629
|
requirePath,
|
|
1558
1630
|
resolvedPath: resolvedPath
|
|
@@ -1560,6 +1632,20 @@ function collectDeps(gameEntry, packages) {
|
|
|
1560
1632
|
: '',
|
|
1561
1633
|
});
|
|
1562
1634
|
}
|
|
1635
|
+
else if (node.type === 'CallExpression' &&
|
|
1636
|
+
node.callee.type === 'Identifier' &&
|
|
1637
|
+
node.callee.name === 'requirePlugin' &&
|
|
1638
|
+
node.arguments.length > 0 &&
|
|
1639
|
+
node.arguments[0].type === 'Literal') {
|
|
1640
|
+
const requirePath = node.arguments[0].value;
|
|
1641
|
+
requireCalls.push({
|
|
1642
|
+
file: path.relative(gameEntry, fullPath),
|
|
1643
|
+
type: 'plugin',
|
|
1644
|
+
callee: node.callee.name,
|
|
1645
|
+
requirePath,
|
|
1646
|
+
resolvedPath: requirePath,
|
|
1647
|
+
});
|
|
1648
|
+
}
|
|
1563
1649
|
});
|
|
1564
1650
|
});
|
|
1565
1651
|
const newRequireCalls = requireCalls.map(i => {
|
|
@@ -1567,11 +1653,16 @@ function collectDeps(gameEntry, packages) {
|
|
|
1567
1653
|
* 基于 packages 来判断
|
|
1568
1654
|
*/
|
|
1569
1655
|
let depModule = '';
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1656
|
+
if (i.type === 'plugin') {
|
|
1657
|
+
depModule = i.requirePath.split('/')[0];
|
|
1658
|
+
}
|
|
1659
|
+
else if (i.type === 'game') {
|
|
1660
|
+
Object.keys(packages).forEach(pkg => {
|
|
1661
|
+
if (i.resolvedPath && i.resolvedPath.startsWith(packages[pkg].root)) {
|
|
1662
|
+
depModule = pkg;
|
|
1663
|
+
}
|
|
1664
|
+
});
|
|
1665
|
+
}
|
|
1575
1666
|
let curModule = '';
|
|
1576
1667
|
Object.keys(packages).forEach(pkg => {
|
|
1577
1668
|
if (i.file.startsWith(packages[pkg].root)) {
|
|
@@ -1585,17 +1676,26 @@ function collectDeps(gameEntry, packages) {
|
|
|
1585
1676
|
const exts = ['.js', '.ts', '.jsx', '.tsx'];
|
|
1586
1677
|
const isJsLike = f => exts.some(ext => f.endsWith(ext));
|
|
1587
1678
|
const result = newRequireCalls.reduce((acc, cur) => {
|
|
1588
|
-
if (!acc[cur.curModule]) {
|
|
1589
|
-
acc[cur.curModule] = {};
|
|
1679
|
+
if (!acc.packageDeps[cur.curModule]) {
|
|
1680
|
+
acc.packageDeps[cur.curModule] = {};
|
|
1681
|
+
}
|
|
1682
|
+
if (!acc.pluginDeps[cur.curModule]) {
|
|
1683
|
+
acc.pluginDeps[cur.curModule] = [];
|
|
1590
1684
|
}
|
|
1591
1685
|
if (cur.curModule === cur.depModule) {
|
|
1592
1686
|
return acc;
|
|
1593
1687
|
}
|
|
1594
|
-
if (cur.resolvedPath && isJsLike(cur.resolvedPath)) {
|
|
1595
|
-
acc
|
|
1688
|
+
if (cur.resolvedPath && isJsLike(cur.resolvedPath) && cur.type === 'game') {
|
|
1689
|
+
acc.packageDeps[cur.curModule][cur.resolvedPath] = cur.depModule;
|
|
1690
|
+
}
|
|
1691
|
+
else if (cur.type === 'plugin') {
|
|
1692
|
+
acc.pluginDeps[cur.curModule].push(cur.depModule);
|
|
1596
1693
|
}
|
|
1597
1694
|
return acc;
|
|
1598
|
-
}, {
|
|
1695
|
+
}, {
|
|
1696
|
+
packageDeps: {},
|
|
1697
|
+
pluginDeps: {},
|
|
1698
|
+
});
|
|
1599
1699
|
return result;
|
|
1600
1700
|
}
|
|
1601
1701
|
function getRootPrefixes(gameEntry) {
|
|
@@ -1641,7 +1741,7 @@ async function pack({ gameEntry, pkgName, allDeps, allMaps, pkgConfig, destRoot,
|
|
|
1641
1741
|
const packMap = allMaps[pkgName];
|
|
1642
1742
|
const moduleConfig = {
|
|
1643
1743
|
main: pkgConfig.main,
|
|
1644
|
-
deps: allDeps[pkgName] || {},
|
|
1744
|
+
deps: allDeps.packageDeps[pkgName] || {},
|
|
1645
1745
|
map: allMaps[pkgName],
|
|
1646
1746
|
};
|
|
1647
1747
|
ensureDirSync(destRoot);
|
|
@@ -1692,7 +1792,8 @@ async function pack({ gameEntry, pkgName, allDeps, allMaps, pkgConfig, destRoot,
|
|
|
1692
1792
|
// });
|
|
1693
1793
|
// const code = fs.readFileSync(absPath, 'utf-8');
|
|
1694
1794
|
const fileId = relPath.replace(/\\/g, '/');
|
|
1695
|
-
const
|
|
1795
|
+
const schema = config.build.type === 'plugin' ? 'plugin' : 'game';
|
|
1796
|
+
const defineHeader = `define("${schema}:${fileId}", ["require", "requireAsync", "module", "exports", "sandboxGlobal"], function(require, requireAsync, module, exports, sandboxGlobal){\nwith(sandboxGlobal){\n`;
|
|
1696
1797
|
const defineFooter = `\n}\n});\n`;
|
|
1697
1798
|
const fileMagic = new MagicString(code, { filename: fileId });
|
|
1698
1799
|
fileMagic.prepend(defineHeader);
|
|
@@ -1779,6 +1880,75 @@ async function partition({ pkgRoot, destRoot, packedFiles, gameEntry, gameOutput
|
|
|
1779
1880
|
}
|
|
1780
1881
|
}
|
|
1781
1882
|
|
|
1883
|
+
/**
|
|
1884
|
+
* 根据 TikTok DevPortal 接口获取插件包信息(url + md5)
|
|
1885
|
+
*
|
|
1886
|
+
* 对应 curl:
|
|
1887
|
+
* POST https://developers.tiktok.com/tiktok/v4/devportal/minigame/plugin_meta/get
|
|
1888
|
+
* body: { plugin_name, plugin_version }
|
|
1889
|
+
*/
|
|
1890
|
+
async function getPluginInfo(params) {
|
|
1891
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
1892
|
+
const baseUrl = (_a = params.baseUrl) !== null && _a !== void 0 ? _a : 'https://developers.tiktok.com';
|
|
1893
|
+
const url = `${baseUrl}/tiktok/v4/devportal/minigame/plugin_meta/get`;
|
|
1894
|
+
const res = await fetch(url, {
|
|
1895
|
+
method: 'POST',
|
|
1896
|
+
headers: Object.assign({ 'Content-Type': 'application/json' }, ((_b = params.headers) !== null && _b !== void 0 ? _b : {})),
|
|
1897
|
+
body: JSON.stringify({
|
|
1898
|
+
plugin_name: params.plugin_name,
|
|
1899
|
+
plugin_version: params.plugin_version,
|
|
1900
|
+
}),
|
|
1901
|
+
});
|
|
1902
|
+
const json = await res.json();
|
|
1903
|
+
const meta = (_g = (_e = (_c = json === null || json === void 0 ? void 0 : json.PluginMeta) !== null && _c !== void 0 ? _c : (_d = json === null || json === void 0 ? void 0 : json.data) === null || _d === void 0 ? void 0 : _d.PluginMeta) !== null && _e !== void 0 ? _e : (_f = json === null || json === void 0 ? void 0 : json.result) === null || _f === void 0 ? void 0 : _f.PluginMeta) !== null && _g !== void 0 ? _g : (_j = (_h = json === null || json === void 0 ? void 0 : json.data) === null || _h === void 0 ? void 0 : _h.result) === null || _j === void 0 ? void 0 : _j.PluginMeta;
|
|
1904
|
+
if (!(meta === null || meta === void 0 ? void 0 : meta.PackageCDNURL) || !(meta === null || meta === void 0 ? void 0 : meta.PackageMD5)) {
|
|
1905
|
+
throw new Error(`[ttmg-pack] plugin get error: ${JSON.stringify(json)}`);
|
|
1906
|
+
}
|
|
1907
|
+
return { url: meta.PackageCDNURL, md5: meta.PackageMD5 };
|
|
1908
|
+
}
|
|
1909
|
+
async function addDepsToPackages(gameEntry, outputDir, allDeps) {
|
|
1910
|
+
const gamePackConfigPath = path.join(outputDir, GAME_PACK_CONFIG_FILE_NAME);
|
|
1911
|
+
const gameJsonPath = path.join(gameEntry, GAME_ORIGIN_CONFIG_FILE_NAME);
|
|
1912
|
+
const gamePackConfig = JSON.parse(fs.readFileSync(gamePackConfigPath, 'utf-8'));
|
|
1913
|
+
const gameJson = JSON.parse(fs.readFileSync(gameJsonPath, 'utf-8'));
|
|
1914
|
+
const pluginConfig = gameJson.plugins;
|
|
1915
|
+
for (const [pkgName, plugins] of Object.entries(allDeps)) {
|
|
1916
|
+
for (const pluginName of plugins) {
|
|
1917
|
+
if (!(pluginConfig === null || pluginConfig === void 0 ? void 0 : pluginConfig[pluginName]))
|
|
1918
|
+
continue;
|
|
1919
|
+
const version = pluginConfig[pluginName].version;
|
|
1920
|
+
const pluginPkgName = `${pluginName}_${version}`;
|
|
1921
|
+
const { url, md5 } = await getPluginInfo({
|
|
1922
|
+
plugin_name: pluginName.toLowerCase(),
|
|
1923
|
+
plugin_version: version,
|
|
1924
|
+
headers: {
|
|
1925
|
+
'x-tt-env': 'ppe_unity_plugin_meta',
|
|
1926
|
+
'x-use-ppe': '1',
|
|
1927
|
+
},
|
|
1928
|
+
});
|
|
1929
|
+
gamePackConfig.packages[pkgName].dependencies.push(pluginPkgName);
|
|
1930
|
+
if (!gamePackConfig.packages[pluginPkgName]) {
|
|
1931
|
+
gamePackConfig.packages[pluginPkgName] = {
|
|
1932
|
+
url,
|
|
1933
|
+
md5,
|
|
1934
|
+
root: pluginPkgName,
|
|
1935
|
+
main: `${pluginPkgName}/index.js`,
|
|
1936
|
+
output: `${pluginPkgName}${STTPKG_EXT}`,
|
|
1937
|
+
independent: false,
|
|
1938
|
+
type: 'plugin',
|
|
1939
|
+
dependencies: [],
|
|
1940
|
+
};
|
|
1941
|
+
}
|
|
1942
|
+
else {
|
|
1943
|
+
// 如果已存在,也覆盖 url/md5,保证最新
|
|
1944
|
+
gamePackConfig.packages[pluginPkgName].url = url;
|
|
1945
|
+
gamePackConfig.packages[pluginPkgName].md5 = md5;
|
|
1946
|
+
}
|
|
1947
|
+
}
|
|
1948
|
+
}
|
|
1949
|
+
fs.writeFileSync(gamePackConfigPath, JSON.stringify(gamePackConfig, null, 2));
|
|
1950
|
+
}
|
|
1951
|
+
|
|
1782
1952
|
function getSkipDirs({ packages, entryDir, }) {
|
|
1783
1953
|
const skipDirs = [];
|
|
1784
1954
|
if (packages) {
|
|
@@ -1791,6 +1961,7 @@ async function makePkgs({ gameEntry, gameOutput, config, }) {
|
|
|
1791
1961
|
logger.info(`pack start,startTime:${startTime}`);
|
|
1792
1962
|
const { packages } = await setup(gameEntry, gameOutput);
|
|
1793
1963
|
const allDeps = collectDeps(gameEntry, packages);
|
|
1964
|
+
await addDepsToPackages(gameEntry, gameOutput, allDeps.pluginDeps);
|
|
1794
1965
|
const allMaps = collectMaps(gameEntry, packages);
|
|
1795
1966
|
const pkgOutput = {};
|
|
1796
1967
|
/**
|
|
@@ -1840,6 +2011,46 @@ async function makePkgs({ gameEntry, gameOutput, config, }) {
|
|
|
1840
2011
|
logger.info(`pack end,duration:${Date.now() - startTime}ms`);
|
|
1841
2012
|
return pkgOutput;
|
|
1842
2013
|
}
|
|
2014
|
+
async function makePlugin({ gameEntry, gameOutput, config, }) {
|
|
2015
|
+
try {
|
|
2016
|
+
const pluginConfig = fs.readFileSync(path.join(gameEntry, 'plugin.json'), 'utf-8');
|
|
2017
|
+
const { name, main, version } = JSON.parse(pluginConfig);
|
|
2018
|
+
const pluginName = `${name}_${version}`;
|
|
2019
|
+
// 把 entryDir 下的所有文件复制到 entryDir/plugin
|
|
2020
|
+
const pluginDir = path.join(gameEntry, pluginName);
|
|
2021
|
+
copyDirectory(gameEntry, pluginDir);
|
|
2022
|
+
const packages = {
|
|
2023
|
+
[pluginName]: {
|
|
2024
|
+
url: '',
|
|
2025
|
+
md5: '',
|
|
2026
|
+
root: pluginName,
|
|
2027
|
+
main,
|
|
2028
|
+
output: `${pluginName}${STTPKG_EXT}`,
|
|
2029
|
+
type: 'game',
|
|
2030
|
+
dependencies: []
|
|
2031
|
+
}
|
|
2032
|
+
};
|
|
2033
|
+
fs.writeFileSync(path.join(gameOutput, GAME_PACK_CONFIG_FILE_NAME), JSON.stringify({ packages }, null, 2));
|
|
2034
|
+
const pluginEntry = path.join(gameEntry, pluginName);
|
|
2035
|
+
const allMaps = collectPluginMaps(gameEntry, pluginEntry, pluginName);
|
|
2036
|
+
await pack({
|
|
2037
|
+
gameEntry,
|
|
2038
|
+
allDeps: {
|
|
2039
|
+
packageDeps: {},
|
|
2040
|
+
pluginDeps: {},
|
|
2041
|
+
},
|
|
2042
|
+
allMaps,
|
|
2043
|
+
pkgName: pluginName,
|
|
2044
|
+
pkgConfig: packages[pluginName],
|
|
2045
|
+
destRoot: path.join(gameOutput, pluginName, packages[pluginName].root),
|
|
2046
|
+
config,
|
|
2047
|
+
});
|
|
2048
|
+
}
|
|
2049
|
+
catch (error) {
|
|
2050
|
+
logger.error('plugin.json 不存在');
|
|
2051
|
+
return;
|
|
2052
|
+
}
|
|
2053
|
+
}
|
|
1843
2054
|
|
|
1844
2055
|
/**
|
|
1845
2056
|
* 将 packages 中的每个 package 下的文件内容合并到 outputDir 下,不保留 package name
|
|
@@ -1915,8 +2126,7 @@ async function clearPkgs(entryDir, uselessDirs = ['node_modules', '__MACOSX']) {
|
|
|
1915
2126
|
removeSystemUseless(entryDir, uselessDirs);
|
|
1916
2127
|
}
|
|
1917
2128
|
|
|
1918
|
-
async function debugPkgs(
|
|
1919
|
-
const config = overrideConfig(originConfig);
|
|
2129
|
+
async function debugPkgs(config) {
|
|
1920
2130
|
const { entry: entryDir, output: outputDir, dev: { enableLog }, } = config;
|
|
1921
2131
|
logger.init(outputDir, enableLog);
|
|
1922
2132
|
try {
|
|
@@ -1962,12 +2172,16 @@ async function debugPkgs(originConfig) {
|
|
|
1962
2172
|
}
|
|
1963
2173
|
}
|
|
1964
2174
|
|
|
1965
|
-
async function buildPkgs(
|
|
1966
|
-
|
|
2175
|
+
async function buildPkgs(config) {
|
|
2176
|
+
var _a;
|
|
2177
|
+
if (((_a = config === null || config === void 0 ? void 0 : config.build) === null || _a === void 0 ? void 0 : _a.type) === 'plugin') {
|
|
2178
|
+
await buildPlugin(config);
|
|
2179
|
+
return;
|
|
2180
|
+
}
|
|
1967
2181
|
const { entry: entryDir, output: outputDir, build } = config;
|
|
1968
2182
|
let startTime = Date.now();
|
|
1969
2183
|
logger.init(outputDir, true);
|
|
1970
|
-
logger.info(`TTMG_PACK_VERSION: ${"0.2.
|
|
2184
|
+
logger.info(`TTMG_PACK_VERSION: ${"0.2.9-beta.2"}`);
|
|
1971
2185
|
logger.info(`pack start, startTime:${startTime}`);
|
|
1972
2186
|
/**
|
|
1973
2187
|
* 清理
|
|
@@ -1999,6 +2213,31 @@ async function buildPkgs(originConfig) {
|
|
|
1999
2213
|
}
|
|
2000
2214
|
logger.info(`pack end:${Date.now() - startTime}ms`);
|
|
2001
2215
|
}
|
|
2216
|
+
async function buildPlugin(originConfig) {
|
|
2217
|
+
const { entry: entryDir, output: outputDir, build } = originConfig;
|
|
2218
|
+
let startTime = Date.now();
|
|
2219
|
+
logger.init(outputDir, true);
|
|
2220
|
+
logger.info(`TTMG_PACK_VERSION: ${"0.2.9-beta.2"}`);
|
|
2221
|
+
logger.info(`pack start, startTime:${startTime}`);
|
|
2222
|
+
/**
|
|
2223
|
+
* 打包
|
|
2224
|
+
*/
|
|
2225
|
+
await makePlugin({
|
|
2226
|
+
config: originConfig,
|
|
2227
|
+
gameEntry: entryDir,
|
|
2228
|
+
gameOutput: outputDir,
|
|
2229
|
+
});
|
|
2230
|
+
if (build === null || build === void 0 ? void 0 : build.enableOdr) {
|
|
2231
|
+
/**
|
|
2232
|
+
* 等待文件全部读写完成后
|
|
2233
|
+
*/
|
|
2234
|
+
await makeOdrPkgs(outputDir);
|
|
2235
|
+
/**
|
|
2236
|
+
* 分拆 odr 包
|
|
2237
|
+
*/
|
|
2238
|
+
}
|
|
2239
|
+
logger.info(`pack end:${Date.now() - startTime}ms`);
|
|
2240
|
+
}
|
|
2002
2241
|
|
|
2003
2242
|
async function getPkgs({ entryDir, }) {
|
|
2004
2243
|
const independentPackages = getIndependentPackagesConfig(entryDir);
|